summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 08:17:02 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 08:17:02 +0000
commitb39512ed755239198a9c294b6a45e65c05900235 (patch)
treed234a3efade1de67c46b9e5a38ce813627726aa7
parentd31474cf3b17ece37939d20082b07f6657cc79a9 (diff)
downloadgitlab-ce-b39512ed755239198a9c294b6a45e65c05900235.tar.gz
Add latest changes from gitlab-org/gitlab@15-3-stable-eev15.3.0-rc42
-rw-r--r--.eslintrc.yml8
-rw-r--r--.gitignore2
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.gitlab/CODEOWNERS665
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml42
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml88
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/review-apps/skip-qa.gitlab-ci.yml13
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml44
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml106
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml19
-rw-r--r--.gitlab/ci/vendored-gems.gitlab-ci.yml16
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md7
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md7
-rw-r--r--.gitlab/issue_templates/Implementation.md13
-rw-r--r--.gitlab/issue_templates/Navigation - Left Sidebar Proposals.md2
-rw-r--r--.gitlab/issue_templates/OSS_Partner.md68
-rw-r--r--.gitlab/issue_templates/Performance Indicator Metric.md23
-rw-r--r--.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md15
-rw-r--r--.gitlab/issue_templates/Service Ping reporting and monitoring.md6
-rw-r--r--.gitlab/issue_templates/UX Theme.md77
-rw-r--r--.gitlab/merge_request_templates/Default.md14
-rw-r--r--.gitlab/merge_request_templates/Documentation.md2
-rw-r--r--.haml-lint.yml4
-rw-r--r--.overcommit.yml.example81
-rw-r--r--.rubocop.yml35
-rw-r--r--.rubocop_todo/capybara/visibility_matcher.yml21
-rw-r--r--.rubocop_todo/database/multiple_databases.yml3
-rw-r--r--.rubocop_todo/gitlab/deprecate_track_redis_hll_event.yml29
-rw-r--r--.rubocop_todo/gitlab/namespaced_class.yml3
-rw-r--r--.rubocop_todo/layout/first_array_element_indentation.yml62
-rw-r--r--.rubocop_todo/layout/first_hash_element_indentation.yml125
-rw-r--r--.rubocop_todo/layout/hash_alignment.yml492
-rw-r--r--.rubocop_todo/layout/line_length.yml15
-rw-r--r--.rubocop_todo/layout/multiline_operation_indentation.yml35
-rw-r--r--.rubocop_todo/layout/space_around_method_call_operator.yml32
-rw-r--r--.rubocop_todo/layout/space_inside_block_braces.yml619
-rw-r--r--.rubocop_todo/lint/missing_cop_enable_directive.yml33
-rw-r--r--.rubocop_todo/naming/heredoc_delimiter_naming.yml13
-rw-r--r--.rubocop_todo/naming/rescued_exceptions_variable_name.yml216
-rw-r--r--.rubocop_todo/performance/block_given_with_explicit_block.yml43
-rw-r--r--.rubocop_todo/performance/constant_regexp.yml30
-rw-r--r--.rubocop_todo/rails/pick.yml43
-rw-r--r--.rubocop_todo/rails/rake_environment.yml25
-rw-r--r--.rubocop_todo/rails/skips_model_validations.yml1
-rw-r--r--.rubocop_todo/rspec/be.yml22
-rw-r--r--.rubocop_todo/rspec/context_wording.yml635
-rw-r--r--.rubocop_todo/rspec/empty_line_after_hook.yml60
-rw-r--r--.rubocop_todo/rspec/expect_change.yml52
-rw-r--r--.rubocop_todo/rspec/expect_in_hook.yml54
-rw-r--r--.rubocop_todo/rspec/hooks_before_examples.yml76
-rw-r--r--.rubocop_todo/rspec/predicate_matcher.yml27
-rw-r--r--.rubocop_todo/rspec/repeated_example_group_description.yml1
-rw-r--r--.rubocop_todo/rspec/return_from_stub.yml12
-rw-r--r--.rubocop_todo/rspec/scattered_let.yml21
-rw-r--r--.rubocop_todo/rspec/verified_doubles.yml1
-rw-r--r--.rubocop_todo/style/array_coercion.yml10
-rw-r--r--.rubocop_todo/style/class_and_module_children.yml3
-rw-r--r--.rubocop_todo/style/empty_else.yml9
-rw-r--r--.rubocop_todo/style/explicit_block_argument.yml1
-rw-r--r--.rubocop_todo/style/format_string.yml45
-rw-r--r--.rubocop_todo/style/guard_clause.yml73
-rw-r--r--.rubocop_todo/style/hash_as_last_array_item.yml6
-rw-r--r--.rubocop_todo/style/hash_each_methods.yml7
-rw-r--r--.rubocop_todo/style/if_inside_else.yml10
-rw-r--r--.rubocop_todo/style/if_unless_modifier.yml136
-rw-r--r--.rubocop_todo/style/missing_respond_to_missing.yml3
-rw-r--r--.rubocop_todo/style/next.yml8
-rw-r--r--.rubocop_todo/style/percent_literal_delimiters.yml86
-rw-r--r--.rubocop_todo/style/redundant_interpolation.yml27
-rw-r--r--.rubocop_todo/style/redundant_regexp_escape.yml15
-rw-r--r--.rubocop_todo/style/redundant_self.yml31
-rw-r--r--.rubocop_todo/style/rescue_modifier.yml51
-rw-r--r--.rubocop_todo/style/string_concatenation.yml21
-rw-r--r--.rubocop_todo/style/symbol_proc.yml32
-rw-r--r--CHANGELOG.md46
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION2
-rw-r--r--GITLAB_METRICS_EXPORTER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile69
-rw-r--r--Gemfile.lock349
-rw-r--r--app/assets/images/auth_buttons/jwt_64.pngbin2457 -> 824 bytes
-rw-r--r--app/assets/images/auth_buttons/salesforce_64.pngbin8774 -> 2012 bytes
-rw-r--r--app/assets/javascripts/access_tokens/components/expires_at_field.vue30
-rw-r--r--app/assets/javascripts/access_tokens/components/projects_field.vue69
-rw-r--r--app/assets/javascripts/access_tokens/components/projects_token_selector.vue156
-rw-r--r--app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql1
-rw-r--r--app/assets/javascripts/access_tokens/index.js57
-rw-r--r--app/assets/javascripts/admin/deploy_keys/components/table.vue8
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql1
-rw-r--r--app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue2
-rw-r--r--app/assets/javascripts/analytics/shared/utils.js26
-rw-r--r--app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql1
-rw-r--r--app/assets/javascripts/api/analytics_api.js3
-rw-r--r--app/assets/javascripts/api/groups_api.js7
-rw-r--r--app/assets/javascripts/attention_requests/components/navigation_popover.vue122
-rw-r--r--app/assets/javascripts/attention_requests/index.js73
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue6
-rw-r--r--app/assets/javascripts/batch_comments/components/review_bar.vue28
-rw-r--r--app/assets/javascripts/batch_comments/components/submit_dropdown.vue39
-rw-r--r--app/assets/javascripts/batch_comments/i18n.js3
-rw-r--r--app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js5
-rw-r--r--app/assets/javascripts/behaviors/components/json_table.vue71
-rw-r--r--app/assets/javascripts/behaviors/markdown/marks/strike.js29
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/code_block.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js44
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_json_table.js70
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js231
-rw-r--r--app/assets/javascripts/blob/blob_links_tracking.js25
-rw-r--r--app/assets/javascripts/boards/boards_util.js4
-rw-r--r--app/assets/javascripts/boards/components/board_add_new_column_form.vue29
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue8
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue3
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue5
-rw-r--r--app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_members.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/lists_issues.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_members.query.graphql2
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js2
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue4
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue101
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue49
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue104
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue212
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue86
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue75
-rw-r--r--app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_modal.vue6
-rw-r--r--app/assets/javascripts/ci_variable_list/constants.js59
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql7
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql16
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql30
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql30
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql30
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql17
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql13
-rw-r--r--app/assets/javascripts/ci_variable_list/graphql/resolvers.js113
-rw-r--r--app/assets/javascripts/ci_variable_list/index.js29
-rw-r--r--app/assets/javascripts/ci_variable_list/store/utils.js6
-rw-r--r--app/assets/javascripts/ci_variable_list/utils.js50
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue2
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue60
-rw-r--r--app/assets/javascripts/commons/nav/user_merge_requests.js21
-rw-r--r--app/assets/javascripts/content_editor/components/bubble_menus/formatting.vue24
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue9
-rw-r--r--app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue11
-rw-r--r--app/assets/javascripts/content_editor/components/top_toolbar.vue2
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue2
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_of_contents.vue55
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/table_of_contents_heading.vue25
-rw-r--r--app/assets/javascripts/content_editor/extensions/code_block_highlight.js3
-rw-r--r--app/assets/javascripts/content_editor/extensions/diagram.js7
-rw-r--r--app/assets/javascripts/content_editor/extensions/frontmatter.js7
-rw-r--r--app/assets/javascripts/content_editor/extensions/image.js6
-rw-r--r--app/assets/javascripts/content_editor/extensions/link.js5
-rw-r--r--app/assets/javascripts/content_editor/extensions/reference_definition.js29
-rw-r--r--app/assets/javascripts/content_editor/extensions/sourcemap.js4
-rw-r--r--app/assets/javascripts/content_editor/extensions/table_of_contents.js15
-rw-r--r--app/assets/javascripts/content_editor/services/content_editor.js6
-rw-r--r--app/assets/javascripts/content_editor/services/create_content_editor.js9
-rw-r--r--app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js82
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js36
-rw-r--r--app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js67
-rw-r--r--app/assets/javascripts/content_editor/services/serialization_helpers.js56
-rw-r--r--app/assets/javascripts/content_editor/services/table_of_contents_utils.js67
-rw-r--r--app/assets/javascripts/contributors/stores/getters.js6
-rw-r--r--app/assets/javascripts/crm/components/form.vue20
-rw-r--r--app/assets/javascripts/crm/constants.js4
-rw-r--r--app/assets/javascripts/crm/contacts/bundle.js18
-rw-r--r--app/assets/javascripts/crm/contacts/components/contact_form_wrapper.vue9
-rw-r--r--app/assets/javascripts/crm/contacts/components/contacts_root.vue220
-rw-r--r--app/assets/javascripts/crm/contacts/components/graphql/crm_contact_fields.fragment.graphql3
-rw-r--r--app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts.query.graphql30
-rw-r--r--app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts_count_by_state.graphql11
-rw-r--r--app/assets/javascripts/crm/organizations/components/graphql/crm_organization_fields.fragment.graphql2
-rw-r--r--app/assets/javascripts/crm/organizations/components/graphql/get_group_organizations.query.graphql1
-rw-r--r--app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue27
-rw-r--r--app/assets/javascripts/cycle_analytics/components/base.vue12
-rw-r--r--app/assets/javascripts/cycle_analytics/store/actions.js25
-rw-r--r--app/assets/javascripts/cycle_analytics/store/getters.js6
-rw-r--r--app/assets/javascripts/cycle_analytics/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/cycle_analytics/store/mutations.js23
-rw-r--r--app/assets/javascripts/cycle_analytics/store/state.js5
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue1
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue1
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/design_todo_item.fragment.graphql2
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/version.fragment.graphql1
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql2
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue2
-rw-r--r--app/assets/javascripts/diff.js3
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue9
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue85
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue22
-rw-r--r--app/assets/javascripts/diffs/constants.js3
-rw-r--r--app/assets/javascripts/diffs/store/actions.js12
-rw-r--r--app/assets/javascripts/dropzone_input.js17
-rw-r--r--app/assets/javascripts/editor/components/source_editor_toolbar_button.vue1
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js5
-rw-r--r--app/assets/javascripts/editor/graphql/typedefs.graphql14
-rw-r--r--app/assets/javascripts/editor/schema/ci.json44
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue2
-rw-r--r--app/assets/javascripts/environments/components/environments_detail_header.vue1
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql1
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js19
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js4
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue1
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js74
-rw-r--r--app/assets/javascripts/gitlab_pages/new.js39
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/blobviewer.fragment.graphql7
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql4
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json9
-rw-r--r--app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql3
-rw-r--r--app/assets/javascripts/group_settings/components/shared_runners_form.vue7
-rw-r--r--app/assets/javascripts/group_settings/mount_shared_runners.js4
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue16
-rw-r--r--app/assets/javascripts/groups/components/group_name_and_path.vue215
-rw-r--r--app/assets/javascripts/groups/components/groups.vue2
-rw-r--r--app/assets/javascripts/groups/components/transfer_group_form.vue1
-rw-r--r--app/assets/javascripts/groups/constants.js29
-rw-r--r--app/assets/javascripts/groups/create_edit_form.js10
-rw-r--r--app/assets/javascripts/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql11
-rw-r--r--app/assets/javascripts/header_search/components/app.vue51
-rw-r--r--app/assets/javascripts/header_search/constants.js4
-rw-r--r--app/assets/javascripts/header_search/index.js11
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue4
-rw-r--r--app/assets/javascripts/ide/components/file_templates/bar.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_project_header.vue1
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue2
-rw-r--r--app/assets/javascripts/ide/lib/common/model.js2
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue7
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue6
-rw-r--r--app/assets/javascripts/integrations/overrides/components/integration_overrides.vue1
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue70
-rw-r--r--app/assets/javascripts/invite_members/components/members_token_select.vue43
-rw-r--r--app/assets/javascripts/invite_members/components/user_limit_notification.vue8
-rw-r--r--app/assets/javascripts/invite_members/constants.js13
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js9
-rw-r--r--app/assets/javascripts/issuable/components/issue_milestone.vue4
-rw-r--r--app/assets/javascripts/issuable/components/related_issuable_item.vue51
-rw-r--r--app/assets/javascripts/issuable/issuable_template_selector.js16
-rw-r--r--app/assets/javascripts/issuable/popover/components/issue_popover.vue54
-rw-r--r--app/assets/javascripts/issuable/popover/queries/issue.query.graphql9
-rw-r--r--app/assets/javascripts/issues/index.js2
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue42
-rw-r--r--app/assets/javascripts/issues/list/constants.js19
-rw-r--r--app/assets/javascripts/issues/list/queries/issue.fragment.graphql4
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue2
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue9
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/constants.js5
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue117
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_form.vue157
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_item.vue100
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue27
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_list_item.vue92
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/timeline_events_tab.vue15
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/utils.js1
-rw-r--r--app/assets/javascripts/jobs/components/environments_block.vue16
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue1
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue94
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_job_details_container.vue9
-rw-r--r--app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql4
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table_app.vue11
-rw-r--r--app/assets/javascripts/labels/labels_select.js2
-rw-r--r--app/assets/javascripts/lib/dompurify.js37
-rw-r--r--app/assets/javascripts/lib/gfm/index.js50
-rw-r--r--app/assets/javascripts/lib/graphql.js1
-rw-r--r--app/assets/javascripts/lib/markdown_it.js11
-rw-r--r--app/assets/javascripts/lib/prosemirror_markdown_serializer.js4
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js242
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js25
-rw-r--r--app/assets/javascripts/lib/utils/yaml.js21
-rw-r--r--app/assets/javascripts/linked_resources/index.js11
-rw-r--r--app/assets/javascripts/main.js6
-rw-r--r--app/assets/javascripts/members/components/table/member_action_buttons.vue5
-rw-r--r--app/assets/javascripts/members/constants.js2
-rw-r--r--app/assets/javascripts/merge_conflicts/utils.js7
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue4
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js64
-rw-r--r--app/assets/javascripts/mr_notes/init_notes.js8
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue2
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue28
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue106
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue6
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue3
-rw-r--r--app/assets/javascripts/notes/constants.js2
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js6
-rw-r--r--app/assets/javascripts/notes/utils.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/index.js8
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js5
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue109
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue35
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue52
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue47
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js15
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql5
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql5
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql4
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue107
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/container_expiration_policy.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue30
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue25
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/constants.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js4
-rw-r--r--app/assets/javascripts/pages/groups/new/components/app.vue73
-rw-r--r--app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue56
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js11
-rw-r--r--app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue2
-rw-r--r--app/assets/javascripts/pages/profiles/personal_access_tokens/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/ci/secure_files/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js23
-rw-r--r--app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue42
-rw-r--r--app/assets/javascripts/pages/projects/init_blob.js9
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pages/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js41
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue42
-rw-r--r--app/assets/javascripts/pages/projects/tags/releases/index.js6
-rw-r--r--app/assets/javascripts/pages/registrations/new/index.js5
-rw-r--r--app/assets/javascripts/pages/sessions/new/email_format_validator.js46
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue55
-rw-r--r--app/assets/javascripts/persistent_user_callout.js4
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue4
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue4
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue53
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue20
-rw-r--r--app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue20
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js8
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql1
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql2
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js2
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue34
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/take_ownership_modal.vue52
-rw-r--r--app/assets/javascripts/pipeline_wizard/components/widgets/checklist.vue9
-rw-r--r--app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/performance_insights_modal.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_tabs.vue18
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue40
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_reports.vue26
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue16
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary.vue55
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue54
-rw-r--r--app/assets/javascripts/pipelines/constants.js2
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines_mixin.js13
-rw-r--r--app/assets/javascripts/pipelines/pipeline_tabs.js33
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/actions.js1
-rw-r--r--app/assets/javascripts/projects/compare/components/app.vue20
-rw-r--r--app/assets/javascripts/projects/compare/index.js12
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js2
-rw-r--r--app/assets/javascripts/projects/project_new.js24
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue87
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue59
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue46
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue52
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue44
-rw-r--r--app/assets/javascripts/projects/settings/components/access_dropdown.vue4
-rw-r--r--app/assets/javascripts/projects/settings/components/transfer_project_form.vue94
-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.js22
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue1
-rw-r--r--app/assets/javascripts/related_issues/components/add_issuable_form.vue7
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue76
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_list.vue2
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue9
-rw-r--r--app/assets/javascripts/related_issues/constants.js10
-rw-r--r--app/assets/javascripts/related_issues/index.js51
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue9
-rw-r--r--app/assets/javascripts/releases/components/asset_links_form.vue2
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue12
-rw-r--r--app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql15
-rw-r--r--app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql88
-rw-r--r--app/assets/javascripts/releases/util.js1
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue1
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue74
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue9
-rw-r--r--app/assets/javascripts/repository/constants.js1
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql1
-rw-r--r--app/assets/javascripts/right_sidebar.js32
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue34
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_summary_cell.vue6
-rw-r--r--app/assets/javascripts/runner/components/runner_assigned_item.vue22
-rw-r--r--app/assets/javascripts/runner/components/runner_bulk_delete.vue149
-rw-r--r--app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue59
-rw-r--r--app/assets/javascripts/runner/components/runner_detail.vue9
-rw-r--r--app/assets/javascripts/runner/components/runner_details.vue25
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue8
-rw-r--r--app/assets/javascripts/runner/components/runner_jobs.vue11
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue15
-rw-r--r--app/assets/javascripts/runner/components/runner_pagination.vue67
-rw-r--r--app/assets/javascripts/runner/components/runner_projects.vue22
-rw-r--r--app/assets/javascripts/runner/components/stat/runner_count.vue7
-rw-r--r--app/assets/javascripts/runner/components/stat/runner_single_stat.vue41
-rw-r--r--app/assets/javascripts/runner/components/stat/runner_stats.vue74
-rw-r--r--app/assets/javascripts/runner/components/stat/runner_status_stat.vue65
-rw-r--r--app/assets/javascripts/runner/constants.js3
-rw-r--r--app/assets/javascripts/runner/graphql/edit/runner_fields_shared.fragment.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/list/all_runners.query.graphql13
-rw-r--r--app/assets/javascripts/runner/graphql/list/all_runners_connection.fragment.graphql13
-rw-r--r--app/assets/javascripts/runner/graphql/list/bulk_runner_delete.mutation.graphql6
-rw-r--r--app/assets/javascripts/runner/graphql/list/group_runner_connection.fragment.graphql16
-rw-r--r--app/assets/javascripts/runner/graphql/list/group_runners.query.graphql16
-rw-r--r--app/assets/javascripts/runner/graphql/list/list_item_shared.fragment.graphql2
-rw-r--r--app/assets/javascripts/runner/graphql/list/local_state.js18
-rw-r--r--app/assets/javascripts/runner/graphql/show/runner_details_shared.fragment.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/show/runner_projects.query.graphql4
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue32
-rw-r--r--app/assets/javascripts/runner/runner_search_utils.js71
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js1
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue39
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue22
-rw-r--r--app/assets/javascripts/sidebar/components/attention_requested_toggle.vue105
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/reviewers.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue64
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue22
-rw-r--r--app/assets/javascripts/sidebar/components/severity/severity.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue8
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js17
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_participants.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_reference.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_todo.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/group_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_reference.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_todo.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/project_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/remove_attention_request.mutation.graphql7
-rw-r--r--app/assets/javascripts/sidebar/queries/request_attention.mutation.graphql5
-rw-r--r--app/assets/javascripts/sidebar/queries/todo_create.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/todo_mark_done.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/update_merge_request_milestone.mutation.graphql2
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js23
-rw-r--r--app/assets/javascripts/sidebar/sidebar_bundle.js12
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js87
-rw-r--r--app/assets/javascripts/sidebar/stores/sidebar_store.js34
-rw-r--r--app/assets/javascripts/snippets/fragments/snippet_base.fragment.graphql35
-rw-r--r--app/assets/javascripts/surveys/merge_request_experience/app.js10
-rw-r--r--app/assets/javascripts/surveys/merge_request_experience/app.vue9
-rw-r--r--app/assets/javascripts/task_list.js8
-rw-r--r--app/assets/javascripts/test_utils/index.js2
-rw-r--r--app/assets/javascripts/user_popovers.js4
-rw-r--r--app/assets/javascripts/visibility_level/constants.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue124
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue85
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue18
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue116
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue34
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue20
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/state_container.vue55
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue94
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue44
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue65
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue168
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue141
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue345
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue33
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue53
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue29
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue158
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue50
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js14
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/store/modules/filters/actions.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/gitlab_version_check.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue95
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue61
-rw-r--r--app/assets/javascripts/vue_shared/components/project_avatar.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_timestamp_tooltip.vue42
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql26
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/source_editor.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/components/chunk.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/constants.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js39
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js13
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image_new.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link_new.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/user_select/user_select.vue54
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue30
-rw-r--r--app/assets/javascripts/vue_shared/constants.js27
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue12
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/constants.js7
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue24
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue7
-rw-r--r--app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue2
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue2
-rw-r--r--app/assets/javascripts/whats_new/components/feature.vue29
-rw-r--r--app/assets/javascripts/work_items/components/item_state.vue10
-rw-r--r--app/assets/javascripts/work_items/components/item_title.vue5
-rw-r--r--app/assets/javascripts/work_items/components/work_item_actions.vue55
-rw-r--r--app/assets/javascripts/work_items/components/work_item_assignees.vue95
-rw-r--r--app/assets/javascripts/work_items/components/work_item_description.vue10
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue150
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail_modal.vue41
-rw-r--r--app/assets/javascripts/work_items/components/work_item_labels.vue3
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/index.js16
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue269
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue133
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue79
-rw-r--r--app/assets/javascripts/work_items/components/work_item_state.vue7
-rw-r--r--app/assets/javascripts/work_items/components/work_item_title.vue7
-rw-r--r--app/assets/javascripts/work_items/components/work_item_type_icon.vue44
-rw-r--r--app/assets/javascripts/work_items/components/work_item_weight.vue40
-rw-r--r--app/assets/javascripts/work_items/constants.js44
-rw-r--r--app/assets/javascripts/work_items/graphql/change_work_item_parent_link.mutation.graphql13
-rw-r--r--app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql3
-rw-r--r--app/assets/javascripts/work_items/graphql/create_work_item_from_task.mutation.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/local_update_work_item.mutation.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/provider.js28
-rw-r--r--app/assets/javascripts/work_items/graphql/typedefs.graphql26
-rw-r--r--app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/update_work_item_task.mutation.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/update_work_item_widgets.mutation.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.fragment.graphql10
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.query.graphql6
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_links.query.graphql6
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-rw-r--r--app/assets/stylesheets/components/avatar.scss12
-rw-r--r--app/assets/stylesheets/components/batch_comments/review_bar.scss2
-rw-r--r--app/assets/stylesheets/components/rich_content_editor.scss54
-rw-r--r--app/assets/stylesheets/framework/blocks.scss83
-rw-r--r--app/assets/stylesheets/framework/calendar.scss39
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss14
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar_header.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss28
-rw-r--r--app/assets/stylesheets/framework/files.scss17
-rw-r--r--app/assets/stylesheets/framework/highlight.scss58
-rw-r--r--app/assets/stylesheets/framework/mixins.scss2
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss19
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss4
-rw-r--r--app/assets/stylesheets/framework/sortable.scss2
-rw-r--r--app/assets/stylesheets/framework/timeline.scss4
-rw-r--r--app/assets/stylesheets/framework/typography.scss29
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/assets/stylesheets/framework/vue_transitions.scss2
-rw-r--r--app/assets/stylesheets/highlight/common.scss31
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss10
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss10
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss10
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss10
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss10
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss10
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/escalation_policies.scss16
-rw-r--r--app/assets/stylesheets/page_bundles/group.scss59
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss32
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss18
-rw-r--r--app/assets/stylesheets/page_bundles/profile.scss212
-rw-r--r--app/assets/stylesheets/page_bundles/runner_details.scss3
-rw-r--r--app/assets/stylesheets/pages/issuable.scss2
-rw-r--r--app/assets/stylesheets/pages/issues.scss2
-rw-r--r--app/assets/stylesheets/pages/login.scss14
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/note_form.scss9
-rw-r--r--app/assets/stylesheets/pages/notes.scss10
-rw-r--r--app/assets/stylesheets/pages/profile.scss94
-rw-r--r--app/assets/stylesheets/pages/search.scss37
-rw-r--r--app/assets/stylesheets/pages/settings_ci_cd.scss18
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss43
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss35
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss177
-rw-r--r--app/assets/stylesheets/themes/_dark.scss2
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss16
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss8
-rw-r--r--app/channels/awareness_channel.rb1
-rw-r--r--app/components/diffs/overflow_warning_component.html.haml2
-rw-r--r--app/components/pajamas/avatar_component.html.haml12
-rw-r--r--app/components/pajamas/avatar_component.rb69
-rw-r--r--app/components/pajamas/button_component.html.haml9
-rw-r--r--app/components/pajamas/button_component.rb8
-rw-r--r--app/components/pajamas/checkbox_component.rb9
-rw-r--r--app/components/pajamas/checkbox_tag_component.html.haml6
-rw-r--r--app/components/pajamas/checkbox_tag_component.rb44
-rw-r--r--app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb4
-rw-r--r--app/components/pajamas/radio_component.rb4
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/controllers/admin/applications_controller.rb1
-rw-r--r--app/controllers/admin/broadcast_messages_controller.rb1
-rw-r--r--app/controllers/admin/ci/variables_controller.rb4
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb17
-rw-r--r--app/controllers/admin/projects_controller.rb4
-rw-r--r--app/controllers/admin/runner_projects_controller.rb2
-rw-r--r--app/controllers/admin/system_info_controller.rb18
-rw-r--r--app/controllers/admin/topics_controller.rb20
-rw-r--r--app/controllers/admin/usage_trends_controller.rb16
-rw-r--r--app/controllers/admin/users_controller.rb2
-rw-r--r--app/controllers/autocomplete_controller.rb9
-rw-r--r--app/controllers/concerns/accepts_pending_invitations.rb14
-rw-r--r--app/controllers/concerns/creates_commit.rb3
-rw-r--r--app/controllers/concerns/issuable_actions.rb16
-rw-r--r--app/controllers/concerns/notes_actions.rb3
-rw-r--r--app/controllers/concerns/product_analytics_tracking.rb37
-rw-r--r--app/controllers/concerns/redis_tracking.rb2
-rw-r--r--app/controllers/concerns/uploads_actions.rb6
-rw-r--r--app/controllers/groups/boards_controller.rb4
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb3
-rw-r--r--app/controllers/groups/variables_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb4
-rw-r--r--app/controllers/import/bulk_imports_controller.rb10
-rw-r--r--app/controllers/oauth/token_info_controller.rb2
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb5
-rw-r--r--app/controllers/profiles/personal_access_tokens_controller.rb6
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb2
-rw-r--r--app/controllers/projects/alerting/notifications_controller.rb2
-rw-r--r--app/controllers/projects/analytics/cycle_analytics/stages_controller.rb21
-rw-r--r--app/controllers/projects/blob_controller.rb1
-rw-r--r--app/controllers/projects/boards_controller.rb4
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb1
-rw-r--r--app/controllers/projects/ci/secure_files_controller.rb11
-rw-r--r--app/controllers/projects/compare_controller.rb2
-rw-r--r--app/controllers/projects/feature_flags_controller.rb6
-rw-r--r--app/controllers/projects/google_cloud/base_controller.rb12
-rw-r--r--app/controllers/projects/google_cloud/configuration_controller.rb1
-rw-r--r--app/controllers/projects/google_cloud/databases_controller.rb1
-rw-r--r--app/controllers/projects/google_cloud/deployments_controller.rb7
-rw-r--r--app/controllers/projects/google_cloud/gcp_regions_controller.rb6
-rw-r--r--app/controllers/projects/google_cloud/service_accounts_controller.rb22
-rw-r--r--app/controllers/projects/incidents_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb16
-rw-r--r--app/controllers/projects/jobs_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb30
-rw-r--r--app/controllers/projects/merge_requests/drafts_controller.rb4
-rw-r--r--app/controllers/projects/merge_requests_controller.rb5
-rw-r--r--app/controllers/projects/milestones_controller.rb4
-rw-r--r--app/controllers/projects/mirrors_controller.rb4
-rw-r--r--app/controllers/projects/pages_controller.rb22
-rw-r--r--app/controllers/projects/pipelines/stages_controller.rb3
-rw-r--r--app/controllers/projects/repositories_controller.rb4
-rw-r--r--app/controllers/projects/runner_projects_controller.rb2
-rw-r--r--app/controllers/projects/settings/integration_hook_logs_controller.rb2
-rw-r--r--app/controllers/projects/settings/integrations_controller.rb2
-rw-r--r--app/controllers/projects/settings/packages_and_registries_controller.rb11
-rw-r--r--app/controllers/projects/tags/releases_controller.rb39
-rw-r--r--app/controllers/projects/tree_controller.rb1
-rw-r--r--app/controllers/projects/variables_controller.rb2
-rw-r--r--app/controllers/projects/work_items_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb30
-rw-r--r--app/controllers/registrations_controller.rb1
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb2
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb12
-rw-r--r--app/controllers/repositories/lfs_locks_api_controller.rb4
-rw-r--r--app/controllers/search_controller.rb19
-rw-r--r--app/controllers/sessions_controller.rb4
-rw-r--r--app/controllers/uploads_controller.rb12
-rw-r--r--app/controllers/users/namespace_callouts_controller.rb17
-rw-r--r--app/controllers/users/project_callouts_controller.rb17
-rw-r--r--app/controllers/users_controller.rb6
-rw-r--r--app/events/groups/group_deleted_event.rb16
-rw-r--r--app/events/groups/group_path_changed_event.rb18
-rw-r--r--app/events/groups/group_transfered_event.rb17
-rw-r--r--app/events/merge_requests/approved_event.rb19
-rw-r--r--app/events/projects/project_archived_event.rb17
-rw-r--r--app/events/projects/project_transfered_event.rb25
-rw-r--r--app/experiments/security_reports_mr_widget_prompt_experiment.rb4
-rw-r--r--app/experiments/video_tutorials_continuous_onboarding_experiment.rb4
-rw-r--r--app/finders/autocomplete/deploy_keys_with_write_access_finder.rb21
-rw-r--r--app/finders/ci/daily_build_group_report_results_finder.rb10
-rw-r--r--app/finders/ci/runners_finder.rb11
-rw-r--r--app/finders/crm/contacts_finder.rb21
-rw-r--r--app/finders/fork_targets_finder.rb30
-rw-r--r--app/finders/groups/accepting_project_transfers_finder.rb43
-rw-r--r--app/finders/groups/user_groups_finder.rb4
-rw-r--r--app/finders/issuable_finder.rb3
-rw-r--r--app/finders/projects/topics_finder.rb7
-rw-r--r--app/finders/releases/group_releases_finder.rb2
-rw-r--r--app/finders/repositories/changelog_tag_finder.rb4
-rw-r--r--app/finders/tags_finder.rb2
-rw-r--r--app/graphql/gitlab_schema.rb2
-rw-r--r--app/graphql/graphql_triggers.rb4
-rw-r--r--app/graphql/mutations/award_emojis/toggle.rb7
-rw-r--r--app/graphql/mutations/ci/job/retry.rb11
-rw-r--r--app/graphql/mutations/ci/pipeline/cancel.rb1
-rw-r--r--app/graphql/mutations/ci/runner/bulk_delete.rb56
-rw-r--r--app/graphql/mutations/ci/runner/update.rb10
-rw-r--r--app/graphql/mutations/ci/runners_registration_token/reset.rb5
-rw-r--r--app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb10
-rw-r--r--app/graphql/mutations/container_repositories/destroy.rb2
-rw-r--r--app/graphql/mutations/design_management/move.rb19
-rw-r--r--app/graphql/mutations/issues/move.rb4
-rw-r--r--app/graphql/mutations/issues/set_confidential.rb2
-rw-r--r--app/graphql/mutations/issues/set_severity.rb5
-rw-r--r--app/graphql/mutations/merge_requests/remove_attention_request.rb40
-rw-r--r--app/graphql/mutations/merge_requests/request_attention.rb40
-rw-r--r--app/graphql/mutations/merge_requests/set_reviewers.rb52
-rw-r--r--app/graphql/mutations/merge_requests/toggle_attention_requested.rb29
-rw-r--r--app/graphql/mutations/notes/create/base.rb10
-rw-r--r--app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb14
-rw-r--r--app/graphql/mutations/timelogs/base.rb18
-rw-r--r--app/graphql/mutations/timelogs/create.rb48
-rw-r--r--app/graphql/mutations/timelogs/delete.rb13
-rw-r--r--app/graphql/mutations/uploads/delete.rb37
-rw-r--r--app/graphql/mutations/work_items/create.rb3
-rw-r--r--app/graphql/mutations/work_items/update.rb2
-rw-r--r--app/graphql/resolvers/ci/config_resolver.rb4
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/template_resolver.rb7
-rw-r--r--app/graphql/resolvers/crm/contact_state_counts_resolver.rb25
-rw-r--r--app/graphql/resolvers/crm/contacts_resolver.rb21
-rw-r--r--app/graphql/resolvers/environments_resolver.rb4
-rw-r--r--app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb2
-rw-r--r--app/graphql/resolvers/group_milestones_resolver.rb4
-rw-r--r--app/graphql/resolvers/projects/fork_targets_resolver.rb27
-rw-r--r--app/graphql/resolvers/projects_resolver.rb4
-rw-r--r--app/graphql/resolvers/users_resolver.rb2
-rw-r--r--app/graphql/resolvers/work_items_resolver.rb2
-rw-r--r--app/graphql/types/access_level_type.rb8
-rw-r--r--app/graphql/types/admin/analytics/usage_trends/measurement_type.rb8
-rw-r--r--app/graphql/types/alert_management/domain_filter_enum.rb11
-rw-r--r--app/graphql/types/base_field.rb4
-rw-r--r--app/graphql/types/board_list_type.rb16
-rw-r--r--app/graphql/types/board_type.rb16
-rw-r--r--app/graphql/types/ci/analytics_type.rb22
-rw-r--r--app/graphql/types/ci/application_setting_type.rb2
-rw-r--r--app/graphql/types/ci/build_need_type.rb4
-rw-r--r--app/graphql/types/ci/ci_cd_setting_type.rb22
-rw-r--r--app/graphql/types/ci/config/config_type.rb12
-rw-r--r--app/graphql/types/ci/config/group_type.rb6
-rw-r--r--app/graphql/types/ci/config/job_restriction_type.rb2
-rw-r--r--app/graphql/types/ci/config/job_type.rb38
-rw-r--r--app/graphql/types/ci/config/need_type.rb2
-rw-r--r--app/graphql/types/ci/config/stage_type.rb4
-rw-r--r--app/graphql/types/ci/detailed_status_type.rb30
-rw-r--r--app/graphql/types/ci/group_type.rb10
-rw-r--r--app/graphql/types/ci/group_variable_type.rb25
-rw-r--r--app/graphql/types/ci/instance_variable_type.rb33
-rw-r--r--app/graphql/types/ci/job_artifact_type.rb8
-rw-r--r--app/graphql/types/ci/job_token_scope_type.rb8
-rw-r--r--app/graphql/types/ci/job_type.rb72
-rw-r--r--app/graphql/types/ci/manual_variable_type.rb25
-rw-r--r--app/graphql/types/ci/pipeline_message_type.rb4
-rw-r--r--app/graphql/types/ci/pipeline_type.rb72
-rw-r--r--app/graphql/types/ci/project_variable_type.rb25
-rw-r--r--app/graphql/types/ci/recent_failures_type.rb4
-rw-r--r--app/graphql/types/ci/runner_architecture_type.rb8
-rw-r--r--app/graphql/types/ci/runner_platform_type.rb10
-rw-r--r--app/graphql/types/ci/runner_setup_type.rb4
-rw-r--r--app/graphql/types/ci/runner_type.rb76
-rw-r--r--app/graphql/types/ci/runner_upgrade_status_enum.rb20
-rw-r--r--app/graphql/types/ci/runner_upgrade_status_type_enum.rb20
-rw-r--r--app/graphql/types/ci/runner_web_url_edge.rb8
-rw-r--r--app/graphql/types/ci/stage_type.rb12
-rw-r--r--app/graphql/types/ci/status_action_type.rb16
-rw-r--r--app/graphql/types/ci/template_type.rb4
-rw-r--r--app/graphql/types/ci/test_case_type.rb26
-rw-r--r--app/graphql/types/ci/test_report_summary_type.rb8
-rw-r--r--app/graphql/types/ci/test_report_total_type.rb14
-rw-r--r--app/graphql/types/ci/test_suite_summary_type.rb30
-rw-r--r--app/graphql/types/ci/test_suite_type.rb29
-rw-r--r--app/graphql/types/ci/variable_input_type.rb13
-rw-r--r--app/graphql/types/ci/variable_interface.rb31
-rw-r--r--app/graphql/types/ci/variable_type.rb40
-rw-r--r--app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb4
-rw-r--r--app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb14
-rw-r--r--app/graphql/types/ci_configuration/sast/entity_input_type.rb6
-rw-r--r--app/graphql/types/ci_configuration/sast/entity_type.rb20
-rw-r--r--app/graphql/types/ci_configuration/sast/options_entity_type.rb4
-rw-r--r--app/graphql/types/ci_configuration/sast/type.rb18
-rw-r--r--app/graphql/types/commit_action_type.rb14
-rw-r--r--app/graphql/types/commit_type.rb30
-rw-r--r--app/graphql/types/concerns/gitlab_style_deprecations.rb5
-rw-r--r--app/graphql/types/countable_connection_type.rb2
-rw-r--r--app/graphql/types/customer_relations/contact_sort_enum.rb21
-rw-r--r--app/graphql/types/customer_relations/contact_state_counts_type.rb23
-rw-r--r--app/graphql/types/customer_relations/contact_state_enum.rb8
-rw-r--r--app/graphql/types/design_management/design_collection_type.rb4
-rw-r--r--app/graphql/types/design_management/design_fields.rb5
-rw-r--r--app/graphql/types/design_management/version_type.rb6
-rw-r--r--app/graphql/types/diff_paths_input_type.rb4
-rw-r--r--app/graphql/types/diff_refs_type.rb6
-rw-r--r--app/graphql/types/diff_stats_summary_type.rb8
-rw-r--r--app/graphql/types/diff_stats_type.rb6
-rw-r--r--app/graphql/types/environment_type.rb12
-rw-r--r--app/graphql/types/evidence_type.rb8
-rw-r--r--app/graphql/types/global_id_type.rb2
-rw-r--r--app/graphql/types/grafana_integration_type.rb10
-rw-r--r--app/graphql/types/group_invitation_type.rb2
-rw-r--r--app/graphql/types/group_member_type.rb2
-rw-r--r--app/graphql/types/group_type.rb19
-rw-r--r--app/graphql/types/invitation_interface.rb14
-rw-r--r--app/graphql/types/issue_type.rb106
-rw-r--r--app/graphql/types/issue_type_enum.rb2
-rw-r--r--app/graphql/types/jira_import_type.rb14
-rw-r--r--app/graphql/types/jira_user_type.rb14
-rw-r--r--app/graphql/types/label_type.rb16
-rw-r--r--app/graphql/types/member_interface.rb14
-rw-r--r--app/graphql/types/merge_request_connection_type.rb4
-rw-r--r--app/graphql/types/merge_request_type.rb157
-rw-r--r--app/graphql/types/merge_requests/detailed_merge_status_enum.rb44
-rw-r--r--app/graphql/types/metadata/kas_type.rb6
-rw-r--r--app/graphql/types/metadata_type.rb6
-rw-r--r--app/graphql/types/metrics/dashboard_type.rb10
-rw-r--r--app/graphql/types/metrics/dashboards/annotation_type.rb12
-rw-r--r--app/graphql/types/milestone_stats_type.rb8
-rw-r--r--app/graphql/types/milestone_type.rb36
-rw-r--r--app/graphql/types/mutation_type.rb25
-rw-r--r--app/graphql/types/namespace_type.rb41
-rw-r--r--app/graphql/types/notes/diff_image_position_input_type.rb16
-rw-r--r--app/graphql/types/notes/diff_position_base_input_type.rb6
-rw-r--r--app/graphql/types/notes/diff_position_input_type.rb4
-rw-r--r--app/graphql/types/notes/diff_position_type.rb24
-rw-r--r--app/graphql/types/notes/discussion_type.rb10
-rw-r--r--app/graphql/types/notes/note_type.rb28
-rw-r--r--app/graphql/types/packages/package_base_type.rb6
-rw-r--r--app/graphql/types/packages/package_details_type.rb2
-rw-r--r--app/graphql/types/packages/package_file_type.rb2
-rw-r--r--app/graphql/types/permission_types/group_enum.rb3
-rw-r--r--app/graphql/types/project_invitation_type.rb2
-rw-r--r--app/graphql/types/project_member_type.rb2
-rw-r--r--app/graphql/types/project_statistics_type.rb26
-rw-r--r--app/graphql/types/project_type.rb134
-rw-r--r--app/graphql/types/projects/service_type.rb6
-rw-r--r--app/graphql/types/projects/services/jira_project_type.rb8
-rw-r--r--app/graphql/types/projects/topic_type.rb12
-rw-r--r--app/graphql/types/prometheus_alert_type.rb2
-rw-r--r--app/graphql/types/query_type.rb6
-rw-r--r--app/graphql/types/release_asset_link_type.rb16
-rw-r--r--app/graphql/types/release_assets_type.rb6
-rw-r--r--app/graphql/types/release_links_type.rb26
-rw-r--r--app/graphql/types/release_source_type.rb4
-rw-r--r--app/graphql/types/release_type.rb36
-rw-r--r--app/graphql/types/repository/blob_type.rb88
-rw-r--r--app/graphql/types/repository_type.rb18
-rw-r--r--app/graphql/types/resolvable_interface.rb10
-rw-r--r--app/graphql/types/snippet_type.rb28
-rw-r--r--app/graphql/types/snippets/blob_connection_type.rb4
-rw-r--r--app/graphql/types/snippets/blob_type.rb22
-rw-r--r--app/graphql/types/subscription_type.rb11
-rw-r--r--app/graphql/types/task_completion_status.rb4
-rw-r--r--app/graphql/types/time_tracking/timelog_category_type.rb51
-rw-r--r--app/graphql/types/tree/blob_type.rb10
-rw-r--r--app/graphql/types/tree/entry_type.rb12
-rw-r--r--app/graphql/types/tree/submodule_type.rb4
-rw-r--r--app/graphql/types/tree/tree_entry_type.rb4
-rw-r--r--app/graphql/types/tree/tree_type.rb10
-rw-r--r--app/graphql/types/upload_type.rb19
-rw-r--r--app/graphql/types/user_callout_type.rb4
-rw-r--r--app/graphql/types/user_interface.rb8
-rw-r--r--app/graphql/types/user_status_type.rb8
-rw-r--r--app/graphql/types/work_item_type.rb31
-rw-r--r--app/graphql/types/work_items/type_type.rb6
-rw-r--r--app/graphql/types/work_items/widget_interface.rb30
-rw-r--r--app/graphql/types/work_items/widgets/assignees_input_type.rb16
-rw-r--r--app/graphql/types/work_items/widgets/assignees_type.rb15
-rw-r--r--app/graphql/types/work_items/widgets/description_type.rb5
-rw-r--r--app/graphql/types/work_items/widgets/hierarchy_type.rb12
-rw-r--r--app/graphql/types/work_items/widgets/labels_type.rb27
-rw-r--r--app/graphql/types/work_items/widgets/start_and_due_date_type.rb25
-rw-r--r--app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb18
-rw-r--r--app/graphql/types/work_items/widgets/weight_input_type.rb15
-rw-r--r--app/graphql/types/work_items/widgets/weight_type.rb21
-rw-r--r--app/helpers/admin/identities_helper.rb36
-rw-r--r--app/helpers/application_helper.rb22
-rw-r--r--app/helpers/avatars_helper.rb6
-rw-r--r--app/helpers/badges_helper.rb6
-rw-r--r--app/helpers/blob_helper.rb16
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb3
-rw-r--r--app/helpers/ci/pipelines_helper.rb4
-rw-r--r--app/helpers/ci/runners_helper.rb2
-rw-r--r--app/helpers/commits_helper.rb9
-rw-r--r--app/helpers/compare_helper.rb57
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/environments_helper.rb44
-rw-r--r--app/helpers/events_helper.rb2
-rw-r--r--app/helpers/favicon_helper.rb6
-rw-r--r--app/helpers/form_helper.rb44
-rw-r--r--app/helpers/gitlab_script_tag_helper.rb4
-rw-r--r--app/helpers/groups/group_members_helper.rb9
-rw-r--r--app/helpers/groups_helper.rb17
-rw-r--r--app/helpers/instance_configuration_helper.rb2
-rw-r--r--app/helpers/issuables_description_templates_helper.rb29
-rw-r--r--app/helpers/issuables_helper.rb10
-rw-r--r--app/helpers/labels_helper.rb2
-rw-r--r--app/helpers/markup_helper.rb13
-rw-r--r--app/helpers/members_helper.rb18
-rw-r--r--app/helpers/merge_requests_helper.rb60
-rw-r--r--app/helpers/namespaces_helper.rb18
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb2
-rw-r--r--app/helpers/nav/top_nav_helper.rb7
-rw-r--r--app/helpers/packages_helper.rb23
-rw-r--r--app/helpers/preferences_helper.rb2
-rw-r--r--app/helpers/profiles_helper.rb4
-rw-r--r--app/helpers/projects/pipeline_helper.rb9
-rw-r--r--app/helpers/projects_helper.rb59
-rw-r--r--app/helpers/search_helper.rb36
-rw-r--r--app/helpers/sorting_helper.rb178
-rw-r--r--app/helpers/storage_helper.rb86
-rw-r--r--app/helpers/system_note_helper.rb1
-rw-r--r--app/helpers/tab_helper.rb8
-rw-r--r--app/helpers/time_zone_helper.rb2
-rw-r--r--app/helpers/todos_helper.rb11
-rw-r--r--app/helpers/users_helper.rb12
-rw-r--r--app/helpers/webpack_helper.rb12
-rw-r--r--app/helpers/wiki_helper.rb8
-rw-r--r--app/mailers/abuse_report_mailer.rb4
-rw-r--r--app/mailers/emails/admin_notification.rb20
-rw-r--r--app/mailers/emails/merge_requests.rb7
-rw-r--r--app/mailers/emails/projects.rb6
-rw-r--r--app/models/application_setting.rb4
-rw-r--r--app/models/application_setting_implementation.rb2
-rw-r--r--app/models/approval.rb3
-rw-r--r--app/models/audit_event.rb12
-rw-r--r--app/models/authentication_event.rb2
-rw-r--r--app/models/blob.rb4
-rw-r--r--app/models/blob_viewer/metrics_dashboard_yml.rb12
-rw-r--r--app/models/bulk_imports/configuration.rb2
-rw-r--r--app/models/bulk_imports/entity.rb4
-rw-r--r--app/models/chat_name.rb6
-rw-r--r--app/models/ci/bridge.rb9
-rw-r--r--app/models/ci/build.rb90
-rw-r--r--app/models/ci/build_metadata.rb1
-rw-r--r--app/models/ci/build_trace_metadata.rb4
-rw-r--r--app/models/ci/deleted_object.rb4
-rw-r--r--app/models/ci/job_artifact.rb67
-rw-r--r--app/models/ci/pipeline.rb104
-rw-r--r--app/models/ci/processable.rb2
-rw-r--r--app/models/ci/runner.rb17
-rw-r--r--app/models/ci/runner_version.rb4
-rw-r--r--app/models/ci/secure_file.rb6
-rw-r--r--app/models/commit.rb2
-rw-r--r--app/models/commit_range.rb4
-rw-r--r--app/models/commit_signatures/ssh_signature.rb2
-rw-r--r--app/models/compare.rb2
-rw-r--r--app/models/concerns/ci/artifactable.rb4
-rw-r--r--app/models/concerns/ci/has_status.rb4
-rw-r--r--app/models/concerns/ci/metadatable.rb10
-rw-r--r--app/models/concerns/counter_attribute.rb47
-rw-r--r--app/models/concerns/cross_database_modification.rb36
-rw-r--r--app/models/concerns/database_event_tracking.rb53
-rw-r--r--app/models/concerns/diff_positionable_note.rb6
-rw-r--r--app/models/concerns/enums/data_visualization_palette.rb22
-rw-r--r--app/models/concerns/enums/sbom.rb13
-rw-r--r--app/models/concerns/expirable.rb5
-rw-r--r--app/models/concerns/featurable.rb8
-rw-r--r--app/models/concerns/integrations/base_data_fields.rb17
-rw-r--r--app/models/concerns/integrations/has_data_fields.rb4
-rw-r--r--app/models/concerns/integrations/has_web_hook.rb1
-rw-r--r--app/models/concerns/issuable.rb18
-rw-r--r--app/models/concerns/participable.rb8
-rw-r--r--app/models/concerns/project_features_compatibility.rb12
-rw-r--r--app/models/concerns/prometheus_adapter.rb4
-rw-r--r--app/models/concerns/repository_storage_movable.rb4
-rw-r--r--app/models/concerns/taskable.rb4
-rw-r--r--app/models/concerns/triggerable_hooks.rb30
-rw-r--r--app/models/concerns/vulnerability_finding_helpers.rb3
-rw-r--r--app/models/concerns/x509_serial_number_attribute.rb4
-rw-r--r--app/models/container_repository.rb44
-rw-r--r--app/models/custom_emoji.rb2
-rw-r--r--app/models/customer_relations/contact.rb26
-rw-r--r--app/models/customer_relations/contact_state_counts.rb42
-rw-r--r--app/models/deploy_key.rb9
-rw-r--r--app/models/deployment.rb7
-rw-r--r--app/models/design_management/design.rb4
-rw-r--r--app/models/design_management/design_action.rb2
-rw-r--r--app/models/environment.rb52
-rw-r--r--app/models/event.rb49
-rw-r--r--app/models/gpg_key.rb2
-rw-r--r--app/models/grafana_integration.rb4
-rw-r--r--app/models/group.rb20
-rw-r--r--app/models/group_group_link.rb17
-rw-r--r--app/models/hooks/web_hook.rb23
-rw-r--r--app/models/integration.rb6
-rw-r--r--app/models/integrations/bamboo.rb4
-rw-r--r--app/models/integrations/base_issue_tracker.rb4
-rw-r--r--app/models/integrations/base_slash_commands.rb2
-rw-r--r--app/models/integrations/buildkite.rb2
-rw-r--r--app/models/integrations/datadog.rb157
-rw-r--r--app/models/integrations/discord.rb39
-rw-r--r--app/models/integrations/emails_on_push.rb2
-rw-r--r--app/models/integrations/external_wiki.rb11
-rw-r--r--app/models/integrations/harbor.rb7
-rw-r--r--app/models/integrations/jenkins.rb4
-rw-r--r--app/models/integrations/jira.rb36
-rw-r--r--app/models/integrations/packagist.rb13
-rw-r--r--app/models/integrations/pipelines_email.rb4
-rw-r--r--app/models/integrations/prometheus.rb4
-rw-r--r--app/models/integrations/pumble.rb59
-rw-r--r--app/models/integrations/slack.rb17
-rw-r--r--app/models/integrations/teamcity.rb4
-rw-r--r--app/models/issuable_severity.rb16
-rw-r--r--app/models/issue.rb61
-rw-r--r--app/models/jira_connect_installation.rb4
-rw-r--r--app/models/key.rb1
-rw-r--r--app/models/lfs_object.rb2
-rw-r--r--app/models/loose_foreign_keys/deleted_record.rb37
-rw-r--r--app/models/member.rb12
-rw-r--r--app/models/members/group_member.rb23
-rw-r--r--app/models/members/last_group_owner_assigner.rb4
-rw-r--r--app/models/members/member_role.rb9
-rw-r--r--app/models/members/project_member.rb7
-rw-r--r--app/models/merge_request.rb86
-rw-r--r--app/models/merge_request/approval_removal_settings.rb39
-rw-r--r--app/models/merge_request/metrics.rb3
-rw-r--r--app/models/merge_request_diff.rb11
-rw-r--r--app/models/ml.rb6
-rw-r--r--app/models/ml/candidate.rb12
-rw-r--r--app/models/ml/candidate_metric.rb10
-rw-r--r--app/models/ml/candidate_param.rb10
-rw-r--r--app/models/ml/experiment.rb12
-rw-r--r--app/models/namespace.rb19
-rw-r--r--app/models/namespace/detail.rb9
-rw-r--r--app/models/namespaces/traversal/linear_scopes.rb61
-rw-r--r--app/models/network/graph.rb2
-rw-r--r--app/models/note.rb18
-rw-r--r--app/models/notification_reason.rb2
-rw-r--r--app/models/oauth_access_token.rb11
-rw-r--r--app/models/operations/feature_flag.rb2
-rw-r--r--app/models/packages/package.rb4
-rw-r--r--app/models/pages_domain.rb4
-rw-r--r--app/models/performance_monitoring/prometheus_dashboard.rb8
-rw-r--r--app/models/personal_access_token.rb10
-rw-r--r--app/models/preloaders/labels_preloader.rb4
-rw-r--r--app/models/project.rb61
-rw-r--r--app/models/project_feature.rb3
-rw-r--r--app/models/projects/import_export/relation_export.rb41
-rw-r--r--app/models/projects/topic.rb1
-rw-r--r--app/models/prometheus_alert.rb2
-rw-r--r--app/models/protected_branch.rb25
-rw-r--r--app/models/release.rb2
-rw-r--r--app/models/release_highlight.rb4
-rw-r--r--app/models/repository.rb18
-rw-r--r--app/models/sent_notification.rb12
-rw-r--r--app/models/serverless/domain_cluster.rb2
-rw-r--r--app/models/snippet.rb4
-rw-r--r--app/models/snippet_repository.rb6
-rw-r--r--app/models/system_note_metadata.rb2
-rw-r--r--app/models/terraform/state.rb2
-rw-r--r--app/models/todo.rb14
-rw-r--r--app/models/u2f_registration.rb34
-rw-r--r--app/models/user.rb129
-rw-r--r--app/models/user_status.rb16
-rw-r--r--app/models/users/callout.rb9
-rw-r--r--app/models/users/group_callout.rb8
-rw-r--r--app/models/users/project_callout.rb21
-rw-r--r--app/models/wiki.rb10
-rw-r--r--app/models/work_item.rb15
-rw-r--r--app/models/work_items/parent_link.rb23
-rw-r--r--app/models/work_items/type.rb16
-rw-r--r--app/models/work_items/widgets/labels.rb10
-rw-r--r--app/models/work_items/widgets/start_and_due_date.rb9
-rw-r--r--app/models/work_items/widgets/weight.rb9
-rw-r--r--app/policies/ci/runner_policy.rb2
-rw-r--r--app/policies/deployment_policy.rb2
-rw-r--r--app/policies/group_policy.rb3
-rw-r--r--app/policies/issuable_policy.rb4
-rw-r--r--app/policies/namespaces/group_project_namespace_shared_policy.rb14
-rw-r--r--app/policies/namespaces/project_namespace_policy.rb6
-rw-r--r--app/policies/namespaces/user_namespace_policy.rb1
-rw-r--r--app/policies/project_hook_policy.rb10
-rw-r--r--app/policies/project_policy.rb27
-rw-r--r--app/policies/system_hook_policy.rb8
-rw-r--r--app/policies/time_tracking/timelog_category_policy.rb7
-rw-r--r--app/policies/upload_policy.rb5
-rw-r--r--app/policies/work_item_policy.rb3
-rw-r--r--app/presenters/analytics/cycle_analytics/stage_presenter.rb2
-rw-r--r--app/presenters/ci/build_runner_presenter.rb3
-rw-r--r--app/presenters/merge_request_presenter.rb13
-rw-r--r--app/presenters/project_hook_presenter.rb2
-rw-r--r--app/presenters/project_member_presenter.rb22
-rw-r--r--app/presenters/project_presenter.rb4
-rw-r--r--app/presenters/service_hook_presenter.rb2
-rw-r--r--app/presenters/web_hook_log_presenter.rb2
-rw-r--r--app/serializers/concerns/user_status_tooltip.rb2
-rw-r--r--app/serializers/environment_serializer.rb21
-rw-r--r--app/serializers/group_access_token_entity.rb26
-rw-r--r--app/serializers/group_access_token_serializer.rb7
-rw-r--r--app/serializers/integrations/project_entity.rb1
-rw-r--r--app/serializers/issue_entity.rb4
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb13
-rw-r--r--app/serializers/merge_request_user_entity.rb4
-rw-r--r--app/serializers/personal_access_token_entity.rb11
-rw-r--r--app/serializers/personal_access_token_serializer.rb7
-rw-r--r--app/serializers/project_access_token_entity.rb27
-rw-r--r--app/serializers/project_access_token_serializer.rb7
-rw-r--r--app/serializers/rollout_status_entity.rb2
-rw-r--r--app/services/audit_events/build_service.rb87
-rw-r--r--app/services/authorized_project_update/project_recalculate_service.rb2
-rw-r--r--app/services/auto_merge/base_service.rb1
-rw-r--r--app/services/base_count_service.rb2
-rw-r--r--app/services/boards/destroy_service.rb4
-rw-r--r--app/services/boards/lists/move_service.rb2
-rw-r--r--app/services/branches/create_service.rb84
-rw-r--r--app/services/bulk_imports/create_service.rb2
-rw-r--r--app/services/bulk_imports/file_download_service.rb9
-rw-r--r--app/services/chat_names/authorize_user_service.rb12
-rw-r--r--app/services/ci/archive_trace_service.rb4
-rw-r--r--app/services/ci/deployments/destroy_service.rb18
-rw-r--r--app/services/ci/destroy_pipeline_service.rb2
-rw-r--r--app/services/ci/job_artifacts/create_service.rb2
-rw-r--r--app/services/ci/job_artifacts/destroy_batch_service.rb4
-rw-r--r--app/services/ci/list_config_variables_service.rb4
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb2
-rw-r--r--app/services/ci/register_job_service.rb18
-rw-r--r--app/services/ci/retry_job_service.rb12
-rw-r--r--app/services/ci/runners/assign_runner_service.rb10
-rw-r--r--app/services/ci/runners/bulk_delete_runners_service.rb36
-rw-r--r--app/services/ci/runners/process_runner_version_update_service.rb27
-rw-r--r--app/services/ci/runners/reconcile_existing_runner_versions_service.rb14
-rw-r--r--app/services/ci/runners/register_runner_service.rb4
-rw-r--r--app/services/ci/runners/reset_registration_token_service.rb10
-rw-r--r--app/services/ci/runners/unassign_runner_service.rb10
-rw-r--r--app/services/ci/runners/unregister_runner_service.rb1
-rw-r--r--app/services/ci/stuck_builds/drop_helpers.rb12
-rw-r--r--app/services/ci/track_failed_build_service.rb49
-rw-r--r--app/services/ci/update_build_state_service.rb2
-rw-r--r--app/services/concerns/alert_management/alert_processing.rb21
-rw-r--r--app/services/concerns/work_items/widgetable_service.rb2
-rw-r--r--app/services/database/consistency_check_service.rb2
-rw-r--r--app/services/deployments/update_environment_service.rb8
-rw-r--r--app/services/design_management/generate_image_versions_service.rb2
-rw-r--r--app/services/error_tracking/base_service.rb2
-rw-r--r--app/services/google_cloud/base_service.rb2
-rw-r--r--app/services/google_cloud/create_cloudsql_instance_service.rb74
-rw-r--r--app/services/google_cloud/enable_cloudsql_service.rb23
-rw-r--r--app/services/google_cloud/get_cloudsql_instances_service.rb18
-rw-r--r--app/services/google_cloud/setup_cloudsql_instance_service.rb80
-rw-r--r--app/services/groups/destroy_service.rb13
-rw-r--r--app/services/groups/import_export/export_service.rb20
-rw-r--r--app/services/groups/import_export/import_service.rb8
-rw-r--r--app/services/groups/transfer_service.rb17
-rw-r--r--app/services/groups/update_service.rb28
-rw-r--r--app/services/import/prepare_service.rb31
-rw-r--r--app/services/incident_management/timeline_events/create_service.rb20
-rw-r--r--app/services/incident_management/timeline_events/update_service.rb2
-rw-r--r--app/services/issuable/clone/base_service.rb1
-rw-r--r--app/services/issuable/common_system_notes_service.rb15
-rw-r--r--app/services/issuable/import_csv/base_service.rb16
-rw-r--r--app/services/issues/clone_service.rb12
-rw-r--r--app/services/issues/create_service.rb2
-rw-r--r--app/services/issues/export_csv_service.rb36
-rw-r--r--app/services/issues/prepare_import_csv_service.rb19
-rw-r--r--app/services/issues/update_service.rb7
-rw-r--r--app/services/jira/requests/base.rb8
-rw-r--r--app/services/merge_requests/approval_service.rb53
-rw-r--r--app/services/merge_requests/base_service.rb18
-rw-r--r--app/services/merge_requests/bulk_remove_attention_requested_service.rb28
-rw-r--r--app/services/merge_requests/close_service.rb1
-rw-r--r--app/services/merge_requests/create_approval_event_service.rb11
-rw-r--r--app/services/merge_requests/create_pipeline_service.rb3
-rw-r--r--app/services/merge_requests/execute_approval_hooks_service.rb13
-rw-r--r--app/services/merge_requests/handle_assignees_change_service.rb4
-rw-r--r--app/services/merge_requests/mergeability/check_base_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/check_broken_status_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/check_ci_status_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/check_discussions_status_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/check_draft_status_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/check_open_status_service.rb8
-rw-r--r--app/services/merge_requests/mergeability/run_checks_service.rb30
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb4
-rw-r--r--app/services/merge_requests/post_merge_service.rb1
-rw-r--r--app/services/merge_requests/push_options_handler_service.rb2
-rw-r--r--app/services/merge_requests/remove_approval_service.rb1
-rw-r--r--app/services/merge_requests/remove_attention_requested_service.rb50
-rw-r--r--app/services/merge_requests/reopen_service.rb2
-rw-r--r--app/services/merge_requests/request_attention_service.rb60
-rw-r--r--app/services/merge_requests/toggle_attention_requested_service.rb68
-rw-r--r--app/services/merge_requests/update_assignees_service.rb23
-rw-r--r--app/services/merge_requests/update_reviewers_service.rb44
-rw-r--r--app/services/merge_requests/update_service.rb36
-rw-r--r--app/services/notes/build_service.rb8
-rw-r--r--app/services/notes/create_service.rb24
-rw-r--r--app/services/notes/destroy_service.rb3
-rw-r--r--app/services/notes/update_service.rb3
-rw-r--r--app/services/notification_recipients/build_service.rb4
-rw-r--r--app/services/notification_recipients/builder/attention_requested.rb23
-rw-r--r--app/services/notification_service.rb10
-rw-r--r--app/services/packages/conan/create_package_file_service.rb6
-rw-r--r--app/services/packages/create_package_file_service.rb10
-rw-r--r--app/services/packages/debian/create_package_file_service.rb10
-rw-r--r--app/services/packages/debian/extract_metadata_service.rb8
-rw-r--r--app/services/packages/npm/create_package_service.rb6
-rw-r--r--app/services/projects/alerting/notify_service.rb2
-rw-r--r--app/services/projects/create_service.rb28
-rw-r--r--app/services/projects/fork_service.rb22
-rw-r--r--app/services/projects/import_export/export_service.rb35
-rw-r--r--app/services/projects/import_export/relation_export_service.rb95
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb2
-rw-r--r--app/services/projects/transfer_service.rb14
-rw-r--r--app/services/projects/update_remote_mirror_service.rb10
-rw-r--r--app/services/projects/update_service.rb14
-rw-r--r--app/services/protected_branches/base_service.rb4
-rw-r--r--app/services/protected_branches/cache_service.rb68
-rw-r--r--app/services/protected_branches/create_service.rb2
-rw-r--r--app/services/protected_branches/destroy_service.rb2
-rw-r--r--app/services/protected_branches/update_service.rb2
-rw-r--r--app/services/releases/create_service.rb4
-rw-r--r--app/services/resource_events/change_labels_service.rb14
-rw-r--r--app/services/security/ci_configuration/sast_parser_service.rb6
-rw-r--r--app/services/system_note_service.rb54
-rw-r--r--app/services/system_notes/issuables_service.rb84
-rw-r--r--app/services/system_notes/time_tracking_service.rb71
-rw-r--r--app/services/timelogs/base_service.rb21
-rw-r--r--app/services/timelogs/create_service.rb45
-rw-r--r--app/services/timelogs/delete_service.rb16
-rw-r--r--app/services/todo_service.rb5
-rw-r--r--app/services/todos/destroy/destroyed_issuable_service.rb7
-rw-r--r--app/services/topics/merge_service.rb64
-rw-r--r--app/services/uploads/destroy_service.rb51
-rw-r--r--app/services/users/dismiss_namespace_callout_service.rb11
-rw-r--r--app/services/users/dismiss_project_callout_service.rb11
-rw-r--r--app/services/users/update_service.rb2
-rw-r--r--app/services/web_hooks/admin_destroy_service.rb20
-rw-r--r--app/services/web_hooks/destroy_service.rb24
-rw-r--r--app/services/web_hooks/log_execution_service.rb25
-rw-r--r--app/services/webauthn/authenticate_service.rb2
-rw-r--r--app/services/work_items/create_and_link_service.rb19
-rw-r--r--app/services/work_items/parent_links/create_service.rb4
-rw-r--r--app/services/work_items/parent_links/destroy_service.rb4
-rw-r--r--app/services/work_items/update_service.rb4
-rw-r--r--app/services/work_items/widgets/assignees_service/update_service.rb36
-rw-r--r--app/services/work_items/widgets/base_service.rb9
-rw-r--r--app/services/work_items/widgets/description_service/update_service.rb8
-rw-r--r--app/services/work_items/widgets/hierarchy_service/base_service.rb15
-rw-r--r--app/services/work_items/widgets/start_and_due_date_service/update_service.rb15
-rw-r--r--app/services/work_items/widgets/weight_service/update_service.rb15
-rw-r--r--app/uploaders/avatar_uploader.rb4
-rw-r--r--app/uploaders/design_management/design_v432x230_uploader.rb4
-rw-r--r--app/uploaders/favicon_uploader.rb8
-rw-r--r--app/uploaders/file_uploader.rb4
-rw-r--r--app/uploaders/object_storage.rb10
-rw-r--r--app/validators/json_schemas/build_metadata_id_tokens.json22
-rw-r--r--app/validators/json_schemas/cyclonedx_report.json1697
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml2
-rw-r--r--app/views/admin/application_settings/_default_branch.html.haml2
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml4
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml2
-rw-r--r--app/views/admin/application_settings/_runner_registrars_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml2
-rw-r--r--app/views/admin/application_settings/_usage.html.haml4
-rw-r--r--app/views/admin/application_settings/_whats_new.html.haml2
-rw-r--r--app/views/admin/application_settings/appearances/_form.html.haml2
-rw-r--r--app/views/admin/applications/index.html.haml3
-rw-r--r--app/views/admin/dashboard/index.html.haml2
-rw-r--r--app/views/admin/groups/_form.html.haml2
-rw-r--r--app/views/admin/hooks/edit.html.haml4
-rw-r--r--app/views/admin/identities/_identity.html.haml28
-rw-r--r--app/views/admin/identities/index.html.haml28
-rw-r--r--app/views/admin/labels/_label.html.haml2
-rw-r--r--app/views/admin/runners/show.html.haml1
-rw-r--r--app/views/admin/users/_head.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml7
-rw-r--r--app/views/clusters/clusters/_gitlab_integration_form.html.haml2
-rw-r--r--app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml2
-rw-r--r--app/views/dashboard/_groups_head.html.haml2
-rw-r--r--app/views/devise/passwords/new.html.haml2
-rw-r--r--app/views/devise/registrations/new.html.haml1
-rw-r--r--app/views/devise/sessions/_new_base.html.haml5
-rw-r--r--app/views/devise/sessions/_new_base_user_login_label.html.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml5
-rw-r--r--app/views/devise/sessions/two_factor.html.haml4
-rw-r--r--app/views/devise/shared/_footer.html.haml1
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml9
-rw-r--r--app/views/devise/shared/_signup_box.html.haml16
-rw-r--r--app/views/devise/shared/_signup_omniauth_provider_list.haml31
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers.haml5
-rw-r--r--app/views/events/event/_push.html.haml7
-rw-r--r--app/views/groups/_home_panel.html.haml5
-rw-r--r--app/views/groups/_new_group_fields.html.haml45
-rw-r--r--app/views/groups/crm/contacts/index.html.haml2
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml4
-rw-r--r--app/views/groups/milestones/_form.html.haml2
-rw-r--r--app/views/groups/new.html.haml3
-rw-r--r--app/views/groups/runners/show.html.haml14
-rw-r--r--app/views/groups/settings/_advanced.html.haml2
-rw-r--r--app/views/groups/settings/access_tokens/index.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/_auto_devops_form.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/import/_githubish_status.html.haml6
-rw-r--r--app/views/layouts/_google_tag_manager_head.html.haml19
-rw-r--r--app/views/layouts/_snowplow.html.haml7
-rw-r--r--app/views/layouts/component_preview.html.haml5
-rw-r--r--app/views/layouts/devise.html.haml78
-rw-r--r--app/views/layouts/group.html.haml4
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_current_user_dropdown_item.html.haml4
-rw-r--r--app/views/layouts/header/_default.html.haml23
-rw-r--r--app/views/layouts/header/_storage_enforcement_banner.html.haml11
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml6
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/layouts/profile.html.haml3
-rw-r--r--app/views/layouts/project.html.haml4
-rw-r--r--app/views/notify/approved_merge_request_email.text.haml2
-rw-r--r--app/views/notify/attention_requested_merge_request_email.html.haml2
-rw-r--r--app/views/notify/attention_requested_merge_request_email.text.erb1
-rw-r--r--app/views/notify/closed_merge_request_email.text.haml2
-rw-r--r--app/views/notify/member_access_requested_email.html.haml3
-rw-r--r--app/views/notify/member_invite_accepted_email.html.haml9
-rw-r--r--app/views/notify/member_invite_accepted_email.text.erb7
-rw-r--r--app/views/notify/member_invite_declined_email.html.haml12
-rw-r--r--app/views/notify/merge_request_status_email.text.haml2
-rw-r--r--app/views/notify/merge_request_unmergeable_email.html.haml2
-rw-r--r--app/views/notify/merge_request_unmergeable_email.text.haml2
-rw-r--r--app/views/notify/merge_when_pipeline_succeeds_email.text.haml2
-rw-r--r--app/views/notify/merged_merge_request_email.html.haml2
-rw-r--r--app/views/notify/merged_merge_request_email.text.haml2
-rw-r--r--app/views/notify/new_mention_in_merge_request_email.text.erb2
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_merge_request_email.text.erb2
-rw-r--r--app/views/notify/unapproved_merge_request_email.text.haml2
-rw-r--r--app/views/notify/user_auto_banned_email.html.haml9
-rw-r--r--app/views/notify/user_auto_banned_email.text.erb7
-rw-r--r--app/views/profiles/emails/index.html.haml39
-rw-r--r--app/views/profiles/keys/index.html.haml6
-rw-r--r--app/views/profiles/preferences/show.html.haml2
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml27
-rw-r--r--app/views/projects/_commit_button.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml8
-rw-r--r--app/views/projects/_last_push.html.haml6
-rw-r--r--app/views/projects/_new_project_fields.html.haml36
-rw-r--r--app/views/projects/_transfer.html.haml2
-rw-r--r--app/views/projects/_visibility_modal.html.haml4
-rw-r--r--app/views/projects/blob/_editor.html.haml2
-rw-r--r--app/views/projects/branches/_branch.html.haml4
-rw-r--r--app/views/projects/branches/_panel.html.haml13
-rw-r--r--app/views/projects/buttons/_remove_tag.html.haml2
-rw-r--r--app/views/projects/buttons/_star.html.haml4
-rw-r--r--app/views/projects/ci/secure_files/show.html.haml3
-rw-r--r--app/views/projects/commit/_same_user_different_email_signature_badge.html.haml2
-rw-r--r--app/views/projects/commits/_commit_list.html.haml21
-rw-r--r--app/views/projects/commits/_commits.html.haml2
-rw-r--r--app/views/projects/commits/show.html.haml5
-rw-r--r--app/views/projects/compare/show.html.haml8
-rw-r--r--app/views/projects/diffs/_diffs.html.haml2
-rw-r--r--app/views/projects/google_cloud/configuration/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/databases/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/deployments/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/gcp_regions/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/service_accounts/index.html.haml2
-rw-r--r--app/views/projects/graphs/charts.html.haml15
-rw-r--r--app/views/projects/hook_logs/_index.html.haml11
-rw-r--r--app/views/projects/hooks/edit.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml18
-rw-r--r--app/views/projects/issues/_new_branch.html.haml3
-rw-r--r--app/views/projects/issues/_related_issues.html.haml4
-rw-r--r--app/views/projects/issues/_work_item_links.html.haml2
-rw-r--r--app/views/projects/labels/index.html.haml6
-rw-r--r--app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml7
-rw-r--r--app/views/projects/merge_requests/show.html.haml13
-rw-r--r--app/views/projects/milestones/_form.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/pages/_access.html.haml8
-rw-r--r--app/views/projects/pages/_header.html.haml11
-rw-r--r--app/views/projects/pages/_list.html.haml69
-rw-r--r--app/views/projects/pages/_no_domains.html.haml6
-rw-r--r--app/views/projects/pages/_use.html.haml15
-rw-r--r--app/views/projects/pages/_waiting.html.haml13
-rw-r--r--app/views/projects/pages/disabled.html.haml4
-rw-r--r--app/views/projects/pages/new.html.haml7
-rw-r--r--app/views/projects/pages/show.html.haml34
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml2
-rw-r--r--app/views/projects/pipelines/charts.html.haml1
-rw-r--r--app/views/projects/project_templates/_template.html.haml3
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml8
-rw-r--r--app/views/projects/runners/_group_runners.html.haml6
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/projects/settings/integrations/edit.html.haml3
-rw-r--r--app/views/projects/settings/operations/show.html.haml28
-rw-r--r--app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml6
-rw-r--r--app/views/projects/settings/packages_and_registries/show.html.haml14
-rw-r--r--app/views/projects/tags/_edit_release_button.html.haml20
-rw-r--r--app/views/projects/tags/_release_link.html.haml4
-rw-r--r--app/views/projects/tags/_tag.html.haml7
-rw-r--r--app/views/projects/tags/releases/edit.html.haml19
-rw-r--r--app/views/projects/tags/show.html.haml13
-rw-r--r--app/views/projects/triggers/_index.html.haml2
-rw-r--r--app/views/projects/triggers/_trigger.html.haml4
-rw-r--r--app/views/search/_results.html.haml2
-rw-r--r--app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml2
-rw-r--r--app/views/shared/_broadcast_message.html.haml4
-rw-r--r--app/views/shared/_clone_panel.html.haml2
-rw-r--r--app/views/shared/_file_highlight.html.haml10
-rw-r--r--app/views/shared/_group_form.html.haml6
-rw-r--r--app/views/shared/_help_dropdown_forum_link.html.haml2
-rw-r--r--app/views/shared/_label_row.html.haml4
-rw-r--r--app/views/shared/_new_project_item_select.html.haml4
-rw-r--r--app/views/shared/_ref_switcher.html.haml4
-rw-r--r--app/views/shared/_remote_mirror_update_button.html.haml2
-rw-r--r--app/views/shared/_search_settings.html.haml2
-rw-r--r--app/views/shared/_sidebar_toggle_button.html.haml2
-rw-r--r--app/views/shared/access_tokens/_form.html.haml6
-rw-r--r--app/views/shared/access_tokens/_table.html.haml2
-rw-r--r--app/views/shared/admin/_admin_note.html.haml6
-rw-r--r--app/views/shared/blob/_markdown_buttons.html.haml6
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml2
-rw-r--r--app/views/shared/empty_states/_labels.html.haml4
-rw-r--r--app/views/shared/empty_states/_priority_labels.html.haml2
-rw-r--r--app/views/shared/empty_states/_topics.html.haml2
-rw-r--r--app/views/shared/empty_states/_wikis.html.haml2
-rw-r--r--app/views/shared/empty_states/_wikis_layout.html.haml2
-rw-r--r--app/views/shared/groups/_group_name_and_path_fields.html.haml3
-rw-r--r--app/views/shared/groups/_search_form.html.haml2
-rw-r--r--app/views/shared/hook_logs/_index.html.haml (renamed from app/views/admin/hook_logs/_index.html.haml)0
-rw-r--r--app/views/shared/issuable/_assignees.html.haml7
-rw-r--r--app/views/shared/issuable/_form.html.haml8
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_merge_request_assignees.html.haml8
-rw-r--r--app/views/shared/issuable/_merge_request_reviewers.html.haml8
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_reviewers.html.haml7
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml10
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml10
-rw-r--r--app/views/shared/issuable/_sidebar_reviewers.html.haml2
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml4
-rw-r--r--app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml2
-rw-r--r--app/views/shared/issuable/form/_title.html.haml2
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml2
-rw-r--r--app/views/shared/labels/_form.html.haml10
-rw-r--r--app/views/shared/labels/_nav.html.haml4
-rw-r--r--app/views/shared/members/_requests.html.haml15
-rw-r--r--app/views/shared/milestones/_form_dates.html.haml4
-rw-r--r--app/views/shared/milestones/_header.html.haml4
-rw-r--r--app/views/shared/notes/_hints.html.haml9
-rw-r--r--app/views/shared/projects/_search_form.html.haml2
-rw-r--r--app/views/shared/projects/_topics.html.haml12
-rw-r--r--app/views/shared/projects/protected_branches/_update_protected_branch.html.haml2
-rw-r--r--app/views/users/show.html.haml17
-rw-r--r--app/workers/all_queues.yml96
-rw-r--r--app/workers/archive_trace_worker.rb5
-rw-r--r--app/workers/build_finished_worker.rb9
-rw-r--r--app/workers/build_hooks_worker.rb6
-rw-r--r--app/workers/ci/build_finished_worker.rb3
-rw-r--r--app/workers/ci/cancel_pipeline_worker.rb25
-rw-r--r--app/workers/ci/runners/process_runner_version_update_worker.rb25
-rw-r--r--app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb18
-rw-r--r--app/workers/ci/track_failed_build_worker.rb26
-rw-r--r--app/workers/concerns/waitable_worker.rb6
-rw-r--r--app/workers/email_receiver_worker.rb3
-rw-r--r--app/workers/emails_on_push_worker.rb18
-rw-r--r--app/workers/gitlab/github_import/stage/import_issue_events_worker.rb28
-rw-r--r--app/workers/merge_requests/create_approval_event_worker.rb34
-rw-r--r--app/workers/merge_requests/create_approval_note_worker.rb32
-rw-r--r--app/workers/merge_requests/execute_approval_hooks_worker.rb37
-rw-r--r--app/workers/merge_requests/resolve_todos_after_approval_worker.rb32
-rw-r--r--app/workers/new_issue_worker.rb10
-rw-r--r--app/workers/pages/invalidate_domain_cache_worker.rb8
-rw-r--r--app/workers/post_receive.rb1
-rw-r--r--app/workers/project_cache_worker.rb3
-rw-r--r--app/workers/projects/import_export/relation_export_worker.rb26
-rw-r--r--app/workers/service_desk_email_receiver_worker.rb3
-rw-r--r--app/workers/update_project_statistics_worker.rb13
-rw-r--r--app/workers/users/deactivate_dormant_users_worker.rb36
-rw-r--r--app/workers/x509_issuer_crl_check_worker.rb26
-rw-r--r--config/application.rb22
-rw-r--r--config/environments/development.rb10
-rw-r--r--config/environments/production.rb13
-rw-r--r--config/environments/test.rb5
-rw-r--r--config/events/1656554755_issues_edit_g_project_management_issue_added_to_epic.yml20
-rw-r--r--config/events/1656555050_issues_edit_g_project_management_issue_changed_epic.yml20
-rw-r--r--config/events/1656555163_issues_edit_g_project_management_issue_health_status_changed.yml20
-rw-r--r--config/events/1656555272_issues_edit_g_project_management_issue_iteration_changed.yml20
-rw-r--r--config/events/1656555342_issues_edit_g_project_management_issue_removed_from_epic.yml20
-rw-r--r--config/events/1656555426_issues_edit_g_project_management_issue_weight_changed.yml20
-rw-r--r--config/events/1658833247_integrations_class_perform_integrations_action.yml23
-rw-r--r--config/events/1659067369_issue_actions_perform_issue_acitons_.yml25
-rw-r--r--config/events/1659626567_analytics_usage_action_perform_analytics_usage_action.yml25
-rw-r--r--config/feature_categories.yml8
-rw-r--r--config/feature_flags/development/always_async_project_authorizations_refresh.yml8
-rw-r--r--config/feature_flags/development/approval_rules_pagination.yml2
-rw-r--r--config/feature_flags/development/archive_rate_limit.yml2
-rw-r--r--config/feature_flags/development/async_after_approval.yml8
-rw-r--r--config/feature_flags/development/async_commit_diff_files.yml2
-rw-r--r--config/feature_flags/development/auto_ban_user_on_namespace_excessive_projects_download.yml8
-rw-r--r--config/feature_flags/development/batch_load_environment_last_deployment_group.yml8
-rw-r--r--config/feature_flags/development/branch_list_keyset_pagination.yml2
-rw-r--r--config/feature_flags/development/change_response_code_merge_status.yml8
-rw-r--r--config/feature_flags/development/changelog_commits_limitation.yml2
-rw-r--r--config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml2
-rw-r--r--config/feature_flags/development/ci_expand_environment_name_and_url.yml8
-rw-r--r--config/feature_flags/development/ci_fix_rules_if_comparison_with_regexp_variable.yml8
-rw-r--r--config/feature_flags/development/ci_job_artifacts_backlog_work.yml2
-rw-r--r--config/feature_flags/development/ci_minimal_cost_factor_for_gitlab_contributors.yml8
-rw-r--r--config/feature_flags/development/ci_new_public_oss_cost_factor.yml8
-rw-r--r--config/feature_flags/development/ci_retry_downstream_pipeline.yml8
-rw-r--r--config/feature_flags/development/ci_rules_changes_compare.yml8
-rw-r--r--config/feature_flags/development/ci_stop_expanding_file_vars_for_runners.yml8
-rw-r--r--config/feature_flags/development/ci_update_unlocked_job_artifacts.yml2
-rw-r--r--config/feature_flags/development/custom_headers_streaming_audit_events_ui.yml8
-rw-r--r--config/feature_flags/development/datadog_integration_logs_collection.yml2
-rw-r--r--config/feature_flags/development/disabled_mr_discussions_redis_cache.yml8
-rw-r--r--config/feature_flags/development/edit_tag_release_notes_via_release_page.yml8
-rw-r--r--config/feature_flags/development/enforce_auth_checks_on_uploads.yml8
-rw-r--r--config/feature_flags/development/enforce_security_report_validation.yml8
-rw-r--r--config/feature_flags/development/etag_merge_request_diff_batches.yml8
-rw-r--r--config/feature_flags/development/execute_build_hooks_inline.yml8
-rw-r--r--config/feature_flags/development/file_line_blame.yml8
-rw-r--r--config/feature_flags/development/fix_sliding_list_partitioning.yml8
-rw-r--r--config/feature_flags/development/group_level_protected_environment_settings_permission.yml8
-rw-r--r--config/feature_flags/development/group_runner_view_ui.yml8
-rw-r--r--config/feature_flags/development/hard_failure_for_mirrors_without_license.yml8
-rw-r--r--config/feature_flags/development/hash_based_cache_for_protected_branches.yml8
-rw-r--r--config/feature_flags/development/hash_oauth_tokens.yml8
-rw-r--r--config/feature_flags/development/import_export_web_upload_stream.yml8
-rw-r--r--config/feature_flags/development/import_relation_object_persistence.yml8
-rw-r--r--config/feature_flags/development/import_release_authors_from_github.yml8
-rw-r--r--config/feature_flags/development/incident_timeline_events_from_labels.yml8
-rw-r--r--config/feature_flags/development/include_groups_from_group_shares_in_project_transfer_locations.yml8
-rw-r--r--config/feature_flags/development/increase_page_size_exponentially.yml2
-rw-r--r--config/feature_flags/development/incremental_repository_backup.yml8
-rw-r--r--config/feature_flags/development/job_log_jump_to_failures.yml8
-rw-r--r--config/feature_flags/development/job_log_search.yml8
-rw-r--r--config/feature_flags/development/json_wrapper_legacy_mode.yml2
-rw-r--r--config/feature_flags/development/lfk_automatic_partition_creation.yml8
-rw-r--r--config/feature_flags/development/lfk_automatic_partition_dropping.yml8
-rw-r--r--config/feature_flags/development/limit_reviewer_and_assignee_size.yml8
-rw-r--r--config/feature_flags/development/linear_scopes_superset.yml8
-rw-r--r--config/feature_flags/development/mr_review_submit_comment.yml2
-rw-r--r--config/feature_flags/development/new_graphql_keyset_pagination.yml8
-rw-r--r--config/feature_flags/development/only_positive_pagination_values.yml8
-rw-r--r--config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml8
-rw-r--r--config/feature_flags/development/paginated_mr_discussions.yml2
-rw-r--r--config/feature_flags/development/performance_bar_stats.yml8
-rw-r--r--config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml8
-rw-r--r--config/feature_flags/development/product_intelligence_database_event_tracking.yml9
-rw-r--r--config/feature_flags/development/rate_limit_gitlab_shell_by_ip.yml8
-rw-r--r--config/feature_flags/development/rebase_without_ci_ui.yml8
-rw-r--r--config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml8
-rw-r--r--config/feature_flags/development/report_artifact_build_completed_metrics_on_build_completion.yml8
-rw-r--r--config/feature_flags/development/repository_archive_hotlinking_interception.yml2
-rw-r--r--config/feature_flags/development/restructured_mr_widget.yml8
-rw-r--r--config/feature_flags/development/restyle_login_page.yml8
-rw-r--r--config/feature_flags/development/searchable_fork_targets.yml8
-rw-r--r--config/feature_flags/development/simulate_pipeline.yml8
-rw-r--r--config/feature_flags/development/subgroups_approval_rules.yml2
-rw-r--r--config/feature_flags/development/timelog_categories.yml8
-rw-r--r--config/feature_flags/development/track_agent_users_using_ci_tunnel.yml8
-rw-r--r--config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml8
-rw-r--r--config/feature_flags/development/trial_email_validation.yml8
-rw-r--r--config/feature_flags/development/uncached_mr_attention_requests_count.yml8
-rw-r--r--config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml2
-rw-r--r--config/feature_flags/development/update_vuln_identifiers_flag.yml2
-rw-r--r--config/feature_flags/development/use_keyset_aware_user_search_query.yml8
-rw-r--r--config/feature_flags/development/use_pipeline_wizard_for_pages.yml8
-rw-r--r--config/feature_flags/development/use_redis_hll_instrumentation_classes.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids.yml2
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_ancestor_scopes_with_inner_join.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml2
-rw-r--r--config/feature_flags/development/work_items.yml2
-rw-r--r--config/feature_flags/development/work_items_create_from_markdown.yml8
-rw-r--r--config/feature_flags/development/work_items_hierarchy.yml2
-rw-r--r--config/feature_flags/development/workhorse_archive_cache_disabled.yml2
-rw-r--r--config/feature_flags/ops/authenticate_markdown_api.yml8
-rw-r--r--config/feature_flags/ops/batched_migrations_health_status_wal.yml8
-rw-r--r--config/feature_flags/ops/ci_build_dependencies_artifacts_logger.yml8
-rw-r--r--config/feature_flags/ops/database_async_index_destruction.yml8
-rw-r--r--config/feature_flags/ops/github_importer_issue_events_import.yml2
-rw-r--r--config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml8
-rw-r--r--config/feature_flags/ops/performance_bar_stats.yml8
-rw-r--r--config/feature_flags/ops/report_jemalloc_stats.yml8
-rw-r--r--config/feature_flags/ops/skip_rugged_auto_detect.yml8
-rw-r--r--config/gitlab.yml.example2
-rw-r--r--config/initializers/00_deprecations.rb33
-rw-r--r--config/initializers/0_log_deprecations.rb19
-rw-r--r--config/initializers/1_settings.rb11
-rw-r--r--config/initializers/active_record_data_types.rb10
-rw-r--r--config/initializers/database_config.rb6
-rw-r--r--config/initializers/database_query_analyzers.rb8
-rw-r--r--config/initializers/default_url_options.rb4
-rw-r--r--config/initializers/diagnostic_reports.rb11
-rw-r--r--config/initializers/doorkeeper.rb2
-rw-r--r--config/initializers/lookbook.rb14
-rw-r--r--config/initializers/memory_watchdog.rb5
-rw-r--r--config/initializers/rest-client-hostname_override.rb4
-rw-r--r--config/initializers/static_files.rb2
-rw-r--r--config/initializers/truncato.rb6
-rw-r--r--config/initializers/wikicloth_redos_patch.rb2
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb1
-rw-r--r--config/jsdocs.config.js14
-rw-r--r--config/locales/devise.zh-cn.yml70
-rw-r--r--config/metrics/aggregates/code_review.yml72
-rw-r--r--config/metrics/aggregates/common.yml13
-rw-r--r--config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20220615103718_incident_management_timeline_event_total_unique_counts_monthly.yml1
-rw-r--r--config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220715195415_p_ci_templates_security_fortify_fod_sast_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725193059_users_updating_work_item_dates_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210913_i_code_review_merge_request_widget_accessibility_view_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210919_i_code_review_merge_request_widget_accessibility_full_report_clicked_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210926_i_code_review_merge_request_widget_accessibility_expand_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210935_i_code_review_merge_request_widget_accessibility_expand_success_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210942_i_code_review_merge_request_widget_accessibility_expand_warning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220725210949_i_code_review_merge_request_widget_accessibility_expand_failed_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020440_i_code_review_merge_request_widget_code_quality_view_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020446_i_code_review_merge_request_widget_code_quality_full_report_clicked_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020452_i_code_review_merge_request_widget_code_quality_expand_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020457_i_code_review_merge_request_widget_code_quality_expand_success_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020503_i_code_review_merge_request_widget_code_quality_expand_warning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727020509_i_code_review_merge_request_widget_code_quality_expand_failed_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045317_i_code_review_merge_request_widget_terraform_view_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045323_i_code_review_merge_request_widget_terraform_full_report_clicked_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045330_i_code_review_merge_request_widget_terraform_expand_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045336_i_code_review_merge_request_widget_terraform_expand_success_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045342_i_code_review_merge_request_widget_terraform_expand_warning_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220727045349_i_code_review_merge_request_widget_terraform_expand_failed_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20220729001651_agent_users_using_ci_tunnel_monthly.yml26
-rw-r--r--config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20220615103711_incident_management_timeline_event_total_unique_counts_weekly.yml1
-rw-r--r--config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220715195411_p_ci_templates_security_fortify_fod_sast_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725201348_users_updating_work_item_dates_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210831_i_code_review_merge_request_widget_accessibility_view_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210838_i_code_review_merge_request_widget_accessibility_full_report_clicked_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210845_i_code_review_merge_request_widget_accessibility_expand_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210851_i_code_review_merge_request_widget_accessibility_expand_success_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210858_i_code_review_merge_request_widget_accessibility_expand_warning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220725210906_i_code_review_merge_request_widget_accessibility_expand_failed_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020407_i_code_review_merge_request_widget_code_quality_view_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020413_i_code_review_merge_request_widget_code_quality_full_report_clicked_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020419_i_code_review_merge_request_widget_code_quality_expand_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020424_i_code_review_merge_request_widget_code_quality_expand_success_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020429_i_code_review_merge_request_widget_code_quality_expand_warning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727020435_i_code_review_merge_request_widget_code_quality_expand_failed_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045240_i_code_review_merge_request_widget_terraform_view_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045246_i_code_review_merge_request_widget_terraform_full_report_clicked_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045252_i_code_review_merge_request_widget_terraform_expand_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045258_i_code_review_merge_request_widget_terraform_expand_success_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045304_i_code_review_merge_request_widget_terraform_expand_warning_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220727045311_i_code_review_merge_request_widget_terraform_expand_failed_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20220729001644_agent_users_using_ci_tunnel_weekly.yml26
-rw-r--r--config/metrics/counts_all/20210216180752_keys.yml2
-rw-r--r--config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml24
-rw-r--r--config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml24
-rw-r--r--config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml24
-rw-r--r--config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml24
-rw-r--r--config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml24
-rw-r--r--config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml24
-rw-r--r--config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml24
-rw-r--r--config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml24
-rw-r--r--config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml24
-rw-r--r--config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml24
-rw-r--r--config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml24
-rw-r--r--config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml24
-rw-r--r--config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml24
-rw-r--r--config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml24
-rw-r--r--config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml24
-rw-r--r--config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml24
-rw-r--r--config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml24
-rw-r--r--config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml24
-rw-r--r--config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml24
-rw-r--r--config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml24
-rw-r--r--config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml24
-rw-r--r--config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml24
-rw-r--r--config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml24
-rw-r--r--config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml24
-rw-r--r--config/metrics/counts_all/20220802141715_groups_inheriting_pumble_active.yml21
-rw-r--r--config/metrics/counts_all/20220802141715_groups_pumble_active.yml21
-rw-r--r--config/metrics/counts_all/20220802141715_instances_pumble_active.yml21
-rw-r--r--config/metrics/counts_all/20220802141715_projects_inheriting_pumble_active.yml21
-rw-r--r--config/metrics/counts_all/20220802141715_projects_pumble_active.yml21
-rw-r--r--config/routes.rb12
-rw-r--r--config/routes/admin.rb1
-rw-r--r--config/routes/development.rb1
-rw-r--r--config/routes/profile.rb8
-rw-r--r--config/routes/project.rb12
-rw-r--r--config/routes/repository.rb5
-rw-r--r--config/routes/unmatched_project.rb8
-rw-r--r--config/routes/uploads.rb18
-rw-r--r--config/routes/user.rb2
-rw-r--r--config/settings.rb6
-rw-r--r--config/sidekiq_queues.yml20
-rw-r--r--config/webpack.config.js9
-rw-r--r--config/webpack.vendor.config.js1
-rw-r--r--danger/customer_success/Dangerfile3
-rw-r--r--danger/plugins/customer_success.rb9
-rw-r--r--danger/roulette/Dangerfile2
-rw-r--r--data/deprecations/14-0-nfs-fot-git-repository-storage.yml2
-rw-r--r--data/deprecations/14-7-deprecate-artifacts-keyword.yml2
-rw-r--r--data/deprecations/15-2-deprecation-vulnerability-report-state-sort.yml7
-rw-r--r--data/deprecations/15-3-deprecate-redis-5.yml16
-rw-r--r--data/deprecations/15-3-omniauth-cas3.yml16
-rw-r--r--data/deprecations/15-3-omniauth-crowd.yml17
-rw-r--r--data/deprecations/15-3-pipeline_activity_limit.yml33
-rw-r--r--data/deprecations/16-0-security_report_schemas_v14-x-x.yml27
-rw-r--r--data/deprecations/templates/_deprecation_template.md.erb2
-rw-r--r--data/removals/15_0/15-0-removal-artifacts-keyword.yml2
-rw-r--r--data/removals/15_0/removal_manage_repository_push_audit_event.yml (renamed from data/removals/15_0/removal_manage_ repository_push_audit_event.yml)0
-rw-r--r--data/removals/templates/_removal_template.md.erb2
-rw-r--r--data/whats_new/202008180001_12_10.yml40
-rw-r--r--data/whats_new/202008180002_13_0.yml40
-rw-r--r--data/whats_new/202008180003_13_01.yml32
-rw-r--r--data/whats_new/202008210001_13_02.yml32
-rw-r--r--data/whats_new/202009150001_13_03.yml32
-rw-r--r--data/whats_new/202009300001_13_04.yml40
-rw-r--r--data/whats_new/202010230001_13_05.yml48
-rw-r--r--data/whats_new/202011230001_13_06.yml40
-rw-r--r--data/whats_new/202012160001_13_07.yml32
-rw-r--r--data/whats_new/202101140001_13_08.yml56
-rw-r--r--data/whats_new/202102180001_13_09.yml80
-rw-r--r--data/whats_new/202103220001_13_10.yml56
-rw-r--r--data/whats_new/202104220001_13_11.yml72
-rw-r--r--data/whats_new/202105220001_13_12.yml80
-rw-r--r--data/whats_new/202106220001_14_0.yml96
-rw-r--r--data/whats_new/202107220001_14_1.yml80
-rw-r--r--data/whats_new/202108190001_14_02.yml56
-rw-r--r--data/whats_new/202109200001_14_03.yml56
-rw-r--r--data/whats_new/2021102000001_14_04.yml40
-rw-r--r--data/whats_new/2021111800001_14_05.yml48
-rw-r--r--data/whats_new/202112200001_14_06.yml40
-rw-r--r--data/whats_new/202201200001_14_07.yml24
-rw-r--r--data/whats_new/202202210001_14_08.yml48
-rw-r--r--data/whats_new/202203210001_14_09.yml48
-rw-r--r--data/whats_new/202204210001_14_10.yml32
-rw-r--r--data/whats_new/202205220001_15_0.yml64
-rw-r--r--data/whats_new/202206220001_15_1.yml36
-rw-r--r--data/whats_new/202207220001_15_2.yml89
-rw-r--r--data/whats_new/templates/YYYYMMDD0001_XX_YY.yml8
-rw-r--r--db/docs/README.md6
-rw-r--r--db/docs/integrations.yml1
-rw-r--r--db/docs/member_roles.yml10
-rw-r--r--db/docs/ml_candidate_metrics.yml10
-rw-r--r--db/docs/ml_candidate_params.yml10
-rw-r--r--db/docs/ml_candidates.yml10
-rw-r--r--db/docs/ml_experiments.yml10
-rw-r--r--db/docs/namespace_details.yml9
-rw-r--r--db/docs/project_statistics.yml8
-rw-r--r--db/docs/user_project_callouts.yml9
-rw-r--r--db/fixtures/development/14_pipelines.rb2
-rw-r--r--db/fixtures/development/18_abuse_reports.rb2
-rw-r--r--db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb2
-rw-r--r--db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb70
-rw-r--r--db/migrate/20210804150320_create_base_work_item_types.rb6
-rw-r--r--db/migrate/20210831203408_upsert_base_work_item_types.rb6
-rw-r--r--db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb5
-rw-r--r--db/migrate/20220316022505_create_namespace_details.rb21
-rw-r--r--db/migrate/20220406113217_add_inactive_project_deletion_to_application_settings.rb4
-rw-r--r--db/migrate/20220506154054_create_sync_namespace_details_trigger.rb70
-rw-r--r--db/migrate/20220513093614_add_ding_talk_into_application_settings.rb4
-rw-r--r--db/migrate/20220513093615_add_ding_talk_tracker_data.rb2
-rw-r--r--db/migrate/20220524184149_create_sync_project_namespace_details_trigger.rb68
-rw-r--r--db/migrate/20220619212618_add_selective_code_owner_removals_to_project_settings.rb9
-rw-r--r--db/migrate/20220627061008_add_fei_shu_integration.rb4
-rw-r--r--db/migrate/20220707105335_rename_chat_name_service_id_to_integration_id.rb13
-rw-r--r--db/migrate/20220707160707_rename_slack_integration_service_id_to_integration_id.rb13
-rw-r--r--db/migrate/20220707181910_create_member_roles.rb15
-rw-r--r--db/migrate/20220707181920_add_member_role_id_to_members.rb13
-rw-r--r--db/migrate/20220707181930_add_member_roles_relation_to_members.rb19
-rw-r--r--db/migrate/20220707190546_add_plan_limits_max_size_cyclonedx_report_column.rb7
-rw-r--r--db/migrate/20220708150315_add_vulnerabilities_foreign_key_to_vulnerability_merge_request_links.rb4
-rw-r--r--db/migrate/20220708150335_add_merge_requests_foreign_key_to_vulnerability_merge_request_links.rb4
-rw-r--r--db/migrate/20220712131513_rename_issue_tracker_data_service_id_to_integration_id.rb13
-rw-r--r--db/migrate/20220712144843_rename_jira_tracker_data_service_id_to_integration_id.rb13
-rw-r--r--db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb11
-rw-r--r--db/migrate/20220720161816_add_namespace_id_to_vulnerability_reads_table.rb9
-rw-r--r--db/migrate/20220720162123_update_vulnerability_reads_triggers_to_set_namespace_id.rb159
-rw-r--r--db/migrate/20220720210446_add_start_date_to_issues_table.rb9
-rw-r--r--db/migrate/20220722123318_update_delayed_deletion_period.rb27
-rw-r--r--db/migrate/20220722150231_create_function_gitlab_schema_prevent_write.rb32
-rw-r--r--db/migrate/20220722203840_update_lock_writes_function_disabled_via_setting.rb36
-rw-r--r--db/migrate/20220723120039_add_author_id_to_vulnerability_state_transitions.rb7
-rw-r--r--db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb17
-rw-r--r--db/migrate/20220726154012_ensure_sbom_occurrences_is_empty.rb18
-rw-r--r--db/migrate/20220726154013_add_component_id_to_sbom_occurrences.rb17
-rw-r--r--db/migrate/20220726154014_add_index_to_sbom_occurrences_component_id.rb15
-rw-r--r--db/migrate/20220726154015_add_component_foreign_key_to_sbom_occurrences.rb18
-rw-r--r--db/migrate/20220726154016_make_component_version_nullable.rb9
-rw-r--r--db/migrate/20220726230052_remove_tmp_index_project_membership_namespace_id_column.rb20
-rw-r--r--db/migrate/20220728114136_make_ssh_signature_key_nullable.rb9
-rw-r--r--db/migrate/20220729073603_index_personal_access_tokens_on_id_and_created_at.rb15
-rw-r--r--db/migrate/20220802154757_add_deactivate_dormant_user_time_setting.rb6
-rw-r--r--db/migrate/20220803145637_create_user_project_callout.rb19
-rw-r--r--db/migrate/20220803154543_add_project_id_fkey_for_user_project_callout.rb15
-rw-r--r--db/migrate/20220803154758_add_user_id_fkey_for_user_project_callout.rb15
-rw-r--r--db/migrate/20220805154101_add_allow_run_pipelines_in_the_parent_project_setting.rb8
-rw-r--r--db/migrate/20220808133824_add_timestamps_to_project_statistics.rb7
-rw-r--r--db/migrate/20220808190124_add_id_token_to_ci_builds_metadata.rb9
-rw-r--r--db/migrate/20220808194857_remove_description_html_limit.rb15
-rw-r--r--db/migrate/20220811092243_create_ml_experiments.rb18
-rw-r--r--db/migrate/20220811092244_create_ml_candidates.rb16
-rw-r--r--db/migrate/20220811092245_create_ml_candidate_params.rb14
-rw-r--r--db/migrate/20220811092246_create_ml_candidate_metrics.rb16
-rw-r--r--db/migrate/20220811092251_add_ml_candidates_reference_to_experiment.rb15
-rw-r--r--db/migrate/20220811092253_add_ml_experiments_reference_to_project.rb15
-rw-r--r--db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb21
-rw-r--r--db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb10
-rw-r--r--db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb6
-rw-r--r--db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb22
-rw-r--r--db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb2
-rw-r--r--db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb10
-rw-r--r--db/post_migrate/20210816183304_schedule_copy_ci_builds_columns_to_security_scans2.rb26
-rw-r--r--db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb7
-rw-r--r--db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb8
-rw-r--r--db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb6
-rw-r--r--db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb6
-rw-r--r--db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb45
-rw-r--r--db/post_migrate/20211007155221_schedule_populate_status_column_of_security_scans.rb15
-rw-r--r--db/post_migrate/20211208122200_schedule_backfill_ci_namespace_mirrors.rb14
-rw-r--r--db/post_migrate/20211208122201_schedule_backfill_ci_project_mirrors.rb14
-rw-r--r--db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb6
-rw-r--r--db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb6
-rw-r--r--db/post_migrate/20220213103859_remove_integrations_type.rb2
-rw-r--r--db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb2
-rw-r--r--db/post_migrate/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects.rb22
-rw-r--r--db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb2
-rw-r--r--db/post_migrate/20220525201022_add_temporary_index_for_vulnerability_reads_cluster_agent_id_migration.rb16
-rw-r--r--db/post_migrate/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent.rb29
-rw-r--r--db/post_migrate/20220603173103_update_vulnerabilities_project_id_id_index.rb22
-rw-r--r--db/post_migrate/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences.rb20
-rw-r--r--db/post_migrate/20220614185644_update_index_vulnerabilities_project_id_id.rb22
-rw-r--r--db/post_migrate/20220621192541_add_project_id_state_severity_default_branch_index_for_vulnerabilities.rb16
-rw-r--r--db/post_migrate/20220622070547_add_temp_index_for_container_registry_size_migration.rb10
-rw-r--r--db/post_migrate/20220629124942_remove_vulnerability_occurrences_migrated_to_new_structure_column.rb21
-rw-r--r--db/post_migrate/20220707105529_cleanup_chat_name_service_id.rb13
-rw-r--r--db/post_migrate/20220707160921_cleanup_slack_integration_service_id.rb13
-rw-r--r--db/post_migrate/20220712131533_cleanup_issue_tracker_data_service_id.rb13
-rw-r--r--db/post_migrate/20220712144900_cleanup_jira_tracker_data_service_id.rb13
-rw-r--r--db/post_migrate/20220715152108_backfill_project_import_level.rb22
-rw-r--r--db/post_migrate/20220715185348_add_index_on_security_findings_id_and_partition_number.rb15
-rw-r--r--db/post_migrate/20220715185436_add_index_on_security_findings_unique_columns.rb15
-rw-r--r--db/post_migrate/20220715190612_drop_index_on_security_findings_uuid_and_scan_id.rb15
-rw-r--r--db/post_migrate/20220715191629_change_primary_key_of_security_findings_table.rb29
-rw-r--r--db/post_migrate/20220719081542_drop_queued_at_index_from_ci_builds.rb17
-rw-r--r--db/post_migrate/20220719165537_remove_ci_runners_semver_column.rb21
-rw-r--r--db/post_migrate/20220720090354_remove_pending_builds_covering_index_from_ci_builds.rb26
-rw-r--r--db/post_migrate/20220720121421_remove_pat_and_ssh_enforcement_columns_from_application_settings.rb8
-rw-r--r--db/post_migrate/20220720123249_remove_token_column_from_ci_builds.rb9
-rw-r--r--db/post_migrate/20220720171102_add_index_on_vulnerability_reads_namespace_id.rb18
-rw-r--r--db/post_migrate/20220720171801_add_foreign_key_on_vulnerability_reads_namespace_id.rb15
-rw-r--r--db/post_migrate/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects.rb33
-rw-r--r--db/post_migrate/20220721140252_prepare_partial_trigram_indexes_for_issues.rb23
-rw-r--r--db/post_migrate/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb33
-rw-r--r--db/post_migrate/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb35
-rw-r--r--db/post_migrate/20220722145845_schedule_backfilling_the_namespace_id_for_vulnerability_reads.rb23
-rw-r--r--db/post_migrate/20220725150127_update_jira_tracker_data_deployment_type_based_on_url.rb28
-rw-r--r--db/post_migrate/20220726182310_add_user_fk_to_vulnerability_state_transitions.rb20
-rw-r--r--db/post_migrate/20220728134255_update_index_vulnerabilities_common_finder.rb21
-rw-r--r--db/post_migrate/20220729033851_add_partial_legacy_open_source_license_available_index.rb18
-rw-r--r--db/post_migrate/20220729052031_add_index_on_vulnerability_reads_namespace_id_with_report_type.rb18
-rw-r--r--db/post_migrate/20220801144713_add_partial_trigram_index_for_issue_title.rb18
-rw-r--r--db/post_migrate/20220801150028_add_partial_trigram_index_for_issue_description.rb18
-rw-r--r--db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb34
-rw-r--r--db/post_migrate/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics.rb37
-rw-r--r--db/post_migrate/20220802132158_index_on_integration_type_new_id_when_active_and_has_group.rb18
-rw-r--r--db/post_migrate/20220802204737_remove_deactivated_user_highest_role_stats.rb27
-rw-r--r--db/post_migrate/20220803042351_add_tmp_index_todos_attention_request_action.rb18
-rw-r--r--db/post_migrate/20220803042352_cleanup_mr_attention_request_todos.rb24
-rw-r--r--db/post_migrate/20220804235614_add_comment_to_vulnerability_state_transitions.rb10
-rw-r--r--db/post_migrate/20220805001210_add_text_limit_to_vulnerability_state_transitions_comment.rb13
-rw-r--r--db/post_migrate/20220808072054_prepare_index_removal_security_findings.rb13
-rw-r--r--db/post_migrate/20220808131659_remove_ci_namespace_monthly_usages_additional_amount_available_column.rb11
-rw-r--r--db/post_migrate/20220810093742_add_async_tmp_index_job_artifacts_id_and_expire_at.rb23
-rw-r--r--db/schema_migrations/202203160225051
-rw-r--r--db/schema_migrations/202205061540541
-rw-r--r--db/schema_migrations/202205241841491
-rw-r--r--db/schema_migrations/202205252010221
-rw-r--r--db/schema_migrations/202205252211331
-rw-r--r--db/schema_migrations/202206031731031
-rw-r--r--db/schema_migrations/202206070829101
-rw-r--r--db/schema_migrations/202206141856441
-rw-r--r--db/schema_migrations/202206192126181
-rw-r--r--db/schema_migrations/202206211925411
-rw-r--r--db/schema_migrations/202206291249421
-rw-r--r--db/schema_migrations/202207071053351
-rw-r--r--db/schema_migrations/202207071055291
-rw-r--r--db/schema_migrations/202207071607071
-rw-r--r--db/schema_migrations/202207071609211
-rw-r--r--db/schema_migrations/202207071819101
-rw-r--r--db/schema_migrations/202207071819201
-rw-r--r--db/schema_migrations/202207071819301
-rw-r--r--db/schema_migrations/202207071905461
-rw-r--r--db/schema_migrations/202207121315131
-rw-r--r--db/schema_migrations/202207121315331
-rw-r--r--db/schema_migrations/202207121448431
-rw-r--r--db/schema_migrations/202207121449001
-rw-r--r--db/schema_migrations/202207151521081
-rw-r--r--db/schema_migrations/202207151853481
-rw-r--r--db/schema_migrations/202207151854361
-rw-r--r--db/schema_migrations/202207151906121
-rw-r--r--db/schema_migrations/202207151916291
-rw-r--r--db/schema_migrations/202207180839451
-rw-r--r--db/schema_migrations/202207190815421
-rw-r--r--db/schema_migrations/202207191655371
-rw-r--r--db/schema_migrations/202207200903541
-rw-r--r--db/schema_migrations/202207201214211
-rw-r--r--db/schema_migrations/202207201232491
-rw-r--r--db/schema_migrations/202207201618161
-rw-r--r--db/schema_migrations/202207201621231
-rw-r--r--db/schema_migrations/202207201711021
-rw-r--r--db/schema_migrations/202207201718011
-rw-r--r--db/schema_migrations/202207202104461
-rw-r--r--db/schema_migrations/202207210314461
-rw-r--r--db/schema_migrations/202207211402521
-rw-r--r--db/schema_migrations/202207220845431
-rw-r--r--db/schema_migrations/202207221100261
-rw-r--r--db/schema_migrations/202207221233181
-rw-r--r--db/schema_migrations/202207221458451
-rw-r--r--db/schema_migrations/202207221502311
-rw-r--r--db/schema_migrations/202207222038401
-rw-r--r--db/schema_migrations/202207231200391
-rw-r--r--db/schema_migrations/202207251501271
-rw-r--r--db/schema_migrations/202207260255161
-rw-r--r--db/schema_migrations/202207261540121
-rw-r--r--db/schema_migrations/202207261540131
-rw-r--r--db/schema_migrations/202207261540141
-rw-r--r--db/schema_migrations/202207261540151
-rw-r--r--db/schema_migrations/202207261540161
-rw-r--r--db/schema_migrations/202207261823101
-rw-r--r--db/schema_migrations/202207262300521
-rw-r--r--db/schema_migrations/202207281141361
-rw-r--r--db/schema_migrations/202207281342551
-rw-r--r--db/schema_migrations/202207290338511
-rw-r--r--db/schema_migrations/202207290520311
-rw-r--r--db/schema_migrations/202207290736031
-rw-r--r--db/schema_migrations/202208011447131
-rw-r--r--db/schema_migrations/202208011500281
-rw-r--r--db/schema_migrations/202208021121021
-rw-r--r--db/schema_migrations/202208021143511
-rw-r--r--db/schema_migrations/202208021321581
-rw-r--r--db/schema_migrations/202208021547571
-rw-r--r--db/schema_migrations/202208022047371
-rw-r--r--db/schema_migrations/202208030423511
-rw-r--r--db/schema_migrations/202208030423521
-rw-r--r--db/schema_migrations/202208031456371
-rw-r--r--db/schema_migrations/202208031545431
-rw-r--r--db/schema_migrations/202208031547581
-rw-r--r--db/schema_migrations/202208042356141
-rw-r--r--db/schema_migrations/202208050012101
-rw-r--r--db/schema_migrations/202208051541011
-rw-r--r--db/schema_migrations/202208080720541
-rw-r--r--db/schema_migrations/202208081316591
-rw-r--r--db/schema_migrations/202208081338241
-rw-r--r--db/schema_migrations/202208081901241
-rw-r--r--db/schema_migrations/202208081948571
-rw-r--r--db/schema_migrations/202208100937421
-rw-r--r--db/schema_migrations/202208110922431
-rw-r--r--db/schema_migrations/202208110922441
-rw-r--r--db/schema_migrations/202208110922451
-rw-r--r--db/schema_migrations/202208110922461
-rw-r--r--db/schema_migrations/202208110922511
-rw-r--r--db/schema_migrations/202208110922531
-rw-r--r--db/structure.sql478
-rw-r--r--doc/.vale/gitlab/Admin.yml2
-rw-r--r--doc/.vale/gitlab/BadPlurals.yml2
-rw-r--r--doc/.vale/gitlab/EOLWhitespace.yml2
-rw-r--r--doc/.vale/gitlab/FutureTense.yml2
-rw-r--r--doc/.vale/gitlab/HeadingContent.yml2
-rw-r--r--doc/.vale/gitlab/HeadingDepth.yml13
-rw-r--r--doc/.vale/gitlab/MultiLineLinks.yml14
-rw-r--r--doc/.vale/gitlab/OutdatedVersions.yml2
-rw-r--r--doc/.vale/gitlab/Possessive.yml2
-rw-r--r--doc/.vale/gitlab/Uppercase.yml1
-rw-r--r--doc/.vale/gitlab/VersionText.yml18
-rw-r--r--doc/.vale/gitlab/VersionTextSingleLine.yml13
-rw-r--r--doc/administration/application_settings_cache.md2
-rw-r--r--doc/administration/audit_event_streaming.md344
-rw-r--r--doc/administration/audit_events.md8
-rw-r--r--doc/administration/audit_reports.md2
-rw-r--r--doc/administration/auditor_users.md6
-rw-r--r--doc/administration/auth/crowd.md22
-rw-r--r--doc/administration/auth/ldap/img/multi_login.pngbin12689 -> 0 bytes
-rw-r--r--doc/administration/auth/ldap/index.md141
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md20
-rw-r--r--doc/administration/auth/ldap/ldap_synchronization.md2
-rw-r--r--doc/administration/auth/oidc.md10
-rw-r--r--doc/administration/compliance.md2
-rw-r--r--doc/administration/external_pipeline_validation.md6
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md4
-rw-r--r--doc/administration/geo/disaster_recovery/index.md4
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md2
-rw-r--r--doc/administration/geo/index.md6
-rw-r--r--doc/administration/geo/replication/container_registry.md167
-rw-r--r--doc/administration/geo/replication/datatypes.md12
-rw-r--r--doc/administration/geo/replication/disable_geo.md2
-rw-r--r--doc/administration/geo/replication/docker_registry.md140
-rw-r--r--doc/administration/geo/replication/faq.md6
-rw-r--r--doc/administration/geo/replication/troubleshooting.md68
-rw-r--r--doc/administration/geo/replication/tuning.md2
-rw-r--r--doc/administration/geo/replication/upgrading_the_geo_sites.md15
-rw-r--r--doc/administration/geo/replication/version_specific_upgrades.md22
-rw-r--r--doc/administration/geo/secondary_proxy/index.md5
-rw-r--r--doc/administration/geo/setup/database.md224
-rw-r--r--doc/administration/geo/setup/index.md2
-rw-r--r--doc/administration/get_started.md6
-rw-r--r--doc/administration/gitaly/configure_gitaly.md156
-rw-r--r--doc/administration/gitaly/index.md72
-rw-r--r--doc/administration/gitaly/monitoring.md4
-rw-r--r--doc/administration/gitaly/praefect.md28
-rw-r--r--doc/administration/gitaly/recovery.md4
-rw-r--r--doc/administration/gitaly/troubleshooting.md21
-rw-r--r--doc/administration/incoming_email.md3
-rw-r--r--doc/administration/index.md5
-rw-r--r--doc/administration/instance_limits.md4
-rw-r--r--doc/administration/integration/mailgun.md6
-rw-r--r--doc/administration/job_artifacts.md2
-rw-r--r--doc/administration/libravatar.md112
-rw-r--r--doc/administration/logs.md1181
-rw-r--r--doc/administration/logs/img/database-query-dialog_v14_3.png (renamed from doc/administration/troubleshooting/img/database-query-dialog_v14_3.png)bin72494 -> 72494 bytes
-rw-r--r--doc/administration/logs/img/network_monitor_xid.png (renamed from doc/administration/troubleshooting/img/network_monitor_xid.png)bin89959 -> 89959 bytes
-rw-r--r--doc/administration/logs/img/obtaining-a-session-cookie-for-request_v14_3.png (renamed from doc/administration/troubleshooting/img/obtaining-a-session-cookie-for-request_v14_3.png)bin113452 -> 113452 bytes
-rw-r--r--doc/administration/logs/img/paste-request-id-into-progress-bar_v14_3.png (renamed from doc/administration/troubleshooting/img/paste-request-id-into-progress-bar_v14_3.png)bin6495 -> 6495 bytes
-rw-r--r--doc/administration/logs/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png (renamed from doc/administration/troubleshooting/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png)bin30026 -> 30026 bytes
-rw-r--r--doc/administration/logs/img/view-pg-details_v14_3.png (renamed from doc/administration/troubleshooting/img/view-pg-details_v14_3.png)bin6656 -> 6656 bytes
-rw-r--r--doc/administration/logs/index.md1182
-rw-r--r--doc/administration/logs/log_parsing.md316
-rw-r--r--doc/administration/logs/tracing_correlation_id.md202
-rw-r--r--doc/administration/maintenance_mode/index.md2
-rw-r--r--doc/administration/monitoring/ip_allowlist.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md16
-rw-r--r--doc/administration/monitoring/prometheus/index.md14
-rw-r--r--doc/administration/monitoring/prometheus/web_exporter.md4
-rw-r--r--doc/administration/nfs.md22
-rw-r--r--doc/administration/object_storage.md20
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md365
-rw-r--r--doc/administration/operations/extra_sidekiq_routing.md196
-rw-r--r--doc/administration/operations/index.md7
-rw-r--r--doc/administration/operations/puma.md4
-rw-r--r--doc/administration/operations/rails_console.md12
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md86
-rw-r--r--doc/administration/operations/ssh_certificates.md15
-rw-r--r--doc/administration/package_information/deprecation_policy.md2
-rw-r--r--doc/administration/package_information/index.md4
-rw-r--r--doc/administration/package_information/postgresql_versions.md7
-rw-r--r--doc/administration/package_information/supported_os.md8
-rw-r--r--doc/administration/packages/container_registry.md12
-rw-r--r--doc/administration/pages/index.md29
-rw-r--r--doc/administration/pages/source.md3
-rw-r--r--doc/administration/postgresql/database_load_balancing.md2
-rw-r--r--doc/administration/pseudonymizer.md3
-rw-r--r--doc/administration/raketasks/maintenance.md2
-rw-r--r--doc/administration/raketasks/project_import_export.md41
-rw-r--r--doc/administration/redis/replication_and_failover.md12
-rw-r--r--doc/administration/redis/replication_and_failover_external.md2
-rw-r--r--doc/administration/redis/troubleshooting.md2
-rw-r--r--doc/administration/reference_architectures/10k_users.md17
-rw-r--r--doc/administration/reference_architectures/25k_users.md17
-rw-r--r--doc/administration/reference_architectures/2k_users.md30
-rw-r--r--doc/administration/reference_architectures/3k_users.md11
-rw-r--r--doc/administration/reference_architectures/50k_users.md17
-rw-r--r--doc/administration/reference_architectures/5k_users.md11
-rw-r--r--doc/administration/reference_architectures/index.md14
-rw-r--r--doc/administration/reference_architectures/troubleshooting.md355
-rw-r--r--doc/administration/repository_checks.md60
-rw-r--r--doc/administration/restart_gitlab.md4
-rw-r--r--doc/administration/sidekiq.md388
-rw-r--r--doc/administration/sidekiq/extra_sidekiq_processes.md362
-rw-r--r--doc/administration/sidekiq/extra_sidekiq_routing.md180
-rw-r--r--doc/administration/sidekiq/img/sidekiq_flamegraph.png (renamed from doc/administration/troubleshooting/img/sidekiq_flamegraph.png)bin54473 -> 54473 bytes
-rw-r--r--doc/administration/sidekiq/index.md403
-rw-r--r--doc/administration/sidekiq/sidekiq_health_check.md58
-rw-r--r--doc/administration/sidekiq/sidekiq_job_migration.md40
-rw-r--r--doc/administration/sidekiq/sidekiq_memory_killer.md82
-rw-r--r--doc/administration/sidekiq/sidekiq_troubleshooting.md381
-rw-r--r--doc/administration/sidekiq_health_check.md61
-rw-r--r--doc/administration/terraform_state.md6
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md407
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md168
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md210
-rw-r--r--doc/administration/troubleshooting/img/Okta-SAMLsetup.pngbin18920 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/Okta-advancedsettings.pngbin15614 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/Okta-attributes.pngbin5540 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/Okta-linkscert.pngbin58832 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/okta_admin_panel_v13_9.pngbin49319 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/img/okta_saml_settings.pngbin25470 -> 0 bytes
-rw-r--r--doc/administration/troubleshooting/index.md7
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md93
-rw-r--r--doc/administration/troubleshooting/log_parsing.md319
-rw-r--r--doc/administration/troubleshooting/postgresql.md2
-rw-r--r--doc/administration/troubleshooting/sidekiq.md398
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md205
-rw-r--r--doc/administration/uploads.md6
-rw-r--r--doc/api/appearance.md2
-rw-r--r--doc/api/audit_events.md9
-rw-r--r--doc/api/bulk_imports.md9
-rw-r--r--doc/api/deployments.md31
-rw-r--r--doc/api/discussions.md32
-rw-r--r--doc/api/features.md10
-rw-r--r--doc/api/geo_nodes.md26
-rw-r--r--doc/api/graphql/index.md4
-rw-r--r--doc/api/graphql/reference/index.md818
-rw-r--r--doc/api/group_protected_environments.md2
-rw-r--r--doc/api/groups.md170
-rw-r--r--doc/api/index.md10
-rw-r--r--doc/api/integrations.md66
-rw-r--r--doc/api/issues.md18
-rw-r--r--doc/api/job_artifacts.md48
-rw-r--r--doc/api/jobs.md14
-rw-r--r--doc/api/lint.md3
-rw-r--r--doc/api/markdown.md24
-rw-r--r--doc/api/merge_request_approvals.md88
-rw-r--r--doc/api/merge_requests.md64
-rw-r--r--doc/api/namespaces.md2
-rw-r--r--doc/api/notes.md22
-rw-r--r--doc/api/oauth2.md13
-rw-r--r--doc/api/packages.md2
-rw-r--r--doc/api/packages/conan.md4
-rw-r--r--doc/api/packages/terraform-modules.md230
-rw-r--r--doc/api/personal_access_tokens.md7
-rw-r--r--doc/api/pipeline_schedules.md54
-rw-r--r--doc/api/pipelines.md2
-rw-r--r--doc/api/project_import_export.md25
-rw-r--r--doc/api/project_templates.md2
-rw-r--r--doc/api/projects.md16
-rw-r--r--doc/api/releases/index.md15
-rw-r--r--doc/api/releases/links.md18
-rw-r--r--doc/api/repositories.md11
-rw-r--r--doc/api/resource_iteration_events.md2
-rw-r--r--doc/api/resource_milestone_events.md2
-rw-r--r--doc/api/resource_state_events.md4
-rw-r--r--doc/api/resource_weight_events.md2
-rw-r--r--doc/api/settings.md2
-rw-r--r--doc/api/topics.md11
-rw-r--r--doc/api/users.md72
-rw-r--r--doc/api/version.md4
-rw-r--r--doc/api/vulnerabilities.md10
-rw-r--r--doc/api/vulnerability_findings.md2
-rw-r--r--doc/architecture/blueprints/ci_data_decay/index.md8
-rw-r--r--doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md16
-rw-r--r--doc/architecture/blueprints/ci_scale/index.md26
-rw-r--r--doc/architecture/blueprints/cloud_native_build_logs/index.md17
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md13
-rw-r--r--doc/architecture/blueprints/consolidating_groups_and_projects/index.md2
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md14
-rw-r--r--doc/architecture/blueprints/database_scaling/size-limits.md4
-rw-r--r--doc/architecture/blueprints/database_testing/index.md2
-rw-r--r--doc/architecture/blueprints/feature_flags_development/index.md6
-rw-r--r--doc/architecture/blueprints/graphql_api/index.md11
-rw-r--r--doc/architecture/blueprints/object_storage/index.md27
-rw-r--r--doc/architecture/blueprints/runner_scaling/index.md8
-rw-r--r--doc/ci/cloud_services/aws/index.md6
-rw-r--r--doc/ci/cloud_services/google_cloud/index.md2
-rw-r--r--doc/ci/docker/using_docker_build.md54
-rw-r--r--doc/ci/docker/using_kaniko.md9
-rw-r--r--doc/ci/environments/index.md4
-rw-r--r--doc/ci/environments/protected_environments.md9
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md24
-rw-r--r--doc/ci/git_submodules.md6
-rw-r--r--doc/ci/interactive_web_terminal/index.md15
-rw-r--r--doc/ci/jobs/ci_job_token.md1
-rw-r--r--doc/ci/jobs/job_control.md25
-rw-r--r--doc/ci/large_repositories/index.md3
-rw-r--r--doc/ci/migration/circleci.md2
-rw-r--r--doc/ci/pipeline_editor/index.md13
-rw-r--r--doc/ci/pipelines/cicd_minutes.md26
-rw-r--r--doc/ci/pipelines/img/pipeline_mini_graph_v15_0.pngbin0 -> 6061 bytes
-rw-r--r--doc/ci/pipelines/merge_request_pipelines.md9
-rw-r--r--doc/ci/pipelines/merge_trains.md5
-rw-r--r--doc/ci/pipelines/multi_project_pipelines.md122
-rw-r--r--doc/ci/pipelines/settings.md36
-rw-r--r--doc/ci/runners/configure_runners.md27
-rw-r--r--doc/ci/runners/img/build_isolation.pngbin0 -> 35301 bytes
-rw-r--r--doc/ci/runners/index.md24
-rw-r--r--doc/ci/runners/runners_scope.md67
-rw-r--r--doc/ci/runners/saas/linux_saas_runner.md2
-rw-r--r--doc/ci/runners/saas/windows_saas_runner.md3
-rw-r--r--doc/ci/secrets/index.md4
-rw-r--r--doc/ci/secure_files/index.md2
-rw-r--r--doc/ci/testing/load_performance_testing.md2
-rw-r--r--doc/ci/testing/unit_test_report_examples.md2
-rw-r--r--doc/ci/testing/unit_test_reports.md42
-rw-r--r--doc/ci/variables/predefined_variables.md5
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md15
-rw-r--r--doc/ci/yaml/artifacts_reports.md24
-rw-r--r--doc/ci/yaml/includes.md14
-rw-r--r--doc/ci/yaml/index.md148
-rw-r--r--doc/ci/yaml/script.md24
-rw-r--r--doc/development/adding_database_indexes.md317
-rw-r--r--doc/development/adding_service_component.md4
-rw-r--r--doc/development/api_graphql_styleguide.md162
-rw-r--r--doc/development/api_styleguide.md16
-rw-r--r--doc/development/application_limits.md3
-rw-r--r--doc/development/application_slis/index.md13
-rw-r--r--doc/development/application_slis/rails_request_apdex.md3
-rw-r--r--doc/development/architecture.md2
-rw-r--r--doc/development/audit_event_guide/index.md23
-rw-r--r--doc/development/auto_devops.md4
-rw-r--r--doc/development/backend/create_source_code_be/index.md2
-rw-r--r--doc/development/backend/ruby_style_guide.md2
-rw-r--r--doc/development/build_test_package.md4
-rw-r--r--doc/development/cached_queries.md2
-rw-r--r--doc/development/caching.md8
-rw-r--r--doc/development/changelog.md4
-rw-r--r--doc/development/chatops_on_gitlabcom.md2
-rw-r--r--doc/development/code_intelligence/index.md4
-rw-r--r--doc/development/code_review.md116
-rw-r--r--doc/development/contributing/design.md6
-rw-r--r--doc/development/contributing/index.md14
-rw-r--r--doc/development/contributing/issue_workflow.md4
-rw-r--r--doc/development/contributing/merge_request_workflow.md152
-rw-r--r--doc/development/creating_enums.md157
-rw-r--r--doc/development/database/add_foreign_key_to_existing_column.md4
-rw-r--r--doc/development/database/adding_database_indexes.md410
-rw-r--r--doc/development/database/avoiding_downtime_in_migrations.md40
-rw-r--r--doc/development/database/background_migrations.md6
-rw-r--r--doc/development/database/batched_background_migrations.md198
-rw-r--r--doc/development/database/ci_mirrored_tables.md156
-rw-r--r--doc/development/database/client_side_connection_pool.md13
-rw-r--r--doc/development/database/creating_enums.md154
-rw-r--r--doc/development/database/database_debugging.md177
-rw-r--r--doc/development/database/database_dictionary.md51
-rw-r--r--doc/development/database/database_lab.md2
-rw-r--r--doc/development/database/database_query_comments.md62
-rw-r--r--doc/development/database/database_reviewer_guidelines.md10
-rw-r--r--doc/development/database/db_dump.md56
-rw-r--r--doc/development/database/filtering_by_label.md179
-rw-r--r--doc/development/database/foreign_keys.md199
-rw-r--r--doc/development/database/hash_indexes.md26
-rw-r--r--doc/development/database/index.md52
-rw-r--r--doc/development/database/insert_into_tables_in_batches.md196
-rw-r--r--doc/development/database/iterating_tables_in_batches.md598
-rw-r--r--doc/development/database/loose_foreign_keys.md11
-rw-r--r--doc/development/database/multiple_databases.md9
-rw-r--r--doc/development/database/namespaces_storage_statistics.md193
-rw-r--r--doc/development/database/not_null_constraints.md4
-rw-r--r--doc/development/database/ordering_table_columns.md152
-rw-r--r--doc/development/database/pagination_guidelines.md2
-rw-r--r--doc/development/database/pagination_performance_guidelines.md10
-rw-r--r--doc/development/database/polymorphic_associations.md152
-rw-r--r--doc/development/database/post_deployment_migrations.md4
-rw-r--r--doc/development/database/query_count_limits.md70
-rw-r--r--doc/development/database/query_performance.md74
-rw-r--r--doc/development/database/query_recorder.md145
-rw-r--r--doc/development/database/rename_database_tables.md6
-rw-r--r--doc/development/database/serializing_data.md90
-rw-r--r--doc/development/database/sha1_as_binary.md42
-rw-r--r--doc/development/database/single_table_inheritance.md63
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md7
-rw-r--r--doc/development/database/swapping_tables.md51
-rw-r--r--doc/development/database/transaction_guidelines.md2
-rw-r--r--doc/development/database/understanding_explain_plans.md829
-rw-r--r--doc/development/database/verifying_database_capabilities.md38
-rw-r--r--doc/development/database_debugging.md180
-rw-r--r--doc/development/database_query_comments.md65
-rw-r--r--doc/development/database_review.md23
-rw-r--r--doc/development/db_dump.md59
-rw-r--r--doc/development/deprecation_guidelines/index.md22
-rw-r--r--doc/development/distributed_tracing.md16
-rw-r--r--doc/development/documentation/restful_api_styleguide.md5
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md22
-rw-r--r--doc/development/documentation/site_architecture/folder_structure.md2
-rw-r--r--doc/development/documentation/site_architecture/global_nav.md36
-rw-r--r--doc/development/documentation/site_architecture/index.md257
-rw-r--r--doc/development/documentation/structure.md61
-rw-r--r--doc/development/documentation/styleguide/index.md117
-rw-r--r--doc/development/documentation/styleguide/word_list.md20
-rw-r--r--doc/development/documentation/testing.md68
-rw-r--r--doc/development/documentation/versions.md6
-rw-r--r--doc/development/ee_features.md339
-rw-r--r--doc/development/elasticsearch.md34
-rw-r--r--doc/development/emails.md9
-rw-r--r--doc/development/event_store.md11
-rw-r--r--doc/development/fe_guide/accessibility.md2
-rw-r--r--doc/development/fe_guide/architecture.md4
-rw-r--r--doc/development/fe_guide/content_editor.md1
-rw-r--r--doc/development/fe_guide/design_anti_patterns.md6
-rw-r--r--doc/development/fe_guide/development_process.md8
-rw-r--r--doc/development/fe_guide/frontend_faq.md6
-rw-r--r--doc/development/fe_guide/graphql.md68
-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/merge_request_widget_extensions.md437
-rw-r--r--doc/development/fe_guide/performance.md25
-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/javascript.md3
-rw-r--r--doc/development/fe_guide/style/scss.md2
-rw-r--r--doc/development/fe_guide/style/vue.md18
-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.md45
-rw-r--r--doc/development/fe_guide/vue.md10
-rw-r--r--doc/development/fe_guide/vuex.md6
-rw-r--r--doc/development/fe_guide/widgets.md4
-rw-r--r--doc/development/feature_categorization/index.md6
-rw-r--r--doc/development/feature_development.md4
-rw-r--r--doc/development/feature_flags/controls.md2
-rw-r--r--doc/development/feature_flags/index.md20
-rw-r--r--doc/development/features_inside_dot_gitlab.md4
-rw-r--r--doc/development/filtering_by_label.md182
-rw-r--r--doc/development/fips_compliance.md105
-rw-r--r--doc/development/foreign_keys.md203
-rw-r--r--doc/development/gemfile.md17
-rw-r--r--doc/development/geo.md2
-rw-r--r--doc/development/geo/proxying.md4
-rw-r--r--doc/development/git_object_deduplication.md13
-rw-r--r--doc/development/gitaly.md3
-rw-r--r--doc/development/github_importer.md4
-rw-r--r--doc/development/gitlab_flavored_markdown/specification_guide/index.md49
-rw-r--r--doc/development/go_guide/dependencies.md6
-rw-r--r--doc/development/go_guide/index.md71
-rw-r--r--doc/development/gotchas.md3
-rw-r--r--doc/development/hash_indexes.md29
-rw-r--r--doc/development/i18n/externalization.md12
-rw-r--r--doc/development/i18n/proofreader.md2
-rw-r--r--doc/development/image_scaling.md2
-rw-r--r--doc/development/import_export.md4
-rw-r--r--doc/development/import_project.md2
-rw-r--r--doc/development/index.md4
-rw-r--r--doc/development/insert_into_tables_in_batches.md199
-rw-r--r--doc/development/integrations/index.md2
-rw-r--r--doc/development/integrations/secure.md17
-rw-r--r--doc/development/internal_api/index.md51
-rw-r--r--doc/development/issue_types.md6
-rw-r--r--doc/development/iterating_tables_in_batches.md601
-rw-r--r--doc/development/jh_features_review.md3
-rw-r--r--doc/development/kubernetes.md2
-rw-r--r--doc/development/lfs.md9
-rw-r--r--doc/development/licensed_feature_availability.md75
-rw-r--r--doc/development/logging.md19
-rw-r--r--doc/development/merge_request_concepts/index.md31
-rw-r--r--doc/development/merge_request_concepts/widget_extensions.md11
-rw-r--r--doc/development/merge_request_performance_guidelines.md9
-rw-r--r--doc/development/migration_style_guide.md56
-rw-r--r--doc/development/module_with_instance_variables.md6
-rw-r--r--doc/development/multi_version_compatibility.md2
-rw-r--r--doc/development/namespaces_storage_statistics.md196
-rw-r--r--doc/development/new_fe_guide/development/accessibility.md55
-rw-r--r--doc/development/new_fe_guide/development/components.md30
-rw-r--r--doc/development/new_fe_guide/development/index.md26
-rw-r--r--doc/development/new_fe_guide/development/performance.md25
-rw-r--r--doc/development/new_fe_guide/index.md25
-rw-r--r--doc/development/new_fe_guide/modules/dirty_submit.md31
-rw-r--r--doc/development/new_fe_guide/modules/index.md18
-rw-r--r--doc/development/new_fe_guide/modules/widget_extensions.md358
-rw-r--r--doc/development/new_fe_guide/tips.md38
-rw-r--r--doc/development/ordering_table_columns.md155
-rw-r--r--doc/development/pages/index.md48
-rw-r--r--doc/development/performance.md10
-rw-r--r--doc/development/permissions.md2
-rw-r--r--doc/development/pipelines.md14
-rw-r--r--doc/development/policies.md3
-rw-r--r--doc/development/polymorphic_associations.md155
-rw-r--r--doc/development/query_count_limits.md73
-rw-r--r--doc/development/query_performance.md77
-rw-r--r--doc/development/query_recorder.md148
-rw-r--r--doc/development/rails_update.md4
-rw-r--r--doc/development/real_time.md4
-rw-r--r--doc/development/redis/new_redis_instance.md6
-rw-r--r--doc/development/reusing_abstractions.md55
-rw-r--r--doc/development/routing.md4
-rw-r--r--doc/development/scalability.md39
-rw-r--r--doc/development/secure_coding_guidelines.md2
-rw-r--r--doc/development/serializing_data.md93
-rw-r--r--doc/development/service_measurement.md2
-rw-r--r--doc/development/service_ping/implement.md27
-rw-r--r--doc/development/service_ping/index.md6
-rw-r--r--doc/development/service_ping/metrics_dictionary.md6
-rw-r--r--doc/development/service_ping/metrics_instrumentation.md12
-rw-r--r--doc/development/service_ping/performance_indicator_metrics.md5
-rw-r--r--doc/development/service_ping/review_guidelines.md6
-rw-r--r--doc/development/service_ping/usage_data.md2
-rw-r--r--doc/development/sha1_as_binary.md45
-rw-r--r--doc/development/shell_commands.md2
-rw-r--r--doc/development/sidekiq/compatibility_across_updates.md13
-rw-r--r--doc/development/sidekiq/idempotent_jobs.md5
-rw-r--r--doc/development/sidekiq/index.md16
-rw-r--r--doc/development/sidekiq/logging.md5
-rw-r--r--doc/development/sidekiq/worker_attributes.md6
-rw-r--r--doc/development/single_table_inheritance.md66
-rw-r--r--doc/development/snowplow/implementation.md2
-rw-r--r--doc/development/snowplow/index.md7
-rw-r--r--doc/development/snowplow/infrastructure.md6
-rw-r--r--doc/development/snowplow/review_guidelines.md2
-rw-r--r--doc/development/sql.md5
-rw-r--r--doc/development/stage_group_observability/dashboards/stage_group_dashboard.md2
-rw-r--r--doc/development/swapping_tables.md54
-rw-r--r--doc/development/testing_guide/best_practices.md11
-rw-r--r--doc/development/testing_guide/contract/consumer_tests.md113
-rw-r--r--doc/development/testing_guide/contract/index.md14
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md4
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md4
-rw-r--r--doc/development/testing_guide/end_to_end/index.md23
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md1
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md83
-rw-r--r--doc/development/testing_guide/frontend_testing.md9
-rw-r--r--doc/development/testing_guide/index.md4
-rw-r--r--doc/development/testing_guide/review_apps.md2
-rw-r--r--doc/development/testing_guide/testing_levels.md4
-rw-r--r--doc/development/testing_guide/testing_migrations_guide.md4
-rw-r--r--doc/development/understanding_explain_plans.md832
-rw-r--r--doc/development/uploads/working_with_uploads.md375
-rw-r--r--doc/development/utilities.md18
-rw-r--r--doc/development/verifying_database_capabilities.md41
-rw-r--r--doc/development/windows.md3
-rw-r--r--doc/development/work_items.md4
-rw-r--r--doc/development/workhorse/configuration.md8
-rw-r--r--doc/development/workhorse/gitlab_features.md2
-rw-r--r--doc/development/workhorse/index.md8
-rw-r--r--doc/downgrade_ee_to_ce/index.md2
-rw-r--r--doc/gitlab-basics/start-using-git.md2
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md13
-rw-r--r--doc/install/azure/index.md4
-rw-r--r--doc/install/docker.md6
-rw-r--r--doc/install/installation.md23
-rw-r--r--doc/install/next_steps.md2
-rw-r--r--doc/install/requirements.md6
-rw-r--r--doc/integration/advanced_search/elasticsearch.md33
-rw-r--r--doc/integration/advanced_search/elasticsearch_troubleshooting.md256
-rw-r--r--doc/integration/azure.md43
-rw-r--r--doc/integration/cas.md6
-rw-r--r--doc/integration/datadog.md3
-rw-r--r--doc/integration/github.md22
-rw-r--r--doc/integration/gitlab.md8
-rw-r--r--doc/integration/img/jenkins_gitlab_service.pngbin19235 -> 0 bytes
-rw-r--r--doc/integration/img/jenkins_project.pngbin42275 -> 0 bytes
-rw-r--r--doc/integration/img/omniauth_providers_v_14_6.pngbin12165 -> 0 bytes
-rw-r--r--doc/integration/index.md1
-rw-r--r--doc/integration/jenkins_deprecated.md62
-rw-r--r--doc/integration/jira/dvcs.md2
-rw-r--r--doc/integration/mattermost/index.md88
-rw-r--r--doc/integration/omniauth.md72
-rw-r--r--doc/integration/saml.md13
-rw-r--r--doc/integration/security_partners/index.md4
-rw-r--r--doc/integration/twitter.md2
-rw-r--r--doc/operations/incident_management/img/linked_resources_list_v15_3.pngbin0 -> 12838 bytes
-rw-r--r--doc/operations/incident_management/img/timeline_events_v15_1.pngbin36994 -> 18226 bytes
-rw-r--r--doc/operations/incident_management/incidents.md17
-rw-r--r--doc/operations/incident_management/linked_resources.md66
-rw-r--r--doc/operations/metrics/embed_grafana.md6
-rw-r--r--doc/policy/alpha-beta-support.md2
-rw-r--r--doc/policy/maintenance.md4
-rw-r--r--doc/raketasks/backup_gitlab.md5
-rw-r--r--doc/raketasks/backup_restore.md14
-rw-r--r--doc/raketasks/sidekiq_job_migration.md43
-rw-r--r--doc/raketasks/spdx.md2
-rw-r--r--doc/security/crime_vulnerability.md4
-rw-r--r--doc/security/index.md6
-rw-r--r--doc/security/information_exclusivity.md4
-rw-r--r--doc/security/reset_user_password.md10
-rw-r--r--doc/security/two_factor_authentication.md15
-rw-r--r--doc/security/user_file_uploads.md48
-rw-r--r--doc/security/webhooks.md2
-rw-r--r--doc/subscriptions/bronze_starter.md14
-rw-r--r--doc/subscriptions/gitlab_com/index.md16
-rw-r--r--doc/subscriptions/index.md4
-rw-r--r--doc/subscriptions/self_managed/index.md14
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md2
-rw-r--r--doc/topics/autodevops/customize.md2
-rw-r--r--doc/topics/autodevops/index.md5
-rw-r--r--doc/topics/autodevops/stages.md6
-rw-r--r--doc/topics/autodevops/troubleshooting.md6
-rw-r--r--doc/topics/autodevops/upgrading_auto_deploy_dependencies.md5
-rw-r--r--doc/topics/autodevops/upgrading_postgresql.md3
-rw-r--r--doc/topics/git/lfs/index.md14
-rw-r--r--doc/topics/git/terminology.md2
-rw-r--r--doc/topics/git/troubleshooting_git.md6
-rw-r--r--doc/topics/offline/quick_start_guide.md3
-rw-r--r--doc/topics/release_your_application.md10
-rw-r--r--doc/topics/set_up_organization.md1
-rw-r--r--doc/tutorials/make_your_first_git_commit.md4
-rw-r--r--doc/tutorials/move_personal_project_to_a_group.md2
-rw-r--r--doc/update/deprecations.md261
-rw-r--r--doc/update/index.md43
-rw-r--r--doc/update/package/convert_to_ee.md6
-rw-r--r--doc/update/package/index.md14
-rw-r--r--doc/update/plan_your_upgrade.md13
-rw-r--r--doc/update/removals.md212
-rw-r--r--doc/update/upgrading_from_ce_to_ee.md3
-rw-r--r--doc/update/upgrading_from_source.md4
-rw-r--r--doc/update/zero_downtime.md6
-rw-r--r--doc/user/admin_area/broadcast_messages.md3
-rw-r--r--doc/user/admin_area/index.md22
-rw-r--r--doc/user/admin_area/merge_requests_approvals.md2
-rw-r--r--doc/user/admin_area/monitoring/background_migrations.md44
-rw-r--r--doc/user/admin_area/review_abuse_reports.md4
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.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.md8
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md7
-rw-r--r--doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.pngbin35894 -> 0 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.pngbin21953 -> 0 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_trendline_v14_4.pngbin13089 -> 0 bytes
-rw-r--r--doc/user/analytics/index.md23
-rw-r--r--doc/user/analytics/merge_request_analytics.md4
-rw-r--r--doc/user/analytics/productivity_analytics.md122
-rw-r--r--doc/user/application_security/api_fuzzing/index.md14
-rw-r--r--doc/user/application_security/container_scanning/index.md151
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md4
-rw-r--r--doc/user/application_security/dast/browser_based.md53
-rw-r--r--doc/user/application_security/dast/checks/16.7.md4
-rw-r--r--doc/user/application_security/dast/checks/601.1.md2
-rw-r--r--doc/user/application_security/dast/checks/798.45.md26
-rw-r--r--doc/user/application_security/dast/checks/798.51.md26
-rw-r--r--doc/user/application_security/dast/checks/798.71.md26
-rw-r--r--doc/user/application_security/dast/checks/798.73.md26
-rw-r--r--doc/user/application_security/dast/checks/798.76.md26
-rw-r--r--doc/user/application_security/dast/checks/798.79.md26
-rw-r--r--doc/user/application_security/dast/checks/798.85.md26
-rw-r--r--doc/user/application_security/dast/checks/index.md7
-rw-r--r--doc/user/application_security/dast/index.md16
-rw-r--r--doc/user/application_security/dast_api/index.md12
-rw-r--r--doc/user/application_security/dependency_scanning/index.md64
-rw-r--r--doc/user/application_security/get-started-security.md34
-rw-r--r--doc/user/application_security/iac_scanning/index.md27
-rw-r--r--doc/user/application_security/index.md21
-rw-r--r--doc/user/application_security/policies/index.md10
-rw-r--r--doc/user/application_security/sast/analyzers.md2
-rw-r--r--doc/user/application_security/sast/customize_rulesets.md381
-rw-r--r--doc/user/application_security/sast/img/sast_vulnerability_page_fp_detection_v15_2.pngbin0 -> 23202 bytes
-rw-r--r--doc/user/application_security/sast/index.md408
-rw-r--r--doc/user/application_security/secret_detection/index.md10
-rw-r--r--doc/user/application_security/vulnerabilities/index.md4
-rw-r--r--doc/user/application_security/vulnerability_report/pipeline.md6
-rw-r--r--doc/user/asciidoc.md4
-rw-r--r--doc/user/clusters/agent/ci_cd_workflow.md6
-rw-r--r--doc/user/clusters/agent/gitops.md3
-rw-r--r--doc/user/clusters/agent/install/index.md2
-rw-r--r--doc/user/clusters/agent/vulnerabilities.md3
-rw-r--r--doc/user/clusters/cost_management.md2
-rw-r--r--doc/user/clusters/environments.md4
-rw-r--r--doc/user/clusters/management_project.md3
-rw-r--r--doc/user/clusters/management_project_template.md13
-rw-r--r--doc/user/compliance/compliance_report/index.md37
-rw-r--r--doc/user/compliance/license_compliance/index.md6
-rw-r--r--doc/user/crm/index.md2
-rw-r--r--doc/user/discussions/index.md30
-rw-r--r--doc/user/feature_highlight.md18
-rw-r--r--doc/user/free_user_limit.md4
-rw-r--r--doc/user/gitlab_com/index.md24
-rw-r--r--doc/user/group/access_and_permissions.md260
-rw-r--r--doc/user/group/custom_project_templates.md2
-rw-r--r--doc/user/group/index.md847
-rw-r--r--doc/user/group/iterations/index.md68
-rw-r--r--doc/user/group/manage.md570
-rw-r--r--doc/user/group/saml_sso/example_saml_config.md211
-rw-r--r--doc/user/group/saml_sso/group_sync.md12
-rw-r--r--doc/user/group/saml_sso/img/AzureAD-basic_SAML.png (renamed from doc/administration/troubleshooting/img/AzureAD-basic_SAML.png)bin101427 -> 101427 bytes
-rw-r--r--doc/user/group/saml_sso/img/AzureAD-claims.png (renamed from doc/administration/troubleshooting/img/AzureAD-claims.png)bin13625 -> 13625 bytes
-rw-r--r--doc/user/group/saml_sso/img/AzureAD-scim_attribute_mapping.png (renamed from doc/administration/troubleshooting/img/AzureAD-scim_attribute_mapping.png)bin11981 -> 11981 bytes
-rw-r--r--doc/user/group/saml_sso/img/AzureAD-scim_provisioning.png (renamed from doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png)bin80244 -> 80244 bytes
-rw-r--r--doc/user/group/saml_sso/img/GoogleWorkspace-basic-SAML_v14_10.png (renamed from doc/administration/troubleshooting/img/GoogleWorkspace-basic-SAML_v14_10.png)bin39027 -> 39027 bytes
-rw-r--r--doc/user/group/saml_sso/img/GoogleWorkspace-claims_v14_10.png (renamed from doc/administration/troubleshooting/img/GoogleWorkspace-claims_v14_10.png)bin30571 -> 30571 bytes
-rw-r--r--doc/user/group/saml_sso/img/GoogleWorkspace-linkscert_v14_10.png (renamed from doc/administration/troubleshooting/img/GoogleWorkspace-linkscert_v14_10.png)bin50479 -> 50479 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-GroupAttribute.pngbin0 -> 7744 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-GroupSAML.pngbin0 -> 23681 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-SM.pngbin0 -> 23386 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-advancedsettings.pngbin0 -> 18912 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-attributes.pngbin0 -> 13687 bytes
-rw-r--r--doc/user/group/saml_sso/img/Okta-linkscert.pngbin0 -> 55321 bytes
-rw-r--r--doc/user/group/saml_sso/img/OneLogin-SSOsettings.png (renamed from doc/administration/troubleshooting/img/OneLogin-SSOsettings.png)bin25397 -> 25397 bytes
-rw-r--r--doc/user/group/saml_sso/img/OneLogin-app_details.png (renamed from doc/administration/troubleshooting/img/OneLogin-app_details.png)bin18305 -> 18305 bytes
-rw-r--r--doc/user/group/saml_sso/img/OneLogin-parameters.png (renamed from doc/administration/troubleshooting/img/OneLogin-parameters.png)bin5051 -> 5051 bytes
-rw-r--r--doc/user/group/saml_sso/img/OneLogin-userAdd.png (renamed from doc/administration/troubleshooting/img/OneLogin-userAdd.png)bin10021 -> 10021 bytes
-rw-r--r--doc/user/group/saml_sso/img/azure_configure_group_claim.png (renamed from doc/administration/troubleshooting/img/azure_configure_group_claim.png)bin14833 -> 14833 bytes
-rw-r--r--doc/user/group/saml_sso/img/okta_saml_settings.pngbin0 -> 21280 bytes
-rw-r--r--doc/user/group/saml_sso/img/okta_setting_username.png (renamed from doc/administration/troubleshooting/img/okta_setting_username.png)bin17785 -> 17785 bytes
-rw-r--r--doc/user/group/saml_sso/index.md12
-rw-r--r--doc/user/group/saml_sso/scim_setup.md6
-rw-r--r--doc/user/group/settings/group_access_tokens.md3
-rw-r--r--doc/user/group/subgroups/index.md26
-rw-r--r--doc/user/img/completed_tasks_v13_3.pngbin14835 -> 0 bytes
-rw-r--r--doc/user/img/completed_tasks_v15_3.pngbin0 -> 19133 bytes
-rw-r--r--doc/user/infrastructure/clusters/connect/new_civo_cluster.md2
-rw-r--r--doc/user/infrastructure/clusters/connect/new_eks_cluster.md3
-rw-r--r--doc/user/infrastructure/clusters/deploy/inventory_object.md5
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md21
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md30
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md73
-rw-r--r--doc/user/infrastructure/clusters/manage/management_project_applications/vault.md2
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md147
-rw-r--r--doc/user/infrastructure/iac/troubleshooting.md2
-rw-r--r--doc/user/markdown.md58
-rw-r--r--doc/user/namespace/index.md21
-rw-r--r--doc/user/packages/composer_repository/index.md2
-rw-r--r--doc/user/packages/container_registry/index.md8
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md23
-rw-r--r--doc/user/packages/dependency_proxy/index.md22
-rw-r--r--doc/user/packages/generic_packages/index.md1
-rw-r--r--doc/user/packages/helm_repository/index.md4
-rw-r--r--doc/user/packages/npm_registry/index.md4
-rw-r--r--doc/user/packages/package_registry/index.md7
-rw-r--r--doc/user/packages/package_registry/reduce_package_registry_storage.md2
-rw-r--r--doc/user/packages/terraform_module_registry/index.md4
-rw-r--r--doc/user/permissions.md28
-rw-r--r--doc/user/profile/account/delete_account.md2
-rw-r--r--doc/user/profile/account/two_factor_authentication.md21
-rw-r--r--doc/user/profile/index.md4
-rw-r--r--doc/user/profile/notifications.md6
-rw-r--r--doc/user/project/canary_deployments.md6
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md6
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md24
-rw-r--r--doc/user/project/clusters/deploy_to_cluster.md2
-rw-r--r--doc/user/project/code_owners.md62
-rw-r--r--doc/user/project/deploy_boards.md4
-rw-r--r--doc/user/project/deploy_keys/index.md6
-rw-r--r--doc/user/project/description_templates.md2
-rw-r--r--doc/user/project/git_attributes.md4
-rw-r--r--doc/user/project/img/code_owners_invite_members_v13_4.pngbin55189 -> 0 bytes
-rw-r--r--doc/user/project/img/code_owners_members_v13_4.pngbin46547 -> 0 bytes
-rw-r--r--doc/user/project/import/clearcase.md4
-rw-r--r--doc/user/project/import/github.md32
-rw-r--r--doc/user/project/insights/index.md248
-rw-r--r--doc/user/project/integrations/harbor.md50
-rw-r--r--doc/user/project/integrations/index.md1
-rw-r--r--doc/user/project/integrations/pumble.md39
-rw-r--r--doc/user/project/integrations/slack.md4
-rw-r--r--doc/user/project/integrations/webhook_events.md29
-rw-r--r--doc/user/project/integrations/webhooks.md10
-rw-r--r--doc/user/project/issue_board.md17
-rw-r--r--doc/user/project/issues/design_management.md2
-rw-r--r--doc/user/project/issues/img/related_issue_block_v12_8.pngbin35817 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/related_issue_block_v15_3.pngbin0 -> 28910 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_add_v12_8.pngbin32939 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_add_v15_3.pngbin0 -> 24947 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_remove_v12_8.pngbin10708 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/related_issues_remove_v15_3.pngbin0 -> 12113 bytes
-rw-r--r--doc/user/project/issues/issue_weight.md1
-rw-r--r--doc/user/project/issues/managing_issues.md6
-rw-r--r--doc/user/project/issues/related_issues.md6
-rw-r--r--doc/user/project/labels.md5
-rw-r--r--doc/user/project/members/index.md23
-rw-r--r--doc/user/project/members/share_project_with_groups.md26
-rw-r--r--doc/user/project/merge_requests/approvals/img/scoped_to_protected_branch_v13_10.pngbin12376 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/approvals/index.md2
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md24
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md35
-rw-r--r--doc/user/project/merge_requests/csv_export.md19
-rw-r--r--doc/user/project/merge_requests/img/license_compliance_widget_v15_3.pngbin0 -> 24463 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_widget_passed_v14_0.pngbin12850 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/status_checks_widget_pending_v14_0.pngbin12735 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/index.md13
-rw-r--r--doc/user/project/merge_requests/methods/index.md8
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v13_11.pngbin32192 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v15_3.pngbin0 -> 32927 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_resolve.pngbin63623 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_resolve2.pngbin62012 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_start.pngbin80651 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_review_unresolve.pngbin78767 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/img/mr_summary_comment_v15_3.pngbin0 -> 49186 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/index.md38
-rw-r--r--doc/user/project/merge_requests/status_checks.md24
-rw-r--r--doc/user/project/merge_requests/widgets.md6
-rw-r--r--doc/user/project/milestones/index.md8
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md1
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md8
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--doc/user/project/pages/img/remove_pages.pngbin12954 -> 0 bytes
-rw-r--r--doc/user/project/pages/img/remove_pages_v15_3.pngbin0 -> 4432 bytes
-rw-r--r--doc/user/project/pages/introduction.md5
-rw-r--r--doc/user/project/pages/pages_access_control.md2
-rw-r--r--doc/user/project/push_options.md8
-rw-r--r--doc/user/project/quick_actions.md1
-rw-r--r--doc/user/project/releases/index.md423
-rw-r--r--doc/user/project/releases/release_cicd_examples.md100
-rw-r--r--doc/user/project/releases/release_cli.md30
-rw-r--r--doc/user/project/releases/release_fields.md274
-rw-r--r--doc/user/project/repository/branches/default.md2
-rw-r--r--doc/user/project/repository/forking_workflow.md2
-rw-r--r--doc/user/project/repository/index.md2
-rw-r--r--doc/user/project/repository/managing_large_repositories.md4
-rw-r--r--doc/user/project/repository/mirror/index.md11
-rw-r--r--doc/user/project/repository/mirror/pull.md5
-rw-r--r--doc/user/project/repository/push_rules.md2
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md10
-rw-r--r--doc/user/project/service_desk.md3
-rw-r--r--doc/user/project/settings/index.md11
-rw-r--r--doc/user/project/web_ide/index.md11
-rw-r--r--doc/user/project/wiki/group.md2
-rw-r--r--doc/user/project/wiki/index.md39
-rw-r--r--doc/user/project/working_with_projects.md8
-rw-r--r--doc/user/ssh.md6
-rw-r--r--doc/user/tasks.md18
-rw-r--r--doc/user/upgrade_email_bypass.md2
-rw-r--r--doc/user/usage_quotas.md33
-rw-r--r--doc/user/workspace/index.md4
-rw-r--r--glfm_specification/example_snapshots/examples_index.yml27
-rw-r--r--glfm_specification/example_snapshots/html.yml281
-rw-r--r--glfm_specification/example_snapshots/markdown.yml38
-rw-r--r--glfm_specification/example_snapshots/prosemirror_json.yml1928
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt185
-rw-r--r--glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml12
-rw-r--r--glfm_specification/output/spec.txt185
-rw-r--r--jest.config.base.js8
-rw-r--r--lib/api/api.rb7
-rw-r--r--lib/api/api_guard.rb4
-rw-r--r--lib/api/applications.rb6
-rw-r--r--lib/api/broadcast_messages.rb14
-rw-r--r--lib/api/bulk_imports.rb29
-rw-r--r--lib/api/ci/helpers/runner.rb6
-rw-r--r--lib/api/ci/job_artifacts.rb38
-rw-r--r--lib/api/ci/jobs.rb4
-rw-r--r--lib/api/ci/pipeline_schedules.rb10
-rw-r--r--lib/api/ci/pipelines.rb22
-rw-r--r--lib/api/ci/runner.rb12
-rw-r--r--lib/api/ci/runners.rb12
-rw-r--r--lib/api/commits.rb8
-rw-r--r--lib/api/concerns/packages/debian_distribution_endpoints.rb12
-rw-r--r--lib/api/debian_project_packages.rb8
-rw-r--r--lib/api/deploy_tokens.rb14
-rw-r--r--lib/api/deployments.rb27
-rw-r--r--lib/api/entities/bulk_imports/entity.rb3
-rw-r--r--lib/api/entities/group_detail.rb3
-rw-r--r--lib/api/entities/merge_request_reviewer.rb12
-rw-r--r--lib/api/entities/note.rb1
-rw-r--r--lib/api/entities/project.rb31
-rw-r--r--lib/api/feature_flags.rb6
-rw-r--r--lib/api/features.rb9
-rw-r--r--lib/api/group_labels.rb31
-rw-r--r--lib/api/group_packages.rb34
-rw-r--r--lib/api/groups.rb7
-rw-r--r--lib/api/helm_packages.rb2
-rw-r--r--lib/api/helpers.rb23
-rw-r--r--lib/api/helpers/groups_helpers.rb4
-rw-r--r--lib/api/helpers/integrations_helpers.rb23
-rw-r--r--lib/api/helpers/merge_requests_helpers.rb6
-rw-r--r--lib/api/helpers/projects_helpers.rb2
-rw-r--r--lib/api/helpers/related_resources_helpers.rb4
-rw-r--r--lib/api/helpers/snippets_helpers.rb7
-rw-r--r--lib/api/internal/base.rb10
-rw-r--r--lib/api/internal/error_tracking.rb2
-rw-r--r--lib/api/internal/kubernetes.rb60
-rw-r--r--lib/api/issue_links.rb2
-rw-r--r--lib/api/issues.rb22
-rw-r--r--lib/api/labels.rb8
-rw-r--r--lib/api/markdown.rb4
-rw-r--r--lib/api/maven_packages.rb19
-rw-r--r--lib/api/members.rb6
-rw-r--r--lib/api/merge_requests.rb33
-rw-r--r--lib/api/metrics/dashboard/annotations.rb6
-rw-r--r--lib/api/metrics/user_starred_dashboards.rb4
-rw-r--r--lib/api/milestone_responses.rb6
-rw-r--r--lib/api/notes.rb7
-rw-r--r--lib/api/pages_domains.rb4
-rw-r--r--lib/api/pagination_params.rb20
-rw-r--r--lib/api/personal_access_tokens.rb11
-rw-r--r--lib/api/project_packages.rb7
-rw-r--r--lib/api/project_templates.rb2
-rw-r--r--lib/api/projects.rb6
-rw-r--r--lib/api/protected_branches.rb4
-rw-r--r--lib/api/releases.rb14
-rw-r--r--lib/api/repositories.rb10
-rw-r--r--lib/api/rubygem_packages.rb2
-rw-r--r--lib/api/search.rb25
-rw-r--r--lib/api/sidekiq_metrics.rb14
-rw-r--r--lib/api/support/git_access_actor.rb4
-rw-r--r--lib/api/topics.rb1
-rw-r--r--lib/api/unleash.rb4
-rw-r--r--lib/api/user_counts.rb8
-rw-r--r--lib/api/users.rb6
-rw-r--r--lib/backup/database.rb20
-rw-r--r--lib/backup/gitaly_backup.rb13
-rw-r--r--lib/backup/manager.rb44
-rw-r--r--lib/banzai/filter/custom_emoji_filter.rb4
-rw-r--r--lib/banzai/filter/references/abstract_reference_filter.rb8
-rw-r--r--lib/banzai/filter/references/label_reference_filter.rb4
-rw-r--r--lib/banzai/filter/references/milestone_reference_filter.rb4
-rw-r--r--lib/banzai/filter/task_list_filter.rb86
-rw-r--r--lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb2
-rw-r--r--lib/banzai/reference_redactor.rb4
-rw-r--r--lib/bitbucket/representation/base.rb2
-rw-r--r--lib/bitbucket_server/representation/base.rb2
-rw-r--r--lib/bulk_imports/clients/http.rb19
-rw-r--r--lib/bulk_imports/groups/transformers/group_attributes_transformer.rb2
-rw-r--r--lib/bulk_imports/pipeline.rb2
-rw-r--r--lib/bulk_imports/projects/transformers/project_attributes_transformer.rb4
-rw-r--r--lib/container_registry/gitlab_api_client.rb23
-rw-r--r--lib/container_registry/tag.rb15
-rw-r--r--lib/feature.rb6
-rw-r--r--lib/gitlab/alert_management/payload/base.rb12
-rw-r--r--lib/gitlab/application_context.rb19
-rw-r--r--lib/gitlab/application_rate_limiter.rb11
-rw-r--r--lib/gitlab/audit/auditor.rb175
-rw-r--r--lib/gitlab/audit/deploy_key_author.rb15
-rw-r--r--lib/gitlab/audit/null_author.rb2
-rw-r--r--lib/gitlab/audit/null_target.rb19
-rw-r--r--lib/gitlab/audit/target.rb21
-rw-r--r--lib/gitlab/auth.rb4
-rw-r--r--lib/gitlab/auth/auth_finders.rb2
-rw-r--r--lib/gitlab/auth/ip_rate_limiter.rb8
-rw-r--r--lib/gitlab/auth/o_auth/auth_hash.rb35
-rw-r--r--lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb77
-rw-r--r--lib/gitlab/background_migration/backfill_ci_project_mirrors.rb52
-rw-r--r--lib/gitlab/background_migration/backfill_ci_runner_semver.rb31
-rw-r--r--lib/gitlab/background_migration/backfill_group_features.rb8
-rw-r--r--lib/gitlab/background_migration/backfill_integrations_type_new.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads.rb36
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_project_import_level.rb35
-rw-r--r--lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent.rb30
-rw-r--r--lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb2
-rw-r--r--lib/gitlab/background_migration/batched_migration_job.rb69
-rw-r--r--lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb2
-rw-r--r--lib/gitlab/background_migration/batching_strategies/backfill_vulnerability_reads_cluster_agent_batching_strategy.rb19
-rw-r--r--lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb2
-rw-r--r--lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb32
-rw-r--r--lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb2
-rw-r--r--lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb44
-rw-r--r--lib/gitlab/background_migration/copy_column_using_background_migration_job.rb4
-rw-r--r--lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb36
-rw-r--r--lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects.rb36
-rw-r--r--lib/gitlab/background_migration/drop_invalid_security_findings.rb2
-rw-r--r--lib/gitlab/background_migration/encrypt_static_object_token.rb2
-rw-r--r--lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb2
-rw-r--r--lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb2
-rw-r--r--lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb16
-rw-r--r--lib/gitlab/background_migration/populate_status_column_of_security_scans.rb13
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_reads.rb2
-rw-r--r--lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb4
-rw-r--r--lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb88
-rw-r--r--lib/gitlab/background_migration/update_timelogs_null_spent_at.rb2
-rw-r--r--lib/gitlab/background_task.rb95
-rw-r--r--lib/gitlab/batch_pop_queueing.rb2
-rw-r--r--lib/gitlab/cache/request_cache.rb2
-rw-r--r--lib/gitlab/chat_name_token.rb4
-rw-r--r--lib/gitlab/ci/artifacts/logger.rb64
-rw-r--r--lib/gitlab/ci/artifacts/metrics.rb7
-rw-r--r--lib/gitlab/ci/build/artifacts/adapters/zip_stream.rb61
-rw-r--r--lib/gitlab/ci/build/releaser.rb2
-rw-r--r--lib/gitlab/ci/build/rules.rb4
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause.rb1
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/changes.rb34
-rw-r--r--lib/gitlab/ci/config.rb4
-rw-r--r--lib/gitlab/ci/config/entry/image.rb46
-rw-r--r--lib/gitlab/ci/config/entry/imageable.rb61
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb2
-rw-r--r--lib/gitlab/ci/config/entry/release.rb5
-rw-r--r--lib/gitlab/ci/config/entry/reports.rb3
-rw-r--r--lib/gitlab/ci/config/entry/rules/rule/changes.rb3
-rw-r--r--lib/gitlab/ci/config/entry/service.rb49
-rw-r--r--lib/gitlab/ci/config/entry/variables.rb16
-rw-r--r--lib/gitlab/ci/jwt.rb2
-rw-r--r--lib/gitlab/ci/parsers.rb3
-rw-r--r--lib/gitlab/ci/parsers/sbom/cyclonedx.rb79
-rw-r--r--lib/gitlab/ci/parsers/sbom/cyclonedx_properties.rb112
-rw-r--r--lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb49
-rw-r--r--lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator.rb37
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schema_validator.rb136
-rw-r--r--lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb8
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb3
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/matches.rb8
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb8
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb12
-rw-r--r--lib/gitlab/ci/pipeline/seed/environment.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/stage.rb2
-rw-r--r--lib/gitlab/ci/reports/coverage_report_generator.rb2
-rw-r--r--lib/gitlab/ci/reports/sbom/component.rb19
-rw-r--r--lib/gitlab/ci/reports/sbom/report.rb34
-rw-r--r--lib/gitlab/ci/reports/sbom/reports.rb21
-rw-r--r--lib/gitlab/ci/reports/sbom/source.rb19
-rw-r--r--lib/gitlab/ci/runner_releases.rb5
-rw-r--r--lib/gitlab/ci/runner_upgrade_check.rb88
-rw-r--r--lib/gitlab/ci/status/bridge/common.rb6
-rw-r--r--lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Dart.gitlab-ci.yml85
-rw-r--r--lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml2
-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/CF-Provision.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml9
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml32
-rw-r--r--lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Secret-Detection.latest.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml100
-rw-r--r--lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Security/Fortify-FoD-sast.gitlab-ci.yml52
-rw-r--r--lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/trace/chunked_io.rb2
-rw-r--r--lib/gitlab/ci/variables/collection.rb35
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb4
-rw-r--r--lib/gitlab/ci/variables/helpers.rb28
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb16
-rw-r--r--lib/gitlab/cleanup/project_uploads.rb2
-rw-r--r--lib/gitlab/contributions_calendar.rb2
-rw-r--r--lib/gitlab/current_settings.rb6
-rw-r--r--lib/gitlab/daemon.rb1
-rw-r--r--lib/gitlab/data_builder/issuable.rb4
-rw-r--r--lib/gitlab/database/async_indexes.rb8
-rw-r--r--lib/gitlab/database/async_indexes/index_destructor.rb66
-rw-r--r--lib/gitlab/database/async_indexes/migration_helpers.rb32
-rw-r--r--lib/gitlab/database/async_indexes/postgres_async_index.rb3
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb4
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb8
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_runner.rb4
-rw-r--r--lib/gitlab/database/background_migration/batched_migration_wrapper.rb3
-rw-r--r--lib/gitlab/database/background_migration/health_status.rb30
-rw-r--r--lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb74
-rw-r--r--lib/gitlab/database/background_migration/health_status/signals.rb8
-rw-r--r--lib/gitlab/database/bulk_update.rb2
-rw-r--r--lib/gitlab/database/dynamic_model_helpers.rb2
-rw-r--r--lib/gitlab/database/gitlab_schemas.yml7
-rw-r--r--lib/gitlab/database/lock_writes_manager.rb80
-rw-r--r--lib/gitlab/database/migration_helpers.rb13
-rw-r--r--lib/gitlab/database/migrations/background_migration_helpers.rb2
-rw-r--r--lib/gitlab/database/migrations/base_background_runner.rb2
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb7
-rw-r--r--lib/gitlab/database/partitioning/sliding_list_strategy.rb1
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb2
-rw-r--r--lib/gitlab/database/postgres_hll/buckets.rb4
-rw-r--r--lib/gitlab/database/reindexing.rb1
-rw-r--r--lib/gitlab/database/reindexing/reindex_concurrently.rb6
-rw-r--r--lib/gitlab/database/with_lock_retries.rb2
-rw-r--r--lib/gitlab/dependency_linker/base_linker.rb4
-rw-r--r--lib/gitlab/dependency_linker/cargo_toml_linker.rb6
-rw-r--r--lib/gitlab/dependency_linker/composer_json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/godeps_json_linker.rb6
-rw-r--r--lib/gitlab/dependency_linker/json_linker.rb6
-rw-r--r--lib/gitlab/dependency_linker/podspec_linker.rb4
-rw-r--r--lib/gitlab/diff/file.rb8
-rw-r--r--lib/gitlab/diff/highlight_cache.rb12
-rw-r--r--lib/gitlab/diff/parser.rb6
-rw-r--r--lib/gitlab/diff/rendered/notebook/diff_file.rb2
-rw-r--r--lib/gitlab/diff/rendered/notebook/diff_file_helper.rb4
-rw-r--r--lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512.rb28
-rw-r--r--lib/gitlab/email/message/in_product_marketing/helper.rb2
-rw-r--r--lib/gitlab/error_tracking/error_repository/open_api_strategy.rb21
-rw-r--r--lib/gitlab/event_store.rb11
-rw-r--r--lib/gitlab/exclusive_lease_helpers/sleeping_lock.rb6
-rw-r--r--lib/gitlab/form_builders/gitlab_ui_form_builder.rb18
-rw-r--r--lib/gitlab/git.rb4
-rw-r--r--lib/gitlab/git/remote_repository.rb72
-rw-r--r--lib/gitlab/git/repository.rb15
-rw-r--r--lib/gitlab/git/rugged_impl/use_rugged.rb1
-rw-r--r--lib/gitlab/git_access.rb1
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb26
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb10
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb12
-rw-r--r--lib/gitlab/github_import/client.rb4
-rw-r--r--lib/gitlab/github_import/importer/events/base_importer.rb36
-rw-r--r--lib/gitlab/github_import/importer/events/changed_assignee.rb52
-rw-r--r--lib/gitlab/github_import/importer/events/changed_label.rb14
-rw-r--r--lib/gitlab/github_import/importer/events/changed_milestone.rb39
-rw-r--r--lib/gitlab/github_import/importer/events/closed.rb18
-rw-r--r--lib/gitlab/github_import/importer/events/cross_referenced.rb23
-rw-r--r--lib/gitlab/github_import/importer/events/renamed.rb14
-rw-r--r--lib/gitlab/github_import/importer/events/reopened.rb18
-rw-r--r--lib/gitlab/github_import/importer/issue_event_importer.rb46
-rw-r--r--lib/gitlab/github_import/importer/issue_events_importer.rb35
-rw-r--r--lib/gitlab/github_import/importer/issue_importer.rb3
-rw-r--r--lib/gitlab/github_import/importer/issues_importer.rb12
-rw-r--r--lib/gitlab/github_import/importer/releases_importer.rb9
-rw-r--r--lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb5
-rw-r--r--lib/gitlab/github_import/issuable_finder.rb2
-rw-r--r--lib/gitlab/github_import/parallel_scheduling.rb29
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb2
-rw-r--r--lib/gitlab/github_import/representation/issue.rb7
-rw-r--r--lib/gitlab/github_import/representation/issue_event.rb83
-rw-r--r--lib/gitlab/github_import/representation/lfs_object.rb2
-rw-r--r--lib/gitlab/github_import/representation/note.rb2
-rw-r--r--lib/gitlab/github_import/representation/pull_request.rb2
-rw-r--r--lib/gitlab/github_import/representation/pull_request_review.rb2
-rw-r--r--lib/gitlab/github_import/representation/user.rb2
-rw-r--r--lib/gitlab/github_import/user_finder.rb14
-rw-r--r--lib/gitlab/global_id/deprecations.rb39
-rw-r--r--lib/gitlab/grape_logging/loggers/token_logger.rb17
-rw-r--r--lib/gitlab/graphql/deprecation.rb20
-rw-r--r--lib/gitlab/graphql/deprecations_base.rb48
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb62
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb55
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb39
-rw-r--r--lib/gitlab/graphql/pagination/keyset/connection.rb97
-rw-r--r--lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb98
-rw-r--r--lib/gitlab/graphql/pagination/keyset/order_info.rb124
-rw-r--r--lib/gitlab/graphql/pagination/keyset/query_builder.rb73
-rw-r--r--lib/gitlab/graphql/type_name_deprecations.rb27
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb3
-rw-r--r--lib/gitlab/http_io.rb2
-rw-r--r--lib/gitlab/i18n.rb20
-rw-r--r--lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb19
-rw-r--r--lib/gitlab/import_export/after_export_strategies/move_file_strategy.rb1
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb28
-rw-r--r--lib/gitlab/import_export/after_export_strategy_builder.rb6
-rw-r--r--lib/gitlab/import_export/base/relation_factory.rb15
-rw-r--r--lib/gitlab/import_export/base/relation_object_saver.rb2
-rw-r--r--lib/gitlab/import_export/decompressed_archive_size_validator.rb20
-rw-r--r--lib/gitlab/import_export/group/relation_tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/json/streaming_serializer.rb25
-rw-r--r--lib/gitlab/import_export/log_util.rb19
-rw-r--r--lib/gitlab/import_export/project/import_export.yml26
-rw-r--r--lib/gitlab/import_export/project/relation_saver.rb57
-rw-r--r--lib/gitlab/import_export/project/tree_saver.rb5
-rw-r--r--lib/gitlab/import_export/remote_stream_upload.rb117
-rw-r--r--lib/gitlab/import_export/shared.rb9
-rw-r--r--lib/gitlab/instrumentation/global_search_api.rb46
-rw-r--r--lib/gitlab/instrumentation_helper.rb5
-rw-r--r--lib/gitlab/issues/rebalancing/state.rb8
-rw-r--r--lib/gitlab/jira_import/issues_importer.rb29
-rw-r--r--lib/gitlab/job_waiter.rb2
-rw-r--r--lib/gitlab/kubernetes.rb6
-rw-r--r--lib/gitlab/legacy_github_import/client.rb2
-rw-r--r--lib/gitlab/mail_room.rb4
-rw-r--r--lib/gitlab/memory/jemalloc.rb22
-rw-r--r--lib/gitlab/memory/reports/jemalloc_stats.rb67
-rw-r--r--lib/gitlab/memory/reports_daemon.rb106
-rw-r--r--lib/gitlab/memory/watchdog.rb18
-rw-r--r--lib/gitlab/merge_requests/mergeability/check_result.rb4
-rw-r--r--lib/gitlab/metrics/dashboard/url.rb10
-rw-r--r--lib/gitlab/metrics/methods/metric_options.rb2
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb6
-rw-r--r--lib/gitlab/null_request_store.rb2
-rw-r--r--lib/gitlab/object_hierarchy.rb3
-rw-r--r--lib/gitlab/pagination/gitaly_keyset_pager.rb8
-rw-r--r--lib/gitlab/patch/global_id.rb2
-rw-r--r--lib/gitlab/path_regex.rb4
-rw-r--r--lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb2
-rw-r--r--lib/gitlab/process_management.rb4
-rw-r--r--lib/gitlab/profiler.rb2
-rw-r--r--lib/gitlab/project_template.rb2
-rw-r--r--lib/gitlab/query_limiting/middleware.rb6
-rw-r--r--lib/gitlab/quick_actions/command_definition.rb18
-rw-r--r--lib/gitlab/quick_actions/dsl.rb10
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb70
-rw-r--r--lib/gitlab/quick_actions/spend_time_and_date_separator.rb6
-rw-r--r--lib/gitlab/redis/cache.rb2
-rw-r--r--lib/gitlab/redis/multi_store.rb2
-rw-r--r--lib/gitlab/regex.rb8
-rw-r--r--lib/gitlab/relative_positioning/item_context.rb7
-rw-r--r--lib/gitlab/saas.rb4
-rw-r--r--lib/gitlab/safe_request_loader.rb2
-rw-r--r--lib/gitlab/search/query.rb2
-rw-r--r--lib/gitlab/seeder.rb42
-rw-r--r--lib/gitlab/sidekiq_daemon/memory_killer.rb15
-rw-r--r--lib/gitlab/sidekiq_logging/logs_jobs.rb1
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb8
-rw-r--r--lib/gitlab/ssh/commit.rb24
-rw-r--r--lib/gitlab/ssh/signature.rb16
-rw-r--r--lib/gitlab/string_placeholder_replacer.rb2
-rw-r--r--lib/gitlab/terraform/state_migration_helper.rb2
-rw-r--r--lib/gitlab/tracking.rb2
-rw-r--r--lib/gitlab/tracking/destinations/snowplow_micro.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/base_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/database_metric.rb20
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb2
-rw-r--r--lib/gitlab/usage/time_frame.rb5
-rw-r--r--lib/gitlab/usage_data_counters.rb3
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb13
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb34
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml8
-rw-r--r--lib/gitlab/usage_data_counters/known_events/code_review_events.yml151
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml41
-rw-r--r--lib/gitlab/usage_data_counters/known_events/kubernetes_agent.yml5
-rw-r--r--lib/gitlab/usage_data_counters/known_events/work_items.yml5
-rw-r--r--lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb19
-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/batch_loader.rb23
-rw-r--r--lib/gitlab/utils/link_header_parser.rb46
-rw-r--r--lib/gitlab/utils/strong_memoize.rb73
-rw-r--r--lib/gitlab/utils/usage_data.rb4
-rw-r--r--lib/gitlab/version_info.rb6
-rw-r--r--lib/gitlab/word_diff/segments/diff_hunk.rb8
-rw-r--r--lib/gitlab/zentao/client.rb6
-rw-r--r--lib/google_api/cloud_platform/client.rb34
-rw-r--r--lib/kramdown/converter/commonmark.rb6
-rw-r--r--lib/release_highlights/validator/entry.rb18
-rw-r--r--lib/security/ci_configuration/sast_build_action.rb10
-rw-r--r--lib/security/report_schema_version_matcher.rb42
-rw-r--r--lib/tasks/contracts/merge_requests.rake23
-rw-r--r--lib/tasks/contracts/pipeline_schedules.rake32
-rw-r--r--lib/tasks/contracts/pipelines.rake37
-rw-r--r--lib/tasks/dev.rake15
-rw-r--r--lib/tasks/gems.rake2
-rw-r--r--lib/tasks/gitlab/backup.rake6
-rw-r--r--lib/tasks/gitlab/db.rake2
-rw-r--r--lib/tasks/gitlab/db/lock_writes.rake111
-rw-r--r--lib/tasks/gitlab/gitaly.rake2
-rw-r--r--lib/tasks/gitlab/info.rake2
-rw-r--r--lib/tasks/gitlab/praefect.rake6
-rw-r--r--lib/tasks/gitlab/shell.rake2
-rw-r--r--lib/tasks/gitlab/tw/codeowners.rake10
-rw-r--r--lib/tasks/gitlab/web_hook.rake11
-rw-r--r--lib/tasks/rubocop.rake3
-rw-r--r--lib/unnested_in_filters/rewriter.rb47
-rw-r--r--locale/am_ET/gitlab.po1372
-rw-r--r--locale/ar_SA/gitlab.po1444
-rw-r--r--locale/as_IN/gitlab.po1372
-rw-r--r--locale/az_AZ/gitlab.po1372
-rw-r--r--locale/ba_RU/gitlab.po1354
-rw-r--r--locale/bg/gitlab.po1372
-rw-r--r--locale/bn_BD/gitlab.po1372
-rw-r--r--locale/bn_IN/gitlab.po1372
-rw-r--r--locale/br_FR/gitlab.po1426
-rw-r--r--locale/bs_BA/gitlab.po1392
-rw-r--r--locale/ca_ES/gitlab.po1372
-rw-r--r--locale/cs_CZ/gitlab.po1408
-rw-r--r--locale/cy_GB/gitlab.po1444
-rw-r--r--locale/da_DK/gitlab.po1396
-rw-r--r--locale/de/gitlab.po2254
-rw-r--r--locale/el_GR/gitlab.po1372
-rw-r--r--locale/en_GB/gitlab.po3026
-rw-r--r--locale/eo/gitlab.po1372
-rw-r--r--locale/es/gitlab.po1868
-rw-r--r--locale/et_EE/gitlab.po1372
-rw-r--r--locale/fa_IR/gitlab.po1372
-rw-r--r--locale/fi_FI/gitlab.po1372
-rw-r--r--locale/fil_PH/gitlab.po1372
-rw-r--r--locale/fr/gitlab.po1534
-rw-r--r--locale/gitlab.pot1149
-rw-r--r--locale/gl_ES/gitlab.po1372
-rw-r--r--locale/he_IL/gitlab.po1408
-rw-r--r--locale/hi_IN/gitlab.po1372
-rw-r--r--locale/hr_HR/gitlab.po1390
-rw-r--r--locale/hu_HU/gitlab.po1372
-rw-r--r--locale/hy_AM/gitlab.po1372
-rw-r--r--locale/id_ID/gitlab.po1354
-rw-r--r--locale/ig_NG/gitlab.po1354
-rw-r--r--locale/is_IS/gitlab.po1372
-rw-r--r--locale/it/gitlab.po1372
-rw-r--r--locale/ja/gitlab.po1368
-rw-r--r--locale/ka_GE/gitlab.po1372
-rw-r--r--locale/kab/gitlab.po1372
-rw-r--r--locale/ko/gitlab.po1522
-rw-r--r--locale/ku_TR/gitlab.po1372
-rw-r--r--locale/ky_KG/gitlab.po1372
-rw-r--r--locale/lt_LT/gitlab.po1408
-rw-r--r--locale/mk_MK/gitlab.po1372
-rw-r--r--locale/ml_IN/gitlab.po1372
-rw-r--r--locale/mn_MN/gitlab.po1372
-rw-r--r--locale/nb_NO/gitlab.po1610
-rw-r--r--locale/nl_NL/gitlab.po1372
-rw-r--r--locale/or_IN/gitlab.po1372
-rw-r--r--locale/pa_IN/gitlab.po1372
-rw-r--r--locale/pl_PL/gitlab.po1416
-rw-r--r--locale/pt_BR/gitlab.po1680
-rw-r--r--locale/pt_PT/gitlab.po1376
-rw-r--r--locale/ro_RO/gitlab.po1630
-rw-r--r--locale/ru/gitlab.po1436
-rw-r--r--locale/si_LK/gitlab.po3274
-rw-r--r--locale/sk_SK/gitlab.po1408
-rw-r--r--locale/sl_SI/gitlab.po1408
-rw-r--r--locale/sq_AL/gitlab.po1372
-rw-r--r--locale/sr_CS/gitlab.po1390
-rw-r--r--locale/sr_SP/gitlab.po1390
-rw-r--r--locale/sv_SE/gitlab.po1372
-rw-r--r--locale/sw_KE/gitlab.po1372
-rw-r--r--locale/ta_IN/gitlab.po1372
-rw-r--r--locale/th_TH/gitlab.po1354
-rw-r--r--locale/tr_TR/gitlab.po1376
-rw-r--r--locale/uk/gitlab.po1868
-rw-r--r--locale/ur_PK/gitlab.po1372
-rw-r--r--locale/uz_UZ/gitlab.po1372
-rw-r--r--locale/vi_VN/gitlab.po1354
-rw-r--r--locale/zh_CN/gitlab.po1452
-rw-r--r--locale/zh_HK/gitlab.po1354
-rw-r--r--locale/zh_TW/gitlab.po30444
-rw-r--r--package.json133
-rw-r--r--qa/Dockerfile2
-rw-r--r--qa/Gemfile4
-rw-r--r--qa/Gemfile.lock19
-rw-r--r--qa/Rakefile7
-rw-r--r--qa/qa.rb12
-rw-r--r--qa/qa/ce/strategy.rb10
-rw-r--r--qa/qa/flow/purchase.rb2
-rw-r--r--qa/qa/page/admin/overview/users/components/impersonation_tokens.rb18
-rw-r--r--qa/qa/page/admin/overview/users/show.rb20
-rw-r--r--qa/qa/page/alert/auto_devops_alert.rb2
-rw-r--r--qa/qa/page/component/access_tokens.rb10
-rw-r--r--qa/qa/page/component/ci_badge_link.rb2
-rw-r--r--qa/qa/page/component/confirm_modal.rb11
-rw-r--r--qa/qa/page/component/groups_filter.rb4
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb4
-rw-r--r--qa/qa/page/component/namespace_select.rb5
-rw-r--r--qa/qa/page/component/wiki_page_form.rb4
-rw-r--r--qa/qa/page/dashboard/groups.rb9
-rw-r--r--qa/qa/page/dashboard/projects.rb6
-rw-r--r--qa/qa/page/file/edit.rb24
-rw-r--r--qa/qa/page/file/shared/editor.rb6
-rw-r--r--qa/qa/page/group/new.rb6
-rw-r--r--qa/qa/page/issuable/new.rb19
-rw-r--r--qa/qa/page/label/index.rb10
-rw-r--r--qa/qa/page/label/new.rb12
-rw-r--r--qa/qa/page/main/login.rb10
-rw-r--r--qa/qa/page/merge_request/show.rb38
-rw-r--r--qa/qa/page/profile/ssh_keys.rb6
-rw-r--r--qa/qa/page/project/new.rb6
-rw-r--r--qa/qa/page/project/pipeline_editor/show.rb25
-rw-r--r--qa/qa/page/project/settings/advanced.rb6
-rw-r--r--qa/qa/page/project/settings/integrations.rb7
-rw-r--r--qa/qa/page/project/settings/pages.rb25
-rw-r--r--qa/qa/page/project/settings/protected_branches.rb4
-rw-r--r--qa/qa/page/project/settings/services/jenkins.rb6
-rw-r--r--qa/qa/page/project/show.rb6
-rw-r--r--qa/qa/page/project/sub_menus/settings.rb8
-rw-r--r--qa/qa/page/project/web_ide/edit.rb12
-rw-r--r--qa/qa/page/view.rb2
-rw-r--r--qa/qa/resource/api_fabricator.rb19
-rw-r--r--qa/qa/resource/group.rb11
-rw-r--r--qa/qa/resource/group_ci_variable.rb47
-rw-r--r--qa/qa/resource/impersonation_token.rb97
-rw-r--r--qa/qa/resource/integrations/project.rb25
-rw-r--r--qa/qa/resource/personal_access_token.rb23
-rw-r--r--qa/qa/resource/personal_access_token_cache.rb12
-rw-r--r--qa/qa/resource/project.rb32
-rw-r--r--qa/qa/resource/sandbox.rb7
-rw-r--r--qa/qa/runtime/env.rb12
-rw-r--r--qa/qa/runtime/ip_address.rb5
-rw-r--r--qa/qa/runtime/user.rb2
-rw-r--r--qa/qa/scenario/test/integration/metrics.rb13
-rw-r--r--qa/qa/scenario/test/sanity/selectors.rb7
-rw-r--r--qa/qa/service/docker_run/gitlab_runner.rb3
-rw-r--r--qa/qa/service/docker_run/jenkins.rb43
-rw-r--r--qa/qa/service/praefect_manager.rb8
-rw-r--r--qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb62
-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_inherited_access_spec.rb5
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb22
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb9
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb21
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb1
-rw-r--r--qa/qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb32
-rw-r--r--qa/qa/specs/features/api/5_package/container_registry_spec.rb8
-rw-r--r--qa/qa/specs/features/api/8_monitor/metrics_spec.rb50
-rw-r--r--qa/qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb41
-rw-r--r--qa/qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/14_product_intelligence/performance_bar_spec.rb41
-rw-r--r--qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_default_enabled_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_disabled_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb37
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb9
-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/protected_tags_spec.rb115
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/impersonation_token_spec.rb32
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb33
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb55
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb37
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb32
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb55
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb37
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb177
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/pages/pages_pipeline_spec.rb47
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/license_detecton_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb112
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb55
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb102
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb103
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb175
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb103
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb46
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb2
-rw-r--r--qa/qa/specs/features/sanity/feature_flags_spec.rb4
-rw-r--r--qa/qa/support/helpers/mask_token.rb10
-rw-r--r--qa/qa/support/knapsack_report.rb6
-rw-r--r--qa/qa/support/loglinking.rb16
-rw-r--r--qa/qa/support/parallel_pipeline_jobs.rb76
-rw-r--r--qa/qa/tools/delete_projects.rb16
-rw-r--r--qa/qa/tools/delete_user_projects.rb64
-rw-r--r--qa/qa/tools/lib/project.rb33
-rw-r--r--qa/qa/vendor/jenkins/README.md61
-rw-r--r--qa/qa/vendor/jenkins/client.rb298
-rw-r--r--qa/qa/vendor/jenkins/helpers.rb36
-rw-r--r--qa/qa/vendor/jenkins/job.rb166
-rw-r--r--qa/qa/vendor/jenkins/page/base.rb24
-rw-r--r--qa/qa/vendor/jenkins/page/configure.rb48
-rw-r--r--qa/qa/vendor/jenkins/page/configure_job.rb77
-rw-r--r--qa/qa/vendor/jenkins/page/last_job_console.rb44
-rw-r--r--qa/qa/vendor/jenkins/page/login.rb31
-rw-r--r--qa/qa/vendor/jenkins/page/new_credentials.rb50
-rw-r--r--qa/qa/vendor/jenkins/page/new_job.rb38
-rw-r--r--qa/spec/scenario/test/sanity/selectors_spec.rb20
-rw-r--r--qa/spec/service/docker_run/gitlab_runner_spec.rb52
-rw-r--r--qa/spec/support/loglinking_spec.rb34
-rw-r--r--qa/spec/support/page_error_checker_spec.rb5
-rw-r--r--qa/tasks/knapsack.rake25
-rw-r--r--qa/tasks/reliable_report.rake2
-rw-r--r--qa/tasks/vulnerabilities.rake2
-rw-r--r--results.txt0
-rw-r--r--rubocop/code_reuse_helpers.rb14
-rw-r--r--rubocop/cop/code_reuse/worker.rb4
-rw-r--r--rubocop/cop/gemspec/avoid_executing_git.rb62
-rw-r--r--rubocop/cop/gitlab/deprecate_track_redis_hll_event.rb33
-rw-r--r--rubocop/cop/gitlab/feature_available_usage.rb3
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb2
-rw-r--r--rubocop/cop/migration/add_limit_to_text_columns.rb2
-rw-r--r--rubocop/cop/scalability/bulk_perform_with_context.rb2
-rw-r--r--rubocop/cop_todo.rb49
-rw-r--r--rubocop/formatter/todo_formatter.rb48
-rw-r--r--scripts/lib/glfm/render_wysiwyg_html_and_json.js3
-rw-r--r--scripts/lib/glfm/update_example_snapshots.rb10
-rwxr-xr-xscripts/lint-vendored-gems.sh5
-rwxr-xr-xscripts/perf/query_limiting_report.rb2
-rwxr-xr-xscripts/qa/testcases-check4
-rwxr-xr-xscripts/review_apps/review-apps.sh4
-rwxr-xr-xscripts/static-analysis7
-rwxr-xr-xscripts/trigger-build.rb5
-rwxr-xr-xscripts/undercoverage3
-rw-r--r--scripts/utils.sh6
-rwxr-xr-xscripts/validate_migration_schema2
-rw-r--r--security.txt16
-rw-r--r--spec/channels/application_cable/connection_spec.rb2
-rw-r--r--spec/channels/awareness_channel_spec.rb3
-rw-r--r--spec/commands/sidekiq_cluster/cli_spec.rb4
-rw-r--r--spec/components/diffs/overflow_warning_component_spec.rb2
-rw-r--r--spec/components/diffs/stats_component_spec.rb2
-rw-r--r--spec/components/docs/01_overview.html.erb20
-rw-r--r--spec/components/pajamas/avatar_component_spec.rb135
-rw-r--r--spec/components/pajamas/banner_component_spec.rb2
-rw-r--r--spec/components/pajamas/button_component_spec.rb54
-rw-r--r--spec/components/pajamas/checkbox_component_spec.rb6
-rw-r--r--spec/components/pajamas/checkbox_tag_component_spec.rb59
-rw-r--r--spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb77
-rw-r--r--spec/components/previews/pajamas/alert_component_preview.rb19
-rw-r--r--spec/components/previews/pajamas/avatar_component_preview.rb27
-rw-r--r--spec/components/previews/pajamas/banner_component_preview.rb54
-rw-r--r--spec/components/previews/pajamas/button_component_preview.rb56
-rw-r--r--spec/components/previews/pajamas/card_component_preview.rb27
-rw-r--r--spec/components/previews/pajamas/spinner_component_preview.rb22
-rw-r--r--spec/contracts/consumer/endpoints/project/merge_requests.js34
-rw-r--r--spec/contracts/consumer/endpoints/project/pipelines.js16
-rw-r--r--spec/contracts/consumer/fixtures/project/merge_request/diffs_batch.fixture.js10
-rw-r--r--spec/contracts/consumer/fixtures/project/merge_request/diffs_metadata.fixture.js10
-rw-r--r--spec/contracts/consumer/fixtures/project/merge_request/discussions.fixture.js10
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js39
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline/delete_pipeline.fixture.js24
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline/get_list_project_pipelines.fixture.js10
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline/get_pipeline_header_data.fixture.js9
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js44
-rw-r--r--spec/contracts/consumer/helpers/common_regex_patterns.js1
-rw-r--r--spec/contracts/consumer/resources/api/pipeline_schedules.js26
-rw-r--r--spec/contracts/consumer/resources/api/project/merge_requests.js34
-rw-r--r--spec/contracts/consumer/resources/api/project/pipelines.js34
-rw-r--r--spec/contracts/consumer/resources/graphql/pipelines.js21
-rw-r--r--spec/contracts/consumer/specs/project/merge_request/show.spec.js36
-rw-r--r--spec/contracts/consumer/specs/project/pipeline/index.spec.js16
-rw-r--r--spec/contracts/consumer/specs/project/pipeline/new.spec.js41
-rw-r--r--spec/contracts/consumer/specs/project/pipeline/show.spec.js54
-rw-r--r--spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js41
-rw-r--r--spec/contracts/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json4
-rw-r--r--spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json43
-rw-r--r--spec/contracts/contracts/project/pipeline/show/pipelines#show-delete_pipeline.json44
-rw-r--r--spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json48
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/diffs_batch_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/diffs_metadata_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/discussions_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb16
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb16
-rw-r--r--spec/contracts/provider/states/project/merge_request/diffs_batch_state.rb18
-rw-r--r--spec/contracts/provider/states/project/merge_request/diffs_metadata_state.rb18
-rw-r--r--spec/contracts/provider/states/project/merge_request/discussions_state.rb17
-rw-r--r--spec/contracts/provider/states/project/merge_request/show_state.rb47
-rw-r--r--spec/contracts/provider/states/project/pipeline/index_state.rb (renamed from spec/contracts/provider/states/project/pipeline/pipelines_state.rb)0
-rw-r--r--spec/contracts/provider/states/project/pipeline/new_state.rb24
-rw-r--r--spec/contracts/provider/states/project/pipeline/pipeline_state.rb27
-rw-r--r--spec/contracts/provider/states/project/pipeline/show_state.rb28
-rw-r--r--spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb15
-rw-r--r--spec/controllers/admin/dev_ops_report_controller_spec.rb11
-rw-r--r--spec/controllers/admin/identities_controller_spec.rb24
-rw-r--r--spec/controllers/admin/topics_controller_spec.rb40
-rw-r--r--spec/controllers/admin/usage_trends_controller_spec.rb13
-rw-r--r--spec/controllers/admin/users_controller_spec.rb6
-rw-r--r--spec/controllers/groups/uploads_controller_spec.rb104
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb38
-rw-r--r--spec/controllers/profiles/personal_access_tokens_controller_spec.rb32
-rw-r--r--spec/controllers/profiles_controller_spec.rb6
-rw-r--r--spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb48
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb1
-rw-r--r--spec/controllers/projects/ci/secure_files_controller_spec.rb67
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb12
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb17
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb19
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb2
-rw-r--r--spec/controllers/projects/hooks_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb32
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb46
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb71
-rw-r--r--spec/controllers/projects/pages_controller_spec.rb48
-rw-r--r--spec/controllers/projects/protected_branches_controller_spec.rb54
-rw-r--r--spec/controllers/projects/tags/releases_controller_spec.rb103
-rw-r--r--spec/controllers/projects/uploads_controller_spec.rb184
-rw-r--r--spec/controllers/projects_controller_spec.rb82
-rw-r--r--spec/controllers/registrations_controller_spec.rb8
-rw-r--r--spec/controllers/search_controller_spec.rb67
-rw-r--r--spec/events/ci/pipeline_created_event_spec.rb27
-rw-r--r--spec/events/pages/page_deleted_event_spec.rb35
-rw-r--r--spec/events/pages/page_deployed_event_spec.rb34
-rw-r--r--spec/events/projects/project_created_event_spec.rb34
-rw-r--r--spec/events/projects/project_deleted_event_spec.rb35
-rw-r--r--spec/events/projects/project_path_changed_event_spec.rb46
-rw-r--r--spec/factories/ci/builds.rb27
-rw-r--r--spec/factories/ci/job_artifacts.rb22
-rw-r--r--spec/factories/ci/runners.rb4
-rw-r--r--spec/factories/ci/secure_files.rb6
-rw-r--r--spec/factories/ci/variables.rb1
-rw-r--r--spec/factories/gitlab/database/async_indexes/postgres_async_index.rb4
-rw-r--r--spec/factories/member_roles.rb8
-rw-r--r--spec/factories/projects.rb10
-rw-r--r--spec/factories/users.rb2
-rw-r--r--spec/factories/users/project_user_callouts.rb10
-rw-r--r--spec/factories/work_items.rb4
-rw-r--r--spec/features/admin/admin_appearance_spec.rb233
-rw-r--r--spec/features/admin/admin_mode/login_spec.rb342
-rw-r--r--spec/features/admin/users/users_spec.rb4
-rw-r--r--spec/features/admin_variables_spec.rb34
-rw-r--r--spec/features/boards/board_filters_spec.rb4
-rw-r--r--spec/features/boards/boards_spec.rb8
-rw-r--r--spec/features/boards/reload_boards_on_browser_back_spec.rb6
-rw-r--r--spec/features/clusters/create_agent_spec.rb5
-rw-r--r--spec/features/cycle_analytics_spec.rb18
-rw-r--r--spec/features/dashboard/archived_projects_spec.rb2
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb78
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb4
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb4
-rw-r--r--spec/features/group_variables_spec.rb10
-rw-r--r--spec/features/groups/crm/contacts/create_spec.rb4
-rw-r--r--spec/features/groups/group_runners_spec.rb74
-rw-r--r--spec/features/groups/issues_spec.rb6
-rw-r--r--spec/features/groups/members/manage_members_spec.rb4
-rw-r--r--spec/features/groups/show_spec.rb45
-rw-r--r--spec/features/groups_spec.rb80
-rw-r--r--spec/features/invites_spec.rb22
-rw-r--r--spec/features/issuables/user_sees_sidebar_spec.rb2
-rw-r--r--spec/features/issues/form_spec.rb7
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb2
-rw-r--r--spec/features/issues/incident_issue_spec.rb70
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb8
-rw-r--r--spec/features/issues/related_issues_spec.rb20
-rw-r--r--spec/features/issues/todo_spec.rb2
-rw-r--r--spec/features/issues/user_bulk_edits_issues_spec.rb2
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb8
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb6
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb2
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb2
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb19
-rw-r--r--spec/features/markdown/gitlab_flavored_markdown_spec.rb2
-rw-r--r--spec/features/markdown/json_table_spec.rb40
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb10
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb6
-rw-r--r--spec/features/merge_request/user_approves_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_merge_request_spec.rb39
-rw-r--r--spec/features/merge_request/user_customizes_merge_commit_message_spec.rb4
-rw-r--r--spec/features/merge_request/user_edits_assignees_sidebar_spec.rb2
-rw-r--r--spec/features/merge_request/user_merges_merge_request_spec.rb21
-rw-r--r--spec/features/merge_request/user_opens_context_commits_modal_spec.rb26
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_closing_issues_message_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb2
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb11
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb2
-rw-r--r--spec/features/merge_request/user_uses_quick_actions_spec.rb2
-rw-r--r--spec/features/merge_requests/user_mass_updates_spec.rb14
-rw-r--r--spec/features/oauth_registration_spec.rb39
-rw-r--r--spec/features/populate_new_pipeline_vars_with_params_spec.rb2
-rw-r--r--spec/features/profile_spec.rb2
-rw-r--r--spec/features/profiles/password_spec.rb15
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb6
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb4
-rw-r--r--spec/features/profiles/user_visits_profile_spec.rb20
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb2
-rw-r--r--spec/features/projects/blobs/edit_spec.rb5
-rw-r--r--spec/features/projects/ci/lint_spec.rb5
-rw-r--r--spec/features/projects/ci/secure_files_spec.rb61
-rw-r--r--spec/features/projects/cluster_agents_spec.rb2
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb2
-rw-r--r--spec/features/projects/compare_spec.rb2
-rw-r--r--spec/features/projects/environments/environment_spec.rb8
-rw-r--r--spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb2
-rw-r--r--spec/features/projects/files/user_browses_files_spec.rb4
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb19
-rw-r--r--spec/features/projects/files/user_edits_files_spec.rb26
-rw-r--r--spec/features/projects/issuable_templates_spec.rb28
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb1
-rw-r--r--spec/features/projects/members/manage_groups_spec.rb2
-rw-r--r--spec/features/projects/members/manage_members_spec.rb200
-rw-r--r--spec/features/projects/merge_request_button_spec.rb20
-rw-r--r--spec/features/projects/new_project_spec.rb32
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb6
-rw-r--r--spec/features/projects/pages/user_configures_pages_pipeline_spec.rb59
-rw-r--r--spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb3
-rw-r--r--spec/features/projects/pages/user_edits_settings_spec.rb13
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb7
-rw-r--r--spec/features/projects/pipelines/legacy_pipeline_spec.rb31
-rw-r--r--spec/features/projects/pipelines/legacy_pipelines_spec.rb3
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb9
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb3
-rw-r--r--spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb49
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb4
-rw-r--r--spec/features/projects/settings/service_desk_setting_spec.rb2
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb74
-rw-r--r--spec/features/projects/tags/user_views_tag_spec.rb8
-rw-r--r--spec/features/projects/tags/user_views_tags_spec.rb30
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb4
-rw-r--r--spec/features/projects/tree/create_file_spec.rb4
-rw-r--r--spec/features/projects/tree/tree_show_spec.rb2
-rw-r--r--spec/features/projects_spec.rb30
-rw-r--r--spec/features/runners_spec.rb6
-rw-r--r--spec/features/search/user_searches_for_commits_spec.rb2
-rw-r--r--spec/features/signed_commits_spec.rb2
-rw-r--r--spec/features/tags/developer_updates_tag_spec.rb56
-rw-r--r--spec/features/task_lists_spec.rb12
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_profile_spec.rb2
-rw-r--r--spec/features/uploads/user_uploads_file_to_note_spec.rb11
-rw-r--r--spec/features/users/email_verification_on_login_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb38
-rw-r--r--spec/features/users/show_spec.rb10
-rw-r--r--spec/features/users/signup_spec.rb465
-rw-r--r--spec/finders/autocomplete/deploy_keys_with_write_access_finder_spec.rb53
-rw-r--r--spec/finders/ci/runners_finder_spec.rb6
-rw-r--r--spec/finders/clusters/knative_services_finder_spec.rb2
-rw-r--r--spec/finders/concerns/finder_with_cross_project_access_spec.rb6
-rw-r--r--spec/finders/crm/contacts_finder_spec.rb61
-rw-r--r--spec/finders/fork_targets_finder_spec.rb40
-rw-r--r--spec/finders/groups/accepting_project_transfers_finder_spec.rb63
-rw-r--r--spec/finders/groups/user_groups_finder_spec.rb112
-rw-r--r--spec/finders/projects/topics_finder_spec.rb28
-rw-r--r--spec/finders/tags_finder_spec.rb10
-rw-r--r--spec/fixtures/api/schemas/entities/discussion.json3
-rw-r--r--spec/fixtures/api/schemas/external_validation.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/notes.json3
-rw-r--r--spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gzbin3846 -> 4603 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/100_files.zipbin0 -> 15902 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/200_mb_decompressed.zipbin0 -> 203718 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/multiple_files.zipbin0 -> 332 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/single_file.zipbin0 -> 177 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/with_directory.zipbin0 -> 520 bytes
-rw-r--r--spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/zipbomb.zipbin0 -> 1042247 bytes
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json71
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson4
-rw-r--r--spec/fixtures/markdown.md.erb2
-rw-r--r--spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.pom.sha11
-rw-r--r--spec/fixtures/whats_new/20201225_01_01.yml6
-rw-r--r--spec/fixtures/whats_new/20201225_01_02.yml6
-rw-r--r--spec/fixtures/whats_new/20201225_01_04.yml18
-rw-r--r--spec/fixtures/whats_new/20201225_01_05.yml12
-rw-r--r--spec/fixtures/whats_new/blank.yml4
-rw-r--r--spec/fixtures/whats_new/invalid.yml16
-rw-r--r--spec/fixtures/whats_new/valid.yml16
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js1
-rw-r--r--spec/frontend/__helpers__/mock_dom_observer.js2
-rw-r--r--spec/frontend/__helpers__/mocks/axios_utils.js2
-rw-r--r--spec/frontend/__helpers__/stub_component.js8
-rw-r--r--spec/frontend/__helpers__/timeout.js59
-rw-r--r--spec/frontend/__helpers__/vue_mount_component_helper.js29
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper.js19
-rw-r--r--spec/frontend/__helpers__/vue_test_utils_helper_spec.js57
-rw-r--r--spec/frontend/__helpers__/vuex_action_helper.js6
-rw-r--r--spec/frontend/__helpers__/vuex_action_helper_spec.js2
-rw-r--r--spec/frontend/__helpers__/wait_for_promises.js6
-rw-r--r--spec/frontend/__helpers__/web_worker_transformer.js2
-rw-r--r--spec/frontend/__mocks__/monaco-editor/index.js1
-rw-r--r--spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap17
-rw-r--r--spec/frontend/access_tokens/components/expires_at_field_spec.js9
-rw-r--r--spec/frontend/access_tokens/components/projects_field_spec.js131
-rw-r--r--spec/frontend/access_tokens/components/projects_token_selector_spec.js266
-rw-r--r--spec/frontend/access_tokens/index_spec.js45
-rw-r--r--spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js4
-rw-r--r--spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js2
-rw-r--r--spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js2
-rw-r--r--spec/frontend/admin/signup_restrictions/components/signup_form_spec.js4
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js2
-rw-r--r--spec/frontend/admin/users/components/actions/actions_spec.js2
-rw-r--r--spec/frontend/admin/users/components/app_spec.js2
-rw-r--r--spec/frontend/admin/users/components/modals/delete_user_modal_spec.js14
-rw-r--r--spec/frontend/admin/users/components/user_actions_spec.js4
-rw-r--r--spec/frontend/admin/users/components/user_avatar_spec.js6
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js8
-rw-r--r--spec/frontend/admin/users/index_spec.js4
-rw-r--r--spec/frontend/api/groups_api_spec.js46
-rw-r--r--spec/frontend/attention_requests/components/navigation_popover_spec.js88
-rw-r--r--spec/frontend/batch_comments/components/review_bar_spec.js51
-rw-r--r--spec/frontend/behaviors/components/json_table_spec.js162
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js2
-rw-r--r--spec/frontend/behaviors/markdown/render_json_table_spec.js119
-rw-r--r--spec/frontend/blob/3d_viewer/mesh_object_spec.js4
-rw-r--r--spec/frontend/blob/blob_links_tracking_spec.js60
-rw-r--r--spec/frontend/blob/components/blob_content_spec.js22
-rw-r--r--spec/frontend/blob/components/blob_edit_content_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js6
-rw-r--r--spec/frontend/blob/components/blob_header_default_actions_spec.js8
-rw-r--r--spec/frontend/blob/components/blob_header_filepath_spec.js4
-rw-r--r--spec/frontend/blob/components/blob_header_spec.js14
-rw-r--r--spec/frontend/blob/components/blob_header_viewer_switcher_spec.js6
-rw-r--r--spec/frontend/blob/notebook/notebook_viever_spec.js8
-rw-r--r--spec/frontend/blob/pdf/pdf_viewer_spec.js6
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js16
-rw-r--r--spec/frontend/blob/sketch/index_spec.js2
-rw-r--r--spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js2
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js6
-rw-r--r--spec/frontend/boards/board_list_spec.js2
-rw-r--r--spec/frontend/boards/components/board_add_new_column_form_spec.js30
-rw-r--r--spec/frontend/boards/components/board_add_new_column_trigger_spec.js4
-rw-r--r--spec/frontend/boards/components/board_blocked_icon_spec.js8
-rw-r--r--spec/frontend/boards/components/board_card_spec.js2
-rw-r--r--spec/frontend/boards/components/board_content_sidebar_spec.js2
-rw-r--r--spec/frontend/boards/components/board_content_spec.js12
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js2
-rw-r--r--spec/frontend/boards/components/board_new_item_spec.js8
-rw-r--r--spec/frontend/boards/components/board_settings_sidebar_spec.js16
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js2
-rw-r--r--spec/frontend/boards/components/new_board_button_spec.js6
-rw-r--r--spec/frontend/boards/components/sidebar/board_editable_item_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js8
-rw-r--r--spec/frontend/boards/project_select_spec.js9
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js15
-rw-r--r--spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js5
-rw-r--r--spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js178
-rw-r--r--spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js139
-rw-r--r--spec/frontend/ci_variable_list/components/ci_group_variables_spec.js183
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js383
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js128
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_table_spec.js98
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js8
-rw-r--r--spec/frontend/ci_variable_list/mocks.js109
-rw-r--r--spec/frontend/ci_variable_list/utils_spec.js78
-rw-r--r--spec/frontend/clusters/agents/components/activity_history_item_spec.js2
-rw-r--r--spec/frontend/clusters/agents/components/create_token_modal_spec.js2
-rw-r--r--spec/frontend/clusters/agents/components/token_table_spec.js4
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js45
-rw-r--r--spec/frontend/clusters/components/new_cluster_spec.js4
-rw-r--r--spec/frontend/clusters/forms/components/integration_form_spec.js4
-rw-r--r--spec/frontend/clusters_list/components/install_agent_modal_spec.js1
-rw-r--r--spec/frontend/commit/pipelines/pipelines_table_spec.js39
-rw-r--r--spec/frontend/content_editor/components/bubble_menus/link_spec.js2
-rw-r--r--spec/frontend/content_editor/components/bubble_menus/media_spec.js2
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js14
-rw-r--r--spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js21
-rw-r--r--spec/frontend/content_editor/components/top_toolbar_spec.js2
-rw-r--r--spec/frontend/content_editor/components/wrappers/__snapshots__/table_of_contents_spec.js.snap115
-rw-r--r--spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js4
-rw-r--r--spec/frontend/content_editor/components/wrappers/table_of_contents_spec.js84
-rw-r--r--spec/frontend/content_editor/extensions/image_spec.js2
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec_helper.js4
-rw-r--r--spec/frontend/content_editor/remark_markdown_processing_spec.js238
-rw-r--r--spec/frontend/content_editor/render_html_and_json_for_all_examples.js4
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js144
-rw-r--r--spec/frontend/content_editor/services/table_of_contents_utils_spec.js96
-rw-r--r--spec/frontend/crm/contact_form_wrapper_spec.js9
-rw-r--r--spec/frontend/crm/contacts_root_spec.js56
-rw-r--r--spec/frontend/crm/form_spec.js38
-rw-r--r--spec/frontend/crm/mock_data.js32
-rw-r--r--spec/frontend/crm/organization_form_wrapper_spec.js2
-rw-r--r--spec/frontend/cycle_analytics/base_spec.js20
-rw-r--r--spec/frontend/cycle_analytics/mock_data.js18
-rw-r--r--spec/frontend/cycle_analytics/store/actions_spec.js56
-rw-r--r--spec/frontend/cycle_analytics/store/mutations_spec.js43
-rw-r--r--spec/frontend/design_management/components/delete_button_spec.js4
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js14
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js18
-rw-r--r--spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js8
-rw-r--r--spec/frontend/design_management/components/design_scaler_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_sidebar_spec.js8
-rw-r--r--spec/frontend/design_management/components/design_todo_button_spec.js2
-rw-r--r--spec/frontend/design_management/components/image_spec.js2
-rw-r--r--spec/frontend/design_management/components/list/item_spec.js10
-rw-r--r--spec/frontend/design_management/components/toolbar/index_spec.js10
-rw-r--r--spec/frontend/design_management/components/upload/button_spec.js2
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js12
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js12
-rw-r--r--spec/frontend/design_management/pages/index_spec.js14
-rw-r--r--spec/frontend/design_management/router_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js10
-rw-r--r--spec/frontend/diffs/store/utils_spec.js8
-rw-r--r--spec/frontend/dropzone_input_spec.js4
-rw-r--r--spec/frontend/editor/schema/ci/ci_schema_spec.js10
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml18
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml8
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/include.yml8
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/rules.yml14
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml25
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml3
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/filter.yml10
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml15
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/rules.yml23
-rw-r--r--spec/frontend/editor/source_editor_instance_spec.js2
-rw-r--r--spec/frontend/editor/source_editor_spec.js7
-rw-r--r--spec/frontend/environment.js1
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js10
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js4
-rw-r--r--spec/frontend/environments/confirm_rollback_modal_spec.js14
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js8
-rw-r--r--spec/frontend/environments/edit_environment_spec.js2
-rw-r--r--spec/frontend/environments/environment_actions_spec.js12
-rw-r--r--spec/frontend/environments/environment_delete_spec.js2
-rw-r--r--spec/frontend/environments/environment_item_spec.js12
-rw-r--r--spec/frontend/environments/environment_pin_spec.js4
-rw-r--r--spec/frontend/environments/environment_rollback_spec.js4
-rw-r--r--spec/frontend/environments/environment_stop_spec.js2
-rw-r--r--spec/frontend/environments/environment_table_spec.js4
-rw-r--r--spec/frontend/environments/environments_detail_header_spec.js12
-rw-r--r--spec/frontend/environments/folder/environments_folder_view_spec.js6
-rw-r--r--spec/frontend/environments/new_environment_spec.js2
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js44
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_actions_spec.js2
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js24
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_entry_spec.js10
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_spec.js4
-rw-r--r--spec/frontend/error_tracking_settings/components/project_dropdown_spec.js24
-rw-r--r--spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js4
-rw-r--r--spec/frontend/feature_flags/components/empty_state_spec.js14
-rw-r--r--spec/frontend/feature_flags/components/environments_dropdown_spec.js10
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_table_spec.js4
-rw-r--r--spec/frontend/feature_flags/components/form_spec.js18
-rw-r--r--spec/frontend/feature_flags/components/new_environments_dropdown_spec.js24
-rw-r--r--spec/frontend/feature_flags/components/new_feature_flag_spec.js6
-rw-r--r--spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js8
-rw-r--r--spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js12
-rw-r--r--spec/frontend/feature_flags/components/strategies/users_with_id_spec.js2
-rw-r--r--spec/frontend/feature_flags/components/strategy_parameters_spec.js6
-rw-r--r--spec/frontend/feature_flags/components/strategy_spec.js40
-rw-r--r--spec/frontend/fixtures/integrations.rb2
-rw-r--r--spec/frontend/fixtures/issues.rb40
-rw-r--r--spec/frontend/fixtures/namespaces.rb46
-rw-r--r--spec/frontend/fixtures/prometheus_integration.rb2
-rw-r--r--spec/frontend/fixtures/runner.rb44
-rw-r--r--spec/frontend/frequent_items/components/app_spec.js13
-rw-r--r--spec/frontend/gfm_auto_complete/mock_data.js34
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js48
-rw-r--r--spec/frontend/group_settings/components/shared_runners_form_spec.js29
-rw-r--r--spec/frontend/groups/components/app_spec.js24
-rw-r--r--spec/frontend/groups/components/group_item_spec.js49
-rw-r--r--spec/frontend/groups/components/group_name_and_path_spec.js75
-rw-r--r--spec/frontend/groups/components/groups_spec.js4
-rw-r--r--spec/frontend/groups/components/transfer_group_form_spec.js1
-rw-r--r--spec/frontend/header_search/components/app_spec.js72
-rw-r--r--spec/frontend/helpers/diffs_helper_spec.js32
-rw-r--r--spec/frontend/ide/components/activity_bar_spec.js72
-rw-r--r--spec/frontend/ide/components/branches/item_spec.js6
-rw-r--r--spec/frontend/ide/components/branches/search_list_spec.js6
-rw-r--r--spec/frontend/ide/components/commit_sidebar/editor_header_spec.js4
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js6
-rw-r--r--spec/frontend/ide/components/error_message_spec.js4
-rw-r--r--spec/frontend/ide/components/file_templates/dropdown_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_file_row_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_project_header_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_review_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_side_bar_spec.js34
-rw-r--r--spec/frontend/ide/components/ide_sidebar_nav_spec.js6
-rw-r--r--spec/frontend/ide/components/ide_spec.js2
-rw-r--r--spec/frontend/ide/components/ide_status_bar_spec.js124
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_mr_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_tree_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/detail/scroll_button_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js10
-rw-r--r--spec/frontend/ide/components/jobs/stage_spec.js8
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js8
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js82
-rw-r--r--spec/frontend/ide/components/panes/collapsible_sidebar_spec.js2
-rw-r--r--spec/frontend/ide/components/panes/right_spec.js8
-rw-r--r--spec/frontend/ide/components/pipelines/empty_state_spec.js2
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js12
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js2
-rw-r--r--spec/frontend/ide/components/preview/navigator_spec.js4
-rw-r--r--spec/frontend/ide/components/repo_commit_section_spec.js12
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js5
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js6
-rw-r--r--spec/frontend/ide/components/resizable_panel_spec.js2
-rw-r--r--spec/frontend/ide/components/shared/commit_message_field_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/empty_state_spec.js10
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_spec.js16
-rw-r--r--spec/frontend/ide/components/terminal/view_spec.js8
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js4
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js8
-rw-r--r--spec/frontend/ide/lib/common/model_manager_spec.js4
-rw-r--r--spec/frontend/ide/lib/diff/diff_spec.js8
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js8
-rw-r--r--spec/frontend/ide/stores/actions/tree_spec.js2
-rw-r--r--spec/frontend/ide/stores/getters_spec.js6
-rw-r--r--spec/frontend/ide/stores/modules/commit/getters_spec.js38
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js20
-rw-r--r--spec/frontend/ide/stores/mutations/merge_request_spec.js2
-rw-r--r--spec/frontend/ide/utils_spec.js6
-rw-r--r--spec/frontend/integrations/edit/components/dynamic_field_spec.js2
-rw-r--r--spec/frontend/integrations/overrides/components/integration_overrides_spec.js5
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js44
-rw-r--r--spec/frontend/invite_members/components/members_token_select_spec.js34
-rw-r--r--spec/frontend/invite_members/components/user_limit_notification_spec.js21
-rw-r--r--spec/frontend/invite_members/mock_data/api_responses.js15
-rw-r--r--spec/frontend/invite_members/mock_data/member_modal.js5
-rw-r--r--spec/frontend/issuable/components/related_issuable_item_spec.js233
-rw-r--r--spec/frontend/issuable/popover/components/issue_popover_spec.js62
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js4
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js71
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js367
-rw-r--r--spec/frontend/issues/list/components/issues_list_app_spec.js87
-rw-r--r--spec/frontend/issues/list/mock_data.js1
-rw-r--r--spec/frontend/issues/show/components/app_spec.js4
-rw-r--r--spec/frontend/issues/show/components/description_spec.js14
-rw-r--r--spec/frontend/issues/show/components/edit_actions_spec.js2
-rw-r--r--spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js189
-rw-r--r--spec/frontend/issues/show/components/incidents/mock_data.js28
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_form_spec.js117
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_item_spec.js116
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_list_item_spec.js116
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js2
-rw-r--r--spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js14
-rw-r--r--spec/frontend/issues/show/components/incidents/utils_spec.js2
-rw-r--r--spec/frontend/jira_connect/branches/components/project_dropdown_spec.js2
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js1
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js6
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js2
-rw-r--r--spec/frontend/jobs/components/job_log_controllers_spec.js148
-rw-r--r--spec/frontend/jobs/components/sidebar_detail_row_spec.js2
-rw-r--r--spec/frontend/labels/labels_select_spec.js6
-rw-r--r--spec/frontend/lib/dompurify_spec.js46
-rw-r--r--spec/frontend/lib/gfm/index_spec.js156
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js23
-rw-r--r--spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js4
-rw-r--r--spec/frontend/lib/utils/rails_ujs_spec.js12
-rw-r--r--spec/frontend/lib/utils/recurrence_spec.js5
-rw-r--r--spec/frontend/lib/utils/sticky_spec.js6
-rw-r--r--spec/frontend/lib/utils/text_markdown_spec.js136
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js66
-rw-r--r--spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/leave_button_spec.js4
-rw-r--r--spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/resend_invite_button_spec.js2
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js4
-rw-r--r--spec/frontend/members/components/app_spec.js4
-rw-r--r--spec/frontend/members/components/avatars/group_avatar_spec.js2
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js4
-rw-r--r--spec/frontend/members/components/filter_sort/filter_sort_container_spec.js4
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js2
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js4
-rw-r--r--spec/frontend/members/components/modals/remove_group_link_modal_spec.js4
-rw-r--r--spec/frontend/members/components/modals/remove_member_modal_spec.js2
-rw-r--r--spec/frontend/members/components/table/created_at_spec.js2
-rw-r--r--spec/frontend/members/components/table/expiration_datepicker_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/components/table/members_table_spec.js20
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js4
-rw-r--r--spec/frontend/members/index_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/anomaly_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/bar_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/gauge_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/heatmap_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/single_stat_spec.js2
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js29
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js19
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_builder_spec.js22
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js43
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js36
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js3
-rw-r--r--spec/frontend/monitoring/components/dashboards_dropdown_spec.js14
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js2
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js12
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js20
-rw-r--r--spec/frontend/monitoring/components/embeds/metric_embed_spec.js8
-rw-r--r--spec/frontend/monitoring/components/empty_state_spec.js4
-rw-r--r--spec/frontend/monitoring/components/graph_group_spec.js8
-rw-r--r--spec/frontend/monitoring/components/group_empty_state_spec.js2
-rw-r--r--spec/frontend/monitoring/components/links_section_spec.js2
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js6
-rw-r--r--spec/frontend/monitoring/components/variables/dropdown_field_spec.js4
-rw-r--r--spec/frontend/monitoring/components/variables_section_spec.js4
-rw-r--r--spec/frontend/monitoring/pages/panel_new_page_spec.js4
-rw-r--r--spec/frontend/monitoring/router_spec.js10
-rw-r--r--spec/frontend/monitoring/store/utils_spec.js8
-rw-r--r--spec/frontend/nav/components/top_nav_dropdown_menu_spec.js2
-rw-r--r--spec/frontend/notes/components/comment_field_layout_spec.js4
-rw-r--r--spec/frontend/notes/components/diff_discussion_header_spec.js29
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js22
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js8
-rw-r--r--spec/frontend/notes/components/discussion_filter_note_spec.js4
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js4
-rw-r--r--spec/frontend/notes/components/discussion_reply_placeholder_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js8
-rw-r--r--spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js2
-rw-r--r--spec/frontend/notes/components/note_actions/reply_button_spec.js2
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js37
-rw-r--r--spec/frontend/notes/components/note_attachment_spec.js4
-rw-r--r--spec/frontend/notes/components/note_body_spec.js21
-rw-r--r--spec/frontend/notes/components/note_form_spec.js20
-rw-r--r--spec/frontend/notes/components/note_header_spec.js22
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js14
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js18
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js7
-rw-r--r--spec/frontend/notes/components/sort_discussion_spec.js2
-rw-r--r--spec/frontend/notes/components/timeline_toggle_spec.js2
-rw-r--r--spec/frontend/notes/deprecated_notes_spec.js22
-rw-r--r--spec/frontend/operation_settings/components/metrics_settings_spec.js11
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js5
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js14
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js2
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js18
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/package_title_spec.js.snap29
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap196
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js192
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js32
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js20
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js16
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js42
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/details_spec.js187
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/__snapshots__/container_expiration_policy_form_spec.js.snap3
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/mock_data.js4
-rw-r--r--spec/frontend/pages/admin/application_settings/account_and_limits_spec.js8
-rw-r--r--spec/frontend/pages/groups/new/components/app_spec.js39
-rw-r--r--spec/frontend/pages/groups/new/components/create_group_description_details_spec.js57
-rw-r--r--spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap28
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js21
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js1
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js20
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js64
-rw-r--r--spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js12
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js72
-rw-r--r--spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js187
-rw-r--r--spec/frontend/pipeline_editor/components/validate/ci_validate_spec.js39
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_home_spec.js6
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js4
-rw-r--r--spec/frontend/pipeline_schedules/components/take_ownership_modal_spec.js54
-rw-r--r--spec/frontend/pipeline_wizard/components/editor_spec.js4
-rw-r--r--spec/frontend/pipeline_wizard/components/step_spec.js4
-rw-r--r--spec/frontend/pipeline_wizard/components/widgets/checklist_spec.js13
-rw-r--r--spec/frontend/pipelines/components/pipeline_tabs_spec.js4
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js2
-rw-r--r--spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js59
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js2
-rw-r--r--spec/frontend/pipelines/performance_insights_modal_spec.js25
-rw-r--r--spec/frontend/pipelines/pipeline_multi_actions_spec.js13
-rw-r--r--spec/frontend/pipelines/pipeline_url_spec.js4
-rw-r--r--spec/frontend/pipelines/pipelines_spec.js11
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js4
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js10
-rw-r--r--spec/frontend/projects/compare/components/app_spec.js3
-rw-r--r--spec/frontend/projects/compare/components/mock_data.js25
-rw-r--r--spec/frontend/projects/project_new_spec.js67
-rw-r--r--spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js17
-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/mock_data.js10
-rw-r--r--spec/frontend/projects/settings/branch_rules/rule_edit_spec.js61
-rw-r--r--spec/frontend/projects/settings/components/transfer_project_form_spec.js164
-rw-r--r--spec/frontend/prometheus_metrics/custom_metrics_spec.js48
-rw-r--r--spec/frontend/prometheus_metrics/prometheus_metrics_spec.js34
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap10
-rw-r--r--spec/frontend/releases/components/release_block_header_spec.js39
-rw-r--r--spec/frontend/reports/components/report_section_spec.js212
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js93
-rw-r--r--spec/frontend/repository/mock_data.js1
-rw-r--r--spec/frontend/right_sidebar_spec.js2
-rw-r--r--spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js2
-rw-r--r--spec/frontend/runner/admin_runner_show/admin_runner_show_app_spec.js13
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js214
-rw-r--r--spec/frontend/runner/components/cells/runner_summary_cell_spec.js13
-rw-r--r--spec/frontend/runner/components/registration/registration_token_spec.js27
-rw-r--r--spec/frontend/runner/components/runner_assigned_item_spec.js16
-rw-r--r--spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js101
-rw-r--r--spec/frontend/runner/components/runner_bulk_delete_spec.js176
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js6
-rw-r--r--spec/frontend/runner/components/runner_jobs_spec.js3
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js8
-rw-r--r--spec/frontend/runner/components/runner_pagination_spec.js138
-rw-r--r--spec/frontend/runner/components/runner_projects_spec.js1
-rw-r--r--spec/frontend/runner/components/stat/runner_count_spec.js4
-rw-r--r--spec/frontend/runner/components/stat/runner_single_stat_spec.js61
-rw-r--r--spec/frontend/runner/components/stat/runner_stats_spec.js37
-rw-r--r--spec/frontend/runner/components/stat/runner_status_stat_spec.js67
-rw-r--r--spec/frontend/runner/graphql/local_state_spec.js62
-rw-r--r--spec/frontend/runner/group_runner_show/group_runner_show_app_spec.js9
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js56
-rw-r--r--spec/frontend/runner/mock_data.js43
-rw-r--r--spec/frontend/runner/runner_search_utils_spec.js40
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js2
-rw-r--r--spec/frontend/sidebar/assignees_spec.js2
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js1
-rw-r--r--spec/frontend/sidebar/components/attention_requested_toggle_spec.js121
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js25
-rw-r--r--spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js5
-rw-r--r--spec/frontend/sidebar/components/incidents/escalation_status_spec.js5
-rw-r--r--spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js5
-rw-r--r--spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js36
-rw-r--r--spec/frontend/sidebar/mock_data.js12
-rw-r--r--spec/frontend/sidebar/reviewer_title_spec.js4
-rw-r--r--spec/frontend/sidebar/reviewers_spec.js64
-rw-r--r--spec/frontend/sidebar/sidebar_mediator_spec.js92
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap1
-rw-r--r--spec/frontend/surveys/merge_request_performance/app_spec.js9
-rw-r--r--spec/frontend/test_setup.js5
-rw-r--r--spec/frontend/user_popovers_spec.js218
-rw-r--r--spec/frontend/vue_merge_request_widget/components/action_buttons.js47
-rw-r--r--spec/frontend/vue_merge_request_widget/components/added_commit_message_spec.js26
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js (renamed from spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js (renamed from spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js (renamed from spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/humanized_text_spec.js (renamed from spec/frontend/vue_mr_widget/components/approvals/humanized_text_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js (renamed from spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js (renamed from spec/frontend/vue_mr_widget/components/artifacts_list_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/extensions/child_content_spec.js (renamed from spec/frontend/vue_mr_widget/components/extensions/child_content_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/extensions/index_spec.js (renamed from spec/frontend/vue_mr_widget/components/extensions/index_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/extensions/status_icon_spec.js (renamed from spec/frontend/vue_mr_widget/components/extensions/status_icon_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/extensions/utils_spec.js (renamed from spec/frontend/vue_mr_widget/components/extensions/utils_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_alert_message_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_author_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_container_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js227
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_rebase_spec.js245
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_related_links_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_status_icon_spec.js43
-rw-r--r--spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js (renamed from spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/pipeline_tour_mock_data.js (renamed from spec/frontend/vue_mr_widget/components/pipeline_tour_mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/review_app_link_spec.js (renamed from spec/frontend/vue_mr_widget/components/review_app_link_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap241
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap24
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap (renamed from spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/commit_edit_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js78
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_archived_spec.js26
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled_spec.js224
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js68
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_checking_spec.js27
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js39
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js135
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_conflicts_spec.js252
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_failed_to_merge_spec.js180
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js180
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_merging_spec.js61
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_missing_branch_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_not_allowed_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge_spec.js28
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js23
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js819
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_sha_mismatch_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_squash_before_merge_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js101
-rw-r--r--spec/frontend/vue_merge_request_widget/components/states/new_ready_to_merge_spec.js (renamed from spec/frontend/vue_mr_widget/components/states/new_ready_to_merge_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/mock_data.js (renamed from spec/frontend/vue_mr_widget/components/terraform/mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js (renamed from spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js (renamed from spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/app_spec.js19
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js167
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_list_spec.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_list_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js (renamed from spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js (renamed from spec/frontend/vue_mr_widget/extensions/test_report/index_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extensions/test_report/utils_spec.js (renamed from spec/frontend/vue_mr_widget/extensions/test_report/utils_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extentions/accessibility/index_spec.js (renamed from spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extentions/accessibility/mock_data.js (renamed from spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extentions/code_quality/index_spec.js (renamed from spec/frontend/vue_mr_widget/extentions/code_quality/index_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extentions/code_quality/mock_data.js (renamed from spec/frontend/vue_mr_widget/extentions/code_quality/mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/extentions/terraform/index_spec.js (renamed from spec/frontend/vue_mr_widget/extentions/terraform/index_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/mock_data.js (renamed from spec/frontend/vue_mr_widget/mock_data.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js (renamed from spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js1198
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/artifacts_list/actions_spec.js (renamed from spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/artifacts_list/getters_spec.js (renamed from spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/artifacts_list/mutations_spec.js (renamed from spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js104
-rw-r--r--spec/frontend/vue_merge_request_widget/stores/mr_widget_store_spec.js (renamed from spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js)0
-rw-r--r--spec/frontend/vue_merge_request_widget/test_extensions.js (renamed from spec/frontend/vue_mr_widget/test_extensions.js)0
-rw-r--r--spec/frontend/vue_mr_widget/components/added_commit_message_spec.js31
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/actions_spec.js47
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js227
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js292
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js60
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap145
-rw-r--r--spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap24
-rw-r--r--spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js78
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js31
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js328
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js68
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js31
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js63
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js136
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js252
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js158
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js235
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js74
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js28
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js30
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js905
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js103
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js1266
-rw-r--r--spec/frontend/vue_mr_widget/stores/get_state_key_spec.js126
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_details_spec.js6
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_metrics_spec.js4
-rw-r--r--spec/frontend/vue_shared/alert_details/alert_status_spec.js2
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js4
-rw-r--r--spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js4
-rw-r--r--spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/actions_button_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/alert_details_table_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/changed_file_icon_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/ci_icon_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/clipboard_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/clone_dropdown_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/color_picker/color_picker_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/commit_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/confirm_modal_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/dismissible_alert_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/dismissible_container_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js77
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/expand_button_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/file_icon_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/file_tree_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js44
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js8
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_contact_token_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/crm_organization_token_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/emoji_token_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/gitlab_version_check_spec.js31
-rw-r--r--spec/frontend/vue_shared/components/gl_modal_vuex_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/help_popover_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/integration_help_text_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/markdown/field_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js17
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/memory_graph_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js81
-rw-r--r--spec/frontend/vue_shared/components/navigation_tabs_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/notes/noteable_warning_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/notes/placeholder_note_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/pagination_links_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/project_avatar_spec.js36
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/code_instruction_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/details_row_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/history_item_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/registry/list_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/registry/metadata_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/registry_search_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/title_area_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/rich_timestamp_tooltip_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/security_reports/artifact_downloads/merge_request_artifact_download_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/security_reports/help_icon_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js32
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/sidebar/todo_button_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/source_editor_spec.js26
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/components/chunk_line_spec.js29
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/mock_data.js2
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/plugins/utils/gemspec_linker_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_spec.js3
-rw-r--r--spec/frontend/vue_shared/components/split_button_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/table_pagination_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/user_access_role_badge_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_new_spec.js45
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_image_spec.js64
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_new_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_old_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js64
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js95
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js10
-rw-r--r--spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js4
-rw-r--r--spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js14
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js48
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js12
-rw-r--r--spec/frontend/vue_shared/issuable/list/mock_data.js1
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js10
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js6
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js12
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js22
-rw-r--r--spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js4
-rw-r--r--spec/frontend/vue_shared/security_reports/security_reports_app_spec.js4
-rw-r--r--spec/frontend/whats_new/components/app_spec.js4
-rw-r--r--spec/frontend/whats_new/components/feature_spec.js9
-rw-r--r--spec/frontend/work_items/components/item_state_spec.js16
-rw-r--r--spec/frontend/work_items/components/item_title_spec.js2
-rw-r--r--spec/frontend/work_items/components/work_item_actions_spec.js85
-rw-r--r--spec/frontend/work_items/components/work_item_assignees_spec.js120
-rw-r--r--spec/frontend/work_items/components/work_item_detail_modal_spec.js134
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js87
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_menu_spec.js119
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_spec.js205
-rw-r--r--spec/frontend/work_items/components/work_item_state_spec.js16
-rw-r--r--spec/frontend/work_items/components/work_item_title_spec.js21
-rw-r--r--spec/frontend/work_items/components/work_item_type_icon_spec.js47
-rw-r--r--spec/frontend/work_items/components/work_item_weight_spec.js87
-rw-r--r--spec/frontend/work_items/mock_data.js218
-rw-r--r--spec/frontend/work_items/pages/work_item_detail_spec.js213
-rw-r--r--spec/frontend/work_items_hierarchy/components/app_spec.js8
-rw-r--r--spec/frontend/work_items_hierarchy/components/hierarchy_spec.js7
-rw-r--r--spec/frontend_integration/content_editor/content_editor_integration_spec.js68
-rw-r--r--spec/frontend_integration/fly_out_nav_browser_spec.js10
-rw-r--r--spec/frontend_integration/ide/helpers/start.js5
-rw-r--r--spec/frontend_integration/ide/ide_integration_spec.js4
-rw-r--r--spec/frontend_integration/snippets/snippets_notes_spec.js5
-rw-r--r--spec/frontend_integration/test_helpers/setup/setup_globals.js4
-rw-r--r--spec/graphql/features/feature_flag_spec.rb2
-rw-r--r--spec/graphql/graphql_triggers_spec.rb14
-rw-r--r--spec/graphql/mutations/ci/runner/bulk_delete_spec.rb91
-rw-r--r--spec/graphql/mutations/ci/runner/update_spec.rb3
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/update_spec.rb39
-rw-r--r--spec/graphql/mutations/merge_requests/set_labels_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/set_reviewers_spec.rb140
-rw-r--r--spec/graphql/mutations/releases/create_spec.rb6
-rw-r--r--spec/graphql/mutations/releases/delete_spec.rb2
-rw-r--r--spec/graphql/mutations/releases/update_spec.rb4
-rw-r--r--spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb63
-rw-r--r--spec/graphql/resolvers/crm/contacts_resolver_spec.rb21
-rw-r--r--spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/project_jobs_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/projects/fork_targets_resolver_spec.rb49
-rw-r--r--spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb2
-rw-r--r--spec/graphql/types/base_field_spec.rb10
-rw-r--r--spec/graphql/types/ci/group_variable_type_spec.rb9
-rw-r--r--spec/graphql/types/ci/instance_variable_type_spec.rb9
-rw-r--r--spec/graphql/types/ci/job_token_scope_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/manual_variable_type_spec.rb7
-rw-r--r--spec/graphql/types/ci/project_variable_type_spec.rb9
-rw-r--r--spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb24
-rw-r--r--spec/graphql/types/ci/runner_upgrade_status_type_enum_spec.rb24
-rw-r--r--spec/graphql/types/ci/variable_input_type_spec.rb11
-rw-r--r--spec/graphql/types/ci/variable_interface_spec.rb11
-rw-r--r--spec/graphql/types/ci/variable_type_spec.rb11
-rw-r--r--spec/graphql/types/customer_relations/contact_sort_enum_spec.rb28
-rw-r--r--spec/graphql/types/customer_relations/contact_state_counts_type_spec.rb17
-rw-r--r--spec/graphql/types/global_id_type_spec.rb6
-rw-r--r--spec/graphql/types/group_type_spec.rb51
-rw-r--r--spec/graphql/types/issue_type_spec.rb6
-rw-r--r--spec/graphql/types/namespace_type_spec.rb1
-rw-r--r--spec/graphql/types/notes/note_type_spec.rb1
-rw-r--r--spec/graphql/types/project_type_spec.rb6
-rw-r--r--spec/graphql/types/projects/service_type_enum_spec.rb1
-rw-r--r--spec/graphql/types/subscription_type_spec.rb1
-rw-r--r--spec/graphql/types/time_tracking/timelog_category_type_spec.rb22
-rw-r--r--spec/graphql/types/upload_type_spec.rb13
-rw-r--r--spec/graphql/types/user_type_spec.rb2
-rw-r--r--spec/graphql/types/work_item_type_spec.rb5
-rw-r--r--spec/graphql/types/work_items/widget_interface_spec.rb1
-rw-r--r--spec/graphql/types/work_items/widgets/assignees_input_type_spec.rb9
-rw-r--r--spec/graphql/types/work_items/widgets/labels_type_spec.rb11
-rw-r--r--spec/graphql/types/work_items/widgets/start_and_due_date_type_spec.rb11
-rw-r--r--spec/graphql/types/work_items/widgets/start_and_due_date_update_input_type_spec.rb9
-rw-r--r--spec/helpers/admin/identities_helper_spec.rb58
-rw-r--r--spec/helpers/application_helper_spec.rb8
-rw-r--r--spec/helpers/boards_helper_spec.rb3
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb8
-rw-r--r--spec/helpers/ci/runners_helper_spec.rb4
-rw-r--r--spec/helpers/commits_helper_spec.rb18
-rw-r--r--spec/helpers/form_helper_spec.rb81
-rw-r--r--spec/helpers/gitlab_script_tag_helper_spec.rb10
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb2
-rw-r--r--spec/helpers/groups_helper_spec.rb75
-rw-r--r--spec/helpers/issuables_description_templates_helper_spec.rb115
-rw-r--r--spec/helpers/issuables_helper_spec.rb48
-rw-r--r--spec/helpers/members_helper_spec.rb33
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb69
-rw-r--r--spec/helpers/namespaces_helper_spec.rb33
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb2
-rw-r--r--spec/helpers/nav/top_nav_helper_spec.rb12
-rw-r--r--spec/helpers/profiles_helper_spec.rb32
-rw-r--r--spec/helpers/projects/pipeline_helper_spec.rb8
-rw-r--r--spec/helpers/projects_helper_spec.rb39
-rw-r--r--spec/helpers/search_helper_spec.rb13
-rw-r--r--spec/helpers/storage_helper_spec.rb24
-rw-r--r--spec/helpers/users_helper_spec.rb19
-rw-r--r--spec/initializers/00_deprecations_spec.rb20
-rw-r--r--spec/initializers/0_log_deprecations_spec.rb78
-rw-r--r--spec/initializers/diagnostic_reports_spec.rb65
-rw-r--r--spec/initializers/global_id_spec.rb2
-rw-r--r--spec/initializers/memory_watchdog_spec.rb116
-rw-r--r--spec/lib/api/ci/helpers/runner_helpers_spec.rb4
-rw-r--r--spec/lib/api/entities/bulk_imports/entity_spec.rb1
-rw-r--r--spec/lib/api/entities/ci/job_request/image_spec.rb2
-rw-r--r--spec/lib/api/entities/ci/job_request/port_spec.rb2
-rw-r--r--spec/lib/api/entities/ci/job_request/service_spec.rb2
-rw-r--r--spec/lib/api/entities/project_spec.rb13
-rw-r--r--spec/lib/api/helpers/authentication_spec.rb2
-rw-r--r--spec/lib/api/helpers_spec.rb2
-rw-r--r--spec/lib/api/support/git_access_actor_spec.rb30
-rw-r--r--spec/lib/backup/database_spec.rb24
-rw-r--r--spec/lib/backup/gitaly_backup_spec.rb70
-rw-r--r--spec/lib/backup/manager_spec.rb24
-rw-r--r--spec/lib/banzai/cross_project_reference_spec.rb2
-rw-r--r--spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb6
-rw-r--r--spec/lib/banzai/filter/commit_trailers_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/task_list_filter_spec.rb34
-rw-r--r--spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb29
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb4
-rw-r--r--spec/lib/banzai/renderer_spec.rb2
-rw-r--r--spec/lib/bitbucket_server/connection_spec.rb2
-rw-r--r--spec/lib/bulk_imports/clients/http_spec.rb66
-rw-r--r--spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb4
-rw-r--r--spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb8
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb8
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb2
-rw-r--r--spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb10
-rw-r--r--spec/lib/container_registry/gitlab_api_client_spec.rb125
-rw-r--r--spec/lib/container_registry/tag_spec.rb35
-rw-r--r--spec/lib/feature_spec.rb4
-rw-r--r--spec/lib/gitlab/alert_management/payload/base_spec.rb40
-rw-r--r--spec/lib/gitlab/application_context_spec.rb2
-rw-r--r--spec/lib/gitlab/application_rate_limiter_spec.rb71
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb2
-rw-r--r--spec/lib/gitlab/audit/auditor_spec.rb258
-rw-r--r--spec/lib/gitlab/audit/ci_runner_token_author_spec.rb2
-rw-r--r--spec/lib/gitlab/audit/deploy_key_author_spec.rb17
-rw-r--r--spec/lib/gitlab/audit/null_author_spec.rb9
-rw-r--r--spec/lib/gitlab/audit/null_target_spec.rb25
-rw-r--r--spec/lib/gitlab/audit/target_spec.rb47
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb6
-rw-r--r--spec/lib/gitlab/auth/ip_rate_limiter_spec.rb22
-rw-r--r--spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb30
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb1
-rw-r--r--spec/lib/gitlab/auth_spec.rb71
-rw-r--r--spec/lib/gitlab/background_migration/backfill_ci_namespace_mirrors_spec.rb45
-rw-r--r--spec/lib/gitlab/background_migration/backfill_ci_project_mirrors_spec.rb46
-rw-r--r--spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/backfill_ci_runner_semver_spec.rb54
-rw-r--r--spec/lib/gitlab/background_migration/backfill_group_features_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb54
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb123
-rw-r--r--spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb93
-rw-r--r--spec/lib/gitlab/background_migration/batched_migration_job_spec.rb151
-rw-r--r--spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb15
-rw-r--r--spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb51
-rw-r--r--spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb58
-rw-r--r--spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb62
-rw-r--r--spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb66
-rw-r--r--spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/extract_project_topics_into_separate_table_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/migrate_project_taggings_context_from_tags_to_topics_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb13
-rw-r--r--spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb298
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb3
-rw-r--r--spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb51
-rw-r--r--spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb41
-rw-r--r--spec/lib/gitlab/background_task_spec.rb209
-rw-r--r--spec/lib/gitlab/bare_repository_import/repository_spec.rb19
-rw-r--r--spec/lib/gitlab/batch_pop_queueing_spec.rb2
-rw-r--r--spec/lib/gitlab/chat_name_token_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/ansi2html_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/ansi2json_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/artifacts/logger_spec.rb60
-rw-r--r--spec/lib/gitlab/ci/artifacts/metrics_spec.rb19
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb86
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/releaser_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb98
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/if_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/config/entry/image_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/entry/imageable_spec.rb81
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/release_spec.rb38
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/config/entry/service_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/entry/tags_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/normalizer_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb17
-rw-r--r--spec/lib/gitlab/ci/cron_parser_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb135
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb40
-rw-r--r--spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb132
-rw-r--r--spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb599
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb90
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/component_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/report_spec.rb54
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/reports_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/source_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/reports/security/reports_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/runner_releases_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/runner_upgrade_check_spec.rb45
-rw-r--r--spec/lib/gitlab/ci/status/bridge/common_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/status/build/canceled_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/build/created_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/build/manual_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/build/pending_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/build/skipped_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb5
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/trace/remote_checksum_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/variables/helpers_spec.rb113
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/result_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb72
-rw-r--r--spec/lib/gitlab/composer/cache_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/build_spec.rb4
-rw-r--r--spec/lib/gitlab/data_builder/issuable_spec.rb21
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/push_spec.rb1
-rw-r--r--spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb69
-rw-r--r--spec/lib/gitlab/database/async_indexes/migration_helpers_spec.rb38
-rw-r--r--spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb17
-rw-r--r--spec/lib/gitlab/database/async_indexes_spec.rb20
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb21
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb12
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb45
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb16
-rw-r--r--spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb2
-rw-r--r--spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb61
-rw-r--r--spec/lib/gitlab/database/background_migration/health_status_spec.rb45
-rw-r--r--spec/lib/gitlab/database/bulk_update_spec.rb3
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb10
-rw-r--r--spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb2
-rw-r--r--spec/lib/gitlab/database/load_balancing/session_spec.rb6
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb2
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb2
-rw-r--r--spec/lib/gitlab/database/load_balancing_spec.rb2
-rw-r--r--spec/lib/gitlab/database/lock_writes_manager_spec.rb123
-rw-r--r--spec/lib/gitlab/database/loose_foreign_keys_spec.rb28
-rw-r--r--spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb7
-rw-r--r--spec/lib/gitlab/database/migration_helpers/v2_spec.rb10
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb82
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb6
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb117
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb6
-rw-r--r--spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb12
-rw-r--r--spec/lib/gitlab/database/migrations/runner_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb15
-rw-r--r--spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb72
-rw-r--r--spec/lib/gitlab/database/partitioning_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb25
-rw-r--r--spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb2
-rw-r--r--spec/lib/gitlab/database/reindexing_spec.rb21
-rw-r--r--spec/lib/gitlab/database/shared_model_spec.rb2
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb4
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_spec.rb8
-rw-r--r--spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb14
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb2
-rw-r--r--spec/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512_spec.rb36
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb4
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb20
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb2
-rw-r--r--spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb2
-rw-r--r--spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/error_tracking/logger_spec.rb2
-rw-r--r--spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb20
-rw-r--r--spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb22
-rw-r--r--spec/lib/gitlab/exclusive_lease_helpers_spec.rb4
-rw-r--r--spec/lib/gitlab/file_markdown_link_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb79
-rw-r--r--spec/lib/gitlab/git/blame_spec.rb2
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb3
-rw-r--r--spec/lib/gitlab/git/branch_spec.rb23
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb10
-rw-r--r--spec/lib/gitlab/git/diff_collection_spec.rb4
-rw-r--r--spec/lib/gitlab/git/raw_diff_change_spec.rb2
-rw-r--r--spec/lib/gitlab/git/remote_repository_spec.rb61
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb73
-rw-r--r--spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb58
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb37
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb9
-rw-r--r--spec/lib/gitlab/git_access_spec.rb38
-rw-r--r--spec/lib/gitlab/git_spec.rb1
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb2
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb208
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb24
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb42
-rw-r--r--spec/lib/gitlab/github_import/client_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/events/base_importer_spec.rb15
-rw-r--r--spec/lib/gitlab/github_import/importer/events/changed_assignee_spec.rb95
-rw-r--r--spec/lib/gitlab/github_import/importer/events/changed_label_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/events/changed_milestone_spec.rb72
-rw-r--r--spec/lib/gitlab/github_import/importer/events/closed_spec.rb16
-rw-r--r--spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb40
-rw-r--r--spec/lib/gitlab/github_import/importer/events/renamed_spec.rb16
-rw-r--r--spec/lib/gitlab/github_import/importer/events/reopened_spec.rb16
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb36
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb122
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_importer_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/issuable_finder_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/parallel_scheduling_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/representation/issue_event_spec.rb81
-rw-r--r--spec/lib/gitlab/github_import/representation/issue_spec.rb15
-rw-r--r--spec/lib/gitlab/github_import/user_finder_spec.rb66
-rw-r--r--spec/lib/gitlab/global_id/deprecations_spec.rb15
-rw-r--r--spec/lib/gitlab/gpg_spec.rb4
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb34
-rw-r--r--spec/lib/gitlab/graphql/deprecation_spec.rb69
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb115
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_spec.rb95
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb415
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb595
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb118
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb135
-rw-r--r--spec/lib/gitlab/graphql/type_name_deprecations_spec.rb52
-rw-r--r--spec/lib/gitlab/graphs/commits_spec.rb2
-rw-r--r--spec/lib/gitlab/highlight_spec.rb2
-rw-r--r--spec/lib/gitlab/hook_data/group_builder_spec.rb3
-rw-r--r--spec/lib/gitlab/hook_data/group_member_builder_spec.rb3
-rw-r--r--spec/lib/gitlab/hook_data/key_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/hook_data/project_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/hook_data/project_member_builder_spec.rb3
-rw-r--r--spec/lib/gitlab/hook_data/subgroup_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/hook_data/user_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/http_io_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb168
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml16
-rw-r--r--spec/lib/gitlab/import_export/base/relation_factory_spec.rb24
-rw-r--r--spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb5
-rw-r--r--spec/lib/gitlab/import_export/group/tree_restorer_spec.rb16
-rw-r--r--spec/lib/gitlab/import_export/import_test_coverage_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb48
-rw-r--r--spec/lib/gitlab/import_export/log_util_spec.rb43
-rw-r--r--spec/lib/gitlab/import_export/project/relation_saver_spec.rb125
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb49
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb27
-rw-r--r--spec/lib/gitlab/import_export/remote_stream_upload_spec.rb232
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml16
-rw-r--r--spec/lib/gitlab/import_export/shared_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/version_checker_spec.rb2
-rw-r--r--spec/lib/gitlab/instrumentation_helper_spec.rb22
-rw-r--r--spec/lib/gitlab/jira/dvcs_spec.rb6
-rw-r--r--spec/lib/gitlab/jira_import/issues_importer_spec.rb43
-rw-r--r--spec/lib/gitlab/kubernetes/rollout_status_spec.rb2
-rw-r--r--spec/lib/gitlab/mail_room/mail_room_spec.rb4
-rw-r--r--spec/lib/gitlab/memory/jemalloc_spec.rb25
-rw-r--r--spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb124
-rw-r--r--spec/lib/gitlab/memory/reports_daemon_spec.rb136
-rw-r--r--spec/lib/gitlab/memory/watchdog_spec.rb139
-rw-r--r--spec/lib/gitlab/metrics/background_transaction_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/web_transaction_spec.rb2
-rw-r--r--spec/lib/gitlab/middleware/compressed_json_spec.rb6
-rw-r--r--spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb2
-rw-r--r--spec/lib/gitlab/octokit/middleware_spec.rb2
-rw-r--r--spec/lib/gitlab/otp_key_rotator_spec.rb2
-rw-r--r--spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb14
-rw-r--r--spec/lib/gitlab/pagination/keyset_spec.rb2
-rw-r--r--spec/lib/gitlab/phabricator_import/conduit/response_spec.rb2
-rw-r--r--spec/lib/gitlab/prometheus_client_spec.rb2
-rw-r--r--spec/lib/gitlab/quick_actions/extractor_spec.rb8
-rw-r--r--spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb2
-rw-r--r--spec/lib/gitlab/rack_attack/user_allowlist_spec.rb2
-rw-r--r--spec/lib/gitlab/redis/cache_spec.rb12
-rw-r--r--spec/lib/gitlab/redis/hll_spec.rb8
-rw-r--r--spec/lib/gitlab/redis/multi_store_spec.rb24
-rw-r--r--spec/lib/gitlab/reference_counter_spec.rb2
-rw-r--r--spec/lib/gitlab/regex_spec.rb8
-rw-r--r--spec/lib/gitlab/search/abuse_detection_spec.rb2
-rw-r--r--spec/lib/gitlab/search_context/builder_spec.rb2
-rw-r--r--spec/lib/gitlab/seeder_spec.rb40
-rw-r--r--spec/lib/gitlab/session_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_config_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb6
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb16
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb4
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb1
-rw-r--r--spec/lib/gitlab/slash_commands/deploy_spec.rb2
-rw-r--r--spec/lib/gitlab/spamcheck/client_spec.rb6
-rw-r--r--spec/lib/gitlab/ssh/commit_spec.rb82
-rw-r--r--spec/lib/gitlab/suggestions/file_suggestion_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb36
-rw-r--r--spec/lib/gitlab/tracking_spec.rb37
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb32
-rw-r--r--spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb4
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb2
-rw-r--r--spec/lib/gitlab/usage/service_ping_report_spec.rb8
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb43
-rw-r--r--spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb36
-rw-r--r--spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb21
-rw-r--r--spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb9
-rw-r--r--spec/lib/gitlab/usage_data_counters/work_item_activity_unique_counter_spec.rb8
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb6
-rw-r--r--spec/lib/gitlab/utils/batch_loader_spec.rb82
-rw-r--r--spec/lib/gitlab/utils/link_header_parser_spec.rb75
-rw-r--r--spec/lib/gitlab/utils/sanitize_node_link_spec.rb2
-rw-r--r--spec/lib/gitlab/utils/strong_memoize_spec.rb139
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb2
-rw-r--r--spec/lib/gitlab/utils_spec.rb4
-rw-r--r--spec/lib/gitlab/verify/uploads_spec.rb2
-rw-r--r--spec/lib/gitlab/version_info_spec.rb19
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb117
-rw-r--r--spec/lib/json_web_token/rsa_token_spec.rb5
-rw-r--r--spec/lib/marginalia_spec.rb18
-rw-r--r--spec/lib/mattermost/session_spec.rb2
-rw-r--r--spec/lib/microsoft_teams/notifier_spec.rb2
-rw-r--r--spec/lib/release_highlights/validator/entry_spec.rb20
-rw-r--r--spec/lib/release_highlights/validator_spec.rb2
-rw-r--r--spec/lib/security/report_schema_version_matcher_spec.rb44
-rw-r--r--spec/lib/sidebars/groups/menus/group_information_menu_spec.rb8
-rw-r--r--spec/lib/sidebars/menu_spec.rb2
-rw-r--r--spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb2
-rw-r--r--spec/lib/unnested_in_filters/rewriter_spec.rb29
-rw-r--r--spec/mailers/emails/admin_notification_spec.rb64
-rw-r--r--spec/mailers/emails/profile_spec.rb3
-rw-r--r--spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb48
-rw-r--r--spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb2
-rw-r--r--spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb2
-rw-r--r--spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb3
-rw-r--r--spec/migrations/20220124130028_dedup_runner_projects_spec.rb2
-rw-r--r--spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb4
-rw-r--r--spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb2
-rw-r--r--spec/migrations/20220506154054_create_sync_namespace_details_trigger_spec.rb76
-rw-r--r--spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb63
-rw-r--r--spec/migrations/20220524184149_create_sync_project_namespace_details_trigger_spec.rb73
-rw-r--r--spec/migrations/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent_spec.rb24
-rw-r--r--spec/migrations/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences_spec.rb22
-rw-r--r--spec/migrations/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb64
-rw-r--r--spec/migrations/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb64
-rw-r--r--spec/migrations/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb64
-rw-r--r--spec/migrations/20220725150127_update_jira_tracker_data_deployment_type_based_on_url_spec.rb58
-rw-r--r--spec/migrations/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics_spec.rb41
-rw-r--r--spec/migrations/20220802204737_remove_deactivated_user_highest_role_stats_spec.rb39
-rw-r--r--spec/migrations/associate_existing_dast_builds_with_variables_spec.rb70
-rw-r--r--spec/migrations/backfill_project_import_level_spec.rb29
-rw-r--r--spec/migrations/change_public_projects_cost_factor_spec.rb11
-rw-r--r--spec/migrations/clean_up_pending_builds_table_spec.rb2
-rw-r--r--spec/migrations/cleanup_mr_attention_request_todos_spec.rb46
-rw-r--r--spec/migrations/delete_security_findings_without_uuid_spec.rb2
-rw-r--r--spec/migrations/disable_job_token_scope_when_unused_spec.rb38
-rw-r--r--spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb2
-rw-r--r--spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb3
-rw-r--r--spec/migrations/schedule_backfilling_the_namespace_id_for_vulnerability_reads_spec.rb32
-rw-r--r--spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb44
-rw-r--r--spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb59
-rw-r--r--spec/migrations/schedule_populate_status_column_of_security_scans_spec.rb48
-rw-r--r--spec/migrations/start_backfill_ci_queuing_tables_spec.rb2
-rw-r--r--spec/models/active_session_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb7
-rw-r--r--spec/models/aws/role_spec.rb2
-rw-r--r--spec/models/board_spec.rb4
-rw-r--r--spec/models/chat_name_spec.rb4
-rw-r--r--spec/models/ci/bridge_spec.rb14
-rw-r--r--spec/models/ci/build_dependencies_spec.rb4
-rw-r--r--spec/models/ci/build_metadata_spec.rb13
-rw-r--r--spec/models/ci/build_runner_session_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb249
-rw-r--r--spec/models/ci/daily_build_group_report_result_spec.rb2
-rw-r--r--spec/models/ci/job_artifact_spec.rb14
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb311
-rw-r--r--spec/models/ci/processable_spec.rb2
-rw-r--r--spec/models/ci/runner_spec.rb65
-rw-r--r--spec/models/ci/runner_version_spec.rb9
-rw-r--r--spec/models/ci/secure_file_spec.rb1
-rw-r--r--spec/models/clusters/cluster_spec.rb4
-rw-r--r--spec/models/commit_signatures/ssh_signature_spec.rb2
-rw-r--r--spec/models/commit_status_spec.rb2
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb4
-rw-r--r--spec/models/concerns/chronic_duration_attribute_spec.rb12
-rw-r--r--spec/models/concerns/ci/artifactable_spec.rb24
-rw-r--r--spec/models/concerns/counter_attribute_spec.rb2
-rw-r--r--spec/models/concerns/cross_database_modification_spec.rb32
-rw-r--r--spec/models/concerns/database_event_tracking_spec.rb69
-rw-r--r--spec/models/concerns/expirable_spec.rb5
-rw-r--r--spec/models/concerns/issuable_spec.rb21
-rw-r--r--spec/models/concerns/nullify_if_blank_spec.rb2
-rw-r--r--spec/models/concerns/participable_spec.rb26
-rw-r--r--spec/models/concerns/project_features_compatibility_spec.rb6
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb2
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb12
-rw-r--r--spec/models/container_expiration_policy_spec.rb2
-rw-r--r--spec/models/container_repository_spec.rb184
-rw-r--r--spec/models/customer_relations/contact_spec.rb53
-rw-r--r--spec/models/customer_relations/contact_state_counts_spec.rb60
-rw-r--r--spec/models/data_list_spec.rb2
-rw-r--r--spec/models/deploy_key_spec.rb9
-rw-r--r--spec/models/design_management/version_spec.rb8
-rw-r--r--spec/models/environment_spec.rb231
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb46
-rw-r--r--spec/models/event_spec.rb26
-rw-r--r--spec/models/group_group_link_spec.rb52
-rw-r--r--spec/models/group_spec.rb44
-rw-r--r--spec/models/hooks/system_hook_spec.rb2
-rw-r--r--spec/models/hooks/web_hook_spec.rb12
-rw-r--r--spec/models/incident_management/issuable_escalation_status_spec.rb1
-rw-r--r--spec/models/incident_management/timeline_event_spec.rb15
-rw-r--r--spec/models/integration_spec.rb5
-rw-r--r--spec/models/integrations/bamboo_spec.rb1
-rw-r--r--spec/models/integrations/bugzilla_spec.rb1
-rw-r--r--spec/models/integrations/buildkite_spec.rb1
-rw-r--r--spec/models/integrations/campfire_spec.rb2
-rw-r--r--spec/models/integrations/chat_message/issue_message_spec.rb4
-rw-r--r--spec/models/integrations/chat_message/wiki_page_message_spec.rb2
-rw-r--r--spec/models/integrations/custom_issue_tracker_spec.rb1
-rw-r--r--spec/models/integrations/datadog_spec.rb16
-rw-r--r--spec/models/integrations/drone_ci_spec.rb1
-rw-r--r--spec/models/integrations/ewm_spec.rb1
-rw-r--r--spec/models/integrations/external_wiki_spec.rb1
-rw-r--r--spec/models/integrations/harbor_spec.rb4
-rw-r--r--spec/models/integrations/jira_spec.rb22
-rw-r--r--spec/models/integrations/microsoft_teams_spec.rb1
-rw-r--r--spec/models/integrations/pumble_spec.rb14
-rw-r--r--spec/models/integrations/slack_spec.rb17
-rw-r--r--spec/models/integrations/teamcity_spec.rb1
-rw-r--r--spec/models/issue_spec.rb179
-rw-r--r--spec/models/jira_import_state_spec.rb30
-rw-r--r--spec/models/lfs_object_spec.rb4
-rw-r--r--spec/models/loose_foreign_keys/deleted_record_spec.rb16
-rw-r--r--spec/models/member_spec.rb31
-rw-r--r--spec/models/members/group_member_spec.rb90
-rw-r--r--spec/models/members/member_role_spec.rb17
-rw-r--r--spec/models/members/project_member_spec.rb9
-rw-r--r--spec/models/merge_request/approval_removal_settings_spec.rb52
-rw-r--r--spec/models/merge_request_spec.rb107
-rw-r--r--spec/models/milestone_spec.rb4
-rw-r--r--spec/models/ml/candidate_metric_spec.rb9
-rw-r--r--spec/models/ml/candidate_param_spec.rb9
-rw-r--r--spec/models/ml/candidate_spec.rb12
-rw-r--r--spec/models/ml/experiment_spec.rb11
-rw-r--r--spec/models/namespace/detail_spec.rb40
-rw-r--r--spec/models/namespace/root_storage_statistics_spec.rb4
-rw-r--r--spec/models/namespace/traversal_hierarchy_spec.rb6
-rw-r--r--spec/models/namespace_spec.rb50
-rw-r--r--spec/models/namespaces/project_namespace_spec.rb8
-rw-r--r--spec/models/note_spec.rb74
-rw-r--r--spec/models/oauth_access_token_spec.rb68
-rw-r--r--spec/models/onboarding_progress_spec.rb2
-rw-r--r--spec/models/packages/cleanup/policy_spec.rb1
-rw-r--r--spec/models/packages/conan/metadatum_spec.rb2
-rw-r--r--spec/models/packages/package_file_spec.rb6
-rw-r--r--spec/models/packages/package_spec.rb6
-rw-r--r--spec/models/personal_access_token_spec.rb24
-rw-r--r--spec/models/postgresql/replication_slot_spec.rb2
-rw-r--r--spec/models/preloaders/labels_preloader_spec.rb2
-rw-r--r--spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb2
-rw-r--r--spec/models/project_spec.rb115
-rw-r--r--spec/models/project_statistics_spec.rb39
-rw-r--r--spec/models/projects/import_export/relation_export_spec.rb32
-rw-r--r--spec/models/projects/topic_spec.rb11
-rw-r--r--spec/models/protected_branch_spec.rb124
-rw-r--r--spec/models/release_highlight_spec.rb14
-rw-r--r--spec/models/release_spec.rb2
-rw-r--r--spec/models/releases/link_spec.rb2
-rw-r--r--spec/models/remote_mirror_spec.rb16
-rw-r--r--spec/models/repository_spec.rb40
-rw-r--r--spec/models/snippet_input_action_collection_spec.rb6
-rw-r--r--spec/models/snippet_spec.rb4
-rw-r--r--spec/models/u2f_registration_spec.rb106
-rw-r--r--spec/models/user_spec.rb444
-rw-r--r--spec/models/user_status_spec.rb26
-rw-r--r--spec/models/users/calloutable_spec.rb4
-rw-r--r--spec/models/users/in_product_marketing_email_spec.rb3
-rw-r--r--spec/models/users/project_callout_spec.rb24
-rw-r--r--spec/models/webauthn_registration_spec.rb1
-rw-r--r--spec/models/wiki_page/meta_spec.rb2
-rw-r--r--spec/models/work_item_spec.rb67
-rw-r--r--spec/models/work_items/parent_link_spec.rb64
-rw-r--r--spec/models/work_items/type_spec.rb11
-rw-r--r--spec/models/work_items/widgets/hierarchy_spec.rb6
-rw-r--r--spec/models/work_items/widgets/labels_spec.rb31
-rw-r--r--spec/models/work_items/widgets/start_and_due_date_spec.rb31
-rw-r--r--spec/policies/group_policy_spec.rb29
-rw-r--r--spec/policies/issuable_policy_spec.rb40
-rw-r--r--spec/policies/issue_policy_spec.rb55
-rw-r--r--spec/policies/namespaces/project_namespace_policy_spec.rb42
-rw-r--r--spec/policies/namespaces/user_namespace_policy_spec.rb2
-rw-r--r--spec/policies/project_hook_policy_spec.rb31
-rw-r--r--spec/policies/project_policy_spec.rb275
-rw-r--r--spec/policies/system_hook_policy_spec.rb29
-rw-r--r--spec/policies/timelog_policy_spec.rb2
-rw-r--r--spec/policies/upload_policy_spec.rb76
-rw-r--r--spec/policies/work_item_policy_spec.rb41
-rw-r--r--spec/presenters/alert_management/alert_presenter_spec.rb2
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb61
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb25
-rw-r--r--spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb2
-rw-r--r--spec/presenters/project_hook_presenter_spec.rb4
-rw-r--r--spec/presenters/project_member_presenter_spec.rb118
-rw-r--r--spec/requests/admin/broadcast_messages_controller_spec.rb18
-rw-r--r--spec/requests/admin/integrations_controller_spec.rb1
-rw-r--r--spec/requests/api/api_spec.rb50
-rw-r--r--spec/requests/api/boards_spec.rb6
-rw-r--r--spec/requests/api/branches_spec.rb5
-rw-r--r--spec/requests/api/bulk_imports_spec.rb93
-rw-r--r--spec/requests/api/ci/jobs_spec.rb2
-rw-r--r--spec/requests/api/ci/pipeline_schedules_spec.rb106
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb2
-rw-r--r--spec/requests/api/ci/runner/jobs_trace_spec.rb4
-rw-r--r--spec/requests/api/ci/runner/runners_post_spec.rb9
-rw-r--r--spec/requests/api/ci/secure_files_spec.rb6
-rw-r--r--spec/requests/api/ci/triggers_spec.rb8
-rw-r--r--spec/requests/api/ci/variables_spec.rb10
-rw-r--r--spec/requests/api/clusters/agents_spec.rb4
-rw-r--r--spec/requests/api/commits_spec.rb107
-rw-r--r--spec/requests/api/conan_instance_packages_spec.rb2
-rw-r--r--spec/requests/api/conan_project_packages_spec.rb2
-rw-r--r--spec/requests/api/dependency_proxy_spec.rb2
-rw-r--r--spec/requests/api/deployments_spec.rb84
-rw-r--r--spec/requests/api/doorkeeper_access_spec.rb6
-rw-r--r--spec/requests/api/go_proxy_spec.rb8
-rw-r--r--spec/requests/api/graphql/boards/board_list_issues_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/boards/board_lists_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/ci/instance_variables_spec.rb12
-rw-r--r--spec/requests/api/graphql/ci/manual_variables_spec.rb8
-rw-r--r--spec/requests/api/graphql/ci/pipelines_spec.rb29
-rw-r--r--spec/requests/api/graphql/ci/runners_spec.rb4
-rw-r--r--spec/requests/api/graphql/crm/contacts_spec.rb24
-rw-r--r--spec/requests/api/graphql/current_user/groups_query_spec.rb19
-rw-r--r--spec/requests/api/graphql/custom_emoji_query_spec.rb4
-rw-r--r--spec/requests/api/graphql/group/group_members_spec.rb18
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb81
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/add_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/boards/destroy_spec.rb11
-rw-r--r--spec/requests/api/graphql/mutations/ci/job_retry_spec.rb32
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/request_attention_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb106
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb65
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/note_spec.rb24
-rw-r--r--spec/requests/api/graphql/mutations/releases/create_spec.rb6
-rw-r--r--spec/requests/api/graphql/mutations/releases/update_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/remove_attention_request_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb6
-rw-r--r--spec/requests/api/graphql/mutations/timelogs/create_spec.rb48
-rw-r--r--spec/requests/api/graphql/mutations/timelogs/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/uploads/delete_spec.rb74
-rw-r--r--spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/work_items/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb223
-rw-r--r--spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/conan_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/helm_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/base_service_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb6
-rw-r--r--spec/requests/api/graphql/project/fork_targets_spec.rb69
-rw-r--r--spec/requests/api/graphql/project/jira_import_spec.rb14
-rw-r--r--spec/requests/api/graphql/project/project_members_spec.rb18
-rw-r--r--spec/requests/api/graphql/project/work_items_spec.rb2
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb96
-rw-r--r--spec/requests/api/graphql/work_item_spec.rb93
-rw-r--r--spec/requests/api/graphql_spec.rb53
-rw-r--r--spec/requests/api/group_variables_spec.rb8
-rw-r--r--spec/requests/api/groups_spec.rb2
-rw-r--r--spec/requests/api/helpers_spec.rb6
-rw-r--r--spec/requests/api/integrations_spec.rb1
-rw-r--r--spec/requests/api/internal/base_spec.rb39
-rw-r--r--spec/requests/api/internal/error_tracking_spec.rb2
-rw-r--r--spec/requests/api/internal/kubernetes_spec.rb178
-rw-r--r--spec/requests/api/internal/workhorse_spec.rb1
-rw-r--r--spec/requests/api/invitations_spec.rb2
-rw-r--r--spec/requests/api/issue_links_spec.rb25
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb44
-rw-r--r--spec/requests/api/markdown_spec.rb59
-rw-r--r--spec/requests/api/maven_packages_spec.rb35
-rw-r--r--spec/requests/api/members_spec.rb49
-rw-r--r--spec/requests/api/merge_requests_spec.rb125
-rw-r--r--spec/requests/api/metrics/dashboard/annotations_spec.rb2
-rw-r--r--spec/requests/api/notes_spec.rb2
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb14
-rw-r--r--spec/requests/api/nuget_group_packages_spec.rb2
-rw-r--r--spec/requests/api/pages/pages_spec.rb2
-rw-r--r--spec/requests/api/pages_domains_spec.rb4
-rw-r--r--spec/requests/api/personal_access_tokens_spec.rb4
-rw-r--r--spec/requests/api/project_attributes.yml2
-rw-r--r--spec/requests/api/project_import_spec.rb2
-rw-r--r--spec/requests/api/project_packages_spec.rb76
-rw-r--r--spec/requests/api/project_templates_spec.rb4
-rw-r--r--spec/requests/api/projects_spec.rb4
-rw-r--r--spec/requests/api/protected_branches_spec.rb62
-rw-r--r--spec/requests/api/pypi_packages_spec.rb4
-rw-r--r--spec/requests/api/release/links_spec.rb8
-rw-r--r--spec/requests/api/releases_spec.rb8
-rw-r--r--spec/requests/api/repositories_spec.rb26
-rw-r--r--spec/requests/api/search_spec.rb11
-rw-r--r--spec/requests/api/settings_spec.rb2
-rw-r--r--spec/requests/api/snippets_spec.rb10
-rw-r--r--spec/requests/api/topics_spec.rb16
-rw-r--r--spec/requests/api/unleash_spec.rb6
-rw-r--r--spec/requests/api/user_counts_spec.rb15
-rw-r--r--spec/requests/api/users_spec.rb14
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/groups/milestones_controller_spec.rb2
-rw-r--r--spec/requests/jira_connect/subscriptions_controller_spec.rb4
-rw-r--r--spec/requests/jwt_controller_spec.rb13
-rw-r--r--spec/requests/lfs_http_spec.rb14
-rw-r--r--spec/requests/oauth/tokens_controller_spec.rb2
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb6
-rw-r--r--spec/requests/projects/merge_requests/diffs_spec.rb189
-rw-r--r--spec/requests/projects/merge_requests_discussions_spec.rb275
-rw-r--r--spec/requests/projects/settings/packages_and_registries_controller_spec.rb70
-rw-r--r--spec/requests/rack_attack_global_spec.rb12
-rw-r--r--spec/requests/users/namespace_callouts_spec.rb57
-rw-r--r--spec/requests/users/project_callouts_spec.rb58
-rw-r--r--spec/routing/project_routing_spec.rb16
-rw-r--r--spec/rubocop/code_reuse_helpers_spec.rb60
-rw-r--r--spec/rubocop/cop/code_reuse/worker_spec.rb19
-rw-r--r--spec/rubocop/cop/gemspec/avoid_executing_git_spec.rb30
-rw-r--r--spec/rubocop/cop/gitlab/deprecate_track_redis_hll_event_spec.rb19
-rw-r--r--spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb4
-rw-r--r--spec/rubocop/cop/inject_enterprise_edition_module_spec.rb1
-rw-r--r--spec/rubocop/cop_todo_spec.rb124
-rw-r--r--spec/rubocop/formatter/todo_formatter_spec.rb12
-rw-r--r--spec/scripts/changed-feature-flags_spec.rb4
-rw-r--r--spec/scripts/lib/glfm/update_example_snapshots_spec.rb12
-rw-r--r--spec/scripts/trigger-build_spec.rb9
-rw-r--r--spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb4
-rw-r--r--spec/serializers/deploy_keys/deploy_key_entity_spec.rb4
-rw-r--r--spec/serializers/environment_serializer_spec.rb31
-rw-r--r--spec/serializers/group_access_token_entity_spec.rb57
-rw-r--r--spec/serializers/group_access_token_serializer_spec.rb28
-rw-r--r--spec/serializers/integrations/project_entity_spec.rb1
-rw-r--r--spec/serializers/issue_entity_spec.rb7
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb34
-rw-r--r--spec/serializers/merge_request_user_entity_spec.rb11
-rw-r--r--spec/serializers/personal_access_token_entity_spec.rb27
-rw-r--r--spec/serializers/personal_access_token_serializer_spec.rb21
-rw-r--r--spec/serializers/project_access_token_entity_spec.rb61
-rw-r--r--spec/serializers/project_access_token_serializer_spec.rb28
-rw-r--r--spec/services/alert_management/process_prometheus_alert_service_spec.rb1
-rw-r--r--spec/services/audit_events/build_service_spec.rb154
-rw-r--r--spec/services/auto_merge/base_service_spec.rb2
-rw-r--r--spec/services/auto_merge_service_spec.rb4
-rw-r--r--spec/services/branches/create_service_spec.rb142
-rw-r--r--spec/services/bulk_imports/create_service_spec.rb6
-rw-r--r--spec/services/bulk_imports/file_download_service_spec.rb35
-rw-r--r--spec/services/bulk_update_integration_service_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service/rules_spec.rb1028
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb815
-rw-r--r--spec/services/ci/deployments/destroy_service_spec.rb65
-rw-r--r--spec/services/ci/destroy_pipeline_service_spec.rb20
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb8
-rw-r--r--spec/services/ci/job_artifacts/destroy_batch_service_spec.rb9
-rw-r--r--spec/services/ci/list_config_variables_service_spec.rb4
-rw-r--r--spec/services/ci/parse_dotenv_artifact_service_spec.rb2
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb2
-rw-r--r--spec/services/ci/process_build_service_spec.rb2
-rw-r--r--spec/services/ci/register_job_service_spec.rb68
-rw-r--r--spec/services/ci/retry_job_service_spec.rb61
-rw-r--r--spec/services/ci/runners/assign_runner_service_spec.rb18
-rw-r--r--spec/services/ci/runners/bulk_delete_runners_service_spec.rb83
-rw-r--r--spec/services/ci/runners/process_runner_version_update_service_spec.rb80
-rw-r--r--spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb77
-rw-r--r--spec/services/ci/runners/register_runner_service_spec.rb150
-rw-r--r--spec/services/ci/runners/reset_registration_token_service_spec.rb13
-rw-r--r--spec/services/ci/runners/unassign_runner_service_spec.rb28
-rw-r--r--spec/services/ci/runners/unregister_runner_service_spec.rb7
-rw-r--r--spec/services/ci/runners/update_runner_service_spec.rb2
-rw-r--r--spec/services/ci/stuck_builds/drop_pending_service_spec.rb4
-rw-r--r--spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb2
-rw-r--r--spec/services/ci/track_failed_build_service_spec.rb56
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb18
-rw-r--r--spec/services/clusters/integrations/create_service_spec.rb2
-rw-r--r--spec/services/clusters/integrations/prometheus_health_check_service_spec.rb1
-rw-r--r--spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb2
-rw-r--r--spec/services/database/consistency_check_service_spec.rb53
-rw-r--r--spec/services/deployments/create_for_build_service_spec.rb2
-rw-r--r--spec/services/deployments/update_environment_service_spec.rb12
-rw-r--r--spec/services/design_management/delete_designs_service_spec.rb24
-rw-r--r--spec/services/design_management/generate_image_versions_service_spec.rb2
-rw-r--r--spec/services/git/branch_push_service_spec.rb4
-rw-r--r--spec/services/google_cloud/create_cloudsql_instance_service_spec.rb90
-rw-r--r--spec/services/google_cloud/enable_cloudsql_service_spec.rb39
-rw-r--r--spec/services/google_cloud/get_cloudsql_instances_service_spec.rb62
-rw-r--r--spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb68
-rw-r--r--spec/services/groups/create_service_spec.rb9
-rw-r--r--spec/services/groups/destroy_service_spec.rb15
-rw-r--r--spec/services/groups/merge_requests_count_service_spec.rb2
-rw-r--r--spec/services/groups/open_issues_count_service_spec.rb2
-rw-r--r--spec/services/groups/transfer_service_spec.rb37
-rw-r--r--spec/services/groups/update_service_spec.rb40
-rw-r--r--spec/services/groups/update_statistics_service_spec.rb2
-rw-r--r--spec/services/import/fogbugz_service_spec.rb2
-rw-r--r--spec/services/import/prepare_service_spec.rb66
-rw-r--r--spec/services/import/validate_remote_git_endpoint_service_spec.rb2
-rw-r--r--spec/services/incident_management/timeline_events/create_service_spec.rb83
-rw-r--r--spec/services/incident_management/timeline_events/update_service_spec.rb21
-rw-r--r--spec/services/issuable/common_system_notes_service_spec.rb45
-rw-r--r--spec/services/issues/clone_service_spec.rb26
-rw-r--r--spec/services/issues/create_service_spec.rb12
-rw-r--r--spec/services/issues/move_service_spec.rb12
-rw-r--r--spec/services/issues/prepare_import_csv_service_spec.rb51
-rw-r--r--spec/services/issues/referenced_merge_requests_service_spec.rb2
-rw-r--r--spec/services/issues/update_service_spec.rb58
-rw-r--r--spec/services/jira_import/start_import_service_spec.rb2
-rw-r--r--spec/services/lfs/push_service_spec.rb2
-rw-r--r--spec/services/markdown_content_rewriter_service_spec.rb2
-rw-r--r--spec/services/members/groups/creator_service_spec.rb5
-rw-r--r--spec/services/members/invite_service_spec.rb6
-rw-r--r--spec/services/merge_requests/approval_service_spec.rb112
-rw-r--r--spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb49
-rw-r--r--spec/services/merge_requests/close_service_spec.rb4
-rw-r--r--spec/services/merge_requests/create_approval_event_service_spec.rb22
-rw-r--r--spec/services/merge_requests/create_pipeline_service_spec.rb10
-rw-r--r--spec/services/merge_requests/execute_approval_hooks_service_spec.rb33
-rw-r--r--spec/services/merge_requests/handle_assignees_change_service_spec.rb8
-rw-r--r--spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb7
-rw-r--r--spec/services/merge_requests/mergeability/check_ci_status_service_spec.rb7
-rw-r--r--spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb7
-rw-r--r--spec/services/merge_requests/mergeability/check_draft_status_service_spec.rb7
-rw-r--r--spec/services/merge_requests/mergeability/check_open_status_service_spec.rb7
-rw-r--r--spec/services/merge_requests/mergeability/run_checks_service_spec.rb94
-rw-r--r--spec/services/merge_requests/push_options_handler_service_spec.rb22
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb2
-rw-r--r--spec/services/merge_requests/remove_attention_requested_service_spec.rb183
-rw-r--r--spec/services/merge_requests/request_attention_service_spec.rb220
-rw-r--r--spec/services/merge_requests/toggle_attention_requested_service_spec.rb188
-rw-r--r--spec/services/merge_requests/update_reviewers_service_spec.rb162
-rw-r--r--spec/services/merge_requests/update_service_spec.rb10
-rw-r--r--spec/services/milestones/transfer_service_spec.rb8
-rw-r--r--spec/services/notes/build_service_spec.rb10
-rw-r--r--spec/services/notes/copy_service_spec.rb6
-rw-r--r--spec/services/notes/create_service_spec.rb94
-rw-r--r--spec/services/notes/destroy_service_spec.rb26
-rw-r--r--spec/services/notes/update_service_spec.rb34
-rw-r--r--spec/services/notification_service_spec.rb45
-rw-r--r--spec/services/packages/composer/create_package_service_spec.rb2
-rw-r--r--spec/services/packages/create_dependency_service_spec.rb2
-rw-r--r--spec/services/packages/debian/extract_deb_metadata_service_spec.rb2
-rw-r--r--spec/services/packages/debian/extract_metadata_service_spec.rb7
-rw-r--r--spec/services/packages/debian/parse_debian822_service_spec.rb8
-rw-r--r--spec/services/packages/debian/sign_distribution_service_spec.rb2
-rw-r--r--spec/services/packages/helm/process_file_service_spec.rb2
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb8
-rw-r--r--spec/services/packages/npm/create_tag_service_spec.rb1
-rw-r--r--spec/services/packages/rubygems/dependency_resolver_service_spec.rb14
-rw-r--r--spec/services/pages/delete_service_spec.rb4
-rw-r--r--spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb2
-rw-r--r--spec/services/personal_access_tokens/revoke_service_spec.rb1
-rw-r--r--spec/services/projects/after_rename_service_spec.rb9
-rw-r--r--spec/services/projects/alerting/notify_service_spec.rb5
-rw-r--r--spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb2
-rw-r--r--spec/services/projects/create_service_spec.rb39
-rw-r--r--spec/services/projects/enable_deploy_key_service_spec.rb2
-rw-r--r--spec/services/projects/hashed_storage/migrate_repository_service_spec.rb6
-rw-r--r--spec/services/projects/hashed_storage/rollback_repository_service_spec.rb8
-rw-r--r--spec/services/projects/import_export/export_service_spec.rb23
-rw-r--r--spec/services/projects/import_export/relation_export_service_spec.rb121
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb2
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb2
-rw-r--r--spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb6
-rw-r--r--spec/services/projects/participants_service_spec.rb6
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb9
-rw-r--r--spec/services/projects/transfer_service_spec.rb43
-rw-r--r--spec/services/projects/update_service_spec.rb12
-rw-r--r--spec/services/projects/update_statistics_service_spec.rb2
-rw-r--r--spec/services/protected_branches/cache_service_spec.rb113
-rw-r--r--spec/services/protected_branches/create_service_spec.rb29
-rw-r--r--spec/services/protected_branches/destroy_service_spec.rb27
-rw-r--r--spec/services/protected_branches/update_service_spec.rb33
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb110
-rw-r--r--spec/services/releases/create_service_spec.rb8
-rw-r--r--spec/services/releases/destroy_service_spec.rb2
-rw-r--r--spec/services/releases/update_service_spec.rb2
-rw-r--r--spec/services/resource_access_tokens/create_service_spec.rb2
-rw-r--r--spec/services/resource_events/change_labels_service_spec.rb60
-rw-r--r--spec/services/search/group_service_spec.rb2
-rw-r--r--spec/services/security/ci_configuration/sast_parser_service_spec.rb1
-rw-r--r--spec/services/snippets/update_service_spec.rb2
-rw-r--r--spec/services/suggestions/apply_service_spec.rb2
-rw-r--r--spec/services/system_note_service_spec.rb86
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb108
-rw-r--r--spec/services/system_notes/merge_requests_service_spec.rb4
-rw-r--r--spec/services/system_notes/time_tracking_service_spec.rb174
-rw-r--r--spec/services/terraform/remote_state_handler_spec.rb2
-rw-r--r--spec/services/timelogs/create_service_spec.rb47
-rw-r--r--spec/services/timelogs/delete_service_spec.rb14
-rw-r--r--spec/services/todo_service_spec.rb15
-rw-r--r--spec/services/todos/destroy/design_service_spec.rb8
-rw-r--r--spec/services/todos/destroy/destroyed_issuable_service_spec.rb53
-rw-r--r--spec/services/topics/merge_service_spec.rb60
-rw-r--r--spec/services/uploads/destroy_service_spec.rb103
-rw-r--r--spec/services/users/create_service_spec.rb15
-rw-r--r--spec/services/users/dismiss_namespace_callout_service_spec.rb24
-rw-r--r--spec/services/users/dismiss_project_callout_service_spec.rb25
-rw-r--r--spec/services/users/update_service_spec.rb2
-rw-r--r--spec/services/web_hook_service_spec.rb4
-rw-r--r--spec/services/web_hooks/destroy_service_spec.rb67
-rw-r--r--spec/services/web_hooks/log_execution_service_spec.rb61
-rw-r--r--spec/services/webauthn/authenticate_service_spec.rb25
-rw-r--r--spec/services/work_items/create_and_link_service_spec.rb40
-rw-r--r--spec/services/work_items/create_from_task_service_spec.rb2
-rw-r--r--spec/services/work_items/create_service_spec.rb10
-rw-r--r--spec/services/work_items/parent_links/create_service_spec.rb28
-rw-r--r--spec/services/work_items/parent_links/destroy_service_spec.rb11
-rw-r--r--spec/services/work_items/update_service_spec.rb119
-rw-r--r--spec/services/work_items/widgets/assignees_service/update_service_spec.rb116
-rw-r--r--spec/services/work_items/widgets/description_service/update_service_spec.rb94
-rw-r--r--spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb26
-rw-r--r--spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb62
-rw-r--r--spec/services/work_items/widgets/weight_service/update_service_spec.rb36
-rw-r--r--spec/spec_helper.rb27
-rw-r--r--spec/support/database/cross-join-allowlist.yml7
-rw-r--r--spec/support/database/gitlab_schemas_validate_connection.rb17
-rw-r--r--spec/support/database/multiple_databases.rb20
-rw-r--r--spec/support/finder_collection_allowlist.yml2
-rw-r--r--spec/support/helpers/api_helpers.rb13
-rw-r--r--spec/support/helpers/ci/template_helpers.rb4
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb25
-rw-r--r--spec/support/helpers/dns_helpers.rb25
-rw-r--r--spec/support/helpers/features/blob_spec_helpers.rb8
-rw-r--r--spec/support/helpers/features/invite_members_modal_helper.rb43
-rw-r--r--spec/support/helpers/features/runners_helpers.rb (renamed from spec/support/helpers/features/runner_helpers.rb)0
-rw-r--r--spec/support/helpers/features/source_editor_spec_helpers.rb5
-rw-r--r--spec/support/helpers/gitaly_setup.rb14
-rw-r--r--spec/support/helpers/global_id_deprecation_helpers.rb8
-rw-r--r--spec/support/helpers/graphql_helpers.rb8
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb21
-rw-r--r--spec/support/helpers/lfs_http_helpers.rb4
-rw-r--r--spec/support/helpers/login_helpers.rb4
-rw-r--r--spec/support/helpers/query_recorder.rb2
-rw-r--r--spec/support/helpers/rack_attack_spec_helpers.rb6
-rw-r--r--spec/support/helpers/redis_commands/recorder.rb34
-rw-r--r--spec/support/helpers/runner_releases_helper.rb22
-rw-r--r--spec/support/helpers/stub_member.rb8
-rw-r--r--spec/support/helpers/stub_method_calls.rb2
-rw-r--r--spec/support/helpers/stubbed_member.rb28
-rw-r--r--spec/support/helpers/type_name_deprecation_helpers.rb15
-rw-r--r--spec/support/matchers/event_store.rb4
-rw-r--r--spec/support/matchers/markdown_matchers.rb4
-rw-r--r--spec/support/shared_contexts/bulk_imports_requests_shared_context.rb14
-rw-r--r--spec/support/shared_contexts/features/integrations/integrations_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/fixtures/analytics_shared_context.rb1
-rw-r--r--spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb8
-rw-r--r--spec/support/shared_contexts/markdown_snapshot_shared_examples.rb5
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb1
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb1
-rw-r--r--spec/support/shared_contexts/policies/project_policy_table_shared_context.rb57
-rw-r--r--spec/support/shared_contexts/upload_type_check_shared_context.rb14
-rw-r--r--spec/support/shared_examples/attention_request_cache_invalidation_examples.rb15
-rw-r--r--spec/support/shared_examples/boards/destroy_service_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/components/pajamas_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/controllers/search_cross_project_authorization_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/controllers/search_external_authorization_service_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb21
-rw-r--r--spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb80
-rw-r--r--spec/support/shared_examples/features/access_tokens_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/content_editor_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/features/inviting_members_shared_examples.rb110
-rw-r--r--spec/support/shared_examples/features/multiple_assignees_widget_mr_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/trial_email_validation_shared_example.rb59
-rw-r--r--spec/support/shared_examples/features/user_views_tag_shared_examples.rb34
-rw-r--r--spec/support/shared_examples/features/variable_list_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/graphql/mutations/timelogs/create_shared_examples.rb97
-rw-r--r--spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb34
-rw-r--r--spec/support/shared_examples/graphql/notes_creation_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb41
-rw-r--r--spec/support/shared_examples/models/chat_integration_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb64
-rw-r--r--spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/issuable_link_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb19
-rw-r--r--spec/support/shared_examples/models/project_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/models/taskable_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/namespaces/traversal_scope_examples.rb16
-rw-r--r--spec/support/shared_examples/policies/group_project_namespace_policy_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/requests/api/discussions_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/notes_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb47
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/services/boards/lists_move_service_shared_examples.rb120
-rw-r--r--spec/support/shared_examples/services/issuable_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/services/snowplow_tracking_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/services/timelogs/create_service_shared_examples.rb89
-rw-r--r--spec/support/shared_examples/services/work_items/create_task_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb31
-rw-r--r--spec/support_specs/database/prevent_cross_joins_spec.rb2
-rw-r--r--spec/support_specs/helpers/redis_commands/recorder_spec.rb128
-rw-r--r--spec/tasks/dev_rake_spec.rb25
-rw-r--r--spec/tasks/gitlab/background_migrations_rake_spec.rb4
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb13
-rw-r--r--spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb3
-rw-r--r--spec/tasks/gitlab/db/lock_writes_rake_spec.rb80
-rw-r--r--spec/tasks/gitlab/db/validate_config_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb8
-rw-r--r--spec/tasks/gitlab/password_rake_spec.rb9
-rw-r--r--spec/tasks/gitlab/web_hook_rake_spec.rb4
-rw-r--r--spec/tooling/danger/customer_success_spec.rb91
-rw-r--r--spec/tooling/graphql/docs/renderer_spec.rb122
-rw-r--r--spec/tooling/lib/tooling/find_codeowners_spec.rb43
-rw-r--r--spec/tooling/quality/test_level_spec.rb4
-rw-r--r--spec/uploaders/avatar_uploader_spec.rb2
-rw-r--r--spec/uploaders/design_management/design_v432x230_uploader_spec.rb2
-rw-r--r--spec/uploaders/favicon_uploader_spec.rb8
-rw-r--r--spec/uploaders/object_storage_spec.rb18
-rw-r--r--spec/views/admin/identities/index.html.haml_spec.rb70
-rw-r--r--spec/views/devise/sessions/new.html.haml_spec.rb94
-rw-r--r--spec/views/groups/group_members/index.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb5
-rw-r--r--spec/views/projects/blob/_viewer.html.haml_spec.rb1
-rw-r--r--spec/views/projects/pages/new.html.haml_spec.rb42
-rw-r--r--spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb4
-rw-r--r--spec/workers/archive_trace_worker_spec.rb31
-rw-r--r--spec/workers/build_finished_worker_spec.rb88
-rw-r--r--spec/workers/build_hooks_worker_spec.rb4
-rw-r--r--spec/workers/ci/build_finished_worker_spec.rb21
-rw-r--r--spec/workers/ci/cancel_pipeline_worker_spec.rb50
-rw-r--r--spec/workers/ci/runners/process_runner_version_update_worker_spec.rb48
-rw-r--r--spec/workers/ci/runners/reconcile_existing_runner_versions_cron_worker_spec.rb45
-rw-r--r--spec/workers/ci/track_failed_build_worker_spec.rb28
-rw-r--r--spec/workers/concerns/limited_capacity/job_tracker_spec.rb2
-rw-r--r--spec/workers/concerns/waitable_worker_spec.rb40
-rw-r--r--spec/workers/database/batched_background_migration/ci_database_worker_spec.rb2
-rw-r--r--spec/workers/database/batched_background_migration_worker_spec.rb2
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb1
-rw-r--r--spec/workers/gitlab/github_import/stage/import_issue_events_worker_spec.rb53
-rw-r--r--spec/workers/merge_requests/create_approval_event_worker_spec.rb51
-rw-r--r--spec/workers/merge_requests/create_approval_note_worker_spec.rb52
-rw-r--r--spec/workers/merge_requests/execute_approval_hooks_worker_spec.rb57
-rw-r--r--spec/workers/merge_requests/resolve_todos_after_approval_worker_spec.rb56
-rw-r--r--spec/workers/new_issue_worker_spec.rb10
-rw-r--r--spec/workers/packages/cleanup/execute_policy_worker_spec.rb2
-rw-r--r--spec/workers/pages/invalidate_domain_cache_worker_spec.rb112
-rw-r--r--spec/workers/post_receive_spec.rb6
-rw-r--r--spec/workers/project_cache_worker_spec.rb2
-rw-r--r--spec/workers/projects/import_export/relation_export_worker_spec.rb36
-rw-r--r--spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb8
-rw-r--r--spec/workers/update_project_statistics_worker_spec.rb28
-rw-r--r--spec/workers/users/deactivate_dormant_users_worker_spec.rb21
-rw-r--r--storybook/yarn.lock6
-rw-r--r--tests.yml4
-rwxr-xr-xtooling/bin/qa/package_and_qa_check45
-rwxr-xr-xtooling/bin/qa/run_qa_check45
-rw-r--r--tooling/config/CODEOWNERS.yml26
-rw-r--r--tooling/danger/customer_success.rb45
-rw-r--r--tooling/danger/product_intelligence.rb2
-rw-r--r--tooling/danger/project_helper.rb2
-rw-r--r--tooling/graphql/docs/helper.rb5
-rw-r--r--tooling/lib/tooling/find_codeowners.rb92
-rw-r--r--tooling/lib/tooling/helm3_client.rb4
-rw-r--r--tooling/lib/tooling/test_map_packer.rb2
-rw-r--r--tooling/overcommit/Gemfile8
-rw-r--r--tooling/overcommit/Gemfile.lock83
-rw-r--r--tooling/overcommit/Makefile7
-rw-r--r--tooling/quality/test_level.rb1
-rw-r--r--vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml2
-rw-r--r--vendor/gems/error_tracking_open_api/README.md18
-rw-r--r--vendor/gems/error_tracking_open_api/docs/ErrorsApi.md36
-rw-r--r--vendor/gems/error_tracking_open_api/docs/EventsApi.md27
-rw-r--r--vendor/gems/error_tracking_open_api/docs/ProjectsApi.md9
-rw-r--r--vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/errors_api.rb8
-rw-r--r--vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/events_api.rb6
-rw-r--r--vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/projects_api.rb2
-rw-r--r--vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api_client.rb1
-rw-r--r--vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/configuration.rb7
-rw-r--r--vendor/gems/ipynbdiff/.gitlab-ci.yml2
-rw-r--r--vendor/gems/mail-smtp_pool/.gitlab-ci.yml6
-rw-r--r--vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml28
-rw-r--r--vendor/gems/omniauth-azure-oauth2/CHANGELOG.md31
-rw-r--r--vendor/gems/omniauth-azure-oauth2/Gemfile8
-rw-r--r--vendor/gems/omniauth-azure-oauth2/Gemfile.lock73
-rw-r--r--vendor/gems/omniauth-azure-oauth2/LICENSE22
-rw-r--r--vendor/gems/omniauth-azure-oauth2/README.md161
-rw-r--r--vendor/gems/omniauth-azure-oauth2/Rakefile6
-rw-r--r--vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb31
-rw-r--r--vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb1
-rw-r--r--vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb1
-rw-r--r--vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb5
-rw-r--r--vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb73
-rw-r--r--vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec25
-rw-r--r--vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb332
-rw-r--r--vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb2
-rw-r--r--vendor/gems/omniauth-cas3/.gitlab-ci.yml28
-rw-r--r--vendor/gems/omniauth-cas3/Gemfile4
-rw-r--r--vendor/gems/omniauth-cas3/Gemfile.lock64
-rw-r--r--vendor/gems/omniauth-cas3/LICENSE23
-rw-r--r--vendor/gems/omniauth-cas3/README.md134
-rw-r--r--vendor/gems/omniauth-cas3/Rakefile15
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb1
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb2
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb5
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb222
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb73
-rw-r--r--vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb103
-rw-r--r--vendor/gems/omniauth-cas3/omniauth-cas3.gemspec27
-rw-r--r--vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml4
-rw-r--r--vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml14
-rw-r--r--vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml16
-rw-r--r--vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb127
-rw-r--r--vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb55
-rw-r--r--vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb250
-rw-r--r--vendor/gems/omniauth-cas3/spec/spec_helper.rb13
-rw-r--r--vendor/gems/omniauth-gitlab/.gitlab-ci.yml8
-rw-r--r--vendor/gems/omniauth_crowd/.gitlab-ci.yml8
-rw-r--r--vendor/gems/omniauth_crowd/Gemfile.lock86
-rw-r--r--vendor/gems/omniauth_crowd/omniauth_crowd.gemspec2
-rw-r--r--vendor/project_templates/hugo.tar.gzbin1048450 -> 26755 bytes
-rw-r--r--workhorse/go.mod44
-rw-r--r--workhorse/go.sum86
-rw-r--r--yarn.lock3699
5482 files changed, 189286 insertions, 105856 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index d268d73e6a6..af2f1d88938 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -53,7 +53,6 @@ rules:
- '^$'
- '^variables$'
- 'attrs?$'
- '@gitlab/vue-prefer-dollar-scopedslots': error
no-param-reassign:
- error
- props: true
@@ -174,3 +173,10 @@ overrides:
'@graphql-eslint/no-anonymous-operations': error
'@graphql-eslint/unique-operation-name': error
'@graphql-eslint/require-id-when-available': error
+ '@graphql-eslint/no-unused-variables': error
+ '@graphql-eslint/no-unused-fragments': error
+ '@graphql-eslint/no-duplicate-fields': error
+ - files:
+ - 'spec/contracts/consumer/**/*'
+ rules:
+ '@gitlab/require-i18n-strings': off
diff --git a/.gitignore b/.gitignore
index bdd3ac98876..0bd718f254b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,8 +90,6 @@ package-lock.json
/coverage-frontend/
jsdoc/
**/tmp/rubocop_cache/**
-.overcommit.yml
-.overcommit.yml.backup
.projections.json
/qa/.rakeTasks
webpack-dev-server.json
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0c06df88b3f..486da5bb906 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -84,7 +84,7 @@ variables:
GIT_SUBMODULE_STRATEGY: "none"
GET_SOURCES_ATTEMPTS: "3"
DEBIAN_VERSION: "bullseye"
- CHROME_VERSION: "101"
+ CHROME_VERSION: "103"
DOCKER_VERSION: "20.10.14"
RUBY_VERSION: "2.7"
@@ -114,6 +114,7 @@ variables:
DOCS_REVIEW_APPS_DOMAIN: "35.193.151.162.nip.io"
DOCS_GITLAB_REPO_SUFFIX: "ee"
+ REVIEW_APPS_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/ruby-3.0:gcloud-383-kubectl-1.23-helm-3.5"
REVIEW_APPS_DOMAIN: "gitlab-review.app"
REVIEW_APPS_GCP_PROJECT: "gitlab-review-apps"
REVIEW_APPS_GCP_REGION: "us-central1"
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 777c5c54ea5..6019fe636a8 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -7,7 +7,7 @@
*.rake @gitlab-org/maintainers/rails-backend
^[Frontend]
-*.scss @annabeldunstone @gitlab-org/maintainers/frontend
+*.scss @gitlab-org/maintainers/frontend
*.js @gitlab-org/maintainers/frontend
/app/assets/ @gitlab-org/maintainers/frontend
/ee/app/assets/ @gitlab-org/maintainers/frontend
@@ -173,7 +173,7 @@ Dangerfile @gl-quality/eng-prod
/config/dependency_decisions.yml @gitlab-org/legal-reviewers
^[Workhorse]
-/workhorse/ @jacobvosmaer-gitlab @nick.thomas @nolith @patrickbajao
+/workhorse/ @jacobvosmaer-gitlab @nolith @patrickbajao
[Application Security]
/app/assets/javascripts/lib/dompurify.js @gitlab-com/gl-security/appsec
@@ -242,7 +242,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/lfs/index.md @aqualls
/doc/administration/libravatar.md @axil
/doc/administration/load_balancer.md @axil
-/doc/administration/logs.md @msedlakjakubowski
+/doc/administration/logs/index.md @msedlakjakubowski
/doc/administration/maintenance_mode/index.md @axil
/doc/administration/merge_request_diffs.md @aqualls
/doc/administration/monitoring/ @msedlakjakubowski
@@ -283,7 +283,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/administration/timezone.md @axil
/doc/administration/troubleshooting/ @axil
/doc/administration/troubleshooting/elasticsearch.md @sselhorn
-/doc/administration/troubleshooting/group_saml_scim.md @eread
/doc/administration/troubleshooting/postgresql.md @aqualls
/doc/administration/uploads.md @axil
/doc/administration/user_settings.md @eread
@@ -494,7 +493,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/ci/unit_test_reports.md @marcel.amirault
/doc/ci/variables/ @marcel.amirault
/doc/ci/yaml/ @marcel.amirault
-/doc/development/adding_database_indexes.md @aqualls
/doc/development/application_limits.md @axil
/doc/development/approval_rules.md @aqualls
/doc/development/audit_event_guide/index.md @eread
@@ -513,12 +511,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/code_intelligence/index.md @aqualls
/doc/development/contributing/ @sselhorn
/doc/development/contributing/merge_request_workflow.md @aqualls
-/doc/development/creating_enums.md @aqualls
-/doc/development/database_debugging.md @aqualls
-/doc/development/database_query_comments.md @aqualls
/doc/development/database_review.md @aqualls
/doc/development/database/ @aqualls
-/doc/development/db_dump.md @aqualls
/doc/development/developing_with_solargraph.md @aqualls
/doc/development/diffs.md @aqualls
/doc/development/distributed_tracing.md @msedlakjakubowski
@@ -539,7 +533,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/feature_flags/controls.md @sselhorn
/doc/development/feature_flags/index.md @sselhorn
/doc/development/filtering_by_label.md @msedlakjakubowski
-/doc/development/foreign_keys.md @aqualls
/doc/development/geo.md @axil
/doc/development/geo/framework.md @axil
/doc/development/git_object_deduplication.md @eread
@@ -553,7 +546,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/image_scaling.md @sselhorn
/doc/development/import_export.md @eread
/doc/development/index.md @sselhorn
-/doc/development/insert_into_tables_in_batches.md @aqualls
/doc/development/integrations/ @kpaizee
/doc/development/integrations/codesandbox.md @sselhorn
/doc/development/integrations/secure_partner_integration.md @rdickenson
@@ -562,39 +554,28 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/internal_users.md @sselhorn
/doc/development/issuable-like-models.md @msedlakjakubowski
/doc/development/issue_types.md @msedlakjakubowski
-/doc/development/iterating_tables_in_batches.md @aqualls
/doc/development/kubernetes.md @sselhorn
/doc/development/lfs.md @aqualls
-/doc/development/licensed_feature_availability.md @sselhorn
+/doc/development/ee_features.md @fneill
/doc/development/logging.md @msedlakjakubowski
/doc/development/maintenance_mode.md @axil
-/doc/development/new_fe_guide/modules/widget_extensions.md @aqualls
-/doc/development/new_fe_guide/tips.md @sselhorn
/doc/development/omnibus.md @axil
-/doc/development/ordering_table_columns.md @aqualls
/doc/development/packages/ @claytoncornell
/doc/development/permissions.md @eread
/doc/development/policies.md @eread
/doc/development/product_qualified_lead_guide/index.md @kpaizee
/doc/development/project_templates.md @fneill
/doc/development/prometheus_metrics.md @msedlakjakubowski
-/doc/development/query_performance.md @aqualls
-/doc/development/query_recorder.md @aqualls
/doc/development/real_time.md @msedlakjakubowski
/doc/development/secure_coding_guidelines.md @sselhorn
-/doc/development/serializing_data.md @aqualls
/doc/development/service_ping/ @claytoncornell
-/doc/development/single_table_inheritance.md @aqualls
/doc/development/snowplow/ @claytoncornell
/doc/development/spam_protection_and_captcha/ @eread
/doc/development/sql.md @aqualls
-/doc/development/swapping_tables.md @aqualls
/doc/development/testing_guide/best_practices.md @sselhorn
/doc/development/testing_guide/end_to_end/best_practices.md @sselhorn
-/doc/development/understanding_explain_plans.md @aqualls
/doc/development/value_stream_analytics.md @fneill
/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md @fneill
-/doc/development/verifying_database_capabilities.md @aqualls
/doc/development/wikis.md @aqualls
/doc/development/work_items_widgets.md @msedlakjakubowski
/doc/development/work_items.md @msedlakjakubowski
@@ -618,7 +599,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/operations/feature_flags.md @rdickenson
/doc/operations/product_analytics.md @claytoncornell
/doc/policy/alpha-beta-support.md @axil
-/doc/policy/maintenance.md @axil
+/doc/policy/maintenance.md @axil @gitlab-org/delivery
/doc/raketasks/ @axil
/doc/raketasks/generate_sample_prometheus_data.md @msedlakjakubowski
/doc/raketasks/migrate_snippets.md @aqualls
@@ -710,6 +691,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/group/saml_sso/group_managed_accounts.md @eread
/doc/user/group/saml_sso/index.md @eread
/doc/user/group/saml_sso/scim_setup.md @eread
+/doc/user/group/saml_sso/example_saml_config.md @eread
/doc/user/group/settings/group_access_tokens.md @eread
/doc/user/group/settings/import_export.md @eread
/doc/user/group/subgroups/index.md @fneill
@@ -804,250 +786,391 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/workspace/index.md @fneill
[Authentication and Authorization]
-/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/authentication/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/ide/components/shared/tokened_input.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/invite_members/components/members_token_select.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/ldap/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/oauth/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/password_prompt/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/projects/settings/topics/components/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/related_issues/components/issue_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/runner/components/registration/registration_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/runner/components/search_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/token_access/components/ @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/token_access/index.js @gitlab-org/manage/authentication-and-authorization
-/app/assets/stylesheets/page_bundles/profile_two_factor_auth.scss @gitlab-org/manage/authentication-and-authorization
-/app/controllers/admin/impersonation_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/access_tokens_actions.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/authenticates_with_two_factor.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/enforces_admin_authentication.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/enforces_two_factor_authentication.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/oauth_applications.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/project_unauthorized.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/sessionless_authentication.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/snippet_authorizations.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/concerns/workhorse_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/groups/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/ldap/ @gitlab-org/manage/authentication-and-authorization
-/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization
-/app/controllers/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/profiles/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/profiles/personal_access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/profiles/two_factor_auths_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/profiles/webauthn_registrations_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/projects/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/finders/groups/projects_requiring_authorizations_refresh/ @gitlab-org/manage/authentication-and-authorization
-/app/finders/personal_access_tokens_finder.rb @gitlab-org/manage/authentication-and-authorization
-/app/helpers/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
-/app/helpers/auth_helper.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/authentication_event.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/admin_changed_password_notifier.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/mirror_authentication.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/select_for_project_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/token_authenticatable.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/token_authenticatable_strategies/ @gitlab-org/manage/authentication-and-authorization
-/app/models/oauth_access_grant.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/project_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/token_with_iv.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/webauthn_registration.rb @gitlab-org/manage/authentication-and-authorization
-/app/policies/personal_access_token_policy.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/access_token_validation_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/auth/ @gitlab-org/manage/authentication-and-authorization
-/app/services/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization
-/app/services/chat_names/authorize_user_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/services/projects/move_project_authorizations_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/services/todos/destroy/unauthorized_features_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/users/authorized_build_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/users/authorized_create_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/users/refresh_authorized_projects_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/webauthn/ @gitlab-org/manage/authentication-and-authorization
-/app/validators/json_schemas/cluster_agent_authorization_configuration.json @gitlab-org/manage/authentication-and-authorization
-/app/views/admin/application_settings/_external_authorization_service_form.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/views/authentication/ @gitlab-org/manage/authentication-and-authorization
-/app/views/ci/token_access/ @gitlab-org/manage/authentication-and-authorization
-/app/views/dashboard/projects/_zero_authorized_projects.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/password_change.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/password_change.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/password_change_by_admin.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/password_change_by_admin.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/reset_password_instructions.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/mailer/reset_password_instructions.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/passwords/ @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/shared/_omniauth_box.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/shared/_signup_omniauth_provider_list.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/shared/_signup_omniauth_providers.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/shared/_signup_omniauth_providers_top.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/doorkeeper/authorizations/ @gitlab-org/manage/authentication-and-authorization
-/app/views/doorkeeper/authorized_applications/ @gitlab-org/manage/authentication-and-authorization
-/app/views/errors/omniauth_error.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/groups/settings/_resource_access_token_creation.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/groups/settings/_two_factor_auth.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/views/layouts/oauth_error.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_about_to_expire_email.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_about_to_expire_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_created_email.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_created_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_expired_email.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/notify/access_token_expired_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/passwords/ @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization
-/app/views/projects/mirrors/_authentication_method.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/_no_password.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/members/_two_factor_auth_badge.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/tokens/ @gitlab-org/manage/authentication-and-authorization
-/app/workers/authorized_keys_worker.rb @gitlab-org/manage/authentication-and-authorization
-/app/workers/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization
-/app/workers/authorized_projects_worker.rb @gitlab-org/manage/authentication-and-authorization
-/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/application_settings_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/async_only_project_authorizations_refresh.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/enforce_auth_checks_on_uploads.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/forti_authenticator.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/forti_token_cloud.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/groups_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/omniauth_login_minimal_scopes.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/projects_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/skip_group_share_unlink_auth_refresh.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/update_oauth_registration_flow.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/development/webauthn.yml @gitlab-org/manage/authentication-and-authorization
-/config/feature_flags/ops/block_password_auth_for_saml_users.yml @gitlab-org/manage/authentication-and-authorization
-/config/initializers/01_secret_token.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/devise_dynamic_password_length_validation.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/devise_password_length.rb.example @gitlab-org/manage/authentication-and-authorization
-/config/initializers/gitlab_shell_secret_token.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/omniauth.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/rails_host_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/rails_host_authorization_gitpod.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers/webauthn.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb @gitlab-org/manage/authentication-and-authorization
-/config/initializers_before_autoloader/100_patch_omniauth_saml.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/audit_events/components/tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/audit_events/token_utils.js @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/groups/settings/components/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/pages/groups/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/pipelines/components/pipelines_list/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/requirements/components/tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/saml_providers/scim_token_service.js @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/saml_sso/components/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_auth.vue @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/concerns/ee/authenticates_with_two_factor.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/concerns/ee/enforces_two_factor_authentication.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/concerns/saml_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/ee/ldap/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/ee/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/ee/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/groups/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/groups/scim_oauth_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/omniauth_kerberos_spnego_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/finders/auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/helpers/ee/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/helpers/ee/auth_helper.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/helpers/ee/personal_access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/models/concerns/password_complexity.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/models/ee/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/models/ee/project_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/models/scim_oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/serializers/scim_oauth_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/security/token_revocation_service.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/validators/password/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/admin/application_settings/_personal_access_token_expiration_policy.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/groups/_personal_access_token_expiration_policy.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/groups/sso/_authorize_pane.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/notify/policy_revoked_personal_access_tokens_email.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/notify/policy_revoked_personal_access_tokens_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/oauth/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/_personal_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/_project_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/project_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/workers/auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
-/ee/config/routes/oauth.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/ee/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/lib/ee/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/authority_analyzer.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/geo/oauth/ @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/kerberos/ @gitlab-org/manage/authentication-and-authorization
-/ee/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization
-/ee/lib/system_check/geo/authorized_keys_check.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/system_check/geo/authorized_keys_flag_check.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/ci/reset_token_result.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/impersonation_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/impersonation_token_with_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/personal_access_token_with_details.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/personal_access_token_with_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/resource_access_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/entities/resource_access_token_with_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/helpers/authentication.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/helpers/packages/basic_auth_helpers.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/personal_access_tokens.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/resource_access_tokens.rb @gitlab-org/manage/authentication-and-authorization
-/lib/api/support/token_with_expiration.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/api_authentication/ @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/auth.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/authorized_keys.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/background_migration/encrypt_static_object_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/background_migration/expire_o_auth_tokens.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/background_migration/migrate_u2f_webauthn.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/chat_name_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/ci/pipeline/expression/token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/external_authorization/ @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/external_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/graphql/authorize/ @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/jwt_authenticatable.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/jwt_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/lfs_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/mail_room/ @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/project_authorizations.rb @gitlab-org/manage/authentication-and-authorization
-/lib/json_web_token/ @gitlab-org/manage/authentication-and-authorization
-/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization
-/lib/system_check/app/authorized_keys_permission_check.rb @gitlab-org/manage/authentication-and-authorization
-/lib/system_check/incoming_email/imap_authentication_check.rb @gitlab-org/manage/authentication-and-authorization
-/lib/tasks/gitlab/password.rake @gitlab-org/manage/authentication-and-authorization
-/lib/tasks/tokens.rake @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/authentication/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/ide/components/shared/tokened_input.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/invite_members/components/members_token_select.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/ldap/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/oauth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/profiles/password_prompt/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/projects/settings/topics/components/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/related_issues/components/issue_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/runner/components/registration/registration_token.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/runner/components/search_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/token_access/components/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/javascripts/token_access/index.js @gitlab-org/manage/authentication-and-authorization/approvers
+/app/assets/stylesheets/page_bundles/profile_two_factor_auth.scss @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/admin/impersonation_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/access_tokens_actions.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/authenticates_with_two_factor.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/enforces_admin_authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/enforces_two_factor_authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/oauth_applications.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/project_unauthorized.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/sessionless_authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/snippet_authorizations.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/concerns/workhorse_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/groups/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/ldap/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/profiles/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/profiles/personal_access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/profiles/two_factor_auths_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/profiles/webauthn_registrations_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/controllers/projects/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/finders/groups/projects_requiring_authorizations_refresh/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/finders/personal_access_tokens_finder.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/helpers/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/helpers/auth_helper.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/authentication_event.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/concerns/admin_changed_password_notifier.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/concerns/mirror_authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/concerns/select_for_project_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/concerns/token_authenticatable.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/concerns/token_authenticatable_strategies/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/oauth_access_grant.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/project_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/token_with_iv.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/models/webauthn_registration.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/policies/personal_access_token_policy.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/access_token_validation_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/chat_names/authorize_user_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/projects/move_project_authorizations_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/todos/destroy/unauthorized_features_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/users/authorized_build_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/users/authorized_create_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/users/refresh_authorized_projects_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/services/webauthn/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/validators/json_schemas/cluster_agent_authorization_configuration.json @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/admin/application_settings/_external_authorization_service_form.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/authentication/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/ci/token_access/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/dashboard/projects/_zero_authorized_projects.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/password_change.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/password_change.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/password_change_by_admin.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/password_change_by_admin.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/reset_password_instructions.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/mailer/reset_password_instructions.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/passwords/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/shared/_omniauth_box.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/shared/_signup_omniauth_provider_list.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/shared/_signup_omniauth_providers.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/devise/shared/_signup_omniauth_providers_top.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/doorkeeper/authorizations/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/doorkeeper/authorized_applications/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/errors/omniauth_error.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/groups/settings/_resource_access_token_creation.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/groups/settings/_two_factor_auth.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/layouts/oauth_error.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_about_to_expire_email.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_about_to_expire_email.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_created_email.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_created_email.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_expired_email.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/notify/access_token_expired_email.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/profiles/passwords/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/projects/mirrors/_authentication_method.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/shared/_no_password.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/shared/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/shared/members/_two_factor_auth_badge.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/app/views/shared/tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/workers/authorized_keys_worker.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/workers/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization/approvers
+/app/workers/authorized_projects_worker.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/access_token_pagination.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/application_settings_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/enforce_auth_checks_on_uploads.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/forti_authenticator.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/forti_token_cloud.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/groups_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/pbkdf2_password_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/pbkdf2_password_encryption_write.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/projects_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/skip_group_share_unlink_auth_refresh.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/update_oauth_registration_flow.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/development/webauthn.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/feature_flags/ops/block_password_auth_for_saml_users.yml @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/01_secret_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/devise_dynamic_password_length_validation.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/devise_password_length.rb.example @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/gitlab_shell_secret_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/omniauth.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/rails_host_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/rails_host_authorization_gitpod.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers/webauthn.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/config/initializers_before_autoloader/100_patch_omniauth_saml.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/audit_events/components/tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/audit_events/token_utils.js @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/groups/settings/components/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/pages/admin/application_settings/general/components/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/pages/groups/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/pages/passwords/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/pages/profiles/passwords/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/password/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/pipelines/components/pipelines_list/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/requirements/components/tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/runner/components/search_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/saml_providers/scim_token_service.js @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/saml_sso/components/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_auth.vue @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/concerns/ee/authenticates_with_two_factor.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/concerns/ee/enforces_two_factor_authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/concerns/saml_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/ee/ldap/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/ee/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/ee/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/groups/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/groups/scim_oauth_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/controllers/omniauth_kerberos_spnego_controller.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/finders/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/helpers/ee/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/helpers/ee/auth_helper.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/helpers/ee/personal_access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/models/concerns/password_complexity.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/models/ee/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/models/ee/project_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/models/scim_oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/serializers/scim_oauth_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/services/ee/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/services/ee/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/services/ee/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/services/security/token_revocation_service.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/validators/password/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/admin/application_settings/_personal_access_token_expiration_policy.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.text.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/groups/_personal_access_token_expiration_policy.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/groups/sso/_authorize_pane.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/notify/policy_revoked_personal_access_tokens_email.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/notify/policy_revoked_personal_access_tokens_email.text.erb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/oauth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/shared/_password_requirements_list.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/shared/credentials_inventory/_personal_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/shared/credentials_inventory/_project_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/shared/credentials_inventory/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/views/shared/credentials_inventory/project_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/workers/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/config/routes/oauth.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/ee/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/ee/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/gitlab/authority_analyzer.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/gitlab/geo/oauth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/gitlab/kerberos/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/system_check/geo/authorized_keys_check.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/ee/lib/system_check/geo/authorized_keys_flag_check.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/ci/reset_token_result.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/impersonation_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/impersonation_token_with_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/personal_access_token_with_details.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/personal_access_token_with_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/resource_access_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/entities/resource_access_token_with_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/helpers/authentication.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/helpers/packages/basic_auth_helpers.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/personal_access_tokens.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/resource_access_tokens.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/api/support/token_with_expiration.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/api_authentication/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/auth.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/authorized_keys.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/background_migration/encrypt_static_object_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/background_migration/expire_o_auth_tokens.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/background_migration/migrate_u2f_webauthn.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/chat_name_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/ci/pipeline/expression/token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/external_authorization/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/external_authorization.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/grape_logging/loggers/token_logger.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/graphql/authorize/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/jwt_authenticatable.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/jwt_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/lfs_token.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/mail_room/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/gitlab/project_authorizations.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/json_web_token/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/system_check/app/authorized_keys_permission_check.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/system_check/incoming_email/imap_authentication_check.rb @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/tasks/gitlab/password.rake @gitlab-org/manage/authentication-and-authorization/approvers
+/lib/tasks/tokens.rake @gitlab-org/manage/authentication-and-authorization/approvers
+
+[Compliance]
+/ee/app/services/audit_events/build_service.rb @gitlab-org/manage/compliance
+/ee/spec/services/audit_events/custom_audit_event_service_spec.rb @gitlab-org/manage/compliance
+/app/models/audit_event.rb @gitlab-org/manage/compliance
+/app/services/audit_event_service.rb @gitlab-org/manage/compliance
+/app/services/concerns/audit_event_save_type.rb @gitlab-org/manage/compliance
+/app/views/profiles/audit_log.html.haml @gitlab-org/manage/compliance
+/data/deprecations/14-3-repository-push-audit-events.yml @gitlab-org/manage/compliance
+/data/removals/15_0/removal_manage_repository_push_audit_event.yml @gitlab-org/manage/compliance
+/db/docs/audit_events.yml @gitlab-org/manage/compliance
+/db/docs/audit_events_external_audit_event_destinations.yml @gitlab-org/manage/compliance
+/db/docs/audit_events_streaming_headers.yml @gitlab-org/manage/compliance
+/db/migrate/20210819185500_create_external_audit_event_destinations_table.rb @gitlab-org/manage/compliance
+/db/migrate/20220524141800_create_audit_events_streaming_headers.rb @gitlab-org/manage/compliance
+/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb @gitlab-org/manage/compliance
+/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb @gitlab-org/manage/compliance
+/doc/administration/audit_event_streaming.md @gitlab-org/manage/compliance
+/doc/administration/audit_events.md @gitlab-org/manage/compliance
+/doc/administration/audit_reports.md @gitlab-org/manage/compliance
+/doc/administration/auditor_users.md @gitlab-org/manage/compliance
+/doc/api/audit_events.md @gitlab-org/manage/compliance
+/doc/api/graphql/audit_report.md @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_app.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_export_button.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_filter.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_log.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_stream.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/audit_events_table.vue @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/components/tokens/shared/ @gitlab-org/manage/compliance
+/ee/app/assets/javascripts/audit_events/init_audit_events.js @gitlab-org/manage/compliance
+/ee/app/controllers/admin/audit_log_reports_controller.rb @gitlab-org/manage/compliance
+/ee/app/controllers/admin/audit_logs_controller.rb @gitlab-org/manage/compliance
+/ee/app/controllers/concerns/audit_events/audit_events_params.rb @gitlab-org/manage/compliance
+/ee/app/controllers/groups/audit_events_controller.rb @gitlab-org/manage/compliance
+/ee/app/controllers/projects/audit_events_controller.rb @gitlab-org/manage/compliance
+/ee/app/finders/audit_event_finder.rb @gitlab-org/manage/compliance
+/ee/app/graphql/types/audit_events/external_audit_event_destination_type.rb @gitlab-org/manage/compliance
+/ee/app/helpers/audit_events_helper.rb @gitlab-org/manage/compliance
+/ee/app/helpers/auditor_user_helper.rb @gitlab-org/manage/compliance
+/ee/app/models/audit_events/external_audit_event_destination.rb @gitlab-org/manage/compliance
+/ee/app/models/concerns/auditable.rb @gitlab-org/manage/compliance
+/ee/app/models/ee/audit_event.rb @gitlab-org/manage/compliance
+/ee/app/policies/audit_events/external_audit_event_destination_policy.rb @gitlab-org/manage/compliance
+/ee/app/presenters/audit_event_presenter.rb @gitlab-org/manage/compliance
+/ee/app/serializers/audit_event_entity.rb @gitlab-org/manage/compliance
+/ee/app/serializers/audit_event_serializer.rb @gitlab-org/manage/compliance
+/ee/app/services/ci/audit_variable_change_service.rb @gitlab-org/manage/compliance
+/ee/app/services/ee/audit_event_service.rb @gitlab-org/manage/compliance
+/ee/app/views/admin/users/_auditor_access_level_radio.html.haml @gitlab-org/manage/compliance
+/ee/app/views/admin/users/_auditor_user_badge.html.haml @gitlab-org/manage/compliance
+/ee/app/views/shared/icons/_icon_audit_events_purple.svg @gitlab-org/manage/compliance
+/ee/app/views/shared/promotions/_promote_audit_events.html.haml @gitlab-org/manage/compliance
+/ee/app/workers/audit_events/audit_event_streaming_worker.rb @gitlab-org/manage/compliance
+/ee/config/events/1652263097_groups__audit_events__index_click_streams_tab.yml @gitlab-org/manage/compliance
+/ee/config/events/202108302307_admin_audit_logs_index_click_date_range_button.yml @gitlab-org/manage/compliance
+/ee/config/events/202108302307_groups__audit_events_controller_search_audit_event.yml @gitlab-org/manage/compliance
+/ee/config/events/202108302307_profiles_controller_search_audit_event.yml @gitlab-org/manage/compliance
+/ee/config/events/202108302307_projects__audit_events_controller_search_audit_event.yml @gitlab-org/manage/compliance
+/ee/config/events/202111041910_admin__audit_logs_controller_search_audit_event.yml @gitlab-org/manage/compliance
+/ee/config/feature_flags/development/audit_event_streaming_git_operations.yml @gitlab-org/manage/compliance
+/ee/config/feature_flags/development/audit_log_group_level.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_28d/20210216183930_g_compliance_audit_events_monthly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_28d/20210216183934_i_compliance_audit_events_monthly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_28d/20210216183942_a_compliance_audit_events_api_monthly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_28d/20211130085433_g_manage_compliance_audit_event_destinations.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183906_g_compliance_audit_events.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183908_i_compliance_audit_events.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183912_a_compliance_audit_events_api.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183928_g_compliance_audit_events_weekly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183932_i_compliance_audit_events_weekly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_7d/20210216183940_a_compliance_audit_events_api_weekly.yml @gitlab-org/manage/compliance
+/ee/config/metrics/counts_all/20211130085433_g_manage_compliance_audit_event_destinations.yml @gitlab-org/manage/compliance
+/ee/lib/api/audit_events.rb @gitlab-org/manage/compliance
+/ee/lib/audit/external_status_check_changes_auditor.rb @gitlab-org/manage/compliance
+/ee/lib/audit/group_merge_request_approval_setting_changes_auditor.rb @gitlab-org/manage/compliance
+/ee/lib/audit/group_push_rules_changes_auditor.rb @gitlab-org/manage/compliance
+/ee/lib/ee/api/entities/audit_event.rb @gitlab-org/manage/compliance
+/ee/lib/ee/audit/ @gitlab-org/manage/compliance
+/ee/lib/ee/gitlab/audit/ @gitlab-org/manage/compliance
+/ee/spec/controllers/admin/audit_log_reports_controller_spec.rb @gitlab-org/manage/compliance
+/ee/spec/controllers/admin/audit_logs_controller_spec.rb @gitlab-org/manage/compliance
+/ee/spec/controllers/groups/audit_events_controller_spec.rb @gitlab-org/manage/compliance
+/ee/spec/controllers/projects/audit_events_controller_spec.rb @gitlab-org/manage/compliance
+/ee/spec/factories/audit_events/external_audit_event_destinations.rb @gitlab-org/manage/compliance
+/ee/spec/features/admin/admin_audit_logs_spec.rb @gitlab-org/manage/compliance
+/ee/spec/features/groups/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/features/projects/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/finders/audit_event_finder_spec.rb @gitlab-org/manage/compliance
+/ee/spec/fixtures/api/schemas/public_api/v4/audit_event.json @gitlab-org/manage/compliance
+/ee/spec/fixtures/api/schemas/public_api/v4/audit_events.json @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/__snapshots__/ @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_app_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_export_button_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_filter_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_logs_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_stream_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/audit_events_table_spec.js @gitlab-org/manage/compliance
+/ee/spec/frontend/audit_events/components/tokens/shared/ @gitlab-org/manage/compliance
+/ee/spec/graphql/types/audit_events/exterrnal_audit_event_destination_type_spec.rb @gitlab-org/manage/compliance
+/ee/spec/helpers/audit_events_helper_spec.rb @gitlab-org/manage/compliance
+/ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb @gitlab-org/manage/compliance
+/ee/spec/lib/audit/group_merge_request_approval_setting_changes_auditor_spec.rb @gitlab-org/manage/compliance
+/ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb @gitlab-org/manage/compliance
+/ee/spec/lib/ee/audit/ @gitlab-org/manage/compliance
+/ee/spec/lib/gitlab/audit/auditor_spec.rb @gitlab-org/manage/compliance
+/ee/spec/models/audit_events/external_audit_event_destination_spec.rb @gitlab-org/manage/compliance
+/ee/spec/models/concerns/auditable_spec.rb @gitlab-org/manage/compliance
+/ee/spec/models/ee/audit_event_spec.rb @gitlab-org/manage/compliance
+/ee/spec/presenters/audit_event_presenter_spec.rb @gitlab-org/manage/compliance
+/ee/spec/requests/admin/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/requests/api/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/requests/api/graphql/group/external_audit_event_destinations_spec.rb @gitlab-org/manage/compliance
+/ee/spec/requests/groups/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/requests/projects/audit_events_spec.rb @gitlab-org/manage/compliance
+/ee/spec/serializers/audit_event_entity_spec.rb @gitlab-org/manage/compliance
+/ee/spec/serializers/audit_event_serializer_spec.rb @gitlab-org/manage/compliance
+/ee/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance
+/ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb @gitlab-org/manage/compliance
+/ee/spec/support/shared_contexts/audit_event_queue_shared_context.rb @gitlab-org/manage/compliance
+/ee/spec/support/shared_examples/audit/ @gitlab-org/manage/compliance
+/ee/spec/support/shared_examples/features/audit_events_filter_shared_examples.rb @gitlab-org/manage/compliance
+/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb @gitlab-org/manage/compliance
+/ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb @gitlab-org/manage/compliance
+/lib/gitlab/audit/auditor.rb @gitlab-org/manage/compliance
+/lib/gitlab/audit_json_logger.rb @gitlab-org/manage/compliance
+/spec/factories/audit_events.rb @gitlab-org/manage/compliance
+/spec/lib/gitlab/audit/auditor_spec.rb @gitlab-org/manage/compliance
+/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb @gitlab-org/manage/compliance
+/spec/models/audit_event_spec.rb @gitlab-org/manage/compliance
+/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance
+/spec/services/concerns/audit_event_save_type_spec.rb @gitlab-org/manage/compliance
+/spec/support/shared_examples/sends_git_audit_streaming_event_shared_examples.rb @gitlab-org/manage/compliance
+/spec/views/profiles/audit_log.html.haml_spec.rb @gitlab-org/manage/compliance
+/vendor/project_templates/hipaa_audit_protocol.tar.gz @gitlab-org/manage/compliance
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 8c49d5c212a..1d0218f4bd7 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -65,12 +65,6 @@ compile-test-assets as-if-foss:
- .frontend:rules:compile-test-assets-as-if-foss
- .as-if-foss
-compile-test-assets as-if-jh:
- extends:
- - compile-test-assets
- - .frontend:rules:compile-test-assets-as-if-jh
- needs: ["add-jh-folder"]
-
update-assets-compile-production-cache:
extends:
- compile-production-assets
@@ -144,24 +138,12 @@ rspec-all frontend_fixture:
rspec-all frontend_fixture as-if-foss:
extends:
- .frontend-fixtures-base
- - .frontend:rules:default-frontend-jobs-as-if-foss
+ - .frontend:rules:frontend_fixture-as-if-foss
- .as-if-foss
needs:
- !reference [.frontend-fixtures-base, needs]
- "compile-test-assets as-if-foss"
-# Builds FOSS, EE, and JH fixtures in the EE project, with the `jh/` folder added (due to `as-if-jh`).
-rspec-all frontend_fixture as-if-jh:
- extends:
- - .frontend-fixtures-base
- - .frontend:rules:default-frontend-jobs-as-if-jh
- needs:
- - !reference [.frontend-fixtures-base, needs]
- - "compile-test-assets as-if-jh"
- - "add-jh-folder"
- script:
- - echo "This job is currently doing nothing since there's no specific JH fixtures yet. To enable this job, remove this line."
-
graphql-schema-dump:
variables:
SETUP_DB: "false"
@@ -194,7 +176,10 @@ graphql-schema-dump as-if-foss:
# Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true"
+ USE_BUNDLE_INSTALL: "false"
+ SETUP_DB: "false"
before_script:
+ - !reference [.default-before_script, before_script]
- *yarn-install
stage: test
@@ -230,6 +215,17 @@ jest minimal:
script:
- run_timed_command "yarn jest:ci:minimal"
+jest minimal as-if-foss:
+ extends:
+ - .jest-base
+ - .frontend:rules:jest:minimal:as-if-foss
+ - .as-if-foss
+ needs:
+ - "rspec-all frontend_fixture as-if-foss"
+ - "detect-tests"
+ script:
+ - run_timed_command "yarn jest:ci:minimal"
+
jest-integration:
extends:
- .frontend-test-base
@@ -248,14 +244,6 @@ jest-as-if-foss:
needs: ["rspec-all frontend_fixture as-if-foss"]
parallel: 2
-jest-as-if-jh:
- extends:
- - .jest-base
- - .frontend:rules:default-frontend-jobs-as-if-jh
- needs: ["rspec-all frontend_fixture as-if-jh", "add-jh-folder"]
- script:
- - echo "This job is currently doing nothing since there's no specific JH Jest tests yet. To enable this job, remove this line."
-
coverage-frontend:
extends:
- .default-retry
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 12275260c0c..a71aac4225e 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -1,5 +1,5 @@
.qa-job-base:
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-2.7:bundler-2.3-git-2.33-chrome-${CHROME_VERSION}
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-2.7:bundler-2.3-chrome-103-docker-20.10.14
extends:
- .default-retry
- .qa-cache
@@ -97,7 +97,7 @@ populate-qa-tests-var:
- tooling/bin/find_change_diffs ${CHANGES_DIFFS_DIR}
script:
- 'echo "QA_TESTS: $QA_TESTS"'
- - exit_code=0 && tooling/bin/qa/package_and_qa_check ${CHANGES_DIFFS_DIR} || exit_code=$?
+ - exit_code=0 && tooling/bin/qa/run_qa_check ${CHANGES_DIFFS_DIR} || exit_code=$?
- echo $exit_code
- |
if [ $exit_code -eq 0 ]; then
@@ -105,7 +105,7 @@ populate-qa-tests-var:
elif [ $exit_code -eq 1 ]; then
exit 1
else
- echo "Downstream jobs will not be triggered because package_and_qa_check exited with code: $exit_code"
+ echo "Downstream jobs will not be triggered because run_qa_check exited with code: $exit_code"
fi
# These jobs often time out, so temporarily use private runners and a long timeout: https://gitlab.com/gitlab-org/gitlab/-/issues/238563
tags:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 6fa9d14d47b..50c86313d29 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -84,12 +84,6 @@
- .use-pg12
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests"]
-.rspec-base-pg12-as-if-jh:
- extends:
- - .rspec-base
- - .use-pg12
- needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-jh", "detect-tests", "add-jh-folder"]
-
.rspec-base-pg13:
extends:
- .rspec-base
@@ -117,11 +111,6 @@
- .use-pg12-opensearch1-ee
- .rails:rules:run-search-tests
-.rspec-jh-base-pg12:
- extends:
- - .rspec-base-pg12-as-if-jh
- - .use-pg12-ee
-
.rspec-ee-base-pg13:
extends:
- .rspec-base
@@ -503,6 +492,12 @@ db:backup_and_restore:
- "lib/backup/**/*"
- "lib/tasks/gitlab/backup.rake"
+db:backup_and_restore single-db:
+ extends:
+ - db:backup_and_restore
+ - .single-db
+ - .rails:rules:single-db
+
rspec:deprecations:
extends:
- .default-retry
@@ -738,31 +733,6 @@ rspec system pg12-as-if-foss single-db:
- .single-db-rspec
- .rails:rules:single-db
-rspec migration pg12-as-if-jh:
- extends:
- - .rspec-base-pg12-as-if-jh
- - .rspec-base-migration
- - .rails:rules:as-if-jh-rspec
- - .rspec-migration-parallel
-
-rspec unit pg12-as-if-jh:
- extends:
- - .rspec-base-pg12-as-if-jh
- - .rails:rules:as-if-jh-rspec
- - .rspec-unit-parallel
-
-rspec integration pg12-as-if-jh:
- extends:
- - .rspec-base-pg12-as-if-jh
- - .rails:rules:as-if-jh-rspec
- - .rspec-integration-parallel
-
-rspec system pg12-as-if-jh:
- extends:
- - .rspec-base-pg12-as-if-jh
- - .rails:rules:as-if-jh-rspec
- - .rspec-system-parallel
-
rspec-ee migration pg12:
extends:
- .rspec-ee-base-pg12
@@ -866,52 +836,6 @@ rspec-ee system pg12 single-db:
- .single-db-rspec
- .rails:rules:single-db
-rspec-ee migration pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rspec-base-migration
- - .rails:rules:as-if-jh-rspec
- - .rspec-ee-migration-parallel
-
-rspec-ee unit pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
- - .rspec-ee-unit-parallel
-
-rspec-ee integration pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
- - .rspec-ee-integration-parallel
-
-rspec-ee system pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
- - .rspec-ee-system-parallel
-
-rspec-jh migration pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rspec-base-migration
- - .rails:rules:as-if-jh-rspec
-
-rspec-jh unit pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
-
-rspec-jh integration pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
-
-rspec-jh system pg12-as-if-jh:
- extends:
- - .rspec-jh-base-pg12
- - .rails:rules:as-if-jh-rspec
-
db:rollback geo:
extends:
- db:rollback
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 68c71b359c2..52ed85190ec 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -13,6 +13,8 @@ code_quality:
artifacts:
paths:
- gl-code-quality-report.json # GitLab-specific
+ # extends generated values cannot overwrite values from included files
+ # Use !reference as a workaround here
rules: !reference [".reports:rules:code_quality", rules]
allow_failure: true
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index 7f3ae70da8c..37ccecc0562 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -14,7 +14,7 @@ include:
.base-before_script: &base-before_script
- source ./scripts/utils.sh
- source ./scripts/review_apps/review-apps.sh
- - install_api_client_dependencies_with_apk
+ - apt-get update && apt-get install -y jq
review-build-cng-env:
extends:
@@ -72,8 +72,7 @@ review-build-cng:
.review-workflow-base:
extends:
- .default-retry
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:gitlab-helm3.5-kubectl1.17
- resource_group: "review/${CI_COMMIT_REF_NAME}"
+ image: ${REVIEW_APPS_IMAGE}
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
@@ -139,6 +138,7 @@ review-stop:
extends:
- .review-stop-base
- .review:rules:review-stop
+ resource_group: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # CI_ENVIRONMENT_SLUG is not available here and we want this to be the same as the environment
stage: deploy
needs: []
script:
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index 8c48e803ad3..631fe7fef30 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -88,10 +88,8 @@ download-knapsack-report:
- .bundle-base
- .review:rules:review-qa-reliable
stage: prepare
- variables:
- QA_KNAPSACK_REPORTS: review-qa-reliable,review-qa-all
script:
- - bundle exec rake "knapsack:download"
+ - bundle exec rake "knapsack:download[qa]"
allow_failure: true
artifacts:
paths:
diff --git a/.gitlab/ci/review-apps/skip-qa.gitlab-ci.yml b/.gitlab/ci/review-apps/skip-qa.gitlab-ci.yml
new file mode 100644
index 00000000000..1305673a4d8
--- /dev/null
+++ b/.gitlab/ci/review-apps/skip-qa.gitlab-ci.yml
@@ -0,0 +1,13 @@
+stages:
+ - review
+
+include:
+ - local: .gitlab/ci/global.gitlab-ci.yml
+ - local: .gitlab/ci/rules.gitlab-ci.yml
+
+no-op:
+ extends:
+ - .review:rules:start-review-app-pipeline
+ stage: review
+ script:
+ - echo "Skip Review App because the MR includes only quarantine changes"
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index b2cd9d61fd8..4f51409d6a8 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -5,7 +5,8 @@ review-cleanup:
extends:
- .default-retry
- .review:rules:review-cleanup
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/ruby-3.0:gcloud-383-kubectl-1.23-helm-3.5
+ image: ${REVIEW_APPS_IMAGE}
+ resource_group: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # CI_ENVIRONMENT_SLUG is not available here and we want this to be the same as the environment
stage: prepare
environment:
name: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # No separator for SCHEDULE_TYPE so it's compatible as before and looks nice without it
@@ -22,11 +23,42 @@ review-cleanup:
- ruby -rrubygems scripts/review_apps/automated_cleanup.rb
- gcp_cleanup
+review-app-pipeline-generate:
+ image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}
+ stage: prepare
+ extends:
+ - .review:rules:start-review-app-pipeline
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${CHANGES_DIFFS_DIR}/*
+ - review-app-pipeline.yml
+ variables:
+ CHANGES_DIFFS_DIR: tmp/diffs
+ before_script:
+ - source scripts/utils.sh
+ - install_gitlab_gem
+ - tooling/bin/find_change_diffs ${CHANGES_DIFFS_DIR}
+ script:
+ - exit_code=0 && tooling/bin/qa/run_qa_check ${CHANGES_DIFFS_DIR} || exit_code=$?
+ - |
+ if [ $exit_code -eq 0 ]; then
+ echo "Review App will use the full pipeline"
+ cp .gitlab/ci/review-apps/main.gitlab-ci.yml review-app-pipeline.yml
+ elif [ $exit_code -eq 2 ]; then
+ echo "Skip Review App because the MR includes only quarantine changes"
+ cp .gitlab/ci/review-apps/skip-qa.gitlab-ci.yml review-app-pipeline.yml
+ else
+ exit $exit_code
+ fi
+
start-review-app-pipeline:
extends:
- .review:rules:start-review-app-pipeline
+ resource_group: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # CI_ENVIRONMENT_SLUG is not available here and we want this to be the same as the environment
stage: review
needs:
+ - review-app-pipeline-generate
- job: build-assets-image
artifacts: false
# These variables are set in the pipeline schedules.
@@ -37,7 +69,8 @@ start-review-app-pipeline:
DAST_RUN: $DAST_RUN
trigger:
include:
- - local: .gitlab/ci/review-apps/main.gitlab-ci.yml
+ - artifact: review-app-pipeline.yml
+ job: review-app-pipeline-generate
strategy: depend
danger-review:
@@ -52,12 +85,13 @@ danger-review:
- bundle_install_script "--with danger"
- run_timed_command "retry yarn install --frozen-lockfile"
script:
+ # ${DANGER_DANGERFILE} is used by Jihulab for customizing danger support: https://jihulab.com/gitlab-cn/gitlab/-/blob/main-jh/jh/.gitlab-ci.yml
- >
if [ -z "$DANGER_GITLAB_API_TOKEN" ]; then
run_timed_command danger_as_local
else
danger_id=$(echo -n ${DANGER_GITLAB_API_TOKEN} | md5sum | awk '{print $1}' | cut -c5-10)
- run_timed_command "bundle exec danger --fail-on-errors=true --verbose --danger_id=${danger_id}"
+ run_timed_command "bundle exec danger --fail-on-errors=true --verbose --danger_id=\"${danger_id}\" --dangerfile=\"${DANGER_DANGERFILE:-Dangerfile}\""
fi
danger-review-local:
@@ -70,6 +104,8 @@ danger-review-local:
reviewers-recommender:
extends:
- .default-retry
- - .review:rules:reviewers-recommender
+ # 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 93790f431dd..fcb853a7bd2 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -252,7 +252,7 @@
- "vendor/assets/**/*"
- "{,ee/,jh/}app/assets/**/*"
-.frontend-patterns: &frontend-patterns
+.frontend-patterns-for-as-if-foss: &frontend-patterns-for-as-if-foss
- "{package.json,yarn.lock}"
- ".browserslistrc"
- "babel.config.js"
@@ -261,7 +261,7 @@
- "Dockerfile.assets"
- "config/**/*.js"
- "vendor/assets/**/*"
- - "{,ee/,jh/}{app/assets,app/helpers,app/presenters,app/views,locale,public,symbol}/**/*"
+ - "{app/assets,app/helpers,app/presenters,app/views,locale,public,spec/frontend,symbol}/**/*"
.controllers-patterns: &controllers-patterns
- "{,ee/,jh/}{app/controllers}/**/*"
@@ -369,7 +369,6 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".gitlab-ci.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -400,7 +399,6 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".gitlab-ci.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -526,17 +524,6 @@
- <<: *if-jh
when: never
-.as-if-jh-default-exclusion-rules:
- rules:
- - <<: *if-security-merge-request
- when: never
- - <<: *if-merge-request-targeting-stable-branch
- when: never
- - <<: *if-stable-branch-refs
- when: never
- - <<: *if-merge-request-labels-as-if-jh
- allow_failure: true
-
.rails:rules:minimal-default-rules:
rules:
- <<: *if-merge-request-approved
@@ -734,6 +721,7 @@
- <<: *if-merge-request-targeting-stable-branch
- <<: *if-merge-request-labels-run-review-app
- <<: *if-auto-deploy-branches
+ - changes: *ci-build-images-patterns
- changes: *code-qa-patterns
- changes: *workhorse-patterns
@@ -753,18 +741,6 @@
- changes: *startup-css-patterns
- changes: *workhorse-patterns
-.frontend:rules:compile-test-assets-as-if-jh:
- rules:
- - !reference [".strict-ee-only-rules", rules]
- - !reference [".as-if-jh-default-exclusion-rules", rules]
- - <<: *if-merge-request-labels-run-all-rspec
- allow_failure: true
- - changes: *code-backstage-qa-patterns
- allow_failure: true
- - changes: *startup-css-patterns
- allow_failure: true
- - changes: *workhorse-patterns
-
.frontend:rules:default-frontend-jobs:
rules:
- <<: *if-merge-request-labels-run-all-rspec
@@ -782,18 +758,11 @@
- <<: *if-merge-request
changes: *ci-patterns
-.frontend:rules:default-frontend-jobs-as-if-jh:
+.frontend:rules:frontend_fixture-as-if-foss:
rules:
- !reference [".strict-ee-only-rules", rules]
- - !reference [".as-if-jh-default-exclusion-rules", rules]
- - <<: *if-merge-request-labels-run-all-rspec
- allow_failure: true
- - <<: *if-merge-request
- changes: *startup-css-patterns
- allow_failure: true
- - <<: *if-merge-request
- changes: *ci-patterns
- allow_failure: true
+ - !reference [".frontend:rules:default-frontend-jobs-as-if-foss", rules]
+ - !reference [".frontend:rules:jest:minimal:as-if-foss", rules]
.frontend:rules:jest:
rules:
@@ -828,12 +797,37 @@
- <<: *if-merge-request
changes: *code-backstage-patterns
+.frontend:rules:jest:minimal:as-if-foss:
+ rules:
+ - !reference [".strict-ee-only-rules", rules]
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ when: never
+ - <<: *if-merge-request-labels-as-if-foss
+ when: never
+ - <<: *if-merge-request-labels-run-all-jest
+ when: never
+ - <<: *if-merge-request-labels-run-all-rspec
+ when: never
+ - <<: *if-merge-request
+ changes: *startup-css-patterns
+ when: never
+ - <<: *if-merge-request
+ changes: *ci-patterns
+ when: never
+ - <<: *if-fork-merge-request
+ when: never
+ - <<: *if-merge-request
+ changes: *core-frontend-patterns
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
+
.frontend:rules:eslint-as-if-foss:
rules:
- !reference [".strict-ee-only-rules", rules]
- <<: *if-merge-request-labels-as-if-foss
- <<: *if-merge-request
- changes: *frontend-patterns
+ changes: *frontend-patterns-for-as-if-foss
.frontend:rules:ee-mr-and-default-branch-only:
rules:
@@ -1300,14 +1294,6 @@
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
-.rails:rules:as-if-jh-rspec:
- rules:
- - !reference [".strict-ee-only-rules", rules]
- - !reference [".as-if-jh-default-exclusion-rules", rules]
- - <<: *if-merge-request
- changes: *ci-patterns
- allow_failure: true
-
.rails:rules:ee-and-foss-db-library-code:
rules:
- changes: *db-library-patterns
@@ -1481,13 +1467,24 @@
changes: ["vendor/gems/ipynbdiff/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
+.vendor:rules:omniauth-azure-oauth2:
+ rules:
+ - <<: *if-merge-request
+ changes: ["vendor/gems/omniauth-azure-oauth2/**/*"]
+ - <<: *if-merge-request-labels-run-all-rspec
+
+.vendor:rules:omniauth-cas3:
+ rules:
+ - <<: *if-merge-request
+ changes: ["vendor/gems/omniauth-cas3/**/*"]
+ - <<: *if-merge-request-labels-run-all-rspec
+
.vendor:rules:omniauth_crowd:
rules:
- <<: *if-merge-request
changes: ["vendor/gems/omniauth_crowd/**/*"]
- <<: *if-merge-request-labels-run-all-rspec
-
.vendor:rules:omniauth-gitlab:
rules:
- <<: *if-merge-request
@@ -1633,7 +1630,7 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
+ changes: *frontend-build-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *controllers-patterns
- <<: *if-dot-com-gitlab-org-merge-request
@@ -1813,19 +1810,6 @@
- ".gitlab/ci/test-metadata.gitlab-ci.yml"
- "scripts/rspec_helpers.sh"
-.setup:rules:add-jh-folder:
- rules:
- - !reference [".strict-ee-only-rules", rules]
- - !reference [".as-if-jh-default-exclusion-rules", rules]
- - <<: *if-merge-request-labels-run-all-rspec
- allow_failure: true
- - changes: *code-backstage-qa-patterns
- allow_failure: true
- - changes: *startup-css-patterns
- allow_failure: true
- - changes: *workhorse-patterns
- allow_failure: true
-
#######################
# Test metadata rules #
#######################
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 2da397aaab8..17113b1245c 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -172,22 +172,3 @@ detect-previous-failed-tests:
expire_in: 7d
paths:
- ${PREVIOUS_FAILED_TESTS_DIR}
-
-add-jh-folder:
- extends: .setup:rules:add-jh-folder
- image: ${GITLAB_DEPENDENCY_PROXY}ruby:${RUBY_VERSION}
- stage: prepare
- before_script:
- - source ./scripts/utils.sh
- - install_gitlab_gem
- script:
- - JH_BRANCH=$(./scripts/setup/find-jh-branch.rb)
- - 'echo "JH_BRANCH: ${JH_BRANCH}"'
- - curl --location -o "jh-folder.tar.gz" "https://gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab/-/archive/${JH_BRANCH}/gitlab-${JH_BRANCH}.tar.gz?path=jh"
- - tar -xf "jh-folder.tar.gz"
- - mv "gitlab-${JH_BRANCH}-jh/jh/" ./
- - ls -l jh/
- artifacts:
- expire_in: 2d
- paths:
- - jh/
diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index 8596d770a87..4408a6e4624 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -14,6 +14,22 @@ vendor ipynbdiff:
include: vendor/gems/ipynbdiff/.gitlab-ci.yml
strategy: depend
+vendor omniauth-azure-oauth2:
+ extends:
+ - .vendor:rules:omniauth-azure-oauth2
+ needs: []
+ trigger:
+ include: vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
+ strategy: depend
+
+vendor omniauth-cas3:
+ extends:
+ - .vendor:rules:omniauth-cas3
+ needs: []
+ trigger:
+ include: vendor/gems/omniauth-cas3/.gitlab-ci.yml
+ strategy: depend
+
vendor omniauth_crowd:
extends:
- .vendor:rules:omniauth_crowd
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 e1c5928b950..7ef5287aba8 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
@@ -392,7 +392,7 @@ That's all of the required database changes.
```
- [ ] Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
-- [ ] Add a custom factory name if needed in `def model_class_factory_name` in `ee/spec/services/geo/registry_consistency_service_spec.rb`.
+- [ ] Add a custom factory name if needed in `def model_class_factory_name` in `ee/spec/support/helpers/ee/geo_helpers.rb`.
- [ ] Update `it 'creates missing registries for each registry class'` in `ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb`.
- [ ] Add `cool_widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
- [ ] Create `ee/spec/factories/geo/cool_widget_registry.rb`:
@@ -539,11 +539,6 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus`
- `geo_cool_widgets_verification_total`
- `geo_cool_widgets_verified`
- `geo_cool_widgets_verification_failed`
-- [ ] Add the following to the parameterized table in the `context 'Replicator stats' do` block in `ee/spec/models/geo_node_status_spec.rb`:
-
- ```ruby
- Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
- ```
Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
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 9158885262d..17a4dd4bc3e 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -358,7 +358,7 @@ That's all of the required database changes.
```
- [ ] Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
-- [ ] Add a custom factory name if needed in `def model_class_factory_name` in `ee/spec/services/geo/registry_consistency_service_spec.rb`.
+- [ ] Add a custom factory name if needed in `def model_class_factory_name` in `ee/spec/support/helpers/ee/geo_helpers.rb`.
- [ ] Update `it 'creates missing registries for each registry class'` in `ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb`.
- [ ] Add `cool_widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
- [ ] Create `ee/spec/factories/geo/cool_widget_registry.rb`:
@@ -503,11 +503,6 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in `GeoNodeStatus`
- `geo_cool_widgets_verification_total`
- `geo_cool_widgets_verified`
- `geo_cool_widgets_verification_failed`
-- [ ] Add the following to the parameterized table in the `context 'Replicator stats' do` block in `ee/spec/models/geo_node_status_spec.rb`:
-
- ```ruby
- Geo::CoolWidgetReplicator | :cool_widget | :geo_cool_widget_registry
- ```
Cool Widget replication and verification metrics should now be available in the API, the `Admin > Geo > Nodes` view, and Prometheus.
diff --git a/.gitlab/issue_templates/Implementation.md b/.gitlab/issue_templates/Implementation.md
index f57bfae4da3..e09f807d3d9 100644
--- a/.gitlab/issue_templates/Implementation.md
+++ b/.gitlab/issue_templates/Implementation.md
@@ -37,13 +37,20 @@ Add details for required items and delete others.
## Implementation plan
<!--
-Steps and the parts of the code that will need to get updated. The plan can also
-call-out responsibilities for other team members or teams.
+Steps and the parts of the code that will need to get updated.
+The plan can also call-out responsibilities for other team members or teams and
+can be split into smaller MRs to simplify the code review process.
e.g.:
+- MR 1: Part 1
+- [ ] ~frontend Step 1
+- [ ] ~frontend Step 2
+- MR 2: Part 2
+- [ ] ~backend Step 1
+- [ ] ~backend Step 2
+- MR 3: Part 3
- [ ] ~frontend Step 1
- - [ ] `@person` Step 1a
- [ ] ~frontend Step 2
-->
diff --git a/.gitlab/issue_templates/Navigation - Left Sidebar Proposals.md b/.gitlab/issue_templates/Navigation - Left Sidebar Proposals.md
index e9e510da11e..3939fca44f1 100644
--- a/.gitlab/issue_templates/Navigation - Left Sidebar Proposals.md
+++ b/.gitlab/issue_templates/Navigation - Left Sidebar Proposals.md
@@ -6,7 +6,7 @@
### Checklist
-- [ ] If your proposal includes changes to the top-level menu items within the left sidebar, engage the [Foundations Product Design Manager](https://about.gitlab.com/handbook/product/categories/#foundations-group) for approval. The Foundations DRI will work with UX partners in product design, research, and technical writing, as applicable.
+- [ ] If your proposal includes changes to the menu items within the left sidebar, engage the [Foundations Product Manager](https://about.gitlab.com/handbook/product/categories/#foundations-group) for approval. The Foundations DRI will work with UX partners in product design, research, and technical writing, as applicable.
- [ ] Follow the [product development workflow](https://about.gitlab.com/handbook/product-development-flow/#validation-phase-2-problem-validation) validation process to ensure you are solving a well understood problem and that the proposed change is understandable and non-disruptive to users. Navigation-specific research is strongly encouraged.
- [ ] Engage the [Foundations](https://about.gitlab.com/handbook/product/categories/#foundations-group) team to ensure your proposal is in alignment with holistic changes happening to the left side bar.
- [ ] Consider whether you need to communicate the change somehow, or if you will have an interim period in the UI where your nav item will live in more than one place.
diff --git a/.gitlab/issue_templates/OSS_Partner.md b/.gitlab/issue_templates/OSS_Partner.md
deleted file mode 100644
index d9c05026e7c..00000000000
--- a/.gitlab/issue_templates/OSS_Partner.md
+++ /dev/null
@@ -1,68 +0,0 @@
-<!-- Please title your issue with the following format: "Project Name | Issue Tracker". -->
-
-## Background
-
-<!--
-Please add information here about why your project is considering a migration to GitLab, or why it decided to do so. Include any initial announcements that have been / were made about the decision or status.
--->
-
-### Goals
-
-<!-- What are some of the goals of your migration to GitLab? Delete this section if you don't want to enumerate goals. -->
-
-## Quick Facts
-
-<!-- Please complete as many items in this list as possible. If you're not sure yet, add "TBD" (To be Decided) or "Unknown" -->
-
- * **Timeline.** -
- * **Product.** - SaaS-Ultimate/Self-Managed-Ultimate or Community Edition
- * **Project's License.** What kind of OSI-approved license does your project use?
-
-## Current Tooling and Replacements
-
-<!--
-Please fill in the table to give an overview of your current tooling. Here's a description of what to include in each column:
-
-- Tool: which tool or platform you are currently using
-- Feature: which particular feature you are using in that tool or platform
-- GitLab feature: equivalent GitLab feature (the GitLab team can help fill this in, as well as the info in the next column)
-- GitLab edition: in which GitLab edition (CE or EE) is this feature available?
-
-Here's an example of a replacements overview from one of the projects which migrated to GitLab: https://gitlab.com/gitlab-org/gitlab/-/issues/25657#gitlab-replacements
-
-Consider deleting the table below if you are unable to expand upon your current tooling.
-
--->
-
-| Tool | Feature | GitLab feature | GitLab edition |
-| --- | --- | --- | --- |
-| | | | |
-
-## Collaborators
-
-<!-- Please add names of collaborators in the format: Name, Title, Role (what will you be helping to do, or how should you be involved), GitLab username -->
-
-## Related Issues
-
-<!-- Add any related issues that are important for your project by adding the title of the issue and a link to it (preferably as an embedded link). You will probably keep editing this section as the migration progresses, so don't worry if it's mostly blank for now.
-
-Here is an example of what this list might look like once populated: https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55039#outstanding-issues
--->
-
-### Blockers
- * [ ] ADD_LINK_TO_ISSUE_HERE
-
-### Urgent
- * [ ]
-
-### Important but not urgent
- * [ ]
-
-### Nice to have
- * [ ]
-
-
-------
-
-/label ~"Open Source Partners"
-/cc @nuritzi @greg
diff --git a/.gitlab/issue_templates/Performance Indicator Metric.md b/.gitlab/issue_templates/Performance Indicator Metric.md
deleted file mode 100644
index 8019be8cad5..00000000000
--- a/.gitlab/issue_templates/Performance Indicator Metric.md
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-Performance Indicator Metric issues are used for adding, updating, or removing performance indicator type in Service Ping metrics.
-
-Please title your issue with the following format: "{action}(Add|Update|Remove) Metric name as performance indicator"
-
-Example of title: "Add some_feature_views as gmau"
-
--->
-
-## Summary
-
-<!--
-Summary of the changes
--->
-
-## Tasks
-
-- [ ] [Link to metric definition]()
-- [ ] Create issue in GitLab Data Team project using [Product Performance Indicator template](https://gitlab.com/gitlab-data/analytics/-/issues/new?issuable_template=Product%20Performance%20Indicator%20Template)
-
-See [Product Intelligence Guide](https://docs.gitlab.com/ee/development/service_ping/performance_indicator_metrics.html) for details
-
-/label ~"product intelligence" ~"Data Warehouse::Impact Check"
diff --git a/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md b/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md
index 4544e675256..523a50dfdf8 100644
--- a/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md
+++ b/.gitlab/issue_templates/Pipeline Authoring Issue Implementation.md
@@ -12,6 +12,21 @@
## Proposal
+## Additional details
+<!--
+_NOTE: If the issue has addressed all of these questions, this separate section can be removed._
+-->
+
+Some relevant technical details, if applicable, such as:
+
+- Does this need a ~"feature flag"?
+- Is there an example response showing the data structure that should be returned (new endpoints only)?
+- What permissions should be used?
+- Is this EE or CE?
+ - [ ] EE
+ - [ ] CE
+- Additional comments:
+
## Implementation Table
<!--
diff --git a/.gitlab/issue_templates/Service Ping reporting and monitoring.md b/.gitlab/issue_templates/Service Ping reporting and monitoring.md
index 1c0d221318b..9a30f71e42b 100644
--- a/.gitlab/issue_templates/Service Ping reporting and monitoring.md
+++ b/.gitlab/issue_templates/Service Ping reporting and monitoring.md
@@ -1,6 +1,6 @@
-<!-- This issue template is used by https://about.gitlab.com/handbook/engineering/development/growth/product-intelligence/ for tracking effort around Service Ping reporting for GitLab.com -->
+<!-- This issue template is used by https://about.gitlab.com/handbook/engineering/development/analytics-section/product-intelligence/ for tracking effort around Service Ping reporting for GitLab.com -->
-The [Product Intelligence group](https://about.gitlab.com/handbook/engineering/development/growth/product-intelligence/) runs manual reporting of ServicePing for GitLab.com on a weekly basis. This issue captures:
+The [Product Intelligence group](https://about.gitlab.com/handbook/engineering/development/analytics/product-intelligence/) runs manual reporting of ServicePing for GitLab.com on a weekly basis. This issue:
- Captures the work required to complete the reporting process,.
- Captures the follow-up tasks that are focused on metrics performance verification.
@@ -123,7 +123,7 @@ If you get mentioned, check the failing metric and open an optimization issue.
<!-- Do not edit below this line -->
/confidential
-/label ~"group::product intelligence" ~"devops::growth" ~backend ~"section::growth" ~"Category:Service Ping"
+/label ~"group::product intelligence" ~"devops::analytics" ~backend ~"section::analytics" ~"Category:Service Ping"
/epic https://gitlab.com/groups/gitlab-org/-/epics/6000
/weight 5
/title Monitor and Generate GitLab.com Service Ping
diff --git a/.gitlab/issue_templates/UX Theme.md b/.gitlab/issue_templates/UX Theme.md
new file mode 100644
index 00000000000..043cb705352
--- /dev/null
+++ b/.gitlab/issue_templates/UX Theme.md
@@ -0,0 +1,77 @@
+<!-- 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 -->
+
+### 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)
+
+!!Note: The theme statement is the defacto title that will be used to reference the theme and serve as the theme issue title.!!
+-->
+
+----
+
+### Problem to solve
+<!-- In a brief statement, summerize the problem we are intending to address with this theme. For instance, users are unable to complete [task], or, users struggle with the amount of steps required to complete [task] -->
+
+
+### Beneficiary
+<!-- Who is the recipient(s) of the value this theme provides; a customer, end-user, or buyer. Who benefits from this theme being executed? This can be a role, a team, or a persona. For instance: "Development teams, [or] Developers, [or], Sasha the Software Engineer". -->
+
+- **[Direct beneficiary]**
+
+#### Need & Primary JTBD
+<!-- What is the JTBD and what are the needs related to the beneficiary and theme?
+- JTBD = The JTBD statement, for instance, (When I am triaging vulns, I want to address business-critical risks, So I can ensure there is no unattended risk in my orgs assets.)
+- Need = Abstracted from the JTBD, for instance, (Identify and escalate business-critical risks detected in my orgs assets.)
+-->
+
+- **JTBD:**
+- **Need:**
+
+#### Expected outcome
+<!-- What will the user be able to achieve when this theme is executed? For instance, (Users will be able to effectively triage vulnerabilities at scale across all their orgs assets.) -->
+
+
+#### Business objective
+<!-- What business objective will result from delivering this theme? This answers why we are working on this theme from a business perspective. Examples of objectives are but are not limited to: Sales rate / conversion rate, Success rate / completion rate, Traffic / visitor count, Engagement, or other business-oriented goals. -->
+
+
+#### 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 -->
+
+
+| Confidence | Research |
+| --- | --- |
+| [High/Medium/Low] | [research/insight issue](Link) |
+
+
+### Subthemes & Requirements
+<!-- Subthemes are more granular validated needs, goals, and additional details that the theme encompasses. These are typically reserved for themes in the next (1-3 milestones) column. Subthemes may also consist of existing feature or design issues that exist in GitLab and directly relate to the theme. Subthemes answer “how†we are going to solve the user need while the theme itself answers “what†the need is and “who†will be benefiting from the solution.
+
+Note: This is not a backlog. If the subthemes can not be delivered in the theme timeframe then the theme is too big and needs to be broken down into multiple themes. -->
+
+#### Feature/solution subthemes
+<!-- Use this table to track feature issues related to this theme (if applicable). Not all themes require subthemes as subthemes are typically discovered while working on the theme itself. Think of subthemes as if they were the result of design breaking down the issue into discrete work items.
+
+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.
+-->
+
+| Issue | UX Weight |
+| ---------- | --------- |
+| [Issue](link) | `0 - 10` |
+| [Issue](link) | `0 - 10` |
+| [Issue](link) | `0 - 10` |
+
+#### Research subthemes
+<!-- Use this table to track UX research related to this theme. This may include, problem validation and/or solution validation activities.
+-->
+
+| Issue | Research type | Research status |
+| ---------- | --------- | --------- |
+| [Issue]() | <!--Solution validation, Problem validation, etc., --> | <!-- Planned, In Progress, Complete, etc.,--> |
+| [Issue]() | <!--Solution validation, Problem validation, etc., --> | <!-- Planned, In Progress, Complete, etc.,--> |
+
+
+/label ~"UX" ~"UX Theme"
diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md
index 90d3c37d6c0..ecb8505e0df 100644
--- a/.gitlab/merge_request_templates/Default.md
+++ b/.gitlab/merge_request_templates/Default.md
@@ -8,23 +8,23 @@ that reviewers can understand your intent. Keeping the description updated is
especially important if they didn't participate in the discussion.
-->
-## Screenshots or screen recordings
+## Screenshots or screen recordings
-_These are strongly recommended to assist reviewers and reduce the time to merge your change._
+_Screenshots are required for UI changes, and strongly recommended for all other merge requests._
-<!--
+<!--
Please include any relevant screenshots or screen recordings that will assist
reviewers and future readers. If you need help visually verifying the change,
please leave a comment and ping a GitLab reviewer, maintainer, or MR coach.
-->
-## How to set up and validate locally
+## How to set up and validate locally
_Numbered steps to set up and validate the change are strongly suggested._
-<!--
+<!--
Example below:
-
+
1. Enable the invite modal
```ruby
Feature.enable(:invite_members_group_modal)
@@ -39,7 +39,7 @@ Example below:
## MR acceptance checklist
-This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
+This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
* [ ] I have evaluated the [MR acceptance checklist](https://docs.gitlab.com/ee/development/code_review.html#acceptance-checklist) for this MR.
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index cdc33b8aacb..4932fbd7f26 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -43,5 +43,5 @@ Documentation-related MRs should be reviewed by a Technical Writer for a non-blo
- If the content still needs to be edited for topic types, you can create a follow-up issue with the ~"docs-technical-debt" label.
- [ ] Review by assigned maintainer, who can always request/require the reviews above. Maintainer's review can occur before or after a technical writer review.
-/label ~documentation ~"type::maintenance" ~"docs::improvement"
+/label ~documentation ~"type::maintenance" ~"docs::improvement" ~"maintenance::refactor"
/assign me
diff --git a/.haml-lint.yml b/.haml-lint.yml
index 1345df2c0bd..7d772831b2c 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -129,11 +129,15 @@ linters:
- Rails/RequestReferer
- Style/ColonMethodCall
- Style/ConditionalAssignment
+ - Style/FormatString
- Style/HashSyntax
+ - Style/IfInsideElse
- Style/IdenticalConditionalBranches
- Style/NegatedIf
- Style/NestedTernaryOperator
+ - Style/RedundantInterpolation
- Style/SelfAssignment
+ - Style/StringConcatenation
- Style/TernaryParentheses
- Style/TrailingCommaInHashLiteral
- Style/UnlessElse
diff --git a/.overcommit.yml.example b/.overcommit.yml.example
deleted file mode 100644
index c1c2395ca93..00000000000
--- a/.overcommit.yml.example
+++ /dev/null
@@ -1,81 +0,0 @@
-# Use this file to configure the Overcommit hooks you wish to use. This will
-# extend the default configuration defined in:
-# https://github.com/sds/overcommit/blob/master/config/default.yml
-#
-# At the topmost level of this YAML file is a key representing type of hook
-# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
-# customize each hook, such as whether to only run it on certain files (via
-# `include`), whether to only display output if it fails (via `quiet`), etc.
-#
-# For a complete list of hooks, see:
-# https://github.com/sds/overcommit/tree/master/lib/overcommit/hook
-#
-# For a complete list of options that you can use to customize hooks, see:
-# https://github.com/sds/overcommit#configuration
-#
-# Uncomment the following lines to make the configuration take effect.
-
-# Make sure to run `make -C tooling/overcommit`
-gemfile: 'tooling/overcommit/Gemfile'
-
-PostCheckout:
- BundleInstall:
- enabled: true
-
-PreCommit:
- AuthorName:
- enabled: false
- EsLint:
- enabled: true
- # https://github.com/sds/overcommit/issues/338
- required_executable: 'yarn'
- command: ['yarn', 'eslint']
- flags: []
- HamlLint:
- enabled: true
- MergeConflicts:
- enabled: true
- exclude:
- - '**/conflict/file_spec.rb'
- - '**/git/conflict/parser_spec.rb'
- # prettier? https://github.com/sds/overcommit/issues/614 https://github.com/sds/overcommit/issues/390#issuecomment-495703284
- RuboCop:
- enabled: true
-# on_warn: fail # Treat all warnings as failures
- ScssLint:
- enabled: true
- MarkdownLint:
- enabled: true
- description: 'Lint documentation for Markdown errors'
- required_executable: 'node_modules/.bin/markdownlint'
- flags: ['--config', '.markdownlint.yml', 'doc/**/*.md']
- install_command: 'yarn install'
- include:
- - 'doc/**/*.md'
- Vale:
- enabled: true
- description: 'Lint documentation for grammatical and formatting errors'
- required_executable: 'vale'
- flags: ['--config', '.vale.ini', '--minAlertLevel', 'error', 'doc']
- install_command: 'brew install vale # (or use another package manager)'
- include:
- - 'doc/**/*.md'
-
-CommitMsg:
- TextWidth:
- enabled: true
- min_subject_width: 8 # three 2-letter words with 2 spaces
- max_subject_width: 72
- quiet: false
-
- EmptyMessage:
- enabled: true
- required: true
- description: 'Checking for empty commit message'
-
-#PostCheckout:
-# ALL: # Special hook name that customizes all hooks of this type
-# quiet: true # Change all post-checkout hooks to only display output on failure
-#
-# IndexTags:
-# enabled: true # Generate a tags file with `ctags` each time HEAD changes
diff --git a/.rubocop.yml b/.rubocop.yml
index 4c7abe0dc89..8ddd5087bb7 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -290,6 +290,10 @@ Rails/MailerName:
# See for the context on why it's excluded https://gitlab.com/gitlab-org/gitlab/-/issues/239356#note_956419227
- 'app/mailers/notify.rb'
+Rails/RakeEnvironment:
+ # Context on why it's disabled: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93419#note_1048223982
+ Enabled: false
+
# GitLab ###################################################################
Gitlab/ModuleWithInstanceVariables:
@@ -431,6 +435,10 @@ Naming/PredicateName:
- 'spec/**/*'
- 'ee/spec/**/*'
+# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93828#note_1050812797
+Naming/RescuedExceptionsVariableName:
+ Enabled: false
+
RSpec/FactoriesInMigrationSpecs:
Enabled: true
Include:
@@ -558,18 +566,6 @@ Graphql/Descriptions:
RSpec/ImplicitSubject:
Enabled: false
-RSpec/EmptyLineAfterHook:
- Enabled: false
-
-RSpec/HooksBeforeExamples:
- Enabled: false
-
-RSpec/EmptyLineAfterExample:
- Enabled: false
-
-RSpec/Be:
- Enabled: false
-
RSpec/DescribedClass:
Enabled: false
@@ -596,6 +592,18 @@ RSpec/HaveGitlabHttpStatus:
- 'spec/**/*'
- 'ee/spec/**/*'
+RSpec/ContextWording:
+ Prefixes:
+ - 'when'
+ - 'with'
+ - 'without'
+ - 'for'
+ - 'and'
+ - 'on'
+ - 'in'
+ - 'as'
+ - 'if'
+
Style/MultilineWhenThen:
Enabled: false
@@ -780,3 +788,6 @@ Style/ClassAndModuleChildren:
Fips/OpenSSL:
Enabled: false
+
+Gemspec/AvoidExecutingGit:
+ Enabled: false
diff --git a/.rubocop_todo/capybara/visibility_matcher.yml b/.rubocop_todo/capybara/visibility_matcher.yml
index 90d71fe2d3a..e236be2593e 100644
--- a/.rubocop_todo/capybara/visibility_matcher.yml
+++ b/.rubocop_todo/capybara/visibility_matcher.yml
@@ -1,24 +1,23 @@
---
Capybara/VisibilityMatcher:
- # Offense count: 213
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- - 'ee/spec/features/billings/billing_plans_spec.rb'
- '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/path_locks_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'
@@ -26,13 +25,6 @@ Capybara/VisibilityMatcher:
- 'spec/features/dashboard/merge_requests_spec.rb'
- 'spec/features/dashboard/todos/todos_spec.rb'
- 'spec/features/groups/group_settings_spec.rb'
- - 'spec/features/issues/filtered_search/dropdown_assignee_spec.rb'
- - 'spec/features/issues/filtered_search/dropdown_author_spec.rb'
- - 'spec/features/issues/filtered_search/dropdown_emoji_spec.rb'
- - 'spec/features/issues/filtered_search/dropdown_hint_spec.rb'
- - 'spec/features/issues/filtered_search/recent_searches_spec.rb'
- - 'spec/features/issues/filtered_search/search_bar_spec.rb'
- - 'spec/features/issues/filtered_search/visual_tokens_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'
@@ -48,17 +40,19 @@ Capybara/VisibilityMatcher:
- '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/tags/user_edits_tags_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'
@@ -66,6 +60,7 @@ Capybara/VisibilityMatcher:
- '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'
diff --git a/.rubocop_todo/database/multiple_databases.yml b/.rubocop_todo/database/multiple_databases.yml
index 1d0085e1ba6..07d8ce12fa8 100644
--- a/.rubocop_todo/database/multiple_databases.yml
+++ b/.rubocop_todo/database/multiple_databases.yml
@@ -6,12 +6,10 @@ Database/MultipleDatabases:
- 'db/post_migrate/20210811122206_update_external_project_bots.rb'
- 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb'
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- - 'lib/backup/manager.rb'
- 'lib/gitlab/background_migration/backfill_projects_with_coverage.rb'
- 'lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb'
- 'spec/db/schema_spec.rb'
- 'spec/initializers/database_config_spec.rb'
- - 'spec/lib/backup/manager_spec.rb'
- 'spec/lib/gitlab/database_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
- 'spec/lib/gitlab/profiler_spec.rb'
@@ -24,5 +22,4 @@ Database/MultipleDatabases:
- 'spec/support/helpers/migrations_helpers.rb'
- 'spec/support/helpers/query_recorder.rb'
- 'spec/support/helpers/usage_data_helpers.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
diff --git a/.rubocop_todo/gitlab/deprecate_track_redis_hll_event.yml b/.rubocop_todo/gitlab/deprecate_track_redis_hll_event.yml
new file mode 100644
index 00000000000..06651a0f60a
--- /dev/null
+++ b/.rubocop_todo/gitlab/deprecate_track_redis_hll_event.yml
@@ -0,0 +1,29 @@
+---
+Gitlab/DeprecateTrackRedisHLLEvent:
+ Exclude:
+ - 'app/controllers/admin/dev_ops_report_controller.rb'
+ - 'app/controllers/admin/usage_trends_controller.rb'
+ - 'app/controllers/concerns/snippets_actions.rb'
+ - 'app/controllers/concerns/wiki_actions.rb'
+ - 'app/controllers/projects/blob_controller.rb'
+ - 'app/controllers/projects/cycle_analytics_controller.rb'
+ - 'app/controllers/projects/graphs_controller.rb'
+ - 'app/controllers/projects/pipelines_controller.rb'
+ - 'ee/app/controllers/admin/audit_logs_controller.rb'
+ - 'ee/app/controllers/admin/credentials_controller.rb'
+ - 'ee/app/controllers/ee/admin/dev_ops_report_controller.rb'
+ - 'ee/app/controllers/groups/analytics/ci_cd_analytics_controller.rb'
+ - 'ee/app/controllers/groups/analytics/devops_adoption_controller.rb'
+ - 'ee/app/controllers/groups/analytics/productivity_analytics_controller.rb'
+ - 'ee/app/controllers/groups/audit_events_controller.rb'
+ - 'ee/app/controllers/groups/contribution_analytics_controller.rb'
+ - 'ee/app/controllers/groups/epic_boards_controller.rb'
+ - 'ee/app/controllers/groups/insights_controller.rb'
+ - 'ee/app/controllers/groups/issues_analytics_controller.rb'
+ - 'ee/app/controllers/groups/security/compliance_dashboards_controller.rb'
+ - 'ee/app/controllers/projects/analytics/code_reviews_controller.rb'
+ - 'ee/app/controllers/projects/analytics/issues_analytics_controller.rb'
+ - 'ee/app/controllers/projects/analytics/merge_request_analytics_controller.rb'
+ - 'ee/app/controllers/projects/insights_controller.rb'
+ - 'ee/app/controllers/projects/integrations/jira/issues_controller.rb'
+ - 'spec/controllers/concerns/redis_tracking_spec.rb'
diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml
index ac5edc05265..ef87efb666a 100644
--- a/.rubocop_todo/gitlab/namespaced_class.yml
+++ b/.rubocop_todo/gitlab/namespaced_class.yml
@@ -402,12 +402,14 @@ Gitlab/NamespacedClass:
- 'app/policies/project_policy.rb'
- 'app/policies/project_snippet_policy.rb'
- 'app/policies/project_statistics_policy.rb'
+ - 'app/policies/project_hook_policy.rb'
- 'app/policies/prometheus_alert_policy.rb'
- 'app/policies/protected_branch_policy.rb'
- 'app/policies/release_policy.rb'
- 'app/policies/repository_policy.rb'
- 'app/policies/resource_label_event_policy.rb'
- 'app/policies/suggestion_policy.rb'
+ - 'app/policies/system_hook_policy.rb'
- 'app/policies/timebox_policy.rb'
- 'app/policies/timelog_policy.rb'
- 'app/policies/todo_policy.rb'
@@ -968,6 +970,7 @@ Gitlab/NamespacedClass:
- 'ee/app/policies/push_rule_policy.rb'
- 'ee/app/policies/saml_provider_policy.rb'
- 'ee/app/policies/vulnerability_policy.rb'
+ - 'ee/app/policies/group_hook_policy.rb'
- 'ee/app/presenters/approval_rule_presenter.rb'
- 'ee/app/presenters/audit_event_presenter.rb'
- 'ee/app/presenters/epic_issue_presenter.rb'
diff --git a/.rubocop_todo/layout/first_array_element_indentation.yml b/.rubocop_todo/layout/first_array_element_indentation.yml
index e3bbf9dc25a..84e367e0514 100644
--- a/.rubocop_todo/layout/first_array_element_indentation.yml
+++ b/.rubocop_todo/layout/first_array_element_indentation.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Layout/FirstArrayElementIndentation:
- # Offense count: 1133
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/abuse_reports_controller.rb'
- 'app/controllers/admin/application_settings_controller.rb'
@@ -22,10 +19,12 @@ Layout/FirstArrayElementIndentation:
- 'app/helpers/search_helper.rb'
- 'app/models/ci/job_token/scope.rb'
- 'app/models/container_repository.rb'
+ - 'app/models/customer_relations/contact.rb'
+ - 'app/models/customer_relations/organization.rb'
- 'app/models/group.rb'
- 'app/models/integration.rb'
- - 'app/models/integrations/bamboo.rb'
- 'app/models/internal_id.rb'
+ - 'app/models/issue.rb'
- 'app/models/member.rb'
- 'app/models/merge_request.rb'
- 'app/models/namespace.rb'
@@ -40,6 +39,7 @@ Layout/FirstArrayElementIndentation:
- 'app/workers/ssh_keys/expired_notification_worker.rb'
- 'config/initializers/postgres_partitioning.rb'
- 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb'
+ - 'ee/app/controllers/groups/settings/reporting_controller.rb'
- 'ee/app/controllers/projects/vulnerability_feedback_controller.rb'
- 'ee/app/finders/autocomplete/project_invited_groups_finder.rb'
- 'ee/app/finders/geo/project_registry_finder.rb'
@@ -47,14 +47,19 @@ Layout/FirstArrayElementIndentation:
- 'ee/app/graphql/mutations/vulnerabilities/create.rb'
- 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/trial_helper.rb'
+ - 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
- 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/ee/project.rb'
- 'ee/app/models/ee/user.rb'
+ - 'ee/app/models/ee/vulnerability.rb'
- 'ee/app/models/protected_environment.rb'
+ - 'ee/app/models/vulnerabilities/read.rb'
- 'ee/app/serializers/dashboard_environments_serializer.rb'
- 'ee/app/services/app_sec/dast/profiles/update_service.rb'
- 'ee/app/services/vulnerabilities/create_service_base.rb'
- 'ee/lib/ee/api/helpers/award_emoji.rb'
- 'ee/lib/ee/gitlab/geo_git_access.rb'
+ - 'ee/lib/gitlab/contribution_analytics/data_collector.rb'
- 'ee/lib/gitlab/elastic/helper.rb'
- 'ee/lib/gitlab/sitemaps/url_extractor.rb'
- 'ee/lib/tasks/gitlab/seed/metrics.rake'
@@ -65,14 +70,17 @@ Layout/FirstArrayElementIndentation:
- 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
- 'ee/spec/features/admin/admin_dev_ops_reports_spec.rb'
- 'ee/spec/features/boards/boards_licensed_features_spec.rb'
+ - 'ee/spec/features/groups/analytics/cycle_analytics/charts_spec.rb'
- 'ee/spec/features/groups/group_roadmap_spec.rb'
- 'ee/spec/finders/billed_users_finder_spec.rb'
- 'ee/spec/finders/merge_requests/by_approvers_finder_spec.rb'
- 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb'
+ - 'ee/spec/finders/security/scan_execution_policies_finder_spec.rb'
- 'ee/spec/frontend/fixtures/dast_profiles.rb'
- 'ee/spec/frontend/fixtures/search.rb'
- 'ee/spec/graphql/mutations/incident_management/escalation_policy/create_spec.rb'
- 'ee/spec/graphql/resolvers/dora_metrics_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/security_orchestration/scan_execution_policy_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/timebox_report_resolver_spec.rb'
- 'ee/spec/graphql/types/ci/pipeline_type_spec.rb'
- 'ee/spec/graphql/types/dast_scanner_profile_type_spec.rb'
@@ -89,6 +97,7 @@ Layout/FirstArrayElementIndentation:
- 'ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/epic_node_spec.rb'
+ - 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_links_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/graphql/loaders/bulk_epic_aggregate_loader_spec.rb'
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_ci_builds_metric_spec.rb'
@@ -104,6 +113,7 @@ Layout/FirstArrayElementIndentation:
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/ee/release_spec.rb'
- 'ee/spec/models/group_wiki_repository_spec.rb'
+ - 'ee/spec/models/namespace_setting_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/requirements_management/test_report_spec.rb'
- 'ee/spec/models/security/orchestration_policy_configuration_spec.rb'
@@ -123,6 +133,7 @@ Layout/FirstArrayElementIndentation:
- 'ee/spec/requests/api/graphql/project/alert_management/payload_fields_spec.rb'
- 'ee/spec/requests/api/graphql/project/incident_management/escalation_policy/rules_spec.rb'
- 'ee/spec/requests/api/graphql/project/merge_requests_spec.rb'
+ - 'ee/spec/requests/api/internal/kubernetes_spec.rb'
- 'ee/spec/requests/api/ldap_group_links_spec.rb'
- 'ee/spec/requests/api/members_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/value_streams/update_service_spec.rb'
@@ -130,16 +141,16 @@ Layout/FirstArrayElementIndentation:
- 'ee/spec/services/gitlab_subscriptions/fetch_purchase_eligible_namespaces_service_spec.rb'
- 'ee/spec/services/groups/seat_usage_export_service_spec.rb'
- 'ee/spec/services/iterations/cadences/create_iterations_in_advance_service_spec.rb'
- - 'ee/spec/services/iterations/cadences/create_service_spec.rb'
- 'ee/spec/services/protected_environments/base_service_spec.rb'
- 'ee/spec/services/search_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/hooks_execution_spec.rb'
- 'ee/spec/services/security/security_orchestration_policies/process_scan_result_policy_service_spec.rb'
- 'ee/spec/services/security/store_findings_metadata_service_spec.rb'
- 'ee/spec/services/timebox_report_service_spec.rb'
- 'ee/spec/services/user_permissions/export_service_spec.rb'
- 'ee/spec/support/shared_examples/services/search_notes_shared_examples.rb'
- 'ee/spec/workers/geo/scheduler/scheduler_worker_spec.rb'
- - 'lib/gitlab/background_migration/fix_merge_request_diff_commit_users.rb'
+ - 'lib/event_filter.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/gitlab/email/message/in_product_marketing/team.rb'
- 'lib/gitlab/email/message/in_product_marketing/trial.rb'
@@ -153,25 +164,27 @@ Layout/FirstArrayElementIndentation:
- '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/snippet/copy_snippet_file_contents_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/npm/npm_instance_level_spec.rb'
- - 'qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_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'
@@ -189,12 +202,14 @@ Layout/FirstArrayElementIndentation:
- 'spec/controllers/projects/pipelines_controller_spec.rb'
- 'spec/deprecation_toolkit_env.rb'
- 'spec/features/clusters/create_agent_spec.rb'
- - 'spec/features/issues/filtered_search/filter_issues_spec.rb'
- - 'spec/features/issues/filtered_search/visual_tokens_spec.rb'
+ - 'spec/finders/bulk_imports/entities_finder_spec.rb'
- 'spec/finders/ci/daily_build_group_report_results_finder_spec.rb'
- 'spec/finders/deploy_tokens/tokens_finder_spec.rb'
+ - 'spec/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder_spec.rb'
+ - 'spec/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder_spec.rb'
- 'spec/frontend/fixtures/search.rb'
- 'spec/graphql/mutations/commits/create_spec.rb'
+ - 'spec/graphql/mutations/environments/canary_ingress/update_spec.rb'
- 'spec/graphql/resolvers/ci/test_suite_resolver_spec.rb'
- 'spec/graphql/types/ci/runner_architecture_type_spec.rb'
- 'spec/graphql/types/ci/runner_platform_type_spec.rb'
@@ -217,8 +232,10 @@ Layout/FirstArrayElementIndentation:
- '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/entry/root_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'
@@ -241,9 +258,13 @@ Layout/FirstArrayElementIndentation:
- '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/gitlab_import/importer_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'
@@ -263,13 +284,16 @@ Layout/FirstArrayElementIndentation:
- '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'
@@ -279,6 +303,7 @@ Layout/FirstArrayElementIndentation:
- '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'
@@ -293,6 +318,7 @@ Layout/FirstArrayElementIndentation:
- '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'
@@ -300,6 +326,8 @@ Layout/FirstArrayElementIndentation:
- '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'
@@ -309,24 +337,30 @@ Layout/FirstArrayElementIndentation:
- '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'
@@ -338,9 +372,9 @@ Layout/FirstArrayElementIndentation:
- 'spec/simplecov_env.rb'
- 'spec/support/atlassian/jira_connect/schemata.rb'
- 'spec/support/capybara.rb'
+ - 'spec/support/helpers/project_template_test_helper.rb'
- 'spec/support/helpers/test_env.rb'
- 'spec/support/helpers/usage_data_helpers.rb'
- - 'spec/support/matchers/background_migrations_matchers.rb'
- 'spec/support/matchers/exceed_query_limit.rb'
- 'spec/support/migrations_helpers/vulnerabilities_findings_helper.rb'
- 'spec/support/prometheus/additional_metrics_shared_examples.rb'
diff --git a/.rubocop_todo/layout/first_hash_element_indentation.yml b/.rubocop_todo/layout/first_hash_element_indentation.yml
index 22d66dcb8c1..94ad3fde252 100644
--- a/.rubocop_todo/layout/first_hash_element_indentation.yml
+++ b/.rubocop_todo/layout/first_hash_element_indentation.yml
@@ -1,10 +1,9 @@
---
# Cop supports --auto-correct.
Layout/FirstHashElementIndentation:
- # Offense count: 1995
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'app/components/diffs/stats_component.rb'
+ - 'app/controllers/admin/ci/variables_controller.rb'
- 'app/controllers/admin/system_info_controller.rb'
- 'app/controllers/boards/issues_controller.rb'
- 'app/controllers/concerns/issuable_actions.rb'
@@ -13,7 +12,6 @@ Layout/FirstHashElementIndentation:
- 'app/controllers/concerns/sourcegraph_decorator.rb'
- 'app/controllers/profiles/two_factor_auths_controller.rb'
- 'app/controllers/projects/badges_controller.rb'
- - 'app/controllers/projects/merge_requests_controller.rb'
- 'app/controllers/repositories/lfs_locks_api_controller.rb'
- 'app/experiments/concerns/project_commit_count.rb'
- 'app/graphql/mutations/clusters/agent_tokens/create.rb'
@@ -26,12 +24,12 @@ Layout/FirstHashElementIndentation:
- 'app/helpers/breadcrumbs_helper.rb'
- 'app/helpers/broadcast_messages_helper.rb'
- 'app/helpers/commits_helper.rb'
- - 'app/helpers/diff_helper.rb'
- 'app/helpers/environments_helper.rb'
- 'app/helpers/icons_helper.rb'
- 'app/helpers/keyset_helper.rb'
- 'app/helpers/listbox_helper.rb'
- 'app/helpers/page_layout_helper.rb'
+ - 'app/helpers/projects/project_members_helper.rb'
- 'app/helpers/search_helper.rb'
- 'app/helpers/sorting_helper.rb'
- 'app/helpers/ssh_keys_helper.rb'
@@ -45,6 +43,7 @@ Layout/FirstHashElementIndentation:
- 'app/models/ci/build_metadata.rb'
- 'app/models/ci/runner.rb'
- 'app/models/clusters/applications/crossplane.rb'
+ - 'app/models/clusters/platforms/kubernetes.rb'
- 'app/models/concerns/cross_database_modification.rb'
- 'app/models/concerns/featurable.rb'
- 'app/models/concerns/has_wiki_page_slug_attributes.rb'
@@ -65,14 +64,27 @@ Layout/FirstHashElementIndentation:
- 'app/serializers/cluster_serializer.rb'
- 'app/serializers/detailed_status_entity.rb'
- 'app/services/award_emojis/base_service.rb'
+ - 'app/services/ci/runners/reconcile_existing_runner_versions_service.rb'
- 'app/services/google_cloud/create_service_accounts_service.rb'
- 'app/services/members/create_service.rb'
- 'app/services/notification_service.rb'
- 'app/services/packages/composer/create_package_service.rb'
+ - 'app/services/pages/delete_service.rb'
+ - 'app/services/projects/after_rename_service.rb'
+ - 'app/services/projects/create_service.rb'
+ - 'app/services/projects/destroy_service.rb'
+ - 'app/services/projects/transfer_service.rb'
+ - 'app/services/projects/update_pages_service.rb'
+ - 'app/services/projects/update_service.rb'
- 'app/services/resource_events/change_milestone_service.rb'
- 'app/services/spam/ham_service.rb'
+ - 'app/services/timelogs/base_service.rb'
- 'app/validators/addressable_url_validator.rb'
- 'app/workers/concerns/cluster_cleanup_methods.rb'
+ - 'ee/app/components/namespaces/free_user_cap/alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personal_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personal_preview_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/preview_alert_component.rb'
- 'ee/app/controllers/groups/analytics/tasks_by_type_controller.rb'
- 'ee/app/graphql/mutations/boards/epic_lists/destroy.rb'
- 'ee/app/graphql/mutations/boards/epics/create.rb'
@@ -81,9 +93,12 @@ Layout/FirstHashElementIndentation:
- 'ee/app/graphql/mutations/iterations/update.rb'
- 'ee/app/graphql/mutations/projects/set_compliance_framework.rb'
- 'ee/app/graphql/mutations/security_policy/commit_scan_execution_policy.rb'
+ - 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/ci/jobs_helper.rb'
- 'ee/app/helpers/ee/geo_helper.rb'
- 'ee/app/helpers/ee/groups/group_members_helper.rb'
+ - 'ee/app/helpers/ee/members_helper.rb'
+ - 'ee/app/helpers/ee/namespaces_helper.rb'
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/helpers/ee/sidebars_helper.rb'
- 'ee/app/helpers/ee/tree_helper.rb'
@@ -96,19 +111,22 @@ Layout/FirstHashElementIndentation:
- 'ee/app/serializers/ee/environment_serializer.rb'
- 'ee/app/services/app_sec/dast/profiles/update_service.rb'
- 'ee/app/services/app_sec/dast/site_profiles/update_service.rb'
+ - 'ee/app/services/audit_events/build_service.rb'
- 'ee/app/services/ee/auth/container_registry_authentication_service.rb'
- 'ee/app/services/ee/ci/register_job_service.rb'
- 'ee/app/services/ee/issues/export_csv_service.rb'
- 'ee/app/services/elastic/cluster_reindexing_service.rb'
- 'ee/app/services/gitlab_subscriptions/plan_upgrade_service.rb'
+ - 'ee/app/services/incident_management/issuable_resource_links/base_service.rb'
- 'ee/app/services/jira/requests/issues/list_service.rb'
- - 'ee/app/services/projects/slack_application_install_service.rb'
- 'ee/app/services/security/token_revocation_service.rb'
- 'ee/app/services/timebox_report_service.rb'
- 'ee/app/workers/elastic_delete_project_worker.rb'
- 'ee/app/workers/groups/create_event_worker.rb'
- 'ee/lib/api/epic_links.rb'
+ - 'ee/lib/ee/api/geo.rb'
- 'ee/lib/ee/container_registry/client.rb'
+ - 'ee/lib/ee/gitlab/application_rate_limiter.rb'
- 'ee/lib/ee/gitlab/ci/parsers.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
- 'ee/lib/elastic/latest/application_class_proxy.rb'
@@ -122,20 +140,23 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/controllers/boards/users_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/jobs_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/variables_controller_spec.rb'
+ - 'ee/spec/controllers/groups/analytics/cycle_analytics/summary_controller_spec.rb'
- 'ee/spec/controllers/groups/epic_boards_controller_spec.rb'
- 'ee/spec/controllers/groups/issues_controller_spec.rb'
- 'ee/spec/controllers/projects/boards_controller_spec.rb'
- 'ee/spec/controllers/projects/feature_flag_issues_controller_spec.rb'
- 'ee/spec/controllers/projects/imports_controller_spec.rb'
+ - 'ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb'
- 'ee/spec/controllers/projects/licenses_controller_spec.rb'
- 'ee/spec/controllers/projects/vulnerability_feedback_controller_spec.rb'
- 'ee/spec/controllers/projects_controller_spec.rb'
- 'ee/spec/controllers/security/projects_controller_spec.rb'
- - 'ee/spec/elastic/migrate/20210421140400_add_new_data_to_merge_requests_documents_spec.rb'
- - 'ee/spec/elastic/migrate/20210623081800_add_upvotes_to_issues_spec.rb'
+ - 'ee/spec/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index_spec.rb'
- 'ee/spec/factories/dependencies.rb'
- 'ee/spec/factories/licenses.rb'
+ - 'ee/spec/features/registrations/saas_user_registration_spec.rb'
- 'ee/spec/finders/epics_finder_spec.rb'
+ - 'ee/spec/finders/security/scan_execution_policies_finder_spec.rb'
- 'ee/spec/frontend/fixtures/dast_profiles.rb'
- 'ee/spec/frontend/fixtures/on_demand_dast_scans.rb'
- 'ee/spec/frontend/fixtures/search.rb'
@@ -143,9 +164,14 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/graphql/types/vulnerability_request_response_header_type_spec.rb'
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
- 'ee/spec/helpers/ee/access_tokens_helper_spec.rb'
+ - 'ee/spec/helpers/ee/groups_helper_spec.rb'
+ - 'ee/spec/helpers/ee/invite_members_helper_spec.rb'
- 'ee/spec/helpers/ee/labels_helper_spec.rb'
+ - 'ee/spec/helpers/ee/namespaces_helper_spec.rb'
+ - 'ee/spec/helpers/ee/projects/pipeline_helper_spec.rb'
- 'ee/spec/helpers/ee/projects/security/dast_configuration_helper_spec.rb'
- 'ee/spec/helpers/ee/projects/security/sast_configuration_helper_spec.rb'
+ - 'ee/spec/helpers/ee/security_orchestration_helper_spec.rb'
- 'ee/spec/helpers/groups/sso_helper_spec.rb'
- 'ee/spec/helpers/nav/new_dropdown_helper_spec.rb'
- 'ee/spec/helpers/projects_helper_spec.rb'
@@ -154,17 +180,19 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/helpers/security_helper_spec.rb'
- 'ee/spec/helpers/trial_registrations/reassurances_helper_spec.rb'
- 'ee/spec/lib/container_registry/client_spec.rb'
- - 'ee/spec/lib/ee/audit/project_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/backup/repositories_spec.rb'
- 'ee/spec/lib/ee/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/config/entry/bridge_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/parsers/security/common_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/request_params_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
- 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/membership_updater_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/saml/membership_updater_spec.rb'
- 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
- 'ee/spec/lib/gitlab/ci/config/entry/job_spec.rb'
- 'ee/spec/lib/gitlab/ci/parsers/security/dast_spec.rb'
@@ -173,9 +201,11 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'ee/spec/lib/gitlab/contribution_analytics/data_collector_spec.rb'
- 'ee/spec/lib/gitlab/elastic/indexer_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/lease_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/subscription_portal/clients/graphql_spec.rb'
- 'ee/spec/lib/gitlab/web_ide/config/entry/schemas_spec.rb'
+ - 'ee/spec/lib/system_check/app/search_check_spec.rb'
- 'ee/spec/mailers/credentials_inventory_mailer_spec.rb'
- 'ee/spec/mailers/emails/requirements_spec.rb'
- 'ee/spec/models/analytics/cycle_analytics/project_stage_spec.rb'
@@ -186,25 +216,28 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/models/security/finding_spec.rb'
- 'ee/spec/requests/api/analytics/project_deployment_frequency_spec.rb'
- 'ee/spec/requests/api/experiments_spec.rb'
+ - 'ee/spec/requests/api/geo_spec.rb'
- 'ee/spec/requests/api/graphql/app_sec/fuzzing/api/ci_configuration_type_spec.rb'
- 'ee/spec/requests/api/graphql/app_sec/fuzzing/coverage/corpus_type_spec.rb'
- 'ee/spec/requests/api/graphql/ci/minutes/usage_spec.rb'
- - 'ee/spec/requests/api/graphql/merge_requests/approval_state_spec.rb'
- 'ee/spec/requests/api/graphql/milestone_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/app_sec/fuzzing/api/ci_configuration/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/gitlab_subscriptions/activate_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/issues/update_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/iterations/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/timelogs/create_spec.rb'
- 'ee/spec/requests/api/internal/base_spec.rb'
- 'ee/spec/requests/api/internal/upcoming_reconciliations_spec.rb'
- 'ee/spec/requests/api/members_spec.rb'
- 'ee/spec/requests/api/merge_requests_spec.rb'
- 'ee/spec/requests/groups/group_members_controller_spec.rb'
+ - 'ee/spec/requests/groups/usage_quotas_spec.rb'
- 'ee/spec/requests/projects/issue_feature_flags_controller_spec.rb'
- 'ee/spec/requests/projects/mirrors_controller_spec.rb'
- 'ee/spec/serializers/issues/linked_issue_feature_flag_entity_spec.rb'
- 'ee/spec/serializers/license_entity_spec.rb'
- 'ee/spec/serializers/linked_feature_flag_issue_entity_spec.rb'
+ - 'ee/spec/serializers/security/vulnerability_report_data_entity_spec.rb'
+ - 'ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/data_loader_service_spec.rb'
- 'ee/spec/services/app_sec/dast/profile_schedules/audit/update_service_spec.rb'
- 'ee/spec/services/app_sec/dast/profiles/audit/update_service_spec.rb'
@@ -220,19 +253,29 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/services/app_sec/fuzzing/coverage/corpuses/create_service_spec.rb'
- 'ee/spec/services/approval_rules/create_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb'
+ - 'ee/spec/services/arkose/user_verification_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
- 'ee/spec/services/ci/create_pipeline_service_spec.rb'
+ - 'ee/spec/services/ci/runners/stale_group_runners_prune_service_spec.rb'
- 'ee/spec/services/ee/alert_management/http_integrations/create_service_spec.rb'
- 'ee/spec/services/ee/alert_management/http_integrations/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/post_receive_service_spec.rb'
+ - 'ee/spec/services/external_status_checks/create_service_spec.rb'
- 'ee/spec/services/geo/node_status_request_service_spec.rb'
- 'ee/spec/services/geo/registry_consistency_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/check_future_renewal_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/create_trial_or_lead_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/plan_upgrade_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/preview_billable_user_change_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/reconciliations/calculate_seat_count_data_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/reconciliations/check_seat_usage_alerts_eligibility_service_spec.rb'
- 'ee/spec/services/groups/create_service_spec.rb'
- 'ee/spec/services/groups/destroy_service_spec.rb'
- 'ee/spec/services/iterations/create_service_spec.rb'
+ - 'ee/spec/services/namespaces/free_user_cap/deactivate_members_over_limit_service_spec.rb'
+ - 'ee/spec/services/namespaces/free_user_cap/remove_group_group_links_outside_hierarchy_service_spec.rb'
- 'ee/spec/services/projects/create_service_spec.rb'
- 'ee/spec/services/projects/group_links/create_service_spec.rb'
- 'ee/spec/services/projects/group_links/destroy_service_spec.rb'
@@ -242,9 +285,16 @@ Layout/FirstHashElementIndentation:
- 'ee/spec/services/security/token_revocation_service_spec.rb'
- 'ee/spec/services/security/track_scan_service_spec.rb'
- 'ee/spec/services/timebox_report_service_spec.rb'
+ - 'ee/spec/services/users/abuse/excessive_projects_download_ban_service_spec.rb'
+ - 'ee/spec/services/users/abuse/git_abuse/namespace_throttle_service_spec.rb'
- 'ee/spec/support/helpers/ee/login_helpers.rb'
- 'ee/spec/support/shared_contexts/fixtures/analytics_shared_context.rb'
- 'ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/shared_stage_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/controllers/namespace_storage_limit_alert_shared_examples.rb'
+ - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
+ - 'ee/spec/workers/analytics/cycle_analytics/consistency_worker_spec.rb'
+ - 'ee/spec/workers/ci/runners/stale_group_runners_prune_cron_worker_spec.rb'
+ - 'ee/spec/workers/gitlab_subscriptions/notify_seats_exceeded_worker_spec.rb'
- 'lib/api/admin/instance_clusters.rb'
- 'lib/api/group_clusters.rb'
- 'lib/api/project_clusters.rb'
@@ -264,6 +314,7 @@ Layout/FirstHashElementIndentation:
- 'lib/gitlab/github_import/importer/diff_note_importer.rb'
- 'lib/gitlab/github_import/importer/pull_request_merged_by_importer.rb'
- 'lib/gitlab/gitlab_import/client.rb'
+ - 'lib/gitlab/graphql/query_analyzers/ast/logger_analyzer.rb'
- 'lib/gitlab/hook_data/issue_builder.rb'
- 'lib/gitlab/hook_data/release_builder.rb'
- 'lib/gitlab/kubernetes.rb'
@@ -279,10 +330,9 @@ Layout/FirstHashElementIndentation:
- 'qa/qa/ee/resource/board/board_list/project/assignee_board_list.rb'
- 'qa/qa/ee/resource/board/board_list/project/milestone_board_list.rb'
- 'qa/qa/resource/snippet.rb'
+ - 'qa/qa/specs/features/api/3_create/repository/commit_to_templated_project_spec.rb'
- 'qa/qa/specs/features/api/5_package/container_registry_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_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/container_registry/container_registry_omnibus_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb'
@@ -294,8 +344,11 @@ Layout/FirstHashElementIndentation:
- '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/browser_ui/5_package/package_registry/pypi_repository_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/13_secure/security_reports_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/new_discussion_not_dropping_merge_trains_mr_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/9_enablement/elasticsearch/elasticsearch_reindexing_spec.rb'
+ - 'spec/components/diffs/stats_component_spec.rb'
+ - 'spec/components/pajamas/component_spec.rb'
- 'spec/config/object_store_settings_spec.rb'
- 'spec/config/smime_signature_settings_spec.rb'
- 'spec/controllers/admin/groups_controller_spec.rb'
@@ -319,7 +372,6 @@ Layout/FirstHashElementIndentation:
- 'spec/controllers/projects/environments_controller_spec.rb'
- 'spec/controllers/projects/feature_flags_controller_spec.rb'
- 'spec/controllers/projects/grafana_api_controller_spec.rb'
- - 'spec/controllers/projects/group_links_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'
@@ -336,27 +388,31 @@ Layout/FirstHashElementIndentation:
- 'spec/controllers/projects/web_ide_terminals_controller_spec.rb'
- 'spec/controllers/projects_controller_spec.rb'
- 'spec/factories/ci/builds.rb'
- - 'spec/factories/container_repositories.rb'
- 'spec/factories/packages/debian/file_metadatum.rb'
- 'spec/features/gitlab_experiments_spec.rb'
- 'spec/frontend/fixtures/autocomplete_sources.rb'
- 'spec/frontend/fixtures/blob.rb'
+ - 'spec/frontend/fixtures/jobs.rb'
- 'spec/frontend/fixtures/runner.rb'
- 'spec/graphql/mutations/release_asset_links/create_spec.rb'
- 'spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb'
+ - 'spec/graphql/resolvers/crm/organizations_resolver_spec.rb'
- 'spec/graphql/types/ci/detailed_status_type_spec.rb'
+ - 'spec/helpers/access_tokens_helper_spec.rb'
+ - 'spec/helpers/admin/application_settings/settings_helper_spec.rb'
- 'spec/helpers/admin/deploy_key_helper_spec.rb'
- 'spec/helpers/analytics/cycle_analytics_helper_spec.rb'
- 'spec/helpers/ci/builds_helper_spec.rb'
- 'spec/helpers/ci/jobs_helper_spec.rb'
- 'spec/helpers/ci/pipeline_editor_helper_spec.rb'
- - 'spec/helpers/ci/runners_helper_spec.rb'
- 'spec/helpers/deploy_tokens_helper_spec.rb'
- 'spec/helpers/groups/settings_helper_spec.rb'
+ - 'spec/helpers/groups_helper_spec.rb'
- 'spec/helpers/issuables_helper_spec.rb'
- 'spec/helpers/namespaces_helper_spec.rb'
- 'spec/helpers/page_layout_helper_spec.rb'
- 'spec/helpers/projects/cluster_agents_helper_spec.rb'
+ - 'spec/helpers/projects/pipeline_helper_spec.rb'
- 'spec/helpers/releases_helper_spec.rb'
- 'spec/helpers/routing/pseudonymization_helper_spec.rb'
- 'spec/helpers/search_helper_spec.rb'
@@ -367,14 +423,18 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/api/entities/design_management/design_spec.rb'
- 'spec/lib/api/entities/merge_request_approvals_spec.rb'
- 'spec/lib/api/entities/personal_access_token_spec.rb'
+ - 'spec/lib/api/entities/personal_access_token_with_details_spec.rb'
- 'spec/lib/atlassian/jira_connect/client_spec.rb'
- 'spec/lib/backup/database_spec.rb'
+ - 'spec/lib/backup/repositories_spec.rb'
- 'spec/lib/banzai/filter/audio_link_filter_spec.rb'
- 'spec/lib/banzai/filter/repository_link_filter_spec.rb'
- 'spec/lib/banzai/filter/video_link_filter_spec.rb'
- 'spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb'
- 'spec/lib/bulk_imports/groups/pipelines/project_entities_pipeline_spec.rb'
- 'spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb'
+ - 'spec/lib/bulk_imports/groups/stage_spec.rb'
+ - 'spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb'
- 'spec/lib/container_registry/client_spec.rb'
@@ -402,9 +462,11 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/gitlab/ci/config/yaml/tags/resolver_spec.rb'
- 'spec/lib/gitlab/ci/config_spec.rb'
- 'spec/lib/gitlab/ci/parsers/codequality/code_climate_spec.rb'
+ - 'spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/common_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb'
+ - 'spec/lib/gitlab/ci/reports/coverage_report_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/identifier_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/scanner_spec.rb'
- 'spec/lib/gitlab/ci/reports/terraform_reports_spec.rb'
@@ -412,11 +474,15 @@ Layout/FirstHashElementIndentation:
- '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'
- 'spec/lib/gitlab/data_builder/pipeline_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/setup_spec.rb'
+ - 'spec/lib/gitlab/database/migration_helpers_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/database_spec.rb'
- 'spec/lib/gitlab/diff/position_spec.rb'
+ - 'spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb'
+ - 'spec/lib/gitlab/error_tracking_spec.rb'
- 'spec/lib/gitlab/experimentation/controller_concern_spec.rb'
- 'spec/lib/gitlab/experimentation_spec.rb'
- 'spec/lib/gitlab/git/conflict/file_spec.rb'
@@ -428,6 +494,7 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/gitlab/github_import/logger_spec.rb'
- 'spec/lib/gitlab/github_import/object_counter_spec.rb'
- 'spec/lib/gitlab/gpg_spec.rb'
+ - 'spec/lib/gitlab/graphql/query_analyzers/ast/logger_analyzer_spec.rb'
- 'spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb'
- 'spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb'
- 'spec/lib/gitlab/http_spec.rb'
@@ -439,6 +506,7 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/gitlab/kubernetes/kubeconfig/template_spec.rb'
- 'spec/lib/gitlab/kubernetes/rollout_instances_spec.rb'
- 'spec/lib/gitlab/legacy_github_import/label_formatter_spec.rb'
+ - 'spec/lib/gitlab/memory/watchdog_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/action_cable_spec.rb'
- 'spec/lib/gitlab/middleware/multipart/handler_spec.rb'
@@ -448,7 +516,6 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/gitlab/push_options_spec.rb'
- 'spec/lib/gitlab/submodule_links_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/web_ide/config/entry/global_spec.rb'
- 'spec/lib/mattermost/team_spec.rb'
@@ -456,11 +523,13 @@ Layout/FirstHashElementIndentation:
- 'spec/lib/peek/views/memory_spec.rb'
- 'spec/mailers/emails/merge_requests_spec.rb'
- 'spec/models/active_session_spec.rb'
+ - 'spec/models/analytics/cycle_analytics/aggregation_spec.rb'
- 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/ci_platform_metric_spec.rb'
- 'spec/models/clusters/applications/prometheus_spec.rb'
- 'spec/models/event_spec.rb'
- 'spec/models/gpg_key_spec.rb'
+ - 'spec/models/instance_configuration_spec.rb'
- 'spec/models/integrations/base_chat_notification_spec.rb'
- 'spec/models/integrations/chat_message/deployment_message_spec.rb'
- 'spec/models/integrations/chat_message/issue_message_spec.rb'
@@ -480,12 +549,14 @@ Layout/FirstHashElementIndentation:
- 'spec/requests/api/feature_flags_spec.rb'
- 'spec/requests/api/feature_flags_user_lists_spec.rb'
- 'spec/requests/api/graphql/ci/config_spec.rb'
+ - 'spec/requests/api/graphql/ci/group_variables_spec.rb'
+ - 'spec/requests/api/graphql/ci/instance_variables_spec.rb'
+ - 'spec/requests/api/graphql/ci/project_variables_spec.rb'
- 'spec/requests/api/graphql/group/milestones_spec.rb'
- 'spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb'
+ - 'spec/requests/api/graphql/mutations/timelogs/create_spec.rb'
- 'spec/requests/api/graphql/project/cluster_agents_spec.rb'
- 'spec/requests/api/graphql/project/release_spec.rb'
- - 'spec/requests/api/graphql/project/terraform/state_spec.rb'
- - 'spec/requests/api/graphql/project/terraform/states_spec.rb'
- 'spec/requests/api/graphql/project_query_spec.rb'
- 'spec/requests/api/internal/base_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
@@ -503,19 +574,29 @@ Layout/FirstHashElementIndentation:
- 'spec/requests/jira_connect/installations_controller_spec.rb'
- 'spec/requests/lfs_http_spec.rb'
- 'spec/serializers/blob_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/services/bulk_imports/create_pipeline_trackers_service_spec.rb'
- 'spec/services/ci/create_pipeline_service/custom_yaml_tags_spec.rb'
- 'spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
- 'spec/services/ci/find_exposed_artifacts_service_spec.rb'
- 'spec/services/ci/play_manual_stage_service_spec.rb'
+ - 'spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb'
- 'spec/services/clusters/agents/create_service_spec.rb'
- 'spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb'
- 'spec/services/clusters/aws/authorize_role_service_spec.rb'
- 'spec/services/clusters/update_service_spec.rb'
- 'spec/services/commits/tag_service_spec.rb'
+ - 'spec/services/database/consistency_check_service_spec.rb'
- 'spec/services/git/branch_push_service_spec.rb'
+ - 'spec/services/google_cloud/create_cloudsql_instance_service_spec.rb'
+ - 'spec/services/import/fogbugz_service_spec.rb'
- 'spec/services/import/github_service_spec.rb'
- 'spec/services/import/gitlab_projects/file_acquisition_strategies/remote_file_spec.rb'
+ - 'spec/services/markdown_content_rewriter_service_spec.rb'
+ - 'spec/services/merge_requests/build_service_spec.rb'
- 'spec/services/merge_requests/create_service_spec.rb'
- 'spec/services/merge_requests/get_urls_service_spec.rb'
- 'spec/services/merge_requests/refresh_service_spec.rb'
@@ -528,6 +609,7 @@ Layout/FirstHashElementIndentation:
- 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
- 'spec/services/projects/operations/update_service_spec.rb'
- 'spec/services/projects/update_service_spec.rb'
+ - 'spec/services/service_ping/submit_service_ping_service_spec.rb'
- 'spec/services/snippets/count_service_spec.rb'
- 'spec/sidekiq_cluster/sidekiq_cluster_spec.rb'
- 'spec/support/atlassian/jira_connect/schemata.rb'
@@ -541,6 +623,9 @@ Layout/FirstHashElementIndentation:
- 'spec/support/shared_contexts/fixtures/analytics_shared_context.rb'
- 'spec/support/shared_contexts/lib/container_registry/client_shared_context.rb'
- 'spec/support/shared_examples/graphql/spam_protection_shared_examples.rb'
+ - 'spec/support/shared_examples/harbor/artifacts_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/harbor/repositories_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/harbor/tags_controller_shared_examples.rb'
- 'spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb'
- 'spec/support/shared_examples/models/clusters/prometheus_client_shared.rb'
- 'spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb'
@@ -551,4 +636,6 @@ Layout/FirstHashElementIndentation:
- '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'
+ - 'spec/workers/ci/runners/reconcile_existing_runner_versions_cron_worker_spec.rb'
- 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
diff --git a/.rubocop_todo/layout/hash_alignment.yml b/.rubocop_todo/layout/hash_alignment.yml
index d6772537f47..4a98bcea706 100644
--- a/.rubocop_todo/layout/hash_alignment.yml
+++ b/.rubocop_todo/layout/hash_alignment.yml
@@ -1,378 +1,26 @@
---
# Cop supports --auto-correct.
Layout/HashAlignment:
- # Offense count: 3804
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- - 'app/controllers/admin/ci/variables_controller.rb'
- - 'app/controllers/admin/system_info_controller.rb'
- - 'app/controllers/oauth/token_info_controller.rb'
- - 'app/controllers/projects/feature_flags_controller.rb'
- - 'app/controllers/repositories/git_http_client_controller.rb'
- - 'app/controllers/repositories/lfs_api_controller.rb'
- - 'app/controllers/repositories/lfs_locks_api_controller.rb'
- - 'app/controllers/uploads_controller.rb'
- - 'app/graphql/mutations/award_emojis/toggle.rb'
- - 'app/graphql/mutations/ci/runner/update.rb'
- - 'app/graphql/mutations/design_management/move.rb'
- - 'app/graphql/mutations/issues/set_severity.rb'
- - 'app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb'
- - 'app/graphql/resolvers/ci/template_resolver.rb'
- - 'app/graphql/resolvers/projects_resolver.rb'
- - 'app/graphql/resolvers/users_resolver.rb'
- - 'app/graphql/types/access_level_type.rb'
- - 'app/graphql/types/admin/analytics/usage_trends/measurement_type.rb'
- - 'app/graphql/types/board_list_type.rb'
- - 'app/graphql/types/board_type.rb'
- - 'app/graphql/types/ci/analytics_type.rb'
- - 'app/graphql/types/ci/application_setting_type.rb'
- - 'app/graphql/types/ci/build_need_type.rb'
- - 'app/graphql/types/ci/ci_cd_setting_type.rb'
- - 'app/graphql/types/ci/config/config_type.rb'
- - 'app/graphql/types/ci/config/group_type.rb'
- - 'app/graphql/types/ci/config/job_restriction_type.rb'
- - 'app/graphql/types/ci/config/job_type.rb'
- - 'app/graphql/types/ci/config/need_type.rb'
- - 'app/graphql/types/ci/config/stage_type.rb'
- - 'app/graphql/types/ci/detailed_status_type.rb'
- - 'app/graphql/types/ci/group_type.rb'
- - 'app/graphql/types/ci/job_artifact_type.rb'
- - 'app/graphql/types/ci/job_token_scope_type.rb'
- - 'app/graphql/types/ci/job_type.rb'
- - 'app/graphql/types/ci/pipeline_message_type.rb'
- - 'app/graphql/types/ci/pipeline_type.rb'
- - 'app/graphql/types/ci/recent_failures_type.rb'
- - 'app/graphql/types/ci/runner_architecture_type.rb'
- - 'app/graphql/types/ci/runner_platform_type.rb'
- - 'app/graphql/types/ci/runner_setup_type.rb'
- - 'app/graphql/types/ci/runner_type.rb'
- - 'app/graphql/types/ci/runner_web_url_edge.rb'
- - 'app/graphql/types/ci/stage_type.rb'
- - 'app/graphql/types/ci/status_action_type.rb'
- - 'app/graphql/types/ci/template_type.rb'
- - 'app/graphql/types/ci/test_case_type.rb'
- - 'app/graphql/types/ci/test_report_summary_type.rb'
- - 'app/graphql/types/ci/test_report_total_type.rb'
- - 'app/graphql/types/ci/test_suite_summary_type.rb'
- - 'app/graphql/types/ci/test_suite_type.rb'
- - 'app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb'
- - 'app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb'
- - 'app/graphql/types/ci_configuration/sast/entity_input_type.rb'
- - 'app/graphql/types/ci_configuration/sast/entity_type.rb'
- - 'app/graphql/types/ci_configuration/sast/options_entity_type.rb'
- - 'app/graphql/types/ci_configuration/sast/type.rb'
- - 'app/graphql/types/commit_action_type.rb'
- - 'app/graphql/types/commit_type.rb'
- - 'app/graphql/types/countable_connection_type.rb'
- - 'app/graphql/types/design_management/design_collection_type.rb'
- - 'app/graphql/types/design_management/design_fields.rb'
- - 'app/graphql/types/design_management/version_type.rb'
- - 'app/graphql/types/diff_paths_input_type.rb'
- - 'app/graphql/types/diff_refs_type.rb'
- - 'app/graphql/types/diff_stats_summary_type.rb'
- - 'app/graphql/types/diff_stats_type.rb'
- - 'app/graphql/types/environment_type.rb'
- - 'app/graphql/types/evidence_type.rb'
- - 'app/graphql/types/grafana_integration_type.rb'
- - 'app/graphql/types/group_invitation_type.rb'
- - 'app/graphql/types/group_member_type.rb'
- - 'app/graphql/types/group_type.rb'
- - 'app/graphql/types/invitation_interface.rb'
- - 'app/graphql/types/issue_type.rb'
- - 'app/graphql/types/jira_import_type.rb'
- - 'app/graphql/types/jira_user_type.rb'
- - 'app/graphql/types/label_type.rb'
- - 'app/graphql/types/member_interface.rb'
- - 'app/graphql/types/merge_request_connection_type.rb'
- - 'app/graphql/types/merge_request_type.rb'
- - 'app/graphql/types/metadata/kas_type.rb'
- - 'app/graphql/types/metadata_type.rb'
- - 'app/graphql/types/metrics/dashboard_type.rb'
- - 'app/graphql/types/metrics/dashboards/annotation_type.rb'
- - 'app/graphql/types/milestone_stats_type.rb'
- - 'app/graphql/types/milestone_type.rb'
- - 'app/graphql/types/namespace_type.rb'
- - 'app/graphql/types/notes/diff_image_position_input_type.rb'
- - 'app/graphql/types/notes/diff_position_base_input_type.rb'
- - 'app/graphql/types/notes/diff_position_input_type.rb'
- - 'app/graphql/types/notes/diff_position_type.rb'
- - 'app/graphql/types/notes/discussion_type.rb'
- - 'app/graphql/types/notes/note_type.rb'
- - 'app/graphql/types/packages/package_details_type.rb'
- - 'app/graphql/types/packages/package_file_type.rb'
- - 'app/graphql/types/packages/package_type.rb'
- - 'app/graphql/types/project_invitation_type.rb'
- - 'app/graphql/types/project_member_type.rb'
- - 'app/graphql/types/project_statistics_type.rb'
- - 'app/graphql/types/project_type.rb'
- - 'app/graphql/types/projects/service_type.rb'
- - 'app/graphql/types/projects/services/jira_project_type.rb'
- - 'app/graphql/types/projects/topic_type.rb'
- - 'app/graphql/types/prometheus_alert_type.rb'
- - 'app/graphql/types/release_asset_link_type.rb'
- - 'app/graphql/types/release_assets_type.rb'
- - 'app/graphql/types/release_links_type.rb'
- - 'app/graphql/types/release_source_type.rb'
- - 'app/graphql/types/release_type.rb'
- - 'app/graphql/types/repository/blob_type.rb'
- - 'app/graphql/types/repository_type.rb'
- - 'app/graphql/types/resolvable_interface.rb'
- - 'app/graphql/types/snippet_type.rb'
- - 'app/graphql/types/snippets/blob_connection_type.rb'
- - 'app/graphql/types/snippets/blob_type.rb'
- - 'app/graphql/types/subscription_type.rb'
- - 'app/graphql/types/task_completion_status.rb'
- - 'app/graphql/types/tree/blob_type.rb'
- - 'app/graphql/types/tree/entry_type.rb'
- - 'app/graphql/types/tree/submodule_type.rb'
- - 'app/graphql/types/tree/tree_entry_type.rb'
- - 'app/graphql/types/tree/tree_type.rb'
- - 'app/graphql/types/user_callout_type.rb'
- - 'app/graphql/types/user_interface.rb'
- - 'app/graphql/types/user_status_type.rb'
- - 'app/graphql/types/work_item_type.rb'
- - 'app/graphql/types/work_items/type_type.rb'
- - 'app/helpers/avatars_helper.rb'
- - 'app/helpers/blob_helper.rb'
- - 'app/helpers/commits_helper.rb'
- - 'app/helpers/environments_helper.rb'
- - 'app/helpers/events_helper.rb'
- - 'app/helpers/markup_helper.rb'
- - 'app/helpers/preferences_helper.rb'
- - 'app/helpers/projects_helper.rb'
- - 'app/helpers/sorting_helper.rb'
- - 'app/helpers/todos_helper.rb'
- - 'app/helpers/wiki_helper.rb'
- - 'app/mailers/abuse_report_mailer.rb'
- - 'app/mailers/emails/projects.rb'
- - 'app/models/bulk_imports/configuration.rb'
- - 'app/models/ci/bridge.rb'
- - 'app/models/ci/build_trace_metadata.rb'
- - 'app/models/ci/pipeline.rb'
- - 'app/models/compare.rb'
- - 'app/models/concerns/ci/has_status.rb'
- - 'app/models/concerns/enums/data_visualization_palette.rb'
- - 'app/models/concerns/featurable.rb'
- - 'app/models/concerns/issuable.rb'
- - 'app/models/concerns/triggerable_hooks.rb'
- - 'app/models/container_repository.rb'
- - 'app/models/design_management/design.rb'
- - 'app/models/design_management/design_action.rb'
- - 'app/models/event.rb'
- - 'app/models/grafana_integration.rb'
- - 'app/models/group.rb'
- - 'app/models/hooks/web_hook.rb'
- - 'app/models/integrations/emails_on_push.rb'
- - 'app/models/integrations/jira.rb'
- - 'app/models/issuable_severity.rb'
- - 'app/models/jira_connect_installation.rb'
- - 'app/models/loose_foreign_keys/deleted_record.rb'
- - 'app/models/merge_request.rb'
- - 'app/models/merge_request_diff.rb'
- - 'app/models/pages_domain.rb'
- - 'app/models/project.rb'
- - 'app/models/prometheus_alert.rb'
- - 'app/models/serverless/domain_cluster.rb'
- - 'app/models/snippet.rb'
- - 'app/models/terraform/state.rb'
- - 'app/models/user.rb'
- - 'app/models/user_status.rb'
- - 'app/models/wiki.rb'
- - 'app/models/work_items/type.rb'
- - 'app/presenters/analytics/cycle_analytics/stage_presenter.rb'
- - 'app/presenters/project_presenter.rb'
- - 'app/serializers/rollout_status_entity.rb'
- - 'app/services/chat_names/authorize_user_service.rb'
- - 'app/services/ci/archive_trace_service.rb'
- - 'app/services/ci/job_artifacts/destroy_batch_service.rb'
- - 'app/services/ci/list_config_variables_service.rb'
- - 'app/services/ci/parse_dotenv_artifact_service.rb'
- - 'app/services/ci/stuck_builds/drop_helpers.rb'
- - 'app/services/groups/import_export/import_service.rb'
- - 'app/services/issuable/import_csv/base_service.rb'
- - 'app/services/issues/export_csv_service.rb'
- - 'app/services/jira/requests/base.rb'
- - 'app/services/merge_requests/mergeability_check_service.rb'
- - 'app/services/merge_requests/push_options_handler_service.rb'
- - 'app/services/merge_requests/toggle_attention_requested_service.rb'
- - 'app/services/packages/conan/create_package_file_service.rb'
- - 'app/services/packages/create_package_file_service.rb'
- - 'app/services/packages/debian/create_package_file_service.rb'
- - 'app/services/packages/npm/create_package_service.rb'
- - 'app/services/projects/fork_service.rb'
- - 'app/services/projects/lfs_pointers/lfs_download_service.rb'
- - 'app/services/projects/update_remote_mirror_service.rb'
- - 'app/uploaders/file_uploader.rb'
- - 'app/workers/emails_on_push_worker.rb'
- - 'app/workers/x509_issuer_crl_check_worker.rb'
- - 'config/initializers/1_settings.rb'
- - 'config/initializers/default_url_options.rb'
- - 'config/initializers/rest-client-hostname_override.rb'
- - 'config/routes/profile.rb'
- - 'config/routes/project.rb'
- - 'config/routes/unmatched_project.rb'
- - 'config/routes/uploads.rb'
- - 'db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb'
- - 'db/migrate/20210804150320_create_base_work_item_types.rb'
- - 'db/migrate/20210831203408_upsert_base_work_item_types.rb'
- - 'db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb'
- - 'db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb'
- - 'db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb'
- - 'db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb'
- - 'db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb'
- - 'db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb'
- - 'db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb'
- - 'db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb'
- - 'db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb'
- - 'db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb'
- - 'db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb'
- - 'db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb'
- - 'ee/app/controllers/ee/search_controller.rb'
- - 'ee/app/controllers/projects/integrations/zentao/issues_controller.rb'
- - 'ee/app/graphql/ee/types/board_list_type.rb'
- - 'ee/app/graphql/ee/types/board_type.rb'
- - 'ee/app/graphql/ee/types/ci/runner_type.rb'
- - 'ee/app/graphql/ee/types/group_type.rb'
- - 'ee/app/graphql/ee/types/issue_type.rb'
- - 'ee/app/graphql/ee/types/merge_request_type.rb'
- - 'ee/app/graphql/ee/types/project_type.rb'
- - 'ee/app/graphql/ee/types/repository/blob_type.rb'
- - 'ee/app/graphql/mutations/iterations/cadences/create.rb'
- - 'ee/app/graphql/mutations/iterations/cadences/destroy.rb'
- - 'ee/app/graphql/mutations/iterations/cadences/update.rb'
- - 'ee/app/graphql/mutations/iterations/delete.rb'
- - 'ee/app/graphql/mutations/projects/set_locked.rb'
- - 'ee/app/graphql/resolvers/iterations/cadences_resolver.rb'
- - 'ee/app/graphql/resolvers/vulnerabilities_count_per_day_resolver.rb'
- - 'ee/app/graphql/types/admin/cloud_licenses/current_license_type.rb'
- - 'ee/app/graphql/types/admin/cloud_licenses/license_type.rb'
- - 'ee/app/graphql/types/admin/cloud_licenses/subscription_future_entry_type.rb'
- - 'ee/app/graphql/types/analytics/devops_adoption/enabled_namespace_type.rb'
- - 'ee/app/graphql/types/analytics/devops_adoption/snapshot_type.rb'
- - 'ee/app/graphql/types/app_sec/fuzzing/api/ci_configuration_type.rb'
- - 'ee/app/graphql/types/app_sec/fuzzing/api/scan_profile_type.rb'
- - 'ee/app/graphql/types/app_sec/fuzzing/coverage/corpus_type.rb'
- - 'ee/app/graphql/types/boards/board_epic_type.rb'
- - 'ee/app/graphql/types/boards/epic_board_type.rb'
- - 'ee/app/graphql/types/boards/epic_list_metadata_type.rb'
- - 'ee/app/graphql/types/boards/epic_list_type.rb'
- - 'ee/app/graphql/types/boards/epic_user_preferences_type.rb'
- - 'ee/app/graphql/types/burnup_chart_daily_totals_type.rb'
- - 'ee/app/graphql/types/ci/code_coverage_activity_type.rb'
- - 'ee/app/graphql/types/ci/code_coverage_summary_type.rb'
- - 'ee/app/graphql/types/ci/code_quality_degradation_type.rb'
- - 'ee/app/graphql/types/ci/minutes/namespace_monthly_usage_type.rb'
- - 'ee/app/graphql/types/ci/minutes/project_monthly_usage_type.rb'
- - 'ee/app/graphql/types/compliance_management/merge_requests/compliance_violation_type.rb'
- - 'ee/app/graphql/types/dast/profile_branch_type.rb'
- - 'ee/app/graphql/types/dast/profile_schedule_type.rb'
- - 'ee/app/graphql/types/dast/profile_type.rb'
- - 'ee/app/graphql/types/dast_scanner_profile_type.rb'
- - 'ee/app/graphql/types/dast_site_profile_type.rb'
- - 'ee/app/graphql/types/dast_site_validation_type.rb'
- - 'ee/app/graphql/types/dora_metric_type.rb'
- - 'ee/app/graphql/types/dora_type.rb'
- - 'ee/app/graphql/types/epic_descendant_weight_sum_type.rb'
- - 'ee/app/graphql/types/epic_issue_type.rb'
- - 'ee/app/graphql/types/epic_type.rb'
- - 'ee/app/graphql/types/external_issue_type.rb'
- - 'ee/app/graphql/types/group_release_stats_type.rb'
- - 'ee/app/graphql/types/instance_security_dashboard_type.rb'
- - 'ee/app/graphql/types/iteration_type.rb'
- - 'ee/app/graphql/types/iterations/cadence_type.rb'
- - 'ee/app/graphql/types/merge_requests/approval_state_type.rb'
- - 'ee/app/graphql/types/metric_image_type.rb'
- - 'ee/app/graphql/types/path_lock_type.rb'
- - 'ee/app/graphql/types/requirements_management/requirement_type.rb'
- - 'ee/app/graphql/types/requirements_management/test_report_type.rb'
- - 'ee/app/graphql/types/security/training_type.rb'
- - 'ee/app/graphql/types/security/training_url_type.rb'
- - 'ee/app/graphql/types/security_report_summary_type.rb'
- - 'ee/app/graphql/types/security_scanners.rb'
- - 'ee/app/graphql/types/time_report_stats_type.rb'
- - 'ee/app/graphql/types/timebox_metrics_type.rb'
- - 'ee/app/graphql/types/timebox_report_interface.rb'
- - 'ee/app/graphql/types/timebox_report_type.rb'
- - 'ee/app/graphql/types/vulnerabilities/asset_type.rb'
- - 'ee/app/graphql/types/vulnerabilities/link_type.rb'
- - 'ee/app/graphql/types/vulnerabilities_count_by_day_type.rb'
- - 'ee/app/graphql/types/vulnerability/external_issue_link_type.rb'
- - 'ee/app/graphql/types/vulnerability/issue_link_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/base_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/boolean_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/code_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/commit_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/diff_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/file_location_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/int_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/list_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/markdown_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/module_location_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/table_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/text_type.rb'
- - 'ee/app/graphql/types/vulnerability_details/url_type.rb'
- - 'ee/app/graphql/types/vulnerability_evidence_source_type.rb'
- - 'ee/app/graphql/types/vulnerability_evidence_supporting_message_type.rb'
- - 'ee/app/graphql/types/vulnerability_evidence_type.rb'
- - 'ee/app/graphql/types/vulnerability_identifier_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/cluster_image_scanning_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/container_scanning_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/coverage_fuzzing_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/dast_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/dependency_scanning_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/generic_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/sast_type.rb'
- - 'ee/app/graphql/types/vulnerability_location/secret_detection_type.rb'
- - 'ee/app/graphql/types/vulnerability_request_response_header_type.rb'
- - 'ee/app/graphql/types/vulnerability_request_type.rb'
- - 'ee/app/graphql/types/vulnerability_response_type.rb'
- - 'ee/app/graphql/types/vulnerability_scanner_type.rb'
- - 'ee/app/graphql/types/vulnerability_severities_count_type.rb'
- - 'ee/app/graphql/types/vulnerability_type.rb'
- - 'ee/app/graphql/types/vulnerable_dependency_type.rb'
- - 'ee/app/graphql/types/vulnerable_kubernetes_resource_type.rb'
- - 'ee/app/graphql/types/vulnerable_package_type.rb'
- - 'ee/app/graphql/types/vulnerable_projects_by_grade_type.rb'
- - 'ee/app/helpers/ee/feature_flags_helper.rb'
- - 'ee/app/helpers/ee/sorting_helper.rb'
- - 'ee/app/models/allowed_email_domain.rb'
- - 'ee/app/models/ci/minutes/usage.rb'
- - 'ee/app/models/ee/application_setting.rb'
- - 'ee/app/models/elastic/reindexing_task.rb'
- - 'ee/app/models/gitlab_subscriptions/features.rb'
- - 'ee/app/models/gitlab_subscriptions/upcoming_reconciliation.rb'
- - 'ee/app/models/historical_data.rb'
- - 'ee/app/models/incident_management/escalation_rule.rb'
- - 'ee/app/models/incident_management/oncall_rotation.rb'
- - 'ee/app/models/scim_identity.rb'
- - 'ee/app/models/status_page/project_setting.rb'
- - 'ee/app/serializers/ee/evidences/release_entity.rb'
- - 'ee/app/services/ci/external_pull_requests/process_github_event_service.rb'
- - 'ee/app/services/ci_cd/setup_project.rb'
- - 'ee/app/services/ee/issues/base_service.rb'
- - 'ee/app/services/elastic/cluster_reindexing_service.rb'
- - 'ee/app/services/elastic/process_bookkeeping_service.rb'
- - 'ee/app/services/epics/issue_promote_service.rb'
- - 'ee/app/services/external_status_checks/create_service.rb'
- - 'ee/app/services/groups/memberships/export_service.rb'
- - 'ee/app/services/projects/setup_ci_cd.rb'
- - 'ee/app/services/security/security_orchestration_policies/on_demand_scan_pipeline_configuration_service.rb'
- - 'ee/config/routes/project.rb'
- - 'ee/config/routes/uploads.rb'
- 'ee/lib/api/iterations.rb'
- 'ee/lib/api/merge_trains.rb'
+ - 'ee/lib/api/related_epic_links.rb'
- 'ee/lib/api/vulnerability_exports.rb'
- 'ee/lib/api/vulnerability_findings.rb'
+ - 'ee/lib/ee/api/helpers/groups_helpers.rb'
- 'ee/lib/ee/api/helpers/issues_helpers.rb'
- 'ee/lib/ee/api/helpers/protected_branches_helpers.rb'
- 'ee/lib/ee/api/merge_requests.rb'
- - 'ee/lib/ee/audit/project_changes_auditor.rb'
+ - 'ee/lib/ee/audit/project_setting_changes_auditor.rb'
+ - 'ee/lib/ee/audit/protected_branches_changes_auditor.rb'
- 'ee/lib/ee/banzai/filter/references/epic_reference_filter.rb'
- 'ee/lib/ee/banzai/filter/references/vulnerability_reference_filter.rb'
+ - 'ee/lib/ee/gitlab/application_rate_limiter.rb'
- 'ee/lib/ee/gitlab/ci/pipeline/chain/validate/after_config.rb'
- 'ee/lib/ee/gitlab/quick_actions/issue_actions.rb'
+ - 'ee/lib/ee/gitlab/tracking.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
+ - 'ee/lib/elastic/latest/commit_config.rb'
- 'ee/lib/elastic/latest/config.rb'
- 'ee/lib/elastic/latest/merge_request_config.rb'
- 'ee/lib/gem_extensions/elasticsearch/model/indexing/instance_methods.rb'
@@ -387,7 +35,9 @@ Layout/HashAlignment:
- 'ee/spec/controllers/projects/settings/operations_controller_spec.rb'
- 'ee/spec/controllers/trials_controller_spec.rb'
- 'ee/spec/factories/dependencies.rb'
+ - 'ee/spec/factories/projects.rb'
- 'ee/spec/features/billings/billing_plans_spec.rb'
+ - 'ee/spec/features/groups/settings/protected_environments_spec.rb'
- 'ee/spec/features/projects/environments/environments_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'
@@ -395,13 +45,21 @@ Layout/HashAlignment:
- 'ee/spec/finders/merge_requests_finder_spec.rb'
- 'ee/spec/frontend/fixtures/dast_profiles.rb'
- 'ee/spec/graphql/ee/mutations/ci/runner/update_spec.rb'
+ - 'ee/spec/graphql/ee/resolvers/namespace_projects_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/path_locks_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/security_orchestration/scan_execution_policy_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/security_report_summary_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/vulnerabilities/issue_links_resolver_spec.rb'
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
- 'ee/spec/helpers/routing/pseudonymization_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/config_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/delete_invalid_epic_issues_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/fix_incorrect_max_seats_used_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/config/entry/need_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/matching/runner_matcher_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/group/legacy_tree_saver_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/group/tree_saver_spec.rb'
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
@@ -410,77 +68,48 @@ Layout/HashAlignment:
- 'ee/spec/lib/gitlab/custom_file_templates_spec.rb'
- 'ee/spec/lib/gitlab/elastic/client_spec.rb'
- 'ee/spec/lib/gitlab/elastic/indexer_spec.rb'
+ - 'ee/spec/lib/gitlab/insights/loader_spec.rb'
- 'ee/spec/lib/gitlab/template/custom_templates_spec.rb'
- 'ee/spec/models/application_setting_spec.rb'
- 'ee/spec/models/approval_merge_request_rule_spec.rb'
- 'ee/spec/models/member_spec.rb'
+ - 'ee/spec/models/preloaders/environments/protected_environment_preloader_spec.rb'
+ - 'ee/spec/models/protected_environments/approval_summary_spec.rb'
- 'ee/spec/models/vulnerabilities/statistic_spec.rb'
+ - 'ee/spec/requests/api/deployments_spec.rb'
- 'ee/spec/requests/api/graphql/app_sec/fuzzing/coverage/corpus_type_spec.rb'
- 'ee/spec/requests/api/graphql/group/epics_spec.rb'
- 'ee/spec/requests/api/internal/base_spec.rb'
- 'ee/spec/requests/api/issues_spec.rb'
+ - 'ee/spec/requests/api/protected_environments_spec.rb'
- 'ee/spec/requests/api/templates_spec.rb'
+ - 'ee/spec/requests/ee/projects/environments_controller_spec.rb'
- 'ee/spec/requests/ee/projects/service_desk_controller_spec.rb'
- 'ee/spec/requests/projects/security/dast_site_profiles_controller_spec.rb'
- 'ee/spec/requests/rack_attack_global_spec.rb'
- 'ee/spec/serializers/integrations/zentao_serializers/issue_entity_spec.rb'
- 'ee/spec/services/app_sec/dast/profiles/create_associations_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/scan_configs/fetch_service_spec.rb'
+ - 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
- 'ee/spec/services/audit_events/protected_branch_audit_event_service_spec.rb'
+ - 'ee/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
- 'ee/spec/services/ci/create_pipeline_service/cross_needs_artifacts_spec.rb'
- 'ee/spec/services/ci/process_pipeline_service_spec.rb'
- 'ee/spec/services/ci/retry_pipeline_service_spec.rb'
- 'ee/spec/services/ci/subscribe_bridge_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/create_pipeline_service_spec.rb'
- 'ee/spec/services/merge_trains/check_status_service_spec.rb'
- 'ee/spec/services/merge_trains/create_pipeline_service_spec.rb'
- 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
- 'ee/spec/services/merge_trains/refresh_service_spec.rb'
- 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
- 'ee/spec/services/status_page/unpublish_details_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/support/shared_examples/services/audit_event_logging_shared_examples.rb'
- 'ee/spec/support/shared_examples/status_page/publish_shared_examples.rb'
- 'ee/spec/support/shared_examples/status_page/reference_links_examples.rb'
- 'ee/spec/workers/scan_security_report_secrets_worker_spec.rb'
- - 'lib/api/applications.rb'
- - 'lib/api/broadcast_messages.rb'
- - 'lib/api/bulk_imports.rb'
- - 'lib/api/ci/job_artifacts.rb'
- - 'lib/api/ci/jobs.rb'
- - 'lib/api/ci/pipelines.rb'
- - 'lib/api/ci/runner.rb'
- - 'lib/api/ci/runners.rb'
- - 'lib/api/concerns/packages/debian_distribution_endpoints.rb'
- - 'lib/api/debian_project_packages.rb'
- - 'lib/api/deploy_tokens.rb'
- - 'lib/api/entities/project.rb'
- - 'lib/api/feature_flags.rb'
- - 'lib/api/group_labels.rb'
- - 'lib/api/group_packages.rb'
- - 'lib/api/groups.rb'
- - 'lib/api/helm_packages.rb'
- - 'lib/api/helpers/groups_helpers.rb'
- - 'lib/api/helpers/merge_requests_helpers.rb'
- - 'lib/api/helpers/snippets_helpers.rb'
- - 'lib/api/issue_links.rb'
- - 'lib/api/issues.rb'
- - 'lib/api/labels.rb'
- - 'lib/api/maven_packages.rb'
- - 'lib/api/members.rb'
- - 'lib/api/merge_requests.rb'
- - 'lib/api/metrics/dashboard/annotations.rb'
- - 'lib/api/metrics/user_starred_dashboards.rb'
- - 'lib/api/milestone_responses.rb'
- - 'lib/api/notes.rb'
- - 'lib/api/pages_domains.rb'
- - 'lib/api/project_packages.rb'
- - 'lib/api/project_templates.rb'
- - 'lib/api/projects.rb'
- - 'lib/api/protected_branches.rb'
- - 'lib/api/releases.rb'
- - 'lib/api/rubygem_packages.rb'
- - 'lib/api/sidekiq_metrics.rb'
- - 'lib/api/users.rb'
- - 'lib/backup/gitaly_backup.rb'
- - 'lib/banzai/filter/references/abstract_reference_filter.rb'
- - 'lib/banzai/reference_redactor.rb'
- 'lib/gitlab/abuse.rb'
- 'lib/gitlab/access.rb'
- 'lib/gitlab/application_rate_limiter.rb'
@@ -488,6 +117,7 @@ Layout/HashAlignment:
- 'lib/gitlab/auth/o_auth/auth_hash.rb'
- 'lib/gitlab/auth/o_auth/provider.rb'
- 'lib/gitlab/auth/o_auth/user.rb'
+ - 'lib/gitlab/auth/otp/strategies/forti_authenticator/manual_otp.rb'
- 'lib/gitlab/background_migration/backfill_project_repositories.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- 'lib/gitlab/ci/ansi2html.rb'
@@ -496,7 +126,7 @@ Layout/HashAlignment:
- 'lib/gitlab/ci/jwt_v2.rb'
- 'lib/gitlab/ci/pipeline/chain/validate/external.rb'
- 'lib/gitlab/ci/reports/security/scanner.rb'
- - 'lib/gitlab/database/partitioning/sliding_list_strategy.rb'
+ - 'lib/gitlab/database/background_migration/health_status.rb'
- 'lib/gitlab/database/reflection.rb'
- 'lib/gitlab/diff/file_collection/compare.rb'
- 'lib/gitlab/email/attachment_uploader.rb'
@@ -514,6 +144,7 @@ Layout/HashAlignment:
- 'lib/gitlab/import_export/members_mapper.rb'
- 'lib/gitlab/import_export/project/import_task.rb'
- 'lib/gitlab/import_export/shared.rb'
+ - 'lib/gitlab/issuable/clone/copy_resource_events_service.rb'
- 'lib/gitlab/kubernetes.rb'
- 'lib/gitlab/marginalia/comment.rb'
- 'lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb'
@@ -533,46 +164,56 @@ Layout/HashAlignment:
- 'lib/tasks/gitlab/import_export/export.rake'
- 'lib/tasks/gitlab/import_export/import.rake'
- 'lib/tasks/tanuki_emoji.rake'
- - 'qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_templates_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
- - 'qa/qa/support/loglinking.rb'
- - 'qa/spec/support/loglinking_spec.rb'
- 'spec/controllers/concerns/product_analytics_tracking_spec.rb'
- 'spec/controllers/concerns/redis_tracking_spec.rb'
+ - 'spec/controllers/import/bitbucket_controller_spec.rb'
- 'spec/controllers/oauth/token_info_controller_spec.rb'
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/controllers/projects/feature_flags_controller_spec.rb'
- 'spec/controllers/projects/grafana_api_controller_spec.rb'
- - 'spec/controllers/projects/issues_controller_spec.rb'
- 'spec/controllers/projects/merge_requests_controller_spec.rb'
+ - 'spec/controllers/projects/pipeline_schedules_controller_spec.rb'
- 'spec/controllers/projects/registry/tags_controller_spec.rb'
- 'spec/controllers/projects/service_desk_controller_spec.rb'
- - 'spec/controllers/search_controller_spec.rb'
+ - 'spec/db/migration_spec.rb'
- 'spec/factories/ci/builds.rb'
- - 'spec/factories/ci/stages.rb'
+ - 'spec/factories/environments.rb'
- 'spec/factories/groups.rb'
- 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
- - 'spec/features/groups/issues_spec.rb'
+ - 'spec/features/dashboard/todos/todos_sorting_spec.rb'
+ - 'spec/features/jira_oauth_provider_authorize_spec.rb'
+ - 'spec/features/merge_request/user_sees_deployment_widget_spec.rb'
- 'spec/features/profiles/active_sessions_spec.rb'
- 'spec/features/projects/badges/coverage_spec.rb'
+ - 'spec/features/projects/environments/environment_spec.rb'
- 'spec/features/projects/feature_flags/user_sees_feature_flag_list_spec.rb'
- 'spec/features/projects/feature_flags/user_updates_feature_flag_spec.rb'
- 'spec/features/projects/jobs/user_browses_jobs_spec.rb'
- 'spec/features/projects/milestones/milestones_sorting_spec.rb'
- 'spec/features/projects/new_project_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipelines_spec.rb'
- 'spec/features/projects/pipelines/pipeline_spec.rb'
- 'spec/features/projects/pipelines/pipelines_spec.rb'
- 'spec/features/snippets/user_creates_snippet_spec.rb'
+ - 'spec/features/users/email_verification_on_login_spec.rb'
- 'spec/features/users/login_spec.rb'
- 'spec/finders/ci/pipelines_for_merge_request_finder_spec.rb'
- 'spec/finders/group_descendants_finder_spec.rb'
- 'spec/finders/group_members_finder_spec.rb'
- 'spec/finders/template_finder_spec.rb'
- 'spec/graphql/mutations/releases/update_spec.rb'
+ - 'spec/graphql/resolvers/board_lists_resolver_spec.rb'
- 'spec/graphql/resolvers/ci/config_resolver_spec.rb'
+ - 'spec/graphql/resolvers/ci/group_runners_resolver_spec.rb'
+ - 'spec/graphql/resolvers/ci/jobs_resolver_spec.rb'
+ - 'spec/graphql/resolvers/ci/runners_resolver_spec.rb'
+ - 'spec/graphql/resolvers/container_repositories_resolver_spec.rb'
+ - 'spec/graphql/resolvers/container_repository_tags_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/versions_resolver_spec.rb'
+ - 'spec/graphql/resolvers/work_items_resolver_spec.rb'
+ - 'spec/helpers/ci/builds_helper_spec.rb'
- 'spec/helpers/sorting_helper_spec.rb'
- 'spec/helpers/storage_helper_spec.rb'
- 'spec/helpers/wiki_helper_spec.rb'
@@ -585,6 +226,8 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/auth/ldap/person_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb'
- 'spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_integrations_enable_ssl_verification_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
- 'spec/lib/gitlab/background_migration/encrypt_integration_properties_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/port_spec.rb'
@@ -594,6 +237,7 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb'
- 'spec/lib/gitlab/ci/variables/builder_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
+ - 'spec/lib/gitlab/data_builder/issuable_spec.rb'
- 'spec/lib/gitlab/data_builder/note_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers_spec.rb'
- 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
@@ -615,6 +259,8 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/import_export/project/sample/relation_tree_restorer_spec.rb'
- 'spec/lib/gitlab/import_sources_spec.rb'
- 'spec/lib/gitlab/instrumentation_helper_spec.rb'
+ - 'spec/lib/gitlab/jira/middleware_spec.rb'
+ - 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/validator_spec.rb'
@@ -625,9 +271,12 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/metrics/web_transaction_spec.rb'
- 'spec/lib/gitlab/omniauth_initializer_spec.rb'
- 'spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_death_handler_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
- 'spec/lib/gitlab/slug/environment_spec.rb'
- 'spec/lib/gitlab/tracking_spec.rb'
- 'spec/lib/gitlab/usage_data/topology_spec.rb'
+ - 'spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/note_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_spec.rb'
- 'spec/lib/gitlab/utils_spec.rb'
@@ -641,8 +290,11 @@ Layout/HashAlignment:
- 'spec/migrations/20211126204445_add_task_to_work_item_types_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/models/ci/pipeline_spec.rb'
+ - 'spec/models/ci/processable_spec.rb'
- 'spec/models/clusters/platforms/kubernetes_spec.rb'
+ - 'spec/models/commit_status_spec.rb'
- 'spec/models/container_registry/event_spec.rb'
+ - 'spec/models/deployment_spec.rb'
- 'spec/models/design_management/version_spec.rb'
- 'spec/models/group_spec.rb'
- 'spec/models/integrations/chat_message/pipeline_message_spec.rb'
@@ -651,7 +303,6 @@ Layout/HashAlignment:
- 'spec/models/namespace_spec.rb'
- 'spec/models/operations/feature_flag_spec.rb'
- 'spec/models/pages_domain_spec.rb'
- - 'spec/models/project_spec.rb'
- 'spec/models/remote_mirror_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/models/user_spec.rb'
@@ -662,9 +313,12 @@ Layout/HashAlignment:
- 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
- 'spec/requests/api/feature_flags_spec.rb'
- 'spec/requests/api/graphql/ci/config_spec.rb'
+ - 'spec/requests/api/graphql/ci/group_variables_spec.rb'
+ - 'spec/requests/api/graphql/ci/instance_variables_spec.rb'
+ - 'spec/requests/api/graphql/ci/project_variables_spec.rb'
- 'spec/requests/api/graphql/ci/runner_spec.rb'
+ - 'spec/requests/api/graphql/ci/runners_spec.rb'
- 'spec/requests/api/graphql/mutations/releases/update_spec.rb'
- - 'spec/requests/api/graphql/packages/conan_spec.rb'
- 'spec/requests/api/graphql/project/issue/design_collection/version_spec.rb'
- 'spec/requests/api/graphql/project/terraform/state_spec.rb'
- 'spec/requests/api/graphql/project/terraform/states_spec.rb'
@@ -672,21 +326,29 @@ Layout/HashAlignment:
- 'spec/requests/api/groups_spec.rb'
- 'spec/requests/api/internal/base_spec.rb'
- 'spec/requests/api/issues/get_group_issues_spec.rb'
+ - 'spec/requests/api/projects_spec.rb'
- 'spec/requests/api/suggestions_spec.rb'
- 'spec/requests/api/unleash_spec.rb'
- 'spec/requests/git_http_spec.rb'
+ - 'spec/requests/oauth_tokens_spec.rb'
- 'spec/requests/openid_connect_spec.rb'
+ - 'spec/requests/projects/environments_controller_spec.rb'
- 'spec/requests/projects/merge_requests_discussions_spec.rb'
- 'spec/routing/project_routing_spec.rb'
- 'spec/serializers/ci/lint/job_entity_spec.rb'
- 'spec/serializers/container_repository_entity_spec.rb'
+ - 'spec/serializers/deployment_entity_spec.rb'
+ - 'spec/serializers/environment_serializer_spec.rb'
- 'spec/serializers/merge_request_metrics_helper_spec.rb'
- 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
- 'spec/services/ci/create_pipeline_service/logger_spec.rb'
- 'spec/services/ci/create_pipeline_service/tags_spec.rb'
- 'spec/services/ci/job_artifacts/create_service_spec.rb'
+ - 'spec/services/ci/retry_job_service_spec.rb'
- 'spec/services/deployments/link_merge_requests_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
+ - 'spec/services/environments/stop_service_spec.rb'
+ - 'spec/services/event_create_service_spec.rb'
- 'spec/services/groups/import_export/import_service_spec.rb'
- 'spec/services/issuable/bulk_update_service_spec.rb'
- 'spec/services/issues/create_service_spec.rb'
@@ -698,7 +360,9 @@ Layout/HashAlignment:
- 'spec/services/notes/destroy_service_spec.rb'
- 'spec/services/packages/debian/parse_debian822_service_spec.rb'
- 'spec/services/projects/destroy_service_spec.rb'
+ - 'spec/services/service_ping/submit_service_ping_service_spec.rb'
- 'spec/services/suggestions/apply_service_spec.rb'
+ - 'spec/services/work_items/widgets/description_service/update_service_spec.rb'
- 'spec/support/helpers/create_environments_helpers.rb'
- 'spec/support/helpers/kubernetes_helpers.rb'
- 'spec/support/helpers/migrations_helpers/work_item_types_helper.rb'
@@ -710,6 +374,8 @@ Layout/HashAlignment:
- 'spec/support/shared_contexts/bulk_imports_requests_shared_context.rb'
- 'spec/support/shared_contexts/design_management_shared_contexts.rb'
- 'spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb'
+ - 'spec/support/shared_examples/finders/issues_finder_shared_examples.rb'
+ - 'spec/support/shared_examples/graphql/members_shared_examples.rb'
- 'spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/database/background_migration_job_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb'
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 7d2674c34f8..80c0f986552 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -801,7 +801,6 @@ Layout/LineLength:
- 'config/initializers/active_record_transaction_observer.rb'
- 'config/initializers/carrierwave_patch.rb'
- 'config/initializers/content_security_policy.rb'
- - 'config/initializers/database_query_analyzers.rb'
- 'config/initializers/deprecations.rb'
- 'config/initializers/devise_dynamic_password_length_validation.rb'
- 'config/initializers/direct_upload_support.rb'
@@ -1138,7 +1137,6 @@ Layout/LineLength:
- '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/search_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'
@@ -1181,11 +1179,6 @@ Layout/LineLength:
- '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/ee/types/deprecated_mutations.rb'
- - 'ee/app/graphql/ee/types/group_type.rb'
- - 'ee/app/graphql/ee/types/merge_request_type.rb'
- - 'ee/app/graphql/ee/types/project_type.rb'
- - 'ee/app/graphql/ee/types/query_type.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'
- 'ee/app/graphql/mutations/audit_events/external_audit_event_destinations/update.rb'
@@ -1361,7 +1354,6 @@ Layout/LineLength:
- 'ee/app/models/ee/merge_request_diff.rb'
- 'ee/app/models/ee/milestone_release.rb'
- 'ee/app/models/ee/namespace.rb'
- - 'ee/app/models/ee/namespace/root_storage_size.rb'
- 'ee/app/models/ee/packages/package_file.rb'
- 'ee/app/models/ee/pages_deployment.rb'
- 'ee/app/models/ee/project.rb'
@@ -2451,9 +2443,7 @@ Layout/LineLength:
- 'ee/spec/models/ee/iterations/cadence_spec.rb'
- 'ee/spec/models/ee/lfs_object_spec.rb'
- 'ee/spec/models/ee/merge_request_diff_spec.rb'
- - 'ee/spec/models/ee/namespace/root_storage_size_spec.rb'
- 'ee/spec/models/ee/namespace/root_storage_statistics_spec.rb'
- - 'ee/spec/models/ee/namespace_limit_spec.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/ee/namespace_statistics_spec.rb'
- 'ee/spec/models/ee/preloaders/group_policy_preloader_spec.rb'
@@ -4441,7 +4431,6 @@ Layout/LineLength:
- 'spec/frontend/fixtures/merge_requests_diffs.rb'
- 'spec/frontend/fixtures/pipeline_schedules.rb'
- 'spec/frontend/fixtures/projects.rb'
- - 'spec/frontend/fixtures/runner.rb'
- 'spec/frontend/fixtures/snippet.rb'
- 'spec/graphql/features/feature_flag_spec.rb'
- 'spec/graphql/gitlab_schema_spec.rb'
@@ -4623,7 +4612,6 @@ Layout/LineLength:
- '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/database_spec.rb'
- 'spec/lib/backup/files_spec.rb'
- 'spec/lib/backup/gitaly_backup_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
@@ -4749,7 +4737,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/background_migration/migrate_merge_request_diff_commit_users_spec.rb'
- 'spec/lib/gitlab/background_migration/migrate_personal_namespace_project_maintainer_to_owner_spec.rb'
- 'spec/lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature_spec.rb'
- - 'spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb'
- 'spec/lib/gitlab/background_migration/populate_container_repository_migration_plan_spec.rb'
- 'spec/lib/gitlab/background_migration/populate_vulnerability_reads_spec.rb'
- 'spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb'
@@ -4858,7 +4845,6 @@ Layout/LineLength:
- 'spec/lib/gitlab/database/batch_count_spec.rb'
- '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/load_balancer_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'
@@ -6026,7 +6012,6 @@ Layout/LineLength:
- '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'
- - 'spec/services/resource_events/change_labels_service_spec.rb'
- 'spec/services/resource_events/change_state_service_spec.rb'
- 'spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb'
- 'spec/services/search/global_service_spec.rb'
diff --git a/.rubocop_todo/layout/multiline_operation_indentation.yml b/.rubocop_todo/layout/multiline_operation_indentation.yml
index 51ecf97d318..cdfa560ef2e 100644
--- a/.rubocop_todo/layout/multiline_operation_indentation.yml
+++ b/.rubocop_todo/layout/multiline_operation_indentation.yml
@@ -1,77 +1,90 @@
---
# Cop supports --auto-correct.
Layout/MultilineOperationIndentation:
- # Offense count: 252
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb'
- 'app/controllers/projects/application_controller.rb'
- 'app/controllers/repositories/git_http_client_controller.rb'
- 'app/controllers/sent_notifications_controller.rb'
- 'app/graphql/types/ci/stage_type.rb'
- - 'app/helpers/application_settings_helper.rb'
- 'app/helpers/auth_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/mirror_helper.rb'
- 'app/helpers/packages_helper.rb'
- 'app/helpers/projects_helper.rb'
- - 'app/helpers/storage_helper.rb'
- 'app/helpers/visibility_level_helper.rb'
- 'app/helpers/whats_new_helper.rb'
- 'app/models/concerns/admin_changed_password_notifier.rb'
- 'app/models/integrations/prometheus.rb'
+ - 'app/models/merge_request_diff_file.rb'
- 'app/models/namespaces/traversal/linear_scopes.rb'
- 'app/models/packages/conan/metadatum.rb'
- 'app/models/packages/sem_ver.rb'
- 'app/models/project.rb'
- 'app/models/project_statistics.rb'
- 'app/models/user.rb'
+ - 'app/models/work_items/parent_link.rb'
+ - 'app/policies/project_policy.rb'
+ - 'app/serializers/deploy_keys/deploy_key_entity.rb'
- 'app/services/ci/create_downstream_pipeline_service.rb'
- 'app/services/ci/create_pipeline_service.rb'
- 'app/services/git/branch_hooks_service.rb'
- - 'app/services/groups/group_links/create_service.rb'
- 'app/services/groups/transfer_service.rb'
- 'app/services/issues/update_service.rb'
- 'app/services/labels/promote_service.rb'
- 'app/services/labels/transfer_service.rb'
+ - 'app/services/members/approve_access_request_service.rb'
- 'app/services/projects/container_repository/cleanup_tags_service.rb'
- 'app/services/webauthn/authenticate_service.rb'
- 'app/validators/feature_flag_strategies_validator.rb'
- 'app/workers/container_expiration_policies/cleanup_container_repository_worker.rb'
+ - 'app/workers/container_registry/migration/guard_worker.rb'
- 'config/initializers/devise_dynamic_password_length_validation.rb'
- 'danger/utility_css/Dangerfile'
+ - 'ee/app/controllers/ee/admin/application_settings_controller.rb'
+ - 'ee/app/controllers/projects/integrations/jira/issues_controller.rb'
- 'ee/app/controllers/smartcard_controller.rb'
- 'ee/app/graphql/resolvers/boards/epic_lists_resolver.rb'
- 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/boards_helper.rb'
+ - 'ee/app/helpers/ee/groups/group_members_helper.rb'
+ - 'ee/app/helpers/ee/groups/reporting_helper.rb'
+ - 'ee/app/helpers/ee/projects/project_members_helper.rb'
- 'ee/app/helpers/groups/security_features_helper.rb'
- 'ee/app/helpers/groups/sso_helper.rb'
+ - 'ee/app/models/approval_project_rule.rb'
+ - 'ee/app/models/concerns/ee/issuable.rb'
- 'ee/app/models/ee/namespace.rb'
- - 'ee/app/models/ee/namespace/root_storage_size.rb'
- 'ee/app/models/ee/project.rb'
- 'ee/app/models/ee/user.rb'
- 'ee/app/models/vulnerabilities/finding_signature.rb'
- 'ee/app/policies/ee/base_policy.rb'
+ - 'ee/app/policies/ee/merge_request_policy.rb'
- 'ee/app/services/analytics/cycle_analytics/value_streams/update_service.rb'
- 'ee/app/services/ee/merge_requests/build_service.rb'
- 'ee/app/services/ee/projects/operations/update_service.rb'
+ - 'ee/app/workers/elastic/project_transfer_worker.rb'
- 'ee/lib/ee/api/entities/group.rb'
+ - 'ee/lib/ee/api/geo.rb'
- 'ee/lib/ee/api/helpers.rb'
+ - 'ee/lib/ee/api/settings.rb'
+ - 'ee/lib/ee/gitlab/git_access_project.rb'
- 'ee/lib/ee/gitlab/middleware/read_only/controller.rb'
- 'ee/lib/ee/gitlab/quick_actions/issue_actions.rb'
- 'ee/lib/ee/sidebars/projects/menus/ci_cd_menu.rb'
- 'ee/lib/ee/sidebars/projects/menus/issues_menu.rb'
- - 'ee/lib/elastic/latest/issue_class_proxy.rb'
+ - 'ee/lib/gitlab/incident_management.rb'
- 'ee/lib/sidebars/groups/menus/analytics_menu.rb'
- 'ee/lib/sidebars/groups/menus/security_compliance_menu.rb'
- 'ee/spec/services/ci/create_pipeline_service/dast_configuration_spec.rb'
- 'lib/api/maven_packages.rb'
- 'lib/api/users.rb'
- 'lib/api/validations/validators/array_none_any.rb'
+ - 'lib/gitlab/auth/o_auth/user.rb'
- 'lib/gitlab/ci/reports/security/finding_key.rb'
- 'lib/gitlab/database/load_balancing/connection_proxy.rb'
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
- - 'lib/gitlab/form_builders/gitlab_ui_form_builder.rb'
+ - 'lib/gitlab/error_tracking/error_repository/open_api_strategy.rb'
- 'lib/gitlab/git_access.rb'
- 'lib/gitlab/gl_repository/repo_type.rb'
- 'lib/gitlab/jwt_token.rb'
@@ -82,6 +95,8 @@ Layout/MultilineOperationIndentation:
- 'lib/gitlab/pagination/cursor_based_keyset.rb'
- 'lib/gitlab/quick_actions/issue_and_merge_request_actions.rb'
- 'lib/gitlab/rack_attack/request.rb'
+ - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
+ - 'lib/gitlab/sidekiq_status.rb'
- 'lib/gitlab/x509/signature.rb'
- 'lib/gitlab_edition.rb'
- 'lib/kramdown/converter/commonmark.rb'
@@ -90,12 +105,12 @@ Layout/MultilineOperationIndentation:
- 'lib/sidebars/projects/menus/deployments_menu.rb'
- 'lib/sidebars/projects/menus/hidden_menu.rb'
- 'lib/sidebars/projects/menus/monitor_menu.rb'
- - 'lib/sidebars/projects/menus/settings_menu.rb'
- 'qa/qa/ee/page/group/roadmap.rb'
- 'qa/qa/page/component/snippet.rb'
- 'qa/qa/runtime/api/repository_storage_moves.rb'
- 'rubocop/cop/gitlab/keys_first_and_values_first.rb'
- 'rubocop/migration_helpers.rb'
+ - 'spec/controllers/graphql_controller_spec.rb'
- 'spec/frontend/fixtures/tabs.rb'
- 'spec/lib/gitlab/ci/pipeline/seed/build_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
diff --git a/.rubocop_todo/layout/space_around_method_call_operator.yml b/.rubocop_todo/layout/space_around_method_call_operator.yml
deleted file mode 100644
index bc174a43d77..00000000000
--- a/.rubocop_todo/layout/space_around_method_call_operator.yml
+++ /dev/null
@@ -1,32 +0,0 @@
----
-# Cop supports --auto-correct.
-Layout/SpaceAroundMethodCallOperator:
- # Offense count: 35
- # Temporarily disabled due to too many offenses
- Enabled: false
- Exclude:
- - 'app/helpers/badges_helper.rb'
- - 'app/services/google_cloud/create_service_accounts_service.rb'
- - 'app/services/google_cloud/enable_cloud_run_service.rb'
- - 'app/services/google_cloud/generate_pipeline_service.rb'
- - 'ee/spec/lib/gitlab/ci/config/entry/dast_configuration_spec.rb'
- - 'ee/spec/migrations/geo/set_resync_flag_for_retried_projects_spec.rb'
- - 'ee/spec/models/approval_project_rule_spec.rb'
- - 'ee/spec/models/integrations/github/status_message_spec.rb'
- - 'ee/spec/services/ee/boards/issues/move_service_spec.rb'
- - 'ee/spec/services/ee/issues/create_service_spec.rb'
- - 'ee/spec/services/geo/repository_base_sync_service_spec.rb'
- - 'ee/spec/services/requirements_management/create_requirement_service_spec.rb'
- - 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
- - 'spec/graphql/types/base_field_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/chain/command_spec.rb'
- - 'spec/lib/gitlab/database/shared_model_spec.rb'
- - 'spec/lib/gitlab/diff/highlight_spec.rb'
- - 'spec/lib/gitlab/spamcheck/client_spec.rb'
- - 'spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb'
- - 'spec/models/integrations/chat_message/issue_message_spec.rb'
- - 'spec/models/milestone_spec.rb'
- - 'spec/presenters/alert_management/alert_presenter_spec.rb'
- - 'spec/requests/api/graphql/custom_emoji_query_spec.rb'
- - 'spec/tasks/gitlab/db_rake_spec.rb'
- - 'spec/workers/concerns/limited_capacity/job_tracker_spec.rb'
diff --git a/.rubocop_todo/layout/space_inside_block_braces.yml b/.rubocop_todo/layout/space_inside_block_braces.yml
index c084147eb58..4fdc308eaa5 100644
--- a/.rubocop_todo/layout/space_inside_block_braces.yml
+++ b/.rubocop_todo/layout/space_inside_block_braces.yml
@@ -1,295 +1,12 @@
---
# Cop supports --auto-correct.
Layout/SpaceInsideBlockBraces:
- # Offense count: 1508
- # Temporarily disabled due to too many offenses
- Enabled: false
- EnforcedStyle: space
Exclude:
- - 'app/controllers/groups/boards_controller.rb'
- - 'app/controllers/profiles/two_factor_auths_controller.rb'
- - 'app/controllers/projects/boards_controller.rb'
- - 'app/experiments/security_reports_mr_widget_prompt_experiment.rb'
- - 'app/experiments/video_tutorials_continuous_onboarding_experiment.rb'
- - 'app/helpers/favicon_helper.rb'
- - 'app/helpers/time_zone_helper.rb'
- - 'app/helpers/todos_helper.rb'
- - 'app/models/authentication_event.rb'
- - 'app/models/bulk_imports/entity.rb'
- - 'app/models/ci/pipeline.rb'
- - 'app/models/concerns/cache_markdown_field.rb'
- - 'app/models/concerns/featurable.rb'
- - 'app/models/integrations/bamboo.rb'
- - 'app/models/integrations/buildkite.rb'
- - 'app/models/integrations/teamcity.rb'
- - 'app/models/network/graph.rb'
- - 'app/models/operations/feature_flag.rb'
- - 'app/models/packages/package.rb'
- - 'app/models/preloaders/labels_preloader.rb'
- - 'app/models/project.rb'
- - 'app/models/release.rb'
- - 'app/models/release_highlight.rb'
- - 'app/services/authorized_project_update/project_recalculate_service.rb'
- - 'app/services/notification_service.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
- - 'db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb'
- - 'db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb'
- - 'ee/app/finders/security/training_providers/base_url_finder.rb'
- - 'ee/app/graphql/mutations/incident_management/oncall_rotation/base.rb'
- - 'ee/app/helpers/ee/dashboard_helper.rb'
- - 'ee/app/models/approvals/scan_finding_wrapped_rule_set.rb'
- - 'ee/app/models/compliance_management/framework.rb'
- - 'ee/app/models/dora/daily_metrics.rb'
- - 'ee/app/models/ee/application_setting.rb'
- - 'ee/app/models/ee/member.rb'
- - 'ee/app/models/vulnerabilities/identifier.rb'
- - 'ee/app/serializers/vulnerabilities/finding_entity.rb'
- - 'ee/app/services/elastic/cluster_reindexing_service.rb'
- - 'ee/lib/ee/banzai/filter/references/iteration_reference_filter.rb'
- - 'ee/lib/ee/gitlab/auth/ldap/group.rb'
- - 'ee/lib/ee/gitlab/background_migration/drop_invalid_remediations.rb'
- - 'ee/lib/elastic/latest/git_class_proxy.rb'
- - 'ee/lib/gitlab/auth/smartcard/san_extension.rb'
- - 'ee/lib/world.rb'
- - 'ee/spec/controllers/autocomplete_controller_spec.rb'
- - 'ee/spec/controllers/countries_controller_spec.rb'
- - 'ee/spec/controllers/groups/epics_controller_spec.rb'
- - 'ee/spec/controllers/projects/issues_controller_spec.rb'
- - 'ee/spec/controllers/projects/pipelines_controller_spec.rb'
- - 'ee/spec/controllers/subscriptions_controller_spec.rb'
- - 'ee/spec/elastic_integration/global_search_spec.rb'
- - 'ee/spec/factories/dast/profiles_pipelines.rb'
- - 'ee/spec/factories/licenses.rb'
- - 'ee/spec/features/billings/billing_plans_spec.rb'
- - 'ee/spec/features/boards/board_filters_spec.rb'
- - 'ee/spec/features/boards/scoped_issue_board_spec.rb'
- - 'ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb'
- - 'ee/spec/features/epics/todo_spec.rb'
- - 'ee/spec/features/google_analytics_datalayer_spec.rb'
- - 'ee/spec/features/groups/issues_spec.rb'
- - 'ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb'
- - 'ee/spec/features/issues/form_spec.rb'
- - 'ee/spec/features/issues/issue_sidebar_spec.rb'
- - 'ee/spec/features/issues/user_edits_issue_spec.rb'
- - 'ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb'
- - 'ee/spec/features/merge_request/user_sees_closing_issues_message_spec.rb'
- - 'ee/spec/features/merge_requests/user_resets_approvers_spec.rb'
- - 'ee/spec/features/merge_requests/user_views_all_merge_requests_spec.rb'
- - 'ee/spec/features/projects/integrations/user_activates_github_spec.rb'
- - 'ee/spec/features/projects/push_rules_spec.rb'
- - 'ee/spec/features/projects/security/dast_scanner_profiles_spec.rb'
- - 'ee/spec/features/projects/security/dast_site_profiles_spec.rb'
- - 'ee/spec/features/projects/settings/ee/service_desk_setting_spec.rb'
- - 'ee/spec/finders/billed_users_finder_spec.rb'
- - 'ee/spec/finders/clusters/environments_finder_spec.rb'
- - 'ee/spec/finders/dast/profiles_finder_spec.rb'
- - 'ee/spec/finders/ee/namespaces/projects_finder_spec.rb'
- - 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb'
- - 'ee/spec/finders/security/training_providers/kontra_url_finder_spec.rb'
- - 'ee/spec/finders/security/vulnerabilities_finder_spec.rb'
- - 'ee/spec/finders/security/vulnerability_reads_finder_spec.rb'
- - 'ee/spec/finders/status_page/incidents_finder_spec.rb'
- - 'ee/spec/frontend/fixtures/epic.rb'
- - 'ee/spec/frontend/fixtures/projects.rb'
- - 'ee/spec/graphql/ee/resolvers/namespace_projects_resolver_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/dast_site_validations/revoke_spec.rb'
- - 'ee/spec/graphql/mutations/incident_management/escalation_policy/create_spec.rb'
- - 'ee/spec/graphql/mutations/releases/update_spec.rb'
- - 'ee/spec/graphql/mutations/vulnerabilities/destroy_external_issue_link_spec.rb'
- - 'ee/spec/graphql/resolvers/iterations_resolver_spec.rb'
- - 'ee/spec/helpers/ee/projects/pipeline_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/trial_helper_spec.rb'
- - 'ee/spec/helpers/projects/on_demand_scans_helper_spec.rb'
- - 'ee/spec/lib/analytics/group_activity_calculator_spec.rb'
- - 'ee/spec/lib/ee/gitlab/alert_management/payload/generic_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/migrate_job_artifact_registry_to_ssf_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/reports/security/reports_spec.rb'
- - 'ee/spec/lib/ee/gitlab/import_export/group/tree_saver_spec.rb'
- - 'ee/spec/lib/ee/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'ee/spec/lib/ee/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb'
- - 'ee/spec/lib/ee/sidebars/groups/menus/issues_menu_spec.rb'
- - 'ee/spec/lib/ee/sidebars/groups/menus/settings_menu_spec.rb'
- - 'ee/spec/lib/ee/sidebars/projects/menus/ci_cd_menu_spec.rb'
- - 'ee/spec/lib/ee/sidebars/projects/menus/issues_menu_spec.rb'
- - 'ee/spec/lib/ee/sidebars/projects/menus/repository_menu_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/gma_membership_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/ci/parsers/security/container_scanning_spec.rb'
- - 'ee/spec/lib/gitlab/ci/reports/license_scanning/dependency_spec.rb'
- - 'ee/spec/lib/gitlab/ci/reports/security/finding_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- - 'ee/spec/lib/gitlab/geo/git_ssh_proxy_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
- - 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/loaders/bulk_epic_aggregate_loader_spec.rb'
- - 'ee/spec/lib/gitlab/ip_address_state_spec.rb'
- - 'ee/spec/lib/gitlab/search_context/builder_spec.rb'
- - 'ee/spec/lib/gitlab/status_page/filter/image_filter_spec.rb'
- - 'ee/spec/lib/gitlab/usage/metrics/instrumentations/approval_project_rules_with_user_metric_spec.rb'
- - 'ee/spec/mailers/credentials_inventory_mailer_spec.rb'
- - 'ee/spec/migrations/geo/migrate_job_artifact_registry_spec.rb'
- - 'ee/spec/models/analytics/devops_adoption/enabled_namespace_spec.rb'
- - 'ee/spec/models/analytics/devops_adoption/snapshot_spec.rb'
- - 'ee/spec/models/approval_project_rule_spec.rb'
- - 'ee/spec/models/approval_state_spec.rb'
- - 'ee/spec/models/approvals/scan_finding_wrapped_rule_set_spec.rb'
- - 'ee/spec/models/ci/minutes/limit_spec.rb'
- - 'ee/spec/models/compliance_management/framework_spec.rb'
- - 'ee/spec/models/concerns/ee/clusters/agents/authorization_config_scopes_spec.rb'
- - 'ee/spec/models/concerns/elastic/issue_spec.rb'
- - 'ee/spec/models/dast/profile_schedule_spec.rb'
- - 'ee/spec/models/ee/audit_event_spec.rb'
- - 'ee/spec/models/ee/ci/build_dependencies_spec.rb'
- - 'ee/spec/models/ee/iteration_spec.rb'
- - 'ee/spec/models/ee/namespace/root_storage_size_spec.rb'
- - 'ee/spec/models/ee/namespace_limit_spec.rb'
- - 'ee/spec/models/environment_spec.rb'
- - 'ee/spec/models/epic_spec.rb'
- - 'ee/spec/models/gitlab/seat_link_data_spec.rb'
- - 'ee/spec/models/gitlab_subscription_spec.rb'
- - 'ee/spec/models/member_spec.rb'
- - 'ee/spec/models/milestone_release_spec.rb'
- - 'ee/spec/models/project_member_spec.rb'
- - 'ee/spec/models/protected_environment_spec.rb'
- - 'ee/spec/models/push_rule_spec.rb'
- - 'ee/spec/models/requirements_management/test_report_spec.rb'
- - 'ee/spec/models/security/orchestration_policy_rule_schedule_spec.rb'
- - 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- - 'ee/spec/models/vulnerabilities/finding_spec.rb'
- - 'ee/spec/presenters/epic_issue_presenter_spec.rb'
- - 'ee/spec/requests/api/analytics/code_review_analytics_spec.rb'
- - 'ee/spec/requests/api/analytics/group_activity_analytics_spec.rb'
- - 'ee/spec/requests/api/ci/minutes_spec.rb'
- - 'ee/spec/requests/api/epic_links_spec.rb'
- - 'ee/spec/requests/api/graphql/boards/board_lists_query_spec.rb'
- - 'ee/spec/requests/api/graphql/group/epic/epic_aggregate_query_spec.rb'
- - 'ee/spec/requests/api/graphql/group/epic/epic_issues_spec.rb'
- - 'ee/spec/requests/api/graphql/group_query_spec.rb'
- - 'ee/spec/requests/api/graphql/iteration_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/dast_site_validations/revoke_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/update_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/releases/create_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/releases/update_spec.rb'
- - 'ee/spec/requests/api/graphql/project/dast_profiles_spec.rb'
- - 'ee/spec/requests/api/graphql/project/dast_site_validations_spec.rb'
- - 'ee/spec/requests/api/graphql/project/issues_spec.rb'
- - 'ee/spec/requests/api/graphql/projects/compliance_frameworks_spec.rb'
- - 'ee/spec/requests/api/group_variables_spec.rb'
- - 'ee/spec/requests/api/internal/base_spec.rb'
- - 'ee/spec/requests/api/managed_licenses_spec.rb'
- - 'ee/spec/requests/api/members_spec.rb'
- - 'ee/spec/requests/api/projects_spec.rb'
- - 'ee/spec/requests/api/protected_branches_spec.rb'
- - 'ee/spec/requests/api/releases_spec.rb'
- - 'ee/spec/requests/groups/contribution_analytics_spec.rb'
- - 'ee/spec/requests/lfs_http_spec.rb'
- - 'ee/spec/requests/projects/security/policies_controller_spec.rb'
- - 'ee/spec/serializers/member_user_entity_spec.rb'
- - 'ee/spec/serializers/merge_request_poll_widget_entity_spec.rb'
- - 'ee/spec/serializers/vulnerabilities/finding_reports_comparer_entity_spec.rb'
- - 'ee/spec/services/audit_events/register_runner_audit_event_service_spec.rb'
- - 'ee/spec/services/audit_events/unregister_runner_audit_event_service_spec.rb'
- - 'ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb'
- - 'ee/spec/services/auto_merge/merge_train_service_spec.rb'
- - 'ee/spec/services/ci/runners/register_runner_service_spec.rb'
- - 'ee/spec/services/ee/design_management/delete_designs_service_spec.rb'
- - 'ee/spec/services/ee/design_management/save_designs_service_spec.rb'
- - 'ee/spec/services/ee/issuable/bulk_update_service_spec.rb'
- - 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
- - 'ee/spec/services/ee/notification_service_spec.rb'
- - 'ee/spec/services/ee/vulnerability_feedback_module/update_service_spec.rb'
- - 'ee/spec/services/epic_issues/create_service_spec.rb'
- - 'ee/spec/services/epics/create_service_spec.rb'
- - 'ee/spec/services/epics/descendant_count_service_spec.rb'
- - 'ee/spec/services/epics/transfer_service_spec.rb'
- - 'ee/spec/services/geo/container_repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/framework_repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/hashed_storage_attachments_event_store_spec.rb'
- - 'ee/spec/services/geo/repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/wiki_sync_service_spec.rb'
- - 'ee/spec/services/gitlab_subscriptions/activate_service_spec.rb'
- - 'ee/spec/services/gitlab_subscriptions/apply_trial_service_spec.rb'
- - 'ee/spec/services/group_saml/sign_up_service_spec.rb'
- - 'ee/spec/services/groups/epics_count_service_spec.rb'
- - 'ee/spec/services/groups/memberships/export_service_spec.rb'
- - 'ee/spec/services/iterations/cadences/create_iterations_in_advance_service_spec.rb'
- - 'ee/spec/services/merge_trains/check_status_service_spec.rb'
- - 'ee/spec/services/personal_access_tokens/groups/update_lifetime_service_spec.rb'
- - 'ee/spec/services/projects/destroy_service_spec.rb'
- - 'ee/spec/services/projects/update_mirror_service_spec.rb'
- - 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- - 'ee/spec/services/requirements_management/create_requirement_service_spec.rb'
- - 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
- - 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
- - 'ee/spec/services/search/group_service_spec.rb'
- - 'ee/spec/services/security/ingestion/tasks/ingest_findings_spec.rb'
- - 'ee/spec/services/security/security_orchestration_policies/policy_commit_service_spec.rb'
- - 'ee/spec/services/sitemap/create_service_spec.rb'
- - 'ee/spec/services/software_license_policies/update_service_spec.rb'
- - 'ee/spec/services/status_page/publish_attachments_service_spec.rb'
- - 'ee/spec/services/system_notes/epics_service_spec.rb'
- - 'ee/spec/services/vulnerability_external_issue_links/create_service_spec.rb'
- - 'ee/spec/services/vulnerability_feedback/destroy_service_spec.rb'
- - 'ee/spec/support/shared_examples/features/ultimate_trial_callout_shared_examples.rb'
- - 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_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/search_notes_shared_examples.rb'
- - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
- - 'ee/spec/views/registrations/groups_projects/new.html.haml_spec.rb'
- - 'ee/spec/views/shared/billings/_eoa_bronze_plan_banner.html.haml_spec.rb'
- - 'ee/spec/views/shared/credentials_inventory/_expiry_date.html.haml_spec.rb'
- - 'ee/spec/views/shared/credentials_inventory/personal_access_tokens/_personal_access_token.html.haml_spec.rb'
- - 'ee/spec/views/shared/credentials_inventory/ssh_keys/_ssh_key.html.haml_spec.rb'
- - 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb'
- - 'ee/spec/workers/adjourned_projects_deletion_cron_worker_spec.rb'
- - 'ee/spec/workers/security/create_orchestration_policy_worker_spec.rb'
- - 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb'
- - 'lib/api/commits.rb'
- - 'lib/api/helpers/merge_requests_helpers.rb'
- - 'lib/backup/manager.rb'
- - 'lib/banzai/filter/references/label_reference_filter.rb'
- - 'lib/banzai/filter/references/milestone_reference_filter.rb'
- - 'lib/bitbucket/representation/base.rb'
- - 'lib/bitbucket_server/representation/base.rb'
- - 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb'
- - 'lib/gitlab/contributions_calendar.rb'
- - 'lib/gitlab/database/migrations/test_background_runner.rb'
- - 'lib/gitlab/database/postgres_hll/buckets.rb'
- - 'lib/gitlab/email/message/in_product_marketing/helper.rb'
- - 'lib/gitlab/issues/rebalancing/state.rb'
- - 'lib/gitlab/profiler.rb'
- - 'lib/kramdown/converter/commonmark.rb'
- - 'lib/release_highlights/validator/entry.rb'
- - 'lib/security/ci_configuration/sast_build_action.rb'
- - 'lib/tasks/gitlab/db.rake'
- - 'lib/tasks/gitlab/info.rake'
- - 'lib/tasks/gitlab/praefect.rake'
- - 'lib/tasks/gitlab/shell.rake'
- - 'lib/tasks/gitlab/tw/codeowners.rake'
- - 'qa/qa/service/praefect_manager.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_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/create_merge_request_via_template_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'
- - 'qa/qa/specs/features/ee/browser_ui/12_geo/geo_replication_npm_registry_spec.rb'
- - 'qa/spec/scenario/test/integration/mattermost_spec.rb'
- - 'qa/spec/support/page_error_checker_spec.rb'
- - 'rubocop/cop/migration/add_limit_to_text_columns.rb'
- 'spec/config/settings_spec.rb'
- 'spec/controllers/admin/application_settings_controller_spec.rb'
- 'spec/controllers/application_controller_spec.rb'
- 'spec/controllers/groups/labels_controller_spec.rb'
- 'spec/controllers/groups/releases_controller_spec.rb'
- - 'spec/controllers/groups/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/import/manifest_controller_spec.rb'
- 'spec/controllers/projects/blame_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
@@ -315,38 +32,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/factories/packages/packages.rb'
- 'spec/factories/prometheus_alert.rb'
- 'spec/factories/prometheus_metrics.rb'
- - 'spec/features/admin/admin_mode/login_spec.rb'
- - 'spec/features/admin/users/users_spec.rb'
- - 'spec/features/boards/board_filters_spec.rb'
- - 'spec/features/boards/reload_boards_on_browser_back_spec.rb'
- - 'spec/features/dashboard/archived_projects_spec.rb'
- - 'spec/features/error_tracking/user_filters_errors_by_status_spec.rb'
- - 'spec/features/groups/issues_spec.rb'
- - 'spec/features/groups_spec.rb'
- - 'spec/features/issuables/user_sees_sidebar_spec.rb'
- - 'spec/features/issues/gfm_autocomplete_spec.rb'
- - 'spec/features/issues/todo_spec.rb'
- - 'spec/features/issues/user_bulk_edits_issues_spec.rb'
- - 'spec/features/issues/user_interacts_with_awards_spec.rb'
- - 'spec/features/issues/user_uses_quick_actions_spec.rb'
- - 'spec/features/merge_request/user_approves_spec.rb'
- - 'spec/features/merge_request/user_customizes_merge_commit_message_spec.rb'
- - 'spec/features/merge_request/user_edits_assignees_sidebar_spec.rb'
- - 'spec/features/merge_request/user_sees_closing_issues_message_spec.rb'
- - 'spec/features/merge_request/user_sees_deployment_widget_spec.rb'
- - 'spec/features/merge_request/user_sees_diff_spec.rb'
- - 'spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb'
- - 'spec/features/merge_request/user_sees_versions_spec.rb'
- - 'spec/features/merge_request/user_uses_quick_actions_spec.rb'
- - 'spec/features/profiles/user_edit_profile_spec.rb'
- - 'spec/features/projects/cluster_agents_spec.rb'
- - 'spec/features/projects/commits/user_browses_commits_spec.rb'
- - 'spec/features/projects/environments/environment_spec.rb'
- - 'spec/features/projects/files/user_browses_files_spec.rb'
- - 'spec/features/projects/pipelines/pipelines_spec.rb'
- - 'spec/features/projects/settings/service_desk_setting_spec.rb'
- - 'spec/features/projects/tree/tree_show_spec.rb'
- - 'spec/features/users/login_spec.rb'
- 'spec/finders/ci/jobs_finder_spec.rb'
- 'spec/finders/ci/runners_finder_spec.rb'
- 'spec/finders/concerns/packages/finder_helper_spec.rb'
@@ -376,18 +61,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/frontend/fixtures/raw.rb'
- 'spec/frontend/fixtures/snippet.rb'
- 'spec/frontend/fixtures/todos.rb'
- - 'spec/graphql/mutations/merge_requests/set_labels_spec.rb'
- - 'spec/graphql/mutations/releases/create_spec.rb'
- - 'spec/graphql/mutations/releases/delete_spec.rb'
- - 'spec/graphql/mutations/releases/update_spec.rb'
- - 'spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb'
- - 'spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb'
- - 'spec/graphql/resolvers/project_jobs_resolver_spec.rb'
- - 'spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb'
- - 'spec/graphql/resolvers/projects_resolver_spec.rb'
- - 'spec/graphql/types/ci/job_token_scope_type_spec.rb'
- - 'spec/graphql/types/issue_type_spec.rb'
- - 'spec/graphql/types/user_type_spec.rb'
- 'spec/helpers/application_settings_helper_spec.rb'
- 'spec/helpers/blob_helper_spec.rb'
- 'spec/helpers/gitlab_script_tag_helper_spec.rb'
@@ -398,139 +71,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/helpers/wiki_page_version_helper_spec.rb'
- 'spec/initializers/carrierwave_patch_spec.rb'
- 'spec/initializers/trusted_proxies_spec.rb'
- - 'spec/lib/api/entities/ci/job_request/image_spec.rb'
- - 'spec/lib/api/entities/ci/job_request/port_spec.rb'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/lib/banzai/cross_project_reference_spec.rb'
- - 'spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb'
- - 'spec/lib/banzai/filter/commit_trailers_filter_spec.rb'
- - 'spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb'
- - 'spec/lib/banzai/renderer_spec.rb'
- - 'spec/lib/bitbucket_server/connection_spec.rb'
- - 'spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb'
- - 'spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb'
- - 'spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb'
- - 'spec/lib/feature/definition_spec.rb'
- - 'spec/lib/feature_spec.rb'
- - 'spec/lib/gitlab/application_context_spec.rb'
- - 'spec/lib/gitlab/asciidoc_spec.rb'
- - 'spec/lib/gitlab/audit/ci_runner_token_author_spec.rb'
- - 'spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb'
- - 'spec/lib/gitlab/batch_pop_queueing_spec.rb'
- - 'spec/lib/gitlab/chat_name_token_spec.rb'
- - 'spec/lib/gitlab/ci/ansi2html_spec.rb'
- - 'spec/lib/gitlab/ci/ansi2json_spec.rb'
- - 'spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/processable_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/release_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/tags_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/base_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/local_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/remote_spec.rb'
- - 'spec/lib/gitlab/ci/config/normalizer_spec.rb'
- - 'spec/lib/gitlab/ci/cron_parser_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb'
- - 'spec/lib/gitlab/ci/reports/security/reports_spec.rb'
- - 'spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb'
- - 'spec/lib/gitlab/ci/reports/test_suite_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/canceled_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/created_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/manual_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/pending_spec.rb'
- - 'spec/lib/gitlab/ci/status/build/skipped_spec.rb'
- - 'spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb'
- - 'spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/trace/remote_checksum_spec.rb'
- - 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- - 'spec/lib/gitlab/composer/cache_spec.rb'
- - 'spec/lib/gitlab/data_builder/build_spec.rb'
- - 'spec/lib/gitlab/data_builder/pipeline_spec.rb'
- - 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb'
- - 'spec/lib/gitlab/database/migration_helpers/v2_spec.rb'
- - 'spec/lib/gitlab/database/migration_helpers_spec.rb'
- - 'spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb'
- - 'spec/lib/gitlab/database/migrations/runner_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_spec.rb'
- - 'spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb'
- - 'spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb'
- - 'spec/lib/gitlab/database/with_lock_retries_spec.rb'
- - 'spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb'
- - 'spec/lib/gitlab/database_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb'
- - 'spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb'
- - 'spec/lib/gitlab/exclusive_lease_helpers_spec.rb'
- - 'spec/lib/gitlab/file_markdown_link_builder_spec.rb'
- - 'spec/lib/gitlab/git/blob_spec.rb'
- - 'spec/lib/gitlab/git/commit_spec.rb'
- - 'spec/lib/gitlab/git/diff_collection_spec.rb'
- - 'spec/lib/gitlab/git/raw_diff_change_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/commit_service_spec.rb'
- - 'spec/lib/gitlab/github_import/client_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb'
- - 'spec/lib/gitlab/gpg_spec.rb'
- - 'spec/lib/gitlab/graphql/markdown_field_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/graphs/commits_spec.rb'
- - 'spec/lib/gitlab/highlight_spec.rb'
- - 'spec/lib/gitlab/import_export/import_test_coverage_spec.rb'
- - 'spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/version_checker_spec.rb'
- - 'spec/lib/gitlab/jira/dvcs_spec.rb'
- - 'spec/lib/gitlab/kubernetes/rollout_status_spec.rb'
- - 'spec/lib/gitlab/metrics/background_transaction_spec.rb'
- - 'spec/lib/gitlab/metrics/web_transaction_spec.rb'
- - 'spec/lib/gitlab/middleware/compressed_json_spec.rb'
- - 'spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb'
- - 'spec/lib/gitlab/otp_key_rotator_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/conduit/response_spec.rb'
- - 'spec/lib/gitlab/prometheus_client_spec.rb'
- - 'spec/lib/gitlab/quick_actions/command_definition_spec.rb'
- - 'spec/lib/gitlab/quick_actions/extractor_spec.rb'
- - 'spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb'
- - 'spec/lib/gitlab/rack_attack/user_allowlist_spec.rb'
- - 'spec/lib/gitlab/redis/hll_spec.rb'
- - 'spec/lib/gitlab/reference_counter_spec.rb'
- - 'spec/lib/gitlab/regex_spec.rb'
- - 'spec/lib/gitlab/search/abuse_detection_spec.rb'
- - 'spec/lib/gitlab/search_context/builder_spec.rb'
- - 'spec/lib/gitlab/session_spec.rb'
- - 'spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb'
- - 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
- - 'spec/lib/gitlab/spamcheck/client_spec.rb'
- - 'spec/lib/gitlab/suggestions/file_suggestion_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb'
- - 'spec/lib/gitlab/utils/sanitize_node_link_spec.rb'
- - 'spec/lib/gitlab/utils/usage_data_spec.rb'
- - 'spec/lib/gitlab/utils_spec.rb'
- - 'spec/lib/gitlab/verify/uploads_spec.rb'
- - 'spec/lib/gitlab/version_info_spec.rb'
- - 'spec/lib/json_web_token/rsa_token_spec.rb'
- - 'spec/lib/marginalia_spec.rb'
- - 'spec/lib/mattermost/session_spec.rb'
- - 'spec/lib/microsoft_teams/notifier_spec.rb'
- - 'spec/lib/sidebars/groups/menus/group_information_menu_spec.rb'
- - 'spec/lib/sidebars/menu_spec.rb'
- 'spec/mailers/emails/service_desk_spec.rb'
- 'spec/migrations/20210812013042_remove_duplicate_project_authorizations_spec.rb'
- 'spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb'
@@ -538,54 +78,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/migrations/reset_job_token_scope_enabled_again_spec.rb'
- 'spec/migrations/reset_job_token_scope_enabled_spec.rb'
- 'spec/migrations/reset_severity_levels_to_new_default_spec.rb'
- - 'spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb'
- - 'spec/models/active_session_spec.rb'
- - 'spec/models/aws/role_spec.rb'
- - 'spec/models/ci/build_dependencies_spec.rb'
- - 'spec/models/ci/build_runner_session_spec.rb'
- - 'spec/models/ci/build_spec.rb'
- - 'spec/models/ci/daily_build_group_report_result_spec.rb'
- - 'spec/models/ci/job_artifact_spec.rb'
- - 'spec/models/ci/pipeline_schedule_spec.rb'
- - 'spec/models/ci/pipeline_spec.rb'
- - 'spec/models/ci/runner_spec.rb'
- - 'spec/models/clusters/cluster_spec.rb'
- - 'spec/models/commit_status_spec.rb'
- - 'spec/models/concerns/chronic_duration_attribute_spec.rb'
- - 'spec/models/concerns/counter_attribute_spec.rb'
- - 'spec/models/concerns/nullify_if_blank_spec.rb'
- - 'spec/models/concerns/reactive_caching_spec.rb'
- - 'spec/models/concerns/token_authenticatable_spec.rb'
- - 'spec/models/container_expiration_policy_spec.rb'
- - 'spec/models/container_repository_spec.rb'
- - 'spec/models/environment_spec.rb'
- - 'spec/models/event_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/hooks/web_hook_log_spec.rb'
- - 'spec/models/integrations/chat_message/wiki_page_message_spec.rb'
- - 'spec/models/issue_spec.rb'
- - 'spec/models/jira_import_state_spec.rb'
- - 'spec/models/merge_request_spec.rb'
- - 'spec/models/namespace/root_storage_statistics_spec.rb'
- - 'spec/models/namespace_spec.rb'
- - 'spec/models/note_spec.rb'
- - 'spec/models/onboarding_progress_spec.rb'
- - 'spec/models/packages/conan/metadatum_spec.rb'
- - 'spec/models/packages/package_file_spec.rb'
- - 'spec/models/packages/package_spec.rb'
- - 'spec/models/postgresql/replication_slot_spec.rb'
- - 'spec/models/preloaders/labels_preloader_spec.rb'
- - 'spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb'
- - 'spec/models/project_spec.rb'
- - 'spec/models/release_spec.rb'
- - 'spec/models/releases/link_spec.rb'
- - 'spec/models/remote_mirror_spec.rb'
- - 'spec/models/repository_spec.rb'
- - 'spec/models/snippet_input_action_collection_spec.rb'
- - 'spec/models/snippet_spec.rb'
- - 'spec/models/user_spec.rb'
- - 'spec/models/users/calloutable_spec.rb'
- - 'spec/models/wiki_page/meta_spec.rb'
- 'spec/policies/clusters/agent_policy_spec.rb'
- 'spec/policies/group_member_policy_spec.rb'
- 'spec/policies/issue_policy_spec.rb'
@@ -596,121 +88,11 @@ Layout/SpaceInsideBlockBraces:
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
- 'spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb'
- 'spec/presenters/project_presenter_spec.rb'
- - 'spec/requests/api/branches_spec.rb'
- - 'spec/requests/api/ci/jobs_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/secure_files_spec.rb'
- - 'spec/requests/api/ci/triggers_spec.rb'
- - 'spec/requests/api/ci/variables_spec.rb'
- - 'spec/requests/api/commits_spec.rb'
- - 'spec/requests/api/conan_instance_packages_spec.rb'
- - 'spec/requests/api/conan_project_packages_spec.rb'
- - 'spec/requests/api/dependency_proxy_spec.rb'
- - 'spec/requests/api/go_proxy_spec.rb'
- - 'spec/requests/api/graphql/boards/board_list_issues_query_spec.rb'
- - 'spec/requests/api/graphql/boards/board_lists_query_spec.rb'
- - 'spec/requests/api/graphql/group/dependency_proxy_manifests_spec.rb'
- - 'spec/requests/api/graphql/mutations/award_emojis/add_spec.rb'
- - 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb'
- - 'spec/requests/api/graphql/mutations/releases/create_spec.rb'
- - 'spec/requests/api/graphql/mutations/releases/update_spec.rb'
- - 'spec/requests/api/graphql/mutations/snippets/create_spec.rb'
- - 'spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb'
- - 'spec/requests/api/graphql/packages/conan_spec.rb'
- - 'spec/requests/api/graphql/packages/helm_spec.rb'
- - 'spec/requests/api/graphql/packages/package_spec.rb'
- - 'spec/requests/api/graphql/project/base_service_spec.rb'
- - 'spec/requests/api/graphql/project/jira_import_spec.rb'
- - 'spec/requests/api/group_variables_spec.rb'
- - 'spec/requests/api/groups_spec.rb'
- - 'spec/requests/api/helpers_spec.rb'
- - 'spec/requests/api/internal/base_spec.rb'
- - 'spec/requests/api/markdown_spec.rb'
- - 'spec/requests/api/maven_packages_spec.rb'
- - 'spec/requests/api/metrics/dashboard/annotations_spec.rb'
- - 'spec/requests/api/notes_spec.rb'
- - 'spec/requests/api/npm_project_packages_spec.rb'
- - 'spec/requests/api/nuget_group_packages_spec.rb'
- - 'spec/requests/api/pages/pages_spec.rb'
- - 'spec/requests/api/pages_domains_spec.rb'
- - 'spec/requests/api/personal_access_tokens_spec.rb'
- - 'spec/requests/api/project_hooks_spec.rb'
- - 'spec/requests/api/project_templates_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/snippets_spec.rb'
- - 'spec/requests/api/unleash_spec.rb'
- - 'spec/requests/git_http_spec.rb'
- - 'spec/requests/groups/milestones_controller_spec.rb'
- - 'spec/requests/lfs_http_spec.rb'
- - 'spec/requests/oauth/tokens_controller_spec.rb'
- 'spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb'
- 'spec/serializers/cluster_entity_spec.rb'
- 'spec/serializers/import/provider_repo_serializer_spec.rb'
- - 'spec/services/auto_merge/base_service_spec.rb'
- - 'spec/services/auto_merge_service_spec.rb'
- - 'spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb'
- - 'spec/services/ci/parse_dotenv_artifact_service_spec.rb'
- - 'spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb'
- - 'spec/services/ci/process_build_service_spec.rb'
- - 'spec/services/ci/runners/register_runner_service_spec.rb'
- - 'spec/services/ci/runners/update_runner_service_spec.rb'
- - 'spec/services/ci/stuck_builds/drop_pending_service_spec.rb'
- - 'spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb'
- - 'spec/services/clusters/integrations/create_service_spec.rb'
- - 'spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb'
- - 'spec/services/deployments/create_for_build_service_spec.rb'
- - 'spec/services/git/branch_push_service_spec.rb'
- - 'spec/services/groups/destroy_service_spec.rb'
- - 'spec/services/groups/merge_requests_count_service_spec.rb'
- - 'spec/services/groups/update_service_spec.rb'
- - 'spec/services/groups/update_statistics_service_spec.rb'
- - 'spec/services/import/validate_remote_git_endpoint_service_spec.rb'
- - 'spec/services/issues/referenced_merge_requests_service_spec.rb'
- - 'spec/services/jira_import/start_import_service_spec.rb'
- - 'spec/services/lfs/push_service_spec.rb'
- - 'spec/services/members/invite_service_spec.rb'
- - 'spec/services/merge_requests/push_options_handler_service_spec.rb'
- - 'spec/services/merge_requests/refresh_service_spec.rb'
- - 'spec/services/merge_requests/update_service_spec.rb'
- - 'spec/services/milestones/transfer_service_spec.rb'
- - 'spec/services/notes/copy_service_spec.rb'
- - 'spec/services/notification_service_spec.rb'
- - 'spec/services/packages/composer/create_package_service_spec.rb'
- - 'spec/services/packages/create_dependency_service_spec.rb'
- - 'spec/services/packages/debian/extract_deb_metadata_service_spec.rb'
- - 'spec/services/packages/debian/parse_debian822_service_spec.rb'
- - 'spec/services/packages/debian/sign_distribution_service_spec.rb'
- - 'spec/services/packages/helm/process_file_service_spec.rb'
- - 'spec/services/packages/npm/create_package_service_spec.rb'
- - 'spec/services/packages/rubygems/dependency_resolver_service_spec.rb'
- - 'spec/services/pages/delete_service_spec.rb'
- - 'spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb'
- - 'spec/services/projects/enable_deploy_key_service_spec.rb'
- - 'spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb'
- - 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
- - 'spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb'
- - 'spec/services/projects/participants_service_spec.rb'
- - 'spec/services/projects/update_statistics_service_spec.rb'
- - 'spec/services/quick_actions/interpret_service_spec.rb'
- - 'spec/services/releases/destroy_service_spec.rb'
- - 'spec/services/releases/update_service_spec.rb'
- - 'spec/services/resource_access_tokens/create_service_spec.rb'
- - 'spec/services/search/group_service_spec.rb'
- - 'spec/services/snippets/update_service_spec.rb'
- - 'spec/services/suggestions/apply_service_spec.rb'
- - 'spec/services/system_notes/merge_requests_service_spec.rb'
- - 'spec/services/terraform/remote_state_handler_spec.rb'
- - 'spec/services/todo_service_spec.rb'
- - 'spec/services/todos/destroy/design_service_spec.rb'
- - 'spec/services/todos/destroy/entity_leave_service_spec.rb'
- - 'spec/services/web_hook_service_spec.rb'
- 'spec/support/helpers/cycle_analytics_helpers.rb'
- 'spec/support/redis/redis_shared_examples.rb'
- - 'spec/support/shared_contexts/features/integrations/integrations_shared_context.rb'
- 'spec/support/shared_contexts/graphql/requests/packages_shared_context.rb'
- 'spec/support/shared_contexts/markdown_golden_master_shared_examples.rb'
- 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
@@ -728,7 +110,6 @@ Layout/SpaceInsideBlockBraces:
- 'spec/support/shared_examples/models/label_note_shared_examples.rb'
- 'spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb'
- 'spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/issues/merge_requests_count_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/labels_api_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb'
diff --git a/.rubocop_todo/lint/missing_cop_enable_directive.yml b/.rubocop_todo/lint/missing_cop_enable_directive.yml
index 4c1c8430204..87ac47deaf5 100644
--- a/.rubocop_todo/lint/missing_cop_enable_directive.yml
+++ b/.rubocop_todo/lint/missing_cop_enable_directive.yml
@@ -1,8 +1,5 @@
---
Lint/MissingCopEnableDirective:
- # Offense count: 199
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/projects/forks_controller.rb'
@@ -20,14 +17,19 @@ Lint/MissingCopEnableDirective:
- 'app/graphql/types/ci/build_need_type.rb'
- 'app/graphql/types/ci/config/config_type.rb'
- 'app/graphql/types/ci/config/group_type.rb'
+ - 'app/graphql/types/ci/config/include_type.rb'
- 'app/graphql/types/ci/config/job_restriction_type.rb'
- 'app/graphql/types/ci/config/job_type.rb'
- 'app/graphql/types/ci/config/need_type.rb'
- 'app/graphql/types/ci/config/stage_type.rb'
- 'app/graphql/types/ci/group_type.rb'
+ - 'app/graphql/types/ci/group_variable_type.rb'
+ - 'app/graphql/types/ci/instance_variable_type.rb'
- 'app/graphql/types/ci/job_artifact_type.rb'
- 'app/graphql/types/ci/job_type.rb'
+ - 'app/graphql/types/ci/manual_variable_type.rb'
- 'app/graphql/types/ci/pipeline_message_type.rb'
+ - 'app/graphql/types/ci/project_variable_type.rb'
- 'app/graphql/types/ci/runner_architecture_type.rb'
- 'app/graphql/types/ci/runner_platform_type.rb'
- 'app/graphql/types/ci/runner_setup_type.rb'
@@ -41,6 +43,7 @@ Lint/MissingCopEnableDirective:
- 'app/graphql/types/countable_connection_type.rb'
- 'app/graphql/types/design_management_type.rb'
- 'app/graphql/types/issue_connection_type.rb'
+ - 'app/graphql/types/limited_countable_connection_type.rb'
- 'app/graphql/types/merge_request_connection_type.rb'
- 'app/graphql/types/packages/composer/json_type.rb'
- 'app/graphql/types/packages/helm/dependency_type.rb'
@@ -71,6 +74,7 @@ Lint/MissingCopEnableDirective:
- 'db/migrate/20210818061156_remove_project_profile_compound_index_from_dast_profile_schedules.rb'
- 'db/migrate/20210818115613_add_index_project_id_on_dast_profile_schedule.rb'
- 'db/migrate/20211013014228_add_content_validation_endpoint_to_application_settings.rb'
+ - 'db/migrate/20220531024905_add_operations_access_levels_to_project_feature.rb'
- 'db/post_migrate/20210825182303_remove_duplicate_dast_site_tokens_with_same_token.rb'
- 'ee/app/controllers/ee/admin/dashboard_controller.rb'
- 'ee/app/controllers/ee/admin/groups_controller.rb'
@@ -90,6 +94,7 @@ Lint/MissingCopEnableDirective:
- 'ee/app/graphql/types/ci/minutes/project_monthly_usage_type.rb'
- 'ee/app/graphql/types/compliance_management/compliance_framework_type.rb'
- 'ee/app/graphql/types/dast/profile_cadence_type.rb'
+ - 'ee/app/graphql/types/geo/ci_secure_file_registry_type.rb'
- 'ee/app/graphql/types/geo/group_wiki_repository_registry_type.rb'
- 'ee/app/graphql/types/geo/job_artifact_registry_type.rb'
- 'ee/app/graphql/types/geo/lfs_object_registry_type.rb'
@@ -107,6 +112,7 @@ Lint/MissingCopEnableDirective:
- 'ee/app/graphql/types/security_report_summary_type.rb'
- 'ee/app/graphql/types/security_scanners.rb'
- 'ee/app/graphql/types/time_report_stats_type.rb'
+ - 'ee/app/graphql/types/timebox_error_type.rb'
- 'ee/app/graphql/types/timebox_metrics_type.rb'
- 'ee/app/graphql/types/timebox_report_type.rb'
- 'ee/app/graphql/types/vulnerabilities_count_by_day_type.rb'
@@ -135,20 +141,29 @@ Lint/MissingCopEnableDirective:
- 'ee/app/graphql/types/vulnerable_dependency_type.rb'
- 'ee/app/graphql/types/vulnerable_kubernetes_resource_type.rb'
- 'ee/app/graphql/types/vulnerable_package_type.rb'
+ - 'ee/app/services/ee/ci/queue/build_queue_service.rb'
+ - 'ee/app/workers/ci/runners/stale_group_runners_prune_cron_worker.rb'
- 'ee/app/workers/groups/export_memberships_worker.rb'
- 'ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb'
- 'ee/lib/api/ldap_group_links.rb'
- 'ee/lib/api/scim.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
- 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.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/spdx/license.rb'
+ - 'ee/spec/controllers/projects/legacy_pipelines_controller_spec.rb'
+ - 'ee/spec/helpers/groups/security_features_helper_spec.rb'
+ - 'ee/spec/helpers/projects/security/discover_helper_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/delete_invalid_epic_issues_spec.rb'
+ - 'lib/gitlab/audit/null_author.rb'
- 'lib/gitlab/auth/ldap/dn.rb'
+ - 'lib/gitlab/background_migration/backfill_imported_issue_search_data.rb'
- 'lib/gitlab/background_migration/backfill_issue_search_data.rb'
- 'lib/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'
- 'lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb'
- 'lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb'
- - 'lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb'
+ - 'lib/gitlab/background_migration/delete_invalid_epic_issues.rb'
- 'lib/gitlab/background_migration/drop_invalid_vulnerabilities.rb'
- 'lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'lib/gitlab/background_migration/mailers/unconfirm_mailer.rb'
@@ -161,11 +176,13 @@ Lint/MissingCopEnableDirective:
- 'lib/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
- 'lib/gitlab/background_migration/populate_test_reports_issue_id.rb'
- 'lib/gitlab/background_migration/populate_uuids_for_security_findings.rb'
+ - 'lib/gitlab/background_migration/purge_stale_security_scans.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb'
- 'lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb'
+ - 'lib/gitlab/buffered_io.rb'
- 'lib/gitlab/ci/reports/test_suite_summary.rb'
- 'lib/gitlab/data_builder/push.rb'
- 'lib/gitlab/database/load_balancing/connection_proxy.rb'
@@ -174,7 +191,6 @@ Lint/MissingCopEnableDirective:
- 'lib/gitlab/github_import/client.rb'
- 'lib/gitlab/github_import/importer/diff_note_importer.rb'
- 'lib/gitlab/gon_helper.rb'
- - 'lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb'
- 'lib/gitlab/graphql/pagination/keyset/last_items.rb'
- 'lib/gitlab/graphql/standard_graphql_error.rb'
- 'lib/gitlab/metrics/methods.rb'
@@ -184,10 +200,13 @@ Lint/MissingCopEnableDirective:
- 'lib/gitlab/testing/request_blocker_middleware.rb'
- 'lib/gitlab/testing/request_inspector_middleware.rb'
- 'lib/gitlab/testing/robots_blocker_middleware.rb'
+ - 'lib/unnested_in_filters/dsl.rb'
+ - 'lib/unnested_in_filters/rewriter.rb'
- 'qa/qa/scenario/test/integration/registry_with_cdn.rb'
- 'spec/benchmarks/banzai_benchmark.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/server_spec.rb'
+ - 'spec/lib/initializer_connections_spec.rb'
- 'spec/support/capybara.rb'
- 'spec/support/cycle_analytics_helpers/test_generation.rb'
- 'spec/support/google_api/cloud_platform_helpers.rb'
- - 'tooling/danger/product_intelligence.rb' \ No newline at end of file
+ - 'tooling/danger/product_intelligence.rb'
diff --git a/.rubocop_todo/naming/heredoc_delimiter_naming.yml b/.rubocop_todo/naming/heredoc_delimiter_naming.yml
index c1d058240a4..29276e529af 100644
--- a/.rubocop_todo/naming/heredoc_delimiter_naming.yml
+++ b/.rubocop_todo/naming/heredoc_delimiter_naming.yml
@@ -1,8 +1,5 @@
---
Naming/HeredocDelimiterNaming:
- # Offense count: 388
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/models/ci/build_trace_chunks/redis_base.rb'
- 'app/models/concerns/counter_attribute.rb'
@@ -31,6 +28,7 @@ Naming/HeredocDelimiterNaming:
- 'ee/spec/services/security/security_orchestration_policies/policy_commit_service_spec.rb'
- 'ee/spec/support/helpers/ee/ldap_helpers.rb'
- 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
+ - 'lib/api/metadata.rb'
- 'lib/api/version.rb'
- 'lib/backup/helper.rb'
- 'lib/feature/shared.rb'
@@ -46,14 +44,14 @@ Naming/HeredocDelimiterNaming:
- 'lib/tasks/gitlab/docs/compile_deprecations.rake'
- 'lib/tasks/gitlab/password.rake'
- 'qa/qa/scenario/test/sanity/selectors.rb'
- - 'qa/qa/service/docker_run/gitlab_runner.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/4_verify/testing/view_code_coverage_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/generic_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'
- 'rubocop/cop/database/multiple_databases.rb'
+ - 'rubocop/cop/database/rescue_query_canceled.rb'
+ - 'rubocop/cop/database/rescue_statement_timeout.rb'
- 'rubocop/cop/default_scope.rb'
- 'rubocop/cop/file_decompression.rb'
- 'rubocop/cop/gitlab/httparty.rb'
@@ -61,6 +59,7 @@ Naming/HeredocDelimiterNaming:
- 'rubocop/cop/gitlab/module_with_instance_variables.rb'
- 'rubocop/cop/gitlab/predicate_memoization.rb'
- 'spec/controllers/projects/pipelines_controller_spec.rb'
+ - 'spec/db/docs_spec.rb'
- 'spec/deprecation_toolkit_env.rb'
- 'spec/factories/packages/debian/distribution.rb'
- 'spec/factories/packages/debian/file_metadatum.rb'
@@ -68,6 +67,7 @@ Naming/HeredocDelimiterNaming:
- 'spec/features/task_lists_spec.rb'
- 'spec/helpers/markup_helper_spec.rb'
- 'spec/initializers/100_patch_omniauth_oauth2_spec.rb'
+ - 'spec/initializers/net_http_response_patch_spec.rb'
- 'spec/initializers/rack_multipart_patch_spec.rb'
- 'spec/initializers/secret_token_spec.rb'
- 'spec/initializers/validate_database_config_spec.rb'
@@ -82,6 +82,7 @@ Naming/HeredocDelimiterNaming:
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb'
- 'spec/lib/gitlab/conflict/file_collection_spec.rb'
+ - 'spec/lib/gitlab/database/loose_foreign_keys_spec.rb'
- 'spec/lib/gitlab/diff/file_spec.rb'
- 'spec/lib/gitlab/diff/pair_selector_spec.rb'
- 'spec/lib/gitlab/diff/parser_spec.rb'
@@ -131,10 +132,10 @@ Naming/HeredocDelimiterNaming:
- 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb'
- 'spec/services/google_cloud/generate_pipeline_service_spec.rb'
- 'spec/services/task_list_toggle_service_spec.rb'
- - 'spec/support/helpers/seed_helper.rb'
- 'spec/support/helpers/stub_object_storage.rb'
- 'spec/support/shared_examples/helm_commands_shared_examples.rb'
- 'spec/support/shared_examples/models/taskable_shared_examples.rb'
- 'spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb'
- 'spec/support/test_reports/test_reports_helper.rb'
+ - 'spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb'
- 'spec/workers/post_receive_spec.rb'
diff --git a/.rubocop_todo/naming/rescued_exceptions_variable_name.yml b/.rubocop_todo/naming/rescued_exceptions_variable_name.yml
deleted file mode 100644
index b557ca8f06e..00000000000
--- a/.rubocop_todo/naming/rescued_exceptions_variable_name.yml
+++ /dev/null
@@ -1,216 +0,0 @@
----
-# Cop supports --auto-correct.
-Naming/RescuedExceptionsVariableName:
- # Offense count: 269
- # Temporarily disabled due to too many offenses
- Enabled: false
- Exclude:
- - 'app/controllers/admin/projects_controller.rb'
- - 'app/controllers/projects/google_cloud/deployments_controller.rb'
- - 'app/controllers/projects/google_cloud/service_accounts_controller.rb'
- - 'app/controllers/projects/merge_requests/drafts_controller.rb'
- - 'app/controllers/projects/milestones_controller.rb'
- - 'app/controllers/projects/mirrors_controller.rb'
- - 'app/controllers/projects/repositories_controller.rb'
- - 'app/controllers/projects_controller.rb'
- - 'app/finders/repositories/changelog_tag_finder.rb'
- - 'app/graphql/mutations/issues/move.rb'
- - 'app/graphql/resolvers/ci/config_resolver.rb'
- - 'app/graphql/resolvers/environments_resolver.rb'
- - 'app/helpers/application_helper.rb'
- - 'app/models/application_setting.rb'
- - 'app/models/blob_viewer/metrics_dashboard_yml.rb'
- - 'app/models/ci/build.rb'
- - 'app/models/ci/deleted_object.rb'
- - 'app/models/concerns/prometheus_adapter.rb'
- - 'app/models/concerns/repository_storage_movable.rb'
- - 'app/models/concerns/x509_serial_number_attribute.rb'
- - 'app/models/integrations/base_issue_tracker.rb'
- - 'app/models/integrations/discord.rb'
- - 'app/models/integrations/jenkins.rb'
- - 'app/models/integrations/jira.rb'
- - 'app/models/integrations/packagist.rb'
- - 'app/models/integrations/pipelines_email.rb'
- - 'app/models/integrations/prometheus.rb'
- - 'app/models/performance_monitoring/prometheus_dashboard.rb'
- - 'app/models/personal_access_token.rb'
- - 'app/models/project.rb'
- - 'app/models/repository.rb'
- - 'app/models/snippet_repository.rb'
- - 'app/models/u2f_registration.rb'
- - 'app/models/wiki.rb'
- - 'app/services/branches/delete_service.rb'
- - 'app/services/branches/validate_new_service.rb'
- - 'app/services/ci/job_artifacts/create_service.rb'
- - 'app/services/ci/parse_dotenv_artifact_service.rb'
- - 'app/services/ci/register_job_service.rb'
- - 'app/services/ci/stuck_builds/drop_helpers.rb'
- - 'app/services/clusters/applications/prometheus_update_service.rb'
- - 'app/services/commits/change_service.rb'
- - 'app/services/commits/create_service.rb'
- - 'app/services/dependency_proxy/head_manifest_service.rb'
- - 'app/services/dependency_proxy/request_token_service.rb'
- - 'app/services/design_management/copy_design_collection/copy_service.rb'
- - 'app/services/git/base_hooks_service.rb'
- - 'app/services/grafana/proxy_service.rb'
- - 'app/services/groups/update_shared_runners_service.rb'
- - 'app/services/issues/relative_position_rebalancing_service.rb'
- - 'app/services/jira/requests/base.rb'
- - 'app/services/jira_import/start_import_service.rb'
- - 'app/services/jira_import/users_importer.rb'
- - 'app/services/lfs/lock_file_service.rb'
- - 'app/services/lfs/locks_finder_service.rb'
- - 'app/services/lfs/push_service.rb'
- - 'app/services/lfs/unlock_file_service.rb'
- - 'app/services/merge_requests/merge_to_ref_service.rb'
- - 'app/services/merge_requests/mergeability_check_service.rb'
- - 'app/services/metrics/dashboard/base_service.rb'
- - 'app/services/metrics/dashboard/panel_preview_service.rb'
- - 'app/services/projects/cleanup_service.rb'
- - 'app/services/projects/destroy_service.rb'
- - 'app/services/projects/hashed_storage/base_repository_service.rb'
- - 'app/services/projects/transfer_service.rb'
- - 'app/services/prometheus/proxy_service.rb'
- - 'app/services/resource_access_tokens/revoke_service.rb'
- - 'app/services/tags/create_service.rb'
- - 'app/services/tags/destroy_service.rb'
- - 'app/services/users/validate_manual_otp_service.rb'
- - 'app/services/users/validate_push_otp_service.rb'
- - 'app/services/verify_pages_domain_service.rb'
- - 'app/validators/js_regex_validator.rb'
- - 'app/workers/concerns/limited_capacity/worker.rb'
- - 'app/workers/gitlab/jira_import/import_issue_worker.rb'
- - 'app/workers/issuable_export_csv_worker.rb'
- - 'app/workers/namespaces/root_statistics_worker.rb'
- - 'app/workers/namespaces/schedule_aggregation_worker.rb'
- - 'app/workers/packages/go/sync_packages_worker.rb'
- - 'app/workers/project_destroy_worker.rb'
- - 'app/workers/projects/git_garbage_collect_worker.rb'
- - 'app/workers/remove_expired_members_worker.rb'
- - 'app/workers/users/create_statistics_worker.rb'
- - 'config/initializers/rspec_profiling.rb'
- - 'config/initializers/wikicloth_redos_patch.rb'
- - 'db/post_migrate/20210606143426_add_index_for_container_registry_access_level.rb'
- - 'db/post_migrate/20211206162601_cleanup_after_add_primary_email_to_emails_if_user_confirmed.rb'
- - 'db/post_migrate/20220318111729_cleanup_after_fixing_issue_when_admin_changed_primary_email.rb'
- - 'db/post_migrate/20220504083836_cleanup_after_fixing_regression_with_new_users_emails.rb'
- - 'ee/app/finders/projects/integrations/jira/by_ids_finder.rb'
- - 'ee/app/graphql/mutations/issues/promote_to_epic.rb'
- - 'ee/app/graphql/mutations/issues/set_epic.rb'
- - 'ee/app/helpers/ee/kerberos_spnego_helper.rb'
- - 'ee/app/models/concerns/geo/replicable_model.rb'
- - 'ee/app/models/integrations/github.rb'
- - 'ee/app/services/app_sec/dast/profiles/create_service.rb'
- - 'ee/app/services/app_sec/dast/profiles/update_service.rb'
- - 'ee/app/services/app_sec/dast/scans/create_service.rb'
- - 'ee/app/services/app_sec/dast/site_validations/find_or_create_service.rb'
- - 'ee/app/services/app_sec/dast/site_validations/revoke_service.rb'
- - 'ee/app/services/app_sec/fuzzing/coverage/corpuses/create_service.rb'
- - 'ee/app/services/arkose/user_verification_service.rb'
- - 'ee/app/services/ci/sync_reports_to_approval_rules_service.rb'
- - 'ee/app/services/elastic/process_bookkeeping_service.rb'
- - 'ee/app/services/geo/file_registry_removal_service.rb'
- - 'ee/app/services/geo/framework_repository_sync_service.rb'
- - 'ee/app/services/geo/move_repository_service.rb'
- - 'ee/app/services/geo/repository_base_sync_service.rb'
- - 'ee/app/services/incident_management/oncall_rotations/create_service.rb'
- - 'ee/app/services/incident_management/oncall_rotations/edit_service.rb'
- - 'ee/app/services/projects/licenses/create_policy_service.rb'
- - 'ee/app/services/projects/licenses/update_policy_service.rb'
- - 'ee/app/services/security/ingestion/ingest_report_service.rb'
- - 'ee/app/services/security/orchestration/assign_service.rb'
- - 'ee/app/services/security/store_grouped_scans_service.rb'
- - 'ee/app/services/security/store_scan_service.rb'
- - 'ee/app/services/security/token_revocation_service.rb'
- - 'ee/app/services/software_license_policies/create_service.rb'
- - 'ee/app/services/software_license_policies/update_service.rb'
- - 'ee/app/workers/adjourned_project_deletion_worker.rb'
- - 'ee/app/workers/geo/file_removal_worker.rb'
- - 'ee/app/workers/geo/repositories_clean_up_worker.rb'
- - 'ee/app/workers/geo/scheduler/scheduler_worker.rb'
- - 'ee/app/workers/refresh_license_compliance_checks_worker.rb'
- - 'ee/app/workers/repository_update_mirror_worker.rb'
- - 'ee/app/workers/sync_seat_link_request_worker.rb'
- - 'ee/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings.rb'
- - 'ee/lib/elastic/instance_proxy_util.rb'
- - 'ee/lib/gitlab/audit/auditor.rb'
- - 'ee/lib/gitlab/auth/smartcard/base.rb'
- - 'ee/lib/gitlab/ci/parsers/license_compliance/license_scanning.rb'
- - 'ee/lib/gitlab/elastic/bulk_indexer.rb'
- - 'ee/lib/gitlab/spdx/catalogue_gateway.rb'
- - 'ee/lib/tasks/gitlab/seed/metrics.rake'
- - 'lib/api/environments.rb'
- - 'lib/api/helpers.rb'
- - 'lib/api/helpers/label_helpers.rb'
- - 'lib/api/issues.rb'
- - 'lib/api/project_milestones.rb'
- - 'lib/api/projects.rb'
- - 'lib/api/repositories.rb'
- - 'lib/api/v3/github.rb'
- - 'lib/gitaly/server.rb'
- - 'lib/gitlab/auth/ldap/adapter.rb'
- - 'lib/gitlab/auth/otp/strategies/forti_authenticator/manual_otp.rb'
- - 'lib/gitlab/auth/otp/strategies/forti_authenticator/push_otp.rb'
- - 'lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb'
- - 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- - 'lib/gitlab/ci/config/external/file/artifact.rb'
- - 'lib/gitlab/ci/pipeline/chain/config/process.rb'
- - 'lib/gitlab/ci/pipeline/chain/validate/external.rb'
- - 'lib/gitlab/ci/reports/codequality_reports.rb'
- - 'lib/gitlab/database/background_migration/batched_job.rb'
- - 'lib/gitlab/database/background_migration/batched_migration_wrapper.rb'
- - 'lib/gitlab/database/batch_counter.rb'
- - 'lib/gitlab/database/load_balancing/load_balancer.rb'
- - 'lib/gitlab/database/load_balancing/service_discovery.rb'
- - 'lib/gitlab/database/reindexing/grafana_notifier.rb'
- - 'lib/gitlab/git/keep_around.rb'
- - 'lib/gitlab/gitaly_client/call.rb'
- - 'lib/gitlab/gitaly_client/commit_service.rb'
- - 'lib/gitlab/gitaly_client/operation_service.rb'
- - 'lib/gitlab/gitaly_client/ref_service.rb'
- - 'lib/gitlab/gitaly_client/repository_service.rb'
- - 'lib/gitlab/hashed_storage/migrator.rb'
- - 'lib/gitlab/health_checks/base_abstract_check.rb'
- - 'lib/gitlab/import_export/merge_request_parser.rb'
- - 'lib/gitlab/instrumentation/redis_interceptor.rb'
- - 'lib/gitlab/issuables_count_for_state.rb'
- - 'lib/gitlab/jira_import/issues_importer.rb'
- - 'lib/gitlab/json.rb'
- - 'lib/gitlab/jwt_token.rb'
- - 'lib/gitlab/kubernetes/namespace.rb'
- - 'lib/gitlab/metrics/dashboard/stages/panel_ids_inserter.rb'
- - 'lib/gitlab/metrics/rack_middleware.rb'
- - 'lib/gitlab/middleware/handle_ip_spoof_attack_error.rb'
- - 'lib/gitlab/prometheus/queries/validate_query.rb'
- - 'lib/gitlab/prometheus_client.rb'
- - 'lib/gitlab/sanitizers/exif.rb'
- - 'lib/gitlab/sidekiq_logging/structured_logger.rb'
- - 'lib/gitlab/tcp_checker.rb'
- - 'lib/gitlab/template_parser/parser.rb'
- - 'lib/gitlab/tracking.rb'
- - 'lib/gitlab/url_blocker.rb'
- - 'lib/gitlab/usage/metrics/aggregates/aggregate.rb'
- - 'lib/gitlab/usage_data.rb'
- - 'lib/gitlab/utils/usage_data.rb'
- - 'lib/gitlab/verify/batch_verifier.rb'
- - 'lib/gitlab/wiki_pages/front_matter_parser.rb'
- - 'lib/microsoft_teams/notifier.rb'
- - 'lib/system_check/incoming_email/imap_authentication_check.rb'
- - 'lib/tasks/gitlab/db/validate_config.rake'
- - 'lib/tasks/gitlab/setup.rake'
- - 'lib/tasks/gitlab/storage.rake'
- - 'lib/tasks/lint.rake'
- - 'qa/qa/resource/user_gpg.rb'
- - 'scripts/review_apps/automated_cleanup.rb'
- - 'scripts/trigger-build.rb'
- - 'spec/commands/metrics_server/metrics_server_spec.rb'
- - 'spec/db/docs_spec.rb'
- - 'spec/lib/bulk_imports/network_error_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/host_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
- - 'spec/lib/gitlab/error_tracking_spec.rb'
- - 'spec/lib/gitlab/sanitizers/exception_message_spec.rb'
- - 'spec/support/capybara.rb'
- - 'spec/support/helpers/capybara_helpers.rb'
- - 'tooling/lib/tooling/helm3_client.rb'
- - 'tooling/lib/tooling/kubernetes_client.rb'
diff --git a/.rubocop_todo/performance/block_given_with_explicit_block.yml b/.rubocop_todo/performance/block_given_with_explicit_block.yml
deleted file mode 100644
index b919dbd19e6..00000000000
--- a/.rubocop_todo/performance/block_given_with_explicit_block.yml
+++ /dev/null
@@ -1,43 +0,0 @@
----
-# Cop supports --auto-correct.
-Performance/BlockGivenWithExplicitBlock:
- Exclude:
- - 'app/controllers/concerns/redis_tracking.rb'
- - 'app/helpers/badges_helper.rb'
- - 'app/helpers/instance_configuration_helper.rb'
- - 'app/helpers/labels_helper.rb'
- - 'app/helpers/tab_helper.rb'
- - 'app/services/base_count_service.rb'
- - 'app/services/error_tracking/base_service.rb'
- - 'app/services/users/update_service.rb'
- - 'ee/lib/elastic/latest/query_context.rb'
- - 'ee/lib/gitlab/geo.rb'
- - 'lib/bulk_imports/clients/http.rb'
- - 'lib/gitlab/batch_pop_queueing.rb'
- - 'lib/gitlab/cache/request_cache.rb'
- - 'lib/gitlab/ci/trace/chunked_io.rb'
- - 'lib/gitlab/database/bulk_update.rb'
- - 'lib/gitlab/database/with_lock_retries.rb'
- - 'lib/gitlab/github_import/client.rb'
- - 'lib/gitlab/legacy_github_import/client.rb'
- - 'lib/gitlab/metrics/methods/metric_options.rb'
- - 'lib/gitlab/null_request_store.rb'
- - 'lib/gitlab/quick_actions/dsl.rb'
- - 'lib/gitlab/redis/multi_store.rb'
- - 'lib/gitlab/safe_request_loader.rb'
- - 'lib/gitlab/search/query.rb'
- - 'lib/gitlab/string_placeholder_replacer.rb'
- - 'lib/gitlab/terraform/state_migration_helper.rb'
- - 'lib/gitlab/usage/metrics/instrumentations/base_metric.rb'
- - 'lib/gitlab/usage/metrics/instrumentations/database_metric.rb'
- - 'lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb'
- - 'lib/gitlab/usage_data_queries.rb'
- - 'lib/gitlab/utils/usage_data.rb'
- - 'qa/qa/page/view.rb'
- - 'spec/lib/api/helpers/authentication_spec.rb'
- - 'spec/lib/gitlab/slash_commands/deploy_spec.rb'
- - 'spec/support/helpers/graphql_helpers.rb'
- - 'spec/support/helpers/query_recorder.rb'
- - 'spec/support/helpers/stub_method_calls.rb'
- - 'tooling/lib/tooling/helm3_client.rb'
- - 'tooling/lib/tooling/test_map_packer.rb'
diff --git a/.rubocop_todo/performance/constant_regexp.yml b/.rubocop_todo/performance/constant_regexp.yml
deleted file mode 100644
index 23d03ced8d7..00000000000
--- a/.rubocop_todo/performance/constant_regexp.yml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-# Cop supports --auto-correct.
-Performance/ConstantRegexp:
- Exclude:
- - 'app/models/commit.rb'
- - 'app/models/commit_range.rb'
- - 'app/models/custom_emoji.rb'
- - 'app/models/gpg_key.rb'
- - 'app/models/merge_request.rb'
- - 'app/models/packages/package.rb'
- - 'app/models/project.rb'
- - 'app/models/wiki.rb'
- - 'ee/app/models/ee/epic.rb'
- - 'lib/banzai/filter/custom_emoji_filter.rb'
- - 'lib/gitlab/cleanup/project_uploads.rb'
- - 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- - 'lib/gitlab/dependency_linker/base_linker.rb'
- - 'lib/gitlab/dependency_linker/composer_json_linker.rb'
- - 'lib/gitlab/dependency_linker/godeps_json_linker.rb'
- - 'lib/gitlab/dependency_linker/podspec_linker.rb'
- - 'lib/gitlab/git.rb'
- - 'lib/gitlab/job_waiter.rb'
- - 'lib/gitlab/metrics/dashboard/url.rb'
- - 'lib/gitlab/path_regex.rb'
- - 'lib/gitlab/regex.rb'
- - 'scripts/perf/query_limiting_report.rb'
- - 'scripts/validate_migration_schema'
- - 'spec/features/users/email_verification_on_login_spec.rb'
- - 'spec/models/concerns/token_authenticatable_spec.rb'
- - 'spec/services/notes/copy_service_spec.rb'
diff --git a/.rubocop_todo/rails/pick.yml b/.rubocop_todo/rails/pick.yml
deleted file mode 100644
index 95ed3e61cb5..00000000000
--- a/.rubocop_todo/rails/pick.yml
+++ /dev/null
@@ -1,43 +0,0 @@
----
-# Cop supports --auto-correct.
-Rails/Pick:
- # Offense count: 42
- # Temporarily disabled due to too many offenses
- Enabled: false
- Exclude:
- - 'app/models/ci/pipeline.rb'
- - 'app/models/merge_request.rb'
- - 'app/models/merge_request/metrics.rb'
- - 'app/models/merge_request_diff.rb'
- - 'db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb'
- - 'db/post_migrate/20220213103859_remove_integrations_type.rb'
- - 'db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb'
- - 'ee/app/models/concerns/epic_tree_sorting.rb'
- - 'ee/app/models/ee/group.rb'
- - 'ee/app/models/ee/namespace.rb'
- - 'ee/app/models/geo/project_registry.rb'
- - 'ee/lib/analytics/merge_request_metrics_calculator.rb'
- - 'ee/lib/ee/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'
- - 'ee/lib/ee/gitlab/background_migration/populate_status_column_of_security_scans.rb'
- - 'ee/spec/finders/security/findings_finder_spec.rb'
- - 'lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb'
- - 'lib/gitlab/background_migration/backfill_ci_project_mirrors.rb'
- - 'lib/gitlab/background_migration/backfill_integrations_type_new.rb'
- - 'lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb'
- - 'lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb'
- - 'lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb'
- - 'lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb'
- - 'lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb'
- - 'lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb'
- - 'lib/gitlab/background_migration/drop_invalid_security_findings.rb'
- - 'lib/gitlab/background_migration/encrypt_static_object_token.rb'
- - 'lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb'
- - 'lib/gitlab/background_migration/populate_vulnerability_reads.rb'
- - 'lib/gitlab/background_migration/update_timelogs_null_spent_at.rb'
- - 'lib/gitlab/database/dynamic_model_helpers.rb'
- - 'lib/gitlab/database/migrations/background_migration_helpers.rb'
- - 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
- - 'lib/gitlab/github_import/user_finder.rb'
- - 'lib/gitlab/relative_positioning/item_context.rb'
- - 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
- - 'spec/requests/projects/cycle_analytics_events_spec.rb'
diff --git a/.rubocop_todo/rails/rake_environment.yml b/.rubocop_todo/rails/rake_environment.yml
deleted file mode 100644
index d248db022ce..00000000000
--- a/.rubocop_todo/rails/rake_environment.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-# Cop supports --auto-correct.
-Rails/RakeEnvironment:
- # Offense count: 31
- # Temporarily disabled due to too many offenses
- Enabled: false
- Exclude:
- - 'ee/lib/tasks/gitlab/elastic/test.rake'
- - 'lib/tasks/config_lint.rake'
- - 'lib/tasks/dev.rake'
- - 'lib/tasks/gettext.rake'
- - 'lib/tasks/gitlab/assets.rake'
- - 'lib/tasks/gitlab/db.rake'
- - 'lib/tasks/gitlab/docs/compile_deprecations.rake'
- - 'lib/tasks/gitlab/docs/redirect.rake'
- - 'lib/tasks/gitlab/helpers.rake'
- - 'lib/tasks/gitlab/sidekiq.rake'
- - 'lib/tasks/gitlab/tw/codeowners.rake'
- - 'lib/tasks/gitlab/update_templates.rake'
- - 'lib/tasks/lint.rake'
- - 'lib/tasks/migrate/setup_postgresql.rake'
- - 'lib/tasks/setup.rake'
- - 'lib/tasks/test.rake'
- - 'lib/tasks/yarn.rake'
- - 'qa/qa/fixtures/auto_devops_rack/Rakefile'
diff --git a/.rubocop_todo/rails/skips_model_validations.yml b/.rubocop_todo/rails/skips_model_validations.yml
index 5c573a484f6..8ef895ed562 100644
--- a/.rubocop_todo/rails/skips_model_validations.yml
+++ b/.rubocop_todo/rails/skips_model_validations.yml
@@ -299,7 +299,6 @@ Rails/SkipsModelValidations:
- 'ee/spec/models/ee/groups/feature_setting_spec.rb'
- 'ee/spec/models/ee/iteration_spec.rb'
- 'ee/spec/models/ee/iterations/cadence_spec.rb'
- - 'ee/spec/models/ee/namespace_limit_spec.rb'
- 'ee/spec/models/ee/vulnerability_spec.rb'
- 'ee/spec/models/geo_node_spec.rb'
- 'ee/spec/models/geo_node_status_spec.rb'
diff --git a/.rubocop_todo/rspec/be.yml b/.rubocop_todo/rspec/be.yml
new file mode 100644
index 00000000000..dad8a7d730b
--- /dev/null
+++ b/.rubocop_todo/rspec/be.yml
@@ -0,0 +1,22 @@
+---
+RSpec/Be:
+ Exclude:
+ - 'ee/spec/services/groups/transfer_service_spec.rb'
+ - 'spec/lib/bulk_imports/common/pipelines/boards_pipeline_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
+ - 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
+ - 'spec/lib/gitlab/search_context/builder_spec.rb'
+ - 'spec/migrations/20220503035221_add_gitlab_schema_to_batched_background_migrations_spec.rb'
+ - 'spec/models/concerns/issuable_spec.rb'
+ - 'spec/models/identity_spec.rb'
+ - 'spec/models/snippet_repository_spec.rb'
+ - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
+ - 'spec/requests/api/graphql/mutations/snippets/create_spec.rb'
+ - 'spec/requests/api/pages_domains_spec.rb'
+ - 'spec/services/pages/delete_service_spec.rb'
+ - 'spec/services/pages/destroy_deployments_service_spec.rb'
+ - 'spec/services/pages/migrate_from_legacy_storage_service_spec.rb'
+ - 'spec/services/projects/update_pages_service_spec.rb'
+ - 'spec/support/shared_examples/requests/api/packages_shared_examples.rb'
+ - 'spec/uploaders/file_uploader_spec.rb'
+ - 'spec/uploaders/namespace_file_uploader_spec.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 724aa420d89..163533621a6 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -1,9 +1,7 @@
---
RSpec/ContextWording:
- # Offense count: 18360
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'ee/spec/components/namespaces/free_user_cap/personal_usage_quota_limitations_alert_component_spec.rb'
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
- 'ee/spec/controllers/admin/audit_logs_controller_spec.rb'
- 'ee/spec/controllers/admin/dev_ops_report_controller_spec.rb'
@@ -15,19 +13,15 @@ RSpec/ContextWording:
- 'ee/spec/controllers/autocomplete_controller_spec.rb'
- 'ee/spec/controllers/boards/lists_controller_spec.rb'
- 'ee/spec/controllers/dashboard_controller_spec.rb'
- - 'ee/spec/controllers/ee/dashboard/projects_controller_spec.rb'
- 'ee/spec/controllers/ee/groups/variables_controller_spec.rb'
- 'ee/spec/controllers/ee/groups_controller_spec.rb'
- - 'ee/spec/controllers/ee/profiles/preferences_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/jobs_controller_spec.rb'
- 'ee/spec/controllers/ee/projects/merge_requests/content_controller_spec.rb'
- 'ee/spec/controllers/ee/registrations_controller_spec.rb'
- 'ee/spec/controllers/ee/root_controller_spec.rb'
- 'ee/spec/controllers/ee/search_controller_spec.rb'
- 'ee/spec/controllers/ee/sent_notifications_controller_spec.rb'
- - 'ee/spec/controllers/ee/sessions_controller_spec.rb'
- 'ee/spec/controllers/groups/analytics/cycle_analytics_controller_spec.rb'
- - 'ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb'
- 'ee/spec/controllers/groups/audit_events_controller_spec.rb'
- 'ee/spec/controllers/groups/billings_controller_spec.rb'
- 'ee/spec/controllers/groups/boards_controller_spec.rb'
@@ -42,21 +36,15 @@ RSpec/ContextWording:
- 'ee/spec/controllers/groups/push_rules_controller_spec.rb'
- 'ee/spec/controllers/groups/saml_providers_controller_spec.rb'
- 'ee/spec/controllers/groups/scim_oauth_controller_spec.rb'
- - 'ee/spec/controllers/groups/security/compliance_dashboards_controller_spec.rb'
- - 'ee/spec/controllers/groups/security/dashboard_controller_spec.rb'
- 'ee/spec/controllers/groups/security/merge_commit_reports_controller_spec.rb'
- - 'ee/spec/controllers/groups/security/vulnerabilities_controller_spec.rb'
- 'ee/spec/controllers/groups/sso_controller_spec.rb'
- 'ee/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb'
- 'ee/spec/controllers/oauth/applications_controller_spec.rb'
- 'ee/spec/controllers/oauth/geo_auth_controller_spec.rb'
- 'ee/spec/controllers/operations_controller_spec.rb'
- 'ee/spec/controllers/profiles_controller_spec.rb'
- - 'ee/spec/controllers/projects/approver_groups_controller_spec.rb'
- - 'ee/spec/controllers/projects/approvers_controller_spec.rb'
- 'ee/spec/controllers/projects/audit_events_controller_spec.rb'
- 'ee/spec/controllers/projects/boards_controller_spec.rb'
- - 'ee/spec/controllers/projects/branches_controller_spec.rb'
- 'ee/spec/controllers/projects/environments_controller_spec.rb'
- 'ee/spec/controllers/projects/imports_controller_spec.rb'
- 'ee/spec/controllers/projects/incident_management/escalation_policies_controller_spec.rb'
@@ -76,29 +64,27 @@ RSpec/ContextWording:
- 'ee/spec/controllers/projects/settings/repository_controller_spec.rb'
- 'ee/spec/controllers/projects/vulnerability_feedback_controller_spec.rb'
- 'ee/spec/controllers/projects_controller_spec.rb'
- - 'ee/spec/controllers/registrations/company_controller_spec.rb'
- 'ee/spec/controllers/registrations/groups_projects_controller_spec.rb'
- 'ee/spec/controllers/registrations/welcome_controller_spec.rb'
- 'ee/spec/controllers/repositories/git_http_controller_spec.rb'
- 'ee/spec/controllers/security/dashboard_controller_spec.rb'
- - 'ee/spec/controllers/security/projects_controller_spec.rb'
- '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'
+ - 'ee/spec/elastic/migrate/20220613120500_migrate_commits_to_separate_index_spec.rb'
+ - 'ee/spec/elastic/migrate/20220713103500_delete_commits_from_original_index_spec.rb'
- 'ee/spec/elastic/migrate/migration_shared_examples.rb'
- 'ee/spec/elastic_integration/global_search_spec.rb'
- 'ee/spec/features/admin/admin_audit_logs_spec.rb'
- 'ee/spec/features/admin/admin_credentials_inventory_spec.rb'
- - 'ee/spec/features/admin/admin_dashboard_spec.rb'
- 'ee/spec/features/admin/admin_dev_ops_reports_spec.rb'
- 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/admin/geo/admin_geo_nodes_spec.rb'
- - 'ee/spec/features/admin/geo/admin_geo_sidebar_spec.rb'
- - 'ee/spec/features/admin/groups/admin_subscription_alerts_spec.rb'
- 'ee/spec/features/admin/licenses/admin_adds_license_spec.rb'
- - 'ee/spec/features/admin/licenses/show_user_count_threshold_spec.rb'
- 'ee/spec/features/analytics/code_analytics_spec.rb'
- 'ee/spec/features/billings/billing_plans_spec.rb'
- 'ee/spec/features/boards/boards_licensed_features_spec.rb'
@@ -109,9 +95,8 @@ RSpec/ContextWording:
- 'ee/spec/features/boards/swimlanes/epics_swimlanes_drag_drop_spec.rb'
- 'ee/spec/features/boards/swimlanes/epics_swimlanes_filtering_spec.rb'
- 'ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_labels_spec.rb'
- - 'ee/spec/features/boards/swimlanes/epics_swimlanes_sidebar_spec.rb'
- 'ee/spec/features/boards/swimlanes/epics_swimlanes_spec.rb'
- - 'ee/spec/features/boards/user_visits_board_spec.rb'
+ - 'ee/spec/features/dashboards/todos_spec.rb'
- 'ee/spec/features/discussion_comments/epic_quick_actions_spec.rb'
- 'ee/spec/features/epic_boards/epic_boards_sidebar_spec.rb'
- 'ee/spec/features/epic_boards/epic_boards_spec.rb'
@@ -120,25 +105,19 @@ RSpec/ContextWording:
- 'ee/spec/features/epics/epic_issues_spec.rb'
- 'ee/spec/features/epics/epics_list_spec.rb'
- 'ee/spec/features/epics/gfm_autocomplete_spec.rb'
- - 'ee/spec/features/epics/issue_promotion_spec.rb'
- 'ee/spec/features/epics/referencing_epics_spec.rb'
- 'ee/spec/features/epics/update_epic_spec.rb'
- - 'ee/spec/features/epics/user_uses_quick_actions_spec.rb'
- 'ee/spec/features/geo_node_spec.rb'
- - 'ee/spec/features/google_analytics_datalayer_spec.rb'
- - 'ee/spec/features/groups/active_tabs_spec.rb'
+ - 'ee/spec/features/gitlab_subscriptions/seat_count_alert_spec.rb'
- 'ee/spec/features/groups/analytics/cycle_analytics/charts_spec.rb'
- 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
- 'ee/spec/features/groups/analytics/cycle_analytics/multiple_value_streams_spec.rb'
- 'ee/spec/features/groups/audit_events_spec.rb'
- - 'ee/spec/features/groups/group_overview_spec.rb'
- 'ee/spec/features/groups/group_roadmap_spec.rb'
- 'ee/spec/features/groups/group_settings_spec.rb'
- 'ee/spec/features/groups/groups_security_credentials_spec.rb'
- 'ee/spec/features/groups/issues_spec.rb'
- 'ee/spec/features/groups/iteration_spec.rb'
- - 'ee/spec/features/groups/iterations/iterations_list_spec.rb'
- - 'ee/spec/features/groups/iterations/user_edits_iteration_cadence_spec.rb'
- 'ee/spec/features/groups/iterations/user_edits_iteration_spec.rb'
- 'ee/spec/features/groups/ldap_group_links_spec.rb'
- 'ee/spec/features/groups/members/manage_groups_spec.rb'
@@ -148,13 +127,11 @@ RSpec/ContextWording:
- 'ee/spec/features/groups/saml_providers_spec.rb'
- 'ee/spec/features/groups/seat_usage/seat_usage_spec.rb'
- 'ee/spec/features/groups/security/compliance_dashboards_spec.rb'
- - 'ee/spec/features/groups/settings/user_searches_in_settings_spec.rb'
- 'ee/spec/features/groups/sso_spec.rb'
- 'ee/spec/features/groups/usage_quotas_spec.rb'
- - 'ee/spec/features/groups/wiki/user_views_wiki_empty_spec.rb'
- 'ee/spec/features/groups_spec.rb'
+ - 'ee/spec/features/ide/user_commits_changes_spec.rb'
- 'ee/spec/features/ide/user_opens_ide_spec.rb'
- - 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
- 'ee/spec/features/issues/epic_in_issue_sidebar_spec.rb'
- 'ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb'
- 'ee/spec/features/issues/form_spec.rb'
@@ -180,20 +157,19 @@ RSpec/ContextWording:
- 'ee/spec/features/merge_requests/user_filters_by_approvers_spec.rb'
- 'ee/spec/features/oncall_schedules/user_creates_schedule_spec.rb'
- 'ee/spec/features/profiles/account_spec.rb'
+ - 'ee/spec/features/profiles/usage_quotas_spec.rb'
- 'ee/spec/features/projects/active_tabs_spec.rb'
- 'ee/spec/features/projects/audit_events_spec.rb'
- 'ee/spec/features/projects/custom_projects_template_spec.rb'
- - 'ee/spec/features/projects/issues/user_creates_issue_spec.rb'
- - 'ee/spec/features/projects/iterations/iteration_cadences_list_spec.rb'
- - 'ee/spec/features/projects/iterations/iterations_list_spec.rb'
- 'ee/spec/features/projects/iterations/user_views_iteration_spec.rb'
- 'ee/spec/features/projects/jobs_spec.rb'
- 'ee/spec/features/projects/kerberos_clone_instructions_spec.rb'
- - 'ee/spec/features/projects/members/invite_group_and_members_spec.rb'
+ - 'ee/spec/features/projects/members/manage_groups_spec.rb'
- 'ee/spec/features/projects/members/member_leaves_project_spec.rb'
- 'ee/spec/features/projects/milestones/milestone_spec.rb'
- 'ee/spec/features/projects/new_project_from_template_spec.rb'
- 'ee/spec/features/projects/new_project_spec.rb'
+ - 'ee/spec/features/projects/pipelines/legacy_pipeline_spec.rb'
- 'ee/spec/features/projects/pipelines/pipeline_spec.rb'
- 'ee/spec/features/projects/push_rules_spec.rb'
- 'ee/spec/features/projects/quality/test_case_create_spec.rb'
@@ -206,25 +182,18 @@ RSpec/ContextWording:
- 'ee/spec/features/projects/settings/merge_requests_settings_spec.rb'
- 'ee/spec/features/projects/settings/protected_environments_spec.rb'
- 'ee/spec/features/projects/settings/push_rules_settings_spec.rb'
- - 'ee/spec/features/projects/settings/user_manages_members_spec.rb'
- - 'ee/spec/features/projects/show_project_spec.rb'
- 'ee/spec/features/promotion_spec.rb'
- 'ee/spec/features/protected_branches_spec.rb'
- 'ee/spec/features/registrations/saas_user_registration_spec.rb'
- 'ee/spec/features/registrations/welcome_spec.rb'
- 'ee/spec/features/search/elastic/global_search_spec.rb'
- - 'ee/spec/features/search/elastic/snippet_search_spec.rb'
- - 'ee/spec/features/security/project/snippet/internal_access_spec.rb'
- - 'ee/spec/features/security/project/snippet/public_access_spec.rb'
- 'ee/spec/features/signup_spec.rb'
- - 'ee/spec/features/subscriptions/expiring_subscription_message_spec.rb'
- 'ee/spec/features/trial_registrations/company_information_spec.rb'
- 'ee/spec/features/trials/select_namespace_spec.rb'
- 'ee/spec/features/users/login_spec.rb'
- 'ee/spec/features/users/signup_spec.rb'
+ - 'ee/spec/finders/approval_rules/group_finder_spec.rb'
- 'ee/spec/finders/audit_event_finder_spec.rb'
- - 'ee/spec/finders/autocomplete/vulnerabilities_autocomplete_finder_spec.rb'
- - 'ee/spec/finders/billed_users_finder_spec.rb'
- 'ee/spec/finders/clusters/environments_finder_spec.rb'
- 'ee/spec/finders/compliance_management/merge_requests/compliance_violations_finder_spec.rb'
- 'ee/spec/finders/custom_project_templates_finder_spec.rb'
@@ -234,6 +203,7 @@ RSpec/ContextWording:
- 'ee/spec/finders/dast_site_validations_finder_spec.rb'
- 'ee/spec/finders/ee/alert_management/http_integrations_finder_spec.rb'
- 'ee/spec/finders/ee/clusters/agent_authorizations_finder_spec.rb'
+ - 'ee/spec/finders/ee/clusters/agents_finder_spec.rb'
- 'ee/spec/finders/ee/group_members_finder_spec.rb'
- 'ee/spec/finders/ee/namespaces/projects_finder_spec.rb'
- 'ee/spec/finders/ee/projects_finder_spec.rb'
@@ -260,7 +230,6 @@ RSpec/ContextWording:
- 'ee/spec/finders/security/vulnerability_reads_finder_spec.rb'
- 'ee/spec/finders/snippets_finder_spec.rb'
- 'ee/spec/finders/software_license_policies_finder_spec.rb'
- - 'ee/spec/finders/status_page/incidents_finder_spec.rb'
- 'ee/spec/finders/template_finder_spec.rb'
- 'ee/spec/frontend/fixtures/dast_profiles.rb'
- 'ee/spec/frontend/fixtures/on_demand_dast_scans.rb'
@@ -269,11 +238,12 @@ RSpec/ContextWording:
- 'ee/spec/graphql/ee/resolvers/board_list_issues_resolver_spec.rb'
- 'ee/spec/graphql/ee/resolvers/namespace_projects_resolver_spec.rb'
- 'ee/spec/graphql/ee/types/projects/service_type_enum_spec.rb'
+ - 'ee/spec/graphql/mutations/audit_events/streaming/headers/create_spec.rb'
+ - 'ee/spec/graphql/mutations/audit_events/streaming/headers/destroy_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/create_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/destroy_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/update_spec.rb'
- - 'ee/spec/graphql/mutations/boards/epic_lists/update_spec.rb'
- 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
- 'ee/spec/graphql/mutations/compliance_management/frameworks/create_spec.rb'
- 'ee/spec/graphql/mutations/compliance_management/frameworks/destroy_spec.rb'
@@ -294,12 +264,11 @@ RSpec/ContextWording:
- 'ee/spec/graphql/mutations/security_policy/assign_security_policy_project_spec.rb'
- 'ee/spec/graphql/mutations/security_policy/commit_scan_execution_policy_spec.rb'
- 'ee/spec/graphql/mutations/security_policy/create_security_policy_project_spec.rb'
- - 'ee/spec/graphql/mutations/security_policy/unassign_security_policy_project_spec.rb'
- - 'ee/spec/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb'
- 'ee/spec/graphql/resolvers/admin/cloud_licenses/subscription_future_entries_resolver_spec.rb'
- - 'ee/spec/graphql/resolvers/analytics/devops_adoption/enabled_namespaces_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/boards/board_list_epics_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/clusters/agents_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver_spec.rb'
+ - 'ee/spec/graphql/resolvers/dora_metrics_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/epics_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/incident_management/oncall_schedule_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/instance_security_dashboard/projects_resolver_spec.rb'
@@ -308,7 +277,6 @@ RSpec/ContextWording:
- 'ee/spec/graphql/resolvers/path_locks_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/requirements_management/requirements_resolver_spec.rb'
- 'ee/spec/graphql/resolvers/security_report_summary_resolver_spec.rb'
- - 'ee/spec/graphql/resolvers/vulnerabilities_resolver_spec.rb'
- 'ee/spec/graphql/types/global_id_type_spec.rb'
- 'ee/spec/graphql/types/incident_management/escalation_rule_input_type_spec.rb'
- 'ee/spec/graphql/types/issue_type_spec.rb'
@@ -320,42 +288,32 @@ RSpec/ContextWording:
- 'ee/spec/helpers/application_helper_spec.rb'
- 'ee/spec/helpers/boards_helper_spec.rb'
- 'ee/spec/helpers/compliance_management/compliance_framework/group_settings_helper_spec.rb'
- - 'ee/spec/helpers/ee/application_settings_helper_spec.rb'
- 'ee/spec/helpers/ee/auth_helper_spec.rb'
- - 'ee/spec/helpers/ee/dashboard_helper_spec.rb'
- 'ee/spec/helpers/ee/environments_helper_spec.rb'
- - 'ee/spec/helpers/ee/events_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_helper_spec.rb'
- 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- 'ee/spec/helpers/ee/issuables_helper_spec.rb'
- 'ee/spec/helpers/ee/issues_helper_spec.rb'
- - 'ee/spec/helpers/ee/learn_gitlab_helper_spec.rb'
- 'ee/spec/helpers/ee/lock_helper_spec.rb'
- - 'ee/spec/helpers/ee/namespaces_helper_spec.rb'
- 'ee/spec/helpers/ee/operations_helper_spec.rb'
- 'ee/spec/helpers/ee/personal_access_tokens_helper_spec.rb'
- 'ee/spec/helpers/ee/projects/security/api_fuzzing_configuration_helper_spec.rb'
- - 'ee/spec/helpers/ee/security_orchestration_helper_spec.rb'
- - 'ee/spec/helpers/ee/system_note_helper_spec.rb'
- - 'ee/spec/helpers/ee/version_check_helper_spec.rb'
- 'ee/spec/helpers/ee/welcome_helper_spec.rb'
- 'ee/spec/helpers/groups/security_features_helper_spec.rb'
- 'ee/spec/helpers/license_helper_spec.rb'
- 'ee/spec/helpers/license_monitoring_helper_spec.rb'
- - 'ee/spec/helpers/notes_helper_spec.rb'
- 'ee/spec/helpers/paid_feature_callout_helper_spec.rb'
- 'ee/spec/helpers/projects/security/discover_helper_spec.rb'
- 'ee/spec/helpers/projects_helper_spec.rb'
- 'ee/spec/helpers/roadmaps_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'
- 'ee/spec/initializers/1_settings_spec.rb'
- - 'ee/spec/initializers/database_config_spec.rb'
- 'ee/spec/initializers/session_store_spec.rb'
- - 'ee/spec/lib/analytics/devops_adoption/snapshot_calculator_spec.rb'
- - 'ee/spec/lib/analytics/refresh_comments_data_spec.rb'
- 'ee/spec/lib/audit/details_spec.rb'
- 'ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb'
- 'ee/spec/lib/banzai/filter/references/epic_reference_filter_spec.rb'
@@ -370,10 +328,10 @@ RSpec/ContextWording:
- 'ee/spec/lib/ee/api/entities/user_with_admin_spec.rb'
- 'ee/spec/lib/ee/api/helpers/variables_helpers_spec.rb'
- 'ee/spec/lib/ee/api/helpers_spec.rb'
+ - 'ee/spec/lib/ee/backup/repositories_spec.rb'
- 'ee/spec/lib/ee/gitlab/alert_management/payload/generic_spec.rb'
- 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/groups_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/backfill_iteration_cadence_id_for_boards_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/fix_incorrect_max_seats_used_spec.rb'
@@ -382,9 +340,7 @@ RSpec/ContextWording:
- 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/config/entry/needs_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/matching/runner_matcher_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/size_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/templates/templates_spec.rb'
- 'ee/spec/lib/ee/gitlab/cleanup/orphan_job_artifact_files_batch_spec.rb'
@@ -395,7 +351,6 @@ RSpec/ContextWording:
- 'ee/spec/lib/ee/gitlab/gon_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/group_search_results_spec.rb'
- 'ee/spec/lib/ee/gitlab/hook_data/group_member_builder_spec.rb'
- - 'ee/spec/lib/ee/gitlab/hook_data/issue_builder_spec.rb'
- 'ee/spec/lib/ee/gitlab/hook_data/user_builder_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/group/legacy_tree_restorer_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/group/legacy_tree_saver_spec.rb'
@@ -403,24 +358,18 @@ RSpec/ContextWording:
- 'ee/spec/lib/ee/gitlab/import_export/group/tree_saver_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/project/tree_saver_spec.rb'
- 'ee/spec/lib/ee/gitlab/ip_restriction/enforcer_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/issuable/clone/copy_resource_events_service_spec.rb'
- 'ee/spec/lib/ee/gitlab/issuable_metadata_spec.rb'
- - 'ee/spec/lib/ee/gitlab/metrics/samplers/database_sampler_spec.rb'
- - 'ee/spec/lib/ee/gitlab/omniauth_initializer_spec.rb'
- - 'ee/spec/lib/ee/gitlab/prometheus/metric_group_spec.rb'
- 'ee/spec/lib/ee/gitlab/repo_path_spec.rb'
- 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
- 'ee/spec/lib/ee/gitlab/usage/service_ping/payload_keys_processor_spec.rb'
- - 'ee/spec/lib/ee/gitlab/usage/service_ping_report_spec.rb'
- - 'ee/spec/lib/ee/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb'
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
+ - 'ee/spec/lib/ee/service_ping/build_payload_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/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/request_params_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/lead_time_for_changes_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/lead_time_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/gma_membership_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/group_lookup_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
- 'ee/spec/lib/gitlab/auth/group_saml/token_actor_spec.rb'
@@ -432,18 +381,12 @@ RSpec/ContextWording:
- 'ee/spec/lib/gitlab/auth/smartcard/certificate_spec.rb'
- 'ee/spec/lib/gitlab/auth/smartcard/ldap_certificate_spec.rb'
- 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
- - 'ee/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb'
- - 'ee/spec/lib/gitlab/cache_spec.rb'
- 'ee/spec/lib/gitlab/checks/diff_check_spec.rb'
- 'ee/spec/lib/gitlab/ci/minutes/cost_factor_spec.rb'
- 'ee/spec/lib/gitlab/ci/minutes/runners_availability_spec.rb'
- 'ee/spec/lib/gitlab/ci/pipeline/chain/create_cross_database_associations_spec.rb'
- 'ee/spec/lib/gitlab/ci/reports/dependency_list/dependency_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Jobs/browser_performance_testing_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Verify/browser_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/api_security_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/api_security_latest_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb'
@@ -454,6 +397,7 @@ RSpec/ContextWording:
- 'ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/license_scanning_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb'
+ - 'ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/sast_iac_latest_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb'
@@ -487,53 +431,38 @@ RSpec/ContextWording:
- 'ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb'
- 'ee/spec/lib/gitlab/geo/replicator_spec.rb'
- 'ee/spec/lib/gitlab/geo/signed_data_spec.rb'
- - 'ee/spec/lib/gitlab/geo_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/git_access_wiki_spec.rb'
- 'ee/spec/lib/gitlab/gl_repository/identifier_spec.rb'
- 'ee/spec/lib/gitlab/gl_repository/repo_type_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/epic_node_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/security_orchestration_policies/lazy_dast_profile_aggregate_spec.rb'
- - '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/import_export/group/group_and_descendants_repo_restorer_spec.rb'
- - 'ee/spec/lib/gitlab/import_export/group/group_and_descendants_repo_saver_spec.rb'
- 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
- 'ee/spec/lib/gitlab/import_export/project/object_builder_spec.rb'
- 'ee/spec/lib/gitlab/insights/finders/issuable_finder_spec.rb'
- 'ee/spec/lib/gitlab/insights/project_insights_config_spec.rb'
- 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
- 'ee/spec/lib/gitlab/pagination_delegate_spec.rb'
- - 'ee/spec/lib/gitlab/patch/database_config_spec.rb'
- - 'ee/spec/lib/gitlab/reference_extractor_spec.rb'
- 'ee/spec/lib/gitlab/search/aggregation_parser_spec.rb'
- - 'ee/spec/lib/gitlab/sitemaps/generator_spec.rb'
- 'ee/spec/lib/gitlab/sitemaps/url_extractor_spec.rb'
- 'ee/spec/lib/gitlab/slash_commands/presenters/issue_show_spec.rb'
- 'ee/spec/lib/gitlab/status_page/filter/image_filter_spec.rb'
- 'ee/spec/lib/gitlab/status_page/storage/s3_client_spec.rb'
- - 'ee/spec/lib/gitlab/status_page/storage/s3_multipart_upload_spec.rb'
- 'ee/spec/lib/gitlab/tracking/snowplow_schema_validation_spec.rb'
- 'ee/spec/lib/gitlab/tracking/standard_context_spec.rb'
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/advanced_search/build_type_metric_spec.rb'
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/advanced_search/distribution_metric_spec.rb'
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/advanced_search/lucene_version_metric_spec.rb'
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/advanced_search/version_metric_spec.rb'
- - 'ee/spec/lib/gitlab/usage/metrics/instrumentations/approval_project_rules_with_user_metric_spec.rb'
- 'ee/spec/lib/gitlab/usage_data_counters/epic_activity_unique_counter_spec.rb'
- 'ee/spec/lib/incident_management/oncall_shift_generator_spec.rb'
- 'ee/spec/lib/omni_auth/strategies/group_saml_spec.rb'
- - 'ee/spec/lib/system_check/app/search_check_spec.rb'
- 'ee/spec/lib/system_check/geo/authorized_keys_check_spec.rb'
- 'ee/spec/lib/system_check/geo/http_connection_check_spec.rb'
- 'ee/spec/lib/system_check/rake_task/geo_task_spec.rb'
- 'ee/spec/mailers/ee/emails/issues_spec.rb'
- 'ee/spec/mailers/notify_spec.rb'
- 'ee/spec/migrations/schedule_requirements_migration_spec.rb'
- - 'ee/spec/migrations/schedule_trace_expiry_removal_spec.rb'
- 'ee/spec/models/alert_management/alert_payload_field_spec.rb'
- 'ee/spec/models/allowed_email_domain_spec.rb'
- 'ee/spec/models/analytics/cycle_analytics/group_stage_spec.rb'
@@ -542,21 +471,18 @@ RSpec/ContextWording:
- 'ee/spec/models/approval_merge_request_rule_spec.rb'
- 'ee/spec/models/approval_project_rule_spec.rb'
- 'ee/spec/models/approval_state_spec.rb'
+ - 'ee/spec/models/audit_events/external_audit_event_destination_spec.rb'
- 'ee/spec/models/board_spec.rb'
- 'ee/spec/models/boards/epic_board_position_spec.rb'
- - 'ee/spec/models/broadcast_message_spec.rb'
- 'ee/spec/models/ci/build_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/ci/pipeline_spec.rb'
- 'ee/spec/models/ci/sources/project_spec.rb'
- 'ee/spec/models/ci/subscriptions/project_spec.rb'
- - 'ee/spec/models/compliance_management/framework_spec.rb'
- 'ee/spec/models/concerns/approval_rule_like_spec.rb'
- 'ee/spec/models/concerns/approver_migrate_hook_spec.rb'
- 'ee/spec/models/concerns/deprecated_approvals_before_merge_spec.rb'
- 'ee/spec/models/concerns/ee/issuable_spec.rb'
- - 'ee/spec/models/concerns/ee/milestoneable_spec.rb'
- 'ee/spec/models/concerns/ee/participable_spec.rb'
- 'ee/spec/models/concerns/elastic/issue_spec.rb'
- 'ee/spec/models/concerns/elastic/note_spec.rb'
@@ -571,38 +497,27 @@ RSpec/ContextWording:
- 'ee/spec/models/dast_site_profile_spec.rb'
- 'ee/spec/models/dast_site_validation_spec.rb'
- 'ee/spec/models/deployment_spec.rb'
- - 'ee/spec/models/dora/change_failure_rate_metric_spec.rb'
- - 'ee/spec/models/dora/time_to_restore_service_metric_spec.rb'
- 'ee/spec/models/ee/audit_event_spec.rb'
- 'ee/spec/models/ee/award_emoji_spec.rb'
- - 'ee/spec/models/ee/ci/build_dependencies_spec.rb'
- 'ee/spec/models/ee/ci/job_artifact_spec.rb'
- - 'ee/spec/models/ee/ci/runner_spec.rb'
+ - 'ee/spec/models/ee/event_collection_spec.rb'
- 'ee/spec/models/ee/event_spec.rb'
+ - 'ee/spec/models/ee/group_group_link_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'
- 'ee/spec/models/ee/iteration_spec.rb'
- 'ee/spec/models/ee/iterations/cadence_spec.rb'
- - 'ee/spec/models/ee/key_spec.rb'
- - 'ee/spec/models/ee/merge_request_diff_spec.rb'
- - 'ee/spec/models/ee/namespace/root_storage_size_spec.rb'
- 'ee/spec/models/ee/namespace_ci_cd_setting_spec.rb'
- - 'ee/spec/models/ee/namespace_limit_spec.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/ee/notification_setting_spec.rb'
- 'ee/spec/models/ee/personal_access_token_spec.rb'
- 'ee/spec/models/ee/project_group_link_spec.rb'
- 'ee/spec/models/ee/protected_branch_spec.rb'
- - 'ee/spec/models/ee/protected_ref_spec.rb'
- - 'ee/spec/models/ee/service_desk_setting_spec.rb'
- 'ee/spec/models/ee/user_spec.rb'
- - 'ee/spec/models/environment_spec.rb'
- 'ee/spec/models/epic_issue_spec.rb'
- 'ee/spec/models/epic_spec.rb'
- 'ee/spec/models/geo/container_repository_registry_spec.rb'
- 'ee/spec/models/geo/design_registry_spec.rb'
- - 'ee/spec/models/geo/job_artifact_registry_spec.rb'
- 'ee/spec/models/geo/project_registry_spec.rb'
- 'ee/spec/models/geo/secondary_usage_data_spec.rb'
- 'ee/spec/models/geo_node_spec.rb'
@@ -611,13 +526,10 @@ RSpec/ContextWording:
- 'ee/spec/models/gitlab_subscriptions/features_spec.rb'
- 'ee/spec/models/group_member_spec.rb'
- 'ee/spec/models/group_wiki_repository_spec.rb'
- - 'ee/spec/models/group_wiki_spec.rb'
- 'ee/spec/models/incident_management/escalation_rule_spec.rb'
- 'ee/spec/models/incident_management/oncall_rotation_spec.rb'
- - 'ee/spec/models/incident_management/oncall_shift_spec.rb'
- 'ee/spec/models/incident_management/pending_escalations/alert_spec.rb'
- 'ee/spec/models/incident_management/pending_escalations/issue_spec.rb'
- - 'ee/spec/models/integrations/github/remote_project_spec.rb'
- 'ee/spec/models/integrations/github_spec.rb'
- 'ee/spec/models/ip_restriction_spec.rb'
- 'ee/spec/models/issuable_metric_image_spec.rb'
@@ -633,7 +545,6 @@ RSpec/ContextWording:
- 'ee/spec/models/note_spec.rb'
- 'ee/spec/models/packages/package_file_spec.rb'
- 'ee/spec/models/path_lock_spec.rb'
- - 'ee/spec/models/productivity_analytics_spec.rb'
- 'ee/spec/models/project_import_data_spec.rb'
- 'ee/spec/models/project_import_state_spec.rb'
- 'ee/spec/models/project_member_spec.rb'
@@ -643,19 +554,13 @@ RSpec/ContextWording:
- 'ee/spec/models/protected_environments/approval_summary_spec.rb'
- 'ee/spec/models/push_rule_spec.rb'
- 'ee/spec/models/release_highlight_spec.rb'
- - 'ee/spec/models/remote_mirror_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/saml_group_link_spec.rb'
- 'ee/spec/models/saml_provider_spec.rb'
- 'ee/spec/models/status_page/project_setting_spec.rb'
- - 'ee/spec/models/uploads/local_spec.rb'
- - 'ee/spec/models/vulnerabilities/export_spec.rb'
- 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- 'ee/spec/models/vulnerabilities/finding_pipeline_spec.rb'
- 'ee/spec/models/vulnerabilities/finding_spec.rb'
- - 'ee/spec/models/vulnerabilities/read_spec.rb'
- 'ee/spec/models/vulnerabilities/statistic_spec.rb'
- 'ee/spec/policies/app_sec/fuzzing/coverage/corpus_policy_spec.rb'
- 'ee/spec/policies/compliance_management/framework_policy_spec.rb'
@@ -669,12 +574,10 @@ RSpec/ContextWording:
- 'ee/spec/policies/incident_management/oncall_shift_policy_spec.rb'
- 'ee/spec/policies/issuable_policy_spec.rb'
- 'ee/spec/policies/merge_request_policy_spec.rb'
- - 'ee/spec/policies/note_policy_spec.rb'
- 'ee/spec/policies/project_policy_spec.rb'
- 'ee/spec/policies/project_snippet_policy_spec.rb'
- 'ee/spec/policies/protected_branch_policy_spec.rb'
- 'ee/spec/policies/saml_provider_policy_spec.rb'
- - 'ee/spec/policies/user_policy_spec.rb'
- 'ee/spec/presenters/approval_rule_presenter_spec.rb'
- 'ee/spec/presenters/audit_event_presenter_spec.rb'
- 'ee/spec/presenters/ci/build_runner_presenter_spec.rb'
@@ -686,18 +589,16 @@ RSpec/ContextWording:
- 'ee/spec/requests/admin/geo/replicables_controller_spec.rb'
- 'ee/spec/requests/api/analytics/group_activity_analytics_spec.rb'
- 'ee/spec/requests/api/audit_events_spec.rb'
- - 'ee/spec/requests/api/award_emoji_spec.rb'
- 'ee/spec/requests/api/boards_spec.rb'
- 'ee/spec/requests/api/ci/jobs_spec.rb'
- 'ee/spec/requests/api/ci/pipelines_spec.rb'
- 'ee/spec/requests/api/ci/runner_spec.rb'
- - 'ee/spec/requests/api/ci/triggers_spec.rb'
- 'ee/spec/requests/api/commits_spec.rb'
- 'ee/spec/requests/api/deployments_spec.rb'
+ - 'ee/spec/requests/api/dora/metrics_spec.rb'
- 'ee/spec/requests/api/epic_issues_spec.rb'
- 'ee/spec/requests/api/epic_links_spec.rb'
- 'ee/spec/requests/api/epics_spec.rb'
- - 'ee/spec/requests/api/experiments_spec.rb'
- 'ee/spec/requests/api/geo_nodes_spec.rb'
- 'ee/spec/requests/api/geo_spec.rb'
- 'ee/spec/requests/api/graphql/boards/epic_boards_query_spec.rb'
@@ -720,15 +621,14 @@ RSpec/ContextWording:
- '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/epics/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/epics/update_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/incident_management/escalation_policy/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/incident_management/issuable_resource_link/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/create_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/update_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/issues/update_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/security_policy/assign_security_policy_project_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/security_policy/commit_scan_execution_policy_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/vulnerabilities/create_external_issue_link_spec.rb'
- 'ee/spec/requests/api/graphql/project/code_coverage_summary_spec.rb'
- 'ee/spec/requests/api/graphql/project/incident_management/escalation_policies_spec.rb'
- 'ee/spec/requests/api/graphql/project/incident_management/oncall_participants_spec.rb'
@@ -739,7 +639,6 @@ RSpec/ContextWording:
- 'ee/spec/requests/api/graphql/projects/compliance_frameworks_spec.rb'
- 'ee/spec/requests/api/graphql/vulnerabilities/sort_spec.rb'
- 'ee/spec/requests/api/group_clusters_spec.rb'
- - 'ee/spec/requests/api/group_hooks_spec.rb'
- 'ee/spec/requests/api/group_push_rule_spec.rb'
- 'ee/spec/requests/api/group_variables_spec.rb'
- 'ee/spec/requests/api/groups_spec.rb'
@@ -753,7 +652,6 @@ RSpec/ContextWording:
- 'ee/spec/requests/api/members_spec.rb'
- 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
- 'ee/spec/requests/api/merge_request_approval_settings_spec.rb'
- - 'ee/spec/requests/api/merge_request_approvals_spec.rb'
- 'ee/spec/requests/api/merge_requests_spec.rb'
- 'ee/spec/requests/api/namespaces_spec.rb'
- 'ee/spec/requests/api/project_aliases_spec.rb'
@@ -773,19 +671,13 @@ RSpec/ContextWording:
- 'ee/spec/requests/api/status_checks_spec.rb'
- 'ee/spec/requests/api/users_spec.rb'
- 'ee/spec/requests/api/v3/github_spec.rb'
- - 'ee/spec/requests/api/visual_review_discussions_spec.rb'
- - 'ee/spec/requests/api/vulnerabilities_spec.rb'
- - 'ee/spec/requests/api/vulnerability_exports_spec.rb'
- 'ee/spec/requests/api/vulnerability_findings_spec.rb'
- 'ee/spec/requests/git_http_geo_spec.rb'
- - 'ee/spec/requests/groups/group_members_controller_spec.rb'
- 'ee/spec/requests/groups/roadmap_controller_spec.rb'
- 'ee/spec/requests/groups/security/credentials_controller_spec.rb'
- - 'ee/spec/requests/groups/usage_quotas_spec.rb'
+ - 'ee/spec/requests/groups/settings/reporting_controller_spec.rb'
- 'ee/spec/requests/groups_controller_spec.rb'
- 'ee/spec/requests/jwt_controller_spec.rb'
- - 'ee/spec/requests/lfs_http_spec.rb'
- - 'ee/spec/requests/projects/analytics/code_reviews_controller_spec.rb'
- 'ee/spec/requests/projects/on_demand_scans_controller_spec.rb'
- 'ee/spec/requests/projects/requirements_management/requirements_controller_spec.rb'
- 'ee/spec/requests/projects/security/corpus_management_controller_spec.rb'
@@ -796,7 +688,6 @@ RSpec/ContextWording:
- 'ee/spec/requests/projects/security/scanned_resources_controller_spec.rb'
- 'ee/spec/requests/rack_attack_spec.rb'
- 'ee/spec/requests/repositories/git_http_controller_spec.rb'
- - 'ee/spec/requests/search_controller_spec.rb'
- 'ee/spec/requests/smartcard_controller_spec.rb'
- 'ee/spec/routing/user_routing_spec.rb'
- 'ee/spec/serializers/analytics/cycle_analytics/value_stream_errors_serializer_spec.rb'
@@ -804,25 +695,19 @@ RSpec/ContextWording:
- 'ee/spec/serializers/board_serializer_spec.rb'
- 'ee/spec/serializers/clusters/environment_entity_spec.rb'
- 'ee/spec/serializers/dashboard_operations_project_entity_spec.rb'
- - 'ee/spec/serializers/ee/blob_entity_spec.rb'
- 'ee/spec/serializers/ee/group_child_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/user_serializer_spec.rb'
- 'ee/spec/serializers/environment_entity_spec.rb'
- - 'ee/spec/serializers/epic_note_entity_spec.rb'
- 'ee/spec/serializers/issue_serializer_spec.rb'
- 'ee/spec/serializers/member_entity_spec.rb'
- 'ee/spec/serializers/member_user_entity_spec.rb'
- 'ee/spec/serializers/merge_request_widget_entity_spec.rb'
- 'ee/spec/serializers/project_mirror_entity_spec.rb'
- 'ee/spec/serializers/vulnerabilities/finding_entity_spec.rb'
- - 'ee/spec/services/alert_management/process_prometheus_alert_service_spec.rb'
- - 'ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/stages/delete_service_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/value_streams/update_service_spec.rb'
- - 'ee/spec/services/analytics/devops_adoption/enabled_namespaces/create_service_spec.rb'
- 'ee/spec/services/app_sec/dast/builds/associate_service_spec.rb'
- 'ee/spec/services/app_sec/dast/profiles/create_associations_service_spec.rb'
- 'ee/spec/services/application_settings/update_service_spec.rb'
@@ -833,29 +718,20 @@ RSpec/ContextWording:
- 'ee/spec/services/approval_rules/update_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
- 'ee/spec/services/audit_events/export_csv_service_spec.rb'
- - 'ee/spec/services/audit_events/register_runner_audit_event_service_spec.rb'
- - 'ee/spec/services/audit_events/runners_token_audit_event_service_spec.rb'
- - 'ee/spec/services/audit_events/unregister_runner_audit_event_service_spec.rb'
- - 'ee/spec/services/award_emojis/add_service_spec.rb'
- 'ee/spec/services/boards/create_service_spec.rb'
- 'ee/spec/services/boards/epic_boards/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/boards/lists/update_service_spec.rb'
- 'ee/spec/services/ci/copy_cross_database_associations_service_spec.rb'
- 'ee/spec/services/ci/create_pipeline_service_spec.rb'
- - 'ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb'
- 'ee/spec/services/ci/minutes/update_project_and_namespace_usage_service_spec.rb'
- - 'ee/spec/services/ci/process_build_service_spec.rb'
+ - 'ee/spec/services/ci/pipeline_trigger_service_spec.rb'
- 'ee/spec/services/ci/register_job_service_spec.rb'
- 'ee/spec/services/ci/retry_job_service_spec.rb'
- - 'ee/spec/services/ci/runners/unregister_runner_service_spec.rb'
- 'ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb'
- 'ee/spec/services/ci_cd/setup_project_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/compliance_management/merge_requests/create_compliance_violations_service_spec.rb'
- - 'ee/spec/services/dashboard/projects/list_service_spec.rb'
- 'ee/spec/services/deployments/approval_service_spec.rb'
- 'ee/spec/services/dora/aggregate_metrics_service_spec.rb'
- 'ee/spec/services/ee/alert_management/alerts/update_service_spec.rb'
@@ -871,16 +747,16 @@ RSpec/ContextWording:
- 'ee/spec/services/ee/integrations/test/project_service_spec.rb'
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
- 'ee/spec/services/ee/issuable/bulk_update_service_spec.rb'
- - 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
- 'ee/spec/services/ee/issues/clone_service_spec.rb'
- 'ee/spec/services/ee/issues/close_service_spec.rb'
- 'ee/spec/services/ee/issues/create_service_spec.rb'
- 'ee/spec/services/ee/issues/move_service_spec.rb'
- 'ee/spec/services/ee/issues/reopen_service_spec.rb'
- 'ee/spec/services/ee/issues/update_service_spec.rb'
- - 'ee/spec/services/ee/labels/create_service_spec.rb'
+ - 'ee/spec/services/ee/keys/destroy_service_spec.rb'
- 'ee/spec/services/ee/members/create_service_spec.rb'
- 'ee/spec/services/ee/members/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/members/import_project_team_service_spec.rb'
- 'ee/spec/services/ee/members/invite_service_spec.rb'
- 'ee/spec/services/ee/merge_requests/base_service_spec.rb'
- 'ee/spec/services/ee/merge_requests/create_service_spec.rb'
@@ -888,16 +764,13 @@ RSpec/ContextWording:
- 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
- 'ee/spec/services/ee/merge_requests/update_assignees_service_spec.rb'
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- - 'ee/spec/services/ee/namespace_settings/update_service_spec.rb'
- 'ee/spec/services/ee/notes/create_service_spec.rb'
- 'ee/spec/services/ee/notes/post_process_service_spec.rb'
- 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
- - 'ee/spec/services/ee/notes/update_service_spec.rb'
- 'ee/spec/services/ee/notification_service_spec.rb'
- 'ee/spec/services/ee/personal_access_tokens/revoke_service_spec.rb'
- 'ee/spec/services/ee/preview_markdown_service_spec.rb'
- 'ee/spec/services/ee/protected_branches/create_service_spec.rb'
- - 'ee/spec/services/ee/quick_actions/target_service_spec.rb'
- 'ee/spec/services/ee/resource_events/merge_into_notes_service_spec.rb'
- 'ee/spec/services/ee/users/build_service_spec.rb'
- 'ee/spec/services/ee/users/create_service_spec.rb'
@@ -915,7 +788,6 @@ RSpec/ContextWording:
- 'ee/spec/services/epic_issues/update_service_spec.rb'
- 'ee/spec/services/epics/create_service_spec.rb'
- 'ee/spec/services/epics/epic_links/list_service_spec.rb'
- - 'ee/spec/services/epics/issue_promote_service_spec.rb'
- 'ee/spec/services/epics/related_epic_links/create_service_spec.rb'
- 'ee/spec/services/epics/related_epic_links/destroy_service_spec.rb'
- 'ee/spec/services/epics/update_dates_service_spec.rb'
@@ -936,13 +808,13 @@ RSpec/ContextWording:
- 'ee/spec/services/geo/repository_created_event_store_spec.rb'
- 'ee/spec/services/geo/repository_sync_service_spec.rb'
- 'ee/spec/services/geo/repository_verification_reset_spec.rb'
- - 'ee/spec/services/geo/repository_verification_secondary_service_spec.rb'
- 'ee/spec/services/geo/wiki_sync_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/activate_awaiting_users_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/apply_trial_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/create_hand_raise_lead_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/create_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/extend_reactivate_trial_service_spec.rb'
- - 'ee/spec/services/group_saml/group_managed_accounts/clean_up_members_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/preview_billable_user_change_service_spec.rb'
- 'ee/spec/services/group_saml/group_managed_accounts/transfer_membership_service_spec.rb'
- 'ee/spec/services/groups/create_service_spec.rb'
- 'ee/spec/services/groups/destroy_service_spec.rb'
@@ -975,10 +847,9 @@ RSpec/ContextWording:
- 'ee/spec/services/merge_requests/approval_service_spec.rb'
- 'ee/spec/services/merge_requests/build_service_spec.rb'
- 'ee/spec/services/merge_requests/merge_service_spec.rb'
+ - 'ee/spec/services/merge_requests/reload_merge_head_diff_service_spec.rb'
- 'ee/spec/services/merge_requests/update_blocks_service_spec.rb'
- 'ee/spec/services/milestones/update_service_spec.rb'
- - 'ee/spec/services/namespaces/in_product_marketing_emails_service_spec.rb'
- - 'ee/spec/services/namespaces/storage/email_notification_service_spec.rb'
- 'ee/spec/services/personal_access_tokens/revoke_invalid_tokens_spec.rb'
- 'ee/spec/services/personal_access_tokens/rotation_verifier_service_spec.rb'
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
@@ -988,7 +859,7 @@ RSpec/ContextWording:
- 'ee/spec/services/projects/gitlab_projects_import_service_spec.rb'
- 'ee/spec/services/projects/group_links/create_service_spec.rb'
- 'ee/spec/services/projects/group_links/destroy_service_spec.rb'
- - 'ee/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb'
+ - 'ee/spec/services/projects/group_links/update_service_spec.rb'
- 'ee/spec/services/projects/import_export/export_service_spec.rb'
- 'ee/spec/services/projects/mark_for_deletion_service_spec.rb'
- 'ee/spec/services/projects/operations/update_service_spec.rb'
@@ -1011,13 +882,12 @@ RSpec/ContextWording:
- 'ee/spec/services/search/snippet_service_spec.rb'
- 'ee/spec/services/search_service_spec.rb'
- 'ee/spec/services/security/dependency_list_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities/create_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/update_vulnerability_uuids_spec.rb'
- 'ee/spec/services/security/merge_reports_service_spec.rb'
- - 'ee/spec/services/security/orchestration/assign_service_spec.rb'
- - 'ee/spec/services/security/orchestration/unassign_service_spec.rb'
- 'ee/spec/services/security/report_summary_service_spec.rb'
- 'ee/spec/services/security/scanned_resources_counting_service_spec.rb'
- 'ee/spec/services/security/scanned_resources_service_spec.rb'
- - 'ee/spec/services/security/security_orchestration_policies/create_pipeline_service_spec.rb'
- 'ee/spec/services/security/security_orchestration_policies/policy_commit_service_spec.rb'
- 'ee/spec/services/security/security_orchestration_policies/process_policy_service_spec.rb'
- 'ee/spec/services/security/store_grouped_scans_service_spec.rb'
@@ -1027,16 +897,12 @@ RSpec/ContextWording:
- 'ee/spec/services/software_license_policies/update_service_spec.rb'
- 'ee/spec/services/status_page/publish_attachments_service_spec.rb'
- 'ee/spec/services/status_page/publish_details_service_spec.rb'
- - 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
- 'ee/spec/services/system_notes/epics_service_spec.rb'
- 'ee/spec/services/timebox_report_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
- 'ee/spec/services/upcoming_reconciliations/update_service_spec.rb'
- 'ee/spec/services/user_permissions/export_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/create_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/historical_statistics/deletion_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/support/features/manual_quarterly_co_term_banner_examples.rb'
- 'ee/spec/support/protected_tags/access_control_shared_examples.rb'
- 'ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb'
@@ -1046,25 +912,22 @@ RSpec/ContextWording:
- 'ee/spec/support/shared_contexts/gitlab_team_member_shared_context.rb'
- 'ee/spec/support/shared_contexts/graphql/resolvers/security_orchestration/resolves_orchestration_policy_shared_contexts.rb'
- 'ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb'
+ - 'ee/spec/support/shared_contexts/lib/gitlab/insights/serializers/serializers_shared_context.rb'
- 'ee/spec/support/shared_contexts/push_rules_checks_shared_context.rb'
- 'ee/spec/support/shared_contexts/requests/api/members_shared_contexts.rb'
- 'ee/spec/support/shared_contexts/status_page/status_page_enabled_context.rb'
- 'ee/spec/support/shared_contexts/status_page/status_page_list_objects.rb'
- 'ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/shared_stage_shared_examples.rb'
- - 'ee/spec/support/shared_examples/controllers/analytics/issues_analytics/shared_issues_analytics_examples.rb'
- 'ee/spec/support/shared_examples/controllers/boards_actions_shared_examples.rb'
- 'ee/spec/support/shared_examples/controllers/cluster_metrics_shared_examples.rb'
- 'ee/spec/support/shared_examples/controllers/concerns/description_diff_actions_shared_examples.rb'
- 'ee/spec/support/shared_examples/controllers/registrations/groups_controller_shared_examples.rb'
- 'ee/spec/support/shared_examples/controllers/registrations/projects_controller_shared_examples.rb'
- - 'ee/spec/support/shared_examples/controllers/security/application_controller_shared_examples.rb'
- - 'ee/spec/support/shared_examples/features/credentials_inventory_shared_examples.rb'
- 'ee/spec/support/shared_examples/features/insights_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/features/password_complexity_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/features/ultimate_trial_callout_shared_examples.rb'
- 'ee/spec/support/shared_examples/graphql/mutations/epics/permission_check_shared_examples.rb'
- - 'ee/spec/support/shared_examples/graphql/mutations/update_health_status_shared_examples.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/git_access_shared_examples.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/middleware/allowlisted_admin_geo_requests_shared_examples.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/middleware/maintenance_mode_gitlab_ee_instance_shared_examples.rb'
@@ -1076,18 +939,13 @@ RSpec/ContextWording:
- 'ee/spec/support/shared_examples/models/concerns/replicator_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_batcher_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/geo_framework_registry_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/geo_verifiable_registry_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/member_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/mentionable_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/protected_environments/authorizable_examples.rb'
- 'ee/spec/support/shared_examples/quick_actions/issue/status_page_quick_actions_shared_examples.rb'
- - 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb'
- 'ee/spec/support/shared_examples/requests/credentials_inventory_shared_examples.rb'
- - 'ee/spec/support/shared_examples/requests/security/security_dashboard_json_endpoint_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/merge_merge_requests_shared_examples.rb'
@@ -1095,66 +953,56 @@ RSpec/ContextWording:
- 'ee/spec/support/shared_examples/services/search_notes_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/search_service_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/update_issuable_health_status_shared_examples.rb'
- - 'ee/spec/support/shared_examples/views/registration_features_prompt_settings_link_shared_examples.rb'
- 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
- 'ee/spec/tasks/gitlab/license_rake_spec.rb'
- - 'ee/spec/tasks/gitlab/uploads/migrate_rake_spec.rb'
- 'ee/spec/views/admin/application_settings/_elasticsearch_form.html.haml_spec.rb'
- 'ee/spec/views/admin/users/show.html.haml_spec.rb'
- 'ee/spec/views/compliance_management/compliance_framework/_project_settings.html.haml_spec.rb'
- 'ee/spec/views/groups/edit.html.haml_spec.rb'
- 'ee/spec/views/groups/security/discover/show.html.haml_spec.rb'
- 'ee/spec/views/layouts/header/_new_dropdown.haml_spec.rb'
+ - 'ee/spec/views/layouts/header/_read_only_banner.html.haml_spec.rb'
- 'ee/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb'
- 'ee/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb'
- 'ee/spec/views/layouts/nav/sidebar/_push_rules_link.html.haml_spec.rb'
- 'ee/spec/views/profiles/preferences/show.html.haml_spec.rb'
- 'ee/spec/views/projects/edit.html.haml_spec.rb'
- - 'ee/spec/views/projects/issues/show.html.haml_spec.rb'
- 'ee/spec/views/projects/security/discover/show.html.haml_spec.rb'
- 'ee/spec/views/registrations/groups/new.html.haml_spec.rb'
- - 'ee/spec/views/registrations/projects/new.html.haml_spec.rb'
- 'ee/spec/views/registrations/welcome/show.html.haml_spec.rb'
- 'ee/spec/views/search/_category.html.haml_spec.rb'
- 'ee/spec/views/shared/_clone_panel.html.haml_spec.rb'
- 'ee/spec/views/shared/_kerberos_clone_button.html.haml_spec.rb'
- 'ee/spec/views/shared/_mirror_update_button.html.haml_spec.rb'
- - 'ee/spec/views/shared/credentials_inventory/_expiry_date.html.haml_spec.rb'
- 'ee/spec/views/shared/credentials_inventory/gpg_keys/_gpg_key.html.haml_spec.rb'
- '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/credentials_inventory/ssh_keys/_ssh_key.html.haml_spec.rb'
- 'ee/spec/views/shared/issuable/_sidebar.html.haml_spec.rb'
- - 'ee/spec/views/shared/labels/_create_label_help_text.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/workers/active_user_count_threshold_worker_spec.rb'
- 'ee/spec/workers/adjourned_projects_deletion_cron_worker_spec.rb'
- 'ee/spec/workers/admin_emails_worker_spec.rb'
- - 'ee/spec/workers/analytics/code_review_metrics_worker_spec.rb'
- 'ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb'
- 'ee/spec/workers/ci/minutes/refresh_cached_data_worker_spec.rb'
- 'ee/spec/workers/ci/minutes/update_project_and_namespace_usage_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/compliance_management/merge_requests/compliance_violations_worker_spec.rb'
- 'ee/spec/workers/ee/repository_check/batch_worker_spec.rb'
- 'ee/spec/workers/ee/repository_check/single_repository_worker_spec.rb'
- 'ee/spec/workers/elastic/migration_worker_spec.rb'
- 'ee/spec/workers/elastic_association_indexer_worker_spec.rb'
- 'ee/spec/workers/elastic_index_bulk_cron_worker_spec.rb'
- 'ee/spec/workers/elastic_indexing_control_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/repository_shard_sync_worker_spec.rb'
- 'ee/spec/workers/geo/repository_sync_worker_spec.rb'
- 'ee/spec/workers/geo/repository_verification/primary/shard_worker_spec.rb'
- 'ee/spec/workers/geo/repository_verification/secondary/shard_worker_spec.rb'
- 'ee/spec/workers/geo/verification_timeout_worker_spec.rb'
+ - 'ee/spec/workers/group_saml_group_sync_worker_spec.rb'
- 'ee/spec/workers/incident_management/apply_incident_sla_exceeded_label_worker_spec.rb'
- 'ee/spec/workers/incident_management/oncall_rotations/persist_shifts_job_spec.rb'
- - 'ee/spec/workers/iterations/cadences/schedule_create_iterations_worker_spec.rb'
- - 'ee/spec/workers/iterations_update_status_worker_spec.rb'
- 'ee/spec/workers/merge_request_reset_approvals_worker_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/personal_access_tokens/groups/policy_worker_spec.rb'
@@ -1163,12 +1011,8 @@ RSpec/ContextWording:
- 'ee/spec/workers/project_import_schedule_worker_spec.rb'
- 'ee/spec/workers/requirements_management/process_requirements_reports_worker_spec.rb'
- 'ee/spec/workers/security/track_secure_scans_worker_spec.rb'
- - 'ee/spec/workers/store_security_reports_worker_spec.rb'
- - 'ee/spec/workers/sync_seat_link_request_worker_spec.rb'
- 'ee/spec/workers/sync_seat_link_worker_spec.rb'
- - 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
- 'ee/spec/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker_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/3_create/gitaly/automatic_failover_and_recovery_spec.rb'
- 'qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb'
@@ -1179,19 +1023,16 @@ RSpec/ContextWording:
- '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/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb'
- - 'qa/qa/specs/features/browser_ui/1_manage/project/create_project_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/user/user_access_termination_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_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/archive_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/merge_request/suggestions/batch_suggestion_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/3_create/web_ide/server_hooks_custom_error_message_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb'
@@ -1200,11 +1041,13 @@ RSpec/ContextWording:
- 'qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_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/pypi_repository_spec.rb'
- 'qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_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'
+ - 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/free_tier_group_namespace_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/purchase_ci_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/purchase_storage_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/12_geo/http_push_spec.rb'
@@ -1215,18 +1058,14 @@ RSpec/ContextWording:
- 'qa/qa/specs/features/ee/browser_ui/12_geo/wiki_ssh_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/13_secure/license_compliance_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/13_secure/security_reports_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_2_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_ldap_sync_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/insights/default_insights_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/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/2_plan/epic/epics_management_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/issue_boards/project_issue_boards_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_root_group_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/merge_with_code_owner_in_subgroup_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/wiki/create_group_wiki_page_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/4_verify/new_discussion_not_dropping_merge_trains_mr_spec.rb'
@@ -1235,7 +1074,6 @@ RSpec/ContextWording:
- 'qa/spec/service/docker_run/gitlab_runner_spec.rb'
- 'qa/spec/service/docker_run/k3s_spec.rb'
- 'qa/spec/specs/helpers/context_selector_spec.rb'
- - 'qa/spec/specs/helpers/feature_flag_spec.rb'
- 'qa/spec/specs/helpers/quarantine_spec.rb'
- 'qa/spec/specs/runner_spec.rb'
- 'qa/spec/support/loglinking_spec.rb'
@@ -1245,29 +1083,26 @@ RSpec/ContextWording:
- 'spec/commands/sidekiq_cluster/cli_spec.rb'
- 'spec/components/diffs/overflow_warning_component_spec.rb'
- 'spec/components/pajamas/alert_component_spec.rb'
+ - 'spec/components/pajamas/banner_component_spec.rb'
+ - 'spec/components/pajamas/button_component_spec.rb'
+ - 'spec/components/pajamas/card_component_spec.rb'
+ - 'spec/components/pajamas/spinner_component_spec.rb'
- 'spec/config/object_store_settings_spec.rb'
- 'spec/controllers/admin/application_settings_controller_spec.rb'
- - 'spec/controllers/admin/clusters_controller_spec.rb'
- - 'spec/controllers/admin/dev_ops_report_controller_spec.rb'
- - 'spec/controllers/admin/impersonations_controller_spec.rb'
- 'spec/controllers/admin/instance_review_controller_spec.rb'
- 'spec/controllers/admin/integrations_controller_spec.rb'
- 'spec/controllers/admin/runner_projects_controller_spec.rb'
- 'spec/controllers/admin/sessions_controller_spec.rb'
- - 'spec/controllers/admin/topics_controller_spec.rb'
- 'spec/controllers/admin/users_controller_spec.rb'
- 'spec/controllers/application_controller_spec.rb'
- 'spec/controllers/autocomplete_controller_spec.rb'
- - 'spec/controllers/boards/issues_controller_spec.rb'
- 'spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb'
- 'spec/controllers/concerns/enforces_admin_authentication_spec.rb'
- - 'spec/controllers/concerns/graceful_timeout_handling_spec.rb'
- 'spec/controllers/concerns/group_tree_spec.rb'
- 'spec/controllers/concerns/import_url_params_spec.rb'
- 'spec/controllers/concerns/issuable_collections_spec.rb'
- 'spec/controllers/concerns/metrics_dashboard_spec.rb'
- 'spec/controllers/concerns/renders_commits_spec.rb'
- - 'spec/controllers/concerns/send_file_upload_spec.rb'
- 'spec/controllers/confirmations_controller_spec.rb'
- 'spec/controllers/dashboard/milestones_controller_spec.rb'
- 'spec/controllers/dashboard/projects_controller_spec.rb'
@@ -1290,7 +1125,6 @@ RSpec/ContextWording:
- 'spec/controllers/groups/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/groups/settings/integrations_controller_spec.rb'
- 'spec/controllers/groups/settings/repository_controller_spec.rb'
- - 'spec/controllers/groups/uploads_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/help_controller_spec.rb'
- 'spec/controllers/import/bitbucket_controller_spec.rb'
@@ -1308,8 +1142,7 @@ RSpec/ContextWording:
- 'spec/controllers/passwords_controller_spec.rb'
- 'spec/controllers/profiles/emails_controller_spec.rb'
- 'spec/controllers/profiles/notifications_controller_spec.rb'
- - 'spec/controllers/profiles/preferences_controller_spec.rb'
- - 'spec/controllers/profiles/two_factor_auths_controller_spec.rb'
+ - 'spec/controllers/profiles/personal_access_tokens_controller_spec.rb'
- 'spec/controllers/projects/alerting/notifications_controller_spec.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/controllers/projects/badges_controller_spec.rb'
@@ -1328,11 +1161,9 @@ RSpec/ContextWording:
- 'spec/controllers/projects/discussions_controller_spec.rb'
- 'spec/controllers/projects/environments_controller_spec.rb'
- 'spec/controllers/projects/feature_flags_clients_controller_spec.rb'
- - 'spec/controllers/projects/feature_flags_controller_spec.rb'
- 'spec/controllers/projects/find_file_controller_spec.rb'
- 'spec/controllers/projects/forks_controller_spec.rb'
- 'spec/controllers/projects/import/jira_controller_spec.rb'
- - 'spec/controllers/projects/incidents_controller_spec.rb'
- 'spec/controllers/projects/issues_controller_spec.rb'
- 'spec/controllers/projects/jobs_controller_spec.rb'
- 'spec/controllers/projects/labels_controller_spec.rb'
@@ -1358,7 +1189,6 @@ RSpec/ContextWording:
- 'spec/controllers/projects/prometheus/metrics_controller_spec.rb'
- 'spec/controllers/projects/raw_controller_spec.rb'
- 'spec/controllers/projects/releases_controller_spec.rb'
- - 'spec/controllers/projects/repositories_controller_spec.rb'
- 'spec/controllers/projects/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/projects/settings/operations_controller_spec.rb'
- 'spec/controllers/projects/settings/repository_controller_spec.rb'
@@ -1367,44 +1197,36 @@ RSpec/ContextWording:
- 'spec/controllers/projects/tags_controller_spec.rb'
- 'spec/controllers/projects/todos_controller_spec.rb'
- 'spec/controllers/projects/tree_controller_spec.rb'
- - 'spec/controllers/projects/uploads_controller_spec.rb'
- 'spec/controllers/projects/web_ide_terminals_controller_spec.rb'
- 'spec/controllers/projects_controller_spec.rb'
- 'spec/controllers/registrations/welcome_controller_spec.rb'
- 'spec/controllers/registrations_controller_spec.rb'
- - 'spec/controllers/repositories/git_http_controller_spec.rb'
- 'spec/controllers/root_controller_spec.rb'
- 'spec/controllers/search_controller_spec.rb'
- - 'spec/controllers/sent_notifications_controller_spec.rb'
- 'spec/controllers/sessions_controller_spec.rb'
- 'spec/controllers/snippets/notes_controller_spec.rb'
- 'spec/controllers/snippets_controller_spec.rb'
- 'spec/controllers/uploads_controller_spec.rb'
- 'spec/controllers/users/terms_controller_spec.rb'
- - 'spec/db/docs_spec.rb'
- 'spec/db/production/settings_spec.rb'
- 'spec/db/schema_spec.rb'
- 'spec/docs_screenshots/container_registry_docs.rb'
- 'spec/docs_screenshots/wiki_docs.rb'
- 'spec/experiments/application_experiment_spec.rb'
- 'spec/experiments/ios_specific_templates_experiment_spec.rb'
- - 'spec/features/admin/admin_abuse_reports_spec.rb'
- 'spec/features/admin/admin_appearance_spec.rb'
- 'spec/features/admin/admin_disables_git_access_protocol_spec.rb'
+ - 'spec/features/admin/admin_hook_logs_spec.rb'
- 'spec/features/admin/admin_hooks_spec.rb'
- 'spec/features/admin/admin_jobs_spec.rb'
- 'spec/features/admin/admin_mode/login_spec.rb'
- - 'spec/features/admin/admin_mode/logout_spec.rb'
- - 'spec/features/admin/admin_mode/workers_spec.rb'
- 'spec/features/admin/admin_mode_spec.rb'
- - 'spec/features/admin/admin_search_settings_spec.rb'
- 'spec/features/admin/admin_settings_spec.rb'
- 'spec/features/admin/dashboard_spec.rb'
- 'spec/features/admin/users/user_spec.rb'
- 'spec/features/admin/users/users_spec.rb'
- 'spec/features/atom/dashboard_issues_spec.rb'
- 'spec/features/atom/dashboard_spec.rb'
- - 'spec/features/atom/issues_spec.rb'
- 'spec/features/atom/merge_requests_spec.rb'
- 'spec/features/atom/users_spec.rb'
- 'spec/features/boards/boards_spec.rb'
@@ -1417,12 +1239,9 @@ RSpec/ContextWording:
- 'spec/features/boards/sidebar_labels_spec.rb'
- 'spec/features/boards/user_visits_board_spec.rb'
- 'spec/features/calendar_spec.rb'
- - 'spec/features/clusters/cluster_detail_page_spec.rb'
- 'spec/features/clusters/cluster_health_dashboard_spec.rb'
- 'spec/features/commits_spec.rb'
- - 'spec/features/cycle_analytics_spec.rb'
- 'spec/features/dashboard/activity_spec.rb'
- - 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
- 'spec/features/dashboard/groups_list_spec.rb'
- 'spec/features/dashboard/issues_filter_spec.rb'
- 'spec/features/dashboard/label_filter_spec.rb'
@@ -1436,7 +1255,6 @@ RSpec/ContextWording:
- 'spec/features/dashboard/user_filters_projects_spec.rb'
- 'spec/features/expand_collapse_diffs_spec.rb'
- 'spec/features/file_uploads/multipart_invalid_uploads_spec.rb'
- - 'spec/features/frequently_visited_projects_and_groups_spec.rb'
- 'spec/features/groups/board_sidebar_spec.rb'
- 'spec/features/groups/board_spec.rb'
- 'spec/features/groups/clusters/user_spec.rb'
@@ -1450,11 +1268,8 @@ RSpec/ContextWording:
- 'spec/features/groups/merge_requests_spec.rb'
- 'spec/features/groups/milestone_spec.rb'
- 'spec/features/groups/packages_spec.rb'
- - 'spec/features/groups/settings/ci_cd_spec.rb'
- 'spec/features/groups/settings/group_badges_spec.rb'
- - 'spec/features/groups/settings/packages_and_registries_spec.rb'
- 'spec/features/groups/settings/repository_spec.rb'
- - 'spec/features/groups/settings/user_searches_in_settings_spec.rb'
- 'spec/features/groups/share_lock_spec.rb'
- 'spec/features/groups/show_spec.rb'
- 'spec/features/groups/user_sees_package_sidebar_spec.rb'
@@ -1492,8 +1307,6 @@ RSpec/ContextWording:
- 'spec/features/issues/user_creates_issue_spec.rb'
- 'spec/features/issues/user_edits_issue_spec.rb'
- 'spec/features/issues/user_interacts_with_awards_spec.rb'
- - 'spec/features/issues/user_scrolls_to_deeplinked_note_spec.rb'
- - 'spec/features/issues/user_sorts_issue_comments_spec.rb'
- 'spec/features/issues/user_toggles_subscription_spec.rb'
- 'spec/features/issues/user_uses_quick_actions_spec.rb'
- 'spec/features/issues/user_views_issues_spec.rb'
@@ -1504,14 +1317,15 @@ RSpec/ContextWording:
- 'spec/features/markdown/metrics_spec.rb'
- 'spec/features/merge_request/batch_comments_spec.rb'
- 'spec/features/merge_request/close_reopen_report_toggle_spec.rb'
+ - 'spec/features/merge_request/merge_request_discussion_lock_spec.rb'
- 'spec/features/merge_request/user_accepts_merge_request_spec.rb'
- 'spec/features/merge_request/user_assigns_themselves_spec.rb'
- - 'spec/features/merge_request/user_comments_on_diff_spec.rb'
- 'spec/features/merge_request/user_creates_image_diff_notes_spec.rb'
- 'spec/features/merge_request/user_creates_merge_request_spec.rb'
- 'spec/features/merge_request/user_creates_mr_spec.rb'
- 'spec/features/merge_request/user_edits_mr_spec.rb'
- 'spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb'
+ - 'spec/features/merge_request/user_manages_subscription_spec.rb'
- 'spec/features/merge_request/user_merges_merge_request_spec.rb'
- 'spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb'
- 'spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb'
@@ -1522,15 +1336,11 @@ RSpec/ContextWording:
- 'spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb'
- 'spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb'
- 'spec/features/merge_request/user_sees_closing_issues_message_spec.rb'
- - 'spec/features/merge_request/user_sees_deployment_widget_spec.rb'
- - 'spec/features/merge_request/user_sees_diff_spec.rb'
- 'spec/features/merge_request/user_sees_discussions_spec.rb'
- 'spec/features/merge_request/user_sees_merge_widget_spec.rb'
- - 'spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb'
- 'spec/features/merge_request/user_suggests_changes_on_diff_spec.rb'
- 'spec/features/merge_request/user_uses_quick_actions_spec.rb'
- 'spec/features/merge_request/user_views_open_merge_request_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'
@@ -1539,7 +1349,6 @@ RSpec/ContextWording:
- 'spec/features/merge_requests/user_filters_by_target_branch_spec.rb'
- 'spec/features/merge_requests/user_lists_merge_requests_spec.rb'
- 'spec/features/merge_requests/user_mass_updates_spec.rb'
- - 'spec/features/merge_requests/user_sees_empty_state_spec.rb'
- 'spec/features/milestones/user_views_milestone_spec.rb'
- 'spec/features/monitor_sidebar_link_spec.rb'
- 'spec/features/nav/top_nav_responsive_spec.rb'
@@ -1550,7 +1359,6 @@ RSpec/ContextWording:
- 'spec/features/profiles/keys_spec.rb'
- 'spec/features/profiles/password_spec.rb'
- 'spec/features/profiles/user_edit_profile_spec.rb'
- - 'spec/features/profiles/user_search_settings_spec.rb'
- 'spec/features/projects/active_tabs_spec.rb'
- 'spec/features/projects/activity/user_sees_design_activity_spec.rb'
- 'spec/features/projects/artifacts/file_spec.rb'
@@ -1565,6 +1373,7 @@ RSpec/ContextWording:
- 'spec/features/projects/commits/multi_view_diff_spec.rb'
- 'spec/features/projects/commits/user_browses_commits_spec.rb'
- 'spec/features/projects/compare_spec.rb'
+ - 'spec/features/projects/deploy_keys_spec.rb'
- 'spec/features/projects/diffs/diff_show_spec.rb'
- 'spec/features/projects/environments/environment_spec.rb'
- 'spec/features/projects/environments/environments_spec.rb'
@@ -1575,6 +1384,7 @@ RSpec/ContextWording:
- 'spec/features/projects/files/user_creates_directory_spec.rb'
- 'spec/features/projects/fork_spec.rb'
- 'spec/features/projects/graph_spec.rb'
+ - 'spec/features/projects/hook_logs/user_reads_log_spec.rb'
- 'spec/features/projects/import_export/export_file_spec.rb'
- 'spec/features/projects/infrastructure_registry_spec.rb'
- 'spec/features/projects/integrations/disable_triggers_spec.rb'
@@ -1582,15 +1392,12 @@ RSpec/ContextWording:
- 'spec/features/projects/issuable_templates_spec.rb'
- 'spec/features/projects/issues/design_management/user_links_to_designs_in_issue_spec.rb'
- 'spec/features/projects/issues/design_management/user_views_designs_spec.rb'
- - 'spec/features/projects/issues/email_participants_spec.rb'
+ - 'spec/features/projects/jobs/user_browses_job_spec.rb'
- 'spec/features/projects/jobs/user_browses_jobs_spec.rb'
- 'spec/features/projects/jobs_spec.rb'
- 'spec/features/projects/labels/search_labels_spec.rb'
- - 'spec/features/projects/labels/update_prioritization_spec.rb'
- - 'spec/features/projects/labels/user_creates_labels_spec.rb'
- 'spec/features/projects/members/group_members_spec.rb'
- 'spec/features/projects/members/groups_with_access_list_spec.rb'
- - 'spec/features/projects/members/manage_groups_spec.rb'
- 'spec/features/projects/members/manage_members_spec.rb'
- 'spec/features/projects/members/tabs_spec.rb'
- 'spec/features/projects/members/user_requests_access_spec.rb'
@@ -1601,21 +1408,20 @@ RSpec/ContextWording:
- 'spec/features/projects/packages_spec.rb'
- 'spec/features/projects/pages/user_edits_settings_spec.rb'
- 'spec/features/projects/pipeline_schedules_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipelines_spec.rb'
- 'spec/features/projects/pipelines/pipeline_spec.rb'
- 'spec/features/projects/pipelines/pipelines_spec.rb'
- 'spec/features/projects/releases/user_views_releases_spec.rb'
+ - 'spec/features/projects/settings/branch_rules_settings_spec.rb'
- 'spec/features/projects/settings/lfs_settings_spec.rb'
- 'spec/features/projects/settings/packages_settings_spec.rb'
- - 'spec/features/projects/settings/pipelines_settings_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/repository_settings_spec.rb'
+ - 'spec/features/projects/settings/secure_files_spec.rb'
- 'spec/features/projects/settings/service_desk_setting_spec.rb'
- 'spec/features/projects/settings/user_interacts_with_deploy_keys_spec.rb'
- - 'spec/features/projects/settings/user_renames_a_project_spec.rb'
- - 'spec/features/projects/settings/user_searches_in_settings_spec.rb'
- - 'spec/features/projects/settings/user_transfers_a_project_spec.rb'
- 'spec/features/projects/settings/visibility_settings_spec.rb'
- 'spec/features/projects/settings/webhooks_settings_spec.rb'
- 'spec/features/projects/show/user_manages_notifications_spec.rb'
@@ -1625,34 +1431,25 @@ RSpec/ContextWording:
- 'spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb'
- 'spec/features/projects/snippets/user_views_snippets_spec.rb'
- 'spec/features/projects/sourcegraph_csp_spec.rb'
- - 'spec/features/projects/tags/user_edits_tags_spec.rb'
- 'spec/features/projects/tags/user_views_tags_spec.rb'
- 'spec/features/projects/tree/tree_show_spec.rb'
- - 'spec/features/projects/user_creates_project_spec.rb'
- - 'spec/features/projects/user_sees_sidebar_spec.rb'
- 'spec/features/projects/user_sorts_projects_spec.rb'
- 'spec/features/projects/user_uses_shortcuts_spec.rb'
- - 'spec/features/projects/view_on_env_spec.rb'
- - 'spec/features/projects/wiki/user_views_wiki_empty_spec.rb'
- 'spec/features/projects_spec.rb'
- 'spec/features/protected_branches_spec.rb'
- 'spec/features/reportable_note/commit_spec.rb'
- 'spec/features/reportable_note/merge_request_spec.rb'
- 'spec/features/runners_spec.rb'
- 'spec/features/search/user_searches_for_code_spec.rb'
- - 'spec/features/search/user_uses_header_search_field_spec.rb'
- - 'spec/features/security/project/snippet/internal_access_spec.rb'
- - 'spec/features/security/project/snippet/public_access_spec.rb'
- 'spec/features/signed_commits_spec.rb'
- 'spec/features/snippets/explore_spec.rb'
- 'spec/features/tags/developer_creates_tag_spec.rb'
- 'spec/features/tags/developer_deletes_tag_spec.rb'
- - 'spec/features/tags/developer_updates_tag_spec.rb'
+ - 'spec/features/tags/maintainer_deletes_protected_tag_spec.rb'
- 'spec/features/uploads/user_uploads_file_to_note_spec.rb'
- 'spec/features/user_can_display_performance_bar_spec.rb'
- 'spec/features/user_opens_link_to_comment_spec.rb'
- 'spec/features/users/login_spec.rb'
- - 'spec/features/users/logout_spec.rb'
- 'spec/features/users/overview_spec.rb'
- 'spec/features/users/show_spec.rb'
- 'spec/features/users/snippets_spec.rb'
@@ -1664,14 +1461,12 @@ RSpec/ContextWording:
- 'spec/finders/applications_finder_spec.rb'
- 'spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb'
- 'spec/finders/autocomplete/move_to_project_finder_spec.rb'
- - 'spec/finders/autocomplete/routes_finder_spec.rb'
- 'spec/finders/autocomplete/users_finder_spec.rb'
- 'spec/finders/branches_finder_spec.rb'
- 'spec/finders/ci/commit_statuses_finder_spec.rb'
- 'spec/finders/ci/jobs_finder_spec.rb'
- 'spec/finders/ci/pipelines_finder_spec.rb'
- 'spec/finders/ci/runners_finder_spec.rb'
- - 'spec/finders/ci/variables_finder_spec.rb'
- 'spec/finders/cluster_ancestors_finder_spec.rb'
- 'spec/finders/clusters/agent_authorizations_finder_spec.rb'
- 'spec/finders/clusters/agents_finder_spec.rb'
@@ -1679,7 +1474,6 @@ RSpec/ContextWording:
- 'spec/finders/contributed_projects_finder_spec.rb'
- 'spec/finders/deploy_tokens/tokens_finder_spec.rb'
- 'spec/finders/deployments_finder_spec.rb'
- - 'spec/finders/design_management/designs_finder_spec.rb'
- 'spec/finders/environments/environment_names_finder_spec.rb'
- 'spec/finders/environments/environments_by_deployments_finder_spec.rb'
- 'spec/finders/environments/environments_finder_spec.rb'
@@ -1690,7 +1484,6 @@ RSpec/ContextWording:
- 'spec/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder_spec.rb'
- 'spec/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder_spec.rb'
- 'spec/finders/groups_finder_spec.rb'
- - 'spec/finders/issues_finder_spec.rb'
- 'spec/finders/joined_groups_finder_spec.rb'
- 'spec/finders/keys_finder_spec.rb'
- 'spec/finders/labels_finder_spec.rb'
@@ -1703,8 +1496,6 @@ RSpec/ContextWording:
- 'spec/finders/metrics/users_starred_dashboards_finder_spec.rb'
- 'spec/finders/milestones_finder_spec.rb'
- 'spec/finders/notes_finder_spec.rb'
- - 'spec/finders/packages/conan/package_finder_spec.rb'
- - 'spec/finders/packages/go/version_finder_spec.rb'
- 'spec/finders/packages/group_packages_finder_spec.rb'
- 'spec/finders/packages/helm/packages_finder_spec.rb'
- 'spec/finders/packages/maven/package_finder_spec.rb'
@@ -1738,7 +1529,6 @@ RSpec/ContextWording:
- 'spec/frontend/fixtures/u2f.rb'
- 'spec/frontend/fixtures/webauthn.rb'
- 'spec/graphql/features/feature_flag_spec.rb'
- - 'spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb'
- 'spec/graphql/mutations/alert_management/create_alert_issue_spec.rb'
- 'spec/graphql/mutations/alert_management/http_integration/create_spec.rb'
- 'spec/graphql/mutations/alert_management/http_integration/destroy_spec.rb'
@@ -1748,14 +1538,12 @@ RSpec/ContextWording:
- 'spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb'
- 'spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb'
- 'spec/graphql/mutations/alert_management/update_alert_status_spec.rb'
- - 'spec/graphql/mutations/boards/lists/update_spec.rb'
- 'spec/graphql/mutations/clusters/agent_tokens/revoke_spec.rb'
- 'spec/graphql/mutations/clusters/agents/create_spec.rb'
- 'spec/graphql/mutations/custom_emoji/destroy_spec.rb'
- 'spec/graphql/mutations/design_management/delete_spec.rb'
- 'spec/graphql/mutations/design_management/move_spec.rb'
- 'spec/graphql/mutations/groups/update_spec.rb'
- - 'spec/graphql/mutations/issues/set_severity_spec.rb'
- 'spec/graphql/mutations/merge_requests/update_spec.rb'
- 'spec/graphql/mutations/release_asset_links/update_spec.rb'
- 'spec/graphql/mutations/releases/delete_spec.rb'
@@ -1780,7 +1568,6 @@ RSpec/ContextWording:
- 'spec/graphql/resolvers/design_management/design_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/designs_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/version/design_at_version_resolver_spec.rb'
- - 'spec/graphql/resolvers/design_management/version/designs_at_version_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/version_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/versions_resolver_spec.rb'
@@ -1793,7 +1580,6 @@ RSpec/ContextWording:
- 'spec/graphql/resolvers/kas/agent_configurations_resolver_spec.rb'
- 'spec/graphql/resolvers/kas/agent_connections_resolver_spec.rb'
- 'spec/graphql/resolvers/last_commit_resolver_spec.rb'
- - 'spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb'
- 'spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb'
- 'spec/graphql/resolvers/namespace_projects_resolver_spec.rb'
- 'spec/graphql/resolvers/project_merge_requests_resolver_spec.rb'
@@ -1802,16 +1588,13 @@ RSpec/ContextWording:
- 'spec/graphql/resolvers/snippets/blobs_resolver_spec.rb'
- 'spec/graphql/resolvers/snippets_resolver_spec.rb'
- 'spec/graphql/resolvers/terraform/states_resolver_spec.rb'
- - 'spec/graphql/resolvers/timelog_resolver_spec.rb'
- 'spec/graphql/resolvers/user_resolver_spec.rb'
- 'spec/graphql/resolvers/users/group_count_resolver_spec.rb'
- 'spec/graphql/resolvers/users/participants_resolver_spec.rb'
- 'spec/graphql/subscriptions/issuable_updated_spec.rb'
- 'spec/graphql/types/base_field_spec.rb'
- 'spec/graphql/types/global_id_type_spec.rb'
- - 'spec/graphql/types/invitation_interface_spec.rb'
- 'spec/graphql/types/issue_type_spec.rb'
- - 'spec/graphql/types/member_interface_spec.rb'
- 'spec/graphql/types/range_input_type_spec.rb'
- 'spec/graphql/types/release_links_type_spec.rb'
- 'spec/graphql/types/user_type_spec.rb'
@@ -1826,13 +1609,12 @@ RSpec/ContextWording:
- 'spec/helpers/award_emoji_helper_spec.rb'
- 'spec/helpers/blob_helper_spec.rb'
- 'spec/helpers/boards_helper_spec.rb'
- - 'spec/helpers/ci/runners_helper_spec.rb'
+ - 'spec/helpers/ci/secure_files_helper_spec.rb'
- 'spec/helpers/clusters_helper_spec.rb'
- 'spec/helpers/colors_helper_spec.rb'
- 'spec/helpers/commits_helper_spec.rb'
- 'spec/helpers/diff_helper_spec.rb'
- 'spec/helpers/emails_helper_spec.rb'
- - 'spec/helpers/environment_helper_spec.rb'
- 'spec/helpers/environments_helper_spec.rb'
- 'spec/helpers/events_helper_spec.rb'
- 'spec/helpers/git_helper_spec.rb'
@@ -1842,7 +1624,6 @@ RSpec/ContextWording:
- 'spec/helpers/ide_helper_spec.rb'
- 'spec/helpers/integrations_helper_spec.rb'
- 'spec/helpers/invite_members_helper_spec.rb'
- - 'spec/helpers/issues_helper_spec.rb'
- 'spec/helpers/jira_connect_helper_spec.rb'
- 'spec/helpers/labels_helper_spec.rb'
- 'spec/helpers/listbox_helper_spec.rb'
@@ -1853,34 +1634,32 @@ RSpec/ContextWording:
- 'spec/helpers/notes_helper_spec.rb'
- 'spec/helpers/operations_helper_spec.rb'
- 'spec/helpers/projects/cluster_agents_helper_spec.rb'
+ - 'spec/helpers/projects/project_members_helper_spec.rb'
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/helpers/releases_helper_spec.rb'
- 'spec/helpers/routing/pseudonymization_helper_spec.rb'
- 'spec/helpers/search_helper_spec.rb'
- - 'spec/helpers/snippets_helper_spec.rb'
- 'spec/helpers/sorting_helper_spec.rb'
- 'spec/helpers/storage_helper_spec.rb'
- 'spec/helpers/submodule_helper_spec.rb'
- 'spec/helpers/timeboxes_helper_spec.rb'
- - 'spec/helpers/timeboxes_routing_helper_spec.rb'
- 'spec/helpers/todos_helper_spec.rb'
- 'spec/helpers/tree_helper_spec.rb'
- - 'spec/helpers/users/group_callouts_helper_spec.rb'
+ - 'spec/helpers/users/callouts_helper_spec.rb'
- 'spec/helpers/users_helper_spec.rb'
- 'spec/helpers/visibility_level_helper_spec.rb'
+ - 'spec/helpers/web_hooks/web_hooks_helper_spec.rb'
- 'spec/helpers/whats_new_helper_spec.rb'
- 'spec/helpers/wiki_helper_spec.rb'
- 'spec/initializers/00_rails_disable_joins_spec.rb'
- - 'spec/initializers/0_log_deprecations_spec.rb'
+ - 'spec/initializers/1_acts_as_taggable_spec.rb'
- 'spec/initializers/carrierwave_patch_spec.rb'
- - 'spec/initializers/lograge_spec.rb'
+ - 'spec/initializers/enumerator_next_patch_spec.rb'
- 'spec/initializers/mail_encoding_patch_spec.rb'
- - 'spec/initializers/net_http_patch_spec.rb'
- 'spec/initializers/rack_multipart_patch_spec.rb'
- 'spec/initializers/secret_token_spec.rb'
- 'spec/initializers/settings_spec.rb'
- 'spec/initializers/validate_database_config_spec.rb'
- - 'spec/initializers/validate_puma_spec.rb'
- 'spec/lib/api/entities/application_setting_spec.rb'
- 'spec/lib/api/entities/basic_project_details_spec.rb'
- 'spec/lib/api/entities/clusters/agent_authorization_spec.rb'
@@ -1911,14 +1690,12 @@ RSpec/ContextWording:
- 'spec/lib/atlassian/jira_connect/serializers/deployment_entity_spec.rb'
- 'spec/lib/atlassian/jira_connect/serializers/feature_flag_entity_spec.rb'
- 'spec/lib/atlassian/jira_connect_spec.rb'
- - 'spec/lib/backup/files_spec.rb'
- 'spec/lib/backup/gitaly_backup_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
- 'spec/lib/backup/repositories_spec.rb'
- 'spec/lib/banzai/color_parser_spec.rb'
- 'spec/lib/banzai/filter/absolute_link_filter_spec.rb'
- 'spec/lib/banzai/filter/asset_proxy_filter_spec.rb'
- - 'spec/lib/banzai/filter/audio_link_filter_spec.rb'
- 'spec/lib/banzai/filter/autolink_filter_spec.rb'
- 'spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb'
- 'spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb'
@@ -1927,7 +1704,6 @@ RSpec/ContextWording:
- 'spec/lib/banzai/filter/front_matter_filter_spec.rb'
- 'spec/lib/banzai/filter/gollum_tags_filter_spec.rb'
- 'spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb'
- - 'spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb'
- 'spec/lib/banzai/filter/markdown_filter_spec.rb'
- 'spec/lib/banzai/filter/reference_redactor_filter_spec.rb'
- 'spec/lib/banzai/filter/references/abstract_reference_filter_spec.rb'
@@ -1949,12 +1725,10 @@ RSpec/ContextWording:
- 'spec/lib/banzai/filter/table_of_contents_filter_spec.rb'
- 'spec/lib/banzai/filter/table_of_contents_tag_filter_spec.rb'
- 'spec/lib/banzai/filter/upload_link_filter_spec.rb'
- - 'spec/lib/banzai/filter/video_link_filter_spec.rb'
- 'spec/lib/banzai/filter/wiki_link_filter_spec.rb'
- 'spec/lib/banzai/pipeline/broadcast_message_pipeline_spec.rb'
- 'spec/lib/banzai/pipeline_spec.rb'
- 'spec/lib/banzai/reference_parser/alert_parser_spec.rb'
- - 'spec/lib/banzai/reference_parser/base_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/feature_flag_parser_spec.rb'
@@ -1984,7 +1758,6 @@ RSpec/ContextWording:
- 'spec/lib/constraints/group_url_constrainer_spec.rb'
- 'spec/lib/constraints/project_url_constrainer_spec.rb'
- 'spec/lib/constraints/user_url_constrainer_spec.rb'
- - 'spec/lib/container_registry/blob_spec.rb'
- 'spec/lib/container_registry/gitlab_api_client_spec.rb'
- 'spec/lib/container_registry/migration_spec.rb'
- 'spec/lib/container_registry/registry_spec.rb'
@@ -1999,11 +1772,7 @@ RSpec/ContextWording:
- 'spec/lib/feature/definition_spec.rb'
- 'spec/lib/feature_spec.rb'
- 'spec/lib/generators/gitlab/snowplow_event_definition_generator_spec.rb'
- - 'spec/lib/generators/gitlab/usage_metric_generator_spec.rb'
- - 'spec/lib/gitlab/alert_management/alert_status_counts_spec.rb'
- 'spec/lib/gitlab/alert_management/fingerprint_spec.rb'
- - 'spec/lib/gitlab/alert_management/payload/base_spec.rb'
- - 'spec/lib/gitlab/alert_management/payload_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb'
@@ -2011,19 +1780,13 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/asciidoc_spec.rb'
- 'spec/lib/gitlab/asset_proxy_spec.rb'
- 'spec/lib/gitlab/auth/atlassian/identity_linker_spec.rb'
- - 'spec/lib/gitlab/auth/atlassian/user_spec.rb'
- 'spec/lib/gitlab/auth/auth_finders_spec.rb'
- 'spec/lib/gitlab/auth/current_user_mode_spec.rb'
- - 'spec/lib/gitlab/auth/key_status_checker_spec.rb'
- - 'spec/lib/gitlab/auth/ldap/access_spec.rb'
- 'spec/lib/gitlab/auth/ldap/adapter_spec.rb'
- - 'spec/lib/gitlab/auth/ldap/auth_hash_spec.rb'
- 'spec/lib/gitlab/auth/ldap/dn_spec.rb'
- - 'spec/lib/gitlab/auth/ldap/person_spec.rb'
- 'spec/lib/gitlab/auth/ldap/user_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb'
- - 'spec/lib/gitlab/auth/o_auth/provider_spec.rb'
- 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
- 'spec/lib/gitlab/auth/otp/strategies/forti_authenticator/manual_otp_spec.rb'
- 'spec/lib/gitlab/auth/otp/strategies/forti_authenticator/push_otp_spec.rb'
@@ -2038,16 +1801,12 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/authorized_keys_spec.rb'
- 'spec/lib/gitlab/avatar_cache_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_with_corrected_regex_spec.rb'
- - 'spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb'
- 'spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb'
- 'spec/lib/gitlab/background_migration/cleanup_draft_data_from_faulty_regex_spec.rb'
- 'spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb'
- 'spec/lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images_spec.rb'
- 'spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb'
- - 'spec/lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid_spec.rb'
- - 'spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb'
- 'spec/lib/gitlab/bare_repository_import/importer_spec.rb'
- 'spec/lib/gitlab/bare_repository_import/repository_spec.rb'
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
@@ -2056,17 +1815,14 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb'
- 'spec/lib/gitlab/cache/helpers_spec.rb'
- 'spec/lib/gitlab/chat/responder_spec.rb'
- - 'spec/lib/gitlab/chat_name_token_spec.rb'
- 'spec/lib/gitlab/checks/branch_check_spec.rb'
- 'spec/lib/gitlab/checks/lfs_integrity_spec.rb'
- - 'spec/lib/gitlab/checks/matching_merge_request_spec.rb'
- 'spec/lib/gitlab/checks/push_file_count_check_spec.rb'
- 'spec/lib/gitlab/checks/snippet_check_spec.rb'
- 'spec/lib/gitlab/checks/tag_check_spec.rb'
- 'spec/lib/gitlab/ci/ansi2html_spec.rb'
- 'spec/lib/gitlab/ci/ansi2json/style_spec.rb'
- 'spec/lib/gitlab/ci/ansi2json_spec.rb'
- - 'spec/lib/gitlab/ci/badge/coverage/report_spec.rb'
- 'spec/lib/gitlab/ci/badge/pipeline/status_spec.rb'
- 'spec/lib/gitlab/ci/badge/release/template_spec.rb'
- 'spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb'
@@ -2074,13 +1830,13 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/ci/build/prerequisite/factory_spec.rb'
- 'spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb'
- 'spec/lib/gitlab/ci/build/releaser_spec.rb'
+ - 'spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb'
- 'spec/lib/gitlab/ci/build/rules/rule/clause/exists_spec.rb'
- 'spec/lib/gitlab/ci/build/rules_spec.rb'
- 'spec/lib/gitlab/ci/charts_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/default_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/environment_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/include/rules/rule_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/include_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/inherit/variables_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/job_spec.rb'
@@ -2089,8 +1845,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/ci/config/entry/port_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/ports_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/processable_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/release_spec.rb'
- - 'spec/lib/gitlab/ci/config/entry/reports_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/retry_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/trigger/forward_spec.rb'
@@ -2100,9 +1854,7 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/ci/jwt_spec.rb'
- 'spec/lib/gitlab/ci/lint_spec.rb'
- 'spec/lib/gitlab/ci/matching/runner_matcher_spec.rb'
- - 'spec/lib/gitlab/ci/parsers/coverage/sax_document_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/common_spec.rb'
- - 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
- 'spec/lib/gitlab/ci/parsers/test/junit_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/command_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/create_spec.rb'
@@ -2113,27 +1865,23 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/seed/build_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb'
- 'spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb'
- 'spec/lib/gitlab/ci/reports/reports_comparer_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/aggregated_report_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb'
- 'spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb'
- 'spec/lib/gitlab/ci/runner_instructions_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/failed_spec.rb'
- 'spec/lib/gitlab/ci/status/composite_spec.rb'
- 'spec/lib/gitlab/ci/status/factory_spec.rb'
- - 'spec/lib/gitlab/ci/status/stage/play_manual_spec.rb'
- 'spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb'
+ - 'spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/npm_spec.rb'
- 'spec/lib/gitlab/ci/templates/templates_spec.rb'
- 'spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb'
@@ -2156,16 +1904,15 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/config/entry/composable_array_spec.rb'
- 'spec/lib/gitlab/config/entry/composable_hash_spec.rb'
- 'spec/lib/gitlab/config_checker/puma_rugged_checker_spec.rb'
- - 'spec/lib/gitlab/console_spec.rb'
- 'spec/lib/gitlab/consul/internal_spec.rb'
- 'spec/lib/gitlab/content_security_policy/config_loader_spec.rb'
- - 'spec/lib/gitlab/current_settings_spec.rb'
- 'spec/lib/gitlab/cycle_analytics/permissions_spec.rb'
- 'spec/lib/gitlab/daemon_spec.rb'
- 'spec/lib/gitlab/data_builder/build_spec.rb'
- 'spec/lib/gitlab/data_builder/issuable_spec.rb'
- 'spec/lib/gitlab/data_builder/pipeline_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb'
+ - '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/batch_count_spec.rb'
- 'spec/lib/gitlab/database/bulk_update_spec.rb'
@@ -2173,7 +1920,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb'
- 'spec/lib/gitlab/database/count_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/host_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/setup_spec.rb'
@@ -2200,9 +1946,9 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/database/postgres_hll/batch_distinct_counter_spec.rb'
- 'spec/lib/gitlab/database/query_analyzer_spec.rb'
- 'spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb'
+ - 'spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb'
- 'spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb'
- 'spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb'
- - 'spec/lib/gitlab/database/reflection_spec.rb'
- 'spec/lib/gitlab/database/reindexing/coordinator_spec.rb'
- 'spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb'
- 'spec/lib/gitlab/database/reindexing/reindex_action_spec.rb'
@@ -2223,6 +1969,7 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/diff/lines_unfolder_spec.rb'
- 'spec/lib/gitlab/diff/position_spec.rb'
- 'spec/lib/gitlab/diff/position_tracer_spec.rb'
+ - 'spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb'
- 'spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb'
- 'spec/lib/gitlab/diff/suggestions_parser_spec.rb'
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
@@ -2234,18 +1981,17 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/email/handler_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/base_spec.rb'
- - 'spec/lib/gitlab/email/message/in_product_marketing/experience_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/helper_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb'
- 'spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb'
- 'spec/lib/gitlab/email/message/repository_push_spec.rb'
+ - 'spec/lib/gitlab/email/reply_parser_spec.rb'
- 'spec/lib/gitlab/encoding_helper_spec.rb'
- 'spec/lib/gitlab/error_tracking/context_payload_generator_spec.rb'
- 'spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb'
- 'spec/lib/gitlab/error_tracking_spec.rb'
- - 'spec/lib/gitlab/exceptions_app_spec.rb'
- 'spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb'
- 'spec/lib/gitlab/experimentation/controller_concern_spec.rb'
- 'spec/lib/gitlab/experimentation_spec.rb'
@@ -2266,7 +2012,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/git/cross_repo_comparer_spec.rb'
- 'spec/lib/gitlab/git/diff_collection_spec.rb'
- 'spec/lib/gitlab/git/diff_spec.rb'
- - 'spec/lib/gitlab/git/keep_around_spec.rb'
- 'spec/lib/gitlab/git/merge_base_spec.rb'
- 'spec/lib/gitlab/git/raw_diff_change_spec.rb'
- 'spec/lib/gitlab/git/repository_spec.rb'
@@ -2284,6 +2029,7 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb'
- 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
- 'spec/lib/gitlab/github_import/representation/diff_note_spec.rb'
+ - 'spec/lib/gitlab/github_import/representation/issue_event_spec.rb'
- 'spec/lib/gitlab/github_import/representation/issue_spec.rb'
- 'spec/lib/gitlab/github_import/representation/note_spec.rb'
- 'spec/lib/gitlab/github_import/representation/pull_request_spec.rb'
@@ -2296,18 +2042,16 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb'
- 'spec/lib/gitlab/graphql/markdown_field_spec.rb'
- 'spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_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/queries_spec.rb'
- 'spec/lib/gitlab/graphql_logger_spec.rb'
+ - 'spec/lib/gitlab/harbor/client_spec.rb'
+ - 'spec/lib/gitlab/harbor/query_spec.rb'
- 'spec/lib/gitlab/health_checks/gitaly_check_spec.rb'
- 'spec/lib/gitlab/health_checks/middleware_spec.rb'
- - 'spec/lib/gitlab/health_checks/puma_check_spec.rb'
- 'spec/lib/gitlab/health_checks/simple_check_shared.rb'
- 'spec/lib/gitlab/highlight_spec.rb'
- 'spec/lib/gitlab/hook_data/group_builder_spec.rb'
- 'spec/lib/gitlab/hook_data/group_member_builder_spec.rb'
- - 'spec/lib/gitlab/hook_data/issue_builder_spec.rb'
- 'spec/lib/gitlab/hook_data/key_builder_spec.rb'
- 'spec/lib/gitlab/hook_data/project_builder_spec.rb'
- 'spec/lib/gitlab/hook_data/project_member_builder_spec.rb'
@@ -2315,10 +2059,10 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/hook_data/user_builder_spec.rb'
- 'spec/lib/gitlab/hotlinking_detector_spec.rb'
- 'spec/lib/gitlab/http_spec.rb'
- - 'spec/lib/gitlab/i18n/po_linter_spec.rb'
- 'spec/lib/gitlab/import/merge_request_creator_spec.rb'
- 'spec/lib/gitlab/import_export/attributes_finder_spec.rb'
- 'spec/lib/gitlab/import_export/command_line_util_spec.rb'
+ - 'spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb'
- 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
- 'spec/lib/gitlab/import_export/file_importer_spec.rb'
- 'spec/lib/gitlab/import_export/group/legacy_tree_restorer_spec.rb'
@@ -2345,9 +2089,10 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/incoming_email_spec.rb'
- 'spec/lib/gitlab/instrumentation/redis_base_spec.rb'
- 'spec/lib/gitlab/instrumentation/redis_cluster_validator_spec.rb'
+ - 'spec/lib/gitlab/instrumentation_helper_spec.rb'
- 'spec/lib/gitlab/internal_post_receive/response_spec.rb'
+ - 'spec/lib/gitlab/issuable/clone/attributes_rewriter_spec.rb'
- 'spec/lib/gitlab/issuable_metadata_spec.rb'
- - 'spec/lib/gitlab/issuable_sorter_spec.rb'
- 'spec/lib/gitlab/issuables_count_for_state_spec.rb'
- 'spec/lib/gitlab/issues/rebalancing/state_spec.rb'
- 'spec/lib/gitlab/jira/dvcs_spec.rb'
@@ -2359,28 +2104,23 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/kubernetes/default_namespace_spec.rb'
- 'spec/lib/gitlab/kubernetes/helm/api_spec.rb'
- 'spec/lib/gitlab/kubernetes/helm/v2/certificate_spec.rb'
- - 'spec/lib/gitlab/kubernetes/helm/v2/init_command_spec.rb'
- 'spec/lib/gitlab/kubernetes/kube_client_spec.rb'
- - 'spec/lib/gitlab/kubernetes/rollout_status_spec.rb'
- 'spec/lib/gitlab/legacy_github_import/client_spec.rb'
- 'spec/lib/gitlab/lfs/client_spec.rb'
- 'spec/lib/gitlab/lfs_token_spec.rb'
- - 'spec/lib/gitlab/logger_spec.rb'
- 'spec/lib/gitlab/lograge/custom_options_spec.rb'
- 'spec/lib/gitlab/mail_room/authenticator_spec.rb'
- 'spec/lib/gitlab/mail_room/mail_room_spec.rb'
- 'spec/lib/gitlab/manifest_import/manifest_spec.rb'
- 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
+ - 'spec/lib/gitlab/memory/reports_daemon_spec.rb'
+ - 'spec/lib/gitlab/memory/watchdog_spec.rb'
- 'spec/lib/gitlab/merge_requests/commit_message_generator_spec.rb'
- - 'spec/lib/gitlab/metrics/boot_time_tracker_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/cache_spec.rb'
- - 'spec/lib/gitlab/metrics/dashboard/finder_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/importer_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb'
- - 'spec/lib/gitlab/metrics/dashboard/processor_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/stages/url_validator_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics_spec.rb'
- - 'spec/lib/gitlab/metrics/dashboard/url_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/validator/post_schema_validator_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/validator_spec.rb'
@@ -2388,7 +2128,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/metrics/method_call_spec.rb'
- 'spec/lib/gitlab/metrics/methods_spec.rb'
- 'spec/lib/gitlab/metrics/requests_rack_middleware_spec.rb'
- - 'spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb'
- 'spec/lib/gitlab/metrics/samplers/threads_sampler_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb'
@@ -2396,9 +2135,7 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/middleware/basic_health_check_spec.rb'
- 'spec/lib/gitlab/middleware/compressed_json_spec.rb'
- 'spec/lib/gitlab/middleware/go_spec.rb'
- - 'spec/lib/gitlab/middleware/handle_malformed_strings_spec.rb'
- 'spec/lib/gitlab/middleware/multipart_spec.rb'
- - 'spec/lib/gitlab/middleware/rack_multipart_tempfile_factory_spec.rb'
- 'spec/lib/gitlab/middleware/request_context_spec.rb'
- 'spec/lib/gitlab/middleware/same_site_cookies_spec.rb'
- 'spec/lib/gitlab/namespaced_session_store_spec.rb'
@@ -2410,22 +2147,18 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/pager_spec.rb'
- - 'spec/lib/gitlab/pagination/keyset/paginator_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/simple_order_builder_spec.rb'
- 'spec/lib/gitlab/pagination/offset_header_builder_spec.rb'
- - 'spec/lib/gitlab/pagination/offset_pagination_spec.rb'
- 'spec/lib/gitlab/patch/prependable_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
- 'spec/lib/gitlab/performance_bar_spec.rb'
- 'spec/lib/gitlab/phabricator_import/issues/importer_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/user_finder_spec.rb'
- 'spec/lib/gitlab/popen_spec.rb'
- 'spec/lib/gitlab/process_supervisor_spec.rb'
- 'spec/lib/gitlab/profiler_spec.rb'
- 'spec/lib/gitlab/project_authorizations_spec.rb'
- 'spec/lib/gitlab/project_search_results_spec.rb'
- 'spec/lib/gitlab/prometheus/adapter_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/knative_invocation_query_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/validate_query_spec.rb'
@@ -2438,7 +2171,8 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/rack_attack_spec.rb'
- 'spec/lib/gitlab/reactive_cache_set_cache_spec.rb'
- 'spec/lib/gitlab/redis/boolean_spec.rb'
- - 'spec/lib/gitlab/redis/hll_spec.rb'
+ - 'spec/lib/gitlab/redis/duplicate_jobs_spec.rb'
+ - 'spec/lib/gitlab/regex_requires_app_spec.rb'
- 'spec/lib/gitlab/regex_spec.rb'
- 'spec/lib/gitlab/relative_positioning/item_context_spec.rb'
- 'spec/lib/gitlab/relative_positioning/mover_spec.rb'
@@ -2452,12 +2186,12 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/runtime_spec.rb'
- 'spec/lib/gitlab/sanitizers/exif_spec.rb'
- 'spec/lib/gitlab/sanitizers/svg_spec.rb'
- - 'spec/lib/gitlab/search/params_spec.rb'
- 'spec/lib/gitlab/search/sort_options_spec.rb'
- 'spec/lib/gitlab/search_context/controller_concern_spec.rb'
- 'spec/lib/gitlab/search_results_spec.rb'
+ - 'spec/lib/gitlab/service_desk_email_spec.rb'
- 'spec/lib/gitlab/sidekiq_config/worker_router_spec.rb'
- - 'spec/lib/gitlab/sidekiq_daemon/monitor_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb'
- 'spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb'
@@ -2467,12 +2201,12 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/compressor_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware_spec.rb'
- 'spec/lib/gitlab/sidekiq_migrate_jobs_spec.rb'
- 'spec/lib/gitlab/sidekiq_signals_spec.rb'
- 'spec/lib/gitlab/slash_commands/command_spec.rb'
- - 'spec/lib/gitlab/slash_commands/deploy_spec.rb'
- 'spec/lib/gitlab/slash_commands/issue_close_spec.rb'
- 'spec/lib/gitlab/slash_commands/issue_new_spec.rb'
- 'spec/lib/gitlab/slash_commands/issue_search_spec.rb'
@@ -2480,9 +2214,7 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/slash_commands/presenters/issue_close_spec.rb'
- 'spec/lib/gitlab/slash_commands/presenters/issue_show_spec.rb'
- 'spec/lib/gitlab/slash_commands/run_spec.rb'
- - 'spec/lib/gitlab/sourcegraph_spec.rb'
- 'spec/lib/gitlab/spamcheck/client_spec.rb'
- - 'spec/lib/gitlab/sql/pattern_spec.rb'
- 'spec/lib/gitlab/ssh_public_key_spec.rb'
- 'spec/lib/gitlab/submodule_links_spec.rb'
- 'spec/lib/gitlab/subscription_portal_spec.rb'
@@ -2493,30 +2225,26 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/tracking/incident_management_spec.rb'
- 'spec/lib/gitlab/tracking/snowplow_schema_validation_spec.rb'
- 'spec/lib/gitlab/tracking/standard_context_spec.rb'
+ - 'spec/lib/gitlab/tracking_spec.rb'
- 'spec/lib/gitlab/tree_summary_spec.rb'
- 'spec/lib/gitlab/untrusted_regexp/ruby_syntax_spec.rb'
- 'spec/lib/gitlab/untrusted_regexp_spec.rb'
- 'spec/lib/gitlab/url_blocker_spec.rb'
- - 'spec/lib/gitlab/url_builder_spec.rb'
- 'spec/lib/gitlab/url_sanitizer_spec.rb'
- 'spec/lib/gitlab/usage/metric_definition_spec.rb'
- 'spec/lib/gitlab/usage/metric_spec.rb'
- 'spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb'
- 'spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_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/instrumentations/snowplow_configured_to_gitlab_collector_metric_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_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/service_ping/payload_keys_processor_spec.rb'
- 'spec/lib/gitlab/usage/service_ping_report_spec.rb'
- 'spec/lib/gitlab/usage_data/topology_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/ci_template_unique_counter_spec.rb'
- - 'spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
- - 'spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb'
+ - 'spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/search_counter_spec.rb'
@@ -2527,8 +2255,6 @@ RSpec/ContextWording:
- 'spec/lib/gitlab/utils/strong_memoize_spec.rb'
- 'spec/lib/gitlab/utils/usage_data_spec.rb'
- 'spec/lib/gitlab/utils_spec.rb'
- - 'spec/lib/gitlab/uuid_spec.rb'
- - 'spec/lib/gitlab/version_info_spec.rb'
- 'spec/lib/gitlab/view/presenter/base_spec.rb'
- 'spec/lib/gitlab/visibility_level_checker_spec.rb'
- 'spec/lib/gitlab/visibility_level_spec.rb'
@@ -2545,14 +2271,11 @@ RSpec/ContextWording:
- 'spec/lib/json_web_token/token_spec.rb'
- 'spec/lib/kramdown/parser/atlassian_document_format_spec.rb'
- 'spec/lib/mattermost/client_spec.rb'
- - 'spec/lib/mattermost/command_spec.rb'
- 'spec/lib/mattermost/session_spec.rb'
- - 'spec/lib/mattermost/team_spec.rb'
- 'spec/lib/object_storage/direct_upload_spec.rb'
- 'spec/lib/omni_auth/strategies/jwt_spec.rb'
- 'spec/lib/peek/views/bullet_detailed_spec.rb'
- 'spec/lib/product_analytics/event_params_spec.rb'
- - 'spec/lib/prometheus/pid_provider_spec.rb'
- 'spec/lib/safe_zip/entry_spec.rb'
- 'spec/lib/security/ci_configuration/container_scanning_build_action_spec.rb'
- 'spec/lib/security/ci_configuration/sast_build_action_spec.rb'
@@ -2571,19 +2294,15 @@ RSpec/ContextWording:
- 'spec/lib/system_check/orphans/repository_check_spec.rb'
- 'spec/lib/uploaded_file_spec.rb'
- 'spec/lib/version_check_spec.rb'
+ - 'spec/mailers/devise_mailer_spec.rb'
- 'spec/mailers/emails/profile_spec.rb'
- 'spec/mailers/emails/projects_spec.rb'
- 'spec/mailers/emails/releases_spec.rb'
- 'spec/mailers/emails/service_desk_spec.rb'
- 'spec/mailers/notify_spec.rb'
- - 'spec/metrics_server/metrics_server_spec.rb'
- 'spec/migrations/20210812013042_remove_duplicate_project_authorizations_spec.rb'
- - 'spec/migrations/20220426185933_backfill_deployments_finished_at_spec.rb'
- - 'spec/migrations/backfill_cadence_id_for_boards_scoped_to_iteration_spec.rb'
- 'spec/migrations/finalize_traversal_ids_background_migrations_spec.rb'
- - 'spec/migrations/fix_and_backfill_project_namespaces_for_projects_with_duplicate_name_spec.rb'
- 'spec/migrations/rename_services_to_integrations_spec.rb'
- - 'spec/migrations/schedule_security_setting_creation_spec.rb'
- 'spec/models/ability_spec.rb'
- 'spec/models/active_session_spec.rb'
- 'spec/models/alert_management/alert_spec.rb'
@@ -2600,11 +2319,9 @@ RSpec/ContextWording:
- 'spec/models/badges/project_badge_spec.rb'
- 'spec/models/blob_spec.rb'
- 'spec/models/blob_viewer/package_json_spec.rb'
- - 'spec/models/board_spec.rb'
- 'spec/models/bulk_imports/entity_spec.rb'
- 'spec/models/ci/artifact_blob_spec.rb'
- 'spec/models/ci/bridge_spec.rb'
- - 'spec/models/ci/build_dependencies_spec.rb'
- 'spec/models/ci/build_metadata_spec.rb'
- 'spec/models/ci/build_runner_session_spec.rb'
- 'spec/models/ci/build_spec.rb'
@@ -2620,7 +2337,6 @@ RSpec/ContextWording:
- 'spec/models/ci/processable_spec.rb'
- 'spec/models/ci/project_mirror_spec.rb'
- 'spec/models/ci/ref_spec.rb'
- - 'spec/models/ci/resource_spec.rb'
- 'spec/models/ci/runner_project_spec.rb'
- 'spec/models/ci/runner_spec.rb'
- 'spec/models/ci/running_build_spec.rb'
@@ -2643,7 +2359,6 @@ RSpec/ContextWording:
- 'spec/models/clusters/kubernetes_namespace_spec.rb'
- 'spec/models/clusters/platforms/kubernetes_spec.rb'
- 'spec/models/clusters/providers/aws_spec.rb'
- - 'spec/models/commit_signatures/x509_commit_signature_spec.rb'
- 'spec/models/commit_spec.rb'
- 'spec/models/commit_status_spec.rb'
- 'spec/models/compare_spec.rb'
@@ -2651,18 +2366,15 @@ RSpec/ContextWording:
- 'spec/models/concerns/awardable_spec.rb'
- 'spec/models/concerns/bulk_insert_safe_spec.rb'
- 'spec/models/concerns/bulk_insertable_associations_spec.rb'
- - 'spec/models/concerns/cache_markdown_field_spec.rb'
- 'spec/models/concerns/cacheable_attributes_spec.rb'
- - 'spec/models/concerns/cascading_namespace_setting_attribute_spec.rb'
- 'spec/models/concerns/ci/artifactable_spec.rb'
- 'spec/models/concerns/ci/has_ref_spec.rb'
- 'spec/models/concerns/ci/has_status_spec.rb'
- - 'spec/models/concerns/cron_schedulable_spec.rb'
- 'spec/models/concerns/cross_database_modification_spec.rb'
- 'spec/models/concerns/deployment_platform_spec.rb'
- - 'spec/models/concerns/group_descendant_spec.rb'
- 'spec/models/concerns/ignorable_columns_spec.rb'
- 'spec/models/concerns/issuable_spec.rb'
+ - 'spec/models/concerns/loose_index_scan_spec.rb'
- 'spec/models/concerns/mentionable_spec.rb'
- 'spec/models/concerns/milestoneable_spec.rb'
- 'spec/models/concerns/noteable_spec.rb'
@@ -2671,20 +2383,16 @@ RSpec/ContextWording:
- 'spec/models/concerns/protected_ref_access_spec.rb'
- 'spec/models/concerns/reactive_caching_spec.rb'
- 'spec/models/concerns/resolvable_note_spec.rb'
- - 'spec/models/concerns/routable_spec.rb'
- - 'spec/models/concerns/schedulable_spec.rb'
- 'spec/models/concerns/sensitive_serializable_hash_spec.rb'
- - 'spec/models/concerns/spammable_spec.rb'
- 'spec/models/concerns/token_authenticatable_spec.rb'
- 'spec/models/concerns/triggerable_hooks_spec.rb'
- 'spec/models/concerns/usage_statistics_spec.rb'
- 'spec/models/container_expiration_policy_spec.rb'
- 'spec/models/container_repository_spec.rb'
- - 'spec/models/customer_relations/issue_contact_spec.rb'
- 'spec/models/dependency_proxy/manifest_spec.rb'
- 'spec/models/dependency_proxy/registry_spec.rb'
- - 'spec/models/deploy_key_spec.rb'
- 'spec/models/deploy_token_spec.rb'
+ - 'spec/models/deployment_cluster_spec.rb'
- 'spec/models/deployment_metrics_spec.rb'
- 'spec/models/deployment_spec.rb'
- 'spec/models/design_management/action_spec.rb'
@@ -2697,25 +2405,21 @@ RSpec/ContextWording:
- 'spec/models/diff_note_spec.rb'
- 'spec/models/environment_spec.rb'
- 'spec/models/environment_status_spec.rb'
- - 'spec/models/error_tracking/error_event_spec.rb'
- 'spec/models/error_tracking/error_spec.rb'
- 'spec/models/event_collection_spec.rb'
- 'spec/models/event_spec.rb'
- 'spec/models/experiment_spec.rb'
- - 'spec/models/external_issue_spec.rb'
- 'spec/models/external_pull_request_spec.rb'
- - 'spec/models/fork_network_spec.rb'
- 'spec/models/gpg_key_spec.rb'
- 'spec/models/grafana_integration_spec.rb'
- - 'spec/models/group_deploy_token_spec.rb'
- 'spec/models/group_label_spec.rb'
- 'spec/models/group_spec.rb'
- 'spec/models/hooks/active_hook_filter_spec.rb'
+ - 'spec/models/hooks/project_hook_spec.rb'
- 'spec/models/hooks/system_hook_spec.rb'
- 'spec/models/identity_spec.rb'
- 'spec/models/import_export_upload_spec.rb'
- 'spec/models/import_failure_spec.rb'
- - 'spec/models/incident_management/timeline_event_spec.rb'
- 'spec/models/integration_spec.rb'
- 'spec/models/integrations/asana_spec.rb'
- 'spec/models/integrations/bamboo_spec.rb'
@@ -2791,45 +2495,36 @@ RSpec/ContextWording:
- 'spec/models/project_metrics_setting_spec.rb'
- 'spec/models/project_spec.rb'
- 'spec/models/project_team_spec.rb'
- - 'spec/models/projects/repository_storage_move_spec.rb'
- 'spec/models/prometheus_alert_event_spec.rb'
- - 'spec/models/protectable_dropdown_spec.rb'
- 'spec/models/protected_branch_spec.rb'
- 'spec/models/raw_usage_data_spec.rb'
- 'spec/models/release_highlight_spec.rb'
- 'spec/models/release_spec.rb'
- - 'spec/models/releases/link_spec.rb'
- 'spec/models/remote_mirror_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/models/resource_label_event_spec.rb'
- 'spec/models/resource_state_event_spec.rb'
- 'spec/models/route_spec.rb'
- - 'spec/models/sent_notification_spec.rb'
- 'spec/models/sentry_issue_spec.rb'
- 'spec/models/snippet_input_action_spec.rb'
- 'spec/models/snippet_repository_spec.rb'
- 'spec/models/snippet_spec.rb'
- 'spec/models/spam_log_spec.rb'
- 'spec/models/ssh_host_key_spec.rb'
- - 'spec/models/suggestion_spec.rb'
- 'spec/models/terraform/state_spec.rb'
- 'spec/models/terraform/state_version_spec.rb'
- - 'spec/models/todo_spec.rb'
- 'spec/models/upload_spec.rb'
- 'spec/models/uploads/fog_spec.rb'
- 'spec/models/uploads/local_spec.rb'
- - 'spec/models/user_interacted_project_spec.rb'
- 'spec/models/user_preference_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/models/users/in_product_marketing_email_spec.rb'
- 'spec/models/wiki_page/meta_spec.rb'
- 'spec/models/wiki_page/slug_spec.rb'
- 'spec/models/wiki_page_spec.rb'
+ - 'spec/models/work_item_spec.rb'
- 'spec/models/x509_certificate_spec.rb'
- - 'spec/models/zoom_meeting_spec.rb'
- - 'spec/policies/application_setting/term_policy_spec.rb'
- 'spec/policies/application_setting_policy_spec.rb'
- - 'spec/policies/base_policy_spec.rb'
- 'spec/policies/board_policy_spec.rb'
- 'spec/policies/ci/build_policy_spec.rb'
- 'spec/policies/clusters/agents/activity_event_policy_spec.rb'
@@ -2837,18 +2532,13 @@ RSpec/ContextWording:
- 'spec/policies/custom_emoji_policy_spec.rb'
- 'spec/policies/deploy_key_policy_spec.rb'
- 'spec/policies/deploy_keys_project_policy_spec.rb'
- - 'spec/policies/design_management/design_policy_spec.rb'
- 'spec/policies/global_policy_spec.rb'
- 'spec/policies/group_member_policy_spec.rb'
- 'spec/policies/group_policy_spec.rb'
- - 'spec/policies/instance_metadata_policy_spec.rb'
- 'spec/policies/issuable_policy_spec.rb'
- 'spec/policies/issue_policy_spec.rb'
- - 'spec/policies/merge_request_policy_spec.rb'
- 'spec/policies/metrics/dashboard/annotation_policy_spec.rb'
- - 'spec/policies/namespaces/project_namespace_policy_spec.rb'
- 'spec/policies/namespaces/user_namespace_policy_spec.rb'
- - 'spec/policies/note_policy_spec.rb'
- 'spec/policies/personal_access_token_policy_spec.rb'
- 'spec/policies/personal_snippet_policy_spec.rb'
- 'spec/policies/project_policy_spec.rb'
@@ -2863,12 +2553,9 @@ RSpec/ContextWording:
- 'spec/presenters/clusters/cluster_presenter_spec.rb'
- 'spec/presenters/commit_status_presenter_spec.rb'
- 'spec/presenters/gitlab/blame_presenter_spec.rb'
- - 'spec/presenters/group_member_presenter_spec.rb'
- 'spec/presenters/merge_request_presenter_spec.rb'
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
- 'spec/presenters/packages/npm/package_presenter_spec.rb'
- - 'spec/presenters/packages/nuget/service_index_presenter_spec.rb'
- - 'spec/presenters/project_member_presenter_spec.rb'
- 'spec/presenters/project_presenter_spec.rb'
- 'spec/presenters/projects/import_export/project_export_presenter_spec.rb'
- 'spec/presenters/projects/security/configuration_presenter_spec.rb'
@@ -2888,10 +2575,8 @@ RSpec/ContextWording:
- 'spec/requests/api/appearance_spec.rb'
- 'spec/requests/api/applications_spec.rb'
- 'spec/requests/api/avatar_spec.rb'
- - 'spec/requests/api/award_emoji_spec.rb'
- 'spec/requests/api/badges_spec.rb'
- 'spec/requests/api/branches_spec.rb'
- - 'spec/requests/api/broadcast_messages_spec.rb'
- 'spec/requests/api/bulk_imports_spec.rb'
- 'spec/requests/api/ci/job_artifacts_spec.rb'
- 'spec/requests/api/ci/jobs_spec.rb'
@@ -2919,10 +2604,8 @@ RSpec/ContextWording:
- 'spec/requests/api/environments_spec.rb'
- 'spec/requests/api/error_tracking/collector_spec.rb'
- 'spec/requests/api/error_tracking/project_settings_spec.rb'
- - 'spec/requests/api/events_spec.rb'
- 'spec/requests/api/files_spec.rb'
- 'spec/requests/api/generic_packages_spec.rb'
- - 'spec/requests/api/go_proxy_spec.rb'
- 'spec/requests/api/graphql/ci/runner_spec.rb'
- 'spec/requests/api/graphql/ci/runners_spec.rb'
- 'spec/requests/api/graphql/container_repository/container_repository_details_spec.rb'
@@ -2933,6 +2616,7 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/group/group_members_spec.rb'
- 'spec/requests/api/graphql/group/issues_spec.rb'
- 'spec/requests/api/graphql/group/milestones_spec.rb'
+ - 'spec/requests/api/graphql/issue/issue_spec.rb'
- 'spec/requests/api/graphql/metadata_query_spec.rb'
- 'spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb'
- 'spec/requests/api/graphql/metrics/dashboard_query_spec.rb'
@@ -2942,7 +2626,6 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/mutations/branches/create_spec.rb'
- 'spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb'
- 'spec/requests/api/graphql/mutations/commits/create_spec.rb'
- - 'spec/requests/api/graphql/mutations/container_expiration_policy/update_spec.rb'
- 'spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb'
- 'spec/requests/api/graphql/mutations/design_management/delete_spec.rb'
- 'spec/requests/api/graphql/mutations/design_management/move_spec.rb'
@@ -2951,9 +2634,7 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/mutations/issues/update_spec.rb'
- 'spec/requests/api/graphql/mutations/merge_requests/create_spec.rb'
- 'spec/requests/api/graphql/mutations/merge_requests/request_attention_spec.rb'
- - 'spec/requests/api/graphql/mutations/namespace/package_settings/update_spec.rb'
- 'spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb'
- - 'spec/requests/api/graphql/mutations/notes/create/note_spec.rb'
- 'spec/requests/api/graphql/mutations/releases/create_spec.rb'
- 'spec/requests/api/graphql/mutations/releases/delete_spec.rb'
- 'spec/requests/api/graphql/mutations/releases/update_spec.rb'
@@ -2963,10 +2644,11 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/mutations/work_items/create_spec.rb'
- 'spec/requests/api/graphql/mutations/work_items/delete_task_spec.rb'
- 'spec/requests/api/graphql/mutations/work_items/update_spec.rb'
+ - 'spec/requests/api/graphql/mutations/work_items/update_task_spec.rb'
+ - 'spec/requests/api/graphql/mutations/work_items/update_widgets_spec.rb'
- 'spec/requests/api/graphql/namespace_query_spec.rb'
- 'spec/requests/api/graphql/packages/maven_spec.rb'
- 'spec/requests/api/graphql/packages/package_spec.rb'
- - 'spec/requests/api/graphql/project/alert_management/alert/notes_spec.rb'
- 'spec/requests/api/graphql/project/alert_management/alerts_spec.rb'
- 'spec/requests/api/graphql/project/cluster_agents_spec.rb'
- 'spec/requests/api/graphql/project/container_repositories_spec.rb'
@@ -2981,7 +2663,6 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/project/pipeline_spec.rb'
- 'spec/requests/api/graphql/project/project_members_spec.rb'
- 'spec/requests/api/graphql/project/release_spec.rb'
- - 'spec/requests/api/graphql/project/repository_spec.rb'
- 'spec/requests/api/graphql/project/terraform/state_spec.rb'
- 'spec/requests/api/graphql/project/terraform/states_spec.rb'
- 'spec/requests/api/graphql/project_query_spec.rb'
@@ -2990,7 +2671,6 @@ RSpec/ContextWording:
- 'spec/requests/api/graphql/user_query_spec.rb'
- 'spec/requests/api/graphql/users_spec.rb'
- 'spec/requests/api/graphql_spec.rb'
- - 'spec/requests/api/group_avatar_spec.rb'
- 'spec/requests/api/group_clusters_spec.rb'
- 'spec/requests/api/group_labels_spec.rb'
- 'spec/requests/api/group_packages_spec.rb'
@@ -2998,6 +2678,7 @@ RSpec/ContextWording:
- 'spec/requests/api/groups_spec.rb'
- 'spec/requests/api/helm_packages_spec.rb'
- 'spec/requests/api/helpers_spec.rb'
+ - 'spec/requests/api/integrations/jira_connect/subscriptions_spec.rb'
- 'spec/requests/api/integrations_spec.rb'
- 'spec/requests/api/internal/base_spec.rb'
- 'spec/requests/api/internal/container_registry/migration_spec.rb'
@@ -3005,6 +2686,7 @@ RSpec/ContextWording:
- 'spec/requests/api/internal/lfs_spec.rb'
- 'spec/requests/api/internal/mail_room_spec.rb'
- 'spec/requests/api/internal/pages_spec.rb'
+ - 'spec/requests/api/internal/workhorse_spec.rb'
- 'spec/requests/api/invitations_spec.rb'
- 'spec/requests/api/issue_links_spec.rb'
- 'spec/requests/api/issues/get_group_issues_spec.rb'
@@ -3013,11 +2695,9 @@ RSpec/ContextWording:
- 'spec/requests/api/issues/post_projects_issues_spec.rb'
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/keys_spec.rb'
- - 'spec/requests/api/labels_spec.rb'
- 'spec/requests/api/lint_spec.rb'
- 'spec/requests/api/maven_packages_spec.rb'
- 'spec/requests/api/members_spec.rb'
- - 'spec/requests/api/merge_request_approvals_spec.rb'
- 'spec/requests/api/merge_request_diffs_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/metrics/user_starred_dashboards_spec.rb'
@@ -3034,8 +2714,6 @@ RSpec/ContextWording:
- 'spec/requests/api/project_container_repositories_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_packages_spec.rb'
- 'spec/requests/api/project_snippets_spec.rb'
- 'spec/requests/api/projects_spec.rb'
@@ -3046,6 +2724,7 @@ RSpec/ContextWording:
- 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/api/search_spec.rb'
- 'spec/requests/api/settings_spec.rb'
+ - 'spec/requests/api/snippets_spec.rb'
- 'spec/requests/api/tags_spec.rb'
- 'spec/requests/api/task_completion_status_spec.rb'
- 'spec/requests/api/templates_spec.rb'
@@ -3053,7 +2732,6 @@ RSpec/ContextWording:
- 'spec/requests/api/terraform/state_spec.rb'
- 'spec/requests/api/terraform/state_version_spec.rb'
- 'spec/requests/api/todos_spec.rb'
- - 'spec/requests/api/topics_spec.rb'
- 'spec/requests/api/usage_data_spec.rb'
- 'spec/requests/api/user_counts_spec.rb'
- 'spec/requests/api/users_preferences_spec.rb'
@@ -3066,31 +2744,32 @@ RSpec/ContextWording:
- 'spec/requests/groups/clusters/integrations_controller_spec.rb'
- 'spec/requests/groups/crm/contacts_controller_spec.rb'
- 'spec/requests/groups/crm/organizations_controller_spec.rb'
- - 'spec/requests/groups/email_campaigns_controller_spec.rb'
- 'spec/requests/groups/milestones_controller_spec.rb'
- 'spec/requests/groups/settings/access_tokens_controller_spec.rb'
- 'spec/requests/groups_controller_spec.rb'
- 'spec/requests/health_controller_spec.rb'
- 'spec/requests/ide_controller_spec.rb'
- 'spec/requests/jira_connect/installations_controller_spec.rb'
+ - 'spec/requests/jira_connect/oauth_application_ids_controller_spec.rb'
- 'spec/requests/jira_routing_spec.rb'
- 'spec/requests/jwt_controller_spec.rb'
- 'spec/requests/lfs_http_spec.rb'
+ - 'spec/requests/mailgun/webhooks_controller_spec.rb'
- 'spec/requests/oauth_tokens_spec.rb'
- 'spec/requests/openid_connect_spec.rb'
- 'spec/requests/product_analytics/collector_app_attack_spec.rb'
- 'spec/requests/product_analytics/collector_app_spec.rb'
- 'spec/requests/projects/clusters/integrations_controller_spec.rb'
- 'spec/requests/projects/commits_controller_spec.rb'
+ - 'spec/requests/projects/google_cloud/configuration_controller_spec.rb'
+ - 'spec/requests/projects/google_cloud/databases_controller_spec.rb'
- 'spec/requests/projects/google_cloud/deployments_controller_spec.rb'
- 'spec/requests/projects/google_cloud/gcp_regions_controller_spec.rb'
- 'spec/requests/projects/google_cloud/service_accounts_controller_spec.rb'
- - 'spec/requests/projects/google_cloud_controller_spec.rb'
- 'spec/requests/projects/issues/discussions_spec.rb'
- 'spec/requests/projects/issues_controller_spec.rb'
- 'spec/requests/projects/merge_requests_controller_spec.rb'
- 'spec/requests/projects/merge_requests_discussions_spec.rb'
- - 'spec/requests/projects/merge_requests_spec.rb'
- 'spec/requests/projects/metrics/dashboards/builder_spec.rb'
- 'spec/requests/projects/releases_controller_spec.rb'
- 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
@@ -3098,13 +2777,11 @@ RSpec/ContextWording:
- 'spec/requests/projects/usage_quotas_spec.rb'
- 'spec/requests/projects_controller_spec.rb'
- 'spec/requests/rack_attack_global_spec.rb'
- - 'spec/requests/search_controller_spec.rb'
- 'spec/requests/sessions_spec.rb'
- 'spec/requests/users_controller_spec.rb'
- 'spec/routing/git_http_routing_spec.rb'
- 'spec/routing/group_routing_spec.rb'
- 'spec/routing/project_routing_spec.rb'
- - 'spec/rubocop/cop/gitlab/avoid_feature_category_not_owned_spec.rb'
- 'spec/rubocop/cop/gitlab/change_timezone_spec.rb'
- 'spec/rubocop/cop/gitlab/const_get_inherit_false_spec.rb'
- 'spec/rubocop/cop/gitlab/duplicate_spec_location_spec.rb'
@@ -3116,7 +2793,6 @@ RSpec/ContextWording:
- 'spec/rubocop/cop/graphql/old_types_spec.rb'
- 'spec/rubocop/cop/lint/last_keyword_argument_spec.rb'
- 'spec/rubocop/cop/migration/add_index_spec.rb'
- - 'spec/rubocop/cop/migration/add_limit_to_text_columns_spec.rb'
- 'spec/rubocop/cop/migration/background_migration_record_spec.rb'
- 'spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb'
- 'spec/rubocop/cop/migration/migration_record_spec.rb'
@@ -3127,45 +2803,31 @@ RSpec/ContextWording:
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/rubocop/cop/migration/versioned_migration_class_spec.rb'
- 'spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb'
- - 'spec/rubocop/cop/performance/readlines_each_spec.rb'
- 'spec/rubocop/cop/qa/ambiguous_page_object_name_spec.rb'
- 'spec/rubocop/cop/qa/element_with_pattern_spec.rb'
- 'spec/rubocop/cop/qa/selector_usage_spec.rb'
- 'spec/rubocop/cop/rspec/factory_bot/inline_association_spec.rb'
- 'spec/scripts/pipeline_test_report_builder_spec.rb'
- 'spec/serializers/analytics_build_entity_spec.rb'
- - 'spec/serializers/blob_entity_spec.rb'
- 'spec/serializers/board_serializer_spec.rb'
- - 'spec/serializers/ci/job_serializer_spec.rb'
- 'spec/serializers/ci/pipeline_entity_spec.rb'
- 'spec/serializers/cluster_application_entity_spec.rb'
- - 'spec/serializers/cluster_entity_spec.rb'
- - 'spec/serializers/context_commits_diff_entity_spec.rb'
+ - 'spec/serializers/deploy_keys/basic_deploy_key_entity_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/diffs_entity_spec.rb'
- - 'spec/serializers/diffs_metadata_entity_spec.rb'
- 'spec/serializers/environment_entity_spec.rb'
- 'spec/serializers/environment_serializer_spec.rb'
- 'spec/serializers/group_child_entity_spec.rb'
- - 'spec/serializers/group_child_serializer_spec.rb'
- 'spec/serializers/group_link/group_group_link_entity_spec.rb'
- - 'spec/serializers/integrations/project_entity_spec.rb'
- 'spec/serializers/issue_serializer_spec.rb'
- - 'spec/serializers/issue_sidebar_basic_entity_spec.rb'
- 'spec/serializers/member_entity_spec.rb'
- 'spec/serializers/member_serializer_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_serializer_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/paginated_diff_entity_spec.rb'
- 'spec/serializers/pipeline_details_entity_spec.rb'
- - 'spec/serializers/stage_entity_spec.rb'
- 'spec/serializers/user_serializer_spec.rb'
- 'spec/services/access_token_validation_service_spec.rb'
- 'spec/services/alert_management/alerts/update_service_spec.rb'
@@ -3178,7 +2840,6 @@ RSpec/ContextWording:
- 'spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
- 'spec/services/boards/issues/list_service_spec.rb'
- 'spec/services/boards/issues/move_service_spec.rb'
- - 'spec/services/boards/lists/update_service_spec.rb'
- 'spec/services/branches/delete_merged_service_spec.rb'
- 'spec/services/branches/validate_new_service_spec.rb'
- 'spec/services/bulk_create_integration_service_spec.rb'
@@ -3186,7 +2847,6 @@ RSpec/ContextWording:
- 'spec/services/ci/after_requeue_job_service_spec.rb'
- 'spec/services/ci/append_build_trace_service_spec.rb'
- 'spec/services/ci/archive_trace_service_spec.rb'
- - 'spec/services/ci/build_report_result_service_spec.rb'
- 'spec/services/ci/compare_test_reports_service_spec.rb'
- 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
- 'spec/services/ci/create_pipeline_service/cache_spec.rb'
@@ -3209,14 +2869,11 @@ RSpec/ContextWording:
- 'spec/services/ci/job_artifacts/update_unknown_locked_status_service_spec.rb'
- 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb'
- 'spec/services/ci/pipelines/add_job_service_spec.rb'
- - 'spec/services/ci/play_build_service_spec.rb'
- 'spec/services/ci/prepare_build_service_spec.rb'
- - 'spec/services/ci/process_sync_events_service_spec.rb'
- 'spec/services/ci/prometheus_metrics/observe_histograms_service_spec.rb'
- 'spec/services/ci/register_job_service_spec.rb'
- 'spec/services/ci/retry_job_service_spec.rb'
- - 'spec/services/ci/stuck_builds/drop_pending_service_spec.rb'
- - 'spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb'
+ - 'spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb'
- 'spec/services/ci/update_build_queue_service_spec.rb'
- 'spec/services/ci/update_pending_build_service_spec.rb'
- 'spec/services/clusters/agent_tokens/track_usage_service_spec.rb'
@@ -3253,18 +2910,16 @@ RSpec/ContextWording:
- 'spec/services/dependency_proxy/find_cached_manifest_service_spec.rb'
- 'spec/services/dependency_proxy/head_manifest_service_spec.rb'
- 'spec/services/dependency_proxy/request_token_service_spec.rb'
- - 'spec/services/deployments/older_deployments_drop_service_spec.rb'
- 'spec/services/deployments/update_environment_service_spec.rb'
- 'spec/services/design_management/delete_designs_service_spec.rb'
- 'spec/services/design_management/generate_image_versions_service_spec.rb'
- 'spec/services/design_management/move_designs_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_position_service_spec.rb'
- - 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
- - 'spec/services/discussions/resolve_service_spec.rb'
- 'spec/services/draft_notes/create_service_spec.rb'
- 'spec/services/draft_notes/destroy_service_spec.rb'
- 'spec/services/draft_notes/publish_service_spec.rb'
- 'spec/services/environments/schedule_to_delete_review_apps_service_spec.rb'
+ - 'spec/services/environments/stop_service_spec.rb'
- 'spec/services/error_tracking/collect_error_service_spec.rb'
- 'spec/services/error_tracking/list_issues_service_spec.rb'
- 'spec/services/error_tracking/list_projects_service_spec.rb'
@@ -3295,12 +2950,13 @@ RSpec/ContextWording:
- 'spec/services/ide/schemas_config_service_spec.rb'
- 'spec/services/ide/terminal_config_service_spec.rb'
- 'spec/services/import/bitbucket_server_service_spec.rb'
+ - 'spec/services/import/fogbugz_service_spec.rb'
- 'spec/services/import/github_service_spec.rb'
- 'spec/services/import/gitlab_projects/file_acquisition_strategies/remote_file_s3_spec.rb'
- 'spec/services/import/gitlab_projects/file_acquisition_strategies/remote_file_spec.rb'
- 'spec/services/incident_management/incidents/create_service_spec.rb'
- 'spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb'
- - 'spec/services/integrations/propagate_service_spec.rb'
+ - 'spec/services/incident_management/timeline_events/destroy_service_spec.rb'
- 'spec/services/integrations/test/project_service_spec.rb'
- 'spec/services/issuable/common_system_notes_service_spec.rb'
- 'spec/services/issue_links/list_service_spec.rb'
@@ -3317,17 +2973,17 @@ RSpec/ContextWording:
- 'spec/services/issues/set_crm_contacts_service_spec.rb'
- 'spec/services/issues/update_service_spec.rb'
- 'spec/services/issues/zoom_link_service_spec.rb'
- - 'spec/services/jira_connect_installations/destroy_service_spec.rb'
- 'spec/services/jira_connect_subscriptions/create_service_spec.rb'
- 'spec/services/keys/create_service_spec.rb'
- 'spec/services/keys/expiry_notification_service_spec.rb'
- - 'spec/services/labels/create_service_spec.rb'
- - 'spec/services/lfs/file_transformer_spec.rb'
- 'spec/services/lfs/locks_finder_service_spec.rb'
- 'spec/services/lfs/push_service_spec.rb'
- 'spec/services/lfs/unlock_file_service_spec.rb'
- 'spec/services/members/approve_access_request_service_spec.rb'
- 'spec/services/members/destroy_service_spec.rb'
+ - 'spec/services/members/groups/creator_service_spec.rb'
+ - 'spec/services/members/projects/creator_service_spec.rb'
+ - 'spec/services/members/update_service_spec.rb'
- 'spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb'
- 'spec/services/merge_requests/after_create_service_spec.rb'
- 'spec/services/merge_requests/approval_service_spec.rb'
@@ -3351,7 +3007,6 @@ RSpec/ContextWording:
- 'spec/services/merge_requests/refresh_service_spec.rb'
- 'spec/services/merge_requests/reload_diffs_service_spec.rb'
- 'spec/services/merge_requests/reopen_service_spec.rb'
- - 'spec/services/merge_requests/retarget_chain_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_assignees_service_spec.rb'
@@ -3379,7 +3034,6 @@ RSpec/ContextWording:
- 'spec/services/milestones/promote_service_spec.rb'
- 'spec/services/milestones/update_service_spec.rb'
- 'spec/services/namespace_settings/update_service_spec.rb'
- - 'spec/services/namespaces/in_product_marketing_emails_service_spec.rb'
- 'spec/services/note_summary_spec.rb'
- 'spec/services/notes/build_service_spec.rb'
- 'spec/services/notes/copy_service_spec.rb'
@@ -3388,12 +3042,11 @@ RSpec/ContextWording:
- 'spec/services/notes/quick_actions_service_spec.rb'
- 'spec/services/notes/update_service_spec.rb'
- 'spec/services/notification_recipients/builder/default_spec.rb'
- - 'spec/services/notification_recipients/builder/new_note_spec.rb'
- 'spec/services/notification_service_spec.rb'
+ - 'spec/services/packages/cleanup/execute_policy_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/conan/create_package_service_spec.rb'
- - 'spec/services/packages/create_event_service_spec.rb'
- 'spec/services/packages/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'
@@ -3404,18 +3057,15 @@ RSpec/ContextWording:
- 'spec/services/packages/helm/process_file_service_spec.rb'
- 'spec/services/packages/maven/create_package_service_spec.rb'
- 'spec/services/packages/maven/find_or_create_package_service_spec.rb'
- - 'spec/services/packages/maven/metadata/create_plugins_xml_service_spec.rb'
- 'spec/services/packages/maven/metadata/create_versions_xml_service_spec.rb'
- 'spec/services/packages/maven/metadata/sync_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/metadata_extraction_service_spec.rb'
- 'spec/services/packages/nuget/search_service_spec.rb'
- 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
- 'spec/services/packages/rubygems/dependency_resolver_service_spec.rb'
- 'spec/services/packages/rubygems/process_gem_service_spec.rb'
- 'spec/services/packages/terraform_module/create_package_service_spec.rb'
- - 'spec/services/packages/update_tags_service_spec.rb'
- 'spec/services/pages/zip_directory_service_spec.rb'
- 'spec/services/personal_access_tokens/create_service_spec.rb'
- 'spec/services/personal_access_tokens/revoke_service_spec.rb'
@@ -3450,7 +3100,6 @@ RSpec/ContextWording:
- 'spec/services/projects/record_target_platforms_service_spec.rb'
- 'spec/services/projects/transfer_service_spec.rb'
- 'spec/services/projects/unlink_fork_service_spec.rb'
- - 'spec/services/projects/update_pages_service_spec.rb'
- 'spec/services/projects/update_remote_mirror_service_spec.rb'
- 'spec/services/projects/update_repository_storage_service_spec.rb'
- 'spec/services/projects/update_service_spec.rb'
@@ -3458,10 +3107,8 @@ RSpec/ContextWording:
- 'spec/services/prometheus/proxy_variable_substitution_service_spec.rb'
- 'spec/services/protected_tags/create_service_spec.rb'
- 'spec/services/quick_actions/interpret_service_spec.rb'
- - 'spec/services/quick_actions/target_service_spec.rb'
- 'spec/services/releases/create_service_spec.rb'
- 'spec/services/releases/update_service_spec.rb'
- - 'spec/services/repositories/destroy_service_spec.rb'
- 'spec/services/resource_access_tokens/create_service_spec.rb'
- 'spec/services/search/global_service_spec.rb'
- 'spec/services/search/group_service_spec.rb'
@@ -3480,18 +3127,18 @@ RSpec/ContextWording:
- 'spec/services/submodules/update_service_spec.rb'
- 'spec/services/suggestions/apply_service_spec.rb'
- 'spec/services/suggestions/create_service_spec.rb'
- - 'spec/services/system_notes/commit_service_spec.rb'
- 'spec/services/system_notes/design_management_service_spec.rb'
- 'spec/services/system_notes/issuables_service_spec.rb'
- 'spec/services/system_notes/merge_requests_service_spec.rb'
- 'spec/services/tasks_to_be_done/base_service_spec.rb'
- 'spec/services/terraform/remote_state_handler_spec.rb'
+ - 'spec/services/terraform/states/destroy_service_spec.rb'
+ - 'spec/services/terraform/states/trigger_destroy_service_spec.rb'
- 'spec/services/test_hooks/project_service_spec.rb'
- 'spec/services/test_hooks/system_service_spec.rb'
- 'spec/services/todo_service_spec.rb'
- 'spec/services/todos/destroy/entity_leave_service_spec.rb'
- 'spec/services/two_factor/destroy_service_spec.rb'
- - 'spec/services/upload_service_spec.rb'
- 'spec/services/user_preferences/update_service_spec.rb'
- 'spec/services/users/activity_service_spec.rb'
- 'spec/services/users/approve_service_spec.rb'
@@ -3514,10 +3161,9 @@ RSpec/ContextWording:
- 'spec/services/wiki_pages/event_create_service_spec.rb'
- 'spec/services/wikis/create_attachment_service_spec.rb'
- 'spec/services/work_items/create_service_spec.rb'
- - 'spec/services/x509_certificate_revoke_service_spec.rb'
+ - 'spec/services/work_items/parent_links/create_service_spec.rb'
- 'spec/support/banzai/reference_filter_shared_examples.rb'
- 'spec/support/prometheus/additional_metrics_shared_examples.rb'
- - 'spec/support/redis/redis_new_instance_shared_examples.rb'
- 'spec/support/redis/redis_shared_examples.rb'
- 'spec/support/services/clusters/create_service_shared.rb'
- 'spec/support/services/deploy_token_shared_examples.rb'
@@ -3546,6 +3192,7 @@ RSpec/ContextWording:
- 'spec/support/shared_contexts/finders/merge_requests_finder_shared_contexts.rb'
- 'spec/support/shared_contexts/finders/packages/npm/package_finder_shared_context.rb'
- 'spec/support/shared_contexts/finders/users_finder_shared_contexts.rb'
+ - 'spec/support/shared_contexts/finders/work_items_finder_shared_contexts.rb'
- 'spec/support/shared_contexts/fixtures/analytics_shared_context.rb'
- 'spec/support/shared_contexts/graphql/requests/packages_shared_context.rb'
- 'spec/support/shared_contexts/graphql/resolvers/runners_resolver_shared_context.rb'
@@ -3569,6 +3216,7 @@ RSpec/ContextWording:
- 'spec/support/shared_contexts/policies/group_policy_shared_context.rb'
- 'spec/support/shared_contexts/policies/project_policy_shared_context.rb'
- 'spec/support/shared_contexts/policies/project_policy_table_shared_context.rb'
+ - 'spec/support/shared_contexts/project_features_shared_context.rb'
- 'spec/support/shared_contexts/prometheus/alert_shared_context.rb'
- 'spec/support/shared_contexts/rack_attack_shared_context.rb'
- 'spec/support/shared_contexts/read_ci_configuration_shared_context.rb'
@@ -3592,18 +3240,13 @@ RSpec/ContextWording:
- 'spec/support/shared_contexts/unique_ip_check_shared_context.rb'
- 'spec/support/shared_contexts/upload_type_check_shared_context.rb'
- 'spec/support/shared_contexts/url_shared_context.rb'
- - 'spec/support/shared_examples/banzai/filters/inline_embeds_shared_examples.rb'
- 'spec/support/shared_examples/banzai/filters/inline_metrics_redactor_shared_examples.rb'
- 'spec/support/shared_examples/boards/multiple_issue_boards_shared_examples.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/hotlink_interceptor_shared_examples.rb'
- 'spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/milestone_tabs_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb'
- 'spec/support/shared_examples/controllers/snippet_blob_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/variables_shared_examples.rb'
- 'spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb'
- 'spec/support/shared_examples/csp.rb'
- 'spec/support/shared_examples/features/access_tokens_shared_examples.rb'
@@ -3622,6 +3265,7 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb'
- 'spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb'
- 'spec/support/shared_examples/finders/assignees_filter_shared_examples.rb'
+ - 'spec/support/shared_examples/finders/issues_finder_shared_examples.rb'
- 'spec/support/shared_examples/finders/packages/debian/distributions_finder_shared_examples.rb'
- 'spec/support/shared_examples/finders/packages_shared_examples.rb'
- 'spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb'
@@ -3632,14 +3276,13 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb'
- 'spec/support/shared_examples/graphql/resolvers/packages_resolvers_shared_examples.rb'
- 'spec/support/shared_examples/graphql/resolves_issuable_shared_examples.rb'
- - 'spec/support/shared_examples/graphql/spam_protection_shared_examples.rb'
+ - 'spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb'
- 'spec/support/shared_examples/helm_commands_shared_examples.rb'
- 'spec/support/shared_examples/helpers/issuable_description_templates_shared_examples.rb'
- 'spec/support/shared_examples/lib/api/internal_base_shared_examples.rb'
- 'spec/support/shared_examples/lib/cache_helpers_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- - 'spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb'
- - 'spec/support/shared_examples/lib/gitlab/import_export/relation_factory_shared_examples.rb'
+ - 'spec/support/shared_examples/lib/gitlab/database/reestablished_connection_stack_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/search_confidential_filter_shared_examples.rb'
@@ -3649,7 +3292,6 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb'
- 'spec/support/shared_examples/models/application_setting_shared_examples.rb'
- 'spec/support/shared_examples/models/chat_integration_shared_examples.rb'
- - 'spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb'
- 'spec/support/shared_examples/models/cluster_application_status_shared_examples.rb'
- 'spec/support/shared_examples/models/cluster_application_version_shared_examples.rb'
- 'spec/support/shared_examples/models/clusters/prometheus_client_shared.rb'
@@ -3657,7 +3299,6 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/models/concerns/composite_id_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb'
- - 'spec/support/shared_examples/models/concerns/issuable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/timebox_shared_examples.rb'
- 'spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb'
@@ -3680,7 +3321,6 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/debian_common_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/discussions_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/graphql/mutations/boards/update_list_shared_examples.rb'
@@ -3688,6 +3328,7 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_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/hooks_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/issues_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/multiple_and_scoped_issue_boards_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/notes_shared_examples.rb'
@@ -3696,17 +3337,12 @@ RSpec/ContextWording:
- '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/read_user_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/repositories_shared_context.rb'
- 'spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/status_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb'
- 'spec/support/shared_examples/requests/clusters/certificate_based_clusters_feature_flag_shared_examples.rb'
- 'spec/support/shared_examples/requests/lfs_http_shared_examples.rb'
- 'spec/support/shared_examples/requests/releases_shared_examples.rb'
- 'spec/support/shared_examples/routing/git_http_routing_shared_examples.rb'
- - 'spec/support/shared_examples/sends_git_audit_streaming_event_shared_examples.rb'
- 'spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb'
- 'spec/support/shared_examples/serializers/note_entity_shared_examples.rb'
- 'spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb'
@@ -3726,42 +3362,36 @@ RSpec/ContextWording:
- 'spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb'
- 'spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb'
- 'spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/updating_mentions_shared_examples.rb'
- 'spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb'
- 'spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb'
- 'spec/support/shared_examples/services/wikis/create_attachment_service_shared_examples.rb'
- - 'spec/support/shared_examples/snippet_blob_shared_examples.rb'
- 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
- 'spec/support/shared_examples/validators/url_validator_shared_examples.rb'
- 'spec/support/shared_examples/views/pipeline_status_changes_email.rb'
+ - 'spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb'
- 'spec/support/shared_examples/workers/concerns/git_garbage_collect_methods_shared_examples.rb'
- 'spec/support/shared_examples/workers/project_export_shared_examples.rb'
- - 'spec/support_specs/database/multiple_databases_spec.rb'
- 'spec/support_specs/helpers/migrations_helpers_spec.rb'
- 'spec/support_specs/helpers/stub_feature_flags_spec.rb'
+ - 'spec/support_specs/helpers/stub_method_calls_spec.rb'
- 'spec/tasks/cache/clear/redis_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- 'spec/tasks/gettext_rake_spec.rb'
- - 'spec/tasks/gitlab/artifacts/migrate_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'
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/tasks/gitlab/dependency_proxy/migrate_rake_spec.rb'
- 'spec/tasks/gitlab/gitaly_rake_spec.rb'
- 'spec/tasks/gitlab/lfs/migrate_rake_spec.rb'
- 'spec/tasks/gitlab/packages/migrate_rake_spec.rb'
- - 'spec/tasks/gitlab/pages_rake_spec.rb'
- '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/uploads/migrate_rake_spec.rb'
- - 'spec/tasks/gitlab/user_management_rake_spec.rb'
- 'spec/tasks/gitlab/workhorse_rake_spec.rb'
- - 'spec/tooling/danger/feature_flag_spec.rb'
- 'spec/tooling/danger/project_helper_spec.rb'
- 'spec/tooling/lib/tooling/parallel_rspec_runner_spec.rb'
- - 'spec/tooling/rspec_flaky/listener_spec.rb'
- 'spec/uploaders/attachment_uploader_spec.rb'
- 'spec/uploaders/avatar_uploader_spec.rb'
- 'spec/uploaders/content_type_whitelist_spec.rb'
@@ -3782,7 +3412,6 @@ RSpec/ContextWording:
- 'spec/uploaders/packages/package_file_uploader_spec.rb'
- 'spec/uploaders/personal_file_uploader_spec.rb'
- 'spec/uploaders/terraform/state_uploader_spec.rb'
- - 'spec/uploaders/workers/object_storage/background_move_worker_spec.rb'
- 'spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb'
- 'spec/validators/addressable_url_validator_spec.rb'
- 'spec/validators/array_members_validator_spec.rb'
@@ -3804,7 +3433,6 @@ RSpec/ContextWording:
- 'spec/views/layouts/_header_search.html.haml_spec.rb'
- 'spec/views/layouts/application.html.haml_spec.rb'
- 'spec/views/layouts/header/_new_dropdown.haml_spec.rb'
- - 'spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb'
- 'spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb'
- 'spec/views/notify/changed_milestone_email.html.haml_spec.rb'
- 'spec/views/profiles/keys/_key.html.haml_spec.rb'
@@ -3817,15 +3445,13 @@ RSpec/ContextWording:
- 'spec/views/projects/hooks/edit.html.haml_spec.rb'
- 'spec/views/projects/hooks/index.html.haml_spec.rb'
- 'spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb'
+ - 'spec/views/projects/settings/integrations/edit.html.haml_spec.rb'
- 'spec/views/projects/settings/operations/show.html.haml_spec.rb'
- 'spec/views/projects/tags/index.html.haml_spec.rb'
- - 'spec/views/projects/tree/show.html.haml_spec.rb'
- 'spec/views/search/_results.html.haml_spec.rb'
- 'spec/views/search/show.html.haml_spec.rb'
- - 'spec/views/shared/access_tokens/_table.html.haml_spec.rb'
- 'spec/views/shared/issuable/_sidebar.html.haml_spec.rb'
- 'spec/views/shared/milestones/_issuable.html.haml_spec.rb'
- - 'spec/views/shared/projects/_list.html.haml_spec.rb'
- 'spec/views/shared/snippets/_snippet.html.haml_spec.rb'
- 'spec/views/shared/wikis/_sidebar.html.haml_spec.rb'
- 'spec/workers/admin_email_worker_spec.rb'
@@ -3834,12 +3460,12 @@ RSpec/ContextWording:
- 'spec/workers/authorized_project_update/project_recalculate_per_user_worker_spec.rb'
- 'spec/workers/authorized_project_update/project_recalculate_worker_spec.rb'
- 'spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb'
- - 'spec/workers/bulk_imports/entity_worker_spec.rb'
- 'spec/workers/ci/build_prepare_worker_spec.rb'
- 'spec/workers/cleanup_container_repository_worker_spec.rb'
- 'spec/workers/cluster_update_app_worker_spec.rb'
- 'spec/workers/clusters/agents/delete_expired_events_worker_spec.rb'
- 'spec/workers/concerns/application_worker_spec.rb'
+ - 'spec/workers/concerns/waitable_worker_spec.rb'
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'
- 'spec/workers/container_expiration_policy_worker_spec.rb'
- 'spec/workers/container_registry/migration/enqueuer_worker_spec.rb'
@@ -3852,6 +3478,7 @@ RSpec/ContextWording:
- 'spec/workers/deployments/update_environment_worker_spec.rb'
- 'spec/workers/design_management/new_version_worker_spec.rb'
- 'spec/workers/every_sidekiq_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/integrations/create_external_cross_reference_worker_spec.rb'
@@ -3868,11 +3495,11 @@ RSpec/ContextWording:
- 'spec/workers/project_export_worker_spec.rb'
- 'spec/workers/projects/git_garbage_collect_worker_spec.rb'
- 'spec/workers/projects/post_creation_worker_spec.rb'
- - 'spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb'
- 'spec/workers/purge_dependency_proxy_cache_worker_spec.rb'
- 'spec/workers/remove_expired_group_links_worker_spec.rb'
- 'spec/workers/remove_expired_members_worker_spec.rb'
- 'spec/workers/remove_unaccepted_member_invites_worker_spec.rb'
- 'spec/workers/repository_fork_worker_spec.rb'
- 'spec/workers/stuck_merge_jobs_worker_spec.rb'
+ - 'spec/workers/terraform/states/destroy_worker_spec.rb'
- 'spec/workers/x509_issuer_crl_check_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/empty_line_after_hook.yml b/.rubocop_todo/rspec/empty_line_after_hook.yml
new file mode 100644
index 00000000000..4b1c4299b20
--- /dev/null
+++ b/.rubocop_todo/rspec/empty_line_after_hook.yml
@@ -0,0 +1,60 @@
+---
+# Cop supports --auto-correct.
+RSpec/EmptyLineAfterHook:
+ Exclude:
+ - 'ee/spec/controllers/projects/integrations/zentao/issues_controller_spec.rb'
+ - 'ee/spec/controllers/projects/push_rules_controller_spec.rb'
+ - 'ee/spec/features/groups/usage_quotas_spec.rb'
+ - 'ee/spec/features/issues/user_bulk_edits_issues_spec.rb'
+ - 'ee/spec/features/profiles/usage_quotas_spec.rb'
+ - 'ee/spec/lib/ee/api/entities/user_with_admin_spec.rb'
+ - 'ee/spec/lib/ee/audit/compliance_framework_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
+ - 'ee/spec/lib/gitlab/audit/auditor_spec.rb'
+ - 'ee/spec/lib/gitlab/proxy_spec.rb'
+ - 'ee/spec/lib/gitlab/vulnerabilities/container_scanning_vulnerability_spec.rb'
+ - 'ee/spec/models/ee/key_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'ee/spec/requests/api/users_spec.rb'
+ - 'ee/spec/requests/search_controller_spec.rb'
+ - 'ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb'
+ - 'ee/spec/services/ee/gpg_keys/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/two_factor/destroy_service_spec.rb'
+ - 'ee/spec/services/external_status_checks/update_service_spec.rb'
+ - 'ee/spec/services/group_saml/saml_group_links/destroy_service_spec.rb'
+ - 'ee/spec/services/groups/memberships/export_service_spec.rb'
+ - 'ee/spec/services/merge_requests/approval_service_spec.rb'
+ - 'ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
+ - 'qa/spec/specs/helpers/quarantine_spec.rb'
+ - 'qa/spec/support/page_error_checker_spec.rb'
+ - 'spec/controllers/admin/spam_logs_controller_spec.rb'
+ - 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/features/admin/admin_mode/login_spec.rb'
+ - 'spec/features/calendar_spec.rb'
+ - 'spec/features/projects/blobs/user_views_pipeline_editor_button_spec.rb'
+ - 'spec/features/users/overview_spec.rb'
+ - 'spec/lib/gitlab/auth/ldap/person_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/instrumentation_spec.rb'
+ - 'spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware_spec.rb'
+ - 'spec/mailers/emails/pages_domains_spec.rb'
+ - 'spec/models/application_record_spec.rb'
+ - 'spec/models/integrations/chat_message/merge_message_spec.rb'
+ - 'spec/models/integrations/microsoft_teams_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb'
+ - 'spec/requests/api/issues/issues_spec.rb'
+ - 'spec/requests/api/pages/internal_access_spec.rb'
+ - 'spec/requests/api/pages/private_access_spec.rb'
+ - 'spec/requests/api/pages/public_access_spec.rb'
+ - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
+ - 'spec/services/merge_requests/execute_approval_hooks_service_spec.rb'
+ - 'spec/services/notes/create_service_spec.rb'
+ - 'spec/services/notes/quick_actions_service_spec.rb'
+ - 'spec/services/projects/fork_service_spec.rb'
+ - 'spec/support/redis/redis_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/milestones_shared_examples.rb'
+ - 'spec/support/shared_examples/sends_git_audit_streaming_event_shared_examples.rb'
diff --git a/.rubocop_todo/rspec/expect_change.yml b/.rubocop_todo/rspec/expect_change.yml
index b08830bd5a3..03066626883 100644
--- a/.rubocop_todo/rspec/expect_change.yml
+++ b/.rubocop_todo/rspec/expect_change.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
RSpec/ExpectChange:
- # Offense count: 1707
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'ee/spec/controllers/admin/applications_controller_spec.rb'
- 'ee/spec/controllers/ee/groups_controller_spec.rb'
@@ -28,8 +25,10 @@ RSpec/ExpectChange:
- 'ee/spec/controllers/registrations/groups_controller_spec.rb'
- 'ee/spec/controllers/registrations/groups_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/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'
@@ -38,9 +37,9 @@ RSpec/ExpectChange:
- 'ee/spec/graphql/mutations/dast_site_profiles/delete_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_validations/revoke_spec.rb'
- 'ee/spec/helpers/paid_feature_callout_helper_spec.rb'
- - 'ee/spec/lib/analytics/group_activity_calculator_spec.rb'
- 'ee/spec/lib/audit/changes_spec.rb'
- 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb'
+ - 'ee/spec/lib/audit/group_merge_request_approval_setting_changes_auditor_spec.rb'
- 'ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb'
- 'ee/spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb'
- 'ee/spec/lib/bulk_imports/projects/pipelines/push_rule_pipeline_spec.rb'
@@ -52,14 +51,17 @@ RSpec/ExpectChange:
- 'ee/spec/lib/ee/audit/project_setting_changes_auditor_spec.rb'
- 'ee/spec/lib/ee/audit/protected_branches_changes_auditor_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/create_security_setting_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/delete_invalid_epic_issues_spec.rb'
- '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/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/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'
- 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
@@ -75,6 +77,7 @@ RSpec/ExpectChange:
- 'ee/spec/models/concerns/geo/verification_state_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'
- 'ee/spec/models/ee/event_spec.rb'
- 'ee/spec/models/ee/lfs_object_spec.rb'
- 'ee/spec/models/ee/merge_request_diff_spec.rb'
@@ -96,6 +99,7 @@ RSpec/ExpectChange:
- 'ee/spec/requests/api/epic_issues_spec.rb'
- 'ee/spec/requests/api/epics_spec.rb'
- 'ee/spec/requests/api/geo_spec.rb'
+ - 'ee/spec/requests/api/graphql/audit_events/streaming/headers/update_spec.rb'
- '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'
@@ -108,6 +112,7 @@ 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/work_items/update_spec.rb'
- 'ee/spec/requests/api/group_push_rule_spec.rb'
- 'ee/spec/requests/api/groups_spec.rb'
- 'ee/spec/requests/api/invitations_spec.rb'
@@ -121,6 +126,7 @@ RSpec/ExpectChange:
- '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/protected_environments_controller_spec.rb'
- 'ee/spec/requests/groups_controller_spec.rb'
- 'ee/spec/requests/smartcard_controller_spec.rb'
- 'ee/spec/services/app_sec/dast/scanner_profiles/destroy_service_spec.rb'
@@ -135,6 +141,9 @@ RSpec/ExpectChange:
- 'ee/spec/services/approval_rules/project_rule_destroy_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
+ - 'ee/spec/services/audit_events/streaming/headers/create_service_spec.rb'
+ - 'ee/spec/services/audit_events/streaming/headers/destroy_service_spec.rb'
+ - '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/epics/create_service_spec.rb'
@@ -146,14 +155,17 @@ RSpec/ExpectChange:
- '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/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'
- 'ee/spec/services/ee/groups/deploy_tokens/revoke_service_spec.rb'
- 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
- 'ee/spec/services/ee/issues/create_service_spec.rb'
- 'ee/spec/services/ee/issues/update_service_spec.rb'
+ - 'ee/spec/services/ee/keys/destroy_service_spec.rb'
- 'ee/spec/services/ee/members/create_service_spec.rb'
- 'ee/spec/services/ee/members/destroy_service_spec.rb'
- 'ee/spec/services/ee/members/invite_service_spec.rb'
@@ -163,6 +175,7 @@ RSpec/ExpectChange:
- 'ee/spec/services/ee/projects/deploy_tokens/create_service_spec.rb'
- 'ee/spec/services/ee/projects/deploy_tokens/destroy_service_spec.rb'
- 'ee/spec/services/ee/todos/destroy/entity_leave_service_spec.rb'
+ - 'ee/spec/services/ee/two_factor/destroy_service_spec.rb'
- 'ee/spec/services/ee/users/approve_service_spec.rb'
- 'ee/spec/services/ee/users/block_service_spec.rb'
- 'ee/spec/services/ee/users/reject_service_spec.rb'
@@ -196,8 +209,12 @@ RSpec/ExpectChange:
- 'ee/spec/services/keys/create_service_spec.rb'
- 'ee/spec/services/lfs/lock_file_service_spec.rb'
- 'ee/spec/services/lfs/unlock_file_service_spec.rb'
+ - '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/disable_deploy_key_service_spec.rb'
+ - 'ee/spec/services/projects/enable_deploy_key_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'
@@ -215,6 +232,7 @@ RSpec/ExpectChange:
- '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_scan_service_spec.rb'
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
- 'ee/spec/services/system_notes/epics_service_spec.rb'
@@ -235,16 +253,15 @@ RSpec/ExpectChange:
- 'ee/spec/support/shared_examples/services/update_issuable_health_status_shared_examples.rb'
- 'ee/spec/tasks/geo/git_rake_spec.rb'
- 'ee/spec/tasks/gitlab/elastic_rake_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/verification_state_backfill_service_spec.rb'
- 'ee/spec/workers/new_epic_worker_spec.rb'
- 'ee/spec/workers/store_security_reports_worker_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/users_controller_spec.rb'
- - 'spec/controllers/groups/clusters_controller_spec.rb'
- 'spec/controllers/groups/runners_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
- 'spec/controllers/import/bitbucket_controller_spec.rb'
@@ -254,7 +271,6 @@ 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/clusters_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
- 'spec/controllers/projects/issues_controller_spec.rb'
- 'spec/controllers/projects/merge_requests/creations_controller_spec.rb'
@@ -277,7 +293,6 @@ RSpec/ExpectChange:
- 'spec/features/groups/import_export/import_file_spec.rb'
- 'spec/features/groups_spec.rb'
- 'spec/features/invites_spec.rb'
- - 'spec/features/profiles/personal_access_tokens_spec.rb'
- 'spec/features/projects/import_export/import_file_spec.rb'
- 'spec/features/projects_spec.rb'
- 'spec/features/users/signup_spec.rb'
@@ -294,11 +309,13 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/auth/saml/identity_linker_spec.rb'
- 'spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_group_features_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb'
- 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
- 'spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb'
- 'spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb'
- 'spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb'
+ - '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/checks/matching_merge_request_spec.rb'
@@ -314,6 +331,7 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/config/entry/validatable_spec.rb'
- 'spec/lib/gitlab/daemon_spec.rb'
- 'spec/lib/gitlab/database/async_indexes/index_creator_spec.rb'
+ - 'spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_job_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
@@ -325,6 +343,8 @@ RSpec/ExpectChange:
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/fogbugz_import/importer_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'
- 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
- 'spec/lib/gitlab/hashed_storage/migrator_spec.rb'
- 'spec/lib/gitlab/import/merge_request_creator_spec.rb'
@@ -353,7 +373,9 @@ RSpec/ExpectChange:
- 'spec/migrations/20220124130028_dedup_runner_projects_spec.rb'
- '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/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'
@@ -363,6 +385,7 @@ RSpec/ExpectChange:
- 'spec/models/alert_management/alert_spec.rb'
- 'spec/models/analytics/cycle_analytics/aggregation_spec.rb'
- 'spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb'
+ - 'spec/models/application_setting_spec.rb'
- 'spec/models/broadcast_message_spec.rb'
- 'spec/models/chat_name_spec.rb'
- 'spec/models/ci/bridge_spec.rb'
@@ -375,8 +398,6 @@ RSpec/ExpectChange:
- 'spec/models/ci/ref_spec.rb'
- 'spec/models/ci/runner_spec.rb'
- 'spec/models/clusters/cluster_spec.rb'
- - 'spec/models/commit_signatures/gpg_signature_spec.rb'
- - 'spec/models/commit_signatures/x509_commit_signature_spec.rb'
- 'spec/models/commit_status_spec.rb'
- 'spec/models/concerns/atomic_internal_id_spec.rb'
- 'spec/models/concerns/bulk_insert_safe_spec.rb'
@@ -384,6 +405,7 @@ RSpec/ExpectChange:
- 'spec/models/concerns/delete_with_limit_spec.rb'
- 'spec/models/concerns/ignorable_columns_spec.rb'
- 'spec/models/concerns/issuable_spec.rb'
+ - 'spec/models/concerns/require_email_verification_spec.rb'
- 'spec/models/concerns/resolvable_discussion_spec.rb'
- 'spec/models/concerns/resolvable_note_spec.rb'
- 'spec/models/concerns/routable_spec.rb'
@@ -449,7 +471,6 @@ RSpec/ExpectChange:
- 'spec/requests/api/projects_spec.rb'
- 'spec/requests/api/releases_spec.rb'
- 'spec/requests/api/snippets_spec.rb'
- - 'spec/requests/api/system_hooks_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'
@@ -504,6 +525,7 @@ RSpec/ExpectChange:
- 'spec/services/issuable/common_system_notes_service_spec.rb'
- 'spec/services/issues/close_service_spec.rb'
- 'spec/services/issues/create_service_spec.rb'
+ - 'spec/services/issues/import_csv_service_spec.rb'
- 'spec/services/issues/move_service_spec.rb'
- 'spec/services/issues/reopen_service_spec.rb'
- 'spec/services/issues/update_service_spec.rb'
@@ -526,6 +548,7 @@ RSpec/ExpectChange:
- '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/helm/process_file_service_spec.rb'
- 'spec/services/packages/mark_package_for_destruction_service_spec.rb'
- 'spec/services/packages/update_package_file_service_spec.rb'
@@ -534,7 +557,6 @@ RSpec/ExpectChange:
- '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'
@@ -562,6 +584,7 @@ RSpec/ExpectChange:
- 'spec/services/todos/destroy/group_private_service_spec.rb'
- 'spec/services/todos/destroy/project_private_service_spec.rb'
- 'spec/services/todos/destroy/unauthorized_features_service_spec.rb'
+ - 'spec/services/uploads/destroy_service_spec.rb'
- 'spec/services/users/approve_service_spec.rb'
- 'spec/services/users/ban_service_spec.rb'
- 'spec/services/users/batch_status_cleaner_service_spec.rb'
@@ -571,7 +594,7 @@ RSpec/ExpectChange:
- 'spec/services/users/update_highest_member_role_service_spec.rb'
- 'spec/services/users/update_service_spec.rb'
- 'spec/services/verify_pages_domain_service_spec.rb'
- - 'spec/services/web_hooks/destroy_service_spec.rb'
+ - 'spec/services/work_items/parent_links/create_service_spec.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'
@@ -581,6 +604,7 @@ RSpec/ExpectChange:
- '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/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'
- 'spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb'
- 'spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb'
@@ -613,6 +637,7 @@ RSpec/ExpectChange:
- '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/new_issue_worker_spec.rb'
@@ -627,3 +652,4 @@ RSpec/ExpectChange:
- 'spec/workers/update_highest_role_worker_spec.rb'
- 'spec/workers/user_status_cleanup/batch_worker_spec.rb'
- 'spec/workers/users/create_statistics_worker_spec.rb'
+ - 'spec/workers/web_hooks/log_destroy_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/expect_in_hook.yml b/.rubocop_todo/rspec/expect_in_hook.yml
index cd73b76b14e..d138ea806f8 100644
--- a/.rubocop_todo/rspec/expect_in_hook.yml
+++ b/.rubocop_todo/rspec/expect_in_hook.yml
@@ -1,8 +1,5 @@
---
RSpec/ExpectInHook:
- # Offense count: 1074
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'ee/spec/controllers/ee/projects/merge_requests/content_controller_spec.rb'
- 'ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb'
@@ -13,11 +10,15 @@ RSpec/ExpectInHook:
- 'ee/spec/controllers/registrations/groups_projects_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'
- 'ee/spec/features/boards/new_issue_spec.rb'
- 'ee/spec/features/projects/feature_flags/user_creates_feature_flag_spec.rb'
- 'ee/spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb'
- 'ee/spec/features/projects/settings/ee/service_desk_setting_spec.rb'
- 'ee/spec/features/registrations/combined_registration_spec.rb'
+ - 'ee/spec/features/registrations/saas_user_registration_spec.rb'
- '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'
@@ -29,10 +30,14 @@ RSpec/ExpectInHook:
- 'ee/spec/graphql/mutations/gitlab_subscriptions/activate_spec.rb'
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
- 'ee/spec/helpers/ee/ci/runners_helper_spec.rb'
+ - 'ee/spec/helpers/ee/groups_helper_spec.rb'
+ - 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- 'ee/spec/helpers/ee/issues_helper_spec.rb'
+ - 'ee/spec/helpers/ee/projects/security/dast_configuration_helper_spec.rb'
- 'ee/spec/helpers/ee/welcome_helper_spec.rb'
- 'ee/spec/helpers/kerberos_spnego_helper_spec.rb'
- 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
+ - 'ee/spec/lib/ee/api/helpers/members_helpers_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- 'ee/spec/lib/ee/gitlab/gon_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/hook_data/user_builder_spec.rb'
@@ -44,7 +49,6 @@ RSpec/ExpectInHook:
- 'ee/spec/lib/gitlab/geo_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate_spec.rb'
- - 'ee/spec/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/mirror_spec.rb'
- 'ee/spec/lib/gitlab/sitemaps/generator_spec.rb'
- 'ee/spec/lib/gitlab/subscription_portal/clients/graphql_spec.rb'
@@ -57,14 +61,15 @@ RSpec/ExpectInHook:
- 'ee/spec/models/concerns/geo/replicable_model_spec.rb'
- 'ee/spec/models/container_repository_spec.rb'
- 'ee/spec/models/dora/daily_metrics_spec.rb'
+ - 'ee/spec/models/ee/namespace/storage/notification_spec.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/gitlab_subscription_spec.rb'
- 'ee/spec/models/license_spec.rb'
+ - 'ee/spec/models/member_spec.rb'
- 'ee/spec/models/project_import_state_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/presenters/group_member_presenter_spec.rb'
- 'ee/spec/requests/api/geo_spec.rb'
- - 'ee/spec/requests/api/graphql/ci/runner_spec.rb'
- 'ee/spec/requests/api/internal/base_spec.rb'
- 'ee/spec/requests/groups/analytics/devops_adoption_controller_spec.rb'
- 'ee/spec/requests/omniauth_kerberos_spnego_spec.rb'
@@ -74,26 +79,32 @@ RSpec/ExpectInHook:
- 'ee/spec/services/ci/minutes/batch_reset_service_spec.rb'
- 'ee/spec/services/ci/runners/assign_runner_service_spec.rb'
- 'ee/spec/services/ci/runners/register_runner_service_spec.rb'
+ - 'ee/spec/services/ci/runners/reset_registration_token_service_spec.rb'
- 'ee/spec/services/ci/runners/unassign_runner_service_spec.rb'
- 'ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb'
- 'ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb'
- 'ee/spec/services/ee/issues/update_service_spec.rb'
- - 'ee/spec/services/ee/post_receive_service_spec.rb'
- 'ee/spec/services/ee/protected_branches/destroy_service_spec.rb'
- 'ee/spec/services/geo/blob_download_service_spec.rb'
- 'ee/spec/services/geo/project_housekeeping_service_spec.rb'
- 'ee/spec/services/geo/registry_consistency_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/create_hand_raise_lead_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/fetch_subscription_plans_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/plan_upgrade_service_spec.rb'
+ - 'ee/spec/services/gitlab_subscriptions/reconciliations/calculate_seat_count_data_service_spec.rb'
- 'ee/spec/services/groups/update_repository_storage_service_spec.rb'
- - 'ee/spec/services/members/activate_service_spec.rb'
+ - 'ee/spec/services/members/await_service_spec.rb'
- 'ee/spec/services/merge_requests/approval_service_spec.rb'
+ - 'ee/spec/services/merge_requests/mergeability/check_approved_service_spec.rb'
+ - 'ee/spec/services/merge_requests/mergeability/check_blocked_by_other_mrs_service_spec.rb'
+ - 'ee/spec/services/merge_requests/mergeability/check_denied_policies_service_spec.rb'
- 'ee/spec/services/projects/create_from_template_service_spec.rb'
- 'ee/spec/services/projects/mark_for_deletion_service_spec.rb'
- 'ee/spec/services/projects/update_mirror_service_spec.rb'
- 'ee/spec/services/security/findings/cleanup_service_spec.rb'
- 'ee/spec/services/upcoming_reconciliations/update_service_spec.rb'
- 'ee/spec/support/shared_examples/controllers/registrations/projects_controller_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/lib/gitlab/graphql/issuables_lazy_links_aggregate_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/concerns/elastic/cannot_read_cross_project_shared_examples.rb'
- 'ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb'
@@ -112,11 +123,13 @@ RSpec/ExpectInHook:
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/license/cloud_activation_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/1_manage/instance/instance_audit_logs_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'
- 'spec/commands/metrics_server/metrics_server_spec.rb'
+ - 'spec/controllers/admin/runners_controller_spec.rb'
- 'spec/controllers/autocomplete_controller_spec.rb'
- 'spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb'
- 'spec/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support_spec.rb'
@@ -153,13 +166,11 @@ RSpec/ExpectInHook:
- 'spec/features/file_uploads/maven_package_spec.rb'
- 'spec/features/groups/container_registry_spec.rb'
- 'spec/features/groups/group_settings_spec.rb'
- - 'spec/features/issues/filtered_search/dropdown_hint_spec.rb'
- 'spec/features/markdown/markdown_spec.rb'
- 'spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb'
- 'spec/features/merge_request/user_sees_versions_spec.rb'
- 'spec/features/oauth_login_spec.rb'
- 'spec/features/profiles/password_spec.rb'
- - 'spec/features/projects/clusters/gcp_spec.rb'
- 'spec/features/projects/container_registry_spec.rb'
- 'spec/features/projects/feature_flags/user_deletes_feature_flag_spec.rb'
- 'spec/features/projects/files/user_creates_files_spec.rb'
@@ -172,17 +183,20 @@ RSpec/ExpectInHook:
- 'spec/features/users/login_spec.rb'
- 'spec/graphql/mutations/design_management/move_spec.rb'
- 'spec/helpers/commits_helper_spec.rb'
+ - 'spec/helpers/groups_helper_spec.rb'
- 'spec/helpers/invite_members_helper_spec.rb'
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/helpers/search_helper_spec.rb'
- 'spec/helpers/users_helper_spec.rb'
- - 'spec/initializers/omniauth_spec.rb'
+ - 'spec/initializers/net_http_response_patch_spec.rb'
- 'spec/initializers/validate_database_config_spec.rb'
- 'spec/lib/api/entities/merge_request_changes_spec.rb'
- 'spec/lib/api/helpers/variables_helpers_spec.rb'
- 'spec/lib/api/helpers_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
- 'spec/lib/banzai/reference_redactor_spec.rb'
+ - 'spec/lib/bulk_imports/common/extractors/json_extractor_spec.rb'
+ - 'spec/lib/bulk_imports/common/extractors/ndjson_extractor_spec.rb'
- 'spec/lib/bulk_imports/ndjson_pipeline_spec.rb'
- 'spec/lib/container_registry/gitlab_api_client_spec.rb'
- 'spec/lib/file_size_validator_spec.rb'
@@ -207,7 +221,6 @@ RSpec/ExpectInHook:
- 'spec/lib/gitlab/ci/pipeline/chain/command_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/config/content_spec.rb'
- 'spec/lib/gitlab/ci/status/build/failed_spec.rb'
- - 'spec/lib/gitlab/ci/trace/archive_spec.rb'
- 'spec/lib/gitlab/ci/trace/remote_checksum_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb'
@@ -216,14 +229,18 @@ RSpec/ExpectInHook:
- 'spec/lib/gitlab/contributions_calendar_spec.rb'
- 'spec/lib/gitlab/current_settings_spec.rb'
- 'spec/lib/gitlab/daemon_spec.rb'
+ - '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/background_migration/health_status_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/host_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/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/partitioning_spec.rb'
+ - 'spec/lib/gitlab/database/postgres_autovacuum_activity_spec.rb'
- 'spec/lib/gitlab/database/query_analyzer_spec.rb'
- 'spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb'
- 'spec/lib/gitlab/database/with_lock_retries_spec.rb'
@@ -251,10 +268,12 @@ RSpec/ExpectInHook:
- 'spec/lib/gitlab/health_checks/gitaly_check_spec.rb'
- 'spec/lib/gitlab/health_checks/probes/collection_spec.rb'
- 'spec/lib/gitlab/health_checks/puma_check_spec.rb'
+ - 'spec/lib/gitlab/health_checks/server_spec.rb'
- 'spec/lib/gitlab/http_spec.rb'
- 'spec/lib/gitlab/import_export/base/relation_factory_spec.rb'
- 'spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb'
- 'spec/lib/gitlab/import_export/command_line_util_spec.rb'
+ - 'spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb'
- 'spec/lib/gitlab/import_export/group/tree_restorer_spec.rb'
- 'spec/lib/gitlab/import_export/import_failure_service_spec.rb'
- 'spec/lib/gitlab/import_export/json/legacy_reader/shared_example.rb'
@@ -271,12 +290,14 @@ RSpec/ExpectInHook:
- 'spec/lib/gitlab/kubernetes/kube_client_spec.rb'
- 'spec/lib/gitlab/kubernetes/kubeconfig/template_spec.rb'
- 'spec/lib/gitlab/memory/instrumentation_spec.rb'
+ - 'spec/lib/gitlab/memory/jemalloc_spec.rb'
- 'spec/lib/gitlab/metrics/boot_time_tracker_spec.rb'
- 'spec/lib/gitlab/metrics/exporter/metrics_middleware_spec.rb'
- 'spec/lib/gitlab/metrics/samplers/puma_sampler_spec.rb'
- 'spec/lib/gitlab/middleware/memory_report_spec.rb'
- 'spec/lib/gitlab/middleware/multipart_spec.rb'
- 'spec/lib/gitlab/omniauth_initializer_spec.rb'
+ - 'spec/lib/gitlab/pages/deployment_update_spec.rb'
- 'spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb'
- 'spec/lib/gitlab/patch/database_config_spec.rb'
- 'spec/lib/gitlab/project_search_results_spec.rb'
@@ -338,6 +359,7 @@ RSpec/ExpectInHook:
- 'spec/models/ssh_host_key_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/policies/ci/bridge_policy_spec.rb'
+ - 'spec/policies/project_policy_spec.rb'
- 'spec/presenters/ci/build_presenter_spec.rb'
- 'spec/presenters/ci/pipeline_presenter_spec.rb'
- 'spec/presenters/commit_presenter_spec.rb'
@@ -352,6 +374,7 @@ RSpec/ExpectInHook:
- 'spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb'
- 'spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb'
- 'spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb'
+ - 'spec/requests/api/graphql/terraform/state/delete_spec.rb'
- 'spec/requests/api/graphql/terraform/state/lock_spec.rb'
- 'spec/requests/api/graphql/terraform/state/unlock_spec.rb'
- 'spec/requests/api/group_export_spec.rb'
@@ -375,6 +398,7 @@ RSpec/ExpectInHook:
- 'spec/rubocop/cop/performance/ar_count_each_spec.rb'
- 'spec/rubocop/cop/performance/ar_exists_and_present_blank_spec.rb'
- 'spec/scripts/setup/find_jh_branch_spec.rb'
+ - 'spec/scripts/trigger-build_spec.rb'
- 'spec/serializers/diffs_metadata_entity_spec.rb'
- 'spec/serializers/merge_request_diff_entity_spec.rb'
- 'spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
@@ -406,6 +430,7 @@ RSpec/ExpectInHook:
- 'spec/services/design_management/save_designs_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_position_service_spec.rb'
- 'spec/services/environments/reset_auto_stop_service_spec.rb'
+ - 'spec/services/error_tracking/list_projects_service_spec.rb'
- 'spec/services/git/base_hooks_service_spec.rb'
- 'spec/services/git/branch_push_service_spec.rb'
- 'spec/services/git/wiki_push_service/change_spec.rb'
@@ -434,6 +459,7 @@ RSpec/ExpectInHook:
- 'spec/services/notes/quick_actions_service_spec.rb'
- 'spec/services/notification_recipients/builder/default_spec.rb'
- 'spec/services/notification_recipients/builder/new_note_spec.rb'
+ - 'spec/services/packages/cleanup/execute_policy_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/helm/extract_file_metadata_service_spec.rb'
@@ -465,7 +491,6 @@ RSpec/ExpectInHook:
- 'spec/services/protected_branches/create_service_spec.rb'
- 'spec/services/protected_branches/destroy_service_spec.rb'
- 'spec/services/protected_branches/update_service_spec.rb'
- - 'spec/services/repositories/destroy_service_spec.rb'
- 'spec/services/search_service_spec.rb'
- 'spec/services/serverless/associate_domain_service_spec.rb'
- 'spec/services/snippets/update_repository_storage_service_spec.rb'
@@ -481,6 +506,7 @@ RSpec/ExpectInHook:
- 'spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb'
- 'spec/support/shared_examples/graphql/notes_creation_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
+ - 'spec/support/shared_examples/lib/gitlab/database/reestablished_connection_stack_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/diff_file_collections_shared_examples.rb'
- 'spec/support/shared_examples/lib/wikis_api_examples.rb'
- 'spec/support/shared_examples/metrics/sampler_shared_examples.rb'
@@ -515,6 +541,7 @@ RSpec/ExpectInHook:
- 'spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb'
- 'spec/views/shared/runners/_runner_details.html.haml_spec.rb'
- 'spec/workers/build_finished_worker_spec.rb'
+ - 'spec/workers/bulk_imports/pipeline_worker_spec.rb'
- 'spec/workers/ci/build_finished_worker_spec.rb'
- 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
- 'spec/workers/concerns/limited_capacity/job_tracker_spec.rb'
@@ -525,6 +552,7 @@ RSpec/ExpectInHook:
- 'spec/workers/gitlab/jira_import/stage/finish_import_worker_spec.rb'
- 'spec/workers/gitlab_performance_bar_stats_worker_spec.rb'
- 'spec/workers/group_import_worker_spec.rb'
+ - 'spec/workers/incident_management/close_incident_worker_spec.rb'
- 'spec/workers/integrations/create_external_cross_reference_worker_spec.rb'
- 'spec/workers/packages/helm/extraction_worker_spec.rb'
- 'spec/workers/packages/nuget/extraction_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/hooks_before_examples.yml b/.rubocop_todo/rspec/hooks_before_examples.yml
new file mode 100644
index 00000000000..0de9ff4b6c0
--- /dev/null
+++ b/.rubocop_todo/rspec/hooks_before_examples.yml
@@ -0,0 +1,76 @@
+---
+# Cop supports --auto-correct.
+RSpec/HooksBeforeExamples:
+ Exclude:
+ - 'ee/spec/features/boards/swimlanes/epics_swimlanes_spec.rb'
+ - 'ee/spec/graphql/mutations/boards/epic_boards/destroy_spec.rb'
+ - 'ee/spec/graphql/mutations/incident_management/escalation_policy/destroy_spec.rb'
+ - 'ee/spec/graphql/mutations/incident_management/issuable_resource_link/create_spec.rb'
+ - 'ee/spec/graphql/mutations/incident_management/issuable_resource_link/destroy_spec.rb'
+ - 'ee/spec/graphql/mutations/incident_management/oncall_schedule/destroy_spec.rb'
+ - 'ee/spec/graphql/mutations/incident_management/oncall_schedule/update_spec.rb'
+ - 'ee/spec/graphql/mutations/issues/set_escalation_policy_spec.rb'
+ - 'ee/spec/graphql/types/app_sec/fuzzing/coverage/corpus_type_spec.rb'
+ - 'ee/spec/graphql/types/dast/profile_schedule_type_spec.rb'
+ - 'ee/spec/graphql/types/dast/profile_type_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/checks/push_rule_check_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
+ - 'ee/spec/models/ee/merge_request_diff_spec.rb'
+ - 'ee/spec/models/merge_train_spec.rb'
+ - 'ee/spec/requests/api/boards_spec.rb'
+ - 'ee/spec/requests/ee/projects/deploy_tokens_controller_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/revoke_service_spec.rb'
+ - 'ee/spec/services/ee/projects/deploy_tokens/destroy_service_spec.rb'
+ - 'ee/spec/services/merge_trains/create_pipeline_service_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/browser_ui/1_manage/login/log_in_with_2fa_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_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/1_manage/user/user_inherited_access_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/web_ide/open_fork_in_web_ide_spec.rb'
+ - 'qa/qa/specs/features/ee/api/1_manage/user/minimal_access_user_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/13_secure/security_reports_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_saml_enforced_sso_git_access_spec.rb'
+ - '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/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/user/minimal_access_user_spec.rb'
+ - 'qa/spec/resource/reusable_collection_spec.rb'
+ - 'qa/spec/specs/runner_spec.rb'
+ - 'spec/controllers/import/github_controller_spec.rb'
+ - 'spec/features/projects/pages/user_configures_pages_pipeline_spec.rb'
+ - 'spec/graphql/resolvers/design_management/design_resolver_spec.rb'
+ - 'spec/graphql/resolvers/design_management/designs_resolver_spec.rb'
+ - 'spec/graphql/resolvers/project_pipeline_resolver_spec.rb'
+ - 'spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb'
+ - 'spec/lib/banzai/filter/references/user_reference_filter_spec.rb'
+ - 'spec/lib/feature/definition_spec.rb'
+ - 'spec/lib/gitlab/auth/saml/user_spec.rb'
+ - 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
+ - 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
+ - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
+ - 'spec/lib/gitlab/email/hook/disable_email_interceptor_spec.rb'
+ - 'spec/lib/gitlab/tracking/event_definition_spec.rb'
+ - 'spec/lib/gitlab/usage/metric_definition_spec.rb'
+ - 'spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'spec/lib/mattermost/session_spec.rb'
+ - 'spec/models/ci/build_trace_chunk_spec.rb'
+ - 'spec/models/clusters/applications/ingress_spec.rb'
+ - 'spec/models/clusters/applications/knative_spec.rb'
+ - 'spec/models/integrations/chat_message/pipeline_message_spec.rb'
+ - 'spec/models/repository_spec.rb'
+ - 'spec/serializers/pipeline_details_entity_spec.rb'
+ - 'spec/services/feature_flags/hook_service_spec.rb'
+ - 'spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb'
+ - 'spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb'
diff --git a/.rubocop_todo/rspec/predicate_matcher.yml b/.rubocop_todo/rspec/predicate_matcher.yml
index c6a75708ae8..7b31ca3622c 100644
--- a/.rubocop_todo/rspec/predicate_matcher.yml
+++ b/.rubocop_todo/rspec/predicate_matcher.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
RSpec/PredicateMatcher:
- # Offense count: 2480
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'ee/spec/controllers/admin/elasticsearch_controller_spec.rb'
- 'ee/spec/controllers/admin/geo/projects_controller_spec.rb'
@@ -11,11 +8,16 @@ RSpec/PredicateMatcher:
- 'ee/spec/controllers/groups/group_members_controller_spec.rb'
- 'ee/spec/controllers/groups/ldaps_controller_spec.rb'
- 'ee/spec/controllers/projects_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/elastic/migrate/20220613120500_migrate_commits_to_separate_index_spec.rb'
+ - 'ee/spec/elastic/migrate/20220713103500_delete_commits_from_original_index_spec.rb'
- 'ee/spec/elastic/migrate/migration_shared_examples.rb'
- 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/projects/members/member_is_removed_from_project_spec.rb'
- 'ee/spec/features/projects/mirror_spec.rb'
- 'ee/spec/features/signup_spec.rb'
+ - 'ee/spec/finders/epics_finder_spec.rb'
- 'ee/spec/graphql/resolvers/path_locks_resolver_spec.rb'
- 'ee/spec/helpers/ee/groups_helper_spec.rb'
- 'ee/spec/helpers/ee/issues_helper_spec.rb'
@@ -70,6 +72,7 @@ RSpec/PredicateMatcher:
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/saml_provider_spec.rb'
- 'ee/spec/models/security/orchestration_policy_configuration_spec.rb'
+ - 'ee/spec/presenters/ci/minutes/usage_presenter_spec.rb'
- 'ee/spec/requests/api/boards_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/epics/set_subscription_spec.rb'
- 'ee/spec/requests/api/groups_spec.rb'
@@ -96,6 +99,8 @@ 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'
@@ -113,7 +118,6 @@ RSpec/PredicateMatcher:
- 'qa/qa/specs/features/ee/browser_ui/12_geo/database_delete_replication_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/2_plan/epic/roadmap_spec.rb'
- 'qa/spec/runtime/env_spec.rb'
- - 'qa/spec/runtime/feature_spec.rb'
- 'qa/spec/specs/helpers/context_selector_spec.rb'
- 'spec/components/diffs/overflow_warning_component_spec.rb'
- 'spec/controllers/admin/dev_ops_report_controller_spec.rb'
@@ -123,6 +127,7 @@ RSpec/PredicateMatcher:
- 'spec/controllers/concerns/checks_collaboration_spec.rb'
- 'spec/controllers/groups/avatars_controller_spec.rb'
- 'spec/controllers/groups/clusters_controller_spec.rb'
+ - 'spec/controllers/groups/group_links_controller_spec.rb'
- 'spec/controllers/groups/group_members_controller_spec.rb'
- 'spec/controllers/groups/settings/applications_controller_spec.rb'
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
@@ -157,7 +162,6 @@ RSpec/PredicateMatcher:
- 'spec/features/unsubscribe_links_spec.rb'
- 'spec/features/users/signup_spec.rb'
- 'spec/finders/group_descendants_finder_spec.rb'
- - 'spec/finders/issues_finder_spec.rb'
- 'spec/finders/merge_request_target_project_finder_spec.rb'
- 'spec/helpers/application_helper_spec.rb'
- 'spec/helpers/application_settings_helper_spec.rb'
@@ -169,6 +173,7 @@ RSpec/PredicateMatcher:
- 'spec/helpers/projects_helper_spec.rb'
- 'spec/helpers/recaptcha_helper_spec.rb'
- 'spec/helpers/sessions_helper_spec.rb'
+ - 'spec/helpers/sorting_helper_spec.rb'
- 'spec/lib/backup/files_spec.rb'
- 'spec/lib/bitbucket/connection_spec.rb'
- 'spec/lib/bitbucket/page_spec.rb'
@@ -260,7 +265,6 @@ RSpec/PredicateMatcher:
- 'spec/lib/gitlab/fake_application_settings_spec.rb'
- 'spec/lib/gitlab/git/blob_spec.rb'
- 'spec/lib/gitlab/git/branch_spec.rb'
- - 'spec/lib/gitlab/git/commit_spec.rb'
- 'spec/lib/gitlab/git/keep_around_spec.rb'
- 'spec/lib/gitlab/git/repository_spec.rb'
- 'spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb'
@@ -273,6 +277,7 @@ RSpec/PredicateMatcher:
- 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
- 'spec/lib/gitlab/gl_repository/repo_type_spec.rb'
- 'spec/lib/gitlab/gpg/commit_spec.rb'
+ - 'spec/lib/gitlab/graphql/query_analyzers/ast/recursion_analyzer_spec.rb'
- 'spec/lib/gitlab/hashed_storage/migrator_spec.rb'
- 'spec/lib/gitlab/i18n/translation_entry_spec.rb'
- 'spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb'
@@ -308,6 +313,7 @@ RSpec/PredicateMatcher:
- 'spec/lib/gitlab/user_access_snippet_spec.rb'
- 'spec/lib/gitlab/user_access_spec.rb'
- 'spec/lib/gitlab/utils/sanitize_node_link_spec.rb'
+ - 'spec/lib/gitlab/version_info_spec.rb'
- 'spec/lib/gitlab/view/presenter/base_spec.rb'
- 'spec/lib/gitlab/visibility_level_spec.rb'
- 'spec/lib/object_storage/direct_upload_spec.rb'
@@ -400,7 +406,6 @@ RSpec/PredicateMatcher:
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/project_clusters_spec.rb'
- 'spec/requests/api/project_export_spec.rb'
- - 'spec/requests/api/project_hooks_spec.rb'
- 'spec/requests/api/project_snippets_spec.rb'
- 'spec/requests/api/projects_spec.rb'
- 'spec/requests/api/resource_access_tokens_spec.rb'
@@ -425,11 +430,13 @@ RSpec/PredicateMatcher:
- 'spec/services/container_expiration_policies/update_service_spec.rb'
- 'spec/services/customer_relations/contacts/update_service_spec.rb'
- 'spec/services/customer_relations/organizations/update_service_spec.rb'
+ - 'spec/services/deployments/create_for_build_service_spec.rb'
- 'spec/services/deployments/older_deployments_drop_service_spec.rb'
- 'spec/services/draft_notes/publish_service_spec.rb'
- 'spec/services/environments/schedule_to_delete_review_apps_service_spec.rb'
- 'spec/services/groups/destroy_service_spec.rb'
- 'spec/services/groups/group_links/create_service_spec.rb'
+ - 'spec/services/groups/group_links/destroy_service_spec.rb'
- 'spec/services/groups/transfer_service_spec.rb'
- 'spec/services/groups/update_service_spec.rb'
- 'spec/services/issuable/bulk_update_service_spec.rb'
@@ -449,6 +456,7 @@ RSpec/PredicateMatcher:
- 'spec/services/note_summary_spec.rb'
- 'spec/services/notes/build_service_spec.rb'
- 'spec/services/notes/quick_actions_service_spec.rb'
+ - 'spec/services/packages/cleanup/update_policy_service_spec.rb'
- 'spec/services/packages/debian/find_or_create_incoming_service_spec.rb'
- 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
- 'spec/services/projects/after_rename_service_spec.rb'
@@ -478,6 +486,7 @@ RSpec/PredicateMatcher:
- 'spec/services/users/destroy_service_spec.rb'
- 'spec/support/shared_contexts/email_shared_context.rb'
- 'spec/support/shared_examples/ci/auto_merge_merge_requests_shared_examples.rb'
+ - 'spec/support/shared_examples/finders/issues_finder_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- 'spec/support/shared_examples/models/application_setting_shared_examples.rb'
- 'spec/support/shared_examples/models/cluster_application_core_shared_examples.rb'
@@ -486,6 +495,7 @@ RSpec/PredicateMatcher:
- 'spec/support/shared_examples/models/member_shared_examples.rb'
- 'spec/support/shared_examples/models/note_access_check_shared_examples.rb'
- 'spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb'
+ - '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'
@@ -497,12 +507,13 @@ RSpec/PredicateMatcher:
- 'spec/validators/namespace_path_validator_spec.rb'
- 'spec/validators/project_path_validator_spec.rb'
- 'spec/workers/bulk_imports/entity_worker_spec.rb'
+ - 'spec/workers/bulk_imports/pipeline_worker_spec.rb'
- 'spec/workers/ci/delete_objects_worker_spec.rb'
- - 'spec/workers/concerns/worker_attributes_spec.rb'
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'
- 'spec/workers/group_destroy_worker_spec.rb'
- 'spec/workers/hashed_storage/migrator_worker_spec.rb'
- 'spec/workers/hashed_storage/rollbacker_worker_spec.rb'
- 'spec/workers/project_destroy_worker_spec.rb'
- 'spec/workers/remote_mirror_notification_worker_spec.rb'
+ - 'spec/workers/remove_expired_group_links_worker_spec.rb'
- 'spec/workers/x509_issuer_crl_check_worker_spec.rb'
diff --git a/.rubocop_todo/rspec/repeated_example_group_description.yml b/.rubocop_todo/rspec/repeated_example_group_description.yml
index b5c4ac090ae..31c17c994a6 100644
--- a/.rubocop_todo/rspec/repeated_example_group_description.yml
+++ b/.rubocop_todo/rspec/repeated_example_group_description.yml
@@ -44,7 +44,6 @@ RSpec/RepeatedExampleGroupDescription:
- 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
- 'spec/features/security/project/private_access_spec.rb'
- 'spec/finders/ci/pipelines_for_merge_request_finder_spec.rb'
- - 'spec/frontend/fixtures/runner.rb'
- 'spec/frontend/fixtures/startup_css.rb'
- 'spec/helpers/admin/user_actions_helper_spec.rb'
- 'spec/helpers/dropdowns_helper_spec.rb'
diff --git a/.rubocop_todo/rspec/return_from_stub.yml b/.rubocop_todo/rspec/return_from_stub.yml
index 21cd26a0a6f..215660f31d3 100644
--- a/.rubocop_todo/rspec/return_from_stub.yml
+++ b/.rubocop_todo/rspec/return_from_stub.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
RSpec/ReturnFromStub:
- # Offense count: 703
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'ee/spec/controllers/admin/geo/nodes_controller_spec.rb'
- 'ee/spec/controllers/groups/billings_controller_spec.rb'
@@ -18,6 +15,7 @@ RSpec/ReturnFromStub:
- 'ee/spec/features/projects/integrations/user_activates_jira_spec.rb'
- 'ee/spec/features/projects/milestones/milestone_spec.rb'
- 'ee/spec/features/projects/new_project_spec.rb'
+ - 'ee/spec/features/projects/pipelines/legacy_pipeline_spec.rb'
- 'ee/spec/features/projects/pipelines/pipeline_spec.rb'
- 'ee/spec/features/projects/settings/ee/service_desk_setting_spec.rb'
- 'ee/spec/features/promotion_spec.rb'
@@ -39,9 +37,9 @@ RSpec/ReturnFromStub:
- 'ee/spec/lib/ee/feature_spec.rb'
- 'ee/spec/lib/ee/gitlab/checks/push_rules/branch_check_spec.rb'
- 'ee/spec/lib/ee/gitlab/database_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/git_access_project_spec.rb'
- 'ee/spec/lib/gitlab/ci/minutes/build_consumption_spec.rb'
- 'ee/spec/lib/gitlab/ci/minutes/cost_factor_spec.rb'
- - 'ee/spec/lib/gitlab/code_owners_spec.rb'
- 'ee/spec/lib/gitlab/geo/health_check_spec.rb'
- 'ee/spec/lib/gitlab/geo/logger_spec.rb'
- 'ee/spec/lib/gitlab/geo_spec.rb'
@@ -62,6 +60,7 @@ RSpec/ReturnFromStub:
- 'ee/spec/presenters/ci/build_presenter_spec.rb'
- 'ee/spec/presenters/merge_request_presenter_spec.rb'
- 'ee/spec/requests/admin/credentials_controller_spec.rb'
+ - 'ee/spec/requests/groups/protected_environments_controller_spec.rb'
- 'ee/spec/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service_spec.rb'
- 'ee/spec/services/auto_merge/merge_train_service_spec.rb'
- 'ee/spec/services/deployments/auto_rollback_service_spec.rb'
@@ -88,6 +87,7 @@ RSpec/ReturnFromStub:
- 'ee/spec/support/shared_examples/services/geo_event_store_shared_examples.rb'
- 'ee/spec/support/shared_examples/services/merge_merge_requests_shared_examples.rb'
- 'ee/spec/views/admin/application_settings/_elasticsearch_form.html.haml_spec.rb'
+ - 'ee/spec/views/admin/application_settings/_git_abuse_rate_limit.html.haml_spec.rb'
- 'ee/spec/views/admin/groups/_form.html.haml_spec.rb'
- 'ee/spec/views/layouts/application.html.haml_spec.rb'
- 'ee/spec/views/shared/_mirror_update_button.html.haml_spec.rb'
@@ -191,13 +191,15 @@ RSpec/ReturnFromStub:
- 'spec/lib/gitlab/instrumentation/redis_base_spec.rb'
- 'spec/lib/gitlab/legacy_github_import/importer_spec.rb'
- 'spec/lib/gitlab/memory/instrumentation_spec.rb'
- - 'spec/lib/gitlab/metrics/rails_slis_spec.rb'
+ - 'spec/lib/gitlab/memory/reports_daemon_spec.rb'
- 'spec/lib/gitlab/metrics/system_spec.rb'
- 'spec/lib/gitlab/middleware/read_only_spec.rb'
- 'spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb'
- 'spec/lib/gitlab/prometheus_client_spec.rb'
- 'spec/lib/gitlab/redis/cache_spec.rb'
+ - 'spec/lib/gitlab/redis/duplicate_jobs_spec.rb'
- 'spec/lib/gitlab/redis/shared_state_spec.rb'
+ - 'spec/lib/gitlab/redis/sidekiq_status_spec.rb'
- 'spec/lib/gitlab/relative_positioning/range_spec.rb'
- 'spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb'
- 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
diff --git a/.rubocop_todo/rspec/scattered_let.yml b/.rubocop_todo/rspec/scattered_let.yml
index 069f9a15fff..93f373b0a9e 100644
--- a/.rubocop_todo/rspec/scattered_let.yml
+++ b/.rubocop_todo/rspec/scattered_let.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
RSpec/ScatteredLet:
- # Offense count: 720
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'ee/spec/features/groups/group_roadmap_spec.rb'
- 'ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb'
@@ -19,10 +16,10 @@ RSpec/ScatteredLet:
- 'ee/spec/graphql/types/instance_security_dashboard_type_spec.rb'
- 'ee/spec/helpers/ee/subscribable_banner_helper_spec.rb'
- 'ee/spec/helpers/trial_status_widget_helper_spec.rb'
- - 'ee/spec/lib/banzai/reference_parser/iteration_parser_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/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'
@@ -44,7 +41,6 @@ RSpec/ScatteredLet:
- 'ee/spec/models/ci/minutes/notification_spec.rb'
- 'ee/spec/models/ci/pipeline_spec.rb'
- 'ee/spec/models/ee/ci/build_dependencies_spec.rb'
- - 'ee/spec/models/ee/namespace/root_storage_size_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'
@@ -62,9 +58,12 @@ RSpec/ScatteredLet:
- '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/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/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'
@@ -88,13 +87,13 @@ RSpec/ScatteredLet:
- '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/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'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
- 'spec/controllers/projects/environments_controller_spec.rb'
@@ -126,14 +125,19 @@ 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/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/ci/config/external/file/artifact_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb'
@@ -162,6 +166,7 @@ RSpec/ScatteredLet:
- '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'
@@ -182,7 +187,6 @@ RSpec/ScatteredLet:
- '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/service_ping_report_spec.rb'
- 'spec/lib/gitlab/usage_data_metrics_spec.rb'
- 'spec/lib/gitlab/utils/measuring_spec.rb'
- 'spec/lib/gitlab/zentao/client_spec.rb'
@@ -236,6 +240,7 @@ RSpec/ScatteredLet:
- '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'
@@ -277,6 +282,8 @@ RSpec/ScatteredLet:
- 'spec/services/system_notes/design_management_service_spec.rb'
- 'spec/services/system_notes/merge_requests_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'
diff --git a/.rubocop_todo/rspec/verified_doubles.yml b/.rubocop_todo/rspec/verified_doubles.yml
index 84e862ff48b..70b54d5bc7f 100644
--- a/.rubocop_todo/rspec/verified_doubles.yml
+++ b/.rubocop_todo/rspec/verified_doubles.yml
@@ -210,6 +210,7 @@ RSpec/VerifiedDoubles:
- ee/spec/views/layouts/header/_ee_subscribable_banner.html.haml_spec.rb
- ee/spec/workers/ci/sync_reports_to_report_approval_rules_worker_spec.rb
- ee/spec/workers/geo/container_repository_sync_worker_spec.rb
+ - ee/spec/workers/compliance_management/chain_of_custody_report_worker_spec.rb
- ee/spec/workers/geo/design_repository_sync_worker_spec.rb
- ee/spec/workers/geo/destroy_worker_spec.rb
- ee/spec/workers/geo/event_worker_spec.rb
diff --git a/.rubocop_todo/style/array_coercion.yml b/.rubocop_todo/style/array_coercion.yml
deleted file mode 100644
index a49fc42967d..00000000000
--- a/.rubocop_todo/style/array_coercion.yml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-# Cop supports --auto-correct.
-Style/ArrayCoercion:
- Exclude:
- - 'app/controllers/admin/ci/variables_controller.rb'
- - 'app/controllers/groups/variables_controller.rb'
- - 'app/controllers/projects/variables_controller.rb'
- - 'ee/app/services/geo/repository_verification_secondary_service.rb'
- - 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
- - 'spec/support/helpers/lfs_http_helpers.rb'
diff --git a/.rubocop_todo/style/class_and_module_children.yml b/.rubocop_todo/style/class_and_module_children.yml
index fab05667adb..e0747f232a1 100644
--- a/.rubocop_todo/style/class_and_module_children.yml
+++ b/.rubocop_todo/style/class_and_module_children.yml
@@ -292,6 +292,7 @@ Style/ClassAndModuleChildren:
- 'app/models/merge_request/metrics.rb'
- 'app/models/namespace/admin_note.rb'
- 'app/models/namespace/aggregation_schedule.rb'
+ - 'app/models/namespace/detail.rb'
- 'app/models/namespace/package_setting.rb'
- 'app/models/namespace/root_storage_statistics.rb'
- 'app/models/namespaces/sync_event.rb'
@@ -478,8 +479,6 @@ Style/ClassAndModuleChildren:
- 'ee/app/models/concerns/geo/syncable.rb'
- 'ee/app/models/dast/profile_schedule.rb'
- 'ee/app/models/ee/ci/job_artifact.rb'
- - 'ee/app/models/ee/namespace/root_excess_storage_size.rb'
- - 'ee/app/models/ee/namespace/root_storage_size.rb'
- 'ee/app/models/elastic/reindexing_slice.rb'
- 'ee/app/models/elastic/reindexing_subtask.rb'
- 'ee/app/models/elastic/reindexing_task.rb'
diff --git a/.rubocop_todo/style/empty_else.yml b/.rubocop_todo/style/empty_else.yml
index ed840856e19..f211d022dcd 100644
--- a/.rubocop_todo/style/empty_else.yml
+++ b/.rubocop_todo/style/empty_else.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/EmptyElse:
- # Offense count: 59
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/concerns/issuable_collections_action.rb'
- 'app/controllers/concerns/sends_blob.rb'
@@ -15,8 +12,8 @@ Style/EmptyElse:
- 'app/graphql/mutations/concerns/mutations/spam_protection.rb'
- 'app/graphql/resolvers/group_milestones_resolver.rb'
- 'app/graphql/types/ci/detailed_status_type.rb'
+ - 'app/graphql/types/packages/package_base_type.rb'
- 'app/graphql/types/packages/package_file_type.rb'
- - 'app/graphql/types/packages/package_type.rb'
- 'app/helpers/submodule_helper.rb'
- 'app/models/commit.rb'
- 'app/models/legacy_diff_discussion.rb'
@@ -27,6 +24,7 @@ Style/EmptyElse:
- 'app/models/resource_timebox_event.rb'
- 'app/services/award_emojis/add_service.rb'
- 'app/services/merge_requests/update_service.rb'
+ - 'app/workers/gitlab/github_import/stage/import_issue_events_worker.rb'
- 'app/workers/post_receive.rb'
- 'config/initializers/doorkeeper_openid_connect.rb'
- 'ee/app/controllers/admin/audit_logs_controller.rb'
@@ -38,13 +36,14 @@ Style/EmptyElse:
- 'ee/app/services/epics/tree_reorder_service.rb'
- 'ee/app/services/gitlab_subscriptions/check_future_renewal_service.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
- - 'ee/app/workers/audit_events/audit_event_streaming_worker.rb'
- 'ee/app/workers/gitlab_subscriptions/notify_seats_exceeded_worker.rb'
- 'ee/db/fixtures/development/20_vulnerabilities.rb'
- 'ee/lib/elastic/latest/note_instance_proxy.rb'
+ - 'ee/lib/gitlab/analytics/cycle_analytics/summary/change_failure_rate.rb'
- 'ee/lib/gitlab/geo/oauth/logout_token.rb'
- 'lib/api/subscriptions.rb'
- 'lib/gitlab/auth/o_auth/provider.rb'
+ - 'lib/gitlab/ci/variables/collection.rb'
- 'lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb'
- 'lib/gitlab/database/sha256_attribute.rb'
- 'lib/gitlab/diff/parser.rb'
diff --git a/.rubocop_todo/style/explicit_block_argument.yml b/.rubocop_todo/style/explicit_block_argument.yml
index e5ce2576f8c..63b7b5d387d 100644
--- a/.rubocop_todo/style/explicit_block_argument.yml
+++ b/.rubocop_todo/style/explicit_block_argument.yml
@@ -100,7 +100,6 @@ Style/ExplicitBlockArgument:
- 'spec/services/pages/zip_directory_service_spec.rb'
- 'spec/services/todo_service_spec.rb'
- 'spec/support/helpers/feature_flag_helpers.rb'
- - 'spec/support/helpers/features/runner_helpers.rb'
- 'spec/support/helpers/features/top_nav_spec_helpers.rb'
- 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/helpers/modal_helpers.rb'
diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml
index caa293b31ae..bb95d8f7fe9 100644
--- a/.rubocop_todo/style/format_string.yml
+++ b/.rubocop_todo/style/format_string.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/FormatString:
- # Offense count: 769
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/components/diffs/overflow_warning_component.rb'
- 'app/controllers/admin/application_settings_controller.rb'
@@ -21,6 +18,7 @@ Style/FormatString:
- 'app/controllers/concerns/membership_actions.rb'
- 'app/controllers/concerns/redirects_for_missing_path_on_tree.rb'
- 'app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb'
+ - 'app/controllers/concerns/verifies_with_email.rb'
- 'app/controllers/groups/settings/ci_cd_controller.rb'
- 'app/controllers/import/bitbucket_server_controller.rb'
- 'app/controllers/import/bulk_imports_controller.rb'
@@ -37,6 +35,8 @@ Style/FormatString:
- 'app/controllers/profiles/preferences_controller.rb'
- 'app/controllers/profiles/two_factor_auths_controller.rb'
- 'app/controllers/profiles_controller.rb'
+ - 'app/controllers/projects/google_cloud/deployments_controller.rb'
+ - 'app/controllers/projects/google_cloud/service_accounts_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
- 'app/controllers/projects/performance_monitoring/dashboards_controller.rb'
@@ -56,15 +56,18 @@ Style/FormatString:
- 'app/helpers/colors_helper.rb'
- 'app/helpers/emails_helper.rb'
- 'app/helpers/form_helper.rb'
+ - 'app/helpers/groups/group_members_helper.rb'
- 'app/helpers/groups_helper.rb'
- 'app/helpers/import_helper.rb'
- 'app/helpers/invite_members_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/issues_helper.rb'
+ - 'app/helpers/members_helper.rb'
- 'app/helpers/merge_requests_helper.rb'
- 'app/helpers/mirror_helper.rb'
- 'app/helpers/preferences_helper.rb'
- 'app/helpers/profiles_helper.rb'
+ - 'app/helpers/projects/project_members_helper.rb'
- 'app/helpers/projects_helper.rb'
- 'app/helpers/registrations_helper.rb'
- 'app/helpers/reminder_emails_helper.rb'
@@ -83,6 +86,7 @@ Style/FormatString:
- 'app/mailers/emails/profile.rb'
- 'app/models/application_setting.rb'
- 'app/models/application_setting_implementation.rb'
+ - 'app/models/concerns/integrations/has_issue_tracker_fields.rb'
- 'app/models/concerns/limitable.rb'
- 'app/models/concerns/metric_image_uploading.rb'
- 'app/models/concerns/spammable.rb'
@@ -108,17 +112,21 @@ Style/FormatString:
- 'app/models/integrations/external_wiki.rb'
- 'app/models/integrations/flowdock.rb'
- 'app/models/integrations/hangouts_chat.rb'
+ - 'app/models/integrations/irker.rb'
- 'app/models/integrations/jenkins.rb'
- 'app/models/integrations/jira.rb'
- 'app/models/integrations/mattermost.rb'
- 'app/models/integrations/pipelines_email.rb'
- 'app/models/integrations/pivotaltracker.rb'
+ - 'app/models/integrations/pumble.rb'
- 'app/models/integrations/pushover.rb'
- 'app/models/integrations/redmine.rb'
- 'app/models/integrations/unify_circuit.rb'
- 'app/models/integrations/webex_teams.rb'
- 'app/models/integrations/youtrack.rb'
- 'app/models/integrations/zentao.rb'
+ - 'app/models/merge_request.rb'
+ - 'app/models/merge_request_diff.rb'
- 'app/models/milestone.rb'
- 'app/models/pages_domain.rb'
- 'app/models/project.rb'
@@ -129,6 +137,7 @@ Style/FormatString:
- 'app/models/user.rb'
- 'app/models/wiki.rb'
- 'app/models/wiki_page.rb'
+ - 'app/models/work_items/parent_link.rb'
- 'app/presenters/ci/pipeline_presenter.rb'
- 'app/presenters/merge_request_presenter.rb'
- 'app/presenters/project_presenter.rb'
@@ -152,6 +161,7 @@ Style/FormatString:
- 'app/services/gravatar_service.rb'
- 'app/services/groups/transfer_service.rb'
- 'app/services/import/bitbucket_server_service.rb'
+ - 'app/services/import/fogbugz_service.rb'
- 'app/services/import/github_service.rb'
- 'app/services/issuable_links/create_service.rb'
- 'app/services/issues/clone_service.rb'
@@ -169,7 +179,10 @@ Style/FormatString:
- 'app/services/projects/create_from_template_service.rb'
- 'app/services/projects/import_service.rb'
- 'app/services/system_notes/design_management_service.rb'
+ - 'app/services/timelogs/create_service.rb'
- 'app/services/users/banned_user_base_service.rb'
+ - 'app/services/work_items/parent_links/create_service.rb'
+ - 'app/services/work_items/widgets/hierarchy_service/base_service.rb'
- 'app/validators/addressable_url_validator.rb'
- 'app/validators/any_field_validator.rb'
- 'app/validators/array_members_validator.rb'
@@ -180,6 +193,14 @@ Style/FormatString:
- 'config/initializers/rack_lineprof.rb'
- 'danger/roulette/Dangerfile'
- 'ee/app/components/billing/plan_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personable.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personal_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personal_preview_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/personal_usage_quota_limitations_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/preview_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/usage_quota_alert_component.rb'
+ - 'ee/app/components/namespaces/free_user_cap/usage_quota_trial_alert_component.rb'
- 'ee/app/controllers/admin/elasticsearch_controller.rb'
- 'ee/app/controllers/admin/geo/application_controller.rb'
- 'ee/app/controllers/admin/geo/projects_controller.rb'
@@ -190,6 +211,7 @@ Style/FormatString:
- 'ee/app/controllers/ee/repositories/git_http_client_controller.rb'
- 'ee/app/controllers/ee/repositories/lfs_api_controller.rb'
- 'ee/app/controllers/groups/saml_group_links_controller.rb'
+ - 'ee/app/controllers/groups/settings/reporting_controller.rb'
- 'ee/app/controllers/groups/sso_controller.rb'
- 'ee/app/controllers/projects/requirements_management/requirements_controller.rb'
- 'ee/app/controllers/subscriptions/groups_controller.rb'
@@ -197,9 +219,11 @@ Style/FormatString:
- 'ee/app/helpers/billing_plans_helper.rb'
- 'ee/app/helpers/ee/application_helper.rb'
- 'ee/app/helpers/ee/geo_helper.rb'
+ - 'ee/app/helpers/ee/groups/reporting_helper.rb'
- 'ee/app/helpers/ee/groups/settings_helper.rb'
- 'ee/app/helpers/ee/groups_helper.rb'
- 'ee/app/helpers/ee/import_helper.rb'
+ - 'ee/app/helpers/ee/members_helper.rb'
- 'ee/app/helpers/ee/profiles_helper.rb'
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/helpers/ee/timeboxes_helper.rb'
@@ -207,6 +231,7 @@ Style/FormatString:
- 'ee/app/helpers/groups/sso_helper.rb'
- 'ee/app/helpers/trial_registrations/reassurances_helper.rb'
- 'ee/app/helpers/vulnerabilities_helper.rb'
+ - 'ee/app/mailers/ee/emails/admin_notification.rb'
- 'ee/app/mailers/emails/namespace_storage_usage_mailer.rb'
- 'ee/app/models/ci/minutes/notification.rb'
- 'ee/app/models/dast/profile.rb'
@@ -214,8 +239,10 @@ Style/FormatString:
- 'ee/app/models/dast_site_profile.rb'
- 'ee/app/models/dast_site_validation.rb'
- 'ee/app/models/ee/member.rb'
+ - 'ee/app/models/ee/namespace/storage/notification.rb'
- 'ee/app/models/geo/upload_registry.rb'
- 'ee/app/models/integrations/github.rb'
+ - 'ee/app/models/iterations/cadence.rb'
- 'ee/app/models/namespace_limit.rb'
- 'ee/app/models/users_security_dashboard_project.rb'
- 'ee/app/services/app_sec/dast/profiles/build_config_service.rb'
@@ -227,6 +254,7 @@ Style/FormatString:
- 'ee/app/services/concerns/incident_management/oncall_rotations/shared_rotation_logic.rb'
- 'ee/app/services/dora/aggregate_metrics_service.rb'
- 'ee/app/services/ee/projects/create_from_template_service.rb'
+ - 'ee/app/services/group_saml/saml_group_links/create_service.rb'
- 'ee/app/services/incident_management/escalation_policies/base_service.rb'
- 'ee/app/services/issues/build_from_vulnerability_service.rb'
- 'ee/app/services/merge_requests/create_from_vulnerability_data_service.rb'
@@ -236,15 +264,18 @@ 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'
+ - 'ee/app/validators/user_existence_validator.rb'
- 'ee/lib/audit/details.rb'
- 'ee/lib/ee/audit/project_changes_auditor.rb'
- 'ee/lib/ee/audit/project_setting_changes_auditor.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/branch_check.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/commit_check.rb'
- 'ee/lib/ee/gitlab/ci/pipeline/chain/validate/security_orchestration_policy.rb'
+ - 'ee/lib/ee/gitlab/namespace_storage_size_error_message.rb'
- 'ee/lib/ee/gitlab/quick_actions/epic_actions.rb'
- 'ee/lib/ee/gitlab/quick_actions/issue_actions.rb'
- 'ee/lib/ee/gitlab/quick_actions/issue_and_merge_request_actions.rb'
@@ -256,11 +287,13 @@ Style/FormatString:
- 'ee/lib/gitlab/auth/group_saml/response_check.rb'
- 'ee/lib/gitlab/expiring_subscription_message.rb'
- 'ee/lib/gitlab/geo.rb'
+ - 'ee/lib/gitlab/licenses/submit_license_usage_data_banner.rb'
- 'ee/lib/gitlab/manual_quarterly_co_term_banner.rb'
- 'ee/lib/gitlab/vulnerabilities/container_scanning_vulnerability.rb'
- 'ee/lib/tasks/gitlab/elastic.rake'
- 'ee/spec/controllers/admin/licenses_controller_spec.rb'
- 'ee/spec/controllers/groups/security/policies_controller_spec.rb'
+ - 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/admin/admin_users_spec.rb'
- 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
- 'ee/spec/features/groups/analytics/cycle_analytics/multiple_value_streams_spec.rb'
@@ -273,6 +306,7 @@ Style/FormatString:
- 'lib/gitlab/ci/ansi2json/line.rb'
- 'lib/gitlab/ci/badge/coverage/template.rb'
- 'lib/gitlab/ci/config/entry/tags.rb'
+ - 'lib/gitlab/ci/parsers/sbom/cyclonedx.rb'
- 'lib/gitlab/ci/status/build/waiting_for_approval.rb'
- 'lib/gitlab/config_checker/external_database_checker.rb'
- 'lib/gitlab/config_checker/puma_rugged_checker.rb'
@@ -293,6 +327,7 @@ Style/FormatString:
- 'lib/gitlab/email/message/in_product_marketing/verify.rb'
- 'lib/gitlab/exceptions_app.rb'
- 'lib/gitlab/github_import/importer/pull_request_merged_by_importer.rb'
+ - 'lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb'
- 'lib/gitlab/github_import/issuable_finder.rb'
- 'lib/gitlab/github_import/label_finder.rb'
- 'lib/gitlab/github_import/milestone_finder.rb'
@@ -307,6 +342,7 @@ Style/FormatString:
- 'lib/gitlab/log_timestamp_formatter.rb'
- 'lib/gitlab/metrics/dashboard/errors.rb'
- 'lib/gitlab/metrics/dashboard/validator/errors.rb'
+ - 'lib/gitlab/pages/cache_control.rb'
- 'lib/gitlab/quick_actions/command_definition.rb'
- 'lib/gitlab/quick_actions/commit_actions.rb'
- 'lib/gitlab/quick_actions/issuable_actions.rb'
@@ -318,11 +354,11 @@ Style/FormatString:
- 'lib/gitlab/version_info.rb'
- 'lib/peek/views/detailed_view.rb'
- 'lib/tasks/test.rake'
- - 'qa/qa/service/docker_run/gitlab_runner.rb'
- 'spec/controllers/graphql_controller_spec.rb'
- 'spec/factories/lfs_objects.rb'
- 'spec/features/admin/admin_users_spec.rb'
- 'spec/features/groups/import_export/connect_instance_spec.rb'
+ - 'spec/features/issues/form_spec.rb'
- 'spec/finders/serverless_domain_finder_spec.rb'
- 'spec/graphql/resolvers/projects/jira_projects_resolver_spec.rb'
- 'spec/helpers/profiles_helper_spec.rb'
@@ -345,6 +381,7 @@ Style/FormatString:
- 'spec/support/shared_examples/services/jira/requests/base_shared_examples.rb'
- 'spec/support/shared_examples/views/registration_features_prompt_shared_examples.rb'
- 'spec/validators/any_field_validator_spec.rb'
+ - 'spec/views/errors/omniauth_error.html.haml_spec.rb'
- 'spec/views/groups/edit.html.haml_spec.rb'
- 'spec/views/profiles/keys/_form.html.haml_spec.rb'
- 'spec/views/profiles/notifications/show.html.haml_spec.rb'
diff --git a/.rubocop_todo/style/guard_clause.yml b/.rubocop_todo/style/guard_clause.yml
index 7ee19ee164e..b07c29ca1df 100644
--- a/.rubocop_todo/style/guard_clause.yml
+++ b/.rubocop_todo/style/guard_clause.yml
@@ -1,8 +1,5 @@
---
Style/GuardClause:
- # Offense count: 1014
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/application_controller.rb'
@@ -28,6 +25,7 @@ Style/GuardClause:
- 'app/controllers/dashboard/todos_controller.rb'
- 'app/controllers/groups/application_controller.rb'
- 'app/controllers/groups_controller.rb'
+ - 'app/controllers/ide_controller.rb'
- 'app/controllers/import/gitea_controller.rb'
- 'app/controllers/import/github_controller.rb'
- 'app/controllers/import/gitlab_controller.rb'
@@ -46,12 +44,14 @@ Style/GuardClause:
- 'app/controllers/projects/google_cloud/base_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
+ - 'app/controllers/projects/pipelines/tests_controller.rb'
- 'app/controllers/projects/repositories_controller.rb'
- 'app/controllers/projects/settings/operations_controller.rb'
- 'app/controllers/projects/tree_controller.rb'
- 'app/controllers/registrations_controller.rb'
- 'app/controllers/repositories/git_http_controller.rb'
- 'app/controllers/repositories/lfs_api_controller.rb'
+ - 'app/controllers/repositories/lfs_storage_controller.rb'
- 'app/controllers/search_controller.rb'
- 'app/controllers/sessions_controller.rb'
- 'app/controllers/users/terms_controller.rb'
@@ -65,6 +65,7 @@ Style/GuardClause:
- 'app/graphql/mutations/design_management/delete.rb'
- 'app/graphql/mutations/notes/create/note.rb'
- 'app/graphql/mutations/notes/reposition_image_diff_note.rb'
+ - 'app/graphql/mutations/packages/destroy_files.rb'
- 'app/graphql/resolvers/blobs_resolver.rb'
- 'app/graphql/resolvers/board_list_issues_resolver.rb'
- 'app/graphql/resolvers/concerns/board_item_filterable.rb'
@@ -72,8 +73,8 @@ Style/GuardClause:
- 'app/graphql/resolvers/concerns/time_frame_arguments.rb'
- 'app/graphql/resolvers/projects/jira_projects_resolver.rb'
- 'app/graphql/types/ci/job_type.rb'
+ - 'app/graphql/types/permission_types/base_permission_type.rb'
- 'app/helpers/admin/user_actions_helper.rb'
- - 'app/helpers/appearances_helper.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/events_helper.rb'
- 'app/helpers/issues_helper.rb'
@@ -121,17 +122,18 @@ Style/GuardClause:
- 'app/models/design_management/design_collection.rb'
- 'app/models/diff_viewer/base.rb'
- 'app/models/environment.rb'
- - 'app/models/error_tracking/error_event.rb'
- 'app/models/error_tracking/project_error_tracking_setting.rb'
- 'app/models/experiment_subject.rb'
- 'app/models/external_pull_request.rb'
- 'app/models/generic_commit_status.rb'
+ - 'app/models/grafana_integration.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/models/integrations/base_issue_tracker.rb'
- 'app/models/integrations/base_third_party_wiki.rb'
- 'app/models/integrations/confluence.rb'
- 'app/models/integrations/datadog.rb'
- 'app/models/integrations/emails_on_push.rb'
+ - 'app/models/integrations/field.rb'
- 'app/models/integrations/harbor.rb'
- 'app/models/integrations/jenkins.rb'
- 'app/models/integrations/jira.rb'
@@ -142,8 +144,6 @@ Style/GuardClause:
- 'app/models/member.rb'
- 'app/models/members/project_member.rb'
- 'app/models/merge_request.rb'
- - 'app/models/merge_request_assignee.rb'
- - 'app/models/merge_request_reviewer.rb'
- 'app/models/namespace.rb'
- 'app/models/namespace_setting.rb'
- 'app/models/operations/feature_flags/strategy.rb'
@@ -161,6 +161,7 @@ Style/GuardClause:
- 'app/models/project_import_state.rb'
- 'app/models/project_label.rb'
- 'app/models/project_setting.rb'
+ - 'app/models/protected_branch.rb'
- 'app/models/protected_branch/push_access_level.rb'
- 'app/models/repository.rb'
- 'app/models/sent_notification.rb'
@@ -170,6 +171,8 @@ Style/GuardClause:
- 'app/models/user.rb'
- 'app/models/users/in_product_marketing_email.rb'
- 'app/models/wiki.rb'
+ - 'app/models/work_item.rb'
+ - 'app/models/work_items/parent_link.rb'
- 'app/presenters/ci/pipeline_presenter.rb'
- 'app/presenters/merge_request_presenter.rb'
- 'app/presenters/project_presenter.rb'
@@ -177,15 +180,19 @@ Style/GuardClause:
- 'app/services/bulk_imports/file_download_service.rb'
- 'app/services/ci/create_web_ide_terminal_service.rb'
- 'app/services/ci/daily_build_group_report_result_service.rb'
+ - 'app/services/ci/job_artifacts/destroy_batch_service.rb'
- 'app/services/ci/parse_dotenv_artifact_service.rb'
- 'app/services/ci/pipelines/add_job_service.rb'
- 'app/services/ci/play_build_service.rb'
- 'app/services/ci/retry_job_service.rb'
+ - 'app/services/ci/runners/reconcile_existing_runner_versions_service.rb'
+ - 'app/services/ci/runners/register_runner_service.rb'
- 'app/services/ci/update_build_queue_service.rb'
- 'app/services/clusters/agent_tokens/track_usage_service.rb'
- 'app/services/clusters/aws/fetch_credentials_service.rb'
- 'app/services/commits/commit_patch_service.rb'
- 'app/services/commits/create_service.rb'
+ - 'app/services/concerns/alert_management/alert_processing.rb'
- 'app/services/concerns/ci/job_token_scope/edit_scope_validations.rb'
- 'app/services/concerns/rate_limited_service.rb'
- 'app/services/concerns/update_repository_storage_methods.rb'
@@ -205,12 +212,12 @@ Style/GuardClause:
- 'app/services/import/gitlab_projects/file_acquisition_strategies/remote_file.rb'
- 'app/services/import/validate_remote_git_endpoint_service.rb'
- 'app/services/issuable/bulk_update_service.rb'
- - 'app/services/issuable/clone/base_service.rb'
- 'app/services/issuable/common_system_notes_service.rb'
- 'app/services/issuable_base_service.rb'
- 'app/services/issues/clone_service.rb'
- 'app/services/issues/move_service.rb'
- 'app/services/issues/update_service.rb'
+ - 'app/services/markdown_content_rewriter_service.rb'
- 'app/services/merge_requests/add_spent_time_service.rb'
- 'app/services/merge_requests/base_service.rb'
- 'app/services/merge_requests/build_service.rb'
@@ -238,10 +245,10 @@ Style/GuardClause:
- 'app/services/projects/import_export/export_service.rb'
- 'app/services/projects/import_service.rb'
- 'app/services/projects/lfs_pointers/lfs_object_download_list_service.rb'
- - 'app/services/projects/update_pages_service.rb'
- 'app/services/projects/update_repository_storage_service.rb'
- 'app/services/projects/update_service.rb'
- 'app/services/protected_branches/legacy_api_update_service.rb'
+ - 'app/services/repositories/changelog_service.rb'
- 'app/services/snippets/repository_validation_service.rb'
- 'app/services/todo_service.rb'
- 'app/services/users/build_service.rb'
@@ -268,20 +275,24 @@ Style/GuardClause:
- 'app/validators/rsa_key_validator.rb'
- 'app/validators/top_level_group_validator.rb'
- 'app/validators/x509_certificate_credentials_validator.rb'
- - 'app/workers/cleanup_container_repository_worker.rb'
- 'app/workers/clusters/agents/delete_expired_events_worker.rb'
- 'app/workers/concerns/application_worker.rb'
- 'app/workers/container_registry/migration/guard_worker.rb'
- 'app/workers/deployments/hooks_worker.rb'
- 'app/workers/deployments/link_merge_request_worker.rb'
- 'app/workers/gitlab/github_import/refresh_import_jid_worker.rb'
+ - 'app/workers/google_cloud/create_cloudsql_instance_worker.rb'
+ - 'app/workers/packages/cleanup/execute_policy_worker.rb'
- 'app/workers/packages/maven/metadata/sync_worker.rb'
+ - 'app/workers/projects/import_export/relation_export_worker.rb'
- 'app/workers/repository_update_remote_mirror_worker.rb'
+ - 'app/workers/terraform/states/destroy_worker.rb'
- 'config/initializers/0_inject_enterprise_edition_module.rb'
- 'config/initializers/carrierwave_patch.rb'
- 'config/initializers/devise_dynamic_password_length_validation.rb'
- 'config/initializers/google_api_client_patch.rb'
- 'config/initializers/postgresql_cte.rb'
+ - 'config/initializers/wikicloth_redos_patch.rb'
- 'config/object_store_settings.rb'
- 'danger/feature_flag/Dangerfile'
- 'db/migrate/20210302212623_rename_vuln_fingerprints_indexes.rb'
@@ -315,6 +326,7 @@ Style/GuardClause:
- 'ee/app/finders/ee/template_finder.rb'
- 'ee/app/finders/iterations_finder.rb'
- 'ee/app/finders/security/vulnerabilities_finder.rb'
+ - 'ee/app/graphql/mutations/concerns/mutations/shared_epic_arguments.rb'
- 'ee/app/graphql/mutations/iterations/create.rb'
- 'ee/app/graphql/mutations/iterations/update.rb'
- 'ee/app/graphql/mutations/projects/set_locked.rb'
@@ -322,13 +334,16 @@ Style/GuardClause:
- 'ee/app/graphql/resolvers/epics_resolver.rb'
- 'ee/app/graphql/resolvers/iterations_resolver.rb'
- 'ee/app/helpers/ee/application_helper.rb'
+ - 'ee/app/helpers/ee/auth_helper.rb'
- 'ee/app/helpers/ee/award_emoji_helper.rb'
- 'ee/app/helpers/ee/nav/new_dropdown_helper.rb'
- 'ee/app/helpers/ee/nav/top_nav_helper.rb'
+ - 'ee/app/helpers/ee/projects/pipeline_helper.rb'
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/models/allowed_email_domain.rb'
- 'ee/app/models/app_sec/fuzzing/coverage/corpus.rb'
- 'ee/app/models/approval_merge_request_rule_source.rb'
+ - 'ee/app/models/audit_events/external_audit_event_destination.rb'
- 'ee/app/models/concerns/app_sec/dast/buildable.rb'
- 'ee/app/models/concerns/ee/protected_ref_access.rb'
- 'ee/app/models/concerns/elastic/application_versioned_search.rb'
@@ -338,6 +353,7 @@ Style/GuardClause:
- 'ee/app/models/dast_site_profile.rb'
- 'ee/app/models/ee/application_setting.rb'
- 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/ee/group_group_link.rb'
- 'ee/app/models/ee/group_member.rb'
- 'ee/app/models/ee/incident_management/issuable_escalation_status.rb'
- 'ee/app/models/ee/issue.rb'
@@ -347,6 +363,7 @@ Style/GuardClause:
- 'ee/app/models/ee/merge_request.rb'
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/ee/project.rb'
+ - 'ee/app/models/ee/project_group_link.rb'
- 'ee/app/models/ee/project_member.rb'
- 'ee/app/models/ee/user.rb'
- 'ee/app/models/elasticsearch_indexed_project.rb'
@@ -361,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/sbom/occurrence.rb'
- 'ee/app/models/users_security_dashboard_project.rb'
- 'ee/app/models/vulnerabilities/feedback.rb'
- 'ee/app/presenters/ee/merge_request_presenter.rb'
@@ -384,8 +402,8 @@ Style/GuardClause:
- 'ee/app/services/ee/groups/update_service.rb'
- '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/merge_requests/merge_base_service.rb'
- - 'ee/app/services/ee/merge_requests/post_merge_service.rb'
- 'ee/app/services/ee/merge_requests/refresh_service.rb'
- 'ee/app/services/ee/namespace_settings/update_service.rb'
- 'ee/app/services/ee/projects/create_service.rb'
@@ -409,11 +427,12 @@ Style/GuardClause:
- 'ee/app/services/merge_trains/refresh_merge_request_service.rb'
- 'ee/app/services/merge_trains/refresh_service.rb'
- 'ee/app/services/namespaces/storage/email_notification_service.rb'
- - 'ee/app/services/projects/slack_application_install_service.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
- 'ee/app/services/security/override_uuids_service.rb'
- 'ee/app/services/timebox_report_service.rb'
+ - 'ee/app/services/vulnerabilities/security_finding/create_issue_service.rb'
- 'ee/app/validators/host_validator.rb'
+ - 'ee/app/validators/user_existence_validator.rb'
- 'ee/app/workers/ee/ci/build_finished_worker.rb'
- 'ee/app/workers/ee/post_receive.rb'
- 'ee/app/workers/elastic/migration_worker.rb'
@@ -462,6 +481,7 @@ Style/GuardClause:
- 'ee/lib/omni_auth/strategies/group_saml.rb'
- 'ee/spec/features/billings/billing_plans_spec.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb'
+ - 'ee/spec/support/ci/minutes_helpers.rb'
- 'ee/spec/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker_spec.rb'
- 'haml_lint/linter/documentation_links.rb'
- 'lib/api/commits.rb'
@@ -481,6 +501,7 @@ Style/GuardClause:
- 'lib/banzai/filter/wiki_link_filter/rewriter.rb'
- 'lib/bulk_imports/clients/graphql.rb'
- 'lib/bulk_imports/clients/http.rb'
+ - 'lib/bulk_imports/pipeline/runner.rb'
- 'lib/bulk_imports/projects/pipelines/project_pipeline.rb'
- 'lib/container_registry/client.rb'
- 'lib/feature/definition.rb'
@@ -525,21 +546,24 @@ Style/GuardClause:
- 'lib/gitlab/ci/reports/codequality_reports_comparer.rb'
- 'lib/gitlab/ci/reports/security/vulnerability_reports_comparer.rb'
- 'lib/gitlab/ci/runner/backoff.rb'
+ - 'lib/gitlab/ci/runner_upgrade_check.rb'
- 'lib/gitlab/ci/trace.rb'
- 'lib/gitlab/ci/trace/archive.rb'
- 'lib/gitlab/ci/trace/stream.rb'
- 'lib/gitlab/ci/yaml_processor.rb'
- 'lib/gitlab/config/entry/validators.rb'
+ - 'lib/gitlab/daemon.rb'
- 'lib/gitlab/database/background_migration/batch_optimizer.rb'
- 'lib/gitlab/database/background_migration/batched_migration_wrapper.rb'
- 'lib/gitlab/database/consistency_checker.rb'
- - 'lib/gitlab/database/load_balancing/configuration.rb'
- 'lib/gitlab/database/load_balancing/load_balancer.rb'
+ - 'lib/gitlab/database/lock_writes_manager.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/gitlab/database/migration_helpers/v2.rb'
- 'lib/gitlab/database/partitioning/partition_manager.rb'
- 'lib/gitlab/database/partitioning/sliding_list_strategy.rb'
- 'lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin.rb'
+ - 'lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb'
- 'lib/gitlab/database/query_analyzers/restrict_allowed_schemas.rb'
- 'lib/gitlab/diff/file.rb'
- 'lib/gitlab/diff/highlight.rb'
@@ -550,7 +574,6 @@ Style/GuardClause:
- 'lib/gitlab/email/hook/email_template_interceptor.rb'
- 'lib/gitlab/email/receiver.rb'
- 'lib/gitlab/endpoint_attributes/config.rb'
- - 'lib/gitlab/error_tracking.rb'
- 'lib/gitlab/event_store/event.rb'
- 'lib/gitlab/event_store/store.rb'
- 'lib/gitlab/exception_log_formatter.rb'
@@ -571,10 +594,7 @@ Style/GuardClause:
- 'lib/gitlab/github_import/object_counter.rb'
- 'lib/gitlab/gitlab_import/client.rb'
- 'lib/gitlab/gitlab_import/importer.rb'
- - 'lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb'
- - 'lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb'
- - 'lib/gitlab/graphql/pagination/keyset/order_info.rb'
- - 'lib/gitlab/graphql/pagination/keyset/query_builder.rb'
+ - 'lib/gitlab/graphql/query_analyzers/ast/recursion_analyzer.rb'
- 'lib/gitlab/i18n/metadata_entry.rb'
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb'
@@ -583,14 +603,19 @@ Style/GuardClause:
- 'lib/gitlab/import_export/command_line_util.rb'
- 'lib/gitlab/import_export/group/tree_restorer.rb'
- 'lib/gitlab/import_export/importer.rb'
+ - 'lib/gitlab/import_export/project/relation_factory.rb'
- 'lib/gitlab/import_export/repo_restorer.rb'
- 'lib/gitlab/import_export/snippet_repo_restorer.rb'
- 'lib/gitlab/import_export/version_checker.rb'
+ - 'lib/gitlab/instrumentation/global_search_api.rb'
+ - 'lib/gitlab/instrumentation/rate_limiting_gates.rb'
- 'lib/gitlab/instrumentation/redis_cluster_validator.rb'
- 'lib/gitlab/instrumentation/uploads.rb'
+ - 'lib/gitlab/issuable/clone/copy_resource_events_service.rb'
- 'lib/gitlab/legacy_github_import/client.rb'
- 'lib/gitlab/legacy_github_import/issuable_formatter.rb'
- 'lib/gitlab/marginalia.rb'
+ - 'lib/gitlab/memory/watchdog.rb'
- 'lib/gitlab/metrics/samplers/ruby_sampler.rb'
- 'lib/gitlab/metrics/subscribers/action_cable.rb'
- 'lib/gitlab/metrics/subscribers/active_record.rb'
@@ -598,6 +623,7 @@ Style/GuardClause:
- 'lib/gitlab/metrics/subscribers/rails_cache.rb'
- 'lib/gitlab/metrics/web_transaction.rb'
- 'lib/gitlab/middleware/read_only/controller.rb'
+ - 'lib/gitlab/pages/deployment_update.rb'
- 'lib/gitlab/pagination/gitaly_keyset_pager.rb'
- 'lib/gitlab/pagination/keyset/column_order_definition.rb'
- 'lib/gitlab/pagination/keyset/in_operator_optimization/array_scope_columns.rb'
@@ -626,6 +652,7 @@ Style/GuardClause:
- 'lib/gitlab/ssh_public_key.rb'
- 'lib/gitlab/url_blocker.rb'
- 'lib/gitlab/usage/metric_definition.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/count_bulk_imports_entities_metric.rb'
- 'lib/gitlab/usage_data_counters/ci_template_unique_counter.rb'
- 'lib/gitlab/utils.rb'
- 'lib/gitlab/utils/override.rb'
@@ -633,6 +660,7 @@ Style/GuardClause:
- 'lib/mattermost/session.rb'
- 'lib/release_highlights/validator/entry.rb'
- 'lib/safe_zip/entry.rb'
+ - 'lib/service_ping/devops_report.rb'
- 'lib/system_check/app/systemd_unit_files_or_init_script_up_to_date_check.rb'
- 'lib/system_check/incoming_email/mail_room_running_check.rb'
- 'lib/tasks/config_lint.rake'
@@ -647,22 +675,22 @@ Style/GuardClause:
- 'qa/qa/page/component/snippet.rb'
- 'qa/qa/page/mattermost/login.rb'
- 'qa/qa/page/page_concern.rb'
+ - 'qa/qa/page/project/settings/deploy_tokens.rb'
- 'qa/qa/resource/api_fabricator.rb'
- 'qa/qa/resource/package.rb'
+ - 'qa/qa/resource/project.rb'
- 'qa/qa/resource/registry_repository.rb'
- 'qa/qa/resource/reusable.rb'
- 'qa/qa/resource/user_gpg.rb'
- 'qa/qa/runtime/feature.rb'
- 'qa/qa/runtime/search.rb'
- 'qa/qa/service/cluster_provider/gcloud.rb'
- - 'qa/qa/service/docker_run/gitlab_runner.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/11_fulfillment/purchase/free_trial_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_file_template_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/group_file_template_spec.rb'
- 'qa/qa/specs/helpers/feature_flag.rb'
- - 'qa/qa/support/page_error_checker.rb'
+ - 'qa/qa/vendor/jenkins/job.rb'
- 'rubocop/cop/api/grape_array_missing_coerce.rb'
- 'rubocop/cop/gitlab/duplicate_spec_location.rb'
- 'rubocop/cop/gitlab/event_store_subscriber.rb'
@@ -702,6 +730,7 @@ Style/GuardClause:
- 'spec/support/import_export/export_file_helper.rb'
- 'spec/support/shared_examples/features/packages_shared_examples.rb'
- 'spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb'
+ - 'spec/tooling/lib/tooling/find_codeowners_spec.rb'
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'
- 'tooling/lib/tooling/helm3_client.rb'
- 'tooling/lib/tooling/image.rb'
diff --git a/.rubocop_todo/style/hash_as_last_array_item.yml b/.rubocop_todo/style/hash_as_last_array_item.yml
index eec2e77eafd..384d2dc5fce 100644
--- a/.rubocop_todo/style/hash_as_last_array_item.yml
+++ b/.rubocop_todo/style/hash_as_last_array_item.yml
@@ -1,15 +1,11 @@
---
# Cop supports --auto-correct.
Style/HashAsLastArrayItem:
- # Offense count: 79
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/admin/application_settings_controller.rb'
- 'app/controllers/admin/groups_controller.rb'
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/boards/issues_controller.rb'
- - 'app/controllers/clusters/clusters_controller.rb'
- 'app/controllers/concerns/issuable_actions.rb'
- 'app/controllers/concerns/issuable_collections.rb'
- 'app/controllers/profiles_controller.rb'
@@ -29,6 +25,7 @@ Style/HashAsLastArrayItem:
- 'app/models/customer_relations/contact.rb'
- 'app/models/customer_relations/organization.rb'
- 'app/models/deploy_key.rb'
+ - 'app/models/deployment.rb'
- 'app/models/issue.rb'
- 'app/models/merge_request.rb'
- 'app/models/milestone.rb'
@@ -59,4 +56,5 @@ Style/HashAsLastArrayItem:
- 'spec/services/git/branch_hooks_service_spec.rb'
- 'spec/services/metrics/dashboard/panel_preview_service_spec.rb'
- 'spec/support/helpers/rack_attack_spec_helpers.rb'
+ - 'spec/workers/concerns/worker_attributes_spec.rb'
- 'spec/workers/merge_worker_spec.rb'
diff --git a/.rubocop_todo/style/hash_each_methods.yml b/.rubocop_todo/style/hash_each_methods.yml
index 648b6fbbe08..cebfe5c0c7d 100644
--- a/.rubocop_todo/style/hash_each_methods.yml
+++ b/.rubocop_todo/style/hash_each_methods.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/HashEachMethods:
- # Offense count: 95
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/graphql/resolvers/concerns/caching_array_resolver.rb'
- 'app/graphql/types/alert_management/severity_enum.rb'
@@ -12,6 +9,7 @@ Style/HashEachMethods:
- 'app/graphql/types/ci/job_artifact_file_type_enum.rb'
- 'app/graphql/types/ci/pipeline_config_source_enum.rb'
- 'app/graphql/types/ci/runner_access_level_enum.rb'
+ - 'app/graphql/types/ci/variable_type_enum.rb'
- 'app/graphql/types/clusters/agent_token_status_enum.rb'
- 'app/graphql/types/container_repository_status_enum.rb'
- 'app/graphql/types/data_visualization_palette/color_enum.rb'
@@ -34,6 +32,7 @@ Style/HashEachMethods:
- 'config/initializers/8_gitaly.rb'
- 'ee/app/graphql/types/compliance_management/merge_requests/compliance_violation_reason_enum.rb'
- 'ee/app/graphql/types/compliance_management/merge_requests/compliance_violation_severity_enum.rb'
+ - 'ee/app/graphql/types/incident_management/issuable_resource_link_type_enum.rb'
- 'ee/app/graphql/types/incident_management/oncall_rotation_length_unit_enum.rb'
- 'ee/app/graphql/types/security_report_summary_type.rb'
- 'ee/app/graphql/types/vulnerabilities_count_by_day_type.rb'
@@ -69,7 +68,6 @@ Style/HashEachMethods:
- 'spec/helpers/application_helper_spec.rb'
- 'spec/lib/gitlab/ci/status/build/failed_spec.rb'
- 'spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb'
- - 'spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb'
- 'spec/lib/gitlab/usage_data_spec.rb'
- 'spec/models/ci/build_spec.rb'
- 'spec/models/ci/job_artifact_spec.rb'
@@ -77,6 +75,7 @@ Style/HashEachMethods:
- 'spec/models/clusters/cluster_spec.rb'
- 'spec/models/concerns/has_user_type_spec.rb'
- 'spec/models/packages/package_spec.rb'
+ - 'spec/models/project_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/presenters/ci/pipeline_presenter_spec.rb'
- 'spec/presenters/commit_status_presenter_spec.rb'
diff --git a/.rubocop_todo/style/if_inside_else.yml b/.rubocop_todo/style/if_inside_else.yml
index 3ce6e5ec704..40b71d7de04 100644
--- a/.rubocop_todo/style/if_inside_else.yml
+++ b/.rubocop_todo/style/if_inside_else.yml
@@ -1,17 +1,13 @@
---
Style/IfInsideElse:
- # Offense count: 43
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/application_controller.rb'
- 'app/controllers/passwords_controller.rb'
- 'app/finders/projects_finder.rb'
- - 'app/finders/user_recent_events_finder.rb'
- 'app/helpers/diff_helper.rb'
+ - 'app/helpers/issuables_helper.rb'
- 'app/helpers/members_helper.rb'
- 'app/helpers/search_helper.rb'
- - 'app/models/ci/build.rb'
- 'app/models/namespace.rb'
- 'app/presenters/project_presenter.rb'
- 'app/services/system_notes/commit_service.rb'
@@ -22,6 +18,7 @@ Style/IfInsideElse:
- 'ee/app/controllers/ee/registrations/welcome_controller.rb'
- 'ee/app/controllers/groups/omniauth_callbacks_controller.rb'
- 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/iterations/cadence.rb'
- 'ee/app/models/protected_environments/authorizable.rb'
- 'ee/app/policies/ee/group_policy.rb'
- 'ee/app/services/app_sec/dast/site_profiles/audit/update_service.rb'
@@ -30,12 +27,15 @@ Style/IfInsideElse:
- 'ee/app/services/geo/repository_base_sync_service.rb'
- 'ee/app/services/gitlab_subscriptions/fetch_subscription_plans_service.rb'
- 'ee/app/services/vulnerability_external_issue_links/create_service.rb'
+ - 'ee/app/workers/elastic/project_transfer_worker.rb'
+ - 'ee/app/workers/project_import_schedule_worker.rb'
- 'ee/lib/gitlab/geo/base_batcher.rb'
- 'lib/api/projects.rb'
- 'lib/gitlab/auth.rb'
- 'lib/gitlab/conflict/file.rb'
- 'lib/gitlab/sql/pattern.rb'
- 'lib/gitlab/usage/service_ping/payload_keys_processor.rb'
+ - 'lib/service_ping/build_payload.rb'
- 'lib/tasks/gitlab/cleanup.rake'
- 'lib/tasks/gitlab/shell.rake'
- 'qa/qa/resource/protected_branch.rb'
diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml
index 1dfedcc91c0..a58f71aee8f 100644
--- a/.rubocop_todo/style/if_unless_modifier.yml
+++ b/.rubocop_todo/style/if_unless_modifier.yml
@@ -1,14 +1,10 @@
---
# Cop supports --auto-correct.
Style/IfUnlessModifier:
- # Offense count: 1937
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/channels/graphql_channel.rb'
- 'app/controllers/admin/application_settings_controller.rb'
- 'app/controllers/admin/projects_controller.rb'
- - 'app/controllers/admin/runners_controller.rb'
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/controllers/concerns/controller_with_cross_project_access_check.rb'
@@ -25,6 +21,8 @@ Style/IfUnlessModifier:
- 'app/controllers/concerns/paginated_collection.rb'
- 'app/controllers/concerns/record_user_last_activity.rb'
- 'app/controllers/concerns/sorting_preference.rb'
+ - 'app/controllers/concerns/uploads_actions.rb'
+ - 'app/controllers/concerns/verifies_with_email.rb'
- 'app/controllers/concerns/wiki_actions.rb'
- 'app/controllers/concerns/with_performance_bar.rb'
- 'app/controllers/explore/projects_controller.rb'
@@ -33,9 +31,9 @@ Style/IfUnlessModifier:
- 'app/controllers/groups_controller.rb'
- 'app/controllers/import/fogbugz_controller.rb'
- 'app/controllers/import/gitea_controller.rb'
+ - 'app/controllers/import/github_controller.rb'
- 'app/controllers/import/gitlab_controller.rb'
- 'app/controllers/import/manifest_controller.rb'
- - 'app/controllers/jira_connect/application_controller.rb'
- 'app/controllers/jwt_controller.rb'
- 'app/controllers/omniauth_callbacks_controller.rb'
- 'app/controllers/profiles/emails_controller.rb'
@@ -53,12 +51,15 @@ Style/IfUnlessModifier:
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/merge_requests/diffs_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
+ - 'app/controllers/projects/pipelines/tests_controller.rb'
- 'app/controllers/projects/protected_refs_controller.rb'
- 'app/controllers/projects/releases_controller.rb'
- 'app/controllers/projects/runners_controller.rb'
+ - 'app/controllers/projects_controller.rb'
- 'app/controllers/registrations_controller.rb'
- 'app/controllers/repositories/git_http_controller.rb'
- 'app/controllers/repositories/lfs_api_controller.rb'
+ - 'app/controllers/repositories/lfs_storage_controller.rb'
- 'app/controllers/sessions_controller.rb'
- 'app/controllers/users/terms_controller.rb'
- 'app/finders/autocomplete/users_finder.rb'
@@ -92,7 +93,6 @@ Style/IfUnlessModifier:
- 'app/graphql/mutations/release_asset_links/delete.rb'
- 'app/graphql/mutations/release_asset_links/update.rb'
- 'app/graphql/mutations/todos/mark_all_done.rb'
- - 'app/graphql/mutations/work_items/create.rb'
- 'app/graphql/resolvers/blobs_resolver.rb'
- 'app/graphql/resolvers/ci/runner_jobs_resolver.rb'
- 'app/graphql/resolvers/concerns/board_item_filterable.rb'
@@ -105,7 +105,6 @@ Style/IfUnlessModifier:
- 'app/graphql/resolvers/timelog_resolver.rb'
- 'app/graphql/types/ci/job_type.rb'
- 'app/helpers/admin/user_actions_helper.rb'
- - 'app/helpers/appearances_helper.rb'
- 'app/helpers/blob_helper.rb'
- 'app/helpers/button_helper.rb'
- 'app/helpers/ci/status_helper.rb'
@@ -116,7 +115,6 @@ Style/IfUnlessModifier:
- 'app/helpers/events_helper.rb'
- 'app/helpers/form_helper.rb'
- 'app/helpers/groups_helper.rb'
- - 'app/helpers/issuables_description_templates_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/issues_helper.rb'
- 'app/helpers/lazy_image_tag_helper.rb'
@@ -135,6 +133,7 @@ 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'
@@ -153,6 +152,7 @@ Style/IfUnlessModifier:
- 'app/models/ci/build.rb'
- 'app/models/ci/build_trace_chunk.rb'
- 'app/models/ci/job_artifact.rb'
+ - 'app/models/ci/pending_build.rb'
- 'app/models/ci/pipeline.rb'
- 'app/models/ci/runner.rb'
- 'app/models/ci/running_build.rb'
@@ -170,7 +170,6 @@ Style/IfUnlessModifier:
- 'app/models/concerns/ci/artifactable.rb'
- 'app/models/concerns/counter_attribute.rb'
- 'app/models/concerns/deprecated_assignee.rb'
- - 'app/models/concerns/diff_positionable_note.rb'
- 'app/models/concerns/group_descendant.rb'
- 'app/models/concerns/has_wiki_page_meta_attributes.rb'
- 'app/models/concerns/id_in_ordered.rb'
@@ -178,10 +177,10 @@ Style/IfUnlessModifier:
- 'app/models/concerns/issuable.rb'
- 'app/models/concerns/issuable_link.rb'
- 'app/models/concerns/issue_available_features.rb'
- - 'app/models/concerns/limitable.rb'
- 'app/models/concerns/mentionable.rb'
- 'app/models/concerns/noteable.rb'
- 'app/models/concerns/routable.rb'
+ - 'app/models/concerns/sha_attribute.rb'
- 'app/models/concerns/timebox.rb'
- 'app/models/concerns/token_authenticatable_strategies/base.rb'
- 'app/models/concerns/token_authenticatable_strategies/digest.rb'
@@ -195,6 +194,7 @@ Style/IfUnlessModifier:
- 'app/models/error_tracking/project_error_tracking_setting.rb'
- 'app/models/external_pull_request.rb'
- 'app/models/generic_commit_status.rb'
+ - 'app/models/grafana_integration.rb'
- 'app/models/group.rb'
- 'app/models/integrations/asana.rb'
- 'app/models/integrations/bamboo.rb'
@@ -205,6 +205,7 @@ Style/IfUnlessModifier:
- 'app/models/integrations/jira.rb'
- 'app/models/integrations/pushover.rb'
- 'app/models/integrations/teamcity.rb'
+ - 'app/models/issue.rb'
- 'app/models/issue_email_participant.rb'
- 'app/models/label_note.rb'
- 'app/models/list.rb'
@@ -217,7 +218,6 @@ Style/IfUnlessModifier:
- 'app/models/namespace.rb'
- 'app/models/namespace_setting.rb'
- 'app/models/namespaces/traversal/linear.rb'
- - 'app/models/namespaces/traversal/linear_scopes.rb'
- 'app/models/network/graph.rb'
- 'app/models/note.rb'
- 'app/models/notification_setting.rb'
@@ -239,7 +239,6 @@ Style/IfUnlessModifier:
- 'app/models/remote_mirror.rb'
- 'app/models/repository.rb'
- 'app/models/route.rb'
- - 'app/models/sent_notification.rb'
- 'app/models/service_desk_setting.rb'
- 'app/models/snippet_input_action.rb'
- 'app/models/state_note.rb'
@@ -247,6 +246,8 @@ Style/IfUnlessModifier:
- 'app/models/synthetic_note.rb'
- 'app/models/user.rb'
- 'app/models/wiki.rb'
+ - 'app/models/work_items/parent_link.rb'
+ - 'app/policies/project_policy.rb'
- 'app/presenters/blob_presenter.rb'
- 'app/presenters/ci/pipeline_presenter.rb'
- 'app/presenters/merge_request_presenter.rb'
@@ -266,7 +267,6 @@ Style/IfUnlessModifier:
- 'app/services/boards/lists/base_create_service.rb'
- 'app/services/boards/lists/list_service.rb'
- 'app/services/branches/validate_new_service.rb'
- - 'app/services/bulk_imports/file_decompression_service.rb'
- 'app/services/ci/create_pipeline_service.rb'
- 'app/services/ci/create_web_ide_terminal_service.rb'
- 'app/services/ci/job_token_scope/remove_project_service.rb'
@@ -276,6 +276,8 @@ Style/IfUnlessModifier:
- 'app/services/ci/register_job_service.rb'
- 'app/services/ci/retry_job_service.rb'
- 'app/services/ci/run_scheduled_build_service.rb'
+ - 'app/services/ci/runners/reconcile_existing_runner_versions_service.rb'
+ - 'app/services/ci/runners/register_runner_service.rb'
- 'app/services/ci/update_build_state_service.rb'
- 'app/services/clusters/applications/base_service.rb'
- 'app/services/clusters/applications/prometheus_update_service.rb'
@@ -299,6 +301,7 @@ Style/IfUnlessModifier:
- 'app/services/error_tracking/collect_error_service.rb'
- 'app/services/git/process_ref_changes_service.rb'
- 'app/services/google_cloud/generate_pipeline_service.rb'
+ - 'app/services/google_cloud/setup_cloudsql_instance_service.rb'
- 'app/services/groups/create_service.rb'
- 'app/services/groups/transfer_service.rb'
- 'app/services/groups/update_statistics_service.rb'
@@ -314,7 +317,6 @@ Style/IfUnlessModifier:
- 'app/services/issues/relative_position_rebalancing_service.rb'
- 'app/services/issues/update_service.rb'
- 'app/services/lfs/lock_file_service.rb'
- - 'app/services/members/approve_access_request_service.rb'
- 'app/services/members/destroy_service.rb'
- 'app/services/members/update_service.rb'
- 'app/services/merge_requests/add_context_service.rb'
@@ -322,7 +324,6 @@ Style/IfUnlessModifier:
- '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/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'
@@ -371,8 +372,8 @@ Style/IfUnlessModifier:
- 'app/services/projects/overwrite_project_service.rb'
- 'app/services/projects/participants_service.rb'
- 'app/services/projects/transfer_service.rb'
- - 'app/services/projects/update_pages_service.rb'
- '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'
@@ -388,6 +389,8 @@ Style/IfUnlessModifier:
- 'app/services/users/respond_to_terms_service.rb'
- 'app/services/wikis/create_attachment_service.rb'
- 'app/services/work_items/create_service.rb'
+ - 'app/services/work_items/parent_links/create_service.rb'
+ - 'app/services/work_items/task_list_reference_removal_service.rb'
- 'app/services/work_items/task_list_reference_replacement_service.rb'
- 'app/uploaders/file_mover.rb'
- 'app/uploaders/object_storage.rb'
@@ -408,17 +411,20 @@ Style/IfUnlessModifier:
- 'app/views/projects/merge_requests/index.atom.builder'
- 'app/workers/authorized_project_update/user_refresh_from_replica_worker.rb'
- 'app/workers/auto_devops/disable_worker.rb'
- - 'app/workers/cleanup_container_repository_worker.rb'
- 'app/workers/concerns/application_worker.rb'
- 'app/workers/concerns/packages/cleanup_artifact_worker.rb'
- 'app/workers/concerns/project_start_import.rb'
+ - 'app/workers/concerns/waitable_worker.rb'
- 'app/workers/concerns/worker_attributes.rb'
- 'app/workers/database/batched_background_migration/single_database_worker.rb'
+ - 'app/workers/delete_container_repository_worker.rb'
- 'app/workers/file_hook_worker.rb'
+ - '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'
- 'app/workers/repository_update_remote_mirror_worker.rb'
@@ -429,11 +435,10 @@ Style/IfUnlessModifier:
- 'config/initializers/1_settings.rb'
- 'config/initializers/6_validations.rb'
- 'config/initializers/8_devise.rb'
- - 'config/initializers/active_record_data_types.rb'
- 'config/initializers/active_record_transaction_patches.rb'
- - 'config/initializers/content_security_policy.rb'
- 'config/initializers/default_url_options.rb'
- 'config/initializers/direct_upload_support.rb'
+ - 'config/initializers/doorkeeper.rb'
- 'config/initializers/geo.rb'
- 'config/initializers/google_api_client.rb'
- 'config/initializers/google_api_client_patch.rb'
@@ -449,7 +454,6 @@ Style/IfUnlessModifier:
- 'config/initializers/zz_metrics.rb'
- 'config/initializers_before_autoloader/002_sidekiq.rb'
- 'config/routes.rb'
- - 'config/settings.rb'
- 'danger/database/Dangerfile'
- 'danger/pipeline/Dangerfile'
- 'danger/specs/Dangerfile'
@@ -465,7 +469,8 @@ Style/IfUnlessModifier:
- 'db/post_migrate/20211021140426_remove_geo_upload_deprecated_fields.rb'
- 'db/post_migrate/20220128155814_fix_approval_rules_code_owners_rule_type_index.rb'
- 'db/post_migrate/20220131000001_schedule_trace_expiry_removal.rb'
- - 'ee/app/controllers/admin/audit_logs_controller.rb'
+ - 'db/post_migrate/20220523171107_drop_deploy_tokens_token_column.rb'
+ - 'ee/app/components/namespaces/storage/limit_alert_component.rb'
- 'ee/app/controllers/admin/elasticsearch_controller.rb'
- 'ee/app/controllers/admin/emails_controller.rb'
- 'ee/app/controllers/admin/geo/application_controller.rb'
@@ -495,10 +500,11 @@ Style/IfUnlessModifier:
- 'ee/app/finders/merge_trains_finder.rb'
- 'ee/app/finders/security/pipeline_vulnerabilities_finder.rb'
- 'ee/app/finders/security/vulnerabilities_finder.rb'
- - 'ee/app/graphql/ee/mutations/issues/create.rb'
- 'ee/app/graphql/ee/resolvers/base_issues_resolver.rb'
- 'ee/app/graphql/mutations/audit_events/external_audit_event_destinations/create.rb'
- 'ee/app/graphql/mutations/audit_events/external_audit_event_destinations/destroy.rb'
+ - 'ee/app/graphql/mutations/boards/scoped_board_mutation.rb'
+ - 'ee/app/graphql/mutations/dast_site_profiles/create.rb'
- 'ee/app/graphql/mutations/iterations/update.rb'
- 'ee/app/graphql/mutations/projects/set_locked.rb'
- 'ee/app/graphql/resolvers/analytics/devops_adoption/enabled_namespaces_resolver.rb'
@@ -506,39 +512,37 @@ Style/IfUnlessModifier:
- 'ee/app/graphql/resolvers/boards/epic_lists_resolver.rb'
- 'ee/app/graphql/resolvers/iterations/cadences_resolver.rb'
- 'ee/app/helpers/billing_plans_helper.rb'
- - 'ee/app/helpers/ee/application_helper.rb'
- 'ee/app/helpers/ee/dashboard_helper.rb'
- - 'ee/app/helpers/ee/environments_helper.rb'
- 'ee/app/helpers/ee/integrations_helper.rb'
- 'ee/app/helpers/ee/issues_helper.rb'
- 'ee/app/helpers/ee/labels_helper.rb'
- 'ee/app/helpers/ee/merge_requests_helper.rb'
- 'ee/app/helpers/ee/notes_helper.rb'
- 'ee/app/helpers/ee/personal_access_tokens_helper.rb'
+ - 'ee/app/helpers/ee/projects/pipeline_helper.rb'
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/models/allowed_email_domain.rb'
- 'ee/app/models/app_sec/fuzzing/coverage/corpus.rb'
+ - 'ee/app/models/approval_project_rule.rb'
- 'ee/app/models/concerns/ee/protected_ref_access.rb'
- 'ee/app/models/concerns/elastic/application_versioned_search.rb'
- - 'ee/app/models/concerns/geo/replicable_model.rb'
- 'ee/app/models/concerns/geo/verifiable_replicator.rb'
- 'ee/app/models/concerns/security/scan_execution_policy.rb'
- 'ee/app/models/dast_site_profile.rb'
- 'ee/app/models/ee/application_setting.rb'
+ - 'ee/app/models/ee/ci/job_artifact.rb'
+ - 'ee/app/models/ee/group.rb'
- 'ee/app/models/ee/group_member.rb'
- 'ee/app/models/ee/issue.rb'
- 'ee/app/models/ee/iteration.rb'
- 'ee/app/models/ee/key.rb'
- 'ee/app/models/ee/list.rb'
- - 'ee/app/models/ee/member.rb'
- 'ee/app/models/ee/milestone_release.rb'
- 'ee/app/models/ee/namespace.rb'
- - 'ee/app/models/ee/namespace/root_storage_size.rb'
- 'ee/app/models/ee/project.rb'
- 'ee/app/models/ee/project_feature.rb'
- 'ee/app/models/ee/project_team.rb'
- 'ee/app/models/ee/user.rb'
- - 'ee/app/models/ee/vulnerability.rb'
- 'ee/app/models/geo/project_registry.rb'
- 'ee/app/models/geo/tracking_base.rb'
- 'ee/app/models/incident_management/escalation_rule.rb'
@@ -554,6 +558,7 @@ Style/IfUnlessModifier:
- 'ee/app/serializers/vulnerabilities/finding_serializer.rb'
- 'ee/app/services/analytics/cycle_analytics/aggregator_service.rb'
- 'ee/app/services/analytics/cycle_analytics/validations.rb'
+ - 'ee/app/services/app_sec/dast/pipelines/find_latest_service.rb'
- 'ee/app/services/app_sec/dast/profiles/build_config_service.rb'
- 'ee/app/services/app_sec/dast/profiles/create_associations_service.rb'
- 'ee/app/services/app_sec/dast/scan_configs/build_service.rb'
@@ -564,7 +569,6 @@ Style/IfUnlessModifier:
- 'ee/app/services/app_sec/dast/site_profiles/destroy_service.rb'
- 'ee/app/services/app_sec/dast/site_profiles/update_service.rb'
- 'ee/app/services/app_sec/fuzzing/api/ci_configuration_create_service.rb'
- - 'ee/app/services/audit_events/runner_audit_event_service.rb'
- 'ee/app/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service.rb'
- 'ee/app/services/billable_members/destroy_service.rb'
- 'ee/app/services/boards/epic_boards/create_service.rb'
@@ -572,6 +576,7 @@ Style/IfUnlessModifier:
- 'ee/app/services/boards/epics/create_service.rb'
- 'ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb'
- 'ee/app/services/ci/subscribe_bridge_service.rb'
+ - 'ee/app/services/ci/sync_reports_to_approval_rules_service.rb'
- 'ee/app/services/compliance_management/frameworks/create_service.rb'
- 'ee/app/services/compliance_management/merge_requests/create_compliance_violations_service.rb'
- 'ee/app/services/deployments/auto_rollback_service.rb'
@@ -581,15 +586,13 @@ Style/IfUnlessModifier:
- 'ee/app/services/ee/audit_event_service.rb'
- 'ee/app/services/ee/boards/base_service.rb'
- 'ee/app/services/ee/boards/issues/move_service.rb'
+ - 'ee/app/services/ee/ci/runners/reset_registration_token_service.rb'
- 'ee/app/services/ee/commits/create_service.rb'
- 'ee/app/services/ee/deploy_keys/create_service.rb'
- 'ee/app/services/ee/groups/update_service.rb'
- 'ee/app/services/ee/ip_restrictions/update_service.rb'
- 'ee/app/services/ee/issuable_base_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/refresh_service.rb'
- 'ee/app/services/ee/merge_requests/update_service.rb'
- 'ee/app/services/ee/milestones/update_service.rb'
@@ -598,16 +601,18 @@ Style/IfUnlessModifier:
- 'ee/app/services/ee/projects/destroy_service.rb'
- 'ee/app/services/ee/projects/gitlab_projects_import_service.rb'
- 'ee/app/services/ee/protected_branches/create_service.rb'
- - 'ee/app/services/ee/resource_events/change_labels_service.rb'
- 'ee/app/services/ee/todo_service.rb'
- 'ee/app/services/ee/users/update_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'
- 'ee/app/services/epics/create_service.rb'
+ - 'ee/app/services/epics/epic_links/create_service.rb'
+ - 'ee/app/services/epics/epic_links/update_service.rb'
- 'ee/app/services/epics/update_dates_service.rb'
- 'ee/app/services/epics/update_service.rb'
- 'ee/app/services/external_status_checks/create_service.rb'
+ - 'ee/app/services/geo/file_registry_removal_service.rb'
- 'ee/app/services/geo/metrics_update_service.rb'
- 'ee/app/services/geo/move_repository_service.rb'
- 'ee/app/services/geo/prune_event_log_service.rb'
@@ -625,7 +630,6 @@ Style/IfUnlessModifier:
- 'ee/app/services/merge_requests/update_blocks_service.rb'
- 'ee/app/services/merge_trains/refresh_merge_request_service.rb'
- 'ee/app/services/projects/mark_for_deletion_service.rb'
- - 'ee/app/services/projects/slack_application_install_service.rb'
- 'ee/app/services/projects/update_mirror_service.rb'
- 'ee/app/services/resource_events/change_weight_service.rb'
- 'ee/app/services/security/dependency_list_service.rb'
@@ -649,17 +653,18 @@ Style/IfUnlessModifier:
- 'ee/app/services/vulnerability_feedback/destroy_service.rb'
- 'ee/app/services/vulnerability_feedback_module/update_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'
- 'ee/app/workers/audit_events/audit_event_streaming_worker.rb'
- 'ee/app/workers/concerns/elastic/migration_helper.rb'
- 'ee/app/workers/ee/ci/build_finished_worker.rb'
- - 'ee/app/workers/ee/post_receive.rb'
+ - 'ee/app/workers/elastic/project_transfer_worker.rb'
- 'ee/app/workers/epics/new_epic_issue_worker.rb'
- 'ee/app/workers/geo/secondary/registry_consistency_worker.rb'
- 'ee/app/workers/security/orchestration_policy_rule_schedule_namespace_worker.rb'
- 'ee/db/geo/migrate/20170627195211_add_index_to_project_registry.rb'
- 'ee/db/geo/migrate/20180402170913_add_missing_on_primary_to_job_artifact_registry..rb'
- - 'ee/lib/analytics/devops_adoption/snapshot_calculator.rb'
+ - 'ee/elastic/migrate/20220119120500_populate_commit_permissions_in_main_index.rb'
- 'ee/lib/api/epics.rb'
- 'ee/lib/api/merge_request_approval_rules.rb'
- 'ee/lib/api/protected_environments.rb'
@@ -679,7 +684,6 @@ Style/IfUnlessModifier:
- 'ee/lib/ee/container_registry/client.rb'
- 'ee/lib/ee/gitlab/auth/ldap/access.rb'
- 'ee/lib/ee/gitlab/auth/ldap/group.rb'
- - 'ee/lib/ee/gitlab/background_migration/drop_invalid_remediations.rb'
- 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb'
- 'ee/lib/ee/gitlab/checks/diff_check.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/tag_check.rb'
@@ -713,7 +717,7 @@ Style/IfUnlessModifier:
- 'ee/lib/gitlab/geo/replication/blob_downloader.rb'
- 'ee/lib/gitlab/geo/replicator.rb'
- 'ee/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate.rb'
- - 'ee/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate.rb'
+ - 'ee/lib/gitlab/graphql/aggregations/issuables/lazy_links_aggregate.rb'
- 'ee/lib/gitlab/graphql/aggregations/security_orchestration_policies/lazy_dast_profile_aggregate.rb'
- 'ee/lib/gitlab/graphql/aggregations/vulnerabilities/lazy_user_notes_count_aggregate.rb'
- 'ee/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate.rb'
@@ -741,7 +745,6 @@ Style/IfUnlessModifier:
- 'ee/spec/graphql/types/pipeline_security_report_finding_type_spec.rb'
- 'ee/spec/helpers/ee/users/callouts_helper_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/project_search_results_spec.rb'
- 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
- 'ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb'
- 'ee/spec/models/concerns/elastic/note_spec.rb'
@@ -766,7 +769,6 @@ Style/IfUnlessModifier:
- 'lib/api/ci/pipeline_schedules.rb'
- 'lib/api/ci/runner.rb'
- 'lib/api/ci/runners.rb'
- - 'lib/api/ci/secure_files.rb'
- 'lib/api/commits.rb'
- 'lib/api/debian_project_packages.rb'
- 'lib/api/deployments.rb'
@@ -775,7 +777,6 @@ Style/IfUnlessModifier:
- 'lib/api/entities/member_access.rb'
- 'lib/api/entities/project_import_status.rb'
- 'lib/api/feature_flags.rb'
- - 'lib/api/feature_flags_user_lists.rb'
- 'lib/api/files.rb'
- 'lib/api/groups.rb'
- 'lib/api/helm_packages.rb'
@@ -791,14 +792,15 @@ Style/IfUnlessModifier:
- 'lib/api/helpers/projects_helpers.rb'
- 'lib/api/helpers/users_helpers.rb'
- 'lib/api/helpers/version.rb'
+ - 'lib/api/helpers/web_hooks_helpers.rb'
- 'lib/api/internal/base.rb'
- 'lib/api/internal/container_registry/migration.rb'
+ - 'lib/api/internal/error_tracking.rb'
- 'lib/api/invitations.rb'
- 'lib/api/maven_packages.rb'
- 'lib/api/merge_requests.rb'
- 'lib/api/nuget_project_packages.rb'
- 'lib/api/pages_domains.rb'
- - 'lib/api/project_clusters.rb'
- 'lib/api/project_snippets.rb'
- 'lib/api/projects.rb'
- 'lib/api/projects_relation_builder.rb'
@@ -840,6 +842,7 @@ Style/IfUnlessModifier:
- 'lib/generators/gitlab/usage_metric_generator.rb'
- 'lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb'
- 'lib/gitlab/analytics/cycle_analytics/request_params.rb'
+ - 'lib/gitlab/application_context.rb'
- 'lib/gitlab/auth.rb'
- 'lib/gitlab/auth/auth_finders.rb'
- 'lib/gitlab/auth/ldap/adapter.rb'
@@ -861,6 +864,7 @@ Style/IfUnlessModifier:
- 'lib/gitlab/checks/matching_merge_request.rb'
- 'lib/gitlab/checks/push_check.rb'
- 'lib/gitlab/checks/push_file_count_check.rb'
+ - 'lib/gitlab/checks/tag_check.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ci/ansi2json/converter.rb'
- 'lib/gitlab/ci/ansi2json/style.rb'
@@ -876,7 +880,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/ci/config/entry/jobs.rb'
- 'lib/gitlab/ci/config/entry/needs.rb'
- 'lib/gitlab/ci/config/entry/policy.rb'
- - 'lib/gitlab/ci/config/entry/processable.rb'
- 'lib/gitlab/ci/config/entry/product/matrix.rb'
- 'lib/gitlab/ci/config/extendable/entry.rb'
- 'lib/gitlab/ci/config/external/file/base.rb'
@@ -912,6 +915,7 @@ Style/IfUnlessModifier:
- 'lib/gitlab/content_security_policy/config_loader.rb'
- 'lib/gitlab/cross_project_access/check_info.rb'
- 'lib/gitlab/data_builder/deployment.rb'
+ - 'lib/gitlab/data_builder/pipeline.rb'
- 'lib/gitlab/database/as_with_materialized.rb'
- 'lib/gitlab/database/background_migration/batched_job.rb'
- 'lib/gitlab/database/background_migration/batched_migration_wrapper.rb'
@@ -932,8 +936,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- 'lib/gitlab/database/transaction/observer.rb'
- 'lib/gitlab/database/with_lock_retries.rb'
- - 'lib/gitlab/diff/formatters/base_formatter.rb'
- - 'lib/gitlab/diff/rendered/notebook/diff_file.rb'
- 'lib/gitlab/email/handler/service_desk_handler.rb'
- 'lib/gitlab/email/message/in_product_marketing/base.rb'
- 'lib/gitlab/email/message/repository_push.rb'
@@ -942,7 +944,6 @@ Style/IfUnlessModifier:
- 'lib/gitlab/encrypted_command_base.rb'
- 'lib/gitlab/encrypted_configuration.rb'
- 'lib/gitlab/endpoint_attributes/config.rb'
- - 'lib/gitlab/error_tracking.rb'
- 'lib/gitlab/error_tracking/context_payload_generator.rb'
- 'lib/gitlab/error_tracking/processor/sidekiq_processor.rb'
- 'lib/gitlab/etag_caching/middleware.rb'
@@ -960,7 +961,6 @@ Style/IfUnlessModifier:
- '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/operation_service.rb'
@@ -971,15 +971,11 @@ Style/IfUnlessModifier:
- 'lib/gitlab/gitlab_import/client.rb'
- 'lib/gitlab/gitlab_import/importer.rb'
- 'lib/gitlab/golang.rb'
- - 'lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb'
- - 'lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb'
- 'lib/gitlab/graphql/pagination/keyset/connection.rb'
- - 'lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb'
- - 'lib/gitlab/graphql/pagination/keyset/order_info.rb'
- - 'lib/gitlab/graphql/pagination/keyset/query_builder.rb'
- 'lib/gitlab/graphql/queries.rb'
- 'lib/gitlab/hashed_storage/rake_helper.rb'
- 'lib/gitlab/hotlinking_detector.rb'
+ - 'lib/gitlab/http.rb'
- 'lib/gitlab/http_io.rb'
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/import/import_failure_service.rb'
@@ -987,12 +983,13 @@ Style/IfUnlessModifier:
- 'lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb'
- 'lib/gitlab/import_export/base/relation_factory.rb'
- 'lib/gitlab/import_export/fast_hash_serializer.rb'
- - 'lib/gitlab/import_export/file_importer.rb'
- 'lib/gitlab/import_export/group/tree_restorer.rb'
- 'lib/gitlab/import_export/json/legacy_writer.rb'
- 'lib/gitlab/import_export/merge_request_parser.rb'
- 'lib/gitlab/import_export/project/export_task.rb'
+ - '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'
@@ -1000,6 +997,7 @@ Style/IfUnlessModifier:
- 'lib/gitlab/legacy_github_import/importer.rb'
- 'lib/gitlab/legacy_github_import/issuable_formatter.rb'
- 'lib/gitlab/legacy_github_import/project_creator.rb'
+ - 'lib/gitlab/lograge/custom_options.rb'
- 'lib/gitlab/mail_room.rb'
- 'lib/gitlab/mail_room/authenticator.rb'
- 'lib/gitlab/manifest_import/manifest.rb'
@@ -1011,19 +1009,19 @@ Style/IfUnlessModifier:
- 'lib/gitlab/metrics/dashboard/stages/metric_endpoint_inserter.rb'
- 'lib/gitlab/metrics/dashboard/stages/variable_endpoint_inserter.rb'
- 'lib/gitlab/metrics/methods.rb'
- - 'lib/gitlab/metrics/rails_slis.rb'
+ - 'lib/gitlab/metrics/subscribers/rack_attack.rb'
- 'lib/gitlab/metrics/web_transaction.rb'
- 'lib/gitlab/middleware/compressed_json.rb'
- 'lib/gitlab/middleware/multipart.rb'
- 'lib/gitlab/middleware/same_site_cookies.rb'
- 'lib/gitlab/object_hierarchy.rb'
- 'lib/gitlab/omniauth_initializer.rb'
+ - 'lib/gitlab/pages/deployment_update.rb'
- 'lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb'
- 'lib/gitlab/patch/database_config.rb'
- 'lib/gitlab/patch/prependable.rb'
- 'lib/gitlab/popen.rb'
- 'lib/gitlab/query_limiting/active_support_subscriber.rb'
- - 'lib/gitlab/quick_actions/command_definition.rb'
- 'lib/gitlab/quick_actions/extractor.rb'
- 'lib/gitlab/quick_actions/issuable_actions.rb'
- 'lib/gitlab/quick_actions/issue_and_merge_request_actions.rb'
@@ -1044,11 +1042,9 @@ Style/IfUnlessModifier:
- 'lib/gitlab/sidekiq_middleware/server_metrics.rb'
- 'lib/gitlab/slash_commands/presenters/issue_show.rb'
- 'lib/gitlab/suggestions/suggestion_set.rb'
- - 'lib/gitlab/template/gitlab_ci_yml_template.rb'
- 'lib/gitlab/template_parser/eval_state.rb'
- 'lib/gitlab/untrusted_regexp.rb'
- 'lib/gitlab/url_blocker.rb'
- - 'lib/gitlab/usage/metrics/aggregates/aggregate.rb'
- 'lib/gitlab/usage_data.rb'
- 'lib/gitlab/usage_data_counters/base_counter.rb'
- 'lib/gitlab/usage_data_counters/hll_redis_counter.rb'
@@ -1084,13 +1080,12 @@ Style/IfUnlessModifier:
- 'qa/qa/ee/page/merge_request/show.rb'
- 'qa/qa/ee/resource/settings/elasticsearch.rb'
- 'qa/qa/flow/sign_up.rb'
- - 'qa/qa/git/repository.rb'
- - 'qa/qa/page/component/design_management.rb'
- 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/component/snippet.rb'
- 'qa/qa/page/element.rb'
- 'qa/qa/page/mattermost/login.rb'
- 'qa/qa/page/page_concern.rb'
+ - 'qa/qa/page/project/settings/deploy_tokens.rb'
- 'qa/qa/page/project/web_ide/edit.rb'
- 'qa/qa/page/view.rb'
- 'qa/qa/resource/registry_repository.rb'
@@ -1099,21 +1094,17 @@ Style/IfUnlessModifier:
- 'qa/qa/resource/runner.rb'
- 'qa/qa/resource/snippet.rb'
- 'qa/qa/runtime/application_settings.rb'
- - 'qa/qa/runtime/browser.rb'
- 'qa/qa/runtime/gpg.rb'
- 'qa/qa/runtime/ip_address.rb'
- 'qa/qa/scenario/bootable.rb'
- - 'qa/qa/scenario/template.rb'
- - 'qa/qa/service/docker_run/gitlab_runner.rb'
- - 'qa/qa/service/docker_run/jenkins.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/browser_ui/5_package/package_registry/nuget/nuget_project_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'
@@ -1121,15 +1112,13 @@ Style/IfUnlessModifier:
- '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/1_manage/project/project_audit_logs_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'
- - 'qa/qa/support/page_error_checker.rb'
- - 'qa/qa/support/wait_for_requests.rb'
- 'qa/qa/tools/delete_projects.rb'
+ - 'qa/qa/tools/delete_user_projects.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- - 'qa/qa/tools/test_resources_handler.rb'
- 'rubocop/cop/api/grape_array_missing_coerce.rb'
- 'rubocop/cop/avoid_keyword_arguments_in_sidekiq_workers.rb'
- 'rubocop/cop/gitlab/event_store_subscriber.rb'
@@ -1149,8 +1138,11 @@ Style/IfUnlessModifier:
- 'scripts/setup/find-jh-branch.rb'
- 'scripts/static-analysis'
- 'sidekiq_cluster/cli.rb'
+ - 'spec/components/previews/pajamas/alert_component_preview.rb'
+ - 'spec/components/previews/pajamas/card_component_preview.rb'
- 'spec/db/docs_spec.rb'
- 'spec/factories/ci/runners.rb'
+ - 'spec/factories/clusters/applications/helm.rb'
- 'spec/factories/container_repositories.rb'
- 'spec/factories/deployments.rb'
- 'spec/factories/labels.rb'
@@ -1164,6 +1156,8 @@ Style/IfUnlessModifier:
- 'spec/features/merge_request/batch_comments_spec.rb'
- 'spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb'
- 'spec/features/projects/blobs/edit_spec.rb'
+ - 'spec/features/projects/tree/create_directory_spec.rb'
+ - 'spec/features/projects/tree/create_file_spec.rb'
- 'spec/graphql/mutations/releases/update_spec.rb'
- 'spec/helpers/application_settings_helper_spec.rb'
- 'spec/helpers/invite_members_helper_spec.rb'
@@ -1173,6 +1167,7 @@ Style/IfUnlessModifier:
- 'spec/lib/gitlab/config/entry/validators/nested_array_helpers_spec.rb'
- 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/database/load_balancing_spec.rb'
+ - 'spec/lib/gitlab/database/lock_writes_manager_spec.rb'
- 'spec/lib/gitlab/rack_attack/user_allowlist_spec.rb'
- 'spec/lib/gitlab/sidekiq_config/worker_router_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
@@ -1186,8 +1181,10 @@ Style/IfUnlessModifier:
- 'spec/policies/project_statistics_policy_spec.rb'
- 'spec/requests/api/ci/jobs_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb'
+ - 'spec/requests/api/commits_spec.rb'
- 'spec/requests/api/files_spec.rb'
- 'spec/requests/api/integrations_spec.rb'
+ - 'spec/requests/users_controller_spec.rb'
- 'spec/routing/import_routing_spec.rb'
- 'spec/serializers/issue_sidebar_basic_entity_spec.rb'
- 'spec/services/application_settings/update_service_spec.rb'
@@ -1207,13 +1204,11 @@ Style/IfUnlessModifier:
- 'spec/support/external_authorization_service_helpers.rb'
- 'spec/support/flaky_tests.rb'
- 'spec/support/generate-seed-repo-rb'
- - 'spec/support/helpers/cycle_analytics_helpers.rb'
- 'spec/support/helpers/filter_spec_helper.rb'
- 'spec/support/helpers/filtered_search_helpers.rb'
- 'spec/support/helpers/gitaly_setup.rb'
- 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/helpers/javascript_fixtures_helpers.rb'
- - 'spec/support/helpers/kubernetes_helpers.rb'
- 'spec/support/helpers/lets_encrypt_helpers.rb'
- 'spec/support/helpers/live_debugger.rb'
- 'spec/support/helpers/modal_helpers.rb'
@@ -1247,6 +1242,7 @@ Style/IfUnlessModifier:
- 'spec/views/shared/access_tokens/_table.html.haml_spec.rb'
- 'spec/workers/analytics/usage_trends/counter_job_worker_spec.rb'
- 'tooling/danger/product_intelligence.rb'
+ - 'tooling/lib/tooling/find_codeowners.rb'
- 'tooling/lib/tooling/image.rb'
- 'tooling/lib/tooling/test_map_packer.rb'
- 'tooling/rspec_flaky/flaky_example.rb'
diff --git a/.rubocop_todo/style/missing_respond_to_missing.yml b/.rubocop_todo/style/missing_respond_to_missing.yml
index 4d602586342..9387ae72d00 100644
--- a/.rubocop_todo/style/missing_respond_to_missing.yml
+++ b/.rubocop_todo/style/missing_respond_to_missing.yml
@@ -1,8 +1,5 @@
---
Style/MissingRespondToMissing:
- # Offense count: 21
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/projects/application_controller.rb'
- 'app/models/network/commit.rb'
diff --git a/.rubocop_todo/style/next.yml b/.rubocop_todo/style/next.yml
index ba2bd293696..4106cba955f 100644
--- a/.rubocop_todo/style/next.yml
+++ b/.rubocop_todo/style/next.yml
@@ -1,10 +1,8 @@
---
# Cop supports --auto-correct.
Style/Next:
- # Offense count: 41
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'app/models/concerns/integrations/slack_mattermost_notifier.rb'
- 'app/models/preloaders/environments/deployment_preloader.rb'
- 'app/models/route.rb'
- 'app/services/authorized_project_update/find_records_due_for_refresh_service.rb'
@@ -16,6 +14,7 @@ Style/Next:
- 'ee/app/services/elastic/cluster_reindexing_service.rb'
- 'ee/app/services/gitlab_subscriptions/fetch_purchase_eligible_namespaces_service.rb'
- 'ee/app/services/security/auto_fix_service.rb'
+ - 'ee/app/services/security/ingestion/tasks/update_vulnerability_uuids.rb'
- 'ee/db/fixtures/development/20_vulnerabilities.rb'
- 'ee/lib/ee/audit/protected_branches_changes_auditor.rb'
- 'ee/lib/gitlab/elastic/search_results.rb'
@@ -36,10 +35,9 @@ Style/Next:
- 'lib/gitlab/metrics/samplers/base_sampler.rb'
- 'lib/gitlab/pagination/keyset/in_operator_optimization/strategies/record_loader_strategy.rb'
- 'lib/gitlab/reference_extractor.rb'
- - 'lib/gitlab/tree_summary.rb'
- 'lib/tasks/gitlab/assets.rake'
- 'lib/tasks/gitlab/db/validate_config.rake'
- - 'rubocop/cop/static_translation_definition.rb'
- 'scripts/perf/query_limiting_report.rb'
+ - 'scripts/qa/quarantine-types-check'
- 'spec/lib/gitlab/import_export/import_test_coverage_spec.rb'
- 'spec/presenters/packages/npm/package_presenter_spec.rb'
diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml
index 16ae8989c97..ae019079a8d 100644
--- a/.rubocop_todo/style/percent_literal_delimiters.yml
+++ b/.rubocop_todo/style/percent_literal_delimiters.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/PercentLiteralDelimiters:
- # Offense count: 3136
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'Guardfile'
- 'app/controllers/abuse_reports_controller.rb'
@@ -85,6 +82,7 @@ Style/PercentLiteralDelimiters:
- 'app/models/concerns/clusters/agents/authorization_config_scopes.rb'
- 'app/models/concerns/diff_positionable_note.rb'
- 'app/models/concerns/enums/prometheus_metric.rb'
+ - 'app/models/concerns/integrations/base_data_fields.rb'
- 'app/models/concerns/issuable.rb'
- 'app/models/concerns/issue_available_features.rb'
- 'app/models/concerns/mentionable/reference_regexes.rb'
@@ -98,11 +96,11 @@ Style/PercentLiteralDelimiters:
- 'app/models/diff_note.rb'
- 'app/models/discussion_note.rb'
- 'app/models/draft_note.rb'
+ - 'app/models/environment.rb'
- 'app/models/event.rb'
- 'app/models/instance_configuration.rb'
- 'app/models/integrations/asana.rb'
- 'app/models/integrations/assembla.rb'
- - 'app/models/integrations/base_ci.rb'
- 'app/models/integrations/base_issue_tracker.rb'
- 'app/models/integrations/base_monitoring.rb'
- 'app/models/integrations/base_slash_commands.rb'
@@ -125,6 +123,7 @@ Style/PercentLiteralDelimiters:
- 'app/models/issuable_severity.rb'
- 'app/models/issue.rb'
- 'app/models/lfs_download_object.rb'
+ - 'app/models/namespace.rb'
- 'app/models/namespace/root_storage_statistics.rb'
- 'app/models/note.rb'
- 'app/models/notification_setting.rb'
@@ -153,6 +152,7 @@ Style/PercentLiteralDelimiters:
- 'app/services/feature_flags/base_service.rb'
- 'app/services/files/multi_service.rb'
- 'app/services/import/bitbucket_server_service.rb'
+ - 'app/services/import/fogbugz_service.rb'
- 'app/services/import/github_service.rb'
- 'app/services/import/gitlab_projects/file_acquisition_strategies/remote_file.rb'
- 'app/services/import/gitlab_projects/file_acquisition_strategies/remote_file_s3.rb'
@@ -172,13 +172,13 @@ Style/PercentLiteralDelimiters:
- 'app/services/projects/update_service.rb'
- 'app/services/prometheus/proxy_service.rb'
- 'app/services/repositories/base_service.rb'
- - 'app/services/repositories/destroy_service.rb'
- '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/search/global_service.rb'
- 'app/services/search/project_service.rb'
- 'app/services/snippets/update_service.rb'
+ - 'app/services/todos/destroy/destroyed_issuable_service.rb'
- 'app/services/todos/destroy/entity_leave_service.rb'
- 'app/uploaders/design_management/design_v432x230_uploader.rb'
- 'app/uploaders/gitlab_uploader.rb'
@@ -194,6 +194,7 @@ Style/PercentLiteralDelimiters:
- 'config/initializers/content_security_policy.rb'
- 'config/initializers/countries.rb'
- 'config/initializers/doorkeeper.rb'
+ - 'config/initializers/enumerator_next_patch.rb'
- 'config/initializers/fog_core_patch.rb'
- 'config/initializers/forbid_sidekiq_in_transactions.rb'
- 'config/initializers/health_check.rb'
@@ -234,6 +235,8 @@ Style/PercentLiteralDelimiters:
- 'ee/app/controllers/ee/admin/application_settings_controller.rb'
- 'ee/app/controllers/ee/projects/service_desk_controller.rb'
- 'ee/app/controllers/ee/repositories/git_http_client_controller.rb'
+ - 'ee/app/controllers/groups/protected_environments_controller.rb'
+ - 'ee/app/controllers/projects/integrations/jira/issues_controller.rb'
- 'ee/app/controllers/projects/protected_environments_controller.rb'
- 'ee/app/controllers/trials_controller.rb'
- 'ee/app/finders/iterations_finder.rb'
@@ -241,6 +244,7 @@ Style/PercentLiteralDelimiters:
- 'ee/app/helpers/credentials_inventory_helper.rb'
- 'ee/app/helpers/ee/auth_helper.rb'
- 'ee/app/helpers/ee/dashboard_helper.rb'
+ - 'ee/app/helpers/ee/integrations_helper.rb'
- 'ee/app/helpers/ee/issues_helper.rb'
- 'ee/app/helpers/ee/labels_helper.rb'
- 'ee/app/helpers/ee/nav_helper.rb'
@@ -264,12 +268,13 @@ Style/PercentLiteralDelimiters:
- 'ee/app/models/geo/project_registry.rb'
- 'ee/app/models/geo/secondary_usage_data.rb'
- 'ee/app/models/geo_node_status.rb'
- - 'ee/app/models/gitlab_subscription.rb'
+ - 'ee/app/models/incident_management/issuable_resource_link.rb'
- 'ee/app/models/integrations/github.rb'
- 'ee/app/models/integrations/gitlab_slack_application.rb'
- 'ee/app/models/merge_requests/status_check_response.rb'
- 'ee/app/models/saml_provider.rb'
- 'ee/app/models/security/orchestration_policy_configuration.rb'
+ - 'ee/app/models/software_license_policy.rb'
- 'ee/app/models/storage_shard.rb'
- 'ee/app/services/approval_rules/create_service.rb'
- 'ee/app/services/boards/epic_boards/update_service.rb'
@@ -284,11 +289,13 @@ Style/PercentLiteralDelimiters:
- 'ee/app/services/requirements_management/export_csv_service.rb'
- 'ee/app/services/security/configuration/save_auto_fix_service.rb'
- 'ee/app/services/security/dependency_list_service.rb'
- - 'ee/lib/api/managed_licenses.rb'
+ - 'ee/app/services/security/ingestion/tasks/update_vulnerability_uuids.rb'
+ - 'ee/elastic/migrate/20220613120500_migrate_commits_to_separate_index.rb'
- 'ee/lib/api/status_checks.rb'
- 'ee/lib/api/visual_review_discussions.rb'
- 'ee/lib/ee/api/helpers/members_helpers.rb'
- 'ee/lib/ee/api/helpers/projects_helpers.rb'
+ - 'ee/lib/ee/api/members.rb'
- 'ee/lib/ee/api/search.rb'
- 'ee/lib/ee/audit/group_changes_auditor.rb'
- 'ee/lib/ee/gitlab/alert_management/payload/generic.rb'
@@ -320,6 +327,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/controllers/groups/scim_oauth_controller_spec.rb'
- 'ee/spec/controllers/groups/sso_controller_spec.rb'
- 'ee/spec/controllers/projects/issues_controller_spec.rb'
+ - 'ee/spec/controllers/projects/legacy_pipelines_controller_spec.rb'
- 'ee/spec/controllers/projects/pipelines_controller_spec.rb'
- 'ee/spec/controllers/projects/security/configuration_controller_spec.rb'
- 'ee/spec/elastic_integration/global_search_spec.rb'
@@ -349,6 +357,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/graphql/types/vulnerable_projects_by_grade_type_spec.rb'
- 'ee/spec/helpers/ee/application_settings_helper_spec.rb'
- 'ee/spec/helpers/ee/auth_helper_spec.rb'
+ - 'ee/spec/helpers/ee/environments_helper_spec.rb'
- 'ee/spec/helpers/ee/geo_helper_spec.rb'
- 'ee/spec/helpers/ee/labels_helper_spec.rb'
- 'ee/spec/helpers/ee/security_orchestration_helper_spec.rb'
@@ -359,6 +368,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/lib/banzai/filter/references/epic_reference_filter_spec.rb'
- 'ee/spec/lib/banzai/filter/references/iteration_reference_filter_spec.rb'
- 'ee/spec/lib/banzai/filter/references/vulnerability_reference_filters_spec.rb'
+ - 'ee/spec/lib/ee/backup/repositories_spec.rb'
- 'ee/spec/lib/ee/gitlab/alert_management/payload/generic_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/config_spec.rb'
@@ -367,7 +377,6 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/groups_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/reports/security/reports_spec.rb'
- - 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/git_access_design_spec.rb'
- 'ee/spec/lib/ee/gitlab/git_access_snippet_spec.rb'
- 'ee/spec/lib/ee/gitlab/security/scan_configuration_spec.rb'
@@ -380,6 +389,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/lib/gitlab/auth/group_saml/user_spec.rb'
- 'ee/spec/lib/gitlab/auth/ldap/adapter_spec.rb'
- 'ee/spec/lib/gitlab/auth/ldap/person_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/saml/membership_updater_spec.rb'
- 'ee/spec/lib/gitlab/auth/saml/user_spec.rb'
- 'ee/spec/lib/gitlab/authority_analyzer_spec.rb'
- 'ee/spec/lib/gitlab/cache_spec.rb'
@@ -387,7 +397,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/sast_iac_latest_gitlab_ci_yaml_spec.rb'
+ - 'ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/secret_detection_latest_gitlab_ci_yaml_spec.rb'
@@ -411,11 +421,11 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/models/concerns/ee/issuable_spec.rb'
- 'ee/spec/models/concerns/ee/project_security_scanners_information_spec.rb'
- 'ee/spec/models/ee/ci/job_artifact_spec.rb'
+ - 'ee/spec/models/ee/ci/runner_spec.rb'
- 'ee/spec/models/ee/groups/feature_setting_spec.rb'
- 'ee/spec/models/ee/integration_spec.rb'
- 'ee/spec/models/ee/integrations/jira_spec.rb'
- 'ee/spec/models/ee/personal_access_token_spec.rb'
- - 'ee/spec/models/gitlab_subscription_spec.rb'
- 'ee/spec/models/instance_security_dashboard_spec.rb'
- 'ee/spec/models/issue_spec.rb'
- 'ee/spec/models/project_feature_spec.rb'
@@ -423,7 +433,6 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/models/push_rule_spec.rb'
- 'ee/spec/models/repository_spec.rb'
- 'ee/spec/models/saml_provider_spec.rb'
- - 'ee/spec/models/security/orchestration_policy_configuration_spec.rb'
- 'ee/spec/models/security/scan_spec.rb'
- 'ee/spec/models/vulnerabilities/historical_statistic_spec.rb'
- 'ee/spec/models/vulnerabilities/stat_diff_spec.rb'
@@ -435,6 +444,7 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/requests/admin/user_permission_exports_controller_spec.rb'
- 'ee/spec/requests/api/dependencies_spec.rb'
- 'ee/spec/requests/api/epics_spec.rb'
+ - 'ee/spec/requests/api/geo_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/alert_management/http_integration/update_spec.rb'
- 'ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb'
- 'ee/spec/requests/api/internal/base_spec.rb'
@@ -443,11 +453,13 @@ Style/PercentLiteralDelimiters:
- 'ee/spec/requests/api/merge_requests_spec.rb'
- 'ee/spec/requests/api/scim_spec.rb'
- 'ee/spec/requests/api/wikis_spec.rb'
+ - 'ee/spec/requests/lfs_locks_api_spec.rb'
- 'ee/spec/serializers/merge_request_widget_entity_spec.rb'
- 'ee/spec/services/admin/email_service_spec.rb'
- 'ee/spec/services/base_count_service_spec.rb'
- 'ee/spec/services/ci/compare_security_reports_service_spec.rb'
- 'ee/spec/services/ci/sync_reports_to_approval_rules_service_spec.rb'
+ - 'ee/spec/services/ee/auth/container_registry_authentication_service_spec.rb'
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
- 'ee/spec/services/ee/members/create_service_spec.rb'
- 'ee/spec/services/ee/protected_branches/create_service_spec.rb'
@@ -507,6 +519,7 @@ Style/PercentLiteralDelimiters:
- 'lib/banzai/filter/table_of_contents_filter.rb'
- 'lib/banzai/pipeline/base_pipeline.rb'
- 'lib/banzai/pipeline/description_pipeline.rb'
+ - 'lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb'
- 'lib/bitbucket/page.rb'
- 'lib/bitbucket/representation/issue.rb'
- 'lib/container_registry/path.rb'
@@ -520,6 +533,7 @@ Style/PercentLiteralDelimiters:
- 'lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb'
- 'lib/gitlab/auth/ldap/adapter.rb'
- 'lib/gitlab/auth/ldap/config.rb'
+ - 'lib/gitlab/background_migration/backfill_note_discussion_id.rb'
- 'lib/gitlab/bare_repository_import/importer.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ci/config/entry/bridge.rb'
@@ -547,7 +561,7 @@ Style/PercentLiteralDelimiters:
- 'lib/gitlab/gitaly_client.rb'
- 'lib/gitlab/gitaly_client/diff.rb'
- 'lib/gitlab/gitaly_client/wiki_page.rb'
- - 'lib/gitlab/graphql/pagination/keyset/order_info.rb'
+ - 'lib/gitlab/graphql/query_analyzers/ast/recursion_analyzer.rb'
- 'lib/gitlab/hotlinking_detector.rb'
- 'lib/gitlab/import_export/command_line_util.rb'
- 'lib/gitlab/import_export/file_importer.rb'
@@ -568,9 +582,10 @@ Style/PercentLiteralDelimiters:
- 'lib/gitlab/metrics/transaction.rb'
- 'lib/gitlab/metrics/web_transaction.rb'
- 'lib/gitlab/middleware/read_only/controller.rb'
- - 'lib/gitlab/process_supervisor.rb'
- 'lib/gitlab/project_search_results.rb'
- 'lib/gitlab/prometheus/query_variables.rb'
+ - 'lib/gitlab/query_limiting/transaction.rb'
+ - 'lib/gitlab/redis/multi_store.rb'
- 'lib/gitlab/reference_extractor.rb'
- 'lib/gitlab/regex.rb'
- 'lib/gitlab/sanitizers/exception_message.rb'
@@ -584,11 +599,14 @@ Style/PercentLiteralDelimiters:
- 'lib/gitlab/task_helpers.rb'
- 'lib/gitlab/uploads/migration_helper.rb'
- 'lib/gitlab/url_blocker.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/count_imported_projects_total_metric.rb'
- 'lib/gitlab/usage/metrics/instrumentations/database_metric.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb'
- 'lib/gitlab/usage_data.rb'
- 'lib/gitlab/usage_data/topology.rb'
- 'lib/gitlab/usage_data_counters/hll_redis_counter.rb'
- 'lib/gitlab/utils/sanitize_node_link.rb'
+ - 'lib/gitlab/web_hooks/rate_limiter.rb'
- 'lib/gitlab/workhorse.rb'
- 'lib/grafana/validator.rb'
- 'lib/omni_auth/strategies/jwt.rb'
@@ -614,40 +632,37 @@ Style/PercentLiteralDelimiters:
- 'qa/qa/ee/page/project/show.rb'
- 'qa/qa/ee/page/project/snippet/index.rb'
- 'qa/qa/ee/page/project/wiki/show.rb'
- - 'qa/qa/git/repository.rb'
- 'qa/qa/resource/events/project.rb'
- - 'qa/qa/resource/members.rb'
+ - 'qa/qa/resource/personal_access_token_cache.rb'
- 'qa/qa/resource/visibility.rb'
- - 'qa/qa/runtime/browser.rb'
- 'qa/qa/service/cluster_provider/gcloud.rb'
- 'qa/qa/service/praefect_manager.rb'
- 'qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb'
- 'qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/13_secure/enable_scanning_from_configuration_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_saml_enforced_sso_new_account_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
- 'qa/spec/git/repository_spec.rb'
- 'qa/spec/page/view_spec.rb'
- - 'qa/spec/support/page_error_checker_spec.rb'
+ - 'rubocop/cop/migration/background_migrations.rb'
- 'rubocop/cop/rspec/httparty_basic_auth.rb'
- 'rubocop/migration_helpers.rb'
+ - 'scripts/qa/quarantine-types-check'
- 'scripts/qa/testcases-check'
- 'scripts/regenerate-schema'
+ - 'scripts/undercoverage'
- 'sidekiq_cluster/cli.rb'
- 'spec/benchmarks/banzai_benchmark.rb'
- 'spec/commands/sidekiq_cluster/cli_spec.rb'
+ - 'spec/components/pajamas/component_spec.rb'
- 'spec/config/mail_room_spec.rb'
- - 'spec/controllers/admin/clusters_controller_spec.rb'
- 'spec/controllers/concerns/continue_params_spec.rb'
- 'spec/controllers/graphql_controller_spec.rb'
- - 'spec/controllers/groups/clusters_controller_spec.rb'
- 'spec/controllers/groups/releases_controller_spec.rb'
- 'spec/controllers/jira_connect/app_descriptor_controller_spec.rb'
- 'spec/controllers/oauth/applications_controller_spec.rb'
- 'spec/controllers/profiles/two_factor_auths_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/environments/prometheus_api_controller_spec.rb'
- 'spec/controllers/projects/environments_controller_spec.rb'
@@ -663,7 +678,6 @@ Style/PercentLiteralDelimiters:
- 'spec/controllers/search_controller_spec.rb'
- 'spec/controllers/snippets_controller_spec.rb'
- 'spec/db/docs_spec.rb'
- - 'spec/db/schema_spec.rb'
- 'spec/experiments/ios_specific_templates_experiment_spec.rb'
- 'spec/factories/ci/builds.rb'
- 'spec/factories/ci/runners.rb'
@@ -689,6 +703,8 @@ Style/PercentLiteralDelimiters:
- 'spec/features/projects/integrations/user_activates_jira_spec.rb'
- 'spec/features/projects/jobs_spec.rb'
- 'spec/features/projects/labels/issues_sorted_by_priority_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
+ - 'spec/features/projects/pipelines/legacy_pipelines_spec.rb'
- 'spec/features/projects/pipelines/pipeline_spec.rb'
- 'spec/features/projects/pipelines/pipelines_spec.rb'
- 'spec/features/protected_branches_spec.rb'
@@ -700,7 +716,6 @@ Style/PercentLiteralDelimiters:
- 'spec/finders/ci/runners_finder_spec.rb'
- 'spec/finders/environments/environments_finder_spec.rb'
- 'spec/finders/groups_finder_spec.rb'
- - 'spec/finders/issues_finder_spec.rb'
- 'spec/finders/license_template_finder_spec.rb'
- 'spec/finders/merge_requests_finder_spec.rb'
- 'spec/finders/tags_finder_spec.rb'
@@ -724,19 +739,24 @@ Style/PercentLiteralDelimiters:
- 'spec/helpers/clusters_helper_spec.rb'
- 'spec/helpers/diff_helper_spec.rb'
- 'spec/helpers/emails_helper_spec.rb'
+ - 'spec/helpers/issuables_description_templates_helper_spec.rb'
- 'spec/helpers/issues_helper_spec.rb'
- 'spec/helpers/nav_helper_spec.rb'
- 'spec/helpers/page_layout_helper_spec.rb'
- 'spec/helpers/profiles_helper_spec.rb'
- 'spec/helpers/releases_helper_spec.rb'
+ - 'spec/helpers/storage_helper_spec.rb'
- 'spec/helpers/tracking_helper_spec.rb'
- 'spec/initializers/direct_upload_support_spec.rb'
+ - 'spec/initializers/enumerator_next_patch_spec.rb'
- 'spec/initializers/rack_multipart_patch_spec.rb'
- 'spec/lib/api/ci/helpers/runner_helpers_spec.rb'
+ - 'spec/lib/api/entities/user_spec.rb'
- 'spec/lib/api/helpers/common_helpers_spec.rb'
- 'spec/lib/atlassian/jira_connect/client_spec.rb'
- 'spec/lib/backup/files_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
+ - 'spec/lib/backup/repositories_spec.rb'
- 'spec/lib/banzai/filter/asset_proxy_filter_spec.rb'
- 'spec/lib/banzai/filter/autolink_filter_spec.rb'
- 'spec/lib/banzai/filter/broadcast_message_sanitization_filter_spec.rb'
@@ -760,6 +780,7 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/banzai/pipeline/description_pipeline_spec.rb'
- 'spec/lib/banzai/pipeline/full_pipeline_spec.rb'
- 'spec/lib/banzai/pipeline/gfm_pipeline_spec.rb'
+ - 'spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb'
- 'spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb'
- 'spec/lib/banzai/reference_parser/base_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_parser_spec.rb'
@@ -777,6 +798,8 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
- 'spec/lib/gitlab/auth/saml/auth_hash_spec.rb'
- 'spec/lib/gitlab/auth/saml/user_spec.rb'
+ - 'spec/lib/gitlab/background_migration/batched_migration_job_spec.rb'
+ - 'spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb'
- 'spec/lib/gitlab/bare_repository_import/importer_spec.rb'
- 'spec/lib/gitlab/batch_worker_context_spec.rb'
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
@@ -784,6 +807,7 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/ci/ansi2html_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/bridge_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/commands_spec.rb'
+ - 'spec/lib/gitlab/ci/config/entry/environment_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/image_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/root_spec.rb'
- 'spec/lib/gitlab/ci/config/entry/service_spec.rb'
@@ -793,6 +817,7 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/ci/pipeline/chain/template_usage_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/expression/lexeme/equals_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/seed/build_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb'
- 'spec/lib/gitlab/ci/reports/accessibility_reports_comparer_spec.rb'
- 'spec/lib/gitlab/ci/reports/accessibility_reports_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/reports_spec.rb'
@@ -801,6 +826,7 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/ci/status/stage/factory_spec.rb'
- 'spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb'
+ - 'spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb'
- 'spec/lib/gitlab/ci/variables/collection/item_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor/dag_spec.rb'
@@ -844,7 +870,6 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/favicon_spec.rb'
- 'spec/lib/gitlab/feature_categories_spec.rb'
- 'spec/lib/gitlab/file_detector_spec.rb'
- - 'spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb'
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- 'spec/lib/gitlab/git/merge_base_spec.rb'
- 'spec/lib/gitlab/git/repository_spec.rb'
@@ -887,6 +912,7 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/gitlab/middleware/go_spec.rb'
- 'spec/lib/gitlab/middleware/multipart_spec.rb'
- 'spec/lib/gitlab/omniauth_initializer_spec.rb'
+ - 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
- 'spec/lib/gitlab/pagination/offset_header_builder_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
- 'spec/lib/gitlab/popen_spec.rb'
@@ -939,6 +965,8 @@ Style/PercentLiteralDelimiters:
- 'spec/lib/system_check/orphans/repository_check_spec.rb'
- 'spec/lib/system_check/sidekiq_check_spec.rb'
- 'spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb'
+ - 'spec/lib/unnested_in_filters/dsl_spec.rb'
+ - 'spec/lib/unnested_in_filters/rewriter_spec.rb'
- 'spec/metrics_server/metrics_server_spec.rb'
- 'spec/migrations/add_new_trail_plans_spec.rb'
- 'spec/migrations/change_web_hook_events_default_spec.rb'
@@ -984,7 +1012,6 @@ Style/PercentLiteralDelimiters:
- 'spec/models/issue_spec.rb'
- 'spec/models/members/member_task_spec.rb'
- 'spec/models/merge_request_diff_spec.rb'
- - 'spec/models/namespace_spec.rb'
- 'spec/models/namespace_statistics_spec.rb'
- 'spec/models/packages/package_spec.rb'
- 'spec/models/packages/tag_spec.rb'
@@ -1020,6 +1047,8 @@ Style/PercentLiteralDelimiters:
- 'spec/requests/api/ci/triggers_spec.rb'
- 'spec/requests/api/container_repositories_spec.rb'
- 'spec/requests/api/deployments_spec.rb'
+ - 'spec/requests/api/geo_spec.rb'
+ - 'spec/requests/api/graphql/ci/manual_variables_spec.rb'
- 'spec/requests/api/graphql/gitlab_schema_spec.rb'
- 'spec/requests/api/graphql/group/container_repositories_spec.rb'
- 'spec/requests/api/graphql/group/milestones_spec.rb'
@@ -1045,6 +1074,7 @@ Style/PercentLiteralDelimiters:
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/members_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
+ - 'spec/requests/api/metadata_spec.rb'
- 'spec/requests/api/project_container_repositories_spec.rb'
- 'spec/requests/api/project_templates_spec.rb'
- 'spec/requests/api/projects_spec.rb'
@@ -1063,6 +1093,7 @@ Style/PercentLiteralDelimiters:
- 'spec/requests/lfs_locks_api_spec.rb'
- 'spec/requests/users_controller_spec.rb'
- 'spec/routing/uploads_routing_spec.rb'
+ - 'spec/rubocop/cop/migration/migration_record_spec.rb'
- 'spec/rubocop/cop/migration/prevent_index_creation_spec.rb'
- 'spec/rubocop/cop/migration/sidekiq_queue_migrate_spec.rb'
- 'spec/rubocop/cop/performance/readlines_each_spec.rb'
@@ -1143,6 +1174,7 @@ Style/PercentLiteralDelimiters:
- 'spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb'
- 'spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb'
- 'spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb'
+ - 'spec/support/shared_examples/finders/issues_finder_shared_examples.rb'
- 'spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb'
- 'spec/support/shared_examples/metrics/transaction_metrics_with_labels_shared_examples.rb'
@@ -1165,6 +1197,7 @@ Style/PercentLiteralDelimiters:
- 'spec/tasks/gitlab/db_rake_spec.rb'
- 'spec/tasks/gitlab/task_helpers_spec.rb'
- 'spec/tasks/gitlab/uploads/migrate_rake_spec.rb'
+ - 'spec/tooling/danger/customer_success_spec.rb'
- 'spec/tooling/danger/datateam_spec.rb'
- 'spec/tooling/danger/sidekiq_queues_spec.rb'
- 'spec/tooling/lib/tooling/test_map_generator_spec.rb'
@@ -1186,7 +1219,6 @@ Style/PercentLiteralDelimiters:
- 'spec/uploaders/pages/deployment_uploader_spec.rb'
- 'spec/uploaders/personal_file_uploader_spec.rb'
- 'spec/validators/any_field_validator_spec.rb'
- - 'spec/views/layouts/_flash.html.haml_spec.rb'
- 'spec/views/layouts/_head.html.haml_spec.rb'
- 'spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb'
- 'spec/views/projects/commit/branches.html.haml_spec.rb'
diff --git a/.rubocop_todo/style/redundant_interpolation.yml b/.rubocop_todo/style/redundant_interpolation.yml
index 0d3651eb7b2..3747312f2c4 100644
--- a/.rubocop_todo/style/redundant_interpolation.yml
+++ b/.rubocop_todo/style/redundant_interpolation.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/RedundantInterpolation:
- # Offense count: 285
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/components/diffs/stats_component.rb'
- 'app/helpers/blob_helper.rb'
@@ -13,7 +10,10 @@ Style/RedundantInterpolation:
- 'app/helpers/environments_helper.rb'
- 'app/helpers/icons_helper.rb'
- 'app/helpers/issuables_helper.rb'
+ - 'app/helpers/nav_helper.rb'
+ - 'app/helpers/projects_helper.rb'
- 'app/helpers/search_helper.rb'
+ - 'app/helpers/tooling/visual_review_helper.rb'
- 'app/models/concerns/issuable.rb'
- 'app/models/integrations/base_chat_notification.rb'
- 'app/models/integrations/hangouts_chat.rb'
@@ -24,6 +24,7 @@ Style/RedundantInterpolation:
- 'app/services/users/approve_service.rb'
- 'app/services/users/banned_user_base_service.rb'
- 'app/services/users/reject_service.rb'
+ - 'db/post_migrate/20220420214703_schedule_backfill_draft_status_on_merge_requests_corrected_regex.rb'
- 'ee/app/graphql/types/compliance_management/merge_requests/compliance_violation_reason_enum.rb'
- 'ee/app/graphql/types/incident_management/oncall_rotation_length_unit_enum.rb'
- 'ee/app/helpers/ee/ci/runners_helper.rb'
@@ -31,23 +32,29 @@ Style/RedundantInterpolation:
- 'ee/app/services/geo/event_store.rb'
- 'ee/app/services/geo/repository_updated_service.rb'
- 'ee/app/services/security/security_orchestration_policies/create_pipeline_service.rb'
+ - 'ee/app/services/users/abuse/excessive_projects_download_ban_service.rb'
+ - 'ee/app/services/users/abuse/git_abuse/namespace_throttle_service.rb'
- 'ee/db/fixtures/development/31_devops_adoption.rb'
+ - 'ee/lib/gitlab/insights/serializers/chartjs/base_serializer.rb'
- 'ee/spec/features/epics/epic_issues_spec.rb'
- 'ee/spec/features/projects/requirements_management/requirements_list_spec.rb'
- 'ee/spec/features/registrations/one_trust_spec.rb'
- 'ee/spec/graphql/ee/mutations/boards/lists/create_spec.rb'
- 'ee/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb'
- 'ee/spec/lib/banzai/filter/references/iteration_reference_filter_spec.rb'
- - 'ee/spec/lib/ee/audit/protected_branches_changes_auditor_spec.rb'
- 'ee/spec/lib/ee/gitlab/import_export/group/tree_saver_spec.rb'
+ - 'ee/spec/lib/gitlab/insights/serializers/chartjs/line_serializer_spec.rb'
+ - 'ee/spec/lib/gitlab/insights/serializers/chartjs/multi_series_serializer_spec.rb'
- 'ee/spec/mailers/ci_minutes_usage_mailer_spec.rb'
- 'ee/spec/mailers/emails/namespace_storage_usage_mailer_spec.rb'
- 'ee/spec/mailers/notify_spec.rb'
- 'ee/spec/models/incident_management/issuable_escalation_status_spec.rb'
- 'ee/spec/requests/api/issues_spec.rb'
- 'ee/spec/requests/api/search_spec.rb'
+ - 'ee/spec/services/analytics/cycle_analytics/consistency_check_service_spec.rb'
- 'ee/spec/services/search_service_spec.rb'
- 'ee/spec/services/timebox_report_service_spec.rb'
+ - 'ee/spec/support/shared_contexts/lib/gitlab/insights/serializers/serializers_shared_context.rb'
- 'ee/spec/support/shared_examples/lib/gitlab/elastic/standalone_indices_shared_examples.rb'
- 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
- 'lib/backup/manager.rb'
@@ -72,15 +79,19 @@ Style/RedundantInterpolation:
- 'lib/gitlab/utils.rb'
- 'lib/kramdown/converter/commonmark.rb'
- 'lib/tasks/gettext.rake'
+ - 'lib/tasks/gitlab/seed/group_seed.rake'
+ - 'qa/qa/ee/page/component/secure_report.rb'
- 'qa/qa/ee/page/merge_request/new.rb'
- 'qa/qa/ee/page/project/issue/show.rb'
+ - 'qa/qa/ee/page/project/secure/vulnerability_details.rb'
- 'qa/qa/resource/events/base.rb'
- 'qa/qa/service/praefect_manager.rb'
- 'qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb'
- 'qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_templates_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/13_secure/scan_result_policy_vulnerabilities_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/project_templates_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/4_verify/parent_child_pipelines_dependent_relationship_spec.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- - 'scripts/changed-feature-flags'
- 'scripts/perf/gc/print_gc_stats.rb'
- 'scripts/qa/testcases-check'
- 'spec/controllers/admin/integrations_controller_spec.rb'
@@ -93,6 +104,7 @@ Style/RedundantInterpolation:
- 'spec/features/projects/jobs/user_browses_jobs_spec.rb'
- 'spec/graphql/resolvers/container_repositories_resolver_spec.rb'
- 'spec/helpers/environments_helper_spec.rb'
+ - 'spec/helpers/snippets_helper_spec.rb'
- 'spec/lib/api/helpers/packages/dependency_proxy_helpers_spec.rb'
- 'spec/lib/api/validations/validators/git_ref_spec.rb'
- 'spec/lib/api/validations/validators/limit_spec.rb'
@@ -116,7 +128,9 @@ Style/RedundantInterpolation:
- 'spec/lib/gitlab/database/batch_count_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb'
- 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
+ - 'spec/lib/gitlab/inactive_projects_deletion_warning_tracker_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/url_spec.rb'
+ - 'spec/lib/gitlab/redis/multi_store_spec.rb'
- 'spec/lib/grafana/client_spec.rb'
- 'spec/mailers/notify_spec.rb'
- 'spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb'
@@ -134,7 +148,6 @@ Style/RedundantInterpolation:
- 'spec/requests/api/terraform/state_spec.rb'
- 'spec/requests/projects/google_cloud/deployments_controller_spec.rb'
- 'spec/requests/projects/google_cloud/service_accounts_controller_spec.rb'
- - 'spec/requests/projects/google_cloud_controller_spec.rb'
- 'spec/routing/project_routing_spec.rb'
- 'spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb'
- 'spec/services/groups/transfer_service_spec.rb'
diff --git a/.rubocop_todo/style/redundant_regexp_escape.yml b/.rubocop_todo/style/redundant_regexp_escape.yml
index cf502711f35..5c97275ee4b 100644
--- a/.rubocop_todo/style/redundant_regexp_escape.yml
+++ b/.rubocop_todo/style/redundant_regexp_escape.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/RedundantRegexpEscape:
- # Offense count: 325
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/help_controller.rb'
- 'app/controllers/import/bitbucket_server_controller.rb'
@@ -16,6 +13,7 @@ Style/RedundantRegexpEscape:
- 'app/models/integrations/chat_message/base_message.rb'
- 'app/models/integrations/datadog.rb'
- 'app/models/integrations/teamcity.rb'
+ - 'app/models/issue.rb'
- 'app/models/label.rb'
- 'app/models/license_template.rb'
- 'app/models/milestone.rb'
@@ -25,6 +23,7 @@ Style/RedundantRegexpEscape:
- 'app/models/snippet.rb'
- 'app/services/metrics/dashboard/grafana_metric_embed_service.rb'
- 'app/uploaders/file_uploader.rb'
+ - 'config/initializers/wikicloth_redos_patch.rb'
- 'config/routes/project.rb'
- 'config/routes/uploads.rb'
- 'ee/app/models/ee/epic.rb'
@@ -37,18 +36,20 @@ Style/RedundantRegexpEscape:
- 'ee/spec/features/read_only_spec.rb'
- 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
- 'ee/spec/lib/ee/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'ee/spec/mailers/ee/emails/admin_notification_spec.rb'
+ - 'ee/spec/mailers/ee/emails/profile_spec.rb'
- 'ee/spec/mailers/notify_spec.rb'
- 'ee/spec/models/release_highlight_spec.rb'
- 'ee/spec/support/shared_examples/services/group_saml/saml_provider/base_service_shared_examples.rb'
- 'lib/api/templates.rb'
- 'lib/banzai/filter/autolink_filter.rb'
- 'lib/banzai/filter/inline_diff_filter.rb'
+ - 'lib/banzai/filter/task_list_filter.rb'
- 'lib/bulk_imports/common/pipelines/uploads_pipeline.rb'
- 'lib/csv_builder.rb'
- 'lib/gitlab/background_migration/backfill_integrations_enable_ssl_verification.rb'
- 'lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb'
- 'lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb'
- - 'lib/gitlab/diff/parser.rb'
- 'lib/gitlab/diff/suggestions_parser.rb'
- 'lib/gitlab/email/handler/create_issue_handler.rb'
- 'lib/gitlab/email/handler/create_merge_request_handler.rb'
@@ -57,7 +58,8 @@ Style/RedundantRegexpEscape:
- 'lib/gitlab/email/reply_parser.rb'
- 'lib/gitlab/git/diff.rb'
- 'lib/gitlab/git/repository.rb'
- - 'lib/gitlab/gitaly_client/operation_service.rb'
+ - 'lib/gitlab/gitaly_client.rb'
+ - 'lib/gitlab/harbor/query.rb'
- 'lib/gitlab/incoming_email.rb'
- 'lib/gitlab/jira/dvcs.rb'
- 'lib/gitlab/path_regex.rb'
@@ -66,6 +68,7 @@ Style/RedundantRegexpEscape:
- 'lib/gitlab/quick_actions/extractor.rb'
- 'lib/gitlab/regex.rb'
- 'lib/gitlab/search/abuse_detection.rb'
+ - 'lib/gitlab/service_desk_email.rb'
- 'lib/gitlab/task_helpers.rb'
- 'lib/gitlab/url_sanitizer.rb'
- 'lib/gitlab/utils.rb'
@@ -87,6 +90,7 @@ Style/RedundantRegexpEscape:
- 'spec/helpers/tab_helper_spec.rb'
- 'spec/lib/banzai/filter/references/reference_filter_spec.rb'
- 'spec/lib/banzai/filter/syntax_highlight_filter_spec.rb'
+ - 'spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb'
- 'spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb'
- 'spec/lib/gitlab/ci/config_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
@@ -96,6 +100,7 @@ Style/RedundantRegexpEscape:
- 'spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb'
- 'spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb'
- 'spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'spec/mailers/emails/profile_spec.rb'
- 'spec/models/release_highlight_spec.rb'
- 'spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb'
- 'spec/requests/api/graphql_spec.rb'
diff --git a/.rubocop_todo/style/redundant_self.yml b/.rubocop_todo/style/redundant_self.yml
index 9951160ae02..65f2ea327d7 100644
--- a/.rubocop_todo/style/redundant_self.yml
+++ b/.rubocop_todo/style/redundant_self.yml
@@ -1,12 +1,11 @@
---
# Cop supports --auto-correct.
Style/RedundantSelf:
- # Offense count: 1222
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'app/channels/awareness_channel.rb'
- 'app/controllers/application_controller.rb'
- 'app/finders/security/jobs_finder.rb'
+ - 'app/graphql/types/permission_types/base_permission_type.rb'
- 'app/models/abuse_report.rb'
- 'app/models/analytics/usage_trends/measurement.rb'
- 'app/models/application_record.rb'
@@ -74,6 +73,7 @@ Style/RedundantSelf:
- 'app/models/concerns/merge_request_reviewer_state.rb'
- 'app/models/concerns/noteable.rb'
- 'app/models/concerns/packages/debian/distribution.rb'
+ - 'app/models/concerns/participable.rb'
- 'app/models/concerns/pg_full_text_searchable.rb'
- 'app/models/concerns/protected_ref.rb'
- 'app/models/concerns/protected_ref_access.rb'
@@ -102,6 +102,7 @@ Style/RedundantSelf:
- 'app/models/gpg_key.rb'
- 'app/models/group.rb'
- 'app/models/group_group_link.rb'
+ - 'app/models/hooks/web_hook_log.rb'
- 'app/models/identity.rb'
- 'app/models/integration.rb'
- 'app/models/integrations/base_chat_notification.rb'
@@ -112,6 +113,7 @@ Style/RedundantSelf:
- 'app/models/integrations/emails_on_push.rb'
- 'app/models/integrations/jira.rb'
- 'app/models/integrations/pipelines_email.rb'
+ - 'app/models/integrations/slack.rb'
- 'app/models/integrations/zentao.rb'
- 'app/models/internal_id.rb'
- 'app/models/issue.rb'
@@ -125,11 +127,10 @@ Style/RedundantSelf:
- 'app/models/member.rb'
- 'app/models/members/project_member.rb'
- 'app/models/merge_request.rb'
+ - 'app/models/merge_request/cleanup_schedule.rb'
- 'app/models/merge_request/metrics.rb'
- - 'app/models/merge_request_assignee.rb'
- 'app/models/merge_request_diff.rb'
- 'app/models/merge_request_diff_commit.rb'
- - 'app/models/merge_request_reviewer.rb'
- 'app/models/namespaces/traversal/linear.rb'
- 'app/models/note.rb'
- 'app/models/packages/dependency.rb'
@@ -179,10 +180,11 @@ Style/RedundantSelf:
- 'app/uploaders/gitlab_uploader.rb'
- 'app/uploaders/object_storage.rb'
- 'app/workers/background_migration/single_database_worker.rb'
+ - 'app/workers/build_hooks_worker.rb'
- 'app/workers/concerns/application_worker.rb'
- 'app/workers/concerns/limited_capacity/worker.rb'
- 'app/workers/concerns/project_start_import.rb'
- - 'app/workers/concerns/waitable_worker.rb'
+ - 'app/workers/concerns/reenqueuer.rb'
- 'app/workers/database/batched_background_migration/single_database_worker.rb'
- 'app/workers/group_import_worker.rb'
- 'app/workers/project_export_worker.rb'
@@ -193,6 +195,7 @@ Style/RedundantSelf:
- 'db/post_migrate/20210329102724_add_new_trail_plans.rb'
- 'db/post_migrate/20211029102822_add_open_source_plan.rb'
- 'ee/app/graphql/resolvers/geo/registries_resolver.rb'
+ - 'ee/app/models/approval_merge_request_rule.rb'
- 'ee/app/models/approval_project_rule.rb'
- 'ee/app/models/concerns/approval_rule_like.rb'
- 'ee/app/models/concerns/custom_model_naming.rb'
@@ -216,9 +219,12 @@ Style/RedundantSelf:
- 'ee/app/models/ee/description_version.rb'
- 'ee/app/models/ee/environment.rb'
- 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/ee/group.rb'
- 'ee/app/models/ee/group_member.rb'
- 'ee/app/models/ee/issue.rb'
- 'ee/app/models/ee/iteration.rb'
+ - 'ee/app/models/ee/member.rb'
+ - 'ee/app/models/ee/merge_request.rb'
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/ee/packages/package_file.rb'
- 'ee/app/models/ee/project.rb'
@@ -247,13 +253,17 @@ Style/RedundantSelf:
- 'ee/lib/ee/gitlab/auth/ldap/sync/groups.rb'
- 'ee/lib/ee/gitlab/auth/ldap/sync/proxy.rb'
- 'ee/lib/ee/gitlab/auth/ldap/sync/users.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
+ - 'ee/lib/ee/gitlab/background_migration/delete_invalid_epic_issues.rb'
- 'ee/lib/ee/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings.rb'
+ - 'ee/lib/ee/gitlab/database.rb'
- 'ee/lib/ee/gitlab/tracking.rb'
- 'ee/lib/ee/legacy_model.rb'
- 'ee/lib/ee/model.rb'
- 'ee/lib/elastic/instance_proxy_util.rb'
- 'ee/lib/elastic/latest/application_class_proxy.rb'
+ - 'ee/lib/elastic/latest/commit_config.rb'
- 'ee/lib/elastic/latest/issue_config.rb'
- 'ee/lib/elastic/latest/merge_request_config.rb'
- 'ee/lib/elastic/latest/note_config.rb'
@@ -275,9 +285,9 @@ Style/RedundantSelf:
- 'ee/lib/gitlab/geo/oauth/logout_state.rb'
- 'ee/lib/gitlab/geo/replicator.rb'
- 'ee/lib/gitlab/template/custom_template.rb'
+ - 'ee/lib/system_check/app/search_check.rb'
- 'ee/spec/helpers/ee/feature_flags_helper_spec.rb'
- 'ee/spec/helpers/ee/graph_helper_spec.rb'
- - 'ee/spec/models/geo/deleted_project_spec.rb'
- 'lib/api/entities/wiki_attachment.rb'
- 'lib/api/helpers.rb'
- 'lib/api/helpers/packages_helpers.rb'
@@ -328,6 +338,7 @@ Style/RedundantSelf:
- 'lib/gitlab/database/load_balancing/service_discovery.rb'
- 'lib/gitlab/database/loose_foreign_keys.rb'
- 'lib/gitlab/database/migration_helpers/restrict_gitlab_schema.rb'
+ - 'lib/gitlab/database/migrations/background_migration_helpers.rb'
- 'lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb'
- 'lib/gitlab/database/query_analyzers/base.rb'
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
@@ -339,6 +350,7 @@ Style/RedundantSelf:
- 'lib/gitlab/diff/file.rb'
- 'lib/gitlab/diff/rendered/notebook/diff_file.rb'
- 'lib/gitlab/email/smtp_config.rb'
+ - 'lib/gitlab/error_tracking/logger.rb'
- 'lib/gitlab/feature_categories.rb'
- 'lib/gitlab/git.rb'
- 'lib/gitlab/git/blob.rb'
@@ -347,6 +359,7 @@ Style/RedundantSelf:
- 'lib/gitlab/git/tree.rb'
- 'lib/gitlab/git_access.rb'
- 'lib/gitlab/github_import.rb'
+ - 'lib/gitlab/graphql/deprecations_base.rb'
- 'lib/gitlab/graphql/known_operations.rb'
- 'lib/gitlab/graphql/lazy.rb'
- 'lib/gitlab/graphql/representation/submodule_tree_entry.rb'
@@ -399,10 +412,10 @@ Style/RedundantSelf:
- 'lib/system_check/rake_task/rake_task_helpers.rb'
- 'lib/uploaded_file.rb'
- 'qa/lib/gitlab/page/main/sign_up.rb'
- - 'qa/qa/git/repository.rb'
- 'qa/qa/page/validatable.rb'
- 'qa/qa/resource/base.rb'
- 'qa/qa/resource/events/project.rb'
+ - 'qa/qa/resource/personal_access_token.rb'
- 'qa/qa/resource/protected_branch.rb'
- 'qa/qa/resource/reusable.rb'
- 'qa/qa/resource/user_gpg.rb'
@@ -416,6 +429,8 @@ Style/RedundantSelf:
- 'spec/helpers/graph_helper_spec.rb'
- 'spec/helpers/ide_helper_spec.rb'
- 'spec/helpers/submodule_helper_spec.rb'
+ - 'spec/lib/gitlab/background_task_spec.rb'
- 'spec/lib/gitlab/database/load_balancing_spec.rb'
+ - 'spec/models/integration_spec.rb'
- 'spec/support/before_all_adapter.rb'
- 'spec/support/cycle_analytics_helpers/test_generation.rb'
diff --git a/.rubocop_todo/style/rescue_modifier.yml b/.rubocop_todo/style/rescue_modifier.yml
deleted file mode 100644
index 298ef3aece9..00000000000
--- a/.rubocop_todo/style/rescue_modifier.yml
+++ /dev/null
@@ -1,51 +0,0 @@
----
-# Cop supports --auto-correct.
-Style/RescueModifier:
- # Offense count: 59
- # Temporarily disabled due to too many offenses
- Enabled: false
- Exclude:
- - 'app/controllers/admin/system_info_controller.rb'
- - 'app/controllers/users_controller.rb'
- - 'app/finders/ci/daily_build_group_report_results_finder.rb'
- - 'app/helpers/blob_helper.rb'
- - 'app/models/concerns/diff_positionable_note.rb'
- - 'app/models/integrations/jira.rb'
- - 'app/models/sent_notification.rb'
- - 'app/models/todo.rb'
- - 'app/services/security/ci_configuration/sast_parser_service.rb'
- - 'config/initializers/active_record_data_types.rb'
- - 'config/settings.rb'
- - 'ee/app/models/license.rb'
- - 'ee/lib/ee/gitlab/background_migration/drop_invalid_remediations.rb'
- - 'ee/lib/gitlab/geo.rb'
- - 'ee/lib/gitlab/geo/health_check.rb'
- - 'lib/api/helpers.rb'
- - 'lib/feature.rb'
- - 'lib/gitlab/current_settings.rb'
- - 'lib/gitlab/dependency_linker/cargo_toml_linker.rb'
- - 'lib/gitlab/dependency_linker/json_linker.rb'
- - 'lib/gitlab/diff/parser.rb'
- - 'lib/gitlab/import_export/after_export_strategy_builder.rb'
- - 'lib/gitlab/kubernetes.rb'
- - 'lib/gitlab/middleware/read_only/controller.rb'
- - 'lib/gitlab/process_management.rb'
- - 'lib/gitlab/query_limiting/middleware.rb'
- - 'lib/gitlab/quick_actions/command_definition.rb'
- - 'lib/gitlab/quick_actions/spend_time_and_date_separator.rb'
- - 'lib/gitlab/word_diff/segments/diff_hunk.rb'
- - 'lib/gitlab/zentao/client.rb'
- - 'lib/tasks/gitlab/praefect.rake'
- - 'qa/qa/page/component/access_tokens.rb'
- - 'qa/qa/page/profile/ssh_keys.rb'
- - 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
- - 'spec/lib/gitlab/database/load_balancing/session_spec.rb'
- - 'spec/lib/gitlab/database/migrations/instrumentation_spec.rb'
- - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- - 'spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb'
- - 'spec/models/concerns/bulk_insert_safe_spec.rb'
- - 'spec/models/design_management/version_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/namespace/traversal_hierarchy_spec.rb'
- - 'spec/services/design_management/delete_designs_service_spec.rb'
- - 'spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb'
diff --git a/.rubocop_todo/style/string_concatenation.yml b/.rubocop_todo/style/string_concatenation.yml
index 8c8dbf86b1c..2330683cc18 100644
--- a/.rubocop_todo/style/string_concatenation.yml
+++ b/.rubocop_todo/style/string_concatenation.yml
@@ -1,10 +1,8 @@
---
# Cop supports --auto-correct.
Style/StringConcatenation:
- # Offense count: 611
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
+ - 'app/components/pajamas/button_component.rb'
- 'app/controllers/concerns/creates_commit.rb'
- 'app/controllers/groups/dependency_proxy_for_containers_controller.rb'
- 'app/controllers/jira_connect/app_descriptor_controller.rb'
@@ -45,7 +43,6 @@ Style/StringConcatenation:
- 'app/services/packages/debian/generate_distribution_key_service.rb'
- 'app/services/packages/debian/generate_distribution_service.rb'
- 'app/services/pages/zip_directory_service.rb'
- - 'app/services/projects/update_pages_service.rb'
- 'app/services/repositories/base_service.rb'
- 'app/services/verify_pages_domain_service.rb'
- 'app/uploaders/gitlab_uploader.rb'
@@ -56,6 +53,7 @@ Style/StringConcatenation:
- 'db/migrate/20210412111213_create_security_orchestration_policy_rule_schedule.rb'
- 'ee/app/controllers/admin/elasticsearch_controller.rb'
- 'ee/app/finders/ee/issuables/label_filter.rb'
+ - 'ee/app/helpers/ee/geo_helper.rb'
- 'ee/app/helpers/ee/gitlab_routing_helper.rb'
- 'ee/app/helpers/ee/mirror_helper.rb'
- 'ee/app/helpers/ee/search_helper.rb'
@@ -70,6 +68,7 @@ Style/StringConcatenation:
- 'ee/lib/api/project_mirror.rb'
- 'ee/lib/ee/audit/project_changes_auditor.rb'
- 'ee/lib/ee/gitlab/auth/ldap/person.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
- 'ee/lib/elastic/latest/git_class_proxy.rb'
@@ -81,7 +80,6 @@ Style/StringConcatenation:
- 'ee/spec/controllers/trial_registrations_controller_spec.rb'
- 'ee/spec/features/boards/boards_spec.rb'
- 'ee/spec/features/projects/pipelines/pipeline_spec.rb'
- - 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- 'ee/spec/helpers/search_helper_spec.rb'
- 'ee/spec/lib/gitlab/auth/ldap/person_spec.rb'
- 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
@@ -94,8 +92,8 @@ Style/StringConcatenation:
- 'ee/spec/models/dast_site_validation_spec.rb'
- 'ee/spec/models/ee/audit_event_spec.rb'
- 'ee/spec/models/geo_node_spec.rb'
+ - 'ee/spec/models/incident_management/issuable_resource_link_spec.rb'
- 'ee/spec/models/status_page/project_setting_spec.rb'
- - 'ee/spec/requests/api/internal/kubernetes_spec.rb'
- 'ee/spec/services/jira/jql_builder_service_spec.rb'
- 'ee/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
@@ -138,6 +136,7 @@ Style/StringConcatenation:
- 'lib/gitlab/kubernetes/kubectl_cmd.rb'
- 'lib/gitlab/lfs/client.rb'
- 'lib/gitlab/logger.rb'
+ - 'lib/gitlab/pages/deployment_update.rb'
- 'lib/gitlab/path_regex.rb'
- 'lib/gitlab/prometheus/internal.rb'
- 'lib/gitlab/quick_actions/extractor.rb'
@@ -150,6 +149,7 @@ Style/StringConcatenation:
- 'lib/gitlab/throttle.rb'
- 'lib/gitlab/time_tracking_formatter.rb'
- 'lib/gitlab/untrusted_regexp.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/issues_created_from_alerts_metric.rb'
- 'lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb'
- 'lib/gitlab/usage_data_queries.rb'
- 'lib/google_api/cloud_platform/client.rb'
@@ -163,8 +163,8 @@ Style/StringConcatenation:
- 'qa/qa/page/milestone/new.rb'
- 'qa/qa/page/project/milestone/new.rb'
- 'qa/qa/page/project/settings/deploy_tokens.rb'
+ - 'qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/assign_code_owners_spec.rb'
- - 'qa/qa/support/page_error_checker.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- 'scripts/perf/gc/print_gc_stats.rb'
- 'scripts/perf/query_limiting_report.rb'
@@ -230,7 +230,6 @@ Style/StringConcatenation:
- 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
- 'spec/lib/gitlab/gitaly_client/wiki_service_spec.rb'
- 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/kubernetes/kube_client_spec.rb'
- 'spec/lib/gitlab/lfs/client_spec.rb'
- 'spec/lib/gitlab/other_markup_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
@@ -246,6 +245,7 @@ Style/StringConcatenation:
- 'spec/lib/gitlab/tree_summary_spec.rb'
- 'spec/lib/gitlab/url_blocker_spec.rb'
- 'spec/lib/gitlab/utils_spec.rb'
+ - 'spec/lib/gitlab/visibility_level_spec.rb'
- 'spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb'
- 'spec/lib/gitlab/workhorse_spec.rb'
- 'spec/lib/kramdown/kramdown_spec.rb'
@@ -288,12 +288,14 @@ Style/StringConcatenation:
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/notes_spec.rb'
- 'spec/requests/api/pypi_packages_spec.rb'
+ - 'spec/requests/users_controller_spec.rb'
- 'spec/routing/git_http_routing_spec.rb'
- 'spec/services/ci/find_exposed_artifacts_service_spec.rb'
- 'spec/services/clusters/gcp/finalize_creation_service_spec.rb'
- 'spec/services/clusters/kubernetes/configure_istio_ingress_service_spec.rb'
- 'spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb'
- 'spec/services/error_tracking/list_projects_service_spec.rb'
+ - 'spec/services/groups/update_service_spec.rb'
- 'spec/services/merge_requests/build_service_spec.rb'
- 'spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb'
- 'spec/services/packages/conan/create_package_file_service_spec.rb'
@@ -303,6 +305,7 @@ Style/StringConcatenation:
- 'spec/services/projects/create_service_spec.rb'
- 'spec/services/projects/destroy_service_spec.rb'
- 'spec/services/projects/download_service_spec.rb'
+ - 'spec/services/projects/update_service_spec.rb'
- 'spec/services/push_event_payload_service_spec.rb'
- 'spec/services/repositories/destroy_service_spec.rb'
- 'spec/services/snippets/bulk_destroy_service_spec.rb'
@@ -323,9 +326,9 @@ Style/StringConcatenation:
- 'spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb'
- 'spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb'
- 'spec/support/shared_examples/models/wiki_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/hooks_shared_examples.rb'
- 'spec/support/shared_examples/requests/snippet_shared_examples.rb'
- 'spec/support/unpack-gitlab-git-test'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- 'spec/tooling/lib/tooling/kubernetes_client_spec.rb'
- 'spec/uploaders/job_artifact_uploader_spec.rb'
- 'spec/validators/addressable_url_validator_spec.rb'
diff --git a/.rubocop_todo/style/symbol_proc.yml b/.rubocop_todo/style/symbol_proc.yml
index ea3a505d2da..75aab7c6116 100644
--- a/.rubocop_todo/style/symbol_proc.yml
+++ b/.rubocop_todo/style/symbol_proc.yml
@@ -1,9 +1,6 @@
---
# Cop supports --auto-correct.
Style/SymbolProc:
- # Offense count: 341
- # Temporarily disabled due to too many offenses
- Enabled: false
Exclude:
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/concerns/renders_blob.rb'
@@ -14,7 +11,10 @@ Style/SymbolProc:
- 'app/controllers/profiles_controller.rb'
- 'app/finders/packages/go/version_finder.rb'
- 'app/graphql/mutations/commits/create.rb'
+ - 'app/graphql/mutations/concerns/mutations/work_items/widgetable.rb'
- 'app/graphql/mutations/jira_import/start.rb'
+ - 'app/graphql/mutations/work_items/update_widgets.rb'
+ - 'app/graphql/types/work_items/widgets/description_type.rb'
- 'app/helpers/graph_helper.rb'
- 'app/models/ci/build_metadata.rb'
- 'app/models/ci/build_trace_chunk.rb'
@@ -24,6 +24,7 @@ Style/SymbolProc:
- 'app/models/concerns/board_recent_visit.rb'
- 'app/models/concerns/resolvable_discussion.rb'
- 'app/models/container_repository.rb'
+ - 'app/models/deployment.rb'
- 'app/models/discussion.rb'
- 'app/models/environment.rb'
- 'app/models/integrations/prometheus.rb'
@@ -43,11 +44,9 @@ Style/SymbolProc:
- 'app/serializers/build_details_entity.rb'
- 'app/serializers/ci/pipeline_entity.rb'
- 'app/serializers/ci/trigger_entity.rb'
- - 'app/serializers/cluster_entity.rb'
- 'app/serializers/deployment_cluster_entity.rb'
- 'app/serializers/deployment_entity.rb'
- 'app/serializers/draft_note_entity.rb'
- - 'app/serializers/environment_entity.rb'
- 'app/serializers/import/bitbucket_provider_repo_entity.rb'
- 'app/serializers/import/fogbugz_provider_repo_entity.rb'
- 'app/serializers/issuable_sidebar_basic_entity.rb'
@@ -55,6 +54,7 @@ Style/SymbolProc:
- 'app/serializers/linked_project_issue_entity.rb'
- 'app/serializers/member_entity.rb'
- 'app/serializers/member_user_entity.rb'
+ - 'app/serializers/merge_request_poll_widget_entity.rb'
- 'app/serializers/merge_request_widget_entity.rb'
- 'app/serializers/project_entity.rb'
- 'app/serializers/project_mirror_entity.rb'
@@ -69,7 +69,6 @@ Style/SymbolProc:
- 'app/services/ci/update_build_state_service.rb'
- 'app/services/clusters/agents/delete_expired_events_service.rb'
- 'app/services/feature_flags/update_service.rb'
- - 'app/services/google_cloud/enable_cloud_run_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'
@@ -81,6 +80,7 @@ Style/SymbolProc:
- 'app/workers/bulk_imports/stuck_import_worker.rb'
- 'app/workers/ci/build_trace_chunk_flush_worker.rb'
- 'app/workers/gitlab/import/stuck_import_job.rb'
+ - 'app/workers/merge_requests/update_head_pipeline_worker.rb'
- 'app/workers/namespaces/prune_aggregation_schedules_worker.rb'
- 'app/workers/stuck_export_jobs_worker.rb'
- 'app/workers/update_head_pipeline_for_merge_request_worker.rb'
@@ -92,6 +92,7 @@ Style/SymbolProc:
- 'db/migrate/20210318134427_delete_security_findings_without_uuid.rb'
- 'db/migrate/20210503105845_add_project_value_stream_id_to_project_stages.rb'
- 'db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb'
+ - 'db/post_migrate/20220803042352_cleanup_mr_attention_request_todos.rb'
- 'ee/app/helpers/ee/mirror_helper.rb'
- 'ee/app/helpers/ee/registrations_helper.rb'
- 'ee/app/models/concerns/epic_tree_sorting.rb'
@@ -119,6 +120,7 @@ Style/SymbolProc:
- 'ee/lib/ee/api/entities/geo_node.rb'
- 'ee/lib/ee/api/entities/merge_request_approval_state.rb'
- 'ee/lib/ee/gitlab/auth/ldap/access.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
- 'ee/lib/ee/gitlab/background_migration/drop_invalid_remediations.rb'
- 'ee/lib/ee/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'ee/lib/ee/gitlab/background_migration/populate_uuids_for_security_findings.rb'
@@ -126,6 +128,7 @@ Style/SymbolProc:
- 'ee/lib/gitlab/contribution_analytics/data_collector.rb'
- 'ee/lib/gitlab/custom_file_templates.rb'
- 'ee/lib/gitlab/geo/oauth/logout_state.rb'
+ - 'ee/spec/elastic/migrate/20220118150500_delete_orphaned_commits_spec.rb'
- 'ee/spec/factories/issues.rb'
- 'ee/spec/features/billings/extend_reactivate_trial_spec.rb'
- 'ee/spec/features/billings/qrtly_reconciliation_alert_spec.rb'
@@ -133,13 +136,12 @@ 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/lib/gitlab/graphql/aggregations/issues/lazy_links_aggregate_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'
- 'lib/api/api_guard.rb'
- 'lib/api/entities/board.rb'
- - 'lib/api/entities/environment.rb'
- 'lib/api/entities/issuable_references.rb'
- 'lib/api/entities/merge_request_approvals.rb'
- 'lib/api/entities/package.rb'
@@ -148,7 +150,6 @@ Style/SymbolProc:
- 'lib/api/go_proxy.rb'
- 'lib/api/helpers/internal_helpers.rb'
- 'lib/api/package_files.rb'
- - 'lib/api/terraform/state.rb'
- 'lib/atlassian/jira_connect/serializers/base_entity.rb'
- 'lib/banzai/filter/inline_cluster_metrics_filter.rb'
- 'lib/banzai/filter/inline_embeds_filter.rb'
@@ -157,6 +158,7 @@ Style/SymbolProc:
- 'lib/container_registry/client.rb'
- 'lib/container_registry/gitlab_api_client.rb'
- 'lib/gitlab/analytics/cycle_analytics/stage_events.rb'
+ - 'lib/gitlab/auth/o_auth/auth_hash.rb'
- 'lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- 'lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb'
@@ -164,7 +166,6 @@ Style/SymbolProc:
- 'lib/gitlab/cache/ci/project_pipeline_status.rb'
- 'lib/gitlab/checks/changes_access.rb'
- 'lib/gitlab/ci/pipeline/preloader.rb'
- - 'lib/gitlab/ci/runner_upgrade_check.rb'
- 'lib/gitlab/ci/trace.rb'
- 'lib/gitlab/config/entry/node.rb'
- 'lib/gitlab/database/async_indexes/migration_helpers.rb'
@@ -172,6 +173,7 @@ Style/SymbolProc:
- 'lib/gitlab/database/migrations/background_migration_helpers.rb'
- 'lib/gitlab/database/migrations/instrumentation.rb'
- 'lib/gitlab/diff/file_collection/base.rb'
+ - 'lib/gitlab/diff/rendered/notebook/diff_file_helper.rb'
- 'lib/gitlab/git/diff_stats_collection.rb'
- 'lib/gitlab/gitaly_client/commit_service.rb'
- 'lib/gitlab/gitaly_client/wiki_service.rb'
@@ -199,9 +201,9 @@ Style/SymbolProc:
- 'qa/qa/resource/project_snippet.rb'
- 'qa/qa/runtime/ip_address.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb'
- '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'
@@ -219,6 +221,7 @@ Style/SymbolProc:
- 'spec/controllers/concerns/product_analytics_tracking_spec.rb'
- 'spec/controllers/concerns/redis_tracking_spec.rb'
- 'spec/controllers/projects/merge_requests/conflicts_controller_spec.rb'
+ - 'spec/factories/application_settings.rb'
- 'spec/factories/ci/builds.rb'
- 'spec/factories/clusters/providers/aws.rb'
- 'spec/factories/oauth_openid_requests.rb'
@@ -234,16 +237,19 @@ Style/SymbolProc:
- 'spec/finders/license_template_finder_spec.rb'
- 'spec/finders/packages/go/version_finder_spec.rb'
- 'spec/graphql/mutations/releases/create_spec.rb'
+ - 'spec/graphql/types/work_items/widget_type_enum_spec.rb'
- 'spec/helpers/instance_configuration_helper_spec.rb'
- 'spec/helpers/learn_gitlab_helper_spec.rb'
- 'spec/helpers/members_helper_spec.rb'
- 'spec/lib/backup/gitaly_backup_spec.rb'
- 'spec/lib/gitlab/database/dynamic_model_helpers_spec.rb'
+ - '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'
- 'spec/lib/gitlab/instrumentation/redis_spec.rb'
- 'spec/lib/gitlab/optimistic_locking_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/in_operator_optimization/query_builder_spec.rb'
@@ -252,12 +258,14 @@ Style/SymbolProc:
- 'spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb'
- 'spec/lib/omni_auth/strategies/jwt_spec.rb'
- 'spec/models/member_spec.rb'
+ - 'spec/models/merge_request_diff_spec.rb'
- 'spec/models/namespace/root_storage_statistics_spec.rb'
- 'spec/models/operations/feature_flags/strategy_spec.rb'
- 'spec/models/project_statistics_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/presenters/projects/import_export/project_export_presenter_spec.rb'
+ - 'spec/requests/api/internal/mail_room_spec.rb'
- 'spec/requests/api/snippet_repository_storage_moves_spec.rb'
- 'spec/requests/api/tags_spec.rb'
- 'spec/services/ci/pipelines/add_job_service_spec.rb'
@@ -266,12 +274,14 @@ Style/SymbolProc:
- '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'
- 'spec/support/helpers/migrations_helpers.rb'
- 'spec/support/shared_contexts/finders/users_finder_shared_contexts.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb'
+ - 'spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb'
- 'spec/support/shared_examples/models/label_note_shared_examples.rb'
- 'spec/views/layouts/_published_experiments.html.haml_spec.rb'
- 'spec/workers/snippets/schedule_bulk_repository_shard_moves_worker_spec.rb'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9d53d1ac30..fa13dc64d47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -718,6 +718,29 @@ entry.
- [Update GitLab Runner Helm Chart to 0.42.0](gitlab-org/gitlab@cc89200f498fe216864914c79b5b0d1d578edab3) ([merge request](gitlab-org/gitlab!90605))
- [Address database documentation Vale warningss](gitlab-org/gitlab@e5f9a089766bace046d3bbd760a2979865a4bbc0) by @cgives ([merge request](gitlab-org/gitlab!90093))
+## 15.1.4 (2022-07-28)
+
+### Security (18 changes)
+
+- [Security datadog integration leaking](gitlab-org/security/gitlab@1aadbf61796ff95b4716fb8ef335c5a4dbdf8c6a) ([merge request](gitlab-org/security/gitlab!2594))
+- [Prevent users who cannot admin a public project from viewing deploy keys](gitlab-org/security/gitlab@a69bec0e58f4ee0df0774dcde1ce1817d41daa7c) ([merge request](gitlab-org/security/gitlab!2641))
+- [Add additional condition to accept invitation](gitlab-org/security/gitlab@b3480d20512d61b761da2a8772ec2bfe32182169) ([merge request](gitlab-org/security/gitlab!2655))
+- [Update GITLAB_PAGES_VERSION](gitlab-org/security/gitlab@6161c0445e4908cdc152bee4be8b9d223df9f1d0) ([merge request](gitlab-org/security/gitlab!2584))
+- [Add html_escape to build_details_entity](gitlab-org/security/gitlab@c0a82385320e144b55e400eff96f39aa56af33ef) ([merge request](gitlab-org/security/gitlab!2610))
+- [Check permissions when filtering by contact or organization](gitlab-org/security/gitlab@5b8f2da656ec7839614d4a49f35778ed00b31b2b) ([merge request](gitlab-org/security/gitlab!2645))
+- [Use author to run subscribed pipeline](gitlab-org/security/gitlab@982917161408cfe4c3191f352bb1d390dfa3c9fd) ([merge request](gitlab-org/security/gitlab!2558))
+- [Remove prohibited branches after project import](gitlab-org/security/gitlab@48864bf7539176eb385f5ce792c8e369a2b79fe6) ([merge request](gitlab-org/security/gitlab!2589))
+- [Remove feature flag `ci_yaml_limit_size`](gitlab-org/security/gitlab@b532b82ef2a0ef5b045932a56ffc06281df7a1d8) ([merge request](gitlab-org/security/gitlab!2630))
+- [Maintainer can change the visibility of Project and Group](gitlab-org/security/gitlab@9556769a3a2fe2c030eb55e87b1465638d315358) ([merge request](gitlab-org/security/gitlab!2618))
+- [Do not link unverified secondary emails with any users](gitlab-org/security/gitlab@331b1d6b590b01c3d45332a6c8e09def249c627e) ([merge request](gitlab-org/security/gitlab!2627))
+- [Forbid exchanging access token for ROP flow to users required 2FA setup](gitlab-org/security/gitlab@15bc29c4ab878365356e59c0c8d2e0f361b71e70) ([merge request](gitlab-org/security/gitlab!2621))
+- [Remove todos from confidential notes when user loses access](gitlab-org/security/gitlab@9672296987190cc4b08b1f32f3c45086880b06bc) ([merge request](gitlab-org/security/gitlab!2608))
+- [Remove group_bot_user and group_access_token after group delete](gitlab-org/security/gitlab@9b1a5e7101e1addee8c3429f4937980020c5f6b3) ([merge request](gitlab-org/security/gitlab!2634))
+- [Protect integration secrets](gitlab-org/security/gitlab@4920ac9b10e237cca5d279cbd3cf60daa829a71b) ([merge request](gitlab-org/security/gitlab!2585))
+- [Protect Grafana and Sentry integrations](gitlab-org/security/gitlab@a5d33edb1c557e9bbd0a1a79c81e851c1d740e37) ([merge request](gitlab-org/security/gitlab!2576))
+- [Fix IDOR in Jira issue show action](gitlab-org/security/gitlab@8b62e0c09c33c44f508266d7b8db4892105124ac) ([merge request](gitlab-org/security/gitlab!2648))
+- [Limit proxied requests to Grafana API](gitlab-org/security/gitlab@4580e61bc22b04eda13e293c5868a26a1a6ee571) ([merge request](gitlab-org/security/gitlab!2597))
+
## 15.1.3 (2022-07-19)
### Added (1 change)
@@ -1727,6 +1750,29 @@ entry.
- [Fix JH skipped subscription portal spec](gitlab-org/gitlab@0e7e7cb4a62d004989c47fafe6fe1f9ffd90da44) by @chaomao ([merge request](gitlab-org/gitlab!87213))
- [Add not null constraint to requirements.issue_id validate:false](gitlab-org/gitlab@5ccac890b13c53c5761ccb8e5cb7ca202e0656c3) ([merge request](gitlab-org/gitlab!86590))
+## 15.0.5 (2022-07-28)
+
+### Security (18 changes)
+
+- [Security datadog integration leaking](gitlab-org/security/gitlab@827505e96860979709654210525007901abd56f0) ([merge request](gitlab-org/security/gitlab!2595))
+- [Prevent users who cannot admin a public project from viewing deploy keys](gitlab-org/security/gitlab@2b06195d21bbd6b566221c49e871cd8da1f744b6) ([merge request](gitlab-org/security/gitlab!2642))
+- [Add additional condition to accept invitation](gitlab-org/security/gitlab@8aa70bcc8a3eb1bd2f96c06e9b0e5b6eb0ac561d) ([merge request](gitlab-org/security/gitlab!2654))
+- [Update GITLAB_PAGES_VERSION](gitlab-org/security/gitlab@6b81c541a60da6c389788d21a216dab4d7e40304) ([merge request](gitlab-org/security/gitlab!2583))
+- [Add html_escape to build_details_entity](gitlab-org/security/gitlab@efe16cfa36ff42981891994d5b5e63dcdd2f1daa) ([merge request](gitlab-org/security/gitlab!2611))
+- [Check permissions when filtering by contact or organization](gitlab-org/security/gitlab@3d210e31d933cfff0c9fae9dd2f1ed97058bfea6) ([merge request](gitlab-org/security/gitlab!2646))
+- [Use author to run subscribed pipeline](gitlab-org/security/gitlab@c1ca513e600d1a963e23ab63c261c982780593b5) ([merge request](gitlab-org/security/gitlab!2559))
+- [Remove prohibited branches after project import](gitlab-org/security/gitlab@8ceb9492555471041f962d54e190314aac86207c) ([merge request](gitlab-org/security/gitlab!2588))
+- [Remove feature flag `ci_yaml_limit_size`](gitlab-org/security/gitlab@df0d379902f0e03a6f1506276402246cfe2e922f) ([merge request](gitlab-org/security/gitlab!2631))
+- [Maintainer can change the visibility of Project and Group](gitlab-org/security/gitlab@1e575f57368d7374dc33e151e81a2f5dfe3fa21e) ([merge request](gitlab-org/security/gitlab!2617))
+- [Do not link unverified secondary emails with any users](gitlab-org/security/gitlab@e15f72a77f67e946258576d1b3006e9471d5ec9a) ([merge request](gitlab-org/security/gitlab!2626))
+- [Forbid exchanging access token for ROP flow to users required 2FA setup](gitlab-org/security/gitlab@7250fb15bf59401acd0c88c89d27423578b24f71) ([merge request](gitlab-org/security/gitlab!2620))
+- [Remove todos from confidential notes when user loses access](gitlab-org/security/gitlab@f91cc66eaa83c9a0744d8f25ee56197b5805035e) ([merge request](gitlab-org/security/gitlab!2609))
+- [Remove group_bot_user and group_access_token after group delete](gitlab-org/security/gitlab@995de100fcba61c0efa11c1a2a98377c90f68f0c) ([merge request](gitlab-org/security/gitlab!2635))
+- [Protect integration secrets](gitlab-org/security/gitlab@e475ad82568f5d9da62d8a89c0ee3393a97685bf) ([merge request](gitlab-org/security/gitlab!2586))
+- [Protect Grafana and Sentry integrations](gitlab-org/security/gitlab@0c3fa9f84e2459e63ec58d6253752649489d6283) ([merge request](gitlab-org/security/gitlab!2577))
+- [Fix IDOR in Jira issue show action](gitlab-org/security/gitlab@cf6ad0474584f701e3f14262284ab681f6a06a42) ([merge request](gitlab-org/security/gitlab!2649))
+- [Limit proxied requests to Grafana API](gitlab-org/security/gitlab@28225721c1bce851d81b6e462ec6965570c7320a) ([merge request](gitlab-org/security/gitlab!2598))
+
## 15.0.4 (2022-06-30)
### Security (17 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index ee7380d66e8..290560112c3 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-15.2.2 \ No newline at end of file
+8263b2f7f00bb5197a1b97f2a420c5662af8e40c
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
index 6c43fc8aefc..5ff58dbcd68 100644
--- a/GITLAB_KAS_VERSION
+++ b/GITLAB_KAS_VERSION
@@ -1 +1 @@
-15.2.0
+15.3.0
diff --git a/GITLAB_METRICS_EXPORTER_VERSION b/GITLAB_METRICS_EXPORTER_VERSION
index ba2906d0666..f3e956091b9 100644
--- a/GITLAB_METRICS_EXPORTER_VERSION
+++ b/GITLAB_METRICS_EXPORTER_VERSION
@@ -1 +1 @@
-main
+2c781b65ccfd6d016c7bfab1982ecb234c4e2cd0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 30e298c7494..76d05362056 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.61.1
+1.62.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 44a5e718d50..6242bb49da0 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-14.9.0
+14.10.0
diff --git a/Gemfile b/Gemfile
index df9b68c5495..e85488a34fb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,25 +2,25 @@
source 'https://rubygems.org'
-gem 'rails', '~> 6.1.4.7'
+gem 'rails', '~> 6.1.6.1'
-gem 'bootsnap', '~> 1.12.0', require: false
+gem 'bootsnap', '~> 1.13.0', require: false
# Responders respond_to and respond_with
gem 'responders', '~> 3.0'
gem 'sprockets', '~> 3.7.0'
-gem 'view_component', '~> 2.50.0'
+gem 'view_component', '~> 2.61'
# Default values for AR models
gem 'default_value_for', '~> 3.4.0'
# Supported DBs
-gem 'pg', '~> 1.3.0'
+gem 'pg', '~> 1.4.0'
gem 'rugged', '~> 1.2'
-gem 'grape-path-helpers', '~> 1.7.0'
+gem 'grape-path-helpers', '~> 1.7.1'
gem 'faraday', '~> 1.0'
gem 'marginalia', '~> 1.10.0'
@@ -39,8 +39,8 @@ gem 'ruby-saml', '~> 1.13.0'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-activedirectory-v2', '~> 1.0'
-gem 'omniauth-azure-oauth2', '~> 0.0.9' # Deprecated v1 version
-gem 'omniauth-cas3', '~> 1.1.4'
+gem 'omniauth-azure-oauth2', '~> 0.0.9' # See vendor/gems/omniauth-azure-oauth2/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-facebook', '~> 4.0.0'
@@ -56,7 +56,7 @@ gem 'omniauth-authentiq', '~> 0.3.3'
gem 'gitlab-omniauth-openid-connect', '~> 0.9.0', require: 'omniauth_openid_connect'
gem 'omniauth-salesforce', '~> 1.0.5'
gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
-gem 'rack-oauth2', '~> 1.19.0'
+gem 'rack-oauth2', '~> 1.21.2'
gem 'jwt', '~> 2.1.0'
# Kerberos authentication. EE-only
@@ -78,7 +78,7 @@ gem 'u2f', '~> 0.2.1'
gem 'validates_hostname', '~> 1.0.11'
gem 'rubyzip', '~> 2.3.2', require: 'zip'
# GitLab Pages letsencrypt support
-gem 'acme-client', '~> 2.0', '>= 2.0.9'
+gem 'acme-client', '~> 2.0'
# Browser detection
gem 'browser', '~> 4.2'
@@ -168,10 +168,10 @@ gem 'asciidoctor', '~> 2.0.10'
gem 'asciidoctor-include-ext', '~> 0.4.0', require: false
gem 'asciidoctor-plantuml', '~> 0.0.12'
gem 'asciidoctor-kroki', '~> 0.5.0', require: false
-gem 'rouge', '~> 3.29.0'
-gem 'truncato', '~> 0.7.11'
+gem 'rouge', '~> 3.30.0'
+gem 'truncato', '~> 0.7.12'
gem 'bootstrap_form', '~> 4.2.0'
-gem 'nokogiri', '~> 1.13.6'
+gem 'nokogiri', '~> 1.13.0'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -187,7 +187,7 @@ gem 'rack', '~> 2.2.4'
gem 'rack-timeout', '~> 0.6.0', require: 'rack/timeout/base'
group :puma do
- gem 'puma', '~> 5.6.2', require: false
+ gem 'puma', '~> 5.6.4', require: false
gem 'puma_worker_killer', '~> 0.3.1', require: false
gem 'sd_notify', '~> 0.1.0', require: false
end
@@ -237,7 +237,7 @@ gem 'redis', '~> 4.4.0'
gem 'connection_pool', '~> 2.0'
# Redis session store
-gem 'redis-actionpack', '~> 5.2.0'
+gem 'redis-actionpack', '~> 5.3.0'
# Discord integration
gem 'discordrb-webhooks', '~> 3.4', require: false
@@ -262,7 +262,7 @@ gem 'asana', '~> 0.10.13'
gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration
-gem 'kubeclient', '~> 4.9.2'
+gem 'kubeclient', '~> 4.9.3'
# Sanitize user input
gem 'sanitize', '~> 6.0'
@@ -299,7 +299,7 @@ gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
-gem 'gitlab-license', '~> 2.1.0'
+gem 'gitlab-license', '~> 2.2.1'
# Protect against bruteforcing
gem 'rack-attack', '~> 6.6.0'
@@ -317,7 +317,7 @@ gem 'pg_query', '~> 2.1.0'
gem 'premailer-rails', '~> 1.10.3'
# LabKit: Tracing and Correlation
-gem 'gitlab-labkit', '~> 0.23.0'
+gem 'gitlab-labkit', '~> 0.24.0'
# Thrift is a dependency of gitlab-labkit, we want a version higher than 0.14.0
# because of https://gitlab.com/gitlab-org/gitlab/-/issues/321900
gem 'thrift', '>= 0.14.0'
@@ -345,27 +345,25 @@ gem 'prometheus-client-mmap', '~> 0.16', require: 'prometheus/client'
gem 'warning', '~> 1.3.0'
group :development do
- gem 'lefthook', '~> 1.0.0', require: false
+ gem 'lefthook', '~> 1.1.0', require: false
gem 'rubocop'
- gem 'solargraph', '~> 0.44.3', require: false
+ gem 'solargraph', '~> 0.45.0', require: false
gem 'letter_opener_web', '~> 2.0.0'
+ gem 'lookbook'
# Better errors handler
gem 'better_errors', '~> 2.9.0'
- # thin instead webrick
- gem 'thin', '~> 1.8.0'
-
gem 'sprite-factory', '~> 1.7'
end
group :development, :test do
gem 'deprecation_toolkit', '~> 1.5.1', require: false
- gem 'bullet', '~> 6.1.3'
+ gem 'bullet', '~> 7.0.2'
gem 'pry-byebug'
gem 'pry-rails', '~> 0.3.9'
- gem 'pry-shell', '~> 0.5.0'
+ gem 'pry-shell', '~> 0.5.1'
gem 'awesome_print', require: false
@@ -408,7 +406,7 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 3.4.3', require: false
+ gem 'gitlab-dangerfiles', '~> 3.5.0', require: false
end
group :development, :test, :coverage do
@@ -420,10 +418,7 @@ end
# Gems required in omnibus-gitlab pipeline
group :development, :test, :omnibus do
- # Using a fork until https://github.com/pivotal/LicenseFinder/pull/816 is
- # resolved. For details, check discussion in
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74881
- gem 'gitlab-license_finder', '~> 6.0', require: false
+ gem 'license_finder', '~> 7.0', require: false
end
group :test do
@@ -437,6 +432,8 @@ group :test do
gem 'capybara-screenshot', '~> 1.0.22'
gem 'selenium-webdriver', '~> 3.142'
+ gem 'graphlyte', '~> 1.0.0'
+
gem 'shoulda-matchers', '~> 5.1.0', require: false
gem 'email_spec', '~> 2.2.0'
gem 'webmock', '~> 3.9.1'
@@ -486,21 +483,21 @@ gem 'ssh_data', '~> 1.3'
gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 15.1.0-rc1'
+gem 'gitaly', '~> 15.3.0-rc3'
# KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2'
gem 'grpc', '~> 1.42.0'
-gem 'google-protobuf', '~> 3.19.0'
+gem 'google-protobuf', '~> 3.21'
gem 'toml-rb', '~> 2.0'
# Feature toggles
-gem 'flipper', '~> 0.21.0'
-gem 'flipper-active_record', '~> 0.21.0'
-gem 'flipper-active_support_cache_store', '~> 0.21.0'
+gem 'flipper', '~> 0.25.0'
+gem 'flipper-active_record', '~> 0.25.0'
+gem 'flipper-active_support_cache_store', '~> 0.25.0'
gem 'unleash', '~> 3.2.2'
gem 'gitlab-experiment', '~> 0.7.1'
@@ -536,9 +533,9 @@ gem 'valid_email', '~> 0.1'
# JSON
gem 'json', '~> 2.5.1'
gem 'json_schemer', '~> 0.2.18'
-gem 'oj', '~> 3.13.19'
+gem 'oj', '~> 3.13.20'
gem 'multi_json', '~> 1.14.1'
-gem 'yajl-ruby', '~> 1.4.1', require: 'yajl'
+gem 'yajl-ruby', '~> 1.4.3', require: 'yajl'
gem 'webauthn', '~> 2.3'
diff --git a/Gemfile.lock b/Gemfile.lock
index 718bcfcac9a..f04445e1d57 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -25,6 +25,14 @@ PATH
mail (~> 2.7)
PATH
+ remote: vendor/gems/omniauth-cas3
+ specs:
+ omniauth-cas3 (1.1.4)
+ addressable (~> 2.3)
+ nokogiri (~> 1.7, >= 1.7.1)
+ omniauth (~> 1.2, < 3)
+
+PATH
remote: vendor/gems/omniauth-gitlab
specs:
omniauth-gitlab (4.0.0)
@@ -43,65 +51,66 @@ GEM
remote: https://rubygems.org/
specs:
RedCloth (4.3.2)
- acme-client (2.0.9)
- faraday (>= 0.17, < 2.0.0)
- actioncable (6.1.4.7)
- actionpack (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ acme-client (2.0.11)
+ faraday (>= 1.0, < 3.0.0)
+ faraday-retry (~> 1.0)
+ actioncable (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.1.4.7)
- actionpack (= 6.1.4.7)
- activejob (= 6.1.4.7)
- activerecord (= 6.1.4.7)
- activestorage (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ actionmailbox (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ activejob (= 6.1.6.1)
+ activerecord (= 6.1.6.1)
+ activestorage (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
mail (>= 2.7.1)
- actionmailer (6.1.4.7)
- actionpack (= 6.1.4.7)
- actionview (= 6.1.4.7)
- activejob (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ actionmailer (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ actionview (= 6.1.6.1)
+ activejob (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.1.4.7)
- actionview (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ actionpack (6.1.6.1)
+ actionview (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.1.4.7)
- actionpack (= 6.1.4.7)
- activerecord (= 6.1.4.7)
- activestorage (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ actiontext (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ activerecord (= 6.1.6.1)
+ activestorage (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
nokogiri (>= 1.8.5)
- actionview (6.1.4.7)
- activesupport (= 6.1.4.7)
+ actionview (6.1.6.1)
+ activesupport (= 6.1.6.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.1.4.7)
- activesupport (= 6.1.4.7)
+ activejob (6.1.6.1)
+ activesupport (= 6.1.6.1)
globalid (>= 0.3.6)
- activemodel (6.1.4.7)
- activesupport (= 6.1.4.7)
- activerecord (6.1.4.7)
- activemodel (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ activemodel (6.1.6.1)
+ activesupport (= 6.1.6.1)
+ activerecord (6.1.6.1)
+ activemodel (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
- activestorage (6.1.4.7)
- actionpack (= 6.1.4.7)
- activejob (= 6.1.4.7)
- activerecord (= 6.1.4.7)
- activesupport (= 6.1.4.7)
- marcel (~> 1.0.0)
+ activestorage (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ activejob (= 6.1.6.1)
+ activerecord (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
+ marcel (~> 1.0)
mini_mime (>= 1.1.0)
- activesupport (6.1.4.7)
+ activesupport (6.1.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@@ -184,14 +193,14 @@ GEM
rack (>= 0.9.0)
bindata (2.4.10)
binding_ninja (0.2.3)
- bootsnap (1.12.0)
+ bootsnap (1.13.0)
msgpack (~> 1.2)
bootstrap_form (4.2.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
browser (4.2.0)
builder (3.2.4)
- bullet (6.1.3)
+ bullet (7.0.2)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
bundler-audit (0.7.0.1)
@@ -257,7 +266,6 @@ GEM
git
css_parser (1.11.0)
addressable
- daemons (1.3.1)
danger (8.6.1)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
@@ -310,7 +318,7 @@ GEM
devise (~> 4.0)
railties (< 7.1)
rotp (~> 6.0)
- diff-lcs (1.4.4)
+ diff-lcs (1.5.0)
diff_match_patch (0.1.0)
diffy (3.3.0)
discordrb-webhooks (3.4.2)
@@ -373,7 +381,6 @@ GEM
tzinfo
ethon (0.15.0)
ffi (>= 1.15.0)
- eventmachine (1.2.7)
excon (0.90.0)
execjs (2.8.1)
expression_parser (0.9.0)
@@ -405,8 +412,8 @@ GEM
faraday-http-cache (2.4.0)
faraday (>= 0.8)
faraday-httpclient (1.0.1)
- faraday-multipart (1.0.3)
- multipart-post (>= 1.2, < 3)
+ faraday-multipart (1.0.4)
+ multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
@@ -431,13 +438,13 @@ GEM
libyajl2 (~> 1.2)
filelock (1.1.1)
find_a_port (1.0.1)
- flipper (0.21.0)
- flipper-active_record (0.21.0)
- activerecord (>= 5.0, < 7)
- flipper (~> 0.21.0)
- flipper-active_support_cache_store (0.21.0)
- activesupport (>= 5.0, < 7)
- flipper (~> 0.21.0)
+ flipper (0.25.0)
+ flipper-active_record (0.25.0)
+ activerecord (>= 4.2, < 8)
+ flipper (~> 0.25.0)
+ flipper-active_support_cache_store (0.25.0)
+ activesupport (>= 4.2, < 8)
+ flipper (~> 0.25.0)
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
@@ -499,9 +506,9 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- git (1.7.0)
+ git (1.11.0)
rchardet (~> 1.8)
- gitaly (15.1.0.pre.rc1)
+ gitaly (15.3.0.pre.rc3)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab (4.16.1)
@@ -509,7 +516,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (3.4.3)
+ gitlab-dangerfiles (3.5.0)
danger (>= 8.4.5)
danger-gitlab (>= 8.0.0)
rake
@@ -523,22 +530,15 @@ GEM
fog-json (~> 1.2.0)
mime-types
ms_rest_azure (~> 0.12.0)
- gitlab-labkit (0.23.0)
- actionpack (>= 5.0.0, < 7.0.0)
- activesupport (>= 5.0.0, < 7.0.0)
+ gitlab-labkit (0.24.0)
+ actionpack (>= 5.0.0, < 8.0.0)
+ activesupport (>= 5.0.0, < 8.0.0)
grpc (>= 1.37)
jaeger-client (~> 1.1.0)
opentracing (~> 0.4)
pg_query (~> 2.1)
redis (> 3.0.0, < 5.0.0)
- gitlab-license (2.1.0)
- gitlab-license_finder (6.14.2.1)
- bundler
- rubyzip (>= 1, < 3)
- thor (~> 1.0)
- tomlrb (>= 1.3, < 2.1)
- with_env (= 1.1.0)
- xml-simple (~> 1.1.5)
+ gitlab-license (2.2.1)
gitlab-mail_room (0.0.9)
gitlab-markup (1.8.0)
gitlab-net-dns (0.9.1)
@@ -578,9 +578,9 @@ GEM
retriable (>= 2.0, < 4.0)
rexml
signet (~> 0.12)
- google-cloud-env (1.5.0)
- faraday (>= 0.17.3, < 2.0)
- google-protobuf (3.19.4)
+ google-cloud-env (1.6.0)
+ faraday (>= 0.17.3, < 3.0)
+ google-protobuf (3.21.3)
googleapis-common-protos-types (1.3.0)
google-protobuf (~> 3.14)
googleauth (0.14.0)
@@ -602,7 +602,7 @@ GEM
grape-entity (0.10.0)
activesupport (>= 3.0.0)
multi_json (>= 1.3.2)
- grape-path-helpers (1.7.0)
+ grape-path-helpers (1.7.1)
activesupport
grape (~> 1.3)
rake (> 12)
@@ -617,6 +617,7 @@ GEM
faraday (>= 1.0)
faraday_middleware
graphql-client
+ graphlyte (1.0.0)
graphql (1.13.12)
graphql-client (0.17.0)
activesupport (>= 3.0)
@@ -676,6 +677,7 @@ GEM
nokogiri (>= 1.4)
html2text (0.2.0)
nokogiri (~> 1.6)
+ htmlbeautifier (1.4.2)
htmlentities (4.3.4)
http (4.4.1)
addressable (~> 2.3)
@@ -683,7 +685,7 @@ GEM
http-form_data (~> 2.2)
http-parser (~> 1.2.0)
http-accept (1.7.0)
- http-cookie (1.0.4)
+ http-cookie (1.0.5)
domain_name (~> 0.5)
http-form_data (2.3.0)
http-parser (1.2.3)
@@ -692,7 +694,7 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.10.0)
+ i18n (1.12.0)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
@@ -725,7 +727,7 @@ GEM
hana (~> 1.3)
regexp_parser (~> 2.0)
uri_template (~> 0.7)
- jsonpath (1.1.0)
+ jsonpath (1.1.2)
multi_json
jwt (2.1.0)
kaminari (1.2.1)
@@ -744,18 +746,18 @@ GEM
grpc (~> 1.0)
knapsack (1.21.1)
rake
- kramdown (2.3.1)
+ kramdown (2.3.2)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
- kubeclient (4.9.2)
+ kubeclient (4.9.3)
http (>= 3.0, < 5.0)
jsonpath (~> 1.0)
recursive-open-struct (~> 1.1, >= 1.1.1)
rest-client (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
- lefthook (1.0.2)
+ lefthook (1.1.0)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (2.0.0)
@@ -764,13 +766,20 @@ GEM
railties (>= 5.2)
rexml
libyajl2 (1.2.0)
+ license_finder (7.0.1)
+ bundler
+ rubyzip (>= 1, < 3)
+ thor (~> 1.2)
+ tomlrb (>= 1.3, < 2.1)
+ with_env (= 1.1.0)
+ xml-simple (~> 1.1.9)
licensee (9.14.1)
dotenv (~> 2.0)
octokit (~> 4.17)
reverse_markdown (~> 1.0)
rugged (>= 0.24, < 2.0)
thor (>= 0.19, < 2.0)
- listen (3.6.0)
+ listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
locale (2.1.3)
@@ -783,6 +792,15 @@ GEM
loofah (2.18.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
+ lookbook (0.9.3)
+ actioncable
+ htmlbeautifier (~> 1.3)
+ listen (~> 3.0)
+ railties (>= 5.0)
+ redcarpet (~> 3.5)
+ rouge (~> 3.26)
+ view_component (~> 2.0)
+ yard (~> 0.9.25)
lru_redux (1.1.0)
lumberjack (1.2.7)
mail (2.7.1)
@@ -794,9 +812,9 @@ GEM
memoist (0.16.2)
memory_profiler (0.9.14)
method_source (1.0.0)
- mime-types (3.3.1)
+ mime-types (3.4.1)
mime-types-data (~> 3.2015)
- mime-types-data (3.2020.0512)
+ mime-types-data (3.2022.0105)
mini_histogram (0.3.1)
mini_magick (4.10.1)
mini_mime (1.1.2)
@@ -817,10 +835,10 @@ GEM
faraday (>= 0.9, < 2.0.0)
faraday-cookie_jar (~> 0.0.6)
ms_rest (~> 0.7.6)
- msgpack (1.5.2)
+ msgpack (1.5.4)
multi_json (1.14.1)
multi_xml (0.6.0)
- multipart-post (2.1.1)
+ multipart-post (2.2.3)
murmurhash3 (0.1.6)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
@@ -838,7 +856,7 @@ GEM
netrc (0.11.0)
nio4r (2.5.8)
no_proxy_fix (0.1.2)
- nokogiri (1.13.6)
+ nokogiri (1.13.8)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
notiffany (0.1.3)
@@ -853,9 +871,9 @@ GEM
rack (>= 1.2, < 3)
rash_alt (>= 0.4, < 1)
version_gem (~> 1.0)
- octokit (4.20.0)
- faraday (>= 0.9)
- sawyer (~> 0.8.0, >= 0.5.3)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
ohai (16.10.6)
chef-config (>= 12.8, < 17)
chef-utils (>= 16.0, < 17)
@@ -869,7 +887,7 @@ GEM
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
- oj (3.13.19)
+ oj (3.13.20)
omniauth (1.9.1)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
@@ -889,10 +907,6 @@ GEM
jwt (>= 1.0, < 3.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.4)
- omniauth-cas3 (1.1.4)
- addressable (~> 2.3)
- nokogiri (~> 1.7, >= 1.7.1)
- omniauth (~> 1.2)
omniauth-dingtalk-oauth2 (1.0.1)
omniauth-oauth2 (~> 1.7)
omniauth-facebook (4.0.0)
@@ -973,7 +987,7 @@ GEM
tty-color (~> 0.5)
peek (1.1.0)
railties (>= 4.0.0)
- pg (1.3.5)
+ pg (1.4.1)
pg_query (2.1.3)
google-protobuf (>= 3.19.2)
plist (3.6.0)
@@ -1000,12 +1014,12 @@ GEM
pry (~> 0.13.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
- pry-shell (0.5.0)
+ pry-shell (0.5.1)
pry (~> 0.13.0)
tty-markdown
tty-prompt
public_suffix (4.0.7)
- puma (5.6.2)
+ puma (5.6.4)
nio4r (~> 2.0)
puma_worker_killer (0.3.1)
get_process_mem (~> 0.2)
@@ -1020,7 +1034,7 @@ GEM
rack (>= 1.0, < 3)
rack-cors (1.1.1)
rack (>= 2.0.0)
- rack-oauth2 (1.19.0)
+ rack-oauth2 (1.21.2)
activesupport
attr_required
httpclient
@@ -1031,20 +1045,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.6.0)
- rails (6.1.4.7)
- actioncable (= 6.1.4.7)
- actionmailbox (= 6.1.4.7)
- actionmailer (= 6.1.4.7)
- actionpack (= 6.1.4.7)
- actiontext (= 6.1.4.7)
- actionview (= 6.1.4.7)
- activejob (= 6.1.4.7)
- activemodel (= 6.1.4.7)
- activerecord (= 6.1.4.7)
- activestorage (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ rails (6.1.6.1)
+ actioncable (= 6.1.6.1)
+ actionmailbox (= 6.1.6.1)
+ actionmailer (= 6.1.6.1)
+ actionpack (= 6.1.6.1)
+ actiontext (= 6.1.6.1)
+ actionview (= 6.1.6.1)
+ activejob (= 6.1.6.1)
+ activemodel (= 6.1.6.1)
+ activerecord (= 6.1.6.1)
+ activestorage (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
bundler (>= 1.15.0)
- railties (= 6.1.4.7)
+ railties (= 6.1.6.1)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -1053,23 +1067,23 @@ GEM
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
- rails-html-sanitizer (1.4.2)
+ rails-html-sanitizer (1.4.3)
loofah (~> 2.3)
rails-i18n (7.0.3)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
- railties (6.1.4.7)
- actionpack (= 6.1.4.7)
- activesupport (= 6.1.4.7)
+ railties (6.1.6.1)
+ actionpack (= 6.1.6.1)
+ activesupport (= 6.1.6.1)
method_source
- rake (>= 0.13)
+ rake (>= 12.2)
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.10.4)
+ rb-fsevent (0.11.1)
rb-inotify (0.10.1)
ffi (~> 1.0)
rbtrace (0.4.14)
@@ -1083,17 +1097,18 @@ GEM
recaptcha (4.13.1)
json
recursive-open-struct (1.1.3)
+ redcarpet (3.5.1)
redis (4.4.0)
- redis-actionpack (5.2.0)
- actionpack (>= 5, < 7)
+ redis-actionpack (5.3.0)
+ 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-rack (2.1.3)
+ redis-rack (2.1.4)
rack (>= 2.0.8, < 3)
redis-store (>= 1.2, < 2)
- redis-store (1.9.0)
+ redis-store (1.9.1)
redis (>= 4, < 5)
regexp_parser (2.5.0)
regexp_property_values (1.0.0)
@@ -1117,7 +1132,7 @@ GEM
rexml (3.2.5)
rinku (2.0.0)
rotp (6.2.0)
- rouge (3.29.0)
+ rouge (3.30.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@@ -1172,7 +1187,7 @@ GEM
rubocop-ast (>= 0.6.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (1.18.0)
+ rubocop-ast (1.19.1)
parser (>= 3.1.1.0)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
@@ -1224,9 +1239,9 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
- sawyer (0.8.2)
+ sawyer (0.9.2)
addressable (>= 2.3.5)
- faraday (> 0.8, < 2.0)
+ faraday (>= 0.17.3, < 3)
sd_notify (0.1.0)
securecompare (1.0.0)
seed-fu (2.3.7)
@@ -1262,9 +1277,9 @@ GEM
fugit (~> 1.1)
sidekiq (>= 4.2.1)
sigdump (0.2.4)
- signet (0.14.0)
- addressable (~> 2.3)
- faraday (>= 0.17.3, < 2.0)
+ signet (0.17.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simple_po_parser (1.1.6)
@@ -1281,7 +1296,7 @@ GEM
slack-messenger (2.3.4)
snowplow-tracker (0.6.1)
contracts (~> 0.7, <= 0.11)
- solargraph (0.44.3)
+ solargraph (0.45.0)
backport (~> 1.2)
benchmark
bundler (>= 1.17.2)
@@ -1348,10 +1363,6 @@ GEM
test_file_finder (0.1.4)
faraday (~> 1.0)
text (1.3.1)
- thin (1.8.0)
- daemons (~> 1.0, >= 1.0.9)
- eventmachine (~> 1.0, >= 1.0.4)
- rack (>= 1, < 3)
thor (1.2.1)
thrift (0.14.0)
tilt (2.0.10)
@@ -1373,7 +1384,7 @@ GEM
mixlib-shellout (>= 2.0, < 4.0)
net-scp (>= 1.2, < 4.0)
net-ssh (>= 2.9, < 7.0)
- truncato (0.7.11)
+ truncato (0.7.12)
htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0)
tty-color (0.6.0)
@@ -1395,7 +1406,7 @@ GEM
tty-screen (0.8.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
- tzinfo (2.0.4)
+ tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
u2f (0.2.1)
uber (0.1.0)
@@ -1405,10 +1416,10 @@ GEM
rugged (>= 0.27, < 1.3)
unf (0.1.4)
unf_ext
- unf_ext (0.0.8)
+ unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
unicode_utils (1.4.0)
- uniform_notifier (1.13.0)
+ uniform_notifier (1.16.0)
unleash (3.2.2)
murmurhash3 (~> 0.1.6)
unparser (0.6.0)
@@ -1429,7 +1440,7 @@ GEM
activesupport (>= 3.0)
version_gem (1.0.0)
version_sorter (2.2.4)
- view_component (2.50.0)
+ view_component (2.61.0)
activesupport (>= 5.0.0, < 8.0)
method_source (~> 1.0)
vmstat (2.3.0)
@@ -1464,10 +1475,11 @@ GEM
wisper (2.0.1)
with_env (1.1.0)
wmi-lite (1.0.5)
- xml-simple (1.1.5)
+ xml-simple (1.1.9)
+ rexml
xpath (3.2.0)
nokogiri (~> 1.8)
- yajl-ruby (1.4.1)
+ yajl-ruby (1.4.3)
yard (0.9.26)
zeitwerk (2.6.0)
@@ -1476,7 +1488,7 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.3.2)
- acme-client (~> 2.0, >= 2.0.9)
+ acme-client (~> 2.0)
activerecord-explain-analyze (~> 0.1)
acts-as-taggable-on (~> 9.0)
addressable (~> 2.8)
@@ -1501,10 +1513,10 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.0)
- bootsnap (~> 1.12.0)
+ bootsnap (~> 1.13.0)
bootstrap_form (~> 4.2.0)
browser (~> 4.2)
- bullet (~> 6.1.3)
+ bullet (~> 7.0.2)
bundler-audit (~> 0.7.0.1)
capybara (~> 3.35.3)
capybara-screenshot (~> 1.0.22)
@@ -1545,9 +1557,9 @@ DEPENDENCIES
faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank
ffaker (~> 2.10)
- flipper (~> 0.21.0)
- flipper-active_record (~> 0.21.0)
- flipper-active_support_cache_store (~> 0.21.0)
+ flipper (~> 0.25.0)
+ flipper-active_record (~> 0.25.0)
+ flipper-active_support_cache_store (~> 0.25.0)
flowdock (~> 0.7)
fog-aliyun (~> 0.3)
fog-aws (~> 3.14)
@@ -1561,15 +1573,14 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 15.1.0.pre.rc1)
+ gitaly (~> 15.3.0.pre.rc3)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 3.4.3)
+ gitlab-dangerfiles (~> 3.5.0)
gitlab-experiment (~> 0.7.1)
gitlab-fog-azure-rm (~> 1.3.0)
- gitlab-labkit (~> 0.23.0)
- gitlab-license (~> 2.1.0)
- gitlab-license_finder (~> 6.0)
+ gitlab-labkit (~> 0.24.0)
+ gitlab-license (~> 2.2.1)
gitlab-mail_room (~> 0.0.9)
gitlab-markup (~> 1.8.0)
gitlab-net-dns (~> 0.9.1)
@@ -1580,14 +1591,15 @@ DEPENDENCIES
gitlab_omniauth-ldap (~> 2.2.0)
gon (~> 6.4.0)
google-api-client (~> 0.33)
- google-protobuf (~> 3.19.0)
+ google-protobuf (~> 3.21)
gpgme (~> 2.0.19)
grape (~> 1.5.2)
grape-entity (~> 0.10.0)
- grape-path-helpers (~> 1.7.0)
+ grape-path-helpers (~> 1.7.1)
grape_logging (~> 1.8)
graphiql-rails (~> 1.8)
graphlient (~> 0.5.0)
+ graphlyte (~> 1.0.0)
graphql (~> 1.13.12)
graphql-docs (~> 2.1.0)
grpc (~> 1.42.0)
@@ -1615,13 +1627,15 @@ DEPENDENCIES
kas-grpc (~> 0.0.2)
knapsack (~> 1.21.1)
kramdown (~> 2.3.1)
- kubeclient (~> 4.9.2)
- lefthook (~> 1.0.0)
+ kubeclient (~> 4.9.3)
+ lefthook (~> 1.1.0)
letter_opener_web (~> 2.0.0)
+ license_finder (~> 7.0)
licensee (~> 9.14.1)
lockbox (~> 0.6.2)
lograge (~> 0.5)
loofah (~> 2.18.0)
+ lookbook
lru_redux
mail (= 2.7.1)
mail-smtp_pool (~> 0.1.0)!
@@ -1633,11 +1647,11 @@ DEPENDENCIES
multi_json (~> 1.14.1)
net-ldap (~> 0.16.3)
net-ntp
- nokogiri (~> 1.13.6)
+ nokogiri (~> 1.13.0)
oauth2 (~> 2.0)
octokit (~> 4.15)
ohai (~> 16.10)
- oj (~> 3.13.19)
+ oj (~> 3.13.20)
omniauth (~> 1.8)
omniauth-alicloud (~> 1.0.1)
omniauth-atlassian-oauth2 (~> 0.2.0)
@@ -1645,7 +1659,7 @@ DEPENDENCIES
omniauth-authentiq (~> 0.3.3)
omniauth-azure-activedirectory-v2 (~> 1.0)
omniauth-azure-oauth2 (~> 0.0.9)
- omniauth-cas3 (~> 1.1.4)
+ omniauth-cas3 (~> 1.1.4)!
omniauth-dingtalk-oauth2 (~> 1.0)
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.4)
@@ -1662,23 +1676,23 @@ DEPENDENCIES
parallel (~> 1.19)
parslet (~> 1.8)
peek (~> 1.1)
- pg (~> 1.3.0)
+ pg (~> 1.4.0)
pg_query (~> 2.1.0)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.16)
pry-byebug
pry-rails (~> 0.3.9)
- pry-shell (~> 0.5.0)
- puma (~> 5.6.2)
+ pry-shell (~> 0.5.1)
+ puma (~> 5.6.4)
puma_worker_killer (~> 0.3.1)
rack (~> 2.2.4)
rack-attack (~> 6.6.0)
rack-cors (~> 1.1.0)
- rack-oauth2 (~> 1.19.0)
+ rack-oauth2 (~> 1.21.2)
rack-proxy (~> 0.7.2)
rack-timeout (~> 0.6.0)
- rails (~> 6.1.4.7)
+ rails (~> 6.1.6.1)
rails-controller-testing
rails-i18n (~> 7.0)
rainbow (~> 3.0)
@@ -1687,13 +1701,13 @@ DEPENDENCIES
re2 (~> 1.4.0)
recaptcha (~> 4.11)
redis (~> 4.4.0)
- redis-actionpack (~> 5.2.0)
+ redis-actionpack (~> 5.3.0)
redis-namespace (~> 1.8.1)
request_store (~> 1.5)
responders (~> 3.0)
retriable (~> 3.1.2)
rexml (~> 3.2.5)
- rouge (~> 3.29.0)
+ rouge (~> 3.30.0)
rqrcode-rails3 (~> 0.1.7)
rspec-benchmark (~> 0.6.0)
rspec-parameterized
@@ -1730,7 +1744,7 @@ DEPENDENCIES
simplecov-lcov (~> 0.8.0)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
- solargraph (~> 0.44.3)
+ solargraph (~> 0.45.0)
spamcheck (~> 0.1.0)
spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
@@ -1744,12 +1758,11 @@ DEPENDENCIES
terser (= 1.0.2)
test-prof (~> 1.0.7)
test_file_finder (~> 0.1.3)
- thin (~> 1.8.0)
thrift (>= 0.14.0)
timecop (~> 0.9.1)
timfel-krb5-auth (~> 0.8)
toml-rb (~> 2.0)
- truncato (~> 0.7.11)
+ truncato (~> 0.7.12)
typhoeus (~> 1.4.0)
u2f (~> 0.2.1)
undercover (~> 0.4.4)
@@ -1758,14 +1771,14 @@ DEPENDENCIES
valid_email (~> 0.1)
validates_hostname (~> 1.0.11)
version_sorter (~> 2.2.4)
- view_component (~> 2.50.0)
+ view_component (~> 2.61)
vmstat (~> 2.3.0)
warning (~> 1.3.0)
webauthn (~> 2.3)
webmock (~> 3.9.1)
webrick (~> 1.6.1)
wikicloth (= 0.8.1)
- yajl-ruby (~> 1.4.1)
+ yajl-ruby (~> 1.4.3)
BUNDLED WITH
2.3.15
diff --git a/app/assets/images/auth_buttons/jwt_64.png b/app/assets/images/auth_buttons/jwt_64.png
index ca97ae47002..fcfecde23d3 100644
--- a/app/assets/images/auth_buttons/jwt_64.png
+++ b/app/assets/images/auth_buttons/jwt_64.png
Binary files differ
diff --git a/app/assets/images/auth_buttons/salesforce_64.png b/app/assets/images/auth_buttons/salesforce_64.png
index c8a86a0c515..b562e09c20f 100644
--- a/app/assets/images/auth_buttons/salesforce_64.png
+++ b/app/assets/images/auth_buttons/salesforce_64.png
Binary files differ
diff --git a/app/assets/javascripts/access_tokens/components/expires_at_field.vue b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
index 147de529eea..5516fd0daf6 100644
--- a/app/assets/javascripts/access_tokens/components/expires_at_field.vue
+++ b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
@@ -1,7 +1,8 @@
<script>
-import { GlDatepicker, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import { GlDatepicker, GlFormGroup } from '@gitlab/ui';
import { __ } from '~/locale';
+import { getDateInFuture } from '~/lib/utils/datetime_utility';
export default {
name: 'ExpiresAtField',
@@ -10,7 +11,6 @@ export default {
},
components: {
GlDatepicker,
- GlFormInput,
GlFormGroup,
MaxExpirationDateMessage: () =>
import('ee_component/access_tokens/components/max_expiration_date_message.vue'),
@@ -32,20 +32,28 @@ export default {
default: () => null,
},
},
+ computed: {
+ in30Days() {
+ const today = new Date();
+ return getDateInFuture(today, 30);
+ },
+ },
};
</script>
<template>
<gl-form-group :label="$options.i18n.label" :label-for="inputAttrs.id">
- <gl-datepicker :target="null" :min-date="minDate" :max-date="maxDate">
- <gl-form-input
- v-bind="inputAttrs"
- class="datepicker gl-datepicker-input"
- autocomplete="off"
- inputmode="none"
- data-qa-selector="expiry_date_field"
- />
- </gl-datepicker>
+ <gl-datepicker
+ :target="null"
+ :min-date="minDate"
+ :max-date="maxDate"
+ :default-date="in30Days"
+ show-clear-button
+ :input-name="inputAttrs.name"
+ :input-id="inputAttrs.id"
+ :placeholder="inputAttrs.placeholder"
+ data-qa-selector="expiry_date_field"
+ />
<template #description>
<max-expiration-date-message :max-date="maxDate" />
</template>
diff --git a/app/assets/javascripts/access_tokens/components/projects_field.vue b/app/assets/javascripts/access_tokens/components/projects_field.vue
deleted file mode 100644
index 066cea5e90c..00000000000
--- a/app/assets/javascripts/access_tokens/components/projects_field.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script>
-import { GlFormGroup, GlFormRadio, GlFormText } from '@gitlab/ui';
-import ProjectsTokenSelector from './projects_token_selector.vue';
-
-export default {
- name: 'ProjectsField',
- ALL_PROJECTS: 'ALL_PROJECTS',
- SELECTED_PROJECTS: 'SELECTED_PROJECTS',
- components: { GlFormGroup, GlFormRadio, GlFormText, ProjectsTokenSelector },
- props: {
- inputAttrs: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- selectedRadio: !this.inputAttrs.value
- ? this.$options.ALL_PROJECTS
- : this.$options.SELECTED_PROJECTS,
- selectedProjects: [],
- };
- },
- computed: {
- allProjectsRadioSelected() {
- return this.selectedRadio === this.$options.ALL_PROJECTS;
- },
- hiddenInputValue() {
- return this.allProjectsRadioSelected
- ? null
- : this.selectedProjects.map((project) => project.id).join(',');
- },
- initialProjectIds() {
- if (!this.inputAttrs.value) {
- return [];
- }
-
- return this.inputAttrs.value.split(',');
- },
- },
- methods: {
- handleTokenSelectorFocus() {
- this.selectedRadio = this.$options.SELECTED_PROJECTS;
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-form-group :label="__('Projects')" label-class="gl-pb-0!">
- <gl-form-text class="gl-pb-3">{{
- __('Set access permissions for this token.')
- }}</gl-form-text>
- <gl-form-radio v-model="selectedRadio" :value="$options.ALL_PROJECTS">{{
- __('All projects')
- }}</gl-form-radio>
- <gl-form-radio v-model="selectedRadio" :value="$options.SELECTED_PROJECTS">{{
- __('Selected projects')
- }}</gl-form-radio>
- <input :id="inputAttrs.id" type="hidden" :name="inputAttrs.name" :value="hiddenInputValue" />
- <projects-token-selector
- v-model="selectedProjects"
- :initial-project-ids="initialProjectIds"
- @focus="handleTokenSelectorFocus"
- />
- </gl-form-group>
- </div>
-</template>
diff --git a/app/assets/javascripts/access_tokens/components/projects_token_selector.vue b/app/assets/javascripts/access_tokens/components/projects_token_selector.vue
deleted file mode 100644
index 4843c52fcbb..00000000000
--- a/app/assets/javascripts/access_tokens/components/projects_token_selector.vue
+++ /dev/null
@@ -1,156 +0,0 @@
-<script>
-import {
- GlTokenSelector,
- GlAvatar,
- GlAvatarLabeled,
- GlIntersectionObserver,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import produce from 'immer';
-
-import { convertToGraphQLIds, convertNodeIdsFromGraphQLIds } from '~/graphql_shared/utils';
-
-import getProjectsQuery from '../graphql/queries/get_projects.query.graphql';
-
-const DEBOUNCE_DELAY = 250;
-const PROJECTS_PER_PAGE = 20;
-const GRAPHQL_ENTITY_TYPE = 'Project';
-
-export default {
- name: 'ProjectsTokenSelector',
- components: {
- GlTokenSelector,
- GlAvatar,
- GlAvatarLabeled,
- GlIntersectionObserver,
- GlLoadingIcon,
- },
- model: {
- prop: 'selectedProjects',
- },
- props: {
- selectedProjects: {
- type: Array,
- required: true,
- },
- initialProjectIds: {
- type: Array,
- required: true,
- },
- },
- apollo: {
- projects: {
- query: getProjectsQuery,
- debounce: DEBOUNCE_DELAY,
- variables() {
- return {
- search: this.searchQuery,
- after: null,
- first: PROJECTS_PER_PAGE,
- };
- },
- update({ projects }) {
- return {
- list: convertNodeIdsFromGraphQLIds(projects.nodes),
- pageInfo: projects.pageInfo,
- };
- },
- result() {
- this.isLoadingMoreProjects = false;
- this.isSearching = false;
- },
- },
- initialProjects: {
- query: getProjectsQuery,
- variables() {
- return {
- ids: convertToGraphQLIds(GRAPHQL_ENTITY_TYPE, this.initialProjectIds),
- };
- },
- manual: true,
- skip() {
- return !this.initialProjectIds.length;
- },
- result({ data: { projects } }) {
- this.$emit('input', convertNodeIdsFromGraphQLIds(projects.nodes));
- },
- },
- },
- data() {
- return {
- projects: {
- list: [],
- pageInfo: {},
- },
- searchQuery: '',
- isLoadingMoreProjects: false,
- isSearching: false,
- };
- },
- methods: {
- handleSearch(query) {
- this.isSearching = true;
- this.searchQuery = query;
- },
- loadMoreProjects() {
- this.isLoadingMoreProjects = true;
-
- this.$apollo.queries.projects.fetchMore({
- variables: {
- after: this.projects.pageInfo.endCursor,
- first: PROJECTS_PER_PAGE,
- },
- updateQuery(previousResult, { fetchMoreResult: { projects: newProjects } }) {
- const { projects: previousProjects } = previousResult;
-
- return produce(previousResult, (draftData) => {
- draftData.projects.nodes = [...previousProjects.nodes, ...newProjects.nodes];
- draftData.projects.pageInfo = newProjects.pageInfo;
- });
- },
- });
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-relative">
- <gl-token-selector
- :selected-tokens="selectedProjects"
- :dropdown-items="projects.list"
- :loading="isSearching"
- :placeholder="__('Select projects')"
- menu-class="gl-w-full! gl-max-w-full!"
- @input="$emit('input', $event)"
- @focus="$emit('focus', $event)"
- @text-input="handleSearch"
- @keydown.enter.prevent
- >
- <template #token-content="{ token: project }">
- <gl-avatar
- :entity-id="project.id"
- :entity-name="project.name"
- :src="project.avatarUrl"
- :size="16"
- />
- {{ project.nameWithNamespace }}
- </template>
- <template #dropdown-item-content="{ dropdownItem: project }">
- <gl-avatar-labeled
- :entity-id="project.id"
- :entity-name="project.name"
- :size="32"
- :src="project.avatarUrl"
- :label="project.name"
- :sub-label="project.nameWithNamespace"
- />
- </template>
- <template #dropdown-footer>
- <gl-intersection-observer v-if="projects.pageInfo.hasNextPage" @appear="loadMoreProjects">
- <gl-loading-icon v-if="isLoadingMoreProjects" class="gl-mb-3" size="sm" />
- </gl-intersection-observer>
- </template>
- </gl-token-selector>
- </div>
-</template>
diff --git a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
index a5fc70b9ca6..6fb17bf0ee6 100644
--- a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
+++ b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql
@@ -22,7 +22,6 @@ query accessTokensGetProjects(
avatarUrl
}
pageInfo {
- __typename
...PageInfo
}
}
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index a7a03523e7f..9801aa08e28 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -1,6 +1,5 @@
import Vue from 'vue';
-import createFlash from '~/flash';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { parseRailsFormFields } from '~/lib/utils/forms';
import { __, sprintf } from '~/locale';
@@ -99,62 +98,6 @@ export const initNewAccessTokenApp = () => {
});
};
-export const initProjectsField = () => {
- const el = document.querySelector('.js-access-tokens-projects');
-
- if (!el) {
- return null;
- }
-
- const { projects: inputAttrs } = parseRailsFormFields(el);
-
- if (window.gon.features.personalAccessTokensScopedToProjects) {
- return new Promise((resolve) => {
- Promise.all([
- import('./components/projects_field.vue'),
- import('vue-apollo'),
- import('~/lib/graphql'),
- ])
- .then(
- ([
- { default: ProjectsField },
- { default: VueApollo },
- { default: createDefaultClient },
- ]) => {
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
-
- Vue.use(VueApollo);
-
- resolve(
- new Vue({
- el,
- apolloProvider,
- render(h) {
- return h(ProjectsField, {
- props: {
- inputAttrs,
- },
- });
- },
- }),
- );
- },
- )
- .catch(() => {
- createFlash({
- message: __(
- 'An error occurred while loading the access tokens form, please try again.',
- ),
- });
- });
- });
- }
-
- return null;
-};
-
export const initTokensApp = () => {
const el = document.getElementById('js-tokens-app');
diff --git a/app/assets/javascripts/admin/deploy_keys/components/table.vue b/app/assets/javascripts/admin/deploy_keys/components/table.vue
index 46e7ac3cf28..6b140590938 100644
--- a/app/assets/javascripts/admin/deploy_keys/components/table.vue
+++ b/app/assets/javascripts/admin/deploy_keys/components/table.vue
@@ -139,15 +139,15 @@ export default {
title,
fingerprint,
fingerprint_sha256,
- projects_with_write_access,
- created_at,
+ projects_with_write_access: projects,
+ created_at: created,
}) => ({
id,
title,
fingerprint,
fingerprint_sha256,
- projects: projects_with_write_access,
- created: created_at,
+ projects,
+ created,
}),
);
} catch (error) {
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
index ac9304391f9..3cd3f2d92f8 100644
--- a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
@@ -5,7 +5,6 @@ query getIntegrations($projectPath: ID!) {
id
alertManagementIntegrations {
nodes {
- __typename
...IntegrationItem
}
}
diff --git a/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue b/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
index b151e1605da..b2e554bc913 100644
--- a/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
+++ b/app/assets/javascripts/analytics/shared/components/projects_dropdown_filter.vue
@@ -285,7 +285,7 @@ export default {
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
/>
<div>
- <div data-testid="project-name">{{ project.name }}</div>
+ <div data-testid="project-name" data-qa-selector="project_name">{{ project.name }}</div>
<div class="gl-text-gray-500" data-testid="project-full-path">
{{ project.fullPath }}
</div>
diff --git a/app/assets/javascripts/analytics/shared/utils.js b/app/assets/javascripts/analytics/shared/utils.js
index 71b7ca29bad..1887f2affc3 100644
--- a/app/assets/javascripts/analytics/shared/utils.js
+++ b/app/assets/javascripts/analytics/shared/utils.js
@@ -19,24 +19,22 @@ export const toYmd = (date) => dateFormat(date, dateFormats.isoDate);
* @returns {Object}
*/
export const extractFilterQueryParameters = (url = '') => {
- /* eslint-disable camelcase */
const {
- source_branch_name = null,
- target_branch_name = null,
- author_username = null,
- milestone_title = null,
- assignee_username = [],
- label_name = [],
+ source_branch_name: selectedSourceBranch = null,
+ target_branch_name: selectedTargetBranch = null,
+ author_username: selectedAuthor = null,
+ milestone_title: selectedMilestone = null,
+ assignee_username: selectedAssigneeList = [],
+ label_name: selectedLabelList = [],
} = urlQueryToFilter(url);
- /* eslint-enable camelcase */
return {
- selectedSourceBranch: source_branch_name,
- selectedTargetBranch: target_branch_name,
- selectedAuthor: author_username,
- selectedMilestone: milestone_title,
- selectedAssigneeList: assignee_username,
- selectedLabelList: label_name,
+ selectedSourceBranch,
+ selectedTargetBranch,
+ selectedAuthor,
+ selectedMilestone,
+ selectedAssigneeList,
+ selectedLabelList,
};
};
diff --git a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
index b353bcdfd0e..2bde5973600 100644
--- a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
+++ b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql
@@ -1,5 +1,4 @@
fragment Count on UsageTrendsMeasurement {
- __typename
count
recordedAt
}
diff --git a/app/assets/javascripts/api/analytics_api.js b/app/assets/javascripts/api/analytics_api.js
index c7a53288ae4..15457f28eff 100644
--- a/app/assets/javascripts/api/analytics_api.js
+++ b/app/assets/javascripts/api/analytics_api.js
@@ -43,9 +43,6 @@ export const getProjectValueStreamStages = (requestPath, valueStreamId) => {
export const getProjectValueStreamStageData = ({ requestPath, stageId, params }) =>
axios.get(joinPaths(requestPath, 'events', stageId), { params });
-export const getProjectValueStreamMetrics = (requestPath, params) =>
- axios.get(requestPath, { params });
-
/**
* Dedicated project VSA paths
*/
diff --git a/app/assets/javascripts/api/groups_api.js b/app/assets/javascripts/api/groups_api.js
index a563afc6abb..48cf346d0e6 100644
--- a/app/assets/javascripts/api/groups_api.js
+++ b/app/assets/javascripts/api/groups_api.js
@@ -2,6 +2,7 @@ import { DEFAULT_PER_PAGE } from '~/api';
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
+const GROUP_PATH = '/api/:version/groups/:id';
const GROUPS_PATH = '/api/:version/groups.json';
const DESCENDANT_GROUPS_PATH = '/api/:version/groups/:id/descendant_groups';
@@ -30,3 +31,9 @@ export function getDescendentGroups(parentGroupId, query, options, callback = ()
const url = buildApiUrl(DESCENDANT_GROUPS_PATH.replace(':id', parentGroupId));
return axiosGet(url, query, options, callback);
}
+
+export function updateGroup(groupId, data = {}) {
+ const url = buildApiUrl(GROUP_PATH).replace(':id', groupId);
+
+ return axios.put(url, data);
+}
diff --git a/app/assets/javascripts/attention_requests/components/navigation_popover.vue b/app/assets/javascripts/attention_requests/components/navigation_popover.vue
deleted file mode 100644
index 804eda8f321..00000000000
--- a/app/assets/javascripts/attention_requests/components/navigation_popover.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<script>
-import { GlPopover, GlSprintf, GlButton, GlLink, GlIcon } from '@gitlab/ui';
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import { helpPagePath } from '~/helpers/help_page_helper';
-import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
-
-export default {
- components: {
- GlPopover,
- GlSprintf,
- GlButton,
- GlLink,
- GlIcon,
- UserCalloutDismisser,
- },
- inject: {
- message: {
- default: '',
- },
- observerElSelector: {
- default: '',
- },
- observerElToggledClass: {
- default: '',
- },
- featureName: {
- default: '',
- },
- popoverTarget: {
- default: '',
- },
- showAttentionIcon: {
- default: false,
- },
- delay: {
- default: 0,
- },
- popoverCssClass: {
- default: '',
- },
- },
- data() {
- return {
- showPopover: false,
- popoverPlacement: this.popoverPosition(),
- };
- },
- mounted() {
- this.observeEl = document.querySelector(this.observerElSelector);
- this.observer = new MutationObserver(this.callback);
- this.observer.observe(this.observeEl, {
- attributes: true,
- });
- this.callback();
-
- window.addEventListener('resize', () => {
- this.popoverPlacement = this.popoverPosition();
- });
- },
- beforeDestroy() {
- this.observer.disconnect();
- },
- methods: {
- callback() {
- if (this.showPopover) {
- this.$root.$emit('bv::hide::popover');
- }
-
- setTimeout(() => this.toggleShowPopover(), this.delay);
- },
- toggleShowPopover() {
- this.showPopover = this.observeEl.classList.contains(this.observerElToggledClass);
- },
- getPopoverTarget() {
- return document.querySelector(this.popoverTarget);
- },
- popoverPosition() {
- if (bp.isDesktop()) {
- return 'left';
- }
-
- return 'bottom';
- },
- },
- docsPage: helpPagePath('user/project/merge_requests/index.md', {
- anchor: 'request-attention-to-a-merge-request',
- }),
-};
-</script>
-
-<template>
- <user-callout-dismisser :feature-name="featureName">
- <template #default="{ shouldShowCallout, dismiss }">
- <gl-popover
- v-if="shouldShowCallout"
- :show-close-button="false"
- :target="() => getPopoverTarget()"
- :show="showPopover"
- :delay="0"
- triggers="manual"
- :placement="popoverPlacement"
- boundary="window"
- no-fade
- :css-classes="[popoverCssClass]"
- >
- <p v-for="(m, index) in message" :key="index" class="gl-mb-5">
- <gl-sprintf :message="m">
- <template #strong="{ content }">
- <strong><gl-icon v-if="showAttentionIcon" name="attention" /> {{ content }}</strong>
- </template>
- </gl-sprintf>
- </p>
- <div class="gl-display-flex gl-align-items-center">
- <gl-button size="small" variant="confirm" class="gl-mr-5" @click.prevent.stop="dismiss">
- {{ __('Got it!') }}
- </gl-button>
- <gl-link :href="$options.docsPage" target="_blank">{{ __('Learn more') }}</gl-link>
- </div>
- </gl-popover>
- </template>
- </user-callout-dismisser>
-</template>
diff --git a/app/assets/javascripts/attention_requests/index.js b/app/assets/javascripts/attention_requests/index.js
deleted file mode 100644
index 2a142ab46e5..00000000000
--- a/app/assets/javascripts/attention_requests/index.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import { __ } from '~/locale';
-import createDefaultClient from '~/lib/graphql';
-import NavigationPopover from './components/navigation_popover.vue';
-
-Vue.use(VueApollo);
-
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
-});
-
-export const initTopNavPopover = () => {
- const el = document.getElementById('js-need-attention-nav-onboarding');
-
- if (!el) return;
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- apolloProvider,
- provide: {
- observerElSelector: '.user-counter.dropdown',
- observerElToggledClass: 'show',
- message: [
- __(
- '%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer.',
- ),
- ],
- featureName: 'attention_requests_top_nav',
- popoverTarget: '#js-need-attention-nav',
- },
- render(h) {
- return h(NavigationPopover);
- },
- });
-};
-
-export const initSideNavPopover = () => {
- const el = document.getElementById('js-need-attention-sidebar-onboarding');
-
- if (!el) return;
-
- // eslint-disable-next-line no-new
- new Vue({
- el,
- apolloProvider,
- provide: {
- observerElSelector: '.js-right-sidebar',
- observerElToggledClass: 'right-sidebar-expanded',
- message: [
- __(
- 'To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request.',
- ),
- __(
- 'Some actions remove attention requests, like a reviewer approving or anyone merging the merge request.',
- ),
- ],
- featureName: 'attention_requests_side_nav',
- popoverTarget: '.js-attention-request-toggle',
- showAttentionIcon: true,
- delay: 500,
- popoverCssClass: 'attention-request-sidebar-popover',
- },
- render(h) {
- return h(NavigationPopover);
- },
- });
-};
-
-export default () => {
- initTopNavPopover();
-};
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 300a81caa5c..e5408d0734a 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -116,11 +116,7 @@ export default {
class="referenced-commands draft-note-commands"
></div>
- <p
- v-if="!glFeatures.mrReviewSubmitComment"
- class="draft-note-actions d-flex"
- data-qa-selector="draft_note_content"
- >
+ <p v-if="!glFeatures.mrReviewSubmitComment" class="draft-note-actions d-flex">
<publish-button
:show-count="true"
:should-publish="false"
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 3cd1a2525e9..111b670596b 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -2,10 +2,20 @@
import { mapActions, mapGetters } from 'vuex';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { REVIEW_BAR_VISIBLE_CLASS_NAME } from '../constants';
+import { PREVENT_LEAVING_PENDING_REVIEW } from '../i18n';
import PreviewDropdown from './preview_dropdown.vue';
import PublishButton from './publish_button.vue';
import SubmitDropdown from './submit_dropdown.vue';
+function closeInterrupt(event) {
+ event.preventDefault();
+
+ // This is the correct way to write backwards-compatible beforeunload listeners
+ // https://developer.chrome.com/blog/page-lifecycle-api/#the-beforeunload-event
+ /* eslint-disable-next-line no-return-assign, no-param-reassign */
+ return (event.returnValue = PREVENT_LEAVING_PENDING_REVIEW);
+}
+
export default {
components: {
PreviewDropdown,
@@ -25,8 +35,26 @@ export default {
},
mounted() {
document.body.classList.add(REVIEW_BAR_VISIBLE_CLASS_NAME);
+ /*
+ * This stuff is a lot trickier than it looks.
+ *
+ * Mandatory reading: https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
+ * Some notable sentences:
+ * - "[...] browsers may not display prompts created in beforeunload event handlers unless the
+ * page has been interacted with, or may even not display them at all."
+ * - "Especially on mobile, the beforeunload event is not reliably fired."
+ * - "The beforeunload event is not compatible with the back/forward cache (bfcache) [...]
+ * It is recommended that developers listen for beforeunload only in this scenario, and only
+ * when they actually have unsaved changes, so as to minimize the effect on performance."
+ *
+ * Please ensure that this is really not working before you modify it, because there are a LOT
+ * of scenarios where browser behavior will make it _seem_ like it's not working, but it actually
+ * is under the right combination of contexts.
+ */
+ window.addEventListener('beforeunload', closeInterrupt, { capture: true });
},
beforeDestroy() {
+ window.removeEventListener('beforeunload', closeInterrupt, { capture: true });
document.body.classList.remove(REVIEW_BAR_VISIBLE_CLASS_NAME);
},
methods: {
diff --git a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
index b070848cae9..54b9953270b 100644
--- a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
@@ -1,8 +1,11 @@
<script>
-import { GlDropdown, GlButton, GlIcon, GlForm, GlFormGroup } from '@gitlab/ui';
+import $ from 'jquery';
+import { GlDropdown, GlButton, GlIcon, GlForm, GlFormGroup, GlLink } from '@gitlab/ui';
import { mapGetters, mapActions } from 'vuex';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
+import Autosave from '~/autosave';
+import { helpPagePath } from '~/helpers/help_page_helper';
export default {
components: {
@@ -11,6 +14,7 @@ export default {
GlIcon,
GlForm,
GlFormGroup,
+ GlLink,
MarkdownField,
},
data() {
@@ -23,6 +27,11 @@ export default {
...mapGetters(['getNotesData', 'getNoteableData', 'noteableType', 'getCurrentUserLastNote']),
},
mounted() {
+ this.autosave = new Autosave(
+ $(this.$refs.textarea),
+ `submit_review_dropdown/${this.getNoteableData.id}`,
+ );
+
// We override the Bootstrap Vue click outside behaviour
// to allow for clicking in the autocomplete dropdowns
// without this override the submit dropdown will close
@@ -47,6 +56,8 @@ export default {
await this.publishReview(noteData);
+ this.autosave.reset();
+
if (window.mrTabs && this.note) {
window.location.hash = `note_${this.getCurrentUserLastNote.id}`;
window.mrTabs.tabShown('show');
@@ -60,6 +71,9 @@ export default {
},
},
restrictedToolbarItems: ['full-screen'],
+ helpPagePath: helpPagePath('user/project/merge_requests/reviews/index.html', {
+ anchor: 'submit-a-review',
+ }),
};
</script>
@@ -68,19 +82,27 @@ export default {
ref="dropdown"
right
class="submit-review-dropdown"
+ data-qa-selector="submit_review_dropdown"
variant="info"
- category="secondary"
+ category="primary"
>
<template #button-content>
{{ __('Finish review') }}
<gl-icon class="dropdown-chevron" name="chevron-up" />
</template>
<gl-form data-testid="submit-gl-form" @submit.prevent="submitReview">
- <gl-form-group
- :label="__('Summary comment (optional)')"
- label-for="review-note-body"
- label-class="gl-mb-2"
- >
+ <gl-form-group label-for="review-note-body" label-class="gl-mb-2">
+ <template #label>
+ {{ __('Summary comment (optional)') }}
+ <gl-link
+ :href="$options.helpPagePath"
+ :aria-label="__('More information')"
+ target="_blank"
+ class="gl-ml-2"
+ >
+ <gl-icon name="question-o" />
+ </gl-link>
+ </template>
<div class="common-note-form gfm-form">
<div
class="comment-warning-wrapper gl-border-solid gl-border-1 gl-rounded-base gl-border-gray-100"
@@ -117,13 +139,14 @@ export default {
</div>
</div>
</gl-form-group>
- <div class="gl-display-flex gl-justify-content-end gl-mt-5">
+ <div class="gl-display-flex gl-justify-content-start gl-mt-5">
<gl-button
:loading="isSubmitting"
variant="confirm"
type="submit"
class="js-no-auto-disable"
data-testid="submit-review-button"
+ data-qa-selector="submit_review_button"
>
{{ __('Submit review') }}
</gl-button>
diff --git a/app/assets/javascripts/batch_comments/i18n.js b/app/assets/javascripts/batch_comments/i18n.js
new file mode 100644
index 00000000000..6cdbf00f9ca
--- /dev/null
+++ b/app/assets/javascripts/batch_comments/i18n.js
@@ -0,0 +1,3 @@
+import { __ } from '~/locale';
+
+export const PREVENT_LEAVING_PENDING_REVIEW = __('There are unsubmitted review comments.');
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 a44b9827fe9..863d2a99972 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,9 +1,12 @@
import { isEmpty } from 'lodash';
+
import createFlash from '~/flash';
import { scrollToElement } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
+
import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants';
import service from '../../../services/drafts_service';
+
import * as types from './mutation_types';
export const saveDraft = ({ dispatch }, draft) =>
@@ -15,6 +18,7 @@ export const addDraftToDiscussion = ({ commit }, { endpoint, data }) =>
.then((res) => res.data)
.then((res) => {
commit(types.ADD_NEW_DRAFT, res);
+
return res;
})
.catch(() => {
@@ -29,6 +33,7 @@ export const createNewDraft = ({ commit }, { endpoint, data }) =>
.then((res) => res.data)
.then((res) => {
commit(types.ADD_NEW_DRAFT, res);
+
return res;
})
.catch(() => {
diff --git a/app/assets/javascripts/behaviors/components/json_table.vue b/app/assets/javascripts/behaviors/components/json_table.vue
new file mode 100644
index 00000000000..bb38d80c1b5
--- /dev/null
+++ b/app/assets/javascripts/behaviors/components/json_table.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlTable, GlFormInput } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlTable,
+ GlFormInput,
+ },
+ props: {
+ fields: {
+ type: Array,
+ required: true,
+ },
+ items: {
+ type: Array,
+ required: true,
+ },
+ hasFilter: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ caption: {
+ type: String,
+ required: false,
+ default: __('Generated with JSON data'),
+ },
+ },
+ data() {
+ return {
+ filterInput: '',
+ };
+ },
+ computed: {
+ cleanedFields() {
+ return this.fields.map((field) => {
+ if (typeof field === 'string') {
+ return field;
+ }
+ return {
+ key: field.key,
+ label: field.label,
+ sortable: field.sortable || false,
+ };
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-inline-block">
+ <gl-form-input
+ v-if="hasFilter"
+ v-model="filterInput"
+ :placeholder="__('Type to search')"
+ class="gl-mb-2!"
+ />
+ <gl-table
+ :fields="cleanedFields"
+ :items="items"
+ :filter="filterInput"
+ show-empty
+ class="gl-mt-0!"
+ >
+ <template v-if="caption" #table-caption>
+ <small>{{ caption }}</small>
+ </template>
+ </gl-table>
+ </div>
+</template>
diff --git a/app/assets/javascripts/behaviors/markdown/marks/strike.js b/app/assets/javascripts/behaviors/markdown/marks/strike.js
index 967c0a120cd..afab266b645 100644
--- a/app/assets/javascripts/behaviors/markdown/marks/strike.js
+++ b/app/assets/javascripts/behaviors/markdown/marks/strike.js
@@ -2,16 +2,35 @@
export default () => ({
name: 'strike',
schema: {
- parseDOM: [
- {
- tag: 'del',
+ attrs: {
+ strike: {
+ default: false,
+ },
+ inapplicable: {
+ default: false,
},
+ },
+ parseDOM: [
+ { tag: 'li.inapplicable > s', attrs: { inapplicable: true } },
+ { tag: 'li.inapplicable > p:first-of-type > s', attrs: { inapplicable: true } },
+ { tag: 's', attrs: { strike: true } },
+ { tag: 'del' },
],
toDOM: () => ['s', 0],
},
toMarkdown: {
- open: '~~',
- close: '~~',
+ open(_, mark) {
+ if (mark.attrs.strike) {
+ return '<s>';
+ }
+ return mark.attrs.inapplicable ? '' : '~~';
+ },
+ close(_, mark) {
+ if (mark.attrs.strike) {
+ return '</s>';
+ }
+ return mark.attrs.inapplicable ? '' : '~~';
+ },
mixable: true,
expelEnclosingWhitespace: true,
},
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
index 0ff59779e7d..b862d111de7 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/code_block.js
@@ -37,7 +37,7 @@ export default () => ({
attrs: { lang: 'math' },
},
// Matches HTML generated by Banzai::Filter::MermaidFilter,
- // after being transformed by app/assets/javascripts/behaviors/markdown/render_mermaid.js
+ // after being transformed by app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js
{
tag: 'svg.mermaid',
preserveWhitespace: 'full',
diff --git a/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
index 10ffce9b1b8..095634340c1 100644
--- a/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
+++ b/app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
@@ -5,8 +5,8 @@ export default () => ({
name: 'task_list_item',
schema: {
attrs: {
- done: {
- default: false,
+ state: {
+ default: null,
},
},
defining: true,
@@ -18,21 +18,53 @@ export default () => ({
tag: 'li.task-list-item',
getAttrs: (el) => {
const checkbox = el.querySelector('input[type=checkbox].task-list-item-checkbox');
- return { done: checkbox && checkbox.checked };
+ if (checkbox?.matches('[data-inapplicable]')) {
+ return { state: 'inapplicable' };
+ } else if (checkbox?.checked) {
+ return { state: 'done' };
+ }
+
+ return {};
},
},
],
toDOM(node) {
return [
'li',
- { class: 'task-list-item' },
- ['input', { type: 'checkbox', class: 'task-list-item-checkbox', checked: node.attrs.done }],
+ {
+ class: () => {
+ if (node.attrs.state === 'inapplicable') {
+ return 'task-list-item inapplicable';
+ }
+
+ return 'task-list-item';
+ },
+ },
+ [
+ 'input',
+ {
+ type: 'checkbox',
+ class: 'task-list-item-checkbox',
+ checked: node.attrs.state === 'done',
+ 'data-inapplicable': node.attrs.state === 'inapplicable',
+ },
+ ],
['div', { class: 'todo-content' }, 0],
];
},
},
toMarkdown(state, node) {
- state.write(`[${node.attrs.done ? 'x' : ' '}] `);
+ switch (node.attrs.state) {
+ case 'done':
+ state.write('[x] ');
+ break;
+ case 'inapplicable':
+ state.write('[~] ');
+ break;
+ default:
+ state.write('[ ] ');
+ break;
+ }
state.renderContent(node);
},
});
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index c9ae3706383..ee5c0fe5ef3 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -5,6 +5,7 @@ import { renderKroki } from './render_kroki';
import renderMath from './render_math';
import renderSandboxedMermaid from './render_sandboxed_mermaid';
import renderMetrics from './render_metrics';
+import { renderJSONTable } from './render_json_table';
// Render GitLab flavoured Markdown
//
@@ -15,6 +16,9 @@ $.fn.renderGFM = function renderGFM() {
renderKroki(this.find('.js-render-kroki[hidden]').get());
renderMath(this.find('.js-render-math'));
renderSandboxedMermaid(this.find('.js-render-mermaid'));
+ renderJSONTable(
+ Array.from(this.find('[lang="json"][data-lang-params="table"]').get()).map((e) => e.parentNode),
+ );
highlightCurrentUser(this.find('.gfm-project_member').get());
diff --git a/app/assets/javascripts/behaviors/markdown/render_json_table.js b/app/assets/javascripts/behaviors/markdown/render_json_table.js
new file mode 100644
index 00000000000..4d9ac1d266b
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/render_json_table.js
@@ -0,0 +1,70 @@
+import { memoize } from 'lodash';
+import Vue from 'vue';
+import { __ } from '~/locale';
+import { createAlert } from '~/flash';
+
+// Async import component since we might not need it...
+const JSONTable = memoize(() =>
+ import(/* webpackChunkName: 'gfm_json_table' */ '../components/json_table.vue'),
+);
+
+const mountParseError = (element) => {
+ // Let the error container be a sibling to the element.
+ // Otherwise, dismissing the alert causes the copy button to be misplaced.
+ const container = document.createElement('div');
+ element.insertAdjacentElement('beforebegin', container);
+
+ // We need to create a child element with a known selector for `createAlert`
+ const el = document.createElement('div');
+ el.classList.add('js-json-table-error');
+
+ container.insertAdjacentElement('afterbegin', el);
+
+ return createAlert({
+ message: __('Unable to parse JSON'),
+ variant: 'warning',
+ parent: container,
+ containerSelector: '.js-json-table-error',
+ });
+};
+
+const mountJSONTableVueComponent = (userData, element) => {
+ const { fields = [], items = [], filter, caption } = userData;
+
+ const container = document.createElement('div');
+ element.innerHTML = '';
+ element.appendChild(container);
+
+ return new Vue({
+ el: container,
+ render(h) {
+ return h(JSONTable, {
+ props: {
+ fields,
+ items,
+ hasFilter: filter,
+ caption,
+ },
+ });
+ },
+ });
+};
+
+const renderTable = (element) => {
+ // Avoid rendering multiple times
+ if (!element || element.classList.contains('js-json-table')) {
+ return;
+ }
+
+ element.classList.add('js-json-table');
+
+ try {
+ mountJSONTableVueComponent(JSON.parse(element.textContent), element);
+ } catch (e) {
+ mountParseError(element);
+ }
+};
+
+export const renderJSONTable = (elements) => {
+ elements.forEach(renderTable);
+};
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
deleted file mode 100644
index 2df0f7387fb..00000000000
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ /dev/null
@@ -1,231 +0,0 @@
-import $ from 'jquery';
-import { once, countBy } from 'lodash';
-import createFlash from '~/flash';
-import { darkModeEnabled } from '~/lib/utils/color_utils';
-import { __, sprintf } from '~/locale';
-import { unrestrictedPages } from './constants';
-
-// Renders diagrams and flowcharts from text using Mermaid in any element with the
-// `js-render-mermaid` class.
-//
-// Example markup:
-//
-// <pre class="js-render-mermaid">
-// graph TD;
-// A-- > B;
-// A-- > C;
-// B-- > D;
-// C-- > D;
-// </pre>
-//
-
-// This is an arbitrary number; Can be iterated upon when suitable.
-const MAX_CHAR_LIMIT = 2000;
-// Max # of mermaid blocks that can be rendered in a page.
-const MAX_MERMAID_BLOCK_LIMIT = 50;
-// Max # of `&` allowed in Chaining of links syntax
-const MAX_CHAINING_OF_LINKS_LIMIT = 30;
-// Keep a map of mermaid blocks we've already rendered.
-const elsProcessingMap = new WeakMap();
-let renderedMermaidBlocks = 0;
-
-let mermaidModule = {};
-
-export function initMermaid(mermaid) {
- let theme = 'neutral';
-
- if (darkModeEnabled()) {
- theme = 'dark';
- }
-
- mermaid.initialize({
- // mermaid core options
- mermaid: {
- startOnLoad: false,
- },
- // mermaidAPI options
- theme,
- flowchart: {
- useMaxWidth: true,
- htmlLabels: true,
- },
- secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'htmlLabels'],
- securityLevel: 'strict',
- });
-
- return mermaid;
-}
-
-function importMermaidModule() {
- return import(/* webpackChunkName: 'mermaid' */ 'mermaid')
- .then(({ default: mermaid }) => {
- mermaidModule = initMermaid(mermaid);
- })
- .catch((err) => {
- createFlash({
- message: sprintf(__("Can't load mermaid module: %{err}"), { err }),
- });
- // eslint-disable-next-line no-console
- console.error(err);
- });
-}
-
-function shouldLazyLoadMermaidBlock(source) {
- /**
- * If source contains `&`, which means that it might
- * contain Chaining of links a new syntax in Mermaid.
- */
- if (countBy(source)['&'] > MAX_CHAINING_OF_LINKS_LIMIT) {
- return true;
- }
-
- return false;
-}
-
-function fixElementSource(el) {
- // Mermaid doesn't like `<br />` tags, so collapse all like tags into `<br>`, which is parsed correctly.
- const source = el.textContent.replace(/<br\s*\/>/g, '<br>');
-
- // Remove any extra spans added by the backend syntax highlighting.
- Object.assign(el, { textContent: source });
-
- return { source };
-}
-
-function renderMermaidEl(el) {
- mermaidModule.init(undefined, el, (id) => {
- const source = el.textContent;
- const svg = document.getElementById(id);
-
- // As of https://github.com/knsv/mermaid/commit/57b780a0d,
- // Mermaid will make two init callbacks:one to initialize the
- // flow charts, and another to initialize the Gannt charts.
- // Guard against an error caused by double initialization.
- if (svg.classList.contains('mermaid')) {
- return;
- }
-
- svg.classList.add('mermaid');
-
- // pre > code > svg
- svg.closest('pre').replaceWith(svg);
-
- // We need to add the original source into the DOM to allow Copy-as-GFM
- // to access it.
- const sourceEl = document.createElement('text');
- sourceEl.classList.add('source');
- sourceEl.setAttribute('display', 'none');
- sourceEl.textContent = source;
-
- svg.appendChild(sourceEl);
- });
-}
-
-function renderMermaids($els) {
- if (!$els.length) return;
-
- const pageName = document.querySelector('body').dataset.page;
-
- // A diagram may have been truncated in search results which will cause errors, so abort the render.
- if (pageName === 'search:show') return;
-
- importMermaidModule()
- .then(() => {
- let renderedChars = 0;
-
- $els.each((i, el) => {
- // Skipping all the elements which we've already queued in requestIdleCallback
- if (elsProcessingMap.has(el)) {
- return;
- }
-
- const { source } = fixElementSource(el);
- /**
- * Restrict the rendering to a certain amount of character
- * and mermaid blocks to prevent mermaidjs from hanging
- * up the entire thread and causing a DoS.
- */
- if (
- !unrestrictedPages.includes(pageName) &&
- ((source && source.length > MAX_CHAR_LIMIT) ||
- renderedChars > MAX_CHAR_LIMIT ||
- renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT ||
- shouldLazyLoadMermaidBlock(source))
- ) {
- const html = `
- <div class="alert gl-alert gl-alert-warning alert-dismissible lazy-render-mermaid-container js-lazy-render-mermaid-container fade show" role="alert">
- <div>
- <div class="display-flex">
- <div>${__(
- 'Warning: Displaying this diagram might cause performance issues on this page.',
- )}</div>
- <div class="gl-alert-actions">
- <button class="js-lazy-render-mermaid btn gl-alert-action btn-confirm btn-md gl-button">Display</button>
- </div>
- </div>
- <button type="button" class="close" data-dismiss="alert" aria-label="Close">
- <span aria-hidden="true">&times;</span>
- </button>
- </div>
- </div>
- `;
-
- const $parent = $(el).parent();
-
- if (!$parent.hasClass('lazy-alert-shown')) {
- $parent.after(html);
- $parent.addClass('lazy-alert-shown');
- }
-
- return;
- }
-
- renderedChars += source.length;
- renderedMermaidBlocks += 1;
-
- const requestId = window.requestIdleCallback(() => {
- renderMermaidEl(el);
- });
-
- elsProcessingMap.set(el, requestId);
- });
- })
- .catch((err) => {
- createFlash({
- message: sprintf(__('Encountered an error while rendering: %{err}'), { err }),
- });
- // eslint-disable-next-line no-console
- console.error(err);
- });
-}
-
-const hookLazyRenderMermaidEvent = once(() => {
- $(document.body).on('click', '.js-lazy-render-mermaid', function eventHandler() {
- const parent = $(this).closest('.js-lazy-render-mermaid-container');
- const pre = parent.prev();
-
- const el = pre.find('.js-render-mermaid');
-
- parent.remove();
-
- renderMermaidEl(el);
- });
-});
-
-export default function renderMermaid($els) {
- if (!$els.length) return;
-
- const visibleMermaids = $els.filter(function filter() {
- return $(this).closest('details').length === 0 && $(this).is(':visible');
- });
-
- renderMermaids(visibleMermaids);
-
- $els.closest('details').one('toggle', function toggle() {
- if (this.open) {
- renderMermaids($(this).find('.js-render-mermaid'));
- }
- });
-
- hookLazyRenderMermaidEvent();
-}
diff --git a/app/assets/javascripts/blob/blob_links_tracking.js b/app/assets/javascripts/blob/blob_links_tracking.js
new file mode 100644
index 00000000000..9a49aa8b0fc
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_links_tracking.js
@@ -0,0 +1,25 @@
+import Tracking from '~/tracking';
+
+function addBlobLinksTracking(containerSelector, eventsToTrack) {
+ const containerEl = document.querySelector(containerSelector);
+
+ if (!containerEl) {
+ return;
+ }
+
+ const eventName = 'click_link';
+ const label = 'file_line_action';
+
+ containerEl.addEventListener('click', (e) => {
+ eventsToTrack.forEach((event) => {
+ if (e.target.matches(event.selector)) {
+ Tracking.event(undefined, eventName, {
+ label,
+ property: event.property,
+ });
+ }
+ });
+ });
+}
+
+export default addBlobLinksTracking;
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index 9fca9860282..8062460f052 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -38,10 +38,8 @@ export function formatIssue(issue) {
export function formatListIssues(listIssues) {
const boardItems = {};
- let listItemsCount;
const listData = listIssues.nodes.reduce((map, list) => {
- listItemsCount = list.issuesCount;
let sortedIssues = list.issues.edges.map((issueNode) => ({
...issueNode.node,
}));
@@ -67,7 +65,7 @@ export function formatListIssues(listIssues) {
};
}, {});
- return { listData, boardItems, listItemsCount };
+ return { listData, boardItems };
}
export function formatListsPageInfo(lists) {
diff --git a/app/assets/javascripts/boards/components/board_add_new_column_form.vue b/app/assets/javascripts/boards/components/board_add_new_column_form.vue
index 10c7a3db2d3..c4a2f83ab50 100644
--- a/app/assets/javascripts/boards/components/board_add_new_column_form.vue
+++ b/app/assets/javascripts/boards/components/board_add_new_column_form.vue
@@ -19,6 +19,7 @@ export default {
scope: __('Scope'),
scopeDescription: __('Issues must match this scope to appear in this list.'),
selected: __('Selected'),
+ requiredFieldFeedback: __('This field is required.'),
},
components: {
GlButton,
@@ -55,12 +56,21 @@ export default {
data() {
return {
searchValue: '',
+ selectedIdValid: true,
};
},
+ computed: {
+ toggleClassList() {
+ return `gl-max-w-full gl-display-flex gl-align-items-center gl-text-trunate ${
+ this.selectedIdValid ? '' : 'gl-inset-border-1-red-400!'
+ }`;
+ },
+ },
watch: {
selectedId(val) {
if (val) {
this.$refs.dropdown.hide(true);
+ this.selectedIdValid = true;
}
},
},
@@ -74,6 +84,13 @@ export default {
this.$emit('filter-items', '');
this.$emit('hide');
},
+ onSubmit() {
+ if (!this.selectedId) {
+ this.selectedIdValid = false;
+ } else {
+ this.$emit('add-list');
+ }
+ },
},
};
</script>
@@ -103,11 +120,16 @@ export default {
<slot name="select-list-type"></slot>
- <gl-form-group class="gl-px-5 lg-mb-3 gl-max-w-full" :label="searchLabel">
+ <gl-form-group
+ class="gl-px-5 lg-mb-3 gl-max-w-full"
+ :label="searchLabel"
+ :state="selectedIdValid"
+ :invalid-feedback="$options.i18n.requiredFieldFeedback"
+ >
<gl-dropdown
ref="dropdown"
class="gl-mb-3 gl-max-w-full"
- toggle-class="gl-max-w-full gl-display-flex gl-align-items-center gl-text-trunate"
+ :toggle-class="toggleClassList"
boundary="viewport"
@shown="setFocus"
@hide="onHide"
@@ -147,10 +169,9 @@ export default {
<div class="gl-display-flex gl-mb-4">
<gl-button
data-testid="addNewColumnButton"
- :disabled="!selectedId"
variant="confirm"
class="gl-mr-3 gl-ml-4"
- @click="$emit('add-list')"
+ @click="onSubmit"
>{{ $options.i18n.add }}</gl-button
>
<gl-button data-testid="cancelAddNewColumn" @click="setAddColumnFormVisibility(false)">{{
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index a632f5ae0ed..8dc521317cd 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -147,6 +147,9 @@ export default {
showReferencePath() {
return !this.isProjectBoard && this.itemReferencePath;
},
+ avatarSize() {
+ return { default: 16, lg: 24 };
+ },
},
methods: {
...mapActions(['performSearch', 'setError']),
@@ -359,16 +362,17 @@ export default {
</span>
</span>
</div>
- <div class="board-card-assignee gl-display-flex">
+ <div class="board-card-assignee gl-display-flex gl-gap-3">
<user-avatar-link
v-for="assignee in cappedAssignees"
:key="assignee.id"
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
:img-src="avatarUrl(assignee)"
- :img-size="24"
+ :img-size="avatarSize"
class="js-no-trigger"
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_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index 0320b4d925e..d25169b5b9d 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -138,9 +138,8 @@ export default {
<template>
<mounting-portal mount-to="#js-right-sidebar-portal" name="board-content-sidebar" append>
<gl-drawer
- v-if="showSidebar"
v-bind="$attrs"
- :open="isSidebarOpen"
+ :open="showSidebar"
class="boards-sidebar gl-absolute"
variant="sidebar"
@close="handleClose"
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index a65269de743..e3012f5b36d 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -117,7 +117,7 @@ export default {
return 'issues';
},
itemsTooltipLabel() {
- return n__(`%d issue`, `%d issues`, this.boardLists?.issuesCount);
+ return n__(`%d issue`, `%d issues`, this.boardList?.issuesCount);
},
chevronTooltip() {
return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index c559e4cdbd3..e93edad675c 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -58,7 +58,7 @@ export default {
return ListTypeTitles[ListType.label];
},
showSidebar() {
- return this.sidebarType === LIST;
+ return this.sidebarType === LIST && this.isSidebarOpen;
},
},
created() {
@@ -87,10 +87,9 @@ export default {
<template>
<mounting-portal mount-to="#js-right-sidebar-portal" name="board-settings-sidebar" append>
<gl-drawer
- v-if="showSidebar"
v-bind="$attrs"
class="js-board-settings-sidebar gl-absolute"
- :open="isSidebarOpen"
+ :open="showSidebar"
variant="sidebar"
@close="unsetActiveId"
>
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql b/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
index 4dc245660a4..01fab571733 100644
--- a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
+++ b/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
@@ -1,9 +1,7 @@
query BoardBlockingIssues($id: IssueID!) {
issuable: issue(id: $id) {
- __typename
id
blockingIssuables: blockedByIssues {
- __typename
nodes {
id
iid
diff --git a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
index aec674eb006..252e8c1ab06 100644
--- a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
@@ -2,10 +2,8 @@
query GroupBoardMembers($fullPath: ID!, $search: String) {
workspace: group(fullPath: $fullPath) {
- __typename
id
assignees: groupMembers(search: $search, relations: [DIRECT, DESCENDANTS, INHERITED]) {
- __typename
nodes {
id
user {
diff --git a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
index bf5329c4a8d..ae6394f9a2f 100644
--- a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
+++ b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
@@ -17,7 +17,6 @@ query BoardListsEE(
lists(id: $id, issueFilters: $filters) {
nodes {
id
- issuesCount
listType
issues(first: $first, filters: $filters, after: $after) {
edges {
@@ -41,7 +40,6 @@ query BoardListsEE(
lists(id: $id, issueFilters: $filters) {
nodes {
id
- issuesCount
listType
issues(first: $first, filters: $filters, after: $after) {
edges {
diff --git a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
index 45bec5e574b..5279680b03c 100644
--- a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
@@ -2,10 +2,8 @@
query ProjectBoardMembers($fullPath: ID!, $search: String) {
workspace: project(fullPath: $fullPath) {
- __typename
id
assignees: projectMembers(search: $search) {
- __typename
nodes {
id
user {
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 04e7d3643e7..26a98a645b3 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -11,7 +11,7 @@ const updateListItemsCount = ({ state, listId, value }) => {
if (state.issuableType === issuableTypes.epic) {
Vue.set(state.boardLists, listId, { ...list, epicsCount: list.epicsCount + value });
} else {
- Vue.set(state.boardLists, listId, { ...list, issuesCount: list.issuesCount + value });
+ Vue.set(state.boardLists, listId, { ...list });
}
};
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 5e5d799d627..fea4b56153f 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
@@ -79,7 +79,7 @@ export default {
:title="$options.i18n.copyTrigger"
css-class="gl-border-none gl-py-0 gl-px-2"
/>
- <div class="label-container">
+ <div class="gl-display-inline-block gl-ml-3">
<gl-badge v-if="!item.canAccessProject" variant="danger">
<span
v-gl-tooltip.viewport
@@ -95,7 +95,7 @@ export default {
:title="item.description"
truncate-target="child"
placement="top"
- class="trigger-description gl-display-flex"
+ class="gl-max-w-15 gl-display-flex"
>
<div class="gl-flex-grow-1 gl-text-truncate">{{ item.description }}</div>
</tooltip-on-truncate>
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
new file mode 100644
index 00000000000..83bad9eb518
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/components/ci_admin_variables.vue
@@ -0,0 +1,101 @@
+<script>
+import createFlash from '~/flash';
+import getAdminVariables from '../graphql/queries/variables.query.graphql';
+import {
+ ADD_MUTATION_ACTION,
+ DELETE_MUTATION_ACTION,
+ UPDATE_MUTATION_ACTION,
+ genericMutationErrorText,
+ variableFetchErrorText,
+} from '../constants';
+import addAdminVariable from '../graphql/mutations/admin_add_variable.mutation.graphql';
+import deleteAdminVariable from '../graphql/mutations/admin_delete_variable.mutation.graphql';
+import updateAdminVariable from '../graphql/mutations/admin_update_variable.mutation.graphql';
+import ciVariableSettings from './ci_variable_settings.vue';
+
+export default {
+ components: {
+ ciVariableSettings,
+ },
+ inject: ['endpoint'],
+ data() {
+ return {
+ adminVariables: [],
+ isInitialLoading: true,
+ };
+ },
+ apollo: {
+ adminVariables: {
+ query: getAdminVariables,
+ update(data) {
+ return data?.ciVariables?.nodes || [];
+ },
+ error() {
+ createFlash({ message: variableFetchErrorText });
+ },
+ watchLoading(flag) {
+ if (!flag) {
+ this.isInitialLoading = false;
+ }
+ },
+ },
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.adminVariables.loading && this.isInitialLoading;
+ },
+ },
+ methods: {
+ addVariable(variable) {
+ this.variableMutation(ADD_MUTATION_ACTION, variable);
+ },
+ deleteVariable(variable) {
+ this.variableMutation(DELETE_MUTATION_ACTION, variable);
+ },
+ updateVariable(variable) {
+ this.variableMutation(UPDATE_MUTATION_ACTION, variable);
+ },
+ async variableMutation(mutationAction, variable) {
+ try {
+ const currentMutation = this.$options.mutationData[mutationAction];
+ const { data } = await this.$apollo.mutate({
+ mutation: currentMutation.action,
+ variables: {
+ endpoint: this.endpoint,
+ variable,
+ },
+ });
+
+ const { errors } = data[currentMutation.name];
+
+ if (errors.length > 0) {
+ createFlash({ 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.
+ // We therefore need to manually refetch.
+ this.$apollo.queries.adminVariables.refetch();
+ }
+ } catch {
+ createFlash({ message: genericMutationErrorText });
+ }
+ },
+ },
+ mutationData: {
+ [ADD_MUTATION_ACTION]: { action: addAdminVariable, name: 'addAdminVariable' },
+ [UPDATE_MUTATION_ACTION]: { action: updateAdminVariable, name: 'updateAdminVariable' },
+ [DELETE_MUTATION_ACTION]: { action: deleteAdminVariable, name: 'deleteAdminVariable' },
+ },
+};
+</script>
+
+<template>
+ <ci-variable-settings
+ :are-scoped-variables-available="false"
+ :is-loading="isLoading"
+ :variables="adminVariables"
+ @add-variable="addVariable"
+ @delete-variable="deleteVariable"
+ @update-variable="updateVariable"
+ />
+</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue b/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
index ecb39f214ec..c9002edc1ab 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_environments_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlSearchBoxByType } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
import { __, sprintf } from '~/locale';
+import { convertEnvironmentScope } from '../utils';
export default {
name: 'CiEnvironmentsDropdown',
@@ -12,7 +12,11 @@ export default {
GlSearchBoxByType,
},
props: {
- value: {
+ environments: {
+ type: Array,
+ required: true,
+ },
+ selectedEnvironmentScope: {
type: String,
required: false,
default: '',
@@ -24,31 +28,36 @@ export default {
};
},
computed: {
- ...mapGetters(['joinedEnvironments']),
composedCreateButtonLabel() {
return sprintf(__('Create wildcard: %{searchTerm}'), { searchTerm: this.searchTerm });
},
+ filteredEnvironments() {
+ const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
+ return this.environments.filter((environment) => {
+ return environment.toLowerCase().includes(lowerCasedSearchTerm);
+ });
+ },
shouldRenderCreateButton() {
- return this.searchTerm && !this.joinedEnvironments.includes(this.searchTerm);
+ return this.searchTerm && !this.environments.includes(this.searchTerm);
},
- filteredResults() {
- const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.joinedEnvironments.filter((resultString) =>
- resultString.toLowerCase().includes(lowerCasedSearchTerm),
- );
+ environmentScopeLabel() {
+ return convertEnvironmentScope(this.selectedEnvironmentScope);
},
},
methods: {
selectEnvironment(selected) {
- this.$emit('selectEnvironment', selected);
- this.searchTerm = '';
+ this.$emit('select-environment', selected);
+ this.clearSearch();
},
- createClicked() {
- this.$emit('createClicked', this.searchTerm);
- this.searchTerm = '';
+ convertEnvironmentScopeValue(scope) {
+ return convertEnvironmentScope(scope);
+ },
+ createEnvironmentScope() {
+ this.$emit('create-environment-scope', this.searchTerm);
+ this.selectEnvironment(this.searchTerm);
},
isSelected(env) {
- return this.value === env;
+ return this.selectedEnvironmentScope === env;
},
clearSearch() {
this.searchTerm = '';
@@ -57,23 +66,23 @@ export default {
};
</script>
<template>
- <gl-dropdown :text="value" @show="clearSearch">
+ <gl-dropdown :text="environmentScopeLabel" @show="clearSearch">
<gl-search-box-by-type v-model.trim="searchTerm" data-testid="ci-environment-search" />
<gl-dropdown-item
- v-for="environment in filteredResults"
+ v-for="environment in filteredEnvironments"
:key="environment"
:is-checked="isSelected(environment)"
is-check-item
@click="selectEnvironment(environment)"
>
- {{ environment }}
+ {{ convertEnvironmentScopeValue(environment) }}
</gl-dropdown-item>
- <gl-dropdown-item v-if="!filteredResults.length" ref="noMatchingResults">{{
+ <gl-dropdown-item v-if="!filteredEnvironments.length" ref="noMatchingResults">{{
__('No matching results')
}}</gl-dropdown-item>
<template v-if="shouldRenderCreateButton">
<gl-dropdown-divider />
- <gl-dropdown-item data-testid="create-wildcard-button" @click="createClicked">
+ <gl-dropdown-item data-testid="create-wildcard-button" @click="createEnvironmentScope">
{{ composedCreateButtonLabel }}
</gl-dropdown-item>
</template>
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
new file mode 100644
index 00000000000..3af83ffa8ed
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue
@@ -0,0 +1,104 @@
+<script>
+import createFlash from '~/flash';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import getGroupVariables from '../graphql/queries/group_variables.query.graphql';
+import {
+ ADD_MUTATION_ACTION,
+ DELETE_MUTATION_ACTION,
+ GRAPHQL_GROUP_TYPE,
+ UPDATE_MUTATION_ACTION,
+ genericMutationErrorText,
+ variableFetchErrorText,
+} from '../constants';
+import addGroupVariable from '../graphql/mutations/group_add_variable.mutation.graphql';
+import deleteGroupVariable from '../graphql/mutations/group_delete_variable.mutation.graphql';
+import updateGroupVariable from '../graphql/mutations/group_update_variable.mutation.graphql';
+import ciVariableSettings from './ci_variable_settings.vue';
+
+export default {
+ components: {
+ ciVariableSettings,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ inject: ['endpoint', 'groupPath', 'groupId'],
+ data() {
+ return {
+ groupVariables: [],
+ };
+ },
+ apollo: {
+ groupVariables: {
+ query: getGroupVariables,
+ variables() {
+ return {
+ fullPath: this.groupPath,
+ };
+ },
+ update(data) {
+ return data?.group?.ciVariables?.nodes || [];
+ },
+ error() {
+ createFlash({ message: variableFetchErrorText });
+ },
+ },
+ },
+ computed: {
+ areScopedVariablesAvailable() {
+ return this.glFeatures.groupScopedCiVariables;
+ },
+ isLoading() {
+ return this.$apollo.queries.groupVariables.loading;
+ },
+ },
+ methods: {
+ addVariable(variable) {
+ this.variableMutation(ADD_MUTATION_ACTION, variable);
+ },
+ deleteVariable(variable) {
+ this.variableMutation(DELETE_MUTATION_ACTION, variable);
+ },
+ updateVariable(variable) {
+ this.variableMutation(UPDATE_MUTATION_ACTION, variable);
+ },
+ async variableMutation(mutationAction, variable) {
+ try {
+ const currentMutation = this.$options.mutationData[mutationAction];
+ const { data } = await this.$apollo.mutate({
+ mutation: currentMutation.action,
+ variables: {
+ endpoint: this.endpoint,
+ fullPath: this.groupPath,
+ groupId: convertToGraphQLId(GRAPHQL_GROUP_TYPE, this.groupId),
+ variable,
+ },
+ });
+
+ const { errors } = data[currentMutation.name];
+
+ if (errors.length > 0) {
+ createFlash({ message: errors[0] });
+ }
+ } catch {
+ createFlash({ message: genericMutationErrorText });
+ }
+ },
+ },
+ mutationData: {
+ [ADD_MUTATION_ACTION]: { action: addGroupVariable, name: 'addGroupVariable' },
+ [UPDATE_MUTATION_ACTION]: { action: updateGroupVariable, name: 'updateGroupVariable' },
+ [DELETE_MUTATION_ACTION]: { action: deleteGroupVariable, name: 'deleteGroupVariable' },
+ },
+};
+</script>
+
+<template>
+ <ci-variable-settings
+ :are-scoped-variables-available="areScopedVariablesAvailable"
+ :is-loading="isLoading"
+ :variables="groupVariables"
+ @add-variable="addVariable"
+ @delete-variable="deleteVariable"
+ @update-variable="updateVariable"
+ />
+</template>
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
index 557a8d6b5ba..5ba63de8c96 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue
@@ -14,22 +14,26 @@ import {
GlModal,
GlSprintf,
} from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
import { getCookie, setCookie } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import Tracking from '~/tracking';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { mapComputed } from '~/vuex_shared/bindings';
+
import {
+ allEnvironments,
AWS_TOKEN_CONSTANTS,
ADD_CI_VARIABLE_MODAL_ID,
AWS_TIP_DISMISSED_COOKIE_NAME,
AWS_TIP_MESSAGE,
CONTAINS_VARIABLE_REFERENCE_MESSAGE,
+ defaultVariableState,
ENVIRONMENT_SCOPE_LINK_TITLE,
EVENT_LABEL,
EVENT_ACTION,
+ EDIT_VARIABLE_ACTION,
+ VARIABLE_ACTIONS,
+ variableOptions,
} from '../constants';
+import { createJoinedEnvironments } from '../utils';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
@@ -58,66 +62,84 @@ export default {
GlModal,
GlSprintf,
},
- mixins: [glFeatureFlagsMixin(), trackingMixin],
+ mixins: [trackingMixin],
+ inject: [
+ 'awsLogoSvgPath',
+ 'awsTipCommandsLink',
+ 'awsTipDeployLink',
+ 'awsTipLearnLink',
+ 'containsVariableReferenceLink',
+ 'environmentScopeLink',
+ 'isProtectedByDefault',
+ 'maskedEnvironmentVariablesLink',
+ 'maskableRegex',
+ 'protectedEnvironmentVariablesLink',
+ ],
+ props: {
+ areScopedVariablesAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ environments: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ mode: {
+ type: String,
+ required: true,
+ validator(val) {
+ return VARIABLE_ACTIONS.includes(val);
+ },
+ },
+ selectedVariable: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ variables: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
data() {
return {
+ newEnvironments: [],
isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
+ typeOptions: variableOptions,
validationErrorEventProperty: '',
+ variable: { ...defaultVariableState, ...this.selectedVariable },
};
},
computed: {
- ...mapState([
- 'projectId',
- 'environments',
- 'typeOptions',
- 'variable',
- 'variableBeingEdited',
- 'isGroup',
- 'maskableRegex',
- 'selectedEnvironment',
- 'isProtectedByDefault',
- 'awsLogoSvgPath',
- 'awsTipDeployLink',
- 'awsTipCommandsLink',
- 'awsTipLearnLink',
- 'containsVariableReferenceLink',
- 'protectedEnvironmentVariablesLink',
- 'maskedEnvironmentVariablesLink',
- 'environmentScopeLink',
- ]),
- ...mapComputed(
- [
- { key: 'key', updateFn: 'updateVariableKey' },
- { key: 'secret_value', updateFn: 'updateVariableValue' },
- { key: 'variable_type', updateFn: 'updateVariableType' },
- { key: 'environment_scope', updateFn: 'setEnvironmentScope' },
- { key: 'protected_variable', updateFn: 'updateVariableProtected' },
- { key: 'masked', updateFn: 'updateVariableMasked' },
- ],
- false,
- 'variable',
- ),
- isTipVisible() {
- return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variable.key);
- },
- canSubmit() {
- return (
- this.variableValidationState &&
- this.variable.key !== '' &&
- this.variable.secret_value !== ''
- );
- },
canMask() {
const regex = RegExp(this.maskableRegex);
- return regex.test(this.variable.secret_value);
+ return regex.test(this.variable.value);
+ },
+ canSubmit() {
+ return this.variableValidationState && this.variable.key !== '' && this.variable.value !== '';
},
containsVariableReference() {
const regex = /\$/;
- return regex.test(this.variable.secret_value);
+ return regex.test(this.variable.value);
},
displayMaskedError() {
return !this.canMask && this.variable.masked;
},
+ isEditing() {
+ return this.mode === EDIT_VARIABLE_ACTION;
+ },
+ isTipVisible() {
+ return !this.isTipDismissed && AWS_TOKEN_CONSTANTS.includes(this.variable.key);
+ },
+ joinedEnvironments() {
+ return createJoinedEnvironments(this.variables, this.environments, this.newEnvironments);
+ },
+ maskedFeedback() {
+ return this.displayMaskedError ? __('This variable can not be masked.') : '';
+ },
maskedState() {
if (this.displayMaskedError) {
return false;
@@ -125,10 +147,7 @@ export default {
return true;
},
modalActionText() {
- return this.variableBeingEdited ? __('Update variable') : __('Add variable');
- },
- maskedFeedback() {
- return this.displayMaskedError ? __('This variable can not be masked.') : '';
+ return this.isEditing ? __('Update variable') : __('Add variable');
},
tokenValidationFeedback() {
const tokenSpecificFeedback = this.$options.tokens?.[this.variable.key]?.invalidMessage;
@@ -141,19 +160,16 @@ export default {
const validator = this.$options.tokens?.[this.variable.key]?.validation;
if (validator) {
- return validator(this.variable.secret_value);
+ return validator(this.variable.value);
}
return true;
},
- scopedVariablesAvailable() {
- return !this.isGroup || this.glFeatures.groupScopedCiVariables;
- },
variableValidationFeedback() {
return `${this.tokenValidationFeedback} ${this.maskedFeedback}`;
},
variableValidationState() {
- return this.variable.secret_value === '' || (this.tokenValidationState && this.maskedState);
+ return this.variable.value === '' || (this.tokenValidationState && this.maskedState);
},
},
watch: {
@@ -165,19 +181,18 @@ export default {
},
},
methods: {
- ...mapActions([
- 'addVariable',
- 'updateVariable',
- 'resetEditing',
- 'displayInputValue',
- 'clearModal',
- 'deleteVariable',
- 'setEnvironmentScope',
- 'addWildCardScope',
- 'resetSelectedEnvironment',
- 'setSelectedEnvironment',
- 'setVariableProtected',
- ]),
+ addVariable() {
+ this.$emit('add-variable', this.variable);
+ },
+ createEnvironmentScope(env) {
+ this.newEnvironments.push(env);
+ },
+ deleteVariable() {
+ this.$emit('delete-variable', this.variable);
+ },
+ updateVariable() {
+ this.$emit('update-variable', this.variable);
+ },
dismissTip() {
setCookie(AWS_TIP_DISMISSED_COOKIE_NAME, 'true', { expires: 90 });
this.isTipDismissed = true;
@@ -190,16 +205,22 @@ export default {
this.$refs.modal.hide();
},
resetModalHandler() {
- if (this.variableBeingEdited) {
- this.resetEditing();
- }
-
- this.clearModal();
- this.resetSelectedEnvironment();
+ this.resetVariableData();
this.resetValidationErrorEvents();
+
+ this.$emit('hideModal');
+ },
+ resetVariableData() {
+ this.variable = { ...defaultVariableState };
+ },
+ setEnvironmentScope(scope) {
+ this.variable = { ...this.variable, environmentScope: scope };
+ },
+ setVariableProtected() {
+ this.variable = { ...this.variable, protected: true };
},
updateOrAddVariable() {
- if (this.variableBeingEdited) {
+ if (this.isEditing) {
this.updateVariable();
} else {
this.addVariable();
@@ -207,7 +228,7 @@ export default {
this.hideModal();
},
setVariableProtectedByDefault() {
- if (this.isProtectedByDefault && !this.variableBeingEdited) {
+ if (this.isProtectedByDefault && !this.isEditing) {
this.setVariableProtected();
}
},
@@ -220,11 +241,11 @@ export default {
},
getTrackingErrorProperty() {
let property;
- if (this.variable.secret_value?.length && !property) {
+ if (this.variable.value?.length && !property) {
if (this.displayMaskedError && this.maskableRegex?.length) {
const supportedChars = this.maskableRegex.replace('^', '').replace(/{(\d,)}\$/, '');
const regex = new RegExp(supportedChars, 'g');
- property = this.variable.secret_value.replace(regex, '');
+ property = this.variable.value.replace(regex, '');
}
if (this.containsVariableReference) {
property = '$';
@@ -237,6 +258,7 @@ export default {
this.validationErrorEventProperty = '';
},
},
+ defaultScope: allEnvironments.text,
};
</script>
@@ -252,7 +274,7 @@ export default {
>
<form>
<gl-form-combobox
- v-model="key"
+ v-model="variable.key"
:token-list="$options.tokenList"
:label-text="__('Key')"
data-qa-selector="ci_variable_key_field"
@@ -267,7 +289,7 @@ export default {
<gl-form-textarea
id="ci-variable-value"
ref="valueField"
- v-model="secret_value"
+ v-model="variable.value"
:state="variableValidationState"
rows="3"
max-rows="6"
@@ -278,7 +300,11 @@ export default {
<div class="d-flex">
<gl-form-group :label="__('Type')" label-for="ci-variable-type" class="w-50 gl-mr-5">
- <gl-form-select id="ci-variable-type" v-model="variable_type" :options="typeOptions" />
+ <gl-form-select
+ id="ci-variable-type"
+ v-model="variable.variableType"
+ :options="typeOptions"
+ />
</gl-form-group>
<gl-form-group label-for="ci-variable-env" class="w-50" data-testid="environment-scope">
@@ -294,22 +320,24 @@ export default {
</gl-link>
</template>
<ci-environments-dropdown
- v-if="scopedVariablesAvailable"
- class="w-100"
- :value="environment_scope"
- @selectEnvironment="setEnvironmentScope"
- @createClicked="addWildCardScope"
+ v-if="areScopedVariablesAvailable"
+ class="gl-w-full"
+ :selected-environment-scope="variable.environmentScope"
+ :environments="joinedEnvironments"
+ @select-environment="setEnvironmentScope"
+ @create-environment-scope="createEnvironmentScope"
/>
- <gl-form-input v-else v-model="environment_scope" class="w-100" readonly />
+ <gl-form-input v-else :value="$options.defaultScope" class="gl-w-full" readonly />
</gl-form-group>
</div>
<gl-form-group :label="__('Flags')" label-for="ci-variable-flags">
<gl-form-checkbox
- v-model="protected_variable"
- class="mb-0"
+ v-model="variable.protected"
+ class="gl-mb-0"
data-testid="ci-variable-protected-checkbox"
+ :data-is-protected-checked="variable.protected"
>
{{ __('Protect variable') }}
<gl-link target="_blank" :href="protectedEnvironmentVariablesLink">
@@ -322,7 +350,7 @@ export default {
<gl-form-checkbox
ref="masked-ci-variable"
- v-model="masked"
+ v-model="variable.masked"
data-testid="ci-variable-masked-checkbox"
>
{{ __('Mask variable') }}
@@ -403,7 +431,7 @@ export default {
<template #modal-footer>
<gl-button @click="hideModal">{{ __('Cancel') }}</gl-button>
<gl-button
- v-if="variableBeingEdited"
+ v-if="isEditing"
ref="deleteCiVariable"
variant="danger"
category="secondary"
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue
index 4cc00eb01d9..81e3a983ea3 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue
@@ -1,9 +1,91 @@
<script>
-export default {};
+import { ADD_VARIABLE_ACTION, EDIT_VARIABLE_ACTION, VARIABLE_ACTIONS } from '../constants';
+import CiVariableTable from './ci_variable_table.vue';
+import CiVariableModal from './ci_variable_modal.vue';
+
+export default {
+ components: {
+ CiVariableTable,
+ CiVariableModal,
+ },
+ props: {
+ areScopedVariablesAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ environments: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ variables: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ selectedVariable: {},
+ mode: null,
+ };
+ },
+ computed: {
+ showModal() {
+ return VARIABLE_ACTIONS.includes(this.mode);
+ },
+ },
+ methods: {
+ addVariable(variable) {
+ this.$emit('add-variable', variable);
+ },
+ deleteVariable(variable) {
+ this.$emit('delete-variable', variable);
+ },
+ updateVariable(variable) {
+ this.$emit('update-variable', variable);
+ },
+ hideModal() {
+ this.mode = null;
+ },
+ setSelectedVariable(variable = null) {
+ if (!variable) {
+ this.selectedVariable = {};
+ this.mode = ADD_VARIABLE_ACTION;
+ } else {
+ this.selectedVariable = variable;
+ this.mode = EDIT_VARIABLE_ACTION;
+ }
+ },
+ },
+};
</script>
<template>
<div class="row">
- <div class="col-lg-12"></div>
+ <div class="col-lg-12">
+ <ci-variable-table
+ :is-loading="isLoading"
+ :variables="variables"
+ @set-selected-variable="setSelectedVariable"
+ />
+ <ci-variable-modal
+ v-if="showModal"
+ :are-scoped-variables-available="areScopedVariablesAvailable"
+ :environments="environments"
+ :variables="variables"
+ :mode="mode"
+ :selected-variable="selectedVariable"
+ @add-variable="addVariable"
+ @delete-variable="deleteVariable"
+ @hideModal="hideModal"
+ @update-variable="updateVariable"
+ />
+ </div>
</div>
</template>
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 f078234829a..1bb94080694 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -1,10 +1,17 @@
<script>
-import { GlTable, GlButton, GlModalDirective, GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { mapState, mapActions } from 'vuex';
+import {
+ GlButton,
+ GlIcon,
+ GlLoadingIcon,
+ GlModalDirective,
+ GlTable,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { s__, __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
-import { ADD_CI_VARIABLE_MODAL_ID } from '../constants';
+import { ADD_CI_VARIABLE_MODAL_ID, variableText } from '../constants';
+import { convertEnvironmentScope } from '../utils';
import CiVariablePopover from './ci_variable_popover.vue';
export default {
@@ -14,7 +21,7 @@ export default {
iconSize: 16,
fields: [
{
- key: 'variable_type',
+ key: 'variableType',
label: s__('CiVariables|Type'),
customStyle: { width: '70px' },
},
@@ -41,7 +48,7 @@ export default {
customStyle: { width: '100px' },
},
{
- key: 'environment_scope',
+ key: 'environmentScope',
label: s__('CiVariables|Environments'),
customStyle: { width: '20%' },
},
@@ -56,6 +63,7 @@ export default {
CiVariablePopover,
GlButton,
GlIcon,
+ GlLoadingIcon,
GlTable,
TooltipOnTruncate,
},
@@ -64,10 +72,25 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagsMixin()],
+ props: {
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ variables: {
+ type: Array,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ areValuesHidden: true,
+ };
+ },
computed: {
- ...mapState(['variables', 'valuesHidden', 'isLoading', 'isDeleting']),
valuesButtonText() {
- return this.valuesHidden ? __('Reveal values') : __('Hide values');
+ return this.areValuesHidden ? __('Reveal values') : __('Hide values');
},
isTableEmpty() {
return !this.variables || this.variables.length === 0;
@@ -76,18 +99,28 @@ export default {
return this.$options.fields;
},
},
- mounted() {
- this.fetchVariables();
- },
methods: {
- ...mapActions(['fetchVariables', 'toggleValues', 'editVariable']),
+ convertEnvironmentScopeValue(env) {
+ return convertEnvironmentScope(env);
+ },
+ generateTypeText(item) {
+ return variableText[item.variableType];
+ },
+ toggleHiddenState() {
+ this.areValuesHidden = !this.areValuesHidden;
+ },
+ setSelectedVariable(variable = null) {
+ this.$emit('set-selected-variable', variable);
+ },
},
};
</script>
<template>
<div class="ci-variable-table" data-testid="ci-variable-table">
+ <gl-loading-icon v-if="isLoading" />
<gl-table
+ v-else
:fields="fields"
:items="variables"
tbody-tr-class="js-ci-variable-row"
@@ -104,6 +137,11 @@ export default {
<template #table-colgroup="scope">
<col v-for="field in scope.fields" :key="field.key" :style="field.customStyle" />
</template>
+ <template #cell(variableType)="{ item }">
+ <div class="gl-pt-2">
+ {{ generateTypeText(item) }}
+ </div>
+ </template>
<template #cell(key)="{ item }">
<div class="gl-display-flex gl-align-items-center">
<tooltip-on-truncate :title="item.key" truncate-target="child">
@@ -125,11 +163,12 @@ export default {
</template>
<template #cell(value)="{ item }">
<div class="gl-display-flex gl-align-items-center">
- <span v-if="valuesHidden">*********************</span>
+ <span v-if="areValuesHidden" data-testid="hiddenValue">*********************</span>
<span
v-else
:id="`ci-variable-value-${item.id}`"
class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ data-testid="revealedValue"
>{{ item.value }}</span
>
<gl-button
@@ -150,16 +189,16 @@ export default {
<gl-icon v-if="item.masked" :size="$options.iconSize" :name="$options.trueIcon" />
<gl-icon v-else :size="$options.iconSize" :name="$options.falseIcon" />
</template>
- <template #cell(environment_scope)="{ item }">
+ <template #cell(environmentScope)="{ item }">
<div class="gl-display-flex">
<span
:id="`ci-variable-env-${item.id}`"
class="gl-display-inline-block gl-max-w-full gl-text-truncate"
- >{{ item.environment_scope }}</span
+ >{{ convertEnvironmentScopeValue(item.environmentScope) }}</span
>
<ci-variable-popover
:target="`ci-variable-env-${item.id}`"
- :value="item.environment_scope"
+ :value="convertEnvironmentScopeValue(item.environmentScope)"
:tooltip-text="__('Copy environment')"
/>
</div>
@@ -170,7 +209,7 @@ export default {
icon="pencil"
:aria-label="__('Edit')"
data-qa-selector="edit_ci_variable_button"
- @click="editVariable(item)"
+ @click="setSelectedVariable(item)"
/>
</template>
<template #empty>
@@ -186,12 +225,14 @@ export default {
data-qa-selector="add_ci_variable_button"
variant="confirm"
category="primary"
+ :aria-label="__('Add')"
+ @click="setSelectedVariable()"
>{{ __('Add variable') }}</gl-button
>
<gl-button
v-if="!isTableEmpty"
data-qa-selector="reveal_ci_variable_value_button"
- @click="toggleValues(!valuesHidden)"
+ @click="toggleHiddenState"
>{{ valuesButtonText }}</gl-button
>
</div>
diff --git a/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_modal.vue b/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_modal.vue
index 7dcc5ce42d7..cebb7eb85ac 100644
--- a/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_modal.vue
+++ b/app/assets/javascripts/ci_variable_list/components/legacy_ci_variable_modal.vue
@@ -30,7 +30,7 @@ import {
EVENT_LABEL,
EVENT_ACTION,
} from '../constants';
-import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
+import LegacyCiEnvironmentsDropdown from './legacy_ci_environments_dropdown.vue';
import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
@@ -43,7 +43,7 @@ export default {
containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE,
environmentScopeLinkTitle: ENVIRONMENT_SCOPE_LINK_TITLE,
components: {
- CiEnvironmentsDropdown,
+ LegacyCiEnvironmentsDropdown,
GlAlert,
GlButton,
GlCollapse,
@@ -293,7 +293,7 @@ export default {
<gl-icon name="question" :size="12" />
</gl-link>
</template>
- <ci-environments-dropdown
+ <legacy-ci-environments-dropdown
v-if="scopedVariablesAvailable"
class="w-100"
:value="environment_scope"
diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js
index fa55b4d9e77..5d22974ffbb 100644
--- a/app/assets/javascripts/ci_variable_list/constants.js
+++ b/app/assets/javascripts/ci_variable_list/constants.js
@@ -2,18 +2,58 @@ import { __ } from '~/locale';
export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable';
+// This const will be deprecated once we remove VueX from the section
export const displayText = {
variableText: __('Variable'),
fileText: __('File'),
allEnvironmentsText: __('All (default)'),
};
+export const variableTypes = {
+ variableType: 'ENV_VAR',
+ fileType: 'FILE',
+};
+
+// Once REST is removed, we won't need `types`
export const types = {
variableType: 'env_var',
fileType: 'file',
- allEnvironmentsType: '*',
};
+export const allEnvironments = {
+ type: '*',
+ text: __('All (default)'),
+};
+
+// Once REST is removed, we won't need `types` key
+export const variableText = {
+ [types.variableType]: __('Variable'),
+ [types.fileType]: __('File'),
+ [variableTypes.variableType]: __('Variable'),
+ [variableTypes.fileType]: __('File'),
+};
+
+export const variableOptions = [
+ { value: types.variableType, text: variableText[types.variableType] },
+ { value: types.fileType, text: variableText[types.fileType] },
+];
+
+export const defaultVariableState = {
+ environmentScope: allEnvironments.type,
+ key: '',
+ masked: false,
+ protected: false,
+ value: '',
+ variableType: types.variableType,
+};
+
+// eslint-disable-next-line @gitlab/require-i18n-strings
+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 AWS_TIP_DISMISSED_COOKIE_NAME = 'ci_variable_list_constants_aws_tip_dismissed';
export const AWS_TIP_MESSAGE = __(
'%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}.',
@@ -33,3 +73,20 @@ export const CONTAINS_VARIABLE_REFERENCE_MESSAGE = __(
);
export const ENVIRONMENT_SCOPE_LINK_TITLE = __('Learn more');
+
+export const ADD_VARIABLE_ACTION = 'ADD_VARIABLE';
+export const EDIT_VARIABLE_ACTION = 'EDIT_VARIABLE';
+export const VARIABLE_ACTIONS = [ADD_VARIABLE_ACTION, EDIT_VARIABLE_ACTION];
+
+export const GRAPHQL_PROJECT_TYPE = 'Project';
+export const GRAPHQL_GROUP_TYPE = 'Group';
+
+export const ADD_MUTATION_ACTION = 'add';
+export const UPDATE_MUTATION_ACTION = 'update';
+export const DELETE_MUTATION_ACTION = 'delete';
+
+export const environmentFetchErrorText = __(
+ 'There was an error fetching the environments information.',
+);
+export const genericMutationErrorText = __('Something went wrong on our end. Please try again.');
+export const variableFetchErrorText = __('There was an error fetching the variables.');
diff --git a/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql b/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql
new file mode 100644
index 00000000000..a28ca4eebc9
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql
@@ -0,0 +1,7 @@
+fragment BaseCiVariable on CiVariable {
+ __typename
+ id
+ key
+ value
+ variableType
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql
new file mode 100644
index 00000000000..eba4b0c32f8
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql
@@ -0,0 +1,16 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation addAdminVariable($variable: CiVariable!, $endpoint: String!) {
+ addAdminVariable(variable: $variable, endpoint: $endpoint) @client {
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiInstanceVariable {
+ protected
+ masked
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql
new file mode 100644
index 00000000000..96eb8c794bc
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql
@@ -0,0 +1,16 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation deleteAdminVariable($variable: CiVariable!, $endpoint: String!) {
+ deleteAdminVariable(variable: $variable, endpoint: $endpoint) @client {
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiInstanceVariable {
+ protected
+ masked
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql
new file mode 100644
index 00000000000..c0388507bb8
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql
@@ -0,0 +1,16 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation updateAdminVariable($variable: CiVariable!, $endpoint: String!) {
+ updateAdminVariable(variable: $variable, endpoint: $endpoint) @client {
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiInstanceVariable {
+ protected
+ masked
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql
new file mode 100644
index 00000000000..f8e4dc55fa4
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql
@@ -0,0 +1,30 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation addGroupVariable(
+ $variable: CiVariable!
+ $endpoint: String!
+ $fullPath: ID!
+ $groupId: ID!
+) {
+ addGroupVariable(
+ variable: $variable
+ endpoint: $endpoint
+ fullPath: $fullPath
+ groupId: $groupId
+ ) @client {
+ group {
+ id
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiGroupVariable {
+ environmentScope
+ masked
+ protected
+ }
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql
new file mode 100644
index 00000000000..310e4a6e551
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql
@@ -0,0 +1,30 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation deleteGroupVariable(
+ $variable: CiVariable!
+ $endpoint: String!
+ $fullPath: ID!
+ $groupId: ID!
+) {
+ deleteGroupVariable(
+ variable: $variable
+ endpoint: $endpoint
+ fullPath: $fullPath
+ groupId: $groupId
+ ) @client {
+ group {
+ id
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiGroupVariable {
+ environmentScope
+ masked
+ protected
+ }
+ }
+ }
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql
new file mode 100644
index 00000000000..5291942eb87
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql
@@ -0,0 +1,30 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+mutation updateGroupVariable(
+ $variable: CiVariable!
+ $endpoint: String!
+ $fullPath: ID!
+ $groupId: ID!
+) {
+ updateGroupVariable(
+ variable: $variable
+ endpoint: $endpoint
+ fullPath: $fullPath
+ groupId: $groupId
+ ) @client {
+ group {
+ id
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiGroupVariable {
+ environmentScope
+ masked
+ protected
+ }
+ }
+ }
+ }
+ errors
+ }
+}
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
new file mode 100644
index 00000000000..c6dd6d4faaf
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql
@@ -0,0 +1,17 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+query getGroupVariables($fullPath: ID!) {
+ group(fullPath: $fullPath) {
+ id
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiGroupVariable {
+ environmentScope
+ masked
+ protected
+ }
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000000..95056842b49
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/queries/variables.query.graphql
@@ -0,0 +1,13 @@
+#import "~/ci_variable_list/graphql/fragments/ci_variable.fragment.graphql"
+
+query getVariables {
+ ciVariables {
+ nodes {
+ ...BaseCiVariable
+ ... on CiInstanceVariable {
+ masked
+ protected
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/ci_variable_list/graphql/resolvers.js b/app/assets/javascripts/ci_variable_list/graphql/resolvers.js
new file mode 100644
index 00000000000..be7e3f88cfd
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/graphql/resolvers.js
@@ -0,0 +1,113 @@
+import axios from 'axios';
+import {
+ convertObjectPropsToCamelCase,
+ convertObjectPropsToSnakeCase,
+} from '../../lib/utils/common_utils';
+import { getIdFromGraphQLId } from '../../graphql_shared/utils';
+import { GRAPHQL_GROUP_TYPE, groupString, instanceString } from '../constants';
+import getAdminVariables from './queries/variables.query.graphql';
+import getGroupVariables from './queries/group_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 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 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: {
+ 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/index.js b/app/assets/javascripts/ci_variable_list/index.js
index 2b54af6a2a4..a74af8aed12 100644
--- a/app/assets/javascripts/ci_variable_list/index.js
+++ b/app/assets/javascripts/ci_variable_list/index.js
@@ -2,8 +2,10 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
-import CiVariableSettings from './components/ci_variable_settings.vue';
+import CiAdminVariables from './components/ci_admin_variables.vue';
+import CiGroupVariables from './components/ci_group_variables.vue';
import LegacyCiVariableSettings from './components/legacy_ci_variable_settings.vue';
+import { resolvers } from './graphql/resolvers';
import createStore from './store';
const mountCiVariableListApp = (containerEl) => {
@@ -13,8 +15,12 @@ const mountCiVariableListApp = (containerEl) => {
awsTipDeployLink,
awsTipLearnLink,
containsVariableReferenceLink,
+ endpoint,
environmentScopeLink,
- group,
+ groupId,
+ groupPath,
+ isGroup,
+ isProject,
maskedEnvironmentVariablesLink,
maskableRegex,
projectFullPath,
@@ -23,13 +29,20 @@ const mountCiVariableListApp = (containerEl) => {
protectedEnvironmentVariablesLink,
} = containerEl.dataset;
- const isGroup = parseBoolean(group);
+ const parsedIsProject = parseBoolean(isProject);
+ const parsedIsGroup = parseBoolean(isGroup);
const isProtectedByDefault = parseBoolean(protectedByDefault);
+ let component = CiAdminVariables;
+
+ if (parsedIsGroup) {
+ component = CiGroupVariables;
+ }
+
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ defaultClient: createDefaultClient(resolvers),
});
return new Vue({
@@ -41,8 +54,12 @@ const mountCiVariableListApp = (containerEl) => {
awsTipDeployLink,
awsTipLearnLink,
containsVariableReferenceLink,
+ endpoint,
environmentScopeLink,
- isGroup,
+ groupId,
+ groupPath,
+ isGroup: parsedIsGroup,
+ isProject: parsedIsProject,
isProtectedByDefault,
maskedEnvironmentVariablesLink,
maskableRegex,
@@ -51,7 +68,7 @@ const mountCiVariableListApp = (containerEl) => {
protectedEnvironmentVariablesLink,
},
render(createElement) {
- return createElement(CiVariableSettings);
+ return createElement(component);
},
});
};
diff --git a/app/assets/javascripts/ci_variable_list/store/utils.js b/app/assets/javascripts/ci_variable_list/store/utils.js
index d9ca460a8e1..f46a671ae7b 100644
--- a/app/assets/javascripts/ci_variable_list/store/utils.js
+++ b/app/assets/javascripts/ci_variable_list/store/utils.js
@@ -1,5 +1,5 @@
import { cloneDeep } from 'lodash';
-import { displayText, types } from '../constants';
+import { displayText, types, allEnvironments } from '../constants';
const variableTypeHandler = (type) =>
type === displayText.variableText ? types.variableType : types.fileType;
@@ -15,7 +15,7 @@ export const prepareDataForDisplay = (variables) => {
}
variableCopy.secret_value = variableCopy.value;
- if (variableCopy.environment_scope === types.allEnvironmentsType) {
+ if (variableCopy.environment_scope === allEnvironments.type) {
variableCopy.environment_scope = displayText.allEnvironmentsText;
}
variableCopy.protected_variable = variableCopy.protected;
@@ -31,7 +31,7 @@ export const prepareDataForApi = (variable, destroy = false) => {
variableCopy.masked = variableCopy.masked.toString();
variableCopy.variable_type = variableTypeHandler(variableCopy.variable_type);
if (variableCopy.environment_scope === displayText.allEnvironmentsText) {
- variableCopy.environment_scope = types.allEnvironmentsType;
+ variableCopy.environment_scope = allEnvironments.type;
}
if (destroy) {
diff --git a/app/assets/javascripts/ci_variable_list/utils.js b/app/assets/javascripts/ci_variable_list/utils.js
new file mode 100644
index 00000000000..1faa97a5f73
--- /dev/null
+++ b/app/assets/javascripts/ci_variable_list/utils.js
@@ -0,0 +1,50 @@
+import { uniq } from 'lodash';
+import { allEnvironments } from './constants';
+
+/**
+ * This function takes a list of variable, environments and
+ * new environments added through the scope dropdown
+ * and create a new Array that concatenate the environment list
+ * with the environment scopes find in the variable list. This is
+ * useful for variable settings so that we can render a list of all
+ * environment scopes available based on the list of envs, the ones the user
+ * added explictly and what is found under each variable.
+ * @param {Array} variables
+ * @param {Array} environments
+ * @returns {Array} - Array of environments
+ */
+
+export const createJoinedEnvironments = (
+ variables = [],
+ environments = [],
+ newEnvironments = [],
+) => {
+ const scopesFromVariables = variables.map((variable) => variable.environmentScope);
+ return uniq([...environments, ...newEnvironments, ...scopesFromVariables]).sort();
+};
+
+/**
+ * This function job is to convert the * wildcard to text when applicable
+ * in the UI. It uses a constants to compare the incoming value to that
+ * of the * and then apply the corresponding label if applicable. If there
+ * is no scope, then we return the default value as well.
+ * @param {String} scope
+ * @returns {String} - Converted value if applicable
+ */
+
+export const convertEnvironmentScope = (environmentScope = '') => {
+ if (environmentScope === allEnvironments.type || !environmentScope) {
+ return allEnvironments.text;
+ }
+
+ return environmentScope;
+};
+
+/**
+ * Gives us an array of all the environments by name
+ * @param {Array} nodes
+ * @return {Array<String>} - Array of environments strings
+ */
+export const mapEnvironmentNames = (nodes = []) => {
+ return nodes.map((env) => env.name);
+};
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 1ea5eff35d4..4b85ca2b508 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -235,7 +235,7 @@ export default {
:fields="fields"
fixed
stacked="md"
- class="qa-clusters-table gl-mb-4!"
+ class="gl-mb-4!"
data-testid="cluster_list_table"
>
<template #cell(name)="{ item }">
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 4ff49433749..95ee3a0d90e 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -1,5 +1,6 @@
<script>
-import { GlButton, GlEmptyState, GlLoadingIcon, GlModal, GlLink } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlLoadingIcon, GlModal, GlLink, GlSprintf } from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
import { getParameterByName } from '~/lib/utils/url_utility';
import PipelinesTableComponent from '~/pipelines/components/pipelines_list/pipelines_table.vue';
import { PipelineKeyOptions } from '~/pipelines/constants';
@@ -19,6 +20,7 @@ export default {
GlLink,
GlLoadingIcon,
GlModal,
+ GlSprintf,
PipelinesTableComponent,
TablePagination,
},
@@ -32,6 +34,10 @@ export default {
type: String,
required: true,
},
+ emptyStateSvgPath: {
+ type: String,
+ required: true,
+ },
viewType: {
type: String,
required: false,
@@ -83,6 +89,9 @@ export default {
shouldRenderErrorState() {
return this.hasError && !this.isLoading;
},
+ shouldRenderEmptyState() {
+ return this.state.pipelines.length === 0 && !this.shouldRenderErrorState;
+ },
/**
* The "Run pipeline" button can only be rendered when:
* - In MR view - we use `canCreatePipelineInTargetProject` for that purpose
@@ -185,6 +194,17 @@ export default {
},
},
},
+ i18n: {
+ runPipelinePopoverTitle: s__('Pipeline|Run merge request pipeline'),
+ runPipelinePopoverDescription: s__(
+ '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.',
+ ),
+ runPipelineText: s__('Pipeline|Run pipeline'),
+ emptyStateTitle: s__('Pipelines|There are currently no pipelines.'),
+ },
+ mrPipelinesDocsPath: helpPagePath('ci/pipelines/merge_request_pipelines.md', {
+ anchor: 'prerequisites',
+ }),
};
</script>
<template>
@@ -203,7 +223,41 @@ export default {
s__(`Pipelines|There was an error fetching the pipelines.
Try again in a few moments or contact your support team.`)
"
+ data-testid="pipeline-error-empty-state"
/>
+ <template v-else-if="shouldRenderEmptyState">
+ <gl-empty-state
+ :svg-path="emptyStateSvgPath"
+ :title="$options.i18n.emptyStateTitle"
+ data-testid="pipeline-empty-state"
+ >
+ <template #description>
+ <gl-sprintf :message="$options.i18n.runPipelinePopoverDescription">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.mrPipelinesDocsPath"
+ target="_blank"
+ data-testid="mr-pipelines-docs-link"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
+
+ <template #actions>
+ <div class="gl-vertical-align-middle">
+ <gl-button
+ variant="confirm"
+ :loading="state.isRunningMergeRequestPipeline"
+ data-testid="run_pipeline_button"
+ @click="tryRunPipeline"
+ >
+ {{ $options.i18n.runPipelineText }}
+ </gl-button>
+ </div>
+ </template>
+ </gl-empty-state>
+ </template>
<div v-else-if="shouldRenderTable">
<gl-button
@@ -215,7 +269,7 @@ export default {
:loading="state.isRunningMergeRequestPipeline"
@click="tryRunPipeline"
>
- {{ s__('Pipeline|Run pipeline') }}
+ {{ $options.i18n.runPipelineText }}
</gl-button>
<pipelines-table-component
@@ -231,7 +285,7 @@ export default {
:loading="state.isRunningMergeRequestPipeline"
@click="tryRunPipeline"
>
- {{ s__('Pipeline|Run pipeline') }}
+ {{ $options.i18n.runPipelineText }}
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/commons/nav/user_merge_requests.js b/app/assets/javascripts/commons/nav/user_merge_requests.js
index 784e9cb2faa..b105273ece7 100644
--- a/app/assets/javascripts/commons/nav/user_merge_requests.js
+++ b/app/assets/javascripts/commons/nav/user_merge_requests.js
@@ -26,39 +26,20 @@ function updateMergeRequestCounts(newCount) {
mergeRequestsCountEl.classList.toggle('gl-display-none', Number(newCount) === 0);
}
-function updateAttentionRequestsCount(count) {
- const attentionCountEl = document.querySelector('.js-attention-count');
- attentionCountEl.textContent = count.toLocaleString();
-
- if (Number(count) === 0) {
- attentionCountEl.classList.replace('badge-warning', 'badge-neutral');
- } else {
- attentionCountEl.classList.replace('badge-neutral', 'badge-warning');
- }
-}
-
/**
* Refresh user counts (and broadcast if open)
*/
export function refreshUserMergeRequestCounts() {
return getUserCounts()
.then(({ data }) => {
- const attentionRequestsEnabled = window.gon?.features?.mrAttentionRequests;
const assignedMergeRequests = data.assigned_merge_requests;
const reviewerMergeRequests = data.review_requested_merge_requests;
- const attentionRequests = data.attention_requests;
- const fullCount = attentionRequestsEnabled
- ? attentionRequests
- : assignedMergeRequests + reviewerMergeRequests;
+ const fullCount = assignedMergeRequests + reviewerMergeRequests;
updateUserMergeRequestCounts(assignedMergeRequests);
updateReviewerMergeRequestCounts(reviewerMergeRequests);
updateMergeRequestCounts(fullCount);
broadcastCount(fullCount);
-
- if (attentionRequestsEnabled) {
- updateAttentionRequestsCount(attentionRequests);
- }
})
.catch((ex) => {
console.error(ex); // eslint-disable-line no-console
diff --git a/app/assets/javascripts/content_editor/components/bubble_menus/formatting.vue b/app/assets/javascripts/content_editor/components/bubble_menus/formatting.vue
index f0726ff3e63..05ca7fd75c3 100644
--- a/app/assets/javascripts/content_editor/components/bubble_menus/formatting.vue
+++ b/app/assets/javascripts/content_editor/components/bubble_menus/formatting.vue
@@ -3,13 +3,11 @@ import { GlButtonGroup } from '@gitlab/ui';
import { BubbleMenu } from '@tiptap/vue-2';
import { BUBBLE_MENU_TRACKING_ACTION } from '../../constants';
import trackUIControl from '../../services/track_ui_control';
-import Image from '../../extensions/image';
+import Paragraph from '../../extensions/paragraph';
+import Heading from '../../extensions/heading';
import Audio from '../../extensions/audio';
import Video from '../../extensions/video';
-import Code from '../../extensions/code';
-import CodeBlockHighlight from '../../extensions/code_block_highlight';
-import Diagram from '../../extensions/diagram';
-import Frontmatter from '../../extensions/frontmatter';
+import Image from '../../extensions/image';
import ToolbarButton from '../toolbar_button.vue';
export default {
@@ -27,17 +25,13 @@ export default {
shouldShow: ({ editor, from, to }) => {
if (from === to) return false;
- const exclude = [
- Code.name,
- CodeBlockHighlight.name,
- Diagram.name,
- Frontmatter.name,
- Image.name,
- Audio.name,
- Video.name,
- ];
+ const includes = [Paragraph.name, Heading.name];
+ const excludes = [Image.name, Audio.name, Video.name];
- return !exclude.some((type) => editor.isActive(type));
+ return (
+ includes.some((type) => editor.isActive(type)) &&
+ !excludes.some((type) => editor.isActive(type))
+ );
},
},
};
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue
index 74ae37b6d06..c3c881d9135 100644
--- a/app/assets/javascripts/content_editor/components/content_editor.vue
+++ b/app/assets/javascripts/content_editor/components/content_editor.vue
@@ -84,7 +84,14 @@ 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"
+ @loading="$emit('loading')"
+ @loadingSuccess="$emit('loadingSuccess')"
+ @loadingError="$emit('loadingError')"
+ />
<content-editor-alert />
<div
data-testid="content-editor"
diff --git a/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue b/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue
index 6e4cde5dad6..9ad739e7358 100644
--- a/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue
+++ b/app/assets/javascripts/content_editor/components/toolbar_more_dropdown.vue
@@ -33,8 +33,12 @@ export default {
this.$emit('execute', { contentType: listType });
},
- execute(command, contentType) {
- this.tiptapEditor.chain().focus()[command]().run();
+ execute(command, contentType, ...args) {
+ this.tiptapEditor
+ .chain()
+ .focus()
+ [command](...args)
+ .run();
this.$emit('execute', { contentType });
},
@@ -67,5 +71,8 @@ export default {
<gl-dropdown-item @click="insert('diagram', { language: 'plantuml' })">
{{ __('PlantUML diagram') }}
</gl-dropdown-item>
+ <gl-dropdown-item @click="execute('insertTableOfContents', 'tableOfContents')">
+ {{ __('Table of contents') }}
+ </gl-dropdown-item>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/content_editor/components/top_toolbar.vue b/app/assets/javascripts/content_editor/components/top_toolbar.vue
index 65d71814268..1030ebbf838 100644
--- a/app/assets/javascripts/content_editor/components/top_toolbar.vue
+++ b/app/assets/javascripts/content_editor/components/top_toolbar.vue
@@ -93,7 +93,7 @@ export default {
icon-name="list-task"
class="gl-mx-2 gl-display-none gl-sm-display-inline"
editor-command="toggleTaskList"
- :label="__('Add a task list')"
+ :label="__('Add a checklist')"
@execute="trackToolbarControlExecution"
/>
<toolbar-image-button
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
index c0d6e32a739..6456540a0dd 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_cell_base.vue
@@ -1,7 +1,7 @@
<script>
import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2';
-import { selectedRect as getSelectedRect } from 'prosemirror-tables';
+import { selectedRect as getSelectedRect } from '@_ueberdosis/prosemirror-tables';
import { __ } from '~/locale';
const TABLE_CELL_HEADER = 'th';
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_of_contents.vue b/app/assets/javascripts/content_editor/components/wrappers/table_of_contents.vue
new file mode 100644
index 00000000000..a4e1be9d95d
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_of_contents.vue
@@ -0,0 +1,55 @@
+<script>
+import { debounce } from 'lodash';
+import { NodeViewWrapper } from '@tiptap/vue-2';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import { getHeadings } from '../../services/table_of_contents_utils';
+import TableOfContentsHeading from './table_of_contents_heading.vue';
+
+export default {
+ name: 'TableOfContentsWrapper',
+ components: {
+ NodeViewWrapper,
+ TableOfContentsHeading,
+ },
+ props: {
+ editor: {
+ type: Object,
+ required: true,
+ },
+ node: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ headings: [],
+ };
+ },
+ mounted() {
+ this.handleUpdate = debounce(this.handleUpdate, DEFAULT_DEBOUNCE_AND_THROTTLE_MS * 2);
+
+ this.editor.on('update', this.handleUpdate);
+ this.$nextTick(this.handleUpdate);
+ },
+ methods: {
+ handleUpdate() {
+ this.headings = getHeadings(this.editor);
+ },
+ },
+};
+</script>
+<template>
+ <node-view-wrapper
+ as="ul"
+ class="table-of-contents gl-border-1 gl-border-solid gl-border-gray-100 gl-mb-5 gl-p-4!"
+ data-testid="table-of-contents"
+ >
+ {{ __('Table of contents') }}
+ <table-of-contents-heading
+ v-for="(heading, index) in headings"
+ :key="index"
+ :heading="heading"
+ />
+ </node-view-wrapper>
+</template>
diff --git a/app/assets/javascripts/content_editor/components/wrappers/table_of_contents_heading.vue b/app/assets/javascripts/content_editor/components/wrappers/table_of_contents_heading.vue
new file mode 100644
index 00000000000..edd75d232e8
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/wrappers/table_of_contents_heading.vue
@@ -0,0 +1,25 @@
+<script>
+export default {
+ name: 'TableOfContentsHeading',
+ props: {
+ heading: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <li>
+ <a v-if="heading.text" href="#" @click.prevent>
+ {{ heading.text }}
+ </a>
+ <ul v-if="heading.subHeadings.length">
+ <table-of-contents-heading
+ v-for="(child, index) in heading.subHeadings"
+ :key="index"
+ :heading="child"
+ />
+ </ul>
+ </li>
+</template>
diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
index edf8b3d3a0b..27432b1e18b 100644
--- a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
+++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
@@ -1,3 +1,4 @@
+import { lowlight } from 'lowlight/lib/core';
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
import { textblockTypeInputRule } from '@tiptap/core';
import { VueNodeViewRenderer } from '@tiptap/vue-2';
@@ -66,4 +67,4 @@ export default CodeBlockLowlight.extend({
addNodeView() {
return new VueNodeViewRenderer(CodeBlockWrapper);
},
-});
+}).configure({ lowlight });
diff --git a/app/assets/javascripts/content_editor/extensions/diagram.js b/app/assets/javascripts/content_editor/extensions/diagram.js
index c59ca8a28b8..d9983b8c1c5 100644
--- a/app/assets/javascripts/content_editor/extensions/diagram.js
+++ b/app/assets/javascripts/content_editor/extensions/diagram.js
@@ -1,3 +1,4 @@
+import { lowlight } from 'lowlight/lib/core';
import { textblockTypeInputRule } from '@tiptap/core';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import languageLoader from '../services/code_block_language_loader';
@@ -10,6 +11,12 @@ export default CodeBlockHighlight.extend({
isolating: true,
+ addOptions() {
+ return {
+ lowlight,
+ };
+ },
+
addAttributes() {
return {
language: {
diff --git a/app/assets/javascripts/content_editor/extensions/frontmatter.js b/app/assets/javascripts/content_editor/extensions/frontmatter.js
index 2ec22158106..428171a9389 100644
--- a/app/assets/javascripts/content_editor/extensions/frontmatter.js
+++ b/app/assets/javascripts/content_editor/extensions/frontmatter.js
@@ -1,9 +1,16 @@
+import { lowlight } from 'lowlight/lib/core';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import CodeBlockHighlight from './code_block_highlight';
export default CodeBlockHighlight.extend({
name: 'frontmatter',
+ addOptions() {
+ return {
+ lowlight,
+ };
+ },
+
addAttributes() {
return {
...this.parent?.(),
diff --git a/app/assets/javascripts/content_editor/extensions/image.js b/app/assets/javascripts/content_editor/extensions/image.js
index 25f976f524f..65849ec4d0d 100644
--- a/app/assets/javascripts/content_editor/extensions/image.js
+++ b/app/assets/javascripts/content_editor/extensions/image.js
@@ -34,6 +34,7 @@ export default Image.extend({
canonicalSrc: {
default: null,
parseHTML: (element) => element.dataset.canonicalSrc,
+ renderHTML: () => '',
},
alt: {
default: null,
@@ -51,6 +52,10 @@ export default Image.extend({
return img.getAttribute('title');
},
},
+ isReference: {
+ default: false,
+ renderHTML: () => '',
+ },
};
},
parseHTML() {
@@ -71,7 +76,6 @@ export default Image.extend({
src: HTMLAttributes.src,
alt: HTMLAttributes.alt,
title: HTMLAttributes.title,
- 'data-canonical-src': HTMLAttributes.canonicalSrc,
},
];
},
diff --git a/app/assets/javascripts/content_editor/extensions/link.js b/app/assets/javascripts/content_editor/extensions/link.js
index f9b12f631fe..e985e561fda 100644
--- a/app/assets/javascripts/content_editor/extensions/link.js
+++ b/app/assets/javascripts/content_editor/extensions/link.js
@@ -56,6 +56,11 @@ export default Link.extend({
canonicalSrc: {
default: null,
parseHTML: (element) => element.dataset.canonicalSrc,
+ renderHTML: () => '',
+ },
+ isReference: {
+ default: false,
+ renderHTML: () => '',
},
};
},
diff --git a/app/assets/javascripts/content_editor/extensions/reference_definition.js b/app/assets/javascripts/content_editor/extensions/reference_definition.js
new file mode 100644
index 00000000000..e2762fe9fd9
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/reference_definition.js
@@ -0,0 +1,29 @@
+import { Node } from '@tiptap/core';
+
+export default Node.create({
+ name: 'referenceDefinition',
+
+ group: 'block',
+
+ content: 'text*',
+
+ marks: '',
+
+ addAttributes() {
+ return {
+ identifier: {
+ default: null,
+ },
+ url: {
+ default: null,
+ },
+ title: {
+ default: null,
+ },
+ };
+ },
+
+ renderHTML() {
+ return ['pre', {}, 0];
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/sourcemap.js b/app/assets/javascripts/content_editor/extensions/sourcemap.js
index 618f17b1c5e..f9de71f601b 100644
--- a/app/assets/javascripts/content_editor/extensions/sourcemap.js
+++ b/app/assets/javascripts/content_editor/extensions/sourcemap.js
@@ -6,6 +6,7 @@ import Code from './code';
import CodeBlockHighlight from './code_block_highlight';
import FootnoteReference from './footnote_reference';
import FootnoteDefinition from './footnote_definition';
+import Frontmatter from './frontmatter';
import Heading from './heading';
import HardBreak from './hard_break';
import HorizontalRule from './horizontal_rule';
@@ -16,6 +17,7 @@ import Link from './link';
import ListItem from './list_item';
import OrderedList from './ordered_list';
import Paragraph from './paragraph';
+import ReferenceDefinition from './reference_definition';
import Strike from './strike';
import TaskList from './task_list';
import TaskItem from './task_item';
@@ -36,6 +38,7 @@ export default Extension.create({
CodeBlockHighlight.name,
FootnoteReference.name,
FootnoteDefinition.name,
+ Frontmatter.name,
HardBreak.name,
Heading.name,
HorizontalRule.name,
@@ -45,6 +48,7 @@ export default Extension.create({
ListItem.name,
OrderedList.name,
Paragraph.name,
+ ReferenceDefinition.name,
Strike.name,
TaskList.name,
TaskItem.name,
diff --git a/app/assets/javascripts/content_editor/extensions/table_of_contents.js b/app/assets/javascripts/content_editor/extensions/table_of_contents.js
index a8882f9ede4..f64ed67199f 100644
--- a/app/assets/javascripts/content_editor/extensions/table_of_contents.js
+++ b/app/assets/javascripts/content_editor/extensions/table_of_contents.js
@@ -1,6 +1,8 @@
import { Node, InputRule } from '@tiptap/core';
-import { s__ } from '~/locale';
+import { VueNodeViewRenderer } from '@tiptap/vue-2';
+import { __ } from '~/locale';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
+import TableOfContentsWrapper from '../components/wrappers/table_of_contents.vue';
export default Node.create({
name: 'tableOfContents',
@@ -25,9 +27,18 @@ export default Node.create({
class:
'table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5',
},
- s__('ContentEditor|Table of Contents'),
+ __('Table of contents'),
];
},
+ addNodeView() {
+ return VueNodeViewRenderer(TableOfContentsWrapper);
+ },
+
+ addCommands() {
+ return {
+ insertTableOfContents: () => ({ commands }) => commands.insertContent({ type: this.name }),
+ };
+ },
addInputRules() {
const { type } = this;
diff --git a/app/assets/javascripts/content_editor/services/content_editor.js b/app/assets/javascripts/content_editor/services/content_editor.js
index 867bf0b4d55..75d8581890f 100644
--- a/app/assets/javascripts/content_editor/services/content_editor.js
+++ b/app/assets/javascripts/content_editor/services/content_editor.js
@@ -1,4 +1,3 @@
-import { TextSelection } from 'prosemirror-state';
import { LOADING_CONTENT_EVENT, LOADING_SUCCESS_EVENT, LOADING_ERROR_EVENT } from '../constants';
/* eslint-disable no-underscore-dangle */
@@ -59,7 +58,6 @@ export class ContentEditor {
async setSerializedContent(serializedContent) {
const { _tiptapEditor: editor, _eventHub: eventHub } = this;
const { doc, tr } = editor.state;
- const selection = TextSelection.create(doc, 0, doc.content.size);
try {
eventHub.$emit(LOADING_CONTENT_EVENT);
@@ -67,9 +65,7 @@ export class ContentEditor {
if (document) {
this._pristineDoc = document;
- tr.setSelection(selection)
- .replaceSelectionWith(document, false)
- .setMeta('preventUpdate', true);
+ tr.replaceWith(0, doc.content.size, document).setMeta('preventUpdate', true);
editor.view.dispatch(tr);
}
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 c5cfa9a4285..7a289df94ea 100644
--- a/app/assets/javascripts/content_editor/services/create_content_editor.js
+++ b/app/assets/javascripts/content_editor/services/create_content_editor.js
@@ -1,6 +1,5 @@
import { Editor } from '@tiptap/vue-2';
import { isFunction } from 'lodash';
-import { lowlight } from 'lowlight/lib/core';
import eventHubFactory from '~/helpers/event_hub_factory';
import { PROVIDE_SERIALIZER_OR_RENDERER_ERROR } from '../constants';
import Attachment from '../extensions/attachment';
@@ -43,6 +42,7 @@ import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph';
import PasteMarkdown from '../extensions/paste_markdown';
import Reference from '../extensions/reference';
+import ReferenceDefinition from '../extensions/reference_definition';
import Sourcemap from '../extensions/sourcemap';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
@@ -96,7 +96,7 @@ export const createContentEditor = ({
BulletList,
Code,
ColorChip,
- CodeBlockHighlight.configure({ lowlight }),
+ CodeBlockHighlight,
DescriptionItem,
DescriptionList,
Details,
@@ -110,7 +110,7 @@ export const createContentEditor = ({
FootnoteDefinition,
FootnoteReference,
FootnotesSection,
- Frontmatter.configure({ lowlight }),
+ Frontmatter,
Gapcursor,
HardBreak,
Heading,
@@ -127,8 +127,9 @@ export const createContentEditor = ({
MathInline,
OrderedList,
Paragraph,
- PasteMarkdown.configure({ renderMarkdown, eventHub }),
+ PasteMarkdown,
Reference,
+ ReferenceDefinition,
Sourcemap,
Strike,
Subscript,
diff --git a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
index 312ab88de4a..28a50adca6b 100644
--- a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
+++ b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
@@ -21,7 +21,7 @@
import { Mark } from 'prosemirror-model';
import { visitParents, SKIP } from 'unist-util-visit-parents';
-import { isFunction, isString, noop } from 'lodash';
+import { isFunction, isString, noop, mapValues } from 'lodash';
const NO_ATTRIBUTES = {};
@@ -73,28 +73,48 @@ function createSourceMapAttributes(hastNode, markdown) {
}
/**
- * Compute ProseMirror node’s attributes from a Hast node.
- * By default, this function includes sourcemap position
- * information in the object returned.
- *
- * Other attributes are retrieved by invoking a getAttrs
- * function provided by the ProseMirror node factory spec.
- *
- * @param {*} proseMirrorNodeSpec ProseMirror node spec object
- * @param {HastNode} hastNode A hast node
- * @param {Array<HastNode>} hastParents All the ancestors of the hastNode
- * @param {String} markdown Markdown source file’s content
- *
- * @returns An object that contains a ProseMirror node’s attributes
+ * Creates a function that resolves the attributes
+ * of a ProseMirror node based on a hast node.
+ *
+ * @param {Object} params Parameters
+ * @param {String} params.markdown Markdown source from which the AST was generated
+ * @param {Object} params.attributeTransformer An object that allows applying a transformation
+ * function to all the attributes listed in the attributes property.
+ * @param {Array} params.attributeTransformer.attributes A list of attributes names
+ * that the getAttrs function should apply the transformation
+ * @param {Function} params.attributeTransformer.transform A function that applies
+ * a transform operation on an attribute value.
+ * @returns A `getAttrs` function
*/
-function getAttrs(proseMirrorNodeSpec, hastNode, hastParents, markdown) {
- const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
+const getAttrsFactory = ({ attributeTransformer, markdown }) =>
+ /**
+ * Compute ProseMirror node’s attributes from a Hast node.
+ * By default, this function includes sourcemap position
+ * information in the object returned.
+ *
+ * Other attributes are retrieved by invoking a getAttrs
+ * function provided by the ProseMirror node factory spec.
+ *
+ * @param {Object} proseMirrorNodeSpec ProseMirror node spec object
+ * @param {Object} hastNode A hast node
+ * @param {Array} hastParents All the ancestors of the hastNode
+ * @param {String} markdown Markdown source file’s content
+ * @returns An object that contains a ProseMirror node’s attributes
+ */
+ function getAttrs(proseMirrorNodeSpec, hastNode, hastParents) {
+ const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
+ const attributes = {
+ ...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
+ };
+ const { transform } = attributeTransformer;
- return {
- ...createSourceMapAttributes(hastNode, markdown),
- ...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
+ return {
+ ...createSourceMapAttributes(hastNode, markdown),
+ ...mapValues(attributes, (attributeValue, attributeName) =>
+ transform(attributeName, attributeValue, hastNode),
+ ),
+ };
};
-}
/**
* Keeps track of the Hast -> ProseMirror conversion process.
@@ -322,7 +342,13 @@ class HastToProseMirrorConverterState {
*
* @returns An object that contains ProseMirror node factories
*/
-const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdown) => {
+const createProseMirrorNodeFactories = (
+ schema,
+ proseMirrorFactorySpecs,
+ attributeTransformer,
+ markdown,
+) => {
+ const getAttrs = getAttrsFactory({ attributeTransformer, markdown });
const factories = {
root: {
selector: 'root',
@@ -355,20 +381,20 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdow
const nodeType = schema.nodeType(proseMirrorName);
state.closeUntil(parent);
- state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+ state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
};
} else if (factory.type === 'inline') {
const nodeType = schema.nodeType(proseMirrorName);
factory.handle = (state, hastNode, parent) => {
state.closeUntil(parent);
- state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+ state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
// Inline nodes do not have children therefore they are immediately closed
state.closeNode();
};
} else if (factory.type === 'mark') {
const markType = schema.marks[proseMirrorName];
factory.handle = (state, hastNode, parent) => {
- state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+ state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent), factory);
};
} else if (factory.type === 'ignore') {
factory.handle = noop;
@@ -581,9 +607,15 @@ export const createProseMirrorDocFromMdastTree = ({
factorySpecs,
wrappableTags,
tree,
+ attributeTransformer,
markdown,
}) => {
- const proseMirrorNodeFactories = createProseMirrorNodeFactories(schema, factorySpecs, markdown);
+ const proseMirrorNodeFactories = createProseMirrorNodeFactories(
+ schema,
+ factorySpecs,
+ attributeTransformer,
+ markdown,
+ );
const state = new HastToProseMirrorConverterState();
visitParents(tree, (hastNode, ancestors) => {
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index c1c7af6b1af..472a0a4815b 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 ReferenceDefinition from '../extensions/reference_definition';
import Strike from '../extensions/strike';
import Subscript from '../extensions/subscript';
import Superscript from '../extensions/superscript';
@@ -148,10 +149,13 @@ const defaultSerializerConfig = {
state.renderInline(node);
state.ensureNewLine();
}),
- [FootnoteReference.name]: preserveUnchanged((state, node) => {
- state.write(`[^${node.attrs.identifier}]`);
+ [FootnoteReference.name]: preserveUnchanged({
+ render: (state, node) => {
+ state.write(`[^${node.attrs.identifier}]`);
+ },
+ inline: true,
}),
- [Frontmatter.name]: (state, node) => {
+ [Frontmatter.name]: preserveUnchanged((state, node) => {
const { language } = node.attrs;
const syntax = {
toml: '+++',
@@ -164,19 +168,41 @@ const defaultSerializerConfig = {
state.ensureNewLine();
state.write(syntax);
state.closeBlock(node);
- },
+ }),
[Figure.name]: renderHTMLNode('figure'),
[FigureCaption.name]: renderHTMLNode('figcaption'),
[HardBreak.name]: preserveUnchanged(renderHardBreak),
[Heading.name]: preserveUnchanged(defaultMarkdownSerializer.nodes.heading),
[HorizontalRule.name]: preserveUnchanged(defaultMarkdownSerializer.nodes.horizontal_rule),
- [Image.name]: preserveUnchanged(renderImage),
+ [Image.name]: preserveUnchanged({
+ render: renderImage,
+ inline: true,
+ }),
[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);
},
+ [ReferenceDefinition.name]: preserveUnchanged({
+ render: (state, node, parent, index, same, sourceMarkdown) => {
+ const nextSibling = parent.maybeChild(index + 1);
+
+ state.text(same ? sourceMarkdown : node.textContent, false);
+
+ /**
+ * Do not insert a blank line between reference definitions
+ * because it isn’t necessary and a more compact text format
+ * is preferred.
+ */
+ if (!nextSibling || nextSibling.type.name !== ReferenceDefinition.name) {
+ state.closeBlock(node);
+ } else {
+ state.ensureNewLine();
+ }
+ },
+ overwriteSourcePreservationStrategy: true,
+ }),
[TableOfContents.name]: (state, node) => {
state.write('[[_TOC_]]');
state.closeBlock(node);
diff --git a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
index 8e2c066e011..8a15633708f 100644
--- a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
+++ b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
@@ -1,4 +1,5 @@
import { render } from '~/lib/gfm';
+import { isValidAttribute } from '~/lib/dompurify';
import { createProseMirrorDocFromMdastTree } from './hast_to_prosemirror_converter';
const wrappableTags = ['img', 'br', 'code', 'i', 'em', 'b', 'strong', 'a', 'strike', 's', 'del'];
@@ -125,6 +126,8 @@ const factorySpecs = {
selector: 'img',
getAttrs: (hastNode) => ({
src: hastNode.properties.src,
+ canonicalSrc: hastNode.properties.identifier ?? hastNode.properties.src,
+ isReference: hastNode.properties.isReference === 'true',
title: hastNode.properties.title,
alt: hastNode.properties.alt,
}),
@@ -154,7 +157,9 @@ const factorySpecs = {
type: 'mark',
selector: 'a',
getAttrs: (hastNode) => ({
+ canonicalSrc: hastNode.properties.identifier ?? hastNode.properties.href,
href: hastNode.properties.href,
+ isReference: hastNode.properties.isReference === 'true',
title: hastNode.properties.title,
}),
},
@@ -170,6 +175,55 @@ const factorySpecs = {
type: 'ignore',
selector: (hastNode) => hastNode.type === 'comment',
},
+
+ referenceDefinition: {
+ type: 'block',
+ selector: 'referencedefinition',
+ getAttrs: (hastNode) => ({
+ title: hastNode.properties.title,
+ url: hastNode.properties.url,
+ identifier: hastNode.properties.identifier,
+ }),
+ },
+
+ frontmatter: {
+ type: 'block',
+ selector: 'frontmatter',
+ getAttrs: (hastNode) => ({
+ language: hastNode.properties.language,
+ }),
+ },
+};
+
+const SANITIZE_ALLOWLIST = ['level', 'identifier', 'numeric', 'language', 'url', 'isReference'];
+
+const sanitizeAttribute = (attributeName, attributeValue, hastNode) => {
+ if (!attributeValue || SANITIZE_ALLOWLIST.includes(attributeName)) {
+ return attributeValue;
+ }
+
+ /**
+ * This is a workaround to validate the value of the canonicalSrc
+ * attribute using DOMPurify without passing the attribute name. canonicalSrc
+ * is not an allowed attribute in DOMPurify therefore the library will remove
+ * it regardless of its value.
+ *
+ * We want to preserve canonicalSrc, and we also want to make sure that its
+ * value is sanitized.
+ */
+ const validateAttributeAs = attributeName === 'canonicalSrc' ? 'src' : attributeName;
+
+ if (!isValidAttribute(hastNode.tagName, validateAttributeAs, attributeValue)) {
+ return null;
+ }
+
+ return attributeValue;
+};
+
+const attributeTransformer = {
+ transform: (attributeName, attributeValue, hastNode) => {
+ return sanitizeAttribute(attributeName, attributeValue, hastNode);
+ },
};
export default () => {
@@ -183,9 +237,20 @@ export default () => {
factorySpecs,
tree,
wrappableTags,
+ attributeTransformer,
markdown,
}),
- skipRendering: ['footnoteReference', 'footnoteDefinition', 'code'],
+ skipRendering: [
+ 'footnoteReference',
+ 'footnoteDefinition',
+ 'code',
+ 'definition',
+ 'linkReference',
+ 'imageReference',
+ 'yaml',
+ 'toml',
+ 'json',
+ ],
});
return { document };
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index 7d5e718b41c..41114571df7 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -1,4 +1,5 @@
-import { uniq, isString, omit } from 'lodash';
+import { uniq, isString, omit, isFunction } from 'lodash';
+import { removeLastSlashInUrlPath, removeUrlProtocol } from '../../lib/utils/url_utility';
const defaultAttrs = {
td: { colspan: 1, rowspan: 1, colwidth: null },
@@ -306,12 +307,15 @@ export function renderHardBreak(state, node, parent, index) {
}
export function renderImage(state, node) {
- const { alt, canonicalSrc, src, title } = node.attrs;
+ const { alt, canonicalSrc, src, title, isReference } = node.attrs;
if (isString(src) || isString(canonicalSrc)) {
const quotedTitle = title ? ` ${state.quote(title)}` : '';
+ const sourceExpression = isReference
+ ? `[${canonicalSrc}]`
+ : `(${state.esc(canonicalSrc || src)}${quotedTitle})`;
- state.write(`![${state.esc(alt || '')}](${state.esc(canonicalSrc || src)}${quotedTitle})`);
+ state.write(`![${state.esc(alt || '')}]${sourceExpression}`);
}
}
@@ -327,16 +331,28 @@ export function renderCodeBlock(state, node) {
state.closeBlock(node);
}
-export function preserveUnchanged(render) {
+const expandPreserveUnchangedConfig = (configOrRender) =>
+ isFunction(configOrRender)
+ ? { render: configOrRender, overwriteSourcePreservationStrategy: false, inline: false }
+ : configOrRender;
+
+export function preserveUnchanged(configOrRender) {
return (state, node, parent, index) => {
+ const { render, overwriteSourcePreservationStrategy, inline } = expandPreserveUnchangedConfig(
+ configOrRender,
+ );
+
const { sourceMarkdown } = node.attrs;
const same = state.options.changeTracker.get(node);
- if (same) {
+ if (same && !overwriteSourcePreservationStrategy) {
state.write(sourceMarkdown);
- state.closeBlock(node);
+
+ if (!inline) {
+ state.closeBlock(node);
+ }
} else {
- render(state, node, parent, index);
+ render(state, node, parent, index, same, sourceMarkdown);
}
};
}
@@ -488,24 +504,16 @@ const linkType = (sourceMarkdown) => {
return LINK_HTML;
};
-const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
-
-const normalizeUrl = (url) => decodeURIComponent(removeUrlProtocol(url));
+const normalizeUrl = (url) => decodeURIComponent(removeLastSlashInUrlPath(removeUrlProtocol(url)));
/**
- * Validates that the provided URL is well-formed
+ * Validates that the provided URL is a valid GFM autolink
*
* @param {String} url
- * @returns Returns true when the browser’s URL constructor
- * can successfully parse the URL string
+ * @returns Returns true when the URL is a valid GFM autolink
*/
-const isValidUrl = (url) => {
- try {
- return new URL(url) && true;
- } catch {
- return false;
- }
-};
+const isValidAutolinkURL = (url) =>
+ /(https?:\/\/)?([\w-])+\.{1}([a-zA-Z]{2,63})([/\w-]*)*\/?\??([^#\n\r]*)?#?([^\n\r]*)/.test(url);
const findChildWithMark = (mark, parent) => {
let child;
@@ -542,7 +550,7 @@ const isAutoLink = (linkMark, parent) => {
if (
!child ||
!child.isText ||
- !isValidUrl(href) ||
+ !isValidAutolinkURL(href) ||
normalizeUrl(child.text) !== normalizeUrl(href)
) {
return false;
@@ -582,7 +590,11 @@ export const link = {
return isBracketAutoLink(mark.attrs.sourceMarkdown) ? '>' : '';
}
- const { canonicalSrc, href, title, sourceMarkdown } = mark.attrs;
+ const { canonicalSrc, href, title, sourceMarkdown, isReference } = mark.attrs;
+
+ if (isReference) {
+ return `][${state.esc(canonicalSrc || href)}]`;
+ }
if (linkType(sourceMarkdown) === LINK_HTML) {
return closeTag('a');
diff --git a/app/assets/javascripts/content_editor/services/table_of_contents_utils.js b/app/assets/javascripts/content_editor/services/table_of_contents_utils.js
new file mode 100644
index 00000000000..dad917b2270
--- /dev/null
+++ b/app/assets/javascripts/content_editor/services/table_of_contents_utils.js
@@ -0,0 +1,67 @@
+export function fillEmpty(headings) {
+ for (let i = 0; i < headings.length; i += 1) {
+ let j = headings[i - 1]?.level || 0;
+ if (headings[i].level - j > 1) {
+ while (j < headings[i].level) {
+ headings.splice(i, 0, { level: j + 1, text: '' });
+ j += 1;
+ }
+ }
+ }
+
+ return headings;
+}
+
+const exitHeadingBranch = (heading, targetLevel) => {
+ let currentHeading = heading;
+
+ while (currentHeading.level > targetLevel) {
+ currentHeading = currentHeading.parent;
+ }
+
+ return currentHeading;
+};
+
+export function toTree(headings) {
+ fillEmpty(headings);
+
+ const tree = [];
+ let currentHeading;
+ for (let i = 0; i < headings.length; i += 1) {
+ const heading = headings[i];
+ if (heading.level === 1) {
+ const h = { ...heading, subHeadings: [] };
+ tree.push(h);
+ currentHeading = h;
+ } else if (heading.level > currentHeading.level) {
+ const h = { ...heading, subHeadings: [], parent: currentHeading };
+ currentHeading.subHeadings.push(h);
+ currentHeading = h;
+ } else if (heading.level <= currentHeading.level) {
+ currentHeading = exitHeadingBranch(currentHeading, heading.level - 1);
+
+ const h = { ...heading, subHeadings: [], parent: currentHeading };
+ (currentHeading?.subHeadings || headings).push(h);
+ currentHeading = h;
+ }
+ }
+
+ return tree;
+}
+
+export function getHeadings(editor) {
+ const headings = [];
+
+ editor.state.doc.descendants((node) => {
+ if (node.type.name !== 'heading') return false;
+
+ headings.push({
+ level: node.attrs.level,
+ text: node.textContent,
+ });
+
+ return true;
+ });
+
+ return toTree(headings);
+}
diff --git a/app/assets/javascripts/contributors/stores/getters.js b/app/assets/javascripts/contributors/stores/getters.js
index 79f5c701fb8..8b432b2041a 100644
--- a/app/assets/javascripts/contributors/stores/getters.js
+++ b/app/assets/javascripts/contributors/stores/getters.js
@@ -4,15 +4,15 @@ export const parsedData = (state) => {
const byAuthorEmail = {};
const total = {};
- state.chartData.forEach(({ date, author_name, author_email }) => {
+ state.chartData.forEach(({ date, author_name: name, author_email: email }) => {
total[date] = total[date] ? total[date] + 1 : 1;
- const normalizedEmail = author_email.toLowerCase();
+ const normalizedEmail = email.toLowerCase();
const authorData = byAuthorEmail[normalizedEmail];
if (!authorData) {
byAuthorEmail[normalizedEmail] = {
- name: author_name,
+ name,
commits: 1,
dates: {
[date]: 1,
diff --git a/app/assets/javascripts/crm/components/form.vue b/app/assets/javascripts/crm/components/form.vue
index 72def54aedf..ea6a6892bbd 100644
--- a/app/assets/javascripts/crm/components/form.vue
+++ b/app/assets/javascripts/crm/components/form.vue
@@ -1,5 +1,13 @@
<script>
-import { GlAlert, GlButton, GlDrawer, GlFormGroup, GlFormInput, GlFormSelect } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlButton,
+ GlDrawer,
+ GlFormCheckbox,
+ GlFormGroup,
+ GlFormInput,
+ GlFormSelect,
+} from '@gitlab/ui';
import { get as getPropValueByPath, isEmpty } from 'lodash';
import { produce } from 'immer';
import { MountingPortal } from 'portal-vue';
@@ -26,6 +34,7 @@ export default {
GlAlert,
GlButton,
GlDrawer,
+ GlFormCheckbox,
GlFormGroup,
GlFormInput,
GlFormSelect,
@@ -113,7 +122,9 @@ export default {
const { fields, model } = this;
return fields.some((field) => {
- return field.required && isEmpty(model[field.name]);
+ return (
+ field.required && isEmpty(model[field.name]) && typeof model[field.name] !== 'boolean'
+ );
});
},
variables() {
@@ -216,6 +227,8 @@ export default {
});
},
getFieldLabel(field) {
+ if (field.bool) return null;
+
const optionalSuffix = field.required ? '' : ` ${MSG_OPTIONAL}`;
return field.label + optionalSuffix;
},
@@ -273,6 +286,9 @@ export default {
v-model="model[field.name]"
:options="field.values"
/>
+ <gl-form-checkbox v-else-if="field.bool" :id="field.name" v-model="model[field.name]"
+ ><span class="gl-font-weight-bold">{{ field.label }}</span></gl-form-checkbox
+ >
<gl-form-input v-else :id="field.name" v-bind="field.input" v-model="model[field.name]" />
</gl-form-group>
<span class="gl-float-right">
diff --git a/app/assets/javascripts/crm/constants.js b/app/assets/javascripts/crm/constants.js
index 3b085837aea..815289e075e 100644
--- a/app/assets/javascripts/crm/constants.js
+++ b/app/assets/javascripts/crm/constants.js
@@ -1,3 +1,7 @@
export const INDEX_ROUTE_NAME = 'index';
export const NEW_ROUTE_NAME = 'new';
export const EDIT_ROUTE_NAME = 'edit';
+export const trackViewsOptions = {
+ category: 'Customer Relations' /* eslint-disable-line @gitlab/require-i18n-strings */,
+ action: 'view_contacts_list',
+};
diff --git a/app/assets/javascripts/crm/contacts/bundle.js b/app/assets/javascripts/crm/contacts/bundle.js
index f49ec64210f..fe62b7cfbe3 100644
--- a/app/assets/javascripts/crm/contacts/bundle.js
+++ b/app/assets/javascripts/crm/contacts/bundle.js
@@ -3,6 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
import createDefaultClient from '~/lib/graphql';
+import { parseBoolean } from '~/lib/utils/common_utils';
import CrmContactsRoot from './components/contacts_root.vue';
import routes from './routes';
@@ -21,7 +22,14 @@ export default () => {
return false;
}
- const { basePath, groupFullPath, groupIssuesPath, canAdminCrmContact, groupId } = el.dataset;
+ const {
+ basePath,
+ groupFullPath,
+ groupIssuesPath,
+ canAdminCrmContact,
+ groupId,
+ textQuery,
+ } = el.dataset;
const router = new VueRouter({
base: basePath,
@@ -33,7 +41,13 @@ export default () => {
el,
router,
apolloProvider,
- provide: { groupFullPath, groupIssuesPath, canAdminCrmContact, groupId },
+ provide: {
+ groupFullPath,
+ groupIssuesPath,
+ canAdminCrmContact: parseBoolean(canAdminCrmContact),
+ groupId,
+ textQuery,
+ },
render(createElement) {
return createElement(CrmContactsRoot);
},
diff --git a/app/assets/javascripts/crm/contacts/components/contact_form_wrapper.vue b/app/assets/javascripts/crm/contacts/components/contact_form_wrapper.vue
index f114ffedfe6..b29089519e2 100644
--- a/app/assets/javascripts/crm/contacts/components/contact_form_wrapper.vue
+++ b/app/assets/javascripts/crm/contacts/components/contact_form_wrapper.vue
@@ -57,7 +57,7 @@ export default {
getQuery() {
return {
query: getGroupContactsQuery,
- variables: { groupFullPath: this.groupFullPath },
+ variables: { groupFullPath: this.groupFullPath, ids: [this.contactGraphQLId] },
};
},
title() {
@@ -74,7 +74,7 @@ export default {
return { groupId: this.groupGraphQLId };
},
fields() {
- return [
+ const fields = [
{ name: 'firstName', label: __('First name'), required: true },
{ name: 'lastName', label: __('Last name'), required: true },
{ name: 'email', label: __('Email'), required: true },
@@ -86,6 +86,11 @@ export default {
},
{ name: 'description', label: __('Description') },
];
+
+ if (this.isEditMode)
+ fields.push({ name: 'active', label: s__('Crm|Active'), required: true, bool: true });
+
+ return fields;
},
organizationSelectValues() {
const values = this.organizations.map((o) => {
diff --git a/app/assets/javascripts/crm/contacts/components/contacts_root.vue b/app/assets/javascripts/crm/contacts/components/contacts_root.vue
index 9d6f34c73b7..562363ff88e 100644
--- a/app/assets/javascripts/crm/contacts/components/contacts_root.vue
+++ b/app/assets/javascripts/crm/contacts/components/contacts_root.vue
@@ -1,36 +1,54 @@
<script>
-import { GlAlert, GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
-import { parseBoolean } from '~/lib/utils/common_utils';
+import { GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { EDIT_ROUTE_NAME, NEW_ROUTE_NAME } from '../../constants';
-import getGroupContactsQuery from './graphql/get_group_contacts.query.graphql';
+import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
+import {
+ bodyTrClass,
+ initialPaginationState,
+} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
+import { convertToSnakeCase } from '~/lib/utils/text_utility';
+import { EDIT_ROUTE_NAME, NEW_ROUTE_NAME, trackViewsOptions } from '../../constants';
+import getGroupContacts from './graphql/get_group_contacts.query.graphql';
+import getGroupContactsCountByState from './graphql/get_group_contacts_count_by_state.graphql';
export default {
components: {
- GlAlert,
GlButton,
GlLoadingIcon,
GlTable,
+ PaginatedTableWithSearchAndTabs,
},
directives: {
GlTooltip: GlTooltipDirective,
},
- inject: ['canAdminCrmContact', 'groupFullPath', 'groupIssuesPath'],
+ inject: ['canAdminCrmContact', 'groupFullPath', 'groupIssuesPath', 'textQuery'],
data() {
return {
- contacts: [],
+ contacts: { list: [] },
+ contactsCount: {},
error: false,
+ filteredByStatus: '',
+ pagination: initialPaginationState,
+ statusFilter: 'all',
+ searchTerm: this.textQuery,
+ sort: 'LAST_NAME_ASC',
+ sortDesc: false,
};
},
apollo: {
contacts: {
- query() {
- return getGroupContactsQuery;
- },
+ query: getGroupContacts,
variables() {
return {
groupFullPath: this.groupFullPath,
+ searchTerm: this.searchTerm,
+ state: this.statusFilter,
+ sort: this.sort,
+ firstPageSize: this.pagination.firstPageSize,
+ lastPageSize: this.pagination.lastPageSize,
+ prevPageCursor: this.pagination.prevPageCursor,
+ nextPageCursor: this.pagination.nextPageCursor,
};
},
update(data) {
@@ -40,19 +58,52 @@ export default {
this.error = true;
},
},
+ contactsCount: {
+ query: getGroupContactsCountByState,
+ variables() {
+ return {
+ groupFullPath: this.groupFullPath,
+ searchTerm: this.searchTerm,
+ };
+ },
+ update(data) {
+ return data?.group?.contactStateCounts;
+ },
+ error() {
+ this.error = true;
+ },
+ },
},
computed: {
isLoading() {
return this.$apollo.queries.contacts.loading;
},
- canAdmin() {
- return parseBoolean(this.canAdminCrmContact);
+ tbodyTrClass() {
+ return {
+ [bodyTrClass]: !this.loading && !this.isEmpty,
+ };
},
},
methods: {
+ errorAlertDismissed() {
+ this.error = true;
+ },
extractContacts(data) {
const contacts = data?.group?.contacts?.nodes || [];
- return contacts.slice().sort((a, b) => a.firstName.localeCompare(b.firstName));
+ const pageInfo = data?.group?.contacts?.pageInfo || {};
+ return {
+ list: contacts,
+ pageInfo,
+ };
+ },
+ fetchSortedData({ sortBy, sortDesc }) {
+ const sortingColumn = convertToSnakeCase(sortBy).toUpperCase();
+ const sortingDirection = sortDesc ? 'DESC' : 'ASC';
+ this.pagination = initialPaginationState;
+ this.sort = `${sortingColumn}_${sortingDirection}`;
+ },
+ filtersChanged({ searchTerm }) {
+ this.searchTerm = searchTerm;
},
getIssuesPath(path, value) {
return `${path}?crm_contact_id=${value}`;
@@ -60,6 +111,13 @@ export default {
getEditRoute(id) {
return { name: this.$options.EDIT_ROUTE_NAME, params: { id } };
},
+ pageChanged(pagination) {
+ this.pagination = pagination;
+ },
+ statusChanged({ filters, status }) {
+ this.statusFilter = filters;
+ this.filteredByStatus = status;
+ },
},
fields: [
{ key: 'firstName', sortable: true },
@@ -92,57 +150,109 @@ export default {
},
EDIT_ROUTE_NAME,
NEW_ROUTE_NAME,
+ statusTabs: [
+ {
+ title: __('Active'),
+ status: 'ACTIVE',
+ filters: 'active',
+ },
+ {
+ title: __('Inactive'),
+ status: 'INACTIVE',
+ filters: 'inactive',
+ },
+ {
+ title: __('All'),
+ status: 'ALL',
+ filters: 'all',
+ },
+ ],
+ trackViewsOptions,
+ emptyArray: [],
};
</script>
<template>
<div>
- <gl-alert v-if="error" variant="danger" class="gl-mt-6" @dismiss="error = false">
- {{ $options.i18n.errorText }}
- </gl-alert>
- <div
- class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
+ <paginated-table-with-search-and-tabs
+ :show-items="true"
+ :show-error-msg="false"
+ :i18n="$options.i18n"
+ :items="contacts.list"
+ :page-info="contacts.pageInfo"
+ :items-count="contactsCount"
+ :status-tabs="$options.statusTabs"
+ :track-views-options="$options.trackViewsOptions"
+ :filter-search-tokens="$options.emptyArray"
+ filter-search-key="contacts"
+ @page-changed="pageChanged"
+ @tabs-changed="statusChanged"
+ @filters-changed="filtersChanged"
+ @error-alert-dismissed="errorAlertDismissed"
>
- <h2 class="gl-font-size-h2 gl-my-0">
- {{ $options.i18n.title }}
- </h2>
- <div v-if="canAdmin">
- <router-link :to="{ name: $options.NEW_ROUTE_NAME }">
- <gl-button variant="confirm" data-testid="new-contact-button">
+ <template #header-actions>
+ <router-link v-if="canAdminCrmContact" :to="{ name: $options.NEW_ROUTE_NAME }">
+ <gl-button class="gl-my-3 gl-mr-5" variant="confirm" data-testid="new-contact-button">
{{ $options.i18n.newContact }}
</gl-button>
</router-link>
- </div>
- </div>
- <router-view />
- <gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
- <gl-table
- v-else
- class="gl-mt-5"
- :items="contacts"
- :fields="$options.fields"
- :empty-text="$options.i18n.emptyText"
- show-empty
- >
- <template #cell(id)="{ value: id }">
- <gl-button
- v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
- class="gl-mr-3"
- data-testid="issues-link"
- icon="issues"
- :aria-label="$options.i18n.issuesButtonLabel"
- :href="getIssuesPath(groupIssuesPath, id)"
- />
- <router-link :to="getEditRoute(id)">
- <gl-button
- v-if="canAdmin"
- v-gl-tooltip.hover.bottom="$options.i18n.editButtonLabel"
- data-testid="edit-contact-button"
- icon="pencil"
- :aria-label="$options.i18n.editButtonLabel"
- />
- </router-link>
</template>
- </gl-table>
+
+ <template #title>
+ {{ $options.i18n.title }}
+ </template>
+
+ <template #table>
+ <gl-table
+ :items="contacts.list"
+ :fields="$options.fields"
+ :busy="isLoading"
+ stacked="md"
+ :tbody-tr-class="tbodyTrClass"
+ sort-direction="asc"
+ :sort-desc.sync="sortDesc"
+ sort-by="createdAt"
+ show-empty
+ no-local-sorting
+ sort-icon-left
+ fixed
+ @sort-changed="fetchSortedData"
+ >
+ <template #cell(id)="{ value: id }">
+ <gl-button
+ v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
+ class="gl-mr-3"
+ data-testid="issues-link"
+ icon="issues"
+ :aria-label="$options.i18n.issuesButtonLabel"
+ :href="getIssuesPath(groupIssuesPath, id)"
+ />
+ <router-link :to="getEditRoute(id)">
+ <gl-button
+ v-if="canAdminCrmContact"
+ v-gl-tooltip.hover.bottom="$options.i18n.editButtonLabel"
+ data-testid="edit-contact-button"
+ icon="pencil"
+ :aria-label="$options.i18n.editButtonLabel"
+ />
+ </router-link>
+ </template>
+
+ <template #table-busy>
+ <gl-loading-icon size="lg" color="dark" class="mt-3" />
+ </template>
+
+ <template #empty>
+ <span v-if="error">
+ {{ $options.i18n.errorText }}
+ </span>
+ <span v-else>
+ {{ $options.i18n.emptyText }}
+ </span>
+ </template>
+ </gl-table>
+ </template>
+ </paginated-table-with-search-and-tabs>
+ <router-view />
</div>
</template>
diff --git a/app/assets/javascripts/crm/contacts/components/graphql/crm_contact_fields.fragment.graphql b/app/assets/javascripts/crm/contacts/components/graphql/crm_contact_fields.fragment.graphql
index cef4083b446..545ddbf5f72 100644
--- a/app/assets/javascripts/crm/contacts/components/graphql/crm_contact_fields.fragment.graphql
+++ b/app/assets/javascripts/crm/contacts/components/graphql/crm_contact_fields.fragment.graphql
@@ -1,13 +1,12 @@
fragment ContactFragment on CustomerRelationsContact {
- __typename
id
firstName
lastName
email
phone
description
+ active
organization {
- __typename
id
name
}
diff --git a/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts.query.graphql b/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts.query.graphql
index 2a8150e42e3..f04d02122fc 100644
--- a/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts.query.graphql
+++ b/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts.query.graphql
@@ -1,13 +1,37 @@
#import "./crm_contact_fields.fragment.graphql"
-query contacts($groupFullPath: ID!) {
+query contacts(
+ $groupFullPath: ID!
+ $state: CustomerRelationsContactState
+ $searchTerm: String
+ $sort: ContactSort
+ $firstPageSize: Int
+ $lastPageSize: Int
+ $prevPageCursor: String = ""
+ $nextPageCursor: String = ""
+ $ids: [CustomerRelationsContactID!]
+) {
group(fullPath: $groupFullPath) {
- __typename
id
- contacts {
+ contacts(
+ state: $state
+ search: $searchTerm
+ sort: $sort
+ first: $firstPageSize
+ last: $lastPageSize
+ after: $nextPageCursor
+ before: $prevPageCursor
+ ids: $ids
+ ) {
nodes {
...ContactFragment
}
+ pageInfo {
+ hasNextPage
+ endCursor
+ hasPreviousPage
+ startCursor
+ }
}
}
}
diff --git a/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts_count_by_state.graphql b/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts_count_by_state.graphql
new file mode 100644
index 00000000000..6b591240096
--- /dev/null
+++ b/app/assets/javascripts/crm/contacts/components/graphql/get_group_contacts_count_by_state.graphql
@@ -0,0 +1,11 @@
+query contactsCountByState($groupFullPath: ID!, $searchTerm: String) {
+ group(fullPath: $groupFullPath) {
+ __typename
+ id
+ contactStateCounts(search: $searchTerm) {
+ all
+ active
+ inactive
+ }
+ }
+}
diff --git a/app/assets/javascripts/crm/organizations/components/graphql/crm_organization_fields.fragment.graphql b/app/assets/javascripts/crm/organizations/components/graphql/crm_organization_fields.fragment.graphql
index 4adc5742d3a..d723bf32ef5 100644
--- a/app/assets/javascripts/crm/organizations/components/graphql/crm_organization_fields.fragment.graphql
+++ b/app/assets/javascripts/crm/organizations/components/graphql/crm_organization_fields.fragment.graphql
@@ -1,7 +1,7 @@
fragment OrganizationFragment on CustomerRelationsOrganization {
- __typename
id
name
defaultRate
description
+ active
}
diff --git a/app/assets/javascripts/crm/organizations/components/graphql/get_group_organizations.query.graphql b/app/assets/javascripts/crm/organizations/components/graphql/get_group_organizations.query.graphql
index e8d8109431e..97b75091cac 100644
--- a/app/assets/javascripts/crm/organizations/components/graphql/get_group_organizations.query.graphql
+++ b/app/assets/javascripts/crm/organizations/components/graphql/get_group_organizations.query.graphql
@@ -2,7 +2,6 @@
query organizations($groupFullPath: ID!) {
group(fullPath: $groupFullPath) {
- __typename
id
organizations {
nodes {
diff --git a/app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue b/app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue
index 38468e1f4e4..5fd0294b0ea 100644
--- a/app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue
+++ b/app/assets/javascripts/crm/organizations/components/organization_form_wrapper.vue
@@ -52,16 +52,23 @@ export default {
additionalCreateParams() {
return { groupId: this.groupGraphQLId };
},
- },
- fields: [
- { name: 'name', label: __('Name'), required: true },
- {
- name: 'defaultRate',
- label: s__('Crm|Default rate'),
- input: { type: 'number', step: '0.01' },
+ fields() {
+ const fields = [
+ { name: 'name', label: __('Name'), required: true },
+ {
+ name: 'defaultRate',
+ label: s__('Crm|Default rate'),
+ input: { type: 'number', step: '0.01' },
+ },
+ { name: 'description', label: __('Description') },
+ ];
+
+ if (this.isEditMode)
+ fields.push({ name: 'active', label: s__('Crm|Active'), required: true, bool: true });
+
+ return fields;
},
- { name: 'description', label: __('Description') },
- ],
+ },
};
</script>
@@ -73,7 +80,7 @@ export default {
:mutation="mutation"
:additional-create-params="additionalCreateParams"
:existing-id="organizationGraphQLId"
- :fields="$options.fields"
+ :fields="fields"
:title="title"
:success-message="successMessage"
/>
diff --git a/app/assets/javascripts/cycle_analytics/components/base.vue b/app/assets/javascripts/cycle_analytics/components/base.vue
index 1883030e51f..f06544f50c6 100644
--- a/app/assets/javascripts/cycle_analytics/components/base.vue
+++ b/app/assets/javascripts/cycle_analytics/components/base.vue
@@ -47,15 +47,13 @@ export default {
'selectedStage',
'selectedStageEvents',
'selectedStageError',
- 'stages',
- 'summary',
- 'permissions',
'stageCounts',
'endpoints',
'features',
'createdBefore',
'createdAfter',
'pagination',
+ 'hasNoAccessError',
]),
...mapGetters(['pathNavigationData', 'filterParams']),
isLoaded() {
@@ -69,9 +67,7 @@ export default {
return !this.isLoadingStage && this.isEmptyStage;
},
displayNoAccess() {
- return (
- !this.isLoadingStage && this.selectedStage?.id && !this.isUserAllowed(this.selectedStage.id)
- );
+ return !this.isLoadingStage && this.hasNoAccessError;
},
displayPathNavigation() {
return this.isLoading || (this.selectedStage && this.pathNavigationData.length);
@@ -137,10 +133,6 @@ export default {
this.isOverviewDialogDismissed = true;
setCookie(OVERVIEW_DIALOG_COOKIE, '1');
},
- isUserAllowed(id) {
- const { permissions } = this;
- return Boolean(permissions?.[id]);
- },
onHandleUpdatePagination(data) {
this.updateStageTablePagination(data);
},
diff --git a/app/assets/javascripts/cycle_analytics/store/actions.js b/app/assets/javascripts/cycle_analytics/store/actions.js
index e0156b24f9d..5c2e29bfa74 100644
--- a/app/assets/javascripts/cycle_analytics/store/actions.js
+++ b/app/assets/javascripts/cycle_analytics/store/actions.js
@@ -1,7 +1,6 @@
import {
getProjectValueStreamStages,
getProjectValueStreams,
- getProjectValueStreamMetrics,
getValueStreamStageMedian,
getValueStreamStageRecords,
getValueStreamStageCounts,
@@ -52,24 +51,6 @@ export const fetchValueStreams = ({ commit, dispatch, state }) => {
commit(types.RECEIVE_VALUE_STREAMS_ERROR, status);
});
};
-export const fetchCycleAnalyticsData = ({
- state: {
- endpoints: { requestPath },
- },
- getters: { legacyFilterParams },
- commit,
-}) => {
- commit(types.REQUEST_CYCLE_ANALYTICS_DATA);
-
- return getProjectValueStreamMetrics(requestPath, legacyFilterParams)
- .then(({ data }) => commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS, data))
- .catch(() => {
- commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR);
- createFlash({
- message: __('There was an error while fetching value stream summary data.'),
- });
- });
-};
export const fetchStageData = ({
getters: { requestParams, filterParams, paginationParams },
@@ -153,7 +134,6 @@ export const fetchStageCountValues = ({
export const fetchValueStreamStageData = ({ dispatch }) =>
Promise.all([
- dispatch('fetchCycleAnalyticsData'),
dispatch('fetchStageData'),
dispatch('fetchStageMedians'),
dispatch('fetchStageCountValues'),
@@ -178,6 +158,11 @@ export const setDateRange = ({ dispatch, commit }, { createdAfter, createdBefore
};
export const setInitialStage = ({ dispatch, commit, state: { stages } }, stage) => {
+ if (!stages.length && !stage) {
+ commit(types.SET_NO_ACCESS_ERROR);
+ return null;
+ }
+
const selectedStage = stage || stages[0];
commit(types.SET_SELECTED_STAGE, selectedStage);
return dispatch('fetchValueStreamStageData');
diff --git a/app/assets/javascripts/cycle_analytics/store/getters.js b/app/assets/javascripts/cycle_analytics/store/getters.js
index 962e1d50d12..6fe353405d4 100644
--- a/app/assets/javascripts/cycle_analytics/store/getters.js
+++ b/app/assets/javascripts/cycle_analytics/store/getters.js
@@ -49,12 +49,6 @@ const dateRangeParams = ({ createdAfter, createdBefore }) => ({
created_before: createdBefore ? dateFormat(createdBefore, dateFormats.isoDate) : null,
});
-export const legacyFilterParams = ({ daysInPast }) => {
- return {
- 'cycle_analytics[start_date]': daysInPast,
- };
-};
-
export const filterParams = (state) => {
return {
...filterBarParams(state),
diff --git a/app/assets/javascripts/cycle_analytics/store/mutation_types.js b/app/assets/javascripts/cycle_analytics/store/mutation_types.js
index 0ad67d4e6bd..9376d81f317 100644
--- a/app/assets/javascripts/cycle_analytics/store/mutation_types.js
+++ b/app/assets/javascripts/cycle_analytics/store/mutation_types.js
@@ -5,6 +5,7 @@ export const SET_SELECTED_VALUE_STREAM = 'SET_SELECTED_VALUE_STREAM';
export const SET_SELECTED_STAGE = 'SET_SELECTED_STAGE';
export const SET_DATE_RANGE = 'SET_DATE_RANGE';
export const SET_PAGINATION = 'SET_PAGINATION';
+export const SET_NO_ACCESS_ERROR = 'SET_NO_ACCESS_ERROR';
export const REQUEST_VALUE_STREAMS = 'REQUEST_VALUE_STREAMS';
export const RECEIVE_VALUE_STREAMS_SUCCESS = 'RECEIVE_VALUE_STREAMS_SUCCESS';
@@ -14,10 +15,6 @@ export const REQUEST_VALUE_STREAM_STAGES = 'REQUEST_VALUE_STREAM_STAGES';
export const RECEIVE_VALUE_STREAM_STAGES_SUCCESS = 'RECEIVE_VALUE_STREAM_STAGES_SUCCESS';
export const RECEIVE_VALUE_STREAM_STAGES_ERROR = 'RECEIVE_VALUE_STREAM_STAGES_ERROR';
-export const REQUEST_CYCLE_ANALYTICS_DATA = 'REQUEST_CYCLE_ANALYTICS_DATA';
-export const RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS = 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS';
-export const RECEIVE_CYCLE_ANALYTICS_DATA_ERROR = 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR';
-
export const REQUEST_STAGE_DATA = 'REQUEST_STAGE_DATA';
export const RECEIVE_STAGE_DATA_SUCCESS = 'RECEIVE_STAGE_DATA_SUCCESS';
export const RECEIVE_STAGE_DATA_ERROR = 'RECEIVE_STAGE_DATA_ERROR';
diff --git a/app/assets/javascripts/cycle_analytics/store/mutations.js b/app/assets/javascripts/cycle_analytics/store/mutations.js
index 64930a5b51f..8567529caf2 100644
--- a/app/assets/javascripts/cycle_analytics/store/mutations.js
+++ b/app/assets/javascripts/cycle_analytics/store/mutations.js
@@ -41,6 +41,9 @@ export default {
direction: direction || PAGINATION_SORT_DIRECTION_DESC,
});
},
+ [types.SET_NO_ACCESS_ERROR](state) {
+ state.hasNoAccessError = true;
+ },
[types.REQUEST_VALUE_STREAMS](state) {
state.valueStreams = [];
},
@@ -59,23 +62,12 @@ export default {
[types.RECEIVE_VALUE_STREAM_STAGES_ERROR](state) {
state.stages = [];
},
- [types.REQUEST_CYCLE_ANALYTICS_DATA](state) {
- state.isLoading = true;
- state.hasError = false;
- },
- [types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, data) {
- state.permissions = data?.permissions || {};
- state.hasError = false;
- },
- [types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR](state) {
- state.isLoading = false;
- state.hasError = true;
- },
[types.REQUEST_STAGE_DATA](state) {
state.isLoadingStage = true;
state.isEmptyStage = false;
state.selectedStageEvents = [];
- state.hasError = false;
+
+ state.hasNoAccessError = false;
},
[types.RECEIVE_STAGE_DATA_SUCCESS](state, events = []) {
state.isLoadingStage = false;
@@ -83,13 +75,14 @@ export default {
state.selectedStageEvents = events.map((ev) =>
convertObjectPropsToCamelCase(ev, { deep: true }),
);
- state.hasError = false;
+
+ state.hasNoAccessError = false;
},
[types.RECEIVE_STAGE_DATA_ERROR](state, error) {
state.isLoadingStage = false;
state.isEmptyStage = true;
state.selectedStageEvents = [];
- state.hasError = true;
+
state.selectedStageError = error;
},
[types.REQUEST_STAGE_MEDIANS](state) {
diff --git a/app/assets/javascripts/cycle_analytics/store/state.js b/app/assets/javascripts/cycle_analytics/store/state.js
index 52bc01cafa4..8d662333afa 100644
--- a/app/assets/javascripts/cycle_analytics/store/state.js
+++ b/app/assets/javascripts/cycle_analytics/store/state.js
@@ -10,9 +10,7 @@ export default () => ({
createdAfter: null,
createdBefore: null,
stages: [],
- summary: [],
analytics: [],
- stats: [],
valueStreams: [],
selectedValueStream: {},
selectedStage: {},
@@ -20,11 +18,10 @@ export default () => ({
selectedStageError: '',
medians: {},
stageCounts: {},
- hasError: false,
+ hasNoAccessError: false,
isLoading: false,
isLoadingStage: false,
isEmptyStage: false,
- permissions: {},
pagination: {
page: null,
hasNextPage: false,
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 618096c5bea..ac00af2ab34 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
@@ -290,7 +290,6 @@ export default {
<template v-else>
<reply-placeholder
v-if="!isFormVisible"
- class="qa-discussion-reply"
:placeholder-text="__('Reply…')"
@focus="showForm"
/>
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 818299e36bd..1b6458668f5 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
@@ -90,7 +90,6 @@ export default {
<form class="new-note common-note-form" @submit.prevent>
<markdown-field
:markdown-preview-path="markdownPreviewPath"
- :can-attach-file="false"
:enable-autocomplete="true"
:textarea-value="value"
:markdown-docs-path="markdownDocsPath"
diff --git a/app/assets/javascripts/design_management/graphql/fragments/design_todo_item.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/design_todo_item.fragment.graphql
index 3fe20705ce2..9d9e3a4ede9 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/design_todo_item.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/design_todo_item.fragment.graphql
@@ -1,11 +1,9 @@
fragment DesignTodoItem on Design {
id
image
- __typename
currentUserTodos(state: pending) {
nodes {
id
- __typename
}
}
}
diff --git a/app/assets/javascripts/design_management/graphql/fragments/version.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/version.fragment.graphql
index b715633a9f2..09a0b39e1cd 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/version.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/version.fragment.graphql
@@ -3,7 +3,6 @@ fragment VersionListItem on DesignVersion {
sha
createdAt
author {
- __typename
id
name
avatarUrl
diff --git a/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
index 3200327e03d..6fe2cae7346 100644
--- a/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
+++ b/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
@@ -6,9 +6,7 @@ mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
designs {
...DesignItem
versions {
- __typename
nodes {
- __typename
...VersionListItem
}
}
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 51983b19677..91e35ad3764 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -372,7 +372,7 @@ export default {
</div>
<div
v-show="hasDesigns"
- class="qa-selector-toolbar gl-display-flex gl-align-items-center gl-my-2"
+ class="gl-display-flex gl-align-items-center gl-my-2"
data-testid="design-selector-toolbar"
>
<gl-button
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index 8388458b11c..833fbb8789e 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -175,6 +175,7 @@ export default class Diff {
}
}
+ // eslint-disable-next-line class-methods-use-this
formatElementToObject = (element) => {
const key = element.attributes['data-file-hash'].value;
const name = element.attributes['data-diff-toggle-entity'].value;
@@ -192,6 +193,7 @@ export default class Diff {
return $elements.toArray().map(diff.formatElementToObject).reduce(merge);
};
+ // eslint-disable-next-line class-methods-use-this
showRawViewer = (fileHash, elements) => {
if (elements === undefined) return;
@@ -202,6 +204,7 @@ export default class Diff {
elements.rawViewer.classList.remove('hidden');
};
+ // eslint-disable-next-line class-methods-use-this
showRenderedViewer = (fileHash, elements) => {
if (elements === undefined) return;
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index ad163a2a615..0e5acd0928b 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -104,12 +104,9 @@ export default {
class="d-inline-flex mb-2"
/>
<gl-button-group class="gl-ml-4 gl-mb-4" data-testid="commit-sha-group">
- <gl-button
- label
- class="gl-font-monospace"
- data-testid="commit-sha-short-id"
- v-text="commit.short_id"
- />
+ <gl-button label class="gl-font-monospace" data-testid="commit-sha-short-id">{{
+ commit.short_id
+ }}</gl-button>
<modal-copy-button
:text="commit.id"
:title="__('Copy commit SHA')"
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index fc5766a23ef..3082ba0f16f 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -217,52 +217,47 @@ export default {
</script>
<template>
- <div class="diff-grid-row diff-grid-row-full diff-tr line_holder match expansion">
- <div :class="{ parallel: !inline }" class="diff-grid-left diff-grid-2-col left-side">
- <div
- class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column"
+ <div>
+ <div
+ class="diff-td diff-line-num gl-text-center! gl-p-0! gl-w-full! gl-display-flex gl-flex-direction-column"
+ >
+ <button
+ v-if="showExpandDown"
+ :title="s__('Diffs|Next 20 lines')"
+ :disabled="loading.down"
+ type="button"
+ class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines($options.EXPAND_DOWN)"
>
- <button
- v-if="showExpandDown"
- v-gl-tooltip.left
- :title="s__('Diffs|Next 20 lines')"
- :disabled="loading.down"
- type="button"
- class="js-unfold-down gl-rounded-0 gl-border-0 diff-line-expand-button"
- @click="handleExpandLines($options.EXPAND_DOWN)"
- >
- <gl-loading-icon v-if="loading.down" size="sm" color="dark" inline />
- <gl-icon v-else name="expand-down" />
- </button>
- <button
- v-if="lineCountBetween !== -1 && lineCountBetween < 20"
- v-gl-tooltip.left
- :title="s__('Diffs|Expand all lines')"
- :disabled="loading.all"
- type="button"
- class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
- @click="handleExpandLines()"
- >
- <gl-loading-icon v-if="loading.all" size="sm" color="dark" inline />
- <gl-icon v-else name="expand" />
- </button>
- <button
- v-if="showExpandUp"
- v-gl-tooltip.left
- :title="s__('Diffs|Previous 20 lines')"
- :disabled="loading.up"
- type="button"
- class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
- @click="handleExpandLines($options.EXPAND_UP)"
- >
- <gl-loading-icon v-if="loading.up" size="sm" color="dark" inline />
- <gl-icon v-else name="expand-up" />
- </button>
- </div>
- <div
- v-safe-html="line.rich_text"
- class="gl-display-flex! gl-flex-direction-column gl-justify-content-center diff-td line_content left-side gl-white-space-normal!"
- ></div>
+ <gl-loading-icon v-if="loading.down" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand-down" />
+ </button>
+ <button
+ v-if="lineCountBetween !== -1 && lineCountBetween < 20"
+ :title="s__('Diffs|Expand all lines')"
+ :disabled="loading.all"
+ type="button"
+ class="js-unfold-all gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines()"
+ >
+ <gl-loading-icon v-if="loading.all" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand" />
+ </button>
+ <button
+ v-if="showExpandUp"
+ :title="s__('Diffs|Previous 20 lines')"
+ :disabled="loading.up"
+ type="button"
+ class="js-unfold gl-rounded-0 gl-border-0 diff-line-expand-button"
+ @click="handleExpandLines($options.EXPAND_UP)"
+ >
+ <gl-loading-icon v-if="loading.up" size="sm" color="dark" inline />
+ <gl-icon v-else name="expand-up" />
+ </button>
</div>
+ <div
+ v-safe-html="line.rich_text"
+ class="gl-display-flex! gl-flex-direction-column gl-justify-content-center diff-td line_content left-side gl-white-space-normal!"
+ ></div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index ad406947561..ea94df1ad5b 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -197,17 +197,33 @@ export default {
@mousedown="handleParallelLineMouseDown"
>
<template v-for="(line, index) in diffLines">
- <template v-if="line.isMatchLineLeft || line.isMatchLineRight">
+ <div
+ v-if="line.isMatchLineLeft || line.isMatchLineRight"
+ :key="`expand-${index}`"
+ class="diff-grid-row diff-tr line_holder match expansion"
+ >
<diff-expansion-cell
- :key="`expand-${index}`"
:file="diffFile"
:line="line.left"
:is-top="index === 0"
:is-bottom="index + 1 === diffLinesLength"
:inline="inline"
:line-count-between="getCountBetweenIndex(index)"
+ :class="{ parallel: !inline }"
+ class="diff-grid-left diff-grid-2-col left-side"
/>
- </template>
+ <diff-expansion-cell
+ v-if="!inline"
+ :file="diffFile"
+ :line="line.left"
+ :is-top="index === 0"
+ :is-bottom="index + 1 === diffLinesLength"
+ :inline="inline"
+ :line-count-between="getCountBetweenIndex(index)"
+ :class="{ parallel: !inline }"
+ class="diff-grid-right diff-grid-2-col right-side"
+ />
+ </div>
<diff-row
v-if="!line.isMatchLineLeft && !line.isMatchLineRight"
:key="line.line_code"
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 6c0c9c4e1d0..1cc96ef3d54 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -71,12 +71,15 @@ export const DIFF_FILE_MANUAL_COLLAPSE = 'manual';
export const STATE_IDLING = 'idle';
export const STATE_LOADING = 'loading';
export const STATE_ERRORED = 'errored';
+export const STATE_PENDING_REVIEW = 'pending_comments';
// State machine transitions
export const TRANSITION_LOAD_START = 'LOAD_START';
export const TRANSITION_LOAD_ERROR = 'LOAD_ERROR';
export const TRANSITION_LOAD_SUCCEED = 'LOAD_SUCCEED';
export const TRANSITION_ACKNOWLEDGE_ERROR = 'ACKNOWLEDGE_ERROR';
+export const TRANSITION_HAS_PENDING_REVIEW = 'PENDING_REVIEW';
+export const TRANSITION_NO_REVIEW = 'NO_REVIEW';
export const RENAMED_DIFF_TRANSITIONS = {
[`${STATE_IDLING}:${TRANSITION_LOAD_START}`]: STATE_LOADING,
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index ace507f601a..5e74a7206b3 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -119,10 +119,10 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
const getBatch = (page = startPage) =>
axios
.get(mergeUrlParams({ ...urlParams, page, per_page: perPage }, state.endpointBatch))
- .then(({ data: { pagination, diff_files } }) => {
- totalLoaded += diff_files.length;
+ .then(({ data: { pagination, diff_files: diffFiles } }) => {
+ totalLoaded += diffFiles.length;
- commit(types.SET_DIFF_DATA_BATCH, { diff_files });
+ commit(types.SET_DIFF_DATA_BATCH, { diff_files: diffFiles });
commit(types.SET_BATCH_LOADING_STATE, 'loaded');
if (!scrolledVirtualScroller) {
@@ -138,7 +138,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
}
if (!isNoteLink && !state.currentDiffFileId) {
- commit(types.SET_CURRENT_DIFF_FILE, diff_files[0]?.file_hash);
+ commit(types.SET_CURRENT_DIFF_FILE, diffFiles[0]?.file_hash);
}
if (isNoteLink) {
@@ -293,8 +293,8 @@ export const assignDiscussionsToDiff = (
};
export const removeDiscussionsFromDiff = ({ commit }, removeDiscussion) => {
- const { file_hash, line_code, id } = removeDiscussion;
- commit(types.REMOVE_LINE_DISCUSSIONS_FOR_FILE, { fileHash: file_hash, lineCode: line_code, id });
+ const { file_hash: fileHash, line_code: lineCode, id } = removeDiscussion;
+ commit(types.REMOVE_LINE_DISCUSSIONS_FOR_FILE, { fileHash, lineCode, id });
};
export const toggleLineDiscussions = ({ commit }, options) => {
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index 491c2ced358..e6f7a31e07b 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -28,7 +28,6 @@ function getErrorMessage(res) {
export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const divHover = '<div class="div-dropzone-hover"></div>';
const iconPaperclip = spriteIcon('paperclip', 'div-dropzone-icon s24');
- const $attachButton = form.find('.button-attach-file');
const $attachingFileMessage = form.find('.attaching-file-message');
const $cancelButton = form.find('.button-cancel-uploading-files');
const $retryLink = form.find('.retry-uploading-link');
@@ -89,8 +88,6 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
const shouldPad = processingFileCount >= 1;
pasteText(response.link.markdown, shouldPad);
- // Show 'Attach a file' link only when all files have been uploaded.
- if (!processingFileCount) $attachButton.removeClass('hide');
addFileToForm(response.link.url);
},
error: (file, errorMessage = __('Attaching the file failed.'), xhr) => {
@@ -104,7 +101,6 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
$uploadingErrorContainer.removeClass('hide');
$uploadingErrorMessage.html(message);
- $attachButton.addClass('hide');
$cancelButton.addClass('hide');
},
totaluploadprogress(totalUploadProgress) {
@@ -115,13 +111,11 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
// DOM elements already exist.
// Instead of dynamically generating them,
// we just either hide or show them.
- $attachButton.addClass('hide');
$uploadingErrorContainer.addClass('hide');
$uploadingProgressContainer.removeClass('hide');
$cancelButton.removeClass('hide');
},
removedfile: () => {
- $attachButton.removeClass('hide');
$cancelButton.addClass('hide');
$uploadingProgressContainer.addClass('hide');
$uploadingErrorContainer.addClass('hide');
@@ -282,11 +276,18 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
messageContainer.text(`${attachingMessage} -`);
};
- form.find('.markdown-selector').click(function onMarkdownClick(e) {
+ function handleAttachFile(e) {
e.preventDefault();
$(this).closest('.gfm-form').find('.div-dropzone').click();
formTextarea.focus();
- });
+ }
+
+ form.find('.markdown-selector').click(handleAttachFile);
+
+ const $attachFileButton = form.find('.js-attach-file-button');
+ if ($attachFileButton.length) {
+ $attachFileButton.get(0).addEventListener('click', handleAttachFile);
+ }
return $formDropzone.get(0) ? Dropzone.forElement($formDropzone.get(0)) : null;
}
diff --git a/app/assets/javascripts/editor/components/source_editor_toolbar_button.vue b/app/assets/javascripts/editor/components/source_editor_toolbar_button.vue
index 194b482c12e..6ce48ddf89a 100644
--- a/app/assets/javascripts/editor/components/source_editor_toolbar_button.vue
+++ b/app/assets/javascripts/editor/components/source_editor_toolbar_button.vue
@@ -52,6 +52,7 @@ export default {
:icon="icon"
:title="label"
:aria-label="label"
+ data-qa-selector="editor_toolbar_button"
@click="clickHandler"
/>
</template>
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 e4ad0bf8e76..bc3cb163c39 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,3 +1,4 @@
+import { KeyMod, KeyCode } from 'monaco-editor';
import { debounce } from 'lodash';
import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
import createFlash from '~/flash';
@@ -158,8 +159,8 @@ export class EditorMarkdownPreviewExtension {
if (instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
const actionBasis = {
keybindings: [
- // eslint-disable-next-line no-bitwise,no-undef
- monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
+ // eslint-disable-next-line no-bitwise
+ KeyMod.chord(KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P),
],
contextMenuGroupId: 'navigation',
contextMenuOrder: 1.5,
diff --git a/app/assets/javascripts/editor/graphql/typedefs.graphql b/app/assets/javascripts/editor/graphql/typedefs.graphql
index 2433ebf6c66..49beae033f1 100644
--- a/app/assets/javascripts/editor/graphql/typedefs.graphql
+++ b/app/assets/javascripts/editor/graphql/typedefs.graphql
@@ -12,12 +12,22 @@ type Items {
nodes: [Item]!
}
+input ItemInput {
+ id: ID!
+ label: String!
+ icon: String
+ selected: Boolean
+ group: Int!
+ category: String
+ selectedLabel: String
+}
+
extend type Query {
items: Items
}
extend type Mutation {
- updateToolbarItem(id: ID!, propsToUpdate: Item!): LocalErrors
+ updateToolbarItem(id: ID!, propsToUpdate: ItemInput!): LocalErrors
removeToolbarItems(ids: [ID!]): LocalErrors
- addToolbarItems(items: [Item]): LocalErrors
+ addToolbarItems(items: [ItemInput]): LocalErrors
}
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index e8b96c25965..848ba7dbeef 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -245,6 +245,10 @@
"terraform": {
"$ref": "#/definitions/string_file_list",
"description": "Path to file or list of files with terraform plan(s)."
+ },
+ "cyclonedx": {
+ "$ref": "#/definitions/string_file_list",
+ "markdownDescription": "Path to file or list of files with cyclonedx report(s). [Learn More](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscyclonedx)."
}
}
}
@@ -292,7 +296,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+)"
},
"ref": {
"description": "Branch/Tag/Commit-hash for the target project.",
@@ -606,11 +610,33 @@
"markdownDescription": "Expression to evaluate whether additional attributes should be provided to the job. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesif)."
},
"changes": {
- "type": "array",
"markdownDescription": "Additional attributes will be provided to job if any of the provided paths matches a modified file. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges).",
- "items": {
- "type": "string"
- }
+ "anyOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["paths"],
+ "properties": {
+ "paths": {
+ "type": "array",
+ "description": "List of file paths.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "compare_to": {
+ "type": "string",
+ "description": "Ref for comparing changes."
+ }
+ }
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
},
"exists": {
"type": "array",
@@ -623,11 +649,11 @@
"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",
+ "type": "object",
"additionalProperties": {
"type": ["string", "integer", "array"]
}
- },
+ },
{
"type": "array",
"items": {
@@ -1204,6 +1230,10 @@
"description": "The tag_name must be specified. It can refer to an existing Git tag or can be specified by the user.",
"minLength": 1
},
+ "tag_message": {
+ "type": "string",
+ "description": "Message to use if creating a new annotated tag."
+ },
"description": {
"type": "string",
"description": "Specifies the longer description of the Release.",
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 7ffe8140a21..1e9924246b9 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -627,7 +627,7 @@ export default {
:title="model.name"
class="environment-name table-mobile-content"
>
- <a class="qa-environment-link" :href="environmentPath">
+ <a data-qa-selector="environment_link" :href="environmentPath">
<span v-if="model.size === 1">{{ model.name }}</span>
<span v-else>{{ model.name_without_type }}</span>
</a>
diff --git a/app/assets/javascripts/environments/components/environments_detail_header.vue b/app/assets/javascripts/environments/components/environments_detail_header.vue
index 13b9cf14f52..bd67908a6b4 100644
--- a/app/assets/javascripts/environments/components/environments_detail_header.vue
+++ b/app/assets/javascripts/environments/components/environments_detail_header.vue
@@ -135,6 +135,7 @@ export default {
>
<gl-button
v-if="shouldShowExternalUrlButton"
+ v-gl-tooltip.hover
data-testid="metrics-button"
:href="metricsPath"
:title="$options.i18n.metricsButtonTitle"
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 2c17c42dd6d..c3ab9cf7fca 100644
--- a/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
+++ b/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
@@ -4,6 +4,5 @@ query getEnvironmentApp($page: Int, $scope: String) {
stoppedCount
environments
reviewApp
- stoppedCount
}
}
diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
index 28a3c54cc8f..d9c627f5c93 100644
--- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -1,8 +1,8 @@
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
const reviewerToken = {
- formattedKey: __('Reviewer'),
+ formattedKey: s__('SearchToken|Reviewer'),
key: 'reviewer',
type: 'string',
param: 'username',
@@ -13,21 +13,6 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
IssuableTokenKeys.tokenKeys.splice(2, 0, reviewerToken);
IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, reviewerToken);
- if (window.gon?.features?.mrAttentionRequests) {
- const attentionRequestedToken = {
- formattedKey: __('Attention'),
- key: 'attention',
- type: 'string',
- param: '',
- symbol: '@',
- icon: 'user',
- tag: '@attention',
- hideNotEqual: true,
- };
- IssuableTokenKeys.tokenKeys.splice(2, 0, attentionRequestedToken);
- IssuableTokenKeys.tokenKeysWithAlternative.splice(2, 0, attentionRequestedToken);
- }
-
const draftToken = {
token: {
formattedKey: __('Draft'),
diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
index 2c58506985a..acb7449f830 100644
--- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
@@ -1,5 +1,5 @@
import { flattenDeep } from 'lodash';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import FilteredSearchTokenKeys from './filtered_search_token_keys';
export const tokenKeys = [
@@ -13,7 +13,7 @@ export const tokenKeys = [
tag: '@author',
},
{
- formattedKey: __('Assignee'),
+ formattedKey: s__('SearchToken|Assignee'),
key: 'assignee',
type: 'string',
param: 'username',
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index 6b1676eca8a..9fb69a3cae3 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -75,6 +75,7 @@ export default {
<project-avatar
class="gl-float-left gl-mr-3"
:project-avatar-url="avatarUrl"
+ :project-id="itemId"
:project-name="itemName"
aria-hidden="true"
/>
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index d4dafbdc94f..01d218438cf 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -7,11 +7,20 @@ import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
import { s__, __, sprintf } from '~/locale';
import { isUserBusy } from '~/set_status_modal/utils';
import SidebarMediator from '~/sidebar/sidebar_mediator';
+import { state } from '~/sidebar/components/reviewers/sidebar_reviewers.vue';
import AjaxCache from './lib/utils/ajax_cache';
import { spriteIcon } from './lib/utils/common_utils';
import { parsePikadayDate } from './lib/utils/datetime_utility';
import glRegexp from './lib/utils/regexp';
+const USERS_ALIAS = 'users';
+const ISSUES_ALIAS = 'issues';
+const MILESTONES_ALIAS = 'milestones';
+const MERGEREQUESTS_ALIAS = 'mergerequests';
+const LABELS_ALIAS = 'labels';
+const SNIPPETS_ALIAS = 'snippets';
+const CONTACTS_ALIAS = 'contacts';
+export const AT_WHO_ACTIVE_CLASS = 'at-who-active';
/**
* Escapes user input before we pass it to at.js, which
* renders it as HTML in the autocomplete dropdown.
@@ -29,6 +38,15 @@ function escape(string) {
return lodashEscape(string).replace(/\$/g, '&dollar;');
}
+export function showAndHideHelper($input, alias = '') {
+ $input.on(`hidden${alias ? '-' : ''}${alias}.atwho`, () => {
+ $input.removeClass(AT_WHO_ACTIVE_CLASS);
+ });
+ $input.on(`shown${alias ? '-' : ''}${alias}.atwho`, () => {
+ $input.addClass(AT_WHO_ACTIVE_CLASS);
+ });
+}
+
function createMemberSearchString(member) {
return `${member.name.replace(/ /g, '')} ${member.username}`;
}
@@ -237,10 +255,18 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
matcher(flag, subtext) {
- const regexp = new RegExp(`(?:[^${glRegexp.unicodeLetters}0-9:]|\n|^):([^:]*)$`, 'gi');
+ const regexp = new RegExp(
+ `(?:[^${glRegexp.unicodeLetters}0-9:]|\n|^):([^ :][^:]*)?$`,
+ 'gi',
+ );
const match = regexp.exec(subtext);
- return match && match.length ? match[1] : null;
+ if (match && match.length) {
+ // Since we have "?" on the group, it's possible it is undefined
+ return match[1] || '';
+ }
+
+ return null;
},
filter(query, items) {
if (GfmAutoComplete.isLoading(items)) {
@@ -265,6 +291,7 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input);
}
setupMembers($input) {
@@ -276,8 +303,6 @@ class GfmAutoComplete {
UNASSIGN_REVIEWER: '/unassign_reviewer',
REASSIGN: '/reassign',
CC: '/cc',
- ATTENTION: '/attention',
- REMOVE_ATTENTION: '/remove_attention',
};
let assignees = [];
let reviewers = [];
@@ -286,7 +311,7 @@ class GfmAutoComplete {
// Team Members
$input.atwho({
at: '@',
- alias: 'users',
+ alias: USERS_ALIAS,
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
const { avatarTag, username, title, icon, availability } = value;
@@ -328,8 +353,7 @@ class GfmAutoComplete {
// Cache assignees & reviewers list for easier filtering later
assignees =
SidebarMediator.singleton?.store?.assignees?.map(createMemberSearchString) || [];
- reviewers =
- SidebarMediator.singleton?.store?.reviewers?.map(createMemberSearchString) || [];
+ reviewers = state.issuable?.reviewers?.nodes?.map(createMemberSearchString) || [];
const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
return match && match.length ? match[1] : null;
@@ -356,23 +380,6 @@ class GfmAutoComplete {
} else if (command === MEMBER_COMMAND.UNASSIGN_REVIEWER) {
// Only include members which are not assigned as a reviewer to Issuable currently
return data.filter((member) => reviewers.includes(member.search));
- } else if (
- command === MEMBER_COMMAND.ATTENTION ||
- command === MEMBER_COMMAND.REMOVE_ATTENTION
- ) {
- const attentionUsers = [
- ...(SidebarMediator.singleton?.store?.assignees || []),
- ...(SidebarMediator.singleton?.store?.reviewers || []),
- ];
- const attentionRequested = command === MEMBER_COMMAND.REMOVE_ATTENTION;
-
- return data.filter((member) =>
- attentionUsers.find(
- (u) =>
- createMemberSearchString(u).includes(member.search) &&
- u.attention_requested === attentionRequested,
- ),
- );
}
return data;
@@ -393,12 +400,13 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, USERS_ALIAS);
}
setupIssues($input) {
$input.atwho({
at: '#',
- alias: 'issues',
+ alias: ISSUES_ALIAS,
searchKey: 'search',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
@@ -427,12 +435,13 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, ISSUES_ALIAS);
}
setupMilestones($input) {
$input.atwho({
at: '%',
- alias: 'milestones',
+ alias: MILESTONES_ALIAS,
searchKey: 'search',
// eslint-disable-next-line no-template-curly-in-string
insertTpl: '${atwho-at}${title}',
@@ -483,12 +492,13 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, MILESTONES_ALIAS);
}
setupMergeRequests($input) {
$input.atwho({
at: '!',
- alias: 'mergerequests',
+ alias: MERGEREQUESTS_ALIAS,
searchKey: 'search',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
@@ -517,6 +527,7 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, MERGEREQUESTS_ALIAS);
}
setupLabels($input) {
@@ -527,7 +538,7 @@ class GfmAutoComplete {
$input.atwho({
at: '~',
- alias: 'labels',
+ alias: LABELS_ALIAS,
searchKey: 'search',
data: GfmAutoComplete.defaultLoadingData,
displayTpl(value) {
@@ -617,12 +628,13 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, LABELS_ALIAS);
}
setupSnippets($input) {
$input.atwho({
at: '$',
- alias: 'snippets',
+ alias: SNIPPETS_ALIAS,
searchKey: 'search',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
@@ -650,13 +662,14 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, SNIPPETS_ALIAS);
}
setupContacts($input) {
$input.atwho({
at: '[contact:',
suffix: ']',
- alias: 'contacts',
+ alias: CONTACTS_ALIAS,
searchKey: 'search',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
@@ -686,6 +699,7 @@ class GfmAutoComplete {
},
},
});
+ showAndHideHelper($input, CONTACTS_ALIAS);
}
getDefaultCallbacks() {
diff --git a/app/assets/javascripts/gitlab_pages/new.js b/app/assets/javascripts/gitlab_pages/new.js
new file mode 100644
index 00000000000..e23b08dcd56
--- /dev/null
+++ b/app/assets/javascripts/gitlab_pages/new.js
@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlToast } from '@gitlab/ui';
+import createDefaultClient from '~/lib/graphql';
+import Pages from './components/pages_pipeline_wizard.vue';
+
+Vue.use(VueApollo);
+Vue.use(GlToast);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(
+ {},
+ {
+ batchMax: 1,
+ assumeImmutableResults: true,
+ },
+ ),
+});
+
+export default function initPages() {
+ const el = document.querySelector('#js-pages');
+
+ if (!el) {
+ return false;
+ }
+
+ return new Vue({
+ el,
+ name: 'GitlabPagesNewRoot',
+ apolloProvider,
+ render(createElement) {
+ return createElement(Pages, {
+ props: {
+ ...el.dataset,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/graphql_shared/fragments/blobviewer.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/blobviewer.fragment.graphql
deleted file mode 100644
index b202ed12f80..00000000000
--- a/app/assets/javascripts/graphql_shared/fragments/blobviewer.fragment.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-fragment BlobViewer on SnippetBlobViewer {
- collapsed
- renderError
- tooLarge
- type
- fileType
-}
diff --git a/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql
deleted file mode 100644
index 78a368089a8..00000000000
--- a/app/assets/javascripts/graphql_shared/fragments/iteration.fragment.graphql
+++ /dev/null
@@ -1,4 +0,0 @@
-fragment Iteration on Iteration {
- id
- title
-}
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index 45c5cca68cc..eac325f184f 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -3,6 +3,12 @@
"AlertManagementHttpIntegration",
"AlertManagementPrometheusIntegration"
],
+ "CiVariable": [
+ "CiGroupVariable",
+ "CiInstanceVariable",
+ "CiManualVariable",
+ "CiProjectVariable"
+ ],
"CurrentUserTodos": [
"BoardEpic",
"Design",
@@ -134,6 +140,9 @@
"WorkItemWidgetAssignees",
"WorkItemWidgetDescription",
"WorkItemWidgetHierarchy",
+ "WorkItemWidgetLabels",
+ "WorkItemWidgetStartAndDueDate",
+ "WorkItemWidgetVerificationStatus",
"WorkItemWidgetWeight"
]
}
diff --git a/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql
index 12b391e41ac..50ed38e0492 100644
--- a/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/get_user_callouts.query.graphql
@@ -1,11 +1,8 @@
query getUser {
currentUser {
id
- __typename
callouts {
- __typename
nodes {
- __typename
featureName
}
}
diff --git a/app/assets/javascripts/group_settings/components/shared_runners_form.vue b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
index 06aea26830d..8011090f1cb 100644
--- a/app/assets/javascripts/group_settings/components/shared_runners_form.vue
+++ b/app/assets/javascripts/group_settings/components/shared_runners_form.vue
@@ -1,6 +1,6 @@
<script>
import { GlToggle, GlAlert } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
+import { updateGroup } from '~/api/groups_api';
import { I18N_UPDATE_ERROR_MESSAGE, I18N_REFRESH_MESSAGE } from '../constants';
export default {
@@ -9,7 +9,7 @@ export default {
GlAlert,
},
inject: [
- 'updatePath',
+ 'groupId',
'sharedRunnersSetting',
'parentSharedRunnersSetting',
'runnerEnabledValue',
@@ -54,8 +54,7 @@ export default {
this.isLoading = true;
- axios
- .put(this.updatePath, { shared_runners_setting: setting })
+ updateGroup(this.groupId, { shared_runners_setting: setting })
.then(() => {
this.value = setting;
})
diff --git a/app/assets/javascripts/group_settings/mount_shared_runners.js b/app/assets/javascripts/group_settings/mount_shared_runners.js
index aeb6d57a11a..e7e104d61b3 100644
--- a/app/assets/javascripts/group_settings/mount_shared_runners.js
+++ b/app/assets/javascripts/group_settings/mount_shared_runners.js
@@ -5,7 +5,7 @@ export default (containerId = 'update-shared-runners-form') => {
const containerEl = document.getElementById(containerId);
const {
- updatePath,
+ groupId,
sharedRunnersSetting,
parentSharedRunnersSetting,
runnerEnabledValue,
@@ -16,7 +16,7 @@ export default (containerId = 'update-shared-runners-form') => {
return new Vue({
el: containerEl,
provide: {
- updatePath,
+ groupId,
sharedRunnersSetting,
parentSharedRunnersSetting,
runnerEnabledValue,
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 7345afb8545..2f182b86d2c 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -16,12 +16,9 @@ import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
import { helpPagePath } from '~/helpers/help_page_helper';
import { __ } from '~/locale';
-import {
- VISIBILITY_TYPE_ICON,
- GROUP_VISIBILITY_TYPE,
- ITEM_TYPE,
- VISIBILITY_PRIVATE,
-} from '../constants';
+import { VISIBILITY_LEVELS_ENUM } from '~/visibility_level/constants';
+import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE, ITEM_TYPE } from '../constants';
+
import eventHub from '../event_hub';
import itemActions from './item_actions.vue';
@@ -114,8 +111,8 @@ export default {
shouldShowVisibilityWarning() {
return (
this.action === 'shared' &&
- this.currentGroupVisibility === VISIBILITY_PRIVATE &&
- this.group.visibility !== VISIBILITY_PRIVATE
+ VISIBILITY_LEVELS_ENUM[this.group.visibility] >
+ VISIBILITY_LEVELS_ENUM[this.currentGroupVisibility]
);
},
},
@@ -142,7 +139,7 @@ export default {
shareProjectsWithGroupsHelpPagePath: helpPagePath(
'user/project/members/share_project_with_groups',
{
- anchor: 'share-a-public-project-with-private-group',
+ anchor: 'sharing-projects-with-groups-of-a-higher-restrictive-visibility-level',
},
),
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
@@ -182,6 +179,7 @@ export default {
>
<gl-avatar
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
+ :entity-id="group.id"
:entity-name="group.name"
:src="group.avatarUrl"
:alt="group.name"
diff --git a/app/assets/javascripts/groups/components/group_name_and_path.vue b/app/assets/javascripts/groups/components/group_name_and_path.vue
index 983535d3e9c..9a1ea2f1812 100644
--- a/app/assets/javascripts/groups/components/group_name_and_path.vue
+++ b/app/assets/javascripts/groups/components/group_name_and_path.vue
@@ -6,6 +6,13 @@ import {
GlInputGroupText,
GlLink,
GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlTruncate,
+ GlSearchBoxByType,
} from '@gitlab/ui';
import { debounce } from 'lodash';
@@ -15,6 +22,11 @@ import { createAlert } from '~/flash';
import { slugify } from '~/lib/utils/text_utility';
import axios from '~/lib/utils/axios_utils';
import { helpPagePath } from '~/helpers/help_page_helper';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
+import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
+
+import searchGroupsWhereUserCanCreateSubgroups from '../queries/search_groups_where_user_can_create_subgroups.query.graphql';
const DEBOUNCE_DURATION = 1000;
@@ -22,7 +34,6 @@ export default {
i18n: {
inputs: {
name: {
- label: s__('Groups|Group name'),
placeholder: __('My awesome group'),
description: s__(
'Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.',
@@ -30,7 +41,6 @@ export default {
invalidFeedback: s__('Groups|Enter a descriptive name for your group.'),
},
path: {
- label: s__('Groups|Group URL'),
placeholder: __('my-awesome-group'),
invalidFeedbackInvalidPattern: s__(
'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.',
@@ -40,9 +50,6 @@ export default {
),
validFeedback: s__('Groups|Group path is available.'),
},
- groupId: {
- label: s__('Groups|Group ID'),
- },
},
apiLoadingMessage: s__('Groups|Checking group URL availability...'),
apiErrorMessage: __(
@@ -51,7 +58,7 @@ export default {
changingUrlWarningMessage: s__('Groups|Changing group URL can have unintended side effects.'),
learnMore: s__('Groups|Learn more'),
},
- nameInputSize: { md: 'lg' },
+ inputSize: { md: 'lg' },
changingGroupPathHelpPagePath: helpPagePath('user/group/index', {
anchor: 'change-a-groups-path',
}),
@@ -63,8 +70,35 @@ export default {
GlInputGroupText,
GlLink,
GlAlert,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlTruncate,
+ GlSearchBoxByType,
+ },
+ apollo: {
+ currentUserGroups: {
+ query: searchGroupsWhereUserCanCreateSubgroups,
+ variables() {
+ return {
+ search: this.search,
+ };
+ },
+ update(data) {
+ return data.currentUser?.groups?.nodes || [];
+ },
+ skip() {
+ const hasNotEnoughSearchCharacters =
+ this.search.length > 0 && this.search.length < MINIMUM_SEARCH_LENGTH;
+
+ return this.shouldSkipQuery || hasNotEnoughSearchCharacters;
+ },
+ debounce: DEBOUNCE_DELAY,
+ },
},
- inject: ['fields', 'basePath', 'mattermostEnabled'],
+ inject: ['fields', 'basePath', 'newSubgroup', 'mattermostEnabled'],
data() {
return {
name: this.fields.name.value,
@@ -76,9 +110,27 @@ export default {
pathFeedbackState: null,
pathInvalidFeedback: null,
activeApiRequestAbortController: null,
+ search: '',
+ currentUserGroups: {},
+ shouldSkipQuery: true,
+ selectedGroup: {
+ id: this.fields.parentId.value,
+ fullPath: this.fields.parentFullPath.value,
+ },
};
},
computed: {
+ inputLabels() {
+ return {
+ name: this.newSubgroup ? s__('Groups|Subgroup name') : s__('Groups|Group name'),
+ path: this.newSubgroup ? s__('Groups|Subgroup slug') : s__('Groups|Group URL'),
+ subgroupPath: s__('Groups|Subgroup URL'),
+ groupId: s__('Groups|Group ID'),
+ };
+ },
+ pathInputSize() {
+ return this.newSubgroup ? {} : this.$options.inputSize;
+ },
computedPath() {
return this.apiSuggestedPath || this.path;
},
@@ -129,9 +181,11 @@ export default {
try {
const {
data: { exists, suggests },
- } = await getGroupPathAvailability(this.path, this.fields.parentId?.value, {
- signal: this.activeApiRequestAbortController.signal,
- });
+ } = await getGroupPathAvailability(
+ this.path,
+ this.selectedGroup.id || this.fields.parentId.value,
+ { signal: this.activeApiRequestAbortController.signal },
+ );
this.apiLoading = false;
@@ -198,6 +252,21 @@ export default {
this.pathInvalidFeedback = this.$options.i18n.inputs.path.invalidFeedbackInvalidPattern;
this.pathFeedbackState = false;
},
+ handleDropdownShown() {
+ if (this.shouldSkipQuery) {
+ this.shouldSkipQuery = false;
+ }
+
+ this.$refs.search.focusInput();
+ },
+ handleDropdownItemClick({ id, fullPath }) {
+ this.selectedGroup = {
+ id: getIdFromGraphQLId(id),
+ fullPath,
+ };
+
+ this.debouncedValidatePath();
+ },
},
};
</script>
@@ -208,10 +277,10 @@ export default {
:id="fields.parentId.id"
type="hidden"
:name="fields.parentId.name"
- :value="fields.parentId.value"
+ :value="selectedGroup.id"
/>
<gl-form-group
- :label="$options.i18n.inputs.name.label"
+ :label="inputLabels.name"
:description="$options.i18n.inputs.name.description"
:label-for="fields.name.id"
:invalid-feedback="$options.i18n.inputs.name.invalidFeedback"
@@ -220,46 +289,102 @@ export default {
<gl-form-input
:id="fields.name.id"
v-model="name"
- class="gl-field-error-ignore"
+ class="gl-field-error-ignore gl-h-auto!"
required
:name="fields.name.name"
:placeholder="$options.i18n.inputs.name.placeholder"
data-qa-selector="group_name_field"
- :size="$options.nameInputSize"
+ :size="$options.inputSize"
:state="nameFeedbackState"
@invalid="handleInvalidName"
/>
</gl-form-group>
- <gl-form-group
- :label="$options.i18n.inputs.path.label"
- :label-for="fields.path.id"
- :description="pathDescription"
- :state="pathFeedbackState"
- :valid-feedback="$options.i18n.inputs.path.validFeedback"
- :invalid-feedback="pathInvalidFeedback"
- >
- <gl-form-input-group>
- <template #prepend>
- <gl-input-group-text class="group-root-path">{{ basePath }}</gl-input-group-text>
- </template>
- <gl-form-input
- :id="fields.path.id"
- class="gl-field-error-ignore"
- :name="fields.path.name"
- :value="computedPath"
- :placeholder="$options.i18n.inputs.path.placeholder"
- :maxlength="fields.path.maxLength"
- :pattern="fields.path.pattern"
- :state="pathFeedbackState"
- :size="$options.nameInputSize"
- required
- data-qa-selector="group_path_field"
- :data-bind-in="mattermostEnabled ? $options.mattermostDataBindName : null"
- @input="handlePathInput"
- @invalid="handleInvalidPath"
- />
- </gl-form-input-group>
- </gl-form-group>
+
+ <div :class="newSubgroup && 'row gl-mb-3'">
+ <gl-form-group v-if="newSubgroup" class="col-sm-6 gl-pr-0" :label="inputLabels.subgroupPath">
+ <div class="input-group gl-flex-nowrap">
+ <gl-button-group class="gl-w-full">
+ <gl-button class="js-group-namespace-button gl-text-truncate gl-flex-grow-0!" label>
+ {{ basePath }}
+ </gl-button>
+
+ <gl-dropdown
+ class="js-group-namespace-dropdown gl-flex-grow-1"
+ toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base! gl-w-20"
+ @shown="handleDropdownShown"
+ >
+ <template #button-text>
+ <gl-truncate
+ v-if="selectedGroup.fullPath"
+ :text="selectedGroup.fullPath"
+ position="start"
+ with-tooltip
+ />
+ </template>
+
+ <gl-search-box-by-type
+ ref="search"
+ v-model.trim="search"
+ :is-loading="$apollo.queries.currentUserGroups.loading"
+ />
+
+ <template v-if="!$apollo.queries.currentUserGroups.loading">
+ <template v-if="currentUserGroups.length">
+ <gl-dropdown-item
+ v-for="group of currentUserGroups"
+ :key="group.id"
+ data-testid="select_group_dropdown_item"
+ @click="handleDropdownItemClick(group)"
+ >
+ {{ group.fullPath }}
+ </gl-dropdown-item>
+ </template>
+ <gl-dropdown-text v-else>{{ __('No matches found') }}</gl-dropdown-text>
+ </template>
+ </gl-dropdown>
+ </gl-button-group>
+
+ <div class="gl-align-self-center gl-pl-5">
+ <span class="gl-display-none gl-md-display-inline">/</span>
+ </div>
+ </div>
+ </gl-form-group>
+
+ <gl-form-group
+ :class="newSubgroup && 'col-sm-6'"
+ :label="inputLabels.path"
+ :label-for="fields.path.id"
+ :description="pathDescription"
+ :state="pathFeedbackState"
+ :valid-feedback="$options.i18n.inputs.path.validFeedback"
+ :invalid-feedback="pathInvalidFeedback"
+ >
+ <gl-form-input-group>
+ <template v-if="!newSubgroup" #prepend>
+ <gl-input-group-text class="group-root-path">
+ {{ basePath.concat(fields.parentFullPath.value) }}
+ </gl-input-group-text>
+ </template>
+ <gl-form-input
+ :id="fields.path.id"
+ class="gl-field-error-ignore gl-h-auto!"
+ :name="fields.path.name"
+ :value="computedPath"
+ :placeholder="$options.i18n.inputs.path.placeholder"
+ :maxlength="fields.path.maxLength"
+ :pattern="fields.path.pattern"
+ :state="pathFeedbackState"
+ :size="pathInputSize"
+ required
+ data-qa-selector="group_path_field"
+ :data-bind-in="mattermostEnabled ? $options.mattermostDataBindName : null"
+ @input="handlePathInput"
+ @invalid="handleInvalidPath"
+ />
+ </gl-form-input-group>
+ </gl-form-group>
+ </div>
+
<template v-if="isEditingGroup">
<gl-alert class="gl-mb-5" :dismissible="false" variant="warning">
{{ $options.i18n.changingUrlWarningMessage }}
@@ -267,7 +392,7 @@ export default {
>{{ $options.i18n.learnMore }}
</gl-link>
</gl-alert>
- <gl-form-group :label="$options.i18n.inputs.groupId.label" :label-for="fields.groupId.id">
+ <gl-form-group :label="inputLabels.groupId" :label-for="fields.groupId.id">
<gl-form-input
:id="fields.groupId.id"
:value="fields.groupId.value"
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
index 5706df0dd1b..3a05c308a2a 100644
--- a/app/assets/javascripts/groups/components/groups.vue
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -42,7 +42,7 @@ export default {
</script>
<template>
- <div class="groups-list-tree-container qa-groups-list-tree-container">
+ <div class="groups-list-tree-container" data-qa-selector="groups_list_tree_container">
<div
v-if="searchEmpty"
class="has-no-search-results gl-font-style-italic gl-text-center gl-text-gray-600 gl-p-5"
diff --git a/app/assets/javascripts/groups/components/transfer_group_form.vue b/app/assets/javascripts/groups/components/transfer_group_form.vue
index e848f10352d..7e7282a27b0 100644
--- a/app/assets/javascripts/groups/components/transfer_group_form.vue
+++ b/app/assets/javascripts/groups/components/transfer_group_form.vue
@@ -70,7 +70,6 @@ export default {
<input type="hidden" name="new_parent_group_id" :value="selectedId" />
</gl-form-group>
<confirm-danger
- button-class="qa-transfer-button"
:disabled="disableSubmitButton"
:phrase="confirmationPhrase"
:button-text="confirmButtonText"
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index 29981d09155..0d09ad9442b 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -1,4 +1,9 @@
import { __, s__ } from '~/locale';
+import {
+ VISIBILITY_LEVEL_PRIVATE,
+ VISIBILITY_LEVEL_INTERNAL,
+ VISIBILITY_LEVEL_PUBLIC,
+} from '~/visibility_level/constants';
export const MAX_CHILDREN_COUNT = 20;
@@ -28,32 +33,30 @@ export const ITEM_TYPE = {
GROUP: 'group',
};
-export const VISIBILITY_PUBLIC = 'public';
-export const VISIBILITY_INTERNAL = 'internal';
-export const VISIBILITY_PRIVATE = 'private';
-
export const GROUP_VISIBILITY_TYPE = {
- [VISIBILITY_PUBLIC]: __(
+ [VISIBILITY_LEVEL_PUBLIC]: __(
'Public - The group and any public projects can be viewed without any authentication.',
),
- [VISIBILITY_INTERNAL]: __(
+ [VISIBILITY_LEVEL_INTERNAL]: __(
'Internal - The group and any internal projects can be viewed by any logged in user except external users.',
),
- [VISIBILITY_PRIVATE]: __('Private - The group and its projects can only be viewed by members.'),
+ [VISIBILITY_LEVEL_PRIVATE]: __(
+ 'Private - The group and its projects can only be viewed by members.',
+ ),
};
export const PROJECT_VISIBILITY_TYPE = {
- [VISIBILITY_PUBLIC]: __('Public - The project can be accessed without any authentication.'),
- [VISIBILITY_INTERNAL]: __(
+ [VISIBILITY_LEVEL_PUBLIC]: __('Public - The project can be accessed without any authentication.'),
+ [VISIBILITY_LEVEL_INTERNAL]: __(
'Internal - The project can be accessed by any logged in user except external users.',
),
- [VISIBILITY_PRIVATE]: __(
+ [VISIBILITY_LEVEL_PRIVATE]: __(
'Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
),
};
export const VISIBILITY_TYPE_ICON = {
- [VISIBILITY_PUBLIC]: 'earth',
- [VISIBILITY_INTERNAL]: 'shield',
- [VISIBILITY_PRIVATE]: 'lock',
+ [VISIBILITY_LEVEL_PUBLIC]: 'earth',
+ [VISIBILITY_LEVEL_INTERNAL]: 'shield',
+ [VISIBILITY_LEVEL_PRIVATE]: 'lock',
};
diff --git a/app/assets/javascripts/groups/create_edit_form.js b/app/assets/javascripts/groups/create_edit_form.js
index 8ca0e6077e9..330d343b776 100644
--- a/app/assets/javascripts/groups/create_edit_form.js
+++ b/app/assets/javascripts/groups/create_edit_form.js
@@ -1,8 +1,12 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import { parseRailsFormFields } from '~/lib/utils/forms';
import { parseBoolean } from '~/lib/utils/common_utils';
import GroupNameAndPath from './components/group_name_and_path.vue';
+Vue.use(VueApollo);
+
export const initGroupNameAndPath = () => {
const elements = document.querySelectorAll('.js-group-name-and-path');
@@ -12,13 +16,17 @@ export const initGroupNameAndPath = () => {
elements.forEach((element) => {
const fields = parseRailsFormFields(element);
- const { basePath, mattermostEnabled } = element.dataset;
+ const { basePath, newSubgroup, mattermostEnabled } = element.dataset;
return new Vue({
el: element,
+ apolloProvider: new VueApollo({
+ defaultClient: createDefaultClient(),
+ }),
provide: {
fields,
basePath,
+ newSubgroup: parseBoolean(newSubgroup),
mattermostEnabled: parseBoolean(mattermostEnabled),
},
render(h) {
diff --git a/app/assets/javascripts/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql b/app/assets/javascripts/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql
new file mode 100644
index 00000000000..c45a31ef387
--- /dev/null
+++ b/app/assets/javascripts/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql
@@ -0,0 +1,11 @@
+query searchGroupsWhereUserCanCreateSubgroups($search: String) {
+ currentUser {
+ id
+ groups(permissionScope: TRANSFER_PROJECTS, search: $search) {
+ nodes {
+ id
+ fullPath
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/header_search/components/app.vue b/app/assets/javascripts/header_search/components/app.vue
index 0c4f9640972..f4b939fb20f 100644
--- a/app/assets/javascripts/header_search/components/app.vue
+++ b/app/assets/javascripts/header_search/components/app.vue
@@ -23,6 +23,9 @@ import {
SEARCH_SHORTCUTS_MIN_CHARACTERS,
SCOPE_TOKEN_MAX_LENGTH,
INPUT_FIELD_PADDING,
+ IS_SEARCHING,
+ IS_FOCUSED,
+ IS_NOT_FOCUSED,
} from '../constants';
import HeaderSearchAutocompleteItems from './header_search_autocomplete_items.vue';
import HeaderSearchDefaultItems from './header_search_default_items.vue';
@@ -65,6 +68,7 @@ export default {
data() {
return {
showDropdown: false,
+ isFocused: false,
currentFocusIndex: SEARCH_BOX_INDEX,
};
},
@@ -92,20 +96,18 @@ export default {
if (!this.showDropdown || !this.isLoggedIn) {
return false;
}
-
return this.searchOptions?.length > 0;
},
showDefaultItems() {
return !this.searchText;
},
- showScopes() {
+ searchTermOverMin() {
return this.searchText?.length > SEARCH_SHORTCUTS_MIN_CHARACTERS;
},
defaultIndex() {
if (this.showDefaultItems) {
return SEARCH_BOX_INDEX;
}
-
return FIRST_DROPDOWN_INDEX;
},
@@ -132,12 +134,15 @@ export default {
count: this.searchOptions.length,
});
},
- searchBarStateIndicator() {
- const hasIcon =
- this.searchContext?.project || this.searchContext?.group ? 'has-icon' : 'has-no-icon';
- const isSearching = this.showScopes ? 'is-searching' : 'is-not-searching';
- const isActive = this.showSearchDropdown ? 'is-active' : 'is-not-active';
- return `${isActive} ${isSearching} ${hasIcon}`;
+ searchBarClasses() {
+ return {
+ [IS_SEARCHING]: this.searchTermOverMin,
+ [IS_FOCUSED]: this.isFocused,
+ [IS_NOT_FOCUSED]: !this.isFocused,
+ };
+ },
+ showScopeHelp() {
+ return this.searchTermOverMin && this.isFocused;
},
searchBarItem() {
return this.searchOptions?.[0];
@@ -158,11 +163,22 @@ export default {
...mapActions(['setSearch', 'fetchAutocompleteOptions', 'clearAutocomplete']),
openDropdown() {
this.showDropdown = true;
- this.$emit('toggleDropdown', this.showDropdown);
+ this.isFocused = true;
+ this.$emit('expandSearchBar', true);
},
closeDropdown() {
this.showDropdown = false;
- this.$emit('toggleDropdown', this.showDropdown);
+ },
+ collapseAndCloseSearchBar() {
+ // we need a delay on this method
+ // for the search bar not to remove
+ // the clear button from dom
+ // and register clicks on dropdown items
+ setTimeout(() => {
+ this.showDropdown = false;
+ this.isFocused = false;
+ this.$emit('collapseSearchBar');
+ }, 200);
},
submitSearch() {
if (this.search?.length <= SEARCH_SHORTCUTS_MIN_CHARACTERS && this.currentFocusIndex < 0) {
@@ -171,6 +187,7 @@ export default {
return visitUrl(this.currentFocusedOption?.url || this.searchQuery);
},
getAutocompleteOptions: debounce(function debouncedSearch(searchTerm) {
+ this.openDropdown();
if (!searchTerm) {
this.clearAutocomplete();
} else {
@@ -201,7 +218,7 @@ export default {
role="search"
:aria-label="$options.i18n.searchGitlab"
class="header-search gl-relative gl-rounded-base gl-w-full"
- :class="searchBarStateIndicator"
+ :class="searchBarClasses"
data-testid="header-search-form"
>
<gl-search-box-by-type
@@ -217,12 +234,13 @@ export default {
:aria-describedby="$options.SEARCH_INPUT_DESCRIPTION"
@focus="openDropdown"
@click="openDropdown"
+ @blur="collapseAndCloseSearchBar"
@input="getAutocompleteOptions"
@keydown.enter.stop.prevent="submitSearch"
@keydown.esc.stop.prevent="closeDropdown"
/>
<gl-token
- v-if="showScopes"
+ v-if="showScopeHelp"
v-gl-resize-observer-directive="observeTokenWidth"
class="in-search-scope-help"
:view-only="true"
@@ -242,6 +260,7 @@ export default {
}}
</gl-token>
<kbd
+ v-show="!isFocused"
v-gl-tooltip.bottom.hover.html
class="gl-absolute gl-right-3 gl-top-0 gl-z-index-1 keyboard-shortcut-helper"
:title="$options.i18n.kbdHelp"
@@ -262,9 +281,9 @@ export default {
<div
v-if="showSearchDropdown"
data-testid="header-search-dropdown-menu"
- class="header-search-dropdown-menu gl-absolute gl-w-full gl-bg-white gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-200 gl-shadow-x0-y2-b4-s0"
+ class="header-search-dropdown-menu gl-overflow-y-auto gl-absolute gl-w-full gl-bg-white gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-200 gl-shadow-x0-y2-b4-s0 gl-mt-3"
>
- <div class="header-search-dropdown-content gl-overflow-y-auto gl-py-2">
+ <div class="header-search-dropdown-content gl-py-2">
<dropdown-keyboard-navigation
v-model="currentFocusIndex"
:max="searchOptions.length - 1"
@@ -278,7 +297,7 @@ export default {
/>
<template v-else>
<header-search-scoped-items
- v-if="showScopes"
+ v-if="searchTermOverMin"
:current-focused-option="currentFocusedOption"
/>
<header-search-autocomplete-items :current-focused-option="currentFocusedOption" />
diff --git a/app/assets/javascripts/header_search/constants.js b/app/assets/javascripts/header_search/constants.js
index a026386b2bd..3a20fb0216d 100644
--- a/app/assets/javascripts/header_search/constants.js
+++ b/app/assets/javascripts/header_search/constants.js
@@ -51,3 +51,7 @@ export const SCOPE_TOKEN_MAX_LENGTH = 36;
export const INPUT_FIELD_PADDING = 52;
export const HEADER_INIT_EVENTS = ['input', 'focus'];
+
+export const IS_SEARCHING = 'is-searching';
+export const IS_FOCUSED = 'is-focused';
+export const IS_NOT_FOCUSED = 'is-not-focused';
diff --git a/app/assets/javascripts/header_search/index.js b/app/assets/javascripts/header_search/index.js
index b2c505d569f..f6f5c6a14fa 100644
--- a/app/assets/javascripts/header_search/index.js
+++ b/app/assets/javascripts/header_search/index.js
@@ -26,12 +26,11 @@ export const initHeaderSearchApp = (search = '') => {
render(createElement) {
return createElement(HeaderSearchApp, {
on: {
- toggleDropdown: (isVisible = false) => {
- if (isVisible) {
- navBarEl?.classList.add('header-search-is-active');
- } else {
- navBarEl?.classList.remove('header-search-is-active');
- }
+ expandSearchBar: () => {
+ navBarEl?.classList.add('header-search-is-active');
+ },
+ collapseSearchBar: () => {
+ navBarEl?.classList.remove('header-search-is-active');
},
},
});
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index 05a254d3fbf..d02dc67d933 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -156,7 +156,7 @@ export default {
category="primary"
variant="confirm"
block
- class="qa-begin-commit-button"
+ data-qa-selector="begin_commit_button"
data-testid="begin-commit-button"
@click="beginCommit"
>
@@ -184,7 +184,7 @@ export default {
:disabled="commitButtonDisabled"
:loading="submitCommitLoading"
data-testid="commit-button"
- class="qa-commit-button"
+ data-qa-selector="commit_button"
category="primary"
variant="confirm"
type="submit"
diff --git a/app/assets/javascripts/ide/components/file_templates/bar.vue b/app/assets/javascripts/ide/components/file_templates/bar.vue
index 0921b5a5424..ba679ae7c9b 100644
--- a/app/assets/javascripts/ide/components/file_templates/bar.vue
+++ b/app/assets/javascripts/ide/components/file_templates/bar.vue
@@ -80,7 +80,9 @@ export default {
<template>
<div
- class="gl-display-flex gl-align-items-center ide-file-templates qa-file-templates-bar gl-relative gl-z-index-1"
+ class="gl-display-flex gl-align-items-center ide-file-templates gl-relative gl-z-index-1"
+ data-testid="file-templates-bar"
+ data-qa-selector="file_templates_container"
>
<strong class="gl-mr-3"> {{ $options.i18n.barLabel }} </strong>
<gl-dropdown
@@ -97,7 +99,8 @@ export default {
</gl-dropdown>
<gl-dropdown
v-if="showTemplatesDropdown"
- class="gl-mr-6 qa-file-template-dropdown"
+ class="gl-mr-6"
+ data-qa-selector="file_template_dropdown"
:text="$options.i18n.templateListDropdownLabel"
@show="fetchTemplateTypes"
>
diff --git a/app/assets/javascripts/ide/components/ide_project_header.vue b/app/assets/javascripts/ide/components/ide_project_header.vue
index 1c25a8e634d..3296dc2060c 100644
--- a/app/assets/javascripts/ide/components/ide_project_header.vue
+++ b/app/assets/javascripts/ide/components/ide_project_header.vue
@@ -18,6 +18,7 @@ export default {
<div class="context-header ide-context-header">
<a :href="project.web_url" :title="s__('IDE|Go to project')" data-testid="go-to-project-link">
<project-avatar
+ :project-id="project.id"
:project-name="project.name"
:project-avatar-url="project.avatar_url"
:size="48"
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index c9bf84be6ac..737ff49f74c 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -52,7 +52,7 @@ export default {
</script>
<template>
- <div class="ide-file-list qa-file-list">
+ <div class="ide-file-list" data-qa-selector="file_list_container">
<template v-if="showLoading">
<div v-for="n in 3" :key="n" class="multi-file-loading-container">
<gl-skeleton-loader />
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
index 46128651547..5f67eee5f18 100644
--- a/app/assets/javascripts/ide/lib/common/model.js
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -51,7 +51,7 @@ export default class Model {
}
get language() {
- return this.model.getModeId();
+ return this.model.getLanguageId();
}
get path() {
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index b4ceec22822..fe687ea9767 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -133,9 +133,6 @@ export default {
this.model = null;
}
},
- helpHtmlConfig: {
- ADD_ATTR: ['target'], // allow external links, can be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1427 is implemented
- },
};
</script>
@@ -147,7 +144,7 @@ export default {
:state="valid"
>
<template v-if="!isCheckbox" #description>
- <span v-safe-html:[$options.helpHtmlConfig]="help"></span>
+ <span v-safe-html="help"></span>
</template>
<template v-if="isCheckbox">
@@ -155,7 +152,7 @@ export default {
<gl-form-checkbox :id="fieldId" v-model="model" :disabled="isInheriting">
{{ checkboxLabel || humanizedTitle }}
<template #help>
- <span v-safe-html:[$options.helpHtmlConfig]="help"></span>
+ <span v-safe-html="help"></span>
</template>
</gl-form-checkbox>
</template>
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index f1f574c6424..7a6f1a953a8 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -192,11 +192,7 @@ export default {
this.integrationActive = integrationActive;
},
},
- descriptionHtmlConfig: {
- ADD_ATTR: ['target'], // allow external links, can be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1427 is implemented
- },
helpHtmlConfig: {
- ADD_ATTR: ['target'], // allow external links, can be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1427 is implemented
ADD_TAGS: ['use'], // to support icon SVGs
FORBID_ATTR: [], // This is trusted input so we can override the default config to allow data-* attributes
},
@@ -254,7 +250,7 @@ export default {
{{ $options.billingPlanNames[section.plan] }}
</gl-badge>
</h4>
- <p v-safe-html:[$options.descriptionHtmlConfig]="section.description"></p>
+ <p v-safe-html="section.description"></p>
</div>
<div class="col-lg-8">
diff --git a/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue b/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
index 1255ed01f6d..a8389e32b40 100644
--- a/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
+++ b/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
@@ -125,6 +125,7 @@ export default {
>
<project-avatar
class="gl-mr-3"
+ :project-id="item.id"
:project-avatar-url="item.avatar_url"
:project-name="item.name"
aria-hidden="true"
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index b71cfbb6112..87f1ed31a7f 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -6,6 +6,9 @@ import {
GlLink,
GlSprintf,
GlFormCheckboxGroup,
+ GlButton,
+ GlCollapse,
+ GlIcon,
} from '@gitlab/ui';
import { partition, isString, uniqueId, isEmpty } from 'lodash';
import InviteModalBase from 'ee_else_ce/invite_members/components/invite_modal_base.vue';
@@ -13,7 +16,7 @@ import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { getParameterValues } from '~/lib/utils/url_utility';
-import { n__ } from '~/locale';
+import { n__, sprintf } from '~/locale';
import {
CLOSE_TO_LIMIT_COUNT,
USERS_FILTER_ALL,
@@ -38,6 +41,9 @@ export default {
GlDropdownItem,
GlSprintf,
GlFormCheckboxGroup,
+ GlButton,
+ GlCollapse,
+ GlIcon,
InviteModalBase,
MembersTokenSelect,
ModalConfetti,
@@ -110,6 +116,8 @@ export default {
mode: 'default',
// Kept in sync with "base"
selectedAccessLevel: undefined,
+ errorsLimit: 2,
+ isErrorsSectionExpanded: false,
};
},
computed: {
@@ -135,7 +143,7 @@ export default {
return n__(
"InviteMembersModal|The following member couldn't be invited",
"InviteMembersModal|The following %d members couldn't be invited",
- Object.keys(this.invalidMembers).length,
+ this.errorList.length,
);
},
tasksToBeDoneEnabled() {
@@ -187,6 +195,29 @@ export default {
? this.$options.labels.placeHolderDisabled
: this.$options.labels.placeHolder;
},
+ errorList() {
+ return Object.entries(this.invalidMembers).map(([member, error]) => {
+ return { member, displayedMemberName: this.tokenName(member), message: error };
+ });
+ },
+ errorsLimited() {
+ return this.errorList.slice(0, this.errorsLimit);
+ },
+ errorsExpanded() {
+ return this.errorList.slice(this.errorsLimit);
+ },
+ shouldErrorsSectionExpand() {
+ return Boolean(this.errorsExpanded.length);
+ },
+ errorCollapseText() {
+ if (this.isErrorsSectionExpanded) {
+ return this.$options.labels.expandedErrors;
+ }
+
+ return sprintf(this.$options.labels.collapsedErrors, {
+ count: this.errorsExpanded.length,
+ });
+ },
},
mounted() {
eventHub.$on('openModal', (options) => {
@@ -311,6 +342,9 @@ export default {
delete this.invalidMembers[memberName(token)];
this.invalidMembers = { ...this.invalidMembers };
},
+ toggleErrorExpansion() {
+ this.isErrorsSectionExpanded = !this.isErrorsSectionExpanded;
+ },
},
labels: MEMBER_MODAL_LABELS,
};
@@ -356,11 +390,37 @@ export default {
data-testid="alert-member-error"
>
{{ $options.labels.memberErrorListText }}
- <ul class="gl-pl-5">
- <li v-for="(error, member) in invalidMembers" :key="member">
- <strong>{{ tokenName(member) }}:</strong> {{ error }}
+ <ul class="gl-pl-5 gl-mb-0">
+ <li v-for="error in errorsLimited" :key="error.member" data-testid="errors-limited-item">
+ <strong>{{ error.displayedMemberName }}:</strong> {{ error.message }}
</li>
</ul>
+ <template v-if="shouldErrorsSectionExpand">
+ <gl-collapse v-model="isErrorsSectionExpanded">
+ <ul class="gl-pl-5 gl-mb-0">
+ <li
+ v-for="error in errorsExpanded"
+ :key="error.member"
+ data-testid="errors-expanded-item"
+ >
+ <strong>{{ error.displayedMemberName }}:</strong> {{ error.message }}
+ </li>
+ </ul>
+ </gl-collapse>
+ <gl-button
+ class="gl-text-decoration-none! gl-shadow-none! gl-mt-3"
+ data-testid="accordion-button"
+ variant="link"
+ @click="toggleErrorExpansion"
+ >
+ {{ errorCollapseText }}
+ <gl-icon
+ name="chevron-down"
+ class="gl-transition-medium"
+ :class="{ 'gl-rotate-180': isErrorsSectionExpanded }"
+ />
+ </gl-button>
+ </template>
</gl-alert>
<user-limit-notification
v-else
diff --git a/app/assets/javascripts/invite_members/components/members_token_select.vue b/app/assets/javascripts/invite_members/components/members_token_select.vue
index b2bcb9a5906..2ddb04e1eeb 100644
--- a/app/assets/javascripts/invite_members/components/members_token_select.vue
+++ b/app/assets/javascripts/invite_members/components/members_token_select.vue
@@ -1,10 +1,16 @@
<script>
import { GlTokenSelector, GlAvatar, GlAvatarLabeled, GlIcon, GlSprintf } from '@gitlab/ui';
-import { debounce } from 'lodash';
+import { debounce, isEmpty } from 'lodash';
import { __ } from '~/locale';
import { getUsers } from '~/rest_api';
import { memberName } from '../utils/member_utils';
-import { SEARCH_DELAY, USERS_FILTER_ALL, USERS_FILTER_SAML_PROVIDER_ID } from '../constants';
+import {
+ SEARCH_DELAY,
+ USERS_FILTER_ALL,
+ USERS_FILTER_SAML_PROVIDER_ID,
+ VALID_TOKEN_BACKGROUND,
+ INVALID_TOKEN_BACKGROUND,
+} from '../constants';
export default {
components: {
@@ -75,6 +81,25 @@ export default {
}
return this.$options.defaultQueryOptions;
},
+ hasInvalidMembers() {
+ return !isEmpty(this.invalidMembers);
+ },
+ },
+ watch: {
+ // We might not really want this to be *reactive* since we want the "class" state to be
+ // tied to the specific `selectedToken` such that if the token is removed and re-added, this
+ // state is reset.
+ // See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90076#note_1027165312
+ hasInvalidMembers: {
+ handler(updatedInvalidMembers) {
+ // Only update tokens if we receive invalid members
+ if (!updatedInvalidMembers) {
+ return;
+ }
+
+ this.updateTokenClasses();
+ },
+ },
},
methods: {
handleTextInput(query) {
@@ -83,6 +108,12 @@ export default {
this.loading = true;
this.retrieveUsers(query);
},
+ updateTokenClasses() {
+ this.selectedTokens = this.selectedTokens.map((token) => ({
+ ...token,
+ class: this.tokenClass(token),
+ }));
+ },
retrieveUsers: debounce(function debouncedRetrieveUsers() {
return getUsers(this.query, this.queryOptions)
.then((response) => {
@@ -98,6 +129,14 @@ export default {
this.loading = false;
});
}, SEARCH_DELAY),
+ tokenClass(token) {
+ if (this.hasError(token)) {
+ return INVALID_TOKEN_BACKGROUND;
+ }
+
+ // assume success for this token
+ return VALID_TOKEN_BACKGROUND;
+ },
handleInput() {
this.$emit('input', this.selectedTokens);
},
diff --git a/app/assets/javascripts/invite_members/components/user_limit_notification.vue b/app/assets/javascripts/invite_members/components/user_limit_notification.vue
index ae5c3c11386..6c9b1f8e6d0 100644
--- a/app/assets/javascripts/invite_members/components/user_limit_notification.vue
+++ b/app/assets/javascripts/invite_members/components/user_limit_notification.vue
@@ -10,7 +10,6 @@ import {
CLOSE_TO_LIMIT_MESSAGE,
CLOSE_TO_LIMIT_MESSAGE_PERSONAL_NAMESPACE,
DANGER_ALERT_TITLE_PERSONAL_NAMESPACE,
- WARNING_ALERT_TITLE_PERSONAL_NAMESPACE,
} from '../constants';
export default {
@@ -46,13 +45,6 @@ export default {
return this.usersLimitDataset.purchasePath;
},
warningAlertTitle() {
- if (this.usersLimitDataset.userNamespace) {
- return sprintf(WARNING_ALERT_TITLE_PERSONAL_NAMESPACE, {
- count: this.freeUsersLimit - this.membersCount,
- members: this.pluralMembers(this.freeUsersLimit - this.membersCount),
- });
- }
-
return sprintf(WARNING_ALERT_TITLE, {
count: this.freeUsersLimit - this.membersCount,
members: this.pluralMembers(this.freeUsersLimit - this.membersCount),
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 6141e5e9e0b..1ceb63e2146 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -2,6 +2,8 @@ import { s__ } from '~/locale';
export const CLOSE_TO_LIMIT_COUNT = 2;
export const SEARCH_DELAY = 200;
+export const VALID_TOKEN_BACKGROUND = 'gl-bg-green-100';
+export const INVALID_TOKEN_BACKGROUND = 'gl-bg-red-100';
export const INVITE_MEMBERS_FOR_TASK = {
minimum_access_level: 30,
name: 'invite_members_for_task',
@@ -77,6 +79,8 @@ export const HEADER_CLOSE_LABEL = s__('InviteMembersModal|Close invite team memb
export const MEMBER_ERROR_LIST_TEXT = s__(
'InviteMembersModal|Review the invite errors and try again:',
);
+export const COLLAPSED_ERRORS = s__('InviteMembersModal|Show more (%{count})');
+export const EXPANDED_ERRORS = s__('InviteMembersModal|Show less');
export const MEMBER_MODAL_LABELS = {
modal: {
@@ -113,6 +117,8 @@ export const MEMBER_MODAL_LABELS = {
},
toastMessageSuccessful: TOAST_MESSAGE_SUCCESSFUL,
memberErrorListText: MEMBER_ERROR_LIST_TEXT,
+ collapsedErrors: COLLAPSED_ERRORS,
+ expandedErrors: EXPANDED_ERRORS,
};
export const GROUP_MODAL_LABELS = {
@@ -136,9 +142,6 @@ export const ON_SUBMIT_TRACK_LABEL = 'manage_members_clicked';
export const WARNING_ALERT_TITLE = s__(
'InviteMembersModal|You only have space for %{count} more %{members} in %{name}',
);
-export const WARNING_ALERT_TITLE_PERSONAL_NAMESPACE = s__(
- 'InviteMembersModal|You only have space for %{count} more %{members} in your personal projects',
-);
export const DANGER_ALERT_TITLE = s__(
"InviteMembersModal|You've reached your %{count} %{members} limit for %{name}",
);
@@ -153,12 +156,12 @@ export const REACHED_LIMIT_MESSAGE = s__(
export const REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE = REACHED_LIMIT_MESSAGE.concat(
s__(
- 'InviteMembersModal| To get more members and access to additional paid features, an owner of this namespace can start a trial or upgrade to a paid tier.',
+ '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.',
),
);
export const CLOSE_TO_LIMIT_MESSAGE = s__(
- 'InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier.',
+ 'InviteMembersModal|To get more members an owner of the group can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier.',
);
export const CLOSE_TO_LIMIT_MESSAGE_PERSONAL_NAMESPACE = s__(
'InviteMembersModal|To make more space, you can remove members who no longer need access.',
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index a4be3f205a3..6e2c0ecb5bb 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -20,6 +20,8 @@ export default (function initInviteMembersModal() {
return false;
}
+ const usersLimitDataset = JSON.parse(el.dataset.usersLimitDataset || '{}');
+
inviteMembersModal = new Vue({
el,
name: 'InviteMembersModalRoot',
@@ -38,9 +40,10 @@ export default (function initInviteMembersModal() {
projects: JSON.parse(el.dataset.projects || '[]'),
usersFilter: el.dataset.usersFilter,
filterId: parseInt(el.dataset.filterId, 10),
- usersLimitDataset: convertObjectPropsToCamelCase(
- JSON.parse(el.dataset.usersLimitDataset || '{}'),
- ),
+ usersLimitDataset: convertObjectPropsToCamelCase({
+ ...usersLimitDataset,
+ user_namespace: parseBoolean(usersLimitDataset.user_namespace),
+ }),
},
}),
});
diff --git a/app/assets/javascripts/issuable/components/issue_milestone.vue b/app/assets/javascripts/issuable/components/issue_milestone.vue
index 11fc032f34f..4f1001e8c3b 100644
--- a/app/assets/javascripts/issuable/components/issue_milestone.vue
+++ b/app/assets/javascripts/issuable/components/issue_milestone.vue
@@ -73,7 +73,9 @@ export default {
<template>
<div ref="milestoneDetails" class="issue-milestone-details">
<gl-icon :size="16" class="gl-mr-2 flex-shrink-0" name="clock" />
- <span class="milestone-title d-inline-block">{{ milestone.title }}</span>
+ <span class="milestone-title gl-display-inline-block gl-text-truncate">{{
+ milestone.title
+ }}</span>
<gl-tooltip :target="() => $refs.milestoneDetails" placement="bottom" class="js-item-milestone">
<span class="bold">{{ __('Milestone') }}</span> <br />
<span>{{ milestone.title }}</span> <br />
diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue
index a505a988360..667c712d3be 100644
--- a/app/assets/javascripts/issuable/components/related_issuable_item.vue
+++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue
@@ -2,29 +2,35 @@
import '~/commons/bootstrap';
import {
GlIcon,
+ GlLink,
GlTooltip,
GlTooltipDirective,
GlButton,
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import { TYPE_WORK_ITEM } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { setUrlParams, updateHistory } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import relatedIssuableMixin from '../mixins/related_issuable_mixin';
import IssueAssignees from './issue_assignees.vue';
import IssueMilestone from './issue_milestone.vue';
export default {
- name: 'IssueItem',
components: {
IssueMilestone,
IssueAssignees,
CiIcon,
GlIcon,
+ GlLink,
GlTooltip,
IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
IssueDueDate,
GlButton,
+ WorkItemDetailModal,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -47,6 +53,11 @@ export default {
required: false,
default: '',
},
+ workItemType: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
stateTitle() {
@@ -62,6 +73,27 @@ export default {
iconClasses() {
return `${this.iconClass} ic-${this.iconName}`;
},
+ workItemId() {
+ return convertToGraphQLId(TYPE_WORK_ITEM, this.idKey);
+ },
+ },
+ methods: {
+ handleTitleClick(event) {
+ if (this.workItemType === 'TASK') {
+ event.preventDefault();
+ this.$refs.modal.show();
+ this.updateWorkItemIdUrlQuery(this.idKey);
+ }
+ },
+ handleWorkItemDeleted(workItemId) {
+ this.$emit('relatedIssueRemoveRequest', workItemId);
+ },
+ updateWorkItemIdUrlQuery(workItemId) {
+ updateHistory({
+ url: setUrlParams({ work_item_id: workItemId }),
+ replace: true,
+ });
+ },
},
};
</script>
@@ -102,7 +134,13 @@ export default {
class="confidential-icon gl-mr-2 align-self-baseline align-self-md-auto mt-xl-0"
:aria-label="__('Confidential')"
/>
- <a :href="computedPath" class="sortable-link gl-font-weight-normal">{{ title }}</a>
+ <gl-link
+ :href="computedPath"
+ class="sortable-link gl-font-weight-normal"
+ @click="handleTitleClick"
+ >
+ {{ title }}
+ </gl-link>
</div>
<!-- Info area: meta, path, and assignees -->
@@ -178,16 +216,15 @@ export default {
<span
v-if="isLocked"
- ref="lockIcon"
v-gl-tooltip
class="gl-px-3 gl-display-inline-block gl-cursor-not-allowed"
:title="lockedMessage"
+ data-testid="lockIcon"
>
<gl-icon name="lock" />
</span>
<gl-button
v-else-if="canRemove"
- ref="removeButton"
v-gl-tooltip
icon="close"
category="tertiary"
@@ -198,5 +235,11 @@ export default {
:aria-label="__('Remove')"
@click="onRemoveRequest"
/>
+ <work-item-detail-modal
+ ref="modal"
+ :work-item-id="workItemId"
+ @close="updateWorkItemIdUrlQuery"
+ @workItemDeleted="handleWorkItemDeleted"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/issuable/issuable_template_selector.js b/app/assets/javascripts/issuable/issuable_template_selector.js
index cce903d388d..6b8f3de8d49 100644
--- a/app/assets/javascripts/issuable/issuable_template_selector.js
+++ b/app/assets/javascripts/issuable/issuable_template_selector.js
@@ -17,7 +17,15 @@ export default class IssuableTemplateSelector extends TemplateSelector {
name: this.dropdown.data('selected'),
};
- if (initialQuery.name) this.requestFile(initialQuery);
+ // Only use the default template if we don't have description data from autosave
+ if (!initialQuery.name && this.dropdown.data('default') && !this.editor.getValue().length) {
+ initialQuery.name = this.dropdown.data('default');
+ }
+
+ if (initialQuery.name) {
+ this.requestFile(initialQuery);
+ this.setToggleText(initialQuery.name);
+ }
$('.reset-template', this.dropdown.parent()).on('click', () => {
this.setInputValueToTemplateContent();
@@ -53,10 +61,14 @@ export default class IssuableTemplateSelector extends TemplateSelector {
}
this.setInputValueToTemplateContent();
- $('.dropdown-toggle-text', this.dropdown).text(__('Choose a template'));
+ this.setToggleText(__('Choose a template'));
this.previousSelectedIndex = null;
}
+ setToggleText(text) {
+ $('.dropdown-toggle-text', this.dropdown).text(text);
+ }
+
setSelectedIndex() {
this.previousSelectedIndex = this.dropdown.data('deprecatedJQueryDropdown').selectedIndex;
}
diff --git a/app/assets/javascripts/issuable/popover/components/issue_popover.vue b/app/assets/javascripts/issuable/popover/components/issue_popover.vue
index 0cafaa1e500..945a3782642 100644
--- a/app/assets/javascripts/issuable/popover/components/issue_popover.vue
+++ b/app/assets/javascripts/issuable/popover/components/issue_popover.vue
@@ -1,14 +1,26 @@
<script>
-import { GlPopover, GlSkeletonLoader } from '@gitlab/ui';
+import { GlIcon, GlPopover, GlSkeletonLoader, GlTooltipDirective } from '@gitlab/ui';
+import query from 'ee_else_ce/issuable/popover/queries/issue.query.graphql';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import IssueMilestone from '~/issuable/components/issue_milestone.vue';
import StatusBox from '~/issuable/components/status_box.vue';
+import { IssuableStatus } from '~/issues/constants';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import query from '../queries/issue.query.graphql';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
export default {
components: {
+ GlIcon,
GlPopover,
GlSkeletonLoader,
+ IssueDueDate,
+ IssueMilestone,
+ IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
StatusBox,
+ WorkItemTypeIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
mixins: [timeagoMixin],
props: {
@@ -44,6 +56,9 @@ export default {
showDetails() {
return Object.keys(this.issue).length > 0;
},
+ isIssueClosed() {
+ return this.issue?.state === IssuableStatus.Closed;
+ },
},
apollo: {
issue: {
@@ -69,15 +84,46 @@ export default {
</gl-skeleton-loader>
<div v-else-if="showDetails" class="gl-display-flex gl-align-items-center">
<status-box issuable-type="issue" :initial-state="issue.state" />
+ <gl-icon
+ v-if="issue.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ class="gl-text-orange-500 gl-mr-2"
+ :aria-label="__('Confidential')"
+ />
<span class="gl-text-secondary">
{{ __('Opened') }} <time :datetime="issue.createdAt">{{ formattedTime }}</time>
</span>
</div>
<h5 v-if="!$apollo.queries.issue.loading" class="gl-my-3">{{ title }}</h5>
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
- <div class="gl-text-secondary">
- {{ `${projectPath}#${iid}` }}
+ <div>
+ <work-item-type-icon v-if="!$apollo.queries.issue.loading" :work-item-type="issue.type" />
+ <span class="gl-text-secondary">{{ `${projectPath}#${iid}` }}</span>
</div>
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
+
+ <div v-if="!$apollo.queries.issue.loading" class="gl-display-flex gl-text-secondary gl-mt-2">
+ <issue-due-date
+ v-if="issue.dueDate"
+ :date="issue.dueDate.toString()"
+ :closed="isIssueClosed"
+ tooltip-placement="top"
+ class="gl-mr-4"
+ css-class="gl-display-flex gl-white-space-nowrap"
+ />
+ <issue-weight
+ v-if="issue.weight"
+ :weight="issue.weight"
+ tag-name="span"
+ class="gl-display-flex gl-mr-4"
+ />
+ <issue-milestone
+ v-if="issue.milestone"
+ :milestone="issue.milestone"
+ class="gl-display-flex gl-overflow-hidden"
+ />
+ </div>
</gl-popover>
</template>
diff --git a/app/assets/javascripts/issuable/popover/queries/issue.query.graphql b/app/assets/javascripts/issuable/popover/queries/issue.query.graphql
index 47a62e2b6ea..1bbe6cb6eac 100644
--- a/app/assets/javascripts/issuable/popover/queries/issue.query.graphql
+++ b/app/assets/javascripts/issuable/popover/queries/issue.query.graphql
@@ -6,6 +6,15 @@ query issue($projectPath: ID!, $iid: String!) {
title
createdAt
state
+ confidential
+ dueDate
+ milestone {
+ id
+ title
+ startDate
+ dueDate
+ }
+ type
}
}
}
diff --git a/app/assets/javascripts/issues/index.js b/app/assets/javascripts/issues/index.js
index 380bb5f5346..22ac37656ea 100644
--- a/app/assets/javascripts/issues/index.js
+++ b/app/assets/javascripts/issues/index.js
@@ -9,7 +9,7 @@ import { IssueType } from '~/issues/constants';
import Issue from '~/issues/issue';
import { initTitleSuggestions, initTypePopover } from '~/issues/new';
import { initRelatedMergeRequests } from '~/issues/related_merge_requests';
-import initRelatedIssues from '~/related_issues';
+import { initRelatedIssues } from '~/related_issues';
import {
initHeaderActions,
initIncidentApp,
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 f567b0f1d68..11911adb401 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -39,13 +39,13 @@ import {
TOKEN_TITLE_TYPE,
} from '~/vue_shared/components/filtered_search_bar/constants';
import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
-import {
- IssuableListTabs,
- IssuableStates,
- IssuableTypes,
-} from '~/vue_shared/issuable/list/constants';
+import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { WORK_ITEM_TYPE_ENUM_TASK } from '~/work_items/constants';
import {
CREATED_DESC,
+ defaultTypeTokenOptions,
+ defaultWorkItemTypes,
i18n,
ISSUE_REFERENCE,
MAX_LIST_SIZE,
@@ -67,6 +67,7 @@ import {
TOKEN_TYPE_ORGANIZATION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
+ TYPE_TOKEN_TASK_OPTION,
UPDATED_DESC,
urlSortParams,
} from '../constants';
@@ -107,7 +108,6 @@ const CrmOrganizationToken = () =>
export default {
i18n,
IssuableListTabs,
- IssuableTypes: [IssuableTypes.Issue, IssuableTypes.Incident, IssuableTypes.TestCase],
components: {
CsvImportExportButtons,
GlButton,
@@ -123,6 +123,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [glFeatureFlagMixin()],
inject: [
'autocompleteAwardEmojisPath',
'calendarPath',
@@ -180,9 +181,7 @@ export default {
issues: {
query: getIssuesQuery,
variables() {
- const { types } = this.queryVariables;
-
- return { ...this.queryVariables, types: types ? [types] : this.$options.IssuableTypes };
+ return this.queryVariables;
},
update(data) {
return data[this.namespace]?.issues.nodes ?? [];
@@ -206,9 +205,7 @@ export default {
issuesCounts: {
query: getIssuesCountsQuery,
variables() {
- const { types } = this.queryVariables;
-
- return { ...this.queryVariables, types: types ? [types] : this.$options.IssuableTypes };
+ return this.queryVariables;
},
update(data) {
return data[this.namespace] ?? {};
@@ -240,11 +237,22 @@ export default {
state: this.state,
...this.pageParams,
...this.apiFilterParams,
+ types: this.apiFilterParams.types || this.defaultWorkItemTypes,
};
},
namespace() {
return this.isProject ? ITEM_TYPE.PROJECT : ITEM_TYPE.GROUP;
},
+ defaultWorkItemTypes() {
+ return this.isWorkItemsEnabled
+ ? defaultWorkItemTypes.concat(WORK_ITEM_TYPE_ENUM_TASK)
+ : defaultWorkItemTypes;
+ },
+ typeTokenOptions() {
+ return this.isWorkItemsEnabled
+ ? defaultTypeTokenOptions.concat(TYPE_TOKEN_TASK_OPTION)
+ : defaultTypeTokenOptions;
+ },
hasSearch() {
return (
this.searchQuery ||
@@ -262,6 +270,9 @@ export default {
isOpenTab() {
return this.state === IssuableStates.Opened;
},
+ isWorkItemsEnabled() {
+ return this.glFeatures.workItems;
+ },
showCsvButtons() {
return this.isProject && this.isSignedIn;
},
@@ -340,11 +351,7 @@ export default {
title: TOKEN_TITLE_TYPE,
icon: 'issues',
token: GlFilteredSearchToken,
- options: [
- { icon: 'issue-type-issue', title: 'issue', value: 'issue' },
- { icon: 'issue-type-incident', title: 'incident', value: 'incident' },
- { icon: 'issue-type-test-case', title: 'test_case', value: 'test_case' },
- ],
+ options: this.typeTokenOptions,
},
];
@@ -767,6 +774,7 @@ export default {
:show-page-size-change-controls="showPageSizeControls"
:has-next-page="pageInfo.hasNextPage"
:has-previous-page="pageInfo.hasPreviousPage"
+ show-work-item-type-icon
@click-tab="handleClickTab"
@dismiss-alert="handleDismissAlert"
@filter="handleFilter"
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index a921eb62e26..38fe4c33792 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -8,6 +8,11 @@ import {
OPERATOR_IS,
OPERATOR_IS_NOT,
} 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,
+} from '~/work_items/constants';
export const i18n = {
anonymousSearchingMessage: __('You must sign in to search for specific terms.'),
@@ -147,6 +152,20 @@ export const TOKEN_TYPE_WEIGHT = 'weight';
export const TOKEN_TYPE_CONTACT = 'crm_contact';
export const TOKEN_TYPE_ORGANIZATION = 'crm_organization';
+export const TYPE_TOKEN_TASK_OPTION = { icon: 'task-done', title: 'task', value: 'task' };
+
+export const defaultWorkItemTypes = [
+ WORK_ITEM_TYPE_ENUM_ISSUE,
+ WORK_ITEM_TYPE_ENUM_INCIDENT,
+ WORK_ITEM_TYPE_ENUM_TEST_CASE,
+];
+
+export const defaultTypeTokenOptions = [
+ { icon: 'issue-type-issue', title: 'issue', value: 'issue' },
+ { icon: 'issue-type-incident', title: 'incident', value: 'incident' },
+ { icon: 'issue-type-test-case', title: 'test_case', value: 'test_case' },
+];
+
export const filters = {
[TOKEN_TYPE_AUTHOR]: {
[API_PARAM]: {
diff --git a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
index 35762120f71..040763f2ba4 100644
--- a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
+++ b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql
@@ -1,5 +1,4 @@
fragment IssueFragment on Issue {
- __typename
id
iid
confidential
@@ -18,9 +17,9 @@ fragment IssueFragment on Issue {
userDiscussionsCount @include(if: $isSignedIn)
webPath
webUrl
+ type
assignees @skip(if: $hideUsers) {
nodes {
- __typename
id
avatarUrl
name
@@ -29,7 +28,6 @@ fragment IssueFragment on Issue {
}
}
author @skip(if: $hideUsers) {
- __typename
id
avatarUrl
name
diff --git a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
index 1d48446b083..a5cba3daafa 100644
--- a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
@@ -66,7 +66,7 @@ export default {
<template>
<div v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)">
<div class="card card-slim gl-mt-5">
- <div class="card-header">
+ <div class="card-header gl-bg-gray-10">
<div
class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
>
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
index 449da394841..a6747d67611 100644
--- a/app/assets/javascripts/issues/show/components/description.vue
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -133,7 +133,7 @@ export default {
},
computed: {
workItemsEnabled() {
- return this.glFeatures.workItems;
+ return this.glFeatures.workItemsCreateFromMarkdown;
},
taskWorkItemType() {
return this.workItemTypes.find((type) => type.name === TASK_TYPE_NAME)?.id;
@@ -302,7 +302,9 @@ export default {
if (taskRegexMatches) {
$tasks.text(this.taskStatus);
$tasksShort.text(
- `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`,
+ `${taskRegexMatches[1]}/${taskRegexMatches[2]} checklist item${
+ taskRegexMatches[2] > 1 ? 's' : ''
+ }`,
);
} else {
$tasks.text('');
@@ -315,7 +317,7 @@ export default {
}
this.taskButtons = [];
- const taskListFields = this.$el.querySelectorAll('.task-list-item');
+ const taskListFields = this.$el.querySelectorAll('.task-list-item:not(.inapplicable)');
taskListFields.forEach((item, index) => {
const taskLink = item.querySelector('.gfm-issue');
@@ -326,6 +328,7 @@ export default {
}
const workItemId = convertToGraphQLId(TYPE_WORK_ITEM, issue);
this.addHoverListeners(taskLink, workItemId);
+ taskLink.classList.add('gl-link');
taskLink.addEventListener('click', (e) => {
e.preventDefault();
this.openWorkItemDetailModal(taskLink);
diff --git a/app/assets/javascripts/issues/show/components/incidents/constants.js b/app/assets/javascripts/issues/show/components/incidents/constants.js
index 9fc5027d457..77d13fe085a 100644
--- a/app/assets/javascripts/issues/show/components/incidents/constants.js
+++ b/app/assets/javascripts/issues/show/components/incidents/constants.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
export const timelineTabI18n = Object.freeze({
title: s__('Incident|Timeline'),
@@ -12,6 +12,9 @@ export const timelineFormI18n = Object.freeze({
'Incident|Something went wrong while creating the incident timeline event.',
),
areaPlaceholder: s__('Incident|Timeline text...'),
+ save: __('Save'),
+ cancel: __('Cancel'),
+ description: __('Description'),
saveAndAdd: s__('Incident|Save and add another event'),
areaLabel: s__('Incident|Timeline text'),
});
diff --git a/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue b/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue
new file mode 100644
index 00000000000..c902895702e
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue
@@ -0,0 +1,117 @@
+<script>
+import { produce } from 'immer';
+import { sortBy } from 'lodash';
+import { sprintf } from '~/locale';
+import { createAlert } from '~/flash';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_ISSUE } from '~/graphql_shared/constants';
+import { timelineFormI18n } from './constants';
+import TimelineEventsForm from './timeline_events_form.vue';
+
+import CreateTimelineEvent from './graphql/queries/create_timeline_event.mutation.graphql';
+import getTimelineEvents from './graphql/queries/get_timeline_events.query.graphql';
+
+export default {
+ name: 'CreateTimelineEvent',
+ i18n: timelineFormI18n,
+ components: {
+ TimelineEventsForm,
+ },
+ inject: ['fullPath', 'issuableId'],
+ props: {
+ hasTimelineEvents: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return { createTimelineEventActive: false };
+ },
+ methods: {
+ clearForm() {
+ this.$refs.eventForm.clear();
+ },
+ focusDate() {
+ this.$refs.eventForm.focusDate();
+ },
+ updateCache(store, { data }) {
+ const { timelineEvent: event, errors } = data?.timelineEventCreate || {};
+
+ if (errors.length) {
+ return;
+ }
+
+ const variables = {
+ incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
+ fullPath: this.fullPath,
+ };
+
+ const sourceData = store.readQuery({
+ query: getTimelineEvents,
+ variables,
+ });
+
+ const newData = produce(sourceData, (draftData) => {
+ const { nodes: draftEventList } = draftData.project.incidentManagementTimelineEvents;
+ draftEventList.push(event);
+ // ISOStrings sort correctly in lexical order
+ const sortedEvents = sortBy(draftEventList, 'occurredAt');
+ draftData.project.incidentManagementTimelineEvents.nodes = sortedEvents;
+ });
+
+ store.writeQuery({
+ query: getTimelineEvents,
+ variables,
+ data: newData,
+ });
+ },
+ createIncidentTimelineEvent(eventDetails, addAnotherEvent = false) {
+ this.createTimelineEventActive = true;
+ return this.$apollo
+ .mutate({
+ mutation: CreateTimelineEvent,
+ variables: {
+ input: {
+ incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
+ note: eventDetails.note,
+ occurredAt: eventDetails.occurredAt,
+ },
+ },
+ update: this.updateCache,
+ })
+ .then(({ data = {} }) => {
+ this.createTimelineEventActive = false;
+ const errors = data.timelineEventCreate?.errors;
+ if (errors.length) {
+ createAlert({
+ message: sprintf(this.$options.i18n.createError, { error: errors.join('. ') }, false),
+ });
+ return;
+ }
+ if (addAnotherEvent) {
+ this.$refs.eventForm.clear();
+ } else {
+ this.$emit('hide-new-timeline-events-form');
+ }
+ })
+ .catch((error) => {
+ createAlert({
+ message: this.$options.i18n.createErrorGeneric,
+ captureError: true,
+ error,
+ });
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <timeline-events-form
+ ref="eventForm"
+ :is-event-processed="createTimelineEventActive"
+ :has-timeline-events="hasTimelineEvents"
+ @save-event="createIncidentTimelineEvent"
+ @cancel="$emit('hide-new-timeline-events-form')"
+ />
+</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 36ec6362a22..0d84fabb1be 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
@@ -1,21 +1,12 @@
<script>
import { GlDatepicker, GlFormInput, GlFormGroup, GlButton, GlIcon } from '@gitlab/ui';
-import { produce } from 'immer';
-import { sortBy } from 'lodash';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import { TYPE_ISSUE } from '~/graphql_shared/constants';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import { createAlert } from '~/flash';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
-import { sprintf } from '~/locale';
-import { getUtcShiftedDateNow } from './utils';
import { timelineFormI18n } from './constants';
-
-import CreateTimelineEvent from './graphql/queries/create_timeline_event.mutation.graphql';
-import getTimelineEvents from './graphql/queries/get_timeline_events.query.graphql';
+import { getUtcShiftedDateNow } from './utils';
export default {
- name: 'IncidentTimelineEventForm',
+ name: 'TimelineEventsForm',
restrictedToolBarItems: [
'quote',
'strikethrough',
@@ -38,112 +29,55 @@ export default {
directives: {
autofocusonshow,
},
- inject: ['fullPath', 'issuableId'],
props: {
hasTimelineEvents: {
type: Boolean,
required: true,
},
+ isEventProcessed: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
- // Create shifted date to force the datepicker to format in UTC
- const utcShiftedDate = getUtcShiftedDateNow();
+ // if occurredAt is undefined, returns "now" in UTC
+ const placeholderDate = getUtcShiftedDateNow();
+
return {
- currentDate: utcShiftedDate,
- currentHour: utcShiftedDate.getHours(),
- currentMinute: utcShiftedDate.getMinutes(),
timelineText: '',
- createTimelineEventActive: false,
+ placeholderDate,
+ hourPickerInput: placeholderDate.getHours(),
+ minutePickerInput: placeholderDate.getMinutes(),
datepickerTextInput: null,
};
},
+ computed: {
+ occurredAt() {
+ const [years, months, days] = this.datepickerTextInput.split('-');
+ const utcDate = new Date(
+ Date.UTC(years, months - 1, days, this.hourPickerInput, this.minutePickerInput),
+ );
+
+ return utcDate.toISOString();
+ },
+ },
methods: {
clear() {
- const utcShiftedDate = getUtcShiftedDateNow();
- this.currentDate = utcShiftedDate;
- this.currentHour = utcShiftedDate.getHours();
- this.currentMinute = utcShiftedDate.getMinutes();
- },
- hideIncidentTimelineEventForm() {
- this.$emit('hide-incident-timeline-event-form');
+ const utcShiftedDateNow = getUtcShiftedDateNow();
+ this.placeholderDate = utcShiftedDateNow;
+ this.hourPickerInput = utcShiftedDateNow.getHours();
+ this.minutePickerInput = utcShiftedDateNow.getMinutes();
+ this.timelineText = '';
},
focusDate() {
this.$refs.datepicker.$el.focus();
},
- updateCache(store, { data }) {
- const { timelineEvent: event, errors } = data?.timelineEventCreate || {};
-
- if (errors.length) {
- return;
- }
-
- const variables = {
- incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
- fullPath: this.fullPath,
+ handleSave(addAnotherEvent) {
+ const eventDetails = {
+ note: this.timelineText,
+ occurredAt: this.occurredAt,
};
-
- const sourceData = store.readQuery({
- query: getTimelineEvents,
- variables,
- });
-
- const newData = produce(sourceData, (draftData) => {
- const { nodes: draftEventList } = draftData.project.incidentManagementTimelineEvents;
- draftEventList.push(event);
- // ISOStrings sort correctly in lexical order
- const sortedEvents = sortBy(draftEventList, 'occurredAt');
- draftData.project.incidentManagementTimelineEvents.nodes = sortedEvents;
- });
-
- store.writeQuery({
- query: getTimelineEvents,
- variables,
- data: newData,
- });
- },
- createIncidentTimelineEvent(addOneEvent) {
- this.createTimelineEventActive = true;
- return this.$apollo
- .mutate({
- mutation: CreateTimelineEvent,
- variables: {
- input: {
- incidentId: convertToGraphQLId(TYPE_ISSUE, this.issuableId),
- note: this.timelineText,
- occurredAt: this.createDateString(),
- },
- },
- update: this.updateCache,
- })
- .then(({ data = {} }) => {
- const errors = data.timelineEventCreate?.errors;
- if (errors.length) {
- createAlert({
- message: sprintf(this.$options.i18n.createError, { error: errors.join('. ') }, false),
- });
- }
- })
- .catch((error) => {
- createAlert({
- message: this.$options.i18n.createErrorGeneric,
- captureError: true,
- error,
- });
- })
- .finally(() => {
- this.createTimelineEventActive = false;
- this.timelineText = '';
- if (addOneEvent) {
- this.hideIncidentTimelineEventForm();
- }
- });
- },
- createDateString() {
- const [years, months, days] = this.datepickerTextInput.split('-');
- const utcDate = new Date(
- Date.UTC(years, months - 1, days, this.currentHour, this.currentMinute),
- );
- return utcDate.toISOString();
+ this.$emit('save-event', eventDetails, addAnotherEvent);
},
},
};
@@ -165,7 +99,7 @@ export default {
class="gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row datetime-picker"
>
<gl-form-group :label="__('Date')" class="gl-mt-5 gl-mr-5">
- <gl-datepicker id="incident-date" #default="{ formattedDate }" v-model="currentDate">
+ <gl-datepicker id="incident-date" #default="{ formattedDate }" v-model="placeholderDate">
<gl-form-input
id="incident-date"
ref="datepicker"
@@ -184,7 +118,7 @@ export default {
<label label-for="timeline-input-hours" class="sr-only"></label>
<gl-form-input
id="timeline-input-hours"
- v-model="currentHour"
+ v-model="hourPickerInput"
data-testid="input-hours"
size="xs"
type="number"
@@ -194,7 +128,7 @@ export default {
<label label-for="timeline-input-minutes" class="sr-only"></label>
<gl-form-input
id="timeline-input-minutes"
- v-model="currentMinute"
+ v-model="minutePickerInput"
class="gl-ml-3"
data-testid="input-minutes"
size="xs"
@@ -223,9 +157,10 @@ export default {
<textarea
v-model="timelineText"
class="note-textarea js-gfm-input js-autosize markdown-area"
+ data-testid="input-note"
dir="auto"
data-supports-quick-actions="false"
- :aria-label="__('Description')"
+ :aria-label="$options.i18n.description"
:placeholder="$options.i18n.areaPlaceholder"
>
</textarea>
@@ -238,26 +173,22 @@ export default {
variant="confirm"
category="primary"
class="gl-mr-3"
- :loading="createTimelineEventActive"
- @click="createIncidentTimelineEvent(true)"
+ :loading="isEventProcessed"
+ @click="handleSave(false)"
>
- {{ __('Save') }}
+ {{ $options.i18n.save }}
</gl-button>
<gl-button
variant="confirm"
category="secondary"
class="gl-mr-3 gl-ml-n2"
- :loading="createTimelineEventActive"
- @click="createIncidentTimelineEvent(false)"
+ :loading="isEventProcessed"
+ @click="handleSave(true)"
>
{{ $options.i18n.saveAndAdd }}
</gl-button>
- <gl-button
- class="gl-ml-n2"
- :disabled="createTimelineEventActive"
- @click="hideIncidentTimelineEventForm"
- >
- {{ __('Cancel') }}
+ <gl-button class="gl-ml-n2" :disabled="isEventProcessed" @click="$emit('cancel')">
+ {{ $options.i18n.cancel }}
</gl-button>
<div class="gl-border-b gl-pt-5"></div>
</gl-form-group>
diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_item.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_item.vue
new file mode 100644
index 00000000000..6175c9969ec
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/incidents/timeline_events_item.vue
@@ -0,0 +1,100 @@
+<script>
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlSafeHtmlDirective,
+ GlSprintf,
+} from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
+import { getEventIcon } from './utils';
+
+export default {
+ name: 'IncidentTimelineEventListItem',
+ i18n: {
+ delete: __('Delete'),
+ moreActions: __('More actions'),
+ timeUTC: __('%{time} UTC'),
+ },
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlSprintf,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ inject: ['canUpdate'],
+ props: {
+ isLastItem: {
+ type: Boolean,
+ required: true,
+ },
+ occurredAt: {
+ type: String,
+ required: true,
+ },
+ action: {
+ type: String,
+ required: true,
+ },
+ noteHtml: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ time() {
+ return formatDate(this.occurredAt, 'HH:MM', true);
+ },
+ },
+ methods: {
+ getEventIcon,
+ },
+};
+</script>
+<template>
+ <li
+ class="timeline-entry timeline-entry-vertical-line note system-note note-wrapper gl-my-2! gl-pr-0!"
+ >
+ <div class="gl-display-flex gl-align-items-center">
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-n2 gl-mr-3 gl-w-8 gl-h-8 gl-p-3 gl-z-index-1"
+ >
+ <gl-icon :name="getEventIcon(action)" class="note-icon" />
+ </div>
+ <div
+ class="timeline-event-note gl-w-full gl-display-flex gl-flex-direction-row"
+ :class="{ 'gl-pb-3 gl-border-gray-50 gl-border-1 gl-border-b-solid': !isLastItem }"
+ data-testid="event-text-container"
+ >
+ <div>
+ <strong class="gl-font-lg" data-testid="event-time">
+ <gl-sprintf :message="$options.i18n.timeUTC">
+ <template #time>{{ time }}</template>
+ </gl-sprintf>
+ </strong>
+ <div v-safe-html="noteHtml"></div>
+ </div>
+ <gl-dropdown
+ v-if="canUpdate"
+ right
+ class="event-note-actions gl-ml-auto gl-align-self-center"
+ icon="ellipsis_v"
+ text-sr-only
+ :text="$options.i18n.moreActions"
+ category="tertiary"
+ no-caret
+ >
+ <gl-dropdown-item @click="$emit('delete')">
+ <gl-button>{{ $options.i18n.delete }}</gl-button>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue
index 519c0d402a0..80ac1c372cd 100644
--- a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue
+++ b/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue
@@ -4,7 +4,7 @@ import { createAlert } from '~/flash';
import { sprintf } from '~/locale';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
-import IncidentTimelineEventListItem from './timeline_events_list_item.vue';
+import IncidentTimelineEventItem from './timeline_events_item.vue';
import deleteTimelineEvent from './graphql/queries/delete_timeline_event.mutation.graphql';
import { timelineListI18n } from './constants';
@@ -12,7 +12,7 @@ export default {
name: 'IncidentTimelineEventList',
i18n: timelineListI18n,
components: {
- IncidentTimelineEventListItem,
+ IncidentTimelineEventItem,
},
props: {
timelineEventLoading: {
@@ -99,16 +99,21 @@ export default {
<div class="gl-pb-3 gl-border-gray-50 gl-border-1 gl-border-b-solid">
<strong class="gl-font-size-h2" data-testid="event-date">{{ eventDate }}</strong>
</div>
- <ul class="notes main-notes-list gl-pl-n3">
- <incident-timeline-event-list-item
+ <ul class="notes main-notes-list">
+ <li
v-for="(event, eventIndex) in events"
- :key="event.id"
- :action="event.action"
- :occurred-at="event.occurredAt"
- :note-html="event.noteHtml"
- :is-last-item="isLastItem(dateGroupedEvents, groupIndex, events, eventIndex)"
- @delete="handleDelete(event)"
- />
+ :key="eventIndex"
+ class="timeline-entry-vertical-line note system-note note-wrapper gl-my-2! gl-pr-0!"
+ >
+ <incident-timeline-event-item
+ :key="event.id"
+ :action="event.action"
+ :occurred-at="event.occurredAt"
+ :note-html="event.noteHtml"
+ :is-last-item="isLastItem(dateGroupedEvents, groupIndex, events, eventIndex)"
+ @delete="handleDelete(event)"
+ />
+ </li>
</ul>
</div>
</div>
diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list_item.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_list_item.vue
deleted file mode 100644
index 62ccd696ef6..00000000000
--- a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list_item.vue
+++ /dev/null
@@ -1,92 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlIcon, GlSafeHtmlDirective, GlSprintf } from '@gitlab/ui';
-import { formatDate } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
-import { getEventIcon } from './utils';
-
-export default {
- name: 'IncidentTimelineEventListItem',
- i18n: {
- delete: __('Delete'),
- moreActions: __('More actions'),
- timeUTC: __('%{time} UTC'),
- },
- components: {
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- GlSprintf,
- },
- directives: {
- SafeHtml: GlSafeHtmlDirective,
- },
- inject: ['canUpdate'],
- props: {
- isLastItem: {
- type: Boolean,
- required: true,
- },
- occurredAt: {
- type: String,
- required: true,
- },
- action: {
- type: String,
- required: true,
- },
- noteHtml: {
- type: String,
- required: true,
- },
- },
- computed: {
- time() {
- return formatDate(this.occurredAt, 'HH:MM', true);
- },
- },
- methods: {
- getEventIcon,
- },
-};
-</script>
-<template>
- <li
- class="timeline-entry timeline-entry-vertical-line note system-note note-wrapper gl-my-2! gl-pr-0!"
- >
- <div class="gl-display-flex gl-align-items-center">
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-mt-n2 gl-mr-3 gl-w-8 gl-h-8 gl-p-3 gl-z-index-1"
- >
- <gl-icon :name="getEventIcon(action)" class="note-icon" />
- </div>
- <div
- class="timeline-event-note gl-w-full gl-display-flex gl-flex-direction-row"
- :class="{ 'gl-pb-3 gl-border-gray-50 gl-border-1 gl-border-b-solid': !isLastItem }"
- data-testid="event-text-container"
- >
- <div>
- <strong class="gl-font-lg" data-testid="event-time">
- <gl-sprintf :message="$options.i18n.timeUTC">
- <template #time>{{ time }}</template>
- </gl-sprintf>
- </strong>
- <div v-safe-html="noteHtml"></div>
- </div>
- <gl-dropdown
- v-if="canUpdate"
- right
- class="event-note-actions gl-ml-auto gl-align-self-center"
- icon="ellipsis_v"
- text-sr-only
- :text="$options.i18n.moreActions"
- category="tertiary"
- no-caret
- >
- <gl-dropdown-item @click="$emit('delete')">
- {{ $options.i18n.delete }}
- </gl-dropdown-item>
- </gl-dropdown>
- </div>
- </div>
- </li>
-</template>
diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_tab.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_tab.vue
index e1946ef4d07..7c2a7878c58 100644
--- a/app/assets/javascripts/issues/show/components/incidents/timeline_events_tab.vue
+++ b/app/assets/javascripts/issues/show/components/incidents/timeline_events_tab.vue
@@ -7,7 +7,7 @@ import getTimelineEvents from './graphql/queries/get_timeline_events.query.graph
import { displayAndLogError } from './utils';
import { timelineTabI18n } from './constants';
-import IncidentTimelineEventForm from './timeline_events_form.vue';
+import CreateTimelineEvent from './create_timeline_event.vue';
import IncidentTimelineEventsList from './timeline_events_list.vue';
export default {
@@ -16,7 +16,7 @@ export default {
GlEmptyState,
GlLoadingIcon,
GlTab,
- IncidentTimelineEventForm,
+ CreateTimelineEvent,
IncidentTimelineEventsList,
},
i18n: timelineTabI18n,
@@ -61,10 +61,10 @@ export default {
this.isEventFormVisible = false;
},
async showEventForm() {
- this.$refs.eventForm.clear();
+ this.$refs.createEventForm.clearForm();
this.isEventFormVisible = true;
await this.$nextTick();
- this.$refs.eventForm.focusDate();
+ this.$refs.createEventForm.focusDate();
},
},
};
@@ -82,14 +82,15 @@ export default {
v-if="hasTimelineEvents"
:timeline-event-loading="timelineEventLoading"
:timeline-events="timelineEvents"
+ @hide-new-timeline-events-form="hideEventForm"
/>
- <incident-timeline-event-form
+ <create-timeline-event
v-show="isEventFormVisible"
- ref="eventForm"
+ ref="createEventForm"
:has-timeline-events="hasTimelineEvents"
class="timeline-event-note timeline-event-note-form"
:class="{ 'gl-pl-0': !hasTimelineEvents }"
- @hide-incident-timeline-event-form="hideEventForm"
+ @hide-new-timeline-events-form="hideEventForm"
/>
<gl-button v-if="canUpdate" variant="default" class="gl-mb-3 gl-mt-7" @click="showEventForm">
{{ $options.i18n.addEventButton }}
diff --git a/app/assets/javascripts/issues/show/components/incidents/utils.js b/app/assets/javascripts/issues/show/components/incidents/utils.js
index 256e3025f19..cf790a11b67 100644
--- a/app/assets/javascripts/issues/show/components/incidents/utils.js
+++ b/app/assets/javascripts/issues/show/components/incidents/utils.js
@@ -11,6 +11,7 @@ export const displayAndLogError = (error) =>
const EVENT_ICONS = {
comment: 'comment',
issues: 'issues',
+ label: 'label',
status: 'status',
default: 'comment',
};
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue
index da72cbeb856..4046e1ade82 100644
--- a/app/assets/javascripts/jobs/components/environments_block.vue
+++ b/app/assets/javascripts/jobs/components/environments_block.vue
@@ -189,25 +189,23 @@ export default {
v-if="hasEnvironment"
:href="environmentLink.link"
data-testid="job-environment-link"
- v-text="environmentLink.name"
- />
+ >{{ environmentLink.name }}</gl-link
+ >
</template>
<template #clusterNameOrLink>
<gl-link
v-if="clusterNameOrLink.path"
:href="clusterNameOrLink.path"
data-testid="job-cluster-link"
- v-text="clusterNameOrLink.name"
- />
+ >{{ clusterNameOrLink.name }}</gl-link
+ >
<template v-else>{{ clusterNameOrLink.name }}</template>
</template>
<template #kubernetesNamespace>{{ kubernetesNamespace }}</template>
<template #deploymentLink>
- <gl-link
- :href="deploymentLink.path"
- data-testid="job-deployment-link"
- v-text="deploymentLink.name"
- />
+ <gl-link :href="deploymentLink.path" data-testid="job-deployment-link">{{
+ deploymentLink.name
+ }}</gl-link>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index f9e6c64aad1..d5ee3423d70 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -287,6 +287,7 @@ export default {
:is-scroll-top-disabled="isScrollTopDisabled"
:is-job-log-size-visible="isJobLogSizeVisible"
:is-scrolling-down="isScrollingDown"
+ :is-complete="isJobLogComplete"
:job-log="jobLog"
@scrollJobLogTop="scrollTop"
@scrollJobLogBottom="scrollBottom"
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 5e89dd5acc2..e9809ac661b 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlLink, GlButton, GlSearchBoxByClick } from '@gitlab/ui';
-import { scrollToElement } from '~/lib/utils/common_utils';
+import { scrollToElement, backOff } from '~/lib/utils/common_utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __, s__, sprintf } from '~/locale';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
@@ -10,6 +10,7 @@ export default {
i18n: {
scrollToBottomButtonLabel: s__('Job|Scroll to bottom'),
scrollToTopButtonLabel: s__('Job|Scroll to top'),
+ scrollToNextFailureButtonLabel: s__('Job|Scroll to next failure'),
showRawButtonLabel: s__('Job|Show complete raw'),
searchPlaceholder: s__('Job|Search job log'),
noResults: s__('Job|No search results found'),
@@ -55,6 +56,10 @@ export default {
type: Boolean,
required: true,
},
+ isComplete: {
+ type: Boolean,
+ required: true,
+ },
jobLog: {
type: Array,
required: true,
@@ -64,6 +69,8 @@ export default {
return {
searchTerm: '',
searchResults: [],
+ failureCount: null,
+ failureIndex: 0,
};
},
computed: {
@@ -72,16 +79,49 @@ export default {
size: numberToHumanSize(this.size),
});
},
- showJobLogSearch() {
- return this.glFeatures.jobLogSearch;
+ showJumpToFailures() {
+ return this.glFeatures.jobLogJumpToFailures;
+ },
+ hasFailures() {
+ return this.failureCount > 0;
+ },
+ shouldDisableJumpToFailures() {
+ return !this.hasFailures;
},
},
+ mounted() {
+ this.checkFailureCount();
+ },
methods: {
+ checkFailureCount() {
+ if (this.glFeatures.jobLogJumpToFailures) {
+ backOff((next, stop) => {
+ this.failureCount = document.querySelectorAll('.term-fg-l-red').length;
+
+ if (this.hasFailures || (this.isComplete && !this.hasFailures)) {
+ stop();
+ } else {
+ next();
+ }
+ });
+ }
+ },
+ handleScrollToNextFailure() {
+ const failures = document.querySelectorAll('.term-fg-l-red');
+ const nextFailure = failures[this.failureIndex];
+
+ if (nextFailure) {
+ nextFailure.scrollIntoView({ block: 'center' });
+ this.failureIndex = (this.failureIndex + 1) % failures.length;
+ }
+ },
handleScrollToTop() {
this.$emit('scrollJobLogTop');
+ this.failureIndex = 0;
},
handleScrollToBottom() {
this.$emit('scrollJobLogBottom');
+ this.failureIndex = 0;
},
searchJobLog() {
this.searchResults = [];
@@ -135,10 +175,10 @@ export default {
};
</script>
<template>
- <div class="top-bar">
+ <div class="top-bar gl-display-flex gl-justify-content-space-between">
<!-- truncate information -->
<div
- class="truncated-info gl-display-none gl-sm-display-block gl-float-left"
+ class="truncated-info gl-display-none gl-sm-display-flex gl-flex-wrap gl-align-items-center"
data-testid="log-truncated-info"
>
<template v-if="isJobLogSizeVisible">
@@ -154,25 +194,23 @@ export default {
</div>
<!-- eo truncate information -->
- <div class="controllers gl-float-right">
- <template v-if="showJobLogSearch">
- <gl-search-box-by-click
- v-model="searchTerm"
- class="gl-mr-3"
- :placeholder="$options.i18n.searchPlaceholder"
- data-testid="job-log-search-box"
- @clear="$emit('searchResults', [])"
- @submit="searchJobLog"
- />
+ <div class="controllers">
+ <gl-search-box-by-click
+ v-model="searchTerm"
+ class="gl-mr-3"
+ :placeholder="$options.i18n.searchPlaceholder"
+ data-testid="job-log-search-box"
+ @clear="$emit('searchResults', [])"
+ @submit="searchJobLog"
+ />
- <help-popover class="gl-mr-3">
- <template #title>{{ $options.i18n.searchPopoverTitle }}</template>
+ <help-popover class="gl-mr-3">
+ <template #title>{{ $options.i18n.searchPopoverTitle }}</template>
- <p class="gl-mb-0">
- {{ $options.i18n.searchPopoverDescription }}
- </p>
- </help-popover>
- </template>
+ <p class="gl-mb-0">
+ {{ $options.i18n.searchPopoverDescription }}
+ </p>
+ </help-popover>
<!-- links -->
<gl-button
@@ -187,6 +225,18 @@ export default {
<!-- eo links -->
<!-- scroll buttons -->
+ <gl-button
+ v-if="showJumpToFailures"
+ v-gl-tooltip
+ :title="$options.i18n.scrollToNextFailureButtonLabel"
+ :aria-label="$options.i18n.scrollToNextFailureButtonLabel"
+ :disabled="shouldDisableJumpToFailures"
+ class="btn-scroll gl-ml-3"
+ data-testid="job-controller-scroll-to-failure"
+ icon="soft-wrap"
+ @click="handleScrollToNextFailure"
+ />
+
<div v-gl-tooltip :title="$options.i18n.scrollToTopButtonLabel" class="gl-ml-3">
<gl-button
:disabled="isScrollTopDisabled"
diff --git a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
index 15c4e503685..3b1509e5be5 100644
--- a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
@@ -1,7 +1,6 @@
<script>
import { mapState } from 'vuex';
import { GlBadge } from '@gitlab/ui';
-import { helpPagePath } from '~/helpers/help_page_helper';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -47,11 +46,6 @@ export default {
this.job.coverage,
);
},
- runnerHelpUrl() {
- return helpPagePath('ci/runners/configure_runners.html', {
- anchor: 'set-maximum-job-timeout-for-a-runner',
- });
- },
runnerId() {
const { id, short_sha: token, description } = this.job.runner;
@@ -85,6 +79,7 @@ export default {
TAGS: __('Tags:'),
TIMEOUT: __('Timeout'),
},
+ RUNNER_HELP_URL: 'https://docs.gitlab.com/runner/register/index.html',
};
</script>
@@ -101,7 +96,7 @@ export default {
<detail-row v-if="job.queued_duration" :value="queuedDuration" :title="$options.i18n.QUEUED" />
<detail-row
v-if="hasTimeout"
- :help-url="runnerHelpUrl"
+ :help-url="$options.RUNNER_HELP_URL"
:value="timeout"
data-testid="job-timeout"
:title="$options.i18n.TIMEOUT"
diff --git a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
index 5b1032c6448..98b51e8c2c4 100644
--- a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
+++ b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql
@@ -1,7 +1,6 @@
query getJobs($fullPath: ID!, $after: String, $first: Int = 30, $statuses: [CiJobStatus!]) {
project(fullPath: $fullPath) {
id
- __typename
jobs(after: $after, first: $first, statuses: $statuses) {
count
pageInfo {
@@ -9,15 +8,12 @@ query getJobs($fullPath: ID!, $after: String, $first: Int = 30, $statuses: [CiJo
hasNextPage
hasPreviousPage
startCursor
- __typename
}
nodes {
- __typename
artifacts {
nodes {
downloadPath
fileType
- __typename
}
}
allowFailure
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 b3db5a94ac5..c2f460cb647 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue
@@ -3,7 +3,6 @@ import { GlAlert, GlSkeletonLoader, GlIntersectionObserver, GlLoadingIcon } from
import { __ } from '~/locale';
import createFlash from '~/flash';
import JobsFilteredSearch from '../filtered_search/jobs_filtered_search.vue';
-import eventHub from './event_hub';
import GetJobs from './graphql/queries/get_jobs.query.graphql';
import JobsTable from './jobs_table.vue';
import JobsTableEmptyState from './jobs_table_empty_state.vue';
@@ -108,16 +107,7 @@ export default {
}
},
},
- mounted() {
- eventHub.$on('jobActionPerformed', this.handleJobAction);
- },
- beforeDestroy() {
- eventHub.$off('jobActionPerformed', this.handleJobAction);
- },
methods: {
- handleJobAction() {
- this.$apollo.queries.jobs.refetch({ statuses: this.scope });
- },
fetchJobsByStatus(scope) {
this.infiniteScrollingTriggered = false;
@@ -169,6 +159,7 @@ export default {
v-if="shouldShowAlert"
class="gl-mt-2"
variant="danger"
+ data-testid="jobs-table-error-alert"
dismissible
@dismiss="isAlertDismissed = true"
>
diff --git a/app/assets/javascripts/labels/labels_select.js b/app/assets/javascripts/labels/labels_select.js
index 9d8ee165df2..3e5396c5bd8 100644
--- a/app/assets/javascripts/labels/labels_select.js
+++ b/app/assets/javascripts/labels/labels_select.js
@@ -438,7 +438,7 @@ export default class LabelsSelect {
[
'<% if (isScopedLabel(label) && enableScopedLabels) { %>',
"<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span>",
- '<br />',
+ '<br>',
'<%= escapeStr(label.description) %>',
'<% } else { %>',
'<%= escapeStr(label.description) %>',
diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js
index a01c6df0003..3e28ca2a0f7 100644
--- a/app/assets/javascripts/lib/dompurify.js
+++ b/app/assets/javascripts/lib/dompurify.js
@@ -33,6 +33,22 @@ const removeUnsafeHref = (node, attr) => {
};
/**
+ * Appends 'noopener' & 'noreferrer' to rel
+ * attr values to prevent reverse tabnabbing.
+ *
+ * @param {String} rel
+ * @returns {String}
+ */
+const appendSecureRelValue = (rel) => {
+ const attributes = new Set(rel ? rel.toLowerCase().split(' ') : []);
+
+ attributes.add('noopener');
+ attributes.add('noreferrer');
+
+ return Array.from(attributes).join(' ');
+};
+
+/**
* Sanitize icons' <use> tag attributes, to safely include
* svgs such as in:
*
@@ -57,4 +73,25 @@ addHook('afterSanitizeAttributes', (node) => {
}
});
+const TEMPORARY_ATTRIBUTE = 'data-temp-href-target';
+
+addHook('beforeSanitizeAttributes', (node) => {
+ if (node.tagName === 'A' && node.hasAttribute('target')) {
+ node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target'));
+ }
+});
+
+addHook('afterSanitizeAttributes', (node) => {
+ if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
+ node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE));
+ node.removeAttribute(TEMPORARY_ATTRIBUTE);
+ if (node.getAttribute('target') === '_blank') {
+ const rel = node.getAttribute('rel');
+ node.setAttribute('rel', appendSecureRelValue(rel));
+ }
+ }
+});
+
export const sanitize = (val, config) => dompurifySanitize(val, { ...defaultConfig, ...config });
+
+export { isValidAttribute } from 'dompurify';
diff --git a/app/assets/javascripts/lib/gfm/index.js b/app/assets/javascripts/lib/gfm/index.js
index 92118c8929f..eaf653e9924 100644
--- a/app/assets/javascripts/lib/gfm/index.js
+++ b/app/assets/javascripts/lib/gfm/index.js
@@ -1,10 +1,15 @@
import { pick } from 'lodash';
+import normalize from 'mdurl/encode';
import { unified } from 'unified';
import remarkParse from 'remark-parse';
+import remarkFrontmatter from 'remark-frontmatter';
import remarkGfm from 'remark-gfm';
import remarkRehype, { all } from 'remark-rehype';
import rehypeRaw from 'rehype-raw';
+const skipFrontmatterHandler = (language) => (h, node) =>
+ h(node.position, 'frontmatter', { language }, [{ type: 'text', value: node.value }]);
+
const skipRenderingHandlers = {
footnoteReference: (h, node) =>
h(node.position, 'footnoteReference', { identifier: node.identifier, label: node.label }, []),
@@ -19,12 +24,57 @@ const skipRenderingHandlers = {
h(node.position, 'codeBlock', { language: node.lang, meta: node.meta }, [
{ type: 'text', value: node.value },
]),
+ definition: (h, node) => {
+ const title = node.title ? ` "${node.title}"` : '';
+
+ return h(
+ node.position,
+ 'referenceDefinition',
+ { identifier: node.identifier, url: node.url, title: node.title },
+ [{ type: 'text', value: `[${node.identifier}]: ${node.url}${title}` }],
+ );
+ },
+ linkReference: (h, node) => {
+ const definition = h.definition(node.identifier);
+
+ return h(
+ node.position,
+ 'a',
+ {
+ href: normalize(definition.url ?? ''),
+ identifier: node.identifier,
+ isReference: 'true',
+ title: definition.title,
+ },
+ all(h, node),
+ );
+ },
+ imageReference: (h, node) => {
+ const definition = h.definition(node.identifier);
+
+ return h(
+ node.position,
+ 'img',
+ {
+ src: normalize(definition.url ?? ''),
+ alt: node.alt,
+ identifier: node.identifier,
+ isReference: 'true',
+ title: definition.title,
+ },
+ all(h, node),
+ );
+ },
+ toml: skipFrontmatterHandler('toml'),
+ yaml: skipFrontmatterHandler('yaml'),
+ json: skipFrontmatterHandler('json'),
};
const createParser = ({ skipRendering = [] }) => {
return unified()
.use(remarkParse)
.use(remarkGfm)
+ .use(remarkFrontmatter, ['yaml', 'toml', { type: 'json', marker: ';' }])
.use(remarkRehype, {
allowDangerousHtml: true,
handlers: {
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index cfcce234bfb..98e45f95b38 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -221,6 +221,7 @@ export default (resolvers = {}, config = {}) => {
ac = new ApolloClient({
typeDefs,
link: appLink,
+ connectToDevTools: process.env.NODE_ENV !== 'production',
cache: new InMemoryCache({
...cacheConfig,
typePolicies: {
diff --git a/app/assets/javascripts/lib/markdown_it.js b/app/assets/javascripts/lib/markdown_it.js
new file mode 100644
index 00000000000..0b7a553737d
--- /dev/null
+++ b/app/assets/javascripts/lib/markdown_it.js
@@ -0,0 +1,11 @@
+/**
+ * This module replaces markdown-it with an empty function. markdown-it
+ * is a dependency of the prosemirror-markdown package. prosemirror-markdown
+ * uses markdown-it to parse markdown and produce an AST. However, the
+ * features that use prosemirror-markdown in the GitLab application do not
+ * require markdown parsing.
+ *
+ * Replacing markdown-it with this empty function removes unnecessary javascript
+ * from the production builds.
+ */
+export default () => {};
diff --git a/app/assets/javascripts/lib/prosemirror_markdown_serializer.js b/app/assets/javascripts/lib/prosemirror_markdown_serializer.js
index 6473683c3af..5e621ca3216 100644
--- a/app/assets/javascripts/lib/prosemirror_markdown_serializer.js
+++ b/app/assets/javascripts/lib/prosemirror_markdown_serializer.js
@@ -1,3 +1 @@
-// Import from `src/to_markdown` to avoid unnecessary bundling of unused libs
-// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79859
-export * from 'prosemirror-markdown/src/to_markdown';
+export { MarkdownSerializer, defaultMarkdownSerializer } from 'prosemirror-markdown';
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 243de48948c..9f4e12a3010 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -4,12 +4,14 @@ import Shortcuts from '~/behaviors/shortcuts/shortcuts';
import { insertText } from '~/lib/utils/common_utils';
const LINK_TAG_PATTERN = '[{text}](url)';
+const INDENT_CHAR = ' ';
+const INDENT_LENGTH = 2;
// at the start of a line, find any amount of whitespace followed by
// a bullet point character (*+-) and an optional checkbox ([ ] [x])
// OR a number with a . after it and an optional checkbox ([ ] [x])
// followed by one or more whitespace characters
-const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isUl>[*+-])|(?<isOl>\d+\.))( \[([xX\s])\])?\s)(?<content>.)?/;
+const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isUl>[*+-])|(?<isOl>\d+\.))( \[([xX~\s])\])?\s)(?<content>.)?/;
// detect a horizontal rule that might be mistaken for a list item (not full pattern for an <hr>)
const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/;
@@ -24,33 +26,104 @@ function addBlockTags(blockTag, selected) {
return `${blockTag}\n${selected}\n${blockTag}`;
}
-function lineBefore(text, textarea, trimNewlines = true) {
- let split = text.substring(0, textarea.selectionStart);
-
- if (trimNewlines) {
- split = split.trim();
- }
+/**
+ * Returns the line of text that is before the first line
+ * of the current selection
+ *
+ * @param {String} text - the text of the targeted text area
+ * @param {Object} textArea - the targeted text area
+ * @returns {String}
+ */
+function lineBeforeSelection(text, textArea) {
+ let split = text.substring(0, textArea.selectionStart);
split = split.split('\n');
- return split[split.length - 1];
-}
+ // Last item, at -1, is the line where the start of selection is.
+ // Line before selection is therefore at -2
+ const lineBefore = split[split.length - 2];
-function lineAfter(text, textarea, trimNewlines = true) {
- let split = text.substring(textarea.selectionEnd);
+ return lineBefore === undefined ? '' : lineBefore;
+}
- if (trimNewlines) {
- split = split.trim();
- } else {
- // remove possible leading newline to get at the real line
- split = split.replace(/^\n/, '');
- }
+/**
+ * Returns the line of text that is after the last line
+ * of the current selection
+ *
+ * @param {String} text - the text of the targeted text area
+ * @param {Object} textArea - the targeted text area
+ * @returns {String}
+ */
+function lineAfterSelection(text, textArea) {
+ let split = text.substring(textArea.selectionEnd);
+ // remove possible leading newline to get at the real line
+ split = split.replace(/^\n/, '');
split = split.split('\n');
return split[0];
}
+/**
+ * Returns the text lines that encompass the current selection
+ *
+ * @param {Object} textArea - the targeted text area
+ * @returns {Object}
+ */
+function linesFromSelection(textArea) {
+ const text = textArea.value;
+ const { selectionStart, selectionEnd } = textArea;
+
+ let startPos = text[selectionStart] === '\n' ? selectionStart - 1 : selectionStart;
+ startPos = text.lastIndexOf('\n', startPos) + 1;
+
+ let endPos = selectionEnd === selectionStart ? selectionEnd : selectionEnd - 1;
+ endPos = text.indexOf('\n', endPos);
+ if (endPos < 0) endPos = text.length;
+
+ const selectedRange = text.substring(startPos, endPos);
+ const lines = selectedRange.split('\n');
+
+ return {
+ lines,
+ selectionStart,
+ selectionEnd,
+ startPos,
+ endPos,
+ };
+}
+
+/**
+ * Set the selection of a textarea such that it maintains the
+ * previous selection before the lines were indented/outdented
+ *
+ * @param {Object} textArea - the targeted text area
+ * @param {Number} selectionStart - start position of original selection
+ * @param {Number} selectionEnd - end position of original selection
+ * @param {Number} lineStart - start pos of first line
+ * @param {Number} firstLineChange - number of characters changed on first line
+ * @param {Number} totalChanged - total number of characters changed
+ */
+function setNewSelectionRange(
+ textArea,
+ selectionStart,
+ selectionEnd,
+ lineStart,
+ firstLineChange,
+ totalChanged,
+) {
+ let newStart = Math.max(lineStart, selectionStart + firstLineChange);
+ let newEnd = Math.max(lineStart, selectionEnd + totalChanged);
+
+ if (selectionStart === selectionEnd) {
+ newEnd = newStart;
+ } else if (selectionStart === lineStart) {
+ newStart = lineStart;
+ }
+
+ textArea.setSelectionRange(newStart, newEnd);
+}
+
function convertMonacoSelectionToAceFormat(sel) {
return {
start: {
@@ -93,7 +166,8 @@ function editorBlockTagText(text, blockTag, selected, editor) {
function blockTagText(text, textArea, blockTag, selected) {
const shouldRemoveBlock =
- lineBefore(text, textArea) === blockTag && lineAfter(text, textArea) === blockTag;
+ lineBeforeSelection(text, textArea) === blockTag &&
+ lineAfterSelection(text, textArea) === blockTag;
if (shouldRemoveBlock) {
// To remove the block tag we have to select the line before & after
@@ -312,9 +386,100 @@ 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
+ */
+function indentLines(textArea) {
+ const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);
+ const shiftedLines = [];
+ let totalAdded = 0;
+
+ textArea.setSelectionRange(startPos, endPos);
+
+ lines.forEach((line) => {
+ line = INDENT_CHAR.repeat(INDENT_LENGTH) + line;
+ totalAdded += INDENT_LENGTH;
+
+ shiftedLines.push(line);
+ });
+
+ const textToInsert = shiftedLines.join('\n');
+
+ insertText(textArea, textToInsert);
+ setNewSelectionRange(textArea, selectionStart, selectionEnd, startPos, INDENT_LENGTH, totalAdded);
+}
+
+/**
+ * Outdents selected lines to the left by 2 spaces
+ *
+ * @param {Object} textArea - the targeted text area
+ */
+function outdentLines(textArea) {
+ const { lines, selectionStart, selectionEnd, startPos, endPos } = linesFromSelection(textArea);
+ const shiftedLines = [];
+ let totalRemoved = 0;
+ let removedFromFirstline = -1;
+ let removedFromLine = 0;
+
+ textArea.setSelectionRange(startPos, endPos);
+
+ lines.forEach((line) => {
+ removedFromLine = 0;
+
+ if (line.length > 0) {
+ // need to count how many spaces are actually removed, so can't use `replace`
+ while (removedFromLine < INDENT_LENGTH && line[removedFromLine] === INDENT_CHAR) {
+ removedFromLine += 1;
+ }
+
+ if (removedFromLine > 0) {
+ line = line.slice(removedFromLine);
+ totalRemoved += removedFromLine;
+ }
+ }
+
+ if (removedFromFirstline === -1) removedFromFirstline = removedFromLine;
+ shiftedLines.push(line);
+ });
+
+ const textToInsert = shiftedLines.join('\n');
+
+ if (totalRemoved > 0) insertText(textArea, textToInsert);
+
+ setNewSelectionRange(
+ textArea,
+ selectionStart,
+ selectionEnd,
+ startPos,
+ -removedFromFirstline,
+ -totalRemoved,
+ );
+}
+
+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 (textArea.selectionStart === textArea.selectionEnd) return;
const keys = {
@@ -348,13 +513,13 @@ function handleSurroundSelectedText(e, textArea) {
/**
* Returns the content for a new line following a list item.
*
- * @param {Object} result - regex match of the current line
- * @param {Object?} nextLineResult - regex match of the next line
+ * @param {Object} listLineMatch - regex match of the current line
+ * @param {Object?} nextLineMatch - regex match of the next line
* @returns string with the new list item
*/
-function continueOlText(result, nextLineResult) {
- const { indent, leader } = result.groups;
- const { indent: nextIndent, isOl: nextIsOl } = nextLineResult?.groups ?? {};
+function continueOlText(listLineMatch, nextLineMatch) {
+ const { indent, leader } = listLineMatch.groups;
+ const { indent: nextIndent, isOl: nextIsOl } = nextLineMatch?.groups ?? {};
const [numStr, postfix = ''] = leader.split('.');
@@ -368,20 +533,20 @@ function handleContinueList(e, textArea) {
if (!(e.key === 'Enter')) return;
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
if (textArea.selectionStart !== textArea.selectionEnd) return;
- // prevent unintended line breaks were inserted using Japanese IME on MacOS
+ // prevent unintended line breaks inserted using Japanese IME on MacOS
if (compositioningNoteText) return;
- const currentLine = lineBefore(textArea.value, textArea, false);
- const result = currentLine.match(LIST_LINE_HEAD_PATTERN);
+ const firstSelectedLine = linesFromSelection(textArea).lines[0];
+ const listLineMatch = firstSelectedLine.match(LIST_LINE_HEAD_PATTERN);
- if (result) {
- const { leader, indent, content, isOl } = result.groups;
- const prevLineEmpty = !content;
+ if (listLineMatch) {
+ const { leader, indent, content, isOl } = listLineMatch.groups;
+ const emptyListItem = !content;
- if (prevLineEmpty) {
- // erase previous empty list item - select the text and allow the
- // natural line feed erase the text
- textArea.selectionStart = textArea.selectionStart - result[0].length;
+ if (emptyListItem) {
+ // erase empty list item - select the text and allow the
+ // natural line feed to erase the text
+ textArea.selectionStart = textArea.selectionStart - listLineMatch[0].length;
return;
}
@@ -389,17 +554,17 @@ function handleContinueList(e, textArea) {
// Behaviors specific to either `ol` or `ul`
if (isOl) {
- const nextLine = lineAfter(textArea.value, textArea, false);
- const nextLineResult = nextLine.match(LIST_LINE_HEAD_PATTERN);
+ const nextLine = lineAfterSelection(textArea.value, textArea);
+ const nextLineMatch = nextLine.match(LIST_LINE_HEAD_PATTERN);
- itemToInsert = continueOlText(result, nextLineResult);
+ itemToInsert = continueOlText(listLineMatch, nextLineMatch);
} else {
- if (currentLine.match(HR_PATTERN)) return;
+ if (firstSelectedLine.match(HR_PATTERN)) return;
itemToInsert = `${indent}${leader}`;
}
- itemToInsert = itemToInsert.replace(/\[x\]/i, '[ ]');
+ itemToInsert = itemToInsert.replace(/\[[x~]\]/i, '[ ]');
e.preventDefault();
@@ -419,6 +584,7 @@ export function keypressNoteText(e) {
if ($(textArea).atwho?.('isSelecting')) return;
+ handleIndentOutdent(e, textArea);
handleContinueList(e, textArea);
handleSurroundSelectedText(e, textArea);
}
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index ff60fd2aecb..ca90eee69c7 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -397,6 +397,7 @@ export function relativePathToAbsolute(path, basePath) {
const absolute = isAbsolute(basePath);
const base = absolute ? basePath : `file:///${basePath}`;
const url = new URL(path, base);
+ url.pathname = url.pathname.replace(/\/\/+/g, '/');
return absolute ? url.href : decodeURIComponent(url.pathname);
}
@@ -668,3 +669,27 @@ export function constructWebIDEPath({
webIDEUrl(`/${sourceProjectFullPath}/merge_requests/${iid}`),
);
}
+
+/**
+ * Examples
+ *
+ * http://gitlab.com => gitlab.com
+ * https://gitlab.com => gitlab.com
+ *
+ * @param {String} url
+ * @returns A url without a protocol / scheme
+ */
+export const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
+
+/**
+ * Examples
+ *
+ * https://www.gitlab.com/path/ => https://www.gitlab.com/path
+ * https://www.gitlab.com/?query=search => https://www.gitlab.com?query=search
+ * https://www.gitlab.com/#fragment => https://www.gitlab.com#fragment
+ *
+ * @param {String} url
+ * @returns A URL that does not have a path that ends with slash
+ */
+export const removeLastSlashInUrlPath = (url) =>
+ url.replace(/\/$/, '').replace(/\/(\?|#){1}([^/]*)$/, '$1$2');
diff --git a/app/assets/javascripts/lib/utils/yaml.js b/app/assets/javascripts/lib/utils/yaml.js
index 9270d388342..48f34624140 100644
--- a/app/assets/javascripts/lib/utils/yaml.js
+++ b/app/assets/javascripts/lib/utils/yaml.js
@@ -16,18 +16,17 @@ function getPath(ancestry) {
function getFirstChildNode(collection) {
let firstChildKey;
- let type;
- switch (collection.constructor.name) {
- case 'YAMLSeq': // eslint-disable-line @gitlab/require-i18n-strings
- return collection.items.find((i) => isNode(i));
- case 'YAMLMap': // eslint-disable-line @gitlab/require-i18n-strings
- firstChildKey = collection.items[0]?.key;
- if (!firstChildKey) return undefined;
- return isScalar(firstChildKey) ? firstChildKey : new Scalar(firstChildKey);
- default:
- type = collection.constructor?.name || typeof collection;
- throw Error(`Cannot identify a child Node for type ${type}`);
+ if (isSeq(collection)) {
+ return collection.items.find((i) => isNode(i));
}
+ if (isMap(collection)) {
+ firstChildKey = collection.items[0]?.key;
+ if (!firstChildKey) return undefined;
+ return isScalar(firstChildKey) ? firstChildKey : new Scalar(firstChildKey);
+ }
+ throw Error(
+ `Cannot identify a child Node for Collection. Expecting a YAMLMap or a YAMLSeq. Got: ${collection}`,
+ );
}
function moveMetaPropsToFirstChildNode(collection) {
diff --git a/app/assets/javascripts/linked_resources/index.js b/app/assets/javascripts/linked_resources/index.js
index 244adca86c9..6d799d30b4b 100644
--- a/app/assets/javascripts/linked_resources/index.js
+++ b/app/assets/javascripts/linked_resources/index.js
@@ -1,25 +1,34 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import ResourceLinksBlock from 'ee_component/linked_resources/components/resource_links_block.vue';
+import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
+Vue.use(VueApollo);
+
export default function initLinkedResources() {
const linkedResourcesRootElement = document.querySelector('.js-linked-resources-root');
if (linkedResourcesRootElement) {
const { issuableId, canAddResourceLinks, helpPath } = linkedResourcesRootElement.dataset;
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
// eslint-disable-next-line no-new
new Vue({
el: linkedResourcesRootElement,
name: 'LinkedResourcesRoot',
+ apolloProvider,
components: {
resourceLinksBlock: ResourceLinksBlock,
},
render: (createElement) =>
createElement('resource-links-block', {
props: {
- issuableId,
helpPath,
+ issuableId: parseInt(issuableId, 10),
canAddResourceLinks: parseBoolean(canAddResourceLinks),
},
}),
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 349a28ace52..c16ed68096d 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -134,12 +134,6 @@ function deferredInitialisation() {
// Adding a helper class to activate animations only after all is rendered
setTimeout(() => $body.addClass('page-initialised'), 1000);
-
- if (window.gon?.features?.mrAttentionRequests) {
- import('~/attention_requests')
- .then((module) => module.default())
- .catch(() => {});
- }
}
// header search vue component bootstrap
diff --git a/app/assets/javascripts/members/components/table/member_action_buttons.vue b/app/assets/javascripts/members/components/table/member_action_buttons.vue
index 971b1a8435e..ecc2ed82ad0 100644
--- a/app/assets/javascripts/members/components/table/member_action_buttons.vue
+++ b/app/assets/javascripts/members/components/table/member_action_buttons.vue
@@ -1,5 +1,5 @@
<script>
-import { MEMBER_TYPES } from '../../constants';
+import { MEMBER_TYPES, EE_ACTION_BUTTONS } from 'ee_else_ce/members/constants';
import AccessRequestActionButtons from '../action_buttons/access_request_action_buttons.vue';
import GroupActionButtons from '../action_buttons/group_action_buttons.vue';
import InviteActionButtons from '../action_buttons/invite_action_buttons.vue';
@@ -12,6 +12,8 @@ export default {
GroupActionButtons,
InviteActionButtons,
AccessRequestActionButtons,
+ BannedActionButtons: () =>
+ import('ee_component/members/components/action_buttons/banned_action_buttons.vue'),
},
props: {
member: {
@@ -42,6 +44,7 @@ export default {
[MEMBER_TYPES.group]: 'group-action-buttons',
[MEMBER_TYPES.invite]: 'invite-action-buttons',
[MEMBER_TYPES.accessRequest]: 'access-request-action-buttons',
+ ...EE_ACTION_BUTTONS,
};
return dictionary[this.memberType];
diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js
index 2fe816c7ea2..93d113d1afe 100644
--- a/app/assets/javascripts/members/constants.js
+++ b/app/assets/javascripts/members/constants.js
@@ -9,6 +9,8 @@ export const EE_APP_OPTIONS = {};
// Overridden in EE
export const EE_TABS = [];
+export const EE_ACTION_BUTTONS = {};
+
export const FIELD_KEY_ACCOUNT = 'account';
export const FIELD_KEY_SOURCE = 'source';
export const FIELD_KEY_GRANTED = 'granted';
diff --git a/app/assets/javascripts/merge_conflicts/utils.js b/app/assets/javascripts/merge_conflicts/utils.js
index cf7a7c304e3..ca0649cc048 100644
--- a/app/assets/javascripts/merge_conflicts/utils.js
+++ b/app/assets/javascripts/merge_conflicts/utils.js
@@ -61,7 +61,7 @@ export const decorateLineForInlineView = (line, id, conflict) => {
};
export const getLineForParallelView = (line, id, lineType, isHead) => {
- const { old_line, new_line, rich_text } = line;
+ const { old_line: oldLine, new_line: newLine, rich_text: richText } = line;
const hasConflict = lineType === 'conflict';
return {
@@ -71,10 +71,9 @@ export const getLineForParallelView = (line, id, lineType, isHead) => {
isHead: hasConflict && isHead,
isOrigin: hasConflict && !isHead,
hasMatch: lineType === 'match',
- // eslint-disable-next-line camelcase
- lineNumber: isHead ? new_line : old_line,
+ lineNumber: isHead ? newLine : oldLine,
section: isHead ? 'head' : 'origin',
- richText: rich_text,
+ richText,
isSelected: false,
isUnselected: false,
};
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index a95b143920b..b74da3ee89b 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -237,10 +237,10 @@ export default {
recentDeployments() {
return this.deploymentData.reduce((acc, deployment) => {
if (deployment.created_at >= this.earliestDatapoint) {
- const { id, created_at, sha, ref, tag } = deployment;
+ const { id, created_at: createdAt, sha, ref, tag } = deployment;
acc.push({
id,
- createdAt: created_at,
+ createdAt,
sha,
commitUrl: `${this.projectPath}/-/commit/${sha}`,
tag,
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 7f75a501635..02a2435d575 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -16,8 +16,8 @@ export const gqClient = createGqClient(
);
/**
- * Metrics loaded from project-defined dashboards do not have a metric_id.
- * This method creates a unique ID combining metric_id and id, if either is present.
+ * Metrics loaded from project-defined dashboards do not have a metricId.
+ * This method creates a unique ID combining metricId and id, if either is present.
* This is hopefully a temporary solution until BE processes metrics before passing to FE
*
* Related:
@@ -25,12 +25,11 @@ export const gqClient = createGqClient(
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27447
*
* @param {Object} metric - metric
- * @param {Number} metric.metric_id - Database metric id
+ * @param {Number} metric.metricId - Database metric id
* @param {String} metric.id - User-defined identifier
* @returns {Object} - normalized metric with a uniqueID
*/
-// eslint-disable-next-line camelcase
-export const uniqMetricsId = ({ metric_id, id }) => `${metric_id || NOT_IN_DB_PREFIX}_${id}`;
+export const uniqMetricsId = ({ metricId, id }) => `${metricId || NOT_IN_DB_PREFIX}_${id}`;
/**
* Project path has a leading slash that doesn't work well
@@ -100,19 +99,28 @@ export const parseAnnotationsResponse = (response) => {
* @returns {Object}
*/
const mapToMetricsViewModel = (metrics) =>
- metrics.map(({ label, id, metric_id, query_range, prometheus_endpoint_path, ...metric }) => ({
- label,
- queryRange: query_range,
- prometheusEndpointPath: prometheus_endpoint_path,
- metricId: uniqMetricsId({ metric_id, id }),
+ metrics.map(
+ ({
+ label,
+ id,
+ metric_id: metricId,
+ query_range: queryRange,
+ prometheus_endpoint_path: prometheusEndpointPath,
+ ...metric
+ }) => ({
+ label,
+ queryRange,
+ prometheusEndpointPath,
+ metricId: uniqMetricsId({ metricId, id }),
- // metric data
- loading: false,
- result: null,
- state: null,
+ // metric data
+ loading: false,
+ result: null,
+ state: null,
- ...metric,
- }));
+ ...metric,
+ }),
+ );
/**
* Maps X-axis view model
@@ -169,26 +177,26 @@ export const mapPanelToViewModel = ({
id = null,
title = '',
type,
- x_axis = {}, // eslint-disable-line camelcase
- x_label,
- y_label,
- y_axis = {}, // eslint-disable-line camelcase
+ x_axis: xAxisBase = {},
+ x_label: xLabel,
+ y_label: yLabel,
+ y_axis: yAxisBase = {},
field,
metrics = [],
links = [],
- min_value,
- max_value,
+ min_value: minValue,
+ max_value: maxValue,
split,
thresholds,
format,
}) => {
// Both `x_axis.name` and `x_label` are supported for now
// https://gitlab.com/gitlab-org/gitlab/issues/210521
- const xAxis = mapXAxisToViewModel({ name: x_label, ...x_axis }); // eslint-disable-line camelcase
+ const xAxis = mapXAxisToViewModel({ name: xLabel, ...xAxisBase });
// Both `y_axis.name` and `y_label` are supported for now
// https://gitlab.com/gitlab-org/gitlab/issues/208385
- const yAxis = mapYAxisToViewModel({ name: y_label, ...y_axis }); // eslint-disable-line camelcase
+ const yAxis = mapYAxisToViewModel({ name: yLabel, ...yAxisBase });
return {
id,
@@ -199,8 +207,8 @@ export const mapPanelToViewModel = ({
yAxis,
xAxis,
field,
- minValue: min_value,
- maxValue: max_value,
+ minValue,
+ maxValue,
split,
thresholds,
format,
@@ -295,13 +303,13 @@ export const mapToDashboardViewModel = ({
dashboard = '',
templating = {},
links = [],
- panel_groups = [], // eslint-disable-line camelcase
+ panel_groups: panelGroups = [],
}) => {
return {
dashboard,
variables: mergeURLVariables(parseTemplatingVariables(templating.variables)),
links: links.map(mapLinksToViewModel),
- panelGroups: panel_groups.map(mapToPanelGroupViewModel),
+ panelGroups: panelGroups.map(mapToPanelGroupViewModel),
};
};
diff --git a/app/assets/javascripts/mr_notes/init_notes.js b/app/assets/javascripts/mr_notes/init_notes.js
index d85fd10be45..cf24d18c7b6 100644
--- a/app/assets/javascripts/mr_notes/init_notes.js
+++ b/app/assets/javascripts/mr_notes/init_notes.js
@@ -44,7 +44,13 @@ export default () => {
},
watch: {
discussionTabCounter() {
- this.updateDiscussionTabCounter();
+ if (window.gon?.features?.paginatedMrDiscussions) {
+ if (this.$store.state.notes.doneFetchingBatchDiscussions) {
+ this.updateDiscussionTabCounter();
+ }
+ } else {
+ this.updateDiscussionTabCounter();
+ }
},
isShowTabActive: {
handler(newVal) {
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index 073b27605bb..8351ae7ced6 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -1,6 +1,6 @@
<script>
import katex from 'katex';
-import marked from 'marked';
+import { marked } from 'marked';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { sanitize } from '~/lib/dompurify';
import { hasContent, markdownConfig } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index 0e213028c7c..3cf47f42e0c 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -1,19 +1,17 @@
<script>
-import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { GlSafeHtmlDirective as SafeHtml, GlAvatar, GlAvatarLink } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions } from 'vuex';
-
import { truncateSha } from '~/lib/utils/text_utility';
import { s__, __, sprintf } from '~/locale';
-
-import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import noteEditedText from './note_edited_text.vue';
import noteHeader from './note_header.vue';
export default {
name: 'DiffDiscussionHeader',
components: {
- userAvatarLink,
+ GlAvatar,
+ GlAvatarLink,
noteEditedText,
noteHeader,
},
@@ -86,6 +84,9 @@ export default {
return sprintf(text, { commitDisplay, linkStart, linkEnd }, false);
},
+ adaptiveAvatarSize() {
+ return { default: 24, md: 32 };
+ },
},
methods: {
...mapActions(['toggleDiscussion']),
@@ -100,16 +101,11 @@ export default {
<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-ml-3 gl-mr-4"
+ 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"
>
- <user-avatar-link
- v-if="author"
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="24"
- :img-css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (https://gitlab.com/groups/gitlab-org/-/epics/7731) */"
- />
+ <gl-avatar-link v-if="author" :href="author.path">
+ <gl-avatar :src="author.avatar_url" :alt="author.name" :size="adaptiveAvatarSize" />
+ </gl-avatar-link>
</div>
<div class="timeline-content w-100">
<note-header
@@ -127,14 +123,14 @@ export default {
:edited-at="discussion.resolved_at"
:edited-by="discussion.resolved_by"
:action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline"
+ class-name="discussion-headline-light js-discussion-headline gl-pl-2"
/>
<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"
+ class-name="discussion-headline-light js-discussion-headline gl-pl-2"
/>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index 10e3f57a56d..c7f293a219a 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -170,7 +170,7 @@ export default {
return this.targetType === 'issue';
},
canAssign() {
- return this.getNoteableData.current_user?.can_update && this.isIssue;
+ return this.getNoteableData.current_user?.can_set_issue_metadata && this.isIssue;
},
displayAuthorBadgeText() {
return sprintf(__('This user is the author of this %{noteable}.'), {
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index cc74c2ee605..f1c41eea428 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -8,7 +8,6 @@ import { __ } from '~/locale';
import '~/behaviors/markdown/render_gfm';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
import autosave from '../mixins/autosave';
-import { INTERNAL_NOTE_CLASSES } from '../constants';
import noteAttachment from './note_attachment.vue';
import noteAwardsList from './note_awards_list.vue';
import noteEditedText from './note_edited_text.vue';
@@ -55,11 +54,6 @@ export default {
required: false,
default: '',
},
- isInternalNote: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
...mapGetters(['getDiscussion', 'suggestionsCount', 'getSuggestionsFilePaths']),
@@ -101,12 +95,6 @@ export default {
return escape(suggestion);
},
- internalNoteContainerClasses() {
- if (this.isInternalNote && !this.isEditing) {
- return INTERNAL_NOTE_CLASSES;
- }
- return '';
- },
},
mounted() {
this.renderGFM();
@@ -179,54 +167,52 @@ export default {
}"
class="note-body"
>
- <div :class="internalNoteContainerClasses" data-testid="note-internal-container">
- <suggestions
- v-if="hasSuggestion && !isEditing"
- :suggestions="note.suggestions"
- :suggestions-count="suggestionsCount"
- :batch-suggestions-info="batchSuggestionsInfo"
- :note-html="note.note_html"
- :line-type="lineType"
- :help-page-path="helpPagePath"
- :default-commit-message="commitMessage"
- :failed-to-load-metadata="failedToLoadMetadata"
- @apply="applySuggestion"
- @applyBatch="applySuggestionBatch"
- @addToBatch="addSuggestionToBatch"
- @removeFromBatch="removeSuggestionFromBatch"
- />
- <div v-else v-safe-html:[$options.safeHtmlConfig]="note.note_html" class="note-text md"></div>
- <note-form
- v-if="isEditing"
- ref="noteForm"
- :note-body="noteBody"
- :note-id="note.id"
- :line="line"
- :note="note"
- :save-button-title="saveButtonTitle"
- :help-page-path="helpPagePath"
- :discussion="discussion"
- :resolve-discussion="note.resolve_discussion"
- @handleFormUpdate="handleFormUpdate"
- @cancelForm="formCancelHandler"
- />
- <!-- eslint-disable vue/no-mutating-props -->
- <textarea
- v-if="canEdit"
- v-model="note.note"
- :data-update-url="note.path"
- class="hidden js-task-list-field"
- dir="auto"
- ></textarea>
- <!-- eslint-enable vue/no-mutating-props -->
- <note-edited-text
- v-if="note.last_edited_at"
- :edited-at="note.last_edited_at"
- :edited-by="note.last_edited_by"
- action-text="Edited"
- class="note_edited_ago"
- />
- </div>
+ <suggestions
+ v-if="hasSuggestion && !isEditing"
+ :suggestions="note.suggestions"
+ :suggestions-count="suggestionsCount"
+ :batch-suggestions-info="batchSuggestionsInfo"
+ :note-html="note.note_html"
+ :line-type="lineType"
+ :help-page-path="helpPagePath"
+ :default-commit-message="commitMessage"
+ :failed-to-load-metadata="failedToLoadMetadata"
+ @apply="applySuggestion"
+ @applyBatch="applySuggestionBatch"
+ @addToBatch="addSuggestionToBatch"
+ @removeFromBatch="removeSuggestionFromBatch"
+ />
+ <div v-else v-safe-html:[$options.safeHtmlConfig]="note.note_html" class="note-text md"></div>
+ <note-form
+ v-if="isEditing"
+ ref="noteForm"
+ :note-body="noteBody"
+ :note-id="note.id"
+ :line="line"
+ :note="note"
+ :save-button-title="saveButtonTitle"
+ :help-page-path="helpPagePath"
+ :discussion="discussion"
+ :resolve-discussion="note.resolve_discussion"
+ @handleFormUpdate="handleFormUpdate"
+ @cancelForm="formCancelHandler"
+ />
+ <!-- eslint-disable vue/no-mutating-props -->
+ <textarea
+ v-if="canEdit"
+ v-model="note.note"
+ :data-update-url="note.path"
+ class="hidden js-task-list-field"
+ dir="auto"
+ ></textarea>
+ <!-- eslint-enable vue/no-mutating-props -->
+ <note-edited-text
+ v-if="note.last_edited_at"
+ :edited-at="note.last_edited_at"
+ :edited-by="note.last_edited_by"
+ action-text="Edited"
+ class="note_edited_ago"
+ />
<note-awards-list
v-if="note.award_emoji && note.award_emoji.length"
:note-id="note.id"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index a4cd20e6db8..30579a8eb0d 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -251,8 +251,10 @@ export default {
}
},
cancelHandler(shouldConfirm = false) {
- // Sends information about confirm message and if the textarea has changed
- this.$emit('cancelForm', shouldConfirm, this.noteBody !== this.updatedNoteBody);
+ // check if any dropdowns are active before sending the cancelation event
+ if (!this.$refs.textarea.classList.contains('at-who-active')) {
+ this.$emit('cancelForm', shouldConfirm, this.noteBody !== this.updatedNoteBody);
+ }
},
onInput() {
if (this.isSubmittingWithKeydown) {
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 095ab5ddb0f..875cfff74fe 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -406,7 +406,7 @@ export default {
<template>
<timeline-entry-item
:id="noteAnchorId"
- :class="classNameBindings"
+ :class="{ ...classNameBindings, 'internal-note': note.confidential }"
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
class="note note-wrapper"
@@ -506,7 +506,6 @@ export default {
ref="noteBody"
:note="note"
:can-edit="note.current_user.can_edit"
- :is-internal-note="note.confidential"
:line="line"
:file="diffFile"
:is-editing="isEditing"
diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js
index 3317f4e2383..a5f459c8910 100644
--- a/app/assets/javascripts/notes/constants.js
+++ b/app/assets/javascripts/notes/constants.js
@@ -51,5 +51,3 @@ export const toggleStateErrorMessage = {
[REOPENED]: __('Something went wrong while closing the merge request. Please try again later.'),
},
};
-
-export const INTERNAL_NOTE_CLASSES = ['gl-bg-orange-50', 'gl-px-4', 'gl-py-2'];
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 39d0a46d6d0..0823eacf1b7 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -7,7 +7,7 @@ import * as utils from './utils';
export default {
[types.ADD_NEW_NOTE](state, data) {
const note = data.discussion ? data.discussion.notes[0] : data;
- const { discussion_id, type } = note;
+ const { discussion_id: discussionId, type } = note;
const [exists] = state.discussions.filter((n) => n.id === note.discussion_id);
const isDiscussion = type === constants.DISCUSSION_NOTE || type === constants.DIFF_NOTE;
@@ -17,9 +17,9 @@ export default {
if (!discussion) {
discussion = {
expanded: true,
- id: discussion_id,
+ id: discussionId,
individual_note: !isDiscussion,
- reply_id: discussion_id,
+ reply_id: discussionId,
};
if (isDiscussion && isInMRPage()) {
diff --git a/app/assets/javascripts/notes/utils.js b/app/assets/javascripts/notes/utils.js
index ec18a570960..14e97fcef46 100644
--- a/app/assets/javascripts/notes/utils.js
+++ b/app/assets/javascripts/notes/utils.js
@@ -1,5 +1,5 @@
/* eslint-disable @gitlab/require-i18n-strings */
-import marked from 'marked';
+import { marked } from 'marked';
import { sanitize } from '~/lib/dompurify';
import { markdownConfig } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
index bfa99c01c3f..ce221a274c9 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status.vue
@@ -60,7 +60,7 @@ export default {
return this.$options.i18n[`CLEANUP_STATUS_${this.status}`];
},
calculatedTimeTilNextRun() {
- return timeTilRun(this.expirationPolicy?.next_run);
+ return timeTilRun(this.expirationPolicy?.next_run_at);
},
expireIconName() {
return this.failedDelete ? 'expire' : 'clock';
@@ -90,9 +90,9 @@ export default {
{{ statusText }}
</span>
<gl-icon
- v-if="failedDelete"
+ v-if="failedDelete && calculatedTimeTilNextRun"
:id="iconId"
- :size="14"
+ :size="16"
class="gl-text-gray-500"
data-testid="extra-info"
name="information-o"
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
index aecc0bf92ea..80bca536b7c 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue
@@ -95,7 +95,7 @@ export default {
if (this.showFullPath) {
return this.item.path;
}
- const projectPath = this.item?.project?.path ?? '';
+ const projectPath = this.item?.project?.path?.toLowerCase() ?? '';
if (this.item.name) {
return joinPaths(projectPath, this.item.name);
}
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
index 1faff1ff4de..45dc217b9e3 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
@@ -39,7 +39,7 @@ export default {
directives: {
GlModalDirective,
},
- inject: ['groupPath', 'groupId', 'noManifestsIllustration'],
+ inject: ['groupPath', 'groupId', 'noManifestsIllustration', 'canClearCache'],
i18n: {
proxyImagePrefix: s__('DependencyProxy|Dependency Proxy image prefix'),
copyImagePrefixText: s__('DependencyProxy|Copy prefix'),
@@ -114,7 +114,7 @@ export default {
);
},
showDeleteDropdown() {
- return this.group.dependencyProxyManifests?.nodes.length > 0;
+ return this.group.dependencyProxyManifests?.nodes.length > 0 && this.canClearCache;
},
showDependencyProxyImagePrefix() {
return this.group.dependencyProxyImagePrefix?.length > 0;
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
index 14789aafdb7..428d6d6cd75 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import app from '~/packages_and_registries/dependency_proxy/app.vue';
import { apolloProvider } from '~/packages_and_registries/dependency_proxy/graphql';
import Translate from '~/vue_shared/translate';
@@ -10,12 +11,15 @@ export const initDependencyProxyApp = () => {
if (!el) {
return null;
}
- const { ...dataset } = el.dataset;
+ const { groupPath, groupId, noManifestsIllustration, canClearCache } = el.dataset;
return new Vue({
el,
apolloProvider,
provide: {
- ...dataset,
+ groupPath,
+ groupId,
+ noManifestsIllustration,
+ canClearCache: parseBoolean(canClearCache),
},
render(createElement) {
return createElement(app);
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 408d34fbe93..51a38c434cb 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
@@ -26,8 +26,7 @@ export const receivePackagesListSuccess = ({ commit }, { data, headers }) => {
export const requestPackagesList = ({ dispatch, state }, params = {}) => {
dispatch('setLoading', true);
- // eslint-disable-next-line camelcase
- const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params;
+ const { page = DEFAULT_PAGE, per_page: perPage = DEFAULT_PAGE_SIZE } = params;
const { sort, orderBy } = state.sorting;
const type = state.config.forceTerraform
? TERRAFORM_SEARCH_TYPE
@@ -38,7 +37,7 @@ export const requestPackagesList = ({ dispatch, state }, params = {}) => {
const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages';
return Api[apiMethod](state.config.resourceId, {
- params: { page, per_page, sort, order_by: orderBy, ...packageFilters },
+ params: { page, per_page: perPage, sort, order_by: orderBy, ...packageFilters },
})
.then(({ data, headers }) => {
dispatch('receivePackagesListSuccess', { data, headers });
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
index a049b0eff8d..b872294d2cf 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
@@ -1,14 +1,16 @@
<script>
-import { GlLink, GlTableLite, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
+import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlButton, GlFormCheckbox } from '@gitlab/ui';
import { last } from 'lodash';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import FileSha from '~/packages_and_registries/package_registry/components/details/file_sha.vue';
import Tracking from '~/tracking';
import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
+ REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION,
+ SELECT_PACKAGE_FILE_TRACKING_ACTION,
TRACKING_LABEL_PACKAGE_ASSET,
TRACKING_ACTION_EXPAND_PACKAGE_ASSET,
} from '~/packages_and_registries/package_registry/constants';
@@ -17,10 +19,10 @@ export default {
name: 'PackageFiles',
components: {
GlLink,
- GlTableLite,
- GlIcon,
+ GlTable,
GlDropdown,
GlDropdownItem,
+ GlFormCheckbox,
GlButton,
FileIcon,
TimeAgoTooltip,
@@ -33,13 +35,29 @@ export default {
required: false,
default: false,
},
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
packageFiles: {
type: Array,
required: false,
default: () => [],
},
},
+ data() {
+ return {
+ selectedReferences: [],
+ };
+ },
computed: {
+ areFilesSelected() {
+ return this.selectedReferences.length > 0;
+ },
+ areAllFilesSelected() {
+ return this.packageFiles.every(this.isSelected);
+ },
filesTableRows() {
return this.packageFiles.map((pf) => ({
...pf,
@@ -47,6 +65,9 @@ export default {
pipeline: last(pf.pipelines),
}));
},
+ hasSelectedSomeFiles() {
+ return this.areFilesSelected && !this.areAllFilesSelected;
+ },
showCommitColumn() {
// note that this is always false for now since we do not return
// pipelines associated to files for performance concerns
@@ -55,6 +76,12 @@ export default {
filesTableHeaderFields() {
return [
{
+ key: 'checkbox',
+ label: __('Select all'),
+ class: 'gl-w-4',
+ hide: !this.canDelete,
+ },
+ {
key: 'name',
label: __('Name'),
},
@@ -77,7 +104,7 @@ export default {
label: '',
hide: !this.canDelete,
class: 'gl-text-right',
- tdClass: 'gl-w-4',
+ tdClass: 'gl-w-4 gl-pt-3!',
},
].filter((c) => !c.hide);
},
@@ -99,21 +126,71 @@ export default {
this.track(TRACKING_ACTION_EXPAND_PACKAGE_ASSET, { label: TRACKING_LABEL_PACKAGE_ASSET });
}
},
+ updateSelectedReferences(selection) {
+ this.track(SELECT_PACKAGE_FILE_TRACKING_ACTION);
+ this.selectedReferences = selection;
+ },
+ isSelected(packageFile) {
+ return this.selectedReferences.find((reference) => reference.id === packageFile.id);
+ },
+ handleFileDeleteSelected() {
+ this.track(REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION);
+ this.$emit('delete-files', this.selectedReferences);
+ },
},
i18n: {
deleteFile: __('Delete file'),
+ deleteSelected: s__('PackageRegistry|Delete selected'),
+ moreActionsText: __('More actions'),
},
};
</script>
<template>
- <div>
- <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3>
- <gl-table-lite
+ <div class="gl-pt-6">
+ <div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
+ <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3>
+ <gl-button
+ v-if="canDelete"
+ :disabled="isLoading || !areFilesSelected"
+ category="secondary"
+ variant="danger"
+ data-testid="delete-selected"
+ @click="handleFileDeleteSelected"
+ >
+ {{ $options.i18n.deleteSelected }}
+ </gl-button>
+ </div>
+ <gl-table
:fields="filesTableHeaderFields"
:items="filesTableRows"
+ show-empty
+ selectable
+ select-mode="multi"
+ selected-variant="primary"
:tbody-tr-attr="{ 'data-testid': 'file-row' }"
+ @row-selected="updateSelectedReferences"
>
+ <template #head(checkbox)="{ selectAllRows, clearSelected }">
+ <gl-form-checkbox
+ v-if="canDelete"
+ data-testid="package-files-checkbox-all"
+ :checked="areAllFilesSelected"
+ :indeterminate="hasSelectedSomeFiles"
+ @change="areAllFilesSelected ? clearSelected() : selectAllRows()"
+ />
+ </template>
+
+ <template #cell(checkbox)="{ rowSelected, selectRow, unselectRow }">
+ <gl-form-checkbox
+ v-if="canDelete"
+ class="gl-mt-1"
+ :checked="rowSelected"
+ data-testid="package-files-checkbox"
+ @change="rowSelected ? unselectRow() : selectRow()"
+ />
+ </template>
+
<template #cell(name)="{ item, toggleDetails, detailsShowing }">
<gl-button
v-if="hasDetails(item)"
@@ -156,11 +233,15 @@ export default {
</template>
<template #cell(actions)="{ item }">
- <gl-dropdown category="tertiary" right>
- <template #button-content>
- <gl-icon name="ellipsis_v" />
- </template>
- <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
+ <gl-dropdown
+ category="tertiary"
+ icon="ellipsis_v"
+ :text-sr-only="true"
+ :text="$options.i18n.moreActionsText"
+ no-caret
+ right
+ >
+ <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-files', [item])">
{{ $options.i18n.deleteFile }}
</gl-dropdown-item>
</gl-dropdown>
@@ -180,6 +261,6 @@ export default {
<file-sha v-if="item.fileSha1" data-testid="sha-1" title="SHA-1" :sha="item.fileSha1" />
</div>
</template>
- </gl-table-lite>
+ </gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
index 96b82a20364..a1fc7563de1 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
@@ -5,12 +5,17 @@ import { first } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__, n__ } from '~/locale';
+import Tracking from '~/tracking';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import { HISTORY_PIPELINES_LIMIT } from '~/packages_and_registries/shared/constants';
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
GRAPHQL_PACKAGE_PIPELINES_PAGE_SIZE,
FETCH_PACKAGE_PIPELINES_ERROR_MESSAGE,
+ TRACKING_ACTION_CLICK_PIPELINE_LINK,
+ TRACKING_ACTION_CLICK_COMMIT_LINK,
+ TRACKING_LABEL_PACKAGE_HISTORY,
} from '../../constants';
import getPackagePipelinesQuery from '../../graphql/queries/get_package_pipelines.query.graphql';
import PackageHistoryLoader from './package_history_loader.vue';
@@ -37,6 +42,9 @@ export default {
PackageHistoryLoader,
TimeAgoTooltip,
},
+ mixins: [Tracking.mixin()],
+ TRACKING_ACTION_CLICK_PIPELINE_LINK,
+ TRACKING_ACTION_CLICK_COMMIT_LINK,
props: {
packageEntity: {
type: Object,
@@ -97,6 +105,11 @@ export default {
first: GRAPHQL_PACKAGE_PIPELINES_PAGE_SIZE,
};
},
+ tracking() {
+ return {
+ category: packageTypeToTrackCategory(this.packageType),
+ };
+ },
},
methods: {
truncate(value) {
@@ -105,6 +118,12 @@ export default {
convertToBaseId(value) {
return getIdFromGraphQLId(value);
},
+ trackPipelineClick() {
+ this.track(TRACKING_ACTION_CLICK_PIPELINE_LINK, { label: TRACKING_LABEL_PACKAGE_HISTORY });
+ },
+ trackCommitClick() {
+ this.track(TRACKING_ACTION_CLICK_COMMIT_LINK, { label: TRACKING_LABEL_PACKAGE_HISTORY });
+ },
},
};
</script>
@@ -140,7 +159,9 @@ export default {
<history-item icon="commit" data-testid="first-pipeline-commit">
<gl-sprintf :message="$options.i18n.createdByCommitText">
<template #link>
- <gl-link :href="firstPipeline.commitPath">#{{ truncate(firstPipeline.sha) }}</gl-link>
+ <gl-link :href="firstPipeline.commitPath" @click="trackCommitClick"
+ >#{{ truncate(firstPipeline.sha) }}</gl-link
+ >
</template>
<template #branch>
<strong>{{ firstPipeline.ref }}</strong>
@@ -150,7 +171,9 @@ export default {
<history-item icon="pipeline" data-testid="first-pipeline-pipeline">
<gl-sprintf :message="$options.i18n.createdByPipelineText">
<template #link>
- <gl-link :href="firstPipeline.path">#{{ convertToBaseId(firstPipeline.id) }}</gl-link>
+ <gl-link :href="firstPipeline.path" @click="trackPipelineClick"
+ >#{{ convertToBaseId(firstPipeline.id) }}</gl-link
+ >
</template>
<template #datetime>
<time-ago-tooltip :time="firstPipeline.createdAt" />
@@ -189,13 +212,17 @@ export default {
>
<gl-sprintf :message="$options.i18n.combinedUpdateText">
<template #link>
- <gl-link :href="pipeline.commitPath">#{{ truncate(pipeline.sha) }}</gl-link>
+ <gl-link :href="pipeline.commitPath" @click="trackCommitClick"
+ >#{{ truncate(pipeline.sha) }}</gl-link
+ >
</template>
<template #branch>
<strong>{{ pipeline.ref }}</strong>
</template>
<template #pipeline>
- <gl-link :href="pipeline.path">#{{ convertToBaseId(pipeline.id) }}</gl-link>
+ <gl-link :href="pipeline.path" @click="trackPipelineClick"
+ >#{{ convertToBaseId(pipeline.id) }}</gl-link
+ >
</template>
<template #datetime>
<time-ago-tooltip :time="pipeline.createdAt" />
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 f5946797626..11fd0db3106 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
@@ -23,6 +23,7 @@ export default {
directives: {
GlResizeObserver: GlResizeObserverDirective,
},
+ inject: ['isGroupPage'],
i18n: {
packageInfo: __('v%{version} published %{timeAgo}'),
},
@@ -65,9 +66,6 @@ export default {
this.checkBreakpoints();
},
methods: {
- dynamicSlotName(index) {
- return `metadata-tag${index}`;
- },
checkBreakpoints() {
this.isDesktop = GlBreakpointInstance.isDesktop();
},
@@ -83,21 +81,38 @@ export default {
data-qa-selector="package_title"
>
<template #sub-header>
- <span data-testid="sub-header">
+ <div data-testid="sub-header" class="gl-display-flex gl-gap-3">
<gl-sprintf :message="$options.i18n.packageInfo">
<template #version>
{{ packageEntity.version }}
</template>
<template #timeAgo>
- <time-ago-tooltip
- v-if="packageEntity.createdAt"
- class="gl-ml-2"
- :time="packageEntity.createdAt"
- />
+ <time-ago-tooltip v-if="packageEntity.createdAt" :time="packageEntity.createdAt" />
</template>
</gl-sprintf>
- </span>
+
+ <package-tags
+ v-if="isDesktop && hasTagsToDisplay"
+ :tag-display-limit="2"
+ :tags="packageEntity.tags.nodes"
+ hide-label
+ />
+
+ <!-- we need to duplicate the package tags on mobile to ensure proper styling inside the flex wrap -->
+ <template v-else-if="hasTagsToDisplay">
+ <gl-badge
+ v-for="(tag, index) in packageEntity.tags.nodes"
+ :key="index"
+ class="gl-my-1"
+ data-testid="tag-badge"
+ variant="info"
+ size="sm"
+ >
+ {{ tag.name }}
+ </gl-badge>
+ </template>
+ </div>
</template>
<template v-if="packageTypeDisplay" #metadata-type>
@@ -108,7 +123,7 @@ export default {
<metadata-item data-testid="package-size" icon="disk" :text="totalSize" />
</template>
- <template v-if="packagePipeline" #metadata-pipeline>
+ <template v-if="isGroupPage && packagePipeline" #metadata-pipeline>
<metadata-item
data-testid="pipeline-project"
icon="review-list"
@@ -121,21 +136,6 @@ export default {
<metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
</template>
- <template v-if="isDesktop && hasTagsToDisplay" #metadata-tags>
- <package-tags :tag-display-limit="2" :tags="packageEntity.tags.nodes" hide-label />
- </template>
-
- <!-- we need to duplicate the package tags on mobile to ensure proper styling inside the flex wrap -->
- <template
- v-for="(tag, index) in packageEntity.tags.nodes"
- v-else-if="hasTagsToDisplay"
- #[dynamicSlotName(index)]
- >
- <gl-badge :key="index" class="gl-my-1" data-testid="tag-badge" variant="info" size="sm">
- {{ tag.name }}
- </gl-badge>
- </template>
-
<template #right-actions>
<slot name="delete-button"></slot>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
index a126d30f1ec..dd58f28a262 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
@@ -1,9 +1,10 @@
<script>
-import { GlLink, GlSprintf } from '@gitlab/ui';
+import { GlFormGroup, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
import {
+ PERSONAL_ACCESS_TOKEN_HELP_URL,
TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND,
TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
@@ -16,6 +17,7 @@ export default {
components: {
InstallationTitle,
CodeInstruction,
+ GlFormGroup,
GlLink,
GlSprintf,
},
@@ -43,6 +45,7 @@ password = <your personal access token>`;
TRACKING_LABEL_CODE_INSTRUCTION,
},
i18n: {
+ tokenText: s__(`PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}.`),
setupText: s__(
`PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file.`,
),
@@ -50,7 +53,10 @@ password = <your personal access token>`;
'PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}.',
),
},
- links: { PYPI_HELP_PATH },
+ links: {
+ PERSONAL_ACCESS_TOKEN_HELP_URL,
+ PYPI_HELP_PATH,
+ },
installOptions: [{ value: 'pypi', label: s__('PackageRegistry|Show PyPi commands') }],
};
</script>
@@ -59,14 +65,28 @@ password = <your personal access token>`;
<div>
<installation-title package-type="pypi" :options="$options.installOptions" />
- <code-instruction
- :label="s__('PackageRegistry|Pip Command')"
- :instruction="pypiPipCommand"
- :copy-text="s__('PackageRegistry|Copy Pip command')"
- data-testid="pip-command"
- :tracking-action="$options.tracking.TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND"
- :tracking-label="$options.tracking.TRACKING_LABEL_CODE_INSTRUCTION"
- />
+ <gl-form-group id="installation-pip-command-group">
+ <code-instruction
+ id="installation-pip-command"
+ :label="s__('PackageRegistry|Pip Command')"
+ :instruction="pypiPipCommand"
+ :copy-text="s__('PackageRegistry|Copy Pip command')"
+ data-testid="pip-command"
+ :tracking-action="$options.tracking.TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND"
+ :tracking-label="$options.tracking.TRACKING_LABEL_CODE_INSTRUCTION"
+ />
+ <template #description>
+ <gl-sprintf :message="$options.i18n.tokenText">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.links.PERSONAL_ACCESS_TOKEN_HELP_URL"
+ data-testid="access-token-link"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-form-group>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
<p>
@@ -87,7 +107,12 @@ password = <your personal access token>`;
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="$options.links.PYPI_HELP_PATH" target="_blank">{{ content }}</gl-link>
+ <gl-link
+ :href="$options.links.PYPI_HELP_PATH"
+ target="_blank"
+ data-testid="pypi-docs-link"
+ >{{ content }}</gl-link
+ >
</template>
</gl-sprintf>
</div>
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 cea053992f8..5b2a347a4ee 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -7,9 +7,12 @@ export {
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
PULL_PACKAGE_TRACKING_ACTION,
DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DELETE_PACKAGE_FILES_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
+ SELECT_PACKAGE_FILE_TRACKING_ACTION,
} from '~/packages_and_registries/shared/constants';
export const PACKAGE_TYPE_CONAN = 'CONAN';
@@ -69,6 +72,11 @@ export const TRACKING_ACTION_DOWNLOAD_PACKAGE_ASSET = 'download_package_asset';
export const TRACKING_ACTION_EXPAND_PACKAGE_ASSET = 'expand_package_asset';
export const TRACKING_ACTION_COPY_PACKAGE_ASSET_SHA = 'copy_package_asset_sha';
+export const TRACKING_ACTION_CLICK_PIPELINE_LINK = 'click_pipeline_link_from_package';
+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_PACKAGE_FILE_ERROR_MESSAGE = s__(
'PackageRegistry|Something went wrong while deleting the package file.',
@@ -76,6 +84,12 @@ export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
export const DELETE_PACKAGE_FILE_SUCCESS_MESSAGE = s__(
'PackageRegistry|Package file deleted successfully',
);
+export const DELETE_PACKAGE_FILES_ERROR_MESSAGE = s__(
+ 'PackageRegistry|Something went wrong while deleting the package assets.',
+);
+export const DELETE_PACKAGE_FILES_SUCCESS_MESSAGE = s__(
+ 'PackageRegistry|Package assets deleted successfully',
+);
export const FETCH_PACKAGE_DETAILS_ERROR_MESSAGE = s__(
'PackageRegistry|Failed to load the package data',
);
@@ -162,5 +176,6 @@ export const CONAN_HELP_PATH = helpPagePath('user/packages/conan_repository/inde
export const NUGET_HELP_PATH = helpPagePath('user/packages/nuget_repository/index');
export const PYPI_HELP_PATH = helpPagePath('user/packages/pypi_repository/index');
export const COMPOSER_HELP_PATH = helpPagePath('user/packages/composer_repository/index');
+export const PERSONAL_ACCESS_TOKEN_HELP_URL = helpPagePath('user/profile/personal_access_tokens');
export const GRAPHQL_PACKAGE_PIPELINES_PAGE_SIZE = 10;
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql
deleted file mode 100644
index f016640f57d..00000000000
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-mutation destroyPackageFile($id: PackagesPackageFileID!) {
- destroyPackageFile(input: { id: $id }) {
- errors
- }
-}
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql
new file mode 100644
index 00000000000..8f9a3156492
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql
@@ -0,0 +1,5 @@
+mutation destroyPackageFiles($projectPath: ID!, $ids: [PackagesPackageFileID!]!) {
+ destroyPackageFiles(input: { projectPath: $projectPath, ids: $ids }) {
+ errors
+ }
+}
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 5574020c9e4..f3f0d096d10 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
@@ -20,6 +20,7 @@ query getPackageDetails($id: PackagesPackageID!) {
id
path
name
+ fullPath
}
tags(first: 10) {
nodes {
@@ -39,6 +40,9 @@ query getPackageDetails($id: PackagesPackageID!) {
}
}
packageFiles(first: 100) {
+ pageInfo {
+ hasNextPage
+ }
nodes {
id
fileMd5
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 29438fba86b..e83962bb608 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
@@ -34,16 +34,19 @@ import {
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DELETE_PACKAGE_FILES_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
SHOW_DELETE_SUCCESS_ALERT,
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+ DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
} from '~/packages_and_registries/package_registry/constants';
-import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql';
+import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import Tracking from '~/tracking';
@@ -83,7 +86,8 @@ export default {
},
data() {
return {
- fileToDelete: null,
+ filesToDelete: [],
+ mutationLoading: false,
packageEntity: {},
};
},
@@ -114,6 +118,9 @@ export default {
projectName() {
return this.packageEntity.project?.name;
},
+ projectPath() {
+ return this.packageEntity.project?.fullPath;
+ },
packageId() {
return this.$route.params.id;
},
@@ -131,6 +138,9 @@ export default {
isLoading() {
return this.$apollo.queries.packageEntity.loading;
},
+ packageFilesLoading() {
+ return this.isLoading || this.mutationLoading;
+ },
isValidPackage() {
return this.isLoading || Boolean(this.packageEntity.name);
},
@@ -175,12 +185,14 @@ export default {
window.location.replace(`${returnTo}?${modalQuery}`);
},
- async deletePackageFile(id) {
+ async deletePackageFiles(ids) {
+ this.mutationLoading = true;
try {
const { data } = await this.$apollo.mutate({
- mutation: destroyPackageFileMutation,
+ mutation: destroyPackageFilesMutation,
variables: {
- id,
+ projectPath: this.projectPath,
+ ids,
},
awaitRefetchQueries: true,
refetchQueries: [
@@ -190,31 +202,53 @@ export default {
},
],
});
- if (data?.destroyPackageFile?.errors[0]) {
- throw data.destroyPackageFile.errors[0];
+ if (data?.destroyPackageFiles?.errors[0]) {
+ throw data.destroyPackageFiles.errors[0];
}
createFlash({
- message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+ message:
+ ids.length === 1
+ ? DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
+ : DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
type: 'success',
});
} catch (error) {
createFlash({
- message: DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ message:
+ ids.length === 1
+ ? DELETE_PACKAGE_FILE_ERROR_MESSAGE
+ : DELETE_PACKAGE_FILES_ERROR_MESSAGE,
type: 'warning',
captureError: true,
error,
});
}
+ this.mutationLoading = false;
},
- handleFileDelete(file) {
+ handleFileDelete(files) {
this.track(REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION);
- this.fileToDelete = { ...file };
- this.$refs.deleteFileModal.show();
+ if (
+ files.length === this.packageFiles.length &&
+ !this.packageEntity.packageFiles?.pageInfo?.hasNextPage
+ ) {
+ this.$refs.deleteModal.show();
+ } else {
+ this.filesToDelete = files;
+ if (files.length === 1) {
+ this.$refs.deleteFileModal.show();
+ } else if (files.length > 1) {
+ this.$refs.deleteFilesModal.show();
+ }
+ }
},
- confirmFileDelete() {
- this.track(DELETE_PACKAGE_FILE_TRACKING_ACTION);
- this.deletePackageFile(this.fileToDelete.id);
- this.fileToDelete = null;
+ confirmFilesDelete() {
+ if (this.filesToDelete.length === 1) {
+ this.track(DELETE_PACKAGE_FILE_TRACKING_ACTION);
+ } else {
+ this.track(DELETE_PACKAGE_FILES_TRACKING_ACTION);
+ }
+ this.deletePackageFiles(this.filesToDelete.map((file) => file.id));
+ this.filesToDelete = [];
},
},
i18n: {
@@ -240,6 +274,10 @@ export default {
text: __('Delete'),
attributes: [{ variant: 'danger' }, { category: 'primary' }],
},
+ filesDeletePrimaryAction: {
+ text: s__('PackageRegistry|Permanently delete assets'),
+ attributes: [{ variant: 'danger' }, { category: 'primary' }],
+ },
cancelAction: {
text: __('Cancel'),
},
@@ -287,9 +325,10 @@ export default {
<package-files
v-if="showFiles"
:can-delete="packageEntity.canDestroy"
+ :is-loading="packageFilesLoading"
:package-files="packageFiles"
@download-file="track($options.trackingActions.DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION)"
- @delete-file="handleFileDelete"
+ @delete-files="handleFileDelete"
/>
</gl-tab>
@@ -355,15 +394,43 @@ export default {
:action-primary="$options.modal.fileDeletePrimaryAction"
:action-cancel="$options.modal.cancelAction"
data-testid="delete-file-modal"
- @primary="confirmFileDelete"
+ @primary="confirmFilesDelete"
@canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
>
<template #modal-title>{{ $options.i18n.deleteFileModalTitle }}</template>
- <gl-sprintf v-if="fileToDelete" :message="$options.i18n.deleteFileModalContent">
+ <gl-sprintf v-if="filesToDelete.length === 1" :message="$options.i18n.deleteFileModalContent">
<template #filename>
- <strong>{{ fileToDelete.file_name }}</strong>
+ <strong>{{ filesToDelete[0].fileName }}</strong>
</template>
</gl-sprintf>
</gl-modal>
+
+ <gl-modal
+ ref="deleteFilesModal"
+ size="sm"
+ modal-id="delete-files-modal"
+ :action-primary="$options.modal.filesDeletePrimaryAction"
+ :action-cancel="$options.modal.cancelAction"
+ data-testid="delete-files-modal"
+ @primary="confirmFilesDelete"
+ @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
+ >
+ <template #modal-title>{{
+ n__(
+ `PackageRegistry|Delete 1 asset`,
+ `PackageRegistry|Delete %d assets`,
+ filesToDelete.length,
+ )
+ }}</template>
+ <span v-if="filesToDelete.length > 0">
+ {{
+ n__(
+ `PackageRegistry|You are about to delete 1 asset. This operation is irreversible.`,
+ `PackageRegistry|You are about to delete %d assets. This operation is irreversible.`,
+ filesToDelete.length,
+ )
+ }}
+ </span>
+ </gl-modal>
</div>
</template>
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 90a18d5cf5a..1c44d2bc38b 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
@@ -11,7 +11,7 @@ import {
UNAVAILABLE_ADMIN_FEATURE_TEXT,
} from '~/packages_and_registries/settings/project/constants';
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 SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue';
import ContainerExpirationPolicyForm from './container_expiration_policy_form.vue';
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
index 7682754fdcb..f06e3a41bd0 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/expiration_dropdown.vue
@@ -35,22 +35,34 @@ export default {
required: false,
default: '',
},
+ dropdownClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
};
</script>
<template>
<gl-form-group :id="`${name}-form-group`" :label-for="name" :label="label">
- <gl-form-select :id="name" :value="value" :disabled="disabled" @input="$emit('input', $event)">
- <option
- v-for="option in formOptions"
- :key="option.key"
- :value="option.key"
- data-testid="option"
+ <div :class="dropdownClass">
+ <gl-form-select
+ :id="name"
+ :value="value"
+ :disabled="disabled"
+ @input="$emit('input', $event)"
>
- {{ option.label }}
- </option>
- </gl-form-select>
+ <option
+ v-for="option in formOptions"
+ :key="option.key"
+ :value="option.key"
+ data-testid="option"
+ >
+ {{ option.label }}
+ </option>
+ </gl-form-select>
+ </div>
<template v-if="description" #description>
<span data-testid="description" class="gl-text-gray-400">
{{ description }}
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue
index 1170407a349..2f4bc35e5f7 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy.vue
@@ -6,7 +6,7 @@ import {
PACKAGES_CLEANUP_POLICY_DESCRIPTION,
} from '~/packages_and_registries/settings/project/constants';
import packagesCleanupPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_packages_cleanup_policy.query.graphql';
-import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+import SettingsBlock from '~/packages_and_registries/shared/components/settings_block.vue';
import PackagesCleanupPolicyForm from './packages_cleanup_policy_form.vue';
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue
index b1751d5174a..f1f0b970b15 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/project/components/packages_cleanup_policy_form.vue
@@ -3,10 +3,10 @@ import { GlButton } from '@gitlab/ui';
import {
UPDATE_SETTINGS_ERROR_MESSAGE,
UPDATE_SETTINGS_SUCCESS_MESSAGE,
- SET_CLEANUP_POLICY_BUTTON,
KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION,
KEEP_N_DUPLICATED_PACKAGE_FILES_FIELDNAME,
KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL,
+ SET_CLEANUP_POLICY_BUTTON,
} from '~/packages_and_registries/settings/project/constants';
import updatePackagesCleanupPolicyMutation from '~/packages_and_registries/settings/project/graphql/mutations/update_packages_cleanup_policy.mutation.graphql';
import { formOptionsGenerator } from '~/packages_and_registries/settings/project/utils';
@@ -108,18 +108,17 @@ export default {
<template>
<form ref="form-element" @submit.prevent="submit">
- <div class="gl-md-max-w-50p">
- <expiration-dropdown
- v-model="prefilledForm.keepNDuplicatedPackageFiles"
- :disabled="isFieldDisabled"
- :form-options="$options.formOptions.keepNDuplicatedPackageFiles"
- :label="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL"
- :description="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION"
- name="keep-n-duplicated-package-files"
- data-testid="keep-n-duplicated-package-files-dropdown"
- @input="onModelChange($event, 'keepNDuplicatedPackageFiles')"
- />
- </div>
+ <expiration-dropdown
+ :value="prefilledForm.keepNDuplicatedPackageFiles"
+ :disabled="isFieldDisabled"
+ :form-options="$options.formOptions.keepNDuplicatedPackageFiles"
+ :label="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_LABEL"
+ :description="$options.i18n.KEEP_N_DUPLICATED_PACKAGE_FILES_DESCRIPTION"
+ dropdown-class="gl-md-max-w-50p gl-sm-pr-5"
+ name="keep-n-duplicated-package-files"
+ data-testid="keep-n-duplicated-package-files-dropdown"
+ @input="onModelChange($event, 'keepNDuplicatedPackageFiles')"
+ />
<div class="gl-mt-7 gl-display-flex gl-align-items-center">
<gl-button
data-testid="save-button"
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/constants.js b/app/assets/javascripts/packages_and_registries/settings/project/constants.js
index 948520151ce..fcb4a8ee297 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/constants.js
+++ b/app/assets/javascripts/packages_and_registries/settings/project/constants.js
@@ -4,7 +4,7 @@ export const CONTAINER_CLEANUP_POLICY_TITLE = s__(`ContainerRegistry|Clean up im
export const CONTAINER_CLEANUP_POLICY_DESCRIPTION = s__(
`ContainerRegistry|Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}`,
);
-export const SET_CLEANUP_POLICY_BUTTON = __('Save');
+export const SET_CLEANUP_POLICY_BUTTON = __('Save changes');
export const UNAVAILABLE_FEATURE_TITLE = s__(
`ContainerRegistry|Cleanup policy for tags is disabled`,
);
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue
index 5caf95cd050..0458b914b58 100644
--- a/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/settings_block.vue
@@ -1,7 +1,7 @@
<template>
<section class="settings gl-py-7">
- <div class="gl-lg-display-flex">
- <div class="gl-lg-w-half gl-pr-10">
+ <div class="gl-lg-display-flex gl-gap-6">
+ <div class="gl-lg-w-40p gl-pr-10 gl-flex-shrink-0">
<h4>
<slot name="title"></slot>
</h4>
@@ -9,7 +9,7 @@
<slot name="description"></slot>
</p>
</div>
- <div class="gl-lg-w-half gl-pt-3">
+ <div class="gl-pt-3 gl-flex-grow-1">
<slot></slot>
</div>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
index 5505205cf33..6744e821565 100644
--- a/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
+++ b/app/assets/javascripts/packages_and_registries/shared/constants/package_registry.js
@@ -9,7 +9,11 @@ export const REQUEST_DELETE_PACKAGE_TRACKING_ACTION = 'request_delete_package';
export const CANCEL_DELETE_PACKAGE_TRACKING_ACTION = 'cancel_delete_package';
export const PULL_PACKAGE_TRACKING_ACTION = 'pull_package';
export const DELETE_PACKAGE_FILE_TRACKING_ACTION = 'delete_package_file';
+export const DELETE_PACKAGE_FILES_TRACKING_ACTION = 'delete_package_files';
+export const SELECT_PACKAGE_FILE_TRACKING_ACTION = 'select_package_file';
export const REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'request_delete_package_file';
+export const REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION =
+ 'request_delete_selected_package_file';
export const CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'cancel_delete_package_file';
export const DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION = 'download_package_asset';
diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue
index 713287f65b4..f01e5e595a3 100644
--- a/app/assets/javascripts/pages/groups/new/components/app.vue
+++ b/app/assets/javascripts/pages/groups/new/components/app.vue
@@ -2,51 +2,74 @@
import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg';
import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
import createGroupDescriptionDetails from './create_group_description_details.vue';
-const PANELS = [
- {
- name: 'create-group-pane',
- selector: '#create-group-pane',
- title: s__('GroupsNew|Create group'),
- description: s__(
- 'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
- ),
- illustration: newGroupIllustration,
- details: createGroupDescriptionDetails,
- },
- {
- name: 'import-group-pane',
- selector: '#import-group-pane',
- title: s__('GroupsNew|Import group'),
- description: s__('GroupsNew|Import a group and related data from another GitLab instance.'),
- illustration: importGroupIllustration,
- details: 'Migrate your existing groups from another instance of GitLab.',
- },
-];
-
export default {
components: {
NewNamespacePage,
},
props: {
+ parentGroupName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ importExistingGroupPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
hasErrors: {
type: Boolean,
required: false,
default: false,
},
},
- PANELS,
+ computed: {
+ initialBreadcrumb() {
+ return this.parentGroupName || __('New group');
+ },
+ panels() {
+ return [
+ {
+ name: 'create-group-pane',
+ selector: '#create-group-pane',
+ title: this.parentGroupName
+ ? s__('GroupsNew|Create subgroup')
+ : s__('GroupsNew|Create group'),
+ description: s__(
+ 'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
+ ),
+ illustration: newGroupIllustration,
+ details: createGroupDescriptionDetails,
+ detailProps: {
+ parentGroupName: this.parentGroupName,
+ importExistingGroupPath: this.importExistingGroupPath,
+ },
+ },
+ {
+ name: 'import-group-pane',
+ selector: '#import-group-pane',
+ title: s__('GroupsNew|Import group'),
+ description: s__(
+ 'GroupsNew|Import a group and related data from another GitLab instance.',
+ ),
+ illustration: importGroupIllustration,
+ details: 'Migrate your existing groups from another instance of GitLab.',
+ },
+ ];
+ },
+ },
};
</script>
<template>
<new-namespace-page
:jump-to-last-persisted-panel="hasErrors"
- :initial-breadcrumb="__('New group')"
- :panels="$options.PANELS"
+ :initial-breadcrumb="initialBreadcrumb"
+ :panels="panels"
:title="s__('GroupsNew|Create new group')"
persistence-key="new_group_last_active_tab"
/>
diff --git a/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
index 35193171fb8..be8542628c4 100644
--- a/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
+++ b/app/assets/javascripts/pages/groups/new/components/create_group_description_details.vue
@@ -1,6 +1,22 @@
<script>
import { GlSprintf, GlLink } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
+import { s__ } from '~/locale';
+
+const DESCRIPTION_DETAILS = {
+ group: [
+ s__(
+ 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
+ ),
+ s__('GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}.'),
+ ],
+ subgroup: [
+ s__(
+ '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.',
+ ),
+ s__('GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}.'),
+ ],
+};
export default {
components: {
@@ -11,30 +27,46 @@ export default {
groupsHelpPath: helpPagePath('user/group/index'),
subgroupsHelpPath: helpPagePath('user/group/subgroups/index'),
},
+ props: {
+ parentGroupName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ importExistingGroupPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ descriptionDetails: DESCRIPTION_DETAILS,
};
</script>
<template>
<div>
<p>
- <gl-sprintf
- :message="
- s__(
- 'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
- )
- "
- >
+ <gl-sprintf v-if="parentGroupName" :message="$options.descriptionDetails.subgroup[0]">
+ <template #groupsLink="{ content }">
+ <gl-link :href="$options.paths.groupsHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ <template #subgroupsLink="{ content }">
+ <gl-link :href="$options.paths.subgroupsHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ <gl-sprintf v-else :message="$options.descriptionDetails.group[0]">
<template #link="{ content }">
<gl-link :href="$options.paths.groupsHelpPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
<p>
- <gl-sprintf
- :message="
- s__('GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}.')
- "
- >
+ <gl-sprintf v-if="parentGroupName" :message="$options.descriptionDetails.subgroup[1]">
+ <template #link="{ content }">
+ <gl-link :href="importExistingGroupPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ <gl-sprintf v-else :message="$options.descriptionDetails.group[1]">
<template #link="{ content }">
<gl-link :href="$options.paths.subgroupsHelpPath" target="_blank">{{ content }}</gl-link>
</template>
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 7c409010510..7dab5258b24 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -16,9 +16,18 @@ BindInOut.initAll();
initFilePickers();
function initNewGroupCreation(el) {
- const { hasErrors, verificationRequired, verificationFormUrl, subscriptionsUrl } = el.dataset;
+ const {
+ hasErrors,
+ parentGroupName,
+ importExistingGroupPath,
+ verificationRequired,
+ verificationFormUrl,
+ subscriptionsUrl,
+ } = el.dataset;
const props = {
+ parentGroupName,
+ importExistingGroupPath,
hasErrors: parseBoolean(hasErrors),
};
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 6748a62e777..9cce6723bf7 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
@@ -68,7 +68,7 @@ export default {
}),
tableCell({
key: 'created_at',
- label: __('Date'),
+ label: __('Start date'),
}),
tableCell({
key: 'status',
diff --git a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
index 3fae9809e51..c520042c172 100644
--- a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
+++ b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
@@ -2,12 +2,10 @@ import {
initAccessTokenTableApp,
initExpiresAtField,
initNewAccessTokenApp,
- initProjectsField,
initTokensApp,
} from '~/access_tokens';
initAccessTokenTableApp();
initExpiresAtField();
initNewAccessTokenApp();
-initProjectsField();
initTokensApp();
diff --git a/app/assets/javascripts/pages/projects/ci/secure_files/show/index.js b/app/assets/javascripts/pages/projects/ci/secure_files/show/index.js
deleted file mode 100644
index 61486606665..00000000000
--- a/app/assets/javascripts/pages/projects/ci/secure_files/show/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { initCiSecureFiles } from '~/ci_secure_files';
-
-initCiSecureFiles();
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index c217bc5a727..65e7f48ed24 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -55,18 +55,30 @@ waitForCSSLoaded(() => {
},
attrs: {
height: LANGUAGE_CHART_HEIGHT,
+ responsive: true,
},
});
},
});
+ const {
+ graphEndpoint,
+ graphEndDate,
+ graphStartDate,
+ graphRef,
+ graphCsvPath,
+ } = codeCoverageContainer.dataset;
// eslint-disable-next-line no-new
new Vue({
el: codeCoverageContainer,
render(h) {
return h(CodeCoverage, {
props: {
- graphEndpoint: codeCoverageContainer.dataset?.graphEndpoint,
+ graphEndpoint,
+ graphEndDate,
+ graphStartDate,
+ graphRef,
+ graphCsvPath,
},
});
},
@@ -92,6 +104,9 @@ waitForCSSLoaded(() => {
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
+ attrs: {
+ responsive: true,
+ },
});
},
});
@@ -125,6 +140,9 @@ waitForCSSLoaded(() => {
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
+ attrs: {
+ responsive: true,
+ },
});
},
});
@@ -149,6 +167,9 @@ waitForCSSLoaded(() => {
yAxisTitle: __('No. of commits'),
xAxisType: 'category',
},
+ attrs: {
+ responsive: true,
+ },
});
},
});
diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
index 92ae8128285..d7e68484143 100644
--- a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
+++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlButton, GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import { get } from 'lodash';
import { formatDate } from '~/lib/utils/datetime_utility';
@@ -11,6 +11,7 @@ export default {
components: {
GlAlert,
GlAreaChart,
+ GlButton,
GlDropdown,
GlDropdownItem,
GlSprintf,
@@ -20,6 +21,22 @@ export default {
type: String,
required: true,
},
+ graphEndDate: {
+ type: String,
+ required: true,
+ },
+ graphStartDate: {
+ type: String,
+ required: true,
+ },
+ graphRef: {
+ type: String,
+ required: true,
+ },
+ graphCsvPath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -119,6 +136,28 @@ export default {
<template>
<div>
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-t gl-pt-4 gl-mb-3"
+ >
+ <h4 class="gl-m-0" sub-header>
+ <gl-sprintf
+ :message="__('Code coverage statistics for %{ref} %{start_date} - %{end_date}')"
+ >
+ <template #ref>
+ <strong> {{ graphRef }} </strong>
+ </template>
+ <template #start_date>
+ <strong> {{ graphStartDate }} </strong>
+ </template>
+ <template #end_date>
+ <strong> {{ graphEndDate }} </strong>
+ </template>
+ </gl-sprintf>
+ </h4>
+ <gl-button v-if="canShowData" size="small" data-testid="download-button" :href="graphCsvPath">
+ {{ __('Download raw data (.csv)') }}
+ </gl-button>
+ </div>
<div class="gl-mt-3 gl-mb-3">
<gl-alert
v-if="hasFetchError"
@@ -155,6 +194,7 @@ export default {
:data="chartData"
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
+ responsive
>
<template v-if="canShowData" #tooltip-title>
{{ tooltipTitle }}
diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js
index 7db34816cfe..f7849e8d588 100644
--- a/app/assets/javascripts/pages/projects/init_blob.js
+++ b/app/assets/javascripts/pages/projects/init_blob.js
@@ -4,6 +4,7 @@ import BlobForkSuggestion from '~/blob/blob_fork_suggestion';
import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import LineHighlighter from '~/blob/line_highlighter';
import initBlobBundle from '~/blob_edit/blob_bundle';
+import addBlobLinksTracking from '~/blob/blob_links_tracking';
export default () => {
new LineHighlighter(); // eslint-disable-line no-new
@@ -11,10 +12,16 @@ export default () => {
// eslint-disable-next-line no-new
new BlobLinePermalinkUpdater(
document.querySelector('#blob-content-holder'),
- '.diff-line-num[data-line-number], .diff-line-num[data-line-number] *',
+ '.file-line-num[data-line-number], .file-line-num[data-line-number] *',
document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'),
);
+ const eventsToTrack = [
+ { selector: '.file-line-blame', property: 'blame' },
+ { selector: '.file-line-num', property: 'link' },
+ ];
+ addBlobLinksTracking('#blob-content-holder', eventsToTrack);
+
const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');
const fileBlobPermalinkUrl =
fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index ca2b1a08be8..c92958cd8c7 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,6 +1,6 @@
import { initShow } from '~/issues';
import { store } from '~/notes/stores';
-import initRelatedIssues from '~/related_issues';
+import { initRelatedIssues } from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initWorkItemLinks from '~/work_items/components/work_item_links';
diff --git a/app/assets/javascripts/pages/projects/pages/new/index.js b/app/assets/javascripts/pages/projects/pages/new/index.js
new file mode 100644
index 00000000000..a5157f5b01b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pages/new/index.js
@@ -0,0 +1,3 @@
+import initPages from '~/gitlab_pages/new';
+
+initPages();
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 cd4bc35e74e..9513f42d9c9 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -1,4 +1,6 @@
import Vue from 'vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import PipelineSchedulesTakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
function initPipelineSchedules() {
@@ -23,4 +25,43 @@ function initPipelineSchedules() {
});
}
+function initTakeownershipModal() {
+ const modalId = 'pipeline-take-ownership-modal';
+ const buttonSelector = 'js-take-ownership-button';
+ const el = document.getElementById(modalId);
+ const takeOwnershipButtons = document.querySelectorAll(`.${buttonSelector}`);
+
+ if (!el) {
+ return;
+ }
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ data() {
+ return {
+ url: '',
+ };
+ },
+ mounted() {
+ takeOwnershipButtons.forEach((button) => {
+ button.addEventListener('click', () => {
+ const { url } = button.dataset;
+
+ this.url = url;
+ this.$root.$emit(BV_SHOW_MODAL, modalId, `.${buttonSelector}`);
+ });
+ });
+ },
+ render(createElement) {
+ return createElement(PipelineSchedulesTakeOwnershipModal, {
+ props: {
+ ownershipUrl: this.url,
+ },
+ });
+ },
+ });
+}
+
initPipelineSchedules();
+initTakeownershipModal();
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 f2c30870a68..c7c331c7de5 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
@@ -29,6 +29,10 @@ export default {
lfsLabel: s__('ProjectSettings|Git Large File Storage (LFS)'),
mergeRequestsLabel: s__('ProjectSettings|Merge requests'),
operationsLabel: s__('ProjectSettings|Operations'),
+ environmentsLabel: s__('ProjectSettings|Environments'),
+ environmentsHelpText: s__(
+ 'ProjectSettings|Every project can make deployments to environments either via CI/CD or API calls. Non-project members have read-only access.',
+ ),
packagesHelpText: s__(
'ProjectSettings|Every project can have its own space to store its packages. Note: The Package Registry is always visible when a project is public.',
),
@@ -209,6 +213,7 @@ export default {
requirementsAccessLevel: featureAccessLevel.EVERYONE,
securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
operationsAccessLevel: featureAccessLevel.EVERYONE,
+ environmentsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryAccessLevel: featureAccessLevel.EVERYONE,
warnAboutPotentiallyUnwantedCharacters: true,
lfsEnabled: true,
@@ -282,6 +287,9 @@ export default {
return this.operationsAccessLevel > featureAccessLevel.NOT_ENABLED;
},
+ environmentsEnabled() {
+ return this.environmentsAccessLevel > featureAccessLevel.NOT_ENABLED;
+ },
repositoryEnabled() {
return this.repositoryAccessLevel > featureAccessLevel.NOT_ENABLED;
},
@@ -318,12 +326,8 @@ export default {
packageRegistryAccessLevelEnabled() {
return this.glFeatures.packageRegistryAccessLevel;
},
- showAdditonalSettings() {
- if (this.glFeatures.enforceAuthChecksOnUploads) {
- return true;
- }
-
- return this.visibilityLevel !== this.visibilityOptions.PRIVATE;
+ splitOperationsEnabled() {
+ return this.glFeatures.splitOperationsVisibilityPermissions;
},
},
@@ -381,6 +385,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.operationsAccessLevel,
);
+ this.environmentsAccessLevel = Math.min(
+ featureAccessLevel.PROJECT_MEMBERS,
+ this.environmentsAccessLevel,
+ );
this.containerRegistryAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.containerRegistryAccessLevel,
@@ -422,6 +430,8 @@ export default {
this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.operationsAccessLevel = featureAccessLevel.EVERYONE;
+ if (this.environmentsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
+ this.environmentsAccessLevel = featureAccessLevel.EVERYONE;
if (this.containerRegistryAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.containerRegistryAccessLevel = featureAccessLevel.EVERYONE;
@@ -545,7 +555,7 @@ export default {
</template>
</gl-sprintf>
</span>
- <div v-if="showAdditonalSettings" class="gl-mt-4">
+ <div class="gl-mt-4">
<strong class="gl-display-block">{{ s__('ProjectSettings|Additional options') }}</strong>
<label
v-if="visibilityLevel !== visibilityOptions.PRIVATE"
@@ -560,9 +570,7 @@ export default {
{{ s__('ProjectSettings|Users can request access') }}
</label>
<label
- v-if="
- visibilityLevel !== visibilityOptions.PUBLIC && glFeatures.enforceAuthChecksOnUploads
- "
+ v-if="visibilityLevel !== visibilityOptions.PUBLIC"
class="gl-line-height-28 gl-font-weight-normal gl-display-block gl-mb-0"
>
<input
@@ -866,6 +874,20 @@ export default {
/>
</project-setting-row>
</div>
+ <template v-if="splitOperationsEnabled">
+ <project-setting-row
+ ref="environments-settings"
+ :label="$options.i18n.environmentsLabel"
+ :help-text="$options.i18n.environmentsHelpText"
+ >
+ <project-feature-setting
+ v-model="environmentsAccessLevel"
+ :label="$options.i18n.environmentsLabel"
+ :options="featureAccessLevelOptions"
+ name="project[project_feature_attributes][environments_access_level]"
+ />
+ </project-setting-row>
+ </template>
</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/projects/tags/releases/index.js b/app/assets/javascripts/pages/projects/tags/releases/index.js
deleted file mode 100644
index cafd880b4be..00000000000
--- a/app/assets/javascripts/pages/projects/tags/releases/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import $ from 'jquery';
-import GLForm from '~/gl_form';
-import ZenMode from '~/zen_mode';
-
-new ZenMode(); // eslint-disable-line no-new
-new GLForm($('.release-form')); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/registrations/new/index.js b/app/assets/javascripts/pages/registrations/new/index.js
index 94a5c1cb29b..897acf9b02c 100644
--- a/app/assets/javascripts/pages/registrations/new/index.js
+++ b/app/assets/javascripts/pages/registrations/new/index.js
@@ -3,12 +3,17 @@ import { trackNewRegistrations } from '~/google_tag_manager';
import NoEmojiValidator from '~/emoji/no_emoji_validator';
import LengthValidator from '~/pages/sessions/new/length_validator';
import UsernameValidator from '~/pages/sessions/new/username_validator';
+import EmailFormatValidator from '~/pages/sessions/new/email_format_validator';
import Tracking from '~/tracking';
new UsernameValidator(); // eslint-disable-line no-new
new LengthValidator(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
+if (gon.features.trialEmailValidation) {
+ new EmailFormatValidator(); // eslint-disable-line no-new
+}
+
trackNewRegistrations();
Tracking.enableFormTracking({
diff --git a/app/assets/javascripts/pages/sessions/new/email_format_validator.js b/app/assets/javascripts/pages/sessions/new/email_format_validator.js
new file mode 100644
index 00000000000..6dcf3b50dca
--- /dev/null
+++ b/app/assets/javascripts/pages/sessions/new/email_format_validator.js
@@ -0,0 +1,46 @@
+import InputValidator from '~/validators/input_validator';
+
+// It checks if email contains at least one character, number or whatever except
+// another "@" or whitespace before "@", at least two characters except
+// another "@" or whitespace after "@" and one dot in between
+const emailRegexPattern = /[^@\s]+@[^@\s]+\.[^@\s]+/;
+const hintMessageSelector = '.validation-hint';
+const warningMessageSelector = '.validation-warning';
+
+export default class EmailFormatValidator extends InputValidator {
+ constructor(opts = {}) {
+ super();
+
+ const container = opts.container || '';
+
+ document
+ .querySelectorAll(`${container} .js-validate-email`)
+ .forEach((element) =>
+ element.addEventListener('keyup', EmailFormatValidator.eventHandler.bind(this)),
+ );
+ }
+
+ static eventHandler(event) {
+ const inputDomElement = event.target;
+
+ EmailFormatValidator.setMessageVisibility(inputDomElement, hintMessageSelector);
+ EmailFormatValidator.setMessageVisibility(inputDomElement, warningMessageSelector);
+ EmailFormatValidator.validateEmailInput(inputDomElement);
+ }
+
+ static validateEmailInput(inputDomElement) {
+ const validEmail = inputDomElement.checkValidity();
+ const validPattern = inputDomElement.value.match(emailRegexPattern);
+
+ EmailFormatValidator.setMessageVisibility(
+ inputDomElement,
+ warningMessageSelector,
+ validEmail && !validPattern,
+ );
+ }
+
+ static setMessageVisibility(inputDomElement, messageSelector, isVisible = false) {
+ const messageElement = inputDomElement.parentElement.querySelector(messageSelector);
+ messageElement.classList.toggle('hide', !isVisible);
+ }
+}
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 3c22844434d..9d7d9e376cf 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -9,6 +9,7 @@ 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';
@@ -81,9 +82,11 @@ export default {
newPage: s__('WikiPage|Create page'),
},
cancel: s__('WikiPage|Cancel'),
- editSourceButtonText: s__('WikiPage|Edit source'),
- editRichTextButtonText: s__('WikiPage|Edit rich text'),
},
+ switchEditingControlOptions: [
+ { text: s__('Wiki Page|Source'), value: 'source' },
+ { text: s__('Wiki Page|Rich text'), value: 'richText' },
+ ],
components: {
GlAlert,
GlIcon,
@@ -94,6 +97,7 @@ export default {
GlSprintf,
GlLink,
GlButton,
+ GlSegmentedControl,
MarkdownField,
LocalStorageSync,
ContentEditor: () =>
@@ -105,14 +109,15 @@ export default {
inject: ['formatOptions', 'pageInfo'],
data() {
return {
+ editingMode: 'source',
title: this.pageInfo.title?.trim() || '',
format: this.pageInfo.format || 'markdown',
content: this.pageInfo.content || '',
- useContentEditor: false,
commitMessage: '',
isDirty: false,
contentEditorRenderFailed: false,
contentEditorEmpty: false,
+ switchEditingControlDisabled: false,
};
},
computed: {
@@ -177,6 +182,9 @@ export default {
isContentEditorActive() {
return this.isMarkdownFormat && this.useContentEditor;
},
+ useContentEditor() {
+ return this.editingMode === 'richText';
+ },
},
mounted() {
this.updateCommitMessage();
@@ -193,16 +201,15 @@ export default {
.then(({ data }) => data.body);
},
- toggleEditingMode() {
- if (this.useContentEditor) {
+ toggleEditingMode(editingMode) {
+ this.editingMode = editingMode;
+ if (!this.useContentEditor && this.contentEditor) {
this.content = this.contentEditor.getSerializedContent();
}
-
- this.useContentEditor = !this.useContentEditor;
},
- setUseContentEditor(value) {
- this.useContentEditor = value;
+ setEditingMode(value) {
+ this.editingMode = value;
},
async handleFormSubmit(e) {
@@ -294,6 +301,14 @@ export default {
},
});
},
+
+ enableSwitchEditingControl() {
+ this.switchEditingControlDisabled = false;
+ },
+
+ disableSwitchEditingControl() {
+ this.switchEditingControlDisabled = true;
+ },
},
};
</script>
@@ -372,20 +387,21 @@ 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-end gl-mb-3">
- <gl-button
+ <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"
- :data-qa-mode="toggleEditingModeButtonText"
- variant="link"
- @click="toggleEditingMode"
- >{{ toggleEditingModeButtonText }}</gl-button
- >
+ class="gl-display-flex"
+ :checked="editingMode"
+ :options="$options.switchEditingControlOptions"
+ :disabled="switchEditingControlDisabled"
+ @input="toggleEditingMode"
+ />
</div>
<local-storage-sync
storage-key="gl-wiki-content-editor-enabled"
- :value="useContentEditor"
- @input="setUseContentEditor"
+ :value="editingMode"
+ @input="setEditingMode"
/>
<markdown-field
v-if="!isContentEditorActive"
@@ -422,6 +438,9 @@ export default {
:uploads-path="pageInfo.uploadsPath"
@initialized="loadInitialContent"
@change="handleContentEditorChange"
+ @loading="disableSwitchEditingControl"
+ @loadingSuccess="enableSwitchEditingControl"
+ @loadingError="enableSwitchEditingControl"
/>
<input id="wiki_content" v-model.trim="content" type="hidden" name="wiki[content]" />
</div>
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
index 7c424088c8b..9cea89f4990 100644
--- a/app/assets/javascripts/persistent_user_callout.js
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -7,11 +7,12 @@ const DEFERRED_LINK_CLASS = 'deferred-link';
export default class PersistentUserCallout {
constructor(container, options = container.dataset) {
- const { dismissEndpoint, featureId, groupId, deferLinks } = options;
+ const { dismissEndpoint, featureId, groupId, namespaceId, deferLinks } = options;
this.container = container;
this.dismissEndpoint = dismissEndpoint;
this.featureId = featureId;
this.groupId = groupId;
+ this.namespaceId = namespaceId;
this.deferLinks = parseBoolean(deferLinks);
this.closeButtons = this.container.querySelectorAll('.js-close');
@@ -56,6 +57,7 @@ export default class PersistentUserCallout {
.post(this.dismissEndpoint, {
feature_name: this.featureId,
group_id: this.groupId,
+ namespace_id: this.namespaceId,
})
.then(() => {
this.container.remove();
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index f836921f5e5..ead512e3574 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -16,6 +16,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-minute-limit-banner',
'.js-submit-license-usage-data-banner',
'.js-project-usage-limitations-callout',
+ '.js-namespace-storage-alert',
];
const initCallouts = () => {
diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
index 1f74e89f90c..0b57433e894 100644
--- a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
+++ b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue
@@ -28,13 +28,13 @@ export default {
GlSprintf,
},
mixins: [Tracking.mixin()],
- inject: ['runnerHelpPagePath'],
methods: {
trackHelpPageClick() {
const { label, actions } = pipelineEditorTrackingOptions;
this.track(actions.helpDrawerLinks.runners, { label });
},
},
+ RUNNER_HELP_URL: 'https://docs.gitlab.com/runner/register/index.html',
};
</script>
<template>
@@ -47,7 +47,7 @@ export default {
<p class="gl-mb-0">
<gl-sprintf :message="$options.i18n.note">
<template #link="{ content }">
- <gl-link :href="runnerHelpPagePath" target="_blank" @click="trackHelpPageClick()">
+ <gl-link :href="$options.RUNNER_HELP_URL" target="_blank" @click="trackHelpPageClick()">
{{ content }}
</gl-link>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue
index 65a2a6b56e4..189690ce2c3 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue
@@ -43,7 +43,9 @@ export default {
</script>
<template>
- <div class="gl-bg-gray-10 gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1">
+ <div
+ class="gl-bg-gray-10 gl-display-flex gl-p-3 gl-gap-3 gl-border-solid gl-border-gray-100 gl-border-1"
+ >
<gl-button
:href="$options.TEMPLATE_REPOSITORY_URL"
size="small"
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
deleted file mode 100644
index f1cf5630fbf..00000000000
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<script>
-import { flatten } from 'lodash';
-import CiLintResults from './ci_lint_results.vue';
-
-export default {
- components: {
- CiLintResults,
- },
- inject: {
- lintHelpPagePath: {
- default: '',
- },
- },
- props: {
- isValid: {
- type: Boolean,
- required: true,
- },
- ciConfig: {
- type: Object,
- required: true,
- },
- },
- computed: {
- stages() {
- return this.ciConfig?.stages || [];
- },
- jobs() {
- const groupedJobs = this.stages.reduce((acc, { groups, name: stageName }) => {
- return acc.concat(
- groups.map(({ jobs }) => {
- return jobs.map((job) => ({
- stage: stageName,
- ...job,
- }));
- }),
- );
- }, []);
-
- return flatten(groupedJobs);
- },
- },
-};
-</script>
-
-<template>
- <ci-lint-results
- :errors="ciConfig.errors"
- :is-valid="isValid"
- :jobs="jobs"
- :lint-help-page-path="lintHelpPagePath"
- />
-</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index 99ee244577e..4941f22230b 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -2,7 +2,6 @@
import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { getParameterValues, setUrlParams, updateHistory } from '~/lib/utils/url_utility';
import {
CREATE_TAB,
@@ -11,7 +10,6 @@ import {
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_VALID,
EDITOR_APP_STATUS_LINT_UNAVAILABLE,
- LINT_TAB,
MERGED_TAB,
TAB_QUERY_PARAM,
TABS_INDEX,
@@ -22,7 +20,6 @@ import {
import getAppStatus from '../graphql/queries/client/app_status.query.graphql';
import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
import CiEditorHeader from './editor/ci_editor_header.vue';
-import CiLint from './lint/ci_lint.vue';
import CiValidate from './validate/ci_validate.vue';
import TextEditor from './editor/text_editor.vue';
import EditorTab from './ui/editor_tab.vue';
@@ -56,7 +53,6 @@ export default {
},
tabConstants: {
CREATE_TAB,
- LINT_TAB,
MERGED_TAB,
VALIDATE_TAB,
VISUALIZE_TAB,
@@ -64,7 +60,6 @@ export default {
components: {
CiConfigMergedPreview,
CiEditorHeader,
- CiLint,
CiValidate,
EditorTab,
GlAlert,
@@ -74,7 +69,6 @@ export default {
TextEditor,
WalkthroughPopover,
},
- mixins: [glFeatureFlagsMixin()],
props: {
ciConfigData: {
type: Object,
@@ -212,7 +206,6 @@ export default {
<pipeline-graph v-else :pipeline-data="ciConfigData" />
</editor-tab>
<editor-tab
- v-if="glFeatures.simulatePipeline"
class="gl-mb-3"
data-testid="validate-tab"
:badge-title="validateTabBadgeTitle"
@@ -222,19 +215,6 @@ export default {
<ci-validate :ci-file-content="ciFileContent" />
</editor-tab>
<editor-tab
- v-else
- class="gl-mb-3"
- :empty-message="$options.i18n.empty.lint"
- :is-empty="isEmpty"
- :is-unavailable="isLintUnavailable"
- :title="$options.i18n.tabLint"
- data-testid="lint-tab"
- @click="setCurrentTab($options.tabConstants.LINT_TAB)"
- >
- <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" />
- <ci-lint v-else :is-valid="isValid" :ci-config="ciConfigData" />
- </editor-tab>
- <editor-tab
class="gl-mb-3"
:empty-message="$options.i18n.empty.merge"
:keep-component-mounted="false"
diff --git a/app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue b/app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue
index 47673119db9..83fcab4b343 100644
--- a/app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue
+++ b/app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue
@@ -11,6 +11,8 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { s__, __ } from '~/locale';
+import Tracking from '~/tracking';
+import { pipelineEditorTrackingOptions } from '../../constants';
import ValidatePipelinePopover from '../popovers/validate_pipeline_popover.vue';
import CiLintResults from '../lint/ci_lint_results.vue';
import getBlobContent from '../../graphql/queries/blob_content.query.graphql';
@@ -70,6 +72,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [Tracking.mixin()],
inject: ['ciConfigPath', 'ciLintPath', 'projectFullPath', 'validateTabIllustrationPath'],
props: {
ciFileContent: {
@@ -110,6 +113,9 @@ export default {
};
},
computed: {
+ canResimulatePipeline() {
+ return this.hasSimulationResults && this.hasCiContentChanged;
+ },
isInitialCiContentLoading() {
return this.$apollo.queries.initialBlobContent.loading;
},
@@ -128,6 +134,10 @@ export default {
variant: this.isValid ? 'success' : 'danger',
};
},
+ trackingAction() {
+ const { actions } = pipelineEditorTrackingOptions;
+ return this.canResimulatePipeline ? actions.resimulatePipeline : actions.simulatePipeline;
+ },
},
watch: {
ciFileContent(value) {
@@ -139,7 +149,12 @@ export default {
cancelSimulation() {
this.state = VALIDATE_TAB_INIT;
},
+ trackSimulation() {
+ const { label } = pipelineEditorTrackingOptions;
+ this.track(this.trackingAction, { label });
+ },
async validateYaml() {
+ this.trackSimulation();
this.state = VALIDATE_TAB_LOADING;
try {
@@ -150,7 +165,7 @@ export default {
} = await this.$apollo.mutate({
mutation: lintCiMutation,
variables: {
- dry_run: true,
+ dry: true,
content: this.yaml,
endpoint: this.ciLintPath,
},
@@ -198,7 +213,7 @@ export default {
:aria-label="$options.i18n.help"
/>
</div>
- <div v-if="hasSimulationResults && hasCiContentChanged">
+ <div v-if="canResimulatePipeline">
<span class="gl-text-gray-400" data-testid="content-status">
{{ $options.i18n.contentChange }}
</span>
@@ -232,6 +247,7 @@ export default {
class="gl-mt-3"
:disabled="isInitialCiContentLoading"
data-testid="simulate-pipeline-button"
+ data-qa-selector="simulate_pipeline_button"
@click="validateYaml"
>
{{ $options.i18n.cta }}
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index 05db0afd15d..dd25c4d433b 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -30,7 +30,6 @@ export const LOAD_FAILURE_UNKNOWN = 'LOAD_FAILURE_UNKNOWN';
export const PIPELINE_FAILURE = 'PIPELINE_FAILURE';
export const CREATE_TAB = 'CREATE_TAB';
-export const LINT_TAB = 'LINT_TAB';
export const MERGED_TAB = 'MERGED_TAB';
export const VALIDATE_TAB = 'VALIDATE_TAB';
export const VISUALIZE_TAB = 'VISUALIZE_TAB';
@@ -38,9 +37,8 @@ export const VISUALIZE_TAB = 'VISUALIZE_TAB';
export const TABS_INDEX = {
[CREATE_TAB]: '0',
[VISUALIZE_TAB]: '1',
- [LINT_TAB]: '2',
- [VALIDATE_TAB]: '3',
- [MERGED_TAB]: '4',
+ [VALIDATE_TAB]: '2',
+ [MERGED_TAB]: '3',
};
export const TAB_QUERY_PARAM = 'tab';
@@ -77,6 +75,8 @@ export const pipelineEditorTrackingOptions = {
[CI_YAML_LINK]: 'visit_help_drawer_link_yaml',
},
openHelpDrawer: 'open_help_drawer',
+ resimulatePipeline: 'resimulate_pipeline',
+ simulatePipeline: 'simulate_pipeline',
},
};
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql
index 5091d63111f..2d42ebb6ac3 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql
@@ -13,7 +13,6 @@ mutation lintCI($endpoint: String, $content: String, $dry: Boolean) {
only {
refs
}
- afterScript
stage
tags
when
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
index 77a3cdf586c..3495ca51283 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
@@ -19,9 +19,7 @@ mutation commitCIFile(
]
}
) {
- __typename
commit {
- __typename
id
sha
}
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 4f5b69107bf..13dad0b2459 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -40,7 +40,6 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectFullPath,
projectPath,
projectNamespace,
- runnerHelpPagePath,
simulatePipelineHelpPagePath,
totalBranches,
validateTabIllustrationPath,
@@ -132,7 +131,6 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
projectFullPath,
projectPath,
projectNamespace,
- runnerHelpPagePath,
simulatePipelineHelpPagePath,
totalBranches: parseInt(totalBranches, 10),
validateTabIllustrationPath,
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 d84fc724d38..9378b67b915 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -3,10 +3,11 @@ import {
GlAlert,
GlIcon,
GlButton,
+ GlDropdown,
+ GlDropdownItem,
GlForm,
GlFormGroup,
GlFormInput,
- GlFormSelect,
GlFormTextarea,
GlLink,
GlSprintf,
@@ -43,10 +44,10 @@ const i18n = {
};
export default {
- typeOptions: [
- { value: VARIABLE_TYPE, text: __('Variable') },
- { value: FILE_TYPE, text: __('File') },
- ],
+ typeOptions: {
+ [VARIABLE_TYPE]: __('Variable'),
+ [FILE_TYPE]: __('File'),
+ },
i18n,
formElementClasses: 'gl-mr-3 gl-mb-3 gl-flex-basis-quarter gl-flex-shrink-0 gl-flex-grow-0',
// this height value is used inline on the textarea to match the input field height
@@ -56,10 +57,11 @@ export default {
GlAlert,
GlIcon,
GlButton,
+ GlDropdown,
+ GlDropdownItem,
GlForm,
GlFormGroup,
GlFormInput,
- GlFormSelect,
GlFormTextarea,
GlLink,
GlSprintf,
@@ -202,6 +204,11 @@ export default {
});
}
},
+ setVariableType(key, type) {
+ const { variables } = this.form[this.refFullName];
+ const variable = variables.find((v) => v.key === key);
+ variable.variable_type = type;
+ },
setVariableParams(refValue, type, paramsObj) {
Object.entries(paramsObj).forEach(([key, value]) => {
this.setVariable(refValue, type, key, value);
@@ -401,12 +408,19 @@ export default {
<div
class="gl-display-flex gl-align-items-stretch gl-flex-direction-column gl-md-flex-direction-row"
>
- <gl-form-select
- v-model="variable.variable_type"
+ <gl-dropdown
+ :text="$options.typeOptions[variable.variable_type]"
:class="$options.formElementClasses"
- :options="$options.typeOptions"
data-testid="pipeline-form-ci-variable-type"
- />
+ >
+ <gl-dropdown-item
+ v-for="type in Object.keys($options.typeOptions)"
+ :key="type"
+ @click="setVariableType(variable.key, type)"
+ >
+ {{ $options.typeOptions[type] }}
+ </gl-dropdown-item>
+ </gl-dropdown>
<gl-form-input
v-model="variable.key"
:placeholder="s__('CiVariables|Input variable key')"
diff --git a/app/assets/javascripts/pipeline_schedules/components/take_ownership_modal.vue b/app/assets/javascripts/pipeline_schedules/components/take_ownership_modal.vue
new file mode 100644
index 00000000000..7ded3945a32
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/take_ownership_modal.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ ownershipUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ modalId: 'pipeline-take-ownership-modal',
+ i18n: {
+ takeOwnership: s__('PipelineSchedules|Take ownership'),
+ ownershipMessage: s__(
+ 'PipelineSchedules|Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?',
+ ),
+ cancelLabel: __('Cancel'),
+ },
+ computed: {
+ actionCancel() {
+ return { text: this.$options.i18n.cancelLabel };
+ },
+ actionPrimary() {
+ return {
+ text: this.$options.i18n.takeOwnership,
+ attributes: [
+ {
+ variant: 'confirm',
+ category: 'primary',
+ href: this.ownershipUrl,
+ 'data-method': 'post',
+ },
+ ],
+ };
+ },
+ },
+};
+</script>
+<template>
+ <gl-modal
+ :modal-id="$options.modalId"
+ :action-primary="actionPrimary"
+ :action-cancel="actionCancel"
+ :title="$options.i18n.takeOwnership"
+ >
+ <p>{{ $options.i18n.ownershipMessage }}</p>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/pipeline_wizard/components/widgets/checklist.vue b/app/assets/javascripts/pipeline_wizard/components/widgets/checklist.vue
index f2b159acfee..4ba5c237311 100644
--- a/app/assets/javascripts/pipeline_wizard/components/widgets/checklist.vue
+++ b/app/assets/javascripts/pipeline_wizard/components/widgets/checklist.vue
@@ -32,6 +32,11 @@ export default {
required: false,
default: false,
},
+ id: {
+ type: String,
+ required: false,
+ default: () => uniqueId('checklist_'),
+ },
},
computed: {
checklistItems() {
@@ -62,8 +67,8 @@ export default {
</script>
<template>
- <gl-form-group #default="{ ariaDescribedby }" :label="title">
- <gl-form-checkbox-group :aria-describedby="ariaDescribedby" @input="updateValidState">
+ <gl-form-group :label="title" :label-for="id">
+ <gl-form-checkbox-group :id="id" :label="title" @input="updateValidState">
<gl-form-checkbox
v-for="item in checklistItems"
:id="item.id"
diff --git a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue
index 939702fd1b5..79b1507ad0e 100644
--- a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue
+++ b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue
@@ -49,7 +49,7 @@ export default {
<template>
<div>
<div class="gl-my-8">
- <h2 class="gl-mb-4" data-testid="title">{{ title }}</h2>
+ <h1 class="gl-mb-4" data-testid="title">{{ title }}</h1>
<p class="text-tertiary gl-font-lg gl-max-w-80" data-testid="description">
{{ description }}
</p>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index 795ba91a164..8d764fad0c5 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -46,6 +46,9 @@ export default {
const { name, status } = this.group;
return `${name} - ${status.label}`;
},
+ jobGroupClasses() {
+ return [this.cssClassJobName, `job-${this.group.status.group}`];
+ },
},
errorCaptured(err, _vm, info) {
reportToSentry('job_group_dropdown', `error: ${err}, info: ${info}`);
@@ -68,7 +71,7 @@ export default {
type="button"
data-toggle="dropdown"
data-display="static"
- :class="cssClassJobName"
+ :class="jobGroupClasses"
class="dropdown-menu-toggle gl-pipeline-job-width! gl-pr-4!"
>
<div class="gl-display-flex gl-align-items-stretch gl-justify-content-space-between">
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 362571930d6..377f21b299f 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -200,6 +200,9 @@ export default {
},
{ 'gl-rounded-lg': this.isBridge },
this.cssClassJobName,
+ {
+ [`job-${this.status.group}`]: this.isSingleItem,
+ },
];
},
},
diff --git a/app/assets/javascripts/pipelines/components/performance_insights_modal.vue b/app/assets/javascripts/pipelines/components/performance_insights_modal.vue
index ae6b9186930..fdbf0ca19bc 100644
--- a/app/assets/javascripts/pipelines/components/performance_insights_modal.vue
+++ b/app/assets/javascripts/pipelines/components/performance_insights_modal.vue
@@ -97,13 +97,16 @@ export default {
<gl-loading-icon v-if="$apollo.queries.jobs.loading" size="lg" />
<template v-else>
- <gl-alert v-if="showLimitMessage" class="gl-mb-4" :dismissible="false">
- <p>{{ $options.i18n.insightsLimit }}</p>
+ <gl-alert class="gl-mb-4" :dismissible="false">
+ <p v-if="showLimitMessage" data-testid="limit-alert-text">
+ {{ $options.i18n.insightsLimit }}
+ </p>
<gl-link href="https://gitlab.com/gitlab-org/gitlab/-/issues/365902" class="gl-mt-5">
{{ $options.i18n.feeback }}
</gl-link>
</gl-alert>
- <div class="gl-display-flex gl-justify-content-space-between gl-mb-7">
+
+ <div class="gl-display-flex gl-justify-content-space-between gl-mt-2 gl-mb-7">
<gl-card class="gl-w-half gl-mr-7 gl-text-center">
<template #header>
<span class="gl-font-weight-bold">{{ $options.i18n.queuedCardHeader }}</span>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_tabs.vue b/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
index e1745969649..df59962569e 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_tabs.vue
@@ -34,7 +34,13 @@ export default {
PipelineGraphWrapper,
TestReports,
},
- inject: ['defaultTabValue', 'failedJobsCount', 'failedJobsSummary', 'totalJobCount'],
+ inject: [
+ 'defaultTabValue',
+ 'failedJobsCount',
+ 'failedJobsSummary',
+ 'totalJobCount',
+ 'testsCount',
+ ],
computed: {
showFailedJobsTab() {
return this.failedJobsCount > 0;
@@ -81,11 +87,11 @@ export default {
</template>
<failed-jobs-app :failed-jobs-summary="failedJobsSummary" />
</gl-tab>
- <gl-tab
- :title="$options.i18n.tabs.testsTitle"
- :active="isActive($options.tabNames.tests)"
- data-testid="tests-tab"
- >
+ <gl-tab :active="isActive($options.tabNames.tests)" data-testid="tests-tab" lazy>
+ <template #title>
+ <span class="gl-mr-2">{{ $options.i18n.tabs.testsTitle }}</span>
+ <gl-badge size="sm" data-testid="tests-counter">{{ testsCount }}</gl-badge>
+ </template>
<test-reports />
</gl-tab>
<slot></slot>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
index 64d4414eb94..439dc0eb253 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/empty_state/ci_templates.vue
@@ -32,9 +32,10 @@ export default {
.map(({ name, logo, title }) => {
return {
name: title || name,
+ description: sprintf(this.$options.i18n.description, { name: title || name }),
+ isPng: logo.endsWith('png'),
logo,
link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
- description: sprintf(this.$options.i18n.description, { name: title || name }),
};
});
@@ -48,6 +49,9 @@ export default {
label: template,
});
},
+ logoStyle(template) {
+ return template.isPng ? { objectFit: 'contain' } : '';
+ },
},
i18n: {
description: s__(
@@ -66,11 +70,13 @@ export default {
>
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center">
<gl-avatar
- :src="template.logo"
- :size="48"
+ :alt="template.name"
class="gl-mr-5 gl-bg-white dark-mode-override"
+ :class="{ 'gl-p-2': template.isPng }"
+ :style="logoStyle(template)"
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
- :alt="template.name"
+ :size="48"
+ :src="template.logo"
data-testid="template-logo"
/>
<div class="gl-flex-direction-row">
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 9725e882d5e..05a1ceface3 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
@@ -3,16 +3,16 @@ import {
GlAlert,
GlDropdown,
GlDropdownItem,
- GlDropdownSectionHeader,
+ GlSearchBoxByType,
GlLoadingIcon,
GlTooltipDirective,
} from '@gitlab/ui';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
import axios from '~/lib/utils/axios_utils';
import { __, s__ } from '~/locale';
export const i18n = {
- artifacts: __('Artifacts'),
- artifactSectionHeader: __('Download artifacts'),
+ downloadArtifacts: __('Download artifacts'),
artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
emptyArtifactsMessage: __('No artifacts found'),
};
@@ -26,7 +26,7 @@ export default {
GlAlert,
GlDropdown,
GlDropdownItem,
- GlDropdownSectionHeader,
+ GlSearchBoxByType,
GlLoadingIcon,
},
inject: {
@@ -48,8 +48,16 @@ export default {
artifacts: [],
hasError: false,
isLoading: false,
+ searchQuery: '',
};
},
+ computed: {
+ filteredArtifacts() {
+ return this.searchQuery.length > 0
+ ? fuzzaldrinPlus.filter(this.artifacts, this.searchQuery, { key: 'name' })
+ : this.artifacts;
+ },
+ },
methods: {
fetchArtifacts() {
this.isLoading = true;
@@ -70,27 +78,27 @@ export default {
this.isLoading = false;
});
},
+ handleDropdownShown() {
+ this.$refs.searchInput.focusInput();
+ },
},
};
</script>
<template>
<gl-dropdown
v-gl-tooltip
- :title="$options.i18n.artifacts"
- :text="$options.i18n.artifacts"
- :aria-label="$options.i18n.artifacts"
- icon="ellipsis_v"
+ :title="$options.i18n.downloadArtifacts"
+ :text="$options.i18n.downloadArtifacts"
+ :aria-label="$options.i18n.downloadArtifacts"
+ :header-text="$options.i18n.downloadArtifacts"
+ icon="download"
data-testid="pipeline-multi-actions-dropdown"
right
lazy
text-sr-only
- no-caret
@show.once="fetchArtifacts"
+ @shown="handleDropdownShown"
>
- <gl-dropdown-section-header>{{
- $options.i18n.artifactSectionHeader
- }}</gl-dropdown-section-header>
-
<gl-alert v-if="hasError" variant="danger" :dismissible="false">
{{ $options.i18n.artifactsFetchErrorMessage }}
</gl-alert>
@@ -101,8 +109,12 @@ export default {
{{ $options.i18n.emptyArtifactsMessage }}
</gl-dropdown-item>
+ <template #header>
+ <gl-search-box-by-type v-if="artifacts.length" ref="searchInput" v-model.trim="searchQuery" />
+ </template>
+
<gl-dropdown-item
- v-for="(artifact, i) in artifacts"
+ v-for="(artifact, i) in filteredArtifacts"
:key="i"
:href="artifact.path"
rel="nofollow"
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
index 3fb46a4f128..e5666f7a658 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
@@ -1,6 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import createTestReportsStore from '../../stores/test_reports';
import EmptyState from './empty_state.vue';
import TestSuiteTable from './test_suite_table.vue';
@@ -16,6 +17,7 @@ export default {
TestSummary,
TestSummaryTable,
},
+ mixins: [glFeatureFlagMixin()],
inject: ['blobPath', 'summaryEndpoint', 'suiteEndpoint'],
computed: {
...mapState('testReports', ['isLoading', 'selectedSuiteIndex', 'testReports']),
@@ -29,14 +31,16 @@ export default {
},
},
created() {
- this.$store.registerModule(
- 'testReports',
- createTestReportsStore({
- blobPath: this.blobPath,
- summaryEndpoint: this.summaryEndpoint,
- suiteEndpoint: this.suiteEndpoint,
- }),
- );
+ if (!this.glFeatures.pipelineTabsVue) {
+ this.$store.registerModule(
+ 'testReports',
+ createTestReportsStore({
+ blobPath: this.blobPath,
+ summaryEndpoint: this.summaryEndpoint,
+ suiteEndpoint: this.suiteEndpoint,
+ }),
+ );
+ }
this.fetchSummary();
},
@@ -74,7 +78,7 @@ export default {
<div
v-else-if="!isLoading && showTests"
ref="container"
- class="position-relative"
+ class="gl-relative"
data-testid="tests-detail"
>
<transition
@@ -82,13 +86,13 @@ export default {
@before-enter="beforeEnterTransition"
@after-leave="afterLeaveTransition"
>
- <div v-if="showSuite" key="detail" class="w-100 slide-enter-to-element">
+ <div v-if="showSuite" key="detail" class="gl-w-full slide-enter-to-element">
<test-summary :report="getSelectedSuite" show-back @on-back-click="summaryBackClick" />
<test-suite-table />
</div>
- <div v-else key="summary" class="w-100 slide-enter-from-element">
+ <div v-else key="summary" class="gl-w-full slide-enter-from-element">
<test-summary :report="testReports" />
<test-summary-table @row-click="summaryTableRowClick" />
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
index 1f438c63fee..7d0f1ba4b5f 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
@@ -80,7 +80,10 @@ export default {
<h4>{{ heading }}</h4>
</div>
</div>
- <div role="row" class="gl-responsive-table-row table-row-header font-weight-bold fgray">
+ <div
+ role="row"
+ class="gl-responsive-table-row table-row-header gl-font-weight-bold gl-fill-gray-700"
+ >
<div role="rowheader" class="table-section section-20">
{{ __('Suite') }}
</div>
@@ -104,7 +107,7 @@ export default {
<div
v-for="(testCase, index) in getSuiteTests"
:key="index"
- class="gl-responsive-table-row rounded align-items-md-start"
+ class="gl-responsive-table-row gl-rounded-base gl-align-items-flex-start"
data-testid="test-case-row"
>
<div class="table-section section-20 section-wrap">
@@ -142,11 +145,8 @@ export default {
<div class="table-section section-10 section-wrap">
<div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
- <div class="table-mobile-content text-center">
- <div
- class="ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
- :class="`ci-status-icon-${testCase.status}`"
- >
+ <div class="table-mobile-content gl-md-display-flex gl-justify-content-center">
+ <div class="ci-status-icon" :class="`ci-status-icon-${testCase.status}`">
<gl-icon :size="24" :name="testCase.icon" />
</div>
</div>
@@ -156,7 +156,7 @@ export default {
<div role="rowheader" class="table-mobile-header">
{{ __('Duration') }}
</div>
- <div class="table-mobile-content pr-sm-1">
+ <div class="table-mobile-content gl-sm-pr-2">
{{ testCase.formattedTime }}
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
index 2f5301715c3..6b723ad5481 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
@@ -65,58 +65,53 @@ export default {
<template>
<div>
- <div class="row">
- <div class="col-12 d-flex gl-mt-3 align-items-center">
- <gl-button
- v-if="showBack"
- size="small"
- class="gl-mr-3 js-back-button"
- icon="chevron-lg-left"
- :aria-label="__('Go back')"
- @click="onBackClick"
- />
+ <div class="gl-w-full gl-display-flex gl-mt-3 gl-align-items-center">
+ <gl-button
+ v-if="showBack"
+ size="small"
+ class="gl-mr-3 js-back-button"
+ icon="chevron-lg-left"
+ :aria-label="__('Go back')"
+ @click="onBackClick"
+ />
- <h4>{{ heading }}</h4>
- </div>
+ <h4>{{ heading }}</h4>
</div>
- <div class="row mt-2">
- <div class="col-4 col-md">
- <span class="js-total-tests">{{
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-w-full gl-mt-3"
+ >
+ <div class="gl-display-flex gl-justify-content-space-between gl-flex-basis-half">
+ <span class="js-total-tests gl-flex-grow-1">{{
sprintf(s__('TestReports|%{count} tests'), { count: report.total_count })
}}</span>
- </div>
- <div class="col-4 col-md text-center text-md-center">
- <span class="js-failed-tests">{{
+ <span class="js-failed-tests gl-flex-grow-1">{{
sprintf(s__('TestReports|%{count} failures'), { count: report.failed_count })
}}</span>
- </div>
- <div class="col-4 col-md text-right text-md-center">
<span class="js-errored-tests">{{
sprintf(s__('TestReports|%{count} errors'), { count: report.error_count })
}}</span>
</div>
-
- <div class="col-6 mt-3 col-md mt-md-0 text-md-center">
- <span class="js-success-rate">{{
+ <div class="gl-display-flex gl-justify-content-space-between gl-flex-grow-1">
+ <div class="gl-display-none gl-md-display-block gl-flex-grow-1"></div>
+ <span class="js-success-rate gl-flex-grow-1">{{
sprintf(s__('TestReports|%{rate}%{sign} success rate'), {
rate: successPercentage,
sign: '%',
})
}}</span>
- </div>
- <div class="col-6 mt-3 col-md mt-md-0 text-right">
<span class="js-duration">{{ formattedDuration }}</span>
</div>
</div>
- <div class="row mt-3">
- <div class="col-12">
- <gl-progress-bar :value="successPercentage" :variant="progressBarVariant" height="10px" />
- </div>
- </div>
+ <gl-progress-bar
+ class="gl-mt-5"
+ :value="successPercentage"
+ :variant="progressBarVariant"
+ height="10px"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
index 8389c2a5104..7ab48da1a9d 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
@@ -34,33 +34,31 @@ export default {
<template>
<div>
- <div class="row gl-mt-3">
- <div class="col-12">
- <h4>{{ heading }}</h4>
- </div>
+ <div class="gl-mt-5">
+ <h4>{{ heading }}</h4>
</div>
- <div v-if="hasSuites" class="test-reports-table gl-mb-3 js-test-suites-table">
- <div role="row" class="gl-responsive-table-row table-row-header font-weight-bold">
- <div role="rowheader" class="table-section section-25 pl-3">
+ <div v-if="hasSuites" class="js-test-suites-table">
+ <div role="row" class="gl-responsive-table-row table-row-header gl-font-weight-bold">
+ <div role="rowheader" class="table-section section-25 gl-pl-5">
{{ __('Job') }}
</div>
<div role="rowheader" class="table-section section-25">
{{ __('Duration') }}
</div>
- <div role="rowheader" class="table-section section-10 text-center">
+ <div role="rowheader" class="table-section section-10 gl-text-center">
{{ __('Failed') }}
</div>
- <div role="rowheader" class="table-section section-10 text-center">
+ <div role="rowheader" class="table-section section-10 gl-text-center">
{{ __('Errors'), }}
</div>
- <div role="rowheader" class="table-section section-10 text-center">
+ <div role="rowheader" class="table-section section-10 gl-text-center">
{{ __('Skipped'), }}
</div>
- <div role="rowheader" class="table-section section-10 text-center">
+ <div role="rowheader" class="table-section section-10 gl-text-center">
{{ __('Passed'), }}
</div>
- <div role="rowheader" class="table-section section-10 pr-3 text-right">
+ <div role="rowheader" class="table-section section-10 gl-pr-5 gl-text-right">
{{ __('Total') }}
</div>
</div>
@@ -69,17 +67,17 @@ export default {
v-for="(testSuite, index) in getTestSuites"
:key="index"
role="row"
- class="gl-responsive-table-row test-reports-summary-row rounded js-suite-row"
+ class="gl-responsive-table-row gl-rounded-base js-suite-row"
:class="{
- 'gl-responsive-table-row-clickable cursor-pointer': !testSuite.suite_error,
+ 'gl-responsive-table-row-clickable gl-cursor-pointer': !testSuite.suite_error,
}"
@click="tableRowClick(index)"
>
<div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Suite') }}
</div>
- <div class="table-mobile-content underline cgray pl-3">
+ <div class="table-mobile-content underline gl-text-gray-900 gl-pl-5">
{{ testSuite.name }}
<gl-icon
v-if="testSuite.suite_error"
@@ -93,44 +91,44 @@ export default {
</div>
<div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Duration') }}
</div>
- <div class="table-mobile-content text-md-left">
+ <div class="table-mobile-content gl-text-left">
{{ testSuite.formattedTime }}
</div>
</div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div class="table-section section-10 gl-text-center">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Failed') }}
</div>
<div class="table-mobile-content">{{ testSuite.failed_count }}</div>
</div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div class="table-section section-10 gl-text-center">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Errors') }}
</div>
<div class="table-mobile-content">{{ testSuite.error_count }}</div>
</div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div class="table-section section-10 gl-text-center">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Skipped') }}
</div>
<div class="table-mobile-content">{{ testSuite.skipped_count }}</div>
</div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div class="table-section section-10 gl-text-center">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Passed') }}
</div>
<div class="table-mobile-content">{{ testSuite.success_count }}</div>
</div>
- <div class="table-section section-10 text-right pr-md-3">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
+ <div class="table-section section-10 gl-text-right pr-md-3">
+ <div role="rowheader" class="table-mobile-header gl-font-weight-bold">
{{ __('Total') }}
</div>
<div class="table-mobile-content">{{ testSuite.total_count }}</div>
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 2e825016c91..7b38f870cb6 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -83,7 +83,7 @@ export const PipelineKeyOptions = [
export const TOAST_MESSAGE = s__('Pipeline|Creating pipeline.');
-export const BUTTON_TOOLTIP_RETRY = __('Retry failed jobs');
+export const BUTTON_TOOLTIP_RETRY = __('Retry all failed or cancelled jobs');
export const BUTTON_TOOLTIP_CANCEL = __('Cancel');
export const DEFAULT_FIELDS = [
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
index c4f7665c91d..e8e49cc652e 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines_mixin.js
@@ -1,5 +1,6 @@
import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
+import createFlash, { 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';
import Poll from '~/lib/utils/poll';
@@ -198,18 +199,20 @@ export default {
})
.catch((e) => {
const unauthorized = e.response.status === httpStatusCodes.UNAUTHORIZED;
- const badRequest = e.response.status === httpStatusCodes.BAD_REQUEST;
-
let errorMessage = __(
'An error occurred while trying to run a new pipeline for this merge request.',
);
- if (unauthorized || badRequest) {
+ if (unauthorized) {
errorMessage = __('You do not have permission to run a pipeline on this branch.');
}
- createFlash({
+ createAlert({
message: errorMessage,
+ primaryButton: {
+ text: __('Learn more'),
+ link: helpPagePath('ci/pipelines/merge_request_pipelines.md'),
+ },
});
})
.finally(() => this.store.toggleIsRunningPipeline(false));
diff --git a/app/assets/javascripts/pipelines/pipeline_tabs.js b/app/assets/javascripts/pipelines/pipeline_tabs.js
index c0e769e2485..7051d356089 100644
--- a/app/assets/javascripts/pipelines/pipeline_tabs.js
+++ b/app/assets/javascripts/pipelines/pipeline_tabs.js
@@ -5,6 +5,7 @@ import PipelineTabs from 'ee_else_ce/pipelines/components/pipeline_tabs.vue';
import { removeParams, updateHistory } from '~/lib/utils/url_utility';
import { TAB_QUERY_PARAM } from '~/pipelines/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
+import createTestReportsStore from './stores/test_reports';
import { getPipelineDefaultTab, reportToSentry } from './utils';
Vue.use(VueApollo);
@@ -29,6 +30,17 @@ export const createAppOptions = (selector, apolloProvider) => {
pipelineIid,
pipelineProjectPath,
totalJobCount,
+ licenseManagementApiUrl,
+ licenseManagementSettingsPath,
+ licensesApiPath,
+ canManageLicenses,
+ summaryEndpoint,
+ suiteEndpoint,
+ blobPath,
+ hasTestReport,
+ emptyStateImagePath,
+ artifactsExpiredImagePath,
+ testsCount,
} = dataset;
const defaultTabValue = getPipelineDefaultTab(window.location.href);
@@ -39,7 +51,15 @@ export const createAppOptions = (selector, apolloProvider) => {
PipelineTabs,
},
apolloProvider,
- store: new Vuex.Store(),
+ store: new Vuex.Store({
+ modules: {
+ testReports: createTestReportsStore({
+ blobPath,
+ summaryEndpoint,
+ suiteEndpoint,
+ }),
+ },
+ }),
provide: {
canGenerateCodequalityReports: parseBoolean(canGenerateCodequalityReports),
codequalityReportDownloadPath,
@@ -54,6 +74,17 @@ export const createAppOptions = (selector, apolloProvider) => {
pipelineIid,
pipelineProjectPath,
totalJobCount,
+ licenseManagementApiUrl,
+ licenseManagementSettingsPath,
+ licensesApiPath,
+ canManageLicenses: parseBoolean(canManageLicenses),
+ summaryEndpoint,
+ suiteEndpoint,
+ blobPath,
+ hasTestReport,
+ emptyStateImagePath,
+ artifactsExpiredImagePath,
+ testsCount,
},
errorCaptured(err, _vm, info) {
reportToSentry('pipeline_tabs', `error: ${err}, info: ${info}`);
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/actions.js b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
index f0556f3d12e..b785fd1753c 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/actions.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/actions.js
@@ -30,7 +30,6 @@ export const fetchTestSuite = ({ state, commit, dispatch }, index) => {
dispatch('toggleLoading');
- // eslint-disable-next-line camelcase
const { build_ids = [] } = state.testReports?.test_suites?.[index] || {};
// Replacing `/:suite_name.json` with the name of the suite. Including the extra characters
// to ensure that we replace exactly the template part of the URL string
diff --git a/app/assets/javascripts/projects/compare/components/app.vue b/app/assets/javascripts/projects/compare/components/app.vue
index bda58091b97..4ba7156b026 100644
--- a/app/assets/javascripts/projects/compare/components/app.vue
+++ b/app/assets/javascripts/projects/compare/components/app.vue
@@ -15,7 +15,11 @@ export default {
type: String,
required: true,
},
- refsProjectPath: {
+ sourceProjectRefsPath: {
+ type: String,
+ required: true,
+ },
+ targetProjectRefsPath: {
type: String,
required: true,
},
@@ -37,7 +41,11 @@ export default {
type: String,
required: true,
},
- defaultProject: {
+ sourceProject: {
+ type: Object,
+ required: true,
+ },
+ targetProject: {
type: Object,
required: true,
},
@@ -50,14 +58,14 @@ export default {
return {
from: {
projects: this.projects,
- selectedProject: this.defaultProject,
+ selectedProject: this.targetProject,
revision: this.paramsFrom,
- refsProjectPath: this.refsProjectPath,
+ refsProjectPath: this.targetProjectRefsPath,
},
to: {
- selectedProject: this.defaultProject,
+ selectedProject: this.sourceProject,
revision: this.paramsTo,
- refsProjectPath: this.refsProjectPath,
+ refsProjectPath: this.sourceProjectRefsPath,
},
};
},
diff --git a/app/assets/javascripts/projects/compare/index.js b/app/assets/javascripts/projects/compare/index.js
index e485a086d39..074b8565c3c 100644
--- a/app/assets/javascripts/projects/compare/index.js
+++ b/app/assets/javascripts/projects/compare/index.js
@@ -5,13 +5,15 @@ export default function init() {
const el = document.getElementById('js-compare-selector');
const {
- refsProjectPath,
+ sourceProjectRefsPath,
+ targetProjectRefsPath,
paramsFrom,
paramsTo,
projectCompareIndexPath,
projectMergeRequestPath,
createMrPath,
- projectTo,
+ sourceProject,
+ targetProject,
projectsFrom,
} = el.dataset;
@@ -23,13 +25,15 @@ export default function init() {
render(createElement) {
return createElement(CompareApp, {
props: {
- refsProjectPath,
+ sourceProjectRefsPath,
+ targetProjectRefsPath,
paramsFrom,
paramsTo,
projectCompareIndexPath,
projectMergeRequestPath,
createMrPath,
- defaultProject: JSON.parse(projectTo),
+ sourceProject: JSON.parse(sourceProject),
+ targetProject: JSON.parse(targetProject),
projects: JSON.parse(projectsFrom),
},
});
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 28b77f6defd..0cfea401be6 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -17,6 +17,7 @@ const mountPipelineChartsApp = (el) => {
coverageChartPath,
defaultBranch,
testRunsEmptyStateImagePath,
+ projectQualitySummaryFeedbackImagePath,
} = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
@@ -37,6 +38,7 @@ const mountPipelineChartsApp = (el) => {
coverageChartPath,
defaultBranch,
testRunsEmptyStateImagePath,
+ projectQualitySummaryFeedbackImagePath,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index fe84660422b..424ea3b61c5 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import { debounce } from 'lodash';
import DEFAULT_PROJECT_TEMPLATES from 'any_else_ce/projects/default_project_templates';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
+import Tracking from '~/tracking';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../lib/utils/constants';
import { ENTER_KEY } from '../lib/utils/keys';
import axios from '../lib/utils/axios_utils';
@@ -109,8 +110,31 @@ const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
);
};
+ const projectPathValueListener = () => {
+ // eslint-disable-next-line no-param-reassign
+ $projectPathInput.oldInputValue = $projectPathInput.value;
+ };
+
+ const projectPathTrackListener = () => {
+ if ($projectPathInput.oldInputValue === $projectPathInput.value) {
+ // no change made to the input
+ return;
+ }
+
+ const trackEvent = 'user_input_path_slug';
+ const trackCategory = undefined; // will be default set in event method
+
+ Tracking.event(trackCategory, trackEvent, {
+ label: 'new_project_form',
+ });
+ };
+
$projectPathInput.removeEventListener('keyup', projectPathInputListener);
$projectPathInput.addEventListener('keyup', projectPathInputListener);
+ $projectPathInput.removeEventListener('focus', projectPathValueListener);
+ $projectPathInput.addEventListener('focus', projectPathValueListener);
+ $projectPathInput.removeEventListener('blur', projectPathTrackListener);
+ $projectPathInput.addEventListener('blur', projectPathTrackListener);
$projectPathInput.removeEventListener('change', projectPathInputListener);
$projectPathInput.addEventListener('change', projectPathInputListener);
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
index 6bbe0ab7d5f..6ba2ef7da99 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue
@@ -1,12 +1,24 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlSearchBoxByType,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
import { createAlert } from '~/flash';
-import { __, sprintf } from '~/locale';
+import { s__, sprintf } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
import branchesQuery from '../queries/branches.query.graphql';
export const i18n = {
- fetchBranchesError: __('An error occurred while fetching branches.'),
- noMatch: __('No matching results'),
+ 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 {
@@ -17,6 +29,8 @@ export default {
GlDropdownItem,
GlDropdownDivider,
GlSearchBoxByType,
+ GlSprintf,
+ GlLink,
},
apollo: {
branchNames: {
@@ -39,6 +53,10 @@ export default {
},
},
},
+ searchInputDelay: 250,
+ wildcardsHelpPath: helpPagePath('user/project/protected_branches', {
+ anchor: 'configure-multiple-protected-branches-by-using-a-wildcard',
+ }),
props: {
projectPath: {
type: String,
@@ -58,7 +76,9 @@ export default {
},
computed: {
createButtonLabel() {
- return sprintf(__('Create wildcard: %{searchTerm}'), { searchTerm: this.searchTerm });
+ return sprintf(this.$options.i18n.wildCardSearchHelp, {
+ searchTerm: this.searchTerm,
+ });
},
shouldRenderCreateButton() {
return this.searchTerm && !this.branchNames.includes(this.searchTerm);
@@ -81,30 +101,37 @@ export default {
};
</script>
<template>
- <gl-dropdown :text="value || branchNames[0]">
- <gl-search-box-by-type
- v-model.trim="searchTerm"
- data-testid="branch-search"
- debounce="250"
- :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 }}
+ <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>
- </template>
- </gl-dropdown>
+ <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/protections/index.vue b/app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue
new file mode 100644
index 00000000000..bcc0f64d667
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/protections/index.vue
@@ -0,0 +1,59 @@
+<script>
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import PushProtections from './push_protections.vue';
+import MergeProtections from './merge_protections.vue';
+
+export const i18n = {
+ protections: s__('BranchRules|Protections'),
+ protectionsHelpText: s__(
+ 'BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}',
+ ),
+};
+
+export default {
+ name: 'BranchProtections',
+ i18n,
+ components: {
+ GlSprintf,
+ GlLink,
+ PushProtections,
+ MergeProtections,
+ },
+ protectedBranchesHelpPath: helpPagePath('user/project/protected_branches'),
+ props: {
+ protections: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h4 class="gl-border-t gl-pt-4">{{ $options.i18n.protections }}</h4>
+
+ <div data-testid="protections-help-text">
+ <gl-sprintf :message="$options.i18n.protectionsHelpText">
+ <template #link="{ content }">
+ <gl-link :href="$options.protectedBranchesHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </div>
+
+ <push-protections
+ class="gl-mt-5"
+ :members-allowed-to-push="protections.membersAllowedToPush"
+ :allow-force-push="protections.allowForcePush"
+ v-on="$listeners"
+ />
+
+ <merge-protections
+ :members-allowed-to-merge="protections.membersAllowedToMerge"
+ :require-code-owners-approval="protections.requireCodeOwnersApproval"
+ v-on="$listeners"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue b/app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue
new file mode 100644
index 00000000000..85f168af4a8
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/protections/merge_protections.vue
@@ -0,0 +1,46 @@
+<script>
+import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
+import { s__ } from '~/locale';
+
+export const i18n = {
+ allowedToMerge: s__('BranchRules|Allowed to merge'),
+ requireApprovalTitle: s__('BranchRules|Require approval from code owners.'),
+ requireApprovalHelpText: s__(
+ 'BranchRules|Reject code pushes that change files listed in the CODEOWNERS file.',
+ ),
+};
+
+export default {
+ name: 'BranchMergeProtections',
+ i18n,
+ components: {
+ GlFormGroup,
+ GlFormCheckbox,
+ },
+ props: {
+ membersAllowedToMerge: {
+ type: Array,
+ required: true,
+ },
+ requireCodeOwnersApproval: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group :label="$options.i18n.allowedToMerge">
+ <!-- TODO: add multi-select-dropdown (https://gitlab.com/gitlab-org/gitlab/-/issues/362212) -->
+
+ <gl-form-checkbox
+ class="gl-mt-5"
+ :checked="requireCodeOwnersApproval"
+ @change="$emit('change-require-code-owners-approval', $event)"
+ >
+ <span>{{ $options.i18n.requireApprovalTitle }}</span>
+ <template #help>{{ $options.i18n.requireApprovalHelpText }}</template>
+ </gl-form-checkbox>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue b/app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue
new file mode 100644
index 00000000000..541923bb735
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/protections/push_protections.vue
@@ -0,0 +1,52 @@
+<script>
+import { GlFormGroup, GlSprintf, GlLink, GlFormCheckbox } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export const i18n = {
+ allowedToPush: s__('BranchRules|Allowed to push'),
+ forcePushTitle: s__(
+ 'BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}.',
+ ),
+};
+
+export default {
+ name: 'BranchPushProtections',
+ i18n,
+ components: {
+ GlFormGroup,
+ GlSprintf,
+ GlLink,
+ GlFormCheckbox,
+ },
+ forcePushHelpPath: helpPagePath('topics/git/git_rebase', { anchor: 'force-push' }),
+ props: {
+ membersAllowedToPush: {
+ type: Array,
+ required: true,
+ },
+ allowForcePush: {
+ type: Boolean,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group :label="$options.i18n.allowedToPush">
+ <!-- TODO: add multi-select-dropdown (https://gitlab.com/gitlab-org/gitlab/-/issues/362212) -->
+
+ <gl-form-checkbox
+ class="gl-mt-5"
+ :checked="allowForcePush"
+ @change="$emit('change-allow-force-push', $event)"
+ >
+ <gl-sprintf :message="$options.i18n.forcePushTitle">
+ <template #link="{ content }">
+ <gl-link :href="$options.forcePushHelpPath">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-form-checkbox>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
index c2e7f4e9b1b..ad3eb7d2899 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue
@@ -1,15 +1,18 @@
<script>
import { GlFormGroup } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { s__ } from '~/locale';
import { getParameterByName } from '~/lib/utils/url_utility';
import BranchDropdown from './branch_dropdown.vue';
+import Protections from './protections/index.vue';
export default {
name: 'RuleEdit',
- i18n: {
- branch: __('Branch'),
+ i18n: { branch: s__('BranchRules|Branch') },
+ components: {
+ BranchDropdown,
+ GlFormGroup,
+ Protections,
},
- components: { BranchDropdown, GlFormGroup },
props: {
projectPath: {
type: String,
@@ -19,20 +22,35 @@ export default {
data() {
return {
branch: getParameterByName('branch'),
+ protections: {
+ membersAllowedToPush: [],
+ allowForcePush: false,
+ membersAllowedToMerge: [],
+ requireCodeOwnersApproval: false,
+ },
};
},
};
</script>
<template>
- <gl-form-group :label="$options.i18n.branch">
- <branch-dropdown
- id="branches"
- v-model="branch"
- class="gl-w-half"
- :project-path="projectPath"
- @createWildcard="branch = $event"
+ <div>
+ <gl-form-group :label="$options.i18n.branch">
+ <branch-dropdown
+ id="branches"
+ v-model="branch"
+ class="gl-w-half"
+ :project-path="projectPath"
+ @createWildcard="branch = $event"
+ />
+ </gl-form-group>
+
+ <protections
+ :protections="protections"
+ @change-allowed-to-push-members="protections.membersAllowedToPush = $event"
+ @change-allow-force-push="protections.allowForcePush = $event"
+ @change-allowed-to-merge-members="protections.membersAllowedToMerge = $event"
+ @change-require-code-owners-approval="protections.requireCodeOwnersApproval = $event"
/>
- </gl-form-group>
- <!-- TODO - Add branch protections (https://gitlab.com/gitlab-org/gitlab/-/issues/362212) -->
+ </div>
</template>
diff --git a/app/assets/javascripts/projects/settings/components/access_dropdown.vue b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
index fcf81c9d1f7..2209172c06d 100644
--- a/app/assets/javascripts/projects/settings/components/access_dropdown.vue
+++ b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
@@ -262,8 +262,8 @@ export default {
const selectedUsers = this.preselectedItems
.filter(({ type }) => type === LEVEL_TYPES.USER)
- .map(({ user_id, name, username, avatar_url, type }) => ({
- id: user_id,
+ .map(({ user_id: id, name, username, avatar_url, type }) => ({
+ id,
name,
username,
avatar_url,
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 fe968e74c6d..c13753da00b 100644
--- a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
+++ b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
@@ -1,7 +1,13 @@
<script>
import { GlFormGroup } from '@gitlab/ui';
-import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import produce from 'immer';
import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import { getIdFromGraphQLId } from '~/graphql_shared/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;
export default {
name: 'TransferProjectForm',
@@ -11,14 +17,6 @@ export default {
ConfirmDanger,
},
props: {
- groupNamespaces: {
- type: Array,
- required: true,
- },
- userNamespaces: {
- type: Array,
- required: true,
- },
confirmationPhrase: {
type: String,
required: true,
@@ -28,19 +26,88 @@ 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 { selectedNamespace: null };
+ return {
+ currentUser: {},
+ selectedNamespace: null,
+ isLoadingMoreGroups: false,
+ isSearchLoading: false,
+ searchTerm: '',
+ };
},
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;
+ },
},
methods: {
handleSelect(selectedNamespace) {
this.selectedNamespace = selectedNamespace;
this.$emit('selectNamespace', selectedNamespace.id);
},
+ handleLoadMoreGroups() {
+ this.isLoadingMoreGroups = true;
+
+ this.$apollo.queries.currentUser.fetchMore({
+ variables: {
+ after: this.currentUser.groups.pageInfo.endCursor,
+ first: GROUPS_PER_PAGE,
+ },
+ updateQuery(
+ previousResult,
+ {
+ fetchMoreResult: {
+ currentUser: { groups: newGroups },
+ },
+ },
+ ) {
+ const previousGroups = previousResult.currentUser.groups;
+
+ return produce(previousResult, (draftData) => {
+ draftData.currentUser.groups.nodes = [...previousGroups.nodes, ...newGroups.nodes];
+ draftData.currentUser.groups.pageInfo = newGroups.pageInfo;
+ });
+ },
+ });
+ },
+ handleSearch(searchTerm) {
+ this.isSearchLoading = true;
+ this.searchTerm = searchTerm;
+ },
+ formatNamespace({ id, fullName }) {
+ return {
+ id: getIdFromGraphQLId(id),
+ humanName: fullName,
+ };
+ },
},
};
</script>
@@ -53,11 +120,16 @@ export default {
:group-namespaces="groupNamespaces"
:user-namespaces="userNamespaces"
:selected-namespace="selectedNamespace"
+ :has-next-page-of-groups="hasNextPageOfGroups"
+ :is-loading-more-groups="isLoadingMoreGroups"
+ :is-search-loading="isSearchLoading"
+ :should-filter-namespaces="false"
@select="handleSelect"
+ @load-more-groups="handleLoadMoreGroups"
+ @search="handleSearch"
/>
</gl-form-group>
<confirm-danger
- button-class="qa-transfer-button"
:disabled="!hasSelectedNamespace"
:phrase="confirmationPhrase"
:button-text="confirmButtonText"
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
new file mode 100644
index 00000000000..d4bcb8c869c
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/graphql/queries/search_namespaces_where_user_can_transfer_projects.query.graphql
@@ -0,0 +1,24 @@
+#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 a5f720bffaa..bc1aff640d2 100644
--- a/app/assets/javascripts/projects/settings/init_transfer_project_form.js
+++ b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
@@ -1,36 +1,29 @@
import Vue from 'vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
import TransferProjectForm from './components/transfer_project_form.vue';
-const prepareNamespaces = (rawNamespaces = '') => {
- if (!rawNamespaces) {
- return { groupNamespaces: [], userNamespaces: [] };
- }
-
- const data = JSON.parse(rawNamespaces);
- return {
- groupNamespaces: data?.group?.map(convertObjectPropsToCamelCase) || [],
- userNamespaces: data?.user?.map(convertObjectPropsToCamelCase) || [],
- };
-};
-
export default () => {
const el = document.querySelector('.js-transfer-project-form');
if (!el) {
return false;
}
+ Vue.use(VueApollo);
+
const {
targetFormId = null,
targetHiddenInputId = null,
buttonText: confirmButtonText = '',
phrase: confirmationPhrase = '',
confirmDangerMessage = '',
- namespaces = '',
} = el.dataset;
return new Vue({
el,
+ apolloProvider: new VueApollo({
+ defaultClient: createDefaultClient(),
+ }),
provide: {
confirmDangerMessage,
},
@@ -39,7 +32,6 @@ export default () => {
props: {
confirmButtonText,
confirmationPhrase,
- ...prepareNamespaces(namespaces),
},
on: {
selectNamespace: (id) => {
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index d02526160fd..1343ad8246c 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -256,6 +256,7 @@ export default {
:error-message="i18n.branchesErrorMessage"
:show-header="showSectionHeaders"
data-testid="branches-section"
+ data-qa-selector="branches_section"
@selected="selectRef($event)"
/>
diff --git a/app/assets/javascripts/related_issues/components/add_issuable_form.vue b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
index d765033d00b..102f1228355 100644
--- a/app/assets/javascripts/related_issues/components/add_issuable_form.vue
+++ b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
@@ -208,7 +208,7 @@ export default {
<p v-if="hasError" class="gl-field-error">
{{ addRelatedErrorMessage }}
</p>
- <div class="gl-mt-5 gl-clearfix">
+ <div class="gl-mt-5">
<gl-button
ref="addButton"
category="primary"
@@ -216,12 +216,13 @@ export default {
:disabled="isSubmitButtonDisabled"
:loading="isSubmitting"
type="submit"
- class="gl-float-left"
+ size="small"
+ class="gl-mr-2"
data-qa-selector="add_issue_button"
>
{{ __('Add') }}
</gl-button>
- <gl-button class="gl-float-right" @click="onFormCancel">
+ <gl-button size="small" @click="onFormCancel">
{{ __('Cancel') }}
</gl-button>
</div>
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 eeb4c254a1b..5b4a6d1fe0d 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -1,5 +1,6 @@
<script>
import { GlLink, GlIcon, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
import {
issuableIconMap,
issuableQaClassMap,
@@ -96,6 +97,11 @@ export default {
default: true,
},
},
+ data() {
+ return {
+ isOpen: true,
+ };
+ },
computed: {
hasRelatedIssues() {
return this.relatedIssues.length > 0;
@@ -139,6 +145,21 @@ export default {
qaClass() {
return issuableQaClassMap[this.issuableType];
},
+ toggleIcon() {
+ return this.isOpen ? 'chevron-lg-up' : 'chevron-lg-down';
+ },
+ toggleLabel() {
+ return this.isOpen ? __('Collapse') : __('Expand');
+ },
+ },
+ methods: {
+ handleToggle() {
+ this.isOpen = !this.isOpen;
+ },
+ addButtonClick(event) {
+ this.isOpen = true;
+ this.$emit('toggleAddRelatedIssuesForm', event);
+ },
},
linkedIssueTypesTextMap,
};
@@ -148,12 +169,10 @@ export default {
<div id="related-issues" class="related-issues-block gl-mt-5">
<div class="card card-slim gl-overflow-hidden">
<div
- :class="{ 'panel-empty-heading border-bottom-0': !hasBody }"
- class="card-header gl-display-flex gl-justify-content-space-between"
+ :class="{ 'panel-empty-heading border-bottom-0': !hasBody, 'gl-border-b-0': !isOpen }"
+ class="gl-display-flex gl-justify-content-space-between gl-line-height-24 gl-py-3 gl-px-5 gl-bg-gray-10 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
>
- <h3
- class="card-title h5 position-relative gl-my-0 gl-display-flex gl-align-items-center gl-h-7"
- >
+ <h3 class="card-title h5 gl-my-0 gl-display-flex gl-align-items-center gl-flex-grow-1">
<gl-link
id="user-content-related-issues"
class="anchor position-absolute gl-text-decoration-none"
@@ -172,30 +191,45 @@ export default {
<gl-icon name="question" :size="12" />
</gl-link>
- <div class="gl-display-inline-flex">
- <div class="js-related-issues-header-issue-count gl-display-inline-flex gl-mx-5">
- <span class="gl-display-inline-flex gl-align-items-center">
- <gl-icon :name="issuableTypeIcon" class="gl-mr-2 gl-text-gray-500" />
- {{ badgeLabel }}
- </span>
- </div>
- <gl-button
- v-if="canAdmin"
- data-qa-selector="related_issues_plus_button"
- icon="plus"
- :aria-label="addIssuableButtonText"
- :class="qaClass"
- @click="$emit('toggleAddRelatedIssuesForm', $event)"
- />
+ <div class="js-related-issues-header-issue-count gl-display-inline-flex gl-mx-3">
+ <span class="gl-display-inline-flex gl-align-items-center">
+ <gl-icon :name="issuableTypeIcon" class="gl-mr-2 gl-text-gray-500" />
+ {{ badgeLabel }}
+ </span>
</div>
</h3>
<slot name="header-actions"></slot>
+ <gl-button
+ v-if="canAdmin"
+ size="small"
+ data-qa-selector="related_issues_plus_button"
+ data-testid="related-issues-plus-button"
+ :aria-label="addIssuableButtonText"
+ :class="qaClass"
+ class="gl-ml-3"
+ @click="addButtonClick"
+ >
+ <slot name="add-button-text">{{ __('Add') }}</slot>
+ </gl-button>
+ <div class="gl-pl-3 gl-ml-3 gl-border-l-1 gl-border-l-solid gl-border-l-gray-100">
+ <gl-button
+ category="tertiary"
+ size="small"
+ :icon="toggleIcon"
+ :aria-label="toggleLabel"
+ :disabled="!hasRelatedIssues"
+ data-testid="toggle-links"
+ @click="handleToggle"
+ />
+ </div>
</div>
<div
- class="linked-issues-card-body bg-gray-light"
+ v-if="isOpen"
+ class="linked-issues-card-body gl-bg-gray-10"
:class="{
'gl-p-5': isFormVisible || shouldShowTokenBody,
}"
+ data-testid="related-issues-body"
>
<div
v-if="isFormVisible"
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue
index 9ed895e90fb..11de734f5d4 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_list.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue
@@ -5,7 +5,6 @@ import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue
import { defaultSortableOptions } from '~/sortable/constants';
export default {
- name: 'RelatedIssuesList',
components: {
GlLoadingIcon,
RelatedIssuableItem,
@@ -141,6 +140,7 @@ export default {
:path-id-separator="pathIdSeparator"
:is-locked="issue.lockIssueRemoval"
:locked-message="issue.lockedMessage"
+ :work-item-type="issue.type"
event-namespace="relatedIssue"
data-qa-selector="related_issuable_content"
@relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $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 da049d68467..cad5037d7e4 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_root.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -24,6 +24,7 @@ Your caret can stop touching a `rawReference` can happen in a variety of ways:
*/
import createFlash from '~/flash';
+import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import {
relatedIssuesRemoveErrorMap,
@@ -123,6 +124,14 @@ export default {
return this.state.relatedIssues.find((issue) => issue.id === id);
},
onRelatedIssueRemoveRequest(idToRemove) {
+ if (isGid(idToRemove)) {
+ const deletedId = getIdFromGraphQLId(idToRemove);
+ this.state.relatedIssues = this.state.relatedIssues.filter(
+ (issue) => issue.id !== deletedId,
+ );
+ return;
+ }
+
const issueToRemove = this.findRelatedIssueById(idToRemove);
if (issueToRemove) {
diff --git a/app/assets/javascripts/related_issues/constants.js b/app/assets/javascripts/related_issues/constants.js
index 3516836952f..23ea93cd258 100644
--- a/app/assets/javascripts/related_issues/constants.js
+++ b/app/assets/javascripts/related_issues/constants.js
@@ -114,8 +114,8 @@ export const PathIdSeparator = {
};
export const issuablesBlockHeaderTextMap = {
- [issuableTypesMap.ISSUE]: __('Linked issues'),
- [issuableTypesMap.INCIDENT]: __('Related incidents or issues'),
+ [issuableTypesMap.ISSUE]: __('Linked items'),
+ [issuableTypesMap.INCIDENT]: __('Linked incidents or issues'),
[issuableTypesMap.EPIC]: __('Linked epics'),
};
@@ -136,7 +136,7 @@ export const issuablesFormCategoryHeaderTextMap = {
};
export const issuablesFormInputTextMap = {
- [issuableTypesMap.ISSUE]: __('the following issue(s)'),
- [issuableTypesMap.INCIDENT]: __('the following incident(s) or issue(s)'),
- [issuableTypesMap.EPIC]: __('the following epic(s)'),
+ [issuableTypesMap.ISSUE]: __('the following issues'),
+ [issuableTypesMap.INCIDENT]: __('the following incidents or issues'),
+ [issuableTypesMap.EPIC]: __('the following epics'),
};
diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js
index 655ec57bc3d..eb2f5d119b8 100644
--- a/app/assets/javascripts/related_issues/index.js
+++ b/app/assets/javascripts/related_issues/index.js
@@ -1,30 +1,33 @@
import Vue from 'vue';
+import apolloProvider from '~/issues/show/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import RelatedIssuesRoot from './components/related_issues_root.vue';
-export default function initRelatedIssues(issueType = 'issue') {
- const relatedIssuesRootElement = document.querySelector('.js-related-issues-root');
- if (relatedIssuesRootElement) {
- // eslint-disable-next-line no-new
- new Vue({
- el: relatedIssuesRootElement,
- name: 'RelatedIssuesRoot',
- components: {
- relatedIssuesRoot: RelatedIssuesRoot,
- },
- render: (createElement) =>
- createElement('related-issues-root', {
- props: {
- endpoint: relatedIssuesRootElement.dataset.endpoint,
- canAdmin: parseBoolean(relatedIssuesRootElement.dataset.canAddRelatedIssues),
- helpPath: relatedIssuesRootElement.dataset.helpPath,
- showCategorizedIssues: parseBoolean(
- relatedIssuesRootElement.dataset.showCategorizedIssues,
- ),
- issuableType: issueType,
- autoCompleteEpics: false,
- },
- }),
- });
+export function initRelatedIssues(issueType = 'issue') {
+ const el = document.querySelector('.js-related-issues-root');
+
+ if (!el) {
+ return null;
}
+
+ return new Vue({
+ el,
+ name: 'RelatedIssuesRoot',
+ apolloProvider,
+ provide: {
+ fullPath: el.dataset.fullPath,
+ hasIssueWeightsFeature: parseBoolean(el.dataset.hasIssueWeightsFeature),
+ },
+ render: (createElement) =>
+ createElement(RelatedIssuesRoot, {
+ props: {
+ endpoint: el.dataset.endpoint,
+ canAdmin: parseBoolean(el.dataset.canAddRelatedIssues),
+ helpPath: el.dataset.helpPath,
+ showCategorizedIssues: parseBoolean(el.dataset.showCategorizedIssues),
+ issuableType: issueType,
+ autoCompleteEpics: false,
+ },
+ }),
+ });
}
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index 022c3224bb4..dd3f4ed636f 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -128,8 +128,13 @@ export default {
async mounted() {
await this.initializeRelease();
- // Focus the first non-disabled input or button element
- this.$el.querySelector('input:enabled, button:enabled').focus();
+ if (this.release?.tagName) {
+ // Focus the release title input if a tag was preselected
+ this.$refs.releaseTitleInput.$el.focus();
+ } else {
+ // Focus the first non-disabled input or button element otherwise
+ this.$el.querySelector('input:enabled, button:enabled').focus();
+ }
},
methods: {
...mapActions('editNew', [
diff --git a/app/assets/javascripts/releases/components/asset_links_form.vue b/app/assets/javascripts/releases/components/asset_links_form.vue
index b81da399a7b..7c6d44456d9 100644
--- a/app/assets/javascripts/releases/components/asset_links_form.vue
+++ b/app/assets/javascripts/releases/components/asset_links_form.vue
@@ -209,7 +209,7 @@ export default {
:id="`asset-type-${index}`"
ref="typeSelect"
:value="link.linkType || $options.defaultTypeOptionValue"
- class="form-control pr-4"
+ class="pr-4"
name="asset-type"
:options="$options.typeOptions"
@change="updateAssetLinkType({ linkIdToUpdate: link.id, newType: $event })"
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index def38780545..070865cf84b 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -7,6 +7,10 @@ import { BACK_URL_PARAM } from '~/releases/constants';
export default {
i18n: {
editButton: __('Edit this release'),
+ historical: __('Historical release'),
+ historicalTooltip: __(
+ 'This release was created with a date in the past. Evidence collection at the moment of the release is unavailable.',
+ ),
},
name: 'ReleaseBlockHeader',
components: {
@@ -65,6 +69,14 @@ export default {
<gl-badge v-if="release.upcomingRelease" variant="warning" class="align-middle">{{
__('Upcoming Release')
}}</gl-badge>
+ <gl-badge
+ v-else-if="release.historicalRelease"
+ v-gl-tooltip
+ :title="$options.i18n.historicalTooltip"
+ class="gl-vertical-align-middle"
+ >
+ {{ $options.i18n.historical }}
+ </gl-badge>
</h2>
<gl-button
v-if="editLink"
diff --git a/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql b/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
index e0de6d12b13..e22726f27a7 100644
--- a/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
+++ b/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
@@ -1,5 +1,4 @@
fragment Release on Release {
- __typename
id
name
tagName
@@ -8,21 +7,17 @@ fragment Release on Release {
releasedAt
createdAt
upcomingRelease
+ historicalRelease
assets {
- __typename
count
sources {
- __typename
nodes {
- __typename
format
url
}
}
links {
- __typename
nodes {
- __typename
id
name
url
@@ -33,9 +28,7 @@ fragment Release on Release {
}
}
evidences {
- __typename
nodes {
- __typename
id
filepath
collectedAt
@@ -43,7 +36,6 @@ fragment Release on Release {
}
}
links {
- __typename
editUrl
selfUrl
openedIssuesUrl
@@ -53,29 +45,24 @@ fragment Release on Release {
closedMergeRequestsUrl
}
commit {
- __typename
id
sha
webUrl
title
}
author {
- __typename
id
webUrl
avatarUrl
username
}
milestones {
- __typename
nodes {
- __typename
id
title
description
webPath
stats {
- __typename
totalIssuesCount
closedIssuesCount
}
diff --git a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
index 61a06f268bd..1e3d31c86bf 100644
--- a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
+++ b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
@@ -1,3 +1,5 @@
+#import "../fragments/release.fragment.graphql"
+
query allReleases(
$fullPath: ID!
$first: Int
@@ -7,96 +9,12 @@ query allReleases(
$sort: ReleaseSort
) {
project(fullPath: $fullPath) {
- __typename
id
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
- __typename
nodes {
- __typename
- id
- name
- tagName
- tagPath
- descriptionHtml
- releasedAt
- createdAt
- upcomingRelease
- assets {
- __typename
- count
- sources {
- __typename
- nodes {
- __typename
- format
- url
- }
- }
- links {
- __typename
- nodes {
- __typename
- id
- name
- url
- directAssetUrl
- linkType
- external
- }
- }
- }
- evidences {
- __typename
- nodes {
- __typename
- id
- filepath
- collectedAt
- sha
- }
- }
- links {
- __typename
- editUrl
- selfUrl
- openedIssuesUrl
- closedIssuesUrl
- openedMergeRequestsUrl
- mergedMergeRequestsUrl
- closedMergeRequestsUrl
- }
- commit {
- __typename
- id
- sha
- webUrl
- title
- }
- author {
- __typename
- id
- webUrl
- avatarUrl
- username
- }
- milestones {
- __typename
- nodes {
- __typename
- id
- title
- description
- webPath
- stats {
- __typename
- totalIssuesCount
- closedIssuesCount
- }
- }
- }
+ ...Release
}
pageInfo {
- __typename
startCursor
hasPreviousPage
hasNextPage
diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js
index f1f5f4bca4c..a1027ef08d7 100644
--- a/app/assets/javascripts/releases/util.js
+++ b/app/assets/javascripts/releases/util.js
@@ -12,6 +12,7 @@ const convertScalarProperties = (graphQLRelease) =>
'description',
'descriptionHtml',
'upcomingRelease',
+ 'historicalRelease',
]);
const convertDateProperties = ({ releasedAt }) => ({
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index 0714d88b392..6061be465ca 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -206,7 +206,6 @@ export default {
<gl-button
v-if="isCollapsible"
- class="js-collapse-btn"
data-testid="report-section-expand-button"
data-qa-selector="expand_report_button"
@click="toggleCollapsed"
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index bf4f19504f0..7999b916e0f 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -8,7 +8,7 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo, getLocationHash } from '~/lib/utils/url_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import CodeIntelligence from '~/code_navigation/components/app.vue';
@@ -63,6 +63,28 @@ export default {
};
},
result() {
+ const urlHash = getLocationHash();
+ const plain = this.$route?.query?.plain;
+
+ // When the 'plain' URL param is present, its value determines which viewer to render:
+ // - when 0 and the rich viewer is available we render with it
+ // - otherwise we render the simple viewer
+ if (plain !== undefined) {
+ if (plain === '0' && this.hasRichViewer) {
+ this.switchViewer(RICH_BLOB_VIEWER);
+ } else {
+ this.switchViewer(SIMPLE_BLOB_VIEWER);
+ }
+ return;
+ }
+
+ // If there is a code line hash in the URL we render with the simple viewer
+ if (urlHash && urlHash.startsWith('L')) {
+ this.switchViewer(SIMPLE_BLOB_VIEWER);
+ return;
+ }
+
+ // By default, if present, use the rich viewer to render
this.switchViewer(this.hasRichViewer ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER);
},
error() {
@@ -173,6 +195,21 @@ export default {
return this.blobInfo.storedExternally && this.blobInfo.externalStorage === LFS_STORAGE;
},
},
+ watch: {
+ // Watch the URL 'plain' query value to know if the viewer needs changing.
+ // This is the case when the user switches the viewer and then goes back
+ // through the hystory.
+ '$route.query.plain': {
+ handler(plainValue) {
+ this.switchViewer(
+ this.hasRichViewer && (plainValue === undefined || plainValue === '0')
+ ? RICH_BLOB_VIEWER
+ : SIMPLE_BLOB_VIEWER,
+ plainValue !== undefined,
+ );
+ },
+ },
+ },
methods: {
onError() {
this.useFallback = true;
@@ -189,15 +226,10 @@ export default {
axios
.get(`${this.blobInfo.webPath}?format=json&viewer=${type}`)
.then(async ({ data: { html, binary } }) => {
- if (type === SIMPLE_BLOB_VIEWER) {
- this.isRenderingLegacyTextViewer = true;
+ this.isRenderingLegacyTextViewer = true;
+ if (type === SIMPLE_BLOB_VIEWER) {
this.legacySimpleViewer = html;
-
- window.requestIdleCallback(() => {
- this.isRenderingLegacyTextViewer = false;
- new LineHighlighter(); // eslint-disable-line no-new
- });
} else {
this.legacyRichViewer = html;
}
@@ -205,6 +237,14 @@ export default {
this.isBinary = binary;
this.isLoadingLegacyViewer = false;
+ window.requestIdleCallback(() => {
+ this.isRenderingLegacyTextViewer = false;
+
+ if (type === SIMPLE_BLOB_VIEWER) {
+ new LineHighlighter(); // eslint-disable-line no-new
+ }
+ });
+
await this.$nextTick();
handleLocationHash(); // Ensures that we scroll to the hash when async content is loaded
})
@@ -220,6 +260,22 @@ export default {
this.loadLegacyViewer();
}
},
+ updateRouteQuery() {
+ const plain = this.activeViewerType === SIMPLE_BLOB_VIEWER ? '1' : '0';
+
+ if (this.$route?.query?.plain === plain) {
+ return;
+ }
+
+ this.$router.push({
+ path: this.$route.path,
+ query: { ...this.$route.query, plain },
+ });
+ },
+ handleViewerChanged(newViewer) {
+ this.switchViewer(newViewer);
+ this.updateRouteQuery();
+ },
editBlob(target) {
if (this.showForkSuggestion) {
this.setForkTarget(target);
@@ -251,7 +307,7 @@ export default {
:has-render-error="hasRenderError"
:show-path="false"
:override-copy="glFeatures.highlightJs"
- @viewer-changed="switchViewer"
+ @viewer-changed="handleViewerChanged"
@copy="onCopy"
>
<template #actions>
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 9f2cf8505d3..7f408485326 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -196,12 +196,9 @@ export default {
</gl-link>
</div>
<gl-button-group class="gl-ml-4 js-commit-sha-group">
- <gl-button
- label
- class="gl-font-monospace"
- data-testid="last-commit-id-label"
- v-text="showCommitId"
- />
+ <gl-button label class="gl-font-monospace" data-testid="last-commit-id-label">{{
+ showCommitId
+ }}</gl-button>
<clipboard-button
:text="commit.sha"
:title="__('Copy commit SHA')"
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
index 0e80f306638..77d3a517d28 100644
--- a/app/assets/javascripts/repository/constants.js
+++ b/app/assets/javascripts/repository/constants.js
@@ -94,7 +94,6 @@ export const LFS_STORAGE = 'lfs';
*/
export const LEGACY_FILE_TYPES = [
'gemfile',
- 'gemspec',
'composer_json',
'podfile',
'podspec',
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index 8baee80e5d6..45a7793e559 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -27,6 +27,7 @@ query getBlobInfo(
fileType
language
path
+ blamePath
editBlobPath
gitpodBlobUrl
ideEditPath
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 9de67015094..3256e13f4da 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -3,9 +3,7 @@
import $ from 'jquery';
import { setCookie } from '~/lib/utils/common_utils';
import { hide, fixTitle } from '~/tooltips';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { sprintf, s__, __ } from './locale';
+import { __ } from './locale';
const updateSidebarClasses = (layoutPage, rightSidebar) => {
if (window.innerWidth >= 992) {
@@ -20,7 +18,6 @@ const updateSidebarClasses = (layoutPage, rightSidebar) => {
};
function Sidebar() {
- this.toggleTodo = this.toggleTodo.bind(this);
this.sidebar = $('aside');
this.removeListeners();
@@ -54,7 +51,6 @@ Sidebar.prototype.addEventListeners = function () {
this.sidebar.on('hiddenGlDropdown', this, this.onSidebarDropdownHidden);
$document.on('click', '.js-sidebar-toggle', this.sidebarToggleClicked);
- $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo);
if (window.gon?.features?.movedMrSidebar) {
const layoutPage = document.querySelector('.layout-page');
@@ -105,32 +101,6 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
}
};
-Sidebar.prototype.toggleTodo = function (e) {
- const $this = $(e.currentTarget);
- const ajaxType = $this.data('deletePath') ? 'delete' : 'post';
- const url = String($this.data('deletePath') || $this.data('createPath'));
-
- hide($this);
-
- $('.js-issuable-todo').disable().addClass('is-loading');
-
- axios[ajaxType](url, {
- issuable_id: $this.data('issuableId'),
- issuable_type: $this.data('issuableType'),
- })
- .then(({ data }) => {
- this.todoUpdateDone(data);
- })
- .catch(() =>
- createFlash({
- message: sprintf(__('There was an error %{message} to-do item.'), {
- message:
- ajaxType === 'post' ? s__('RightSidebar|adding a') : s__('RightSidebar|deleting the'),
- }),
- }),
- );
-};
-
Sidebar.prototype.sidebarCollapseClicked = function (e) {
if ($(e.currentTarget).hasClass('js-dont-change-state')) {
return;
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 f6b7a8b46d7..777a332333d 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -12,10 +12,12 @@ import {
isSearchFiltered,
} from 'ee_else_ce/runner/runner_search_utils';
import allRunnersQuery from 'ee_else_ce/runner/graphql/list/all_runners.query.graphql';
+import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_count.query.graphql';
import RegistrationDropdown from '../components/registration/registration_dropdown.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';
@@ -37,6 +39,7 @@ export default {
RegistrationDropdown,
RunnerFilteredSearchBar,
RunnerBulkDelete,
+ RunnerBulkDeleteCheckbox,
RunnerList,
RunnerListEmptyState,
RunnerName,
@@ -138,11 +141,15 @@ export default {
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.refetchCounts();
this.$root.$toast?.show(message);
},
+ refetchCounts() {
+ this.$apollo.getClient().refetchQueries({ include: [allRunnersCountQuery] });
+ },
reportToSentry(error) {
captureException({ error, component: this.$options.name });
},
@@ -152,6 +159,9 @@ export default {
isChecked,
});
},
+ onPaginationInput(value) {
+ this.search.pagination = value;
+ },
},
filteredSearchNamespace: ADMIN_FILTERED_SEARCH_NAMESPACE,
INSTANCE_TYPE,
@@ -163,7 +173,6 @@ export default {
class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0"
>
<runner-type-tabs
- ref="runner-type-tabs"
v-model="search"
:count-scope="$options.INSTANCE_TYPE"
:count-variables="countVariables"
@@ -196,13 +205,20 @@ export default {
:filtered-svg-path="emptyStateFilteredSvgPath"
/>
<template v-else>
- <runner-bulk-delete v-if="isBulkDeleteEnabled" />
+ <runner-bulk-delete
+ v-if="isBulkDeleteEnabled"
+ :runners="runners.items"
+ @deleted="onDeleted"
+ />
<runner-list
:runners="runners.items"
:loading="runnersLoading"
:checkable="isBulkDeleteEnabled"
@checked="onChecked"
>
+ <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" />
@@ -217,11 +233,13 @@ export default {
/>
</template>
</runner-list>
- <runner-pagination
- v-model="search.pagination"
- class="gl-mt-3"
- :page-info="runners.pageInfo"
- />
</template>
+
+ <runner-pagination
+ class="gl-mt-3"
+ :disabled="runnersLoading"
+ :page-info="runners.pageInfo"
+ @input="onPaginationInput"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
index 1eb383a1904..1cd098d6713 100644
--- a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
@@ -59,7 +59,11 @@ export default {
<tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="description">
{{ description }}
</tooltip-on-truncate>
- <tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="ipAddress">
+ <tooltip-on-truncate
+ v-if="ipAddress"
+ class="gl-display-block gl-text-truncate"
+ :title="ipAddress"
+ >
<span class="gl-md-display-none gl-lg-display-inline">{{ __('IP Address') }}</span>
<strong>{{ ipAddress }}</strong>
</tooltip-on-truncate>
diff --git a/app/assets/javascripts/runner/components/runner_assigned_item.vue b/app/assets/javascripts/runner/components/runner_assigned_item.vue
index 38bdfecb7df..2fa87bdd776 100644
--- a/app/assets/javascripts/runner/components/runner_assigned_item.vue
+++ b/app/assets/javascripts/runner/components/runner_assigned_item.vue
@@ -1,10 +1,11 @@
<script>
-import { GlAvatar, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlBadge, GlLink } from '@gitlab/ui';
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
export default {
components: {
GlAvatar,
+ GlBadge,
GlLink,
},
props: {
@@ -25,6 +26,16 @@ export default {
required: false,
default: null,
},
+ description: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ isOwner: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
AVATAR_SHAPE_OPTION_RECT,
};
@@ -41,7 +52,12 @@ export default {
:size="48"
/>
</gl-link>
-
- <gl-link :href="href" class="gl-font-weight-bold gl-text-gray-900!">{{ fullName }}</gl-link>
+ <div>
+ <div class="gl-mb-1">
+ <gl-link :href="href" class="gl-font-weight-bold gl-text-gray-900!">{{ fullName }}</gl-link>
+ <gl-badge v-if="isOwner" variant="info">{{ s__('Runner|Owner') }}</gl-badge>
+ </div>
+ <div v-if="description">{{ description }}</div>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_bulk_delete.vue b/app/assets/javascripts/runner/components/runner_bulk_delete.vue
index 50791de0bda..703da01d9c8 100644
--- a/app/assets/javascripts/runner/components/runner_bulk_delete.vue
+++ b/app/assets/javascripts/runner/components/runner_bulk_delete.vue
@@ -1,21 +1,31 @@
<script>
-import { GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
-import { n__, sprintf } from '~/locale';
-import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
-import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
+import { GlButton, GlModalDirective, GlModal, GlSprintf } from '@gitlab/ui';
+import { createAlert } from '~/flash';
+import { __, s__, n__, sprintf } from '~/locale';
import checkedRunnerIdsQuery from '../graphql/list/checked_runner_ids.query.graphql';
+import BulkRunnerDelete from '../graphql/list/bulk_runner_delete.mutation.graphql';
+import { RUNNER_TYPENAME } from '../constants';
export default {
components: {
GlButton,
+ GlModal,
GlSprintf,
},
directives: {
GlModal: GlModalDirective,
},
inject: ['localMutations'],
+ props: {
+ runners: {
+ type: Array,
+ default: () => [],
+ required: false,
+ },
+ },
data() {
return {
+ isDeleting: false,
checkedRunnerIds: [],
};
},
@@ -25,8 +35,13 @@ export default {
},
},
computed: {
+ currentCheckedRunnerIds() {
+ return this.runners
+ .map(({ id }) => id)
+ .filter((id) => this.checkedRunnerIds.indexOf(id) >= 0);
+ },
checkedCount() {
- return this.checkedRunnerIds.length || 0;
+ return this.currentCheckedRunnerIds.length || 0;
},
bannerMessage() {
return sprintf(
@@ -43,48 +58,103 @@ export default {
modalTitle() {
return n__('Runners|Delete %d runner', 'Runners|Delete %d runners', this.checkedCount);
},
- modalHtmlMessage() {
+ modalActionPrimary() {
+ return {
+ text: n__(
+ 'Runners|Permanently delete %d runner',
+ 'Runners|Permanently delete %d runners',
+ this.checkedCount,
+ ),
+ attributes: {
+ loading: this.isDeleting,
+ variant: 'danger',
+ },
+ };
+ },
+ modalActionCancel() {
+ return {
+ text: __('Cancel'),
+ attributes: {
+ loading: this.isDeleting,
+ },
+ };
+ },
+ modalMessage() {
return sprintf(
n__(
'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?',
'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?',
this.checkedCount,
),
- {
- strongStart: '<strong>',
- strongEnd: '</strong>',
- count: this.checkedCount,
- },
- false,
+ { count: this.checkedCount },
);
},
- primaryBtnText() {
+ },
+ methods: {
+ toastConfirmationMessage(deletedCount) {
return n__(
- 'Runners|Permanently delete %d runner',
- 'Runners|Permanently delete %d runners',
- this.checkedCount,
+ 'Runners|%d selected runner deleted',
+ 'Runners|%d selected runners deleted',
+ deletedCount,
);
},
- },
- methods: {
onClearChecked() {
this.localMutations.clearChecked();
},
- onClickDelete: ignoreWhilePending(async function onClickDelete() {
- const confirmed = await confirmAction(null, {
- title: this.modalTitle,
- modalHtmlMessage: this.modalHtmlMessage,
- primaryBtnVariant: 'danger',
- primaryBtnText: this.primaryBtnText,
- });
+ async onConfirmDelete(e) {
+ this.isDeleting = true;
+ e.preventDefault(); // don't close modal until deletion is complete
+
+ try {
+ await this.$apollo.mutate({
+ mutation: BulkRunnerDelete,
+ variables: {
+ input: {
+ ids: this.currentCheckedRunnerIds,
+ },
+ },
+ update: (cache, { data }) => {
+ const { errors, deletedIds } = data.bulkRunnerDelete;
+
+ if (errors?.length) {
+ this.onError(new Error(errors.join(' ')));
+ this.$refs.modal.hide();
+ return;
+ }
+
+ this.$emit('deleted', {
+ message: this.toastConfirmationMessage(deletedIds.length),
+ });
- if (confirmed) {
- // TODO Call $apollo.mutate with list of runner
- // ids in `this.checkedRunnerIds`.
- // See https://gitlab.com/gitlab-org/gitlab/-/issues/339525/
+ // Clean up
+
+ // Remove deleted runners from the cache
+ deletedIds.forEach((id) => {
+ const cacheId = cache.identify({ __typename: RUNNER_TYPENAME, id });
+ cache.evict({ id: cacheId });
+ });
+ cache.gc();
+
+ this.$refs.modal.hide();
+ },
+ });
+ } catch (error) {
+ this.onError(error);
+ } finally {
+ this.isDeleting = false;
}
- }),
+ },
+ onError(error) {
+ createAlert({
+ message: s__(
+ 'Runners|Something went wrong while deleting. Please refresh the page to try again.',
+ ),
+ captureError: true,
+ error,
+ });
+ },
},
+ BULK_DELETE_MODAL_ID: 'bulk-delete-modal',
};
</script>
@@ -99,13 +169,28 @@ export default {
</gl-sprintf>
</div>
<div class="gl-ml-auto">
- <gl-button data-testid="clear-btn" variant="default" @click="onClearChecked">{{
+ <gl-button variant="default" @click="onClearChecked">{{
s__('Runners|Clear selection')
}}</gl-button>
- <gl-button data-testid="delete-btn" variant="danger" @click="onClickDelete">{{
+ <gl-button v-gl-modal="$options.BULK_DELETE_MODAL_ID" variant="danger">{{
s__('Runners|Delete selected')
}}</gl-button>
</div>
</div>
+ <gl-modal
+ ref="modal"
+ size="sm"
+ :modal-id="$options.BULK_DELETE_MODAL_ID"
+ :title="modalTitle"
+ :action-primary="modalActionPrimary"
+ :action-cancel="modalActionCancel"
+ @primary="onConfirmDelete"
+ >
+ <gl-sprintf :message="modalMessage">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-modal>
</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
new file mode 100644
index 00000000000..dde5a5a4a05
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_bulk_delete_checkbox.vue
@@ -0,0 +1,59 @@
+<script>
+import { GlFormCheckbox } from '@gitlab/ui';
+import checkedRunnerIdsQuery from '../graphql/list/checked_runner_ids.query.graphql';
+
+export default {
+ components: {
+ GlFormCheckbox,
+ },
+ inject: ['localMutations'],
+ props: {
+ runners: {
+ type: Array,
+ default: () => [],
+ required: false,
+ },
+ },
+ data() {
+ return {
+ checkedRunnerIds: [],
+ };
+ },
+ apollo: {
+ checkedRunnerIds: {
+ query: checkedRunnerIdsQuery,
+ },
+ },
+ computed: {
+ disabled() {
+ return !this.runners.length;
+ },
+ checked() {
+ return Boolean(this.runners.length) && this.runners.every(this.isChecked);
+ },
+ indeterminate() {
+ return !this.checked && this.runners.some(this.isChecked);
+ },
+ },
+ methods: {
+ isChecked({ id }) {
+ return this.checkedRunnerIds.indexOf(id) >= 0;
+ },
+ onChange($event) {
+ this.localMutations.setRunnersChecked({
+ runners: this.runners,
+ isChecked: $event,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-checkbox
+ :indeterminate="indeterminate"
+ :checked="checked"
+ :disabled="disabled"
+ @change="onChange"
+ />
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_detail.vue b/app/assets/javascripts/runner/components/runner_detail.vue
index db67acef3db..584f77b7648 100644
--- a/app/assets/javascripts/runner/components/runner_detail.vue
+++ b/app/assets/javascripts/runner/components/runner_detail.vue
@@ -38,11 +38,10 @@ export default {
</script>
<template>
- <div class="gl-display-flex gl-pb-4">
- <dt class="gl-mr-2">{{ label }}</dt>
- <dd class="gl-mb-0">
- <!-- eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots -->
- <template v-if="value || $slots.value">
+ <div class="gl-display-contents">
+ <dt class="gl-mb-5 gl-mr-6 gl-max-w-26">{{ label }}</dt>
+ <dd class="gl-mb-5">
+ <template v-if="value || $scopedSlots.value">
<slot name="value">{{ value }}</slot>
</template>
<span v-else class="gl-text-gray-500">{{ emptyValue }}</span>
diff --git a/app/assets/javascripts/runner/components/runner_details.vue b/app/assets/javascripts/runner/components/runner_details.vue
index 60469d26dd5..d5222f39b81 100644
--- a/app/assets/javascripts/runner/components/runner_details.vue
+++ b/app/assets/javascripts/runner/components/runner_details.vue
@@ -51,6 +51,9 @@ export default {
}
return null;
},
+ tagList() {
+ return this.runner.tagList || [];
+ },
isGroupRunner() {
return this.runner?.runnerType === GROUP_TYPE;
},
@@ -66,14 +69,17 @@ export default {
<div>
<runner-upgrade-status-alert class="gl-my-4" :runner="runner" />
<div class="gl-pt-4">
- <dl class="gl-mb-0" data-testid="runner-details-list">
+ <dl
+ class="gl-mb-0 gl-display-grid runner-details-grid-template"
+ data-testid="runner-details-list"
+ >
<runner-detail :label="s__('Runners|Description')" :value="runner.description" />
<runner-detail
:label="s__('Runners|Last contact')"
:empty-value="s__('Runners|Never contacted')"
>
- <template #value>
- <time-ago v-if="runner.contactedAt" :time="runner.contactedAt" />
+ <template v-if="runner.contactedAt" #value>
+ <time-ago :time="runner.contactedAt" />
</template>
</runner-detail>
<runner-detail :label="s__('Runners|Version')">
@@ -87,8 +93,8 @@ export default {
<runner-detail :label="s__('Runners|Architecture')" :value="runner.architectureName" />
<runner-detail :label="s__('Runners|Platform')" :value="runner.platformName" />
<runner-detail :label="s__('Runners|Configuration')">
- <template #value>
- <gl-intersperse v-if="configTextProtected || configTextUntagged">
+ <template v-if="configTextProtected || configTextUntagged" #value>
+ <gl-intersperse>
<span v-if="configTextProtected">{{ configTextProtected }}</span>
<span v-if="configTextUntagged">{{ configTextUntagged }}</span>
</gl-intersperse>
@@ -96,13 +102,8 @@ export default {
</runner-detail>
<runner-detail :label="s__('Runners|Maximum job timeout')" :value="maximumTimeout" />
<runner-detail :label="s__('Runners|Tags')">
- <template #value>
- <runner-tags
- v-if="runner.tagList && runner.tagList.length"
- class="gl-vertical-align-middle"
- :tag-list="runner.tagList"
- size="sm"
- />
+ <template v-if="tagList.length" #value>
+ <runner-tags class="gl-vertical-align-middle" :tag-list="tagList" size="sm" />
</template>
</runner-detail>
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 bff5ec9b238..5a9ab21a457 100644
--- a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -64,19 +64,19 @@ export default {
},
methods: {
onFilter(filters) {
- // Apply new filters, from page 1
+ // Apply new filters, resetting pagination
this.$emit('input', {
...this.value,
filters,
- pagination: { page: 1 },
+ pagination: {},
});
},
onSort(sort) {
- // Apply new sort, from page 1
+ // Apply new sort, resetting pagination
this.$emit('input', {
...this.value,
sort,
- pagination: { page: 1 },
+ pagination: {},
});
},
},
diff --git a/app/assets/javascripts/runner/components/runner_jobs.vue b/app/assets/javascripts/runner/components/runner_jobs.vue
index 57afdc4b9be..9003eba3636 100644
--- a/app/assets/javascripts/runner/components/runner_jobs.vue
+++ b/app/assets/javascripts/runner/components/runner_jobs.vue
@@ -27,9 +27,7 @@ export default {
items: [],
pageInfo: {},
},
- pagination: {
- page: 1,
- },
+ pagination: {},
};
},
apollo: {
@@ -62,6 +60,11 @@ export default {
return this.$apollo.queries.jobs.loading;
},
},
+ methods: {
+ onPaginationInput(value) {
+ this.pagination = value;
+ },
+ },
I18N_NO_JOBS_FOUND,
};
</script>
@@ -74,6 +77,6 @@ export default {
<runner-jobs-table v-else-if="jobs.items.length" :jobs="jobs.items" />
<p v-else>{{ $options.I18N_NO_JOBS_FOUND }}</p>
- <runner-pagination v-model="pagination" :disabled="loading" :page-info="jobs.pageInfo" />
+ <runner-pagination :disabled="loading" :page-info="jobs.pageInfo" @input="onPaginationInput" />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index f1f99c728c5..2e406f71792 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTableLite, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
+import { GlFormCheckbox, GlTableLite, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __, s__ } from '~/locale';
@@ -23,6 +23,7 @@ const defaultFields = [
export default {
components: {
+ GlFormCheckbox,
GlTableLite,
GlSkeletonLoader,
TooltipOnTruncate,
@@ -123,19 +124,11 @@ export default {
fixed
>
<template #head(checkbox)>
- <!--
- Checkbox to select all to be added here
- See https://gitlab.com/gitlab-org/gitlab/-/issues/339525/
- -->
- <span></span>
+ <slot name="head-checkbox"></slot>
</template>
<template #cell(checkbox)="{ item }">
- <input
- type="checkbox"
- :checked="isChecked(item)"
- @change="onCheckboxChange(item, $event.target.checked)"
- />
+ <gl-form-checkbox :checked="isChecked(item)" @change="onCheckboxChange(item, $event)" />
</template>
<template #head(status)="{ label }">
diff --git a/app/assets/javascripts/runner/components/runner_pagination.vue b/app/assets/javascripts/runner/components/runner_pagination.vue
index cfc21d1407b..a5bf3074dd1 100644
--- a/app/assets/javascripts/runner/components/runner_pagination.vue
+++ b/app/assets/javascripts/runner/components/runner_pagination.vue
@@ -1,18 +1,12 @@
<script>
-import { GlPagination } from '@gitlab/ui';
+import { GlKeysetPagination } from '@gitlab/ui';
export default {
components: {
- GlPagination,
+ GlKeysetPagination,
},
+ inheritAttrs: false,
props: {
- value: {
- required: false,
- type: Object,
- default: () => ({
- page: 1,
- }),
- },
pageInfo: {
required: false,
type: Object,
@@ -20,46 +14,37 @@ export default {
},
},
computed: {
- prevPage() {
- return this.pageInfo?.hasPreviousPage ? this.value.page - 1 : null;
+ paginationProps() {
+ return { ...this.pageInfo, ...this.$attrs };
},
- nextPage() {
- return this.pageInfo?.hasNextPage ? this.value.page + 1 : null;
+ isShown() {
+ const { hasPreviousPage, hasNextPage } = this.pageInfo;
+ return hasPreviousPage || hasNextPage;
},
},
methods: {
- handlePageChange(page) {
- if (page === 1) {
- // Small optimization for first page
- // If we have loaded using "first",
- // page is already cached.
- this.$emit('input', {
- page,
- });
- } else if (page > this.value.page) {
- this.$emit('input', {
- page,
- after: this.pageInfo.endCursor,
- });
- } else {
- this.$emit('input', {
- page,
- before: this.pageInfo.startCursor,
- });
- }
+ prevPage() {
+ this.$emit('input', {
+ before: this.pageInfo.startCursor,
+ });
+ },
+ nextPage() {
+ this.$emit('input', {
+ after: this.pageInfo.endCursor,
+ });
},
},
};
</script>
<template>
- <gl-pagination
- v-bind="$attrs"
- :value="value.page"
- :prev-page="prevPage"
- :next-page="nextPage"
- align="center"
- class="gl-pagination"
- @input="handlePageChange"
- />
+ <div v-if="isShown" class="gl-text-center">
+ <gl-keyset-pagination
+ v-bind="paginationProps"
+ :prev-text="s__('Pagination|Prev')"
+ :next-text="s__('Pagination|Next')"
+ @prev="prevPage"
+ @next="nextPage"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/runner/components/runner_projects.vue b/app/assets/javascripts/runner/components/runner_projects.vue
index c0c0c14e91e..2c1d2fc2b10 100644
--- a/app/assets/javascripts/runner/components/runner_projects.vue
+++ b/app/assets/javascripts/runner/components/runner_projects.vue
@@ -30,13 +30,12 @@ export default {
data() {
return {
projects: {
+ ownerProjectId: null,
items: [],
pageInfo: {},
count: 0,
},
- pagination: {
- page: 1,
- },
+ pagination: {},
};
},
apollo: {
@@ -48,6 +47,7 @@ export default {
update(data) {
const { runner } = data;
return {
+ ownerProjectId: runner?.ownerProject?.id,
count: runner?.projectCount || 0,
items: runner?.projects?.nodes || [],
pageInfo: runner?.projects?.pageInfo || {},
@@ -76,6 +76,14 @@ export default {
});
},
},
+ methods: {
+ isOwner(projectId) {
+ return projectId === this.projects.ownerProjectId;
+ },
+ onPaginationInput(value) {
+ this.pagination = value;
+ },
+ },
I18N_NONE,
};
</script>
@@ -98,10 +106,16 @@ export default {
:name="project.name"
:full-name="project.nameWithNamespace"
:avatar-url="project.avatarUrl"
+ :description="project.description"
+ :is-owner="isOwner(project.id)"
/>
</template>
<span v-else class="gl-text-gray-500">{{ $options.I18N_NONE }}</span>
- <runner-pagination v-model="pagination" :disabled="loading" :page-info="projects.pageInfo" />
+ <runner-pagination
+ :disabled="loading"
+ :page-info="projects.pageInfo"
+ @input="onPaginationInput"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/stat/runner_count.vue b/app/assets/javascripts/runner/components/stat/runner_count.vue
index af18b203f90..37c6f922f9a 100644
--- a/app/assets/javascripts/runner/components/stat/runner_count.vue
+++ b/app/assets/javascripts/runner/components/stat/runner_count.vue
@@ -1,8 +1,9 @@
<script>
import { fetchPolicies } from '~/lib/graphql';
+import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_count.query.graphql';
+import groupRunnersCountQuery from 'ee_else_ce/runner/graphql/list/group_runners_count.query.graphql';
+
import { captureException } from '../../sentry_utils';
-import allRunnersCountQuery from '../../graphql/list/all_runners_count.query.graphql';
-import groupRunnersCountQuery from '../../graphql/list/group_runners_count.query.graphql';
import { INSTANCE_TYPE, GROUP_TYPE } from '../../constants';
/**
@@ -38,7 +39,7 @@ export default {
variables: {
type: Object,
required: false,
- default: () => {},
+ default: () => ({}),
},
skip: {
type: Boolean,
diff --git a/app/assets/javascripts/runner/components/stat/runner_single_stat.vue b/app/assets/javascripts/runner/components/stat/runner_single_stat.vue
new file mode 100644
index 00000000000..ae732b052ac
--- /dev/null
+++ b/app/assets/javascripts/runner/components/stat/runner_single_stat.vue
@@ -0,0 +1,41 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { formatNumber } from '~/locale';
+import RunnerCount from './runner_count.vue';
+
+export default {
+ components: {
+ GlSingleStat,
+ RunnerCount,
+ },
+ props: {
+ scope: {
+ type: String,
+ required: true,
+ },
+ variables: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ skip: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ methods: {
+ formattedValue(value) {
+ if (typeof value === 'number') {
+ return formatNumber(value);
+ }
+ return '-';
+ },
+ },
+};
+</script>
+<template>
+ <runner-count #default="{ count }" :scope="scope" :variables="variables" :skip="skip">
+ <gl-single-stat v-bind="$attrs" :value="formattedValue(count)" />
+ </runner-count>
+</template>
diff --git a/app/assets/javascripts/runner/components/stat/runner_stats.vue b/app/assets/javascripts/runner/components/stat/runner_stats.vue
index 9e1ca9ba4ee..93e54ebe7f4 100644
--- a/app/assets/javascripts/runner/components/stat/runner_stats.vue
+++ b/app/assets/javascripts/runner/components/stat/runner_stats.vue
@@ -1,12 +1,13 @@
<script>
+import { s__ } from '~/locale';
+import RunnerSingleStat from '~/runner/components/stat/runner_single_stat.vue';
import { STATUS_ONLINE, STATUS_OFFLINE, STATUS_STALE } from '../../constants';
-import RunnerCount from './runner_count.vue';
-import RunnerStatusStat from './runner_status_stat.vue';
export default {
components: {
- RunnerCount,
- RunnerStatusStat,
+ RunnerSingleStat,
+ RunnerUpgradeStatusStats: () =>
+ import('ee_component/runner/components/stat/runner_upgrade_status_stats.vue'),
},
props: {
scope: {
@@ -16,32 +17,67 @@ export default {
variables: {
type: Object,
required: false,
- default: () => {},
+ default: () => ({}),
},
},
- methods: {
- countVariables(vars) {
- return { ...this.variables, ...vars };
+ computed: {
+ stats() {
+ return [
+ {
+ key: STATUS_ONLINE,
+ props: {
+ skip: this.statusCountSkip(STATUS_ONLINE),
+ variables: { ...this.variables, status: STATUS_ONLINE },
+ variant: 'success',
+ title: s__('Runners|Online runners'),
+ metaText: s__('Runners|online'),
+ },
+ },
+ {
+ key: STATUS_OFFLINE,
+ props: {
+ skip: this.statusCountSkip(STATUS_OFFLINE),
+ variables: { ...this.variables, status: STATUS_OFFLINE },
+ variant: 'muted',
+ title: s__('Runners|Offline runners'),
+ metaText: s__('Runners|offline'),
+ },
+ },
+ {
+ key: STATUS_STALE,
+ props: {
+ skip: this.statusCountSkip(STATUS_STALE),
+ variables: { ...this.variables, status: STATUS_STALE },
+ variant: 'warning',
+ title: s__('Runners|Stale runners'),
+ metaText: s__('Runners|stale'),
+ },
+ },
+ ];
},
+ },
+ methods: {
statusCountSkip(status) {
// Show an empty result when we already filter by another status
return this.variables.status && this.variables.status !== status;
},
},
- STATUS_LIST: [STATUS_ONLINE, STATUS_OFFLINE, STATUS_STALE],
};
</script>
<template>
- <div class="gl-display-flex gl-py-6">
- <runner-count
- v-for="status in $options.STATUS_LIST"
- #default="{ count }"
- :key="status"
+ <div class="gl-display-flex gl-flex-wrap gl-py-6">
+ <runner-single-stat
+ v-for="stat in stats"
+ :key="stat.key"
+ :scope="scope"
+ v-bind="stat.props"
+ class="gl-px-5"
+ />
+
+ <runner-upgrade-status-stats
+ class="gl-display-contents"
:scope="scope"
- :variables="countVariables({ status })"
- :skip="statusCountSkip(status)"
- >
- <runner-status-stat class="gl-px-5" :status="status" :value="count" />
- </runner-count>
+ :variables="variables"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/stat/runner_status_stat.vue b/app/assets/javascripts/runner/components/stat/runner_status_stat.vue
deleted file mode 100644
index b77bbe15541..00000000000
--- a/app/assets/javascripts/runner/components/stat/runner_status_stat.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import { s__, formatNumber } from '~/locale';
-import { STATUS_ONLINE, STATUS_OFFLINE, STATUS_STALE } from '../../constants';
-
-export default {
- components: {
- GlSingleStat,
- },
- props: {
- value: {
- type: Number,
- required: false,
- default: null,
- },
- status: {
- type: String,
- required: true,
- },
- },
- computed: {
- formattedValue() {
- if (typeof this.value === 'number') {
- return formatNumber(this.value);
- }
- return '-';
- },
- stat() {
- switch (this.status) {
- case STATUS_ONLINE:
- return {
- variant: 'success',
- title: s__('Runners|Online runners'),
- metaText: s__('Runners|online'),
- };
- case STATUS_OFFLINE:
- return {
- variant: 'muted',
- title: s__('Runners|Offline runners'),
- metaText: s__('Runners|offline'),
- };
- case STATUS_STALE:
- return {
- variant: 'warning',
- title: s__('Runners|Stale runners'),
- metaText: s__('Runners|stale'),
- };
- default:
- return {
- title: s__('Runners|Runners'),
- };
- }
- },
- },
-};
-</script>
-<template>
- <gl-single-stat
- v-if="stat"
- :value="formattedValue"
- :variant="stat.variant"
- :title="stat.title"
- :meta-text="stat.metaText"
- />
-</template>
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index 64541729701..ed1afcbf691 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -1,5 +1,7 @@
import { __, s__ } from '~/locale';
+export const RUNNER_TYPENAME = 'CiRunner'; // __typename
+
export const RUNNER_PAGE_SIZE = 20;
export const RUNNER_JOB_COUNT_LIMIT = 1000;
@@ -102,7 +104,6 @@ export const PARAM_KEY_TAG = 'tag';
export const PARAM_KEY_SEARCH = 'search';
export const PARAM_KEY_SORT = 'sort';
-export const PARAM_KEY_PAGE = 'page';
export const PARAM_KEY_AFTER = 'after';
export const PARAM_KEY_BEFORE = 'before';
diff --git a/app/assets/javascripts/runner/graphql/edit/runner_fields_shared.fragment.graphql b/app/assets/javascripts/runner/graphql/edit/runner_fields_shared.fragment.graphql
index f900a0450e5..29abddf84f5 100644
--- a/app/assets/javascripts/runner/graphql/edit/runner_fields_shared.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/edit/runner_fields_shared.fragment.graphql
@@ -1,5 +1,4 @@
fragment RunnerFieldsShared on CiRunner {
- __typename
id
shortSha
runnerType
diff --git a/app/assets/javascripts/runner/graphql/list/all_runners.query.graphql b/app/assets/javascripts/runner/graphql/list/all_runners.query.graphql
index 6bb896dda16..1160596aff3 100644
--- a/app/assets/javascripts/runner/graphql/list/all_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/list/all_runners.query.graphql
@@ -1,5 +1,4 @@
-#import "ee_else_ce/runner/graphql/list/list_item.fragment.graphql"
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+#import "~/runner/graphql/list/all_runners_connection.fragment.graphql"
query getAllRunners(
$before: String
@@ -25,14 +24,6 @@ query getAllRunners(
search: $search
sort: $sort
) {
- nodes {
- ...ListItem
- adminUrl
- editAdminUrl
- }
- pageInfo {
- __typename
- ...PageInfo
- }
+ ...AllRunnersConnection
}
}
diff --git a/app/assets/javascripts/runner/graphql/list/all_runners_connection.fragment.graphql b/app/assets/javascripts/runner/graphql/list/all_runners_connection.fragment.graphql
new file mode 100644
index 00000000000..4440b8e98da
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/list/all_runners_connection.fragment.graphql
@@ -0,0 +1,13 @@
+#import "ee_else_ce/runner/graphql/list/list_item.fragment.graphql"
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+
+fragment AllRunnersConnection on CiRunnerConnection {
+ nodes {
+ ...ListItem
+ adminUrl
+ editAdminUrl
+ }
+ pageInfo {
+ ...PageInfo
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/list/bulk_runner_delete.mutation.graphql b/app/assets/javascripts/runner/graphql/list/bulk_runner_delete.mutation.graphql
new file mode 100644
index 00000000000..b73c016b1de
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/list/bulk_runner_delete.mutation.graphql
@@ -0,0 +1,6 @@
+mutation bulkRunnerDelete($input: BulkRunnerDeleteInput!) {
+ bulkRunnerDelete(input: $input) {
+ deletedIds
+ errors
+ }
+}
diff --git a/app/assets/javascripts/runner/graphql/list/group_runner_connection.fragment.graphql b/app/assets/javascripts/runner/graphql/list/group_runner_connection.fragment.graphql
new file mode 100644
index 00000000000..baef16a4b41
--- /dev/null
+++ b/app/assets/javascripts/runner/graphql/list/group_runner_connection.fragment.graphql
@@ -0,0 +1,16 @@
+#import "ee_else_ce/runner/graphql/list/list_item.fragment.graphql"
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+
+fragment GroupRunnerConnection on CiRunnerConnection {
+ edges {
+ webUrl
+ editUrl
+ node {
+ ...ListItem
+ projectCount # Used to determine why some project runners can't be deleted
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+}
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 8755636a7ad..4c519b9b867 100644
--- a/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/list/group_runners.query.graphql
@@ -1,5 +1,4 @@
-#import "ee_else_ce/runner/graphql/list/list_item.fragment.graphql"
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+#import "~/runner/graphql/list/group_runner_connection.fragment.graphql"
query getGroupRunners(
$groupFullPath: ID!
@@ -27,18 +26,7 @@ query getGroupRunners(
search: $search
sort: $sort
) {
- edges {
- webUrl
- editUrl
- node {
- ...ListItem
- projectCount # Used to determine why some project runners can't be deleted
- }
- }
- pageInfo {
- __typename
- ...PageInfo
- }
+ ...GroupRunnerConnection
}
}
}
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 cf925359ffb..ce23bddb898 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
@@ -1,11 +1,9 @@
fragment ListItemShared on CiRunner {
- __typename
id
description
runnerType
shortSha
version
- revision
ipAddress
active
locked
diff --git a/app/assets/javascripts/runner/graphql/list/local_state.js b/app/assets/javascripts/runner/graphql/list/local_state.js
index e87bc72c86a..154af261bba 100644
--- a/app/assets/javascripts/runner/graphql/list/local_state.js
+++ b/app/assets/javascripts/runner/graphql/list/local_state.js
@@ -1,4 +1,5 @@
import { makeVar } from '@apollo/client/core';
+import { RUNNER_TYPENAME } from '../../constants';
import typeDefs from './typedefs.graphql';
/**
@@ -33,10 +34,16 @@ export const createLocalState = () => {
typePolicies: {
Query: {
fields: {
- checkedRunnerIds() {
+ checkedRunnerIds(_, { canRead, toReference }) {
return Object.entries(checkedRunnerIdsVar())
+ .filter(([id]) => {
+ // Some runners may be deleted by the user separately.
+ // Skip dangling references, those not in the cache.
+ // See: https://www.apollographql.com/docs/react/caching/garbage-collection/#dangling-references
+ return canRead(toReference({ __typename: RUNNER_TYPENAME, id }));
+ })
.filter(([, isChecked]) => isChecked)
- .map(([key]) => key);
+ .map(([id]) => id);
},
},
},
@@ -50,6 +57,13 @@ export const createLocalState = () => {
[runner.id]: isChecked,
});
},
+ setRunnersChecked({ runners, isChecked }) {
+ const newVal = runners.reduce(
+ (acc, { id }) => ({ ...acc, [id]: isChecked }),
+ checkedRunnerIdsVar(),
+ );
+ checkedRunnerIdsVar(newVal);
+ },
clearChecked() {
checkedRunnerIdsVar({});
},
diff --git a/app/assets/javascripts/runner/graphql/show/runner_details_shared.fragment.graphql b/app/assets/javascripts/runner/graphql/show/runner_details_shared.fragment.graphql
index b79ad4d9280..499c0156770 100644
--- a/app/assets/javascripts/runner/graphql/show/runner_details_shared.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/show/runner_details_shared.fragment.graphql
@@ -1,5 +1,4 @@
fragment RunnerDetailsShared on CiRunner {
- __typename
id
shortSha
runnerType
diff --git a/app/assets/javascripts/runner/graphql/show/runner_projects.query.graphql b/app/assets/javascripts/runner/graphql/show/runner_projects.query.graphql
index cb27de7c200..acc4a641565 100644
--- a/app/assets/javascripts/runner/graphql/show/runner_projects.query.graphql
+++ b/app/assets/javascripts/runner/graphql/show/runner_projects.query.graphql
@@ -9,11 +9,15 @@ query getRunnerProjects(
) {
runner(id: $id) {
id
+ ownerProject {
+ id
+ }
projectCount
projects(first: $first, last: $last, before: $before, after: $after) {
nodes {
id
avatarUrl
+ description
name
nameWithNamespace
webUrl
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 e8446dbe345..a82411a2120 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -3,6 +3,14 @@ import { GlLink } from '@gitlab/ui';
import { createAlert } from '~/flash';
import { updateHistory } from '~/lib/utils/url_utility';
import { fetchPolicies } from '~/lib/graphql';
+import { upgradeStatusTokenConfig } from 'ee_else_ce/runner/components/search_tokens/upgrade_status_token_config';
+import {
+ fromUrlQueryToSearch,
+ fromSearchToUrl,
+ fromSearchToVariables,
+ isSearchFiltered,
+} from 'ee_else_ce/runner/runner_search_utils';
+import groupRunnersQuery from 'ee_else_ce/runner/graphql/list/group_runners.query.graphql';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
@@ -22,13 +30,6 @@ import {
PROJECT_TYPE,
I18N_FETCH_ERROR,
} from '../constants';
-import groupRunnersQuery from '../graphql/list/group_runners.query.graphql';
-import {
- fromUrlQueryToSearch,
- fromSearchToUrl,
- fromSearchToVariables,
- isSearchFiltered,
-} from '../runner_search_utils';
import { captureException } from '../sentry_utils';
export default {
@@ -123,7 +124,7 @@ export default {
return !this.runnersLoading && !this.runners.items.length;
},
searchTokens() {
- return [pausedTokenConfig, statusTokenConfig];
+ return [pausedTokenConfig, statusTokenConfig, upgradeStatusTokenConfig];
},
filteredSearchNamespace() {
return `${GROUP_FILTERED_SEARCH_NAMESPACE}/${this.groupFullPath}`;
@@ -166,6 +167,9 @@ export default {
reportToSentry(error) {
captureException({ error, component: this.$options.name });
},
+ onPaginationInput(value) {
+ this.search.pagination = value;
+ },
},
TABS_RUNNER_TYPES: [GROUP_TYPE, PROJECT_TYPE],
GROUP_TYPE,
@@ -225,11 +229,13 @@ export default {
/>
</template>
</runner-list>
- <runner-pagination
- v-model="search.pagination"
- class="gl-mt-3"
- :page-info="runners.pageInfo"
- />
</template>
+
+ <runner-pagination
+ class="gl-mt-3"
+ :disabled="runnersLoading"
+ :page-info="runners.pageInfo"
+ @input="onPaginationInput"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/runner/runner_search_utils.js b/app/assets/javascripts/runner/runner_search_utils.js
index e01878f355a..dc582ccbac1 100644
--- a/app/assets/javascripts/runner/runner_search_utils.js
+++ b/app/assets/javascripts/runner/runner_search_utils.js
@@ -1,3 +1,4 @@
+import { isEmpty } from 'lodash';
import { queryToObject, setUrlParams } from '~/lib/utils/url_utility';
import {
filterToQueryObject,
@@ -13,7 +14,6 @@ import {
PARAM_KEY_TAG,
PARAM_KEY_SEARCH,
PARAM_KEY_SORT,
- PARAM_KEY_PAGE,
PARAM_KEY_AFTER,
PARAM_KEY_BEFORE,
DEFAULT_SORT,
@@ -41,7 +41,7 @@ import { getPaginationVariables } from './utils';
* sort: 'CREATED_DESC',
*
* // Pagination information
- * pagination: { page: 1 },
+ * pagination: { "after": "..." },
* };
* ```
*
@@ -66,25 +66,16 @@ export const searchValidator = ({ runnerType, filters, sort }) => {
};
const getPaginationFromParams = (params) => {
- const page = parseInt(params[PARAM_KEY_PAGE], 10);
- const after = params[PARAM_KEY_AFTER];
- const before = params[PARAM_KEY_BEFORE];
-
- if (page && (before || after)) {
- return {
- page,
- before,
- after,
- };
- }
return {
- page: 1,
+ after: params[PARAM_KEY_AFTER],
+ before: params[PARAM_KEY_BEFORE],
};
};
// Outdated URL parameters
const STATUS_ACTIVE = 'ACTIVE';
const STATUS_PAUSED = 'PAUSED';
+const PARAM_KEY_PAGE = 'page';
/**
* Replaces params into a URL
@@ -97,6 +88,21 @@ const updateUrlParams = (url, params = {}) => {
return setUrlParams(params, url, false, true, true);
};
+const outdatedStatusParams = (status) => {
+ if (status === STATUS_ACTIVE) {
+ return {
+ [PARAM_KEY_PAUSED]: ['false'],
+ [PARAM_KEY_STATUS]: [], // Important! clear PARAM_KEY_STATUS to avoid a redirection loop!
+ };
+ } else if (status === STATUS_PAUSED) {
+ return {
+ [PARAM_KEY_PAUSED]: ['true'],
+ [PARAM_KEY_STATUS]: [], // Important! clear PARAM_KEY_STATUS to avoid a redirection loop!
+ };
+ }
+ return {};
+};
+
/**
* Returns an updated URL for old (or deprecated) admin runner URLs.
*
@@ -108,25 +114,22 @@ const updateUrlParams = (url, params = {}) => {
export const updateOutdatedUrl = (url = window.location.href) => {
const urlObj = new URL(url);
const query = urlObj.search;
-
const params = queryToObject(query, { gatherArrays: true });
- const status = params[PARAM_KEY_STATUS]?.[0] || null;
-
- switch (status) {
- case STATUS_ACTIVE:
- return updateUrlParams(url, {
- [PARAM_KEY_PAUSED]: ['false'],
- [PARAM_KEY_STATUS]: [], // Important! clear PARAM_KEY_STATUS to avoid a redirection loop!
- });
- case STATUS_PAUSED:
- return updateUrlParams(url, {
- [PARAM_KEY_PAUSED]: ['true'],
- [PARAM_KEY_STATUS]: [], // Important! clear PARAM_KEY_STATUS to avoid a redirection loop!
- });
- default:
- return null;
+ // Remove `page` completely, not needed for keyset pagination
+ const pageParams = PARAM_KEY_PAGE in params ? { [PARAM_KEY_PAGE]: null } : {};
+
+ const status = params[PARAM_KEY_STATUS]?.[0];
+ const redirectParams = {
+ // Replace paused status (active, paused) with a paused flag
+ ...outdatedStatusParams(status),
+ ...pageParams,
+ };
+
+ if (!isEmpty(redirectParams)) {
+ return updateUrlParams(url, redirectParams);
}
+ return null;
};
/**
@@ -182,13 +185,11 @@ export const fromSearchToUrl = (
}
const isDefaultSort = sort !== DEFAULT_SORT;
- const isFirstPage = pagination?.page === 1;
const otherParams = {
// Sorting & Pagination
[PARAM_KEY_SORT]: isDefaultSort ? sort : null,
- [PARAM_KEY_PAGE]: isFirstPage ? null : pagination.page,
- [PARAM_KEY_BEFORE]: isFirstPage ? null : pagination.before,
- [PARAM_KEY_AFTER]: isFirstPage ? null : pagination.after,
+ [PARAM_KEY_BEFORE]: pagination?.before || null,
+ [PARAM_KEY_AFTER]: pagination?.after || null,
};
return setUrlParams({ ...filterParams, ...otherParams }, url, false, true, true);
@@ -247,6 +248,6 @@ export const fromSearchToVariables = ({
*/
export const isSearchFiltered = ({ runnerType = null, filters = [], pagination = {} } = {}) => {
return Boolean(
- runnerType !== null || filters?.length !== 0 || (pagination && pagination?.page !== 1),
+ runnerType !== null || filters?.length !== 0 || pagination?.before || pagination?.after,
);
};
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 6efaf08a178..5a9ef832e05 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -157,6 +157,7 @@ export const SCANNER_NAMES_MAP = {
COVERAGE_FUZZING: COVERAGE_FUZZING_NAME,
SECRET_DETECTION: SECRET_DETECTION_NAME,
DEPENDENCY_SCANNING: DEPENDENCY_SCANNING_NAME,
+ GENERIC: s__('ciReport|Manually Added'),
};
export const securityFeatures = [
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 579316f481c..2cdec8fc481 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
@@ -91,7 +91,7 @@ export default {
modalId: 'set-user-status-modal',
noEmoji: true,
availability: isUserBusy(this.currentAvailability),
- clearStatusAfter: statusTimeRanges[0].label,
+ clearStatusAfter: statusTimeRanges[0],
clearStatusAfterMessage: sprintf(s__('SetStatusModal|Your status resets on %{date}.'), {
date: this.currentClearStatusAfter,
}),
@@ -178,9 +178,7 @@ export default {
message,
availability: availability ? AVAILABILITY_STATUS.BUSY : AVAILABILITY_STATUS.NOT_SET,
clearStatusAfter:
- clearStatusAfter === statusTimeRanges[0].label
- ? null
- : clearStatusAfter.replace(' ', '_'),
+ clearStatusAfter.label === statusTimeRanges[0].label ? null : clearStatusAfter.shortcut,
})
.then(this.onUpdateSuccess)
.catch(this.onUpdateFail);
@@ -279,12 +277,12 @@ export default {
<div class="form-group">
<div class="gl-display-flex gl-align-items-baseline">
<span class="gl-mr-3">{{ s__('SetStatusModal|Clear status after') }}</span>
- <gl-dropdown :text="clearStatusAfter" data-testid="clear-status-at-dropdown">
+ <gl-dropdown :text="clearStatusAfter.label" data-testid="clear-status-at-dropdown">
<gl-dropdown-item
v-for="after in $options.statusTimeRanges"
:key="after.name"
:data-testid="after.name"
- @click="setClearStatusAfter(after.label)"
+ @click="setClearStatusAfter(after)"
>{{ after.label }}</gl-dropdown-item
>
</gl-dropdown>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index 3602b5ec4f6..29ea390a81d 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -39,9 +39,6 @@ export default {
assignSelf() {
this.$emit('assign-self');
},
- toggleAttentionRequested(data) {
- this.$emit('toggle-attention-requested', data);
- },
},
};
</script>
@@ -66,12 +63,7 @@ export default {
</template>
</span>
- <uncollapsed-assignee-list
- v-else
- :users="sortedAssigness"
- :issuable-type="issuableType"
- @toggle-attention-requested="toggleAttentionRequested"
- />
+ <uncollapsed-assignee-list v-else :users="sortedAssigness" :issuable-type="issuableType" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
index 59a4eb54bbe..a94dd128a1a 100644
--- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -32,11 +32,6 @@ export default {
return this.users.length === 0;
},
},
- methods: {
- toggleAttentionRequested(data) {
- this.$emit('toggle-attention-requested', data);
- },
- },
};
</script>
@@ -66,7 +61,6 @@ export default {
:users="users"
:issuable-type="issuableType"
class="gl-text-gray-800 hide-collapsed"
- @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index e596d6292bf..18b26c7d8bd 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -125,9 +125,6 @@ export default {
availability: this.assigneeAvailabilityStatus[username] || '',
}));
},
- toggleAttentionRequested(data) {
- this.mediator.toggleAttentionRequested('assignee', data);
- },
},
};
</script>
@@ -155,7 +152,6 @@ export default {
:editable="store.editable"
:issuable-type="issuableType"
@assign-self="assignSelf"
- @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
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 14f6c9d3a15..5c432ca0e03 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -149,6 +149,9 @@ export default {
signedIn() {
return this.currentUser.username !== undefined;
},
+ issuableAuthor() {
+ return this.issuable?.author;
+ },
},
watch: {
iid(_, oldIid) {
@@ -266,6 +269,7 @@ export default {
:current-user="currentUser"
:issuable-type="issuableType"
:is-editing="edit"
+ :issuable-author="issuableAuthor"
class="gl-w-full dropdown-menu-user gl-mt-n3"
@toggle="collapseWidget"
@error="showError"
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
index e9c68008143..0ed40f56bea 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_participant.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAvatarLabeled, GlAvatarLink, GlIcon } from '@gitlab/ui';
+import { GlAvatarLabeled, GlIcon } from '@gitlab/ui';
import { IssuableType } from '~/issues/constants';
import { s__, sprintf } from '~/locale';
@@ -11,7 +11,6 @@ const AVAILABILITY_STATUS = {
export default {
components: {
GlAvatarLabeled,
- GlAvatarLink,
GlIcon,
},
props: {
@@ -47,23 +46,21 @@ export default {
</script>
<template>
- <gl-avatar-link>
- <gl-avatar-labeled
- :size="32"
- :label="userLabel"
- :sub-label="`@${user.username}`"
- :src="user.avatarUrl || user.avatar || user.avatar_url"
- class="gl-align-items-center gl-relative"
- >
- <template #meta>
- <gl-icon
- v-if="hasCannotMergeIcon"
- name="warning-solid"
- aria-hidden="true"
- class="merge-icon"
- :size="12"
- />
- </template>
- </gl-avatar-labeled>
- </gl-avatar-link>
+ <gl-avatar-labeled
+ :size="32"
+ :label="userLabel"
+ :sub-label="`@${user.username}`"
+ :src="user.avatarUrl || user.avatar || user.avatar_url"
+ class="gl-align-items-center gl-relative sidebar-participant"
+ >
+ <template #meta>
+ <gl-icon
+ v-if="hasCannotMergeIcon"
+ name="warning-solid"
+ aria-hidden="true"
+ class="merge-icon gl-left-6 gl-bottom-0"
+ :size="12"
+ />
+ </template>
+ </gl-avatar-labeled>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index b6260418837..0e4d4c74160 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -2,7 +2,6 @@
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { IssuableType } from '~/issues/constants';
import { __, sprintf } from '~/locale';
-import AttentionRequestedToggle from '../attention_requested_toggle.vue';
import AssigneeAvatarLink from './assignee_avatar_link.vue';
import UserNameWithStatus from './user_name_with_status.vue';
@@ -10,7 +9,6 @@ const DEFAULT_RENDER_COUNT = 5;
export default {
components: {
- AttentionRequestedToggle,
AssigneeAvatarLink,
UserNameWithStatus,
},
@@ -46,10 +44,6 @@ export default {
return this.users.length - DEFAULT_RENDER_COUNT;
},
uncollapsedUsers() {
- if (this.showVerticalList) {
- return this.users;
- }
-
const uncollapsedLength = this.showLess
? Math.min(this.users.length, DEFAULT_RENDER_COUNT)
: this.users.length;
@@ -58,9 +52,6 @@ export default {
username() {
return `@${this.firstUser.username}`;
},
- showVerticalList() {
- return this.glFeatures.mrAttentionRequests && this.isMergeRequest;
- },
isMergeRequest() {
return this.issuableType === IssuableType.MergeRequest;
},
@@ -75,9 +66,6 @@ export default {
}
return u?.status?.availability || '';
},
- toggleAttentionRequested(data) {
- this.$emit('toggle-attention-requested', data);
- },
},
};
</script>
@@ -96,7 +84,7 @@ export default {
<assignee-avatar-link
:user="user"
:issuable-type="issuableType"
- :tooltip-has-name="!showVerticalList"
+ :tooltip-has-name="!isMergeRequest"
class="gl-word-break-word"
data-css-area="user"
>
@@ -107,14 +95,6 @@ export default {
<user-name-with-status :name="user.name" :availability="userAvailability(user)" />
</div>
</assignee-avatar-link>
- <attention-requested-toggle
- v-if="showVerticalList"
- :user="user"
- type="assignee"
- class="gl-mr-2"
- data-css-area="attention"
- @toggle-attention-requested="toggleAttentionRequested"
- />
</div>
</div>
<div v-if="renderShowMoreSection" class="user-list-more gl-hover-text-blue-800">
diff --git a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
deleted file mode 100644
index 974ad189f32..00000000000
--- a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
+++ /dev/null
@@ -1,105 +0,0 @@
-<script>
-import { GlButton, GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
-import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
-
-export default {
- i18n: {
- addAttentionRequest: __('Add attention request'),
- removeAttentionRequest: __('Remove attention request'),
- attentionRequestedNoPermission: __('Attention requested'),
- noAttentionRequestedNoPermission: __('No attention request'),
- },
- components: {
- GlButton,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- type: {
- type: String,
- required: true,
- },
- user: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- loading: false,
- };
- },
- computed: {
- tooltipTitle() {
- if (this.user.attention_requested) {
- if (this.user.can_update_merge_request) {
- return this.$options.i18n.removeAttentionRequest;
- }
-
- return this.$options.i18n.attentionRequestedNoPermission;
- }
-
- if (this.user.can_update_merge_request) {
- return this.$options.i18n.addAttentionRequest;
- }
-
- return this.$options.i18n.noAttentionRequestedNoPermission;
- },
- request() {
- const state = {
- selected: false,
- icon: 'attention',
- direction: 'add',
- };
-
- if (this.user.attention_requested) {
- Object.assign(state, {
- selected: true,
- icon: 'attention-solid',
- direction: 'remove',
- });
- }
-
- return state;
- },
- },
- methods: {
- toggleAttentionRequired() {
- if (this.loading || !this.user.can_update_merge_request) return;
-
- this.$root.$emit(BV_HIDE_TOOLTIP);
- this.loading = true;
- this.$emit('toggle-attention-requested', {
- user: this.user,
- callback: this.toggleAttentionRequiredComplete,
- direction: this.request.direction,
- });
- },
- toggleAttentionRequiredComplete() {
- this.loading = false;
- },
- },
-};
-</script>
-
-<template>
- <div>
- <span
- v-gl-tooltip.left.viewport="tooltipTitle"
- class="gl-display-inline-block js-attention-request-toggle"
- >
- <gl-button
- :loading="loading"
- :selected="request.selected"
- :icon="request.icon"
- :aria-label="tooltipTitle"
- :class="{ 'gl-pointer-events-none': !user.can_update_merge_request }"
- size="small"
- category="tertiary"
- @click="toggleAttentionRequired"
- />
- </span>
- </div>
-</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..336c291d4f1 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
@@ -88,7 +88,10 @@ export default {
.then(
({
data: {
- issuableSetConfidential: { errors },
+ issuableSetConfidential: {
+ issuable: { confidential },
+ errors,
+ },
},
}) => {
if (errors.length) {
@@ -96,7 +99,7 @@ export default {
message: errors[0],
});
} else {
- this.$emit('closeForm');
+ this.$emit('closeForm', { confidential });
}
},
)
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..eec083f23f3 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue
@@ -95,10 +95,10 @@ export default {
confidentialWidget.setConfidentiality = null;
},
methods: {
- closeForm() {
+ closeForm({ confidential } = {}) {
this.$refs.editable.collapse();
this.$el.dispatchEvent(hideDropdownEvent);
- this.$emit('closeForm');
+ this.$emit('closeForm', { confidential });
},
// synchronizing the quick action with the sidebar widget
// this is a temporary solution until we have confidentiality real-time updates
diff --git a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
index 9502b2e78b3..6f82178b6fd 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
@@ -33,7 +33,7 @@ export default {
return this.users.length > 2;
},
allReviewersCanMerge() {
- return this.users.every((user) => user.can_merge);
+ return this.users.every((user) => user.mergeRequestInteraction?.canMerge);
},
sidebarAvatarCounter() {
if (this.users.length > DEFAULT_MAX_COUNTER) {
@@ -48,7 +48,7 @@ export default {
return this.users.slice(0, collapsedLength);
},
tooltipTitleMergeStatus() {
- const mergeLength = this.users.filter((u) => u.can_merge).length;
+ const mergeLength = this.users.filter((u) => u.mergeRequestInteraction?.canMerge).length;
if (mergeLength === this.users.length) {
return '';
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar.vue
index 7961b7cd679..a7db3b3d09f 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar.vue
@@ -23,10 +23,10 @@ export default {
return sprintf(__("%{userName}'s avatar"), { userName: this.user.name });
},
avatarUrl() {
- return this.user.avatar || this.user.avatar_url || gon.default_avatar_url;
+ return this.user.avatarUrl || this.user.avatar_url || gon.default_avatar_url;
},
hasMergeIcon() {
- return !this.user.can_merge;
+ return !this.user.mergeRequestInteraction?.canMerge;
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
index c9b0a4ae2b3..f69c027e201 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue
@@ -40,7 +40,7 @@ export default {
},
computed: {
cannotMerge() {
- return this.issuableType === 'merge_request' && !this.user.can_merge;
+ return this.issuableType === 'merge_request' && !this.user.mergeRequestInteraction?.canMerge;
},
tooltipTitle() {
if (this.cannotMerge && this.tooltipHasName) {
@@ -59,7 +59,7 @@ export default {
};
},
reviewerUrl() {
- return this.user.web_url;
+ return this.user.webUrl;
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
index b07fd944ff9..5e1172ad835 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue
@@ -36,8 +36,8 @@ export default {
return !this.users.length;
},
sortedReviewers() {
- const canMergeUsers = this.users.filter((user) => user.can_merge);
- const canNotMergeUsers = this.users.filter((user) => !user.can_merge);
+ const canMergeUsers = this.users.filter((user) => user.mergeRequestInteraction?.canMerge);
+ const canNotMergeUsers = this.users.filter((user) => !user.mergeRequestInteraction?.canMerge);
return [...canMergeUsers, ...canNotMergeUsers];
},
@@ -49,9 +49,6 @@ export default {
requestReview(data) {
this.$emit('request-review', data);
},
- toggleAttentionRequested(data) {
- this.$emit('toggle-attention-requested', data);
- },
},
};
</script>
@@ -73,7 +70,6 @@ export default {
:root-path="rootPath"
:issuable-type="issuableType"
@request-review="requestReview"
- @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
index 2ea63219e92..b0d820ddd15 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue
@@ -1,15 +1,23 @@
<script>
// NOTE! For the first iteration, we are simply copying the implementation of Assignees
// 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 { __ } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import getMergeRequestReviewersQuery from '~/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql';
import ReviewerTitle from './reviewer_title.vue';
import Reviewers from './reviewers.vue';
+export const state = Vue.observable({
+ issuable: {},
+ loading: false,
+ initialLoading: true,
+});
+
export default {
name: 'SidebarReviewers',
components: {
@@ -40,18 +48,49 @@ export default {
required: true,
},
},
+ apollo: {
+ issuable: {
+ query: getMergeRequestReviewersQuery,
+ variables() {
+ return {
+ iid: this.issuableIid,
+ fullPath: this.projectPath,
+ };
+ },
+ update(data) {
+ return data.workspace?.issuable;
+ },
+ result() {
+ this.initialLoading = false;
+ },
+ error() {
+ createFlash({ message: __('An error occurred while fetching reviewers.') });
+ },
+ },
+ },
data() {
- return {
- store: new Store(),
- loading: false,
- };
+ return state;
},
computed: {
relativeUrlRoot() {
return gon.relative_url_root ?? '';
},
+ reviewers() {
+ return this.issuable.reviewers?.nodes || [];
+ },
+ graphqlFetching() {
+ return this.$apollo.queries.issuable.loading;
+ },
+ isLoading() {
+ return this.loading || this.$apollo.queries.issuable.loading;
+ },
+ canUpdate() {
+ return this.issuable.userPermissions?.updateMergeRequest || false;
+ },
},
created() {
+ this.store = new Store();
+
this.removeReviewer = this.store.removeReviewer.bind(this.store);
this.addReviewer = this.store.addReviewer.bind(this.store);
this.removeAllReviewers = this.store.removeAllReviewers.bind(this.store);
@@ -77,6 +116,7 @@ export default {
.then(() => {
this.loading = false;
refreshUserMergeRequestCounts();
+ this.$apollo.queries.issuable.refetch();
})
.catch(() => {
this.loading = false;
@@ -88,9 +128,6 @@ export default {
requestReview(data) {
this.mediator.requestReview(data);
},
- toggleAttentionRequested(data) {
- this.mediator.toggleAttentionRequested('reviewer', data);
- },
},
};
</script>
@@ -98,18 +135,17 @@ export default {
<template>
<div>
<reviewer-title
- :number-of-reviewers="store.reviewers.length"
- :loading="loading || store.isFetching.reviewers"
- :editable="store.editable"
+ :number-of-reviewers="reviewers.length"
+ :loading="isLoading"
+ :editable="canUpdate"
/>
<reviewers
- v-if="!store.isFetching.reviewers"
+ v-if="!initialLoading"
:root-path="relativeUrlRoot"
- :users="store.reviewers"
- :editable="store.editable"
+ :users="reviewers"
+ :editable="canUpdate"
:issuable-type="issuableType"
@request-review="requestReview"
- @toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index 2f58e11c00f..217ca2e2548 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -1,8 +1,6 @@
<script>
import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, sprintf, s__ } from '~/locale';
-import AttentionRequestedToggle from '../attention_requested_toggle.vue';
import ReviewerAvatarLink from './reviewer_avatar_link.vue';
const LOADING_STATE = 'loading';
@@ -16,12 +14,10 @@ export default {
GlButton,
GlIcon,
ReviewerAvatarLink,
- AttentionRequestedToggle,
},
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagsMixin()],
props: {
users: {
type: Array,
@@ -80,9 +76,6 @@ export default {
this.loadingStates[userId] = null;
}
},
- toggleAttentionRequested(data) {
- this.$emit('toggle-attention-requested', data);
- },
},
LOADING_STATE,
SUCCESS_STATE,
@@ -96,7 +89,6 @@ export default {
:key="user.id"
:class="{
'gl-mb-3': index !== users.length - 1,
- 'attention-requests': glFeatures.mrAttentionRequests,
}"
class="gl-display-grid gl-align-items-center reviewer-grid gl-mr-2"
data-testid="reviewer"
@@ -112,16 +104,8 @@ export default {
{{ user.name }}
</div>
</reviewer-avatar-link>
- <attention-requested-toggle
- v-if="glFeatures.mrAttentionRequests"
- :user="user"
- type="reviewer"
- class="gl-mr-2"
- data-css-area="attention"
- @toggle-attention-requested="toggleAttentionRequested"
- />
<gl-icon
- v-if="user.approved"
+ v-if="user.mergeRequestInteraction.approved"
v-gl-tooltip.left
:size="16"
:title="approvedByTooltipTitle(user)"
@@ -137,9 +121,7 @@ export default {
data-testid="re-request-success"
/>
<gl-button
- v-else-if="
- user.can_update_merge_request && user.reviewed && !glFeatures.mrAttentionRequests
- "
+ v-else-if="user.mergeRequestInteraction.canUpdate && user.mergeRequestInteraction.reviewed"
v-gl-tooltip.left
:title="$options.i18n.reRequestReview"
:aria-label="$options.i18n.reRequestReview"
diff --git a/app/assets/javascripts/sidebar/components/severity/severity.vue b/app/assets/javascripts/sidebar/components/severity/severity.vue
index 0db856543d0..776dab98f01 100644
--- a/app/assets/javascripts/sidebar/components/severity/severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/severity.vue
@@ -37,10 +37,10 @@ export default {
<gl-icon
:size="iconSize"
:name="`severity-${severity.icon}`"
- :class="[`icon-${severity.icon}`, { 'gl-mr-3': !iconOnly }]"
+ :class="[`icon-${severity.icon}`, { 'gl-mr-3 gl-flex-shrink-0': !iconOnly }]"
/>
- <tooltip-on-truncate v-if="!iconOnly" :title="severity.label" class="gl-text-truncate">{{
- severity.label
- }}</tooltip-on-truncate>
+ <tooltip-on-truncate v-if="!iconOnly" :title="severity.label" class="gl-text-truncate">
+ {{ severity.label }}
+ </tooltip-on-truncate>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index 86e46016534..bf4ba715f85 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -149,23 +149,25 @@ export default {
</div>
<div class="hide-collapsed">
- <p
- class="gl-line-height-20 gl-mb-2 gl-text-gray-900 gl-display-flex gl-justify-content-space-between"
+ <div
+ class="gl-display-flex gl-align-items-center gl-line-height-20 gl-text-gray-900 gl-font-weight-bold"
>
{{ $options.i18n.SEVERITY }}
<gl-button
v-if="canUpdate"
category="tertiary"
size="small"
+ class="gl-ml-auto hide-collapsed gl-mr-n2"
data-testid="editButton"
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
{{ $options.i18n.EDIT }}
</gl-button>
- </p>
+ </div>
<gl-dropdown
+ class="gl-mt-3"
:class="dropdownClass"
block
:header-text="__('Assign severity')"
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 3f82fe5ce87..fec4d0e346d 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -27,8 +27,6 @@ import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
import LabelsSelectWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
-import eventHub from '~/sidebar/event_hub';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
@@ -41,6 +39,7 @@ import SidebarTimeTracking from './components/time_tracking/sidebar_time_trackin
import { IssuableAttributeType } from './constants';
import SidebarMoveIssue from './lib/sidebar_move_issue';
import CrmContacts from './components/crm_contacts/crm_contacts.vue';
+import SidebarEventHub from './event_hub';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -361,6 +360,13 @@ function mountConfidentialComponent() {
? IssuableType.Issue
: IssuableType.MergeRequest,
},
+ on: {
+ closeForm({ confidential }) {
+ if (confidential !== undefined) {
+ SidebarEventHub.$emit('confidentialityUpdated', confidential);
+ }
+ },
+ },
}),
});
}
@@ -652,13 +658,6 @@ export function mountSidebar(mediator, store) {
mountSeverityComponent();
mountEscalationStatusComponent();
-
- if (window.gon?.features?.mrAttentionRequests) {
- eventHub.$on('removeCurrentUserAttentionRequested', () => {
- mediator.removeCurrentUserAttentionRequested();
- refreshUserMergeRequestCounts();
- });
- }
}
export { getSidebarOptions };
diff --git a/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql b/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
index 4998b2af666..a9d7e9878c6 100644
--- a/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
@@ -1,9 +1,7 @@
query epicConfidential($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
confidential
}
diff --git a/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql b/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
index 00529042e92..45c15a86961 100644
--- a/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
@@ -1,9 +1,7 @@
query epicDueDate($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
dueDate
dueDateIsFixed
diff --git a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
index dada7ffc034..d665ca1e084 100644
--- a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
@@ -3,10 +3,8 @@
query epicParticipants($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
participants {
nodes {
diff --git a/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql b/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
index f35ca896ef8..76d570a0f16 100644
--- a/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
@@ -1,9 +1,7 @@
query epicReference($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
reference(full: true)
}
diff --git a/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql b/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
index 85fc7de8d02..c85ede07fde 100644
--- a/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
@@ -1,9 +1,7 @@
query epicStartDate($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
startDate
startDateIsFixed
diff --git a/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
index a8fe6b8ddc3..b1973075d48 100644
--- a/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
@@ -1,10 +1,8 @@
query epicSubscribed($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
emailsDisabled
issuable: epic(iid: $iid) {
- __typename
id
subscribed
}
diff --git a/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql b/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
index b0ba724e727..3c035bcc6db 100644
--- a/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
@@ -1,9 +1,7 @@
query epicTodos($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
- __typename
id
issuable: epic(iid: $iid) {
- __typename
id
currentUserTodos(state: pending) {
nodes {
diff --git a/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql b/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql
index dceab61ed26..6b15fcda2e8 100644
--- a/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql
@@ -2,7 +2,6 @@
query groupMilestones($fullPath: ID!, $title: String, $state: MilestoneStateEnum) {
workspace: group(fullPath: $fullPath) {
- __typename
id
attributes: milestones(
searchTitle: $title
diff --git a/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql b/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
index e578cf3bda5..fcdc84c5a06 100644
--- a/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
@@ -1,9 +1,7 @@
query issueConfidential($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
confidential
}
diff --git a/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
index 48cbff252b3..4369104704a 100644
--- a/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
@@ -1,9 +1,7 @@
query issueDueDate($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
dueDate
}
diff --git a/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql b/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
index c3128d6d961..2c69cc04429 100644
--- a/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
@@ -1,9 +1,7 @@
query issueReference($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
id
- __typename
issuable: issue(iid: $iid) {
- __typename
id
reference(full: true)
}
diff --git a/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
index e2722fc86a4..419036ee15d 100644
--- a/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
@@ -1,9 +1,7 @@
query issueSubscribed($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
subscribed
emailsDisabled
diff --git a/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
index 059361dd370..f4d0e9b5deb 100644
--- a/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
@@ -1,9 +1,7 @@
query issueTimeTracking($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
humanTimeEstimate
humanTotalTimeSpent
diff --git a/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql b/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
index 5cd5d81c439..3211ded66ae 100644
--- a/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
@@ -1,9 +1,7 @@
query issueTodos($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
currentUserTodos(state: pending) {
nodes {
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
index b0a16677cf2..26bf901babf 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
@@ -2,10 +2,8 @@
query mergeRequestMilestone($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: mergeRequest(iid: $iid) {
- __typename
id
attribute: milestone {
...MilestoneFragment
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
index 7c78f812b67..e42e50ba861 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
@@ -1,9 +1,7 @@
query mergeRequestReference($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: mergeRequest(iid: $iid) {
- __typename
id
reference(full: true)
}
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
index d5e27ca7b69..d29f4d512c5 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
@@ -1,9 +1,7 @@
query mergeRequestSubscribed($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: mergeRequest(iid: $iid) {
- __typename
id
subscribed
}
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
index d480ff3d5ba..5d05cb2f34c 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
@@ -1,9 +1,7 @@
query mergeRequestTimeTracking($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: mergeRequest(iid: $iid) {
- __typename
id
humanTimeEstimate
humanTotalTimeSpent
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
index 65b9ef45260..906bfcdf9cd 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
@@ -1,9 +1,7 @@
query mergeRequestTodos($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: mergeRequest(iid: $iid) {
- __typename
id
currentUserTodos(state: pending) {
nodes {
diff --git a/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql b/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql
index 721a71bef63..507221946fa 100644
--- a/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/project_issue_milestone.mutation.graphql
@@ -2,10 +2,8 @@ mutation projectIssueMilestoneMutation($fullPath: ID!, $iid: String!, $attribute
issuableSetAttribute: updateIssue(
input: { projectPath: $fullPath, iid: $iid, milestoneId: $attributeId }
) {
- __typename
errors
issuable: issue {
- __typename
id
attribute: milestone {
title
diff --git a/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
index c7f3adc9aca..bcb055d4f0f 100644
--- a/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
@@ -2,10 +2,8 @@
query projectIssueMilestone($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
attribute: milestone {
...MilestoneFragment
diff --git a/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
index d9eab18628d..b75c2138525 100644
--- a/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
@@ -2,7 +2,6 @@
query projectMilestones($fullPath: ID!, $title: String, $state: MilestoneStateEnum) {
workspace: project(fullPath: $fullPath) {
- __typename
id
attributes: milestones(
searchTitle: $title
diff --git a/app/assets/javascripts/sidebar/queries/remove_attention_request.mutation.graphql b/app/assets/javascripts/sidebar/queries/remove_attention_request.mutation.graphql
deleted file mode 100644
index d9b9c04fd63..00000000000
--- a/app/assets/javascripts/sidebar/queries/remove_attention_request.mutation.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-mutation mergeRequestRemoveAttentionRequest($projectPath: ID!, $iid: String!, $userId: UserID!) {
- mergeRequestRemoveAttentionRequest(
- input: { projectPath: $projectPath, iid: $iid, userId: $userId }
- ) {
- errors
- }
-}
diff --git a/app/assets/javascripts/sidebar/queries/request_attention.mutation.graphql b/app/assets/javascripts/sidebar/queries/request_attention.mutation.graphql
deleted file mode 100644
index 99a86e4fe5c..00000000000
--- a/app/assets/javascripts/sidebar/queries/request_attention.mutation.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-mutation mergeRequestRequestAttention($projectPath: ID!, $iid: String!, $userId: UserID!) {
- mergeRequestRequestAttention(input: { projectPath: $projectPath, iid: $iid, userId: $userId }) {
- errors
- }
-}
diff --git a/app/assets/javascripts/sidebar/queries/todo_create.mutation.graphql b/app/assets/javascripts/sidebar/queries/todo_create.mutation.graphql
index 4675db9153e..51d461989e4 100644
--- a/app/assets/javascripts/sidebar/queries/todo_create.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/todo_create.mutation.graphql
@@ -1,6 +1,5 @@
mutation issuableTodoCreate($input: TodoCreateInput!) {
todoMutation: todoCreate(input: $input) {
- __typename
todo {
id
}
diff --git a/app/assets/javascripts/sidebar/queries/todo_mark_done.mutation.graphql b/app/assets/javascripts/sidebar/queries/todo_mark_done.mutation.graphql
index 8253e5e82bc..4a91147c246 100644
--- a/app/assets/javascripts/sidebar/queries/todo_mark_done.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/todo_mark_done.mutation.graphql
@@ -1,6 +1,5 @@
mutation issuableTodoMarkDone($input: TodoMarkDoneInput!) {
todoMutation: todoMarkDone(input: $input) {
- __typename
todo {
id
}
diff --git a/app/assets/javascripts/sidebar/queries/update_merge_request_milestone.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_merge_request_milestone.mutation.graphql
index 938953ccfb2..2714d815bcd 100644
--- a/app/assets/javascripts/sidebar/queries/update_merge_request_milestone.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_merge_request_milestone.mutation.graphql
@@ -2,10 +2,8 @@ mutation mergeRequestSetMilestone($fullPath: ID!, $iid: String!, $attributeId: M
issuableSetAttribute: mergeRequestSetMilestone(
input: { projectPath: $fullPath, iid: $iid, milestoneId: $attributeId }
) {
- __typename
errors
issuable: mergeRequest {
- __typename
id
attribute: milestone {
title
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index 05268a5c89c..beacdeb559c 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -5,8 +5,6 @@ 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';
-import requestAttentionMutation from '../queries/request_attention.mutation.graphql';
-import removeAttentionRequestMutation from '../queries/remove_attention_request.mutation.graphql';
const queries = {
merge_request: sidebarDetailsMRQuery,
@@ -93,25 +91,4 @@ export default class SidebarService {
},
});
}
-
- requestAttention(userId) {
- return gqClient.mutate({
- mutation: requestAttentionMutation,
- variables: {
- userId: convertToGraphQLId(TYPE_USER, `${userId}`),
- projectPath: this.fullPath,
- iid: this.iid.toString(),
- },
- });
- }
- removeAttentionRequest(userId) {
- return gqClient.mutate({
- mutation: removeAttentionRequestMutation,
- variables: {
- userId: convertToGraphQLId(TYPE_USER, `${userId}`),
- projectPath: this.fullPath,
- iid: this.iid.toString(),
- },
- });
- }
}
diff --git a/app/assets/javascripts/sidebar/sidebar_bundle.js b/app/assets/javascripts/sidebar/sidebar_bundle.js
index 74ab65e4e04..1be670f7590 100644
--- a/app/assets/javascripts/sidebar/sidebar_bundle.js
+++ b/app/assets/javascripts/sidebar/sidebar_bundle.js
@@ -3,17 +3,7 @@ import Mediator from './sidebar_mediator';
export default (store) => {
const mediator = new Mediator(getSidebarOptions());
- mediator
- .fetch()
- .then(() => {
- if (window.gon?.features?.mrAttentionRequests) {
- return import('~/attention_requests');
- }
-
- return null;
- })
- .then((module) => module?.initSideNavPopover())
- .catch(() => {});
+ mediator.fetch();
mountSidebar(mediator, store);
};
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 4df00903ab6..f7c93b6903c 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,8 +1,7 @@
import Store from '~/sidebar/stores/sidebar_store';
import createFlash from '~/flash';
-import { __, sprintf } from '~/locale';
+import { __ } from '~/locale';
import toast from '~/vue_shared/plugins/global_toast';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import { visitUrl } from '../lib/utils/url_utility';
import Service from './services/sidebar_service';
@@ -42,7 +41,6 @@ export default class SidebarMediator {
const data = { assignee_ids: assignees };
try {
- const { currentUserHasAttention } = this.store;
const res = await this.service.update(field, data);
this.store.overwrite('assignees', res.data.assignees);
@@ -51,10 +49,6 @@ export default class SidebarMediator {
this.store.overwrite('reviewers', res.data.reviewers);
}
- if (currentUserHasAttention && this.store.isAddingAssignee) {
- toast(__('Assigned user(s). Your attention request was removed.'));
- }
-
return Promise.resolve(res);
} catch (e) {
return Promise.reject(e);
@@ -70,16 +64,11 @@ export default class SidebarMediator {
const data = { reviewer_ids: reviewers };
try {
- const { currentUserHasAttention } = this.store;
const res = await this.service.update(field, data);
this.store.overwrite('reviewers', res.data.reviewers);
this.store.overwrite('assignees', res.data.assignees);
- if (currentUserHasAttention && this.store.isAddingAssignee) {
- toast(__('Requested review. Your attention request was removed.'));
- }
-
return Promise.resolve(res);
} catch (e) {
return Promise.reject();
@@ -97,80 +86,6 @@ export default class SidebarMediator {
.catch(() => callback(userId, false));
}
- removeCurrentUserAttentionRequested() {
- const currentUserId = gon.current_user_id;
-
- const currentUserReviewer = this.store.findReviewer({ id: currentUserId });
- const currentUserAssignee = this.store.findAssignee({ id: currentUserId });
-
- if (currentUserReviewer?.attention_requested || currentUserAssignee?.attention_requested) {
- // Update current users attention_requested state
- this.store.updateReviewer(currentUserId, 'attention_requested');
- this.store.updateAssignee(currentUserId, 'attention_requested');
- }
- }
-
- async toggleAttentionRequested(type, { user, callback, direction }) {
- const mutations = {
- add: (id) => this.service.requestAttention(id),
- remove: (id) => this.service.removeAttentionRequest(id),
- };
-
- try {
- const isReviewer = type === 'reviewer';
- const reviewerOrAssignee = isReviewer
- ? this.store.findReviewer(user)
- : this.store.findAssignee(user);
-
- await mutations[direction]?.(user.id);
-
- if (reviewerOrAssignee.attention_requested) {
- toast(
- sprintf(__('Removed attention request from @%{username}'), {
- username: user.username,
- }),
- );
- } else {
- const currentUserId = gon.current_user_id;
- const { currentUserHasAttention } = this.store;
-
- if (currentUserId !== user.id) {
- this.removeCurrentUserAttentionRequested();
- }
-
- toast(
- currentUserHasAttention && currentUserId !== user.id
- ? sprintf(
- __(
- 'Requested attention from @%{username}. Your own attention request was removed.',
- ),
- { username: user.username },
- )
- : sprintf(__('Requested attention from @%{username}'), { username: user.username }),
- );
- }
-
- this.store.updateReviewer(user.id, 'attention_requested');
- this.store.updateAssignee(user.id, 'attention_requested');
-
- refreshUserMergeRequestCounts();
- callback();
- } catch (error) {
- callback();
- createFlash({
- message: sprintf(__('Updating the attention request for %{username} failed.'), {
- username: user.username,
- }),
- error,
- captureError: true,
- actionConfig: {
- title: __('Try again'),
- clickHandler: () => this.toggleAttentionRequired(type, { user, callback, direction }),
- },
- });
- }
- }
-
setMoveToProjectId(projectId) {
this.store.setMoveToProjectId(projectId);
}
diff --git a/app/assets/javascripts/sidebar/stores/sidebar_store.js b/app/assets/javascripts/sidebar/stores/sidebar_store.js
index 971e2a15c68..e2581a8f30e 100644
--- a/app/assets/javascripts/sidebar/stores/sidebar_store.js
+++ b/app/assets/javascripts/sidebar/stores/sidebar_store.js
@@ -19,9 +19,7 @@ export default class SidebarStore {
this.humanTimeSpent = '';
this.timeTrackingLimitToHours = timeTrackingLimitToHours;
this.assignees = [];
- this.addingAssignees = [];
this.reviewers = [];
- this.addingReviewers = [];
this.isFetching = {
assignees: true,
reviewers: true,
@@ -77,20 +75,12 @@ export default class SidebarStore {
if (!this.findAssignee(assignee)) {
this.changing = true;
this.assignees.push(assignee);
-
- if (assignee.id !== this.currentUser.id) {
- this.addingAssignees.push(assignee.id);
- }
}
}
addReviewer(reviewer) {
if (!this.findReviewer(reviewer)) {
this.reviewers.push(reviewer);
-
- if (reviewer.id !== this.currentUser.id) {
- this.addingReviewers.push(reviewer.id);
- }
}
}
@@ -126,14 +116,12 @@ export default class SidebarStore {
if (assignee) {
this.changing = true;
this.assignees = this.assignees.filter(({ id }) => id !== assignee.id);
- this.addingAssignees = this.addingAssignees.filter(({ id }) => id !== assignee.id);
}
}
removeReviewer(reviewer) {
if (reviewer) {
this.reviewers = this.reviewers.filter(({ id }) => id !== reviewer.id);
- this.addingReviewers = this.addingReviewers.filter(({ id }) => id !== reviewer.id);
}
}
@@ -161,26 +149,4 @@ export default class SidebarStore {
setMoveToProjectId(moveToProjectId) {
this.moveToProjectId = moveToProjectId;
}
-
- get currentUserHasAttention() {
- if (!window.gon?.features?.mrAttentionRequests || !this.isMergeRequest) return false;
-
- const currentUserId = this.currentUser.id;
- const currentUserReviewer = this.findReviewer({ id: currentUserId });
- const currentUserAssignee = this.findAssignee({ id: currentUserId });
-
- return currentUserReviewer?.attention_requested || currentUserAssignee?.attention_requested;
- }
-
- get isAddingAssignee() {
- return this.addingAssignees.length > 0;
- }
-
- get isAddingReviewer() {
- return this.addingReviewers.length > 0;
- }
-
- get isMergeRequest() {
- return this.issuableType === 'merge_request';
- }
}
diff --git a/app/assets/javascripts/snippets/fragments/snippet_base.fragment.graphql b/app/assets/javascripts/snippets/fragments/snippet_base.fragment.graphql
deleted file mode 100644
index d75b4011d1c..00000000000
--- a/app/assets/javascripts/snippets/fragments/snippet_base.fragment.graphql
+++ /dev/null
@@ -1,35 +0,0 @@
-#import '~/graphql_shared/fragments/blobviewer.fragment.graphql'
-
-fragment SnippetBase on Snippet {
- id
- title
- description
- descriptionHtml
- createdAt
- updatedAt
- visibilityLevel
- webUrl
- httpUrlToRepo
- sshUrlToRepo
- blobs {
- nodes {
- binary
- name
- path
- rawPath
- size
- externalStorage
- renderedAsText
- simpleViewer {
- ...BlobViewer
- }
- richViewer {
- ...BlobViewer
- }
- }
- }
- userPermissions {
- adminSnippet
- updateSnippet
- }
-}
diff --git a/app/assets/javascripts/surveys/merge_request_experience/app.js b/app/assets/javascripts/surveys/merge_request_experience/app.js
index ea5d8aef3c5..50b1c2c3f39 100644
--- a/app/assets/javascripts/surveys/merge_request_experience/app.js
+++ b/app/assets/javascripts/surveys/merge_request_experience/app.js
@@ -8,12 +8,17 @@ Vue.use(Translate);
Vue.use(VueApollo);
export const startMrSurveyApp = () => {
+ const mountEl = document.querySelector('#js-mr-experience-survey');
+ if (!mountEl) return;
+
let channel = null;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
+ const { accountAge } = mountEl.dataset;
+
const app = new Vue({
apolloProvider,
data() {
@@ -24,6 +29,9 @@ export const startMrSurveyApp = () => {
render(h) {
if (this.hidden) return null;
return h(MergeRequestExperienceSurveyApp, {
+ props: {
+ accountAge: Number(accountAge),
+ },
on: {
close: () => {
channel?.postMessage('close');
@@ -37,7 +45,7 @@ export const startMrSurveyApp = () => {
},
});
- app.$mount('#js-mr-experience-survey');
+ app.$mount(mountEl);
if (window.BroadcastChannel) {
channel = new BroadcastChannel('mr_survey');
diff --git a/app/assets/javascripts/surveys/merge_request_experience/app.vue b/app/assets/javascripts/surveys/merge_request_experience/app.vue
index 85eed6ae82a..4e4ef49b1c6 100644
--- a/app/assets/javascripts/surveys/merge_request_experience/app.vue
+++ b/app/assets/javascripts/surveys/merge_request_experience/app.vue
@@ -32,6 +32,12 @@ export default {
tooltip: GlTooltipDirective,
},
mixins: [Tracking.mixin()],
+ props: {
+ accountAge: {
+ type: Number,
+ required: true,
+ },
+ },
i18n: {
survey: s__('MrSurvey|Merge request experience survey'),
close: __('Close'),
@@ -68,6 +74,9 @@ export default {
this.track('survey:mr_experience', {
label: this.step.label,
value: event,
+ extra: {
+ accountAge: this.accountAge,
+ },
});
this.stepIndex += 1;
if (!this.step) {
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index 79a30340856..6e72d95c8e6 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -62,13 +62,21 @@ export default class TaskList {
.prop('disabled', true);
}
+ updateInapplicableTaskListItems(e) {
+ this.getTaskListTarget(e)
+ .find('.task-list-item-checkbox[data-inapplicable]')
+ .prop('disabled', true);
+ }
+
disableTaskListItems(e) {
this.getTaskListTarget(e).taskList('disable');
+ this.updateInapplicableTaskListItems();
}
enableTaskListItems(e) {
this.getTaskListTarget(e).taskList('enable');
this.disableNonMarkdownTaskListItems(e);
+ this.updateInapplicableTaskListItems(e);
}
enable() {
diff --git a/app/assets/javascripts/test_utils/index.js b/app/assets/javascripts/test_utils/index.js
index 2727485fb95..369cf9714e8 100644
--- a/app/assets/javascripts/test_utils/index.js
+++ b/app/assets/javascripts/test_utils/index.js
@@ -1,8 +1,10 @@
+import { editor } from 'monaco-editor';
import { Sortable } from 'sortablejs';
import simulateDrag from './simulate_drag';
import simulateInput from './simulate_input';
// Export to global space for rspec to use
+window.localMonaco = editor;
window.simulateDrag = simulateDrag;
window.simulateInput = simulateInput;
window.Sortable = Sortable;
diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js
index 3356cada58a..c2892fb8dac 100644
--- a/app/assets/javascripts/user_popovers.js
+++ b/app/assets/javascripts/user_popovers.js
@@ -131,7 +131,9 @@ const lazyLaunchPopover = debounce((mountPopover, event) => {
let hasAddedLazyPopovers = false;
export default function addPopovers(mountPopover = (instance) => instance.$mount()) {
- if (!hasAddedLazyPopovers) {
+ // The web request fails for anonymous users so we don't want to show the popover when the user is not signed in.
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/351395#note_1039341458
+ if (window.gon?.current_user_id && !hasAddedLazyPopovers) {
document.addEventListener('mouseover', (event) => lazyLaunchPopover(mountPopover, event));
hasAddedLazyPopovers = true;
}
diff --git a/app/assets/javascripts/visibility_level/constants.js b/app/assets/javascripts/visibility_level/constants.js
new file mode 100644
index 00000000000..65f0eceae55
--- /dev/null
+++ b/app/assets/javascripts/visibility_level/constants.js
@@ -0,0 +1,10 @@
+export const VISIBILITY_LEVEL_PRIVATE = 'private';
+export const VISIBILITY_LEVEL_INTERNAL = 'internal';
+export const VISIBILITY_LEVEL_PUBLIC = 'public';
+
+// Matches `lib/gitlab/visibility_level.rb`
+export const VISIBILITY_LEVELS_ENUM = {
+ [VISIBILITY_LEVEL_PRIVATE]: 0,
+ [VISIBILITY_LEVEL_INTERNAL]: 10,
+ [VISIBILITY_LEVEL_PUBLIC]: 20,
+};
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
new file mode 100644
index 00000000000..38f40e8a3c8
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
@@ -0,0 +1,124 @@
+<script>
+import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, __ } from '~/locale';
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ widget: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ tertiaryButtons: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ data: () => {
+ return {
+ timeout: null,
+ updatingTooltip: false,
+ };
+ },
+ computed: {
+ dropdownLabel() {
+ if (!this.widget) return undefined;
+
+ return sprintf(__('%{widget} options'), { widget: this.widget });
+ },
+ },
+ methods: {
+ onClickAction(action) {
+ this.$emit('clickedAction', action);
+
+ if (action.onClick) {
+ action.onClick();
+ }
+
+ if (action.tooltipOnClick) {
+ this.updatingTooltip = true;
+ this.$root.$emit('bv::show::tooltip', action.id);
+
+ clearTimeout(this.timeout);
+
+ this.timeout = setTimeout(() => {
+ this.updatingTooltip = false;
+ this.$root.$emit('bv::hide::tooltip', action.id);
+ }, 1000);
+ }
+ },
+ setTooltip(btn) {
+ if (this.updatingTooltip && btn.tooltipOnClick) {
+ return btn.tooltipOnClick;
+ }
+
+ return btn.tooltipText;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-dropdown
+ v-if="tertiaryButtons.length"
+ :text="dropdownLabel"
+ icon="ellipsis_v"
+ no-caret
+ category="tertiary"
+ right
+ lazy
+ text-sr-only
+ size="small"
+ toggle-class="gl-p-2!"
+ class="gl-display-block gl-md-display-none!"
+ >
+ <gl-dropdown-item
+ v-for="(btn, index) in tertiaryButtons"
+ :key="index"
+ :href="btn.href"
+ :target="btn.target"
+ :data-clipboard-text="btn.dataClipboardText"
+ :data-method="btn.dataMethod"
+ @click="onClickAction(btn)"
+ >
+ {{ btn.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <template v-if="tertiaryButtons.length">
+ <gl-button
+ v-for="(btn, index) in tertiaryButtons"
+ :id="btn.id"
+ :key="index"
+ v-gl-tooltip.hover
+ :title="setTooltip(btn)"
+ :href="btn.href"
+ :target="btn.target"
+ :class="[{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }, btn.class]"
+ :data-clipboard-text="btn.dataClipboardText"
+ :data-qa-selector="btn.dataQaSelector"
+ :data-method="btn.dataMethod"
+ :icon="btn.icon"
+ :data-testid="btn.testId || 'extension-actions-button'"
+ :variant="btn.variant || 'confirm'"
+ :loading="btn.loading"
+ :disabled="btn.loading"
+ category="tertiary"
+ size="small"
+ class="gl-display-none gl-md-display-block gl-float-left"
+ @click="onClickAction(btn)"
+ >
+ {{ btn.text }}
+ </gl-button>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
index 437d035fbf5..254b280bf14 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
@@ -2,9 +2,9 @@
import { GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { n__, s__ } from '~/locale';
+import { n__, s__, sprintf } from '~/locale';
-const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
+const mergeCommitCount = s__('mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit');
export default {
components: {
@@ -49,40 +49,45 @@ export default {
return escape(this.targetBranch);
},
commitsCountMessage() {
- return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
+ const count = this.isSquashEnabled ? 1 : this.commitsCount;
+
+ return sprintf(
+ n__(
+ '%{strongStart}%{count}%{strongEnd} commit',
+ '%{strongStart}%{count}%{strongEnd} commits',
+ count,
+ ),
+ { count },
+ );
},
message() {
- if (this.glFeatures.restructuredMrWidget) {
- if (this.state === 'closed') {
- return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.');
- } else if (this.isMerged) {
- return s__(
- 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.',
- );
- }
-
- return this.isFastForwardEnabled
- ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
- : s__(
- 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.',
- );
+ if (this.state === 'closed') {
+ return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.');
+ } else if (this.isMerged) {
+ return s__(
+ 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.',
+ );
}
return this.isFastForwardEnabled
- ? s__('mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}.')
+ ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
: s__(
- 'mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}.',
+ 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.',
);
},
- textDecorativeComponent() {
- return this.glFeatures.restructuredMrWidget ? 'span' : 'strong';
- },
squashCommitMessage() {
if (this.isMerged) {
- return s__('mergedCommitsAdded|(commits were squashed)');
+ return s__('mergedCommitsAdded| (commits were squashed)');
}
- return n__('(squashes %d commit)', '(squashes %d commits)', this.commitsCount);
+ return sprintf(
+ n__(
+ ' (squashes %{strongStart}%{count}%{strongEnd} commit)',
+ ' (squashes %{strongStart}%{count}%{strongEnd} commits)',
+ this.commitsCount,
+ ),
+ { count: this.commitsCount },
+ );
},
},
mergeCommitCount,
@@ -93,25 +98,33 @@ export default {
<span>
<gl-sprintf :message="message">
<template #commitCount>
- <component :is="textDecorativeComponent" class="commits-count-message">{{
- commitsCountMessage
- }}</component>
+ <gl-sprintf :message="commitsCountMessage">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
</template>
<template #mergeCommitCount>
- <component :is="textDecorativeComponent">{{ $options.mergeCommitCount }}</component>
+ <gl-sprintf :message="$options.mergeCommitCount">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
</template>
<template #targetBranch>
- <span class="label-branch">{{ targetBranchEscaped }}</span>
+ <span class="label-branch gl-font-weight-bold">{{ targetBranchEscaped }}</span>
</template>
<template #squashedCommits>
- <template v-if="glFeatures.restructuredMrWidget && isSquashEnabled">
- {{ squashCommitMessage }}</template
- ></template
- >
+ <template v-if="isSquashEnabled">
+ <gl-sprintf :message="squashCommitMessage">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
+ </template>
+ </template>
<template #mergeCommitSha>
- <template v-if="glFeatures.restructuredMrWidget"
- ><span class="label-branch">{{ mergeCommitSha }}</span></template
- >
+ <span class="label-branch">{{ mergeCommitSha }}</span>
</template>
</gl-sprintf>
</span>
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 4163d195e0f..f782c28ea19 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
@@ -4,9 +4,6 @@ import createFlash from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__, __ } from '~/locale';
-import sidebarEventHub from '~/sidebar/event_hub';
-import showToast from '~/vue_shared/plugins/global_toast';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
import eventHub from '../../event_hub';
import approvalsMixin from '../../mixins/approvals';
import MrWidgetContainer from '../mr_widget_container.vue';
@@ -192,16 +189,8 @@ export default {
.then((data) => {
this.mr.setApprovals(data);
- if (
- this.glFeatures.mrAttentionRequests &&
- SidebarMediator.singleton?.store.currentUserHasAttention
- ) {
- showToast(__('Approved. Your attention request was removed.'));
- }
-
eventHub.$emit('MRWidgetUpdateRequested');
eventHub.$emit('ApprovalUpdated');
- sidebarEventHub.$emit('removeCurrentUserAttentionRequested');
this.$emit('updated');
})
.catch(errFn)
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
index bb1837399ed..1256b3a8e52 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
@@ -80,22 +80,26 @@ export default {
},
computeGraphData(metrics, deploymentTime) {
this.loadingMetrics = false;
- const { memory_before, memory_after, memory_values } = metrics;
+ const {
+ memory_before: memoryBefore,
+ memory_after: memoryAfter,
+ memory_values: memoryValues,
+ } = metrics;
// Both `memory_before` and `memory_after` objects
// have peculiar structure where accessing only a specific
// index yeilds correct value that we can use to show memory delta.
- if (memory_before.length > 0) {
- this.memoryFrom = this.getMegabytes(memory_before[0].value[1]);
+ if (memoryBefore.length > 0) {
+ this.memoryFrom = this.getMegabytes(memoryBefore[0].value[1]);
}
- if (memory_after.length > 0) {
- this.memoryTo = this.getMegabytes(memory_after[0].value[1]);
+ if (memoryAfter.length > 0) {
+ this.memoryTo = this.getMegabytes(memoryAfter[0].value[1]);
}
- if (memory_values.length > 0) {
+ if (memoryValues.length > 0) {
this.hasMetrics = true;
- this.memoryMetrics = memory_values[0].values;
+ this.memoryMetrics = memoryValues[0].values;
this.deploymentTime = deploymentTime;
}
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md
new file mode 100644
index 00000000000..45ebafec8bf
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md
@@ -0,0 +1 @@
+Please see [the Widget Extensions documentation](development/merge_request_concepts/widget_extensions.md) for necessary information regarding development of new MR Widgets.
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
deleted file mode 100644
index b76d5d90ead..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-<script>
-import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui';
-import { sprintf, __ } from '~/locale';
-
-export default {
- components: {
- GlButton,
- GlDropdown,
- GlDropdownItem,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- widget: {
- type: String,
- required: true,
- },
- tertiaryButtons: {
- type: Array,
- required: false,
- default: () => [],
- },
- },
- data: () => {
- return {
- timeout: null,
- updatingTooltip: false,
- };
- },
- computed: {
- dropdownLabel() {
- return sprintf(__('%{widget} options'), { widget: this.widget });
- },
- },
- methods: {
- onClickAction(action) {
- this.$emit('clickedAction', action);
-
- if (action.onClick) {
- action.onClick();
- }
-
- if (action.tooltipOnClick) {
- this.updatingTooltip = true;
- this.$root.$emit('bv::show::tooltip', action.id);
-
- clearTimeout(this.timeout);
-
- this.timeout = setTimeout(() => {
- this.updatingTooltip = false;
- this.$root.$emit('bv::hide::tooltip', action.id);
- }, 1000);
- }
- },
- setTooltip(btn) {
- if (this.updatingTooltip && btn.tooltipOnClick) {
- return btn.tooltipOnClick;
- }
-
- return btn.tooltipText;
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-dropdown
- v-if="tertiaryButtons.length"
- :text="dropdownLabel"
- icon="ellipsis_v"
- no-caret
- category="tertiary"
- right
- lazy
- text-sr-only
- size="small"
- toggle-class="gl-p-2!"
- class="gl-display-block gl-md-display-none!"
- >
- <gl-dropdown-item
- v-for="(btn, index) in tertiaryButtons"
- :key="index"
- :href="btn.href"
- :target="btn.target"
- :data-clipboard-text="btn.dataClipboardText"
- @click="onClickAction(btn)"
- >
- {{ btn.text }}
- </gl-dropdown-item>
- </gl-dropdown>
- <template v-if="tertiaryButtons.length">
- <gl-button
- v-for="(btn, index) in tertiaryButtons"
- :id="btn.id"
- :key="index"
- v-gl-tooltip.hover
- :title="setTooltip(btn)"
- :href="btn.href"
- :target="btn.target"
- :class="{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }"
- :data-clipboard-text="btn.dataClipboardText"
- :icon="btn.icon"
- :data-testid="btn.testId || 'extension-actions-button'"
- :variant="btn.variant || 'confirm'"
- category="tertiary"
- size="small"
- class="gl-display-none gl-md-display-block gl-float-left"
- @click="onClickAction(btn)"
- >
- {{ btn.text }}
- </gl-button>
- </template>
- </div>
-</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 410331004e4..414c5bf9691 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
@@ -12,8 +12,8 @@ import { sprintf, s__, __ } from '~/locale';
import Poll from '~/lib/utils/poll';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
+import Actions from '../action_buttons.vue';
import StatusIcon from './status_icon.vue';
-import Actions from './actions.vue';
import ChildContent from './child_content.vue';
import { createTelemetryHub } from './telemetry';
import { generateText } from './utils';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
index 38f83a61b30..1eccc7de660 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
@@ -1,7 +1,7 @@
<script>
import { GlBadge, GlLink, GlSafeHtmlDirective, GlModalDirective } from '@gitlab/ui';
+import Actions from '../action_buttons.vue';
import StatusIcon from './status_icon.vue';
-import Actions from './actions.vue';
import { generateText } from './utils';
export default {
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 b551cd2fd60..bc84459e298 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
@@ -34,6 +34,36 @@ const nonStandardEvents = {
},
counter: {},
},
+ metrics: {
+ uniqueUser: {
+ expand: ['i_testing_metrics_report_widget_total'],
+ },
+ counter: {},
+ },
+ browserPerformance: {
+ uniqueUser: {
+ expand: ['i_testing_web_performance_widget_total'],
+ },
+ counter: {},
+ },
+ licenseCompliance: {
+ uniqueUser: {
+ expand: ['i_testing_license_compliance_widget_total'],
+ },
+ counter: {},
+ },
+ loadPerformance: {
+ uniqueUser: {
+ expand: ['i_testing_load_performance_widget_total'],
+ },
+ counter: {},
+ },
+ statusChecks: {
+ uniqueUser: {
+ expand: ['i_testing_status_checks_widget'],
+ },
+ counter: {},
+ },
};
function combineDeepArray(path, ...objects) {
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 913aa0e1e34..94a1b805b99 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,7 +1,6 @@
<script>
-import { GlSafeHtmlDirective as SafeHtml, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlSafeHtmlDirective as SafeHtml, GlLink } from '@gitlab/ui';
import { s__, n__ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'MRWidgetRelatedLinks',
@@ -10,9 +9,7 @@ export default {
},
components: {
GlLink,
- GlSprintf,
},
- mixins: [glFeatureFlagMixin()],
props: {
relatedLinks: {
type: Object,
@@ -67,42 +64,21 @@ export default {
</script>
<template>
<section>
- <p
- v-if="relatedLinks.closing"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
+ <p v-if="relatedLinks.closing" class="gl-display-inline gl-m-0">
{{ closesText }}
<span v-safe-html="relatedLinks.closing"></span>
</p>
- <p
- v-if="relatedLinks.mentioned"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
- <span v-if="relatedLinks.closing && glFeatures.restructuredMrWidget">&middot;</span>
+ <p v-if="relatedLinks.mentioned" class="gl-display-inline gl-m-0">
+ <span v-if="relatedLinks.closing">&middot;</span>
{{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }}
<span v-safe-html="relatedLinks.mentioned"></span>
</p>
- <p
- v-if="shouldShowAssignToMeLink"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
+ <p v-if="shouldShowAssignToMeLink" class="gl-display-inline gl-m-0">
<span>
<gl-link rel="nofollow" data-method="post" :href="relatedLinks.assignToMe">{{
assignIssueText
}}</gl-link>
</span>
</p>
- <div
- v-if="divergedCommitsCount > 0 && !glFeatures.restructuredMrWidget"
- class="diverged-commits-count"
- >
- <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
- <template #link>
- <gl-link :href="targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
index 7ff1eb6e73a..5b8acb4ebf8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
@@ -1,25 +1,17 @@
<script>
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { GlLoadingIcon } from '@gitlab/ui';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
export default {
components: {
ciIcon,
- GlButton,
GlLoadingIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
status: {
type: String,
required: true,
},
- showDisabledButton: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
isLoading() {
@@ -42,15 +34,5 @@ export default {
</div>
<ci-icon v-else :status="statusObj" :size="24" />
</div>
-
- <gl-button
- v-if="!glFeatures.restructuredMrWidget && showDisabledButton"
- category="primary"
- variant="confirm"
- data-testid="disabled-merge-button"
- :disabled="true"
- >
- {{ s__('mrWidget|Merge') }}
- </gl-button>
</div>
</template>
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
new file mode 100644
index 00000000000..4a5a03fb598
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
@@ -0,0 +1,55 @@
+<script>
+import StatusIcon from './mr_widget_status_icon.vue';
+import Actions from './action_buttons.vue';
+
+export default {
+ components: {
+ StatusIcon,
+ Actions,
+ },
+ props: {
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ status: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ actions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="mr-widget-body media">
+ <div v-if="isLoading" class="gl-w-full mr-conflict-loader">
+ <slot name="loading"></slot>
+ </div>
+ <template v-else>
+ <slot name="icon">
+ <status-icon :status="status" />
+ </slot>
+ <div
+ :class="{ 'gl-display-flex': actions.length, 'gl-md-display-flex': !actions.length }"
+ class="media-body"
+ >
+ <slot></slot>
+ <div
+ :class="{ 'gl-flex-direction-column-reverse': !actions.length }"
+ class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto gl-mt-1"
+ >
+ <slot name="actions">
+ <actions v-if="actions.length" :tertiary-buttons="actions" />
+ </slot>
+ </div>
+ </div>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
index 18761d04c2e..515a7cf51a1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
@@ -1,8 +1,5 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
export default {
- mixins: [glFeatureFlagMixin()],
props: {
value: {
type: String,
@@ -23,10 +20,7 @@ export default {
<template>
<li>
<div class="commit-message-editor">
- <div
- :class="{ 'gl-mb-3': glFeatures.restructuredMrWidget }"
- class="d-flex flex-wrap align-items-center justify-content-between"
- >
+ <div class="d-flex flex-wrap align-items-center justify-content-between gl-mb-3">
<label class="col-form-label" :for="inputId">
<strong>{{ label }}</strong>
</label>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
index 071920856a8..f74826f95d3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -7,7 +6,6 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
};
</script>
<template>
@@ -16,7 +14,7 @@ export default {
<status-icon status="warning" show-disabled-button />
</div>
<div class="media-body">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }}
</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index aabbeac564a..690acc9a6dc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -1,15 +1,15 @@
<script>
-import { GlSkeletonLoader, GlIcon, GlButton, GlSprintf } from '@gitlab/ui';
+import { GlSkeletonLoader, GlIcon, 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 { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { AUTO_MERGE_STRATEGIES } from '../../constants';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MrWidgetAuthor from '../mr_widget_author.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetAutoMergeEnabled',
@@ -29,8 +29,8 @@ export default {
MrWidgetAuthor,
GlSkeletonLoader,
GlIcon,
- GlButton,
GlSprintf,
+ StateContainer,
},
mixins: [autoMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
@@ -78,18 +78,25 @@ export default {
autoMergeStrategy() {
return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy;
},
- canRemoveSourceBranch() {
- const { currentUserId } = this.mr;
- const mergeUserId = this.glFeatures.mergeRequestWidgetGraphql
- ? getIdFromGraphQLId(this.state.mergeUser?.id)
- : this.mr.mergeUserId;
- const canRemoveSourceBranch = this.glFeatures.mergeRequestWidgetGraphql
- ? this.state.userPermissions.removeSourceBranch
- : this.mr.canRemoveSourceBranch;
+ actions() {
+ const actions = [];
- return (
- !this.shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId
- );
+ if (this.loading) {
+ return actions;
+ }
+
+ if (this.mr.canCancelAutomaticMerge) {
+ actions.push({
+ text: this.cancelButtonText,
+ loading: this.isCancellingAutoMerge,
+ dataQaSelector: 'cancel_auto_merge_button',
+ class: 'js-cancel-auto-merge',
+ testId: 'cancelAutomaticMergeButton',
+ onClick: () => this.cancelAutomaticMerge(),
+ });
+ }
+
+ return actions;
},
},
methods: {
@@ -144,56 +151,25 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <div v-if="loading" class="gl-w-full mr-conflict-loader">
+ <state-container status="scheduled" :is-loading="loading" :actions="actions">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="3" width="24" height="24" rx="4" />
<rect x="32" y="7" width="150" height="16" rx="4" />
<rect x="190" y="7" width="144" height="16" rx="4" />
</gl-skeleton-loader>
- </div>
- <template v-else>
+ </template>
+ <template v-if="!loading">
+ <h4 class="gl-mr-3" data-testid="statusText">
+ <gl-sprintf :message="statusText" data-testid="statusText">
+ <template #merge_author>
+ <mr-widget-author :author="mergeUser" />
+ </template>
+ </gl-sprintf>
+ </h4>
+ </template>
+ <template v-if="!loading" #icon>
<gl-icon name="status_scheduled" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
- <div class="media-body">
- <h4 class="gl-display-flex">
- <span class="gl-mr-3">
- <gl-sprintf :message="statusText" data-testid="statusText">
- <template #merge_author>
- <mr-widget-author :author="mergeUser" />
- </template>
- </gl-sprintf>
- </span>
- <gl-button
- v-if="mr.canCancelAutomaticMerge"
- :loading="isCancellingAutoMerge"
- size="small"
- class="js-cancel-auto-merge"
- data-qa-selector="cancel_auto_merge_button"
- data-testid="cancelAutomaticMergeButton"
- @click="cancelAutomaticMerge"
- >
- {{ cancelButtonText }}
- </gl-button>
- </h4>
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p v-if="shouldRemoveSourceBranch">
- {{ s__('mrWidget|Deletes the source branch') }}
- </p>
- <p v-else class="gl-display-flex">
- <span class="gl-mr-3">{{ s__('mrWidget|Does not delete the source branch') }}</span>
- <gl-button
- v-if="canRemoveSourceBranch"
- :loading="isRemovingSourceBranch"
- size="small"
- class="js-remove-source-branch"
- data-testid="removeSourceBranchButton"
- @click="removeSourceBranch"
- >
- {{ s__('mrWidget|Delete source branch') }}
- </gl-button>
- </p>
- </section>
- </div>
</template>
- </div>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
index 1a764d3d091..b0cda85f361 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
@@ -1,17 +1,15 @@
<script>
-import { GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import autoMergeFailedQuery from '../../queries/states/auto_merge_failed.query.graphql';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetAutoMergeFailed',
components: {
- statusIcon,
- GlLoadingIcon,
- GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -38,6 +36,17 @@ export default {
isRefreshing: false,
};
},
+ computed: {
+ actions() {
+ return [
+ {
+ text: s__('mrWidget|Refresh'),
+ loading: this.isRefreshing,
+ onClick: () => this.refreshWidget(),
+ },
+ ];
+ },
+ },
methods: {
refreshWidget() {
this.isRefreshing = true;
@@ -49,23 +58,10 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon status="warning" />
- <div class="media-body space-children gl-display-flex gl-flex-wrap gl-align-items-center">
- <span class="bold">
- <template v-if="mergeError">{{ mergeError }}</template>
- {{ s__('mrWidget|This merge request failed to be merged automatically') }}
- </span>
- <gl-button
- :disabled="isRefreshing"
- category="secondary"
- variant="default"
- size="small"
- @click="refreshWidget"
- >
- <gl-loading-icon v-if="isRefreshing" size="sm" :inline="true" />
- {{ s__('mrWidget|Refresh') }}
- </gl-button>
- </div>
- </div>
+ <state-container status="warning" :actions="actions">
+ <span class="bold gl-ml-0!">
+ <template v-if="mergeError">{{ mergeError }}</template>
+ {{ s__('mrWidget|This merge request failed to be merged automatically') }}
+ </span>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
index fd42fa0421f..e2d87d8d536 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -7,14 +6,13 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
};
</script>
<template>
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="loading" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{ s__('mrWidget|Checking if merge request can be merged…') }}
</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
index d50e52f5ac1..61f7d26f51e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -9,7 +8,6 @@ export default {
MrWidgetAuthorTime,
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
/* TODO: This is providing all store and service down when it
only needs metrics and targetBranch */
@@ -30,13 +28,6 @@ export default {
:date-title="mr.metrics.closedAt"
:date-readable="mr.metrics.readableClosedAt"
/>
-
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p>
- {{ s__('mrWidget|The changes were not merged into') }}
- <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
- </p>
- </section>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index def30dacf8a..8abd915b93e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -4,14 +4,14 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import userPermissionsQuery from '../../queries/permissions.query.graphql';
import conflictsStateQuery from '../../queries/states/conflicts.query.graphql';
-import StatusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetConflicts',
components: {
GlSkeletonLoader,
- StatusIcon,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -86,29 +86,23 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="true" status="warning" />
-
- <div v-if="isLoading" class="gl-ml-4 gl-w-full mr-conflict-loader">
+ <state-container status="warning" :is-loading="isLoading">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="7" width="150" height="16" rx="4" />
<rect x="158" y="7" width="84" height="16" rx="4" />
<rect x="250" y="7" width="84" height="16" rx="4" />
</gl-skeleton-loader>
- </div>
- <div v-else class="media-body space-children gl-display-flex gl-align-items-center">
- <span
- v-if="shouldBeRebased"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="bold"
- >
+ </template>
+ <template v-if="!isLoading">
+ <span v-if="shouldBeRebased" class="bold gl-ml-0! gl-text-body!">
{{
s__(`mrWidget|Merge blocked: fast-forward merge is not possible.
To merge this request, first rebase locally.`)
}}
</span>
<template v-else>
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="bold gl-ml-0! gl-text-body! gl-flex-grow-1 gl-w-full gl-md-w-auto gl-mr-2">
{{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }}
<span v-if="!canMerge">
{{
@@ -118,23 +112,30 @@ export default {
}}
</span>
</span>
- <gl-button
- v-if="showResolveButton"
- :href="mr.conflictResolutionPath"
- :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
- data-testid="resolve-conflicts-button"
- >
- {{ s__('mrWidget|Resolve conflicts') }}
- </gl-button>
- <gl-button
- v-if="canMerge"
- :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
- data-testid="merge-locally-button"
- class="js-check-out-modal-trigger"
- >
- {{ s__('mrWidget|Resolve locally') }}
- </gl-button>
</template>
- </div>
- </div>
+ </template>
+ <template v-if="!isLoading && !shouldBeRebased" #actions>
+ <gl-button
+ v-if="canMerge"
+ size="small"
+ variant="confirm"
+ category="secondary"
+ data-testid="merge-locally-button"
+ class="js-check-out-modal-trigger gl-align-self-start"
+ :class="{ 'gl-mr-2': showResolveButton }"
+ >
+ {{ s__('mrWidget|Resolve locally') }}
+ </gl-button>
+ <gl-button
+ v-if="showResolveButton"
+ :href="mr.conflictResolutionPath"
+ size="small"
+ variant="confirm"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start"
+ data-testid="resolve-conflicts-button"
+ >
+ {{ s__('mrWidget|Resolve conflicts') }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index 42e9261b82c..18103ac4a0e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -30,7 +30,7 @@ export default {
computed: {
mergeError() {
- const mergeError = this.mr.mergeError ? stripHtml(this.mr.mergeError, ' ').trim() : '';
+ const mergeError = this.prepareMergeError(this.mr.mergeError);
return sprintf(
s__('mrWidget|%{mergeError}.'),
@@ -76,6 +76,13 @@ export default {
this.refresh();
}
},
+ prepareMergeError(mergeError) {
+ return mergeError
+ ? stripHtml(mergeError, ' ')
+ .replace(/(\.$|\s+)/g, ' ')
+ .trim()
+ : '';
+ },
},
};
</script>
@@ -89,7 +96,9 @@ export default {
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- <span v-if="mr.mergeError" class="has-error-message"> {{ mergeError }} </span>
+ <span v-if="mr.mergeError" class="has-error-message" data-testid="merge-error">
+ {{ mergeError }}
+ </span>
<span v-else> {{ s__('mrWidget|Merge failed.') }} </span>
<span :class="{ 'has-custom-error': mr.mergeError }"> {{ timerText }} </span>
</span>
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 bf036f562ed..4416123cd51 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,15 +1,13 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLoadingIcon, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import api from '~/api';
import createFlash 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';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../../event_hub';
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetMerged',
@@ -19,11 +17,8 @@ export default {
components: {
MrWidgetAuthorTime,
GlIcon,
- ClipboardButton,
- GlLoadingIcon,
- GlButton,
+ StateContainer,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -78,6 +73,53 @@ export default {
cherryPickLabel() {
return s__('mrWidget|Cherry-pick');
},
+ actions() {
+ const actions = [];
+
+ if (this.mr.canRevertInCurrentMR) {
+ actions.push({
+ text: this.revertLabel,
+ tooltipText: this.revertTitle,
+ dataQaSelector: 'revert_button',
+ onClick: () => this.openRevertModal(),
+ });
+ } else if (this.mr.revertInForkPath) {
+ actions.push({
+ text: this.revertLabel,
+ tooltipText: this.revertTitle,
+ href: this.mr.revertInForkPath,
+ dataQaSelector: 'revert_button',
+ dataMethod: 'post',
+ });
+ }
+
+ if (this.mr.canCherryPickInCurrentMR) {
+ actions.push({
+ text: this.cherryPickLabel,
+ tooltipText: this.cherryPickTitle,
+ dataQaSelector: 'cherry_pick_button',
+ onClick: () => this.openCherryPickModal(),
+ });
+ } else if (this.mr.cherryPickInForkPath) {
+ actions.push({
+ text: this.cherryPickLabel,
+ tooltipText: this.cherryPickTitle,
+ href: this.mr.cherryPickInForkPath,
+ dataQaSelector: 'cherry_pick_button',
+ dataMethod: 'post',
+ });
+ }
+
+ if (this.shouldShowRemoveSourceBranch) {
+ actions.push({
+ text: s__('mrWidget|Delete source branch'),
+ class: 'js-remove-branch-button',
+ onClick: () => this.removeSourceBranch(),
+ });
+ }
+
+ return actions;
+ },
},
mounted() {
document.dispatchEvent(new CustomEvent('merged:UpdateActions'));
@@ -121,103 +163,15 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <gl-icon name="merge" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
- <div class="media-body">
- <div class="space-children">
- <mr-widget-author-time
- :action-text="s__('mrWidget|Merged by')"
- :author="mr.metrics.mergedBy"
- :date-title="mr.metrics.mergedAt"
- :date-readable="mr.metrics.readableMergedAt"
- />
- <gl-button
- v-if="mr.canRevertInCurrentMR"
- v-gl-tooltip.hover
- :title="revertTitle"
- size="small"
- category="secondary"
- data-qa-selector="revert_button"
- @click="openRevertModal"
- >
- {{ revertLabel }}
- </gl-button>
- <gl-button
- v-else-if="mr.revertInForkPath"
- v-gl-tooltip.hover
- :href="mr.revertInForkPath"
- :title="revertTitle"
- size="small"
- category="secondary"
- data-method="post"
- >
- {{ revertLabel }}
- </gl-button>
- <gl-button
- v-if="mr.canCherryPickInCurrentMR"
- v-gl-tooltip.hover
- :title="cherryPickTitle"
- size="small"
- data-qa-selector="cherry_pick_button"
- @click="openCherryPickModal"
- >
- {{ cherryPickLabel }}
- </gl-button>
- <gl-button
- v-else-if="mr.cherryPickInForkPath"
- v-gl-tooltip.hover
- :href="mr.cherryPickInForkPath"
- :title="cherryPickTitle"
- size="small"
- data-method="post"
- >
- {{ cherryPickLabel }}
- </gl-button>
- <gl-button
- v-if="shouldShowRemoveSourceBranch"
- :disabled="isMakingRequest"
- size="small"
- class="js-remove-branch-button"
- @click="removeSourceBranch"
- >
- {{ s__('mrWidget|Delete source branch') }}
- </gl-button>
- </div>
- <section
- v-if="!glFeatures.restructuredMrWidget"
- class="mr-info-list"
- data-qa-selector="merged_status_content"
- >
- <p>
- {{ s__('mrWidget|The changes were merged into') }}
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
- </span>
- <template v-if="mr.mergeCommitSha">
- with
- <a
- :href="mr.mergeCommitPath"
- class="commit-sha js-mr-merged-commit-sha"
- v-text="mr.shortMergeCommitSha"
- >
- </a>
- <clipboard-button
- :title="__('Copy commit SHA')"
- :text="mr.mergeCommitSha"
- css-class="js-mr-merged-copy-sha"
- category="tertiary"
- size="small"
- />
- </template>
- </p>
- <p v-if="mr.sourceBranchRemoved">
- {{ s__('mrWidget|The source branch has been deleted') }}
- </p>
- <p v-if="shouldShowSourceBranchRemoving">
- <gl-loading-icon size="sm" :inline="true" />
- <span> {{ s__('mrWidget|The source branch is being deleted') }} </span>
- </p>
- </section>
- </div>
- </div>
+ <state-container :actions="actions">
+ <template #icon>
+ <gl-icon name="merge" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
+ </template>
+ <mr-widget-author-time
+ :action-text="s__('mrWidget|Merged by')"
+ :author="mr.metrics.mergedBy"
+ :date-title="mr.metrics.mergedAt"
+ :date-readable="mr.metrics.readableMergedAt"
+ />
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
index b86ab69af3f..c7574a41bb8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
@@ -1,6 +1,5 @@
<script>
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import simplePoll from '~/lib/utils/simple_poll';
import MergeRequest from '~/merge_request';
import eventHub from '../../event_hub';
@@ -15,7 +14,6 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -90,14 +88,6 @@ export default {
{{ mergeStatus.message }}
<gl-emoji :data-name="mergeStatus.emoji" />
</h4>
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p>
- {{ s__('mrWidget|Merges changes into') }}
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
- </span>
- </p>
- </section>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
index cadbd9c28a9..659d12d1160 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
@@ -74,13 +74,7 @@ export default {
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span
- :class="{
- 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
- }"
- class="bold js-branch-text"
- data-testid="widget-content"
- >
+ <span class="gl-ml-0! gl-text-body! bold js-branch-text" data-testid="widget-content">
<gl-sprintf :message="warning">
<template #code="{ content }">
<code>{{ content }}</code>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
index 34c5a2ff2c8..e99ee59b877 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
@@ -14,7 +14,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{
s__(
`mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`,
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 59767eb2e6e..6c5fc916799 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
@@ -8,7 +8,7 @@ import simplePoll from '~/lib/utils/simple_poll';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import rebaseQuery from '../../queries/states/rebase.query.graphql';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetRebase',
@@ -25,9 +25,9 @@ export default {
},
},
components: {
- statusIcon,
GlSkeletonLoader,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
@@ -51,9 +51,6 @@ export default {
isLoading() {
return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
},
- showRebaseWithoutCi() {
- return this.glFeatures?.rebaseWithoutCiUi;
- },
rebaseInProgress() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.rebaseInProgress;
@@ -76,6 +73,10 @@ export default {
return this.mr.targetBranch;
},
status() {
+ if (this.isLoading) {
+ return undefined;
+ }
+
if (this.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
@@ -148,92 +149,70 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <div v-if="isLoading" class="gl-w-full mr-conflict-loader">
+ <state-container :status="status" :is-loading="isLoading">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="3" width="24" height="24" rx="4" />
<rect x="32" y="5" width="302" height="20" rx="4" />
</gl-skeleton-loader>
- </div>
- <template v-else>
- <status-icon :status="status" :show-disabled-button="showDisabledButton" />
-
- <div class="rebase-state-find-class-convention media media-body space-children">
+ </template>
+ <template v-if="!isLoading">
+ <span
+ v-if="rebaseInProgress || isMakingRequest"
+ class="gl-ml-0! gl-text-body! gl-font-weight-bold"
+ data-testid="rebase-message"
+ >{{ __('Rebase in progress') }}</span
+ >
+ <span
+ v-if="!rebaseInProgress && !canPushToSourceBranch"
+ class="gl-text-body! gl-font-weight-bold gl-ml-0!"
+ data-testid="rebase-message"
+ >{{ fastForwardMergeText }}</span
+ >
+ <div
+ v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
+ class="accept-merge-holder clearfix js-toggle-container media gl-md-display-flex gl-flex-wrap gl-flex-grow-1"
+ >
<span
- v-if="rebaseInProgress || isMakingRequest"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
+ v-if="!rebasingError"
+ class="gl-font-weight-bold gl-w-100 gl-md-w-auto gl-flex-grow-1 gl-ml-0! gl-text-body! gl-md-mr-3"
data-testid="rebase-message"
- >{{ __('Rebase in progress') }}</span
+ data-qa-selector="no_fast_forward_message_content"
+ >{{
+ __('Merge blocked: the source branch must be rebased onto the target branch.')
+ }}</span
>
<span
- v-if="!rebaseInProgress && !canPushToSourceBranch"
- :class="{ 'gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold gl-ml-0!"
+ v-else
+ class="gl-font-weight-bold danger gl-w-100 gl-md-w-auto gl-flex-grow-1 gl-md-mr-3"
data-testid="rebase-message"
- >{{ fastForwardMergeText }}</span
- >
- <div
- v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
- class="accept-merge-holder clearfix js-toggle-container accept-action media space-children gl-align-items-center"
+ >{{ rebasingError }}</span
>
- <gl-button
- v-if="!glFeatures.restructuredMrWidget"
- :loading="isMakingRequest"
- variant="confirm"
- data-qa-selector="mr_rebase_button"
- data-testid="standard-rebase-button"
- @click="rebase"
- >
- {{ __('Rebase') }}
- </gl-button>
- <gl-button
- v-if="!glFeatures.restructuredMrWidget && showRebaseWithoutCi"
- :loading="isMakingRequest"
- variant="confirm"
- category="secondary"
- data-testid="rebase-without-ci-button"
- @click="rebaseWithoutCi"
- >
- {{ __('Rebase without pipeline') }}
- </gl-button>
- <span
- v-if="!rebasingError"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
- data-testid="rebase-message"
- data-qa-selector="no_fast_forward_message_content"
- >{{
- __('Merge blocked: the source branch must be rebased onto the target branch.')
- }}</span
- >
- <span v-else class="gl-font-weight-bold danger" data-testid="rebase-message">{{
- rebasingError
- }}</span>
- <gl-button
- v-if="glFeatures.restructuredMrWidget"
- :loading="isMakingRequest"
- variant="confirm"
- size="small"
- data-qa-selector="mr_rebase_button"
- class="gl-ml-3!"
- @click="rebase"
- >
- {{ __('Rebase') }}
- </gl-button>
- <gl-button
- v-if="glFeatures.restructuredMrWidget && showRebaseWithoutCi"
- :loading="isMakingRequest"
- variant="confirm"
- size="small"
- category="secondary"
- data-testid="rebase-without-ci-button"
- @click="rebaseWithoutCi"
- >
- {{ __('Rebase without pipeline') }}
- </gl-button>
- </div>
</div>
</template>
- </div>
+ <template v-if="!isLoading" #actions>
+ <gl-button
+ :loading="isMakingRequest"
+ variant="confirm"
+ size="small"
+ category="secondary"
+ data-testid="rebase-without-ci-button"
+ class="gl-align-self-start gl-mr-2"
+ @click="rebaseWithoutCi"
+ >
+ {{ __('Rebase without pipeline') }}
+ </gl-button>
+ <gl-button
+ :loading="isMakingRequest"
+ variant="confirm"
+ size="small"
+ data-qa-selector="mr_rebase_button"
+ data-testid="standard-rebase-button"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start"
+ @click="rebase"
+ >
+ {{ __('Rebase') }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
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 d204befef58..d507e5f232b 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
@@ -1,7 +1,6 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -12,7 +11,6 @@ export default {
GlSprintf,
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
computed: {
troubleshootingDocsPath() {
return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' });
@@ -30,7 +28,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
<gl-sprintf :message="$options.i18n.failedMessage">
<template #link="{ content }">
<gl-link :href="troubleshootingDocsPath" target="_blank">
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 cf482410bef..d2c85b14999 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
@@ -31,12 +31,10 @@ import {
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store';
-import statusIcon from '../mr_widget_status_icon.vue';
import AddedCommitMessage from '../added_commit_message.vue';
import RelatedLinks from '../mr_widget_related_links.vue';
import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue';
-import CommitsHeader from './commits_header.vue';
import SquashBeforeMerge from './squash_before_merge.vue';
import MergeFailedPipelineConfirmationDialog from './merge_failed_pipeline_confirmation_dialog.vue';
@@ -96,9 +94,7 @@ export default {
},
},
components: {
- statusIcon,
SquashBeforeMerge,
- CommitsHeader,
CommitEdit,
CommitMessageDropdown,
GlIcon,
@@ -320,34 +316,27 @@ export default {
showDangerMessageForMergeTrain() {
return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed;
},
- restructuredWidgetShowMergeButtons() {
- if (this.glFeatures.restructuredMrWidget) {
- return (
- (this.isMergeAllowed || this.isAutoMergeAvailable) &&
- this.state.userPermissions.canMerge &&
- !this.mr.mergeOngoing &&
- !this.mr.autoMergeEnabled
- );
- }
-
- return true;
+ shouldShowMergeControls() {
+ return (
+ (this.isMergeAllowed || this.isAutoMergeAvailable) &&
+ (this.stateData.userPermissions?.canMerge || this.mr.canMerge) &&
+ !this.mr.mergeOngoing &&
+ !this.mr.autoMergeEnabled
+ );
},
sourceBranchDeletedText() {
- if (this.glFeatures.restructuredMrWidget) {
- if (this.removeSourceBranch) {
- return this.mr.state === 'merged'
- ? __('Deleted the source branch.')
- : __('Source branch will be deleted.');
- }
-
+ if (this.removeSourceBranch) {
return this.mr.state === 'merged'
- ? __('Did not delete the source branch.')
- : __('Source branch will not be deleted.');
+ ? __('Deleted the source branch.')
+ : __('Source branch will be deleted.');
}
- return this.removeSourceBranch
- ? __('Deletes the source branch.')
- : __('Does not delete the source branch.');
+ return this.mr.state === 'merged'
+ ? __('Did not delete the source branch.')
+ : __('Source branch will not be deleted.');
+ },
+ showMergeDetailsHeader() {
+ return ['readyToMerge'].indexOf(this.mr.state) >= 0;
},
},
mounted() {
@@ -525,10 +514,7 @@ export default {
<template>
<div
data-testid="ready_to_merge_state"
- :class="{
- 'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7 gl-rounded-bottom-left-base gl-rounded-bottom-right-base':
- glFeatures.restructuredMrWidget,
- }"
+ class="gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7 gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
>
<div v-if="loading" class="mr-widget-body">
<div class="gl-w-full mr-ready-to-merge-loader">
@@ -541,16 +527,10 @@ export default {
</div>
</div>
<template v-else>
- <div
- class="mr-widget-body media"
- :class="{
- 'mr-widget-body-line-height-1': glFeatures.restructuredMrWidget,
- }"
- >
- <status-icon v-if="!glFeatures.restructuredMrWidget" :status="iconClass" />
+ <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="restructuredWidgetShowMergeButtons" class="gl-align-self-start">
+ <gl-button-group v-if="shouldShowMergeControls" class="gl-align-self-start">
<gl-button
size="medium"
category="primary"
@@ -603,19 +583,14 @@ export default {
<merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
<div
v-if="shouldShowMergeControls"
- :class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }"
- class="gl-display-flex gl-align-items-center gl-flex-wrap"
+ 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="{
- 'gl-mx-3': !glFeatures.restructuredMrWidget,
- 'gl-mr-5': glFeatures.restructuredMrWidget,
- }"
- class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center"
+ class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
>
{{ __('Delete source branch') }}
</gl-form-checkbox>
@@ -626,16 +601,11 @@ export default {
v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly"
- :class="{
- 'gl-mx-3': !glFeatures.restructuredMrWidget,
- 'gl-mr-5': glFeatures.restructuredMrWidget,
- }"
+ class="gl-mr-5"
/>
<gl-form-checkbox
- v-if="
- glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)
- "
+ v-if="shouldShowSquashEdit || shouldShowMergeEdit"
v-model="editCommitMessage"
data-testid="widget_edit_commit_message"
class="gl-display-flex gl-align-items-center"
@@ -644,198 +614,113 @@ export default {
</gl-form-checkbox>
</div>
<div
- v-else-if="!glFeatures.restructuredMrWidget"
- class="bold js-resolve-mr-widget-items-message gl-ml-3"
+ v-if="editCommitMessage"
+ class="gl-w-full gl-order-n1"
+ data-testid="edit_commit_message"
>
- <div
- v-if="hasPipelineMustSucceedConflict"
- class="gl-display-flex gl-align-items-center"
- data-testid="pipeline-succeed-conflict"
- >
- <gl-sprintf :message="pipelineMustSucceedConflictText" />
- <gl-link
- :href="mr.pipelineMustSucceedDocsPath"
- target="_blank"
- class="gl-display-flex gl-ml-2"
+ <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-icon name="question" />
- </gl-link>
- </div>
- <gl-sprintf v-else :message="mergeDisabledText" />
+ <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>
- <template v-if="glFeatures.restructuredMrWidget">
- <div
- v-if="editCommitMessage"
- class="gl-w-full gl-order-n1"
- data-testid="edit_commit_message"
- >
- <ul
- :class="{
- 'content-list': !glFeatures.restructuredMrWidget,
- 'gl-list-style-none gl-p-0 gl-pt-4': glFeatures.restructuredMrWidget,
- }"
- class="border-top commits-list flex-list"
- >
- <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"
+ <div
+ v-if="!shouldShowMergeControls"
+ class="gl-w-full gl-order-n1 mr-widget-merge-details"
+ data-qa-selector="merged_status_content"
+ >
+ <p v-if="showMergeDetailsHeader" class="gl-mb-3 gl-text-gray-900">
+ {{ __('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')"
>
- <template #header>
- <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ <template #link>
+ <gl-link :href="mr.targetBranchPath">{{
+ n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
+ }}</gl-link>
</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-sprintf>
+ </li>
+ <li class="gl-line-height-normal">
+ <added-commit-message
+ :state="mr.state"
+ :merge-commit-sha="mr.shortMergeCommitSha"
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
/>
- <li class="gl-m-0! gl-p-0!">
- <p class="form-text text-muted">
- <gl-sprintf :message="commitTemplateHintText">
- <template #link="{ content }">
- <gl-link
- :href="commitTemplateHelpPage"
- class="inline-link"
- target="_blank"
- >
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </li>
- </ul>
- </div>
- <div
- v-if="!restructuredWidgetShowMergeButtons"
- class="gl-w-full gl-order-n1 gl-text-gray-500"
- data-qa-selector="merged_status_content"
- >
- <strong v-if="mr.state !== 'closed'">
- {{ __('Merge details') }}
- </strong>
- <ul class="gl-pl-4 gl-m-0">
- <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal">
- <gl-sprintf
- :message="s__('mrWidget|The source branch is %{link} the target branch')"
- >
- <template #link>
- <gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </li>
- <li class="gl-line-height-normal">
- <added-commit-message
- :state="mr.state"
- :merge-commit-sha="mr.shortMergeCommitSha"
- :is-squash-enabled="squashBeforeMerge"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- />
- </li>
- <li v-if="mr.state !== 'closed'" class="gl-line-height-normal">
- {{ sourceBranchDeletedText }}
- </li>
- <li v-if="mr.relatedLinks" class="gl-line-height-normal">
- <related-links
- :state="mr.state"
- :related-links="mr.relatedLinks"
- :show-assign-to-me="false"
- class="mr-ready-merge-related-links gl-display-inline"
- />
- </li>
- </ul>
- </div>
- <div
- v-else
- :class="{ 'gl-mb-5': restructuredWidgetShowMergeButtons }"
- 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;
+ </li>
+ <li v-if="mr.state !== 'closed'" class="gl-line-height-normal">
+ {{ sourceBranchDeletedText }}
+ </li>
+ <li v-if="mr.relatedLinks" class="gl-line-height-normal">
<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>
- </template>
- </div>
- <div
- v-if="showDangerMessageForMergeTrain && !glFeatures.restructuredMrWidget"
- class="gl-mt-5 gl-text-gray-500"
- data-testid="failed-pipeline-merge-train-text"
- >
- {{ __('The latest pipeline for this merge request did not complete successfully.') }}
+ </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>
- <template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget">
- <div v-if="!shouldShowMergeEdit" class="mr-fast-forward-message">
- {{ __('Fast-forward merge without a merge commit') }}
- </div>
- <commits-header
- v-if="!glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)"
- :is-squash-enabled="squashBeforeMerge"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :class="{ 'border-bottom': stateData.mergeError }"
- >
- <ul class="border-top content-list commits-list flex-list">
- <commit-edit
- v-if="shouldShowSquashEdit"
- :value="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- squash
- @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"
- @input="setCommitMessage"
- />
- <li>
- <p class="form-text text-muted">
- <gl-sprintf :message="commitTemplateHintText">
- <template #link="{ content }">
- <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </li>
- </ul>
- </commits-header>
- </template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
index b1fbe150fcf..d149f5208fc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
@@ -1,19 +1,17 @@
<script>
import { GlButton } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { I18N_SHA_MISMATCH } from '../../i18n';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'ShaMismatch',
components: {
- statusIcon,
GlButton,
+ StateContainer,
},
i18n: {
I18N_SHA_MISMATCH,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -24,25 +22,24 @@ export default {
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="false" status="warning" />
- <div class="media-body">
- <span
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
- data-qa-selector="head_mismatch_content"
- >
- {{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }}
- </span>
+ <state-container status="warning">
+ <span
+ class="gl-font-weight-bold gl-md-mr-3 gl-flex-grow-1 gl-ml-0! gl-text-body!"
+ data-qa-selector="head_mismatch_content"
+ >
+ {{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }}
+ </span>
+ <template #actions>
<gl-button
- class="gl-ml-3"
data-testid="action-button"
size="small"
category="primary"
variant="confirm"
+ class="gl-align-self-start"
:href="mr.mergeRequestDiffsPath"
- >{{ $options.i18n.I18N_SHA_MISMATCH.actionButtonLabel }}</gl-button
>
- </div>
- </div>
+ {{ $options.i18n.I18N_SHA_MISMATCH.actionButtonLabel }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index c6227c4394d..1413a46b4b9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -1,6 +1,5 @@
<script>
import { GlIcon, GlTooltipDirective, GlFormCheckbox, GlLink } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SQUASH_BEFORE_MERGE } from '../../i18n';
export default {
@@ -12,7 +11,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagsMixin()],
i18n: {
...SQUASH_BEFORE_MERGE,
},
@@ -36,9 +34,6 @@ export default {
tooltipTitle() {
return this.isDisabled ? this.$options.i18n.tooltipTitle : null;
},
- helpIconName() {
- return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question';
- },
},
};
</script>
@@ -62,10 +57,10 @@ export default {
v-gl-tooltip
:href="helpPath"
:title="$options.i18n.helpLabel"
- :class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }"
+ class="gl-text-blue-600"
target="_blank"
>
- <gl-icon :name="helpIconName" />
+ <gl-icon name="question-o" />
<span class="sr-only">
{{ $options.i18n.helpLabel }}
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
index 25ba4bf12af..035d62eaa59 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
@@ -1,16 +1,14 @@
<script>
import { GlButton } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '~/notes/event_hub';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'UnresolvedDiscussions',
components: {
- statusIcon,
GlButton,
+ StateContainer,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -26,38 +24,33 @@ export default {
</script>
<template>
- <div class="mr-widget-body media gl-flex-wrap">
- <status-icon show-disabled-button status="warning" />
- <div class="media-body">
- <span
- :class="{
- 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
- 'gl-display-block': !glFeatures.restructuredMrWidget,
- }"
- class="gl-ml-3 gl-font-weight-bold gl-w-100"
- >
- {{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
- </span>
+ <state-container status="warning">
+ <span
+ class="gl-ml-3 gl-font-weight-bold gl-w-100 gl-flex-grow-1 gl-md-mr-3 gl-ml-0! gl-text-body!"
+ >
+ {{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
+ </span>
+ <template #actions>
<gl-button
- data-testid="jump-to-first"
- class="gl-ml-3"
+ v-if="mr.createIssueToResolveDiscussionsPath"
+ :href="mr.createIssueToResolveDiscussionsPath"
+ class="js-create-issue gl-align-self-start gl-vertical-align-top gl-mr-2"
size="small"
- :icon="glFeatures.restructuredMrWidget ? undefined : 'comment-next'"
- :variant="glFeatures.restructuredMrWidget ? 'confirm' : 'default'"
- :category="glFeatures.restructuredMrWidget ? 'secondary' : 'primary'"
- @click="jumpToFirstUnresolvedDiscussion"
+ variant="confirm"
+ category="secondary"
>
- {{ s__('mrWidget|Jump to first unresolved thread') }}
+ {{ s__('mrWidget|Create issue to resolve all threads') }}
</gl-button>
<gl-button
- v-if="mr.createIssueToResolveDiscussionsPath"
- :href="mr.createIssueToResolveDiscussionsPath"
- class="js-create-issue gl-ml-3"
+ data-testid="jump-to-first"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start gl-vertical-align-top"
size="small"
- :icon="glFeatures.restructuredMrWidget ? undefined : 'issue-new'"
+ variant="confirm"
+ category="primary"
+ @click="jumpToFirstUnresolvedDiscussion"
>
- {{ s__('mrWidget|Create issue to resolve all threads') }}
+ {{ s__('mrWidget|Jump to first unresolved thread') }}
</gl-button>
- </div>
- </div>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index 5bd7745d704..cf7f83c014a 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
@@ -12,13 +12,13 @@ import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_va
import getStateQuery from '../../queries/get_state.query.graphql';
import draftQuery from '../../queries/states/draft.query.graphql';
import removeDraftMutation from '../../queries/toggle_draft.mutation.graphql';
-import StatusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'WorkInProgress',
components: {
- StatusIcon,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -163,29 +163,22 @@ export default {
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="canUpdate" status="warning" />
- <div class="media-body">
- <div class="float-left">
- <span
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
- >
- {{
- __("Merge blocked: merge request must be marked as ready. It's still marked as draft.")
- }}
- </span>
- </div>
+ <state-container status="warning">
+ <span class="gl-font-weight-bold gl-ml-0! gl-text-body! gl-flex-grow-1">
+ {{ __("Merge blocked: merge request must be marked as ready. It's still marked as draft.") }}
+ </span>
+ <template #actions>
<gl-button
v-if="canUpdate"
size="small"
:disabled="isMakingRequest"
:loading="isMakingRequest"
- class="js-remove-draft gl-ml-3"
+ variant="confirm"
+ class="js-remove-draft gl-md-ml-3 gl-align-self-start"
@click="handleRemoveDraft"
>
{{ s__('mrWidget|Mark as ready') }}
</gl-button>
- </div>
- </div>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
new file mode 100644
index 00000000000..f1c1bde256f
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
@@ -0,0 +1,27 @@
+<script>
+export default {
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ widgets() {
+ return [].filter((w) => w);
+ },
+ },
+};
+</script>
+
+<template>
+ <section role="region" :aria-label="__('Merge request reports')" data-testid="mr-widget-app">
+ <component
+ :is="widget"
+ v-for="(widget, index) in widgets"
+ :key="widget.name || index"
+ :mr="mr"
+ :class="{ 'mr-widget-border-top': index === 0 }"
+ />
+ </section>
+</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
new file mode 100644
index 00000000000..9c8819327e6
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -0,0 +1,158 @@
+<script>
+import * as Sentry from '@sentry/browser';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import Poll from '~/lib/utils/poll';
+import StatusIcon from '../extensions/status_icon.vue';
+import { EXTENSION_ICON_NAMES } from '../../constants';
+
+const FETCH_TYPE_COLLAPSED = 'collapsed';
+
+export default {
+ components: {
+ StatusIcon,
+ },
+ props: {
+ /**
+ * @param {value.collapsed} Object
+ * @param {value.extended} Object
+ */
+ value: {
+ type: Object,
+ required: true,
+ },
+ loadingText: {
+ type: String,
+ required: false,
+ default: __('Loading'),
+ },
+ errorText: {
+ type: String,
+ required: false,
+ default: __('Failed to load'),
+ },
+ fetchCollapsedData: {
+ type: Function,
+ required: true,
+ },
+ fetchExtendedData: {
+ type: Function,
+ required: false,
+ default: undefined,
+ },
+ // If the summary slot is not used, this value will be used as a fallback.
+ summary: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ // If the content slot is not used, this value will be used as a fallback.
+ content: {
+ type: Object,
+ required: false,
+ default: undefined,
+ },
+ multiPolling: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ statusIconName: {
+ type: String,
+ default: 'neutral',
+ required: false,
+ validator: (value) => Object.keys(EXTENSION_ICON_NAMES).indexOf(value) > -1,
+ },
+ widgetName: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ error: null,
+ };
+ },
+ watch: {
+ isLoading(newValue) {
+ this.$emit('is-loading', newValue);
+ },
+ },
+ async mounted() {
+ this.isLoading = true;
+
+ try {
+ await this.fetch(this.fetchCollapsedData, FETCH_TYPE_COLLAPSED);
+ } catch {
+ this.error = this.errorText;
+ }
+
+ this.isLoading = false;
+ },
+ methods: {
+ fetch(handler, dataType) {
+ const requests = this.multiPolling ? handler() : [handler];
+
+ const promises = requests.map((request) => {
+ return new Promise((resolve, reject) => {
+ const poll = new Poll({
+ resource: {
+ fetchData: () => request(),
+ },
+ method: 'fetchData',
+ successCallback: (response) => {
+ const headers = normalizeHeaders(response.headers);
+
+ if (headers['POLL-INTERVAL']) {
+ return;
+ }
+
+ resolve(response.data);
+ },
+ errorCallback: (e) => {
+ Sentry.captureException(e);
+ reject(e);
+ },
+ });
+
+ poll.makeRequest();
+ });
+ });
+
+ return Promise.all(promises).then((data) => {
+ this.$emit('input', { ...this.value, [dataType]: this.multiPolling ? data : data[0] });
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <section class="media-section" data-testid="widget-extension">
+ <div class="media gl-p-5">
+ <status-icon
+ :level="1"
+ :name="widgetName"
+ :is-loading="isLoading"
+ :icon-name="statusIconName"
+ />
+ <div
+ class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
+ data-testid="widget-extension-top-level"
+ >
+ <div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary">
+ <slot name="summary">{{ isLoading ? loadingText : summary }}</slot>
+ </div>
+ <!-- actions will go here -->
+ <!-- toggle button will go here -->
+ </div>
+ </div>
+ <div
+ class="mr-widget-grouped-section gl-relative"
+ data-testid="widget-extension-collapsed-section"
+ >
+ <slot name="content">{{ content }}</slot>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
index 22e907f7e48..0fb5e13ad82 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
@@ -6,7 +6,6 @@ import { EXTENSION_ICONS } from '../../constants';
export default {
name: 'WidgetAccessibility',
enablePolling: true,
- telemetry: false,
i18n: {
loading: s__('Reports|Accessibility scanning results are being parsed'),
error: s__('Reports|Accessibility scanning failed loading results'),
@@ -76,9 +75,9 @@ export default {
return sprintf(s__('AccessibilityReport|Message: %{message}'), { message });
},
prepareReports() {
- const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+ const { collapsedData } = this;
- const newErrors = new_errors.map((error) => {
+ const newErrors = collapsedData.new_errors.map((error) => {
return {
header: __('New'),
id: uniqueId('new-error-'),
@@ -92,7 +91,7 @@ export default {
};
});
- const existingErrors = existing_errors.map((error) => {
+ const existingErrors = collapsedData.existing_errors.map((error) => {
return {
id: uniqueId('existing-error-'),
text: this.formatText(error.code),
@@ -105,7 +104,7 @@ export default {
};
});
- const resolvedErrors = resolved_errors.map((error) => {
+ const resolvedErrors = collapsedData.resolved_errors.map((error) => {
return {
id: uniqueId('resolved-error-'),
text: this.formatText(error.code),
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
index 4ffd06de61f..6896f8831e8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
@@ -51,14 +51,14 @@ export const recentFailuresTextBuilder = (summary = {}) => {
return i18n.recentFailureSummary(recentlyFailed, failed);
};
-export const reportSubTextBuilder = ({ suite_errors, summary }) => {
- if (suite_errors?.head || suite_errors?.base) {
+export const reportSubTextBuilder = ({ suite_errors: suiteErrors, summary }) => {
+ if (suiteErrors?.head || suiteErrors?.base) {
const errors = [];
- if (suite_errors?.head) {
- errors.push(`${i18n.headReportParsingError} ${suite_errors.head}`);
+ if (suiteErrors?.head) {
+ errors.push(`${i18n.headReportParsingError} ${suiteErrors.head}`);
}
- if (suite_errors?.base) {
- errors.push(`${i18n.baseReportParsingError} ${suite_errors.base}`);
+ if (suiteErrors?.base) {
+ errors.push(`${i18n.baseReportParsingError} ${suiteErrors.base}`);
}
return errors.join('<br />');
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index 627ddb0445e..d964b4bacac 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -20,13 +20,6 @@ export default {
this.mr.preventMerge,
);
},
- shouldShowMergeControls() {
- if (this.glFeatures.restructuredMrWidget) {
- return this.restructuredWidgetShowMergeButtons;
- }
-
- return this.isMergeAllowed || this.isAutoMergeAvailable;
- },
mergeDisabledText() {
if (this.pipeline?.status === PIPELINE_SKIPPED_STATUS) {
return MERGE_DISABLED_SKIPPED_PIPELINE_TEXT;
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 3e0ac236fdf..1e25143e15c 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
@@ -1,7 +1,6 @@
<script>
import { GlSafeHtmlDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import securityReportExtension from 'ee_else_ce/vue_merge_request_widget/extensions/security_reports';
import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
import MrWidgetApprovals from 'ee_else_ce/vue_merge_request_widget/components/approvals/approvals.vue';
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
@@ -17,7 +16,6 @@ import { setFaviconOverlay } from '../lib/utils/favicon';
import Loading from './components/loading.vue';
import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
-import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import ArchivedState from './components/states/mr_widget_archived.vue';
@@ -40,6 +38,7 @@ import ShaMismatch from './components/states/sha_mismatch.vue';
import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
import WorkInProgressState from './components/states/work_in_progress.vue';
import ExtensionsContainer from './components/extensions/container';
+import WidgetContainer from './components/widget/app.vue';
import { STATE_MACHINE, stateToComponentMap } from './constants';
import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
@@ -59,9 +58,9 @@ export default {
components: {
Loading,
ExtensionsContainer,
+ WidgetContainer,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
MrWidgetPipelineContainer,
- 'mr-widget-related-links': WidgetRelatedLinks,
MrWidgetAlertMessage,
'mr-widget-merged': MergedState,
'mr-widget-closed': ClosedState,
@@ -73,9 +72,7 @@ export default {
'mr-widget-nothing-to-merge': NothingToMergeState,
'mr-widget-not-allowed': NotAllowedState,
'mr-widget-missing-branch': MissingBranchState,
- 'mr-widget-ready-to-merge': window.gon?.features?.restructuredMrWidget
- ? () => import('./components/states/new_ready_to_merge.vue')
- : ReadyToMergeState,
+ 'mr-widget-ready-to-merge': () => import('./components/states/new_ready_to_merge.vue'),
'sha-mismatch': ShaMismatch,
'mr-widget-checking': CheckingState,
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
@@ -163,12 +160,6 @@ export default {
shouldRenderCodeQuality() {
return this.mr?.codequalityReportsPath;
},
- shouldRenderRelatedLinks() {
- return (
- (Boolean(this.mr.relatedLinks) || this.mr.divergedCommitsCount > 0) &&
- !this.mr.isNothingToMergeState
- );
- },
shouldRenderSourceBranchRemovalStatus() {
return (
!this.mr.canRemoveSourceBranch &&
@@ -239,9 +230,6 @@ export default {
shouldShowCodeQualityExtension() {
return window.gon?.features?.refactorCodeQualityExtension;
},
- isRestructuredMrWidgetEnabled() {
- return window.gon?.features?.restructuredMrWidget;
- },
},
watch: {
'mr.machineValue': {
@@ -275,11 +263,6 @@ export default {
this.registerTestReportExtension();
}
},
- shouldRenderSecurityReport(newVal) {
- if (newVal) {
- this.registerSecurityReportExtension();
- }
- },
},
mounted() {
MRWidgetService.fetchInitialData()
@@ -535,11 +518,6 @@ export default {
registerExtension(testReportExtension);
}
},
- registerSecurityReportExtension() {
- if (this.shouldRenderSecurityReport && this.shouldShowSecurityExtension) {
- registerExtension(securityReportExtension);
- }
- },
},
};
</script>
@@ -600,7 +578,11 @@ export default {
</template>
</mr-widget-alert-message>
</div>
+
<extensions-container :mr="mr" />
+
+ <widget-container v-if="mr" :mr="mr" />
+
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality && !shouldShowCodeQualityExtension"
:head-blob-path="mr.headBlobPath"
@@ -638,23 +620,7 @@ export default {
<div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
- <ready-to-merge
- v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
- :mr="mr"
- :service="service"
- />
- <div v-else class="mr-widget-info">
- <mr-widget-related-links
- v-if="shouldRenderRelatedLinks"
- :state="mr.state"
- :related-links="mr.relatedLinks"
- :diverged-commits-count="mr.divergedCommitsCount"
- :target-branch-path="mr.targetBranchPath"
- class="mr-info-list gl-ml-7 gl-pb-5"
- />
-
- <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
- </div>
+ <ready-to-merge v-if="mr.commitsCount" :mr="mr" :service="service" />
</div>
</div>
<mr-widget-pipeline-container
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
index efc0673bc26..54770e6579a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -1,11 +1,9 @@
fragment ReadyToMerge on Project {
- __typename
id
onlyAllowMergeIfPipelineSucceeds
mergeRequestsFfOnlyEnabled
squashReadOnly
mergeRequest(iid: $iid) {
- __typename
id
autoMergeEnabled
shouldRemoveSourceBranch
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 18d955652ba..7a458f9ce7e 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
@@ -27,8 +27,6 @@ export default function deviseState() {
return stateKey.shaMismatch;
} else if (this.autoMergeEnabled && !this.mergeError) {
return stateKey.autoMergeEnabled;
- } else if (!this.canMerge && !window.gon?.features?.restructuredMrWidget) {
- return stateKey.notAllowedToMerge;
} else if (this.canBeMerged) {
return stateKey.readyToMerge;
}
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 03c9a01cc7a..146cf7e11a7 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
@@ -33,7 +33,6 @@ export default class MergeRequestStore {
this.setData(data);
this.initCodeQualityReport(data);
- this.initSecurityReport(data);
this.setGitpodData(data);
}
@@ -42,19 +41,6 @@ export default class MergeRequestStore {
this.codeQuality = data.codequality_reports_path;
}
- initSecurityReport(data) {
- // TODO: check if gl.mrWidgetData can be safely removed after we migrate to the
- // widget extension.
- this.securityReportPaths = {
- apiFuzzingReportPath: data.api_fuzzing_comparison_path,
- coverageFuzzingReportPath: data.coverage_fuzzing_comparison_path,
- sastReportPath: data.sast_comparison_path,
- dastReportPath: data.dast_comparison_path,
- secretDetectionReportPath: data.secret_detection_comparison_path,
- dependencyScanningReportPath: data.dependency_scanning_comparison_path,
- };
- }
-
setData(data, isRebased) {
this.initApprovals();
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
index e12e06a2454..5b9efff1c06 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
@@ -53,6 +53,7 @@ export default {
:variant="buttonVariant"
:disabled="disabled"
:data-testid="buttonTestid"
+ data-qa-selector="confirm_danger_button"
>{{ buttonText }}</gl-button
>
<confirm-danger-modal
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
index 37e480f7e41..7a982bc035a 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
@@ -66,7 +66,13 @@ export default {
actionPrimary() {
return {
text: this.confirmButtonText,
- attributes: [{ variant: 'danger', disabled: !this.isValid, class: 'qa-confirm-button' }],
+ attributes: [
+ {
+ variant: 'danger',
+ disabled: !this.isValid,
+ 'data-qa-selector': 'confirm_danger_modal_button',
+ },
+ ],
};
},
actionCancel() {
@@ -122,7 +128,8 @@ export default {
<gl-form-input
id="confirm_name_input"
v-model="confirmationPhrase"
- class="form-control qa-confirm-input"
+ class="form-control"
+ data-qa-selector="confirm_danger_field"
data-testid="confirm-danger-input"
type="text"
/>
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 f4317ba90a2..7c4e372dda1 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
@@ -30,12 +30,12 @@ export function fetchBranches({ commit, state }, search = '') {
});
}
-export const fetchMilestones = ({ commit, state }, search_title = '') => {
+export const fetchMilestones = ({ commit, state }, searchTitle = '') => {
commit(types.REQUEST_MILESTONES);
const { milestonesEndpoint } = state;
return axios
- .get(milestonesEndpoint, { params: { search_title } })
+ .get(milestonesEndpoint, { params: { search_title: searchTitle } })
.then((response) => {
commit(types.RECEIVE_MILESTONES_SUCCESS, response.data);
return response;
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 acddf16bd27..72148a0aa7c 100644
--- a/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue
+++ b/app/assets/javascripts/vue_shared/components/gitlab_version_check.vue
@@ -2,6 +2,7 @@
import { GlBadge } from '@gitlab/ui';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import { joinPaths } from '~/lib/utils/url_utility';
const STATUS_TYPES = {
SUCCESS: 'success',
@@ -45,7 +46,7 @@ export default {
methods: {
checkGitlabVersion() {
axios
- .get('/admin/version_check.json')
+ .get(joinPaths('/', gon.relative_url_root, '/admin/version_check.json'))
.then((res) => {
if (res.data) {
this.status = res.data.severity;
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 4fdf7f45643..1d1b65aa1af 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -156,6 +156,14 @@ export default {
})
.catch(() => {});
},
+ handleAttachFile(e) {
+ e.preventDefault();
+ const $gfmForm = $(this.$el).closest('.gfm-form');
+ const $gfmTextarea = $gfmForm.find('.js-gfm-input');
+
+ $gfmForm.find('.div-dropzone').click();
+ $gfmTextarea.focus();
+ },
},
shortcuts: {
bold: keysFor(BOLD_TEXT),
@@ -195,6 +203,44 @@ export default {
:class="{ 'gl-display-none!': previewMarkdown }"
class="md-header-toolbar gl-ml-auto gl-pb-3 gl-justify-content-center"
>
+ <template v-if="canSuggest">
+ <toolbar-button
+ ref="suggestButton"
+ :tag="mdSuggestion"
+ :prepend="true"
+ :button-title="__('Insert suggestion')"
+ :cursor-offset="4"
+ :tag-content="lineContent"
+ icon="doc-code"
+ data-qa-selector="suggestion_button"
+ class="js-suggestion-btn"
+ @click="handleSuggestDismissed"
+ />
+ <gl-popover
+ v-if="suggestPopoverVisible"
+ :target="$refs.suggestButton.$el"
+ :css-classes="['diff-suggest-popover']"
+ placement="bottom"
+ :show="suggestPopoverVisible"
+ >
+ <strong>{{ __('New! Suggest changes directly') }}</strong>
+ <p class="mb-2">
+ {{
+ __(
+ 'Suggest code changes which can be immediately applied in one click. Try it out!',
+ )
+ }}
+ </p>
+ <gl-button
+ variant="confirm"
+ category="primary"
+ size="small"
+ @click="handleSuggestDismissed"
+ >
+ {{ __('Got it') }}
+ </gl-button>
+ </gl-popover>
+ </template>
<toolbar-button
tag="**"
:button-title="
@@ -237,44 +283,6 @@ export default {
icon="quote"
@click="handleQuote"
/>
- <template v-if="canSuggest">
- <toolbar-button
- ref="suggestButton"
- :tag="mdSuggestion"
- :prepend="true"
- :button-title="__('Insert suggestion')"
- :cursor-offset="4"
- :tag-content="lineContent"
- icon="doc-code"
- data-qa-selector="suggestion_button"
- class="js-suggestion-btn"
- @click="handleSuggestDismissed"
- />
- <gl-popover
- v-if="suggestPopoverVisible"
- :target="$refs.suggestButton.$el"
- :css-classes="['diff-suggest-popover']"
- placement="bottom"
- :show="suggestPopoverVisible"
- >
- <strong>{{ __('New! Suggest changes directly') }}</strong>
- <p class="mb-2">
- {{
- __(
- 'Suggest code changes which can be immediately applied in one click. Try it out!',
- )
- }}
- </p>
- <gl-button
- variant="confirm"
- category="primary"
- size="small"
- @click="handleSuggestDismissed"
- >
- {{ __('Got it') }}
- </gl-button>
- </gl-popover>
- </template>
<toolbar-button tag="`" tag-block="```" :button-title="__('Insert code')" icon="code" />
<toolbar-button
tag="[{text}](url)"
@@ -306,7 +314,7 @@ export default {
v-if="!restrictedToolBarItems.includes('task-list')"
:prepend="true"
tag="- [ ] "
- :button-title="__('Add a task list')"
+ :button-title="__('Add a checklist')"
icon="list-task"
/>
<toolbar-button
@@ -324,6 +332,15 @@ export default {
:button-title="__('Add a table')"
icon="table"
/>
+ <gl-button
+ v-if="!restrictedToolBarItems.includes('attach-file')"
+ v-gl-tooltip
+ :title="__('Attach a file or image')"
+ data-testid="button-attach-file"
+ category="tertiary"
+ icon="paperclip"
+ @click="handleAttachFile"
+ />
<toolbar-button
v-if="!restrictedToolBarItems.includes('full-screen')"
class="js-zen-enter"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 6c99a749edc..aa325862f06 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -74,7 +74,7 @@ export default {
</div>
<span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
- <gl-icon name="media" />
+ <gl-icon name="paperclip" />
<span class="attaching-file-message"></span>
<!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
<span class="uploading-progress">0%</span>
@@ -82,7 +82,7 @@ export default {
</span>
<span class="uploading-error-container hide">
<span class="uploading-error-icon">
- <gl-icon name="media" />
+ <gl-icon name="paperclip" />
</span>
<span class="uploading-error-message"></span>
@@ -114,14 +114,6 @@ export default {
</gl-sprintf>
</span>
<gl-button
- icon="media"
- variant="link"
- category="primary"
- class="markdown-selector button-attach-file gl-vertical-align-text-bottom"
- >
- {{ __('Attach a file') }}
- </gl-button>
- <gl-button
variant="link"
category="primary"
class="button-cancel-uploading-files gl-vertical-align-baseline hide"
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 6a83939795c..49217e38a1b 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -88,6 +88,6 @@ export default {
category="tertiary"
class="js-md"
data-container="body"
- @click="() => $emit('click')"
+ @click="$emit('click', $event)"
/>
</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
index 521b1a1075a..e9f278a5db5 100644
--- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
@@ -5,6 +5,8 @@ import {
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
} from '@gitlab/ui';
import { __ } from '~/locale';
@@ -32,6 +34,8 @@ export default {
GlDropdownItem,
GlDropdownSectionHeader,
GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
},
props: {
groupNamespaces: {
@@ -69,6 +73,26 @@ export default {
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 {
@@ -84,10 +108,12 @@ export default {
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);
},
@@ -107,9 +133,15 @@ export default {
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() {
@@ -122,7 +154,11 @@ export default {
<template>
<gl-dropdown :text="selectedNamespaceText" :block="fullWidth" data-qa-selector="namespaces_list">
<template #header>
- <gl-search-box-by-type v-model.trim="searchTerm" />
+ <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
@@ -133,29 +169,40 @@ export default {
</gl-dropdown-item>
<gl-dropdown-divider />
</div>
- <div v-if="hasGroupNamespaces" data-qa-selector="namespaces_list_groups">
+ <div
+ v-if="hasUserNamespaces"
+ data-qa-selector="namespaces_list_users"
+ data-testid="namespace-list-users"
+ >
<gl-dropdown-section-header v-if="includeHeaders">{{
- $options.i18n.GROUPS
+ $options.i18n.USERS
}}</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="item in filteredGroupNamespaces"
+ 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="hasUserNamespaces" data-qa-selector="namespaces_list_users">
+ <div
+ v-if="hasGroupNamespaces"
+ data-qa-selector="namespaces_list_groups"
+ data-testid="namespace-list-groups"
+ >
<gl-dropdown-section-header v-if="includeHeaders">{{
- $options.i18n.USERS
+ $options.i18n.GROUPS
}}</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="item in filteredUserNamespaces"
+ 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/project_avatar.vue b/app/assets/javascripts/vue_shared/components/project_avatar.vue
index 402e75962d2..f65cc8bf2f3 100644
--- a/app/assets/javascripts/vue_shared/components/project_avatar.vue
+++ b/app/assets/javascripts/vue_shared/components/project_avatar.vue
@@ -1,5 +1,6 @@
<script>
import { GlAvatar } from '@gitlab/ui';
+import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
export default {
@@ -7,6 +8,14 @@ export default {
GlAvatar,
},
props: {
+ projectId: {
+ type: [Number, String],
+ default: 0,
+ required: false,
+ validator(value) {
+ return typeof value === 'string' ? isGid(value) : true;
+ },
+ },
projectName: {
type: String,
required: true,
@@ -31,6 +40,9 @@ export default {
avatarAlt() {
return this.alt ?? this.projectName;
},
+ entityId() {
+ return isGid(this.projectId) ? getIdFromGraphQLId(this.projectId) : this.projectId;
+ },
},
AVATAR_SHAPE_OPTION_RECT,
};
@@ -39,6 +51,7 @@ export default {
<template>
<gl-avatar
:shape="$options.AVATAR_SHAPE_OPTION_RECT"
+ :entity-id="entityId"
:entity-name="projectName"
:src="projectAvatarUrl"
:alt="avatarAlt"
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 19ffbe37ce7..66643ff4026 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -53,6 +53,7 @@ export default {
>
<gl-icon v-if="selected" class="js-selected-icon" name="mobile-issue-close" />
<project-avatar
+ :project-id="project.id"
:project-avatar-url="projectAvatarUrl"
:project-name="projectNameWithNamespace"
class="gl-mr-3"
diff --git a/app/assets/javascripts/vue_shared/components/rich_timestamp_tooltip.vue b/app/assets/javascripts/vue_shared/components/rich_timestamp_tooltip.vue
new file mode 100644
index 00000000000..424a11bf88b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_timestamp_tooltip.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlTooltip } from '@gitlab/ui';
+
+import { formatDate } from '~/lib/utils/datetime_utility';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+export default {
+ components: {
+ GlTooltip,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ target: {
+ type: [Object, HTMLElement, SVGElement, String, Function],
+ required: true,
+ },
+ rawTimestamp: {
+ type: String,
+ required: true,
+ },
+ timestampTypeText: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ timestampInWords() {
+ return this.rawTimestamp ? this.timeFormatted(this.rawTimestamp) : '';
+ },
+ timestamp() {
+ return this.rawTimestamp ? formatDate(new Date(this.rawTimestamp)) : '';
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-tooltip :target="target">
+ <div class="bold" data-testid="header-text">{{ timestampTypeText }} {{ timestampInWords }}</div>
+ <div class="text-tertiary" data-testid="body-text">{{ timestamp }}</div>
+ </gl-tooltip>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
index be270e440ed..4af07366a6d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
@@ -3,11 +3,13 @@
query issueAssignees($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
+ author {
+ ...User
+ ...UserAvailability
+ }
assignees {
nodes {
...User
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 96a40e597ee..445817d3e52 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
@@ -3,10 +3,8 @@
query issueParticipants($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
- __typename
id
issuable: issue(iid: $iid) {
- __typename
id
participants {
nodes {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
index dffcc053fac..b127b8ec5a9 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_timelogs.query.graphql
@@ -2,7 +2,6 @@
query issueTimeTrackingReport($id: IssueID!) {
issuable: issue(id: $id) {
- __typename
id
title
timelogs {
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
new file mode 100644
index 00000000000..05de680ab05
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_merge_request_reviewers.query.graphql
@@ -0,0 +1,26 @@
+#import "~/graphql_shared/fragments/user.fragment.graphql"
+#import "~/graphql_shared/fragments/user_availability.fragment.graphql"
+
+query mergeRequestReviewers($fullPath: ID!, $iid: String!) {
+ workspace: project(fullPath: $fullPath) {
+ id
+ issuable: mergeRequest(iid: $iid) {
+ id
+ reviewers {
+ nodes {
+ ...User
+ ...UserAvailability
+ mergeRequestInteraction {
+ canMerge
+ canUpdate
+ approved
+ reviewed
+ }
+ }
+ }
+ userPermissions {
+ updateMergeRequest
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
index 7127940bb05..f70cd723f2e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
@@ -6,6 +6,13 @@ query getMrAssignees($fullPath: ID!, $iid: String!) {
id
issuable: mergeRequest(iid: $iid) {
id
+ author {
+ ...User
+ ...UserAvailability
+ mergeRequestInteraction {
+ canMerge
+ }
+ }
assignees {
nodes {
...User
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
index ede9b75d765..17f548b44b5 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_timelogs.query.graphql
@@ -2,7 +2,6 @@
query mrTimeTrackingReport($id: MergeRequestID!) {
issuable: mergeRequest(id: $id) {
- __typename
id
title
timelogs {
diff --git a/app/assets/javascripts/vue_shared/components/source_editor.vue b/app/assets/javascripts/vue_shared/components/source_editor.vue
index 6a0bf07c8b4..1925c5d4064 100644
--- a/app/assets/javascripts/vue_shared/components/source_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/source_editor.vue
@@ -1,5 +1,5 @@
<script>
-import { debounce } from 'lodash';
+import { debounce, isEmpty } from 'lodash';
import { CONTENT_UPDATE_DEBOUNCE, EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/source_editor';
@@ -37,9 +37,9 @@ export default {
default: '',
},
extensions: {
- type: [String, Array],
+ type: [Object, Array],
required: false,
- default: () => null,
+ default: () => ({}),
},
editorOptions: {
type: Object,
@@ -74,11 +74,13 @@ export default {
blobPath: this.fileName,
blobContent: this.value,
blobGlobalId: this.fileGlobalId,
- extensions: this.extensions,
...this.editorOptions,
});
this.editor.onDidChangeModelContent(debounce(this.onFileChange.bind(this), this.debounceValue));
+ if (!isEmpty(this.extensions)) {
+ this.editor.use(this.extensions);
+ }
},
beforeDestroy() {
this.editor.dispose();
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk.vue b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk.vue
index 6babbca58c3..9683288f937 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk.vue
@@ -51,6 +51,10 @@ export default {
required: false,
default: null,
},
+ blamePath: {
+ type: String,
+ required: true,
+ },
},
computed: {
lines() {
@@ -76,6 +80,7 @@ export default {
:number="startingFrom + index + 1"
:content="line"
:language="language"
+ :blame-path="blamePath"
/>
</div>
<div v-else class="gl-display-flex">
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 7b62f0cdb7d..257b9f57222 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,15 +1,14 @@
<script>
-import { GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
+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 {
- components: {
- GlLink,
- },
directives: {
SafeHtml: GlSafeHtmlDirective,
},
+ mixins: [glFeatureFlagMixin()],
props: {
number: {
type: Number,
@@ -23,6 +22,10 @@ export default {
type: String,
required: true,
},
+ blamePath: {
+ type: String,
+ required: true,
+ },
},
computed: {
formattedContent() {
@@ -36,9 +39,6 @@ export default {
return content;
},
- firstLineClass() {
- return { 'gl-mt-3!': this.number === 1 };
- },
},
methods: {
wrapBidiChar(bidiChar) {
@@ -59,21 +59,26 @@ export default {
</script>
<template>
<div class="gl-display-flex">
- <div class="gl-p-0! gl-absolute gl-z-index-3 gl-border-r diff-line-num line-numbers">
- <gl-link
+ <div
+ class="gl-p-0! gl-absolute gl-z-index-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
+ >
+ <a
+ v-if="glFeatures.fileLineBlame"
+ class="gl-user-select-none gl-shadow-none! file-line-blame"
+ :href="`${blamePath}#L${number}`"
+ ></a>
+ <a
:id="`L${number}`"
- class="gl-user-select-none gl-ml-5 gl-pr-3 gl-shadow-none! file-line-num diff-line-num"
- :class="firstLineClass"
- :to="`#L${number}`"
+ class="gl-user-select-none gl-shadow-none! file-line-num"
+ :href="`#L${number}`"
:data-line-number="number"
>
{{ number }}
- </gl-link>
+ </a>
</div>
<pre
- class="gl-p-0! gl-w-full gl-overflow-visible! gl-ml-11! gl-border-none! code highlight gl-line-height-normal"
- :class="firstLineClass"
+ 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>
</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 3ac35abcf3a..cc930d67fa4 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
@@ -147,3 +147,4 @@ export const HLJS_COMMENT_SELECTOR = 'hljs-comment';
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/link_dependencies.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js
index 5b7650c56ae..d957990fe7f 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js
@@ -1,7 +1,9 @@
import packageJsonLinker from './utils/package_json_linker';
+import gemspecLinker from './utils/gemspec_linker';
const DEPENDENCY_LINKERS = {
package_json: packageJsonLinker,
+ gemspec: gemspecLinker,
};
/**
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 56ad55ef553..dbe6812cf16 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
@@ -7,9 +7,10 @@ export const createLink = (href, innerText) => {
const link = document.createElement('a');
setAttributes(link, { href: escape(href), rel });
- link.innerText = escape(innerText);
+ link.textContent = innerText;
return link.outerHTML;
};
-export const generateHLJSOpenTag = (type) => `<span class="hljs-${escape(type)}">&quot;`;
+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
new file mode 100644
index 00000000000..35de8fd13d6
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/gemspec_linker.js
@@ -0,0 +1,39 @@
+import { joinPaths } from '~/lib/utils/url_utility';
+import { GEM_URL } from '../../constants';
+import { createLink, generateHLJSOpenTag } from './dependency_linker_util';
+
+const methodRegex = '.*add_dependency.*|.*add_runtime_dependency.*|.*add_development_dependency.*';
+const openTagRegex = generateHLJSOpenTag('string', '(&.*;)');
+const closeTagRegex = '&.*</span>';
+
+const DEPENDENCY_REGEX = new RegExp(
+ /*
+ * Detects gemspec dependencies inside of content that is highlighted by Highlight.js
+ * Example: s.add_dependency(<span class="hljs-string">&#x27;rugged&#x27;</span>, <span class="hljs-string">&#x27;~&gt; 0.24.0&#x27;</span>)
+ *
+ * Group 1 (method) : s.add_dependency(
+ * Group 2 (delimiter) : &#x27;
+ * Group 3 (packageName): rugged
+ * Group 4 (closeTag) : &#x27;</span>
+ * Group 5 (rest) : , <span class="hljs-string">&#x27;~&gt; 0.24.0&#x27;</span>)
+ */
+ `(${methodRegex})${openTagRegex}(.*)(${closeTagRegex})(.*${closeTagRegex})`,
+ 'gm',
+);
+
+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 packageLink = createLink(href, packageName);
+
+ return `${method}${openTag}${packageLink}${closeTag}${rest}`;
+};
+
+export default (result) => {
+ return result.value.replace(
+ DEPENDENCY_REGEX,
+ (_, method, delimiter, packageName, closeTag, rest) =>
+ handleReplace(method, delimiter, packageName, 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 d013d077ba3..3c6fc23c138 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,3 +1,4 @@
+import { unescape } from 'lodash';
import { joinPaths } from '~/lib/utils/url_utility';
import { NPM_URL } from '../../constants';
import { createLink, generateHLJSOpenTag } from './dependency_linker_util';
@@ -17,13 +18,15 @@ const DEPENDENCY_REGEX = new RegExp(
);
const handleReplace = (original, packageName, version, dependenciesToLink) => {
- const href = joinPaths(NPM_URL, packageName);
- const packageLink = createLink(href, packageName);
- const versionLink = createLink(href, version);
+ const unescapedPackageName = unescape(packageName);
+ const unescapedVersion = unescape(version);
+ const href = joinPaths(NPM_URL, unescapedPackageName);
+ const packageLink = createLink(href, unescapedPackageName);
+ const versionLink = createLink(href, unescapedVersion);
const closeAndOpenTag = `${closeTag}: ${attrOpenTag}`;
- const dependencyToLink = dependenciesToLink[packageName];
+ const dependencyToLink = dependenciesToLink[unescapedPackageName];
- if (dependencyToLink && dependencyToLink === version) {
+ if (dependencyToLink && dependencyToLink === unescapedVersion) {
return `${attrOpenTag}${packageLink}${closeAndOpenTag}${versionLink}${closeTag}`;
}
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 1bdae40332f..ccc8b44942a 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
@@ -199,6 +199,7 @@ export default {
:starting-from="firstChunk.startingFrom"
:is-highlighted="firstChunk.isHighlighted"
:language="firstChunk.language"
+ :blame-path="blob.blamePath"
/>
<gl-loading-icon v-if="isLoading" size="sm" class="gl-my-5" />
@@ -213,6 +214,7 @@ export default {
:is-highlighted="chunk.isHighlighted"
:chunk-index="index"
:language="chunk.language"
+ :blame-path="blob.blamePath"
@appear="highlightChunk"
/>
</div>
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 d07f65cf5c1..c1e618620d8 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
@@ -50,7 +50,7 @@ export default {
default: __('user avatar'),
},
size: {
- type: Number,
+ type: [Number, Object],
required: false,
default: 20,
},
@@ -64,12 +64,19 @@ export default {
required: false,
default: 'top',
},
+ enforceGlAvatar: {
+ type: Boolean,
+ required: false,
+ },
},
};
</script>
<template>
- <user-avatar-image-new v-if="glFeatures.glAvatarForAllUserAvatars" v-bind="$props">
+ <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">
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
index 707b0bbec67..cd610314292 100644
--- 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
@@ -16,6 +16,7 @@
*/
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';
@@ -48,7 +49,7 @@ export default {
default: __('user avatar'),
},
size: {
- type: Number,
+ type: [Number, Object],
required: false,
default: 20,
},
@@ -71,9 +72,16 @@ export default {
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}`;
+ 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;
},
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 887deff17c9..f80abed4d69 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
@@ -55,7 +55,7 @@ export default {
default: '',
},
imgSize: {
- type: Number,
+ type: [Number, Object],
required: false,
default: 20,
},
@@ -74,12 +74,19 @@ export default {
required: false,
default: '',
},
+ enforceGlAvatar: {
+ type: Boolean,
+ required: false,
+ },
},
};
</script>
<template>
- <user-avatar-link-new v-if="glFeatures.glAvatarForAllUserAvatars" v-bind="$props">
+ <user-avatar-link-new
+ v-if="glFeatures.glAvatarForAllUserAvatars || enforceGlAvatar"
+ v-bind="$props"
+ >
<slot></slot>
<template #avatar-badge>
<slot name="avatar-badge"></slot>
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
index 3b459569274..83551c689c4 100644
--- 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
@@ -56,7 +56,7 @@ export default {
default: '',
},
imgSize: {
- type: Number,
+ type: [Number, Object],
required: false,
default: 20,
},
@@ -75,6 +75,10 @@ export default {
required: false,
default: '',
},
+ enforceGlAvatar: {
+ type: Boolean,
+ required: false,
+ },
},
computed: {
shouldShowUsername() {
@@ -97,6 +101,7 @@ export default {
:tooltip-text="avatarTooltipText"
:tooltip-placement="tooltipPlacement"
:lazy="lazy"
+ :enforce-gl-avatar="enforceGlAvatar"
>
<slot></slot>
</user-avatar-image>
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 60b26d688b2..9da298ad705 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
@@ -21,7 +21,7 @@ export default {
default: 10,
},
imgSize: {
- type: Number,
+ type: [Number, Object],
required: false,
default: 20,
},
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 a0d8ca117a4..2b9804796ae 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
@@ -14,6 +14,7 @@ import { glEmojiTag } from '~/emoji';
import createFlash from '~/flash';
import { followUser, unfollowUser } from '~/rest_api';
import { isUserBusy } from '~/set_status_modal/utils';
+import Tracking from '~/tracking';
import { USER_POPOVER_DELAY } from './constants';
const MAX_SKELETON_LINES = 4;
@@ -37,6 +38,7 @@ export default {
directives: {
SafeHtml: GlSafeHtmlDirective,
},
+ mixins: [Tracking.mixin()],
props: {
target: {
type: HTMLElement,
@@ -117,6 +119,11 @@ export default {
},
async follow() {
this.toggleFollowLoading = true;
+
+ this.track('click_button', {
+ label: 'follow_from_user_popover',
+ });
+
try {
await followUser(this.user.id);
this.$emit('follow');
@@ -132,6 +139,11 @@ export default {
},
async unfollow() {
this.toggleFollowLoading = true;
+
+ this.track('click_button', {
+ label: 'unfollow_from_user_popover',
+ });
+
try {
await unfollowUser(this.user.id);
this.$emit('unfollow');
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 91f20863089..43a590c2367 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
@@ -77,6 +77,11 @@ export default {
required: false,
default: null,
},
+ issuableAuthor: {
+ type: Object,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -178,7 +183,7 @@ export default {
[],
);
- return this.moveCurrentUserToStart(mergedSearchResults);
+ return this.moveCurrentUserAndAuthorToStart(mergedSearchResults);
},
isSearchEmpty() {
return this.search === '';
@@ -196,14 +201,21 @@ export default {
showCurrentUser() {
return this.currentUser.username && !this.isCurrentUserInList && this.isSearchEmpty;
},
+ showAuthor() {
+ return (
+ this.issuableAuthor &&
+ !this.users.some((user) => user.id === this.issuableAuthor.id) &&
+ this.isSearchEmpty
+ );
+ },
selectedFiltered() {
if (this.shouldShowParticipants) {
- return this.moveCurrentUserToStart(this.value);
+ return this.moveCurrentUserAndAuthorToStart(this.value);
}
const foundUsernames = this.users.map(({ username }) => username);
const filtered = this.value.filter(({ username }) => foundUsernames.includes(username));
- return this.moveCurrentUserToStart(filtered);
+ return this.moveCurrentUserAndAuthorToStart(filtered);
},
selectedUserNames() {
return this.value.map(({ username }) => username);
@@ -254,20 +266,22 @@ export default {
showDivider(list) {
return list.length > 0 && this.isSearchEmpty;
},
- moveCurrentUserToStart(users) {
- if (!users) {
- return [];
+ moveCurrentUserAndAuthorToStart(users = []) {
+ let sortedUsers = [...users];
+
+ const author = sortedUsers.find((user) => user.id === this.issuableAuthor?.id);
+ if (author) {
+ sortedUsers = [author, ...sortedUsers.filter((user) => user.id !== author.id)];
}
- const usersCopy = [...users];
- const currentUser = usersCopy.find((user) => user.username === this.currentUser.username);
+
+ const currentUser = sortedUsers.find((user) => user.username === this.currentUser.username);
if (currentUser) {
currentUser.canMerge = this.currentUser.canMerge;
- const index = usersCopy.indexOf(currentUser);
- usersCopy.splice(0, 0, usersCopy.splice(index, 1)[0]);
+ sortedUsers = [currentUser, ...sortedUsers.filter((user) => user.id !== currentUser.id)];
}
- return usersCopy;
+ return sortedUsers;
},
setSearchKey(value) {
this.search = value.trim();
@@ -298,7 +312,7 @@ export default {
<gl-loading-icon
v-if="isLoading"
data-testid="loading-participants"
- size="lg"
+ size="md"
class="gl-absolute gl-left-0 gl-top-0 gl-right-0"
/>
<template v-else>
@@ -312,8 +326,8 @@ export default {
>
<span :class="selectedIsEmpty ? 'gl-pl-0' : 'gl-pl-6'" class="gl-font-weight-bold">{{
$options.i18n.unassigned
- }}</span></gl-dropdown-item
- >
+ }}</span>
+ </gl-dropdown-item>
</template>
<gl-dropdown-divider v-if="showDivider(selectedFiltered)" />
<gl-dropdown-item
@@ -342,7 +356,17 @@ export default {
/>
</gl-dropdown-item>
</template>
- <gl-dropdown-divider v-if="showDivider(unselectedFiltered)" />
+ <gl-dropdown-item
+ v-if="showAuthor"
+ data-testid="issuable-author"
+ @click.native.capture.stop="selectAssignee(issuableAuthor)"
+ >
+ <sidebar-participant
+ :user="issuableAuthor"
+ :issuable-type="issuableType"
+ class="gl-pl-6!"
+ />
+ </gl-dropdown-item>
<gl-dropdown-item
v-for="unselectedUser in unselectedFiltered"
:key="unselectedUser.id"
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index cac0d5a45c9..6d179b3dc92 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -10,6 +10,21 @@ const KEY_WEB_IDE = 'webide';
const KEY_GITPOD = 'gitpod';
const KEY_PIPELINE_EDITOR = 'pipeline_editor';
+export const i18n = {
+ modal: {
+ title: __('Enable Gitpod?'),
+ content: s__(
+ 'Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}.',
+ ),
+ actionCancelText: __('Cancel'),
+ actionPrimaryText: __('Enable Gitpod'),
+ },
+ webIdeText: s__('WebIDE|Quickly and easily edit multiple files in your project.'),
+ webIdeTooltip: s__(
+ 'WebIDE|Quickly and easily edit multiple files in your project. Press . to open',
+ ),
+};
+
export default {
components: {
ActionsButton,
@@ -19,16 +34,7 @@ export default {
GlLink,
ConfirmForkModal,
},
- i18n: {
- modal: {
- title: __('Enable Gitpod?'),
- content: s__(
- 'Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}.',
- ),
- actionCancelText: __('Cancel'),
- actionPrimaryText: __('Enable Gitpod'),
- },
- },
+ i18n,
props: {
isFork: {
type: Boolean,
@@ -207,8 +213,8 @@ export default {
return {
key: KEY_WEB_IDE,
text: this.webIdeActionText,
- secondaryText: __('Quickly and easily edit multiple files in your project.'),
- tooltip: '',
+ secondaryText: this.$options.i18n.webIdeText,
+ tooltip: this.$options.i18n.webIdeTooltip,
attrs: {
'data-qa-selector': 'web_ide_button',
'data-track-action': 'click_consolidated_edit_ide',
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 14328b1f25f..b6d69faebb5 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -1,4 +1,4 @@
-import { __, sprintf } from '~/locale';
+import { __, n__, sprintf } from '~/locale';
import { IssuableType, WorkspaceType } from '~/issues/constants';
const INTERVALS = {
@@ -15,51 +15,62 @@ export const ISO_SHORT_FORMAT = 'yyyy-mm-dd';
export const DATE_FORMATS = [SHORT_DATE_FORMAT, ISO_SHORT_FORMAT];
+const getTimeLabel = (days) => n__('1 day', '%d days', days);
+
+/* eslint-disable @gitlab/require-i18n-strings */
export const timeRanges = [
{
- label: __('30 minutes'),
+ label: n__('1 minute', '%d minutes', 30),
+ shortcut: '30_minutes',
duration: { seconds: 60 * 30 },
name: 'thirtyMinutes',
interval: INTERVALS.minute,
},
{
- label: __('3 hours'),
+ label: n__('1 hour', '%d hours', 3),
+ shortcut: '3_hours',
duration: { seconds: 60 * 60 * 3 },
name: 'threeHours',
interval: INTERVALS.hour,
},
{
- label: __('8 hours'),
+ label: n__('1 hour', '%d hours', 8),
+ shortcut: '8_hours',
duration: { seconds: 60 * 60 * 8 },
name: 'eightHours',
default: true,
interval: INTERVALS.hour,
},
{
- label: __('1 day'),
+ label: getTimeLabel(1),
+ shortcut: '1_day',
duration: { seconds: 60 * 60 * 24 * 1 },
name: 'oneDay',
interval: INTERVALS.hour,
},
{
- label: __('3 days'),
+ label: getTimeLabel(3),
+ shortcut: '3_days',
duration: { seconds: 60 * 60 * 24 * 3 },
name: 'threeDays',
interval: INTERVALS.hour,
},
{
- label: __('7 days'),
+ label: getTimeLabel(7),
+ shortcut: '7_days',
duration: { seconds: 60 * 60 * 24 * 7 * 1 },
name: 'oneWeek',
interval: INTERVALS.day,
},
{
- label: __('30 days'),
+ label: getTimeLabel(30),
+ shortcut: '30_days',
duration: { seconds: 60 * 60 * 24 * 30 },
name: 'oneMonth',
interval: INTERVALS.day,
},
];
+/* eslint-enable @gitlab/require-i18n-strings */
export const defaultTimeRange = timeRanges.find((tr) => tr.default);
export const getTimeWindow = (timeWindowName) =>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
index b616b390032..38083327593 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
@@ -7,6 +7,7 @@ import { differenceInSeconds, getTimeago, SECONDS_IN_DAY } from '~/lib/utils/dat
import { isExternal, setUrlFragment } from '~/lib/utils/url_utility';
import { __, n__, sprintf } from '~/locale';
import IssuableAssignees from '~/issuable/components/issue_assignees.vue';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
@@ -17,6 +18,7 @@ export default {
GlFormCheckbox,
GlSprintf,
IssuableAssignees,
+ WorkItemTypeIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -50,6 +52,11 @@ export default {
required: false,
default: false,
},
+ showWorkItemTypeIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
issuableId() {
@@ -118,8 +125,8 @@ export default {
return sprintf(
n__(
- '%{completedCount} of %{count} task completed',
- '%{completedCount} of %{count} tasks completed',
+ '%{completedCount} of %{count} checklist item completed',
+ '%{completedCount} of %{count} checklist items completed',
count,
),
{ completedCount, count },
@@ -225,6 +232,7 @@ export default {
</span>
</div>
<div class="issuable-info">
+ <work-item-type-icon v-if="showWorkItemTypeIcon" :work-item-type="issuable.type" />
<slot v-if="hasSlotContents('reference')" name="reference"></slot>
<span v-else data-testid="issuable-reference" class="issuable-reference">
{{ reference }}
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
index 189bbb56432..bc10f84b819 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -182,6 +182,11 @@ export default {
required: false,
default: false,
},
+ showWorkItemTypeIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -344,6 +349,7 @@ export default {
:label-filter-param="labelFilterParam"
:show-checkbox="showBulkEditSidebar"
:checked="issuableChecked(issuable)"
+ :show-work-item-type-icon="showWorkItemTypeIcon"
@checked-input="handleIssuableCheckedInput(issuable, $event)"
>
<template #reference>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/constants.js b/app/assets/javascripts/vue_shared/issuable/list/constants.js
index 507f333a34e..f6b864dfde0 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/constants.js
+++ b/app/assets/javascripts/vue_shared/issuable/list/constants.js
@@ -46,13 +46,6 @@ export const AvailableSortOptions = [
},
];
-export const IssuableTypes = {
- Issue: 'ISSUE',
- Incident: 'INCIDENT',
- TestCase: 'TEST_CASE',
- Requirement: 'REQUIREMENT',
-};
-
export const DEFAULT_PAGE_SIZE = 20;
export const DEFAULT_SKELETON_COUNT = 5;
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
index cdc5903b934..1f23fdfaafd 100644
--- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
@@ -12,6 +12,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isExternal } from '~/lib/utils/url_utility';
import { n__, sprintf } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import { IssuableStates } from '~/vue_shared/issuable/list/constants';
export default {
@@ -22,6 +23,7 @@ export default {
GlAvatarLink,
GlAvatarLabeled,
TimeAgoTooltip,
+ WorkItemTypeIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -65,6 +67,16 @@ export default {
required: false,
default: null,
},
+ issuableType: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ showWorkItemTypeIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
badgeVariant() {
@@ -81,8 +93,8 @@ export default {
return sprintf(
n__(
- '%{completedCount} of %{count} task completed',
- '%{completedCount} of %{count} tasks completed',
+ '%{completedCount} of %{count} checklist item completed',
+ '%{completedCount} of %{count} checklist items completed',
count,
),
{ completedCount, count },
@@ -122,7 +134,13 @@ export default {
</div>
</div>
<span>
- {{ __('Created') }}
+ <template v-if="showWorkItemTypeIcon">
+ <work-item-type-icon :work-item-type="issuableType" show-text />
+ {{ __('created') }}
+ </template>
+ <template v-else>
+ {{ __('Created') }}
+ </template>
<time-ago-tooltip data-testid="startTimeItem" :time="createdAt" />
{{ __('by') }}
</span>
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue
index 7ed93c042f8..2bc57ecba55 100644
--- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue
@@ -87,6 +87,11 @@ export default {
required: false,
default: 0,
},
+ showWorkItemTypeIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
methods: {
handleKeydownTitle(e, issuableMeta) {
@@ -110,6 +115,8 @@ export default {
:created-at="issuable.createdAt"
:author="issuable.author"
:task-completion-status="taskCompletionStatus"
+ :issuable-type="issuable.type"
+ :show-work-item-type-icon="showWorkItemTypeIcon"
>
<template #status-badge>
<slot name="status-badge"></slot>
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 8e9b8ef3e6f..232749a2d01 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
@@ -125,7 +125,7 @@ export default {
<h4>{{ activePanel.title }}</h4>
<p v-if="hasTextDetails">{{ details }}</p>
- <component :is="details" v-else />
+ <component :is="details" v-else v-bind="activePanel.detailProps || {}" />
<slot name="extra-description"></slot>
</div>
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index 0c55cc2f8a6..9e5361e8302 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -79,7 +79,7 @@ export default {
@bottomReached="bottomReached"
>
<template #items>
- <feature v-for="feature in features" :key="feature.title" :feature="feature" />
+ <feature v-for="feature in features" :key="feature.name" :feature="feature" />
</template>
</gl-infinite-scroll>
</template>
diff --git a/app/assets/javascripts/whats_new/components/feature.vue b/app/assets/javascripts/whats_new/components/feature.vue
index 90f6230ef72..c954a86e593 100644
--- a/app/assets/javascripts/whats_new/components/feature.vue
+++ b/app/assets/javascripts/whats_new/components/feature.vue
@@ -30,7 +30,6 @@ export default {
return dateInWords(date);
},
},
- safeHtmlConfig: { ADD_ATTR: ['target'] },
};
</script>
@@ -38,35 +37,35 @@ export default {
<div class="gl-py-6 gl-px-6 gl-border-b-1 gl-border-b-solid gl-border-b-gray-100">
<gl-link
v-if="feature.image_url"
- :href="feature.url"
+ :href="feature.documentation_link"
target="_blank"
class="gl-display-block"
data-testid="whats-new-image-link"
data-track-action="click_whats_new_item"
- :data-track-label="feature.title"
- :data-track-property="feature.url"
+ :data-track-label="feature.name"
+ :data-track-property="feature.documentation_link"
>
<div
class="whats-new-item-image gl-bg-size-cover"
:style="`background-image: url(${feature.image_url});`"
>
- <span class="gl-sr-only">{{ feature.title }}</span>
+ <span class="gl-sr-only">{{ feature.name }}</span>
</div>
</gl-link>
<gl-link
- :href="feature.url"
+ :href="feature.documentation_link"
target="_blank"
class="whats-new-item-title-link gl-display-block gl-mt-4 gl-mb-1"
data-track-action="click_whats_new_item"
- :data-track-label="feature.title"
- :data-track-property="feature.url"
+ :data-track-label="feature.name"
+ :data-track-property="feature.documentation_link"
>
- <h5 class="gl-font-lg gl-my-0" data-test-id="feature-title">{{ feature.title }}</h5>
+ <h5 class="gl-font-lg gl-my-0" data-test-id="feature-name">{{ feature.name }}</h5>
</gl-link>
<div v-if="releaseDate" class="gl-mb-3" data-testid="release-date">{{ releaseDate }}</div>
- <div v-if="feature.packages" class="gl-mb-3">
+ <div v-if="feature.available_in" class="gl-mb-3">
<gl-badge
- v-for="packageName in feature.packages"
+ v-for="packageName in feature.available_in"
:key="packageName"
size="md"
variant="tier"
@@ -77,15 +76,15 @@ export default {
</gl-badge>
</div>
<div
- v-safe-html:[$options.safeHtmlConfig]="feature.body"
+ v-safe-html:[$options.safeHtmlConfig]="feature.description"
class="gl-pt-3 gl-line-height-20"
></div>
<gl-button
- :href="feature.url"
+ :href="feature.documentation_link"
target="_blank"
data-track-action="click_whats_new_item"
- :data-track-label="feature.title"
- :data-track-property="feature.url"
+ :data-track-label="feature.name"
+ :data-track-property="feature.documentation_link"
>
{{ __('Learn more') }} <gl-icon name="arrow-right" />
</gl-button>
diff --git a/app/assets/javascripts/work_items/components/item_state.vue b/app/assets/javascripts/work_items/components/item_state.vue
index 2dc8e3a1101..2a0913e380a 100644
--- a/app/assets/javascripts/work_items/components/item_state.vue
+++ b/app/assets/javascripts/work_items/components/item_state.vue
@@ -26,7 +26,7 @@ export default {
type: String,
required: true,
},
- loading: {
+ disabled: {
type: Boolean,
required: false,
default: false,
@@ -61,15 +61,17 @@ export default {
:id="$options.labelId"
:value="state"
:options="$options.states"
- :disabled="loading"
- class="gl-w-auto hide-select-decoration"
+ :disabled="disabled"
+ class="gl-w-auto hide-select-decoration gl-pl-3"
+ :class="{ 'gl-bg-transparent! gl-cursor-text!': disabled }"
@change="setState"
/>
</gl-form-group>
</template>
<style>
-.hide-select-decoration:not(:focus, :hover) {
+.hide-select-decoration:not(:focus, :hover),
+.hide-select-decoration:disabled {
background-image: none;
box-shadow: none;
}
diff --git a/app/assets/javascripts/work_items/components/item_title.vue b/app/assets/javascripts/work_items/components/item_title.vue
index 1cdc9c28f05..551ebbadb21 100644
--- a/app/assets/javascripts/work_items/components/item_title.vue
+++ b/app/assets/javascripts/work_items/components/item_title.vue
@@ -36,7 +36,7 @@ export default {
<template>
<h2
class="gl-font-weight-normal gl-sm-font-weight-bold gl-mb-5 gl-mt-0 gl-w-full"
- :class="{ 'gl-cursor-not-allowed': disabled }"
+ :class="{ 'gl-cursor-text': disabled }"
aria-labelledby="item-title"
>
<div
@@ -46,7 +46,8 @@ export default {
:aria-label="__('Title')"
:data-placeholder="placeholder"
:contenteditable="!disabled"
- class="gl-pseudo-placeholder gl-px-4 gl-py-3 gl-ml-n4 gl-border gl-border-white gl-hover-border-gray-200 gl-rounded-base"
+ class="gl-px-4 gl-py-3 gl-ml-n4 gl-border gl-border-white gl-rounded-base"
+ :class="{ 'gl-hover-border-gray-200 gl-pseudo-placeholder': !disabled }"
@blur="handleBlur"
@keyup="handleInput"
@keydown.enter.exact="handleSubmit"
diff --git a/app/assets/javascripts/work_items/components/work_item_actions.vue b/app/assets/javascripts/work_items/components/work_item_actions.vue
index 77002eeaf55..2753c3fa388 100644
--- a/app/assets/javascripts/work_items/components/work_item_actions.vue
+++ b/app/assets/javascripts/work_items/components/work_item_actions.vue
@@ -1,15 +1,24 @@
<script>
-import { GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlModal,
+ GlModalDirective,
+} from '@gitlab/ui';
import { s__ } from '~/locale';
import Tracking from '~/tracking';
export default {
i18n: {
deleteTask: s__('WorkItem|Delete task'),
+ enableTaskConfidentiality: s__('WorkItem|Turn on confidentiality'),
+ disableTaskConfidentiality: s__('WorkItem|Turn off confidentiality'),
},
components: {
GlDropdown,
GlDropdownItem,
+ GlDropdownDivider,
GlModal,
},
directives: {
@@ -22,14 +31,33 @@ export default {
required: false,
default: null,
},
+ canUpdate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
canDelete: {
type: Boolean,
required: false,
default: false,
},
+ isConfidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isParentConfidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
- emits: ['deleteWorkItem'],
+ emits: ['deleteWorkItem', 'toggleWorkItemConfidentiality'],
methods: {
+ handleToggleWorkItemConfidentiality() {
+ this.track('click_toggle_work_item_confidentiality');
+ this.$emit('toggleWorkItemConfidentiality', !this.isConfidential);
+ },
handleDeleteWorkItem() {
this.track('click_delete_work_item');
this.$emit('deleteWorkItem');
@@ -44,7 +72,7 @@ export default {
</script>
<template>
- <div v-if="canDelete">
+ <div>
<gl-dropdown
icon="ellipsis_v"
text-sr-only
@@ -53,9 +81,24 @@ export default {
no-caret
right
>
- <gl-dropdown-item v-gl-modal="'work-item-confirm-delete'">{{
- $options.i18n.deleteTask
- }}</gl-dropdown-item>
+ <template v-if="canUpdate && !isParentConfidential">
+ <gl-dropdown-item
+ data-testid="confidentiality-toggle-action"
+ @click="handleToggleWorkItemConfidentiality"
+ >{{
+ isConfidential
+ ? $options.i18n.disableTaskConfidentiality
+ : $options.i18n.enableTaskConfidentiality
+ }}</gl-dropdown-item
+ >
+ <gl-dropdown-divider v-if="canDelete" />
+ </template>
+ <gl-dropdown-item
+ v-if="canDelete"
+ v-gl-modal="'work-item-confirm-delete'"
+ data-testid="delete-action"
+ >{{ $options.i18n.deleteTask }}</gl-dropdown-item
+ >
</gl-dropdown>
<gl-modal
modal-id="work-item-confirm-delete"
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 9ff424aa20f..7342f215b5e 100644
--- a/app/assets/javascripts/work_items/components/work_item_assignees.vue
+++ b/app/assets/javascripts/work_items/components/work_item_assignees.vue
@@ -18,11 +18,17 @@ import { n__, s__ } from '~/locale';
import Tracking from '~/tracking';
import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
+import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import { i18n, TRACKING_CATEGORY_SHOW } from '../constants';
function isTokenSelectorElement(el) {
- return el?.classList.contains('gl-token-close') || el?.classList.contains('dropdown-item');
+ return (
+ el?.classList.contains('gl-token-close') ||
+ el?.classList.contains('dropdown-item') ||
+ // TODO: replace this logic when we have a class added to clear-all button in GitLab UI
+ (el?.classList.contains('gl-button') &&
+ el?.closest('.form-control')?.classList.contains('gl-token-selector'))
+ );
}
function addClass(el) {
@@ -69,6 +75,11 @@ export default {
required: false,
default: false,
},
+ canInviteMembers: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -130,7 +141,7 @@ export default {
if (this.searchUsers.some((user) => user.username === this.currentUser.username)) {
return this.moveCurrentUserToStart(this.searchUsers);
}
- return [this.currentUser, ...this.searchUsers];
+ return [addClass(this.currentUser), ...this.searchUsers];
}
return this.searchUsers;
},
@@ -138,16 +149,25 @@ export default {
return this.searchKey.length === 0;
},
addAssigneesText() {
+ if (!this.canUpdate) {
+ return s__('WorkItem|None');
+ }
return this.allowsMultipleAssignees
? s__('WorkItem|Add assignees')
: s__('WorkItem|Add assignee');
},
+ assigneeIds() {
+ return this.localAssignees.map(({ id }) => id);
+ },
},
watch: {
- assignees(newVal) {
- if (!this.isEditing) {
- this.localAssignees = newVal.map(addClass);
- }
+ assignees: {
+ handler(newVal) {
+ if (!this.isEditing) {
+ this.localAssignees = newVal.map(addClass);
+ }
+ },
+ deep: true,
},
},
created() {
@@ -169,19 +189,33 @@ export default {
handleBlur(e) {
if (isTokenSelectorElement(e.relatedTarget) || !this.isEditing) return;
this.isEditing = false;
- this.setAssignees(this.localAssignees);
+ this.setAssignees(this.assigneeIds);
},
- setAssignees(assignees) {
- this.$apollo.mutate({
- mutation: localUpdateWorkItemMutation,
- variables: {
- input: {
- id: this.workItemId,
- assignees,
+ async setAssignees(assigneeIds) {
+ try {
+ const {
+ data: {
+ workItemUpdate: { errors },
},
- },
- });
- this.track('updated_assignees');
+ } = await this.$apollo.mutate({
+ mutation: updateWorkItemMutation,
+ variables: {
+ input: {
+ id: this.workItemId,
+ assigneesWidget: {
+ assigneeIds,
+ },
+ },
+ },
+ });
+ if (errors.length > 0) {
+ this.throwUpdateError();
+ return;
+ }
+ this.track('updated_assignees');
+ } catch {
+ this.throwUpdateError();
+ }
},
handleFocus() {
this.isEditing = true;
@@ -205,13 +239,25 @@ export default {
},
moveCurrentUserToStart(users = []) {
if (this.currentUser) {
- return [this.currentUser, ...users.filter((user) => user.id !== this.currentUser.id)];
+ return [
+ addClass(this.currentUser),
+ ...users.filter((user) => user.id !== this.currentUser.id),
+ ];
}
return users;
},
closeDropdown() {
this.$refs.tokenSelector.closeDropdown();
},
+ assignToCurrentUser() {
+ this.setAssignees([this.currentUser.id]);
+ this.localAssignees = [addClass(this.currentUser)];
+ },
+ throwUpdateError() {
+ this.$emit('error', i18n.updateError);
+ // If mutation is rejected, we're rolling back to initial state
+ this.localAssignees = this.assignees.map(addClass);
+ },
},
};
</script>
@@ -227,11 +273,12 @@ export default {
ref="tokenSelector"
:selected-tokens="localAssignees"
:container-class="containerClass"
- class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0!"
:class="{ 'gl-hover-border-gray-200': canUpdate }"
:dropdown-items="dropdownItems"
:loading="isLoadingUsers"
:view-only="!canUpdate"
+ :allow-clear-all="isEditing"
+ class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2"
@input="handleAssigneesInput"
@text-input="debouncedSearchKeyUpdate"
@focus="handleFocus"
@@ -241,7 +288,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-top-2"
+ 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"
data-testid="empty-state"
>
<gl-icon name="profile" />
@@ -251,7 +298,7 @@ export default {
size="small"
class="assign-myself"
data-testid="assign-self"
- @click.stop="setAssignees([currentUser])"
+ @click.stop="assignToCurrentUser"
>{{ __('Assign myself') }}</gl-button
>
</div>
@@ -262,7 +309,7 @@ export default {
:title="token.name"
:data-user-id="getUserId(token.id)"
data-placement="top"
- class="gl-text-decoration-none! gl-text-body! gl-display-flex gl-md-display-inline-flex! gl-align-items-center js-user-link"
+ class="gl-ml-n2 gl-text-decoration-none! gl-text-body! gl-display-flex gl-md-display-inline-flex! gl-align-items-center js-user-link"
>
<gl-avatar :size="24" :src="token.avatarUrl" />
<span class="gl-pl-2">{{ token.name }}</span>
@@ -279,7 +326,7 @@ export default {
<rect width="280" height="20" x="10" y="130" rx="4" />
</gl-skeleton-loader>
</template>
- <template #dropdown-footer>
+ <template v-if="canInviteMembers" #dropdown-footer>
<gl-dropdown-divider />
<gl-dropdown-item @click="closeDropdown">
<invite-members-trigger
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 90e3cd45cb4..cf59789ce2d 100644
--- a/app/assets/javascripts/work_items/components/work_item_description.vue
+++ b/app/assets/javascripts/work_items/components/work_item_description.vue
@@ -172,7 +172,7 @@ export default {
<template>
<gl-form-group
v-if="isEditing"
- class="gl-my-5"
+ class="gl-my-5 gl-border-t gl-pt-6"
:label="__('Description')"
label-for="work-item-description"
>
@@ -182,7 +182,7 @@ export default {
:is-submitting="isSubmitting"
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="$options.markdownDocsPath"
- class="gl-p-3 bordered-box"
+ class="gl-p-3 bordered-box gl-mt-5"
>
<template #textarea>
<textarea
@@ -217,9 +217,9 @@ export default {
}}</gl-button>
</div>
</gl-form-group>
- <div v-else class="gl-mb-5">
- <div class="gl-display-flex gl-align-items-center gl-mb-5">
- <h3 class="gl-font-base gl-my-0">{{ __('Description') }}</h3>
+ <div v-else class="gl-mb-5 gl-border-t">
+ <div class="gl-display-inline-flex gl-align-items-center gl-mb-5">
+ <label class="d-block col-form-label gl-mr-5">{{ __('Description') }}</label>
<gl-button
v-if="canEdit"
class="gl-ml-auto"
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 ad90fe88947..a5580c14a7a 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -1,7 +1,16 @@
<script>
-import { GlAlert, GlSkeletonLoader, GlIcon, GlButton } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlSkeletonLoader,
+ GlLoadingIcon,
+ GlIcon,
+ GlBadge,
+ GlButton,
+ GlTooltipDirective,
+} from '@gitlab/ui';
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';
import {
i18n,
WIDGET_TYPE_ASSIGNEES,
@@ -11,8 +20,12 @@ import {
WIDGET_TYPE_HIERARCHY,
WORK_ITEM_VIEWED_STORAGE_KEY,
} from '../constants';
+
import workItemQuery from '../graphql/work_item.query.graphql';
import workItemTitleSubscription from '../graphql/work_item_title.subscription.graphql';
+import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
+import updateWorkItemTaskMutation from '../graphql/update_work_item_task.mutation.graphql';
+
import WorkItemActions from './work_item_actions.vue';
import WorkItemState from './work_item_state.vue';
import WorkItemTitle from './work_item_title.vue';
@@ -24,9 +37,14 @@ import WorkItemInformation from './work_item_information.vue';
export default {
i18n,
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
components: {
GlAlert,
+ GlBadge,
GlButton,
+ GlLoadingIcon,
GlSkeletonLoader,
GlIcon,
WorkItemAssignees,
@@ -38,6 +56,7 @@ export default {
WorkItemWeight,
WorkItemInformation,
LocalStorageSync,
+ WorkItemTypeIcon,
},
mixins: [glFeatureFlagMixin()],
props: {
@@ -62,6 +81,7 @@ export default {
error: undefined,
workItem: {},
showInfoBanner: true,
+ updateInProgress: false,
};
},
apollo: {
@@ -114,7 +134,7 @@ export default {
return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_LABELS);
},
workItemWeight() {
- return this.workItem?.mockWidgets?.find((widget) => widget.type === WIDGET_TYPE_WEIGHT);
+ return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_WEIGHT);
},
workItemHierarchy() {
return this.workItem?.widgets?.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY);
@@ -122,9 +142,15 @@ export default {
parentWorkItem() {
return this.workItemHierarchy?.parent;
},
+ parentWorkItemConfidentiality() {
+ return this.parentWorkItem?.confidential;
+ },
parentUrl() {
return `../../issues/${this.parentWorkItem?.iid}`;
},
+ workItemIconName() {
+ return this.workItem?.workItemType?.iconName;
+ },
},
beforeDestroy() {
/** make sure that if the user has not even dismissed the alert ,
@@ -135,6 +161,54 @@ export default {
dismissBanner() {
this.showInfoBanner = false;
},
+ toggleConfidentiality(confidentialStatus) {
+ this.updateInProgress = true;
+ let updateMutation = updateWorkItemMutation;
+ let inputVariables = {
+ id: this.workItemId,
+ confidential: confidentialStatus,
+ };
+
+ if (this.parentWorkItem) {
+ updateMutation = updateWorkItemTaskMutation;
+ inputVariables = {
+ id: this.parentWorkItem.id,
+ taskData: {
+ id: this.workItemId,
+ confidential: confidentialStatus,
+ },
+ };
+ }
+
+ this.$apollo
+ .mutate({
+ mutation: updateMutation,
+ variables: {
+ input: inputVariables,
+ },
+ })
+ .then(
+ ({
+ data: {
+ workItemUpdate: { errors, workItem, task },
+ },
+ }) => {
+ if (errors?.length) {
+ throw new Error(errors[0]);
+ }
+
+ this.$emit('workItemUpdated', {
+ confidential: workItem?.confidential || task?.confidential,
+ });
+ },
+ )
+ .catch((error) => {
+ this.error = error.message;
+ })
+ .finally(() => {
+ this.updateInProgress = false;
+ });
+ },
},
WORK_ITEM_VIEWED_STORAGE_KEY,
};
@@ -142,7 +216,7 @@ export default {
<template>
<section class="gl-pt-5">
- <gl-alert v-if="error" variant="danger" @dismiss="error = undefined">
+ <gl-alert v-if="error" class="gl-mb-3" variant="danger" @dismiss="error = undefined">
{{ error }}
</gl-alert>
@@ -153,33 +227,61 @@ export default {
</gl-skeleton-loader>
</div>
<template v-else>
- <div class="gl-display-flex gl-align-items-center">
+ <div class="gl-display-flex gl-align-items-center" data-testid="work-item-body">
<ul
v-if="parentWorkItem"
- class="list-unstyled gl-display-flex gl-mr-auto"
+ class="list-unstyled gl-display-flex gl-mr-auto gl-max-w-26 gl-md-max-w-50p gl-min-w-0 gl-mb-0"
data-testid="work-item-parent"
>
- <li class="gl-ml-n4">
- <gl-button icon="issues" category="tertiary" :href="parentUrl">{{
- parentWorkItem.title
- }}</gl-button>
- <gl-icon name="chevron-right" :size="16" />
+ <li class="gl-ml-n4 gl-display-flex gl-align-items-center gl-overflow-hidden">
+ <gl-button
+ v-gl-tooltip.hover
+ class="gl-text-truncate gl-max-w-full"
+ icon="issues"
+ category="tertiary"
+ :href="parentUrl"
+ :title="parentWorkItem.title"
+ >{{ parentWorkItem.title }}</gl-button
+ >
+ <gl-icon name="chevron-right" :size="16" class="gl-flex-shrink-0" />
</li>
- <li class="gl-px-4 gl-py-3 gl-line-height-0">
- <gl-icon name="task-done" />
+ <li
+ class="gl-px-4 gl-py-3 gl-line-height-0 gl-display-flex gl-align-items-center gl-overflow-hidden gl-flex-shrink-0"
+ >
+ <work-item-type-icon
+ :work-item-icon-name="workItemIconName"
+ :work-item-type="workItemType && workItemType.toUpperCase()"
+ />
{{ workItemType }}
</li>
</ul>
- <span
+ <work-item-type-icon
v-else
+ :work-item-icon-name="workItemIconName"
+ :work-item-type="workItemType && workItemType.toUpperCase()"
+ show-text
class="gl-font-weight-bold gl-text-secondary gl-mr-auto"
data-testid="work-item-type"
- >{{ workItemType }}</span
+ />
+ <gl-loading-icon v-if="updateInProgress" :inline="true" class="gl-mr-3" />
+ <gl-badge
+ v-if="workItem.confidential"
+ v-gl-tooltip.bottom
+ :title="$options.i18n.confidentialTooltip"
+ variant="warning"
+ icon="eye-slash"
+ class="gl-mr-3 gl-cursor-help"
+ >{{ __('Confidential') }}</gl-badge
>
<work-item-actions
+ v-if="canUpdate || canDelete"
:work-item-id="workItem.id"
:can-delete="canDelete"
+ :can-update="canUpdate"
+ :is-confidential="workItem.confidential"
+ :is-parent-confidential="parentWorkItemConfidentiality"
@deleteWorkItem="$emit('deleteWorkItem')"
+ @toggleWorkItemConfidentiality="toggleConfidentiality"
@error="error = $event"
/>
<gl-button
@@ -206,11 +308,13 @@ export default {
:work-item-title="workItem.title"
:work-item-type="workItemType"
:work-item-parent-id="workItemParentId"
+ :can-update="canUpdate"
@error="error = $event"
/>
<work-item-state
:work-item="workItem"
:work-item-parent-id="workItemParentId"
+ :can-update="canUpdate"
@error="error = $event"
/>
<template v-if="workItemsMvc2Enabled">
@@ -221,6 +325,7 @@ export default {
:assignees="workItemAssignees.assignees.nodes"
:allows-multiple-assignees="workItemAssignees.allowsMultipleAssignees"
:work-item-type="workItemType"
+ :can-invite-members="workItemAssignees.canInviteMembers"
@error="error = $event"
/>
<work-item-labels
@@ -229,15 +334,16 @@ export default {
:can-update="canUpdate"
@error="error = $event"
/>
- <work-item-weight
- v-if="workItemWeight"
- class="gl-mb-5"
- :can-update="canUpdate"
- :weight="workItemWeight.weight"
- :work-item-id="workItem.id"
- :work-item-type="workItemType"
- />
</template>
+ <work-item-weight
+ v-if="workItemWeight"
+ class="gl-mb-5"
+ :can-update="canUpdate"
+ :weight="workItemWeight.weight"
+ :work-item-id="workItem.id"
+ :work-item-type="workItemType"
+ @error="error = $event"
+ />
<work-item-description
v-if="hasDescriptionWidget"
:work-item-id="workItem.id"
diff --git a/app/assets/javascripts/work_items/components/work_item_detail_modal.vue b/app/assets/javascripts/work_items/components/work_item_detail_modal.vue
index df7c6cab7ef..39a662a6c54 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail_modal.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail_modal.vue
@@ -2,9 +2,13 @@
import { GlAlert, GlModal } from '@gitlab/ui';
import { s__ } from '~/locale';
import deleteWorkItemFromTaskMutation from '../graphql/delete_task_from_work_item.mutation.graphql';
+import deleteWorkItemMutation from '../graphql/delete_work_item.mutation.graphql';
import WorkItemDetail from './work_item_detail.vue';
export default {
+ i18n: {
+ errorMessage: s__('WorkItem|Something went wrong when deleting the task. Please try again.'),
+ },
components: {
GlAlert,
GlModal,
@@ -45,6 +49,13 @@ export default {
},
methods: {
deleteWorkItem() {
+ if (this.lockVersion != null && this.lineNumberStart && this.lineNumberEnd) {
+ this.deleteWorkItemWithTaskData();
+ } else {
+ this.deleteWorkItemWithoutTaskData();
+ }
+ },
+ deleteWorkItemWithTaskData() {
this.$apollo
.mutate({
mutation: deleteWorkItemFromTaskMutation,
@@ -70,17 +81,33 @@ export default {
},
}) => {
if (errors?.length) {
- throw new Error(errors[0].message);
+ throw new Error(errors[0]);
}
this.$emit('workItemDeleted', descriptionHtml);
- this.$refs.modal.hide();
+ this.hide();
},
)
- .catch((e) => {
- this.error =
- e.message ||
- s__('WorkItem|Something went wrong when deleting the task. Please try again.');
+ .catch((error) => {
+ this.setErrorMessage(error.message);
+ });
+ },
+ deleteWorkItemWithoutTaskData() {
+ this.$apollo
+ .mutate({
+ mutation: deleteWorkItemMutation,
+ variables: { input: { id: this.workItemId } },
+ })
+ .then(({ data }) => {
+ if (data.workItemDelete.errors?.length) {
+ throw new Error(data.workItemDelete.errors[0]);
+ }
+
+ this.$emit('workItemDeleted', this.workItemId);
+ this.hide();
+ })
+ .catch((error) => {
+ this.setErrorMessage(error.message);
});
},
closeModal() {
@@ -91,7 +118,7 @@ export default {
this.$refs.modal.hide();
},
setErrorMessage(message) {
- this.error = message;
+ this.error = message || this.$options.i18n.errorMessage;
},
show() {
this.$refs.modal.show();
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 78ed67998d7..e73488bbd70 100644
--- a/app/assets/javascripts/work_items/components/work_item_labels.vue
+++ b/app/assets/javascripts/work_items/components/work_item_labels.vue
@@ -202,7 +202,8 @@ export default {
:dropdown-items="searchLabels"
:loading="isLoading"
:view-only="!canUpdate"
- class="gl-flex-grow-1 gl-border gl-border-white gl-hover-border-gray-200 gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2!"
+ class="gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2!"
+ :class="{ 'gl-hover-border-gray-200': canUpdate }"
@input="focusTokenSelector"
@text-input="debouncedSearchKeyUpdate"
@focus="handleFocus"
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 176f84f6c1a..86f03583ea3 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
@@ -1,16 +1,10 @@
import Vue from 'vue';
-import VueApollo from 'vue-apollo';
import { GlToast } from '@gitlab/ui';
-import createDefaultClient from '~/lib/graphql';
+import { createApolloProvider } from '../../graphql/provider';
import WorkItemLinks from './work_item_links.vue';
-Vue.use(VueApollo);
Vue.use(GlToast);
-const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
-});
-
export default function initWorkItemLinks() {
if (!window.gon.features.workItemsHierarchy) {
return;
@@ -22,16 +16,20 @@ export default function initWorkItemLinks() {
return;
}
+ const { projectPath, wiHasIssueWeightsFeature } = workItemLinksRoot.dataset;
+
// eslint-disable-next-line no-new
new Vue({
el: workItemLinksRoot,
name: 'WorkItemLinksRoot',
- apolloProvider,
+ apolloProvider: createApolloProvider(),
components: {
workItemLinks: WorkItemLinks,
},
provide: {
- projectPath: workItemLinksRoot.dataset.projectPath,
+ projectPath,
+ fullPath: projectPath,
+ hasIssueWeightsFeature: wiHasIssueWeightsFeature,
},
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 89f086cfca5..534ebabee08 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
@@ -1,8 +1,14 @@
<script>
-import { GlButton, GlBadge, GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlIcon, GlAlert, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { produce } from 'immer';
import { s__ } from '~/locale';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
+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 { isMetaKey } from '~/lib/utils/common_utils';
+import { setUrlParams, updateHistory } from '~/lib/utils/url_utility';
+import SidebarEventHub from '~/sidebar/event_hub';
+
import {
STATE_OPEN,
WIDGET_ICONS,
@@ -10,18 +16,26 @@ import {
WIDGET_TYPE_HIERARCHY,
} from '../../constants';
import getWorkItemLinksQuery from '../../graphql/work_item_links.query.graphql';
+import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql';
+import workItemQuery from '../../graphql/work_item.query.graphql';
+import WorkItemDetailModal from '../work_item_detail_modal.vue';
import WorkItemLinksForm from './work_item_links_form.vue';
import WorkItemLinksMenu from './work_item_links_menu.vue';
export default {
components: {
GlButton,
- GlBadge,
GlIcon,
+ GlAlert,
GlLoadingIcon,
WorkItemLinksForm,
WorkItemLinksMenu,
+ WorkItemDetailModal,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
+ inject: ['projectPath'],
props: {
workItemId: {
type: String,
@@ -35,32 +49,44 @@ export default {
},
},
apollo: {
- children: {
+ workItem: {
query: getWorkItemLinksQuery,
variables() {
return {
id: this.issuableGid,
};
},
- update(data) {
- return (
- data.workItem.widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY)?.children
- .nodes ?? []
- );
- },
skip() {
return !this.issuableId;
},
+ error(e) {
+ this.error = e.message || this.$options.i18n.fetchError;
+ },
},
},
data() {
return {
isShownAddForm: false,
isOpen: true,
- children: [],
+ activeChildId: null,
+ activeToast: null,
+ prefetchedWorkItem: null,
+ error: undefined,
};
},
computed: {
+ children() {
+ return (
+ this.workItem?.widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY)?.children
+ .nodes ?? []
+ );
+ },
+ canUpdate() {
+ return this.workItem?.userPermissions.updateWorkItem || false;
+ },
+ confidential() {
+ return this.workItem?.confidential || false;
+ },
// Only used for children for now but should be extended later to support parents and siblings
isChildrenEmpty() {
return this.children?.length === 0;
@@ -77,28 +103,149 @@ export default {
return this.issuableId ? convertToGraphQLId(TYPE_WORK_ITEM, this.issuableId) : null;
},
isLoading() {
- return this.$apollo.queries.children.loading;
+ return this.$apollo.queries.workItem.loading;
},
childrenIds() {
return this.children.map((c) => c.id);
},
+ childrenCountLabel() {
+ return this.isLoading && this.children.length === 0 ? '...' : this.children.length;
+ },
+ },
+ mounted() {
+ SidebarEventHub.$on('confidentialityUpdated', this.refetchWorkItems);
+ },
+ destroyed() {
+ SidebarEventHub.$off('confidentialityUpdated', this.refetchWorkItems);
},
methods: {
- badgeVariant(state) {
- return state === STATE_OPEN ? 'success' : 'info';
+ refetchWorkItems() {
+ this.$apollo.queries.workItem.refetch();
+ },
+ iconClass(state) {
+ return state === STATE_OPEN ? 'gl-text-green-500' : 'gl-text-blue-500';
+ },
+ iconName(state) {
+ return state === STATE_OPEN ? 'issue-open-m' : 'issue-close';
},
toggle() {
this.isOpen = !this.isOpen;
},
- toggleAddForm() {
- this.isShownAddForm = !this.isShownAddForm;
+ showAddForm() {
+ this.isOpen = true;
+ this.isShownAddForm = true;
+ this.$nextTick(() => {
+ this.$refs.wiLinksForm.$refs.wiTitleInput?.$el.focus();
+ });
+ },
+ hideAddForm() {
+ this.isShownAddForm = false;
},
addChild(child) {
- this.children = [child, ...this.children];
+ const { defaultClient: client } = this.$apollo.provider.clients;
+ this.toggleChildFromCache(child, child.id, client);
+ },
+ openChild(childItemId, e) {
+ if (isMetaKey(e)) {
+ return;
+ }
+ e.preventDefault();
+ this.activeChildId = childItemId;
+ this.$refs.modal.show();
+ this.updateWorkItemIdUrlQuery(childItemId);
+ },
+ closeModal() {
+ this.activeChildId = null;
+ this.updateWorkItemIdUrlQuery(undefined);
+ },
+ handleWorkItemDeleted(childId) {
+ const { defaultClient: client } = this.$apollo.provider.clients;
+ this.toggleChildFromCache(null, childId, client);
+ this.activeToast = this.$toast.show(s__('WorkItem|Task deleted'));
+ },
+ updateWorkItemIdUrlQuery(childItemId) {
+ updateHistory({
+ url: setUrlParams({ work_item_id: getIdFromGraphQLId(childItemId) }),
+ replace: true,
+ });
+ },
+ childPath(childItemId) {
+ return `/${this.projectPath}/-/work_items/${getIdFromGraphQLId(childItemId)}`;
+ },
+ toggleChildFromCache(workItem, childId, store) {
+ const sourceData = store.readQuery({
+ query: getWorkItemLinksQuery,
+ variables: { id: this.issuableGid },
+ });
+
+ const newData = produce(sourceData, (draftState) => {
+ const widgetHierarchy = draftState.workItem.widgets.find(
+ (widget) => widget.type === WIDGET_TYPE_HIERARCHY,
+ );
+
+ const index = widgetHierarchy.children.nodes.findIndex((child) => child.id === childId);
+
+ if (index >= 0) {
+ widgetHierarchy.children.nodes.splice(index, 1);
+ } else {
+ widgetHierarchy.children.nodes.push(workItem);
+ }
+ });
+
+ store.writeQuery({
+ query: getWorkItemLinksQuery,
+ variables: { id: this.issuableGid },
+ data: newData,
+ });
+ },
+ async updateWorkItem(workItem, childId, parentId) {
+ return this.$apollo.mutate({
+ mutation: updateWorkItemMutation,
+ variables: { input: { id: childId, hierarchyWidget: { parentId } } },
+ update: (store) => this.toggleChildFromCache(workItem, childId, store),
+ });
+ },
+ async undoChildRemoval(workItem, childId) {
+ const { data } = await this.updateWorkItem(workItem, childId, this.issuableGid);
+
+ if (data.workItemUpdate.errors.length === 0) {
+ this.activeToast?.hide();
+ }
+ },
+ async removeChild(childId) {
+ const { data } = await this.updateWorkItem(null, childId, null);
+
+ if (data.workItemUpdate.errors.length === 0) {
+ this.activeToast = this.$toast.show(s__('WorkItem|Child removed'), {
+ action: {
+ text: s__('WorkItem|Undo'),
+ onClick: this.undoChildRemoval.bind(this, data.workItemUpdate.workItem, childId),
+ },
+ });
+ }
+ },
+ prefetchWorkItem(id) {
+ this.prefetch = setTimeout(
+ () =>
+ this.$apollo.addSmartQuery('prefetchedWorkItem', {
+ query: workItemQuery,
+ variables: {
+ id,
+ },
+ update: (data) => data.workItem,
+ }),
+ DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
+ );
+ },
+ clearPrefetching() {
+ clearTimeout(this.prefetch);
},
},
i18n: {
title: s__('WorkItem|Child items'),
+ fetchError: s__(
+ 'WorkItem|Something went wrong when fetching the items list. Please refresh this page.',
+ ),
emptyStateMessage: s__(
'WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!',
),
@@ -112,21 +259,32 @@ export default {
<template>
<div class="gl-rounded-base gl-border-1 gl-border-solid gl-border-gray-100 gl-bg-gray-10">
<div
- class="gl-p-4 gl-display-flex gl-justify-content-space-between"
+ class="gl-px-5 gl-py-3 gl-display-flex gl-justify-content-space-between"
:class="{ 'gl-border-b-1 gl-border-b-solid gl-border-b-gray-100': isOpen }"
>
- <h5 class="gl-m-0 gl-line-height-32 gl-flex-grow-1">{{ $options.i18n.title }}</h5>
+ <div class="gl-display-flex gl-flex-grow-1">
+ <h5 class="gl-m-0 gl-line-height-24">{{ $options.i18n.title }}</h5>
+ <span
+ 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" />
+ {{ childrenCountLabel }}
+ </span>
+ </div>
<gl-button
- v-if="!isShownAddForm"
+ v-if="canUpdate"
category="secondary"
+ size="small"
data-testid="toggle-add-form"
- @click="toggleAddForm"
+ @click="showAddForm"
>
{{ $options.i18n.addChildButtonLabel }}
</gl-button>
- <div class="gl-border-l-1 gl-border-l-solid gl-border-l-gray-50 gl-pl-4 gl-ml-3">
+ <div class="gl-border-l-1 gl-border-l-solid gl-border-l-gray-100 gl-pl-3 gl-ml-3">
<gl-button
category="tertiary"
+ size="small"
:icon="toggleIcon"
:aria-label="toggleLabel"
data-testid="toggle-links"
@@ -134,48 +292,81 @@ export default {
/>
</div>
</div>
+ <gl-alert v-if="error && !isLoading" variant="danger" @dismiss="error = undefined">
+ {{ error }}
+ </gl-alert>
<div
v-if="isOpen"
- class="gl-bg-gray-10 gl-p-4 gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
+ class="gl-bg-gray-10 gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
+ :class="{ 'gl-p-5 gl-pb-3': !error }"
data-testid="links-body"
>
<gl-loading-icon v-if="isLoading" color="dark" class="gl-my-3" />
<template v-else>
- <div v-if="isChildrenEmpty && !isShownAddForm" data-testid="links-empty">
- <p class="gl-my-3">
+ <div v-if="isChildrenEmpty && !isShownAddForm && !error" data-testid="links-empty">
+ <p class="gl-mt-3 gl-mb-4">
{{ $options.i18n.emptyStateMessage }}
</p>
</div>
<work-item-links-form
v-if="isShownAddForm"
+ ref="wiLinksForm"
data-testid="add-links-form"
:issuable-gid="issuableGid"
:children-ids="childrenIds"
- @cancel="toggleAddForm"
+ :parent-confidential="confidential"
+ @cancel="hideAddForm"
@addWorkItemChild="addChild"
/>
<div
v-for="child in children"
:key="child.id"
- class="gl-relative gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-overflow-break-word gl-min-w-0 gl-bg-white gl-mb-3 gl-py-3 gl-px-4 gl-border gl-border-gray-100 gl-rounded-base gl-line-height-32"
+ class="gl-relative gl-display-flex gl-overflow-break-word gl-min-w-0 gl-bg-white gl-mb-3 gl-py-3 gl-px-4 gl-border gl-border-gray-100 gl-rounded-base gl-line-height-32"
data-testid="links-child"
>
- <div>
- <gl-icon :name="$options.WIDGET_TYPE_TASK_ICON" class="gl-mr-3 gl-text-gray-700" />
- <span class="gl-word-break-all">{{ child.title }}</span>
+ <div class="gl-overflow-hidden gl-display-flex gl-align-items-center gl-flex-grow-1">
+ <gl-icon
+ :name="iconName(child.state)"
+ class="gl-mr-3"
+ :class="iconClass(child.state)"
+ />
+ <gl-icon
+ v-if="child.confidential"
+ v-gl-tooltip.top
+ name="eye-slash"
+ class="gl-mr-2 gl-text-orange-500"
+ data-testid="confidential-icon"
+ :title="__('Confidential')"
+ />
+ <gl-button
+ :href="childPath(child.id)"
+ category="tertiary"
+ variant="link"
+ class="gl-text-truncate gl-max-w-80 gl-text-black-normal!"
+ @click="openChild(child.id, $event)"
+ @mouseover="prefetchWorkItem(child.id)"
+ @mouseout="clearPrefetching"
+ >
+ {{ child.title }}
+ </gl-button>
</div>
- <div
- class="gl-ml-0 gl-sm-ml-auto! gl-mt-3 gl-sm-mt-0 gl-display-inline-flex gl-align-items-center"
- >
- <gl-badge :variant="badgeVariant(child.state)">
- <span class="gl-sm-display-block">{{
- $options.WORK_ITEM_STATUS_TEXT[child.state]
- }}</span>
- </gl-badge>
- <work-item-links-menu :work-item-id="child.id" :parent-work-item-id="issuableGid" />
+ <div class="gl-ml-0 gl-sm-ml-auto! gl-display-inline-flex gl-align-items-center">
+ <work-item-links-menu
+ v-if="canUpdate"
+ :work-item-id="child.id"
+ :parent-work-item-id="issuableGid"
+ data-testid="links-menu"
+ @removeChild="removeChild(child.id)"
+ />
</div>
</div>
+ <work-item-detail-modal
+ ref="modal"
+ :work-item-id="activeChildId"
+ @close="closeModal"
+ @workItemDeleted="handleWorkItemDeleted(activeChildId)"
+ />
</template>
</div>
</div>
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 fadba0753db..8b848995d44 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
@@ -1,9 +1,11 @@
<script>
-import { GlAlert, GlForm, GlFormCombobox, GlButton } from '@gitlab/ui';
+import { GlAlert, GlFormGroup, GlForm, GlFormCombobox, GlButton, GlFormInput } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __, s__ } from '~/locale';
-import projectWorkItemsQuery from '../../graphql/project_work_items.query.graphql';
+import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql';
+import createWorkItemMutation from '../../graphql/create_work_item.mutation.graphql';
+import { TASK_TYPE_NAME } from '../../constants';
export default {
components: {
@@ -11,6 +13,8 @@ export default {
GlForm,
GlFormCombobox,
GlButton,
+ GlFormGroup,
+ GlFormInput,
},
inject: ['projectPath'],
props: {
@@ -24,24 +28,22 @@ export default {
required: false,
default: () => [],
},
+ parentConfidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
apollo: {
- availableWorkItems: {
- query: projectWorkItemsQuery,
+ workItemTypes: {
+ query: projectWorkItemTypesQuery,
variables() {
return {
- projectPath: this.projectPath,
- searchTerm: this.search?.title || this.search,
- types: ['TASK'],
+ fullPath: this.projectPath,
};
},
- skip() {
- return this.search.length === 0;
- },
update(data) {
- return data.workspace.workItems.edges
- .filter((wi) => !this.childrenIds.includes(wi.node.id))
- .map((wi) => wi.node);
+ return data.workspace?.workItemTypes?.nodes;
},
},
},
@@ -50,8 +52,32 @@ export default {
availableWorkItems: [],
search: '',
error: null,
+ childToCreateTitle: null,
};
},
+ computed: {
+ actionsList() {
+ return [
+ {
+ label: this.$options.i18n.createChildOptionLabel,
+ fn: () => {
+ this.childToCreateTitle = this.search?.title || this.search;
+ },
+ },
+ ];
+ },
+ addOrCreateButtonLabel() {
+ return this.childToCreateTitle
+ ? this.$options.i18n.createChildOptionLabel
+ : this.$options.i18n.addTaskButtonLabel;
+ },
+ addOrCreateMethod() {
+ return this.childToCreateTitle ? this.createChild : this.addChild;
+ },
+ taskWorkItemType() {
+ return this.workItemTypes.find((type) => type.name === TASK_TYPE_NAME)?.id;
+ },
+ },
methods: {
getIdFromGraphQLId,
unsetError() {
@@ -79,35 +105,78 @@ export default {
}
})
.catch(() => {
- this.error = this.$options.i18n.errorMessage;
+ this.error = this.$options.i18n.addChildErrorMessage;
})
.finally(() => {
this.search = '';
});
},
+ createChild() {
+ this.$apollo
+ .mutate({
+ mutation: createWorkItemMutation,
+ variables: {
+ input: {
+ title: this.search?.title || this.search,
+ projectPath: this.projectPath,
+ workItemTypeId: this.taskWorkItemType,
+ hierarchyWidget: {
+ parentId: this.issuableGid,
+ },
+ confidential: this.parentConfidential,
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.workItemCreate?.errors?.length) {
+ [this.error] = data.workItemCreate.errors;
+ } else {
+ this.unsetError();
+ this.$emit('addWorkItemChild', data.workItemCreate.workItem);
+ }
+ })
+ .catch(() => {
+ this.error = this.$options.i18n.createChildErrorMessage;
+ })
+ .finally(() => {
+ this.search = '';
+ this.childToCreateTitle = null;
+ });
+ },
},
i18n: {
- inputLabel: __('Children'),
- errorMessage: s__(
+ inputLabel: __('Title'),
+ addTaskButtonLabel: s__('WorkItem|Add task'),
+ addChildErrorMessage: s__(
'WorkItem|Something went wrong when trying to add a child. Please try again.',
),
+ createChildOptionLabel: s__('WorkItem|Create task'),
+ createChildErrorMessage: s__(
+ 'WorkItem|Something went wrong when trying to create a child. Please try again.',
+ ),
+ placeholder: s__('WorkItem|Add a title'),
+ fieldValidationMessage: __('Maximum of 255 characters'),
},
};
</script>
<template>
<gl-form
- class="gl-mb-3 gl-bg-white gl-mb-3 gl-py-3 gl-px-4 gl-border gl-border-gray-100 gl-rounded-base"
+ class="gl-bg-white gl-mb-3 gl-p-4 gl-border gl-border-gray-100 gl-rounded-base"
+ @submit.prevent="createChild"
>
<gl-alert v-if="error" variant="danger" class="gl-mb-3" @dismiss="unsetError">
{{ error }}
</gl-alert>
+ <!-- Follow up issue to turn this functionality back on https://gitlab.com/gitlab-org/gitlab/-/issues/368757 -->
<gl-form-combobox
+ v-if="false"
v-model="search"
:token-list="availableWorkItems"
match-value-to-attr="title"
class="gl-mb-4"
:label-text="$options.i18n.inputLabel"
+ :action-list="actionsList"
label-sr-only
autofocus
>
@@ -117,11 +186,35 @@ export default {
<div>{{ item.title }}</div>
</div>
</template>
+ <template #action="{ item }">
+ <span class="gl-text-blue-500">{{ item.label }}</span>
+ </template>
</gl-form-combobox>
- <gl-button category="secondary" data-testid="add-child-button" @click="addChild">
- {{ s__('WorkItem|Add task') }}
+ <gl-form-group
+ :label="$options.i18n.inputLabel"
+ :description="$options.i18n.fieldValidationMessage"
+ >
+ <gl-form-input
+ ref="wiTitleInput"
+ v-model="search"
+ :placeholder="$options.i18n.placeholder"
+ maxlength="255"
+ class="gl-mb-3"
+ autofocus
+ />
+ </gl-form-group>
+ <gl-button
+ category="primary"
+ variant="confirm"
+ size="small"
+ type="submit"
+ :disabled="search.length === 0"
+ data-testid="add-child-button"
+ class="gl-mr-2"
+ >
+ {{ $options.i18n.createChildOptionLabel }}
</gl-button>
- <gl-button category="tertiary" @click="$emit('cancel')">
+ <gl-button category="secondary" size="small" @click="$emit('cancel')">
{{ s__('WorkItem|Cancel') }}
</gl-button>
</gl-form>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
index 6deb87c5dca..1aa4a433a58 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
@@ -1,10 +1,5 @@
<script>
import { GlIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { produce } from 'immer';
-import { s__ } from '~/locale';
-import changeWorkItemParentMutation from '../../graphql/change_work_item_parent_link.mutation.graphql';
-import getWorkItemLinksQuery from '../../graphql/work_item_links.query.graphql';
-import { WIDGET_TYPE_HIERARCHY } from '../../constants';
export default {
components: {
@@ -12,78 +7,6 @@ export default {
GlDropdown,
GlIcon,
},
- props: {
- workItemId: {
- type: String,
- required: true,
- },
- parentWorkItemId: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- activeToast: null,
- };
- },
- methods: {
- toggleChildFromCache(data, store) {
- const sourceData = store.readQuery({
- query: getWorkItemLinksQuery,
- variables: { id: this.parentWorkItemId },
- });
-
- const newData = produce(sourceData, (draftState) => {
- const widgetHierarchy = draftState.workItem.widgets.find(
- (widget) => widget.type === WIDGET_TYPE_HIERARCHY,
- );
-
- const index = widgetHierarchy.children.nodes.findIndex(
- (child) => child.id === this.workItemId,
- );
-
- if (index >= 0) {
- widgetHierarchy.children.nodes.splice(index, 1);
- } else {
- widgetHierarchy.children.nodes.push(data.workItemUpdate.workItem);
- }
- });
-
- store.writeQuery({
- query: getWorkItemLinksQuery,
- variables: { id: this.parentWorkItemId },
- data: newData,
- });
- },
- async addChild(data) {
- const { data: resp } = await this.$apollo.mutate({
- mutation: changeWorkItemParentMutation,
- variables: { id: this.workItemId, parentId: this.parentWorkItemId },
- update: this.toggleChildFromCache.bind(this, data),
- });
-
- if (resp.workItemUpdate.errors.length === 0) {
- this.activeToast?.hide();
- }
- },
- async removeChild() {
- const { data } = await this.$apollo.mutate({
- mutation: changeWorkItemParentMutation,
- variables: { id: this.workItemId, parentId: null },
- update: this.toggleChildFromCache.bind(this, null),
- });
-
- if (data.workItemUpdate.errors.length === 0) {
- this.activeToast = this.$toast.show(s__('WorkItem|Child removed'), {
- action: {
- text: s__('WorkItem|Undo'),
- onClick: this.addChild.bind(this, data),
- },
- });
- }
- },
- },
};
</script>
@@ -93,7 +16,7 @@ export default {
<template #button-content>
<gl-icon name="ellipsis_v" :size="14" />
</template>
- <gl-dropdown-item @click="removeChild">
+ <gl-dropdown-item @click="$emit('removeChild')">
{{ s__('WorkItem|Remove') }}
</gl-dropdown-item>
</gl-dropdown>
diff --git a/app/assets/javascripts/work_items/components/work_item_state.vue b/app/assets/javascripts/work_items/components/work_item_state.vue
index 87f4a8822b1..080d4025cc3 100644
--- a/app/assets/javascripts/work_items/components/work_item_state.vue
+++ b/app/assets/javascripts/work_items/components/work_item_state.vue
@@ -27,6 +27,11 @@ export default {
required: false,
default: null,
},
+ canUpdate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -102,7 +107,7 @@ export default {
<item-state
v-if="workItem.state"
:state="workItem.state"
- :loading="updateInProgress"
+ :disabled="updateInProgress || !canUpdate"
@changed="updateWorkItemState"
/>
</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_title.vue b/app/assets/javascripts/work_items/components/work_item_title.vue
index b4c13037038..cd5cc3894f6 100644
--- a/app/assets/javascripts/work_items/components/work_item_title.vue
+++ b/app/assets/javascripts/work_items/components/work_item_title.vue
@@ -31,6 +31,11 @@ export default {
required: false,
default: null,
},
+ canUpdate: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
tracking() {
@@ -84,5 +89,5 @@ export default {
</script>
<template>
- <item-title :title="workItemTitle" @title-changed="updateTitle" />
+ <item-title :title="workItemTitle" :disabled="!canUpdate" @title-changed="updateTitle" />
</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
new file mode 100644
index 00000000000..fd914fa350b
--- /dev/null
+++ b/app/assets/javascripts/work_items/components/work_item_type_icon.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import { WORK_ITEMS_TYPE_MAP } from '../constants';
+
+export default {
+ components: {
+ GlIcon,
+ },
+ props: {
+ workItemType: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ showText: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ workItemIconName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ iconName() {
+ return (
+ this.workItemIconName || WORK_ITEMS_TYPE_MAP[this.workItemType]?.icon || 'issue-type-issue'
+ );
+ },
+ workItemTypeName() {
+ return WORK_ITEMS_TYPE_MAP[this.workItemType]?.name;
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <gl-icon :name="iconName" class="gl-mr-2" />
+ <span v-if="workItemTypeName" :class="{ 'gl-sr-only': !showText }">{{ workItemTypeName }}</span>
+ </span>
+</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_weight.vue b/app/assets/javascripts/work_items/components/work_item_weight.vue
index 30e2c1e56b8..b0ad7c97bb1 100644
--- a/app/assets/javascripts/work_items/components/work_item_weight.vue
+++ b/app/assets/javascripts/work_items/components/work_item_weight.vue
@@ -1,9 +1,10 @@
<script>
import { GlForm, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import { __ } from '~/locale';
import Tracking from '~/tracking';
-import { TRACKING_CATEGORY_SHOW } from '../constants';
-import localUpdateWorkItemMutation from '../graphql/local_update_work_item.mutation.graphql';
+import { i18n, TRACKING_CATEGORY_SHOW } from '../constants';
+import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
/* eslint-disable @gitlab/require-i18n-strings */
const allowedKeys = [
@@ -97,17 +98,36 @@ export default {
}
},
updateWeight(event) {
+ if (!this.canUpdate) return;
this.isEditing = false;
+
+ const weight = Number(event.target.value);
+ if (this.weight === weight) {
+ return;
+ }
+
this.track('updated_weight');
- this.$apollo.mutate({
- mutation: localUpdateWorkItemMutation,
- variables: {
- input: {
- id: this.workItemId,
- weight: event.target.value === '' ? null : Number(event.target.value),
+ this.$apollo
+ .mutate({
+ mutation: updateWorkItemMutation,
+ variables: {
+ input: {
+ id: this.workItemId,
+ weightWidget: {
+ weight: event.target.value === '' ? null : weight,
+ },
+ },
},
- },
- });
+ })
+ .then(({ data }) => {
+ if (data.workItemUpdate.errors.length) {
+ throw new Error(data.workItemUpdate.errors.join('\n'));
+ }
+ })
+ .catch((error) => {
+ this.$emit('error', i18n.updateError);
+ Sentry.captureException(error);
+ });
},
},
};
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
index 2140b418e6d..a2aea3cd327 100644
--- a/app/assets/javascripts/work_items/constants.js
+++ b/app/assets/javascripts/work_items/constants.js
@@ -8,11 +8,6 @@ export const STATE_EVENT_CLOSE = 'CLOSE';
export const TRACKING_CATEGORY_SHOW = 'workItems:show';
-export const i18n = {
- fetchError: s__('WorkItem|Something went wrong when fetching the work item. Please try again.'),
- updateError: s__('WorkItem|Something went wrong while updating the work item. Please try again.'),
-};
-
export const TASK_TYPE_NAME = 'Task';
export const WIDGET_TYPE_ASSIGNEES = 'ASSIGNEES';
@@ -22,13 +17,48 @@ export const WIDGET_TYPE_WEIGHT = 'WEIGHT';
export const WIDGET_TYPE_HIERARCHY = 'HIERARCHY';
export const WORK_ITEM_VIEWED_STORAGE_KEY = 'gl-show-work-item-banner';
-export const WIDGET_TYPE_TASK_ICON = 'task-done';
+export const WORK_ITEM_TYPE_ENUM_INCIDENT = 'INCIDENT';
+export const WORK_ITEM_TYPE_ENUM_ISSUE = 'ISSUE';
+export const WORK_ITEM_TYPE_ENUM_TASK = 'TASK';
+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.'),
+ 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 WIDGET_ICONS = {
- TASK: 'task-done',
+ TASK: 'issue-type-task',
};
export const WORK_ITEM_STATUS_TEXT = {
CLOSED: s__('WorkItem|Closed'),
OPEN: s__('WorkItem|Open'),
};
+
+export const WORK_ITEMS_TYPE_MAP = {
+ [WORK_ITEM_TYPE_ENUM_INCIDENT]: {
+ icon: `issue-type-incident`,
+ name: s__('WorkItem|Incident'),
+ },
+ [WORK_ITEM_TYPE_ENUM_ISSUE]: {
+ icon: `issue-type-issue`,
+ name: s__('WorkItem|Issue'),
+ },
+ [WORK_ITEM_TYPE_ENUM_TASK]: {
+ icon: `issue-type-task`,
+ name: s__('WorkItem|Task'),
+ },
+ [WORK_ITEM_TYPE_ENUM_TEST_CASE]: {
+ icon: `issue-type-test-case`,
+ name: s__('WorkItem|Test case'),
+ },
+ [WORK_ITEM_TYPE_ENUM_REQUIREMENTS]: {
+ icon: `issue-type-requirements`,
+ name: s__('WorkItem|Requirements'),
+ },
+};
diff --git a/app/assets/javascripts/work_items/graphql/change_work_item_parent_link.mutation.graphql b/app/assets/javascripts/work_items/graphql/change_work_item_parent_link.mutation.graphql
deleted file mode 100644
index dc5286174d8..00000000000
--- a/app/assets/javascripts/work_items/graphql/change_work_item_parent_link.mutation.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-mutation changeWorkItemParentLink($id: WorkItemID!, $parentId: WorkItemID) {
- workItemUpdate(input: { id: $id, hierarchyWidget: { parentId: $parentId } }) {
- workItem {
- id
- workItemType {
- id
- }
- title
- state
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql b/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
index 7f9aaf43068..4cc23fa0071 100644
--- a/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
@@ -1,9 +1,10 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation createWorkItem($input: WorkItemCreateInput!) {
workItemCreate(input: $input) {
workItem {
...WorkItem
}
+ errors
}
}
diff --git a/app/assets/javascripts/work_items/graphql/create_work_item_from_task.mutation.graphql b/app/assets/javascripts/work_items/graphql/create_work_item_from_task.mutation.graphql
index ccfe62cc585..1f98cd4fa2b 100644
--- a/app/assets/javascripts/work_items/graphql/create_work_item_from_task.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/create_work_item_from_task.mutation.graphql
@@ -1,4 +1,4 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation workItemCreateFromTask($input: WorkItemCreateFromTaskInput!) {
workItemCreateFromTask(input: $input) {
diff --git a/app/assets/javascripts/work_items/graphql/local_update_work_item.mutation.graphql b/app/assets/javascripts/work_items/graphql/local_update_work_item.mutation.graphql
index 43c92cf89ec..790b8e60b6a 100644
--- a/app/assets/javascripts/work_items/graphql/local_update_work_item.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/local_update_work_item.mutation.graphql
@@ -1,4 +1,4 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation localUpdateWorkItem($input: LocalUpdateWorkItemInput) {
localUpdateWorkItem(input: $input) @client {
diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js
index 8788ad21e7b..b70c06fddea 100644
--- a/app/assets/javascripts/work_items/graphql/provider.js
+++ b/app/assets/javascripts/work_items/graphql/provider.js
@@ -2,7 +2,7 @@ import produce from 'immer';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import { WIDGET_TYPE_ASSIGNEES, WIDGET_TYPE_LABELS, WIDGET_TYPE_WEIGHT } from '../constants';
+import { WIDGET_TYPE_LABELS } from '../constants';
import typeDefs from './typedefs.graphql';
import workItemQuery from './work_item.query.graphql';
@@ -10,7 +10,7 @@ export const temporaryConfig = {
typeDefs,
cacheConfig: {
possibleTypes: {
- LocalWorkItemWidget: ['LocalWorkItemLabels', 'LocalWorkItemWeight'],
+ LocalWorkItemWidget: ['LocalWorkItemLabels'],
},
typePolicies: {
WorkItem: {
@@ -25,15 +25,15 @@ export const temporaryConfig = {
allowScopedLabels: true,
nodes: [],
},
- {
- __typename: 'LocalWorkItemWeight',
- type: 'WEIGHT',
- weight: null,
- },
]
);
},
},
+ widgets: {
+ merge(_, incoming) {
+ return incoming;
+ },
+ },
},
},
},
@@ -49,20 +49,6 @@ export const resolvers = {
});
const data = produce(sourceData, (draftData) => {
- if (input.assignees) {
- const assigneesWidget = draftData.workItem.widgets.find(
- (widget) => widget.type === WIDGET_TYPE_ASSIGNEES,
- );
- assigneesWidget.assignees.nodes = [...input.assignees];
- }
-
- if (input.weight != null) {
- const weightWidget = draftData.workItem.mockWidgets.find(
- (widget) => widget.type === WIDGET_TYPE_WEIGHT,
- );
- weightWidget.weight = input.weight;
- }
-
if (input.labels) {
const labelsWidget = draftData.workItem.mockWidgets.find(
(widget) => widget.type === WIDGET_TYPE_LABELS,
diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql
index 48228b15a53..36ffba8a540 100644
--- a/app/assets/javascripts/work_items/graphql/typedefs.graphql
+++ b/app/assets/javascripts/work_items/graphql/typedefs.graphql
@@ -1,7 +1,6 @@
enum LocalWidgetType {
ASSIGNEES
LABELS
- WEIGHT
}
interface LocalWorkItemWidget {
@@ -19,20 +18,29 @@ type LocalWorkItemLabels implements LocalWorkItemWidget {
nodes: [Label!]
}
-type LocalWorkItemWeight implements LocalWorkItemWidget {
- type: LocalWidgetType!
- weight: Int
-}
-
extend type WorkItem {
mockWidgets: [LocalWorkItemWidget]
}
+input LocalUserInput {
+ id: ID!
+ name: String
+ username: String
+ webUrl: String
+ avatarUrl: String
+}
+
+input LocalLabelInput {
+ id: ID!
+ title: String!
+ color: String
+ description: String
+}
+
input LocalUpdateWorkItemInput {
id: WorkItemID!
- assignees: [UserCore!]
- labels: [Label]
- weight: Int
+ assignees: [LocalUserInput!]
+ labels: [LocalLabelInput]
}
type LocalWorkItemPayload {
diff --git a/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql b/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
index 25eb8099251..0a887fcfc00 100644
--- a/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
@@ -1,4 +1,4 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation workItemUpdate($input: WorkItemUpdateInput!) {
workItemUpdate(input: $input) {
diff --git a/app/assets/javascripts/work_items/graphql/update_work_item_task.mutation.graphql b/app/assets/javascripts/work_items/graphql/update_work_item_task.mutation.graphql
index ad861a60d15..fad5a9fa5bc 100644
--- a/app/assets/javascripts/work_items/graphql/update_work_item_task.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/update_work_item_task.mutation.graphql
@@ -1,4 +1,4 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation workItemUpdateTask($input: WorkItemUpdateTaskInput!) {
workItemUpdate: workItemUpdateTask(input: $input) {
diff --git a/app/assets/javascripts/work_items/graphql/update_work_item_widgets.mutation.graphql b/app/assets/javascripts/work_items/graphql/update_work_item_widgets.mutation.graphql
index 148b340b439..6a94c96b347 100644
--- a/app/assets/javascripts/work_items/graphql/update_work_item_widgets.mutation.graphql
+++ b/app/assets/javascripts/work_items/graphql/update_work_item_widgets.mutation.graphql
@@ -1,4 +1,4 @@
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
mutation workItemUpdateWidgets($input: WorkItemUpdateWidgetsInput!) {
workItemUpdateWidgets(input: $input) {
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 5f64eda96aa..e8ef27ec778 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
@@ -5,9 +5,11 @@ fragment WorkItem on WorkItem {
title
state
description
+ confidential
workItemType {
id
name
+ iconName
}
userPermissions {
deleteWorkItem
@@ -22,6 +24,7 @@ fragment WorkItem on WorkItem {
... on WorkItemWidgetAssignees {
type
allowsMultipleAssignees
+ canInviteMembers
assignees {
nodes {
...User
@@ -34,12 +37,11 @@ fragment WorkItem on WorkItem {
id
iid
title
+ confidential
}
children {
- edges {
- node {
- id
- }
+ nodes {
+ id
}
}
}
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 61cb8802187..a9f7b714551 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.query.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
@@ -1,5 +1,5 @@
#import "~/graphql_shared/fragments/label.fragment.graphql"
-#import "./work_item.fragment.graphql"
+#import "ee_else_ce/work_items/graphql/work_item.fragment.graphql"
query workItem($id: WorkItemID!) {
workItem(id: $id) {
@@ -12,10 +12,6 @@ query workItem($id: WorkItemID!) {
...Label
}
}
- ... on LocalWorkItemWeight {
- type
- weight
- }
}
}
}
diff --git a/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql b/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
index c2496f53cc8..df62ca1c143 100644
--- a/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
@@ -5,6 +5,11 @@ query workItemQuery($id: WorkItemID!) {
id
}
title
+ userPermissions {
+ deleteWorkItem
+ updateWorkItem
+ }
+ confidential
widgets {
type
... on WorkItemWidgetHierarchy {
@@ -15,6 +20,7 @@ query workItemQuery($id: WorkItemID!) {
children {
nodes {
id
+ confidential
workItemType {
id
}
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index be72ec33465..004dc22c9b8 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -27,7 +27,6 @@
@import './pages/registry';
@import './pages/search';
@import './pages/service_desk';
-@import './pages/settings_ci_cd';
@import './pages/settings';
@import './pages/storage_quota';
@import './pages/tree';
diff --git a/app/assets/stylesheets/components/avatar.scss b/app/assets/stylesheets/components/avatar.scss
index ceac5da7f80..6a6febbf7b4 100644
--- a/app/assets/stylesheets/components/avatar.scss
+++ b/app/assets/stylesheets/components/avatar.scss
@@ -37,7 +37,7 @@ $avatar-sizes: (
),
60: (
font-size: 32px,
- line-height: 58px,
+ line-height: 60px,
border-radius: $border-radius-large
),
64: (
@@ -47,7 +47,7 @@ $avatar-sizes: (
),
90: (
font-size: 36px,
- line-height: 88px,
+ line-height: 90px,
border-radius: $border-radius-large
),
96: (
@@ -72,7 +72,6 @@ $avatar-sizes: (
float: left;
margin-right: $gl-padding;
border-radius: $avatar-radius;
- border: 1px solid $t-gray-a-08;
@each $size, $size-config in $avatar-sizes {
&.s#{$size} {
@@ -83,13 +82,12 @@ $avatar-sizes: (
.avatar {
transition-property: none;
-
width: 40px;
height: 40px;
padding: 0;
background: $gray-lightest;
overflow: hidden;
- border-color: rgba($black, $gl-avatar-border-opacity);
+ box-shadow: inset 0 0 0 1px rgba($gray-950, $gl-avatar-border-opacity);
&.avatar-inline {
float: none;
@@ -180,6 +178,10 @@ $avatar-sizes: (
@each $size, $size-config in $avatar-sizes {
&.s#{$size} {
border-radius: map-get($size-config, 'border-radius');
+
+ .avatar {
+ border-radius: map-get($size-config, 'border-radius');
+ }
}
}
}
diff --git a/app/assets/stylesheets/components/batch_comments/review_bar.scss b/app/assets/stylesheets/components/batch_comments/review_bar.scss
index 6f5c5c5a080..5e1128dc4ce 100644
--- a/app/assets/stylesheets/components/batch_comments/review_bar.scss
+++ b/app/assets/stylesheets/components/batch_comments/review_bar.scss
@@ -11,7 +11,7 @@
padding-right: $gutter_collapsed_width;
background: $white;
border-top: 1px solid $border-color;
- transition: padding $sidebar-transition-duration;
+ transition: padding $gl-transition-duration-medium;
.page-with-icon-sidebar & {
padding-left: $contextual-sidebar-collapsed-width;
diff --git a/app/assets/stylesheets/components/rich_content_editor.scss b/app/assets/stylesheets/components/rich_content_editor.scss
deleted file mode 100644
index 59bd69955d3..00000000000
--- a/app/assets/stylesheets/components/rich_content_editor.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
-* Overrides styles from ToastUI editor
-*/
-
-.tui-editor-defaultUI {
-
- // Toolbar buttons
- .tui-editor-defaultUI-toolbar .toolbar-button {
- color: $gray-500;
- border: 0;
-
- &:hover,
- &:active {
- color: $blue-500;
- border: 0;
- }
- }
-
- // Contextual menu's & popups
- .tui-popup-wrapper {
- @include gl-overflow-hidden;
- @include gl-rounded-base;
- @include gl-border-gray-200;
-
- hr {
- @include gl-m-0;
- @include gl-bg-gray-200;
- }
-
- button {
- @include gl-text-gray-700;
- }
- }
-
- /**
- * Overrides styles from ToastUI's Code Mirror (markdown mode) editor.
- * Toast UI internally overrides some of these using the `.tui-md-` prefix.
- * https://codemirror.net/doc/manual.html#styling
- */
-
- .te-md-container .CodeMirror * {
- @include gl-font-monospace;
- @include gl-font-size-monospace;
- @include gl-line-height-20;
- }
-}
-
-/**
-* Styling below ensures that YouTube videos are displayed in the editor the same as they would in about.gitlab.com
-* https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/main/source/stylesheets/_base.scss#L977
-*/
-.video_container {
- padding-bottom: 56.25%;
-}
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 549289450a4..f947042ba51 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -84,89 +84,6 @@
border-bottom: 1px solid $white-dark;
padding: 11px 0;
margin-bottom: 11px;
-
- &.no-bottom-space {
- border-bottom: 0;
- margin-bottom: 0;
- }
-}
-
-.cover-block {
- text-align: center;
- background: $gray-light;
- padding-top: 44px;
- position: relative;
-
- .avatar-holder {
- .avatar,
- .identicon {
- margin: 0 auto;
- float: none;
- }
-
- .identicon {
- border-radius: 50%;
- }
- }
-
- .cover-title {
- color: $gl-text-color;
- font-size: 23px;
-
- h1 {
- color: $gl-text-color;
- margin-bottom: 6px;
- font-size: 23px;
- }
-
- .visibility-icon {
- display: inline-block;
- margin-left: 5px;
- font-size: 18px;
- color: color('gray');
- }
-
- p {
- padding: 0 $gl-padding;
- color: $gl-text-color;
- }
- }
-
- .cover-controls {
- @include media-breakpoint-up(sm) {
- position: absolute;
- top: 1rem;
- right: 1.25rem;
- }
-
- &.left {
- @include media-breakpoint-up(sm) {
- left: 1.25rem;
- right: auto;
- }
- }
- }
-
- &.user-cover-block {
- padding: 24px 0 0;
-
- .nav-links {
- width: 100%;
- float: none;
-
- &.scrolling-tabs {
- float: none;
- }
- }
-
- li:first-child {
- margin-left: auto;
- }
-
- li:last-child {
- margin-right: auto;
- }
- }
}
.content-block {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 1fa03d66f32..b1e5ca50a8b 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,30 +1,3 @@
-.calendar-block {
- padding-left: 0;
- padding-right: 0;
- border-top: 0;
-
- @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
- overflow-x: auto;
- }
-}
-
-.user-calendar-activities {
- direction: ltr;
-
- .str-truncated {
- max-width: 70%;
- }
-}
-
-.user-calendar {
- text-align: center;
- min-height: 172px;
-
- .calendar {
- display: inline-block;
- }
-}
-
.user-contrib-cell {
&:hover {
cursor: pointer;
@@ -42,18 +15,6 @@
}
}
-.user-contrib-text {
- font-size: 12px;
- fill: $calendar-user-contrib-text;
-}
-
-.calendar-hint {
- font-size: 12px;
- direction: ltr;
- margin-top: -23px;
- float: right;
-}
-
.pika-single.gitlab-theme {
.pika-label {
color: $gl-text-color-secondary;
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 036cec15935..ad0036df607 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -134,16 +134,6 @@
.avatar-container {
@include gl-font-weight-normal;
flex: none;
- box-shadow: $avatar-box-shadow;
-
- &.rect-avatar {
- @include gl-border-none;
-
- .avatar.s32 {
- border-radius: $border-radius-default;
- box-shadow: $avatar-box-shadow;
- }
- }
}
}
@@ -214,7 +204,7 @@
//
.page-with-contextual-sidebar {
- transition: padding-left $sidebar-transition-duration;
+ transition: padding-left $gl-transition-duration-medium;
@include media-breakpoint-up(md) {
padding-left: $contextual-sidebar-collapsed-width;
@@ -243,7 +233,7 @@
@include gl-fixed;
@include gl-bottom-0;
@include gl-left-0;
- transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium, left $gl-transition-duration-medium;
z-index: 600;
width: $contextual-sidebar-width;
top: $header-height;
diff --git a/app/assets/stylesheets/framework/contextual_sidebar_header.scss b/app/assets/stylesheets/framework/contextual_sidebar_header.scss
index 7159dadf7cc..a3d752dcc3d 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar_header.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar_header.scss
@@ -5,7 +5,7 @@
> a,
> button {
- transition: padding $sidebar-transition-duration;
+ transition: padding $gl-transition-duration-medium;
font-weight: $gl-font-weight-bold;
display: flex;
width: 100%;
@@ -25,7 +25,7 @@
}
.avatar-container {
- flex: 0 0 40px;
+ flex: 0 0 32px;
background-color: $white;
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 43e14a63f9d..d91524d99e6 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -125,10 +125,6 @@
padding-right: 25px;
}
- .fa {
- color: $gray-darkest;
- }
-
&:hover {
border-color: $gray-darkest;
}
@@ -148,10 +144,6 @@
text-overflow: ellipsis;
width: 160px;
- .fa {
- position: absolute;
- }
-
.gl-spinner {
position: absolute;
top: 9px;
@@ -387,10 +379,6 @@
margin: 0;
text-align: left;
text-overflow: inherit;
-
- &.btn .fa:not(:last-child) {
- margin-left: 5px;
- }
}
> button.dropdown-epic-button {
@@ -477,6 +465,12 @@
height: 2 * $gl-padding;
margin: 0 10px 0 0;
}
+
+ .sidebar-participant {
+ .merge-icon {
+ top: calc(50% + 5px);
+ }
+ }
}
.dropdown-menu-user-full-name {
@@ -645,14 +639,12 @@
border-color: $blue-300;
box-shadow: 0 0 4px $dropdown-input-focus-shadow;
- ~ .fa,
~ .dropdown-input-clear {
color: $gray-700;
}
}
&:hover {
- ~ .fa,
~ .dropdown-input-clear {
color: $gray-700;
}
@@ -710,14 +702,6 @@
z-index: 9;
background-color: $dropdown-loading-bg;
font-size: 28px;
-
- .fa {
- position: absolute;
- top: 50%;
- left: 50%;
- margin-top: -14px;
- margin-left: -14px;
- }
}
.dropdown-label-box {
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index f322c6c8929..b980d7fdaa7 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -202,6 +202,10 @@
float: none;
border-left: 1px solid $gray-100;
+ .file-line-num {
+ @include gl-min-w-9;
+ }
+
i {
float: none;
margin-right: 0;
@@ -478,6 +482,11 @@ span.idiff {
background-color: transparent;
border: transparent;
}
+
+ .gl-dark & {
+ background: transparent;
+ filter: invert(1) hue-rotate(180deg);
+ }
}
.code-navigation-line:hover {
@@ -575,3 +584,11 @@ span.idiff {
@include gl-text-center;
}
}
+
+// *:nth-of-type(1n+30) - makes sure we do not render elements 30+ right away when
+// viewing a file. Even though the HTML is injected in the DOM, as long as we do
+// not render those elements, the browser doesn't need to spend resources
+// calculating and repainting what's hidden.
+.file-holder [data-loading] .file-content *:nth-of-type(1n+30) {
+ @include gl-display-none;
+}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 1c43212f501..2b76e70fa17 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -31,7 +31,8 @@
width: 100%;
padding-left: 10px;
padding-right: 10px;
- white-space: pre;
+ white-space: break-spaces;
+ word-break: break-word;
&:empty::before {
content: '\200b';
@@ -48,8 +49,9 @@
a {
font-family: $monospace-font;
- display: block;
white-space: nowrap;
+ @include gl-display-flex;
+ @include gl-justify-content-end;
i,
svg {
@@ -90,3 +92,55 @@ td.line-numbers {
cursor: pointer;
text-decoration: underline wavy $red-500;
}
+
+.blob-viewer {
+ .line-numbers {
+ // for server-side-rendering
+ .line-links {
+ @include gl-display-flex;
+
+
+ &:first-child {
+ margin-top: 10px;
+ }
+
+ &:last-child {
+ margin-bottom: 10px;
+ }
+ }
+
+ // for client
+ &.line-links {
+ min-width: 6rem;
+ border-bottom-left-radius: 0;
+
+ + pre {
+ margin-left: 6rem;
+ }
+ }
+ }
+
+ .line-links {
+ &:hover a::before,
+ &:focus-within a::before {
+ @include gl-visibility-visible;
+ }
+ }
+
+ .file-line-num {
+ min-width: 4.5rem;
+ @include gl-justify-content-end;
+ @include gl-flex-grow-1;
+ @include gl-pr-3;
+ }
+
+ .file-line-blame {
+ @include gl-ml-3;
+ }
+
+ .file-line-num,
+ .file-line-blame {
+ @include gl-align-items-center;
+ @include gl-display-flex;
+ }
+}
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 2cea3b96ff7..47856f1a0d3 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -478,7 +478,7 @@
}
@mixin side-panel-toggle {
- transition: width $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium;
height: $toggle-sidebar-height;
padding: 0 $gl-padding;
background-color: $gray-light;
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 74aed1bd984..92ca8654287 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -135,27 +135,8 @@
}
@include media-breakpoint-down(md) {
- $controls-margin: $btn-margin-5 - 2px;
flex: 0 0 100%;
margin-top: $gl-padding-8;
-
- .controls-item,
- .controls-item-full,
- .controls-item:last-child {
- flex: 1 1 35%;
- display: block;
- width: 100%;
- margin: $controls-margin;
-
- .btn,
- .dropdown {
- margin: 0;
- }
- }
-
- .controls-item-full {
- flex: 1 1 100%;
- }
}
@include media-breakpoint-down(sm) {
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 13201d43fd0..ae0f18753ad 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -13,7 +13,7 @@
}
.page-initialised .content-wrapper {
- transition: padding $sidebar-transition-duration;
+ transition: padding $gl-transition-duration-medium;
}
.right-sidebar-collapsed {
@@ -109,7 +109,7 @@
@include maintain-sidebar-dimensions;
width: 0;
padding: 0;
- transition: width $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium;
&.right-sidebar-expanded {
@include maintain-sidebar-dimensions;
diff --git a/app/assets/stylesheets/framework/sortable.scss b/app/assets/stylesheets/framework/sortable.scss
index 953c42219a9..f9e95d16f63 100644
--- a/app/assets/stylesheets/framework/sortable.scss
+++ b/app/assets/stylesheets/framework/sortable.scss
@@ -1,6 +1,4 @@
.sortable-container {
- background-color: $gray-light;
-
.flex-list {
padding: 5px;
margin-bottom: 0;
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index 086b83b13e0..43effbdd7d7 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -35,6 +35,10 @@
background-color: $white;
}
+ &:not(.note-form).internal-note {
+ background-color: $orange-50;
+ }
+
.timeline-entry-inner {
position: relative;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index b5e0dcd875a..031f5dc45ca 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -435,6 +435,35 @@
}
}
+ li.inapplicable {
+ // for a single line list item, no paragraph (tight list)
+ > s {
+ color: $gl-text-color-disabled;
+ }
+
+ // additional blocks, other than paragraphs
+ > div {
+ text-decoration: line-through;
+ color: $gl-text-color-disabled;
+ }
+
+ // because of the embedded checkbox, putting line-through on the entire
+ // paragraph causes the space between the checkbox and the text to have the
+ // line-through. Targeting just the `s` fixes this
+ > p:first-of-type > s {
+ color: $gl-text-color-disabled;
+ }
+
+ > p:not(:first-of-type) {
+ text-decoration: line-through;
+ color: $gl-text-color-disabled;
+ }
+
+ .drag-icon {
+ color: $gl-text-color;
+ }
+ }
+
a.with-attachment-icon,
a[href*='/uploads/'],
a[href*='storage.googleapis.com/google-code-attachments/'] {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 1e921b4234e..e9ad930ef2b 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -5,7 +5,6 @@ $grid-size: 8px;
$gutter-collapsed-width: 62px;
$gutter-width: 290px;
$gutter-inner-width: 250px;
-$sidebar-transition-duration: 0.3s;
$sidebar-breakpoint: 1024px;
$default-transition-duration: 0.15s;
$contextual-sidebar-width: 256px;
@@ -454,7 +453,6 @@ $default-icon-size: 16px;
$layout-link-gray: #7e7c7c;
$btn-side-margin: $grid-size;
$btn-sm-side-margin: 7px;
-$btn-margin-5: 5px;
$count-arrow-border: #dce0e5;
$general-hover-transition-duration: 100ms;
$general-hover-transition-curve: linear;
@@ -880,8 +878,6 @@ $image-comment-cursor-top-offset: 12;
Security & Compliance Carousel
*/
$security-and-compliance-carousel-image-carousel-width: 1000px;
-$security-and-compliance-carousel-image-discover-button-width: 45%;
-$security-and-compliance-carousel-image-discover-buttons-max-width: 280px;
$security-and-compliance-carousel-image-discover-footer-max-width: 500px;
$security-and-compliance-carousel-image-discover-text-carousel-max-width: 650px;
$security-and-compliance-carousel-image-discover-text-carousel-caption-height: 100%;
diff --git a/app/assets/stylesheets/framework/vue_transitions.scss b/app/assets/stylesheets/framework/vue_transitions.scss
index 1a536b97142..e3ac615234c 100644
--- a/app/assets/stylesheets/framework/vue_transitions.scss
+++ b/app/assets/stylesheets/framework/vue_transitions.scss
@@ -2,7 +2,7 @@
.fade-leave-active,
.fade-in-enter-active,
.fade-out-leave-active {
- transition: opacity $sidebar-transition-duration $general-hover-transition-curve;
+ transition: opacity $gl-transition-duration-medium $general-hover-transition-curve;
}
.fade-enter,
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index fcbd05141b9..96df8487c0e 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -98,32 +98,33 @@
}
}
-@mixin line-number-link($color) {
- min-width: $gl-spacing-scale-9;
+@mixin line-link($color, $icon) {
&::before {
- @include gl-display-none;
+ @include gl-visibility-hidden;
@include gl-align-self-center;
- @include gl-mt-2;
- @include gl-mr-2;
- @include gl-w-4;
- @include gl-h-4;
- @include gl-absolute;
- @include gl-left-3;
- background-color: $color;
- mask-image: asset_url('icons-stacked.svg#link');
+ @include gl-mr-1;
+ @include gl-w-5;
+ @include gl-h-5;
+ background-color: rgba($color, 0.3);
+ mask-image: asset_url('icons-stacked.svg##{$icon}');
mask-repeat: no-repeat;
mask-size: cover;
mask-position: center;
content: '';
}
- &:hover::before {
- @include gl-display-inline-block;
+ &:hover {
+ &::before {
+ background-color: rgba($color, 0.6);
+ }
}
+}
- &:focus::before {
- @include gl-display-inline-block;
+@mixin line-hover-bg($color: $white-normal) {
+ &:hover,
+ &:focus-within {
+ background-color: darken($color, 10);
}
}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 709e7f5ae18..5e6e10e44be 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -127,7 +127,15 @@ $dark-il: #de935f;
.code.dark {
// Line numbers
.file-line-num {
- @include line-number-link($dark-line-num-color);
+ @include line-link($white, 'link');
+ }
+
+ .file-line-blame {
+ @include line-link($white, 'git');
+ }
+
+ .line-links {
+ @include line-hover-bg($dark-main-bg);
}
.line-numbers,
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index 0ed9c209417..19c3d6926e7 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -120,7 +120,15 @@ $monokai-gh: #75715e;
// Line numbers
.file-line-num {
- @include line-number-link($monokai-line-num-color);
+ @include line-link($white, 'link');
+ }
+
+ .file-line-blame {
+ @include line-link($white, 'git');
+ }
+
+ .line-links {
+ @include line-hover-bg($monokai-bg);
}
.line-numbers,
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index 868e466b1f8..4c716d20ddf 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -25,7 +25,15 @@
// Line numbers
.file-line-num {
- @include line-number-link($black-transparent);
+ @include line-link($black, 'link');
+ }
+
+ .file-line-blame {
+ @include line-link($black, 'git');
+ }
+
+ .line-links {
+ @include line-hover-bg;
}
.line-numbers,
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index 6260339a48d..70086be1606 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -123,7 +123,15 @@ $solarized-dark-il: #2aa198;
// Line numbers
.file-line-num {
- @include line-number-link($solarized-dark-line-color);
+ @include line-link($white, 'link');
+ }
+
+ .file-line-blame {
+ @include line-link($white, 'git');
+ }
+
+ .line-links {
+ @include line-hover-bg($solarized-dark-pre-bg);
}
.line-numbers,
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index e6f098f4cdf..8d223d1fdb1 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -109,7 +109,15 @@ $solarized-light-il: #2aa198;
@include hljs-override('title.class_.inherited__', $solarized-light-no);
// Line numbers
.file-line-num {
- @include line-number-link($solarized-light-line-color);
+ @include line-link($black, 'link');
+ }
+
+ .file-line-blame {
+ @include line-link($black, 'git');
+ }
+
+ .line-links {
+ @include line-hover-bg($solarized-light-pre-bg);
}
.line-numbers,
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 770a90bbc57..9761e3961dd 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -95,7 +95,15 @@ $white-gc-bg: #eaf2f5;
// Line numbers
.file-line-num {
- @include line-number-link($black-transparent);
+ @include line-link($black, 'link');
+}
+
+.file-line-blame {
+ @include line-link($black, 'git');
+}
+
+.line-links {
+ @include line-hover-bg;
}
.line-numbers,
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index 81d35b8bc7b..197073412e8 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -35,7 +35,7 @@
.boards-app {
@include media-breakpoint-up(sm) {
- transition: width $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium;
width: 100%;
&.is-compact {
@@ -349,7 +349,7 @@
.right-sidebar.right-sidebar-expanded {
&.boards-sidebar-slide-enter-active,
&.boards-sidebar-slide-leave-active {
- transition: width $sidebar-transition-duration, padding $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium, padding $gl-transition-duration-medium;
}
&.boards-sidebar-slide-enter,
diff --git a/app/assets/stylesheets/page_bundles/escalation_policies.scss b/app/assets/stylesheets/page_bundles/escalation_policies.scss
index 6f3873fea0c..84c62ba93dd 100644
--- a/app/assets/stylesheets/page_bundles/escalation_policies.scss
+++ b/app/assets/stylesheets/page_bundles/escalation_policies.scss
@@ -15,17 +15,11 @@
$stroke-size: 1px;
.right-arrow {
- @include gl-relative;
height: $stroke-size;
- background-color: var(--gray-900, $gray-900);
- min-width: $gl-spacing-scale-7;
&-head {
- @include gl-absolute;
- top: -2*$stroke-size;
- left: calc(100% - #{5*$stroke-size});
- @include gl-p-1;
- @include gl-border-solid;
+ top: -2 * $stroke-size;
+ left: calc(100% - #{5 * $stroke-size});
border-width: 0 $stroke-size $stroke-size 0;
border-color: var(--gray-900, $gray-900);
transform: rotate(-45deg);
@@ -41,14 +35,10 @@ $stroke-size: 1px;
.rule-condition {
@media (min-width: $breakpoint-lg) {
flex-basis: 25%;
- flex-shrink: 0;
+ @include gl-flex-shrink-0;
}
@media (max-width: $breakpoint-lg) {
@include gl-w-full;
}
}
-
-.rule-action {
- min-width: 0;
-}
diff --git a/app/assets/stylesheets/page_bundles/group.scss b/app/assets/stylesheets/page_bundles/group.scss
index 38dd07f617c..71dbb855103 100644
--- a/app/assets/stylesheets/page_bundles/group.scss
+++ b/app/assets/stylesheets/page_bundles/group.scss
@@ -72,36 +72,43 @@
}
}
-.group-nav-container .nav-controls {
- .group-filter-form {
- flex: 1 1 auto;
- margin-right: $gl-padding-8;
- }
-
- .dropdown-menu-right {
- margin-top: 0;
- }
-
- @include media-breakpoint-down(sm) {
- .dropdown,
- .dropdown .dropdown-toggle,
- .btn-success {
- display: block;
+.group-nav-container {
+ .nav-controls {
+ .group-filter-form {
+ flex: 1 1 auto;
+ margin-right: $gl-padding-8;
}
- .group-filter-form,
- .dropdown {
- margin-bottom: 10px;
- margin-right: 0;
+ .dropdown-menu-right {
+ margin-top: 0;
}
- &,
- .group-filter-form,
- .group-filter-form-field,
- .dropdown,
- .dropdown .dropdown-toggle,
- .btn-success {
- width: 100%;
+ @include media-breakpoint-down(sm) {
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ display: block;
+ }
+
+ .group-filter-form,
+ .dropdown {
+ margin-bottom: 10px;
+ margin-right: 0;
+ }
+
+ &,
+ .group-filter-form,
+ .group-filter-form-field,
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ width: 100%;
+ }
}
}
+
+ // Remove this selector once https://gitlab.com/gitlab-org/gitlab/-/issues/370050 is addressed.
+ .scrolling-tabs-container {
+ width: 100%;
+ }
}
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 1b27e51e793..b7a75884425 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -416,8 +416,6 @@ $tabs-holder-z-index: 250;
.label-branch {
@include gl-font-monospace;
font-size: 95%;
- color: var(--gl-text-color, $gl-text-color);
- font-weight: normal;
overflow: hidden;
word-break: break-all;
}
@@ -477,8 +475,7 @@ $tabs-holder-z-index: 250;
margin: 0 0 0 10px;
}
- .bold,
- .gl-font-weight-bold {
+ .bold {
font-weight: $gl-font-weight-bold;
color: var(--gray-600, $gray-600);
margin-left: 10px;
@@ -494,8 +491,7 @@ $tabs-holder-z-index: 250;
}
.spacing,
- .bold,
- .gl-font-weight-bold {
+ .bold {
vertical-align: middle;
}
@@ -602,6 +598,12 @@ $tabs-holder-z-index: 250;
padding: $gl-padding;
}
+.mr-widget-body-ready-merge {
+ @include media-breakpoint-down(sm) {
+ @include gl-p-3;
+ }
+}
+
.mr-widget-border-top {
border-top: 1px solid var(--border-color, $border-color);
}
@@ -820,3 +822,21 @@ $tabs-holder-z-index: 250;
height: 180px;
}
}
+
+.mr-widget-merge-details {
+ li:not(:last-child) {
+ @include gl-mb-3;
+ }
+}
+
+.mr-ready-merge-related-links,
+.mr-widget-merge-details {
+ a {
+ @include gl-text-decoration-underline;
+
+ &:hover,
+ &:focus {
+ @include gl-text-decoration-none;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index e6afc70acbb..98e9e2b3c27 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -225,12 +225,20 @@
}
}
-.test-reports-table {
- .build-log {
- @include build-log();
+.progress-bar.bg-primary {
+ background-color: var(--blue-500, $blue-500) !important;
+}
+
+.ci-job-component {
+ .job-failed {
+ background-color: var(--red-50, $red-50);
}
}
-.progress-bar.bg-primary {
- background-color: var(--blue-500, $blue-500) !important;
+.gl-dark {
+ .ci-job-component {
+ .job-failed {
+ background-color: var(--gray-200, $gray-200);
+ }
+ }
}
diff --git a/app/assets/stylesheets/page_bundles/profile.scss b/app/assets/stylesheets/page_bundles/profile.scss
new file mode 100644
index 00000000000..59b8823c113
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/profile.scss
@@ -0,0 +1,212 @@
+@import 'mixins_and_variables_and_functions';
+
+.calendar-block {
+ padding-left: 0;
+ padding-right: 0;
+ border-top: 0;
+
+ @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
+ overflow-x: auto;
+ }
+}
+
+.calendar-hint {
+ font-size: 12px;
+ direction: ltr;
+ margin-top: -23px;
+ float: right;
+}
+
+.cover-block {
+ text-align: center;
+ background: var(--gray-50, $gray-light);
+ padding-top: 44px;
+ position: relative;
+
+ .avatar-holder {
+ .avatar,
+ .identicon {
+ margin: 0 auto;
+ float: none;
+ }
+
+ .identicon {
+ border-radius: 50%;
+ }
+ }
+
+ .cover-title {
+ color: var(--gl-text-color, $gl-text-color);
+ font-size: 23px;
+
+ h1 {
+ color: var(--gl-text-color, $gl-text-color);
+ margin-bottom: 6px;
+ font-size: 23px;
+ }
+
+ .visibility-icon {
+ display: inline-block;
+ margin-left: 5px;
+ font-size: 18px;
+ color: color('gray');
+ }
+
+ p {
+ padding: 0 $gl-padding;
+ color: var(--gl-text-color, $gl-text-color);
+ }
+ }
+
+ .cover-controls {
+ @include media-breakpoint-up(sm) {
+ position: absolute;
+ top: 1rem;
+ right: 1.25rem;
+ }
+
+ &.left {
+ @include media-breakpoint-up(sm) {
+ left: 1.25rem;
+ right: auto;
+ }
+ }
+ }
+
+ &.user-cover-block {
+ padding: 24px 0 0;
+
+ .nav-links {
+ width: 100%;
+ float: none;
+
+ &.scrolling-tabs {
+ float: none;
+ }
+ }
+
+ li:first-child {
+ margin-left: auto;
+ }
+
+ li:last-child {
+ margin-right: auto;
+ }
+ }
+}
+
+// Middle dot divider between each element in a list of items.
+.middle-dot-divider {
+ @include middle-dot-divider;
+}
+
+.middle-dot-divider-sm {
+ @include media-breakpoint-up(sm) {
+ @include middle-dot-divider;
+ }
+}
+
+.profile-user-bio {
+ // Limits the width of the user bio for readability.
+ max-width: 600px;
+ margin: 10px auto;
+}
+
+.user-calendar {
+ text-align: center;
+ min-height: 172px;
+
+ .calendar {
+ display: inline-block;
+ }
+}
+
+.user-calendar-activities {
+ direction: ltr;
+
+ .str-truncated {
+ max-width: 70%;
+ }
+}
+
+.user-contrib-text {
+ font-size: 12px;
+ fill: $calendar-user-contrib-text;
+}
+
+.user-profile {
+ .profile-header {
+ margin: 0 $gl-padding;
+
+ &.with-no-profile-tabs {
+ margin-bottom: $gl-padding-24;
+ }
+
+ .avatar-holder {
+ width: 90px;
+ margin: 0 auto 10px;
+ }
+ }
+
+ .user-profile-nav {
+ font-size: 0;
+ }
+
+ .fade-right {
+ right: 0;
+ }
+
+ .fade-left {
+ left: 0;
+ }
+
+ .activities-block {
+ .event-item {
+ padding-left: 40px;
+ }
+
+ .gl-label-scoped {
+ --label-inset-border: inset 0 0 0 1px currentColor;
+ }
+
+ @include media-breakpoint-up(lg) {
+ margin-right: 5px;
+ }
+ }
+
+ .projects-block {
+ @include media-breakpoint-up(lg) {
+ margin-left: 5px;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .cover-block {
+ padding-top: 20px;
+ }
+
+ .user-profile-nav {
+ a {
+ margin-right: 0;
+ }
+ }
+
+ .activities-block {
+ .event-item {
+ padding-left: 0;
+ }
+ }
+ }
+}
+
+.linkedin-icon {
+ color: $linkedin;
+}
+
+.skype-icon {
+ color: $skype;
+}
+
+.twitter-icon {
+ color: $twitter;
+}
diff --git a/app/assets/stylesheets/page_bundles/runner_details.scss b/app/assets/stylesheets/page_bundles/runner_details.scss
new file mode 100644
index 00000000000..6e5580a18e4
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/runner_details.scss
@@ -0,0 +1,3 @@
+.runner-details-grid-template {
+ grid-template-columns: auto 1fr;
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 51f964a4b70..69797c6b303 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -132,7 +132,7 @@
// stylelint-disable-next-line length-zero-no-unit
bottom: var(--review-bar-height, 0px);
right: 0;
- transition: width $sidebar-transition-duration;
+ transition: width $gl-transition-duration-medium;
background-color: $white;
z-index: 200;
overflow: hidden;
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index c0a283ec643..a151c28fe93 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -318,7 +318,7 @@ ul.related-merge-requests > li gl-emoji {
.issuable-header-slide-enter-active,
.issuable-header-slide-leave-active {
- @include gl-transition-slow;
+ @include gl-transition-medium;
}
.issuable-header-slide-enter,
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 7f0bdadd2bc..1beb9f05b6c 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -41,6 +41,20 @@
font-size: 13px;
}
+ .borderless {
+ .login-box,
+ .omniauth-container {
+ box-shadow: none;
+ }
+
+ .g-recaptcha {
+ > div {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ }
+ }
+
.login-box,
.omniauth-container {
box-shadow: 0 0 0 1px $border-color;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 96fe6caeea2..b016d0a1068 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -342,10 +342,10 @@ $comparison-empty-state-height: 62px;
.mr-compare {
.diff-file .file-title-flex-parent {
- top: calc(#{$header-height} + #{$mr-tabs-height} + 36px);
+ top: calc(#{$header-height} + #{$mr-tabs-height});
.with-performance-bar & {
- top: calc(#{$performance-bar-height} + #{$header-height} + #{$mr-tabs-height} + 36px);
+ top: calc(#{$performance-bar-height} + #{$header-height} + #{$mr-tabs-height});
}
}
}
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 645f145328b..9692becef4f 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -121,15 +121,6 @@
border-radius: $label-border-radius;
padding-top: $gl-vert-padding;
padding-bottom: $gl-vert-padding;
-
- .icon svg {
- position: relative;
- top: 2px;
- margin-right: $btn-margin-5;
- width: $gl-font-size;
- height: $gl-font-size;
- fill: $orange-600;
- }
}
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 4d0cf30a3b2..db07f16dfd0 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -4,7 +4,7 @@ $system-note-svg-size: 16px;
@mixin vertical-line($left) {
&::before {
content: '';
- border-left: 2px solid $gray-50;
+ border-left: 2px solid $gray-10;
position: absolute;
top: 0;
bottom: 0;
@@ -29,7 +29,7 @@ $system-note-svg-size: 16px;
.issuable-discussion {
.main-notes-list {
- @include vertical-line(36px);
+ @include vertical-line(35px);
}
}
@@ -300,17 +300,17 @@ $system-note-svg-size: 16px;
.timeline-icon {
display: flex;
align-items: center;
- background-color: $white;
+ background-color: $gray-10;
width: $system-note-icon-size;
height: $system-note-icon-size;
- border: 1px solid $border-color;
+ border: 1px solid $gray-10;
border-radius: $system-note-icon-size;
margin: -6px 20px 0 0;
svg {
width: $system-note-svg-size;
height: $system-note-svg-size;
- fill: $gray-darkest;
+ fill: $gray-400;
display: block;
margin: 0 auto;
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 812cc6ab4e6..951e31ef768 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -29,23 +29,6 @@
}
}
-// Middle dot divider between each element in a list of items.
-.middle-dot-divider {
- @include middle-dot-divider;
-}
-
-.middle-dot-divider-sm {
- @include media-breakpoint-up(sm) {
- @include middle-dot-divider;
- }
-}
-
-.profile-user-bio {
- // Limits the width of the user bio for readability.
- max-width: 600px;
- margin: 10px auto;
-}
-
.user-avatar-button {
.file-name {
display: inline-block;
@@ -156,71 +139,6 @@
}
}
-.user-profile {
- .profile-header {
- margin: 0 $gl-padding;
-
- &.with-no-profile-tabs {
- margin-bottom: $gl-padding-24;
- }
-
- .avatar-holder {
- width: 90px;
- margin: 0 auto 10px;
- }
- }
-
- .user-profile-nav {
- font-size: 0;
- }
-
- .fade-right {
- right: 0;
- }
-
- .fade-left {
- left: 0;
- }
-
- .activities-block {
- .event-item {
- padding-left: 40px;
- }
-
- .gl-label-scoped {
- --label-inset-border: inset 0 0 0 1px currentColor;
- }
-
- @include media-breakpoint-up(lg) {
- margin-right: 5px;
- }
- }
-
- .projects-block {
- @include media-breakpoint-up(lg) {
- margin-left: 5px;
- }
- }
-
- @include media-breakpoint-down(xs) {
- .cover-block {
- padding-top: 20px;
- }
-
- .user-profile-nav {
- a {
- margin-right: 0;
- }
- }
-
- .activities-block {
- .event-item {
- padding-left: 0;
- }
- }
- }
-}
-
table.u2f-registrations {
th:not(:last-child),
td:not(:last-child) {
@@ -366,15 +284,3 @@ table.u2f-registrations {
.gitlab-slack-slack-logo {
transform: scale(200%); // Slack logo SVG is scaled down 50% and has empty space around it
}
-
-.skype-icon {
- color: $skype;
-}
-
-.linkedin-icon {
- color: $linkedin;
-}
-
-.twitter-icon {
- color: $twitter;
-}
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index f1865a7dc40..6c909b8d9fa 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -82,19 +82,17 @@ input[type='checkbox']:hover {
min-width: $search-input-field-x-min-width;
}
- &.is-active {
- &.is-searching {
- .in-search-scope-help {
- position: absolute;
- top: $gl-spacing-scale-2;
- right: 2.125rem;
- z-index: 2;
- }
+ &.is-searching {
+ .in-search-scope-help {
+ position: absolute;
+ top: $gl-spacing-scale-2;
+ right: 2.125rem;
+ z-index: 2;
}
}
- &.is-not-searching {
- .in-search-scope-help {
+ &.is-not-focused {
+ .gl-search-box-by-type-clear {
display: none;
}
}
@@ -104,28 +102,11 @@ input[type='checkbox']:hover {
box-shadow: none;
border-color: transparent;
}
-
- &.is-active {
- .keyboard-shortcut-helper {
- display: none;
- }
- }
-
- &.is-not-active {
- .btn.gl-clear-icon-button,
- .in-search-scope-help {
- display: none;
- }
- }
}
.header-search-dropdown-menu {
max-height: $dropdown-max-height;
- top: $header-height;
-}
-
-.header-search-dropdown-content {
- max-height: $dropdown-max-height;
+ top: 100%;
}
.search {
diff --git a/app/assets/stylesheets/pages/settings_ci_cd.scss b/app/assets/stylesheets/pages/settings_ci_cd.scss
deleted file mode 100644
index 7d74070b4f2..00000000000
--- a/app/assets/stylesheets/pages/settings_ci_cd.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-.triggers-container {
- .label-container {
- display: inline-block;
- margin-left: 10px;
- }
-}
-
-.trigger-description {
- max-width: 100px;
-}
-
-.trigger-actions {
- white-space: nowrap;
-}
-
-.auto-devops-card {
- margin-bottom: $gl-vert-padding;
-}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 801c9ea828f..ffe4d5dde9d 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -1043,7 +1043,7 @@ kbd {
text-align: left;
}
.context-header .avatar-container {
- flex: 0 0 40px;
+ flex: 0 0 32px;
background-color: #333;
}
.context-header .sidebar-context-title {
@@ -1376,18 +1376,6 @@ kbd {
.nav-sidebar-inner-scroll > div.context-header a .avatar-container {
font-weight: 400;
flex: none;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
-}
-.nav-sidebar-inner-scroll > div.context-header a .avatar-container.rect-avatar {
- border-style: none;
-}
-.nav-sidebar-inner-scroll
- > div.context-header
- a
- .avatar-container.rect-avatar
- .avatar.s32 {
- border-radius: 4px;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.sidebar-top-level-items {
margin-bottom: 60px;
@@ -1400,18 +1388,6 @@ kbd {
.sidebar-top-level-items .context-header a .avatar-container {
font-weight: 400;
flex: none;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
-}
-.sidebar-top-level-items .context-header a .avatar-container.rect-avatar {
- border-style: none;
-}
-.sidebar-top-level-items
- .context-header
- a
- .avatar-container.rect-avatar
- .avatar.s32 {
- border-radius: 4px;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.sidebar-top-level-items
> li.active
@@ -1628,7 +1604,6 @@ svg.s16 {
float: left;
margin-right: 16px;
border-radius: 50%;
- border: 1px solid rgba(0, 0, 0, 0.08);
}
.avatar.s16,
.avatar-container.s16 {
@@ -1649,7 +1624,7 @@ svg.s16 {
padding: 0;
background: #222;
overflow: hidden;
- border-color: rgba(255, 255, 255, 0.1);
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.avatar.avatar-tile {
border-radius: 0;
@@ -1676,7 +1651,7 @@ svg.s16 {
background-color: #232150;
}
.identicon.bg3 {
- background-color: #f1f1ff;
+ background-color: #1a1a40;
}
.identicon.bg4 {
background-color: #033464;
@@ -1714,9 +1689,15 @@ svg.s16 {
.rect-avatar.s16 {
border-radius: 2px;
}
+.rect-avatar.s16 .avatar {
+ border-radius: 2px;
+}
.rect-avatar.s32 {
border-radius: 4px;
}
+.rect-avatar.s32 .avatar {
+ border-radius: 4px;
+}
:root {
color-scheme: dark;
}
@@ -1817,6 +1798,10 @@ body.gl-dark {
background-color: #262626;
border-right: 1px solid #303030;
}
+.avatar-container,
+.avatar {
+ background: rgba(255, 255, 255, 0.04);
+}
.nav-sidebar li a {
color: var(--gray-600);
}
@@ -1907,7 +1892,7 @@ body.gl-dark .header-search input::placeholder {
body.gl-dark .header-search input:active::placeholder {
color: #868686;
}
-body.gl-dark .header-search.is-not-active .keyboard-shortcut-helper {
+body.gl-dark .header-search .keyboard-shortcut-helper {
color: #fafafa;
background-color: rgba(250, 250, 250, 0.2);
}
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 43ca5a512d5..00ca98bfd27 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1022,7 +1022,7 @@ kbd {
text-align: left;
}
.context-header .avatar-container {
- flex: 0 0 40px;
+ flex: 0 0 32px;
background-color: #fff;
}
.context-header .sidebar-context-title {
@@ -1355,18 +1355,6 @@ kbd {
.nav-sidebar-inner-scroll > div.context-header a .avatar-container {
font-weight: 400;
flex: none;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
-}
-.nav-sidebar-inner-scroll > div.context-header a .avatar-container.rect-avatar {
- border-style: none;
-}
-.nav-sidebar-inner-scroll
- > div.context-header
- a
- .avatar-container.rect-avatar
- .avatar.s32 {
- border-radius: 4px;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.sidebar-top-level-items {
margin-bottom: 60px;
@@ -1379,18 +1367,6 @@ kbd {
.sidebar-top-level-items .context-header a .avatar-container {
font-weight: 400;
flex: none;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
-}
-.sidebar-top-level-items .context-header a .avatar-container.rect-avatar {
- border-style: none;
-}
-.sidebar-top-level-items
- .context-header
- a
- .avatar-container.rect-avatar
- .avatar.s32 {
- border-radius: 4px;
- box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.sidebar-top-level-items
> li.active
@@ -1607,7 +1583,6 @@ svg.s16 {
float: left;
margin-right: 16px;
border-radius: 50%;
- border: 1px solid rgba(0, 0, 0, 0.08);
}
.avatar.s16,
.avatar-container.s16 {
@@ -1628,7 +1603,7 @@ svg.s16 {
padding: 0;
background: #fdfdfd;
overflow: hidden;
- border-color: rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 0 0 1px rgba(31, 31, 31, 0.1);
}
.avatar.avatar-tile {
border-radius: 0;
@@ -1693,9 +1668,15 @@ svg.s16 {
.rect-avatar.s16 {
border-radius: 2px;
}
+.rect-avatar.s16 .avatar {
+ border-radius: 2px;
+}
.rect-avatar.s32 {
border-radius: 4px;
}
+.rect-avatar.s32 .avatar {
+ border-radius: 4px;
+}
.tab-width-8 {
tab-size: 8;
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index 3090edfb123..c0e2d8d44d4 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -11,9 +11,6 @@ html {
font-family: sans-serif;
line-height: 1.15;
}
-header {
- display: block;
-}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
@@ -31,8 +28,7 @@ hr {
height: 0;
overflow: visible;
}
-h1,
-h3 {
+h1 {
margin-top: 0;
margin-bottom: 0.25rem;
}
@@ -53,10 +49,6 @@ img {
vertical-align: middle;
border-style: none;
}
-svg {
- overflow: hidden;
- vertical-align: middle;
-}
label {
display: inline-block;
margin-bottom: 0.5rem;
@@ -86,8 +78,7 @@ fieldset {
[hidden] {
display: none !important;
}
-h1,
-h3 {
+h1 {
margin-bottom: 0.25rem;
font-weight: 600;
line-height: 1.2;
@@ -96,9 +87,6 @@ h3 {
h1 {
font-size: 2.1875rem;
}
-h3 {
- font-size: 1.53125rem;
-}
hr {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
@@ -132,13 +120,6 @@ hr {
max-width: 1140px;
}
}
-.row {
- display: flex;
- flex-wrap: wrap;
- margin-right: -15px;
- margin-left: -15px;
-}
-.col-md-6,
.col-sm-12,
.col {
position: relative;
@@ -151,29 +132,11 @@ hr {
flex-grow: 1;
max-width: 100%;
}
-.order-1 {
- order: 1;
-}
-.order-12 {
- order: 12;
-}
@media (min-width: 576px) {
.col-sm-12 {
flex: 0 0 100%;
max-width: 100%;
}
- .order-sm-1 {
- order: 1;
- }
- .order-sm-12 {
- order: 12;
- }
-}
-@media (min-width: 768px) {
- .col-md-6 {
- flex: 0 0 50%;
- max-width: 50%;
- }
}
.form-control {
display: block;
@@ -241,39 +204,18 @@ hr {
fieldset:disabled a.btn {
pointer-events: none;
}
-.navbar {
- position: relative;
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- justify-content: space-between;
- padding: 0.25rem 0.5rem;
-}
-.navbar .container {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- justify-content: space-between;
-}
-.fixed-top {
- position: fixed;
- top: 0;
- right: 0;
- left: 0;
- z-index: 1030;
-}
.mt-3 {
margin-top: 1rem !important;
}
.mb-3 {
margin-bottom: 1rem !important;
}
+.text-nowrap {
+ white-space: nowrap !important;
+}
.text-center {
text-align: center !important;
}
-.font-weight-normal {
- font-weight: 400 !important;
-}
.gl-form-input,
.gl-form-input.form-control {
background-color: #fff;
@@ -373,8 +315,7 @@ body {
[type="submit"] {
cursor: pointer;
}
-h1,
-h3 {
+h1 {
margin-top: 20px;
margin-bottom: 10px;
}
@@ -384,9 +325,6 @@ a {
hr {
overflow: hidden;
}
-svg {
- vertical-align: baseline;
-}
.form-control {
font-size: 0.875rem;
}
@@ -442,13 +380,6 @@ body.navless {
border-color: #e3e3e3;
color: #303030;
}
-.btn svg {
- height: 15px;
- width: 15px;
-}
-.btn svg:not(:last-child) {
- margin-right: 5px;
-}
.light {
color: #303030;
}
@@ -504,26 +435,6 @@ label.label-bold {
.gl-show-field-errors .gl-field-hint {
color: #303030;
}
-.navbar-empty {
- justify-content: center;
- height: var(--header-height, 48px);
- background: #fff;
- border-bottom: 1px solid #dbdbdb;
-}
-.navbar-empty .tanuki-logo,
-.navbar-empty .brand-header-logo {
- max-height: 100%;
-}
-.tanuki-logo .tanuki {
- fill: #e24329;
-}
-.tanuki-logo .left-cheek,
-.tanuki-logo .right-cheek {
- fill: #fc6d26;
-}
-.tanuki-logo .chin {
- fill: #fca326;
-}
input::-moz-placeholder {
color: #868686;
opacity: 1;
@@ -534,9 +445,6 @@ input::-ms-input-placeholder {
input:-ms-input-placeholder {
color: #868686;
}
-svg {
- fill: currentColor;
-}
.login-page .container {
max-width: 960px;
}
@@ -569,6 +477,14 @@ svg {
.login-page p {
font-size: 13px;
}
+.login-page .borderless .login-box,
+.login-page .borderless .omniauth-container {
+ box-shadow: none;
+}
+.login-page .borderless .g-recaptcha > div {
+ margin-left: auto;
+ margin-right: auto;
+}
.login-page .login-box,
.login-page .omniauth-container {
box-shadow: 0 0 0 1px #dbdbdb;
@@ -732,61 +648,76 @@ svg {
}
}
-.gl-border-solid {
- border-style: solid;
-}
-.gl-border-gray-100 {
- border-color: #dbdbdb;
-}
-.gl-border-1 {
- border-width: 1px;
-}
-.gl-rounded-base {
- border-radius: 0.25rem;
-}
.gl-text-green-600 {
color: #217645;
}
.gl-text-red-500 {
color: #dd2b0e;
}
-.gl-display-flex {
- display: flex;
-}
.gl-display-block {
display: block;
}
-.gl-align-items-center {
- align-items: center;
+.gl-w-10 {
+ width: 3.5rem;
}
-.gl-flex-wrap {
- flex-wrap: wrap;
+.gl-w-half {
+ width: 50%;
+}
+.gl-w-90p {
+ width: 90%;
}
.gl-w-full {
width: 100%;
}
+@media (max-width: 575.98px) {
+ .gl-xs-w-full {
+ width: 100%;
+ }
+}
.gl-p-4 {
padding: 0.75rem;
}
+.gl-pt-5 {
+ padding-top: 1rem;
+}
.gl-mt-2 {
margin-top: 0.25rem;
}
.gl-mt-5 {
margin-top: 1rem;
}
+.gl-mr-auto {
+ margin-right: auto;
+}
+.gl-mr-2 {
+ margin-right: 0.25rem;
+}
+.gl-mb-1 {
+ margin-bottom: 0.125rem;
+}
+.gl-mb-2 {
+ margin-bottom: 0.25rem;
+}
.gl-mb-3 {
margin-bottom: 0.5rem;
}
.gl-mb-5 {
margin-bottom: 1rem;
}
-@media (min-width: 576px) {
- .gl-sm-mt-0 {
- margin-top: 0;
- }
+.gl-ml-auto {
+ margin-left: auto;
}
-.gl-font-weight-bold {
- font-weight: 600;
+.gl-ml-2 {
+ margin-left: 0.25rem;
+}
+.gl-text-center {
+ text-align: center;
+}
+.gl-font-size-h2 {
+ font-size: 1.1875rem;
+}
+.gl-font-weight-normal {
+ font-weight: 400;
}
@import "startup/cloaking";
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index e6e736ef47c..eeb4604f32a 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -98,6 +98,8 @@ $white-light: #2b2b2b;
$white-normal: #333;
$white-dark: #444;
+$theme-indigo-50: #1a1a40;
+
$border-color: #4f4f4f;
$nav-active-bg: rgba(255, 255, 255, 0.08);
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index 34bb4925249..92740aaf89e 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -48,6 +48,17 @@
border-right: 1px solid $gray-50;
}
+.gl-avatar:not(.gl-avatar-identicon),
+.avatar-container,
+.avatar {
+ background: rgba($gray-950, 0.04);
+}
+
+.gl-avatar {
+ @include gl-border-none;
+ box-shadow: inset 0 0 0 1px rgba($gray-950, $gl-avatar-border-opacity);
+}
+
.nav-sidebar {
li {
a {
@@ -149,3 +160,8 @@ body.gl-dark {
background-color: $gray-200;
}
}
+
+.timeline-entry.internal-note:not(.note-form) {
+ // soften on darkmode
+ background-color: mix($gray-50, $orange-50, 75%);
+}
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index 2b6221a6c87..042e21cebd6 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -176,11 +176,9 @@
}
}
- &.is-not-active {
- .keyboard-shortcut-helper {
- color: $search-and-nav-links;
- background-color: rgba($search-and-nav-links, 0.2);
- }
+ .keyboard-shortcut-helper {
+ color: $search-and-nav-links;
+ background-color: rgba($search-and-nav-links, 0.2);
}
}
diff --git a/app/channels/awareness_channel.rb b/app/channels/awareness_channel.rb
index 554e057ca83..cf85e4b3d33 100644
--- a/app/channels/awareness_channel.rb
+++ b/app/channels/awareness_channel.rb
@@ -66,6 +66,7 @@ class AwarenessChannel < ApplicationCable::Channel # rubocop:disable Gitlab/Name
{
id: user.id,
name: user.name,
+ username: user.username,
avatar_url: user.avatar_url(size: 36),
last_activity: last_activity,
last_activity_humanized: ActionController::Base.helpers.distance_of_time_in_words(
diff --git a/app/components/diffs/overflow_warning_component.html.haml b/app/components/diffs/overflow_warning_component.html.haml
index b334bfbcd89..551d995cb22 100644
--- a/app/components/diffs/overflow_warning_component.html.haml
+++ b/app/components/diffs/overflow_warning_component.html.haml
@@ -1,6 +1,6 @@
= render Pajamas::AlertComponent.new(title: _('Too many changes to show.'),
variant: :warning,
- alert_options: { class: 'gl-mb-5' }) do |c|
+ alert_options: { class: 'gl-mb-5', data: { testid: "too-many-changes-alert" } }) do |c|
= c.body do
= message
diff --git a/app/components/pajamas/avatar_component.html.haml b/app/components/pajamas/avatar_component.html.haml
new file mode 100644
index 00000000000..502f673fe2c
--- /dev/null
+++ b/app/components/pajamas/avatar_component.html.haml
@@ -0,0 +1,12 @@
+- if src
+ = image_tag src,
+ srcset: srcset,
+ alt: alt,
+ class: avatar_classes,
+ height: @size,
+ width: @size,
+ loading: "lazy",
+ **@avatar_options
+- else
+ %div{ @avatar_options, alt: alt, class: avatar_classes }
+ = initial
diff --git a/app/components/pajamas/avatar_component.rb b/app/components/pajamas/avatar_component.rb
new file mode 100644
index 00000000000..073968e0491
--- /dev/null
+++ b/app/components/pajamas/avatar_component.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module Pajamas
+ class AvatarComponent < Pajamas::Component
+ include Gitlab::Utils::StrongMemoize
+
+ # @param record [User, Project, Group]
+ # @param alt [String] text for the alt tag
+ # @param class [String] custom CSS class(es)
+ # @param size [Integer] size in pixel
+ # @param [Hash] avatar_options
+ def initialize(record, alt: nil, class: "", size: 64, avatar_options: {})
+ @record = record
+ @alt = alt
+ @class = binding.local_variable_get(:class)
+ @size = filter_attribute(size.to_i, SIZE_OPTIONS, default: 64)
+ @avatar_options = avatar_options
+ end
+
+ private
+
+ SIZE_OPTIONS = [16, 24, 32, 48, 64, 96].freeze
+
+ def avatar_classes
+ classes = ["gl-avatar", "gl-avatar-s#{@size}", @class]
+ classes.push("gl-avatar-circle") if @record.is_a?(User)
+
+ unless src
+ classes.push("gl-avatar-identicon")
+ classes.push("gl-avatar-identicon-bg#{((@record.id || 0) % 7) + 1}")
+ end
+
+ classes.join(' ')
+ end
+
+ def src
+ strong_memoize(:src) do
+ if @record.is_a?(User)
+ # Users show a gravatar instead of an identicon. Also avatars of
+ # blocked users are only shown if the current_user is an admin.
+ # To not duplicate this logic, we are using existing helpers here.
+ current_user = begin
+ helpers.current_user
+ rescue StandardError
+ nil
+ end
+ helpers.avatar_icon_for_user(@record, @size, current_user: current_user)
+ elsif @record.try(:avatar_url)
+ "#{@record.avatar_url}?width=#{@size}"
+ end
+ end
+ end
+
+ def srcset
+ return unless src
+
+ retina_src = src.gsub(/(?<=width=)#{@size}+/, (@size * 2).to_s)
+ "#{src} 1x, #{retina_src} 2x"
+ end
+
+ def alt
+ @alt || @record.name
+ end
+
+ def initial
+ @record.name[0, 1].upcase
+ end
+ end
+end
diff --git a/app/components/pajamas/button_component.html.haml b/app/components/pajamas/button_component.html.haml
index 8ce7d9e0315..5cf57deb7f1 100644
--- a/app/components/pajamas/button_component.html.haml
+++ b/app/components/pajamas/button_component.html.haml
@@ -1,4 +1,4 @@
-= content_tag tag, {**@button_options, **base_attributes, class: button_class, href: @href, target: @target } do
+= content_for :pajamas_button_content, flush: true do
- if @loading
= gl_loading_icon(inline: true, css_class: 'gl-button-icon gl-button-loading-indicator')
- if @icon && (!@loading || content)
@@ -6,3 +6,10 @@
- if content
%span.gl-button-text{ class: @button_text_classes }
= content
+
+- if link?
+ = link_to @href, { **@button_options, **base_attributes, class: button_class, target: @target, method: @method } do
+ = content_for :pajamas_button_content
+- else
+ = content_tag 'button', { **@button_options, **base_attributes, class: button_class } do
+ = content_for :pajamas_button_content
diff --git a/app/components/pajamas/button_component.rb b/app/components/pajamas/button_component.rb
index c6193d1ae05..4233e446d5b 100644
--- a/app/components/pajamas/button_component.rb
+++ b/app/components/pajamas/button_component.rb
@@ -13,6 +13,7 @@ module Pajamas
# @param [String] icon
# @param [String] href
# @param [String] target
+ # @param [Symbol] method
# @param [Hash] button_options
# @param [String] button_text_classes
# @param [String] icon_classes
@@ -28,6 +29,7 @@ module Pajamas
icon: nil,
href: nil,
target: nil,
+ method: nil,
button_options: {},
button_text_classes: nil,
icon_classes: nil
@@ -43,6 +45,7 @@ module Pajamas
@icon = icon
@href = href
@target = filter_attribute(target, TARGET_OPTIONS)
+ @method = filter_attribute(method, METHOD_OPTIONS)
@button_options = button_options
@button_text_classes = button_text_classes
@icon_classes = icon_classes
@@ -75,6 +78,7 @@ module Pajamas
SIZE_OPTIONS = [:small, :medium].freeze
TYPE_OPTIONS = [:button, :reset, :submit].freeze
TARGET_OPTIONS = %w[_self _blank _parent _top].freeze
+ METHOD_OPTIONS = [:get, :post, :put, :delete, :patch].freeze
CATEGORY_CLASSES = {
primary: '',
@@ -101,8 +105,8 @@ module Pajamas
delegate :sprite_icon, to: :helpers
delegate :gl_loading_icon, to: :helpers
- def tag
- @href ? 'a' : 'button'
+ def link?
+ @href.present?
end
def base_attributes
diff --git a/app/components/pajamas/checkbox_component.rb b/app/components/pajamas/checkbox_component.rb
index ae78d0453f8..d9987b7653c 100644
--- a/app/components/pajamas/checkbox_component.rb
+++ b/app/components/pajamas/checkbox_component.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
# Renders a Pajamas compliant checkbox element
-# Must be used in an instance of `ActionView::Helpers::FormBuilder`
+# An instance of `ActionView::Helpers::FormBuilder` must be passed as the `form` argument.
+# The easiest way to use this component is by using the `gitlab_ui_checkbox_component` helper.
+# See https://docs.gitlab.com/ee/development/fe_guide/haml.html#gitlab_ui_checkbox_component
+# To use a checkbox without an instance of `ActionView::Helpers::FormBuilder` use `CheckboxTagComponent`.
module Pajamas
class CheckboxComponent < Pajamas::Component
include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
@@ -31,6 +34,8 @@ module Pajamas
@value = checked_value if checkbox_options[:multiple]
end
+ private
+
attr_reader(
:form,
:method,
@@ -43,8 +48,6 @@ module Pajamas
:value
)
- private
-
def label_content
label? ? label : label_argument
end
diff --git a/app/components/pajamas/checkbox_tag_component.html.haml b/app/components/pajamas/checkbox_tag_component.html.haml
new file mode 100644
index 00000000000..ad02c966fad
--- /dev/null
+++ b/app/components/pajamas/checkbox_tag_component.html.haml
@@ -0,0 +1,6 @@
+.gl-form-checkbox.custom-control.custom-checkbox
+ = check_box_tag(name,
+ value,
+ checked,
+ formatted_input_options)
+ = render_label_tag_with_help_text
diff --git a/app/components/pajamas/checkbox_tag_component.rb b/app/components/pajamas/checkbox_tag_component.rb
new file mode 100644
index 00000000000..45e88588059
--- /dev/null
+++ b/app/components/pajamas/checkbox_tag_component.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# Renders a Pajamas compliant checkbox element
+module Pajamas
+ class CheckboxTagComponent < Pajamas::Component
+ include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
+ include Pajamas::Concerns::CheckboxRadioOptions
+
+ renders_one :label
+ renders_one :help_text
+
+ def initialize(
+ name:,
+ label_options: {},
+ checkbox_options: {},
+ value: '1',
+ checked: false
+ )
+ @name = name
+ @label_options = label_options
+ @input_options = checkbox_options
+ @value = value
+ @checked = checked
+ end
+
+ private
+
+ attr_reader(
+ :name,
+ :label_options,
+ :input_options,
+ :value,
+ :checked
+ )
+
+ def label_content
+ label
+ end
+
+ def help_text_content
+ help_text
+ end
+ end
+end
diff --git a/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb b/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
index 4ece904fb85..298ed200101 100644
--- a/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
+++ b/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
@@ -7,6 +7,10 @@ module Pajamas
form.label(method, formatted_label_options) { label_entry }
end
+ def render_label_tag_with_help_text
+ label_tag(name, formatted_label_options) { label_entry }
+ end
+
private
def label_entry
diff --git a/app/components/pajamas/radio_component.rb b/app/components/pajamas/radio_component.rb
index 52a761b9d7d..7a3d95c8565 100644
--- a/app/components/pajamas/radio_component.rb
+++ b/app/components/pajamas/radio_component.rb
@@ -28,6 +28,8 @@ module Pajamas
@value = value
end
+ private
+
attr_reader(
:form,
:method,
@@ -38,8 +40,6 @@ module Pajamas
:value
)
- private
-
def label_content
label? ? label : label_argument
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index e05e87ffd89..6f21b123eb0 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -13,6 +13,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action :disable_query_limiting, only: [:usage_data]
+ before_action do
+ push_frontend_feature_flag(:ci_variable_settings_graphql)
+ end
+
feature_category :not_owned, [ # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned
:general, :reporting, :metrics_and_profiling, :network,
:preferences, :update, :reset_health_check_token
diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb
index a6a21cf3649..b0d7c8cb8f2 100644
--- a/app/controllers/admin/applications_controller.rb
+++ b/app/controllers/admin/applications_controller.rb
@@ -11,7 +11,6 @@ class Admin::ApplicationsController < Admin::ApplicationController
def index
applications = ApplicationsFinder.new.execute
@applications = Kaminari.paginate_array(applications).page(params[:page])
- @application_counts = OauthAccessToken.distinct_resource_owner_counts(@applications)
end
def show
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index bf573d45852..a53e832329f 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -58,7 +58,6 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
def broadcast_message_params
params.require(:broadcast_message).permit(%i(
- color
theme
ends_at
message
diff --git a/app/controllers/admin/ci/variables_controller.rb b/app/controllers/admin/ci/variables_controller.rb
index d4b7d750759..7d643435ddb 100644
--- a/app/controllers/admin/ci/variables_controller.rb
+++ b/app/controllers/admin/ci/variables_controller.rb
@@ -31,7 +31,7 @@ class Admin::Ci::VariablesController < Admin::ApplicationController
def render_instance_variables
render status: :ok,
- json: {
+ json: {
variables: Ci::InstanceVariableSerializer.new.represent(variables)
}
end
@@ -41,7 +41,7 @@ class Admin::Ci::VariablesController < Admin::ApplicationController
end
def variables_params
- params.permit(variables_attributes: [*variable_params_attributes])
+ params.permit(variables_attributes: Array(variable_params_attributes))
end
def variable_params_attributes
diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
index 47e3337aed7..71ee19ddf39 100644
--- a/app/controllers/admin/dev_ops_report_controller.rb
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -1,11 +1,16 @@
# frozen_string_literal: true
class Admin::DevOpsReportController < Admin::ApplicationController
- include RedisTracking
+ include ProductAnalyticsTracking
helper_method :show_adoption?
- track_redis_hll_event :show, name: 'i_analytics_dev_ops_score', if: -> { should_track_devops_score? }
+ track_custom_event :show,
+ name: 'i_analytics_dev_ops_score',
+ action: 'perform_analytics_usage_action',
+ label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
+ destinations: %i[redis_hll snowplow],
+ conditions: -> { should_track_devops_score? }
feature_category :devops_reports
@@ -24,6 +29,14 @@ class Admin::DevOpsReportController < Admin::ApplicationController
def should_track_devops_score?
true
end
+
+ def tracking_namespace_source
+ nil
+ end
+
+ def tracking_project_source
+ nil
+ end
end
Admin::DevOpsReportController.prepend_mod_with('Admin::DevOpsReportController')
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 6fd1e9bb70e..3f3c3581555 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -48,8 +48,8 @@ class Admin::ProjectsController < Admin::ApplicationController
flash[:notice] = _("Project '%{project_name}' is in the process of being deleted.") % { project_name: @project.full_name }
redirect_to admin_projects_path, status: :found
- rescue Projects::DestroyService::DestroyError => ex
- redirect_to admin_projects_path, status: :found, alert: ex.message
+ rescue Projects::DestroyService::DestroyError => e
+ redirect_to admin_projects_path, status: :found, alert: e.message
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/controllers/admin/runner_projects_controller.rb b/app/controllers/admin/runner_projects_controller.rb
index 0165c6471db..7dbae565d07 100644
--- a/app/controllers/admin/runner_projects_controller.rb
+++ b/app/controllers/admin/runner_projects_controller.rb
@@ -9,7 +9,7 @@ class Admin::RunnerProjectsController < Admin::ApplicationController
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
- if ::Ci::Runners::AssignRunnerService.new(@runner, @project, current_user).execute
+ if ::Ci::Runners::AssignRunnerService.new(@runner, @project, current_user).execute.success?
redirect_to edit_admin_runner_url(@runner), notice: s_('Runners|Runner assigned to project.')
else
redirect_to edit_admin_runner_url(@runner), alert: 'Failed adding runner to project'
diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb
index f81b02ad31f..41f95addc66 100644
--- a/app/controllers/admin/system_info_controller.rb
+++ b/app/controllers/admin/system_info_controller.rb
@@ -37,8 +37,16 @@ class Admin::SystemInfoController < Admin::ApplicationController
].freeze
def show
- @cpus = Vmstat.cpu rescue nil
- @memory = Vmstat.memory rescue nil
+ @cpus = begin
+ Vmstat.cpu
+ rescue StandardError
+ nil
+ end
+ @memory = begin
+ Vmstat.memory
+ rescue StandardError
+ nil
+ end
mounts = Sys::Filesystem.mounts
@disks = []
@@ -52,9 +60,9 @@ class Admin::SystemInfoController < Admin::ApplicationController
disk = Sys::Filesystem.stat(mount.mount_point)
@disks.push({
bytes_total: disk.bytes_total,
- bytes_used: disk.bytes_used,
- disk_name: mount.name,
- mount_path: disk.path
+ bytes_used: disk.bytes_used,
+ disk_name: mount.name,
+ mount_path: disk.path
})
rescue Sys::Filesystem::Error
end
diff --git a/app/controllers/admin/topics_controller.rb b/app/controllers/admin/topics_controller.rb
index b451928e591..69bcfdf4791 100644
--- a/app/controllers/admin/topics_controller.rb
+++ b/app/controllers/admin/topics_controller.rb
@@ -45,6 +45,22 @@ class Admin::TopicsController < Admin::ApplicationController
notice: _('Topic %{topic_name} was successfully removed.') % { topic_name: @topic.title_or_name }
end
+ def merge
+ source_topic = Projects::Topic.find(merge_params[:source_topic_id])
+ target_topic = Projects::Topic.find(merge_params[:target_topic_id])
+
+ begin
+ ::Topics::MergeService.new(source_topic, target_topic).execute
+ rescue ArgumentError => e
+ return render status: :bad_request, json: { type: :alert, message: e.message }
+ end
+
+ message = _('Topic %{source_topic} was successfully merged into topic %{target_topic}.')
+ redirect_to admin_topics_path,
+ status: :found,
+ notice: message % { source_topic: source_topic.name, target_topic: target_topic.name }
+ end
+
private
def topic
@@ -63,4 +79,8 @@ class Admin::TopicsController < Admin::ApplicationController
:title
]
end
+
+ def merge_params
+ params.permit([:source_topic_id, :target_topic_id])
+ end
end
diff --git a/app/controllers/admin/usage_trends_controller.rb b/app/controllers/admin/usage_trends_controller.rb
index 2cede1aec05..082b38ac3a8 100644
--- a/app/controllers/admin/usage_trends_controller.rb
+++ b/app/controllers/admin/usage_trends_controller.rb
@@ -1,9 +1,13 @@
# frozen_string_literal: true
class Admin::UsageTrendsController < Admin::ApplicationController
- include RedisTracking
+ include ProductAnalyticsTracking
- track_redis_hll_event :index, name: 'i_analytics_instance_statistics'
+ track_custom_event :index,
+ name: 'i_analytics_instance_statistics',
+ action: 'perform_analytics_usage_action',
+ label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
+ destinations: %i[redis_hll snowplow]
feature_category :devops_reports
@@ -11,4 +15,12 @@ class Admin::UsageTrendsController < Admin::ApplicationController
def index
end
+
+ def tracking_namespace_source
+ @group
+ end
+
+ def tracking_project_source
+ nil
+ end
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 874eb8985fb..5cc0c8f3970 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -88,7 +88,7 @@ class Admin::UsersController < Admin::ApplicationController
result = Users::RejectService.new(current_user).execute(user)
if result[:status] == :success
- redirect_to admin_users_path, status: :found, notice: _("You've rejected %{user}" % { user: user.name })
+ redirect_back_or_admin_user(notice: _("You've rejected %{user}" % { user: user.name }))
else
redirect_back_or_admin_user(alert: result[:message])
end
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 6d1ffc1f2e8..88592efcec7 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -5,7 +5,6 @@ class AutocompleteController < ApplicationController
skip_before_action :authenticate_user!, only: [:users, :award_emojis, :merge_request_target_branches]
before_action :check_search_rate_limit!, only: [:users, :projects]
- before_action :authorize_admin_project, only: :deploy_keys_with_owners
feature_category :users, [:users, :user]
feature_category :projects, [:projects]
@@ -61,7 +60,9 @@ class AutocompleteController < ApplicationController
end
def deploy_keys_with_owners
- deploy_keys = DeployKey.with_write_access_for_project(project)
+ deploy_keys = Autocomplete::DeployKeysWithWriteAccessFinder
+ .new(current_user, project)
+ .execute
render json: DeployKeys::BasicDeployKeySerializer.new.represent(
deploy_keys, { with_owner: true, user: current_user }
@@ -70,10 +71,6 @@ class AutocompleteController < ApplicationController
private
- def authorize_admin_project
- render_403 unless Ability.allowed?(current_user, :admin_project, project)
- end
-
def project
@project ||= Autocomplete::ProjectFinder
.new(current_user, params)
diff --git a/app/controllers/concerns/accepts_pending_invitations.rb b/app/controllers/concerns/accepts_pending_invitations.rb
index 5601b7a7f79..53dec698fa0 100644
--- a/app/controllers/concerns/accepts_pending_invitations.rb
+++ b/app/controllers/concerns/accepts_pending_invitations.rb
@@ -3,12 +3,12 @@
module AcceptsPendingInvitations
extend ActiveSupport::Concern
- def accept_pending_invitations
- return unless resource.active_for_authentication?
+ def accept_pending_invitations(user: resource)
+ return unless user.active_for_authentication?
- if resource.pending_invitations.load.any?
- resource.accept_pending_invitations!
- clear_stored_location_for_resource
+ if user.pending_invitations.load.any?
+ user.accept_pending_invitations!
+ clear_stored_location_for(user: user)
after_pending_invitations_hook
end
end
@@ -17,8 +17,8 @@ module AcceptsPendingInvitations
# no-op
end
- def clear_stored_location_for_resource
- session_key = stored_location_key_for(resource)
+ def clear_stored_location_for(user:)
+ session_key = stored_location_key_for(user)
session.delete(session_key)
end
diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb
index 0fb77e2aaf4..b6ba1b13cc3 100644
--- a/app/controllers/concerns/creates_commit.rb
+++ b/app/controllers/concerns/creates_commit.rb
@@ -98,8 +98,7 @@ module CreatesCommit
project_new_merge_request_path(
@project_to_commit_into,
merge_request: {
- source_project_id: @project_to_commit_into.id,
- target_project_id: target_project.id,
+ target_project_id: @project_to_commit_into.default_merge_request_target.id,
source_branch: @branch_name,
target_branch: @start_branch
}
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index a5e49b1b16a..f1d80e37674 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -171,7 +171,7 @@ module IssuableActions
discussions = Discussion.build_collection(notes, issuable)
if issuable.is_a?(MergeRequest)
- render_cached(discussions, with: discussion_serializer, cache_context: -> (_) { discussion_cache_context }, context: self)
+ render_mr_discussions(discussions, discussion_serializer, discussion_cache_context)
elsif issuable.is_a?(Issue)
render json: discussion_serializer.represent(discussions, context: self) if stale?(etag: [discussion_cache_context, discussions])
else
@@ -182,6 +182,20 @@ module IssuableActions
private
+ def render_mr_discussions(discussions, serializer, cache_context)
+ return unless stale?(etag: [cache_context, discussions])
+
+ if Feature.enabled?(:disabled_mr_discussions_redis_cache, project)
+ render json: serializer.represent(discussions, context: self)
+ else
+ render_cached_discussions(discussions, serializer, cache_context)
+ end
+ end
+
+ def render_cached_discussions(discussions, serializer, cache_context)
+ render_cached(discussions, with: serializer, cache_context: -> (_) { cache_context }, context: self)
+ end
+
def paginated_discussions
return if params[:per_page].blank?
return if issuable.instance_of?(MergeRequest) && Feature.disabled?(:paginated_mr_discussions, project)
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index 928c617471b..b595c3c6790 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -217,7 +217,8 @@ module NotesActions
:note,
:line_code, # LegacyDiffNote
:position, # DiffNote
- :confidential
+ :confidential,
+ :internal
).tap do |create_params|
create_params.merge!(
params.permit(:merge_request_diff_head_sha, :in_reply_to_discussion_id)
diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb
index dc7ba8295b9..260b433cc6f 100644
--- a/app/controllers/concerns/product_analytics_tracking.rb
+++ b/app/controllers/concerns/product_analytics_tracking.rb
@@ -13,6 +13,14 @@ module ProductAnalyticsTracking
route_events_to(destinations, name, &block)
end
end
+
+ def track_custom_event(*controller_actions, name:, conditions: nil, action:, label:, destinations: [:redis_hll], &block)
+ custom_conditions = [:trackable_html_request?, *conditions]
+
+ after_action only: controller_actions, if: custom_conditions do
+ route_custom_events_to(destinations, name, action, label, &block)
+ end
+ end
end
private
@@ -25,13 +33,40 @@ module ProductAnalyticsTracking
end
end
+ def route_custom_events_to(destinations, name, action, label, &block)
+ track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
+
+ return unless destinations.include?(:snowplow) && event_enabled?(name)
+
+ optional_arguments = {
+ namespace: tracking_namespace_source,
+ project: tracking_project_source
+ }.compact
+
+ Gitlab::Tracking.event(
+ self.class.to_s,
+ action,
+ user: current_user,
+ property: name,
+ label: label,
+ **optional_arguments
+ )
+ end
+
def event_enabled?(event)
events_to_ff = {
g_analytics_valuestream: :route_hll_to_snowplow,
i_search_paid: :route_hll_to_snowplow_phase2,
i_search_total: :route_hll_to_snowplow_phase2,
- i_search_advanced: :route_hll_to_snowplow_phase2
+ i_search_advanced: :route_hll_to_snowplow_phase2,
+ i_ecosystem_jira_service_list_issues: :route_hll_to_snowplow_phase2,
+ users_viewing_analytics_group_devops_adoption: :route_hll_to_snowplow_phase2,
+ i_analytics_dev_ops_adoption: :route_hll_to_snowplow_phase2,
+ i_analytics_dev_ops_score: :route_hll_to_snowplow_phase2,
+ p_analytics_merge_request: :route_hll_to_snowplow_phase2,
+ i_analytics_instance_statistics: :route_hll_to_snowplow_phase2,
+ g_analytics_contribution: :route_hll_to_snowplow_phase2
}
Feature.enabled?(events_to_ff[event.to_sym], tracking_namespace_source)
diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb
index c1135d2f759..445e72b8266 100644
--- a/app/controllers/concerns/redis_tracking.rb
+++ b/app/controllers/concerns/redis_tracking.rb
@@ -29,7 +29,7 @@ module RedisTracking
private
def track_unique_redis_hll_event(event_name, &block)
- custom_id = block_given? ? yield(self) : nil
+ custom_id = block ? yield(self) : nil
unique_id = custom_id || visitor_id
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
index f914e804e18..e98d36854f1 100644
--- a/app/controllers/concerns/uploads_actions.rb
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -143,10 +143,8 @@ module UploadsActions
end
def bypass_auth_checks_on_uploads?
- if ::Feature.enabled?(:enforce_auth_checks_on_uploads, target_project)
- if target_project && !target_project.public? && target_project.enforce_auth_checks_on_uploads?
- return false
- end
+ if target_project && !target_project.public? && target_project.enforce_auth_checks_on_uploads?
+ return false
end
action_name == 'show' && embeddable?
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 0fbceb43be1..e64d838b7d1 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -10,8 +10,8 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag(:board_multi_select, group)
push_frontend_feature_flag(:realtime_labels, group)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
- e.control { }
- e.candidate { }
+ e.control {}
+ e.candidate {}
end.run
end
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index b1afac1f1c7..e164a834519 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -10,6 +10,9 @@ module Groups
before_action :define_variables, only: [:show]
before_action :push_licensed_features, only: [:show]
before_action :assign_variables_to_gon, only: [:show]
+ before_action do
+ push_frontend_feature_flag(:ci_variable_settings_graphql, @group)
+ end
feature_category :continuous_integration
urgency :low
diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb
index 1e23db9f32b..220b0b4509c 100644
--- a/app/controllers/groups/variables_controller.rb
+++ b/app/controllers/groups/variables_controller.rb
@@ -46,7 +46,7 @@ module Groups
end
def group_variables_params
- params.permit(variables_attributes: [*variable_params_attributes])
+ params.permit(variables_attributes: Array(variable_params_attributes))
end
def variable_params_attributes
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 327b4832f31..32b187c3260 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -34,6 +34,10 @@ class GroupsController < Groups::ApplicationController
before_action :track_experiment_event, only: [:new]
+ before_action only: :issues do
+ push_force_frontend_feature_flag(:work_items, group.work_items_feature_flag_enabled?)
+ end
+
helper_method :captcha_required?
skip_cross_project_access_check :index, :new, :create, :edit, :update,
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index 2d607fb7ff7..893c0b6ac54 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -47,7 +47,14 @@ class Import::BulkImportsController < ApplicationController
end
def create
- responses = create_params.map { |entry| ::BulkImports::CreateService.new(current_user, entry, credentials).execute }
+ responses = create_params.map do |entry|
+ if entry[:destination_name]
+ entry[:destination_slug] ||= entry[:destination_name]
+ entry.delete(:destination_name)
+ end
+
+ ::BulkImports::CreateService.new(current_user, entry, credentials).execute
+ end
render json: responses.map { |response| { success: response.success?, id: response.payload[:id], message: response.message } }
end
@@ -100,6 +107,7 @@ class Import::BulkImportsController < ApplicationController
source_type
source_full_path
destination_name
+ destination_slug
destination_namespace
]
end
diff --git a/app/controllers/oauth/token_info_controller.rb b/app/controllers/oauth/token_info_controller.rb
index 789356f4410..626184150bd 100644
--- a/app/controllers/oauth/token_info_controller.rb
+++ b/app/controllers/oauth/token_info_controller.rb
@@ -9,7 +9,7 @@ class Oauth::TokenInfoController < Doorkeeper::TokenInfoController
# maintain backwards compatibility
render json: token_json.merge(
- 'scopes' => token_json[:scope],
+ 'scopes' => token_json[:scope],
'expires_in_seconds' => token_json[:expires_in]
), status: :ok
else
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 45decccfc36..817f272d458 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -6,6 +6,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
include AuthHelper
include InitializesCurrentUserMode
include KnownSignIn
+ include AcceptsPendingInvitations
after_action :verify_known_sign_in
@@ -25,7 +26,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# the number of failed sign in attempts
def failure
if params[:username].present? && AuthHelper.form_based_provider?(failed_strategy.name)
- user = User.by_login(params[:username])
+ user = User.find_by_login(params[:username])
user&.increment_failed_attempts!
log_failed_login(params[:username], failed_strategy.name)
@@ -159,6 +160,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def sign_in_user_flow(auth_user_class)
auth_user = build_auth_user(auth_user_class)
+ new_user = auth_user.new?
user = auth_user.find_and_update!
if auth_user.valid_sign_in?
@@ -178,6 +180,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
flash[:notice] = _('Welcome back! Your account had been deactivated due to inactivity but is now reactivated.')
end
+ accept_pending_invitations(user: user) if new_user
store_after_sign_up_path_for_user if intent_to_register?
sign_in_and_redirect(user, event: :authentication)
end
diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb
index 1a8908e8571..07d786ab060 100644
--- a/app/controllers/profiles/personal_access_tokens_controller.rb
+++ b/app/controllers/profiles/personal_access_tokens_controller.rb
@@ -3,10 +3,6 @@
class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
feature_category :authentication_and_authorization
- before_action do
- push_frontend_feature_flag(:personal_access_tokens_scoped_to_projects, current_user)
- end
-
def index
set_index_vars
scopes = params[:scopes].split(',').map(&:squish).select(&:present?).map(&:to_sym) unless params[:scopes].nil?
@@ -62,7 +58,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
end
def active_personal_access_tokens
- tokens = finder(state: 'active', sort: 'expires_at_asc').execute
+ tokens = finder(state: 'active', sort: 'expires_at_asc_id_desc').execute
if Feature.enabled?('access_token_pagination')
tokens = tokens.page(page)
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 2e71b4801ed..0b7d4626c6d 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -234,7 +234,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
def groups_notification(groups)
group_links = groups.map { |group| view_context.link_to group.full_name, group_path(group) }.to_sentence
- leave_group_links = groups.map { |group| view_context.link_to (s_("leave %{group_name}") % { group_name: group.full_name }), leave_group_members_path(group), remote: false, method: :delete}.to_sentence
+ leave_group_links = groups.map { |group| view_context.link_to (s_("leave %{group_name}") % { group_name: group.full_name }), leave_group_members_path(group), remote: false, method: :delete }.to_sentence
s_(%{The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}.})
.html_safe % { group_links: group_links.html_safe, leave_group_links: leave_group_links.html_safe }
diff --git a/app/controllers/projects/alerting/notifications_controller.rb b/app/controllers/projects/alerting/notifications_controller.rb
index 82fff287c4a..f3283c88740 100644
--- a/app/controllers/projects/alerting/notifications_controller.rb
+++ b/app/controllers/projects/alerting/notifications_controller.rb
@@ -13,8 +13,6 @@ module Projects
prepend_before_action :repository, :project_without_auth
feature_category :incident_management
- # Goal is to increase the urgency to medium.
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/361310.
urgency :low, [:create]
def create
diff --git a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
index 7b38c069a60..ab2cf3abdde 100644
--- a/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
+++ b/app/controllers/projects/analytics/cycle_analytics/stages_controller.rb
@@ -2,6 +2,7 @@
class Projects::Analytics::CycleAnalytics::StagesController < Projects::ApplicationController
include ::Analytics::CycleAnalytics::StageActions
+ include Gitlab::Utils::StrongMemoize
extend ::Gitlab::Utils::Override
respond_to :json
@@ -10,6 +11,7 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat
before_action :authorize_read_cycle_analytics!
before_action :only_default_value_stream_is_allowed!
+ before_action :authorize_stage!, only: [:median, :count, :average, :records]
urgency :low
@@ -25,7 +27,26 @@ class Projects::Analytics::CycleAnalytics::StagesController < Projects::Applicat
Analytics::CycleAnalytics::ProjectValueStream
end
+ override :cycle_analytics_configuration
+ def cycle_analytics_configuration(stages)
+ super(stages.select { |stage| permitted_stage?(stage) })
+ end
+
def only_default_value_stream_is_allowed!
render_404 if params[:value_stream_id] != Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME
end
+
+ def permitted_stage?(stage)
+ permissions[stage.name.to_sym] # name matches the permission key (only when default stages are used)
+ end
+
+ def permissions
+ strong_memoize(:permissions) do
+ Gitlab::CycleAnalytics::Permissions.new(user: current_user, project: parent).get
+ end
+ end
+
+ def authorize_stage!
+ render_403 unless permitted_stage?(stage)
+ end
end
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 97aae56c4ec..f5188e28b81 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -43,6 +43,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:highlight_js, @project)
+ push_frontend_feature_flag(:file_line_blame, @project)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 36986a714fb..82b35a22669 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -10,8 +10,8 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag(:board_multi_select, project)
push_frontend_feature_flag(:realtime_labels, project&.group)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
- e.control { }
- e.candidate { }
+ e.control {}
+ e.candidate {}
end.run
end
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 85e258b62e8..84e5d59a2c3 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -4,7 +4,6 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
before_action :check_can_collaborate!
before_action do
push_frontend_feature_flag(:schema_linting, @project)
- push_frontend_feature_flag(:simulate_pipeline, @project)
end
feature_category :pipeline_authoring
diff --git a/app/controllers/projects/ci/secure_files_controller.rb b/app/controllers/projects/ci/secure_files_controller.rb
deleted file mode 100644
index 59ddca19081..00000000000
--- a/app/controllers/projects/ci/secure_files_controller.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class Projects::Ci::SecureFilesController < Projects::ApplicationController
- before_action :authorize_read_secure_files!
-
- feature_category :pipeline_authoring
-
- def show
- render_404 unless Feature.enabled?(:ci_secure_files, project)
- end
-end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 09a06aaed8c..d7fd65f02a8 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -88,7 +88,7 @@ class Projects::CompareController < Projects::ApplicationController
# target == start_ref == from
def target_project
strong_memoize(:target_project) do
- next source_project unless compare_params.key?(:from_project_id)
+ next source_project.default_merge_request_target unless compare_params.key?(:from_project_id)
next source_project if compare_params[:from_project_id].to_i == source_project.id
target_project = target_projects(source_project).find_by_id(compare_params[:from_project_id])
diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb
index 1d1fe91ad70..16392775c09 100644
--- a/app/controllers/projects/feature_flags_controller.rb
+++ b/app/controllers/projects/feature_flags_controller.rb
@@ -111,9 +111,9 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
.permit(:name, :description, :active,
scopes_attributes: [:id, :environment_scope, :active, :_destroy,
strategies: [:name, parameters: [:groupId, :percentage, :userIds]]],
- strategies_attributes: [:id, :name, :user_list_id, :_destroy,
- parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness],
- scopes_attributes: [:id, :environment_scope, :_destroy]])
+ strategies_attributes: [:id, :name, :user_list_id, :_destroy,
+ parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness],
+ scopes_attributes: [:id, :environment_scope, :_destroy]])
end
def feature_flag_json(feature_flag)
diff --git a/app/controllers/projects/google_cloud/base_controller.rb b/app/controllers/projects/google_cloud/base_controller.rb
index 050b26a40c7..d1eb86c5e49 100644
--- a/app/controllers/projects/google_cloud/base_controller.rb
+++ b/app/controllers/projects/google_cloud/base_controller.rb
@@ -80,4 +80,16 @@ class Projects::GoogleCloud::BaseController < Projects::ApplicationController
Gitlab::Tracking.event('Projects::GoogleCloud', action, **options)
end
+
+ def gcp_projects
+ google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ google_api_client.list_projects
+ end
+
+ def refs
+ params = { per_page: 50 }
+ branches = BranchesFinder.new(project.repository, params).execute(gitaly_pagination: true)
+ tags = TagsFinder.new(project.repository, params).execute(gitaly_pagination: true)
+ (branches + tags).map(&:name)
+ end
end
diff --git a/app/controllers/projects/google_cloud/configuration_controller.rb b/app/controllers/projects/google_cloud/configuration_controller.rb
index fa672058247..8d252c35031 100644
--- a/app/controllers/projects/google_cloud/configuration_controller.rb
+++ b/app/controllers/projects/google_cloud/configuration_controller.rb
@@ -4,7 +4,6 @@ module Projects
module GoogleCloud
class ConfigurationController < Projects::GoogleCloud::BaseController
def index
- @google_cloud_path = project_google_cloud_configuration_path(project)
js_data = {
configurationUrl: project_google_cloud_configuration_path(project),
deploymentsUrl: project_google_cloud_deployments_path(project),
diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb
index 711409e7550..7b1cf6e5ce1 100644
--- a/app/controllers/projects/google_cloud/databases_controller.rb
+++ b/app/controllers/projects/google_cloud/databases_controller.rb
@@ -4,7 +4,6 @@ module Projects
module GoogleCloud
class DatabasesController < Projects::GoogleCloud::BaseController
def index
- @google_cloud_path = project_google_cloud_configuration_path(project)
js_data = {
configurationUrl: project_google_cloud_configuration_path(project),
deploymentsUrl: project_google_cloud_deployments_path(project),
diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb
index 4aa17b36fad..1ac4697a63f 100644
--- a/app/controllers/projects/google_cloud/deployments_controller.rb
+++ b/app/controllers/projects/google_cloud/deployments_controller.rb
@@ -4,7 +4,6 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base
before_action :validate_gcp_token!
def index
- @google_cloud_path = project_google_cloud_configuration_path(project)
js_data = {
configurationUrl: project_google_cloud_configuration_path(project),
deploymentsUrl: project_google_cloud_deployments_path(project),
@@ -40,9 +39,9 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base
redirect_to project_new_merge_request_path(project, merge_request: cloud_run_mr_params)
end
end
- rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error
- track_event('deployments#cloud_run', 'error_gcp', error)
- flash[:warning] = _('Google Cloud Error - %{error}') % { error: error }
+ rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => e
+ track_event('deployments#cloud_run', 'error_gcp', e)
+ flash[:warning] = _('Google Cloud Error - %{error}') % { error: e }
redirect_to project_google_cloud_deployments_path(project)
end
diff --git a/app/controllers/projects/google_cloud/gcp_regions_controller.rb b/app/controllers/projects/google_cloud/gcp_regions_controller.rb
index 3fbe9a96284..39f33624804 100644
--- a/app/controllers/projects/google_cloud/gcp_regions_controller.rb
+++ b/app/controllers/projects/google_cloud/gcp_regions_controller.rb
@@ -9,13 +9,7 @@ class Projects::GoogleCloud::GcpRegionsController < Projects::GoogleCloud::BaseC
GCP_REGION_CI_VAR_KEY = 'GCP_REGION'
def index
- @google_cloud_path = project_google_cloud_configuration_path(project)
- params = { per_page: 50 }
- branches = BranchesFinder.new(project.repository, params).execute(gitaly_pagination: true)
- tags = TagsFinder.new(project.repository, params).execute(gitaly_pagination: true)
- refs = (branches + tags).map(&:name)
js_data = {
- screen: 'gcp_regions_form',
availableRegions: AVAILABLE_REGIONS,
refs: refs,
cancelPath: project_google_cloud_configuration_path(project)
diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb
index dbd83be19db..7f25054177e 100644
--- a/app/controllers/projects/google_cloud/service_accounts_controller.rb
+++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb
@@ -4,22 +4,12 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
before_action :validate_gcp_token!
def index
- @google_cloud_path = project_google_cloud_configuration_path(project)
- google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
- gcp_projects = google_api_client.list_projects
-
if gcp_projects.empty?
- @js_data = { screen: 'no_gcp_projects' }.to_json
track_event('service_accounts#index', 'error_form', 'no_gcp_projects')
flash[:warning] = _('No Google Cloud projects - You need at least one Google Cloud project')
redirect_to project_google_cloud_configuration_path(project)
else
- params = { per_page: 50 }
- branches = BranchesFinder.new(project.repository, params).execute(gitaly_pagination: true)
- tags = TagsFinder.new(project.repository, params).execute(gitaly_pagination: true)
- refs = (branches + tags).map(&:name)
js_data = {
- screen: 'service_accounts_form',
gcpProjects: gcp_projects,
refs: refs,
cancelPath: project_google_cloud_configuration_path(project)
@@ -28,9 +18,9 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
track_event('service_accounts#index', 'success', js_data)
end
- rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error
- track_event('service_accounts#index', 'error_gcp', error)
- flash[:warning] = _('Google Cloud Error - %{error}') % { error: error }
+ rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => e
+ track_event('service_accounts#index', 'error_gcp', e)
+ flash[:warning] = _('Google Cloud Error - %{error}') % { error: e }
redirect_to project_google_cloud_configuration_path(project)
end
@@ -47,9 +37,9 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::
track_event('service_accounts#create', 'success', response)
redirect_to project_google_cloud_configuration_path(project), notice: response.message
- rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error
- track_event('service_accounts#create', 'error_gcp', error)
- flash[:warning] = _('Google Cloud Error - %{error}') % { error: error }
+ rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => e
+ track_event('service_accounts#create', 'error_gcp', e)
+ flash[:warning] = _('Google Cloud Error - %{error}') % { error: e }
redirect_to project_google_cloud_configuration_path(project)
end
end
diff --git a/app/controllers/projects/incidents_controller.rb b/app/controllers/projects/incidents_controller.rb
index f9fa8046962..36b52533e78 100644
--- a/app/controllers/projects/incidents_controller.rb
+++ b/app/controllers/projects/incidents_controller.rb
@@ -9,7 +9,7 @@ class Projects::IncidentsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:incident_timeline, @project)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
- push_frontend_feature_flag(:work_items_mvc_2)
+ 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)
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index f1c9e2b2653..d19db2b11ab 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -44,12 +44,16 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:incident_timeline, project)
end
+ before_action only: [:index, :show] do
+ push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
+ end
+
before_action only: :show do
push_frontend_feature_flag(:issue_assignees_widget, project)
push_frontend_feature_flag(:realtime_labels, project)
- push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
- push_frontend_feature_flag(:work_items_mvc_2)
+ 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_force_frontend_feature_flag(:work_items_create_from_markdown, project&.work_items_create_from_markdown_feature_flag_enabled?)
end
around_action :allow_gitaly_ref_name_caching, only: [:discussions]
@@ -239,12 +243,12 @@ class Projects::IssuesController < Projects::ApplicationController
end
def import_csv
- if uploader = UploadService.new(project, params[:file]).execute
- ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id) # rubocop:disable CodeReuse/Worker
+ result = Issues::PrepareImportCsvService.new(project, current_user, file: params[:file]).execute
- flash[:notice] = _("Your issues are being imported. Once finished, you'll get a confirmation email.")
+ if result.success?
+ flash[:notice] = result.message
else
- flash[:alert] = _("File upload error.")
+ flash[:alert] = result.message
end
redirect_to project_issues_path(project)
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index ad59f421c06..7878ace5015 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -18,7 +18,7 @@ class Projects::JobsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :authorize_create_proxy_build!, only: :proxy_websocket_authorize
before_action :verify_proxy_request!, only: :proxy_websocket_authorize
- before_action :push_job_log_search, only: [:show]
+ before_action :push_job_log_jump_to_failures, only: [:show]
before_action :reject_if_build_artifacts_size_refreshing!, only: [:erase]
layout 'project'
@@ -249,7 +249,7 @@ class Projects::JobsController < Projects::ApplicationController
::Gitlab::Workhorse.channel_websocket(service)
end
- def push_job_log_search
- push_frontend_feature_flag(:job_log_search, @project)
+ def push_job_log_jump_to_failures
+ push_frontend_feature_flag(:job_log_jump_to_failures, @project)
end
end
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 0dcc2bc3181..279fd4c457e 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -48,20 +48,24 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
allow_tree_conflicts: display_merge_conflicts_in_diff?
}
- if diff_options_hash[:paths].blank?
- # NOTE: Any variables that would affect the resulting json needs to be added to the cache_context to avoid stale cache issues.
- cache_context = [
- current_user&.cache_key,
- unfoldable_positions.map(&:to_h),
- diff_view,
- params[:w],
- params[:expanded],
- params[:page],
- params[:per_page],
- options[:merge_ref_head_diff],
- options[:allow_tree_conflicts]
- ]
+ # NOTE: Any variables that would affect the resulting json needs to be added to the cache_context to avoid stale cache issues.
+ cache_context = [
+ current_user&.cache_key,
+ unfoldable_positions.map(&:to_h),
+ diff_view,
+ params[:w],
+ params[:expanded],
+ params[:page],
+ params[:per_page],
+ options[:merge_ref_head_diff],
+ options[:allow_tree_conflicts]
+ ]
+
+ if Feature.enabled?(:etag_merge_request_diff_batches, @merge_request.project)
+ return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs])
+ end
+ if diff_options_hash[:paths].blank?
render_cached(
diffs,
with: PaginatedDiffSerializer.new(current_user: current_user),
diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb
index db7557674b2..ff6b6bfaf27 100644
--- a/app/controllers/projects/merge_requests/drafts_controller.rb
+++ b/app/controllers/projects/merge_requests/drafts_controller.rb
@@ -72,9 +72,9 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli
strong_memoize(:draft_note) do
draft_notes.find(params[:id])
end
- rescue ActiveRecord::RecordNotFound => ex
+ rescue ActiveRecord::RecordNotFound => e
# draft_note is allowed to be nil in #publish
- raise ex unless allow_nil
+ raise e unless allow_nil
end
def draft_notes
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index a2f018c013b..870c57fd6f3 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -34,16 +34,13 @@ 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(:restructured_mr_widget, 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(:rebase_without_ci_ui, project)
push_frontend_feature_flag(:issue_assignees_widget, @project)
push_frontend_feature_flag(:realtime_labels, project)
push_frontend_feature_flag(:refactor_security_extension, @project)
push_frontend_feature_flag(:refactor_code_quality_inline_findings, project)
- push_frontend_feature_flag(:mr_attention_requests, current_user)
push_frontend_feature_flag(:moved_mr_sidebar, project)
push_frontend_feature_flag(:paginated_mr_discussions, project)
push_frontend_feature_flag(:mr_review_submit_comment, project)
@@ -367,7 +364,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def rebase
- @merge_request.rebase_async(current_user.id)
+ @merge_request.rebase_async(current_user.id, skip_ci: Gitlab::Utils.to_boolean(merge_params[:skip_ci], default: false))
head :ok
rescue MergeRequest::RebaseLockTimeout => e
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 744e45a0f9c..cfb67b7b4ff 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -92,8 +92,8 @@ class Projects::MilestonesController < Projects::ApplicationController
render json: { url: project_milestones_path(project) }
end
end
- rescue Milestones::PromoteService::PromoteMilestoneError => error
- redirect_to milestone, alert: error.message
+ rescue Milestones::PromoteService::PromoteMilestoneError => e
+ redirect_to milestone, alert: e.message
end
def flash_notice_for(milestone, group)
diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb
index bcb6b574d5a..acbd26cbdf6 100644
--- a/app/controllers/projects/mirrors_controller.rb
+++ b/app/controllers/projects/mirrors_controller.rb
@@ -58,8 +58,8 @@ class Projects::MirrorsController < Projects::ApplicationController
else
render json: lookup
end
- rescue ArgumentError => err
- render json: { message: err.message }, status: :bad_request
+ rescue ArgumentError => e
+ render json: { message: e.message }, status: :bad_request
end
private
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
index 4bd33882eee..0e990b64cd6 100644
--- a/app/controllers/projects/pages_controller.rb
+++ b/app/controllers/projects/pages_controller.rb
@@ -10,11 +10,29 @@ class Projects::PagesController < Projects::ApplicationController
feature_category :pages
- # rubocop: disable CodeReuse/ActiveRecord
+ def new
+ @pipeline_wizard_data = {
+ project_path: @project.full_path,
+ default_branch: @project.repository.root_ref,
+ redirect_to_when_done: project_pages_path(@project)
+ }
+ end
+
def show
+ unless @project.pages_enabled?
+ render :disabled
+ return
+ end
+
+ if @project.pages_show_onboarding?
+ redirect_to action: 'new'
+ return
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
@domains = @project.pages_domains.order(:domain).present(current_user: current_user)
+ # rubocop: enable CodeReuse/ActiveRecord
end
- # rubocop: enable CodeReuse/ActiveRecord
def destroy
::Pages::DeleteService.new(@project, current_user).execute
diff --git a/app/controllers/projects/pipelines/stages_controller.rb b/app/controllers/projects/pipelines/stages_controller.rb
index 0447bbf29e7..c94d468cf2e 100644
--- a/app/controllers/projects/pipelines/stages_controller.rb
+++ b/app/controllers/projects/pipelines/stages_controller.rb
@@ -4,6 +4,7 @@ module Projects
module Pipelines
class StagesController < Projects::Pipelines::ApplicationController
before_action :authorize_update_pipeline!
+ before_action :stage, only: [:play_manual]
urgency :low, [
:play_manual
@@ -26,7 +27,7 @@ module Projects
private
def stage
- @pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name])
+ @stage ||= pipeline.stage(params[:stage_name]).presence || render_404
end
end
end
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index 9fc75fff807..33ce37ef4fb 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -35,8 +35,8 @@ class Projects::RepositoriesController < Projects::ApplicationController
return if archive_not_modified?
send_git_archive @repository, **repo_params
- rescue StandardError => ex
- logger.error("#{self.class.name}: #{ex}")
+ rescue StandardError => e
+ logger.error("#{self.class.name}: #{e}")
git_not_found!
end
diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb
index 34ce8df202b..5946c43b134 100644
--- a/app/controllers/projects/runner_projects_controller.rb
+++ b/app/controllers/projects/runner_projects_controller.rb
@@ -15,7 +15,7 @@ class Projects::RunnerProjectsController < Projects::ApplicationController
path = project_runners_path(project)
- if ::Ci::Runners::AssignRunnerService.new(@runner, @project, current_user).execute
+ if ::Ci::Runners::AssignRunnerService.new(@runner, @project, current_user).execute.success?
redirect_to path, notice: s_('Runners|Runner assigned to project.')
else
assign_to_messages = @runner.errors.messages[:assign_to]
diff --git a/app/controllers/projects/settings/integration_hook_logs_controller.rb b/app/controllers/projects/settings/integration_hook_logs_controller.rb
index b3b5a292d42..1e42fbce4c4 100644
--- a/app/controllers/projects/settings/integration_hook_logs_controller.rb
+++ b/app/controllers/projects/settings/integration_hook_logs_controller.rb
@@ -20,7 +20,7 @@ module Projects
override :hook
def hook
- @hook ||= integration.service_hook || not_found
+ @hook ||= integration.try(:service_hook) || not_found
end
end
end
diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb
index cee9e9feb7b..03ef434456f 100644
--- a/app/controllers/projects/settings/integrations_controller.rb
+++ b/app/controllers/projects/settings/integrations_controller.rb
@@ -122,7 +122,7 @@ module Projects
end
def web_hook_logs
- return unless integration.service_hook.present?
+ return unless integration.try(:service_hook).present?
@web_hook_logs ||= integration.service_hook.web_hook_logs.recent.page(params[:page])
end
diff --git a/app/controllers/projects/settings/packages_and_registries_controller.rb b/app/controllers/projects/settings/packages_and_registries_controller.rb
index d3c08bef808..76c9cead360 100644
--- a/app/controllers/projects/settings/packages_and_registries_controller.rb
+++ b/app/controllers/projects/settings/packages_and_registries_controller.rb
@@ -14,11 +14,22 @@ module Projects
def show
end
+ def cleanup_tags
+ registry_settings_enabled!
+
+ @hide_search_settings = true
+ end
+
private
def packages_and_registries_settings_enabled!
render_404 unless can?(current_user, :view_package_registry_project_settings, project)
end
+
+ def registry_settings_enabled!
+ render_404 unless Gitlab.config.registry.enabled &&
+ can?(current_user, :admin_container_image, project)
+ end
end
end
end
diff --git a/app/controllers/projects/tags/releases_controller.rb b/app/controllers/projects/tags/releases_controller.rb
deleted file mode 100644
index adeadf2133e..00000000000
--- a/app/controllers/projects/tags/releases_controller.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-# TODO: remove this file together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
-# also delete view/routes
-class Projects::Tags::ReleasesController < Projects::ApplicationController
- # Authorize
- before_action :require_non_empty_project
- before_action :authorize_download_code!
- before_action :authorize_push_code!
- before_action :tag
- before_action :release
-
- feature_category :release_evidence
- urgency :low
-
- def edit
- end
-
- def update
- release.update(release_params) if release.persisted? || release_params[:description].present?
-
- redirect_to project_tag_path(@project, tag.name)
- end
-
- private
-
- def tag
- @tag ||= @repository.find_tag(params[:tag_id])
- end
-
- def release
- @release ||= Releases::CreateService.new(project, current_user, tag: @tag.name)
- .find_or_build_release
- end
-
- def release_params
- params.require(:release).permit(:description)
- end
-end
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index ce51cbb6677..fea2689db14 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -19,6 +19,7 @@ class Projects::TreeController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:lazy_load_commits, @project)
push_frontend_feature_flag(:highlight_js, @project)
+ push_frontend_feature_flag(:file_line_blame, @project)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb
index e7bccf5a243..a8f062bd7c1 100644
--- a/app/controllers/projects/variables_controller.rb
+++ b/app/controllers/projects/variables_controller.rb
@@ -43,7 +43,7 @@ class Projects::VariablesController < Projects::ApplicationController
end
def variables_params
- params.permit(variables_attributes: [*variable_params_attributes])
+ params.permit(variables_attributes: Array(variable_params_attributes))
end
def variable_params_attributes
diff --git a/app/controllers/projects/work_items_controller.rb b/app/controllers/projects/work_items_controller.rb
index ba23af41bb0..b794785f285 100644
--- a/app/controllers/projects/work_items_controller.rb
+++ b/app/controllers/projects/work_items_controller.rb
@@ -3,7 +3,7 @@
class Projects::WorkItemsController < Projects::ApplicationController
before_action do
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
- push_frontend_feature_flag(:work_items_mvc_2)
+ 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)
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 37e472050a0..8a6bcb4b3fc 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -37,17 +37,18 @@ class ProjectsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:lazy_load_commits, @project)
push_frontend_feature_flag(:highlight_js, @project)
+ push_frontend_feature_flag(:file_line_blame, @project)
push_frontend_feature_flag(:increase_page_size_exponentially, @project)
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
push_licensed_feature(:security_orchestration_policies) if @project.present? && @project.licensed_feature_available?(:security_orchestration_policies)
push_force_frontend_feature_flag(:work_items, @project&.work_items_feature_flag_enabled?)
- push_frontend_feature_flag(:work_items_mvc_2)
+ push_force_frontend_feature_flag(:work_items_mvc_2, @project&.work_items_mvc_2_feature_flag_enabled?)
push_frontend_feature_flag(:package_registry_access_level)
push_frontend_feature_flag(:work_items_hierarchy, @project)
end
before_action only: :edit do
- push_frontend_feature_flag(:enforce_auth_checks_on_uploads, @project)
+ push_frontend_feature_flag(:split_operations_visibility_permissions, @project)
end
layout :determine_layout
@@ -197,8 +198,8 @@ class ProjectsController < Projects::ApplicationController
flash[:notice] = _("Project '%{project_name}' is in the process of being deleted.") % { project_name: @project.full_name }
redirect_to dashboard_projects_path, status: :found
- rescue Projects::DestroyService::DestroyError => ex
- redirect_to edit_project_path(@project), status: :found, alert: ex.message
+ rescue Projects::DestroyService::DestroyError => e
+ redirect_to edit_project_path(@project), status: :found, alert: e.message
end
def new_issuable_address
@@ -231,10 +232,10 @@ class ProjectsController < Projects::ApplicationController
project_path(@project),
notice: _("Housekeeping successfully started")
)
- rescue ::Repositories::HousekeepingService::LeaseTaken => ex
+ rescue ::Repositories::HousekeepingService::LeaseTaken => e
redirect_to(
edit_project_path(@project, anchor: 'js-project-advanced-settings'),
- alert: ex.to_s
+ alert: e.to_s
)
end
@@ -245,10 +246,10 @@ class ProjectsController < Projects::ApplicationController
edit_project_path(@project, anchor: 'js-export-project'),
notice: _("Project export started. A download link will be sent by email and made available on this page.")
)
- rescue Project::ExportLimitExceeded => ex
+ rescue Project::ExportLimitExceeded => e
redirect_to(
edit_project_path(@project, anchor: 'js-export-project'),
- alert: ex.to_s
+ alert: e.to_s
)
end
@@ -420,10 +421,19 @@ class ProjectsController < Projects::ApplicationController
pages_access_level
metrics_dashboard_access_level
analytics_access_level
- operations_access_level
security_and_compliance_access_level
container_registry_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
+ ]
+ else
+ %i[operations_access_level]
+ end
end
def project_setting_attributes
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index bb16c2d2098..33d2c482795 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -21,6 +21,7 @@ class RegistrationsController < Devise::RegistrationsController
before_action only: [:new] do
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
+ push_frontend_feature_flag(:trial_email_validation, type: :development)
end
feature_category :authentication_and_authorization
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index 24520a187e3..8d7ba3e38c0 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -107,7 +107,7 @@ module Repositories
render plain: "HTTP Basic: Access denied\n" \
"You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.\n" \
"You can generate one at #{profile_personal_access_tokens_url}",
- status: :unauthorized
+ status: :unauthorized
end
def repository
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 7deda473b9d..83973d07a17 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -173,12 +173,12 @@ module Repositories
LfsObjectsProject.link_to_project!(lfs_object, project)
Gitlab::AppJsonLogger.info(message: "LFS object auto-linked to forked project",
- lfs_object_oid: lfs_object.oid,
- lfs_object_size: lfs_object.size,
- source_project_id: project.fork_source.id,
- source_project_path: project.fork_source.full_path,
- target_project_id: project.project_id,
- target_project_path: project.full_path)
+ lfs_object_oid: lfs_object.oid,
+ lfs_object_size: lfs_object.size,
+ source_project_id: project.fork_source.id,
+ source_project_path: project.fork_source.full_path,
+ target_project_id: project.project_id,
+ target_project_path: project.full_path)
end
end
end
diff --git a/app/controllers/repositories/lfs_locks_api_controller.rb b/app/controllers/repositories/lfs_locks_api_controller.rb
index 1d091a5bfcd..f36126d67ff 100644
--- a/app/controllers/repositories/lfs_locks_api_controller.rb
+++ b/app/controllers/repositories/lfs_locks_api_controller.rb
@@ -38,8 +38,8 @@ module Repositories
def render_json(data, process = true)
render json: build_payload(data, process),
- content_type: LfsRequest::CONTENT_TYPE,
- status: @result[:http_status]
+ content_type: LfsRequest::CONTENT_TYPE,
+ status: @result[:http_status]
end
def build_payload(data, process)
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 7a7e63f5fc4..5843e13c7cd 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -7,10 +7,14 @@ class SearchController < ApplicationController
include ProductAnalyticsTracking
include SearchRateLimitable
- RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete].freeze
+ RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete, :aggregations].freeze
track_event :show, name: 'i_search_total', destinations: [:redis_hll, :snowplow]
+ def self.search_rate_limited_endpoints
+ %i[show count autocomplete]
+ end
+
around_action :allow_gitaly_ref_name_caching
before_action :block_anonymous_global_searches, :check_scope_global_search_enabled, except: :opensearch
@@ -19,7 +23,7 @@ class SearchController < ApplicationController
search_term_present = params[:search].present? || params[:term].present?
search_term_present && !params[:project_id].present?
end
- before_action :check_search_rate_limit!, only: [:show, :count, :autocomplete]
+ before_action :check_search_rate_limit!, only: search_rate_limited_endpoints
rescue_from ActiveRecord::QueryCanceled, with: :render_timeout
@@ -32,8 +36,6 @@ class SearchController < ApplicationController
@project = search_service.project
@group = search_service.group
- return if params[:search].blank?
-
return unless search_term_valid?
return if check_single_commit_result?
@@ -53,7 +55,6 @@ class SearchController < ApplicationController
@search_results = @search_service.search_results
@search_objects = @search_service.search_objects
@search_highlight = @search_service.search_highlight
- @aggregations = @search_service.search_aggregations
end
increment_search_counters
@@ -83,8 +84,9 @@ class SearchController < ApplicationController
@project = search_service.project
@ref = params[:project_ref] if params[:project_ref].present?
+ @filter = params[:filter]
- render json: search_autocomplete_opts(term).to_json
+ render json: search_autocomplete_opts(term, filter: @filter).to_json
end
def opensearch
@@ -98,6 +100,8 @@ class SearchController < ApplicationController
end
def search_term_valid?
+ return false if params[:search].blank?
+
unless search_service.valid_query_length?
flash[:alert] = t('errors.messages.search_chars_too_long', count: Gitlab::Search::Params::SEARCH_CHAR_LIMIT)
return false
@@ -150,6 +154,7 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.filters.state'] = params[:state]
payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results]
payload[:metadata]['meta.search.project_ids'] = params[:project_ids]
+ payload[:metadata]['meta.search.filters.language'] = params[:language]
payload[:metadata]['meta.search.type'] = @search_type if @search_type.present?
payload[:metadata]['meta.search.level'] = @search_level if @search_level.present?
payload[:metadata][:global_search_duration_s] = @global_search_duration_s if @global_search_duration_s.present?
@@ -205,7 +210,7 @@ class SearchController < ApplicationController
case action_name.to_sym
when :count
render json: {}, status: :request_timeout
- when :autocomplete
+ when :autocomplete, :aggregations
render json: [], status: :request_timeout
else
render status: :request_timeout
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 6195d152f00..fe3b8d9b8b4 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -215,11 +215,11 @@ class SessionsController < Devise::SessionsController
def find_user
strong_memoize(:find_user) do
if session[:otp_user_id] && user_params[:login]
- User.by_id_and_login(session[:otp_user_id], user_params[:login]).first
+ User.by_login(user_params[:login]).find_by_id(session[:otp_user_id])
elsif session[:otp_user_id]
User.find(session[:otp_user_id])
elsif user_params[:login]
- User.by_login(user_params[:login])
+ User.find_by_login(user_params[:login])
end
end
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 97bbb96eae6..09419a4589d 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -7,13 +7,13 @@ class UploadsController < ApplicationController
UnknownUploadModelError = Class.new(StandardError)
MODEL_CLASSES = {
- "user" => User,
- "project" => Project,
- "note" => Note,
- "group" => Group,
- "appearance" => Appearance,
+ "user" => User,
+ "project" => Project,
+ "note" => Note,
+ "group" => Group,
+ "appearance" => Appearance,
"personal_snippet" => PersonalSnippet,
- "projects/topic" => Projects::Topic,
+ "projects/topic" => Projects::Topic,
'alert_management_metric_image' => ::AlertManagement::MetricImage,
nil => PersonalSnippet
}.freeze
diff --git a/app/controllers/users/namespace_callouts_controller.rb b/app/controllers/users/namespace_callouts_controller.rb
new file mode 100644
index 00000000000..d4876382dfe
--- /dev/null
+++ b/app/controllers/users/namespace_callouts_controller.rb
@@ -0,0 +1,17 @@
+# 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/project_callouts_controller.rb b/app/controllers/users/project_callouts_controller.rb
new file mode 100644
index 00000000000..64d89630021
--- /dev/null
+++ b/app/controllers/users/project_callouts_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Users
+ class ProjectCalloutsController < Users::CalloutsController
+ private
+
+ def callout
+ Users::DismissProjectCalloutService.new(
+ container: nil, current_user: current_user, params: callout_params
+ ).execute
+ end
+
+ def callout_params
+ params.permit(:project_id).merge(feature_name: feature_name)
+ end
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index eaf08cd421b..3c1a3534912 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -155,7 +155,11 @@ class UsersController < ApplicationController
end
def calendar_activities
- @calendar_date = Date.parse(params[:date]) rescue Date.today
+ @calendar_date = begin
+ Date.parse(params[:date])
+ rescue StandardError
+ Date.today
+ end
@events = contributions_calendar.events_by_date(@calendar_date).map(&:present)
render 'calendar_activities', layout: false
diff --git a/app/events/groups/group_deleted_event.rb b/app/events/groups/group_deleted_event.rb
new file mode 100644
index 00000000000..d89cce17be9
--- /dev/null
+++ b/app/events/groups/group_deleted_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Groups
+ class GroupDeletedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'group_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[group_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/groups/group_path_changed_event.rb b/app/events/groups/group_path_changed_event.rb
new file mode 100644
index 00000000000..e8d9b733a0a
--- /dev/null
+++ b/app/events/groups/group_path_changed_event.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Groups
+ class GroupPathChangedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'group_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' },
+ 'old_path' => { 'type' => 'string' },
+ 'new_path' => { 'type' => 'string' }
+ },
+ 'required' => %w[group_id root_namespace_id old_path new_path]
+ }
+ end
+ end
+end
diff --git a/app/events/groups/group_transfered_event.rb b/app/events/groups/group_transfered_event.rb
new file mode 100644
index 00000000000..da573892108
--- /dev/null
+++ b/app/events/groups/group_transfered_event.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Groups
+ class GroupTransferedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'group_id' => { 'type' => 'integer' },
+ 'old_root_namespace_id' => { 'type' => 'integer' },
+ 'new_root_namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[group_id old_root_namespace_id new_root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/merge_requests/approved_event.rb b/app/events/merge_requests/approved_event.rb
new file mode 100644
index 00000000000..c68a002dcc3
--- /dev/null
+++ b/app/events/merge_requests/approved_event.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ApprovedEvent < Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'required' => %w[
+ current_user_id
+ merge_request_id
+ ],
+ 'properties' => {
+ 'current_user_id' => { 'type' => 'integer' },
+ 'merge_request_id' => { 'type' => 'integer' }
+ }
+ }
+ end
+ end
+end
diff --git a/app/events/projects/project_archived_event.rb b/app/events/projects/project_archived_event.rb
new file mode 100644
index 00000000000..9ac83fd791b
--- /dev/null
+++ b/app/events/projects/project_archived_event.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Projects
+ class ProjectArchivedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'namespace_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[project_id namespace_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/events/projects/project_transfered_event.rb b/app/events/projects/project_transfered_event.rb
new file mode 100644
index 00000000000..14cc53daabb
--- /dev/null
+++ b/app/events/projects/project_transfered_event.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Projects
+ class ProjectTransferedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'project_id' => { 'type' => 'integer' },
+ 'old_namespace_id' => { 'type' => 'integer' },
+ 'old_root_namespace_id' => { 'type' => 'integer' },
+ 'new_namespace_id' => { 'type' => 'integer' },
+ 'new_root_namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[
+ project_id
+ old_namespace_id
+ old_root_namespace_id
+ new_namespace_id
+ new_root_namespace_id
+ ]
+ }
+ end
+ end
+end
diff --git a/app/experiments/security_reports_mr_widget_prompt_experiment.rb b/app/experiments/security_reports_mr_widget_prompt_experiment.rb
index 51b81be672d..1bf3e15ba3b 100644
--- a/app/experiments/security_reports_mr_widget_prompt_experiment.rb
+++ b/app/experiments/security_reports_mr_widget_prompt_experiment.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class SecurityReportsMrWidgetPromptExperiment < ApplicationExperiment
- control { }
- candidate { }
+ control {}
+ candidate {}
def publish(_result = nil)
super
diff --git a/app/experiments/video_tutorials_continuous_onboarding_experiment.rb b/app/experiments/video_tutorials_continuous_onboarding_experiment.rb
index 3cb676b25f2..2c5790f83d1 100644
--- a/app/experiments/video_tutorials_continuous_onboarding_experiment.rb
+++ b/app/experiments/video_tutorials_continuous_onboarding_experiment.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
class VideoTutorialsContinuousOnboardingExperiment < ApplicationExperiment
- control { }
- candidate { }
+ control {}
+ candidate {}
end
diff --git a/app/finders/autocomplete/deploy_keys_with_write_access_finder.rb b/app/finders/autocomplete/deploy_keys_with_write_access_finder.rb
new file mode 100644
index 00000000000..a123a0dc4f0
--- /dev/null
+++ b/app/finders/autocomplete/deploy_keys_with_write_access_finder.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Autocomplete
+ # Finder for retrieving deploy keys to use for autocomplete data sources.
+ class DeployKeysWithWriteAccessFinder
+ attr_reader :current_user, :project
+
+ def initialize(current_user, project)
+ @current_user = current_user
+ @project = project
+ end
+
+ def execute
+ return DeployKey.none if project.nil?
+
+ raise Gitlab::Access::AccessDeniedError unless current_user.can?(:admin_project, project)
+
+ project.deploy_keys.merge(DeployKeysProject.with_write_access)
+ end
+ end
+end
diff --git a/app/finders/ci/daily_build_group_report_results_finder.rb b/app/finders/ci/daily_build_group_report_results_finder.rb
index 33aefe29392..b93b7dbe0c5 100644
--- a/app/finders/ci/daily_build_group_report_results_finder.rb
+++ b/app/finders/ci/daily_build_group_report_results_finder.rb
@@ -82,14 +82,20 @@ module Ci
end
def start_date
- start_date = Date.strptime(params[:start_date], DATE_FORMAT_ALLOWED) rescue REPORT_WINDOW.ago.to_date
+ start_date = begin
+ Date.strptime(params[:start_date], DATE_FORMAT_ALLOWED)
+ rescue StandardError
+ REPORT_WINDOW.ago.to_date
+ end
# The start_date cannot be older than `end_date - 90 days`
[start_date, end_date - REPORT_WINDOW].max
end
def end_date
- Date.strptime(params[:end_date], DATE_FORMAT_ALLOWED) rescue Date.current
+ Date.strptime(params[:end_date], DATE_FORMAT_ALLOWED)
+ rescue StandardError
+ Date.current
end
end
end
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 4f9244d9825..774947a35b7 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -69,10 +69,15 @@ module Ci
end
def filter_by_upgrade_status!
- return unless @params.key?(:upgrade_status)
- return unless Ci::RunnerVersion.statuses.key?(@params[:upgrade_status])
+ upgrade_status = @params[:upgrade_status]
- @runners = @runners.with_upgrade_status(@params[:upgrade_status])
+ return unless upgrade_status
+
+ unless Ci::RunnerVersion.statuses.key?(upgrade_status)
+ raise ArgumentError, "Invalid upgrade status value '#{upgrade_status}'"
+ end
+
+ @runners = @runners.with_upgrade_status(upgrade_status)
end
def filter_by_runner_type!
diff --git a/app/finders/crm/contacts_finder.rb b/app/finders/crm/contacts_finder.rb
index 29f3d6f0f16..58ec4cf8a47 100644
--- a/app/finders/crm/contacts_finder.rb
+++ b/app/finders/crm/contacts_finder.rb
@@ -16,6 +16,11 @@ module Crm
attr_reader :params, :current_user
+ def self.counts_by_state(current_user, params = {})
+ params = params.merge(sort: nil)
+ new(current_user, params).execute.counts_by_state
+ end
+
def initialize(current_user, params = {})
@current_user = current_user
@params = params
@@ -28,11 +33,25 @@ module Crm
contacts = by_ids(contacts)
contacts = by_state(contacts)
contacts = by_search(contacts)
- contacts.sort_by_name
+ sort_contacts(contacts)
end
private
+ def sort_contacts(contacts)
+ return contacts.sort_by_name unless @params.key?(:sort)
+ return contacts if @params[:sort].nil?
+
+ field = @params[:sort][:field]
+ direction = @params[:sort][:direction]
+
+ if field == 'organization'
+ contacts.sort_by_organization(direction)
+ else
+ contacts.sort_by_field(field, direction)
+ end
+ end
+
def root_group
strong_memoize(:root_group) do
group = params[:group]&.root_ancestor
diff --git a/app/finders/fork_targets_finder.rb b/app/finders/fork_targets_finder.rb
index 0b5dfb16572..e129fde3748 100644
--- a/app/finders/fork_targets_finder.rb
+++ b/app/finders/fork_targets_finder.rb
@@ -6,17 +6,39 @@ class ForkTargetsFinder
@user = user
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute(options = {})
- return ::Namespace.where(id: user.forkable_namespaces).sort_by_type unless options[:only_groups]
+ return previous_execute(options) unless Feature.enabled?(:searchable_fork_targets)
- ::Group.where(id: user.manageable_groups(include_groups_with_developer_maintainer_access: true))
+ items = fork_targets(options)
+
+ by_search(items, options)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
attr_reader :project, :user
+
+ def by_search(items, options)
+ return items if options[:search].blank?
+
+ items.search(options[:search])
+ end
+
+ def fork_targets(options)
+ if options[:only_groups]
+ user.manageable_groups(include_groups_with_developer_maintainer_access: true)
+ else
+ user.forkable_namespaces.sort_by_type
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def previous_execute(options = {})
+ return ::Namespace.where(id: user.forkable_namespaces).sort_by_type unless options[:only_groups]
+
+ ::Group.where(id: user.manageable_groups(include_groups_with_developer_maintainer_access: true))
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
ForkTargetsFinder.prepend_mod_with('ForkTargetsFinder')
diff --git a/app/finders/groups/accepting_project_transfers_finder.rb b/app/finders/groups/accepting_project_transfers_finder.rb
new file mode 100644
index 00000000000..09d3c430641
--- /dev/null
+++ b/app/finders/groups/accepting_project_transfers_finder.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Groups
+ class AcceptingProjectTransfersFinder
+ def initialize(current_user)
+ @current_user = current_user
+ end
+
+ def execute
+ if Feature.disabled?(:include_groups_from_group_shares_in_project_transfer_locations)
+ return current_user.manageable_groups
+ end
+
+ groups_accepting_project_transfers =
+ [
+ current_user.manageable_groups,
+ managable_groups_originating_from_group_shares
+ ]
+
+ groups = ::Group.from_union(groups_accepting_project_transfers)
+
+ groups.project_creation_allowed
+ end
+
+ private
+
+ attr_reader :current_user
+
+ def managable_groups_originating_from_group_shares
+ GroupGroupLink
+ .with_owner_or_maintainer_access
+ .groups_accessible_via(
+ groups_that_user_has_owner_or_maintainer_access_via_direct_membership
+ .select(:id)
+ )
+ end
+
+ def groups_that_user_has_owner_or_maintainer_access_via_direct_membership
+ # Only maintainers or above in a group has access to transfer projects to that group
+ current_user.owned_or_maintainers_groups
+ end
+ end
+end
diff --git a/app/finders/groups/user_groups_finder.rb b/app/finders/groups/user_groups_finder.rb
index 90367638dcf..bda8b7cc1e0 100644
--- a/app/finders/groups/user_groups_finder.rb
+++ b/app/finders/groups/user_groups_finder.rb
@@ -41,14 +41,14 @@ module Groups
def by_search(items)
return items if params[:search].blank?
- items.search(params[:search])
+ items.search(params[:search], include_parents: true)
end
def by_permission_scope
if permission_scope_create_projects?
target_user.manageable_groups(include_groups_with_developer_maintainer_access: true)
elsif permission_scope_transfer_projects?
- target_user.manageable_groups(include_groups_with_developer_maintainer_access: false)
+ Groups::AcceptingProjectTransfersFinder.new(target_user).execute # rubocop: disable CodeReuse/Finder
else
target_user.groups
end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 47b2a460e6f..1088d53c9a0 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -46,7 +46,8 @@ class IssuableFinder
requires_cross_project_access unless: -> { params.project? }
- FULL_TEXT_SEARCH_TERM_REGEX = /\A[\p{ASCII}|\p{Latin}]+\z/.freeze
+ FULL_TEXT_SEARCH_TERM_PATTERN = '[\u0000-\u218F]*'
+ FULL_TEXT_SEARCH_TERM_REGEX = /\A#{FULL_TEXT_SEARCH_TERM_PATTERN}\z/.freeze
NEGATABLE_PARAMS_HELPER_KEYS = %i[project_id scope status include_subgroups].freeze
attr_accessor :current_user, :params
diff --git a/app/finders/projects/topics_finder.rb b/app/finders/projects/topics_finder.rb
index c26b166a786..fb0a77db548 100644
--- a/app/finders/projects/topics_finder.rb
+++ b/app/finders/projects/topics_finder.rb
@@ -13,6 +13,7 @@ module Projects
def execute
topics = Projects::Topic.order_by_non_private_projects_count
+ topics = by_without_projects(topics)
by_search(topics)
end
@@ -25,5 +26,11 @@ module Projects
topics.search(params[:search]).reorder_by_similarity(params[:search])
end
+
+ def by_without_projects(topics)
+ return topics unless params[:without_projects]
+
+ topics.without_assigned_projects
+ end
end
end
diff --git a/app/finders/releases/group_releases_finder.rb b/app/finders/releases/group_releases_finder.rb
index 8b1b0c552fd..08530f63ea6 100644
--- a/app/finders/releases/group_releases_finder.rb
+++ b/app/finders/releases/group_releases_finder.rb
@@ -32,7 +32,7 @@ module Releases
def get_releases
Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
scope: releases_scope,
- array_scope: Project.for_group_and_its_subgroups(parent).select(:id),
+ array_scope: Project.for_group_and_its_subgroups(parent).select(:id),
array_mapping_scope: -> (project_id_expression) { Release.where(Release.arel_table[:project_id].eq(project_id_expression)) },
finder_query: -> (order_by, id_expression) { Release.where(Release.arel_table[:id].eq(id_expression)) }
)
diff --git a/app/finders/repositories/changelog_tag_finder.rb b/app/finders/repositories/changelog_tag_finder.rb
index 3c110e6c65d..7dd7404730f 100644
--- a/app/finders/repositories/changelog_tag_finder.rb
+++ b/app/finders/repositories/changelog_tag_finder.rb
@@ -37,14 +37,14 @@ module Repositories
begin
regex = Gitlab::UntrustedRegexp.new(@regex)
- rescue RegexpError => ex
+ rescue RegexpError => e
# The error messages produced by default are not very helpful, so we
# raise a better one here. We raise the specific error here so its
# message is displayed in the API (where we catch this specific
# error).
raise(
Gitlab::Changelog::Error,
- "The regular expression to use for finding the previous tag for a version is invalid: #{ex.message}"
+ "The regular expression to use for finding the previous tag for a version is invalid: #{e.message}"
)
end
diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb
index 16bba62f766..52b1fff4883 100644
--- a/app/finders/tags_finder.rb
+++ b/app/finders/tags_finder.rb
@@ -2,7 +2,7 @@
class TagsFinder < GitRefsFinder
def execute(gitaly_pagination: false)
- tags = if gitaly_pagination
+ tags = if gitaly_pagination && search.blank?
repository.tags_sorted_by(sort, pagination_params)
else
repository.tags_sorted_by(sort)
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index b399f0490ee..c0e063a34d5 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -53,6 +53,7 @@ class GitlabSchema < GraphQL::Schema
def get_type(type_name, context = GraphQL::Query::NullContext)
type_name = Gitlab::GlobalId::Deprecations.apply_to_graphql_name(type_name)
+ type_name = Gitlab::Graphql::TypeNameDeprecations.apply_to_graphql_name(type_name)
super(type_name, context)
end
@@ -163,6 +164,7 @@ class GitlabSchema < GraphQL::Schema
def get_type(type_name)
type_name = Gitlab::GlobalId::Deprecations.apply_to_graphql_name(type_name)
+ type_name = Gitlab::Graphql::TypeNameDeprecations.apply_to_graphql_name(type_name)
super(type_name)
end
diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb
index 342cff83e90..b39875b83a9 100644
--- a/app/graphql/graphql_triggers.rb
+++ b/app/graphql/graphql_triggers.rb
@@ -16,4 +16,8 @@ module GraphqlTriggers
def self.issuable_labels_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableLabelsUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+
+ def self.issuable_dates_updated(issuable)
+ GitlabSchema.subscriptions.trigger('issuableDatesUpdated', { issuable_id: issuable.to_gid }, issuable)
+ end
end
diff --git a/app/graphql/mutations/award_emojis/toggle.rb b/app/graphql/mutations/award_emojis/toggle.rb
index 5da2731d562..a419a8df64e 100644
--- a/app/graphql/mutations/award_emojis/toggle.rb
+++ b/app/graphql/mutations/award_emojis/toggle.rb
@@ -5,9 +5,10 @@ module Mutations
class Toggle < Base
graphql_name 'AwardEmojiToggle'
- field :toggled_on, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the status of the emoji. ' \
- 'True if the toggle awarded the emoji, and false if the toggle removed the emoji.'
+ field :toggled_on, GraphQL::Types::Boolean,
+ null: false,
+ description: 'Indicates the status of the emoji. ' \
+ 'True if the toggle awarded the emoji, and false if the toggle removed the emoji.'
def resolve(args)
awardable = authorized_find!(id: args[:awardable_id])
diff --git a/app/graphql/mutations/ci/job/retry.rb b/app/graphql/mutations/ci/job/retry.rb
index 50e9c51c9e7..bfb9b902cc5 100644
--- a/app/graphql/mutations/ci/job/retry.rb
+++ b/app/graphql/mutations/ci/job/retry.rb
@@ -11,13 +11,20 @@ module Mutations
null: true,
description: 'Job after the mutation.'
+ argument :variables, [::Types::Ci::VariableInputType],
+ required: false,
+ default_value: [],
+ replace_null_with_default: true,
+ description: 'Variables to use when retrying a manual job.'
+
authorize :update_build
- def resolve(id:)
+ def resolve(id:, variables:)
job = authorized_find!(id: id)
project = job.project
+ variables = variables.map(&:to_h)
- response = ::Ci::RetryJobService.new(project, current_user).execute(job)
+ response = ::Ci::RetryJobService.new(project, current_user).execute(job, variables: variables)
if response.success?
{
diff --git a/app/graphql/mutations/ci/pipeline/cancel.rb b/app/graphql/mutations/ci/pipeline/cancel.rb
index 3ec6eee9f54..c52e3b4f4b8 100644
--- a/app/graphql/mutations/ci/pipeline/cancel.rb
+++ b/app/graphql/mutations/ci/pipeline/cancel.rb
@@ -13,7 +13,6 @@ module Mutations
if pipeline.cancelable?
pipeline.cancel_running
- pipeline.cancel
{ success: true, errors: [] }
else
diff --git a/app/graphql/mutations/ci/runner/bulk_delete.rb b/app/graphql/mutations/ci/runner/bulk_delete.rb
new file mode 100644
index 00000000000..4c1c2967799
--- /dev/null
+++ b/app/graphql/mutations/ci/runner/bulk_delete.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ module Runner
+ class BulkDelete < BaseMutation
+ graphql_name 'BulkRunnerDelete'
+
+ RunnerID = ::Types::GlobalIDType[::Ci::Runner]
+
+ argument :ids, [RunnerID],
+ required: false,
+ description: 'IDs of the runners to delete.'
+
+ field :deleted_count,
+ ::GraphQL::Types::Int,
+ null: true,
+ description: 'Number of records effectively deleted. ' \
+ 'Only present if operation was performed synchronously.'
+
+ field :deleted_ids,
+ [RunnerID],
+ null: true,
+ description: 'IDs of records effectively deleted. ' \
+ 'Only present if operation was performed synchronously.'
+
+ def resolve(**runner_attrs)
+ raise_resource_not_available_error! unless Ability.allowed?(current_user, :delete_runners)
+
+ if ids = runner_attrs[:ids]
+ runners = find_all_runners_by_ids(model_ids_of(ids))
+
+ result = ::Ci::Runners::BulkDeleteRunnersService.new(runners: runners).execute
+ result.payload.slice(:deleted_count, :deleted_ids).merge(errors: [])
+ else
+ { errors: [] }
+ end
+ end
+
+ private
+
+ def model_ids_of(ids)
+ ids.map do |gid|
+ gid.model_id.to_i
+ end.compact
+ end
+
+ def find_all_runners_by_ids(ids)
+ return ::Ci::Runner.none if ids.blank?
+
+ ::Ci::Runner.id_in(ids)
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/ci/runner/update.rb b/app/graphql/mutations/ci/runner/update.rb
index b6d8c20c40b..1c6cf6989bf 100644
--- a/app/graphql/mutations/ci/runner/update.rb
+++ b/app/graphql/mutations/ci/runner/update.rb
@@ -39,15 +39,17 @@ module Mutations
required: false,
description: 'Indicates the runner is not allowed to receive jobs.'
- argument :locked, GraphQL::Types::Boolean, required: false,
- description: 'Indicates the runner is locked.'
+ argument :locked, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Indicates the runner is locked.'
argument :run_untagged, GraphQL::Types::Boolean,
required: false,
description: 'Indicates the runner is able to run untagged jobs.'
- argument :tag_list, [GraphQL::Types::String], required: false,
- description: 'Tags associated with the runner.'
+ argument :tag_list, [GraphQL::Types::String],
+ required: false,
+ description: 'Tags associated with the runner.'
field :runner,
Types::Ci::RunnerType,
diff --git a/app/graphql/mutations/ci/runners_registration_token/reset.rb b/app/graphql/mutations/ci/runners_registration_token/reset.rb
index 8c49b682ab0..c9fe7ea47f0 100644
--- a/app/graphql/mutations/ci/runners_registration_token/reset.rb
+++ b/app/graphql/mutations/ci/runners_registration_token/reset.rb
@@ -49,7 +49,10 @@ module Mutations
end
def reset_token(scope)
- ::Ci::Runners::ResetRegistrationTokenService.new(scope, current_user).execute if scope
+ return unless scope
+
+ result = ::Ci::Runners::ResetRegistrationTokenService.new(scope, current_user).execute
+ result.payload[:new_registration_token] if result.success?
end
end
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 cbe1cfb4099..1f90f394521 100644
--- a/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
+++ b/app/graphql/mutations/concerns/mutations/work_items/update_arguments.rb
@@ -15,15 +15,21 @@ module Mutations
argument :title, GraphQL::Types::String,
required: false,
description: copy_field_description(Types::WorkItemType, :title)
+ argument :confidential, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Sets the work item confidentiality.'
argument :description_widget, ::Types::WorkItems::Widgets::DescriptionInputType,
required: false,
description: 'Input for description widget.'
- argument :weight_widget, ::Types::WorkItems::Widgets::WeightInputType,
+ argument :assignees_widget, ::Types::WorkItems::Widgets::AssigneesInputType,
required: false,
- description: 'Input for weight widget.'
+ description: 'Input for assignees widget.'
argument :hierarchy_widget, ::Types::WorkItems::Widgets::HierarchyUpdateInputType,
required: false,
description: 'Input for hierarchy widget.'
+ argument :start_and_due_date_widget, ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType,
+ required: false,
+ description: 'Input for start and due date widget.'
end
end
end
diff --git a/app/graphql/mutations/container_repositories/destroy.rb b/app/graphql/mutations/container_repositories/destroy.rb
index 1d8f7b22f88..2a45291be22 100644
--- a/app/graphql/mutations/container_repositories/destroy.rb
+++ b/app/graphql/mutations/container_repositories/destroy.rb
@@ -21,7 +21,9 @@ module Mutations
container_repository = authorized_find!(id: id)
container_repository.delete_scheduled!
+ # rubocop:disable CodeReuse/Worker
DeleteContainerRepositoryWorker.perform_async(current_user.id, container_repository.id)
+ # rubocop:enable CodeReuse/Worker
track_event(:delete_repository, :container)
{
diff --git a/app/graphql/mutations/design_management/move.rb b/app/graphql/mutations/design_management/move.rb
index b19d9b4ce61..cf7b7a7b99b 100644
--- a/app/graphql/mutations/design_management/move.rb
+++ b/app/graphql/mutations/design_management/move.rb
@@ -7,18 +7,21 @@ module Mutations
DesignID = ::Types::GlobalIDType[::DesignManagement::Design]
- argument :id, DesignID, required: true, as: :current_design,
- description: "ID of the design to move."
+ argument :id, DesignID,
+ required: true, as: :current_design,
+ description: "ID of the design to move."
- argument :previous, DesignID, required: false, as: :previous_design,
- description: "ID of the immediately preceding design."
+ argument :previous, DesignID,
+ required: false, as: :previous_design,
+ description: "ID of the immediately preceding design."
- argument :next, DesignID, required: false, as: :next_design,
- description: "ID of the immediately following design."
+ argument :next, DesignID,
+ required: false, as: :next_design,
+ description: "ID of the immediately following design."
field :design_collection, Types::DesignManagement::DesignCollectionType,
- null: true,
- description: "Current state of the collection."
+ null: true,
+ description: "Current state of the collection."
def resolve(**args)
service = ::DesignManagement::MoveDesignsService.new(current_user, parameters(**args))
diff --git a/app/graphql/mutations/issues/move.rb b/app/graphql/mutations/issues/move.rb
index fb22a2d891c..63bc9dabbf9 100644
--- a/app/graphql/mutations/issues/move.rb
+++ b/app/graphql/mutations/issues/move.rb
@@ -19,8 +19,8 @@ module Mutations
begin
moved_issue = ::Issues::MoveService.new(project: source_project, current_user: current_user).execute(issue, target_project)
- rescue ::Issues::MoveService::MoveError => error
- errors = error.message
+ rescue ::Issues::MoveService::MoveError => e
+ errors = e.message
end
{
diff --git a/app/graphql/mutations/issues/set_confidential.rb b/app/graphql/mutations/issues/set_confidential.rb
index abfd6fec0bd..b795d66c16f 100644
--- a/app/graphql/mutations/issues/set_confidential.rb
+++ b/app/graphql/mutations/issues/set_confidential.rb
@@ -24,7 +24,7 @@ module Mutations
check_spam_action_response!(issue)
{
- issue: issue,
+ issue: issue.reset,
errors: errors_on_object(issue)
}
end
diff --git a/app/graphql/mutations/issues/set_severity.rb b/app/graphql/mutations/issues/set_severity.rb
index 872a0e7b33d..4a24bfd18ef 100644
--- a/app/graphql/mutations/issues/set_severity.rb
+++ b/app/graphql/mutations/issues/set_severity.rb
@@ -5,8 +5,9 @@ module Mutations
class SetSeverity < Base
graphql_name 'IssueSetSeverity'
- argument :severity, Types::IssuableSeverityEnum, required: true,
- description: 'Set the incident severity level.'
+ argument :severity, Types::IssuableSeverityEnum,
+ required: true,
+ description: 'Set the incident severity level.'
authorize :admin_issue
diff --git a/app/graphql/mutations/merge_requests/remove_attention_request.rb b/app/graphql/mutations/merge_requests/remove_attention_request.rb
deleted file mode 100644
index 3b12b09528b..00000000000
--- a/app/graphql/mutations/merge_requests/remove_attention_request.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module MergeRequests
- class RemoveAttentionRequest < Base
- graphql_name 'MergeRequestRemoveAttentionRequest'
-
- argument :user_id, ::Types::GlobalIDType[::User],
- loads: Types::UserType,
- required: true,
- description: <<~DESC
- User ID of the user for attention request removal.
- DESC
-
- def resolve(project_path:, iid:, user:)
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled?
-
- merge_request = authorized_find!(project_path: project_path, iid: iid)
-
- result = ::MergeRequests::RemoveAttentionRequestedService.new(
- project: merge_request.project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- ).execute
-
- {
- merge_request: merge_request,
- errors: Array(result[:message])
- }
- end
-
- private
-
- def feature_enabled?
- current_user&.mr_attention_requests_enabled?
- end
- end
- end
-end
diff --git a/app/graphql/mutations/merge_requests/request_attention.rb b/app/graphql/mutations/merge_requests/request_attention.rb
deleted file mode 100644
index 5f5565285f6..00000000000
--- a/app/graphql/mutations/merge_requests/request_attention.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module MergeRequests
- class RequestAttention < Base
- graphql_name 'MergeRequestRequestAttention'
-
- argument :user_id, ::Types::GlobalIDType[::User],
- loads: Types::UserType,
- required: true,
- description: <<~DESC
- User ID of the user to request attention.
- DESC
-
- def resolve(project_path:, iid:, user:)
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless feature_enabled?
-
- merge_request = authorized_find!(project_path: project_path, iid: iid)
-
- result = ::MergeRequests::RequestAttentionService.new(
- project: merge_request.project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- ).execute
-
- {
- merge_request: merge_request,
- errors: Array(result[:message])
- }
- end
-
- private
-
- def feature_enabled?
- current_user&.mr_attention_requests_enabled?
- end
- end
- end
-end
diff --git a/app/graphql/mutations/merge_requests/set_reviewers.rb b/app/graphql/mutations/merge_requests/set_reviewers.rb
new file mode 100644
index 00000000000..8d3f8601597
--- /dev/null
+++ b/app/graphql/mutations/merge_requests/set_reviewers.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Mutations
+ module MergeRequests
+ class SetReviewers < Base
+ graphql_name 'MergeRequestSetReviewers'
+
+ argument :reviewer_usernames,
+ [GraphQL::Types::String],
+ required: true,
+ description: 'Usernames of reviewers to assign. Replaces existing reviewers by default.'
+
+ argument :operation_mode,
+ Types::MutationOperationModeEnum,
+ required: false,
+ default_value: Types::MutationOperationModeEnum.default_mode,
+ description: 'Operation to perform. Defaults to REPLACE.'
+
+ def resolve(project_path:, iid:, reviewer_usernames:, operation_mode:)
+ resource = authorized_find!(project_path: project_path, iid: iid)
+
+ ::MergeRequests::UpdateReviewersService.new(
+ project: resource.project,
+ current_user: current_user,
+ params: { reviewer_ids: reviewer_ids(resource, reviewer_usernames, operation_mode) }
+ ).execute(resource)
+
+ {
+ resource.class.name.underscore.to_sym => resource,
+ errors: errors_on_object(resource)
+ }
+ end
+
+ private
+
+ def reviewer_ids(resource, usernames, mode)
+ new_reviewers = UsersFinder.new(current_user, username: usernames).execute.to_a
+ new_reviewer_ids = user_ids(new_reviewers)
+
+ case mode
+ when 'REPLACE' then new_reviewer_ids
+ when 'APPEND' then user_ids(resource.reviewers) | new_reviewer_ids
+ when 'REMOVE' then user_ids(resource.reviewers) - new_reviewer_ids
+ end
+ end
+
+ def user_ids(users)
+ users.map(&:id)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb b/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
deleted file mode 100644
index 8913ca48531..00000000000
--- a/app/graphql/mutations/merge_requests/toggle_attention_requested.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module MergeRequests
- class ToggleAttentionRequested < Base
- graphql_name 'MergeRequestToggleAttentionRequested'
-
- argument :user_id, ::Types::GlobalIDType[::User],
- loads: Types::UserType,
- required: true,
- description: <<~DESC
- User ID for the user to toggle attention requested.
- DESC
-
- def resolve(project_path:, iid:, user:)
- raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless current_user&.mr_attention_requests_enabled?
-
- merge_request = authorized_find!(project_path: project_path, iid: iid)
-
- result = ::MergeRequests::ToggleAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: user).execute
-
- {
- merge_request: merge_request,
- errors: Array(result[:message])
- }
- end
- end
- end
-end
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index 1b673204213..f48e62af767 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -21,7 +21,13 @@ module Mutations
argument :confidential,
GraphQL::Types::Boolean,
required: false,
- description: 'Confidentiality flag of a note. Default is false.'
+ description: 'Confidentiality flag of a note. Default is false.',
+ deprecated: { reason: :renamed, replacement: 'internal', milestone: '15.3' }
+
+ argument :internal,
+ GraphQL::Types::Boolean,
+ required: false,
+ description: 'Internal flag for a note. Default is false.'
def resolve(args)
noteable = authorized_find!(id: args[:noteable_id])
@@ -49,7 +55,7 @@ module Mutations
{
noteable: noteable,
note: args[:body],
- confidential: args[:confidential]
+ internal: args[:internal] || args[:confidential]
}
end
diff --git a/app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb b/app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb
index e5bb5b6d573..3ccc90c16ae 100644
--- a/app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb
+++ b/app/graphql/mutations/security/ci_configuration/base_security_analyzer.rb
@@ -7,14 +7,16 @@ module Mutations
include FindsProject
argument :project_path, GraphQL::Types::ID,
- required: true,
- description: 'Full path of the project.'
+ required: true,
+ description: 'Full path of the project.'
- field :success_path, GraphQL::Types::String, null: true,
- description: 'Redirect path to use when the response is successful.'
+ field :success_path, GraphQL::Types::String,
+ null: true,
+ description: 'Redirect path to use when the response is successful.'
- field :branch, GraphQL::Types::String, null: true,
- description: 'Branch that has the new/modified `.gitlab-ci.yml` file.'
+ field :branch, GraphQL::Types::String,
+ null: true,
+ description: 'Branch that has the new/modified `.gitlab-ci.yml` file.'
authorize :push_code
diff --git a/app/graphql/mutations/timelogs/base.rb b/app/graphql/mutations/timelogs/base.rb
new file mode 100644
index 00000000000..9859f0e7d79
--- /dev/null
+++ b/app/graphql/mutations/timelogs/base.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Timelogs
+ class Base < Mutations::BaseMutation
+ field :timelog,
+ Types::TimelogType,
+ null: true,
+ description: 'Timelog.'
+
+ private
+
+ def response(result)
+ { timelog: result.payload[:timelog], errors: result.errors }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/timelogs/create.rb b/app/graphql/mutations/timelogs/create.rb
new file mode 100644
index 00000000000..bab7508454e
--- /dev/null
+++ b/app/graphql/mutations/timelogs/create.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Timelogs
+ class Create < Base
+ graphql_name 'TimelogCreate'
+
+ argument :time_spent,
+ GraphQL::Types::String,
+ required: true,
+ description: 'Amount of time spent.'
+
+ argument :spent_at,
+ Types::DateType,
+ required: true,
+ description: 'When the time was spent.'
+
+ argument :summary,
+ GraphQL::Types::String,
+ required: true,
+ description: 'Summary of time spent.'
+
+ argument :issuable_id,
+ ::Types::GlobalIDType[::Issuable],
+ required: true,
+ description: 'Global ID of the issuable (Issue, WorkItem or MergeRequest).'
+
+ authorize :create_timelog
+
+ def resolve(issuable_id:, time_spent:, spent_at:, summary:, **args)
+ issuable = authorized_find!(id: issuable_id)
+ parsed_time_spent = Gitlab::TimeTrackingFormatter.parse(time_spent)
+
+ result = ::Timelogs::CreateService.new(
+ issuable, parsed_time_spent, spent_at, summary, current_user
+ ).execute
+
+ response(result)
+ end
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: [::Issue, ::WorkItem, ::MergeRequest]).sync
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/timelogs/delete.rb b/app/graphql/mutations/timelogs/delete.rb
index 8fd41c27b88..61588d839a7 100644
--- a/app/graphql/mutations/timelogs/delete.rb
+++ b/app/graphql/mutations/timelogs/delete.rb
@@ -2,14 +2,9 @@
module Mutations
module Timelogs
- class Delete < Mutations::BaseMutation
+ class Delete < Base
graphql_name 'TimelogDelete'
- field :timelog,
- Types::TimelogType,
- null: true,
- description: 'Deleted timelog.'
-
argument :id,
::Types::GlobalIDType[::Timelog],
required: true,
@@ -22,11 +17,13 @@ module Mutations
result = ::Timelogs::DeleteService.new(timelog, current_user).execute
# Return the result payload, not the loaded timelog, so that it returns null in case of unauthorized access
- { timelog: result.payload, errors: result.errors }
+ response(result)
end
+ private
+
def find_object(id:)
- GitlabSchema.find_by_gid(id)
+ GitlabSchema.object_from_id(id, expected_type: ::Timelog).sync
end
end
end
diff --git a/app/graphql/mutations/uploads/delete.rb b/app/graphql/mutations/uploads/delete.rb
new file mode 100644
index 00000000000..e2fb967cd2c
--- /dev/null
+++ b/app/graphql/mutations/uploads/delete.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Uploads
+ class Delete < BaseMutation
+ graphql_name 'UploadDelete'
+ description 'Deletes an upload.'
+
+ include Mutations::ResolvesResourceParent
+
+ authorize :destroy_upload
+
+ argument :secret, GraphQL::Types::String,
+ required: true,
+ description: 'Secret part of upload path.'
+
+ argument :filename, GraphQL::Types::String,
+ required: true,
+ description: 'Upload filename.'
+
+ field :upload, Types::UploadType,
+ null: true,
+ description: 'Deleted upload.'
+
+ def resolve(args)
+ parent = authorized_resource_parent_find!(args)
+
+ result = ::Uploads::DestroyService.new(parent, current_user).execute(args[:secret], args[:filename])
+
+ {
+ upload: result[:status] == :success ? result[:upload] : nil,
+ errors: Array(result[:message])
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/work_items/create.rb b/app/graphql/mutations/work_items/create.rb
index 350153eaf19..ece00e04ed9 100644
--- a/app/graphql/mutations/work_items/create.rb
+++ b/app/graphql/mutations/work_items/create.rb
@@ -13,6 +13,9 @@ module Mutations
authorize :create_work_item
+ argument :confidential, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Sets the work item confidentiality.'
argument :description, GraphQL::Types::String,
required: false,
description: copy_field_description(Types::WorkItemType, :description)
diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb
index 5d8c574877a..b4ed0a1a3ca 100644
--- a/app/graphql/mutations/work_items/update.rb
+++ b/app/graphql/mutations/work_items/update.rb
@@ -51,3 +51,5 @@ module Mutations
end
end
end
+
+Mutations::WorkItems::Update.prepend_mod
diff --git a/app/graphql/resolvers/ci/config_resolver.rb b/app/graphql/resolvers/ci/config_resolver.rb
index 1f486c47771..ec6ede58cf5 100644
--- a/app/graphql/resolvers/ci/config_resolver.rb
+++ b/app/graphql/resolvers/ci/config_resolver.rb
@@ -38,8 +38,8 @@ module Resolvers
.validate(content, dry_run: dry_run)
response(result)
- rescue GRPC::InvalidArgument => error
- Gitlab::ErrorTracking.track_and_raise_exception(error, sha: sha)
+ rescue GRPC::InvalidArgument => e
+ Gitlab::ErrorTracking.track_and_raise_exception(e, sha: sha)
end
private
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 64738608b60..b52a4cc0ab4 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -36,7 +36,7 @@ module Resolvers
required: false,
description: 'Sort order of results.'
- argument :upgrade_status, ::Types::Ci::RunnerUpgradeStatusTypeEnum,
+ argument :upgrade_status, ::Types::Ci::RunnerUpgradeStatusEnum,
required: false,
description: 'Filter by upgrade status.'
diff --git a/app/graphql/resolvers/ci/template_resolver.rb b/app/graphql/resolvers/ci/template_resolver.rb
index 17f2668df11..f2531d877c7 100644
--- a/app/graphql/resolvers/ci/template_resolver.rb
+++ b/app/graphql/resolvers/ci/template_resolver.rb
@@ -5,8 +5,11 @@ module Resolvers
class TemplateResolver < BaseResolver
type Types::Ci::TemplateType, null: true
- argument :name, GraphQL::Types::String, required: true,
- description: 'Name of the CI/CD template to search for. Template must be formatted as `Name.gitlab-ci.yml`.'
+ argument :name,
+ GraphQL::Types::String,
+ required: true,
+ description: 'Name of the CI/CD template to search for. ' \
+ 'Template must be formatted as `Name.gitlab-ci.yml`.'
alias_method :project, :object
diff --git a/app/graphql/resolvers/crm/contact_state_counts_resolver.rb b/app/graphql/resolvers/crm/contact_state_counts_resolver.rb
new file mode 100644
index 00000000000..f696400d44e
--- /dev/null
+++ b/app/graphql/resolvers/crm/contact_state_counts_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Crm
+ class ContactStateCountsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorize :read_crm_contact
+
+ type Types::CustomerRelations::ContactStateCountsType, null: true
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search term to find contacts with.'
+
+ argument :state, Types::CustomerRelations::ContactStateEnum,
+ required: false,
+ description: 'State of the contacts to search for.'
+
+ def resolve(**args)
+ CustomerRelations::ContactStateCounts.new(context[:current_user], object, args)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/crm/contacts_resolver.rb b/app/graphql/resolvers/crm/contacts_resolver.rb
index 58d0e2ce13d..a93942cf93b 100644
--- a/app/graphql/resolvers/crm/contacts_resolver.rb
+++ b/app/graphql/resolvers/crm/contacts_resolver.rb
@@ -10,6 +10,11 @@ module Resolvers
type Types::CustomerRelations::ContactType, null: true
+ argument :sort, Types::CustomerRelations::ContactSortEnum,
+ description: 'Criteria to sort contacts by.',
+ required: false,
+ default_value: { field: 'last_name', direction: :asc }
+
argument :search, GraphQL::Types::String,
required: false,
description: 'Search term to find contacts with.'
@@ -24,13 +29,25 @@ module Resolvers
def resolve(**args)
args[:ids] = resolve_ids(args.delete(:ids))
-
- ::Crm::ContactsFinder.new(current_user, { group: group }.merge(args)).execute
+ args.delete(:state) if args[:state] == :all
+
+ contacts = ::Crm::ContactsFinder.new(current_user, { group: group }.merge(args)).execute
+ if needs_offset?(args)
+ offset_pagination(contacts)
+ else
+ contacts
+ end
end
def group
object.respond_to?(:sync) ? object.sync : object
end
+
+ private
+
+ def needs_offset?(args)
+ args.key?(:sort) && args[:sort][:field] == 'organization'
+ end
end
end
end
diff --git a/app/graphql/resolvers/environments_resolver.rb b/app/graphql/resolvers/environments_resolver.rb
index 1823eb65d44..934c1ba2738 100644
--- a/app/graphql/resolvers/environments_resolver.rb
+++ b/app/graphql/resolvers/environments_resolver.rb
@@ -22,8 +22,8 @@ module Resolvers
return unless project.present?
Environments::EnvironmentsFinder.new(project, context[:current_user], args).execute
- rescue Environments::EnvironmentsFinder::InvalidStatesError => exception
- raise Gitlab::Graphql::Errors::ArgumentError, exception.message
+ rescue Environments::EnvironmentsFinder::InvalidStatesError => e
+ raise Gitlab::Graphql::Errors::ArgumentError, e.message
end
end
end
diff --git a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
index 27bba6c8144..187063bb8c3 100644
--- a/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
+++ b/app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb
@@ -14,7 +14,7 @@ module Resolvers
response = ::ErrorTracking::IssueDetailsService.new(
project,
current_user,
- { issue_id: id.model_id }
+ { issue_id: id.model_id, tracking_event: :error_tracking_view_details }
).execute
issue = response[:issue]
issue.gitlab_project = project if issue
diff --git a/app/graphql/resolvers/group_milestones_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb
index 319ff9f68c4..9242be7f684 100644
--- a/app/graphql/resolvers/group_milestones_resolver.rb
+++ b/app/graphql/resolvers/group_milestones_resolver.rb
@@ -45,5 +45,9 @@ module Resolvers
options: { include_subgroups: true }
).execute
end
+
+ def preloads
+ super.merge({ subgroup_milestone: :group })
+ end
end
end
diff --git a/app/graphql/resolvers/projects/fork_targets_resolver.rb b/app/graphql/resolvers/projects/fork_targets_resolver.rb
new file mode 100644
index 00000000000..5e8be325d43
--- /dev/null
+++ b/app/graphql/resolvers/projects/fork_targets_resolver.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Projects
+ class ForkTargetsResolver < BaseResolver
+ include ResolvesGroups
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::NamespaceType.connection_type, null: true
+
+ authorize :fork_project
+ authorizes_object!
+
+ alias_method :project, :object
+
+ argument :search, GraphQL::Types::String,
+ required: false,
+ description: 'Search query for path or name.'
+
+ private
+
+ def resolve_groups(**args)
+ ForkTargetsFinder.new(project, current_user).execute(args)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index b846248458f..facf8ffe36f 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -25,8 +25,8 @@ module Resolvers
description: 'Sort order of results.'
argument :topics, type: [GraphQL::Types::String],
- required: false,
- description: 'Filters projects by topics.'
+ required: false,
+ description: 'Filters projects by topics.'
def resolve(**args)
ProjectsFinder
diff --git a/app/graphql/resolvers/users_resolver.rb b/app/graphql/resolvers/users_resolver.rb
index b0d704d09fc..90a6bd3e6b2 100644
--- a/app/graphql/resolvers/users_resolver.rb
+++ b/app/graphql/resolvers/users_resolver.rb
@@ -12,7 +12,7 @@ module Resolvers
description: 'List of user Global IDs.'
argument :usernames, [GraphQL::Types::String], required: false,
- description: 'List of usernames.'
+ description: 'List of usernames.'
argument :sort, Types::SortEnum,
description: 'Sort users by this criteria.',
diff --git a/app/graphql/resolvers/work_items_resolver.rb b/app/graphql/resolvers/work_items_resolver.rb
index 1bc74131b9e..055984db3cb 100644
--- a/app/graphql/resolvers/work_items_resolver.rb
+++ b/app/graphql/resolvers/work_items_resolver.rb
@@ -58,3 +58,5 @@ module Resolvers
end
end
end
+
+Resolvers::WorkItemsResolver.prepend_mod_with('Resolvers::WorkItemsResolver')
diff --git a/app/graphql/types/access_level_type.rb b/app/graphql/types/access_level_type.rb
index 2d97f6b30e8..4a709aa4711 100644
--- a/app/graphql/types/access_level_type.rb
+++ b/app/graphql/types/access_level_type.rb
@@ -7,11 +7,11 @@ module Types
description 'Represents the access level of a relationship between a User and object that it is related to'
field :integer_value, GraphQL::Types::Int, null: true,
- description: 'Integer representation of access level.',
- method: :to_i
+ description: 'Integer representation of access level.',
+ method: :to_i
field :string_value, Types::AccessLevelEnum, null: true,
- description: 'String representation of access level.',
- method: :to_i
+ description: 'String representation of access level.',
+ method: :to_i
end
end
diff --git a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
index 1fc47303d67..0da0a6bcd1a 100644
--- a/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
+++ b/app/graphql/types/admin/analytics/usage_trends/measurement_type.rb
@@ -13,12 +13,14 @@ module Types
authorize :read_usage_trends_measurement
field :recorded_at, Types::TimeType, null: true,
- description: 'Time the measurement was recorded.'
+ description: 'Time the measurement was recorded.'
field :count, GraphQL::Types::Int, null: false,
- description: 'Object count.'
+ description: 'Object count.'
- field :identifier, Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum, null: false,
+ field :identifier,
+ Types::Admin::Analytics::UsageTrends::MeasurementIdentifierEnum,
+ null: false,
description: 'Type of objects being measured.'
end
end
diff --git a/app/graphql/types/alert_management/domain_filter_enum.rb b/app/graphql/types/alert_management/domain_filter_enum.rb
index cd70cdd8ecf..86da345fd69 100644
--- a/app/graphql/types/alert_management/domain_filter_enum.rb
+++ b/app/graphql/types/alert_management/domain_filter_enum.rb
@@ -7,11 +7,12 @@ module Types
description 'Filters the alerts based on given domain'
value 'operations', description: 'Alerts for operations domain.'
- value 'threat_monitoring', description: 'Alerts for threat monitoring domain.',
- deprecated: {
- reason: 'Network policies are deprecated and will be removed in GitLab 16.0',
- milestone: '15.0'
- }
+ value 'threat_monitoring',
+ description: 'Alerts for threat monitoring domain.',
+ deprecated: {
+ reason: 'Network policies are deprecated and will be removed in GitLab 16.0',
+ milestone: '15.0'
+ }
end
end
end
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 6aee9a5c052..1c43432594a 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -17,7 +17,7 @@ module Types
@requires_argument = !!kwargs.delete(:requires_argument)
@authorize = Array.wrap(kwargs.delete(:authorize))
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
- @feature_flag = kwargs[:feature_flag]
+ @feature_flag = kwargs[:_deprecated_feature_flag]
kwargs = check_feature_flag(kwargs)
@deprecation = gitlab_deprecation(kwargs)
after_connection_extensions = kwargs.delete(:late_extensions) || []
@@ -136,7 +136,7 @@ module Types
end
def check_feature_flag(args)
- ff = args.delete(:feature_flag)
+ ff = args.delete(:_deprecated_feature_flag)
return args unless ff.present?
args[:description] = feature_documentation_message(ff, args[:description])
diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb
index 7f4c49df429..2352a21bd87 100644
--- a/app/graphql/types/board_list_type.rb
+++ b/app/graphql/types/board_list_type.rb
@@ -15,19 +15,21 @@ module Types
description: 'ID (global ID) of the list.'
field :collapsed, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the list is collapsed for this user.'
+ description: 'Indicates if the list is collapsed for this user.'
field :issues_count, GraphQL::Types::Int, null: true,
- description: 'Count of issues in the list.'
+ description: 'Count of issues in the list.'
field :label, Types::LabelType, null: true,
- description: 'Label of the list.'
+ description: 'Label of the list.'
field :list_type, GraphQL::Types::String, null: false,
- description: 'Type of the list.'
+ description: 'Type of the list.'
field :position, GraphQL::Types::Int, null: true,
- description: 'Position of list within the board.'
+ description: 'Position of list within the board.'
field :title, GraphQL::Types::String, null: false,
- description: 'Title of the list.'
+ description: 'Title of the list.'
- field :issues, ::Types::IssueType.connection_type, null: true,
+ field :issues,
+ ::Types::IssueType.connection_type,
+ null: true,
description: 'Board issues.',
late_extensions: [Gitlab::Graphql::Board::IssuesConnectionExtension],
resolver: ::Resolvers::BoardListIssuesResolver
diff --git a/app/graphql/types/board_type.rb b/app/graphql/types/board_type.rb
index 4ec9a8a9c63..00638988989 100644
--- a/app/graphql/types/board_type.rb
+++ b/app/graphql/types/board_type.rb
@@ -10,21 +10,21 @@ module Types
present_using BoardPresenter
field :id, type: GraphQL::Types::ID, null: false,
- description: 'ID (global ID) of the board.'
+ description: 'ID (global ID) of the board.'
field :name, type: GraphQL::Types::String, null: true,
- description: 'Name of the board.'
+ description: 'Name of the board.'
field :hide_backlog_list, type: GraphQL::Types::Boolean, null: true,
- description: 'Whether or not backlog list is hidden.'
+ description: 'Whether or not backlog list is hidden.'
field :hide_closed_list, type: GraphQL::Types::Boolean, null: true,
- description: 'Whether or not closed list is hidden.'
+ description: 'Whether or not closed list is hidden.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the board was created.'
+ description: 'Timestamp of when the board was created.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of when the board was last updated.'
+ description: 'Timestamp of when the board was last updated.'
field :lists,
Types::BoardListType.connection_type,
@@ -34,10 +34,10 @@ module Types
extras: [:lookahead]
field :web_path, GraphQL::Types::String, null: false,
- description: 'Web path of the board.'
+ description: 'Web path of the board.'
field :web_url, GraphQL::Types::String, null: false,
- description: 'Web URL of the board.'
+ description: 'Web URL of the board.'
end
end
diff --git a/app/graphql/types/ci/analytics_type.rb b/app/graphql/types/ci/analytics_type.rb
index a77b8026f86..6a55a6138ea 100644
--- a/app/graphql/types/ci/analytics_type.rb
+++ b/app/graphql/types/ci/analytics_type.rb
@@ -7,27 +7,27 @@ module Types
graphql_name 'PipelineAnalytics'
field :month_pipelines_labels, [GraphQL::Types::String], null: true,
- description: 'Labels for the monthly pipeline count.'
+ description: 'Labels for the monthly pipeline count.'
field :month_pipelines_successful, [GraphQL::Types::Int], null: true,
- description: 'Total monthly successful pipeline count.'
+ description: 'Total monthly successful pipeline count.'
field :month_pipelines_totals, [GraphQL::Types::Int], null: true,
- description: 'Total monthly pipeline count.'
+ description: 'Total monthly pipeline count.'
field :pipeline_times_labels, [GraphQL::Types::String], null: true,
- description: 'Pipeline times labels.'
+ description: 'Pipeline times labels.'
field :pipeline_times_values, [GraphQL::Types::Int], null: true,
- description: 'Pipeline times.'
+ description: 'Pipeline times.'
field :week_pipelines_labels, [GraphQL::Types::String], null: true,
- description: 'Labels for the weekly pipeline count.'
+ description: 'Labels for the weekly pipeline count.'
field :week_pipelines_successful, [GraphQL::Types::Int], null: true,
- description: 'Total weekly successful pipeline count.'
+ description: 'Total weekly successful pipeline count.'
field :week_pipelines_totals, [GraphQL::Types::Int], null: true,
- description: 'Total weekly pipeline count.'
+ description: 'Total weekly pipeline count.'
field :year_pipelines_labels, [GraphQL::Types::String], null: true,
- description: 'Labels for the yearly pipeline count.'
+ description: 'Labels for the yearly pipeline count.'
field :year_pipelines_successful, [GraphQL::Types::Int], null: true,
- description: 'Total yearly successful pipeline count.'
+ description: 'Total yearly successful pipeline count.'
field :year_pipelines_totals, [GraphQL::Types::Int], null: true,
- description: 'Total yearly pipeline count.'
+ description: 'Total yearly pipeline count.'
end
end
end
diff --git a/app/graphql/types/ci/application_setting_type.rb b/app/graphql/types/ci/application_setting_type.rb
index 2322778d159..53202c56f03 100644
--- a/app/graphql/types/ci/application_setting_type.rb
+++ b/app/graphql/types/ci/application_setting_type.rb
@@ -8,7 +8,7 @@ module Types
authorize :read_application_setting
field :keep_latest_artifact, GraphQL::Types::Boolean, null: true,
- description: 'Whether to keep the latest jobs artifacts.'
+ description: 'Whether to keep the latest jobs artifacts.'
end
end
end
diff --git a/app/graphql/types/ci/build_need_type.rb b/app/graphql/types/ci/build_need_type.rb
index b71d10c4c06..4ab711881fe 100644
--- a/app/graphql/types/ci/build_need_type.rb
+++ b/app/graphql/types/ci/build_need_type.rb
@@ -8,9 +8,9 @@ module Types
graphql_name 'CiBuildNeed'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the BuildNeed.'
+ description: 'ID of the BuildNeed.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the job we need to complete.'
+ description: 'Name of the job we need to complete.'
end
end
end
diff --git a/app/graphql/types/ci/ci_cd_setting_type.rb b/app/graphql/types/ci/ci_cd_setting_type.rb
index e43af6f3e78..bec8c72e783 100644
--- a/app/graphql/types/ci/ci_cd_setting_type.rb
+++ b/app/graphql/types/ci/ci_cd_setting_type.rb
@@ -7,20 +7,22 @@ module Types
authorize :admin_project
- field :job_token_scope_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
- method: :job_token_scope_enabled?
+ field :job_token_scope_enabled,
+ GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates CI job tokens generated in this project have restricted access to resources.',
+ method: :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?
+ description: 'Whether to keep the latest builds artifacts.',
+ method: :keep_latest_artifacts_available?
field :merge_pipelines_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Whether merge pipelines are enabled.',
- method: :merge_pipelines_enabled?
+ description: 'Whether merge pipelines are enabled.',
+ method: :merge_pipelines_enabled?
field :merge_trains_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Whether merge trains are enabled.',
- method: :merge_trains_enabled?
+ description: 'Whether merge trains are enabled.',
+ method: :merge_trains_enabled?
field :project, Types::ProjectType, null: true,
- description: 'Project the CI/CD settings belong to.'
+ description: 'Project the CI/CD settings belong to.'
end
end
end
diff --git a/app/graphql/types/ci/config/config_type.rb b/app/graphql/types/ci/config/config_type.rb
index a7a6927136d..6ccc62331df 100644
--- a/app/graphql/types/ci/config/config_type.rb
+++ b/app/graphql/types/ci/config/config_type.rb
@@ -8,17 +8,17 @@ module Types
graphql_name 'CiConfig'
field :errors, [GraphQL::Types::String], null: true,
- description: 'Linting errors.'
+ description: 'Linting errors.'
field :includes, [Types::Ci::Config::IncludeType], null: true,
- description: 'List of included files.'
+ description: 'List of included files.'
field :merged_yaml, GraphQL::Types::String, null: true,
- description: 'Merged CI configuration YAML.'
+ description: 'Merged CI configuration YAML.'
field :stages, Types::Ci::Config::StageType.connection_type, null: true,
- description: 'Stages of the pipeline.'
+ description: 'Stages of the pipeline.'
field :status, Types::Ci::Config::StatusEnum, null: true,
- description: 'Status of linting, can be either valid or invalid.'
+ description: 'Status of linting, can be either valid or invalid.'
field :warnings, [GraphQL::Types::String], null: true,
- description: 'Linting warnings.'
+ description: 'Linting warnings.'
end
end
end
diff --git a/app/graphql/types/ci/config/group_type.rb b/app/graphql/types/ci/config/group_type.rb
index 19076fe9c20..8c4a0c04a2a 100644
--- a/app/graphql/types/ci/config/group_type.rb
+++ b/app/graphql/types/ci/config/group_type.rb
@@ -8,11 +8,11 @@ module Types
graphql_name 'CiConfigGroup'
field :jobs, Types::Ci::Config::JobType.connection_type, null: true,
- description: 'Jobs in group.'
+ description: 'Jobs in group.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the job group.'
+ description: 'Name of the job group.'
field :size, GraphQL::Types::Int, null: true,
- description: 'Size of the job group.'
+ description: 'Size of the job group.'
end
end
end
diff --git a/app/graphql/types/ci/config/job_restriction_type.rb b/app/graphql/types/ci/config/job_restriction_type.rb
index 8cf0e210def..bb9c03f7c1e 100644
--- a/app/graphql/types/ci/config/job_restriction_type.rb
+++ b/app/graphql/types/ci/config/job_restriction_type.rb
@@ -8,7 +8,7 @@ module Types
graphql_name 'CiConfigJobRestriction'
field :refs, [GraphQL::Types::String], null: true,
- description: 'Git refs the job restriction applies to.'
+ description: 'Git refs the job restriction applies to.'
end
end
end
diff --git a/app/graphql/types/ci/config/job_type.rb b/app/graphql/types/ci/config/job_type.rb
index 20279143635..fb92a37dee6 100644
--- a/app/graphql/types/ci/config/job_type.rb
+++ b/app/graphql/types/ci/config/job_type.rb
@@ -7,33 +7,41 @@ module Types
class JobType < BaseObject
graphql_name 'CiConfigJob'
- field :after_script, [GraphQL::Types::String], null: true,
+ field :after_script,
+ [GraphQL::Types::String],
+ null: true,
description: 'Override a set of commands that are executed after the job.'
field :allow_failure, GraphQL::Types::Boolean, null: true,
- description: 'Allow job to fail.'
- field :before_script, [GraphQL::Types::String], null: true,
+ description: 'Allow job to fail.'
+ field :before_script,
+ [GraphQL::Types::String],
+ null: true,
description: 'Override a set of commands that are executed before the job.'
field :environment, GraphQL::Types::String, null: true,
- description: 'Name of an environment to which the job deploys.'
+ description: 'Name of an environment to which the job deploys.'
field :except, Types::Ci::Config::JobRestrictionType, null: true,
- description: 'Limit when jobs are not created.'
+ description: 'Limit when jobs are not created.'
field :group_name, GraphQL::Types::String, null: true,
- description: 'Name of the job group.'
+ description: 'Name of the job group.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the job.'
- field :needs, Types::Ci::Config::NeedType.connection_type, null: true,
+ description: 'Name of the job.'
+ field :needs,
+ Types::Ci::Config::NeedType.connection_type,
+ null: true,
description: 'Builds that must complete before the jobs run.'
- field :only, Types::Ci::Config::JobRestrictionType, null: true,
- description: 'Jobs are created when these conditions do not apply.'
+ field :only,
+ Types::Ci::Config::JobRestrictionType,
+ null: true,
+ description: 'Jobs are created when these conditions do not apply.'
field :script, [GraphQL::Types::String], null: true,
- description: 'Shell script that is executed by a runner.'
+ description: 'Shell script that is executed by a runner.'
field :stage, GraphQL::Types::String, null: true,
- description: 'Name of the job stage.'
+ description: 'Name of the job stage.'
field :tags, [GraphQL::Types::String], null: true,
- description: 'List of tags that are used to select a runner.'
+ description: 'List of tags that are used to select a runner.'
field :when, GraphQL::Types::String, null: true,
- description: 'When to run the job.',
- resolver_method: :restrict_when_to_run_jobs
+ description: 'When to run the job.',
+ resolver_method: :restrict_when_to_run_jobs
def restrict_when_to_run_jobs
object[:when]
diff --git a/app/graphql/types/ci/config/need_type.rb b/app/graphql/types/ci/config/need_type.rb
index 6e9aea8eb64..dd262923246 100644
--- a/app/graphql/types/ci/config/need_type.rb
+++ b/app/graphql/types/ci/config/need_type.rb
@@ -8,7 +8,7 @@ module Types
graphql_name 'CiConfigNeed'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the need.'
+ description: 'Name of the need.'
end
end
end
diff --git a/app/graphql/types/ci/config/stage_type.rb b/app/graphql/types/ci/config/stage_type.rb
index 5b1163edac2..4dacba2f1ed 100644
--- a/app/graphql/types/ci/config/stage_type.rb
+++ b/app/graphql/types/ci/config/stage_type.rb
@@ -8,9 +8,9 @@ module Types
graphql_name 'CiConfigStage'
field :groups, Types::Ci::Config::GroupType.connection_type, null: true,
- description: 'Groups of jobs for the stage.'
+ description: 'Groups of jobs for the stage.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the stage.'
+ description: 'Name of the stage.'
end
end
end
diff --git a/app/graphql/types/ci/detailed_status_type.rb b/app/graphql/types/ci/detailed_status_type.rb
index 3fab040cc0b..8bc50e974bb 100644
--- a/app/graphql/types/ci/detailed_status_type.rb
+++ b/app/graphql/types/ci/detailed_status_type.rb
@@ -6,31 +6,33 @@ module Types
class DetailedStatusType < BaseObject
graphql_name 'DetailedStatus'
- field :action, Types::Ci::StatusActionType, null: true,
+ field :action,
+ Types::Ci::StatusActionType,
+ null: true,
calls_gitaly: true,
description: 'Action information for the status. This includes method, button title, icon, path, and title.'
field :details_path, GraphQL::Types::String, null: true,
- description: 'Path of the details for the status.'
+ description: 'Path of the details for the status.'
field :favicon, GraphQL::Types::String, null: true,
- description: 'Favicon of the status.'
+ description: 'Favicon of the status.'
field :group, GraphQL::Types::String, null: true,
- description: 'Group of the status.'
+ description: 'Group of the status.'
field :has_details, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the status has further details.',
- method: :has_details?
+ description: 'Indicates if the status has further details.',
+ method: :has_details?
field :icon, GraphQL::Types::String, null: true,
- description: 'Icon of the status.'
+ description: 'Icon of the status.'
field :id, GraphQL::Types::String, null: false,
- description: 'ID for a detailed status.',
- extras: [:parent]
+ description: 'ID for a detailed status.',
+ extras: [:parent]
field :label, GraphQL::Types::String, null: true,
- calls_gitaly: true,
- description: 'Label of the status.'
+ calls_gitaly: true,
+ description: 'Label of the status.'
field :text, GraphQL::Types::String, null: true,
- description: 'Text of the status.'
+ description: 'Text of the status.'
field :tooltip, GraphQL::Types::String, null: true,
- description: 'Tooltip associated with the status.',
- method: :status_tooltip
+ description: 'Tooltip associated with the status.',
+ method: :status_tooltip
def id(parent:)
"#{object.id}-#{parent.id}"
diff --git a/app/graphql/types/ci/group_type.rb b/app/graphql/types/ci/group_type.rb
index c3c73ef170c..f2150fa5e1a 100644
--- a/app/graphql/types/ci/group_type.rb
+++ b/app/graphql/types/ci/group_type.rb
@@ -7,15 +7,15 @@ module Types
graphql_name 'CiGroup'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the group.'
+ description: 'Detailed status of the group.'
field :id, GraphQL::Types::String, null: false,
- description: 'ID for a group.'
+ description: 'ID for a group.'
field :jobs, Ci::JobType.connection_type, null: true,
- description: 'Jobs in group.'
+ description: 'Jobs in group.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the job group.'
+ description: 'Name of the job group.'
field :size, GraphQL::Types::Int, null: true,
- description: 'Size of the group.'
+ description: 'Size of the group.'
def detailed_status
object.detailed_status(context[:current_user])
diff --git a/app/graphql/types/ci/group_variable_type.rb b/app/graphql/types/ci/group_variable_type.rb
new file mode 100644
index 00000000000..3322f741342
--- /dev/null
+++ b/app/graphql/types/ci/group_variable_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class GroupVariableType < BaseObject
+ graphql_name 'CiGroupVariable'
+ description 'CI/CD variables for a group.'
+
+ implements(VariableInterface)
+
+ field :environment_scope, GraphQL::Types::String,
+ null: true,
+ description: 'Scope defining the environments that can use the variable.'
+
+ field :protected, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is protected.'
+
+ field :masked, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is masked.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/instance_variable_type.rb b/app/graphql/types/ci/instance_variable_type.rb
new file mode 100644
index 00000000000..f564a2f59a0
--- /dev/null
+++ b/app/graphql/types/ci/instance_variable_type.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class InstanceVariableType < BaseObject
+ graphql_name 'CiInstanceVariable'
+ description 'CI/CD variables for a GitLab instance.'
+
+ implements(VariableInterface)
+
+ field :environment_scope, GraphQL::Types::String,
+ null: true,
+ deprecated: {
+ reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
+ milestone: '15.3'
+ },
+ description: 'Scope defining the environments that can use the variable.'
+
+ field :protected, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is protected.'
+
+ field :masked, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is masked.'
+
+ def environment_scope
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/job_artifact_type.rb b/app/graphql/types/ci/job_artifact_type.rb
index 69bb5325dba..a6ab445702c 100644
--- a/app/graphql/types/ci/job_artifact_type.rb
+++ b/app/graphql/types/ci/job_artifact_type.rb
@@ -7,14 +7,14 @@ module Types
graphql_name 'CiJobArtifact'
field :download_path, GraphQL::Types::String, null: true,
- description: "URL for downloading the artifact's file."
+ description: "URL for downloading the artifact's file."
field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true,
- description: 'File type of the artifact.'
+ description: 'File type of the artifact.'
field :name, GraphQL::Types::String, null: true,
- description: 'File name of the artifact.',
- method: :filename
+ description: 'File name of the artifact.',
+ method: :filename
def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
diff --git a/app/graphql/types/ci/job_token_scope_type.rb b/app/graphql/types/ci/job_token_scope_type.rb
index 9f48298e1d3..37c0af944a7 100644
--- a/app/graphql/types/ci/job_token_scope_type.rb
+++ b/app/graphql/types/ci/job_token_scope_type.rb
@@ -7,9 +7,11 @@ module Types
class JobTokenScopeType < BaseObject
graphql_name 'CiJobTokenScopeType'
- field :projects, Types::ProjectType.connection_type, null: false,
- description: 'Allow list of projects that can be accessed by CI Job tokens created by this project.',
- method: :all_projects
+ field :projects,
+ Types::ProjectType.connection_type,
+ null: false,
+ description: 'Allow list of projects that can be accessed by CI Job tokens created by this project.',
+ method: :all_projects
end
end
# rubocop: enable Graphql/AuthorizeTypes
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 42b55f47f92..4ea9a016e74 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -12,39 +12,39 @@ module Types
expose_permissions Types::PermissionTypes::Ci::Job
field :allow_failure, ::GraphQL::Types::Boolean, null: false,
- description: 'Whether the job is allowed to fail.'
+ description: 'Whether the job is allowed to fail.'
field :duration, GraphQL::Types::Int, null: true,
- description: 'Duration of the job in seconds.'
+ description: 'Duration of the job in seconds.'
field :id, ::Types::GlobalIDType[::CommitStatus].as('JobID'), null: true,
- description: 'ID of the job.'
+ description: 'ID of the job.'
field :kind, type: ::Types::Ci::JobKindEnum, null: false,
- description: 'Indicates the type of job.'
+ description: 'Indicates the type of job.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the job.'
+ description: 'Name of the job.'
field :needs, BuildNeedType.connection_type, null: true,
- description: 'References to builds that must complete before the jobs run.'
+ description: 'References to builds that must complete before the jobs run.'
field :pipeline, Types::Ci::PipelineType, null: true,
- description: 'Pipeline the job belongs to.'
+ description: 'Pipeline the job belongs to.'
field :stage, Types::Ci::StageType, null: true,
- description: 'Stage of the job.'
+ description: 'Stage of the job.'
field :status,
type: ::Types::Ci::JobStatusEnum,
null: true,
description: "Status of the job."
field :tags, [GraphQL::Types::String], null: true,
- description: 'Tags for the current job.'
+ description: 'Tags for the current job.'
# Life-cycle timestamps:
field :created_at, Types::TimeType, null: false,
- description: "When the job was created."
+ description: "When the job was created."
field :finished_at, Types::TimeType, null: true,
- description: 'When a job has finished running.'
+ description: 'When a job has finished running.'
field :queued_at, Types::TimeType, null: true,
- description: 'When the job was enqueued and marked as pending.'
+ description: 'When the job was enqueued and marked as pending.'
field :scheduled_at, Types::TimeType, null: true,
- description: 'Schedule for the build.'
+ description: 'Schedule for the build.'
field :started_at, Types::TimeType, null: true,
- description: 'When the job was started.'
+ description: 'When the job was started.'
# Life-cycle durations:
field :queued_duration,
@@ -53,45 +53,45 @@ module Types
description: 'How long the job was enqueued before starting.'
field :active, GraphQL::Types::Boolean, null: false, method: :active?,
- description: 'Indicates the job is active.'
+ description: 'Indicates the job is active.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
- description: 'Artifacts generated by the job.'
+ description: 'Artifacts generated by the job.'
field :cancelable, GraphQL::Types::Boolean, null: false, method: :cancelable?,
- description: 'Indicates the job can be canceled.'
+ description: 'Indicates the job can be canceled.'
field :commit_path, GraphQL::Types::String, null: true,
- description: 'Path to the commit that triggered the job.'
+ description: 'Path to the commit that triggered the job.'
field :coverage, GraphQL::Types::Float, null: true,
- description: 'Coverage level of the job.'
+ description: 'Coverage level of the job.'
field :created_by_tag, GraphQL::Types::Boolean, null: false,
- description: 'Whether the job was created by a tag.', method: :tag?
+ description: 'Whether the job was created by a tag.', method: :tag?
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the job.'
+ description: 'Detailed status of the job.'
field :downstream_pipeline, Types::Ci::PipelineType, null: true,
- description: 'Downstream pipeline for a bridge.'
+ description: 'Downstream pipeline for a bridge.'
field :manual_job, GraphQL::Types::Boolean, null: true,
- description: 'Whether the job has a manual action.'
- field :manual_variables, VariableType.connection_type, null: true,
- description: 'Variables added to a manual job when the job is triggered.'
+ description: 'Whether the job has a manual action.'
+ field :manual_variables, ManualVariableType.connection_type, null: true,
+ description: 'Variables added to a manual job when the job is triggered.'
field :playable, GraphQL::Types::Boolean, null: false, method: :playable?,
- description: 'Indicates the job can be played.'
+ description: 'Indicates the job can be played.'
field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true,
- description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
+ description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
field :ref_name, GraphQL::Types::String, null: true,
- description: 'Ref name of the job.'
+ description: 'Ref name of the job.'
field :ref_path, GraphQL::Types::String, null: true,
- description: 'Path to the ref.'
+ description: 'Path to the ref.'
field :retried, GraphQL::Types::Boolean, null: true,
- description: 'Indicates that the job has been retried.'
+ description: 'Indicates that the job has been retried.'
field :retryable, GraphQL::Types::Boolean, null: false, method: :retryable?,
- description: 'Indicates the job can be retried.'
+ description: 'Indicates the job can be retried.'
field :scheduling_type, GraphQL::Types::String, null: true,
- description: 'Type of job scheduling. Value is `dag` if the job uses the `needs` keyword, and `stage` otherwise.'
+ description: 'Type of job scheduling. Value is `dag` if the job uses the `needs` keyword, and `stage` otherwise.'
field :short_sha, type: GraphQL::Types::String, null: false,
- description: 'Short SHA1 ID of the commit.'
+ description: 'Short SHA1 ID of the commit.'
field :stuck, GraphQL::Types::Boolean, null: false, method: :stuck?,
- description: 'Indicates the job is stuck.'
+ description: 'Indicates the job is stuck.'
field :triggered, GraphQL::Types::Boolean, null: true,
- description: 'Whether the job was triggered.'
+ description: 'Whether the job was triggered.'
def kind
return ::Ci::Build unless [::Ci::Build, ::Ci::Bridge].include?(object.class)
@@ -194,7 +194,7 @@ module Types
end
def manual_variables
- if object.manual? && object.respond_to?(:job_variables)
+ if object.action? && object.respond_to?(:job_variables)
object.job_variables
else
[]
diff --git a/app/graphql/types/ci/manual_variable_type.rb b/app/graphql/types/ci/manual_variable_type.rb
new file mode 100644
index 00000000000..d6f59c1d249
--- /dev/null
+++ b/app/graphql/types/ci/manual_variable_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class ManualVariableType < BaseObject
+ graphql_name 'CiManualVariable'
+ description 'CI/CD variables given to a manual job.'
+
+ implements(VariableInterface)
+
+ field :environment_scope, GraphQL::Types::String,
+ null: true,
+ deprecated: {
+ reason: 'No longer used, only available for GroupVariableType and ProjectVariableType',
+ milestone: '15.3'
+ },
+ description: 'Scope defining the environments that can use the variable.'
+
+ def environment_scope
+ nil
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/pipeline_message_type.rb b/app/graphql/types/ci/pipeline_message_type.rb
index 7edea1901a1..35164b0894a 100644
--- a/app/graphql/types/ci/pipeline_message_type.rb
+++ b/app/graphql/types/ci/pipeline_message_type.rb
@@ -7,10 +7,10 @@ module Types
graphql_name 'PipelineMessage'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the pipeline message.'
+ description: 'ID of the pipeline message.'
field :content, GraphQL::Types::String, null: false,
- description: 'Content of the pipeline message.'
+ description: 'Content of the pipeline message.'
end
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 60418fec6c5..4a523f2edd9 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -13,14 +13,14 @@ module Types
expose_permissions Types::PermissionTypes::Ci::Pipeline
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the pipeline.'
+ description: 'ID of the pipeline.'
field :iid, GraphQL::Types::String, null: false,
- description: 'Internal ID of the pipeline.'
+ description: 'Internal ID of the pipeline.'
field :sha, GraphQL::Types::String, null: true,
- method: :sha,
- description: "SHA of the pipeline's commit." do
+ method: :sha,
+ description: "SHA of the pipeline's commit." do
argument :format,
type: Types::ShaFormatEnum,
required: false,
@@ -28,46 +28,46 @@ module Types
end
field :before_sha, GraphQL::Types::String, null: true,
- description: 'Base SHA of the source branch.'
+ description: 'Base SHA of the source branch.'
field :complete, GraphQL::Types::Boolean, null: false, method: :complete?,
- description: 'Indicates if a pipeline is complete.'
+ description: 'Indicates if a pipeline is complete.'
field :status, PipelineStatusEnum, null: false,
- description: "Status of the pipeline (#{::Ci::Pipeline.all_state_names.compact.join(', ').upcase})"
+ description: "Status of the pipeline (#{::Ci::Pipeline.all_state_names.compact.join(', ').upcase})"
field :warnings, GraphQL::Types::Boolean, null: false, method: :has_warnings?,
- description: "Indicates if a pipeline has warnings."
+ description: "Indicates if a pipeline has warnings."
field :detailed_status, Types::Ci::DetailedStatusType, null: false,
- description: 'Detailed status of the pipeline.'
+ description: 'Detailed status of the pipeline.'
field :config_source, PipelineConfigSourceEnum, null: true,
- description: "Configuration source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
+ description: "Configuration source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
field :duration, GraphQL::Types::Int, null: true,
- description: 'Duration of the pipeline in seconds.'
+ description: 'Duration of the pipeline in seconds.'
field :queued_duration, Types::DurationType, null: true,
- description: 'How long the pipeline was queued before starting.'
+ description: 'How long the pipeline was queued before starting.'
field :coverage, GraphQL::Types::Float, null: true,
- description: 'Coverage percentage.'
+ description: 'Coverage percentage.'
field :created_at, Types::TimeType, null: false,
- description: "Timestamp of the pipeline's creation."
+ description: "Timestamp of the pipeline's creation."
field :updated_at, Types::TimeType, null: false,
- description: "Timestamp of the pipeline's last activity."
+ description: "Timestamp of the pipeline's last activity."
field :started_at, Types::TimeType, null: true,
- description: 'Timestamp when the pipeline was started.'
+ description: 'Timestamp when the pipeline was started.'
field :finished_at, Types::TimeType, null: true,
- description: "Timestamp of the pipeline's completion."
+ description: "Timestamp of the pipeline's completion."
field :committed_at, Types::TimeType, null: true,
- description: "Timestamp of the pipeline's commit."
+ description: "Timestamp of the pipeline's commit."
field :stages,
type: Types::Ci::StageType.connection_type,
@@ -126,32 +126,32 @@ module Types
description: 'Job where pipeline was triggered from.'
field :downstream, Types::Ci::PipelineType.connection_type, null: true,
- description: 'Pipelines this pipeline will trigger.',
- method: :triggered_pipelines_with_preloads
+ description: 'Pipelines this pipeline will trigger.',
+ method: :triggered_pipelines_with_preloads
field :upstream, Types::Ci::PipelineType, null: true,
- description: 'Pipeline that triggered the pipeline.',
- method: :triggered_by_pipeline
+ description: 'Pipeline that triggered the pipeline.',
+ method: :triggered_by_pipeline
field :path, GraphQL::Types::String, null: true,
- description: "Relative path to the pipeline's page."
+ description: "Relative path to the pipeline's page."
field :commit, Types::CommitType, null: true,
- description: "Git commit of the pipeline.",
- calls_gitaly: true
+ description: "Git commit of the pipeline.",
+ calls_gitaly: true
field :commit_path, GraphQL::Types::String, null: true,
- description: 'Path to the commit that triggered the pipeline.'
+ description: 'Path to the commit that triggered the pipeline.'
field :project, Types::ProjectType, null: true,
- description: 'Project the pipeline belongs to.'
+ description: 'Project the pipeline belongs to.'
field :active, GraphQL::Types::Boolean, null: false, method: :active?,
- description: 'Indicates if the pipeline is active.'
+ description: 'Indicates if the pipeline is active.'
field :uses_needs, GraphQL::Types::Boolean, null: true,
- method: :uses_needs?,
- description: 'Indicates if the pipeline has jobs with `needs` dependencies.'
+ method: :uses_needs?,
+ description: 'Indicates if the pipeline has jobs with `needs` dependencies.'
field :test_report_summary,
Types::Ci::TestReportSummaryType,
@@ -166,17 +166,17 @@ module Types
resolver: Resolvers::Ci::TestSuiteResolver
field :ref, GraphQL::Types::String, null: true,
- description: 'Reference to the branch from which the pipeline was triggered.'
+ description: 'Reference to the branch from which the pipeline was triggered.'
field :ref_path, GraphQL::Types::String, null: true,
- description: 'Reference path to the branch from which the pipeline was triggered.',
- method: :source_ref_path
+ description: 'Reference path to the branch from which the pipeline was triggered.',
+ method: :source_ref_path
field :warning_messages, [Types::Ci::PipelineMessageType], null: true,
- description: 'Pipeline warning messages.'
+ description: 'Pipeline warning messages.'
field :merge_request_event_type, Types::Ci::PipelineMergeRequestEventTypeEnum, null: true,
- description: "Event type of the pipeline associated with a merge request."
+ description: "Event type of the pipeline associated with a merge request."
def detailed_status
object.detailed_status(current_user)
@@ -200,7 +200,7 @@ module Types
if id
pipeline.statuses.id_in(id.model_id)
else
- pipeline.statuses.by_name(name)
+ pipeline.latest_statuses.by_name(name)
end.take # rubocop: disable CodeReuse/ActiveRecord
end
diff --git a/app/graphql/types/ci/project_variable_type.rb b/app/graphql/types/ci/project_variable_type.rb
new file mode 100644
index 00000000000..625bb7fd4b1
--- /dev/null
+++ b/app/graphql/types/ci/project_variable_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ # rubocop: disable Graphql/AuthorizeTypes
+ class ProjectVariableType < BaseObject
+ graphql_name 'CiProjectVariable'
+ description 'CI/CD variables for a project.'
+
+ implements(VariableInterface)
+
+ field :environment_scope, GraphQL::Types::String,
+ null: true,
+ description: 'Scope defining the environments that can use the variable.'
+
+ field :protected, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is protected.'
+
+ field :masked, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is masked.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/recent_failures_type.rb b/app/graphql/types/ci/recent_failures_type.rb
index f56b0939086..0892cb2735c 100644
--- a/app/graphql/types/ci/recent_failures_type.rb
+++ b/app/graphql/types/ci/recent_failures_type.rb
@@ -10,10 +10,10 @@ module Types
connection_type_class(Types::CountableConnectionType)
field :count, GraphQL::Types::Int, null: true,
- description: 'Number of times the test case has failed in the past 14 days.'
+ description: 'Number of times the test case has failed in the past 14 days.'
field :base_branch, GraphQL::Types::String, null: true,
- description: 'Name of the base branch of the project.'
+ description: 'Name of the base branch of the project.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/runner_architecture_type.rb b/app/graphql/types/ci/runner_architecture_type.rb
index eb576cf09ce..8b0558fc6a6 100644
--- a/app/graphql/types/ci/runner_architecture_type.rb
+++ b/app/graphql/types/ci/runner_architecture_type.rb
@@ -6,10 +6,12 @@ module Types
class RunnerArchitectureType < BaseObject
graphql_name 'RunnerArchitecture'
- field :download_location, GraphQL::Types::String, null: false,
- description: 'Download location for the runner for the platform architecture.'
+ field :download_location,
+ GraphQL::Types::String,
+ null: false,
+ description: 'Download location for the runner for the platform architecture.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the runner platform architecture.'
+ description: 'Name of the runner platform architecture.'
end
end
end
diff --git a/app/graphql/types/ci/runner_platform_type.rb b/app/graphql/types/ci/runner_platform_type.rb
index 3c893615b20..1e481cc08bf 100644
--- a/app/graphql/types/ci/runner_platform_type.rb
+++ b/app/graphql/types/ci/runner_platform_type.rb
@@ -6,12 +6,14 @@ module Types
class RunnerPlatformType < BaseObject
graphql_name 'RunnerPlatform'
- field :architectures, Types::Ci::RunnerArchitectureType.connection_type, null: true,
- description: 'Runner architectures supported for the platform.'
+ field :architectures,
+ Types::Ci::RunnerArchitectureType.connection_type,
+ null: true,
+ description: 'Runner architectures supported for the platform.'
field :human_readable_name, GraphQL::Types::String, null: false,
- description: 'Human readable name of the runner platform.'
+ description: 'Human readable name of the runner platform.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name slug of the runner platform.'
+ description: 'Name slug of the runner platform.'
end
end
end
diff --git a/app/graphql/types/ci/runner_setup_type.rb b/app/graphql/types/ci/runner_setup_type.rb
index b6b020db40e..5328ac8f21f 100644
--- a/app/graphql/types/ci/runner_setup_type.rb
+++ b/app/graphql/types/ci/runner_setup_type.rb
@@ -7,9 +7,9 @@ module Types
graphql_name 'RunnerSetup'
field :install_instructions, GraphQL::Types::String, null: false,
- description: 'Instructions for installing the runner on the specified architecture.'
+ description: 'Instructions for installing the runner on the specified architecture.'
field :register_instructions, GraphQL::Types::String, null: true,
- description: 'Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown.'
+ description: 'Instructions for registering the runner. The actual registration tokens are not included in the commands. Instead, a placeholder `$REGISTRATION_TOKEN` is shown.'
end
end
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index ac5ffd39407..0afb61d2b64 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -17,77 +17,77 @@ module Types
alias_method :runner, :object
field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false,
- description: 'Access level of the runner.'
+ description: 'Access level of the runner.'
field :active, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the runner is allowed to receive jobs.',
- deprecated: { reason: 'Use paused', milestone: '14.8' }
+ description: 'Indicates the runner is allowed to receive jobs.',
+ deprecated: { reason: 'Use paused', milestone: '14.8' }
field :admin_url, GraphQL::Types::String, null: true,
- description: 'Admin URL of the runner. Only available for administrators.'
+ description: 'Admin URL of the runner. Only available for administrators.'
field :contacted_at, Types::TimeType, null: true,
- description: 'Timestamp of last contact from this runner.',
- method: :contacted_at
+ description: 'Timestamp of last contact from this runner.',
+ method: :contacted_at
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of creation of this runner.'
+ description: 'Timestamp of creation of this runner.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the runner.'
+ description: 'Description of the runner.'
field :edit_admin_url, GraphQL::Types::String, null: true,
- description: 'Admin form URL of the runner. Only available for administrators.'
+ description: 'Admin form URL of the runner. Only available for administrators.'
field :executor_name, GraphQL::Types::String, null: true,
- description: 'Executor last advertised by the runner.',
- method: :executor_name
+ description: 'Executor last advertised by the runner.',
+ method: :executor_name
field :platform_name, GraphQL::Types::String, null: true,
- description: 'Platform provided by the runner.',
- method: :platform
+ description: 'Platform provided by the runner.',
+ method: :platform
field :architecture_name, GraphQL::Types::String, null: true,
- description: 'Architecture provided by the the runner.',
- method: :architecture
+ description: 'Architecture provided by the the runner.',
+ method: :architecture
field :maintenance_note, GraphQL::Types::String, null: true,
- description: 'Runner\'s maintenance notes.'
+ description: 'Runner\'s maintenance notes.'
field :groups, ::Types::GroupType.connection_type, null: true,
- description: 'Groups the runner is associated with. For group runners only.'
+ description: 'Groups the runner is associated with. For group runners only.'
field :id, ::Types::GlobalIDType[::Ci::Runner], null: false,
- description: 'ID of the runner.'
+ description: 'ID of the runner.'
field :ip_address, GraphQL::Types::String, null: true,
- description: 'IP address of the runner.'
+ description: 'IP address of the runner.'
field :job_count, GraphQL::Types::Int, null: true,
- description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)."
+ description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)."
field :jobs, ::Types::Ci::JobType.connection_type, null: true,
- description: 'Jobs assigned to the runner.',
- authorize: :read_builds,
- resolver: ::Resolvers::Ci::RunnerJobsResolver
+ description: 'Jobs assigned to the runner.',
+ authorize: :read_builds,
+ resolver: ::Resolvers::Ci::RunnerJobsResolver
field :locked, GraphQL::Types::Boolean, null: true,
- description: 'Indicates the runner is locked.'
+ description: 'Indicates the runner is locked.'
field :maximum_timeout, GraphQL::Types::Int, null: true,
- description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
+ description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
field :paused, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the runner is paused and not available to run jobs.'
+ description: 'Indicates the runner is paused and not available to run jobs.'
field :project_count, GraphQL::Types::Int, null: true,
- description: 'Number of projects that the runner is associated with.'
+ description: 'Number of projects that the runner is associated with.'
field :projects, ::Types::ProjectType.connection_type, null: true,
- description: 'Projects the runner is associated with. For project runners only.'
+ description: 'Projects the runner is associated with. For project runners only.'
field :revision, GraphQL::Types::String, null: true,
- description: 'Revision of the runner.'
+ description: 'Revision of the runner.'
field :run_untagged, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the runner is able to run untagged jobs.'
+ description: 'Indicates the runner is able to run untagged jobs.'
field :runner_type, ::Types::Ci::RunnerTypeEnum, null: false,
- description: 'Type of the runner.'
+ description: 'Type of the runner.'
field :short_sha, GraphQL::Types::String, null: true,
- description: %q(First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID.)
+ description: %q(First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID.)
field :status,
Types::Ci::RunnerStatusEnum,
null: false,
description: 'Status of the runner.',
resolver: ::Resolvers::Ci::RunnerStatusResolver # TODO: Remove :resolver in %17.0
field :tag_list, [GraphQL::Types::String], null: true,
- description: 'Tags associated with the runner.'
+ description: 'Tags associated with the runner.'
field :token_expires_at, Types::TimeType, null: true,
- description: 'Runner token expiration time.',
- method: :token_expires_at
+ description: 'Runner token expiration time.',
+ method: :token_expires_at
field :version, GraphQL::Types::String, null: true,
- description: 'Version of the runner.'
+ description: 'Version of the runner.'
field :owner_project, ::Types::ProjectType, null: true,
- description: 'Project that owns the runner. For project runners only.',
- resolver: ::Resolvers::Ci::RunnerOwnerProjectResolver
+ description: 'Project that owns the runner. For project runners only.',
+ resolver: ::Resolvers::Ci::RunnerOwnerProjectResolver
markdown_field :maintenance_note_html, null: true
diff --git a/app/graphql/types/ci/runner_upgrade_status_enum.rb b/app/graphql/types/ci/runner_upgrade_status_enum.rb
new file mode 100644
index 00000000000..34a931c8f79
--- /dev/null
+++ b/app/graphql/types/ci/runner_upgrade_status_enum.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class RunnerUpgradeStatusEnum < BaseEnum
+ graphql_name 'CiRunnerUpgradeStatus'
+
+ ::Ci::RunnerVersion::STATUS_DESCRIPTIONS.each do |status, description|
+ status_name_src =
+ if status == :invalid_version
+ :invalid
+ else
+ status
+ end
+
+ value status_name_src.to_s.upcase, description: description, value: status
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb
deleted file mode 100644
index 8e32eee5e6e..00000000000
--- a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module Ci
- class RunnerUpgradeStatusTypeEnum < BaseEnum
- graphql_name 'CiRunnerUpgradeStatusType'
-
- ::Ci::RunnerVersion::STATUS_DESCRIPTIONS.each do |status, description|
- status_name_src =
- if status == :invalid_version
- :invalid
- else
- status
- end
-
- value status_name_src.to_s.upcase, description: description, value: status
- end
- end
- end
-end
diff --git a/app/graphql/types/ci/runner_web_url_edge.rb b/app/graphql/types/ci/runner_web_url_edge.rb
index 7dfcd1f3510..9255e59267c 100644
--- a/app/graphql/types/ci/runner_web_url_edge.rb
+++ b/app/graphql/types/ci/runner_web_url_edge.rb
@@ -5,11 +5,11 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class RunnerWebUrlEdge < ::Types::BaseEdge
field :edit_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the runner edit page. The value depends on where you put this field in the query. You can use it for projects or groups.',
- extras: [:parent]
+ description: 'Web URL of the runner edit page. The value depends on where you put this field in the query. You can use it for projects or groups.',
+ extras: [:parent]
field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the runner. The value depends on where you put this field in the query. You can use it for projects or groups.',
- extras: [:parent]
+ description: 'Web URL of the runner. The value depends on where you put this field in the query. You can use it for projects or groups.',
+ extras: [:parent]
def initialize(node, connection)
super
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index dcb3092d15a..c0f3d1db57b 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -7,16 +7,16 @@ module Types
authorize :read_build
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
- description: 'Detailed status of the stage.'
+ description: 'Detailed status of the stage.'
field :groups, type: Ci::GroupType.connection_type, null: true,
- extras: [:lookahead],
- description: 'Group of jobs for the stage.'
+ extras: [:lookahead],
+ description: 'Group of jobs for the stage.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the stage.'
+ description: 'ID of the stage.'
field :jobs, Types::Ci::JobType.connection_type, null: true,
- description: 'Jobs for the stage.'
+ description: 'Jobs for the stage.'
field :name, type: GraphQL::Types::String, null: true,
- description: 'Name of the stage.'
+ description: 'Name of the stage.'
field :status, GraphQL::Types::String,
null: true,
description: 'Status of the pipeline stage.'
diff --git a/app/graphql/types/ci/status_action_type.rb b/app/graphql/types/ci/status_action_type.rb
index c0f61cf49f2..45773be49e2 100644
--- a/app/graphql/types/ci/status_action_type.rb
+++ b/app/graphql/types/ci/status_action_type.rb
@@ -6,19 +6,19 @@ module Types
graphql_name 'StatusAction'
field :button_title, GraphQL::Types::String, null: true,
- description: 'Title for the button, for example: Retry this job.'
+ description: 'Title for the button, for example: Retry this job.'
field :icon, GraphQL::Types::String, null: true,
- description: 'Icon used in the action button.'
+ description: 'Icon used in the action button.'
field :id, GraphQL::Types::String, null: false,
- description: 'ID for a status action.',
- extras: [:parent]
+ description: 'ID for a status action.',
+ extras: [:parent]
field :method, GraphQL::Types::String, null: true,
- description: 'Method for the action, for example: :post.',
- resolver_method: :action_method
+ description: 'Method for the action, for example: :post.',
+ resolver_method: :action_method
field :path, GraphQL::Types::String, null: true,
- description: 'Path for the action.'
+ description: 'Path for the action.'
field :title, GraphQL::Types::String, null: true,
- description: 'Title for the action, for example: Retry.'
+ description: 'Title for the action, for example: Retry.'
def id(parent:)
# parent is a SimpleDelegator
diff --git a/app/graphql/types/ci/template_type.rb b/app/graphql/types/ci/template_type.rb
index 4f1ec6436de..91e10c619c8 100644
--- a/app/graphql/types/ci/template_type.rb
+++ b/app/graphql/types/ci/template_type.rb
@@ -8,9 +8,9 @@ module Types
description 'GitLab CI/CD configuration template.'
field :content, GraphQL::Types::String, null: false,
- description: 'Contents of the CI template.'
+ description: 'Contents of the CI template.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the CI template.'
+ description: 'Name of the CI template.'
end
end
end
diff --git a/app/graphql/types/ci/test_case_type.rb b/app/graphql/types/ci/test_case_type.rb
index 6e5f55aa3ed..f88923215eb 100644
--- a/app/graphql/types/ci/test_case_type.rb
+++ b/app/graphql/types/ci/test_case_type.rb
@@ -9,32 +9,36 @@ module Types
connection_type_class(Types::CountableConnectionType)
- field :status, Types::Ci::TestCaseStatusEnum, null: true,
- description: "Status of the test case (#{::Gitlab::Ci::Reports::TestCase::STATUS_TYPES.join(', ')})."
+ field :status,
+ Types::Ci::TestCaseStatusEnum,
+ null: true,
+ description: "Status of the test case (#{::Gitlab::Ci::Reports::TestCase::STATUS_TYPES.join(', ')})."
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the test case.'
+ description: 'Name of the test case.'
field :classname, GraphQL::Types::String, null: true,
- description: 'Classname of the test case.'
+ description: 'Classname of the test case.'
field :execution_time, GraphQL::Types::Float, null: true,
- description: 'Test case execution time in seconds.'
+ description: 'Test case execution time in seconds.'
field :file, GraphQL::Types::String, null: true,
- description: 'Path to the file of the test case.'
+ description: 'Path to the file of the test case.'
field :attachment_url, GraphQL::Types::String, null: true,
- description: 'URL of the test case attachment file.'
+ description: 'URL of the test case attachment file.'
field :system_output, GraphQL::Types::String, null: true,
- description: 'System output of the test case.'
+ description: 'System output of the test case.'
field :stack_trace, GraphQL::Types::String, null: true,
- description: 'Stack trace of the test case.'
+ description: 'Stack trace of the test case.'
- field :recent_failures, Types::Ci::RecentFailuresType, null: true,
- description: 'Recent failure history of the test case on the base branch.'
+ field :recent_failures,
+ Types::Ci::RecentFailuresType,
+ null: true,
+ description: 'Recent failure history of the test case on the base branch.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/test_report_summary_type.rb b/app/graphql/types/ci/test_report_summary_type.rb
index 87207c8a765..e3577f4fa8f 100644
--- a/app/graphql/types/ci/test_report_summary_type.rb
+++ b/app/graphql/types/ci/test_report_summary_type.rb
@@ -9,10 +9,12 @@ module Types
description 'Test report for a pipeline'
field :total, Types::Ci::TestReportTotalType, null: false,
- description: 'Total report statistics for a pipeline test report.'
+ description: 'Total report statistics for a pipeline test report.'
- field :test_suites, Types::Ci::TestSuiteSummaryType.connection_type, null: false,
- description: 'Test suites belonging to a pipeline test report.'
+ field :test_suites,
+ Types::Ci::TestSuiteSummaryType.connection_type,
+ null: false,
+ description: 'Test suites belonging to a pipeline test report.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/test_report_total_type.rb b/app/graphql/types/ci/test_report_total_type.rb
index 48aea1257c5..54959d5173f 100644
--- a/app/graphql/types/ci/test_report_total_type.rb
+++ b/app/graphql/types/ci/test_report_total_type.rb
@@ -8,25 +8,25 @@ module Types
description 'Total test report statistics.'
field :time, GraphQL::Types::Float, null: true,
- description: 'Total duration of the tests.'
+ description: 'Total duration of the tests.'
field :count, GraphQL::Types::Int, null: true,
- description: 'Total number of the test cases.'
+ description: 'Total number of the test cases.'
field :success, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that succeeded.'
+ description: 'Total number of test cases that succeeded.'
field :failed, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that failed.'
+ description: 'Total number of test cases that failed.'
field :skipped, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that were skipped.'
+ description: 'Total number of test cases that were skipped.'
field :error, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that had an error.'
+ description: 'Total number of test cases that had an error.'
field :suite_error, GraphQL::Types::String, null: true,
- description: 'Test suite error message.'
+ description: 'Test suite error message.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/test_suite_summary_type.rb b/app/graphql/types/ci/test_suite_summary_type.rb
index ec7b852213b..8801501c8d4 100644
--- a/app/graphql/types/ci/test_suite_summary_type.rb
+++ b/app/graphql/types/ci/test_suite_summary_type.rb
@@ -10,31 +10,37 @@ module Types
connection_type_class(Types::CountableConnectionType)
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the test suite.'
+ description: 'Name of the test suite.'
field :total_time, GraphQL::Types::Float, null: true,
- description: 'Total duration of the tests in the test suite.'
+ description: 'Total duration of the tests in the test suite.'
field :total_count, GraphQL::Types::Int, null: true,
- description: 'Total number of the test cases in the test suite.'
+ description: 'Total number of the test cases in the test suite.'
- field :success_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that succeeded in the test suite.'
+ field :success_count,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of test cases that succeeded in the test suite.'
- field :failed_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that failed in the test suite.'
+ field :failed_count,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of test cases that failed in the test suite.'
- field :skipped_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that were skipped in the test suite.'
+ field :skipped_count,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of test cases that were skipped in the test suite.'
field :error_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that had an error.'
+ description: 'Total number of test cases that had an error.'
field :suite_error, GraphQL::Types::String, null: true,
- description: 'Test suite error message.'
+ description: 'Test suite error message.'
field :build_ids, [GraphQL::Types::ID], null: true,
- description: 'IDs of the builds used to run the test suite.'
+ description: 'IDs of the builds used to run the test suite.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/test_suite_type.rb b/app/graphql/types/ci/test_suite_type.rb
index 7ce479632cc..8845338ed6d 100644
--- a/app/graphql/types/ci/test_suite_type.rb
+++ b/app/graphql/types/ci/test_suite_type.rb
@@ -10,31 +10,36 @@ module Types
connection_type_class(Types::CountableConnectionType)
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the test suite.'
+ description: 'Name of the test suite.'
field :total_time, GraphQL::Types::Float, null: true,
- description: 'Total duration of the tests in the test suite.'
+ description: 'Total duration of the tests in the test suite.'
field :total_count, GraphQL::Types::Int, null: true,
- description: 'Total number of the test cases in the test suite.'
+ description: 'Total number of the test cases in the test suite.'
- field :success_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that succeeded in the test suite.'
+ field :success_count,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of test cases that succeeded in the test suite.'
- field :failed_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that failed in the test suite.'
+ field :failed_count,
+ GraphQL::Types::Int,
+ null: true,
+ description: 'Total number of test cases that failed in the test suite.'
- field :skipped_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that were skipped in the test suite.'
+ field :skipped_count,
+ GraphQL::Types::Int, null: true,
+ description: 'Total number of test cases that were skipped in the test suite.'
field :error_count, GraphQL::Types::Int, null: true,
- description: 'Total number of test cases that had an error.'
+ description: 'Total number of test cases that had an error.'
field :suite_error, GraphQL::Types::String, null: true,
- description: 'Test suite error message.'
+ description: 'Test suite error message.'
field :test_cases, Types::Ci::TestCaseType.connection_type, null: true,
- description: 'Test cases in the test suite.'
+ description: 'Test cases in the test suite.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/ci/variable_input_type.rb b/app/graphql/types/ci/variable_input_type.rb
new file mode 100644
index 00000000000..193ca6ffe4e
--- /dev/null
+++ b/app/graphql/types/ci/variable_input_type.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class VariableInputType < BaseInputObject
+ graphql_name 'CiVariableInput'
+ description 'Attributes for defining a CI/CD variable.'
+
+ argument :key, GraphQL::Types::String, description: 'Name of the variable.'
+ argument :value, GraphQL::Types::String, description: 'Value of the variable.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/variable_interface.rb b/app/graphql/types/ci/variable_interface.rb
new file mode 100644
index 00000000000..82c9ba7121c
--- /dev/null
+++ b/app/graphql/types/ci/variable_interface.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ module VariableInterface
+ include Types::BaseInterface
+
+ graphql_name 'CiVariable'
+
+ field :id, GraphQL::Types::ID,
+ null: false,
+ description: 'ID of the variable.'
+
+ field :key, GraphQL::Types::String,
+ null: true,
+ description: 'Name of the variable.'
+
+ field :value, GraphQL::Types::String,
+ null: true,
+ description: 'Value of the variable.'
+
+ field :variable_type, ::Types::Ci::VariableTypeEnum,
+ null: true,
+ description: 'Type of the variable.'
+
+ field :raw, GraphQL::Types::Boolean,
+ null: true,
+ description: 'Indicates whether the variable is raw.'
+ end
+ end
+end
diff --git a/app/graphql/types/ci/variable_type.rb b/app/graphql/types/ci/variable_type.rb
deleted file mode 100644
index 63f89b6d207..00000000000
--- a/app/graphql/types/ci/variable_type.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module Ci
- # rubocop: disable Graphql/AuthorizeTypes
- class VariableType < BaseObject
- graphql_name 'CiVariable'
-
- field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the variable.'
-
- field :key, GraphQL::Types::String, null: true,
- description: 'Name of the variable.'
-
- field :value, GraphQL::Types::String, null: true,
- description: 'Value of the variable.'
-
- field :variable_type, ::Types::Ci::VariableTypeEnum, null: true,
- description: 'Type of the variable.'
-
- field :protected, GraphQL::Types::Boolean, null: true,
- description: 'Indicates whether the variable is protected.'
-
- field :masked, GraphQL::Types::Boolean, null: true,
- description: 'Indicates whether the variable is masked.'
-
- field :raw, GraphQL::Types::Boolean, null: true,
- description: 'Indicates whether the variable is raw.'
-
- field :environment_scope, GraphQL::Types::String, null: true,
- description: 'Scope defining the environments in which the variable can be used.'
-
- def environment_scope
- if object.respond_to?(:environment_scope)
- object.environment_scope
- end
- end
- end
- end
-end
diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb
index 68b9a63d8dc..3344693bf46 100644
--- a/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb
+++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_input_type.rb
@@ -8,10 +8,10 @@ module Types
description 'Represents the analyzers entity in SAST CI configuration'
argument :name, GraphQL::Types::String, required: true,
- description: 'Name of analyzer.'
+ description: 'Name of analyzer.'
argument :enabled, GraphQL::Types::Boolean, required: true,
- description: 'State of the analyzer.'
+ description: 'State of the analyzer.'
argument :variables, [::Types::CiConfiguration::Sast::EntityInputType],
description: 'List of variables for the analyzer.',
diff --git a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb
index 9fdc7c1b000..de160756c8c 100644
--- a/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb
+++ b/app/graphql/types/ci_configuration/sast/analyzers_entity_type.rb
@@ -9,19 +9,21 @@ module Types
description 'Represents an analyzer entity in SAST CI configuration'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the analyzer.'
+ description: 'Name of the analyzer.'
field :label, GraphQL::Types::String, null: true,
- description: 'Analyzer label used in the config UI.'
+ description: 'Analyzer label used in the config UI.'
field :enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates whether an analyzer is enabled.'
+ description: 'Indicates whether an analyzer is enabled.'
field :description, GraphQL::Types::String, null: true,
- description: 'Analyzer description that is displayed on the form.'
+ description: 'Analyzer description that is displayed on the form.'
- field :variables, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
- description: 'List of supported variables.'
+ field :variables,
+ ::Types::CiConfiguration::Sast::EntityType.connection_type,
+ null: true,
+ description: 'List of supported variables.'
end
end
end
diff --git a/app/graphql/types/ci_configuration/sast/entity_input_type.rb b/app/graphql/types/ci_configuration/sast/entity_input_type.rb
index f0e3c07d71f..095097fe7b5 100644
--- a/app/graphql/types/ci_configuration/sast/entity_input_type.rb
+++ b/app/graphql/types/ci_configuration/sast/entity_input_type.rb
@@ -8,13 +8,13 @@ module Types
description 'Represents an entity in SAST CI configuration'
argument :field, GraphQL::Types::String, required: true,
- description: 'CI keyword of entity.'
+ description: 'CI keyword of entity.'
argument :default_value, GraphQL::Types::String, required: true,
- description: 'Default value that is used if value is empty.'
+ description: 'Default value that is used if value is empty.'
argument :value, GraphQL::Types::String, required: true,
- description: 'Current value of the entity.'
+ description: 'Current value of the entity.'
end
end
end
diff --git a/app/graphql/types/ci_configuration/sast/entity_type.rb b/app/graphql/types/ci_configuration/sast/entity_type.rb
index 41b8575d99a..91e80fdd9f8 100644
--- a/app/graphql/types/ci_configuration/sast/entity_type.rb
+++ b/app/graphql/types/ci_configuration/sast/entity_type.rb
@@ -9,28 +9,30 @@ module Types
description 'Represents an entity in SAST CI configuration'
field :field, GraphQL::Types::String, null: true,
- description: 'CI keyword of entity.'
+ description: 'CI keyword of entity.'
field :label, GraphQL::Types::String, null: true,
- description: 'Label for entity used in the form.'
+ description: 'Label for entity used in the form.'
field :type, GraphQL::Types::String, null: true,
- description: 'Type of the field value.'
+ description: 'Type of the field value.'
- field :options, ::Types::CiConfiguration::Sast::OptionsEntityType.connection_type, null: true,
- description: 'Different possible values of the field.'
+ field :options,
+ ::Types::CiConfiguration::Sast::OptionsEntityType.connection_type,
+ null: true,
+ description: 'Different possible values of the field.'
field :default_value, GraphQL::Types::String, null: true,
- description: 'Default value that is used if value is empty.'
+ description: 'Default value that is used if value is empty.'
field :description, GraphQL::Types::String, null: true,
- description: 'Entity description that is displayed on the form.'
+ description: 'Entity description that is displayed on the form.'
field :value, GraphQL::Types::String, null: true,
- description: 'Current value of the entity.'
+ description: 'Current value of the entity.'
field :size, ::Types::CiConfiguration::Sast::UiComponentSizeEnum, null: true,
- description: 'Size of the UI component.'
+ description: 'Size of the UI component.'
end
end
end
diff --git a/app/graphql/types/ci_configuration/sast/options_entity_type.rb b/app/graphql/types/ci_configuration/sast/options_entity_type.rb
index 5f365807cfe..2de84adf685 100644
--- a/app/graphql/types/ci_configuration/sast/options_entity_type.rb
+++ b/app/graphql/types/ci_configuration/sast/options_entity_type.rb
@@ -9,10 +9,10 @@ module Types
description 'Represents an entity for options in SAST CI configuration'
field :label, GraphQL::Types::String, null: true,
- description: 'Label of option entity.'
+ description: 'Label of option entity.'
field :value, GraphQL::Types::String, null: true,
- description: 'Value of option entity.'
+ description: 'Value of option entity.'
end
end
end
diff --git a/app/graphql/types/ci_configuration/sast/type.rb b/app/graphql/types/ci_configuration/sast/type.rb
index 35d11584ac7..edfdf296929 100644
--- a/app/graphql/types/ci_configuration/sast/type.rb
+++ b/app/graphql/types/ci_configuration/sast/type.rb
@@ -8,14 +8,20 @@ module Types
graphql_name 'SastCiConfiguration'
description 'Represents a CI configuration of SAST'
- field :global, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
- description: 'List of global entities related to SAST configuration.'
+ field :global,
+ ::Types::CiConfiguration::Sast::EntityType.connection_type,
+ null: true,
+ description: 'List of global entities related to SAST configuration.'
- field :pipeline, ::Types::CiConfiguration::Sast::EntityType.connection_type, null: true,
- description: 'List of pipeline entities related to SAST configuration.'
+ field :pipeline,
+ ::Types::CiConfiguration::Sast::EntityType.connection_type,
+ null: true,
+ description: 'List of pipeline entities related to SAST configuration.'
- field :analyzers, ::Types::CiConfiguration::Sast::AnalyzersEntityType.connection_type, null: true,
- description: 'List of analyzers entities attached to SAST configuration.'
+ field :analyzers,
+ ::Types::CiConfiguration::Sast::AnalyzersEntityType.connection_type,
+ null: true,
+ description: 'List of analyzers entities attached to SAST configuration.'
end
end
end
diff --git a/app/graphql/types/commit_action_type.rb b/app/graphql/types/commit_action_type.rb
index 1aa3a4e7ee1..9e808bd3174 100644
--- a/app/graphql/types/commit_action_type.rb
+++ b/app/graphql/types/commit_action_type.rb
@@ -3,18 +3,18 @@
module Types
class CommitActionType < BaseInputObject
argument :action, type: Types::CommitActionModeEnum, required: true,
- description: 'Action to perform: create, delete, move, update, or chmod.'
+ description: 'Action to perform: create, delete, move, update, or chmod.'
argument :content, type: GraphQL::Types::String, required: false,
- description: 'Content of the file.'
+ description: 'Content of the file.'
argument :encoding, type: Types::CommitEncodingEnum, required: false,
- description: 'Encoding of the file. Default is text.'
+ description: 'Encoding of the file. Default is text.'
argument :execute_filemode, type: GraphQL::Types::Boolean, required: false,
- description: 'Enables/disables the execute flag on the file.'
+ description: 'Enables/disables the execute flag on the file.'
argument :file_path, type: GraphQL::Types::String, required: true,
- description: 'Full path to the file.'
+ description: 'Full path to the file.'
argument :last_commit_id, type: GraphQL::Types::String, required: false,
- description: 'Last known file commit ID.'
+ description: 'Last known file commit ID.'
argument :previous_path, type: GraphQL::Types::String, required: false,
- description: 'Original full path to the file being moved.'
+ description: 'Original full path to the file being moved.'
end
end
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index c3a6d6f7faa..dfb02f29fb7 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -11,48 +11,48 @@ module Types
implements(Types::TodoableInterface)
field :id, type: GraphQL::Types::ID, null: false,
- description: 'ID (global ID) of the commit.'
+ description: 'ID (global ID) of the commit.'
field :sha, type: GraphQL::Types::String, null: false,
- description: 'SHA1 ID of the commit.'
+ description: 'SHA1 ID of the commit.'
field :short_id, type: GraphQL::Types::String, null: false,
- description: 'Short SHA1 ID of the commit.'
+ description: 'Short SHA1 ID of the commit.'
field :title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Title of the commit message.'
+ description: 'Title of the commit message.'
field :full_title, type: GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Full title of the commit message.'
+ description: 'Full title of the commit message.'
field :description, type: GraphQL::Types::String, null: true,
- description: 'Description of the commit message.'
+ description: 'Description of the commit message.'
field :message, type: GraphQL::Types::String, null: true,
- description: 'Raw commit message.'
+ description: 'Raw commit message.'
field :authored_date, type: Types::TimeType, null: true,
- description: 'Timestamp of when the commit was authored.'
+ description: 'Timestamp of when the commit was authored.'
field :web_url, type: GraphQL::Types::String, null: false,
- description: 'Web URL of the commit.'
+ description: 'Web URL of the commit.'
field :web_path, type: GraphQL::Types::String, null: false,
- description: 'Web path of the commit.'
+ description: 'Web path of the commit.'
field :signature_html, type: GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Rendered HTML of the commit signature.'
+ description: 'Rendered HTML of the commit signature.'
field :author_email, type: GraphQL::Types::String, null: true,
- description: "Commit author's email."
+ description: "Commit author's email."
field :author_gravatar, type: GraphQL::Types::String, null: true,
- description: 'Commit authors gravatar.'
+ description: 'Commit authors gravatar.'
field :author_name, type: GraphQL::Types::String, null: true,
- description: 'Commit authors name.'
+ description: 'Commit authors name.'
# models/commit lazy loads the author by email
field :author, type: Types::UserType, null: true,
- description: 'Author of the commit.'
+ description: 'Author of the commit.'
field :pipelines,
null: true,
diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb
index cd8e393b235..e404f1fcad9 100644
--- a/app/graphql/types/concerns/gitlab_style_deprecations.rb
+++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb
@@ -14,7 +14,10 @@ module GitlabStyleDeprecations
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items'
end
- deprecation = ::Gitlab::Graphql::Deprecation.parse(kwargs.delete(:deprecated))
+ # GitLab allows items to be marked as "alpha", which leverages GraphQL deprecations.
+ deprecation_args = kwargs.extract!(:alpha, :deprecated)
+
+ deprecation = ::Gitlab::Graphql::Deprecation.parse(**deprecation_args)
return unless deprecation
raise ArgumentError, "Bad deprecation. #{deprecation.errors.full_messages.to_sentence}" unless deprecation.valid?
diff --git a/app/graphql/types/countable_connection_type.rb b/app/graphql/types/countable_connection_type.rb
index 0f24964daa6..4c216ceceb6 100644
--- a/app/graphql/types/countable_connection_type.rb
+++ b/app/graphql/types/countable_connection_type.rb
@@ -4,7 +4,7 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class CountableConnectionType < GraphQL::Types::Relay::BaseConnection
field :count, GraphQL::Types::Int, null: false,
- description: 'Total count of collection.'
+ description: 'Total count of collection.'
def count
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/graphql/types/customer_relations/contact_sort_enum.rb b/app/graphql/types/customer_relations/contact_sort_enum.rb
new file mode 100644
index 00000000000..221dedacb6a
--- /dev/null
+++ b/app/graphql/types/customer_relations/contact_sort_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module CustomerRelations
+ class ContactSortEnum < SortEnum
+ graphql_name 'ContactSort'
+ description 'Values for sorting contacts'
+
+ sortable_fields = ['First name', 'Last name', 'Email', 'Phone', 'Description', 'Organization']
+
+ sortable_fields.each do |field|
+ value "#{field.upcase.tr(' ', '_')}_ASC",
+ value: { field: field.downcase.tr(' ', '_'), direction: :asc },
+ description: "#{field} by ascending order."
+ value "#{field.upcase.tr(' ', '_')}_DESC",
+ value: { field: field.downcase.tr(' ', '_'), direction: :desc },
+ description: "#{field} by descending order."
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/customer_relations/contact_state_counts_type.rb b/app/graphql/types/customer_relations/contact_state_counts_type.rb
new file mode 100644
index 00000000000..96230f8a952
--- /dev/null
+++ b/app/graphql/types/customer_relations/contact_state_counts_type.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Types
+ module CustomerRelations
+ class ContactStateCountsType < Types::BaseObject
+ graphql_name 'ContactStateCounts'
+ description 'Represents the total number of contacts for the represented states.'
+
+ authorize :read_crm_contact
+
+ def self.available_contact_states
+ @available_contact_states ||= ::CustomerRelations::Contact.states.keys.push('all')
+ end
+
+ available_contact_states.each do |state|
+ field state,
+ GraphQL::Types::Int,
+ null: true,
+ description: "Number of contacts with state `#{state.upcase}`"
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/customer_relations/contact_state_enum.rb b/app/graphql/types/customer_relations/contact_state_enum.rb
index 445d2a41401..1e5cae8528f 100644
--- a/app/graphql/types/customer_relations/contact_state_enum.rb
+++ b/app/graphql/types/customer_relations/contact_state_enum.rb
@@ -5,12 +5,16 @@ module Types
class ContactStateEnum < BaseEnum
graphql_name 'CustomerRelationsContactState'
+ value 'all',
+ description: "All available contacts.",
+ value: :all
+
value 'active',
- description: "Active contact.",
+ description: "Active contacts.",
value: :active
value 'inactive',
- description: "Inactive contact.",
+ description: "Inactive contacts.",
value: :inactive
end
end
diff --git a/app/graphql/types/design_management/design_collection_type.rb b/app/graphql/types/design_management/design_collection_type.rb
index 91978aa37b0..38864075288 100644
--- a/app/graphql/types/design_management/design_collection_type.rb
+++ b/app/graphql/types/design_management/design_collection_type.rb
@@ -9,9 +9,9 @@ module Types
authorize :read_design
field :issue, Types::IssueType, null: false,
- description: 'Issue associated with the design collection.'
+ description: 'Issue associated with the design collection.'
field :project, Types::ProjectType, null: false,
- description: 'Project associated with the design collection.'
+ description: 'Project associated with the design collection.'
field :designs,
Types::DesignManagement::DesignType.connection_type,
diff --git a/app/graphql/types/design_management/design_fields.rb b/app/graphql/types/design_management/design_fields.rb
index c3a35cfe1ad..f9e9b270a36 100644
--- a/app/graphql/types/design_management/design_fields.rb
+++ b/app/graphql/types/design_management/design_fields.rb
@@ -13,7 +13,10 @@ module Types
field :filename, GraphQL::Types::String, null: false, description: 'Filename of the design.'
field :full_path, GraphQL::Types::String, null: false, description: 'Full path to the design file.'
field :image, GraphQL::Types::String, null: false, extras: [:parent], description: 'URL of the full-sized image.'
- field :image_v432x230, GraphQL::Types::String, null: true, extras: [:parent],
+ field :image_v432x230,
+ GraphQL::Types::String,
+ null: true,
+ extras: [:parent],
description: 'The URL of the design resized to fit within the bounds of 432x230. ' \
'This will be `null` if the image has not been generated'
field :diff_refs, Types::DiffRefsType,
diff --git a/app/graphql/types/design_management/version_type.rb b/app/graphql/types/design_management/version_type.rb
index cfd2b887dc3..2cbe50afae6 100644
--- a/app/graphql/types/design_management/version_type.rb
+++ b/app/graphql/types/design_management/version_type.rb
@@ -12,9 +12,9 @@ module Types
authorize :read_design
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the design version.'
+ description: 'ID of the design version.'
field :sha, GraphQL::Types::ID, null: false,
- description: 'SHA of the design version.'
+ description: 'SHA of the design version.'
field :designs,
::Types::DesignManagement::DesignType.connection_type,
@@ -35,7 +35,7 @@ module Types
field :author, Types::UserType, null: false, description: 'Author of the version.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the version was created.'
+ description: 'Timestamp of when the version was created.'
end
end
end
diff --git a/app/graphql/types/diff_paths_input_type.rb b/app/graphql/types/diff_paths_input_type.rb
index c5c75105fda..94e86285b86 100644
--- a/app/graphql/types/diff_paths_input_type.rb
+++ b/app/graphql/types/diff_paths_input_type.rb
@@ -3,8 +3,8 @@
module Types
class DiffPathsInputType < BaseInputObject
argument :new_path, GraphQL::Types::String, required: false,
- description: 'Path of the file on the HEAD SHA.'
+ description: 'Path of the file on the HEAD SHA.'
argument :old_path, GraphQL::Types::String, required: false,
- description: 'Path of the file on the start SHA.'
+ description: 'Path of the file on the start SHA.'
end
end
diff --git a/app/graphql/types/diff_refs_type.rb b/app/graphql/types/diff_refs_type.rb
index a03d72a4dc2..6caf2eb87e6 100644
--- a/app/graphql/types/diff_refs_type.rb
+++ b/app/graphql/types/diff_refs_type.rb
@@ -7,11 +7,11 @@ module Types
graphql_name 'DiffRefs'
field :base_sha, GraphQL::Types::String, null: true,
- description: 'Merge base of the branch the comment was made on.'
+ description: 'Merge base of the branch the comment was made on.'
field :head_sha, GraphQL::Types::String, null: false,
- description: 'SHA of the HEAD at the time the comment was made.'
+ description: 'SHA of the HEAD at the time the comment was made.'
field :start_sha, GraphQL::Types::String, null: false,
- description: 'SHA of the branch being compared against.'
+ description: 'SHA of the branch being compared against.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/diff_stats_summary_type.rb b/app/graphql/types/diff_stats_summary_type.rb
index 95705ddecf3..44b92789408 100644
--- a/app/graphql/types/diff_stats_summary_type.rb
+++ b/app/graphql/types/diff_stats_summary_type.rb
@@ -9,13 +9,13 @@ module Types
description 'Aggregated summary of changes'
field :additions, GraphQL::Types::Int, null: false,
- description: 'Number of lines added.'
+ description: 'Number of lines added.'
field :changes, GraphQL::Types::Int, null: false,
- description: 'Number of lines changed.'
+ description: 'Number of lines changed.'
field :deletions, GraphQL::Types::Int, null: false,
- description: 'Number of lines deleted.'
+ description: 'Number of lines deleted.'
field :file_count, GraphQL::Types::Int, null: false,
- description: 'Number of files changed.'
+ description: 'Number of files changed.'
def changes
object[:additions] + object[:deletions]
diff --git a/app/graphql/types/diff_stats_type.rb b/app/graphql/types/diff_stats_type.rb
index da366fec8c3..a6b7f8e9084 100644
--- a/app/graphql/types/diff_stats_type.rb
+++ b/app/graphql/types/diff_stats_type.rb
@@ -9,11 +9,11 @@ module Types
description 'Changes to a single file'
field :additions, GraphQL::Types::Int, null: false,
- description: 'Number of lines added to this file.'
+ description: 'Number of lines added to this file.'
field :deletions, GraphQL::Types::Int, null: false,
- description: 'Number of lines deleted from this file.'
+ description: 'Number of lines deleted from this file.'
field :path, GraphQL::Types::String, null: false,
- description: 'File path, relative to repository root.'
+ description: 'File path, relative to repository root.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/environment_type.rb b/app/graphql/types/environment_type.rb
index aba83f559fa..2a7076cc3c9 100644
--- a/app/graphql/types/environment_type.rb
+++ b/app/graphql/types/environment_type.rb
@@ -10,20 +10,20 @@ module Types
authorize :read_environment
field :name, GraphQL::Types::String, null: false,
- description: 'Human-readable name of the environment.'
+ description: 'Human-readable name of the environment.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the environment.'
+ description: 'ID of the environment.'
field :state, GraphQL::Types::String, null: false,
- description: 'State of the environment, for example: available/stopped.'
+ description: 'State of the environment, for example: available/stopped.'
field :path, GraphQL::Types::String, null: false,
- description: 'Path to the environment.'
+ description: 'Path to the environment.'
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,
- description: 'Metrics dashboard schema for the environment.',
- resolver: Resolvers::Metrics::DashboardResolver
+ description: 'Metrics dashboard schema for the environment.',
+ resolver: Resolvers::Metrics::DashboardResolver
field :latest_opened_most_severe_alert,
Types::AlertManagement::AlertType,
diff --git a/app/graphql/types/evidence_type.rb b/app/graphql/types/evidence_type.rb
index ed644a4b2c6..0d73a935e50 100644
--- a/app/graphql/types/evidence_type.rb
+++ b/app/graphql/types/evidence_type.rb
@@ -10,12 +10,12 @@ module Types
present_using Releases::EvidencePresenter
field :collected_at, Types::TimeType, null: true,
- description: 'Timestamp when the evidence was collected.'
+ description: 'Timestamp when the evidence was collected.'
field :filepath, GraphQL::Types::String, null: true,
- description: 'URL from where the evidence can be downloaded.'
+ description: 'URL from where the evidence can be downloaded.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the evidence.'
+ description: 'ID of the evidence.'
field :sha, GraphQL::Types::String, null: true,
- description: 'SHA1 ID of the evidence hash.'
+ description: 'SHA1 ID of the evidence hash.'
end
end
diff --git a/app/graphql/types/global_id_type.rb b/app/graphql/types/global_id_type.rb
index 145a5a22460..a71c2fb0e6c 100644
--- a/app/graphql/types/global_id_type.rb
+++ b/app/graphql/types/global_id_type.rb
@@ -50,7 +50,7 @@ module Types
#{
if deprecation = Gitlab::GlobalId::Deprecations.deprecation_by(model_name)
'The older format `"' +
- ::Gitlab::GlobalId.build(model_name: deprecation.old_model_name, id: 1).to_s +
+ ::Gitlab::GlobalId.build(model_name: deprecation.old_name, id: 1).to_s +
'"` was deprecated in ' + deprecation.milestone + '.'
end}
diff --git a/app/graphql/types/grafana_integration_type.rb b/app/graphql/types/grafana_integration_type.rb
index 2bbc0d34db6..982ba803603 100644
--- a/app/graphql/types/grafana_integration_type.rb
+++ b/app/graphql/types/grafana_integration_type.rb
@@ -7,14 +7,14 @@ module Types
authorize :admin_operations
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of the issue\'s creation.'
+ description: 'Timestamp of the issue\'s creation.'
field :enabled, GraphQL::Types::Boolean, null: false,
- description: 'Indicates whether Grafana integration is enabled.'
+ description: 'Indicates whether Grafana integration is enabled.'
field :grafana_url, GraphQL::Types::String, null: false,
- description: 'URL for the Grafana host for the Grafana integration.'
+ description: 'URL for the Grafana host for the Grafana integration.'
field :id, GraphQL::Types::ID, null: false,
- description: 'Internal ID of the Grafana integration.'
+ description: 'Internal ID of the Grafana integration.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of the issue\'s last activity.'
+ description: 'Timestamp of the issue\'s last activity.'
end
end
diff --git a/app/graphql/types/group_invitation_type.rb b/app/graphql/types/group_invitation_type.rb
index 48281dcfd9f..2b874e23c64 100644
--- a/app/graphql/types/group_invitation_type.rb
+++ b/app/graphql/types/group_invitation_type.rb
@@ -11,7 +11,7 @@ module Types
implements InvitationInterface
field :group, Types::GroupType, null: true,
- description: 'Group that a User is invited to.'
+ description: 'Group that a User is invited to.'
def group
Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, object.source_id).find
diff --git a/app/graphql/types/group_member_type.rb b/app/graphql/types/group_member_type.rb
index c4582f31bec..2745853c9bb 100644
--- a/app/graphql/types/group_member_type.rb
+++ b/app/graphql/types/group_member_type.rb
@@ -11,7 +11,7 @@ module Types
implements MemberInterface
field :group, Types::GroupType, null: true,
- description: 'Group that a User is a member of.'
+ description: 'Group that a User is a member of.'
field :notification_email,
resolver: Resolvers::GroupMembers::NotificationEmailResolver,
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 52e9f808066..235a2bc2a34 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -22,7 +22,7 @@ module Types
type: Types::CustomEmojiType.connection_type,
null: true,
description: 'Custom emoji within this namespace.',
- feature_flag: :custom_emoji
+ _deprecated_feature_flag: :custom_emoji
field :share_with_group_lock,
type: GraphQL::Types::Boolean,
@@ -85,6 +85,7 @@ module Types
field :milestones,
description: 'Milestones of the group.',
+ extras: [:lookahead],
resolver: Resolvers::GroupMilestonesResolver
field :boards,
@@ -183,10 +184,10 @@ module Types
resolver: Resolvers::GroupLabelsResolver
field :timelogs, ::Types::TimelogType.connection_type, null: false,
- description: 'Time logged on issues and merge requests in the group and its subgroups.',
- extras: [:lookahead],
- complexity: 5,
- resolver: ::Resolvers::TimelogResolver
+ description: 'Time logged on issues and merge requests in the group and its subgroups.',
+ extras: [:lookahead],
+ complexity: 5,
+ resolver: ::Resolvers::TimelogResolver
field :descendant_groups, Types::GroupType.connection_type,
null: true,
@@ -195,7 +196,7 @@ module Types
resolver: Resolvers::GroupsResolver
field :ci_variables,
- Types::Ci::VariableType.connection_type,
+ Types::Ci::GroupVariableType.connection_type,
null: true,
description: "List of the group's CI/CD variables.",
authorize: :admin_group,
@@ -216,6 +217,12 @@ module Types
description: "Find contacts of this group.",
resolver: Resolvers::Crm::ContactsResolver
+ field :contact_state_counts,
+ Types::CustomerRelations::ContactStateCountsType,
+ null: true,
+ description: 'Counts of contacts by state for the group.',
+ resolver: Resolvers::Crm::ContactStateCountsResolver
+
field :work_item_types, Types::WorkItems::TypeType.connection_type,
resolver: Resolvers::WorkItems::TypesResolver,
description: 'Work item types available to the group.' \
diff --git a/app/graphql/types/invitation_interface.rb b/app/graphql/types/invitation_interface.rb
index 1f0746d7726..bbecf5b5f54 100644
--- a/app/graphql/types/invitation_interface.rb
+++ b/app/graphql/types/invitation_interface.rb
@@ -5,25 +5,25 @@ module Types
include BaseInterface
field :email, GraphQL::Types::String, null: false,
- description: 'Email of the member to invite.'
+ description: 'Email of the member to invite.'
field :access_level, Types::AccessLevelType, null: true,
- description: 'GitLab::Access level.'
+ description: 'GitLab::Access level.'
field :created_by, Types::UserType, null: true,
- description: 'User that authorized membership.'
+ description: 'User that authorized membership.'
field :created_at, Types::TimeType, null: true,
- description: 'Date and time the membership was created.'
+ description: 'Date and time the membership was created.'
field :updated_at, Types::TimeType, null: true,
- description: 'Date and time the membership was last updated.'
+ description: 'Date and time the membership was last updated.'
field :expires_at, Types::TimeType, null: true,
- description: 'Date and time the membership expires.'
+ description: 'Date and time the membership expires.'
field :user, Types::UserType, null: true,
- description: 'User that is associated with the member object.'
+ description: 'User that is associated with the member object.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 58729b34fc7..d897f3cde48 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -17,101 +17,101 @@ module Types
present_using IssuePresenter
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the issue.'
+ description: 'Description of the issue.'
field :id, GraphQL::Types::ID, null: false,
- description: "ID of the issue."
+ description: "ID of the issue."
field :iid, GraphQL::Types::ID, null: false,
- description: "Internal ID of the issue."
+ description: "Internal ID of the issue."
field :state, IssueStateEnum, null: false,
- description: 'State of the issue.'
+ description: 'State of the issue.'
field :title, GraphQL::Types::String, null: false,
- description: 'Title of the issue.'
+ description: 'Title of the issue.'
field :reference, GraphQL::Types::String, null: false,
- description: 'Internal reference of the issue. Returned in shortened format by default.',
- method: :to_reference do
+ description: 'Internal reference of the issue. Returned in shortened format by default.',
+ method: :to_reference do
argument :full, GraphQL::Types::Boolean, required: false, default_value: false,
- description: 'Boolean option specifying whether the reference should be returned in full.'
+ description: 'Boolean option specifying whether the reference should be returned in full.'
end
field :author, Types::UserType, null: false,
- description: 'User that created the issue.'
+ description: 'User that created the issue.'
field :assignees, Types::UserType.connection_type, null: true,
- description: 'Assignees of the issue.'
+ description: 'Assignees of the issue.'
field :updated_by, Types::UserType, null: true,
- description: 'User that last updated the issue.'
+ description: 'User that last updated the issue.'
field :labels, Types::LabelType.connection_type, null: true,
- description: 'Labels of the issue.'
+ description: 'Labels of the issue.'
field :milestone, Types::MilestoneType, null: true,
- description: 'Milestone of the issue.'
+ description: 'Milestone of the issue.'
field :confidential, GraphQL::Types::Boolean, null: false,
- description: 'Indicates the issue is confidential.'
+ description: 'Indicates the issue is confidential.'
field :discussion_locked, GraphQL::Types::Boolean, null: false,
- description: 'Indicates discussion is locked on the issue.'
+ description: 'Indicates discussion is locked on the issue.'
field :due_date, Types::TimeType, null: true,
- description: 'Due date of the issue.'
+ description: 'Due date of the issue.'
field :hidden, GraphQL::Types::Boolean, null: true, resolver_method: :hidden?,
- description: 'Indicates the issue is hidden because the author has been banned. ' \
+ 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.'
+ description: 'Number of downvotes the issue has received.'
field :merge_requests_count, GraphQL::Types::Int, null: false,
- description: 'Number of merge requests that close the issue on merge.',
- resolver: Resolvers::MergeRequestsCountResolver
+ 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).'
+ 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.'
+ description: 'Number of upvotes the issue has received.'
field :user_discussions_count, GraphQL::Types::Int, null: false,
- description: 'Number of user discussions in the issue.',
- resolver: Resolvers::UserDiscussionsCountResolver
+ description: 'Number of user discussions in the issue.',
+ resolver: Resolvers::UserDiscussionsCountResolver
field :user_notes_count, GraphQL::Types::Int, null: false,
- description: 'Number of user notes of the issue.',
- resolver: Resolvers::UserNotesCountResolver
+ description: 'Number of user notes of the issue.',
+ resolver: Resolvers::UserNotesCountResolver
field :web_path, GraphQL::Types::String, null: false, method: :issue_path,
- description: 'Web path of the issue.'
+ description: 'Web path of the issue.'
field :web_url, GraphQL::Types::String, null: false,
- description: 'Web URL of the issue.'
+ description: 'Web URL of the issue.'
field :emails_disabled, GraphQL::Types::Boolean, null: false,
- method: :project_emails_disabled?,
- description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled.'
+ method: :project_emails_disabled?,
+ description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled.'
field :human_time_estimate, GraphQL::Types::String, null: true,
- description: 'Human-readable time estimate of the issue.'
+ description: 'Human-readable time estimate of the issue.'
field :human_total_time_spent, GraphQL::Types::String, null: true,
- description: 'Human-readable total time reported as spent on the issue.'
+ description: 'Human-readable total time reported as spent on the issue.'
field :participants, Types::UserType.connection_type, null: true, complexity: 5,
- description: 'List of participants in the issue.',
- resolver: Resolvers::Users::ParticipantsResolver
+ description: 'List of participants in the issue.',
+ resolver: Resolvers::Users::ParticipantsResolver
field :subscribed, GraphQL::Types::Boolean, method: :subscribed?, null: false, complexity: 5,
- description: 'Indicates the currently logged in user is subscribed to the issue.'
+ description: 'Indicates the currently logged in user is subscribed to the issue.'
field :time_estimate, GraphQL::Types::Int, null: false,
- description: 'Time estimate of the issue.'
+ description: 'Time estimate of the issue.'
field :total_time_spent, GraphQL::Types::Int, null: false,
- description: 'Total time reported as spent on the issue.'
+ description: 'Total time reported as spent on the issue.'
field :closed_at, Types::TimeType, null: true,
- description: 'Timestamp of when the issue was closed.'
+ description: 'Timestamp of when the issue was closed.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the issue was created.'
+ description: 'Timestamp of when the issue was created.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of when the issue was last updated.'
+ description: 'Timestamp of when the issue was last updated.'
field :task_completion_status, Types::TaskCompletionStatus, null: false,
- description: 'Task completion status of the issue.'
+ description: 'Task completion status of the issue.'
field :design_collection, Types::DesignManagement::DesignCollectionType, null: true,
- description: 'Collection of design images associated with this issue.'
+ description: 'Collection of design images associated with this issue.'
field :type, Types::IssueTypeEnum, null: true,
- method: :issue_type,
- description: 'Type of the issue.'
+ method: :issue_type,
+ description: 'Type of the issue.'
field :alert_management_alert,
Types::AlertManagement::AlertType,
@@ -119,31 +119,31 @@ module Types
description: 'Alert associated to this issue.'
field :severity, Types::IssuableSeverityEnum, null: true,
- description: 'Severity level of the incident.'
+ description: 'Severity level of the incident.'
field :moved, GraphQL::Types::Boolean, method: :moved?, null: true,
- description: 'Indicates if issue got moved from other project.'
+ description: 'Indicates if issue got moved from other project.'
field :moved_to, Types::IssueType, null: true,
- description: 'Updated Issue after it got moved to another project.'
+ description: 'Updated Issue after it got moved to another project.'
field :closed_as_duplicate_of, Types::IssueType, null: true,
- description: 'Issue this issue was closed as a duplicate of.'
+ description: 'Issue this issue was closed as a duplicate of.'
field :create_note_email, GraphQL::Types::String, null: true,
- description: 'User specific email address for the issue.'
+ description: 'User specific email address for the issue.'
field :timelogs, Types::TimelogType.connection_type, null: false,
- description: 'Timelogs on the issue.'
+ description: 'Timelogs on the issue.'
field :project_id, GraphQL::Types::Int, null: false, method: :project_id,
- description: 'ID of the issue project.'
+ description: 'ID of the issue project.'
field :customer_relations_contacts, Types::CustomerRelations::ContactType.connection_type, null: true,
- description: 'Customer relations contacts of the issue.'
+ description: 'Customer relations contacts of the issue.'
field :escalation_status, Types::IncidentManagement::EscalationStatusEnum, null: true,
- description: 'Escalation status of the issue.'
+ description: 'Escalation status of the issue.'
markdown_field :title_html, null: true
markdown_field :description_html, null: true
diff --git a/app/graphql/types/issue_type_enum.rb b/app/graphql/types/issue_type_enum.rb
index bc21b802179..1044c2ceea4 100644
--- a/app/graphql/types/issue_type_enum.rb
+++ b/app/graphql/types/issue_type_enum.rb
@@ -11,6 +11,6 @@ module Types
value 'TASK', value: 'task',
description: 'Task issue type. Available only when feature flag `work_items` is enabled.',
- deprecated: { milestone: '15.2', reason: :alpha }
+ alpha: { milestone: '15.2' }
end
end
diff --git a/app/graphql/types/jira_import_type.rb b/app/graphql/types/jira_import_type.rb
index 8477f0b97f0..bcbecff1ad8 100644
--- a/app/graphql/types/jira_import_type.rb
+++ b/app/graphql/types/jira_import_type.rb
@@ -7,19 +7,19 @@ module Types
graphql_name 'JiraImport'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of when the Jira import was created.'
+ description: 'Timestamp of when the Jira import was created.'
field :failed_to_import_count, GraphQL::Types::Int, null: false,
- description: 'Count of issues that failed to import.'
+ description: 'Count of issues that failed to import.'
field :imported_issues_count, GraphQL::Types::Int, null: false,
- description: 'Count of issues that were successfully imported.'
+ description: 'Count of issues that were successfully imported.'
field :jira_project_key, GraphQL::Types::String, null: false,
- description: 'Project key for the imported Jira project.'
+ description: 'Project key for the imported Jira project.'
field :scheduled_at, Types::TimeType, null: true,
- description: 'Timestamp of when the Jira import was scheduled.'
+ description: 'Timestamp of when the Jira import was scheduled.'
field :scheduled_by, Types::UserType, null: true,
- description: 'User that started the Jira import.'
+ description: 'User that started the Jira import.'
field :total_issue_count, GraphQL::Types::Int, null: false,
- description: 'Total count of issues that were attempted to import.'
+ description: 'Total count of issues that were attempted to import.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/jira_user_type.rb b/app/graphql/types/jira_user_type.rb
index aba05385ece..aa070d2c4c9 100644
--- a/app/graphql/types/jira_user_type.rb
+++ b/app/graphql/types/jira_user_type.rb
@@ -7,16 +7,18 @@ module Types
graphql_name 'JiraUser'
field :gitlab_id, GraphQL::Types::Int, null: true,
- description: 'ID of the matched GitLab user.'
+ description: 'ID of the matched GitLab user.'
field :gitlab_name, GraphQL::Types::String, null: true,
- description: 'Name of the matched GitLab user.'
+ description: 'Name of the matched GitLab user.'
field :gitlab_username, GraphQL::Types::String, null: true,
- description: 'Username of the matched GitLab user.'
+ description: 'Username of the matched GitLab user.'
field :jira_account_id, GraphQL::Types::String, null: false,
- description: 'Account ID of the Jira user.'
+ description: 'Account ID of the Jira user.'
field :jira_display_name, GraphQL::Types::String, null: false,
- description: 'Display name of the Jira user.'
- field :jira_email, GraphQL::Types::String, null: true,
+ description: 'Display name of the Jira user.'
+ field :jira_email,
+ GraphQL::Types::String,
+ null: true,
description: 'Email of the Jira user, returned only for users with public emails.'
end
# rubocop: enable Graphql/AuthorizeTypes
diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb
index b5b3e20bcbc..05b703e60af 100644
--- a/app/graphql/types/label_type.rb
+++ b/app/graphql/types/label_type.rb
@@ -9,19 +9,21 @@ module Types
authorize :read_label
field :color, GraphQL::Types::String, null: false,
- description: 'Background color of the label.'
+ description: 'Background color of the label.'
field :created_at, Types::TimeType, null: false,
- description: 'When this label was created.'
- field :description, GraphQL::Types::String, null: true,
+ description: 'When this label was created.'
+ field :description,
+ GraphQL::Types::String,
+ null: true,
description: 'Description of the label (Markdown rendered as HTML for caching).'
field :id, GraphQL::Types::ID, null: false,
- description: 'Label ID.'
+ description: 'Label ID.'
field :text_color, GraphQL::Types::String, null: false,
- description: 'Text color of the label.'
+ description: 'Text color of the label.'
field :title, GraphQL::Types::String, null: false,
- description: 'Content of the label.'
+ description: 'Content of the label.'
field :updated_at, Types::TimeType, null: false,
- description: 'When this label was last updated.'
+ description: 'When this label was last updated.'
markdown_field :description_html, null: true
end
diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb
index 67d0e18b522..edadbcddfb3 100644
--- a/app/graphql/types/member_interface.rb
+++ b/app/graphql/types/member_interface.rb
@@ -5,25 +5,25 @@ module Types
include BaseInterface
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the member.'
+ description: 'ID of the member.'
field :access_level, Types::AccessLevelType, null: true,
- description: 'GitLab::Access level.'
+ description: 'GitLab::Access level.'
field :created_by, Types::UserType, null: true,
- description: 'User that authorized membership.'
+ description: 'User that authorized membership.'
field :created_at, Types::TimeType, null: true,
- description: 'Date and time the membership was created.'
+ description: 'Date and time the membership was created.'
field :updated_at, Types::TimeType, null: true,
- description: 'Date and time the membership was last updated.'
+ description: 'Date and time the membership was last updated.'
field :expires_at, Types::TimeType, null: true,
- description: 'Date and time the membership expires.'
+ description: 'Date and time the membership expires.'
field :user, Types::UserType, null: true,
- description: 'User that is associated with the member object.'
+ description: 'User that is associated with the member object.'
field :merge_request_interaction, Types::UserMergeRequestInteractionType,
null: true,
diff --git a/app/graphql/types/merge_request_connection_type.rb b/app/graphql/types/merge_request_connection_type.rb
index 9596c812c69..f77b66954c1 100644
--- a/app/graphql/types/merge_request_connection_type.rb
+++ b/app/graphql/types/merge_request_connection_type.rb
@@ -3,7 +3,9 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class MergeRequestConnectionType < Types::CountableConnectionType
- field :total_time_to_merge, GraphQL::Types::Float, null: true,
+ field :total_time_to_merge,
+ GraphQL::Types::Float,
+ null: true,
description: 'Total sum of time to merge, in seconds, for the collection of merge requests.'
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index cc3df474bef..d88653f2f8c 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -17,93 +17,98 @@ module Types
present_using MergeRequestPresenter
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of when the merge request was created.'
+ description: 'Timestamp of when the merge request was created.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the merge request (Markdown rendered as HTML for caching).'
+ description: 'Description of the merge request (Markdown rendered as HTML for caching).'
field :diff_head_sha, GraphQL::Types::String, null: true,
- description: 'Diff head SHA of the merge request.'
+ description: 'Diff head SHA of the merge request.'
field :diff_refs, Types::DiffRefsType, null: true,
- description: 'References of the base SHA, the head SHA, and the start SHA for this merge request.'
+ description: 'References of the base SHA, the head SHA, and the start SHA for this merge request.'
field :diff_stats, [Types::DiffStatsType], null: true, calls_gitaly: true,
- description: 'Details about which files were changed in this merge request.' do
+ description: 'Details about which files were changed in this merge request.' do
argument :path, GraphQL::Types::String, required: false, description: 'Specific file path.'
end
field :draft, GraphQL::Types::Boolean, method: :draft?, null: false,
- description: 'Indicates if the merge request is a draft.'
+ description: 'Indicates if the merge request is a draft.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the merge request.'
+ description: 'ID of the merge request.'
field :iid, GraphQL::Types::String, null: false,
- description: 'Internal ID of the merge request.'
+ description: 'Internal ID of the merge request.'
field :merge_when_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
+ description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
field :merged_at, Types::TimeType, null: true, complexity: 5,
- description: 'Timestamp of when the merge request was merged, null if not merged.'
+ description: 'Timestamp of when the merge request was merged, null if not merged.'
field :project, Types::ProjectType, null: false,
- description: 'Alias for target_project.'
+ description: 'Alias for target_project.'
field :project_id, GraphQL::Types::Int, null: false, method: :target_project_id,
- description: 'ID of the merge request project.'
+ description: 'ID of the merge request project.'
field :source_branch, GraphQL::Types::String, null: false,
- description: 'Source branch of the merge request.'
+ description: 'Source branch of the merge request.'
field :source_branch_protected, GraphQL::Types::Boolean, null: false, calls_gitaly: true,
- description: 'Indicates if the source branch is protected.'
+ description: 'Indicates if the source branch is protected.'
field :source_project, Types::ProjectType, null: true,
- description: 'Source project of the merge request.'
+ description: 'Source project of the merge request.'
field :source_project_id, GraphQL::Types::Int, null: true,
- description: 'ID of the merge request source project.'
+ description: 'ID of the merge request source project.'
field :state, MergeRequestStateEnum, null: false,
- description: 'State of the merge request.'
+ description: 'State of the merge request.'
field :target_branch, GraphQL::Types::String, null: false,
- description: 'Target branch of the merge request.'
+ description: 'Target branch of the merge request.'
field :target_project, Types::ProjectType, null: false,
- description: 'Target project of the merge request.'
+ description: 'Target project of the merge request.'
field :target_project_id, GraphQL::Types::Int, null: false,
- description: 'ID of the merge request target project.'
+ description: 'ID of the merge request target project.'
field :title, GraphQL::Types::String, null: false,
- description: 'Title of the merge request.'
+ description: 'Title of the merge request.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of when the merge request was last updated.'
+ description: 'Timestamp of when the merge request was last updated.'
field :allow_collaboration, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if members of the target project can push to the fork.'
+ description: 'Indicates if members of the target project can push to the fork.'
field :default_merge_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Default merge commit message of the merge request.'
+ description: 'Default merge commit message of the merge request.'
field :default_squash_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Default squash commit message of the merge request.'
+ description: 'Default squash commit message of the merge request.'
field :diff_stats_summary, Types::DiffStatsSummaryType, null: true, calls_gitaly: true,
- description: 'Summary of which files were changed in this merge request.'
+ description: 'Summary of which files were changed in this merge request.'
field :diverged_from_target_branch, GraphQL::Types::Boolean,
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.'
+ description: 'Number of downvotes for the merge request.'
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.'
+ 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,
- description: 'Commit SHA of the merge request if merge is in progress.'
+ description: 'Commit SHA of the merge request if merge is in progress.'
field :merge_commit_sha, GraphQL::Types::String, null: true,
- description: 'SHA of the merge request commit (set once merged).'
+ description: 'SHA of the merge request commit (set once merged).'
field :merge_error, GraphQL::Types::String, null: true,
- description: 'Error message due to a merge error.'
+ description: 'Error message due to a merge error.'
field :merge_ongoing, GraphQL::Types::Boolean, method: :merge_ongoing?, null: false,
- description: 'Indicates if a merge is currently occurring.'
+ description: 'Indicates if a merge is currently occurring.'
field :merge_status, GraphQL::Types::String, method: :public_merge_status, null: true,
- description: 'Status of the merge request.',
- deprecated: { reason: :renamed, replacement: 'MergeRequest.mergeStatusEnum', milestone: '14.0' }
+ description: 'Status of the merge request.',
+ deprecated: { reason: :renamed, replacement: 'MergeRequest.mergeStatusEnum', milestone: '14.0' }
field :merge_status_enum, ::Types::MergeRequests::MergeStatusEnum,
method: :public_merge_status, null: true,
description: 'Merge status of the merge request.'
+
+ field :detailed_merge_status, ::Types::MergeRequests::DetailedMergeStatusEnum, method: :detailed_merge_status, null: true,
+ calls_gitaly: true,
+ description: 'Detailed merge status of the merge request.', alpha: { milestone: '15.3' }
+
field :mergeable_discussions_state, GraphQL::Types::Boolean, null: true,
- calls_gitaly: true,
- description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.'
+ calls_gitaly: true,
+ description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.'
field :rebase_commit_sha, GraphQL::Types::String, null: true,
- description: 'Rebase commit SHA of the merge request.'
+ description: 'Rebase commit SHA of the merge request.'
field :rebase_in_progress, GraphQL::Types::Boolean, method: :rebase_in_progress?, null: false, calls_gitaly: true,
- description: 'Indicates if there is a rebase currently in progress for the merge request.'
+ description: 'Indicates if there is a rebase currently in progress for the merge request.'
field :should_be_rebased, GraphQL::Types::Boolean, method: :should_be_rebased?, null: false, calls_gitaly: true,
- description: 'Indicates if the merge request will be rebased.'
+ description: 'Indicates if the merge request will be rebased.'
field :should_remove_source_branch, GraphQL::Types::Boolean, method: :should_remove_source_branch?, null: true,
- description: 'Indicates if the source branch of the merge request will be deleted after merge.'
+ description: 'Indicates if the source branch of the merge request will be deleted after merge.'
field :source_branch_exists, GraphQL::Types::Boolean,
null: false, calls_gitaly: true,
method: :source_branch_exists?,
@@ -113,18 +118,18 @@ module Types
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.'
+ description: 'Number of upvotes for the merge request.'
field :user_discussions_count, GraphQL::Types::Int, null: true,
- description: 'Number of user discussions in the merge request.',
- resolver: Resolvers::UserDiscussionsCountResolver
+ description: 'Number of user discussions in the merge request.',
+ resolver: Resolvers::UserDiscussionsCountResolver
field :user_notes_count, GraphQL::Types::Int, null: true,
- description: 'User notes count of the merge request.',
- resolver: Resolvers::UserNotesCountResolver
+ description: 'User notes count of the merge request.',
+ resolver: Resolvers::UserNotesCountResolver
field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the merge request.'
+ description: 'Web URL of the merge request.'
field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline,
- description: 'Pipeline running on the branch HEAD of the merge request.'
+ description: 'Pipeline running on the branch HEAD of the merge request.'
field :pipelines,
null: true,
description: 'Pipelines for the merge request. Note: for performance reasons, no more than the most recent 500 pipelines will be returned.',
@@ -136,72 +141,72 @@ module Types
complexity: 5,
description: 'Assignees of the merge request.'
field :author, Types::MergeRequests::AuthorType, null: true,
- description: 'User who created this merge request.'
+ description: 'User who created this merge request.'
field :discussion_locked, GraphQL::Types::Boolean,
description: 'Indicates if comments on the merge request are locked to members only.',
null: false
field :human_time_estimate, GraphQL::Types::String, null: true,
- description: 'Human-readable time estimate of the merge request.'
+ 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.'
+ 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.'
+ description: 'Labels of the merge request.'
field :milestone, Types::MilestoneType, null: true,
- description: 'Milestone of the merge request.'
+ description: 'Milestone of the merge request.'
field :participants, Types::MergeRequests::ParticipantType.connection_type, null: true, complexity: 15,
- description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.',
- resolver: Resolvers::Users::ParticipantsResolver
+ description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.',
+ resolver: Resolvers::Users::ParticipantsResolver
field :reference, GraphQL::Types::String, null: false, method: :to_reference,
- description: 'Internal reference of the merge request. Returned in shortened format by default.' do
+ description: 'Internal reference of the merge request. Returned in shortened format by default.' do
argument :full, GraphQL::Types::Boolean, required: false, default_value: false,
- description: 'Boolean option specifying whether the reference should be returned in full.'
+ description: 'Boolean option specifying whether the reference should be returned in full.'
end
field :auto_merge_enabled, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if auto merge is enabled for the merge request.'
+ description: 'Indicates if auto merge is enabled for the merge request.'
field :commit_count, GraphQL::Types::Int, null: true, method: :commits_count,
- description: 'Number of commits in the merge request.'
+ description: 'Number of commits in the merge request.'
field :conflicts, GraphQL::Types::Boolean, null: false, method: :cannot_be_merged?,
- description: 'Indicates if the merge request has conflicts.'
+ description: 'Indicates if the merge request has conflicts.'
field :reviewers,
type: Types::MergeRequests::ReviewerType.connection_type,
null: true,
complexity: 5,
description: 'Users from whom a review has been requested.'
field :subscribed, GraphQL::Types::Boolean, method: :subscribed?, null: false, complexity: 5,
- description: 'Indicates if the currently logged in user is subscribed to this merge request.'
+ description: 'Indicates if the currently logged in user is subscribed to this merge request.'
field :task_completion_status, Types::TaskCompletionStatus, null: false,
- description: Types::TaskCompletionStatus.description
+ description: Types::TaskCompletionStatus.description
field :time_estimate, GraphQL::Types::Int, null: false,
- description: 'Time estimate of the merge request.'
+ description: 'Time estimate of the merge request.'
field :total_time_spent, GraphQL::Types::Int, null: false,
- description: 'Total time reported as spent on the merge request.'
+ description: 'Total time reported as spent on the merge request.'
field :approved_by, Types::UserType.connection_type, null: true,
- description: 'Users who approved the merge request.', method: :approved_by_users
+ description: 'Users who approved the merge request.', method: :approved_by_users
field :auto_merge_strategy, GraphQL::Types::String, null: true,
- description: 'Selected auto merge strategy.'
+ description: 'Selected auto merge strategy.'
field :available_auto_merge_strategies, [GraphQL::Types::String], null: true, calls_gitaly: true,
- description: 'Array of available auto merge strategies.'
+ description: 'Array of available auto merge strategies.'
field :commits, Types::CommitType.connection_type, null: true,
- calls_gitaly: true, description: 'Merge request commits.'
+ calls_gitaly: true, description: 'Merge request commits.'
field :committers, Types::UserType.connection_type, null: true, complexity: 5,
- calls_gitaly: true, description: 'Users who have added commits to the merge request.'
+ calls_gitaly: true, description: 'Users who have added commits to the merge request.'
field :commits_without_merge_commits, Types::CommitType.connection_type, null: true,
- calls_gitaly: true, description: 'Merge request commits excluding merge commits.'
+ calls_gitaly: true, description: 'Merge request commits excluding merge commits.'
field :has_ci, GraphQL::Types::Boolean, null: false, method: :has_ci?,
- description: 'Indicates if the merge request has CI.'
+ description: 'Indicates if the merge request has CI.'
field :merge_user, Types::UserType, null: true,
- description: 'User who merged this merge request or set it to merge when pipeline succeeds.'
+ description: 'User who merged this merge request or set it to merge when pipeline succeeds.'
field :mergeable, GraphQL::Types::Boolean, null: false, method: :mergeable?, calls_gitaly: true,
- description: 'Indicates if the merge request is mergeable.'
+ description: 'Indicates if the merge request is mergeable.'
field :security_auto_fix, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the merge request is created by @GitLab-Security-Bot.'
+ description: 'Indicates if the merge request is created by @GitLab-Security-Bot.'
field :squash, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if squash on merge is enabled.'
+ description: 'Indicates if squash on merge is enabled.'
field :squash_on_merge, GraphQL::Types::Boolean, null: false, method: :squash_on_merge?,
- description: 'Indicates if squash on merge is enabled.'
+ description: 'Indicates if squash on merge is enabled.'
field :timelogs, Types::TimelogType.connection_type, null: false,
- description: 'Timelogs on the merge request.'
+ description: 'Timelogs on the merge request.'
markdown_field :title_html, null: true
markdown_field :description_html, null: true
diff --git a/app/graphql/types/merge_requests/detailed_merge_status_enum.rb b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
new file mode 100644
index 00000000000..58104159303
--- /dev/null
+++ b/app/graphql/types/merge_requests/detailed_merge_status_enum.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Types
+ module MergeRequests
+ class DetailedMergeStatusEnum < BaseEnum
+ graphql_name 'DetailedMergeStatus'
+ description 'Detailed representation of whether a GitLab merge request can be merged.'
+
+ value 'UNCHECKED',
+ value: :unchecked,
+ description: 'Merge status has not been checked.'
+ value 'CHECKING',
+ value: :checking,
+ description: 'Currently checking for mergeability.'
+ value 'MERGEABLE',
+ value: :mergeable,
+ description: 'Branch can be merged.'
+ value 'BROKEN_STATUS',
+ value: :broken_status,
+ description: 'Can not merge the source into the target branch, potential conflict.'
+ value 'CI_MUST_PASS',
+ value: :ci_must_pass,
+ description: 'Pipeline must succeed before merging.'
+ value 'DISCUSSIONS_NOT_RESOLVED',
+ value: :discussions_not_resolved,
+ description: 'Discussions must be resolved before merging.'
+ value 'DRAFT_STATUS',
+ value: :draft_status,
+ description: 'Merge request must not be draft before merging.'
+ value 'NOT_OPEN',
+ value: :not_open,
+ description: 'Merge request must be open before merging.'
+ value 'NOT_APPROVED',
+ value: :not_approved,
+ description: 'Merge request must be approved before merging.'
+ value 'BLOCKED_STATUS',
+ value: :merge_request_blocked,
+ description: 'Merge request is blocked by another merge request.'
+ value 'POLICIES_DENIED',
+ value: :policies_denied,
+ description: 'There are denied policies for the merge request.'
+ end
+ end
+end
diff --git a/app/graphql/types/metadata/kas_type.rb b/app/graphql/types/metadata/kas_type.rb
index 6a8d54b6c7d..e29635aedcf 100644
--- a/app/graphql/types/metadata/kas_type.rb
+++ b/app/graphql/types/metadata/kas_type.rb
@@ -8,11 +8,11 @@ module Types
authorize :read_instance_metadata
field :enabled, GraphQL::Types::Boolean, null: false,
- description: 'Indicates whether the Kubernetes Agent Server is enabled.'
+ description: 'Indicates whether the Kubernetes Agent Server is enabled.'
field :external_url, GraphQL::Types::String, null: true,
- description: 'URL used by the Agents to communicate with KAS.'
+ description: 'URL used by the Agents to communicate with KAS.'
field :version, GraphQL::Types::String, null: true,
- description: 'KAS version.'
+ description: 'KAS version.'
end
end
end
diff --git a/app/graphql/types/metadata_type.rb b/app/graphql/types/metadata_type.rb
index 6fb141a50c9..b00fcfd38ad 100644
--- a/app/graphql/types/metadata_type.rb
+++ b/app/graphql/types/metadata_type.rb
@@ -7,10 +7,10 @@ module Types
authorize :read_instance_metadata
field :kas, ::Types::Metadata::KasType, null: false,
- description: 'Metadata about KAS.'
+ description: 'Metadata about KAS.'
field :revision, GraphQL::Types::String, null: false,
- description: 'Revision.'
+ description: 'Revision.'
field :version, GraphQL::Types::String, null: false,
- description: 'Version.'
+ description: 'Version.'
end
end
diff --git a/app/graphql/types/metrics/dashboard_type.rb b/app/graphql/types/metrics/dashboard_type.rb
index 04cac55894e..5570b904d79 100644
--- a/app/graphql/types/metrics/dashboard_type.rb
+++ b/app/graphql/types/metrics/dashboard_type.rb
@@ -8,12 +8,16 @@ module Types
graphql_name 'MetricsDashboard'
field :path, GraphQL::Types::String, null: true,
- description: 'Path to a file with the dashboard definition.'
+ description: 'Path to a file with the dashboard definition.'
- field :schema_validation_warnings, [GraphQL::Types::String], null: true,
+ field :schema_validation_warnings,
+ [GraphQL::Types::String],
+ null: true,
description: 'Dashboard schema validation warnings.'
- field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true,
+ field :annotations,
+ Types::Metrics::Dashboards::AnnotationType.connection_type,
+ null: true,
description: 'Annotations added to the dashboard.',
resolver: Resolvers::Metrics::Dashboards::AnnotationResolver
diff --git a/app/graphql/types/metrics/dashboards/annotation_type.rb b/app/graphql/types/metrics/dashboards/annotation_type.rb
index 0621cf4d674..ec479078272 100644
--- a/app/graphql/types/metrics/dashboards/annotation_type.rb
+++ b/app/graphql/types/metrics/dashboards/annotation_type.rb
@@ -8,20 +8,22 @@ module Types
authorize :read_metrics_dashboard_annotation
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the annotation.'
+ description: 'Description of the annotation.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the annotation.'
+ description: 'ID of the annotation.'
- field :panel_id, GraphQL::Types::String, null: true,
+ field :panel_id,
+ GraphQL::Types::String,
+ null: true,
description: 'ID of a dashboard panel to which the annotation should be scoped.',
method: :panel_xid
field :starting_at, Types::TimeType, null: true,
- description: 'Timestamp marking start of annotated time span.'
+ description: 'Timestamp marking start of annotated time span.'
field :ending_at, Types::TimeType, null: true,
- description: 'Timestamp marking end of annotated time span.'
+ description: 'Timestamp marking end of annotated time span.'
end
end
end
diff --git a/app/graphql/types/milestone_stats_type.rb b/app/graphql/types/milestone_stats_type.rb
index 6d8b7deb8e7..36448c4987b 100644
--- a/app/graphql/types/milestone_stats_type.rb
+++ b/app/graphql/types/milestone_stats_type.rb
@@ -7,10 +7,14 @@ module Types
authorize :read_milestone
- field :total_issues_count, GraphQL::Types::Int, null: true,
+ field :total_issues_count,
+ GraphQL::Types::Int,
+ null: true,
description: 'Total number of issues associated with the milestone.'
- field :closed_issues_count, GraphQL::Types::Int, null: true,
+ field :closed_issues_count,
+ GraphQL::Types::Int,
+ null: true,
description: 'Number of closed issues associated with the milestone.'
end
end
diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb
index 7741fd723f0..447528917f0 100644
--- a/app/graphql/types/milestone_type.rb
+++ b/app/graphql/types/milestone_type.rb
@@ -12,52 +12,52 @@ module Types
alias_method :milestone, :object
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the milestone.'
+ description: 'ID of the milestone.'
field :iid, GraphQL::Types::ID, null: false,
- description: "Internal ID of the milestone."
+ description: "Internal ID of the milestone."
field :title, GraphQL::Types::String, null: false,
- description: 'Title of the milestone.'
+ description: 'Title of the milestone.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the milestone.'
+ description: 'Description of the milestone.'
field :state, Types::MilestoneStateEnum, null: false,
- description: 'State of the milestone.'
+ description: 'State of the milestone.'
field :expired, GraphQL::Types::Boolean, null: false,
- description: 'Expired state of the milestone (a milestone is expired when the due date is past the current date). Defaults to `false` when due date has not been set.'
+ description: 'Expired state of the milestone (a milestone is expired when the due date is past the current date). Defaults to `false` when due date has not been set.'
field :web_path, GraphQL::Types::String, null: false, method: :milestone_path,
- description: 'Web path of the milestone.'
+ description: 'Web path of the milestone.'
field :due_date, Types::TimeType, null: true,
- description: 'Timestamp of the milestone due date.'
+ description: 'Timestamp of the milestone due date.'
field :start_date, Types::TimeType, null: true,
- description: 'Timestamp of the milestone start date.'
+ description: 'Timestamp of the milestone start date.'
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of milestone creation.'
+ description: 'Timestamp of milestone creation.'
field :updated_at, Types::TimeType, null: false,
- description: 'Timestamp of last milestone update.'
+ description: 'Timestamp of last milestone update.'
field :project_milestone, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if milestone is at project level.',
- method: :project_milestone?
+ description: 'Indicates if milestone is at project level.',
+ method: :project_milestone?
field :group_milestone, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if milestone is at group level.',
- method: :group_milestone?
+ description: 'Indicates if milestone is at group level.',
+ method: :group_milestone?
field :subgroup_milestone, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if milestone is at subgroup level.',
- method: :subgroup_milestone?
+ description: 'Indicates if milestone is at subgroup level.',
+ method: :subgroup_milestone?
field :stats, Types::MilestoneStatsType, null: true,
- description: 'Milestone statistics.'
+ description: 'Milestone statistics.'
field :releases, ::Types::ReleaseType.connection_type,
null: true,
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 46ab3f3f432..499c2e786bf 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -37,8 +37,8 @@ module Types
mount_mutation Mutations::Clusters::AgentTokens::Create
mount_mutation Mutations::Clusters::AgentTokens::Revoke
mount_mutation Mutations::Commits::Create, calls_gitaly: true
- mount_mutation Mutations::CustomEmoji::Create, feature_flag: :custom_emoji
- mount_mutation Mutations::CustomEmoji::Destroy, feature_flag: :custom_emoji
+ mount_mutation Mutations::CustomEmoji::Create, _deprecated_feature_flag: :custom_emoji
+ mount_mutation Mutations::CustomEmoji::Destroy, _deprecated_feature_flag: :custom_emoji
mount_mutation Mutations::CustomerRelations::Contacts::Create
mount_mutation Mutations::CustomerRelations::Contacts::Update
mount_mutation Mutations::CustomerRelations::Organizations::Create
@@ -72,10 +72,8 @@ module Types
mount_mutation Mutations::MergeRequests::SetSubscription
mount_mutation Mutations::MergeRequests::SetDraft, calls_gitaly: true
mount_mutation Mutations::MergeRequests::SetAssignees
+ mount_mutation Mutations::MergeRequests::SetReviewers
mount_mutation Mutations::MergeRequests::ReviewerRereview
- mount_mutation Mutations::MergeRequests::RequestAttention
- mount_mutation Mutations::MergeRequests::RemoveAttentionRequest
- mount_mutation Mutations::MergeRequests::ToggleAttentionRequested
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
@@ -94,6 +92,7 @@ module Types
mount_mutation Mutations::Terraform::State::Delete
mount_mutation Mutations::Terraform::State::Lock
mount_mutation Mutations::Terraform::State::Unlock
+ mount_mutation Mutations::Timelogs::Create
mount_mutation Mutations::Timelogs::Delete
mount_mutation Mutations::Todos::Create
mount_mutation Mutations::Todos::MarkDone
@@ -129,6 +128,7 @@ module Types
mount_mutation Mutations::Ci::JobTokenScope::RemoveProject
mount_mutation Mutations::Ci::Runner::Update
mount_mutation Mutations::Ci::Runner::Delete
+ mount_mutation Mutations::Ci::Runner::BulkDelete, alpha: { milestone: '15.3' }
mount_mutation Mutations::Ci::RunnersRegistrationToken::Reset
mount_mutation Mutations::Namespace::PackageSettings::Update
mount_mutation Mutations::Groups::Update
@@ -139,17 +139,18 @@ module Types
mount_mutation Mutations::Packages::DestroyFiles
mount_mutation Mutations::Packages::Cleanup::Policy::Update
mount_mutation Mutations::Echo
- mount_mutation Mutations::WorkItems::Create, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::CreateFromTask, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::Delete, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::DeleteTask, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::Update, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::UpdateWidgets, deprecated: { milestone: '15.1', reason: :alpha }
- mount_mutation Mutations::WorkItems::UpdateTask, deprecated: { milestone: '15.1', reason: :alpha }
+ mount_mutation Mutations::WorkItems::Create, alpha: { milestone: '15.1' }
+ mount_mutation Mutations::WorkItems::CreateFromTask, alpha: { milestone: '15.1' }
+ 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
mount_mutation Mutations::Pages::MarkOnboardingComplete
mount_mutation Mutations::SavedReplies::Destroy
+ mount_mutation Mutations::Uploads::Delete
end
end
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
index de6a078c6ef..0f634e7c2d3 100644
--- a/app/graphql/types/namespace_type.rb
+++ b/app/graphql/types/namespace_type.rb
@@ -7,38 +7,45 @@ module Types
authorize :read_namespace
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the namespace.'
+ description: 'ID of the namespace.'
field :full_name, GraphQL::Types::String, null: false,
- description: 'Full name of the namespace.'
+ description: 'Full name of the namespace.'
field :full_path, GraphQL::Types::ID, null: false,
- description: 'Full path of the namespace.'
+ description: 'Full path of the namespace.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the namespace.'
+ description: 'Name of the namespace.'
field :path, GraphQL::Types::String, null: false,
- description: 'Path of the namespace.'
+ description: 'Path of the namespace.'
- field :cross_project_pipeline_available, GraphQL::Types::Boolean, null: false,
+ field :cross_project_pipeline_available,
+ GraphQL::Types::Boolean,
+ null: false,
resolver_method: :cross_project_pipeline_available?,
description: 'Indicates if the cross_project_pipeline feature is available for the namespace.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the namespace.'
+ description: 'Description of the namespace.'
- field :lfs_enabled, GraphQL::Types::Boolean, null: true, method: :lfs_enabled?,
+ field :lfs_enabled,
+ GraphQL::Types::Boolean,
+ null: true,
+ method: :lfs_enabled?,
description: 'Indicates if Large File Storage (LFS) is enabled for namespace.'
- field :request_access_enabled, GraphQL::Types::Boolean, null: true,
+ field :request_access_enabled,
+ GraphQL::Types::Boolean,
+ null: true,
description: 'Indicates if users can request access to namespace.'
field :visibility, GraphQL::Types::String, null: true,
- description: 'Visibility of the namespace.'
+ description: 'Visibility of the namespace.'
field :root_storage_statistics, Types::RootStorageStatisticsType,
null: true,
description: 'Aggregated storage statistics of the namespace. Only available for root namespaces.'
field :projects, Types::ProjectType.connection_type, null: false,
- description: 'Projects within this namespace.',
- resolver: ::Resolvers::NamespaceProjectsResolver
+ description: 'Projects within this namespace.',
+ resolver: ::Resolvers::NamespaceProjectsResolver
field :package_settings,
Types::Namespace::PackageSettingsType,
@@ -50,8 +57,18 @@ module Types
null: true,
description: "Shared runners availability for the namespace and its descendants."
+ field :timelog_categories,
+ Types::TimeTracking::TimelogCategoryType.connection_type,
+ null: true,
+ description: "Timelog categories for the namespace.",
+ alpha: { milestone: '15.3' }
+
markdown_field :description_html, null: true
+ def timelog_categories
+ object.timelog_categories if Feature.enabled?(:timelog_categories)
+ end
+
def cross_project_pipeline_available?
object.licensed_feature_available?(:cross_project_pipelines)
end
diff --git a/app/graphql/types/notes/diff_image_position_input_type.rb b/app/graphql/types/notes/diff_image_position_input_type.rb
index d535dea2e07..8c82f4fec2e 100644
--- a/app/graphql/types/notes/diff_image_position_input_type.rb
+++ b/app/graphql/types/notes/diff_image_position_input_type.rb
@@ -5,13 +5,21 @@ module Types
class DiffImagePositionInputType < DiffPositionBaseInputType
graphql_name 'DiffImagePositionInput'
- argument :height, GraphQL::Types::Int, required: true,
+ argument :height,
+ GraphQL::Types::Int,
+ required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :height)
- argument :width, GraphQL::Types::Int, required: true,
+ argument :width,
+ GraphQL::Types::Int,
+ required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :width)
- argument :x, GraphQL::Types::Int, required: true,
+ argument :x,
+ GraphQL::Types::Int,
+ required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :x)
- argument :y, GraphQL::Types::Int, required: true,
+ argument :y,
+ GraphQL::Types::Int,
+ required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :y)
end
end
diff --git a/app/graphql/types/notes/diff_position_base_input_type.rb b/app/graphql/types/notes/diff_position_base_input_type.rb
index 2780dbab573..433cd442235 100644
--- a/app/graphql/types/notes/diff_position_base_input_type.rb
+++ b/app/graphql/types/notes/diff_position_base_input_type.rb
@@ -4,11 +4,11 @@ module Types
module Notes
class DiffPositionBaseInputType < BaseInputObject
argument :base_sha, GraphQL::Types::String, required: false,
- description: copy_field_description(Types::DiffRefsType, :base_sha)
+ description: copy_field_description(Types::DiffRefsType, :base_sha)
argument :head_sha, GraphQL::Types::String, required: true,
- description: copy_field_description(Types::DiffRefsType, :head_sha)
+ description: copy_field_description(Types::DiffRefsType, :head_sha)
argument :start_sha, GraphQL::Types::String, required: true,
- description: copy_field_description(Types::DiffRefsType, :start_sha)
+ description: copy_field_description(Types::DiffRefsType, :start_sha)
argument :paths,
Types::DiffPathsInputType,
diff --git a/app/graphql/types/notes/diff_position_input_type.rb b/app/graphql/types/notes/diff_position_input_type.rb
index ccde4188f29..5823a4f19cc 100644
--- a/app/graphql/types/notes/diff_position_input_type.rb
+++ b/app/graphql/types/notes/diff_position_input_type.rb
@@ -6,9 +6,9 @@ module Types
graphql_name 'DiffPositionInput'
argument :new_line, GraphQL::Types::Int, required: false,
- description: "#{copy_field_description(Types::Notes::DiffPositionType, :new_line)} Please see the [REST API Documentation](https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff) for more information on how to use this field."
+ description: "#{copy_field_description(Types::Notes::DiffPositionType, :new_line)} Please see the [REST API Documentation](https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff) for more information on how to use this field."
argument :old_line, GraphQL::Types::Int, required: false,
- description: "#{copy_field_description(Types::Notes::DiffPositionType, :old_line)} Please see the [REST API Documentation](https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff) for more information on how to use this field."
+ description: "#{copy_field_description(Types::Notes::DiffPositionType, :old_line)} Please see the [REST API Documentation](https://docs.gitlab.com/ee/api/discussions.html#create-a-new-thread-in-the-merge-request-diff) for more information on how to use this field."
end
end
end
diff --git a/app/graphql/types/notes/diff_position_type.rb b/app/graphql/types/notes/diff_position_type.rb
index 531bd0edac0..dd343cf45e4 100644
--- a/app/graphql/types/notes/diff_position_type.rb
+++ b/app/graphql/types/notes/diff_position_type.rb
@@ -7,33 +7,35 @@ module Types
class DiffPositionType < BaseObject
graphql_name 'DiffPosition'
- field :diff_refs, Types::DiffRefsType, null: false,
+ field :diff_refs,
+ Types::DiffRefsType,
+ null: false,
description: 'Information about the branch, HEAD, and base at the time of commenting.'
field :file_path, GraphQL::Types::String, null: false,
- description: 'Path of the file that was changed.'
+ description: 'Path of the file that was changed.'
field :new_path, GraphQL::Types::String, null: true,
- description: 'Path of the file on the HEAD SHA.'
+ description: 'Path of the file on the HEAD SHA.'
field :old_path, GraphQL::Types::String, null: true,
- description: 'Path of the file on the start SHA.'
+ description: 'Path of the file on the start SHA.'
field :position_type, Types::Notes::PositionTypeEnum, null: false,
- description: 'Type of file the position refers to.'
+ description: 'Type of file the position refers to.'
# Fields for text positions
field :new_line, GraphQL::Types::Int, null: true,
- description: 'Line on HEAD SHA that was changed.'
+ description: 'Line on HEAD SHA that was changed.'
field :old_line, GraphQL::Types::Int, null: true,
- description: 'Line on start SHA that was changed.'
+ description: 'Line on start SHA that was changed.'
# Fields for image positions
field :height, GraphQL::Types::Int, null: true,
- description: 'Total height of the image.'
+ description: 'Total height of the image.'
field :width, GraphQL::Types::Int, null: true,
- description: 'Total width of the image.'
+ description: 'Total width of the image.'
field :x, GraphQL::Types::Int, null: true,
- description: 'X position of the note.'
+ description: 'X position of the note.'
field :y, GraphQL::Types::Int, null: true,
- description: 'Y position of the note.'
+ description: 'Y position of the note.'
def old_line
object.old_line if object.on_text?
diff --git a/app/graphql/types/notes/discussion_type.rb b/app/graphql/types/notes/discussion_type.rb
index 89778b2a99a..5e40c8008a9 100644
--- a/app/graphql/types/notes/discussion_type.rb
+++ b/app/graphql/types/notes/discussion_type.rb
@@ -12,15 +12,15 @@ module Types
implements(Types::ResolvableInterface)
field :created_at, Types::TimeType, null: false,
- description: "Timestamp of the discussion's creation."
+ description: "Timestamp of the discussion's creation."
field :id, DiscussionID, null: false,
- description: "ID of this discussion."
+ description: "ID of this discussion."
field :noteable, Types::NoteableType, null: true,
- description: 'Object which the discussion belongs to.'
+ description: 'Object which the discussion belongs to.'
field :notes, Types::Notes::NoteType.connection_type, null: false,
- description: 'All notes in the discussion.'
+ description: 'All notes in the discussion.'
field :reply_id, DiscussionID, null: false,
- description: 'ID used to reply to this discussion.'
+ description: 'ID used to reply to this discussion.'
# DiscussionID.coerce_result is suitable here, but will always mark this
# as being a 'Discussion'. Using `GlobalId.build` guarantees that we get
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index 32f3ff7f556..c254460a51f 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -12,7 +12,7 @@ module Types
implements(Types::ResolvableInterface)
field :id, ::Types::GlobalIDType[::Note], null: false,
- description: 'ID of the note.'
+ description: 'ID of the note.'
field :project, Types::ProjectType,
null: true,
@@ -25,7 +25,9 @@ module Types
field :system, GraphQL::Types::Boolean,
null: false,
description: 'Indicates whether this note was created by the system or by a user.'
- field :system_note_icon_name, GraphQL::Types::String, null: true,
+ field :system_note_icon_name,
+ GraphQL::Types::String,
+ null: true,
description: 'Name of the icon corresponding to a system note.'
field :body, GraphQL::Types::String,
@@ -34,16 +36,26 @@ module Types
description: 'Content of the note.'
field :confidential, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if this note is confidential.',
- method: :confidential?
+ description: 'Indicates if this note is confidential.',
+ method: :confidential?,
+ deprecated: {
+ reason: :renamed,
+ replacement: 'internal',
+ milestone: '15.3'
+ }
+
+ field :internal, GraphQL::Types::Boolean, null: true,
+ description: 'Indicates if this note is internal.',
+ method: :confidential?
+
field :created_at, Types::TimeType, null: false,
- description: 'Timestamp of the note creation.'
+ description: 'Timestamp of the note creation.'
field :discussion, Types::Notes::DiscussionType, null: true,
- description: 'Discussion this note is a part of.'
+ description: 'Discussion this note is a part of.'
field :position, Types::Notes::DiffPositionType, null: true,
- description: 'Position of this note on a diff.'
+ description: 'Position of this note on a diff.'
field :updated_at, Types::TimeType, null: false,
- description: "Timestamp of the note's last activity."
+ description: "Timestamp of the note's last activity."
field :url, GraphQL::Types::String,
null: true,
description: 'URL to view this Note in the Web UI.'
diff --git a/app/graphql/types/packages/package_base_type.rb b/app/graphql/types/packages/package_base_type.rb
index 06ccde94cd4..2dc4a2a2bb6 100644
--- a/app/graphql/types/packages/package_base_type.rb
+++ b/app/graphql/types/packages/package_base_type.rb
@@ -10,12 +10,12 @@ module Types
authorize :read_package
- field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
- description: 'ID of the package.'
+ field :id, ::Types::GlobalIDType[::Packages::Package], null: false, description: 'ID of the package.'
field :can_destroy, GraphQL::Types::Boolean, null: false, description: 'Whether the user can destroy the package.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
- field :metadata, Types::Packages::MetadataType, null: true,
+ field :metadata, Types::Packages::MetadataType,
+ null: true,
description: 'Package metadata.'
field :name, GraphQL::Types::String, null: false, description: 'Name of the package.'
field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
index ae57e103f40..0413177ef14 100644
--- a/app/graphql/types/packages/package_details_type.rb
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -11,7 +11,7 @@ module Types
authorize :read_package
field :versions, ::Types::Packages::PackageBaseType.connection_type, null: true,
- description: 'Other versions of the package.'
+ description: 'Other versions of the package.'
field :package_files, Types::Packages::PackageFileType.connection_type, null: true, method: :installable_package_files, description: 'Package files.'
diff --git a/app/graphql/types/packages/package_file_type.rb b/app/graphql/types/packages/package_file_type.rb
index b058dc0ab0d..3ee0d983745 100644
--- a/app/graphql/types/packages/package_file_type.rb
+++ b/app/graphql/types/packages/package_file_type.rb
@@ -11,7 +11,7 @@ module Types
field :download_path, GraphQL::Types::String, null: false, description: 'Download path of the package file.'
field :file_md5, GraphQL::Types::String, null: true, description: 'Md5 of the package file.'
field :file_metadata, Types::Packages::FileMetadataType, null: true,
- description: 'File metadata.'
+ description: 'File metadata.'
field :file_name, GraphQL::Types::String, null: false, description: 'Name of the package file.'
field :file_sha1, GraphQL::Types::String, null: true, description: 'Sha1 of the package file.'
field :file_sha256, GraphQL::Types::String, null: true, description: 'Sha256 of the package file.'
diff --git a/app/graphql/types/permission_types/group_enum.rb b/app/graphql/types/permission_types/group_enum.rb
index 8b0fee8898c..f636d43790f 100644
--- a/app/graphql/types/permission_types/group_enum.rb
+++ b/app/graphql/types/permission_types/group_enum.rb
@@ -7,7 +7,8 @@ module Types
description 'User permission on groups'
value 'CREATE_PROJECTS', value: :create_projects, description: 'Groups where the user can create projects.'
- value 'TRANSFER_PROJECTS', value: :transfer_projects,
+ value 'TRANSFER_PROJECTS',
+ value: :transfer_projects,
description: 'Groups where the user can transfer projects to.'
end
end
diff --git a/app/graphql/types/project_invitation_type.rb b/app/graphql/types/project_invitation_type.rb
index b76f05e289f..b5760a911be 100644
--- a/app/graphql/types/project_invitation_type.rb
+++ b/app/graphql/types/project_invitation_type.rb
@@ -12,7 +12,7 @@ module Types
authorize :admin_project
field :project, Types::ProjectType, null: true,
- description: 'Project ID for the project of the invitation.'
+ description: 'Project ID for the project of the invitation.'
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.source_id).find
diff --git a/app/graphql/types/project_member_type.rb b/app/graphql/types/project_member_type.rb
index 1f00df84641..2eba0d2dea2 100644
--- a/app/graphql/types/project_member_type.rb
+++ b/app/graphql/types/project_member_type.rb
@@ -12,7 +12,7 @@ module Types
authorize :read_project
field :project, Types::ProjectType, null: true,
- description: 'Project that User is a member of.'
+ description: 'Project that User is a member of.'
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.source_id).find
diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb
index 5ab3cc33e85..c43baf1280b 100644
--- a/app/graphql/types/project_statistics_type.rb
+++ b/app/graphql/types/project_statistics_type.rb
@@ -7,27 +7,31 @@ module Types
authorize :read_statistics
field :commit_count, GraphQL::Types::Float, null: false,
- description: 'Commit count of the project.'
+ description: 'Commit count of the project.'
field :build_artifacts_size, GraphQL::Types::Float, null: false,
- description: 'Build artifacts size of the project in bytes.'
- field :lfs_objects_size, GraphQL::Types::Float, null: false,
+ description: 'Build artifacts size of the project in bytes.'
+ field :lfs_objects_size,
+ GraphQL::Types::Float,
+ null: false,
description: 'Large File Storage (LFS) object size of the project in bytes.'
field :packages_size, GraphQL::Types::Float, null: false,
- description: 'Packages size of the project in bytes.'
+ description: 'Packages size of the project in bytes.'
field :pipeline_artifacts_size, GraphQL::Types::Float, null: true,
- description: 'CI Pipeline artifacts size in bytes.'
+ description: 'CI Pipeline artifacts size in bytes.'
field :repository_size, GraphQL::Types::Float, null: false,
- description: 'Repository size of the project in bytes.'
+ description: 'Repository size of the project in bytes.'
field :snippets_size, GraphQL::Types::Float, null: true,
- description: 'Snippets size of the project in bytes.'
+ description: 'Snippets size of the project in bytes.'
field :storage_size, GraphQL::Types::Float, null: false,
- description: 'Storage size of the project in bytes.'
+ description: 'Storage size of the project in bytes.'
field :uploads_size, GraphQL::Types::Float, null: true,
- description: 'Uploads size of the project in bytes.'
+ description: 'Uploads size of the project in bytes.'
field :wiki_size, GraphQL::Types::Float, null: true,
- description: 'Wiki size of the project in bytes.'
- field :container_registry_size, GraphQL::Types::Float, null: true,
+ description: 'Wiki size of the project in bytes.'
+ field :container_registry_size,
+ GraphQL::Types::Float,
+ null: true,
description: 'Container Registry size of the project in bytes.'
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 7e3800c6a13..ecc6c9d7811 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -11,118 +11,118 @@ module Types
expose_permissions Types::PermissionTypes::Project
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the project.'
+ description: 'ID of the project.'
field :ci_config_path_or_default, GraphQL::Types::String, null: false,
- description: 'Path of the CI configuration file.'
+ description: 'Path of the CI configuration file.'
field :full_path, GraphQL::Types::ID, null: false,
- description: 'Full path of the project.'
+ description: 'Full path of the project.'
field :path, GraphQL::Types::String, null: false,
- description: 'Path of the project.'
+ description: 'Path of the project.'
field :sast_ci_configuration, Types::CiConfiguration::Sast::Type, null: true,
- calls_gitaly: true,
- description: 'SAST CI configuration for the project.'
+ calls_gitaly: true,
+ description: 'SAST CI configuration for the project.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the project (without namespace).'
+ description: 'Name of the project (without namespace).'
field :name_with_namespace, GraphQL::Types::String, null: false,
- description: 'Full name of the project with its namespace.'
+ description: 'Full name of the project with its namespace.'
field :description, GraphQL::Types::String, null: true,
- description: 'Short description of the project.'
+ description: 'Short description of the project.'
field :tag_list, GraphQL::Types::String, null: true,
- deprecated: { reason: 'Use `topics`', milestone: '13.12' },
- description: 'List of project topics (not Git tags).', method: :topic_list
+ deprecated: { reason: 'Use `topics`', milestone: '13.12' },
+ description: 'List of project topics (not Git tags).', method: :topic_list
field :topics, [GraphQL::Types::String], null: true,
- description: 'List of project topics.', method: :topic_list
+ description: 'List of project topics.', method: :topic_list
field :http_url_to_repo, GraphQL::Types::String, null: true,
- description: 'URL to connect to the project via HTTPS.'
+ description: 'URL to connect to the project via HTTPS.'
field :ssh_url_to_repo, GraphQL::Types::String, null: true,
- description: 'URL to connect to the project via SSH.'
+ description: 'URL to connect to the project via SSH.'
field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the project.'
+ description: 'Web URL of the project.'
field :forks_count, GraphQL::Types::Int, null: false, calls_gitaly: true, # 4 times
- description: 'Number of times the project has been forked.'
+ description: 'Number of times the project has been forked.'
field :star_count, GraphQL::Types::Int, null: false,
- description: 'Number of times the project has been starred.'
+ description: 'Number of times the project has been starred.'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of the project creation.'
+ description: 'Timestamp of the project creation.'
field :last_activity_at, Types::TimeType, null: true,
- description: 'Timestamp of the project last activity.'
+ description: 'Timestamp of the project last activity.'
field :archived, GraphQL::Types::Boolean, null: true,
- description: 'Indicates the archived status of the project.'
+ description: 'Indicates the archived status of the project.'
field :visibility, GraphQL::Types::String, null: true,
- description: 'Visibility of the project.'
+ description: 'Visibility of the project.'
field :lfs_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the project has Large File Storage (LFS) enabled.'
+ description: 'Indicates if the project has Large File Storage (LFS) enabled.'
field :merge_requests_ff_only_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
+ description: 'Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
field :shared_runners_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if shared runners are enabled for the project.'
+ description: 'Indicates if shared runners are enabled for the project.'
field :service_desk_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the project has Service Desk enabled.'
+ description: 'Indicates if the project has Service Desk enabled.'
field :service_desk_address, GraphQL::Types::String, null: true,
- description: 'E-mail address of the Service Desk.'
+ description: 'E-mail address of the Service Desk.'
field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'URL to avatar image file of the project.'
+ description: 'URL to avatar image file of the project.'
field :jobs_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
+ description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
field :public_jobs, GraphQL::Types::Boolean, method: :public_builds, null: true,
- description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.'
+ description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.'
field :open_issues_count, GraphQL::Types::Int, null: true,
- description: 'Number of open issues for the project.'
+ description: 'Number of open issues for the project.'
field :allow_merge_on_skipped_pipeline, GraphQL::Types::Boolean, null: true,
- description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.'
+ description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.'
field :autoclose_referenced_issues, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.'
+ description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.'
field :import_status, GraphQL::Types::String, null: true,
- description: 'Status of import background job of the project.'
+ description: 'Status of import background job of the project.'
field :jira_import_status, GraphQL::Types::String, null: true,
- description: 'Status of Jira import background job of the project.'
+ description: 'Status of Jira import background job of the project.'
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
+ description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
field :only_allow_merge_if_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
+ description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
field :printing_merge_request_link_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line.'
+ description: 'Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line.'
field :remove_source_branch_after_merge, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.'
+ description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.'
field :request_access_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if users can request member access to the project.'
+ description: 'Indicates if users can request member access to the project.'
field :squash_read_only, GraphQL::Types::Boolean, null: false, method: :squash_readonly?,
- description: 'Indicates if `squashReadOnly` is enabled.'
+ description: 'Indicates if `squashReadOnly` is enabled.'
field :suggestion_commit_message, GraphQL::Types::String, null: true,
- description: 'Commit message used to apply merge request suggestions.'
+ description: 'Commit message used to apply merge request suggestions.'
# No, the quotes are not a typo. Used to get around circular dependencies.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27536#note_871009675
field :group, 'Types::GroupType', null: true,
- description: 'Group of the project.'
+ description: 'Group of the project.'
field :namespace, Types::NamespaceType, null: true,
- description: 'Namespace of the project.'
+ description: 'Namespace of the project.'
field :statistics, Types::ProjectStatisticsType,
null: true,
description: 'Statistics of the project.'
field :repository, Types::RepositoryType, null: true,
- description: 'Git repository of the project.'
+ description: 'Git repository of the project.'
field :merge_requests,
Types::MergeRequestType.connection_type,
@@ -147,7 +147,7 @@ module Types
field :work_items,
Types::WorkItemType.connection_type,
null: true,
- deprecated: { milestone: '15.1', reason: :alpha },
+ alpha: { milestone: '15.1' },
description: 'Work items of the project.',
extras: [:lookahead],
resolver: Resolvers::WorkItemsResolver
@@ -160,8 +160,8 @@ module Types
resolver: Resolvers::IssueStatusCountsResolver
field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones of the project.',
- resolver: Resolvers::ProjectMilestonesResolver
+ description: 'Milestones of the project.',
+ resolver: Resolvers::ProjectMilestonesResolver
field :project_members,
description: 'Members of the project.',
@@ -221,7 +221,7 @@ module Types
resolver: Resolvers::Ci::ProjectPipelineCountsResolver
field :ci_variables,
- Types::Ci::VariableType.connection_type,
+ Types::Ci::ProjectVariableType.connection_type,
null: true,
description: "List of the project's CI/CD variables.",
authorize: :admin_build,
@@ -355,7 +355,7 @@ module Types
resolver: Resolvers::ContainerRepositoriesResolver
field :container_repositories_count, GraphQL::Types::Int, null: false,
- description: 'Number of container repositories in the project.'
+ description: 'Number of container repositories in the project.'
field :label,
Types::LabelType,
@@ -379,23 +379,23 @@ module Types
resolver: Resolvers::Terraform::StatesResolver
field :pipeline_analytics, Types::Ci::AnalyticsType, null: true,
- description: 'Pipeline analytics.',
- resolver: Resolvers::ProjectPipelineStatisticsResolver
+ description: 'Pipeline analytics.',
+ resolver: Resolvers::ProjectPipelineStatisticsResolver
field :ci_template, Types::Ci::TemplateType, null: true,
- description: 'Find a single CI/CD template by name.',
- resolver: Resolvers::Ci::TemplateResolver
+ description: 'Find a single CI/CD template by name.',
+ resolver: Resolvers::Ci::TemplateResolver
field :ci_job_token_scope, Types::Ci::JobTokenScopeType, null: true,
- description: 'The CI Job Tokens scope of access.',
- resolver: Resolvers::Ci::JobTokenScopeResolver
+ description: 'The CI Job Tokens scope of access.',
+ resolver: Resolvers::Ci::JobTokenScopeResolver
field :timelogs,
Types::TimelogType.connection_type, null: true,
- description: 'Time logged on issues and merge requests in the project.',
- extras: [:lookahead],
- complexity: 5,
- resolver: ::Resolvers::TimelogResolver
+ description: 'Time logged on issues and merge requests in the project.',
+ extras: [:lookahead],
+ complexity: 5,
+ resolver: ::Resolvers::TimelogResolver
field :agent_configurations,
::Types::Kas::AgentConfigurationType.connection_type,
@@ -438,6 +438,20 @@ module Types
' Returns `null` if `work_items` feature flag is disabled.' \
' This flag is disabled by default, because the feature is experimental and is subject to change without notice.'
+ field :timelog_categories,
+ Types::TimeTracking::TimelogCategoryType.connection_type,
+ null: true,
+ description: "Timelog categories for the project.",
+ alpha: { milestone: '15.3' }
+
+ field :fork_targets, Types::NamespaceType.connection_type,
+ resolver: Resolvers::Projects::ForkTargetsResolver,
+ description: 'Namespaces in which the current user can fork the project into.'
+
+ def timelog_categories
+ object.project_namespace.timelog_categories if Feature.enabled?(:timelog_categories)
+ end
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
@@ -455,7 +469,7 @@ module Types
container_registry: 'Container Registry is'
}.each do |feature, name_string|
field "#{feature}_enabled", GraphQL::Types::Boolean, null: true,
- description: "Indicates if #{name_string} enabled for the current user"
+ description: "Indicates if #{name_string} enabled for the current user"
define_method "#{feature}_enabled" do
object.feature_available?(feature, context[:current_user])
diff --git a/app/graphql/types/projects/service_type.rb b/app/graphql/types/projects/service_type.rb
index 88b7b95aa57..1416d93d3b4 100644
--- a/app/graphql/types/projects/service_type.rb
+++ b/app/graphql/types/projects/service_type.rb
@@ -9,11 +9,11 @@ module Types
# TODO: Add all the fields that we want to expose for the project services integrations
# https://gitlab.com/gitlab-org/gitlab/-/issues/213088
field :type, GraphQL::Types::String, null: true,
- description: 'Class name of the service.'
+ description: 'Class name of the service.'
field :service_type, ::Types::Projects::ServiceTypeEnum, null: true,
- description: 'Type of the service.'
+ description: 'Type of the service.'
field :active, GraphQL::Types::Boolean, null: true,
- description: 'Indicates if the service is active.'
+ description: 'Indicates if the service is active.'
def type
enum = ::Types::Projects::ServiceTypeEnum.coerce_result(service_type, context)
diff --git a/app/graphql/types/projects/services/jira_project_type.rb b/app/graphql/types/projects/services/jira_project_type.rb
index 0ff1b9d8903..1c5b97802e3 100644
--- a/app/graphql/types/projects/services/jira_project_type.rb
+++ b/app/graphql/types/projects/services/jira_project_type.rb
@@ -8,12 +8,12 @@ module Types
graphql_name 'JiraProject'
field :key, GraphQL::Types::String, null: false,
- description: 'Key of the Jira project.'
+ description: 'Key of the Jira project.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the Jira project.'
+ description: 'Name of the Jira project.'
field :project_id, GraphQL::Types::Int, null: false,
- description: 'ID of the Jira project.',
- method: :id
+ description: 'ID of the Jira project.',
+ method: :id
end
# rubocop:enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/projects/topic_type.rb b/app/graphql/types/projects/topic_type.rb
index bde6d79ddbf..da7df6df4a2 100644
--- a/app/graphql/types/projects/topic_type.rb
+++ b/app/graphql/types/projects/topic_type.rb
@@ -7,20 +7,20 @@ module Types
graphql_name 'Topic'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the topic.'
+ description: 'ID of the topic.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the topic.'
+ description: 'Name of the topic.'
field :title, GraphQL::Types::String, null: false,
- method: :title_or_name,
- description: 'Title of the topic.'
+ method: :title_or_name,
+ description: 'Title of the topic.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the topic.'
+ description: 'Description of the topic.'
field :avatar_url, GraphQL::Types::String, null: true,
- description: 'URL to avatar image file of the topic.'
+ description: 'URL to avatar image file of the topic.'
markdown_field :description_html, null: true
diff --git a/app/graphql/types/prometheus_alert_type.rb b/app/graphql/types/prometheus_alert_type.rb
index 789f1d6eb5f..fddb8b73768 100644
--- a/app/graphql/types/prometheus_alert_type.rb
+++ b/app/graphql/types/prometheus_alert_type.rb
@@ -10,7 +10,7 @@ module Types
present_using PrometheusAlertPresenter
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the alert condition.'
+ description: 'ID of the alert condition.'
field :humanized_text,
GraphQL::Types::String,
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index 9207a867639..84355390ea0 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -91,7 +91,7 @@ module Types
field :work_item, Types::WorkItemType,
null: true,
resolver: Resolvers::WorkItemResolver,
- deprecated: { milestone: '15.1', reason: :alpha },
+ alpha: { milestone: '15.1' },
description: 'Find a work item. Returns `null` if `work_items` feature flag is disabled.'
field :merge_request, Types::MergeRequestType,
@@ -124,7 +124,7 @@ module Types
description: "Find runners visible to the current user."
field :ci_variables,
- Types::Ci::VariableType.connection_type,
+ Types::Ci::InstanceVariableType.connection_type,
null: true,
description: "List of the instance's CI/CD variables."
@@ -184,7 +184,7 @@ module Types
end
def ci_variables
- return unless current_user.can_admin_all_resources?
+ return unless current_user&.can_admin_all_resources?
::Ci::InstanceVariable.all
end
diff --git a/app/graphql/types/release_asset_link_type.rb b/app/graphql/types/release_asset_link_type.rb
index 29738de27e5..e171c683e7d 100644
--- a/app/graphql/types/release_asset_link_type.rb
+++ b/app/graphql/types/release_asset_link_type.rb
@@ -10,19 +10,21 @@ module Types
present_using Releases::LinkPresenter
field :external, GraphQL::Types::Boolean, null: true, method: :external?,
- description: 'Indicates the link points to an external resource.'
+ description: 'Indicates the link points to an external resource.'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the link.'
- field :link_type, Types::ReleaseAssetLinkTypeEnum, null: true,
+ description: 'ID of the link.'
+ field :link_type,
+ Types::ReleaseAssetLinkTypeEnum,
+ null: true,
description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.'
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the link.'
+ description: 'Name of the link.'
field :url, GraphQL::Types::String, null: true,
- description: 'URL of the link.'
+ description: 'URL of the link.'
field :direct_asset_path, GraphQL::Types::String, null: true, method: :filepath,
- description: 'Relative path for the direct asset link.'
+ description: 'Relative path for the direct asset link.'
field :direct_asset_url, GraphQL::Types::String, null: true,
- description: 'Direct asset URL of the link.'
+ description: 'Direct asset URL of the link.'
end
end
diff --git a/app/graphql/types/release_assets_type.rb b/app/graphql/types/release_assets_type.rb
index ea6ee0b5fd9..396ba112130 100644
--- a/app/graphql/types/release_assets_type.rb
+++ b/app/graphql/types/release_assets_type.rb
@@ -12,10 +12,10 @@ module Types
present_using ReleasePresenter
field :count, GraphQL::Types::Int, null: true, method: :assets_count,
- description: 'Number of assets of the release.'
+ description: 'Number of assets of the release.'
field :links, Types::ReleaseAssetLinkType.connection_type, null: true, method: :sorted_links,
- description: 'Asset links of the release.'
+ description: 'Asset links of the release.'
field :sources, Types::ReleaseSourceType.connection_type, null: true,
- description: 'Sources of the release.'
+ description: 'Sources of the release.'
end
end
diff --git a/app/graphql/types/release_links_type.rb b/app/graphql/types/release_links_type.rb
index b7a1a5a9dbe..6bc767152e8 100644
--- a/app/graphql/types/release_links_type.rb
+++ b/app/graphql/types/release_links_type.rb
@@ -10,25 +10,35 @@ module Types
present_using ReleasePresenter
- field :closed_issues_url, GraphQL::Types::String, null: true,
+ field :closed_issues_url,
+ GraphQL::Types::String,
+ null: true,
description: 'HTTP URL of the issues page, filtered by this release and `state=closed`.',
authorize: :download_code
- field :closed_merge_requests_url, GraphQL::Types::String, null: true,
+ field :closed_merge_requests_url,
+ GraphQL::Types::String,
+ null: true,
description: 'HTTP URL of the merge request page , filtered by this release and `state=closed`.',
authorize: :download_code
field :edit_url, GraphQL::Types::String, null: true,
- description: "HTTP URL of the release's edit page.",
- authorize: :update_release
- field :merged_merge_requests_url, GraphQL::Types::String, null: true,
+ description: "HTTP URL of the release's edit page.",
+ authorize: :update_release
+ field :merged_merge_requests_url,
+ GraphQL::Types::String,
+ null: true,
description: 'HTTP URL of the merge request page , filtered by this release and `state=merged`.',
authorize: :download_code
- field :opened_issues_url, GraphQL::Types::String, null: true,
+ field :opened_issues_url,
+ GraphQL::Types::String,
+ null: true,
description: 'HTTP URL of the issues page, filtered by this release and `state=open`.',
authorize: :download_code
- field :opened_merge_requests_url, GraphQL::Types::String, null: true,
+ field :opened_merge_requests_url,
+ GraphQL::Types::String,
+ null: true,
description: 'HTTP URL of the merge request page, filtered by this release and `state=open`.',
authorize: :download_code
field :self_url, GraphQL::Types::String, null: true,
- description: 'HTTP URL of the release.'
+ description: 'HTTP URL of the release.'
end
end
diff --git a/app/graphql/types/release_source_type.rb b/app/graphql/types/release_source_type.rb
index fd29a69d72a..e05a2926ac1 100644
--- a/app/graphql/types/release_source_type.rb
+++ b/app/graphql/types/release_source_type.rb
@@ -8,8 +8,8 @@ module Types
authorize :download_code
field :format, GraphQL::Types::String, null: true,
- description: 'Format of the source.'
+ description: 'Format of the source.'
field :url, GraphQL::Types::String, null: true,
- description: 'Download URL of the source.'
+ description: 'Download URL of the source.'
end
end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index d906c577aa5..d70fe05c906 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -17,38 +17,40 @@ module Types
null: false,
description: 'Global ID of the release.'
field :assets, Types::ReleaseAssetsType, null: true, method: :itself,
- description: 'Assets of the release.'
+ description: 'Assets of the release.'
field :created_at, Types::TimeType, null: true,
- description: 'Timestamp of when the release was created.'
- field :description, GraphQL::Types::String, null: true,
+ description: 'Timestamp of when the release was created.'
+ field :description,
+ GraphQL::Types::String,
+ null: true,
description: 'Description (also known as "release notes") of the release.'
field :evidences, Types::EvidenceType.connection_type, null: true,
- description: 'Evidence for the release.'
+ description: 'Evidence for the release.'
field :links, Types::ReleaseLinksType, null: true, method: :itself,
- description: 'Links of the release.'
+ description: 'Links of the release.'
field :milestones, Types::MilestoneType.connection_type, null: true,
- description: 'Milestones associated to the release.',
- resolver: ::Resolvers::ReleaseMilestonesResolver
+ description: 'Milestones associated to the release.',
+ resolver: ::Resolvers::ReleaseMilestonesResolver
field :name, GraphQL::Types::String, null: true,
- description: 'Name of the release.'
+ description: 'Name of the release.'
field :released_at, Types::TimeType, null: true,
- description: 'Timestamp of when the release was released.'
+ description: 'Timestamp of when the release was released.'
field :tag_name, GraphQL::Types::String, null: true, method: :tag,
- description: 'Name of the tag associated with the release.'
+ description: 'Name of the tag associated with the release.'
field :tag_path, GraphQL::Types::String, null: true,
- description: 'Relative web path to the tag associated with the release.',
- authorize: :download_code
+ description: 'Relative web path to the tag associated with the release.',
+ authorize: :download_code
field :upcoming_release, GraphQL::Types::Boolean, null: true, method: :upcoming_release?,
- description: 'Indicates the release is an upcoming release.'
+ description: 'Indicates the release is an upcoming release.'
field :historical_release, GraphQL::Types::Boolean, null: true, method: :historical_release?,
- description: 'Indicates the release is an historical release.'
+ description: 'Indicates the release is an historical release.'
field :author, Types::UserType, null: true,
- description: 'User that created the release.'
+ description: 'User that created the release.'
field :commit, Types::CommitType, null: true,
- complexity: 10, calls_gitaly: true,
- description: 'Commit associated with the release.'
+ complexity: 10, calls_gitaly: true,
+ description: 'Commit associated with the release.'
markdown_field :description_html, null: true
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index dd5c70887de..8c90a8df611 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -9,108 +9,108 @@ module Types
present_using BlobPresenter
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the blob.'
+ description: 'ID of the blob.'
field :oid, GraphQL::Types::String, null: false, method: :id,
- description: 'OID of the blob.'
+ description: 'OID of the blob.'
field :path, GraphQL::Types::String, null: false,
- description: 'Path of the blob.'
+ description: 'Path of the blob.'
field :name, GraphQL::Types::String,
description: 'Blob name.',
null: true
field :mode, type: GraphQL::Types::String,
- description: 'Blob mode.',
- null: true
+ description: 'Blob mode.',
+ null: true
field :lfs_oid, GraphQL::Types::String, null: true,
- calls_gitaly: true,
- description: 'LFS OID of the blob.'
+ calls_gitaly: true,
+ description: 'LFS OID of the blob.'
field :web_path, GraphQL::Types::String, null: true,
- description: 'Web path of the blob.'
+ description: 'Web path of the blob.'
field :ide_edit_path, GraphQL::Types::String, null: true,
- description: 'Web path to edit this blob in the Web IDE.'
+ description: 'Web path to edit this blob in the Web IDE.'
field :fork_and_edit_path, GraphQL::Types::String, null: true,
- description: 'Web path to edit this blob using a forked project.'
+ description: 'Web path to edit this blob using a forked project.'
field :ide_fork_and_edit_path, GraphQL::Types::String, null: true,
- description: 'Web path to edit this blob in the Web IDE using a forked project.'
+ description: 'Web path to edit this blob in the Web IDE using a forked project.'
field :fork_and_view_path, GraphQL::Types::String, null: true,
- description: 'Web path to view this blob using a forked project.'
+ description: 'Web path to view this blob using a forked project.'
field :size, GraphQL::Types::Int, null: true,
- description: 'Size (in bytes) of the blob.'
+ description: 'Size (in bytes) of the blob.'
field :raw_size, GraphQL::Types::Int, null: true,
- description: 'Size (in bytes) of the blob, or the blob target if stored externally.'
+ description: 'Size (in bytes) of the blob, or the blob target if stored externally.'
field :raw_blob, GraphQL::Types::String, null: true, method: :data,
- description: 'Raw content of the blob.'
+ description: 'Raw content of the blob.'
field :raw_text_blob, GraphQL::Types::String, null: true, method: :text_only_data,
- description: 'Raw content of the blob, if the blob is text data.'
+ description: 'Raw content of the blob, if the blob is text data.'
field :stored_externally, GraphQL::Types::Boolean, null: true, method: :stored_externally?,
- description: "Whether the blob's content is stored externally (for instance, in LFS)."
+ description: "Whether the blob's content is stored externally (for instance, in LFS)."
field :external_storage, GraphQL::Types::String, null: true, method: :external_storage,
- description: "External storage being used, if enabled (for instance, 'LFS')."
+ description: "External storage being used, if enabled (for instance, 'LFS')."
field :edit_blob_path, GraphQL::Types::String, null: true,
- description: 'Web path to edit the blob in the old-style editor.'
+ description: 'Web path to edit the blob in the old-style editor.'
field :raw_path, GraphQL::Types::String, null: true,
- description: 'Web path to download the raw blob.'
+ description: 'Web path to download the raw blob.'
field :external_storage_url, GraphQL::Types::String, null: true,
- description: 'Web path to download the raw blob via external storage, if enabled.'
+ description: 'Web path to download the raw blob via external storage, if enabled.'
field :replace_path, GraphQL::Types::String, null: true,
- description: 'Web path to replace the blob content.'
+ description: 'Web path to replace the blob content.'
field :pipeline_editor_path, GraphQL::Types::String, null: true,
- description: 'Web path to edit .gitlab-ci.yml file.'
+ description: 'Web path to edit .gitlab-ci.yml file.'
field :gitpod_blob_url, GraphQL::Types::String, null: true,
- description: 'URL to the blob within Gitpod.'
+ description: 'URL to the blob within Gitpod.'
field :find_file_path, GraphQL::Types::String, null: true,
- description: 'Web path to find file.'
+ description: 'Web path to find file.'
field :blame_path, GraphQL::Types::String, null: true,
- description: 'Web path to blob blame page.'
+ description: 'Web path to blob blame page.'
field :history_path, GraphQL::Types::String, null: true,
- description: 'Web path to blob history page.'
+ description: 'Web path to blob history page.'
field :permalink_path, GraphQL::Types::String, null: true,
- description: 'Web path to blob permalink.',
- calls_gitaly: true
+ description: 'Web path to blob permalink.',
+ calls_gitaly: true
field :environment_formatted_external_url, GraphQL::Types::String, null: true,
- description: 'Environment on which the blob is available.',
- calls_gitaly: true
+ description: 'Environment on which the blob is available.',
+ calls_gitaly: true
field :environment_external_url_for_route_map, GraphQL::Types::String, null: true,
- description: 'Web path to blob on an environment.',
- calls_gitaly: true
+ description: 'Web path to blob on an environment.',
+ calls_gitaly: true
field :file_type, GraphQL::Types::String, null: true,
- description: 'Expected format of the blob based on the extension.'
+ description: 'Expected format of the blob based on the extension.'
field :simple_viewer, type: Types::BlobViewerType,
- description: 'Blob content simple viewer.',
- null: false
+ description: 'Blob content simple viewer.',
+ null: false
field :rich_viewer, type: Types::BlobViewerType,
- description: 'Blob content rich viewer.',
- null: true
+ description: 'Blob content rich viewer.',
+ null: true
field :plain_data, GraphQL::Types::String,
description: 'Blob plain highlighted data.',
@@ -118,14 +118,14 @@ module Types
calls_gitaly: true
field :can_modify_blob, GraphQL::Types::Boolean, null: true, method: :can_modify_blob?,
- calls_gitaly: true,
- description: 'Whether the current user can modify the blob.'
+ calls_gitaly: true,
+ description: 'Whether the current user can modify the blob.'
field :can_current_user_push_to_branch, GraphQL::Types::Boolean, null: true, method: :can_current_user_push_to_branch?,
- description: 'Whether the current user can push to the branch.'
+ description: 'Whether the current user can push to the branch.'
field :archived, GraphQL::Types::Boolean, null: true, method: :archived?,
- description: 'Whether the current project is archived.'
+ description: 'Whether the current project is archived.'
field :language, GraphQL::Types::String,
description: 'Blob language.',
@@ -134,10 +134,10 @@ module Types
calls_gitaly: true
field :code_navigation_path, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Web path for code navigation.'
+ description: 'Web path for code navigation.'
field :project_blob_path_root, GraphQL::Types::String, null: true,
- description: 'Web path for the root of the blob.'
+ description: 'Web path for the root of the blob.'
def raw_text_blob
object.data unless object.binary?
diff --git a/app/graphql/types/repository_type.rb b/app/graphql/types/repository_type.rb
index aa02f0058da..ba94f59ab6c 100644
--- a/app/graphql/types/repository_type.rb
+++ b/app/graphql/types/repository_type.rb
@@ -7,24 +7,24 @@ module Types
authorize :download_code
field :blobs, Types::Repository::BlobType.connection_type, null: true, resolver: Resolvers::BlobsResolver, calls_gitaly: true,
- description: 'Blobs contained within the repository'
+ description: 'Blobs contained within the repository'
field :branch_names, [GraphQL::Types::String], null: true, calls_gitaly: true,
- complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
- resolver: Resolvers::RepositoryBranchNamesResolver
+ complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
+ resolver: Resolvers::RepositoryBranchNamesResolver
field :disk_path, GraphQL::Types::String,
description: 'Shows a disk path of the repository.',
null: true,
authorize: :read_storage_disk_path
field :empty, GraphQL::Types::Boolean, null: false, method: :empty?, calls_gitaly: true,
- description: 'Indicates repository has no visible content.'
+ description: 'Indicates repository has no visible content.'
field :exists, GraphQL::Types::Boolean, null: false, method: :exists?, calls_gitaly: true,
- description: 'Indicates a corresponding Git repository exists on disk.'
+ description: 'Indicates a corresponding Git repository exists on disk.'
field :paginated_tree, Types::Tree::TreeType.connection_type, null: true, resolver: Resolvers::PaginatedTreeResolver, calls_gitaly: true,
- max_page_size: 100,
- description: 'Paginated tree of the repository.'
+ max_page_size: 100,
+ description: 'Paginated tree of the repository.'
field :root_ref, GraphQL::Types::String, null: true, calls_gitaly: true,
- description: 'Default branch of the repository.'
+ description: 'Default branch of the repository.'
field :tree, Types::Tree::TreeType, null: true, resolver: Resolvers::TreeResolver, calls_gitaly: true,
- description: 'Tree of the repository.'
+ description: 'Tree of the repository.'
end
end
diff --git a/app/graphql/types/resolvable_interface.rb b/app/graphql/types/resolvable_interface.rb
index 42784aa5e00..2869d2cfd0f 100644
--- a/app/graphql/types/resolvable_interface.rb
+++ b/app/graphql/types/resolvable_interface.rb
@@ -17,12 +17,12 @@ module Types
end
field :resolved, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if the object is resolved.',
- method: :resolved?
+ description: 'Indicates if the object is resolved.',
+ method: :resolved?
field :resolvable, GraphQL::Types::Boolean, null: false,
- description: 'Indicates if the object can be resolved.',
- method: :resolvable?
+ description: 'Indicates if the object can be resolved.',
+ method: :resolvable?
field :resolved_at, Types::TimeType, null: true,
- description: 'Timestamp of when the object was resolved.'
+ description: 'Timestamp of when the object was resolved.'
end
end
diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb
index 7b96cc34941..5ee0500b1e0 100644
--- a/app/graphql/types/snippet_type.rb
+++ b/app/graphql/types/snippet_type.rb
@@ -54,28 +54,28 @@ module Types
null: false
field :web_url, type: GraphQL::Types::String,
- description: 'Web URL of the snippet.',
- null: false
+ description: 'Web URL of the snippet.',
+ null: false
field :raw_url, type: GraphQL::Types::String,
- description: 'Raw URL of the snippet.',
- null: false
+ description: 'Raw URL of the snippet.',
+ null: false
field :blobs, type: Types::Snippets::BlobType.connection_type,
- description: 'Snippet blobs.',
- calls_gitaly: true,
- null: true,
- resolver: Resolvers::Snippets::BlobsResolver
+ description: 'Snippet blobs.',
+ calls_gitaly: true,
+ null: true,
+ resolver: Resolvers::Snippets::BlobsResolver
field :ssh_url_to_repo, type: GraphQL::Types::String,
- description: 'SSH URL to the snippet repository.',
- calls_gitaly: true,
- null: true
+ description: 'SSH URL to the snippet repository.',
+ calls_gitaly: true,
+ null: true
field :http_url_to_repo, type: GraphQL::Types::String,
- description: 'HTTP URL to the snippet repository.',
- calls_gitaly: true,
- null: true
+ description: 'HTTP URL to the snippet repository.',
+ calls_gitaly: true,
+ null: true
markdown_field :description_html, null: true, method: :description
diff --git a/app/graphql/types/snippets/blob_connection_type.rb b/app/graphql/types/snippets/blob_connection_type.rb
index 15d26af7374..476a6f04b4a 100644
--- a/app/graphql/types/snippets/blob_connection_type.rb
+++ b/app/graphql/types/snippets/blob_connection_type.rb
@@ -4,7 +4,9 @@ module Types
module Snippets
# rubocop: disable Graphql/AuthorizeTypes
class BlobConnectionType < GraphQL::Types::Relay::BaseConnection
- field :has_unretrievable_blobs, GraphQL::Types::Boolean, null: false,
+ field :has_unretrievable_blobs,
+ GraphQL::Types::Boolean,
+ null: false,
description: 'Indicates if the snippet has unretrievable blobs.',
resolver_method: :unretrievable_blobs?
diff --git a/app/graphql/types/snippets/blob_type.rb b/app/graphql/types/snippets/blob_type.rb
index 80702c71f63..bb4a0a64de8 100644
--- a/app/graphql/types/snippets/blob_type.rb
+++ b/app/graphql/types/snippets/blob_type.rb
@@ -44,25 +44,25 @@ module Types
null: true
field :simple_viewer, type: Types::Snippets::BlobViewerType,
- description: 'Blob content simple viewer.',
- null: false
+ description: 'Blob content simple viewer.',
+ null: false
field :rich_viewer, type: Types::Snippets::BlobViewerType,
- description: 'Blob content rich viewer.',
- null: true
+ description: 'Blob content rich viewer.',
+ null: true
field :mode, type: GraphQL::Types::String,
- description: 'Blob mode.',
- null: true
+ description: 'Blob mode.',
+ null: true
field :external_storage, type: GraphQL::Types::String,
- description: 'Blob external storage.',
- null: true
+ description: 'Blob external storage.',
+ null: true
field :rendered_as_text, type: GraphQL::Types::Boolean,
- description: 'Shows whether the blob is rendered as text.',
- method: :rendered_as_text?,
- null: false
+ description: 'Shows whether the blob is rendered as text.',
+ method: :rendered_as_text?,
+ null: false
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index de3f71090f6..9b5f028a857 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -5,15 +5,18 @@ module Types
graphql_name 'Subscription'
field :issuable_assignees_updated, subscription: Subscriptions::IssuableUpdated, null: true,
- description: 'Triggered when the assignees of an issuable are updated.'
+ description: 'Triggered when the assignees of an issuable are updated.'
field :issue_crm_contacts_updated, subscription: Subscriptions::IssuableUpdated, null: true,
- description: 'Triggered when the crm contacts of an issuable are updated.'
+ description: 'Triggered when the crm contacts of an issuable are updated.'
field :issuable_title_updated, subscription: Subscriptions::IssuableUpdated, null: true,
- description: 'Triggered when the title of an issuable is updated.'
+ description: 'Triggered when the title of an issuable is updated.'
field :issuable_labels_updated, subscription: Subscriptions::IssuableUpdated, null: true,
- description: 'Triggered when the labels of an issuable are updated.'
+ description: 'Triggered when the labels of an issuable are updated.'
+
+ field :issuable_dates_updated, subscription: Subscriptions::IssuableUpdated, null: true,
+ description: 'Triggered when the due date or start date of an issuable is updated.'
end
end
diff --git a/app/graphql/types/task_completion_status.rb b/app/graphql/types/task_completion_status.rb
index 9a979b04d37..c7da2f2cf01 100644
--- a/app/graphql/types/task_completion_status.rb
+++ b/app/graphql/types/task_completion_status.rb
@@ -9,9 +9,9 @@ module Types
description 'Completion status of tasks'
field :completed_count, GraphQL::Types::Int, null: false,
- description: 'Number of completed tasks.'
+ description: 'Number of completed tasks.'
field :count, GraphQL::Types::Int, null: false,
- description: 'Number of total tasks.'
+ description: 'Number of total tasks.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/time_tracking/timelog_category_type.rb b/app/graphql/types/time_tracking/timelog_category_type.rb
new file mode 100644
index 00000000000..c73a6fbd43b
--- /dev/null
+++ b/app/graphql/types/time_tracking/timelog_category_type.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Types
+ module TimeTracking
+ class TimelogCategoryType < BaseObject
+ graphql_name 'TimeTrackingTimelogCategory'
+
+ authorize :read_timelog_category
+
+ field :id,
+ GraphQL::Types::ID,
+ null: false,
+ description: 'Internal ID of the timelog category.'
+
+ field :name,
+ GraphQL::Types::String,
+ null: false,
+ description: 'Name of the category.'
+
+ field :description,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Description of the category.'
+
+ field :color,
+ Types::ColorType,
+ null: true,
+ description: 'Color assigned to the category.'
+
+ field :billable,
+ GraphQL::Types::Boolean,
+ null: true,
+ description: 'Whether the category is billable or not.'
+
+ field :billing_rate,
+ GraphQL::Types::Float,
+ null: true,
+ description: 'Billing rate for the category.'
+
+ field :created_at,
+ Types::TimeType,
+ null: false,
+ description: 'When the category was created.'
+
+ field :updated_at,
+ Types::TimeType,
+ null: false,
+ description: 'When the category was last updated.'
+ end
+ end
+end
diff --git a/app/graphql/types/tree/blob_type.rb b/app/graphql/types/tree/blob_type.rb
index 284542e1d2a..3db64d812c5 100644
--- a/app/graphql/types/tree/blob_type.rb
+++ b/app/graphql/types/tree/blob_type.rb
@@ -10,14 +10,14 @@ module Types
present_using BlobPresenter
field :lfs_oid, GraphQL::Types::String, null: true,
- calls_gitaly: true,
- description: 'LFS ID of the blob.'
+ calls_gitaly: true,
+ description: 'LFS ID of the blob.'
field :mode, GraphQL::Types::String, null: true,
- description: 'Blob mode in numeric format.'
+ description: 'Blob mode in numeric format.'
field :web_path, GraphQL::Types::String, null: true,
- description: 'Web path of the blob.'
+ description: 'Web path of the blob.'
field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL of the blob.'
+ description: 'Web URL of the blob.'
def lfs_oid
Gitlab::Graphql::Loaders::BatchLfsOidLoader.new(object.repository, object.id).find
diff --git a/app/graphql/types/tree/entry_type.rb b/app/graphql/types/tree/entry_type.rb
index 1c612f91a5b..4b4119dcab9 100644
--- a/app/graphql/types/tree/entry_type.rb
+++ b/app/graphql/types/tree/entry_type.rb
@@ -5,17 +5,17 @@ module Types
include Types::BaseInterface
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the entry.'
+ description: 'ID of the entry.'
field :sha, GraphQL::Types::String, null: false,
- description: 'Last commit SHA for the entry.', method: :id
+ description: 'Last commit SHA for the entry.', method: :id
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the entry.'
+ description: 'Name of the entry.'
field :type, Tree::TypeEnum, null: false,
- description: 'Type of tree entry.'
+ description: 'Type of tree entry.'
field :path, GraphQL::Types::String, null: false,
- description: 'Path of the entry.'
+ description: 'Path of the entry.'
field :flat_path, GraphQL::Types::String, null: false,
- description: 'Flat path of the entry.'
+ description: 'Flat path of the entry.'
end
end
end
diff --git a/app/graphql/types/tree/submodule_type.rb b/app/graphql/types/tree/submodule_type.rb
index 8f462011f0f..57597d9884c 100644
--- a/app/graphql/types/tree/submodule_type.rb
+++ b/app/graphql/types/tree/submodule_type.rb
@@ -9,9 +9,9 @@ module Types
implements Types::Tree::EntryType
field :tree_url, type: GraphQL::Types::String, null: true,
- description: 'Tree URL for the sub-module.'
+ description: 'Tree URL for the sub-module.'
field :web_url, type: GraphQL::Types::String, null: true,
- description: 'Web URL for the sub-module.'
+ description: 'Web URL for the sub-module.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/tree/tree_entry_type.rb b/app/graphql/types/tree/tree_entry_type.rb
index 28024fd010b..1de78250812 100644
--- a/app/graphql/types/tree/tree_entry_type.rb
+++ b/app/graphql/types/tree/tree_entry_type.rb
@@ -11,9 +11,9 @@ module Types
present_using TreeEntryPresenter
field :web_path, GraphQL::Types::String, null: true,
- description: 'Web path for the tree entry (directory).'
+ description: 'Web path for the tree entry (directory).'
field :web_url, GraphQL::Types::String, null: true,
- description: 'Web URL for the tree entry (directory).'
+ description: 'Web URL for the tree entry (directory).'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/tree/tree_type.rb b/app/graphql/types/tree/tree_type.rb
index 011cff0c89c..51dc8cdb7bb 100644
--- a/app/graphql/types/tree/tree_type.rb
+++ b/app/graphql/types/tree/tree_type.rb
@@ -12,15 +12,15 @@ module Types
description: 'Last commit for the tree.'
field :trees, Types::Tree::TreeEntryType.connection_type, null: false,
- description: 'Trees of the tree.'
+ description: 'Trees of the tree.'
field :submodules, Types::Tree::SubmoduleType.connection_type, null: false,
- description: 'Sub-modules of the tree.',
- calls_gitaly: true
+ description: 'Sub-modules of the tree.',
+ calls_gitaly: true
field :blobs, Types::Tree::BlobType.connection_type, null: false,
- description: 'Blobs of the tree.',
- calls_gitaly: true
+ description: 'Blobs of the tree.',
+ calls_gitaly: true
def trees
Gitlab::Graphql::Representation::TreeEntry.decorate(object.trees, object.repository)
diff --git a/app/graphql/types/upload_type.rb b/app/graphql/types/upload_type.rb
new file mode 100644
index 00000000000..0bb7f68cdba
--- /dev/null
+++ b/app/graphql/types/upload_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ class UploadType < BaseObject
+ graphql_name 'FileUpload'
+
+ authorize :read_upload
+
+ field :id, Types::GlobalIDType[::Upload],
+ null: false,
+ description: 'Global ID of the upload.'
+ field :path, GraphQL::Types::String,
+ null: false,
+ description: 'Path of the upload.'
+ field :size, GraphQL::Types::Int,
+ null: false,
+ description: 'Size of the upload in bytes.'
+ end
+end
diff --git a/app/graphql/types/user_callout_type.rb b/app/graphql/types/user_callout_type.rb
index 526027322ef..f509900e91d 100644
--- a/app/graphql/types/user_callout_type.rb
+++ b/app/graphql/types/user_callout_type.rb
@@ -5,8 +5,8 @@ module Types
graphql_name 'UserCallout'
field :dismissed_at, Types::TimeType, null: true,
- description: 'Date when the callout was dismissed.'
+ description: 'Date when the callout was dismissed.'
field :feature_name, UserCalloutFeatureNameEnum, null: true,
- description: 'Name of the feature that the callout is for.'
+ description: 'Name of the feature that the callout is for.'
end
end
diff --git a/app/graphql/types/user_interface.rb b/app/graphql/types/user_interface.rb
index edbc8aee9c5..f49b3eee4f5 100644
--- a/app/graphql/types/user_interface.rb
+++ b/app/graphql/types/user_interface.rb
@@ -122,13 +122,15 @@ module Types
'Will not return saved replies if `saved_replies` feature flag is disabled.'
field :gitpod_enabled, GraphQL::Types::Boolean, null: true,
- description: 'Whether Gitpod is enabled at the user level.'
+ description: 'Whether Gitpod is enabled at the user level.'
- field :preferences_gitpod_path, GraphQL::Types::String, null: true,
+ field :preferences_gitpod_path,
+ GraphQL::Types::String,
+ null: true,
description: 'Web path to the Gitpod section within user preferences.'
field :profile_enable_gitpod_path, GraphQL::Types::String, null: true,
- description: 'Web path to enable Gitpod for the user.'
+ description: 'Web path to enable Gitpod for the user.'
definition_methods do
def resolve_type(object, context)
diff --git a/app/graphql/types/user_status_type.rb b/app/graphql/types/user_status_type.rb
index 68c00bffe48..199c7d31083 100644
--- a/app/graphql/types/user_status_type.rb
+++ b/app/graphql/types/user_status_type.rb
@@ -6,12 +6,12 @@ module Types
graphql_name 'UserStatus'
markdown_field :message_html, null: true,
- description: 'HTML of the user status message'
+ description: 'HTML of the user status message'
field :availability, Types::AvailabilityEnum, null: false,
- description: 'User availability status.'
+ description: 'User availability status.'
field :emoji, GraphQL::Types::String, null: true,
- description: 'String representation of emoji.'
+ description: 'String representation of emoji.'
field :message, GraphQL::Types::String, null: true,
- description: 'User status message.'
+ description: 'User status message.'
end
end
diff --git a/app/graphql/types/work_item_type.rb b/app/graphql/types/work_item_type.rb
index 18b9bfd1c9a..7904841863b 100644
--- a/app/graphql/types/work_item_type.rb
+++ b/app/graphql/types/work_item_type.rb
@@ -6,22 +6,37 @@ module Types
authorize :read_work_item
+ field :closed_at, Types::TimeType, null: true,
+ description: 'Timestamp of when the work item was closed.'
+ field :confidential, GraphQL::Types::Boolean, null: false,
+ description: 'Indicates the work item is confidential.'
+ field :created_at, Types::TimeType, null: false,
+ description: 'Timestamp of when the work item was created.'
field :description, GraphQL::Types::String, null: true,
- description: 'Description of the work item.'
+ description: 'Description of the work item.'
field :id, Types::GlobalIDType[::WorkItem], null: false,
- description: 'Global ID of the work item.'
+ description: 'Global ID of the work item.'
field :iid, GraphQL::Types::ID, null: false,
- description: 'Internal ID of the work item.'
- field :lock_version, GraphQL::Types::Int, null: false,
+ description: 'Internal ID of the work item.'
+ field :lock_version,
+ GraphQL::Types::Int,
+ null: false,
description: 'Lock version of the work item. Incremented each time the work item is updated.'
+ field :project, Types::ProjectType, null: false,
+ description: 'Project the work item belongs to.',
+ alpha: { milestone: '15.3' }
field :state, WorkItemStateEnum, null: false,
- description: 'State of the work item.'
+ description: 'State of the work item.'
field :title, GraphQL::Types::String, null: false,
- description: 'Title of the work item.'
- field :widgets, [Types::WorkItems::WidgetInterface], null: true,
+ description: 'Title of the work item.'
+ field :updated_at, Types::TimeType, null: false,
+ description: 'Timestamp of when the work item was last updated.'
+ field :widgets,
+ [Types::WorkItems::WidgetInterface],
+ null: true,
description: 'Collection of widgets that belong to the work item.'
field :work_item_type, Types::WorkItems::TypeType, null: false,
- description: 'Type assigned to the work item.'
+ description: 'Type assigned to the work item.'
markdown_field :title_html, null: true
markdown_field :description_html, null: true
diff --git a/app/graphql/types/work_items/type_type.rb b/app/graphql/types/work_items/type_type.rb
index f31bd7ee9ba..4d008a21b9c 100644
--- a/app/graphql/types/work_items/type_type.rb
+++ b/app/graphql/types/work_items/type_type.rb
@@ -8,11 +8,11 @@ module Types
authorize :read_work_item_type
field :icon_name, GraphQL::Types::String, null: true,
- description: 'Icon name of the work item type.'
+ description: 'Icon name of the work item type.'
field :id, Types::GlobalIDType[::WorkItems::Type], null: false,
- description: 'Global ID of the work item type.'
+ description: 'Global ID of the work item type.'
field :name, GraphQL::Types::String, null: false,
- description: 'Name of the work item type.'
+ description: 'Name of the work item type.'
end
end
end
diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb
index 1b752393296..eca8c8d845a 100644
--- a/app/graphql/types/work_items/widget_interface.rb
+++ b/app/graphql/types/work_items/widget_interface.rb
@@ -7,8 +7,21 @@ module Types
graphql_name 'WorkItemWidget'
- field :type, ::Types::WorkItems::WidgetTypeEnum, null: true,
- description: 'Widget type.'
+ field :type, ::Types::WorkItems::WidgetTypeEnum,
+ null: true,
+ description: 'Widget type.'
+
+ ORPHAN_TYPES = [
+ ::Types::WorkItems::Widgets::DescriptionType,
+ ::Types::WorkItems::Widgets::HierarchyType,
+ ::Types::WorkItems::Widgets::LabelsType,
+ ::Types::WorkItems::Widgets::AssigneesType,
+ ::Types::WorkItems::Widgets::StartAndDueDateType
+ ].freeze
+
+ def self.ce_orphan_types
+ ORPHAN_TYPES
+ end
def self.resolve_type(object, context)
case object
@@ -18,17 +31,18 @@ module Types
::Types::WorkItems::Widgets::HierarchyType
when ::WorkItems::Widgets::Assignees
::Types::WorkItems::Widgets::AssigneesType
- when ::WorkItems::Widgets::Weight
- ::Types::WorkItems::Widgets::WeightType
+ when ::WorkItems::Widgets::Labels
+ ::Types::WorkItems::Widgets::LabelsType
+ when ::WorkItems::Widgets::StartAndDueDate
+ ::Types::WorkItems::Widgets::StartAndDueDateType
else
raise "Unknown GraphQL type for widget #{object}"
end
end
- orphan_types ::Types::WorkItems::Widgets::DescriptionType,
- ::Types::WorkItems::Widgets::HierarchyType,
- ::Types::WorkItems::Widgets::AssigneesType,
- ::Types::WorkItems::Widgets::WeightType
+ orphan_types(*ORPHAN_TYPES)
end
end
end
+
+Types::WorkItems::WidgetInterface.prepend_mod
diff --git a/app/graphql/types/work_items/widgets/assignees_input_type.rb b/app/graphql/types/work_items/widgets/assignees_input_type.rb
new file mode 100644
index 00000000000..ee61bc73054
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/assignees_input_type.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ class AssigneesInputType < BaseInputObject
+ graphql_name 'WorkItemWidgetAssigneesInput'
+
+ argument :assignee_ids, [::Types::GlobalIDType[::User]],
+ required: true,
+ description: 'Global IDs of assignees.',
+ prepare: ->(ids, _) { ids.map(&:model_id) }
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/assignees_type.rb b/app/graphql/types/work_items/widgets/assignees_type.rb
index 08ee06fdfa0..74da3264567 100644
--- a/app/graphql/types/work_items/widgets/assignees_type.rb
+++ b/app/graphql/types/work_items/widgets/assignees_type.rb
@@ -12,14 +12,17 @@ module Types
implements Types::WorkItems::WidgetInterface
- field :assignees, Types::UserType.connection_type, null: true,
- description: 'Assignees of the work item.'
+ field :assignees, Types::UserType.connection_type,
+ null: true,
+ description: 'Assignees of the work item.'
- field :allows_multiple_assignees, GraphQL::Types::Boolean, null: true, method: :allows_multiple_assignees?,
- description: 'Indicates whether multiple assignees are allowed.'
+ field :allows_multiple_assignees, GraphQL::Types::Boolean,
+ null: true, method: :allows_multiple_assignees?,
+ description: 'Indicates whether multiple assignees are allowed.'
- field :can_invite_members, GraphQL::Types::Boolean, null: false, resolver_method: :can_invite_members?,
- description: 'Indicates whether the current user can invite members to the work item\'s project.'
+ field :can_invite_members, GraphQL::Types::Boolean,
+ null: false, resolver_method: :can_invite_members?,
+ description: 'Indicates whether the current user can invite members to the work item\'s project.'
def can_invite_members?
Ability.allowed?(current_user, :admin_project_member, object.work_item.project)
diff --git a/app/graphql/types/work_items/widgets/description_type.rb b/app/graphql/types/work_items/widgets/description_type.rb
index 79192d7c3d4..4c365a67bfd 100644
--- a/app/graphql/types/work_items/widgets/description_type.rb
+++ b/app/graphql/types/work_items/widgets/description_type.rb
@@ -12,8 +12,9 @@ module Types
implements Types::WorkItems::WidgetInterface
- field :description, GraphQL::Types::String, null: true,
- description: 'Description of the work item.'
+ field :description, GraphQL::Types::String,
+ null: true,
+ description: 'Description of the work item.'
markdown_field :description_html, null: true do |resolved_object|
resolved_object.work_item
diff --git a/app/graphql/types/work_items/widgets/hierarchy_type.rb b/app/graphql/types/work_items/widgets/hierarchy_type.rb
index 057d5fbf056..0ccd8af7dc8 100644
--- a/app/graphql/types/work_items/widgets/hierarchy_type.rb
+++ b/app/graphql/types/work_items/widgets/hierarchy_type.rb
@@ -12,13 +12,13 @@ module Types
implements Types::WorkItems::WidgetInterface
- field :parent, ::Types::WorkItemType, null: true,
- description: 'Parent work item.',
- complexity: 5
+ field :parent, ::Types::WorkItemType,
+ null: true, complexity: 5,
+ description: 'Parent work item.'
- field :children, ::Types::WorkItemType.connection_type, null: true,
- description: 'Child work items.',
- complexity: 5
+ field :children, ::Types::WorkItemType.connection_type,
+ null: true, complexity: 5,
+ description: 'Child work items.'
def children
object.children.inc_relations_for_permission_check
diff --git a/app/graphql/types/work_items/widgets/labels_type.rb b/app/graphql/types/work_items/widgets/labels_type.rb
new file mode 100644
index 00000000000..20574b3e3bc
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/labels_type.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ # Disabling widget level authorization as it might be too granular
+ # and we already authorize the parent work item
+ # rubocop:disable Graphql/AuthorizeTypes
+ class LabelsType < BaseObject
+ graphql_name 'WorkItemWidgetLabels'
+ description 'Represents the labels widget'
+
+ implements Types::WorkItems::WidgetInterface
+
+ field :labels, Types::LabelType.connection_type,
+ null: true,
+ description: 'Labels assigned to the work item.'
+
+ field :allows_scoped_labels, GraphQL::Types::Boolean,
+ null: true,
+ method: :allows_scoped_labels?,
+ description: 'Indicates whether a scoped label is allowed.'
+ end
+ # rubocop:enable Graphql/AuthorizeTypes
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/start_and_due_date_type.rb b/app/graphql/types/work_items/widgets/start_and_due_date_type.rb
new file mode 100644
index 00000000000..d4dbc969937
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/start_and_due_date_type.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ # Disabling widget level authorization as it might be too granular
+ # and we already authorize the parent work item
+ # rubocop:disable Graphql/AuthorizeTypes
+ class StartAndDueDateType < BaseObject
+ graphql_name 'WorkItemWidgetStartAndDueDate'
+ description 'Represents a start and due date widget'
+
+ implements Types::WorkItems::WidgetInterface
+
+ field :due_date, Types::DateType,
+ null: true,
+ description: 'Due date of the work item.'
+ field :start_date, Types::DateType,
+ null: true,
+ description: 'Start date of the work item.'
+ end
+ # rubocop:enable Graphql/AuthorizeTypes
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb b/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb
new file mode 100644
index 00000000000..bccd4afe8f3
--- /dev/null
+++ b/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Types
+ module WorkItems
+ module Widgets
+ class StartAndDueDateUpdateInputType < BaseInputObject
+ graphql_name 'WorkItemWidgetStartAndDueDateUpdateInput'
+
+ argument :due_date, Types::DateType,
+ required: false,
+ description: 'Due date for the work item.'
+ argument :start_date, Types::DateType,
+ required: false,
+ description: 'Start date for the work item.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/work_items/widgets/weight_input_type.rb b/app/graphql/types/work_items/widgets/weight_input_type.rb
deleted file mode 100644
index a01c63222a5..00000000000
--- a/app/graphql/types/work_items/widgets/weight_input_type.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module WorkItems
- module Widgets
- class WeightInputType < BaseInputObject
- graphql_name 'WorkItemWidgetWeightInput'
-
- argument :weight, GraphQL::Types::Int,
- required: true,
- description: 'Weight of the work item.'
- end
- end
- end
-end
diff --git a/app/graphql/types/work_items/widgets/weight_type.rb b/app/graphql/types/work_items/widgets/weight_type.rb
deleted file mode 100644
index c8eaf560268..00000000000
--- a/app/graphql/types/work_items/widgets/weight_type.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- module WorkItems
- module Widgets
- # Disabling widget level authorization as it might be too granular
- # and we already authorize the parent work item
- # rubocop:disable Graphql/AuthorizeTypes
- class WeightType < BaseObject
- graphql_name 'WorkItemWidgetWeight'
- description 'Represents a weight widget'
-
- implements Types::WorkItems::WidgetInterface
-
- field :weight, GraphQL::Types::Int, null: true,
- description: 'Weight of the work item.'
- end
- # rubocop:enable Graphql/AuthorizeTypes
- end
- end
-end
diff --git a/app/helpers/admin/identities_helper.rb b/app/helpers/admin/identities_helper.rb
new file mode 100644
index 00000000000..48e01840394
--- /dev/null
+++ b/app/helpers/admin/identities_helper.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Admin
+ module IdentitiesHelper
+ def label_for_identity_provider(identity)
+ provider = identity.provider
+ "#{Gitlab::Auth::OAuth::Provider.label_for(provider)} (#{provider})"
+ end
+
+ def provider_id_cell_testid(identity)
+ 'provider_id_blank'
+ end
+
+ def provider_id(identity)
+ '-'
+ end
+
+ def saml_group_cell_testid(identity)
+ 'saml_group_blank'
+ end
+
+ def saml_group_link(identity)
+ '-'
+ end
+
+ def identity_cells_to_render?(identities, _user)
+ identities.present?
+ end
+
+ def scim_identities_collection(_user)
+ []
+ end
+ end
+end
+
+Admin::IdentitiesHelper.prepend_mod
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index d2cc50be509..a75c1b16145 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -19,23 +19,23 @@ module ApplicationHelper
def dispensable_render(...)
render(...)
- rescue StandardError => error
+ rescue StandardError => e
if Feature.enabled?(:dispensable_render)
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
nil
else
- raise error
+ raise e
end
end
def dispensable_render_if_exists(...)
render_if_exists(...)
- rescue StandardError => error
+ rescue StandardError => e
if Feature.enabled?(:dispensable_render)
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
nil
else
- raise error
+ raise e
end
end
@@ -223,6 +223,16 @@ module ApplicationHelper
ApplicationHelper.promo_host
end
+ # This needs to be used outside of Rails
+ def self.community_forum
+ 'https://forum.gitlab.com'
+ end
+
+ # Convenient method for Rails helper
+ def community_forum
+ ApplicationHelper.community_forum
+ end
+
def promo_url
'https://' + promo_host
end
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index 9dc93779b12..617bc0e9bee 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -84,9 +84,9 @@ module AvatarsHelper
end
image_options = {
- alt: alt_text,
- src: avatar_url,
- data: data_attributes,
+ alt: alt_text,
+ src: avatar_url,
+ data: data_attributes,
class: css_class,
title: user_name
}
diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
index 26ebe8a6470..d48eae26a90 100644
--- a/app/helpers/badges_helper.rb
+++ b/app/helpers/badges_helper.rb
@@ -8,13 +8,13 @@ module BadgesHelper
success: "badge-success",
warning: "badge-warning",
danger: "badge-danger"
- }.tap { |hash| hash.default = hash.fetch(:muted) } .freeze
+ }.tap { |hash| hash.default = hash.fetch(:muted) }.freeze
SIZE_CLASSES = {
sm: "sm",
md: "md",
lg: "lg"
- }.tap { |hash| hash.default = hash.fetch(:md) } .freeze
+ }.tap { |hash| hash.default = hash.fetch(:md) }.freeze
GL_BADGE_CLASSES = %w[gl-badge badge badge-pill].freeze
@@ -53,7 +53,7 @@ module BadgesHelper
#
# See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-badge--default.
def gl_badge_tag(*args, &block)
- if block_given?
+ if block
build_gl_badge_tag(capture(&block), *args)
else
build_gl_badge_tag(*args)
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index fcf6a177984..2c84da4862a 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -98,9 +98,9 @@ module BlobHelper
ref,
path,
blob: blob,
- label: _("Replace"),
- action: "replace",
- btn_class: "default",
+ label: _("Replace"),
+ action: "replace",
+ btn_class: "default",
modal_type: "upload"
)
end
@@ -111,9 +111,9 @@ module BlobHelper
ref,
path,
blob: blob,
- label: _("Delete"),
- action: "delete",
- btn_class: "default",
+ label: _("Delete"),
+ action: "delete",
+ btn_class: "default",
modal_type: "remove"
)
end
@@ -298,7 +298,9 @@ module BlobHelper
def readable_blob(options, path, project, ref)
blob = options.fetch(:blob) do
- project.repository.blob_at(ref, path) rescue nil
+ project.repository.blob_at(ref, path)
+ rescue StandardError
+ nil
end
blob if blob&.readable_text?
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index d044a93213a..d00301678dd 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -32,8 +32,7 @@ module Ci
"project-path" => project.path,
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
- "runner-help-page-path" => help_page_path('ci/runners/index'),
- "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'),
+ "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
"total-branches" => total_branches,
"validate-tab-illustration-path" => image_path('illustrations/project-run-CICD-pipelines-sm.svg'),
"yml-help-page-path" => help_page_path('ci/yaml/index')
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 7722677e503..a67771116b9 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -40,14 +40,14 @@ module Ci
{ name: 'Crystal', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/crystal.svg') },
{ name: 'Dart', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/dart.svg') },
{ name: 'Django', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/django.svg') },
- { name: 'Docker', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/docker.svg') },
+ { name: 'Docker', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/docker.png') },
{ name: 'Elixir', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/elixir.svg') },
{ name: 'iOS-Fastlane', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/fastlane.svg'), title: 'iOS with Fastlane' },
{ name: 'Flutter', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/flutter.svg') },
{ name: 'Go', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/go_logo.svg') },
{ name: 'Gradle', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/gradle.svg') },
{ name: 'Grails', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/grails.svg') },
- { name: 'dotNET', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/dotnet.svg') },
+ { name: 'dotNET', logo: image_path('illustrations/third-party-logos/dotnet.svg') },
{ name: 'Julia', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/julia.svg') },
{ name: 'Laravel', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/laravel.svg') },
{ name: 'LaTeX', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/latex.svg') },
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 74318797069..852eaeca5e3 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -73,7 +73,7 @@ module Ci
def group_shared_runners_settings_data(group)
{
- update_path: api_v4_groups_path(id: group.id),
+ group_id: group.id,
shared_runners_setting: group.shared_runners_setting,
parent_shared_runners_setting: group.parent&.shared_runners_setting,
runner_enabled_value: Namespace::SR_ENABLED,
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 33b771eef69..1920650bc93 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -28,7 +28,7 @@ module CommitsHelper
def commit_to_html(commit, ref, project)
render partial: 'projects/commits/commit', formats: :html,
- locals: {
+ locals: {
commit: commit,
ref: ref,
project: project
@@ -137,7 +137,12 @@ module CommitsHelper
def conditionally_paginate_diff_files(diffs, paginate:, page:, per:)
if paginate
- Kaminari.paginate_array(diffs.diff_files.to_a).page(page).per(per)
+ diff_files = diffs.diff_files.to_a
+ Gitlab::Utils::BatchLoader.clear_key([:repository_blobs, diffs.project.repository])
+
+ Kaminari.paginate_array(diff_files).page(page).per(per).tap do |diff_files|
+ diff_files.each(&:add_blobs_to_batch_loader)
+ end
else
diffs.diff_files
end
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index f9d62747308..e955ad4cfda 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -1,25 +1,30 @@
# frozen_string_literal: true
module CompareHelper
- def create_mr_button?(from: params[:from], to: params[:to], source_project: @project, target_project: @target_project)
+ def create_mr_button?(source_project:, from:, to: nil, target_project: nil)
+ target_project ||= source_project.default_merge_request_target
+ to ||= target_project.default_branch
+
from.present? &&
to.present? &&
from != to &&
can?(current_user, :create_merge_request_from, source_project) &&
can?(current_user, :create_merge_request_in, target_project) &&
- target_project.repository.branch_exists?(from) &&
- source_project.repository.branch_exists?(to)
+ target_project.repository.branch_exists?(to) &&
+ source_project.repository.branch_exists?(from)
end
- def create_mr_path(from: params[:from], to: params[:to], source_project: @project, target_project: @target_project)
+ def create_mr_path(from:, source_project:, to: nil, target_project: nil, mr_params: {})
+ merge_request_params = {
+ source_branch: from
+ }
+
+ merge_request_params[:target_project_id] = target_project.id if target_project
+ merge_request_params[:target_branch] = to if to
+
project_new_merge_request_path(
- target_project,
- merge_request: {
- source_project_id: source_project.id,
- source_branch: to,
- target_project_id: target_project.id,
- target_branch: from
- }
+ source_project,
+ merge_request: merge_request_params.merge(mr_params)
)
end
@@ -32,14 +37,32 @@ module CompareHelper
def project_compare_selector_data(project, merge_request, params)
{
project_compare_index_path: project_compare_index_path(project),
- refs_project_path: refs_project_path(project),
+ source_project: { id: project.id, name: project.full_path }.to_json,
+ target_project: { id: @target_project.id, name: @target_project.full_path }.to_json,
+ 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],
- project_merge_request_path: merge_request.present? ? project_merge_request_path(project, merge_request) : '',
- create_mr_path: create_mr_button? ? create_mr_path : ''
+ params_to: params[:to]
}.tap do |data|
- data[:project_to] = { id: project.id, name: project.full_path }.to_json
- data[:projects_from] = target_projects(project).map { |project| { id: project.id, name: project.full_path } }.to_json
+ data[:projects_from] = target_projects(project).map do |target_project|
+ { id: target_project.id, name: target_project.full_path }
+ end.to_json
+
+ data[:project_merge_request_path] =
+ if merge_request.present?
+ project_merge_request_path(project, merge_request)
+ else
+ ''
+ end
+
+ # The `from` and `to` params are inverted in the compare page. The route is `/compare/:from...:to`, but the UI
+ # correctly shows `:to` as the "Source" (i.e. the `from` for MR), and `:from` as "Target" (i.e. the `to` for MR).
+ data[:create_mr_path] =
+ if create_mr_button?(from: params[:to], to: params[:from], source_project: project, target_project: @target_project)
+ create_mr_path(from: params[:to], to: params[:from], source_project: project, target_project: @target_project)
+ else
+ ''
+ end
end
end
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index bcb1f63840d..f0e1f252917 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -15,10 +15,6 @@ module DashboardHelper
merge_requests_dashboard_path(reviewer_username: current_user.username)
end
- def attention_requested_mrs_dashboard_path
- merge_requests_dashboard_path(attention: current_user.username)
- end
-
def dashboard_nav_links
@dashboard_nav_links ||= get_dashboard_nav_links
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 2623e32dbc8..333237db6a4 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -58,17 +58,17 @@ module EnvironmentsHelper
return {} unless project
{
- 'settings_path' => edit_project_settings_integration_path(project, 'prometheus'),
- 'clusters_path' => project_clusters_path(project),
- 'dashboards_endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
- 'default_branch' => project.default_branch,
- 'project_path' => project_path(project),
- 'tags_path' => project_tags_path(project),
- 'external_dashboard_url' => project.metrics_setting_external_dashboard_url,
- 'custom_metrics_path' => project_prometheus_metrics_path(project),
- 'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
- 'custom_metrics_available' => "#{custom_metrics_available?(project)}",
- 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
+ 'settings_path' => edit_project_settings_integration_path(project, 'prometheus'),
+ 'clusters_path' => project_clusters_path(project),
+ 'dashboards_endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
+ 'default_branch' => project.default_branch,
+ 'project_path' => project_path(project),
+ 'tags_path' => project_tags_path(project),
+ 'external_dashboard_url' => project.metrics_setting_external_dashboard_url,
+ 'custom_metrics_path' => project_prometheus_metrics_path(project),
+ 'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
+ 'custom_metrics_available' => "#{custom_metrics_available?(project)}",
+ 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
}
end
@@ -77,9 +77,9 @@ module EnvironmentsHelper
{
'metrics_dashboard_base_path' => metrics_dashboard_base_path(environment, project),
- 'current_environment_name' => environment.name,
- 'has_metrics' => "#{environment.has_metrics?}",
- 'environment_state' => "#{environment.state}"
+ 'current_environment_name' => environment.name,
+ 'has_metrics' => "#{environment.has_metrics?}",
+ 'environment_state' => "#{environment.state}"
}
end
@@ -98,8 +98,8 @@ module EnvironmentsHelper
return {} unless project && environment
{
- 'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
- 'dashboard_endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
+ 'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
+ 'dashboard_endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
'operations_settings_path' => project_settings_operations_path(project),
'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s,
@@ -109,14 +109,14 @@ module EnvironmentsHelper
def static_metrics_data
{
- 'documentation_path' => help_page_path('administration/monitoring/prometheus/index.md'),
+ 'documentation_path' => help_page_path('administration/monitoring/prometheus/index.md'),
'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
- 'empty_getting_started_svg_path' => image_path('illustrations/monitoring/getting_started.svg'),
- 'empty_loading_svg_path' => image_path('illustrations/monitoring/loading.svg'),
- 'empty_no_data_svg_path' => image_path('illustrations/monitoring/no_data.svg'),
- 'empty_no_data_small_svg_path' => image_path('illustrations/chart-empty-state-small.svg'),
+ 'empty_getting_started_svg_path' => image_path('illustrations/monitoring/getting_started.svg'),
+ 'empty_loading_svg_path' => image_path('illustrations/monitoring/loading.svg'),
+ 'empty_no_data_svg_path' => image_path('illustrations/monitoring/no_data.svg'),
+ 'empty_no_data_small_svg_path' => image_path('illustrations/chart-empty-state-small.svg'),
'empty_unable_to_connect_svg_path' => image_path('illustrations/monitoring/unable_to_connect.svg'),
- 'custom_dashboard_base_path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT
+ 'custom_dashboard_base_path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT
}
end
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 4ee3acd32d2..b35dc3b00cb 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -38,7 +38,7 @@ module EventsHelper
active = 'active' if @event_filter.active?(key)
link_opts = {
class: "event-filter-link",
- id: "#{key}_event_filter",
+ id: "#{key}_event_filter",
title: tooltip
}
diff --git a/app/helpers/favicon_helper.rb b/app/helpers/favicon_helper.rb
index 4a809731d97..c98c7c4909a 100644
--- a/app/helpers/favicon_helper.rb
+++ b/app/helpers/favicon_helper.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
module FaviconHelper
- def favicon_extension_whitelist
- FaviconUploader::EXTENSION_WHITELIST
- .map { |extension| "'.#{extension}'"}
+ def favicon_extension_allowlist
+ FaviconUploader::EXTENSION_ALLOWLIST
+ .map { |extension| "'.#{extension}'" }
.to_sentence
end
end
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 17812aed3ff..f74eeeb8c6a 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module FormHelper
- def form_errors(model, type: 'form', truncate: [], pajamas_alert: false)
+ def form_errors(model, type: 'form', truncate: [], pajamas_alert: true)
errors = model.errors
return unless errors.any?
@@ -25,26 +25,27 @@ module FormHelper
tag.li(message)
end.join.html_safe
- if pajamas_alert
- render Pajamas::AlertComponent.new(
- variant: :danger,
- title: headline,
- dismissible: false,
- alert_options: { id: 'error_explanation', class: 'gl-mb-5' }
- ) do |c|
- c.body do
- tag.ul(class: 'gl-pl-5 gl-mb-0') do
- messages
- end
+ render Pajamas::AlertComponent.new(
+ variant: :danger,
+ title: headline,
+ dismissible: false,
+ alert_options: { id: 'error_explanation', class: 'gl-mb-5' }
+ ) do |c|
+ c.body do
+ tag.ul(class: 'gl-pl-5 gl-mb-0') do
+ messages
end
end
+ end
+ end
+
+ def dropdown_max_select(data)
+ return data[:'max-select'] unless Feature.enabled?(:limit_reviewer_and_assignee_size)
+
+ if data[:'max-select'] && data[:'max-select'] < MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ data[:'max-select']
else
- tag.div(class: 'alert alert-danger', id: 'error_explanation') do
- tag.h4(headline) <<
- tag.ul do
- messages
- end
- end
+ MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
end
end
@@ -165,7 +166,12 @@ module FormHelper
new_options[:title] = _('Select reviewer(s)')
new_options[:data][:'dropdown-header'] = _('Reviewer(s)')
- new_options[:data].delete(:'max-select')
+
+ if Feature.enabled?(:limit_reviewer_and_assignee_size)
+ new_options[:data][:'max-select'] = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+ else
+ new_options[:data].delete(:'max-select')
+ end
new_options
end
diff --git a/app/helpers/gitlab_script_tag_helper.rb b/app/helpers/gitlab_script_tag_helper.rb
index f784bb69dd8..55653c592e5 100644
--- a/app/helpers/gitlab_script_tag_helper.rb
+++ b/app/helpers/gitlab_script_tag_helper.rb
@@ -7,7 +7,9 @@ module GitlabScriptTagHelper
# The helper also makes sure the `nonce` attribute is included in every script when the content security
# policy is enabled.
def javascript_include_tag(*sources)
- super(*sources, defer: true, nonce: true)
+ options = { defer: true }.merge(sources.extract_options!)
+ options[:nonce] = true
+ super(*sources, **options)
end
# The helper makes sure the `nonce` attribute is included in every script when the content security
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index 2021961772a..6a013a6c864 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -21,10 +21,11 @@ module Groups::GroupMembersHelper
end
def group_member_header_subtext(group)
- html_escape(_('You can invite a new member to ' \
- '%{strong_start}%{group_name}%{strong_end}.')) % { group_name: group.name,
- strong_start: '<strong>'.html_safe,
- strong_end: '</strong>'.html_safe }
+ html_escape(_("You're viewing members of %{strong_start}%{group_name}%{strong_end}.").html_safe) % {
+ group_name: group.name,
+ strong_start: '<strong>'.html_safe,
+ strong_end: '</strong>'.html_safe
+ }
end
private
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 9d152416b2e..bb92792de2d 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -134,6 +134,13 @@ module GroupsHelper
@group_projects_sort || @sort || params[:sort] || sort_value_recently_created
end
+ def subgroup_creation_data(group)
+ {
+ parent_group_name: group.parent&.name,
+ import_existing_group_path: new_group_path(parent_id: group.parent_id, anchor: 'import-group-pane')
+ }
+ end
+
def verification_for_group_creation_data
# overridden in EE
{}
@@ -144,11 +151,9 @@ module GroupsHelper
false
end
- def group_name_and_path_app_data(group)
- parent = group.parent
-
+ def group_name_and_path_app_data
{
- base_path: URI.join(root_url, parent&.full_path || "").to_s,
+ base_path: root_url,
mattermost_enabled: Gitlab.config.mattermost.enabled.to_s
}
end
@@ -156,7 +161,7 @@ module GroupsHelper
def subgroups_and_projects_list_app_data(group)
{
show_schema_markup: 'true',
- new_subgroup_path: new_group_path(parent_id: group.id),
+ new_subgroup_path: new_group_path(parent_id: group.id, anchor: 'create-group-pane'),
new_project_path: new_project_path(namespace_id: group.id),
new_subgroup_illustration: image_path('illustrations/subgroup-create-new-sm.svg'),
new_project_illustration: image_path('illustrations/project-create-new-sm.svg'),
@@ -182,7 +187,7 @@ module GroupsHelper
def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false)
link_to(group_path(group), class: "group-path #{'breadcrumb-item-text' unless for_dropdown} js-breadcrumb-item-text #{'hidable' if hidable}") do
- icon = group_icon(group, class: "avatar-tile", width: 15, height: 15) if (group.try(:avatar_url) || show_avatar) && !Rails.env.test?
+ icon = group_icon(group, alt: group.name, class: "avatar-tile", width: 15, height: 15) if group.try(:avatar_url) || show_avatar
[icon, simple_sanitize(group.name)].join.html_safe
end
end
diff --git a/app/helpers/instance_configuration_helper.rb b/app/helpers/instance_configuration_helper.rb
index b06e3ff2904..7eb14d31dc7 100644
--- a/app/helpers/instance_configuration_helper.rb
+++ b/app/helpers/instance_configuration_helper.rb
@@ -4,7 +4,7 @@ module InstanceConfigurationHelper
def instance_configuration_cell_html(value, &block)
return '-' unless value.to_s.presence
- block_given? ? yield(value) : value
+ block ? yield(value) : value
end
def instance_configuration_host(host)
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index a82a5ac0fb0..58b86dca1e0 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -5,8 +5,12 @@ module IssuablesDescriptionTemplatesHelper
include GitlabRoutingHelper
def template_dropdown_tag(issuable, &block)
- selected_template = selected_template(issuable)
- title = selected_template || _('Choose a template')
+ template_names = template_names(issuable)
+
+ selected_template = selected_template_name(template_names)
+ default_template = default_template_name(template_names, issuable)
+ title = _('Choose a template')
+
options = {
toggle_class: 'js-issuable-selector',
title: title,
@@ -17,6 +21,7 @@ module IssuablesDescriptionTemplatesHelper
data: issuable_templates(ref_project, issuable.to_ability_name),
field_name: 'issuable_template',
selected: selected_template,
+ default: default_template,
project_id: ref_project.id
}
}
@@ -32,19 +37,19 @@ module IssuablesDescriptionTemplatesHelper
@template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names(project, issuable_type.pluralize)
end
- def selected_template(issuable)
- all_templates = issuable_templates(ref_project, issuable.to_ability_name)
-
- # Only local templates will be listed if licenses for inherited templates are not present
- all_templates = all_templates.values.flatten.map { |tpl| tpl[:name] }.compact.uniq
+ def selected_template_name(template_names)
+ template_names.find { |tmpl_name| tmpl_name == params[:issuable_template] }
+ end
- template = all_templates.find { |tmpl_name| tmpl_name == params[:issuable_template] }
+ def default_template_name(template_names, issuable)
+ return if issuable.description.present? || issuable.persisted?
- unless issuable.description.present?
- template ||= all_templates.find { |tmpl_name| tmpl_name.casecmp?('default') }
- end
+ template_names.find { |tmpl_name| tmpl_name.casecmp?('default') }
+ end
- template
+ def template_names(issuable)
+ # Only local templates will be listed if licenses for inherited templates are not present
+ issuable_templates(ref_project, issuable.to_ability_name).values.flatten.map { |tpl| tpl[:name] }.compact.uniq
end
def available_service_desk_templates_for(project)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 486d5bb3866..8fd004233e2 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -147,14 +147,20 @@ module IssuablesHelper
end
def issuable_meta_author_status(author)
- return "" unless show_status_emoji?(author&.status) && status = user_status(author)
+ return "" unless author&.status&.customized? && status = user_status(author)
"#{status}".html_safe
end
def issuable_meta(issuable, project)
output = []
- output << "Created #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe
+
+ 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'), 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) }
+ else
+ output << s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) }
+ end
if issuable.is_a?(Issue) && issuable.service_desk_reply_to
output << "#{html_escape(issuable.service_desk_reply_to)} via "
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 877785c9eaf..2d0bc1bc63f 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -39,7 +39,7 @@ module LabelsHelper
def link_to_label(label, type: :issue, tooltip: true, small: false, css_class: nil, &block)
link = label.filter_path(type: type)
- if block_given?
+ if block
link_to link, class: css_class, &block
else
render_label(label, link: link, tooltip: tooltip, small: small)
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 6077a059f6f..fc558958ca3 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -266,9 +266,10 @@ module MarkupHelper
def markdown_toolbar_button(options = {})
data = options[:data].merge({ container: 'body' })
+ css_classes = %w[gl-button btn btn-default-tertiary btn-icon js-md has-tooltip] << options[:css_class].to_s
content_tag :button,
type: 'button',
- class: 'gl-button btn btn-default-tertiary btn-icon js-md has-tooltip',
+ class: css_classes.join(' '),
data: data,
title: options[:title],
aria: { label: options[:title] } do
@@ -282,8 +283,8 @@ module MarkupHelper
def asciidoc_unsafe(text, context = {})
context.reverse_merge!(
- commit: @commit,
- ref: @ref,
+ commit: @commit,
+ ref: @ref,
requested_path: @path
)
Gitlab::Asciidoc.render(text, context)
@@ -323,9 +324,9 @@ module MarkupHelper
current_user: (current_user if defined?(current_user)),
# RepositoryLinkFilter and UploadLinkFilter
- commit: @commit,
- wiki: @wiki,
- ref: @ref,
+ commit: @commit,
+ wiki: @wiki,
+ ref: @ref,
requested_path: @path
)
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index 4b1cbd3f1ae..f1f5f941edd 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -83,6 +83,24 @@ module MembersHelper
params: pagination[:params] || {}
}
end
+
+ def member_request_access_link(member)
+ user = member.user
+ member_source = member.source
+
+ member_link = link_to user.name, user, class: :highlight
+ member_role = content_tag :span, member.human_access, class: :highlight
+ target_source_link = link_to member_source.human_name, polymorphic_url([member_source, :members]), class: :highlight
+ target_type = member_source.model_name.singular
+
+ s_('Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}.')
+ .html_safe % {
+ member_link: member_link,
+ member_role: member_role,
+ target_source_link: target_source_link,
+ target_type: target_type
+ }
+ end
end
MembersHelper.prepend_mod_with('MembersHelper')
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index d840223a066..4581da4a063 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -3,23 +3,12 @@
module MergeRequestsHelper
include Gitlab::Utils::StrongMemoize
- def new_mr_path_from_push_event(event)
- target_project = event.project.default_merge_request_target
- project_new_merge_request_path(
- event.project,
- new_mr_from_push_event(event, target_project)
- )
+ def create_mr_button_from_event?(event)
+ create_mr_button?(from: event.branch_name, source_project: event.project)
end
- def new_mr_from_push_event(event, target_project)
- {
- merge_request: {
- source_project_id: event.project.id,
- target_project_id: target_project.id,
- source_branch: event.branch_name,
- target_branch: target_project.repository.root_ref
- }
- }
+ def create_mr_path_from_push_event(event)
+ create_mr_path(from: event.branch_name, source_project: event.project)
end
def mr_css_classes(mr)
@@ -29,11 +18,31 @@ module MergeRequestsHelper
classes.join(' ')
end
- def merge_path_description(merge_request, separator)
+ def merge_path_description(merge_request, with_arrow: false)
if merge_request.for_fork?
- "Project:Branches: #{@merge_request.source_project_path}:#{@merge_request.source_branch} #{separator} #{@merge_request.target_project.full_path}:#{@merge_request.target_branch}"
+ msg = if with_arrow
+ _("Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}")
+ else
+ _("Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}")
+ end
+
+ msg % {
+ source_project_path: merge_request.source_project_path,
+ source_branch: merge_request.source_branch,
+ target_project_path: merge_request.target_project.full_path,
+ target_branch: merge_request.target_branch
+ }
else
- "Branches: #{@merge_request.source_branch} #{separator} #{@merge_request.target_branch}"
+ msg = if with_arrow
+ _("Branches: %{source_branch} → %{target_branch}")
+ else
+ _("Branches: %{source_branch} to %{target_branch}")
+ end
+
+ msg % {
+ source_branch: merge_request.source_branch,
+ target_branch: merge_request.target_branch
+ }
end
end
@@ -150,20 +159,11 @@ module MergeRequestsHelper
review_requested_count = review_requested_merge_requests_count
total_count = assigned_count + review_requested_count
- counts = {
+ {
assigned: assigned_count,
review_requested: review_requested_count,
total: total_count
}
-
- if current_user&.mr_attention_requests_enabled?
- attention_requested_count = attention_requested_merge_requests_count
-
- counts[:attention_requested_count] = attention_requested_count
- counts[:total] = attention_requested_count
- end
-
- counts
end
end
@@ -225,10 +225,6 @@ module MergeRequestsHelper
current_user.review_requested_open_merge_requests_count
end
- def attention_requested_merge_requests_count
- current_user.attention_requested_open_merge_requests_count
- end
-
def default_suggestion_commit_message
@project.suggestion_commit_message.presence || Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
end
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index a50629b7996..60796e628a3 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -81,13 +81,6 @@ module NamespacesHelper
group.namespace_settings.public_send(method_name, **args) # rubocop:disable GitlabSecurity/PublicSend
end
- def namespaces_as_json(selected = :current_user)
- {
- group: formatted_namespaces(current_user.manageable_groups_with_routes),
- user: formatted_namespaces([current_user.namespace])
- }.to_json
- end
-
def pipeline_usage_app_data(namespace)
{
namespace_actual_plan_name: namespace.actual_plan_name,
@@ -129,17 +122,6 @@ module NamespacesHelper
[group_label.camelize, elements]
end
-
- def formatted_namespaces(namespaces)
- namespaces.sort_by(&:human_name).map! do |n|
- {
- id: n.id,
- display_path: n.full_path,
- human_name: n.human_name,
- name: n.name
- }
- end
- end
end
NamespacesHelper.prepend_mod_with('NamespacesHelper')
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index fb8fafe59f3..dc7d8049556 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -42,7 +42,7 @@ module Nav
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_subgroup',
title: _('New subgroup'),
- href: new_group_path(parent_id: group.id),
+ href: new_group_path(parent_id: group.id, anchor: 'create-group-pane'),
data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
)
)
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index 3ceb60251c2..efec6f2d0d8 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -81,13 +81,6 @@ module Nav
**snippets_menu_item_attrs
)
end
-
- builder.add_secondary_menu_item(
- id: 'help',
- title: _('Help'),
- icon: 'question-o',
- href: help_path
- )
end
def build_view_model(builder:, project:, group:)
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index ec64746d6b6..b52357bc891 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -63,4 +63,27 @@ module PackagesHelper
Gitlab.config.packages.enabled &&
Ability.allowed?(current_user, :admin_package, project)
end
+
+ def cleanup_settings_data
+ {
+ project_id: @project.id,
+ project_path: @project.full_path,
+ cadence_options: cadence_options.to_json,
+ keep_n_options: keep_n_options.to_json,
+ older_than_options: older_than_options.to_json,
+ is_admin: current_user&.admin.to_s,
+ admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
+ enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
+ help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
+ show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
+ tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples')
+ }
+ end
+
+ def settings_data
+ cleanup_settings_data.merge(
+ show_container_registry_settings: show_container_registry_settings(@project).to_s,
+ show_package_registry_settings: show_package_registry_settings(@project).to_s
+ )
+ end
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 39a57e786ed..57afe0ed0be 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -26,7 +26,7 @@ module PreferencesHelper
def localized_dashboard_choices
{
projects: _("Your Projects (default)"),
- stars: _("Starred Projects"),
+ stars: _("Starred Projects"),
project_activity: _("Your Projects' Activity"),
starred_project_activity: _("Starred Projects' Activity"),
followed_user_activity: _("Followed Users' Activity"),
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 20d0dd9b30c..104026ff21e 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -31,10 +31,6 @@ module ProfilesHelper
Types::AvailabilityEnum.enum
end
- def user_status_set_to_busy?(status)
- status&.availability == availability_values[:busy]
- end
-
def middle_dot_divider_classes(stacking, breakpoint)
['gl-mb-3'].tap do |classes|
if stacking
diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb
index 3b3fe13e58a..5f2a9f7bf21 100644
--- a/app/helpers/projects/pipeline_helper.rb
+++ b/app/helpers/projects/pipeline_helper.rb
@@ -14,7 +14,14 @@ module Projects
metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, format: :json),
pipeline_iid: pipeline.iid,
pipeline_project_path: project.full_path,
- total_job_count: pipeline.total_size
+ total_job_count: pipeline.total_size,
+ summary_endpoint: summary_project_pipeline_tests_path(project, pipeline, format: :json),
+ suite_endpoint: project_pipeline_test_path(project, pipeline, suite_name: 'suite', format: :json),
+ blob_path: project_blob_path(project, pipeline.sha),
+ has_test_report: pipeline.has_test_reports?,
+ empty_state_image_path: image_path('illustrations/empty-state/empty-test-cases-lg.svg'),
+ artifacts_expired_image_path: image_path('illustrations/pipeline.svg'),
+ tests_count: pipeline.test_report_summary.total[:count]
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 2ece3e87500..dfc270adf8b 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -458,6 +458,16 @@ module ProjectsHelper
end
end
+ def project_coverage_chart_data_attributes(daily_coverage_options, ref)
+ {
+ graph_endpoint: "#{daily_coverage_options[:graph_api_path]}?#{daily_coverage_options[:base_params].to_query}",
+ graph_start_date: "#{daily_coverage_options[:base_params][:start_date].strftime('%b %d')}",
+ graph_end_date: "#{daily_coverage_options[:base_params][:end_date].strftime('%b %d')}",
+ graph_ref: "#{ref}",
+ graph_csv_path: "#{daily_coverage_options[:download_path]}?#{daily_coverage_options[:base_params].to_query}"
+ }
+ end
+
private
def configure_oauth_import_message(provider, help_url)
@@ -473,35 +483,35 @@ module ProjectsHelper
def tab_ability_map
{
- cycle_analytics: :read_cycle_analytics,
- environments: :read_environment,
+ cycle_analytics: :read_cycle_analytics,
+ environments: :read_environment,
metrics_dashboards: :metrics_dashboard,
- milestones: :read_milestone,
- snippets: :read_snippet,
- settings: :admin_project,
- builds: :read_build,
- clusters: :read_cluster,
- serverless: :read_cluster,
- terraform: :read_terraform_state,
- error_tracking: :read_sentry_issue,
- alert_management: :read_alert_management_alert,
- incidents: :read_issue,
- labels: :read_label,
- issues: :read_issue,
- project_members: :read_project_member,
- wiki: :read_wiki,
- feature_flags: :read_feature_flag,
- analytics: :read_analytics
+ milestones: :read_milestone,
+ snippets: :read_snippet,
+ settings: :admin_project,
+ builds: :read_build,
+ clusters: :read_cluster,
+ serverless: :read_cluster,
+ terraform: :read_terraform_state,
+ error_tracking: :read_sentry_issue,
+ alert_management: :read_alert_management_alert,
+ incidents: :read_issue,
+ labels: :read_label,
+ issues: :read_issue,
+ project_members: :read_project_member,
+ wiki: :read_wiki,
+ feature_flags: :read_feature_flag,
+ analytics: :read_analytics
}
end
def search_tab_ability_map
@search_tab_ability_map ||= tab_ability_map.merge(
- blobs: :download_code,
- commits: :download_code,
+ blobs: :download_code,
+ commits: :download_code,
merge_requests: :read_merge_request,
- notes: [:read_merge_request, :download_code, :read_issue, :read_snippet],
- members: :read_project_member
+ notes: [:read_merge_request, :download_code, :read_issue, :read_snippet],
+ members: :read_project_member
)
end
@@ -629,7 +639,10 @@ module ProjectsHelper
warnAboutPotentiallyUnwantedCharacters: project.warn_about_potentially_unwanted_characters?,
enforceAuthChecksOnUploads: project.enforce_auth_checks_on_uploads?,
securityAndComplianceAccessLevel: project.security_and_compliance_access_level,
- containerRegistryAccessLevel: feature.container_registry_access_level
+ containerRegistryAccessLevel: feature.container_registry_access_level,
+ environmentsAccessLevel: feature.environments_access_level,
+ featureFlagsAccessLevel: feature.feature_flags_access_level,
+ releasesAccessLevel: feature.releases_access_level
}
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index ecbcaec27bc..dc53be330fe 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -14,28 +14,42 @@ module SearchHelper
:project_ids
].freeze
- def search_autocomplete_opts(term)
+ def search_autocomplete_opts(term, filter: nil)
return unless current_user
- resources_results = [
- recent_items_autocomplete(term),
+ results = case filter&.to_sym
+ when :search
+ resource_results(term)
+ when :generic
+ [
+ recent_items_autocomplete(term),
+ generic_results(term)
+ ]
+ else
+ [
+ recent_items_autocomplete(term),
+ resource_results(term),
+ generic_results(term)
+ ]
+ end
+
+ results.flatten { |item| item[:label] }
+ end
+
+ def resource_results(term)
+ [
groups_autocomplete(term),
projects_autocomplete(term),
issue_autocomplete(term)
].flatten
+ end
+ def generic_results(term)
search_pattern = Regexp.new(Regexp.escape(term), "i")
generic_results = project_autocomplete + default_autocomplete + help_autocomplete
generic_results.concat(default_autocomplete_admin) if current_user.admin?
- generic_results.select! { |result| result[:label] =~ search_pattern }
-
- [
- resources_results,
- generic_results
- ].flatten do |item|
- item[:label]
- end
+ generic_results.select { |result| result[:label] =~ search_pattern }
end
def recent_items_autocomplete(term)
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index ef79e2bc86f..58f0af883f5 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -6,39 +6,39 @@ module SortingHelper
# rubocop: disable Metrics/AbcSize
def sort_options_hash
{
- sort_value_created_date => sort_title_created_date,
- sort_value_downvotes => sort_title_downvotes,
- sort_value_due_date => sort_title_due_date,
- sort_value_due_date_later => sort_title_due_date_later,
- sort_value_due_date_soon => sort_title_due_date_soon,
- sort_value_label_priority => sort_title_label_priority,
- sort_value_largest_group => sort_title_largest_group,
- sort_value_largest_repo => sort_title_largest_repo,
- sort_value_milestone => sort_title_milestone,
- sort_value_milestone_later => sort_title_milestone_later,
- sort_value_milestone_soon => sort_title_milestone_soon,
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_oldest_created => sort_title_oldest_created,
- sort_value_oldest_signin => sort_title_oldest_signin,
- sort_value_oldest_updated => sort_title_oldest_updated,
- sort_value_recently_created => sort_title_recently_created,
- sort_value_recently_signin => sort_title_recently_signin,
- sort_value_recently_updated => sort_title_recently_updated,
- sort_value_popularity => sort_title_popularity,
- sort_value_priority => sort_title_priority,
- sort_value_merged_date => sort_title_merged_date,
- sort_value_merged_recently => sort_title_merged_recently,
- sort_value_merged_earlier => sort_title_merged_earlier,
- sort_value_closed_date => sort_title_closed_date,
- sort_value_closed_recently => sort_title_closed_recently,
- sort_value_closed_earlier => sort_title_closed_earlier,
- sort_value_upvotes => sort_title_upvotes,
- sort_value_contacted_date => sort_title_contacted_date,
+ sort_value_created_date => sort_title_created_date,
+ sort_value_downvotes => sort_title_downvotes,
+ sort_value_due_date => sort_title_due_date,
+ sort_value_due_date_later => sort_title_due_date_later,
+ sort_value_due_date_soon => sort_title_due_date_soon,
+ sort_value_label_priority => sort_title_label_priority,
+ sort_value_largest_group => sort_title_largest_group,
+ sort_value_largest_repo => sort_title_largest_repo,
+ sort_value_milestone => sort_title_milestone,
+ sort_value_milestone_later => sort_title_milestone_later,
+ sort_value_milestone_soon => sort_title_milestone_soon,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_signin => sort_title_oldest_signin,
+ sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_recently_created => sort_title_recently_created,
+ sort_value_recently_signin => sort_title_recently_signin,
+ sort_value_recently_updated => sort_title_recently_updated,
+ sort_value_popularity => sort_title_popularity,
+ sort_value_priority => sort_title_priority,
+ sort_value_merged_date => sort_title_merged_date,
+ sort_value_merged_recently => sort_title_merged_recently,
+ sort_value_merged_earlier => sort_title_merged_earlier,
+ sort_value_closed_date => sort_title_closed_date,
+ sort_value_closed_recently => sort_title_closed_recently,
+ sort_value_closed_earlier => sort_title_closed_earlier,
+ sort_value_upvotes => sort_title_upvotes,
+ sort_value_contacted_date => sort_title_contacted_date,
sort_value_relative_position => sort_title_relative_position,
- sort_value_size => sort_title_size,
- sort_value_expire_date => sort_title_expire_date,
- sort_value_title => sort_title_title
+ sort_value_size => sort_title_size,
+ sort_value_expire_date => sort_title_expire_date,
+ sort_value_title => sort_title_title
}
end
# rubocop: enable Metrics/AbcSize
@@ -47,19 +47,19 @@ module SortingHelper
use_old_sorting = Feature.disabled?(:project_list_filter_bar) || current_controller?('admin/projects')
options = {
- sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_latest_activity => sort_title_latest_activity,
sort_value_recently_created => sort_title_created_date,
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_stars_desc => sort_title_stars
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
+ sort_value_stars_desc => sort_title_stars
}
if use_old_sorting
options = options.merge({
- sort_value_oldest_activity => sort_title_oldest_activity,
- sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_activity => sort_title_oldest_activity,
+ sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_created => sort_title_recently_created,
- sort_value_stars_desc => sort_title_most_stars
+ sort_value_stars_desc => sort_title_most_stars
})
end
@@ -73,52 +73,52 @@ module SortingHelper
def forks_sort_options_hash
{
sort_value_recently_created => sort_title_created_date,
- sort_value_oldest_created => sort_title_created_date,
- sort_value_latest_activity => sort_title_latest_activity,
- sort_value_oldest_activity => sort_title_latest_activity
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_oldest_activity => sort_title_latest_activity
}
end
def projects_sort_option_titles
# Only used for the project filter search bar
projects_sort_options_hash.merge({
- sort_value_oldest_activity => sort_title_latest_activity,
- sort_value_oldest_created => sort_title_created_date,
- sort_value_name_desc => sort_title_name,
- sort_value_stars_asc => sort_title_stars
+ sort_value_oldest_activity => sort_title_latest_activity,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_name_desc => sort_title_name,
+ sort_value_stars_asc => sort_title_stars
})
end
def projects_reverse_sort_options_hash
{
- sort_value_latest_activity => sort_value_oldest_activity,
+ sort_value_latest_activity => sort_value_oldest_activity,
sort_value_recently_created => sort_value_oldest_created,
- sort_value_name => sort_value_name_desc,
- sort_value_stars_desc => sort_value_stars_asc,
- sort_value_oldest_activity => sort_value_latest_activity,
- sort_value_oldest_created => sort_value_recently_created,
- sort_value_name_desc => sort_value_name,
- sort_value_stars_asc => sort_value_stars_desc
+ sort_value_name => sort_value_name_desc,
+ sort_value_stars_desc => sort_value_stars_asc,
+ sort_value_oldest_activity => sort_value_latest_activity,
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_name_desc => sort_value_name,
+ sort_value_stars_asc => sort_value_stars_desc
}
end
def forks_reverse_sort_options_hash
{
sort_value_recently_created => sort_value_oldest_created,
- sort_value_oldest_created => sort_value_recently_created,
- sort_value_latest_activity => sort_value_oldest_activity,
- sort_value_oldest_activity => sort_value_latest_activity
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_latest_activity => sort_value_oldest_activity,
+ sort_value_oldest_activity => sort_value_latest_activity
}
end
def groups_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created,
- sort_value_latest_activity => sort_title_recently_updated,
- sort_value_oldest_activity => sort_title_oldest_updated
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_latest_activity => sort_title_recently_updated,
+ sort_value_oldest_activity => sort_title_oldest_updated
}
end
@@ -136,27 +136,27 @@ module SortingHelper
def milestones_sort_options_hash
{
- sort_value_due_date_soon => sort_title_due_date_soon,
- sort_value_due_date_later => sort_title_due_date_later,
- sort_value_start_date_soon => sort_title_start_date_soon,
+ sort_value_due_date_soon => sort_title_due_date_soon,
+ sort_value_due_date_later => sort_title_due_date_later,
+ sort_value_start_date_soon => sort_title_start_date_soon,
sort_value_start_date_later => sort_title_start_date_later,
- sort_value_name => sort_title_name_asc,
- sort_value_name_desc => sort_title_name_desc
+ sort_value_name => sort_title_name_asc,
+ sort_value_name_desc => sort_title_name_desc
}
end
def branches_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_name => sort_title_name,
+ sort_value_oldest_updated => sort_title_oldest_updated,
sort_value_recently_updated => sort_title_recently_updated
}
end
def tags_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_name => sort_title_name,
+ sort_value_oldest_updated => sort_title_oldest_updated,
sort_value_recently_updated => sort_title_recently_updated
}
end
@@ -240,7 +240,7 @@ module SortingHelper
def audit_logs_sort_order_hash
{
sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created
+ sort_value_oldest_created => sort_title_oldest_created
}
end
@@ -336,31 +336,31 @@ module SortingHelper
def packages_sort_options_hash
{
- sort_value_recently_created => sort_title_created_date,
- sort_value_oldest_created => sort_title_created_date,
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name,
- sort_value_version_desc => sort_title_version,
- sort_value_version_asc => sort_title_version,
- sort_value_type_desc => sort_title_type,
- sort_value_type_asc => sort_title_type,
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name,
+ sort_value_version_desc => sort_title_version,
+ sort_value_version_asc => sort_title_version,
+ sort_value_type_desc => sort_title_type,
+ sort_value_type_asc => sort_title_type,
sort_value_project_name_desc => sort_title_project_name,
- sort_value_project_name_asc => sort_title_project_name
+ sort_value_project_name_asc => sort_title_project_name
}
end
def packages_reverse_sort_order_hash
{
- sort_value_recently_created => sort_value_oldest_created,
- sort_value_oldest_created => sort_value_recently_created,
- sort_value_name => sort_value_name_desc,
- sort_value_name_desc => sort_value_name,
- sort_value_version_desc => sort_value_version_asc,
- sort_value_version_asc => sort_value_version_desc,
- sort_value_type_desc => sort_value_type_asc,
- sort_value_type_asc => sort_value_type_desc,
+ sort_value_recently_created => sort_value_oldest_created,
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_name => sort_value_name_desc,
+ sort_value_name_desc => sort_value_name,
+ sort_value_version_desc => sort_value_version_asc,
+ sort_value_version_asc => sort_value_version_desc,
+ sort_value_type_desc => sort_value_type_asc,
+ sort_value_type_asc => sort_value_type_desc,
sort_value_project_name_desc => sort_value_project_name_asc,
- sort_value_project_name_asc => sort_value_project_name_desc
+ sort_value_project_name_asc => sort_value_project_name_desc
}
end
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index ca81d5af4af..9e516d726c1 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -24,29 +24,89 @@ module StorageHelper
_("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}") % counters
end
- def storage_enforcement_banner_info(namespace)
- root_ancestor = namespace.root_ancestor
+ def storage_enforcement_banner_info(context)
+ root_ancestor = context.root_ancestor
- return unless can?(current_user, :maintain_namespace, root_ancestor)
- return if root_ancestor.paid?
- return unless future_enforcement_date?(root_ancestor)
- return if user_dismissed_storage_enforcement_banner?(root_ancestor)
- return unless ::Feature.enabled?(:namespace_storage_limit_show_preenforcement_banner, root_ancestor)
+ return unless should_show_storage_enforcement_banner?(context, current_user, root_ancestor)
+
+ text_args = storage_enforcement_banner_text_args(root_ancestor, context)
+
+ text_paragraph_2 = if root_ancestor.user_namespace?
+ html_escape_once(s_("UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. " \
+ "View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more%{link_end} " \
+ "about how to reduce your storage.")).html_safe % text_args[:p2]
+ else
+ html_escape_once(s_("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}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}" \
+ )).html_safe % text_args[:p2]
+ end
{
- text: html_escape_once(s_("UsageQuota|From %{storage_enforcement_date} storage limits will apply to this namespace. " \
- "You are currently using %{used_storage} of namespace storage. " \
- "View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}.")).html_safe %
- { storage_enforcement_date: root_ancestor.storage_enforcement_date, used_storage: storage_counter(root_ancestor.root_storage_statistics&.storage_size || 0), strong_start: "<strong>".html_safe, strong_end: "</strong>".html_safe, namespace_type: root_ancestor.type },
+ text_paragraph_1: html_escape_once(s_("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}.")).html_safe % text_args[:p1],
+ text_paragraph_2: text_paragraph_2,
+ text_paragraph_3: html_escape_once(s_("UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information.")).html_safe % text_args[:p3],
variant: 'warning',
+ namespace_id: root_ancestor.id,
callouts_path: root_ancestor.user_namespace? ? callouts_path : group_callouts_path,
- callouts_feature_name: storage_enforcement_banner_user_callouts_feature_name(root_ancestor),
- learn_more_link: link_to(_('Learn more.'), help_page_path('/'), rel: 'noopener noreferrer', target: '_blank')
+ callouts_feature_name: storage_enforcement_banner_user_callouts_feature_name(root_ancestor)
}
end
private
+ def should_show_storage_enforcement_banner?(context, current_user, root_ancestor)
+ return false unless user_allowed_storage_enforcement_banner?(context, current_user, root_ancestor)
+ return false if root_ancestor.paid?
+ return false unless future_enforcement_date?(root_ancestor)
+ return false if user_dismissed_storage_enforcement_banner?(root_ancestor)
+
+ ::Feature.enabled?(:namespace_storage_limit_show_preenforcement_banner, root_ancestor)
+ end
+
+ def user_allowed_storage_enforcement_banner?(context, current_user, root_ancestor)
+ return can?(current_user, :maintainer_access, context) unless context.respond_to?(:user_namespace?) && context.user_namespace?
+
+ can?(current_user, :owner_access, context)
+ end
+
+ def storage_enforcement_banner_text_args(root_ancestor, context)
+ strong_tags = {
+ strong_start: "<strong>".html_safe,
+ strong_end: "</strong>".html_safe
+ }
+
+ extra_message = if context.is_a?(Project)
+ html_escape_once(s_("UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "))
+ .html_safe % strong_tags.merge(context_name: context.name)
+ elsif !context.root?
+ html_escape_once(s_("UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "))
+ .html_safe % strong_tags.merge(context_name: context.name)
+ else
+ ''
+ end
+
+ {
+ p1: {
+ storage_enforcement_date: root_ancestor.storage_enforcement_date,
+ namespace_name: root_ancestor.name,
+ extra_message: extra_message,
+ rollout_link_start: '<a href="%{url}" >'.html_safe % { url: help_page_path('user/usage_quotas', anchor: 'namespace-storage-limit-enforcement-schedule') },
+ link_end: "</a>".html_safe
+ }.merge(strong_tags),
+ p2: {
+ used_storage: storage_counter(root_ancestor.root_storage_statistics&.storage_size || 0),
+ docs_link_start: '<a href="%{url}" >'.html_safe % { url: help_page_path('user/usage_quotas', anchor: 'manage-your-storage-usage') },
+ link_end: "</a>".html_safe
+ }.merge(strong_tags),
+ p3: {
+ faq_link_start: '<a href="%{url}" >'.html_safe % { url: "#{Gitlab::Saas.about_pricing_url}faq-efficient-free-tier/#storage-limits-on-gitlab-saas-free-tier" },
+ link_end: "</a>".html_safe
+ }
+ }
+ end
+
def storage_enforcement_banner_user_callouts_feature_name(namespace)
"storage_enforcement_banner_#{storage_enforcement_banner_threshold(namespace)}_enforcement_threshold"
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 5ab70115f34..a957c9ce9e0 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -30,6 +30,7 @@ module SystemNoteHelper
'locked' => 'lock',
'unlocked' => 'lock-open',
'due_date' => 'calendar',
+ 'start_date_or_due_date' => 'calendar',
'health_status' => 'status-health',
'designs_added' => 'doc-image',
'designs_modified' => 'doc-image',
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index dbbe7069ca4..04619ad3bda 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -17,7 +17,7 @@ module TabHelper
class: [*html_options[:class], gl_tabs_classes].join(' ')
)
- content = capture(&block) if block_given?
+ content = capture(&block) if block
content_tag(:ul, content, html_options)
end
@@ -35,7 +35,7 @@ module TabHelper
link_classes = %w[nav-link gl-tab-nav-item]
active_link_classes = %w[active gl-tab-nav-item-active]
- if block_given?
+ if block
# Shift params to skip the omitted "name" param
html_options = options
options = name
@@ -54,7 +54,7 @@ module TabHelper
tab_class = %w[nav-item].push(*extra_tab_classes)
content_tag(:li, class: tab_class) do
- if block_given?
+ if block
link_to(options, html_options, &block)
else
link_to(name, options, html_options)
@@ -150,7 +150,7 @@ module TabHelper
o[:class] = [*o[:class], klass].join(' ')
o[:class].strip!
- if block_given?
+ if block
content_tag(:li, capture(&block), o)
else
content_tag(:li, nil, o)
diff --git a/app/helpers/time_zone_helper.rb b/app/helpers/time_zone_helper.rb
index d16f13304e5..29bd5a84651 100644
--- a/app/helpers/time_zone_helper.rb
+++ b/app/helpers/time_zone_helper.rb
@@ -18,7 +18,7 @@ module TimeZoneHelper
#
def timezone_data(format: :short)
attrs = TIME_ZONE_FORMAT_ATTRS.fetch(format) do
- valid_formats = TIME_ZONE_FORMAT_ATTRS.keys.map { |k| ":#{k}"}.join(", ")
+ valid_formats = TIME_ZONE_FORMAT_ATTRS.keys.map { |k| ":#{k}" }.join(", ")
raise ArgumentError, "Invalid format :#{format}. Valid formats are #{valid_formats}."
end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index f87125af07d..5977f51cab1 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -23,7 +23,6 @@ module TodosHelper
when Todo::APPROVAL_REQUIRED then "set #{todo_action_subject(todo)} as an approver for"
when Todo::UNMERGEABLE then 'Could not merge'
when Todo::MERGE_TRAIN_REMOVED then "Removed from Merge Train:"
- when Todo::ATTENTION_REQUESTED then 'requested your attention on'
end
end
@@ -131,11 +130,11 @@ module TodosHelper
def todos_filter_params
{
- state: params[:state],
+ state: params[:state],
project_id: params[:project_id],
- author_id: params[:author_id],
- type: params[:type],
- action_id: params[:action_id]
+ author_id: params[:author_id],
+ type: params[:type],
+ action_id: params[:action_id]
}
end
@@ -179,7 +178,7 @@ module TodosHelper
end
def todo_actions_dropdown_label(selected_action_id, default_action)
- selected_action = todo_actions_options.find { |action| action[:id] == selected_action_id.to_i}
+ selected_action = todo_actions_options.find { |action| action[:id] == selected_action_id.to_i }
selected_action ? selected_action[:text] : default_action
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 4ea2512bc67..cae2addea9c 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -15,11 +15,11 @@ module UsersHelper
end
def user_email_help_text(user)
- return 'We also use email for avatar detection if no avatar is uploaded.' unless user.unconfirmed_email.present?
+ return _('We also use email for avatar detection if no avatar is uploaded.') unless user.unconfirmed_email.present?
- confirmation_link = link_to 'Resend confirmation e-mail', user_confirmation_path(user: { email: @user.unconfirmed_email }), method: :post
+ confirmation_link = link_to _('Resend confirmation e-mail'), user_confirmation_path(user: { email: user.unconfirmed_email }), method: :post
- h('Please click the link in the confirmation email before continuing. It was sent to ') +
+ h(_('Please click the link in the confirmation email before continuing. It was sent to ')) +
content_tag(:strong) { user.unconfirmed_email } + h('.') +
content_tag(:p) { confirmation_link }
end
@@ -67,12 +67,6 @@ module UsersHelper
"access:#{max_project_member_access(project)}"
end
- def show_status_emoji?(status)
- return false unless status
-
- status.message.present? || status.emoji != UserStatus::DEFAULT_EMOJI
- end
-
def user_status(user)
return unless user
diff --git a/app/helpers/webpack_helper.rb b/app/helpers/webpack_helper.rb
index 64900714327..ba3c232bec4 100644
--- a/app/helpers/webpack_helper.rb
+++ b/app/helpers/webpack_helper.rb
@@ -83,16 +83,8 @@ module WebpackHelper
end
def webpack_public_host
- # We do not proxy the webpack output in the 'test' environment,
- # so we must reference the webpack dev server directly.
- if Rails.env.test? && Gitlab.config.webpack.dev_server.enabled
- host = Gitlab.config.webpack.dev_server.host
- port = Gitlab.config.webpack.dev_server.port
- protocol = Gitlab.config.webpack.dev_server.https ? 'https' : 'http'
- "#{protocol}://#{host}:#{port}"
- else
- ActionController::Base.asset_host.try(:chomp, '/')
- end
+ # We proxy webpack output in 'test' and 'dev' environment, so we can just use asset_host
+ ActionController::Base.asset_host.try(:chomp, '/')
end
def webpack_public_path
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 02ea3c1b010..d6ffd3deafe 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -121,11 +121,11 @@ module WikiHelper
def wiki_page_tracking_context(page)
{
- 'wiki-format' => page.format,
- 'wiki-title-size' => page.title.bytesize,
- 'wiki-content-size' => page.raw_content.bytesize,
+ 'wiki-format' => page.format,
+ 'wiki-title-size' => page.title.bytesize,
+ 'wiki-content-size' => page.raw_content.bytesize,
'wiki-directory-nest-level' => page.path.scan('/').count,
- 'wiki-container-type' => page.wiki.container.class.name
+ 'wiki-container-type' => page.wiki.container.class.name
}
end
diff --git a/app/mailers/abuse_report_mailer.rb b/app/mailers/abuse_report_mailer.rb
index 20aabb6fe58..1fa85064c57 100644
--- a/app/mailers/abuse_report_mailer.rb
+++ b/app/mailers/abuse_report_mailer.rb
@@ -11,8 +11,8 @@ class AbuseReportMailer < ApplicationMailer
@abuse_report = AbuseReport.find(abuse_report_id)
mail(
- to: Gitlab::CurrentSettings.abuse_notification_email,
- subject: "#{@abuse_report.user.name} (#{@abuse_report.user.username}) was reported for abuse"
+ to: Gitlab::CurrentSettings.abuse_notification_email,
+ subject: "#{@abuse_report.user.name} (#{@abuse_report.user.username}) was reported for abuse"
)
end
diff --git a/app/mailers/emails/admin_notification.rb b/app/mailers/emails/admin_notification.rb
index 9d02d4132a1..3766b4447d1 100644
--- a/app/mailers/emails/admin_notification.rb
+++ b/app/mailers/emails/admin_notification.rb
@@ -15,23 +15,7 @@ module Emails
email = user.notification_email_or_default
mail to: email, subject: "Unsubscribed from GitLab administrator notifications"
end
-
- def user_auto_banned_email(admin_id, user_id, max_project_downloads:, within_seconds:, group: nil)
- admin = User.find(admin_id)
- @user = User.find(user_id)
- @max_project_downloads = max_project_downloads
- @within_minutes = within_seconds / 60
- @ban_scope = if group.present?
- _('your group (%{group_name})' % { group_name: group.name })
- else
- _('your GitLab instance')
- end
-
- Gitlab::I18n.with_locale(admin.preferred_language) do
- email_with_layout(
- to: admin.notification_email_or_default,
- subject: subject(_("We've detected unusual activity")))
- end
- end
end
end
+
+Emails::AdminNotification.prepend_mod
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 6a2b447f4a0..fc944c34166 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -104,13 +104,6 @@ module Emails
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
- def attention_requested_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
- setup_merge_request_mail(merge_request_id, recipient_id)
-
- @updated_by = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
- end
-
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index ed3fa28b15f..5b8471abb0f 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -51,9 +51,9 @@ module Emails
add_project_headers
headers['X-GitLab-Author'] = @message.author_username
- mail(from: sender(@message.author_id, send_from_user_email: @message.send_from_committer_email?),
- reply_to: @message.reply_to,
- subject: @message.subject)
+ mail(from: sender(@message.author_id, send_from_user_email: @message.send_from_committer_email?),
+ reply_to: @message.reply_to,
+ subject: @message.subject)
end
def prometheus_alert_fired_email(project, user, alert)
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 17b46f929c3..579f2c38ae6 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -790,10 +790,10 @@ class ApplicationSetting < ApplicationRecord
def parsed_kroki_url
@parsed_kroki_url ||= Gitlab::UrlBlocker.validate!(kroki_url, schemes: %w(http https), enforce_sanitization: true)[0]
- rescue Gitlab::UrlBlocker::BlockedUrlError => error
+ rescue Gitlab::UrlBlocker::BlockedUrlError => e
self.errors.add(
:kroki_url,
- "is not valid. #{error}"
+ "is not valid. #{e}"
)
end
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index e9a0a156121..4d377855dea 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -122,7 +122,7 @@ module ApplicationSettingImplementation
password_authentication_enabled_for_git: true,
password_authentication_enabled_for_web: Settings.gitlab['signin_enabled'],
performance_bar_allowed_group_id: nil,
- personal_access_token_prefix: nil,
+ personal_access_token_prefix: 'glpat-',
plantuml_enabled: false,
plantuml_url: nil,
polling_interval_multiplier: 1,
diff --git a/app/models/approval.rb b/app/models/approval.rb
index 899ea466315..9ded44fe425 100644
--- a/app/models/approval.rb
+++ b/app/models/approval.rb
@@ -2,11 +2,12 @@
class Approval < ApplicationRecord
include CreatedAtFilterable
+ include Importable
belongs_to :user
belongs_to :merge_request
- validates :merge_request_id, presence: true
+ validates :merge_request_id, presence: true, unless: :importing?
validates :user_id, presence: true, uniqueness: { scope: [:merge_request_id] }
scope :with_user, -> { joins(:user) }
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 8e8e9389e2d..0ad17cd8869 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -86,6 +86,18 @@ class AuditEvent < ApplicationRecord
end
end
+ def target_type
+ super || details[:target_type]
+ end
+
+ def target_id
+ details[:target_id]
+ end
+
+ def target_details
+ super || details[:target_details]
+ end
+
private
def sanitize_message
diff --git a/app/models/authentication_event.rb b/app/models/authentication_event.rb
index 0ed197f32df..d5a5079acd6 100644
--- a/app/models/authentication_event.rb
+++ b/app/models/authentication_event.rb
@@ -20,7 +20,7 @@ class AuthenticationEvent < ApplicationRecord
}
scope :for_provider, ->(provider) { where(provider: provider) }
- scope :ldap, -> { where('provider LIKE ?', 'ldap%')}
+ scope :ldap, -> { where('provider LIKE ?', 'ldap%') }
def self.providers
STATIC_PROVIDERS | Devise.omniauth_providers.map(&:to_s)
diff --git a/app/models/blob.rb b/app/models/blob.rb
index a12d856dc36..20d7c230aa2 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -93,8 +93,8 @@ class Blob < SimpleDelegator
end
def self.lazy(repository, commit_id, path, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE)
- BatchLoader.for([commit_id, path]).batch(key: repository) do |items, loader, args|
- args[:key].blobs_at(items, blob_size_limit: blob_size_limit).each do |blob|
+ BatchLoader.for([commit_id, path]).batch(key: [:repository_blobs, repository]) do |items, loader, args|
+ args[:key].last.blobs_at(items, blob_size_limit: blob_size_limit).each do |blob|
loader.call([blob.commit_id, blob.path], blob) if blob
end
end
diff --git a/app/models/blob_viewer/metrics_dashboard_yml.rb b/app/models/blob_viewer/metrics_dashboard_yml.rb
index 88643253d3d..cac6b2192d0 100644
--- a/app/models/blob_viewer/metrics_dashboard_yml.rb
+++ b/app/models/blob_viewer/metrics_dashboard_yml.rb
@@ -36,10 +36,10 @@ module BlobViewer
yaml = ::Gitlab::Config::Loader::Yaml.new(blob.data).load_raw!
::PerformanceMonitoring::PrometheusDashboard.from_json(yaml)
[]
- rescue Gitlab::Config::Loader::FormatError => error
- ["YAML syntax: #{error.message}"]
- rescue ActiveModel::ValidationError => invalid
- invalid.model.errors.messages.map { |messages| messages.join(': ') }
+ rescue Gitlab::Config::Loader::FormatError => e
+ ["YAML syntax: #{e.message}"]
+ rescue ActiveModel::ValidationError => e
+ e.model.errors.messages.map { |messages| messages.join(': ') }
end
def exhaustive_metrics_dashboard_validation
@@ -47,8 +47,8 @@ module BlobViewer
Gitlab::Metrics::Dashboard::Validator
.errors(yaml, dashboard_path: blob.path, project: project)
.map(&:message)
- rescue Gitlab::Config::Loader::FormatError => error
- [error.message]
+ rescue Gitlab::Config::Loader::FormatError => e
+ [e.message]
end
end
end
diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb
index 6d9f598583e..3b263ed0340 100644
--- a/app/models/bulk_imports/configuration.rb
+++ b/app/models/bulk_imports/configuration.rb
@@ -9,7 +9,7 @@ class BulkImports::Configuration < ApplicationRecord
validates :url, :access_token, length: { maximum: 255 }, presence: true
validates :url, public_url: { schemes: %w[http https], enforce_sanitization: true, ascii_only: true },
- allow_nil: true
+ allow_nil: true
attr_encrypted :url,
key: Settings.attr_encrypted_db_key_base_32,
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index cad2fafe640..e0a616b5fb4 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -52,9 +52,11 @@ class BulkImports::Entity < ApplicationRecord
scope :by_user_id, ->(user_id) { joins(:bulk_import).where(bulk_imports: { user_id: user_id }) }
scope :stale, -> { where('created_at < ?', 8.hours.ago).where(status: [0, 1]) }
- scope :by_bulk_import_id, ->(bulk_import_id) { where(bulk_import_id: bulk_import_id)}
+ scope :by_bulk_import_id, ->(bulk_import_id) { where(bulk_import_id: bulk_import_id) }
scope :order_by_created_at, -> (direction) { order(created_at: direction) }
+ alias_attribute :destination_slug, :destination_name
+
state_machine :status, initial: :created do
state :created, value: 0
state :started, value: 1
diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb
index ff3f2663b73..60370c525d5 100644
--- a/app/models/chat_name.rb
+++ b/app/models/chat_name.rb
@@ -3,7 +3,7 @@
class ChatName < ApplicationRecord
LAST_USED_AT_INTERVAL = 1.hour
- belongs_to :integration, foreign_key: :service_id
+ belongs_to :integration
belongs_to :user
validates :user, presence: true
@@ -11,8 +11,8 @@ class ChatName < ApplicationRecord
validates :team_id, presence: true
validates :chat_id, presence: true
- validates :user_id, uniqueness: { scope: [:service_id] }
- validates :chat_id, uniqueness: { scope: [:service_id, :team_id] }
+ validates :user_id, uniqueness: { scope: [:integration_id] }
+ validates :chat_id, uniqueness: { scope: [:integration_id, :team_id] }
# Updates the "last_used_timestamp" but only if it wasn't already updated
# recently.
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 13af5b1f8d1..3fda8693a58 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -19,7 +19,7 @@ module Ci
belongs_to :project
belongs_to :trigger_request
has_many :sourced_pipelines, class_name: "::Ci::Sources::Pipeline",
- foreign_key: :source_job_id
+ foreign_key: :source_job_id
has_one :sourced_pipeline, class_name: "::Ci::Sources::Pipeline", foreign_key: :source_job_id
has_one :downstream_pipeline, through: :sourced_pipeline, source: :pipeline
@@ -114,7 +114,12 @@ module Ci
def downstream_project_path
strong_memoize(:downstream_project_path) do
- options&.dig(:trigger, :project)
+ project = options&.dig(:trigger, :project)
+ next unless project
+
+ scoped_variables.to_runner_variables.yield_self do |all_variables|
+ ::ExpandVariables.expand(project, all_variables)
+ end
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 7f9697d0424..bf8817e6e78 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -194,7 +194,7 @@ module Ci
after_save :stick_build_if_status_changed
after_create unless: :importing? do |build|
- run_after_commit { BuildHooksWorker.perform_async(build) }
+ run_after_commit { build.feature_flagged_execute_hooks }
end
class << self
@@ -285,7 +285,7 @@ module Ci
build.run_after_commit do
BuildQueueWorker.perform_async(id)
- BuildHooksWorker.perform_async(build)
+ build.feature_flagged_execute_hooks
end
end
@@ -313,7 +313,7 @@ module Ci
build.run_after_commit do
build.ensure_persistent_ref
- BuildHooksWorker.perform_async(build)
+ build.feature_flagged_execute_hooks
end
end
@@ -322,6 +322,8 @@ module Ci
build.run_status_commit_hooks!
Ci::BuildFinishedWorker.perform_async(id)
+
+ observe_report_types
end
end
@@ -340,8 +342,8 @@ module Ci
# rubocop: disable CodeReuse/ServiceClass
Ci::RetryJobService.new(build.project, build.user).execute(build)
# rubocop: enable CodeReuse/ServiceClass
- rescue Gitlab::Access::AccessDeniedError => ex
- Gitlab::AppLogger.error "Unable to auto-retry job #{build.id}: #{ex}"
+ rescue Gitlab::Access::AccessDeniedError => e
+ Gitlab::AppLogger.error "Unable to auto-retry job #{build.id}: #{e}"
end
end
end
@@ -490,11 +492,7 @@ module Ci
if metadata&.expanded_environment_name.present?
metadata.expanded_environment_name
else
- if ::Feature.enabled?(:ci_expand_environment_name_and_url, project)
- ExpandVariables.expand(environment, -> { simple_variables.sort_and_expand_all })
- else
- ExpandVariables.expand(environment, -> { simple_variables })
- end
+ ExpandVariables.expand(environment, -> { simple_variables.sort_and_expand_all })
end
end
end
@@ -527,10 +525,14 @@ module Ci
self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
end
- def environment_deployment_tier
+ def environment_tier_from_options
self.options.dig(:environment, :deployment_tier) if self.options
end
+ def environment_tier
+ environment_tier_from_options || persisted_environment.try(:tier)
+ end
+
def triggered_by?(current_user)
user == current_user
end
@@ -585,6 +587,7 @@ module Ci
variables.concat(persisted_environment.predefined_variables)
variables.append(key: 'CI_ENVIRONMENT_ACTION', value: environment_action)
+ variables.append(key: 'CI_ENVIRONMENT_TIER', value: environment_tier)
# Here we're passing unexpanded environment_url for runner to expand,
# and we need to make sure that CI_ENVIRONMENT_NAME and
@@ -777,10 +780,20 @@ module Ci
pending? && !any_runners_online?
end
+ def feature_flagged_execute_hooks
+ if Feature.enabled?(:execute_build_hooks_inline, project)
+ execute_hooks
+ else
+ BuildHooksWorker.perform_async(self)
+ end
+ end
+
def execute_hooks
return unless project
return if user&.blocked?
+ ActiveRecord::Associations::Preloader.new.preload([self], { runner: :tags })
+
project.execute_hooks(build_data.dup, :job_hooks) if project.has_active_hooks?(:job_hooks)
project.execute_integrations(build_data.dup, :job_hooks) if project.has_active_integrations?(:job_hooks)
end
@@ -818,7 +831,11 @@ module Ci
)
end
- job_artifacts.erasable.destroy_all # rubocop: disable Cop/DestroyAll
+ destroyed_artifacts = job_artifacts.erasable.destroy_all # rubocop: disable Cop/DestroyAll
+
+ Gitlab::Ci::Artifacts::Logger.log_deleted(destroyed_artifacts, 'Ci::Build#erase_erasable_artifacts!')
+
+ destroyed_artifacts
end
def erase(opts = {})
@@ -831,7 +848,12 @@ module Ci
)
end
- job_artifacts.destroy_all # rubocop: disable Cop/DestroyAll
+ # TODO: We should use DestroyBatchService here
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/369132
+ destroyed_artifacts = job_artifacts.destroy_all # rubocop: disable Cop/DestroyAll
+
+ Gitlab::Ci::Artifacts::Logger.log_deleted(destroyed_artifacts, 'Ci::Build#erase')
+
erase_trace!
update_erased!(opts[:erased_by])
end
@@ -983,7 +1005,7 @@ module Ci
def collect_test_reports!(test_reports)
test_reports.get_suite(test_suite_name).tap do |test_suite|
- each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob|
+ each_report(Ci::JobArtifact.file_types_for_report(:test)) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
blob,
test_suite,
@@ -994,7 +1016,7 @@ module Ci
end
def collect_accessibility_reports!(accessibility_report)
- each_report(Ci::JobArtifact::ACCESSIBILITY_REPORT_FILE_TYPES) do |file_type, blob|
+ each_report(Ci::JobArtifact.file_types_for_report(:accessibility)) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, accessibility_report)
end
@@ -1002,7 +1024,7 @@ module Ci
end
def collect_codequality_reports!(codequality_report)
- each_report(Ci::JobArtifact::CODEQUALITY_REPORT_FILE_TYPES) do |file_type, blob|
+ each_report(Ci::JobArtifact.file_types_for_report(:codequality)) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, codequality_report)
end
@@ -1010,7 +1032,7 @@ module Ci
end
def collect_terraform_reports!(terraform_reports)
- each_report(::Ci::JobArtifact::TERRAFORM_REPORT_FILE_TYPES) do |file_type, blob, report_artifact|
+ each_report(::Ci::JobArtifact.file_types_for_report(:terraform)) do |file_type, blob, report_artifact|
::Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, terraform_reports, artifact: report_artifact)
end
@@ -1079,7 +1101,10 @@ module Ci
end
def drop_with_exit_code!(failure_reason, exit_code)
- drop!(::Gitlab::Ci::Build::Status::Reason.new(self, failure_reason, exit_code))
+ failure_reason ||= :unknown_failure
+ result = drop!(::Gitlab::Ci::Build::Status::Reason.new(self, failure_reason, exit_code))
+ ::Ci::TrackFailedBuildWorker.perform_async(id, exit_code, failure_reason)
+ result
end
def exit_codes_defined?
@@ -1149,6 +1174,21 @@ module Ci
end
end
+ def clone(current_user:, new_job_variables_attributes: [])
+ new_build = super
+
+ if action? && new_job_variables_attributes.any?
+ new_build.job_variables = []
+ new_build.job_variables_attributes = new_job_variables_attributes
+ end
+
+ new_build
+ end
+
+ def job_artifact_types
+ job_artifacts.map(&:file_type)
+ end
+
protected
def run_status_commit_hooks!
@@ -1256,6 +1296,20 @@ module Ci
expires_in: RUNNERS_STATUS_CACHE_EXPIRATION
) { yield }
end
+
+ def observe_report_types
+ return unless ::Gitlab.com? && Feature.enabled?(:report_artifact_build_completed_metrics_on_build_completion)
+
+ report_types = options&.dig(:artifacts, :reports)&.keys || []
+
+ report_types.each do |report_type|
+ next unless Ci::JobArtifact::REPORT_TYPES.include?(report_type)
+
+ ::Gitlab::Ci::Artifacts::Metrics
+ .build_completed_report_type_counter(report_type)
+ .increment(status: status)
+ end
+ end
end
end
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 4ee661d89f4..5fc21ba3f28 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -19,6 +19,7 @@ module Ci
before_create :set_build_project
validates :build, presence: true
+ validates :id_tokens, json_schema: { filename: 'build_metadata_id_tokens' }
validates :secrets, json_schema: { filename: 'build_metadata_secrets' }
serialize :config_options, Serializers::SymbolizedJson # rubocop:disable Cop/ActiveRecordSerialize
diff --git a/app/models/ci/build_trace_metadata.rb b/app/models/ci/build_trace_metadata.rb
index 1ffa0e31f99..86de90983ff 100644
--- a/app/models/ci/build_trace_metadata.rb
+++ b/app/models/ci/build_trace_metadata.rb
@@ -39,8 +39,8 @@ module Ci
def track_archival!(trace_artifact_id, checksum)
update!(trace_artifact_id: trace_artifact_id,
- checksum: checksum,
- archived_at: Time.current)
+ checksum: checksum,
+ archived_at: Time.current)
end
def archival_attempts_message
diff --git a/app/models/ci/deleted_object.rb b/app/models/ci/deleted_object.rb
index aba7b73aba9..d36646aba66 100644
--- a/app/models/ci/deleted_object.rb
+++ b/app/models/ci/deleted_object.rb
@@ -27,8 +27,8 @@ module Ci
def delete_file_from_storage
file.remove!
true
- rescue StandardError => exception
- Gitlab::ErrorTracking.track_exception(exception)
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e)
false
end
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index ee7175a4f69..71d33f0bb63 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -13,14 +13,19 @@ module Ci
include EachBatch
include Gitlab::Utils::StrongMemoize
- TEST_REPORT_FILE_TYPES = %w[junit].freeze
- COVERAGE_REPORT_FILE_TYPES = %w[cobertura].freeze
- CODEQUALITY_REPORT_FILE_TYPES = %w[codequality].freeze
- ACCESSIBILITY_REPORT_FILE_TYPES = %w[accessibility].freeze
NON_ERASABLE_FILE_TYPES = %w[trace].freeze
- TERRAFORM_REPORT_FILE_TYPES = %w[terraform].freeze
- SAST_REPORT_TYPES = %w[sast].freeze
- SECRET_DETECTION_REPORT_TYPES = %w[secret_detection].freeze
+
+ REPORT_FILE_TYPES = {
+ sast: %w[sast],
+ secret_detection: %w[secret_detection],
+ test: %w[junit],
+ accessibility: %w[accessibility],
+ coverage: %w[cobertura],
+ codequality: %w[codequality],
+ terraform: %w[terraform],
+ sbom: %w[cyclonedx]
+ }.freeze
+
DEFAULT_FILE_NAMES = {
archive: nil,
metadata: nil,
@@ -48,7 +53,8 @@ module Ci
cluster_applications: 'gl-cluster-applications.json', # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/361094
requirements: 'requirements.json',
coverage_fuzzing: 'gl-coverage-fuzzing.json',
- api_fuzzing: 'gl-api-fuzzing-report.json'
+ api_fuzzing: 'gl-api-fuzzing-report.json',
+ cyclonedx: 'gl-sbom.cdx.zip'
}.freeze
INTERNAL_TYPES = {
@@ -88,7 +94,8 @@ module Ci
terraform: :raw,
requirements: :raw,
coverage_fuzzing: :raw,
- api_fuzzing: :raw
+ api_fuzzing: :raw,
+ cyclonedx: :zip
}.freeze
DOWNLOADABLE_TYPES = %w[
@@ -112,6 +119,7 @@ module Ci
secret_detection
requirements
cluster_image_scanning
+ cyclonedx
].freeze
TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze
@@ -152,36 +160,14 @@ module Ci
where(file_type: types)
end
- scope :all_reports, -> do
- with_file_types(REPORT_TYPES.keys.map(&:to_s))
- end
-
- scope :sast_reports, -> do
- with_file_types(SAST_REPORT_TYPES)
- end
-
- scope :secret_detection_reports, -> do
- with_file_types(SECRET_DETECTION_REPORT_TYPES)
- end
-
- scope :test_reports, -> do
- with_file_types(TEST_REPORT_FILE_TYPES)
- end
-
- scope :accessibility_reports, -> do
- with_file_types(ACCESSIBILITY_REPORT_FILE_TYPES)
- end
-
- scope :coverage_reports, -> do
- with_file_types(COVERAGE_REPORT_FILE_TYPES)
- end
-
- scope :codequality_reports, -> do
- with_file_types(CODEQUALITY_REPORT_FILE_TYPES)
+ REPORT_FILE_TYPES.each do |report_type, file_types|
+ scope "#{report_type}_reports", -> do
+ with_file_types(file_types)
+ end
end
- scope :terraform_reports, -> do
- with_file_types(TERRAFORM_REPORT_FILE_TYPES)
+ scope :all_reports, -> do
+ with_file_types(REPORT_TYPES.keys.map(&:to_s))
end
scope :erasable, -> do
@@ -225,7 +211,8 @@ module Ci
browser_performance: 24, ## EE-specific
load_performance: 25, ## EE-specific
api_fuzzing: 26, ## EE-specific
- cluster_image_scanning: 27 ## EE-specific
+ cluster_image_scanning: 27, ## EE-specific
+ cyclonedx: 28 ## EE-specific
}
# `file_location` indicates where actual files are stored.
@@ -259,6 +246,10 @@ module Ci
end
end
+ def self.file_types_for_report(report_type)
+ REPORT_FILE_TYPES.fetch(report_type)
+ end
+
def self.associated_file_types_for(file_type)
return unless file_types.include?(file_type)
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 95c6da4a7af..a94330270e2 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -52,15 +52,15 @@ module Ci
belongs_to :ci_ref, class_name: 'Ci::Ref', foreign_key: :ci_ref_id, inverse_of: :pipelines
has_internal_id :iid, scope: :project, presence: false,
- track_if: -> { !importing? },
- ensure_if: -> { !importing? },
- init: ->(pipeline, scope) do
- if pipeline
- pipeline.project&.all_pipelines&.maximum(:iid) || pipeline.project&.all_pipelines&.count
- elsif scope
- ::Ci::Pipeline.where(**scope).maximum(:iid)
- end
- end
+ track_if: -> { !importing? },
+ ensure_if: -> { !importing? },
+ init: ->(pipeline, scope) do
+ if pipeline
+ pipeline.project&.all_pipelines&.maximum(:iid) || pipeline.project&.all_pipelines&.count
+ elsif scope
+ ::Ci::Pipeline.where(**scope).maximum(:iid)
+ end
+ end
has_many :stages, -> { order(position: :asc) }, inverse_of: :pipeline
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
@@ -102,6 +102,7 @@ module Ci
has_one :chat_data, class_name: 'Ci::PipelineChatData'
has_many :triggered_pipelines, through: :sourced_pipelines, source: :pipeline
+ # Only includes direct and not nested children
has_many :child_pipelines, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :sourced_pipelines, source: :pipeline
has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline
has_one :parent_pipeline, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :source_pipeline, source: :source_pipeline
@@ -389,7 +390,7 @@ module Ci
end
def self.latest_status(ref = nil)
- newest_first(ref: ref).pluck(:status).first
+ newest_first(ref: ref).pick(:status)
end
def self.latest_successful_for_ref(ref)
@@ -592,26 +593,20 @@ module Ci
canceled? && auto_canceled_by_id?
end
- def cancel_running(retries: 1)
- preloaded_relations = [:project, :pipeline, :deployment, :taggings]
-
- retry_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelables|
- cancelables.find_in_batches do |batch|
- Preloaders::CommitStatusPreloader.new(batch).execute(preloaded_relations)
-
- batch.each do |job|
- yield(job) if block_given?
- job.cancel
- end
- end
- end
- end
+ # Cancel a pipelines cancelable jobs and optionally it's child pipelines cancelable jobs
+ # retries - # of times to retry if errors
+ # cascade_to_children - if true cancels all related child pipelines for parent child pipelines
+ # 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)
+ update(auto_canceled_by_id: auto_canceled_by_pipeline_id) if auto_canceled_by_pipeline_id
- def auto_cancel_running(pipeline, retries: 1)
- update(auto_canceled_by: pipeline)
+ cancel_jobs(cancelable_statuses, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id)
- cancel_running(retries: retries) do |job|
- job.auto_canceled_by = pipeline
+ if cascade_to_children
+ # cancel any bridges that could spin up new child pipelines
+ cancel_jobs(bridges_in_self_and_descendants.cancelable, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id)
+ cancel_children(auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id, execute_async: execute_async)
end
end
@@ -953,6 +948,10 @@ module Ci
Ci::Build.latest.where(pipeline: self_and_descendants)
end
+ def bridges_in_self_and_descendants
+ Ci::Bridge.latest.where(pipeline: self_and_descendants)
+ end
+
def environments_in_self_and_descendants(deployment_status: nil)
# We limit to 100 unique environments for application safety.
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700
@@ -986,6 +985,11 @@ module Ci
object_hierarchy(project_condition: :same).base_and_descendants
end
+ # With only parent-child pipelines
+ def all_child_pipelines
+ object_hierarchy(project_condition: :same).descendants
+ end
+
def self_and_descendants_complete?
self_and_descendants.all?(&:complete?)
end
@@ -1152,6 +1156,10 @@ module Ci
end
end
+ def modified_paths_since(compare_to_sha)
+ project.repository.diff_stats(project.repository.merge_base(compare_to_sha, sha), sha).paths
+ end
+
def all_worktree_paths
strong_memoize(:all_worktree_paths) do
project.repository.ls_files(sha)
@@ -1216,10 +1224,6 @@ module Ci
stages.find_by(name: name)
end
- def find_stage_by_name!(name)
- stages.find_by!(name: name)
- end
-
def full_error_messages
errors ? errors.full_messages.to_sentence : ""
end
@@ -1321,6 +1325,42 @@ module Ci
private
+ def cancel_jobs(jobs, retries: 1, auto_canceled_by_pipeline_id: nil)
+ retry_lock(jobs, retries, name: 'ci_pipeline_cancel_running') do |statuses|
+ preloaded_relations = [:project, :pipeline, :deployment, :taggings]
+
+ statuses.find_in_batches do |status_batch|
+ relation = CommitStatus.where(id: status_batch)
+ Preloaders::CommitStatusPreloader.new(relation).execute(preloaded_relations)
+
+ relation.each do |job|
+ job.auto_canceled_by_id = auto_canceled_by_pipeline_id if auto_canceled_by_pipeline_id
+ job.cancel
+ end
+ end
+ end
+ end
+
+ # For parent child-pipelines only (not multi-project)
+ def cancel_children(auto_canceled_by_pipeline_id: nil, execute_async: true)
+ all_child_pipelines.each do |child_pipeline|
+ if execute_async
+ ::Ci::CancelPipelineWorker.perform_async(
+ child_pipeline.id,
+ auto_canceled_by_pipeline_id
+ )
+ else
+ child_pipeline.cancel_running(
+ # cascade_to_children is false because we iterate through children
+ # we also cancel bridges prior to prevent more children
+ cascade_to_children: false,
+ execute_async: execute_async,
+ auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id
+ )
+ end
+ end
+ end
+
def add_message(severity, content)
messages.build(severity: severity, content: content)
end
diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb
index f666629c8fd..a2ff49077be 100644
--- a/app/models/ci/processable.rb
+++ b/app/models/ci/processable.rb
@@ -101,7 +101,7 @@ module Ci
:merge_train_pipeline?,
to: :pipeline
- def clone(current_user:)
+ def clone(current_user:, new_job_variables_attributes: [])
new_attributes = self.class.clone_accessors.to_h do |attribute|
[attribute, public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index f41ad890184..6c3754d84d0 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -15,7 +15,7 @@ module Ci
include Presentable
include EachBatch
- ignore_column :semver, remove_with: '15.3', remove_after: '2022-07-22'
+ ignore_column :semver, remove_with: '15.4', remove_after: '2022-08-22'
add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration, expiration_enforced?: :token_expiration_enforced?
@@ -437,7 +437,12 @@ module Ci
cache_attributes(values)
# We save data without validation, it will always change due to `contacted_at`
- self.update_columns(values) if persist_cached_data?
+ if persist_cached_data?
+ version_updated = values.include?(:version) && values[:version] != version
+
+ update_columns(values)
+ schedule_runner_version_update if version_updated
+ end
end
end
@@ -477,7 +482,7 @@ module Ci
private
scope :with_upgrade_status, ->(upgrade_status) do
- Ci::Runner.joins(:runner_version).where(runner_version: { status: upgrade_status })
+ joins(:runner_version).where(runner_version: { status: upgrade_status })
end
EXECUTOR_NAME_TO_TYPES = {
@@ -565,6 +570,12 @@ module Ci
errors.add(:runner, 'needs to be assigned to exactly one group')
end
end
+
+ def schedule_runner_version_update
+ return unless version
+
+ Ci::Runners::ProcessRunnerVersionUpdateWorker.perform_async(version)
+ end
end
end
diff --git a/app/models/ci/runner_version.rb b/app/models/ci/runner_version.rb
index 6b2d0060c9b..bbde98ee591 100644
--- a/app/models/ci/runner_version.rb
+++ b/app/models/ci/runner_version.rb
@@ -8,7 +8,6 @@ module Ci
enum_with_nil status: {
not_processed: nil,
invalid_version: -1,
- unknown: 0,
not_available: 1,
available: 2,
recommended: 3
@@ -16,7 +15,6 @@ module Ci
STATUS_DESCRIPTIONS = {
invalid_version: 'Runner version is not valid.',
- unknown: 'Upgrade status is unknown.',
not_available: 'Upgrade is not available for the runner.',
available: 'Upgrade is available for the runner.',
recommended: 'Upgrade is available and recommended for the runner.'
@@ -27,7 +25,7 @@ module Ci
# This scope returns all versions that might need recalculating. For instance, once a version is considered
# :recommended, it normally doesn't change status even if the instance is upgraded
- scope :potentially_outdated, -> { where(status: [nil, :not_available, :available, :unknown]) }
+ scope :potentially_outdated, -> { where(status: [nil, :not_available, :available]) }
validates :version, length: { maximum: 2048 }
end
diff --git a/app/models/ci/secure_file.rb b/app/models/ci/secure_file.rb
index 078b05ff779..9a35f1876c9 100644
--- a/app/models/ci/secure_file.rb
+++ b/app/models/ci/secure_file.rb
@@ -3,11 +3,8 @@
module Ci
class SecureFile < Ci::ApplicationRecord
include FileStoreMounter
- include IgnorableColumns
include Limitable
- ignore_column :permissions, remove_with: '15.2', remove_after: '2022-06-22'
-
FILE_SIZE_LIMIT = 5.megabytes.freeze
CHECKSUM_ALGORITHM = 'sha256'
@@ -24,6 +21,7 @@ module Ci
before_validation :assign_checksum
scope :order_by_created_at, -> { order(created_at: :desc) }
+ scope :project_id_in, ->(ids) { where(project_id: ids) }
default_value_for(:file_store) { Ci::SecureFileUploader.default_store }
@@ -46,3 +44,5 @@ module Ci
end
end
end
+
+Ci::SecureFile.prepend_mod
diff --git a/app/models/commit.rb b/app/models/commit.rb
index ca18cb50e02..bd60f02b532 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -190,7 +190,7 @@ class Commit
def self.link_reference_pattern
@link_reference_pattern ||=
- super("commit", /(?<commit>#{COMMIT_SHA_PATTERN})?(\.(?<extension>#{LINK_EXTENSION_PATTERN}))?/)
+ super("commit", /(?<commit>#{COMMIT_SHA_PATTERN})?(\.(?<extension>#{LINK_EXTENSION_PATTERN}))?/o)
end
def to_reference(from = nil, full: false)
diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb
index 08f1eb3731e..e2f0de52bc9 100644
--- a/app/models/commit_range.rb
+++ b/app/models/commit_range.rb
@@ -50,7 +50,7 @@ class CommitRange
end
def self.link_reference_pattern
- @link_reference_pattern ||= super("compare", /(?<commit_range>#{PATTERN})/)
+ @link_reference_pattern ||= super("compare", /(?<commit_range>#{PATTERN})/o)
end
# Initialize a CommitRange
@@ -64,7 +64,7 @@ class CommitRange
range_string = range_string.strip
- unless range_string =~ /\A#{PATTERN}\z/
+ unless range_string =~ /\A#{PATTERN}\z/o
raise ArgumentError, "invalid CommitRange string format: #{range_string}"
end
diff --git a/app/models/commit_signatures/ssh_signature.rb b/app/models/commit_signatures/ssh_signature.rb
index dbfbe0c3889..7a8d0653fcd 100644
--- a/app/models/commit_signatures/ssh_signature.rb
+++ b/app/models/commit_signatures/ssh_signature.rb
@@ -4,6 +4,6 @@ module CommitSignatures
class SshSignature < ApplicationRecord
include CommitSignature
- belongs_to :key, optional: false
+ belongs_to :key, optional: true
end
end
diff --git a/app/models/compare.rb b/app/models/compare.rb
index 7f42e1ee491..f594a796987 100644
--- a/app/models/compare.rb
+++ b/app/models/compare.rb
@@ -92,7 +92,7 @@ class Compare
def diff_refs
Gitlab::Diff::DiffRefs.new(
- base_sha: @straight ? start_commit_sha : base_commit_sha,
+ base_sha: @straight ? start_commit_sha : base_commit_sha,
start_sha: start_commit_sha,
head_sha: head_commit_sha
)
diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb
index fb4ea4206f4..ee8e98ec1bf 100644
--- a/app/models/concerns/ci/artifactable.rb
+++ b/app/models/concerns/ci/artifactable.rb
@@ -5,11 +5,13 @@ module Ci
extend ActiveSupport::Concern
include ObjectStorable
+ include Gitlab::Ci::Artifacts::Logger
STORE_COLUMN = :file_store
NotSupportedAdapterError = Class.new(StandardError)
FILE_FORMAT_ADAPTERS = {
gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream,
+ zip: Gitlab::Ci::Build::Artifacts::Adapters::ZipStream,
raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream
}.freeze
@@ -30,7 +32,7 @@ module Ci
raise NotSupportedAdapterError, 'This file format requires a dedicated adapter'
end
- ::Gitlab::ApplicationContext.push(artifact: file.model)
+ log_artifacts_filesize(file.model)
file.open do |stream|
file_format_adapter_class.new(stream).each_blob(&blk)
diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb
index 721cb14201f..910885c833f 100644
--- a/app/models/concerns/ci/has_status.rb
+++ b/app/models/concerns/ci/has_status.rb
@@ -17,8 +17,8 @@ module Ci
ALIVE_STATUSES = (ACTIVE_STATUSES + ['created']).freeze
CANCELABLE_STATUSES = (ALIVE_STATUSES + ['scheduled']).freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
- failed: 4, canceled: 5, skipped: 6, manual: 7,
- scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
+ failed: 4, canceled: 5, skipped: 6, manual: 7,
+ scheduled: 8, preparing: 9, waiting_for_resource: 10 }.freeze
UnknownStatusError = Class.new(StandardError)
diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb
index aa9669ee208..8c3a05c23f0 100644
--- a/app/models/concerns/ci/metadatable.rb
+++ b/app/models/concerns/ci/metadatable.rb
@@ -20,6 +20,8 @@ module Ci
delegate :interruptible, to: :metadata, prefix: false, allow_nil: true
delegate :environment_auto_stop_in, to: :metadata, prefix: false, allow_nil: true
delegate :set_cancel_gracefully, to: :metadata, prefix: false, allow_nil: false
+ delegate :id_tokens, to: :metadata, allow_nil: true
+
before_create :ensure_metadata
end
@@ -77,6 +79,14 @@ module Ci
ensure_metadata.interruptible = value
end
+ def id_tokens?
+ !!metadata&.id_tokens?
+ end
+
+ def id_tokens=(value)
+ ensure_metadata.id_tokens = value
+ end
+
private
def read_metadata_attribute(legacy_key, metadata_key, default_value = nil)
diff --git a/app/models/concerns/counter_attribute.rb b/app/models/concerns/counter_attribute.rb
index b41b1ba6008..65cf3246d11 100644
--- a/app/models/concerns/counter_attribute.rb
+++ b/app/models/concerns/counter_attribute.rb
@@ -82,18 +82,23 @@ module CounterAttribute
lock_key = counter_lock_key(attribute)
with_exclusive_lease(lock_key) do
+ previous_db_value = read_attribute(attribute)
increment_key = counter_key(attribute)
flushed_key = counter_flushed_key(attribute)
increment_value = steal_increments(increment_key, flushed_key)
+ new_db_value = nil
next if increment_value == 0
transaction do
unsafe_update_counters(id, attribute => increment_value)
redis_state { |redis| redis.del(flushed_key) }
+ new_db_value = reset.read_attribute(attribute)
end
execute_after_flush_callbacks
+
+ log_flush_counter(attribute, increment_value, previous_db_value, new_db_value)
end
end
@@ -115,15 +120,19 @@ module CounterAttribute
def increment_counter(attribute, increment)
if counter_attribute_enabled?(attribute)
- redis_state do |redis|
+ new_value = redis_state do |redis|
redis.incrby(counter_key(attribute), increment)
end
+
+ log_increment_counter(attribute, increment, new_value)
end
end
def clear_counter!(attribute)
if counter_attribute_enabled?(attribute)
redis_state { |redis| redis.del(counter_key(attribute)) }
+
+ log_clear_counter(attribute)
end
end
@@ -184,4 +193,40 @@ module CounterAttribute
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
# a worker is already updating the counters
end
+
+ def log_increment_counter(attribute, increment, new_value)
+ payload = Gitlab::ApplicationContext.current.merge(
+ message: 'Increment counter attribute',
+ attribute: attribute,
+ project_id: project_id,
+ increment: increment,
+ new_counter_value: new_value,
+ current_db_value: read_attribute(attribute)
+ )
+
+ Gitlab::AppLogger.info(payload)
+ end
+
+ def log_flush_counter(attribute, increment, previous_db_value, new_db_value)
+ payload = Gitlab::ApplicationContext.current.merge(
+ message: 'Flush counter attribute to database',
+ attribute: attribute,
+ project_id: project_id,
+ increment: increment,
+ previous_db_value: previous_db_value,
+ new_db_value: new_db_value
+ )
+
+ Gitlab::AppLogger.info(payload)
+ end
+
+ def log_clear_counter(attribute)
+ payload = Gitlab::ApplicationContext.current.merge(
+ message: 'Clear counter attribute',
+ attribute: attribute,
+ project_id: project_id
+ )
+
+ Gitlab::AppLogger.info(payload)
+ end
end
diff --git a/app/models/concerns/cross_database_modification.rb b/app/models/concerns/cross_database_modification.rb
index dea62f03f91..273d5f35e76 100644
--- a/app/models/concerns/cross_database_modification.rb
+++ b/app/models/concerns/cross_database_modification.rb
@@ -80,34 +80,22 @@ module CrossDatabaseModification
end
def transaction(**options, &block)
- if track_gitlab_schema_in_current_transaction?
- super(**options) do
- # Hook into current transaction to ensure that once
- # the `COMMIT` is executed the `gitlab_transactions_stack`
- # will be allowing to execute `after_commit_queue`
- record = TransactionStackTrackRecord.new(self, gitlab_schema)
-
- begin
- connection.current_transaction.add_record(record)
-
- yield
- ensure
- record.done!
- end
+ super(**options) do
+ # Hook into current transaction to ensure that once
+ # the `COMMIT` is executed the `gitlab_transactions_stack`
+ # will be allowing to execute `after_commit_queue`
+ record = TransactionStackTrackRecord.new(self, gitlab_schema)
+
+ begin
+ connection.current_transaction.add_record(record)
+
+ yield
+ ensure
+ record.done!
end
- else
- super(**options, &block)
end
end
- def track_gitlab_schema_in_current_transaction?
- return false unless Feature::FlipperFeature.table_exists?
-
- Feature.enabled?(:track_gitlab_schema_in_current_transaction)
- rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad
- false
- end
-
def gitlab_schema
case self.name
when 'ActiveRecord::Base', 'ApplicationRecord'
diff --git a/app/models/concerns/database_event_tracking.rb b/app/models/concerns/database_event_tracking.rb
new file mode 100644
index 00000000000..9f75b3ed4d8
--- /dev/null
+++ b/app/models/concerns/database_event_tracking.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module DatabaseEventTracking
+ extend ActiveSupport::Concern
+
+ included do
+ after_create_commit :publish_database_create_event
+ after_destroy_commit :publish_database_destroy_event
+ after_update_commit :publish_database_update_event
+ end
+
+ def publish_database_create_event
+ publish_database_event('create')
+ end
+
+ def publish_database_destroy_event
+ publish_database_event('destroy')
+ end
+
+ def publish_database_update_event
+ publish_database_event('update')
+ end
+
+ def publish_database_event(name)
+ return unless Feature.enabled?(:product_intelligence_database_event_tracking)
+
+ # Gitlab::Tracking#event is triggering Snowplow event
+ # Snowplow events are sent with usage of
+ # https://snowplow.github.io/snowplow-ruby-tracker/SnowplowTracker/AsyncEmitter.html
+ # that reports data asynchronously and does not impact performance nor carries a risk of
+ # rollback in case of error
+
+ Gitlab::Tracking.event(
+ self.class.to_s,
+ "database_event_#{name}",
+ label: self.class.table_name,
+ namespace: try(:group) || try(:namespace),
+ property: name,
+ **filtered_record_attributes
+ )
+ rescue StandardError => err
+ # this rescue should be a dead code due to utilization of AsyncEmitter, however
+ # since this concern is expected to be included in every model, it is better to
+ # prevent against any unexpected outcome
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(err)
+ end
+
+ def filtered_record_attributes
+ attributes
+ .with_indifferent_access
+ .slice(*self.class::SNOWPLOW_ATTRIBUTES)
+ end
+end
diff --git a/app/models/concerns/diff_positionable_note.rb b/app/models/concerns/diff_positionable_note.rb
index 051158e5de5..7a6076c7d2e 100644
--- a/app/models/concerns/diff_positionable_note.rb
+++ b/app/models/concerns/diff_positionable_note.rb
@@ -17,7 +17,11 @@ module DiffPositionableNote
%i(original_position position change_position).each do |meth|
define_method "#{meth}=" do |new_position|
if new_position.is_a?(String)
- new_position = Gitlab::Json.parse(new_position) rescue nil
+ new_position = begin
+ Gitlab::Json.parse(new_position)
+ rescue StandardError
+ nil
+ end
end
if new_position.is_a?(Hash)
diff --git a/app/models/concerns/enums/data_visualization_palette.rb b/app/models/concerns/enums/data_visualization_palette.rb
index 25002e64ba6..6e712e79915 100644
--- a/app/models/concerns/enums/data_visualization_palette.rb
+++ b/app/models/concerns/enums/data_visualization_palette.rb
@@ -16,17 +16,17 @@ module Enums
def self.weights
{
- '50' => 0,
- '100' => 1,
- '200' => 2,
- '300' => 3,
- '400' => 4,
- '500' => 5,
- '600' => 6,
- '700' => 7,
- '800' => 8,
- '900' => 9,
- '950' => 10
+ '50' => 0,
+ '100' => 1,
+ '200' => 2,
+ '300' => 3,
+ '400' => 4,
+ '500' => 5,
+ '600' => 6,
+ '700' => 7,
+ '800' => 8,
+ '900' => 9,
+ '950' => 10
}
end
end
diff --git a/app/models/concerns/enums/sbom.rb b/app/models/concerns/enums/sbom.rb
new file mode 100644
index 00000000000..518efa669ad
--- /dev/null
+++ b/app/models/concerns/enums/sbom.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Enums
+ class Sbom
+ COMPONENT_TYPES = {
+ library: 0
+ }.with_indifferent_access.freeze
+
+ def self.component_types
+ COMPONENT_TYPES
+ end
+ end
+end
diff --git a/app/models/concerns/expirable.rb b/app/models/concerns/expirable.rb
index e029ada84f0..5975ea23723 100644
--- a/app/models/concerns/expirable.rb
+++ b/app/models/concerns/expirable.rb
@@ -6,7 +6,10 @@ module Expirable
DAYS_TO_EXPIRE = 7
included do
- scope :expired, -> { where('expires_at <= ?', Time.current) }
+ scope :not, ->(scope) { where(scope.arel.constraints.reduce(:and).not) }
+
+ scope :expired, -> { where('expires_at IS NOT NULL AND expires_at <= ?', Time.current) }
+ scope :not_expired, -> { self.not(expired) }
end
def expired?
diff --git a/app/models/concerns/featurable.rb b/app/models/concerns/featurable.rb
index 08189d83534..3b741208221 100644
--- a/app/models/concerns/featurable.rb
+++ b/app/models/concerns/featurable.rb
@@ -30,9 +30,9 @@ module Featurable
STRING_OPTIONS = HashWithIndifferentAccess.new({
'disabled' => DISABLED,
- 'private' => PRIVATE,
- 'enabled' => ENABLED,
- 'public' => PUBLIC
+ 'private' => PRIVATE,
+ 'enabled' => ENABLED,
+ 'public' => PUBLIC
}).freeze
class_methods do
@@ -114,7 +114,7 @@ module Featurable
self.errors.add(field, "cannot have public visibility level") if not_allowed
end
- (self.class.available_features - feature_validation_exclusion).each {|f| validator.call("#{f}_access_level")}
+ (self.class.available_features - feature_validation_exclusion).each { |f| validator.call("#{f}_access_level") }
end
# Features that we should exclude from the validation
diff --git a/app/models/concerns/integrations/base_data_fields.rb b/app/models/concerns/integrations/base_data_fields.rb
index 11bdd3aae7b..2870922d90d 100644
--- a/app/models/concerns/integrations/base_data_fields.rb
+++ b/app/models/concerns/integrations/base_data_fields.rb
@@ -4,15 +4,10 @@ module Integrations
module BaseDataFields
extend ActiveSupport::Concern
- LEGACY_FOREIGN_KEY_NAME = %w(
- Integrations::IssueTrackerData
- Integrations::JiraTrackerData
- ).freeze
-
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: foreign_key_name
+ belongs_to :integration, inverse_of: self.table_name.to_sym, foreign_key: :integration_id
validates :integration, presence: true
end
@@ -26,16 +21,6 @@ module Integrations
algorithm: 'aes-256-gcm'
}
end
-
- private
-
- # Older data field models use the `service_id` foreign key for the
- # integration association.
- def foreign_key_name
- return :service_id if self.name.in?(LEGACY_FOREIGN_KEY_NAME)
-
- :integration_id
- end
end
def activated?
diff --git a/app/models/concerns/integrations/has_data_fields.rb b/app/models/concerns/integrations/has_data_fields.rb
index 635147a2f3c..2671df873aa 100644
--- a/app/models/concerns/integrations/has_data_fields.rb
+++ b/app/models/concerns/integrations/has_data_fields.rb
@@ -44,8 +44,8 @@ module Integrations
end
included do
- has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::IssueTrackerData'
- has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::JiraTrackerData'
+ has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :integration_id, class_name: 'Integrations::IssueTrackerData'
+ has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :integration_id, class_name: 'Integrations::JiraTrackerData'
has_one :zentao_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :integration_id, class_name: 'Integrations::ZentaoTrackerData'
def data_fields
diff --git a/app/models/concerns/integrations/has_web_hook.rb b/app/models/concerns/integrations/has_web_hook.rb
index bc28c32695c..e6ca6cc7938 100644
--- a/app/models/concerns/integrations/has_web_hook.rb
+++ b/app/models/concerns/integrations/has_web_hook.rb
@@ -6,6 +6,7 @@ module Integrations
included do
after_save :update_web_hook!, if: :activated?
+ has_one :service_hook, inverse_of: :integration, foreign_key: :service_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 4dca07132ef..b81a9b51e1c 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -515,11 +515,23 @@ module Issuable
changes
end
+ def hook_reviewer_changes(old_associations)
+ changes = {}
+ old_reviewers = old_associations.fetch(:reviewers, reviewers)
+
+ if old_reviewers != reviewers
+ changes[:reviewers] = [old_reviewers.map(&:hook_attrs), reviewers.map(&:hook_attrs)]
+ end
+
+ changes
+ end
+
def to_hook_data(user, old_associations: {})
changes = previous_changes
if old_associations.present?
changes.merge!(hook_association_changes(old_associations))
+ changes.merge!(hook_reviewer_changes(old_associations)) if allows_reviewers?
end
Gitlab::DataBuilder::Issuable.new(self).build(user: user, changes: changes)
@@ -537,6 +549,10 @@ module Issuable
labels.map(&:hook_attrs)
end
+ def allows_scoped_labels?
+ false
+ end
+
# Convert this Issuable class name to a format usable by Ability definitions
#
# Examples:
@@ -550,7 +566,7 @@ module Issuable
# Returns a Hash of attributes to be used for Twitter card metadata
def card_attributes
{
- 'Author' => author.try(:name),
+ 'Author' => author.try(:name),
'Assignee' => assignee_list
}
end
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index f59b5d1ecc8..8130adf05f1 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -109,6 +109,7 @@ module Participable
when User
participants << source
when Participable
+ next if skippable_system_notes?(source, participants)
next unless !verify_access || source_visible_to_user?(source, current_user)
source.class.participant_attrs.each do |attr|
@@ -133,6 +134,13 @@ module Participable
participants.merge(extractor.users)
end
+ def skippable_system_notes?(source, participants)
+ source.is_a?(Note) &&
+ source.system? &&
+ source.author.in?(participants) &&
+ !source.note.match?(User.reference_pattern)
+ end
+
def use_internal_notes_extractor_for?(source)
source.is_a?(Note) && source.confidential?
end
diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb
index 900e8f7d39b..7613691bc2e 100644
--- a/app/models/concerns/project_features_compatibility.rb
+++ b/app/models/concerns/project_features_compatibility.rb
@@ -94,6 +94,18 @@ module ProjectFeaturesCompatibility
write_feature_attribute_string(:container_registry_access_level, value)
end
+ def environments_access_level=(value)
+ write_feature_attribute_string(:environments_access_level, value)
+ end
+
+ def feature_flags_access_level=(value)
+ write_feature_attribute_string(:feature_flags_access_level, value)
+ end
+
+ def releases_access_level=(value)
+ write_feature_attribute_string(:releases_access_level, value)
+ end
+
# TODO: Remove this method after we drop support for project create/edit APIs to set the
# container_registry_enabled attribute. They can instead set the container_registry_access_level
# attribute.
diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb
index 86280097d19..df297017119 100644
--- a/app/models/concerns/prometheus_adapter.rb
+++ b/app/models/concerns/prometheus_adapter.rb
@@ -62,8 +62,8 @@ module PrometheusAdapter
data: data,
last_update: Time.current.utc
}
- rescue Gitlab::PrometheusClient::Error => err
- { success: false, result: err.message }
+ rescue Gitlab::PrometheusClient::Error => e
+ { success: false, result: e.message }
end
def query_klass_for(query_name)
diff --git a/app/models/concerns/repository_storage_movable.rb b/app/models/concerns/repository_storage_movable.rb
index 1dd8eebeff3..b7fd52ab305 100644
--- a/app/models/concerns/repository_storage_movable.rb
+++ b/app/models/concerns/repository_storage_movable.rb
@@ -50,8 +50,8 @@ module RepositoryStorageMovable
begin
storage_move.container.set_repository_read_only!(skip_git_transfer_check: true)
- rescue StandardError => err
- storage_move.add_error(err.message)
+ rescue StandardError => e
+ storage_move.add_error(e.message)
next false
end
diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb
index 904c96b11b3..ee5774d4868 100644
--- a/app/models/concerns/taskable.rb
+++ b/app/models/concerns/taskable.rb
@@ -59,7 +59,7 @@ module Taskable
end
# Return a string that describes the current state of this Taskable's task
- # list items, e.g. "12 of 20 tasks completed"
+ # list items, e.g. "12 of 20 checklist items completed"
def task_status(short: false)
return '' if description.blank?
@@ -70,7 +70,7 @@ module Taskable
end
sum = tasks.summary
- "#{sum.complete_count}#{prep}#{sum.item_count} #{'task'.pluralize(sum.item_count)}#{completed}"
+ "#{sum.complete_count}#{prep}#{sum.item_count} #{'checklist item'.pluralize(sum.item_count)}#{completed}"
end
# Return a short string that describes the current state of this Taskable's
diff --git a/app/models/concerns/triggerable_hooks.rb b/app/models/concerns/triggerable_hooks.rb
index 8fe34632430..e3800caa43f 100644
--- a/app/models/concerns/triggerable_hooks.rb
+++ b/app/models/concerns/triggerable_hooks.rb
@@ -2,22 +2,22 @@
module TriggerableHooks
AVAILABLE_TRIGGERS = {
- repository_update_hooks: :repository_update_events,
- push_hooks: :push_events,
- tag_push_hooks: :tag_push_events,
- issue_hooks: :issues_events,
- confidential_note_hooks: :confidential_note_events,
+ repository_update_hooks: :repository_update_events,
+ push_hooks: :push_events,
+ tag_push_hooks: :tag_push_events,
+ issue_hooks: :issues_events,
+ confidential_note_hooks: :confidential_note_events,
confidential_issue_hooks: :confidential_issues_events,
- note_hooks: :note_events,
- merge_request_hooks: :merge_requests_events,
- job_hooks: :job_events,
- pipeline_hooks: :pipeline_events,
- wiki_page_hooks: :wiki_page_events,
- deployment_hooks: :deployment_events,
- feature_flag_hooks: :feature_flag_events,
- release_hooks: :releases_events,
- member_hooks: :member_events,
- subgroup_hooks: :subgroup_events
+ note_hooks: :note_events,
+ merge_request_hooks: :merge_requests_events,
+ job_hooks: :job_events,
+ pipeline_hooks: :pipeline_events,
+ wiki_page_hooks: :wiki_page_events,
+ deployment_hooks: :deployment_events,
+ feature_flag_hooks: :feature_flag_events,
+ release_hooks: :releases_events,
+ member_hooks: :member_events,
+ subgroup_hooks: :subgroup_events
}.freeze
extend ActiveSupport::Concern
diff --git a/app/models/concerns/vulnerability_finding_helpers.rb b/app/models/concerns/vulnerability_finding_helpers.rb
index 4cf36f83857..b5d48260072 100644
--- a/app/models/concerns/vulnerability_finding_helpers.rb
+++ b/app/models/concerns/vulnerability_finding_helpers.rb
@@ -50,7 +50,7 @@ module VulnerabilityFindingHelpers
finding_data = report_finding.to_hash.except(:compare_key, :identifiers, :location, :scanner, :links, :signatures,
:flags, :evidence)
identifiers = report_finding.identifiers.map do |identifier|
- Vulnerabilities::Identifier.new(identifier.to_hash)
+ Vulnerabilities::Identifier.new(identifier.to_hash.merge({ project: project }))
end
signatures = report_finding.signatures.map do |signature|
Vulnerabilities::FindingSignature.new(signature.to_hash)
@@ -72,6 +72,7 @@ module VulnerabilityFindingHelpers
end
finding.identifiers = identifiers
+ finding.primary_identifier = identifiers.first
finding.signatures = signatures
end
end
diff --git a/app/models/concerns/x509_serial_number_attribute.rb b/app/models/concerns/x509_serial_number_attribute.rb
index e51ed95bf70..9dc53859ac0 100644
--- a/app/models/concerns/x509_serial_number_attribute.rb
+++ b/app/models/concerns/x509_serial_number_attribute.rb
@@ -33,8 +33,8 @@ module X509SerialNumberAttribute
unless column.type == :binary
raise ArgumentError, "x509_serial_number_attribute #{name.inspect} is invalid since the column type is not :binary"
end
- rescue StandardError => error
- Gitlab::AppLogger.error "X509SerialNumberAttribute initialization: #{error.message}"
+ rescue StandardError => e
+ Gitlab::AppLogger.error "X509SerialNumberAttribute initialization: #{e.message}"
raise
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index cdfd24e00aa..e10452c1081 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -19,6 +19,8 @@ class ContainerRepository < ApplicationRecord
MIGRATION_PHASE_1_STARTED_AT = Date.new(2021, 11, 4).freeze
MIGRATION_PHASE_1_ENDED_AT = Date.new(2022, 01, 23).freeze
+ MAX_TAGS_PAGES = 2000
+
TooManyImportsError = Class.new(StandardError)
belongs_to :project
@@ -377,6 +379,10 @@ class ContainerRepository < ApplicationRecord
migration_retries_count >= ContainerRegistry::Migration.max_retries - 1
end
+ def migrated?
+ MIGRATION_PHASE_1_ENDED_AT < self.created_at || import_done?
+ end
+
def last_import_step_done_at
[migration_pre_import_done_at, migration_import_done_at, migration_aborted_at, migration_skipped_at].compact.max
end
@@ -427,6 +433,32 @@ class ContainerRepository < ApplicationRecord
end
end
+ def each_tags_page(page_size: 100, &block)
+ raise ArgumentError, 'not a migrated repository' unless migrated?
+ raise ArgumentError, 'block not given' unless block
+
+ # dummy uri to initialize the loop
+ next_page_uri = URI('')
+ page_count = 0
+
+ while next_page_uri && page_count < MAX_TAGS_PAGES
+ last = Rack::Utils.parse_nested_query(next_page_uri.query)['last']
+ current_page = gitlab_api_client.tags(self.path, page_size: page_size, last: last)
+
+ if current_page&.key?(:response_body)
+ yield transform_tags_page(current_page[:response_body])
+ next_page_uri = current_page.dig(:pagination, :next, :uri)
+ else
+ # no current page. Break the loop
+ next_page_uri = nil
+ end
+
+ page_count += 1
+ end
+
+ raise 'too many pages requested' if page_count >= MAX_TAGS_PAGES
+ end
+
def tags_count
return 0 unless manifest && manifest['tags']
@@ -550,7 +582,7 @@ class ContainerRepository < ApplicationRecord
def self.find_by_path(path)
self.find_by(project: path.repository_project,
- name: path.repository_name)
+ name: path.repository_name)
end
private
@@ -559,6 +591,16 @@ class ContainerRepository < ApplicationRecord
self.migration_skipped_reason = reason
finish_import
end
+
+ def transform_tags_page(tags_response_body)
+ return [] unless tags_response_body
+
+ tags_response_body.map do |raw_tag|
+ tag = ContainerRegistry::Tag.new(self, raw_tag['name'])
+ tag.force_created_at_from_iso8601(raw_tag['created_at'])
+ tag
+ end
+ end
end
ContainerRepository.prepend_mod_with('ContainerRepository')
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 09fbb93525b..625d68925c6 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -22,7 +22,7 @@ class CustomEmoji < ApplicationRecord
presence: true,
length: { maximum: 36 },
- format: { with: /\A#{NAME_REGEXP}\z/ }
+ format: { with: /\A#{NAME_REGEXP}\z/o }
scope :by_name, -> (names) { where(name: names) }
diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb
index 0f13c45b84d..f6455da890b 100644
--- a/app/models/customer_relations/contact.rb
+++ b/app/models/customer_relations/contact.rb
@@ -29,6 +29,12 @@ class CustomerRelations::Contact < ApplicationRecord
validate :validate_email_format
validate :validate_root_group
+ scope :order_scope_asc, ->(field) { order(arel_table[field].asc.nulls_last) }
+ scope :order_scope_desc, ->(field) { order(arel_table[field].desc.nulls_last) }
+
+ scope :order_by_organization_asc, -> { includes(:organization).order("customer_relations_organizations.name ASC NULLS LAST") }
+ scope :order_by_organization_desc, -> { includes(:organization).order("customer_relations_organizations.name DESC NULLS LAST") }
+
def self.reference_prefix
'[contact:'
end
@@ -56,6 +62,22 @@ class CustomerRelations::Contact < ApplicationRecord
where(state: state)
end
+ def self.sort_by_field(field, direction)
+ if direction == :asc
+ order_scope_asc(field)
+ else
+ order_scope_desc(field)
+ end
+ end
+
+ def self.sort_by_organization(direction)
+ if direction == :asc
+ order_by_organization_asc
+ else
+ order_by_organization_desc
+ end
+ end
+
def self.sort_by_name
order(Gitlab::Pagination::Keyset::Order.build([
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
@@ -115,6 +137,10 @@ class CustomerRelations::Contact < ApplicationRecord
where(group: group).update_all(group_id: group.root_ancestor.id)
end
+ def self.counts_by_state
+ group(:state).count
+ end
+
private
def validate_email_format
diff --git a/app/models/customer_relations/contact_state_counts.rb b/app/models/customer_relations/contact_state_counts.rb
new file mode 100644
index 00000000000..31c95e166bb
--- /dev/null
+++ b/app/models/customer_relations/contact_state_counts.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module CustomerRelations
+ class ContactStateCounts
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :group
+
+ def self.declarative_policy_class
+ 'CustomerRelations::ContactPolicy'
+ end
+
+ def initialize(current_user, group, params)
+ @current_user = current_user
+ @group = group
+ @params = params
+ end
+
+ # Define method for each state
+ ::CustomerRelations::Contact.states.each_key do |state|
+ define_method(state) { counts[state] }
+ end
+
+ def all
+ counts.values.sum
+ end
+
+ private
+
+ attr_reader :current_user, :params
+
+ def counts
+ strong_memoize(:counts) do
+ Hash.new(0).merge(counts_by_state)
+ end
+ end
+
+ def counts_by_state
+ ::Crm::ContactsFinder.counts_by_state(current_user, params.merge({ group: group }))
+ end
+ end
+end
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 4ed38f578ee..94ac2405f61 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -40,6 +40,10 @@ class DeployKey < Key
super || User.ghost
end
+ def audit_details
+ title
+ end
+
def has_access_to?(project)
deploy_keys_project_for(project).present?
end
@@ -62,4 +66,9 @@ class DeployKey < Key
query
end
+
+ # This is used for the internal logic of AuditEvents::BuildService.
+ def impersonated?
+ false
+ end
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index c25ba6f9268..a3213a59bed 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -206,11 +206,6 @@ class Deployment < ApplicationRecord
end
end
- def self.distinct_on_environment
- order('environment_id, deployments.id DESC')
- .select('DISTINCT ON (environment_id) deployments.*')
- end
-
def self.find_successful_deployment!(iid)
success.find_by!(iid: iid)
end
@@ -438,7 +433,7 @@ class Deployment < ApplicationRecord
def tier_in_yaml
return unless deployable
- deployable.environment_deployment_tier
+ deployable.environment_tier_from_options
end
private
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index feb1bf5438c..317399e780a 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -28,8 +28,8 @@ module DesignManagement
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_internal_id :iid, scope: :project, presence: true,
- hook_names: %i[create update], # Deal with old records
- track_if: -> { !importing? }
+ hook_names: %i[create update], # Deal with old records
+ track_if: -> { !importing? }
validates :project, :filename, presence: true
validates :issue, presence: true, unless: :importing?
diff --git a/app/models/design_management/design_action.rb b/app/models/design_management/design_action.rb
index 43dcce545d2..eae470a1ae2 100644
--- a/app/models/design_management/design_action.rb
+++ b/app/models/design_management/design_action.rb
@@ -21,7 +21,7 @@ module DesignManagement
validates :action, presence: true, inclusion: { in: EVENT_FOR_GITALY_ACTION.keys }
validates :content,
absence: { if: :forbids_content?,
- message: 'this action forbids content' },
+ message: 'this action forbids content' },
presence: { if: :needs_content?,
message: 'this action needs content' }
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 68540ce0f5c..1950431446b 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -26,12 +26,11 @@ class Environment < ApplicationRecord
has_many :self_managed_prometheus_alert_events, inverse_of: :environment
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
+ # NOTE: If you preload multiple last deployments of environments, use Preloaders::Environments::DeploymentPreloader.
has_one :last_deployment, -> { success.ordered }, class_name: 'Deployment', inverse_of: :environment
- has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment'
- has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus', disable_joins: true
- has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline', disable_joins: true
+ has_one :last_visible_deployment, -> { visible.order(id: :desc) }, inverse_of: :environment, class_name: 'Deployment'
- has_one :upcoming_deployment, -> { upcoming.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
+ has_one :upcoming_deployment, -> { upcoming.order(id: :desc) }, class_name: 'Deployment', inverse_of: :environment
has_one :latest_opened_most_severe_alert, -> { order_severity_with_open_prometheus_alert }, class_name: 'AlertManagement::Alert', inverse_of: :environment
before_validation :generate_slug, if: ->(env) { env.slug.blank? }
@@ -56,8 +55,9 @@ class Environment < ApplicationRecord
validates :external_url,
length: { maximum: 255 },
- allow_nil: true,
- addressable_url: true
+ allow_nil: true
+
+ validate :safe_external_url
delegate :manual_actions, :other_manual_actions, to: :last_deployment, allow_nil: true
delegate :auto_rollback_enabled?, to: :project
@@ -215,28 +215,11 @@ class Environment < ApplicationRecord
deployable_id: last_deployment_pipeline.latest_builds.pluck(:id))
end
- # NOTE: Below assocation overrides is a workaround for issue https://gitlab.com/gitlab-org/gitlab/-/issues/339908
- # It helps to avoid cross joins with the CI database.
- # Caveat: It also overrides and losses the default AR caching mechanism.
- # Read - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68870#note_677227727
-
- # NOTE: Association Preloads does not use the overriden definitions below.
- # Association Preloads when preloading uses the original definitions from the relationships above.
- # https://github.com/rails/rails/blob/75ac626c4e21129d8296d4206a1960563cc3d4aa/activerecord/lib/active_record/associations/preloader.rb#L158
- # But after preloading, when they are called it is using the overriden methods below.
- # So we are checking for `association_cached?(:association_name)` in the overridden methods and calling `super` which inturn fetches the preloaded values.
-
- # Overriding association
def last_visible_deployable
- return super if association_cached?(:last_visible_deployable)
-
last_visible_deployment&.deployable
end
- # Overriding association
def last_visible_pipeline
- return super if association_cached?(:last_visible_pipeline)
-
last_visible_deployable&.pipeline
end
@@ -252,7 +235,6 @@ class Environment < ApplicationRecord
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI_ENVIRONMENT_NAME', value: name)
.append(key: 'CI_ENVIRONMENT_SLUG', value: slug)
- .append(key: 'CI_ENVIRONMENT_TIER', value: tier)
end
def recently_updated_on_branch?(ref)
@@ -329,11 +311,7 @@ class Environment < ApplicationRecord
end
def last_deployment_group
- if ::Feature.enabled?(:batch_load_environment_last_deployment_group, project)
- Deployment.last_deployment_group_for_environment(self)
- else
- legacy_last_deployment_group
- end
+ Deployment.last_deployment_group_for_environment(self)
end
def reset_auto_stop
@@ -493,6 +471,22 @@ class Environment < ApplicationRecord
private
+ # We deliberately avoid using AddressableUrlValidator to allow users to update their environments even if they have
+ # misconfigured `environment:url` keyword. The external URL is presented as a clickable link on UI and not consumed
+ # in GitLab internally, thus we sanitize the URL before the persistence to make sure the rendered link is XSS safe.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/337417
+ def safe_external_url
+ return unless self.external_url.present?
+
+ new_external_url = Addressable::URI.parse(self.external_url)
+
+ if Gitlab::Utils::SanitizeNodeLink::UNSAFE_PROTOCOLS.include?(new_external_url.normalized_scheme)
+ errors.add(:external_url, "#{new_external_url.normalized_scheme} scheme is not allowed")
+ end
+ rescue Addressable::URI::InvalidURIError
+ errors.add(:external_url, 'URI is invalid')
+ end
+
def rollout_status_available?
has_terminals?
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 7760be3e817..a20ca0dc423 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -14,18 +14,18 @@ class Event < ApplicationRecord
default_scope { reorder(nil) } # rubocop:disable Cop/DefaultScope
ACTIONS = HashWithIndifferentAccess.new(
- created: 1,
- updated: 2,
- closed: 3,
- reopened: 4,
- pushed: 5,
- commented: 6,
- merged: 7,
- joined: 8, # User joined project
- left: 9, # User left project
- destroyed: 10,
- expired: 11, # User left project due to expiry
- approved: 12
+ created: 1,
+ updated: 2,
+ closed: 3,
+ reopened: 4,
+ pushed: 5,
+ commented: 6,
+ merged: 7,
+ joined: 8, # User joined project
+ left: 9, # User left project
+ destroyed: 10,
+ expired: 11, # User left project due to expiry
+ approved: 12
).freeze
private_constant :ACTIONS
@@ -36,15 +36,15 @@ class Event < ApplicationRecord
ISSUE_ACTIONS = [:created, :updated, :closed, :reopened].freeze
TARGET_TYPES = HashWithIndifferentAccess.new(
- issue: Issue,
- milestone: Milestone,
- merge_request: MergeRequest,
- note: Note,
- project: Project,
- snippet: Snippet,
- user: User,
- wiki: WikiPage::Meta,
- design: DesignManagement::Design
+ issue: Issue,
+ milestone: Milestone,
+ merge_request: MergeRequest,
+ note: Note,
+ project: Project,
+ snippet: Snippet,
+ user: User,
+ wiki: WikiPage::Meta,
+ design: DesignManagement::Design
).freeze
RESET_PROJECT_ACTIVITY_INTERVAL = 1.hour
@@ -216,6 +216,10 @@ class Event < ApplicationRecord
target_type == 'DesignManagement::Design'
end
+ def work_item?
+ target_type == 'WorkItem'
+ end
+
def milestone
target if milestone?
end
@@ -399,7 +403,8 @@ class Event < ApplicationRecord
read_milestone: %i[milestone?],
read_wiki: %i[wiki_page?],
read_design: %i[design_note? design?],
- read_note: %i[note?]
+ read_note: %i[note?],
+ read_work_item: %i[work_item?]
}
end
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index a56e28859c9..2db074e733e 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -21,7 +21,7 @@ class GpgKey < ApplicationRecord
presence: true,
uniqueness: true,
format: {
- with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX})(?!#{KEY_SUFFIX}).)+#{KEY_SUFFIX}\Z/m,
+ with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX})(?!#{KEY_SUFFIX}).)+#{KEY_SUFFIX}\Z/mo,
message: "is invalid. A valid public GPG key begins with '#{KEY_PREFIX}' and ends with '#{KEY_SUFFIX}'"
}
diff --git a/app/models/grafana_integration.rb b/app/models/grafana_integration.rb
index 0358e37c58b..5cd5aa1b085 100644
--- a/app/models/grafana_integration.rb
+++ b/app/models/grafana_integration.rb
@@ -4,9 +4,9 @@ class GrafanaIntegration < ApplicationRecord
belongs_to :project
attr_encrypted :token,
- mode: :per_attribute_iv,
+ mode: :per_attribute_iv,
algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32
+ key: Settings.attr_encrypted_db_key_base_32
before_validation :check_token_changes
diff --git a/app/models/group.rb b/app/models/group.rb
index 6d8f8bd7613..55455d85531 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -149,7 +149,7 @@ class Group < Namespace
add_authentication_token_field :runners_token,
encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption) ? :optional : :required },
- prefix: RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX
+ prefix: RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX
after_create :post_create_hook
after_destroy :post_destroy_hook
@@ -176,6 +176,16 @@ class Group < Namespace
.where(project_authorizations: { user_id: user_ids })
end
+ scope :project_creation_allowed, -> do
+ permitted_levels = [
+ ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS,
+ ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS,
+ nil
+ ]
+
+ where(project_creation_level: permitted_levels)
+ end
+
class << self
def sort_by_attribute(method)
if method == 'storage_size_desc'
@@ -855,6 +865,14 @@ class Group < Namespace
feature_flag_enabled_for_self_or_ancestor?(:work_items)
end
+ def work_items_mvc_2_feature_flag_enabled?
+ feature_flag_enabled_for_self_or_ancestor?(:work_items_mvc_2)
+ end
+
+ def work_items_create_from_markdown_feature_flag_enabled?
+ feature_flag_enabled_for_self_or_ancestor?(:work_items_create_from_markdown)
+ end
+
# Check for enabled features, similar to `Project#feature_available?`
# NOTE: We still want to keep this after removing `Namespace#feature_available?`.
override :feature_available?
diff --git a/app/models/group_group_link.rb b/app/models/group_group_link.rb
index a70110c4076..8dd245a6ab5 100644
--- a/app/models/group_group_link.rb
+++ b/app/models/group_group_link.rb
@@ -14,6 +14,23 @@ class GroupGroupLink < ApplicationRecord
presence: true
scope :non_guests, -> { where('group_access > ?', Gitlab::Access::GUEST) }
+
+ scope :with_owner_or_maintainer_access, -> do
+ where(group_access: [Gitlab::Access::OWNER, Gitlab::Access::MAINTAINER])
+ end
+
+ scope :groups_accessible_via, -> (shared_with_group_ids) do
+ links = where(shared_with_group_id: shared_with_group_ids)
+ # a group share also gives you access to the descendants of the group being shared,
+ # so we must include the descendants as well in the result.
+ Group.id_in(links.select(:shared_group_id)).self_and_descendants
+ end
+
+ scope :groups_having_access_to, -> (shared_group_ids) do
+ links = where(shared_group_id: shared_group_ids)
+ Group.id_in(links.select(:shared_with_group_id))
+ end
+
scope :preload_shared_with_groups, -> { preload(:shared_with_group) }
scope :distinct_on_shared_with_group_id_with_group_access, -> do
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index f428d07cd7f..84ee23d77ce 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -12,14 +12,14 @@ class WebHook < ApplicationRecord
BACKOFF_GROWTH_FACTOR = 2.0
attr_encrypted :token,
- mode: :per_attribute_iv,
+ mode: :per_attribute_iv,
algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32
+ key: Settings.attr_encrypted_db_key_base_32
attr_encrypted :url,
- mode: :per_attribute_iv,
+ mode: :per_attribute_iv,
algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32
+ key: Settings.attr_encrypted_db_key_base_32
attr_encrypted :url_variables,
mode: :per_attribute_iv,
@@ -57,14 +57,14 @@ class WebHook < ApplicationRecord
!temporarily_disabled? && !permanently_disabled?
end
- def temporarily_disabled?(ignore_flag: false)
- return false unless ignore_flag || web_hooks_disable_failed?
+ def temporarily_disabled?
+ return false unless web_hooks_disable_failed?
disabled_until.present? && disabled_until >= Time.current
end
- def permanently_disabled?(ignore_flag: false)
- return false unless ignore_flag || web_hooks_disable_failed?
+ def permanently_disabled?
+ return false unless web_hooks_disable_failed?
recent_failures > FAILURE_THRESHOLD
end
@@ -126,13 +126,6 @@ class WebHook < ApplicationRecord
save(validate: false)
end
- def active_state(ignore_flag: false)
- return :permanently_disabled if permanently_disabled?(ignore_flag: ignore_flag)
- return :temporarily_disabled if temporarily_disabled?(ignore_flag: ignore_flag)
-
- :enabled
- end
-
# @return [Boolean] Whether or not the WebHook is currently throttled.
def rate_limited?
rate_limiter.rate_limited?
diff --git a/app/models/integration.rb b/app/models/integration.rb
index f5f701662e7..6d755016380 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -21,7 +21,7 @@ class Integration < ApplicationRecord
asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord
drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat harbor irker jira
mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email
- pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
+ pivotaltracker prometheus pumble pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
].freeze
# TODO Shimo is temporary disabled on group and instance-levels.
@@ -48,6 +48,9 @@ class Integration < ApplicationRecord
SECTION_TYPE_CONNECTION = 'connection'
SECTION_TYPE_TRIGGER = 'trigger'
+ SNOWPLOW_EVENT_ACTION = 'perform_integrations_action'
+ SNOWPLOW_EVENT_LABEL = 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly'
+
attr_encrypted :properties,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_32,
@@ -89,7 +92,6 @@ class Integration < ApplicationRecord
belongs_to :project, inverse_of: :integrations
belongs_to :group, inverse_of: :integrations
- has_one :service_hook, inverse_of: :integration, foreign_key: :service_id
validates :project_id, presence: true, unless: -> { instance_level? || group_level? }
validates :group_id, presence: true, unless: -> { instance_level? || project_level? }
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 230dc6bb336..c3a4b84bb2d 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -63,11 +63,11 @@ module Integrations
end
def build_page(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
+ with_reactive_cache(sha, ref) { |cached| cached[:build_page] }
end
def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
end
def execute(data)
diff --git a/app/models/integrations/base_issue_tracker.rb b/app/models/integrations/base_issue_tracker.rb
index fe4a2f43b13..a4cec5f927b 100644
--- a/app/models/integrations/base_issue_tracker.rb
+++ b/app/models/integrations/base_issue_tracker.rb
@@ -100,8 +100,8 @@ module Integrations
message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
result = true
end
- rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
- message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
+ rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => e
+ message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{e.message}"
end
log_info(message)
result
diff --git a/app/models/integrations/base_slash_commands.rb b/app/models/integrations/base_slash_commands.rb
index a0ac5474893..e51d748b562 100644
--- a/app/models/integrations/base_slash_commands.rb
+++ b/app/models/integrations/base_slash_commands.rb
@@ -8,7 +8,7 @@ module Integrations
prop_accessor :token
- has_many :chat_names, foreign_key: :service_id, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :chat_names, foreign_key: :integration_id, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
def valid_token?(token)
self.respond_to?(:token) &&
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb
index def646c6d49..7a48e71b934 100644
--- a/app/models/integrations/buildkite.rb
+++ b/app/models/integrations/buildkite.rb
@@ -60,7 +60,7 @@ module Integrations
end
def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
end
def commit_status_path(sha)
diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb
index 97e586c0662..bb0fb6b9079 100644
--- a/app/models/integrations/datadog.rb
+++ b/app/models/integrations/datadog.rb
@@ -15,75 +15,7 @@ module Integrations
TAG_KEY_VALUE_RE = %r{\A [\w-]+ : .*\S.* \z}x.freeze
- 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,
- 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,
- 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
+ prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env, :datadog_tags
before_validation :strip_properties
@@ -145,11 +77,92 @@ module Integrations
end
def fields
+ f = [
+ {
+ 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
+ }
+ ]
+
if Feature.enabled?(:datadog_integration_logs_collection, parent)
- super
- else
- super.reject { _1.name == 'archive_trace_events' }
+ f.append({
+ 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
+ })
end
+
+ f += [
+ {
+ 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
+ }
+ }
+ ]
+
+ f
end
override :hook_url
diff --git a/app/models/integrations/discord.rb b/app/models/integrations/discord.rb
index ecabf23c90b..ec8a12e4760 100644
--- a/app/models/integrations/discord.rb
+++ b/app/models/integrations/discord.rb
@@ -33,10 +33,21 @@ module Integrations
def default_fields
[
- { type: "text", name: "webhook", placeholder: "https://discordapp.com/api/webhooks/…", help: "URL to the webhook for the Discord channel." },
- { type: "checkbox", name: "notify_only_broken_pipelines" },
+ {
+ type: 'text',
+ section: SECTION_TYPE_CONNECTION,
+ name: 'webhook',
+ placeholder: 'https://discordapp.com/api/webhooks/…',
+ help: 'URL to the webhook for the Discord channel.'
+ },
+ {
+ type: 'checkbox',
+ section: SECTION_TYPE_CONFIGURATION,
+ name: 'notify_only_broken_pipelines'
+ },
{
type: 'select',
+ section: SECTION_TYPE_CONFIGURATION,
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
choices: self.class.branch_choices
@@ -44,6 +55,26 @@ module Integrations
]
end
+ def sections
+ [
+ {
+ type: SECTION_TYPE_CONNECTION,
+ title: s_('Integrations|Connection details'),
+ description: help
+ },
+ {
+ type: SECTION_TYPE_TRIGGER,
+ title: s_('Integrations|Trigger'),
+ description: s_('Integrations|An event will be triggered when one of the following items happen.')
+ },
+ {
+ type: SECTION_TYPE_CONFIGURATION,
+ title: s_('Integrations|Notification settings'),
+ description: s_('Integrations|Configure the scope of notifications.')
+ }
+ ]
+ end
+
private
def notify(message, opts)
@@ -57,8 +88,8 @@ module Integrations
embed.timestamp = Time.now.utc
end
end
- rescue RestClient::Exception => error
- log_error(error.message)
+ rescue RestClient::Exception => e
+ log_error(e.message)
false
end
diff --git a/app/models/integrations/emails_on_push.rb b/app/models/integrations/emails_on_push.rb
index ed12a3a8d63..25bda8c2bf0 100644
--- a/app/models/integrations/emails_on_push.rb
+++ b/app/models/integrations/emails_on_push.rb
@@ -71,7 +71,7 @@ module Integrations
recipients,
push_data,
send_from_committer_email: send_from_committer_email?,
- disable_diffs: disable_diffs?
+ disable_diffs: disable_diffs?
)
end
diff --git a/app/models/integrations/external_wiki.rb b/app/models/integrations/external_wiki.rb
index bc2ea193a84..75fe6b6f164 100644
--- a/app/models/integrations/external_wiki.rb
+++ b/app/models/integrations/external_wiki.rb
@@ -5,6 +5,7 @@ module Integrations
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
field :external_wiki_url,
+ section: SECTION_TYPE_CONNECTION,
title: -> { s_('ExternalWikiService|External wiki URL') },
placeholder: -> { s_('ExternalWikiService|https://example.com/xxx/wiki/...') },
help: -> { s_('ExternalWikiService|Enter the URL to the external wiki.') },
@@ -28,6 +29,16 @@ module Integrations
s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
+ def sections
+ [
+ {
+ type: SECTION_TYPE_CONNECTION,
+ title: s_('Integrations|Connection details'),
+ description: help
+ }
+ ]
+ end
+
def execute(_data)
response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
response.body if response.code == 200
diff --git a/app/models/integrations/harbor.rb b/app/models/integrations/harbor.rb
index 82981493822..03913a71d47 100644
--- a/app/models/integrations/harbor.rb
+++ b/app/models/integrations/harbor.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+require 'uri'
module Integrations
class Harbor < Integration
@@ -20,7 +21,7 @@ module Integrations
end
def help
- s_("HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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
class << self
@@ -78,8 +79,12 @@ module Integrations
def ci_variables
return [] unless activated?
+ oci_uri = URI.parse(url)
+ oci_uri.scheme = 'oci'
[
{ key: 'HARBOR_URL', value: url },
+ { key: 'HARBOR_HOST', value: oci_uri.host },
+ { key: 'HARBOR_OCI', value: oci_uri.to_s },
{ key: 'HARBOR_PROJECT', value: project_name },
{ key: 'HARBOR_USERNAME', value: username.gsub(/^robot\$/, 'robot$$') },
{ key: 'HARBOR_PASSWORD', value: password, public: false, masked: true }
diff --git a/app/models/integrations/jenkins.rb b/app/models/integrations/jenkins.rb
index ab39d1f7b77..c68b5fd2a96 100644
--- a/app/models/integrations/jenkins.rb
+++ b/app/models/integrations/jenkins.rb
@@ -53,8 +53,8 @@ module Integrations
begin
result = execute(data)
return { success: false, result: result[:message] } if result[:http_status] != 200
- rescue StandardError => error
- return { success: false, result: error }
+ rescue StandardError => e
+ return { success: false, result: e }
end
{ success: true, result: result[:message] }
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 566bbc456f8..3ca514ab1fd 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -18,6 +18,8 @@ module Integrations
SECTION_TYPE_JIRA_TRIGGER = 'jira_trigger'
SECTION_TYPE_JIRA_ISSUES = 'jira_issues'
+ SNOWPLOW_EVENT_CATEGORY = self.name
+
validates :url, public_url: true, presence: true, if: :activated?
validates :api_url, public_url: true, allow_blank: true
validates :username, presence: true, if: :activated?
@@ -362,13 +364,17 @@ module Integrations
)
true
- rescue StandardError => error
- log_exception(error, message: 'Issue transition failed', client_url: client_url)
+ rescue StandardError => e
+ log_exception(e, message: 'Issue transition failed', client_url: client_url)
false
end
def transition_issue_to_done(issue)
- transitions = issue.transitions rescue []
+ transitions = begin
+ issue.transitions
+ rescue StandardError
+ []
+ end
transition = transitions.find do |transition|
status = transition&.to&.statusCategory
@@ -384,6 +390,22 @@ module Integrations
key = "i_ecosystem_jira_service_#{action}"
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user.id)
+
+ return unless Feature.enabled?(:route_hll_to_snowplow_phase2)
+
+ optional_arguments = {
+ project: project,
+ namespace: group || project&.namespace
+ }.compact
+
+ Gitlab::Tracking.event(
+ SNOWPLOW_EVENT_CATEGORY,
+ Integration::SNOWPLOW_EVENT_ACTION,
+ label: Integration::SNOWPLOW_EVENT_LABEL,
+ property: key,
+ user: user,
+ **optional_arguments
+ )
end
def add_issue_solved_comment(issue, commit_id, commit_url)
@@ -505,7 +527,7 @@ module Integrations
self.project,
entity_type.to_sym
],
- id: entity_id,
+ id: entity_id,
host: Settings.gitlab.base_url
)
end
@@ -538,9 +560,9 @@ module Integrations
# Handle errors when doing Jira API calls
def jira_request
yield
- rescue StandardError => error
- @error = error
- log_exception(error, message: 'Error sending message', client_url: client_url)
+ rescue StandardError => e
+ @error = e
+ log_exception(e, message: 'Error sending message', client_url: client_url)
nil
end
diff --git a/app/models/integrations/packagist.rb b/app/models/integrations/packagist.rb
index fda4822c19f..f91404dab23 100644
--- a/app/models/integrations/packagist.rb
+++ b/app/models/integrations/packagist.rb
@@ -6,14 +6,14 @@ module Integrations
extend Gitlab::Utils::Override
field :username,
- title: -> { _('Username') },
+ title: -> { s_('Username') },
help: -> { s_('Enter your Packagist username.') },
placeholder: '',
required: true
field :token,
type: 'password',
- title: -> { _('Token') },
+ title: -> { s_('Token') },
help: -> { s_('Enter your Packagist token.') },
non_empty_password_title: -> { s_('ProjectService|Enter new token') },
non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
@@ -21,10 +21,11 @@ module Integrations
required: true
field :server,
- title: -> { _('Server (optional)') },
+ title: -> { s_('Server (optional)') },
help: -> { s_('Enter your Packagist server. Defaults to https://packagist.org.') },
placeholder: 'https://packagist.org',
- exposes_secrets: true
+ exposes_secrets: true,
+ required: false
validates :username, presence: true, if: :activated?
validates :token, presence: true, if: :activated?
@@ -55,8 +56,8 @@ module Integrations
begin
result = execute(data)
return { success: false, result: result[:message] } if result[:http_status] != 202
- rescue StandardError => error
- return { success: false, result: error }
+ rescue StandardError => e
+ return { success: false, result: e }
end
{ success: true, result: result[:message] }
diff --git a/app/models/integrations/pipelines_email.rb b/app/models/integrations/pipelines_email.rb
index 77cbba25f2c..55a8ce0be11 100644
--- a/app/models/integrations/pipelines_email.rb
+++ b/app/models/integrations/pipelines_email.rb
@@ -84,8 +84,8 @@ module Integrations
result = execute(data, force: true)
{ success: true, result: result }
- rescue StandardError => error
- { success: false, result: error }
+ rescue StandardError => e
+ { success: false, result: e }
end
def should_pipeline_be_notified?(data)
diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb
index e672a985810..142f466018b 100644
--- a/app/models/integrations/prometheus.rb
+++ b/app/models/integrations/prometheus.rb
@@ -70,8 +70,8 @@ module Integrations
prometheus_client.ping
{ success: true, result: 'Checked API endpoint' }
- rescue Gitlab::PrometheusClient::Error => err
- { success: false, result: err }
+ rescue Gitlab::PrometheusClient::Error => e
+ { success: false, result: e }
end
def prometheus_client
diff --git a/app/models/integrations/pumble.rb b/app/models/integrations/pumble.rb
new file mode 100644
index 00000000000..17026410eb1
--- /dev/null
+++ b/app/models/integrations/pumble.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Pumble < BaseChatNotification
+ def title
+ 'Pumble'
+ end
+
+ def description
+ s_("PumbleIntegration|Send notifications about project events to Pumble.")
+ end
+
+ def self.to_param
+ 'pumble'
+ end
+
+ def help
+ docs_link = ActionController::Base.helpers.link_to(
+ _('Learn more.'),
+ Rails.application.routes.url_helpers.help_page_url('user/project/integrations/pumble'),
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ )
+ # rubocop:disable Layout/LineLength
+ s_("PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}") % { docs_link: docs_link.html_safe }
+ # rubocop:enable Layout/LineLength
+ end
+
+ def default_channel_placeholder
+ end
+
+ def self.supported_events
+ %w[push issue confidential_issue merge_request note confidential_note tag_push
+ pipeline wiki_page]
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "https://api.pumble.com/workspaces/x/...", required: true },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ {
+ type: 'select',
+ name: 'branches_to_be_notified',
+ title: s_('Integrations|Branches for which notifications are to be sent'),
+ choices: self.class.branch_choices
+ }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ header = { 'Content-Type' => 'application/json' }
+ response = Gitlab::HTTP.post(webhook, headers: header, body: { text: message.summary }.to_json)
+
+ response if response.success?
+ end
+ end
+end
diff --git a/app/models/integrations/slack.rb b/app/models/integrations/slack.rb
index 93263229109..c254ea379bb 100644
--- a/app/models/integrations/slack.rb
+++ b/app/models/integrations/slack.rb
@@ -9,6 +9,7 @@ module Integrations
push issue confidential_issue merge_request note confidential_note
tag_push wiki_page deployment
].freeze
+ SNOWPLOW_EVENT_CATEGORY = self.name
prop_accessor EVENT_CHANNEL['alert']
@@ -54,6 +55,22 @@ module Integrations
key = "i_ecosystem_slack_service_#{event}_notification"
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user_id)
+
+ return unless Feature.enabled?(:route_hll_to_snowplow_phase2)
+
+ optional_arguments = {
+ project: project,
+ namespace: group || project&.namespace
+ }.compact
+
+ Gitlab::Tracking.event(
+ SNOWPLOW_EVENT_CATEGORY,
+ Integration::SNOWPLOW_EVENT_ACTION,
+ label: Integration::SNOWPLOW_EVENT_LABEL,
+ property: key,
+ user: User.find(user_id),
+ **optional_arguments
+ )
end
override :configurable_channels?
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
index e0299c9ac5f..ca7a715f4b3 100644
--- a/app/models/integrations/teamcity.rb
+++ b/app/models/integrations/teamcity.rb
@@ -67,11 +67,11 @@ module Integrations
end
def build_page(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
+ with_reactive_cache(sha, ref) { |cached| cached[:build_page] }
end
def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
end
def calculate_reactive_cache(sha, ref)
diff --git a/app/models/issuable_severity.rb b/app/models/issuable_severity.rb
index 928301e1da6..cd7e5fafb60 100644
--- a/app/models/issuable_severity.rb
+++ b/app/models/issuable_severity.rb
@@ -3,18 +3,18 @@
class IssuableSeverity < ApplicationRecord
DEFAULT = 'unknown'
SEVERITY_LABELS = {
- unknown: 'Unknown',
- low: 'Low - S4',
- medium: 'Medium - S3',
- high: 'High - S2',
+ unknown: 'Unknown',
+ low: 'Low - S4',
+ medium: 'Medium - S3',
+ high: 'High - S2',
critical: 'Critical - S1'
}.freeze
SEVERITY_QUICK_ACTION_PARAMS = {
- unknown: %w(Unknown 0),
- low: %w(Low S4 4),
- medium: %w(Medium S3 3),
- high: %w(High S2 2),
+ unknown: %w(Unknown 0),
+ low: %w(Low S4 4),
+ medium: %w(Medium S3 3),
+ high: %w(High S2 2),
critical: %w(Critical S1 1)
}.freeze
diff --git a/app/models/issue.rb b/app/models/issue.rb
index cae42115bef..4114467eb25 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -99,6 +99,10 @@ class Issue < ApplicationRecord
validates :project, presence: true
validates :issue_type, presence: true
validates :namespace, presence: true, if: -> { project.present? }
+ validates :work_item_type, presence: true
+
+ validate :due_date_after_start_date
+ validate :parent_link_confidentiality
enum issue_type: WorkItems::Type.base_types
@@ -201,7 +205,7 @@ class Issue < ApplicationRecord
scope :with_null_relative_position, -> { where(relative_position: nil) }
scope :with_non_null_relative_position, -> { where.not(relative_position: nil) }
- before_validation :ensure_namespace_id
+ before_validation :ensure_namespace_id, :ensure_work_item_type
after_commit :expire_etag_cache, unless: :importing?
after_save :ensure_metrics, unless: :importing?
@@ -257,17 +261,17 @@ class Issue < ApplicationRecord
order = ::Gitlab::Pagination::Keyset::Order.build([
::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: attribute_name,
- column_expression: column,
- order_expression: column.send(direction).send(nullable),
- reversed_order_expression: column.send(reversed_direction).send(nullable),
- order_direction: direction,
- distinct: false,
- add_to_projections: true,
- nullable: nullable
+ column_expression: column,
+ order_expression: column.send(direction).send(nullable),
+ reversed_order_expression: column.send(reversed_direction).send(nullable),
+ order_direction: direction,
+ distinct: false,
+ add_to_projections: true,
+ nullable: nullable
),
::Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: 'id',
- order_expression: arel_table['id'].desc
+ order_expression: arel_table['id'].desc
)
])
# rubocop: enable GitlabSecurity/PublicSend
@@ -289,6 +293,16 @@ class Issue < ApplicationRecord
def pg_full_text_search(search_term)
super.where('issue_search_data.project_id = issues.project_id')
end
+
+ override :full_search
+ def full_search(query, matched_columns: nil, use_minimum_char_limit: true)
+ return super if query.match?(IssuableFinder::FULL_TEXT_SEARCH_TERM_REGEX)
+
+ super.where(
+ 'issues.title NOT SIMILAR TO :pattern OR issues.description NOT SIMILAR TO :pattern',
+ pattern: IssuableFinder::FULL_TEXT_SEARCH_TERM_PATTERN
+ )
+ end
end
def next_object_by_relative_position(ignoring: nil, order: :asc)
@@ -660,6 +674,29 @@ class Issue < ApplicationRecord
private
+ def due_date_after_start_date
+ return unless start_date.present? && due_date.present?
+
+ if due_date < start_date
+ errors.add(:due_date, 'must be greater than or equal to start date')
+ end
+ end
+
+ # Although parent/child relationship can be set only for WorkItems, we
+ # still need to validate it for Issue model too, because both models use
+ # same table.
+ def parent_link_confidentiality
+ return unless persisted?
+
+ if confidential? && WorkItems::ParentLink.has_public_children?(id)
+ errors.add(:confidential, _('confidential parent can not be used if there are non-confidential children.'))
+ end
+
+ if !confidential? && WorkItems::ParentLink.has_confidential_parent?(id)
+ errors.add(:confidential, _('associated parent is confidential and can not have non-confidential children.'))
+ end
+ end
+
override :persist_pg_full_text_search_vector
def persist_pg_full_text_search_vector(search_vector)
Issues::SearchData.upsert({ project_id: project_id, issue_id: id, search_vector: search_vector }, unique_by: %i(project_id issue_id))
@@ -696,6 +733,12 @@ class Issue < ApplicationRecord
def ensure_namespace_id
self.namespace = project.project_namespace if project
end
+
+ def ensure_work_item_type
+ return if work_item_type_id.present? || work_item_type_id_change&.last.present?
+
+ self.work_item_type = WorkItems::Type.default_by_type(issue_type)
+ end
end
Issue.prepend_mod_with('Issue')
diff --git a/app/models/jira_connect_installation.rb b/app/models/jira_connect_installation.rb
index e34543534f3..8befe9a9230 100644
--- a/app/models/jira_connect_installation.rb
+++ b/app/models/jira_connect_installation.rb
@@ -2,9 +2,9 @@
class JiraConnectInstallation < ApplicationRecord
attr_encrypted :shared_secret,
- mode: :per_attribute_iv,
+ mode: :per_attribute_iv,
algorithm: 'aes-256-gcm',
- key: Settings.attr_encrypted_db_key_base_32
+ key: Settings.attr_encrypted_db_key_base_32
has_many :subscriptions, class_name: 'JiraConnectSubscription'
diff --git a/app/models/key.rb b/app/models/key.rb
index 9f6029cc5d4..78b0a38bcaa 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -40,6 +40,7 @@ class Key < ApplicationRecord
after_destroy :refresh_user_cache
alias_attribute :fingerprint_md5, :fingerprint
+ alias_attribute :name, :title
scope :preload_users, -> { preload(:user) }
scope :for_user, -> (user) { where(user: user) }
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index caeffae7bda..8aa48561e60 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -15,7 +15,7 @@ class LfsObject < ApplicationRecord
scope :for_oids, -> (oids) { where(oid: oids) }
scope :for_oid_and_size, -> (oid, size) { find_by(oid: oid, size: size) }
- validates :oid, presence: true, uniqueness: true
+ validates :oid, presence: true, uniqueness: true, format: { with: /\A\h{64}\z/ }
mount_file_store_uploader LfsObjectUploader
diff --git a/app/models/loose_foreign_keys/deleted_record.rb b/app/models/loose_foreign_keys/deleted_record.rb
index 6dfd6ea2aae..94444f4b6d3 100644
--- a/app/models/loose_foreign_keys/deleted_record.rb
+++ b/app/models/loose_foreign_keys/deleted_record.rb
@@ -9,26 +9,23 @@ class LooseForeignKeys::DeletedRecord < Gitlab::Database::SharedModel
self.ignored_columns = %i[partition]
partitioned_by :partition, strategy: :sliding_list,
- next_partition_if: -> (active_partition) do
- return false if Feature.disabled?(:lfk_automatic_partition_creation)
-
- oldest_record_in_partition = LooseForeignKeys::DeletedRecord
- .select(:id, :created_at)
- .for_partition(active_partition)
- .order(:id)
- .limit(1)
- .take
-
- oldest_record_in_partition.present? && oldest_record_in_partition.created_at < PARTITION_DURATION.ago
- end,
- detach_partition_if: -> (partition) do
- return false if Feature.disabled?(:lfk_automatic_partition_dropping)
-
- !LooseForeignKeys::DeletedRecord
- .for_partition(partition)
- .status_pending
- .exists?
- end
+ next_partition_if: -> (active_partition) do
+ oldest_record_in_partition = LooseForeignKeys::DeletedRecord
+ .select(:id, :created_at)
+ .for_partition(active_partition)
+ .order(:id)
+ .limit(1)
+ .take
+
+ oldest_record_in_partition.present? &&
+ oldest_record_in_partition.created_at < PARTITION_DURATION.ago
+ end,
+ detach_partition_if: -> (partition) do
+ !LooseForeignKeys::DeletedRecord
+ .for_partition(partition)
+ .status_pending
+ .exists?
+ end
scope :for_table, -> (table) { where(fully_qualified_table_name: table) }
scope :for_partition, -> (partition) { where(partition: partition) }
diff --git a/app/models/member.rb b/app/models/member.rb
index dcca63b5691..0cd1e022617 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -28,6 +28,7 @@ class Member < ApplicationRecord
belongs_to :user
belongs_to :source, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
belongs_to :member_namespace, inverse_of: :namespace_members, foreign_key: 'member_namespace_id', class_name: 'Namespace'
+ belongs_to :member_role
has_one :member_task
delegate :name, :username, :email, :last_activity_on, to: :user, prefix: true
@@ -58,6 +59,7 @@ class Member < ApplicationRecord
},
if: :project_bot?
validate :access_level_inclusion
+ validate :validate_member_role_access_level
scope :with_invited_user_state, -> do
joins('LEFT JOIN users as invited_user ON invited_user.email = members.invite_email')
@@ -428,6 +430,14 @@ class Member < ApplicationRecord
errors.add(:access_level, "is not included in the list")
end
+ def validate_member_role_access_level
+ return unless member_role_id
+
+ if access_level != member_role.base_access_level
+ errors.add(:member_role_id, _("role's base access level does not match the access level of the membership"))
+ end
+ end
+
def send_invite
# override in subclass
end
@@ -455,6 +465,8 @@ class Member < ApplicationRecord
# transaction has been committed, resulting in the job either throwing an
# error or not doing any meaningful work.
# rubocop: disable CodeReuse/ServiceClass
+
+ # This method is overridden in the test environment, see stubbed_member.rb
def refresh_member_authorized_projects(blocking:)
UserProjectAccessChangedService.new(user_id).execute(blocking: blocking)
end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 87af6a9a7f7..2b35f7da7b4 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -7,7 +7,6 @@ class GroupMember < Member
SOURCE_TYPE = 'Namespace'
SOURCE_TYPE_FORMAT = /\ANamespace\z/.freeze
- THRESHOLD_FOR_REFRESHING_AUTHORIZATIONS_VIA_PROJECTS = 1000
belongs_to :group, foreign_key: 'source_id'
alias_attribute :namespace_id, :source_id
@@ -67,28 +66,8 @@ class GroupMember < Member
# its projects are also destroyed, so the removal of project_authorizations
# will happen behind the scenes via DB foreign keys anyway.
return if destroyed_by_association.present?
- return unless user_id
- return super if Feature.disabled?(:refresh_authorizations_via_affected_projects_on_group_membership, group)
- # rubocop:disable CodeReuse/ServiceClass
- projects_to_refresh = Groups::ProjectsRequiringAuthorizationsRefresh::OnDirectMembershipFinder.new(group).execute
- threshold_exceeded = (projects_to_refresh.size > THRESHOLD_FOR_REFRESHING_AUTHORIZATIONS_VIA_PROJECTS)
-
- # We want to try the new approach only if the number of affected projects are greater than the set threshold.
- return super unless threshold_exceeded
-
- AuthorizedProjectUpdate::ProjectAccessChangedService
- .new(projects_to_refresh)
- .execute(blocking: false)
-
- # Until we compare the inconsistency rates of the new approach
- # the old approach, we still run AuthorizedProjectsWorker
- # but with some delay and lower urgency as a safety net.
- UserProjectAccessChangedService
- .new(user_id)
- .execute(blocking: false, priority: UserProjectAccessChangedService::LOW_PRIORITY)
-
- # rubocop:enable CodeReuse/ServiceClass
+ super
end
def send_invite
diff --git a/app/models/members/last_group_owner_assigner.rb b/app/models/members/last_group_owner_assigner.rb
index c85116858c7..e411a0ef5eb 100644
--- a/app/models/members/last_group_owner_assigner.rb
+++ b/app/models/members/last_group_owner_assigner.rb
@@ -8,7 +8,7 @@ class LastGroupOwnerAssigner
end
def execute
- @last_blocked_owner = no_owners_in_heirarchy? && group.single_blocked_owner?
+ @last_blocked_owner = no_owners_in_hierarchy? && group.single_blocked_owner?
@group_single_owner = owners.size == 1
members.each { |member| set_last_owner(member) }
@@ -18,7 +18,7 @@ class LastGroupOwnerAssigner
attr_reader :group, :members, :last_blocked_owner, :group_single_owner
- def no_owners_in_heirarchy?
+ def no_owners_in_hierarchy?
owners.empty?
end
diff --git a/app/models/members/member_role.rb b/app/models/members/member_role.rb
new file mode 100644
index 00000000000..2e8532fa739
--- /dev/null
+++ b/app/models/members/member_role.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class MemberRole < ApplicationRecord # rubocop:disable Gitlab/NamespacedClass
+ has_many :members
+ belongs_to :namespace
+
+ validates :namespace_id, presence: true
+ validates :base_access_level, presence: true
+end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index c97f00364fd..8fd82fcb34a 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -111,7 +111,7 @@ class ProjectMember < Member
# rubocop:disable CodeReuse/ServiceClass
if blocking
- AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.bulk_perform_and_wait([[project.id, user.id]])
+ blocking_project_authorizations_refresh
else
AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.perform_async(project.id, user.id)
end
@@ -124,6 +124,11 @@ class ProjectMember < Member
# rubocop:enable CodeReuse/ServiceClass
end
+ # This method is overridden in the test environment, see stubbed_member.rb
+ def blocking_project_authorizations_refresh
+ AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.bulk_perform_and_wait([[project.id, user.id]])
+ end
+
# TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
# temporary until we can we properly remove the source columns
override :set_member_namespace_id
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index ec97ab0ea42..3c06e1aa983 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -37,23 +37,25 @@ class MergeRequest < ApplicationRecord
SORTING_PREFERENCE_FIELD = :merge_requests_sort
ALLOWED_TO_USE_MERGE_BASE_PIPELINE_FOR_COMPARISON = {
- 'Ci::CompareMetricsReportsService' => ->(project) { true },
+ 'Ci::CompareMetricsReportsService' => ->(project) { true },
'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"
belongs_to :iteration, foreign_key: 'sprint_id'
has_internal_id :iid, scope: :target_project, track_if: -> { !importing? },
- init: ->(mr, scope) do
- if mr
- mr.target_project&.merge_requests&.maximum(:iid)
- elsif scope[:project]
- where(target_project: scope[:project]).maximum(:iid)
- end
- end
+ init: ->(mr, scope) do
+ if mr
+ mr.target_project&.merge_requests&.maximum(:iid)
+ elsif scope[:project]
+ where(target_project: scope[:project]).maximum(:iid)
+ end
+ end
has_many :merge_request_diffs,
-> { regular }, inverse_of: :merge_request
@@ -121,7 +123,8 @@ class MergeRequest < ApplicationRecord
:force_remove_source_branch,
:commit_message,
:squash_commit_message,
- :sha
+ :sha,
+ :skip_ci
].freeze
serialize :merge_params, Hash # rubocop:disable Cop/ActiveRecordSerialize
@@ -263,6 +266,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?
scope :by_source_or_target_branch, ->(branch_name) do
where("source_branch = :branch OR target_branch = :branch", branch: branch_name)
@@ -427,8 +431,7 @@ class MergeRequest < ApplicationRecord
def self.total_time_to_merge
join_metrics
.merge(MergeRequest::Metrics.with_valid_time_to_merge)
- .pluck(MergeRequest::Metrics.time_to_merge_expression)
- .first
+ .pick(MergeRequest::Metrics.time_to_merge_expression)
end
after_save :keep_around_commit, unless: :importing?
@@ -927,9 +930,9 @@ class MergeRequest < ApplicationRecord
# most recent data possible.
def repository_diff_refs
Gitlab::Diff::DiffRefs.new(
- base_sha: branch_merge_base_sha,
+ base_sha: branch_merge_base_sha,
start_sha: target_branch_sha,
- head_sha: source_branch_sha
+ head_sha: source_branch_sha
)
end
@@ -992,6 +995,20 @@ 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
+ 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 }
+ end
+
def merge_ongoing?
# While the MergeRequest is locked, it should present itself as 'merge ongoing'.
# The unlocking process is handled by StuckMergeJobsWorker scheduled in Cron.
@@ -1170,17 +1187,30 @@ class MergeRequest < ApplicationRecord
]
end
+ def detailed_merge_status
+ if cannot_be_merged_rechecking? || preparing? || checking?
+ return :checking
+ elsif unchecked?
+ return :unchecked
+ end
+
+ checks = execute_merge_checks
+
+ if checks.success?
+ :mergeable
+ else
+ checks.failure_reason
+ end
+ end
+
# rubocop: disable CodeReuse/ServiceClass
def mergeable_state?(skip_ci_check: false, skip_discussions_check: false)
if Feature.enabled?(:improved_mergeability_checks, self.project)
- additional_checks = MergeRequests::Mergeability::RunChecksService.new(
- merge_request: self,
- params: {
- skip_ci_check: skip_ci_check,
- skip_discussions_check: skip_discussions_check
- }
- )
- additional_checks.execute.all?(&:success?)
+ additional_checks = execute_merge_checks(params: {
+ skip_ci_check: skip_ci_check,
+ skip_discussions_check: skip_discussions_check
+ })
+ additional_checks.execute.success?
else
return false unless open?
return false if draft?
@@ -1500,14 +1530,14 @@ class MergeRequest < ApplicationRecord
end
def self.merge_train_ref?(ref)
- %r{\Arefs/#{Repository::REF_MERGE_REQUEST}/\d+/train\z}.match?(ref)
+ %r{\Arefs/#{Repository::REF_MERGE_REQUEST}/\d+/train\z}o.match?(ref)
end
def in_locked_state
lock_mr
yield
ensure
- unlock_mr
+ unlock_mr if locked?
end
def update_and_mark_in_progress_merge_commit_sha(commit_id)
@@ -1985,6 +2015,10 @@ class MergeRequest < ApplicationRecord
target_branch == project.default_branch
end
+ def merge_blocked_by_other_mrs?
+ false # Overridden in EE
+ end
+
private
attr_accessor :skip_fetch_ref
@@ -2038,6 +2072,12 @@ class MergeRequest < ApplicationRecord
def report_type_enabled?(report_type)
!!actual_head_pipeline&.batch_lookup_report_artifact_for_file_type(report_type)
end
+
+ def execute_merge_checks(params: {})
+ # rubocop: disable CodeReuse/ServiceClass
+ MergeRequests::Mergeability::RunChecksService.new(merge_request: self, params: params).execute
+ # rubocop: enable CodeReuse/ServiceClass
+ end
end
MergeRequest.prepend_mod_with('MergeRequest')
diff --git a/app/models/merge_request/approval_removal_settings.rb b/app/models/merge_request/approval_removal_settings.rb
new file mode 100644
index 00000000000..b07242e2578
--- /dev/null
+++ b/app/models/merge_request/approval_removal_settings.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class MergeRequest::ApprovalRemovalSettings # rubocop:disable Style/ClassAndModuleChildren
+ include ActiveModel::Validations
+
+ attr_accessor :project
+
+ validate :mutually_exclusive_settings
+
+ def initialize(project, reset_approvals_on_push, selective_code_owner_removals)
+ @project = project
+ @reset_approvals_on_push = reset_approvals_on_push
+ @selective_code_owner_removals = selective_code_owner_removals
+ end
+
+ private
+
+ def selective_code_owner_removals
+ if @selective_code_owner_removals.nil?
+ project.project_setting.selective_code_owner_removals
+ else
+ @selective_code_owner_removals
+ end
+ end
+
+ def reset_approvals_on_push
+ if @reset_approvals_on_push.nil?
+ project.reset_approvals_on_push
+ else
+ @reset_approvals_on_push
+ end
+ end
+
+ def mutually_exclusive_settings
+ return unless selective_code_owner_removals && reset_approvals_on_push
+
+ errors.add(:base, 'selective_code_owner_removals can only be enabled when reset_approvals_on_push is disabled')
+ end
+end
diff --git a/app/models/merge_request/metrics.rb b/app/models/merge_request/metrics.rb
index b984228eb13..c546a5a0025 100644
--- a/app/models/merge_request/metrics.rb
+++ b/app/models/merge_request/metrics.rb
@@ -41,8 +41,7 @@ class MergeRequest::Metrics < ApplicationRecord
def self.total_time_to_merge
with_valid_time_to_merge
- .pluck(time_to_merge_expression)
- .first
+ .pick(time_to_merge_expression)
end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index e08b2cc2a7d..9f7e98dc04b 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -358,9 +358,9 @@ class MergeRequestDiff < ApplicationRecord
return unless start_commit_sha || base_commit_sha
Gitlab::Diff::DiffRefs.new(
- base_sha: base_commit_sha,
+ base_sha: base_commit_sha,
start_sha: start_commit_sha,
- head_sha: head_commit_sha
+ head_sha: head_commit_sha
)
end
@@ -381,9 +381,9 @@ class MergeRequestDiff < ApplicationRecord
likely_base_commit_sha = (first_commit&.parent || first_commit)&.sha
Gitlab::Diff::DiffRefs.new(
- base_sha: likely_base_commit_sha,
+ base_sha: likely_base_commit_sha,
start_sha: safe_start_commit_sha,
- head_sha: head_commit_sha
+ head_sha: head_commit_sha
)
end
@@ -706,8 +706,7 @@ class MergeRequestDiff < ApplicationRecord
latest_id = MergeRequest
.where(id: merge_request_id)
.limit(1)
- .pluck(:latest_merge_request_diff_id)
- .first
+ .pick(:latest_merge_request_diff_id)
latest_id && self.id < latest_id
end
diff --git a/app/models/ml.rb b/app/models/ml.rb
new file mode 100644
index 00000000000..e426ce851eb
--- /dev/null
+++ b/app/models/ml.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+module Ml
+ def self.table_name_prefix
+ 'ml_'
+ end
+end
diff --git a/app/models/ml/candidate.rb b/app/models/ml/candidate.rb
new file mode 100644
index 00000000000..e181217f01c
--- /dev/null
+++ b/app/models/ml/candidate.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Ml
+ class Candidate < ApplicationRecord
+ validates :iid, :experiment, presence: true
+
+ belongs_to :experiment, class_name: 'Ml::Experiment'
+ belongs_to :user
+ has_many :metrics, class_name: 'Ml::CandidateMetric'
+ has_many :params, class_name: 'Ml::CandidateParam'
+ end
+end
diff --git a/app/models/ml/candidate_metric.rb b/app/models/ml/candidate_metric.rb
new file mode 100644
index 00000000000..e03a8b83ee6
--- /dev/null
+++ b/app/models/ml/candidate_metric.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Ml
+ class CandidateMetric < ApplicationRecord
+ validates :candidate, presence: true
+ validates :name, length: { maximum: 250 }, presence: true
+
+ belongs_to :candidate, class_name: 'Ml::Candidate'
+ end
+end
diff --git a/app/models/ml/candidate_param.rb b/app/models/ml/candidate_param.rb
new file mode 100644
index 00000000000..cbdddcc8a1a
--- /dev/null
+++ b/app/models/ml/candidate_param.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Ml
+ class CandidateParam < ApplicationRecord
+ validates :candidate, presence: true
+ validates :name, :value, length: { maximum: 250 }, presence: true
+
+ belongs_to :candidate, class_name: 'Ml::Candidate'
+ end
+end
diff --git a/app/models/ml/experiment.rb b/app/models/ml/experiment.rb
new file mode 100644
index 00000000000..7ef9c70ba7e
--- /dev/null
+++ b/app/models/ml/experiment.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Ml
+ class Experiment < ApplicationRecord
+ validates :name, :iid, :project, presence: true
+ validates :iid, :name, uniqueness: { scope: :project, message: "should be unique in the project" }
+
+ belongs_to :project
+ belongs_to :user
+ has_many :candidates, class_name: 'Ml::Candidate'
+ end
+end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index f23a859b119..06f49f16d66 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -40,15 +40,21 @@ class Namespace < ApplicationRecord
PATH_TRAILING_VIOLATIONS = %w[.git .atom .].freeze
+ # The first date in https://docs.gitlab.com/ee/user/usage_quotas.html#namespace-storage-limit-enforcement-schedule
+ # Determines when we start enforcing namespace storage
+ MIN_STORAGE_ENFORCEMENT_DATE = Date.new(2022, 10, 19)
+
cache_markdown_field :description, pipeline: :description
has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :project_statistics
has_one :namespace_settings, inverse_of: :namespace, class_name: 'NamespaceSetting', autosave: true
has_one :ci_cd_settings, inverse_of: :namespace, class_name: 'NamespaceCiCdSetting', autosave: true
+ has_one :namespace_details, inverse_of: :namespace, class_name: 'Namespace::Detail', autosave: true
has_one :namespace_statistics
has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route'
has_many :namespace_members, foreign_key: :member_namespace_id, inverse_of: :member_namespace, class_name: 'Member'
+ has_many :member_roles
has_many :runner_namespaces, inverse_of: :namespace, class_name: 'Ci::RunnerNamespace'
has_many :runners, through: :runner_namespaces, source: :runner, class_name: 'Ci::Runner'
@@ -77,6 +83,8 @@ class Namespace < ApplicationRecord
has_many :work_items, inverse_of: :namespace
has_many :issues, inverse_of: :namespace
+ has_many :timelog_categories, class_name: 'TimeTracking::TimelogCategory'
+
validates :owner, presence: true, if: ->(n) { n.owner_required? }
validates :name,
presence: true,
@@ -120,6 +128,7 @@ class Namespace < ApplicationRecord
to: :namespace_settings, allow_nil: true
after_save :schedule_sync_event_worker, if: -> { saved_change_to_id? || saved_change_to_parent_id? }
+ after_save :reload_namespace_details
after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') }
@@ -559,9 +568,7 @@ class Namespace < ApplicationRecord
def storage_enforcement_date
return Date.current if Feature.enabled?(:namespace_storage_limit_bypass_date_check, self)
- # should return something like Date.new(2022, 02, 03)
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
- nil
+ MIN_STORAGE_ENFORCEMENT_DATE
end
def certificate_based_clusters_enabled?
@@ -671,6 +678,12 @@ class Namespace < ApplicationRecord
end
end
+ def reload_namespace_details
+ return unless !project_namespace? && (previous_changes.keys & %w(description description_html cached_markdown_version)).any? && namespace_details.present?
+
+ namespace_details.reset
+ end
+
def sync_share_with_group_lock_with_parent
if parent&.share_with_group_lock?
self.share_with_group_lock = true
diff --git a/app/models/namespace/detail.rb b/app/models/namespace/detail.rb
new file mode 100644
index 00000000000..dbbf9f4944a
--- /dev/null
+++ b/app/models/namespace/detail.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Namespace::Detail < ApplicationRecord
+ belongs_to :namespace, inverse_of: :namespace_details
+ validates :namespace, presence: true
+ validates :description, length: { maximum: 255 }
+
+ self.primary_key = :namespace_id
+end
diff --git a/app/models/namespaces/traversal/linear_scopes.rb b/app/models/namespaces/traversal/linear_scopes.rb
index 6f404ec12d0..81ac026d7ff 100644
--- a/app/models/namespaces/traversal/linear_scopes.rb
+++ b/app/models/namespaces/traversal/linear_scopes.rb
@@ -27,15 +27,9 @@ module Namespaces
def self_and_ancestors(include_self: true, upto: nil, hierarchy_order: nil)
return super unless use_traversal_ids_for_ancestor_scopes?
- if Feature.enabled?(:use_traversal_ids_for_ancestor_scopes_with_inner_join)
- self_and_ancestors_from_inner_join(include_self: include_self,
- upto: upto, hierarchy_order:
- hierarchy_order)
- else
- self_and_ancestors_from_ancestors_cte(include_self: include_self,
- upto: upto,
- hierarchy_order: hierarchy_order)
- end
+ self_and_ancestors_from_inner_join(include_self: include_self,
+ upto: upto, hierarchy_order:
+ hierarchy_order)
end
def self_and_ancestor_ids(include_self: true)
@@ -117,37 +111,6 @@ module Namespaces
use_traversal_ids?
end
- def self_and_ancestors_from_ancestors_cte(include_self: true, upto: nil, hierarchy_order: nil)
- base_cte = all.select('namespaces.id', 'namespaces.traversal_ids').as_cte(:base_ancestors_cte)
-
- # We have to alias id with 'AS' to avoid ambiguous column references by calling methods.
- ancestors_cte = unscoped
- .unscope(where: [:type])
- .select('id as base_id',
- "#{unnest_func(base_cte.table['traversal_ids']).to_sql} as ancestor_id")
- .from(base_cte.table)
- .as_cte(:ancestors_cte)
-
- namespaces = Arel::Table.new(:namespaces)
-
- records = unscoped
- .with(base_cte.to_arel, ancestors_cte.to_arel)
- .distinct
- .from([ancestors_cte.table, namespaces])
- .where(namespaces[:id].eq(ancestors_cte.table[:ancestor_id]))
- .order_by_depth(hierarchy_order)
-
- unless include_self
- records = records.where(ancestors_cte.table[:base_id].not_eq(ancestors_cte.table[:ancestor_id]))
- end
-
- if upto
- records = records.where.not(id: unscoped.where(id: upto).select('unnest(traversal_ids)'))
- end
-
- records
- end
-
def self_and_ancestors_from_inner_join(include_self: true, upto: nil, hierarchy_order: nil)
base_cte = all.reselect('namespaces.traversal_ids').as_cte(:base_ancestors_cte)
@@ -181,25 +144,15 @@ module Namespaces
end
def self_and_descendants_with_comparison_operators(include_self: true)
- base = all.select(:traversal_ids)
- base = base.select(:id) if Feature.enabled?(:linear_scopes_superset)
+ base = all.select(:id, :traversal_ids)
base_cte = base.as_cte(:descendants_base_cte)
namespaces = Arel::Table.new(:namespaces)
- withs = [base_cte.to_arel]
- froms = []
-
- if Feature.enabled?(:linear_scopes_superset)
- superset_cte = self.superset_cte(base_cte.table.name)
- withs += [superset_cte.to_arel]
- froms = [superset_cte.table]
- else
- froms = [base_cte.table]
- end
-
+ superset_cte = self.superset_cte(base_cte.table.name)
+ withs = [base_cte.to_arel, superset_cte.to_arel]
# Order is important. namespace should be last to handle future joins.
- froms += [namespaces]
+ froms = [superset_cte.table, namespaces]
base_ref = froms.first
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 560ff861105..a034d97a6bb 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -211,7 +211,7 @@ module Network
# Visit branching chains
leaves.each do |l|
- parents = l.parents(@map).select {|p| p.space == 0}
+ parents = l.parents(@map).select { |p| p.space == 0 }
parents.each do |p|
place_chain(p, l.time)
end
diff --git a/app/models/note.rb b/app/models/note.rb
index 986a85acac6..1715f7cdc3b 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -23,6 +23,8 @@ class Note < ApplicationRecord
include FromUnion
include Sortable
+ ISSUE_TASK_SYSTEM_NOTE_PATTERN = /\A.*marked\sthe\stask.+as\s(completed|incomplete).*\z/.freeze
+
cache_markdown_field :note, pipeline: :note, issuable_reference_expansion_enabled: true
redact_field :note
@@ -685,6 +687,22 @@ class Note < ApplicationRecord
Ability.users_that_can_read_internal_notes(users, resource_parent).pluck(:id)
end
+ # 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)
+
+ super.sub!('task', 'checklist item')
+ end
+
+ # 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)
+
+ super.sub!('task', 'checklist item')
+ end
+
private
def system_note_viewable_by?(user)
diff --git a/app/models/notification_reason.rb b/app/models/notification_reason.rb
index 3713be6cb91..c227626af9e 100644
--- a/app/models/notification_reason.rb
+++ b/app/models/notification_reason.rb
@@ -6,7 +6,6 @@ class NotificationReason
OWN_ACTIVITY = 'own_activity'
ASSIGNED = 'assigned'
REVIEW_REQUESTED = 'review_requested'
- ATTENTION_REQUESTED = 'attention_requested'
MENTIONED = 'mentioned'
SUBSCRIBED = 'subscribed'
@@ -15,7 +14,6 @@ class NotificationReason
OWN_ACTIVITY,
ASSIGNED,
REVIEW_REQUESTED,
- ATTENTION_REQUESTED,
MENTIONED,
SUBSCRIBED
].freeze
diff --git a/app/models/oauth_access_token.rb b/app/models/oauth_access_token.rb
index 20130f01d44..7d71e15d3c5 100644
--- a/app/models/oauth_access_token.rb
+++ b/app/models/oauth_access_token.rb
@@ -6,7 +6,6 @@ class OauthAccessToken < Doorkeeper::AccessToken
alias_attribute :user, :resource_owner
- scope :distinct_resource_owner_counts, ->(applications) { where(application: applications).distinct.group(:application_id).count(:resource_owner_id) }
scope :latest_per_application, -> { select('distinct on(application_id) *').order(application_id: :desc, created_at: :desc) }
scope :preload_application, -> { preload(:application) }
@@ -17,4 +16,14 @@ class OauthAccessToken < Doorkeeper::AccessToken
super
end
end
+
+ # this method overrides a shortcoming upstream, more context:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/367888
+ def self.find_by_fallback_token(attr, plain_secret)
+ return unless fallback_secret_strategy && fallback_secret_strategy == Doorkeeper::SecretStoring::Plain
+ # token is hashed, don't allow plaintext comparison
+ return if plain_secret.starts_with?("$")
+
+ super
+ end
end
diff --git a/app/models/operations/feature_flag.rb b/app/models/operations/feature_flag.rb
index 7db396bcad5..e36c59366fe 100644
--- a/app/models/operations/feature_flag.rb
+++ b/app/models/operations/feature_flag.rb
@@ -42,7 +42,7 @@ module Operations
scope :enabled, -> { where(active: true) }
scope :disabled, -> { where(active: false) }
- scope :new_version_only, -> { where(version: :new_version_flag)}
+ scope :new_version_only, -> { where(version: :new_version_flag) }
enum version: {
new_version_flag: 2
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index 90a1bb4bc69..afd55b4f143 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -65,7 +65,7 @@ class Packages::Package < ApplicationRecord
validates :name,
uniqueness: {
scope: %i[project_id version package_type],
- conditions: -> { not_pending_destruction}
+ conditions: -> { not_pending_destruction }
},
unless: -> { pending_destruction? || conan? || debian_package? }
@@ -327,7 +327,7 @@ class Packages::Package < ApplicationRecord
def normalized_pypi_name
return name unless pypi?
- name.gsub(/#{Gitlab::Regex::Packages::PYPI_NORMALIZED_NAME_REGEX_STRING}/, '-').downcase
+ name.gsub(/#{Gitlab::Regex::Packages::PYPI_NORMALIZED_NAME_REGEX_STRING}/o, '-').downcase
end
private
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 9e93bff4acf..2e25839c47f 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -23,10 +23,10 @@ class PagesDomain < ApplicationRecord
validates :domain, uniqueness: { case_sensitive: false }
validates :certificate, :key, presence: true, if: :usage_serverless?
validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' },
- if: :certificate_should_be_present?
+ if: :certificate_should_be_present?
validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
validates :key, presence: { message: 'must be present if HTTPS-only is enabled' },
- if: :certificate_should_be_present?
+ if: :certificate_should_be_present?
validates :key, certificate_key: true, named_ecdsa_key: true, if: ->(domain) { domain.key.present? }
validates :verification_code, presence: true, allow_blank: false
diff --git a/app/models/performance_monitoring/prometheus_dashboard.rb b/app/models/performance_monitoring/prometheus_dashboard.rb
index 40d14aaa1de..4804f620a99 100644
--- a/app/models/performance_monitoring/prometheus_dashboard.rb
+++ b/app/models/performance_monitoring/prometheus_dashboard.rb
@@ -57,10 +57,10 @@ module PerformanceMonitoring
self.class.from_json(reload_schema)
[]
- rescue Gitlab::Metrics::Dashboard::Errors::LayoutError => error
- [error.message]
- rescue ActiveModel::ValidationError => exception
- exception.model.errors.map { |attr, error| "#{attr}: #{error}" }
+ rescue Gitlab::Metrics::Dashboard::Errors::LayoutError => e
+ [e.message]
+ rescue ActiveModel::ValidationError => e
+ e.model.errors.map { |attr, error| "#{attr}: #{error}" }
end
private
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 68ba3d6eab4..7e6e366f8da 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -20,7 +20,7 @@ class PersonalAccessToken < ApplicationRecord
before_save :ensure_token
- scope :active, -> { where("revoked = false AND (expires_at >= CURRENT_DATE OR expires_at IS NULL)") }
+ scope :active, -> { not_revoked.not_expired }
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") }
@@ -33,6 +33,7 @@ class PersonalAccessToken < ApplicationRecord
scope :preload_users, -> { preload(:user) }
scope :order_expires_at_asc, -> { reorder(expires_at: :asc) }
scope :order_expires_at_desc, -> { reorder(expires_at: :desc) }
+ 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 }) }
@@ -57,8 +58,8 @@ class PersonalAccessToken < ApplicationRecord
begin
Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_token)
- rescue StandardError => ex
- logger.warn "Failed to decrypt #{self.name} value stored in Redis for key ##{redis_key}: #{ex.class}"
+ rescue StandardError => e
+ logger.warn "Failed to decrypt #{self.name} value stored in Redis for key ##{redis_key}: #{e.class}"
encrypted_token
end
end
@@ -77,7 +78,8 @@ class PersonalAccessToken < ApplicationRecord
super.merge(
{
'expires_at_asc' => -> { order_expires_at_asc },
- 'expires_at_desc' => -> { order_expires_at_desc }
+ 'expires_at_desc' => -> { order_expires_at_desc },
+ 'expires_at_asc_id_desc' => -> { order_expires_at_asc_id_desc }
}
)
end
diff --git a/app/models/preloaders/labels_preloader.rb b/app/models/preloaders/labels_preloader.rb
index bb3206f5399..722d588d8bc 100644
--- a/app/models/preloaders/labels_preloader.rb
+++ b/app/models/preloaders/labels_preloader.rb
@@ -21,8 +21,8 @@ module Preloaders
def preload_all
preloader = ActiveRecord::Associations::Preloader.new
- preloader.preload(labels.select {|l| l.is_a? ProjectLabel }, { project: [:project_feature, namespace: :route] })
- preloader.preload(labels.select {|l| l.is_a? GroupLabel }, { group: :route })
+ 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/project.rb b/app/models/project.rb
index ebfec34c3e1..0c49cc24a8d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -53,6 +53,7 @@ class Project < ApplicationRecord
ignore_columns :mirror_last_update_at, :mirror_last_successful_update_at, remove_after: '2021-09-22', remove_with: '14.4'
ignore_columns :pull_mirror_branch_prefix, remove_after: '2021-09-22', remove_with: '14.4'
+ ignore_columns :build_coverage_regex, remove_after: '2022-10-22', remove_with: '15.5'
STATISTICS_ATTRIBUTE = 'repositories_count'
UNKNOWN_IMPORT_URL = 'http://unknown.git'
@@ -131,6 +132,8 @@ class Project < ApplicationRecord
after_save :save_topics
+ after_save :reload_project_namespace_details
+
after_create -> { create_or_load_association(:project_feature) }
after_create -> { create_or_load_association(:ci_cd_settings) }
@@ -176,7 +179,7 @@ class Project < ApplicationRecord
alias_method :parent, :namespace
alias_attribute :parent_id, :namespace_id
- has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
+ has_one :last_event, -> { order 'events.created_at DESC' }, class_name: 'Event'
has_many :boards
def self.integration_association_name(name)
@@ -213,6 +216,7 @@ class Project < ApplicationRecord
has_one :pipelines_email_integration, class_name: 'Integrations::PipelinesEmail'
has_one :pivotaltracker_integration, class_name: 'Integrations::Pivotaltracker'
has_one :prometheus_integration, class_name: 'Integrations::Prometheus', inverse_of: :project
+ has_one :pumble_integration, class_name: 'Integrations::Pumble'
has_one :pushover_integration, class_name: 'Integrations::Pushover'
has_one :redmine_integration, class_name: 'Integrations::Redmine'
has_one :shimo_integration, class_name: 'Integrations::Shimo'
@@ -288,6 +292,8 @@ class Project < ApplicationRecord
has_many :project_members, -> { where(requested_at: nil) },
as: :source, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
+ has_many :project_callouts, class_name: 'Users::ProjectCallout', foreign_key: :project_id
+
alias_method :members, :project_members
has_many :users, through: :project_members
@@ -446,7 +452,8 @@ class Project < ApplicationRecord
:repository_access_level, :package_registry_access_level, :pages_access_level,
:metrics_dashboard_access_level, :analytics_access_level,
:operations_access_level, :security_and_compliance_access_level,
- :container_registry_access_level,
+ :container_registry_access_level, :environments_access_level, :feature_flags_access_level,
+ :releases_access_level,
to: :project_feature, allow_nil: true
delegate :show_default_award_emojis, :show_default_award_emojis=,
@@ -472,6 +479,7 @@ class Project < ApplicationRecord
delegate :job_token_scope_enabled, :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
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, to: :ci_cd_settings, allow_nil: true
delegate :separated_caches, :separated_caches=, to: :ci_cd_settings, prefix: :ci, allow_nil: true
delegate :runner_token_expiration_interval, :runner_token_expiration_interval=, :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval_human_readable=, to: :ci_cd_settings, allow_nil: true
@@ -663,6 +671,7 @@ class Project < ApplicationRecord
scope :imported_from, -> (type) { where(import_type: type) }
scope :imported, -> { where.not(import_type: nil) }
scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) }
+ scope :last_activity_before, -> (time) { where('projects.last_activity_at < ?', time) }
scope :with_service_desk_key, -> (key) do
# project_key is not indexed for now
@@ -814,7 +823,7 @@ class Project < ApplicationRecord
(?<!#{Gitlab::PathRegex::PATH_START_CHAR})
((?<namespace>#{Gitlab::PathRegex::FULL_NAMESPACE_FORMAT_REGEX})\/)?
(?<project>#{Gitlab::PathRegex::PROJECT_PATH_FORMAT_REGEX})
- }x
+ }xo
end
def reference_postfix
@@ -1041,6 +1050,7 @@ class Project < ApplicationRecord
def emails_enabled?
!emails_disabled?
end
+
override :lfs_enabled?
def lfs_enabled?
return namespace.lfs_enabled? if self[:lfs_enabled].nil?
@@ -1675,7 +1685,13 @@ class Project < ApplicationRecord
end
def has_active_hooks?(hooks_scope = :push_hooks)
- hooks.hooks_for(hooks_scope).any? || SystemHook.hooks_for(hooks_scope).any? || Gitlab::FileHook.any?
+ @has_active_hooks ||= {} # rubocop: disable Gitlab/PredicateMemoization
+
+ return @has_active_hooks[hooks_scope] if @has_active_hooks.key?(hooks_scope)
+
+ @has_active_hooks[hooks_scope] = hooks.hooks_for(hooks_scope).any? ||
+ SystemHook.hooks_for(hooks_scope).any? ||
+ Gitlab::FileHook.any?
end
def has_active_integrations?(hooks_scope = :push_hooks)
@@ -1757,8 +1773,8 @@ class Project < ApplicationRecord
repository.after_create
true
- rescue StandardError => err
- Gitlab::ErrorTracking.track_exception(err, project: { id: id, full_path: full_path, disk_path: disk_path })
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, project: { id: id, full_path: full_path, disk_path: disk_path })
errors.add(:base, _('Failed to create repository'))
false
end
@@ -2254,6 +2270,7 @@ class Project < ApplicationRecord
.concat(dependency_proxy_variables)
.concat(auto_devops_variables)
.concat(api_variables)
+ .concat(ci_template_variables)
end
end
@@ -2307,6 +2324,12 @@ class Project < ApplicationRecord
end
end
+ def ci_template_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_TEMPLATE_REGISTRY_HOST', value: 'registry.gitlab.com')
+ end
+ end
+
def dependency_proxy_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless Gitlab.config.dependency_proxy.enabled
@@ -2651,7 +2674,7 @@ class Project < ApplicationRecord
{
repository_storage: repository_storage,
- pool_repository: pool_repository || create_new_pool_repository
+ pool_repository: pool_repository || create_new_pool_repository
}
end
@@ -2880,6 +2903,12 @@ class Project < ApplicationRecord
ci_cd_settings.forward_deployment_enabled?
end
+ def ci_allow_fork_pipelines_to_run_in_parent_project?
+ return false unless ci_cd_settings
+
+ ci_cd_settings.allow_fork_pipelines_to_run_in_parent_project?
+ end
+
def ci_job_token_scope_enabled?
return false unless ci_cd_settings
@@ -2984,6 +3013,14 @@ class Project < ApplicationRecord
group&.work_items_feature_flag_enabled? || Feature.enabled?(:work_items, self)
end
+ def work_items_mvc_2_feature_flag_enabled?
+ group&.work_items_mvc_2_feature_flag_enabled? || Feature.enabled?(:work_items_mvc_2)
+ end
+
+ def work_items_create_from_markdown_feature_flag_enabled?
+ work_items_feature_flag_enabled? && (group&.work_items_create_from_markdown_feature_flag_enabled? || Feature.enabled?(:work_items_create_from_markdown))
+ end
+
def enqueue_record_project_target_platforms
return unless Gitlab.com?
return unless Feature.enabled?(:record_projects_target_platforms, self)
@@ -3008,6 +3045,10 @@ class Project < ApplicationRecord
licensed_feature_available?(:security_training)
end
+ def destroy_deployment_by_id(deployment_id)
+ deployments.where(id: deployment_id).fast_destroy_all
+ end
+
private
# overridden in EE
@@ -3238,6 +3279,12 @@ class Project < ApplicationRecord
project_namespace.assign_attributes(attributes_to_sync)
end
+ def reload_project_namespace_details
+ return unless (previous_changes.keys & %w(description description_html cached_markdown_version)).any? && project_namespace.namespace_details.present?
+
+ project_namespace.namespace_details.reset
+ end
+
# SyncEvents are created by PG triggers (with the function `insert_projects_sync_event`)
def schedule_sync_event_worker
run_after_commit do
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index 0a30e125c83..8623e477c06 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -21,6 +21,9 @@ class ProjectFeature < ApplicationRecord
security_and_compliance
container_registry
package_registry
+ environments
+ feature_flags
+ releases
].freeze
EXPORTABLE_FEATURES = (FEATURES - [:security_and_compliance, :pages]).freeze
diff --git a/app/models/projects/import_export/relation_export.rb b/app/models/projects/import_export/relation_export.rb
index 0a31e525ac2..15198049f87 100644
--- a/app/models/projects/import_export/relation_export.rb
+++ b/app/models/projects/import_export/relation_export.rb
@@ -3,6 +3,20 @@
module Projects
module ImportExport
class RelationExport < ApplicationRecord
+ DESIGN_REPOSITORY_RELATION = 'design_repository'
+ LFS_OBJECTS_RELATION = 'lfs_objects'
+ REPOSITORY_RELATION = 'repository'
+ ROOT_RELATION = 'project'
+ SNIPPETS_REPOSITORY_RELATION = 'snippets_repository'
+ UPLOADS_RELATION = 'uploads'
+ WIKI_REPOSITORY_RELATION = 'wiki_repository'
+
+ EXTRA_RELATION_LIST = [
+ DESIGN_REPOSITORY_RELATION, LFS_OBJECTS_RELATION, REPOSITORY_RELATION, ROOT_RELATION,
+ SNIPPETS_REPOSITORY_RELATION, UPLOADS_RELATION, WIKI_REPOSITORY_RELATION
+ ].freeze
+ private_constant :EXTRA_RELATION_LIST
+
self.table_name = 'project_relation_exports'
belongs_to :project_export_job
@@ -17,6 +31,33 @@ module Projects
validates :project_export_job, presence: true
validates :relation, presence: true, length: { maximum: 255 }, uniqueness: { scope: :project_export_job_id }
validates :status, numericality: { only_integer: true }, presence: true
+
+ scope :by_relation, -> (relation) { where(relation: relation) }
+
+ state_machine :status, initial: :queued do
+ state :queued, value: 0
+ state :started, value: 1
+ state :finished, value: 2
+ state :failed, value: 3
+
+ event :start do
+ transition queued: :started
+ end
+
+ event :finish do
+ transition started: :finished
+ end
+
+ event :fail_op do
+ transition [:queued, :started] => :failed
+ end
+ end
+
+ def self.relation_names_list
+ project_tree_relation_names = ::Gitlab::ImportExport::Reader.new(shared: nil).project_relation_names.map(&:to_s)
+
+ project_tree_relation_names + EXTRA_RELATION_LIST
+ end
end
end
end
diff --git a/app/models/projects/topic.rb b/app/models/projects/topic.rb
index bc7f94e4374..b0f138714a0 100644
--- a/app/models/projects/topic.rb
+++ b/app/models/projects/topic.rb
@@ -15,6 +15,7 @@ module Projects
has_many :project_topics, class_name: 'Projects::ProjectTopic'
has_many :projects, through: :project_topics
+ scope :without_assigned_projects, -> { where(total_projects_count: 0) }
scope :order_by_non_private_projects_count, -> { order(non_private_projects_count: :desc).order(id: :asc) }
scope :reorder_by_similarity, -> (search) do
order_expression = Gitlab::Database::SimilarityScore.build_expression(search: search, rules: [
diff --git a/app/models/prometheus_alert.rb b/app/models/prometheus_alert.rb
index 684f50d5f58..9080f3d9de1 100644
--- a/app/models/prometheus_alert.rb
+++ b/app/models/prometheus_alert.rb
@@ -25,7 +25,7 @@ class PrometheusAlert < ApplicationRecord
validates :environment, :project, :prometheus_metric, :threshold, :operator, presence: true
validates :runbook_url, length: { maximum: 255 }, allow_blank: true,
- addressable_url: { enforce_sanitization: true, ascii_only: true }
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
validate :require_valid_environment_project!
validate :require_valid_metric_project!
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 7cf15439b47..76c277e4b86 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -4,8 +4,6 @@ class ProtectedBranch < ApplicationRecord
include ProtectedRef
include Gitlab::SQL::Pattern
- CACHE_EXPIRE_IN = 1.hour
-
scope :requiring_code_owner_approval,
-> { where(code_owner_approval_required: true) }
@@ -27,10 +25,30 @@ class ProtectedBranch < ApplicationRecord
end
# Check if branch name is marked as protected in the system
- def self.protected?(project, ref_name)
+ def self.protected?(project, ref_name, dry_run: true)
return true if project.empty_repo? && project.default_branch_protected?
return false if ref_name.blank?
+ new_cache_result = new_cache(project, ref_name, dry_run: dry_run)
+
+ return new_cache_result unless new_cache_result.nil?
+
+ deprecated_cache(project, ref_name)
+ end
+
+ def self.new_cache(project, ref_name, dry_run: true)
+ if Feature.enabled?(:hash_based_cache_for_protected_branches, project)
+ ProtectedBranches::CacheService.new(project).fetch(ref_name, dry_run: dry_run) do # rubocop: disable CodeReuse/ServiceClass
+ self.matching(ref_name, protected_refs: protected_refs(project)).present?
+ end
+ end
+ end
+
+ # Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/368279
+ # ----------------------------------------------------------------
+ CACHE_EXPIRE_IN = 1.hour
+
+ def self.deprecated_cache(project, ref_name)
Rails.cache.fetch(protected_ref_cache_key(project, ref_name), expires_in: CACHE_EXPIRE_IN) do
self.matching(ref_name, protected_refs: protected_refs(project)).present?
end
@@ -39,6 +57,7 @@ class ProtectedBranch < ApplicationRecord
def self.protected_ref_cache_key(project, ref_name)
"protected_ref-#{project.cache_key}-#{Digest::SHA1.hexdigest(ref_name)}"
end
+ # End of deprecation --------------------------------------------
def self.allow_force_push?(project, ref_name)
project.protected_branches.allowing_force_push.matching(ref_name).any?
diff --git a/app/models/release.rb b/app/models/release.rb
index ee5d7bab190..5ef3ff1bc6c 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -94,7 +94,7 @@ class Release < ApplicationRecord
end
def milestone_titles
- self.milestones.order_by_dates_and_title.map {|m| m.title }.join(', ')
+ self.milestones.order_by_dates_and_title.map { |m| m.title }.join(', ')
end
def to_hook_data(action)
diff --git a/app/models/release_highlight.rb b/app/models/release_highlight.rb
index 17a9ad7db66..c2d498ecb13 100644
--- a/app/models/release_highlight.rb
+++ b/app/models/release_highlight.rb
@@ -33,7 +33,7 @@ class ReleaseHighlight
next unless include_item?(item)
begin
- item.tap {|i| i['body'] = Banzai.render(i['body'], { project: nil }) }
+ item.tap { |i| i['description'] = Banzai.render(i['description'], { project: nil }) }
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, file_path: file_path)
@@ -116,6 +116,6 @@ class ReleaseHighlight
return true unless Gitlab::CurrentSettings.current_application_settings.whats_new_variant_current_tier?
- item['packages']&.include?(current_package)
+ item['available_in']&.include?(current_package)
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 9039bdf1a20..eb8e45877f3 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -244,10 +244,10 @@ class Repository
end
end
- def add_branch(user, branch_name, ref)
+ def add_branch(user, branch_name, ref, expire_cache: true)
branch = raw_repository.add_branch(branch_name, user: user, target: ref)
- after_create_branch
+ after_create_branch(expire_cache: expire_cache)
branch
rescue Gitlab::Git::Repository::InvalidRef
@@ -337,11 +337,17 @@ class Repository
def expire_branches_cache
expire_method_caches(%i(branch_names merged_branch_names branch_count has_visible_content? has_ambiguous_refs?))
+ expire_protected_branches_cache
+
@local_branches = nil
@branch_exists_memo = nil
@branch_names_include = nil
end
+ def expire_protected_branches_cache
+ ProtectedBranches::CacheService.new(project).refresh if project # rubocop:disable CodeReuse/ServiceClass
+ end
+
def expire_statistics_caches
expire_method_caches(%i(size commit_count))
end
@@ -646,8 +652,8 @@ class Repository
return if licensee_object.name.blank?
licensee_object
- rescue Licensee::InvalidLicense => ex
- Gitlab::ErrorTracking.track_exception(ex)
+ rescue Licensee::InvalidLicense => e
+ Gitlab::ErrorTracking.track_exception(e)
nil
end
memoize_method :license
@@ -1072,9 +1078,9 @@ class Repository
) do |commit_id|
merge_request.update!(rebase_commit_sha: commit_id, merge_error: nil)
end
- rescue StandardError => error
+ rescue StandardError => e
merge_request.update!(rebase_commit_sha: nil)
- raise error
+ raise e
end
def squash(user, merge_request, message)
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 5d7b3879d75..8fea0d6d993 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -68,7 +68,11 @@ class SentNotification < ApplicationRecord
def noteable
if for_commit?
- project.commit(commit_id) rescue nil
+ begin
+ project.commit(commit_id)
+ rescue StandardError
+ nil
+ end
else
super
end
@@ -76,7 +80,11 @@ class SentNotification < ApplicationRecord
def position=(new_position)
if new_position.is_a?(String)
- new_position = Gitlab::Json.parse(new_position) rescue nil
+ new_position = begin
+ Gitlab::Json.parse(new_position)
+ rescue StandardError
+ nil
+ end
end
if new_position.is_a?(Hash)
diff --git a/app/models/serverless/domain_cluster.rb b/app/models/serverless/domain_cluster.rb
index 0d54a97370e..1effabf1c22 100644
--- a/app/models/serverless/domain_cluster.rb
+++ b/app/models/serverless/domain_cluster.rb
@@ -17,7 +17,7 @@ module Serverless
validates :pages_domain, :knative, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: ::Serverless::Domain::UUID_LENGTH },
- format: { with: HEX_REGEXP, message: 'only allows hex characters' }
+ format: { with: HEX_REGEXP, message: 'only allows hex characters' }
default_value_for(:uuid, allows_nil: false) { ::Serverless::Domain.generate_uuid }
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 47b23bbd28a..fd882633a44 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -94,8 +94,8 @@ class Snippet < ApplicationRecord
attr_spammable :content, spam_description: true
attr_encrypted :secret_token,
- key: Settings.attr_encrypted_db_key_base_truncated,
- mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ mode: :per_attribute_iv,
algorithm: 'aes-256-cbc'
class << self
diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb
index 92405a0d943..5ac159d9615 100644
--- a/app/models/snippet_repository.rb
+++ b/app/models/snippet_repository.rb
@@ -44,11 +44,11 @@ class SnippetRepository < ApplicationRecord
Gitlab::Git::CommitError,
Gitlab::Git::PreReceiveError,
Gitlab::Git::CommandError,
- ArgumentError => error
+ ArgumentError => e
- logger.error(message: "Snippet git error. Reason: #{error.message}", snippet: snippet.id)
+ logger.error(message: "Snippet git error. Reason: #{e.message}", snippet: snippet.id)
- raise commit_error_exception(error)
+ raise commit_error_exception(e)
end
def transform_file_entries(files)
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index 2643ef272d8..cc389dbe3f4 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -22,7 +22,7 @@ class SystemNoteMetadata < ApplicationRecord
designs_added designs_modified designs_removed designs_discussion_added
title time_tracking branch milestone discussion task moved cloned
opened closed merged duplicate locked unlocked outdated reviewer
- tag due_date pinned_embed cherry_pick health_status approved unapproved
+ tag due_date start_date_or_due_date pinned_embed cherry_pick health_status approved unapproved
status alert_issue_added relate unrelate new_alert_added severity
attention_requested attention_request_removed contact timeline_event
].freeze
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index 59f7d852ce6..e5c8f4ab32a 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -26,7 +26,7 @@ module Terraform
validates :project_id, :name, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: UUID_LENGTH },
- format: { with: HEX_REGEXP, message: 'only allows hex characters' }
+ format: { with: HEX_REGEXP, message: 'only allows hex characters' }
default_value_for(:uuid, allows_nil: false) { SecureRandom.hex(UUID_LENGTH / 2) }
diff --git a/app/models/todo.rb b/app/models/todo.rb
index c698783d750..d165e60e4c3 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -19,7 +19,6 @@ class Todo < ApplicationRecord
DIRECTLY_ADDRESSED = 7
MERGE_TRAIN_REMOVED = 8 # This is an EE-only feature
REVIEW_REQUESTED = 9
- ATTENTION_REQUESTED = 10
ACTION_NAMES = {
ASSIGNED => :assigned,
@@ -30,8 +29,7 @@ class Todo < ApplicationRecord
APPROVAL_REQUIRED => :approval_required,
UNMERGEABLE => :unmergeable,
DIRECTLY_ADDRESSED => :directly_addressed,
- MERGE_TRAIN_REMOVED => :merge_train_removed,
- ATTENTION_REQUESTED => :attention_requested
+ MERGE_TRAIN_REMOVED => :merge_train_removed
}.freeze
ACTIONS_MULTIPLE_ALLOWED = [Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED].freeze
@@ -195,10 +193,6 @@ class Todo < ApplicationRecord
action == REVIEW_REQUESTED
end
- def attention_requested?
- action == ATTENTION_REQUESTED
- end
-
def merge_train_removed?
action == MERGE_TRAIN_REMOVED
end
@@ -238,7 +232,11 @@ class Todo < ApplicationRecord
# override to return commits, which are not active record
def target
if for_commit?
- project.commit(commit_id) rescue nil
+ begin
+ project.commit(commit_id)
+ rescue StandardError
+ nil
+ end
else
super
end
diff --git a/app/models/u2f_registration.rb b/app/models/u2f_registration.rb
index 7c01aa7a420..ba6c1ee6af1 100644
--- a/app/models/u2f_registration.rb
+++ b/app/models/u2f_registration.rb
@@ -6,21 +6,7 @@ class U2fRegistration < ApplicationRecord
belongs_to :user
after_create :create_webauthn_registration
- after_update :update_webauthn_registration, if: :counter_changed?
-
- def create_webauthn_registration
- converter = Gitlab::Auth::U2fWebauthnConverter.new(self)
- WebauthnRegistration.create!(converter.convert)
- rescue StandardError => ex
- Gitlab::ErrorTracking.track_exception(ex, u2f_registration_id: self.id)
- end
-
- def update_webauthn_registration
- # When we update the sign count of this registration
- # we need to update the sign count of the corresponding webauthn registration
- # as well if it exists already
- WebauthnRegistration.find_by_credential_xid(webauthn_credential_xid)&.update_attribute(:counter, counter)
- end
+ after_update :update_webauthn_registration, if: :saved_change_to_counter?
def self.register(user, app_id, params, challenges)
u2f = U2F::U2F.new(app_id)
@@ -60,10 +46,22 @@ class U2fRegistration < ApplicationRecord
private
+ def create_webauthn_registration
+ converter = Gitlab::Auth::U2fWebauthnConverter.new(self)
+ WebauthnRegistration.create!(converter.convert)
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, u2f_registration_id: self.id)
+ end
+
+ def update_webauthn_registration
+ # When we update the sign count of this registration
+ # we need to update the sign count of the corresponding webauthn registration
+ # as well if it exists already
+ WebauthnRegistration.find_by_credential_xid(webauthn_credential_xid)
+ &.update_attribute(:counter, counter)
+ end
+
def webauthn_credential_xid
- # To find the corresponding webauthn registration, we use that
- # the key handle of the u2f reg corresponds to the credential xid of the webauthn reg
- # (with some base64 back and forth)
Base64.strict_encode64(Base64.urlsafe_decode64(key_handle))
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 188b27383f9..afee2d70844 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -30,6 +30,7 @@ class User < ApplicationRecord
include Gitlab::Auth::Otp::Fortinet
include RestrictedSignup
include StripAttribute
+ include EachBatch
DEFAULT_NOTIFICATION_LEVEL = :participating
@@ -69,8 +70,8 @@ class User < ApplicationRecord
default_value_for :theme_id, gitlab_config.default_theme
attr_encrypted :otp_secret,
- key: Gitlab::Application.secrets.otp_key_base,
- mode: :per_attribute_iv_and_salt,
+ key: Gitlab::Application.secrets.otp_key_base,
+ mode: :per_attribute_iv_and_salt,
insecure_mode: true,
algorithm: 'aes-256-cbc'
@@ -222,6 +223,7 @@ class User < ApplicationRecord
has_many :custom_attributes, class_name: 'UserCustomAttribute'
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'
@@ -272,10 +274,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?
@@ -447,6 +449,11 @@ class User < ApplicationRecord
scope :without_projects, -> { joins('LEFT JOIN project_authorizations ON users.id = project_authorizations.user_id').where(project_authorizations: { user_id: nil }) }
scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) }
scope :by_name, -> (names) { iwhere(name: Array(names)) }
+ scope :by_login, -> (login) do
+ return none if login.blank?
+
+ login.include?('@') ? iwhere(email: login) : iwhere(username: login)
+ end
scope :by_user_email, -> (emails) { iwhere(email: Array(emails)) }
scope :by_emails, -> (emails) { joins(:emails).where(emails: { email: Array(emails).map(&:downcase) }) }
scope :for_todos, -> (todos) { where(id: todos.select(:user_id).distinct) }
@@ -481,7 +488,6 @@ class User < ApplicationRecord
scope :order_oldest_sign_in, -> { reorder(arel_table[:current_sign_in_at].asc.nulls_last) }
scope :order_recent_last_activity, -> { reorder(arel_table[:last_activity_on].desc.nulls_last, arel_table[:id].asc) }
scope :order_oldest_last_activity, -> { reorder(arel_table[:last_activity_on].asc.nulls_first, arel_table[:id].desc) }
- scope :by_id_and_login, ->(id, login) { where(id: id).where('username = LOWER(:login) OR email = LOWER(:login)', login: login) }
scope :dormant, -> { with_state(:active).human_or_service_user.where('last_activity_on <= ?', MINIMUM_INACTIVE_DAYS.day.ago.to_date) }
scope :with_no_activity, -> { with_state(:active).human_or_service_user.where(last_activity_on: nil).where('created_at <= ?', MINIMUM_DAYS_CREATED.day.ago.to_date) }
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
@@ -691,33 +697,29 @@ class User < ApplicationRecord
scope = options[:with_private_emails] ? with_primary_or_secondary_email(query) : with_public_email(query)
scope = scope.or(search_by_name_or_username(query, use_minimum_char_limit: options[:use_minimum_char_limit]))
- if Feature.enabled?(:use_keyset_aware_user_search_query)
- order = Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'users_match_priority',
- order_expression: sanitized_order_sql.asc,
- add_to_projections: true,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'users_name',
- order_expression: arel_table[:name].asc,
- add_to_projections: true,
- nullable: :not_nullable,
- distinct: false
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'users_id',
- order_expression: arel_table[:id].asc,
- add_to_projections: true,
- nullable: :not_nullable,
- distinct: true
- )
- ])
- scope.reorder(order)
- else
- scope.reorder(sanitized_order_sql, :name)
- end
+ order = Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'users_match_priority',
+ order_expression: sanitized_order_sql.asc,
+ add_to_projections: true,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'users_name',
+ order_expression: arel_table[:name].asc,
+ add_to_projections: true,
+ nullable: :not_nullable,
+ distinct: false
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'users_id',
+ order_expression: arel_table[:id].asc,
+ add_to_projections: true,
+ nullable: :not_nullable,
+ distinct: true
+ )
+ ])
+ scope.reorder(order)
end
# Limits the result set to users _not_ in the given query/list of IDs.
@@ -768,14 +770,8 @@ class User < ApplicationRecord
true
end
- def by_login(login)
- return unless login
-
- if login.include?('@')
- unscoped.iwhere(email: login).take
- else
- unscoped.iwhere(username: login).take
- end
+ def find_by_login(login)
+ by_login(login).take
end
def find_by_username(username)
@@ -991,12 +987,12 @@ class User < ApplicationRecord
def disable_two_factor!
transaction do
update(
- otp_required_for_login: false,
- encrypted_otp_secret: nil,
- encrypted_otp_secret_iv: nil,
- encrypted_otp_secret_salt: nil,
+ otp_required_for_login: false,
+ encrypted_otp_secret: nil,
+ encrypted_otp_secret_iv: nil,
+ encrypted_otp_secret_salt: nil,
otp_grace_period_started_at: nil,
- otp_backup_codes: nil
+ otp_backup_codes: nil
)
self.u2f_registrations.destroy_all # rubocop: disable Cop/DestroyAll
self.webauthn_registrations.destroy_all # rubocop: disable Cop/DestroyAll
@@ -1663,7 +1659,14 @@ class User < ApplicationRecord
end
def forkable_namespaces
- @forkable_namespaces ||= [namespace] + manageable_groups(include_groups_with_developer_maintainer_access: true)
+ strong_memoize(:forkable_namespaces) do
+ personal_namespace = Namespace.where(id: namespace_id)
+
+ Namespace.from_union([
+ manageable_groups(include_groups_with_developer_maintainer_access: true),
+ personal_namespace
+ ])
+ end
end
def manageable_groups(include_groups_with_developer_maintainer_access: false)
@@ -1808,16 +1811,6 @@ class User < ApplicationRecord
end
end
- def attention_requested_open_merge_requests_count(force: false)
- if Feature.enabled?(:uncached_mr_attention_requests_count, self)
- MergeRequestsFinder.new(self, attention: self.username, state: 'opened', non_archived: true).execute.count
- else
- Rails.cache.fetch(attention_request_cache_key, force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
- MergeRequestsFinder.new(self, attention: self.username, state: 'opened', non_archived: true).execute.count
- end
- end
- end
-
def assigned_open_issues_count(force: false)
Rails.cache.fetch(['users', id, 'assigned_open_issues_count'], force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
IssuesFinder.new(self, assignee_id: self.id, state: 'opened', non_archived: true).execute.count
@@ -1861,11 +1854,6 @@ class User < ApplicationRecord
def invalidate_merge_request_cache_counts
Rails.cache.delete(['users', id, 'assigned_open_merge_requests_count'])
Rails.cache.delete(['users', id, 'review_requested_open_merge_requests_count'])
- invalidate_attention_requested_count
- end
-
- def invalidate_attention_requested_count
- Rails.cache.delete(attention_request_cache_key)
end
def invalidate_todos_cache_counts
@@ -1877,10 +1865,6 @@ class User < ApplicationRecord
Rails.cache.delete(['users', id, 'personal_projects_count'])
end
- def attention_request_cache_key
- ['users', id, 'attention_requested_open_merge_requests_count']
- end
-
# This is copied from Devise::Models::Lockable#valid_for_authentication?, as our auth
# flow means we don't call that automatically (and can't conveniently do so).
#
@@ -2095,6 +2079,12 @@ class User < ApplicationRecord
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)
+
+ callout_dismissed?(callout, ignore_dismissal_earlier_than)
+ end
+
# Load the current highest access by looking directly at the user's memberships
def current_highest_access_level
members.non_request.maximum(:access_level)
@@ -2126,6 +2116,11 @@ class User < ApplicationRecord
.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)
+ end
+
def can_trigger_notifications?
confirmed? && !blocked? && !ghost?
end
@@ -2160,6 +2155,10 @@ class User < ApplicationRecord
Feature.enabled?(:mr_attention_requests, self)
end
+ def account_age_in_days
+ (Date.current - created_at.to_date).to_i
+ end
+
protected
# override, from Devise::Validatable
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 7a803e8f1f6..dee976a4497 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -9,12 +9,12 @@ class UserStatus < ApplicationRecord
CLEAR_STATUS_QUICK_OPTIONS = {
'30_minutes' => 30.minutes,
- '3_hours' => 3.hours,
- '8_hours' => 8.hours,
- '1_day' => 1.day,
- '3_days' => 3.days,
- '7_days' => 7.days,
- '30_days' => 30.days
+ '3_hours' => 3.hours,
+ '8_hours' => 8.hours,
+ '1_day' => 1.day,
+ '3_days' => 3.days,
+ '7_days' => 7.days,
+ '30_days' => 30.days
}.freeze
belongs_to :user
@@ -32,6 +32,10 @@ class UserStatus < ApplicationRecord
def clear_status_after=(value)
self.clear_status_at = CLEAR_STATUS_QUICK_OPTIONS[value]&.from_now
end
+
+ def customized?
+ message.present? || emoji != UserStatus::DEFAULT_EMOJI
+ end
end
UserStatus.prepend_mod_with('UserStatus')
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
index 570e3ae9b3c..7b5c7fef7ba 100644
--- a/app/models/users/callout.rb
+++ b/app/models/users/callout.rb
@@ -55,8 +55,13 @@ module Users
preview_user_over_limit_free_plan_alert: 50, # EE-only
user_reached_limit_free_plan_alert: 51, # EE-only
submit_license_usage_data_banner: 52, # EE-only
- personal_project_limitations_banner: 53, # EE-only
- mr_experience_survey: 54
+ personal_project_limitations_banner: 53, # EE-only
+ mr_experience_survey: 54,
+ namespace_storage_limit_banner_info_threshold: 55, # EE-only
+ namespace_storage_limit_banner_warning_threshold: 56, # EE-only
+ 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
}
validates :feature_name,
diff --git a/app/models/users/group_callout.rb b/app/models/users/group_callout.rb
index 0ea7b8199aa..70498ae83e0 100644
--- a/app/models/users/group_callout.rb
+++ b/app/models/users/group_callout.rb
@@ -17,7 +17,13 @@ module Users
storage_enforcement_banner_fourth_enforcement_threshold: 6,
preview_user_over_limit_free_plan_alert: 7, # EE-only
user_reached_limit_free_plan_alert: 8, # EE-only
- free_group_limited_alert: 9 # EE-only
+ free_group_limited_alert: 9, # EE-only
+ namespace_storage_limit_banner_info_threshold: 10, # EE-only
+ namespace_storage_limit_banner_warning_threshold: 11, # EE-only
+ namespace_storage_limit_banner_alert_threshold: 12, # EE-only
+ namespace_storage_limit_banner_error_threshold: 13, # EE-only
+ usage_quota_trial_alert: 14, # EE-only
+ preview_usage_quota_free_plan_alert: 15 # EE-only
}
validates :group, presence: true
diff --git a/app/models/users/project_callout.rb b/app/models/users/project_callout.rb
new file mode 100644
index 00000000000..ddc5f8fb4de
--- /dev/null
+++ b/app/models/users/project_callout.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Users
+ class ProjectCallout < ApplicationRecord
+ include Users::Calloutable
+
+ self.table_name = 'user_project_callouts'
+
+ belongs_to :project
+
+ enum feature_name: {
+ awaiting_members_banner: 1 # EE-only
+ }
+
+ validates :project, presence: true
+ validates :feature_name,
+ presence: true,
+ uniqueness: { scope: [:user_id, :project_id] },
+ inclusion: { in: ProjectCallout.feature_names.keys }
+ end
+end
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index c9cb3b0b796..d28a73b644f 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -146,8 +146,8 @@ class Wiki
repository.create_if_not_exists(default_branch)
raise CouldNotCreateWikiError unless repository_exists?
- rescue StandardError => err
- Gitlab::ErrorTracking.track_exception(err, wiki: {
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, wiki: {
container_type: container.class.name,
container_id: container.id,
full_path: full_path,
@@ -335,7 +335,7 @@ class Wiki
end
def wiki_base_path
- web_url(only_path: true).sub(%r{/#{Wiki::HOMEPAGE}\z}, '')
+ web_url(only_path: true).sub(%r{/#{Wiki::HOMEPAGE}\z}o, '')
end
# Callbacks for synchronous processing after wiki changes.
@@ -364,9 +364,9 @@ class Wiki
Gitlab::Git::CommitError,
Gitlab::Git::PreReceiveError,
Gitlab::Git::CommandError,
- ArgumentError => error
+ ArgumentError => e
- Gitlab::ErrorTracking.log_exception(error, action: action, wiki_id: id)
+ Gitlab::ErrorTracking.log_exception(e, action: action, wiki_id: id)
false
end
diff --git a/app/models/work_item.rb b/app/models/work_item.rb
index d29df0c31fc..451359c1f85 100644
--- a/app/models/work_item.rb
+++ b/app/models/work_item.rb
@@ -12,7 +12,7 @@ class WorkItem < Issue
has_many :child_links, class_name: '::WorkItems::ParentLink', foreign_key: :work_item_parent_id
has_many :work_item_children, through: :child_links, class_name: 'WorkItem',
- foreign_key: :work_item_id, source: :work_item
+ foreign_key: :work_item_id, source: :work_item
scope :inc_relations_for_permission_check, -> { includes(:author, project: :project_feature) }
@@ -34,9 +34,22 @@ class WorkItem < Issue
private
+ override :parent_link_confidentiality
+ def parent_link_confidentiality
+ if confidential? && work_item_children.public_only.exists?
+ errors.add(:confidential, _('confidential parent can not be used if there are non-confidential children.'))
+ end
+
+ if !confidential? && work_item_parent&.confidential?
+ errors.add(:confidential, _('associated parent is confidential and can not have non-confidential children.'))
+ end
+ end
+
def record_create_action
super
Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter.track_work_item_created_action(author: author)
end
end
+
+WorkItem.prepend_mod
diff --git a/app/models/work_items/parent_link.rb b/app/models/work_items/parent_link.rb
index f5ebbfa59b8..13d6db3e08e 100644
--- a/app/models/work_items/parent_link.rb
+++ b/app/models/work_items/parent_link.rb
@@ -16,6 +16,20 @@ module WorkItems
validate :validate_parent_type
validate :validate_same_project
validate :validate_max_children
+ validate :validate_confidentiality
+
+ class << self
+ def has_public_children?(parent_id)
+ joins(:work_item).where(work_item_parent_id: parent_id, 'issues.confidential': false).exists?
+ end
+
+ def has_confidential_parent?(id)
+ link = find_by_work_item_id(id)
+ return false unless link
+
+ link.work_item_parent.confidential?
+ end
+ end
private
@@ -56,5 +70,14 @@ module WorkItems
errors.add :work_item_parent, _('parent already has maximum number of children.')
end
end
+
+ def validate_confidentiality
+ return unless work_item_parent && work_item
+
+ if work_item_parent.confidential? && !work_item.confidential?
+ errors.add :work_item, _("cannot assign a non-confidential work item to a confidential "\
+ "parent. Make the work item confidential and try again.")
+ end
+ end
end
end
diff --git a/app/models/work_items/type.rb b/app/models/work_items/type.rb
index e38d0ae153a..753fcbcb8f9 100644
--- a/app/models/work_items/type.rb
+++ b/app/models/work_items/type.rb
@@ -13,21 +13,23 @@ module WorkItems
# Base types need to exist on the DB on app startup
# This constant is used by the DB seeder
BASE_TYPES = {
- issue: { name: 'Issue', icon_name: 'issue-type-issue', enum_value: 0 },
- incident: { name: 'Incident', icon_name: 'issue-type-incident', enum_value: 1 },
- test_case: { name: 'Test Case', icon_name: 'issue-type-test-case', enum_value: 2 }, ## EE-only
+ issue: { name: 'Issue', icon_name: 'issue-type-issue', enum_value: 0 },
+ incident: { name: 'Incident', icon_name: 'issue-type-incident', enum_value: 1 },
+ test_case: { name: 'Test Case', icon_name: 'issue-type-test-case', enum_value: 2 }, ## EE-only
requirement: { name: 'Requirement', icon_name: 'issue-type-requirements', enum_value: 3 }, ## EE-only
- task: { name: 'Task', icon_name: 'issue-type-task', enum_value: 4 }
+ task: { name: 'Task', icon_name: 'issue-type-task', enum_value: 4 }
}.freeze
WIDGETS_FOR_TYPE = {
- issue: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight],
+ issue: [Widgets::Assignees, Widgets::Labels, Widgets::Description, Widgets::Hierarchy, Widgets::StartAndDueDate],
incident: [Widgets::Description, Widgets::Hierarchy],
test_case: [Widgets::Description],
requirement: [Widgets::Description],
- task: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight]
+ task: [Widgets::Assignees, Widgets::Labels, Widgets::Description, Widgets::Hierarchy, Widgets::StartAndDueDate]
}.freeze
+ WI_TYPES_WITH_CREATED_HEADER = %w[issue incident].freeze
+
cache_markdown_field :description, pipeline: :single_line
enum base_type: BASE_TYPES.transform_values { |value| value[:enum_value] }
@@ -83,3 +85,5 @@ module WorkItems
end
end
end
+
+WorkItems::Type.prepend_mod
diff --git a/app/models/work_items/widgets/labels.rb b/app/models/work_items/widgets/labels.rb
new file mode 100644
index 00000000000..4ad8319ffac
--- /dev/null
+++ b/app/models/work_items/widgets/labels.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ class Labels < Base
+ delegate :labels, to: :work_item
+ delegate :allows_scoped_labels?, to: :work_item
+ end
+ end
+end
diff --git a/app/models/work_items/widgets/start_and_due_date.rb b/app/models/work_items/widgets/start_and_due_date.rb
new file mode 100644
index 00000000000..0b828c5b5a9
--- /dev/null
+++ b/app/models/work_items/widgets/start_and_due_date.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ class StartAndDueDate < Base
+ delegate :start_date, :due_date, to: :work_item
+ end
+ end
+end
diff --git a/app/models/work_items/widgets/weight.rb b/app/models/work_items/widgets/weight.rb
deleted file mode 100644
index f589378f307..00000000000
--- a/app/models/work_items/widgets/weight.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module WorkItems
- module Widgets
- class Weight < Base
- delegate :weight, to: :work_item
- end
- end
-end
diff --git a/app/policies/ci/runner_policy.rb b/app/policies/ci/runner_policy.rb
index 6dfe9cc496b..8a99f4d1a3e 100644
--- a/app/policies/ci/runner_policy.rb
+++ b/app/policies/ci/runner_policy.rb
@@ -31,3 +31,5 @@ module Ci
rule { ~admin & locked }.prevent :assign_runner
end
end
+
+Ci::RunnerPolicy.prepend_mod_with('Ci::RunnerPolicy')
diff --git a/app/policies/deployment_policy.rb b/app/policies/deployment_policy.rb
index 1a92b735e36..70b2e864094 100644
--- a/app/policies/deployment_policy.rb
+++ b/app/policies/deployment_policy.rb
@@ -24,3 +24,5 @@ class DeploymentPolicy < BasePolicy
prevent :update_deployment
end
end
+
+DeploymentPolicy.prepend_mod_with('DeploymentPolicy')
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 50b6f4bbe15..44393539327 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -180,7 +180,8 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :read_deploy_token
enable :create_jira_connect_subscription
enable :maintainer_access
- enable :maintain_namespace
+ enable :read_upload
+ enable :destroy_upload
end
rule { owner }.policy do
diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb
index f1efcb25331..3c5e1020c8a 100644
--- a/app/policies/issuable_policy.rb
+++ b/app/policies/issuable_policy.rb
@@ -44,6 +44,10 @@ class IssuablePolicy < BasePolicy
rule { can?(:read_issue) & can?(:developer_access) }.policy do
enable :admin_incident_management_timeline_event
end
+
+ rule { can?(:reporter_access) }.policy do
+ enable :create_timelog
+ end
end
IssuablePolicy.prepend_mod_with('IssuablePolicy')
diff --git a/app/policies/namespaces/group_project_namespace_shared_policy.rb b/app/policies/namespaces/group_project_namespace_shared_policy.rb
index 1ed9f05306f..bfb1706bc5a 100644
--- a/app/policies/namespaces/group_project_namespace_shared_policy.rb
+++ b/app/policies/namespaces/group_project_namespace_shared_policy.rb
@@ -2,8 +2,20 @@
module Namespaces
class GroupProjectNamespaceSharedPolicy < ::NamespacePolicy
- # Nothing here at the moment, but as we move policies from ProjectPolicy to ProjectNamespacePolicy,
+ # As we move policies from ProjectPolicy to ProjectNamespacePolicy,
# anything common with GroupPolicy but not with UserNamespacePolicy can go in here.
# See https://gitlab.com/groups/gitlab-org/-/epics/6689
+
+ condition(:timelog_categories_enabled, score: 0, scope: :subject) do
+ Feature.enabled?(:timelog_categories, @subject)
+ end
+
+ rule { ~timelog_categories_enabled }.policy do
+ prevent :read_timelog_category
+ end
+
+ rule { can?(:reporter_access) }.policy do
+ enable :read_timelog_category
+ end
end
end
diff --git a/app/policies/namespaces/project_namespace_policy.rb b/app/policies/namespaces/project_namespace_policy.rb
index 33aadc7c411..500c325138e 100644
--- a/app/policies/namespaces/project_namespace_policy.rb
+++ b/app/policies/namespaces/project_namespace_policy.rb
@@ -2,8 +2,8 @@
module Namespaces
class ProjectNamespacePolicy < Namespaces::GroupProjectNamespaceSharedPolicy
- # For now users are not granted any permissions on project namespace
- # as it's completely hidden to them. When we start using project
- # namespaces in queries, we will have to extend this policy.
+ # TODO: once https://gitlab.com/gitlab-org/gitlab/-/issues/364277 is solved, this
+ # should not be necessary anymore, and should be replaced with `delegate(:project)`.
+ delegate(:reload_project)
end
end
diff --git a/app/policies/namespaces/user_namespace_policy.rb b/app/policies/namespaces/user_namespace_policy.rb
index 26112332003..028247497e5 100644
--- a/app/policies/namespaces/user_namespace_policy.rb
+++ b/app/policies/namespaces/user_namespace_policy.rb
@@ -11,7 +11,6 @@ module Namespaces
enable :owner_access
enable :create_projects
enable :admin_namespace
- enable :maintain_namespace
enable :read_namespace
enable :read_statistics
enable :create_jira_connect_subscription
diff --git a/app/policies/project_hook_policy.rb b/app/policies/project_hook_policy.rb
new file mode 100644
index 00000000000..c177fabb1ba
--- /dev/null
+++ b/app/policies/project_hook_policy.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class ProjectHookPolicy < ::BasePolicy
+ delegate(:project)
+
+ rule { can?(:admin_project) }.policy do
+ enable :read_web_hook
+ enable :destroy_web_hook
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 54270dc186e..f4f7275a78a 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -209,6 +209,9 @@ class ProjectPolicy < BasePolicy
analytics
operations
security_and_compliance
+ environments
+ feature_flags
+ releases
]
features.each do |f|
@@ -366,7 +369,11 @@ class ProjectPolicy < BasePolicy
prevent(:metrics_dashboard)
end
- rule { operations_disabled }.policy do
+ condition(:split_operations_visibility_permissions) do
+ ::Feature.enabled?(:split_operations_visibility_permissions, @subject)
+ end
+
+ rule { ~split_operations_visibility_permissions & operations_disabled }.policy do
prevent(*create_read_update_admin_destroy(:feature_flag))
prevent(*create_read_update_admin_destroy(:environment))
prevent(*create_read_update_admin_destroy(:sentry_issue))
@@ -379,6 +386,21 @@ class ProjectPolicy < BasePolicy
prevent(:read_prometheus)
end
+ rule { split_operations_visibility_permissions & environments_disabled }.policy do
+ prevent(*create_read_update_admin_destroy(:environment))
+ prevent(*create_read_update_admin_destroy(:deployment))
+ end
+
+ rule { split_operations_visibility_permissions & feature_flags_disabled }.policy do
+ prevent(*create_read_update_admin_destroy(:feature_flag))
+ prevent(:admin_feature_flags_user_lists)
+ prevent(:admin_feature_flags_client)
+ end
+
+ rule { split_operations_visibility_permissions & releases_disabled }.policy do
+ prevent(*create_read_update_admin_destroy(:release))
+ end
+
rule { can?(:metrics_dashboard) }.policy do
enable :read_prometheus
enable :read_deployment
@@ -470,6 +492,7 @@ class ProjectPolicy < BasePolicy
enable :admin_pipeline
enable :admin_environment
enable :admin_deployment
+ enable :destroy_deployment
enable :admin_pages
enable :read_pages
enable :update_pages
@@ -497,6 +520,8 @@ class ProjectPolicy < BasePolicy
enable :admin_project_google_cloud
enable :admin_secure_files
enable :read_web_hooks
+ enable :read_upload
+ enable :destroy_upload
end
rule { public_project & metrics_dashboard_allowed }.policy do
diff --git a/app/policies/system_hook_policy.rb b/app/policies/system_hook_policy.rb
new file mode 100644
index 00000000000..ec28d39a5fa
--- /dev/null
+++ b/app/policies/system_hook_policy.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class SystemHookPolicy < ::BasePolicy
+ rule { admin }.policy do
+ enable :read_web_hook
+ enable :destroy_web_hook
+ end
+end
diff --git a/app/policies/time_tracking/timelog_category_policy.rb b/app/policies/time_tracking/timelog_category_policy.rb
new file mode 100644
index 00000000000..89161cdacfb
--- /dev/null
+++ b/app/policies/time_tracking/timelog_category_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module TimeTracking
+ class TimelogCategoryPolicy < BasePolicy
+ delegate { @subject.namespace }
+ end
+end
diff --git a/app/policies/upload_policy.rb b/app/policies/upload_policy.rb
new file mode 100644
index 00000000000..c7fde5d9df4
--- /dev/null
+++ b/app/policies/upload_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class UploadPolicy < BasePolicy # rubocop:disable Gitlab/NamespacedClass
+ delegate { @subject.model }
+end
diff --git a/app/policies/work_item_policy.rb b/app/policies/work_item_policy.rb
index 2f3561f1135..1ccc152bc6b 100644
--- a/app/policies/work_item_policy.rb
+++ b/app/policies/work_item_policy.rb
@@ -3,9 +3,12 @@
class WorkItemPolicy < IssuePolicy
condition(:is_member_and_author) { is_project_member? & is_author? }
+ rule { can?(:admin_issue) }.enable :admin_work_item
+
rule { can?(:destroy_issue) | is_member_and_author }.enable :delete_work_item
rule { can?(:update_issue) }.enable :update_work_item
+ rule { can?(:set_issue_metadata) }.enable :set_work_item_metadata
rule { can?(:read_issue) }.enable :read_work_item
# because IssuePolicy delegates to ProjectPolicy and
diff --git a/app/presenters/analytics/cycle_analytics/stage_presenter.rb b/app/presenters/analytics/cycle_analytics/stage_presenter.rb
index 7b295b814bc..d023b0c5d55 100644
--- a/app/presenters/analytics/cycle_analytics/stage_presenter.rb
+++ b/app/presenters/analytics/cycle_analytics/stage_presenter.rb
@@ -28,7 +28,7 @@ module Analytics
description: _('Time before an issue gets scheduled')
},
plan: {
- title: s_('CycleAnalyticsStage|Plan'),
+ title: s_('CycleAnalyticsStage|Plan'),
description: _('Time before an issue starts implementation')
},
code: {
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 015dfc16df0..71a05ef2c72 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -33,7 +33,8 @@ module Ci
end
def runner_variables
- variables.sort_and_expand_all(keep_undefined: true).to_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
end
def refspecs
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index efab1e84923..417a2f9c51f 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -191,18 +191,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
def mergeable_discussions_state
- if Feature.enabled?(:change_response_code_merge_status, project)
- merge_request.mergeable_discussions_state?
- else
- # This avoids calling MergeRequest#mergeable_discussions_state without
- # considering the state of the MR first. If a MR isn't mergeable, we can
- # safely short-circuit it.
- if merge_request.mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
- merge_request.mergeable_discussions_state?
- else
- false
- end
- end
+ merge_request.mergeable_discussions_state?
end
delegator_override :subscribed?
diff --git a/app/presenters/project_hook_presenter.rb b/app/presenters/project_hook_presenter.rb
index a696e9fd0ec..76a3a187924 100644
--- a/app/presenters/project_hook_presenter.rb
+++ b/app/presenters/project_hook_presenter.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class ProjectHookPresenter < Gitlab::View::Presenter::Delegated
- presents ::ProjectHook, as: :project_hook
+ presents ::ProjectHook
def logs_details_path(log)
project_hook_hook_log_path(project, self, log)
diff --git a/app/presenters/project_member_presenter.rb b/app/presenters/project_member_presenter.rb
index 91d3ae96877..da24972775a 100644
--- a/app/presenters/project_member_presenter.rb
+++ b/app/presenters/project_member_presenter.rb
@@ -3,6 +3,24 @@
class ProjectMemberPresenter < MemberPresenter
presents ::ProjectMember
+ def access_level_roles
+ ProjectMember.permissible_access_level_roles(current_user, source)
+ end
+
+ def can_remove?
+ # If this user is attempting to manage an Owner member and doesn't have permission, do not allow
+ return can_manage_owners? if member.owner?
+
+ super
+ end
+
+ def can_update?
+ # If this user is attempting to manage an Owner member and doesn't have permission, do not allow
+ return can_manage_owners? if member.owner?
+
+ super
+ end
+
private
def admin_member_permission
@@ -16,6 +34,10 @@ class ProjectMemberPresenter < MemberPresenter
def destroy_member_permission
:destroy_project_member
end
+
+ def can_manage_owners?
+ can?(current_user, :manage_owners, source)
+ end
end
ProjectMemberPresenter.prepend_mod_with('ProjectMemberPresenter')
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 84aec19cba0..209f016dc6b 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -437,9 +437,9 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
project_new_blob_path(
project,
default_branch_or_main,
- file_name: file_name,
+ file_name: file_name,
commit_message: commit_message,
- branch_name: branch_name,
+ branch_name: branch_name,
**additional_params
)
end
diff --git a/app/presenters/service_hook_presenter.rb b/app/presenters/service_hook_presenter.rb
index b34679c85cf..7ec3d7c5b5c 100644
--- a/app/presenters/service_hook_presenter.rb
+++ b/app/presenters/service_hook_presenter.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class ServiceHookPresenter < Gitlab::View::Presenter::Delegated
- presents ::ServiceHook, as: :service_hook
+ presents ::ServiceHook
def logs_details_path(log)
project_settings_integration_hook_log_path(integration.project, integration, log)
diff --git a/app/presenters/web_hook_log_presenter.rb b/app/presenters/web_hook_log_presenter.rb
index a5166589073..30941076913 100644
--- a/app/presenters/web_hook_log_presenter.rb
+++ b/app/presenters/web_hook_log_presenter.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class WebHookLogPresenter < Gitlab::View::Presenter::Delegated
- presents ::WebHookLog, as: :web_hook_log
+ presents ::WebHookLog
def details_path
web_hook.present.logs_details_path(self)
diff --git a/app/serializers/concerns/user_status_tooltip.rb b/app/serializers/concerns/user_status_tooltip.rb
index ca2854224a7..38b3c16dd2a 100644
--- a/app/serializers/concerns/user_status_tooltip.rb
+++ b/app/serializers/concerns/user_status_tooltip.rb
@@ -13,7 +13,7 @@ module UserStatusTooltip
end
expose :show_status do |user|
- status_loaded? && show_status_emoji?(user.status)
+ status_loaded? && !!user.status&.customized?
end
expose :availability, if: -> (*) { status_loaded? } do |user|
diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb
index 3f236fa55df..6363d6276a7 100644
--- a/app/serializers/environment_serializer.rb
+++ b/app/serializers/environment_serializer.rb
@@ -34,8 +34,8 @@ class EnvironmentSerializer < BaseSerializer
# rubocop: disable CodeReuse/ActiveRecord
def itemize(resource)
items = resource.order('folder ASC')
- .group('COALESCE(environment_type, name)')
- .select('COALESCE(environment_type, name) AS folder',
+ .group('COALESCE(environment_type, id::text)', 'COALESCE(environment_type, name)')
+ .select('COALESCE(environment_type, id::text), COALESCE(environment_type, name) AS folder',
'COUNT(*) AS size', 'MAX(id) AS last_id')
# It makes a difference when you call `paginate` method, because
@@ -54,11 +54,7 @@ class EnvironmentSerializer < BaseSerializer
def batch_load(resource)
temp_deployment_associations = deployment_associations
- resource = resource.preload(environment_associations.except(:last_deployment, :upcoming_deployment))
-
- if ::Feature.enabled?(:batch_load_environment_last_deployment_group, resource.first&.project)
- temp_deployment_associations[:deployable][:pipeline][:latest_successful_builds] = []
- end
+ resource = resource.preload(environment_associations)
Preloaders::Environments::DeploymentPreloader.new(resource)
.execute_with_union(:last_deployment, temp_deployment_associations)
@@ -72,18 +68,14 @@ class EnvironmentSerializer < BaseSerializer
environment.last_deployment&.commit&.try(:lazy_author)
environment.upcoming_deployment&.commit&.try(:lazy_author)
- if ::Feature.enabled?(:batch_load_environment_last_deployment_group, environment.project)
- # Batch loading last_deployment_group which is called later by environment.stop_actions
- environment.last_deployment_group
- end
+ # Batch loading last_deployment_group which is called later by environment.stop_actions
+ environment.last_deployment_group
end
end
end
def environment_associations
{
- last_deployment: deployment_associations,
- upcoming_deployment: deployment_associations,
project: project_associations
}
end
@@ -101,7 +93,8 @@ class EnvironmentSerializer < BaseSerializer
metadata: [],
pipeline: {
manual_actions: [:metadata, :deployment],
- scheduled_actions: [:metadata]
+ scheduled_actions: [:metadata],
+ latest_successful_builds: []
},
project: project_associations,
deployment: []
diff --git a/app/serializers/group_access_token_entity.rb b/app/serializers/group_access_token_entity.rb
new file mode 100644
index 00000000000..e832eef1188
--- /dev/null
+++ b/app/serializers/group_access_token_entity.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class GroupAccessTokenEntity < API::Entities::PersonalAccessToken
+ include Gitlab::Routing
+
+ expose :revoke_path do |token, options|
+ group = options.fetch(:group)
+
+ next unless group
+
+ revoke_group_settings_access_token_path(
+ id: token,
+ group_id: group.path)
+ end
+
+ expose :access_level do |token, options|
+ group = options.fetch(:group)
+
+ next unless group
+ next unless token.user
+
+ group.member(token.user)&.access_level
+ end
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/group_access_token_serializer.rb b/app/serializers/group_access_token_serializer.rb
new file mode 100644
index 00000000000..55f6de77844
--- /dev/null
+++ b/app/serializers/group_access_token_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class GroupAccessTokenSerializer < BaseSerializer
+ entity GroupAccessTokenEntity
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/integrations/project_entity.rb b/app/serializers/integrations/project_entity.rb
index ee28c7c19c1..c091133eb39 100644
--- a/app/serializers/integrations/project_entity.rb
+++ b/app/serializers/integrations/project_entity.rb
@@ -4,6 +4,7 @@ module Integrations
class ProjectEntity < Grape::Entity
include RequestAwareEntity
+ expose :id
expose :avatar_url
expose :full_name
expose :name
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index ea43ed87d22..7ff75927fcd 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -47,6 +47,10 @@ class IssueEntity < IssuableEntity
can?(request.current_user, :update_issue, issue)
end
+ expose :can_set_issue_metadata do |issue|
+ can?(request.current_user, :set_issue_metadata, issue)
+ end
+
expose :can_award_emoji do |issue|
can?(request.current_user, :award_emoji, issue)
end
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index fc1534a88aa..40bb905c5c9 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -33,18 +33,7 @@ class MergeRequestPollWidgetEntity < Grape::Entity
# Booleans
expose :mergeable_discussions_state?, as: :mergeable_discussions_state do |merge_request|
- if Feature.enabled?(:change_response_code_merge_status, merge_request.project)
- merge_request.mergeable_discussions_state?
- else
- # This avoids calling MergeRequest#mergeable_discussions_state without
- # considering the state of the MR first. If a MR isn't mergeable, we can
- # safely short-circuit it.
- if merge_request.mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
- merge_request.mergeable_discussions_state?
- else
- false
- end
- end
+ merge_request.mergeable_discussions_state?
end
expose :project_archived do |merge_request|
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index 12c573d1a13..2e875af6531 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -20,10 +20,6 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
find_reviewer_or_assignee(user, options)&.reviewed?
end
- expose :attention_requested, if: ->(_, options) { options[:merge_request].present? && options[:merge_request].allows_reviewers? && request.current_user&.mr_attention_requests_enabled? } do |user, options|
- find_reviewer_or_assignee(user, options)&.attention_requested?
- end
-
expose :approved, if: satisfies(:present?) do |user, options|
# This approach is preferred over MergeRequest#approved_by? since this
# makes one query per merge request, whereas #approved_by? makes one per user
diff --git a/app/serializers/personal_access_token_entity.rb b/app/serializers/personal_access_token_entity.rb
new file mode 100644
index 00000000000..acd06fecd12
--- /dev/null
+++ b/app/serializers/personal_access_token_entity.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class PersonalAccessTokenEntity < API::Entities::PersonalAccessToken
+ include Gitlab::Routing
+
+ expose :revoke_path do |token, options|
+ revoke_profile_personal_access_token_path(token)
+ end
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/personal_access_token_serializer.rb b/app/serializers/personal_access_token_serializer.rb
new file mode 100644
index 00000000000..0a59fa117f9
--- /dev/null
+++ b/app/serializers/personal_access_token_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class PersonalAccessTokenSerializer < BaseSerializer
+ entity PersonalAccessTokenEntity
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/project_access_token_entity.rb b/app/serializers/project_access_token_entity.rb
new file mode 100644
index 00000000000..b317057c952
--- /dev/null
+++ b/app/serializers/project_access_token_entity.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class ProjectAccessTokenEntity < API::Entities::PersonalAccessToken
+ include Gitlab::Routing
+
+ expose :revoke_path do |token, options|
+ project = options.fetch(:project)
+
+ next unless project
+
+ revoke_namespace_project_settings_access_token_path(
+ id: token,
+ namespace_id: project.namespace.path,
+ project_id: project.path)
+ end
+
+ expose :access_level do |token, options|
+ project = options.fetch(:project)
+
+ next unless project
+ next unless token.user
+
+ project.member(token.user)&.access_level
+ end
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/project_access_token_serializer.rb b/app/serializers/project_access_token_serializer.rb
new file mode 100644
index 00000000000..97db088cf64
--- /dev/null
+++ b/app/serializers/project_access_token_serializer.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class ProjectAccessTokenSerializer < BaseSerializer
+ entity ProjectAccessTokenEntity
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/serializers/rollout_status_entity.rb b/app/serializers/rollout_status_entity.rb
index 9f4c844859b..f432fe98289 100644
--- a/app/serializers/rollout_status_entity.rb
+++ b/app/serializers/rollout_status_entity.rb
@@ -14,5 +14,5 @@ class RolloutStatusEntity < Grape::Entity
expose :completion, if: -> (rollout_status, _) { rollout_status.found? }
expose :complete?, as: :is_completed, if: -> (rollout_status, _) { rollout_status.found? }
expose :canary_ingress, using: RolloutStatuses::IngressEntity, expose_nil: false,
- if: -> (rollout_status, _) { rollout_status.found? && rollout_status.canary_ingress_exists? }
+ if: -> (rollout_status, _) { rollout_status.found? && rollout_status.canary_ingress_exists? }
end
diff --git a/app/services/audit_events/build_service.rb b/app/services/audit_events/build_service.rb
new file mode 100644
index 00000000000..f5322fa5ff4
--- /dev/null
+++ b/app/services/audit_events/build_service.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module AuditEvents
+ class BuildService
+ # Handle missing attributes
+ MissingAttributeError = Class.new(StandardError)
+
+ # @raise [MissingAttributeError] when required attributes are blank
+ #
+ # @return [BuildService]
+ def initialize(
+ author:, scope:, target:, message:,
+ created_at: DateTime.current, additional_details: {}, ip_address: nil, target_details: nil)
+ raise MissingAttributeError if missing_attribute?(author, scope, target, message)
+
+ @author = build_author(author)
+ @scope = scope
+ @target = build_target(target)
+ @ip_address = ip_address || build_ip_address
+ @message = build_message(message)
+ @created_at = created_at
+ @additional_details = additional_details
+ @target_details = target_details
+ end
+
+ # Create an instance of AuditEvent
+ #
+ # @return [AuditEvent]
+ def execute
+ AuditEvent.new(payload)
+ end
+
+ private
+
+ def missing_attribute?(author, scope, target, message)
+ author.blank? || scope.blank? || target.blank? || message.blank?
+ end
+
+ def payload
+ base_payload.merge(details: base_details_payload)
+ end
+
+ def base_payload
+ {
+ author_id: @author.id,
+ author_name: @author.name,
+ entity_id: @scope.id,
+ entity_type: @scope.class.name,
+ created_at: @created_at
+ }
+ end
+
+ def base_details_payload
+ @additional_details.merge({
+ author_name: @author.name,
+ author_class: @author.class.name,
+ target_id: @target.id,
+ target_type: @target.type,
+ target_details: @target_details || @target.details,
+ custom_message: @message
+ })
+ end
+
+ def build_author(author)
+ author.id = -2 if author.instance_of? DeployToken
+ author.id = -3 if author.instance_of? DeployKey
+
+ author
+ end
+
+ def build_target(target)
+ return target if target.is_a? ::Gitlab::Audit::NullTarget
+
+ ::Gitlab::Audit::Target.new(target)
+ end
+
+ def build_message(message)
+ message
+ end
+
+ def build_ip_address
+ Gitlab::RequestContext.instance.client_ip || @author.current_sign_in_ip
+ end
+ end
+end
+
+AuditEvents::BuildService.prepend_mod_with('AuditEvents::BuildService')
diff --git a/app/services/authorized_project_update/project_recalculate_service.rb b/app/services/authorized_project_update/project_recalculate_service.rb
index 17ba48cffcd..e0b8158417c 100644
--- a/app/services/authorized_project_update/project_recalculate_service.rb
+++ b/app/services/authorized_project_update/project_recalculate_service.rb
@@ -47,7 +47,7 @@ module AuthorizedProjectUpdate
def user_ids_to_remove
strong_memoize(:user_ids_to_remove) do
(current_authorizations - fresh_authorizations)
- .map {|user_id, _| user_id }
+ .map { |user_id, _| user_id }
end
end
diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb
index 9e49bd86ec0..1660ddb934f 100644
--- a/app/services/auto_merge/base_service.rb
+++ b/app/services/auto_merge/base_service.rb
@@ -59,6 +59,7 @@ module AutoMerge
!merge_request.broken? &&
!merge_request.draft? &&
merge_request.mergeable_discussions_state? &&
+ !merge_request.merge_blocked_by_other_mrs? &&
yield
end
end
diff --git a/app/services/base_count_service.rb b/app/services/base_count_service.rb
index ff1949ce4dd..eff3eb33c71 100644
--- a/app/services/base_count_service.rb
+++ b/app/services/base_count_service.rb
@@ -45,7 +45,7 @@ class BaseCountService
end
def update_cache_for_key(key, &block)
- Rails.cache.write(key, block_given? ? yield : uncached_count, raw: raw?)
+ Rails.cache.write(key, block ? yield : uncached_count, raw: raw?)
end
end
diff --git a/app/services/boards/destroy_service.rb b/app/services/boards/destroy_service.rb
index 0b1cd61b119..ceda005044e 100644
--- a/app/services/boards/destroy_service.rb
+++ b/app/services/boards/destroy_service.rb
@@ -3,10 +3,6 @@
module Boards
class DestroyService < Boards::BaseService
def execute(board)
- if boards.size == 1
- return ServiceResponse.error(message: "The board could not be deleted, because the parent doesn't have any other boards.")
- end
-
board.destroy!
ServiceResponse.success
diff --git a/app/services/boards/lists/move_service.rb b/app/services/boards/lists/move_service.rb
index 93f81837d1a..4bb7b4dbc6d 100644
--- a/app/services/boards/lists/move_service.rb
+++ b/app/services/boards/lists/move_service.rb
@@ -23,7 +23,7 @@ module Boards
def valid_move?
new_position.present? && new_position != old_position &&
- new_position >= 0 && new_position < board.lists.movable.size
+ new_position >= 0 && new_position <= board.lists.movable.last.position
end
def reorder_intermediate_lists
diff --git a/app/services/branches/create_service.rb b/app/services/branches/create_service.rb
index 7300b31e3b3..5cbd587e546 100644
--- a/app/services/branches/create_service.rb
+++ b/app/services/branches/create_service.rb
@@ -2,35 +2,91 @@
module Branches
class CreateService < BaseService
+ def initialize(project, user = nil, params = {})
+ super(project, user, params)
+
+ @errors = []
+ end
+
def execute(branch_name, ref, create_default_branch_if_empty: true)
create_default_branch if create_default_branch_if_empty && project.empty_repo?
- result = ::Branches::ValidateNewService.new(project).execute(branch_name)
+ result = branch_validation_service.execute(branch_name)
return result if result[:status] == :error
- begin
- new_branch = repository.add_branch(current_user, branch_name, ref)
- rescue Gitlab::Git::CommandError => e
- return error("Failed to create branch '#{branch_name}': #{e}")
+ create_branch(branch_name, ref)
+ end
+
+ def bulk_create(branches)
+ reset_errors
+
+ created_branches =
+ branches
+ .then { |branches| only_valid_branches(branches) }
+ .then { |branches| create_branches(branches) }
+ .then { |branches| expire_branches_cache(branches) }
+
+ return error(errors) if errors.present?
+
+ success(branches: created_branches)
+ end
+
+ private
+
+ attr_reader :errors
+
+ def reset_errors
+ @errors = []
+ end
+
+ def only_valid_branches(branches)
+ branches.select do |branch_name, _ref|
+ result = branch_validation_service.execute(branch_name)
+
+ if result[:status] == :error
+ errors << result[:message]
+ next
+ end
+
+ true
end
+ end
+
+ def create_branches(branches)
+ branches.filter_map do |branch_name, ref|
+ result = create_branch(branch_name, ref, expire_cache: false)
+
+ if result[:status] == :error
+ errors << result[:message]
+ next
+ end
+
+ result[:branch]
+ end
+ end
+
+ def expire_branches_cache(branches)
+ repository.expire_branches_cache if branches.present?
+
+ branches
+ end
+
+ def create_branch(branch_name, ref, expire_cache: true)
+ new_branch = repository.add_branch(current_user, branch_name, ref, expire_cache: expire_cache)
if new_branch
- success(new_branch)
+ success(branch: new_branch)
else
error("Failed to create branch '#{branch_name}': invalid reference name '#{ref}'")
end
+ rescue Gitlab::Git::CommandError => e
+ error("Failed to create branch '#{branch_name}': #{e}")
rescue Gitlab::Git::PreReceiveError => e
Gitlab::ErrorTracking.log_exception(e, pre_receive_message: e.raw_message, branch_name: branch_name, ref: ref)
error(e.message)
end
- def success(branch)
- super().merge(branch: branch)
- end
-
- private
-
def create_default_branch
project.repository.create_file(
current_user,
@@ -40,5 +96,9 @@ module Branches
branch_name: project.default_branch_or_main
)
end
+
+ def branch_validation_service
+ @branch_validation_service ||= ::Branches::ValidateNewService.new(project)
+ end
end
end
diff --git a/app/services/bulk_imports/create_service.rb b/app/services/bulk_imports/create_service.rb
index cbf2b34b33c..31e1a822e78 100644
--- a/app/services/bulk_imports/create_service.rb
+++ b/app/services/bulk_imports/create_service.rb
@@ -64,7 +64,7 @@ module BulkImports
bulk_import: bulk_import,
source_type: entity[:source_type],
source_full_path: entity[:source_full_path],
- destination_name: entity[:destination_name],
+ destination_slug: entity[:destination_slug],
destination_namespace: entity[:destination_namespace]
)
end
diff --git a/app/services/bulk_imports/file_download_service.rb b/app/services/bulk_imports/file_download_service.rb
index 8d6ba54cd50..a2c8ba5b1cd 100644
--- a/app/services/bulk_imports/file_download_service.rb
+++ b/app/services/bulk_imports/file_download_service.rb
@@ -55,12 +55,17 @@ module BulkImports
bytes_downloaded = 0
http_client.stream(relative_url) do |chunk|
+ next if bytes_downloaded == 0 && [301, 302, 303, 307, 308].include?(chunk.code)
+
bytes_downloaded += chunk.size
validate_size!(bytes_downloaded)
- raise(ServiceError, "File download error #{chunk.code}") unless chunk.code == 200
- file.write(chunk)
+ if chunk.code == 200
+ file.write(chunk)
+ else
+ raise(ServiceError, "File download error #{chunk.code}")
+ end
end
end
rescue StandardError => e
diff --git a/app/services/chat_names/authorize_user_service.rb b/app/services/chat_names/authorize_user_service.rb
index f7780488923..6c28a1cea7e 100644
--- a/app/services/chat_names/authorize_user_service.rb
+++ b/app/services/chat_names/authorize_user_service.rb
@@ -4,8 +4,8 @@ module ChatNames
class AuthorizeUserService
include Gitlab::Routing
- def initialize(service, params)
- @service = service
+ def initialize(integration, params)
+ @integration = integration
@params = params
end
@@ -29,11 +29,11 @@ module ChatNames
def chat_name_params
{
- service_id: @service.id,
- team_id: @params[:team_id],
+ integration_id: @integration.id,
+ team_id: @params[:team_id],
team_domain: @params[:team_domain],
- chat_id: @params[:user_id],
- chat_name: @params[:user_name]
+ chat_id: @params[:user_id],
+ chat_name: @params[:user_name]
}
end
end
diff --git a/app/services/ci/archive_trace_service.rb b/app/services/ci/archive_trace_service.rb
index 7b1d2207460..9705a236d98 100644
--- a/app/services/ci/archive_trace_service.rb
+++ b/app/services/ci/archive_trace_service.rb
@@ -62,8 +62,8 @@ module Ci
failed_archive_counter.increment
Sidekiq.logger.warn(class: worker_name,
- message: "Failed to archive trace. message: #{error.message}.",
- job_id: job.id)
+ message: "Failed to archive trace. message: #{error.message}.",
+ job_id: job.id)
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(error,
diff --git a/app/services/ci/deployments/destroy_service.rb b/app/services/ci/deployments/destroy_service.rb
new file mode 100644
index 00000000000..ac51fa55537
--- /dev/null
+++ b/app/services/ci/deployments/destroy_service.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Ci
+ module Deployments
+ class DestroyService < BaseService
+ def execute(deployment)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_deployment, deployment)
+
+ return ServiceResponse.error(message: 'Cannot destroy running deployment') if deployment&.running?
+ return ServiceResponse.error(message: 'Deployment currently deployed to environment') if deployment&.last?
+
+ project.destroy_deployment_by_id(deployment)
+
+ ServiceResponse.success(message: 'Deployment destroyed')
+ end
+ end
+ end
+end
diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb
index d85e52e1312..1c563396162 100644
--- a/app/services/ci/destroy_pipeline_service.rb
+++ b/app/services/ci/destroy_pipeline_service.rb
@@ -7,7 +7,7 @@ module Ci
Ci::ExpirePipelineCacheService.new.execute(pipeline, delete: true)
- pipeline.cancel_running if pipeline.cancelable?
+ pipeline.cancel_running(cascade_to_children: true, execute_async: false) if pipeline.cancelable?
# The pipeline, the builds, job and pipeline artifacts all get destroyed here.
# Ci::Pipeline#destroy triggers fast destroy on job_artifacts and
diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb
index 05f8e804c67..af56eb221d5 100644
--- a/app/services/ci/job_artifacts/create_service.rb
+++ b/app/services/ci/job_artifacts/create_service.rb
@@ -126,6 +126,8 @@ module Ci
job.update_column(:artifacts_expire_at, artifact.expire_at)
end
+ Gitlab::Ci::Artifacts::Logger.log_created(artifact)
+
success(artifact: artifact)
rescue ActiveRecord::RecordNotUnique => error
track_exception(error, params)
diff --git a/app/services/ci/job_artifacts/destroy_batch_service.rb b/app/services/ci/job_artifacts/destroy_batch_service.rb
index 9d6b413ce59..54ec2c671c6 100644
--- a/app/services/ci/job_artifacts/destroy_batch_service.rb
+++ b/app/services/ci/job_artifacts/destroy_batch_service.rb
@@ -53,8 +53,10 @@ module Ci
update_project_statistics! if update_stats
increment_monitoring_statistics(artifacts_count, artifacts_bytes)
+ Gitlab::Ci::Artifacts::Logger.log_deleted(@job_artifacts, 'Ci::JobArtifacts::DestroyBatchService#execute')
+
success(destroyed_artifacts_count: artifacts_count,
- statistics_updates: affected_project_statistics)
+ statistics_updates: affected_project_statistics)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/ci/list_config_variables_service.rb b/app/services/ci/list_config_variables_service.rb
index 88dac514bb9..c791a89b804 100644
--- a/app/services/ci/list_config_variables_service.rb
+++ b/app/services/ci/list_config_variables_service.rb
@@ -26,8 +26,8 @@ module Ci
return {} unless config
result = Gitlab::Ci::YamlProcessor.new(config, project: project,
- user: current_user,
- sha: sha).execute
+ user: current_user,
+ sha: sha).execute
result.valid? ? result.variables_with_data : {}
end
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index 40e2cd82b4f..fd13ed245cf 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)
end
end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 8969b95b81f..b357855db12 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -4,6 +4,8 @@ module Ci
# This class responsible for assigning
# proper pending build to runner on runner API request
class RegisterJobService
+ include ::Gitlab::Ci::Artifacts::Logger
+
attr_reader :runner, :metrics
TEMPORARY_LOCK_TIMEOUT = 3.seconds
@@ -220,10 +222,26 @@ module Ci
# We need to use the presenter here because Gitaly calls in the presenter
# may fail, and we need to ensure the response has been generated.
presented_build = ::Ci::BuildRunnerPresenter.new(build) # rubocop:disable CodeReuse/Presenter
+
+ log_artifacts_context(build)
+ log_build_dependencies_size(presented_build)
+
build_json = ::API::Entities::Ci::JobRequest::Response.new(presented_build).to_json
Result.new(build, build_json, true)
end
+ def log_build_dependencies_size(presented_build)
+ return unless ::Feature.enabled?(:ci_build_dependencies_artifacts_logger, type: :ops)
+
+ presented_build.all_dependencies.then do |dependencies|
+ size = dependencies.sum do |build|
+ build.available_artifacts? ? build.artifacts_file.size : 0
+ end
+
+ log_build_dependencies(size: size, count: dependencies.size) if size > 0
+ end
+ end
+
def assign_runner!(build, params)
build.runner_id = runner.id
build.runner_session_attributes = params[:session] if params[:session].present?
diff --git a/app/services/ci/retry_job_service.rb b/app/services/ci/retry_job_service.rb
index e0ced3d0197..25bda8a6380 100644
--- a/app/services/ci/retry_job_service.rb
+++ b/app/services/ci/retry_job_service.rb
@@ -4,10 +4,10 @@ module Ci
class RetryJobService < ::BaseService
include Gitlab::Utils::StrongMemoize
- def execute(job)
+ def execute(job, variables: [])
if job.retryable?
job.ensure_scheduling_type!
- new_job = retry_job(job)
+ new_job = retry_job(job, variables: variables)
ServiceResponse.success(payload: { job: new_job })
else
@@ -19,7 +19,7 @@ module Ci
end
# rubocop: disable CodeReuse/ActiveRecord
- def clone!(job)
+ def clone!(job, variables: [])
# Cloning a job requires a strict type check to ensure
# the attributes being used for the clone are taken straight
# from the model and not overridden by other abstractions.
@@ -27,7 +27,7 @@ module Ci
check_access!(job)
- new_job = job.clone(current_user: current_user)
+ new_job = job.clone(current_user: current_user, new_job_variables_attributes: variables)
new_job.run_after_commit do
::Ci::CopyCrossDatabaseAssociationsService.new.execute(job, new_job)
@@ -55,8 +55,8 @@ module Ci
def check_assignable_runners!(job); end
- def retry_job(job)
- clone!(job).tap do |new_job|
+ def retry_job(job, variables: [])
+ clone!(job, variables: variables).tap do |new_job|
check_assignable_runners!(new_job) if new_job.is_a?(Ci::Build)
next if new_job.failed?
diff --git a/app/services/ci/runners/assign_runner_service.rb b/app/services/ci/runners/assign_runner_service.rb
index 886cd3a4e44..290f945cc72 100644
--- a/app/services/ci/runners/assign_runner_service.rb
+++ b/app/services/ci/runners/assign_runner_service.rb
@@ -13,9 +13,15 @@ module Ci
end
def execute
- return false unless @user.present? && @user.can?(:assign_runner, @runner)
+ unless @user.present? && @user.can?(:assign_runner, @runner)
+ return ServiceResponse.error(message: 'user not allowed to assign runner', http_status: :forbidden)
+ end
- @runner.assign_to(@project, @user)
+ if @runner.assign_to(@project, @user)
+ ServiceResponse.success
+ else
+ ServiceResponse.error(message: 'failed to assign runner')
+ end
end
private
diff --git a/app/services/ci/runners/bulk_delete_runners_service.rb b/app/services/ci/runners/bulk_delete_runners_service.rb
new file mode 100644
index 00000000000..ce07aa541c2
--- /dev/null
+++ b/app/services/ci/runners/bulk_delete_runners_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Ci
+ module Runners
+ class BulkDeleteRunnersService
+ attr_reader :runners
+
+ RUNNER_LIMIT = 50
+
+ # @param runners [Array<Ci::Runner, Integer>] the runners to unregister/destroy
+ def initialize(runners:)
+ @runners = runners
+ end
+
+ def execute
+ if @runners
+ # Delete a few runners immediately
+ return ServiceResponse.success(payload: delete_runners)
+ end
+
+ ServiceResponse.success(payload: { deleted_count: 0, deleted_ids: [] })
+ end
+
+ private
+
+ def delete_runners
+ # rubocop:disable CodeReuse/ActiveRecord
+ runners_to_be_deleted = Ci::Runner.where(id: @runners).limit(RUNNER_LIMIT)
+ # rubocop:enable CodeReuse/ActiveRecord
+ deleted_ids = runners_to_be_deleted.destroy_all.map(&:id) # rubocop: disable Cop/DestroyAll
+
+ { deleted_count: deleted_ids.count, deleted_ids: deleted_ids }
+ end
+ end
+ end
+end
diff --git a/app/services/ci/runners/process_runner_version_update_service.rb b/app/services/ci/runners/process_runner_version_update_service.rb
new file mode 100644
index 00000000000..c8a5e42ccab
--- /dev/null
+++ b/app/services/ci/runners/process_runner_version_update_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Ci
+ module Runners
+ class ProcessRunnerVersionUpdateService
+ def initialize(version)
+ @version = version
+ end
+
+ def execute
+ return ServiceResponse.error(message: 'version not present') unless @version
+
+ _, status = upgrade_check_service.check_runner_upgrade_suggestion(@version)
+ return ServiceResponse.error(message: 'upgrade version check failed') if status == :error
+
+ Ci::RunnerVersion.upsert({ version: @version, status: status })
+ ServiceResponse.success(payload: { upgrade_status: status.to_s })
+ end
+
+ private
+
+ def upgrade_check_service
+ @runner_upgrade_check ||= Gitlab::Ci::RunnerUpgradeCheck.new(::Gitlab::VERSION)
+ end
+ end
+ end
+end
diff --git a/app/services/ci/runners/reconcile_existing_runner_versions_service.rb b/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
index e04079bfe27..1950d82845b 100644
--- a/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
+++ b/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
@@ -3,8 +3,6 @@
module Ci
module Runners
class ReconcileExistingRunnerVersionsService
- include BaseServiceUtility
-
VERSION_BATCH_SIZE = 100
def execute
@@ -12,7 +10,7 @@ module Ci
total_deleted = cleanup_runner_versions(insert_result[:versions_from_runners])
total_updated = update_status_on_outdated_runner_versions(insert_result[:versions_from_runners])
- success({
+ ServiceResponse.success(payload: {
total_inserted: insert_result[:new_record_count],
total_updated: total_updated,
total_deleted: total_deleted
@@ -22,7 +20,7 @@ module Ci
private
def upgrade_check
- Gitlab::Ci::RunnerUpgradeCheck.instance
+ @runner_upgrade_check ||= Gitlab::Ci::RunnerUpgradeCheck.new(::Gitlab::VERSION)
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -74,13 +72,11 @@ module Ci
end
def runner_version_with_updated_status(runner_version)
- version = runner_version['version']
- suggestion = upgrade_check.check_runner_upgrade_status(version)
- new_status = suggestion.each_key.first
+ _, new_status = upgrade_check.check_runner_upgrade_suggestion(runner_version.version)
- if new_status != :error && new_status != runner_version['status'].to_sym
+ if new_status != :error && new_status != runner_version.status.to_sym
{
- version: version,
+ version: runner_version.version,
status: Ci::RunnerVersion.statuses[new_status]
}
end
diff --git a/app/services/ci/runners/register_runner_service.rb b/app/services/ci/runners/register_runner_service.rb
index 6588cd7e248..ae9b8bc8a16 100644
--- a/app/services/ci/runners/register_runner_service.rb
+++ b/app/services/ci/runners/register_runner_service.rb
@@ -6,7 +6,7 @@ module Ci
def execute(registration_token, attributes)
runner_type_attrs = extract_runner_type_attrs(registration_token)
- return unless runner_type_attrs
+ return ServiceResponse.error(message: 'invalid token supplied', http_status: :forbidden) unless runner_type_attrs
runner = ::Ci::Runner.new(attributes.merge(runner_type_attrs))
@@ -20,7 +20,7 @@ module Ci
end
end
- runner
+ ServiceResponse.success(payload: { runner: runner })
end
private
diff --git a/app/services/ci/runners/reset_registration_token_service.rb b/app/services/ci/runners/reset_registration_token_service.rb
index 81a70a771cf..dddbfb78d44 100644
--- a/app/services/ci/runners/reset_registration_token_service.rb
+++ b/app/services/ci/runners/reset_registration_token_service.rb
@@ -11,15 +11,19 @@ module Ci
end
def execute
- return unless @user.present? && @user.can?(:update_runners_registration_token, scope)
+ unless @user.present? && @user.can?(:update_runners_registration_token, scope)
+ return ServiceResponse.error(message: 'user not allowed to update runners registration token')
+ end
if scope.respond_to?(:runners_registration_token)
scope.reset_runners_registration_token!
- scope.runners_registration_token
+ runners_token = scope.runners_registration_token
else
scope.reset_runners_token!
- scope.runners_token
+ runners_token = scope.runners_token
end
+
+ ServiceResponse.success(payload: { new_registration_token: runners_token })
end
private
diff --git a/app/services/ci/runners/unassign_runner_service.rb b/app/services/ci/runners/unassign_runner_service.rb
index 1e46cf6add8..c40e5e0d44e 100644
--- a/app/services/ci/runners/unassign_runner_service.rb
+++ b/app/services/ci/runners/unassign_runner_service.rb
@@ -13,9 +13,15 @@ module Ci
end
def execute
- return false unless @user.present? && @user.can?(:assign_runner, @runner)
+ unless @user.present? && @user.can?(:assign_runner, @runner)
+ return ServiceResponse.error(message: 'user not allowed to assign runner')
+ end
- @runner_project.destroy
+ if @runner_project.destroy
+ ServiceResponse.success
+ else
+ ServiceResponse.error(message: 'failed to destroy runner project')
+ end
end
private
diff --git a/app/services/ci/runners/unregister_runner_service.rb b/app/services/ci/runners/unregister_runner_service.rb
index 4ee1e73c458..742b21f77df 100644
--- a/app/services/ci/runners/unregister_runner_service.rb
+++ b/app/services/ci/runners/unregister_runner_service.rb
@@ -14,6 +14,7 @@ module Ci
def execute
@runner&.destroy
+ ServiceResponse.success
end
end
end
diff --git a/app/services/ci/stuck_builds/drop_helpers.rb b/app/services/ci/stuck_builds/drop_helpers.rb
index 048b52c6e13..dca50963883 100644
--- a/app/services/ci/stuck_builds/drop_helpers.rb
+++ b/app/services/ci/stuck_builds/drop_helpers.rb
@@ -56,12 +56,12 @@ module Ci
def log_dropping_message(type, build, reason)
Gitlab::AppLogger.info(class: self.class.name,
- message: "Dropping #{type} build",
- build_stuck_type: type,
- build_id: build.id,
- runner_id: build.runner_id,
- build_status: build.status,
- build_failure_reason: reason)
+ message: "Dropping #{type} build",
+ build_stuck_type: type,
+ build_id: build.id,
+ runner_id: build.runner_id,
+ build_status: build.status,
+ build_failure_reason: reason)
end
end
end
diff --git a/app/services/ci/track_failed_build_service.rb b/app/services/ci/track_failed_build_service.rb
new file mode 100644
index 00000000000..caf7034234c
--- /dev/null
+++ b/app/services/ci/track_failed_build_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+# This service tracks failed CI builds using Snowplow.
+#
+# @param build [Ci::Build] the build that failed.
+# @param exit_code [Int] the resulting exit code.
+module Ci
+ class TrackFailedBuildService
+ SCHEMA_URL = 'iglu:com.gitlab/ci_build_failed/jsonschema/1-0-0'
+
+ def initialize(build:, exit_code:, failure_reason:)
+ @build = build
+ @exit_code = exit_code
+ @failure_reason = failure_reason
+ end
+
+ def execute
+ # rubocop:disable Style/IfUnlessModifier
+ unless @build.failed?
+ return ServiceResponse.error(message: 'Attempted to track a non-failed CI build')
+ end
+
+ # rubocop:enable Style/IfUnlessModifier
+
+ context = SnowplowTracker::SelfDescribingJson.new(SCHEMA_URL, payload)
+
+ ::Gitlab::Tracking.event(
+ 'ci::build',
+ 'failed',
+ context: [context],
+ user: @build.user,
+ project: @build.project_id)
+
+ ServiceResponse.success
+ end
+
+ private
+
+ def payload
+ {
+ build_id: @build.id,
+ build_name: @build.name,
+ build_artifact_types: @build.job_artifact_types,
+ exit_code: @exit_code,
+ failure_reason: @failure_reason
+ }
+ end
+ end
+end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index a74ddcfaf06..835d5f9a16c 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -105,7 +105,7 @@ module Ci
Result.new(status: 200)
when 'failed'
- build.drop_with_exit_code!(params[:failure_reason] || :unknown_failure, params[:exit_code])
+ build.drop_with_exit_code!(params[:failure_reason], params[:exit_code])
Result.new(status: 200)
else
diff --git a/app/services/concerns/alert_management/alert_processing.rb b/app/services/concerns/alert_management/alert_processing.rb
index f10ff4e6f19..8c6c7b15d28 100644
--- a/app/services/concerns/alert_management/alert_processing.rb
+++ b/app/services/concerns/alert_management/alert_processing.rb
@@ -39,12 +39,6 @@ module AlertManagement
SystemNoteService.change_alert_status(alert, User.alert_bot)
close_issue(alert.issue_id) if auto_close_incident?
- else
- logger.warn(
- message: 'Unable to update AlertManagement::Alert status to resolved',
- project_id: project.id,
- alert_id: alert.id
- )
end
end
@@ -64,13 +58,18 @@ module AlertManagement
if alert.save
alert.execute_integrations
SystemNoteService.create_new_alert(alert, alert_source)
+ elsif alert.errors[:fingerprint].any?
+ refind_and_increment_alert
else
logger.warn(
- message: "Unable to create AlertManagement::Alert from #{alert_source}",
+ message: "Unable to create AlertManagement::Alert",
project_id: project.id,
- alert_errors: alert.errors.messages
+ alert_errors: alert.errors.messages,
+ alert_source: alert_source
)
end
+ rescue ActiveRecord::RecordNotUnique
+ refind_and_increment_alert
end
def process_incident_issues
@@ -107,6 +106,12 @@ module AlertManagement
AlertManagement::Alert.new(**incoming_payload.alert_params, ended_at: nil)
end
+ def refind_and_increment_alert
+ clear_memoization(:alert)
+
+ process_firing_alert
+ end
+
def resolving_alert?
incoming_payload.ends_at.present?
end
diff --git a/app/services/concerns/work_items/widgetable_service.rb b/app/services/concerns/work_items/widgetable_service.rb
index 5665b07dce1..beb614c7b76 100644
--- a/app/services/concerns/work_items/widgetable_service.rb
+++ b/app/services/concerns/work_items/widgetable_service.rb
@@ -18,7 +18,7 @@ module WorkItems
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def widget_service_class(widget)
- "WorkItems::Widgets::#{widget.type.capitalize}Service::#{self.class.name.demodulize}".constantize
+ "WorkItems::Widgets::#{widget.type.to_s.camelize}Service::#{self.class.name.demodulize}".constantize
rescue NameError
nil
end
diff --git a/app/services/database/consistency_check_service.rb b/app/services/database/consistency_check_service.rb
index e39bc8f25b8..fee2e79a6cb 100644
--- a/app/services/database/consistency_check_service.rb
+++ b/app/services/database/consistency_check_service.rb
@@ -80,7 +80,7 @@ module Database
end
def max_id
- @max_id ||= source_model.minimum(source_sort_column)
+ @max_id ||= source_model.maximum(source_sort_column)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/deployments/update_environment_service.rb b/app/services/deployments/update_environment_service.rb
index b0eb153a7af..3cacedc7d6e 100644
--- a/app/services/deployments/update_environment_service.rb
+++ b/app/services/deployments/update_environment_service.rb
@@ -58,11 +58,7 @@ module Deployments
def expanded_environment_url
return unless environment_url
- if ::Feature.enabled?(:ci_expand_environment_name_and_url, deployment.project)
- ExpandVariables.expand(environment_url, -> { variables.sort_and_expand_all })
- else
- ExpandVariables.expand(environment_url, -> { variables })
- end
+ ExpandVariables.expand(environment_url, -> { variables.sort_and_expand_all })
end
def environment_url
@@ -88,7 +84,7 @@ module Deployments
def renew_deployment_tier
return unless deployable
- if (tier = deployable.environment_deployment_tier)
+ if (tier = deployable.environment_tier_from_options)
environment.tier = tier
end
end
diff --git a/app/services/design_management/generate_image_versions_service.rb b/app/services/design_management/generate_image_versions_service.rb
index e56d163c461..3ff239b59cc 100644
--- a/app/services/design_management/generate_image_versions_service.rb
+++ b/app/services/design_management/generate_image_versions_service.rb
@@ -43,7 +43,7 @@ module DesignManagement
end
# Skip attempting to process images that would be rejected by CarrierWave.
- return unless DesignManagement::DesignV432x230Uploader::MIME_TYPE_WHITELIST.include?(raw_file.content_type)
+ return unless DesignManagement::DesignV432x230Uploader::MIME_TYPE_ALLOWLIST.include?(raw_file.content_type)
# Store and process the file
action.image_v432x230.store!(raw_file)
diff --git a/app/services/error_tracking/base_service.rb b/app/services/error_tracking/base_service.rb
index d2ecd0a6d5a..8458eb1f3b8 100644
--- a/app/services/error_tracking/base_service.rb
+++ b/app/services/error_tracking/base_service.rb
@@ -25,7 +25,7 @@ module ErrorTracking
errors = parse_errors(response)
return errors if errors
- yield if block_given?
+ yield if block
track_usage_event(params[:tracking_event], current_user.id) if params[:tracking_event]
diff --git a/app/services/google_cloud/base_service.rb b/app/services/google_cloud/base_service.rb
index 016ab15408f..01aee2231c9 100644
--- a/app/services/google_cloud/base_service.rb
+++ b/app/services/google_cloud/base_service.rb
@@ -22,7 +22,7 @@ module GoogleCloud
def unique_gcp_project_ids
filter_params = { key: 'GCP_PROJECT_ID' }
- ::Ci::VariablesFinder.new(project, filter_params).execute.map(&:value).uniq
+ @unique_gcp_project_ids ||= ::Ci::VariablesFinder.new(project, filter_params).execute.map(&:value).uniq
end
def group_vars_by_environment(keys)
diff --git a/app/services/google_cloud/create_cloudsql_instance_service.rb b/app/services/google_cloud/create_cloudsql_instance_service.rb
new file mode 100644
index 00000000000..f7fca277c52
--- /dev/null
+++ b/app/services/google_cloud/create_cloudsql_instance_service.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ DEFAULT_REGION = 'us-east1'
+
+ class CreateCloudsqlInstanceService < ::GoogleCloud::BaseService
+ WORKER_INTERVAL = 30.seconds
+
+ def execute
+ create_cloud_instance
+ trigger_instance_setup_worker
+ success
+ rescue Google::Apis::Error => err
+ error(err.to_json)
+ end
+
+ private
+
+ def create_cloud_instance
+ google_api_client.create_cloudsql_instance(gcp_project_id,
+ instance_name,
+ root_password,
+ database_version,
+ region,
+ tier)
+ end
+
+ def trigger_instance_setup_worker
+ GoogleCloud::CreateCloudsqlInstanceWorker.perform_in(WORKER_INTERVAL,
+ current_user.id,
+ project.id,
+ {
+ 'google_oauth2_token': google_oauth2_token,
+ 'gcp_project_id': gcp_project_id,
+ 'instance_name': instance_name,
+ 'database_version': database_version,
+ 'environment_name': environment_name,
+ 'is_protected': protected?
+ })
+ end
+
+ def protected?
+ project.protected_for?(environment_name)
+ end
+
+ def instance_name
+ # Generates an `instance_name` for the to-be-created Cloud SQL instance
+ # Example: `gitlab-34647-postgres-14-staging`
+ environment_alias = environment_name == '*' ? 'ALL' : environment_name
+ name = "gitlab-#{project.id}-#{database_version}-#{environment_alias}"
+ name.tr("_", "-").downcase
+ end
+
+ def root_password
+ SecureRandom.hex(16)
+ end
+
+ def database_version
+ params[:database_version]
+ end
+
+ def region
+ region = ::Ci::VariablesFinder
+ .new(project, { key: Projects::GoogleCloud::GcpRegionsController::GCP_REGION_CI_VAR_KEY,
+ environment_scope: environment_name })
+ .execute.first
+ region&.value || DEFAULT_REGION
+ end
+
+ def tier
+ params[:tier]
+ end
+ end
+end
diff --git a/app/services/google_cloud/enable_cloudsql_service.rb b/app/services/google_cloud/enable_cloudsql_service.rb
new file mode 100644
index 00000000000..a466b2f3696
--- /dev/null
+++ b/app/services/google_cloud/enable_cloudsql_service.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ class EnableCloudsqlService < ::GoogleCloud::BaseService
+ def execute
+ return no_projects_error if unique_gcp_project_ids.empty?
+
+ unique_gcp_project_ids.each do |gcp_project_id|
+ google_api_client.enable_cloud_sql_admin(gcp_project_id)
+ google_api_client.enable_compute(gcp_project_id)
+ google_api_client.enable_service_networking(gcp_project_id)
+ end
+
+ success({ gcp_project_ids: unique_gcp_project_ids })
+ end
+
+ private
+
+ def no_projects_error
+ error("No GCP projects found. Configure a service account or GCP_PROJECT_ID CI variable.")
+ end
+ end
+end
diff --git a/app/services/google_cloud/get_cloudsql_instances_service.rb b/app/services/google_cloud/get_cloudsql_instances_service.rb
new file mode 100644
index 00000000000..701e83d556d
--- /dev/null
+++ b/app/services/google_cloud/get_cloudsql_instances_service.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module GoogleCloud
+ class GetCloudsqlInstancesService < ::GoogleCloud::BaseService
+ CLOUDSQL_KEYS = %w[GCP_PROJECT_ID GCP_CLOUDSQL_INSTANCE_NAME GCP_CLOUDSQL_VERSION].freeze
+
+ def execute
+ group_vars_by_environment(CLOUDSQL_KEYS).map do |environment_scope, value|
+ {
+ ref: environment_scope,
+ gcp_project: value['GCP_PROJECT_ID'],
+ instance_name: value['GCP_CLOUDSQL_INSTANCE_NAME'],
+ version: value['GCP_CLOUDSQL_VERSION']
+ }
+ end
+ end
+ end
+end
diff --git a/app/services/google_cloud/setup_cloudsql_instance_service.rb b/app/services/google_cloud/setup_cloudsql_instance_service.rb
index 73650ee752f..10237f83b37 100644
--- a/app/services/google_cloud/setup_cloudsql_instance_service.rb
+++ b/app/services/google_cloud/setup_cloudsql_instance_service.rb
@@ -16,29 +16,29 @@ module GoogleCloud
return error("CloudSQL instance not RUNNABLE: #{get_instance_response.to_json}")
end
- database_response = google_api_client.create_cloudsql_database(gcp_project_id, instance_name, database_name)
+ save_instance_ci_vars(get_instance_response)
- if database_response.status != OPERATION_STATE_DONE
- return error("Database creation failed: #{database_response.to_json}")
- end
+ list_database_response = google_api_client.list_cloudsql_databases(gcp_project_id, instance_name)
+ list_user_response = google_api_client.list_cloudsql_users(gcp_project_id, instance_name)
- user_response = google_api_client.create_cloudsql_user(gcp_project_id, instance_name, username, password)
+ existing_database = list_database_response.items.find { |database| database.name == database_name }
+ existing_user = list_user_response.items.find { |user| user.name == username }
- if user_response.status != OPERATION_STATE_DONE
- return error("User creation failed: #{user_response.to_json}")
+ if existing_database && existing_user
+ save_database_ci_vars
+ save_user_ci_vars(existing_user)
+ return success
end
- primary_ip_address = get_instance_response.ip_addresses.first.ip_address
- connection_name = get_instance_response.connection_name
+ database_response = execute_database_setup(existing_database)
+ return database_response if database_response[:status] == :error
- save_ci_var('GCP_PROJECT_ID', gcp_project_id)
- save_ci_var('GCP_CLOUDSQL_INSTANCE_NAME', instance_name)
- save_ci_var('GCP_CLOUDSQL_CONNECTION_NAME', connection_name)
- save_ci_var('GCP_CLOUDSQL_PRIMARY_IP_ADDRESS', primary_ip_address)
- save_ci_var('GCP_CLOUDSQL_VERSION', database_version)
- save_ci_var('GCP_CLOUDSQL_DATABASE_NAME', database_name)
- save_ci_var('GCP_CLOUDSQL_DATABASE_USER', username)
- save_ci_var('GCP_CLOUDSQL_DATABASE_PASS', password, true)
+ save_database_ci_vars
+
+ user_response = execute_user_setup(existing_user)
+ return user_response if user_response[:status] == :error
+
+ save_user_ci_vars(existing_user)
success
rescue Google::Apis::Error => err
@@ -64,11 +64,55 @@ module GoogleCloud
end
def password
- SecureRandom.hex(16)
+ @password ||= SecureRandom.hex(16)
end
def save_ci_var(key, value, is_masked = false)
create_or_replace_project_vars(environment_name, key, value, @params[:is_protected], is_masked)
end
+
+ def save_instance_ci_vars(cloudsql_instance)
+ primary_ip_address = cloudsql_instance.ip_addresses.first.ip_address
+ connection_name = cloudsql_instance.connection_name
+
+ save_ci_var('GCP_PROJECT_ID', gcp_project_id)
+ save_ci_var('GCP_CLOUDSQL_INSTANCE_NAME', instance_name)
+ save_ci_var('GCP_CLOUDSQL_CONNECTION_NAME', connection_name)
+ save_ci_var('GCP_CLOUDSQL_PRIMARY_IP_ADDRESS', primary_ip_address)
+ save_ci_var('GCP_CLOUDSQL_VERSION', database_version)
+ end
+
+ def save_database_ci_vars
+ save_ci_var('GCP_CLOUDSQL_DATABASE_NAME', database_name)
+ end
+
+ def save_user_ci_vars(user_exists)
+ save_ci_var('GCP_CLOUDSQL_DATABASE_USER', username)
+ save_ci_var('GCP_CLOUDSQL_DATABASE_PASS', user_exists ? user_exists.password : password, true)
+ end
+
+ def execute_database_setup(database_exists)
+ return success if database_exists
+
+ database_response = google_api_client.create_cloudsql_database(gcp_project_id, instance_name, database_name)
+
+ if database_response.status != OPERATION_STATE_DONE
+ return error("Database creation failed: #{database_response.to_json}")
+ end
+
+ success
+ end
+
+ def execute_user_setup(existing_user)
+ return success if existing_user
+
+ user_response = google_api_client.create_cloudsql_user(gcp_project_id, instance_name, username, password)
+
+ if user_response.status != OPERATION_STATE_DONE
+ return error("User creation failed: #{user_response.to_json}")
+ end
+
+ success
+ end
end
end
diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb
index bcf3110ca21..02a760ccf29 100644
--- a/app/services/groups/destroy_service.rb
+++ b/app/services/groups/destroy_service.rb
@@ -45,6 +45,8 @@ module Groups
.execute(blocking: true)
end
+ publish_event
+
group
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -91,6 +93,17 @@ module Groups
end
end
# rubocop:enable CodeReuse/ActiveRecord
+
+ def publish_event
+ event = Groups::GroupDeletedEvent.new(
+ data: {
+ group_id: group.id,
+ root_namespace_id: group.root_ancestor.id
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/groups/import_export/export_service.rb b/app/services/groups/import_export/export_service.rb
index 2bfd5a5ebab..bd54b48c5f4 100644
--- a/app/services/groups/import_export/export_service.rb
+++ b/app/services/groups/import_export/export_service.rb
@@ -49,13 +49,23 @@ module Groups
# We cannot include the file_saver with the other savers because
# it removes the tmp dir. This means that if we want to add new savers
# in EE the data won't be available.
- if savers.all?(&:save) && file_saver.save
+ if save_exporters && file_saver.save
notify_success
else
notify_error!
end
end
+ def save_exporters
+ log_info('Group export started')
+
+ savers.all? do |exporter|
+ log_info("#{exporter.class.name} saver started")
+
+ exporter.save
+ end
+ end
+
def savers
[version_saver, tree_exporter]
end
@@ -99,12 +109,16 @@ module Groups
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
end
- def notify_success
+ def log_info(message)
@logger.info(
- message: 'Group Export succeeded',
+ message: message,
group_id: group.id,
group_name: group.name
)
+ end
+
+ def notify_success
+ log_info('Group Export succeeded')
notification_service.group_was_exported(group, current_user)
end
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index f026f1698a9..db52a272bf2 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -97,17 +97,17 @@ module Groups
def notify_success
@logger.info(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: 'Group Import/Export: Import succeeded'
+ message: 'Group Import/Export: Import succeeded'
)
end
def notify_error
@logger.error(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
+ message: "Group Import/Export: Errors occurred, see '#{Gitlab::ErrorTracking::Logger.file_name}' for details"
)
end
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 29e3a9473ab..6fbf7daeb81 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -36,7 +36,7 @@ module Groups
update_crm_objects(was_root_group)
end
- post_update_hooks(@updated_project_ids)
+ post_update_hooks(@updated_project_ids, old_root_ancestor_id)
propagate_integrations
update_pending_builds
@@ -44,9 +44,10 @@ module Groups
end
# Overridden in EE
- def post_update_hooks(updated_project_ids)
+ def post_update_hooks(updated_project_ids, old_root_ancestor_id)
refresh_project_authorizations
refresh_descendant_groups if @new_parent_group
+ publish_event(old_root_ancestor_id)
end
def ensure_allowed_transfer
@@ -266,6 +267,18 @@ module Groups
CustomerRelations::IssueContact.delete_for_group(@group)
end
+
+ def publish_event(old_root_ancestor_id)
+ event = ::Groups::GroupTransferedEvent.new(
+ data: {
+ group_id: group.id,
+ old_root_namespace_id: old_root_ancestor_id,
+ new_root_namespace_id: group.root_ancestor.id
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index b3b0397eac3..2135892a95a 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -61,15 +61,18 @@ module Groups
end
def before_assignment_hook(group, params)
- # overridden in EE
+ @full_path_before = group.full_path
+ @path_before = group.path
end
def renaming_group_with_container_registry_images?
+ renaming? && group.has_container_repository_including_subgroups?
+ end
+
+ def renaming?
new_path = params[:path]
- new_path &&
- new_path != group.path &&
- group.has_container_repository_including_subgroups?
+ new_path && new_path != @path_before
end
def container_images_error
@@ -83,6 +86,8 @@ module Groups
end
update_two_factor_requirement_for_subgroups
+
+ publish_event
end
def update_two_factor_requirement_for_subgroups
@@ -154,6 +159,21 @@ module Groups
group.errors.add(:update_shared_runners, result[:message])
false
end
+
+ def publish_event
+ return unless renaming?
+
+ event = Groups::GroupPathChangedEvent.new(
+ data: {
+ group_id: group.id,
+ root_namespace_id: group.root_ancestor.id,
+ old_path: @full_path_before,
+ new_path: group.full_path
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/import/prepare_service.rb b/app/services/import/prepare_service.rb
new file mode 100644
index 00000000000..278bd463dcd
--- /dev/null
+++ b/app/services/import/prepare_service.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Import
+ class PrepareService < ::BaseService
+ def execute
+ uploader = UploadService.new(project, params[:file]).execute
+
+ if uploader
+ enqueue_import(uploader.upload)
+
+ ServiceResponse.success(message: success_message)
+ else
+ ServiceResponse.error(message: _('File upload error.'))
+ end
+ end
+
+ private
+
+ def enqueue_import(upload)
+ worker.perform_async(current_user.id, project.id, upload.id)
+ end
+
+ def worker
+ raise NotImplementedError
+ end
+
+ def success_message
+ raise NotImplementedError
+ end
+ end
+end
diff --git a/app/services/incident_management/timeline_events/create_service.rb b/app/services/incident_management/timeline_events/create_service.rb
index 3cb67ccf2b1..40ce9097c88 100644
--- a/app/services/incident_management/timeline_events/create_service.rb
+++ b/app/services/incident_management/timeline_events/create_service.rb
@@ -48,6 +48,26 @@ module IncidentManagement
new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
end
+
+ def change_labels(incident, user, added_labels: [], removed_labels: [])
+ return if Feature.disabled?(:incident_timeline_events_from_labels, incident.project)
+
+ if added_labels.blank? && removed_labels.blank?
+ return ServiceResponse.error(message: _('There are no changed labels'))
+ end
+
+ labels_note = -> (verb, labels) {
+ "#{verb} #{labels.map(&:to_reference).join(' ')} #{'label'.pluralize(labels.count)}" if labels.present?
+ }
+
+ added_note = labels_note.call('added', added_labels)
+ removed_note = labels_note.call('removed', removed_labels)
+ note = "@#{user.username} #{[added_note, removed_note].compact.join(' and ')}"
+ occurred_at = incident.updated_at
+ action = 'label'
+
+ new(incident, user, note: note, occurred_at: occurred_at, action: action, auto_created: true).execute
+ end
end
def execute
diff --git a/app/services/incident_management/timeline_events/update_service.rb b/app/services/incident_management/timeline_events/update_service.rb
index 8217c8125c2..5c5de4717bc 100644
--- a/app/services/incident_management/timeline_events/update_service.rb
+++ b/app/services/incident_management/timeline_events/update_service.rb
@@ -34,7 +34,7 @@ module IncidentManagement
attr_reader :timeline_event, :incident, :user, :note, :occurred_at
def update_params
- { updated_by_user: user, note: note.presence, occurred_at: occurred_at.presence }.compact
+ { updated_by_user: user, note: note, occurred_at: occurred_at }.compact
end
def add_system_note(timeline_event)
diff --git a/app/services/issuable/clone/base_service.rb b/app/services/issuable/clone/base_service.rb
index 98c50347719..3c13944cfbc 100644
--- a/app/services/issuable/clone/base_service.rb
+++ b/app/services/issuable/clone/base_service.rb
@@ -16,6 +16,7 @@ module Issuable
#
ApplicationRecord.transaction do
@new_entity = create_new_entity
+ @new_entity.system_note_timestamp = nil
update_new_entity
update_old_entity
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index 5cf32ee3e40..db28be864a7 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -21,7 +21,7 @@ module Issuable
create_discussion_lock_note if issuable.previous_changes.include?('discussion_locked')
end
- create_due_date_note if issuable.previous_changes.include?('due_date')
+ handle_start_date_or_due_date_change_note
create_milestone_change_event(old_milestone) if issuable.previous_changes.include?('milestone_id')
create_labels_note(old_labels) if old_labels && issuable.labels != old_labels
end
@@ -29,6 +29,13 @@ module Issuable
private
+ def handle_start_date_or_due_date_change_note
+ # Type check needed as some issuables do their own date change handling for date fields other than due_date
+ change_date_fields = issuable.is_a?(Issue) ? %w[due_date start_date] : %w[due_date]
+ changed_dates = issuable.previous_changes.slice(*change_date_fields)
+ create_start_date_or_due_date_note(changed_dates)
+ end
+
def handle_time_tracking_note
if issuable.previous_changes.include?('time_estimate')
create_time_estimate_note
@@ -99,8 +106,10 @@ module Issuable
.execute
end
- def create_due_date_note
- SystemNoteService.change_due_date(issuable, issuable.project, current_user, issuable.due_date)
+ def create_start_date_or_due_date_note(changed_dates)
+ return if changed_dates.blank?
+
+ SystemNoteService.change_start_date_or_due_date(issuable, issuable.project, current_user, changed_dates)
end
def create_discussion_lock_note
diff --git a/app/services/issuable/import_csv/base_service.rb b/app/services/issuable/import_csv/base_service.rb
index 9b41c88159f..822e3cd787c 100644
--- a/app/services/issuable/import_csv/base_service.rb
+++ b/app/services/issuable/import_csv/base_service.rb
@@ -21,13 +21,9 @@ module Issuable
def process_csv
with_csv_lines.each do |row, line_no|
- issuable_attributes = {
- title: row[:title],
- description: row[:description],
- due_date: row[:due_date]
- }
+ attributes = issuable_attributes_for(row)
- if create_issuable(issuable_attributes).persisted?
+ if create_issuable(attributes).persisted?
@results[:success] += 1
else
@results[:error_lines].push(line_no)
@@ -37,6 +33,14 @@ module Issuable
@results[:parse_error] = true
end
+ def issuable_attributes_for(row)
+ {
+ title: row[:title],
+ description: row[:description],
+ due_date: row[:due_date]
+ }
+ end
+
def with_csv_lines
csv_data = @csv_io.open(&:read).force_encoding(Encoding::UTF_8)
validate_headers_presence!(csv_data.lines.first)
diff --git a/app/services/issues/clone_service.rb b/app/services/issues/clone_service.rb
index 896b15a14b8..07dd9a98f89 100644
--- a/app/services/issues/clone_service.rb
+++ b/app/services/issues/clone_service.rb
@@ -41,7 +41,6 @@ module Issues
def update_new_entity
# we don't call `super` because we want to be able to decide whether or not to copy all comments over.
update_new_entity_description
- copy_award_emoji
if with_notes
copy_notes
@@ -96,9 +95,14 @@ module Issues
end
def add_note_from
- SystemNoteService.noteable_cloned(new_entity, target_project,
- original_entity, current_user,
- direction: :from)
+ SystemNoteService.noteable_cloned(
+ new_entity,
+ target_project,
+ original_entity,
+ current_user,
+ direction: :from,
+ created_at: new_entity.created_at
+ )
end
def add_note_to
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 30d4cb68840..92cf4811439 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -45,7 +45,7 @@ module Issues
# current_user (defined in BaseService) is not available within run_after_commit block
user = current_user
issue.run_after_commit do
- NewIssueWorker.perform_async(issue.id, user.id)
+ 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)
end
diff --git a/app/services/issues/export_csv_service.rb b/app/services/issues/export_csv_service.rb
index 7076e858155..6209127bd86 100644
--- a/app/services/issues/export_csv_service.rb
+++ b/app/services/issues/export_csv_service.rb
@@ -25,24 +25,24 @@ module Issues
{
'Title' => 'title',
'Description' => 'description',
- 'Issue ID' => 'iid',
- 'URL' => -> (issue) { issue_url(issue) },
- 'State' => -> (issue) { issue.closed? ? 'Closed' : 'Open' },
- 'Author' => 'author_name',
- 'Author Username' => -> (issue) { issue.author&.username },
- 'Assignee' => -> (issue) { issue.assignees.map(&:name).join(', ') },
- 'Assignee Username' => -> (issue) { issue.assignees.map(&:username).join(', ') },
- 'Confidential' => -> (issue) { issue.confidential? ? 'Yes' : 'No' },
- 'Locked' => -> (issue) { issue.discussion_locked? ? 'Yes' : 'No' },
- 'Due Date' => -> (issue) { issue.due_date&.to_s(:csv) },
- 'Created At (UTC)' => -> (issue) { issue.created_at&.to_s(:csv) },
- 'Updated At (UTC)' => -> (issue) { issue.updated_at&.to_s(:csv) },
- 'Closed At (UTC)' => -> (issue) { issue.closed_at&.to_s(:csv) },
- 'Milestone' => -> (issue) { issue.milestone&.title },
- 'Weight' => -> (issue) { issue.weight },
- 'Labels' => -> (issue) { issue_labels(issue) },
- 'Time Estimate' => ->(issue) { issue.time_estimate.to_s(:csv) },
- 'Time Spent' => -> (issue) { issue_time_spent(issue) }
+ 'Issue ID' => 'iid',
+ 'URL' => -> (issue) { issue_url(issue) },
+ 'State' => -> (issue) { issue.closed? ? 'Closed' : 'Open' },
+ 'Author' => 'author_name',
+ 'Author Username' => -> (issue) { issue.author&.username },
+ 'Assignee' => -> (issue) { issue.assignees.map(&:name).join(', ') },
+ 'Assignee Username' => -> (issue) { issue.assignees.map(&:username).join(', ') },
+ 'Confidential' => -> (issue) { issue.confidential? ? 'Yes' : 'No' },
+ 'Locked' => -> (issue) { issue.discussion_locked? ? 'Yes' : 'No' },
+ 'Due Date' => -> (issue) { issue.due_date&.to_s(:csv) },
+ 'Created At (UTC)' => -> (issue) { issue.created_at&.to_s(:csv) },
+ 'Updated At (UTC)' => -> (issue) { issue.updated_at&.to_s(:csv) },
+ 'Closed At (UTC)' => -> (issue) { issue.closed_at&.to_s(:csv) },
+ 'Milestone' => -> (issue) { issue.milestone&.title },
+ 'Weight' => -> (issue) { issue.weight },
+ 'Labels' => -> (issue) { issue_labels(issue) },
+ 'Time Estimate' => ->(issue) { issue.time_estimate.to_s(:csv) },
+ 'Time Spent' => -> (issue) { issue_time_spent(issue) }
}
end
diff --git a/app/services/issues/prepare_import_csv_service.rb b/app/services/issues/prepare_import_csv_service.rb
new file mode 100644
index 00000000000..7afe363117e
--- /dev/null
+++ b/app/services/issues/prepare_import_csv_service.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Issues
+ class PrepareImportCsvService < Import::PrepareService
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ override :worker
+ def worker
+ ImportIssuesCsvWorker
+ end
+
+ override :success_message
+ def success_message
+ _("Your issues are being imported. Once finished, you'll get a confirmation email.")
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index afc61eed287..46c28d82ddc 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -70,6 +70,7 @@ module Issues
handle_severity_change(issue, old_severity)
handle_escalation_status_change(issue)
handle_issue_type_change(issue)
+ handle_date_changes(issue)
end
def handle_assignee_changes(issue, old_assignees)
@@ -116,6 +117,12 @@ module Issues
attr_reader :spam_params
+ def handle_date_changes(issue)
+ return unless issue.previous_changes.slice('due_date', 'start_date').any?
+
+ GraphqlTriggers.issuable_dates_updated(issue)
+ end
+
def clone_issue(issue)
target_project = params.delete(:target_clone_project)
with_notes = params.delete(:clone_with_notes)
diff --git a/app/services/jira/requests/base.rb b/app/services/jira/requests/base.rb
index 8e8511e5180..d0ca8863c29 100644
--- a/app/services/jira/requests/base.rb
+++ b/app/services/jira/requests/base.rb
@@ -9,10 +9,10 @@ module Jira
ERRORS = {
connection: [Errno::ECONNRESET, Errno::ECONNREFUSED],
- jira_ruby: JIRA::HTTPError,
- ssl: OpenSSL::SSL::SSLError,
- timeout: [Timeout::Error, Errno::ETIMEDOUT],
- uri: [URI::InvalidURIError, SocketError]
+ jira_ruby: JIRA::HTTPError,
+ ssl: OpenSSL::SSL::SSLError,
+ timeout: [Timeout::Error, Errno::ETIMEDOUT],
+ uri: [URI::InvalidURIError, SocketError]
}.freeze
ALL_ERRORS = ERRORS.values.flatten.freeze
diff --git a/app/services/merge_requests/approval_service.rb b/app/services/merge_requests/approval_service.rb
index b8d817a15f3..dcc4cf4bb1e 100644
--- a/app/services/merge_requests/approval_service.rb
+++ b/app/services/merge_requests/approval_service.rb
@@ -10,14 +10,27 @@ module MergeRequests
return success unless save_approval(approval)
reset_approvals_cache(merge_request)
- create_event(merge_request)
- stream_audit_event(merge_request)
- create_approval_note(merge_request)
- mark_pending_todos_as_done(merge_request)
- execute_approval_hooks(merge_request, current_user)
- remove_attention_requested(merge_request)
merge_request_activity_counter.track_approve_mr_action(user: current_user, merge_request: merge_request)
+ # Approval side effects (things not required to be done immediately but
+ # should happen after a successful approval) should be done asynchronously
+ # utilizing the `Gitlab::EventStore`.
+ #
+ # Workers can subscribe to the `MergeRequests::ApprovedEvent`.
+ if Feature.enabled?(:async_after_approval, project)
+ Gitlab::EventStore.publish(
+ MergeRequests::ApprovedEvent.new(
+ data: { current_user_id: current_user.id, merge_request_id: merge_request.id }
+ )
+ )
+ else
+ create_event(merge_request)
+ stream_audit_event(merge_request)
+ create_approval_note(merge_request)
+ mark_pending_todos_as_done(merge_request)
+ execute_approval_hooks(merge_request, current_user)
+ end
+
success
end
@@ -27,21 +40,22 @@ module MergeRequests
current_user.can?(:approve_merge_request, merge_request)
end
+ def save_approval(approval)
+ Approval.safe_ensure_unique do
+ approval.save
+ end
+ end
+
def reset_approvals_cache(merge_request)
merge_request.approvals.reset
end
- def execute_approval_hooks(merge_request, current_user)
- # Only one approval is required for a merge request to be approved
- notification_service.async.approve_mr(merge_request, current_user)
-
- execute_hooks(merge_request, 'approved')
+ def create_event(merge_request)
+ event_service.approve_mr(merge_request, current_user)
end
- def save_approval(approval)
- Approval.safe_ensure_unique do
- approval.save
- end
+ def stream_audit_event(merge_request)
+ # Defined in EE
end
def create_approval_note(merge_request)
@@ -52,12 +66,11 @@ module MergeRequests
todo_service.resolve_todos_for_target(merge_request, current_user)
end
- def create_event(merge_request)
- event_service.approve_mr(merge_request, current_user)
- end
+ def execute_approval_hooks(merge_request, current_user)
+ # Only one approval is required for a merge request to be approved
+ notification_service.async.approve_mr(merge_request, current_user)
- def stream_audit_event(merge_request)
- # Defined in EE
+ execute_hooks(merge_request, 'approved')
end
end
end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 9bd38478796..bda8dc64ac0 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -61,10 +61,6 @@ module MergeRequests
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
bulk_update_reviewers_state(merge_request, new_reviewers)
-
- unless new_reviewers.include?(current_user)
- remove_attention_requested(merge_request)
- end
end
def cleanup_environments(merge_request)
@@ -252,20 +248,6 @@ module MergeRequests
Milestones::MergeRequestsCountService.new(milestone).delete_cache
end
- def remove_all_attention_requests(merge_request)
- return unless current_user.mr_attention_requests_enabled?
-
- users = merge_request.reviewers + merge_request.assignees
-
- ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, users: users.uniq).execute
- end
-
- def remove_attention_requested(merge_request)
- return unless current_user.mr_attention_requests_enabled?
-
- ::MergeRequests::RemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: current_user).execute
- end
-
def bulk_update_assignees_state(merge_request, new_assignees)
return unless current_user.mr_attention_requests_enabled?
return if new_assignees.empty?
diff --git a/app/services/merge_requests/bulk_remove_attention_requested_service.rb b/app/services/merge_requests/bulk_remove_attention_requested_service.rb
deleted file mode 100644
index 774f2c2ee35..00000000000
--- a/app/services/merge_requests/bulk_remove_attention_requested_service.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequests
- class BulkRemoveAttentionRequestedService < MergeRequests::BaseService
- attr_accessor :merge_request
- attr_accessor :users
-
- def initialize(project:, current_user:, merge_request:, users:)
- super(project: project, current_user: current_user)
-
- @merge_request = merge_request
- @users = users
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def execute
- return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
-
- merge_request.merge_request_assignees.where(user_id: users).update_all(state: :reviewed)
- merge_request.merge_request_reviewers.where(user_id: users).update_all(state: :reviewed)
-
- users.each { |user| user.invalidate_attention_requested_count }
-
- success
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
-end
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index e9b253129b4..f83b14c7269 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -17,7 +17,6 @@ module MergeRequests
create_note(merge_request)
notification_service.async.close_mr(merge_request, current_user)
todo_service.close_merge_request(merge_request, current_user)
- remove_all_attention_requests(merge_request)
execute_hooks(merge_request, 'close')
invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
diff --git a/app/services/merge_requests/create_approval_event_service.rb b/app/services/merge_requests/create_approval_event_service.rb
new file mode 100644
index 00000000000..1678bf31139
--- /dev/null
+++ b/app/services/merge_requests/create_approval_event_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CreateApprovalEventService < MergeRequests::BaseService
+ def execute(merge_request)
+ event_service.approve_mr(merge_request, current_user)
+ end
+ end
+end
+
+MergeRequests::CreateApprovalEventService.prepend_mod
diff --git a/app/services/merge_requests/create_pipeline_service.rb b/app/services/merge_requests/create_pipeline_service.rb
index c6a91a3b61e..4f20ade2a42 100644
--- a/app/services/merge_requests/create_pipeline_service.rb
+++ b/app/services/merge_requests/create_pipeline_service.rb
@@ -50,7 +50,8 @@ module MergeRequests
end
def can_create_pipeline_in_target_project?(merge_request)
- can?(current_user, :create_pipeline, merge_request.target_project) &&
+ merge_request.target_project.ci_allow_fork_pipelines_to_run_in_parent_project? &&
+ can?(current_user, :create_pipeline, merge_request.target_project) &&
can_update_source_branch_in_target_project?(merge_request)
end
diff --git a/app/services/merge_requests/execute_approval_hooks_service.rb b/app/services/merge_requests/execute_approval_hooks_service.rb
new file mode 100644
index 00000000000..7beeb9ea3f9
--- /dev/null
+++ b/app/services/merge_requests/execute_approval_hooks_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ExecuteApprovalHooksService < MergeRequests::BaseService
+ def execute(merge_request)
+ # Only one approval is required for a merge request to be approved
+ notification_service.async.approve_mr(merge_request, current_user)
+ execute_hooks(merge_request, 'approved')
+ end
+ end
+end
+
+MergeRequests::ExecuteApprovalHooksService.prepend_mod
diff --git a/app/services/merge_requests/handle_assignees_change_service.rb b/app/services/merge_requests/handle_assignees_change_service.rb
index 78c93d10f2a..87cd6544406 100644
--- a/app/services/merge_requests/handle_assignees_change_service.rb
+++ b/app/services/merge_requests/handle_assignees_change_service.rb
@@ -22,10 +22,6 @@ module MergeRequests
merge_request_activity_counter.track_assignees_changed_action(user: current_user)
execute_assignees_hooks(merge_request, old_assignees) if options[:execute_hooks]
-
- unless new_assignees.include?(current_user)
- remove_attention_requested(merge_request)
- end
end
private
diff --git a/app/services/merge_requests/mergeability/check_base_service.rb b/app/services/merge_requests/mergeability/check_base_service.rb
index d5ddcb4b828..e614a7c27fe 100644
--- a/app/services/merge_requests/mergeability/check_base_service.rb
+++ b/app/services/merge_requests/mergeability/check_base_service.rb
@@ -24,12 +24,12 @@ module MergeRequests
private
- def success(*args)
- Gitlab::MergeRequests::Mergeability::CheckResult.success(*args)
+ def success(**args)
+ Gitlab::MergeRequests::Mergeability::CheckResult.success(payload: args)
end
- def failure(*args)
- Gitlab::MergeRequests::Mergeability::CheckResult.failed(*args)
+ def failure(**args)
+ Gitlab::MergeRequests::Mergeability::CheckResult.failed(payload: args)
end
end
end
diff --git a/app/services/merge_requests/mergeability/check_broken_status_service.rb b/app/services/merge_requests/mergeability/check_broken_status_service.rb
index 9a54a4292c8..6fe4eb4a57f 100644
--- a/app/services/merge_requests/mergeability/check_broken_status_service.rb
+++ b/app/services/merge_requests/mergeability/check_broken_status_service.rb
@@ -4,7 +4,7 @@ module MergeRequests
class CheckBrokenStatusService < CheckBaseService
def execute
if merge_request.broken?
- failure
+ failure(reason: failure_reason)
else
success
end
@@ -17,6 +17,12 @@ module MergeRequests
def cacheable?
false
end
+
+ private
+
+ def failure_reason
+ :broken_status
+ end
end
end
end
diff --git a/app/services/merge_requests/mergeability/check_ci_status_service.rb b/app/services/merge_requests/mergeability/check_ci_status_service.rb
index c0ef5ba1c30..9e09b513c57 100644
--- a/app/services/merge_requests/mergeability/check_ci_status_service.rb
+++ b/app/services/merge_requests/mergeability/check_ci_status_service.rb
@@ -6,7 +6,7 @@ module MergeRequests
if merge_request.mergeable_ci_state?
success
else
- failure
+ failure(reason: failure_reason)
end
end
@@ -17,6 +17,12 @@ module MergeRequests
def cacheable?
false
end
+
+ private
+
+ def failure_reason
+ :ci_must_pass
+ end
end
end
end
diff --git a/app/services/merge_requests/mergeability/check_discussions_status_service.rb b/app/services/merge_requests/mergeability/check_discussions_status_service.rb
index 9b4eab9d399..3421d96e8ae 100644
--- a/app/services/merge_requests/mergeability/check_discussions_status_service.rb
+++ b/app/services/merge_requests/mergeability/check_discussions_status_service.rb
@@ -6,7 +6,7 @@ module MergeRequests
if merge_request.mergeable_discussions_state?
success
else
- failure
+ failure(reason: failure_reason)
end
end
@@ -17,6 +17,12 @@ module MergeRequests
def cacheable?
false
end
+
+ private
+
+ def failure_reason
+ :discussions_not_resolved
+ end
end
end
end
diff --git a/app/services/merge_requests/mergeability/check_draft_status_service.rb b/app/services/merge_requests/mergeability/check_draft_status_service.rb
index bc940e2116d..a1524317155 100644
--- a/app/services/merge_requests/mergeability/check_draft_status_service.rb
+++ b/app/services/merge_requests/mergeability/check_draft_status_service.rb
@@ -5,7 +5,7 @@ module MergeRequests
class CheckDraftStatusService < CheckBaseService
def execute
if merge_request.draft?
- failure
+ failure(reason: failure_reason)
else
success
end
@@ -18,6 +18,12 @@ module MergeRequests
def cacheable?
false
end
+
+ private
+
+ def failure_reason
+ :draft_status
+ end
end
end
end
diff --git a/app/services/merge_requests/mergeability/check_open_status_service.rb b/app/services/merge_requests/mergeability/check_open_status_service.rb
index 361af946e3f..29f3d0d3ccb 100644
--- a/app/services/merge_requests/mergeability/check_open_status_service.rb
+++ b/app/services/merge_requests/mergeability/check_open_status_service.rb
@@ -7,7 +7,7 @@ module MergeRequests
if merge_request.open?
success
else
- failure
+ failure(reason: failure_reason)
end
end
@@ -18,6 +18,12 @@ module MergeRequests
def cacheable?
false
end
+
+ private
+
+ def failure_reason
+ :not_open
+ end
end
end
end
diff --git a/app/services/merge_requests/mergeability/run_checks_service.rb b/app/services/merge_requests/mergeability/run_checks_service.rb
index 1d4b96b3090..68f842b3322 100644
--- a/app/services/merge_requests/mergeability/run_checks_service.rb
+++ b/app/services/merge_requests/mergeability/run_checks_service.rb
@@ -10,36 +10,50 @@ module MergeRequests
end
def execute
- merge_request.mergeability_checks.each_with_object([]) do |check_class, results|
+ @results = merge_request.mergeability_checks.each_with_object([]) do |check_class, result_hash|
check = check_class.new(merge_request: merge_request, params: params)
next if check.skip?
check_result = run_check(check)
- results << check_result
+ result_hash << check_result
- break results if check_result.failed?
+ break result_hash if check_result.failed?
end
+
+ self
+ end
+
+ def success?
+ raise 'Execute needs to be called before' if results.nil?
+
+ results.all?(&:success?)
+ end
+
+ def failure_reason
+ raise 'Execute needs to be called before' if results.nil?
+
+ results.find(&:failed?)&.payload&.fetch(:reason)
end
private
- attr_reader :merge_request, :params
+ attr_reader :merge_request, :params, :results
def run_check(check)
return check.execute unless Feature.enabled?(:mergeability_caching, merge_request.project)
return check.execute unless check.cacheable?
- cached_result = results.read(merge_check: check)
+ cached_result = cached_results.read(merge_check: check)
return cached_result if cached_result.respond_to?(:status)
check.execute.tap do |result|
- results.write(merge_check: check, result_hash: result.to_hash)
+ cached_results.write(merge_check: check, result_hash: result.to_hash)
end
end
- def results
- strong_memoize(:results) do
+ def cached_results
+ strong_memoize(:cached_results) do
Gitlab::MergeRequests::Mergeability::ResultsStore.new(merge_request: merge_request)
end
end
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
index 30531fcc17b..1ce44f465cd 100644
--- a/app/services/merge_requests/mergeability_check_service.rb
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -78,8 +78,8 @@ module MergeRequests
lease_key = "mergeability_check:#{merge_request.id}"
lease_opts = {
- ttl: 1.minute,
- retries: retry_lease ? 10 : 0,
+ ttl: 1.minute,
+ retries: retry_lease ? 10 : 0,
sleep_sec: retry_lease ? 1.second : 0
}
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index 286c082ac8a..9fca2b0d19e 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -28,7 +28,6 @@ module MergeRequests
notification_service.merge_mr(merge_request, current_user)
invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
- remove_all_attention_requests(merge_request)
delete_non_latest_diffs(merge_request)
cancel_review_app_jobs!(merge_request)
cleanup_environments(merge_request)
diff --git a/app/services/merge_requests/push_options_handler_service.rb b/app/services/merge_requests/push_options_handler_service.rb
index 076fe8c3b21..ef251f121ae 100644
--- a/app/services/merge_requests/push_options_handler_service.rb
+++ b/app/services/merge_requests/push_options_handler_service.rb
@@ -105,7 +105,7 @@ module MergeRequests
project: project,
current_user: current_user,
params: merge_request.attributes.merge(assignees: merge_request.assignees,
- label_ids: merge_request.label_ids)
+ label_ids: merge_request.label_ids)
).execute
end
diff --git a/app/services/merge_requests/remove_approval_service.rb b/app/services/merge_requests/remove_approval_service.rb
index d9bb17a7b1b..52628729519 100644
--- a/app/services/merge_requests/remove_approval_service.rb
+++ b/app/services/merge_requests/remove_approval_service.rb
@@ -17,7 +17,6 @@ module MergeRequests
reset_approvals_cache(merge_request)
create_note(merge_request)
merge_request_activity_counter.track_unapprove_mr_action(user: current_user)
- remove_attention_requested(merge_request)
end
success
diff --git a/app/services/merge_requests/remove_attention_requested_service.rb b/app/services/merge_requests/remove_attention_requested_service.rb
deleted file mode 100644
index 8a410fda691..00000000000
--- a/app/services/merge_requests/remove_attention_requested_service.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequests
- class RemoveAttentionRequestedService < MergeRequests::BaseService
- attr_accessor :merge_request, :user
-
- def initialize(project:, current_user:, merge_request:, user:)
- super(project: project, current_user: current_user)
-
- @merge_request = merge_request
- @user = user
- end
-
- def execute
- return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
-
- if reviewer || assignee
- return success if reviewer&.reviewed? || assignee&.reviewed?
-
- update_state(reviewer)
- update_state(assignee)
-
- user.invalidate_attention_requested_count
- create_remove_attention_request_note
-
- success
- else
- error("User is not a reviewer or assignee of the merge request")
- end
- end
-
- private
-
- def assignee
- @assignee ||= merge_request.find_assignee(user)
- end
-
- def reviewer
- @reviewer ||= merge_request.find_reviewer(user)
- end
-
- def update_state(reviewer_or_assignee)
- reviewer_or_assignee&.update(state: :reviewed)
- end
-
- def create_remove_attention_request_note
- SystemNoteService.remove_attention_request(merge_request, merge_request.project, current_user, user)
- end
- end
-end
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index 4612688f78b..d2247a6d4c1 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -20,8 +20,6 @@ module MergeRequests
merge_request.cache_merge_request_closes_issues!(current_user)
merge_request.cleanup_schedule&.destroy
merge_request.update_column(:merge_ref_sha, nil)
-
- users.each { |user| user.invalidate_attention_requested_count }
end
merge_request
diff --git a/app/services/merge_requests/request_attention_service.rb b/app/services/merge_requests/request_attention_service.rb
deleted file mode 100644
index 07e9996f87b..00000000000
--- a/app/services/merge_requests/request_attention_service.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequests
- class RequestAttentionService < MergeRequests::BaseService
- attr_accessor :merge_request, :user
-
- def initialize(project:, current_user:, merge_request:, user:)
- super(project: project, current_user: current_user)
-
- @merge_request = merge_request
- @user = user
- end
-
- def execute
- return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
-
- if reviewer || assignee
- return success if reviewer&.attention_requested? || assignee&.attention_requested?
-
- update_state(reviewer)
- update_state(assignee)
-
- user.invalidate_attention_requested_count
- create_attention_request_note
- notity_user
-
- if current_user.id != user.id
- remove_attention_requested(merge_request)
- end
-
- success
- else
- error("User is not a reviewer or assignee of the merge request")
- end
- end
-
- private
-
- def notity_user
- notification_service.async.attention_requested_of_merge_request(merge_request, current_user, user)
- todo_service.create_attention_requested_todo(merge_request, current_user, user)
- end
-
- def create_attention_request_note
- SystemNoteService.request_attention(merge_request, merge_request.project, current_user, user)
- end
-
- def assignee
- @assignee ||= merge_request.find_assignee(user)
- end
-
- def reviewer
- @reviewer ||= merge_request.find_reviewer(user)
- end
-
- def update_state(reviewer_or_assignee)
- reviewer_or_assignee&.update(state: :attention_requested, updated_state_by: current_user)
- end
- end
-end
diff --git a/app/services/merge_requests/toggle_attention_requested_service.rb b/app/services/merge_requests/toggle_attention_requested_service.rb
deleted file mode 100644
index 64cdcd725a2..00000000000
--- a/app/services/merge_requests/toggle_attention_requested_service.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-module MergeRequests
- class ToggleAttentionRequestedService < MergeRequests::BaseService
- attr_accessor :merge_request, :user
-
- def initialize(project:, current_user:, merge_request:, user:)
- super(project: project, current_user: current_user)
-
- @merge_request = merge_request
- @user = user
- end
-
- def execute
- return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
-
- if reviewer || assignee
- update_state(reviewer)
- update_state(assignee)
-
- user.invalidate_attention_requested_count
-
- if reviewer&.attention_requested? || assignee&.attention_requested?
- create_attention_request_note
- notity_user
-
- if current_user.id != user.id
- remove_attention_requested(merge_request)
- end
- else
- create_remove_attention_request_note
- end
-
- success
- else
- error("User is not a reviewer or assignee of the merge request")
- end
- end
-
- private
-
- def notity_user
- notification_service.async.attention_requested_of_merge_request(merge_request, current_user, user)
- todo_service.create_attention_requested_todo(merge_request, current_user, user)
- end
-
- def create_attention_request_note
- SystemNoteService.request_attention(merge_request, merge_request.project, current_user, user)
- end
-
- def create_remove_attention_request_note
- SystemNoteService.remove_attention_request(merge_request, merge_request.project, current_user, user)
- end
-
- def assignee
- merge_request.find_assignee(user)
- end
-
- def reviewer
- merge_request.find_reviewer(user)
- end
-
- def update_state(reviewer_or_assignee)
- reviewer_or_assignee&.update(state: reviewer_or_assignee&.attention_requested? ? :reviewed : :attention_requested,
- updated_state_by: current_user)
- end
- end
-end
diff --git a/app/services/merge_requests/update_assignees_service.rb b/app/services/merge_requests/update_assignees_service.rb
index 5b23f69ac4a..a6b0235c525 100644
--- a/app/services/merge_requests/update_assignees_service.rb
+++ b/app/services/merge_requests/update_assignees_service.rb
@@ -11,7 +11,7 @@ module MergeRequests
old_assignees = merge_request.assignees.to_a
old_ids = old_assignees.map(&:id)
- new_ids = new_assignee_ids(merge_request)
+ new_ids = new_user_ids(merge_request, update_attrs[:assignee_ids], :assignees)
return merge_request if merge_request.errors.any?
return merge_request if new_ids.size != update_attrs[:assignee_ids].size
@@ -32,27 +32,8 @@ module MergeRequests
private
- def new_assignee_ids(merge_request)
- # prime the cache - prevent N+1 lookup during authorization loop.
- user_ids = update_attrs[:assignee_ids]
- return [] if user_ids.empty?
-
- merge_request.project.team.max_member_access_for_user_ids(user_ids)
- User.id_in(user_ids).map do |user|
- if user.can?(:read_merge_request, merge_request)
- user.id
- else
- merge_request.errors.add(
- :assignees,
- "Cannot assign #{user.to_reference} to #{merge_request.to_reference}"
- )
- nil
- end
- end.compact
- end
-
def assignee_ids
- params.fetch(:assignee_ids).reject { _1 == 0 }.first(1)
+ filter_sentinel_values(params.fetch(:assignee_ids)).first(1)
end
def params
diff --git a/app/services/merge_requests/update_reviewers_service.rb b/app/services/merge_requests/update_reviewers_service.rb
new file mode 100644
index 00000000000..8e974d75676
--- /dev/null
+++ b/app/services/merge_requests/update_reviewers_service.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class UpdateReviewersService < UpdateService
+ def execute(merge_request)
+ return merge_request unless current_user&.can?(:update_merge_request, merge_request)
+
+ old_reviewers = merge_request.reviewers.to_a
+ old_ids = old_reviewers.map(&:id)
+ new_ids = new_user_ids(merge_request, update_attrs[:reviewer_ids], :reviewers)
+
+ return merge_request if merge_request.errors.any?
+ return merge_request if new_ids.size != update_attrs[:reviewer_ids].size
+ return merge_request if old_ids.to_set == new_ids.to_set # no-change
+
+ merge_request.update!(update_attrs.merge(reviewer_ids: new_ids))
+ handle_reviewers_change(merge_request, old_reviewers)
+ resolve_todos_for(merge_request)
+ execute_reviewers_hooks(merge_request, old_reviewers)
+
+ merge_request
+ end
+
+ private
+
+ def reviewer_ids
+ filter_sentinel_values(params.fetch(:reviewer_ids)).first(1)
+ end
+
+ def update_attrs
+ @attrs ||= { updated_by: current_user, reviewer_ids: reviewer_ids }
+ end
+
+ def execute_reviewers_hooks(merge_request, old_reviewers)
+ execute_hooks(
+ merge_request,
+ 'update',
+ old_associations: { reviewers: old_reviewers }
+ )
+ end
+ end
+end
+
+MergeRequests::UpdateReviewersService.prepend_mod
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 603da4ef535..0902b5195a1 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -155,11 +155,7 @@ module MergeRequests
def resolve_todos(merge_request, old_labels, old_assignees, old_reviewers)
return unless has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers)
- service_user = current_user
-
- merge_request.run_after_commit_or_now do
- ::MergeRequests::ResolveTodosService.new(merge_request, service_user).async_execute
- end
+ resolve_todos_for(merge_request)
end
def handle_target_branch_change(merge_request)
@@ -296,6 +292,36 @@ module MergeRequests
def add_time_spent_service
@add_time_spent_service ||= ::MergeRequests::AddSpentTimeService.new(project: project, current_user: current_user, params: params)
end
+
+ def new_user_ids(merge_request, user_ids, attribute)
+ # prime the cache - prevent N+1 lookup during authorization loop.
+ return [] if user_ids.empty?
+
+ merge_request.project.team.max_member_access_for_user_ids(user_ids)
+ User.id_in(user_ids).map do |user|
+ if user.can?(:read_merge_request, merge_request)
+ user.id
+ else
+ merge_request.errors.add(
+ attribute,
+ "Cannot assign #{user.to_reference} to #{merge_request.to_reference}"
+ )
+ nil
+ end
+ end.compact
+ end
+
+ def resolve_todos_for(merge_request)
+ service_user = current_user
+
+ merge_request.run_after_commit_or_now do
+ ::MergeRequests::ResolveTodosService.new(merge_request, service_user).async_execute
+ end
+ end
+
+ def filter_sentinel_values(param)
+ param.reject { _1 == 0 }
+ end
end
end
diff --git a/app/services/notes/build_service.rb b/app/services/notes/build_service.rb
index 8c250526efc..cc5c81cf280 100644
--- a/app/services/notes/build_service.rb
+++ b/app/services/notes/build_service.rb
@@ -16,6 +16,14 @@ module Notes
params.merge!(discussion.reply_attributes)
end
+ # The `confidential` param for notes is deprecated with 15.3
+ # and renamed to `internal`.
+ # We still accept `confidential` until the param gets removed from the API.
+ # Until we have not migrated the database column to `internal` we need to rename
+ # the parameter. Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/367923.
+ params[:confidential] = params[:internal] || params[:confidential]
+ params.delete(:internal)
+
new_note(params, discussion)
end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 4074b1d1182..b7e6a50fa5c 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -88,8 +88,13 @@ module Notes
return if quick_actions_service.commands_executed_count.to_i == 0
if update_params.present?
- quick_actions_service.apply_updates(update_params, note)
- note.commands_changes = update_params
+ if check_for_reviewer_validity(message, update_params)
+ 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
# We must add the error after we call #save because errors are reset
@@ -109,6 +114,18 @@ module Notes
}
end
+ def check_for_reviewer_validity(message, update_params)
+ return true 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
+ end
+
+ true
+ end
+
def track_event(note, user)
track_note_creation_usage_for_issues(note) if note.for_issue?
track_note_creation_usage_for_merge_requests(note) if note.for_merge_request?
@@ -130,7 +147,8 @@ module Notes
end
def track_note_creation_usage_for_issues(note)
- Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_added_action(author: note.author)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_added_action(author: note.author,
+ project: project)
end
def track_note_creation_usage_for_merge_requests(note)
diff --git a/app/services/notes/destroy_service.rb b/app/services/notes/destroy_service.rb
index c25b1ab0379..eda8bbcbc2e 100644
--- a/app/services/notes/destroy_service.rb
+++ b/app/services/notes/destroy_service.rb
@@ -15,7 +15,8 @@ module Notes
private
def track_note_removal_usage_for_issues(note)
- Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_removed_action(author: note.author)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_removed_action(author: note.author,
+ project: project)
end
def track_note_removal_usage_for_merge_requests(note)
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index 04fc4c7c944..2dae76feb0b 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -86,7 +86,8 @@ module Notes
end
def track_note_edit_usage_for_issues(note)
- Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_edited_action(author: note.author)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_comment_edited_action(author: note.author,
+ project: project)
end
def track_note_edit_usage_for_merge_requests(note)
diff --git a/app/services/notification_recipients/build_service.rb b/app/services/notification_recipients/build_service.rb
index e63e19e365c..bdeebc641b8 100644
--- a/app/services/notification_recipients/build_service.rb
+++ b/app/services/notification_recipients/build_service.rb
@@ -36,9 +36,5 @@ module NotificationRecipients
def self.build_requested_review_recipients(*args)
::NotificationRecipients::Builder::RequestReview.new(*args).notification_recipients
end
-
- def self.build_attention_requested_recipients(*args)
- ::NotificationRecipients::Builder::AttentionRequested.new(*args).notification_recipients
- end
end
end
diff --git a/app/services/notification_recipients/builder/attention_requested.rb b/app/services/notification_recipients/builder/attention_requested.rb
deleted file mode 100644
index cdc371fcece..00000000000
--- a/app/services/notification_recipients/builder/attention_requested.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module NotificationRecipients
- module Builder
- class AttentionRequested < Base
- attr_reader :merge_request, :current_user, :user
-
- def initialize(merge_request, current_user, user)
- @merge_request = merge_request
- @current_user = current_user
- @user = user
- end
-
- def target
- merge_request
- end
-
- def build!
- add_recipients(user, :mention, NotificationReason::ATTENTION_REQUESTED)
- end
- end
- end
-end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 2477fcd02e5..5a92adfd25a 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -333,14 +333,6 @@ class NotificationService
end
end
- def attention_requested_of_merge_request(merge_request, current_user, user)
- recipients = NotificationRecipients::BuildService.build_attention_requested_recipients(merge_request, current_user, user)
-
- recipients.each do |recipient|
- mailer.attention_requested_merge_request_email(recipient.user.id, merge_request.id, current_user.id, recipient.reason).deliver_later
- end
- end
-
# When we add labels to a merge request we should send an email to:
#
# * watchers of the mr's labels
@@ -799,7 +791,7 @@ class NotificationService
end
recipients = NotificationRecipients::BuildService.build_recipients(target, current_user, action: "new")
- recipients = recipients.select {|r| new_mentioned_users.include?(r.user) }
+ recipients = recipients.select { |r| new_mentioned_users.include?(r.user) }
recipients.each do |recipient|
mailer.send(method, recipient.user.id, target.id, current_user.id, recipient.reason).deliver_later
diff --git a/app/services/packages/conan/create_package_file_service.rb b/app/services/packages/conan/create_package_file_service.rb
index 1bde9606492..904a1d10bcb 100644
--- a/app/services/packages/conan/create_package_file_service.rb
+++ b/app/services/packages/conan/create_package_file_service.rb
@@ -13,11 +13,11 @@ module Packages
def execute
package_file = package.package_files.build(
- file: file,
- size: params['file.size'],
+ file: file,
+ size: params['file.size'],
file_name: params[:file_name],
file_sha1: params['file.sha1'],
- file_md5: params['file.md5'],
+ file_md5: params['file.md5'],
conan_file_metadatum_attributes: {
recipe_revision: params[:recipe_revision],
package_revision: params[:package_revision],
diff --git a/app/services/packages/create_package_file_service.rb b/app/services/packages/create_package_file_service.rb
index 5723b0b4717..6e1a5672a52 100644
--- a/app/services/packages/create_package_file_service.rb
+++ b/app/services/packages/create_package_file_service.rb
@@ -10,12 +10,12 @@ module Packages
def execute
package_file = package.package_files.build(
- file: params[:file],
- size: params[:size],
- file_name: params[:file_name],
- file_sha1: params[:file_sha1],
+ file: params[:file],
+ size: params[:size],
+ file_name: params[:file_name],
+ file_sha1: params[:file_sha1],
file_sha256: params[:file_sha256],
- file_md5: params[:file_md5]
+ file_md5: params[:file_md5]
)
if params[:build].present?
diff --git a/app/services/packages/debian/create_package_file_service.rb b/app/services/packages/debian/create_package_file_service.rb
index fbbc8159ca0..53275fdc9bb 100644
--- a/app/services/packages/debian/create_package_file_service.rb
+++ b/app/services/packages/debian/create_package_file_service.rb
@@ -17,12 +17,12 @@ module Packages
# Debian package file are first uploaded to incoming with empty metadata,
# and are moved later by Packages::Debian::ProcessChangesService
package.package_files.create!(
- file: params[:file],
- size: params[:file]&.size,
- file_name: params[:file_name],
- file_sha1: params[:file_sha1],
+ file: params[:file],
+ size: params[:file]&.size,
+ file_name: params[:file_name],
+ file_sha1: params[:file_sha1],
file_sha256: params[:file]&.sha256,
- file_md5: params[:file_md5],
+ file_md5: params[:file_md5],
debian_file_metadatum_attributes: {
file_type: 'unknown',
architecture: nil,
diff --git a/app/services/packages/debian/extract_metadata_service.rb b/app/services/packages/debian/extract_metadata_service.rb
index f94587919b9..eb8227d1296 100644
--- a/app/services/packages/debian/extract_metadata_service.rb
+++ b/app/services/packages/debian/extract_metadata_service.rb
@@ -61,12 +61,12 @@ module Packages
def fields
strong_memoize(:fields) do
if file_type_debian?
- package_file.file.use_file do |file_path|
- ::Packages::Debian::ExtractDebMetadataService.new(file_path).execute
+ package_file.file.use_open_file(unlink_early: false) do |file|
+ ::Packages::Debian::ExtractDebMetadataService.new(file.file_path).execute
end
elsif file_type_meta?
- package_file.file.use_file do |file_path|
- ::Packages::Debian::ParseDebian822Service.new(File.read(file_path)).execute.each_value.first
+ package_file.file.use_open_file do |file|
+ ::Packages::Debian::ParseDebian822Service.new(file.read).execute.each_value.first
end
end
end
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index b0a5f37cfa3..a3596314199 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -87,11 +87,11 @@ module Packages
def file_params
{
- file: CarrierWaveStringFile.new(Base64.decode64(attachment['data'])),
- size: calculated_package_file_size,
+ file: CarrierWaveStringFile.new(Base64.decode64(attachment['data'])),
+ size: calculated_package_file_size,
file_sha1: version_data[:dist][:shasum],
file_name: package_file_name,
- build: params[:build]
+ build: params[:build]
}
end
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index e5d40b60747..c21a61bcb52 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -32,7 +32,7 @@ module Projects
attr_reader :project, :payload, :integration
def valid_payload_size?
- Gitlab::Utils::DeepSize.new(payload).valid?
+ Gitlab::Utils::DeepSize.new(payload.to_h).valid?
end
override :alert_source
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 9bc8bb428fb..6381ee67ce7 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -26,7 +26,7 @@ module Projects
return ::Projects::CreateFromTemplateService.new(current_user, params).execute
end
- @project = Project.new(params)
+ @project = Project.new(params.merge(creator: current_user))
validate_import_source_enabled!
@@ -45,20 +45,14 @@ module Projects
set_project_name_from_path
# get namespace id
- namespace_id = params[:namespace_id]
-
- if namespace_id
- # Find matching namespace and check if it allowed
- # for current user if namespace_id passed.
- unless current_user.can?(:create_projects, parent_namespace)
- @project.namespace_id = nil
- deny_namespace
- return @project
- end
- else
- # Set current user namespace if namespace_id is nil
- @project.namespace_id = current_user.namespace_id
- end
+ namespace_id = params[:namespace_id] || current_user.namespace_id
+ @project.namespace_id = namespace_id.to_i
+
+ @project.check_personal_projects_limit
+ return @project if @project.errors.any?
+
+ validate_create_permissions
+ return @project if @project.errors.any?
@relations_block&.call(@project)
yield(@project) if block_given?
@@ -92,7 +86,9 @@ module Projects
protected
- def deny_namespace
+ def validate_create_permissions
+ return if current_user.can?(:create_projects, parent_namespace)
+
@project.errors.add(:namespace, "is not valid")
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 70a04cd556a..5fce816064b 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -46,15 +46,15 @@ module Projects
def new_fork_params
new_params = {
- forked_from_project: @project,
- visibility_level: target_visibility_level,
- description: target_description,
- name: target_name,
- path: target_path,
- shared_runners_enabled: @project.shared_runners_enabled,
- namespace_id: target_namespace.id,
- fork_network: fork_network,
- ci_config_path: @project.ci_config_path,
+ forked_from_project: @project,
+ visibility_level: target_visibility_level,
+ description: target_description,
+ name: target_name,
+ path: target_path,
+ shared_runners_enabled: @project.shared_runners_enabled,
+ namespace_id: target_namespace.id,
+ fork_network: fork_network,
+ ci_config_path: @project.ci_config_path,
# We need to set ci_default_git_depth to 0 for the forked project when
# @project.ci_default_git_depth is nil in order to keep the same behaviour
# and not get ProjectCiCdSetting::DEFAULT_GIT_DEPTH set on create
@@ -63,8 +63,8 @@ module Projects
# been instantiated to avoid ActiveRecord trying to create it when
# initializing the project, as that would cause a foreign key constraint
# exception.
- relations_block: -> (project) { build_fork_network_member(project) },
- skip_disk_validation: skip_disk_validation,
+ relations_block: -> (project) { build_fork_network_member(project) },
+ skip_disk_validation: skip_disk_validation,
external_authorization_classification_label: @project.external_authorization_classification_label,
suggestion_commit_message: @project.suggestion_commit_message,
merge_commit_template: @project.merge_commit_template,
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index d8d35422590..ddbcfbb675c 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -54,15 +54,21 @@ module Projects
end
def save_all!
+ log_info('Project export started')
+
if save_exporters && save_export_archive
- notify_success
+ log_info('Project successfully exported')
else
notify_error!
end
end
def save_exporters
- exporters.all?(&:save)
+ exporters.all? do |exporter|
+ log_info("#{exporter.class.name} saver started")
+
+ exporter.save
+ end
end
def save_export_archive
@@ -78,11 +84,12 @@ module Projects
end
def project_tree_saver
- @project_tree_saver ||= tree_saver_class.new(project: project,
- current_user: current_user,
- shared: shared,
- params: params,
- logger: logger)
+ @project_tree_saver ||= tree_saver_class.new(
+ project: project,
+ current_user: current_user,
+ shared: shared,
+ params: params,
+ logger: logger)
end
def tree_saver_class
@@ -127,11 +134,10 @@ module Projects
raise Gitlab::ImportExport::Error, shared.errors.to_sentence
end
- def notify_success
+ def log_info(message)
logger.info(
- message: 'Project successfully exported',
- project_name: project.name,
- project_id: project.id
+ message: message,
+ **log_base_data
)
end
@@ -139,8 +145,7 @@ module Projects
logger.error(
message: 'Project export error',
export_errors: shared.errors.join(', '),
- project_name: project.name,
- project_id: project.id
+ **log_base_data
)
user = current_user
@@ -150,6 +155,10 @@ module Projects
NotificationService.new.project_not_exported(project, user, errors)
end
end
+
+ def log_base_data
+ @log_base_data ||= Gitlab::ImportExport::LogUtil.exportable_to_log_payload(project)
+ end
end
end
end
diff --git a/app/services/projects/import_export/relation_export_service.rb b/app/services/projects/import_export/relation_export_service.rb
new file mode 100644
index 00000000000..dce40cf18ba
--- /dev/null
+++ b/app/services/projects/import_export/relation_export_service.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module Projects
+ module ImportExport
+ class RelationExportService
+ include Gitlab::ImportExport::CommandLineUtil
+
+ def initialize(relation_export, jid)
+ @relation_export = relation_export
+ @jid = jid
+ @logger = Gitlab::Export::Logger.build
+ end
+
+ def execute
+ relation_export.update!(status_event: :start, jid: jid)
+
+ mkdir_p(shared.export_path)
+ mkdir_p(shared.archive_path)
+
+ if relation_saver.save
+ compress_export_path
+ upload_compressed_file
+ relation_export.finish!
+ else
+ fail_export(shared.errors.join(', '))
+ end
+ rescue StandardError => e
+ fail_export(e.message)
+ ensure
+ FileUtils.remove_entry(shared.export_path) if File.exist?(shared.export_path)
+ FileUtils.remove_entry(shared.archive_path) if File.exist?(shared.archive_path)
+ end
+
+ private
+
+ attr_reader :relation_export, :jid, :logger
+
+ delegate :relation, :project_export_job, to: :relation_export
+ delegate :project, to: :project_export_job
+
+ def shared
+ project.import_export_shared
+ end
+
+ def relation_saver
+ case relation
+ when Projects::ImportExport::RelationExport::UPLOADS_RELATION
+ Gitlab::ImportExport::UploadsSaver.new(project: project, shared: shared)
+ when Projects::ImportExport::RelationExport::REPOSITORY_RELATION
+ Gitlab::ImportExport::RepoSaver.new(exportable: project, shared: shared)
+ when Projects::ImportExport::RelationExport::WIKI_REPOSITORY_RELATION
+ Gitlab::ImportExport::WikiRepoSaver.new(exportable: project, shared: shared)
+ when Projects::ImportExport::RelationExport::LFS_OBJECTS_RELATION
+ Gitlab::ImportExport::LfsSaver.new(project: project, shared: shared)
+ when Projects::ImportExport::RelationExport::SNIPPETS_REPOSITORY_RELATION
+ Gitlab::ImportExport::SnippetsRepoSaver.new(project: project, shared: shared, current_user: nil)
+ when Projects::ImportExport::RelationExport::DESIGN_REPOSITORY_RELATION
+ Gitlab::ImportExport::DesignRepoSaver.new(exportable: project, shared: shared)
+ else
+ Gitlab::ImportExport::Project::RelationSaver.new(
+ project: project,
+ shared: shared,
+ relation: relation
+ )
+ end
+ end
+
+ def upload_compressed_file
+ upload = relation_export.build_upload
+ File.open(archive_file_full_path) { |file| upload.export_file = file }
+ upload.save!
+ end
+
+ def compress_export_path
+ tar_czf(archive: archive_file_full_path, dir: shared.export_path)
+ end
+
+ def archive_file_full_path
+ @archive_file ||= File.join(shared.archive_path, "#{relation}.tar.gz")
+ end
+
+ def fail_export(error_message)
+ relation_export.update!(status_event: :fail_op, export_error: error_message.truncate(300))
+
+ logger.error(
+ message: 'Project relation export failed',
+ export_error: error_message,
+ project_export_job_id: project_export_job.id,
+ project_name: project.name,
+ project_id: project.id
+ )
+ end
+ end
+ end
+end
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index c032fbf1508..eaf73b78c1c 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -50,7 +50,7 @@ module Projects
def find_or_create_lfs_object(tmp_file)
lfs_obj = LfsObject.safe_find_or_create_by!(
- oid: lfs_oid,
+ oid: lfs_oid,
size: lfs_size
)
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
index bc517ee3d6f..6265a74fad2 100644
--- a/app/services/projects/prometheus/alerts/notify_service.rb
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -56,7 +56,7 @@ module Projects
attr_reader :project, :payload
def valid_payload_size?
- Gitlab::Utils::DeepSize.new(payload).valid?
+ Gitlab::Utils::DeepSize.new(payload.to_h).valid?
end
def max_alerts_exceeded?
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 666227951c6..3cb5a564ba5 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -121,6 +121,8 @@ module Projects
# Overridden in EE
def post_update_hooks(project)
ensure_personal_project_owner_membership(project)
+
+ publish_event
end
# Overridden in EE
@@ -268,6 +270,18 @@ module Projects
CustomerRelations::IssueContact.delete_for_project(project.id)
end
+
+ def publish_event
+ event = ::Projects::ProjectTransferedEvent.new(data: {
+ project_id: project.id,
+ old_namespace_id: old_namespace.id,
+ old_root_namespace_id: old_namespace.root_ancestor.id,
+ new_namespace_id: new_namespace.id,
+ new_root_namespace_id: new_namespace.root_ancestor.id
+ })
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index 705d23ec704..f686f14b5b3 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -76,11 +76,11 @@ module Projects
if message.present?
Gitlab::AppJsonLogger.info(message: "Error synching remote mirror",
- project_id: project.id,
- project_path: project.full_path,
- remote_mirror_id: remote_mirror.id,
- lfs_sync_failed: lfs_sync_failed,
- divergent_ref_list: response.divergent_refs)
+ project_id: project.id,
+ project_path: project.full_path,
+ remote_mirror_id: remote_mirror.id,
+ lfs_sync_failed: lfs_sync_failed,
+ divergent_ref_list: response.divergent_refs)
end
[failed, message]
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 5708421014a..d757b0700b9 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -121,6 +121,8 @@ module Projects
end
update_pending_builds if runners_settings_toggled?
+
+ publish_event
end
def after_rename_service(project)
@@ -209,6 +211,18 @@ module Projects
[]
end
end
+
+ def publish_event
+ return unless project.archived_previously_changed?
+
+ event = Projects::ProjectArchivedEvent.new(data: {
+ project_id: @project.id,
+ namespace_id: @project.namespace_id,
+ root_namespace_id: @project.root_namespace.id
+ })
+
+ Gitlab::EventStore.publish(event)
+ end
end
end
diff --git a/app/services/protected_branches/base_service.rb b/app/services/protected_branches/base_service.rb
index f48e02ab4b5..d26c1b148bf 100644
--- a/app/services/protected_branches/base_service.rb
+++ b/app/services/protected_branches/base_service.rb
@@ -13,5 +13,9 @@ module ProtectedBranches
def after_execute(*)
# overridden in EE::ProtectedBranches module
end
+
+ def refresh_cache
+ CacheService.new(@project, @current_user, @params).refresh
+ end
end
end
diff --git a/app/services/protected_branches/cache_service.rb b/app/services/protected_branches/cache_service.rb
new file mode 100644
index 00000000000..8c521f4ebcb
--- /dev/null
+++ b/app/services/protected_branches/cache_service.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module ProtectedBranches
+ class CacheService < ProtectedBranches::BaseService
+ CACHE_ROOT_KEY = 'cache:gitlab:protected_branch'
+ TTL_UNSET = -1
+ CACHE_EXPIRE_IN = 1.day
+ CACHE_LIMIT = 1000
+
+ def fetch(ref_name, dry_run: false)
+ record = OpenSSL::Digest::SHA256.hexdigest(ref_name)
+
+ Gitlab::Redis::Cache.with do |redis|
+ cached_result = redis.hget(redis_key, record)
+
+ decoded_result = Gitlab::Redis::Boolean.decode(cached_result) unless cached_result.nil?
+
+ # If we're dry-running, don't break because we need to check against
+ # the real value to ensure the cache is working properly.
+ # If the result is nil we'll need to run the block, so don't break yet.
+ break decoded_result unless dry_run || decoded_result.nil?
+
+ calculated_value = yield
+
+ check_and_log_discrepancy(decoded_result, calculated_value, ref_name) if dry_run
+
+ redis.hset(redis_key, record, Gitlab::Redis::Boolean.encode(calculated_value))
+
+ # We don't want to extend cache expiration time
+ if redis.ttl(redis_key) == TTL_UNSET
+ redis.expire(redis_key, CACHE_EXPIRE_IN)
+ end
+
+ # If the cache record has too many elements, then something went wrong and
+ # it's better to drop the cache key.
+ if redis.hlen(redis_key) > CACHE_LIMIT
+ redis.unlink(redis_key)
+ end
+
+ calculated_value
+ end
+ end
+
+ def refresh
+ Gitlab::Redis::Cache.with { |redis| redis.unlink(redis_key) }
+ end
+
+ private
+
+ def check_and_log_discrepancy(cached_value, real_value, ref_name)
+ return if cached_value.nil?
+ return if cached_value == real_value
+
+ encoded_ref_name = Gitlab::EncodingHelper.encode_utf8_with_replacement_character(ref_name)
+
+ log_error(
+ 'class' => self.class.name,
+ 'message' => "Cache mismatch '#{encoded_ref_name}': cached value: #{cached_value}, real value: #{real_value}",
+ 'project_id' => @project.id,
+ 'project_path' => @project.full_path
+ )
+ end
+
+ def redis_key
+ @redis_key ||= [CACHE_ROOT_KEY, @project.id].join(':')
+ end
+ end
+end
diff --git a/app/services/protected_branches/create_service.rb b/app/services/protected_branches/create_service.rb
index dada449989a..903addf7afc 100644
--- a/app/services/protected_branches/create_service.rb
+++ b/app/services/protected_branches/create_service.rb
@@ -7,6 +7,8 @@ module ProtectedBranches
save_protected_branch
+ refresh_cache
+
protected_branch
end
diff --git a/app/services/protected_branches/destroy_service.rb b/app/services/protected_branches/destroy_service.rb
index 47332ace417..01d3b68314f 100644
--- a/app/services/protected_branches/destroy_service.rb
+++ b/app/services/protected_branches/destroy_service.rb
@@ -5,7 +5,7 @@ module ProtectedBranches
def execute(protected_branch)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_protected_branch, protected_branch)
- protected_branch.destroy
+ protected_branch.destroy.tap { refresh_cache }
end
end
end
diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb
index 1e70f2d9793..c155e0022f5 100644
--- a/app/services/protected_branches/update_service.rb
+++ b/app/services/protected_branches/update_service.rb
@@ -10,6 +10,8 @@ module ProtectedBranches
if protected_branch.update(params)
after_execute(protected_branch: protected_branch, old_merge_access_levels: old_merge_access_levels, old_push_access_levels: old_push_access_levels)
+
+ refresh_cache
end
protected_branch
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index e3134070231..2588d2187a5 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -19,10 +19,6 @@ module Releases
create_release(tag, evidence_pipeline)
end
- def find_or_build_release
- release || build_release(existing_tag)
- end
-
private
def ensure_tag
diff --git a/app/services/resource_events/change_labels_service.rb b/app/services/resource_events/change_labels_service.rb
index 03ac839c509..04f917ec8ef 100644
--- a/app/services/resource_events/change_labels_service.rb
+++ b/app/services/resource_events/change_labels_service.rb
@@ -24,6 +24,9 @@ module ResourceEvents
end
ApplicationRecord.legacy_bulk_insert(ResourceLabelEvent.table_name, labels) # rubocop:disable Gitlab/BulkInsert
+
+ create_timeline_events_from(added_labels: added_labels, removed_labels: removed_labels)
+
resource.expire_note_etag_cache
Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_label_changed_action(author: user) if resource.is_a?(Issue)
@@ -41,6 +44,17 @@ module ResourceEvents
raise ArgumentError, "Unknown resource type #{resource.class.name}"
end
end
+
+ def create_timeline_events_from(added_labels: [], removed_labels: [])
+ return unless resource.incident?
+
+ IncidentManagement::TimelineEvents::CreateService.change_labels(
+ resource,
+ user,
+ added_labels: added_labels,
+ removed_labels: removed_labels
+ )
+ end
end
end
diff --git a/app/services/security/ci_configuration/sast_parser_service.rb b/app/services/security/ci_configuration/sast_parser_service.rb
index cae9a90f0a0..16a9efcefdf 100644
--- a/app/services/security/ci_configuration/sast_parser_service.rb
+++ b/app/services/security/ci_configuration/sast_parser_service.rb
@@ -75,7 +75,11 @@ module Security
def sast_excluded_analyzers
strong_memoize(:sast_excluded_analyzers) do
excluded_analyzers = gitlab_ci_yml_attributes["SAST_EXCLUDED_ANALYZERS"] || sast_template_attributes["SAST_EXCLUDED_ANALYZERS"]
- excluded_analyzers.split(',').map(&:strip) rescue []
+ begin
+ excluded_analyzers.split(',').map(&:strip)
+ rescue StandardError
+ []
+ end
end
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index d7e4b53b5de..9de73a00eac 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -57,7 +57,7 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).unrelate_issuable(noteable_ref)
end
- # Called when the due_date of a Noteable is changed
+ # Called when the due_date or start_date of a Noteable is changed
#
# noteable - Noteable object
# project - Project owning noteable
@@ -68,11 +68,15 @@ module SystemNoteService
#
# "removed due date"
#
- # "changed due date to September 20, 2018"
+ # "changed due date to September 20, 2018 and changed start date to September 25, 2018"
#
# Returns the created Note object
- def change_due_date(noteable, project, author, due_date)
- ::SystemNotes::TimeTrackingService.new(noteable: noteable, project: project, author: author).change_due_date(due_date)
+ def change_start_date_or_due_date(noteable, project, author, changed_dates)
+ ::SystemNotes::TimeTrackingService.new(
+ noteable: noteable,
+ project: project,
+ author: author
+ ).change_start_date_or_due_date(changed_dates)
end
# Called when the estimated time of a Noteable is changed
@@ -111,6 +115,24 @@ module SystemNoteService
::SystemNotes::TimeTrackingService.new(noteable: noteable, project: project, author: author).change_time_spent
end
+ # Called when a timelog is added to an issuable
+ #
+ # issuable - Issuable object (Issue, WorkItem or MergeRequest)
+ # project - Project owning the issuable
+ # author - User performing the change
+ # timelog - Created timelog
+ #
+ # Example Note text:
+ #
+ # "subtracted 1h 15m of time spent"
+ #
+ # "added 2h 30m of time spent"
+ #
+ # Returns the created Note object
+ def created_timelog(issuable, project, author, timelog)
+ ::SystemNotes::TimeTrackingService.new(noteable: issuable, project: project, author: author).created_timelog(timelog)
+ end
+
# Called when a timelog is removed from a Noteable
#
# noteable - Noteable object
@@ -134,14 +156,6 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).change_status(status, source)
end
- def request_attention(noteable, project, author, user)
- ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).request_attention(user)
- end
-
- def remove_attention_request(noteable, project, author, user)
- ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).remove_attention_request(user)
- end
-
# Called when 'merge when pipeline succeeds' is executed
def merge_when_pipeline_succeeds(noteable, project, author, sha)
::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).merge_when_pipeline_succeeds(sha)
@@ -256,8 +270,8 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).noteable_moved(noteable_ref, direction)
end
- def noteable_cloned(noteable, project, noteable_ref, author, direction:)
- ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).noteable_cloned(noteable_ref, direction)
+ def noteable_cloned(noteable, project, noteable_ref, author, direction:, created_at: nil)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).noteable_cloned(noteable_ref, direction, created_at: created_at)
end
def mark_duplicate_issue(noteable, project, author, canonical_issue)
@@ -280,6 +294,18 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: mentioned).cross_reference_disallowed?(mentioned_in)
end
+ def relate_work_item(noteable, work_item, user)
+ ::SystemNotes::IssuablesService
+ .new(noteable: noteable, project: noteable.project, author: user)
+ .hierarchy_changed(work_item, 'relate')
+ end
+
+ def unrelate_work_item(noteable, work_item, user)
+ ::SystemNotes::IssuablesService
+ .new(noteable: noteable, project: noteable.project, author: user)
+ .hierarchy_changed(work_item, 'unrelate')
+ end
+
def zoom_link_added(issue, project, author)
::SystemNotes::ZoomService.new(noteable: issue, project: project, author: author).zoom_link_added
end
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index f9e5c3725d8..75903fde39e 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -178,6 +178,24 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
end
+ # Called when the hierarchy of a work item is changed
+ #
+ # noteable - Noteable object that responds to `work_item_parent` and `work_item_children`
+ # project - Project owning noteable
+ # author - User performing the change
+ #
+ # Example Note text:
+ #
+ # "added #1 as child Task"
+ #
+ # Returns the created Note object
+ def hierarchy_changed(work_item, action)
+ params = hierarchy_note_params(action, noteable, work_item)
+
+ create_note(NoteSummary.new(noteable, project, author, params[:parent_note_body], action: params[:parent_action]))
+ create_note(NoteSummary.new(work_item, project, author, params[:child_note_body], action: params[:child_action]))
+ end
+
# Called when the description of a Noteable is changed
#
# noteable - Noteable object that responds to `description`
@@ -255,12 +273,12 @@ module SystemNotes
#
# Example Note text:
#
- # "marked the task Whatever as completed."
+ # "marked the checklist item Whatever as completed."
#
# Returns the created Note object
def change_task_status(new_task)
status_label = new_task.complete? ? Taskable::COMPLETED : Taskable::INCOMPLETE
- body = "marked the task **#{new_task.source}** as #{status_label}"
+ body = "marked the checklist item **#{new_task.source}** as #{status_label}"
issue_activity_counter.track_issue_description_changed_action(author: author) if noteable.is_a?(Issue)
@@ -294,13 +312,14 @@ module SystemNotes
#
# noteable_ref - Referenced noteable
# direction - symbol, :to or :from
+ # created_at - timestamp for the system note, defaults to current time
#
# Example Note text:
#
# "cloned to some_namespace/project_new#11"
#
# Returns the created Note object
- def noteable_cloned(noteable_ref, direction)
+ def noteable_cloned(noteable_ref, direction, created_at: nil)
unless [:to, :from].include?(direction)
raise ArgumentError, "Invalid direction `#{direction}`"
end
@@ -308,9 +327,11 @@ module SystemNotes
cross_reference = noteable_ref.to_reference(project)
body = "cloned #{direction} #{cross_reference}"
- issue_activity_counter.track_issue_cloned_action(author: author) if noteable.is_a?(Issue) && direction == :to
+ if noteable.is_a?(Issue) && direction == :to
+ issue_activity_counter.track_issue_cloned_action(author: author, project: project)
+ end
- create_note(NoteSummary.new(noteable, project, author, body, action: 'cloned'))
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'cloned', created_at: created_at))
end
# Called when the confidentiality changes
@@ -367,36 +388,6 @@ module SystemNotes
existing_mentions_for(mentioned_in, noteable, notes).exists?
end
- # Called when a user's attention has been requested for a Notable
- #
- # user - User's whos attention has been requested
- #
- # Example Note text:
- #
- # "requested attention from @eli.wisoky"
- #
- # Returns the created Note object
- def request_attention(user)
- body = "requested attention from #{user.to_reference}"
-
- create_note(NoteSummary.new(noteable, project, author, body, action: 'attention_requested'))
- end
-
- # Called when a user's attention request has been removed for a Notable
- #
- # user - User's whos attention request has been removed
- #
- # Example Note text:
- #
- # "removed attention request from @eli.wisoky"
- #
- # Returns the created Note object
- def remove_attention_request(user)
- body = "removed attention request from #{user.to_reference}"
-
- create_note(NoteSummary.new(noteable, project, author, body, action: 'attention_request_removed'))
- end
-
# Called when a Noteable has been marked as the canonical Issue of a duplicate
#
# duplicate_issue - Issue that was a duplicate of this
@@ -506,6 +497,29 @@ module SystemNotes
def track_cross_reference_action
issue_activity_counter.track_issue_cross_referenced_action(author: author) if noteable.is_a?(Issue)
end
+
+ def hierarchy_note_params(action, parent, child)
+ return {} unless child && parent
+
+ child_type = child.issue_type.humanize(capitalize: false)
+ parent_type = parent.issue_type.humanize(capitalize: false)
+
+ if action == 'relate'
+ {
+ parent_note_body: "added #{child.to_reference} as child #{child_type}",
+ child_note_body: "added #{parent.to_reference} as parent #{parent_type}",
+ parent_action: 'relate_to_child',
+ child_action: 'relate_to_parent'
+ }
+ else
+ {
+ parent_note_body: "removed child #{child_type} #{child.to_reference}",
+ child_note_body: "removed parent #{parent_type} #{parent.to_reference}",
+ parent_action: 'unrelate_from_child',
+ child_action: 'unrelate_from_parent'
+ }
+ end
+ end
end
end
diff --git a/app/services/system_notes/time_tracking_service.rb b/app/services/system_notes/time_tracking_service.rb
index a9b1f6d3d37..68df52a03c7 100644
--- a/app/services/system_notes/time_tracking_service.rb
+++ b/app/services/system_notes/time_tracking_service.rb
@@ -2,8 +2,9 @@
module SystemNotes
class TimeTrackingService < ::SystemNotes::BaseService
- # Called when the due_date of a Noteable is changed
+ # Called when the start_date or due_date of an Issue/WorkItem is changed
#
+ # start_date - Start date being assigned, or nil
# due_date - Due date being assigned, or nil
#
# Example Note text:
@@ -11,14 +12,23 @@ module SystemNotes
# "removed due date"
#
# "changed due date to September 20, 2018"
+
+ # "changed start date to September 20, 2018 and changed due date to September 25, 2018"
#
# Returns the created Note object
- def change_due_date(due_date)
- body = due_date ? "changed due date to #{due_date.to_s(:long)}" : 'removed due date'
+ def change_start_date_or_due_date(changed_dates = {})
+ return if changed_dates.empty?
+
+ # Using instance_of because WorkItem < Issue. We don't want to track work item updates as issue updates
+ if noteable.instance_of?(Issue) && changed_dates.key?('due_date')
+ issue_activity_counter.track_issue_due_date_changed_action(author: author)
+ end
- issue_activity_counter.track_issue_due_date_changed_action(author: author) if noteable.is_a?(Issue)
+ work_item_activity_counter.track_work_item_date_changed_action(author: author) if noteable.is_a?(WorkItem)
- create_note(NoteSummary.new(noteable, project, author, body, action: 'due_date'))
+ create_note(
+ NoteSummary.new(noteable, project, author, changed_date_body(changed_dates), action: 'start_date_or_due_date')
+ )
end
# Called when the estimated time of a Noteable is changed
@@ -76,6 +86,32 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
end
+ # Called when a timelog is added to an issuable
+ #
+ # timelog - Added timelog
+ #
+ # Example Note text:
+ #
+ # "subtracted 1h 15m of time spent"
+ #
+ # "added 2h 30m of time spent"
+ #
+ # Returns the created Note object
+ def created_timelog(timelog)
+ time_spent = timelog.time_spent
+ spent_at = timelog.spent_at&.to_date
+ parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent.abs)
+ action = time_spent > 0 ? 'added' : 'subtracted'
+
+ text_parts = ["#{action} #{parsed_time} of time spent"]
+ text_parts << "at #{spent_at}" if spent_at && spent_at != DateTime.current.to_date
+ body = text_parts.join(' ')
+
+ issue_activity_counter.track_issue_time_spent_changed_action(author: author) if noteable.is_a?(Issue)
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
+ end
+
def remove_timelog(timelog)
time_spent = timelog.time_spent
spent_at = timelog.spent_at&.to_date
@@ -90,8 +126,33 @@ module SystemNotes
private
+ def changed_date_body(changed_dates)
+ %w[start_date due_date].each_with_object([]) do |date_field, word_array|
+ next unless changed_dates.key?(date_field)
+
+ word_array << 'and' if word_array.any?
+
+ word_array << message_for_changed_date(changed_dates, date_field)
+ end.join(' ')
+ end
+
+ def message_for_changed_date(changed_dates, date_key)
+ changed_date = changed_dates[date_key].last
+ readable_date = date_key.humanize.downcase
+
+ if changed_date.nil?
+ "removed #{readable_date}"
+ else
+ "changed #{readable_date} to #{changed_date.to_s(:long)}"
+ end
+ end
+
def issue_activity_counter
Gitlab::UsageDataCounters::IssueActivityUniqueCounter
end
+
+ def work_item_activity_counter
+ Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter
+ end
end
end
diff --git a/app/services/timelogs/base_service.rb b/app/services/timelogs/base_service.rb
index be46c26e047..e09264864fd 100644
--- a/app/services/timelogs/base_service.rb
+++ b/app/services/timelogs/base_service.rb
@@ -5,11 +5,26 @@ module Timelogs
include BaseServiceUtility
include Gitlab::Utils::StrongMemoize
- attr_accessor :timelog, :current_user
+ attr_accessor :current_user
- def initialize(timelog, user)
- @timelog = timelog
+ def initialize(user)
@current_user = user
end
+
+ def success(timelog)
+ ServiceResponse.success(payload: {
+ timelog: timelog
+ })
+ end
+
+ def error(message, http_status = nil)
+ ServiceResponse.error(message: message, http_status: http_status)
+ end
+
+ def error_in_save(timelog)
+ return error(_("Failed to save timelog")) if timelog.errors.empty?
+
+ error(timelog.errors.full_messages.to_sentence)
+ end
end
end
diff --git a/app/services/timelogs/create_service.rb b/app/services/timelogs/create_service.rb
new file mode 100644
index 00000000000..12181cec20a
--- /dev/null
+++ b/app/services/timelogs/create_service.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Timelogs
+ class CreateService < Timelogs::BaseService
+ attr_accessor :issuable, :time_spent, :spent_at, :summary
+
+ def initialize(issuable, time_spent, spent_at, summary, user)
+ super(user)
+
+ @issuable = issuable
+ @time_spent = time_spent
+ @spent_at = spent_at
+ @summary = summary
+ end
+
+ def execute
+ unless can?(current_user, :create_timelog, issuable)
+ return error(
+ _("%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it.") % {
+ issuable_class_name: issuable.nil? ? 'Issuable' : issuable.base_class_name
+ }, 404)
+ end
+
+ issue = issuable if issuable.is_a?(Issue)
+ merge_request = issuable if issuable.is_a?(MergeRequest)
+
+ timelog = Timelog.new(
+ time_spent: time_spent,
+ spent_at: spent_at,
+ summary: summary,
+ user: current_user,
+ issue: issue,
+ merge_request: merge_request,
+ note: nil
+ )
+
+ if !timelog.save
+ error_in_save(timelog)
+ else
+ SystemNoteService.created_timelog(issuable, issuable.project, current_user, timelog)
+ success(timelog)
+ end
+ end
+ end
+end
diff --git a/app/services/timelogs/delete_service.rb b/app/services/timelogs/delete_service.rb
index 0df888a3706..e72dfd98494 100644
--- a/app/services/timelogs/delete_service.rb
+++ b/app/services/timelogs/delete_service.rb
@@ -2,11 +2,17 @@
module Timelogs
class DeleteService < Timelogs::BaseService
+ attr_accessor :timelog
+
+ def initialize(timelog, user)
+ super(user)
+
+ @timelog = timelog
+ end
+
def execute
unless can?(current_user, :admin_timelog, timelog)
- return ServiceResponse.error(
- message: "Timelog doesn't exist or you don't have permission to delete it",
- http_status: 404)
+ return error(_("Timelog doesn't exist or you don't have permission to delete it"), 404)
end
if timelog.destroy
@@ -17,9 +23,9 @@ module Timelogs
SystemNoteService.remove_timelog(issuable, issuable.project, current_user, timelog)
end
- ServiceResponse.success(payload: timelog)
+ success(timelog)
else
- ServiceResponse.error(message: 'Failed to remove timelog', http_status: 400)
+ error(_('Failed to remove timelog'), 400)
end
end
end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 14cf264cc51..6ae394072c6 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -218,11 +218,6 @@ class TodoService
create_todos(reviewers, attributes)
end
- def create_attention_requested_todo(target, author, users)
- attributes = attributes_for_todo(target.project, target, author, Todo::ATTENTION_REQUESTED)
- create_todos(users, attributes)
- end
-
private
def create_todos(users, attributes)
diff --git a/app/services/todos/destroy/destroyed_issuable_service.rb b/app/services/todos/destroy/destroyed_issuable_service.rb
index 7a85b59eeea..759c430ec7a 100644
--- a/app/services/todos/destroy/destroyed_issuable_service.rb
+++ b/app/services/todos/destroy/destroyed_issuable_service.rb
@@ -5,9 +5,14 @@ module Todos
class DestroyedIssuableService
BATCH_SIZE = 100
+ # Since we are moving towards work items, in some instances we create todos with
+ # `target_type: WorkItem` in other instances we still create todos with `target_type: Issue`
+ # So when an issue/work item is deleted, we just make sure to delete todos for both target types
+ BOUND_TARGET_TYPES = %w(Issue WorkItem).freeze
+
def initialize(target_id, target_type)
@target_id = target_id
- @target_type = target_type
+ @target_type = BOUND_TARGET_TYPES.include?(target_type) ? BOUND_TARGET_TYPES : target_type
end
def execute
diff --git a/app/services/topics/merge_service.rb b/app/services/topics/merge_service.rb
new file mode 100644
index 00000000000..0d256579fe0
--- /dev/null
+++ b/app/services/topics/merge_service.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Topics
+ class MergeService
+ attr_accessor :source_topic, :target_topic
+
+ def initialize(source_topic, target_topic)
+ @source_topic = source_topic
+ @target_topic = target_topic
+ end
+
+ def execute
+ validate_parameters!
+
+ ::Projects::ProjectTopic.transaction do
+ move_project_topics
+ refresh_target_topic_counters
+ delete_source_topic
+ end
+ end
+
+ private
+
+ def validate_parameters!
+ raise ArgumentError, 'The source topic is not a topic.' unless source_topic.is_a?(Projects::Topic)
+ raise ArgumentError, 'The target topic is not a topic.' unless target_topic.is_a?(Projects::Topic)
+ raise ArgumentError, 'The source topic and the target topic are identical.' if source_topic == target_topic
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def move_project_topics
+ project_ids_for_projects_currently_using_source_and_target = ::Projects::ProjectTopic
+ .where(topic_id: target_topic).select(:project_id)
+ # Only update for projects that exclusively use the source topic
+ ::Projects::ProjectTopic.where(topic_id: source_topic.id)
+ .where.not(project_id: project_ids_for_projects_currently_using_source_and_target)
+ .update_all(topic_id: target_topic.id)
+
+ # Delete source topic for projects that were using source and target
+ ::Projects::ProjectTopic.where(topic_id: source_topic.id).delete_all
+ end
+
+ def refresh_target_topic_counters
+ target_topic.update!(
+ total_projects_count: total_projects_count(target_topic.id),
+ non_private_projects_count: non_private_projects_count(target_topic.id)
+ )
+ end
+
+ def delete_source_topic
+ source_topic.destroy!
+ end
+
+ def total_projects_count(topic_id)
+ ::Projects::ProjectTopic.where(topic_id: topic_id).count
+ end
+
+ def non_private_projects_count(topic_id)
+ ::Projects::ProjectTopic.joins(:project).where(topic_id: topic_id).where('projects.visibility_level in (10, 20)')
+ .count
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/services/uploads/destroy_service.rb b/app/services/uploads/destroy_service.rb
new file mode 100644
index 00000000000..1f0d99ff7bb
--- /dev/null
+++ b/app/services/uploads/destroy_service.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Uploads
+ class DestroyService < BaseService
+ attr_accessor :model, :current_user
+
+ def initialize(model, user = nil)
+ @model = model
+ @current_user = user
+ end
+
+ def execute(secret, filename)
+ upload = find_upload(secret, filename)
+
+ unless current_user && upload && current_user.can?(:destroy_upload, upload)
+ return error(_("The resource that you are attempting to access does not "\
+ "exist or you don't have permission to perform this action."))
+ end
+
+ if upload.destroy
+ success(upload: upload)
+ else
+ error(_('Upload could not be deleted.'))
+ end
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def find_upload(secret, filename)
+ uploader = uploader_class.new(model, secret: secret)
+ upload_paths = uploader.upload_paths(filename)
+
+ Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths)
+ rescue FileUploader::InvalidSecret
+ nil
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def uploader_class
+ case model
+ when Group
+ NamespaceFileUploader
+ when Project
+ FileUploader
+ else
+ raise ArgumentError, "unknown uploader for #{model.class.name}"
+ end
+ end
+ end
+end
diff --git a/app/services/users/dismiss_namespace_callout_service.rb b/app/services/users/dismiss_namespace_callout_service.rb
new file mode 100644
index 00000000000..51261a93e20
--- /dev/null
+++ b/app/services/users/dismiss_namespace_callout_service.rb
@@ -0,0 +1,11 @@
+# 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/dismiss_project_callout_service.rb b/app/services/users/dismiss_project_callout_service.rb
new file mode 100644
index 00000000000..23549b3b194
--- /dev/null
+++ b/app/services/users/dismiss_project_callout_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Users
+ class DismissProjectCalloutService < DismissCalloutService
+ private
+
+ def callout
+ current_user.find_or_initialize_project_callout(params[:feature_name], params[:project_id])
+ end
+ end
+end
diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb
index c3df9b153a1..cb2711b6fee 100644
--- a/app/services/users/update_service.rb
+++ b/app/services/users/update_service.rb
@@ -17,7 +17,7 @@ module Users
end
def execute(validate: true, check_password: false, &block)
- yield(@user) if block_given?
+ yield(@user) if block
user_exists = @user.persisted?
@user.user_detail # prevent assignment
diff --git a/app/services/web_hooks/admin_destroy_service.rb b/app/services/web_hooks/admin_destroy_service.rb
new file mode 100644
index 00000000000..e9835801a39
--- /dev/null
+++ b/app/services/web_hooks/admin_destroy_service.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module WebHooks
+ # A variant of the destroy service that can only be used by an administrator
+ # from a rake task.
+ class AdminDestroyService < WebHooks::DestroyService
+ def initialize(rake_task:)
+ super(nil)
+ @rake_task = rake_task
+ end
+
+ def authorized?(web_hook)
+ @rake_task.present? # Not impossible to circumvent, but you need to provide something
+ end
+
+ def log_message(hook)
+ "An administrator scheduled a deletion of logs for hook ID #{hook.id} from #{@rake_task.name}"
+ end
+ end
+end
diff --git a/app/services/web_hooks/destroy_service.rb b/app/services/web_hooks/destroy_service.rb
index 54c6c7ea71b..dbd164ab20e 100644
--- a/app/services/web_hooks/destroy_service.rb
+++ b/app/services/web_hooks/destroy_service.rb
@@ -1,25 +1,41 @@
# frozen_string_literal: true
module WebHooks
+ # Destroy a hook, and schedule the logs for deletion.
class DestroyService
+ include Services::ReturnServiceResponses
+
attr_accessor :current_user
+ DENIED = 'Insufficient permissions'
+
def initialize(current_user)
@current_user = current_user
end
- # Destroy the hook immediately, schedule the logs for deletion
def execute(web_hook)
+ return error(DENIED, 401) unless authorized?(web_hook)
+
hook_id = web_hook.id
if web_hook.destroy
WebHooks::LogDestroyWorker.perform_async({ 'hook_id' => hook_id })
- Gitlab::AppLogger.info("User #{current_user&.id} scheduled a deletion of logs for hook ID #{hook_id}")
+ Gitlab::AppLogger.info(log_message(web_hook))
- ServiceResponse.success(payload: { async: false })
+ success({ async: false })
else
- ServiceResponse.error(message: "Unable to destroy #{web_hook.model_name.human}")
+ error("Unable to destroy #{web_hook.model_name.human}", 500)
end
end
+
+ private
+
+ def log_message(hook)
+ "User #{current_user&.id} scheduled a deletion of logs for hook ID #{hook.id}"
+ end
+
+ def authorized?(web_hook)
+ Ability.allowed?(current_user, :destroy_web_hook, web_hook)
+ end
end
end
diff --git a/app/services/web_hooks/log_execution_service.rb b/app/services/web_hooks/log_execution_service.rb
index 17dcf615830..5be8aee3ae8 100644
--- a/app/services/web_hooks/log_execution_service.rb
+++ b/app/services/web_hooks/log_execution_service.rb
@@ -14,7 +14,6 @@ module WebHooks
@hook = hook
@log_data = log_data.transform_keys(&:to_sym)
@response_category = response_category
- @prev_state = hook.active_state(ignore_flag: true)
end
def execute
@@ -43,36 +42,12 @@ module WebHooks
hook.failed!
end
- log_state_change
hook.update_last_failure
end
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
raise if raise_lock_error?
end
- def log_state_change
- new_state = hook.active_state(ignore_flag: true)
-
- return if @prev_state == new_state
-
- Gitlab::AuthLogger.info(
- message: 'WebHook change active_state',
- # identification
- hook_id: hook.id,
- hook_type: hook.type,
- project_id: hook.project_id,
- group_id: hook.group_id,
- # relevant data
- prev_state: @prev_state,
- new_state: new_state,
- duration: log_data[:execution_duration],
- response_status: log_data[:response_status],
- recent_hook_failures: hook.recent_failures,
- # context
- **Gitlab::ApplicationContext.current
- )
- end
-
def lock_name
"web_hooks:update_hook_failure_state:#{hook.id}"
end
diff --git a/app/services/webauthn/authenticate_service.rb b/app/services/webauthn/authenticate_service.rb
index a575a853995..52437a77df8 100644
--- a/app/services/webauthn/authenticate_service.rb
+++ b/app/services/webauthn/authenticate_service.rb
@@ -30,6 +30,8 @@ module Webauthn
false
end
+ private
+
##
# Validates that webauthn_credential is syntactically valid
#
diff --git a/app/services/work_items/create_and_link_service.rb b/app/services/work_items/create_and_link_service.rb
index 6a773a84225..5cc358c4b4f 100644
--- a/app/services/work_items/create_and_link_service.rb
+++ b/app/services/work_items/create_and_link_service.rb
@@ -7,19 +7,20 @@ module WorkItems
# new work items that were never associated with other work items as expected.
class CreateAndLinkService
def initialize(project:, current_user: nil, params: {}, spam_params:, link_params: {})
- @create_service = CreateService.new(
- project: project,
- current_user: current_user,
- params: params,
- spam_params: spam_params
- )
@project = project
@current_user = current_user
+ @params = params
@link_params = link_params
+ @spam_params = spam_params
end
def execute
- create_result = @create_service.execute
+ create_result = CreateService.new(
+ project: @project,
+ current_user: @current_user,
+ params: @params.merge(title: @params[:title].strip).reverse_merge(confidential: confidential_parent),
+ spam_params: @spam_params
+ ).execute
return create_result if create_result.error?
work_item = create_result[:work_item]
@@ -40,6 +41,10 @@ module WorkItems
private
+ def confidential_parent
+ !!@link_params[:parent_work_item]&.confidential
+ end
+
def payload(work_item)
{ work_item: work_item }
end
diff --git a/app/services/work_items/parent_links/create_service.rb b/app/services/work_items/parent_links/create_service.rb
index 9940776e367..e7906f1fcdd 100644
--- a/app/services/work_items/parent_links/create_service.rb
+++ b/app/services/work_items/parent_links/create_service.rb
@@ -41,10 +41,8 @@ module WorkItems
params[:issuable_references]
end
- # TODO: Create system notes when work item's parent or children are updated
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/362213
def create_notes(work_item)
- # no-op
+ SystemNoteService.relate_work_item(issuable, work_item, current_user)
end
def target_issuable_type
diff --git a/app/services/work_items/parent_links/destroy_service.rb b/app/services/work_items/parent_links/destroy_service.rb
index 55870d44db9..19770b3e4b5 100644
--- a/app/services/work_items/parent_links/destroy_service.rb
+++ b/app/services/work_items/parent_links/destroy_service.rb
@@ -14,10 +14,8 @@ module WorkItems
private
- # TODO: Create system notes when work item's parent or children are removed
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/362213
def create_notes
- # no-op
+ SystemNoteService.unrelate_work_item(parent, child, current_user)
end
def not_found_message
diff --git a/app/services/work_items/update_service.rb b/app/services/work_items/update_service.rb
index 98818fda263..2deb8c82741 100644
--- a/app/services/work_items/update_service.rb
+++ b/app/services/work_items/update_service.rb
@@ -26,8 +26,8 @@ module WorkItems
private
- def update(work_item)
- execute_widgets(work_item: work_item, callback: :update, widget_params: @widget_params)
+ def before_update(work_item, skip_spam_check: false)
+ execute_widgets(work_item: work_item, callback: :before_update_callback, widget_params: @widget_params)
super
end
diff --git a/app/services/work_items/widgets/assignees_service/update_service.rb b/app/services/work_items/widgets/assignees_service/update_service.rb
new file mode 100644
index 00000000000..9176b71c85e
--- /dev/null
+++ b/app/services/work_items/widgets/assignees_service/update_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ module AssigneesService
+ class UpdateService < WorkItems::Widgets::BaseService
+ def before_update_in_transaction(params:)
+ return unless params.present? && params.has_key?(:assignee_ids)
+ return unless has_permission?(:set_work_item_metadata)
+
+ assignee_ids = filter_assignees_count(params[:assignee_ids])
+ assignee_ids = filter_assignee_permissions(assignee_ids)
+
+ return if assignee_ids.sort == work_item.assignee_ids.sort
+
+ work_item.assignee_ids = assignee_ids
+ work_item.touch
+ end
+
+ private
+
+ def filter_assignees_count(assignee_ids)
+ return assignee_ids if work_item.allows_multiple_assignees?
+
+ assignee_ids.first(1)
+ end
+
+ def filter_assignee_permissions(assignee_ids)
+ assignees = User.id_in(assignee_ids)
+
+ assignees.select { |assignee| assignee.can?(:read_work_item, work_item) }.map(&:id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/work_items/widgets/base_service.rb b/app/services/work_items/widgets/base_service.rb
index 037733bbed5..37ed2bf4b05 100644
--- a/app/services/work_items/widgets/base_service.rb
+++ b/app/services/work_items/widgets/base_service.rb
@@ -5,12 +5,19 @@ module WorkItems
class BaseService < ::BaseService
WidgetError = Class.new(StandardError)
- attr_reader :widget, :current_user
+ attr_reader :widget, :work_item, :current_user
def initialize(widget:, current_user:)
@widget = widget
+ @work_item = widget.work_item
@current_user = current_user
end
+
+ private
+
+ def has_permission?(permission)
+ can?(current_user, permission, widget.work_item)
+ end
end
end
end
diff --git a/app/services/work_items/widgets/description_service/update_service.rb b/app/services/work_items/widgets/description_service/update_service.rb
index e63b6b2ee6c..fe591ba605e 100644
--- a/app/services/work_items/widgets/description_service/update_service.rb
+++ b/app/services/work_items/widgets/description_service/update_service.rb
@@ -4,10 +4,12 @@ module WorkItems
module Widgets
module DescriptionService
class UpdateService < WorkItems::Widgets::BaseService
- def update(params: {})
- return unless params.present? && params[:description]
+ def before_update_callback(params: {})
+ return unless params.present? && params.key?(:description)
+ return unless has_permission?(:update_work_item)
- widget.work_item.description = params[:description]
+ work_item.description = params[:description]
+ work_item.assign_attributes(last_edited_at: Time.current, last_edited_by: current_user)
end
end
end
diff --git a/app/services/work_items/widgets/hierarchy_service/base_service.rb b/app/services/work_items/widgets/hierarchy_service/base_service.rb
index 085d6c6b0e7..bb681ef0083 100644
--- a/app/services/work_items/widgets/hierarchy_service/base_service.rb
+++ b/app/services/work_items/widgets/hierarchy_service/base_service.rb
@@ -15,7 +15,7 @@ module WorkItems
elsif params.key?(:children)
update_work_item_children(params.delete(:children))
else
- invalid_args_error
+ invalid_args_error(params)
end
end
@@ -29,13 +29,13 @@ module WorkItems
def set_parent(parent)
::WorkItems::ParentLinks::CreateService
- .new(parent, current_user, { target_issuable: widget.work_item })
+ .new(parent, current_user, { target_issuable: work_item })
.execute
end
# rubocop: disable CodeReuse/ActiveRecord
def remove_parent
- link = ::WorkItems::ParentLink.find_by(work_item: widget.work_item)
+ link = ::WorkItems::ParentLink.find_by(work_item: work_item)
return success unless link.present?
::WorkItems::ParentLinks::DestroyService.new(link, current_user).execute
@@ -44,12 +44,12 @@ module WorkItems
def update_work_item_children(children)
::WorkItems::ParentLinks::CreateService
- .new(widget.work_item, current_user, { issuable_references: children })
+ .new(work_item, current_user, { issuable_references: children })
.execute
end
def feature_flag_enabled?
- Feature.enabled?(:work_items_hierarchy, widget.work_item&.project)
+ Feature.enabled?(:work_items_hierarchy, work_item&.project)
end
def incompatible_args?(params)
@@ -64,11 +64,14 @@ module WorkItems
error(_('A Work Item can be a parent or a child, but not both.'))
end
- def invalid_args_error
+ def invalid_args_error(params)
error(_("One or more arguments are invalid: %{args}." % { args: params.keys.to_sentence } ))
end
def service_response!(result)
+ work_item.reload_work_item_parent
+ work_item.work_item_children.reset
+
return result unless result[:status] == :error
raise WidgetError, result[:message]
diff --git a/app/services/work_items/widgets/start_and_due_date_service/update_service.rb b/app/services/work_items/widgets/start_and_due_date_service/update_service.rb
new file mode 100644
index 00000000000..6a5dc0d5ef3
--- /dev/null
+++ b/app/services/work_items/widgets/start_and_due_date_service/update_service.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module WorkItems
+ module Widgets
+ module StartAndDueDateService
+ class UpdateService < WorkItems::Widgets::BaseService
+ def before_update_callback(params: {})
+ return if params.blank?
+
+ widget.work_item.assign_attributes(params.slice(:start_date, :due_date))
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/work_items/widgets/weight_service/update_service.rb b/app/services/work_items/widgets/weight_service/update_service.rb
deleted file mode 100644
index cd62a25358f..00000000000
--- a/app/services/work_items/widgets/weight_service/update_service.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module WorkItems
- module Widgets
- module WeightService
- class UpdateService < WorkItems::Widgets::BaseService
- def update(params: {})
- return unless params.present? && params[:weight]
-
- widget.work_item.weight = params[:weight]
- end
- end
- end
- end
-end
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
index 73dafaefb41..ac7b05bc7ea 100644
--- a/app/uploaders/avatar_uploader.rb
+++ b/app/uploaders/avatar_uploader.rb
@@ -6,7 +6,7 @@ class AvatarUploader < GitlabUploader
include ObjectStorage::Concern
prepend ObjectStorage::Extension::RecordsUploads
- MIME_WHITELIST = %w[image/png image/jpeg image/gif image/bmp image/tiff image/vnd.microsoft.icon].freeze
+ MIME_ALLOWLIST = %w[image/png image/jpeg image/gif image/bmp image/tiff image/vnd.microsoft.icon].freeze
def exists?
model.avatar.file && model.avatar.file.present?
@@ -29,7 +29,7 @@ class AvatarUploader < GitlabUploader
end
def content_type_whitelist
- MIME_WHITELIST
+ MIME_ALLOWLIST
end
private
diff --git a/app/uploaders/design_management/design_v432x230_uploader.rb b/app/uploaders/design_management/design_v432x230_uploader.rb
index ba48f381bbd..975050c26e4 100644
--- a/app/uploaders/design_management/design_v432x230_uploader.rb
+++ b/app/uploaders/design_management/design_v432x230_uploader.rb
@@ -20,13 +20,13 @@ module DesignManagement
#
# We currently choose not to resize `image/svg+xml` for security reasons.
# See https://gitlab.com/gitlab-org/gitlab/issues/207740#note_302766171
- MIME_TYPE_WHITELIST = %w(image/png image/jpeg image/bmp image/gif).freeze
+ MIME_TYPE_ALLOWLIST = %w(image/png image/jpeg image/bmp image/gif).freeze
process resize_to_fit: [432, 230]
# Allow CarrierWave to reject files without correct mimetypes.
def content_type_whitelist
- MIME_TYPE_WHITELIST
+ MIME_TYPE_ALLOWLIST
end
# Override `GitlabUploader` and always return false, otherwise local
diff --git a/app/uploaders/favicon_uploader.rb b/app/uploaders/favicon_uploader.rb
index c9be55e001c..a21b21de101 100644
--- a/app/uploaders/favicon_uploader.rb
+++ b/app/uploaders/favicon_uploader.rb
@@ -1,15 +1,15 @@
# frozen_string_literal: true
class FaviconUploader < AttachmentUploader
- EXTENSION_WHITELIST = %w[png ico].freeze
- MIME_WHITELIST = %w[image/png image/vnd.microsoft.icon].freeze
+ EXTENSION_ALLOWLIST = %w[png ico].freeze
+ MIME_ALLOWLIST = %w[image/png image/vnd.microsoft.icon].freeze
def extension_whitelist
- EXTENSION_WHITELIST
+ EXTENSION_ALLOWLIST
end
def content_type_whitelist
- MIME_WHITELIST
+ MIME_ALLOWLIST
end
private
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index bd959b14648..bf5be708060 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -142,8 +142,8 @@ class FileUploader < GitlabUploader
def to_h
{
- alt: markdown_name,
- url: secure_url,
+ alt: markdown_name,
+ url: secure_url,
markdown: markdown_link
}
end
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index 891df5180d8..063aca7937c 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -224,6 +224,10 @@ module ObjectStorage
def initialize(file)
@file = file
end
+
+ def file_path
+ @file.path
+ end
end
# allow to configure and overwrite the filename
@@ -275,9 +279,9 @@ module ObjectStorage
end
end
- def use_open_file(&blk)
+ def use_open_file(unlink_early: true)
Tempfile.open(path) do |file|
- file.unlink
+ file.unlink if unlink_early
file.binmode
if file_storage?
@@ -291,6 +295,8 @@ module ObjectStorage
file.seek(0, IO::SEEK_SET)
yield OpenFile.new(file)
+ ensure
+ file.unlink unless unlink_early
end
end
diff --git a/app/validators/json_schemas/build_metadata_id_tokens.json b/app/validators/json_schemas/build_metadata_id_tokens.json
new file mode 100644
index 00000000000..7f39c7274f3
--- /dev/null
+++ b/app/validators/json_schemas/build_metadata_id_tokens.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "CI builds metadata ID tokens",
+ "type": "object",
+ "patternProperties": {
+ ".*": {
+ "type": "object",
+ "patternProperties": {
+ "^id_token$": {
+ "type": "object",
+ "required": ["aud"],
+ "properties": {
+ "aud": { "type": "string" },
+ "field": { "type": "string" }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+}
diff --git a/app/validators/json_schemas/cyclonedx_report.json b/app/validators/json_schemas/cyclonedx_report.json
new file mode 100644
index 00000000000..65c3c3c0cb9
--- /dev/null
+++ b/app/validators/json_schemas/cyclonedx_report.json
@@ -0,0 +1,1697 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "http://cyclonedx.org/schema/bom-1.4.schema.json",
+ "type": "object",
+ "title": "CycloneDX Software Bill of Materials Standard",
+ "$comment" : "CycloneDX JSON schema is published under the terms of the Apache License 2.0.",
+ "required": [
+ "bomFormat",
+ "specVersion",
+ "version"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "$schema": {
+ "type": "string",
+ "enum": [
+ "http://cyclonedx.org/schema/bom-1.4.schema.json"
+ ]
+ },
+ "bomFormat": {
+ "type": "string",
+ "title": "BOM Format",
+ "description": "Specifies the format of the BOM. This helps to identify the file as CycloneDX since BOMs do not have a filename convention nor does JSON schema support namespaces. This value MUST be \"CycloneDX\".",
+ "enum": [
+ "CycloneDX"
+ ]
+ },
+ "specVersion": {
+ "type": "string",
+ "title": "CycloneDX Specification Version",
+ "description": "The version of the CycloneDX specification a BOM conforms to (starting at version 1.2).",
+ "examples": ["1.4"]
+ },
+ "serialNumber": {
+ "type": "string",
+ "title": "BOM Serial Number",
+ "description": "Every BOM generated SHOULD have a unique serial number, even if the contents of the BOM have not changed over time. If specified, the serial number MUST conform to RFC-4122. Use of serial numbers are RECOMMENDED.",
+ "examples": ["urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79"],
+ "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
+ },
+ "version": {
+ "type": "integer",
+ "title": "BOM Version",
+ "description": "Whenever an existing BOM is modified, either manually or through automated processes, the version of the BOM SHOULD be incremented by 1. When a system is presented with multiple BOMs with identical serial numbers, the system SHOULD use the most recent version of the BOM. The default version is '1'.",
+ "default": 1,
+ "examples": [1]
+ },
+ "metadata": {
+ "$ref": "#/definitions/metadata",
+ "title": "BOM Metadata",
+ "description": "Provides additional information about a BOM."
+ },
+ "components": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/component"},
+ "uniqueItems": true,
+ "title": "Components",
+ "description": "A list of software and hardware components."
+ },
+ "services": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/service"},
+ "uniqueItems": true,
+ "title": "Services",
+ "description": "A list of services. This may include microservices, function-as-a-service, and other types of network or intra-process services."
+ },
+ "externalReferences": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/externalReference"},
+ "title": "External References",
+ "description": "External references provide a way to document systems, sites, and information that may be relevant but which are not included with the BOM."
+ },
+ "dependencies": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/dependency"},
+ "uniqueItems": true,
+ "title": "Dependencies",
+ "description": "Provides the ability to document dependency relationships."
+ },
+ "compositions": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/compositions"},
+ "uniqueItems": true,
+ "title": "Compositions",
+ "description": "Compositions describe constituent parts (including components, services, and dependency relationships) and their completeness."
+ },
+ "vulnerabilities": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/vulnerability"},
+ "uniqueItems": true,
+ "title": "Vulnerabilities",
+ "description": "Vulnerabilities identified in components or services."
+ },
+ "signature": {
+ "$ref": "#/definitions/signature",
+ "title": "Signature",
+ "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+ }
+ },
+ "definitions": {
+ "refType": {
+ "$comment": "Identifier-DataType for interlinked elements.",
+ "type": "string"
+ },
+ "metadata": {
+ "type": "object",
+ "title": "BOM Metadata Object",
+ "additionalProperties": false,
+ "properties": {
+ "timestamp": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Timestamp",
+ "description": "The date and time (timestamp) when the BOM was created."
+ },
+ "tools": {
+ "type": "array",
+ "title": "Creation Tools",
+ "description": "The tool(s) used in the creation of the BOM.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/tool"}
+ },
+ "authors" :{
+ "type": "array",
+ "title": "Authors",
+ "description": "The person(s) who created the BOM. Authors are common in BOMs created through manual processes. BOMs created through automated means may not have authors.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/organizationalContact"}
+ },
+ "component": {
+ "title": "Component",
+ "description": "The component that the BOM describes.",
+ "$ref": "#/definitions/component"
+ },
+ "manufacture": {
+ "title": "Manufacture",
+ "description": "The organization that manufactured the component that the BOM describes.",
+ "$ref": "#/definitions/organizationalEntity"
+ },
+ "supplier": {
+ "title": "Supplier",
+ "description": " The organization that supplied the component that the BOM describes. The supplier may often be the manufacturer, but may also be a distributor or repackager.",
+ "$ref": "#/definitions/organizationalEntity"
+ },
+ "licenses": {
+ "type": "array",
+ "title": "BOM License(s)",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/licenseChoice"}
+ },
+ "properties": {
+ "type": "array",
+ "title": "Properties",
+ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/property"}
+ }
+ }
+ },
+ "tool": {
+ "type": "object",
+ "title": "Tool",
+ "description": "Information about the automated or manual tool used",
+ "additionalProperties": false,
+ "properties": {
+ "vendor": {
+ "type": "string",
+ "title": "Tool Vendor",
+ "description": "The name of the vendor who created the tool"
+ },
+ "name": {
+ "type": "string",
+ "title": "Tool Name",
+ "description": "The name of the tool"
+ },
+ "version": {
+ "type": "string",
+ "title": "Tool Version",
+ "description": "The version of the tool"
+ },
+ "hashes": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/hash"},
+ "title": "Hashes",
+ "description": "The hashes of the tool (if applicable)."
+ },
+ "externalReferences": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/externalReference"},
+ "title": "External References",
+ "description": "External references provide a way to document systems, sites, and information that may be relevant but which are not included with the BOM."
+ }
+ }
+ },
+ "organizationalEntity": {
+ "type": "object",
+ "title": "Organizational Entity Object",
+ "description": "",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the organization",
+ "examples": [
+ "Example Inc."
+ ]
+ },
+ "url": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "iri-reference"
+ },
+ "title": "URL",
+ "description": "The URL of the organization. Multiple URLs are allowed.",
+ "examples": ["https://example.com"]
+ },
+ "contact": {
+ "type": "array",
+ "title": "Contact",
+ "description": "A contact at the organization. Multiple contacts are allowed.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/organizationalContact"}
+ }
+ }
+ },
+ "organizationalContact": {
+ "type": "object",
+ "title": "Organizational Contact Object",
+ "description": "",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of a contact",
+ "examples": ["Contact name"]
+ },
+ "email": {
+ "type": "string",
+ "format": "idn-email",
+ "title": "Email Address",
+ "description": "The email address of the contact.",
+ "examples": ["firstname.lastname@example.com"]
+ },
+ "phone": {
+ "type": "string",
+ "title": "Phone",
+ "description": "The phone number of the contact.",
+ "examples": ["800-555-1212"]
+ }
+ }
+ },
+ "component": {
+ "type": "object",
+ "title": "Component Object",
+ "required": [
+ "type",
+ "name"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "application",
+ "framework",
+ "library",
+ "container",
+ "operating-system",
+ "device",
+ "firmware",
+ "file"
+ ],
+ "title": "Component Type",
+ "description": "Specifies the type of component. For software components, classify as application if no more specific appropriate classification is available or cannot be determined for the component. Types include:\n\n* __application__ = A software application. Refer to [https://en.wikipedia.org/wiki/Application_software](https://en.wikipedia.org/wiki/Application_software) for information about applications.\n* __framework__ = A software framework. Refer to [https://en.wikipedia.org/wiki/Software_framework](https://en.wikipedia.org/wiki/Software_framework) for information on how frameworks vary slightly from libraries.\n* __library__ = A software library. Refer to [https://en.wikipedia.org/wiki/Library_(computing)](https://en.wikipedia.org/wiki/Library_(computing))\n for information about libraries. All third-party and open source reusable components will likely be a library. If the library also has key features of a framework, then it should be classified as a framework. If not, or is unknown, then specifying library is RECOMMENDED.\n* __container__ = A packaging and/or runtime format, not specific to any particular technology, which isolates software inside the container from software outside of a container through virtualization technology. Refer to [https://en.wikipedia.org/wiki/OS-level_virtualization](https://en.wikipedia.org/wiki/OS-level_virtualization)\n* __operating-system__ = A software operating system without regard to deployment model (i.e. installed on physical hardware, virtual machine, image, etc) Refer to [https://en.wikipedia.org/wiki/Operating_system](https://en.wikipedia.org/wiki/Operating_system)\n* __device__ = A hardware device such as a processor, or chip-set. A hardware device containing firmware SHOULD include a component for the physical hardware itself, and another component of type 'firmware' or 'operating-system' (whichever is relevant), describing information about the software running on the device.\n* __firmware__ = A special type of software that provides low-level control over a devices hardware. Refer to [https://en.wikipedia.org/wiki/Firmware](https://en.wikipedia.org/wiki/Firmware)\n* __file__ = A computer file. Refer to [https://en.wikipedia.org/wiki/Computer_file](https://en.wikipedia.org/wiki/Computer_file) for information about files.",
+ "examples": ["library"]
+ },
+ "mime-type": {
+ "type": "string",
+ "title": "Mime-Type",
+ "description": "The optional mime-type of the component. When used on file components, the mime-type can provide additional context about the kind of file being represented such as an image, font, or executable. Some library or framework components may also have an associated mime-type.",
+ "examples": ["image/jpeg"],
+ "pattern": "^[-+a-z0-9.]+/[-+a-z0-9.]+$"
+ },
+ "bom-ref": {
+ "$ref": "#/definitions/refType",
+ "title": "BOM Reference",
+ "description": "An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+ },
+ "supplier": {
+ "title": "Component Supplier",
+ "description": " The organization that supplied the component. The supplier may often be the manufacturer, but may also be a distributor or repackager.",
+ "$ref": "#/definitions/organizationalEntity"
+ },
+ "author": {
+ "type": "string",
+ "title": "Component Author",
+ "description": "The person(s) or organization(s) that authored the component",
+ "examples": ["Acme Inc"]
+ },
+ "publisher": {
+ "type": "string",
+ "title": "Component Publisher",
+ "description": "The person(s) or organization(s) that published the component",
+ "examples": ["Acme Inc"]
+ },
+ "group": {
+ "type": "string",
+ "title": "Component Group",
+ "description": "The grouping name or identifier. This will often be a shortened, single name of the company or project that produced the component, or the source package or domain name. Whitespace and special characters should be avoided. Examples include: apache, org.apache.commons, and apache.org.",
+ "examples": ["com.acme"]
+ },
+ "name": {
+ "type": "string",
+ "title": "Component Name",
+ "description": "The name of the component. This will often be a shortened, single name of the component. Examples: commons-lang3 and jquery",
+ "examples": ["tomcat-catalina"]
+ },
+ "version": {
+ "type": "string",
+ "title": "Component Version",
+ "description": "The component version. The version should ideally comply with semantic versioning but is not enforced.",
+ "examples": ["9.0.14"]
+ },
+ "description": {
+ "type": "string",
+ "title": "Component Description",
+ "description": "Specifies a description for the component"
+ },
+ "scope": {
+ "type": "string",
+ "enum": [
+ "required",
+ "optional",
+ "excluded"
+ ],
+ "title": "Component Scope",
+ "description": "Specifies the scope of the component. If scope is not specified, 'required' scope SHOULD be assumed by the consumer of the BOM.",
+ "default": "required"
+ },
+ "hashes": {
+ "type": "array",
+ "title": "Component Hashes",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/hash"}
+ },
+ "licenses": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/licenseChoice"},
+ "title": "Component License(s)"
+ },
+ "copyright": {
+ "type": "string",
+ "title": "Component Copyright",
+ "description": "A copyright notice informing users of the underlying claims to copyright ownership in a published work.",
+ "examples": ["Acme Inc"]
+ },
+ "cpe": {
+ "type": "string",
+ "title": "Component Common Platform Enumeration (CPE)",
+ "description": "Specifies a well-formed CPE name that conforms to the CPE 2.2 or 2.3 specification. See [https://nvd.nist.gov/products/cpe](https://nvd.nist.gov/products/cpe)",
+ "examples": ["cpe:2.3:a:acme:component_framework:-:*:*:*:*:*:*:*"]
+ },
+ "purl": {
+ "type": "string",
+ "title": "Component Package URL (purl)",
+ "description": "Specifies the package-url (purl). The purl, if specified, MUST be valid and conform to the specification defined at: [https://github.com/package-url/purl-spec](https://github.com/package-url/purl-spec)",
+ "examples": ["pkg:maven/com.acme/tomcat-catalina@9.0.14?packaging=jar"]
+ },
+ "swid": {
+ "$ref": "#/definitions/swid",
+ "title": "SWID Tag",
+ "description": "Specifies metadata and content for [ISO-IEC 19770-2 Software Identification (SWID) Tags](https://www.iso.org/standard/65666.html)."
+ },
+ "modified": {
+ "type": "boolean",
+ "title": "Component Modified From Original",
+ "description": "[Deprecated] - DO NOT USE. This will be removed in a future version. Use the pedigree element instead to supply information on exactly how the component was modified. A boolean value indicating if the component has been modified from the original. A value of true indicates the component is a derivative of the original. A value of false indicates the component has not been modified from the original."
+ },
+ "pedigree": {
+ "type": "object",
+ "title": "Component Pedigree",
+ "description": "Component pedigree is a way to document complex supply chain scenarios where components are created, distributed, modified, redistributed, combined with other components, etc. Pedigree supports viewing this complex chain from the beginning, the end, or anywhere in the middle. It also provides a way to document variants where the exact relation may not be known.",
+ "additionalProperties": false,
+ "properties": {
+ "ancestors": {
+ "type": "array",
+ "title": "Ancestors",
+ "description": "Describes zero or more components in which a component is derived from. This is commonly used to describe forks from existing projects where the forked version contains a ancestor node containing the original component it was forked from. For example, Component A is the original component. Component B is the component being used and documented in the BOM. However, Component B contains a pedigree node with a single ancestor documenting Component A - the original component from which Component B is derived from.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/component"}
+ },
+ "descendants": {
+ "type": "array",
+ "title": "Descendants",
+ "description": "Descendants are the exact opposite of ancestors. This provides a way to document all forks (and their forks) of an original or root component.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/component"}
+ },
+ "variants": {
+ "type": "array",
+ "title": "Variants",
+ "description": "Variants describe relations where the relationship between the components are not known. For example, if Component A contains nearly identical code to Component B. They are both related, but it is unclear if one is derived from the other, or if they share a common ancestor.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/component"}
+ },
+ "commits": {
+ "type": "array",
+ "title": "Commits",
+ "description": "A list of zero or more commits which provide a trail describing how the component deviates from an ancestor, descendant, or variant.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/commit"}
+ },
+ "patches": {
+ "type": "array",
+ "title": "Patches",
+ "description": ">A list of zero or more patches describing how the component deviates from an ancestor, descendant, or variant. Patches may be complimentary to commits or may be used in place of commits.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/patch"}
+ },
+ "notes": {
+ "type": "string",
+ "title": "Notes",
+ "description": "Notes, observations, and other non-structured commentary describing the components pedigree."
+ }
+ }
+ },
+ "externalReferences": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/externalReference"},
+ "title": "External References",
+ "description": "External references provide a way to document systems, sites, and information that may be relevant but which are not included with the BOM."
+ },
+ "components": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/component"},
+ "uniqueItems": true,
+ "title": "Components",
+ "description": "A list of software and hardware components included in the parent component. This is not a dependency tree. It provides a way to specify a hierarchical representation of component assemblies, similar to system &#8594; subsystem &#8594; parts assembly in physical supply chains."
+ },
+ "evidence": {
+ "$ref": "#/definitions/componentEvidence",
+ "title": "Evidence",
+ "description": "Provides the ability to document evidence collected through various forms of extraction or analysis."
+ },
+ "releaseNotes": {
+ "$ref": "#/definitions/releaseNotes",
+ "title": "Release notes",
+ "description": "Specifies optional release notes."
+ },
+ "properties": {
+ "type": "array",
+ "title": "Properties",
+ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/property"}
+ },
+ "signature": {
+ "$ref": "#/definitions/signature",
+ "title": "Signature",
+ "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+ }
+ }
+ },
+ "swid": {
+ "type": "object",
+ "title": "SWID Tag",
+ "description": "Specifies metadata and content for ISO-IEC 19770-2 Software Identification (SWID) Tags.",
+ "required": [
+ "tagId",
+ "name"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "tagId": {
+ "type": "string",
+ "title": "Tag ID",
+ "description": "Maps to the tagId of a SoftwareIdentity."
+ },
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "Maps to the name of a SoftwareIdentity."
+ },
+ "version": {
+ "type": "string",
+ "title": "Version",
+ "default": "0.0",
+ "description": "Maps to the version of a SoftwareIdentity."
+ },
+ "tagVersion": {
+ "type": "integer",
+ "title": "Tag Version",
+ "default": 0,
+ "description": "Maps to the tagVersion of a SoftwareIdentity."
+ },
+ "patch": {
+ "type": "boolean",
+ "title": "Patch",
+ "default": false,
+ "description": "Maps to the patch of a SoftwareIdentity."
+ },
+ "text": {
+ "title": "Attachment text",
+ "description": "Specifies the metadata and content of the SWID tag.",
+ "$ref": "#/definitions/attachment"
+ },
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "The URL to the SWID file.",
+ "format": "iri-reference"
+ }
+ }
+ },
+ "attachment": {
+ "type": "object",
+ "title": "Attachment",
+ "description": "Specifies the metadata and content for an attachment.",
+ "required": [
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "contentType": {
+ "type": "string",
+ "title": "Content-Type",
+ "description": "Specifies the content type of the text. Defaults to text/plain if not specified.",
+ "default": "text/plain"
+ },
+ "encoding": {
+ "type": "string",
+ "title": "Encoding",
+ "description": "Specifies the optional encoding the text is represented in.",
+ "enum": [
+ "base64"
+ ]
+ },
+ "content": {
+ "type": "string",
+ "title": "Attachment Text",
+ "description": "The attachment data. Proactive controls such as input validation and sanitization should be employed to prevent misuse of attachment text."
+ }
+ }
+ },
+ "hash": {
+ "type": "object",
+ "title": "Hash Objects",
+ "required": [
+ "alg",
+ "content"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "alg": {
+ "$ref": "#/definitions/hash-alg"
+ },
+ "content": {
+ "$ref": "#/definitions/hash-content"
+ }
+ }
+ },
+ "hash-alg": {
+ "type": "string",
+ "enum": [
+ "MD5",
+ "SHA-1",
+ "SHA-256",
+ "SHA-384",
+ "SHA-512",
+ "SHA3-256",
+ "SHA3-384",
+ "SHA3-512",
+ "BLAKE2b-256",
+ "BLAKE2b-384",
+ "BLAKE2b-512",
+ "BLAKE3"
+ ],
+ "title": "Hash Algorithm"
+ },
+ "hash-content": {
+ "type": "string",
+ "title": "Hash Content (value)",
+ "examples": ["3942447fac867ae5cdb3229b658f4d48"],
+ "pattern": "^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$"
+ },
+ "license": {
+ "type": "object",
+ "title": "License Object",
+ "oneOf": [
+ {
+ "required": ["id"]
+ },
+ {
+ "required": ["name"]
+ }
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "$ref": "spdx.schema.json",
+ "title": "License ID (SPDX)",
+ "description": "A valid SPDX license ID",
+ "examples": ["Apache-2.0"]
+ },
+ "name": {
+ "type": "string",
+ "title": "License Name",
+ "description": "If SPDX does not define the license used, this field may be used to provide the license name",
+ "examples": ["Acme Software License"]
+ },
+ "text": {
+ "title": "License text",
+ "description": "An optional way to include the textual content of a license.",
+ "$ref": "#/definitions/attachment"
+ },
+ "url": {
+ "type": "string",
+ "title": "License URL",
+ "description": "The URL to the license file. If specified, a 'license' externalReference should also be specified for completeness",
+ "examples": ["https://www.apache.org/licenses/LICENSE-2.0.txt"],
+ "format": "iri-reference"
+ }
+ }
+ },
+ "licenseChoice": {
+ "type": "object",
+ "title": "License(s)",
+ "additionalProperties": false,
+ "properties": {
+ "license": {
+ "$ref": "#/definitions/license"
+ },
+ "expression": {
+ "type": "string",
+ "title": "SPDX License Expression",
+ "examples": [
+ "Apache-2.0 AND (MIT OR GPL-2.0-only)",
+ "GPL-3.0-only WITH Classpath-exception-2.0"
+ ]
+ }
+ },
+ "oneOf":[
+ {
+ "required": ["license"]
+ },
+ {
+ "required": ["expression"]
+ }
+ ]
+ },
+ "commit": {
+ "type": "object",
+ "title": "Commit",
+ "description": "Specifies an individual commit",
+ "additionalProperties": false,
+ "properties": {
+ "uid": {
+ "type": "string",
+ "title": "UID",
+ "description": "A unique identifier of the commit. This may be version control specific. For example, Subversion uses revision numbers whereas git uses commit hashes."
+ },
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "The URL to the commit. This URL will typically point to a commit in a version control system.",
+ "format": "iri-reference"
+ },
+ "author": {
+ "title": "Author",
+ "description": "The author who created the changes in the commit",
+ "$ref": "#/definitions/identifiableAction"
+ },
+ "committer": {
+ "title": "Committer",
+ "description": "The person who committed or pushed the commit",
+ "$ref": "#/definitions/identifiableAction"
+ },
+ "message": {
+ "type": "string",
+ "title": "Message",
+ "description": "The text description of the contents of the commit"
+ }
+ }
+ },
+ "patch": {
+ "type": "object",
+ "title": "Patch",
+ "description": "Specifies an individual patch",
+ "required": [
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "unofficial",
+ "monkey",
+ "backport",
+ "cherry-pick"
+ ],
+ "title": "Type",
+ "description": "Specifies the purpose for the patch including the resolution of defects, security issues, or new behavior or functionality.\n\n* __unofficial__ = A patch which is not developed by the creators or maintainers of the software being patched. Refer to [https://en.wikipedia.org/wiki/Unofficial_patch](https://en.wikipedia.org/wiki/Unofficial_patch)\n* __monkey__ = A patch which dynamically modifies runtime behavior. Refer to [https://en.wikipedia.org/wiki/Monkey_patch](https://en.wikipedia.org/wiki/Monkey_patch)\n* __backport__ = A patch which takes code from a newer version of software and applies it to older versions of the same software. Refer to [https://en.wikipedia.org/wiki/Backporting](https://en.wikipedia.org/wiki/Backporting)\n* __cherry-pick__ = A patch created by selectively applying commits from other versions or branches of the same software."
+ },
+ "diff": {
+ "title": "Diff",
+ "description": "The patch file (or diff) that show changes. Refer to [https://en.wikipedia.org/wiki/Diff](https://en.wikipedia.org/wiki/Diff)",
+ "$ref": "#/definitions/diff"
+ },
+ "resolves": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/issue"},
+ "title": "Resolves",
+ "description": "A collection of issues the patch resolves"
+ }
+ }
+ },
+ "diff": {
+ "type": "object",
+ "title": "Diff",
+ "description": "The patch file (or diff) that show changes. Refer to https://en.wikipedia.org/wiki/Diff",
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "title": "Diff text",
+ "description": "Specifies the optional text of the diff",
+ "$ref": "#/definitions/attachment"
+ },
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "Specifies the URL to the diff",
+ "format": "iri-reference"
+ }
+ }
+ },
+ "issue": {
+ "type": "object",
+ "title": "Diff",
+ "description": "An individual issue that has been resolved.",
+ "required": [
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": [
+ "defect",
+ "enhancement",
+ "security"
+ ],
+ "title": "Type",
+ "description": "Specifies the type of issue"
+ },
+ "id": {
+ "type": "string",
+ "title": "ID",
+ "description": "The identifier of the issue assigned by the source of the issue"
+ },
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the issue"
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "A description of the issue"
+ },
+ "source": {
+ "type": "object",
+ "title": "Source",
+ "description": "The source of the issue where it is documented",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the source. For example 'National Vulnerability Database', 'NVD', and 'Apache'"
+ },
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "The url of the issue documentation as provided by the source",
+ "format": "iri-reference"
+ }
+ }
+ },
+ "references": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "iri-reference"
+ },
+ "title": "References",
+ "description": "A collection of URL's for reference. Multiple URLs are allowed.",
+ "examples": ["https://example.com"]
+ }
+ }
+ },
+ "identifiableAction": {
+ "type": "object",
+ "title": "Identifiable Action",
+ "description": "Specifies an individual commit",
+ "additionalProperties": false,
+ "properties": {
+ "timestamp": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Timestamp",
+ "description": "The timestamp in which the action occurred"
+ },
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the individual who performed the action"
+ },
+ "email": {
+ "type": "string",
+ "format": "idn-email",
+ "title": "E-mail",
+ "description": "The email address of the individual who performed the action"
+ }
+ }
+ },
+ "externalReference": {
+ "type": "object",
+ "title": "External Reference",
+ "description": "Specifies an individual external reference",
+ "required": [
+ "url",
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "The URL to the external reference",
+ "format": "iri-reference"
+ },
+ "comment": {
+ "type": "string",
+ "title": "Comment",
+ "description": "An optional comment describing the external reference"
+ },
+ "type": {
+ "type": "string",
+ "title": "Type",
+ "description": "Specifies the type of external reference. There are built-in types to describe common references. If a type does not exist for the reference being referred to, use the \"other\" type.",
+ "enum": [
+ "vcs",
+ "issue-tracker",
+ "website",
+ "advisories",
+ "bom",
+ "mailing-list",
+ "social",
+ "chat",
+ "documentation",
+ "support",
+ "distribution",
+ "license",
+ "build-meta",
+ "build-system",
+ "release-notes",
+ "other"
+ ]
+ },
+ "hashes": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/hash"},
+ "title": "Hashes",
+ "description": "The hashes of the external reference (if applicable)."
+ }
+ }
+ },
+ "dependency": {
+ "type": "object",
+ "title": "Dependency",
+ "description": "Defines the direct dependencies of a component. Components that do not have their own dependencies MUST be declared as empty elements within the graph. Components that are not represented in the dependency graph MAY have unknown dependencies. It is RECOMMENDED that implementations assume this to be opaque and not an indicator of a component being dependency-free.",
+ "required": [
+ "ref"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "ref": {
+ "$ref": "#/definitions/refType",
+ "title": "Reference",
+ "description": "References a component by the components bom-ref attribute"
+ },
+ "dependsOn": {
+ "type": "array",
+ "uniqueItems": true,
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/refType"
+ },
+ "title": "Depends On",
+ "description": "The bom-ref identifiers of the components that are dependencies of this dependency object."
+ }
+ }
+ },
+ "service": {
+ "type": "object",
+ "title": "Service Object",
+ "required": [
+ "name"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "bom-ref": {
+ "$ref": "#/definitions/refType",
+ "title": "BOM Reference",
+ "description": "An optional identifier which can be used to reference the service elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+ },
+ "provider": {
+ "title": "Provider",
+ "description": "The organization that provides the service.",
+ "$ref": "#/definitions/organizationalEntity"
+ },
+ "group": {
+ "type": "string",
+ "title": "Service Group",
+ "description": "The grouping name, namespace, or identifier. This will often be a shortened, single name of the company or project that produced the service or domain name. Whitespace and special characters should be avoided.",
+ "examples": ["com.acme"]
+ },
+ "name": {
+ "type": "string",
+ "title": "Service Name",
+ "description": "The name of the service. This will often be a shortened, single name of the service.",
+ "examples": ["ticker-service"]
+ },
+ "version": {
+ "type": "string",
+ "title": "Service Version",
+ "description": "The service version.",
+ "examples": ["1.0.0"]
+ },
+ "description": {
+ "type": "string",
+ "title": "Service Description",
+ "description": "Specifies a description for the service"
+ },
+ "endpoints": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "iri-reference"
+ },
+ "title": "Endpoints",
+ "description": "The endpoint URIs of the service. Multiple endpoints are allowed.",
+ "examples": ["https://example.com/api/v1/ticker"]
+ },
+ "authenticated": {
+ "type": "boolean",
+ "title": "Authentication Required",
+ "description": "A boolean value indicating if the service requires authentication. A value of true indicates the service requires authentication prior to use. A value of false indicates the service does not require authentication."
+ },
+ "x-trust-boundary": {
+ "type": "boolean",
+ "title": "Crosses Trust Boundary",
+ "description": "A boolean value indicating if use of the service crosses a trust zone or boundary. A value of true indicates that by using the service, a trust boundary is crossed. A value of false indicates that by using the service, a trust boundary is not crossed."
+ },
+ "data": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/dataClassification"},
+ "title": "Data Classification",
+ "description": "Specifies the data classification."
+ },
+ "licenses": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/licenseChoice"},
+ "title": "Component License(s)"
+ },
+ "externalReferences": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/externalReference"},
+ "title": "External References",
+ "description": "External references provide a way to document systems, sites, and information that may be relevant but which are not included with the BOM."
+ },
+ "services": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/service"},
+ "uniqueItems": true,
+ "title": "Services",
+ "description": "A list of services included or deployed behind the parent service. This is not a dependency tree. It provides a way to specify a hierarchical representation of service assemblies."
+ },
+ "releaseNotes": {
+ "$ref": "#/definitions/releaseNotes",
+ "title": "Release notes",
+ "description": "Specifies optional release notes."
+ },
+ "properties": {
+ "type": "array",
+ "title": "Properties",
+ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/property"}
+ },
+ "signature": {
+ "$ref": "#/definitions/signature",
+ "title": "Signature",
+ "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+ }
+ }
+ },
+ "dataClassification": {
+ "type": "object",
+ "title": "Hash Objects",
+ "required": [
+ "flow",
+ "classification"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "flow": {
+ "$ref": "#/definitions/dataFlow",
+ "title": "Directional Flow",
+ "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known."
+ },
+ "classification": {
+ "type": "string",
+ "title": "Classification",
+ "description": "Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed."
+ }
+ }
+ },
+ "dataFlow": {
+ "type": "string",
+ "enum": [
+ "inbound",
+ "outbound",
+ "bi-directional",
+ "unknown"
+ ],
+ "title": "Data flow direction",
+ "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known."
+ },
+
+ "copyright": {
+ "type": "object",
+ "title": "Copyright",
+ "required": [
+ "text"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "text": {
+ "type": "string",
+ "title": "Copyright Text"
+ }
+ }
+ },
+
+ "componentEvidence": {
+ "type": "object",
+ "title": "Evidence",
+ "description": "Provides the ability to document evidence collected through various forms of extraction or analysis.",
+ "additionalProperties": false,
+ "properties": {
+ "licenses": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/licenseChoice"},
+ "title": "Component License(s)"
+ },
+ "copyright": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/copyright"},
+ "title": "Copyright"
+ }
+ }
+ },
+ "compositions": {
+ "type": "object",
+ "title": "Compositions",
+ "required": [
+ "aggregate"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "aggregate": {
+ "$ref": "#/definitions/aggregateType",
+ "title": "Aggregate",
+ "description": "Specifies an aggregate type that describe how complete a relationship is."
+ },
+ "assemblies": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ },
+ "title": "BOM references",
+ "description": "The bom-ref identifiers of the components or services being described. Assemblies refer to nested relationships whereby a constituent part may include other constituent parts. References do not cascade to child parts. References are explicit for the specified constituent part only."
+ },
+ "dependencies": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ },
+ "title": "BOM references",
+ "description": "The bom-ref identifiers of the components or services being described. Dependencies refer to a relationship whereby an independent constituent part requires another independent constituent part. References do not cascade to transitive dependencies. References are explicit for the specified dependency only."
+ },
+ "signature": {
+ "$ref": "#/definitions/signature",
+ "title": "Signature",
+ "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+ }
+ }
+ },
+ "aggregateType": {
+ "type": "string",
+ "default": "not_specified",
+ "enum": [
+ "complete",
+ "incomplete",
+ "incomplete_first_party_only",
+ "incomplete_third_party_only",
+ "unknown",
+ "not_specified"
+ ]
+ },
+ "property": {
+ "type": "object",
+ "title": "Lightweight name-value pair",
+ "properties": {
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the property. Duplicate names are allowed, each potentially having a different value."
+ },
+ "value": {
+ "type": "string",
+ "title": "Value",
+ "description": "The value of the property."
+ }
+ }
+ },
+ "localeType": {
+ "type": "string",
+ "pattern": "^([a-z]{2})(-[A-Z]{2})?$",
+ "title": "Locale",
+ "description": "Defines a syntax for representing two character language code (ISO-639) followed by an optional two character country code. The language code MUST be lower case. If the country code is specified, the country code MUST be upper case. The language code and country code MUST be separated by a minus sign. Examples: en, en-US, fr, fr-CA"
+ },
+ "releaseType": {
+ "type": "string",
+ "examples": [
+ "major",
+ "minor",
+ "patch",
+ "pre-release",
+ "internal"
+ ],
+ "description": "The software versioning type. It is RECOMMENDED that the release type use one of 'major', 'minor', 'patch', 'pre-release', or 'internal'. Representing all possible software release types is not practical, so standardizing on the recommended values, whenever possible, is strongly encouraged.\n\n* __major__ = A major release may contain significant changes or may introduce breaking changes.\n* __minor__ = A minor release, also known as an update, may contain a smaller number of changes than major releases.\n* __patch__ = Patch releases are typically unplanned and may resolve defects or important security issues.\n* __pre-release__ = A pre-release may include alpha, beta, or release candidates and typically have limited support. They provide the ability to preview a release prior to its general availability.\n* __internal__ = Internal releases are not for public consumption and are intended to be used exclusively by the project or manufacturer that produced it."
+ },
+ "note": {
+ "type": "object",
+ "title": "Note",
+ "description": "A note containing the locale and content.",
+ "required": [
+ "text"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "locale": {
+ "$ref": "#/definitions/localeType",
+ "title": "Locale",
+ "description": "The ISO-639 (or higher) language code and optional ISO-3166 (or higher) country code. Examples include: \"en\", \"en-US\", \"fr\" and \"fr-CA\""
+ },
+ "text": {
+ "title": "Release note content",
+ "description": "Specifies the full content of the release note.",
+ "$ref": "#/definitions/attachment"
+ }
+ }
+ },
+ "releaseNotes": {
+ "type": "object",
+ "title": "Release notes",
+ "required": [
+ "type"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/releaseType",
+ "title": "Type",
+ "description": "The software versioning type the release note describes."
+ },
+ "title": {
+ "type": "string",
+ "title": "Title",
+ "description": "The title of the release."
+ },
+ "featuredImage": {
+ "type": "string",
+ "format": "iri-reference",
+ "title": "Featured image",
+ "description": "The URL to an image that may be prominently displayed with the release note."
+ },
+ "socialImage": {
+ "type": "string",
+ "format": "iri-reference",
+ "title": "Social image",
+ "description": "The URL to an image that may be used in messaging on social media platforms."
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "A short description of the release."
+ },
+ "timestamp": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Timestamp",
+ "description": "The date and time (timestamp) when the release note was created."
+ },
+ "aliases": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "title": "Aliases",
+ "description": "One or more alternate names the release may be referred to. This may include unofficial terms used by development and marketing teams (e.g. code names)."
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "title": "Tags",
+ "description": "One or more tags that may aid in search or retrieval of the release note."
+ },
+ "resolves": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/issue"},
+ "title": "Resolves",
+ "description": "A collection of issues that have been resolved."
+ },
+ "notes": {
+ "type": "array",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/note"},
+ "title": "Notes",
+ "description": "Zero or more release notes containing the locale and content. Multiple note objects may be specified to support release notes in a wide variety of languages."
+ },
+ "properties": {
+ "type": "array",
+ "title": "Properties",
+ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/property"}
+ }
+ }
+ },
+ "advisory": {
+ "type": "object",
+ "title": "Advisory",
+ "description": "Title and location where advisory information can be obtained. An advisory is a notification of a threat to a component, service, or system.",
+ "required": ["url"],
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "title": "Title",
+ "description": "An optional name of the advisory."
+ },
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "format": "iri-reference",
+ "description": "Location where the advisory can be obtained."
+ }
+ }
+ },
+ "cwe": {
+ "type": "integer",
+ "minimum": 1,
+ "title": "CWE",
+ "description": "Integer representation of a Common Weaknesses Enumerations (CWE). For example 399 (of https://cwe.mitre.org/data/definitions/399.html)"
+ },
+ "severity": {
+ "type": "string",
+ "title": "Severity",
+ "description": "Textual representation of the severity of the vulnerability adopted by the analysis method. If the analysis method uses values other than what is provided, the user is expected to translate appropriately.",
+ "enum": [
+ "critical",
+ "high",
+ "medium",
+ "low",
+ "info",
+ "none",
+ "unknown"
+ ]
+ },
+ "scoreMethod": {
+ "type": "string",
+ "title": "Method",
+ "description": "Specifies the severity or risk scoring methodology or standard used.\n\n* CVSSv2 - [Common Vulnerability Scoring System v2](https://www.first.org/cvss/v2/)\n* CVSSv3 - [Common Vulnerability Scoring System v3](https://www.first.org/cvss/v3-0/)\n* CVSSv31 - [Common Vulnerability Scoring System v3.1](https://www.first.org/cvss/v3-1/)\n* OWASP - [OWASP Risk Rating Methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology)",
+ "enum": [
+ "CVSSv2",
+ "CVSSv3",
+ "CVSSv31",
+ "OWASP",
+ "other"
+ ]
+ },
+ "impactAnalysisState": {
+ "type": "string",
+ "title": "Impact Analysis State",
+ "description": "Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. \n\n* __resolved__ = the vulnerability has been remediated. \n* __resolved\\_with\\_pedigree__ = the vulnerability has been remediated and evidence of the changes are provided in the affected components pedigree containing verifiable commit history and/or diff(s). \n* __exploitable__ = the vulnerability may be directly or indirectly exploitable. \n* __in\\_triage__ = the vulnerability is being investigated. \n* __false\\_positive__ = the vulnerability is not specific to the component or service and was falsely identified or associated. \n* __not\\_affected__ = the component or service is not affected by the vulnerability. Justification should be specified for all not_affected cases.",
+ "enum": [
+ "resolved",
+ "resolved_with_pedigree",
+ "exploitable",
+ "in_triage",
+ "false_positive",
+ "not_affected"
+ ]
+ },
+ "impactAnalysisJustification": {
+ "type": "string",
+ "title": "Impact Analysis Justification",
+ "description": "The rationale of why the impact analysis state was asserted. \n\n* __code\\_not\\_present__ = the code has been removed or tree-shaked. \n* __code\\_not\\_reachable__ = the vulnerable code is not invoked at runtime. \n* __requires\\_configuration__ = exploitability requires a configurable option to be set/unset. \n* __requires\\_dependency__ = exploitability requires a dependency that is not present. \n* __requires\\_environment__ = exploitability requires a certain environment which is not present. \n* __protected\\_by\\_compiler__ = exploitability requires a compiler flag to be set/unset. \n* __protected\\_at\\_runtime__ = exploits are prevented at runtime. \n* __protected\\_at\\_perimeter__ = attacks are blocked at physical, logical, or network perimeter. \n* __protected\\_by\\_mitigating\\_control__ = preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability.",
+ "enum": [
+ "code_not_present",
+ "code_not_reachable",
+ "requires_configuration",
+ "requires_dependency",
+ "requires_environment",
+ "protected_by_compiler",
+ "protected_at_runtime",
+ "protected_at_perimeter",
+ "protected_by_mitigating_control"
+ ]
+ },
+ "rating": {
+ "type": "object",
+ "title": "Rating",
+ "description": "Defines the severity or risk ratings of a vulnerability.",
+ "additionalProperties": false,
+ "properties": {
+ "source": {
+ "$ref": "#/definitions/vulnerabilitySource",
+ "description": "The source that calculated the severity or risk rating of the vulnerability."
+ },
+ "score": {
+ "type": "number",
+ "title": "Score",
+ "description": "The numerical score of the rating."
+ },
+ "severity": {
+ "$ref": "#/definitions/severity",
+ "description": "Textual representation of the severity that corresponds to the numerical score of the rating."
+ },
+ "method": {
+ "$ref": "#/definitions/scoreMethod"
+ },
+ "vector": {
+ "type": "string",
+ "title": "Vector",
+ "description": "Textual representation of the metric values used to score the vulnerability"
+ },
+ "justification": {
+ "type": "string",
+ "title": "Justification",
+ "description": "An optional reason for rating the vulnerability as it was"
+ }
+ }
+ },
+ "vulnerabilitySource": {
+ "type": "object",
+ "title": "Source",
+ "description": "The source of vulnerability information. This is often the organization that published the vulnerability.",
+ "additionalProperties": false,
+ "properties": {
+ "url": {
+ "type": "string",
+ "title": "URL",
+ "description": "The url of the vulnerability documentation as provided by the source.",
+ "examples": [
+ "https://nvd.nist.gov/vuln/detail/CVE-2021-39182"
+ ]
+ },
+ "name": {
+ "type": "string",
+ "title": "Name",
+ "description": "The name of the source.",
+ "examples": [
+ "NVD",
+ "National Vulnerability Database",
+ "OSS Index",
+ "VulnDB",
+ "GitHub Advisories"
+ ]
+ }
+ }
+ },
+ "vulnerability": {
+ "type": "object",
+ "title": "Vulnerability",
+ "description": "Defines a weakness in an component or service that could be exploited or triggered by a threat source.",
+ "additionalProperties": false,
+ "properties": {
+ "bom-ref": {
+ "$ref": "#/definitions/refType",
+ "title": "BOM Reference",
+ "description": "An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+ },
+ "id": {
+ "type": "string",
+ "title": "ID",
+ "description": "The identifier that uniquely identifies the vulnerability.",
+ "examples": [
+ "CVE-2021-39182",
+ "GHSA-35m5-8cvj-8783",
+ "SNYK-PYTHON-ENROCRYPT-1912876"
+ ]
+ },
+ "source": {
+ "$ref": "#/definitions/vulnerabilitySource",
+ "description": "The source that published the vulnerability."
+ },
+ "references": {
+ "type": "array",
+ "title": "References",
+ "description": "Zero or more pointers to vulnerabilities that are the equivalent of the vulnerability specified. Often times, the same vulnerability may exist in multiple sources of vulnerability intelligence, but have different identifiers. References provide a way to correlate vulnerabilities across multiple sources of vulnerability intelligence.",
+ "additionalItems": false,
+ "items": {
+ "required": [
+ "id",
+ "source"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "title": "ID",
+ "description": "An identifier that uniquely identifies the vulnerability.",
+ "examples": [
+ "CVE-2021-39182",
+ "GHSA-35m5-8cvj-8783",
+ "SNYK-PYTHON-ENROCRYPT-1912876"
+ ]
+ },
+ "source": {
+ "$ref": "#/definitions/vulnerabilitySource",
+ "description": "The source that published the vulnerability."
+ }
+ }
+ }
+ },
+ "ratings": {
+ "type": "array",
+ "title": "Ratings",
+ "description": "List of vulnerability ratings",
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/rating"
+ }
+ },
+ "cwes": {
+ "type": "array",
+ "title": "CWEs",
+ "description": "List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability. For example 399 (of https://cwe.mitre.org/data/definitions/399.html)",
+ "examples": [399],
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/cwe"
+ }
+ },
+ "description": {
+ "type": "string",
+ "title": "Description",
+ "description": "A description of the vulnerability as provided by the source."
+ },
+ "detail": {
+ "type": "string",
+ "title": "Details",
+ "description": "If available, an in-depth description of the vulnerability as provided by the source organization. Details often include examples, proof-of-concepts, and other information useful in understanding root cause."
+ },
+ "recommendation": {
+ "type": "string",
+ "title": "Details",
+ "description": "Recommendations of how the vulnerability can be remediated or mitigated."
+ },
+ "advisories": {
+ "type": "array",
+ "title": "Advisories",
+ "description": "Published advisories of the vulnerability if provided.",
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/advisory"
+ }
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Created",
+ "description": "The date and time (timestamp) when the vulnerability record was created in the vulnerability database."
+ },
+ "published": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Published",
+ "description": "The date and time (timestamp) when the vulnerability record was first published."
+ },
+ "updated": {
+ "type": "string",
+ "format": "date-time",
+ "title": "Updated",
+ "description": "The date and time (timestamp) when the vulnerability record was last updated."
+ },
+ "credits": {
+ "type": "object",
+ "title": "Credits",
+ "description": "Individuals or organizations credited with the discovery of the vulnerability.",
+ "additionalProperties": false,
+ "properties": {
+ "organizations": {
+ "type": "array",
+ "title": "Organizations",
+ "description": "The organizations credited with vulnerability discovery.",
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/organizationalEntity"
+ }
+ },
+ "individuals": {
+ "type": "array",
+ "title": "Individuals",
+ "description": "The individuals, not associated with organizations, that are credited with vulnerability discovery.",
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/organizationalContact"
+ }
+ }
+ }
+ },
+ "tools": {
+ "type": "array",
+ "title": "Creation Tools",
+ "description": "The tool(s) used to identify, confirm, or score the vulnerability.",
+ "additionalItems": false,
+ "items": {"$ref": "#/definitions/tool"}
+ },
+ "analysis": {
+ "type": "object",
+ "title": "Impact Analysis",
+ "description": "An assessment of the impact and exploitability of the vulnerability.",
+ "additionalProperties": false,
+ "properties": {
+ "state": {
+ "$ref": "#/definitions/impactAnalysisState"
+ },
+ "justification": {
+ "$ref": "#/definitions/impactAnalysisJustification"
+ },
+ "response": {
+ "type": "array",
+ "title": "Response",
+ "description": "A response to the vulnerability by the manufacturer, supplier, or project responsible for the affected component or service. More than one response is allowed. Responses are strongly encouraged for vulnerabilities where the analysis state is exploitable.",
+ "additionalItems": false,
+ "items": {
+ "type": "string",
+ "enum": [
+ "can_not_fix",
+ "will_not_fix",
+ "update",
+ "rollback",
+ "workaround_available"
+ ]
+ }
+ },
+ "detail": {
+ "type": "string",
+ "title": "Detail",
+ "description": "Detailed description of the impact including methods used during assessment. If a vulnerability is not exploitable, this field should include specific details on why the component or service is not impacted by this vulnerability."
+ }
+ }
+ },
+ "affects": {
+ "type": "array",
+ "uniqueItems": true,
+ "additionalItems": false,
+ "items": {
+ "required": [
+ "ref"
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "ref": {
+ "$ref": "#/definitions/refType",
+ "title": "Reference",
+ "description": "References a component or service by the objects bom-ref"
+ },
+ "versions": {
+ "type": "array",
+ "title": "Versions",
+ "description": "Zero or more individual versions or range of versions.",
+ "additionalItems": false,
+ "items": {
+ "oneOf": [
+ {
+ "required": ["version"]
+ },
+ {
+ "required": ["range"]
+ }
+ ],
+ "additionalProperties": false,
+ "properties": {
+ "version": {
+ "description": "A single version of a component or service.",
+ "$ref": "#/definitions/version"
+ },
+ "range": {
+ "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst",
+ "$ref": "#/definitions/version"
+ },
+ "status": {
+ "description": "The vulnerability status for the version or range of versions.",
+ "$ref": "#/definitions/affectedStatus",
+ "default": "affected"
+ }
+ }
+ }
+ }
+ }
+ },
+ "title": "Affects",
+ "description": "The components or services that are affected by the vulnerability."
+ },
+ "properties": {
+ "type": "array",
+ "title": "Properties",
+ "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+ "additionalItems": false,
+ "items": {
+ "$ref": "#/definitions/property"
+ }
+ }
+ }
+ },
+ "affectedStatus": {
+ "description": "The vulnerability status of a given version or range of versions of a product. The statuses 'affected' and 'unaffected' indicate that the version is affected or unaffected by the vulnerability. The status 'unknown' indicates that it is unknown or unspecified whether the given version is affected. There can be many reasons for an 'unknown' status, including that an investigation has not been undertaken or that a vendor has not disclosed the status.",
+ "type": "string",
+ "enum": [
+ "affected",
+ "unaffected",
+ "unknown"
+ ]
+ },
+ "version": {
+ "description": "A single version of a component or service.",
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 1024
+ },
+ "range": {
+ "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst",
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 1024
+ },
+ "signature": {
+ "$ref": "jsf-0.82.schema.json#/definitions/signature",
+ "title": "Signature",
+ "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+ }
+ }
+}
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index ba2a2f34d63..77170761448 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -22,7 +22,7 @@
.form-group
= f.label :shared_runners_text, _('Shared runners details'), class: 'label-bold'
= f.text_area :shared_runners_text, class: 'form-control gl-form-input', rows: 4
- .form-text.text-muted= _("Add a custom message with details about the instance's shared runners. The message is visible in group and project CI/CD settings, in the Runners section. Markdown is supported.")
+ .form-text.text-muted= _("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.")
.form-group
= f.label :max_artifacts_size, _('Maximum artifacts size (MB)'), class: 'label-bold'
= f.number_field :max_artifacts_size, class: 'form-control gl-form-input'
diff --git a/app/views/admin/application_settings/_default_branch.html.haml b/app/views/admin/application_settings/_default_branch.html.haml
index 4a06dcbc031..f9b1aa22b7a 100644
--- a/app/views/admin/application_settings/_default_branch.html.haml
+++ b/app/views/admin/application_settings/_default_branch.html.haml
@@ -14,4 +14,4 @@
= render_if_exists 'admin/application_settings/group_owners_can_manage_default_branch_protection_setting', form: f
- = f.submit _('Save changes'), class: 'gl-button btn-confirm'
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index 1af4d294c1b..30165139711 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form', id: 'merge-request-settings' } do |f|
+= gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form', id: 'merge-request-settings' } do |f|
= form_errors(@application_setting, pajamas_alert: true)
%fieldset
@@ -29,4 +29,4 @@
= link_to sprite_icon('question-o'),
help_page_path('user/admin_area/diff_limits',
anchor: 'diff-limits-administration')
- = 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 5dc2d322bb3..ff10e4a8f77 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -23,7 +23,7 @@
= link_to s_('Learn more.'), help_page_path('administration/repository_storage_paths.md'), target: '_blank', rel: 'noopener noreferrer'
.form-check
= f.fields_for :repository_storages_weighted, storage_weights do |storage_form|
- - Gitlab.config.repositories.storages.keys.each do |storage|
+ - Gitlab.config.repositories.storages.each_key do |storage|
= storage_form.text_field storage, class: 'form-text-input'
= storage_form.label storage, storage, class: 'label-bold form-check-label'
%br
diff --git a/app/views/admin/application_settings/_runner_registrars_form.html.haml b/app/views/admin/application_settings/_runner_registrars_form.html.haml
index 1d6051a06ea..7781db29bab 100644
--- a/app/views/admin/application_settings/_runner_registrars_form.html.haml
+++ b/app/views/admin/application_settings/_runner_registrars_form.html.haml
@@ -1,5 +1,5 @@
= gitlab_ui_form_for @application_setting, url: ci_cd_admin_application_settings_path(anchor: 'js-runner-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
+ = form_errors(@application_setting, pajamas_alert: true)
%fieldset
.gl-form-group
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 8684b909853..d500194b742 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -10,7 +10,7 @@
= html_escape(_('Configure %{link} to track events. %{link_start}Learn more.%{link_end}')) % { link: link_to('Snowplow', 'https://snowplowanalytics.com/', target: '_blank', rel: 'noopener noreferrer').html_safe, link_start: link_start, link_end: '</a>'.html_safe }
.settings-content
= gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-snowplow-settings'), html: { class: 'fieldset-form', id: 'snowplow-settings' } do |f|
- = form_errors(@application_setting) if expanded
+ = form_errors(@application_setting, pajamas_alert: true) if expanded
%fieldset
.form-group
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index c9ed2309cec..7326a63f8c2 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -3,7 +3,7 @@
- link_end = '</a>'.html_safe
= gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
+ = form_errors(@application_setting, pajamas_alert: true)
%fieldset
.form-group
@@ -38,7 +38,7 @@
%p.gl-mb-3= s_('AdminSettings|Registration Features include:')
- email_from_gitlab_path = help_page_path('user/admin_area/email_from_gitlab')
- repo_size_limit_path = help_page_path('user/admin_area/settings/account_and_limit_settings', anchor: 'repository-size-limit')
- - restrict_ip_path = help_page_path('user/group/index', anchor: 'restrict-group-access-by-ip-address')
+ - restrict_ip_path = help_page_path('user/group/access_and_permissions', anchor: 'restrict-group-access-by-ip-address')
- email_from_gitlab_link = link_start % { url: email_from_gitlab_path }
- repo_size_limit_link = link_start % { url: repo_size_limit_path }
- restrict_ip_link = link_start % { url: restrict_ip_path }
diff --git a/app/views/admin/application_settings/_whats_new.html.haml b/app/views/admin/application_settings/_whats_new.html.haml
index 8ae912d24b7..d82bb1c94e4 100644
--- a/app/views/admin/application_settings/_whats_new.html.haml
+++ b/app/views/admin/application_settings/_whats_new.html.haml
@@ -1,7 +1,7 @@
= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-whats-new-settings'), html: { class: 'fieldset-form whats-new-settings' } do |f|
= form_errors(@application_setting, pajamas_alert: true)
- - whats_new_variants.keys.each do |variant|
+ - whats_new_variants.each_key do |variant|
.gl-mb-4
= f.gitlab_ui_radio_component :whats_new_variant, variant, whats_new_variants_label(variant), help_text: whats_new_variants_description(variant)
diff --git a/app/views/admin/application_settings/appearances/_form.html.haml b/app/views/admin/application_settings/appearances/_form.html.haml
index 224d9fbe953..349e1dfde5d 100644
--- a/app/views/admin/application_settings/appearances/_form.html.haml
+++ b/app/views/admin/application_settings/appearances/_form.html.haml
@@ -40,7 +40,7 @@
= f.hidden_field :favicon_cache
= f.file_field :favicon, class: '', accept: 'image/*'
.form-text.text-muted
- = _("Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}.") % { favicon_extension_whitelist: favicon_extension_whitelist }
+ = _("Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}.") % { favicon_extension_allowlist: favicon_extension_allowlist }
%br
= _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
index 180871e48dd..b603c7e5f49 100644
--- a/app/views/admin/applications/index.html.haml
+++ b/app/views/admin/applications/index.html.haml
@@ -29,8 +29,6 @@
%th
= _('Callback URL')
%th
- = _('Clients')
- %th
= _('Trusted')
%th
= _('Confidential')
@@ -41,7 +39,6 @@
%tr{ id: "application_#{application.id}" }
%td= link_to application.name, admin_application_path(application)
%td= application.redirect_uri
- %td= @application_counts[application.id].to_i
%td= application.trusted? ? _('Yes'): _('No')
%td= application.confidential? ? _('Yes'): _('No')
%td= link_to 'Edit', edit_admin_application_path(application), class: 'gl-button btn btn-link'
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 88fbbb28201..271f89a6b08 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -58,7 +58,7 @@
= link_to(s_('AdminArea|New user'), new_admin_user_path, class: "btn gl-button btn-default")
= c.footer do
.d-flex.align-items-center
- = link_to(s_('AdminArea|View latest users'), admin_users_path)
+ = link_to(s_('AdminArea|View latest users'), admin_users_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|
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 7bcc97914e5..a254690de72 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -9,7 +9,7 @@
= _('Update your group name, description, avatar, and visibility.')
= link_to _('Learn more about groups.'), help_page_path('user/group/index')
.col-lg-8
- = render 'shared/group_form', f: f
+ = render 'shared/groups/group_name_and_path_fields', f: f
= render 'shared/group_form_description', f: f
.form-group.gl-form-group{ role: 'group' }
= f.label :avatar, _("Group avatar"), class: 'gl-display-block col-form-label'
diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml
index e8176e9f8bb..224afbff39a 100644
--- a/app/views/admin/hooks/edit.html.haml
+++ b/app/views/admin/hooks/edit.html.haml
@@ -15,6 +15,6 @@
= 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' }
- %hr
+%hr
- = render partial: 'admin/hook_logs/index', locals: { hook: @hook, hook_logs: @hook_logs }
+= render partial: 'shared/hook_logs/index', locals: { hook: @hook, hook_logs: @hook_logs }
diff --git a/app/views/admin/identities/_identity.html.haml b/app/views/admin/identities/_identity.html.haml
index d852e4a2463..3121cd2ae59 100644
--- a/app/views/admin/identities/_identity.html.haml
+++ b/app/views/admin/identities/_identity.html.haml
@@ -1,12 +1,24 @@
%tr
%td
- #{Gitlab::Auth::OAuth::Provider.label_for(identity.provider)} (#{identity.provider}) #{identity.saml_provider_id.present? ? "for #{link_to identity.saml_provider.group.path, identity.saml_provider.group} ID: #{identity.saml_provider_id}".html_safe : ""}
+ = label_for_identity_provider(identity)
+ %td{ data: { testid: provider_id_cell_testid(identity) } }
+ = provider_id(identity)
+ %td{ data: { testid: saml_group_cell_testid(identity) } }
+ = saml_group_link(identity)
%td
= identity.extern_uid
- %td
- = link_to edit_admin_user_identity_path(@user, identity), class: 'gl-button btn btn-sm btn-grouped' do
- = _("Edit")
- = link_to [:admin, @user, identity], method: :delete,
- class: 'gl-button btn btn-sm btn-danger',
- data: { confirm: _("Are you sure you want to remove this identity?") } do
- = _('Delete')
+ %td{ class: 'gl-py-0!' }
+ - button_classes = 'has-tooltip gl-my-3'
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ href: edit_admin_user_identity_path(@user, identity),
+ icon: 'pencil',
+ button_options: { title: _('Edit'),
+ 'aria-label' => _('Edit'),
+ class: button_classes } )
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ href: url_for([:admin, @user, identity]),
+ icon: 'remove',
+ button_options: { title: _('Delete'),
+ 'aria-label' => _('Delete identity'),
+ class: button_classes,
+ data: { method: :delete, confirm: _("Are you sure you want to remove this identity?") } } )
diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml
index 2bab802b2c1..1bb14969939 100644
--- a/app/views/admin/identities/index.html.haml
+++ b/app/views/admin/identities/index.html.haml
@@ -3,14 +3,20 @@
- page_title _("Identities"), @user.name, _("Users")
= render 'admin/users/head'
-- if @identities.present?
- .table-holder
- %table.table
- %thead
- %tr
- %th= _('Provider')
- %th= _('Identifier')
- %th
- = render @identities
-- else
- %h4= _('This user has no identities')
+%table.table.gl-table
+ %thead
+ %tr
+ %th{ class: 'gl-border-t-0!' }= _('Provider')
+ %th{ class: 'gl-border-t-0!' }= s_('Identity|Provider ID')
+ %th{ class: 'gl-border-t-0!' }= _('Group')
+ %th{ class: 'gl-border-t-0!' }= _('Identifier')
+ %th{ class: 'gl-border-t-0!' }= _('Actions')
+ - if identity_cells_to_render?(@identities, @user)
+ = render_if_exists partial: 'admin/identities/scim_identity', collection: scim_identities_collection(@user)
+ = render @identities
+ - else
+ %tbody
+ %tr
+ %td{ colspan: '5' }
+ .text-center.my-2
+ = _('This user has no identities')
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index ae8fed8964f..333c865629f 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -1,7 +1,7 @@
%li.label-list-item{ id: dom_id(label) }
= render "shared/label_row", label: label.present(issuable_subject: nil)
.label-actions-list
- = link_to edit_admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
+ = link_to edit_admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria: { label: _('Edit') } do
= sprite_icon('pencil')
= link_to admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary hover-red js-remove-label label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: _('Are you sure you want to delete this label?'), confirm_btn_variant: 'danger' }, aria: { label: _('Delete label') }, method: :delete, remote: true do
= sprite_icon('remove')
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 22351397b9a..a9dbcf4a6a5 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -1,4 +1,5 @@
- add_page_specific_style 'page_bundles/ci_status'
+- add_page_specific_style 'page_bundles/runner_details'
- title = "##{@runner.id} (#{@runner.short_sha})"
- breadcrumb_title title
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index ed453b42725..0ceff211806 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -45,5 +45,5 @@
= gl_tab_link_to _("SSH keys"), keys_admin_user_path(@user)
= gl_tab_link_to _("Identities"), admin_user_identities_path(@user)
- if impersonation_enabled?
- = gl_tab_link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user)
+ = gl_tab_link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user), data: { qa_selector: 'impersonation_tokens_tab' }
.gl-mb-3
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index 9ef2599a2a6..02c468cebd7 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -6,10 +6,15 @@
= s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- is_group = !@group.nil?
+- is_project = !@project.nil?
#js-ci-project-variables{ data: { endpoint: save_endpoint,
+ is_project: is_project.to_s,
project_id: @project&.id || '',
- group: is_group.to_s,
+ project_full_path: @project&.full_path || '',
+ is_group: is_group.to_s,
+ group_id: @group&.id || '',
+ group_path: @group&.full_path,
maskable_regex: ci_variable_maskable_regex,
protected_by_default: ci_variable_protected_by_default?.to_s,
aws_logo_svg_path: image_path('aws_logo.svg'),
diff --git a/app/views/clusters/clusters/_gitlab_integration_form.html.haml b/app/views/clusters/clusters/_gitlab_integration_form.html.haml
index b6d6dcdd7a9..e0f5a984529 100644
--- a/app/views/clusters/clusters/_gitlab_integration_form.html.haml
+++ b/app/views/clusters/clusters/_gitlab_integration_form.html.haml
@@ -1,3 +1,3 @@
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'js-cluster-details-form' } do |field|
- = form_errors(@cluster)
+ = form_errors(@cluster, pajamas_alert: true)
#js-cluster-details-form{ data: js_cluster_form_data(@cluster, can?(current_user, :update_cluster, @cluster)) }
diff --git a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
index 3e0a8a4f88b..88da252f2bb 100644
--- a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
+++ b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
@@ -2,7 +2,7 @@
- help_path = local_assigns.fetch(:help_path)
- label = local_assigns.fetch(:label)
- last = local_assigns.fetch(:last, false)
-- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-flex-basis-0 gl-flex-grow-1 gl-min-w-0"]
+- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-flex-basis-third "]
- conditional_classes = [("gl-mr-5" unless last)]
= link_to help_path, class: classes + conditional_classes do
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index f0f1413831a..813c1cdbfe4 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -3,7 +3,7 @@
- if current_user.can_create_group?
.page-title-controls
- = link_to _("New group"), new_group_path, class: "gl-button btn btn-confirm", data: { testid: "new-group-button" }
+ = link_to _("New group"), new_group_path, class: "gl-button btn btn-confirm", data: { qa_selector: "new_group_button", testid: "new-group-button" }
.top-area
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml
index c90a9e7c672..1400ac9ca72 100644
--- a/app/views/devise/passwords/new.html.haml
+++ b/app/views/devise/passwords/new.html.haml
@@ -4,7 +4,7 @@
.devise-errors
= render "devise/shared/error_messages", resource: resource
.form-group.gl-px-5.gl-pt-5
- = f.label :email
+ = f.label :email, class: ("gl-mb-1" if Feature.enabled?(:restyle_login_page))
= f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
.form-text.text-muted
= _('Requires your primary GitLab email address.')
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index b6acb244384..b6719834358 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -11,5 +11,6 @@
= render 'devise/shared/signup_box',
url: registration_path(resource_name),
button_text: _('Register'),
+ borderless: Feature.enabled?(:restyle_login_page, @project),
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 48b38861e6e..5a322a8f89b 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -3,7 +3,7 @@
= render_if_exists 'devise/sessions/new_base_user_login_label', form: f
= f.text_field :login, value: @invite_email, class: 'form-control gl-form-input top js-username-field', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field', testid: 'username-field' }
.form-group.gl-px-5
- = f.label :password, class: 'label-bold'
+ = f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.password_field :password, class: 'form-control gl-form-input bottom', autocomplete: 'current-password', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
- if devise_mapping.rememberable?
.gl-px-5
@@ -23,3 +23,6 @@
.submit-container.move-submit-down.gl-px-5
= f.button _('Sign in'), type: :submit, class: "gl-button btn btn-block btn-confirm js-sign-in-button#{' js-no-auto-disable' if Feature.enabled?(:arkose_labs_login_challenge)}", data: { qa_selector: 'sign_in_button', testid: 'sign-in-button' }
+ - if Gitlab::CurrentSettings.sign_in_text.present? && Feature.enabled?(:restyle_login_page, @project)
+ .gl-px-5
+ = markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
diff --git a/app/views/devise/sessions/_new_base_user_login_label.html.haml b/app/views/devise/sessions/_new_base_user_login_label.html.haml
index 2aa66684cad..8a8b9f7a361 100644
--- a/app/views/devise/sessions/_new_base_user_login_label.html.haml
+++ b/app/views/devise/sessions/_new_base_user_login_label.html.haml
@@ -1 +1 @@
-= local_assigns[:form].label _('Username or email'), for: 'user_login', class: 'label-bold'
+= local_assigns[:form].label _('Username or email'), for: 'user_login', class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 9a09f6bee38..f4db9ea5637 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -18,10 +18,9 @@
= _('No authentication methods configured.')
- if allow_signup?
- %p.gl-mt-3
+ %p{ class: "gl-mt-3 #{'gl-text-center' if Feature.enabled?(:restyle_login_page, @project)}" }
= _("Don't have an account yet?")
- = link_to _("Register now"), new_registration_path(:user, invite_email: @invite_email), data: { qa_selector: 'register_link' }
-
+ = link_to _("Register now"), new_registration_path(:user, invite_email: @invite_email), data: { qa_selector: 'register_link' }, class: "#{'gl-font-weight-bold' if Feature.enabled?(:restyle_login_page, @project)} "
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
.clearfix
= render 'devise/shared/omniauth_box'
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 77a2fda021f..fd20ff9a418 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -1,5 +1,5 @@
%div
- = render 'devise/shared/tab_single', tab_title: _('Two-Factor Authentication')
+ = render 'devise/shared/tab_single', tab_title: _('Two-Factor Authentication') if Feature.disabled?(:restyle_login_page, @project)
.login-box.gl-p-5
.login-body
- if @user.two_factor_otp_enabled?
@@ -7,7 +7,7 @@
- resource_params = params[resource_name].presence || params
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
- = f.label _('Two-Factor Authentication code'), name: :otp_attempt
+ = f.label _('Two-Factor Authentication code'), name: :otp_attempt, class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-mb-1' : ''
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
%p.form-text.text-muted.hint= _("Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.")
.prepend-top-20
diff --git a/app/views/devise/shared/_footer.html.haml b/app/views/devise/shared/_footer.html.haml
index 5803107a8f7..10cfc07a719 100644
--- a/app/views/devise/shared/_footer.html.haml
+++ b/app/views/devise/shared/_footer.html.haml
@@ -5,4 +5,5 @@
= link_to _("Explore"), explore_root_path
= link_to _("Help"), help_path
= link_to _("About GitLab"), "https://#{ApplicationHelper.promo_host}"
+ = link_to _("Community forum"), ApplicationHelper.community_forum, target: '_blank', class: 'text-nowrap', rel: 'noopener noreferrer'
= footer_message
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 32b4a15517e..d67669352a6 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,20 +1,19 @@
- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
-
-.omniauth-container.gl-mt-5.gl-p-5
- %label.gl-font-weight-bold
+%div{ class: Feature.enabled?(:restyle_login_page, @project) ? 'omniauth-container gl-mt-5 gl-p-5 gl-text-center gl-w-90p gl-ml-auto gl-mr-auto' : 'omniauth-container gl-mt-5 gl-p-5' }
+ %label{ class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-font-weight-normal' : 'gl-font-weight-bold' }
= _('Sign in with')
- providers = enabled_button_based_providers
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default gl-w-full js-oauth-login #{qa_class_for_provider(provider)}", form: { class: 'gl-w-full gl-mb-3' } do
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default gl-ml-2 gl-mr-2 gl-mb-2 js-oauth-login #{qa_class_for_provider(provider)} #{'gl-w-full' if Feature.disabled?(:restyle_login_page, @project)}", form: { class: 'gl-w-full gl-mb-3' } do
- if has_icon
= provider_image_tag(provider)
%span.gl-button-text
= label_for_provider(provider)
- unless hide_remember_me
%fieldset
- %label
+ %label{ class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-font-weight-normal' : '' }
= check_box_tag :remember_me, nil, false
%span
= _('Remember me')
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 1868cfa06e9..991af1eea0c 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -13,7 +13,7 @@
= invisible_captcha nonce: true, autocomplete: SecureRandom.alphanumeric(12)
.name.form-row
.col.form-group
- = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
+ = f.label :first_name, _('First name'), for: 'new_user_first_name', class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.text_field :first_name,
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
data: { max_length: max_first_name_length,
@@ -22,7 +22,7 @@
required: true,
title: _('This field is required.')
.col.form-group
- = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
+ = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.text_field :last_name,
class: 'form-control gl-form-input top js-block-emoji js-validate-length',
data: { max_length: max_last_name_length,
@@ -31,7 +31,7 @@
required: true,
title: _('This field is required.')
.username.form-group
- = f.label :username, class: 'label-bold'
+ = f.label :username, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.text_field :username,
class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username',
data: signup_username_data_attributes,
@@ -42,18 +42,19 @@
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
.form-group
- = f.label :email, class: 'label-bold'
+ = f.label :email, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.email_field :email,
value: @invite_email,
class: 'form-control gl-form-input middle js-validate-email',
data: { qa_selector: 'new_user_email_field' },
required: true,
title: _('Please provide a valid email address.')
- %p.gl-field-hint.text-secondary= _('We recommend a work email address.')
+ %p.validation-hint.gl-field-hint.text-secondary= _('We recommend a work email address.')
+ %p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
-# This is used for providing entry to Jihu on email verification
= render_if_exists 'devise/shared/signup_email_additional_info'
.form-group.gl-mb-5#password-strength
- = f.label :password, class: 'label-bold'
+ = f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.password_field :password,
class: 'form-control gl-form-input bottom js-password-complexity-validation',
data: { qa_selector: 'new_user_password_field' },
@@ -69,6 +70,9 @@
= recaptcha_tags nonce: content_security_policy_nonce
.submit-container.gl-mt-5
= f.submit button_text, class: 'btn gl-button btn-confirm gl-display-block gl-w-full', data: { qa_selector: 'new_user_register_button' }
+ - if Gitlab::CurrentSettings.sign_in_text.present? && Feature.enabled?(:restyle_login_page, @project)
+ .gl-pt-5
+ = markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
= render 'devise/shared/terms_of_service_notice', button_text: button_text
- if show_omniauth_providers && omniauth_providers_placement == :bottom
= render 'devise/shared/signup_omniauth_providers'
diff --git a/app/views/devise/shared/_signup_omniauth_provider_list.haml b/app/views/devise/shared/_signup_omniauth_provider_list.haml
index 84aabbe0efd..8dc22674243 100644
--- a/app/views/devise/shared/_signup_omniauth_provider_list.haml
+++ b/app/views/devise/shared/_signup_omniauth_provider_list.haml
@@ -1,11 +1,22 @@
- register_omniauth_params = Feature.enabled?(:update_oauth_registration_flow) ? { intent: :register } : {}
-
-%label.gl-font-weight-bold
- = _("Create an account using:")
-.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- - providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
- - if provider_has_icon?(provider)
- = provider_image_tag(provider)
- %span.gl-button-text
- = label_for_provider(provider)
+- if Feature.enabled?(:restyle_login_page, @project)
+ .gl-text-center.gl-pt-5
+ %label.gl-font-weight-normal
+ = _("Create an account using:")
+ .gl-text-center.gl-w-90p.gl-ml-auto.gl-mr-auto
+ - providers.each do |provider|
+ = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-ml-2 gl-mr-2 gl-mb-2 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
+ - if provider_has_icon?(provider)
+ = provider_image_tag(provider)
+ %span.gl-button-text
+ = label_for_provider(provider)
+- else
+ %label.gl-font-weight-bold
+ = _("Create an account using:")
+ .gl-display-flex.gl-justify-content-between.gl-flex-wrap
+ - providers.each do |provider|
+ = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
+ - if provider_has_icon?(provider)
+ = provider_image_tag(provider)
+ %span.gl-button-text
+ = label_for_provider(provider)
diff --git a/app/views/devise/shared/_signup_omniauth_providers.haml b/app/views/devise/shared/_signup_omniauth_providers.haml
index 30a54ab86a6..d2a47974e01 100644
--- a/app/views/devise/shared/_signup_omniauth_providers.haml
+++ b/app/views/devise/shared/_signup_omniauth_providers.haml
@@ -1,3 +1,4 @@
-.omniauth-divider.gl-display-flex.gl-align-items-center
- = _("or")
+- if Feature.disabled?(:restyle_login_page, @project)
+ .omniauth-divider.gl-display-flex.gl-align-items-center
+ = _("or")
= render 'devise/shared/signup_omniauth_provider_list', providers: enabled_button_based_providers
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 62d6ab36578..4a6b7fcfa84 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -21,8 +21,7 @@
%ul.content-list.event-commits
= render "events/commit", project: project, event: event
- - create_mr = event.new_ref? && create_mr_button?(from: project.default_branch, to: event.ref_name, source_project: project, target_project: project) && event.authored_by?(current_user)
- - create_mr_path = create_mr_path(from: project.default_branch, to: event.ref_name, source_project: project, target_project: project) if create_mr
+ - create_mr = event.new_ref? && create_mr_button_from_event?(event) && event.authored_by?(current_user)
- if event.commits_count > 1
%li.commits-stat
%span ... and #{pluralize(event.commits_count - 1, 'more commit')}.
@@ -41,9 +40,9 @@
- if create_mr
%span
or
- = link_to create_mr_path do
+ = link_to create_mr_path_from_push_event(event) do
create a merge request
- elsif create_mr
%li.commits-stat
- = link_to create_mr_path do
+ = link_to create_mr_path_from_push_event(event) do
Create merge request
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index bd893ca3162..2911e9991f2 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -33,7 +33,10 @@
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-mx-2 gl-mt-3 gl-vertical-align-top', no_flip: 'true' } }
- if can_create_subgroups
.gl-px-2.gl-sm-w-auto.gl-w-full
- = link_to _("New subgroup"), new_group_path(parent_id: @group.id), class: "btn btn-default gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_subgroup_button' }
+ = link_to _("New subgroup"),
+ new_group_path(parent_id: @group.id, anchor: 'create-group-pane'),
+ class: "btn btn-default gl-button gl-mt-3 gl-sm-w-auto gl-w-full",
+ data: { qa_selector: 'new_subgroup_button' }
- if can_create_projects
.gl-px-2.gl-sm-w-auto.gl-w-full
= link_to _("New project"), new_project_path(namespace_id: @group.id), class: "btn btn-confirm gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_project_button' }
diff --git a/app/views/groups/_new_group_fields.html.haml b/app/views/groups/_new_group_fields.html.haml
index 0527d38159b..632884051f0 100644
--- a/app/views/groups/_new_group_fields.html.haml
+++ b/app/views/groups/_new_group_fields.html.haml
@@ -1,31 +1,34 @@
+- parent = @group.parent
+- submit_label = parent ? s_('GroupsNew|Create subgroup') : s_('GroupsNew|Create group')
= form_errors(@group, pajamas_alert: true)
-= render 'shared/group_form', f: f, autofocus: true
+= render 'shared/groups/group_name_and_path_fields', f: f, autofocus: true, new_subgroup: !!parent
-.row
- .form-group.gl-form-group.col-sm-12
- %label.label-bold
- = _('Visibility level')
- %p
- = _('Who will be able to see this group?')
- = link_to _('View the documentation'), help_page_path("user/public_access"), target: '_blank', rel: 'noopener noreferrer'
- = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
-
-- if Gitlab.config.mattermost.enabled
+- unless parent
.row
- = render 'create_chat_team', f: f
+ .form-group.gl-form-group.col-sm-12
+ %label.label-bold
+ = _('Visibility level')
+ %p
+ = _('Who will be able to see this group?')
+ = link_to _('View the documentation'), help_page_path("user/public_access"), target: '_blank', rel: 'noopener noreferrer'
+ = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
-- unless Gitlab::CurrentSettings.current_application_settings.hide_third_party_offers?
- = render 'personalize', f: f
+ - if Gitlab.config.mattermost.enabled
+ .row
+ = render 'create_chat_team', f: f
-.row.js-invite-members-section
- .col-sm-4
- = render_if_exists 'shared/groups/invite_members'
+ - unless Gitlab::CurrentSettings.current_application_settings.hide_third_party_offers?
+ = render 'personalize', f: f
-- if captcha_required?
- .row.recaptcha
+ .row.js-invite-members-section
.col-sm-4
- = recaptcha_tags nonce: content_security_policy_nonce
+ = render_if_exists 'shared/groups/invite_members'
+
+ - if captcha_required?
+ .row.recaptcha
+ .col-sm-4
+ = recaptcha_tags nonce: content_security_policy_nonce
.row
.col-sm-12
- = f.submit _('Create group'), class: "btn gl-button btn-confirm"
+ = f.submit submit_label, class: "btn gl-button btn-confirm", data: { qa_selector: 'create_group_button' }
= link_to _('Cancel'), dashboard_groups_path, class: 'btn gl-button btn-default btn-cancel'
diff --git a/app/views/groups/crm/contacts/index.html.haml b/app/views/groups/crm/contacts/index.html.haml
index 8a971e451a4..27f18ac1c57 100644
--- a/app/views/groups/crm/contacts/index.html.haml
+++ b/app/views/groups/crm/contacts/index.html.haml
@@ -5,4 +5,4 @@
= content_for :after_content do
#js-crm-form-portal
-#js-crm-contacts-app{ data: { group_full_path: @group.full_path, group_issues_path: issues_group_path(@group), group_id: @group.id, can_admin_crm_contact: can?(current_user, :admin_crm_contact, @group).to_s, base_path: group_crm_contacts_path(@group) } }
+#js-crm-contacts-app{ data: { group_full_path: @group.full_path, group_issues_path: issues_group_path(@group), group_id: @group.id, can_admin_crm_contact: can?(current_user, :admin_crm_contact, @group).to_s, base_path: group_crm_contacts_path(@group), text_query: params[:search] } }
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 082f637e854..178d8980ab8 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -2,4 +2,6 @@
- @content_class = "limit-container-width" unless fluid_layout
#js-dependency-proxy{ data: { group_path: @group.full_path,
- no_manifests_illustration: image_path('illustrations/docker-empty-state.svg'), group_id: @group.id } }
+ no_manifests_illustration: image_path('illustrations/docker-empty-state.svg'),
+ group_id: @group.id,
+ can_clear_cache: can?(current_user, :admin_group, @group).to_s } }
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index 7da5a9e9664..9f13ad301bb 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -1,4 +1,4 @@
-= form_for [@group, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
+= gitlab_ui_form_for [@group, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone, pajamas_alert: true)
.form-group.row
.col-form-label.col-sm-2
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 3fb2b88dadd..8384c906eeb 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -6,7 +6,8 @@
.group-edit-container.gl-mt-5
- .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(verification_for_group_creation_data) }
+ .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(subgroup_creation_data(@group),
+ verification_for_group_creation_data) }
.row{ 'v-cloak': true }
#create-group-pane.tab-pane
diff --git a/app/views/groups/runners/show.html.haml b/app/views/groups/runners/show.html.haml
index 65e797a2e82..2fc314cc37f 100644
--- a/app/views/groups/runners/show.html.haml
+++ b/app/views/groups/runners/show.html.haml
@@ -1,10 +1,8 @@
-- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
+- add_page_specific_style 'page_bundles/runner_details'
-- if Feature.enabled?(:group_runner_view_ui, @group)
- - title = "##{@runner.id} (#{@runner.short_sha})"
- - breadcrumb_title title
- - page_title title
+- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
+- title = "##{@runner.id} (#{@runner.short_sha})"
+- breadcrumb_title title
+- page_title title
- #js-group-runner-show{ data: {runner_id: @runner.id, runners_path: group_runners_path(@group), edit_group_runner_path: edit_group_runner_path(@group, @runner)} }
-- else
- = render 'shared/runners/runner_details', runner: @runner
+#js-group-runner-show{ data: {runner_id: @runner.id, runners_path: group_runners_path(@group), edit_group_runner_path: edit_group_runner_path(@group, @runner)} }
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index 3624ff2bcb3..8fa8eeea3cd 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -8,7 +8,7 @@
.form-group
%p
= s_("GroupSettings|Changing a group's URL can have unintended side effects.")
- = link_to _('Learn more.'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('user/group/manage', anchor: 'change-a-groups-path'), target: '_blank', rel: 'noopener noreferrer'
.input-group.gl-field-error-anchor
.group-root-path.input-group-prepend.has-tooltip{ title: group_path(@group), :'data-placement' => 'bottom' }
diff --git a/app/views/groups/settings/access_tokens/index.html.haml b/app/views/groups/settings/access_tokens/index.html.haml
index 16ea96f0b08..ac6c5d1842c 100644
--- a/app/views/groups/settings/access_tokens/index.html.haml
+++ b/app/views/groups/settings/access_tokens/index.html.haml
@@ -37,7 +37,7 @@
token: @resource_access_token,
scopes: @scopes,
access_levels: GroupMember.access_level_roles,
- default_access_level: Gitlab::Access::MAINTAINER,
+ default_access_level: Gitlab::Access::GUEST,
prefix: :resource_access_token,
help_path: help_page_path('user/group/settings/group_access_tokens', anchor: 'scopes-for-a-group-access-token')
diff --git a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
index c294df5ac62..3691c470ea7 100644
--- a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
@@ -2,7 +2,7 @@
= form_errors(group, pajamas_alert: true)
%fieldset
.form-group
- .card.auto-devops-card
+ .card.gl-mb-3
.card-body
- learn_more_link = link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer'
- help_text = s_('GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 3b117022d1e..88352ea351c 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -32,7 +32,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
- = link_to s_('How do I configure runners?'), help_page_path('ci/runners/index'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to s_('What is GitLab Runner?'), 'https://docs.gitlab.com/runner/', target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'groups/runners/settings'
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index 08f7cd57732..35fd5d6eda6 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -13,9 +13,9 @@
can_select_namespace: current_user.can_select_namespace?.to_s,
ci_cd_only: has_ci_cd_only_params?.to_s,
namespaces_path: import_available_namespaces_path,
- repos_path: url_for([:status, :import, provider, format: :json]),
- jobs_path: url_for([:realtime_changes, :import, provider, format: :json]),
+ repos_path: url_for([:status, :import, provider, { format: :json }]),
+ jobs_path: url_for([:realtime_changes, :import, provider, { format: :json }]),
default_target_namespace: default_namespace_path,
- import_path: url_for([:import, provider, format: :json]),
+ import_path: url_for([:import, provider, { format: :json }]),
filterable: filterable.to_s,
paginatable: paginatable.to_s }.merge(extra_data) }
diff --git a/app/views/layouts/_google_tag_manager_head.html.haml b/app/views/layouts/_google_tag_manager_head.html.haml
index 25af51ca9cb..f5c823465be 100644
--- a/app/views/layouts/_google_tag_manager_head.html.haml
+++ b/app/views/layouts/_google_tag_manager_head.html.haml
@@ -1,4 +1,23 @@
- return unless google_tag_manager_enabled?
+- if Feature.enabled?(:gitlab_gtm_datalayer, type: :ops)
+ = javascript_tag do
+ :plain
+ window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+
+ gtag('consent', 'default', {
+ 'analytics_storage': 'denied',
+ 'ad_storage': 'denied',
+ 'functionality_storage': 'denied',
+ 'region': ['EU', 'UK', 'PE', 'RU'],
+ 'wait_for_update': 500
+ });
+ gtag('consent', 'default', {
+ 'analytics_storage': 'granted',
+ 'ad_storage': 'granted',
+ 'functionality_storage': 'granted',
+ 'wait_for_update': 500
+ });
- if Feature.enabled?(:gtm_nonce, type: :ops)
= javascript_tag nonce: content_security_policy_nonce do
diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml
index 0dad6d367c3..22cc8027202 100644
--- a/app/views/layouts/_snowplow.html.haml
+++ b/app/views/layouts/_snowplow.html.haml
@@ -12,6 +12,9 @@
window.snowplowOptions = #{Gitlab::Tracking.options(@group).to_json}
gl = window.gl || {};
- gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(namespace: namespace,
- project: @project, user: current_user).to_context.to_json.to_json}
+ gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(
+ namespace: namespace,
+ project: @project,
+ user: current_user
+ ).to_context.to_json.to_json}
gl.snowplowPseudonymizedPageUrl = #{masked_page_url(group: namespace, project: @project).to_json};
diff --git a/app/views/layouts/component_preview.html.haml b/app/views/layouts/component_preview.html.haml
new file mode 100644
index 00000000000..ec12395a5d4
--- /dev/null
+++ b/app/views/layouts/component_preview.html.haml
@@ -0,0 +1,5 @@
+%head
+ = stylesheet_link_tag "application"
+ = stylesheet_link_tag "application_utilities"
+%body{ style: "background-color: #{params.dig(:lookbook, :display, :bg_color) || 'white'}" }
+ .container.gl-mt-6= yield
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index cb1a2a8c690..87a8b6dd870 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -4,39 +4,61 @@
%body.login-page.application.navless{ class: "#{user_application_theme} #{client_class_list}", data: { page: body_data_page, qa_selector: 'login_page' } }
= header_message
= render "layouts/init_client_detection_flags"
- .page-wrap
- = render "layouts/header/empty"
- .login-page-broadcast
- = render "layouts/broadcast"
- .container.navless-container
- .content
- = render "layouts/flash"
- .row.mt-3
- .col-sm-12
- %h1.mb-3.font-weight-normal
- = current_appearance&.title.presence || _('GitLab')
- .row.mb-3
- .col-md-6.order-12.order-sm-1.brand-holder
- - unless recently_confirmed_com?
- = brand_image
+ - if Feature.enabled?(:restyle_login_page, @project)
+ .page-wrap.borderless
+ .login-page-broadcast
+ = render "layouts/broadcast"
+ .container.navless-container
+ .content
+ = render "layouts/flash"
+ .mt-3
+ .col-sm-12.gl-text-center
+ %img.gl-w-10{ :alt => _("GitLab Logo"), :src => image_path('logo.svg') }
+ %h1.mb-3.gl-font-size-h2
+ = current_appearance&.title.presence || _('GitLab')
- if current_appearance&.description?
= brand_text
- - else
- %h3.gl-sm-mt-0
- = _('A complete DevOps platform')
+ .mb-3
+ .gl-w-half.gl-xs-w-full.gl-ml-auto.gl-mr-auto.bar
+ = yield
+ = render_if_exists 'layouts/devise_help_text'
- %p
- = _('GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security.')
- %p
- = _('This is a self-managed instance of GitLab.')
+ = render 'devise/shared/footer', footer_message: footer_message
+ - else
+ .page-wrap
+ = render "layouts/header/empty"
+ .login-page-broadcast
+ = render "layouts/broadcast"
+ .container.navless-container
+ .content
+ = render "layouts/flash"
+ .row.mt-3
+ .col-sm-12
+ %h1.mb-3.font-weight-normal
+ = current_appearance&.title.presence || _('GitLab')
+ .row.mb-3
+ .col-md-6.order-12.order-sm-1.brand-holder
+ - unless recently_confirmed_com?
+ = brand_image
+ - if current_appearance&.description?
+ = brand_text
+ - else
+ %h3.gl-sm-mt-0
+ = _('A complete DevOps platform')
- - if Gitlab::CurrentSettings.sign_in_text.present?
- = markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
+ %p
+ = _('GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security.')
- = render_if_exists 'layouts/devise_help_text'
+ %p
+ = _('This is a self-managed instance of GitLab.')
- .col-md-6.order-1.new-session-forms-container{ class: recently_confirmed_com? ? 'order-sm-first' : 'order-sm-12' }
- = yield
+ - if Gitlab::CurrentSettings.sign_in_text.present?
+ = markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
- = render 'devise/shared/footer', footer_message: footer_message
+ = render_if_exists 'layouts/devise_help_text'
+
+ .col-md-6.order-1.new-session-forms-container{ class: recently_confirmed_com? ? 'order-sm-first' : 'order-sm-12' }
+ = yield
+
+ = render 'devise/shared/footer', footer_message: footer_message
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 1c2ab8cf008..67809cbc608 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -6,8 +6,8 @@
- @left_sidebar = true
- content_for :flash_message do
- = render "layouts/header/storage_enforcement_banner", namespace: @group
- = dispensable_render_if_exists "shared/namespace_storage_limit_alert"
+ = render "layouts/header/storage_enforcement_banner", context: @group
+ = dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: @group
- content_for :page_specific_javascripts do
- if current_user
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 11dd8ba6c08..353f07c07c5 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -12,7 +12,7 @@
- if can?(current_user, :update_user_status, current_user)
%li
%button.gl-button.btn.btn-link.menu-item.js-set-status-modal-trigger{ type: 'button' }
- - if show_status_emoji?(current_user.status) || user_status_set_to_busy?(current_user.status)
+ - if current_user.status&.busy? || current_user.status&.customized?
= s_('SetStatusModal|Edit status')
- else
= s_('SetStatusModal|Set status')
diff --git a/app/views/layouts/header/_current_user_dropdown_item.html.haml b/app/views/layouts/header/_current_user_dropdown_item.html.haml
index 06c597b4932..3fded43ee4f 100644
--- a/app/views/layouts/header/_current_user_dropdown_item.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown_item.html.haml
@@ -1,11 +1,11 @@
.gl-font-weight-bold
= current_user.name
- - if current_user&.status && user_status_set_to_busy?(current_user.status)
+ - if current_user.status&.busy?
%span.gl-font-weight-normal.gl-text-gray-500= s_("UserProfile|(Busy)")
= current_user.to_reference
- if current_user.status
.user-status.d-flex.align-items-center.gl-mt-2.gl-mr-0.gl-font-sm.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
- - if show_status_emoji?(current_user.status)
+ - if current_user.status.customized?
.user-status-emoji.d-flex.align-items-center
= emoji_icon current_user.status.emoji
%span.user-status-message.str-truncated
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 911cb85de53..783733bb313 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -8,7 +8,7 @@
.title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0
.title
%span.gl-sr-only GitLab
- = link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
+ = link_to root_path, title: _('Dashboard'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
= brand_header_logo
- if Gitlab.com_and_canary?
= link_to Gitlab::Saas.canary_toggle_com_url, class: 'canary-badge bg-transparent', data: { qa_selector: 'canary_badge_link' }, target: :_blank, rel: 'noopener noreferrer' do
@@ -57,8 +57,8 @@
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter dropdown" }) do
- - top_level_link = current_user.mr_attention_requests_enabled? ? attention_requested_mrs_dashboard_path : assigned_mrs_dashboard_path
- = link_to top_level_link, class: 'dashboard-shortcuts-merge_requests', title: _('Merge requests'), aria: { label: _('Merge requests') },
+ - top_level_link = assigned_mrs_dashboard_path
+ = link_to top_level_link, class: 'dashboard-shortcuts-merge_requests has-tooltip', title: _('Merge requests'), aria: { label: _('Merge requests') },
data: { qa_selector: 'merge_requests_shortcut_button',
toggle: "dropdown",
placement: 'bottom',
@@ -74,27 +74,14 @@
%ul
%li.dropdown-header
= _('Merge requests')
- - if current_user.mr_attention_requests_enabled?
- %li#js-need-attention-nav
- #js-need-attention-nav-onboarding
- = link_to attention_requested_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
- = _('Need your attention')
- = gl_badge_tag user_merge_requests_counts[:attention_requested_count], { size: :sm, variant: user_merge_requests_counts[:attention_requested_count] == 0 ? :neutral : :warning }, { class: 'merge-request-badge gl-ml-auto js-attention-count' }
- %li.divider
%li
= link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
- - if current_user.mr_attention_requests_enabled?
- = _('Assignee')
- - else
- = _('Assigned to you')
+ = _('Assigned to you')
= gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-assigned-mr-count gl-ml-auto" }) do
= user_merge_requests_counts[:assigned]
%li
= link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
- - if current_user.mr_attention_requests_enabled?
- = _('Reviewer')
- - else
- = _('Review requests for you')
+ = _('Review requests for you')
= gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-reviewer-mr-count gl-ml-auto" }) do
= user_merge_requests_counts[:review_requested]
- if header_link?(:todos)
diff --git a/app/views/layouts/header/_storage_enforcement_banner.html.haml b/app/views/layouts/header/_storage_enforcement_banner.html.haml
index c117f22a402..1f7060f8235 100644
--- a/app/views/layouts/header/_storage_enforcement_banner.html.haml
+++ b/app/views/layouts/header/_storage_enforcement_banner.html.haml
@@ -1,14 +1,15 @@
- return unless current_user
-- namespace = local_assigns.fetch(:namespace)
-- banner_info = storage_enforcement_banner_info(namespace)
+- context = local_assigns.fetch(:context)
+- banner_info = storage_enforcement_banner_info(context)
- return unless banner_info.present?
= render Pajamas::AlertComponent.new(variant: :warning,
alert_options: { class: 'js-storage-enforcement-banner',
data: { feature_id: banner_info[:callouts_feature_name],
dismiss_endpoint: banner_info[:callouts_path],
- group_id: namespace.id,
+ group_id: banner_info[:namespace_id],
defer_links: "true" }}) do |c|
= c.body do
- = banner_info[:text]
- = banner_info[:learn_more_link]
+ %p= banner_info[:text_paragraph_1]
+ %p= banner_info[:text_paragraph_2]
+ %p= banner_info[:text_paragraph_3]
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 02565a8f573..f3f79750643 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -7,14 +7,14 @@
%span.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_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
+ = 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
= sprite_icon('overview')
%span.nav-item-name
= _('Overview')
%ul.sidebar-sub-level-items
- = nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers cohorts), html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: %w[dashboard admin admin/projects users groups jobs runners gitaly_servers cohorts], html_options: { class: "fly-out-top-item" } ) do
= link_to admin_root_path do
%strong.fly-out-top-item-name
= _('Overview')
@@ -27,7 +27,7 @@
= link_to admin_projects_path, title: _('Projects') do
%span
= _('Projects')
- = nav_link(controller: %w(users cohorts)) do
+ = nav_link(controller: %w[users cohorts]) do
= link_to admin_users_path, title: _('Users'), data: { qa_selector: 'users_overview_link' } do
%span
= _('Users')
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 16c0c00ad3f..cf1f84790a2 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -3,7 +3,7 @@
.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'], alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
+ = 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' }
%span.sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index 322a77116c8..1ec839ef642 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -7,6 +7,7 @@
- enable_search_settings locals: { container_class: 'gl-my-5' }
- content_for :flash_message do
- = render "layouts/header/storage_enforcement_banner", namespace: current_user.namespace
+ = render "layouts/header/storage_enforcement_banner", context: current_user.namespace
+ = dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: current_user.namespace
= render template: "layouts/application"
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 86b4c4eabe3..9503e874fd0 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -8,8 +8,8 @@
- @content_class = [@content_class, project_classes(@project)].compact.join(" ")
- content_for :flash_message do
- = render "layouts/header/storage_enforcement_banner", namespace: @project.namespace
- = dispensable_render_if_exists "shared/namespace_storage_limit_alert"
+ = render "layouts/header/storage_enforcement_banner", context: @project
+ = dispensable_render_if_exists "shared/namespace_storage_limit_alert", context: @project
- content_for :project_javascripts do
- project = @target_project || @project
diff --git a/app/views/notify/approved_merge_request_email.text.haml b/app/views/notify/approved_merge_request_email.text.haml
index 476da7f9af7..ab79a96c4ed 100644
--- a/app/views/notify/approved_merge_request_email.text.haml
+++ b/app/views/notify/approved_merge_request_email.text.haml
@@ -2,7 +2,7 @@ Merge request #{@merge_request.to_reference} was approved by #{sanitize_name(@ap
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
Author: #{sanitize_name(@merge_request.author_name)}
= assignees_label(@merge_request)
diff --git a/app/views/notify/attention_requested_merge_request_email.html.haml b/app/views/notify/attention_requested_merge_request_email.html.haml
deleted file mode 100644
index af42f180ae7..00000000000
--- a/app/views/notify/attention_requested_merge_request_email.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-%p
- #{sanitize_name(@updated_by.name)} requested your attention on #{merge_request_reference_link(@merge_request)}.
diff --git a/app/views/notify/attention_requested_merge_request_email.text.erb b/app/views/notify/attention_requested_merge_request_email.text.erb
deleted file mode 100644
index 97b1d4a824b..00000000000
--- a/app/views/notify/attention_requested_merge_request_email.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= sanitize_name(@updated_by.name) %> requested your attention on <%= merge_request_reference_link(@merge_request) %>.
diff --git a/app/views/notify/closed_merge_request_email.text.haml b/app/views/notify/closed_merge_request_email.text.haml
index 942e771261a..c6e38f5fc3d 100644
--- a/app/views/notify/closed_merge_request_email.text.haml
+++ b/app/views/notify/closed_merge_request_email.text.haml
@@ -2,7 +2,7 @@ Merge request #{@merge_request.to_reference} was closed by #{sanitize_name(@upda
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
Author: #{sanitize_name(@merge_request.author_name)}
= assignees_label(@merge_request)
diff --git a/app/views/notify/member_access_requested_email.html.haml b/app/views/notify/member_access_requested_email.html.haml
index 43f25af3dba..c3b8d586425 100644
--- a/app/views/notify/member_access_requested_email.html.haml
+++ b/app/views/notify/member_access_requested_email.html.haml
@@ -1,6 +1,5 @@
%tr
%td.text-content
%p
- #{link_to member.user.name, member.user, class: :highlight} requested #{content_tag :span, member.human_access, class: :highlight}
- access to the #{link_to member_source.human_name, polymorphic_url([member_source, :members]), class: :highlight} #{member_source.model_name.singular}.
+ = member_request_access_link member
diff --git a/app/views/notify/member_invite_accepted_email.html.haml b/app/views/notify/member_invite_accepted_email.html.haml
index 0abb79000e0..6a2fda22c36 100644
--- a/app/views/notify/member_invite_accepted_email.html.haml
+++ b/app/views/notify/member_invite_accepted_email.html.haml
@@ -1,8 +1,7 @@
%tr
%td.text-content
%p
- #{content_tag :span, member.invite_email, class: :highlight}, now known as
- #{link_to member.user.name, user_url(member.user)},
- has accepted your invitation to join the
- #{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}.
-
+ = s_('Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}.').html_safe % { invite_email: content_tag(:span, member.invite_email, class: :highlight),
+ user_name: link_to(member.user.name, user_url(member.user)),
+ target_name: link_to(member_source.human_name, member_source.web_url, class: :highlight),
+ target_model_name: member_source.model_name.singular }
diff --git a/app/views/notify/member_invite_accepted_email.text.erb b/app/views/notify/member_invite_accepted_email.text.erb
index c824533eac2..c694bb96f3c 100644
--- a/app/views/notify/member_invite_accepted_email.text.erb
+++ b/app/views/notify/member_invite_accepted_email.text.erb
@@ -1,3 +1,8 @@
-<%= member.invite_email %>, now known as <%= sanitize_name(member.user.name) %>, has accepted your invitation to join the <%= member_source.human_name %> <%= member_source.model_name.singular %>.
+<%= s_('Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}.') % {
+ invite_email: member.invite_email,
+ user_name: member.user.name,
+ target_name: member_source.human_name,
+ target_model_name: member_source.model_name.singular }
+%>
<%= member_source.web_url %>
diff --git a/app/views/notify/member_invite_declined_email.html.haml b/app/views/notify/member_invite_declined_email.html.haml
index 5e626767235..df9f388d0b9 100644
--- a/app/views/notify/member_invite_declined_email.html.haml
+++ b/app/views/notify/member_invite_declined_email.html.haml
@@ -1,7 +1,11 @@
%tr
%td.text-content
%p
- #{content_tag :span, @invite_email, class: :highlight}
- has #{content_tag :span, 'declined', class: :highlight} your invitation to join the
- #{link_to member_source.human_name, member_source.web_url, class: :highlight} #{member_source.model_name.singular}.
-
+ - invited_user = content_tag :span, @invite_email, class: :highlight
+ - target_link = link_to member_source.human_name, strip_tags(member_source.web_url), class: :highlight
+ - target_name = sanitize_name(member_source.model_name.singular)
+ = sanitize(html_escape(s_('Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}.')) % { invited_user: invited_user,
+ highlight_start: '<span class="highlight">'.html_safe,
+ highlight_end: '</span>'.html_safe,
+ target_link: target_link,
+ target_name: target_name })
diff --git a/app/views/notify/merge_request_status_email.text.haml b/app/views/notify/merge_request_status_email.text.haml
index f3845b2b910..61c9b130da8 100644
--- a/app/views/notify/merge_request_status_email.text.haml
+++ b/app/views/notify/merge_request_status_email.text.haml
@@ -2,7 +2,7 @@
= sprintf(s_('Notify|Merge request URL: %{merge_request_url}'), { merge_request_url: project_merge_request_url(@merge_request.target_project, @merge_request) })
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
= sprintf(s_('Notify|Author: %{author_name}'), { author_name: sanitize_name(@merge_request.author_name) })
= assignees_label(@merge_request)
diff --git a/app/views/notify/merge_request_unmergeable_email.html.haml b/app/views/notify/merge_request_unmergeable_email.html.haml
index f0a5e5d4367..38c9710f385 100644
--- a/app/views/notify/merge_request_unmergeable_email.html.haml
+++ b/app/views/notify/merge_request_unmergeable_email.html.haml
@@ -1,7 +1,7 @@
%p
= sprintf(s_('Notify|Merge request %{merge_request} can no longer be merged due to conflict.'), { merge_request: merge_request_reference_link(@merge_request) }).html_safe
%p
- = merge_path_description(@merge_request, 'to')
+ = merge_path_description(@merge_request)
%p
= sprintf(s_('Author: %{author_name}'), { author_name: sanitize_name(@merge_request.author_name) })
%p
diff --git a/app/views/notify/merge_request_unmergeable_email.text.haml b/app/views/notify/merge_request_unmergeable_email.text.haml
index 22d56e73ca8..211e4e379df 100644
--- a/app/views/notify/merge_request_unmergeable_email.text.haml
+++ b/app/views/notify/merge_request_unmergeable_email.text.haml
@@ -2,7 +2,7 @@
= sprintf(s_('Notify|Merge request URL: %{merge_request_url}'), { merge_request_url: project_merge_request_url(@merge_request.target_project, @merge_request) })
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
= sprintf(s_('Author: %{author_name}'), { author_name: sanitize_name(@merge_request.author_name) })
= assignees_label(@merge_request)
diff --git a/app/views/notify/merge_when_pipeline_succeeds_email.text.haml b/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
index 568ca995e04..dbf742a5cbc 100644
--- a/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
+++ b/app/views/notify/merge_when_pipeline_succeeds_email.text.haml
@@ -2,7 +2,7 @@ Merge request #{@merge_request.to_reference} was scheduled to merge after pipeli
Merge request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
Author: #{sanitize_name(@merge_request.author_name)}
= assignees_label(@merge_request)
diff --git a/app/views/notify/merged_merge_request_email.html.haml b/app/views/notify/merged_merge_request_email.html.haml
index e2e4d6d937f..bf50ad0a9ad 100644
--- a/app/views/notify/merged_merge_request_email.html.haml
+++ b/app/views/notify/merged_merge_request_email.html.haml
@@ -2,7 +2,7 @@
= sprintf(s_('Notify|Merge request %{merge_request} was merged'), { merge_request: merge_request_reference_link(@merge_request) }).html_safe
%p
- = merge_path_description(@merge_request, 'to')
+ = merge_path_description(@merge_request)
%div
= sprintf(s_('Notify|Author: %{author_name}'), { author_name: sanitize_name(@merge_request.author_name) })
diff --git a/app/views/notify/merged_merge_request_email.text.haml b/app/views/notify/merged_merge_request_email.text.haml
index 9b9eb566903..b80e4606f35 100644
--- a/app/views/notify/merged_merge_request_email.text.haml
+++ b/app/views/notify/merged_merge_request_email.text.haml
@@ -2,7 +2,7 @@
= sprintf(s_('Notify|Merge request URL: %{merge_request_url}'), { merge_request_url: project_merge_request_url(@merge_request.target_project, @merge_request) })
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
= sprintf(s_('Notify|Author: %{author_name}'), { author_name: sanitize_name(@merge_request.author_name) })
diff --git a/app/views/notify/new_mention_in_merge_request_email.text.erb b/app/views/notify/new_mention_in_merge_request_email.text.erb
index 9ba86f17ef6..9a45aaf1148 100644
--- a/app/views/notify/new_mention_in_merge_request_email.text.erb
+++ b/app/views/notify/new_mention_in_merge_request_email.text.erb
@@ -2,7 +2,7 @@ You have been mentioned in merge request <%= @merge_request.to_reference %>
<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
-<%= merge_path_description(@merge_request, 'to') %>
+<%= merge_path_description(@merge_request) %>
Author: <%= sanitize_name(@merge_request.author_name) %>
<%= assignees_label(@merge_request) %>
<%= reviewers_label(@merge_request) %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 1542d5bba85..3c60235e6d2 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -3,7 +3,7 @@
mr_link: merge_request_reference_link(@merge_request) }
.branch
- = merge_path_description(@merge_request, 'to')
+ = merge_path_description(@merge_request)
.author
Author: #{@merge_request.author_name}
.assignee
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index 09e8ca36225..f2be0b71592 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -2,7 +2,7 @@
mr_link: url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) }
%>
-<%= merge_path_description(@merge_request, 'to') %>
+<%= merge_path_description(@merge_request) %>
<%= "#{_('Author')}: #{sanitize_name(@merge_request.author_name)}" %>
<%= assignees_label(@merge_request) if @merge_request.assignees.any? %>
<%= reviewers_label(@merge_request) if @merge_request.reviewers.any? %>
diff --git a/app/views/notify/unapproved_merge_request_email.text.haml b/app/views/notify/unapproved_merge_request_email.text.haml
index 4e34b883906..52c65e6f5c6 100644
--- a/app/views/notify/unapproved_merge_request_email.text.haml
+++ b/app/views/notify/unapproved_merge_request_email.text.haml
@@ -2,7 +2,7 @@ Merge request #{@merge_request.to_reference} was unapproved by #{@unapproved_by.
Merge request URL: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
-= merge_path_description(@merge_request, 'to')
+= merge_path_description(@merge_request)
Author: #{sanitize_name(@merge_request.author_name)}
= assignees_label(@merge_request)
diff --git a/app/views/notify/user_auto_banned_email.html.haml b/app/views/notify/user_auto_banned_email.html.haml
deleted file mode 100644
index 8c33cd7299d..00000000000
--- a/app/views/notify/user_auto_banned_email.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
-- link_end = '</a>'.html_safe
-= email_default_heading(_("We've detected some unusual activity"))
-%p
- = _('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.') % { username: sanitize_name(@user.name), max_project_downloads: @max_project_downloads, within_minutes: @within_minutes, scope: @ban_scope }
-%p
- = _('If this is a mistake, you can %{link_start}unban them%{link_end}.').html_safe % { link_start: link_start % { url: admin_users_url(filter: 'banned') }, link_end: link_end }
-%p
- = _('You can adjust rules on auto-banning %{link_start}here%{link_end}.').html_safe % { link_start: link_start % { url: network_admin_application_settings_url(anchor: 'js-ip-limits-settings') }, link_end: link_end }
diff --git a/app/views/notify/user_auto_banned_email.text.erb b/app/views/notify/user_auto_banned_email.text.erb
deleted file mode 100644
index 336973c2e42..00000000000
--- a/app/views/notify/user_auto_banned_email.text.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-<%= _("We've detected some unusual activity") %>
-
-<%= _('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.') % { username: sanitize_name(@user.name), max_project_downloads: @max_project_downloads, within_minutes: @within_minutes, scope: @ban_scope } %>
-
-<%= _('If this is a mistake, you can unban them: %{url}.') % { url: admin_users_url(filter: 'banned') } %>
-
-<%= _('You can adjust rules on auto-banning here: %{url}.') % { url: network_admin_application_settings_url(anchor: 'js-ip-limits-settings') } %>
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index 69f765ee163..ef9e7512b57 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -18,7 +18,7 @@
= f.submit _('Add email address'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_email_address_button' }
%hr
%h4.gl-mt-0
- = _('Linked emails (%{email_count})') % { email_count: @emails.load.size + 1 }
+ = _('Linked emails (%{email_count})') % { email_count: @emails.load.size }
.account-well.gl-mb-3
%ul
%li
@@ -36,28 +36,31 @@
%ul.content-list
%li
= render partial: 'shared/email_with_badge', locals: { email: @primary_email, verified: current_user.confirmed? }
- %span.float-right
- = gl_badge_tag s_('Profiles|Primary email'), variant: :success
+ %ul
+ %li= s_('Profiles|Primary email')
- if @primary_email === current_user.commit_email_or_default
- = gl_badge_tag s_('Profiles|Commit email'), variant: :info
+ %li= s_('Profiles|Commit email')
- if @primary_email === current_user.public_email
- = gl_badge_tag s_('Profiles|Public email'), variant: :info
+ %li= s_('Profiles|Public email')
- if @primary_email === current_user.notification_email_or_default
- = gl_badge_tag s_('Profiles|Default notification email'), variant: :info
+ %li= s_('Profiles|Default notification email')
- @emails.reject(&:user_primary_email?).each do |email|
%li{ data: { qa_selector: 'email_row_content' } }
- = render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
- %span.float-right
+ .gl-display-flex.gl-justify-content-space-between{ style: 'flex-flow: wrap-reverse; row-gap: 0.5rem' }
+ %div
+ = render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
+ .gl-ml-n3
+ - unless email.confirmed?
+ - confirm_title = "#{email.confirmation_sent_at ? _('Resend confirmation email') : _('Send confirmation email')}"
+ = link_to confirm_title, resend_confirmation_instructions_profile_email_path(email), method: :put, class: 'gl-button btn btn-sm btn-default gl-ml-3'
+
+ = link_to profile_email_path(email), data: { confirm: _('Are you sure?'), qa_selector: 'delete_email_link'}, method: :delete, class: 'gl-button btn btn-sm btn-danger gl-ml-3' do
+ %span.sr-only= _('Remove')
+ = sprite_icon('remove')
+ %ul
- if email.email === current_user.commit_email_or_default
- = gl_badge_tag s_('Profiles|Commit email'), variant: :info
+ %li= s_('Profiles|Commit email')
- if email.email === current_user.public_email
- = gl_badge_tag s_('Profiles|Public email'), variant: :info
+ %li= s_('Profiles|Public email')
- if email.email === current_user.notification_email_or_default
- = gl_badge_tag s_('Profiles|Notification email'), variant: :info
- - unless email.confirmed?
- - confirm_title = "#{email.confirmation_sent_at ? _('Resend confirmation email') : _('Send confirmation email')}"
- = link_to confirm_title, resend_confirmation_instructions_profile_email_path(email), method: :put, class: 'gl-button btn btn-sm btn-default gl-ml-3'
-
- = link_to profile_email_path(email), data: { confirm: _('Are you sure?'), qa_selector: 'delete_email_link'}, method: :delete, class: 'gl-button btn btn-sm btn-danger gl-ml-3' do
- %span.sr-only= _('Remove')
- = sprite_icon('remove')
+ %li= s_('Profiles|Notification email')
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 5c8acc053f4..35bf7d81502 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -7,6 +7,12 @@
= page_title
%p
= _('SSH keys allow you to establish a secure connection between your computer and GitLab.')
+ %br
+ %h4.gl-mt-0
+ = _('SSH Fingerprints')
+ %p
+ - config_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_instance_configuration_url }
+ = html_escape(s_('SSH fingerprints verify that the client is connecting to the correct host. Check the %{config_link_start}current instance configuration%{config_link_end}.')) % { config_link_start: config_link_start, config_link_end: '</a>'.html_safe }
.col-lg-8
%h5.gl-mt-0
= _('Add an SSH key')
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index a63e02fca1d..f8737a4e54a 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -99,7 +99,7 @@
s_("Preferences|Show one file at a time on merge request's Changes tab"),
help_text: s_("Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser.")
.form-group
- - supported_characters = %w(" ' ` &#40; [ { < * _).map {|char| "<code>#{char}</code>" }.join(', ')
+ - supported_characters = %w(" ' ` &#40; [ { < * _).map { |char| "<code>#{char}</code>" }.join(', ')
= 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
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index dda1640968e..a64968cdcbb 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -3,7 +3,7 @@
- @content_class = "limit-container-width" unless fluid_layout
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
- availability = availability_values
-- custom_emoji = show_status_emoji?(@user.status)
+- custom_emoji = @user.status&.customized?
= gitlab_ui_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user js-edit-user gl-mt-3 js-quick-submit gl-show-field-errors js-password-prompt-form', remote: true }, authenticity_token: true do |f|
.row.js-search-settings-section
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 6304d42896d..c1eaa84e99d 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -21,24 +21,27 @@
- else
%p
- - register_2fa_token = _('We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device.')
+ - register_2fa_token = _('We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device.')
= register_2fa_token.html_safe
+ = link_to _('What are some examples?'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'enable-one-time-password'), target: '_blank', rel: 'noopener noreferrer'
.row.gl-mb-3
.col-md-4.gl-min-w-fit-content
.gl-p-2.gl-mb-3{ style: 'background: #fff' }
= raw @qr_code
.col-md-8
- .account-well
- %p.gl-mt-0.gl-mb-0
- = _("Can't scan the code?")
- %p.gl-mt-0.gl-mb-0
- = _('To add the entry manually, provide the following details to the application on your phone.')
- %p.gl-mt-0.gl-mb-0
- = _('Account: %{account}') % { account: @account_string }
- %p.gl-mt-0.gl-mb-0.two-factor-secret{ data: { qa_selector: 'otp_secret_content' } }
- = _('Key: %{key}') %{ key: current_user.otp_secret.scan(/.{4}/).join(' ') }
- %p.two-factor-new-manual-content
- = _('Time based: Yes')
+ .gl-card
+ .gl-card-body
+ %p.gl-mt-0.gl-mb-3.gl-font-weight-bold
+ = _("Can't scan the code?")
+ %p.gl-mt-0.gl-mb-3
+ = _('To add the entry manually, provide the following details to the application on your phone.')
+ %p.gl-mt-0.gl-mb-0
+ = _('Account: %{account}') % { account: @account_string }
+ %p.gl-mt-0.gl-mb-0{ data: { qa_selector: 'otp_secret_content' } }
+ = _('Key:')
+ %code.two-factor-secret= current_user.otp_secret.scan(/.{4}/).join(' ')
+ %p.gl-mb-0.two-factor-new-manual-content
+ = _('Time based: Yes')
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
= render Pajamas::AlertComponent.new(title: @error[:message],
diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index 659bca25533..952c6daf415 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -1,5 +1,5 @@
.form-actions.gl-display-flex
- = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, button_options: { id: 'commit-changes', class: 'js-commit-button qa-commit-button' }) do
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, button_options: { id: 'commit-changes', class: 'js-commit-button', data: { qa_selector: 'commit_button' } }) do
= _('Commit changes')
= render Pajamas::ButtonComponent.new(href: cancel_path, button_options: { class: 'gl-ml-3', id: 'cancel-changes', aria: { label: _('Discard changes') }, data: { confirm: leave_edit_message, confirm_btn_variant: "danger" } }) do
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index eee9cfe0618..c220aa66c81 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -24,15 +24,12 @@
%span.gl-ml-3.gl-mb-3
= render 'shared/members/access_request_links', source: @project
- .gl-mt-3.gl-pl-3.gl-w-full
- = render "shared/projects/topics", project: @project, cache_enabled: cache_enabled
-
= cache_if(cache_enabled, [@project, :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?
= link_to [:admin, @project], class: 'btn gl-button btn-icon gl-align-self-start gl-py-2! gl-mr-3', title: _('View project in admin area'),
- data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ data: {toggle: 'tooltip', placement: 'top', container: 'body'} do
= sprite_icon('admin')
.gl-display-flex.gl-align-items-start.gl-mr-3
- if @notification_setting
@@ -49,7 +46,8 @@
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
- else
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
-
+ .gl-my-3
+ = render "shared/projects/topics", project: @project, cache_enabled: cache_enabled
.home-panel-home-desc.mt-1
- if @project.description.present?
.home-panel-description.text-break
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 9845de17a11..859f065377d 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -14,7 +14,7 @@
#{time_ago_with_tooltip(event.created_at)}
- - if can?(current_user, :create_merge_request_in, event.project.default_merge_request_target)
+ - if create_mr_button_from_event?(event)
= c.actions do
- = link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn gl-button btn-confirm qa-create-merge-request" do
- #{ _('Create merge request') }
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path_from_push_event(event), button_options: { class: 'qa-create-merge-request' }) do
+ = _('Create merge request')
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 992b46c1f7b..98cd831d6f1 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -1,6 +1,7 @@
- visibility_level = selected_visibility_level(@project, params.dig(:project, :visibility_level))
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
- hide_init_with_readme = local_assigns.fetch(:hide_init_with_readme, false)
+- include_description = local_assigns.fetch(:include_description, true)
- track_label = local_assigns.fetch(:track_label, 'blank_project')
.row{ id: project_name_id }
@@ -44,10 +45,19 @@
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'add-details-to-your-profile-with-a-readme') }
= html_escape(_('%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}')) % { project_path: "<strong>#{current_user.username} / #{current_user.username}</strong>".html_safe, help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
-.form-group
- = f.label :description, class: 'label-bold' do
- = s_('ProjectsNew|Project description %{tag_start}(optional)%{tag_end}').html_safe % { tag_start: '<span>'.html_safe, tag_end: '</span>'.html_safe }
- = f.text_area :description, placeholder: s_('ProjectsNew|Description format'), class: "form-control gl-form-input", rows: 3, maxlength: 250, data: { qa_selector: 'project_description', track_label: "#{track_label}", track_action: "activate_form_input", track_property: "project_description", track_value: "" }
+- if include_description
+ .form-group
+ = f.label :description, class: 'label-bold' do
+ = s_('ProjectsNew|Project description %{tag_start}(optional)%{tag_end}').html_safe % { tag_start: '<span>'.html_safe, tag_end: '</span>'.html_safe }
+ = f.text_area :description,
+ placeholder: s_('ProjectsNew|Description format'),
+ class: "form-control gl-form-input",
+ rows: 3,
+ maxlength: 250,
+ data: { qa_selector: 'project_description',
+ track_label: track_label,
+ track_action: "activate_form_input",
+ track_property: "project_description" }
- unless Gitlab::CurrentSettings.current_application_settings.hide_third_party_offers? || !Gitlab.com?
.js-deployment-target-select
@@ -63,18 +73,20 @@
= s_('ProjectsNew|Project Configuration')
.form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_readme]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' }
- = label_tag 'project[initialize_with_readme]', s_('ProjectsNew|Initialize repository with a README'), class: 'form-check-label'
- .form-text.text-muted
+ = render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_readme]',
+ checked: true,
+ checkbox_options: { data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' } }) do |c|
+ = c.label do
+ = s_('ProjectsNew|Initialize repository with a README')
+ = c.help_text do
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
.form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_sast]',
+ checkbox_options: { data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' } }) do |c|
+ = c.label do
= s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- .form-text.text-muted
+ = c.help_text do
= s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
= link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed' }
diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml
index 393b199fb05..02aa1f7e93b 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 = { namespaces: namespaces_as_json, button_text: s_('ProjectSettings|Transfer project'), confirm_danger_message: transfer_project_message(@project), phrase: @project.name, target_form_id: form_id, target_hidden_input_id: hidden_input_id }
+- 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 }
.sub-section
%h4.danger-title= _('Transfer project')
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index 66066ceb5b2..e8a4e091dcf 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -22,8 +22,8 @@
%label{ for: "confirm_path_input" }
= _("To confirm, type %{phrase_code}").html_safe % { phrase_code: '<code class="js-legacy-confirm-danger-match">%{phrase_name}</code>'.html_safe % { phrase_name: @project.full_path } }
.form-group
- = text_field_tag 'confirm_path_input', '', class: 'form-control js-legacy-confirm-danger-input qa-confirm-input'
+ = text_field_tag 'confirm_path_input', '', class: 'form-control js-legacy-confirm-danger-input'
.form-actions
%button.btn.gl-button.btn-default.gl-mr-4{ type: "button", "data-dismiss": "modal" }
= _('Cancel')
- = submit_tag _('Reduce project visibility'), class: "btn gl-button btn-danger js-legacy-confirm-danger-submit qa-confirm-button", disabled: true
+ = submit_tag _('Reduce project visibility'), class: "btn gl-button btn-danger js-legacy-confirm-danger-submit", disabled: true
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 09a275c24a1..398ca3dd27c 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -42,7 +42,7 @@
.file-editor.code
- if Feature.enabled?(:source_editor_toolbar, current_user)
#editor-toolbar
- .js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }<
+ .js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true, qa_selector: 'source_editor_preview_container' } }<
%pre.editor-loading-content= params[:content] || local_assigns[:blob_data]
- if local_assigns[:path]
.js-edit-mode-pane#preview.hide
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 1477ae66d80..52b8d6bc66f 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -33,8 +33,8 @@
.gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5
%svg.s24
- - if merge_project && create_mr_button?(from: @repository.root_ref, to: branch.name, source_project: @project, target_project: @project)
- = link_to create_mr_path(from: @repository.root_ref, to: branch.name, source_project: @project, target_project: @project), class: 'gl-button btn btn-default' do
+ - if merge_project && create_mr_button?(from: branch.name, source_project: @project)
+ = render Pajamas::ButtonComponent.new(href: create_mr_path(from: branch.name, source_project: @project)) do
= _('Merge request')
- if branch.name != @repository.root_ref
diff --git a/app/views/projects/branches/_panel.html.haml b/app/views/projects/branches/_panel.html.haml
index bd6831ff3b2..6ca5aaf061e 100644
--- a/app/views/projects/branches/_panel.html.haml
+++ b/app/views/projects/branches/_panel.html.haml
@@ -7,12 +7,13 @@
- return unless branches.any?
-.card
- .card-header
+= render Pajamas::CardComponent.new(card_options: {class: 'gl-mb-5'}, body_options: {class: 'gl-py-0'}, footer_options: {class: 'gl-text-center'}) do |c|
+ - c.header do
= panel_title
- %ul.content-list.all-branches.qa-all-branches
- - branches.first(overview_max_branches).each do |branch|
- = render "projects/branches/branch", branch: branch, merged: project.repository.merged_to_root_ref?(branch), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
+ - c.body do
+ %ul.content-list.all-branches.qa-all-branches
+ - branches.first(overview_max_branches).each do |branch|
+ = render "projects/branches/branch", branch: branch, merged: project.repository.merged_to_root_ref?(branch), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
- if branches.size > overview_max_branches
- .card-footer.text-center
+ - c.footer do
= link_to show_more_text, project_branches_filtered_path(project, state: state), id: "state-#{state}", data: { state: state }
diff --git a/app/views/projects/buttons/_remove_tag.html.haml b/app/views/projects/buttons/_remove_tag.html.haml
index 060a854d4e4..dfa643a87bb 100644
--- a/app/views/projects/buttons/_remove_tag.html.haml
+++ b/app/views/projects/buttons/_remove_tag.html.haml
@@ -8,4 +8,4 @@
- title = s_('TagsPage|Only a project maintainer or owner can delete a protected tag')
- disabled = true
-= render Pajamas::ButtonComponent.new(variant: :default, icon: 'remove', button_options: { class: "js-delete-tag-button gl-ml-3\!", 'aria-label': s_('TagsPage|Delete tag'), title: title, disabled: disabled, data: { toggle: 'tooltip', container: 'body', path: project_tag_path(@project, tag.name), tag_name: tag.name, is_protected: protected_tag?(project, tag).to_s } })
+= render Pajamas::ButtonComponent.new(variant: :default, icon: 'remove', button_options: { class: "js-delete-tag-button", 'aria-label': s_('TagsPage|Delete tag'), title: title, disabled: disabled, data: { toggle: 'tooltip', container: 'body', path: project_tag_path(@project, tag.name), tag_name: tag.name, is_protected: protected_tag?(project, tag).to_s } })
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index 00d518450e9..f607a21ad21 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -7,7 +7,7 @@
- else
= sprite_icon('star-o', css_class: 'icon')
%span= s_('ProjectOverview|Star')
- = 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 star-count count' do
+ = 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
@@ -15,5 +15,5 @@
= 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
= sprite_icon('star-o', css_class: 'icon')
%span= s_('ProjectOverview|Star')
- = 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 star-count count' do
+ = 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
diff --git a/app/views/projects/ci/secure_files/show.html.haml b/app/views/projects/ci/secure_files/show.html.haml
deleted file mode 100644
index 1a87ccd753c..00000000000
--- a/app/views/projects/ci/secure_files/show.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- page_title s_('Secure Files')
-
-#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/commit/_same_user_different_email_signature_badge.html.haml b/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml
index e56579b162f..629d3cfaf74 100644
--- a/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml
+++ b/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml
@@ -1,5 +1,5 @@
- title = capture do
- = html_escape(_('This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
+ = html_escape(_('This commit was signed with a verified signature, but the committer email is not associated with the GPG Key.'))
- locals = { signature: signature, title: title, label: _('Unverified'), css_class: ['invalid'], icon: 'status_notfound_borderless', show_user: true }
diff --git a/app/views/projects/commits/_commit_list.html.haml b/app/views/projects/commits/_commit_list.html.haml
index 6ed65d07202..23b25b5dcbd 100644
--- a/app/views/projects/commits/_commit_list.html.haml
+++ b/app/views/projects/commits/_commit_list.html.haml
@@ -2,14 +2,15 @@
- hidden = @hidden_commit_count
- commits = Commit.decorate(commits, @project)
-.card
- .card-header
+= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, body_options: { class: 'gl-py-0'}) do |c|
+ - c.header do
Commits (#{@total_commit_count})
- - if hidden > 0
- %ul.content-list
- - commits.each do |commit|
- = render "projects/commits/inline_commit", commit: commit, project: @project
- %li.warning-row.unstyled
- #{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
- - else
- %ul.content-list= render commits, project: @project, ref: @ref
+ - c.body do
+ - if hidden > 0
+ %ul.content-list
+ - commits.each do |commit|
+ = render "projects/commits/inline_commit", commit: commit, project: @project
+ %li.warning-row.unstyled
+ #{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
+ - else
+ %ul.content-list= render commits, project: @project, ref: @ref
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 764ddace0ad..bb3a38d6ac8 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -41,7 +41,7 @@
= n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden)
- if can_update_merge_request && context_commits&.empty?
- = render Pajamas::ButtonComponent.new(button_options: { class: 'gl-mt-5', data: { context_commits_empty: 'true' } }) do
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'gl-mt-5 add-review-item-modal-trigger', data: { context_commits_empty: 'true' } }) do
= _('Add previously merged commits')
- if commits.size == 0 && context_commits.nil?
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index e5be3a897a5..4007b657403 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -18,9 +18,10 @@
- if @merge_request.present?
.control.d-none.d-md-block
= link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'btn gl-button'
- - elsif create_mr_button?(from: @repository.root_ref, to: @ref, source_project: @project, target_project: @project)
+ - elsif create_mr_button?(from: @ref, source_project: @project)
.control.d-none.d-md-block
- = link_to _("Create merge request"), create_mr_path(from: @repository.root_ref, to: @ref, source_project: @project, target_project: @project), class: 'btn gl-button btn-confirm'
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path(from: @ref, source_project: @project)) do
+ = _("Create merge request")
.control
= form_tag(project_commits_path(@project, @id), method: :get, class: 'commits-search-form js-signature-container', data: { 'signatures-path' => namespace_project_signatures_path }) do
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index a6be6695b75..95186b85838 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -1,7 +1,7 @@
- add_to_breadcrumbs _("Compare Revisions"), project_compare_index_path(@project)
- page_title "#{params[:from]}...#{params[:to]}"
-.sub-header-block.no-bottom-space
+.sub-header-block.gl-border-b-0.gl-mb-0
.js-signature-container{ data: { 'signatures-path' => signatures_namespace_project_compare_index_path } }
#js-compare-selector{ data: project_compare_selector_data(@project, @merge_request, params) }
@@ -17,11 +17,11 @@
paginate_diffs: true,
paginate_diffs_per_page: Projects::CompareController::COMMIT_DIFFS_PER_PAGE
- else
- .card.gl-bg-gray-50.gl-border-none.gl-p-2
- .center
+ = render Pajamas::CardComponent.new(card_options: { class: "gl-bg-gray-50 gl-mb-5 gl-border-none gl-text-center" }) do |c|
+ - c.body do
%h4
= s_("CompareBranches|There isn't anything to compare.")
- %p.slead
+ %p.gl-mb-4.gl-line-height-24
- if params[:to] == params[:from]
- source_branch = capture do
%span.ref-name= params[:from]
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index d596199f816..11984a9d6f6 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -11,7 +11,7 @@
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
.files-changed-inner
.inline-parallel-buttons.gl-display-none.gl-md-display-flex
- - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
+ - if !diffs_expanded? && diff_files.any?(&:collapsed?)
= link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'gl-button btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
diff --git a/app/views/projects/google_cloud/configuration/index.html.haml b/app/views/projects/google_cloud/configuration/index.html.haml
index ec977898f47..dab49d5032a 100644
--- a/app/views/projects/google_cloud/configuration/index.html.haml
+++ b/app/views/projects/google_cloud/configuration/index.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- add_to_breadcrumbs _('Google Cloud'), project_google_cloud_path(@project)
- breadcrumb_title s_('CloudSeed|Configuration')
- page_title s_('CloudSeed|Configuration')
diff --git a/app/views/projects/google_cloud/databases/index.html.haml b/app/views/projects/google_cloud/databases/index.html.haml
index ad732317d8d..0528ac3d1f5 100644
--- a/app/views/projects/google_cloud/databases/index.html.haml
+++ b/app/views/projects/google_cloud/databases/index.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- add_to_breadcrumbs _('Google Cloud'), project_google_cloud_path(@project)
- breadcrumb_title s_('CloudSeed|Databases')
- page_title s_('CloudSeed|Databases')
diff --git a/app/views/projects/google_cloud/deployments/index.html.haml b/app/views/projects/google_cloud/deployments/index.html.haml
index b140159a7f5..22a365671bc 100644
--- a/app/views/projects/google_cloud/deployments/index.html.haml
+++ b/app/views/projects/google_cloud/deployments/index.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- add_to_breadcrumbs _('Google Cloud'), project_google_cloud_path(@project)
- breadcrumb_title s_('CloudSeed|Deployments')
- page_title s_('CloudSeed|Deployments')
diff --git a/app/views/projects/google_cloud/gcp_regions/index.html.haml b/app/views/projects/google_cloud/gcp_regions/index.html.haml
index d7cabaa029b..36b5630611e 100644
--- a/app/views/projects/google_cloud/gcp_regions/index.html.haml
+++ b/app/views/projects/google_cloud/gcp_regions/index.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- add_to_breadcrumbs _('Google Cloud'), project_google_cloud_path(@project)
- breadcrumb_title _('CloudSeed|Regions')
- page_title s_('CloudSeed|Regions')
diff --git a/app/views/projects/google_cloud/service_accounts/index.html.haml b/app/views/projects/google_cloud/service_accounts/index.html.haml
index 6191de577fe..8f70818abd9 100644
--- a/app/views/projects/google_cloud/service_accounts/index.html.haml
+++ b/app/views/projects/google_cloud/service_accounts/index.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- add_to_breadcrumbs _('Google Cloud'), project_google_cloud_path(@project)
- breadcrumb_title s_('CloudSeed|Service Account')
- page_title s_('CloudSeed|Service Account')
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index ca0307aed60..04d400688d4 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -15,20 +15,7 @@
- if defined?(@daily_coverage_options)
.repo-charts.my-5
- .sub-header-block.border-top
- .d-flex.justify-content-between.align-items-center
- %h4.sub-header.m-0
- - start_date = capture do
- #{@daily_coverage_options[:base_params][:start_date].strftime('%b %d')}
- - end_date = capture do
- #{@daily_coverage_options[:base_params][:end_date].strftime('%b %d')}
- = (_("Code coverage statistics for %{ref} %{start_date} - %{end_date}") % { ref: "<strong>#{h @ref}</strong>", start_date: start_date, end_date: end_date }).html_safe
- - download_path = capture do
- #{@daily_coverage_options[:download_path]}
- %a.btn.gl-button.btn-default.btn-sm{ href: "#{download_path}?#{@daily_coverage_options[:base_params].to_query}" }
- %small
- = _("Download raw data (.csv)")
- #js-code-coverage-chart{ data: { graph_endpoint: "#{@daily_coverage_options[:graph_api_path]}?#{@daily_coverage_options[:base_params].to_query}" } }
+ #js-code-coverage-chart{ data: project_coverage_chart_data_attributes(@daily_coverage_options, @ref) }
.repo-charts
.sub-header-block.border-top
diff --git a/app/views/projects/hook_logs/_index.html.haml b/app/views/projects/hook_logs/_index.html.haml
deleted file mode 100644
index 6a46b0b3510..00000000000
--- a/app/views/projects/hook_logs/_index.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks')
-- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
-- link_end = '</a>'.html_safe
-
-.row.gl-mt-3.gl-mb-3
- .col-lg-3
- %h4.gl-mt-0
- = _('Recent events')
- %p= _('GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}').html_safe % { link_start: link_start, link_end: link_end }
- .col-lg-9
- = render partial: 'shared/hook_logs/recent_deliveries_table', locals: { hook: hook, hook_logs: hook_logs }
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index 74af65904cd..b350455807d 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -18,4 +18,4 @@
%hr
-= render partial: 'projects/hook_logs/index', locals: { hook: @hook, hook_logs: @hook_logs, project: @project }
+= render partial: 'shared/hook_logs/index', locals: { hook: @hook, hook_logs: @hook_logs, project: @project }
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index bcfa32566fb..306f24d717b 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -1,19 +1,19 @@
-- page_title _("Import repository")
+- page_title _('Import repository')
%h1.page-title.gl-font-size-h-display
= _('Import repository')
%hr
- if @project.import_failed?
- .card.border-danger
- .card-header.bg-danger.text-white The repository could not be imported.
- .card-body
- %pre
- :preserve
- #{h(@project.import_state.last_error)}
+ = render Pajamas::AlertComponent.new(title: s_('Import|The repository could not be imported.'),
+ dismissible: false,
+ variant: :danger,
+ alert_options: { class: 'gl-mb-5' }) do |c|
+ = c.body do
+ = @project.import_state.last_error
= gitlab_ui_form_for @project, url: project_import_path(@project), method: :post, html: { class: 'js-project-import' } do |f|
- = render "shared/import_form", f: f
+ = render 'shared/import_form', f: f
.form-actions
- = f.submit 'Start import', class: "gl-button btn btn-confirm", data: { disable_with: false }
+ = f.submit 'Start import', class: 'gl-button btn btn-confirm', data: { disable_with: false }
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 801841edc26..f9798d25b06 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -6,11 +6,10 @@
- create_mr_text = can_create_confidential_merge_request? ? _('Create confidential merge request') : _('Create merge request')
- can_create_path = can_create_branch_project_issue_path(@project, @issue)
- - create_mr_path = project_new_merge_request_path(@project, merge_request: { source_branch: @issue.to_branch_name, target_branch: @project.default_branch, issue_iid: @issue.iid })
- create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid, format: :json)
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
- .create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }
+ .create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path(from: @issue.to_branch_name, source_project: @project, to: @project.default_branch, mr_params: { issue_iid: @issue.iid }), create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }
.btn-group.unavailable
%button.gl-button.btn{ type: 'button', disabled: 'disabled' }
= gl_loading_icon(inline: true, css_class: 'js-create-mr-spinner gl-button-icon gl-display-none')
diff --git a/app/views/projects/issues/_related_issues.html.haml b/app/views/projects/issues/_related_issues.html.haml
index bab37609c20..1c252958525 100644
--- a/app/views/projects/issues/_related_issues.html.haml
+++ b/app/views/projects/issues/_related_issues.html.haml
@@ -1,5 +1,7 @@
- if can?(current_user, :read_issue_link, @project)
.js-related-issues-root{ data: { endpoint: project_issue_links_path(@project, @issue),
can_add_related_issues: "#{can?(current_user, :admin_issue_link, @issue)}",
+ full_path: @project.full_path,
+ has_issue_weights_feature: @project.licensed_feature_available?(:issue_weights).to_s,
help_path: help_page_path('user/project/issues/related_issues'),
- show_categorized_issues: "false" } }
+ show_categorized_issues: @project.licensed_feature_available?(:blocked_issues).to_s } }
diff --git a/app/views/projects/issues/_work_item_links.html.haml b/app/views/projects/issues/_work_item_links.html.haml
index 5d478784350..df2ffdd30ee 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, project_path: @project.full_path } }
+ .js-work-item-links-root{ data: { issuable_id: @issue.id, project_path: @project.full_path, wi: work_items_index_data(@project) } }
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 647464b31f8..f7a02c521f5 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -11,14 +11,14 @@
.labels-container.gl-mt-5
- if can_admin_label && search.blank?
%p.text-muted
- = _('Labels can be applied to issues and merge requests.')
- %br
- = _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.')
+ = _('Labels can be applied to issues and merge requests. Star a label to make it a priority label.')
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
.prioritized-labels.gl-mb-7{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
%h4.gl-mt-3= _('Prioritized Labels')
+ %p.text-muted
+ = _('Drag to reorder prioritized labels and change their relative priority.')
.manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } }
#js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" }
= render 'shared/empty_states/priority_labels'
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 6b367c735c3..62cd8bd94e3 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
@@ -34,9 +34,10 @@
= display_issuable_type
- unless current_controller?('conflicts')
- - if current_user && moved_mr_sidebar_enabled? && !@merge_request.merged?
- %li.gl-new-dropdown-divider
- %hr.dropdown-divider
+ - if current_user && moved_mr_sidebar_enabled?
+ - if !@merge_request.merged?
+ %li.gl-new-dropdown-divider
+ %hr.dropdown-divider
%li.gl-new-dropdown-item.js-sidebar-subscriptions-entry-point
- unless issuable_author_is_current_user(@merge_request)
%li.gl-new-dropdown-item
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 4ef557fbd8f..78976be5dd7 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -32,7 +32,7 @@
= tab_link_for @merge_request, :commits do
= _("Commits")
= gl_badge_tag @commits_count, { size: :sm }
- - if @number_of_pipelines.nonzero?
+ - if @project.builds_enabled?
= render "projects/merge_requests/tabs/tab", name: "pipelines", class: "pipelines-tab" do
= tab_link_for @merge_request, :pipelines do
= _("Pipelines")
@@ -44,7 +44,7 @@
- if Feature.enabled?(:moved_mr_sidebar, @project)
.gl-ml-auto.gl-align-items-center.gl-display-none.gl-md-display-flex.js-expand-sidebar{ class: "gl-lg-display-none!" }
= render Pajamas::ButtonComponent.new(size: 'small',
- icon: 'angle-double-left',
+ icon: 'chevron-double-lg-left',
button_options: { class: 'js-sidebar-toggle' }) do
= _('Expand')
.d-flex.flex-wrap.align-items-center.justify-content-lg-end
@@ -80,7 +80,7 @@
= render "projects/merge_requests/tabs/pane", name: "commits", id: "commits", class: "commits" do
-# This tab is always loaded via AJAX
= render "projects/merge_requests/tabs/pane", name: "pipelines", id: "pipelines", class: "pipelines" do
- - if @number_of_pipelines.nonzero?
+ - if @project.builds_enabled?
= render 'projects/commit/pipelines_list', disable_initialization: true, endpoint: pipelines_project_merge_request_path(@project, @merge_request)
- params = request.query_parameters.merge(diff_head: true)
= render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: diffs_tab_pane_data(@project, @merge_request, params)
@@ -99,11 +99,8 @@
#js-review-bar
-- if Feature.enabled?(:mr_experience_survey, @project)
- #js-mr-experience-survey
-
-- if current_user&.mr_attention_requests_enabled?
- #js-need-attention-sidebar-onboarding
+- if Feature.enabled?(:mr_experience_survey, @project) && current_user
+ #js-mr-experience-survey{ data: { account_age: current_user.account_age_in_days } }
= render 'projects/invite_members_modal', project: @project
= render 'shared/web_ide_path'
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 9b0508d8cb5..0d56bf7793d 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -1,4 +1,4 @@
-= form_for [@project, @milestone],
+= gitlab_ui_form_for [@project, @milestone],
html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone, pajamas_alert: true)
.form-group.row
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 07c38d9845c..56581fe7b18 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -13,7 +13,7 @@
.row{ 'v-cloak': true }
#blank-project-pane.tab-pane.active
= gitlab_ui_form_for @project, html: { class: 'new_project gl-mt-3' } do |f|
- = render 'new_project_fields', f: f, project_name_id: "blank-project-name"
+ = render 'new_project_fields', f: f, project_name_id: "blank-project-name", include_description: false
#create-from-template-pane.tab-pane
= render Pajamas::CardComponent.new(card_options: { class: 'gl-my-5' }) do |c|
diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml
index c5efacb21af..28f04d78861 100644
--- a/app/views/projects/pages/_access.html.haml
+++ b/app/views/projects/pages/_access.html.haml
@@ -1,8 +1,8 @@
- if @project.pages_deployed?
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5', data: { qa_selector: 'access_page_container' } }, footer_options: { class: 'gl-alert-warning' }) do |c|
+ - c.header do
= s_('GitLabPages|Access pages')
- .card-body
+ - c.body do
%p
%strong
= s_('GitLabPages|Your pages are served under:')
@@ -14,7 +14,7 @@
%p
= external_link(domain.url, domain.url)
- unless @project.public_pages?
- .card-footer.gl-alert-warning
+ - c.footer do
- help_page = help_page_path('user/project/pages/pages_access_control')
- link_start = '<a href="%{url}" target="_blank" class="gl-alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page }
- link_end = '</a>'.html_safe
diff --git a/app/views/projects/pages/_header.html.haml b/app/views/projects/pages/_header.html.haml
new file mode 100644
index 00000000000..da35f2fdf09
--- /dev/null
+++ b/app/views/projects/pages/_header.html.haml
@@ -0,0 +1,11 @@
+- can_add_new_domain = can?(current_user, :update_pages, @project) && (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https)
+
+%h1.page-title.gl-font-size-h-display.with-button
+ = s_('GitLabPages|Pages')
+ - if can_add_new_domain
+ = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'float-right'}, href: new_project_pages_domain_path(@project)) do
+ = s_('GitLabPages|New Domain')
+%p
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
+ - docs_link_end = '</a>'.html_safe
+ = s_('GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}').html_safe % { docs_link_start: docs_link_start, link_end: docs_link_end }
diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml
index 0ddf105ef60..16312da1353 100644
--- a/app/views/projects/pages/_list.html.haml
+++ b/app/views/projects/pages/_list.html.haml
@@ -1,38 +1,39 @@
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
- if can?(current_user, :update_pages, @project) && @domains.any?
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}) do |c|
+ - c.header do
Domains (#{@domains.size})
- %ul.list-group.list-group-flush
- - @domains.each do |domain|
- %li.list-group-item.gl-display-flex.gl-justify-content-space-between.gl-align-items-center
- .gl-display-flex.gl-align-items-center
- - if verification_enabled
- - tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success']
- .domain-status.ci-status-icon.has-tooltip{ class: "gl-mr-5 ci-status-icon-#{status}", title: tooltip }
- = sprite_icon("status_#{status}" )
- .domain-name
- = external_link(domain.url, domain.url)
- - if domain.certificate
- %div
- = gl_badge_tag(s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject })
- - if domain.expired?
- = gl_badge_tag s_('GitLabPages|Expired'), variant: :danger
- %div
- = link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn gl-button btn-sm btn-grouped btn-confirm btn-inverted"
- = link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_("GitLabPages|Remove domain"), method: :delete, class: "btn gl-button btn-danger btn-sm btn-grouped"
- - if domain.needs_verification?
- %li.list-group-item.bs-callout-warning
- - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
- - details_link_end = '</a>'.html_safe
- = s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
- link_start: details_link_start,
- link_end: details_link_end }
- - if domain.show_auto_ssl_failed_warning?
- %li.list-group-item.bs-callout-warning
- - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
- - details_link_end = '</a>'.html_safe
- = s_("GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}.").html_safe % { domain: domain.domain,
- link_start: details_link_start,
- link_end: details_link_end }
+ - c.body do
+ %ul.list-group.list-group-flush
+ - @domains.each do |domain|
+ %li.list-group-item.gl-display-flex.gl-justify-content-space-between.gl-align-items-center.gl-p-0
+ .gl-display-flex.gl-align-items-center
+ - if verification_enabled
+ - tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success']
+ .domain-status.ci-status-icon.has-tooltip{ class: "gl-mr-5 ci-status-icon-#{status}", title: tooltip }
+ = sprite_icon("status_#{status}" )
+ .domain-name
+ = external_link(domain.url, domain.url)
+ - if domain.certificate
+ %div
+ = gl_badge_tag(s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject })
+ - if domain.expired?
+ = gl_badge_tag s_('GitLabPages|Expired'), variant: :danger
+ %div
+ = link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn gl-button btn-sm btn-grouped btn-confirm btn-inverted"
+ = link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_("GitLabPages|Remove domain"), method: :delete, class: "btn gl-button btn-danger btn-sm btn-grouped"
+ - if domain.needs_verification?
+ %li.list-group-item.bs-callout-warning
+ - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
+ - details_link_end = '</a>'.html_safe
+ = s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
+ link_start: details_link_start,
+ link_end: details_link_end }
+ - if domain.show_auto_ssl_failed_warning?
+ %li.list-group-item.bs-callout-warning
+ - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
+ - details_link_end = '</a>'.html_safe
+ = s_("GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}.").html_safe % { domain: domain.domain,
+ link_start: details_link_start,
+ link_end: details_link_end }
diff --git a/app/views/projects/pages/_no_domains.html.haml b/app/views/projects/pages/_no_domains.html.haml
index a537bd80d30..eee7d062d00 100644
--- a/app/views/projects/pages/_no_domains.html.haml
+++ b/app/views/projects/pages/_no_domains.html.haml
@@ -1,6 +1,6 @@
- if can?(current_user, :update_pages, @project)
- .card
- .card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, body_options: { class: 'gl-text-center nothing-here-block' }) do |c|
+ - c.header do
= s_('GitLabPages|Domains')
- .nothing-here-block
+ - c.body do
= s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
index 20e6338fa76..dccf61c6ec5 100644
--- a/app/views/projects/pages/_use.html.haml
+++ b/app/views/projects/pages/_use.html.haml
@@ -1,10 +1,9 @@
- unless @project.pages_deployed?
- .card.border-info
- .card-header.bg-info.text-white
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-border-blue-500' }, header_options: { class: 'gl-bg-blue-500 gl-text-white' }) do |c|
+ - c.header do
= s_('GitLabPages|Configure pages')
- .card-body
- %p.gl-mb-0
- - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
- - samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer'>".html_safe
- - link_end = '</a>'.html_safe
- = s_('GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, link_end: link_end }
+ - c.body do
+ - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_docs_link'>".html_safe
+ - samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_samples_link'>".html_safe
+ - link_end = '</a>'.html_safe
+ = s_('GitLabPages|Your Pages site is not configured yet. See the %{docs_link_start}GitLab Pages documentation%{link_end} to learn how to upload your static site and have GitLab serve it. You can also take some inspiration from the %{samples_link_start}sample Pages projects%{link_end}.').html_safe % { docs_link_start: docs_link_start, samples_link_start: samples_link_start, link_end: link_end }
diff --git a/app/views/projects/pages/_waiting.html.haml b/app/views/projects/pages/_waiting.html.haml
new file mode 100644
index 00000000000..e8acadbabe3
--- /dev/null
+++ b/app/views/projects/pages/_waiting.html.haml
@@ -0,0 +1,13 @@
+.empty-state
+ .row.gl-align-items-center.gl-justify-content-center
+ .order-md-2
+ = image_tag 'illustrations/pipelines_pending.svg'
+ .row.gl-align-items-center.gl-justify-content-center
+ .text-content.gl-text-center.order-md-1
+ %h4= s_("GitLabPages|Waiting for the Pages Pipeline to complete...")
+ %p= s_("GitLabPages|Your Project has been configured for Pages. Now we have to wait for the Pipeline to succeed for the first time.")
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: project_pipelines_path(@project)) do
+ = s_("GitLabPages|Check the Pipeline Status")
+ = render Pajamas::ButtonComponent.new(href: new_namespace_project_pages_path) do
+ = s_("GitLabPages|Start over")
+
diff --git a/app/views/projects/pages/disabled.html.haml b/app/views/projects/pages/disabled.html.haml
new file mode 100644
index 00000000000..769ecac636b
--- /dev/null
+++ b/app/views/projects/pages/disabled.html.haml
@@ -0,0 +1,4 @@
+= render 'header'
+
+.bs-callout.bs-callout-warning
+ = html_escape_once(s_('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.')).html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
diff --git a/app/views/projects/pages/new.html.haml b/app/views/projects/pages/new.html.haml
new file mode 100644
index 00000000000..cdd52a933e9
--- /dev/null
+++ b/app/views/projects/pages/new.html.haml
@@ -0,0 +1,7 @@
+- if Feature.enabled?(:use_pipeline_wizard_for_pages, @group)
+ #js-pages{ data: @pipeline_wizard_data }
+
+- else
+ = render 'header'
+
+ = render 'use'
diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml
index 3fea9f9ff1b..01477967394 100644
--- a/app/views/projects/pages/show.html.haml
+++ b/app/views/projects/pages/show.html.haml
@@ -1,30 +1,20 @@
- page_title _('Pages')
-- if @project.pages_enabled?
- %h1.page-title.gl-font-size-h-display.with-button
- = s_('GitLabPages|Pages')
+- unless @project.pages_deployed?
+ = render 'waiting'
- - if can?(current_user, :update_pages, @project) && (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https)
- = link_to new_project_pages_domain_path(@project), class: 'btn gl-button btn-confirm float-right', title: s_('GitLabPages|New Domain') do
- = s_('GitLabPages|New Domain')
+- else
+ = render 'header'
- %p.light
- - docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
- - link_end = '</a>'.html_safe
- = s_('GitLabPages|With GitLab Pages you can host your static website directly from your GitLab repository. %{docs_link_start}Learn more.%{link_end}').html_safe % { docs_link_start: docs_link_start, link_end: link_end }
+ %section
= render 'pages_settings'
%hr.clearfix
-
- = render 'ssl_limitations_warning' if @project.pages_subdomain.include?(".")
- = render 'access'
- = render 'use'
- - if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
- = render 'list'
- - else
- = render 'no_domains'
- = render 'destroy'
-- else
- .bs-callout.bs-callout-warning
- = html_escape_once(s_('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.')).html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
+ = render 'ssl_limitations_warning' if @project.pages_subdomain.include?(".")
+ = render 'access'
+ - if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
+ = render 'list'
+ - else
+ = render 'no_domains'
+ = render 'destroy'
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index edcd44563f7..c36c3ae5adf 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -33,7 +33,7 @@
= link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: _('Play'), class: 'btn gl-button btn-default btn-icon' do
= sprite_icon('play')
- if can?(current_user, :take_ownership_pipeline_schedule, pipeline_schedule)
- = link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn gl-button btn-default' do
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-take-ownership-button has-tooltip', title: s_('PipelineSchedule|Take ownership to edit'), data: { url: take_ownership_pipeline_schedule_path(pipeline_schedule) } }) do
= s_('PipelineSchedules|Take ownership')
- if can?(current_user, :update_pipeline_schedule, pipeline_schedule)
= link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-button btn-default btn-icon' do
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index a56e8f7f5c7..661cf465081 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -18,3 +18,5 @@
- else
.card.bg-light.gl-mt-3
.nothing-here-block= _("No schedules")
+
+#pipeline-take-ownership-modal
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 5a655e7e83d..e16a2235e53 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -6,4 +6,5 @@
failed_pipelines_link: project_pipelines_path(@project, page: '1', scope: 'all', status: 'failed'),
coverage_chart_path: charts_project_graph_path(@project, @project.default_branch),
test_runs_empty_state_image_path: image_path('illustrations/pipeline.svg'),
+ project_quality_summary_feedback_image_path: image_path('illustrations/chat-bubble-sm.svg'),
default_branch: @project.default_branch } }
diff --git a/app/views/projects/project_templates/_template.html.haml b/app/views/projects/project_templates/_template.html.haml
index 5e4b1397dd3..d0fdd3a729a 100644
--- a/app/views/projects/project_templates/_template.html.haml
+++ b/app/views/projects/project_templates/_template.html.haml
@@ -10,7 +10,8 @@
.controls.d-flex.align-items-center
%a.btn.gl-button.btn-default.gl-mr-3{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "template_preview", track_property: template.name, track_action: "click_button", track_value: "" } }
= _("Preview")
- %label.btn.gl-button.btn-confirm.template-button.choose-template.gl-mb-0{ for: template.name }
+ %label.btn.gl-button.btn-confirm.template-button.choose-template.gl-mb-0{ for: template.name,
+ 'data-testid': "use_template_#{template.name}" }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "template_use", track_property: template.name, track_action: "click_button", track_value: "" } }
%span{ data: { qa_selector: 'use_template_button' } }
= _("Use template")
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 3b8294a1dec..35770c32f9f 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,9 +1,9 @@
= 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' }
- .card
- .card-header.gl-font-weight-bold
+ = render Pajamas::CardComponent.new(card_options: { class: "gl-mb-5" }) do |c|
+ - c.header do
= s_("ProtectedBranch|Protect a branch")
- .card-body
+ - c.body do
= form_errors(@protected_branch, pajamas_alert: true)
.form-group.row
= f.label :name, s_('ProtectedBranch|Branch:'), class: 'col-sm-12'
@@ -31,5 +31,5 @@
- force_push_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: force_push_docs_url }
= (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
- .card-footer
+ - c.footer do
= f.submit s_('ProtectedBranch|Protect'), class: 'gl-button btn btn-confirm', disabled: true, data: { qa_selector: 'protect_button' }
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index 449b6c25f50..5acd6f95df4 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -28,9 +28,9 @@
= _('This group does not have any group runners yet.')
- if can?(current_user, :admin_group_runners, @project.group)
- - register_runners_path = group_runners_path(@project.group)
- - group_link = link_to _("group's CI/CD settings."), register_runners_path
- = _('Group owners can register group runners in the %{link}').html_safe % { link: group_link }
+ - group_link_start = "<a href='#{group_runners_path(@project.group)}'>".html_safe
+ - group_link_end = '</a>'.html_safe
+ = s_("Runners|To register them, go to the %{link_start}group's Runners page%{link_end}.").html_safe % { link_start: group_link_start, link_end: group_link_end }
- else
= _('Ask your group owner to set up a group runner.')
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index 359e34d8918..7ecc8004334 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -37,7 +37,7 @@
token: @resource_access_token,
scopes: @scopes,
access_levels: ProjectMember.permissible_access_level_roles(current_user, @project),
- default_access_level: Gitlab::Access::MAINTAINER,
+ default_access_level: Gitlab::Access::GUEST,
prefix: :resource_access_token,
help_path: help_page_path('user/project/settings/project_access_tokens', anchor: 'scopes-for-a-project-access-token')
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 64f45ec89d1..ea77bda0b0f 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -20,7 +20,7 @@
%fieldset.builds-feature.js-auto-devops-settings
.form-group
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
- .card.auto-devops-card
+ .card.gl-mb-3
.card-body
- autodevops_help_link = link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer'
- auto_devops_badge = auto_devops_enabled ? (gl_badge_tag badge_for_auto_devops_scope(@project), { variant: :info }, { class: 'js-instance-default-badge gl-ml-3 gl-mt-n1'}) : ''
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 09f9ca60b3e..dd9cc296d52 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -41,7 +41,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
- = link_to s_('How do I configure runners?'), help_page_path('ci/runners/index'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to s_('What is GitLab Runner?'), 'https://docs.gitlab.com/runner/', target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/runners/settings'
diff --git a/app/views/projects/settings/integrations/edit.html.haml b/app/views/projects/settings/integrations/edit.html.haml
index a250daafdbb..46276e6c6c9 100644
--- a/app/views/projects/settings/integrations/edit.html.haml
+++ b/app/views/projects/settings/integrations/edit.html.haml
@@ -6,4 +6,5 @@
= render 'form', integration: @integration
- if @web_hook_logs
- = render partial: 'projects/hook_logs/index', locals: { hook: @integration.service_hook, hook_logs: @web_hook_logs, project: @project }
+ %hr
+ = render partial: 'shared/hook_logs/index', locals: { hook: @integration.service_hook, hook_logs: @web_hook_logs, project: @project }
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 50bfd3c6976..87e3e03099c 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -2,22 +2,18 @@
- page_title _('Monitor Settings')
- breadcrumb_title _('Monitor Settings')
-.gl-alert.gl-alert-danger.gl-mb-5
- - removal_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/7188'
- - removal_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: removal_epic_link_url }
- - opstrace_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/6976'
- - opstrace_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: opstrace_link_url }
- - link_end = '</a>'.html_safe
- .gl-alert-container
- = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-content
- .gl-alert-title
- = s_('Deprecations|Feature deprecation and removal')
- .gl-alert-body
- %p
- = html_escape(s_('Deprecations|The metrics feature was deprecated in GitLab 14.7.'))
- = html_escape(s_('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.')) % {removal_link_start: removal_epic_link_start, link_end: link_end }
- = html_escape(s_('Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {opstrace_link_start: opstrace_link_start, link_end: link_end }
+= render Pajamas::AlertComponent.new(variant: :danger,
+ dismissible: false,
+ title: s_('Deprecations|Feature deprecation and removal')) do |c|
+ = c.body do
+ - removal_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/7188'
+ - removal_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: removal_epic_link_url }
+ - opstrace_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/6976'
+ - opstrace_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: opstrace_link_url }
+ - link_end = '</a>'.html_safe
+ = html_escape(s_('Deprecations|The metrics feature was deprecated in GitLab 14.7.'))
+ = html_escape(s_('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.')) % {removal_link_start: removal_epic_link_start, link_end: link_end }
+ = html_escape(s_('Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {opstrace_link_start: opstrace_link_start, link_end: link_end }
= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/error_tracking'
diff --git a/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml b/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml
new file mode 100644
index 00000000000..795544b75a2
--- /dev/null
+++ b/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml
@@ -0,0 +1,6 @@
+- add_to_breadcrumbs _('Packages & Registries'), project_settings_packages_and_registries_path(@project)
+- breadcrumb_title s_('ContainerRegistry|Clean up image tags')
+- page_title s_('ContainerRegistry|Clean up image tags'), _('Packages & Registries')
+- @content_class = 'limit-container-width' unless fluid_layout
+
+#js-registry-settings-cleanup-image-tags{ data: cleanup_settings_data }
diff --git a/app/views/projects/settings/packages_and_registries/show.html.haml b/app/views/projects/settings/packages_and_registries/show.html.haml
index 1a7821d3268..d579981ebc0 100644
--- a/app/views/projects/settings/packages_and_registries/show.html.haml
+++ b/app/views/projects/settings/packages_and_registries/show.html.haml
@@ -2,16 +2,4 @@
- page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout
-#js-registry-settings{ data: { project_id: @project.id,
- project_path: @project.full_path,
- cadence_options: cadence_options.to_json,
- keep_n_options: keep_n_options.to_json,
- older_than_options: older_than_options.to_json,
- is_admin: current_user&.admin.to_s,
- show_container_registry_settings: show_container_registry_settings(@project).to_s,
- show_package_registry_settings: show_package_registry_settings(@project).to_s,
- admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
- enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
- help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
- show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
- tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples') } }
+#js-registry-settings{ data: settings_data }
diff --git a/app/views/projects/tags/_edit_release_button.html.haml b/app/views/projects/tags/_edit_release_button.html.haml
index 5bdf1c7896c..1c2626e5612 100644
--- a/app/views/projects/tags/_edit_release_button.html.haml
+++ b/app/views/projects/tags/_edit_release_button.html.haml
@@ -1,11 +1,9 @@
-- if Feature.enabled?(:edit_tag_release_notes_via_release_page, project)
- - release_btn_text = s_('TagsPage|Create release')
- - release_btn_path = new_project_release_path(project, tag_name: tag.name)
- - if release
- - release_btn_text = s_('TagsPage|Edit release')
- - release_btn_path = edit_project_release_path(project, release)
- = link_to release_btn_path, class: 'btn gl-button btn-default btn-icon btn-edit has-tooltip', title: release_btn_text, data: { container: "body" } do
- = sprite_icon('pencil', css_class: 'gl-icon')
-- else
- = link_to edit_project_tag_release_path(project, tag.name), class: 'btn gl-button btn-default btn-icon btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
- = sprite_icon('pencil', css_class: 'gl-icon')
+- release_btn_text = s_('TagsPage|Create release')
+- release_btn_path = new_project_release_path(project, tag_name: tag.name)
+- option_css_classes = local_assigns.fetch(:option_css_classes, '')
+- css_classes = "btn gl-button btn-default btn-icon btn-edit has-tooltip #{option_css_classes}"
+- if release
+ - release_btn_text = s_('TagsPage|Edit release')
+ - release_btn_path = edit_project_release_path(project, release)
+= link_to release_btn_path, class: css_classes, title: release_btn_text, data: { container: "body" } do
+ = sprite_icon('pencil', css_class: 'gl-icon')
diff --git a/app/views/projects/tags/_release_link.html.haml b/app/views/projects/tags/_release_link.html.haml
new file mode 100644
index 00000000000..c942d122a58
--- /dev/null
+++ b/app/views/projects/tags/_release_link.html.haml
@@ -0,0 +1,4 @@
+.gl-text-secondary
+ = sprite_icon("rocket", size: 12)
+ = _("Release")
+ = link_to release.name, project_release_path(project, release), class: "gl-text-blue-600!"
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index 258f662420b..fcad8509a7d 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -18,10 +18,7 @@
= s_("TagsPage|Can't find HEAD commit for this tag")
- if release
- .text-secondary
- = sprite_icon("rocket", size: 12)
- = _("Release")
- = link_to release.name, project_release_path(@project, release), class: 'gl-text-blue-600!'
+ = render 'release_link', project: @project, release: release
- if tag.message.present?
%pre.wrap
@@ -40,5 +37,5 @@
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :admin_tag, @project)
- = render 'edit_release_button', tag: tag, project: @project, release: release
+ = render 'edit_release_button', tag: tag, project: @project, release: release, option_css_classes: 'gl-mr-3!'
= render 'projects/buttons/remove_tag', project: @project, tag: tag
diff --git a/app/views/projects/tags/releases/edit.html.haml b/app/views/projects/tags/releases/edit.html.haml
deleted file mode 100644
index c99f146ea7a..00000000000
--- a/app/views/projects/tags/releases/edit.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-- add_to_breadcrumbs _("Tags"), project_tags_path(@project)
-- breadcrumb_title @tag.name
-- page_title _("Edit"), @tag.name, _("Tags")
-
-.sub-header-block.no-bottom-space
- .oneline
- .title
- Release notes for tag
- %strong= @tag.name
-
-= form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name),
- html: { class: 'common-note-form release-form js-quick-submit' }) do |f|
- = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do
- = render 'shared/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here…"
- = render 'shared/notes/hints'
- .error-alert
- .gl-mt-5.gl-display-flex
- = f.submit _('Save changes'), class: 'btn gl-button btn-confirm gl-mr-3'
- = link_to _('Cancel'), project_tag_path(@project, @tag.name), class: "btn gl-button btn-default btn-cancel"
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 24da8e2db87..cb7751ecf2e 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -37,20 +37,21 @@
- else
= s_("TagsPage|Can't find HEAD commit for this tag")
+ - if @release
+ = render 'release_link', project: @project, release: @release
+
.nav-controls
- if @tag.has_signature?
= render partial: 'projects/commit/signature', object: @tag.signature
- if can?(current_user, :admin_tag, @project)
= render 'edit_release_button', tag: @tag, project: @project, release: @release
- = link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse files') do
+ = link_to project_tree_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default has-tooltip', title: s_('TagsPage|Browse files') do
= sprite_icon('folder-open', css_class: 'gl-icon')
- = link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default controls-item has-tooltip', title: s_('TagsPage|Browse commits') do
+ = link_to project_commits_path(@project, @tag.name), class: 'btn btn-icon gl-button btn-default has-tooltip', title: s_('TagsPage|Browse commits') do
= sprite_icon('history', css_class: 'gl-icon')
- .controls-item
- = render 'projects/buttons/download', project: @project, ref: @tag.name
+ = render 'projects/buttons/download', project: @project, ref: @tag.name
- if can?(current_user, :admin_tag, @project)
- .btn-container.controls-item-full
- = render 'projects/buttons/remove_tag', project: @project, tag: @tag
+ = render 'projects/buttons/remove_tag', project: @project, tag: @tag
- if @tag.message.present?
%pre.wrap{ data: { qa_selector: 'tag_message_content' } }
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index 8b3d0ef17a4..0c53ed48210 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -1,4 +1,4 @@
-.row.gl-mt-3.gl-mb-3.triggers-container
+.row.gl-mt-3.gl-mb-3
.col-lg-12
.card
.card-header
diff --git a/app/views/projects/triggers/_trigger.html.haml b/app/views/projects/triggers/_trigger.html.haml
index ce036606a1c..bce7dc8a94b 100644
--- a/app/views/projects/triggers/_trigger.html.haml
+++ b/app/views/projects/triggers/_trigger.html.haml
@@ -6,7 +6,7 @@
- else
%span= trigger.short_token
- .label-container
+ .gl-display-inline-block.gl-ml-3
- unless trigger.can_access_project?
= gl_badge_tag s_('Trigger|invalid'), { variant: :danger }, { title: s_('Trigger|Trigger user has insufficient permissions to project'), data: { toggle: 'tooltip', container: 'body' } }
@@ -27,7 +27,7 @@
- else
Never
- %td.text-right.trigger-actions
+ %td.text-right.gl-white-space-nowrap
- revoke_trigger_confirmation = "By revoking a trigger you will break any processes making use of it. Are you sure?"
- if can?(current_user, :admin_trigger, trigger)
= link_to edit_project_trigger_path(@project, trigger), method: :get, title: "Edit", class: "gl-button btn btn-default btn-icon" do
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index d5d3cd753f3..168f4ca10bc 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -3,7 +3,7 @@
= 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)
+ - 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
diff --git a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
index 1f37e33a037..ac7d56520f7 100644
--- a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
+++ b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
@@ -1,5 +1,5 @@
- if show_auto_devops_implicitly_enabled_banner?(project, current_user)
- = render Pajamas::AlertComponent.new(alert_options: { class: 'qa-auto-devops-banner auto-devops-implicitly-enabled-banner' },
+ = render Pajamas::AlertComponent.new(alert_options: { class: 'auto-devops-implicitly-enabled-banner', data: { qa_selector: 'auto_devops_banner_content' } },
close_button_options: { class: 'hide-auto-devops-implicitly-enabled-banner',
data: { project_id: project.id }}) do |c|
= c.body do
diff --git a/app/views/shared/_broadcast_message.html.haml b/app/views/shared/_broadcast_message.html.haml
index f7794677dc1..a202add339f 100644
--- a/app/views/shared/_broadcast_message.html.haml
+++ b/app/views/shared/_broadcast_message.html.haml
@@ -21,7 +21,7 @@
- else
- notification_class = "js-broadcast-notification-#{message.id}"
- notification_class << ' preview' if preview
- .broadcast-message.broadcast-notification-message.mt-2{ role: "alert", class: notification_class }
+ .broadcast-message.broadcast-notification-message.mt-2{ role: "alert", class: notification_class, data: { qa_selector: 'broadcast_notification_container' } }
= sprite_icon(icon_name, css_class: 'vertical-align-text-top')
- if message.message.present?
= render_broadcast_message(message)
@@ -31,5 +31,5 @@
= render Pajamas::ButtonComponent.new(variant: :link,
icon: 'close',
size: :small,
- button_options: { class: 'js-dismiss-current-broadcast-notification', 'aria-label': _('Close'), data: { id: message.id, expire_date: message.ends_at.iso8601 } },
+ button_options: { class: 'js-dismiss-current-broadcast-notification', 'aria-label': _('Close'), data: { id: message.id, expire_date: message.ends_at.iso8601, qa_selector: 'close_button' } },
icon_classes: 'gl-mx-3! gl-text-gray-700')
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index 80b50f7a3de..6b502ee928e 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -5,7 +5,7 @@
%span.js-clone-dropdown-label
= enabled_protocol_button(container, enabled_protocol)
- else
- %a#clone-dropdown.input-group-text.gl-button.btn.btn-default.btn-icon.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %a#clone-dropdown.input-group-text.gl-button.btn.btn-default.btn-icon.clone-dropdown-btn{ href: '#', data: { toggle: 'dropdown', qa_selector: 'clone_dropdown' } }
%span.js-clone-dropdown-label
= default_clone_protocol.upcase
= sprite_icon('chevron-down', css_class: 'gl-icon')
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index f8ac3832a77..23a17c07ea8 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,13 +1,17 @@
#blob-content.file-content.code.js-syntax-highlight
- offset = defined?(first_line_number) ? first_line_number : 1
- .line-numbers
+ .line-numbers{ class: "gl-p-0\!" }
- if blob.data.present?
- link = blob_link if defined?(blob_link)
+ - blame_link = project_blame_path(@project, tree_join(@ref, blob.path))
- 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{ href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
- = i
+ .line-links.diff-line-num
+ - if Feature.enabled?(:file_line_blame)
+ %a.file-line-blame{ href: "#{blame_link}#L#{i}" }
+ %a.file-line-num{ href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
+ = i
- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
.blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
%pre.code.highlight
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
deleted file mode 100644
index db5e055a1c4..00000000000
--- a/app/views/shared/_group_form.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- parent = @group.parent
-- group_path = root_url
-- group_path << parent.full_path + '/' if parent
-
-
-= render 'shared/groups/group_name_and_path_fields', f: f
diff --git a/app/views/shared/_help_dropdown_forum_link.html.haml b/app/views/shared/_help_dropdown_forum_link.html.haml
index f3c69a7c897..06889428e82 100644
--- a/app/views/shared/_help_dropdown_forum_link.html.haml
+++ b/app/views/shared/_help_dropdown_forum_link.html.haml
@@ -1,2 +1,2 @@
-= link_to _("Community forum"), "https://forum.gitlab.com/", target: '_blank', class: 'text-nowrap',
+= link_to _("Community forum"), ApplicationHelper.community_forum, target: '_blank', class: 'text-nowrap',
rel: 'noopener noreferrer', data: { 'track_action': 'click_forum', 'track_property': 'question_menu' }
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index 252f9c26f06..c351ea29c7c 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -3,11 +3,11 @@
- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues)
- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests)
-.label-name.gl-flex-shrink-0.gl-mt-2.gl-mr-3
+.label-name.gl-flex-shrink-0.gl-mt-2.gl-mr-5
= render_label(label, tooltip: false)
.label-description.gl-overflow-hidden.gl-w-full
.gl-display-flex.gl-align-items-stretch.gl-flex-wrap.gl-mt-2
- .gl-flex-basis-half.gl-flex-grow-1.gl-overflow-hidden.gl-mr-2
+ .gl-flex-basis-half.gl-flex-grow-1.gl-overflow-hidden.gl-mr-5
- if label.description.present?
= markdown_field(label, :description)
- elsif show_labels_full_path?(@project, @group)
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index 821f1ede422..0bd5d1795d0 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -1,6 +1,6 @@
- if any_projects?(@projects)
.dropdown.b-dropdown.gl-new-dropdown.btn-group.project-item-select-holder{ class: 'gl-display-inline-flex!' }
- %a.btn.gl-button.btn-confirm.split-content-button.js-new-project-item-link.block-truncated.qa-new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
+ %a.btn.gl-button.btn-confirm.split-content-button.js-new-project-item-link.block-truncated{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
= gl_loading_icon(inline: true, color: 'light')
= project_select_tag :project_path, class: "project-item-select gl-absolute! gl-visibility-hidden", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path], with_shared: local_assigns[:with_shared], include_projects_in_subgroups: local_assigns[:include_projects_in_subgroups] }, with_feature_enabled: local_assigns[:with_feature_enabled]
- %button.btn.dropdown-toggle.btn-confirm.btn-md.gl-button.gl-dropdown-toggle.dropdown-toggle-split.new-project-item-select-button.qa-new-project-item-select-button{ 'aria-label': _('Toggle project select') }
+ %button.btn.dropdown-toggle.btn-confirm.btn-md.gl-button.gl-dropdown-toggle.dropdown-toggle-split.new-project-item-select-button{ 'aria-label': _('Toggle project select') }
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
index 74e0a088656..20bf2141cc3 100644
--- a/app/views/shared/_ref_switcher.html.haml
+++ b/app/views/shared/_ref_switcher.html.haml
@@ -13,8 +13,8 @@
- @options && @options.each do |key, value|
= hidden_field_tag key, value, id: nil
.dropdown
- = dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: ref, refs_url: refs_project_path(@project, sort: 'updated_desc'), field_name: field_name, submit_form_on_click: true, visit: true }, { toggle_class: "js-project-refs-dropdown qa-branches-select" }
- .dropdown-menu.dropdown-menu-selectable.git-revision-dropdown.dropdown-menu-paging.qa-branches-dropdown{ class: ("dropdown-menu-right" if local_assigns[:align_right]) }
+ = dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: ref, refs_url: refs_project_path(@project, sort: 'updated_desc'), field_name: field_name, submit_form_on_click: true, visit: true, qa_selector: "branches_dropdown", testid: "branches-select" }, { toggle_class: "js-project-refs-dropdown" }
+ .dropdown-menu.dropdown-menu-selectable.git-revision-dropdown.dropdown-menu-paging{ class: ("dropdown-menu-right" if local_assigns[:align_right]), data: { qa_selector: "branches_dropdown_content" } }
.dropdown-page-one
= dropdown_title _("Switch branch/tag")
= dropdown_filter _("Search branches and tags")
diff --git a/app/views/shared/_remote_mirror_update_button.html.haml b/app/views/shared/_remote_mirror_update_button.html.haml
index f3942aa5dc2..770d335a88b 100644
--- a/app/views/shared/_remote_mirror_update_button.html.haml
+++ b/app/views/shared/_remote_mirror_update_button.html.haml
@@ -3,5 +3,5 @@
button_options: { class: 'disabled', title: _('Updating'), data: { toggle: 'tooltip', container: 'body', qa_selector: 'updating_button' } },
icon_classes: 'spin')
- elsif remote_mirror.enabled?
- = link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn btn-icon gl-button qa-update-now-button rspec-update-now-button", data: { toggle: 'tooltip', container: 'body' }, title: _('Update now') do
+ = link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn btn-icon gl-button rspec-update-now-button", data: { toggle: 'tooltip', container: 'body', qa_selector: 'update_now_button' }, title: _('Update now') do
= sprite_icon("retry")
diff --git a/app/views/shared/_search_settings.html.haml b/app/views/shared/_search_settings.html.haml
index 7265f090967..95eb421dbfe 100644
--- a/app/views/shared/_search_settings.html.haml
+++ b/app/views/shared/_search_settings.html.haml
@@ -4,4 +4,4 @@
%div{ class: container_class }
.js-search-settings-app
- %input.gl-form-input.form-control{ type: "text", placeholder: _("Search settings"), aria_label: _("Search settings"), disabled: true }
+ %input.gl-form-input.form-control{ type: "text", placeholder: _("Search settings"), aria: { label: _("Search settings") }, disabled: true }
diff --git a/app/views/shared/_sidebar_toggle_button.html.haml b/app/views/shared/_sidebar_toggle_button.html.haml
index 0a74e47fa4c..4cdf1340d64 100644
--- a/app/views/shared/_sidebar_toggle_button.html.haml
+++ b/app/views/shared/_sidebar_toggle_button.html.haml
@@ -1,4 +1,4 @@
-%a.toggle-sidebar-button.js-toggle-sidebar.qa-toggle-sidebar.rspec-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
+%a.toggle-sidebar-button.js-toggle-sidebar.rspec-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
= sprite_icon('chevron-double-lg-left', size: 12, css_class: 'icon-chevron-double-lg-left')
%span.collapse-text.gl-ml-3= _("Collapse sidebar")
diff --git a/app/views/shared/access_tokens/_form.html.haml b/app/views/shared/access_tokens/_form.html.haml
index 0f6fc860883..dd4d2ab46c1 100644
--- a/app/views/shared/access_tokens/_form.html.haml
+++ b/app/views/shared/access_tokens/_form.html.haml
@@ -27,7 +27,7 @@
.row
.col
.js-access-tokens-expires-at{ data: expires_at_field_data }
- = f.text_field :expires_at, class: 'datepicker gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', data: { js_name: 'expiresAt' }
+ = f.text_field :expires_at, class: 'gl-datepicker-input form-control gl-form-input', placeholder: 'YYYY-MM-DD', autocomplete: 'off', data: { js_name: 'expiresAt' }
- if resource
.row
@@ -45,9 +45,5 @@
= link_to _("Learn more."), help_path, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/tokens/scopes_form', prefix: prefix, token: token, scopes: scopes, f: f
- - if prefix == :personal_access_token && Feature.enabled?(:personal_access_tokens_scoped_to_projects, current_user)
- .js-access-tokens-projects
- %input{ type: 'hidden', name: 'personal_access_token[projects]', id: 'personal_access_token_projects', data: { js_name: 'projects' } }
-
.gl-mt-3
= f.submit _('Create %{type}') % { type: type }, class: 'gl-button btn btn-confirm', data: { qa_selector: 'create_token_button' }
diff --git a/app/views/shared/access_tokens/_table.html.haml b/app/views/shared/access_tokens/_table.html.haml
index 5ca9cf8d9a4..53c6800f93d 100644
--- a/app/views/shared/access_tokens/_table.html.haml
+++ b/app/views/shared/access_tokens/_table.html.haml
@@ -45,7 +45,7 @@
%span.token-never-expires-label= _('Never')
- if resource
%td= resource.member(token.user).human_access
- %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: "gl-button btn btn-danger btn-sm float-right qa-revoke-button #{'btn-danger-secondary' unless token.expires?}", aria: { label: _('Revoke') }, data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type }, 'confirm-btn-variant': 'danger' }
+ %td= link_to _('Revoke'), revoke_route_helper.call(token), method: :put, class: "gl-button btn btn-danger btn-sm float-right #{'btn-danger-secondary' unless token.expires?}", aria: { label: _('Revoke') }, data: { confirm: _('Are you sure you want to revoke this %{type}? This action cannot be undone.') % { type: type }, 'confirm-btn-variant': 'danger', qa_selector: 'revoke_button' }
- else
.settings-message.text-center
= no_active_tokens_message
diff --git a/app/views/shared/admin/_admin_note.html.haml b/app/views/shared/admin/_admin_note.html.haml
index 82407705885..9dcf181a118 100644
--- a/app/views/shared/admin/_admin_note.html.haml
+++ b/app/views/shared/admin/_admin_note.html.haml
@@ -1,7 +1,7 @@
- if @group.admin_note.present?
- text = @group.admin_note.note
- .card.border-info
- .card-header.bg-info.gl-text-white
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-border-blue-500 gl-mb-5' }, header_options: { class: 'gl-bg-blue-500 gl-text-white' }) do |c|
+ - c.header do
= s_('Admin|Admin notes')
- .card-body
+ - c.body do
%p= text
diff --git a/app/views/shared/blob/_markdown_buttons.html.haml b/app/views/shared/blob/_markdown_buttons.html.haml
index 60641006e96..4db1d20e81b 100644
--- a/app/views/shared/blob/_markdown_buttons.html.haml
+++ b/app/views/shared/blob/_markdown_buttons.html.haml
@@ -22,11 +22,15 @@
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "- ", "md-prepend" => true }, title: _("Add a bullet list") })
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
- = markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a task list") })
+ = markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a checklist") })
= 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") })
- 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")
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index 2e04bbf3605..eade973d72a 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -12,7 +12,7 @@
.form-group
= f.label :expires_at, _('Expiration date (optional)'), class: 'label-bold'
- = f.text_field :expires_at, class: 'datepicker form-control', data: { qa_selector: 'deploy_token_expires_at_field' }, value: f.object.expires_at
+ = f.gitlab_ui_datepicker :expires_at, data: { qa_selector: 'deploy_token_expires_at_field' }, value: f.object.expires_at
.text-secondary= s_('DeployTokens|Enter an expiration date for your token. Defaults to never expire.')
.form-group
diff --git a/app/views/shared/empty_states/_labels.html.haml b/app/views/shared/empty_states/_labels.html.haml
index 4e5e04ba4d4..e96fcd11cef 100644
--- a/app/views/shared/empty_states/_labels.html.haml
+++ b/app/views/shared/empty_states/_labels.html.haml
@@ -1,6 +1,6 @@
.row.empty-state.labels
.col-12
- .svg-content.qa-label-svg
+ .svg-content{ data: { qa_selector: 'label_svg_content' } }
= image_tag 'illustrations/labels.svg'
.col-12
.text-content
@@ -8,7 +8,7 @@
%p= _("You can also star a label to make it a priority label.")
.text-center
- if can?(current_user, :admin_label, @project)
- = link_to _('New label'), new_project_label_path(@project), class: 'btn gl-button btn-confirm qa-label-create-new', title: _('New label'), id: 'new_label_link'
+ = link_to _('New label'), new_project_label_path(@project), class: 'btn gl-button btn-confirm', title: _('New label'), id: 'new_label_link'
= link_to _('Generate a default set of labels'), generate_project_labels_path(@project), method: :post, class: 'btn gl-button btn-confirm-secondary', title: _('Generate a default set of labels'), id: 'generate_labels_link'
- if can?(current_user, :admin_label, @group)
= link_to _('New label'), new_group_label_path(@group), class: 'btn gl-button btn-confirm', title: _('New label'), id: 'new_label_link'
diff --git a/app/views/shared/empty_states/_priority_labels.html.haml b/app/views/shared/empty_states/_priority_labels.html.haml
index a93f6e4c795..3381c5f0c67 100644
--- a/app/views/shared/empty_states/_priority_labels.html.haml
+++ b/app/views/shared/empty_states/_priority_labels.html.haml
@@ -1,5 +1,5 @@
.text-center
- .svg-content.qa-label-svg
+ .svg-content{ data: { qa_selector: 'label_svg_content' } }
= image_tag 'illustrations/priority_labels.svg'
- if can?(current_user, :admin_label, @project)
%p
diff --git a/app/views/shared/empty_states/_topics.html.haml b/app/views/shared/empty_states/_topics.html.haml
index fd82a853037..0283e852c7d 100644
--- a/app/views/shared/empty_states/_topics.html.haml
+++ b/app/views/shared/empty_states/_topics.html.haml
@@ -1,7 +1,7 @@
.row.empty-state
.col-12
.svg-content
- = image_tag 'illustrations/labels.svg', data: { qa_selector: 'svg_content' }
+ = image_tag 'illustrations/labels.svg'
.text-content.gl-text-center.gl-pt-0!
%h4= _('There are no topics to show.')
%p= _('Add topics to projects to help users find them.')
diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index 552b100d5dd..8304a2f18a0 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -3,7 +3,7 @@
- if can?(current_user, :create_wiki, @wiki.container)
- create_path = wiki_page_path(@wiki, params[:id], view: 'create')
- - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn gl-button btn-confirm qa-create-first-page-link', title: s_('WikiEmpty|Create your first page')
+ - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn gl-button btn-confirm', title: s_('WikiEmpty|Create your first page'), data: { qa_selector: 'create_first_page_link' }
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_login_empty.svg' } do
%h4.text-left
diff --git a/app/views/shared/empty_states/_wikis_layout.html.haml b/app/views/shared/empty_states/_wikis_layout.html.haml
index 3b100f832b2..0b7034838ed 100644
--- a/app/views/shared/empty_states/_wikis_layout.html.haml
+++ b/app/views/shared/empty_states/_wikis_layout.html.haml
@@ -1,6 +1,6 @@
.row.empty-state.empty-state-wiki
.col-12
- .svg-content.qa-svg-content
+ .svg-content{ data: { qa_selector: 'svg_content' } }
= image_tag image_path
.col-12
.text-content.text-center
diff --git a/app/views/shared/groups/_group_name_and_path_fields.html.haml b/app/views/shared/groups/_group_name_and_path_fields.html.haml
index 634b8448535..08192cc0cc5 100644
--- a/app/views/shared/groups/_group_name_and_path_fields.html.haml
+++ b/app/views/shared/groups/_group_name_and_path_fields.html.haml
@@ -1,5 +1,6 @@
-.js-group-name-and-path{ data: group_name_and_path_app_data(@group) }
+.js-group-name-and-path{ data: group_name_and_path_app_data.merge(new_subgroup: local_assigns[:new_subgroup].to_s) }
= f.hidden_field :name, data: { js_name: 'name' }
= f.hidden_field :path, maxlength: ::Namespace::URL_MAX_LENGTH, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, data: { js_name: 'path' }
= f.hidden_field :parent_id, value: @group.parent&.id, data: { js_name: 'parentId' }
+ = f.hidden_field :parent_full_path, value: @group.parent&.full_path, data: { js_name: 'parentFullPath' }
= f.hidden_field :id, data: { js_name: 'groupId' }
diff --git a/app/views/shared/groups/_search_form.html.haml b/app/views/shared/groups/_search_form.html.haml
index a574394694d..2afac0ad733 100644
--- a/app/views/shared/groups/_search_form.html.haml
+++ b/app/views/shared/groups/_search_form.html.haml
@@ -1,2 +1,2 @@
= form_tag request.path, method: :get, class: "group-filter-form js-group-filter-form", id: 'group-filter-form' do |f|
- = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter qa-groups-filter', spellcheck: false, id: 'group-filter-form-field'
+ = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter', data: { qa_selector: 'groups_filter_field' }, spellcheck: false, id: 'group-filter-form-field'
diff --git a/app/views/admin/hook_logs/_index.html.haml b/app/views/shared/hook_logs/_index.html.haml
index 6a46b0b3510..6a46b0b3510 100644
--- a/app/views/admin/hook_logs/_index.html.haml
+++ b/app/views/shared/hook_logs/_index.html.haml
diff --git a/app/views/shared/issuable/_assignees.html.haml b/app/views/shared/issuable/_assignees.html.haml
index 112b0368a3a..5326b26d655 100644
--- a/app/views/shared/issuable/_assignees.html.haml
+++ b/app/views/shared/issuable/_assignees.html.haml
@@ -3,11 +3,8 @@
- render_count = assignees_rendering_overflow ? max_render - 1 : max_render
- more_assignees_count = issuable.assignees.size - render_count
-- if issuable.instance_of?(MergeRequest) && current_user&.mr_attention_requests_enabled?
- = render 'shared/issuable/merge_request_assignees', issuable: issuable, count: render_count
-- else
- - issuable.assignees.take(render_count).each do |assignee| # rubocop: disable CodeReuse/ActiveRecord
- = link_to_member(@project, assignee, name: false, title: s_("MrList|Assigned to %{name}") % { name: assignee.name})
+- issuable.assignees.take(render_count).each do |assignee| # rubocop: disable CodeReuse/ActiveRecord
+ = link_to_member(@project, assignee, name: false, title: s_("MrList|Assigned to %{name}") % { name: assignee.name})
- if more_assignees_count > 0
%span{ class: 'avatar-counter has-tooltip', data: { container: 'body', placement: 'bottom', 'line-type' => 'old', qa_selector: 'avatar_counter_content' }, title: _("+%{more_assignees_count} more assignees") % { more_assignees_count: more_assignees_count} }
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index e90ea35f28e..ae8b266c092 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -3,7 +3,7 @@
- project = @target_project || @project
- presenter = local_assigns.fetch(:presenter, nil)
-= form_errors(issuable)
+= form_errors(issuable, pajamas_alert: true)
- if @conflict
= render Pajamas::AlertComponent.new(variant: :danger,
@@ -57,9 +57,9 @@
.gl-mt-5{ class: (is_footer ? "footer-block" : "middle-block") }
- if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path)
.gl-mb-5
- Please review the
- %strong= link_to('contribution guidelines', guide_url)
- for this project.
+ - contribution_guidelines_start = '<strong><a href="%{url}">'.html_safe % {url: strip_tags(guide_url)}
+ - contribution_guidelines_end = '</a></strong>'.html_safe
+ = 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 }
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index 08883bb3372..af63839d7c1 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -11,7 +11,7 @@
- dropdown_title = local_assigns.fetch(:dropdown_title, _('Filter by label'))
- dropdown_data = label_dropdown_data(edit_context, labels: labels_filter_path_with_defaults(only_group_labels: edit_context.is_a?(Group)), default_label: _('Labels'))
-- dropdown_data.merge!(data_options)
+- dropdown_data.merge!(data_options, qa_selector: "issuable_label_dropdown")
- label_name = local_assigns.fetch(:label_name, _('Labels'))
- no_default_styles = local_assigns.fetch(:no_default_styles, false)
- classes << 'js-extra-options' if extra_options
@@ -22,7 +22,7 @@
= hidden_field_tag data_options[:field_name], use_id ? label.try(:id) : label.try(:title), id: nil
.dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect.qa-issuable-label{ class: classes.join(' '), type: "button", data: dropdown_data }
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect{ class: classes.join(' '), type: "button", data: dropdown_data }
- apply_is_default_styles = (selected.nil? || selected.empty?) && !no_default_styles
%span.dropdown-toggle-text{ class: ("is-default" if apply_is_default_styles) }
= multi_label_name(selected, label_name)
diff --git a/app/views/shared/issuable/_merge_request_assignees.html.haml b/app/views/shared/issuable/_merge_request_assignees.html.haml
deleted file mode 100644
index 6c7a2496ec6..00000000000
--- a/app/views/shared/issuable/_merge_request_assignees.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- issuable.merge_request_assignees.take(count).each do |merge_request_assignee| # rubocop: disable CodeReuse/ActiveRecord
- - assignee = merge_request_assignee.assignee
- - assignee_tooltip = ( merge_request_assignee.attention_requested? ? s_("MrList|Attention requested from assignee %{name}") : s_("MrList|Assigned to %{name}") ) % { name: assignee.name}
-
- = link_to_member(@project, assignee, name: false, title: assignee_tooltip, extra_class: "gl-flex-direction-row-reverse") do
- - if merge_request_assignee.attention_requested?
- %span.gl-display-inline-flex
- = sprite_icon('attention-solid-sm', css_class: 'gl-text-orange-500 icon-overlap-and-shadow')
diff --git a/app/views/shared/issuable/_merge_request_reviewers.html.haml b/app/views/shared/issuable/_merge_request_reviewers.html.haml
deleted file mode 100644
index 8dd74e12aff..00000000000
--- a/app/views/shared/issuable/_merge_request_reviewers.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- issuable.merge_request_reviewers.take(count).each do |merge_request_reviewer| # rubocop: disable CodeReuse/ActiveRecord
- - reviewer = merge_request_reviewer.reviewer
- - reviewer_tooltip = ( merge_request_reviewer.attention_requested? ? s_("MrList|Attention requested from reviewer %{name}") : s_("MrList|Review requested from %{name}") ) % { name: reviewer.name}
-
- = link_to_member(@project, reviewer, name: false, title: reviewer_tooltip, extra_class: "gl-flex-direction-row-reverse") do
- - if merge_request_reviewer.attention_requested?
- %span.gl-display-inline-flex
- = sprite_icon('attention-solid-sm', css_class: 'gl-text-orange-500 icon-overlap-and-shadow')
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
index dc713337747..ef539029272 100644
--- a/app/views/shared/issuable/_milestone_dropdown.html.haml
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -7,8 +7,8 @@
- dropdown_title = local_assigns.fetch(:dropdown_title, _('Filter by milestone'))
- if selected.present? || params[:milestone_title].present?
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
-= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "qa-issuable-milestone-dropdown js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "qa-issuable-dropdown-menu-milestone dropdown-menu-selectable dropdown-menu-milestone",
- placeholder: _('Search milestones'), footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), default_label: _('Milestone') } }) do
+= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", dropdown_qa_selector: "issuable_milestone_dropdown_content",
+ 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
diff --git a/app/views/shared/issuable/_reviewers.html.haml b/app/views/shared/issuable/_reviewers.html.haml
index 3bf923eb946..4adb7096181 100644
--- a/app/views/shared/issuable/_reviewers.html.haml
+++ b/app/views/shared/issuable/_reviewers.html.haml
@@ -3,11 +3,8 @@
- render_count = reviewers_rendering_overflow ? max_render - 1 : max_render
- more_reviewers_count = issuable.reviewers.size - render_count
-- if issuable.instance_of?(MergeRequest) && current_user&.mr_attention_requests_enabled?
- = render 'shared/issuable/merge_request_reviewers', issuable: issuable, count: render_count
-- else
- - issuable.reviewers.take(render_count).each do |reviewer| # rubocop: disable CodeReuse/ActiveRecord
- = link_to_member(@project, reviewer, name: false, title: s_("MrList|Review requested from %{name}") % { name: reviewer.name})
+- issuable.reviewers.take(render_count).each do |reviewer| # rubocop: disable CodeReuse/ActiveRecord
+ = link_to_member(@project, reviewer, name: false, title: s_("MrList|Review requested from %{name}") % { name: reviewer.name})
- if more_reviewers_count > 0
%span{ class: 'avatar-counter has-tooltip', data: { container: 'body', placement: 'bottom', 'line-type' => 'old' }, title: _("+%{more_reviewers_count} more reviewers") % { more_reviewers_count: more_reviewers_count} }
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 6394e05ae24..21716710015 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -88,16 +88,6 @@
= render 'shared/issuable/user_dropdown_item',
user: User.new(username: '{{username}}', name: '{{name}}'),
avatar: { lazy: true, url: '{{avatar_url}}' }
- - if current_user&.mr_attention_requests_enabled?
- #js-dropdown-attention-requested.filtered-search-input-dropdown-menu.dropdown-menu
- - if current_user
- %ul{ data: { dropdown: true } }
- = render 'shared/issuable/user_dropdown_item',
- user: current_user
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- = render 'shared/issuable/user_dropdown_item',
- user: User.new(username: '{{username}}', name: '{{name}}'),
- avatar: { lazy: true, url: '{{avatar_url}}' }
= render_if_exists 'shared/issuable/approver_dropdown'
= render_if_exists 'shared/issuable/approved_by_dropdown'
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 55f5dce8b37..6da094924a0 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -26,11 +26,14 @@
= _('To-Do')
.js-issuable-todo{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } }
- .block.assignee.qa-assignee-block{ class: "#{'gl-mt-3' if !signed_in && moved_sidebar_enabled}" }
+ .block.assignee{ class: "#{'gl-mt-3' if !signed_in && moved_sidebar_enabled}", data: { qa_selector: 'assignee_block_container' } }
= render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees, signed_in: signed_in
+ - if issuable_sidebar[:supports_severity]
+ #js-severity
+
- if reviewers
- .block.reviewer.qa-reviewer-block
+ .block.reviewer
= render "shared/issuable/sidebar_reviewers", issuable_sidebar: issuable_sidebar, reviewers: reviewers, signed_in: signed_in
- if issuable_sidebar[:supports_escalation]
@@ -67,9 +70,6 @@
= _('Time tracking')
= gl_loading_icon(inline: true)
- - if issuable_sidebar[:supports_severity]
- #js-severity
-
- if issuable_sidebar.dig(:features_available, :health_status)
.js-sidebar-status-entry-point{ data: sidebar_status_data(issuable_sidebar, @project) }
diff --git a/app/views/shared/issuable/_sidebar_reviewers.html.haml b/app/views/shared/issuable/_sidebar_reviewers.html.haml
index ce252e74570..cd976b88304 100644
--- a/app/views/shared/issuable/_sidebar_reviewers.html.haml
+++ b/app/views/shared/issuable/_sidebar_reviewers.html.haml
@@ -36,7 +36,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])
- options[:data].merge!(data)
= render 'shared/issuable/sidebar_user_dropdown',
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 61cc408f6b3..76469b34832 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -35,7 +35,7 @@
= form.label :milestone_id, _('Milestone'), class: "col-12"
.col-12
.issuable-form-select-holder
- = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: _('Select milestone')
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: _('Select milestone')
.form-group.row
= form.label :label_ids, _('Labels'), class: "col-12"
@@ -53,4 +53,4 @@
= form.label :due_date, _('Due date'), class: "col-12"
.col-12
.issuable-form-select-holder
- = form.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: _('Select due date'), autocomplete: 'off'
+ = form.gitlab_ui_datepicker :due_date, placeholder: _('Select due date'), autocomplete: 'off', id: "issuable-due-date"
diff --git a/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml b/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
index f9c3c11eed8..efecffbcc2e 100644
--- a/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
+++ b/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
@@ -8,4 +8,4 @@
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' }
= dropdown_tag(users_dropdown_label(issuable.assignees), options: assignees_dropdown_options(issuable.to_ability_name))
- = link_to _('Assign to me'), '#', class: "assign-to-me-link gl-white-space-nowrap gl-pl-4 qa-assign-to-me-link #{'hide' if issuable.assignees.include?(current_user)}"
+ = link_to _('Assign to me'), '#', class: "assign-to-me-link gl-white-space-nowrap gl-pl-4 #{'hide' if issuable.assignees.include?(current_user)}", data: { qa_selector: 'assign_to_me_link' }
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index e7c0833de0f..51f49c7ca8e 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -9,7 +9,7 @@
%div{ data: { testid: 'issue-title-input-field' } }
= form.text_field :title, required: true, aria: { required: true }, maxlength: 255, autofocus: true,
- autocomplete: 'off', class: 'form-control pad qa-issuable-form-title', dir: 'auto'
+ autocomplete: 'off', class: 'form-control pad', dir: 'auto', data: { qa_selector: 'issuable_form_title_field' }
- if issuable.respond_to?(:draft?)
.form-text.text-muted
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
index 39e7d196965..369aa53586f 100644
--- a/app/views/shared/issue_type/_details_content.html.haml
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -19,7 +19,7 @@
= render_if_exists 'projects/issues/work_item_links'
= render_if_exists 'projects/issues/linked_resources'
- = render_if_exists 'projects/issues/related_issues'
+ = render 'projects/issues/related_issues'
#js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: issuable.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml
index f768b63afff..cf8bd23b153 100644
--- a/app/views/shared/labels/_form.html.haml
+++ b/app/views/shared/labels/_form.html.haml
@@ -1,23 +1,23 @@
= form_for @label, as: :label, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f|
- = form_errors(@label)
+ = form_errors(@label, pajamas_alert: true)
.form-group.row
.col-12
= f.label :title
- = f.text_field :title, class: "gl-form-input form-control js-label-title qa-label-title", required: true, autofocus: true
+ = f.text_field :title, class: "gl-form-input form-control js-label-title", required: true, autofocus: true, data: { qa_selector: 'label_title_field' }
= render_if_exists 'shared/labels/create_label_help_text'
.form-group.row
.col-12
= f.label :description
- = f.text_field :description, class: "gl-form-input form-control js-quick-submit qa-label-description"
+ = f.text_field :description, class: "gl-form-input form-control js-quick-submit", data: { qa_selector: 'label_description_field' }
.form-group.row
.col-12
= f.label :color, _("Background color")
.input-group
.input-group-prepend
.input-group-text.label-color-preview &nbsp;
- = f.text_field :color, class: "gl-form-input form-control qa-label-color"
+ = f.text_field :color, class: "gl-form-input form-control", data: { qa_selector: 'label_color_field' }
.form-text.text-muted
= _('Choose any color.')
%br
@@ -28,7 +28,7 @@
- if @label.persisted?
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2'
- else
- = f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button qa-label-create-button gl-mr-2'
+ = f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2', data: { qa_selector: 'label_create_button' }
= 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/labels/_nav.html.haml b/app/views/shared/labels/_nav.html.haml
index 622ad9db425..c82a22c73b8 100644
--- a/app/views/shared/labels/_nav.html.haml
+++ b/app/views/shared/labels/_nav.html.haml
@@ -14,8 +14,8 @@
= render Pajamas::ButtonComponent.new(icon: 'search', button_options: { type: "submit", "aria-label" => _('Submit search') })
= render 'shared/labels/sort_dropdown'
- if labels_or_filters && can_admin_label && @project
- = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_project_label_path(@project), button_options: { class: 'qa-label-create-new' }) do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_project_label_path(@project), button_options: { data: { qa_selector: 'create_new_label_button' } }) do
= _('New label')
- if labels_or_filters && can_admin_label && @group
- = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_group_label_path(@group), button_options: { class: 'qa-label-create-new' }) do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_group_label_path(@group), button_options: { data: { qa_selector: 'create_new_label_button' } }) do
= _('New label')
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index ec08dde37bf..98e2c6c43b1 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -5,15 +5,16 @@
- return if requesters.empty?
-.card.gl-mt-3{ data: { testid: 'access-requests' } }
- .card-header
- = _("Users requesting access to")
+= 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|
+ - c.header do
+ = _('Users requesting access to')
%strong= membership_source.name
= gl_badge_tag requesters.size
= render 'shared/members/manage_access_button', path: membership_source.is_a?(Project) ? project_project_members_path(@project, tab: 'access_requests') : group_group_members_path(@group, tab: 'access_requests')
- %ul.content-list.members-list
- = render partial: 'shared/members/member',
- collection: requesters, as: :member,
- locals: { membership_source: membership_source,
+ - c.body do
+ %ul.content-list.members-list
+ = render partial: 'shared/members/member',
+ collection: requesters, as: :member,
+ locals: { membership_source: membership_source,
group: group,
current_user_is_group_owner: current_user_is_group_owner }
diff --git a/app/views/shared/milestones/_form_dates.html.haml b/app/views/shared/milestones/_form_dates.html.haml
index 7a41e381a96..50e3e8e195c 100644
--- a/app/views/shared/milestones/_form_dates.html.haml
+++ b/app/views/shared/milestones/_form_dates.html.haml
@@ -2,10 +2,10 @@
.col-form-label.col-sm-2
= f.label :start_date, _('Start Date')
.col-sm-4
- = f.text_field :start_date, class: "datepicker form-control gl-form-input", data: { qa_selector: "start_date_field" }, placeholder: _('Select start date'), autocomplete: 'off'
+ = f.gitlab_ui_datepicker :start_date, data: { qa_selector: "start_date_field" }, placeholder: _('Select start date'), autocomplete: 'off'
%a.inline.float-right.gl-mt-2.js-clear-start-date{ href: "#" }= _('Clear start date')
.col-form-label.col-sm-2
= f.label :due_date, _('Due Date')
.col-sm-4
- = f.text_field :due_date, class: "datepicker form-control gl-form-input", data: { qa_selector: "due_date_field" }, placeholder: _('Select due date'), autocomplete: 'off'
+ = f.gitlab_ui_datepicker :due_date, data: { qa_selector: "due_date_field" }, placeholder: _('Select due date'), autocomplete: 'off'
%a.inline.float-right.gl-mt-2.js-clear-due-date{ href: "#" }= _('Clear due date')
diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml
index 18db556e024..334785685d5 100644
--- a/app/views/shared/milestones/_header.html.haml
+++ b/app/views/shared/milestones/_header.html.haml
@@ -20,10 +20,10 @@
#promote-milestone-modal
- if milestone.active?
- = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), button_options: { class: 'btn-grouped btn-close', data: { method: 'put' }, rel: 'nofollow' }) do
+ = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), method: :put, button_options: { class: 'btn-grouped btn-close' }) do
= _('Close milestone')
- else
- = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), button_options: { class: 'btn-grouped', data: { method: 'put' }, rel: 'nofollow' }) do
+ = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), method: :put, button_options: { class: 'btn-grouped' }) do
= _('Reopen milestone')
= render 'shared/milestones/delete_button'
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index c845d4df7df..44740db5a00 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -11,7 +11,7 @@
- if supports_file_upload
%span.uploading-container
%span.uploading-progress-container.hide
- = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
+ = sprite_icon('paperclip', css_class: 'gl-icon gl-vertical-align-text-bottom')
%span.attaching-file-message
-# Populated by app/assets/javascripts/dropzone_input.js
%span.uploading-progress 0%
@@ -19,7 +19,7 @@
%span.uploading-error-container.hide
%span.uploading-error-icon
- = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
+ = sprite_icon('paperclip', css_class: 'gl-icon gl-vertical-align-text-bottom')
%span.uploading-error-message
-# Populated by app/assets/javascripts/dropzone_input.js
%button.btn.gl-button.btn-link.gl-vertical-align-baseline.retry-uploading-link
@@ -31,11 +31,6 @@
= _("attach a new file")
= _(".")
- %button.btn.gl-button.btn-link.button-attach-file.markdown-selector.button-attach-file.gl-vertical-align-text-bottom
- = sprite_icon('media')
- %span.gl-button-text
- = _("Attach a file")
-
%button.btn.gl-button.btn-link.button-cancel-uploading-files.gl-vertical-align-baseline.hide
%span.gl-button-text
= _("Cancel")
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index e96a9152c80..51a5c9dd38f 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -1,7 +1,7 @@
- form_field_classes = local_assigns[:admin_view] || !Feature.enabled?(:project_list_filter_bar) ? 'input-short js-projects-list-filter' : ''
- placeholder = local_assigns[:search_form_placeholder] ? search_form_placeholder : 'Filter by name...'
-= form_tag filter_projects_path, method: :get, class: 'project-filter-form qa-project-filter-form', id: 'project-filter-form' do |f|
+= form_tag filter_projects_path, method: :get, class: 'project-filter-form', data: { qa_selector: 'project_filter_form_container' }, id: 'project-filter-form' do |f|
= search_field_tag :name, params[:name],
placeholder: placeholder,
class: "project-filter-form-field form-control #{form_field_classes}",
diff --git a/app/views/shared/projects/_topics.html.haml b/app/views/shared/projects/_topics.html.haml
index e3895663033..be513af4e3f 100644
--- a/app/views/shared/projects/_topics.html.haml
+++ b/app/views/shared/projects/_topics.html.haml
@@ -3,16 +3,16 @@
- if project.topics.present?
= cache_if(cache_enabled, [project, :topic_list], expires_in: 1.day) do
- %span.gl-w-full.gl-display-inline-flex.gl-font-base.gl-font-weight-normal.gl-align-items-center{ 'data-testid': 'project_topic_list' }
- = sprite_icon('tag', css_class: 'icon gl-relative gl-mr-2')
-
+ .gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-weight-normal.gl-align-items-center.gl-mx-n2.gl-my-n2{ 'data-testid': 'project_topic_list' }
+ %span.gl-p-2.gl-text-gray-500
+ = _('Topics') + ':'
- project.topics_to_show.each do |topic|
- explore_project_topic_path = topic_explore_projects_path(topic_name: topic[:name])
- if topic[:title].length > max_project_topic_length
- %a.gl-mr-3.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
+ %a.gl-p-2.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
= gl_badge_tag truncate(topic[:title], length: max_project_topic_length)
- else
- %a.gl-mr-3{ href: explore_project_topic_path, itemprop: 'keywords' }
+ %a.gl-p-2{ href: explore_project_topic_path, itemprop: 'keywords' }
= gl_badge_tag topic[:title]
- if project.has_extra_topics?
@@ -27,5 +27,5 @@
- else
%a.gl-mr-3.gl-mb-3{ href: explore_project_topic_path, itemprop: 'keywords' }
= gl_badge_tag topic[:title]
- .text-nowrap{ role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
+ .text-nowrap.gl-p-2{ role: 'button', tabindex: 0, data: { toggle: 'popover', triggers: 'focus hover', html: 'true', placement: 'top', title: title, content: content } }
= _("+ %{count} more") % { count: project.count_of_extra_topics_not_shown }
diff --git a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
index 32b9044c551..d10196a83cc 100644
--- a/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
+++ b/app/views/shared/projects/protected_branches/_update_protected_branch.html.haml
@@ -10,7 +10,7 @@
%td.merge_access_levels-container
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", merge_access_levels.first&.access_level
= dropdown_tag( (merge_access_levels.first&.humanize || 'Select') ,
- options: { toggle_class: 'js-allowed-to-merge qa-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
+ options: { toggle_class: 'js-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", preselected_items: access_levels_data(merge_access_levels) }})
- if user_merge_access_levels.any?
%p.small
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 361beda4d02..25070138128 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -4,6 +4,7 @@
- page_title user_display_name(@user)
- page_description @user.bio unless @user.blocked? || !@user.confirmed?
- page_itemtype 'http://schema.org/Person'
+- add_page_specific_style 'page_bundles/profile'
- link_classes = "flex-grow-1 mx-1 "
= content_for :meta_tags do
@@ -42,16 +43,18 @@
= sprite_icon('user')
- if current_user && current_user.id != @user.id
- if current_user.following?(@user)
- = link_to user_unfollow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
- = _('Unfollow')
+ = form_tag user_unfollow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
+ = render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-w-full', data: { track_action: 'click_button', track_label: 'unfollow_from_profile' } }) do
+ = _('Unfollow')
- else
- = link_to user_follow_path(@user, :json) , class: link_classes + 'btn gl-button btn-confirm', method: :post, data: { qa_selector: 'follow_user_link' } do
- = _('Follow')
+ = form_tag user_follow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, type: :submit, button_options: { class: 'gl-w-full', data: { qa_selector: 'follow_user_link', track_action: 'click_button', track_label: 'follow_from_profile' } }) do
+ = _('Follow')
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder
= link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer' do
- = image_tag avatar_icon_for_user(@user, 90, current_user: current_user), class: "avatar s90", alt: '', itemprop: 'image'
+ = render Pajamas::AvatarComponent.new(@user, alt: "", size: 96, avatar_options: { itemprop: "image" })
- if @user.blocked? || !@user.confirmed?
.user-info
@@ -65,14 +68,14 @@
- if @user.pronouns.present?
%span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle
= "(#{@user.pronouns})"
- - if @user&.status && user_status_set_to_busy?(@user.status)
+ - if @user.status&.busy?
%span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle= s_("UserProfile|(Busy)")
- if @user.pronunciation.present?
.gl-align-items-center
%p.gl-mb-4.gl-text-gray-500= s_("UserProfile|Pronounced as: %{pronunciation}") % { pronunciation: @user.pronunciation }
- - if show_status_emoji?(@user.status)
+ - if @user.status&.customized?
.cover-status.gl-display-inline-flex.gl-align-items-center
= emoji_icon(@user.status.emoji, class: 'gl-mr-2')
= markdown_field(@user.status, :message)
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 966a1202db2..8bba5e36b52 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1551,15 +1551,6 @@
:weight: 1
:idempotent: false
:tags: []
-- :name: pipeline_background:archive_trace
- :worker_name: ArchiveTraceWorker
- :feature_category: :continuous_integration
- :has_external_dependencies: false
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: false
- :tags: []
- :name: pipeline_background:ci_archive_trace
:worker_name: Ci::ArchiveTraceWorker
:feature_category: :continuous_integration
@@ -1650,6 +1641,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: pipeline_background:ci_track_failed_build
+ :worker_name: Ci::TrackFailedBuildWorker
+ :feature_category: :static_application_security_testing
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: pipeline_creation:ci_external_pull_requests_create_pipeline
:worker_name: Ci::ExternalPullRequests::CreatePipelineWorker
:feature_category: :continuous_integration
@@ -1776,15 +1776,6 @@
:weight: 2
:idempotent: false
:tags: []
-- :name: pipeline_processing:build_finished
- :worker_name: BuildFinishedWorker
- :feature_category: :continuous_integration
- :has_external_dependencies: false
- :urgency: :high
- :resource_boundary: :cpu
- :weight: 5
- :idempotent: false
- :tags: []
- :name: pipeline_processing:build_queue
:worker_name: BuildQueueWorker
:feature_category: :continuous_integration
@@ -2109,6 +2100,15 @@
:weight: 2
:idempotent: false
:tags: []
+- :name: ci_cancel_pipeline
+ :worker_name: Ci::CancelPipelineWorker
+ :feature_category: :continuous_integration
+ :has_external_dependencies: false
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: ci_delete_objects
:worker_name: Ci::DeleteObjectsWorker
:feature_category: :continuous_integration
@@ -2127,6 +2127,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: ci_runners_process_runner_version_update
+ :worker_name: Ci::Runners::ProcessRunnerVersionUpdateWorker
+ :feature_category: :runner_fleet
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: create_commit_signature
:worker_name: CreateCommitSignatureWorker
:feature_category: :source_code_management
@@ -2252,8 +2261,7 @@
:resource_boundary: :unknown
:weight: 2
:idempotent: false
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: emails_on_push
:worker_name: EmailsOnPushWorker
:feature_category: :source_code_management
@@ -2551,6 +2559,24 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: merge_requests_create_approval_event
+ :worker_name: MergeRequests::CreateApprovalEventWorker
+ :feature_category: :code_review
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: merge_requests_create_approval_note
+ :worker_name: MergeRequests::CreateApprovalNoteWorker
+ :feature_category: :code_review
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: merge_requests_delete_source_branch
:worker_name: MergeRequests::DeleteSourceBranchWorker
:feature_category: :source_code_management
@@ -2560,6 +2586,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: merge_requests_execute_approval_hooks
+ :worker_name: MergeRequests::ExecuteApprovalHooksWorker
+ :feature_category: :code_review
+ :has_external_dependencies: true
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: merge_requests_handle_assignees_change
:worker_name: MergeRequests::HandleAssigneesChangeWorker
:feature_category: :code_review
@@ -2578,6 +2613,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: merge_requests_resolve_todos_after_approval
+ :worker_name: MergeRequests::ResolveTodosAfterApprovalWorker
+ :feature_category: :code_review
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: merge_requests_update_head_pipeline
:worker_name: MergeRequests::UpdateHeadPipelineWorker
:feature_category: :code_review
@@ -2812,6 +2856,15 @@
:weight: 1
:idempotent: false
:tags: []
+- :name: projects_import_export_relation_export
+ :worker_name: Projects::ImportExport::RelationExportWorker
+ :feature_category: :importers
+ :has_external_dependencies: false
+ :urgency: :low
+ :resource_boundary: :memory
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: projects_inactive_projects_deletion_notification
:worker_name: Projects::InactiveProjectsDeletionNotificationWorker
:feature_category: :compliance_management
@@ -3018,8 +3071,7 @@
:resource_boundary: :unknown
:weight: 2
:idempotent: false
- :tags:
- - :needs_own_queue
+ :tags: []
- :name: snippets_schedule_bulk_repository_shard_moves
:worker_name: Snippets::ScheduleBulkRepositoryShardMovesWorker
:feature_category: :gitaly
diff --git a/app/workers/archive_trace_worker.rb b/app/workers/archive_trace_worker.rb
deleted file mode 100644
index ecde05f94dc..00000000000
--- a/app/workers/archive_trace_worker.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class ArchiveTraceWorker < ::Ci::ArchiveTraceWorker # rubocop:disable Scalability/IdempotentWorker
- # DEPRECATED: Not triggered since https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64934/
-end
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
deleted file mode 100644
index 0d41f7b9438..00000000000
--- a/app/workers/build_finished_worker.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class BuildFinishedWorker < ::Ci::BuildFinishedWorker # rubocop:disable Scalability/IdempotentWorker
- # DEPRECATED: Not triggered since https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64934/
-
- # We need to explicitly specify these settings. They aren't inheriting from the parent class.
- urgency :high
- worker_resource_boundary :cpu
-end
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index 5c08344bfe3..2c62aed72d6 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -13,9 +13,9 @@ class BuildHooksWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
- Ci::Build.includes({ runner: :tags })
- .find_by_id(build_id)
- .try(:execute_hooks)
+ build = Ci::Build.find_by_id(build_id)
+
+ build.execute_hooks if build
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/ci/build_finished_worker.rb b/app/workers/ci/build_finished_worker.rb
index 25c7637a79f..36a50735fed 100644
--- a/app/workers/ci/build_finished_worker.rb
+++ b/app/workers/ci/build_finished_worker.rb
@@ -36,8 +36,7 @@ module Ci
build.update_coverage
Ci::BuildReportResultService.new.execute(build)
- # We execute these async as these are independent operations.
- BuildHooksWorker.perform_async(build)
+ build.feature_flagged_execute_hooks
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
build.track_deployment_usage
build.track_verify_usage
diff --git a/app/workers/ci/cancel_pipeline_worker.rb b/app/workers/ci/cancel_pipeline_worker.rb
new file mode 100644
index 00000000000..147839a0625
--- /dev/null
+++ b/app/workers/ci/cancel_pipeline_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Ci
+ class CancelPipelineWorker
+ include ApplicationWorker
+
+ # lots of updates to ci_builds
+ data_consistency :always
+ feature_category :continuous_integration
+ idempotent!
+ deduplicate :until_executed
+ urgency :high
+
+ def perform(pipeline_id, auto_canceled_by_pipeline_id)
+ ::Ci::Pipeline.find_by_id(pipeline_id).try do |pipeline|
+ pipeline.cancel_running(
+ # cascade_to_children is false because we iterate through children
+ # we also cancel bridges prior to prevent more children
+ cascade_to_children: false,
+ auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id
+ )
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/runners/process_runner_version_update_worker.rb b/app/workers/ci/runners/process_runner_version_update_worker.rb
new file mode 100644
index 00000000000..f1ad0c8563e
--- /dev/null
+++ b/app/workers/ci/runners/process_runner_version_update_worker.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Ci
+ module Runners
+ class ProcessRunnerVersionUpdateWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ feature_category :runner_fleet
+ urgency :low
+
+ idempotent!
+ deduplicate :until_executing
+
+ def perform(version)
+ result = ::Ci::Runners::ProcessRunnerVersionUpdateService.new(version).execute
+
+ result.to_h.slice(:status, :message, :upgrade_status).each do |key, value|
+ log_extra_metadata_on_done(key, value)
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb b/app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb
index 035b2563e56..69ab477c80a 100644
--- a/app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb
+++ b/app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb
@@ -12,11 +12,25 @@ module Ci
feature_category :runner_fleet
urgency :low
+ deduplicate :until_executed
idempotent!
- def perform
+ def perform(cronjob_scheduled = true)
+ if cronjob_scheduled
+ # Introduce some randomness across the day so that instances don't all hit the GitLab Releases API
+ # around the same time of day
+ period = rand(0..12.hours.in_seconds)
+ self.class.perform_in(period, false)
+
+ Sidekiq.logger.info(
+ class: self.class.name,
+ message: "rescheduled job for #{period.seconds.from_now}")
+
+ return
+ end
+
result = ::Ci::Runners::ReconcileExistingRunnerVersionsService.new.execute
- result.each { |key, value| log_extra_metadata_on_done(key, value) }
+ result.payload.each { |key, value| log_extra_metadata_on_done(key, value) }
end
end
end
diff --git a/app/workers/ci/track_failed_build_worker.rb b/app/workers/ci/track_failed_build_worker.rb
new file mode 100644
index 00000000000..2ad948876ac
--- /dev/null
+++ b/app/workers/ci/track_failed_build_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# Worker for tracking exit codes of failed CI jobs
+module Ci
+ class TrackFailedBuildWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+ include PipelineBackgroundQueue
+
+ feature_category :static_application_security_testing
+
+ urgency :low
+ data_consistency :sticky
+ worker_resource_boundary :cpu
+ idempotent!
+ worker_has_external_dependencies!
+
+ def perform(build_id, exit_code, failure_reason)
+ ::Ci::Build.find_by_id(build_id).try do |build|
+ ::Ci::TrackFailedBuildService.new(
+ build: build,
+ exit_code: exit_code,
+ failure_reason: failure_reason).execute
+ end
+ end
+ end
+end
diff --git a/app/workers/concerns/waitable_worker.rb b/app/workers/concerns/waitable_worker.rb
index 336d60d46ac..9300c2a5790 100644
--- a/app/workers/concerns/waitable_worker.rb
+++ b/app/workers/concerns/waitable_worker.rb
@@ -7,7 +7,7 @@ module WaitableWorker
# Schedules multiple jobs and waits for them to be completed.
def bulk_perform_and_wait(args_list)
# Short-circuit: it's more efficient to do small numbers of jobs inline
- if args_list.size == 1
+ if args_list.size == 1 && !always_async_project_authorizations_refresh?
return bulk_perform_inline(args_list)
end
@@ -29,6 +29,10 @@ module WaitableWorker
bulk_perform_async(failed) if failed.present?
end
+
+ def always_async_project_authorizations_refresh?
+ Feature.enabled?(:always_async_project_authorizations_refresh)
+ end
end
def perform(*args)
diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb
index 54689df4d7b..339383476be 100644
--- a/app/workers/email_receiver_worker.rb
+++ b/app/workers/email_receiver_worker.rb
@@ -11,9 +11,6 @@ class EmailReceiverWorker # rubocop:disable Scalability/IdempotentWorker
urgency :high
weight 2
- # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1263
- tags :needs_own_queue
-
attr_accessor :raw
def perform(raw)
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index d7bd8207f06..5cc9bb6954e 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -17,8 +17,8 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker
def perform(project_id, recipients, push_data, options = {})
options.symbolize_keys!
options.reverse_merge!(
- send_from_committer_email: false,
- disable_diffs: false
+ send_from_committer_email: false,
+ disable_diffs: false
)
send_from_committer_email = options[:send_from_committer_email]
disable_diffs = options[:disable_diffs]
@@ -64,14 +64,14 @@ class EmailsOnPushWorker # rubocop:disable Scalability/IdempotentWorker
send_email(
recipient,
project_id,
- author_id: author_id,
- ref: ref,
- action: action,
- compare: compare,
- reverse_compare: reverse_compare,
- diff_refs: diff_refs,
+ author_id: author_id,
+ ref: ref,
+ action: action,
+ compare: compare,
+ reverse_compare: reverse_compare,
+ diff_refs: diff_refs,
send_from_committer_email: send_from_committer_email,
- disable_diffs: disable_diffs
+ disable_diffs: disable_diffs
)
# These are input errors and won't be corrected even if Sidekiq retries
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 8155b910677..0ec0a1b58d2 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,32 +15,34 @@ module Gitlab
# client - An instance of Gitlab::GithubImport::Client.
# project - An instance of Project.
def import(client, project)
- importer = ::Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
- return skip_to_next_stage(project, importer) if feature_disabled?(project)
+ importer = importer_class(project)
+ return skip_to_next_stage(project) if importer.nil?
- start_importer(project, importer, client)
+ 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 })
end
private
- def start_importer(project, importer, client)
- 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)
+ 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, importer)
- info(project.id, message: "skipping importer", importer: importer.name)
+ def skip_to_next_stage(project)
+ info(project.id, message: "skipping importer", importer: "IssueEventsImporter")
move_to_next_stage(project)
end
def move_to_next_stage(project, waiters = {})
AdvanceStageWorker.perform_async(project.id, waiters, :notes)
end
-
- def feature_disabled?(project)
- Feature.disabled?(:github_importer_issue_events_import, project.group, type: :ops)
- end
end
end
end
diff --git a/app/workers/merge_requests/create_approval_event_worker.rb b/app/workers/merge_requests/create_approval_event_worker.rb
new file mode 100644
index 00000000000..9b1a3c262e4
--- /dev/null
+++ b/app/workers/merge_requests/create_approval_event_worker.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CreateApprovalEventWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :always
+ feature_category :code_review
+ urgency :low
+ idempotent!
+
+ def handle_event(event)
+ current_user_id = event.data[:current_user_id]
+ merge_request_id = event.data[:merge_request_id]
+ current_user = User.find_by_id(current_user_id)
+
+ unless current_user
+ logger.info(structured_payload(message: 'Current user not found.', current_user_id: current_user_id))
+ return
+ end
+
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ unless merge_request
+ logger.info(structured_payload(message: 'Merge request not found.', merge_request_id: merge_request_id))
+ return
+ end
+
+ ::MergeRequests::CreateApprovalEventService
+ .new(project: merge_request.project, current_user: current_user)
+ .execute(merge_request)
+ end
+ end
+end
diff --git a/app/workers/merge_requests/create_approval_note_worker.rb b/app/workers/merge_requests/create_approval_note_worker.rb
new file mode 100644
index 00000000000..841431f6a9d
--- /dev/null
+++ b/app/workers/merge_requests/create_approval_note_worker.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CreateApprovalNoteWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :always
+ feature_category :code_review
+ urgency :low
+ idempotent!
+
+ def handle_event(event)
+ current_user_id = event.data[:current_user_id]
+ merge_request_id = event.data[:merge_request_id]
+ current_user = User.find_by_id(current_user_id)
+
+ unless current_user
+ logger.info(structured_payload(message: 'Current user not found.', current_user_id: current_user_id))
+ return
+ end
+
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ unless merge_request
+ logger.info(structured_payload(message: 'Merge request not found.', merge_request_id: merge_request_id))
+ return
+ end
+
+ SystemNoteService.approve_mr(merge_request, current_user)
+ end
+ end
+end
diff --git a/app/workers/merge_requests/execute_approval_hooks_worker.rb b/app/workers/merge_requests/execute_approval_hooks_worker.rb
new file mode 100644
index 00000000000..81eca425a38
--- /dev/null
+++ b/app/workers/merge_requests/execute_approval_hooks_worker.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ExecuteApprovalHooksWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :always
+ feature_category :code_review
+ urgency :low
+ idempotent!
+
+ # MergeRequests::ExecuteApprovalHooksService execute webhooks which are treated as external dependencies
+ worker_has_external_dependencies!
+
+ def handle_event(event)
+ current_user_id = event.data[:current_user_id]
+ merge_request_id = event.data[:merge_request_id]
+ current_user = User.find_by_id(current_user_id)
+
+ unless current_user
+ logger.info(structured_payload(message: 'Current user not found.', current_user_id: current_user_id))
+ return
+ end
+
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ unless merge_request
+ logger.info(structured_payload(message: 'Merge request not found.', merge_request_id: merge_request_id))
+ return
+ end
+
+ ::MergeRequests::ExecuteApprovalHooksService
+ .new(project: merge_request.project, current_user: current_user)
+ .execute(merge_request)
+ end
+ end
+end
diff --git a/app/workers/merge_requests/resolve_todos_after_approval_worker.rb b/app/workers/merge_requests/resolve_todos_after_approval_worker.rb
new file mode 100644
index 00000000000..7d9c76ea872
--- /dev/null
+++ b/app/workers/merge_requests/resolve_todos_after_approval_worker.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class ResolveTodosAfterApprovalWorker
+ include Gitlab::EventStore::Subscriber
+
+ data_consistency :always
+ feature_category :code_review
+ urgency :low
+ idempotent!
+
+ def handle_event(event)
+ current_user_id = event.data[:current_user_id]
+ merge_request_id = event.data[:merge_request_id]
+ current_user = User.find_by_id(current_user_id)
+
+ unless current_user
+ logger.info(structured_payload(message: 'Current user not found.', current_user_id: current_user_id))
+ return
+ end
+
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ unless merge_request
+ logger.info(structured_payload(message: 'Merge request not found.', merge_request_id: merge_request_id))
+ return
+ end
+
+ TodoService.new.resolve_todos_for_target(merge_request, current_user)
+ end
+ end
+end
diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb
index 13936fac1e4..e14f0dc7dfe 100644
--- a/app/workers/new_issue_worker.rb
+++ b/app/workers/new_issue_worker.rb
@@ -13,7 +13,11 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
worker_resource_boundary :cpu
weight 2
- def perform(issue_id, user_id)
+ attr_reader :issuable_class
+
+ def perform(issue_id, user_id, issuable_class = 'Issue')
+ @issuable_class = issuable_class.constantize
+
return unless objects_found?(issue_id, user_id)
::EventCreateService.new.open_issue(issuable, user)
@@ -25,8 +29,4 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
.new(project: issuable.project, current_user: user)
.execute(issuable)
end
-
- def issuable_class
- Issue
- end
end
diff --git a/app/workers/pages/invalidate_domain_cache_worker.rb b/app/workers/pages/invalidate_domain_cache_worker.rb
index 63b6f5c05b5..97e8966b342 100644
--- a/app/workers/pages/invalidate_domain_cache_worker.rb
+++ b/app/workers/pages/invalidate_domain_cache_worker.rb
@@ -15,9 +15,13 @@ module Pages
.clear_cache
end
- if event.data[:root_namespace_id]
+ event.data.values_at(
+ :root_namespace_id,
+ :old_root_namespace_id,
+ :new_root_namespace_id
+ ).compact.uniq.each do |namespace_id|
::Gitlab::Pages::CacheControl
- .for_namespace(event.data[:root_namespace_id])
+ .for_namespace(namespace_id)
.clear_cache
end
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 68a0934e2b7..329ccfc6362 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -85,6 +85,7 @@ class PostReceive
replicate_snippet_changes(snippet)
expire_caches(post_received, snippet.repository)
+ snippet.touch
Snippets::UpdateStatisticsService.new(snippet).execute
end
diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb
index 0e90b41e28d..cb1a7c8560a 100644
--- a/app/workers/project_cache_worker.rb
+++ b/app/workers/project_cache_worker.rb
@@ -47,7 +47,8 @@ class ProjectCacheWorker
Projects::UpdateStatisticsService.new(project, nil, statistics: statistics).execute
- UpdateProjectStatisticsWorker.perform_in(LEASE_TIMEOUT, project.id, statistics)
+ lease_key = project_cache_worker_key(project.id, statistics)
+ UpdateProjectStatisticsWorker.perform_in(LEASE_TIMEOUT, lease_key, project.id, statistics)
end
private
diff --git a/app/workers/projects/import_export/relation_export_worker.rb b/app/workers/projects/import_export/relation_export_worker.rb
new file mode 100644
index 00000000000..13ca33c4457
--- /dev/null
+++ b/app/workers/projects/import_export/relation_export_worker.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Projects
+ module ImportExport
+ class RelationExportWorker
+ include ApplicationWorker
+ include ExceptionBacktrace
+
+ idempotent!
+ data_consistency :always
+ deduplicate :until_executed
+ feature_category :importers
+ sidekiq_options status_expiration: StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION
+ urgency :low
+ worker_resource_boundary :memory
+
+ def perform(project_relation_export_id)
+ relation_export = Projects::ImportExport::RelationExport.find(project_relation_export_id)
+
+ if relation_export.queued?
+ Projects::ImportExport::RelationExportService.new(relation_export, jid).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/service_desk_email_receiver_worker.rb b/app/workers/service_desk_email_receiver_worker.rb
index c8ab8891856..b3b36ca2ada 100644
--- a/app/workers/service_desk_email_receiver_worker.rb
+++ b/app/workers/service_desk_email_receiver_worker.rb
@@ -9,9 +9,6 @@ class ServiceDeskEmailReceiverWorker < EmailReceiverWorker # rubocop:disable Sca
urgency :high
sidekiq_options retry: 3
- # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1263
- tags :needs_own_queue
-
def should_perform?
::Gitlab::ServiceDeskEmail.enabled?
end
diff --git a/app/workers/update_project_statistics_worker.rb b/app/workers/update_project_statistics_worker.rb
index 45a6cc8f476..3308fa149f5 100644
--- a/app/workers/update_project_statistics_worker.rb
+++ b/app/workers/update_project_statistics_worker.rb
@@ -10,10 +10,15 @@ class UpdateProjectStatisticsWorker # rubocop:disable Scalability/IdempotentWork
feature_category :source_code_management
- # project_id - The ID of the project for which to flush the cache.
- # statistics - An Array containing columns from ProjectStatistics to
- # refresh, if empty all columns will be refreshed
- def perform(project_id, statistics = [])
+ # lease_key - The exclusive lease key to take
+ # project_id - The ID of the project for which to flush the cache.
+ # statistics - An Array containing columns from ProjectStatistics to
+ # refresh, if empty all columns will be refreshed
+ def perform(lease_key, project_id, statistics = [])
+ return unless Gitlab::ExclusiveLease
+ .new(lease_key, timeout: ProjectCacheWorker::LEASE_TIMEOUT)
+ .try_obtain
+
project = Project.find_by_id(project_id)
Projects::UpdateStatisticsService.new(project, nil, statistics: statistics).execute
diff --git a/app/workers/users/deactivate_dormant_users_worker.rb b/app/workers/users/deactivate_dormant_users_worker.rb
index d7ea20e4b62..b14b7e67450 100644
--- a/app/workers/users/deactivate_dormant_users_worker.rb
+++ b/app/workers/users/deactivate_dormant_users_worker.rb
@@ -10,43 +10,23 @@ module Users
feature_category :utilization
- NUMBER_OF_BATCHES = 50
- BATCH_SIZE = 200
- PAUSE_SECONDS = 0.25
-
def perform
return if Gitlab.com?
return unless ::Gitlab::CurrentSettings.current_application_settings.deactivate_dormant_users
- with_context(caller_id: self.class.name.to_s) do
- NUMBER_OF_BATCHES.times do
- result = User.connection.execute(update_query)
-
- break if result.cmd_tuples == 0
-
- sleep(PAUSE_SECONDS)
- end
- end
+ deactivate_users(User.dormant)
+ deactivate_users(User.with_no_activity)
end
private
- def update_query
- <<~SQL
- UPDATE "users"
- SET "state" = 'deactivated'
- WHERE "users"."id" IN (
- (#{users.dormant.to_sql})
- UNION
- (#{users.with_no_activity.to_sql})
- LIMIT #{BATCH_SIZE}
- )
- SQL
- end
-
- def users
- User.select(:id).limit(BATCH_SIZE)
+ def deactivate_users(scope)
+ with_context(caller_id: self.class.name.to_s) do
+ scope.each_batch do |batch|
+ batch.each(&:deactivate)
+ end
+ end
end
end
end
diff --git a/app/workers/x509_issuer_crl_check_worker.rb b/app/workers/x509_issuer_crl_check_worker.rb
index 39440504927..cb5bae7ca4e 100644
--- a/app/workers/x509_issuer_crl_check_worker.rb
+++ b/app/workers/x509_issuer_crl_check_worker.rb
@@ -41,13 +41,13 @@ class X509IssuerCrlCheckWorker
certs.find_each do |cert|
logger.info(message: "Certificate revoked",
- id: cert.id,
- email: cert.email,
- subject: cert.subject,
- serial_number: cert.serial_number,
- issuer: cert.x509_issuer.id,
- issuer_subject: cert.x509_issuer.subject,
- issuer_crl_url: cert.x509_issuer.crl_url)
+ id: cert.id,
+ email: cert.email,
+ subject: cert.subject,
+ serial_number: cert.serial_number,
+ issuer: cert.x509_issuer.id,
+ issuer_subject: cert.x509_issuer.subject,
+ issuer_crl_url: cert.x509_issuer.crl_url)
end
certs.update_all(certificate_status: :revoked)
@@ -61,18 +61,18 @@ class X509IssuerCrlCheckWorker
OpenSSL::X509::CRL.new(response.body)
else
logger.warn(message: "Failed to download certificate revocation list",
- issuer: issuer.id,
- issuer_subject: issuer.subject,
- issuer_crl_url: issuer.crl_url)
+ issuer: issuer.id,
+ issuer_subject: issuer.subject,
+ issuer_crl_url: issuer.crl_url)
nil
end
rescue OpenSSL::X509::CRLError
logger.warn(message: "Failed to parse certificate revocation list",
- issuer: issuer.id,
- issuer_subject: issuer.subject,
- issuer_crl_url: issuer.crl_url)
+ issuer: issuer.id,
+ issuer_subject: issuer.subject,
+ issuer_crl_url: issuer.crl_url)
nil
end
diff --git a/config/application.rb b/config/application.rb
index b758f2df857..d28967f2966 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -18,8 +18,6 @@ module Gitlab
class Application < Rails::Application
config.load_defaults 6.1
- config.view_component.preview_route = "/-/view_component/previews"
-
config.active_support.hash_digest_class = ::OpenSSL::Digest::SHA256
# This section contains configuration from Rails upgrades to override the new defaults so that we
@@ -292,11 +290,13 @@ module Gitlab
config.assets.precompile << "page_bundles/pipelines.css"
config.assets.precompile << "page_bundles/pipeline_editor.css"
config.assets.precompile << "page_bundles/productivity_analytics.css"
+ config.assets.precompile << "page_bundles/profile.css"
config.assets.precompile << "page_bundles/profile_two_factor_auth.css"
config.assets.precompile << "page_bundles/project.css"
config.assets.precompile << "page_bundles/projects_edit.css"
config.assets.precompile << "page_bundles/reports.css"
config.assets.precompile << "page_bundles/roadmap.css"
+ config.assets.precompile << "page_bundles/runner_details.css"
config.assets.precompile << "page_bundles/security_dashboard.css"
config.assets.precompile << "page_bundles/security_discover.css"
config.assets.precompile << "page_bundles/signup.css"
@@ -330,6 +330,7 @@ module Gitlab
config.assets.precompile << "icons.svg"
config.assets.precompile << "icons.json"
config.assets.precompile << "illustrations/*.svg"
+ config.assets.precompile << "illustrations/*.png"
# Import css for xterm
config.assets.paths << "#{config.root}/node_modules/xterm/src/"
@@ -532,6 +533,23 @@ module Gitlab
# DO NOT PLACE ANY INITIALIZERS AFTER THIS.
config.after_initialize do
+ config.active_record.yaml_column_permitted_classes = [
+ Symbol, Date, Time,
+ BigDecimal, # https://gitlab.com/gitlab-org/gitlab/issues/368846
+ Gitlab::Diff::Position,
+ # Used in:
+ # app/models/concerns/diff_positionable_note.rb
+ # app/models/legacy_diff_note.rb: serialize :st_diff
+ ActiveSupport::HashWithIndifferentAccess,
+ # Used in ee/lib/ee/api/helpers.rb: send_git_archive
+ DeployToken,
+ ActiveModel::Attribute.const_get(:FromDatabase, false), # https://gitlab.com/gitlab-org/gitlab/-/issues/368072
+ # Used in app/services/web_hooks/log_execution_service.rb: log_execution
+ ActiveSupport::TimeWithZone,
+ ActiveSupport::TimeZone,
+ Gitlab::Color # https://gitlab.com/gitlab-org/gitlab/-/issues/368844
+ ]
+
# on_master_start yields immediately in unclustered environments and runs
# when the primary process is done initializing otherwise.
Gitlab::Cluster::LifecycleEvents.on_master_start do
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 5b72c6b35f8..d475a2a6642 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -25,6 +25,9 @@ Rails.application.configure do
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
+ # Raise exceptions for disallowed deprecations.
+ config.active_support.disallowed_deprecation = :raise
+
# Raise an error on page load if there are pending migrations
config.active_record.migration_error = :page_load
@@ -40,6 +43,13 @@ Rails.application.configure do
# Annotate rendered view with template file names as HTML comments
config.action_view.annotate_rendered_view_with_filenames = true
+ # ViewComponent previews
+ config.view_component.default_preview_layout = "component_preview"
+ config.view_component.preview_route = "/-/view_component/previews"
+ config.view_component.preview_paths << "#{config.root}/spec/components/previews"
+ # Push preview path now to prevent FrozenError during view_component's initialzer
+ config.autoload_paths.push("#{config.root}/spec/components/previews")
+
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
diff --git a/config/environments/production.rb b/config/environments/production.rb
index b56aadb8b11..202f6205c7f 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -65,8 +65,17 @@ Rails.application.configure do
# Enable threaded mode
# config.threadsafe! unless $rails_rake_task
- # Send deprecation notices to registered listeners
- config.active_support.deprecation = :notify
+ # Silence deprecation notices on production.
+ # See also config/initializers/00_deprecations.rb.
+ #
+ # Logging to `log/deprecation_json.log` can be enabled with
+ # `GITLAB_LOG_DEPRECATIONS=1`.
+ #
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/368379
+ config.active_support.deprecation = :silence
+
+ # Silence disallowed deprecations.
+ config.active_support.disallowed_deprecation = :silence
config.action_mailer.delivery_method = :sendmail
# Defaults to:
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 2935e0c7636..f4d3d2ddfda 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -21,6 +21,8 @@ Rails.application.configure do
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = Gitlab::Utils.to_boolean(ENV['CACHE_CLASSES'], default: false)
+ config.view_component.preview_route = "/-/view_component/previews"
+
# Configure static asset server for tests with Cache-Control for performance
config.assets.compile = false if ENV['CI']
# There is no need to check if assets are precompiled locally
@@ -49,6 +51,9 @@ Rails.application.configure do
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
+ # Raise exceptions for disallowed deprecations.
+ config.active_support.disallowed_deprecation = :raise
+
config.eager_load = Gitlab::Utils.to_boolean(ENV['GITLAB_TEST_EAGER_LOAD'], default: ENV['CI'].present?)
config.cache_store = :null_store
diff --git a/config/events/1656554755_issues_edit_g_project_management_issue_added_to_epic.yml b/config/events/1656554755_issues_edit_g_project_management_issue_added_to_epic.yml
deleted file mode 100644
index 0c1ea4584e1..00000000000
--- a/config/events/1656554755_issues_edit_g_project_management_issue_added_to_epic.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: Issue was added to an epic
-category: issues_edit
-action: g_project_management_issue_added_to_epic
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1656555050_issues_edit_g_project_management_issue_changed_epic.yml b/config/events/1656555050_issues_edit_g_project_management_issue_changed_epic.yml
deleted file mode 100644
index b74054b4eb5..00000000000
--- a/config/events/1656555050_issues_edit_g_project_management_issue_changed_epic.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: Epic was changed on an issue
-category: issues_edit
-action: g_project_management_issue_changed_epic
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1656555163_issues_edit_g_project_management_issue_health_status_changed.yml b/config/events/1656555163_issues_edit_g_project_management_issue_health_status_changed.yml
deleted file mode 100644
index 00a375074f6..00000000000
--- a/config/events/1656555163_issues_edit_g_project_management_issue_health_status_changed.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: Health status was changed on an issue
-category: issues_edit
-action: g_project_management_issue_health_status_changed
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1656555272_issues_edit_g_project_management_issue_iteration_changed.yml b/config/events/1656555272_issues_edit_g_project_management_issue_iteration_changed.yml
deleted file mode 100644
index 7e755c6e0e9..00000000000
--- a/config/events/1656555272_issues_edit_g_project_management_issue_iteration_changed.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: Issue's iteration was changed
-category: issues_edit
-action: g_project_management_issue_iteration_changed
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1656555342_issues_edit_g_project_management_issue_removed_from_epic.yml b/config/events/1656555342_issues_edit_g_project_management_issue_removed_from_epic.yml
deleted file mode 100644
index 5241e48ee9f..00000000000
--- a/config/events/1656555342_issues_edit_g_project_management_issue_removed_from_epic.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: An issue was removed from an epic
-category: issues_edit
-action: g_project_management_issue_removed_from_epic
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1656555426_issues_edit_g_project_management_issue_weight_changed.yml b/config/events/1656555426_issues_edit_g_project_management_issue_weight_changed.yml
deleted file mode 100644
index 99492d50176..00000000000
--- a/config/events/1656555426_issues_edit_g_project_management_issue_weight_changed.yml
+++ /dev/null
@@ -1,20 +0,0 @@
----
-description: Issue's weight was changed
-category: issues_edit
-action: g_project_management_issue_weight_changed
-identifiers:
- - project
- - user
- - namespace
-product_section: dev
-product_stage: plan
-product_group: project_management
-product_category: issue_tracking
-milestone: "15.2"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91443
-distributions:
- - ee
-tiers:
- - premium
- - ultimate
-
diff --git a/config/events/1658833247_integrations_class_perform_integrations_action.yml b/config/events/1658833247_integrations_class_perform_integrations_action.yml
new file mode 100644
index 00000000000..62da809fe14
--- /dev/null
+++ b/config/events/1658833247_integrations_class_perform_integrations_action.yml
@@ -0,0 +1,23 @@
+---
+description: Integration usage event
+category: integrations class
+action: perform_integrations_action
+property_description: the name of the performed action
+identifiers:
+- project
+- user
+- namespace
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93468
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/events/1659067369_issue_actions_perform_issue_acitons_.yml b/config/events/1659067369_issue_actions_perform_issue_acitons_.yml
new file mode 100644
index 00000000000..77fabfa2d6a
--- /dev/null
+++ b/config/events/1659067369_issue_actions_perform_issue_acitons_.yml
@@ -0,0 +1,25 @@
+---
+description: Issue usage event
+category: issues_edit
+action: perform_issue_action
+label_description:
+property_description: the name of the performed action
+value_description:
+extra_properties:
+identifiers:
+ - namespace
+ - project
+ - user
+product_section: dev
+product_stage: plan
+product_group: project_management
+product_category: issue_tracking
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91659
+distributions:
+ - ce
+ - ee
+tiers:
+ - free
+ - premium
+ - ultimate
diff --git a/config/events/1659626567_analytics_usage_action_perform_analytics_usage_action.yml b/config/events/1659626567_analytics_usage_action_perform_analytics_usage_action.yml
new file mode 100644
index 00000000000..ff1fb8e9408
--- /dev/null
+++ b/config/events/1659626567_analytics_usage_action_perform_analytics_usage_action.yml
@@ -0,0 +1,25 @@
+---
+description: Analytics usage event
+category: class of the controller triggering given event
+action: perform_analytics_usage_action
+label_description: key_path of corresponding redis hll total metric
+property_description: the name of the performed action, corresponding to migrated redis hll event name
+value_description:
+extra_properties:
+identifiers:
+- user
+- namespace
+product_section: dev
+product_stage: manage
+product_group: optimize
+product_category:
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94369
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
+
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index d52f621e436..9b5f3de3f75 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -8,13 +8,16 @@
#
---
- advanced_deployments
+- advisory_database
- api_security
+- application_performance
- attack_emulation
- audit_events
- audit_reports
- authentication_and_authorization
- auto_devops
- backup_restore
+- billing_and_subscription_management
- build
- build_artifacts
- chatops
@@ -65,6 +68,7 @@
- importers
- incident_management
- infrastructure_as_code
+- infrastructure_cost_data
- insider_threat
- instance_resiliency
- integrations
@@ -75,7 +79,6 @@
- kubernetes_management
- license_compliance
- logging
-- memory
- merge_trains
- metrics
- mlops
@@ -96,6 +99,7 @@
- product_analytics
- projects
- provision
+- pubsec_services
- purchase
- quality_management
- redis
@@ -118,7 +122,6 @@
- snippets
- source_code_management
- static_application_security_testing
-- static_site_editor
- subgroups
- system_access
- team_planning
@@ -127,7 +130,6 @@
- users
- utilization
- value_stream_management
-- vulnerability_database
- vulnerability_management
- web_ide
- wiki
diff --git a/config/feature_flags/development/always_async_project_authorizations_refresh.yml b/config/feature_flags/development/always_async_project_authorizations_refresh.yml
new file mode 100644
index 00000000000..233be4d930e
--- /dev/null
+++ b/config/feature_flags/development/always_async_project_authorizations_refresh.yml
@@ -0,0 +1,8 @@
+---
+name: always_async_project_authorizations_refresh
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92333
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367683
+milestone: '15.3'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/approval_rules_pagination.yml b/config/feature_flags/development/approval_rules_pagination.yml
index 494109e3f5a..78d4ad37ced 100644
--- a/config/feature_flags/development/approval_rules_pagination.yml
+++ b/config/feature_flags/development/approval_rules_pagination.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366823
milestone: '15.2'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/archive_rate_limit.yml b/config/feature_flags/development/archive_rate_limit.yml
index 3318d7fa939..e5840c1dab3 100644
--- a/config/feature_flags/development/archive_rate_limit.yml
+++ b/config/feature_flags/development/archive_rate_limit.yml
@@ -1,7 +1,7 @@
---
name: archive_rate_limit
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25750
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369432
milestone: '12.9'
type: development
group: group::source code
diff --git a/config/feature_flags/development/async_after_approval.yml b/config/feature_flags/development/async_after_approval.yml
new file mode 100644
index 00000000000..db53454b88f
--- /dev/null
+++ b/config/feature_flags/development/async_after_approval.yml
@@ -0,0 +1,8 @@
+---
+name: async_after_approval
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92520
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368098
+milestone: '15.3'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/async_commit_diff_files.yml b/config/feature_flags/development/async_commit_diff_files.yml
index a4519835fa1..0cadf592cc1 100644
--- a/config/feature_flags/development/async_commit_diff_files.yml
+++ b/config/feature_flags/development/async_commit_diff_files.yml
@@ -1,7 +1,7 @@
---
name: async_commit_diff_files
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38450
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369439
milestone: '13.3'
type: development
group: group::source code
diff --git a/config/feature_flags/development/auto_ban_user_on_namespace_excessive_projects_download.yml b/config/feature_flags/development/auto_ban_user_on_namespace_excessive_projects_download.yml
new file mode 100644
index 00000000000..6e14a8dd62c
--- /dev/null
+++ b/config/feature_flags/development/auto_ban_user_on_namespace_excessive_projects_download.yml
@@ -0,0 +1,8 @@
+---
+name: auto_ban_user_on_namespace_excessive_projects_download
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91343
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367611
+milestone: '15.3'
+type: development
+group: group::anti-abuse
+default_enabled: false
diff --git a/config/feature_flags/development/batch_load_environment_last_deployment_group.yml b/config/feature_flags/development/batch_load_environment_last_deployment_group.yml
deleted file mode 100644
index 4d35b638fbc..00000000000
--- a/config/feature_flags/development/batch_load_environment_last_deployment_group.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: batch_load_environment_last_deployment_group
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86584/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363023
-milestone: '15.1'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/branch_list_keyset_pagination.yml b/config/feature_flags/development/branch_list_keyset_pagination.yml
index 12200292058..7e8e437fa96 100644
--- a/config/feature_flags/development/branch_list_keyset_pagination.yml
+++ b/config/feature_flags/development/branch_list_keyset_pagination.yml
@@ -1,7 +1,7 @@
---
name: branch_list_keyset_pagination
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35819
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369435
milestone: '13.2'
type: development
group: group::source code
diff --git a/config/feature_flags/development/change_response_code_merge_status.yml b/config/feature_flags/development/change_response_code_merge_status.yml
deleted file mode 100644
index 9f102d70354..00000000000
--- a/config/feature_flags/development/change_response_code_merge_status.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: change_response_code_merge_status
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82465/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/356930
-milestone: '15.1'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/changelog_commits_limitation.yml b/config/feature_flags/development/changelog_commits_limitation.yml
index 3339fc7f946..ee1f0b0654d 100644
--- a/config/feature_flags/development/changelog_commits_limitation.yml
+++ b/config/feature_flags/development/changelog_commits_limitation.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364101
milestone: '15.1'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
index dd7192f0bc8..eba1c4ead3b 100644
--- a/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
+++ b/config/feature_flags/development/ci_destroy_unlocked_job_artifacts.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338165
milestone: '14.5'
type: development
group: group::pipeline insights
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_expand_environment_name_and_url.yml b/config/feature_flags/development/ci_expand_environment_name_and_url.yml
deleted file mode 100644
index beb7065cf53..00000000000
--- a/config/feature_flags/development/ci_expand_environment_name_and_url.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_expand_environment_name_and_url
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84969
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/358831
-milestone: '14.10'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_fix_rules_if_comparison_with_regexp_variable.yml b/config/feature_flags/development/ci_fix_rules_if_comparison_with_regexp_variable.yml
deleted file mode 100644
index d4393f64059..00000000000
--- a/config/feature_flags/development/ci_fix_rules_if_comparison_with_regexp_variable.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_fix_rules_if_comparison_with_regexp_variable
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85310
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359740
-milestone: '15.0'
-type: development
-group: group::pipeline authoring
-default_enabled: true
diff --git a/config/feature_flags/development/ci_job_artifacts_backlog_work.yml b/config/feature_flags/development/ci_job_artifacts_backlog_work.yml
index a97982d2043..9ab5b0210c0 100644
--- a/config/feature_flags/development/ci_job_artifacts_backlog_work.yml
+++ b/config/feature_flags/development/ci_job_artifacts_backlog_work.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347144
milestone: '14.10'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_minimal_cost_factor_for_gitlab_contributors.yml b/config/feature_flags/development/ci_minimal_cost_factor_for_gitlab_contributors.yml
deleted file mode 100644
index e571abdc97f..00000000000
--- a/config/feature_flags/development/ci_minimal_cost_factor_for_gitlab_contributors.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_minimal_cost_factor_for_gitlab_contributors
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89742
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365862
-milestone: '15.2'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_new_public_oss_cost_factor.yml b/config/feature_flags/development/ci_new_public_oss_cost_factor.yml
new file mode 100644
index 00000000000..20ab9bd4509
--- /dev/null
+++ b/config/feature_flags/development/ci_new_public_oss_cost_factor.yml
@@ -0,0 +1,8 @@
+---
+name: ci_new_public_oss_cost_factor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93046
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369113
+milestone: '15.3'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_retry_downstream_pipeline.yml b/config/feature_flags/development/ci_retry_downstream_pipeline.yml
deleted file mode 100644
index 69a2821c86e..00000000000
--- a/config/feature_flags/development/ci_retry_downstream_pipeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_retry_downstream_pipeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76115
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347424
-milestone: '14.6'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_rules_changes_compare.yml b/config/feature_flags/development/ci_rules_changes_compare.yml
new file mode 100644
index 00000000000..094692def26
--- /dev/null
+++ b/config/feature_flags/development/ci_rules_changes_compare.yml
@@ -0,0 +1,8 @@
+---
+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_stop_expanding_file_vars_for_runners.yml b/config/feature_flags/development/ci_stop_expanding_file_vars_for_runners.yml
new file mode 100644
index 00000000000..e9f378288d9
--- /dev/null
+++ b/config/feature_flags/development/ci_stop_expanding_file_vars_for_runners.yml
@@ -0,0 +1,8 @@
+---
+name: ci_stop_expanding_file_vars_for_runners
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94198
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369907
+milestone: '15.3'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
index f756de86efb..7cb79c05774 100644
--- a/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
+++ b/config/feature_flags/development/ci_update_unlocked_job_artifacts.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343465
milestone: '14.5'
type: development
group: group::pipeline insights
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/custom_headers_streaming_audit_events_ui.yml b/config/feature_flags/development/custom_headers_streaming_audit_events_ui.yml
deleted file mode 100644
index 710a4f55130..00000000000
--- a/config/feature_flags/development/custom_headers_streaming_audit_events_ui.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: custom_headers_streaming_audit_events_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90135
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365259
-milestone: '15.2'
-type: development
-group: group::compliance
-default_enabled: false
diff --git a/config/feature_flags/development/datadog_integration_logs_collection.yml b/config/feature_flags/development/datadog_integration_logs_collection.yml
index 5bd155eece9..3e65b70d0e6 100644
--- a/config/feature_flags/development/datadog_integration_logs_collection.yml
+++ b/config/feature_flags/development/datadog_integration_logs_collection.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346339
milestone: '14.8'
type: development
group: group::integrations
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/disabled_mr_discussions_redis_cache.yml b/config/feature_flags/development/disabled_mr_discussions_redis_cache.yml
new file mode 100644
index 00000000000..c4f0ca0effe
--- /dev/null
+++ b/config/feature_flags/development/disabled_mr_discussions_redis_cache.yml
@@ -0,0 +1,8 @@
+---
+name: disabled_mr_discussions_redis_cache
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92752
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368366
+milestone: '15.3'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/edit_tag_release_notes_via_release_page.yml b/config/feature_flags/development/edit_tag_release_notes_via_release_page.yml
deleted file mode 100644
index 1f67eafc06b..00000000000
--- a/config/feature_flags/development/edit_tag_release_notes_via_release_page.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: edit_tag_release_notes_via_release_page
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88832
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366244
-milestone: '15.2'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/enforce_auth_checks_on_uploads.yml b/config/feature_flags/development/enforce_auth_checks_on_uploads.yml
deleted file mode 100644
index d0cbe123a8f..00000000000
--- a/config/feature_flags/development/enforce_auth_checks_on_uploads.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: enforce_auth_checks_on_uploads
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80117
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352291
-milestone: '14.8'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/enforce_security_report_validation.yml b/config/feature_flags/development/enforce_security_report_validation.yml
deleted file mode 100644
index 2a8d3e32ec4..00000000000
--- a/config/feature_flags/development/enforce_security_report_validation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: enforce_security_report_validation
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351000
-milestone: '14.9'
-type: development
-group: group::threat insights
-default_enabled: true
diff --git a/config/feature_flags/development/etag_merge_request_diff_batches.yml b/config/feature_flags/development/etag_merge_request_diff_batches.yml
new file mode 100644
index 00000000000..8cd3ba8637a
--- /dev/null
+++ b/config/feature_flags/development/etag_merge_request_diff_batches.yml
@@ -0,0 +1,8 @@
+---
+name: etag_merge_request_diff_batches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93953
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369488
+milestone: '15.3'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/execute_build_hooks_inline.yml b/config/feature_flags/development/execute_build_hooks_inline.yml
new file mode 100644
index 00000000000..0389fca3bb1
--- /dev/null
+++ b/config/feature_flags/development/execute_build_hooks_inline.yml
@@ -0,0 +1,8 @@
+---
+name: execute_build_hooks_inline
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93665
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370387
+milestone: '15.3'
+type: development
+group: group::integrations
+default_enabled: false
diff --git a/config/feature_flags/development/file_line_blame.yml b/config/feature_flags/development/file_line_blame.yml
new file mode 100644
index 00000000000..1be6aeee40a
--- /dev/null
+++ b/config/feature_flags/development/file_line_blame.yml
@@ -0,0 +1,8 @@
+---
+name: file_line_blame
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92538
+rollout_issue_url:
+milestone: '15.3'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/fix_sliding_list_partitioning.yml b/config/feature_flags/development/fix_sliding_list_partitioning.yml
deleted file mode 100644
index 7d553ea938c..00000000000
--- a/config/feature_flags/development/fix_sliding_list_partitioning.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: fix_sliding_list_partitioning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85222
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362246
-milestone: '15.1'
-type: development
-group: group::sharding
-default_enabled: true
diff --git a/config/feature_flags/development/group_level_protected_environment_settings_permission.yml b/config/feature_flags/development/group_level_protected_environment_settings_permission.yml
new file mode 100644
index 00000000000..bbcfe24ba72
--- /dev/null
+++ b/config/feature_flags/development/group_level_protected_environment_settings_permission.yml
@@ -0,0 +1,8 @@
+---
+name: 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/369873
+milestone: '15.3'
+type: development
+group: group::release
+default_enabled: true
diff --git a/config/feature_flags/development/group_runner_view_ui.yml b/config/feature_flags/development/group_runner_view_ui.yml
deleted file mode 100644
index f3a9eb15f0f..00000000000
--- a/config/feature_flags/development/group_runner_view_ui.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: group_runner_view_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89638/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364811
-milestone: '15.1'
-type: development
-group: group::runner
-default_enabled: false
diff --git a/config/feature_flags/development/hard_failure_for_mirrors_without_license.yml b/config/feature_flags/development/hard_failure_for_mirrors_without_license.yml
deleted file mode 100644
index f138c8ea497..00000000000
--- a/config/feature_flags/development/hard_failure_for_mirrors_without_license.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: hard_failure_for_mirrors_without_license
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92422
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367851
-milestone: '15.2'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/hash_based_cache_for_protected_branches.yml b/config/feature_flags/development/hash_based_cache_for_protected_branches.yml
new file mode 100644
index 00000000000..4e071707182
--- /dev/null
+++ b/config/feature_flags/development/hash_based_cache_for_protected_branches.yml
@@ -0,0 +1,8 @@
+---
+name: hash_based_cache_for_protected_branches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92934
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368279
+milestone: '15.3'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/hash_oauth_tokens.yml b/config/feature_flags/development/hash_oauth_tokens.yml
new file mode 100644
index 00000000000..43cd5672fc4
--- /dev/null
+++ b/config/feature_flags/development/hash_oauth_tokens.yml
@@ -0,0 +1,8 @@
+---
+name: hash_oauth_tokens
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91501
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367570
+milestone: '15.3'
+type: development
+group: group::authentication and authorization
+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
new file mode 100644
index 00000000000..59e06fbec43
--- /dev/null
+++ b/config/feature_flags/development/import_export_web_upload_stream.yml
@@ -0,0 +1,8 @@
+---
+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/import_relation_object_persistence.yml b/config/feature_flags/development/import_relation_object_persistence.yml
deleted file mode 100644
index e182ea31a72..00000000000
--- a/config/feature_flags/development/import_relation_object_persistence.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: import_relation_object_persistence
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79963
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354497
-milestone: '14.9'
-type: development
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/development/import_release_authors_from_github.yml b/config/feature_flags/development/import_release_authors_from_github.yml
deleted file mode 100644
index c263892fbf8..00000000000
--- a/config/feature_flags/development/import_release_authors_from_github.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: import_release_authors_from_github
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89692
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343448
-milestone: '15.1'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/incident_timeline_events_from_labels.yml b/config/feature_flags/development/incident_timeline_events_from_labels.yml
new file mode 100644
index 00000000000..5f04c57462a
--- /dev/null
+++ b/config/feature_flags/development/incident_timeline_events_from_labels.yml
@@ -0,0 +1,8 @@
+---
+name: incident_timeline_events_from_labels
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93175
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369416
+milestone: '15.3'
+type: development
+group: group::respond
+default_enabled: false
diff --git a/config/feature_flags/development/include_groups_from_group_shares_in_project_transfer_locations.yml b/config/feature_flags/development/include_groups_from_group_shares_in_project_transfer_locations.yml
new file mode 100644
index 00000000000..3db60cfd2d7
--- /dev/null
+++ b/config/feature_flags/development/include_groups_from_group_shares_in_project_transfer_locations.yml
@@ -0,0 +1,8 @@
+---
+name: include_groups_from_group_shares_in_project_transfer_locations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90127
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366305
+milestone: '15.2'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/increase_page_size_exponentially.yml b/config/feature_flags/development/increase_page_size_exponentially.yml
index 88f05d1e850..8297a4078fa 100644
--- a/config/feature_flags/development/increase_page_size_exponentially.yml
+++ b/config/feature_flags/development/increase_page_size_exponentially.yml
@@ -1,7 +1,7 @@
---
name: increase_page_size_exponentially
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66174
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369434
milestone: '14.1'
type: development
group: group::source code
diff --git a/config/feature_flags/development/incremental_repository_backup.yml b/config/feature_flags/development/incremental_repository_backup.yml
deleted file mode 100644
index 2b980abd403..00000000000
--- a/config/feature_flags/development/incremental_repository_backup.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: incremental_repository_backup
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79589
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355945
-milestone: '14.9'
-type: development
-group: group::gitaly
-default_enabled: true
diff --git a/config/feature_flags/development/job_log_jump_to_failures.yml b/config/feature_flags/development/job_log_jump_to_failures.yml
new file mode 100644
index 00000000000..45d11c82fe9
--- /dev/null
+++ b/config/feature_flags/development/job_log_jump_to_failures.yml
@@ -0,0 +1,8 @@
+---
+name: job_log_jump_to_failures
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91098
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368633
+milestone: '15.3'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/job_log_search.yml b/config/feature_flags/development/job_log_search.yml
deleted file mode 100644
index b6f1cec26f6..00000000000
--- a/config/feature_flags/development/job_log_search.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: job_log_search
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91293
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366455
-milestone: '15.2'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/json_wrapper_legacy_mode.yml b/config/feature_flags/development/json_wrapper_legacy_mode.yml
index 13a4bb30d09..071f5ef7022 100644
--- a/config/feature_flags/development/json_wrapper_legacy_mode.yml
+++ b/config/feature_flags/development/json_wrapper_legacy_mode.yml
@@ -1,7 +1,7 @@
---
name: json_wrapper_legacy_mode
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30849
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369436
milestone: '13.0'
type: development
group: group::source code
diff --git a/config/feature_flags/development/lfk_automatic_partition_creation.yml b/config/feature_flags/development/lfk_automatic_partition_creation.yml
deleted file mode 100644
index 5eb50d36f27..00000000000
--- a/config/feature_flags/development/lfk_automatic_partition_creation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: lfk_automatic_partition_creation
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346907
-milestone: '14.6'
-type: development
-group: group::sharding
-default_enabled: true
diff --git a/config/feature_flags/development/lfk_automatic_partition_dropping.yml b/config/feature_flags/development/lfk_automatic_partition_dropping.yml
deleted file mode 100644
index a45d6b8f346..00000000000
--- a/config/feature_flags/development/lfk_automatic_partition_dropping.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: lfk_automatic_partition_dropping
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346908
-milestone: '14.6'
-type: development
-group: group::sharding
-default_enabled: true
diff --git a/config/feature_flags/development/limit_reviewer_and_assignee_size.yml b/config/feature_flags/development/limit_reviewer_and_assignee_size.yml
new file mode 100644
index 00000000000..b2a762cc583
--- /dev/null
+++ b/config/feature_flags/development/limit_reviewer_and_assignee_size.yml
@@ -0,0 +1,8 @@
+---
+name: limit_reviewer_and_assignee_size
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91406
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366485
+milestone: '15.3'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/linear_scopes_superset.yml b/config/feature_flags/development/linear_scopes_superset.yml
deleted file mode 100644
index 555b36262ec..00000000000
--- a/config/feature_flags/development/linear_scopes_superset.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_scopes_superset
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87643
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362687
-milestone: '15.1'
-type: development
-group: group::workspace
-default_enabled: false
diff --git a/config/feature_flags/development/mr_review_submit_comment.yml b/config/feature_flags/development/mr_review_submit_comment.yml
index d06901d992c..8457b46340e 100644
--- a/config/feature_flags/development/mr_review_submit_comment.yml
+++ b/config/feature_flags/development/mr_review_submit_comment.yml
@@ -5,4 +5,4 @@ rollout_issue_url:
milestone: '15.1'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/new_graphql_keyset_pagination.yml b/config/feature_flags/development/new_graphql_keyset_pagination.yml
deleted file mode 100644
index 7f1c73756b3..00000000000
--- a/config/feature_flags/development/new_graphql_keyset_pagination.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: new_graphql_keyset_pagination
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56751
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323730
-milestone: '13.10'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/only_positive_pagination_values.yml b/config/feature_flags/development/only_positive_pagination_values.yml
new file mode 100644
index 00000000000..9347c628e65
--- /dev/null
+++ b/config/feature_flags/development/only_positive_pagination_values.yml
@@ -0,0 +1,8 @@
+---
+name: only_positive_pagination_values
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93571
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369225
+milestone: '15.3'
+type: development
+group: group::source code
+default_enabled: false
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
new file mode 100644
index 00000000000..7e7789e2e8f
--- /dev/null
+++ b/config/feature_flags/development/override_group_level_protected_environment_settings_permission.yml
@@ -0,0 +1,8 @@
+---
+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/paginated_mr_discussions.yml b/config/feature_flags/development/paginated_mr_discussions.yml
index ec2fb41f310..d72189d447b 100644
--- a/config/feature_flags/development/paginated_mr_discussions.yml
+++ b/config/feature_flags/development/paginated_mr_discussions.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364497
milestone: '15.1'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/performance_bar_stats.yml b/config/feature_flags/development/performance_bar_stats.yml
deleted file mode 100644
index 79315050c58..00000000000
--- a/config/feature_flags/development/performance_bar_stats.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: performance_bar_stats
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48149
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285480
-milestone: '13.7'
-type: development
-group: group::product_planning
-default_enabled: false
diff --git a/config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml b/config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml
deleted file mode 100644
index 9188b0dbab4..00000000000
--- a/config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: personal_access_tokens_scoped_to_projects
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54617
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322187
-milestone: '13.10'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/product_intelligence_database_event_tracking.yml b/config/feature_flags/development/product_intelligence_database_event_tracking.yml
new file mode 100644
index 00000000000..83a65398e87
--- /dev/null
+++ b/config/feature_flags/development/product_intelligence_database_event_tracking.yml
@@ -0,0 +1,9 @@
+---
+name: product_intelligence_database_event_tracking
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92079
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368976
+rollout_issue_url:
+milestone: '15.3'
+type: development
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/development/rate_limit_gitlab_shell_by_ip.yml b/config/feature_flags/development/rate_limit_gitlab_shell_by_ip.yml
new file mode 100644
index 00000000000..67a465ef6d6
--- /dev/null
+++ b/config/feature_flags/development/rate_limit_gitlab_shell_by_ip.yml
@@ -0,0 +1,8 @@
+---
+name: rate_limit_gitlab_shell_by_ip
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91599
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367998
+milestone: '15.3'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/rebase_without_ci_ui.yml b/config/feature_flags/development/rebase_without_ci_ui.yml
deleted file mode 100644
index b05711ced29..00000000000
--- a/config/feature_flags/development/rebase_without_ci_ui.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: rebase_without_ci_ui
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78194
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350262
-milestone: '14.7'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml b/config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml
deleted file mode 100644
index 77b6b5a8a40..00000000000
--- a/config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refresh_authorizations_via_affected_projects_on_group_membership
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87071
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362204
-milestone: '15.0'
-type: development
-group: group::workspace
-default_enabled: false
diff --git a/config/feature_flags/development/report_artifact_build_completed_metrics_on_build_completion.yml b/config/feature_flags/development/report_artifact_build_completed_metrics_on_build_completion.yml
new file mode 100644
index 00000000000..76b6c8c6b2f
--- /dev/null
+++ b/config/feature_flags/development/report_artifact_build_completed_metrics_on_build_completion.yml
@@ -0,0 +1,8 @@
+---
+name: report_artifact_build_completed_metrics_on_build_completion
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80334
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369500
+milestone: '15.3'
+type: development
+group: group::static analysis
+default_enabled: false
diff --git a/config/feature_flags/development/repository_archive_hotlinking_interception.yml b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
index 56943627231..dbdde4993f8 100644
--- a/config/feature_flags/development/repository_archive_hotlinking_interception.yml
+++ b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
@@ -1,7 +1,7 @@
---
name: repository_archive_hotlinking_interception
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/50c11f278d18fe1f3fb12eb595067216bb58ade2
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369433
milestone: '12.10'
type: development
group: group::source code
diff --git a/config/feature_flags/development/restructured_mr_widget.yml b/config/feature_flags/development/restructured_mr_widget.yml
deleted file mode 100644
index cf20130509a..00000000000
--- a/config/feature_flags/development/restructured_mr_widget.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: restructured_mr_widget
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68565
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339181
-milestone: '14.3'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/restyle_login_page.yml b/config/feature_flags/development/restyle_login_page.yml
new file mode 100644
index 00000000000..ed3ae3ef6ea
--- /dev/null
+++ b/config/feature_flags/development/restyle_login_page.yml
@@ -0,0 +1,8 @@
+---
+name: restyle_login_page
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91673
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368387
+milestone: '15.2'
+type: development
+group: group::authentication and authorization
+default_enabled: false
diff --git a/config/feature_flags/development/searchable_fork_targets.yml b/config/feature_flags/development/searchable_fork_targets.yml
new file mode 100644
index 00000000000..3baea34623a
--- /dev/null
+++ b/config/feature_flags/development/searchable_fork_targets.yml
@@ -0,0 +1,8 @@
+---
+name: searchable_fork_targets
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94991
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370795
+milestone: '15.3'
+type: development
+group: group::source code
+default_enabled: true
diff --git a/config/feature_flags/development/simulate_pipeline.yml b/config/feature_flags/development/simulate_pipeline.yml
deleted file mode 100644
index 3bc12d5b741..00000000000
--- a/config/feature_flags/development/simulate_pipeline.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: simulate_pipeline
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88630
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/364257
-milestone: '15.1'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/subgroups_approval_rules.yml b/config/feature_flags/development/subgroups_approval_rules.yml
index 13f4e872b4f..e7935f5e5d2 100644
--- a/config/feature_flags/development/subgroups_approval_rules.yml
+++ b/config/feature_flags/development/subgroups_approval_rules.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366741
milestone: '15.2'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/timelog_categories.yml b/config/feature_flags/development/timelog_categories.yml
new file mode 100644
index 00000000000..64bb089bc97
--- /dev/null
+++ b/config/feature_flags/development/timelog_categories.yml
@@ -0,0 +1,8 @@
+---
+name: timelog_categories
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88462
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365829
+milestone: '15.3'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/track_agent_users_using_ci_tunnel.yml b/config/feature_flags/development/track_agent_users_using_ci_tunnel.yml
new file mode 100644
index 00000000000..0a00babc2db
--- /dev/null
+++ b/config/feature_flags/development/track_agent_users_using_ci_tunnel.yml
@@ -0,0 +1,8 @@
+---
+name: track_agent_users_using_ci_tunnel
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92300
+rollout_issue_url:
+milestone: '15.3'
+type: development
+group: group::configure
+default_enabled: false
diff --git a/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml b/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml
deleted file mode 100644
index a4685732f27..00000000000
--- a/config/feature_flags/development/track_gitlab_schema_in_current_transaction.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: track_gitlab_schema_in_current_transaction
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76717
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349944
-milestone: '14.8'
-type: development
-group: group::sharding
-default_enabled: false
diff --git a/config/feature_flags/development/trial_email_validation.yml b/config/feature_flags/development/trial_email_validation.yml
new file mode 100644
index 00000000000..c658a49f195
--- /dev/null
+++ b/config/feature_flags/development/trial_email_validation.yml
@@ -0,0 +1,8 @@
+---
+name: trial_email_validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92762
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368999
+milestone: '15.3'
+type: development
+group: group::acquisition
+default_enabled: false
diff --git a/config/feature_flags/development/uncached_mr_attention_requests_count.yml b/config/feature_flags/development/uncached_mr_attention_requests_count.yml
deleted file mode 100644
index 239490ab1c2..00000000000
--- a/config/feature_flags/development/uncached_mr_attention_requests_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: uncached_mr_attention_requests_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84145
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357480
-milestone: '14.10'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
index c94b48d8329..e7e220c310b 100644
--- a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
+++ b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
@@ -1,7 +1,7 @@
---
name: unlink_fork_network_upon_visibility_decrease
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20466
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369438
milestone: '12.6'
type: development
group: group::source code
diff --git a/config/feature_flags/development/update_vuln_identifiers_flag.yml b/config/feature_flags/development/update_vuln_identifiers_flag.yml
index 62fdc08ce34..3e0e7f4fa41 100644
--- a/config/feature_flags/development/update_vuln_identifiers_flag.yml
+++ b/config/feature_flags/development/update_vuln_identifiers_flag.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362179
milestone: '15.1'
type: development
group: group::static analysis
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/use_keyset_aware_user_search_query.yml b/config/feature_flags/development/use_keyset_aware_user_search_query.yml
deleted file mode 100644
index 8c2babfd1c7..00000000000
--- a/config/feature_flags/development/use_keyset_aware_user_search_query.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_keyset_aware_user_search_query
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91764
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367025
-milestone: '15.2'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/use_pipeline_wizard_for_pages.yml b/config/feature_flags/development/use_pipeline_wizard_for_pages.yml
new file mode 100644
index 00000000000..10d4478934e
--- /dev/null
+++ b/config/feature_flags/development/use_pipeline_wizard_for_pages.yml
@@ -0,0 +1,8 @@
+---
+name: use_pipeline_wizard_for_pages
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78276
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349095
+milestone: '15.3'
+type: development
+group: group::incubation
+default_enabled: false
diff --git a/config/feature_flags/development/use_redis_hll_instrumentation_classes.yml b/config/feature_flags/development/use_redis_hll_instrumentation_classes.yml
deleted file mode 100644
index 46e53688b70..00000000000
--- a/config/feature_flags/development/use_redis_hll_instrumentation_classes.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_redis_hll_instrumentation_classes
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90237
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365332
-milestone: '15.1'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids.yml b/config/feature_flags/development/use_traversal_ids.yml
index ab3a2eaf733..3d566ddc3c0 100644
--- a/config/feature_flags/development/use_traversal_ids.yml
+++ b/config/feature_flags/development/use_traversal_ids.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948
milestone: '13.11'
type: development
group: group::workspace
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/use_traversal_ids_for_ancestor_scopes_with_inner_join.yml b/config/feature_flags/development/use_traversal_ids_for_ancestor_scopes_with_inner_join.yml
deleted file mode 100644
index a9f7b18acd9..00000000000
--- a/config/feature_flags/development/use_traversal_ids_for_ancestor_scopes_with_inner_join.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_traversal_ids_for_ancestor_scopes_with_inner_join
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83371
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/356628
-milestone: '15.1'
-type: development
-group: group::workspace
-default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml b/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml
index 74ae139b68a..00c6edfc148 100644
--- a/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml
+++ b/config/feature_flags/development/use_traversal_ids_for_root_ancestor.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331907
milestone: '14.0'
type: development
group: group::workspace
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/work_items.yml b/config/feature_flags/development/work_items.yml
index 7401c14979a..f19ed6d8ce6 100644
--- a/config/feature_flags/development/work_items.yml
+++ b/config/feature_flags/development/work_items.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339664
milestone: '14.3'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/work_items_create_from_markdown.yml b/config/feature_flags/development/work_items_create_from_markdown.yml
new file mode 100644
index 00000000000..9a954001f2b
--- /dev/null
+++ b/config/feature_flags/development/work_items_create_from_markdown.yml
@@ -0,0 +1,8 @@
+---
+name: work_items_create_from_markdown
+introduced_by_url:
+rollout_issue_url:
+milestone: '15.3'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/work_items_hierarchy.yml b/config/feature_flags/development/work_items_hierarchy.yml
index 439fb941eb9..ce27c58df96 100644
--- a/config/feature_flags/development/work_items_hierarchy.yml
+++ b/config/feature_flags/development/work_items_hierarchy.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363447
milestone: '15.1'
type: development
group: group::product planning
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/workhorse_archive_cache_disabled.yml b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
index e40741863d4..fb171616dc5 100644
--- a/config/feature_flags/development/workhorse_archive_cache_disabled.yml
+++ b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
@@ -1,7 +1,7 @@
---
name: workhorse_archive_cache_disabled
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/16325
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369437
milestone: '10.5'
type: development
group: group::source code
diff --git a/config/feature_flags/ops/authenticate_markdown_api.yml b/config/feature_flags/ops/authenticate_markdown_api.yml
new file mode 100644
index 00000000000..8e7a7833d27
--- /dev/null
+++ b/config/feature_flags/ops/authenticate_markdown_api.yml
@@ -0,0 +1,8 @@
+---
+name: authenticate_markdown_api
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93727
+rollout_issue_url:
+milestone: '15.3'
+type: ops
+group: group::project management
+default_enabled: true
diff --git a/config/feature_flags/ops/batched_migrations_health_status_wal.yml b/config/feature_flags/ops/batched_migrations_health_status_wal.yml
new file mode 100644
index 00000000000..dfef528ee39
--- /dev/null
+++ b/config/feature_flags/ops/batched_migrations_health_status_wal.yml
@@ -0,0 +1,8 @@
+---
+name: batched_migrations_health_status_wal
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84555
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366855
+milestone: '15.2'
+type: ops
+group: group::database
+default_enabled: false
diff --git a/config/feature_flags/ops/ci_build_dependencies_artifacts_logger.yml b/config/feature_flags/ops/ci_build_dependencies_artifacts_logger.yml
new file mode 100644
index 00000000000..533900efdac
--- /dev/null
+++ b/config/feature_flags/ops/ci_build_dependencies_artifacts_logger.yml
@@ -0,0 +1,8 @@
+---
+name: ci_build_dependencies_artifacts_logger
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93179
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369441
+milestone: '15.3'
+type: ops
+group: group::pipeline insights
+default_enabled: false
diff --git a/config/feature_flags/ops/database_async_index_destruction.yml b/config/feature_flags/ops/database_async_index_destruction.yml
new file mode 100644
index 00000000000..a100b3a40f2
--- /dev/null
+++ b/config/feature_flags/ops/database_async_index_destruction.yml
@@ -0,0 +1,8 @@
+---
+name: database_async_index_destruction
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92328
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367964
+milestone: '15.3'
+type: ops
+group: group::database
+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
index c4710858a0a..58660ceb287 100644
--- a/config/feature_flags/ops/github_importer_issue_events_import.yml
+++ b/config/feature_flags/ops/github_importer_issue_events_import.yml
@@ -2,7 +2,7 @@
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.2'
+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
new file mode 100644
index 00000000000..88e9db6721f
--- /dev/null
+++ b/config/feature_flags/ops/github_importer_single_endpoint_issue_events_import.yml
@@ -0,0 +1,8 @@
+---
+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/performance_bar_stats.yml b/config/feature_flags/ops/performance_bar_stats.yml
new file mode 100644
index 00000000000..00f2a8eeef8
--- /dev/null
+++ b/config/feature_flags/ops/performance_bar_stats.yml
@@ -0,0 +1,8 @@
+---
+name: performance_bar_stats
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48149
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285480
+milestone: '13.7'
+type: ops
+group: group::product_planning
+default_enabled: false
diff --git a/config/feature_flags/ops/report_jemalloc_stats.yml b/config/feature_flags/ops/report_jemalloc_stats.yml
new file mode 100644
index 00000000000..9cf5fd9d14b
--- /dev/null
+++ b/config/feature_flags/ops/report_jemalloc_stats.yml
@@ -0,0 +1,8 @@
+---
+name: report_jemalloc_stats
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91283
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367845
+milestone: '15.2'
+type: ops
+group: group::memory
+default_enabled: true
diff --git a/config/feature_flags/ops/skip_rugged_auto_detect.yml b/config/feature_flags/ops/skip_rugged_auto_detect.yml
new file mode 100644
index 00000000000..57da3bba4ea
--- /dev/null
+++ b/config/feature_flags/ops/skip_rugged_auto_detect.yml
@@ -0,0 +1,8 @@
+---
+name: skip_rugged_auto_detect
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95330
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370708
+milestone: '15.3'
+type: ops
+group: group::gitaly
+default_enabled: true
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 78ddc0afa3a..6861864999f 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -542,7 +542,7 @@ production: &base
# Periodically update ci_runner_versions table with up-to-date versions and status.
ci_runner_versions_reconciliation_worker:
- cron: "20 * * * *"
+ cron: "@daily"
# GitLab EE only jobs. These jobs are automatically enabled for an EE
# installation, and ignored for a CE installation.
diff --git a/config/initializers/00_deprecations.rb b/config/initializers/00_deprecations.rb
new file mode 100644
index 00000000000..bfbd57c99fe
--- /dev/null
+++ b/config/initializers/00_deprecations.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# Disallowed deprecation warnings are silenced in production. For performance
+# reasons we even skip the definition of disallowed warnings in production.
+#
+# See
+# * https://gitlab.com/gitlab-org/gitlab/-/issues/368379 for a follow-up
+# * https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92557#note_1032212676
+# for benchmarks
+#
+# In Rails 7 we will use `config.active_support.report_deprecations = false`
+# instead of this early return.
+if Rails.env.production?
+ ActiveSupport::Deprecation.silenced = true
+ return
+end
+
+# Ban the following deprecation warnings and turn them into runtime errors
+# in `development` and `test` environments.
+#
+# This way we prevent already fixed warnings from sneaking back into the codebase silently.
+rails7_deprecation_warnings = [
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/339739
+ /ActiveModel::Errors#keys is deprecated/,
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/342492
+ /Rendering actions with '\.' in the name is deprecated/,
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/333086
+ /default_hash is deprecated/,
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/369970
+ /Passing an Active Record object to `\w+` directly is deprecated/
+]
+
+ActiveSupport::Deprecation.disallowed_warnings.concat rails7_deprecation_warnings
diff --git a/config/initializers/0_log_deprecations.rb b/config/initializers/0_log_deprecations.rb
index 6ba18ea1136..b3ef391053e 100644
--- a/config/initializers/0_log_deprecations.rb
+++ b/config/initializers/0_log_deprecations.rb
@@ -6,6 +6,18 @@ def log_deprecations?
via_env_var.nil? ? Rails.env.development? : via_env_var
end
+# Add `:notify` behavior only if not already added.
+#
+# See https://github.com/Shopify/deprecation_toolkit/blob/1d0e6f5b99785806f715ce2e9a13dc50f453d1e1/lib/deprecation_toolkit.rb#L21
+def add_notify_behavior
+ notify = ActiveSupport::Deprecation::DEFAULT_BEHAVIORS.fetch(:notify)
+ behaviors = ActiveSupport::Deprecation.behavior
+
+ return if behaviors.find { |behavior| behavior == notify }
+
+ ActiveSupport::Deprecation.behavior = behaviors << notify
+end
+
if log_deprecations?
# Log deprecation warnings emitted through Kernel#warn, such as from gems or
# the Ruby VM.
@@ -19,6 +31,13 @@ if log_deprecations?
Warning.process('', actions)
+ # We may have silenced deprecations warnings in 00_deprecations.rb on production.
+ # Unsilence them again.
+ ActiveSupport::Deprecation.silenced = false
+
+ # If we want to consume emitted warnings from Rails we need to attach a notifier first.
+ add_notify_behavior
+
# Log deprecation warnings emitted from Rails (see ActiveSupport::Deprecation).
ActiveSupport::Notifications.subscribe('deprecation.rails') do |name, start, finish, id, payload|
Gitlab::DeprecationJsonLogger.info(message: payload[:message].strip, source: 'rails')
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 2de4efbe8ef..b271cefadd9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -136,9 +136,9 @@ if github_settings
OmniAuth::Strategies::GitHub.default_options[:client_options]
else
{
- "site" => File.join(github_settings["url"], "api/v3"),
+ "site" => File.join(github_settings["url"], "api/v3"),
"authorize_url" => File.join(github_settings["url"], "login/oauth/authorize"),
- "token_url" => File.join(github_settings["url"], "login/oauth/access_token")
+ "token_url" => File.join(github_settings["url"], "login/oauth/access_token")
}
end
end
@@ -631,7 +631,7 @@ Settings.cron_jobs['loose_foreign_keys_cleanup_worker'] ||= Settingslogic.new({}
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['job_class'] = 'LooseForeignKeys::CleanupWorker'
Settings.cron_jobs['ci_runner_versions_reconciliation_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['cron'] ||= '20 * * * *'
+Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['cron'] ||= '@daily'
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['job_class'] = 'Ci::Runners::ReconcileExistingRunnerVersionsCronWorker'
Gitlab.ee do
@@ -779,6 +779,11 @@ Gitlab.ee do
Settings.cron_jobs['licenses_reset_submit_license_usage_data_banner'] ||= Settingslogic.new({})
Settings.cron_jobs['licenses_reset_submit_license_usage_data_banner']['cron'] ||= "0 0 * * *"
Settings.cron_jobs['licenses_reset_submit_license_usage_data_banner']['job_class'] = 'Licenses::ResetSubmitLicenseUsageDataBannerWorker'
+ Gitlab.com do
+ Settings.cron_jobs['disable_legacy_open_source_license_for_inactive_projects'] ||= Settingslogic.new({})
+ Settings.cron_jobs['disable_legacy_open_source_license_for_inactive_projects']['cron'] ||= "30 5 * * 0"
+ Settings.cron_jobs['disable_legacy_open_source_license_for_inactive_projects']['job_class'] = 'Projects::DisableLegacyOpenSourceLicenseForInactiveProjectsWorker'
+ end
end
#
diff --git a/config/initializers/active_record_data_types.rb b/config/initializers/active_record_data_types.rb
index f8f0a69622f..7f4bd32c221 100644
--- a/config/initializers/active_record_data_types.rb
+++ b/config/initializers/active_record_data_types.rb
@@ -45,9 +45,13 @@ class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
NATIVE_DATABASE_TYPES[:datetime_with_timezone] = { name: 'timestamptz' }
end
-# Ensure `datetime_with_timezone` columns are correctly written to schema.rb
-if (ActiveRecord::Base.connection.active? rescue false)
- ActiveRecord::Base.connection.send :reload_type_map
+def connection_active?
+ ActiveRecord::Base.connection.active? # rubocop:disable Database/MultipleDatabases
+rescue StandardError
+ false
end
+# Ensure `datetime_with_timezone` columns are correctly written to schema.rb
+ActiveRecord::Base.connection.send(:reload_type_map) if connection_active?
+
ActiveRecord::Base.time_zone_aware_types += [:datetime_with_timezone]
diff --git a/config/initializers/database_config.rb b/config/initializers/database_config.rb
index 31666c884bc..09dedd903f8 100644
--- a/config/initializers/database_config.rb
+++ b/config/initializers/database_config.rb
@@ -1,5 +1,11 @@
# frozen_string_literal: true
+Rails.application.reloader.to_run(:before) do
+ # Make sure connects_to for Ci::ApplicationRecord gets called outside of config/routes.rb first
+ # See InitializerConnections.with_disabled_database_connections
+ Ci::ApplicationRecord
+end
+
Gitlab.ee do
if Gitlab::Geo.geo_database_configured?
# Make sure connects_to for geo gets called outside of config/routes.rb first
diff --git a/config/initializers/database_query_analyzers.rb b/config/initializers/database_query_analyzers.rb
index d1010e054af..2e73fbb79a2 100644
--- a/config/initializers/database_query_analyzers.rb
+++ b/config/initializers/database_query_analyzers.rb
@@ -3,9 +3,13 @@
# Currently we register validator only for `dev` or `test` environment
Gitlab::Database::QueryAnalyzer.instance.hook!
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
+Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(
+ ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification
+)
-if Rails.env.test? || Gitlab::Utils.to_boolean(ENV['ENABLE_CROSS_DATABASE_MODIFICATION_DETECTION'], default: false)
- Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification)
+if Gitlab.dev_or_test_env?
+ query_analyzer = ::Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection
+ Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(query_analyzer)
end
Gitlab::Application.configure do |config|
diff --git a/config/initializers/default_url_options.rb b/config/initializers/default_url_options.rb
index 138a8e467c7..43e4ed5478f 100644
--- a/config/initializers/default_url_options.rb
+++ b/config/initializers/default_url_options.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
default_url_options = {
- host: Gitlab.config.gitlab.host,
- protocol: Gitlab.config.gitlab.protocol,
+ host: Gitlab.config.gitlab.host,
+ protocol: Gitlab.config.gitlab.protocol,
script_name: Gitlab.config.gitlab.relative_url_root
}
diff --git a/config/initializers/diagnostic_reports.rb b/config/initializers/diagnostic_reports.rb
new file mode 100644
index 00000000000..b9932822a0b
--- /dev/null
+++ b/config/initializers/diagnostic_reports.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+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?
+
+Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ Gitlab::Memory::ReportsDaemon.instance.start
+end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 761904009bb..867f3fd47cc 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -90,6 +90,8 @@ Doorkeeper.configure do
# Check out the wiki for more information on customization
access_token_methods :from_access_token_param, :from_bearer_authorization, :from_bearer_param
+ hash_token_secrets using: '::Gitlab::DoorkeeperSecretStoring::Pbkdf2Sha512', fallback: :plain
+
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
#
diff --git a/config/initializers/lookbook.rb b/config/initializers/lookbook.rb
new file mode 100644
index 00000000000..4cb1b827286
--- /dev/null
+++ b/config/initializers/lookbook.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+if Rails.env.development?
+ # :nocov: Lookbook is only available in development
+ Lookbook::ApplicationController.class_eval do
+ content_security_policy false
+ end
+
+ Rails.application.configure do
+ config.lookbook.experimental_features = [:pages]
+ config.lookbook.page_paths = ["#{config.root}/spec/components/docs"]
+ end
+ # :nocov:
+end
diff --git a/config/initializers/memory_watchdog.rb b/config/initializers/memory_watchdog.rb
index 72779a18b10..82ad615ce25 100644
--- a/config/initializers/memory_watchdog.rb
+++ b/config/initializers/memory_watchdog.rb
@@ -13,7 +13,8 @@ Gitlab::Cluster::LifecycleEvents.on_worker_start do
Gitlab::Memory::Watchdog::NullHandler.instance
end
- Gitlab::Memory::Watchdog.new(
+ watchdog = Gitlab::Memory::Watchdog.new(
handler: handler, logger: Gitlab::AppLogger
- ).start
+ )
+ Gitlab::BackgroundTask.new(watchdog).start
end
diff --git a/config/initializers/rest-client-hostname_override.rb b/config/initializers/rest-client-hostname_override.rb
index 80b123ebe61..bb8995a4659 100644
--- a/config/initializers/rest-client-hostname_override.rb
+++ b/config/initializers/rest-client-hostname_override.rb
@@ -8,8 +8,8 @@ module RestClient
def transmit(uri, req, payload, &block)
begin
ip, hostname_override = Gitlab::UrlBlocker.validate!(uri, allow_local_network: allow_settings_local_requests?,
- allow_localhost: allow_settings_local_requests?,
- dns_rebind_protection: dns_rebind_protection?)
+ allow_localhost: allow_settings_local_requests?,
+ dns_rebind_protection: dns_rebind_protection?)
self.hostname_override = hostname_override
rescue Gitlab::UrlBlocker::BlockedUrlError => e
diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb
index 2879d48387d..a26d78f102b 100644
--- a/config/initializers/static_files.rb
+++ b/config/initializers/static_files.rb
@@ -21,7 +21,7 @@ if app.config.public_file_server.enabled
# If webpack-dev-server is configured, proxy webpack's public directory
# instead of looking for static assets
- if Gitlab.config.webpack.dev_server.enabled && Rails.env.development?
+ if Gitlab.config.webpack.dev_server.enabled && Gitlab.dev_or_test_env?
app.config.middleware.insert_before(
Gitlab::Middleware::Static,
Gitlab::Webpack::DevServerMiddleware,
diff --git a/config/initializers/truncato.rb b/config/initializers/truncato.rb
deleted file mode 100644
index dd0a8a313c3..00000000000
--- a/config/initializers/truncato.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-# Source: https://github.com/jorgemanrubia/truncato/issues/20#issuecomment-1135105823
-silence_warnings do
- Truncato::ARTIFICIAL_ROOT_NAME = 'truncato-artificial-root'
-end
diff --git a/config/initializers/wikicloth_redos_patch.rb b/config/initializers/wikicloth_redos_patch.rb
index a0b7c2e2466..4ff545dd6f7 100644
--- a/config/initializers/wikicloth_redos_patch.rb
+++ b/config/initializers/wikicloth_redos_patch.rb
@@ -120,7 +120,7 @@ module WikiCloth
key = params[0].to_s.strip
key_options = params[1..].collect { |p| p.is_a?(Hash) ? { :name => p[:name].strip, :value => p[:value].strip } : p.strip }
key_options ||= []
- key_digest = Digest::SHA256.hexdigest(key_options.to_a.sort {|x,y| (x.is_a?(Hash) ? x[:name] : x) <=> (y.is_a?(Hash) ? y[:name] : y) }.inspect)
+ key_digest = Digest::SHA256.hexdigest(key_options.to_a.sort { |x,y| (x.is_a?(Hash) ? x[:name] : x) <=> (y.is_a?(Hash) ? y[:name] : y) }.inspect)
return @options[:params][key] if @options[:params].has_key?(key)
# if we have a valid cache fragment use it
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index 64686bdd962..70c9ec0a0ba 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -15,6 +15,7 @@ ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w(
custom_emoji
award_emoji
+ ci_secure_file_registry
container_repository_registry
design_registry
event_log
diff --git a/config/jsdocs.config.js b/config/jsdocs.config.js
deleted file mode 100644
index 52635b1ce13..00000000000
--- a/config/jsdocs.config.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- source: {
- include: ['app/assets/javascripts/'],
- },
- opts: {
- template: 'node_modules/docdash',
- destination: 'jsdoc/',
- recurse: true,
- },
- docdash: {
- search: true,
- static: true,
- },
-};
diff --git a/config/locales/devise.zh-cn.yml b/config/locales/devise.zh-cn.yml
new file mode 100644
index 00000000000..2a74df865f0
--- /dev/null
+++ b/config/locales/devise.zh-cn.yml
@@ -0,0 +1,70 @@
+# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
+
+zh-CN:
+ devise:
+ confirmations:
+ confirmed: "您的电å­é‚®ä»¶åœ°å€å·²æˆåŠŸç¡®è®¤ã€‚"
+ send_instructions: "您将收到一å°ç”µå­é‚®ä»¶ï¼Œè¯´æ˜Žå¦‚何在几分钟内确认您的电å­é‚®ä»¶åœ°å€ã€‚"
+ send_paranoid_instructions: "如果您的电å­é‚®ä»¶åœ°å€å­˜åœ¨äºŽæˆ‘们的数æ®åº“中,您将在几分钟内收到一å°ç”µå­é‚®ä»¶ï¼Œå…¶ä¸­åŒ…å«å¦‚何确认您的电å­é‚®ä»¶åœ°å€çš„说明。"
+ failure:
+ already_authenticated: "您已ç»ç™»å½•ã€‚"
+ inactive: "您的å¸æˆ·å°šæœªæ¿€æ´»ã€‚"
+ invalid: "无效的登录信æ¯æˆ–密ç ã€‚"
+ locked: "您的å¸æˆ·å·²é”定。"
+ last_attempt: "在您的å¸æˆ·è¢«é”定之å‰ï¼Œæ‚¨è¿˜æœ‰ä¸€æ¬¡å°è¯•æœºä¼šã€‚"
+ not_found_in_database: "无效的登录信æ¯æˆ–密ç ã€‚"
+ timeout: "您的会è¯å·²è¿‡æœŸï¼Œè¯·é‡æ–°ç™»å½•ã€‚"
+ unauthenticated: "您需è¦å…ˆç™»å½•æˆ–注册,然åŽæ‰èƒ½ç»§ç»­ã€‚"
+ unconfirmed: "在继续之å‰ï¼Œæ‚¨å¿…须确认您的电å­é‚®ä»¶åœ°å€ã€‚请检查您的电å­é‚®ä»¶ï¼ŒèŽ·å–我们å‘é€ç»™æ‚¨çš„链接,或å•å‡»â€œé‡æ–°å‘é€ç¡®è®¤ç”µå­é‚®ä»¶â€ã€‚"
+ blocked: "您的å¸æˆ·å·²è¢«å°ç¦ã€‚如果您认为存在错误,请è”系您的管ç†å‘˜ã€‚"
+ forbidden: "您的å¸æˆ·æ²¡æœ‰ç™»å½•æ‰€éœ€çš„æƒé™ã€‚如果您认为存在错误,请è”系您的管ç†å‘˜ã€‚"
+ blocked_pending_approval: "您的å¸æˆ·æ­£åœ¨ç­‰å¾…管ç†å‘˜çš„批准,因此被阻止。如果您认为存在错误,请è”系您的管ç†å‘˜ã€‚"
+ mailer:
+ confirmation_instructions:
+ subject: "确认说明"
+ reset_password_instructions:
+ subject: "é‡ç½®å¯†ç è¯´æ˜Ž"
+ unlock_instructions:
+ subject: "解é”说明"
+ password_change:
+ subject: "密ç å·²æ›´æ”¹"
+ password_change_by_admin:
+ subject: "密ç å·²ç”±ç®¡ç†å‘˜æ›´æ”¹"
+ user_admin_approval:
+ subject: "欢迎使用æžç‹GitLabï¼"
+ omniauth_callbacks:
+ failure: "无法通过 %{kind} 对您进行身份验è¯ï¼ŒåŽŸå› ï¼š\"%{reason}\"。"
+ success: "å·²æˆåŠŸé€šè¿‡ %{kind} å¸æˆ·è¿›è¡Œèº«ä»½éªŒè¯ã€‚"
+ passwords:
+ no_token: "如果没有密ç é‡ç½®ç”µå­é‚®ä»¶ï¼Œæ‚¨å°†æ— æ³•è®¿é—®æ­¤é¡µé¢ã€‚如果您确实从密ç é‡ç½®ç”µå­é‚®ä»¶è®¿é—®æ­¤é¡µé¢ï¼Œè¯·ç¡®ä¿æ‚¨ä½¿ç”¨äº†æ供的完整 URL。"
+ send_instructions: "您将收到一å°ç”µå­é‚®ä»¶ï¼Œå…¶ä¸­åŒ…å«æœ‰å…³å¦‚何在几分钟内é‡ç½®å¯†ç çš„说明。"
+ send_paranoid_instructions: "如果您的电å­é‚®ä»¶åœ°å€å­˜åœ¨äºŽæˆ‘们的数æ®åº“中,您将在几分钟åŽåœ¨æ‚¨çš„电å­é‚®ä»¶åœ°å€ä¸­æ”¶åˆ°ä¸€ä¸ªå¯†ç æ¢å¤é“¾æŽ¥ã€‚"
+ updated: "您已æˆåŠŸæ›´æ”¹å¯†ç ã€‚您现在已登录。"
+ updated_not_active: "您已æˆåŠŸæ›´æ”¹å¯†ç ã€‚"
+ registrations:
+ destroyed: "å†è§ï¼æ‚¨çš„å¸æˆ·å·²æˆåŠŸæ³¨é”€ã€‚我们希望很快å†è§åˆ°æ‚¨ã€‚"
+ signed_up: "欢迎ï¼æ‚¨å·²æˆåŠŸæ³¨å†Œã€‚"
+ signed_up_but_inactive: "您已æˆåŠŸæ³¨å†Œã€‚但是,由于您的å¸æˆ·å°šæœªæ¿€æ´»ï¼Œæˆ‘们无法让您登录。"
+ signed_up_but_locked: "您已æˆåŠŸæ³¨å†Œã€‚但是,由于您的å¸æˆ·è¢«é”定,我们无法让您登录。"
+ signed_up_but_unconfirmed: "带有确认链接的消æ¯å·²å‘é€åˆ°æ‚¨çš„电å­é‚®ä»¶åœ°å€ã€‚请点击链接激活您的å¸æˆ·ã€‚"
+ signed_up_but_blocked_pending_approval: "您已æˆåŠŸæ³¨å†Œã€‚但是,由于您的å¸æˆ·æ­£åœ¨ç­‰å¾…管ç†å‘˜çš„批准,我们无法让您登录。"
+ update_needs_confirmation: "您已æˆåŠŸæ›´æ–°æ‚¨çš„å¸æˆ·ï¼Œä½†æˆ‘们需è¦éªŒè¯æ‚¨çš„新电å­é‚®ä»¶åœ°å€ã€‚请检查您的电å­é‚®ä»¶å¹¶ç‚¹å‡»ç¡®è®¤é“¾æŽ¥ï¼Œç¡®è®¤æ‚¨çš„新电å­é‚®ä»¶åœ°å€ã€‚"
+ updated: "您的å¸æˆ·å·²æˆåŠŸæ›´æ–°ã€‚"
+ sessions:
+ signed_in: "登录æˆåŠŸã€‚"
+ signed_out: "登出æˆåŠŸã€‚"
+ already_signed_out: "登出æˆåŠŸã€‚"
+ unlocks:
+ send_instructions: "您将收到一å°ç”µå­é‚®ä»¶ï¼Œè¯´æ˜Žå¦‚何在几分钟内解é”您的å¸æˆ·ã€‚"
+ send_paranoid_instructions: "如果您的å¸æˆ·å­˜åœ¨ï¼Œæ‚¨å°†åœ¨å‡ åˆ†é’Ÿå†…收到一å°ç”µå­é‚®ä»¶ï¼Œå…¶ä¸­åŒ…å«å¦‚何解é”它的说明。"
+ unlocked: "您的å¸æˆ·å·²æˆåŠŸè§£é”。请登录以继续。"
+ errors:
+ messages:
+ already_confirmed: "已确认,请å°è¯•ç™»å½•"
+ confirmation_period_expired: "需è¦åœ¨ %{period} 内确认,请在下方é‡æ–°è¯·æ±‚新的确认电å­é‚®ä»¶"
+ expired: "已过期,请é‡æ–°è¯·æ±‚新的确认电å­é‚®ä»¶"
+ not_found: "未找到"
+ not_locked: "未被é”定"
+ not_saved:
+ one: "å‘生 1 个错误,ç¦æ­¢ä¿å­˜æ­¤ %{resource}:"
+ other: "å‘生 %{count} 个错误,ç¦æ­¢ä¿å­˜æ­¤ %{resource}:"
diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml
index 2a58540f348..2e1eab78fa3 100644
--- a/config/metrics/aggregates/code_review.yml
+++ b/config/metrics/aggregates/code_review.yml
@@ -80,6 +80,42 @@
- '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'
- name: code_review_category_monthly_active_users
operator: OR
source: redis
@@ -148,6 +184,42 @@
- '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'
- name: code_review_extension_category_monthly_active_users
operator: OR
source: redis
diff --git a/config/metrics/aggregates/common.yml b/config/metrics/aggregates/common.yml
index 6396187a26a..35311858c64 100644
--- a/config/metrics/aggregates/common.yml
+++ b/config/metrics/aggregates/common.yml
@@ -17,16 +17,6 @@
# Corresponding feature flag should have `default_enabled` attribute set to `false`.
# This attribute is OPTIONAL and can be omitted, when `feature_flag` is missing no feature flag will be checked.
---
-- name: compliance_features_track_unique_visits_union
- operator: OR
- source: redis
- time_frame: [7d, 28d]
- events:
- - 'g_compliance_audit_events'
- - 'g_compliance_dashboard'
- - 'i_compliance_audit_events'
- - 'a_compliance_audit_events_api'
- - 'i_compliance_credential_inventory'
- name: incident_management_alerts_total_unique_counts
operator: OR
source: redis
@@ -59,6 +49,7 @@
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
@@ -67,6 +58,7 @@
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
@@ -75,4 +67,5 @@
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/20210216180622_incident_management_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180622_incident_management_total_unique_counts_monthly.yml
index ab0ddaf32e9..d9aa7d17f43 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
@@ -27,6 +27,9 @@ options:
- incident_management_alert_status_changed
- incident_management_alert_assigned
- incident_management_alert_todo
+ - incident_management_timeline_event_created
+ - incident_management_timeline_event_edited
+ - incident_management_timeline_event_deleted
distribution:
- ce
- ee
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 9f7a78cefdf..cfdd8987275 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
@@ -20,7 +20,6 @@ options:
- incident_management_timeline_event_edited
- incident_management_timeline_event_deleted
performance_indicator_type:
- - smau
- gmau
- paid_gmau
distribution:
diff --git a/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml b/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml
new file mode 100644
index 00000000000..07ba085063a
--- /dev/null
+++ b/config/metrics/counts_28d/20220708162311_i_code_review_merge_request_widget_test_summary_view_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_view_monthly
+description: The count of unique users (monthly) who were able to see the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml
new file mode 100644
index 00000000000..1b27e018e5e
--- /dev/null
+++ b/config/metrics/counts_28d/20220708163625_i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_full_report_clicked_monthly
+description: The count of unique users (monthly) who clicked the Full Report button on the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml b/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml
new file mode 100644
index 00000000000..40134414c5b
--- /dev/null
+++ b/config/metrics/counts_28d/20220708164545_i_code_review_merge_request_widget_test_summary_expand_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_monthly
+description: The count of unique users (monthly) who expanded the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml b/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml
new file mode 100644
index 00000000000..a6c08e49a5b
--- /dev/null
+++ b/config/metrics/counts_28d/20220708165638_i_code_review_merge_request_widget_test_summary_expand_success_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_success_monthly
+description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml b/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml
new file mode 100644
index 00000000000..7636ffae159
--- /dev/null
+++ b/config/metrics/counts_28d/20220708170514_i_code_review_merge_request_widget_test_summary_expand_warning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_warning_monthly
+description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml b/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml
new file mode 100644
index 00000000000..7b84436ad57
--- /dev/null
+++ b/config/metrics/counts_28d/20220708173741_i_code_review_merge_request_widget_test_summary_expand_failed_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_failed_monthly
+description: The count of unique users (monthly) who expanded the Test Summary widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220715195415_p_ci_templates_security_fortify_fod_sast_monthly.yml b/config/metrics/counts_28d/20220715195415_p_ci_templates_security_fortify_fod_sast_monthly.yml
new file mode 100644
index 00000000000..27c387dc423
--- /dev/null
+++ b/config/metrics/counts_28d/20220715195415_p_ci_templates_security_fortify_fod_sast_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_fortify_fod_sast_monthly
+description: Count of pipelines using the Fortify FoD SAST template
+product_section: sec
+product_stage: secure
+product_group: static_analysis
+product_category: SAST
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
+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_fortify_fod_sast
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
new file mode 100644
index 00000000000..56c9fb62bd3
--- /dev/null
+++ b/config/metrics/counts_28d/20220719133315_p_ci_templates_implicit_security_fortify_fod_sast_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_fortify_fod_sast_monthly
+description: Count of pipelines with implicit runs using the Fortify FoD SAST template
+product_section: sec
+product_stage: secure
+product_group: static_analysis
+product_category: SAST
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
+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_fortify_fod_sast
diff --git a/config/metrics/counts_28d/20220725193059_users_updating_work_item_dates_monthly.yml b/config/metrics/counts_28d/20220725193059_users_updating_work_item_dates_monthly.yml
new file mode 100644
index 00000000000..8e214153e9d
--- /dev/null
+++ b/config/metrics/counts_28d/20220725193059_users_updating_work_item_dates_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_dates_monthly
+description: Unique users updating a work item's date
+product_category: team_planning
+product_section: dev
+product_stage: plan
+product_group: project_management
+value_type: number
+status: active
+milestone: '15.3'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93231
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_dates
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210913_i_code_review_merge_request_widget_accessibility_view_monthly.yml b/config/metrics/counts_28d/20220725210913_i_code_review_merge_request_widget_accessibility_view_monthly.yml
new file mode 100644
index 00000000000..aa17e1ccf55
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210913_i_code_review_merge_request_widget_accessibility_view_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_view_monthly
+description: The count of unique users (monthly) who were able to see the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210919_i_code_review_merge_request_widget_accessibility_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220725210919_i_code_review_merge_request_widget_accessibility_full_report_clicked_monthly.yml
new file mode 100644
index 00000000000..ad86cccdf72
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210919_i_code_review_merge_request_widget_accessibility_full_report_clicked_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_full_report_clicked_monthly
+description: The count of unique users (monthly) who clicked the Full Report button on the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210926_i_code_review_merge_request_widget_accessibility_expand_monthly.yml b/config/metrics/counts_28d/20220725210926_i_code_review_merge_request_widget_accessibility_expand_monthly.yml
new file mode 100644
index 00000000000..2e1ca0c8e70
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210926_i_code_review_merge_request_widget_accessibility_expand_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_monthly
+description: The count of unique users (monthly) who expanded the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210935_i_code_review_merge_request_widget_accessibility_expand_success_monthly.yml b/config/metrics/counts_28d/20220725210935_i_code_review_merge_request_widget_accessibility_expand_success_monthly.yml
new file mode 100644
index 00000000000..79505bad72e
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210935_i_code_review_merge_request_widget_accessibility_expand_success_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_success_monthly
+description: The count of unique users (monthly) who expanded the Accessibility widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210942_i_code_review_merge_request_widget_accessibility_expand_warning_monthly.yml b/config/metrics/counts_28d/20220725210942_i_code_review_merge_request_widget_accessibility_expand_warning_monthly.yml
new file mode 100644
index 00000000000..78009cb34c3
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210942_i_code_review_merge_request_widget_accessibility_expand_warning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_warning_monthly
+description: The count of unique users (monthly) who expanded the Accessibility widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220725210949_i_code_review_merge_request_widget_accessibility_expand_failed_monthly.yml b/config/metrics/counts_28d/20220725210949_i_code_review_merge_request_widget_accessibility_expand_failed_monthly.yml
new file mode 100644
index 00000000000..e4ba9b8f53b
--- /dev/null
+++ b/config/metrics/counts_28d/20220725210949_i_code_review_merge_request_widget_accessibility_expand_failed_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_failed_monthly
+description: The count of unique users (monthly) who expanded the Accessibility widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020440_i_code_review_merge_request_widget_code_quality_view_monthly.yml b/config/metrics/counts_28d/20220727020440_i_code_review_merge_request_widget_code_quality_view_monthly.yml
new file mode 100644
index 00000000000..a73f6a919ea
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020440_i_code_review_merge_request_widget_code_quality_view_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_view_monthly
+description: The count of unique users (monthly) who were able to see the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020446_i_code_review_merge_request_widget_code_quality_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220727020446_i_code_review_merge_request_widget_code_quality_full_report_clicked_monthly.yml
new file mode 100644
index 00000000000..3fbd759deab
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020446_i_code_review_merge_request_widget_code_quality_full_report_clicked_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_full_report_clicked_monthly
+description: The count of unique users (monthly) who clicked the Full Report button on the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020452_i_code_review_merge_request_widget_code_quality_expand_monthly.yml b/config/metrics/counts_28d/20220727020452_i_code_review_merge_request_widget_code_quality_expand_monthly.yml
new file mode 100644
index 00000000000..3b4686c28cc
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020452_i_code_review_merge_request_widget_code_quality_expand_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_monthly
+description: The count of unique users (monthly) who expanded the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020457_i_code_review_merge_request_widget_code_quality_expand_success_monthly.yml b/config/metrics/counts_28d/20220727020457_i_code_review_merge_request_widget_code_quality_expand_success_monthly.yml
new file mode 100644
index 00000000000..e36a74550d4
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020457_i_code_review_merge_request_widget_code_quality_expand_success_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_success_monthly
+description: The count of unique users (monthly) who expanded the Code Quality widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020503_i_code_review_merge_request_widget_code_quality_expand_warning_monthly.yml b/config/metrics/counts_28d/20220727020503_i_code_review_merge_request_widget_code_quality_expand_warning_monthly.yml
new file mode 100644
index 00000000000..181c06ec06f
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020503_i_code_review_merge_request_widget_code_quality_expand_warning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_warning_monthly
+description: The count of unique users (monthly) who expanded the Code Quality widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727020509_i_code_review_merge_request_widget_code_quality_expand_failed_monthly.yml b/config/metrics/counts_28d/20220727020509_i_code_review_merge_request_widget_code_quality_expand_failed_monthly.yml
new file mode 100644
index 00000000000..5e4e6221142
--- /dev/null
+++ b/config/metrics/counts_28d/20220727020509_i_code_review_merge_request_widget_code_quality_expand_failed_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_failed_monthly
+description: The count of unique users (monthly) who expanded the Code Quality widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045317_i_code_review_merge_request_widget_terraform_view_monthly.yml b/config/metrics/counts_28d/20220727045317_i_code_review_merge_request_widget_terraform_view_monthly.yml
new file mode 100644
index 00000000000..c18e947f722
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045317_i_code_review_merge_request_widget_terraform_view_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_view_monthly
+description: The count of unique users (monthly) who were able to see the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045323_i_code_review_merge_request_widget_terraform_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220727045323_i_code_review_merge_request_widget_terraform_full_report_clicked_monthly.yml
new file mode 100644
index 00000000000..1791ba6d4cf
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045323_i_code_review_merge_request_widget_terraform_full_report_clicked_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_full_report_clicked_monthly
+description: The count of unique users (monthly) who clicked the Full Report button on the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045330_i_code_review_merge_request_widget_terraform_expand_monthly.yml b/config/metrics/counts_28d/20220727045330_i_code_review_merge_request_widget_terraform_expand_monthly.yml
new file mode 100644
index 00000000000..67f73ee4122
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045330_i_code_review_merge_request_widget_terraform_expand_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_monthly
+description: The count of unique users (monthly) who expanded the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045336_i_code_review_merge_request_widget_terraform_expand_success_monthly.yml b/config/metrics/counts_28d/20220727045336_i_code_review_merge_request_widget_terraform_expand_success_monthly.yml
new file mode 100644
index 00000000000..a374ed99263
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045336_i_code_review_merge_request_widget_terraform_expand_success_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_success_monthly
+description: The count of unique users (monthly) who expanded the Terraform widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045342_i_code_review_merge_request_widget_terraform_expand_warning_monthly.yml b/config/metrics/counts_28d/20220727045342_i_code_review_merge_request_widget_terraform_expand_warning_monthly.yml
new file mode 100644
index 00000000000..909211e2a35
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045342_i_code_review_merge_request_widget_terraform_expand_warning_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_warning_monthly
+description: The count of unique users (monthly) who expanded the Terraform widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220727045349_i_code_review_merge_request_widget_terraform_expand_failed_monthly.yml b/config/metrics/counts_28d/20220727045349_i_code_review_merge_request_widget_terraform_expand_failed_monthly.yml
new file mode 100644
index 00000000000..a1d247d405f
--- /dev/null
+++ b/config/metrics/counts_28d/20220727045349_i_code_review_merge_request_widget_terraform_expand_failed_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_failed_monthly
+description: The count of unique users (monthly) who expanded the Terraform widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_28d/20220729001651_agent_users_using_ci_tunnel_monthly.yml b/config/metrics/counts_28d/20220729001651_agent_users_using_ci_tunnel_monthly.yml
new file mode 100644
index 00000000000..8fc01895a1d
--- /dev/null
+++ b/config/metrics/counts_28d/20220729001651_agent_users_using_ci_tunnel_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.kubernetes_agent.agent_users_using_ci_tunnel_monthly
+description: MAU of the Agent for Kubernetes CI/CD Tunnel
+product_section: ops
+product_stage: configure
+product_group: configure
+product_category: kubernetes_management
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - agent_users_using_ci_tunnel
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml
index 6ad3e8e0c16..7bc0d698f3a 100644
--- a/config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216180620_incident_management_total_unique_counts_weekly.yml
@@ -27,6 +27,9 @@ options:
- incident_management_alert_status_changed
- incident_management_alert_assigned
- incident_management_alert_todo
+ - incident_management_timeline_event_created
+ - incident_management_timeline_event_edited
+ - incident_management_timeline_event_deleted
distribution:
- ce
- ee
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 d67dc70f013..964297bde96 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
@@ -20,7 +20,6 @@ options:
- incident_management_timeline_event_edited
- incident_management_timeline_event_deleted
performance_indicator_type:
- - smau
- gmau
- paid_gmau
distribution:
diff --git a/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml b/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml
new file mode 100644
index 00000000000..a1cf41b62f0
--- /dev/null
+++ b/config/metrics/counts_7d/20220708162305_i_code_review_merge_request_widget_test_summary_view_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_view_weekly
+description: The count of unique users (weekly) who were able to see the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml
new file mode 100644
index 00000000000..73c5799d984
--- /dev/null
+++ b/config/metrics/counts_7d/20220708163619_i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_full_report_clicked_weekly
+description: The count of unique users (weekly) who clicked the Full Report button on the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml b/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml
new file mode 100644
index 00000000000..a3616e92e6f
--- /dev/null
+++ b/config/metrics/counts_7d/20220708164539_i_code_review_merge_request_widget_test_summary_expand_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_weekly
+description: The count of unique users (weekly) who expanded the Test Summary widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml b/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml
new file mode 100644
index 00000000000..728ca303438
--- /dev/null
+++ b/config/metrics/counts_7d/20220708165632_i_code_review_merge_request_widget_test_summary_expand_success_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_success_weekly
+description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml b/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml
new file mode 100644
index 00000000000..70a2bab68d8
--- /dev/null
+++ b/config/metrics/counts_7d/20220708170508_i_code_review_merge_request_widget_test_summary_expand_warning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_warning_weekly
+description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml b/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml
new file mode 100644
index 00000000000..a25ac7de33c
--- /dev/null
+++ b/config/metrics/counts_7d/20220708173736_i_code_review_merge_request_widget_test_summary_expand_failed_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_test_summary_expand_failed_weekly
+description: The count of unique users (weekly) who expanded the Test Summary widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220715195411_p_ci_templates_security_fortify_fod_sast_weekly.yml b/config/metrics/counts_7d/20220715195411_p_ci_templates_security_fortify_fod_sast_weekly.yml
new file mode 100644
index 00000000000..6ee30064f91
--- /dev/null
+++ b/config/metrics/counts_7d/20220715195411_p_ci_templates_security_fortify_fod_sast_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_fortify_fod_sast_weekly
+description: Count of pipelines using the Fortify FoD SAST template
+product_section: sec
+product_stage: secure
+product_group: static_analysis
+product_category: SAST
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_security_fortify_fod_sast
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
new file mode 100644
index 00000000000..4f3cfcc25d4
--- /dev/null
+++ b/config/metrics/counts_7d/20220719133311_p_ci_templates_implicit_security_fortify_fod_sast_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_fortify_fod_sast_weekly
+description: Count of pipelines with implicit runs using the Fortify FoD SAST template
+product_section: sec
+product_stage: secure
+product_group: static_analysis
+product_category: SAST
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91956
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_security_fortify_fod_sast
diff --git a/config/metrics/counts_7d/20220725201348_users_updating_work_item_dates_weekly.yml b/config/metrics/counts_7d/20220725201348_users_updating_work_item_dates_weekly.yml
new file mode 100644
index 00000000000..eaed8420bdb
--- /dev/null
+++ b/config/metrics/counts_7d/20220725201348_users_updating_work_item_dates_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.work_items.users_updating_work_item_dates_weekly
+description: Unique users updating a work item's date
+product_category: team_planning
+product_section: dev
+product_stage: plan
+product_group: project_management
+value_type: number
+status: active
+milestone: '15.3'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93231
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_updating_work_item_dates
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210831_i_code_review_merge_request_widget_accessibility_view_weekly.yml b/config/metrics/counts_7d/20220725210831_i_code_review_merge_request_widget_accessibility_view_weekly.yml
new file mode 100644
index 00000000000..72b59b312e3
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210831_i_code_review_merge_request_widget_accessibility_view_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_view_weekly
+description: The count of unique users (weekly) who were able to see the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210838_i_code_review_merge_request_widget_accessibility_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220725210838_i_code_review_merge_request_widget_accessibility_full_report_clicked_weekly.yml
new file mode 100644
index 00000000000..3d247a80f1e
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210838_i_code_review_merge_request_widget_accessibility_full_report_clicked_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_full_report_clicked_weekly
+description: The count of unique users (weekly) who clicked the Full Report button on the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210845_i_code_review_merge_request_widget_accessibility_expand_weekly.yml b/config/metrics/counts_7d/20220725210845_i_code_review_merge_request_widget_accessibility_expand_weekly.yml
new file mode 100644
index 00000000000..7dc508c1faf
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210845_i_code_review_merge_request_widget_accessibility_expand_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_weekly
+description: The count of unique users (weekly) who expanded the Accessibility widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210851_i_code_review_merge_request_widget_accessibility_expand_success_weekly.yml b/config/metrics/counts_7d/20220725210851_i_code_review_merge_request_widget_accessibility_expand_success_weekly.yml
new file mode 100644
index 00000000000..f8f7f01b4bd
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210851_i_code_review_merge_request_widget_accessibility_expand_success_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_success_weekly
+description: The count of unique users (weekly) who expanded the Accessibility widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210858_i_code_review_merge_request_widget_accessibility_expand_warning_weekly.yml b/config/metrics/counts_7d/20220725210858_i_code_review_merge_request_widget_accessibility_expand_warning_weekly.yml
new file mode 100644
index 00000000000..ad7e54291b5
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210858_i_code_review_merge_request_widget_accessibility_expand_warning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_warning_weekly
+description: The count of unique users (weekly) who expanded the Accessibility widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220725210906_i_code_review_merge_request_widget_accessibility_expand_failed_weekly.yml b/config/metrics/counts_7d/20220725210906_i_code_review_merge_request_widget_accessibility_expand_failed_weekly.yml
new file mode 100644
index 00000000000..e617afa70f6
--- /dev/null
+++ b/config/metrics/counts_7d/20220725210906_i_code_review_merge_request_widget_accessibility_expand_failed_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_accessibility_expand_failed_weekly
+description: The count of unique users (weekly) who expanded the Accessibility widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020407_i_code_review_merge_request_widget_code_quality_view_weekly.yml b/config/metrics/counts_7d/20220727020407_i_code_review_merge_request_widget_code_quality_view_weekly.yml
new file mode 100644
index 00000000000..029103609cd
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020407_i_code_review_merge_request_widget_code_quality_view_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_view_weekly
+description: The count of unique users (weekly) who were able to see the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020413_i_code_review_merge_request_widget_code_quality_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220727020413_i_code_review_merge_request_widget_code_quality_full_report_clicked_weekly.yml
new file mode 100644
index 00000000000..d6e9d88d395
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020413_i_code_review_merge_request_widget_code_quality_full_report_clicked_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_full_report_clicked_weekly
+description: The count of unique users (weekly) who clicked the Full Report button on the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020419_i_code_review_merge_request_widget_code_quality_expand_weekly.yml b/config/metrics/counts_7d/20220727020419_i_code_review_merge_request_widget_code_quality_expand_weekly.yml
new file mode 100644
index 00000000000..7d35f90ff4d
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020419_i_code_review_merge_request_widget_code_quality_expand_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_weekly
+description: The count of unique users (weekly) who expanded the Code Quality widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020424_i_code_review_merge_request_widget_code_quality_expand_success_weekly.yml b/config/metrics/counts_7d/20220727020424_i_code_review_merge_request_widget_code_quality_expand_success_weekly.yml
new file mode 100644
index 00000000000..a0c94702a5f
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020424_i_code_review_merge_request_widget_code_quality_expand_success_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_success_weekly
+description: The count of unique users (weekly) who expanded the Code Quality widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020429_i_code_review_merge_request_widget_code_quality_expand_warning_weekly.yml b/config/metrics/counts_7d/20220727020429_i_code_review_merge_request_widget_code_quality_expand_warning_weekly.yml
new file mode 100644
index 00000000000..c88c435eaf2
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020429_i_code_review_merge_request_widget_code_quality_expand_warning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_warning_weekly
+description: The count of unique users (weekly) who expanded the Code Quality widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727020435_i_code_review_merge_request_widget_code_quality_expand_failed_weekly.yml b/config/metrics/counts_7d/20220727020435_i_code_review_merge_request_widget_code_quality_expand_failed_weekly.yml
new file mode 100644
index 00000000000..4ef43c77c5d
--- /dev/null
+++ b/config/metrics/counts_7d/20220727020435_i_code_review_merge_request_widget_code_quality_expand_failed_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_code_quality_expand_failed_weekly
+description: The count of unique users (weekly) who expanded the Code Quality widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045240_i_code_review_merge_request_widget_terraform_view_weekly.yml b/config/metrics/counts_7d/20220727045240_i_code_review_merge_request_widget_terraform_view_weekly.yml
new file mode 100644
index 00000000000..26d4709a35b
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045240_i_code_review_merge_request_widget_terraform_view_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_view_weekly
+description: The count of unique users (weekly) who were able to see the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045246_i_code_review_merge_request_widget_terraform_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220727045246_i_code_review_merge_request_widget_terraform_full_report_clicked_weekly.yml
new file mode 100644
index 00000000000..85017ed6ae4
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045246_i_code_review_merge_request_widget_terraform_full_report_clicked_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_full_report_clicked_weekly
+description: The count of unique users (weekly) who clicked the Full Report button on the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045252_i_code_review_merge_request_widget_terraform_expand_weekly.yml b/config/metrics/counts_7d/20220727045252_i_code_review_merge_request_widget_terraform_expand_weekly.yml
new file mode 100644
index 00000000000..7a73af7a042
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045252_i_code_review_merge_request_widget_terraform_expand_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_weekly
+description: The count of unique users (weekly) who expanded the Terraform widget extension
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045258_i_code_review_merge_request_widget_terraform_expand_success_weekly.yml b/config/metrics/counts_7d/20220727045258_i_code_review_merge_request_widget_terraform_expand_success_weekly.yml
new file mode 100644
index 00000000000..b9c2593f3cc
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045258_i_code_review_merge_request_widget_terraform_expand_success_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_success_weekly
+description: The count of unique users (weekly) who expanded the Terraform widget extension while it is in its Success state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045304_i_code_review_merge_request_widget_terraform_expand_warning_weekly.yml b/config/metrics/counts_7d/20220727045304_i_code_review_merge_request_widget_terraform_expand_warning_weekly.yml
new file mode 100644
index 00000000000..8eaff0bd1ea
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045304_i_code_review_merge_request_widget_terraform_expand_warning_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_warning_weekly
+description: The count of unique users (weekly) who expanded the Terraform widget extension while it is in its Warning state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220727045311_i_code_review_merge_request_widget_terraform_expand_failed_weekly.yml b/config/metrics/counts_7d/20220727045311_i_code_review_merge_request_widget_terraform_expand_failed_weekly.yml
new file mode 100644
index 00000000000..55de00b858c
--- /dev/null
+++ b/config/metrics/counts_7d/20220727045311_i_code_review_merge_request_widget_terraform_expand_failed_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_terraform_expand_failed_weekly
+description: The count of unique users (weekly) who expanded the Terraform widget extension while it is in its Failed state
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_7d/20220729001644_agent_users_using_ci_tunnel_weekly.yml b/config/metrics/counts_7d/20220729001644_agent_users_using_ci_tunnel_weekly.yml
new file mode 100644
index 00000000000..cd18a2433de
--- /dev/null
+++ b/config/metrics/counts_7d/20220729001644_agent_users_using_ci_tunnel_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.kubernetes_agent.agent_users_using_ci_tunnel_weekly
+description: WAU of the Agent for Kubernetes CI/CD Tunnel
+product_section: ops
+product_stage: configure
+product_group: configure
+product_category: kubernetes_management
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+options:
+ events:
+ - agent_users_using_ci_tunnel
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20210216180752_keys.yml b/config/metrics/counts_all/20210216180752_keys.yml
index f6de1a1fdd1..dad2a777d26 100644
--- a/config/metrics/counts_all/20210216180752_keys.yml
+++ b/config/metrics/counts_all/20210216180752_keys.yml
@@ -3,7 +3,7 @@ data_category: optional
key_path: counts.keys
description: Number of keys.
product_section: dev
-product_stage: managed
+product_stage: manage
product_group: authentication_and_authorization
product_category: authentication_and_authorization
value_type: number
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
new file mode 100644
index 00000000000..79d9f062999
--- /dev/null
+++ b/config/metrics/counts_all/20220708154149_i_code_review_merge_request_widget_test_summary_count_view.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_view
+description: Total number of times the Test Summary widget extension was viewed (rendered to the screen)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..b4887bbe219
--- /dev/null
+++ b/config/metrics/counts_all/20220708154156_i_code_review_merge_request_widget_test_summary_count_full_report_clicked.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_full_report_clicked
+description: Total number of times the Test Summary widget extension Full Report button was clicked
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..1898fa971fa
--- /dev/null
+++ b/config/metrics/counts_all/20220708154201_i_code_review_merge_request_widget_test_summary_count_expand.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand
+description: Total number of times the Test Summary widget extension was expanded (in any state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..91cd4d7a232
--- /dev/null
+++ b/config/metrics/counts_all/20220708154206_i_code_review_merge_request_widget_test_summary_count_expand_success.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_success
+description: Total number of times the Test Summary widget extension was expanded (while in its Success state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..970d843c58e
--- /dev/null
+++ b/config/metrics/counts_all/20220708154211_i_code_review_merge_request_widget_test_summary_count_expand_warning.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_warning
+description: Total number of times the Test Summary widget extension was expanded (while in its Warning state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..9b7c5c61602
--- /dev/null
+++ b/config/metrics/counts_all/20220708154216_i_code_review_merge_request_widget_test_summary_count_expand_failed.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_test_summary_count_expand_failed
+description: Total number of times the Test Summary widget extension was expanded (while in its Failed state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.2"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91831"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_test_summary_count_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..215bf8f0a1b
--- /dev/null
+++ b/config/metrics/counts_all/20220725205853_i_code_review_merge_request_widget_accessibility_count_view.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_view
+description: Total number of times the Accessibility widget extension was viewed (rendered to the screen)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..a8792444287
--- /dev/null
+++ b/config/metrics/counts_all/20220725205901_i_code_review_merge_request_widget_accessibility_count_full_report_clicked.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_full_report_clicked
+description: Total number of times the Accessibility widget extension Full Report button was clicked
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..d5679b65533
--- /dev/null
+++ b/config/metrics/counts_all/20220725205908_i_code_review_merge_request_widget_accessibility_count_expand.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_expand
+description: Total number of times the Accessibility widget extension was expanded (in any state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..25ef6ab85ca
--- /dev/null
+++ b/config/metrics/counts_all/20220725205915_i_code_review_merge_request_widget_accessibility_count_expand_success.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_expand_success
+description: Total number of times the Accessibility widget extension was expanded (while in its Success state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..7939fb8ac7f
--- /dev/null
+++ b/config/metrics/counts_all/20220725205922_i_code_review_merge_request_widget_accessibility_count_expand_warning.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_expand_warning
+description: Total number of times the Accessibility widget extension was expanded (while in its Warning state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..9e348eb8e27
--- /dev/null
+++ b/config/metrics/counts_all/20220725205928_i_code_review_merge_request_widget_accessibility_count_expand_failed.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_accessibility_count_expand_failed
+description: Total number of times the Accessibility widget extension was expanded (while in its Failed state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93232"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_accessibility_count_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..1687d346e34
--- /dev/null
+++ b/config/metrics/counts_all/20220727004434_i_code_review_merge_request_widget_code_quality_count_view.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_view
+description: Total number of times the Code Quality widget extension was viewed (rendered to the screen)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..21ff87b8e39
--- /dev/null
+++ b/config/metrics/counts_all/20220727004440_i_code_review_merge_request_widget_code_quality_count_full_report_clicked.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_full_report_clicked
+description: Total number of times the Code Quality widget extension Full Report button was clicked
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..49123b462d9
--- /dev/null
+++ b/config/metrics/counts_all/20220727004446_i_code_review_merge_request_widget_code_quality_count_expand.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_expand
+description: Total number of times the Code Quality widget extension was expanded (in any state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..8b349e04d21
--- /dev/null
+++ b/config/metrics/counts_all/20220727004451_i_code_review_merge_request_widget_code_quality_count_expand_success.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_expand_success
+description: Total number of times the Code Quality widget extension was expanded (while in its Success state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..e94c6999711
--- /dev/null
+++ b/config/metrics/counts_all/20220727004457_i_code_review_merge_request_widget_code_quality_count_expand_warning.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_expand_warning
+description: Total number of times the Code Quality widget extension was expanded (while in its Warning state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..5e49393afff
--- /dev/null
+++ b/config/metrics/counts_all/20220727004502_i_code_review_merge_request_widget_code_quality_count_expand_failed.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_code_quality_count_expand_failed
+description: Total number of times the Code Quality widget extension was expanded (while in its Failed state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93333"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_code_quality_count_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..f523b91b5d9
--- /dev/null
+++ b/config/metrics/counts_all/20220727044257_i_code_review_merge_request_widget_terraform_count_view.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_view
+description: Total number of times the Terraform widget extension was viewed (rendered to the screen)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_view
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..53eb5770ed5
--- /dev/null
+++ b/config/metrics/counts_all/20220727044304_i_code_review_merge_request_widget_terraform_count_full_report_clicked.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_full_report_clicked
+description: Total number of times the Terraform widget extension Full Report button was clicked
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_full_report_clicked
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..0406b84d457
--- /dev/null
+++ b/config/metrics/counts_all/20220727044310_i_code_review_merge_request_widget_terraform_count_expand.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_expand
+description: Total number of times the Terraform widget extension was expanded (in any state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_expand
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..c497758b543
--- /dev/null
+++ b/config/metrics/counts_all/20220727044316_i_code_review_merge_request_widget_terraform_count_expand_success.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_expand_success
+description: Total number of times the Terraform widget extension was expanded (while in its Success state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_expand_success
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..1a0a112dc89
--- /dev/null
+++ b/config/metrics/counts_all/20220727044322_i_code_review_merge_request_widget_terraform_count_expand_warning.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_expand_warning
+description: Total number of times the Terraform widget extension was expanded (while in its Warning state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_expand_warning
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
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
new file mode 100644
index 00000000000..3e1ac7db1d5
--- /dev/null
+++ b/config/metrics/counts_all/20220727044329_i_code_review_merge_request_widget_terraform_count_expand_failed.yml
@@ -0,0 +1,24 @@
+---
+key_path: counts.i_code_review_merge_request_widget_terraform_count_expand_failed
+description: Total number of times the Terraform widget extension was expanded (while in its Failed state)
+product_section: dev
+product_stage: create
+product_group: code_review
+product_category: code_review
+value_type: number
+status: active
+milestone: "15.3"
+introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93340"
+time_frame: all
+data_source: redis
+data_category: optional
+options:
+ events:
+ - i_code_review_merge_request_widget_terraform_count_expand_failed
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20220802141715_groups_inheriting_pumble_active.yml b/config/metrics/counts_all/20220802141715_groups_inheriting_pumble_active.yml
new file mode 100644
index 00000000000..960f859b07f
--- /dev/null
+++ b/config/metrics/counts_all/20220802141715_groups_inheriting_pumble_active.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.groups_inheriting_pumble_active
+description: Count of active groups inheriting integrations for Pumble
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "15.3"
diff --git a/config/metrics/counts_all/20220802141715_groups_pumble_active.yml b/config/metrics/counts_all/20220802141715_groups_pumble_active.yml
new file mode 100644
index 00000000000..3a62a002f10
--- /dev/null
+++ b/config/metrics/counts_all/20220802141715_groups_pumble_active.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.groups_pumble_active
+description: Count of groups with active integrations for Pumble
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "15.3"
diff --git a/config/metrics/counts_all/20220802141715_instances_pumble_active.yml b/config/metrics/counts_all/20220802141715_instances_pumble_active.yml
new file mode 100644
index 00000000000..d313ee39b31
--- /dev/null
+++ b/config/metrics/counts_all/20220802141715_instances_pumble_active.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.instances_pumble_active
+description: Count of active instance-level integrations for Pumble
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "15.3"
diff --git a/config/metrics/counts_all/20220802141715_projects_inheriting_pumble_active.yml b/config/metrics/counts_all/20220802141715_projects_inheriting_pumble_active.yml
new file mode 100644
index 00000000000..ae928de6140
--- /dev/null
+++ b/config/metrics/counts_all/20220802141715_projects_inheriting_pumble_active.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.projects_inheriting_pumble_active
+description: Count of active projects inheriting integrations for Pumble
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "15.3"
diff --git a/config/metrics/counts_all/20220802141715_projects_pumble_active.yml b/config/metrics/counts_all/20220802141715_projects_pumble_active.yml
new file mode 100644
index 00000000000..5f352a1cae4
--- /dev/null
+++ b/config/metrics/counts_all/20220802141715_projects_pumble_active.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: counts.projects_pumble_active
+description: Count of projects with active integrations for Pumble
+product_section: dev
+product_stage: ecosystem
+product_group: integrations
+product_category: integrations
+value_type: number
+status: active
+time_frame: all
+data_source: database
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+performance_indicator_type: []
+milestone: "15.3"
diff --git a/config/routes.rb b/config/routes.rb
index dd3095f0a8d..ddc7b77460c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -25,10 +25,10 @@ InitializerConnections.with_disabled_database_connections do
use_doorkeeper do
controllers applications: 'oauth/applications',
- authorized_applications: 'oauth/authorized_applications',
- authorizations: 'oauth/authorizations',
- token_info: 'oauth/token_info',
- tokens: 'oauth/tokens'
+ authorized_applications: 'oauth/authorized_applications',
+ authorizations: 'oauth/authorizations',
+ token_info: 'oauth/token_info',
+ tokens: 'oauth/tokens'
end
# This prefixless path is required because Jira gets confused if we set it up with a path
@@ -88,6 +88,10 @@ InitializerConnections.with_disabled_database_connections do
get 'search/count' => 'search#count', as: :search_count
get 'search/opensearch' => 'search#opensearch', as: :search_opensearch
+ Gitlab.ee do
+ get 'search/aggregations' => 'search#aggregations', as: :search_aggregations
+ end
+
# JSON Web Token
get 'jwt/auth' => 'jwt#auth'
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index bbf00cd0b00..2f4e286f5eb 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -65,6 +65,7 @@ namespace :admin do
resource :avatar, controller: 'topics/avatars', only: [:destroy]
collection do
post :preview_markdown
+ post :merge
end
end
diff --git a/config/routes/development.rb b/config/routes/development.rb
index 4ea53e14120..34f4eb5556b 100644
--- a/config/routes/development.rb
+++ b/config/routes/development.rb
@@ -12,4 +12,5 @@ if Rails.env.development?
get '/rails/info' => 'rails/info#index'
mount LetterOpenerWeb::Engine, at: '/rails/letter_opener'
+ mount Lookbook::Engine, at: '/rails/lookbook'
end
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
index b8d4a0c49c2..91f6eb678e4 100644
--- a/config/routes/profile.rb
+++ b/config/routes/profile.rb
@@ -23,10 +23,10 @@ resource :profile, only: [:show, :update] do
resource :notifications, only: [:show, :update] do
scope(path: 'groups/*id',
- id: Gitlab::PathRegex.full_namespace_route_regex,
- as: :group,
- controller: :groups,
- constraints: { format: /(html|json)/ }) do
+ id: Gitlab::PathRegex.full_namespace_route_regex,
+ as: :group,
+ controller: :groups,
+ constraints: { format: /(html|json)/ }) do
patch '/', action: :update
put '/', action: :update
end
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 5eb0b9396c9..53d9be13611 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -29,7 +29,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# "Route Globbing" syntax (/*page) so that the route helpers do not encode
# the slash character.
get 'metrics(/:dashboard_path)(/*page)', constraints: { dashboard_path: /.+\.yml/, page: 'panel/new' },
- to: 'metrics_dashboard#show', as: :metrics_dashboard, format: false
+ to: 'metrics_dashboard#show', as: :metrics_dashboard, format: false
namespace :metrics, module: :metrics do
namespace :dashboards do
@@ -96,7 +96,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
namespace :ci do
resource :lint, only: [:show, :create]
resource :pipeline_editor, only: [:show], controller: :pipeline_editor, path: 'editor'
- resource :secure_files, only: [:show], controller: :secure_files, path: 'secure_files'
resources :daily_build_group_report_results, only: [:index], constraints: { format: /(csv|json)/ }
namespace :prometheus_metrics do
resources :histograms, only: [:create], constraints: { format: 'json' }
@@ -157,7 +156,9 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resource :packages_and_registries, only: [:show]
+ resource :packages_and_registries, only: [:show] do
+ get '/cleanup_image_tags', to: 'packages_and_registries#cleanup_tags'
+ end
end
resources :usage_quotas, only: [:index]
@@ -299,6 +300,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :terraform, only: [:index]
namespace :google_cloud do
+ get '/', to: redirect('%{namespace_id}/%{project_id}/-/google_cloud/configuration')
+
get '/configuration', to: 'configuration#index'
resources :revoke_oauth, only: [:create]
@@ -358,6 +361,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'alert_management/:id', to: 'alert_management#details', as: 'alert_management_alert'
get 'work_items/*work_items_path' => 'work_items#index', as: :work_items
+ get 'work_items/*work_items_path' => 'work_items#index', as: :work_item
post 'incidents/integrations/pagerduty', to: 'incident_management/pager_duty_incidents#create'
@@ -499,7 +503,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
defaults: { format: 'json' },
constraints: { template_type: %r{issue|merge_request}, format: 'json' }
- resource :pages, only: [:show, :update, :destroy] do # rubocop: disable Cop/PutProjectRoutesUnderScope
+ resource :pages, only: [:new, :show, :update, :destroy] do # rubocop: disable Cop/PutProjectRoutesUnderScope
resources :domains, except: :index, controller: 'pages_domains', constraints: { id: %r{[^/]+} } do # rubocop: disable Cop/PutProjectRoutesUnderScope
member do
post :verify # rubocop:todo Cop/PutProjectRoutesUnderScope
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 74e72927699..0202eb80b23 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -51,10 +51,7 @@ scope format: false do
end
delete :merged_branches, controller: 'branches', action: :destroy_all_merged
- resources :tags, only: [:index, :show, :new, :create, :destroy] do
- resource :release, controller: 'tags/releases', only: [:edit, :update]
- end
-
+ resources :tags, only: [:index, :show, :new, :create, :destroy]
resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex }
resources :protected_tags, only: [:index, :show, :create, :update, :destroy]
end
diff --git a/config/routes/unmatched_project.rb b/config/routes/unmatched_project.rb
index b4fe243c7b0..3f94af33e18 100644
--- a/config/routes/unmatched_project.rb
+++ b/config/routes/unmatched_project.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
scope(path: '*namespace_id',
- as: :namespace,
- namespace_id: Gitlab::PathRegex.full_namespace_route_regex) do
+ as: :namespace,
+ namespace_id: Gitlab::PathRegex.full_namespace_route_regex) do
scope(path: ':project_id',
- constraints: { project_id: Gitlab::PathRegex.project_route_regex },
- as: :project) do
+ constraints: { project_id: Gitlab::PathRegex.project_route_regex },
+ as: :project) do
post '*all', to: 'application#route_not_found'
put '*all', to: 'application#route_not_found'
patch '*all', to: 'application#route_not_found'
diff --git a/config/routes/uploads.rb b/config/routes/uploads.rb
index a72730c1214..ba2e8493ef9 100644
--- a/config/routes/uploads.rb
+++ b/config/routes/uploads.rb
@@ -3,8 +3,8 @@
scope path: :uploads do
# Note attachments and User/Group/Project/Topic avatars
get "-/system/:model/:mounted_as/:id/:filename",
- to: "uploads#show",
- constraints: { model: %r{note|user|group|project|projects\/topic}, mounted_as: /avatar|attachment/, filename: %r{[^/]+} }
+ to: "uploads#show",
+ constraints: { model: %r{note|user|group|project|projects\/topic}, mounted_as: /avatar|attachment/, filename: %r{[^/]+} }
# show uploads for models, snippets (notes) available for now
get '-/system/:model/:id/:secret/:filename',
@@ -18,8 +18,8 @@ scope path: :uploads do
# Appearance
get "-/system/:model/:mounted_as/:id/:filename",
- to: "uploads#show",
- constraints: { model: /appearance/, mounted_as: /logo|header_logo|favicon/, filename: /.+/ },
+ to: "uploads#show",
+ constraints: { model: /appearance/, mounted_as: /logo|header_logo|favicon/, filename: /.+/ },
as: 'appearance_upload'
# Project markdown uploads
@@ -27,7 +27,7 @@ scope path: :uploads do
# https://gitlab.com/gitlab-org/gitlab/issues/196396
get ":namespace_id/:project_id/:secret/:filename",
to: redirect("%{namespace_id}/%{project_id}/uploads/%{secret}/%{filename}"),
- constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: %r{[^/]+} }, format: false, defaults: { format: nil }
+ constraints: { namespace_id: /[a-zA-Z.0-9_\-]+/, project_id: /[a-zA-Z.0-9_\-]+/, filename: %r{[^/]+} }, format: false, defaults: { format: nil }
# create uploads for models, snippets (notes) available for now
post ':model',
@@ -41,12 +41,12 @@ scope path: :uploads do
# Alert Metric Images
get "-/system/:model/:mounted_as/:id/:filename",
- to: "uploads#show",
- constraints: { model: /alert_management_metric_image/, mounted_as: /file/, filename: %r{[^/]+} },
+ to: "uploads#show",
+ constraints: { model: /alert_management_metric_image/, mounted_as: /file/, filename: %r{[^/]+} },
as: 'alert_metric_image_upload'
end
# Redirect old note attachments path to new uploads path.
get "files/note/:id/:filename",
- to: redirect("uploads/note/attachment/%{id}/%{filename}"),
- constraints: { filename: %r{[^/]+} }
+ to: redirect("uploads/note/attachment/%{id}/%{filename}"),
+ constraints: { filename: %r{[^/]+} }
diff --git a/config/routes/user.rb b/config/routes/user.rb
index 96e8c850da4..a9e0d7df88f 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -64,7 +64,9 @@ 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
scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) do
diff --git a/config/settings.rb b/config/settings.rb
index 35c8ad72bcf..51d54817646 100644
--- a/config/settings.rb
+++ b/config/settings.rb
@@ -109,7 +109,11 @@ class Settings < Settingslogic
constant = modul.constants.find { |name| modul.const_get(name, false) == current }
value = constant.nil? ? default : modul.const_get(constant, false)
if current.is_a? String
- value = modul.const_get(current.upcase, false) rescue default
+ value = begin
+ modul.const_get(current.upcase, false)
+ rescue StandardError
+ default
+ end
end
value
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index c901ea09f4c..61e27f9aeb8 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -87,14 +87,20 @@
- 2
- - ci_batch_reset_minutes
- 1
+- - ci_cancel_pipeline
+ - 1
- - ci_delete_objects
- 1
- - ci_job_artifacts_expire_project_build_artifacts
- 1
+- - ci_runners_process_runner_version_update
+ - 1
- - ci_upstream_projects_subscriptions_cleanup
- 1
- - cluster_agent
- 1
+- - compliance_management_chain_of_custody_report
+ - 1
- - compliance_management_merge_requests_compliance_violations
- 1
- - container_repository
@@ -275,12 +281,22 @@
- 1
- - merge_requests_close_issue
- 1
+- - merge_requests_create_approval_event
+ - 1
+- - merge_requests_create_approval_note
+ - 1
- - merge_requests_delete_source_branch
- 1
+- - merge_requests_execute_approval_hooks
+ - 1
- - merge_requests_handle_assignees_change
- 1
- - merge_requests_resolve_todos
- 1
+- - merge_requests_resolve_todos_after_approval
+ - 1
+- - merge_requests_stream_approval_audit_event
+ - 1
- - merge_requests_sync_code_owner_approval_rules
- 1
- - merge_requests_update_head_pipeline
@@ -363,6 +379,8 @@
- 1
- - projects_git_garbage_collect
- 1
+- - projects_import_export_relation_export
+ - 1
- - projects_inactive_projects_deletion_notification
- 1
- - projects_post_creation
@@ -413,6 +431,8 @@
- 1
- - requirements_management_process_requirements_reports
- 1
+- - sbom_reports
+ - 1
- - security_auto_fix
- 1
- - security_findings_delete_by_job_id
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 3c1d7cbf631..0d759de4900 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -473,9 +473,7 @@ module.exports = {
new VueLoaderPlugin(),
// automatically configure monaco editor web workers
- new MonacoWebpackPlugin({
- globalAPI: true,
- }),
+ new MonacoWebpackPlugin(),
new GraphqlKnownOperationsPlugin({ filename: 'graphql_known_operations.yml' }),
@@ -557,6 +555,11 @@ module.exports = {
);
}),
+ new webpack.NormalModuleReplacementPlugin(/markdown-it/, (resource) => {
+ // eslint-disable-next-line no-param-reassign
+ resource.request = path.join(ROOT_PATH, 'app/assets/javascripts/lib/markdown_it.js');
+ }),
+
!IS_JH &&
new webpack.NormalModuleReplacementPlugin(/^jh_component\/(.*)\.vue/, (resource) => {
// eslint-disable-next-line no-param-reassign
diff --git a/config/webpack.vendor.config.js b/config/webpack.vendor.config.js
index ff38497a05e..903607679a4 100644
--- a/config/webpack.vendor.config.js
+++ b/config/webpack.vendor.config.js
@@ -41,7 +41,6 @@ module.exports = {
'three',
'select2',
'moment-mini',
- 'aws-sdk',
'dompurify',
'bootstrap/dist/js/bootstrap.js',
'sortablejs/modular/sortable.esm.js',
diff --git a/danger/customer_success/Dangerfile b/danger/customer_success/Dangerfile
new file mode 100644
index 00000000000..a9043e030a1
--- /dev/null
+++ b/danger/customer_success/Dangerfile
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+markdown(customer_success.build_message)
diff --git a/danger/plugins/customer_success.rb b/danger/plugins/customer_success.rb
new file mode 100644
index 00000000000..dad8174c311
--- /dev/null
+++ b/danger/plugins/customer_success.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/danger/customer_success'
+
+module Danger
+ class CustomerSuccess < ::Danger::Plugin
+ include Tooling::Danger::CustomerSuccess
+ end
+end
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 0e6af5792cd..c3f7806069c 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -55,7 +55,7 @@ end
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/growth/product-intelligence/engineers'),
+ 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')
}.freeze
diff --git a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
index 5a0fc88dad9..778744c9363 100644
--- a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
+++ b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
@@ -5,7 +5,7 @@
removal_date: "2022-11-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
breaking_change: false
body: | # Do not modify this line, instead modify the lines below.
- With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS on November 22, 2022. This was originally planned for May 22, 2022, but in an effort to allow continued maturity of Gitaly Cluster, we have chosen to extend our deprecation of support date. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for further information.
+ With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS on November 22, 2022. This was originally planned for May 22, 2022, but in an effort to allow continued maturity of Gitaly Cluster, we have chosen to extend our deprecation of support date. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support/#gitaly-and-nfs) for further information.
Gitaly Cluster offers tremendous benefits for our customers such as:
diff --git a/data/deprecations/14-7-deprecate-artifacts-keyword.yml b/data/deprecations/14-7-deprecate-artifacts-keyword.yml
index 29b5ec39193..26fd6b485df 100644
--- a/data/deprecations/14-7-deprecate-artifacts-keyword.yml
+++ b/data/deprecations/14-7-deprecate-artifacts-keyword.yml
@@ -3,7 +3,7 @@
announcement_date: "2022-01-22"
removal_milestone: "15.0"
removal_date: "2022-05-22"
- breaking_change: false
+ breaking_change: true
body: |
Currently, test coverage visualizations in GitLab only support Cobertura reports. Starting 15.0, the
`artifacts:reports:cobertura` keyword will be replaced by
diff --git a/data/deprecations/15-2-deprecation-vulnerability-report-state-sort.yml b/data/deprecations/15-2-deprecation-vulnerability-report-state-sort.yml
index 271e11f0d7f..058ff44d618 100644
--- a/data/deprecations/15-2-deprecation-vulnerability-report-state-sort.yml
+++ b/data/deprecations/15-2-deprecation-vulnerability-report-state-sort.yml
@@ -1,8 +1,8 @@
- name: "Vulnerability Report sort by State" # (required) The name of the feature to be deprecated
announcement_milestone: "15.0" # (required) The milestone when this feature was first announced as deprecated.
announcement_date: "2022-05-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
- removal_milestone: "15.2" # (required) The milestone when this feature is planned to be removed
- removal_date: "2022-07-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.3" # (required) The milestone when this feature is planned to be removed
+ removal_date: "2022-08-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: false # (required) If this deprecation is a breaking change, set this value to true
reporter: matt_wilson # (required) GitLab username of the person reporting the deprecation
stage: Secure # (required) String value of the stage that the feature was created in. e.g., Growth
@@ -10,8 +10,7 @@
body: | # (required) Do not modify this line, instead modify the lines below.
The ability to sort the Vulnerability Report by the `State` column was disabled and put behind a feature flag in GitLab 14.10 due to a refactor
of the underlying data model. The feature flag has remained off by default as further refactoring will be required to ensure sorting
- by this value remains performant. Due to very low usage of the `State` column for sorting, the feature flag will instead be removed in
- GitLab 15.2 to simplify the codebase and prevent any unwanted performance degradation.
+ by this value remains performant. Due to very low usage of the `State` column for sorting, the feature flag will instead be removed to simplify the codebase and prevent any unwanted performance degradation.
# The following items are not published on the docs page, but may be used in the future.
tiers: Ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: # (optional) This is a link to the current documentation page
diff --git a/data/deprecations/15-3-deprecate-redis-5.yml b/data/deprecations/15-3-deprecate-redis-5.yml
new file mode 100644
index 00000000000..f0e350cc62b
--- /dev/null
+++ b/data/deprecations/15-3-deprecate-redis-5.yml
@@ -0,0 +1,16 @@
+- name: "Redis 5 deprecated" # (required) The name of the feature to be deprecated
+ announcement_milestone: "15.3" # (required) The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-08-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
+ removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
+ reporter: tnir
+ stage: Enablement
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331468
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ With GitLab 13.9, in the Omnibus GitLab package and GitLab Helm chart 4.9, the Redis version [was updated to Redis 6](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#omnibus-improvements).
+ Redis 5 has reached the end of life in April 2022 and will no longer be supported as of GitLab 15.6.
+ If you are using your own Redis 5.0 instance, you should upgrade it to Redis 6.0 or higher before upgrading to GitLab 16.0 or higher.
+ end_of_support_milestone: "15.6"
+ end_of_support_date: "2022-11-22"
+ documentation_url: https://docs.gitlab.com/ee/install/requirements.html
diff --git a/data/deprecations/15-3-omniauth-cas3.yml b/data/deprecations/15-3-omniauth-cas3.yml
new file mode 100644
index 00000000000..156c89ed06b
--- /dev/null
+++ b/data/deprecations/15-3-omniauth-cas3.yml
@@ -0,0 +1,16 @@
+#
+# REQUIRED FIELDS
+#
+- name: "CAS OmniAuth provider" # (required) The name of the feature to be deprecated
+ announcement_milestone: "15.3" # (required) The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-08-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
+ removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
+ reporter: hsutor # (required) GitLab username of the person reporting the deprecation
+ stage: Manage # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369127 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ The `omniauth-cas3` gem that provides GitLab with the CAS OmniAuth provider will be removed in our next major
+ release, GitLab 16.0. This gem sees very little use and its lack of upstream maintenance is preventing GitLab's
+ [upgrade to OmniAuth 2.0](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
diff --git a/data/deprecations/15-3-omniauth-crowd.yml b/data/deprecations/15-3-omniauth-crowd.yml
new file mode 100644
index 00000000000..1f40ae73901
--- /dev/null
+++ b/data/deprecations/15-3-omniauth-crowd.yml
@@ -0,0 +1,17 @@
+#
+# REQUIRED FIELDS
+#
+- name: "Atlassian Crowd OmniAuth provider" # (required) The name of the feature to be deprecated
+ announcement_milestone: "15.3" # (required) The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-08-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
+ removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
+ reporter: hsutor # (required) GitLab username of the person reporting the deprecation
+ stage: Manage # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369117 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ The `omniauth_crowd` gem that provides GitLab with the Atlassian Crowd OmniAuth provider will be removed in our
+ next major release, GitLab 16.0. This gem sees very little use and its
+ [lack of compatibility](https://github.com/robdimarco/omniauth_crowd/issues/37) with OmniAuth 2.0 is
+ [blocking our upgrade](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
diff --git a/data/deprecations/15-3-pipeline_activity_limit.yml b/data/deprecations/15-3-pipeline_activity_limit.yml
new file mode 100644
index 00000000000..5cb620e576e
--- /dev/null
+++ b/data/deprecations/15-3-pipeline_activity_limit.yml
@@ -0,0 +1,33 @@
+# This is a template for a feature deprecation.
+#
+# Please refer to the deprecation guidelines to confirm your understanding of GitLab's definitions.
+# https://docs.gitlab.com/ee/development/deprecation_guidelines/#terminology
+#
+# Deprecations must be announced at least three releases prior to removal.
+#
+# If an End of Support period applies, the announcement should be shared with GitLab Support
+# in the `#spt_managers` on Slack and mention `@gitlab-com/support` in this MR.
+#
+# Breaking changes must happen in a major release.
+#
+# For more information please refer to the handbook documentation here:
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations
+#
+# Please delete this line and above before submitting your merge request.
+#
+# REQUIRED FIELDS
+#
+- name: "Maximum number of active pipelines per project limit (`ci_active_pipelines`)" # (required) The name of the feature to be deprecated
+ announcement_milestone: "15.3" # (required) The milestone when this feature was first announced as deprecated.
+ announcement_date: "2022-08-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
+ removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ breaking_change: false # (required) If this deprecation is a breaking change, set this value to true
+ reporter: jheimbuck_gl # (required) GitLab username of the person reporting the deprecation
+ stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368195 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ The [**Maximum number of active pipelines per project** limit](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#set-cicd-limits) was never enabled by default and will be removed in GitLab 16.0. This limit can also be configured in the Rails console under [`ci_active_pipelines`](https://docs.gitlab.com/ee/administration/instance_limits.html#number-of-pipelines-running-concurrently). Instead, use the other recommended rate limits that offer similar protection:
+
+ - [**Pipelines rate limits**](https://docs.gitlab.com/ee/user/admin_area/settings/rate_limit_on_pipelines_creation.html).
+ - [**Total number of jobs in currently active pipelines**](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#set-cicd-limits).
diff --git a/data/deprecations/16-0-security_report_schemas_v14-x-x.yml b/data/deprecations/16-0-security_report_schemas_v14-x-x.yml
new file mode 100644
index 00000000000..3487deaf5a7
--- /dev/null
+++ b/data/deprecations/16-0-security_report_schemas_v14-x-x.yml
@@ -0,0 +1,27 @@
+#
+# REQUIRED FIELDS
+#
+- name: "Security report schemas version 14.x.x" # (required) the name of the feature being removed. Avoid the words `deprecation`, `deprecate`, `removal`, and `remove` in this field because these are implied.
+ announcement_milestone: "15.8" # (required) The milestone when this feature was deprecated.
+ announcement_date: "2023-01-22" # (required) The date of the milestone release when this feature was deprecated. This should almost always be the 22nd of a month (YYYY-MM-DD), unless you did an out of band blog post.
+ removal_milestone: "16.0" # (required) The milestone when this feature is being removed.
+ removal_date: "2023-05-22" # (required) This should almost always be the 22nd of a month (YYYY-MM-DD), the date of the milestone release when this feature will be removed.
+ breaking_change: true # (required) Change to true if this removal is a breaking change.
+ reporter: matt_wilson # (required) GitLab username of the person reporting the removal
+ stage: Secure # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366477 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ All [security report schema](https://gitlab.com/gitlab-org/security-products/security-report-schemas) versions before 15.0.0 are considered deprecated in GitLab %15.8. Specifically, all [schemas](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/lib/ee/gitlab/ci/parsers/security/validators/schemas) that match 14.*.* will be deprecated.
+
+ Please note that any [security report scanner integration](https://docs.gitlab.com/ee/development/integrations/secure.html) with GitLab using a deprecated schema version will result in a deprecation warning as a result of [report validation](https://docs.gitlab.com/ee/development/integrations/secure.html#report-validation).
+
+ See [Security report validation](https://docs.gitlab.com/ee/user/application_security/#security-report-validation) for more information.
+#
+# OPTIONAL FIELDS
+#
+ end_of_support_milestone: "15.8" # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
+ end_of_support_date: "2023-01-22" # (optional) The date of the milestone release when support for this feature will end.
+ tiers: [Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/templates/_deprecation_template.md.erb b/data/deprecations/templates/_deprecation_template.md.erb
index 7c11e6706ba..93713a5e407 100644
--- a/data/deprecations/templates/_deprecation_template.md.erb
+++ b/data/deprecations/templates/_deprecation_template.md.erb
@@ -59,7 +59,7 @@ Planned removal: GitLab <span class="removal-milestone"><%= deprecation["removal
<% if deprecation["breaking_change"] -%>
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
<%= deprecation["body"] -%><% else %>
diff --git a/data/removals/15_0/15-0-removal-artifacts-keyword.yml b/data/removals/15_0/15-0-removal-artifacts-keyword.yml
index 29edd922eae..15c9a5ee27a 100644
--- a/data/removals/15_0/15-0-removal-artifacts-keyword.yml
+++ b/data/removals/15_0/15-0-removal-artifacts-keyword.yml
@@ -3,7 +3,7 @@
announcement_date: "2022-02-22"
removal_milestone: "15.0"
removal_date: "2022-05-22"
- breaking_change: false
+ breaking_change: true
body: |
As of GitLab 15.0, the [`artifacts:reports:cobertura`](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscobertura-removed)
keyword has been [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/344533) by
diff --git a/data/removals/15_0/removal_manage_ repository_push_audit_event.yml b/data/removals/15_0/removal_manage_repository_push_audit_event.yml
index 474a5c41a95..474a5c41a95 100644
--- a/data/removals/15_0/removal_manage_ repository_push_audit_event.yml
+++ b/data/removals/15_0/removal_manage_repository_push_audit_event.yml
diff --git a/data/removals/templates/_removal_template.md.erb b/data/removals/templates/_removal_template.md.erb
index 8bee1d69e42..dc779323096 100644
--- a/data/removals/templates/_removal_template.md.erb
+++ b/data/removals/templates/_removal_template.md.erb
@@ -38,7 +38,7 @@ For removal reviewers (Technical Writers only):
<% if removal["breaking_change"] -%>
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
<%= removal["body"] -%><% else %>
diff --git a/data/whats_new/202008180001_12_10.yml b/data/whats_new/202008180001_12_10.yml
index a21e9d795a1..aa53a2f6140 100644
--- a/data/whats_new/202008180001_12_10.yml
+++ b/data/whats_new/202008180001_12_10.yml
@@ -1,32 +1,32 @@
---
-- title: Create and view requirements in GitLab
- body: |
+- name: Create and view requirements in GitLab
+ description: |
The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level.
As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/requirements/index.html
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/requirements/index.html
image_url: https://docs.gitlab.com/ee/user/project/requirements/img/requirements_list_v13_5.png
published_at: 2020-04-22
release: 12.10
-- title: Retrieve CI/CD secrets from HashiCorp Vault
- body: |
+- name: Retrieve CI/CD secrets from HashiCorp Vault
+ description: |
In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault.
Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of [HashiCorp's JWT authentication method](https://www.vaultproject.io/docs/auth/jwt) rather than manually having to provide secrets as a variable in GitLab.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
release: 12.10
-- title: Epic and Issue Health Tracking
- body: |
+- name: Epic and Issue Health Tracking
+ description: |
To help users track projects and in-flight work GitLab now enables you to report on and quickly respond to the health of individual issues and epics by showing a red, amber, or green health status on your Epic Tree.
Assign an issue a health status of **On track** (green), **Needs attention** (amber), or **At risk** (red) and see an aggregate report of health at the Epic level.
@@ -35,34 +35,34 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/issues/index.html#health-status
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/issues/index.html#health-status
image_url: https://about.gitlab.com/images/12_10/epic-health-status.png
published_at: 2020-04-22
release: 12.10
-- title: Import Issues from Jira to GitLab
- body: |
+- name: Import Issues from Jira to GitLab
+ description: |
Until now, the only way to get Jira issues into GitLab was manually, with our CSV importer, or by hand-rolling your own migration utility.
GitLab 12.10 includes an [MVC](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc) to automatically import your Jira issues into GitLab. This is the first of [many planned enhancements](https://gitlab.com/groups/gitlab-org/-/epics/2738) to make transitioning from Jira to GitLab as frictionless as possible.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/import/jira.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/import/jira.html
image_url: https://about.gitlab.com/images/12_10/jira-importer.png
published_at: 2020-04-22
release: 12.10
-- title: Autoscaling GitLab CI jobs on AWS Fargate
- body: |
+- name: Autoscaling GitLab CI jobs on AWS Fargate
+ description: |
You can now auto-scale GitLab CI on AWS Fargate with the MVC release of GitLab’s AWS Fargate Driver.
With this new autoscaling pattern, [GitLab’s AWS Fargate driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate) automatically runs each build in a separate and isolated container on Amazon’s Elastic Container Service (ECS) using a user-defined container image.
stage: Verify
self-managed: true
gitlab-com: false
- packages: [Free, Premium, Ultimate]
- url: https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate/-/blob/master/docs/README.md
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate/-/blob/master/docs/README.md
image_url: https://about.gitlab.com/images/12_9/autoscaling_ci_fargate.png
published_at: 2020-04-22
release: 12.10
diff --git a/data/whats_new/202008180002_13_0.yml b/data/whats_new/202008180002_13_0.yml
index e82fa82cae0..930c4245ea5 100644
--- a/data/whats_new/202008180002_13_0.yml
+++ b/data/whats_new/202008180002_13_0.yml
@@ -1,66 +1,66 @@
---
-- title: Gitaly Cluster for High Availability Git Storage
- body: |
+- name: Gitaly Cluster for High Availability Git Storage
+ description: |
GitLab now supports highly available Git storage without using NFS. High Availability (HA) configurations improve the availability of important systems, like Git storage, by removing single points of failure, detecting outages, and automatically switching to a replica.
This means that an individual component of the system can fail without causing the end user to experience an outage. Access to Git repositories is critical to developers and businesses, because when an outage occurs, developers can’t push code, and deployments are blocked.
stage: Create
self-managed: true
gitlab-com: false
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/administration/gitaly/praefect.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/administration/gitaly/praefect.html
image_url: https://about.gitlab.com/images/13_0/praefect-architecture.png
published_at: 2020-05-22
release: 13.0
-- title: Auto Deploy to ECS
- body: |
+- name: Auto Deploy to ECS
+ description: |
Until now, there hasn’t been a simple way to deploy to Amazon Web Services. As a result, GitLab users had to spend a lot of time figuring out their own configuration.
In GitLab 13.0, Auto DevOps has been extended to support deployment to AWS! GitLab users who are deploying to AWS Elastic Container Service (ECS) can now take advantage of Auto DevOps, even if they are not using Kubernetes.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/topics/autodevops/index.html#aws-ecs
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/topics/autodevops/index.html#aws-ecs
image_url: https://docs.gitlab.com/ee/ci/img/ecs_dashboard_v12_9.png
published_at: 2020-05-22
release: 13.0
-- title: View Epic Hierarchy on a Roadmap
- body: |
+- name: View Epic Hierarchy on a Roadmap
+ description: |
When leveraging Multi-Level Epics, it can be difficult to keep track of where each child epic lives on the Roadmap.
You can now quickly expand a parent epic on your roadmap to view all its child epics to ensure work is properly organized and your planned timeline is on track!
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/group/roadmap/
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/roadmap/
image_url: https://about.gitlab.com/images/13_0/Expand-Epic-Hierarchy-Roadmap_roadmap.png
published_at: 2020-05-22
release: 13.0
-- title: Versioned Snippets
- body: |
+- name: Versioned Snippets
+ description: |
Snippets in GitLab are now version controlled by a Git repository. When editing a Snippet, each change creates a commit.
Snippets can also be cloned to make edits locally, and then pushed back to the Snippet repository.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/snippets.html#versioned-snippets
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/snippets.html#versioned-snippets
image_url: https://about.gitlab.com/images/13_0/phikai-versioned-snippets.png
published_at: 2020-05-22
release: 13.0
-- title: Dark Theme in the Web IDE
- body: |
+- name: Dark Theme in the Web IDE
+ description: |
For people who spend time working in code editors, the ability to customize the environment to match their preferences is important. Dark themes are some of the most [popular](https://marketplace.visualstudio.com/search?target=VSCode&category=Themes&sortBy=Installs) for other editors and important for providing a comfortable experience.
That's why we're excited that the GitLab Web IDE is now completely themed dark for users who choose the **Dark** [syntax highlighting theme perference](https://docs.gitlab.com/ee/user/profile/preferences.html#syntax-highlighting-theme)!
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/web_ide/#themes
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/web_ide/#themes
image_url: https://about.gitlab.com/images/13_0/phikai-web-ide-dark-theme.png
published_at: 2020-05-22
release: 13.0
diff --git a/data/whats_new/202008180003_13_01.yml b/data/whats_new/202008180003_13_01.yml
index 835b0f8567b..d3ae61e3be5 100644
--- a/data/whats_new/202008180003_13_01.yml
+++ b/data/whats_new/202008180003_13_01.yml
@@ -1,49 +1,49 @@
---
-- title: Manage IT Alerts in GitLab
- body: |
+- name: Manage IT Alerts in GitLab
+ description: |
GitLab is excited to introduce Alert Management to aggregate multiple IT service alerts in one interface, helping your team triage alerts and promote them to Incidents.
We’ve added the ability to triage alerts in a [list view](https://gitlab.com/groups/gitlab-org/-/epics/2986), [view alert details](https://gitlab.com/groups/gitlab-org/-/epics/2987), [assign alerts](https://gitlab.com/groups/gitlab-org/-/epics/3349), [update the status of alerts](https://gitlab.com/gitlab-org/gitlab/-/issues/214542), and [create Incident Issues from Alerts](https://gitlab.com/gitlab-org/gitlab/-/issues/213909).
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/operations/incident_management/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/incident_management/index.html
image_url: https://about.gitlab.com/images/13_1/alert_management.png
published_at: 2020-06-22
release: 13.1
-- title: Accessibility testing merge request widget
- body: |
+- name: Accessibility testing merge request widget
+ description: |
Today, developers who want to ensure their application is accessible to everyone suffer from slow feedback loops, which make it difficult to catch degradations in their code.
In GitLab 13.1, merge requests can have a widget that details accessibility degradations related to the changed pages. This will immediately show developers the impact of their changes, which helps prevent degradations before they are merged and deployed.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_testing.html#accessibility-merge-request-widget
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_testing.html#accessibility-merge-request-widget
image_url: https://about.gitlab.com/images/13_1/a11y-merge-request-widget.png
published_at: 2020-06-22
release: 13.1
-- title: Mark any Design Thread as Resolved
- body: |
+- name: Mark any Design Thread as Resolved
+ description: |
When you receive lots of feedback on a Design, the number of comment pins can build up quickly! As your discussion thread grows, it gets hard to know which discussions are complete and which still need work. Now you’ll have the ability to mark any comment as **Resolved** to signify that it is now complete. Even better — your **Resolved Comment** pins will disappear from the Design so you can focus on what’s left!
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads
image_url: https://about.gitlab.com/images/13_1/resolve-design-comment.gif
published_at: 2020-06-22
release: 13.1
-- title: Merge request reviews moved to Free
- body: |
+- name: Merge request reviews moved to Free
+ description: |
Originally introduced in GitLab 11.4 as a GitLab Premium feature, merge request reviews allow merge request reviewers to submit multiple comments at once, cutting down on notification noise for the merge request author, and allowing for a more cohesive and streamlined review process.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/discussions/index.html#merge-request-reviews
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/discussions/index.html#merge-request-reviews
image_url: https://about.gitlab.com/images/13_1/batch_comments.png
published_at: 2020-06-22
release: 13.1
diff --git a/data/whats_new/202008210001_13_02.yml b/data/whats_new/202008210001_13_02.yml
index ce562abbf29..55e2608108a 100644
--- a/data/whats_new/202008210001_13_02.yml
+++ b/data/whats_new/202008210001_13_02.yml
@@ -1,45 +1,45 @@
---
-- title: Assign Issues to Iterations
- body: |
+- name: Assign Issues to Iterations
+ description: |
Prior to this release, there was no way to associate an issue with more than one timebox in GitLab. This has been particularly problematic for teams that follow Scrum or XP. Such teams often need to associate issues with iterations/sprints, while also rolling that issue up to longer-running milestones, such as program increments.
Instead of having to decide whether to use milestones for sprints or program increments and track the other in a spreadsheet, you can now assign issues to iterations, milestones, or both.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://www.youtube.com/watch?v=31pNKjenlJY&feature=emb_title
+ available_in: [Premium, Ultimate]
+ documentation_link: https://www.youtube.com/watch?v=31pNKjenlJY&feature=emb_title
image_url: https://img.youtube.com/vi/31pNKjenlJY/hqdefault.jpg
published_at: 2020-07-22
release: 13.2
-- title: Container Host Monitoring and Blocking
- body: |
+- name: Container Host Monitoring and Blocking
+ description: |
We’re pleased to announce the first release of [Container Host Security](https://about.gitlab.com/direction/protect/container_host_security/). This initial feature, container host monitoring and blocking, allows security administrators to secure their running containers at the host level by monitoring and optionally blocking unexpected activity.
Such activity includes process starts, file changes, or opened network ports. This feature uses [Falco](https://falco.org/) to provide the monitoring functionality and [AppArmor](https://www.kernel.org/doc/html/v4.15/admin-guide/LSM/apparmor.html) and [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) for the blocking functionality.
stage: Defend
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://www.youtube.com/watch?v=WxBzBz76FxU&feature=youtu.be
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://www.youtube.com/watch?v=WxBzBz76FxU&feature=youtu.be
image_url: https://img.youtube.com/vi/WxBzBz76FxU/hqdefault.jpg
published_at: 2020-07-22
release: 13.2
-- title: Official GitLab-Figma Plugin
- body: |
+- name: Official GitLab-Figma Plugin
+ description: |
Recently, the GitLab product design team and our open source [Pajamas Design System](https://design.gitlab.com/) switched over to Figma. We decided to build a new Figma plugin, which allows for easy uploads from Figma to issues on GitLab.com.
This makes it quick and easy to collaborate on Designs. Connect your design environment with your source code management in a seamless workflow.
stage: Create
self-managed: false
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#gitlab-figma-plugin
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/issues/design_management.html#gitlab-figma-plugin
image_url: https://about.gitlab.com/images/13_2/figma-plugin.png
published_at: 2020-07-22
release: 13.2
-- title: Cluster health monitoring now available in Free
- body: |
+- name: Cluster health monitoring now available in Free
+ description: |
To understand system performance, your development team must monitor the health and performance of the underlying infrastructure.
We want our metrics solution to be available to all GitLab users, so as part of our [2020 gift](https://about.gitlab.com/blog/2019/12/16/observability/), we’ve moved cluster health in the Monitor stage from GitLab Ultimate to GitLab Free.
@@ -48,8 +48,8 @@
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/clusters/#visualizing-cluster-health
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/clusters/#visualizing-cluster-health
image_url: https://about.gitlab.com/images/13_2/k8s_cluster_monitoring.png
published_at: 2020-07-22
release: 13.2
diff --git a/data/whats_new/202009150001_13_03.yml b/data/whats_new/202009150001_13_03.yml
index e9d63561af8..100c615f974 100644
--- a/data/whats_new/202009150001_13_03.yml
+++ b/data/whats_new/202009150001_13_03.yml
@@ -1,30 +1,30 @@
---
-- title: Coverage-guided fuzz testing for Go and C/C++ applications
- body: |
+- name: Coverage-guided fuzz testing for Go and C/C++ applications
+ description: |
You can now run coverage-guided fuzz tests against your Go and C/C++ apps. This is a great way to start finding security issues and bugs that other security scanners and traditional QA may miss.
Coverage-guided fuzz testing uses contextual information about your app to randomly generate inputs and find crashes or other faults that you can then fix before they affect users in production.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://www.youtube.com/watch?v=3wdWMDRLdp4
+ available_in: [Ultimate]
+ documentation_link: https://www.youtube.com/watch?v=3wdWMDRLdp4
image_url: https://img.youtube.com/vi/3wdWMDRLdp4/hqdefault.jpg
published_at: 2020-08-22
release: 13.3
-- title: Create a matrix of jobs using a simple syntax
- body: |
+- name: Create a matrix of jobs using a simple syntax
+ description: |
GitLab’s [child/parent pipelines](https://gitlab.com/gitlab-org/gitlab/-/issues/16094) let you write your own code to generate an entire pipeline YAML. This is a powerful way to generate custom behaviors, including generating jobs at runtime. This might not be needed for simpler scenarios where you just want to create multiple similar jobs for a defined set of cases. In this release you can find a new `matrix` keyword that works along with `parallel` to handle the creation of multiple jobs for you, each with different variables.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs
image_url: https://about.gitlab.com/images/13_3/cartesian-matrix.png
published_at: 2020-08-22
release: 13.3
-- title: On-demand DAST scans
- body: |
+- name: On-demand DAST scans
+ description: |
Dynamic Application Security Testing at GitLab has always been focused on integrating DAST into the DevOps pipeline and enabling developers to scan their review app, running website, or API for vulnerabilities as early as possible.
However, there are times when it is necessary to run a DAST scan against an already deployed application when no code changes have been made and no merge request has been created. These scans could be needed for audit or compliance reasons, to debug and reproduce an issue that has been found, or to support teams who do not commit code, such as security analysts.
@@ -33,21 +33,21 @@
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans
image_url: https://about.gitlab.com/images/13_3/dast_on_demand_v13_3.png
published_at: 2020-08-22
release: 13.3
-- title: SAST security analyzers available for all
- body: |
+- name: SAST security analyzers available for all
+ description: |
We want to help developers write better code and worry less about common security mistakes. [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) helps prevent security vulnerabilities by allowing developers to easily identify common security issues as code is being committed and mitigate proactively.
As part of our [community stewardship commitment](https://about.gitlab.com/company/stewardship/#promises) we have made [all 15 of our open source based SAST analyzers](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) available in every GitLab tier. This allows ALL GitLab users developing in any of our [18 supported languages and frameworks](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) to leverage GitLab SAST in their projects.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/sast/#making-sast-analyzers-available-to-all-gitlab-tiers
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/sast/#making-sast-analyzers-available-to-all-gitlab-tiers
image_url: https://about.gitlab.com/images/13_3/sast-gitlab-languages.png
published_at: 2020-08-22
release: 13.3
diff --git a/data/whats_new/202009300001_13_04.yml b/data/whats_new/202009300001_13_04.yml
index 4ba278def0c..a86defd61c5 100644
--- a/data/whats_new/202009300001_13_04.yml
+++ b/data/whats_new/202009300001_13_04.yml
@@ -1,17 +1,17 @@
---
-- title: Use HashiCorp Vault secrets in CI jobs
- body: |
+- name: Use HashiCorp Vault secrets in CI jobs
+ description: |
In GitLab 12.10, GitLab introduced functionality for GitLab Runner to fetch and inject secrets into CI jobs. GitLab is now expanding the [JWT Vault Authentication method](https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/) by building a new `secrets` syntax in the `.gitlab-ci.yml` file. This makes it easier for you to configure and use HashiCorp Vault with GitLab.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/secrets
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/secrets
image_url: https://about.gitlab.com/images/13_4/vault_ci.png
published_at: 2020-09-22
release: 13.4
-- title: Introducing the GitLab Kubernetes Agent
- body: |
+- name: Introducing the GitLab Kubernetes Agent
+ description: |
GitLab's Kubernetes integration has long enabled deployment to Kubernetes clusters without manual setup. Many users have enjoyed the ease-of-use, while others have run into some challenges. The current integration requires your cluster to be open to the Internet for GitLab to access it.
For many organizations, this isn't possible, because they must lock down their cluster access for security, compliance, or regulatory purposes. To work around these restrictions, users needed to create custom tooling on top of GitLab, or they couldn't use the feature.
@@ -22,26 +22,26 @@
stage: Configure
self-managed: true
gitlab-com: false
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/clusters/agent
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/clusters/agent
image_url: https://about.gitlab.com/images/13_4/gitops-header.png
published_at: 2020-09-22
release: 13.4
-- title: Grant users deployment permissions without code access
- body: |
+- name: Grant users deployment permissions without code access
+ description: |
If your team needs to maintain separation of duties between team members who own development, and team members who own deployments, the permissions paradigm in GitLab has made this challenging.
In GitLab 13.4, you can give non-code contributors permission to approve merge requests for deployment, and actually deploy code, without also granting them maintainer access.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/environments/protected_environments.html#environment-access-by-group-membership
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/environments/protected_environments.html#environment-access-by-group-membership
image_url: https://about.gitlab.com/images/13_4/deployer-role.png
published_at: 2020-09-22
release: 13.4
-- title: Security Center
- body: |
+- name: Security Center
+ description: |
We've made a foundational change to security visibility and management in GitLab. The Instance Security Dashboard has been transformed into a Security Center. The biggest change is introducing a new menu structure. Rather than a single page, you can now find a Security Dashboard, Vulnerability Report, and Settings area.
While the functionality hasn't changed, breaking things apart enables future enhancements that would have been difficult otherwise. This also creates a top-level framework for including other security-related functionality in the future.
@@ -50,21 +50,21 @@
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/security_dashboard/#instance-security-center
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/security_dashboard/#instance-security-center
image_url: https://about.gitlab.com/images/13_4/instance_vulnerability_report.png
published_at: 2020-09-22
release: 13.4
-- title: Quick navigation using the Search bar
- body: |
+- name: Quick navigation using the Search bar
+ description: |
When navigating through GitLab, sometimes you just want to go to a specific project and not a search result page. Using the Global search bar, you can now quickly jump to recent issues, groups, projects, settings, and help topics.
You can even use the `/` keyboard shortcut to move the cursor to the search bar, to navigate GitLab even more efficiently!
stage: Enablement
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/search/#autocomplete-suggestions
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/search/#autocomplete-suggestions
image_url: https://about.gitlab.com/images/13_4/enablement_global_search.gif
published_at: 2020-09-22
release: 13.4
diff --git a/data/whats_new/202010230001_13_05.yml b/data/whats_new/202010230001_13_05.yml
index 9166d148b37..e68d89db669 100644
--- a/data/whats_new/202010230001_13_05.yml
+++ b/data/whats_new/202010230001_13_05.yml
@@ -1,6 +1,6 @@
---
-- title: Group wikis
- body: |
+- name: Group wikis
+ description: |
For many teams, using GitLab wikis for planning and documentation is a critical part of their workflow. Wikis are so popular that they get over a million views each month on GitLab.com.
Despite this popularity, teams have struggled with the limitation that wikis were only available at the project level. Teams working on multiple projects needed to create separate wikis for each repository, leading to a fragmented experience.
@@ -11,26 +11,26 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/index.html#group-wikis
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/index.html#group-wikis
image_url: https://about.gitlab.com/images/13_5/cdybenko-group-wiki.png
published_at: 2020-10-22
release: 13.5
-- title: Install the GitLab Kubernetes Agent with Omnibus GitLab
- body: |
+- name: Install the GitLab Kubernetes Agent with Omnibus GitLab
+ description: |
Last month we introduced the [GitLab Kubernetes Agent](https://about.gitlab.com/releases/2020/09/22/gitlab-13-4-released/#introducing-the-gitlab-kubernetes-agent) for self-managed GitLab instances installed with Helm.
This release adds support for the [official Linux package](https://about.gitlab.com/install/). In this new Kubernetes integration, the Agent orchestrates deployments by pulling new changes from GitLab, rather than GitLab pushing updates to your cluster. You can learn more about [how the Kubernetes Agent works now](https://docs.gitlab.com/ee/user/clusters/agent/) and [check out our vision](https://about.gitlab.com/direction/configure/kubernetes_management/) to see what’s in store.
stage: Configure
self-managed: true
gitlab-com: false
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/clusters/agent/
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/clusters/agent/
image_url: https://about.gitlab.com/images/13_5/gitops-header.png
published_at: 2020-10-22
release: 13.5
-- title: Snippets with multiple files
- body: |
+- name: Snippets with multiple files
+ description: |
Engineers often use Snippets to share examples of code, reusable components, logs, and other items. These valuable pieces of information often require additional context and may require more than one file. Sharing a link to multiple files or multiple Snippets makes it challenging for users to piece this context together and understand the scope of what is being presented.
In GitLab 13.0, we laid a foundation for Snippets by giving them [version control](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#versioned-snippets) support based on a Git repository. Version control and the history it provides are an important piece of context when looking at code and understanding its purpose, but it may not be everything.
@@ -39,47 +39,47 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/snippets.html#multiple-files-by-snippet
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/snippets.html#multiple-files-by-snippet
image_url: https://about.gitlab.com/images/13_5/phikai-snippets-multiple-files.png
published_at: 2020-10-22
release: 13.5
-- title: Enable instance-level shared runners when viewing groups
- body: |
+- name: Enable instance-level shared runners when viewing groups
+ description: |
GitLab SaaS includes Linux and Windows runners, which are easy to use agents that run your GitLab CI/CD pipeline jobs. These runners, visible in the GitLab.com UI as "shared runners," are enabled by default and can be disabled for each project. However, some organizations require their CI/CD jobs to run only on self-managed runners, and so disabling the use of instance-level shared runners on each project resulted in unnecessary administrative overhead.
Now administrators can enable or disable shared runners at the group level. Administrators can also allow groups to override the global setting and use shared runners on a project-by-project basis.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/runners/index.html#disable-shared-runners
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/runners/index.html#disable-shared-runners
image_url: https://about.gitlab.com/images/13_5/enable_shared_runners_v2.png
published_at: 2020-10-22
release: 13.5
-- title: Feature Flags flexible rollout strategy
- body: |
+- name: Feature Flags flexible rollout strategy
+ description: |
When you use the `percent rollout` strategy today, the stickiness, or the experience consistency, is determined only by the user ID. This can be limiting; as an example, anonymous users cannot be affected by this strategy.
We have improved this rollout strategy by enabling you to define the stickiness based on session ID, user ID, or at random (no stickiness). This gives you more control over the rollout and allows you to support stickiness for anonymous users.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/operations/feature_flags.html#percent-rollout
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/feature_flags.html#percent-rollout
image_url: https://about.gitlab.com/images/13_5/percent-rollout.png
published_at: 2020-10-22
release: 13.5
-- title: SAST support for iOS and Android mobile apps
- body: |
+- name: SAST support for iOS and Android mobile apps
+ description: |
GitLab [SAST](https://docs.gitlab.com/ee/user/application_security/sast/) now supports mobile applications including iOS apps written in Objective-C and Swift as well as Android apps written in Java and Kotlin powered by the [Mobile Security Framework (MobSF)](https://github.com/MobSF/Mobile-Security-Framework-MobSF). Initially this analyzer supports source code analysis but we [intend to expand support for binary scanning](https://gitlab.com/gitlab-org/gitlab/-/issues/269915) of `.ipa` and `.apk` files in the near future.
This feature was a generous contribution by the [H-E-B Digital](https://digital.heb.com/) team.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
image_url: https://about.gitlab.com/images/13_5/sast-gitlab-mobile.png
published_at: 2020-10-22
release: 13.5
diff --git a/data/whats_new/202011230001_13_06.yml b/data/whats_new/202011230001_13_06.yml
index 1e47bcca0ec..effaa243812 100644
--- a/data/whats_new/202011230001_13_06.yml
+++ b/data/whats_new/202011230001_13_06.yml
@@ -1,6 +1,6 @@
---
-- title: Auto Deploy to EC2
- body: |
+- name: Auto Deploy to EC2
+ description: |
Auto DevOps has been expanded to support deployments to Amazon Web Services. You can now deploy to AWS Cloud Compute (EC2) and take advantage of Auto DevOps, even without Kubernetes.
To enable this workflow, you must enable Auto DevOps and define the AWS-typed environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION`. This allows you to provision your own infrastructure by leveraging the [AWS CloudFormation API](https://aws.amazon.com/cloudformation/).
@@ -9,26 +9,26 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/cloud_deployment/#custom-build-job-for-auto-devops
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/cloud_deployment/#custom-build-job-for-auto-devops
image_url: https://img.youtube.com/vi/4B-qSwKnacA/hqdefault.jpg
published_at: 2020-11-22
release: 13.6
-- title: Display Code Quality severity ratings
- body: |
+- name: Display Code Quality severity ratings
+ description: |
The Code Quality feature in GitLab is great at showing what quality violations exist in a project or are changing in the merge request. However, understanding which of those violations is the most important is not clear in the GitLab interface today.
With the Full Code Quality Report and merge request widget, now you can see the severity rating. This makes it easy for you to understand which code quality violations are most important to resolve before merging and reduces the technical debt in your project.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-widget
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-widget
image_url: https://about.gitlab.com/images/13_6/code_quality_severity.png
published_at: 2020-11-22
release: 13.6
-- title: Display code coverage data for selected projects
- body: |
+- name: Display code coverage data for selected projects
+ description: |
In 13.4, we released the first iteration of [Code Coverage data for Groups](https://about.gitlab.com/releases/2020/09/22/gitlab-13-4-released/#code-coverage-data-for-all-projects-in-a-group) that enables you to compare the coverage of multiple projects and download the data in a single file from a single screen.
However, to analyze the data, you had to open the file to check it manually, and probably imported it into a spreadsheet for further analysis.
@@ -39,13 +39,13 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/repositories_analytics/index.html#latest-project-test-coverage-list
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/repositories_analytics/index.html#latest-project-test-coverage-list
image_url: https://about.gitlab.com/images/13_6/display_selected_coverage_projects_example.png
published_at: 2020-11-22
release: 13.6
-- title: Group-level management of project integrations
- body: |
+- name: Group-level management of project integrations
+ description: |
In GitLab 13.3, we added the ability to [enable an integration across an entire instance](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#instance-level-project-integration-management-for-external-services). With GitLab 13.6, that feature is being expanded to allow integrations to be managed at the group level as well! Group owners can now add an integration to a group, and that integration will be inherited by all projects under that group.
This has the potential for saving massive amounts of time, as many organizations have specific integrations that they want rolled out to every project they create.
@@ -58,13 +58,13 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/admin_area/settings/project_integration_management.html
image_url: https://about.gitlab.com/images/13_6/project-integration-inheriting-settings.png
published_at: 2020-11-22
release: 13.6
-- title: Milestone Burnup Charts and historically accurate reporting
- body: |
+- name: Milestone Burnup Charts and historically accurate reporting
+ description: |
A milestone or iteration burndown chart helps track completion progress of total scope, but it doesn't provide insight into how the scope changed during the course of the timebox. Neither has it previously retained historical accuracy regarding how much of the initial committed scope of the milestone or iteration was actually completed.
To solve these problems and help teams have better insights into scope creep, milestones and iterations now show a burnup chart that tracks the daily total count and weight of issues added to and completed within a given timebox.
@@ -75,8 +75,8 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html#burnup-charts
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/milestones/burndown_and_burnup_charts.html#burnup-charts
image_url: https://about.gitlab.com/images/13_6/burnup-chart.png
published_at: 2020-11-22
release: 13.6
diff --git a/data/whats_new/202012160001_13_07.yml b/data/whats_new/202012160001_13_07.yml
index 28d596081cc..6b07bd4341a 100644
--- a/data/whats_new/202012160001_13_07.yml
+++ b/data/whats_new/202012160001_13_07.yml
@@ -1,17 +1,17 @@
---
-- title: Auto rollback in case of failure
- body: |
+- name: Auto rollback in case of failure
+ description: |
If you have a critical problem with a deployment, manual actions to fix it often take too long and lead to a degradation in production that impacts your users. Now, you can leverage an automatic rollback mechanism that reverts your deployment back to the last successful deployment. Also, when GitLab finds problems in production it automatically notifies you with an alert. This gives you peace of mind and precious development time to debug, investigate, and fix problems without causing downtime.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/ci/environments/#auto-rollback
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/environments/#auto-rollback
image_url: https://img.youtube.com/vi/G8fYYrxqF5E/hqdefault.jpg
published_at: 2020-12-22
release: 13.7
-- title: Reviewers for merge requests
- body: |
+- name: Reviewers for merge requests
+ description: |
Asking a colleague to review your code should be a routine part of contributing code, but it's often needlessly complex. A simple task like asking for a review can lead to confusion. For example, how should you ask? An email? Comment? Chat message? Without a formal process, reviews can be inconsistent and hard to keep track of. Previously, an option was to assign a reviewer to a merge request, but even with this formality, both the author and the reviewer appeared in the same assignee field, making it hard for other team members to know who was doing what.
GitLab 13.7 introduces reviewers for merge requests, which allows authors to request a review from someone. The new "Reviewers" field allows users to be designated as reviewers in a similar way to assignees. The reviewers receive a notification inviting them to review the merge request. This provides a formal process for requesting a review and clarifies the roles of each user in a merge request.
@@ -20,32 +20,32 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/getting_started#reviewer
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/getting_started#reviewer
image_url: https://about.gitlab.com/images/13_7/reviewers_sidebar.png
published_at: 2020-12-22
release: 13.7
-- title: Clone an issue with a quick action
- body: |
+- name: Clone an issue with a quick action
+ description: |
To make generating similar issues more efficient, issues now support a `/clone` quick action, which creates a new issue in the same project, with an identical title, description, and metadata. The `/clone` quick action replaces a more cumbersome process, which involves multiple steps to create an issue, copy the ID or path of the source issue, and use the `copy_meta` quick action.
By default, issues are cloned into the same project and do not include system notes and comments, but you can also change the default behavior when cloning.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/quick_actions.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/quick_actions.html
image_url: https://about.gitlab.com/images/13_7/clone_issue_with_quick_action.png
published_at: 2020-12-22
release: 13.7
-- title: GitLab Runner for Red Hat OpenShift
- packages: [Free, Premium, Ultimate]
+- name: GitLab Runner for Red Hat OpenShift
+ available_in: [Free, Premium, Ultimate]
self-managed: true
gitlab-com: true
- url: 'https://docs.gitlab.com/runner/install/openshift.html'
+ documentation_link: 'https://docs.gitlab.com/runner/install/openshift.html'
image_url: 'https://about.gitlab.com/images/13_7/runner-redhat-openshift.png'
stage: Verify
- body: |
+ description: |
Available today is the GitLab Runner container image for the [Red Hat OpenShift Container Platform](https://www.openshift.com/products/container-platform). To install the runner on OpenShift, you can use the new [GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator) available from the beta channel in Red Hat's Operator Hub - a web console for OpenShift cluster administrators to discover and select Operators to install on their cluster. Operator Hub is deployed by default in the OpenShift Container Platform. We plan to transition the GitLab Runner Operator to the stable channel, and by extension [GA](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator/-/issues/6), in early 2021. Finally, we are also developing an operator for GitLab, so stay tuned to future release posts for those announcements.
published_at: 2020-12-22
release: 13.7
diff --git a/data/whats_new/202101140001_13_08.yml b/data/whats_new/202101140001_13_08.yml
index 3a1c0179d84..084d09a18e4 100644
--- a/data/whats_new/202101140001_13_08.yml
+++ b/data/whats_new/202101140001_13_08.yml
@@ -1,82 +1,82 @@
---
-- title: Pipeline editor
- body: |
+- name: Pipeline editor
+ description: |
GitLab CI/CD provides you with flexible options to support a variety of advanced pipeline use cases. Pipeline syntax can be verbose and sometimes complicated, especially for those who are new to GitLab CI/CD. In this release, we are proud to introduce our first iteration of the Pipeline Editor.
The editor makes the CI configuration authoring experience much easier for both novice and advanced users alike. The pipeline editor is a single solution that groups all the existing CI authoring features (and future ones) in a single location. The pipeline editor is the best place to go when configuring your pipeline.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/pipeline_editor/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/pipeline_editor/index.html
image_url: https://img.youtube.com/vi/MQpSyvMpsHA/hqdefault.jpg
published_at: 2021-01-22
release: 13.8
-- title: Visualization of pipeline configuration
- body: |
+- name: Visualization of pipeline configuration
+ description: |
A complex CI configuration can be difficult to understand as a developer, especially when trying to predict how your pipeline might behave (or misbehave). Without a visual aid, it is challenging to form a mental image of the relationships between all of the jobs and determine how they are interconnected. In our first iteration of a pipeline visualization, you can now see a graphic representation of your `.gitlab-ci.yml` configuration to better understand and predict how your pipelines will perform.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/visualization.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/visualization.html
image_url: https://about.gitlab.com/images/13_8/pipeline_visual_builder.png
published_at: 2021-01-22
release: 13.8
-- title: Deployment frequency charts
- packages: [Ultimate]
+- name: Deployment frequency charts
+ available_in: [Ultimate]
self-managed: true
gitlab-com: true
image_url: https://about.gitlab.com/images/13_8/deployment_graph.png
- url: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#deployment-frequency-charts
+ documentation_link: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#deployment-frequency-charts
stage: Release
- body: |
+ description: |
Knowing and monitoring deployment frequency is a starting point for organizations adopting DevOps. We are proud to introduce the deployment frequency charts at the project level so that you and your development teams can monitor the efficiency of deployments over time, find bottlenecks, and make improvements when necessary. This is the first of the DORA metrics that we are making available within GitLab out of the box.
published_at: 2021-01-22
release: 13.8
-- title: Scope a board to the current iteration
- body: |
+- name: Scope a board to the current iteration
+ description: |
Many teams use boards to manage issues during an iteration. In 13.6, we added support for [filtering issues on a board to a specific Iteration](https://gitlab.com/gitlab-org/gitlab/-/issues/118742), but it is cumbersome to remember to apply that filter every time you go to your board. In this release, we've added the ability to scope your board to the currently active iteration.
stage: plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/issue_board.html#configurable-issue-boards
image_url: https://about.gitlab.com/images/13_8/scope_board_to_current_iteration.png
published_at: 2021-01-22
release: 13.8
-- title: Download artifacts directly from the merge request widget
- body: |
+- name: Download artifacts directly from the merge request widget
+ description: |
We added the ability to download build artifacts directly from the MR widget. This is especially useful for mobile development. An example of this is where users want to test an Android package of a specific build created on a physical device or an emulator. You can now access these artifacts directly from the merge request widget without having to find the artifacts buried in the pipeline view.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#downloading-artifacts
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#downloading-artifacts
image_url: https://about.gitlab.com/images/13_8/artifact_mr.png
published_at: 2021-01-22
release: 13.8
-- title: Rebase quick action for merge requests
- body: |
+- name: Rebase quick action for merge requests
+ description: |
Rebase is a Git command used to reapply commits on top of a new commit. In practice, this means reapplying commits from a feature branch on top of the latest version of the target branch (e.g. `main`). In this way, it is possible to bring the feature branch up to date and resolve any conflicts without using a merge commit with the benefit of a simpler linear Git history.
GitLab 13.8 brings the ability to execute the rebase quick action in merge requests, allowing you to quickly invoke the rebase Git utility.
stage: create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics
image_url: https://about.gitlab.com/images/13_8/rebase_comment.png
published_at: 2021-01-22
release: 13.8
-- title: GitLab Pages is now available for Kubernetes deployments of GitLab
- body: |
+- name: GitLab Pages is now available for Kubernetes deployments of GitLab
+ description: |
GitLab Pages is a popular static-site hosting service built into GitLab, and we are excited to announce that it is now available for GitLab instances running on Kubernetes. Pages was one of the last remaining feature gaps compared to an Omnibus deployment.
stage: enablement
self-managed: true
gitlab-com: false
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/charts/charts/gitlab/gitlab-pages/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/charts/charts/gitlab/gitlab-pages/index.html
image_url: https://about.gitlab.com/images/home/kubernetes.png
published_at: 2021-01-22
release: 13.8
diff --git a/data/whats_new/202102180001_13_09.yml b/data/whats_new/202102180001_13_09.yml
index 5f50a05bef2..ee097583884 100644
--- a/data/whats_new/202102180001_13_09.yml
+++ b/data/whats_new/202102180001_13_09.yml
@@ -1,77 +1,77 @@
-- title: "Select CI/CD configuration from any job and reuse it"
- body: |
+- name: "Select CI/CD configuration from any job and reuse it"
+ description: |
Previously, if you wanted to reuse the same configuration in multiple jobs, you had two options: add YAML anchors, which don't work across different configuration files, or use `extends` to reuse an entire section.
In this release, we've added a new YAML function called `!reference`, which lets you target the exact configuration you want to reuse as part of your CI/CD pipeline, even if it's in another file.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/index.html#reference-tags
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/index.html#reference-tags
image_url: https://about.gitlab.com/images/13_9/reference.png
published_at: 2021-02-22
release: 13.9
-- title: "GPU and smart scheduling support for GitLab Runner"
- body: |
+- name: "GPU and smart scheduling support for GitLab Runner"
+ description: |
Specialized compute workloads like those used in machine learning can significantly benefit from access to GPUs. Developers can configure GitLab Runner to leverage GPUs in the Docker executor by forwarding the `--gpu` flag. You can also use this with recent support in [GitLab’s fork of Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html#using-the-forked-version-of-docker-machine), which allows you to [accelerate workloads with attached GPUs](https://cloud.google.com/compute/docs/gpus/create-vm-with-gpus). Doing so can help control costs associated with potentially expensive machine configurations.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/runner/executors/docker_machine.html#using-gpus-on-google-compute-engine
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/runner/executors/docker_machine.html#using-gpus-on-google-compute-engine
image_url: https://about.gitlab.com/images/ci/gitlab-ci-cd-logo_2x.png
published_at: 2021-02-22
release: 13.9
-- title: "Vault JWT (JSON Web Token) supports GitLab environments"
- body: |
+- name: "Vault JWT (JSON Web Token) supports GitLab environments"
+ description: |
To simplify integrations with HashiCorp Vault, we've shipped Vault JWT token support. From the launch, you could restrict access based on data in the JWT. This release gives you a new dimension for restricting access to credentials: the environment a job targets.
This release extends the existing Vault JWT token to support environment-based restrictions too. As the `environment` name could be supplied by the user running the pipeline, we recommend you use the new environment-based restrictions with the already-existing `ref_type` values for maximum security.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/icons/get-a-license.svg
published_at: 2021-02-22
release: 13.9
-- title: "SAST Support for .NET 5"
- body: |
+- name: "SAST Support for .NET 5"
+ description: |
Microsoft's [release of .NET 5.0](https://docs.microsoft.com/en-us/dotnet/core/dotnet-five) is the next major release of .NET Core which supports more types of apps and more platforms than .NET Core or .NET Framework. We have updated our .NET SAST analyzer, [Security Code Scan](https://security-code-scan.github.io/) to support this new version which is also now supported with [our SAST language detection](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) allowing GitLab SAST to automatically detect .NET 5 projects. This change was part of a community contribution by [@shaun.burns](https://gitlab.com/shaun.burns).
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/sast/analyzers.html#analyzers-data
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/sast/analyzers.html#analyzers-data
image_url: https://about.gitlab.com/images/solutions/icon_sheild-check.svg
published_at: 2021-02-22
release: 13.9
-- title: "Create Jira issues from Vulnerabilities"
- body: |
+- name: "Create Jira issues from Vulnerabilities"
+ description: |
Many customers use Jira as their single source of truth for tracking issues and engineering work. When using GitLab for SCM and CI/CD, they can take advantage of our existing integration to pass information from MRs and commits into existing Jira issues. However, until now there has been no way to automatically pass information about vulnerabilities detected by security scanners into Jira. This leaves users who rely on Jira to track work no choice but to manually copy vulnerability information into new Jira issues.
To address this, we're introducing a new ability to create Jira issues directly from a vulnerability's details. You will see this as a new option in your existing Jira integration settings. Simply enable the new option and select the desired Jira issue type. Available issue types are pulled automatically based on the currently configured Jira target project. Once enabled, all places in your project where you can create GitLab issues from a vulnerability will instead directly create a Jira issue of the configured type.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#create-a-gitlab-issue-for-a-vulnerability
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#create-a-gitlab-issue-for-a-vulnerability
image_url: https://about.gitlab.com/images/13_9/jira-vulnerability-integration.png
published_at: 2021-02-22
release: 13.9
-- title: "Security Alert Dashboard for Container Network Policy Alerts"
- body: |
+- name: "Security Alert Dashboard for Container Network Policy Alerts"
+ description: |
We're pleased to announce the first release of a dashboard for security alerts! Users can now configure Container Network Policies to send alerts to the security alert dashboard. This is especially useful when traffic must be closely monitored but cannot be blocked entirely without negatively impacting the business. You can configure the alerts at **Security & Compliance > Threat Management > Policies**, and view them at **Security & Compliance > Threat Management > Alerts**.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/threat_monitoring/#configuring-network-policy-alerts
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/threat_monitoring/#configuring-network-policy-alerts
image_url: https://about.gitlab.com/images/13_9/security_alert_dashboard.png
published_at: 2021-02-22
release: 13.9
-- title: "Maintenance Mode"
- body: |
+- name: "Maintenance Mode"
+ description: |
Systems administrators occasionally perform maintenance operations on their GitLab instance to keep it performing optimally. Administrators want to offer the highest level of access to their users while these operations are taking place. For example, you may want to perform a [failover test to a secondary site](https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html) as part of the company's business continuity plan. Prior to the failover, you want to pause changes for a short period to ensure the secondary is fully synchronized. Until GitLab 13.8, you could [restrict users from logging in](https://docs.gitlab.com/omnibus/maintenance/#restrict-users-from-logging-into-gitlab), but this would block the entire UI and would render GitLab inaccessible to users.
GitLab 13.9 introduces [maintenance mode](https://docs.gitlab.com/ee/administration/maintenance_mode/index.html), where write operations are disabled at the application level. This means that GitLab is effectively in a read-only state for all non-administrative users (administrators are still able to edit application settings and [background jobs continue](https://docs.gitlab.com/ee/administration/maintenance_mode/index.html#background-jobs)). Regular users are able to log in to GitLab, view the interface and perform other read-only operations, such as `git clone` or `git pull`. Using maintenance mode, systems administrators can perform maintenance operations, such as failing over to a secondary site, with minimal disruption to regular users.
@@ -80,43 +80,43 @@
stage: Enablement
self-managed: true
gitlab-com: false
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/administration/maintenance_mode/index.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/administration/maintenance_mode/index.html
image_url: https://about.gitlab.com/images/13_9/maintenance_mode.png
published_at: 2021-02-22
release: 13.9
-- title: "New merge request metric: mean time to merge"
- body: |
+- name: "New merge request metric: mean time to merge"
+ description: |
A new metric, mean time to merge (MTTM), is available in project-level merge request analytics. MTTM is the average time from when a merge request (MR) is created, until the time it is merged. By selecting different dates in the date range selector, you can see how your time to merge MRs changes over time and understand whether you are becoming more efficient at reviewing and merging code.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/analytics/merge_request_analytics.html#mean-time-to-merge
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/analytics/merge_request_analytics.html#mean-time-to-merge
image_url: https://about.gitlab.com/images/13_9/mttm.png
published_at: 2021-02-22
release: 13.9
-- title: "Filter roadmaps by confidentiality"
- body: |
+- name: "Filter roadmaps by confidentiality"
+ description: |
When viewing a roadmap, there used to be no way to hide confidential epics from the main view. This could be frustrating if you wanted to share your roadmap with a public audience. We've updated the search bar filter to include confidentiality so you now have another layer in which you can refine your roadmap.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/roadmap/#sort-and-filter-the-roadmap
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/roadmap/#sort-and-filter-the-roadmap
image_url: https://about.gitlab.com/images/13_9/roadmap-filter-by-confidentiality.png
published_at: 2021-02-22
release: 13.9
-- title: "Allow Deploy Keys to push to protected branches"
- body: |
+- name: "Allow Deploy Keys to push to protected branches"
+ description: |
Prior to GitLab 12.0, deploy keys with write access could push commits to protected branches. Support for this was removed due to security concerns, but many users still requested it, as they used deploy keys to ensure that only users with deploy keys could push to their repositories. Removing deploy keys also eliminates the need to use a service user or machine user, which ties up a license for any team that wants to allow deploy keys to push to protected branches just for this use case.
We are excited to announce that we resolved this issue and now deploy keys can push to protected branches once more while abiding by security best practices. By moving towards an isolated permission model for deploy keys, users can now select deploy keys to link to protected branches directly from the **Settings** page on protected branches.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/protected_branches.html#allow-deploy-keys-to-push-to-a-protected-branch
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/protected_branches.html#allow-deploy-keys-to-push-to-a-protected-branch
image_url: https://about.gitlab.com/images/13_9/deploy_keys.png
published_at: 2021-02-22
release: 13.9
diff --git a/data/whats_new/202103220001_13_10.yml b/data/whats_new/202103220001_13_10.yml
index a1f456a6c8d..bba60a60ca2 100644
--- a/data/whats_new/202103220001_13_10.yml
+++ b/data/whats_new/202103220001_13_10.yml
@@ -1,16 +1,16 @@
-- title: "GitLab Runner for Red Hat OpenShift GA"
- body: |
+- name: "GitLab Runner for Red Hat OpenShift GA"
+ description: |
The GitLab Runner Operator is generally available in the [Red Hat OpenShift Container Platform](https://www.openshift.com/products/container-platform). To install GitLab Runner on OpenShift, you can use the [GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator), which is available from the stable channel in the OperatorHub. The Container Platform is a web console for OpenShift cluster administrators to discover and select Operators to install on their cluster. We are also developing an [Operator](https://gitlab.com/groups/gitlab-org/-/epics/3444) for GitLab, so stay tuned to future release posts for those announcements.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/runner/install/openshift.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/runner/install/openshift.html
image_url: https://img.youtube.com/vi/ZNBc_QnDUu4/hqdefault.jpg
published_at: 2021-03-22
release: 13.10
-- title: "View epics on a board (MVC)"
- body: |
+- name: "View epics on a board (MVC)"
+ description: |
If you work on epics in GitLab, it can be tough to visualize your epics' workflow status. Often, when drafting or writing epics, you might want to use labels (like `Open`, `Doing`, or `Done`) to keep tabs on the next steps when creating your project plan.
In this release, we took our awesome [Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html) feature and optimized it for viewing epics. You can now visualize the workflow status of your epics on an epic board by applying [labels](https://docs.gitlab.com/ee/user/project/labels.html#label-management) or [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to them.
@@ -19,13 +19,13 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
image_url: https://about.gitlab.com/images/13_10/view-epics-on-a-board-mvc-1.png
published_at: 2021-03-22
release: 13.10
-- title: "View Jira issue details in GitLab"
- body: |
+- name: "View Jira issue details in GitLab"
+ description: |
Users of our Jira issue list feature can now view the details of an issue directly inside of GitLab! This MVC enables developers to see the details, labels, and comments on an issue, giving them the ability to stay in GitLab while working on Jira issues.
Our goal is to empower developers to _stay inside of GitLab_ during the majority of their day, and this is now one less trip to Jira you'll have to make.
@@ -34,48 +34,48 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/integrations/jira.html#view-a-jira-issue
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/integrations/jira.html#view-a-jira-issue
image_url: https://about.gitlab.com/images/13_10/jira-detail-view.png
published_at: 2021-03-22
release: 13.10
-- title: "DORA4-based lead time for changes"
- body: |
+- name: "DORA4-based lead time for changes"
+ description: |
Measuring the efficiency of your software development lifecycle is an important step to grow DevOps adoption for any organization. In the previous milestone, we added support for [DORA4-based Deployment Frequency](https://docs.gitlab.com/ee/api/dora4_project_analytics.html). In this release, we are excited to announce the support of a new API for lead time for changes (via merge requests) on the project level. The lead time for changes gives you an indication of how long it takes for code to be committed and deployed to your production environment. Understanding and tracking this data is a great starting point in your journey to continuous improvement in your DevOps process.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-merge-request-lead-times
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-merge-request-lead-times
image_url: https://about.gitlab.com/images/13_10/api.png
published_at: 2021-03-22
release: 13.10
-- title: "Create a release from an existing tag"
- body: |
+- name: "Create a release from an existing tag"
+ description: |
Previously, creating a release was supported only for new tags. In GitLab 13.10, you can now create a release by selecting an existing tag, something that will give you more flexibility when planning releases.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/releases/#create-a-release
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/releases/#create-a-release
image_url: https://about.gitlab.com/images/13_10/exiting_tags.png
published_at: 2021-03-22
release: 13.10
-- title: "Integrate any IT alerting tool with GitLab"
- body: |
+- name: "Integrate any IT alerting tool with GitLab"
+ description: |
Alert integrations are a critical part of your Incident Management workflows. It's difficult to manage integrations between tools, especially when several monitoring tools like Nagios, Solarwinds, etc. alert on your services. These integrations notify you and your team of incidents, so it's critical for them to be easy to set up and maintain.
In this version of GitLab, you can create multiple HTTP endpoints with unique auth tokens for each integrated monitoring tool. When you set up an HTTP endpoint with a unique auth token for each monitoring tool, your team can manage each tool separately without affecting alerts from other tools nor take down all of your alerting by resetting a single auth token!
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/operations/incident_management/integrations.html#http-endpoints
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/incident_management/integrations.html#http-endpoints
image_url: https://about.gitlab.com/images/13_10/integrate_alerts.png
published_at: 2021-03-22
release: 13.10
-- title: "Merge request test summary usability improvements"
- body: |
+- name: "Merge request test summary usability improvements"
+ description: |
Increasing the number of tests or custom metrics in a pipeline gives you additional confidence and information. However, increasing these to a large number has also come with a degraded visual experience of the merge request page. The merge request test summary widget has been improved so you can better differentiate between the different test jobs in the widget, making it easier to identify which job contains failed tests.
It has also been challenging to understand why a `junit.xml` file was not parsed without errors being presented. Now you can see parsing errors in the Test Summary widget, as well as the Unit Test report, to identify and resolve structural issues and see test results in GitLab.
@@ -84,8 +84,8 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/unit_test_reports.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/unit_test_reports.html
image_url: https://about.gitlab.com/images/13_10/test_summary_ux_improvements.png
published_at: 2021-03-22
release: 13.10
diff --git a/data/whats_new/202104220001_13_11.yml b/data/whats_new/202104220001_13_11.yml
index 6453893b6de..7a3bb433340 100644
--- a/data/whats_new/202104220001_13_11.yml
+++ b/data/whats_new/202104220001_13_11.yml
@@ -1,18 +1,18 @@
-- title: GitLab Kubernetes Agent available on GitLab.com
- body: |
+- name: GitLab Kubernetes Agent available on GitLab.com
+ description: |
The GitLab Kubernetes Agent is finally available on GitLab.com. By using the Agent, you can benefit from fast, pull-based deployments to your cluster, while GitLab.com manages the necessary server-side components of the Agent. The GitLab Kubernetes Agent is the core building block of GitLab's Kubernetes integrations. The Agent-based integration today supports pull-based deployments and Network Security policy integration and alerts, and will soon receive support for push-based deployments too.
Unlike the legacy, certificate-based Kubernetes integration, the GitLab Kubernetes Agent does not require opening up your cluster towards GitLab and allows fine-tuned RBAC controls around GitLab's capabilities within your clusters.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/clusters/agent/
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/clusters/agent/
image_url: https://img.youtube.com/vi/4Sh5bghbAjY/hqdefault.jpg
published_at: 2021-04-22
release: 13.11
-- title: Compliance pipeline configurations
- body: |
+- name: Compliance pipeline configurations
+ description: |
We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding [compliance framework](https://docs.gitlab.com/ee/user/project/settings/#compliance-framework).
For teams looking to implement compliance requirements in the pipeline workflow, they can now enforce even more separation of duties by setting up a single pipeline definition for a specific compliance framework. All projects using that framework will include the predefined pipeline automatically. Users extend, but cannot modify, the pipeline configuration in the downstream projects, ensuring that compliance steps are run the same way every time.
@@ -23,48 +23,48 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration
image_url: https://img.youtube.com/vi/upLJ_equomw/hqdefault.jpg
published_at: 2021-04-22
release: 13.11
-- title: On-call schedule management
- body: |
+- name: On-call schedule management
+ description: |
Software services do not get "turned off" at the end of the business day. Your customers expect 24/7 availability. When things go wrong, you need a team (or multiple teams!) that can quickly and effectively respond to service outages.
Being on-call can be a stressful job. To better manage stress and burn-out, most teams rotate this on-call responsibility. GitLab's **on-call schedule management** allows you and your team to create and manage schedules for on-call responsibilities. Alerts received in GitLab through an HTTP endpoint are routed to the on-call engineer in the schedule for that specific project.
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/operations/incident_management/oncall_schedules.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/incident_management/oncall_schedules.html
image_url: https://img.youtube.com/vi/QXfCQ24-Ufo/hqdefault.jpg
published_at: 2021-04-22
release: 13.11
-- title: Use multiple caches in the same job
- body: |
+- name: Use multiple caches in the same job
+ description: |
GitLab CI/CD provides a caching mechanism that saves precious development time when your jobs are running. Previously, it was impossible to configure multiple cache keys in the same job. This limitation may have caused you to use artifacts for caching, or use duplicate jobs with different cache paths. In this release, we provide the ability to configure multiple cache keys in a single job which will help you increase your pipeline performance.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/index.html#multiple-caches
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/index.html#multiple-caches
image_url: https://about.gitlab.com/images/13_11/cache.png
published_at: 2021-04-22
release: 13.11
-- title: Group SAML Enforcement for Git activity
- body: |
+- name: Group SAML Enforcement for Git activity
+ description: |
GitLab group maintainers can now enhance their group security by enforcing Group SAML for Git activity. Security-minded organizations want all GitLab activity to be protected and governed by their SAML Identity Provider. Currently, SAML SSO enforcement only applies to activity in the GitLab UI. Git CLI operations do not require an active SAML SSO session. When Git Group SAML SSO enforcement is enabled, users must have an active web SAML session to perform Git operations in the CLI.
stage: Manage
self-managed: false
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/saml_sso/#sso-enforcement
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/saml_sso/#sso-enforcement
image_url: https://about.gitlab.com/images/sdlc-icons/manage.svg
published_at: 2021-04-22
release: 13.11
-- title: Cherry pick commits from fork to parent
- body: |
+- name: Cherry pick commits from fork to parent
+ description: |
With GitLab 13.11, if you are a project member, you can now cherry-pick commits from downstream forks back into your project. We've added a new **Pick into project** section to the cherry-pick dialog, shown when you select **Options > Cherry-pick** on a commit's details page.
Your community of contributors can contribute to your project, and your team no longer needs to manually download a fork's `.patch` file to pull in good changes from stale or unmaintained forks.
@@ -73,24 +73,24 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html#cherry-pick-into-a-project
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/cherry_pick_changes.html#cherry-pick-into-a-project
image_url: https://about.gitlab.com/images/13_11/cherry_pick_commits_from_fork_to_parent.png
published_at: 2021-04-22
release: 13.11
-- title: Improvements to Jira Connect application configuration
- body: |
+- name: Improvements to Jira Connect application configuration
+ description: |
When configuring the [GitLab.com for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) application, you can now filter the available namespaces when linking them to your account, simplifying configuration for users with access to a large number of namespaces.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/integration/jira/connect-app.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/integration/jira/connect-app.html
image_url: https://about.gitlab.com/images/13_11/jira-connect-app-search.png
published_at: 2021-04-22
release: 13.11
-- title: Search within a settings page
- body: |
+- name: Search within a settings page
+ description: |
Finding the exact location of a GitLab setting can be challenging. Even if you know generally where to look, many of the settings views have multiple sections and dozens of individual configuration options.
In this release, you can now use the search field in group, project, admin, and user settings to quickly pinpoint your desired configuration. Your search criteria will filter the current page down to display only relevant settings and even highlight occurrences of your search term on the page.
@@ -99,19 +99,19 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/search/#search-settings
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/search/#search-settings
image_url: https://about.gitlab.com/images/13_11/search-settings.gif
published_at: 2021-04-22
release: 13.11
-- title: Deploy GitLab on OpenShift and Kubernetes with the GitLab Operator (beta)
- body: |
+- name: Deploy GitLab on OpenShift and Kubernetes with the GitLab Operator (beta)
+ description: |
GitLab is working to offer full support for OpenShift. To accomplish this, we have released the MVP [GitLab Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-operator/-/tree/master/doc). The operator aims to manage the full lifecycle of GitLab instances on Kubernetes and OpenShift container platforms. Currently, this is a [beta release](https://gitlab.com/groups/gitlab-org/-/epics/3444) and it is **not recommended for production use**. The next steps will be to make the operator generally available (GA). In the future the operator will become the recommended installation method for Kubernetes and OpenShift, although the GitLab Helm chart will still be supported. We welcome you to try this operator and [provide feedback on our issue tracker](https://gitlab.com/gitlab-org/gl-openshift/gitlab-operator/-/issues/131).
stage: Enablement
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://gitlab.com/gitlab-org/gl-openshift/gitlab-operator/-/tree/master/doc
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://gitlab.com/gitlab-org/gl-openshift/gitlab-operator/-/tree/master/doc
image_url: https://about.gitlab.com/images/13_11/gitlab-operator.png
published_at: 2021-04-22
release: 13.11
diff --git a/data/whats_new/202105220001_13_12.yml b/data/whats_new/202105220001_13_12.yml
index bbe614959a0..893ea694988 100644
--- a/data/whats_new/202105220001_13_12.yml
+++ b/data/whats_new/202105220001_13_12.yml
@@ -1,31 +1,31 @@
-- title: On-demand DAST GA launch
- body: |
+- name: On-demand DAST GA launch
+ description: |
After months of work, we are pleased to announce that our on-demand DAST scanning has reached a General Availability (GA) maturity level. It is ready for usage by anyone who needs to scan an already-deployed application or API outside of a CI/CD pipeline job. With the 13.11 release, we added to on-demand DAST Site profiles the ability to specify authentication information, exclude URLs, add additional request headers, and switch between scanning web applications and APIs. This is in addition to the ability to save scans for quick reusability that was added in 13.9, and the ability to select the branch that a scan is associated with that was added in 13.10. We believe this feature set meets the needs of a majority of GitLab customers.
As we continue to add features, such as scan scheduling, we expect on-demand DAST scanning to cover an ever-increasing range of use cases. As always, we would love as much feedback about these features as possible. Please let us know how things are working for you by leaving a comment in [issue 327396](https://gitlab.com/gitlab-org/gitlab/-/issues/327396).
stage: secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans
image_url: https://about.gitlab.com/images/13_12/dast_on_demand_auth.png
published_at: 2021-05-22
release: 13.12
-- title: Filter Project Vulnerability Report by vendor name
- body: |
+- name: Filter Project Vulnerability Report by vendor name
+ description: |
GitLab strives to play well with others and security is no exception. We provide many security scanners as part of our Secure offering. We also encourage 3rd party vendors to [integrate their scanning tools](https://docs.gitlab.com/ee/development/integrations/secure.html) using our open API and data interchange formats. A benefit of using GitLab is managing vulnerabilities from multiple scanners in a unified experience. While you were already able to filter by scanner type (SAST, DAST), it wasn't possible to drill down by the tool provider.
You now have even more granularity when managing vulnerabilities with the new ability to filter by scanner and vendor. You can look at all results across a single vendor's scanners or gain confidence in findings from one scan type (e.g. SAST) that are confirmed by both GitLab and the 3rd party tool. The new filtering capability is available now in Project Vulnerability Reports.
stage: secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/security_dashboard/#vulnerability-report
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/security_dashboard/#vulnerability-report
image_url: https://about.gitlab.com/images/13_12/select_scanner_by_vendor.png
published_at: 2021-05-22
release: 13.12
-- title: Lock latest pipeline artifact to prevent deletion
- body: |
+- name: Lock latest pipeline artifact to prevent deletion
+ description: |
GitLab now automatically locks the latest artifact produced from a successful pipeline on any active branch, merge request, or tag to prevent it from being deleted based on expiration if it is still the most recent artifact.
This makes it easier to set a more aggressive expiration policy to clean up older artifacts, helps reduce disk space consumption, and ensures you have always got a copy of the latest artifact from your pipeline.
@@ -34,13 +34,13 @@
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/index.html#artifactsexpire_in
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/index.html#artifactsexpire_in
image_url: https://about.gitlab.com/images/growth/verify.png
published_at: 2021-05-22
release: 13.12
-- title: Delete associated package files via API
- body: |
+- name: Delete associated package files via API
+ description: |
You use the GitLab Package Registry to publish, install, and share your dependencies. You may do this using a variety of package manager formats, such as Maven or npm. If you do this as part of your CI workflow, you may publish many packages to your registry. When you publish a dependency, it generates several files including the package archive.
Prior to GitLab 13.12, GitLab didn't provide a way to delete the files from a package. You could only delete the package itself. These extra files can clutter the user interface or result in someone installing an incorrect or outdated dependency.
@@ -49,79 +49,79 @@
stage: package
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/api/packages.html#delete-a-package-file
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/api/packages.html#delete-a-package-file
image_url: https://about.gitlab.com/images/growth/package.png
published_at: 2021-05-22
release: 13.12
-- title: Configuration tool for Secret Detection
- body: |
+- name: Configuration tool for Secret Detection
+ description: |
Following in the footsteps of the [GitLab SAST configuration tool](https://docs.gitlab.com/ee/user/application_security/sast/index.html#configure-sast-in-the-ui) we are adding support for Secret Detection on the Security Configuration page. We believe that [security is a team effort](https://about.gitlab.com/direction/secure/#security-is-a-team-effort) and this configuration experience makes it easier for non-CI experts to get started with [GitLab Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/). The tool helps a user create a merge request to enable Secret Detection scanning while leveraging best configuration practices like using the GitLab-managed [`SAST.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml). The Configuration tool can create a new `.gitlab-ci.yml` file if one does not exist or update existing simple GitLab CI files, allowing the tool to be used with projects that already have GitLab CI setup.
stage: secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/configuration/
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/configuration/
image_url: https://about.gitlab.com/images/13_12/secret_config_button_13_12.png
published_at: 2021-05-22
release: 13.12
-- title: Code quality violation notices in MR diffs
- body: |
+- name: Code quality violation notices in MR diffs
+ description: |
During code reviews, you may have wanted to highlight Code Quality violations and how to resolve them. Previously, this involved having a browser window open to see the violations on the Merge Request summary and another window reviewing the changes in the MR or your IDE. You may have found switching between them too difficult and given up.
Now, you can see if the file you are reviewing has new code quality violations that are part of the changes right in the Merge Request diff view. This gives you the necessary context to suggest a fix as part of your normal workflow within GitLab without having to keep additional windows open and context switch back and forth between them.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-in-diff-view
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-in-diff-view
image_url: https://about.gitlab.com/images/13_12/code-quality-mr-diff-mvc.png
published_at: 2021-05-22
release: 13.12
-- title: Group-level deployment frequency CI/CD chart
- body: |
+- name: Group-level deployment frequency CI/CD chart
+ description: |
As part of our efforts to natively support [DORA4 metrics](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#devops-research-and-assessment-dora-key-metrics) in GitLab, the group-level deployment frequency chart is now available. This chart will show the aggregated deployment frequency metrics for all the projects that are part of the group, and allow you to get a full picture of the deployment frequency across multiple projects and teams, so that you can comprehend their efficiency more accurately. Monitoring deployment frequency helps you understand the efficiency of your deployments over time, find bottlenecks, and focus on improvement areas that span across your projects and teams.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#deployment-frequency-charts
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#deployment-frequency-charts
image_url: https://about.gitlab.com/images/13_12/group_deployment_frequency.png
published_at: 2021-05-22
release: 13.12
-- title: Enforce delayed project removal for all subgroups
- body: |
+- name: Enforce delayed project removal for all subgroups
+ description: |
Group owners can now enable and enforce [delayed project removal](https://docs.gitlab.com/ee/user/group/#enable-delayed-project-removal) for all subgroups and projects in their group. Delayed project removal protects your data by placing deleted projects in a read-only state after deletion and can be restored, if required. We plan to expand our settings model and allow more settings to be inherited and enforced in subgroups and projects in future milestones. Our new settings management model gives group owners a way to ensure that their subgroups and projects settings adhere to their organization's security and compliance needs.
stage: manage
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/#enable-delayed-project-removal
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/#enable-delayed-project-removal
image_url: https://about.gitlab.com/images/13_12/mushakov_delayed_deletion.png
published_at: 2021-05-22
release: 13.12
-- title: Mobile application binary scanning support
- body: |
+- name: Mobile application binary scanning support
+ description: |
Since GitLab 13.6, we've offered [SAST for Android and iOS mobile projects](https://about.gitlab.com/releases/2020/10/22/gitlab-13-5-released/#sast-support-for-ios-and-android-mobile-apps). Initially our Mobile App SAST supported the automatic detection of Xcode projects and Android manifest files. With this release and contribution from community contributor [@proletarius101](https://gitlab.com/proletarius101), GitLab SAST now also supports the automatic detection of .ipa (iOS) and .apk (Android) binary files enabling the security scanning of fully built mobile application artifacts. This offers mobile teams more flexibility with how they build and scan their mobile projects with GitLab SAST for security vulnerabilities.
Please note that mobile application scanning is still an experimental feature and [requires enabling the experimental flag](https://docs.gitlab.com/ee/user/application_security/sast/#experimental-features) in your CI template. We will make the mobile application scanner generally available without this flag [in the near future](https://gitlab.com/groups/gitlab-org/-/epics/5977).
stage: secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks
image_url: https://about.gitlab.com/images/growth/verify.png
published_at: 2021-05-22
release: 13.12
-- title: Instance-level Federated Learning of Cohorts (FLoC) opt-in
- body: |
+- name: Instance-level Federated Learning of Cohorts (FLoC) opt-in
+ description: |
[Federated Learning of Cohorts (FLoC)](https://en.wikipedia.org/wiki/Federated_Learning_of_Cohorts) is a new type of web tracking, intended to replace the use of third-party cookies. It does this by grouping users into cohorts based on their browsing history, for the primary purpose of interest-based advertising. FLoC is being activated in the Chrome browser in some regions.
With GitLab 13.12, FLoC will not incorporate GitLab browsing activity by default. If an instance administrator would like their users' GitLab instance usage to contribute to FLoC, they can re-enable in instance settings.
stage: enablement
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/admin_area/settings/floc.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/admin_area/settings/floc.html
image_url: https://about.gitlab.com/images/growth/enablement.png
published_at: 2021-05-22
release: 13.12
diff --git a/data/whats_new/202106220001_14_0.yml b/data/whats_new/202106220001_14_0.yml
index a17261e8586..62bb78cecbb 100644
--- a/data/whats_new/202106220001_14_0.yml
+++ b/data/whats_new/202106220001_14_0.yml
@@ -1,29 +1,29 @@
-- title: Streamlined top navigation menu
- body: |
+- name: Streamlined top navigation menu
+ description: |
GitLab 14.0 introduces an all-new, streamlined top navigation menu to help you get where you're going faster and with fewer clicks. This new, consolidated menu offers the combined functionality of the previous Projects, Groups, and More menus. It gives you access to your projects, groups, and instance-level features with a single click. Additionally, all-new responsive views improve the navigation experience on smaller screens.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://gitlab.com/gitlab-org/gitlab/-/issues/332635
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://gitlab.com/gitlab-org/gitlab/-/issues/332635
image_url: https://about.gitlab.com/images/14_0/consolidated-top-nav.png
published_at: 2021-06-22
release: 14.0
-- title: Sidebar navigation redesign
- body: |
+- name: Sidebar navigation redesign
+ description: |
GitLab is big. And it's getting bigger. As we've introduced new features and categories, navigating the densely-packed left sidebar has become less intuitive.
In GitLab 14.0 we've redesigned and restructured the left sidebar for improved usability, consistency, and discoverability. We've moved some links to features around, split up features in the **Operations** menu into three distinct menus, improved visual contrast, and optimized spacing so all the menu items can fit comfortably on a smaller screen. These changes are intended to better match your mental model of the DevOps lifecycle, and provide a more predictable and consistent experience while navigating within your projects and groups.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://gitlab.com/gitlab-org/gitlab/-/issues/332635
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://gitlab.com/gitlab-org/gitlab/-/issues/332635
image_url: https://about.gitlab.com/images/14_0/redesigned-left-sidebar.png
published_at: 2021-06-22
release: 14.0
-- title: Merge request reviews in VS Code
- body: |
+- name: Merge request reviews in VS Code
+ description: |
As a developer, you often spend a majority of your time working in your local development environment. When you're assigned a merge request for review, this requires you to leave your editor and perform that review inside of GitLab. While performing your review inside GitLab, you might also need to use your local editor to gain more context on the proposed changes.
[GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) version `3.21.0` for Visual Studio Code (VS Code) now supports the complete merge request review process, including threads. Select the GitLab icon in VS Code to open the [sidebar](https://gitlab.com/gitlab-org/gitlab-vscode-extension#sidebar-details) to display **Merge requests I'm reviewing**. Select a merge request overview to view the complete details and discussions of the merge request.
@@ -34,26 +34,26 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md
image_url: https://img.youtube.com/vi/F5ypjlOZ4-0/hqdefault.jpg
published_at: 2021-06-22
release: 14.0
-- title: Track usage of Code Owners
- body: |
+- name: Track usage of Code Owners
+ description: |
Code Owners are an important piece of the code review process in GitLab. When code owners are clearly identified, contributors can see who should review contributions to a file or repository. The Code Owners feature can also be used to establish a merge request approval process. Now, you can track which teams across your organization are using the Code Owners feature in their development workflow.
If you would like to drive adoption of Code Owners, sort the DevOps Adoption table by the Code Owners column to find teams that haven't yet adopted the feature so you can easily identify which teams need help getting started. Alternatively, find teams that have successfully configured Code Owners and get tips and feedback. The DevOps Adoption table is available at [the group level](https://docs.gitlab.com/ee/user/group/devops_adoption/) and [the instance level](https://docs.gitlab.com/ee/user/admin_area/analytics/dev_ops_report.html#devops-adoption).
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/admin_area/analytics/dev_ops_report#devops-adoption
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/admin_area/analytics/dev_ops_report#devops-adoption
image_url: https://about.gitlab.com/images/14_0/codeownersadoption.png
published_at: 2021-06-22
release: 14.0
-- title: Set pronouns on GitLab user profiles
- body: |
+- name: Set pronouns on GitLab user profiles
+ description: |
Pronouns have been added to GitLab user profiles. The pronouns appear next to user names in the **Profile** tab. You can:
- Decide whether or not to add pronouns to your profile.
@@ -63,24 +63,24 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns
image_url: https://about.gitlab.com/images/14_0/pronouns.png
published_at: 2021-06-22
release: 14.0
-- title: Container Scanning Integration with Trivy
- body: |
+- name: Container Scanning Integration with Trivy
+ description: |
Container scanning in GitLab now uses the Trivy engine by default. This change provides customers with more timely vulnerability intelligence updates, more accurate results, and support for a larger number of operating systems. Users who run container scanning with default settings are switched seamlessly and automatically to the new engine in GitLab 14.0. Users who customize the variables in their container scanning job should review our [migration guide](https://docs.gitlab.com/ee/user/application_security/container_scanning/#change-scanners) and make any necessary updates.
stage: Protect
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/container_scanning
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/container_scanning
image_url: https://about.gitlab.com/images/14_0/trivy_scanning_engine.png
published_at: 2021-06-22
release: 14.0
-- title: Aggregate identical DAST vulnerabilities into a single vulnerability
- body: |
+- name: Aggregate identical DAST vulnerabilities into a single vulnerability
+ description: |
In GitLab 13.12 and earlier, all DAST vulnerabilities found in a scan were listed individually for each URL the vulnerability was found on. This could create many vulnerabilities when the fix was a single file or configuration change. For example: an issue with a server header sent with every HTTP response would be reported on every page on the site, rather than reported as a single issue with multiple occurrences.
To reduce the overhead of managing vulnerabilities, GitLab combines identical vulnerabilities found on multiple pages into a single reported vulnerability in the DAST report. The vulnerability details include a list of all the URLs where the vulnerability was found, rather than individual vulnerabilities being created in the vulnerability list and dashboard for each page.
@@ -89,26 +89,26 @@
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/dast/#reports
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/dast/#reports
image_url: https://about.gitlab.com/images/14_0/dast_aggregated_urls.png
published_at: 2021-06-22
release: 14.0
-- title: Epic Boards
- body: |
+- name: Epic Boards
+ description: |
Epic Boards align teams and organizations by communicating the status of epics continuously. Previous versions of GitLab required you to view and sort epics in a list to view the overall status. Keeping epics up to date meant making most changes through an epic's detail page. Epic Boards enable you to visualize and refine all of your epics in one place, using a customizable, drag-and-drop interface that is easy for any teammate to understand and collaborate.
Epic Boards are also a game-changer for managing and visualizing ideal epic workflows, such as authoring workflow states (Draft, Writing, Done), DevOps workflow states (such as Planned, In Development, and In Production), or any other mutually exclusive states you might model with scoped labels. Visualizing workflows with an Epic Board empowers you to increase predictability and efficiency.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
image_url: https://about.gitlab.com/images/14_0/epic-boards.png
published_at: 2021-06-22
release: 14.0
-- title: Edit wiki pages with the WYSIWYG Markdown editor
- body: |
+- name: Edit wiki pages with the WYSIWYG Markdown editor
+ description: |
Editing wiki content could be so much easier! Many GitLab wikis use Markdown formatting, and for some users, Markdown is a barrier to efficient collaboration. In this release, you now have access to a rich, modern Markdown editing experience in your wiki, so you can edit with confidence.
Instant feedback and visual editing tools help make wiki editing more intuitive, and remove barriers to collaboration. GitLab saves the changes as Markdown when you're done, so users who want to edit the Markdown directly can do so. You can even type Markdown into the new editor and it will automatically format the text as you type.
@@ -117,45 +117,45 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/wiki/#content-editor
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/wiki/#content-editor
image_url: https://about.gitlab.com/images/14_0/wiki-content-editor-demo.gif
published_at: 2021-06-22
release: 14.0
-- title: Change an issue's type
- body: |
+- name: Change an issue's type
+ description: |
In some cases, you may wish to change an issue's type. For example, you may want to escalate an issue to an [incident](https://docs.gitlab.com/ee/operations/incident_management/index.html) to ensure that your team handles the problem properly. To change an issue's type, edit the issue and select an issue type from the **Issue type** selector menu.
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#change-the-issue-type
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#change-the-issue-type
image_url: https://about.gitlab.com/images/14_0/change_type_on_issues.png
published_at: 2021-06-22
release: 14.0
-- title: Prepopulate the CI/CD pipeline editor with an initial template
- body: |
+- name: Prepopulate the CI/CD pipeline editor with an initial template
+ description: |
The pipeline editor in GitLab is your one-stop shop when interacting with CI/CD pipelines. Previously, when writing your first pipeline with the editor, you were presented with a blank configuration. While perfectly useful for experienced pipeline authors, it was a bit of a leap for those just starting out.
In this release, if a project does not have a pipeline configured, the editor preloads a template showing an example 3-stage pipeline. You can save and run this pipeline right away to see it in action in your project. On top of that, it also has comments that help you understand the syntax, and tips and hints to help you start customizing the template to match your needs. It is now much easier to get your first green pipeline!
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/pipeline_editor/
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/pipeline_editor/
image_url: https://about.gitlab.com/images/14_0/template.png
published_at: 2021-06-22
release: 14.0
-- title: Terraform module registry built into GitLab
- body: |
+- name: Terraform module registry built into GitLab
+ description: |
Terraform modules play a central role in building standard infrastructure components throughout an organization. Up to GitLab 13.12, GitLab users had to use either a third-party Terraform module registry, local modules, or Git-based modules. While these options work well, they do not help with the distribution of the modules and they lack proper versioning support, which introduces risks for module users. GitLab 14.0 extends our [Infrastructure-as-Code offerings](https://docs.gitlab.com/ee/user/infrastructure/) with a Terraform module registry. Now, you can use the Terraform module registry built into GitLab to discover Terraform modules with semantic versioning support for upgrades and maintenance. Moreover, you can publish modules easily using GitLab CI/CD.
While following Terraform's best practices, we recommend developing each Terraform module in a dedicated GitLab project. To simplify the transition to the registry, users can host and publish multiple modules from a single GitLab repository. You can learn more about publishing and consuming a new module [in our documentation](https://docs.gitlab.com/ee/user/packages/terraform_module_registry/index.html).
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/packages/terraform_module_registry/index.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/packages/terraform_module_registry/index.html
image_url: https://about.gitlab.com/images/14_0/terraform-module-registry.png
published_at: 2021-06-22
release: 14.0
diff --git a/data/whats_new/202107220001_14_1.yml b/data/whats_new/202107220001_14_1.yml
index 881d96c58d3..32764b98803 100644
--- a/data/whats_new/202107220001_14_1.yml
+++ b/data/whats_new/202107220001_14_1.yml
@@ -1,28 +1,28 @@
-- title: Track progress on overall DevOps adoption
- body: |
+- name: Track progress on overall DevOps adoption
+ description: |
See the total number of key DevOps features adopted across your organization using the new progress bars in DevOps Adoption. Progress bars help you understand the value that teams are getting from GitLab and evaluate the state of your DevOps transformation.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/group/devops_adoption/
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/devops_adoption/
image_url: https://about.gitlab.com/images/14_1/progressbar.png
published_at: 2021-07-22
release: 14.1
-- title: Track use of security scanning across multiple teams
- body: |
+- name: Track use of security scanning across multiple teams
+ description: |
Track which groups across your organization have enabled SAST and DAST scanning. This is helpful for verifying compliance with organizational requirements, responding to audit requests, and tracking progress on company initiatives to make applications more secure. To track adoption, go to the **Sec** tab in DevOps Adoption either at the group level or instance level.
To see groups that have enabled fuzz testing and dependency scanning, use [the DevOps API](https://docs.gitlab.com/ee/api/graphql/reference/index.html#devopsadoptionsnapshot). Fuzz testing and dependency scanning will be added to the DevOps Adoption UI in an upcoming release.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/group/devops_adoption
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/devops_adoption
image_url: https://about.gitlab.com/images/14_1/scanadoption.png
published_at: 2021-07-22
release: 14.1
-- title: Create and apply patches in VS Code
- body: |
+- name: Create and apply patches in VS Code
+ description: |
When reviewing a merge request (MR) it can be helpful to make suggestions to many of the changed files. This is often done by creating a patch file with the suggestions and sharing it with others. The problem is that this requires several manual steps like running Git commands and uploading the patch file somewhere others can download it.
With [GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) [v3.26.0](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/CHANGELOG.md#3260-2021-07-13) for VS Code you can now create and apply patches directly in your editor. The new `GitLab: Create snippet patch` command creates a patch with the changes in your editor and uploads that patch as a [GitLab snippet](https://docs.gitlab.com/ee/user/snippets.html).
@@ -33,37 +33,37 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#create-and-apply-snippet-patch'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#create-and-apply-snippet-patch'
image_url: https://img.youtube.com/vi/QQxpLoKJULQ/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
-- title: Code coverage merge request approval rule
- body: |
+- name: Code coverage merge request approval rule
+ description: |
To keep code test coverage high, you need to ensure that merge requests to your codebase never decrease test coverage. Previously, the only way to enforce this was to [require approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/#required-approvals) from users who would check for test coverage decreases as part of their reviews.
Now you can enforce this organizational policy with the new Coverage check approval rule. This is a simple way to ensure merge requests that would decrease test coverage cannot be merged.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/pipelines/settings.html#coverage-check-approval-rule'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/pipelines/settings.html#coverage-check-approval-rule'
image_url: https://about.gitlab.com/images/14_1/coverage-mr-approval-rule.png
published_at: 2021-07-22
release: 14.1
-- title: Registration Features
- body: |
+- name: Registration Features
+ description: |
[Registration Features](https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program) introduces the ability for free, self-managed users running GitLab EE to access paid features by registering with GitLab and sharing activity data via [Service Ping](https://docs.gitlab.com/ee/development/service_ping/index.html#what-is-service-ping). The first feature introduced is [email from GitLab](https://docs.gitlab.com/ee/tools/email.html), enabling instance administrators to email users within their instance.
stage: Growth
self-managed: true
gitlab-com: false
- packages: [Free]
- url: 'https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program'
+ available_in: [Free]
+ documentation_link: 'https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program'
image_url: https://about.gitlab.com/images/14_1/registration-features.png
published_at: 2021-07-22
release: 14.1
-- title: Build, publish, and share Helm charts
- body: |
+- name: Build, publish, and share Helm charts
+ description: |
Helm defines a [chart](https://helm.sh/docs/intro/using_helm/#three-big-concepts) as a Helm package that contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. For organizations that create and manage their own Helm charts, it's important to have a central repository to collect and share them.
GitLab already supports a variety of other [package manager formats](https://docs.gitlab.com/ee/user/packages/). Why not also support Helm? That's what community member and [MVP from the 14.0 milestone](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#mvp) [Mathieu Parent](https://gitlab.com/sathieu) asked several months ago before breaking ground on the new GitLab Helm chart registry. The collaboration between the community and GitLab is part of our [dual flywheel strategy](https://about.gitlab.com/company/strategy/#dual-flywheels) and one of the reasons we love working at GitLab. Chapeau Mathieu!
@@ -72,26 +72,26 @@
stage: Package
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/packages/helm_repository/
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/packages/helm_repository/
image_url: https://img.youtube.com/vi/B6K373-pAgw/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
-- title: Escalation Policies
- body: |
+- name: Escalation Policies
+ description: |
Being on-call is a stressful, 24/7 job. It's possible to miss a notification despite your best efforts and intentions. Teams that maintain critical systems can't afford to miss alerts for outages or service disruptions. Escalation policies are a safety net for these situations. Escalation policies contain time-boxed steps that automatically page a responder in the next escalation step if the responder in the step before didn't respond. To protect your company from missed critical alerts, create an escalation policy in the GitLab project where you manage on-call schedules.
In GitLab 14.1, users can create, view, or delete escalation policies.
stage: Monitor
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/operations/incident_management/escalation_policies.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/incident_management/escalation_policies.html
image_url: https://img.youtube.com/vi/-1MuKzWJXKQ/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
-- title: CI/CD workflow for Kubernetes clusters
- body: |
+- name: CI/CD workflow for Kubernetes clusters
+ description: |
Until now, connecting Kubernetes clusters to GitLab CI/CD required you to open up your clusters towards GitLab. Some organizations do not encourage opening up their firewall externally due to security concerns.
GitLab now ships with a CI/CD functionality that connects runners with your Kubernetes cluster by using the [GitLab agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/). This enables versatile GitOps workflows where the deployment logic can be coded in the pipeline.
@@ -104,13 +104,13 @@
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html
image_url: https://img.youtube.com/vi/eXxM4ScqiJs/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
-- title: External status checks for merge requests
- body: |
+- name: External status checks for merge requests
+ description: |
You can now contact an external API to perform a status check in a merge request. This is a great way to integrate GitLab with third-party systems that:
- Run in an external system and do not have specific pipeline jobs.
- Require manual approval in another system.
@@ -121,19 +121,19 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html
image_url: https://about.gitlab.com/images/14_1/status-checks-pending.png
published_at: 2021-07-22
release: 14.1
-- title: Pronouns viewable in user profile snapshot
- body: |
+- name: Pronouns viewable in user profile snapshot
+ description: |
You can now see pronouns on the snapshot view of a user profile when you hover over someone's name on an issue or merge request. This helps users better respond to comments using the correct pronouns without needing to navigate to the user's profile.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns'
image_url: https://about.gitlab.com/images/14_1/pronouns.png
published_at: 2021-07-22
release: 14.1
diff --git a/data/whats_new/202108190001_14_02.yml b/data/whats_new/202108190001_14_02.yml
index 99ba097b60c..bb9c8becd06 100644
--- a/data/whats_new/202108190001_14_02.yml
+++ b/data/whats_new/202108190001_14_02.yml
@@ -1,85 +1,85 @@
-- title: Add pronunciation to GitLab profile page
- body: |
+- name: Add pronunciation to GitLab profile page
+ description: |
You can now add pronunciation to your user profile. In distributed teams where team members are from different countries, it can be difficult to determine how to say someone's name correctly. This will help others know how to pronounce your name.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/profile/#add-your-pronunciation'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/profile/#add-your-pronunciation'
image_url: https://about.gitlab.com/images/14_2/pronounce.png
published_at: 2021-08-22
release: 14.2
-- title: View historical CI pipeline minute usage
- body: |
+- name: View historical CI pipeline minute usage
+ description: |
Before GitLab 14.2, the CI pipeline minutes usage on the [Usage Quotas](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#shared-runners-pipeline-minutes-quota) page only showed the current month's usage. This data would reset every month and there was no way to view activity from the past months for analyzing historical usage.
Now there are two charts that show historical CI pipeline minutes usage by month or by project, so you can make informed decisions about your pipeline usage.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/subscriptions/gitlab_com/index.html#ci-pipeline-minutes'
image_url: https://about.gitlab.com/images/14_2/CI_minutes_usage_graph.png
published_at: 2021-08-22
release: 14.2
-- title: Edit issue title from an issue board
- body: |
+- name: Edit issue title from an issue board
+ description: |
Editing an issue in an issue board currently requires many steps and takes you out of your workflow. We've added an easy way to edit an issue's title right in the issue board, without navigating to another page. To edit the title, in the right sidebar, select the issue, then select **Edit**.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/project/issue_board.html#edit-an-issue'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/project/issue_board.html#edit-an-issue'
image_url: https://about.gitlab.com/images/14_2/issue-board-edit-title.gif
published_at: 2021-08-22
release: 14.2
-- title: Preview Markdown live while editing
- body: |
+- name: Preview Markdown live while editing
+ description: |
Markdown is a fast and intuitive syntax for writing rich web content. Until it isn't. Luckily, it's easy to preview the rendered output of Markdown to ensure the accuracy of your markup from the **Preview** tab. Unfortunately, the context switch required to move between the raw source code and the preview can be tedious and disruptive to your flow.
Now, in both the Web IDE and single file editor, Markdown files have a new live preview option available. Right-click the editor and select **Preview Markdown** or use `Command/Control + Shift + P` to toggle a split-screen live preview of your Markdown content. The preview refreshes as you type, so you can be confident that your markup is valid and will render as you intended.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/project/web_ide/#markdown-editing'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/project/web_ide/#markdown-editing'
image_url: https://about.gitlab.com/images/14_2/create-markdown-live-preview.png
published_at: 2021-08-22
release: 14.2
-- title: Stageless pipelines
- body: |
+- name: Stageless pipelines
+ description: |
Using the [`needs`](https://docs.gitlab.com/ee/ci/yaml/#needs) keyword in your pipeline configuration helps to reduce cycle times by ignoring stage ordering and running jobs without waiting for others to complete. Previously, `needs` could only be used between jobs on different stages.
In this release, we've removed this limitation so you can define a `needs` relationship between any job you want. As a result, you can now create a complete CI/CD pipeline without using stages by including `needs` in every job to implicitly configure the execution order. This lets you define a less verbose pipeline that takes less time to create and can run even faster.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/yaml/#needs'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/yaml/#needs'
image_url: https://about.gitlab.com/images/14_2/need.png
published_at: 2021-08-22
release: 14.2
-- title: New GitLab Kubernetes Agent UI
- body: |
+- name: New GitLab Kubernetes Agent UI
+ description: |
The GitLab Kubernetes Agent allows a secure bi-directional connection between GitLab and any Kubernetes cluster. Until now, registering a new Kubernetes Agent required writing GraphQL queries.
As of GitLab 14.2, GitLab ships with a user-friendly user interface and a registration form to help you get started with the Kubernetes Agent with ease.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/clusters/agent/'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/clusters/agent/'
image_url: https://about.gitlab.com/images/14_2/k8s-agent-registration.png
published_at: 2021-08-22
release: 14.2
-- title: Create a GitLab branch from a Jira issue
- body: |
+- name: Create a GitLab branch from a Jira issue
+ description: |
Users of the [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) application can now create GitLab branches directly from a Jira issue's [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/). This enables developers to begin work on issues without having to switch tools and lose context.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/integration/jira/connect-app.html'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/integration/jira/connect-app.html'
image_url: https://about.gitlab.com/images/14_2/jira_dev_panel_jira_setup_3.png
published_at: 2021-08-22
release: 14.2
diff --git a/data/whats_new/202109200001_14_03.yml b/data/whats_new/202109200001_14_03.yml
index fa0f05bf0a0..59d2655f072 100644
--- a/data/whats_new/202109200001_14_03.yml
+++ b/data/whats_new/202109200001_14_03.yml
@@ -1,83 +1,83 @@
-- title: Project-level DAST and secret detection scan execution policies
- body: |
+- name: Project-level DAST and secret detection scan execution policies
+ description: |
We have completed the first iterative step [toward our vision](https://about.gitlab.com/direction/protect/security_orchestration/) of bringing unified security policies to GitLab. Users can now require DAST and secret detection scans to run on a regular schedule or as part of project CI pipelines, independent of the `.gitlab-ci.yml` file's contents. This allows security teams to separately manage these scan requirements without allowing developers to change the configuration. You can get started with these policies on the **Security & Compliance > Policies** page.
stage: Protect
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/policies/'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/policies/'
image_url: https://about.gitlab.com/images/14_3/security_policies.png
published_at: 2021-09-22
release: 14.3
-- title: Next Generation SAST to reduce Ruby false positives
- body: |
+- name: Next Generation SAST to reduce Ruby false positives
+ description: |
GitLab SAST historically has been powered by [over a dozen open-source static analysis security analyzers](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). These analyzers have proactively identified millions of vulnerabilities for developers using GitLab every month. These tools use a variety of different approaches for identifying vulnerabilities from basic regex pattern matching to abstract syntax tree parsing which can lead to issues with false positives. GitLab's Secure tools already offer vulnerability fingerprinting allowing you to dismiss these false positives persistently, however, we want to go a step further and not require this manual triaging.
Today we're releasing the first version of our proprietary static application security testing engine built in-house and maintained by GitLab's Static Analysis and Vulnerability Research groups. Initially, this tool is focused on Ruby and Rails to help reduce false positives.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/sast/#false-positive-detection'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/sast/#false-positive-detection'
image_url: https://about.gitlab.com/images/14_3/secure-fp-reduction-ui.png
published_at: 2021-09-22
release: 14.3
-- title: Group-level permissions for Protected Environments
- body: |
+- name: Group-level permissions for Protected Environments
+ description: |
In this release, we are introducing group-level protected environments, based on the [deployment tier](https://docs.gitlab.com/ee/ci/environments/index.html#deployment-tier-of-environments) as the identifier. This enables operators to responsibly lock down deployments to higher tier environments without unnecessarily preventing developers from doing their work as the maintainers of their individual projects.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/environments/protected_environments.html#group-level-protected-environments'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/environments/protected_environments.html#group-level-protected-environments'
image_url: https://about.gitlab.com/images/growth/release.png
published_at: 2021-09-22
release: 14.3
-- title: Edit a table's structure visually in the new wiki editor
- body: |
+- name: Edit a table's structure visually in the new wiki editor
+ description: |
Editing a Markdown table that has 9 columns and 25 rows is one thing. But adding a tenth column to that table in Markdown? That involves very repetitive and error-prone edits to every row. One mistake or misplaced `|` and the table fails to render.
The new WYSIWYG Markdown editor in the wiki lets you quickly and easily insert a table using the button in the toolbar. After selecting the initial number of rows and columns, however, dealing with the structure of the table can be more difficult. In GitLab 14.3, you can now click on the caret icon in the top right corner of any selected cell to add or remove columns and rows, either before or after the selected cell. Now, as your content scales, the complexity doesn't follow suit.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/project/wiki/#content-editor'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/project/wiki/#content-editor'
image_url: https://about.gitlab.com/images/14_3/wiki-editor-edit-table-structure.png
published_at: 2021-09-22
release: 14.3
-- title: Use variables in other variables
- body: |
+- name: Use variables in other variables
+ description: |
CI/CD pipeline execution scenarios can depend on expanding variables declared in a pipeline or using GitLab predefined variables within another variable declaration. In 14.3, we are enabling the "variables inside other variables" feature on GitLab SaaS. Now you can define a variable and use it in another variable definition within the same pipeline. You can also use GitLab predefined variables inside of another variable declaration. This feature simplifies your pipeline definition and eliminates pipeline management issues caused by the duplicating of variable data. Note - for GitLab self-managed customers the feature is disabled by default. To use this feature, your GitLab administrator will need to enable the [feature flag](https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html#nested-variable-expansion).
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/variables/#use-variables-in-other-variables'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/variables/#use-variables-in-other-variables'
image_url: https://about.gitlab.com/images/growth/verify.png
published_at: 2021-09-22
release: 14.3
-- title: Add GitLab CI/CD configuration conditionally with `include`
- body: |
+- name: Add GitLab CI/CD configuration conditionally with `include`
+ description: |
[`include`](https://docs.gitlab.com/ee/ci/yaml/index.html#include) is one of the most popular keywords to use when writing a full CI/CD pipeline. If you are building larger pipelines, you are probably using the `include` keyword to bring external YAML configuration into your pipeline.
In this release, we are expanding the power of the keyword so you can use `include` with [`rules`](https://docs.gitlab.com/ee/ci/yaml/index.html#include) conditions. Now, you can decide when external CI/CD configuration should or shouldn't be included. This will help you write a standardized pipeline with the ability to dynamically modify itself based on the conditions you choose.
stage: Verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/#amazing'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/#amazing'
image_url: https://about.gitlab.com/images/14_3/conditional_include.png
published_at: 2021-09-22
release: 14.3
-- title: Grant group access to the GitLab Kubernetes Agent
- body: |
+- name: Grant group access to the GitLab Kubernetes Agent
+ description: |
The GitLab Kubernetes Agent provides a secure connection between a Kubernetes cluster and GitLab. Until GitLab 14.2, the GitLab CI/CD enabled pushing to a cluster only from the same project where the Kubernetes Agent was registered. In GitLab 14.3, the Agent can be authorized to access entire groups. As a result, every project under the authorized group has access to the cluster without the need to register an agent for every project.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/clusters/agent/repository.html#authorize-groups-to-use-an-agent'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/clusters/agent/repository.html#authorize-groups-to-use-an-agent'
image_url: https://about.gitlab.com/images/growth/configure.png
published_at: 2021-09-22
release: 14.3
diff --git a/data/whats_new/2021102000001_14_04.yml b/data/whats_new/2021102000001_14_04.yml
index 13caddd2bc5..3342be0c34f 100644
--- a/data/whats_new/2021102000001_14_04.yml
+++ b/data/whats_new/2021102000001_14_04.yml
@@ -1,16 +1,16 @@
-- title: Scheduled DAST scans
- body: |
+- name: Scheduled DAST scans
+ description: |
GitLab’s Dynamic Application Security Testing (DAST) now supports scheduled on-demand scans. Previously, on-demand DAST scans could only be manually triggered, which limited the usability to scans that you wanted to run immediately. With this new scheduler, you can set a DAST scan to run either once at a specific time in the future, or on a recurring basis. If adding DAST to your pipelines is not an option for your organization, or if the security or compliance regulations for your area require a scan to be scheduled, this feature provides an easy way to create a scheduled scan to meet your needs. The scan can be associated with the default branch, which allows for the results to show on the Secure Dashboard and Vulnerability list. Combined with the scan and site profiles, the scheduled on-demand scans give you quick and easy access to DAST results for your application or API, on a schedule that works for your development and security teams.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/dast/index.html#schedule-an-on-demand-scan'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/dast/index.html#schedule-an-on-demand-scan'
image_url: https://about.gitlab.com/images/14_4/dast_on_demand_schedule.png
published_at: 2021-10-22
release: 14.4
-- title: Remote Repositories for GitLab in Visual Studio Code
- body: |
+- name: Remote Repositories for GitLab in Visual Studio Code
+ description: |
When working in your editor you may need to refer to another project or upstream library for additional information. When you don't have that project already cloned locally, you're forced to either leave your editor and browse the project on GitLab, or locate and then clone the project so you can browse it in your editor. Both of those tasks break your current context, introduce delays, and can take you to a less familiar interface for working with code.
[GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) version `3.33.0` provides an option to open a remote repository. Open the command palette and use the `GitLab: Open Remote Repository` command to find and then open a project.
@@ -19,41 +19,41 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#browse-a-repository-without-cloning'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#browse-a-repository-without-cloning'
image_url: https://img.youtube.com/vi/p4GTVx_Nd2s/hqdefault.jpg
published_at: 2021-10-22
release: 14.4
-- title: The GitLab Operator is Generally Available
- body: |
+- name: The GitLab Operator is Generally Available
+ description: |
GitLab 14.4 is proud to announce the general availability of [the GitLab Operator](https://about.gitlab.com/blog/2021/10/12/open-shift-ga/), with the ability to run production instances of GitLab on Kubernetes platforms, including Red Hat OpenShift. The GitLab Operator also automates day 2 operations such as upgrading components, application reconfiguration, and autoscaling. Check out the [GitLab Operator installation documentation](https://docs.gitlab.com/charts/installation/operator.html) for additional information.
stage: Enablement
self-managed: true
gitlab-com: false
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/charts/installation/operator.html'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/charts/installation/operator.html'
image_url: https://img.youtube.com/vi/sEBnuhzYD2I/hqdefault.jpg
published_at: 2021-10-22
release: 14.4
-- title: DevOps Adoption trend graph
- body: |
+- name: DevOps Adoption trend graph
+ description: |
In GitLab 14.4, we added a new graph to group-level DevOps Adoption for trend over time. This graph shows you how groups adopt DevOps features over time and can give insights into how quickly groups are adopting additional DevOps processes. This is broken down by Dev, Sec, and Ops functionality.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/group/devops_adoption/#adoption-over-time'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/group/devops_adoption/#adoption-over-time'
image_url: https://about.gitlab.com/images/14_4/devops_adop_table.png
published_at: 2021-10-22
release: 14.4
-- title: Integrated error tracking inside GitLab without a Sentry instance
- body: |
+- name: Integrated error tracking inside GitLab without a Sentry instance
+ description: |
Prior to GitLab 14.4, you could integrate with Sentry Error Tracking by supplying an endpoint for a Sentry backend (either self-deployed or in their cloud service). With GitLab 14.4, you now have access to a Sentry-compatible backend built into your GitLab instance. This allows you to quickly instrument your apps so your errors show up directly in GitLab without the need for a separate Sentry instance.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/operations/error_tracking.html#integrated-error-tracking'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/operations/error_tracking.html#integrated-error-tracking'
image_url: https://about.gitlab.com/images/14_4/monitor-integrated-error-tracking.png
published_at: 2021-10-22
release: 14.4
diff --git a/data/whats_new/2021111800001_14_05.yml b/data/whats_new/2021111800001_14_05.yml
index 71f4b0245b9..967d8b05cfa 100644
--- a/data/whats_new/2021111800001_14_05.yml
+++ b/data/whats_new/2021111800001_14_05.yml
@@ -1,27 +1,27 @@
-- title: Introducing Infrastructure as Code (IaC) security scanning
- body: |
+- name: Introducing Infrastructure as Code (IaC) security scanning
+ description: |
With GitLab 14.5 we're introducing security scanning for Infrastructure as Code (IaC) configuration files. Like all our SAST scanners, we've chosen to make this capability available for all customers for free to encourage secure coding practices with the rise of IaC. The initial version of this IaC security scanner supports configuration files for Terraform, Ansible, AWS CloudFormation, and Kubernetes and is based on the open-source [Keeping Infrastructure as Code Secure (KICS) project](https://kics.io/). This new IaC scanning capability joins our [existing Kubernetes manifest SAST scanner](https://docs.gitlab.com/ee/user/application_security/sast/#enabling-kubesec-analyzer).
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/iac_scanning/'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/iac_scanning/'
image_url: https://about.gitlab.com/images/14_5/gitlab-iac.png
published_at: 2021-11-22
release: 14.5
-- title: Add personal README to profile
- body: |
+- name: Add personal README to profile
+ description: |
You can now add a README section to your GitLab profile! This is a great way to tell others about, your interests, how you work, or anything else you want! To add a README section, create a new public project with the same name as your user account and add a new [README file](https://docs.gitlab.com/ee/user/project/repository/index.html#readme-and-index-files). The contents of that file are automatically shown on your GitLab profile.
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/profile/#add-details-to-your-profile-with-a-readme'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/profile/#add-details-to-your-profile-with-a-readme'
image_url: https://about.gitlab.com/images/14_5/user_profiles_readme.png
published_at: 2021-11-22
release: 14.5
-- title: Geo provides a single command to promote a secondary node
- body: |
+- name: Geo provides a single command to promote a secondary node
+ description: |
When performing a failover, systems administrators use different tools depending on the underlying architecture. On a single-node Geo site, administrators can use the `gitlab-ctl promote-to-primary-node` command. However, multi-node sites did not support this command and required manual editing of configuration. This was cumbersome for large environments because it required updating dozens of configuration files.
Now, administrators can use `gitlab-ctl geo promote` on any node of a Geo secondary site to promote it to a primary. In a disaster recovery scenario or planned failover, this saves precious time and reduces potential errors when promoting a secondary site to a primary. This command also makes it easier to script the failover process.
@@ -30,13 +30,13 @@
stage: Enablement
self-managed: true
gitlab-com: false
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/administration/geo/disaster_recovery/planned_failover.html'
image_url: https://about.gitlab.com/images/growth/enablement.png
published_at: 2021-11-22
release: 14.5
-- title: Group-level settings for merge request approvals
- body: |
+- name: Group-level settings for merge request approvals
+ description: |
You can now define and enforce values for merge request approval settings at the group level. These values cascade and are used by any projects within the group. Group-level merge request approvals make it easy for organizations to ensure proper separation of duties across all teams. You only have to specify settings in a single location now, rather than needing to update and monitor every project.
When these settings are set at the group level, you:
@@ -46,32 +46,32 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/group/#group-approval-rules'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/group/#group-approval-rules'
image_url: https://about.gitlab.com/images/14_5/group_level_mr_settings_picture.png
published_at: 2021-11-22
release: 14.5
-- title: GitLab Kubernetes Agent available in GitLab Free
- body: |
+- name: GitLab Kubernetes Agent available in GitLab Free
+ description: |
Connecting a Kubernetes cluster with the GitLab Kubernetes Agent simplifies the setup for cluster applications and enables secure GitOps deployments to the cluster. Initially, the GitLab Kubernetes Agent was available only for Premium users. In our commitment to the open source ethos, we moved the core features of the GitLab agent for Kubernetes and the ability to use CI/CD with Kubernetes to GitLab Free. We expect that the open-sourced features are compelling to many users without dedicated infrastructure teams and strong requirements around cluster management. Advanced features remain available as part of the GitLab Premium offering.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/clusters/agent/'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/clusters/agent/'
image_url: https://about.gitlab.com/images/growth/configure.png
published_at: 2021-11-22
release: 14.5
-- title: Cleaner diffs for Jupyter Notebook files
- body: |
+- name: Cleaner diffs for Jupyter Notebook files
+ description: |
Jupyter notebooks are key to data scientists' and machine learning engineers' workflows, but the file structure makes code review challenging. Often, the files can't be reviewed properly, and users are forced to accept those changes or treat their repositories as stores of data versus collaborative projects.
Now GitLab automatically strips out the noise and displays a cleaner version of the diff for these files. Human-readable diffs make it easier to review the substance of the change, without worrying about the formatting pieces that Jupyter Notebooks need.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/project/repository/jupyter_notebooks/#cleaner-diffs'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/project/repository/jupyter_notebooks/#cleaner-diffs'
image_url: https://about.gitlab.com/images/14_5/create-code-review-jupyter-notebook-diffs.png
published_at: 2021-11-22
release: 14.5
diff --git a/data/whats_new/202112200001_14_06.yml b/data/whats_new/202112200001_14_06.yml
index 178cc4dc019..c0d6426209f 100644
--- a/data/whats_new/202112200001_14_06.yml
+++ b/data/whats_new/202112200001_14_06.yml
@@ -1,57 +1,57 @@
-- title: Seamless worldwide performance with Geo
- body: |
+- name: Seamless worldwide performance with Geo
+ description: |
In GitLab 14.6, Geo secondary sites transparently proxy write requests to the primary site while accelerating most read requests. Systems administrators can provide all GitLab users across their organization with a single URL that automatically uses the Geo site closest to them. Users no longer need to use different configuration to benefit from Geo, or worry about what operations won’t work on Geo secondary sites. Globally distributed teams now benefit from accelerated git clone or git pull commands, and a seamless worldwide experience.
stage: Enablement
self-managed: true
gitlab-com: false
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/administration/geo/secondary_proxy/'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/administration/geo/secondary_proxy/'
image_url: https://about.gitlab.com/images/14_6/geo_secondary_proxy_flow.png
published_at: 2021-12-22
release: 14.6
-- title: GitLab Agent's activity information
- body: |
+- name: GitLab Agent's activity information
+ description: |
Being able to monitor your cluster's activity helps you detect and troubleshoot faulty events, and rest assured when they succeed. GitLab now ships with an activity list for the GitLab Agent that logs real-time events. This first implementation logs connection and token statuses and will be followed with more events in future releases.
stage: Configure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/clusters/agent/install/#view-agent-activity-information'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/clusters/agent/install/#view-agent-activity-information'
image_url: https://about.gitlab.com/images/14_6/gitlab_agent_activity_events_v14_6.png
published_at: 2021-12-22
release: 14.6
-- title: SAST Support for .NET 6
- body: |
+- name: SAST Support for .NET 6
+ description: |
We have updated our .NET SAST analyzer, [Security Code Scan](https://security-code-scan.github.io/), to support this new version, which is also now supported with [our SAST language detection](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks), allowing GitLab SAST to automatically detect .NET 6 projects. This change was part of a community contribution by [@vasyl11](https://gitlab.com/vasyl11) at [Clay Solutions](https://my-clay.com/), who we thank for their efforts.
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/sast/analyzers'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/sast/analyzers'
image_url: https://about.gitlab.com/images/14_6/14_6-cover-image.jpg
published_at: 2021-12-22
release: 14.6
-- title: Toggle wiki editors seamlessly
- body: |
+- name: Toggle wiki editors seamlessly
+ description: |
Editing wiki pages with the new rich Markdown editor makes it easier for everyone to contribute regardless of how well they know Markdown syntax. You may also prefer to write raw Markdown in some situations, but use the WYSIWYG interface for more complex or tedious formatting tasks, like creating tables.
Previous versions of GitLab required you to save changes before switching between the rich Markdown editor and the Markdown source, adding more steps and friction to your edits. In GitLab 14.6 you can now seamlessly switch between the two editing experiences without committing your changes, choosing the editor that suits your needs at any given moment.
stage: Create
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/project/wiki/#content-editor'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/project/wiki/#content-editor'
image_url: https://docs.gitlab.com/ee/user/project/wiki/img/content_editor_v14.6.png
published_at: 2021-12-22
release: 14.6
-- title: Custom ruleset composability for SAST and Secret Detection
- body: |
+- name: Custom ruleset composability for SAST and Secret Detection
+ description: |
Custom Rulesets let users tailor the behavior of SAST and Secret Detection analyzers to their organization’s preferences. We're introducing the ability to add rules from multiple sources, like Git repositories, local files, and raw source changes. This change makes it easier to synthesize and manage multiple custom rulesets from different locations, which organizations can use to inherit rules across repositories and sources for greater flexibility. Initially, this change is available for our [SAST Semgrep, Nodejs, and Gosec analyzers](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) and [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/#custom-rulesets). We will expand this capability to our other analyzers [in future releases](https://gitlab.com/groups/gitlab-org/-/epics/4179).
stage: Secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets'
image_url: https://docs.gitlab.com/ee/user/application_security/img/mr_security_scanning_results_v14_3.png
published_at: 2021-12-22
release: 14.6
diff --git a/data/whats_new/202201200001_14_07.yml b/data/whats_new/202201200001_14_07.yml
index d8c76334775..2b389621253 100644
--- a/data/whats_new/202201200001_14_07.yml
+++ b/data/whats_new/202201200001_14_07.yml
@@ -1,16 +1,16 @@
-- title: GitLab Runner compliant with FIPS 140-2
- body: |
+- name: GitLab Runner compliant with FIPS 140-2
+ description: |
For some GitLab customers, U.S. government regulatory requirements require the use of FIPS (Federal Information Processing Standards) compliant software. The FIPS 140-2 and FIPS 140-3 publications define the security requirements for cryptographic modules used in computer and telecommunication systems, and within cyber systems that protect sensitive information. GitLab Runner is now FIPS 140-2 compliant for AMD64 compute architectures and Red Hat Enterprise Linux (RHEL) distributions. Refer to [this epic](https://gitlab.com/groups/gitlab-org/-/epics/5104) to follow the discussions about making GitLab FIPS compliant.
stage: Verify
self-managed: true
gitlab-com: false
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/runner/install/index.html#fips-compliant-gitlab-runner'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/runner/install/index.html#fips-compliant-gitlab-runner'
image_url: https://about.gitlab.com/images/growth/verify.png
published_at: 2022-01-22
release: 14.7
-- title: Streaming audit events
- body: |
+- name: Streaming audit events
+ description: |
You can now stream audit events to a destination of your choosing! This is a great way to correlate GitLab audit events with other data streams you have, maintain a backup of audit events, or build out your own automation to take action when a specific audit event happens.
You can specify an HTTPS endpoint with our new GraphQL API and events are sent to it as webhooks. These messages contain the same information as the Audit Events UI about what type of change happened, when it happened, who was involved, as well as some additional metadata.
@@ -19,13 +19,13 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/administration/audit_event_streaming.html'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/administration/audit_event_streaming.html'
image_url: https://about.gitlab.com/images/growth/manage.jpg
published_at: 2022-01-22
release: 14.7
-- title: Group access tokens
- body: |
+- name: Group access tokens
+ description: |
With group access tokens, you can use a single token to perform actions for groups, manage the projects within the group, and, in GitLab 14.2 and later, authenticate with Git over HTTPS.
Previously, group access tokens were limited to self-managed instances only, and could only be generated using the Rails console. Now, you can create group access tokens using the UI and API. You can define token name, expiration date, and scope. You can also revoke an existing group access token.
@@ -34,8 +34,8 @@
stage: Manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/group/settings/group_access_tokens.html'
image_url: https://about.gitlab.com/images/14_7/group_access_token.png
published_at: 2022-01-22
release: 14.7
diff --git a/data/whats_new/202202210001_14_08.yml b/data/whats_new/202202210001_14_08.yml
index 930535dd4e0..206fec03359 100644
--- a/data/whats_new/202202210001_14_08.yml
+++ b/data/whats_new/202202210001_14_08.yml
@@ -1,5 +1,5 @@
-- title: "Support for ecdsa-sk and ed25519-sk SSH keys"
- body: |
+- name: "Support for ecdsa-sk and ed25519-sk SSH keys"
+ description: |
[OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) added support for FIDO/U2F hardware authenticators with new
ecdsa-sk and ed25519-sk key types.
@@ -7,24 +7,24 @@
stage: manage
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ssh/#generate-an-ssh-key-pair-for-a-fidou2f-hardware-security-key'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ssh/#generate-an-ssh-key-pair-for-a-fidou2f-hardware-security-key'
image_url: 'https://about.gitlab.com/images/14_8/ssh_key.png'
published_at: 2022-02-22
release: 14.8
-- title: "Auto-completion of keywords in the Pipeline Editor"
- body: |
+- name: "Auto-completion of keywords in the Pipeline Editor"
+ description: |
Writing a valid GitLab CI/CD pipeline can be difficult regardless of whether you're a novice or more advanced user. Syntax structure should be accurate and even a small typo or misconfiguration could cause your pipeline to be invalid, introducing more work to find the source of the problem. In this release, we've added auto-completion of CI/CD keywords to the pipeline editor, which will greatly increase your efficiency when writing and debugging pipelines. You'll be more confident that your pipeline will run the way you want it the very first time it runs.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/pipeline_editor/index.html#validate-ci-configuration'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/pipeline_editor/index.html#validate-ci-configuration'
image_url: 'https://about.gitlab.com/images/growth/verify.png'
published_at: 2022-02-22
release: 14.8
-- title: "Security approval policies"
- body: |
+- name: "Security approval policies"
+ description: |
GitLab now supports flexible security approvals as the replacement for the deprecated Vulnerability-Check feature. Security approvals are similar to Vulnerability-Check in that both can require approvals for MRs that contain security vulnerabilities. However, security approvals improve the previous experience in several ways:
- Users can choose who is allowed to edit security approval rules. An independent security or compliance team can therefore manage rules in a way that prevents development project maintainers from modifying the rules.
@@ -36,24 +36,24 @@
stage: protect
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/policies/scan-result-policies'
image_url: 'https://about.gitlab.com/images/14_8/protect-security-approval-policies.png'
published_at: 2022-02-22
release: 14.8
-- title: "On-demand security scan index view"
- body: |
+- name: "On-demand security scan index view"
+ description: |
Find all your on-demand DAST and DAST API scans on a single page. We have introduced a new index page for on-demand scans that shows your in-progress scans, previously run scans, saved scans, and scheduled scans. From this index page, you can find specific scans easily or re-run scans that have already finished. In previous versions of GitLab, to see on-demand scans that were in-progress or had finished, you needed to search through the pipelines page to find the right pipeline. Saved on-demand scans were located in the Security & Compliance configuration section. To find scheduled scans, you needed to look at each saved scan individually to see their schedule. All of those activities are now rolled into one page to make it easier to run on-demand security testing outside of CI/CD builds, MRs, or pipelines.
stage: secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/dast/#view-on-demand-dast-scans'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/dast/#view-on-demand-dast-scans'
image_url: 'https://about.gitlab.com/images/14_8/dast-on-demand-index-page.png'
published_at: 2022-02-22
release: 14.8
-- title: "User impersonation audit events for groups"
- body: |
+- name: "User impersonation audit events for groups"
+ description: |
GitLab now provides audit events on the group audit events page for
[user impersonation](https://docs.gitlab.com/ee/user/admin_area/#user-impersonation) starting and stopping. This was previously
only available on a page unavailable to GitLab SaaS customers. We are excited to bring
@@ -71,21 +71,21 @@
stage: manage
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/administration/audit_events.html#group-events'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/administration/audit_events.html#group-events'
image_url: 'https://about.gitlab.com/images/14_8/impersonation_audit_event.png'
published_at: 2022-02-22
release: 14.8
-- title: "Additional display options for roadmaps"
- body: |
+- name: "Additional display options for roadmaps"
+ description: |
In this release, we have introduced additional progress tracking capabilities to roadmaps. You can now view the percentage of completed epics based on issue count instead of issue weight. This functionality is useful for organizations that are using Kanban or other methodologies that don't require their teams to set a weight on issues.
You can now also customize the level of milestones to include in your roadmap, allowing you to tailor your view to meet the needs of your audience.
stage: plan
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/user/group/roadmap/index.html#roadmap-settings'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/group/roadmap/index.html#roadmap-settings'
image_url: 'https://about.gitlab.com/images/14_8/rp_roadmap_settings.png'
published_at: 2022-02-22
release: 14.8
diff --git a/data/whats_new/202203210001_14_09.yml b/data/whats_new/202203210001_14_09.yml
index 05a5899d751..027f42fda1b 100644
--- a/data/whats_new/202203210001_14_09.yml
+++ b/data/whats_new/202203210001_14_09.yml
@@ -1,62 +1,62 @@
-- title: "Link an epic to another epic"
- body: |
+- name: "Link an epic to another epic"
+ description: |
GitLab now supports linking epics using "related", "blocking," or "blocked" relationships. This feature enables teams to better track and manage epic dependencies across GitLab groups. Effective dependency management is a key component of reducing variability and increasing predictability in value delivery.
stage: plan
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/group/epics/linked_epics.html'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/group/epics/linked_epics.html'
image_url: 'https://about.gitlab.com/images/14_9/related_epics_add.png'
published_at: 2022-03-22
release: 14.9
-- title: "Rule mode for scan result policies"
- body: |
+- name: "Rule mode for scan result policies"
+ description: |
With the GitLab 14.9 release, users can now use rule mode to design and edit scan result policies without needing to edit the policy's YAML directly. This new UI editor makes it easier for users who want to create and manage MR approval rules that are triggered when a given threshold of vulnerabilities are detected in the MR.
To get started with this new rule mode, navigate to **Security & Compliance > Policies** and create a new Scan Result policy.
stage: protect
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/policies/#policy-editor'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/policies/#policy-editor'
image_url: 'https://about.gitlab.com/images/14_9/protect-scan-result-policy-rule-mode.png'
published_at: 2022-03-22
release: 14.9
-- title: "Deployment Approval on the Environments page"
- body: |
+- name: "Deployment Approval on the Environments page"
+ description: |
We are excited to introduce the Deployment Approval capability in the GitLab interface. In GitLab 14.8, we introduced the ability to approve deployments via the [API](https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#using-the-api). Now, deployment approvers can view a pending deployment and approve or reject it conveniently directly in the Environments page. This update continues our work to enable teams to create workflows for approving software to go to production or other protected environments. With this update, we are now upgrading the feature to beta.
stage: "Release"
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#approve-or-reject-a-deployment'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#approve-or-reject-a-deployment'
image_url: 'https://about.gitlab.com/images/growth/release.png'
published_at: 2022-03-22
release: 14.9
-- title: "New design for the Environments Page"
- body: |
+- name: "New design for the Environments Page"
+ description: |
Previously, the Environments page enabled you to operate and understand deployments but the design hid some important information and was difficult to read. In GitLab 14.9, we made a comprehensive update to the page so that you can answer key questions about your environments and deployments. Now, you can easily see the status of the latest deployment, the status for various environments, and which commits have been deployed.
stage: "Release"
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/environments/#view-environments-and-deployments'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/environments/#view-environments-and-deployments'
image_url: 'https://about.gitlab.com/images/14_9/release-enviroments-page-redesign.png'
published_at: 2022-03-22
release: 14.9
-- title: "Project Level Time to restore service API"
- body: |
+- name: "Project Level Time to restore service API"
+ description: |
In this release, we added API support for Time to Restore Service. This is the 3rd of the 4 [DORA Metrics](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#devops-research-and-assessment-dora-key-metrics). This data helps teams continuously improve in their stability metrics.
stage: manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/api/dora/metrics.html'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/api/dora/metrics.html'
image_url: 'https://about.gitlab.com/images/14_9/ttr_api.png'
published_at: 2022-03-22
release: 14.9
-- title: "Integrated security training"
- body: |
+- name: "Integrated security training"
+ description: |
GitLab provides a comprehensive set of [security scanning tools](https://docs.gitlab.com/ee/user/application_security/#security-scanning-tools)
that can identify all manner of security issues. Scanner findings are presented
in merge requests, pipelines, and in a dedicated Vulnerability Report. When
@@ -78,8 +78,8 @@
stage: secure
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#enable-security-training-for-vulnerabilities'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#enable-security-training-for-vulnerabilities'
image_url: 'https://about.gitlab.com/images/14_9/secure-enable-security-training.png'
published_at: 2022-03-22
release: 14.9
diff --git a/data/whats_new/202204210001_14_10.yml b/data/whats_new/202204210001_14_10.yml
index 2f3d32bd87c..c4028662f59 100644
--- a/data/whats_new/202204210001_14_10.yml
+++ b/data/whats_new/202204210001_14_10.yml
@@ -1,48 +1,48 @@
-- title: "Compliance report individual violation reporting"
- body: |
+- name: "Compliance report individual violation reporting"
+ description: |
The compliance report now reports every individual merge request violation for the projects within a group. This is a huge improvement over the previous version, which only showed the latest MR that had one or more violations. The new version allows you to see history and patterns of violations over time.
stage: manage
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: 'https://docs.gitlab.com/ee/user/compliance/compliance_report/'
+ available_in: [Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/user/compliance/compliance_report/'
image_url: 'https://about.gitlab.com/images/14_10/manage_compliance_report_individual_violation.png'
published_at: 2022-04-22
release: 14.10
-- title: "Improved pipeline variables inheritance"
- body: |
+- name: "Improved pipeline variables inheritance"
+ description: |
Previously, it was possible to pass some CI/CD variables to a downstream pipeline through a trigger job, but variables added in manual pipeline runs or by using the API could not be forwarded.
In this release we've added a new `trigger:forward` keyword to control what things you forward to downstream parent-child pipelines or multi-project pipelines, which provides a flexible way to handle variable inheritance in downstream pipelines.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/yaml/#triggerforward'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/yaml/#triggerforward'
image_url: 'https://about.gitlab.com/images/growth/verify.png'
published_at: 2022-04-22
release: 14.10
-- title: "Escalating manually created incidents"
- body: |
+- name: "Escalating manually created incidents"
+ description: |
Incident Management is set up to trigger escalation policies for new alerts. In this scenario, the on-call responder who is paged can end the paging by acknowledging the alert. If the responder changes the status back to triggered, we restart the escalation policy and begin paging again. When a user creates an incident manually, there is no associated alert and therefore no way to page on-call responders.
This release enables paging on manually created incidents. Responders now have the ability to acknowledge the page on incidents, or restart paging by resetting the status to triggered, just as you can for alerts.
stage: monitor
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/operations/incident_management/paging.html#escalating-an-incident'
+ available_in: [Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/operations/incident_management/paging.html#escalating-an-incident'
image_url: 'https://about.gitlab.com/images/14_10/manually_escalated_incident.png'
published_at: 2022-04-22
release: 14.10
-- title: "Expanded view of group runners"
- body: |
+- name: "Expanded view of group runners"
+ description: |
Group runners are now displayed in an expanded view, where you can more easily administer and manage the runners associated with the namespace. To view the new UI, on the left sidebar, select **CI/CD**. This view includes the number of online, offline, and stale runners associated with the group and subgroups.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: 'https://docs.gitlab.com/ee/ci/runners/runners_scope.html#group-runners'
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: 'https://docs.gitlab.com/ee/ci/runners/runners_scope.html#group-runners'
image_url: 'https://about.gitlab.com/images/14_10/group-runners-view-new-3.png'
published_at: 2022-04-22
release: 14.10
diff --git a/data/whats_new/202205220001_15_0.yml b/data/whats_new/202205220001_15_0.yml
index 8aa09d442c8..e1449f13c0a 100644
--- a/data/whats_new/202205220001_15_0.yml
+++ b/data/whats_new/202205220001_15_0.yml
@@ -1,5 +1,5 @@
-- title: Edit code blocks, links, and media inline in the WYSIWYG editor # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Edit code blocks, links, and media inline in the WYSIWYG editor # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
GitLab 15.0 includes a few exciting improvements to speed up your workflow in the WYSIWYG Markdown editor for your wikis.
First, you'll find no more un-styled, monochrome code blocks: choose from over 100 languages in the dropdown list above the code block so your `CSS`, `YAML`, and `Python` code are distinct from each other with accurate syntax highlighting. The code blocks will even inherit your preferred syntax highlighting theme. You can also quickly copy the code block to your clipboard for use in your code editor of choice.
@@ -8,26 +8,26 @@
stage: create # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/project/wiki/#content-editor # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/wiki/#content-editor # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/inline-editing-in-wysiwyg.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Advanced Search is compatible with OpenSearch # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Advanced Search is compatible with OpenSearch # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
[OpenSearch](https://opensearch.org) is an open source Elasticsearch fork. Prior to GitLab 15.0, Advanced Search was not compatible with OpenSearch. If you used AWS-managed services, you had to use older versions of Elasticsearch.
You can now take full advantage of OpenSearch for Advanced Search.
stage: enablement # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/integration/elasticsearch.html # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/integration/elasticsearch.html # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/gitlab_advanced_search_is_now_compatible_with_opensearch.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Plan and schedule issues with automated iteration cadences # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Plan and schedule issues with automated iteration cadences # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
In GitLab 14.10 and earlier, groups supported only one set of iterations. It made it difficult for different teams that worked in a single group to have autonomy with scheduling and tracking their issues from iteration to iteration. To improve this, we're adding the ability for a group to manage multiple sets of concurrent iterations with iteration cadences. This allows each team to have control over the start day and duration of each iteration in their iteration cadence.
The day-to-day management of iterations is now much more efficient too. When you create a new iteration cadence, select the first day of your first iteration, how many weeks each iteration should be, and how many upcoming iterations GitLab should maintain for you. You can also optionally enable unfinished issues to automatically roll over from one completed iteration to the next. After a cadence is created, GitLab automatically creates the specified number of upcoming iterations.
@@ -36,13 +36,13 @@
stage: plan # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/iterations/#iteration-cadences # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/iterations/#iteration-cadences # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/iteration-cadences.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Internal notes # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Internal notes # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
In many cases, organizations want to keep issues and epics public, but apply stricter governance to conversations within them. For example, when using GitLab issues as part of Service Desk workflows, organizations may want to make core details about an issue public, but not to expose customer-specific confidential data broadly.
With internal notes, you can redact discussions with internal or customer data that should only be visible to certain users, while keeping the core details about an issue public. Internal notes in issues or epics can only be seen by the issue author, assignee, and group or project members with at least the Reporter role.
@@ -51,13 +51,13 @@
stage: plan # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/discussions/index.html#add-an-internal-note # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/discussions/index.html#add-an-internal-note # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/add_internal_note_v15_0.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Link external organizations and contacts to issues # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Link external organizations and contacts to issues # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
GitLab 15.0 introduces the first [MVC](https://about.gitlab.com/handbook/product/product-principles/#the-minimal-viable-change-mvc) toward [managing and billing external customers from GitLab](https://gitlab.com/groups/gitlab-org/-/epics/5323). With the customer relations management (CRM) feature, you can:
- Create organizations and contacts.
@@ -72,43 +72,43 @@
stage: plan # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/crm/ # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/crm/ # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://img.youtube.com/vi/8ubOS80yNvc/hqdefault.jpg # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Container Scanning available in all tiers # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Container Scanning available in all tiers # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
[Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/) helps developers to easily find known security vulnerabilities in dependencies that are installed in their container images. With GitLab 15.0, we are making the basic Container Scanning features available in every [GitLab tier](/pricing/).
stage: protect # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/application_security/container_scanning/#capabilities # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/container_scanning/#capabilities # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://img.youtube.com/vi/vge_DQ6af9Y/hqdefault.jpg # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Limited Availability GitLab SaaS runners on macOS (x86-64) # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Limited Availability GitLab SaaS runners on macOS (x86-64) # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
GitLab SaaS runners on macOS are now in [Limited Availability](https://about.gitlab.com/handbook/product/gitlab-the-product/#limited-availability-la). If you use GitLab SaaS and have a Premium or Ultimate subscription, you can build applications that require macOS in a secure, on-demand GitLab Runner build environment that's fully integrated with GitLab CI/CD. As part of the Limited Availability release, CI jobs that run on the macOS runners will count toward your CI/CD minutes quota at a [cost factor](https://docs.gitlab.com/ee/ci/pipelines/cicd_minutes.html#cost-factor) of 6.
stage: verify # String value of the stage that the feature was created in. e.g., Growth
self-managed: false # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://img.youtube.com/vi/G7ektKx8slg/hqdefault.jpg # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
-- title: Use nested CI/CD variables with environments in pipeline configuration # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: Use nested CI/CD variables with environments in pipeline configuration # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
Using CI/CD variables with the `environments` keyword in your CI/CD configuration is great, because it lets you [create environments dynamically](https://docs.gitlab.com/ee/ci/environments/#create-a-dynamic-environment). While this is already a powerful feature, there were still some limitations, because you could not use nested variables to define environments.
Starting in GitLab 15.0, you can nest variables inside other variables, and have them all expand the way you expect. This makes dynamic environments even more powerful due to the increased flexibility!
stage: verify # String value of the stage that the feature was created in. e.g., Growth
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
- packages: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/yaml/#environment # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: [Free, Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/#environment # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/environment.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y
diff --git a/data/whats_new/202206220001_15_1.yml b/data/whats_new/202206220001_15_1.yml
index 76ef7fd1a46..ab91ffeecb6 100644
--- a/data/whats_new/202206220001_15_1.yml
+++ b/data/whats_new/202206220001_15_1.yml
@@ -9,30 +9,30 @@
#
# Please delete this line and above before submitting your merge request.
-- title: SAML Group Sync for self-managed GitLab
- body: | # Do not modify this line, instead modify the lines below.
+- name: SAML Group Sync for self-managed GitLab
+ description: | # Do not modify this line, instead modify the lines below.
You can now map a group in your identity provider to a self-managed GitLab group using SAML group links. Previously, this feature was only available for GitLab.com. Group memberships are updated when a user logs into GitLab through their SAML provider. This new functionality decreases the workload for GitLab administrators and reduces onboarding time for group members.
stage: manage # String value of the stage that the feature was created in. e.g., Growth
self-managed: true
gitlab-com: true
- packages: [Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/group/saml_sso/group_sync.html
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/saml_sso/group_sync.html
image_url: https://about.gitlab.com/images/15_1/SAML_Group_Sync.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-06-22
release: 15.1
-- title: Enhancing visibility into Value Stream with DORA metrics
- body: | # Do not modify this line, instead modify the lines below.
+- name: Enhancing visibility into Value Stream with DORA metrics
+ description: | # Do not modify this line, instead modify the lines below.
With the addition of the four [DORA metrics](https://docs.gitlab.com/ee/user/analytics/#devops-research-and-assessment-dora-key-metrics) tiles to the [Value Stream Analytics](https://docs.gitlab.com/ee/user/group/value_stream_analytics/) dashboard, you can now track team performance and value flow from ideation to customer delivery. Additionally, we added a new trend chart for the DORA [Time to restore service](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html) metric to provide insights into software stability and reliability trends. This new chart shows information about how long it takes an organization to recover from a failure in production. This is the third DORA chart that's available out of the box in GitLab. We plan to keep improving the visibility into DORA metrics and also add charts for the fourth metric- Change failure rate.
stage: manage # String value of the stage that the feature was created in. e.g., Growth
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html
image_url: https://about.gitlab.com/images/15_1/vsa_dora_n_ttrs.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-06-22
release: 15.1
-- title: "SLSA-2 attestation included for build artifacts"
- body: | # Do not modify this line, instead modify the lines below.
+- name: "SLSA-2 attestation included for build artifacts"
+ description: | # Do not modify this line, instead modify the lines below.
[Supply-chain Levels for Software Artifacts (SLSA)](https://github.com/slsa-framework/slsa) is a security framework that helps ensure the security and integrity of your software supply chain. By default, GitLab Runner is now capable of generating and producing SLSA-2 compliant attestation metadata for build artifacts.
If the artifact is stored in a registry, then the attestation metadata is stored alongside the artifact in that registry. Otherwise, the metadata is in rendered in a plain text `.json` file that's stored with the artifact.
This new attestation information can help you more easily verify that your build artifacts have not been tampered with. To enable this feature, simply set `RUNNER_GENERATE_ARTIFACTS_METADATA = "true"` in your `.gitlab-ci.yml` file.
@@ -40,20 +40,20 @@
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-attestation
- image_url: https://www.youtube.com/embed/MlIdqrDgI8U
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-attestation
+ image_url: https://img.youtube.com/vi/MlIdqrDgI8U/hqdefault.jpg
published_at: 2022-06-22
release: 15.1
-- title: "Link to included CI/CD configuration from the pipeline editor"
- body: | # Do not modify this line, instead modify the lines below.
+- name: "Link to included CI/CD configuration from the pipeline editor"
+ description: | # Do not modify this line, instead modify the lines below.
A typical CI/CD configuration uses the `include` keyword to import configuration stored in other files or CI/CD templates. When editing or troubleshooting your configuration though, it can be difficult to understand how all the configuration works together because the included configuration is not visible in your `.gitlab-ci-yml`, you only see the `include` entry.
In this release, we added links to all included configuration files and templates to the pipeline editor. Now you can easily access and view all the CI/CD configuration your pipeline uses, making it much easier to manage large and complex pipelines.
stage: verify
self-managed: true
gitlab-com: true
- packages: [Free, Premium, Ultimate]
- url: https://docs.gitlab.com/ee/ci/pipeline_editor/
- image_url: https://www.youtube.com/embed/7BNDUYfY_ok
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/pipeline_editor/
+ image_url: https://img.youtube.com/vi/7BNDUYfY_ok/hqdefault.jpg
published_at: 2022-06-22
release: 15.1
diff --git a/data/whats_new/202207220001_15_2.yml b/data/whats_new/202207220001_15_2.yml
new file mode 100644
index 00000000000..4f6f65c9f18
--- /dev/null
+++ b/data/whats_new/202207220001_15_2.yml
@@ -0,0 +1,89 @@
+- name: "Live preview diagrams in the wiki WYSIWYG editor" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ GitLab Flavored Markdown includes extensions to support [Mermaid, PlantUML, and Kroki diagrams](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) but writing anything other than the most basic diagrams can be cumbersome without a live preview. You can toggle between the raw source and static preview and there are external tools you can use to write these diagrams, but the shift away from your content can be distracting.
+
+ GitLab 15.2 introduces a live rendered preview of your diagram in the wiki's WYSIWYG editor. Now, as you write your diagram in a specialized code block we will detect the diagram type and display a preview icon. When enabled, the live preview renders above the code block and updates as you type, so you can ensure your formatting is correct and the output will be exactly what you expect.
+ stage: create
+ self-managed: true
+ gitlab-com: true
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/wiki/#use-the-content-editor
+ image_url: https://about.gitlab.com/images/15_2/create-preview-diagrams-in-wysiwyg.png
+ published_at: 2022-07-22
+ release: 15.2
+- name: Incident timeline # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ Capturing what happened during an incident is an important practice that facilitates learning and the opportunity for improvement. Yet, asking incident responders to take on additional administrative tasks when they're busy fire-fighting, or trying to reconstruct the timeline of events post incident lead to incomplete or less than accurate information.
+
+ GitLab incident timeline is designed to make information capture during an incident, or post incident, easy and efficient. In the Incident timeline MVC, we make it possible to add new timeline events manually, delete a timeline event, and view the incident timeline in a dedicated tab within an incident issue.
+ stage: monitor
+ self-managed: true
+ gitlab-com: true
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/operations/incident_management/incidents.html#timeline-events
+ image_url: https://img.youtube.com/vi/a0brUwOajvQ/hqdefault.jpg
+ published_at: 2022-07-22
+ release: 15.2
+- name: "Merge request reports redesign" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ Merge request reports are an important part of code review, providing insights into the impact of changes and improvements to meet project standards.
+
+ Report widgets now all follow design guidelines for layout, hierarchy, and content sections, making them consistent, scannable, and utilitarian. These improvements make it easier for you to find actionable information in each report.
+ stage: create
+ self-managed: true
+ gitlab-com: true
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/wiki/#use-the-content-editor
+ image_url: https://about.gitlab.com/images/15_2/create-merge-request-widget-redesign.png
+ published_at: 2022-07-22
+ release: 15.2
+- name: "Change failure rate chart for visualizing software stability" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ In this release, we added a new trend chart for the DORA [Change failure rate](https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html) metric. This chart shows the percentage of deployments that cause an incident in a production environment. GitLab measures the change failure rate as the number of [incidents](https://docs.gitlab.com/ee/operations/incident_management/incidents.html) divided by the number of deployments to a production environment during a given time period.
+
+ This is the fourth DORA chart available in GitLab that provides insights into [value stream velocity and reliability trends](https://about.gitlab.com/blog/2022/06/20/gitlab-value-stream-management-and-dora/).
+ stage: manage
+ self-managed: true
+ gitlab-com: true
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/analytics/ci_cd_analytics.html#view-change-failure-rate-chart
+ image_url: https://about.gitlab.com/images/15_2/dora4_chart_cfr.png
+ published_at: 2022-07-22
+ release: 15.2
+- name: "Enforce IP address restrictions for Git over SSH" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ Limiting access to requests from a trusted set of IP addresses may improve security. Until now, only the API and UI supported such access restrictions; SSH access was blocked entirely. SSH now also adheres to this restriction, and grants access only to requests coming from IP addresses in your list.
+ stage: create
+ self-managed: false
+ gitlab-com: true
+ available_in: [Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/group/#group-access-restriction-by-ip-address
+ image_url: https://img.youtube.com/vi/f60EgVK3mWc/hqdefault.jpg
+ published_at: 2022-07-22
+ release: 15.2
+- name: "Group and subgroup scan execution policies" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ Your security and compliance teams can now apply policies uniformly to all projects by scanning execution policies at the group and subgroup levels. This functionality is especially helpful for large organizations who have a large number of projects. Policies defined for the group or subgroup will flow down and apply to all child projects. To get started, ask your group owner to link a security policy project to your group on the **Security & Compliance > Policies** page.
+
+ Currently scan execution policies are the only policy type that is supported at the group and subgroup levels. You can track the efforts to add group and subgroup level support for scan result policies in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7622).
+ stage: protect
+ self-managed: true
+ gitlab-com: true
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/application_security/policies/scan-execution-policies.html'
+ image_url: https://about.gitlab.com/images/15_2/protect_group_policies.png
+ published_at: 2022-07-22
+ release: 15.2
+- name: "Set the image pull policy in pipeline configuration" # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
+ You can select different [pull policies](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) for how a GitLab Runner downloads Docker images in CI/CD jobs. `always` (the default behavior) ensures the image is always downloaded, `if-not-present` downloads an image only when a local version does not exist, and `never` only uses the local version (never download an image).
+
+ Previously, you could define the pull policy only at the runner level. In this release we've added the ability to define the pull policy at the pipeline level. Use `pull_policy` in your `.gitlab-ci.yml` to define different pull policies at the job or pipeline level. This feature is not supported by shared runners.
+ stage: verify
+ self-managed: true
+ gitlab-com: true
+ available_in: [Free, Premium, Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/ci/yaml/#imagepull_policy
+ image_url: https://about.gitlab.com/images/15_2/pull_policy.png
+ published_at: 2022-07-22
+ release: 15.2
diff --git a/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
index 31d2312809d..691db083301 100644
--- a/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
+++ b/data/whats_new/templates/YYYYMMDD0001_XX_YY.yml
@@ -9,8 +9,8 @@
#
# Please delete this line and above before submitting your merge request.
-- title: # Match the release post entry
- body: | # Do not modify this line, instead modify the lines below.
+- name: # Match the release post entry
+ description: | # Do not modify this line, instead modify the lines below.
<!-- START OF BODY COMMENT
This area supports markdown.
@@ -25,8 +25,8 @@
stage: # String value of the stage that the feature was created in. e.g., Growth
self-managed: # Boolean value (true or false)
gitlab-com: # Boolean value (true or false)
- packages: # Array of strings. The Array brackets are required here. e.g., [Free, Premium, Ultimate]
- url: # This is the documentation URL, but can be a URL to a video if there is one
+ available_in: # Array of strings. The Array brackets are required here. e.g., [Free, Premium, Ultimate]
+ documentation_link: # This is the documentation URL, but can be a URL to a video if there is one
image_url: # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: # YYYY-MM-DD
release: # XX.Y
diff --git a/db/docs/README.md b/db/docs/README.md
new file mode 100644
index 00000000000..ef0d6b335d4
--- /dev/null
+++ b/db/docs/README.md
@@ -0,0 +1,6 @@
+# Database Dictionary
+
+This directory contains a metadata file for each database table.
+
+See [documentation](https://docs.gitlab.com/ee/development/database/database_dictionary.html)
+for more information on the schema and purpose of these metadata files.
diff --git a/db/docs/integrations.yml b/db/docs/integrations.yml
index 4629b7558ed..5100ee77fa7 100644
--- a/db/docs/integrations.yml
+++ b/db/docs/integrations.yml
@@ -38,6 +38,7 @@ classes:
- Integrations::PipelinesEmail
- Integrations::Pivotaltracker
- Integrations::Prometheus
+- Integrations::Pumble
- Integrations::Pushover
- Integrations::Redmine
- Integrations::Shimo
diff --git a/db/docs/member_roles.yml b/db/docs/member_roles.yml
new file mode 100644
index 00000000000..314c65a1ef7
--- /dev/null
+++ b/db/docs/member_roles.yml
@@ -0,0 +1,10 @@
+---
+table_name: member_roles
+classes:
+- MemberRole
+feature_categories:
+- projects
+- subgroups
+description: Stores custom roles with composable permissions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92152
+milestone: '15.2'
diff --git a/db/docs/ml_candidate_metrics.yml b/db/docs/ml_candidate_metrics.yml
new file mode 100644
index 00000000000..b0d9ed13489
--- /dev/null
+++ b/db/docs/ml_candidate_metrics.yml
@@ -0,0 +1,10 @@
+---
+table_name: ml_candidate_metrics
+classes:
+ - Ml::CandidateMetric
+feature_categories:
+ - mlops
+ - incubation
+description: Metrics recorded for a Machine Learning model candidate
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95168
+milestone: '15.4'
diff --git a/db/docs/ml_candidate_params.yml b/db/docs/ml_candidate_params.yml
new file mode 100644
index 00000000000..01903b66108
--- /dev/null
+++ b/db/docs/ml_candidate_params.yml
@@ -0,0 +1,10 @@
+---
+table_name: ml_candidate_params
+classes:
+ - Ml::CandidateParams
+feature_categories:
+ - mlops
+ - incubation
+description: Configuration parameters recorded for a Machine Learning model candidate
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95168
+milestone: '15.4'
diff --git a/db/docs/ml_candidates.yml b/db/docs/ml_candidates.yml
new file mode 100644
index 00000000000..c1f7f622350
--- /dev/null
+++ b/db/docs/ml_candidates.yml
@@ -0,0 +1,10 @@
+---
+table_name: ml_candidates
+classes:
+ - Ml::Candidate
+feature_categories:
+ - mlops
+ - incubation
+description: A Model Candidate is a record of the results on training a model on some configuration
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95168
+milestone: '15.4'
diff --git a/db/docs/ml_experiments.yml b/db/docs/ml_experiments.yml
new file mode 100644
index 00000000000..ea5edc9569c
--- /dev/null
+++ b/db/docs/ml_experiments.yml
@@ -0,0 +1,10 @@
+---
+table_name: ml_experiments
+classes:
+ - Ml::Experiment
+feature_categories:
+ - mlops
+ - incubation
+description: A Machine Learning Experiments groups many Model Candidates
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95168
+milestone: '15.4'
diff --git a/db/docs/namespace_details.yml b/db/docs/namespace_details.yml
new file mode 100644
index 00000000000..00053d39396
--- /dev/null
+++ b/db/docs/namespace_details.yml
@@ -0,0 +1,9 @@
+---
+table_name: namespace_details
+classes:
+- NamespaceDetail
+feature_categories:
+- subgroups
+description: Used to store details for namespaces
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82958
+milestone: '15.3'
diff --git a/db/docs/project_statistics.yml b/db/docs/project_statistics.yml
index 75d4af85ce4..323ba1d60d4 100644
--- a/db/docs/project_statistics.yml
+++ b/db/docs/project_statistics.yml
@@ -3,7 +3,7 @@ table_name: project_statistics
classes:
- ProjectStatistics
feature_categories:
-- source_code_management
-description: TODO
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/3ef4f74b1acc9399db320b53dffc592542de0126
-milestone: '9.0'
+- utilization
+description: Records statistics about the usage of various product features
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7754
+milestone: '8.16'
diff --git a/db/docs/user_project_callouts.yml b/db/docs/user_project_callouts.yml
new file mode 100644
index 00000000000..308c3048aa7
--- /dev/null
+++ b/db/docs/user_project_callouts.yml
@@ -0,0 +1,9 @@
+---
+table_name: user_project_callouts
+classes:
+- Users::ProjectCallout
+feature_categories:
+- navigation
+description: Adds the ability to track a user callout being dismissed by project
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94144
+milestone: '15.3'
diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb
index 47d72c4c2e7..e8fa3ee2110 100644
--- a/db/fixtures/development/14_pipelines.rb
+++ b/db/fixtures/development/14_pipelines.rb
@@ -59,6 +59,8 @@ class Gitlab::Seeder::Pipelines
pipeline.update_duration
::Ci::ProcessPipelineService.new(pipeline).execute
end
+
+ ::Gitlab::Seeder::Ci::DailyBuildGroupReportResult.new(@project).seed if @project.last_pipeline
end
private
diff --git a/db/fixtures/development/18_abuse_reports.rb b/db/fixtures/development/18_abuse_reports.rb
index 88d2f784852..7dd93069122 100644
--- a/db/fixtures/development/18_abuse_reports.rb
+++ b/db/fixtures/development/18_abuse_reports.rb
@@ -11,7 +11,7 @@ module Db
name: FFaker::Name.name,
email: FFaker::Internet.email,
confirmed_at: DateTime.now,
- password: '12345678'
+ password: ::User.random_password
)
::AbuseReport.create(reporter: ::User.take, user: reported_user, message: 'User sends spam')
diff --git a/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb b/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb
index 611619e496c..1109d814ee9 100644
--- a/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb
+++ b/db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb
@@ -9,7 +9,7 @@ class GroupProtectedEnvironmentsAddIndexAndConstraint < ActiveRecord::Migration[
def up
add_concurrent_index :protected_environments, [:group_id, :name], unique: true,
- name: INDEX_NAME, where: 'group_id IS NOT NULL'
+ name: INDEX_NAME, where: 'group_id IS NOT NULL'
add_concurrent_foreign_key :protected_environments, :namespaces, column: :group_id, on_delete: :cascade
add_check_constraint :protected_environments,
diff --git a/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb b/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
index 5db39334550..14b6b9efad3 100644
--- a/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
+++ b/db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb
@@ -1,77 +1,11 @@
# frozen_string_literal: true
class AssociateExistingDastBuildsWithVariables < ActiveRecord::Migration[6.1]
- disable_ddl_transaction!
-
- class Profile < ApplicationRecord
- self.table_name = 'dast_profiles'
- self.inheritance_column = :_type_disabled
- end
-
- class ProfilesPipeline < ApplicationRecord
- include EachBatch
-
- self.table_name = 'dast_profiles_pipelines'
- self.inheritance_column = :_type_disabled
-
- belongs_to :profile, foreign_key: :dast_profile_id
- end
-
- class Build < ApplicationRecord
- self.table_name = 'ci_builds'
- self.inheritance_column = :_type_disabled
-
- default_scope { where(name: :dast, stage: :dast) } # rubocop:disable Cop/DefaultScope
- end
-
- class SiteProfilesBuild < ApplicationRecord
- self.table_name = 'dast_site_profiles_builds'
- self.inheritance_column = :_type_disabled
- end
-
- BATCH_SIZE = 300
-
def up
- process_batch do |batch|
- bulk_inserts = []
-
- grouped_builds = fetch_builds(batch).group_by(&:commit_id)
-
- batch.includes(:profile).each do |profile_pipeline|
- builds = grouped_builds[profile_pipeline.ci_pipeline_id]
-
- next if builds.blank?
-
- builds.each do |build|
- bulk_inserts.push(dast_site_profile_id: profile_pipeline.profile.dast_site_profile_id, ci_build_id: build.id)
- end
- end
-
- SiteProfilesBuild.insert_all(bulk_inserts, unique_by: :ci_build_id)
- end
+ # no-op: Must have run before %"15.X" as it is not compatible with decomposed CI database
end
def down
- process_batch do |batch|
- builds = fetch_builds(batch)
-
- SiteProfilesBuild
- .where(ci_build_id: builds)
- .delete_all
- end
- end
-
- private
-
- def fetch_builds(batch)
- # pluck necessary to support ci table decomposition
- # https://gitlab.com/groups/gitlab-org/-/epics/6289
- Build.where(commit_id: batch.pluck(:ci_pipeline_id))
- end
-
- def process_batch
- ProfilesPipeline.each_batch(of: BATCH_SIZE, column: :ci_pipeline_id) do |batch|
- yield(batch)
- end
+ # No-op
end
end
diff --git a/db/migrate/20210804150320_create_base_work_item_types.rb b/db/migrate/20210804150320_create_base_work_item_types.rb
index b7a44eaabe0..836264aae6e 100644
--- a/db/migrate/20210804150320_create_base_work_item_types.rb
+++ b/db/migrate/20210804150320_create_base_work_item_types.rb
@@ -8,9 +8,9 @@ class CreateBaseWorkItemTypes < ActiveRecord::Migration[6.1]
self.table_name = 'work_item_types'
enum base_type: {
- issue: 0,
- incident: 1,
- test_case: 2,
+ issue: 0,
+ incident: 1,
+ test_case: 2,
requirement: 3
}
diff --git a/db/migrate/20210831203408_upsert_base_work_item_types.rb b/db/migrate/20210831203408_upsert_base_work_item_types.rb
index 314412d8d3d..9a556bd6c2c 100644
--- a/db/migrate/20210831203408_upsert_base_work_item_types.rb
+++ b/db/migrate/20210831203408_upsert_base_work_item_types.rb
@@ -6,9 +6,9 @@ class UpsertBaseWorkItemTypes < ActiveRecord::Migration[6.1]
self.table_name = 'work_item_types'
enum base_type: {
- issue: 0,
- incident: 1,
- test_case: 2,
+ issue: 0,
+ incident: 1,
+ test_case: 2,
requirement: 3
}
end
diff --git a/db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb b/db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb
index 77b9e5297a7..e0c9d932b38 100644
--- a/db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb
+++ b/db/migrate/20210901065504_add_index_on_name_and_id_to_public_groups.rb
@@ -7,8 +7,9 @@ class AddIndexOnNameAndIdToPublicGroups < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
def up
- add_concurrent_index :namespaces, [:name, :id], name: INDEX_NAME,
- where: "type = 'Group' AND visibility_level = #{PUBLIC_VISIBILITY_LEVEL}"
+ add_concurrent_index :namespaces, [:name, :id],
+ name: INDEX_NAME,
+ where: "type = 'Group' AND visibility_level = #{PUBLIC_VISIBILITY_LEVEL}"
end
def down
diff --git a/db/migrate/20220316022505_create_namespace_details.rb b/db/migrate/20220316022505_create_namespace_details.rb
new file mode 100644
index 00000000000..6df8606c726
--- /dev/null
+++ b/db/migrate/20220316022505_create_namespace_details.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class CreateNamespaceDetails < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ create_table :namespace_details, id: false do |t|
+ t.references :namespace, primary_key: true, null: false, default: nil, type: :bigint, index: false, foreign_key: { on_delete: :cascade } # rubocop:disable Layout/LineLength
+ t.timestamps_with_timezone null: true
+ t.integer :cached_markdown_version
+ t.text :description, limit: 255
+ t.text :description_html, limit: 255
+ end
+ end
+ end
+
+ def down
+ drop_table :namespace_details
+ end
+end
diff --git a/db/migrate/20220406113217_add_inactive_project_deletion_to_application_settings.rb b/db/migrate/20220406113217_add_inactive_project_deletion_to_application_settings.rb
index 78970d308d9..ffb0fe3f5d8 100644
--- a/db/migrate/20220406113217_add_inactive_project_deletion_to_application_settings.rb
+++ b/db/migrate/20220406113217_add_inactive_project_deletion_to_application_settings.rb
@@ -5,7 +5,7 @@ class AddInactiveProjectDeletionToApplicationSettings < Gitlab::Database::Migrat
add_column :application_settings, :delete_inactive_projects, :boolean, default: false, null: false
add_column :application_settings, :inactive_projects_delete_after_months, :integer, default: 2, null: false
add_column :application_settings, :inactive_projects_min_size_mb, :integer, default: 0, null: false
- add_column :application_settings, :inactive_projects_send_warning_email_after_months, :integer, default: 1,
- null: false
+ add_column :application_settings, :inactive_projects_send_warning_email_after_months,
+ :integer, default: 1, null: false
end
end
diff --git a/db/migrate/20220506154054_create_sync_namespace_details_trigger.rb b/db/migrate/20220506154054_create_sync_namespace_details_trigger.rb
new file mode 100644
index 00000000000..1351fe91318
--- /dev/null
+++ b/db/migrate/20220506154054_create_sync_namespace_details_trigger.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+class CreateSyncNamespaceDetailsTrigger < Gitlab::Database::Migration[2.0]
+ include Gitlab::Database::SchemaHelpers
+
+ UPDATE_TRIGGER_NAME = 'trigger_update_details_on_namespace_update'
+ INSERT_TRIGGER_NAME = 'trigger_update_details_on_namespace_insert'
+ FUNCTION_NAME = 'update_namespace_details_from_namespaces'
+
+ enable_lock_retries!
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ INSERT INTO
+ namespace_details (
+ description,
+ description_html,
+ cached_markdown_version,
+ updated_at,
+ created_at,
+ namespace_id
+ )
+ VALUES
+ (
+ NEW.description,
+ NEW.description_html,
+ NEW.cached_markdown_version,
+ NEW.updated_at,
+ NEW.updated_at,
+ NEW.id
+ ) ON CONFLICT (namespace_id) DO
+ UPDATE
+ SET
+ description = NEW.description,
+ description_html = NEW.description_html,
+ cached_markdown_version = NEW.cached_markdown_version,
+ updated_at = NEW.updated_at
+ WHERE
+ namespace_details.namespace_id = NEW.id;RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{UPDATE_TRIGGER_NAME}
+ AFTER UPDATE ON namespaces
+ FOR EACH ROW
+ WHEN (
+ NEW.type <> 'Project' AND (
+ OLD.description IS DISTINCT FROM NEW.description OR
+ OLD.description_html IS DISTINCT FROM NEW.description_html OR
+ OLD.cached_markdown_version IS DISTINCT FROM NEW.cached_markdown_version)
+ )
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{INSERT_TRIGGER_NAME}
+ AFTER INSERT ON namespaces
+ FOR EACH ROW
+ WHEN (NEW.type <> 'Project')
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:namespaces, UPDATE_TRIGGER_NAME)
+ drop_trigger(:namespaces, INSERT_TRIGGER_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220513093614_add_ding_talk_into_application_settings.rb b/db/migrate/20220513093614_add_ding_talk_into_application_settings.rb
index 5a34200a3c8..4af8071f564 100644
--- a/db/migrate/20220513093614_add_ding_talk_into_application_settings.rb
+++ b/db/migrate/20220513093614_add_ding_talk_into_application_settings.rb
@@ -2,8 +2,8 @@
class AddDingTalkIntoApplicationSettings < Gitlab::Database::Migration[2.0]
def change
- add_column :application_settings, :dingtalk_integration_enabled, :boolean, null: false,
- default: false, comment: 'JiHu-specific column'
+ add_column :application_settings, :dingtalk_integration_enabled, :boolean,
+ null: false, default: false, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_dingtalk_corpid, :binary, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_dingtalk_corpid_iv, :binary, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_dingtalk_app_key, :binary, comment: 'JiHu-specific column'
diff --git a/db/migrate/20220513093615_add_ding_talk_tracker_data.rb b/db/migrate/20220513093615_add_ding_talk_tracker_data.rb
index 0a9c340fbf0..0289b983a48 100644
--- a/db/migrate/20220513093615_add_ding_talk_tracker_data.rb
+++ b/db/migrate/20220513093615_add_ding_talk_tracker_data.rb
@@ -6,7 +6,7 @@ class AddDingTalkTrackerData < Gitlab::Database::Migration[2.0]
def change
create_table :dingtalk_tracker_data, comment: 'JiHu-specific table' do |t|
t.references :integration, foreign_key: { on_delete: :cascade },
- type: :bigint, index: true, null: false, comment: 'JiHu-specific column'
+ type: :bigint, index: true, null: false, comment: 'JiHu-specific column'
t.timestamps_with_timezone
t.text :corpid, comment: 'JiHu-specific column', limit: 255
t.index :corpid, where: "(corpid IS NOT NULL)", name: INDEX_NAME, comment: 'JiHu-specific index'
diff --git a/db/migrate/20220524184149_create_sync_project_namespace_details_trigger.rb b/db/migrate/20220524184149_create_sync_project_namespace_details_trigger.rb
new file mode 100644
index 00000000000..efce35b443a
--- /dev/null
+++ b/db/migrate/20220524184149_create_sync_project_namespace_details_trigger.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+class CreateSyncProjectNamespaceDetailsTrigger < Gitlab::Database::Migration[2.0]
+ include Gitlab::Database::SchemaHelpers
+
+ UPDATE_TRIGGER_NAME = 'trigger_update_details_on_project_update'
+ INSERT_TRIGGER_NAME = 'trigger_update_details_on_project_insert'
+ FUNCTION_NAME = 'update_namespace_details_from_projects'
+
+ enable_lock_retries!
+
+ def up
+ create_trigger_function(FUNCTION_NAME, replace: true) do
+ <<~SQL
+ INSERT INTO
+ namespace_details (
+ description,
+ description_html,
+ cached_markdown_version,
+ updated_at,
+ created_at,
+ namespace_id
+ )
+ VALUES
+ (
+ NEW.description,
+ NEW.description_html,
+ NEW.cached_markdown_version,
+ NEW.updated_at,
+ NEW.updated_at,
+ NEW.project_namespace_id
+ ) ON CONFLICT (namespace_id) DO
+ UPDATE
+ SET
+ description = NEW.description,
+ description_html = NEW.description_html,
+ cached_markdown_version = NEW.cached_markdown_version,
+ updated_at = NEW.updated_at
+ WHERE
+ namespace_details.namespace_id = NEW.project_namespace_id;RETURN NULL;
+ SQL
+ end
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{UPDATE_TRIGGER_NAME}
+ AFTER UPDATE ON projects
+ FOR EACH ROW
+ WHEN (
+ OLD.description IS DISTINCT FROM NEW.description OR
+ OLD.description_html IS DISTINCT FROM NEW.description_html OR
+ OLD.cached_markdown_version IS DISTINCT FROM NEW.cached_markdown_version
+ )
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+
+ execute(<<~SQL)
+ CREATE TRIGGER #{INSERT_TRIGGER_NAME}
+ AFTER INSERT ON projects
+ FOR EACH ROW
+ EXECUTE PROCEDURE #{FUNCTION_NAME}();
+ SQL
+ end
+
+ def down
+ drop_trigger(:projects, UPDATE_TRIGGER_NAME)
+ drop_trigger(:projects, INSERT_TRIGGER_NAME)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20220619212618_add_selective_code_owner_removals_to_project_settings.rb b/db/migrate/20220619212618_add_selective_code_owner_removals_to_project_settings.rb
new file mode 100644
index 00000000000..435a1d7a40e
--- /dev/null
+++ b/db/migrate/20220619212618_add_selective_code_owner_removals_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddSelectiveCodeOwnerRemovalsToProjectSettings < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :selective_code_owner_removals, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20220627061008_add_fei_shu_integration.rb b/db/migrate/20220627061008_add_fei_shu_integration.rb
index 8feedc70ce6..6a3bdb0a2e9 100644
--- a/db/migrate/20220627061008_add_fei_shu_integration.rb
+++ b/db/migrate/20220627061008_add_fei_shu_integration.rb
@@ -2,8 +2,8 @@
class AddFeiShuIntegration < Gitlab::Database::Migration[2.0]
def change
- add_column :application_settings, :feishu_integration_enabled, :boolean, null: false,
- default: false, comment: 'JiHu-specific column'
+ add_column :application_settings, :feishu_integration_enabled, :boolean,
+ null: false, default: false, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_feishu_app_key, :binary, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_feishu_app_key_iv, :binary, comment: 'JiHu-specific column'
add_column :application_settings, :encrypted_feishu_app_secret, :binary, comment: 'JiHu-specific column'
diff --git a/db/migrate/20220707105335_rename_chat_name_service_id_to_integration_id.rb b/db/migrate/20220707105335_rename_chat_name_service_id_to_integration_id.rb
new file mode 100644
index 00000000000..a6625d030a4
--- /dev/null
+++ b/db/migrate/20220707105335_rename_chat_name_service_id_to_integration_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameChatNameServiceIdToIntegrationId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :chat_names, :service_id, :integration_id
+ end
+
+ def down
+ undo_rename_column_concurrently :chat_names, :service_id, :integration_id
+ end
+end
diff --git a/db/migrate/20220707160707_rename_slack_integration_service_id_to_integration_id.rb b/db/migrate/20220707160707_rename_slack_integration_service_id_to_integration_id.rb
new file mode 100644
index 00000000000..d553e349fc1
--- /dev/null
+++ b/db/migrate/20220707160707_rename_slack_integration_service_id_to_integration_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameSlackIntegrationServiceIdToIntegrationId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :slack_integrations, :service_id, :integration_id
+ end
+
+ def down
+ undo_rename_column_concurrently :slack_integrations, :service_id, :integration_id
+ end
+end
diff --git a/db/migrate/20220707181910_create_member_roles.rb b/db/migrate/20220707181910_create_member_roles.rb
new file mode 100644
index 00000000000..271ec064f08
--- /dev/null
+++ b/db/migrate/20220707181910_create_member_roles.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CreateMemberRoles < Gitlab::Database::Migration[2.0]
+ def change
+ create_table :member_roles do |t|
+ t.references :namespace,
+ index: true,
+ null: false,
+ foreign_key: { on_delete: :cascade }
+ t.timestamps_with_timezone null: false
+ t.integer :base_access_level, null: false
+ t.boolean :download_code, default: false
+ end
+ end
+end
diff --git a/db/migrate/20220707181920_add_member_role_id_to_members.rb b/db/migrate/20220707181920_add_member_role_id_to_members.rb
new file mode 100644
index 00000000000..f335d2da6f5
--- /dev/null
+++ b/db/migrate/20220707181920_add_member_role_id_to_members.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddMemberRoleIdToMembers < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ add_column :members, :member_role_id, :bigint
+ end
+
+ def down
+ remove_column :members, :member_role_id
+ end
+end
diff --git a/db/migrate/20220707181930_add_member_roles_relation_to_members.rb b/db/migrate/20220707181930_add_member_roles_relation_to_members.rb
new file mode 100644
index 00000000000..ede168fe51e
--- /dev/null
+++ b/db/migrate/20220707181930_add_member_roles_relation_to_members.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddMemberRolesRelationToMembers < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+ INDEX_NAME = 'index_members_on_member_role_id'
+
+ def up
+ add_concurrent_index :members, :member_role_id, name: INDEX_NAME
+ add_concurrent_foreign_key :members, :member_roles, column: :member_role_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :members, column: :member_role_id
+ end
+
+ remove_concurrent_index_by_name :members, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220707190546_add_plan_limits_max_size_cyclonedx_report_column.rb b/db/migrate/20220707190546_add_plan_limits_max_size_cyclonedx_report_column.rb
new file mode 100644
index 00000000000..5ccc6362d2b
--- /dev/null
+++ b/db/migrate/20220707190546_add_plan_limits_max_size_cyclonedx_report_column.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddPlanLimitsMaxSizeCyclonedxReportColumn < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :plan_limits, :ci_max_artifact_size_cyclonedx, :integer, null: false, default: 1
+ end
+end
diff --git a/db/migrate/20220708150315_add_vulnerabilities_foreign_key_to_vulnerability_merge_request_links.rb b/db/migrate/20220708150315_add_vulnerabilities_foreign_key_to_vulnerability_merge_request_links.rb
index f821e2fbe3a..6a1123a2c00 100644
--- a/db/migrate/20220708150315_add_vulnerabilities_foreign_key_to_vulnerability_merge_request_links.rb
+++ b/db/migrate/20220708150315_add_vulnerabilities_foreign_key_to_vulnerability_merge_request_links.rb
@@ -4,8 +4,8 @@ class AddVulnerabilitiesForeignKeyToVulnerabilityMergeRequestLinks < Gitlab::Dat
disable_ddl_transaction!
def up
- add_concurrent_foreign_key :vulnerability_merge_request_links, :vulnerabilities, column: :vulnerability_id,
- on_delete: :cascade
+ add_concurrent_foreign_key :vulnerability_merge_request_links, :vulnerabilities,
+ column: :vulnerability_id, on_delete: :cascade
end
def down
diff --git a/db/migrate/20220708150335_add_merge_requests_foreign_key_to_vulnerability_merge_request_links.rb b/db/migrate/20220708150335_add_merge_requests_foreign_key_to_vulnerability_merge_request_links.rb
index fedda9677f1..af9cef19b75 100644
--- a/db/migrate/20220708150335_add_merge_requests_foreign_key_to_vulnerability_merge_request_links.rb
+++ b/db/migrate/20220708150335_add_merge_requests_foreign_key_to_vulnerability_merge_request_links.rb
@@ -4,8 +4,8 @@ class AddMergeRequestsForeignKeyToVulnerabilityMergeRequestLinks < Gitlab::Datab
disable_ddl_transaction!
def up
- add_concurrent_foreign_key :vulnerability_merge_request_links, :merge_requests, column: :merge_request_id,
- on_delete: :cascade
+ add_concurrent_foreign_key :vulnerability_merge_request_links, :merge_requests, column:
+ :merge_request_id, on_delete: :cascade
end
def down
diff --git a/db/migrate/20220712131513_rename_issue_tracker_data_service_id_to_integration_id.rb b/db/migrate/20220712131513_rename_issue_tracker_data_service_id_to_integration_id.rb
new file mode 100644
index 00000000000..e6a59b66df9
--- /dev/null
+++ b/db/migrate/20220712131513_rename_issue_tracker_data_service_id_to_integration_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameIssueTrackerDataServiceIdToIntegrationId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :issue_tracker_data, :service_id, :integration_id
+ end
+
+ def down
+ undo_rename_column_concurrently :issue_tracker_data, :service_id, :integration_id
+ end
+end
diff --git a/db/migrate/20220712144843_rename_jira_tracker_data_service_id_to_integration_id.rb b/db/migrate/20220712144843_rename_jira_tracker_data_service_id_to_integration_id.rb
new file mode 100644
index 00000000000..5971c68bd93
--- /dev/null
+++ b/db/migrate/20220712144843_rename_jira_tracker_data_service_id_to_integration_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class RenameJiraTrackerDataServiceIdToIntegrationId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ rename_column_concurrently :jira_tracker_data, :service_id, :integration_id
+ end
+
+ def down
+ undo_rename_column_concurrently :jira_tracker_data, :service_id, :integration_id
+ end
+end
diff --git a/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb b/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb
new file mode 100644
index 00000000000..49d9a652472
--- /dev/null
+++ b/db/migrate/20220718083945_add_unique_project_download_limit_allowlist_to_namespace_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddUniqueProjectDownloadLimitAllowlistToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :namespace_settings, :unique_project_download_limit_allowlist,
+ :text,
+ array: true,
+ default: [],
+ null: false
+ end
+end
diff --git a/db/migrate/20220720161816_add_namespace_id_to_vulnerability_reads_table.rb b/db/migrate/20220720161816_add_namespace_id_to_vulnerability_reads_table.rb
new file mode 100644
index 00000000000..b6af71eb088
--- /dev/null
+++ b/db/migrate/20220720161816_add_namespace_id_to_vulnerability_reads_table.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddNamespaceIdToVulnerabilityReadsTable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :vulnerability_reads, :namespace_id, :bigint
+ end
+end
diff --git a/db/migrate/20220720162123_update_vulnerability_reads_triggers_to_set_namespace_id.rb b/db/migrate/20220720162123_update_vulnerability_reads_triggers_to_set_namespace_id.rb
new file mode 100644
index 00000000000..25ecf45bfd5
--- /dev/null
+++ b/db/migrate/20220720162123_update_vulnerability_reads_triggers_to_set_namespace_id.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: true
+
+class UpdateVulnerabilityReadsTriggersToSetNamespaceId < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION insert_or_update_vulnerability_reads() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ severity smallint;
+ state smallint;
+ report_type smallint;
+ resolved_on_default_branch boolean;
+ present_on_default_branch boolean;
+ namespace_id bigint;
+ BEGIN
+ IF (NEW.vulnerability_id IS NULL AND (TG_OP = 'INSERT' OR TG_OP = 'UPDATE')) THEN
+ RETURN NULL;
+ END IF;
+
+ IF (TG_OP = 'UPDATE' AND OLD.vulnerability_id IS NOT NULL AND NEW.vulnerability_id IS NOT NULL) THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT
+ vulnerabilities.severity, vulnerabilities.state, vulnerabilities.report_type, vulnerabilities.resolved_on_default_branch, vulnerabilities.present_on_default_branch
+ INTO
+ severity, state, report_type, resolved_on_default_branch, present_on_default_branch
+ FROM
+ vulnerabilities
+ WHERE
+ vulnerabilities.id = NEW.vulnerability_id;
+
+ IF present_on_default_branch IS NOT true THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT
+ projects.namespace_id
+ INTO
+ namespace_id
+ FROM
+ projects
+ WHERE
+ projects.id = NEW.project_id;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, namespace_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.vulnerability_id, namespace_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id', CAST(NEW.location->'kubernetes_resource'->>'agent_id' AS bigint))
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+ END
+ $$;
+ SQL
+
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION insert_vulnerability_reads_from_vulnerability() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ scanner_id bigint;
+ uuid uuid;
+ location_image text;
+ cluster_agent_id text;
+ casted_cluster_agent_id bigint;
+ namespace_id bigint;
+ BEGIN
+ SELECT
+ v_o.scanner_id, v_o.uuid, v_o.location->>'image', v_o.location->'kubernetes_resource'->>'agent_id', CAST(v_o.location->'kubernetes_resource'->>'agent_id' AS bigint), projects.namespace_id
+ INTO
+ scanner_id, uuid, location_image, cluster_agent_id, casted_cluster_agent_id, namespace_id
+ FROM
+ vulnerability_occurrences v_o
+ INNER JOIN projects ON projects.id = v_o.project_id
+ WHERE
+ v_o.vulnerability_id = NEW.id
+ LIMIT 1;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, namespace_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.id, namespace_id, NEW.project_id, scanner_id, NEW.report_type, NEW.severity, NEW.state, NEW.resolved_on_default_branch, uuid::uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+ END
+ $$;
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION insert_or_update_vulnerability_reads() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ severity smallint;
+ state smallint;
+ report_type smallint;
+ resolved_on_default_branch boolean;
+ present_on_default_branch boolean;
+ BEGIN
+ IF (NEW.vulnerability_id IS NULL AND (TG_OP = 'INSERT' OR TG_OP = 'UPDATE')) THEN
+ RETURN NULL;
+ END IF;
+
+ IF (TG_OP = 'UPDATE' AND OLD.vulnerability_id IS NOT NULL AND NEW.vulnerability_id IS NOT NULL) THEN
+ RETURN NULL;
+ END IF;
+
+ SELECT
+ vulnerabilities.severity, vulnerabilities.state, vulnerabilities.report_type, vulnerabilities.resolved_on_default_branch, vulnerabilities.present_on_default_branch
+ INTO
+ severity, state, report_type, resolved_on_default_branch, present_on_default_branch
+ FROM
+ vulnerabilities
+ WHERE
+ vulnerabilities.id = NEW.vulnerability_id;
+
+ IF present_on_default_branch IS NOT true THEN
+ RETURN NULL;
+ END IF;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.vulnerability_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id', CAST(NEW.location->'kubernetes_resource'->>'agent_id' AS bigint))
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+ END
+ $$;
+ SQL
+
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION insert_vulnerability_reads_from_vulnerability() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+ DECLARE
+ scanner_id bigint;
+ uuid uuid;
+ location_image text;
+ cluster_agent_id text;
+ casted_cluster_agent_id bigint;
+ BEGIN
+ SELECT
+ v_o.scanner_id, v_o.uuid, v_o.location->>'image', v_o.location->'kubernetes_resource'->>'agent_id', CAST(v_o.location->'kubernetes_resource'->>'agent_id' AS bigint)
+ INTO
+ scanner_id, uuid, location_image, cluster_agent_id, casted_cluster_agent_id
+ FROM
+ vulnerability_occurrences v_o
+ WHERE
+ v_o.vulnerability_id = NEW.id
+ LIMIT 1;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.id, NEW.project_id, scanner_id, NEW.report_type, NEW.severity, NEW.state, NEW.resolved_on_default_branch, uuid::uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ ON CONFLICT(vulnerability_id) DO NOTHING;
+ RETURN NULL;
+ END
+ $$;
+ SQL
+ end
+end
diff --git a/db/migrate/20220720210446_add_start_date_to_issues_table.rb b/db/migrate/20220720210446_add_start_date_to_issues_table.rb
new file mode 100644
index 00000000000..315d80fa654
--- /dev/null
+++ b/db/migrate/20220720210446_add_start_date_to_issues_table.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddStartDateToIssuesTable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :issues, :start_date, :date
+ end
+end
diff --git a/db/migrate/20220722123318_update_delayed_deletion_period.rb b/db/migrate/20220722123318_update_delayed_deletion_period.rb
new file mode 100644
index 00000000000..4d928a41259
--- /dev/null
+++ b/db/migrate/20220722123318_update_delayed_deletion_period.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class UpdateDelayedDeletionPeriod < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ # Before 15.1 the only way to disable delayed deletion was to set
+ # the period to 0, as of 15.1 zero is no longer a valid value (1-90).
+ # This migration sets the period to a valid value and disables
+ # delayed deletion using the delayed_* boolean attributes.
+
+ def up
+ execute <<~SQL
+ UPDATE application_settings SET
+ deletion_adjourned_period = 1,
+ delayed_group_deletion = 'f',
+ delayed_project_removal ='f'
+ WHERE deletion_adjourned_period = 0;
+ SQL
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20220722150231_create_function_gitlab_schema_prevent_write.rb b/db/migrate/20220722150231_create_function_gitlab_schema_prevent_write.rb
new file mode 100644
index 00000000000..d25923923f2
--- /dev/null
+++ b/db/migrate/20220722150231_create_function_gitlab_schema_prevent_write.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class CreateFunctionGitlabSchemaPreventWrite < Gitlab::Database::Migration[2.0]
+ TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write'
+
+ enable_lock_retries!
+
+ # This migration is only to make sure that the lock-write trigger function
+ # matches what we already have on staging/production for Gitlab.com
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{TRIGGER_FUNCTION_NAME}()
+ RETURNS TRIGGER AS
+ $$
+ BEGIN
+ RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
+ USING ERRCODE = 'modifying_sql_data_not_permitted',
+ HINT = 'Make sure you are using the right database connection';
+ END
+ $$ LANGUAGE PLPGSQL
+ SQL
+ end
+
+ def down
+ return if Gitlab.com?
+
+ execute(<<~SQL)
+ DROP FUNCTION #{TRIGGER_FUNCTION_NAME}
+ SQL
+ end
+end
diff --git a/db/migrate/20220722203840_update_lock_writes_function_disabled_via_setting.rb b/db/migrate/20220722203840_update_lock_writes_function_disabled_via_setting.rb
new file mode 100644
index 00000000000..f78d2b7f155
--- /dev/null
+++ b/db/migrate/20220722203840_update_lock_writes_function_disabled_via_setting.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class UpdateLockWritesFunctionDisabledViaSetting < Gitlab::Database::Migration[2.0]
+ TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write'
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{TRIGGER_FUNCTION_NAME}()
+ RETURNS TRIGGER AS
+ $$
+ BEGIN
+ IF COALESCE(NULLIF(current_setting(CONCAT('lock_writes.', TG_TABLE_NAME), true), ''), 'true') THEN
+ RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
+ USING ERRCODE = 'modifying_sql_data_not_permitted',
+ HINT = 'Make sure you are using the right database connection';
+ END IF;
+ RETURN NEW;
+ END
+ $$ LANGUAGE PLPGSQL;
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{TRIGGER_FUNCTION_NAME}()
+ RETURNS TRIGGER AS
+ $$
+ BEGIN
+ RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
+ USING ERRCODE = 'modifying_sql_data_not_permitted',
+ HINT = 'Make sure you are using the right database connection';
+ END
+ $$ LANGUAGE PLPGSQL
+ SQL
+ end
+end
diff --git a/db/migrate/20220723120039_add_author_id_to_vulnerability_state_transitions.rb b/db/migrate/20220723120039_add_author_id_to_vulnerability_state_transitions.rb
new file mode 100644
index 00000000000..4b16ba2bb82
--- /dev/null
+++ b/db/migrate/20220723120039_add_author_id_to_vulnerability_state_transitions.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddAuthorIdToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :vulnerability_state_transitions, :author_id, :bigint
+ end
+end
diff --git a/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb b/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb
new file mode 100644
index 00000000000..bded83f7941
--- /dev/null
+++ b/db/migrate/20220726025516_add_namespace_settings_unique_project_download_limit_allowlist_size_constraint.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddNamespaceSettingsUniqueProjectDownloadLimitAllowlistSizeConstraint < Gitlab::Database::Migration[2.0]
+ CONSTRAINT_NAME = 'namespace_settings_unique_project_download_limit_allowlist_size'
+
+ disable_ddl_transaction!
+
+ def up
+ add_check_constraint :namespace_settings,
+ 'CARDINALITY(unique_project_download_limit_allowlist) <= 100',
+ CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :namespace_settings, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20220726154012_ensure_sbom_occurrences_is_empty.rb b/db/migrate/20220726154012_ensure_sbom_occurrences_is_empty.rb
new file mode 100644
index 00000000000..18c48d1202d
--- /dev/null
+++ b/db/migrate/20220726154012_ensure_sbom_occurrences_is_empty.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class EnsureSbomOccurrencesIsEmpty < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ # Ensure that the sbom_occurrences table is empty to ensure that the
+ # following migration adding a not-null column succeeds.
+ # The code which creates records in this table has not been implemented yet.
+ execute('DELETE FROM sbom_occurrences')
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/migrate/20220726154013_add_component_id_to_sbom_occurrences.rb b/db/migrate/20220726154013_add_component_id_to_sbom_occurrences.rb
new file mode 100644
index 00000000000..9631dadc938
--- /dev/null
+++ b/db/migrate/20220726154013_add_component_id_to_sbom_occurrences.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddComponentIdToSbomOccurrences < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ # Code using this table has not been implemented yet.
+ # The migration prior to this one ensures that it is empty.
+ # rubocop:disable Rails/NotNullColumn
+ add_column :sbom_occurrences, :component_id, :bigint, null: false
+ # rubocop:enable Rails/NotNullColumn
+ end
+
+ def down
+ remove_column :sbom_occurrences, :component_id
+ end
+end
diff --git a/db/migrate/20220726154014_add_index_to_sbom_occurrences_component_id.rb b/db/migrate/20220726154014_add_index_to_sbom_occurrences_component_id.rb
new file mode 100644
index 00000000000..ed944fd0b90
--- /dev/null
+++ b/db/migrate/20220726154014_add_index_to_sbom_occurrences_component_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToSbomOccurrencesComponentId < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "index_sbom_occurrences_on_component_id"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_occurrences, :component_id, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :sbom_occurrences, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220726154015_add_component_foreign_key_to_sbom_occurrences.rb b/db/migrate/20220726154015_add_component_foreign_key_to_sbom_occurrences.rb
new file mode 100644
index 00000000000..1c7341c4aa2
--- /dev/null
+++ b/db/migrate/20220726154015_add_component_foreign_key_to_sbom_occurrences.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddComponentForeignKeyToSbomOccurrences < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :sbom_occurrences,
+ :sbom_components,
+ column: :component_id,
+ on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :sbom_occurrences, column: :component_id
+ end
+ end
+end
diff --git a/db/migrate/20220726154016_make_component_version_nullable.rb b/db/migrate/20220726154016_make_component_version_nullable.rb
new file mode 100644
index 00000000000..8619b9dad12
--- /dev/null
+++ b/db/migrate/20220726154016_make_component_version_nullable.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class MakeComponentVersionNullable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ change_column_null :sbom_occurrences, :component_version_id, true
+ end
+end
diff --git a/db/migrate/20220726230052_remove_tmp_index_project_membership_namespace_id_column.rb b/db/migrate/20220726230052_remove_tmp_index_project_membership_namespace_id_column.rb
new file mode 100644
index 00000000000..e50665c106b
--- /dev/null
+++ b/db/migrate/20220726230052_remove_tmp_index_project_membership_namespace_id_column.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveTmpIndexProjectMembershipNamespaceIdColumn < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'tmp_index_for_namespace_id_migration_on_project_members'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :members, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :members, :id,
+ where: "members.member_namespace_id IS NULL and members.type = 'ProjectMember'",
+ name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220728114136_make_ssh_signature_key_nullable.rb b/db/migrate/20220728114136_make_ssh_signature_key_nullable.rb
new file mode 100644
index 00000000000..5d724e9f406
--- /dev/null
+++ b/db/migrate/20220728114136_make_ssh_signature_key_nullable.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class MakeSshSignatureKeyNullable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ change_column_null :ssh_signatures, :key_id, true
+ end
+end
diff --git a/db/migrate/20220729073603_index_personal_access_tokens_on_id_and_created_at.rb b/db/migrate/20220729073603_index_personal_access_tokens_on_id_and_created_at.rb
new file mode 100644
index 00000000000..b865f76fec1
--- /dev/null
+++ b/db/migrate/20220729073603_index_personal_access_tokens_on_id_and_created_at.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class IndexPersonalAccessTokensOnIdAndCreatedAt < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_personal_access_tokens_on_id_and_created_at'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :personal_access_tokens, [:id, :created_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :personal_access_tokens, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20220802154757_add_deactivate_dormant_user_time_setting.rb b/db/migrate/20220802154757_add_deactivate_dormant_user_time_setting.rb
new file mode 100644
index 00000000000..ca887cc2255
--- /dev/null
+++ b/db/migrate/20220802154757_add_deactivate_dormant_user_time_setting.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class AddDeactivateDormantUserTimeSetting < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :application_settings, :deactivate_dormant_users_period, :integer, default: 90, null: false
+ end
+end
diff --git a/db/migrate/20220803145637_create_user_project_callout.rb b/db/migrate/20220803145637_create_user_project_callout.rb
new file mode 100644
index 00000000000..1d0baf741a9
--- /dev/null
+++ b/db/migrate/20220803145637_create_user_project_callout.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateUserProjectCallout < Gitlab::Database::Migration[2.0]
+ def up
+ create_table :user_project_callouts do |t|
+ t.bigint :user_id, null: false
+ t.bigint :project_id, null: false
+ t.integer :feature_name, limit: 2, null: false
+ t.datetime_with_timezone :dismissed_at
+
+ t.index :project_id
+ t.index [:user_id, :feature_name, :project_id], unique: true, name: 'index_project_user_callouts_feature'
+ end
+ end
+
+ def down
+ drop_table :user_project_callouts
+ end
+end
diff --git a/db/migrate/20220803154543_add_project_id_fkey_for_user_project_callout.rb b/db/migrate/20220803154543_add_project_id_fkey_for_user_project_callout.rb
new file mode 100644
index 00000000000..3cea53dc127
--- /dev/null
+++ b/db/migrate/20220803154543_add_project_id_fkey_for_user_project_callout.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddProjectIdFkeyForUserProjectCallout < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :user_project_callouts, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :user_project_callouts, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20220803154758_add_user_id_fkey_for_user_project_callout.rb b/db/migrate/20220803154758_add_user_id_fkey_for_user_project_callout.rb
new file mode 100644
index 00000000000..01a05f816da
--- /dev/null
+++ b/db/migrate/20220803154758_add_user_id_fkey_for_user_project_callout.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUserIdFkeyForUserProjectCallout < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :user_project_callouts, :users, column: :user_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :user_project_callouts, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20220805154101_add_allow_run_pipelines_in_the_parent_project_setting.rb b/db/migrate/20220805154101_add_allow_run_pipelines_in_the_parent_project_setting.rb
new file mode 100644
index 00000000000..dbc76e8ccfd
--- /dev/null
+++ b/db/migrate/20220805154101_add_allow_run_pipelines_in_the_parent_project_setting.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class AddAllowRunPipelinesInTheParentProjectSetting < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :project_ci_cd_settings, :allow_fork_pipelines_to_run_in_parent_project, :boolean,
+ default: true, null: false
+ end
+end
diff --git a/db/migrate/20220808133824_add_timestamps_to_project_statistics.rb b/db/migrate/20220808133824_add_timestamps_to_project_statistics.rb
new file mode 100644
index 00000000000..c5125ebc8ff
--- /dev/null
+++ b/db/migrate/20220808133824_add_timestamps_to_project_statistics.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddTimestampsToProjectStatistics < Gitlab::Database::Migration[2.0]
+ def change
+ add_timestamps_with_timezone(:project_statistics, null: false, default: -> { 'NOW()' })
+ end
+end
diff --git a/db/migrate/20220808190124_add_id_token_to_ci_builds_metadata.rb b/db/migrate/20220808190124_add_id_token_to_ci_builds_metadata.rb
new file mode 100644
index 00000000000..00d27d7c516
--- /dev/null
+++ b/db/migrate/20220808190124_add_id_token_to_ci_builds_metadata.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddIdTokenToCiBuildsMetadata < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ add_column :ci_builds_metadata, :id_tokens, :jsonb, null: false, default: {}
+ end
+end
diff --git a/db/migrate/20220808194857_remove_description_html_limit.rb b/db/migrate/20220808194857_remove_description_html_limit.rb
new file mode 100644
index 00000000000..f7444594566
--- /dev/null
+++ b/db/migrate/20220808194857_remove_description_html_limit.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveDescriptionHtmlLimit < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ remove_text_limit :namespace_details, :description_html
+ remove_text_limit :namespace_details, :description
+ end
+
+ def down
+ add_text_limit :namespace_details, :description_html, 255
+ add_text_limit :namespace_details, :description, 255
+ end
+end
diff --git a/db/migrate/20220811092243_create_ml_experiments.rb b/db/migrate/20220811092243_create_ml_experiments.rb
new file mode 100644
index 00000000000..a357d62133c
--- /dev/null
+++ b/db/migrate/20220811092243_create_ml_experiments.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CreateMlExperiments < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ create_table :ml_experiments do |t|
+ t.timestamps_with_timezone null: false
+ t.bigint :iid, null: false
+ t.bigint :project_id, null: false
+ t.references :user, foreign_key: true, index: true, on_delete: :nullify
+ t.text :name, limit: 255, null: false
+
+ t.index [:project_id, :iid], unique: true
+ t.index [:project_id, :name], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20220811092244_create_ml_candidates.rb b/db/migrate/20220811092244_create_ml_candidates.rb
new file mode 100644
index 00000000000..fe9fc293b03
--- /dev/null
+++ b/db/migrate/20220811092244_create_ml_candidates.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class CreateMlCandidates < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ create_table :ml_candidates do |t|
+ t.timestamps_with_timezone null: false
+ t.uuid :iid, null: false
+ t.bigint :experiment_id, null: false
+ t.references :user, foreign_key: true, index: true, on_delete: :nullify
+
+ t.index [:experiment_id, :iid], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20220811092245_create_ml_candidate_params.rb b/db/migrate/20220811092245_create_ml_candidate_params.rb
new file mode 100644
index 00000000000..55fc1cbe7af
--- /dev/null
+++ b/db/migrate/20220811092245_create_ml_candidate_params.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class CreateMlCandidateParams < Gitlab::Database::Migration[2.0]
+ def change
+ create_table :ml_candidate_params do |t|
+ t.timestamps_with_timezone null: false
+ t.references :candidate,
+ foreign_key: { to_table: :ml_candidates },
+ index: true
+ t.text :name, limit: 250, null: false
+ t.text :value, limit: 250, null: false
+ end
+ end
+end
diff --git a/db/migrate/20220811092246_create_ml_candidate_metrics.rb b/db/migrate/20220811092246_create_ml_candidate_metrics.rb
new file mode 100644
index 00000000000..a4d417f270e
--- /dev/null
+++ b/db/migrate/20220811092246_create_ml_candidate_metrics.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class CreateMlCandidateMetrics < Gitlab::Database::Migration[2.0]
+ def change
+ create_table :ml_candidate_metrics do |t|
+ t.timestamps_with_timezone null: false
+ t.references :candidate,
+ foreign_key: { to_table: :ml_candidates },
+ index: true
+ t.float :value
+ t.integer :step
+ t.binary :is_nan
+ t.text :name, limit: 250, null: false
+ end
+ end
+end
diff --git a/db/migrate/20220811092251_add_ml_candidates_reference_to_experiment.rb b/db/migrate/20220811092251_add_ml_candidates_reference_to_experiment.rb
new file mode 100644
index 00000000000..a3be644552c
--- /dev/null
+++ b/db/migrate/20220811092251_add_ml_candidates_reference_to_experiment.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddMlCandidatesReferenceToExperiment < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ml_candidates, :ml_experiments, column: :experiment_id
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ml_candidates, column: :experiment_id
+ end
+ end
+end
diff --git a/db/migrate/20220811092253_add_ml_experiments_reference_to_project.rb b/db/migrate/20220811092253_add_ml_experiments_reference_to_project.rb
new file mode 100644
index 00000000000..4fd832dfe14
--- /dev/null
+++ b/db/migrate/20220811092253_add_ml_experiments_reference_to_project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddMlExperimentsReferenceToProject < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :ml_experiments, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :ml_experiments, column: :project_id
+ end
+ end
+end
diff --git a/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb b/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb
index bb444f5b407..0d610f1dde1 100644
--- a/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb
+++ b/db/post_migrate/20210311120156_backfill_push_event_payload_event_id_for_bigint_conversion.rb
@@ -11,7 +11,7 @@ class BackfillPushEventPayloadEventIdForBigintConversion < ActiveRecord::Migrati
return unless should_run?
backfill_conversion_of_integer_to_bigint :push_event_payloads, :event_id, primary_key: :event_id,
- batch_size: 15000, sub_batch_size: 100
+ batch_size: 15000, sub_batch_size: 100
end
def down
diff --git a/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb b/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb
index 7d4d97acf58..0f6cf970778 100644
--- a/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb
+++ b/db/post_migrate/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url.rb
@@ -1,23 +1,12 @@
# frozen_string_literal: true
class ScheduleUpdateJiraTrackerDataDeploymentTypeBasedOnUrl < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- MIGRATION = 'UpdateJiraTrackerDataDeploymentTypeBasedOnUrl'
- DELAY_INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 2_500
-
- disable_ddl_transaction!
-
def up
- say "Scheduling #{MIGRATION} jobs"
- queue_background_migration_jobs_by_range_at_intervals(
- define_batchable_model('jira_tracker_data'),
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
+ # no-op (being re-run in 20220324152945_update_jira_tracker_data_deployment_type_based_on_url.rb)
+ # due to this migration causing this issue: https://gitlab.com/gitlab-org/gitlab/-/issues/336849
+ # The migration is rescheduled in
+ # db/post_migrate/20220725150127_update_jira_tracker_data_deployment_type_based_on_url.rb
+ # Related discussion: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82103#note_862401816
end
def down
diff --git a/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb b/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
index 715bc392c68..1f0bdfc5012 100644
--- a/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
+++ b/db/post_migrate/20210622045705_finalize_events_bigint_conversion.rb
@@ -31,7 +31,7 @@ class FinalizeEventsBigintConversion < ActiveRecord::Migration[6.1]
add_concurrent_index TABLE_NAME, [:project_id, :id_convert_to_bigint], name: 'index_events_on_project_id_and_id_convert_to_bigint'
# This is to replace the existing "index_events_on_project_id_and_id_desc_on_merged_action" btree (project_id, id DESC) WHERE action = 7
add_concurrent_index TABLE_NAME, [:project_id, :id_convert_to_bigint], order: { id_convert_to_bigint: :desc },
- where: "action = 7", name: 'index_events_on_project_id_and_id_bigint_desc_on_merged_action'
+ where: "action = 7", name: 'index_events_on_project_id_and_id_bigint_desc_on_merged_action'
# Add a FK on `push_event_payloads(event_id)` to `id_convert_to_bigint`, the old FK (fk_36c74129da)
# will be removed when events_pkey constraint is droppped.
diff --git a/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb b/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
index 161366590be..776f1ad545d 100644
--- a/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
+++ b/db/post_migrate/20210701141346_finalize_ci_builds_stage_id_bigint_conversion.rb
@@ -30,7 +30,7 @@ class FinalizeCiBuildsStageIdBigintConversion < ActiveRecord::Migration[6.1]
# Create a copy of the original column's FK on the new column
add_concurrent_foreign_key TABLE_NAME, :ci_stages, column: :stage_id_convert_to_bigint, on_delete: :cascade,
- reverse_lock_order: true
+ reverse_lock_order: true
with_lock_retries(raise_on_exhaustion: true) do
quoted_table_name = quote_table_name(TABLE_NAME)
diff --git a/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb b/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
index dbefbeb26cb..f3ce32ad9c8 100644
--- a/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
+++ b/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb
@@ -37,10 +37,10 @@ class FinalizeCiStagesBigintConversion < ActiveRecord::Migration[6.1]
fk_stage_id = concurrent_foreign_key_name(:ci_builds, :stage_id)
fk_stage_id_tmp = "#{fk_stage_id}_tmp"
add_concurrent_foreign_key :ci_builds, :ci_stages, column: :stage_id,
- target_column: :id_convert_to_bigint,
- name: fk_stage_id_tmp,
- on_delete: :cascade,
- reverse_lock_order: true
+ target_column: :id_convert_to_bigint,
+ name: fk_stage_id_tmp,
+ on_delete: :cascade,
+ reverse_lock_order: true
# Now it's time to do things in a transaction
with_lock_retries(raise_on_exhaustion: true) do
@@ -58,7 +58,7 @@ class FinalizeCiStagesBigintConversion < ActiveRecord::Migration[6.1]
# Swap defaults
execute "ALTER SEQUENCE ci_stages_id_seq OWNED BY #{TABLE_NAME}.id"
- change_column_default TABLE_NAME, :id, -> { "nextval('ci_stages_id_seq'::regclass)"}
+ change_column_default TABLE_NAME, :id, -> { "nextval('ci_stages_id_seq'::regclass)" }
change_column_default TABLE_NAME, :id_convert_to_bigint, 0
# Swap pkey constraint
diff --git a/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb b/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
index c2444ccbc6c..3879c3c368a 100644
--- a/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
+++ b/db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb
@@ -40,7 +40,7 @@ class FinalizeCiBuildsMetadataBigintConversion < Gitlab::Database::Migration[1.0
# rubocop:enable Migration/PreventIndexCreation
add_concurrent_foreign_key TABLE_NAME, :ci_builds, column: :build_id_convert_to_bigint, on_delete: :cascade,
- reverse_lock_order: true
+ reverse_lock_order: true
with_lock_retries(raise_on_exhaustion: true) do
execute "LOCK TABLE ci_builds, #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
diff --git a/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb b/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
index 6dab29e10d4..289b77f0a5c 100644
--- a/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
+++ b/db/post_migrate/20210802043253_finalize_push_event_payloads_bigint_conversion_3.rb
@@ -29,8 +29,8 @@ class FinalizePushEventPayloadsBigintConversion3 < ActiveRecord::Migration[6.1]
def already_swapped?
push_event_payloads_columns = columns(TABLE_NAME)
- event_id = push_event_payloads_columns.find {|c| c.name == 'event_id'}
- event_id_convert_to_bigint = push_event_payloads_columns.find {|c| c.name == 'event_id_convert_to_bigint'}
+ event_id = push_event_payloads_columns.find { |c| c.name == 'event_id' }
+ event_id_convert_to_bigint = push_event_payloads_columns.find { |c| c.name == 'event_id_convert_to_bigint' }
event_id.sql_type == 'bigint' && event_id_convert_to_bigint.sql_type == 'integer'
end
@@ -40,7 +40,7 @@ class FinalizePushEventPayloadsBigintConversion3 < ActiveRecord::Migration[6.1]
# Add a foreign key on `event_id_convert_to_bigint` before we swap the columns and drop the old FK (fk_36c74129da)
add_concurrent_foreign_key TABLE_NAME, :events, column: :event_id_convert_to_bigint,
- on_delete: :cascade, reverse_lock_order: true
+ on_delete: :cascade, reverse_lock_order: true
with_lock_retries(raise_on_exhaustion: true) do
# We'll need ACCESS EXCLUSIVE lock on the related tables,
diff --git a/db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb b/db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb
index 8115465e311..81e73effe7b 100644
--- a/db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb
+++ b/db/post_migrate/20210804151444_prepare_indexes_for_ci_job_artifact_bigint_conversion.rb
@@ -5,19 +5,23 @@ class PrepareIndexesForCiJobArtifactBigintConversion < ActiveRecord::Migration[6
def up
prepare_async_index :ci_job_artifacts, :id_convert_to_bigint, unique: true,
- name: :index_ci_job_artifact_on_id_convert_to_bigint
+ name: :index_ci_job_artifact_on_id_convert_to_bigint
- prepare_async_index :ci_job_artifacts, [:project_id, :id_convert_to_bigint], where: 'file_type = 18',
- name: :index_ci_job_artifacts_for_terraform_reports_bigint
+ prepare_async_index :ci_job_artifacts,
+ [:project_id, :id_convert_to_bigint],
+ where: 'file_type = 18', name: :index_ci_job_artifacts_for_terraform_reports_bigint
- prepare_async_index :ci_job_artifacts, :id_convert_to_bigint, where: 'file_type = 18',
- name: :index_ci_job_artifacts_id_for_terraform_reports_bigint
+ prepare_async_index :ci_job_artifacts, :id_convert_to_bigint,
+ where: 'file_type = 18',
+ name: :index_ci_job_artifacts_id_for_terraform_reports_bigint
- prepare_async_index :ci_job_artifacts, [:expire_at, :job_id_convert_to_bigint],
- name: :index_ci_job_artifacts_on_expire_at_and_job_id_bigint
+ prepare_async_index :ci_job_artifacts,
+ [:expire_at, :job_id_convert_to_bigint],
+ name: :index_ci_job_artifacts_on_expire_at_and_job_id_bigint
- prepare_async_index :ci_job_artifacts, [:job_id_convert_to_bigint, :file_type], unique: true,
- name: :index_ci_job_artifacts_on_job_id_and_file_type_bigint
+ prepare_async_index :ci_job_artifacts,
+ [:job_id_convert_to_bigint, :file_type],
+ unique: true, name: :index_ci_job_artifacts_on_job_id_and_file_type_bigint
end
def down
diff --git a/db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb b/db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb
index 98f90bafce3..ab6691dea1f 100644
--- a/db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb
+++ b/db/post_migrate/20210804153307_prepare_indexes_for_tagging_bigint_conversion.rb
@@ -5,7 +5,7 @@ class PrepareIndexesForTaggingBigintConversion < ActiveRecord::Migration[6.1]
def up
prepare_async_index :taggings, :id_convert_to_bigint, unique: true,
- name: :index_taggings_on_id_convert_to_bigint
+ name: :index_taggings_on_id_convert_to_bigint
prepare_async_index :taggings, [:taggable_id_convert_to_bigint, :taggable_type],
name: :i_taggings_on_taggable_id_convert_to_bigint_and_taggable_type
diff --git a/db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb b/db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb
index 82af595b2d3..16f3e87000c 100644
--- a/db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb
+++ b/db/post_migrate/20210804154407_prepare_indexes_for_ci_stage_bigint_conversion.rb
@@ -5,14 +5,16 @@ class PrepareIndexesForCiStageBigintConversion < ActiveRecord::Migration[6.1]
def up
prepare_async_index :ci_stages, :id_convert_to_bigint, unique: true,
- name: :index_ci_stages_on_id_convert_to_bigint
+ name: :index_ci_stages_on_id_convert_to_bigint
- prepare_async_index :ci_stages, [:pipeline_id, :id_convert_to_bigint], where: 'status in (0, 1, 2, 8, 9, 10)',
- name: :index_ci_stages_on_pipeline_id_and_id_convert_to_bigint
+ prepare_async_index :ci_stages, [:pipeline_id, :id_convert_to_bigint],
+ where: 'status in (0, 1, 2, 8, 9, 10)',
+ name: :index_ci_stages_on_pipeline_id_and_id_convert_to_bigint
end
def down
- unprepare_async_index_by_name :ci_stages, :index_ci_stages_on_pipeline_id_and_id_convert_to_bigint
+ unprepare_async_index_by_name :ci_stages,
+ :index_ci_stages_on_pipeline_id_and_id_convert_to_bigint
unprepare_async_index_by_name :ci_stages, :index_ci_stages_on_id_convert_to_bigint
end
diff --git a/db/post_migrate/20210816183304_schedule_copy_ci_builds_columns_to_security_scans2.rb b/db/post_migrate/20210816183304_schedule_copy_ci_builds_columns_to_security_scans2.rb
index b8f843fdd50..074ba97da65 100644
--- a/db/post_migrate/20210816183304_schedule_copy_ci_builds_columns_to_security_scans2.rb
+++ b/db/post_migrate/20210816183304_schedule_copy_ci_builds_columns_to_security_scans2.rb
@@ -1,32 +1,8 @@
# frozen_string_literal: true
class ScheduleCopyCiBuildsColumnsToSecurityScans2 < ActiveRecord::Migration[6.1]
- include Gitlab::Database::MigrationHelpers
-
- INTERVAL = 2.minutes.to_i
- BATCH_SIZE = 5_000
- MIGRATION = 'CopyCiBuildsColumnsToSecurityScans'
-
- disable_ddl_transaction!
-
- class SecurityScan < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'security_scans'
- end
-
def up
- SecurityScan.reset_column_information
-
- delete_job_tracking(MIGRATION, status: %w[pending succeeded])
-
- queue_background_migration_jobs_by_range_at_intervals(
- SecurityScan,
- MIGRATION,
- INTERVAL,
- batch_size: BATCH_SIZE,
- track_jobs: true
- )
+ # no-op: Must have run before %"15.X" as it is not compatible with decomposed CI database
end
def down
diff --git a/db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb b/db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb
index 1d102d6216c..e1ed28f6826 100644
--- a/db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb
+++ b/db/post_migrate/20210817024335_prepare_indexes_for_events_bigint_conversion.rb
@@ -7,13 +7,14 @@ class PrepareIndexesForEventsBigintConversion < ActiveRecord::Migration[6.1]
def up
prepare_async_index TABLE_NAME, :id_convert_to_bigint, unique: true,
- name: :index_events_on_id_convert_to_bigint
+ name: :index_events_on_id_convert_to_bigint
prepare_async_index TABLE_NAME, [:project_id, :id_convert_to_bigint],
name: :index_events_on_project_id_and_id_convert_to_bigint
- prepare_async_index TABLE_NAME, [:project_id, :id_convert_to_bigint], order: { id_convert_to_bigint: :desc },
- where: 'action = 7', name: :index_events_on_project_id_and_id_bigint_desc_on_merged_action
+ prepare_async_index TABLE_NAME, [:project_id, :id_convert_to_bigint],
+ order: { id_convert_to_bigint: :desc },
+ where: 'action = 7', name: :index_events_on_project_id_and_id_bigint_desc_on_merged_action
end
def down
diff --git a/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb b/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
index f63645b4ffa..bf95aa98295 100644
--- a/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
+++ b/db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
@@ -5,13 +5,13 @@ class PrepareCiBuildsMetadataAndCiBuildAsyncIndexes < ActiveRecord::Migration[6.
def up
prepare_async_index :ci_builds_metadata, :id_convert_to_bigint, unique: true,
- name: :index_ci_builds_metadata_on_id_convert_to_bigint
+ name: :index_ci_builds_metadata_on_id_convert_to_bigint
prepare_async_index :ci_builds_metadata, :build_id_convert_to_bigint, unique: true,
- name: :index_ci_builds_metadata_on_build_id_convert_to_bigint
+ name: :index_ci_builds_metadata_on_build_id_convert_to_bigint
prepare_async_index :ci_builds_metadata, :build_id_convert_to_bigint, where: 'has_exposed_artifacts IS TRUE',
- name: :index_ci_builds_metadata_on_build_id_int8_and_exposed_artifacts
+ name: :index_ci_builds_metadata_on_build_id_int8_and_exposed_artifacts
prepare_async_index_from_sql(:ci_builds_metadata, :index_ci_builds_metadata_on_build_id_int8_where_interruptible, <<~SQL.squish)
CREATE INDEX CONCURRENTLY "index_ci_builds_metadata_on_build_id_int8_where_interruptible"
@@ -20,7 +20,7 @@ class PrepareCiBuildsMetadataAndCiBuildAsyncIndexes < ActiveRecord::Migration[6.
SQL
prepare_async_index :ci_builds, :id_convert_to_bigint, unique: true,
- name: :index_ci_builds_on_converted_id
+ name: :index_ci_builds_on_converted_id
end
def down
diff --git a/db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb b/db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb
index f350fbe3d12..1f6650140d4 100644
--- a/db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb
+++ b/db/post_migrate/20210825193652_backfill_cadence_id_for_boards_scoped_to_iteration.rb
@@ -20,7 +20,7 @@ class BackfillCadenceIdForBoardsScopedToIteration < Gitlab::Database::Migration[
def down
MigrationBoard.where.not(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
+ range = batch.pick(Arel.sql('MIN(id)'), Arel.sql('MAX(id)'))
delay = index * DELAY
migrate_in(delay, MIGRATION, ['none', 'down', *range])
@@ -31,7 +31,7 @@ class BackfillCadenceIdForBoardsScopedToIteration < Gitlab::Database::Migration[
def schedule_backfill_project_boards
MigrationBoard.where(iteration_id: -4).where.not(project_id: nil).where(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
+ range = batch.pick(Arel.sql('MIN(id)'), Arel.sql('MAX(id)'))
delay = index * DELAY
migrate_in(delay, MIGRATION, ['project', 'up', *range])
@@ -40,7 +40,7 @@ class BackfillCadenceIdForBoardsScopedToIteration < Gitlab::Database::Migration[
def schedule_backfill_group_boards
MigrationBoard.where(iteration_id: -4).where.not(group_id: nil).where(iteration_cadence_id: nil).each_batch(of: BATCH_SIZE) do |batch, index|
- range = batch.pluck(Arel.sql('MIN(id)'), Arel.sql('MAX(id)')).first
+ range = batch.pick(Arel.sql('MIN(id)'), Arel.sql('MAX(id)'))
delay = index * DELAY
migrate_in(delay, MIGRATION, ['group', 'up', *range])
diff --git a/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb b/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
index 7544842c196..f164cdbf379 100644
--- a/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
+++ b/db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb
@@ -200,8 +200,7 @@ class FinalizeCiBuildsBigintConversion < Gitlab::Database::Migration[1.0]
column: column,
target_column: :id_convert_to_bigint,
name: temporary_name,
- on_delete: on_delete,
- reverse_lock_order: true)
+ on_delete: on_delete)
end
end
@@ -214,9 +213,6 @@ class FinalizeCiBuildsBigintConversion < Gitlab::Database::Migration[1.0]
next unless foreign_key_exists?(from_table, TABLE_NAME, column: column, primary_key: :id, name: existing_name)
with_lock_retries do
- # Explicitly lock table in order of parent, child to attempt to avoid deadlocks
- execute "LOCK TABLE #{TABLE_NAME}, #{from_table} IN ACCESS EXCLUSIVE MODE"
-
temporary_name = "#{existing_name}_tmp"
remove_foreign_key(from_table, TABLE_NAME, column: column, primary_key: :id, name: existing_name)
diff --git a/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb b/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb
index 2e6ad12f928..3a758394d7f 100644
--- a/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb
+++ b/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb
@@ -1,52 +1,11 @@
# frozen_string_literal: true
class DisableJobTokenScopeWhenUnused < Gitlab::Database::Migration[1.0]
- disable_ddl_transaction!
-
- class ProjectCiCdSetting < ApplicationRecord
- include EachBatch
-
- self.table_name = 'project_ci_cd_settings'
- end
-
- module Ci
- module JobToken
- class ProjectScopeLink < ApplicationRecord
- self.table_name = 'ci_job_token_project_scope_links'
- end
- end
- end
-
def up
- # Disabling job token scope after db/migrate/20210902171808_set_default_job_token_scope_false.rb
- # if users haven't configured it.
- ProjectCiCdSetting.each_batch(of: 10_000) do |settings|
- with_enabled_but_unused_scope(settings).each_batch(of: 500) do |settings_to_update|
- settings_to_update.update_all(job_token_scope_enabled: false)
- end
- end
+ # no-op: Must have run before %"15.X" as it is not compatible with decomposed CI database
end
def down
- # irreversible data migration
-
- # The migration relies on the state of `job_token_scope_enabled` and
- # updates it based on whether the feature is used or not.
- #
- # The inverse migration would be to set `job_token_scope_enabled: true`
- # for those projects that have the feature disabled and unused. But there
- # could be also existing cases where the feature is disabled and unused.
- # For example, old projects.
- end
-
- private
-
- # The presence of ProjectScopeLinks means that the job token scope
- # is configured and we need to leave it enabled. Unused job token scope
- # can be disabled since they weren't configured.
- def with_enabled_but_unused_scope(settings)
- settings
- .where(job_token_scope_enabled: true)
- .where.not(project_id: Ci::JobToken::ProjectScopeLink.select(:source_project_id))
+ # no-op
end
end
diff --git a/db/post_migrate/20211007155221_schedule_populate_status_column_of_security_scans.rb b/db/post_migrate/20211007155221_schedule_populate_status_column_of_security_scans.rb
index 03032dfbb0a..04af23446fd 100644
--- a/db/post_migrate/20211007155221_schedule_populate_status_column_of_security_scans.rb
+++ b/db/post_migrate/20211007155221_schedule_populate_status_column_of_security_scans.rb
@@ -1,21 +1,8 @@
# frozen_string_literal: true
class SchedulePopulateStatusColumnOfSecurityScans < Gitlab::Database::Migration[1.0]
- MIGRATION = 'PopulateStatusColumnOfSecurityScans'
- BATCH_SIZE = 10_000
- DELAY_INTERVAL = 2.minutes
-
- disable_ddl_transaction!
-
def up
- return unless Gitlab.ee?
-
- queue_background_migration_jobs_by_range_at_intervals(
- define_batchable_model('security_scans'),
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE
- )
+ # no-op
end
def down
diff --git a/db/post_migrate/20211208122200_schedule_backfill_ci_namespace_mirrors.rb b/db/post_migrate/20211208122200_schedule_backfill_ci_namespace_mirrors.rb
index 3d39148f402..e42b74748d7 100644
--- a/db/post_migrate/20211208122200_schedule_backfill_ci_namespace_mirrors.rb
+++ b/db/post_migrate/20211208122200_schedule_backfill_ci_namespace_mirrors.rb
@@ -1,20 +1,8 @@
# frozen_string_literal: true
class ScheduleBackfillCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
- MIGRATION = 'BackfillCiNamespaceMirrors'
- BATCH_SIZE = 10_000
- DELAY_INTERVAL = 2.minutes
-
- disable_ddl_transaction!
-
def up
- queue_background_migration_jobs_by_range_at_intervals(
- Gitlab::BackgroundMigration::BackfillCiNamespaceMirrors::Namespace.base_query,
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- track_jobs: true
- )
+ # no-op
end
def down
diff --git a/db/post_migrate/20211208122201_schedule_backfill_ci_project_mirrors.rb b/db/post_migrate/20211208122201_schedule_backfill_ci_project_mirrors.rb
index 5678ee9f292..2a58eda040e 100644
--- a/db/post_migrate/20211208122201_schedule_backfill_ci_project_mirrors.rb
+++ b/db/post_migrate/20211208122201_schedule_backfill_ci_project_mirrors.rb
@@ -1,20 +1,8 @@
# frozen_string_literal: true
class ScheduleBackfillCiProjectMirrors < Gitlab::Database::Migration[1.0]
- MIGRATION = 'BackfillCiProjectMirrors'
- BATCH_SIZE = 10_000
- DELAY_INTERVAL = 2.minutes
-
- disable_ddl_transaction!
-
def up
- queue_background_migration_jobs_by_range_at_intervals(
- Gitlab::BackgroundMigration::BackfillCiProjectMirrors::Project.base_query,
- MIGRATION,
- DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- track_jobs: true
- )
+ # no-op
end
def down
diff --git a/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb b/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb
index 65ec2f9a282..a6775251d42 100644
--- a/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb
+++ b/db/post_migrate/20220127132200_cleanup_backfill_ci_namespace_mirrors.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
class CleanupBackfillCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
- MIGRATION = 'BackfillCiNamespaceMirrors'
-
- disable_ddl_transaction!
-
def up
- finalize_background_migration(MIGRATION)
+ # no-op
end
def down
diff --git a/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb b/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb
index 8c7d9a945ba..c0cdb74c595 100644
--- a/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb
+++ b/db/post_migrate/20220127132201_cleanup_backfill_ci_project_mirrors.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
class CleanupBackfillCiProjectMirrors < Gitlab::Database::Migration[1.0]
- MIGRATION = 'BackfillCiProjectMirrors'
-
- disable_ddl_transaction!
-
def up
- finalize_background_migration(MIGRATION)
+ # no-op
end
def down
diff --git a/db/post_migrate/20220213103859_remove_integrations_type.rb b/db/post_migrate/20220213103859_remove_integrations_type.rb
index c3633d1e7d3..3c420760a2d 100644
--- a/db/post_migrate/20220213103859_remove_integrations_type.rb
+++ b/db/post_migrate/20220213103859_remove_integrations_type.rb
@@ -73,7 +73,7 @@ class RemoveIntegrationsType < Gitlab::Database::Migration[1.0]
add_concurrent_index :integrations, :id, where: 'type_new is null', name: tmp_index_name
define_batchable_model(:integrations).where(type_new: nil).each_batch do |batch|
- min_id, max_id = batch.pluck(Arel.sql('MIN(id), MAX(id)')).first
+ min_id, max_id = batch.pick(Arel.sql('MIN(id), MAX(id)'))
connection.execute(<<~SQL)
WITH mapping(old_type, new_type) AS (VALUES
diff --git a/db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb b/db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb
index 69850b3a32f..2213268fa73 100644
--- a/db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb
+++ b/db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb
@@ -12,7 +12,7 @@ class ConsumeRemainingEncryptIntegrationPropertyJobs < Gitlab::Database::Migrati
relation = model.where.not(properties: nil).where(encrypted_properties: nil)
relation.each_batch(of: BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
+ range = batch.pick('MIN(id)', 'MAX(id)')
Gitlab::BackgroundMigration::EncryptIntegrationProperties.new.perform(*range)
end
diff --git a/db/post_migrate/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects.rb b/db/post_migrate/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects.rb
index 47b1c169d74..a9bb09b3378 100644
--- a/db/post_migrate/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects.rb
+++ b/db/post_migrate/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects.rb
@@ -1,31 +1,13 @@
# frozen_string_literal: true
class ScheduleSetLegacyOpenSourceLicenseAvailableForNonPublicProjects < Gitlab::Database::Migration[2.0]
- MIGRATION = 'SetLegacyOpenSourceLicenseAvailableForNonPublicProjects'
- INTERVAL = 2.minutes
- BATCH_SIZE = 5_000
- SUB_BATCH_SIZE = 200
-
- disable_ddl_transaction!
-
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
- return unless Gitlab.com?
-
- queue_batched_background_migration(
- MIGRATION,
- :projects,
- :id,
- job_interval: INTERVAL,
- batch_size: BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE
- )
+ # Replaced by 20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb
end
def down
- return unless Gitlab.com?
-
- delete_batched_background_migration(MIGRATION, :projects, :id, [])
+ # Replaced by 20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb
end
end
diff --git a/db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb b/db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb
index f11846ebe1d..45dbc028b18 100644
--- a/db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb
+++ b/db/post_migrate/20220524074947_finalize_backfill_null_note_discussion_ids.rb
@@ -12,7 +12,7 @@ class FinalizeBackfillNullNoteDiscussionIds < Gitlab::Database::Migration[2.0]
Gitlab::BackgroundMigration.steal(MIGRATION)
define_batchable_model('notes').where(discussion_id: nil).each_batch(of: BATCH_SIZE) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
+ range = batch.pick('MIN(id)', 'MAX(id)')
Gitlab::BackgroundMigration::BackfillNoteDiscussionId.new.perform(*range)
end
diff --git a/db/post_migrate/20220525201022_add_temporary_index_for_vulnerability_reads_cluster_agent_id_migration.rb b/db/post_migrate/20220525201022_add_temporary_index_for_vulnerability_reads_cluster_agent_id_migration.rb
new file mode 100644
index 00000000000..b795a41e9cd
--- /dev/null
+++ b/db/post_migrate/20220525201022_add_temporary_index_for_vulnerability_reads_cluster_agent_id_migration.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddTemporaryIndexForVulnerabilityReadsClusterAgentIdMigration < Gitlab::Database::Migration[2.0]
+ INDEX_VULNERABILITY_READS_NAME = 'tmp_index_cis_vulnerability_reads_on_id'
+
+ disable_ddl_transaction!
+
+ def up
+ # this index is used in 20220525221133_schedule_backfill_vulnerability_reads_cluster_agent
+ add_concurrent_index :vulnerability_reads, :id, name: INDEX_VULNERABILITY_READS_NAME, where: 'report_type = 7'
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_reads, INDEX_VULNERABILITY_READS_NAME
+ end
+end
diff --git a/db/post_migrate/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent.rb b/db/post_migrate/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent.rb
new file mode 100644
index 00000000000..bf83781e89c
--- /dev/null
+++ b/db/post_migrate/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class ScheduleBackfillVulnerabilityReadsClusterAgent < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+ MIGRATION_NAME = 'BackfillVulnerabilityReadsClusterAgent'
+ BATCH_CLASS_NAME = 'BackfillVulnerabilityReadsClusterAgentBatchingStrategy'
+
+ disable_ddl_transaction!
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION_NAME,
+ :vulnerability_reads,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ batch_class_name: BATCH_CLASS_NAME,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION_NAME, :vulnerability_reads, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220603173103_update_vulnerabilities_project_id_id_index.rb b/db/post_migrate/20220603173103_update_vulnerabilities_project_id_id_index.rb
new file mode 100644
index 00000000000..8f10fd61273
--- /dev/null
+++ b/db/post_migrate/20220603173103_update_vulnerabilities_project_id_id_index.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class UpdateVulnerabilitiesProjectIdIdIndex < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'idx_vulnerabilities_partial_devops_adoption_and_default_branch'
+ OLD_INDEX_NAME = 'idx_vulnerabilities_partial_devops_adoption'
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :created_at, :present_on_default_branch],
+ where: 'state != 1',
+ name: NEW_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :vulnerabilities, [:project_id, :created_at], where: 'state != 1', name: OLD_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, NEW_INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences.rb b/db/post_migrate/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..fe4ffbf6cc3
--- /dev/null
+++ b/db/post_migrate/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddSyncTmpIndexForPotentiallyMisassociatedVulnerabilityOccurrences < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "tmp_index_vulnerability_occurrences_on_id_and_scanner_id"
+ REPORT_TYPES = { cluster_image_scanning: 7, generic: 99 }.freeze
+ CLAUSE = "report_type IN (#{REPORT_TYPES.values.join(',')})"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_occurrences,
+ [:id, :scanner_id],
+ where: CLAUSE,
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220614185644_update_index_vulnerabilities_project_id_id.rb b/db/post_migrate/20220614185644_update_index_vulnerabilities_project_id_id.rb
new file mode 100644
index 00000000000..142cac09a01
--- /dev/null
+++ b/db/post_migrate/20220614185644_update_index_vulnerabilities_project_id_id.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class UpdateIndexVulnerabilitiesProjectIdId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'index_vulnerabilities_project_id_and_id_on_default_branch'
+ OLD_INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id'
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :id],
+ where: 'present_on_default_branch IS TRUE',
+ name: NEW_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :vulnerabilities, [:project_id, :id], name: OLD_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, NEW_INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220621192541_add_project_id_state_severity_default_branch_index_for_vulnerabilities.rb b/db/post_migrate/20220621192541_add_project_id_state_severity_default_branch_index_for_vulnerabilities.rb
new file mode 100644
index 00000000000..76753cdd737
--- /dev/null
+++ b/db/post_migrate/20220621192541_add_project_id_state_severity_default_branch_index_for_vulnerabilities.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddProjectIdStateSeverityDefaultBranchIndexForVulnerabilities < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerabilities_project_id_state_severity_default_branch'
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :state, :severity, :present_on_default_branch],
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220622070547_add_temp_index_for_container_registry_size_migration.rb b/db/post_migrate/20220622070547_add_temp_index_for_container_registry_size_migration.rb
index 64cdd75f5a7..1533c502b3d 100644
--- a/db/post_migrate/20220622070547_add_temp_index_for_container_registry_size_migration.rb
+++ b/db/post_migrate/20220622070547_add_temp_index_for_container_registry_size_migration.rb
@@ -9,10 +9,12 @@ class AddTempIndexForContainerRegistrySizeMigration < Gitlab::Database::Migratio
def up
# Temporary index used in 20220622080547_backfill_project_statistics_with_container_registry_size
# Temporary index to be remove via https://gitlab.com/gitlab-org/gitlab/-/issues/366392
- add_concurrent_index :container_repositories, [:project_id], name: INDEX_CONTAINER_REGISTRY_SIZE,
- where: "migration_state = 'import_done' OR created_at >= '2022-01-23'"
- add_concurrent_index :project_statistics, [:project_id], name: INDEX_PROJECT_STATS_CONT_REG_SIZE,
- where: "container_registry_size = 0"
+ add_concurrent_index :container_repositories, [:project_id],
+ name: INDEX_CONTAINER_REGISTRY_SIZE,
+ where: "migration_state = 'import_done' OR created_at >= '2022-01-23'"
+ add_concurrent_index :project_statistics, [:project_id],
+ name: INDEX_PROJECT_STATS_CONT_REG_SIZE,
+ where: "container_registry_size = 0"
end
def down
diff --git a/db/post_migrate/20220629124942_remove_vulnerability_occurrences_migrated_to_new_structure_column.rb b/db/post_migrate/20220629124942_remove_vulnerability_occurrences_migrated_to_new_structure_column.rb
new file mode 100644
index 00000000000..2a980290cc9
--- /dev/null
+++ b/db/post_migrate/20220629124942_remove_vulnerability_occurrences_migrated_to_new_structure_column.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RemoveVulnerabilityOccurrencesMigratedToNewStructureColumn < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerability_occurrences_on_migrated_to_new_structure'
+
+ def up
+ with_lock_retries do
+ remove_column :vulnerability_occurrences, :migrated_to_new_structure
+ end
+ end
+
+ def down
+ unless column_exists?(:vulnerability_occurrences, :migrated_to_new_structure)
+ add_column :vulnerability_occurrences, :migrated_to_new_structure, :boolean, default: false, null: false
+ end
+
+ add_concurrent_index :vulnerability_occurrences, [:migrated_to_new_structure, :id], name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220707105529_cleanup_chat_name_service_id.rb b/db/post_migrate/20220707105529_cleanup_chat_name_service_id.rb
new file mode 100644
index 00000000000..aa3af4acf31
--- /dev/null
+++ b/db/post_migrate/20220707105529_cleanup_chat_name_service_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CleanupChatNameServiceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :chat_names, :service_id, :integration_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :chat_names, :service_id, :integration_id
+ end
+end
diff --git a/db/post_migrate/20220707160921_cleanup_slack_integration_service_id.rb b/db/post_migrate/20220707160921_cleanup_slack_integration_service_id.rb
new file mode 100644
index 00000000000..25b4252e48b
--- /dev/null
+++ b/db/post_migrate/20220707160921_cleanup_slack_integration_service_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CleanupSlackIntegrationServiceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :slack_integrations, :service_id, :integration_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :slack_integrations, :service_id, :integration_id
+ end
+end
diff --git a/db/post_migrate/20220712131533_cleanup_issue_tracker_data_service_id.rb b/db/post_migrate/20220712131533_cleanup_issue_tracker_data_service_id.rb
new file mode 100644
index 00000000000..be304c5fe6d
--- /dev/null
+++ b/db/post_migrate/20220712131533_cleanup_issue_tracker_data_service_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CleanupIssueTrackerDataServiceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :issue_tracker_data, :service_id, :integration_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :issue_tracker_data, :service_id, :integration_id
+ end
+end
diff --git a/db/post_migrate/20220712144900_cleanup_jira_tracker_data_service_id.rb b/db/post_migrate/20220712144900_cleanup_jira_tracker_data_service_id.rb
new file mode 100644
index 00000000000..90b35f03054
--- /dev/null
+++ b/db/post_migrate/20220712144900_cleanup_jira_tracker_data_service_id.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CleanupJiraTrackerDataServiceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_rename :jira_tracker_data, :service_id, :integration_id
+ end
+
+ def down
+ undo_cleanup_concurrent_column_rename :jira_tracker_data, :service_id, :integration_id
+ end
+end
diff --git a/db/post_migrate/20220715152108_backfill_project_import_level.rb b/db/post_migrate/20220715152108_backfill_project_import_level.rb
new file mode 100644
index 00000000000..65a0dc0a58a
--- /dev/null
+++ b/db/post_migrate/20220715152108_backfill_project_import_level.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class BackfillProjectImportLevel < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = 'BackfillProjectImportLevel'
+ INTERVAL = 120.seconds
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :namespaces,
+ :id,
+ job_interval: INTERVAL
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :namespaces, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220715185348_add_index_on_security_findings_id_and_partition_number.rb b/db/post_migrate/20220715185348_add_index_on_security_findings_id_and_partition_number.rb
new file mode 100644
index 00000000000..e867ef81381
--- /dev/null
+++ b/db/post_migrate/20220715185348_add_index_on_security_findings_id_and_partition_number.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnSecurityFindingsIdAndPartitionNumber < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'security_findings_partitioned_pkey'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_findings, [:id, :partition_number], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220715185436_add_index_on_security_findings_unique_columns.rb b/db/post_migrate/20220715185436_add_index_on_security_findings_unique_columns.rb
new file mode 100644
index 00000000000..33b069a27d4
--- /dev/null
+++ b/db/post_migrate/20220715185436_add_index_on_security_findings_unique_columns.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnSecurityFindingsUniqueColumns < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_security_findings_on_unique_columns'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_findings, [:uuid, :scan_id, :partition_number], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220715190612_drop_index_on_security_findings_uuid_and_scan_id.rb b/db/post_migrate/20220715190612_drop_index_on_security_findings_uuid_and_scan_id.rb
new file mode 100644
index 00000000000..a8a9bab2c84
--- /dev/null
+++ b/db/post_migrate/20220715190612_drop_index_on_security_findings_uuid_and_scan_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DropIndexOnSecurityFindingsUuidAndScanId < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_security_findings_on_uuid_and_scan_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :security_findings, [:uuid, :scan_id], unique: true, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220715191629_change_primary_key_of_security_findings_table.rb b/db/post_migrate/20220715191629_change_primary_key_of_security_findings_table.rb
new file mode 100644
index 00000000000..c2859c68c52
--- /dev/null
+++ b/db/post_migrate/20220715191629_change_primary_key_of_security_findings_table.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class ChangePrimaryKeyOfSecurityFindingsTable < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def up
+ execute(<<~SQL)
+ ALTER TABLE security_findings DROP CONSTRAINT security_findings_pkey;
+ SQL
+
+ execute(<<~SQL)
+ ALTER TABLE security_findings ADD CONSTRAINT security_findings_pkey PRIMARY KEY USING index security_findings_partitioned_pkey;
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ ALTER TABLE security_findings DROP CONSTRAINT security_findings_pkey;
+ SQL
+
+ execute(<<~SQL)
+ ALTER TABLE security_findings ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id);
+ SQL
+
+ execute(<<~SQL)
+ CREATE UNIQUE INDEX security_findings_partitioned_pkey ON security_findings USING btree(id, partition_number);
+ SQL
+ end
+end
diff --git a/db/post_migrate/20220719081542_drop_queued_at_index_from_ci_builds.rb b/db/post_migrate/20220719081542_drop_queued_at_index_from_ci_builds.rb
new file mode 100644
index 00000000000..4a16d022c70
--- /dev/null
+++ b/db/post_migrate/20220719081542_drop_queued_at_index_from_ci_builds.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class DropQueuedAtIndexFromCiBuilds < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ci_builds_on_queued_at'
+
+ def up
+ remove_concurrent_index_by_name :ci_builds, INDEX_NAME
+ end
+
+ # rubocop:disable Migration/PreventIndexCreation
+ def down
+ add_concurrent_index :ci_builds, :queued_at, name: INDEX_NAME
+ end
+ # rubocop:enable Migration/PreventIndexCreation
+end
diff --git a/db/post_migrate/20220719165537_remove_ci_runners_semver_column.rb b/db/post_migrate/20220719165537_remove_ci_runners_semver_column.rb
new file mode 100644
index 00000000000..a6929153d10
--- /dev/null
+++ b/db/post_migrate/20220719165537_remove_ci_runners_semver_column.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RemoveCiRunnersSemverColumn < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ci_runners_on_id_and_semver_cidr'
+
+ def up
+ with_lock_retries do
+ remove_column :ci_runners, :semver
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_column :ci_runners, :semver, :text, null: true
+ end
+ add_text_limit :ci_runners, :semver, 16
+ add_concurrent_index :ci_runners, 'id, (semver::cidr)', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220720090354_remove_pending_builds_covering_index_from_ci_builds.rb b/db/post_migrate/20220720090354_remove_pending_builds_covering_index_from_ci_builds.rb
new file mode 100644
index 00000000000..fb3d12840cc
--- /dev/null
+++ b/db/post_migrate/20220720090354_remove_pending_builds_covering_index_from_ci_builds.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class RemovePendingBuildsCoveringIndexFromCiBuilds < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ci_builds_runner_id_pending_covering'
+
+ def up
+ remove_concurrent_index_by_name :ci_builds, INDEX_NAME
+ end
+
+ # rubocop:disable Migration/PreventIndexCreation
+ def down
+ disable_statement_timeout do
+ unless index_exists_by_name?(:ci_builds, INDEX_NAME)
+ execute <<~SQL.squish
+ CREATE INDEX CONCURRENTLY #{INDEX_NAME}
+ ON ci_builds (runner_id, id)
+ INCLUDE (project_id)
+ WHERE status = 'pending' AND type = 'Ci::Build'
+ SQL
+ end
+ end
+ end
+ # rubocop:enable Migration/PreventIndexCreation
+end
diff --git a/db/post_migrate/20220720121421_remove_pat_and_ssh_enforcement_columns_from_application_settings.rb b/db/post_migrate/20220720121421_remove_pat_and_ssh_enforcement_columns_from_application_settings.rb
new file mode 100644
index 00000000000..b03cad08f35
--- /dev/null
+++ b/db/post_migrate/20220720121421_remove_pat_and_ssh_enforcement_columns_from_application_settings.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class RemovePatAndSshEnforcementColumnsFromApplicationSettings < Gitlab::Database::Migration[2.0]
+ def change
+ remove_column :application_settings, :enforce_pat_expiration, :boolean, default: true, null: false
+ remove_column :application_settings, :enforce_ssh_key_expiration, :boolean, default: true, null: false
+ end
+end
diff --git a/db/post_migrate/20220720123249_remove_token_column_from_ci_builds.rb b/db/post_migrate/20220720123249_remove_token_column_from_ci_builds.rb
new file mode 100644
index 00000000000..1bc13b6ea05
--- /dev/null
+++ b/db/post_migrate/20220720123249_remove_token_column_from_ci_builds.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class RemoveTokenColumnFromCiBuilds < Gitlab::Database::Migration[2.0]
+ enable_lock_retries!
+
+ def change
+ remove_column :ci_builds, :token, :string
+ end
+end
diff --git a/db/post_migrate/20220720171102_add_index_on_vulnerability_reads_namespace_id.rb b/db/post_migrate/20220720171102_add_index_on_vulnerability_reads_namespace_id.rb
new file mode 100644
index 00000000000..e90fcfd3016
--- /dev/null
+++ b/db/post_migrate/20220720171102_add_index_on_vulnerability_reads_namespace_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexOnVulnerabilityReadsNamespaceId < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_vuln_reads_on_namespace_id_state_severity_and_vuln_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_reads,
+ [:namespace_id, :state, :severity, :vulnerability_id],
+ name: INDEX_NAME,
+ order: { vulnerability_id: :desc }
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_reads, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220720171801_add_foreign_key_on_vulnerability_reads_namespace_id.rb b/db/post_migrate/20220720171801_add_foreign_key_on_vulnerability_reads_namespace_id.rb
new file mode 100644
index 00000000000..c1b6a9d6909
--- /dev/null
+++ b/db/post_migrate/20220720171801_add_foreign_key_on_vulnerability_reads_namespace_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyOnVulnerabilityReadsNamespaceId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :vulnerability_reads, :namespaces, column: :namespace_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :vulnerability_reads, column: :namespace_id
+ end
+ end
+end
diff --git a/db/post_migrate/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects.rb b/db/post_migrate/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects.rb
new file mode 100644
index 00000000000..7665d49b1d9
--- /dev/null
+++ b/db/post_migrate/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class ScheduleDisableLegacyOpenSourceLicenseForOneMemberNoRepoProjects < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'DisableLegacyOpenSourceLicenseForOneMemberNoRepoProjects'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 5_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 500
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ return unless Gitlab.com?
+
+ queue_batched_background_migration(
+ MIGRATION,
+ :projects,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ delete_batched_background_migration(MIGRATION, :projects, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220721140252_prepare_partial_trigram_indexes_for_issues.rb b/db/post_migrate/20220721140252_prepare_partial_trigram_indexes_for_issues.rb
new file mode 100644
index 00000000000..00a51f3024e
--- /dev/null
+++ b/db/post_migrate/20220721140252_prepare_partial_trigram_indexes_for_issues.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class PreparePartialTrigramIndexesForIssues < 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-\\u218F]*' OR description NOT SIMILAR TO '[\\u0000-\\u218F]*'"
+
+ prepare_async_index :issues, :description,
+ name: DESCRIPTION_INDEX_NAME,
+ using: :gin, opclass: { description: :gin_trgm_ops },
+ where: "title NOT SIMILAR TO '[\\u0000-\\u218F]*' OR description NOT SIMILAR TO '[\\u0000-\\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/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb b/db/post_migrate/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb
new file mode 100644
index 00000000000..7fbf09846cf
--- /dev/null
+++ b/db/post_migrate/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class ScheduleDisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'DisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 5_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 200
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ return unless Gitlab.com?
+
+ queue_batched_background_migration(
+ MIGRATION,
+ :projects,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ delete_batched_background_migration(MIGRATION, :projects, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb b/db/post_migrate/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb
new file mode 100644
index 00000000000..546923141e2
--- /dev/null
+++ b/db/post_migrate/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class RescheduleSetLegacyOpenSourceLicenseAvailableForNonPublicProjects < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'SetLegacyOpenSourceLicenseAvailableForNonPublicProjects'
+ INTERVAL = 2.minutes
+ BATCH_SIZE = 5_000
+ MAX_BATCH_SIZE = 10_000
+ SUB_BATCH_SIZE = 200
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ return unless Gitlab.com?
+
+ delete_batched_background_migration(MIGRATION, :projects, :id, [])
+
+ queue_batched_background_migration(
+ MIGRATION,
+ :projects,
+ :id,
+ job_interval: INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ return unless Gitlab.com?
+
+ delete_batched_background_migration(MIGRATION, :projects, :id, [])
+ end
+end
diff --git a/db/post_migrate/20220722145845_schedule_backfilling_the_namespace_id_for_vulnerability_reads.rb b/db/post_migrate/20220722145845_schedule_backfilling_the_namespace_id_for_vulnerability_reads.rb
new file mode 100644
index 00000000000..e2d1846f8f6
--- /dev/null
+++ b/db/post_migrate/20220722145845_schedule_backfilling_the_namespace_id_for_vulnerability_reads.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ScheduleBackfillingTheNamespaceIdForVulnerabilityReads < Gitlab::Database::Migration[2.0]
+ MIGRATION_NAME = 'BackfillNamespaceIdOfVulnerabilityReads'
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+ disable_ddl_transaction!
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION_NAME,
+ :vulnerability_reads,
+ :vulnerability_id,
+ job_interval: 2.minutes,
+ batch_size: 10_000,
+ sub_batch_size: 200
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION_NAME, :vulnerability_reads, :vulnerability_id, [])
+ end
+end
diff --git a/db/post_migrate/20220725150127_update_jira_tracker_data_deployment_type_based_on_url.rb b/db/post_migrate/20220725150127_update_jira_tracker_data_deployment_type_based_on_url.rb
new file mode 100644
index 00000000000..0deba9b3e81
--- /dev/null
+++ b/db/post_migrate/20220725150127_update_jira_tracker_data_deployment_type_based_on_url.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class UpdateJiraTrackerDataDeploymentTypeBasedOnUrl < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'UpdateJiraTrackerDataDeploymentTypeBasedOnUrl'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 2_500
+ SUB_BATCH_SIZE = 2_500
+
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ say "Scheduling #{MIGRATION} jobs"
+ delete_queued_jobs(MIGRATION)
+ queue_batched_background_migration(
+ MIGRATION,
+ :jira_tracker_data,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20220726182310_add_user_fk_to_vulnerability_state_transitions.rb b/db/post_migrate/20220726182310_add_user_fk_to_vulnerability_state_transitions.rb
new file mode 100644
index 00000000000..ad0bf6141b2
--- /dev/null
+++ b/db/post_migrate/20220726182310_add_user_fk_to_vulnerability_state_transitions.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddUserFkToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerability_state_transitions_on_author_id'
+
+ def up
+ add_concurrent_index :vulnerability_state_transitions, :author_id, name: INDEX_NAME
+ add_concurrent_foreign_key :vulnerability_state_transitions, :users, column: :author_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :vulnerability_state_transitions, column: :author_id
+ end
+
+ remove_concurrent_index_by_name :vulnerability_state_transitions, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220728134255_update_index_vulnerabilities_common_finder.rb b/db/post_migrate/20220728134255_update_index_vulnerabilities_common_finder.rb
new file mode 100644
index 00000000000..617d7661b5b
--- /dev/null
+++ b/db/post_migrate/20220728134255_update_index_vulnerabilities_common_finder.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class UpdateIndexVulnerabilitiesCommonFinder < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'index_vulnerabilities_common_finder_query_on_default_branch'
+ OLD_INDEX_NAME = 'index_vulnerabilites_common_finder_query'
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :state, :report_type, :present_on_default_branch,
+ :severity, :id], name: NEW_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :vulnerabilities, [:project_id, :state, :report_type, :severity, :id], name: OLD_INDEX_NAME
+
+ remove_concurrent_index_by_name(:vulnerabilities, NEW_INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220729033851_add_partial_legacy_open_source_license_available_index.rb b/db/post_migrate/20220729033851_add_partial_legacy_open_source_license_available_index.rb
new file mode 100644
index 00000000000..c99c452c149
--- /dev/null
+++ b/db/post_migrate/20220729033851_add_partial_legacy_open_source_license_available_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialLegacyOpenSourceLicenseAvailableIndex < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_project_settings_on_legacy_open_source_license_available'
+
+ def up
+ add_concurrent_index :project_settings,
+ %i[legacy_open_source_license_available],
+ where: "legacy_open_source_license_available = TRUE",
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:project_settings, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20220729052031_add_index_on_vulnerability_reads_namespace_id_with_report_type.rb b/db/post_migrate/20220729052031_add_index_on_vulnerability_reads_namespace_id_with_report_type.rb
new file mode 100644
index 00000000000..53b2c1728e1
--- /dev/null
+++ b/db/post_migrate/20220729052031_add_index_on_vulnerability_reads_namespace_id_with_report_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexOnVulnerabilityReadsNamespaceIdWithReportType < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_vulnerability_reads_common_finder_query_with_namespace_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_reads,
+ [:namespace_id, :state, :report_type, :severity, :vulnerability_id],
+ name: INDEX_NAME,
+ order: { vulnerability_id: :desc }
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_reads, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220801144713_add_partial_trigram_index_for_issue_title.rb b/db/post_migrate/20220801144713_add_partial_trigram_index_for_issue_title.rb
new file mode 100644
index 00000000000..c4db8232eba
--- /dev/null
+++ b/db/post_migrate/20220801144713_add_partial_trigram_index_for_issue_title.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialTrigramIndexForIssueTitle < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_issues_on_title_trigram_non_latin'
+
+ def up
+ add_concurrent_index :issues, :title,
+ name: INDEX_NAME,
+ using: :gin, opclass: { description: :gin_trgm_ops },
+ where: "title NOT SIMILAR TO '[\\u0000-\\u218F]*' OR description NOT SIMILAR TO '[\\u0000-\\u218F]*'"
+ end
+
+ def down
+ remove_concurrent_index_by_name :issues, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220801150028_add_partial_trigram_index_for_issue_description.rb b/db/post_migrate/20220801150028_add_partial_trigram_index_for_issue_description.rb
new file mode 100644
index 00000000000..79f25718e15
--- /dev/null
+++ b/db/post_migrate/20220801150028_add_partial_trigram_index_for_issue_description.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialTrigramIndexForIssueDescription < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_issues_on_description_trigram_non_latin'
+
+ def up
+ add_concurrent_index :issues, :description,
+ name: INDEX_NAME,
+ using: :gin, opclass: { description: :gin_trgm_ops },
+ where: "title NOT SIMILAR TO '[\\u0000-\\u218F]*' OR description NOT SIMILAR TO '[\\u0000-\\u218F]*'"
+ end
+
+ def down
+ remove_concurrent_index_by_name :issues, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb b/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb
new file mode 100644
index 00000000000..92ca0998bae
--- /dev/null
+++ b/db/post_migrate/20220802112102_schedule_migrate_shared_vulnerability_scanners.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class ScheduleMigrateSharedVulnerabilityScanners < Gitlab::Database::Migration[2.0]
+ MIGRATION = "MigrateSharedVulnerabilityScanners"
+ TABLE_NAME = :vulnerability_occurrences
+ BATCH_COLUMN = :id
+ DELAY_INTERVAL = 5.minutes
+ BATCH_SIZE = 1000
+ SUB_BATCH_SIZE = 100
+
+ BATCH_MIN_VALUE = 23658505
+ BATCH_MAX_VALUE = 204428752
+
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ TABLE_NAME,
+ BATCH_COLUMN,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE,
+ batch_min_value: BATCH_MIN_VALUE,
+ batch_max_value: BATCH_MAX_VALUE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, TABLE_NAME, BATCH_COLUMN, [])
+ end
+end
diff --git a/db/post_migrate/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics.rb b/db/post_migrate/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics.rb
new file mode 100644
index 00000000000..46b98d319fd
--- /dev/null
+++ b/db/post_migrate/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class RescheduleBackfillContainerRegistrySizeIntoProjectStatistics < Gitlab::Database::Migration[2.0]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 500
+ MIGRATION_CLASS = 'BackfillProjectStatisticsContainerRepositorySize'
+ BATCH_CLASS_NAME = 'BackfillProjectStatisticsWithContainerRegistrySizeBatchingStrategy'
+ SUB_BATCH_SIZE = 100
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.dev_or_test_env? || Gitlab.com?
+
+ # remove the original migration
+ delete_batched_background_migration(MIGRATION_CLASS, :container_repositories, :project_id, [])
+
+ # reschedule the migration
+ queue_batched_background_migration(
+ MIGRATION_CLASS,
+ :container_repositories,
+ :project_id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ batch_class_name: BATCH_CLASS_NAME,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ return unless Gitlab.dev_or_test_env? || Gitlab.com?
+
+ delete_batched_background_migration(MIGRATION_CLASS, :container_repositories, :project_id, [])
+ end
+end
diff --git a/db/post_migrate/20220802132158_index_on_integration_type_new_id_when_active_and_has_group.rb b/db/post_migrate/20220802132158_index_on_integration_type_new_id_when_active_and_has_group.rb
new file mode 100644
index 00000000000..81e95f531c1
--- /dev/null
+++ b/db/post_migrate/20220802132158_index_on_integration_type_new_id_when_active_and_has_group.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class IndexOnIntegrationTypeNewIdWhenActiveAndHasGroup < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_integrations_on_type_new_id_when_active_and_has_group'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :integrations,
+ [:type_new, :id, :inherit_from_id],
+ name: INDEX_NAME,
+ where: '((active = true) AND (group_id IS NOT NULL))'
+ end
+
+ def down
+ remove_concurrent_index_by_name :integrations, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220802204737_remove_deactivated_user_highest_role_stats.rb b/db/post_migrate/20220802204737_remove_deactivated_user_highest_role_stats.rb
new file mode 100644
index 00000000000..e23fbfdf7f2
--- /dev/null
+++ b/db/post_migrate/20220802204737_remove_deactivated_user_highest_role_stats.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class RemoveDeactivatedUserHighestRoleStats < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ # This migration is applicable to self-managed instances that may utilize the
+ # dormant user deactivation feature. This feature is not enabled on Gitlab.com.
+ return if Gitlab.com?
+
+ users_table = define_batchable_model('users')
+ user_highest_roles_table = define_batchable_model('user_highest_roles')
+
+ users_table.where(state: 'deactivated').each_batch do |users_batch|
+ user_ids = users_batch.pluck(:id)
+ user_highest_roles_table.where(user_id: user_ids).delete_all
+ end
+ end
+
+ def down
+ # no-op
+
+ # This migration removes entries from the UserHighestRole table and cannot be reversed
+ end
+end
diff --git a/db/post_migrate/20220803042351_add_tmp_index_todos_attention_request_action.rb b/db/post_migrate/20220803042351_add_tmp_index_todos_attention_request_action.rb
new file mode 100644
index 00000000000..fa80b2b95e7
--- /dev/null
+++ b/db/post_migrate/20220803042351_add_tmp_index_todos_attention_request_action.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddTmpIndexTodosAttentionRequestAction < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = "tmp_index_todos_attention_request_action"
+ ATTENTION_REQUESTED = 10
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :todos, [:id],
+ where: "action = #{ATTENTION_REQUESTED}",
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :todos, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220803042352_cleanup_mr_attention_request_todos.rb b/db/post_migrate/20220803042352_cleanup_mr_attention_request_todos.rb
new file mode 100644
index 00000000000..d3b281b08ad
--- /dev/null
+++ b/db/post_migrate/20220803042352_cleanup_mr_attention_request_todos.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CleanupMrAttentionRequestTodos < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ class Todo < MigrationRecord
+ self.table_name = 'todos'
+
+ include ::EachBatch
+
+ ATTENTION_REQUESTED = 10
+ end
+
+ def up
+ Todo.where(action: Todo::ATTENTION_REQUESTED).each_batch do |todos_batch|
+ todos_batch.delete_all
+ end
+ end
+
+ def down
+ # Attention request feature has been reverted.
+ end
+end
diff --git a/db/post_migrate/20220804235614_add_comment_to_vulnerability_state_transitions.rb b/db/post_migrate/20220804235614_add_comment_to_vulnerability_state_transitions.rb
new file mode 100644
index 00000000000..3e3cb5746bc
--- /dev/null
+++ b/db/post_migrate/20220804235614_add_comment_to_vulnerability_state_transitions.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddCommentToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.0]
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in db/post_migrate/20220805001210_add_text_limit_to_vulnerability_state_transitions_comment.rb
+ def change
+ add_column :vulnerability_state_transitions, :comment, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/post_migrate/20220805001210_add_text_limit_to_vulnerability_state_transitions_comment.rb b/db/post_migrate/20220805001210_add_text_limit_to_vulnerability_state_transitions_comment.rb
new file mode 100644
index 00000000000..dd84c0620ce
--- /dev/null
+++ b/db/post_migrate/20220805001210_add_text_limit_to_vulnerability_state_transitions_comment.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToVulnerabilityStateTransitionsComment < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :vulnerability_state_transitions, :comment, 255
+ end
+
+ def down
+ remove_text_limit :vulnerability_state_transitions, :comment
+ end
+end
diff --git a/db/post_migrate/20220808072054_prepare_index_removal_security_findings.rb b/db/post_migrate/20220808072054_prepare_index_removal_security_findings.rb
new file mode 100644
index 00000000000..eb4158fa9dd
--- /dev/null
+++ b/db/post_migrate/20220808072054_prepare_index_removal_security_findings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class PrepareIndexRemovalSecurityFindings < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = :index_on_security_findings_uuid_and_id_order_desc
+
+ def up
+ prepare_async_index_removal :security_findings, [:uuid, :id], name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20220808131659_remove_ci_namespace_monthly_usages_additional_amount_available_column.rb b/db/post_migrate/20220808131659_remove_ci_namespace_monthly_usages_additional_amount_available_column.rb
new file mode 100644
index 00000000000..70a1e425e0d
--- /dev/null
+++ b/db/post_migrate/20220808131659_remove_ci_namespace_monthly_usages_additional_amount_available_column.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RemoveCiNamespaceMonthlyUsagesAdditionalAmountAvailableColumn < Gitlab::Database::Migration[2.0]
+ def up
+ remove_column :ci_namespace_monthly_usages, :additional_amount_available
+ end
+
+ def down
+ add_column :ci_namespace_monthly_usages, :additional_amount_available, :integer, default: 0, null: false
+ end
+end
diff --git a/db/post_migrate/20220810093742_add_async_tmp_index_job_artifacts_id_and_expire_at.rb b/db/post_migrate/20220810093742_add_async_tmp_index_job_artifacts_id_and_expire_at.rb
new file mode 100644
index 00000000000..5a52b26ed92
--- /dev/null
+++ b/db/post_migrate/20220810093742_add_async_tmp_index_job_artifacts_id_and_expire_at.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddAsyncTmpIndexJobArtifactsIdAndExpireAt < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'tmp_index_ci_job_artifacts_on_id_expire_at_file_type_trace'
+
+ EXPIRE_AT_ON_22_MIDNIGHT_IN_TIMEZONE_OR_TRACE = <<~SQL
+ (EXTRACT(day FROM timezone('UTC', expire_at)) IN (21, 22, 23)
+ AND EXTRACT(minute FROM timezone('UTC', expire_at)) IN (0, 30, 45)
+ AND EXTRACT(second FROM timezone('UTC', expire_at)) = 0)
+ OR file_type = 3
+ SQL
+
+ def up
+ prepare_async_index :ci_job_artifacts, :id,
+ where: EXPIRE_AT_ON_22_MIDNIGHT_IN_TIMEZONE_OR_TRACE, name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :ci_job_artifacts, INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20220316022505 b/db/schema_migrations/20220316022505
new file mode 100644
index 00000000000..dd6bed30e8a
--- /dev/null
+++ b/db/schema_migrations/20220316022505
@@ -0,0 +1 @@
+c974e1a600323bac9b913e9e382384c302037ed6d1fc1df3b747471810293167 \ No newline at end of file
diff --git a/db/schema_migrations/20220506154054 b/db/schema_migrations/20220506154054
new file mode 100644
index 00000000000..8240d040c25
--- /dev/null
+++ b/db/schema_migrations/20220506154054
@@ -0,0 +1 @@
+a931441890bd5d472f88dcef82bb42e3c8046a981788f2362a8deb89f4ac049a \ No newline at end of file
diff --git a/db/schema_migrations/20220524184149 b/db/schema_migrations/20220524184149
new file mode 100644
index 00000000000..b75a7640a76
--- /dev/null
+++ b/db/schema_migrations/20220524184149
@@ -0,0 +1 @@
+f28bf2a6fe412342eef053b57cce14c0681d04f9e978e37bbd505f1efa36e92e \ No newline at end of file
diff --git a/db/schema_migrations/20220525201022 b/db/schema_migrations/20220525201022
new file mode 100644
index 00000000000..7b4ce7c509c
--- /dev/null
+++ b/db/schema_migrations/20220525201022
@@ -0,0 +1 @@
+c2b2fc7674b99791f6d239e42add7db3c72f2b27e653e2348887d0178f77686a \ No newline at end of file
diff --git a/db/schema_migrations/20220525221133 b/db/schema_migrations/20220525221133
new file mode 100644
index 00000000000..0e78ee5df45
--- /dev/null
+++ b/db/schema_migrations/20220525221133
@@ -0,0 +1 @@
+b22a0dd285d383f556a5402441f3e82a6db6dd47008444b94303351b295b414e \ No newline at end of file
diff --git a/db/schema_migrations/20220603173103 b/db/schema_migrations/20220603173103
new file mode 100644
index 00000000000..cf2a199ee5b
--- /dev/null
+++ b/db/schema_migrations/20220603173103
@@ -0,0 +1 @@
+4a618d15ee56e7cb9a20385824cc63cf12f8a2eb3604c787f79356398094a3b6 \ No newline at end of file
diff --git a/db/schema_migrations/20220607082910 b/db/schema_migrations/20220607082910
new file mode 100644
index 00000000000..db9c63e20c5
--- /dev/null
+++ b/db/schema_migrations/20220607082910
@@ -0,0 +1 @@
+2ce59d4c11daec217cd55148476f123f25727c5519f0f180f68e07b4fa33be97 \ No newline at end of file
diff --git a/db/schema_migrations/20220614185644 b/db/schema_migrations/20220614185644
new file mode 100644
index 00000000000..dcc2d926276
--- /dev/null
+++ b/db/schema_migrations/20220614185644
@@ -0,0 +1 @@
+f1d4faf4d32a3271a97b389d53c9d3accbfa3fa2bd47d63257fe589efa4bb665 \ No newline at end of file
diff --git a/db/schema_migrations/20220619212618 b/db/schema_migrations/20220619212618
new file mode 100644
index 00000000000..1ecfdb6aed4
--- /dev/null
+++ b/db/schema_migrations/20220619212618
@@ -0,0 +1 @@
+34a9ec48e8480f3a235089f01944f60e93e4b87909a660f18a42bc47a3a0fe51 \ No newline at end of file
diff --git a/db/schema_migrations/20220621192541 b/db/schema_migrations/20220621192541
new file mode 100644
index 00000000000..6a638616894
--- /dev/null
+++ b/db/schema_migrations/20220621192541
@@ -0,0 +1 @@
+b5bc058c3a0217dc6a62af717861f4bce052c8b86d6c053919e2b10bcc9af845 \ No newline at end of file
diff --git a/db/schema_migrations/20220629124942 b/db/schema_migrations/20220629124942
new file mode 100644
index 00000000000..a5f9968b622
--- /dev/null
+++ b/db/schema_migrations/20220629124942
@@ -0,0 +1 @@
+d0e6dda681ec7980d1aeccd7976425edbe212b0676e6c57c6941f0ba73bbb8b4 \ No newline at end of file
diff --git a/db/schema_migrations/20220707105335 b/db/schema_migrations/20220707105335
new file mode 100644
index 00000000000..1f1a4d8b41b
--- /dev/null
+++ b/db/schema_migrations/20220707105335
@@ -0,0 +1 @@
+2f3dc1952c43a6786f8a66713ac89ca24f828f683a57f7373c91d5e629242909 \ No newline at end of file
diff --git a/db/schema_migrations/20220707105529 b/db/schema_migrations/20220707105529
new file mode 100644
index 00000000000..df01b63f89c
--- /dev/null
+++ b/db/schema_migrations/20220707105529
@@ -0,0 +1 @@
+82504ed0c287565d9b9eadf929badaa893beaac36224c7c2c7b4e14a663fa9e5 \ No newline at end of file
diff --git a/db/schema_migrations/20220707160707 b/db/schema_migrations/20220707160707
new file mode 100644
index 00000000000..f9b10cb637f
--- /dev/null
+++ b/db/schema_migrations/20220707160707
@@ -0,0 +1 @@
+772af1dd1d9d7a0cc9ec35b23db66cf2f43767f1f8351023e951090d91544d23 \ No newline at end of file
diff --git a/db/schema_migrations/20220707160921 b/db/schema_migrations/20220707160921
new file mode 100644
index 00000000000..644d56898ca
--- /dev/null
+++ b/db/schema_migrations/20220707160921
@@ -0,0 +1 @@
+ce50506f9e56f26b5e773888c0ec8d1465b3b4aed152bf8c9a20bf1215e9fa19 \ No newline at end of file
diff --git a/db/schema_migrations/20220707181910 b/db/schema_migrations/20220707181910
new file mode 100644
index 00000000000..d9aef7bdba0
--- /dev/null
+++ b/db/schema_migrations/20220707181910
@@ -0,0 +1 @@
+78bb335a94237bfb5c5401807c9fc5e8ff9ec331af0ca0d3c5626253af5cde3f \ No newline at end of file
diff --git a/db/schema_migrations/20220707181920 b/db/schema_migrations/20220707181920
new file mode 100644
index 00000000000..de6972176f9
--- /dev/null
+++ b/db/schema_migrations/20220707181920
@@ -0,0 +1 @@
+179c400efd7d31b78b4314104c5e9cbdf744c5e2966cecf724d1b7088b515fd1 \ No newline at end of file
diff --git a/db/schema_migrations/20220707181930 b/db/schema_migrations/20220707181930
new file mode 100644
index 00000000000..11594611609
--- /dev/null
+++ b/db/schema_migrations/20220707181930
@@ -0,0 +1 @@
+431392f5f88f493371b77263bbe380d08e486e8ba0d013213e6fe7fdcda3c7db \ No newline at end of file
diff --git a/db/schema_migrations/20220707190546 b/db/schema_migrations/20220707190546
new file mode 100644
index 00000000000..b46b27e60c8
--- /dev/null
+++ b/db/schema_migrations/20220707190546
@@ -0,0 +1 @@
+fd68f63f6ec50233c99b5173b69fa6ff99b1ae9b2d023cdccdff3cd94be35b36 \ No newline at end of file
diff --git a/db/schema_migrations/20220712131513 b/db/schema_migrations/20220712131513
new file mode 100644
index 00000000000..e16feb4d96c
--- /dev/null
+++ b/db/schema_migrations/20220712131513
@@ -0,0 +1 @@
+4ee9f603c04284cbc0fcb6aa47ecc0f0fe238b4d68083a51f5f170edca19608b \ No newline at end of file
diff --git a/db/schema_migrations/20220712131533 b/db/schema_migrations/20220712131533
new file mode 100644
index 00000000000..276b649097e
--- /dev/null
+++ b/db/schema_migrations/20220712131533
@@ -0,0 +1 @@
+b4ff0087acba9b91182219ea49a5a7d1bfd5b55391f0174ea62a2bfa14af03ce \ No newline at end of file
diff --git a/db/schema_migrations/20220712144843 b/db/schema_migrations/20220712144843
new file mode 100644
index 00000000000..d1bd4fbecc8
--- /dev/null
+++ b/db/schema_migrations/20220712144843
@@ -0,0 +1 @@
+2d225c96f4fbc08b2443a1e6c723d2a337ed1e10412323ba816858db03299738 \ No newline at end of file
diff --git a/db/schema_migrations/20220712144900 b/db/schema_migrations/20220712144900
new file mode 100644
index 00000000000..e84149e7b76
--- /dev/null
+++ b/db/schema_migrations/20220712144900
@@ -0,0 +1 @@
+4e19d3306807b83e4dddd3c7212b662f39c0d852826df1d22fc29c251fa0d1da \ No newline at end of file
diff --git a/db/schema_migrations/20220715152108 b/db/schema_migrations/20220715152108
new file mode 100644
index 00000000000..23d61b45334
--- /dev/null
+++ b/db/schema_migrations/20220715152108
@@ -0,0 +1 @@
+76f4adebfb71dcd51f861097ba441ae5ee3f62eeb2060f147730d4e6c6006402 \ No newline at end of file
diff --git a/db/schema_migrations/20220715185348 b/db/schema_migrations/20220715185348
new file mode 100644
index 00000000000..6df20d578f0
--- /dev/null
+++ b/db/schema_migrations/20220715185348
@@ -0,0 +1 @@
+5a8e178601b1b88bef0186269bc62f8e3b10eacb0fe8a9a11e322c244883cfde \ No newline at end of file
diff --git a/db/schema_migrations/20220715185436 b/db/schema_migrations/20220715185436
new file mode 100644
index 00000000000..31f9a069d31
--- /dev/null
+++ b/db/schema_migrations/20220715185436
@@ -0,0 +1 @@
+673e77eb5ffa49ab70088a7a43119c5f388d199e69504994c8c0a2a867ee1da3 \ No newline at end of file
diff --git a/db/schema_migrations/20220715190612 b/db/schema_migrations/20220715190612
new file mode 100644
index 00000000000..ffafb037b43
--- /dev/null
+++ b/db/schema_migrations/20220715190612
@@ -0,0 +1 @@
+bbb07db2554d2b1c7083341efcdc065a3a25ba4b042b0b3ea3cb26ec25e1e023 \ No newline at end of file
diff --git a/db/schema_migrations/20220715191629 b/db/schema_migrations/20220715191629
new file mode 100644
index 00000000000..88874ec93d3
--- /dev/null
+++ b/db/schema_migrations/20220715191629
@@ -0,0 +1 @@
+e300a6144e63f734e41b3a3ad40089dea5764ea2636ea11f5782fe86b6574229 \ No newline at end of file
diff --git a/db/schema_migrations/20220718083945 b/db/schema_migrations/20220718083945
new file mode 100644
index 00000000000..f1d247e5349
--- /dev/null
+++ b/db/schema_migrations/20220718083945
@@ -0,0 +1 @@
+42b601de66244f527b8c40182b7c9c8ba3a6ea9863582be3c499ffe2491c8d4f \ No newline at end of file
diff --git a/db/schema_migrations/20220719081542 b/db/schema_migrations/20220719081542
new file mode 100644
index 00000000000..4bd2a3008ca
--- /dev/null
+++ b/db/schema_migrations/20220719081542
@@ -0,0 +1 @@
+2d5bf23684afbd4dbf3251c4886c22eaaa144332901c1183bc474772f065c54f \ No newline at end of file
diff --git a/db/schema_migrations/20220719165537 b/db/schema_migrations/20220719165537
new file mode 100644
index 00000000000..f60f26fb705
--- /dev/null
+++ b/db/schema_migrations/20220719165537
@@ -0,0 +1 @@
+c9b214fd49c97d17f43faef4d86b811ea2ad5f573c3cb4a6725de8ee4c92262a \ No newline at end of file
diff --git a/db/schema_migrations/20220720090354 b/db/schema_migrations/20220720090354
new file mode 100644
index 00000000000..f6a34d452ec
--- /dev/null
+++ b/db/schema_migrations/20220720090354
@@ -0,0 +1 @@
+caf9b383524401d5b552d5593aa8ae51d58138759af5aebdec0825818033100d \ No newline at end of file
diff --git a/db/schema_migrations/20220720121421 b/db/schema_migrations/20220720121421
new file mode 100644
index 00000000000..da6450068ee
--- /dev/null
+++ b/db/schema_migrations/20220720121421
@@ -0,0 +1 @@
+3ccb1e6d2ab41d4d84e0582563c68b0518d57f518d1560b1bacd257a40e14034 \ No newline at end of file
diff --git a/db/schema_migrations/20220720123249 b/db/schema_migrations/20220720123249
new file mode 100644
index 00000000000..f29b38f7efe
--- /dev/null
+++ b/db/schema_migrations/20220720123249
@@ -0,0 +1 @@
+d64ae3a91253fa497f897e7843c9b86f1dec3ccb6f997c4bbe50aec96699f1d2 \ No newline at end of file
diff --git a/db/schema_migrations/20220720161816 b/db/schema_migrations/20220720161816
new file mode 100644
index 00000000000..be1e2809a3f
--- /dev/null
+++ b/db/schema_migrations/20220720161816
@@ -0,0 +1 @@
+8933e0dfff73ebef359de9512e8a89d43da37991b03500aac1d1a1ba78d6a4a9 \ No newline at end of file
diff --git a/db/schema_migrations/20220720162123 b/db/schema_migrations/20220720162123
new file mode 100644
index 00000000000..8a4c17468c0
--- /dev/null
+++ b/db/schema_migrations/20220720162123
@@ -0,0 +1 @@
+1b8fd9394fefd20a8a0ad281f10b4006063e436e3e41d5651e84b43dccd9c221 \ No newline at end of file
diff --git a/db/schema_migrations/20220720171102 b/db/schema_migrations/20220720171102
new file mode 100644
index 00000000000..f041d3d9db3
--- /dev/null
+++ b/db/schema_migrations/20220720171102
@@ -0,0 +1 @@
+4daf9a0b571968640c4b6ddfa6dbc2d71ed1632b4dc4d350cd5cab4ae53c8178 \ No newline at end of file
diff --git a/db/schema_migrations/20220720171801 b/db/schema_migrations/20220720171801
new file mode 100644
index 00000000000..ada8897b868
--- /dev/null
+++ b/db/schema_migrations/20220720171801
@@ -0,0 +1 @@
+161186e3bb37a3c03f7e6ec5f833e86bcc163af33847666006e9a0cf814eb876 \ No newline at end of file
diff --git a/db/schema_migrations/20220720210446 b/db/schema_migrations/20220720210446
new file mode 100644
index 00000000000..143d05d70f3
--- /dev/null
+++ b/db/schema_migrations/20220720210446
@@ -0,0 +1 @@
+d9ce6e056d66e6c1fb9dc6ac6340cc74cf2572edefce1a2a2cefe0556ee5db41 \ No newline at end of file
diff --git a/db/schema_migrations/20220721031446 b/db/schema_migrations/20220721031446
new file mode 100644
index 00000000000..cb58abdd70c
--- /dev/null
+++ b/db/schema_migrations/20220721031446
@@ -0,0 +1 @@
+fb37a812240cd314227b112f1c5f379fece783fddcf922ceafbf2c968c72ab30 \ No newline at end of file
diff --git a/db/schema_migrations/20220721140252 b/db/schema_migrations/20220721140252
new file mode 100644
index 00000000000..9bf2074ccc4
--- /dev/null
+++ b/db/schema_migrations/20220721140252
@@ -0,0 +1 @@
+42de6dadaff1c9666f759992488eda01c5327e5c377088ffc703b60fa37b18da \ No newline at end of file
diff --git a/db/schema_migrations/20220722084543 b/db/schema_migrations/20220722084543
new file mode 100644
index 00000000000..44d94a312b8
--- /dev/null
+++ b/db/schema_migrations/20220722084543
@@ -0,0 +1 @@
+b189304b940d01a527bba4ad8b0865ae44de1e3af2ef1b711d95993821106b6b \ No newline at end of file
diff --git a/db/schema_migrations/20220722110026 b/db/schema_migrations/20220722110026
new file mode 100644
index 00000000000..56f4699cace
--- /dev/null
+++ b/db/schema_migrations/20220722110026
@@ -0,0 +1 @@
+79c7847740cb02fffeaeae55f869889f201b7a9431693bea7249ddff9d405fb4 \ No newline at end of file
diff --git a/db/schema_migrations/20220722123318 b/db/schema_migrations/20220722123318
new file mode 100644
index 00000000000..a9b01a68114
--- /dev/null
+++ b/db/schema_migrations/20220722123318
@@ -0,0 +1 @@
+71ac60c42a546f65329eb2028d2de1252da01909b866fcc5151b928ee69f26d6 \ No newline at end of file
diff --git a/db/schema_migrations/20220722145845 b/db/schema_migrations/20220722145845
new file mode 100644
index 00000000000..458facc060d
--- /dev/null
+++ b/db/schema_migrations/20220722145845
@@ -0,0 +1 @@
+612a9cf3004e4d837749ef522ed72920275c9ddd8570b1a5a5e6ff51b49afd67 \ No newline at end of file
diff --git a/db/schema_migrations/20220722150231 b/db/schema_migrations/20220722150231
new file mode 100644
index 00000000000..fb36c04c168
--- /dev/null
+++ b/db/schema_migrations/20220722150231
@@ -0,0 +1 @@
+d5fac73cd92e84f49b41aa38e560eed36906e29e7009ff03ef59ebcf9836ee1f \ No newline at end of file
diff --git a/db/schema_migrations/20220722203840 b/db/schema_migrations/20220722203840
new file mode 100644
index 00000000000..0c719b0ce3d
--- /dev/null
+++ b/db/schema_migrations/20220722203840
@@ -0,0 +1 @@
+6a3f6ca25cac7f846c2f52388a8898bd05095f0d612bc7d4950e899880e0c8b8 \ No newline at end of file
diff --git a/db/schema_migrations/20220723120039 b/db/schema_migrations/20220723120039
new file mode 100644
index 00000000000..54be61091e3
--- /dev/null
+++ b/db/schema_migrations/20220723120039
@@ -0,0 +1 @@
+1a6a488243a8fa564f07301028477d64ca290b4ec636cfaab4816dab8bf3dd3f \ No newline at end of file
diff --git a/db/schema_migrations/20220725150127 b/db/schema_migrations/20220725150127
new file mode 100644
index 00000000000..3cbc80d8883
--- /dev/null
+++ b/db/schema_migrations/20220725150127
@@ -0,0 +1 @@
+78563f41df5a49803c59b4e41845c985fd1e5f19b1050998fb78d53a9dfe7a28 \ No newline at end of file
diff --git a/db/schema_migrations/20220726025516 b/db/schema_migrations/20220726025516
new file mode 100644
index 00000000000..58bab5467db
--- /dev/null
+++ b/db/schema_migrations/20220726025516
@@ -0,0 +1 @@
+326acd1c7e562056d29d5727869a0d0e5a5e9c387b0f54238c79c89f3947808b \ No newline at end of file
diff --git a/db/schema_migrations/20220726154012 b/db/schema_migrations/20220726154012
new file mode 100644
index 00000000000..b3e54480054
--- /dev/null
+++ b/db/schema_migrations/20220726154012
@@ -0,0 +1 @@
+6db09c05e52a9397eff77c56ab54886cd5b1ea5235425cbc83f865352dd75706 \ No newline at end of file
diff --git a/db/schema_migrations/20220726154013 b/db/schema_migrations/20220726154013
new file mode 100644
index 00000000000..6ef0bc248bb
--- /dev/null
+++ b/db/schema_migrations/20220726154013
@@ -0,0 +1 @@
+e079df21e69a855a3dc6c306e14796dacfabacc97632b859481009808a7ce133 \ No newline at end of file
diff --git a/db/schema_migrations/20220726154014 b/db/schema_migrations/20220726154014
new file mode 100644
index 00000000000..1991af185e8
--- /dev/null
+++ b/db/schema_migrations/20220726154014
@@ -0,0 +1 @@
+22c29639048e83f926b5ed2a44a14638fa70cba01f7f11a97f97ec321ae9173c \ No newline at end of file
diff --git a/db/schema_migrations/20220726154015 b/db/schema_migrations/20220726154015
new file mode 100644
index 00000000000..1eb661be563
--- /dev/null
+++ b/db/schema_migrations/20220726154015
@@ -0,0 +1 @@
+4c8d8356b977f875540bb931bfe03c811de17223bd76632ba65af53b7e227b08 \ No newline at end of file
diff --git a/db/schema_migrations/20220726154016 b/db/schema_migrations/20220726154016
new file mode 100644
index 00000000000..1df82964d21
--- /dev/null
+++ b/db/schema_migrations/20220726154016
@@ -0,0 +1 @@
+87bd0e2a2d0a9a8a45ce177ed847a15d2f015b155a1a47cd8fcf6ea00713b98c \ No newline at end of file
diff --git a/db/schema_migrations/20220726182310 b/db/schema_migrations/20220726182310
new file mode 100644
index 00000000000..fd5d282f525
--- /dev/null
+++ b/db/schema_migrations/20220726182310
@@ -0,0 +1 @@
+318684106f2976e285b6aaa1a73363badeec083a180a68973ba9d51dd89886c0 \ No newline at end of file
diff --git a/db/schema_migrations/20220726230052 b/db/schema_migrations/20220726230052
new file mode 100644
index 00000000000..985c5989f99
--- /dev/null
+++ b/db/schema_migrations/20220726230052
@@ -0,0 +1 @@
+1ca4a1260dee3a034529eeeb8a340a84b9bbc3abf0f853d46f26b6853527bbf0 \ No newline at end of file
diff --git a/db/schema_migrations/20220728114136 b/db/schema_migrations/20220728114136
new file mode 100644
index 00000000000..f5bd9962aa3
--- /dev/null
+++ b/db/schema_migrations/20220728114136
@@ -0,0 +1 @@
+eb0a6cff006f54f3b5fe12ab566dabfbefa1af46fafbfadde1b292b46e9d17c9 \ No newline at end of file
diff --git a/db/schema_migrations/20220728134255 b/db/schema_migrations/20220728134255
new file mode 100644
index 00000000000..f5ab53d70a0
--- /dev/null
+++ b/db/schema_migrations/20220728134255
@@ -0,0 +1 @@
+c868a83176c8e0024ef16e0f95d8a16a0f1b7be0c1a5d58902397cc0462a7e34 \ No newline at end of file
diff --git a/db/schema_migrations/20220729033851 b/db/schema_migrations/20220729033851
new file mode 100644
index 00000000000..b24c964cdb2
--- /dev/null
+++ b/db/schema_migrations/20220729033851
@@ -0,0 +1 @@
+0e8b193943aa02c8b700c06110725fd643378cf79715d1398238abc407639c67 \ No newline at end of file
diff --git a/db/schema_migrations/20220729052031 b/db/schema_migrations/20220729052031
new file mode 100644
index 00000000000..9305fbfade6
--- /dev/null
+++ b/db/schema_migrations/20220729052031
@@ -0,0 +1 @@
+504d33abb6bb9f8b53f33872715ce9839bd7264ef00618d033adf4d8899190b2 \ No newline at end of file
diff --git a/db/schema_migrations/20220729073603 b/db/schema_migrations/20220729073603
new file mode 100644
index 00000000000..eb69bd1ce51
--- /dev/null
+++ b/db/schema_migrations/20220729073603
@@ -0,0 +1 @@
+b0499c9b4cf3f39eec49dc7def7eaf8f1bbd03f2a34ba9eefa8440a109672136 \ No newline at end of file
diff --git a/db/schema_migrations/20220801144713 b/db/schema_migrations/20220801144713
new file mode 100644
index 00000000000..764c53e212a
--- /dev/null
+++ b/db/schema_migrations/20220801144713
@@ -0,0 +1 @@
+a332483a18eb46c1c4ce0d93b4269d630978a8c93e307f22ec5b412f3fa8f355 \ No newline at end of file
diff --git a/db/schema_migrations/20220801150028 b/db/schema_migrations/20220801150028
new file mode 100644
index 00000000000..c6d12f6a70d
--- /dev/null
+++ b/db/schema_migrations/20220801150028
@@ -0,0 +1 @@
+6515dbfcf8bc32c25e0547ea21af95c1dc2e89e3571abdef0e43e5289cd71c2c \ No newline at end of file
diff --git a/db/schema_migrations/20220802112102 b/db/schema_migrations/20220802112102
new file mode 100644
index 00000000000..b37b29b5800
--- /dev/null
+++ b/db/schema_migrations/20220802112102
@@ -0,0 +1 @@
+e5728437ae659e14906f5c0c36eea80d66e1ca056b037934b24d5a3f5489d8b7 \ No newline at end of file
diff --git a/db/schema_migrations/20220802114351 b/db/schema_migrations/20220802114351
new file mode 100644
index 00000000000..e371419c392
--- /dev/null
+++ b/db/schema_migrations/20220802114351
@@ -0,0 +1 @@
+c314412f0c5d4ad9447671a8e03e94af1a1b79718479769f763e20a689ce7d2f \ No newline at end of file
diff --git a/db/schema_migrations/20220802132158 b/db/schema_migrations/20220802132158
new file mode 100644
index 00000000000..06d7e747f30
--- /dev/null
+++ b/db/schema_migrations/20220802132158
@@ -0,0 +1 @@
+5aeb871227aa1a4c6c08c0e394d7b6324fe55ff6513e83668cf413c569b0b30f \ No newline at end of file
diff --git a/db/schema_migrations/20220802154757 b/db/schema_migrations/20220802154757
new file mode 100644
index 00000000000..a92f69e31da
--- /dev/null
+++ b/db/schema_migrations/20220802154757
@@ -0,0 +1 @@
+17d0f47b4663fdbcba617a456f713ebfe3782318abc7e46dc4a8e69bc76cf16f \ No newline at end of file
diff --git a/db/schema_migrations/20220802204737 b/db/schema_migrations/20220802204737
new file mode 100644
index 00000000000..faf1e6b89ba
--- /dev/null
+++ b/db/schema_migrations/20220802204737
@@ -0,0 +1 @@
+4de7fddbc2f44cf1450af25bd55a5f2586c3daf79b1443ec26ba9d47002707d7 \ No newline at end of file
diff --git a/db/schema_migrations/20220803042351 b/db/schema_migrations/20220803042351
new file mode 100644
index 00000000000..1b35b709eaf
--- /dev/null
+++ b/db/schema_migrations/20220803042351
@@ -0,0 +1 @@
+50c58b03d92451753cbdcb2e820e7d1ca9644f914027db46b57d2206e7832ec7 \ No newline at end of file
diff --git a/db/schema_migrations/20220803042352 b/db/schema_migrations/20220803042352
new file mode 100644
index 00000000000..011051cd5e4
--- /dev/null
+++ b/db/schema_migrations/20220803042352
@@ -0,0 +1 @@
+03d95257a9169a33a90baf28a6737f68fb999f920450a1cb90732820490be1c4 \ No newline at end of file
diff --git a/db/schema_migrations/20220803145637 b/db/schema_migrations/20220803145637
new file mode 100644
index 00000000000..36688f97184
--- /dev/null
+++ b/db/schema_migrations/20220803145637
@@ -0,0 +1 @@
+bf12037cb99a399302610f948dad48589eca4e631d82d9f26b04bae882b10020 \ No newline at end of file
diff --git a/db/schema_migrations/20220803154543 b/db/schema_migrations/20220803154543
new file mode 100644
index 00000000000..f5cfb3d91ba
--- /dev/null
+++ b/db/schema_migrations/20220803154543
@@ -0,0 +1 @@
+047147acc972ab8681f097d5060998a47e44612fde7f2137714683bd61350c2d \ No newline at end of file
diff --git a/db/schema_migrations/20220803154758 b/db/schema_migrations/20220803154758
new file mode 100644
index 00000000000..71ac8b4f301
--- /dev/null
+++ b/db/schema_migrations/20220803154758
@@ -0,0 +1 @@
+2cdf4c4fe218a5fb7061bf65643868c7b592cd3ef0d7611949e8fd86bc635c24 \ No newline at end of file
diff --git a/db/schema_migrations/20220804235614 b/db/schema_migrations/20220804235614
new file mode 100644
index 00000000000..29d78297b22
--- /dev/null
+++ b/db/schema_migrations/20220804235614
@@ -0,0 +1 @@
+699f3b81d8694e30161ce3cc58c50f6e638e89c784df9e174ba87636d49a4fc9 \ No newline at end of file
diff --git a/db/schema_migrations/20220805001210 b/db/schema_migrations/20220805001210
new file mode 100644
index 00000000000..c13eddc30ea
--- /dev/null
+++ b/db/schema_migrations/20220805001210
@@ -0,0 +1 @@
+8863596a3b18497d6f995291953afa5a0ec9c0f7d76a98758add72c8859078b5 \ No newline at end of file
diff --git a/db/schema_migrations/20220805154101 b/db/schema_migrations/20220805154101
new file mode 100644
index 00000000000..2f443da6760
--- /dev/null
+++ b/db/schema_migrations/20220805154101
@@ -0,0 +1 @@
+6b6cb1cd97434e8d172257f9ef404ed31d07fb2b9a5e27a5bc0a9cf9a175b066 \ No newline at end of file
diff --git a/db/schema_migrations/20220808072054 b/db/schema_migrations/20220808072054
new file mode 100644
index 00000000000..93ef145ba92
--- /dev/null
+++ b/db/schema_migrations/20220808072054
@@ -0,0 +1 @@
+5e489655875408b2879f44f006b420a62554e6523ca687cfa64485e0123fc25c \ No newline at end of file
diff --git a/db/schema_migrations/20220808131659 b/db/schema_migrations/20220808131659
new file mode 100644
index 00000000000..65a08ad1b7a
--- /dev/null
+++ b/db/schema_migrations/20220808131659
@@ -0,0 +1 @@
+07488e8c6ea0f3dc92e1370efb0190facf520b850e170fcd8f3ce0e2a15c096a \ No newline at end of file
diff --git a/db/schema_migrations/20220808133824 b/db/schema_migrations/20220808133824
new file mode 100644
index 00000000000..bf7755d3163
--- /dev/null
+++ b/db/schema_migrations/20220808133824
@@ -0,0 +1 @@
+bab4f4d3aaedd698400fcbd5991797530450fe845a8034b03b1bf525a61e628a \ No newline at end of file
diff --git a/db/schema_migrations/20220808190124 b/db/schema_migrations/20220808190124
new file mode 100644
index 00000000000..99b7173cbb6
--- /dev/null
+++ b/db/schema_migrations/20220808190124
@@ -0,0 +1 @@
+ab8dfd7549b2b61a5cf9d5b46935ec534ea77ec2025fdb58d03f654d81c8f6ee \ No newline at end of file
diff --git a/db/schema_migrations/20220808194857 b/db/schema_migrations/20220808194857
new file mode 100644
index 00000000000..10a35a98cb2
--- /dev/null
+++ b/db/schema_migrations/20220808194857
@@ -0,0 +1 @@
+12e5d5c0cb73c8c2fdde4f640a57ab9c70d2e41382bd6eb2e2d36c1018f299ef \ No newline at end of file
diff --git a/db/schema_migrations/20220810093742 b/db/schema_migrations/20220810093742
new file mode 100644
index 00000000000..27b700c9031
--- /dev/null
+++ b/db/schema_migrations/20220810093742
@@ -0,0 +1 @@
+ebe256fcaccd70055b08e0f5cedfffc039bcacddbf5722135ee47cb02d3babb8 \ No newline at end of file
diff --git a/db/schema_migrations/20220811092243 b/db/schema_migrations/20220811092243
new file mode 100644
index 00000000000..6640e5f1a65
--- /dev/null
+++ b/db/schema_migrations/20220811092243
@@ -0,0 +1 @@
+211eda22a78d14aaaf86345d3e33b852ba22a7dc9e41d9d683d58f162a7bdcc7 \ No newline at end of file
diff --git a/db/schema_migrations/20220811092244 b/db/schema_migrations/20220811092244
new file mode 100644
index 00000000000..824d936a09c
--- /dev/null
+++ b/db/schema_migrations/20220811092244
@@ -0,0 +1 @@
+f871847fbd494e31f13cf2fb87a1b8e9fc47c44e7f0ec9cf37f2084d19b9bf5f \ No newline at end of file
diff --git a/db/schema_migrations/20220811092245 b/db/schema_migrations/20220811092245
new file mode 100644
index 00000000000..09bd431d928
--- /dev/null
+++ b/db/schema_migrations/20220811092245
@@ -0,0 +1 @@
+0c856ce8170e4b864578f1bcb89d8930d8c1952e92356965a98e057521456968 \ No newline at end of file
diff --git a/db/schema_migrations/20220811092246 b/db/schema_migrations/20220811092246
new file mode 100644
index 00000000000..64d3153b833
--- /dev/null
+++ b/db/schema_migrations/20220811092246
@@ -0,0 +1 @@
+17bcb2fddd6331cbcec505e8094d1a400b7c3fd8b18897697aa9868689147cd7 \ No newline at end of file
diff --git a/db/schema_migrations/20220811092251 b/db/schema_migrations/20220811092251
new file mode 100644
index 00000000000..61e2afaa74a
--- /dev/null
+++ b/db/schema_migrations/20220811092251
@@ -0,0 +1 @@
+4ea4bc7e6f88561553b19c7bf4992561772506cf532cf569241a536f69e19b7f \ No newline at end of file
diff --git a/db/schema_migrations/20220811092253 b/db/schema_migrations/20220811092253
new file mode 100644
index 00000000000..fc8ad6918e9
--- /dev/null
+++ b/db/schema_migrations/20220811092253
@@ -0,0 +1 @@
+6a6eed069e051786a925b40469e7b53a563f99f0c6bfb810058511d3de8b0923 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index cc1e6dfb288..b055d831ce6 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -22,6 +22,19 @@ RETURN NULL;
END
$$;
+CREATE FUNCTION gitlab_schema_prevent_write() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ IF COALESCE(NULLIF(current_setting(CONCAT('lock_writes.', TG_TABLE_NAME), true), ''), 'true') THEN
+ RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
+ USING ERRCODE = 'modifying_sql_data_not_permitted',
+ HINT = 'Make sure you are using the right database connection';
+ END IF;
+ RETURN NEW;
+END
+$$;
+
CREATE FUNCTION insert_into_loose_foreign_keys_deleted_records() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -54,6 +67,7 @@ DECLARE
report_type smallint;
resolved_on_default_branch boolean;
present_on_default_branch boolean;
+ namespace_id bigint;
BEGIN
IF (NEW.vulnerability_id IS NULL AND (TG_OP = 'INSERT' OR TG_OP = 'UPDATE')) THEN
RETURN NULL;
@@ -76,8 +90,17 @@ BEGIN
RETURN NULL;
END IF;
- INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
- VALUES (NEW.vulnerability_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id', CAST(NEW.location->'kubernetes_resource'->>'agent_id' AS bigint))
+ SELECT
+ projects.namespace_id
+ INTO
+ namespace_id
+ FROM
+ projects
+ WHERE
+ projects.id = NEW.project_id;
+
+ INSERT INTO vulnerability_reads (vulnerability_id, namespace_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.vulnerability_id, namespace_id, NEW.project_id, NEW.scanner_id, report_type, severity, state, resolved_on_default_branch, NEW.uuid::uuid, NEW.location->>'image', NEW.location->'kubernetes_resource'->>'agent_id', CAST(NEW.location->'kubernetes_resource'->>'agent_id' AS bigint))
ON CONFLICT(vulnerability_id) DO NOTHING;
RETURN NULL;
END
@@ -103,19 +126,21 @@ DECLARE
location_image text;
cluster_agent_id text;
casted_cluster_agent_id bigint;
+ namespace_id bigint;
BEGIN
SELECT
- v_o.scanner_id, v_o.uuid, v_o.location->>'image', v_o.location->'kubernetes_resource'->>'agent_id', CAST(v_o.location->'kubernetes_resource'->>'agent_id' AS bigint)
+ v_o.scanner_id, v_o.uuid, v_o.location->>'image', v_o.location->'kubernetes_resource'->>'agent_id', CAST(v_o.location->'kubernetes_resource'->>'agent_id' AS bigint), projects.namespace_id
INTO
- scanner_id, uuid, location_image, cluster_agent_id, casted_cluster_agent_id
+ scanner_id, uuid, location_image, cluster_agent_id, casted_cluster_agent_id, namespace_id
FROM
- vulnerability_occurrences v_o
+ vulnerability_occurrences v_o
+ INNER JOIN projects ON projects.id = v_o.project_id
WHERE
v_o.vulnerability_id = NEW.id
LIMIT 1;
- INSERT INTO vulnerability_reads (vulnerability_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
- VALUES (NEW.id, NEW.project_id, scanner_id, NEW.report_type, NEW.severity, NEW.state, NEW.resolved_on_default_branch, uuid::uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ INSERT INTO vulnerability_reads (vulnerability_id, namespace_id, project_id, scanner_id, report_type, severity, state, resolved_on_default_branch, uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
+ VALUES (NEW.id, namespace_id, NEW.project_id, scanner_id, NEW.report_type, NEW.severity, NEW.state, NEW.resolved_on_default_branch, uuid::uuid, location_image, cluster_agent_id, casted_cluster_agent_id)
ON CONFLICT(vulnerability_id) DO NOTHING;
RETURN NULL;
END
@@ -247,6 +272,74 @@ RETURN NULL;
END
$$;
+CREATE FUNCTION update_namespace_details_from_namespaces() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+INSERT INTO
+ namespace_details (
+ description,
+ description_html,
+ cached_markdown_version,
+ updated_at,
+ created_at,
+ namespace_id
+ )
+VALUES
+ (
+ NEW.description,
+ NEW.description_html,
+ NEW.cached_markdown_version,
+ NEW.updated_at,
+ NEW.updated_at,
+ NEW.id
+ ) ON CONFLICT (namespace_id) DO
+UPDATE
+SET
+ description = NEW.description,
+ description_html = NEW.description_html,
+ cached_markdown_version = NEW.cached_markdown_version,
+ updated_at = NEW.updated_at
+WHERE
+ namespace_details.namespace_id = NEW.id;RETURN NULL;
+
+END
+$$;
+
+CREATE FUNCTION update_namespace_details_from_projects() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+INSERT INTO
+ namespace_details (
+ description,
+ description_html,
+ cached_markdown_version,
+ updated_at,
+ created_at,
+ namespace_id
+ )
+VALUES
+ (
+ NEW.description,
+ NEW.description_html,
+ NEW.cached_markdown_version,
+ NEW.updated_at,
+ NEW.updated_at,
+ NEW.project_namespace_id
+ ) ON CONFLICT (namespace_id) DO
+UPDATE
+SET
+ description = NEW.description,
+ description_html = NEW.description_html,
+ cached_markdown_version = NEW.cached_markdown_version,
+ updated_at = NEW.updated_at
+WHERE
+ namespace_details.namespace_id = NEW.project_namespace_id;RETURN NULL;
+
+END
+$$;
+
CREATE FUNCTION update_vulnerability_reads_from_vulnerability() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -11174,7 +11267,6 @@ CREATE TABLE application_settings (
elasticsearch_pause_indexing boolean DEFAULT false NOT NULL,
repository_storages_weighted jsonb DEFAULT '{}'::jsonb NOT NULL,
max_import_size integer DEFAULT 0 NOT NULL,
- enforce_pat_expiration boolean DEFAULT true NOT NULL,
compliance_frameworks smallint[] DEFAULT '{}'::smallint[] NOT NULL,
notify_on_unknown_sign_in boolean DEFAULT true NOT NULL,
default_branch_name text,
@@ -11222,7 +11314,6 @@ CREATE TABLE application_settings (
rate_limiting_response_text text,
invisible_captcha_enabled boolean DEFAULT false NOT NULL,
container_registry_cleanup_tags_service_max_list_size integer DEFAULT 200 NOT NULL,
- enforce_ssh_key_expiration boolean DEFAULT true NOT NULL,
git_two_factor_session_expiry integer DEFAULT 15 NOT NULL,
keep_latest_artifact boolean DEFAULT true NOT NULL,
notes_create_limit integer DEFAULT 300 NOT NULL,
@@ -11366,6 +11457,7 @@ CREATE TABLE application_settings (
git_rate_limit_users_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
error_tracking_access_token_encrypted text,
package_registry_cleanup_policies_worker_capacity integer DEFAULT 2 NOT NULL,
+ deactivate_dormant_users_period integer DEFAULT 90 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)),
@@ -12332,14 +12424,15 @@ ALTER SEQUENCE bulk_imports_id_seq OWNED BY bulk_imports.id;
CREATE TABLE chat_names (
id integer NOT NULL,
user_id integer NOT NULL,
- service_id integer NOT NULL,
team_id character varying NOT NULL,
team_domain character varying,
chat_id character varying NOT NULL,
chat_name character varying,
last_used_at timestamp without time zone,
created_at timestamp without time zone NOT NULL,
- updated_at timestamp without time zone NOT NULL
+ updated_at timestamp without time zone NOT NULL,
+ integration_id integer,
+ CONSTRAINT check_2b0a0d0f0f CHECK ((integration_id IS NOT NULL))
);
CREATE SEQUENCE chat_names_id_seq
@@ -12471,7 +12564,6 @@ CREATE TABLE ci_builds (
"when" character varying,
yaml_variables text,
queued_at timestamp without time zone,
- token character varying,
lock_version integer DEFAULT 0,
coverage_regex character varying,
auto_canceled_by_id integer,
@@ -12512,7 +12604,8 @@ CREATE TABLE ci_builds_metadata (
secrets jsonb DEFAULT '{}'::jsonb NOT NULL,
build_id bigint NOT NULL,
id bigint NOT NULL,
- runtime_runner_features jsonb DEFAULT '{}'::jsonb NOT NULL
+ runtime_runner_features jsonb DEFAULT '{}'::jsonb NOT NULL,
+ id_tokens jsonb DEFAULT '{}'::jsonb NOT NULL
);
CREATE SEQUENCE ci_builds_metadata_id_seq
@@ -12766,7 +12859,6 @@ CREATE TABLE ci_namespace_monthly_usages (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
date date NOT NULL,
- additional_amount_available integer DEFAULT 0 NOT NULL,
amount_used numeric(18,2) DEFAULT 0.0 NOT NULL,
notification_level smallint DEFAULT 100 NOT NULL,
shared_runners_duration integer DEFAULT 0 NOT NULL,
@@ -13154,8 +13246,6 @@ CREATE TABLE ci_runners (
maintainer_note text,
token_expires_at timestamp with time zone,
allowed_plans text[] DEFAULT '{}'::text[] NOT NULL,
- semver text,
- CONSTRAINT check_a4f24953fd CHECK ((char_length(semver) <= 16)),
CONSTRAINT check_ce275cee06 CHECK ((char_length(maintainer_note) <= 1024))
);
@@ -16509,7 +16599,6 @@ ALTER SEQUENCE issue_metrics_id_seq OWNED BY issue_metrics.id;
CREATE TABLE issue_tracker_data (
id bigint NOT NULL,
- service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
encrypted_project_url character varying,
@@ -16517,7 +16606,9 @@ CREATE TABLE issue_tracker_data (
encrypted_issues_url character varying,
encrypted_issues_url_iv character varying,
encrypted_new_issue_url character varying,
- encrypted_new_issue_url_iv character varying
+ encrypted_new_issue_url_iv character varying,
+ integration_id integer,
+ CONSTRAINT check_7ca00cd891 CHECK ((integration_id IS NOT NULL))
);
CREATE SEQUENCE issue_tracker_data_id_seq
@@ -16585,6 +16676,7 @@ CREATE TABLE issues (
upvotes_count integer DEFAULT 0 NOT NULL,
work_item_type_id bigint,
namespace_id bigint,
+ start_date date,
CONSTRAINT check_fba63f706d CHECK ((lock_version IS NOT NULL))
);
@@ -16706,7 +16798,6 @@ ALTER SEQUENCE jira_imports_id_seq OWNED BY jira_imports.id;
CREATE TABLE jira_tracker_data (
id bigint NOT NULL,
- service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
encrypted_url character varying,
@@ -16724,7 +16815,9 @@ CREATE TABLE jira_tracker_data (
vulnerabilities_issuetype text,
vulnerabilities_enabled boolean DEFAULT false NOT NULL,
jira_issue_transition_automatic boolean DEFAULT false NOT NULL,
+ integration_id integer,
CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
+ CONSTRAINT check_0fbd71d9f2 CHECK ((integration_id IS NOT NULL)),
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
@@ -16989,6 +17082,24 @@ CREATE SEQUENCE loose_foreign_keys_deleted_records_id_seq
ALTER SEQUENCE loose_foreign_keys_deleted_records_id_seq OWNED BY loose_foreign_keys_deleted_records.id;
+CREATE TABLE member_roles (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ base_access_level integer NOT NULL,
+ download_code boolean DEFAULT false
+);
+
+CREATE SEQUENCE member_roles_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE member_roles_id_seq OWNED BY member_roles.id;
+
CREATE TABLE member_tasks (
id bigint NOT NULL,
member_id bigint NOT NULL,
@@ -17027,7 +17138,8 @@ CREATE TABLE members (
override boolean DEFAULT false NOT NULL,
state smallint DEFAULT 0,
invite_email_success boolean DEFAULT true NOT NULL,
- member_namespace_id bigint
+ member_namespace_id bigint,
+ member_role_id bigint
);
CREATE SEQUENCE members_id_seq
@@ -17484,6 +17596,85 @@ CREATE SEQUENCE milestones_id_seq
ALTER SEQUENCE milestones_id_seq OWNED BY milestones.id;
+CREATE TABLE ml_candidate_metrics (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ candidate_id bigint,
+ value double precision,
+ step integer,
+ is_nan bytea,
+ name text NOT NULL,
+ CONSTRAINT check_3bb4a3fbd9 CHECK ((char_length(name) <= 250))
+);
+
+CREATE SEQUENCE ml_candidate_metrics_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ml_candidate_metrics_id_seq OWNED BY ml_candidate_metrics.id;
+
+CREATE TABLE ml_candidate_params (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ candidate_id bigint,
+ name text NOT NULL,
+ value text NOT NULL,
+ CONSTRAINT check_093034d049 CHECK ((char_length(name) <= 250)),
+ CONSTRAINT check_28a3c29e43 CHECK ((char_length(value) <= 250))
+);
+
+CREATE SEQUENCE ml_candidate_params_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ml_candidate_params_id_seq OWNED BY ml_candidate_params.id;
+
+CREATE TABLE ml_candidates (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ iid uuid NOT NULL,
+ experiment_id bigint NOT NULL,
+ user_id bigint
+);
+
+CREATE SEQUENCE ml_candidates_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ml_candidates_id_seq OWNED BY ml_candidates.id;
+
+CREATE TABLE ml_experiments (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ iid bigint NOT NULL,
+ project_id bigint NOT NULL,
+ user_id bigint,
+ name text NOT NULL,
+ CONSTRAINT check_ee07a0be2c CHECK ((char_length(name) <= 255))
+);
+
+CREATE SEQUENCE ml_experiments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ml_experiments_id_seq OWNED BY ml_experiments.id;
+
CREATE TABLE namespace_admin_notes (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -17528,6 +17719,15 @@ CREATE TABLE namespace_ci_cd_settings (
allow_stale_runner_pruning boolean DEFAULT false NOT NULL
);
+CREATE TABLE namespace_details (
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone,
+ updated_at timestamp with time zone,
+ cached_markdown_version integer,
+ description text,
+ description_html text
+);
+
CREATE TABLE namespace_limits (
additional_purchased_storage_size bigint DEFAULT 0 NOT NULL,
additional_purchased_storage_ends_on date,
@@ -17586,7 +17786,9 @@ CREATE TABLE namespace_settings (
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,
- CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
+ unique_project_download_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
+ 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))
);
CREATE TABLE namespace_statistics (
@@ -18874,7 +19076,8 @@ CREATE TABLE plan_limits (
web_hook_calls_mid integer DEFAULT 0 NOT NULL,
web_hook_calls_low integer DEFAULT 0 NOT NULL,
project_ci_variables integer DEFAULT 200 NOT NULL,
- group_ci_variables integer DEFAULT 200 NOT NULL
+ group_ci_variables integer DEFAULT 200 NOT NULL,
+ ci_max_artifact_size_cyclonedx integer DEFAULT 1 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
@@ -19286,7 +19489,8 @@ CREATE TABLE project_ci_cd_settings (
job_token_scope_enabled boolean DEFAULT false NOT NULL,
runner_token_expiration_interval integer,
separated_caches boolean DEFAULT true NOT NULL,
- opt_in_jwt boolean DEFAULT false NOT NULL
+ opt_in_jwt boolean DEFAULT false NOT NULL,
+ allow_fork_pipelines_to_run_in_parent_project boolean DEFAULT true NOT NULL
);
CREATE SEQUENCE project_ci_cd_settings_id_seq
@@ -19693,6 +19897,7 @@ CREATE TABLE project_settings (
legacy_open_source_license_available boolean DEFAULT true NOT NULL,
target_platforms character varying[] DEFAULT '{}'::character varying[] NOT NULL,
enforce_auth_checks_on_uploads boolean DEFAULT true NOT NULL,
+ selective_code_owner_removals boolean DEFAULT false NOT NULL,
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)),
@@ -19715,7 +19920,9 @@ CREATE TABLE project_statistics (
snippets_size bigint,
pipeline_artifacts_size bigint DEFAULT 0 NOT NULL,
uploads_size bigint DEFAULT 0 NOT NULL,
- container_registry_size bigint DEFAULT 0 NOT NULL
+ container_registry_size bigint DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ updated_at timestamp with time zone DEFAULT now() NOT NULL
);
CREATE SEQUENCE project_statistics_id_seq
@@ -20577,11 +20784,12 @@ CREATE TABLE sbom_occurrences (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- component_version_id bigint NOT NULL,
+ component_version_id bigint,
project_id bigint NOT NULL,
pipeline_id bigint,
source_id bigint,
- commit_sha bytea NOT NULL
+ commit_sha bytea NOT NULL,
+ component_id bigint NOT NULL
);
CREATE SEQUENCE sbom_occurrences_id_seq
@@ -20882,7 +21090,6 @@ ALTER SEQUENCE shards_id_seq OWNED BY shards.id;
CREATE TABLE slack_integrations (
id integer NOT NULL,
- service_id integer NOT NULL,
team_id character varying NOT NULL,
team_name character varying NOT NULL,
alias character varying NOT NULL,
@@ -20892,7 +21099,9 @@ CREATE TABLE slack_integrations (
bot_user_id text,
encrypted_bot_access_token bytea,
encrypted_bot_access_token_iv bytea,
- CONSTRAINT check_bc553aea8a CHECK ((char_length(bot_user_id) <= 255))
+ integration_id integer,
+ CONSTRAINT check_bc553aea8a CHECK ((char_length(bot_user_id) <= 255)),
+ CONSTRAINT check_c9ca9ae80d CHECK ((integration_id IS NOT NULL))
);
CREATE SEQUENCE slack_integrations_id_seq
@@ -21103,7 +21312,7 @@ CREATE TABLE ssh_signatures (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id bigint NOT NULL,
- key_id bigint NOT NULL,
+ key_id bigint,
verification_status smallint DEFAULT 0 NOT NULL,
commit_sha bytea NOT NULL
);
@@ -21781,6 +21990,23 @@ CREATE SEQUENCE user_preferences_id_seq
ALTER SEQUENCE user_preferences_id_seq OWNED BY user_preferences.id;
+CREATE TABLE user_project_callouts (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ feature_name smallint NOT NULL,
+ dismissed_at timestamp with time zone
+);
+
+CREATE SEQUENCE user_project_callouts_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE user_project_callouts_id_seq OWNED BY user_project_callouts.id;
+
CREATE TABLE user_statuses (
user_id integer NOT NULL,
cached_markdown_version integer,
@@ -22331,7 +22557,6 @@ CREATE TABLE vulnerability_occurrences (
cve text,
location jsonb,
detection_method smallint DEFAULT 0 NOT NULL,
- migrated_to_new_structure boolean DEFAULT false NOT NULL,
CONSTRAINT check_4a3a60f2ba CHECK ((char_length(solution) <= 7000)),
CONSTRAINT check_ade261da6b CHECK ((char_length(description) <= 15000)),
CONSTRAINT check_df6dd20219 CHECK ((char_length(message) <= 3000)),
@@ -22361,6 +22586,7 @@ CREATE TABLE vulnerability_reads (
location_image text,
cluster_agent_id text,
casted_cluster_agent_id bigint,
+ namespace_id bigint,
CONSTRAINT check_380451bdbe CHECK ((char_length(location_image) <= 2048)),
CONSTRAINT check_a105eb825a CHECK ((char_length(cluster_agent_id) <= 10))
);
@@ -22423,7 +22649,10 @@ CREATE TABLE vulnerability_state_transitions (
to_state smallint NOT NULL,
from_state smallint NOT NULL,
created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL
+ updated_at timestamp with time zone NOT NULL,
+ author_id bigint,
+ comment text,
+ CONSTRAINT check_fca4a7ca39 CHECK ((char_length(comment) <= 255))
);
CREATE SEQUENCE vulnerability_state_transitions_id_seq
@@ -23278,6 +23507,8 @@ ALTER TABLE ONLY lists ALTER COLUMN id SET DEFAULT nextval('lists_id_seq'::regcl
ALTER TABLE ONLY loose_foreign_keys_deleted_records ALTER COLUMN id SET DEFAULT nextval('loose_foreign_keys_deleted_records_id_seq'::regclass);
+ALTER TABLE ONLY member_roles ALTER COLUMN id SET DEFAULT nextval('member_roles_id_seq'::regclass);
+
ALTER TABLE ONLY member_tasks ALTER COLUMN id SET DEFAULT nextval('member_tasks_id_seq'::regclass);
ALTER TABLE ONLY members ALTER COLUMN id SET DEFAULT nextval('members_id_seq'::regclass);
@@ -23316,6 +23547,14 @@ ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
+ALTER TABLE ONLY ml_candidate_metrics ALTER COLUMN id SET DEFAULT nextval('ml_candidate_metrics_id_seq'::regclass);
+
+ALTER TABLE ONLY ml_candidate_params ALTER COLUMN id SET DEFAULT nextval('ml_candidate_params_id_seq'::regclass);
+
+ALTER TABLE ONLY ml_candidates ALTER COLUMN id SET DEFAULT nextval('ml_candidates_id_seq'::regclass);
+
+ALTER TABLE ONLY ml_experiments ALTER COLUMN id SET DEFAULT nextval('ml_experiments_id_seq'::regclass);
+
ALTER TABLE ONLY namespace_admin_notes ALTER COLUMN id SET DEFAULT nextval('namespace_admin_notes_id_seq'::regclass);
ALTER TABLE ONLY namespace_bans ALTER COLUMN id SET DEFAULT nextval('namespace_bans_id_seq'::regclass);
@@ -23658,6 +23897,8 @@ ALTER TABLE ONLY user_permission_export_uploads ALTER COLUMN id SET DEFAULT next
ALTER TABLE ONLY user_preferences ALTER COLUMN id SET DEFAULT nextval('user_preferences_id_seq'::regclass);
+ALTER TABLE ONLY user_project_callouts ALTER COLUMN id SET DEFAULT nextval('user_project_callouts_id_seq'::regclass);
+
ALTER TABLE ONLY user_statuses ALTER COLUMN user_id SET DEFAULT nextval('user_statuses_user_id_seq'::regclass);
ALTER TABLE ONLY user_synced_attributes_metadata ALTER COLUMN id SET DEFAULT nextval('user_synced_attributes_metadata_id_seq'::regclass);
@@ -25253,6 +25494,9 @@ ALTER TABLE ONLY lists
ALTER TABLE ONLY loose_foreign_keys_deleted_records
ADD CONSTRAINT loose_foreign_keys_deleted_records_pkey PRIMARY KEY (partition, id);
+ALTER TABLE ONLY member_roles
+ ADD CONSTRAINT member_roles_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY member_tasks
ADD CONSTRAINT member_tasks_pkey PRIMARY KEY (id);
@@ -25322,6 +25566,18 @@ ALTER TABLE ONLY milestone_releases
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ml_candidate_metrics
+ ADD CONSTRAINT ml_candidate_metrics_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ml_candidate_params
+ ADD CONSTRAINT ml_candidate_params_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ml_candidates
+ ADD CONSTRAINT ml_candidates_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ml_experiments
+ ADD CONSTRAINT ml_experiments_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY namespace_admin_notes
ADD CONSTRAINT namespace_admin_notes_pkey PRIMARY KEY (id);
@@ -25334,6 +25590,9 @@ ALTER TABLE ONLY namespace_bans
ALTER TABLE ONLY namespace_ci_cd_settings
ADD CONSTRAINT namespace_ci_cd_settings_pkey PRIMARY KEY (namespace_id);
+ALTER TABLE ONLY namespace_details
+ ADD CONSTRAINT namespace_details_pkey PRIMARY KEY (namespace_id);
+
ALTER TABLE ONLY namespace_limits
ADD CONSTRAINT namespace_limits_pkey PRIMARY KEY (namespace_id);
@@ -25764,7 +26023,7 @@ ALTER TABLE ONLY scim_oauth_access_tokens
ADD CONSTRAINT scim_oauth_access_tokens_pkey PRIMARY KEY (id);
ALTER TABLE ONLY security_findings
- ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id);
+ ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id, partition_number);
ALTER TABLE ONLY security_orchestration_policy_configurations
ADD CONSTRAINT security_orchestration_policy_configurations_pkey PRIMARY KEY (id);
@@ -25940,6 +26199,9 @@ ALTER TABLE ONLY user_permission_export_uploads
ALTER TABLE ONLY user_preferences
ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY user_project_callouts
+ ADD CONSTRAINT user_project_callouts_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY user_statuses
ADD CONSTRAINT user_statuses_pkey PRIMARY KEY (user_id);
@@ -27210,7 +27472,7 @@ CREATE UNIQUE INDEX idx_vuln_signatures_on_occurrences_id_and_signature_sha ON v
CREATE UNIQUE INDEX idx_vuln_signatures_uniqueness_signature_sha ON vulnerability_finding_signatures USING btree (finding_id, algorithm_type, signature_sha);
-CREATE INDEX idx_vulnerabilities_partial_devops_adoption ON vulnerabilities USING btree (project_id, created_at) WHERE (state <> 1);
+CREATE INDEX idx_vulnerabilities_partial_devops_adoption_and_default_branch ON vulnerabilities USING btree (project_id, created_at, present_on_default_branch) WHERE (state <> 1);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
@@ -27498,9 +27760,9 @@ CREATE INDEX index_bulk_import_failures_on_correlation_id_value ON bulk_import_f
CREATE INDEX index_bulk_imports_on_user_id ON bulk_imports USING btree (user_id);
-CREATE UNIQUE INDEX index_chat_names_on_service_id_and_team_id_and_chat_id ON chat_names USING btree (service_id, team_id, chat_id);
+CREATE UNIQUE INDEX index_chat_names_on_integration_id_and_team_id_and_chat_id ON chat_names USING btree (integration_id, team_id, chat_id);
-CREATE UNIQUE INDEX index_chat_names_on_user_id_and_service_id ON chat_names USING btree (user_id, service_id);
+CREATE UNIQUE INDEX index_chat_names_on_user_id_and_integration_id ON chat_names USING btree (user_id, integration_id);
CREATE UNIQUE INDEX index_chat_teams_on_namespace_id ON chat_teams USING btree (namespace_id);
@@ -27538,8 +27800,6 @@ CREATE INDEX index_ci_builds_on_project_id_and_id ON ci_builds USING btree (proj
CREATE INDEX index_ci_builds_on_project_id_and_name_and_ref ON ci_builds USING btree (project_id, name, ref) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = 'success'::text) AND ((retried = false) OR (retried IS NULL)));
-CREATE INDEX index_ci_builds_on_queued_at ON ci_builds USING btree (queued_at);
-
CREATE INDEX index_ci_builds_on_resource_group_and_status_and_commit_id ON ci_builds USING btree (resource_group_id, status, commit_id) WHERE (resource_group_id IS NOT NULL);
CREATE INDEX index_ci_builds_on_runner_id_and_id_desc ON ci_builds USING btree (runner_id, id DESC);
@@ -27560,8 +27820,6 @@ CREATE INDEX index_ci_builds_on_user_id_and_created_at_and_type_eq_ci_build ON c
CREATE INDEX index_ci_builds_project_id_and_status_for_live_jobs_partial2 ON ci_builds USING btree (project_id, status) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])));
-CREATE INDEX index_ci_builds_runner_id_pending_covering ON ci_builds USING btree (runner_id, id) INCLUDE (project_id) WHERE (((status)::text = 'pending'::text) AND ((type)::text = 'Ci::Build'::text));
-
CREATE INDEX index_ci_builds_runner_id_running ON ci_builds USING btree (runner_id) WHERE (((status)::text = 'running'::text) AND ((type)::text = 'Ci::Build'::text));
CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON ci_builds_runner_session USING btree (build_id);
@@ -27748,8 +28006,6 @@ CREATE INDEX index_ci_runners_on_created_at_desc_and_id_desc ON ci_runners USING
CREATE INDEX index_ci_runners_on_description_trigram ON ci_runners USING gin (description gin_trgm_ops);
-CREATE INDEX index_ci_runners_on_id_and_semver_cidr ON ci_runners USING btree (id, ((semver)::cidr));
-
CREATE INDEX index_ci_runners_on_locked ON ci_runners USING btree (locked);
CREATE INDEX index_ci_runners_on_runner_type ON ci_runners USING btree (runner_type);
@@ -28494,6 +28750,8 @@ CREATE INDEX index_integrations_on_type_new ON integrations USING btree (type_ne
CREATE INDEX index_integrations_on_type_new_and_instance_partial ON integrations USING btree (type_new, instance) WHERE (instance = true);
+CREATE INDEX index_integrations_on_type_new_id_when_active_and_has_group ON integrations USING btree (type_new, id, inherit_from_id) WHERE ((active = true) AND (group_id IS NOT NULL));
+
CREATE INDEX index_integrations_on_type_new_id_when_active_and_has_project ON integrations USING btree (type_new, id) WHERE ((active = true) AND (project_id IS NOT NULL));
CREATE INDEX index_integrations_on_unique_group_id_and_type_new ON integrations USING btree (group_id, type_new);
@@ -28540,7 +28798,7 @@ CREATE INDEX index_issue_metrics_on_issue_id_and_timestamps ON issue_metrics USI
CREATE INDEX index_issue_on_project_id_state_id_and_blocking_issues_count ON issues USING btree (project_id, state_id, blocking_issues_count);
-CREATE INDEX index_issue_tracker_data_on_service_id ON issue_tracker_data USING btree (service_id);
+CREATE INDEX index_issue_tracker_data_on_integration_id ON issue_tracker_data USING btree (integration_id);
CREATE UNIQUE INDEX index_issue_user_mentions_on_note_id ON issue_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
@@ -28554,6 +28812,8 @@ CREATE INDEX index_issues_on_confidential ON issues USING btree (confidential);
CREATE INDEX index_issues_on_description_trigram ON issues USING gin (description gin_trgm_ops);
+CREATE INDEX index_issues_on_description_trigram_non_latin ON issues USING gin (description gin_trgm_ops) WHERE (((title)::text !~ similar_escape('[\u0000-\u218F]*'::text, NULL::text)) OR (description !~ similar_escape('[\u0000-\u218F]*'::text, NULL::text)));
+
CREATE INDEX index_issues_on_duplicated_to_id ON issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL);
CREATE INDEX index_issues_on_id_and_weight ON issues USING btree (id, weight);
@@ -28588,6 +28848,8 @@ CREATE INDEX index_issues_on_sprint_id ON issues USING btree (sprint_id);
CREATE INDEX index_issues_on_title_trigram ON issues USING gin (title gin_trgm_ops);
+CREATE INDEX index_issues_on_title_trigram_non_latin ON issues USING gin (title gin_trgm_ops) WHERE (((title)::text !~ similar_escape('[\u0000-\u218F]*'::text, NULL::text)) OR (description !~ similar_escape('[\u0000-\u218F]*'::text, NULL::text)));
+
CREATE INDEX index_issues_on_updated_at ON issues USING btree (updated_at);
CREATE INDEX index_issues_on_updated_by_id ON issues USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
@@ -28604,7 +28866,7 @@ CREATE INDEX index_jira_imports_on_project_id_and_jira_project_key ON jira_impor
CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id);
-CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
+CREATE INDEX index_jira_tracker_data_on_integration_id ON jira_tracker_data USING btree (integration_id);
CREATE INDEX index_job_artifact_states_failed_verification ON ci_job_artifact_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
@@ -28696,6 +28958,8 @@ CREATE INDEX index_lists_on_user_id ON lists USING btree (user_id);
CREATE INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ON ONLY loose_foreign_keys_deleted_records USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
+CREATE INDEX index_member_roles_on_namespace_id ON member_roles USING btree (namespace_id);
+
CREATE INDEX index_member_tasks_on_member_id ON member_tasks USING btree (member_id);
CREATE UNIQUE INDEX index_member_tasks_on_member_id_and_project_id ON member_tasks USING btree (member_id, project_id);
@@ -28712,6 +28976,8 @@ CREATE UNIQUE INDEX index_members_on_invite_token ON members USING btree (invite
CREATE INDEX index_members_on_member_namespace_id ON members USING btree (member_namespace_id);
+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);
@@ -28870,6 +29136,20 @@ CREATE INDEX index_milestones_on_title_trigram ON milestones USING gin (title gi
CREATE INDEX index_mirror_data_non_scheduled_or_started ON project_mirror_data USING btree (next_execution_timestamp, retry_count) WHERE ((status)::text <> ALL ('{scheduled,started}'::text[]));
+CREATE INDEX index_ml_candidate_metrics_on_candidate_id ON ml_candidate_metrics USING btree (candidate_id);
+
+CREATE INDEX index_ml_candidate_params_on_candidate_id ON ml_candidate_params USING btree (candidate_id);
+
+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);
+
+CREATE UNIQUE INDEX index_ml_experiments_on_project_id_and_iid ON ml_experiments USING btree (project_id, iid);
+
+CREATE UNIQUE INDEX index_ml_experiments_on_project_id_and_name ON ml_experiments USING btree (project_id, name);
+
+CREATE INDEX index_ml_experiments_on_user_id ON ml_experiments USING btree (user_id);
+
CREATE UNIQUE INDEX index_mr_blocks_on_blocking_and_blocked_mr_ids ON merge_request_blocks USING btree (blocking_merge_request_id, blocked_merge_request_id);
CREATE INDEX index_mr_cleanup_schedules_timestamps_status ON merge_request_cleanup_schedules USING btree (scheduled_at) WHERE ((completed_at IS NULL) AND (status = 0));
@@ -29212,6 +29492,8 @@ CREATE INDEX index_path_locks_on_user_id ON path_locks USING btree (user_id);
CREATE INDEX index_pe_approval_rules_on_required_approvals_and_created_at ON protected_environment_approval_rules USING btree (required_approvals, created_at);
+CREATE INDEX index_personal_access_tokens_on_id_and_created_at ON personal_access_tokens USING btree (id, created_at);
+
CREATE UNIQUE INDEX index_personal_access_tokens_on_token_digest ON personal_access_tokens USING btree (token_digest);
CREATE INDEX index_personal_access_tokens_on_user_id ON personal_access_tokens USING btree (user_id);
@@ -29318,6 +29600,8 @@ CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON project_rep
CREATE INDEX index_project_repository_storage_moves_on_project_id ON project_repository_storage_moves USING btree (project_id);
+CREATE INDEX index_project_settings_on_legacy_open_source_license_available ON project_settings USING btree (legacy_open_source_license_available) WHERE (legacy_open_source_license_available = true);
+
CREATE INDEX index_project_settings_on_project_id_partially ON project_settings USING btree (project_id) WHERE (has_vulnerabilities IS TRUE);
CREATE UNIQUE INDEX index_project_settings_on_push_rule_id ON project_settings USING btree (push_rule_id);
@@ -29342,6 +29626,8 @@ CREATE UNIQUE INDEX index_project_topics_on_project_id_and_topic_id ON project_t
CREATE INDEX index_project_topics_on_topic_id ON project_topics USING btree (topic_id);
+CREATE UNIQUE INDEX index_project_user_callouts_feature ON user_project_callouts USING btree (user_id, feature_name, project_id);
+
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);
@@ -29630,6 +29916,8 @@ 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 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 INDEX index_sbom_occurrences_on_pipeline_id ON sbom_occurrences USING btree (pipeline_id);
@@ -29662,7 +29950,7 @@ CREATE INDEX index_security_findings_on_scanner_id ON security_findings USING bt
CREATE INDEX index_security_findings_on_severity ON security_findings USING btree (severity);
-CREATE UNIQUE INDEX index_security_findings_on_uuid_and_scan_id ON security_findings USING btree (uuid, scan_id);
+CREATE UNIQUE INDEX index_security_findings_on_unique_columns ON security_findings USING btree (uuid, scan_id, partition_number);
CREATE INDEX index_security_scans_on_created_at ON security_scans USING btree (created_at);
@@ -29706,7 +29994,7 @@ CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
CREATE UNIQUE INDEX index_site_profile_secret_variables_on_site_profile_id_and_key ON dast_site_profile_secret_variables USING btree (dast_site_profile_id, key);
-CREATE INDEX index_slack_integrations_on_service_id ON slack_integrations USING btree (service_id);
+CREATE INDEX index_slack_integrations_on_integration_id ON slack_integrations USING btree (integration_id);
CREATE UNIQUE INDEX index_slack_integrations_on_team_id_and_alias ON slack_integrations USING btree (team_id, alias);
@@ -29978,6 +30266,8 @@ CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
+CREATE INDEX index_user_project_callouts_on_project_id ON user_project_callouts USING btree (project_id);
+
CREATE INDEX index_user_statuses_on_clear_status_at_not_null ON user_statuses USING btree (clear_status_at) WHERE (clear_status_at IS NOT NULL);
CREATE INDEX index_user_statuses_on_user_id ON user_statuses USING btree (user_id);
@@ -30054,9 +30344,11 @@ CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON v
CREATE INDEX index_vuln_reads_on_casted_cluster_agent_id_where_it_is_null ON vulnerability_reads USING btree (casted_cluster_agent_id) WHERE (casted_cluster_agent_id IS NOT NULL);
+CREATE INDEX index_vuln_reads_on_namespace_id_state_severity_and_vuln_id ON vulnerability_reads USING btree (namespace_id, state, severity, vulnerability_id DESC);
+
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_vulnerabilites_common_finder_query ON vulnerabilities USING btree (project_id, state, report_type, severity, id);
+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);
@@ -30072,8 +30364,6 @@ CREATE INDEX index_vulnerabilities_on_last_edited_by_id ON vulnerabilities USING
CREATE INDEX index_vulnerabilities_on_milestone_id ON vulnerabilities USING btree (milestone_id);
-CREATE INDEX index_vulnerabilities_on_project_id_and_id ON vulnerabilities USING btree (project_id, id);
-
CREATE INDEX index_vulnerabilities_on_project_id_and_id_active_cis ON vulnerabilities USING btree (project_id, id) WHERE ((report_type = 7) AND (state = ANY (ARRAY[1, 4])));
CREATE INDEX index_vulnerabilities_on_project_id_and_state_and_severity ON vulnerabilities USING btree (project_id, state, severity);
@@ -30088,6 +30378,10 @@ CREATE INDEX index_vulnerabilities_on_state_case_id_desc ON vulnerabilities USIN
CREATE INDEX index_vulnerabilities_on_updated_by_id ON vulnerabilities USING btree (updated_by_id);
+CREATE INDEX index_vulnerabilities_project_id_and_id_on_default_branch ON vulnerabilities USING btree (project_id, id) WHERE (present_on_default_branch IS TRUE);
+
+CREATE INDEX index_vulnerabilities_project_id_state_severity_default_branch ON vulnerabilities USING btree (project_id, state, severity, present_on_default_branch);
+
CREATE INDEX index_vulnerability_exports_on_author_id ON vulnerability_exports USING btree (author_id);
CREATE INDEX index_vulnerability_exports_on_file_store ON vulnerability_exports USING btree (file_store);
@@ -30150,8 +30444,6 @@ CREATE INDEX index_vulnerability_occurrences_on_location_k8s_agent_id ON vulnera
CREATE INDEX index_vulnerability_occurrences_on_location_k8s_cluster_id ON vulnerability_occurrences USING gin ((((location -> 'kubernetes_resource'::text) -> 'cluster_id'::text))) WHERE (report_type = 7);
-CREATE INDEX index_vulnerability_occurrences_on_migrated_to_new_structure ON vulnerability_occurrences USING btree (migrated_to_new_structure, id);
-
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerability_occurrences USING btree (project_fingerprint);
@@ -30164,6 +30456,8 @@ CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerabilit
CREATE INDEX index_vulnerability_reads_common_finder_query ON vulnerability_reads USING btree (project_id, state, report_type, severity, vulnerability_id DESC);
+CREATE INDEX index_vulnerability_reads_common_finder_query_with_namespace_id ON vulnerability_reads USING btree (namespace_id, state, report_type, severity, vulnerability_id DESC);
+
CREATE INDEX index_vulnerability_reads_on_cluster_agent_id ON vulnerability_reads USING btree (cluster_agent_id) WHERE (report_type = 7);
CREATE INDEX index_vulnerability_reads_on_location_image ON vulnerability_reads USING btree (location_image) WHERE (report_type = ANY (ARRAY[2, 7]));
@@ -30182,6 +30476,8 @@ CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id O
CREATE INDEX index_vulnerability_state_transitions_id_and_vulnerability_id ON vulnerability_state_transitions USING btree (vulnerability_id, id);
+CREATE INDEX index_vulnerability_state_transitions_on_author_id ON vulnerability_state_transitions USING btree (author_id);
+
CREATE INDEX index_vulnerability_statistics_on_latest_pipeline_id ON vulnerability_statistics USING btree (latest_pipeline_id);
CREATE INDEX index_vulnerability_statistics_on_letter_grade ON vulnerability_statistics USING btree (letter_grade);
@@ -30308,12 +30604,12 @@ CREATE INDEX tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown ON ci_
CREATE INDEX tmp_index_ci_job_artifacts_on_id_where_trace_and_expire_at ON ci_job_artifacts USING btree (id) WHERE ((file_type = 3) AND (expire_at = ANY (ARRAY['2021-04-22 00:00:00+00'::timestamp with time zone, '2021-05-22 00:00:00+00'::timestamp with time zone, '2021-06-22 00:00:00+00'::timestamp with time zone, '2022-01-22 00:00:00+00'::timestamp with time zone, '2022-02-22 00:00:00+00'::timestamp with time zone, '2022-03-22 00:00:00+00'::timestamp with time zone, '2022-04-22 00:00:00+00'::timestamp with time zone])));
+CREATE INDEX tmp_index_cis_vulnerability_reads_on_id ON vulnerability_reads USING btree (id) WHERE (report_type = 7);
+
CREATE INDEX tmp_index_container_repositories_on_id_migration_state ON container_repositories USING btree (id, migration_state);
CREATE INDEX tmp_index_for_namespace_id_migration_on_group_members ON members USING btree (id) WHERE ((member_namespace_id IS NULL) AND ((type)::text = 'GroupMember'::text));
-CREATE INDEX tmp_index_for_namespace_id_migration_on_project_members ON members USING btree (id) WHERE ((member_namespace_id IS NULL) AND ((type)::text = 'ProjectMember'::text));
-
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_project_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Project'::text));
@@ -30332,6 +30628,10 @@ 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_todos_attention_request_action ON todos USING btree (id) WHERE (action = 10);
+
+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);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name);
@@ -31690,6 +31990,14 @@ CREATE TRIGGER trigger_projects_parent_id_on_insert AFTER INSERT ON projects FOR
CREATE TRIGGER trigger_projects_parent_id_on_update AFTER UPDATE ON projects FOR EACH ROW WHEN ((old.namespace_id IS DISTINCT FROM new.namespace_id)) EXECUTE FUNCTION insert_projects_sync_event();
+CREATE TRIGGER trigger_update_details_on_namespace_insert AFTER INSERT ON namespaces FOR EACH ROW WHEN (((new.type)::text <> 'Project'::text)) EXECUTE FUNCTION update_namespace_details_from_namespaces();
+
+CREATE TRIGGER trigger_update_details_on_namespace_update AFTER UPDATE ON namespaces FOR EACH ROW WHEN ((((new.type)::text <> 'Project'::text) AND (((old.description)::text IS DISTINCT FROM (new.description)::text) OR (old.description_html IS DISTINCT FROM new.description_html) OR (old.cached_markdown_version IS DISTINCT FROM new.cached_markdown_version)))) EXECUTE FUNCTION update_namespace_details_from_namespaces();
+
+CREATE TRIGGER trigger_update_details_on_project_insert AFTER INSERT ON projects FOR EACH ROW EXECUTE FUNCTION update_namespace_details_from_projects();
+
+CREATE TRIGGER trigger_update_details_on_project_update AFTER UPDATE ON projects FOR EACH ROW WHEN (((old.description IS DISTINCT FROM new.description) OR (old.description_html IS DISTINCT FROM new.description_html) OR (old.cached_markdown_version IS DISTINCT FROM new.cached_markdown_version))) EXECUTE FUNCTION update_namespace_details_from_projects();
+
CREATE TRIGGER trigger_update_has_issues_on_vulnerability_issue_links_delete AFTER DELETE ON vulnerability_issue_links FOR EACH ROW EXECUTE FUNCTION unset_has_issues_on_vulnerability_reads();
CREATE TRIGGER trigger_update_has_issues_on_vulnerability_issue_links_update AFTER INSERT ON vulnerability_issue_links FOR EACH ROW EXECUTE FUNCTION set_has_issues_on_vulnerability_reads();
@@ -31700,9 +32008,6 @@ CREATE TRIGGER trigger_update_vulnerability_reads_on_vulnerability_update AFTER
CREATE TRIGGER users_loose_fk_trigger AFTER DELETE ON users REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
-ALTER TABLE ONLY chat_names
- ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY deployments
ADD CONSTRAINT fk_009fd21147 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE NOT VALID;
@@ -31880,6 +32185,12 @@ ALTER TABLE ONLY approvals
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_319256d87a FOREIGN KEY (file_template_project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY issue_tracker_data
+ ADD CONSTRAINT fk_33921c0ee1 FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY user_project_callouts
+ ADD CONSTRAINT fk_33b4814f6b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
@@ -31956,6 +32267,9 @@ ALTER TABLE ONLY sbom_occurrences
ADD CONSTRAINT fk_4b88e5b255 FOREIGN KEY (component_version_id) REFERENCES sbom_component_versions(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_reads
+ ADD CONSTRAINT fk_4f593f6c62 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY vulnerability_reads
ADD CONSTRAINT fk_5001652292 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY alert_management_alerts
@@ -31979,6 +32293,9 @@ ALTER TABLE ONLY merge_request_metrics
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT fk_563ff1912e FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ml_candidates
+ ADD CONSTRAINT fk_56d6ed4d3d FOREIGN KEY (experiment_id) REFERENCES ml_experiments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY deploy_keys_projects
ADD CONSTRAINT fk_58a901ca7e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -31988,6 +32305,9 @@ ALTER TABLE ONLY dast_scanner_profiles_builds
ALTER TABLE ONLY issue_assignees
ADD CONSTRAINT fk_5e0c8d9154 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY members
+ ADD CONSTRAINT fk_5e12d50db3 FOREIGN KEY (member_role_id) REFERENCES member_roles(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY csv_issue_imports
ADD CONSTRAINT fk_5e1572387c FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -32195,6 +32515,9 @@ ALTER TABLE ONLY vulnerability_occurrences
ALTER TABLE ONLY protected_branch_merge_access_levels
ADD CONSTRAINT fk_98f3d044fe FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY chat_names
+ ADD CONSTRAINT fk_99a1348daf FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY notes
ADD CONSTRAINT fk_99e097b079 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -32270,6 +32593,9 @@ ALTER TABLE ONLY member_tasks
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_ad525e1f87 FOREIGN KEY (merge_user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ml_experiments
+ ADD CONSTRAINT fk_ad89c59858 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT fk_ae440388cc FOREIGN KEY (latest_closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -32387,12 +32713,18 @@ ALTER TABLE ONLY agent_activity_events
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_c900194ff2 FOREIGN KEY (source_id) REFERENCES issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_tracker_data
+ ADD CONSTRAINT fk_c98abcd54c FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY external_approval_rules_protected_branches
ADD CONSTRAINT fk_c9a037a926 FOREIGN KEY (external_approval_rule_id) REFERENCES external_approval_rules(id) ON DELETE CASCADE;
ALTER TABLE ONLY external_approval_rules_protected_branches
ADD CONSTRAINT fk_ca2ffb55e6 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY slack_integrations
+ ADD CONSTRAINT fk_cbe270434e FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY external_status_checks_protected_branches
ADD CONSTRAINT fk_cc0dcc36d1 FOREIGN KEY (external_status_check_id) REFERENCES external_status_checks(id) ON DELETE CASCADE;
@@ -32450,6 +32782,9 @@ ALTER TABLE ONLY ci_pipelines
ALTER TABLE ONLY system_note_metadata
ADD CONSTRAINT fk_d83a918cb1 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY sbom_occurrences
+ ADD CONSTRAINT fk_d857c6edc1 FOREIGN KEY (component_id) REFERENCES sbom_components(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_d94154aa95 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -32489,6 +32824,9 @@ ALTER TABLE ONLY gitlab_subscriptions
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_state_transitions
+ ADD CONSTRAINT fk_e719dc63df FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_e71bb44f1f FOREIGN KEY (target_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -32561,6 +32899,9 @@ ALTER TABLE ONLY analytics_devops_adoption_segments
ALTER TABLE ONLY boards_epic_list_user_preferences
ADD CONSTRAINT fk_f5f2fe5c1f FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_project_callouts
+ ADD CONSTRAINT fk_f62dd11a33 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY cluster_agents
ADD CONSTRAINT fk_f7d43dee13 FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -32765,6 +33106,9 @@ ALTER TABLE ONLY vulnerability_user_mentions
ALTER TABLE ONLY packages_debian_file_metadata
ADD CONSTRAINT fk_rails_1ae85be112 FOREIGN KEY (package_file_id) REFERENCES packages_package_files(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ml_candidates
+ ADD CONSTRAINT fk_rails_1b37441fe5 FOREIGN KEY (user_id) REFERENCES users(id);
+
ALTER TABLE ONLY issuable_slas
ADD CONSTRAINT fk_rails_1b8768cd63 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -32792,6 +33136,9 @@ ALTER TABLE ONLY geo_repository_created_events
ALTER TABLE ONLY external_status_checks
ADD CONSTRAINT fk_rails_1f5a8aa809 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ml_experiments
+ ADD CONSTRAINT fk_rails_1fbc5e001f FOREIGN KEY (user_id) REFERENCES users(id);
+
ALTER TABLE ONLY dora_daily_metrics
ADD CONSTRAINT fk_rails_1fd07aff6f FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
@@ -33326,9 +33673,6 @@ ALTER TABLE ONLY dast_scanner_profiles
ALTER TABLE ONLY vulnerability_historical_statistics
ADD CONSTRAINT fk_rails_72b73ed023 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY slack_integrations
- ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY custom_emoji
ADD CONSTRAINT fk_rails_745925b412 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -33617,9 +33961,6 @@ ALTER TABLE ONLY vulnerability_user_mentions
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_rails_a27c483435 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY jira_tracker_data
- ADD CONSTRAINT fk_rails_a299066916 FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY protected_environments
ADD CONSTRAINT fk_rails_a354313d11 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -33875,21 +34216,24 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY vulnerability_finding_links
ADD CONSTRAINT fk_rails_cbdfde27ce FOREIGN KEY (vulnerability_occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_details
+ ADD CONSTRAINT fk_rails_cc11a451f8 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
ADD CONSTRAINT fk_rails_cc5d88bbb0 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY operations_strategies_user_lists
ADD CONSTRAINT fk_rails_ccb7e4bc0b FOREIGN KEY (user_list_id) REFERENCES operations_user_lists(id) ON DELETE CASCADE;
-ALTER TABLE ONLY issue_tracker_data
- ADD CONSTRAINT fk_rails_ccc0840427 FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY resource_milestone_events
ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY resource_iteration_events
ADD CONSTRAINT fk_rails_cee126f66c FOREIGN KEY (iteration_id) REFERENCES sprints(id) ON DELETE CASCADE;
+ALTER TABLE ONLY member_roles
+ ADD CONSTRAINT fk_rails_cf0ee35814 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY upload_states
ADD CONSTRAINT fk_rails_d00f153613 FOREIGN KEY (upload_id) REFERENCES uploads(id) ON DELETE CASCADE;
@@ -33926,6 +34270,9 @@ ALTER TABLE ONLY alert_management_alert_assignees
ALTER TABLE ONLY geo_hashed_storage_attachments_events
ADD CONSTRAINT fk_rails_d496b088e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ml_candidate_params
+ ADD CONSTRAINT fk_rails_d4a51d1185 FOREIGN KEY (candidate_id) REFERENCES ml_candidates(id);
+
ALTER TABLE ONLY merge_request_reviewers
ADD CONSTRAINT fk_rails_d9fec24b9d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
@@ -34073,6 +34420,9 @@ ALTER TABLE ONLY project_relation_exports
ALTER TABLE ONLY label_priorities
ADD CONSTRAINT fk_rails_ef916d14fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ml_candidate_metrics
+ ADD CONSTRAINT fk_rails_efb613a25a FOREIGN KEY (candidate_id) REFERENCES ml_candidates(id);
+
ALTER TABLE ONLY fork_network_members
ADD CONSTRAINT fk_rails_efccadc4ec FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml
index f6b0a988499..78a86e27456 100644
--- a/doc/.vale/gitlab/Admin.yml
+++ b/doc/.vale/gitlab/Admin.yml
@@ -1,5 +1,5 @@
---
-# Warning: gitlab.Admin
+# Suggestion: gitlab.Admin
#
# Checks for "admin" and recommends using the full word instead. "Admin Area" is OK.
#
diff --git a/doc/.vale/gitlab/BadPlurals.yml b/doc/.vale/gitlab/BadPlurals.yml
index 63f002fec94..533805c67b0 100644
--- a/doc/.vale/gitlab/BadPlurals.yml
+++ b/doc/.vale/gitlab/BadPlurals.yml
@@ -1,5 +1,5 @@
---
-# Suggestion: gitlab.BadPlurals
+# Warning: gitlab.BadPlurals
#
# Don't write plural words with the '(s)' construction. "HTTP(S)" is acceptable.
#
diff --git a/doc/.vale/gitlab/EOLWhitespace.yml b/doc/.vale/gitlab/EOLWhitespace.yml
index 483db0cafe6..e160b706014 100644
--- a/doc/.vale/gitlab/EOLWhitespace.yml
+++ b/doc/.vale/gitlab/EOLWhitespace.yml
@@ -1,5 +1,5 @@
---
-# Error: gitlab.EOLWhitespace
+# Warning: gitlab.EOLWhitespace
#
# Checks that there is no useless whitespace at the end of lines.
#
diff --git a/doc/.vale/gitlab/FutureTense.yml b/doc/.vale/gitlab/FutureTense.yml
index fc414a9c0fd..64e79612fff 100644
--- a/doc/.vale/gitlab/FutureTense.yml
+++ b/doc/.vale/gitlab/FutureTense.yml
@@ -1,5 +1,5 @@
---
-# Suggestion: gitlab.FutureTense
+# Warning: gitlab.FutureTense
#
# Checks for use of future tense in sentences. Present tense is strongly preferred.
#
diff --git a/doc/.vale/gitlab/HeadingContent.yml b/doc/.vale/gitlab/HeadingContent.yml
index a8dc596f2a2..c2dd2a5c6c2 100644
--- a/doc/.vale/gitlab/HeadingContent.yml
+++ b/doc/.vale/gitlab/HeadingContent.yml
@@ -1,5 +1,5 @@
---
-# Error: gitlab.HeadingContent
+# Warning: gitlab.HeadingContent
#
# Checks for generic, unhelpful subheadings.
#
diff --git a/doc/.vale/gitlab/HeadingDepth.yml b/doc/.vale/gitlab/HeadingDepth.yml
new file mode 100644
index 00000000000..466ab317226
--- /dev/null
+++ b/doc/.vale/gitlab/HeadingDepth.yml
@@ -0,0 +1,13 @@
+---
+# Warning: gitlab.HeadingDepth
+#
+# Checks that there are no headings greater than 3 levels
+#
+# For a list of all options, see https://vale.sh/docs/topics/styles/
+extends: existence
+message: 'The subheading "%s" is nested too deeply. Headings deeper than H5 suggest the section or page should be refactored.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#headings-in-markdown
+level: warning
+scope: raw
+raw:
+ - '(?<=\n)#{5,}\s.*'
diff --git a/doc/.vale/gitlab/MultiLineLinks.yml b/doc/.vale/gitlab/MultiLineLinks.yml
new file mode 100644
index 00000000000..64ad017f16c
--- /dev/null
+++ b/doc/.vale/gitlab/MultiLineLinks.yml
@@ -0,0 +1,14 @@
+---
+# Error: gitlab.MultiLineLinks
+#
+# Checks that links are all on a single line.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'Link "%s" must be on a single line, even if very long.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#basic-link-criteria
+level: error
+scope: raw
+raw:
+ - '\[[^\[\]]*?\n[^\[\]]*?\]\([^\)]*?\)|'
+ - '\[[^\[\]]*?\]\([^\)]*?\n[^\)]*\)'
diff --git a/doc/.vale/gitlab/OutdatedVersions.yml b/doc/.vale/gitlab/OutdatedVersions.yml
index c78c045a1fd..f25de44ad17 100644
--- a/doc/.vale/gitlab/OutdatedVersions.yml
+++ b/doc/.vale/gitlab/OutdatedVersions.yml
@@ -1,5 +1,5 @@
---
-# Warning: gitlab.OutdatedVersions
+# Suggestion: gitlab.OutdatedVersions
#
# Checks for references to versions of GitLab that are no longer supported.
#
diff --git a/doc/.vale/gitlab/Possessive.yml b/doc/.vale/gitlab/Possessive.yml
index 158c689cac1..92ae66543a2 100644
--- a/doc/.vale/gitlab/Possessive.yml
+++ b/doc/.vale/gitlab/Possessive.yml
@@ -1,5 +1,5 @@
---
-# Warning: gitlab.Possessive
+# Error: gitlab.Possessive
#
# The word GitLab should not be used in the possessive form.
#
diff --git a/doc/.vale/gitlab/Uppercase.yml b/doc/.vale/gitlab/Uppercase.yml
index a8519d898db..dc05aa05730 100644
--- a/doc/.vale/gitlab/Uppercase.yml
+++ b/doc/.vale/gitlab/Uppercase.yml
@@ -56,6 +56,7 @@ exceptions:
- DML
- DNS
- DOM
+ - DORA
- DSA
- DSL
- DVCS
diff --git a/doc/.vale/gitlab/VersionText.yml b/doc/.vale/gitlab/VersionText.yml
index 68753de60aa..571fba52ab7 100644
--- a/doc/.vale/gitlab/VersionText.yml
+++ b/doc/.vale/gitlab/VersionText.yml
@@ -1,23 +1,19 @@
---
# Error: gitlab.VersionText
#
-# Checks that version text is formatted correctly.
+# Checks that multi-line version text is formatted correctly.
#
-# Specifically looks for either of the following that is immediately followed on the next line
-# by content, which will break rendering:
+# Specifically, looks for multi-line version text that doesn't use `-` to make it a list.
+# For example:
#
-# - `> Introduced` (version text without a link)
-# - `> [Introduced` (version text with a link)
-#
-# Because it excludes the prefix `> - `, it doesn't look for multi-line version text, for which
-# content immediately on the next line is ok. However, this will often highlight where multi-line
-# version text is attempted without `-` characters.
+# - `> Introduced in GitLab 14.0.
+# - `> Removed in GitLab 15.0.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
-message: 'This introduced-in line is not formatted correctly.'
+message: 'This introduced-in section is not formatted correctly. Each entry must start with `> -` and long entries must be on one line.'
link: https://docs.gitlab.com/ee/development/documentation/versions.html
level: error
scope: raw
raw:
- - '> \[?Introduced.+\n[^\n]'
+ - '\n#.*\n\n> [^-].+\n[^\n`]'
diff --git a/doc/.vale/gitlab/VersionTextSingleLine.yml b/doc/.vale/gitlab/VersionTextSingleLine.yml
new file mode 100644
index 00000000000..f76574bcf8a
--- /dev/null
+++ b/doc/.vale/gitlab/VersionTextSingleLine.yml
@@ -0,0 +1,13 @@
+---
+# Error: gitlab.VersionTextSingleLine
+#
+# Verifies that single-item version notes don't have a hyphen.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'Version text with only a single item must not start with a hyphen.'
+link: https://docs.gitlab.com/ee/development/documentation/versions.html#add-a-version-history-item
+level: error
+scope: raw
+raw:
+ - '(\r|\n|\r\n){2}(> - .*)(\r|\n|\r\n){2}'
diff --git a/doc/administration/application_settings_cache.md b/doc/administration/application_settings_cache.md
index 6c58e6886c4..30fd9ab85a8 100644
--- a/doc/administration/application_settings_cache.md
+++ b/doc/administration/application_settings_cache.md
@@ -1,6 +1,6 @@
---
stage: Data Stores
-group: Memory
+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
---
diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md
index 817f22debbc..3bb0ce41861 100644
--- a/doc/administration/audit_event_streaming.md
+++ b/doc/administration/audit_event_streaming.md
@@ -6,44 +6,53 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Audit event streaming **(ULTIMATE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
-> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
-> - [Feature flag `ff_external_audit_events_namespace`](https://gitlab.com/gitlab-org/gitlab/-/issues/349588) removed in GitLab 14.8.
+> - API [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
+> - API [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
+> - API [Feature flag `ff_external_audit_events_namespace`](https://gitlab.com/gitlab-org/gitlab/-/issues/349588) removed in GitLab 14.8.
+> - UI [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336411) in GitLab 14.9.
> - [Subgroup events recording](https://gitlab.com/gitlab-org/gitlab/-/issues/366878) fixed in GitLab 15.2.
-
-Users can set an HTTP endpoint for a top-level group to receive all audit events about the group, its subgroups, and
+> - Custom HTTP headers API [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361216) in GitLab 15.1 [with a flag](feature_flags.md) named `streaming_audit_event_headers`. Disabled by default.
+> - Custom HTTP headers API [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/362941) in GitLab 15.2.
+> - Custom HTTP headers API [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/366524) in GitLab 15.3. [Feature flag `streaming_audit_event_headers`](https://gitlab.com/gitlab-org/gitlab/-/issues/362941) removed.
+> - Custom HTTP headers UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361630) in GitLab 15.2 [with a flag](feature_flags.md) named `custom_headers_streaming_audit_events_ui`. Disabled by default.
+> - Custom HTTP headers UI [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/365259) in GitLab 15.3. [Feature flag `custom_headers_streaming_audit_events_ui`](https://gitlab.com/gitlab-org/gitlab/-/issues/365259) removed.
+> - [Improved user experience](https://gitlab.com/gitlab-org/gitlab/-/issues/367963) in GitLab 15.4.
+
+Users can set a streaming destination for a top-level group to receive all audit events about the group, its subgroups, and
projects as structured JSON.
Top-level group owners can manage their audit logs in third-party systems. Any service that can receive
-structured JSON data can be used as the endpoint.
+structured JSON data can be used as the streaming destination.
+
+Each streaming destination can have up to 20 custom HTTP headers included with each streamed event.
NOTE:
GitLab can stream a single event more than once to the same destination. Use the `id` key in the payload to deduplicate incoming data.
-## Add a new event streaming destination
+## Add a new streaming destination
WARNING:
-Event streaming destinations receive **all** audit event data, which could include sensitive information. Make sure you trust the destination endpoint.
+Streaming destinations receive **all** audit event data, which could include sensitive information. Make sure you trust the streaming destination.
### Use the GitLab UI
-Users with at least the Owner role for a group can add event streaming destinations for it:
+Users with the Owner role for a group can add streaming destinations for it:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Audit events**.
1. On the main area, select **Streams** tab.
- - When the destination list is empty, select **Add stream** to show the section for adding destinations.
- - When the destination list is not empty, select **{plus}** to show the section for adding destinations.
-1. Enter the destination URL to add and select **Add**.
-
-Event streaming is enabled if:
-
-- No warning is shown.
-- The added endpoint is displayed in the UI.
+1. Select **Add streaming destination** to show the section for adding destinations.
+1. Enter the destination URL to add.
+1. Optional. Locate the **Custom HTTP headers** table.
+1. Ignore the **Active** checkbox because it isn't functional. To track progress on adding functionality to the **Active** checkbox, see the
+ [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925).
+1. Select **Add header** to create a new name and value pair. Enter as many name and value pairs as required. You can add up to
+ 20 headers per streaming destination.
+1. After all headers have been filled out, select **Add** to add the new streaming destination.
### Use the API
-To enable event streaming and add a destination, users with at least the Owner role for a group must use the
+To enable streaming and add a destination, users with the Owner role for a group must use the
`externalAuditEventDestinationCreate` mutation in the GraphQL API.
```graphql
@@ -51,6 +60,7 @@ mutation {
externalAuditEventDestinationCreate(input: { destinationUrl: "https://mydomain.io/endpoint/ingest", groupPath: "my-group" } ) {
errors
externalAuditEventDestination {
+ id
destinationUrl
verificationToken
group {
@@ -66,23 +76,35 @@ Event streaming is enabled if:
- The returned `errors` object is empty.
- The API responds with `200 OK`.
+Group owners can add an HTTP header using the GraphQL `auditEventsStreamingHeadersCreate` mutation. You can retrieve the destination ID
+by [listing all the streaming destinations](#use-the-api-1) for the group or from the mutation above.
+
+```graphql
+mutation {
+ auditEventsStreamingHeadersCreate(input: { destinationId: "gid://gitlab/AuditEvents::ExternalAuditEventDestination/24601", key: "foo", value: "bar" }) {
+ errors
+ }
+}
+```
+
+The header is created if the returned `errors` object is empty.
+
## List streaming destinations
-Users with at least the Owner role for a group can list event streaming destinations.
+Users with the Owner role for a group can list streaming destinations.
### Use the GitLab UI
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336411) in GitLab 14.9.
-
-Users with at least the Owner role for a group can list event streaming destinations:
+To list the streaming destinations:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Audit events**.
1. On the main area, select **Streams** tab.
+1. To the right of the item, select **Edit** (**{pencil}**) to see all the custom HTTP headers.
### Use the API
-Users with at least the Owner role for a group can view a list of event streaming destinations at any time using the
+Users with the Owner role for a group can view a list of streaming destinations at any time using the
`externalAuditEventDestinations` query type.
```graphql
@@ -94,42 +116,48 @@ query {
destinationUrl
verificationToken
id
+ headers {
+ nodes {
+ key
+ value
+ id
+ }
+ }
}
}
}
}
```
-If the resulting list is empty, then audit event streaming is not enabled for that group.
+If the resulting list is empty, then audit streaming is not enabled for that group.
-## Delete streaming destinations
+You need the ID values returned by this query for the update and delete mutations.
-Users with at least the Owner role for a group can delete event streaming destinations using the
-`deleteAuditEventDestinations` mutation type.
+## Update streaming destinations
-When the last destination is successfully deleted, event streaming is disabled for the group.
+Users with the Owner role for a group can update streaming destinations.
### Use the GitLab UI
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336411) in GitLab 14.9.
-
-Users with at least the Owner role for a group can delete event streaming destinations.
+To update a streaming destinations custom HTTP headers:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Audit events**.
1. On the main area, select **Streams** tab.
-1. Select **{remove}** at the right side of each item.
-
-The external streaming destination is deleted when:
-
-- No warning is shown.
-- The deleted endpoint is not displayed in the UI.
+1. To the right of the item, select **Edit** (**{pencil}**).
+1. Locate the **Custom HTTP headers** table.
+1. Locate the header that you wish to update.
+1. Ignore the **Active** checkbox because it isn't functional. To track progress on adding functionality to the **Active** checkbox, see the
+ [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925).
+1. Select **Add header** to create a new name and value pair. Enter as many name and value pairs as required. You can add up to
+ 20 headers per streaming destination.
+1. Select **Save** to update the streaming destination.
### Use the API
-Delete an event streaming destination by specifying an ID. Get the required ID by
-[listing the details](audit_event_streaming.md#use-the-api-1) of event
-streaming destinations.
+Users with the Owner role for a group can update streaming destinations custom HTTP headers using the
+`auditEventsStreamingHeadersUpdate` mutation type. You can retrieve the custom HTTP headers ID
+by [listing all the custom HTTP headers](#use-the-api-1) for the group.
```graphql
mutation {
@@ -139,89 +167,71 @@ mutation {
}
```
-Destination is deleted if:
+Streaming destination is updated if:
- The returned `errors` object is empty.
- The API responds with `200 OK`.
-## Custom HTTP headers
-
-> - API [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361216) in GitLab 15.1 [with a flag](feature_flags.md) named `streaming_audit_event_headers`. Disabled by default.
-> - API [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/362941) in GitLab 15.2.
-> - UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361630) in GitLab 15.2 [with a flag](feature_flags.md) named `custom_headers_streaming_audit_events_ui`. Disabled by default.
-
-FLAG:
-On self-managed GitLab, by default the API for this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../administration/feature_flags.md) named `streaming_audit_event_headers`.
-On GitLab.com, the API for this feature is available.
-
-Each streaming destination can have up to 20 custom HTTP headers included with each streamed event.
-
-### Adding custom HTTP headers
-
-Add custom HTTP headers with the API or GitLab UI.
-
-#### Use the API
-
-Group owners can add a HTTP header using the GraphQL `auditEventsStreamingHeadersCreate` mutation. You can retrieve the destination ID
-by [listing the external audit destinations](#list-streaming-destinations) on the group.
+Group owners can remove an HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
+by [listing all the custom HTTP headers](#use-the-api-1) for the group.
```graphql
mutation {
- auditEventsStreamingHeadersCreate(input: { destinationId: "gid://gitlab/AuditEvents::ExternalAuditEventDestination/24601", key: "foo", value: "bar" }) {
+ auditEventsStreamingHeadersDestroy(input: { headerId: "gid://gitlab/AuditEvents::Streaming::Header/1" }) {
errors
}
}
```
-The header is created if the returned `errors` object is empty.
+The header is deleted if the returned `errors` object is empty.
-#### Use the GitLab UI
+## Delete streaming destinations
-FLAG:
-On self-managed GitLab, by default the UI for this feature is not available. To make it available per group, ask an administrator to
-[enable the feature flag](../administration/feature_flags.md) named `custom_headers_streaming_audit_events_ui`. On GitLab.com, the UI for this feature is
-not available. The UI for this feature is not ready for production use.
+Users with the Owner role for a group can delete streaming destinations.
-Users with at least the Owner role for a group can add event streaming destinations and custom HTTP headers for it:
+When the last destination is successfully deleted, streaming is disabled for the group.
+
+### Use the GitLab UI
+
+To delete a streaming destination:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Audit events**.
-1. On the main area, select **Streams** tab.
- - When the destination list is empty, select **Add stream** to show the section for adding destinations.
- - When the destination list is not empty, select **{plus}** to show the section for adding destinations.
-1. Enter the destination URL to add.
-1. Locate the **Custom HTTP headers** table.
-1. In the **Header** column, add the header's name.
-1. In the **Value** column, add the header's value.
-1. Ignore the **Active** checkbox because it isn't functional. To track progress on adding functionality to the **Active** checkbox, see the
- [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925).
-1. Enter as many name and value pairs as required. When you enter a unique name and a value for a header, a new row in the table automatically appears. You can add up to
- 20 headers per endpoint.
-1. After all headers have been filled out, select **Add** to add the new endpoint.
-
-Event streaming is enabled if:
+1. On the main area, select the **Streams** tab.
+1. To the right of the item, select **Delete** (**{remove}**).
-- No warning is shown.
-- The added endpoint is displayed in the UI.
+To delete only the custom HTTP headers for a streaming destination:
-### Updating custom HTTP headers
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Security & Compliance > Audit events**.
+1. On the main area, select the **Streams** tab.
+1. To the right of the item, **Edit** (**{pencil}**).
+1. Locate the **Custom HTTP headers** table.
+1. Locate the header that you wish to remove.
+1. To the right of the header, select **Delete** (**{remove}**).
+1. Select **Save** to update the streaming destination.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/361964) in GitLab 15.2.
+### Use the API
-Group owners can update a HTTP header using the GraphQL `auditEventsStreamingHeadersCreate` mutation.
+Users with the Owner role for a group can delete streaming destinations using the
+`externalAuditEventDestinationDestroy` mutation type. You can retrieve the destinations ID
+by [listing all the streaming destinations](#use-the-api-1) for the group.
```graphql
mutation {
- auditEventsStreamingHeadersUpdate(input: { headerId: "gid://gitlab/AuditEvents::Streaming::Header/24255", key: "new-foo", value: "new-bar" }) {
+ externalAuditEventDestinationDestroy(input: { id: destination }) {
errors
}
}
```
-### Deleting custom HTTP headers
+Streaming destination is deleted if:
-Group owners can remove a HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
-by [listing all the custom headers](#list-all-custom-headers) on the group.
+- The returned `errors` object is empty.
+- The API responds with `200 OK`.
+
+Group owners can remove an HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
+by [listing all the custom HTTP headers](#use-the-api-1) for the group.
```graphql
mutation {
@@ -233,52 +243,6 @@ mutation {
The header is deleted if the returned `errors` object is empty.
-### List all custom headers
-
-List all custom HTTP headers with the API or GitLab UI.
-
-#### Use the API
-
-You can list all custom headers for a top-level group as well as their value and ID using the GraphQL `externalAuditEventDestinations` query. The ID
-value returned by this query is what you need to pass to the `deletion` mutation.
-
-```graphql
-query {
- group(fullPath: "your-group") {
- id
- externalAuditEventDestinations {
- nodes {
- destinationUrl
- id
- headers {
- nodes {
- key
- value
- id
- }
- }
- }
- }
- }
-}
-```
-
-#### Use the GitLab UI
-
-FLAG:
-On self-managed GitLab, by default the UI for this feature is not available. To make it available per group, ask an administrator to
-[enable the feature flag](../administration/feature_flags.md) named `custom_headers_streaming_audit_events_ui`. On GitLab.com, the UI for this feature is
-not available. The UI for this feature is not ready for production use.
-
-Users with at least the Owner role for a group can add event streaming destinations and custom HTTP headers for it:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Security & Compliance > Audit events**.
-1. On the main area, select **Streams** tab.
-1. Select **{pencil}** at the right side of an item.
-1. A read-only view of the items custom headers is shown. To track progress on adding editing functionality, see the [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/361925).
-1. Select **Cancel** to close the read-only view.
-
## Verify event authenticity
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345424) in GitLab 14.8.
@@ -293,18 +257,41 @@ the destination's value when [listing streaming destinations](#list-streaming-de
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/360814) in GitLab 15.2.
-Users with at least the Owner role for a group can list event streaming destinations and see the verification tokens:
+Users with the Owner role for a group can list streaming destinations and see the verification tokens:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Audit events**.
-1. On the main area, select **Streams**.
+1. On the main area, select the **Streams**.
1. View the verification token on the right side of each item.
+## Payload schema
+
+> Documentation for an audit event streaming schema was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358149) in GitLab 15.3.
+
+Streamed audit events have a predictable schema in the body of the response.
+
+| Field | Description | Notes |
+|------------------|------------------------------------------------------------|-----------------------------------------------------------------------------------|
+| `author_id` | User ID of the user who triggered the event | |
+| `author_name` | Human-readable name of the author that triggered the event | Helpful when the author no longer exists |
+| `created_at` | Timestamp when event was triggered | |
+| `details` | JSON object containing additional metadata | Has no defined schema but often contains additional information about an event |
+| `entity_id` | ID of the audit event's entity | |
+| `entity_path` | Full path of the entity affected by the auditable event | |
+| `entity_type` | String representation of the type of entity | Acceptable values include `User`, `Group`, and `Key`. This list is not exhaustive |
+| `event_type` | String representation of the type of audit event | |
+| `id` | Unique identifier for the audit event | Can be used for deduplication if required |
+| `ip_address` | IP address of the host used to trigger the event | |
+| `target_details` | Additional details about the target | |
+| `target_id` | ID of the audit event's target | |
+| `target_type` | String representation of the target's type | |
+
## Audit event streaming on Git operations
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.9 [with a flag](../administration/feature_flags.md) named `audit_event_streaming_git_operations`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/357211) in GitLab 15.0.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/357211) in GitLab 15.1 by default.
+> - [Added `details.author_class` field](https://gitlab.com/gitlab-org/gitlab/-/issues/363876) in GitLab 15.3.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the
@@ -318,7 +305,7 @@ Streaming audit events can be sent when signed-in users push or pull a project's
Audit events are not captured for users that are not signed in. For example, when downloading a public project.
-To configure streaming audit events for Git operations, see [Add a new event streaming destination](#add-a-new-event-streaming-destination).
+To configure streaming audit events for Git operations, see [Add a new streaming destination](#add-a-new-streaming-destination).
### Headers
@@ -346,6 +333,7 @@ Fetch:
"entity_type": "Project",
"details": {
"author_name": "Administrator",
+ "author_class": "User",
"target_id": 29,
"target_type": "Project",
"target_details": "example-project",
@@ -377,6 +365,7 @@ Push:
"entity_type": "Project",
"details": {
"author_name": "Administrator",
+ "author_class": "User",
"target_id": 29,
"target_type": "Project",
"target_details": "example-project",
@@ -398,6 +387,42 @@ Push:
}
```
+### Example payloads for SSH events with Deploy Key
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363876) in GitLab 15.3.
+
+Fetch:
+
+```json
+{
+ "id": 1,
+ "author_id": -3,
+ "entity_id": 29,
+ "entity_type": "Project",
+ "details": {
+ "author_name": "deploy-key-name",
+ "author_class": "DeployKey",
+ "target_id": 29,
+ "target_type": "Project",
+ "target_details": "example-project",
+ "custom_message": {
+ "protocol": "ssh",
+ "action": "git-upload-pack"
+ },
+ "ip_address": "127.0.0.1",
+ "entity_path": "example-group/example-project"
+ },
+ "ip_address": "127.0.0.1",
+ "author_name": "deploy-key-name",
+ "entity_path": "example-group/example-project",
+ "target_details": "example-project",
+ "created_at": "2022-07-26T05:43:53.662Z",
+ "target_type": "Project",
+ "target_id": 29,
+ "event_type": "repository_git_operation"
+}
+```
+
### Example payloads for HTTP and HTTPS events
Fetch:
@@ -410,6 +435,7 @@ Fetch:
"entity_type": "Project",
"details": {
"author_name": "Administrator",
+ "author_class": "User",
"target_id": 29,
"target_type": "Project",
"target_details": "example-project",
@@ -441,6 +467,7 @@ Push:
"entity_type": "Project",
"details": {
"author_name": "Administrator",
+ "author_class": "User",
"target_id": 29,
"target_type": "Project",
"target_details": "example-project",
@@ -462,6 +489,40 @@ Push:
}
```
+### Example payloads for HTTP and HTTPS events with Deploy Token
+
+Fetch:
+
+```json
+{
+ "id": 1,
+ "author_id": -2,
+ "entity_id": 22,
+ "entity_type": "Project",
+ "details": {
+ "author_name": "deploy-token-name",
+ "author_class": "DeployToken",
+ "target_id": 22,
+ "target_type": "Project",
+ "target_details": "example-project",
+ "custom_message": {
+ "protocol": "http",
+ "action": "git-upload-pack"
+ },
+ "ip_address": "127.0.0.1",
+ "entity_path": "example-group/example-project"
+ },
+ "ip_address": "127.0.0.1",
+ "author_name": "deploy-token-name",
+ "entity_path": "example-group/example-project",
+ "target_details": "example-project",
+ "created_at": "2022-07-26T05:46:25.850Z",
+ "target_type": "Project",
+ "target_id": 22,
+ "event_type": "repository_git_operation"
+}
+```
+
### Example payloads for events from GitLab UI download button
Fetch:
@@ -475,6 +536,7 @@ Fetch:
"details": {
"custom_message": "Repository Download Started",
"author_name": "example_username",
+ "author_class": "User",
"target_id": 29,
"target_type": "Project",
"target_details": "example-group/example-project",
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index a329adbed22..92504c226fb 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab offers a way to view the changes made within the GitLab server for owners and administrators
on a [paid plan](https://about.gitlab.com/pricing/).
-GitLab system administrators can also view all audit events by accessing the [`audit_json.log` file](logs.md#audit_jsonlog).
+GitLab system administrators can also view all audit events by accessing the [`audit_json.log` file](logs/index.md#audit_jsonlog).
The JSON audit log does not include events that are [only streamed](../development/audit_event_guide/index.md#event-streaming).
You can:
@@ -115,7 +115,7 @@ From there, you can see the following actions:
- Instance administrator started or stopped impersonation of a group member. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300961) in GitLab 14.8.
- Group deploy token was successfully created, revoked, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
- Failed attempt to create a group deploy token. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
-- [IP restrictions](../user/group/index.md#group-access-restriction-by-ip-address) changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
+- [IP restrictions](../user/group/access_and_permissions.md#restrict-group-access-by-ip-address) changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
- Changes to push rules. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227629) in GitLab 15.0.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356152) in GitLab 15.1, changes to the following merge request approvals settings:
- Prevent approval by author.
@@ -123,6 +123,7 @@ From there, you can see the following actions:
- Prevent editing approval rules in projects and merge requests.
- Require user password to approve.
- Remove all approvals when commits are added to the source branch.
+- Changes to streaming audit destination custom HTTP headers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) in GitLab 15.3.
Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
@@ -151,6 +152,7 @@ From there, you can see the following actions:
- Added, removed, or updated protected branches
- Release was added to a project
- Release was updated
+- Release was deleted ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94793/) in GitLab 13.5)
- Release milestone associations changed
- Permission to approve merge requests by committers was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Permission to approve merge requests by committers was updated.
@@ -271,7 +273,7 @@ Don't see the event you want in any of the epics linked above? You can either:
- Use the **Audit Event Proposal** issue template to
[create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Audit%20Event%20Proposal) to
request it.
-- [Add it yourself](../development/audit_event_guide/).
+- [Add it yourself](../development/audit_event_guide/index.md).
### Removed events
diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md
index 6fa592b96db..e33b5153c5b 100644
--- a/doc/administration/audit_reports.md
+++ b/doc/administration/audit_reports.md
@@ -26,4 +26,4 @@ needs.
## Features
- [Audit events](audit_events.md)
-- [Log system](logs.md)
+- [Log system](logs/index.md)
diff --git a/doc/administration/auditor_users.md b/doc/administration/auditor_users.md
index d82683e1778..561aa5d7b2e 100644
--- a/doc/administration/auditor_users.md
+++ b/doc/administration/auditor_users.md
@@ -55,3 +55,9 @@ If you are signed in with auditor access, you:
you can push commits or comment on issues.
- Can access the same resources using the GitLab UI or API.
- Can't view the Admin Area, or perform any administration actions.
+
+## Maintain auditor users using API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3.
+
+Administrators can use the GitLab API to [create](../api/users.md#user-creation) and [modify](../api/users.md#user-modification) auditor users.
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 8dfa832a103..ced7cdb7119 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -5,7 +5,11 @@ 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
---
-# Atlassian Crowd OmniAuth Provider **(FREE SELF)**
+# Atlassian Crowd OmniAuth provider (deprecated) **(FREE SELF)**
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/369117) in GitLab 15.3 and is planned for
+removal in 16.0.
Authenticate to GitLab using the Atlassian Crowd OmniAuth provider. Enabling
this provider also allows Crowd authentication for Git-over-https requests.
@@ -68,24 +72,24 @@ this provider also allows Crowd authentication for Git-over-https requests.
application_password: 'YOUR_APP_PASSWORD' } }
```
-1. Change `CROWD_SERVER_URL` to the URL of your Crowd server.
+1. Change `CROWD_SERVER_URL` to the [base URL of your Crowd server](https://confluence.atlassian.com/crowdkb/how-to-change-the-crowd-base-url-245827278.html).
1. Change `YOUR_APP_NAME` to the application name from Crowd applications page.
1. Change `YOUR_APP_PASSWORD` to the application password you've set.
1. Save the configuration file.
-1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../restart_gitlab.md#installations-from-source) for the changes to take effect if you
- installed GitLab via Omnibus or from source respectively.
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) (Omnibus GitLab) or [restart](../restart_gitlab.md#installations-from-source) (source installations) for
+ the changes to take effect.
On the sign in page there should now be a Crowd tab in the sign in form.
## Troubleshooting
-If you see an error message like the one below when you sign in after Crowd authentication is configured, you may want to consult the Crowd administrator for the Crowd log file to know the exact cause:
+### Error: "could not authorize you from Crowd because invalid credentials"
-```plaintext
-could not authorize you from Crowd because invalid credentials
-```
+This error sometimes occurs when a user attempts to authenticate with Crowd. The
+Crowd administrator should consult the Crowd log file to know the exact cause of
+this error message.
-Ensure the Crowd users who need to sign in to GitLab are authorized to the
+Ensure the Crowd users who must sign in to GitLab are authorized to the
[application](#configure-a-new-crowd-application) in the **Authorization** step.
This could be verified by trying "Authentication test" for Crowd (as of 2.11).
diff --git a/doc/administration/auth/ldap/img/multi_login.png b/doc/administration/auth/ldap/img/multi_login.png
deleted file mode 100644
index 512f403a442..00000000000
--- a/doc/administration/auth/ldap/img/multi_login.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 05eee338e64..2f0a0db9d6f 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -75,7 +75,7 @@ To configure LDAP integration, add your LDAP server settings in:
- `/home/git/gitlab/config/gitlab.yml` for source install instances.
After configuring LDAP, to test the configuration, use the
-[LDAP check Rake task](../../raketasks/check.md#ldap-check).
+[LDAP check Rake task](../../raketasks/ldap.md#check).
NOTE:
The `encryption` value `simple_tls` corresponds to 'Simple TLS' in the LDAP
@@ -95,42 +95,42 @@ This example shows configuration for Omnibus GitLab instances:
gitlab_rails['ldap_enabled'] = true
gitlab_rails['prevent_ldap_sign_in'] = false
gitlab_rails['ldap_servers'] = {
-'main' => {
- 'label' => 'LDAP',
- 'host' => 'ldap.mydomain.com',
- 'port' => 389,
- 'uid' => 'sAMAccountName',
- 'encryption' => 'simple_tls',
- 'verify_certificates' => true,
- 'bind_dn' => '_the_full_dn_of_the_user_you_will_bind_with',
- 'password' => '_the_password_of_the_bind_user',
- 'tls_options' => {
- 'ca_file' => '',
- 'ssl_version' => '',
- 'ciphers' => '',
- 'cert' => '',
- 'key' => ''
- },
- 'timeout' => 10,
- 'active_directory' => true,
- 'allow_username_or_email_login' => false,
- 'block_auto_created_users' => false,
- 'base' => 'dc=example,dc=com',
- 'user_filter' => '',
- 'attributes' => {
- 'username' => ['uid', 'userid', 'sAMAccountName'],
- 'email' => ['mail', 'email', 'userPrincipalName'],
- 'name' => 'cn',
- 'first_name' => 'givenName',
- 'last_name' => 'sn'
- },
- 'lowercase_usernames' => false,
-
- # EE Only
- 'group_base' => '',
- 'admin_group' => '',
- 'external_groups' => [],
- 'sync_ssh_keys' => false
+ 'main' => {
+ 'label' => 'LDAP',
+ 'host' => 'ldap.mydomain.com',
+ 'port' => 389,
+ 'uid' => 'sAMAccountName',
+ 'encryption' => 'simple_tls',
+ 'verify_certificates' => true,
+ 'bind_dn' => '_the_full_dn_of_the_user_you_will_bind_with',
+ 'password' => '_the_password_of_the_bind_user',
+ 'tls_options' => {
+ 'ca_file' => '',
+ 'ssl_version' => '',
+ 'ciphers' => '',
+ 'cert' => '',
+ 'key' => ''
+ },
+ 'timeout' => 10,
+ 'active_directory' => true,
+ 'allow_username_or_email_login' => false,
+ 'block_auto_created_users' => false,
+ 'base' => 'dc=example,dc=com',
+ 'user_filter' => '',
+ 'attributes' => {
+ 'username' => ['uid', 'userid', 'sAMAccountName'],
+ 'email' => ['mail', 'email', 'userPrincipalName'],
+ 'name' => 'cn',
+ 'first_name' => 'givenName',
+ 'last_name' => 'sn'
+ },
+ 'lowercase_usernames' => false,
+
+ # EE Only
+ 'group_base' => '',
+ 'admin_group' => '',
+ 'external_groups' => [],
+ 'sync_ssh_keys' => false
}
}
```
@@ -248,33 +248,34 @@ The following example shows how to configure three LDAP servers in `gitlab.rb`:
```ruby
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = {
-'main' => {
- 'label' => 'GitLab AD',
- 'host' => 'ad.example.org',
- 'port' => 636,
- ...
+ 'main' => {
+ 'label' => 'GitLab AD',
+ 'host' => 'ad.example.org',
+ 'port' => 636,
+ ...
},
-'secondary' => {
- 'label' => 'GitLab Secondary AD',
- 'host' => 'ad-secondary.example.net',
- 'port' => 636,
- ...
+ 'secondary' => {
+ 'label' => 'GitLab Secondary AD',
+ 'host' => 'ad-secondary.example.net',
+ 'port' => 636,
+ ...
},
-'tertiary' => {
- 'label' => 'GitLab Tertiary AD',
- 'host' => 'ad-tertiary.example.net',
- 'port' => 636,
- ...
+ 'tertiary' => {
+ 'label' => 'GitLab Tertiary AD',
+ 'host' => 'ad-tertiary.example.net',
+ 'port' => 636,
+ ...
}
-
}
```
-This example results in the following sign-in page:
+This example results in a sign-in page with the following tabs:
-![Multiple LDAP servers sign in](img/multi_login.png)
+- **GitLab AD**.
+- **GitLab Secondary AD**.
+- **GitLab Tertiary AD**.
### Set up LDAP user filter
@@ -286,9 +287,9 @@ necessary, you can set up an LDAP user filter. The filter must comply with [RFC
```ruby
gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'user_filter' => '(employeeType=developer)'
+ 'main' => {
+ # snip...
+ 'user_filter' => '(employeeType=developer)'
}
}
```
@@ -363,9 +364,9 @@ the configuration option `lowercase_usernames`. By default, this configuration o
```ruby
gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'lowercase_usernames' => true
+ 'main' => {
+ # snip...
+ 'lowercase_usernames' => true
}
}
```
@@ -444,15 +445,15 @@ If initially your LDAP configuration looked like:
1. In `/etc/gitlab/gitlab.rb`:
- ```ruby
- gitlab_rails['ldap_servers'] = {
- 'main' => {
- # snip...
- 'bind_dn' => 'admin',
- 'password' => '123'
- }
- }
- ```
+ ```ruby
+ gitlab_rails['ldap_servers'] = {
+ 'main' => {
+ # snip...
+ 'bind_dn' => 'admin',
+ 'password' => '123'
+ }
+ }
+ ```
1. Edit the encrypted secret:
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index c7572ec0a18..64ef27cbf51 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -181,7 +181,7 @@ The user should now be able to sign in.
#### Email has already been taken
A user tries to sign in with the correct LDAP credentials, is denied access,
-and the [production.log](../../logs.md#productionlog) shows an error that looks like this:
+and the [production.log](../../logs/index.md#productionlog) shows an error that looks like this:
```plaintext
(LDAP) Error saving user <USER DN> (email@example.com): ["Email has already been taken"]
@@ -210,8 +210,8 @@ This shows you which user has this email address. One of two steps must be taken
remove this email as a secondary email and make it a primary one so GitLab
associates this profile to the LDAP identity.
-The user can do either of these steps [in their
-profile](../../../user/profile/index.md#access-your-user-profile) or an administrator can do it.
+The user can do either of these steps
+[in their profile](../../../user/profile/index.md#access-your-user-profile) or an administrator can do it.
#### Projects limit errors
@@ -426,13 +426,12 @@ Rails.logger.level = Logger::DEBUG
LdapAllGroupsSyncWorker.new.perform
```
-Next, [learn how to read the
-output](#example-console-output-after-a-group-sync).
+Next, [learn how to read the output](#example-console-output-after-a-group-sync).
##### Example console output after a group sync
-Like the output from the user sync, the output from the [manual group
-sync](#sync-all-groups) is also very verbose. However, it contains lots
+Like the output from the user sync, the output from the
+[manual group sync](#sync-all-groups) is also very verbose. However, it contains lots
of helpful information.
Indicates the point where syncing actually begins:
@@ -644,10 +643,10 @@ users, [see what to do when no users are found](#no-users-are-found).
### GitLab logs
If a user account is blocked or unblocked due to the LDAP configuration, a
-message is [logged to `application.log`](../../logs.md#applicationlog).
+message is [logged to `application.log`](../../logs/index.md#applicationlog).
If there is an unexpected error during an LDAP lookup (configuration error,
-timeout), the sign-in is rejected and a message is [logged to `production.log`](../../logs.md#productionlog).
+timeout), the sign-in is rejected and a message is [logged to `production.log`](../../logs/index.md#productionlog).
### ldapsearch
@@ -743,8 +742,7 @@ For instructions about how to use the rails console, refer to this
This provides debug output that shows what GitLab is doing and with what.
This value is not persisted, and is only enabled for this session in the Rails console.
-To enable debug output in the rails console, [enter the rails
-console](#rails-console) and run:
+To enable debug output in the rails console, [enter the rails console](#rails-console) and run:
```ruby
Rails.logger.level = Logger::DEBUG
diff --git a/doc/administration/auth/ldap/ldap_synchronization.md b/doc/administration/auth/ldap/ldap_synchronization.md
index b0ada1c11dd..62706a9e3b9 100644
--- a/doc/administration/auth/ldap/ldap_synchronization.md
+++ b/doc/administration/auth/ldap/ldap_synchronization.md
@@ -128,7 +128,7 @@ To take advantage of group sync, group Owners or users with the [Maintainer role
### Add group links
For information on adding group links by using CNs and filters, refer to the
-[GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
+[GitLab groups documentation](../../../user/group/access_and_permissions.md#manage-group-memberships-via-ldap).
### Administrator sync
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 60a4cc8706f..8c5bf96e99e 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -250,8 +250,8 @@ 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 [OIDC
- specification](https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.4.3).
+1. For OIDC discovery to work with B2C, the policy must be configured 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).
In `TrustFrameworkBase.xml` under `JwtIssuer`, set `IssuanceClaimPattern` to `AuthorityWithTfp`:
@@ -529,8 +529,7 @@ If you're having trouble, here are some tips:
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 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`.
@@ -540,5 +539,4 @@ If you're having trouble, here are some tips:
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).
+ may need to [add a configuration parameter to Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 869de929eb8..8c7f8bf766d 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -97,7 +97,7 @@ These features can also help with compliance requirements:
projects): Search dependencies for their licenses. This lets you determine if
the licenses of your project's dependencies are compatible with your project's
license.
-- [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group)
+- [**Lock project membership to group**](../user/group/access_and_permissions.md#prevent-members-from-being-added-to-projects-in-a-group)
(for groups): Group owners can prevent new members from being added to projects
within a group.
- [**LDAP group sync**](auth/ldap/ldap_synchronization.md#group-sync) (for
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index 06eb9ffc84e..99876cdf503 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -46,6 +46,7 @@ required number of seconds.
"user",
"pipeline",
"builds",
+ "total_builds_count",
"namespace"
],
"properties" : {
@@ -61,7 +62,9 @@ required number of seconds.
"properties": {
"id": { "type": "integer" },
"path": { "type": "string" },
- "created_at": { "type": ["string", "null"], "format": "date-time" }
+ "created_at": { "type": ["string", "null"], "format": "date-time" },
+ "shared_runners_enabled": { "type": "boolean" },
+ "group_runners_enabled": { "type": "boolean" }
}
},
"user": {
@@ -121,6 +124,7 @@ required number of seconds.
}
}
},
+ "total_builds_count": { "type": "integer" },
"namespace": {
"type": "object",
"required": [
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index 833b9a877e9..a2d4f35a7c3 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -41,8 +41,8 @@ To bring the former **primary** site up to date:
NOTE:
If you [changed the DNS records](index.md#step-4-optional-updating-the-primary-domain-dns-record)
- for this site during disaster recovery procedure you may need to [block
- all the writes to this site](planned_failover.md#prevent-updates-to-the-primary-site)
+ for this site during disaster recovery procedure you may need to
+ [block all the writes to this site](planned_failover.md#prevent-updates-to-the-primary-site)
during this procedure.
1. [Set up database replication](../setup/database.md). In this case, the **secondary** site
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index f457cb4b0a2..0cae94fcec1 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -572,7 +572,7 @@ and after that you also need two extra steps.
postgresql['md5_auth_cidr_addresses'] = ['<primary_site_ip>/32', '<secondary_site_ip>/32']
# Every secondary site needs to have its own slot so specify the number of secondary sites you're going to have
- postgresql['max_replication_slots'] = 1
+ # postgresql['max_replication_slots'] = 1 # Set this to be the number of Geo secondary nodes if you have more than one
##
## Disable automatic database migrations temporarily
@@ -581,7 +581,7 @@ and after that you also need two extra steps.
gitlab_rails['auto_migrate'] = false
```
- (For more details about these settings you can read [Configure the primary server](../setup/database.md#step-1-configure-the-primary-server))
+ (For more details about these settings you can read [Configure the primary server](../setup/database.md#step-1-configure-the-primary-site))
1. Save the file and reconfigure GitLab for the database listen changes and
the replication slot changes to be applied:
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index 5a5d896c20a..6c3353e7d7e 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -45,7 +45,7 @@ be adapted for use with any other file-based data, such as [GitLab Pages](../../
### Container registry
By default, the container registry is not automatically replicated to secondary
-sites and this needs to be manually configured, see [Docker Registry for a secondary site](../replication/docker_registry.md).
+sites and this needs to be manually configured, see [Container Registry for a secondary site](../replication/container_registry.md).
If you are using local storage on your current primary site for the container
registry, you can `rsync` the container registry objects to the secondary
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index cf7d2649142..e3bf5ccdfe7 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -119,8 +119,8 @@ The following are required to run Geo:
The following operating systems are known to ship with a current version of OpenSSH:
- [CentOS](https://www.centos.org) 7.4 or later
- [Ubuntu](https://ubuntu.com) 16.04 or later
-- PostgreSQL 12 with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
- - PostgreSQL 13 is not supported for Geo, see [epic 3832](https://gitlab.com/groups/gitlab-org/-/epics/3832)
+- PostgreSQL 12 or 13 with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
+ - Note,[PostgreSQL 12 is deprecated](../../update/deprecations.md#postgresql-12-deprecated) and will be removed in GitLab 16.0.
- Git 2.9 or later
- Git-lfs 2.4.2 or later on the user side when using LFS
- All sites must run [the same GitLab and PostgreSQL versions](setup/database.md#postgresql-replication).
@@ -283,7 +283,7 @@ For information on using Geo in disaster recovery situations to mitigate data-lo
### Replicating the Container Registry
-For more information on how to replicate the Container Registry, see [Docker Registry for a **secondary** site](replication/docker_registry.md).
+For more information on how to replicate the Container Registry, see [Container Registry for a **secondary** site](replication/container_registry.md).
### Geo secondary proxy
diff --git a/doc/administration/geo/replication/container_registry.md b/doc/administration/geo/replication/container_registry.md
new file mode 100644
index 00000000000..b425e5dcc0d
--- /dev/null
+++ b/doc/administration/geo/replication/container_registry.md
@@ -0,0 +1,167 @@
+---
+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
+type: howto
+---
+
+# Container Registry for a secondary site **(PREMIUM SELF)**
+
+You can set up a Container Registry on your **secondary** Geo site that mirrors the one on the **primary** Geo site.
+
+## Supported container registries
+
+Geo supports the following types of container registries:
+
+- [Docker](https://docs.docker.com/registry/)
+- [OCI](https://github.com/opencontainers/distribution-spec/blob/main/spec.md)
+
+## Supported image formats
+
+The following container image formats are support by Geo:
+
+- [Docker V2, schema 1](https://docs.docker.com/registry/spec/manifest-v2-1/)
+- [Docker V2, schema 2](https://docs.docker.com/registry/spec/manifest-v2-2/)
+- [OCI (Open Container Initiative)](https://github.com/opencontainers/image-spec)
+
+In addition, Geo also supports [BuildKit cache images](https://github.com/moby/buildkit).
+
+## Supported storage
+
+### Docker
+
+For more information on supported registry storage drivers see
+[Docker registry storage drivers](https://docs.docker.com/registry/storage-drivers/)
+
+Read the [Load balancing considerations](https://docs.docker.com/registry/deploying/#load-balancing-considerations)
+when deploying the Registry, and how to set up the storage driver for the GitLab integrated
+[Container Registry](../../packages/container_registry.md#use-object-storage).
+
+### Registries that support OCI artifacts
+
+The following registries support OCI artifacts:
+
+- CNCF Distribution - local/offline verification
+- Azure Container Registry (ACR)
+- Amazon Elastic Container Registry (ECR)
+- Google Artifact Registry (GAR)
+- GitHub Packages container registry (GHCR)
+- Bundle Bar
+
+For more information, see the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec).
+
+## Configure Container Registry replication
+
+You can enable a storage-agnostic replication so it
+can be used for cloud or local storage. Whenever a new image is pushed to the
+**primary** site, each **secondary** site pulls it to its own container
+repository.
+
+To configure Container Registry replication:
+
+1. Configure the [**primary** site](#configure-primary-site).
+1. Configure the [**secondary** site](#configure-secondary-site).
+1. Verify Container Registry [replication](#verify-replication).
+
+### Configure **primary** site
+
+Make sure that you have Container Registry set up and working on
+the **primary** site before following the next steps.
+
+We need to make Container Registry send notification events to the
+**primary** site.
+
+1. SSH into your GitLab **primary** server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['notifications'] = [
+ {
+ 'name' => 'geo_event',
+ 'url' => 'https://<example.com>/api/v4/container_registry_event/events',
+ 'timeout' => '500ms',
+ 'threshold' => 5,
+ 'backoff' => '1s',
+ 'headers' => {
+ 'Authorization' => ['<replace_with_a_secret_token>']
+ }
+ }
+ ]
+ ```
+
+ NOTE:
+ Replace `<example.com>` with the `external_url` defined in your primary site's `/etc/gitlab/gitlab.rb` file, and
+ replace `<replace_with_a_secret_token>` with a case sensitive alphanumeric string
+ that starts with a letter. You can generate one with `< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`
+
+ NOTE:
+ If you use an external Registry (not the one integrated with GitLab), you must add
+ these settings to its configuration yourself. In this case, you also have to specify
+ notification secret in `registry.notification_secret` section of
+ `/etc/gitlab/gitlab.rb` file.
+
+ NOTE:
+ If you use GitLab HA, you also have to specify
+ the notification secret in `registry.notification_secret` section of
+ `/etc/gitlab/gitlab.rb` file for every web node.
+
+1. Reconfigure the **primary** node for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+### Configure **secondary** site
+
+Make sure you have Container Registry set up and working on
+the **secondary** site before following the next steps.
+
+The following steps should be done on each **secondary** site you're
+expecting to see the container images replicated.
+
+Because we need to allow the **secondary** site to communicate securely with
+the **primary** site Container Registry, we need to have a single key
+pair for all the sites. The **secondary** site uses this key to
+generate a short-lived JWT that is pull-only-capable to access the
+**primary** site Container Registry.
+
+For each application and Sidekiq node on the **secondary** site:
+
+1. SSH into the node and login as the `root` user:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Copy `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` from the **primary** to the node.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ gitlab_rails['geo_registry_replication_enabled'] = true
+
+ # Primary registry's hostname and port, it will be used by
+ # the secondary node to directly communicate to primary registry
+ gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/'
+ ```
+
+1. Reconfigure the node for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+### Verify replication
+
+To verify Container Registry replication is working, on the **secondary** site:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Geo > Nodes**.
+ The initial replication, or "backfill", is probably still in progress.
+
+You can monitor the synchronization process on each Geo site from the **primary** site's **Geo Nodes** dashboard in your browser.
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index acd27d5feed..40b71684bac 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -57,6 +57,8 @@ verification methods:
| Blobs | Pipeline artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | Pages _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | Pages _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | CI Secure Files _(file system)_ | Geo with API | SHA256 checksum |
+| Blobs | CI Secure Files _(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
@@ -185,8 +187,8 @@ successfully, you must replicate their data using some other means.
|Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | GitLab-managed object storage replication (added in GitLab version) | GitLab-managed object storage verification (added in GitLab version) | Notes |
|:--------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------|:---------------------------------------------------------------------------|:--------------------------------------------------------------------|:----------------------------------------------------------------|:------|
|[Application data in PostgreSQL](../../postgresql/index.md) | **Yes** (10.2) | **Yes** (10.2) | N/A | N/A | |
-|[Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
-|[Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
+|[Project repository](../../../user/project/repository/index.md) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
+|[Project wiki repository](../../../user/project/wiki/index.md) | **Yes** (10.2) | **Yes** (10.7) | N/A | N/A | |
|[Group wiki repository](../../../user/project/wiki/group.md) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | N/A | N/A | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default. |
|[Uploads](../../uploads.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification was behind the feature flag `geo_upload_verification`, removed in 14.8. |
|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification was behind the feature flag `geo_lfs_object_verification`, removed in 14.7. |
@@ -194,7 +196,8 @@ successfully, you must replicate their data using some other means.
|[Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | N/A | N/A | |
|[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. |
-|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
+|[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. |
|[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. |
@@ -202,9 +205,10 @@ successfully, you must replicate their data using some other means.
|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification was behind the feature flag `geo_merge_request_diff_verification`, removed in 14.7.|
|[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 | |
|[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. |
-|[Vulnerability Export](../../../user/application_security/vulnerability_report/#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. |
+|[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. |
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index 5d4ae12c990..f0658ae45a2 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -28,7 +28,7 @@ To disable Geo, you need to first remove all your secondary Geo sites, which mea
anymore on these sites. You can follow our docs to [remove your secondary Geo sites](remove_geo_site.md).
If the current site that you want to keep using is a secondary site, you need to first promote it to primary.
-You can use our steps on [how to promote a secondary site](../disaster_recovery/#step-3-promoting-a-secondary-site)
+You can use our steps on [how to promote a secondary site](../disaster_recovery/index.md#step-3-promoting-a-secondary-site)
to do that.
## Remove the primary site from the UI
diff --git a/doc/administration/geo/replication/docker_registry.md b/doc/administration/geo/replication/docker_registry.md
index 855e33d9a51..d0af6f2a66f 100644
--- a/doc/administration/geo/replication/docker_registry.md
+++ b/doc/administration/geo/replication/docker_registry.md
@@ -1,137 +1,11 @@
---
-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
-type: howto
+redirect_to: 'container_registry.md'
+remove_date: '2022-10-29'
---
-# Docker Registry for a secondary site **(PREMIUM SELF)**
+This document was moved to [another location](container_registry.md).
-You can set up a [Docker Registry](https://docs.docker.com/registry/) on your
-**secondary** Geo site that mirrors the one on the **primary** Geo site.
-
-## Storage support
-
-Docker Registry currently supports a few types of storage. If you choose a
-distributed storage (`azure`, `gcs`, `s3`, `swift`, or `oss`) for your Docker
-Registry on the **primary** site, you can use the same storage for a **secondary**
-Docker Registry as well. For more information, read the
-[Load balancing considerations](https://docs.docker.com/registry/deploying/#load-balancing-considerations)
-when deploying the Registry, and how to set up the storage driver for the GitLab
-integrated [Container Registry](../../packages/container_registry.md#use-object-storage).
-
-## Replicating Docker Registry
-
-You can enable a storage-agnostic replication so it
-can be used for cloud or local storage. Whenever a new image is pushed to the
-**primary** site, each **secondary** site pulls it to its own container
-repository.
-
-To configure Docker Registry replication:
-
-1. Configure the [**primary** site](#configure-primary-site).
-1. Configure the [**secondary** site](#configure-secondary-site).
-1. Verify Docker Registry [replication](#verify-replication).
-
-### Configure **primary** site
-
-Make sure that you have Container Registry set up and working on
-the **primary** site before following the next steps.
-
-We need to make Docker Registry send notification events to the
-**primary** site.
-
-1. SSH into your GitLab **primary** server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['notifications'] = [
- {
- 'name' => 'geo_event',
- 'url' => 'https://<example.com>/api/v4/container_registry_event/events',
- 'timeout' => '500ms',
- 'threshold' => 5,
- 'backoff' => '1s',
- 'headers' => {
- 'Authorization' => ['<replace_with_a_secret_token>']
- }
- }
- ]
- ```
-
- NOTE:
- Replace `<example.com>` with the `external_url` defined in your primary site's `/etc/gitlab/gitlab.rb` file, and
- replace `<replace_with_a_secret_token>` with a case sensitive alphanumeric string
- that starts with a letter. You can generate one with `< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 32 | sed "s/^[0-9]*//"; echo`
-
- NOTE:
- If you use an external Registry (not the one integrated with GitLab), you must add
- these settings to its configuration yourself. In this case, you also have to specify
- notification secret in `registry.notification_secret` section of
- `/etc/gitlab/gitlab.rb` file.
-
- NOTE:
- If you use GitLab HA, you also have to specify
- the notification secret in `registry.notification_secret` section of
- `/etc/gitlab/gitlab.rb` file for every web node.
-
-1. Reconfigure the **primary** node for the change to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-### Configure **secondary** site
-
-Make sure you have Container Registry set up and working on
-the **secondary** site before following the next steps.
-
-The following steps should be done on each **secondary** site you're
-expecting to see the Docker images replicated.
-
-Because we need to allow the **secondary** site to communicate securely with
-the **primary** site Container Registry, we need to have a single key
-pair for all the sites. The **secondary** site uses this key to
-generate a short-lived JWT that is pull-only-capable to access the
-**primary** site Container Registry.
-
-For each application and Sidekiq node on the **secondary** site:
-
-1. SSH into the node and login as the `root` user:
-
- ```shell
- sudo -i
- ```
-
-1. Copy `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` from the **primary** to the node.
-
-1. Edit `/etc/gitlab/gitlab.rb` and add:
-
- ```ruby
- gitlab_rails['geo_registry_replication_enabled'] = true
-
- # Primary registry's hostname and port, it will be used by
- # the secondary node to directly communicate to primary registry
- gitlab_rails['geo_registry_replication_primary_api_url'] = 'https://primary.example.com:5050/'
- ```
-
-1. Reconfigure the node for the change to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-### Verify replication
-
-To verify Container Registry replication is working, on the **secondary** site:
-
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Geo > Nodes**.
- The initial replication, or "backfill", is probably still in progress.
-
-You can monitor the synchronization process on each Geo site from the **primary** site's **Geo Nodes** dashboard in your browser.
+<!-- This redirect file can be deleted after <2022-10-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 --> \ No newline at end of file
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index bdf1771e8a8..7a67af1cfa2 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -65,10 +65,10 @@ connectivity between your sites, your hardware, and so on.
That's totally fine. We use HTTP(s) to fetch repository changes from the **primary** site to all **secondary** sites.
-## Is this possible to set up a Docker Registry for a **secondary** site that mirrors the one on the **primary** site?
+## Is this possible to set up a Container Registry for a **secondary** site that mirrors the one on the **primary** site?
-Yes. See [Docker Registry for a **secondary** site](docker_registry.md).
+Yes. See [Container Registry for a **secondary** site](container_registry.md).
-## Can you login to a secondary site?
+## Can you log 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/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 082ecbbb208..26d192f62cd 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -129,7 +129,7 @@ http://secondary.example.com/
```
To find more details about failed items, check
-[the `gitlab-rails/geo.log` file](../../troubleshooting/log_parsing.md#find-most-common-geo-sync-errors)
+[the `gitlab-rails/geo.log` file](../../logs/log_parsing.md#find-most-common-geo-sync-errors)
### Check if PostgreSQL replication is working
@@ -191,7 +191,7 @@ If a replication slot is inactive,
the `pg_wal` logs corresponding to the slot are reserved forever
(or until the slot is active again). This causes continuous disk usage growth
and the following messages appear repeatedly in the
-[PostgreSQL logs](../../logs.md#postgresql-logs):
+[PostgreSQL logs](../../logs/index.md#postgresql-logs):
```plaintext
WARNING: oldest xmin is far in the past
@@ -331,8 +331,7 @@ Be sure to restart PostgreSQL for this to take effect. See the
This occurs when PostgreSQL does not have a replication slot for the
**secondary** node by that name.
-You may want to rerun the [replication
-process](../setup/database.md) on the **secondary** node .
+You may want to rerun the [replication process](../setup/database.md) on the **secondary** node .
### Message: "Command exceeded allowed execution time" when setting up replication?
@@ -376,7 +375,7 @@ log data to build up in `pg_xlog`. Removing the unused slots can reduce the amou
Slots where `active` is `f` are not active.
- When this slot should be active, because you have a **secondary** node configured using that slot,
- sign in to that **secondary** node and check the [PostgreSQL logs](../../logs.md#postgresql-logs)
+ sign in to that **secondary** node and check the [PostgreSQL logs](../../logs/index.md#postgresql-logs)
to view why the replication is not running.
- If you are no longer using the slot (for example, you no longer have Geo enabled), you can remove it with in the
@@ -510,7 +509,7 @@ To solve this:
1. Back up [the `.git` folder](../../repository_storage_types.md#translate-hashed-storage-paths).
-1. Optional. [Spot-check](../../troubleshooting/log_parsing.md#find-all-projects-affected-by-a-fatal-git-problem)
+1. Optional. [Spot-check](../../logs/log_parsing.md#find-all-projects-affected-by-a-fatal-git-problem)
a few of those IDs whether they indeed correspond
to a project with known Geo replication failures.
Use `fatal: 'geo'` as the `grep` term and the following API call:
@@ -597,7 +596,7 @@ to start again from scratch, there are a few steps that can help you:
gitlab-ctl stop geo-logcursor
```
- You can watch the [Sidekiq logs](../../logs.md#sidekiq-logs) to know when Sidekiq jobs processing has finished:
+ You can watch the [Sidekiq logs](../../logs/index.md#sidekiq-logs) to know when Sidekiq jobs processing has finished:
```shell
gitlab-ctl tail sidekiq
@@ -837,7 +836,7 @@ to transfer each affected repository from the primary to the secondary site.
The following are possible error messages that might be encountered during failover or
when promoting a secondary to a primary node with strategies to resolve them.
-### Message: ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
+### Message: `ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`
When [promoting a **secondary** site](../disaster_recovery/index.md#step-3-promoting-a-secondary-site),
you might encounter the following error message:
@@ -869,11 +868,10 @@ or `gitlab-ctl promote-to-primary-node`, either:
```
- Upgrade to GitLab 12.6.3 or later if it is safe to do so. For example,
- if the failover was just a test. A [caching-related
- bug](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22021) was
- fixed.
+ if the failover was just a test. A
+ [caching-related bug](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22021) was fixed.
-### Message: ActiveRecord::RecordInvalid: Validation failed: Enabled Geo primary node cannot be disabled
+### Message: `ActiveRecord::RecordInvalid: Validation failed: Enabled Geo primary node cannot be disabled`
If you disabled a secondary node, either with the [replication pause task](../index.md#pausing-and-resuming-replication)
(GitLab 13.2) or by using the user interface (GitLab 13.1 and earlier), you must first
@@ -1127,12 +1125,6 @@ Geo secondary sites continue to replicate and verify data, and the secondary sit
This bug was [fixed in GitLab 14.4](https://gitlab.com/gitlab-org/gitlab/-/issues/292983).
-### GitLab Pages return 404 errors after promoting
-
-This is due to [Pages data not being managed by Geo](datatypes.md#limitations-on-replicationverification).
-Find advice to resolve those error messages in the
-[Pages administration documentation](../../../administration/pages/index.md#404-error-after-promoting-a-geo-secondary-to-a-primary-node).
-
### Primary site returns 500 error when accessing `/admin/geo/replication/projects`
Navigating to **Admin > Geo > Replication** (or `/admin/geo/replication/projects`) on a primary Geo site, shows a 500 error, while that same link on the secondary works fine. The primary's `production.log` has a similar entry to the following:
@@ -1146,7 +1138,28 @@ Geo::TrackingBase::SecondaryNotConfigured: Geo secondary database is not configu
On a Geo primary site this error can be ignored.
-This happens because GitLab is attempting to display registries from the [Geo tracking database](../../../administration/geo/#geo-tracking-database) which doesn't exist on the primary site (only the original projects exist on the primary; no replicated projects are present, therefore no tracking database exists).
+This happens because GitLab is attempting to display registries from the [Geo tracking database](../../../administration/geo/index.md#geo-tracking-database) which doesn't exist on the primary site (only the original projects exist on the primary; no replicated projects are present, therefore no tracking database exists).
+
+### Secondary site returns 400 error "Request header or cookie too large"
+
+This error can happen when the internal URL of the primary site is incorrect.
+
+For example, when you use a unified URL and the primary site's internal URL is also equal to the external URL. This causes a loop when a secondary site proxies requests to the primary site's internal URL.
+
+To fix this issue, set the primary site's internal URL to a URL that is:
+
+- Unique to the primary site.
+- Accessible from all secondary sites.
+
+1. Enter the [Rails console](../../operations/rails_console.md) on the primary site.
+
+1. Run the following, replacing `https://unique.url.for.primary.site` with your specific internal URL.
+ For example, depending on your network configuration, you could use an IP address, like
+ `http://1.2.3.4`.
+
+ ```ruby
+ GeoNode.where(primary: true).first.update!(internal_url: "https://unique.url.for.primary.site")
+ ```
## Fixing client errors
@@ -1158,6 +1171,23 @@ requests redirected from the secondary to the primary node do not properly send
Authorization header. This may result in either an infinite `Authorization <-> Redirect`
loop, or Authorization error messages.
+### Error: Net::ReadTimeout when pushing through SSH on a Geo secondary
+
+When you push large repositories through SSH on a Geo secondary site, you may encounter a timeout.
+This is because Rails proxies the push to the primary and has a 60 second default timeout,
+[as described in this Geo issue](https://gitlab.com/gitlab-org/gitlab/-/issues/7405).
+
+Current workarounds are:
+
+- Push through HTTP instead, where Workhorse proxies the request to the primary (or redirects to the primary if Geo proxying is not enabled).
+- Push directly to the primary.
+
+Example log (`gitlab-shell.log`):
+
+```plaintext
+Failed to contact primary https://primary.domain.com/namespace/push_test.git\\nError: Net::ReadTimeout\",\"result\":null}" code=500 method=POST pid=5483 url="http://127.0.0.1:3000/api/v4/geo/proxy_git_push_ssh/push"
+```
+
## Recovering from a partial failover
The partial failover to a secondary Geo *site* may be the result of a temporary/transient issue. Therefore, first attempt to run the promote command again.
diff --git a/doc/administration/geo/replication/tuning.md b/doc/administration/geo/replication/tuning.md
index 670459624f3..755ab45a76c 100644
--- a/doc/administration/geo/replication/tuning.md
+++ b/doc/administration/geo/replication/tuning.md
@@ -30,7 +30,7 @@ However, this may not lead to more downloads in parallel unless the number of
available Sidekiq threads is also increased. For example, if repository synchronization
concurrency is increased from 25 to 50, you may also want to increase the number
of Sidekiq threads from 25 to 50. See the
-[Sidekiq concurrency documentation](../../operations/extra_sidekiq_processes.md#number-of-threads)
+[Sidekiq concurrency documentation](../../sidekiq/extra_sidekiq_processes.md#number-of-threads)
for more details.
## Repository re-verification
diff --git a/doc/administration/geo/replication/upgrading_the_geo_sites.md b/doc/administration/geo/replication/upgrading_the_geo_sites.md
index 30961de0381..ce1ff4fe6a5 100644
--- a/doc/administration/geo/replication/upgrading_the_geo_sites.md
+++ b/doc/administration/geo/replication/upgrading_the_geo_sites.md
@@ -28,12 +28,23 @@ and cause downtime. If you want to avoid downtime, consider using
To upgrade the Geo sites when a new GitLab version is released, upgrade **primary**
and all **secondary** sites:
-1. **Optional:** [Pause replication on each **secondary** sites.](../index.md#pausing-and-resuming-replication)
+1. Optional. [Pause replication on each **secondary** site](../index.md#pausing-and-resuming-replication)
+ to protect the disaster recovery (DR) capability of the **secondary** sites.
1. SSH into each node of the **primary** site.
1. [Upgrade GitLab on the **primary** site](../../../update/package/index.md#upgrade-using-the-official-repositories).
+1. Perform testing on the **primary** site, particularly if you paused replication in step 1 to protect DR. [There are some suggestions for post-upgrade testing](../../../update/plan_your_upgrade.md#pre-upgrade-and-post-upgrade-checks) in the upgrade documentation.
1. SSH into each node of **secondary** sites.
1. [Upgrade GitLab on each **secondary** site](../../../update/package/index.md#upgrade-using-the-official-repositories).
-1. If you paused replication in step 1, [resume replication on each **secondary**](../index.md#pausing-and-resuming-replication)
+1. If you paused replication in step 1, [resume replication on each **secondary**](../index.md#pausing-and-resuming-replication).
+ Then, restart Puma and Sidekiq on each **secondary** site. This is to ensure they
+ are initialized against the newer database schema that is now replicated from
+ the previously upgraded **primary** site.
+
+ ```shell
+ sudo gitlab-ctl restart sidekiq
+ sudo gitlab-ctl restart puma
+ ```
+
1. [Test](#check-status-after-upgrading) **primary** and **secondary** sites, and check version in each.
### Check status after upgrading
diff --git a/doc/administration/geo/replication/version_specific_upgrades.md b/doc/administration/geo/replication/version_specific_upgrades.md
index f0925bdf87e..350310c7076 100644
--- a/doc/administration/geo/replication/version_specific_upgrades.md
+++ b/doc/administration/geo/replication/version_specific_upgrades.md
@@ -178,11 +178,15 @@ GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab
## Upgrading to GitLab 13.7
-We've detected an issue with the `FetchRemove` call used by Geo secondaries.
-This causes performance issues as we execute reference transaction hooks for
-each upgraded reference. Delay any upgrade attempts until this is in the
-[13.7.5 patch release.](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3002).
-More details are available [in this issue](https://gitlab.com/gitlab-org/git/-/issues/79).
+- We've detected an issue with the `FetchRemove` call used by Geo secondaries.
+ This causes performance issues as we execute reference transaction hooks for
+ each upgraded reference. Delay any upgrade attempts until this is in the
+ [13.7.5 patch release.](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3002).
+ More details are available [in this issue](https://gitlab.com/gitlab-org/git/-/issues/79).
+- A new secret is generated in `/etc/gitlab/gitlab-secrets.json`.
+ In an HA GitLab or GitLab Geo environment, secrets need to be the same on all nodes.
+ Ensure this new secret is also accounted for if you are manually syncing the file across
+ nodes, or manually specifying secrets in `/etc/gitlab/gitlab.rb`.
## Upgrading to GitLab 13.5
@@ -243,8 +247,8 @@ the recommended procedure, see the
## Upgrading to GitLab 12.9
WARNING:
-GitLab 12.9.0 through GitLab 12.9.3 are affected by [a bug that stops
-repository verification](https://gitlab.com/gitlab-org/gitlab/-/issues/213523).
+GitLab 12.9.0 through GitLab 12.9.3 are affected by
+[a bug that stops repository verification](https://gitlab.com/gitlab-org/gitlab/-/issues/213523).
The issue is fixed in GitLab 12.9.4. Upgrade to GitLab 12.9.4 or later.
By default, GitLab 12.9 attempts to upgrade the embedded PostgreSQL server
@@ -397,6 +401,6 @@ For the recommended procedure, see the
## Upgrading to GitLab 12.0
WARNING:
-This version is affected by a [bug that results in new LFS objects not being
-replicated to Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
+This version is affected by a
+[bug that results in new LFS objects not being replicated to Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/32696).
The issue is fixed in GitLab 12.1. Be sure to upgrade to GitLab 12.1 or later.
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index e8c290e197b..6c1812b2754 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -112,8 +112,9 @@ gitlab:
Since GitLab 15.1, Geo secondary proxying is enabled by default for separate URLs also.
-There are minor known issues linked in the ["Geo secondary proxying with separate URLs"
-epic](https://gitlab.com/groups/gitlab-org/-/epics/6865). You can also add feedback in the epic about any use-cases that
+There are minor known issues linked in the
+["Geo secondary proxying with separate URLs" epic](https://gitlab.com/groups/gitlab-org/-/epics/6865).
+You can also add feedback in the epic about any use-cases that
are not possible anymore with proxying enabled.
If you run into issues, to disable this feature, disable the `geo_secondary_proxy_separate_urls` feature flag.
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
index c0ed7829fce..8a919a0a269 100644
--- a/doc/administration/geo/setup/database.md
+++ b/doc/administration/geo/setup/database.md
@@ -8,7 +8,7 @@ type: howto
# Geo database replication **(PREMIUM SELF)**
This document describes the minimal required steps to replicate your primary
-GitLab database to a secondary node's database. You may have to change some
+GitLab database to a secondary site's database. You may have to change some
values, based on attributes including your database's setup and size.
NOTE:
@@ -41,31 +41,31 @@ instructions on setting up replication with a Patroni cluster.
### PostgreSQL replication
-The GitLab **primary** node where the write operations happen connects to
-the **primary** database server, and **secondary** nodes
+The GitLab **primary** site where the write operations happen connects to
+the **primary** database server, and **secondary** sites
connect to their own database servers (which are read-only).
We recommend using [PostgreSQL replication slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
-to ensure that the **primary** node retains all the data necessary for the **secondary** nodes to
+to ensure that the **primary** site retains all the data necessary for the **secondary** sites to
recover. See below for more details.
The following guide assumes that:
- You are using Omnibus and therefore you are using PostgreSQL 12 or later
which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/12/app-pgbasebackup.html).
-- You have a **primary** node already set up (the GitLab server you are
+- You have a **primary** site already set up (the GitLab server you are
replicating from), running Omnibus' PostgreSQL (or equivalent version), and
- you have a new **secondary** server set up with the same
+ you have a new **secondary** site set up with the same
[versions of PostgreSQL](../index.md#requirements-for-running-geo),
- OS, and GitLab on all nodes.
+ OS, and GitLab on all sites.
WARNING:
Geo works with streaming replication. Logical replication is not supported at this time.
There is an [issue where support is being discussed](https://gitlab.com/gitlab-org/gitlab/-/issues/7420).
-#### Step 1. Configure the **primary** server
+#### Step 1. Configure the **primary** site
-1. SSH into your GitLab **primary** server and login as root:
+1. SSH into your GitLab **primary** site and login as root:
```shell
sudo -i
@@ -81,13 +81,13 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
gitlab_rails['geo_node_name'] = '<site_name_here>'
```
-1. Reconfigure the **primary** node for the change to take effect:
+1. Reconfigure the **primary** site for the change to take effect:
```shell
gitlab-ctl reconfigure
```
-1. Execute the command below to define the node as **primary** node:
+1. Execute the command below to define the site as **primary** site:
```shell
gitlab-ctl set-geo-primary-node
@@ -154,17 +154,17 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
1. Configure PostgreSQL to listen on network interfaces:
For security reasons, PostgreSQL does not listen on any network interfaces
- by default. However, Geo requires the **secondary** node to be able to
- connect to the **primary** node's database. For this reason, we need the address of
- each node.
+ by default. However, Geo requires the **secondary** site to be able to
+ connect to the **primary** site's database. For this reason, we need the IP address of
+ each site.
NOTE:
For external PostgreSQL instances, see [additional instructions](external_database.md).
If you are using a cloud provider, you can lookup the addresses for each
- Geo node through your cloud provider's management console.
+ Geo site through your cloud provider's management console.
- To lookup the address of a Geo node, SSH in to the Geo node and execute:
+ To lookup the address of a Geo site, SSH in to the Geo site and execute:
```shell
##
@@ -183,11 +183,11 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
| Configuration | Address |
|:----------------------------------------|:----------------------------------------------------------------------|
- | `postgresql['listen_address']` | **Primary** node's public or VPC private address. |
- | `postgresql['md5_auth_cidr_addresses']` | **Primary** and **Secondary** nodes' public or VPC private addresses. |
+ | `postgresql['listen_address']` | **Primary** site's public or VPC private address. |
+ | `postgresql['md5_auth_cidr_addresses']` | **Primary** and **Secondary** sites' public or VPC private addresses. |
If you are using Google Cloud Platform, SoftLayer, or any other vendor that
- provides a virtual private cloud (VPC) you can use the **primary** and **secondary** nodes
+ provides a virtual private cloud (VPC) you can use the **primary** and **secondary** sites
private addresses (corresponds to "internal address" for Google Cloud Platform) for
`postgresql['md5_auth_cidr_addresses']` and `postgresql['listen_address']`.
@@ -201,10 +201,10 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
`127.0.0.1`. For more information, see [omnibus-5258](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5258).
Depending on your network configuration, the suggested addresses may not
- be correct. If your **primary** node and **secondary** nodes connect over a local
+ be correct. If your **primary** site and **secondary** sites connect over a local
area network, or a virtual network connecting availability zones like
[Amazon's VPC](https://aws.amazon.com/vpc/) or [Google's VPC](https://cloud.google.com/vpc/)
- you should use the **secondary** node's private address for `postgresql['md5_auth_cidr_addresses']`.
+ you should use the **secondary** site's private address for `postgresql['md5_auth_cidr_addresses']`.
Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
addresses with addresses appropriate to your network configuration:
@@ -225,19 +225,18 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
## Primary address
## - replace '<primary_node_ip>' with the public or VPC address of your Geo primary node
##
- postgresql['listen_address'] = '<primary_node_ip>'
+ postgresql['listen_address'] = '<primary_site_ip>'
##
# Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
# public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
##
- postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_site_ip>/32', '<secondary_site_ip>/32']
##
## Replication settings
- ## - set this to be the number of Geo secondary nodes you have
##
- postgresql['max_replication_slots'] = 1
+ # postgresql['max_replication_slots'] = 1 # Set this to be the number of Geo secondary nodes if you have more than one
# postgresql['max_wal_senders'] = 10
# postgresql['wal_keep_segments'] = 10
@@ -248,10 +247,10 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
gitlab_rails['auto_migrate'] = false
```
-1. Optional: If you want to add another **secondary** node, the relevant setting would look like:
+1. Optional: If you want to add another **secondary** site, the relevant setting would look like:
```ruby
- postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32', '<another_secondary_node_ip>/32']
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_site_ip>/32', '<secondary_site_ip>/32', '<another_secondary_site_ip>/32']
```
You may also want to edit the `wal_keep_segments` and `max_wal_senders` to match your
@@ -288,20 +287,20 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
1. Now that the PostgreSQL server is set up to accept remote connections, run
`netstat -plnt | grep 5432` to make sure that PostgreSQL is listening on port
- `5432` to the **primary** server's private address.
+ `5432` to the **primary** site's private address.
1. A certificate was automatically generated when GitLab was reconfigured. This
is used automatically to protect your PostgreSQL traffic from
eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
- the **secondary** node needs a copy of the certificate. Make a copy of the PostgreSQL
- `server.crt` file on the **primary** node by running this command:
+ the **secondary** site needs a copy of the certificate. Make a copy of the PostgreSQL
+ `server.crt` file on the **primary** site by running this command:
```shell
cat ~gitlab-psql/data/server.crt
```
Copy the output into a clipboard or into a local file. You
- need it when setting up the **secondary** node! The certificate is not sensitive
+ need it when setting up the **secondary** site! The certificate is not sensitive
data.
However, this certificate is created with a generic `PostgreSQL` Common Name. For this,
@@ -324,7 +323,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
#### Step 2. Configure the **secondary** server
-1. SSH into your GitLab **secondary** server and login as root:
+1. SSH into your GitLab **secondary** site and login as root:
```shell
sudo -i
@@ -338,28 +337,28 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
```
NOTE:
- This step is important so we don't try to execute anything before the node is fully configured.
+ This step is important so we don't try to execute anything before the site is fully configured.
-1. [Check TCP connectivity](../../raketasks/maintenance.md) to the **primary** node's PostgreSQL server:
+1. [Check TCP connectivity](../../raketasks/maintenance.md) to the **primary** site's PostgreSQL server:
```shell
- gitlab-rake gitlab:tcp_check[<primary_node_ip>,5432]
+ gitlab-rake gitlab:tcp_check[<primary_site_ip>,5432]
```
NOTE:
If this step fails, you may be using the wrong IP address, or a firewall may
- be preventing access to the server. Check the IP address, paying close
+ be preventing access to the site. Check the IP address, paying close
attention to the difference between public and private addresses and ensure
- that, if a firewall is present, the **secondary** node is permitted to connect to the
- **primary** node on port 5432.
+ that, if a firewall is present, the **secondary** site is permitted to connect to the
+ **primary** site on port 5432.
-1. Create a file `server.crt` in the **secondary** server, with the content you got on the last step of the **primary** node's setup:
+1. Create a file `server.crt` in the **secondary** site, with the content you got on the last step of the **primary** site's setup:
```shell
editor server.crt
```
-1. Set up PostgreSQL TLS verification on the **secondary** node:
+1. Set up PostgreSQL TLS verification on the **secondary** site:
Install the `server.crt` file:
@@ -374,9 +373,9 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
PostgreSQL now only recognizes that exact certificate when verifying TLS
connections. The certificate can only be replicated by someone with access
- to the private key, which is **only** present on the **primary** node.
+ to the private key, which is **only** present on the **primary** site.
-1. Test that the `gitlab-psql` user can connect to the **primary** node's database
+1. Test that the `gitlab-psql` user can connect to the **primary** site's database
(the default Omnibus database name is `gitlabhq_production`):
```shell
@@ -386,7 +385,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
-U gitlab_replicator \
-d "dbname=gitlabhq_production sslmode=verify-ca" \
-W \
- -h <primary_node_ip>
+ -h <primary_site_ip>
```
NOTE:
@@ -397,11 +396,11 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
When prompted enter the _plaintext_ password you set in the first step for the
`gitlab_replicator` user. If all worked correctly, you should see
- the list of **primary** node's databases.
+ the list of **primary** site's databases.
A failure to connect here indicates that the TLS configuration is incorrect.
- Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** node
- match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** node.
+ Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** site
+ match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** site.
1. Configure PostgreSQL:
@@ -420,14 +419,14 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
##
## Secondary address
- ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
+ ## - replace '<secondary_site_ip>' with the public or VPC address of your Geo secondary site
##
- postgresql['listen_address'] = '<secondary_node_ip>'
- postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
+ postgresql['listen_address'] = '<secondary_site_ip>'
+ postgresql['md5_auth_cidr_addresses'] = ['<secondary_site_ip>/32']
##
- ## Database credentials password (defined previously in primary node)
- ## - replicate same values here as defined in primary node
+ ## Database credentials password (defined previously in primary site)
+ ## - replicate same values here as defined in primary site
##
postgresql['sql_replication_password'] = '<md5_hash_of_your_password>'
postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
@@ -435,7 +434,7 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
```
For external PostgreSQL instances, see [additional instructions](external_database.md).
- If you bring a former **primary** node back online to serve as a **secondary** node, then you also must remove `roles(['geo_primary_role'])` or `geo_primary_role['enable'] = true`.
+ If you bring a former **primary** site back online to serve as a **secondary** site, then you also must remove `roles(['geo_primary_role'])` or `geo_primary_role['enable'] = true`.
1. Reconfigure GitLab for the changes to take effect:
@@ -451,24 +450,24 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
#### Step 3. Initiate the replication process
-Below we provide a script that connects the database on the **secondary** node to
-the database on the **primary** node, replicates the database, and creates the
+Below we provide a script that connects the database on the **secondary** site to
+the database on the **primary** site, replicates the database, and creates the
needed files for streaming replication.
The directories used are the defaults that are set up in Omnibus. If you have
changed any defaults, configure it as you see fit replacing the directories and paths.
WARNING:
-Make sure to run this on the **secondary** server as it removes all PostgreSQL's
+Make sure to run this on the **secondary** site as it removes all PostgreSQL's
data before running `pg_basebackup`.
-1. SSH into your GitLab **secondary** server and login as root:
+1. SSH into your GitLab **secondary** site and login as root:
```shell
sudo -i
```
-1. Choose a database-friendly name to use for your **secondary** node to
+1. Choose a database-friendly name to use for your **secondary** site to
use as the replication slot name. For example, if your domain is
`secondary.geo.example.com`, you may use `secondary_example` as the slot
name as shown in the commands below.
@@ -476,13 +475,13 @@ data before running `pg_basebackup`.
1. Execute the command below to start a backup/restore and begin the replication
WARNING:
- Each Geo **secondary** node must have its own unique replication slot name.
+ Each Geo **secondary** site must have its own unique replication slot name.
Using the same slot name between two secondaries breaks PostgreSQL replication.
```shell
gitlab-ctl replicate-geo-database \
- --slot-name=<secondary_node_name> \
- --host=<primary_node_ip> \
+ --slot-name=<secondary_site_name> \
+ --host=<primary_site_ip> \
--sslmode=verify-ca
```
@@ -516,7 +515,7 @@ data before running `pg_basebackup`.
- Change the `--slot-name` to the name of the replication slot
to be used on the **primary** database. The script attempts to create the
replication slot automatically if it does not exist.
- - If you're repurposing an old server into a Geo **secondary** node, you must
+ - If you're repurposing an old site into a Geo **secondary** site, you must
add `--force` to the command line.
- When not in a production machine you can disable backup step if you
really sure this is what you want by adding `--skip-backup`
@@ -540,7 +539,7 @@ see [High Availability with Omnibus GitLab](../../postgresql/replication_and_fai
To change the password for the [replication user](https://wiki.postgresql.org/wiki/Streaming_Replication)
when using Omnibus-managed PostgreSQL instances:
-On the GitLab Geo **primary** server:
+On the GitLab Geo **primary** site:
1. The default value for the replication user is `gitlab_replicator`, but if you've set a custom replication
user in your `/etc/gitlab/gitlab.rb` under the `postgresql['sql_replication_user']` setting, make sure to
@@ -574,19 +573,18 @@ On the GitLab Geo **primary** server:
sudo gitlab-ctl restart postgresql
```
-Until the password is updated on any **secondary** servers, the [PostgreSQL log](../../logs.md#postgresql-logs) on
+Until the password is updated on any **secondary** sites, the [PostgreSQL log](../../logs/index.md#postgresql-logs) on
the secondaries will report the following error message:
```console
FATAL: could not connect to the primary server: FATAL: password authentication failed for user "gitlab_replicator"
```
-On all GitLab Geo **secondary** servers:
+On all GitLab Geo **secondary** sites:
1. The first step isn't necessary from a configuration perspective, because the hashed `'sql_replication_password'`
- is not used on the GitLab Geo **secondary**. However in the event that **secondary** needs to be promoted
- to the GitLab Geo **primary**, make sure to match the `'sql_replication_password'` in the secondary
- server configuration.
+ is not used on the GitLab Geo **secondary** sites. However in the event that **secondary** site needs to be promoted
+ to the GitLab Geo **primary**, make sure to match the `'sql_replication_password'` in the **secondary** site configuration.
Edit `/etc/gitlab/gitlab.rb`:
@@ -616,6 +614,28 @@ In GitLab 14.0, Patroni replaced `repmgr` as the supported
NOTE:
If you still haven't [migrated from repmgr to Patroni](#migrating-from-repmgr-to-patroni) you're highly advised to do so.
+### Migrating from repmgr to Patroni
+
+1. Before migrating, we recommend that there is no replication lag between the **primary** and **secondary** sites and that replication is paused. In GitLab 13.2 and later, you can pause and resume replication with `gitlab-ctl geo-replication-pause` and `gitlab-ctl geo-replication-resume` on a Geo secondary database node.
+1. Follow the [instructions to migrate repmgr to Patroni](../../postgresql/replication_and_failover.md#switching-from-repmgr-to-patroni). When configuring Patroni on each **primary** site database node, add `patroni['replication_slots'] = { '<slot_name>' => 'physical' }`
+to `gitlab.rb` where `<slot_name>` is the name of the replication slot for your **secondary** site. This ensures that Patroni recognizes the replication slot as permanent and not drop it upon restarting.
+1. If database replication to the **secondary** site was paused before migration, resume replication once Patroni is confirmed working on the **primary** site.
+
+### Migrating a single PostgreSQL node to Patroni
+
+Before the introduction of Patroni, Geo had no Omnibus support for HA setups on the **secondary** site.
+
+With Patroni it's now possible to support that. To migrate the existing PostgreSQL to Patroni:
+
+1. Make sure you have a Consul cluster setup on the secondary (similar to how you set it up on the **primary** site).
+1. [Configure a permanent replication slot](#step-1-configure-patroni-permanent-replication-slot-on-the-primary-site).
+1. [Configure the internal load balancer](#step-2-configure-the-internal-load-balancer-on-the-primary-site).
+1. [Configure a PgBouncer node](#step-3-configure-pgbouncer-nodes-on-the-secondary-site)
+1. [Configure a Standby Cluster](#step-4-configure-a-standby-cluster-on-the-secondary-site)
+ on that single node machine.
+
+You end up with a “Standby Cluster†with a single node. That allows you to later on add additional Patroni nodes by following the same instructions above.
+
### Patroni support
Patroni is the official replication management solution for Geo. It
@@ -648,11 +668,11 @@ and other database best practices.
##### Step 1. Configure Patroni permanent replication slot on the primary site
-To set up database replication with Patroni on a secondary node, we must
-configure a _permanent replication slot_ on the primary node's Patroni cluster,
+To set up database replication with Patroni on a secondary site, we must
+configure a _permanent replication slot_ on the primary site's Patroni cluster,
and ensure password authentication is used.
-For each Patroni instance on the primary site **starting on the Patroni
+On each node running a Patroni instance on the primary site **starting on the Patroni
Leader instance**:
1. SSH into your Patroni instance and login as root:
@@ -755,7 +775,7 @@ backend postgresql
Refer to your preferred Load Balancer's documentation for further guidance.
-##### Step 3. Configure a PgBouncer node on the secondary site
+##### Step 3. Configure PgBouncer nodes on the secondary site
A production-ready and highly available configuration requires at least
three Consul nodes, a minimum of one PgBouncer node, but it's recommended to have
@@ -764,7 +784,7 @@ more than one PgBouncer service nodes. The internal load balancer provides a sin
endpoint for connecting to the PgBouncer cluster. For more information,
see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
-Follow the minimal configuration for the PgBouncer node:
+On each node running a PgBouncer instance on the **secondary** site:
1. SSH into your PgBouncer node and login as root:
@@ -820,11 +840,10 @@ Follow the minimal configuration for the PgBouncer node:
##### Step 4. Configure a Standby cluster on the secondary site
NOTE:
-If you are converting a secondary site to a Patroni Cluster, you must start
-on the PostgreSQL instance. It becomes the Patroni Standby Leader instance,
-and then you can switchover to another replica if you need.
+If you are converting a secondary site with a single PostgreSQL instance to a Patroni Cluster, you must start on the PostgreSQL instance. It becomes the Patroni Standby Leader instance,
+and then you can switch over to another replica if you need.
-For each Patroni instance on the secondary site:
+For each node running a Patroni instance on the secondary site:
1. SSH into your Patroni node and login as root:
@@ -894,39 +913,29 @@ For each Patroni instance on the secondary site:
gitlab-ctl start patroni
```
-### Migrating from repmgr to Patroni
-
-1. Before migrating, we recommend that there is no replication lag between the primary and secondary sites and that replication is paused. In GitLab 13.2 and later, you can pause and resume replication with `gitlab-ctl geo-replication-pause` and `gitlab-ctl geo-replication-resume` on a Geo secondary database node.
-1. Follow the [instructions to migrate repmgr to Patroni](../../postgresql/replication_and_failover.md#switching-from-repmgr-to-patroni). When configuring Patroni on each primary site database node, add `patroni['replication_slots'] = { '<slot_name>' => 'physical' }`
-to `gitlab.rb` where `<slot_name>` is the name of the replication slot for your Geo secondary. This ensures that Patroni recognizes the replication slot as permanent and not drop it upon restarting.
-1. If database replication to the secondary was paused before migration, resume replication once Patroni is confirmed working on the primary.
-
-### Migrating a single PostgreSQL node to Patroni
-
-Before the introduction of Patroni, Geo had no Omnibus support for HA setups on the secondary node.
+### Migrating a single tracking database node to Patroni
-With Patroni it's now possible to support that. To migrate the existing PostgreSQL to Patroni:
+Before the introduction of Patroni, Geo had no Omnibus support for HA setups on
+the secondary site.
-1. Make sure you have a Consul cluster setup on the secondary (similar to how you set it up on the primary).
-1. [Configure a permanent replication slot](#step-1-configure-patroni-permanent-replication-slot-on-the-primary-site).
-1. [Configure the internal load balancer](#step-2-configure-the-internal-load-balancer-on-the-primary-site).
-1. [Configure a PgBouncer node](#step-3-configure-a-pgbouncer-node-on-the-secondary-site)
-1. [Configure a Standby Cluster](#step-4-configure-a-standby-cluster-on-the-secondary-site)
- on that single node machine.
+With Patroni, it's now possible to support that. Due to some restrictions on the
+Patroni implementation on Omnibus that do not allow us to manage two different
+clusters on the same machine, we recommend setting up a new Patroni cluster for
+the tracking database by following the same instructions above.
-You end up with a "Standby Cluster" with a single node. That allows you to later on add additional Patroni nodes
-by following the same instructions above.
+The secondary nodes backfill the new tracking database, and no data
+synchronization is required.
### Configuring Patroni cluster for the tracking PostgreSQL database
-Secondary sites use a separate PostgreSQL installation as a tracking database to
+**Secondary** sites use a separate PostgreSQL installation as a tracking database to
keep track of replication status and automatically recover from potential replication issues.
Omnibus automatically configures a tracking database when `roles(['geo_secondary_role'])` is set.
If you want to run this database in a highly available configuration, don't use the `geo_secondary_role` above.
Instead, follow the instructions below.
-A production-ready and secure setup requires at least three Consul nodes, two
+A production-ready and secure setup for the tracking PostgreSQL DB requires at least three Consul nodes, two
Patroni nodes and one PgBouncer node on the secondary site.
Because of [omnibus-6587](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6587), Consul can't track multiple
@@ -935,9 +944,9 @@ services, so these must be different than the nodes used for the Standby Cluster
Be sure to use [password credentials](../../postgresql/replication_and_failover.md#database-authorization-for-patroni)
and other database best practices.
-#### Step 1. Configure a PgBouncer node on the secondary site
+#### Step 1. Configure PgBouncer nodes on the secondary site
-Follow the minimal configuration for the PgBouncer node for the tracking database:
+On each node running the PgBouncer service for the PostgreSQL tracking database:
1. SSH into your PgBouncer node and login as root:
@@ -999,7 +1008,7 @@ Follow the minimal configuration for the PgBouncer node for the tracking databas
#### Step 2. Configure a Patroni cluster
-For each Patroni instance on the secondary site for the tracking database:
+On each node running a Patroni instance on the secondary site for the PostgreSQL tracking database:
1. SSH into your Patroni node and login as root:
@@ -1063,7 +1072,7 @@ For each Patroni instance on the secondary site for the tracking database:
gitlab-ctl reconfigure
```
-#### Step 3. Configure the tracking database on the secondary nodes
+#### Step 3. Configure the tracking database on the secondary sites
For each node running the `gitlab-rails`, `sidekiq`, and `geo-logcursor` services:
@@ -1100,19 +1109,6 @@ For each node running the `gitlab-rails`, `sidekiq`, and `geo-logcursor` service
gitlab-rake db:migrate:geo
```
-### Migrating a single tracking database node to Patroni
-
-Before the introduction of Patroni, Geo had no Omnibus support for HA setups on
-the secondary node.
-
-With Patroni, it's now possible to support that. Due to some restrictions on the
-Patroni implementation on Omnibus that do not allow us to manage two different
-clusters on the same machine, we recommend setting up a new Patroni cluster for
-the tracking database by following the same instructions above.
-
-The secondary nodes backfill the new tracking database, and no data
-synchronization is required.
-
## Troubleshooting
Read the [troubleshooting document](../replication/troubleshooting.md).
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
index 5ddfee6774e..79b52ef71da 100644
--- a/doc/administration/geo/setup/index.md
+++ b/doc/administration/geo/setup/index.md
@@ -22,8 +22,10 @@ The steps below should be followed in the order they appear. **Make sure the Git
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. [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).
1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** sites.
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** sites.
diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md
index b2bdd876499..44b09ef185a 100644
--- a/doc/administration/get_started.md
+++ b/doc/administration/get_started.md
@@ -37,8 +37,8 @@ Watch an overview of [groups and projects](https://www.youtube.com/watch?v=cqb2m
Get started:
- Create a [project](../user/project/working_with_projects.md#create-a-project).
-- Create a [group](../user/group/index.md#create-a-group).
-- [Add members](../user/group/index.md#add-users-to-a-group) to the group.
+- Create a [group](../user/group/manage.md#create-a-group).
+- [Add members](../user/group/manage.md#add-users-to-a-group) to the group.
- Create a [subgroup](../user/group/subgroups/index.md#create-a-subgroup).
- [Add members](../user/group/subgroups/index.md#subgroup-membership) to the subgroup.
- Enable [external authorization control](../user/admin_area/settings/external_authorization.md#configuration).
@@ -144,7 +144,7 @@ You can restore a backup only to **the exact same version and type** (Community
### Back up GitLab SaaS
-Backups of GitLab databases and filesystems are taken every 24 hours, and are kept for two weeks on a rolling schedule. All backups are encrypted.
+Backups of GitLab databases and file systems are taken every 24 hours, and are kept for two weeks on a rolling schedule. All backups are encrypted.
- GitLab SaaS creates backups to ensure your data is secure, but you can't use these methods to export or back up your data yourself.
- Issues are stored in the database. They can't be stored in Git itself.
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 4b2832bebc0..5b868c274cd 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -280,8 +280,9 @@ Updates to example must be made at:
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-1. Run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`
- to confirm that Gitaly can perform callbacks to the GitLab internal API.
+1. Confirm that Gitaly can perform callbacks to the GitLab internal API:
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
**For installations from source**
@@ -330,8 +331,9 @@ Updates to example must be made at:
```
1. Save the files and [restart GitLab](../restart_gitlab.md#installations-from-source).
-1. Run `sudo -u git /home/git/gitaly/gitaly-hooks check /home/git/gitaly/config.toml`
- to confirm that Gitaly can perform callbacks to the GitLab internal API.
+1. Confirm that Gitaly can perform callbacks to the GitLab internal API:
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
WARNING:
If directly copying repository data from a GitLab server to Gitaly, ensure that the metadata file,
@@ -792,7 +794,7 @@ gitaly['concurrency'] = [
- `max_per_repo` is the maximum number of in-flight RPC calls for the given RPC per repository.
- `max_queue_time` is the maximum amount of time a request can wait in the concurrency queue to
be picked up by Gitaly.
-- `max_queue_size` is the maximum size the concurrency queue can grow to before requests are rejected by
+- `max_queue_size` is the maximum size the concurrency queue (per RPC method) can grow to before requests are rejected by
Gitaly.
This limits the number of in-flight RPC calls for the given RPCs. The limit is applied per
@@ -811,26 +813,12 @@ information, see the [relevant documentation](monitoring.md#monitor-gitaly-concu
## Control groups
FLAG:
-On self-managed GitLab, by default cgroups are not available. To make it available, ask an administrator to
+On self-managed GitLab, by default repository cgroups are not available. To make it available, ask an administrator to
[enable the feature flag](../feature_flags.md) named `gitaly_run_cmds_in_cgroup`.
-Gitaly shells out to Git for many of its operations. Git can consume a lot of resources for certain operations,
-especially for large repositories.
-
Control groups (cgroups) in Linux allow limits to be imposed on how much memory and CPU can be consumed.
See the [`cgroups` Linux man page](https://man7.org/linux/man-pages/man7/cgroups.7.html) for more information.
-cgroups can be useful for protecting the system against resource exhaustion because of overcomsumption of memory and CPU.
-
-Gitaly has built-in cgroups control. When configured, Gitaly assigns Git
-processes to a cgroup based on the repository the Git command is operating in.
-Each cgroup has a memory and CPU limit. When a cgroup reaches its:
-
-- Memory limit, the kernel looks through the processes for a candidate to kill.
-- CPU limit, processes are not killed, but the processes are prevented from consuming more CPU than allowed.
-
-The main reason to configure cgroups for your GitLab installation is that it
-protects against system resource starvation due to a few large repositories or
-bad actors.
+cgroups can be useful for protecting the system against resource exhaustion because of over consumption of memory and CPU.
Some Git operations are expensive by nature. `git clone`, for instance,
spawns a `git-upload-pack` process on the server that can consume a lot of memory
@@ -838,33 +826,33 @@ for large repositories. For example, a client that keeps on cloning a
large repository over and over again. This situation could potentially use up all of the
memory on a server, causing other operations to fail for other users.
-There are many ways someone can create a repository that can consume large amounts of memory when cloned or downloaded.
+A repository can consume large amounts of memory for many reasons when cloned or downloaded.
Using cgroups allows the kernel to kill these operations before they hog up all system resources.
-### Configure cgroups in Gitaly
+Gitaly shells out to Git for many of its operations. Git can consume a lot of resources for certain operations,
+especially for large repositories.
-Two ways of configuring cgroups are available.
+Gitaly has built-in cgroups control. When configured, Gitaly assigns Git processes to a cgroup based on the repository
+the Git command is operating in. These cgroups are called repository cgroups. Each repository cgroup:
-#### Configure cgroups (new method)
+- Has a memory and CPU limit.
+- Contains the Git processes for a single repository.
+- Uses a consistent hash to ensure a Git process for a given repository always ends up in the same cgroup.
-> This method of configuring cgroups introduced in GitLab 15.1.
+When a repository cgroup reaches its:
-Gitaly creates a pool of cgroups that are isolated based on the repository used in the Git command to be placed under one of these cgroups.
+- Memory limit, the kernel looks through the processes for a candidate to kill.
+- CPU limit, processes are not killed, but the processes are prevented from consuming more CPU than allowed.
-To configure cgroups in Gitaly, add `gitaly['cgroups']` to `/etc/gitlab/gitlab.rb`.
+You configure repository cgroups for your GitLab installation to protect against system resource starvation from a few
+large repositories or bad actors.
-For example:
+### Configure repository cgroups (new method)
-```ruby
-# in /etc/gitlab/gitlab.rb
-gitaly['cgroups_mountpoint'] = "/sys/fs/cgroup"
-gitaly['cgroups_hierarchy_root'] =>"gitaly"
-gitaly['cgroups_memory_bytes'] = 64424509440, # 60gb
-gitaly['cgroups_cpu_shares'] = 1024
-gitaly['cgroups_repositories_count'] => 1000,
-gitaly['cgroups_repositories_memory_bytes'] => 32212254720 # 20gb
-gitaly['cgroups_repositories_cpu_shares'] => 512
-```
+> This method of configuring repository cgroups was introduced in GitLab 15.1.
+
+To configure repository cgroups in Gitaly using the new method, use the following settings for the new configuration method
+to `gitaly['cgroups']` in `/etc/gitlab/gitlab.rb`:
- `cgroups_mountpoint` is where the parent cgroup directory is mounted. Defaults to `/sys/fs/cgroup`.
- `cgroups_hierarchy_root` is the parent cgroup under which Gitaly creates groups, and
@@ -873,7 +861,7 @@ gitaly['cgroups_repositories_cpu_shares'] => 512
when Gitaly starts.
- `cgroups_memory_bytes` is the total memory limit that is imposed collectively on all
Git processes that Gitaly spawns. 0 implies no limit.
-- `cgroups_cpu_shares` is the cpu limit that is imposed collectively on all Git
+- `cgroups_cpu_shares` is the CPU limit that is imposed collectively on all Git
processes that Gitaly spawns. 0 implies no limit. The maximum is 1024 shares,
which represents 100% of CPU.
- `cgroups_repositories_count` is the number of cgroups in the cgroups pool. Each time a new Git
@@ -881,30 +869,30 @@ gitaly['cgroups_repositories_cpu_shares'] => 512
on the repository the command is for. A circular hashing algorithm assigns
Git commands to these cgroups, so a Git command for a repository is
always assigned to the same cgroup.
-- `cgroups_repositories_memory_bytes` is the total memory limit that is imposed collectively on all
- Git processes that Gitaly spawns. 0 implies no limit. This value cannot exceed
- that of the top level `cgroups_memory_bytes`.
-- `cgroups_repositories_cpu_shares` is the CPU limit that is imposed collectively on all Git
- processes Gitaly spawns. 0 implies no limit. The maximum is 1024 shares,
- which represents 100% of CPU. This value cannot exceed that of the top
- level`cgroups_cpu_shares`.
-
-#### Configure cgroups (legacy method)
+- `cgroups_repositories_memory_bytes` is the total memory limit imposed on all Git processes contained in a repository cgroup.
+ 0 implies no limit. This value cannot exceed that of the top level `cgroups_memory_bytes`.
+- `cgroups_repositories_cpu_shares` is the CPU limit that is imposed on all Git processes contained in a repository cgroup.
+ 0 implies no limit. The maximum is 1024 shares, which represents 100% of CPU.
+ This value cannot exceed that of the top level`cgroups_cpu_shares`.
-To configure cgroups in Gitaly for GitLab versions using the legacy method, add `gitaly['cgroups']` to `/etc/gitlab/gitlab.rb`. For
-example:
+For example:
```ruby
# in /etc/gitlab/gitlab.rb
-gitaly['cgroups_count'] = 1000
gitaly['cgroups_mountpoint'] = "/sys/fs/cgroup"
-gitaly['cgroups_hierarchy_root'] = "gitaly"
-gitaly['cgroups_memory_limit'] = 32212254720
-gitaly['cgroups_memory_enabled'] = true
+gitaly['cgroups_hierarchy_root'] => "gitaly"
+gitaly['cgroups_memory_bytes'] = 64424509440, # 60gb
gitaly['cgroups_cpu_shares'] = 1024
-gitaly['cgroups_cpu_enabled'] = true
+gitaly['cgroups_repositories_count'] => 1000,
+gitaly['cgroups_repositories_memory_bytes'] => 32212254720 # 20gb
+gitaly['cgroups_repositories_cpu_shares'] => 512
```
+### Configure repository cgroups (legacy method)
+
+To configure repository cgroups in Gitaly using the legacy method, use the following settings
+in `/etc/gitlab/gitlab.rb`:
+
- `cgroups_count` is the number of cgroups created. Each time a new
command is spawned, Gitaly assigns it to one of these cgroups based
on the command line arguments of the command. A circular hashing algorithm assigns
@@ -917,7 +905,21 @@ gitaly['cgroups_cpu_enabled'] = true
- `cgroups_memory_enabled` enables or disables the memory limit on cgroups.
- `cgroups_memory_bytes` is the total memory limit each cgroup imposes on the processes added to it.
- `cgroups_cpu_enabled` enables or disables the CPU limit on cgroups.
-- `cgroups_cpu_shares` is the CPU limit each cgroup imposes on the processes added to it. The maximum is 1024 shares, which represents 100% of CPU.
+- `cgroups_cpu_shares` is the CPU limit each cgroup imposes on the processes added to it. The maximum is 1024 shares,
+ which represents 100% of CPU.
+
+For example:
+
+```ruby
+# in /etc/gitlab/gitlab.rb
+gitaly['cgroups_count'] = 1000
+gitaly['cgroups_mountpoint'] = "/sys/fs/cgroup"
+gitaly['cgroups_hierarchy_root'] = "gitaly"
+gitaly['cgroups_memory_limit'] = 32212254720
+gitaly['cgroups_memory_enabled'] = true
+gitaly['cgroups_cpu_shares'] = 1024
+gitaly['cgroups_cpu_enabled'] = true
+```
### Configuring oversubscription
@@ -926,16 +928,15 @@ In the previous example using the new configuration method:
- The top level memory limit is capped at 60gb.
- Each of the 1000 cgroups in the repositories pool is capped at 20gb.
-This is called "oversubscription". Each cgroup in the pool has a much larger capacity than 1/1000th
+This configuration leads to "oversubscription". Each cgroup in the pool has a much larger capacity than 1/1000th
of the top-level memory limit.
This strategy has two main benefits:
-- It gives the host protection from overall memory starvation (OOM), because the top-level
- cgroup's memory limit can be set to a threshold smaller than the host's
- capacity. Processes outside of that cgroup are not at risk of OOM.
+- It gives the host protection from overall memory starvation (OOM), because the memory limit of the top-level cgroup
+ can be set to a threshold smaller than the host's capacity. Processes outside of that cgroup are not at risk of OOM.
- It allows each individual cgroup in the pool to burst up to a generous upper
- bound (in this example 20 GB) that is smaller than the parent cgroup's limit,
+ bound (in this example 20 GB) that is smaller than the limit of the parent cgroup,
but substantially larger than 1/N of the parent's limit. In this example, up
to 3 child cgroups can concurrently burst up to their max. In general, all
1000 cgroups would use much less than the 20 GB.
@@ -1141,8 +1142,7 @@ gitaly['pack_objects_cache_enabled'] = true
#### `enabled` defaults to `false`
The cache is disabled by default. This is because in some cases, it
-can create an [extreme
-increase](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4010#note_534564684)
+can create an [extreme increase](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4010#note_534564684)
in the number of bytes written to disk. On GitLab.com, we have verified
that our repository storage disks can handle this extra workload, but
we felt we cannot assume this is true everywhere.
@@ -1302,14 +1302,26 @@ process repositories that do not pass consistency checks.
For Omnibus GitLab installations, edit `/etc/gitlab/gitlab.rb` and set the
following keys (in this example, to disable the `hasDotgit` consistency check):
-```ruby
-ignored_git_errors = ["hasDotgit = ignore"]
-omnibus_gitconfig['system'] = {
- "fsck" => ignored_git_errors,
- "fetch.fsck" => ignored_git_errors,
- "receive.fsck" => ignored_git_errors,
-}
-```
+- In [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later:
+
+ ```ruby
+ gitaly['gitconfig'] = [
+ { key: "fsck.hasDotgit", value: "ignore" },
+ { key: "fetch.fsck.hasDotgit", value: "ignore" },
+ { key: "receive.fsck.hasDotgit", value: "ignore "},
+ ]
+ ```
+
+- In GitLab 15.2 and earlier (legacy method):
+
+ ```ruby
+ ignored_git_errors = ["hasDotgit = ignore"]
+ omnibus_gitconfig['system'] = {
+ "fsck" => ignored_git_errors,
+ "fetch.fsck" => ignored_git_errors,
+ "receive.fsck" => ignored_git_errors,
+ }
+ ```
For source installs, edit the Gitaly configuration (`gitaly.toml`) to do the
equivalent:
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index c543f62f135..b053da7ac9b 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -70,7 +70,7 @@ the current status of these issues, please refer to the referenced issues and ep
| Issue | Summary | How to avoid |
|:--------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------|
-| Gitaly Cluster + Geo - Issues retrying failed syncs | If Gitaly Cluster is used on a Geo secondary site, repositories that have failed to sync could continue to fail when Geo tries to resync them. Recovering from this state requires assistance from support to run manual steps. Work is in-progress to update Gitaly Cluster to [identify repositories with a unique and persistent identifier](https://gitlab.com/gitlab-org/gitaly/-/issues/3485), which is expected to resolve the issue. | No known solution at this time. |
+| Gitaly Cluster + Geo - Issues retrying failed syncs | If Gitaly Cluster is used on a Geo secondary site, repositories that have failed to sync could continue to fail when Geo tries to resync them. Recovering from this state requires assistance from support to run manual steps. | No known solution prior to GitLab 15.0. In GitLab 15.0 to 15.2, enable the [`gitaly_praefect_generated_replica_paths` feature flag](#praefect-generated-replica-paths-gitlab-150-and-later). In GitLab 15.3, the feature flag is enabled by default. |
| Praefect unable to insert data into the database due to migrations not being applied after an upgrade | If the database is not kept up to date with completed migrations, then the Praefect node is unable to perform normal operation. | Make sure the Praefect database is up and running with all migrations completed (For example: `/opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate-status` should show a list of all applied migrations). Consider [requesting upgrade assistance](https://about.gitlab.com/support/scheduling-upgrade-assistance/) so your upgrade plan can be reviewed by support. |
| Restoring a Gitaly Cluster node from a snapshot in a running cluster | Because the Gitaly Cluster runs with consistent state, introducing a single node that is behind will result in the cluster not being able to reconcile the nodes data and other nodes data | Don't restore a single Gitaly Cluster node from a backup snapshot. If you must restore from backup, it's best to snapshot all Gitaly Cluster nodes at the same time and take a database dump of the Praefect database. |
@@ -80,16 +80,31 @@ Gitaly Cluster does not support snapshot backups. Snapshot backups can cause iss
out of sync with the disk storage. Because of how Praefect rebuilds the replication metadata of Gitaly disk information
during a restore, we recommend using the [official backup and restore Rake tasks](../../raketasks/backup_restore.md).
-If you are unable to use this method, please contact customer support for restoration help.
+The [incremental backup method](../../raketasks/backup_gitlab.md#incremental-repository-backups)
+can be used to speed up Gitaly Cluster backups.
-We are tracking in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/351383) improvements to the
-[official backup and restore Rake tasks](../../raketasks/backup_restore.md) to add support for incremental backups. For
-more information, see [this epic](https://gitlab.com/groups/gitlab-org/-/epics/2094).
+If you are unable to use either method, please contact customer support for restoration help.
### What to do if you are on Gitaly Cluster experiencing an issue or limitation
Please contact customer support for immediate help in restoration or recovery.
+## Directly accessing repositories
+
+GitLab doesn't advise directly accessing Gitaly repositories stored on disk with a Git client or any other tool,
+because Gitaly is being continuously improved and changed. These improvements may invalidate
+your assumptions, resulting in performance degradation, instability, and even data loss. For example:
+
+- Gitaly has optimizations such as the [`info/refs` advertisement cache](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md),
+ that rely on Gitaly controlling and monitoring access to repositories by using the official gRPC
+ interface.
+- [Gitaly Cluster](#gitaly-cluster) has optimizations, such as fault tolerance and
+ [distributed reads](#distributed-reads), that depend on the gRPC interface and database
+ to determine repository state.
+
+WARNING:
+Accessing Git repositories directly is done at your own risk and is not supported.
+
## Gitaly
The following shows GitLab set up to use direct access to Gitaly:
@@ -141,6 +156,11 @@ Gitaly comes pre-configured with Omnibus GitLab, which is a configuration
GitLab installations for more than 2000 active users performing daily Git write operation may be
best suited by using Gitaly Cluster.
+### Backing up repositories
+
+When backing up or syncing repositories using tools other than GitLab, you must [prevent writes](../../raketasks/backup_restore.md#prevent-writes-and-copy-the-git-repository-data)
+while copying repository data.
+
## Gitaly Cluster
Git storage is provided through the Gitaly service in GitLab, and is essential to the operation of
@@ -297,11 +317,12 @@ follow the [hashed storage](../repository_storage_types.md#hashed-storage) schem
#### Praefect-generated replica paths (GitLab 15.0 and later)
-> Introduced in GitLab 15.0 behind [a feature flag](https://gitlab.com/gitlab-org/gitaly/-/issues/4218) named `gitaly_praefect_generated_replica_paths`. Disabled by default.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4218) in GitLab 15.0 [with a flag](../feature_flags.md) named `gitaly_praefect_generated_replica_paths`. Disabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitaly/-/issues/4218) in GitLab 15.2.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4809) in GitLab 15.3.
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 `gitaly_praefect_generated_replica_paths`. On GitLab.com, this feature is available but can be configured by GitLab.com administrators only. The feature is not ready for production use.
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](../feature_flags.md) named `gitaly_praefect_generated_replica_paths`. On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
When Gitaly Cluster creates a repository, it assigns the repository a unique and permanent ID called the _repository ID_. The repository ID is
internal to Gitaly Cluster and doesn't relate to any IDs elsewhere in GitLab. If a repository is removed from Gitaly Cluster and later moved
@@ -525,12 +546,9 @@ To upgrade a Gitaly Cluster, follow the documentation for
### Downgrade Gitaly Cluster to a previous version
-If you need to roll back a Gitaly Cluster to an earlier version, some Praefect database migrations may need to be reverted. In a cluster with:
+If you need to roll back a Gitaly Cluster to an earlier version, some Praefect database migrations may need to be reverted.
-- A single Praefect node, this happens when GitLab itself is downgraded.
-- Multiple Praefect nodes, additional steps are required.
-
-To downgrade a Gitaly Cluster with multiple Praefect nodes:
+To downgrade a Gitaly Cluster (assuming multiple Praefect nodes):
1. Stop the Praefect service on all Praefect nodes:
@@ -565,7 +583,7 @@ To downgrade a Gitaly Cluster with multiple Praefect nodes:
gitlab-ctl start praefect
```
-## Migrate to Gitaly Cluster
+### Migrate to Gitaly Cluster
WARNING:
Some [known issues](#known-issues) exist in Gitaly Cluster. Review the following information before you continue.
@@ -587,7 +605,7 @@ To migrate to Gitaly Cluster:
Even if you don't use the `default` repository storage, you must ensure it is configured.
[Read more about this limitation](configure_gitaly.md#gitlab-requires-a-default-repository-storage).
-## Migrate off Gitaly Cluster
+### Migrate off Gitaly Cluster
If the limitations and tradeoffs of Gitaly Cluster are found to be not suitable for your environment, you can Migrate
off Gitaly Cluster to a sharded Gitaly instance:
@@ -596,22 +614,6 @@ off Gitaly Cluster to a sharded Gitaly instance:
1. [Move the repositories](../operations/moving_repositories.md#move-repositories) to the newly created storage. You can
move them by shard or by group, which gives you the opportunity to spread them over multiple Gitaly servers.
-## Do not bypass Gitaly
-
-GitLab doesn't advise directly accessing Gitaly repositories stored on disk with a Git client,
-because Gitaly is being continuously improved and changed. These improvements may invalidate
-your assumptions, resulting in performance degradation, instability, and even data loss. For example:
-
-- Gitaly has optimizations such as the [`info/refs` advertisement cache](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/design_diskcache.md),
- that rely on Gitaly controlling and monitoring access to repositories by using the official gRPC
- interface.
-- [Gitaly Cluster](#gitaly-cluster) has optimizations, such as fault tolerance and
- [distributed reads](#distributed-reads), that depend on the gRPC interface and database
- to determine repository state.
-
-WARNING:
-Accessing Git repositories directly is done at your own risk and is not supported.
-
## Direct access to Git in GitLab
Direct access to Git uses code in GitLab known as the "Rugged patches".
@@ -683,8 +685,12 @@ To see if GitLab can access the repository file system directly, we use the foll
- GitLab Rails tries to read the metadata file directly. If it exists, and if the UUID's match,
assume we have direct access.
-Direct Git access is enable by default in Omnibus GitLab because it fills in the correct repository
-paths in the GitLab configuration file `config/gitlab.yml`. This satisfies the UUID check.
+Versions of GitLab 15.3 and later disable direct Git access by default.
+
+For versions of GitLab prior to 15.3, direct Git access is enabled by
+default in Omnibus GitLab because it fills in the correct repository
+paths in the GitLab configuration file `config/gitlab.yml`. This
+satisfies the UUID check.
### Transition to Gitaly Cluster
diff --git a/doc/administration/gitaly/monitoring.md b/doc/administration/gitaly/monitoring.md
index 0dd9e0d7128..a435fff74fc 100644
--- a/doc/administration/gitaly/monitoring.md
+++ b/doc/administration/gitaly/monitoring.md
@@ -34,7 +34,7 @@ of requests dropped due to request limiting. The `reason` label indicates why a
You can observe specific behavior of [concurrency-queued requests](configure_gitaly.md#limit-rpc-concurrency) using
the Gitaly logs and Prometheus:
-- In the [Gitaly logs](../logs.md#gitaly-logs), look for the string (or structured log field)
+- In the [Gitaly logs](../logs/index.md#gitaly-logs), look for the string (or structured log field)
`acquire_ms`. Messages that have this field are reporting about the concurrency limiter.
- In Prometheus, look for the following metrics:
- `gitaly_concurrency_limiting_in_progress` indicates how many concurrent requests are
@@ -188,7 +188,7 @@ To monitor [repository verification](praefect.md#repository-verification), use t
- `gitaly_praefect_stale_verification_leases_released_total`, the number of stale verification leases
released.
-You can also monitor the [Praefect logs](../logs.md#praefect-logs).
+You can also monitor the [Praefect logs](../logs/index.md#praefect-logs).
### Database metrics `/db_metrics` endpoint
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 5635898293b..488e6a0df5f 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -97,8 +97,8 @@ If you [installed](https://about.gitlab.com/install/) GitLab using the Omnibus G
### Preparation
-Before beginning, you should already have a working GitLab instance. [Learn how
-to install GitLab](https://about.gitlab.com/install/).
+Before beginning, you should already have a working GitLab instance.
+[Learn how to install GitLab](https://about.gitlab.com/install/).
Provision a PostgreSQL server. We recommend using the PostgreSQL that is shipped
with Omnibus GitLab and use it to configure the PostgreSQL database. You can use an
@@ -331,8 +331,8 @@ To configure the additional connection, you must either:
#### Configure a new PgBouncer database with `pool_mode = session`
We recommend using PgBouncer with `session` pool mode. You can use the
-[bundled PgBouncer](../postgresql/pgbouncer.md) or use an external PgBouncer and [configure it
-manually](https://www.pgbouncer.org/config.html).
+[bundled PgBouncer](../postgresql/pgbouncer.md) or use an external PgBouncer and
+[configure it manually](https://www.pgbouncer.org/config.html).
The following example uses the bundled PgBouncer and sets up two separate connection pools on PostgreSQL host,
one in `session` pool mode and the other in `transaction` pool mode. For this example to work,
@@ -620,8 +620,8 @@ Updates to example must be made at:
gitlab-ctl reconfigure
```
-1. To ensure that Praefect [has updated its Prometheus listen
- address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734),
+1. To ensure that Praefect
+ [has updated its Prometheus listen address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734),
[restart Praefect](../restart_gitlab.md#omnibus-gitlab-restart):
```shell
@@ -928,8 +928,8 @@ For more information on Gitaly server configuration, see our
gitlab-ctl reconfigure
```
-1. To ensure that Gitaly [has updated its Prometheus listen
- address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734),
+1. To ensure that Gitaly
+ [has updated its Prometheus listen address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734),
[restart Gitaly](../restart_gitlab.md#omnibus-gitlab-restart):
```shell
@@ -1103,10 +1103,8 @@ Particular attention should be shown to:
```
1. Verify on each Gitaly node the Git Hooks can reach GitLab. On each Gitaly node run:
-
- ```shell
- /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml
- ```
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
1. Verify that GitLab can reach Praefect:
@@ -1151,8 +1149,7 @@ running multiple Gitaly storages.
### Grafana
Grafana is included with GitLab, and can be used to monitor your Praefect
-cluster. See [Grafana Dashboard
-Service](https://docs.gitlab.com/omnibus/settings/grafana.html)
+cluster. See [Grafana Dashboard Service](https://docs.gitlab.com/omnibus/settings/grafana.html)
for detailed documentation.
To get started quickly:
@@ -1320,8 +1317,7 @@ praefect['background_verification_verification_interval'] = '0'
WARNING:
Deletions are disabled by default due to a race condition with repository renames that can cause incorrect
deletions. This is especially prominent in Geo instances as Geo performs more renames than instances without Geo.
-See [Handle repository creations, deletions and renames atomically](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4101)
-for progress on a fix. We do not recommend enabling the deletions until this is fixed.
+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
metrics for them.
diff --git a/doc/administration/gitaly/recovery.md b/doc/administration/gitaly/recovery.md
index 551a7ab289a..bd4846a986d 100644
--- a/doc/administration/gitaly/recovery.md
+++ b/doc/administration/gitaly/recovery.md
@@ -296,6 +296,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.
The `remove-repository` Praefect sub-command removes a repository from a Gitaly Cluster, and all state associated with a given repository including:
@@ -310,6 +311,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
+ 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).
- In GitLab 14.6 and later, add `-apply` to run the command outside of dry-run mode and remove the repository. For example:
```shell
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index fb3a31d61b8..e308fa9da43 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -13,7 +13,7 @@ Refer to the information below when troubleshooting Gitaly and Gitaly Cluster.
The following sections provide possible solutions to Gitaly errors.
See also [Gitaly timeout](../../user/admin_area/settings/gitaly_timeouts.md) settings,
-and our advice on [parsing the `gitaly/current` file](../troubleshooting/log_parsing.md#parsing-gitalycurrent).
+and our advice on [parsing the `gitaly/current` file](../logs/log_parsing.md#parsing-gitalycurrent).
### Check versions when using standalone Gitaly servers
@@ -24,6 +24,17 @@ as GitLab to ensure full compatibility:
1. On the left sidebar, select **Overview > Gitaly Servers**.
1. Confirm all Gitaly servers indicate that they are up to date.
+### Find storage resource details
+
+You can run the following commands in a [Rails console](../operations/rails_console.md#starting-a-rails-console-session)
+to determine the available and used space on a Gitaly storage:
+
+```ruby
+Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
+# For Gitaly Cluster
+Gitlab::GitalyClient::ServerService.new("<storage name>").disk_statistics
+```
+
### Use `gitaly-debug`
The `gitaly-debug` command provides "production debugging" tools for Gitaly and Git
@@ -444,15 +455,15 @@ If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
Here are common errors and potential causes:
- 500 response code
- - **ActionView::Template::Error (7:permission denied)**
+ - `ActionView::Template::Error (7:permission denied)`
- `praefect['auth_token']` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
- - **Unable to save project. Error: 7:permission denied**
+ - `Unable to save project. Error: 7:permission denied`
- Secret token in `praefect['storage_nodes']` on GitLab server does not match the
value in `gitaly['auth_token']` on one or more Gitaly servers.
- 503 response code
- - **GRPC::Unavailable (14:failed to connect to all addresses)**
+ - `GRPC::Unavailable (14:failed to connect to all addresses)`
- GitLab was unable to reach Praefect.
- - **GRPC::Unavailable (14:all SubCons are in TransientFailure...)**
+ - `GRPC::Unavailable (14:all SubCons are in TransientFailure...)`
- Praefect cannot reach one or more of its child Gitaly nodes. Try running
the Praefect connection checker to diagnose.
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 95301ec026a..9351a101ee4 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -75,11 +75,12 @@ Email is processed correctly when a configured email address is present in one o
(sorted in the order they are checked):
- `To`
-- `References`
- `Delivered-To`
- `Envelope-To` or `X-Envelope-To`
- `Received`
+The `References` header is also accepted, however it is used specifically to relate email responses to existing discussion threads. It is not used for creating issues by email.
+
In GitLab 14.6 and later, [Service Desk](../user/project/service_desk.md)
also checks accepted headers.
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 4565c0a8e00..3f2ae3170ab 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -207,9 +207,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Troubleshooting
-- [Log system](logs.md): Where to look for logs.
+- [Log system](logs/index.md): Where to look for logs.
- [Sidekiq Troubleshooting](troubleshooting/sidekiq.md): Debug when Sidekiq appears hung and is not processing jobs.
-- [Troubleshooting Elasticsearch](troubleshooting/elasticsearch.md)
- [Navigating GitLab via Rails console](operations/rails_console.md)
- [GitLab application limits](instance_limits.md)
- [Responding to security incidents](../security/responding_to_security_incidents.md)
@@ -241,4 +240,4 @@ who are aware of the risks.
- [Testing with OpenSSL](https://www.feistyduck.com/library/openssl-cookbook/online/testing-with-openssl/index.html)
- [`strace` zine](https://wizardzines.com/zines/strace/)
- GitLab.com-specific resources:
- - [Group SAML/SCIM setup](troubleshooting/group_saml_scim.md)
+ - [Example group SAML and SCIM configurations](../user/group/saml_sso/example_saml_config.md)
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 5158e2bbdd9..31434a8ee6f 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -639,6 +639,7 @@ setting is used:
| `ci_max_artifact_size_secret_detection` | 0 |
| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) |
| `ci_max_artifact_size_trace` | 0 |
+| `ci_max_artifact_size_cyclonedx` | 1 MB |
For example, to set the `ci_max_artifact_size_junit` limit to 10 MB on a self-managed
installation, run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
@@ -1047,7 +1048,8 @@ The [secure files API](../api/secure_files.md) enforces the following limits:
## Changelog API 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`. Disabled by default.
+> - [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`. Disabled by default.
+> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/33893) in GitLab 15.3.
The [changelog API](../api/repositories.md#add-changelog-data-to-a-changelog-file) enforces the following limits:
diff --git a/doc/administration/integration/mailgun.md b/doc/administration/integration/mailgun.md
index 6b0cb0466fc..c007116d213 100644
--- a/doc/administration/integration/mailgun.md
+++ b/doc/administration/integration/mailgun.md
@@ -18,8 +18,8 @@ After completing the integration, Mailgun `temporary_failure` and `permanent_fai
## Configure your Mailgun domain
-> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the `/-/members/mailgun/permanent_failures` URL in GitLab 15.0.
-> [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the URL to handle both temporary and permanent failures in GitLab 15.0.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the `/-/members/mailgun/permanent_failures` URL in GitLab 15.0.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/359113) the URL to handle both temporary and permanent failures in GitLab 15.0.
Before you can enable Mailgun in GitLab, set up your own Mailgun endpoints to receive the webhooks.
@@ -47,6 +47,6 @@ you're ready to enable the Mailgun integration:
1. On the left sidebar, go to **Settings > General** and expand the **Mailgun** section.
1. Select the **Enable Mailgun** check box.
1. Enter the Mailgun HTTP webhook signing key as described in
- [the Mailgun documentation](https://documentation.mailgun.com/en/latest/user_manual.html#webhooks) and
+ [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.
1. Select **Save changes**.
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 2582df1b0c4..a4ab0e07020 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -533,7 +533,7 @@ review:
WARNING: Uploading artifacts as "archive" to coordinator... failed id=12345 responseStatus=500 Internal Server Error status=500 token=abcd1234
```
-- The [workhorse log](logs.md#workhorse-logs) for an error message similar to:
+- The [workhorse log](logs/index.md#workhorse-logs) for an error message similar to:
```json
{"error":"MissingRegion: could not find region configuration","level":"error","msg":"error uploading S3 session","time":"2021-03-16T22:10:55-04:00"}
diff --git a/doc/administration/libravatar.md b/doc/administration/libravatar.md
index eac7c6f848b..88a46759924 100644
--- a/doc/administration/libravatar.md
+++ b/doc/administration/libravatar.md
@@ -11,63 +11,99 @@ GitLab by default supports the [Gravatar](https://gravatar.com) avatar service.
Libravatar is another service that delivers your avatar (profile picture) to
other websites. The Libravatar API is
-[heavily based on gravatar](https://wiki.libravatar.org/api/), so you can
+[heavily based on Gravatar](https://wiki.libravatar.org/api/), so you can
switch to the Libravatar avatar service or even your own Libravatar
server.
-## Configuration
+You cannot use any Libravatar service including Gravatar in [FIPS mode](../development/fips_compliance.md).
-In the [`gitlab.yml` gravatar section](https://gitlab.com/gitlab-org/gitlab/-/blob/672bd3902d86b78d730cea809fce312ec49d39d7/config/gitlab.yml.example#L122), set
+## Change the Libravatar service to your own service
+
+NOTE:
+You can use only the MD5 hash in the URL for the Libravatar service. See [issue 370057](https://gitlab.com/gitlab-org/gitlab/-/issues/370057) for adding SHA-256 support.
+
+In the [`gitlab.yml` gravatar section](https://gitlab.com/gitlab-org/gitlab/-/blob/68dac188ec6b1b03d53365e7579422f44cbe7a1c/config/gitlab.yml.example#L469-476), set
the configuration options as follows:
-### For HTTP
+**For Omnibus installations**
-```yaml
- gravatar:
- enabled: true
- # gravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
- plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
-```
+1. Edit `/etc/gitlab/gitlab.rb`:
-### For HTTPS
+ ```ruby
+ gitlab_rails['gravatar_enabled'] = true
+ #### For HTTPS
+ gitlab_rails['gravatar_ssl_url'] = "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
+ #### Use this line instead for HTTP
+ # gitlab_rails['gravatar_plain_url'] = "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
+ ```
-```yaml
- gravatar:
- enabled: true
- # gravatar URLs: possible placeholders: %{hash} %{size} %{email} %{username}
- ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
-```
+1. To apply the changes, run `sudo gitlab-ctl reconfigure`.
-### Your own Libravatar server
+**For installations from source**
-If you are [running your own Libravatar service](https://wiki.libravatar.org/running_your_own/),
-the URL is different in the configuration, but you must provide the same
-placeholders so GitLab can parse the URL correctly.
+1. Edit `config/gitlab.yml`:
-For example, you host a service on `http://libravatar.example.com` and the
-`plain_url` you must supply in `gitlab.yml` is
+ ```yaml
+ gravatar:
+ enabled: true
+ # default: https://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
+ plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
+ # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
+ ssl_url: https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
+ ```
-`http://libravatar.example.com/avatar/%{hash}?s=%{size}&d=identicon`
+1. Save the file, and then [restart](restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
-### Omnibus GitLab example
+## Set the Libravatar service to default (Gravatar)
-In `/etc/gitlab/gitlab.rb`:
+**For Omnibus installations**
-#### For HTTP
+1. Delete `gitlab_rails['gravatar_ssl_url']` or `gitlab_rails['gravatar_plain_url']` from `/etc/gitlab/gitlab.rb`.
+1. To apply the changes, run `sudo gitlab-ctl reconfigure`.
-```ruby
-gitlab_rails['gravatar_enabled'] = true
-gitlab_rails['gravatar_plain_url'] = "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
-```
+**For installations from source**
-#### For HTTPS
+1. Remove `gravatar:` section from `config/gitlab.yml`.
+1. Save the file, then [restart](restart_gitlab.md#installations-from-source)
+ GitLab to apply the changes.
-```ruby
-gitlab_rails['gravatar_enabled'] = true
-gitlab_rails['gravatar_ssl_url'] = "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
-```
+## Disable Gravatar service
+
+To disable Gravatar, for example, to prohibit third-party services, complete the following steps:
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['gravatar_enabled'] = false
+ ```
+
+1. To apply the changes, run `sudo gitlab-ctl reconfigure`.
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ gravatar:
+ enabled: false
+ ```
+
+1. Save the file, then [restart](restart_gitlab.md#installations-from-source)
+ GitLab to apply the changes.
+
+### Your own Libravatar server
+
+If you are [running your own Libravatar service](https://wiki.libravatar.org/running_your_own/),
+the URL is different in the configuration, but you must provide the same
+placeholders so GitLab can parse the URL correctly.
+
+For example, you host a service on `https://libravatar.example.com` and the
+`ssl_url` you must supply in `gitlab.yml` is:
-Then run `sudo gitlab-ctl reconfigure` for the changes to take effect.
+`https://libravatar.example.com/avatar/%{hash}?s=%{size}&d=identicon`
## Default URL for missing images
@@ -77,7 +113,7 @@ service.
To use a set other than `identicon`, replace the `&d=identicon` portion of the
URL with another supported set. For example, you can use the `retro` set, in
-which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
+which case the URL would look like: `ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
## Usage examples for Microsoft Office 365
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 671c264ed85..7264cf6db98 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -1,1178 +1,11 @@
---
-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
+redirect_to: 'logs/index.md'
+remove_date: '2022-10-23'
---
-# Log system **(FREE SELF)**
+This document was moved to [another location](logs/index.md).
-GitLab has an advanced log system where everything is logged, so you
-can analyze your instance using various system log files. In addition to
-system log files, GitLab Enterprise Edition provides [Audit Events](audit_events.md).
-
-System log files are typically plain text in a standard log file format.
-This guide talks about how to read and use these system log files.
-
-Read more about the log system and using the logs:
-
-- [Customize logging on Omnibus GitLab installations](https://docs.gitlab.com/omnibus/settings/logs.html)
-including adjusting log retention, log forwarding,
-switching logs from JSON to plain text logging, and more.
-- [How to parse and analyze JSON logs](troubleshooting/log_parsing.md).
-
-## Log Levels
-
-Each log message has an assigned log level that indicates its importance and verbosity.
-Each logger has an assigned minimum log level.
-A logger emits a log message only if its log level is equal to or above the minimum log level.
-
-The following log levels are supported:
-
-| Level | Name |
-|:------|:----------|
-| 0 | `DEBUG` |
-| 1 | `INFO` |
-| 2 | `WARN` |
-| 3 | `ERROR` |
-| 4 | `FATAL` |
-| 5 | `UNKNOWN` |
-
-GitLab loggers emit all log messages because they are set to `DEBUG` by default.
-
-### Override default log level
-
-You can override the minimum log level for GitLab loggers using the `GITLAB_LOG_LEVEL` environment variable.
-Valid values are either a value of `0` to `5`, or the name of the log level.
-
-Example:
-
-```shell
-GITLAB_LOG_LEVEL=info
-```
-
-For some services, other log levels are in place that are not affected by this setting.
-Some of these services have their own environment variables to override the log level. For example:
-
-| Service | Log level | Environment variable |
-|:---------------------|:----------|:---------------------|
-| GitLab API | `INFO` | |
-| GitLab Cleanup | `INFO` | `DEBUG` |
-| GitLab Doctor | `INFO` | `VERBOSE` |
-| GitLab Export | `INFO` | `EXPORT_DEBUG` |
-| GitLab Geo | `INFO` | |
-| GitLab Import | `INFO` | `IMPORT_DEBUG` |
-| GitLab QA Runtime | `INFO` | `QA_LOG_LEVEL` |
-| Google APIs | `INFO` | |
-| Rack Timeout | `ERROR` | |
-| Sidekiq (server) | `INFO` | |
-| Snowplow Tracker | `FATAL` | |
-| gRPC Client (Gitaly) | `WARN` | `GRPC_LOG_LEVEL` |
-
-## Log Rotation
-
-The logs for a given service may be managed and rotated by:
-
-- `logrotate`
-- `svlogd` (`runit`'s service logging daemon)
-- `logrotate` and `svlogd`
-- Or not at all
-
-The following table includes information about what's responsible for managing and rotating logs for
-the included services. Logs
-[managed by `svlogd`](https://docs.gitlab.com/omnibus/settings/logs.html#runit-logs)
-are written to a file called `current`. The `logrotate` service built into GitLab
-[manages all logs](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
-except those captured by `runit`.
-
-| Log type | Managed by logrotate | Managed by svlogd/runit |
-|:------------------------------------------------|:------------------------|:------------------------|
-| [Alertmanager Logs](#alertmanager-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Crond Logs](#crond-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Gitaly](#gitaly-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
-| [GitLab Exporter for Omnibus](#gitlab-exporter) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [GitLab Pages Logs](#pages-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
-| GitLab Rails | **{check-circle}** Yes | **{dotted-circle}** No |
-| [GitLab Shell Logs](#gitlab-shelllog) | **{check-circle}** Yes | **{dotted-circle}** No |
-| [Grafana Logs](#grafana-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [LogRotate Logs](#logrotate-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Mailroom](#mail_room_jsonlog-default) | **{check-circle}** Yes | **{check-circle}** Yes |
-| [NGINX](#nginx-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
-| [PostgreSQL Logs](#postgresql-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Praefect Logs](#praefect-logs) | **{dotted-circle}** Yes | **{check-circle}** Yes |
-| [Prometheus Logs](#prometheus-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Puma](#puma-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
-| [Redis Logs](#redis-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Registry Logs](#registry-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
-| [Workhorse Logs](#workhorse-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
-
-## `production_json.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/production_json.log`
-- Installations from source: `/home/git/gitlab/log/production_json.log`
-
-It contains a structured log for Rails controller requests received from
-GitLab, thanks to [Lograge](https://github.com/roidrage/lograge/).
-Requests from the API are logged to a separate file in `api_json.log`.
-
-Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
-Line breaks were added to examples for legibility:
-
-```json
-{
- "method":"GET",
- "path":"/gitlab/gitlab-foss/issues/1234",
- "format":"html",
- "controller":"Projects::IssuesController",
- "action":"show",
- "status":200,
- "time":"2017-08-08T20:15:54.821Z",
- "params":[{"key":"param_key","value":"param_value"}],
- "remote_ip":"18.245.0.1",
- "user_id":1,
- "username":"admin",
- "queue_duration_s":0.0,
- "gitaly_calls":16,
- "gitaly_duration_s":0.16,
- "redis_calls":115,
- "redis_duration_s":0.13,
- "redis_read_bytes":1507378,
- "redis_write_bytes":2920,
- "correlation_id":"O1SdybnnIq7",
- "cpu_s":17.50,
- "db_duration_s":0.08,
- "view_duration_s":2.39,
- "duration_s":20.54,
- "pid": 81836,
- "worker_id":"puma_0"
-}
-```
-
-This example was a GET request for a specific
-issue. Each line also contains performance data, with times in
-seconds:
-
-- `duration_s`: Total time to retrieve the request
-- `queue_duration_s`: Total time the request was queued inside GitLab Workhorse
-- `view_duration_s`: Total time inside the Rails views
-- `db_duration_s`: Total time to retrieve data from PostgreSQL
-- `cpu_s`: Total time spent on CPU
-- `gitaly_duration_s`: Total time by Gitaly calls
-- `gitaly_calls`: Total number of calls made to Gitaly
-- `redis_calls`: Total number of calls made to Redis
-- `redis_duration_s`: Total time to retrieve data from Redis
-- `redis_read_bytes`: Total bytes read from Redis
-- `redis_write_bytes`: Total bytes written to Redis
-- `redis_<instance>_calls`: Total number of calls made to a Redis instance
-- `redis_<instance>_duration_s`: Total time to retrieve data from a Redis instance
-- `redis_<instance>_read_bytes`: Total bytes read from a Redis instance
-- `redis_<instance>_write_bytes`: Total bytes written to a Redis instance
-- `pid`: The worker's Linux process ID (changes when workers restart)
-- `worker_id`: The worker's logical ID (does not change when workers restart)
-
-User clone and fetch activity using HTTP transport appears in the log as `action: git_upload_pack`.
-
-In addition, the log contains the originating IP address,
-(`remote_ip`), the user's ID (`user_id`), and username (`username`).
-
-Some endpoints (such as `/search`) may make requests to Elasticsearch if using
-[Advanced Search](../user/search/advanced_search.md). These
-additionally log `elasticsearch_calls` and `elasticsearch_call_duration_s`,
-which correspond to:
-
-- `elasticsearch_calls`: Total number of calls to Elasticsearch
-- `elasticsearch_duration_s`: Total time taken by Elasticsearch calls
-- `elasticsearch_timed_out_count`: Total number of calls to Elasticsearch that
- timed out and therefore returned partial results
-
-ActionCable connection and subscription events are also logged to this file and they follow the
-previous format. The `method`, `path`, and `format` fields are not applicable, and are always empty.
-The ActionCable connection or channel class is used as the `controller`.
-
-```json
-{
- "method":null,
- "path":null,
- "format":null,
- "controller":"IssuesChannel",
- "action":"subscribe",
- "status":200,
- "time":"2020-05-14T19:46:22.008Z",
- "params":[{"key":"project_path","value":"gitlab/gitlab-foss"},{"key":"iid","value":"1"}],
- "remote_ip":"127.0.0.1",
- "user_id":1,
- "username":"admin",
- "ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0",
- "correlation_id":"jSOIEynHCUa",
- "duration_s":0.32566
-}
-```
-
-NOTE:
-Starting with GitLab 12.5, if an error occurs, an
-`exception` field is included with `class`, `message`, and
-`backtrace`. Previous versions included an `error` field instead of
-`exception.class` and `exception.message`. For example:
-
-```json
-{
- "method": "GET",
- "path": "/admin",
- "format": "html",
- "controller": "Admin::DashboardController",
- "action": "index",
- "status": 500,
- "time": "2019-11-14T13:12:46.156Z",
- "params": [],
- "remote_ip": "127.0.0.1",
- "user_id": 1,
- "username": "root",
- "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0",
- "queue_duration": 274.35,
- "correlation_id": "KjDVUhNvvV3",
- "queue_duration_s":0.0,
- "gitaly_calls":16,
- "gitaly_duration_s":0.16,
- "redis_calls":115,
- "redis_duration_s":0.13,
- "correlation_id":"O1SdybnnIq7",
- "cpu_s":17.50,
- "db_duration_s":0.08,
- "view_duration_s":2.39,
- "duration_s":20.54,
- "pid": 81836,
- "worker_id": "puma_0",
- "exception.class": "NameError",
- "exception.message": "undefined local variable or method `adsf' for #<Admin::DashboardController:0x00007ff3c9648588>",
- "exception.backtrace": [
- "app/controllers/admin/dashboard_controller.rb:11:in `index'",
- "ee/app/controllers/ee/admin/dashboard_controller.rb:14:in `index'",
- "ee/lib/gitlab/ip_address_state.rb:10:in `with'",
- "ee/app/controllers/ee/application_controller.rb:43:in `set_current_ip_address'",
- "lib/gitlab/session.rb:11:in `with_session'",
- "app/controllers/application_controller.rb:450:in `set_session_storage'",
- "app/controllers/application_controller.rb:444:in `set_locale'",
- "ee/lib/gitlab/jira/middleware.rb:19:in `call'"
- ]
-}
-```
-
-## `production.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/production.log`
-- Installations from source: `/home/git/gitlab/log/production.log`
-
-It contains information about all performed requests. You can see the
-URL and type of request, IP address, and what parts of code were
-involved to service this particular request. Also, you can see all SQL
-requests performed, and how much time each took. This task is
-more useful for GitLab contributors and developers. Use part of this log
-file when you're reporting bugs. For example:
-
-```plaintext
-Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200
-Processing by Projects::TreeController#show as HTML
- Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"}
-
- ... [CUT OUT]
-
- Namespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1 [["id", 26]]
- CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]]
- CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members".
- (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["target_project_id", 18]]
- Rendered layouts/nav/_project.html.haml (28.0ms)
- Rendered layouts/_collapse_button.html.haml (0.2ms)
- Rendered layouts/_flash.html.haml (0.1ms)
- Rendered layouts/_page.html.haml (32.9ms)
-Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms)
-```
-
-In this example, the server processed an HTTP request with URL
-`/gitlabhq/yaml_db/tree/master` from IP `168.111.56.1` at `2015-02-12 19:34:53 +0200`.
-The request was processed by `Projects::TreeController`.
-
-## `api_json.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/api_json.log`
-- Installations from source: `/home/git/gitlab/log/api_json.log`
-
-It helps you see requests made directly to the API. For example:
-
-```json
-{
- "time":"2018-10-29T12:49:42.123Z",
- "severity":"INFO",
- "duration":709.08,
- "db":14.59,
- "view":694.49,
- "status":200,
- "method":"GET",
- "path":"/api/v4/projects",
- "params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}],
- "host":"localhost",
- "remote_ip":"::1",
- "ua":"Ruby",
- "route":"/api/:version/projects",
- "user_id":1,
- "username":"root",
- "queue_duration":100.31,
- "gitaly_calls":30,
- "gitaly_duration":5.36,
- "pid": 81836,
- "worker_id": "puma_0",
- ...
-}
-```
-
-This entry shows an internal endpoint accessed to check whether an
-associated SSH key can download the project in question by using a `git fetch` or
-`git clone`. In this example, we see:
-
-- `duration`: Total time in milliseconds to retrieve the request
-- `queue_duration`: Total time in milliseconds the request was queued inside GitLab Workhorse
-- `method`: The HTTP method used to make the request
-- `path`: The relative path of the query
-- `params`: Key-value pairs passed in a query string or HTTP body (sensitive parameters, such as passwords and tokens, are filtered out)
-- `ua`: The User-Agent of the requester
-
-## `application.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/application.log`
-- Installations from source: `/home/git/gitlab/log/application.log`
-
-It helps you discover events happening in your instance such as user creation
-and project deletion. For example:
-
-```plaintext
-October 06, 2014 11:56: User "Administrator" (admin@example.com) was created
-October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore"
-October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce"
-October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was removed
-October 07, 2014 11:25: Project "project133" was removed
-```
-
-## `application_json.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22812) in GitLab 12.7.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/application_json.log`
-- Installations from source: `/home/git/gitlab/log/application_json.log`
-
-It contains the JSON version of the logs in `application.log`, like this example:
-
-```json
-{
- "severity":"INFO",
- "time":"2020-01-14T13:35:15.466Z",
- "correlation_id":"3823a1550b64417f9c9ed8ee0f48087e",
- "message":"User \"Administrator\" (admin@example.com) was created"
-}
-{
- "severity":"INFO",
- "time":"2020-01-14T13:35:15.466Z",
- "correlation_id":"78e3df10c9a18745243d524540bd5be4",
- "message":"Project \"project133\" was removed"
-}
-```
-
-## `integrations_json.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/integrations_json.log`
-- Installations from source: `/home/git/gitlab/log/integrations_json.log`
-
-It contains information about [integration](../user/project/integrations/index.md)
-activities, such as Jira, Asana, and irker services. It uses JSON format,
-like this example:
-
-```json
-{
- "severity":"ERROR",
- "time":"2018-09-06T14:56:20.439Z",
- "service_class":"Integrations::Jira",
- "project_id":8,
- "project_path":"h5bp/html5-boilerplate",
- "message":"Error sending message",
- "client_url":"http://jira.gitlap.com:8080",
- "error":"execution expired"
-}
-{
- "severity":"INFO",
- "time":"2018-09-06T17:15:16.365Z",
- "service_class":"Integrations::Jira",
- "project_id":3,
- "project_path":"namespace2/project2",
- "message":"Successfully posted",
- "client_url":"http://jira.example.com"
-}
-```
-
-## `kubernetes.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/kubernetes.log`
-- Installations from source: `/home/git/gitlab/log/kubernetes.log`
-
-It logs information related to the Kubernetes Integration, including errors
-during installing cluster applications on your managed Kubernetes
-clusters.
-
-Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
-Line breaks have been added to the following example for clarity:
-
-```json
-{
- "severity":"ERROR",
- "time":"2018-11-23T15:14:54.652Z",
- "exception":"Kubeclient::HttpError",
- "error_code":401,
- "service":"Clusters::Applications::CheckInstallationProgressService",
- "app_id":14,
- "project_ids":[1],
- "group_ids":[],
- "message":"Unauthorized"
-}
-{
- "severity":"ERROR",
- "time":"2018-11-23T15:42:11.647Z",
- "exception":"Kubeclient::HttpError",
- "error_code":null,
- "service":"Clusters::Applications::InstallService",
- "app_id":2,
- "project_ids":[19],
- "group_ids":[],
- "message":"SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)"
-}
-```
-
-## `git_json.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/git_json.log`
-- Installations from source: `/home/git/gitlab/log/git_json.log`
-
-After GitLab version 12.2, this file was renamed from `githost.log` to
-`git_json.log` and stored in JSON format.
-
-GitLab has to interact with Git repositories, but in some rare cases
-something can go wrong. If this happens, you need to know exactly what
-happened. This log file contains all failed requests from GitLab to Git
-repositories. In the majority of cases this file is useful for developers
-only. For example:
-
-```json
-{
- "severity":"ERROR",
- "time":"2019-07-19T22:16:12.528Z",
- "correlation_id":"FeGxww5Hj64",
- "message":"Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict\n\nerror: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'"
-}
-```
-
-## `audit_json.log` **(FREE)**
-
-NOTE:
-GitLab Free tracks a small number of different audit events.
-GitLab Premium tracks many more.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/audit_json.log`
-- Installations from source: `/home/git/gitlab/log/audit_json.log`
-
-Changes to group or project settings and memberships (`target_details`)
-are logged to this file. For example:
-
-```json
-{
- "severity":"INFO",
- "time":"2018-10-17T17:38:22.523Z",
- "author_id":3,
- "entity_id":2,
- "entity_type":"Project",
- "change":"visibility",
- "from":"Private",
- "to":"Public",
- "author_name":"John Doe4",
- "target_id":2,
- "target_type":"Project",
- "target_details":"namespace2/project2"
-}
-```
-
-## Sidekiq Logs
-
-NOTE:
-In Omnibus GitLab `12.10` or earlier, the Sidekiq log is at `/var/log/gitlab/gitlab-rails/sidekiq.log`.
-
-For Omnibus GitLab installations, some Sidekiq logs are in `/var/log/gitlab/sidekiq/current`
-and as follows.
-
-### `sidekiq.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/sidekiq/current`
-- Installations from source: `/home/git/gitlab/log/sidekiq.log`
-
-GitLab uses background jobs for processing tasks which can take a long
-time. All information about processing these jobs are written down to
-this file. For example:
-
-```plaintext
-2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read'
-2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"}
-```
-
-Instead of the previous format, you can opt to generate JSON logs for
-Sidekiq. For example:
-
-```json
-{
- "severity":"INFO",
- "time":"2018-04-03T22:57:22.071Z",
- "queue":"cronjob:update_all_mirrors",
- "args":[],
- "class":"UpdateAllMirrorsWorker",
- "retry":false,
- "queue_namespace":"cronjob",
- "jid":"06aeaa3b0aadacf9981f368e",
- "created_at":"2018-04-03T22:57:21.930Z",
- "enqueued_at":"2018-04-03T22:57:21.931Z",
- "pid":10077,
- "worker_id":"sidekiq_0",
- "message":"UpdateAllMirrorsWorker JID-06aeaa3b0aadacf9981f368e: done: 0.139 sec",
- "job_status":"done",
- "duration":0.139,
- "completed_at":"2018-04-03T22:57:22.071Z",
- "db_duration":0.05,
- "db_duration_s":0.0005,
- "gitaly_duration":0,
- "gitaly_calls":0
-}
-```
-
-For Omnibus GitLab installations, add the configuration option:
-
-```ruby
-sidekiq['log_format'] = 'json'
-```
-
-For installations from source, edit the `gitlab.yml` and set the Sidekiq
-`log_format` configuration option:
-
-```yaml
- ## Sidekiq
- sidekiq:
- log_format: json
-```
-
-### `sidekiq_client.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26586) in GitLab 12.9.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/sidekiq_client.log`
-- Installations from source: `/home/git/gitlab/log/sidekiq_client.log`
-
-This file contains logging information about jobs before Sidekiq starts
-processing them, such as before being enqueued.
-
-This log file follows the same structure as
-[`sidekiq.log`](#sidekiqlog), so it is structured as JSON if
-you've configured this for Sidekiq as mentioned above.
-
-## `gitlab-shell.log`
-
-GitLab Shell is used by GitLab for executing Git commands and provide SSH
-access to Git repositories.
-
-### For GitLab versions 12.10 and up
-
-Information containing `git-{upload-pack,receive-pack}` requests is at
-`/var/log/gitlab/gitlab-shell/gitlab-shell.log`. Information about hooks to
-GitLab Shell from Gitaly is at `/var/log/gitlab/gitaly/current`.
-
-Example log entries for `/var/log/gitlab/gitlab-shell/gitlab-shell.log`:
-
-```json
-{
- "duration_ms": 74.104,
- "level": "info",
- "method": "POST",
- "msg": "Finished HTTP request",
- "time": "2020-04-17T20:28:46Z",
- "url": "http://127.0.0.1:8080/api/v4/internal/allowed"
-}
-{
- "command": "git-upload-pack",
- "git_protocol": "",
- "gl_project_path": "root/example",
- "gl_repository": "project-1",
- "level": "info",
- "msg": "executing git command",
- "time": "2020-04-17T20:28:46Z",
- "user_id": "user-1",
- "username": "root"
-}
-```
-
-Example log entries for `/var/log/gitlab/gitaly/current`:
-
-```json
-{
- "method": "POST",
- "url": "http://127.0.0.1:8080/api/v4/internal/allowed",
- "duration": 0.058012959,
- "gitaly_embedded": true,
- "pid": 16636,
- "level": "info",
- "msg": "finished HTTP request",
- "time": "2020-04-17T20:29:08+00:00"
-}
-{
- "method": "POST",
- "url": "http://127.0.0.1:8080/api/v4/internal/pre_receive",
- "duration": 0.031022552,
- "gitaly_embedded": true,
- "pid": 16636,
- "level": "info",
- "msg": "finished HTTP request",
- "time": "2020-04-17T20:29:08+00:00"
-}
-```
-
-### For GitLab versions 12.5 through 12.9
-
-For GitLab 12.5 to 12.9, depending on your installation method, this
-file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitaly/gitlab-shell.log`
-- Installation from source: `/home/git/gitaly/gitlab-shell.log`
-
-Example log entries:
-
-```json
-{
- "method": "POST",
- "url": "http://127.0.0.1:8080/api/v4/internal/post_receive",
- "duration": 0.031809164,
- "gitaly_embedded": true,
- "pid": 27056,
- "level": "info",
- "msg": "finished HTTP request",
- "time": "2020-04-17T16:24:38+00:00"
-}
-```
-
-### For GitLab 12.5 and earlier
-
-For GitLab 12.5 and earlier, the file is at `/var/log/gitlab/gitlab-shell/gitlab-shell.log`.
-
-Example log entries:
-
-```plaintext
-I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at </var/opt/gitlab/git-data/repositories/root/dcdcdcdcd.git>.
-I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
-```
-
-User clone/fetch activity using SSH transport appears in this log as
-`executing git command <gitaly-upload-pack...`.
-
-## Gitaly Logs
-
-This file is in `/var/log/gitlab/gitaly/current` and is produced by [runit](http://smarden.org/runit/).
-`runit` is packaged with Omnibus GitLab and a brief explanation of its purpose
-is available [in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/architecture/#runit).
-[Log files are rotated](http://smarden.org/runit/svlogd.8.html), renamed in
-Unix timestamp format, and `gzip`-compressed (like `@1584057562.s`).
-
-### `grpc.log`
-
-This file is at `/var/log/gitlab/gitlab-rails/grpc.log` for Omnibus GitLab
-packages. Native [gRPC](https://grpc.io/) logging used by Gitaly.
-
-### `gitaly_ruby_json.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2678) in GitLab 13.6.
-
-This file is at `/var/log/gitlab/gitaly/gitaly_ruby_json.log` and is
-produced by [`gitaly-ruby`](gitaly/reference.md#gitaly-ruby). It contains an
-access log of gRPC calls made by Gitaly to `gitaly-ruby`.
-
-### `gitaly_hooks.log`
-
-This file is at `/var/log/gitlab/gitaly/gitaly_hooks.log` and is
-produced by `gitaly-hooks` command. It also contains records about
-failures received during processing of the responses from GitLab API.
-
-## Puma Logs
-
-### `puma_stdout.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/puma/puma_stdout.log`
-- Installations from source: `/home/git/gitlab/log/puma_stdout.log`
-
-### `puma_stderr.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/puma/puma_stderr.log`
-- Installations from source: `/home/git/gitlab/log/puma_stderr.log`
-
-## `repocheck.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/repocheck.log`
-- Installations from source: `/home/git/gitlab/log/repocheck.log`
-
-It logs information whenever a [repository check is run](repository_checks.md)
-on a project.
-
-## `importer.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/importer.log`
-- Installations from source: `/home/git/gitlab/log/importer.log`
-
-It logs the progress of the import process.
-
-## `exporter.log`
-
-> Introduced in GitLab 13.1.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/exporter.log`
-- Installations from source: `/home/git/gitlab/log/exporter.log`
-
-It logs the progress of the export process.
-
-## `features_json.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 13.7.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/features_json.log`
-- Installations from source: `/home/git/gitlab/log/features_json.log`
-
-The modification events from [Feature flags in development of GitLab](../development/feature_flags/index.md)
-are recorded in this file. For example:
-
-```json
-{"severity":"INFO","time":"2020-11-24T02:30:59.860Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"true"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.108Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"true"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.129Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable","extra.thing":"false"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.177Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"Project:1"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.183Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable","extra.thing":"Project:1"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.188Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable_percentage_of_time","extra.percentage":"50"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.193Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable_percentage_of_time"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.198Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable_percentage_of_actors","extra.percentage":"50"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.203Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable_percentage_of_actors"}
-{"severity":"INFO","time":"2020-11-24T02:31:29.329Z","correlation_id":null,"key":"cd_auto_rollback","action":"remove"}
-```
-
-## `auth.log`
-
-> Introduced in GitLab 12.0.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/auth.log`
-- Installations from source: `/home/git/gitlab/log/auth.log`
-
-This log records:
-
-- Requests over the [Rate Limit](../user/admin_area/settings/rate_limits_on_raw_endpoints.md) on raw endpoints.
-- [Protected paths](../user/admin_area/settings/protected_paths.md) abusive requests.
-- In GitLab versions [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239) and later,
- user ID and username, if available.
-
-## `graphql_json.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 12.0.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/graphql_json.log`
-- Installations from source: `/home/git/gitlab/log/graphql_json.log`
-
-GraphQL queries are recorded in the file. For example:
-
-```json
-{"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration_s":7}
-```
-
-## `migrations.log`
-
-> Introduced in GitLab 12.3.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/migrations.log`
-- Installations from source: `/home/git/gitlab/log/migrations.log`
-
-## `mail_room_json.log` (default)
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19186) in GitLab 12.6.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/mailroom/current`
-- Installations from source: `/home/git/gitlab/log/mail_room_json.log`
-
-This structured log file records internal activity in the `mail_room` gem.
-Its name and path are configurable, so the name and path may not match the above.
-
-## Reconfigure logs
-
-Reconfigure log files are in `/var/log/gitlab/reconfigure` for Omnibus GitLab
-packages. Installations from source don't have reconfigure logs. A reconfigure log
-is populated whenever `gitlab-ctl reconfigure` is run manually or as part of an upgrade.
-
-Reconfigure logs files are named according to the UNIX timestamp of when the reconfigure
-was initiated, such as `1509705644.log`
-
-## `sidekiq_exporter.log` and `web_exporter.log`
-
-If Prometheus metrics and the Sidekiq Exporter are both enabled, Sidekiq
-starts a Web server and listen to the defined port (default:
-`8082`). By default, Sidekiq Exporter access logs are disabled but can
-be enabled based on your installation method:
-
-- Omnibus GitLab: Use the `sidekiq['exporter_log_enabled'] = true`
- option in `/etc/gitlab/gitlab.rb`
-- Installations from source: Use the `sidekiq_exporter.log_enabled` option
- in `gitlab.yml`
-
-When enabled, depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/sidekiq_exporter.log`
-- Installations from source: `/home/git/gitlab/log/sidekiq_exporter.log`
-
-If Prometheus metrics and the Web Exporter are both enabled, Puma
-starts a Web server and listen to the defined port (default: `8083`), and access logs
-are generated in a location based on your installation method:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/web_exporter.log`
-- Installations from source: `/home/git/gitlab/log/web_exporter.log`
-
-## `database_load_balancing.log` **(PREMIUM SELF)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) in GitLab 12.3.
-
-Contains details of GitLab [Database Load Balancing](postgresql/database_load_balancing.md).
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/database_load_balancing.log`
-- Installations from source: `/home/git/gitlab/log/database_load_balancing.log`
-
-## `elasticsearch.log` **(PREMIUM SELF)**
-
-> Introduced in GitLab 12.6.
-
-This file logs information related to the Elasticsearch Integration, including
-errors during indexing or searching Elasticsearch. Depending on your installation
-method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/elasticsearch.log`
-- Installations from source: `/home/git/gitlab/log/elasticsearch.log`
-
-Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
-Line breaks have been added to the following example line for clarity:
-
-```json
-{
- "severity":"DEBUG",
- "time":"2019-10-17T06:23:13.227Z",
- "correlation_id":null,
- "message":"redacted_search_result",
- "class_name":"Milestone",
- "id":2,
- "ability":"read_milestone",
- "current_user_id":2,
- "query":"project"
-}
-```
-
-## `exceptions_json.log`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819) in GitLab 12.6.
-
-This file logs the information about exceptions being tracked by
-`Gitlab::ErrorTracking`, which provides a standard and consistent way of
-[processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/logging.md#exception-handling).
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/exceptions_json.log`
-- Installations from source: `/home/git/gitlab/log/exceptions_json.log`
-
-Each line contains JSON that can be ingested by Elasticsearch. For example:
-
-```json
-{
- "severity": "ERROR",
- "time": "2019-12-17T11:49:29.485Z",
- "correlation_id": "AbDVUrrTvM1",
- "extra.project_id": 55,
- "extra.relation_key": "milestones",
- "extra.relation_index": 1,
- "exception.class": "NoMethodError",
- "exception.message": "undefined method `strong_memoize' for #<Gitlab::ImportExport::RelationFactory:0x00007fb5d917c4b0>",
- "exception.backtrace": [
- "lib/gitlab/import_export/relation_factory.rb:329:in `unique_relation?'",
- "lib/gitlab/import_export/relation_factory.rb:345:in `find_or_create_object!'"
- ]
-}
-```
-
-## `service_measurement.log`
-
-> Introduced in GitLab 13.0.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/service_measurement.log`
-- Installations from source: `/home/git/gitlab/log/service_measurement.log`
-
-It contains only a single structured log with measurements for each service execution.
-It contains measurements such as the number of SQL calls, `execution_time`, `gc_stats`, and `memory usage`.
-
-For example:
-
-```json
-{ "severity":"INFO", "time":"2020-04-22T16:04:50.691Z","correlation_id":"04f1366e-57a1-45b8-88c1-b00b23dc3616","class":"Projects::ImportExport::ExportService","current_user":"John Doe","project_full_path":"group1/test-export","file_path":"/path/to/archive","gc_stats":{"count":{"before":127,"after":127,"diff":0},"heap_allocated_pages":{"before":10369,"after":10369,"diff":0},"heap_sorted_length":{"before":10369,"after":10369,"diff":0},"heap_allocatable_pages":{"before":0,"after":0,"diff":0},"heap_available_slots":{"before":4226409,"after":4226409,"diff":0},"heap_live_slots":{"before":2542709,"after":2641420,"diff":98711},"heap_free_slots":{"before":1683700,"after":1584989,"diff":-98711},"heap_final_slots":{"before":0,"after":0,"diff":0},"heap_marked_slots":{"before":2542704,"after":2542704,"diff":0},"heap_eden_pages":{"before":10369,"after":10369,"diff":0},"heap_tomb_pages":{"before":0,"after":0,"diff":0},"total_allocated_pages":{"before":10369,"after":10369,"diff":0},"total_freed_pages":{"before":0,"after":0,"diff":0},"total_allocated_objects":{"before":24896308,"after":24995019,"diff":98711},"total_freed_objects":{"before":22353599,"after":22353599,"diff":0},"malloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"malloc_increase_bytes_limit":{"before":25804104,"after":25804104,"diff":0},"minor_gc_count":{"before":94,"after":94,"diff":0},"major_gc_count":{"before":33,"after":33,"diff":0},"remembered_wb_unprotected_objects":{"before":34284,"after":34284,"diff":0},"remembered_wb_unprotected_objects_limit":{"before":68568,"after":68568,"diff":0},"old_objects":{"before":2404725,"after":2404725,"diff":0},"old_objects_limit":{"before":4809450,"after":4809450,"diff":0},"oldmalloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"oldmalloc_increase_bytes_limit":{"before":68537556,"after":68537556,"diff":0}},"time_to_finish":0.12298400001600385,"number_of_sql_calls":70,"memory_usage":"0.0 MiB","label":"process_48616"}
-```
-
-## `geo.log` **(PREMIUM SELF)**
-
-Geo stores structured log messages in a `geo.log` file. For Omnibus GitLab
-installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
-
-This file contains information about when Geo attempts to sync repositories
-and files. Each line in the file contains a separate JSON entry that can be
-ingested into (for example, Elasticsearch or Splunk).
-
-For example:
-
-```json
-{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038}
-```
-
-This message shows that Geo detected that a repository update was needed for project `1`.
-
-## `update_mirror_service_json.log`
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/update_mirror_service_json.log`
-- Installations from source: `/home/git/gitlab/log/update_mirror_service_json.log`
-
-This file contains information about LFS errors that occurred during project mirroring.
-While we work to move other project mirroring errors into this log, the [general log](#productionlog)
-can be used.
-
-```json
-{
- "severity":"ERROR",
- "time":"2020-07-28T23:29:29.473Z",
- "correlation_id":"5HgIkCJsO53",
- "user_id":"x",
- "project_id":"x",
- "import_url":"https://mirror-source/group/project.git",
- "error_message":"The LFS objects download list couldn't be imported. Error: Unauthorized"
-}
-```
-
-## Registry Logs
-
-For Omnibus GitLab installations, Container Registry logs are in `/var/log/gitlab/registry/current`.
-
-## NGINX Logs
-
-For Omnibus GitLab installations, NGINX logs are in:
-
-- `/var/log/gitlab/nginx/gitlab_access.log`: A log of requests made to GitLab
-- `/var/log/gitlab/nginx/gitlab_error.log`: A log of NGINX errors for GitLab
-- `/var/log/gitlab/nginx/gitlab_pages_access.log`: A log of requests made to Pages static sites
-- `/var/log/gitlab/nginx/gitlab_pages_error.log`: A log of NGINX errors for Pages static sites
-- `/var/log/gitlab/nginx/gitlab_registry_access.log`: A log of requests made to the Container Registry
-- `/var/log/gitlab/nginx/gitlab_registry_error.log`: A log of NGINX errors for the Container Registry
-- `/var/log/gitlab/nginx/gitlab_mattermost_access.log`: A log of requests made to Mattermost
-- `/var/log/gitlab/nginx/gitlab_mattermost_error.log`: A log of NGINX errors for Mattermost
-
-Below is the default GitLab NGINX access log format:
-
-```plaintext
-$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"
-```
-
-## Pages Logs
-
-For Omnibus GitLab installations, Pages logs are in `/var/log/gitlab/gitlab-pages/current`.
-
-For example:
-
-```json
-{
- "level": "info",
- "msg": "GitLab Pages Daemon",
- "revision": "52b2899",
- "time": "2020-04-22T17:53:12Z",
- "version": "1.17.0"
-}
-{
- "level": "info",
- "msg": "URL: https://gitlab.com/gitlab-org/gitlab-pages",
- "time": "2020-04-22T17:53:12Z"
-}
-{
- "gid": 998,
- "in-place": false,
- "level": "info",
- "msg": "running the daemon as unprivileged user",
- "time": "2020-04-22T17:53:12Z",
- "uid": 998
-}
-```
-
-## Mattermost Logs
-
-For Omnibus GitLab installations, Mattermost logs are in these locations:
-
-- `/var/log/gitlab/mattermost/mattermost.log`
-- `/var/log/gitlab/mattermost/current`
-
-## Workhorse Logs
-
-For Omnibus GitLab installations, Workhorse logs are in `/var/log/gitlab/gitlab-workhorse/current`.
-
-## PostgreSQL Logs
-
-For Omnibus GitLab installations, PostgreSQL logs are in `/var/log/gitlab/postgresql/current`.
-
-## Prometheus Logs
-
-For Omnibus GitLab installations, Prometheus logs are in `/var/log/gitlab/prometheus/current`.
-
-## Redis Logs
-
-For Omnibus GitLab installations, Redis logs are in `/var/log/gitlab/redis/current`.
-
-## Alertmanager Logs
-
-For Omnibus GitLab installations, Alertmanager logs are in `/var/log/gitlab/alertmanager/current`.
-
-<!-- vale gitlab.Spelling = NO -->
-
-## Crond Logs
-
-For Omnibus GitLab installations, crond logs are in `/var/log/gitlab/crond/`.
-
-<!-- vale gitlab.Spelling = YES -->
-
-## Grafana Logs
-
-For Omnibus GitLab installations, Grafana logs are in `/var/log/gitlab/grafana/current`.
-
-## LogRotate Logs
-
-For Omnibus GitLab installations, `logrotate` logs are in `/var/log/gitlab/logrotate/current`.
-
-## GitLab Monitor Logs
-
-For Omnibus GitLab installations, GitLab Monitor logs are in `/var/log/gitlab/gitlab-monitor/`.
-
-## GitLab Exporter
-
-For Omnibus GitLab installations, GitLab Exporter logs are in `/var/log/gitlab/gitlab-exporter/current`.
-
-## GitLab agent server
-
-For Omnibus GitLab installations, GitLab agent server logs are
-in `/var/log/gitlab/gitlab-kas/current`.
-
-## Praefect Logs
-
-For Omnibus GitLab installations, Praefect logs are in `/var/log/gitlab/praefect/`.
-
-GitLab also tracks [Prometheus metrics for Praefect](gitaly/monitoring.md#monitor-gitaly-cluster).
-
-## Backup log
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63832) in GitLab 14.1.
-
-For Omnibus installations, the backup log is located at `/var/log/gitlab/gitlab-rails/backup_json.log`.
-
-This log is populated when a [GitLab backup is created](../raketasks/backup_restore.md). You can use this log to understand how the backup process performed.
-
-## Performance bar stats
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48149) in GitLab 13.7.
-
-Depending on your installation method, this file is located at:
-
-- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/performance_bar_json.log`
-- Installations from source: `/home/git/gitlab/log/performance_bar_json.log`
-
-Performance bar statistics (currently only duration of SQL queries) are recorded
-in that file. For example:
-
-```json
-{"severity":"INFO","time":"2020-12-04T09:29:44.592Z","correlation_id":"33680b1490ccd35981b03639c406a697","filename":"app/models/ci/pipeline.rb","method_path":"app/models/ci/pipeline.rb:each_with_object","request_id":"rYHomD0VJS4","duration_ms":26.889,"count":2,"query_type": "active-record"}
-```
-
-These statistics are logged on .com only, disabled on self-deployments.
-
-## Gathering logs
-
-When [troubleshooting](troubleshooting/index.md) issues that aren't localized to one of the
-previously listed components, it's helpful to simultaneously gather multiple logs and statistics
-from a GitLab instance.
-
-NOTE:
-GitLab Support often asks for one of these, and maintains the required tools.
-
-### Briefly tail the main logs
-
-If the bug or error is readily reproducible, save the main GitLab logs
-[to a file](troubleshooting/linux_cheat_sheet.md#files-and-directories) while reproducing the
-problem a few times:
-
-```shell
-sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
-```
-
-Conclude the log gathering with <kbd>Control</kbd> + <kbd>C</kbd>.
-
-### GitLabSOS
-
-If performance degradations or cascading errors occur that can't readily be attributed to one
-of the previously listed GitLab components, [GitLabSOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/)
-can provide a broader perspective of the GitLab instance. For more details and instructions
-to run it, read [the GitLabSOS documentation](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/#gitlabsos).
-
-### Fast-stats
-
-[Fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats) is a tool
-for creating and comparing performance statistics from GitLab logs.
-For more details and instructions to run it, read the
-[documentation for fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats#usage).
+<!-- This redirect file can be deleted after <2022-10-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 (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/troubleshooting/img/database-query-dialog_v14_3.png b/doc/administration/logs/img/database-query-dialog_v14_3.png
index 197cfa17da2..197cfa17da2 100644
--- a/doc/administration/troubleshooting/img/database-query-dialog_v14_3.png
+++ b/doc/administration/logs/img/database-query-dialog_v14_3.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/network_monitor_xid.png b/doc/administration/logs/img/network_monitor_xid.png
index fa64fd1509c..fa64fd1509c 100644
--- a/doc/administration/troubleshooting/img/network_monitor_xid.png
+++ b/doc/administration/logs/img/network_monitor_xid.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/obtaining-a-session-cookie-for-request_v14_3.png b/doc/administration/logs/img/obtaining-a-session-cookie-for-request_v14_3.png
index a63ebf9ecf2..a63ebf9ecf2 100644
--- a/doc/administration/troubleshooting/img/obtaining-a-session-cookie-for-request_v14_3.png
+++ b/doc/administration/logs/img/obtaining-a-session-cookie-for-request_v14_3.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/paste-request-id-into-progress-bar_v14_3.png b/doc/administration/logs/img/paste-request-id-into-progress-bar_v14_3.png
index a19585d7a89..a19585d7a89 100644
--- a/doc/administration/troubleshooting/img/paste-request-id-into-progress-bar_v14_3.png
+++ b/doc/administration/logs/img/paste-request-id-into-progress-bar_v14_3.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png b/doc/administration/logs/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png
index b8314056c9b..b8314056c9b 100644
--- a/doc/administration/troubleshooting/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png
+++ b/doc/administration/logs/img/select-request-id-from-request-selector-drop-down-menu_v14_3.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/view-pg-details_v14_3.png b/doc/administration/logs/img/view-pg-details_v14_3.png
index 1fe12462e4e..1fe12462e4e 100644
--- a/doc/administration/troubleshooting/img/view-pg-details_v14_3.png
+++ b/doc/administration/logs/img/view-pg-details_v14_3.png
Binary files differ
diff --git a/doc/administration/logs/index.md b/doc/administration/logs/index.md
new file mode 100644
index 00000000000..d3529de08db
--- /dev/null
+++ b/doc/administration/logs/index.md
@@ -0,0 +1,1182 @@
+---
+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
+---
+
+# Log system **(FREE SELF)**
+
+GitLab has an advanced log system where everything is logged, so you
+can analyze your instance using various system log files. In addition to
+system log files, GitLab Enterprise Edition provides [Audit Events](../audit_events.md).
+
+System log files are typically plain text in a standard log file format.
+This guide talks about how to read and use these system log files.
+
+Read more about the log system and using the logs:
+
+- [Customize logging on Omnibus GitLab installations](https://docs.gitlab.com/omnibus/settings/logs.html)
+including adjusting log retention, log forwarding,
+switching logs from JSON to plain text logging, and more.
+- [How to parse and analyze JSON logs](../logs/log_parsing.md).
+
+## Log Levels
+
+Each log message has an assigned log level that indicates its importance and verbosity.
+Each logger has an assigned minimum log level.
+A logger emits a log message only if its log level is equal to or above the minimum log level.
+
+The following log levels are supported:
+
+| Level | Name |
+|:------|:----------|
+| 0 | `DEBUG` |
+| 1 | `INFO` |
+| 2 | `WARN` |
+| 3 | `ERROR` |
+| 4 | `FATAL` |
+| 5 | `UNKNOWN` |
+
+GitLab loggers emit all log messages because they are set to `DEBUG` by default.
+
+### Override default log level
+
+You can override the minimum log level for GitLab loggers using the `GITLAB_LOG_LEVEL` environment variable.
+Valid values are either a value of `0` to `5`, or the name of the log level.
+
+Example:
+
+```shell
+GITLAB_LOG_LEVEL=info
+```
+
+For some services, other log levels are in place that are not affected by this setting.
+Some of these services have their own environment variables to override the log level. For example:
+
+| Service | Log level | Environment variable |
+|:---------------------|:----------|:---------------------|
+| GitLab API | `INFO` | |
+| GitLab Cleanup | `INFO` | `DEBUG` |
+| GitLab Doctor | `INFO` | `VERBOSE` |
+| GitLab Export | `INFO` | `EXPORT_DEBUG` |
+| GitLab Geo | `INFO` | |
+| GitLab Import | `INFO` | `IMPORT_DEBUG` |
+| GitLab QA Runtime | `INFO` | `QA_LOG_LEVEL` |
+| Google APIs | `INFO` | |
+| Rack Timeout | `ERROR` | |
+| Sidekiq (server) | `INFO` | |
+| Snowplow Tracker | `FATAL` | |
+| gRPC Client (Gitaly) | `WARN` | `GRPC_LOG_LEVEL` |
+
+## Log Rotation
+
+The logs for a given service may be managed and rotated by:
+
+- `logrotate`
+- `svlogd` (`runit`'s service logging daemon)
+- `logrotate` and `svlogd`
+- Or not at all
+
+The following table includes information about what's responsible for managing and rotating logs for
+the included services. Logs
+[managed by `svlogd`](https://docs.gitlab.com/omnibus/settings/logs.html#runit-logs)
+are written to a file called `current`. The `logrotate` service built into GitLab
+[manages all logs](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
+except those captured by `runit`.
+
+| Log type | Managed by logrotate | Managed by svlogd/runit |
+|:------------------------------------------------|:------------------------|:------------------------|
+| [Alertmanager Logs](#alertmanager-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Crond Logs](#crond-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Gitaly](#gitaly-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
+| [GitLab Exporter for Omnibus](#gitlab-exporter) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [GitLab Pages Logs](#pages-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
+| GitLab Rails | **{check-circle}** Yes | **{dotted-circle}** No |
+| [GitLab Shell Logs](#gitlab-shelllog) | **{check-circle}** Yes | **{dotted-circle}** No |
+| [Grafana Logs](#grafana-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [LogRotate Logs](#logrotate-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Mailroom](#mail_room_jsonlog-default) | **{check-circle}** Yes | **{check-circle}** Yes |
+| [NGINX](#nginx-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
+| [PostgreSQL Logs](#postgresql-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Praefect Logs](#praefect-logs) | **{dotted-circle}** Yes | **{check-circle}** Yes |
+| [Prometheus Logs](#prometheus-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Puma](#puma-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
+| [Redis Logs](#redis-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Registry Logs](#registry-logs) | **{dotted-circle}** No | **{check-circle}** Yes |
+| [Workhorse Logs](#workhorse-logs) | **{check-circle}** Yes | **{check-circle}** Yes |
+
+## `production_json.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/production_json.log`
+- Installations from source: `/home/git/gitlab/log/production_json.log`
+
+It contains a structured log for Rails controller requests received from
+GitLab, thanks to [Lograge](https://github.com/roidrage/lograge/).
+Requests from the API are logged to a separate file in `api_json.log`.
+
+Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
+Line breaks were added to examples for legibility:
+
+```json
+{
+ "method":"GET",
+ "path":"/gitlab/gitlab-foss/issues/1234",
+ "format":"html",
+ "controller":"Projects::IssuesController",
+ "action":"show",
+ "status":200,
+ "time":"2017-08-08T20:15:54.821Z",
+ "params":[{"key":"param_key","value":"param_value"}],
+ "remote_ip":"18.245.0.1",
+ "user_id":1,
+ "username":"admin",
+ "queue_duration_s":0.0,
+ "gitaly_calls":16,
+ "gitaly_duration_s":0.16,
+ "redis_calls":115,
+ "redis_duration_s":0.13,
+ "redis_read_bytes":1507378,
+ "redis_write_bytes":2920,
+ "correlation_id":"O1SdybnnIq7",
+ "cpu_s":17.50,
+ "db_duration_s":0.08,
+ "view_duration_s":2.39,
+ "duration_s":20.54,
+ "pid": 81836,
+ "worker_id":"puma_0"
+}
+```
+
+This example was a GET request for a specific
+issue. Each line also contains performance data, with times in
+seconds:
+
+- `duration_s`: Total time to retrieve the request
+- `queue_duration_s`: Total time the request was queued inside GitLab Workhorse
+- `view_duration_s`: Total time inside the Rails views
+- `db_duration_s`: Total time to retrieve data from PostgreSQL
+- `cpu_s`: Total time spent on CPU
+- `gitaly_duration_s`: Total time by Gitaly calls
+- `gitaly_calls`: Total number of calls made to Gitaly
+- `redis_calls`: Total number of calls made to Redis
+- `redis_duration_s`: Total time to retrieve data from Redis
+- `redis_read_bytes`: Total bytes read from Redis
+- `redis_write_bytes`: Total bytes written to Redis
+- `redis_<instance>_calls`: Total number of calls made to a Redis instance
+- `redis_<instance>_duration_s`: Total time to retrieve data from a Redis instance
+- `redis_<instance>_read_bytes`: Total bytes read from a Redis instance
+- `redis_<instance>_write_bytes`: Total bytes written to a Redis instance
+- `pid`: The worker's Linux process ID (changes when workers restart)
+- `worker_id`: The worker's logical ID (does not change when workers restart)
+
+User clone and fetch activity using HTTP transport appears in the log as `action: git_upload_pack`.
+
+In addition, the log contains the originating IP address,
+(`remote_ip`), the user's ID (`user_id`), and username (`username`).
+
+Some endpoints (such as `/search`) may make requests to Elasticsearch if using
+[Advanced Search](../../user/search/advanced_search.md). These
+additionally log `elasticsearch_calls` and `elasticsearch_call_duration_s`,
+which correspond to:
+
+- `elasticsearch_calls`: Total number of calls to Elasticsearch
+- `elasticsearch_duration_s`: Total time taken by Elasticsearch calls
+- `elasticsearch_timed_out_count`: Total number of calls to Elasticsearch that
+ timed out and therefore returned partial results
+
+ActionCable connection and subscription events are also logged to this file and they follow the
+previous format. The `method`, `path`, and `format` fields are not applicable, and are always empty.
+The ActionCable connection or channel class is used as the `controller`.
+
+```json
+{
+ "method":null,
+ "path":null,
+ "format":null,
+ "controller":"IssuesChannel",
+ "action":"subscribe",
+ "status":200,
+ "time":"2020-05-14T19:46:22.008Z",
+ "params":[{"key":"project_path","value":"gitlab/gitlab-foss"},{"key":"iid","value":"1"}],
+ "remote_ip":"127.0.0.1",
+ "user_id":1,
+ "username":"admin",
+ "ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0",
+ "correlation_id":"jSOIEynHCUa",
+ "duration_s":0.32566
+}
+```
+
+NOTE:
+Starting with GitLab 12.5, if an error occurs, an
+`exception` field is included with `class`, `message`, and
+`backtrace`. Previous versions included an `error` field instead of
+`exception.class` and `exception.message`. For example:
+
+```json
+{
+ "method": "GET",
+ "path": "/admin",
+ "format": "html",
+ "controller": "Admin::DashboardController",
+ "action": "index",
+ "status": 500,
+ "time": "2019-11-14T13:12:46.156Z",
+ "params": [],
+ "remote_ip": "127.0.0.1",
+ "user_id": 1,
+ "username": "root",
+ "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0",
+ "queue_duration": 274.35,
+ "correlation_id": "KjDVUhNvvV3",
+ "queue_duration_s":0.0,
+ "gitaly_calls":16,
+ "gitaly_duration_s":0.16,
+ "redis_calls":115,
+ "redis_duration_s":0.13,
+ "correlation_id":"O1SdybnnIq7",
+ "cpu_s":17.50,
+ "db_duration_s":0.08,
+ "view_duration_s":2.39,
+ "duration_s":20.54,
+ "pid": 81836,
+ "worker_id": "puma_0",
+ "exception.class": "NameError",
+ "exception.message": "undefined local variable or method `adsf' for #<Admin::DashboardController:0x00007ff3c9648588>",
+ "exception.backtrace": [
+ "app/controllers/admin/dashboard_controller.rb:11:in `index'",
+ "ee/app/controllers/ee/admin/dashboard_controller.rb:14:in `index'",
+ "ee/lib/gitlab/ip_address_state.rb:10:in `with'",
+ "ee/app/controllers/ee/application_controller.rb:43:in `set_current_ip_address'",
+ "lib/gitlab/session.rb:11:in `with_session'",
+ "app/controllers/application_controller.rb:450:in `set_session_storage'",
+ "app/controllers/application_controller.rb:444:in `set_locale'",
+ "ee/lib/gitlab/jira/middleware.rb:19:in `call'"
+ ]
+}
+```
+
+## `production.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/production.log`
+- Installations from source: `/home/git/gitlab/log/production.log`
+
+It contains information about all performed requests. You can see the
+URL and type of request, IP address, and what parts of code were
+involved to service this particular request. Also, you can see all SQL
+requests performed, and how much time each took. This task is
+more useful for GitLab contributors and developers. Use part of this log
+file when you're reporting bugs. For example:
+
+```plaintext
+Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200
+Processing by Projects::TreeController#show as HTML
+ Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"}
+
+ ... [CUT OUT]
+
+ Namespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1 [["id", 26]]
+ CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]]
+ CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members".
+ (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["target_project_id", 18]]
+ Rendered layouts/nav/_project.html.haml (28.0ms)
+ Rendered layouts/_collapse_button.html.haml (0.2ms)
+ Rendered layouts/_flash.html.haml (0.1ms)
+ Rendered layouts/_page.html.haml (32.9ms)
+Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms)
+```
+
+In this example, the server processed an HTTP request with URL
+`/gitlabhq/yaml_db/tree/master` from IP `168.111.56.1` at `2015-02-12 19:34:53 +0200`.
+The request was processed by `Projects::TreeController`.
+
+## `api_json.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/api_json.log`
+- Installations from source: `/home/git/gitlab/log/api_json.log`
+
+It helps you see requests made directly to the API. For example:
+
+```json
+{
+ "time":"2018-10-29T12:49:42.123Z",
+ "severity":"INFO",
+ "duration":709.08,
+ "db":14.59,
+ "view":694.49,
+ "status":200,
+ "method":"GET",
+ "path":"/api/v4/projects",
+ "params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}],
+ "host":"localhost",
+ "remote_ip":"::1",
+ "ua":"Ruby",
+ "route":"/api/:version/projects",
+ "user_id":1,
+ "username":"root",
+ "queue_duration":100.31,
+ "gitaly_calls":30,
+ "gitaly_duration":5.36,
+ "pid": 81836,
+ "worker_id": "puma_0",
+ ...
+}
+```
+
+This entry shows an internal endpoint accessed to check whether an
+associated SSH key can download the project in question by using a `git fetch` or
+`git clone`. In this example, we see:
+
+- `duration`: Total time in milliseconds to retrieve the request
+- `queue_duration`: Total time in milliseconds the request was queued inside GitLab Workhorse
+- `method`: The HTTP method used to make the request
+- `path`: The relative path of the query
+- `params`: Key-value pairs passed in a query string or HTTP body (sensitive parameters, such as passwords and tokens, are filtered out)
+- `ua`: The User-Agent of the requester
+
+## `application.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/application.log`
+- Installations from source: `/home/git/gitlab/log/application.log`
+
+It helps you discover events happening in your instance such as user creation
+and project deletion. For example:
+
+```plaintext
+October 06, 2014 11:56: User "Administrator" (admin@example.com) was created
+October 06, 2014 11:56: Documentcloud created a new project "Documentcloud / Underscore"
+October 06, 2014 11:56: Gitlab Org created a new project "Gitlab Org / Gitlab Ce"
+October 07, 2014 11:25: User "Claudie Hodkiewicz" (nasir_stehr@olson.co.uk) was removed
+October 07, 2014 11:25: Project "project133" was removed
+```
+
+## `application_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22812) in GitLab 12.7.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/application_json.log`
+- Installations from source: `/home/git/gitlab/log/application_json.log`
+
+It contains the JSON version of the logs in `application.log`, like this example:
+
+```json
+{
+ "severity":"INFO",
+ "time":"2020-01-14T13:35:15.466Z",
+ "correlation_id":"3823a1550b64417f9c9ed8ee0f48087e",
+ "message":"User \"Administrator\" (admin@example.com) was created"
+}
+{
+ "severity":"INFO",
+ "time":"2020-01-14T13:35:15.466Z",
+ "correlation_id":"78e3df10c9a18745243d524540bd5be4",
+ "message":"Project \"project133\" was removed"
+}
+```
+
+## `integrations_json.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/integrations_json.log`
+- Installations from source: `/home/git/gitlab/log/integrations_json.log`
+
+It contains information about [integration](../../user/project/integrations/index.md)
+activities, such as Jira, Asana, and irker services. It uses JSON format,
+like this example:
+
+```json
+{
+ "severity":"ERROR",
+ "time":"2018-09-06T14:56:20.439Z",
+ "service_class":"Integrations::Jira",
+ "project_id":8,
+ "project_path":"h5bp/html5-boilerplate",
+ "message":"Error sending message",
+ "client_url":"http://jira.gitlap.com:8080",
+ "error":"execution expired"
+}
+{
+ "severity":"INFO",
+ "time":"2018-09-06T17:15:16.365Z",
+ "service_class":"Integrations::Jira",
+ "project_id":3,
+ "project_path":"namespace2/project2",
+ "message":"Successfully posted",
+ "client_url":"http://jira.example.com"
+}
+```
+
+## `kubernetes.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/kubernetes.log`
+- Installations from source: `/home/git/gitlab/log/kubernetes.log`
+
+It logs information related to the Kubernetes Integration, including errors
+during installing cluster applications on your managed Kubernetes
+clusters.
+
+Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
+Line breaks have been added to the following example for clarity:
+
+```json
+{
+ "severity":"ERROR",
+ "time":"2018-11-23T15:14:54.652Z",
+ "exception":"Kubeclient::HttpError",
+ "error_code":401,
+ "service":"Clusters::Applications::CheckInstallationProgressService",
+ "app_id":14,
+ "project_ids":[1],
+ "group_ids":[],
+ "message":"Unauthorized"
+}
+{
+ "severity":"ERROR",
+ "time":"2018-11-23T15:42:11.647Z",
+ "exception":"Kubeclient::HttpError",
+ "error_code":null,
+ "service":"Clusters::Applications::InstallService",
+ "app_id":2,
+ "project_ids":[19],
+ "group_ids":[],
+ "message":"SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)"
+}
+```
+
+## `git_json.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/git_json.log`
+- Installations from source: `/home/git/gitlab/log/git_json.log`
+
+After GitLab version 12.2, this file was renamed from `githost.log` to
+`git_json.log` and stored in JSON format.
+
+GitLab has to interact with Git repositories, but in some rare cases
+something can go wrong. If this happens, you need to know exactly what
+happened. This log file contains all failed requests from GitLab to Git
+repositories. In the majority of cases this file is useful for developers
+only. For example:
+
+```json
+{
+ "severity":"ERROR",
+ "time":"2019-07-19T22:16:12.528Z",
+ "correlation_id":"FeGxww5Hj64",
+ "message":"Command failed [1]: /usr/bin/git --git-dir=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq/.git --work-tree=/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/group184/gitlabhq merge --no-ff -mMerge branch 'feature_conflict' into 'feature' source/feature_conflict\n\nerror: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'"
+}
+```
+
+## `audit_json.log` **(FREE)**
+
+NOTE:
+GitLab Free tracks a small number of different audit events.
+GitLab Premium tracks many more.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/audit_json.log`
+- Installations from source: `/home/git/gitlab/log/audit_json.log`
+
+Changes to group or project settings and memberships (`target_details`)
+are logged to this file. For example:
+
+```json
+{
+ "severity":"INFO",
+ "time":"2018-10-17T17:38:22.523Z",
+ "author_id":3,
+ "entity_id":2,
+ "entity_type":"Project",
+ "change":"visibility",
+ "from":"Private",
+ "to":"Public",
+ "author_name":"John Doe4",
+ "target_id":2,
+ "target_type":"Project",
+ "target_details":"namespace2/project2"
+}
+```
+
+## Sidekiq Logs
+
+NOTE:
+In Omnibus GitLab `12.10` or earlier, the Sidekiq log is at `/var/log/gitlab/gitlab-rails/sidekiq.log`.
+
+For Omnibus GitLab installations, some Sidekiq logs are in `/var/log/gitlab/sidekiq/current`
+and as follows.
+
+### `sidekiq.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/sidekiq/current`
+- Installations from source: `/home/git/gitlab/log/sidekiq.log`
+
+GitLab uses background jobs for processing tasks which can take a long
+time. All information about processing these jobs are written down to
+this file. For example:
+
+```plaintext
+2014-06-10T07:55:20Z 2037 TID-tm504 ERROR: /opt/bitnami/apps/discourse/htdocs/vendor/bundle/ruby/1.9.1/gems/redis-3.0.7/lib/redis/client.rb:228:in `read'
+2014-06-10T18:18:26Z 14299 TID-55uqo INFO: Booting Sidekiq 3.0.0 with redis options {:url=>"redis://localhost:6379/0", :namespace=>"sidekiq"}
+```
+
+Instead of the previous format, you can opt to generate JSON logs for
+Sidekiq. For example:
+
+```json
+{
+ "severity":"INFO",
+ "time":"2018-04-03T22:57:22.071Z",
+ "queue":"cronjob:update_all_mirrors",
+ "args":[],
+ "class":"UpdateAllMirrorsWorker",
+ "retry":false,
+ "queue_namespace":"cronjob",
+ "jid":"06aeaa3b0aadacf9981f368e",
+ "created_at":"2018-04-03T22:57:21.930Z",
+ "enqueued_at":"2018-04-03T22:57:21.931Z",
+ "pid":10077,
+ "worker_id":"sidekiq_0",
+ "message":"UpdateAllMirrorsWorker JID-06aeaa3b0aadacf9981f368e: done: 0.139 sec",
+ "job_status":"done",
+ "duration":0.139,
+ "completed_at":"2018-04-03T22:57:22.071Z",
+ "db_duration":0.05,
+ "db_duration_s":0.0005,
+ "gitaly_duration":0,
+ "gitaly_calls":0
+}
+```
+
+For Omnibus GitLab installations, add the configuration option:
+
+```ruby
+sidekiq['log_format'] = 'json'
+```
+
+For installations from source, edit the `gitlab.yml` and set the Sidekiq
+`log_format` configuration option:
+
+```yaml
+ ## Sidekiq
+ sidekiq:
+ log_format: json
+```
+
+### `sidekiq_client.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26586) in GitLab 12.9.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/sidekiq_client.log`
+- Installations from source: `/home/git/gitlab/log/sidekiq_client.log`
+
+This file contains logging information about jobs before Sidekiq starts
+processing them, such as before being enqueued.
+
+This log file follows the same structure as
+[`sidekiq.log`](#sidekiqlog), so it is structured as JSON if
+you've configured this for Sidekiq as mentioned above.
+
+## `gitlab-shell.log`
+
+GitLab Shell is used by GitLab for executing Git commands and provide SSH
+access to Git repositories.
+
+### For GitLab versions 12.10 and up
+
+Information containing `git-{upload-pack,receive-pack}` requests is at
+`/var/log/gitlab/gitlab-shell/gitlab-shell.log`. Information about hooks to
+GitLab Shell from Gitaly is at `/var/log/gitlab/gitaly/current`.
+
+Example log entries for `/var/log/gitlab/gitlab-shell/gitlab-shell.log`:
+
+```json
+{
+ "duration_ms": 74.104,
+ "level": "info",
+ "method": "POST",
+ "msg": "Finished HTTP request",
+ "time": "2020-04-17T20:28:46Z",
+ "url": "http://127.0.0.1:8080/api/v4/internal/allowed"
+}
+{
+ "command": "git-upload-pack",
+ "git_protocol": "",
+ "gl_project_path": "root/example",
+ "gl_repository": "project-1",
+ "level": "info",
+ "msg": "executing git command",
+ "time": "2020-04-17T20:28:46Z",
+ "user_id": "user-1",
+ "username": "root"
+}
+```
+
+Example log entries for `/var/log/gitlab/gitaly/current`:
+
+```json
+{
+ "method": "POST",
+ "url": "http://127.0.0.1:8080/api/v4/internal/allowed",
+ "duration": 0.058012959,
+ "gitaly_embedded": true,
+ "pid": 16636,
+ "level": "info",
+ "msg": "finished HTTP request",
+ "time": "2020-04-17T20:29:08+00:00"
+}
+{
+ "method": "POST",
+ "url": "http://127.0.0.1:8080/api/v4/internal/pre_receive",
+ "duration": 0.031022552,
+ "gitaly_embedded": true,
+ "pid": 16636,
+ "level": "info",
+ "msg": "finished HTTP request",
+ "time": "2020-04-17T20:29:08+00:00"
+}
+```
+
+### For GitLab versions 12.5 through 12.9
+
+For GitLab 12.5 to 12.9, depending on your installation method, this
+file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitaly/gitlab-shell.log`
+- Installation from source: `/home/git/gitaly/gitlab-shell.log`
+
+Example log entries:
+
+```json
+{
+ "method": "POST",
+ "url": "http://127.0.0.1:8080/api/v4/internal/post_receive",
+ "duration": 0.031809164,
+ "gitaly_embedded": true,
+ "pid": 27056,
+ "level": "info",
+ "msg": "finished HTTP request",
+ "time": "2020-04-17T16:24:38+00:00"
+}
+```
+
+### For GitLab 12.5 and earlier
+
+For GitLab 12.5 and earlier, the file is at `/var/log/gitlab/gitlab-shell/gitlab-shell.log`.
+
+Example log entries:
+
+```plaintext
+I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at </var/opt/gitlab/git-data/repositories/root/dcdcdcdcd.git>.
+I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
+```
+
+User clone/fetch activity using SSH transport appears in this log as
+`executing git command <gitaly-upload-pack...`.
+
+## Gitaly Logs
+
+This file is in `/var/log/gitlab/gitaly/current` and is produced by [runit](http://smarden.org/runit/).
+`runit` is packaged with Omnibus GitLab and a brief explanation of its purpose
+is available [in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/architecture/#runit).
+[Log files are rotated](http://smarden.org/runit/svlogd.8.html), renamed in
+Unix timestamp format, and `gzip`-compressed (like `@1584057562.s`).
+
+### `grpc.log`
+
+This file is at `/var/log/gitlab/gitlab-rails/grpc.log` for Omnibus GitLab
+packages. Native [gRPC](https://grpc.io/) logging used by Gitaly.
+
+### `gitaly_ruby_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2678) in GitLab 13.6.
+
+This file is at `/var/log/gitlab/gitaly/gitaly_ruby_json.log` and is
+produced by [`gitaly-ruby`](../gitaly/reference.md#gitaly-ruby). It contains an
+access log of gRPC calls made by Gitaly to `gitaly-ruby`.
+
+### `gitaly_hooks.log`
+
+This file is at `/var/log/gitlab/gitaly/gitaly_hooks.log` and is
+produced by `gitaly-hooks` command. It also contains records about
+failures received during processing of the responses from GitLab API.
+
+## Puma Logs
+
+### `puma_stdout.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/puma/puma_stdout.log`
+- Installations from source: `/home/git/gitlab/log/puma_stdout.log`
+
+### `puma_stderr.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/puma/puma_stderr.log`
+- Installations from source: `/home/git/gitlab/log/puma_stderr.log`
+
+## `repocheck.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/repocheck.log`
+- Installations from source: `/home/git/gitlab/log/repocheck.log`
+
+It logs information whenever a [repository check is run](../repository_checks.md)
+on a project.
+
+## `importer.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/importer.log`
+- Installations from source: `/home/git/gitlab/log/importer.log`
+
+It logs the progress of the import process.
+
+## `exporter.log`
+
+> Introduced in GitLab 13.1.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/exporter.log`
+- Installations from source: `/home/git/gitlab/log/exporter.log`
+
+It logs the progress of the export process.
+
+## `features_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 13.7.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/features_json.log`
+- Installations from source: `/home/git/gitlab/log/features_json.log`
+
+The modification events from [Feature flags in development of GitLab](../../development/feature_flags/index.md)
+are recorded in this file. For example:
+
+```json
+{"severity":"INFO","time":"2020-11-24T02:30:59.860Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"true"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.108Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"true"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.129Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable","extra.thing":"false"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.177Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable","extra.thing":"Project:1"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.183Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable","extra.thing":"Project:1"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.188Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable_percentage_of_time","extra.percentage":"50"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.193Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable_percentage_of_time"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.198Z","correlation_id":null,"key":"cd_auto_rollback","action":"enable_percentage_of_actors","extra.percentage":"50"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.203Z","correlation_id":null,"key":"cd_auto_rollback","action":"disable_percentage_of_actors"}
+{"severity":"INFO","time":"2020-11-24T02:31:29.329Z","correlation_id":null,"key":"cd_auto_rollback","action":"remove"}
+```
+
+## `auth.log`
+
+> Introduced in GitLab 12.0.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/auth.log`
+- Installations from source: `/home/git/gitlab/log/auth.log`
+
+This log records:
+
+- Requests over the [Rate Limit](../../user/admin_area/settings/rate_limits_on_raw_endpoints.md) on raw endpoints.
+- [Protected paths](../../user/admin_area/settings/protected_paths.md) abusive requests.
+- In GitLab versions [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/29239) and later,
+ user ID and username, if available.
+
+## `graphql_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/59587) in GitLab 12.0.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/graphql_json.log`
+- Installations from source: `/home/git/gitlab/log/graphql_json.log`
+
+GraphQL queries are recorded in the file. For example:
+
+```json
+{"query_string":"query IntrospectionQuery{__schema {queryType { name },mutationType { name }}}...(etc)","variables":{"a":1,"b":2},"complexity":181,"depth":1,"duration_s":7}
+```
+
+## `migrations.log`
+
+> Introduced in GitLab 12.3.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/migrations.log`
+- Installations from source: `/home/git/gitlab/log/migrations.log`
+
+## `mail_room_json.log` (default)
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19186) in GitLab 12.6.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/mailroom/current`
+- Installations from source: `/home/git/gitlab/log/mail_room_json.log`
+
+This structured log file records internal activity in the `mail_room` gem.
+Its name and path are configurable, so the name and path may not match the above.
+
+## Reconfigure logs
+
+Reconfigure log files are in `/var/log/gitlab/reconfigure` for Omnibus GitLab
+packages. Installations from source don't have reconfigure logs. A reconfigure log
+is populated whenever `gitlab-ctl reconfigure` is run manually or as part of an upgrade.
+
+Reconfigure logs files are named according to the UNIX timestamp of when the reconfigure
+was initiated, such as `1509705644.log`
+
+## `sidekiq_exporter.log` and `web_exporter.log`
+
+If Prometheus metrics and the Sidekiq Exporter are both enabled, Sidekiq
+starts a Web server and listen to the defined port (default:
+`8082`). By default, Sidekiq Exporter access logs are disabled but can
+be enabled based on your installation method:
+
+- Omnibus GitLab: Use the `sidekiq['exporter_log_enabled'] = true`
+ option in `/etc/gitlab/gitlab.rb`
+- Installations from source: Use the `sidekiq_exporter.log_enabled` option
+ in `gitlab.yml`
+
+When enabled, depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/sidekiq_exporter.log`
+- Installations from source: `/home/git/gitlab/log/sidekiq_exporter.log`
+
+If Prometheus metrics and the Web Exporter are both enabled, Puma
+starts a Web server and listen to the defined port (default: `8083`), and access logs
+are generated in a location based on your installation method:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/web_exporter.log`
+- Installations from source: `/home/git/gitlab/log/web_exporter.log`
+
+## `database_load_balancing.log` **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) in GitLab 12.3.
+
+Contains details of GitLab [Database Load Balancing](../postgresql/database_load_balancing.md).
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/database_load_balancing.log`
+- Installations from source: `/home/git/gitlab/log/database_load_balancing.log`
+
+## `elasticsearch.log` **(PREMIUM SELF)**
+
+> Introduced in GitLab 12.6.
+
+This file logs information related to the Elasticsearch Integration, including
+errors during indexing or searching Elasticsearch. Depending on your installation
+method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/elasticsearch.log`
+- Installations from source: `/home/git/gitlab/log/elasticsearch.log`
+
+Each line contains JSON that can be ingested by services like Elasticsearch and Splunk.
+Line breaks have been added to the following example line for clarity:
+
+```json
+{
+ "severity":"DEBUG",
+ "time":"2019-10-17T06:23:13.227Z",
+ "correlation_id":null,
+ "message":"redacted_search_result",
+ "class_name":"Milestone",
+ "id":2,
+ "ability":"read_milestone",
+ "current_user_id":2,
+ "query":"project"
+}
+```
+
+## `exceptions_json.log`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17819) in GitLab 12.6.
+
+This file logs the information about exceptions being tracked by
+`Gitlab::ErrorTracking`, which provides a standard and consistent way of
+[processing rescued exceptions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/logging.md#exception-handling).
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/exceptions_json.log`
+- Installations from source: `/home/git/gitlab/log/exceptions_json.log`
+
+Each line contains JSON that can be ingested by Elasticsearch. For example:
+
+```json
+{
+ "severity": "ERROR",
+ "time": "2019-12-17T11:49:29.485Z",
+ "correlation_id": "AbDVUrrTvM1",
+ "extra.project_id": 55,
+ "extra.relation_key": "milestones",
+ "extra.relation_index": 1,
+ "exception.class": "NoMethodError",
+ "exception.message": "undefined method `strong_memoize' for #<Gitlab::ImportExport::RelationFactory:0x00007fb5d917c4b0>",
+ "exception.backtrace": [
+ "lib/gitlab/import_export/relation_factory.rb:329:in `unique_relation?'",
+ "lib/gitlab/import_export/relation_factory.rb:345:in `find_or_create_object!'"
+ ]
+}
+```
+
+## `service_measurement.log`
+
+> Introduced in GitLab 13.0.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/service_measurement.log`
+- Installations from source: `/home/git/gitlab/log/service_measurement.log`
+
+It contains only a single structured log with measurements for each service execution.
+It contains measurements such as the number of SQL calls, `execution_time`, `gc_stats`, and `memory usage`.
+
+For example:
+
+```json
+{ "severity":"INFO", "time":"2020-04-22T16:04:50.691Z","correlation_id":"04f1366e-57a1-45b8-88c1-b00b23dc3616","class":"Projects::ImportExport::ExportService","current_user":"John Doe","project_full_path":"group1/test-export","file_path":"/path/to/archive","gc_stats":{"count":{"before":127,"after":127,"diff":0},"heap_allocated_pages":{"before":10369,"after":10369,"diff":0},"heap_sorted_length":{"before":10369,"after":10369,"diff":0},"heap_allocatable_pages":{"before":0,"after":0,"diff":0},"heap_available_slots":{"before":4226409,"after":4226409,"diff":0},"heap_live_slots":{"before":2542709,"after":2641420,"diff":98711},"heap_free_slots":{"before":1683700,"after":1584989,"diff":-98711},"heap_final_slots":{"before":0,"after":0,"diff":0},"heap_marked_slots":{"before":2542704,"after":2542704,"diff":0},"heap_eden_pages":{"before":10369,"after":10369,"diff":0},"heap_tomb_pages":{"before":0,"after":0,"diff":0},"total_allocated_pages":{"before":10369,"after":10369,"diff":0},"total_freed_pages":{"before":0,"after":0,"diff":0},"total_allocated_objects":{"before":24896308,"after":24995019,"diff":98711},"total_freed_objects":{"before":22353599,"after":22353599,"diff":0},"malloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"malloc_increase_bytes_limit":{"before":25804104,"after":25804104,"diff":0},"minor_gc_count":{"before":94,"after":94,"diff":0},"major_gc_count":{"before":33,"after":33,"diff":0},"remembered_wb_unprotected_objects":{"before":34284,"after":34284,"diff":0},"remembered_wb_unprotected_objects_limit":{"before":68568,"after":68568,"diff":0},"old_objects":{"before":2404725,"after":2404725,"diff":0},"old_objects_limit":{"before":4809450,"after":4809450,"diff":0},"oldmalloc_increase_bytes":{"before":140032,"after":6650240,"diff":6510208},"oldmalloc_increase_bytes_limit":{"before":68537556,"after":68537556,"diff":0}},"time_to_finish":0.12298400001600385,"number_of_sql_calls":70,"memory_usage":"0.0 MiB","label":"process_48616"}
+```
+
+## `geo.log` **(PREMIUM SELF)**
+
+Geo stores structured log messages in a `geo.log` file. For Omnibus GitLab
+installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
+
+This file contains information about when Geo attempts to sync repositories
+and files. Each line in the file contains a separate JSON entry that can be
+ingested into (for example, Elasticsearch or Splunk).
+
+For example:
+
+```json
+{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038}
+```
+
+This message shows that Geo detected that a repository update was needed for project `1`.
+
+## `update_mirror_service_json.log`
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/update_mirror_service_json.log`
+- Installations from source: `/home/git/gitlab/log/update_mirror_service_json.log`
+
+This file contains information about LFS errors that occurred during project mirroring.
+While we work to move other project mirroring errors into this log, the [general log](#productionlog)
+can be used.
+
+```json
+{
+ "severity":"ERROR",
+ "time":"2020-07-28T23:29:29.473Z",
+ "correlation_id":"5HgIkCJsO53",
+ "user_id":"x",
+ "project_id":"x",
+ "import_url":"https://mirror-source/group/project.git",
+ "error_message":"The LFS objects download list couldn't be imported. Error: Unauthorized"
+}
+```
+
+## Registry Logs
+
+For Omnibus GitLab installations, Container Registry logs are in `/var/log/gitlab/registry/current`.
+
+## NGINX Logs
+
+For Omnibus GitLab installations, NGINX logs are in:
+
+- `/var/log/gitlab/nginx/gitlab_access.log`: A log of requests made to GitLab
+- `/var/log/gitlab/nginx/gitlab_error.log`: A log of NGINX errors for GitLab
+- `/var/log/gitlab/nginx/gitlab_pages_access.log`: A log of requests made to Pages static sites
+- `/var/log/gitlab/nginx/gitlab_pages_error.log`: A log of NGINX errors for Pages static sites
+- `/var/log/gitlab/nginx/gitlab_registry_access.log`: A log of requests made to the Container Registry
+- `/var/log/gitlab/nginx/gitlab_registry_error.log`: A log of NGINX errors for the Container Registry
+- `/var/log/gitlab/nginx/gitlab_mattermost_access.log`: A log of requests made to Mattermost
+- `/var/log/gitlab/nginx/gitlab_mattermost_error.log`: A log of NGINX errors for Mattermost
+
+Below is the default GitLab NGINX access log format:
+
+```plaintext
+$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"
+```
+
+## Pages Logs
+
+For Omnibus GitLab installations, Pages logs are in `/var/log/gitlab/gitlab-pages/current`.
+
+For example:
+
+```json
+{
+ "level": "info",
+ "msg": "GitLab Pages Daemon",
+ "revision": "52b2899",
+ "time": "2020-04-22T17:53:12Z",
+ "version": "1.17.0"
+}
+{
+ "level": "info",
+ "msg": "URL: https://gitlab.com/gitlab-org/gitlab-pages",
+ "time": "2020-04-22T17:53:12Z"
+}
+{
+ "gid": 998,
+ "in-place": false,
+ "level": "info",
+ "msg": "running the daemon as unprivileged user",
+ "time": "2020-04-22T17:53:12Z",
+ "uid": 998
+}
+```
+
+## Mattermost Logs
+
+For Omnibus GitLab installations, Mattermost logs are in these locations:
+
+- `/var/log/gitlab/mattermost/mattermost.log`
+- `/var/log/gitlab/mattermost/current`
+
+## Workhorse Logs
+
+For Omnibus GitLab installations, Workhorse logs are in `/var/log/gitlab/gitlab-workhorse/current`.
+
+## PostgreSQL Logs
+
+For Omnibus GitLab installations, PostgreSQL logs are in `/var/log/gitlab/postgresql/current`.
+
+## Prometheus Logs
+
+For Omnibus GitLab installations, Prometheus logs are in `/var/log/gitlab/prometheus/current`.
+
+## Redis Logs
+
+For Omnibus GitLab installations, Redis logs are in `/var/log/gitlab/redis/current`.
+
+## Alertmanager Logs
+
+For Omnibus GitLab installations, Alertmanager logs are in `/var/log/gitlab/alertmanager/current`.
+
+<!-- vale gitlab.Spelling = NO -->
+
+## Crond Logs
+
+For Omnibus GitLab installations, crond logs are in `/var/log/gitlab/crond/`.
+
+<!-- vale gitlab.Spelling = YES -->
+
+## Grafana Logs
+
+For Omnibus GitLab installations, Grafana logs are in `/var/log/gitlab/grafana/current`.
+
+## LogRotate Logs
+
+For Omnibus GitLab installations, `logrotate` logs are in `/var/log/gitlab/logrotate/current`.
+
+## GitLab Monitor Logs
+
+For Omnibus GitLab installations, GitLab Monitor logs are in `/var/log/gitlab/gitlab-monitor/`.
+
+## GitLab Exporter
+
+For Omnibus GitLab installations, GitLab Exporter logs are in `/var/log/gitlab/gitlab-exporter/current`.
+
+## GitLab agent server
+
+For Omnibus GitLab installations, GitLab agent server logs are
+in `/var/log/gitlab/gitlab-kas/current`.
+
+## Praefect Logs
+
+For Omnibus GitLab installations, Praefect logs are in `/var/log/gitlab/praefect/`.
+
+GitLab also tracks [Prometheus metrics for Praefect](../gitaly/monitoring.md#monitor-gitaly-cluster).
+
+## Backup log
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63832) in GitLab 14.1.
+
+For Omnibus installations, the backup log is located at `/var/log/gitlab/gitlab-rails/backup_json.log`.
+
+This log is populated when a [GitLab backup is created](../../raketasks/backup_restore.md). You can use this log to understand how the backup process performed.
+
+## Performance bar stats
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48149) in GitLab 13.7.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/performance_bar_json.log`
+- Installations from source: `/home/git/gitlab/log/performance_bar_json.log`
+
+Performance bar statistics (currently only duration of SQL queries) are recorded
+in that file. For example:
+
+```json
+{"severity":"INFO","time":"2020-12-04T09:29:44.592Z","correlation_id":"33680b1490ccd35981b03639c406a697","filename":"app/models/ci/pipeline.rb","method_path":"app/models/ci/pipeline.rb:each_with_object","request_id":"rYHomD0VJS4","duration_ms":26.889,"count":2,"query_type": "active-record"}
+```
+
+These statistics are logged on .com only, disabled on self-deployments.
+
+## Gathering logs
+
+When [troubleshooting](../troubleshooting/index.md) issues that aren't localized to one of the
+previously listed components, it's helpful to simultaneously gather multiple logs and statistics
+from a GitLab instance.
+
+NOTE:
+GitLab Support often asks for one of these, and maintains the required tools.
+
+### Briefly tail the main logs
+
+If the bug or error is readily reproducible, save the main GitLab logs
+[to a file](../troubleshooting/linux_cheat_sheet.md#files-and-directories) while reproducing the
+problem a few times:
+
+```shell
+sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
+```
+
+Conclude the log gathering with <kbd>Control</kbd> + <kbd>C</kbd>.
+
+### GitLabSOS
+
+If performance degradations or cascading errors occur that can't readily be attributed to one
+of the previously listed GitLab components, [GitLabSOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/)
+can provide a broader perspective of the GitLab instance. For more details and instructions
+to run it, read [the GitLabSOS documentation](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/#gitlabsos).
+
+### Fast-stats
+
+[Fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats) is a tool
+for creating and comparing performance statistics from GitLab logs.
+For more details and instructions to run it, read the
+[documentation for fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats#usage).
+
+## Find relevant log entries with a correlation ID
+
+Most requests have a log ID that can be used to [find relevant log entries](tracing_correlation_id.md).
diff --git a/doc/administration/logs/log_parsing.md b/doc/administration/logs/log_parsing.md
new file mode 100644
index 00000000000..20b439af49b
--- /dev/null
+++ b/doc/administration/logs/log_parsing.md
@@ -0,0 +1,316 @@
+---
+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
+---
+
+# Parsing GitLab logs with `jq` **(FREE SELF)**
+
+We recommend using log aggregation and search tools like Kibana and Splunk whenever possible,
+but if they are not available you can still quickly parse
+[GitLab logs](../logs/index.md) in JSON format
+(the default in GitLab 12.0 and later) using [`jq`](https://stedolan.github.io/jq/).
+
+NOTE:
+Specifically for summarizing error events and basic usage statistics,
+the GitLab Support Team provides the specialised
+[`fast-stats` tool](https://gitlab.com/gitlab-com/support/toolbox/fast-stats/#when-to-use-it).
+
+## What is JQ?
+
+As noted in its [manual](https://stedolan.github.io/jq/manual/), `jq` is a command-line JSON processor. The following examples
+include use cases targeted for parsing GitLab log files.
+
+## Parsing Logs
+
+The examples listed below address their respective log files by
+their relative Omnibus paths and default filenames.
+Find the respective full paths in the [GitLab logs sections](../logs/index.md#production_jsonlog).
+
+### General Commands
+
+#### Pipe colorized `jq` output into `less`
+
+```shell
+jq . <FILE> -C | less -R
+```
+
+#### Search for a term and pretty-print all matching lines
+
+```shell
+grep <TERM> <FILE> | jq .
+```
+
+#### Skip invalid lines of JSON
+
+```shell
+jq -cR 'fromjson?' file.json | jq <COMMAND>
+```
+
+By default `jq` errors out when it encounters a line that is not valid JSON.
+This skips over all invalid lines and parses the rest.
+
+#### Print a JSON log's time range
+
+```shell
+cat log.json | (head -1; tail -1) | jq '.time'
+```
+
+Use `zcat` if the file has been rotated and compressed:
+
+```shell
+zcat @400000006026b71d1a7af804.s | (head -1; tail -1) | jq '.time'
+
+zcat some_json.log.25.gz | (head -1; tail -1) | jq '.time'
+```
+
+#### Get activity for correlation ID across multiple JSON logs in chronological order
+
+```shell
+grep -hR <correlationID> | jq -c -R 'fromjson?' | jq -C -s 'sort_by(.time)' | less -R
+```
+
+### Parsing `gitlab-rails/production_json.log` and `gitlab-rails/api_json.log`
+
+#### Find all requests with a 5XX status code
+
+```shell
+jq 'select(.status >= 500)' <FILE>
+```
+
+#### Top 10 slowest requests
+
+```shell
+jq -s 'sort_by(-.duration_s) | limit(10; .[])' <FILE>
+```
+
+#### Find and pretty print all requests related to a project
+
+```shell
+grep <PROJECT_NAME> <FILE> | jq .
+```
+
+#### Find all requests with a total duration > 5 seconds
+
+```shell
+jq 'select(.duration_s > 5000)' <FILE>
+```
+
+#### Find all project requests with more than 5 rugged calls
+
+```shell
+grep <PROJECT_NAME> <FILE> | jq 'select(.rugged_calls > 5)'
+```
+
+#### Find all requests with a Gitaly duration > 10 seconds
+
+```shell
+jq 'select(.gitaly_duration_s > 10000)' <FILE>
+```
+
+#### Find all requests with a queue duration > 10 seconds
+
+```shell
+jq 'select(.queue_duration_s > 10000)' <FILE>
+```
+
+#### Top 10 requests by # of Gitaly calls
+
+```shell
+jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE>
+```
+
+### Parsing `gitlab-rails/production_json.log`
+
+#### Print the top three controller methods by request volume and their three longest durations
+
+```shell
+jq -s -r 'group_by(.controller+.action) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tMETHOD: \(.[0].controller)#\(.[0].action)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' production_json.log
+```
+
+**Example output**
+
+```plaintext
+CT: 2721 METHOD: SessionsController#new DURS: 844.06, 713.81, 704.66
+CT: 2435 METHOD: MetricsController#index DURS: 299.29, 284.01, 158.57
+CT: 1328 METHOD: Projects::NotesController#index DURS: 403.99, 386.29, 384.39
+```
+
+### Parsing `gitlab-rails/api_json.log`
+
+#### Print top three routes with request count and their three longest durations
+
+```shell
+jq -s -r 'group_by(.route) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tROUTE: \(.[0].route)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' api_json.log
+```
+
+**Example output**
+
+```plaintext
+CT: 2472 ROUTE: /api/:version/internal/allowed DURS: 56402.65, 38411.43, 19500.41
+CT: 297 ROUTE: /api/:version/projects/:id/repository/tags DURS: 731.39, 685.57, 480.86
+CT: 190 ROUTE: /api/:version/projects/:id/repository/commits DURS: 1079.02, 979.68, 958.21
+```
+
+### Print top API user agents
+
+```shell
+jq --raw-output '[.route, .ua] | @tsv' api_json.log | sort | uniq -c | sort -n
+```
+
+**Example output**:
+
+```plaintext
+ 89 /api/:version/usage_data/increment_unique_users # plus browser details
+ 567 /api/:version/jobs/:id/trace gitlab-runner # plus version details
+1234 /api/:version/internal/allowed GitLab-Shell
+```
+
+This sample response seems normal. A custom tool or script might be causing a high load
+if the output contains many:
+
+- Third party libraries like `python-requests` or `curl`.
+- [GitLab CLI clients](https://about.gitlab.com/partners/technology-partners/#cli-clients).
+
+You can also [use `fast-stats top`](#parsing-gitlab-logs-with-jq) to extract performance statistics.
+
+### Parsing `gitlab-workhorse/current`
+
+### Print top Workhorse user agents
+
+```shell
+jq --raw-output '[.uri, .user_agent] | @tsv' current | sort | uniq -c | sort -n
+```
+
+**Example output**:
+
+```plaintext
+ 89 /api/graphql # plus browser details
+ 567 /api/v4/internal/allowed GitLab-Shell
+1234 /api/v4/jobs/request gitlab-runner # plus version details
+```
+
+Similar to the [API `ua` data](#print-top-api-user-agents),
+deviations from this common order might indicate scripts that could be optimized.
+
+The performance impact of runners checking for new jobs can be reduced by increasing
+[the `check_interval` setting](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section),
+for example.
+
+### Parsing `gitlab-rails/geo.log`
+
+#### Find most common Geo sync errors
+
+If [the `geo:status` Rake task](../geo/replication/troubleshooting.md#sync-status-rake-task)
+repeatedly reports that some items never reach 100%,
+the following command helps to focus on the most common errors.
+
+```shell
+jq --raw-output 'select(.severity == "ERROR") | [.project_path, .message] | @tsv' geo.log | sort | uniq -c | sort | tail
+```
+
+### Parsing `gitaly/current`
+
+Use the following examples to [troubleshoot Gitaly](../gitaly/troubleshooting.md).
+
+#### Find all Gitaly requests sent from web UI
+
+```shell
+jq 'select(."grpc.meta.client_name" == "gitlab-web")' current
+```
+
+#### Find all failed Gitaly requests
+
+```shell
+jq 'select(."grpc.code" != null and ."grpc.code" != "OK")' current
+```
+
+#### Find all requests that took longer than 30 seconds
+
+```shell
+jq 'select(."grpc.time_ms" > 30000)' current
+```
+
+#### Print top ten projects by request volume and their three longest durations
+
+```shell
+jq --raw-output --slurp '
+ map(
+ select(
+ ."grpc.request.glProjectPath" != null
+ and ."grpc.request.glProjectPath" != ""
+ and ."grpc.time_ms" != null
+ )
+ )
+ | group_by(."grpc.request.glProjectPath")
+ | sort_by(-length)
+ | limit(10; .[])
+ | sort_by(-."grpc.time_ms")
+ | [
+ length,
+ .[0]."grpc.time_ms",
+ .[1]."grpc.time_ms",
+ .[2]."grpc.time_ms",
+ .[0]."grpc.request.glProjectPath"
+ ]
+ | @sh' current \
+| awk 'BEGIN { printf "%7s %10s %10s %10s\t%s\n", "CT", "MAX DURS", "", "", "PROJECT" }
+ { printf "%7u %7u ms, %7u ms, %7u ms\t%s\n", $1, $2, $3, $4, $5 }'
+```
+
+**Example output**
+
+```plaintext
+ CT MAX DURS PROJECT
+ 206 4898 ms, 1101 ms, 1032 ms 'groupD/project4'
+ 109 1420 ms, 962 ms, 875 ms 'groupEF/project56'
+ 663 106 ms, 96 ms, 94 ms 'groupABC/project123'
+ ...
+```
+
+#### Find all projects affected by a fatal Git problem
+
+```shell
+grep "fatal: " current | \
+ jq '."grpc.request.glProjectPath"' | \
+ sort | uniq
+```
+
+### Parsing `gitlab-shell/gitlab-shell.log`
+
+For investigating Git calls via SSH, from [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/367).
+
+Find the top 20 calls by project and user:
+
+```shell
+jq --raw-output --slurp '
+ map(
+ select(
+ .username != null and
+ .gl_project_path !=null
+ )
+ )
+ | group_by(.username+.gl_project_path)
+ | sort_by(-length)
+ | limit(20; .[])
+ | "count: \(length)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
+ gitlab-shell.log
+```
+
+Find the top 20 calls by project, user, and command:
+
+```shell
+jq --raw-output --slurp '
+ map(
+ select(
+ .command != null and
+ .username != null and
+ .gl_project_path !=null
+ )
+ )
+ | group_by(.username+.gl_project_path+.command)
+ | sort_by(-length)
+ | limit(20; .[])
+ | "count: \(length)\tcommand: \(.[0].command)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
+ gitlab-shell.log
+```
diff --git a/doc/administration/logs/tracing_correlation_id.md b/doc/administration/logs/tracing_correlation_id.md
new file mode 100644
index 00000000000..1d3e4955d3a
--- /dev/null
+++ b/doc/administration/logs/tracing_correlation_id.md
@@ -0,0 +1,202 @@
+---
+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
+---
+
+# Find relevant log entries with a correlation ID **(FREE SELF)**
+
+GitLab instances log a unique request tracking ID (known as the
+"correlation ID") for most requests. Each individual request to GitLab gets
+its own correlation ID, which then gets logged in each GitLab component's logs for that
+request. This makes it easier to trace behavior in a
+distributed system. Without this ID it can be difficult or
+impossible to match correlating log entries.
+
+## Identify the correlation ID for a request
+
+The correlation ID is logged in structured logs under the key `correlation_id`
+and in all response headers GitLab sends under the header `x-request-id`.
+You can find your correlation ID by searching in either place.
+
+### Getting the correlation ID in your browser
+
+You can use your browser's developer tools to monitor and inspect network
+activity with the site that you're visiting. See the links below for network monitoring
+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/)
+
+To locate a relevant request and view its correlation ID:
+
+1. Enable persistent logging in your network monitor. Some actions in GitLab redirect you quickly after you submit a form, so this helps capture all relevant activity.
+1. To help isolate the requests you are looking for, you can filter for `document` requests.
+1. Select the request of interest to view further detail.
+1. Go to the **Headers** section and look for **Response Headers**. There you should find an `x-request-id` header with a
+value that was randomly generated by GitLab for the request.
+
+See the following example:
+
+![Firefox's network monitor showing an request ID header](img/network_monitor_xid.png)
+
+### Getting the correlation ID from your logs
+
+Another approach to finding the correct correlation ID is to search or watch
+your logs and find the `correlation_id` value for the log entry that you're
+watching for.
+
+For example, let's say that you want learn what's happening or breaking when
+you reproduce an action in GitLab. You could tail the GitLab logs, filtering
+to requests by your user, and then watch the requests until you see what you're
+interested in.
+
+### Getting the correlation ID from curl
+
+If you're using `curl` then you can use the verbose option to show request and response headers, as well as other debug information.
+
+```shell
+➜ ~ curl --verbose "https://gitlab.example.com/api/v4/projects"
+# look for a line that looks like this
+< x-request-id: 4rAMkV3gof4
+```
+
+#### Using jq
+
+This example uses [jq](https://stedolan.github.io/jq/) to filter results and
+display values we most likely care about.
+
+```shell
+sudo gitlab-ctl tail gitlab-rails/production_json.log | jq 'select(.username == "bob") | "User: \(.username), \(.method) \(.path), \(.controller)#\(.action), ID: \(.correlation_id)"'
+```
+
+```plaintext
+"User: bob, GET /root/linux, ProjectsController#show, ID: U7k7fh6NpW3"
+"User: bob, GET /root/linux/commits/master/signatures, Projects::CommitsController#signatures, ID: XPIHpctzEg1"
+"User: bob, GET /root/linux/blob/master/README, Projects::BlobController#show, ID: LOt9hgi1TV4"
+```
+
+#### Using grep
+
+This example uses only `grep` and `tr`, which are more likely to be installed than `jq`.
+
+```shell
+sudo gitlab-ctl tail gitlab-rails/production_json.log | grep '"username":"bob"' | tr ',' '\n' | egrep 'method|path|correlation_id'
+```
+
+```plaintext
+{"method":"GET"
+"path":"/root/linux"
+"username":"bob"
+"correlation_id":"U7k7fh6NpW3"}
+{"method":"GET"
+"path":"/root/linux/commits/master/signatures"
+"username":"bob"
+"correlation_id":"XPIHpctzEg1"}
+{"method":"GET"
+"path":"/root/linux/blob/master/README"
+"username":"bob"
+"correlation_id":"LOt9hgi1TV4"}
+```
+
+## Searching your logs for the correlation ID
+
+Once you have the correlation ID you can start searching for relevant log
+entries. You can filter the lines by the correlation ID itself.
+Combining a `find` and `grep` should be sufficient to find the entries you are looking for.
+
+```shell
+# find <gitlab log directory> -type f -mtime -0 exec grep '<correlation ID>' '{}' '+'
+find /var/log/gitlab -type f -mtime 0 -exec grep 'LOt9hgi1TV4' '{}' '+'
+```
+
+```plaintext
+/var/log/gitlab/gitlab-workhorse/current:{"correlation_id":"LOt9hgi1TV4","duration_ms":2478,"host":"gitlab.domain.tld","level":"info","method":"GET","msg":"access","proto":"HTTP/1.1","referrer":"https://gitlab.domain.tld/root/linux","remote_addr":"68.0.116.160:0","remote_ip":"[filtered]","status":200,"system":"http","time":"2019-09-17T22:17:19Z","uri":"/root/linux/blob/master/README?format=json\u0026viewer=rich","user_agent":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","written_bytes":1743}
+/var/log/gitlab/gitaly/current:{"correlation_id":"LOt9hgi1TV4","grpc.code":"OK","grpc.meta.auth_version":"v2","grpc.meta.client_name":"gitlab-web","grpc.method":"FindCommits","grpc.request.deadline":"2019-09-17T22:17:47Z","grpc.request.fullMethod":"/gitaly.CommitService/FindCommits","grpc.request.glProjectPath":"root/linux","grpc.request.glRepository":"project-1","grpc.request.repoPath":"@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git","grpc.request.repoStorage":"default","grpc.request.topLevelGroup":"@hashed","grpc.service":"gitaly.CommitService","grpc.start_time":"2019-09-17T22:17:17Z","grpc.time_ms":2319.161,"level":"info","msg":"finished streaming call with code OK","peer.address":"@","span.kind":"server","system":"grpc","time":"2019-09-17T22:17:19Z"}
+/var/log/gitlab/gitlab-rails/production_json.log:{"method":"GET","path":"/root/linux/blob/master/README","format":"json","controller":"Projects::BlobController","action":"show","status":200,"duration":2448.77,"view":0.49,"db":21.63,"time":"2019-09-17T22:17:19.800Z","params":[{"key":"viewer","value":"rich"},{"key":"namespace_id","value":"root"},{"key":"project_id","value":"linux"},{"key":"id","value":"master/README"}],"remote_ip":"[filtered]","user_id":2,"username":"bob","ua":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","queue_duration":3.38,"gitaly_calls":1,"gitaly_duration":0.77,"rugged_calls":4,"rugged_duration_ms":28.74,"correlation_id":"LOt9hgi1TV4"}
+```
+
+### Searching in distributed architectures
+
+If you have done some horizontal scaling in your GitLab infrastructure, then
+you must search across _all_ of your GitLab nodes. You can do this with
+some sort of log aggregation software like Loki, ELK, Splunk, or others.
+
+You can use a tool like Ansible or PSSH (parallel SSH) that can execute identical commands across your servers in
+parallel, or craft your own solution.
+
+### Viewing the request in the Performance Bar
+
+You can use the [performance bar](../monitoring/performance/performance_bar.md) to view interesting data including calls made to SQL and Gitaly.
+
+To view the data, the correlation ID of the request must match the same session as the user
+viewing the performance bar. For API requests, this means that you must perform the request
+using the session cookie of the signed-in user.
+
+For example, if you want to view the database queries executed for the following API endpoint:
+
+```shell
+https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1
+```
+
+First, enable the **Developer Tools** panel. See [Getting the correlation ID in your browser](#getting-the-correlation-id-in-your-browser) for details on how to do this.
+
+After developer tools have been enabled, obtain a session cookie as follows:
+
+1. Visit <https://gitlab.com> while logged in.
+1. Optional. Select **Fetch/XHR** request filter in the **Developer Tools** panel. This step is described for Google Chrome developer tools and is not strictly necessary, it just makes it easier to find the correct request.
+1. Select the `results?request_id=<some-request-id>` request on the left hand side.
+1. The session cookie is displayed under the `Request Headers` section of the `Headers` panel. Right-click on the cookie value and select `Copy value`.
+
+![Obtaining a session cookie for request](img/obtaining-a-session-cookie-for-request_v14_3.png)
+
+You have the value of the session cookie copied to your clipboard, for example:
+
+```shell
+experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false; frequently_used_emojis=clap,thumbsup,rofl,tada,eyes,bow
+```
+
+Use the value of the session cookie to craft an API request by pasting it into a custom header of a `curl` request:
+
+```shell
+$ curl --include "https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1" \
+--header 'cookie: experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false; frequently_used_emojis=clap,thumbsup,rofl,tada,eyes,bow'
+
+ date: Tue, 28 Sep 2021 03:55:33 GMT
+ content-type: application/json
+ ...
+ x-request-id: 01FGN8P881GF2E5J91JYA338Y3
+ ...
+ [
+ {
+ "id":27497069,
+ "description":"Analyzer for images used on live K8S containers based on Starboard"
+ },
+ "container_registry_image_prefix":"registry.gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning",
+ "..."
+ ]
+```
+
+The response contains the data from the API endpoint, and a `correlation_id` value, returned in the `x-request-id` header, as described in the [Identify the correlation ID for a request](#identify-the-correlation-id-for-a-request) section.
+
+You can then view the database details for this request:
+
+1. Paste the `x-request-id` value into the `request details` field of the [performance bar](../monitoring/performance/performance_bar.md) and press <kbd>Enter/Return</kbd>. This example uses the `x-request-id` value `01FGN8P881GF2E5J91JYA338Y3`, returned by the above response:
+
+ ![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:
+
+ ![Select request ID from request selector drop down menu](img/select-request-id-from-request-selector-drop-down-menu_v14_3.png)
+
+ <!-- vale gitlab.Substitutions = NO -->
+1. Select the `pg` link in the Progress Bar to view the database queries executed by the API request:
+
+ ![View pg database details](img/view-pg-details_v14_3.png)
+ <!-- vale gitlab.Substitutions = YES -->
+
+ The database query dialog is displayed:
+
+ ![Database query dialog](img/database-query-dialog_v14_3.png)
diff --git a/doc/administration/maintenance_mode/index.md b/doc/administration/maintenance_mode/index.md
index 9128f978dd5..00e28e650ea 100644
--- a/doc/administration/maintenance_mode/index.md
+++ b/doc/administration/maintenance_mode/index.md
@@ -135,6 +135,8 @@ For most JSON requests, `POST`, `PUT`, `PATCH`, and `DELETE` are blocked, and th
even if they finish running on the GitLab Runner.
- Jobs in the `running` state for longer than the project's time limit do not time out.
- Pipelines cannot be started, retried or canceled. No new jobs can be created either.
+- The status of the runners in `/admin/runners` won't be updated.
+- `gitlab-runner verify` will return the error `ERROR: Verifying runner... is removed`.
After Maintenance Mode is disabled, new jobs are picked up again. Jobs that were
in the `running` state before enabling Maintenance Mode resume and their logs start
diff --git a/doc/administration/monitoring/ip_allowlist.md b/doc/administration/monitoring/ip_allowlist.md
index adf9516733a..3151b696182 100644
--- a/doc/administration/monitoring/ip_allowlist.md
+++ b/doc/administration/monitoring/ip_allowlist.md
@@ -1,6 +1,6 @@
---
stage: Data Stores
-group: Memory
+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
---
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index d6575766b17..a2def8a9f64 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -111,6 +111,7 @@ The following metrics are available:
| `failed_login_captcha_total` | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login | |
| `successful_login_captcha_total` | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | |
| `auto_devops_pipelines_completed_total` | Counter | 12.7 | Counter of completed Auto DevOps pipelines, labeled by status | |
+| `artifact_report_<report_type>_builds_completed_total` | Counter | 15.3 | Counter of completed CI Builds with report-type artifacts, grouped by report type and labeled by status | |
| `gitlab_metrics_dashboard_processing_time_ms` | Summary | 12.10 | Metrics dashboard processing time in milliseconds | service, stages |
| `action_cable_active_connections` | Gauge | 13.4 | Number of ActionCable WS clients currently connected | `server_mode` |
| `action_cable_broadcasts_total` | Counter | 13.10 | The number of ActionCable broadcasts emitted | `server_mode` |
@@ -184,6 +185,7 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `sidekiq_elasticsearch_requests_total` | Counter | 13.1 | Elasticsearch requests during a Sidekiq job execution | `queue`, `boundary`, `external_dependencies`, `feature_category`, `job_status`, `urgency` |
| `sidekiq_running_jobs` | Gauge | 12.2 | Number of Sidekiq jobs running | `queue`, `boundary`, `external_dependencies`, `feature_category`, `urgency` |
| `sidekiq_concurrency` | Gauge | 12.5 | Maximum number of Sidekiq jobs | |
+| `sidekiq_mem_total_bytes` | Gauge | 15.3 | Number of bytes allocated for both objects consuming an object slot and objects that required a malloc'| |
| `geo_db_replication_lag_seconds` | Gauge | 10.2 | Database replication lag (seconds) | `url` |
| `geo_repositories` | Gauge | 10.2 | Total number of repositories available on primary | `url` |
| `geo_repositories_synced` | Gauge | 10.2 | Number of repositories synced on secondary | `url` |
@@ -300,6 +302,16 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_uploads_verification_failed` | Gauge | 14.6 | Number of uploads verifications failed on secondary | `url` |
| `gitlab_sli:rails_request_apdex:total` | Counter | 14.4 | The number of request-apdex measurements, [more information the development documentation](../../../development/application_slis/rails_request_apdex.md) | `endpoint_id`, `feature_category`, `request_urgency` |
| `gitlab_sli:rails_request_apdex:success_total` | Counter | 14.4 | The number of 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` |
+| `geo_ci_secure_files_checksum_total` | Gauge | 15.3 | Number of secure files tried to checksum on primary | `url` |
+| `geo_ci_secure_files_checksummed` | Gauge | 15.3 | Number of secure files successfully checksummed on primary | `url` |
+| `geo_ci_secure_files_checksum_failed` | Gauge | 15.3 | Number of secure files failed to calculate the checksum on primary | `url` |
+| `geo_ci_secure_files_synced` | Gauge | 15.3 | Number of syncable secure files synced on secondary | `url` |
+| `geo_ci_secure_files_failed` | Gauge | 15.3 | Number of syncable secure files failed to sync on secondary | `url` |
+| `geo_ci_secure_files_registry` | Gauge | 15.3 | Number of secure files in the registry | `url` |
+| `geo_ci_secure_files_verification_total` | Gauge | 15.3 | Number of secure files verifications tried on secondary | `url` |
+| `geo_ci_secure_files_verified` | Gauge | 15.3 | Number of secure files verified on secondary | `url` |
+| `geo_ci_secure_files_verification_failed` | Gauge | 15.3 | Number of secure files verifications failed on secondary | `url` |
## Database load balancing metrics **(PREMIUM SELF)**
@@ -378,8 +390,8 @@ Some basic Ruby runtime metrics are available:
## Redis metrics
These client metrics are meant to complement Redis server metrics.
-These metrics are broken down per [Redis
-instance](https://docs.gitlab.com/omnibus/settings/redis.html#running-with-multiple-redis-instances).
+These metrics are broken down per
+[Redis instance](https://docs.gitlab.com/omnibus/settings/redis.html#running-with-multiple-redis-instances).
These metrics all have a `storage` label which indicates the Redis
instance (`cache`, `shared_state`, and so on).
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index 51360800d66..6f6ac5c5d4b 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -465,3 +465,17 @@ If you are using Prometheus monitoring:
```
1. Optional. [Configure the storage retention size](index.md#configure-the-storage-retention-size).
+
+### Monitoring node not receiving data
+
+If the monitoring node is not receiving any data, check that the exporters are capturing data:
+
+```shell
+curl "http[s]://localhost:<EXPORTER LISTENING PORT>/metrics"
+```
+
+or
+
+```shell
+curl "http[s]://localhost:<EXPORTER LISTENING PORT>/-/metrics"
+```
diff --git a/doc/administration/monitoring/prometheus/web_exporter.md b/doc/administration/monitoring/prometheus/web_exporter.md
index fe140b15ed2..45a8e8d5640 100644
--- a/doc/administration/monitoring/prometheus/web_exporter.md
+++ b/doc/administration/monitoring/prometheus/web_exporter.md
@@ -1,6 +1,6 @@
---
stage: Data Stores
-group: Memory
+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
---
@@ -14,7 +14,7 @@ Prometheus scraper understands.
NOTE:
This page is about web application metrics.
-To export background job metrics, learn how to [configure the Sidekiq metrics server](../../sidekiq.md#configure-the-sidekiq-metrics-server).
+To export background job metrics, learn how to [configure the Sidekiq metrics server](../../sidekiq/index.md#configure-the-sidekiq-metrics-server).
We provide two mechanisms by which web application metrics can be exported:
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 51fa627b8d4..29f00fec3f7 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -65,8 +65,7 @@ Read:
## Known kernel version incompatibilities
RedHat Enterprise Linux (RHEL) and CentOS v7.7 and v7.8 ship with kernel
-version `3.10.0-1127`, which [contains a
-bug](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) that causes
+version `3.10.0-1127`, which [contains a bug](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) that causes
[uploads to fail to copy over NFS](https://gitlab.com/gitlab-org/gitlab/-/issues/218999). The
following GitLab versions include a fix to work properly with that
kernel version:
@@ -99,9 +98,20 @@ NFS performance with GitLab can in some cases be improved with
[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using
[Rugged](https://github.com/libgit2/rugged).
-From GitLab 12.1, GitLab automatically detects if Rugged can and should be used per storage.
-If you previously enabled Rugged using the feature flag and you want to use automatic detection instead,
-you must unset the feature flag:
+Versions of GitLab after 12.2 and prior to 15.3 automatically detect if
+Rugged can and should be used per storage.
+
+NOTE:
+GitLab 15.3 and later disables this automatic detection. Auto-detection can be enabled via the
+`skip_rugged_auto_detect` feature flag:
+
+```ruby
+Feature.disable(:skip_rugged_auto_detect)
+```
+
+In addition, if you previously enabled Rugged using the feature flag and
+you want to use automatic detection instead, you must unset the feature
+flag:
```shell
sudo gitlab-rake gitlab:features:unset_rugged
@@ -485,7 +495,7 @@ sudo perf trace --no-syscalls --event 'nfs4:*' -p $(pgrep -fd ',' puma)
### Warnings `garbage found: .../repositories/@hashed/...git/objects/pack/.nfs...` in Gitaly logs
-If you find any warnings like `garbage found: .../repositories/@hashed/...git/objects/pack/.nfs...` in [Gitaly logs](logs.md#gitaly-logs),
+If you find any warnings like `garbage found: .../repositories/@hashed/...git/objects/pack/.nfs...` in [Gitaly logs](logs/index.md#gitaly-logs),
this problem occurs if `lookupcache=positive` is not set, which we recommend as an
[NFS mount option](#mount-options).
See [Gitaly issue #3175](https://gitlab.com/gitlab-org/gitaly/-/issues/3175) for more details.
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index ddeaf0280eb..0299d5f8b0c 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -26,8 +26,8 @@ GitLab has been tested by vendors and customers on a number of object storage pr
### Known compatibility issues
-- Dell EMC ECS: Prior to GitLab 13.3, there is a [known bug in GitLab Workhorse that prevents
- HTTP Range Requests from working with CI job artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/223806).
+- Dell EMC ECS: Prior to GitLab 13.3, there is a
+ [known bug in GitLab Workhorse that prevents HTTP Range Requests from working with CI job artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/223806).
Be sure to upgrade to GitLab 13.3.0 or above if you use S3 storage with this hardware.
- Ceph S3 prior to [Kraken 11.0.2](https://ceph.com/releases/kraken-11-0-2-released/) does not support the [Upload Copy Part API](https://gitlab.com/gitlab-org/gitlab/-/issues/300604). You may need to [disable multi-threaded copying](#multi-threaded-copying).
@@ -578,9 +578,8 @@ real bucket into multiple virtual buckets. If your object storage
bucket is called `my-gitlab-objects` you can configure uploads to go
into `my-gitlab-objects/uploads`, artifacts into
`my-gitlab-objects/artifacts`, etc. The application will act as if
-these are separate buckets. Note that use of bucket prefixes [may not
-work correctly with Helm
-backups](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3376).
+these are separate buckets. Note that use of bucket prefixes
+[may not work correctly with Helm backups](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3376).
Helm-based installs require separate buckets to
[handle backup restorations](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-terraform-state-dependency-proxy).
@@ -693,18 +692,17 @@ configuration.
When configured either with an instance profile or with the consolidated
object configuration, GitLab Workhorse properly uploads files to S3
-buckets that have [SSE-S3 or SSE-KMS encryption enabled by
-default](https://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html).
-Customer master keys (CMKs) and SSE-C encryption are [not
-supported since this requires sending the encryption keys in every request](https://gitlab.com/gitlab-org/gitlab/-/issues/226006).
+buckets that have [SSE-S3 or SSE-KMS encryption enabled by default](https://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html).
+Customer master keys (CMKs) and SSE-C encryption are
+[not supported since this requires sending the encryption keys in every request](https://gitlab.com/gitlab-org/gitlab/-/issues/226006).
##### Server-side encryption headers
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38240) in GitLab 13.3.
Setting a default encryption on an S3 bucket is the easiest way to
-enable encryption, but you may want to [set a bucket policy to ensure
-only encrypted objects are uploaded](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-store-kms-encrypted-objects/).
+enable encryption, but you may want to
+[set a bucket policy to ensure only encrypted objects are uploaded](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-store-kms-encrypted-objects/).
To do this, you must configure GitLab to send the proper encryption headers
in the `storage_options` configuration section:
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 373017eefa7..58858c54843 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -1,362 +1,11 @@
---
-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
+redirect_to: '../sidekiq/extra_sidekiq_processes.md'
+remove_date: '2022-11-11'
---
-# Run multiple Sidekiq processes **(FREE SELF)**
+This document was moved to [another location](../sidekiq/extra_sidekiq_processes.md).
-GitLab allows you to start multiple Sidekiq processes.
-These processes can be used to consume a dedicated set
-of queues. This can be used to ensure certain queues always have dedicated
-workers, no matter the number of jobs to be processed.
-
-NOTE:
-The information in this page applies only to Omnibus GitLab.
-
-## Available Sidekiq queues
-
-For a list of the existing Sidekiq queues, check the following files:
-
-- [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
-- [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml)
-
-Each entry in the above files represents a queue on which Sidekiq processes
-can be started.
-
-## Start multiple processes
-
-> - [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4006) in GitLab 12.10, starting multiple processes with Sidekiq cluster.
-> - [Sidekiq cluster moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
-> - [Sidekiq cluster became default](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) in GitLab 13.0.
-
-When starting multiple processes, the number of processes should
-equal (and **not** exceed) the number of CPU cores you want to
-dedicate to Sidekiq. Each Sidekiq process can use only 1 CPU
-core, subject to the available workload and concurrency settings.
-
-To start multiple processes:
-
-1. Using the `sidekiq['queue_groups']` array setting, specify how many processes to
- create using `sidekiq-cluster` and which queue they should handle.
- Each item in the array equates to one additional Sidekiq
- process, and values in each item determine the queues it works on.
-
- For example, the following setting creates three Sidekiq processes, one to run on
- `elastic_commit_indexer`, one to run on `mailers`, and one process running on all queues:
-
- ```ruby
- sidekiq['queue_groups'] = [
- "elastic_commit_indexer",
- "mailers",
- "*"
- ]
- ```
-
- To have an additional Sidekiq process handle multiple queues, add multiple
- queue names to its item delimited by commas. For example:
-
- ```ruby
- sidekiq['queue_groups'] = [
- "elastic_commit_indexer, elastic_association_indexer",
- "mailers",
- "*"
- ]
- ```
-
- [In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
- later, the special queue name `*` means all queues. This starts two
- processes, each handling all queues:
-
- ```ruby
- sidekiq['queue_groups'] = [
- "*",
- "*"
- ]
- ```
-
- `*` cannot be combined with concrete queue names - `*, mailers`
- just handles the `mailers` queue.
-
- When `sidekiq-cluster` is only running on a single node, make sure that at least
- one process is running on all queues using `*`. This ensures a process
- automatically picks up jobs in queues created in the future,
- including queues that have dedicated processes.
-
- If `sidekiq-cluster` is running on more than one node, you can also use
- [`--negate`](#negate-settings) and list all the queues that are already being
- processed.
-
-1. Save the file and reconfigure GitLab for the changes to take effect:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-To view the Sidekiq processes in GitLab:
-
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Monitoring > Background Jobs**.
-
-## Negate settings
-
-To have the Sidekiq process work on every queue **except** the ones
-you list. In this example, we exclude all import-related jobs from a Sidekiq node:
-
-1. Edit `/etc/gitlab/gitlab.rb` and add:
-
- ```ruby
- sidekiq['negate'] = true
- sidekiq['queue_selector'] = true
- sidekiq['queue_groups'] = [
- "feature_category=importers"
- ]
- ```
-
-1. Save the file and reconfigure GitLab for the changes to take effect:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-## Queue selector
-
-> - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in GitLab 12.8.
-> - [Sidekiq cluster, including queue selector, moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
-> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6.
-
-In addition to selecting queues by name, as above, the `queue_selector` option
-allows queue groups to be selected in a more general way using a [worker matching
-query](extra_sidekiq_routing.md#worker-matching-query). After `queue_selector`
-is set, all `queue_groups` must follow the aforementioned syntax.
-
-In `/etc/gitlab/gitlab.rb`:
-
-```ruby
-sidekiq['enable'] = true
-sidekiq['queue_selector'] = true
-sidekiq['queue_groups'] = [
- # Run all non-CPU-bound queues that are high urgency
- 'resource_boundary!=cpu&urgency=high',
- # Run all continuous integration and pages queues that are not high urgency
- 'feature_category=continuous_integration,pages&urgency!=high',
- # Run all queues
- '*'
-]
-```
-
-## Ignore all import queues
-
-When [importing from GitHub](../../user/project/import/github.md) or
-other sources, Sidekiq might use all of its resources to perform those
-operations. To set up two separate `sidekiq-cluster` processes, where
-one only processes imports and the other processes all other queues:
-
-1. Edit `/etc/gitlab/gitlab.rb` and add:
-
- ```ruby
- sidekiq['enable'] = true
- sidekiq['queue_selector'] = true
- sidekiq['queue_groups'] = [
- "feature_category=importers",
- "feature_category!=importers"
- ]
- ```
-
-1. Save the file and reconfigure GitLab for the changes to take effect:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-## Number of threads
-
-By default each process defined under `sidekiq` starts with a
-number of threads that equals the number of queues, plus one spare thread.
-For example, a process that handles the `process_commit` and `post_receive`
-queues uses three threads in total.
-
-These thread run inside a single Ruby process, and each process
-can only use a single CPU core. The usefulness of threading depends
-on the work having some external dependencies to wait on, like database queries or
-HTTP requests. Most Sidekiq deployments benefit from this threading, and when
-running fewer queues in a process, increasing the thread count might be
-even more desirable to make the most effective use of CPU resources.
-
-### Manage thread counts explicitly
-
-The correct maximum thread count (also called concurrency) depends on the workload.
-Typical values range from `1` for highly CPU-bound tasks to `15` or higher for mixed
-low-priority work. A reasonable starting range is `15` to `25` for a non-specialized
-deployment.
-
-You can find example values used by GitLab.com by searching for `concurrency:` in
-[the Helm charts](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/blob/master/releases/gitlab/values/gprd.yaml.gotmpl).
-The values vary according to the work each specific deployment of Sidekiq does.
-Any other specialized deployments with processes dedicated to specific queues should
-have the concurrency tuned according to:
-have the concurrency tuned according to:
-
-- The CPU usage of each type of process.
-- The throughput achieved.
-
-Each thread requires a Redis connection, so adding threads may increase Redis
-latency and potentially cause client timeouts. See the [Sidekiq documentation
-about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis) for more
-details.
-
-#### When running Sidekiq cluster (default)
-
-Running Sidekiq cluster is the default in GitLab 13.0 and later.
-
-1. Edit `/etc/gitlab/gitlab.rb` and add:
-
- ```ruby
- sidekiq['min_concurrency'] = 15
- sidekiq['max_concurrency'] = 25
- ```
-
-1. Save the file and reconfigure GitLab for the changes to take effect:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-`min_concurrency` and `max_concurrency` are independent; one can be set without
-the other. Setting `min_concurrency` to `0` disables the limit.
-
-For each queue group, let `N` be one more than the number of queues. The
-concurrency is set to:
-
-1. `N`, if it's between `min_concurrency` and `max_concurrency`.
-1. `max_concurrency`, if `N` exceeds this value.
-1. `min_concurrency`, if `N` is less than this value.
-
-If `min_concurrency` is equal to `max_concurrency`, then this value is used
-regardless of the number of queues.
-
-When `min_concurrency` is greater than `max_concurrency`, it is treated as
-being equal to `max_concurrency`.
-
-#### When running a single Sidekiq process
-
-Running a single Sidekiq process is the default in GitLab 12.10 and earlier.
-
-WARNING:
-Running Sidekiq directly was removed in GitLab
-[14.0](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240).
-
-1. Edit `/etc/gitlab/gitlab.rb` and add:
-
- ```ruby
- sidekiq['cluster'] = false
- sidekiq['concurrency'] = 25
- ```
-
-1. Save the file and reconfigure GitLab for the changes to take effect:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-This sets the concurrency (number of threads) for the Sidekiq process.
-
-## Modify the check interval
-
-To modify `sidekiq-cluster`'s health check interval for the additional Sidekiq processes:
-
-1. Edit `/etc/gitlab/gitlab.rb` and add (the value can be any integer number of seconds):
-
- ```ruby
- sidekiq['interval'] = 5
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-## Troubleshoot using the CLI
-
-WARNING:
-It's recommended to use `/etc/gitlab/gitlab.rb` to configure the Sidekiq processes.
-If you experience a problem, you should contact GitLab support. Use the command
-line at your own risk.
-
-For debugging purposes, you can start extra Sidekiq processes by using the command
-`/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster`. This command
-takes arguments using the following syntax:
-
-```shell
-/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster [QUEUE,QUEUE,...] [QUEUE, ...]
-```
-
-Each separate argument denotes a group of queues that have to be processed by a
-Sidekiq process. Multiple queues can be processed by the same process by
-separating them with a comma instead of a space.
-
-Instead of a queue, a queue namespace can also be provided, to have the process
-automatically listen on all queues in that namespace without needing to
-explicitly list all the queue names. For more information about queue namespaces,
-see the relevant section in the
-[Sidekiq development documentation](../../development/sidekiq/index.md#queue-namespaces).
-
-For example, say you want to start 2 extra processes: one to process the
-`process_commit` queue, and one to process the `post_receive` queue. This can be
-done as follows:
-
-```shell
-/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit post_receive
-```
-
-If you instead want to start one process processing both queues, you'd use the
-following syntax:
-
-```shell
-/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive
-```
-
-If you want to have one Sidekiq process dealing with the `process_commit` and
-`post_receive` queues, and one process to process the `gitlab_shell` queue,
-you'd use the following:
-
-```shell
-/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive gitlab_shell
-```
-
-### Monitor the `sidekiq-cluster` command
-
-The `sidekiq-cluster` command does not terminate once it has started the desired
-amount of Sidekiq processes. Instead, the process continues running and
-forwards any signals to the child processes. This allows you to stop all
-Sidekiq processes as you send a signal to the `sidekiq-cluster` process,
-instead of having to send it to the individual processes.
-
-If the `sidekiq-cluster` process crashes or receives a `SIGKILL`, the child
-processes terminate themselves after a few seconds. This ensures you don't
-end up with zombie Sidekiq processes.
-
-This allows you to monitor the processes by hooking up
-`sidekiq-cluster` to your supervisor of choice (for example, runit).
-
-If a child process died the `sidekiq-cluster` command signals all remaining
-process to terminate, then terminate itself. This removes the need for
-`sidekiq-cluster` to re-implement complex process monitoring/restarting code.
-Instead you should make sure your supervisor restarts the `sidekiq-cluster`
-process whenever necessary.
-
-### PID files
-
-The `sidekiq-cluster` command can store its PID in a file. By default no PID
-file is written, but this can be changed by passing the `--pidfile` option to
-`sidekiq-cluster`. For example:
-
-```shell
-/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit
-```
-
-Keep in mind that the PID file contains the PID of the `sidekiq-cluster`
-command and not the PIDs of the started Sidekiq processes.
-
-### Environment
-
-The Rails environment can be set by passing the `--environment` flag to the
-`sidekiq-cluster` command, or by setting `RAILS_ENV` to a non-empty value. The
-default value can be found in `/opt/gitlab/etc/gitlab-rails/env/RAILS_ENV`.
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/administration/operations/extra_sidekiq_routing.md b/doc/administration/operations/extra_sidekiq_routing.md
index a6ad3e62bb7..072b6f63537 100644
--- a/doc/administration/operations/extra_sidekiq_routing.md
+++ b/doc/administration/operations/extra_sidekiq_routing.md
@@ -1,193 +1,11 @@
---
-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
+redirect_to: '../sidekiq/extra_sidekiq_routing.md'
+remove_date: '2022-11-11'
---
-# Queue routing rules **(FREE SELF)**
+This document was moved to [another location](../sidekiq/extra_sidekiq_routing.md).
-When the number of Sidekiq jobs increases to a certain scale, the system faces
-some scalability issues. One of them is that the length of the queue tends to get
-longer. High-urgency jobs have to wait longer until other less urgent jobs
-finish. This head-of-line blocking situation may eventually affect the
-responsiveness of the system, especially critical actions. In another scenario,
-the performance of some jobs is degraded due to other long running or CPU-intensive jobs
-(computing or rendering ones) in the same machine.
-
-To counter the aforementioned issues, one effective solution is to split
-Sidekiq jobs into different queues and assign machines handling each queue
-exclusively. For example, all CPU-intensive jobs could be routed to the
-`cpu-bound` queue and handled by a fleet of CPU optimized instances. The queue
-topology differs between companies depending on the workloads and usage
-patterns. Therefore, GitLab supports a flexible mechanism for the
-administrator to route the jobs based on their characteristics.
-
-As an alternative to [Queue selector](extra_sidekiq_processes.md#queue-selector), which
-configures Sidekiq cluster to listen to a specific set of workers or queues,
-GitLab also supports routing a job from a worker to the desired queue when it
-is scheduled. Sidekiq clients try to match a job against a configured list of
-routing rules. Rules are evaluated from first to last, and as soon as we find a
-match for a given worker we stop processing for that worker (first match wins).
-If the worker doesn't match any rule, it falls back to the queue name generated
-from the worker name.
-
-By default, if the routing rules are not configured (or denoted with an empty
-array), all the jobs are routed to the queue generated from the worker name.
-
-## Example configuration
-
-In `/etc/gitlab/gitlab.rb`:
-
-```ruby
-sidekiq['routing_rules'] = [
- # Do not re-route workers that require their own queue
- ['tags=needs_own_queue', nil],
- # Route all non-CPU-bound workers that are high urgency to `high-urgency` queue
- ['resource_boundary!=cpu&urgency=high', 'high-urgency'],
- # Route all database, gitaly and global search workers that are throttled to `throttled` queue
- ['feature_category=database,gitaly,global_search&urgency=throttled', 'throttled'],
- # Route all workers having contact with outside work to a `network-intenstive` queue
- ['has_external_dependencies=true|feature_category=hooks|tags=network', 'network-intensive'],
- # Route all import workers to the queues generated by the worker name, for
- # example, JiraImportWorker to `jira_import`, SVNWorker to `svn_worker`
- ['feature_category=import', nil],
- # Wildcard matching, route the rest to `default` queue
- ['*', 'default']
-]
-```
-
-The routing rules list is an order-matter array of tuples of query and
-corresponding queue:
-
-- The query is following a [worker matching query](#worker-matching-query) syntax.
-- The `<queue_name>` must be a valid Sidekiq queue name. If the queue name
- is `nil`, or an empty string, the worker is routed to the queue generated
- by the name of the worker instead.
-
-The query supports wildcard matching `*`, 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.
-
-NOTE:
-Mixing queue routing rules and queue selectors requires care to
-ensure all jobs that are scheduled and picked up by appropriate Sidekiq
-workers.
-
-## Worker matching query
-
-GitLab provides a query syntax to match a worker based on its
-attributes. This query syntax is employed by both [Queue routing
-rules](#queue-routing-rules) and [Queue
-selector](extra_sidekiq_processes.md#queue-selector). A query includes two
-components:
-
-- Attributes that can be selected.
-- Operators used to construct a query.
-
-### Available attributes
-
-> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1 (`tags`).
-
-Queue matching query works upon the worker attributes, described in
-[Sidekiq style guide](../../development/sidekiq/index.md). We support querying
-based on a subset of worker attributes:
-
-- `feature_category` - the [GitLab feature
- category](https://about.gitlab.com/direction/maturity/#category-maturity) the
- queue belongs to. For example, the `merge` queue belongs to the
- `source_code_management` category.
-- `has_external_dependencies` - whether or not the queue connects to external
- services. For example, all importers have this set to `true`.
-- `urgency` - how important it is that this queue's jobs run
- quickly. Can be `high`, `low`, or `throttled`. For example, the
- `authorized_projects` queue is used to refresh user permissions, and
- is `high` urgency.
-- `worker_name` - the worker name. Use this attribute to select a specific worker.
-- `name` - the queue name generated from the worker name. Use this attribute to select a specific queue. Because this is generated from
- the worker name, it does not change based on the result of other routing
- rules.
-- `resource_boundary` - if the queue is bound by `cpu`, `memory`, or
- `unknown`. For example, the `ProjectExportWorker` is memory bound as it has
- to load data in memory before saving it for export.
-- `tags` - short-lived annotations for queues. These are expected to frequently
- change from release to release, and may be removed entirely.
-
-`has_external_dependencies` is a boolean attribute: only the exact
-string `true` is considered true, and everything else is considered
-false.
-
-`tags` is a set, which means that `=` checks for intersecting sets, and
-`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
-that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
-neither of those tags.
-
-The attributes of each worker are hard-coded in the source code. For
-convenience, we generate a [list of all available attributes in
-GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
-and a [list of all available attributes in
-GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml).
-
-### Available operators
-
-`queue_selector` supports the following operators, listed from highest
-to lowest precedence:
-
-- `|` - the logical `OR` operator. For example, `query_a|query_b` (where `query_a`
- and `query_b` are queries made up of the other operators here) includes
- queues that match either query.
-- `&` - the logical `AND` operator. For example, `query_a&query_b` (where
- `query_a` and `query_b` are queries made up of the other operators here) will
- only include queues that match both queries.
-- `!=` - the `NOT IN` operator. For example, `feature_category!=issue_tracking`
- excludes all queues from the `issue_tracking` feature category.
-- `=` - the `IN` operator. For example, `resource_boundary=cpu` includes all
- queues that are CPU bound.
-- `,` - the concatenate set operator. For example,
- `feature_category=continuous_integration,pages` includes all queues from
- either the `continuous_integration` category or the `pages` category. This
- example is also possible using the OR operator, but allows greater brevity, as
- well as being lower precedence.
-
-The operator precedence for this syntax is fixed: it's not possible to make `AND`
-have higher precedence than `OR`.
-
-[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
-later, as with the standard queue group syntax above, a single `*` as the
-entire queue group selects all queues.
-
-### Migration
-
-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](../../raketasks/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).
-
-The following table shows the workers that should have their own queue:
-
-| Worker name | Queue name | GitLab issue |
-| --- | --- | --- |
-| `EmailReceiverWorker` | `email_receiver` | [`gitlab-com/gl-infra/scalability#1263`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1263) |
-| `ServiceDeskEmailReceiverWorker` | `service_desk_email_receiver` | [`gitlab-com/gl-infra/scalability#1263`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1263) |
-| `ProjectImportScheduleWorker` | `project_import_schedule` | [`gitlab-org/gitlab#340630`](https://gitlab.com/gitlab-org/gitlab/-/issues/340630) |
-| `HashedStorage::MigratorWorker` | `hashed_storage:hashed_storage_migrator` | [`gitlab-org/gitlab#340629`](https://gitlab.com/gitlab-org/gitlab/-/issues/340629) |
-| `HashedStorage::ProjectMigrateWorker` | `hashed_storage:hashed_storage_project_migrate` | [`gitlab-org/gitlab#340629`](https://gitlab.com/gitlab-org/gitlab/-/issues/340629) |
-| `HashedStorage::ProjectRollbackWorker` | `hashed_storage:hashed_storage_project_rollback` | [`gitlab-org/gitlab#340629`](https://gitlab.com/gitlab-org/gitlab/-/issues/340629) |
-| `HashedStorage::RollbackerWorker` | `hashed_storage:hashed_storage_rollbacker` | [`gitlab-org/gitlab#340629`](https://gitlab.com/gitlab-org/gitlab/-/issues/340629) |
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/administration/operations/index.md b/doc/administration/operations/index.md
index 41a9a0e6d67..a6e66abdbdb 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -18,10 +18,9 @@ Keep your GitLab instance up and running smoothly.
- [Multiple Sidekiq processes](extra_sidekiq_processes.md): Configure multiple Sidekiq processes to ensure certain queues always have dedicated workers, no matter the number of jobs that must be processed. **(FREE SELF)**
- [Sidekiq routing rules](extra_sidekiq_routing.md): Configure the routing rules to route a job from a worker to a desirable queue. **(FREE SELF)**
- [Puma](puma.md): Understand Puma and puma-worker-killer.
-- Speed up SSH operations by [Authorizing SSH users via a fast,
- indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
- by [doing away with user SSH keys stored on GitLab entirely in favor
- of SSH certificates](ssh_certificates.md).
+- Speed up SSH operations by
+ [Authorizing SSH users via a fast, indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
+ by [doing away with user SSH keys stored on GitLab entirely in favor of SSH certificates](ssh_certificates.md).
- [File System Performance Benchmarking](filesystem_benchmarking.md): File system
performance can have a big impact on GitLab performance, especially for actions
that read or write Git repositories. This information helps benchmark
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index bc95ee626ce..5ce469d3e63 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -54,7 +54,7 @@ A higher value of `1200` or more would be beneficial if the server has free memo
The worker killer checks memory every 20 seconds.
-To monitor the worker killer, use [the Puma log](../logs.md#puma_stdoutlog) `/var/log/gitlab/puma/puma_stdout.log`.
+To monitor the worker killer, use [the Puma log](../logs/index.md#puma_stdoutlog) `/var/log/gitlab/puma/puma_stdout.log`.
For example:
```plaintext
@@ -246,7 +246,7 @@ automatically, due to differences between the two application servers.
To switch from Unicorn to Puma:
1. Determine suitable Puma [worker and thread settings](../../install/requirements.md#puma-settings).
-1. Convert any custom Unicorn settings to Puma.
+1. Convert any custom Unicorn settings to Puma in `/etc/gitlab/gitlab.rb`.
The table below summarizes which Unicorn configuration keys correspond to those
in Puma when using the Linux package, and which ones have no corresponding counterpart.
diff --git a/doc/administration/operations/rails_console.md b/doc/administration/operations/rails_console.md
index 660a99faaf8..430dfbc637c 100644
--- a/doc/administration/operations/rails_console.md
+++ b/doc/administration/operations/rails_console.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Rails console **(FREE SELF)**
-At the heart of GitLab is a web application [built using the Ruby on Rails
-framework](https://about.gitlab.com/blog/2018/10/29/why-we-use-rails-to-build-gitlab/).
+At the heart of GitLab is a web application
+[built using the Ruby on Rails framework](https://about.gitlab.com/blog/2018/10/29/why-we-use-rails-to-build-gitlab/).
The [Rails console](https://guides.rubyonrails.org/command_line.html#rails-console).
provides a way to interact with your GitLab instance from the command line, and also grants access to the amazing tools built right into Rails.
@@ -19,8 +19,8 @@ with no consequences, you are strongly advised to do so in a test environment.
The Rails console is for GitLab system administrators who are troubleshooting
a problem or need to retrieve some data that can only be done through direct
-access of the GitLab application. Basic knowledge of Ruby is needed (try [this
-30-minute tutorial](https://try.ruby-lang.org/) for a quick introduction).
+access of the GitLab application. Basic knowledge of Ruby is needed (try
+[this 30-minute tutorial](https://try.ruby-lang.org/) for a quick introduction).
Rails experience is useful but not required.
## Starting a Rails console session
@@ -136,8 +136,8 @@ root
1
```
-Some basic knowledge of Ruby will be very useful. Try [this
-30-minute tutorial](https://try.ruby-lang.org/) for a quick introduction.
+Some basic knowledge of Ruby will be very useful. Try
+[this 30-minute tutorial](https://try.ruby-lang.org/) for a quick introduction.
Rails experience is helpful but not essential.
### Troubleshooting Rails Runner
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
index d9558c3d7a6..b1977589fae 100644
--- a/doc/administration/operations/sidekiq_memory_killer.md
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -1,83 +1,11 @@
---
-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
+redirect_to: '../sidekiq/sidekiq_memory_killer.md'
+remove_date: '2022-11-11'
---
-# Sidekiq MemoryKiller **(FREE SELF)**
+This document was moved to [another location](../sidekiq/sidekiq_memory_killer.md).
-The GitLab Rails application code suffers from memory leaks. For web requests
-this problem is made manageable using
-[`puma-worker-killer`](https://github.com/schneems/puma_worker_killer) which
-restarts Puma worker processes if it exceeds a memory limit. The Sidekiq
-MemoryKiller applies the same approach to the Sidekiq processes used by GitLab
-to process background jobs.
-
-Unlike puma-worker-killer, which is enabled by default for all GitLab
-installations of GitLab 13.0 and later, the Sidekiq MemoryKiller is enabled by default
-_only_ for Omnibus packages. The reason for this is that the MemoryKiller
-relies on runit to restart Sidekiq after a memory-induced shutdown and GitLab
-installations from source do not all use runit or an equivalent.
-
-With the default settings, the MemoryKiller causes a Sidekiq restart no
-more often than once every 15 minutes, with the restart causing about one
-minute of delay for incoming background jobs.
-
-Some background jobs rely on long-running external processes. To ensure these
-are cleanly terminated when Sidekiq is restarted, each Sidekiq process should be
-run as a process group leader (for example, using `chpst -P`). If using Omnibus or the
-`bin/background_jobs` script with `runit` installed, this is handled for you.
-
-## Configuring the MemoryKiller
-
-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
- `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.
-
- 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
- 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
- often to check process RSS, default to 3 seconds.
-
-- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults to 900 seconds (15 minutes).
- The usage of this variable is described as part of `SIDEKIQ_MEMORY_KILLER_MAX_RSS`.
-
-- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. This defines the
- maximum time allowed for all Sidekiq jobs to finish. No new jobs are accepted
- during that time, and the process exits as soon as all jobs finish.
-
- If jobs do not finish during that time, the MemoryKiller interrupts all currently
- running jobs by sending `SIGTERM` to the Sidekiq process.
-
- If the process hard shutdown/restart is not performed by Sidekiq,
- the Sidekiq process is forcefully terminated after
- `Sidekiq.options[:timeout] + 2` seconds. An external supervision mechanism
- (for example, runit) must restart Sidekiq afterwards.
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md
index a777f5484fd..1e405189342 100644
--- a/doc/administration/operations/ssh_certificates.md
+++ b/doc/administration/operations/ssh_certificates.md
@@ -35,10 +35,10 @@ uploading user SSH keys to GitLab entirely.
## Setting up SSH certificate lookup via GitLab Shell
How to fully set up SSH certificates is outside the scope of this
-document. See [OpenSSH's
-`PROTOCOL.certkeys`](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD)
-for how it works, for example [RedHat's documentation about
-it](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_openssh_certificate_authentication).
+document. See
+[OpenSSH's`PROTOCOL.certkeys`](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD)
+for how it works, for example
+[RedHat's documentation about it](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-using_openssh_certificate_authentication).
We assume that you already have SSH certificates set up, and have
added the `TrustedUserCAKeys` of your CA to your `sshd_config`, for example:
@@ -143,8 +143,7 @@ This is because if the `AuthorizedPrincipalsCommand` can't
authenticate the user, OpenSSH falls back on
`~/.ssh/authorized_keys` (or the `AuthorizedKeysCommand`).
-Therefore there may still be a reason to use the ["Fast lookup of
-authorized SSH keys in the database"](fast_ssh_key_lookup.html) method
+Therefore there may still be a reason to use the [Fast lookup of authorized SSH keys in the database](fast_ssh_key_lookup.md) method
in conjunction with this. Since you are using SSH certificates for
all your normal users, and relying on the `~/.ssh/authorized_keys`
fallback for deploy keys, if you make use of those.
@@ -160,8 +159,8 @@ users (especially if they're renewed) than you have deploy keys.
Users can still bypass SSH certificate authentication by manually
uploading an SSH public key to their profile, relying on the
`~/.ssh/authorized_keys` fallback to authenticate it. There's
-currently no feature to prevent this, [but there's an open request for
-adding it](https://gitlab.com/gitlab-org/gitlab/-/issues/23260).
+currently no feature to prevent this,
+[but there's an open request for adding it](https://gitlab.com/gitlab-org/gitlab/-/issues/23260).
Such a restriction can currently be hacked in by, for example, providing a
custom `AuthorizedKeysCommand` which checks if the discovered key-ID
diff --git a/doc/administration/package_information/deprecation_policy.md b/doc/administration/package_information/deprecation_policy.md
index 422339c014c..73059514e1c 100644
--- a/doc/administration/package_information/deprecation_policy.md
+++ b/doc/administration/package_information/deprecation_policy.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Deprecation policy **(FREE SELF)**
+# Omnibus GitLab deprecation policy **(FREE SELF)**
The Omnibus GitLab packages come with number of different libraries and services which offers users plethora of configuration options.
diff --git a/doc/administration/package_information/index.md b/doc/administration/package_information/index.md
index 746961e8613..d3a82b87116 100644
--- a/doc/administration/package_information/index.md
+++ b/doc/administration/package_information/index.md
@@ -34,8 +34,8 @@ These defaults are noted in the package [defaults document](defaults.md).
## Checking the versions of bundled software
-After the Omnibus GitLab package is installed, all versions of the bundled
-libraries are located in `/opt/gitlab/version-manifest.txt`.
+After the Omnibus GitLab package is installed, you can find the version of
+GitLab and all bundled libraries in `/opt/gitlab/version-manifest.txt`.
If you don't have the package installed, you can always check the Omnibus GitLab
[source repository](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master), specifically the
diff --git a/doc/administration/package_information/postgresql_versions.md b/doc/administration/package_information/postgresql_versions.md
index afdc63c4851..d831e8cea7f 100644
--- a/doc/administration/package_information/postgresql_versions.md
+++ b/doc/administration/package_information/postgresql_versions.md
@@ -11,15 +11,16 @@ This table lists only GitLab versions where a significant change happened in the
package regarding PostgreSQL versions, not all.
Usually, PostgreSQL versions change with major or minor GitLab releases. However, patch versions
-of Omnibus GitLab sometimes update the patch level of PostgreSQL.
+of Omnibus GitLab sometimes update the patch level of PostgreSQL. We've established a
+[yearly cadence for PostgreSQL upgrades](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/database/postgresql-upgrade-cadence.html)
+and trigger automatic database upgrades in the release before the new version is required.
For example:
- Omnibus 12.7.6 shipped with PostgreSQL 9.6.14 and 10.9.
- Omnibus 12.7.7 shipped with PostgreSQL 9.6.17 and 10.12.
-[Find out which versions of PostgreSQL (and other components) ship with
-each Omnibus GitLab release](https://gitlab-org.gitlab.io/omnibus-gitlab/licenses.html).
+[Find out which versions of PostgreSQL (and other components) ship with each Omnibus GitLab release](https://gitlab-org.gitlab.io/omnibus-gitlab/licenses.html).
The lowest supported PostgreSQL versions are listed in the
[installation requirements](../../install/requirements.md#postgresql-requirements).
diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md
index 4f31981a05c..e4d7ea72cdc 100644
--- a/doc/administration/package_information/supported_os.md
+++ b/doc/administration/package_information/supported_os.md
@@ -10,8 +10,8 @@ GitLab officially supports LTS versions of operating systems. While OSs like
Ubuntu have a clear distinction between LTS and non-LTS versions, there are
other OSs, openSUSE for example, that don't follow the LTS concept. Hence to
avoid confusion, the official policy is that at any point of time, all the
-operating systems supported by GitLab are listed in the [installation
-page](https://about.gitlab.com/install/).
+operating systems supported by GitLab are listed in the
+[installation page](https://about.gitlab.com/install/).
The following lists the currently supported OSs and their possible EOL dates.
@@ -19,11 +19,10 @@ The following lists the currently supported OSs and their possible EOL dates.
| ------------------------------------------------------------ | ------------------------------ | --------------- | :----------------------------------------------------------: | ---------- | ------------------------------------------------------------ |
| AlmaLinux 8 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | [AlmaLinux Install Documentation](https://about.gitlab.com/install/#almalinux-8) | 2029 | <https://almalinux.org/> |
| CentOS 7 | GitLab CE / GitLab EE 7.10.0 | x86_64 | [CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | June 2024 | <https://wiki.centos.org/About/Product> |
-| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | [Debian Install Documentation](https://about.gitlab.com/install/#debian) | 2022 | <https://wiki.debian.org/LTS> |
| Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | [Debian Install Documentation](https://about.gitlab.com/install/#debian) | 2024 | <https://wiki.debian.org/LTS> |
| Debian 11 | GitLab CE / GitLab EE 14.6.0 | amd64, arm64 | [Debian Install Documentation](https://about.gitlab.com/install/#debian) | 2026 | <https://wiki.debian.org/LTS> |
| OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | [OpenSUSE Install Documentation](https://about.gitlab.com/install/#opensuse-leap-15-3) | Nov 2022 | <https://en.opensuse.org/Lifetime> |
-| RHEL 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, arm64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | May 2024 | [RHEL Details](https://access.redhat.com/support/policy/updates/errata/#Life_Cycle_Dates) |
+| RHEL 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, arm64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | May 2029 | [RHEL Details](https://access.redhat.com/support/policy/updates/errata/#Life_Cycle_Dates) |
| SLES 12 | GitLab EE 9.0.0 | x86_64 | [Use OpenSUSE Install Documentation](https://about.gitlab.com/install/#opensuse-leap-15-3) | Oct 2027 | <https://www.suse.com/lifecycle/> |
| Oracle Linux | GitLab CE / GitLab EE 8.14.0 | x86_64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | Jul 2024 | <https://www.oracle.com/a/ocom/docs/elsp-lifetime-069338.pdf> |
| Scientific Linux | GitLab CE / GitLab EE 8.14.0 | x86_64 | [Use CentOS Install Documentation](https://about.gitlab.com/install/#centos-7) | June 2024 | <https://scientificlinux.org/downloads/sl-versions/sl7/> |
@@ -87,6 +86,7 @@ release for them can be found below:
| OpenSUSE 15.1 | [November 2020](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-13.12&dist=opensuse%2F15.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-13.12&dist=opensuse%2F15.1) 13.12 |
| Ubuntu 16.04 | [April 2021](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.12&dist=ubuntu%2Fxenial) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.12&dist=ubuntu%2Fxenial) 13.12 |
| OpenSUSE 15.2 | [December 2021](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-14.7&dist=opensuse%2F15.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-14.7&dist=opensuse%2F15.2) 14.7 |
+| Debian 9 "Stretch" | [June 2022](https://lists.debian.org/debian-lts-announce/2022/07/msg00002.html) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_15.2&dist=debian%2Fstretch) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_15.2&dist=debian%2Fstretch) 15.2 |
NOTE:
An exception to this deprecation policy is when we are unable to provide
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 3bfb3ceca86..8b115ca1af4 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -739,7 +739,7 @@ auth:
Without these entries, the registry logins cannot authenticate with GitLab.
GitLab also remains unaware of
-[nested image names](../../user/packages/container_registry/#image-naming-convention)
+[nested image names](../../user/packages/container_registry/index.md#image-naming-convention)
under the project hierarchy, like
`registry.example.com/group/project/image-name:tag` or
`registry.example.com/group/project/my/image-name:tag`, and only recognizes
@@ -1202,8 +1202,8 @@ Before diving in to the following sections, here's some basic troubleshooting:
been synchronized (for example, via NTP).
1. If you are using an S3-backed Registry, double check that the IAM
- permissions and the S3 credentials (including region) are correct. See [the
- sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
+ permissions and the S3 credentials (including region) are correct. See
+ [the sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
for more details.
1. Check the Registry logs (for example `/var/log/gitlab/registry/current`) and the GitLab production logs
@@ -1388,7 +1388,7 @@ project or branch name. Special characters can include:
- Trailing hyphen/dash
- Double hyphen/dash
-To get around this, you can [change the group path](../../user/group/index.md#change-a-groups-path),
+To get around this, you can [change the group path](../../user/group/manage.md#change-a-groups-path),
[change the project path](../../user/project/settings/index.md#rename-a-repository) or change the
branch name. Another option is to create a [push rule](../../user/project/repository/push_rules.md) to prevent
this at the instance level.
@@ -1631,8 +1631,8 @@ wrong. However, since all communications between Docker clients and servers
are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
if you know the private key. What can we do instead?
-One way would be to disable HTTPS by setting up an [insecure
-Registry](https://docs.docker.com/registry/insecure/). This could introduce a
+One way would be to disable HTTPS by setting up an
+[insecure Registry](https://docs.docker.com/registry/insecure/). This could introduce a
security hole and is only recommended for local testing. If you have a
production system and can't or don't want to do this, there is another way:
use mitmproxy, which stands for Man-in-the-Middle Proxy.
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index b58eeff48cf..e545fb3cd1b 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -78,7 +78,7 @@ among other things.
Follow [these instructions](https://publicsuffix.org/submit/) to submit your
GitLab Pages subdomain. For instance, if your domain is `example.io`, you should
request that `example.io` is added to the Public Suffix List. GitLab.com
-added `gitlab.io` [in 2016](https://gitlab.com/gitlab-com/infrastructure/-/issues/230).
+added `gitlab.io` [in 2016](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/230).
### DNS configuration
@@ -614,7 +614,7 @@ Follow the steps below to configure verbose logging of GitLab Pages daemon.
Setting the `propagate_correlation_id` to true allows installations behind a reverse proxy to generate
and set a correlation ID to requests sent to GitLab Pages. When a reverse proxy sets the header value `X-Request-ID`,
the value propagates in the request chain.
-Users [can find the correlation ID in the logs](../troubleshooting/tracing_correlation_id.md#identify-the-correlation-id-for-a-request).
+Users [can find the correlation ID in the logs](../logs/tracing_correlation_id.md#identify-the-correlation-id-for-a-request).
To enable the propagation of the correlation ID:
@@ -933,8 +933,8 @@ The following settings are:
| `connection` | Various connection options described below. | |
NOTE:
-If you want to stop using and disconnect the NFS server, you need to [explicitly disable
-local storage](#disable-pages-local-storage), and it's only possible after upgrading to GitLab 13.11.
+If you want to stop using and disconnect the NFS server, you need to
+[explicitly disable local storage](#disable-pages-local-storage), and it's only possible after upgrading to GitLab 13.11.
#### S3-compatible connection settings
@@ -1319,25 +1319,6 @@ and in your Pages log shows this error:
sudo gitlab-ctl restart gitlab-pages
```
-### 404 error after promoting a Geo secondary to a primary node
-
-Pages files are not among the
-[supported data types](../geo/replication/datatypes.md#limitations-on-replicationverification) for replication in Geo. After a secondary node is promoted to a primary node, attempts to access a Pages site result in a `404 Not Found` error.
-
-It is possible to copy the subfolders and files in the [Pages path](#change-storage-path)
-to the new primary node to resolve this.
-For example, you can adapt the `rsync` strategy from the
-[moving repositories documentation](../operations/moving_repositories.md).
-Alternatively, run the CI pipelines of those projects that contain a `pages` job again.
-
-### 404 or 500 error when accessing GitLab Pages in a Geo setup
-
-Pages sites are only available on the primary Geo site, while the codebase of the project is available on all sites.
-
-If you try to access a Pages page on a secondary site, a 404 or 500 HTTP code is returned depending on the access control.
-
-Read more which [features don't support Geo replication/verification](../geo/replication/datatypes.md#limitations-on-replicationverification).
-
### Failed to connect to the internal GitLab API
If you see the following error:
@@ -1495,7 +1476,7 @@ In GitLab 14.0-14.2 you can temporarily enable legacy storage and configuration
To do that:
-1. Please describe the issue you're seeing in the [migration feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331699).
+1. Describe the issue you're seeing in the [migration feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331699).
1. Edit `/etc/gitlab/gitlab.rb`:
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 4bb9fc56b6f..5ab508dbaca 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -14,8 +14,7 @@ This is the documentation for configuring a GitLab Pages when you have installed
GitLab from source and not using the Omnibus packages.
You are encouraged to read the [Omnibus documentation](index.md) as it provides
-some invaluable information to the configuration of GitLab Pages. Please proceed
-to read it before going forward with this guide.
+invaluable information about the configuration of GitLab Pages.
We also highly recommend that you use the Omnibus GitLab packages. We
optimize them specifically for GitLab, and we take care of upgrading GitLab
diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md
index b03abf9881c..f53b50192eb 100644
--- a/doc/administration/postgresql/database_load_balancing.md
+++ b/doc/administration/postgresql/database_load_balancing.md
@@ -180,7 +180,7 @@ gitlab_rails['db_load_balancing'] = {
## Logging
The load balancer logs various events in
-[`database_load_balancing.log`](../logs.md#database_load_balancinglog), such as
+[`database_load_balancing.log`](../logs/index.md#database_load_balancinglog), such as
- When a host is marked as offline
- When a host comes back online
diff --git a/doc/administration/pseudonymizer.md b/doc/administration/pseudonymizer.md
index b14c1f64efe..8f27d41b75f 100644
--- a/doc/administration/pseudonymizer.md
+++ b/doc/administration/pseudonymizer.md
@@ -8,8 +8,7 @@ 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.
+> [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/maintenance.md b/doc/administration/raketasks/maintenance.md
index 6de47c37957..a900da52aba 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -187,7 +187,7 @@ Checking GitLab ... Finished
In some cases it is necessary to rebuild the `authorized_keys` file,
for example, if after an upgrade you receive `Permission denied (publickey)` when pushing [via SSH](../../user/ssh.md)
-and find `404 Key Not Found` errors in [the `gitlab-shell.log` file](../logs.md#gitlab-shelllog).
+and find `404 Key Not Found` errors in [the `gitlab-shell.log` file](../logs/index.md#gitlab-shelllog).
To rebuild `authorized_keys`, run:
**Omnibus Installation**
diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md
index f623d4e4526..f3a9845d129 100644
--- a/doc/administration/raketasks/project_import_export.md
+++ b/doc/administration/raketasks/project_import_export.md
@@ -17,11 +17,7 @@ GitLab provides Rake tasks relating to project import and export. For more infor
You can query an import 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.
-## Import large projects
-
-If you have a larger project, consider using a Rake task, as described in our [developer documentation](../../development/import_project.md#importing-via-a-rake-task).
-
-## Import/export tasks
+## Import/export Rake tasks
The GitLab import/export version can be checked by using the following command:
@@ -57,3 +53,38 @@ Note the following:
- The exports are stored in a temporary directory and are deleted every
24 hours by a specific worker.
+
+### Import large projects using a Rake task
+
+If you have a larger project, consider using a Rake task as described in our [developer documentation](../../development/import_project.md#importing-via-a-rake-task).
+
+### Export using a Rake task
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25598) in GitLab 12.9.
+
+You can use a Rake task to export large project.
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `username` | string | yes | User name |
+| `namespace_path` | string | yes | Namespace path |
+| `project_path` | string | yes | Project name |
+| `archive_path` | string | yes | Path to file to store the export project tarball |
+
+```shell
+gitlab-rake "gitlab:import_export:export[username, namespace_path, project_path, archive_path]"
+```
+
+## Troubleshooting
+
+If you are having trouble with import/export, you can enable debug mode using the same Rake task:
+
+```shell
+# Import
+IMPORT_DEBUG=true gitlab-rake "gitlab:import_export:import[root, group/subgroup, testingprojectimport, /path/to/file_to_import.tar.gz]"
+
+# Export
+EXPORT_DEBUG=true gitlab-rake "gitlab:import_export:export[root, group/subgroup, projectnametoexport, /tmp/export_file.tar.gz]"
+```
diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md
index 9b1a456835a..c4b83b66738 100644
--- a/doc/administration/redis/replication_and_failover.md
+++ b/doc/administration/redis/replication_and_failover.md
@@ -16,14 +16,14 @@ In Redis lingo, `primary` is called `master`. In this document, `primary` is use
instead of `master`, except the settings where `master` is required.
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -67,7 +67,7 @@ When a **Primary** fails to respond, it's the application's responsibility
for a new **Primary**).
To get a better understanding on how to correctly set up Sentinel, please read
-the [Redis Sentinel documentation](https://redis.io/topics/sentinel) first, as
+the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation first, as
failing to configure it correctly can lead to data loss or can bring your
whole cluster down, invalidating the failover effort.
@@ -343,8 +343,8 @@ NOTE:
If you are using an external Redis Sentinel instance, be sure
to exclude the `requirepass` parameter from the Sentinel
configuration. This parameter causes clients to report `NOAUTH
-Authentication required.`. [Redis Sentinel 3.2.x does not support
-password authentication](https://github.com/antirez/redis/issues/3279).
+Authentication required.`.
+[Redis Sentinel 3.2.x does not support password authentication](https://github.com/antirez/redis/issues/3279).
Now that the Redis servers are all set up, let's configure the Sentinel
servers.
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index 998455e5621..d624fe28f80 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -148,7 +148,7 @@ starting with `sentinel` prefix.
Assuming that the Redis Sentinel is installed on the same instance as Redis
primary with IP `10.0.0.1` (some settings might overlap with the primary):
-1. [Install Redis Sentinel](https://redis.io/topics/sentinel).
+1. [Install Redis Sentinel](https://redis.io/docs/manual/sentinel/).
1. Edit `/etc/redis/sentinel.conf`:
```conf
diff --git a/doc/administration/redis/troubleshooting.md b/doc/administration/redis/troubleshooting.md
index ca52fe0a29a..f9e5390c227 100644
--- a/doc/administration/redis/troubleshooting.md
+++ b/doc/administration/redis/troubleshooting.md
@@ -167,4 +167,4 @@ production:
port: 26379 # point to sentinel, not to redis port
```
-When in doubt, read the [Redis Sentinel documentation](https://redis.io/topics/sentinel).
+When in doubt, read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation.
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index a64828be4be..fcc32100bc8 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -693,7 +693,8 @@ SSH in to any of the Patroni nodes on the **primary site**:
```
If the 'State' column for any node doesn't say "running", check the
-[Troubleshooting section](troubleshooting.md) before proceeding.
+[PostgreSQL replication and failover troubleshooting section](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+before proceeding.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -800,14 +801,14 @@ The following IPs will be used as an example:
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -2062,10 +2063,8 @@ On each node perform the following:
```
1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml
- ```
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
@@ -2086,7 +2085,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 5b1e8bfc16b..51d3e3d39a6 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -696,7 +696,8 @@ SSH in to any of the Patroni nodes on the **primary site**:
```
If the 'State' column for any node doesn't say "running", check the
-[Troubleshooting section](troubleshooting.md) before proceeding.
+[PostgreSQL replication and failover troubleshooting section](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+before proceeding.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -803,14 +804,14 @@ The following IPs will be used as an example:
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -2067,10 +2068,8 @@ On each node perform the following:
```
1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml
- ```
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
@@ -2091,7 +2090,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index df84bf0402d..8ca58da55ca 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -512,10 +512,8 @@ Updates to example must be made at:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Confirm that Gitaly can perform callbacks to the internal API:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml
- ```
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
### Gitaly TLS support
@@ -658,10 +656,12 @@ On each node perform the following:
# Set the network addresses that the exporters used for monitoring will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229'
+ puma['listen'] = '0.0.0.0'
sidekiq['listen_address'] = "0.0.0.0"
- # Set number of Sidekiq threads per queue process to the recommend number of 10
+
+ # Configure Sidekiq with 2 workers and 10 max concurrency
sidekiq['max_concurrency'] = 10
- puma['listen'] = '0.0.0.0'
+ sidekiq['queue_groups'] = ['*'] * 2
# Add the monitoring node's IP address to the monitoring whitelist and allow it to
# scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with
@@ -766,7 +766,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
@@ -1011,8 +1011,8 @@ future with further specific cloud provider details.
| Service | Nodes | Configuration | GCP | AWS | Min Allocatable CPUs and Memory |
|-----------------------------------------------|-------|------------------------|-----------------|--------------|---------------------------------|
| Webservice | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | 23.7 vCPU, 16.9 GB memory |
-| Sidekiq | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | 3.9 vCPU, 11.8 GB memory |
-| Supporting services such as NGINX, Prometheus | 2 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | 1.9 vCPU, 5.5 GB memory |
+| Sidekiq | 1 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | 3.9 vCPU, 11.8 GB memory |
+| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | 1.9 vCPU, 5.5 GB memory |
- For this setup, we **recommend** and regularly [test](index.md#validation-and-test-results)
[Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary.
@@ -1048,8 +1048,8 @@ card "Kubernetes via Helm Charts" as kubernetes {
together {
collections "**Webservice** x3" as gitlab #32CD32
- collections "**Sidekiq** x2" as sidekiq #ff8dd1
- card "**Supporting Services**" as support
+ card "**Sidekiq**" as sidekiq #ff8dd1
+ collections "**Supporting Services** x2" as support
}
}
@@ -1082,13 +1082,13 @@ documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
-Each Webservice pod consumes roughly 2 vCPUs and 2.5 GB of memory using
+Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because two worker processes
are created by default and each pod has other small processes running.
For 2,000 users we recommend a total Puma worker count of around 12.
-With the [provided recommendations](#cluster-topology) this allows the deployment of up to 6
-Webservice pods with 2 workers per pod and 2 pods per node. Expand available resources using
+With the [provided recommendations](#cluster-topology) this allows the deployment of up to 3
+Webservice pods with 4 workers per pod and 1 pod per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional
Webservice pod.
@@ -1099,7 +1099,7 @@ For further information on resource usage, see the [Webservice resources](https:
Sidekiq pods should generally have 1 vCPU and 2 GB of memory.
[The provided starting point](#cluster-topology) allows the deployment of up to
-2 Sidekiq pods. Expand available resources using the 1 vCPU to 2GB memory
+4 Sidekiq pods. Expand available resources using the 1 vCPU to 2 GB memory
ratio for each additional pod.
For further information on resource usage, see the [Sidekiq resources](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#resources).
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 6a70739ca31..db81ae7ae3c 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -425,14 +425,14 @@ all nodes.
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -978,7 +978,8 @@ SSH in to any of the Patroni nodes on the **primary site**:
```
If the 'State' column for any node doesn't say "running", check the
-[Troubleshooting section](troubleshooting.md) before proceeding.
+[PostgreSQL replication and failover troubleshooting section](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+before proceeding.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -2018,7 +2019,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 0d0e44e2364..535e483cb7d 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -703,7 +703,8 @@ SSH in to any of the Patroni nodes on the **primary site**:
```
If the 'State' column for any node doesn't say "running", check the
-[Troubleshooting section](troubleshooting.md) before proceeding.
+[PostgreSQL replication and failover troubleshooting section](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+before proceeding.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -810,14 +811,14 @@ The following IPs will be used as an example:
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -2083,10 +2084,8 @@ On each node perform the following:
```
1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml
- ```
+ - For GitLab 15.3 and later, run `sudo /opt/gitlab/embedded/bin/gitaly check /var/opt/gitlab/gitaly/config.toml`.
+ - For GitLab 15.2 and earlier, run `sudo /opt/gitlab/embedded/bin/gitaly-hooks check /var/opt/gitlab/gitaly/config.toml`.
When you specify `https` in the `external_url`, as in the previous example,
GitLab expects that the SSL certificates are in `/etc/gitlab/ssl/`. If the
@@ -2107,7 +2106,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index ef2e48baa33..e19440e7660 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -423,14 +423,14 @@ all nodes.
## Configure Redis
Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica**
-topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically
+topology with a [Redis Sentinel](https://redis.io/docs/manual/sentinel/) service to watch and automatically
start the failover procedure.
Redis requires authentication if used with Sentinel. See
-[Redis Security](https://redis.io/topics/security) documentation for more
+[Redis Security](https://redis.io/docs/manual/security/) documentation for more
information. We recommend using a combination of a Redis password and tight
firewall rules to secure your Redis service.
-You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation
+You are highly encouraged to read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation
before configuring Redis with GitLab to fully understand the topology and
architecture.
@@ -975,7 +975,8 @@ SSH in to any of the Patroni nodes on the **primary site**:
```
If the 'State' column for any node doesn't say "running", check the
-[Troubleshooting section](troubleshooting.md) before proceeding.
+[PostgreSQL replication and failover troubleshooting section](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server)
+before proceeding.
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
@@ -2018,7 +2019,7 @@ the [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#en
failing to connect to PostgreSQL, it may be that your PgBouncer node's IP
address is missing from PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb`
on your database nodes. Before proceeding, see
- [PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
+ [PgBouncer error `ERROR: pgbouncer cannot connect to server`](../postgresql/replication_and_failover.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server).
1. [Configure fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md).
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index e996acb1157..7be12e12386 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -240,7 +240,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=b51f178f4403b69a63f6eb33ea425f82de3bf249">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/1adf30bef7e34ceba9efa97c4470417b">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=1adf30bef7e34ceba9efa97c4470417b">Calculated cost</a></td>
</tr>
<tr>
<th scope="row">2k</th>
@@ -248,7 +248,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=dce36b5cb6ab25211f74e47233d77f58fefb54e2">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/72764902f3854f798407fb03c3de4b6f">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=72764902f3854f798407fb03c3de4b6f">Calculated cost</a></td>
</tr>
<tr>
<th scope="row">3k</th>
@@ -256,7 +256,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=b1c5b4e32e990eaeb035a148255132bd28988760">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/0dbfc575051943b9970e5d8ace03680d">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=0dbfc575051943b9970e5d8ace03680d">Calculated cost</a></td>
</tr>
<tr>
<th scope="row">5k</th>
@@ -264,7 +264,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=2bf1af883096e6f4c6efddb4f3c35febead7fec2">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/8f618711ffec4b039f1581871ca6a7c9">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=8f618711ffec4b039f1581871ca6a7c9">Calculated cost</a></td>
</tr>
<tr>
<th scope="row">10k</th>
@@ -272,7 +272,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=1d374df13c0f2088d332ab0134f5b1d0f717259e">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/de3da8286dda4d4db1362932bc75410b">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=de3da8286dda4d4db1362932bc75410b">Calculated cost</a></td>
</tr>
<tr>
<th scope="row">25k</th>
@@ -280,7 +280,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=46fe6a6e9256d9b7779fae59fbbfa7e836942b7d">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/69724ebd82914a60857da6a3ace05a64">Calculate cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=69724ebd82914a60857da6a3ace05a64">Calculate cost</a></td>
</tr>
<tr>
<th scope="row">50k</th>
@@ -288,7 +288,7 @@ The following table details the cost to run the different reference architecture
<td></td>
<td><a href="https://calculator.aws/#/estimate?id=e15926b1a3c7139e4faf390a3875ff807d2ab91c">Calculated cost</a></td>
<td></td>
- <td><a href="https://azure.com/e/3f973040ebc14023933d35f576c89846">Calculated cost</a></td>
+ <td><a href="https://azure.microsoft.com/en-us/pricing/calculator/?shared-estimate=3f973040ebc14023933d35f576c89846">Calculated cost</a></td>
</tr>
</table>
diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md
index 6e0aaacd598..a9bf035a528 100644
--- a/doc/administration/reference_architectures/troubleshooting.md
+++ b/doc/administration/reference_architectures/troubleshooting.md
@@ -1,352 +1,11 @@
---
-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
+redirect_to: '../configure.md'
+remove_date: '2022-10-24'
---
-# Troubleshooting a reference architecture setup **(FREE SELF)**
+This document was moved to [another location](../configure.md).
-This page serves as the troubleshooting documentation if you followed one of
-the [reference architectures](index.md#reference-architectures).
-
-## Troubleshooting object storage
-
-### S3 API compatibility issues
-
-Not all S3 providers [are fully compatible](../../raketasks/backup_gitlab.md#other-s3-providers)
-with the Fog library that GitLab uses. Symptoms include:
-
-```plaintext
-411 Length Required
-```
-
-### GitLab Pages can use object storage
-
-If you intend to use [GitLab Pages](../../user/project/pages/index.md), you can
-[configure object storage](../pages/index.md#using-object-storage).
-NFS is still available if you prefer.
-
-The [GitLab Pages Helm chart](https://docs.gitlab.com/charts/charts/gitlab/gitlab-pages/) is also available
-for Kubernetes deployments.
-
-### Incremental logging is required for CI to use object storage
-
-If you configure GitLab to use object storage for CI logs and artifacts,
-[you must also enable incremental logging](../job_logs.md#incremental-logging-architecture).
-
-### Proxy Download
-
-A number of the use cases for object storage allow client traffic to be redirected to the
-object storage back end, like when Git clients request large files via LFS or when
-downloading CI artifacts and logs.
-
-When the files are stored on local block storage or NFS, GitLab has to act as a proxy.
-With object storage, the default behavior is for GitLab to redirect to the object
-storage device rather than proxy the request.
-
-The `proxy_download` setting controls this behavior: the default is generally `false`.
-Verify this in the documentation for each use case. Set it to `true` to make
-GitLab proxy the files rather than redirect.
-
-When not proxying files, GitLab returns an
-[HTTP 302 redirect with a pre-signed, time-limited object storage URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298).
-This can result in some of the following problems:
-
-- If GitLab is using non-secure HTTP to access the object storage, clients may generate
-`https->http` downgrade errors and refuse to process the redirect. The solution to this
-is for GitLab to use HTTPS. LFS, for example, generates this error:
-
- ```plaintext
- LFS: lfsapi/client: refusing insecure redirect, https->http
- ```
-
-- Clients must trust the certificate authority that issued the object storage
-certificate, or may return common TLS errors such as:
-
- ```plaintext
- x509: certificate signed by unknown authority
- ```
-
-- Clients need network access to the object storage. Errors that might result
-if this access is not in place include:
-
- ```plaintext
- Received status code 403 from server: Forbidden
- ```
-
-### ETag mismatch
-
-Using the default GitLab settings, some object storage back-ends such as
-[MinIO](https://gitlab.com/gitlab-org/gitlab/-/issues/23188)
-and [Alibaba](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564)
-might generate `ETag mismatch` errors.
-
-When using GitLab direct upload, the
-[workaround for MinIO](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1564#note_244497658)
-is to use the `--compat` parameter on the server.
-
-We are working on a fix to GitLab component Workhorse, and also
-a workaround, in the mean time, to
-[allow ETag verification to be disabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18175).
-
-## Troubleshooting Redis
-
-There are a lot of moving parts that needs to be taken care carefully
-in order for the HA setup to work as expected.
-
-Before proceeding with the troubleshooting below, check your firewall rules:
-
-- Redis machines
- - Accept TCP connection in `6379`
- - Connect to the other Redis machines via TCP in `6379`
-- Sentinel machines
- - Accept TCP connection in `26379`
- - Connect to other Sentinel machines via TCP in `26379`
- - Connect to the Redis machines via TCP in `6379`
-
-### Troubleshooting Redis replication
-
-You can check if everything is correct by connecting to each server using
-`redis-cli` application, and sending the `info replication` command as below.
-
-```shell
-/opt/gitlab/embedded/bin/redis-cli -h <redis-host-or-ip> -a '<redis-password>' info replication
-```
-
-When connected to a `Primary` Redis, you see the number of connected
-`replicas`, and a list of each with connection details:
-
-```plaintext
-# Replication
-role:master
-connected_replicas:1
-replica0:ip=10.133.5.21,port=6379,state=online,offset=208037514,lag=1
-master_repl_offset:208037658
-repl_backlog_active:1
-repl_backlog_size:1048576
-repl_backlog_first_byte_offset:206989083
-repl_backlog_histlen:1048576
-```
-
-When it's a `replica`, you see details of the primary connection and if
-its `up` or `down`:
-
-```plaintext
-# Replication
-role:replica
-master_host:10.133.1.58
-master_port:6379
-master_link_status:up
-master_last_io_seconds_ago:1
-master_sync_in_progress:0
-replica_repl_offset:208096498
-replica_priority:100
-replica_read_only:1
-connected_replicas:0
-master_repl_offset:0
-repl_backlog_active:0
-repl_backlog_size:1048576
-repl_backlog_first_byte_offset:0
-repl_backlog_histlen:0
-```
-
-### Troubleshooting Sentinel
-
-If you get an error like: `Redis::CannotConnectError: No sentinels available.`,
-there may be something wrong with your configuration files or it can be related
-to [this issue](https://github.com/redis/redis-rb/issues/531).
-
-You must make sure you are defining the same value in `redis['master_name']`
-and `redis['master_password']` as you defined for your sentinel node.
-
-The way the Redis connector `redis-rb` works with sentinel is a bit
-non-intuitive. We try to hide the complexity in omnibus, but it still requires
-a few extra configurations.
-
----
-
-To make sure your configuration is correct:
-
-1. SSH into your GitLab application server
-1. Enter the Rails console:
-
- ```shell
- # For Omnibus installations
- sudo gitlab-rails console
-
- # For source installations
- sudo -u git rails console -e production
- ```
-
-1. Run in the console:
-
- ```ruby
- redis = Redis.new(Gitlab::Redis::SharedState.params)
- redis.info
- ```
-
- Keep this screen open and try to simulate a failover below.
-
-1. To simulate a failover on primary Redis, SSH into the Redis server and run:
-
- ```shell
- # port must match your primary redis port, and the sleep time must be a few seconds bigger than defined one
- redis-cli -h localhost -p 6379 DEBUG sleep 20
- ```
-
-1. Then back in the Rails console from the first step, run:
-
- ```ruby
- redis.info
- ```
-
- You should see a different port after a few seconds delay
- (the failover/reconnect time).
-
-## Troubleshooting Gitaly
-
-For troubleshooting information, see Gitaly and Gitaly Cluster
-[troubleshooting information](../gitaly/troubleshooting.md).
-
-## Troubleshooting the GitLab Rails application
-
-- `mount: wrong fs type, bad option, bad superblock on`
-
-You have not installed the necessary NFS client utilities. See step 1 above.
-
-- `mount: mount point /var/opt/gitlab/... does not exist`
-
-This particular directory does not exist on the NFS server. Ensure
-the share is exported and exists on the NFS server and try to remount.
-
-## Troubleshooting Monitoring
-
-If the monitoring node is not receiving any data, check that the exporters are
-capturing data.
-
-```shell
-curl "http[s]://localhost:<EXPORTER LISTENING PORT>/metric"
-```
-
-or
-
-```shell
-curl "http[s]://localhost:<EXPORTER LISTENING PORT>/-/metric"
-```
-
-## Troubleshooting PgBouncer
-
-In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs:
-
-```shell
-sudo gitlab-ctl tail pgbouncer
-```
-
-Additionally, you can check the output from `show databases` in the [administrative console](#pgbouncer-administrative-console). In the output, you would expect to see values in the `host` field for the `gitlabhq_production` database. Additionally, `current_connections` should be greater than 1.
-
-### PgBouncer administrative console
-
-As part of Omnibus GitLab, the `gitlab-ctl pgb-console` command is provided to automatically connect to the PgBouncer administrative console. See the [PgBouncer documentation](https://www.pgbouncer.org/usage.html#admin-console) for detailed instructions on how to interact with the console.
-
-To start a session:
-
-```shell
-sudo gitlab-ctl pgb-console
-```
-
-The password you are prompted for is the `pgbouncer_user_password`
-
-To get some basic information about the instance, run
-
-```shell
-pgbouncer=# show databases; show clients; show servers;
- name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections
----------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+---------------------
- gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1
- pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0
-(2 rows)
-
- type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link
-| remote_pid | tls
-------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------
-+------------+-----
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 |
-| 0 |
- C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 |
-| 0 |
- C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 |
-| 0 |
-(8 rows)
-
- type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem
-ote_pid | tls
-------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+----
---------+-----
- S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | |
- 19980 |
-(1 row)
-```
-
-### Message: `LOG: invalid CIDR mask in address`
-
-See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-cidr-mask-in-address).
-
-### Message: `LOG: invalid IP mask "md5": Name or service not known`
-
-See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-ip-mask-md5-name-or-service-not-known).
-
-## Troubleshooting PostgreSQL with Patroni
-
-In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs for PostgreSQL (which is run through Patroni):
-
-```shell
-sudo gitlab-ctl tail patroni
-```
-
-### Consul and PostgreSQL with Patroni changes not taking effect
-
-Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it does not restart the services. However, not all changes can be activated by reloading.
-
-To restart either service, run `gitlab-ctl restart consul` or `gitlab-ctl restart patroni` respectively.
-
-For PostgreSQL with Patroni, to prevent the primary node from being failed over automatically, it's safest to stop all secondaries first, then restart the primary and finally restart the secondaries again.
-
-On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../consul.md#restart-consul) for instructions on how to restart the service.
-
-### PgBouncer error `ERROR: pgbouncer cannot connect to server`
-
-You may get this error when running `gitlab-rake gitlab:db:configure` or you
-may see the error in the PgBouncer log file.
-
-```plaintext
-PG::ConnectionBad: ERROR: pgbouncer cannot connect to server
-```
-
-The problem may be that your PgBouncer node's IP address is not included in the
-`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes.
-
-You can confirm that this is the issue by checking the PostgreSQL log on the primary
-database node. If you see the following error then `trust_auth_cidr_addresses`
-is the problem.
-
-```plaintext
-2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off
-```
-
-To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`.
-
-```ruby
-postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>)
-```
-
-[Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+<!-- This redirect file can be deleted after <2022-10-24>. -->
+<!-- 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/repository_checks.md b/doc/administration/repository_checks.md
index 8cfefdb9b56..a97c8611239 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -7,8 +7,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Repository checks **(FREE SELF)**
You can use [`git fsck`](https://git-scm.com/docs/git-fsck) to verify the integrity of all data
-committed to a repository. GitLab administrators can trigger this check for a project using the
-GitLab UI:
+committed to a repository. GitLab administrators can:
+
+- Manually trigger this check for a project, using the GitLab UI.
+- Schedule this check to run automatically for all projects.
+- Run this check from the command line.
+- Run a [Rake task](raketasks/check.md#repository-integrity) for checking Git repositories, which can be used to run
+ `git fsck` against all repositories and generate repository checksums, as a way to compare repositories on different
+ servers.
+
+## Check a project's repository using GitLab UI
+
+To check a project's repository using GitLab UI:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Projects**.
@@ -18,9 +28,7 @@ GitLab UI:
The checks run asynchronously so it may take a few minutes before the check result is visible on the
project page in the Admin Area. If the checks fail, see [what to do](#what-to-do-if-a-check-failed).
-This setting is off by default, because it can cause many false alarms.
-
-## Enable periodic checks
+## Enable repository checks for all projects
Instead of checking repositories manually, GitLab can be configured to run the checks periodically:
@@ -45,13 +53,31 @@ the start of Sunday.
Repositories with known check failures can be found at
`/admin/projects?last_repository_check_failed=1`.
+## Run a check using the command line
+
+You can run [`git fsck`](https://git-scm.com/docs/git-fsck) using the command line on repositories on
+[Gitaly servers](gitaly/index.md). To locate the repositories:
+
+1. Go to the storage location for repositories:
+ - For Omnibus GitLab installations, repositories are stored in the `/var/opt/gitlab/git-data/repositories` directory
+ by default.
+ - For GitLab Helm chart installations, repositories are stored in the `/home/git/repositories` directory inside the
+ Gitaly pod by default.
+1. [Identify the subdirectory that contains the repository](repository_storage_types.md#from-project-name-to-hashed-path)
+ that you need to check.
+1. Run the check. For example:
+
+ ```shell
+ sudo /opt/gitlab/embedded/bin/git -C /var/opt/gitlab/git-data/repositories/@hashed/0b/91/0b91...f9.git fsck
+ ```
+
## What to do if a check failed
-If a repository check fails, locate the error in the [`repocheck.log` file](logs.md#repochecklog) on
-disk at:
+If a repository check fails, locate the error in the [`repocheck.log` file](logs/index.md#repochecklog) on disk at:
- `/var/log/gitlab/gitlab-rails` for Omnibus GitLab installations.
- `/home/git/gitlab/log` for installations from source.
+- `/var/log/gitlab` in the Sidekiq pod for GitLab Helm chart installations.
If periodic repository checks cause false alarms, you can clear all repository check states:
@@ -59,23 +85,3 @@ If periodic repository checks cause false alarms, you can clear all repository c
1. On the left sidebar, select **Settings > Repository** (`/admin/application_settings/repository`).
1. Expand the **Repository maintenance** section.
1. Select **Clear all repository checks**.
-
-## Run a check using the command line
-
-You can run [`git fsck`](https://git-scm.com/docs/git-fsck) using the command line on repositories
-on [Gitaly servers](gitaly/index.md). To locate the repositories:
-
-1. Go to the storage location for repositories. For Omnibus GitLab installations, repositories are
- stored by default in the `/var/opt/gitlab/git-data/repositories` directory.
-1. [Identify the subdirectory that contains the repository](repository_storage_types.md#from-project-name-to-hashed-path)
- that you need to check.
-
-To run a check (for example):
-
-```shell
-sudo /opt/gitlab/embedded/bin/git -C /var/opt/gitlab/git-data/repositories/@hashed/0b/91/0b91...f9.git fsck
-```
-
-You can also run [Rake tasks](raketasks/check.md#repository-integrity) for checking Git
-repositories, which can be used to run `git fsck` against all repositories and generate repository
-checksums, as a way to compare repositories on different servers.
diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md
index 6ac031ea6bd..6625039504a 100644
--- a/doc/administration/restart_gitlab.md
+++ b/doc/administration/restart_gitlab.md
@@ -102,8 +102,8 @@ depend on those files.
## Installations from source
-If you have followed the official installation guide to [install GitLab from
-source](../install/installation.md), run the following command to restart GitLab:
+If you have followed the official installation guide to
+[install GitLab from source](../install/installation.md), run the following command to restart GitLab:
```shell
# For systems running systemd
diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md
index fc24c764330..01f83f98607 100644
--- a/doc/administration/sidekiq.md
+++ b/doc/administration/sidekiq.md
@@ -1,385 +1,11 @@
---
-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
+redirect_to: 'sidekiq/index.md'
+remove_date: '2022-11-11'
---
-# Configure an external Sidekiq instance **(FREE SELF)**
+This document was moved to [another location](sidekiq/index.md).
-You can configure an external Sidekiq instance by using the Sidekiq that's bundled in the GitLab package. Sidekiq requires connection to the Redis,
-PostgreSQL, and Gitaly instances.
-
-## Configure TCP access for PostgreSQL, Gitaly, and Redis
-
-By default, GitLab uses UNIX sockets and is not set up to communicate via TCP. To change this:
-
-1. Edit the `/etc/gitlab/gitlab.rb` file on your GitLab instance, and add the following:
-
- ```ruby
-
- ## PostgreSQL
-
- # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
- postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
- postgresql['listen_address'] = '0.0.0.0'
- postgresql['port'] = 5432
-
- # Add the Sidekiq nodes to PostgreSQL's trusted addresses.
- # In the following example, 10.10.1.30/32 is the private IP
- # of the Sidekiq server.
- postgresql['md5_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32)
- postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32)
-
- ## Gitaly
-
- # Make Gitaly accept connections on all network interfaces
- gitaly['listen_addr'] = "0.0.0.0:8075"
- ## Set up the Gitaly token as a form of authentication since you are accessing Gitaly over the network
- ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token
- gitaly['auth_token'] = 'abc123secret'
- praefect['auth_token'] = 'abc123secret'
- gitlab_rails['gitaly_token'] = 'abc123secret'
-
- ## Redis configuration
-
- redis['bind'] = '0.0.0.0'
- redis['port'] = 6379
- # Password to Authenticate Redis
- redis['password'] = 'redis-password-goes-here'
- gitlab_rails['redis_password'] = 'redis-password-goes-here'
-
- gitlab_rails['auto_migrate'] = false
- ```
-
-1. Run `reconfigure`:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-1. Restart the `PostgreSQL` server:
-
- ```shell
- sudo gitlab-ctl restart postgresql
- ```
-
-1. After the restart, set `auto_migrate` to `true` or comment to use the default settings:
-
- ```ruby
- gitlab_rails['auto_migrate'] = true
- ```
-
-1. Run `reconfigure` again:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-## Set up Sidekiq instance
-
-1. SSH into the Sidekiq server.
-
-1. Confirm that you can access the PostgreSQL, Gitaly, and Redis ports:
-
- ```shell
- telnet <GitLab host> 5432 # PostgreSQL
- telnet <GitLab host> 8075 # Gitaly
- telnet <GitLab host> 6379 # Redis
- ```
-
-1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab package
- using steps 1 and 2. **Do not complete any other steps.**
-
-1. Copy the `/etc/gitlab/gitlab.rb` file from the GitLab instance and add the following settings. Make sure
- to replace them with your values:
-
-<!--
-Updates to example must be made at:
-- https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/sidekiq.md
-- all reference architecture pages
--->
-
- ```ruby
- ########################################
- ##### Services Disabled ###
- ########################################
- #
- # When running GitLab on just one server, you have a single `gitlab.rb`
- # to enable all services you want to run.
- # When running GitLab on N servers, you have N `gitlab.rb` files.
- # Enable only the services you want to run on each
- # specific server, while disabling all others.
- #
- gitaly['enable'] = false
- postgresql['enable'] = false
- redis['enable'] = false
- nginx['enable'] = false
- puma['enable'] = false
- gitlab_workhorse['enable'] = false
- prometheus['enable'] = false
- alertmanager['enable'] = false
- grafana['enable'] = false
- gitlab_exporter['enable'] = false
- gitlab_kas['enable'] = false
-
- ##
- ## To maintain uniformity of links across nodes, the
- ## `external_url` on the Sidekiq server should point to the external URL that users
- ## use to access GitLab. This can be either:
- ##
- ## - The `external_url` set on your application server.
- ## - The URL of a external load balancer, which routes traffic to the GitLab application server.
- ##
- external_url 'https://gitlab.example.com'
-
- # Configure the gitlab-shell API callback URL. Without this, `git push` will
- # fail. This can be your 'front door' GitLab URL or an internal load
- # balancer.
- gitlab_rails['internal_api_url'] = 'GITLAB_URL'
- gitlab_shell['secret_token'] = 'SHELL_TOKEN'
-
- ########################################
- #### Redis ###
- ########################################
-
- ## Must be the same in every sentinel node.
- redis['master_name'] = 'gitlab-redis' # Required if you have setup redis cluster
- ## The same password for Redis authentication you set up for the master node.
- redis['master_password'] = '<redis_master_password>'
-
- ### If redis is running on the main Gitlab instance and you have opened the TCP port as above add the following
- gitlab_rails['redis_host'] = '<gitlab_host>'
- gitlab_rails['redis_port'] = 6379
-
- #######################################
- ### Gitaly ###
- #######################################
-
- ## Replace <gitaly_token> with the one you set up, see
- ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token
- git_data_dirs({
- "default" => {
- "gitaly_address" => "tcp://<gitlab_host>:8075",
- "gitaly_token" => "<gitaly_token>"
- }
- })
-
- #######################################
- ### Postgres ###
- #######################################
-
- # Replace <database_host> and <database_password>
- gitlab_rails['db_host'] = '<database_host>'
- gitlab_rails['db_port'] = '5432'
- gitlab_rails['db_password'] = '<database_password>'
- ## Prevent database migrations from running on upgrade automatically
- gitlab_rails['auto_migrate'] = false
-
- #######################################
- ### Sidekiq configuration ###
- #######################################
- sidekiq['enable'] = true
- sidekiq['listen_address'] = "0.0.0.0"
-
- ## Set number of Sidekiq queue processes to the same number as available CPUs
- sidekiq['queue_groups'] = ['*'] * 4
-
- ## Set number of Sidekiq threads per queue process to the recommend number of 10
- sidekiq['max_concurrency'] = 10
- ```
-
-1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the GitLab instance and replace the file in the Sidekiq instance.
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-1. Restart the Sidekiq instance after completing the process and finishing the database migrations.
-
-## Configure multiple Sidekiq nodes with shared storage
-
-If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
-specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
-and GIDs prevents permissions issues in the file system. This advice is similar to the
-[advice for Geo setups](geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site).
-
-To set up multiple Sidekiq nodes:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- user['uid'] = 9000
- user['gid'] = 9000
- web_server['uid'] = 9001
- web_server['gid'] = 9001
- registry['uid'] = 9002
- registry['gid'] = 9002
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-## Configure the Container Registry when using an external Sidekiq
-
-If you're using the Container Registry and it's running on a different
-node than Sidekiq, follow the steps below.
-
-1. Edit `/etc/gitlab/gitlab.rb`, and configure the registry URL:
-
- ```ruby
- registry_external_url 'https://registry.example.com'
- gitlab_rails['registry_api_url'] = "https://registry.example.com"
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-1. In the instance where Container Registry is hosted, copy the `registry.key`
- file to the Sidekiq node.
-
-## Configure the Sidekiq metrics server
-
-If you want to collect Sidekiq metrics, enable the Sidekiq metrics server.
-To make metrics available from `localhost:8082/metrics`:
-
-To configure the metrics server:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- sidekiq['metrics_enabled'] = true
- sidekiq['listen_address'] = "localhost"
- sidekiq['listen_port'] = "8082"
-
- # Optionally log all the metrics server logs to log/sidekiq_exporter.log
- sidekiq['exporter_log_enabled'] = true
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-### Enable HTTPS
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364771) in GitLab 15.2.
-
-To serve metrics via HTTPS instead of HTTP, enable TLS in the exporter settings:
-
-1. Edit `/etc/gitlab/gitlab.rb` to add (or find and uncomment) the following lines:
-
- ```ruby
- sidekiq['exporter_tls_enabled'] = true
- sidekiq['exporter_tls_cert_path'] = "/path/to/certificate.pem"
- sidekiq['exporter_tls_key_path'] = "/path/to/private-key.pem"
- ```
-
-1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure)
- for the changes to take effect.
-
-When TLS is enabled, the same `port` and `address` are used as described above.
-The metrics server cannot serve both HTTP and HTTPS at the same time.
-
-## Configure health checks
-
-If you use health check probes to observe Sidekiq, enable the Sidekiq health check server.
-To make health checks available from `localhost:8092`:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- sidekiq['health_checks_enabled'] = true
- sidekiq['health_checks_listen_address'] = "localhost"
- sidekiq['health_checks_listen_port'] = "8092"
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-For more information about health checks, see the [Sidekiq health check page](sidekiq_health_check.md).
-
-## Configure LDAP and user or group synchronization
-
-If you use LDAP for user and group management, you must add the LDAP configuration to your Sidekiq node as well as the LDAP
-synchronization worker. If the LDAP configuration and LDAP synchronization worker are not applied to your Sidekiq node,
-users and groups are not automatically synchronized.
-
-For more information about configuring LDAP for GitLab, see:
-
-- [GitLab LDAP configuration documentation](auth/ldap/index.md#configure-ldap)
-- [LDAP synchronization documentation](auth/ldap/ldap_synchronization.md#adjust-ldap-user-sync-schedule)
-
-To enable LDAP with the synchronization worker for Sidekiq:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['ldap_enabled'] = true
- gitlab_rails['prevent_ldap_sign_in'] = false
- gitlab_rails['ldap_servers'] = {
- 'main' => {
- 'label' => 'LDAP',
- 'host' => 'ldap.mydomain.com',
- 'port' => 389,
- 'uid' => 'sAMAccountName',
- 'encryption' => 'simple_tls',
- 'verify_certificates' => true,
- 'bind_dn' => '_the_full_dn_of_the_user_you_will_bind_with',
- 'password' => '_the_password_of_the_bind_user',
- 'tls_options' => {
- 'ca_file' => '',
- 'ssl_version' => '',
- 'ciphers' => '',
- 'cert' => '',
- 'key' => ''
- },
- 'timeout' => 10,
- 'active_directory' => true,
- 'allow_username_or_email_login' => false,
- 'block_auto_created_users' => false,
- 'base' => 'dc=example,dc=com',
- 'user_filter' => '',
- 'attributes' => {
- 'username' => ['uid', 'userid', 'sAMAccountName'],
- 'email' => ['mail', 'email', 'userPrincipalName'],
- 'name' => 'cn',
- 'first_name' => 'givenName',
- 'last_name' => 'sn'
- },
- 'lowercase_usernames' => false,
-
- # Enterprise Edition only
- # https://docs.gitlab.com/ee/administration/auth/ldap/ldap_synchronization.html
- 'group_base' => '',
- 'admin_group' => '',
- 'external_groups' => [],
- 'sync_ssh_keys' => false
- }
- }
- gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
- ```
-
-1. Reconfigure GitLab:
-
- ```shell
- sudo gitlab-ctl reconfigure
- ```
-
-## Related topics
-
-- [Extra Sidekiq processes](operations/extra_sidekiq_processes.md)
-- [Extra Sidekiq routing](operations/extra_sidekiq_routing.md)
-- [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/)
-- [Sidekiq health checks](sidekiq_health_check.md)
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/administration/sidekiq/extra_sidekiq_processes.md b/doc/administration/sidekiq/extra_sidekiq_processes.md
new file mode 100644
index 00000000000..1cd3771c94d
--- /dev/null
+++ b/doc/administration/sidekiq/extra_sidekiq_processes.md
@@ -0,0 +1,362 @@
+---
+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
+---
+
+# Run multiple Sidekiq processes **(FREE SELF)**
+
+GitLab allows you to start multiple Sidekiq processes.
+These processes can be used to consume a dedicated set
+of queues. This can be used to ensure certain queues always have dedicated
+workers, no matter the number of jobs to be processed.
+
+NOTE:
+The information in this page applies only to Omnibus GitLab.
+
+## Available Sidekiq queues
+
+For a list of the existing Sidekiq queues, check the following files:
+
+- [Queues for both GitLab Community and Enterprise Editions](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
+- [Queues for GitLab Enterprise Editions only](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml)
+
+Each entry in the above files represents a queue on which Sidekiq processes
+can be started.
+
+## Start multiple processes
+
+> - [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4006) in GitLab 12.10, starting multiple processes with Sidekiq cluster.
+> - [Sidekiq cluster moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
+> - [Sidekiq cluster became default](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4140) in GitLab 13.0.
+
+When starting multiple processes, the number of processes should
+equal (and **not** exceed) the number of CPU cores you want to
+dedicate to Sidekiq. Each Sidekiq process can use only 1 CPU
+core, subject to the available workload and concurrency settings.
+
+To start multiple processes:
+
+1. Using the `sidekiq['queue_groups']` array setting, specify how many processes to
+ create using `sidekiq-cluster` and which queue they should handle.
+ Each item in the array equates to one additional Sidekiq
+ process, and values in each item determine the queues it works on.
+
+ For example, the following setting creates three Sidekiq processes, one to run on
+ `elastic_commit_indexer`, one to run on `mailers`, and one process running on all queues:
+
+ ```ruby
+ sidekiq['queue_groups'] = [
+ "elastic_commit_indexer",
+ "mailers",
+ "*"
+ ]
+ ```
+
+ To have an additional Sidekiq process handle multiple queues, add multiple
+ queue names to its item delimited by commas. For example:
+
+ ```ruby
+ sidekiq['queue_groups'] = [
+ "elastic_commit_indexer, elastic_association_indexer",
+ "mailers",
+ "*"
+ ]
+ ```
+
+ [In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
+ later, the special queue name `*` means all queues. This starts two
+ processes, each handling all queues:
+
+ ```ruby
+ sidekiq['queue_groups'] = [
+ "*",
+ "*"
+ ]
+ ```
+
+ `*` cannot be combined with concrete queue names - `*, mailers`
+ just handles the `mailers` queue.
+
+ When `sidekiq-cluster` is only running on a single node, make sure that at least
+ one process is running on all queues using `*`. This ensures a process
+ automatically picks up jobs in queues created in the future,
+ including queues that have dedicated processes.
+
+ If `sidekiq-cluster` is running on more than one node, you can also use
+ [`--negate`](#negate-settings) and list all the queues that are already being
+ processed.
+
+1. Save the file and reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+To view the Sidekiq processes in GitLab:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Monitoring > Background Jobs**.
+
+## Negate settings
+
+To have the Sidekiq process work on every queue **except** the ones
+you list. In this example, we exclude all import-related jobs from a Sidekiq node:
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq['negate'] = true
+ sidekiq['queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category=importers"
+ ]
+ ```
+
+1. Save the file and reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Queue selector
+
+> - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in GitLab 12.8.
+> - [Sidekiq cluster, including queue selector, moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab Free in 12.10.
+> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6.
+
+In addition to selecting queues by name, as above, the `queue_selector` option
+allows queue groups to be selected in a more general way using a
+[worker matching query](extra_sidekiq_routing.md#worker-matching-query). After `queue_selector`
+is set, all `queue_groups` must follow the aforementioned syntax.
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+sidekiq['enable'] = true
+sidekiq['queue_selector'] = true
+sidekiq['queue_groups'] = [
+ # Run all non-CPU-bound queues that are high urgency
+ 'resource_boundary!=cpu&urgency=high',
+ # Run all continuous integration and pages queues that are not high urgency
+ 'feature_category=continuous_integration,pages&urgency!=high',
+ # Run all queues
+ '*'
+]
+```
+
+## Ignore all import queues
+
+When [importing from GitHub](../../user/project/import/github.md) or
+other sources, Sidekiq might use all of its resources to perform those
+operations. To set up two separate `sidekiq-cluster` processes, where
+one only processes imports and the other processes all other queues:
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq['enable'] = true
+ sidekiq['queue_selector'] = true
+ sidekiq['queue_groups'] = [
+ "feature_category=importers",
+ "feature_category!=importers"
+ ]
+ ```
+
+1. Save the file and reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Number of threads
+
+By default each process defined under `sidekiq` starts with a
+number of threads that equals the number of queues, plus one spare thread.
+For example, a process that handles the `process_commit` and `post_receive`
+queues uses three threads in total.
+
+These thread run inside a single Ruby process, and each process
+can only use a single CPU core. The usefulness of threading depends
+on the work having some external dependencies to wait on, like database queries or
+HTTP requests. Most Sidekiq deployments benefit from this threading, and when
+running fewer queues in a process, increasing the thread count might be
+even more desirable to make the most effective use of CPU resources.
+
+### Manage thread counts explicitly
+
+The correct maximum thread count (also called concurrency) depends on the workload.
+Typical values range from `1` for highly CPU-bound tasks to `15` or higher for mixed
+low-priority work. A reasonable starting range is `15` to `25` for a non-specialized
+deployment.
+
+You can find example values used by GitLab.com by searching for `concurrency:` in
+[the Helm charts](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/blob/master/releases/gitlab/values/gprd.yaml.gotmpl).
+The values vary according to the work each specific deployment of Sidekiq does.
+Any other specialized deployments with processes dedicated to specific queues should
+have the concurrency tuned according to:
+have the concurrency tuned according to:
+
+- The CPU usage of each type of process.
+- The throughput achieved.
+
+Each thread requires a Redis connection, so adding threads may increase Redis
+latency and potentially cause client timeouts. See the
+[Sidekiq documentation about Redis](https://github.com/mperham/sidekiq/wiki/Using-Redis) for more
+details.
+
+#### When running Sidekiq cluster (default)
+
+Running Sidekiq cluster is the default in GitLab 13.0 and later.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq['min_concurrency'] = 15
+ sidekiq['max_concurrency'] = 25
+ ```
+
+1. Save the file and reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+`min_concurrency` and `max_concurrency` are independent; one can be set without
+the other. Setting `min_concurrency` to `0` disables the limit.
+
+For each queue group, let `N` be one more than the number of queues. The
+concurrency is set to:
+
+1. `N`, if it's between `min_concurrency` and `max_concurrency`.
+1. `max_concurrency`, if `N` exceeds this value.
+1. `min_concurrency`, if `N` is less than this value.
+
+If `min_concurrency` is equal to `max_concurrency`, then this value is used
+regardless of the number of queues.
+
+When `min_concurrency` is greater than `max_concurrency`, it is treated as
+being equal to `max_concurrency`.
+
+#### When running a single Sidekiq process
+
+Running a single Sidekiq process is the default in GitLab 12.10 and earlier.
+
+WARNING:
+Running Sidekiq directly was removed in GitLab
+[14.0](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/240).
+
+1. Edit `/etc/gitlab/gitlab.rb` and add:
+
+ ```ruby
+ sidekiq['cluster'] = false
+ sidekiq['concurrency'] = 25
+ ```
+
+1. Save the file and reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+This sets the concurrency (number of threads) for the Sidekiq process.
+
+## Modify the check interval
+
+To modify `sidekiq-cluster`'s health check interval for the additional Sidekiq processes:
+
+1. Edit `/etc/gitlab/gitlab.rb` and add (the value can be any integer number of seconds):
+
+ ```ruby
+ sidekiq['interval'] = 5
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+## Troubleshoot using the CLI
+
+WARNING:
+It's recommended to use `/etc/gitlab/gitlab.rb` to configure the Sidekiq processes.
+If you experience a problem, you should contact GitLab support. Use the command
+line at your own risk.
+
+For debugging purposes, you can start extra Sidekiq processes by using the command
+`/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster`. This command
+takes arguments using the following syntax:
+
+```shell
+/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster [QUEUE,QUEUE,...] [QUEUE, ...]
+```
+
+Each separate argument denotes a group of queues that have to be processed by a
+Sidekiq process. Multiple queues can be processed by the same process by
+separating them with a comma instead of a space.
+
+Instead of a queue, a queue namespace can also be provided, to have the process
+automatically listen on all queues in that namespace without needing to
+explicitly list all the queue names. For more information about queue namespaces,
+see the relevant section in the
+[Sidekiq development documentation](../../development/sidekiq/index.md#queue-namespaces).
+
+For example, say you want to start 2 extra processes: one to process the
+`process_commit` queue, and one to process the `post_receive` queue. This can be
+done as follows:
+
+```shell
+/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit post_receive
+```
+
+If you instead want to start one process processing both queues, you'd use the
+following syntax:
+
+```shell
+/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive
+```
+
+If you want to have one Sidekiq process dealing with the `process_commit` and
+`post_receive` queues, and one process to process the `gitlab_shell` queue,
+you'd use the following:
+
+```shell
+/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster process_commit,post_receive gitlab_shell
+```
+
+### Monitor the `sidekiq-cluster` command
+
+The `sidekiq-cluster` command does not terminate once it has started the desired
+amount of Sidekiq processes. Instead, the process continues running and
+forwards any signals to the child processes. This allows you to stop all
+Sidekiq processes as you send a signal to the `sidekiq-cluster` process,
+instead of having to send it to the individual processes.
+
+If the `sidekiq-cluster` process crashes or receives a `SIGKILL`, the child
+processes terminate themselves after a few seconds. This ensures you don't
+end up with zombie Sidekiq processes.
+
+This allows you to monitor the processes by hooking up
+`sidekiq-cluster` to your supervisor of choice (for example, runit).
+
+If a child process died the `sidekiq-cluster` command signals all remaining
+process to terminate, then terminate itself. This removes the need for
+`sidekiq-cluster` to re-implement complex process monitoring/restarting code.
+Instead you should make sure your supervisor restarts the `sidekiq-cluster`
+process whenever necessary.
+
+### PID files
+
+The `sidekiq-cluster` command can store its PID in a file. By default no PID
+file is written, but this can be changed by passing the `--pidfile` option to
+`sidekiq-cluster`. For example:
+
+```shell
+/opt/gitlab/embedded/service/gitlab-rails/bin/sidekiq-cluster --pidfile /var/run/gitlab/sidekiq_cluster.pid process_commit
+```
+
+Keep in mind that the PID file contains the PID of the `sidekiq-cluster`
+command and not the PIDs of the started Sidekiq processes.
+
+### Environment
+
+The Rails environment can be set by passing the `--environment` flag to the
+`sidekiq-cluster` command, or by setting `RAILS_ENV` to a non-empty value. The
+default value can be found in `/opt/gitlab/etc/gitlab-rails/env/RAILS_ENV`.
diff --git a/doc/administration/sidekiq/extra_sidekiq_routing.md b/doc/administration/sidekiq/extra_sidekiq_routing.md
new file mode 100644
index 00000000000..ebbf4059290
--- /dev/null
+++ b/doc/administration/sidekiq/extra_sidekiq_routing.md
@@ -0,0 +1,180 @@
+---
+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
+---
+
+# Queue routing rules **(FREE SELF)**
+
+When the number of Sidekiq jobs increases to a certain scale, the system faces
+some scalability issues. One of them is that the length of the queue tends to get
+longer. High-urgency jobs have to wait longer until other less urgent jobs
+finish. This head-of-line blocking situation may eventually affect the
+responsiveness of the system, especially critical actions. In another scenario,
+the performance of some jobs is degraded due to other long running or CPU-intensive jobs
+(computing or rendering ones) in the same machine.
+
+To counter the aforementioned issues, one effective solution is to split
+Sidekiq jobs into different queues and assign machines handling each queue
+exclusively. For example, all CPU-intensive jobs could be routed to the
+`cpu-bound` queue and handled by a fleet of CPU optimized instances. The queue
+topology differs between companies depending on the workloads and usage
+patterns. Therefore, GitLab supports a flexible mechanism for the
+administrator to route the jobs based on their characteristics.
+
+As an alternative to [Queue selector](extra_sidekiq_processes.md#queue-selector), which
+configures Sidekiq cluster to listen to a specific set of workers or queues,
+GitLab also supports routing a job from a worker to the desired queue when it
+is scheduled. Sidekiq clients try to match a job against a configured list of
+routing rules. Rules are evaluated from first to last, and as soon as we find a
+match for a given worker we stop processing for that worker (first match wins).
+If the worker doesn't match any rule, it falls back to the queue name generated
+from the worker name.
+
+By default, if the routing rules are not configured (or denoted with an empty
+array), all the jobs are routed to the queue generated from the worker name.
+
+## Example configuration
+
+In `/etc/gitlab/gitlab.rb`:
+
+```ruby
+sidekiq['routing_rules'] = [
+ # Do not re-route workers that require their own queue
+ ['tags=needs_own_queue', nil],
+ # Route all non-CPU-bound workers that are high urgency to `high-urgency` queue
+ ['resource_boundary!=cpu&urgency=high', 'high-urgency'],
+ # Route all database, gitaly and global search workers that are throttled to `throttled` queue
+ ['feature_category=database,gitaly,global_search&urgency=throttled', 'throttled'],
+ # Route all workers having contact with outside work to a `network-intenstive` queue
+ ['has_external_dependencies=true|feature_category=hooks|tags=network', 'network-intensive'],
+ # Route all import workers to the queues generated by the worker name, for
+ # example, JiraImportWorker to `jira_import`, SVNWorker to `svn_worker`
+ ['feature_category=import', nil],
+ # Wildcard matching, route the rest to `default` queue
+ ['*', 'default']
+]
+```
+
+The routing rules list is an order-matter array of tuples of query and
+corresponding queue:
+
+- The query is following a [worker matching query](#worker-matching-query) syntax.
+- The `<queue_name>` must be a valid Sidekiq queue name. If the queue name
+ is `nil`, or an empty string, the worker is routed to the queue generated
+ by the name of the worker instead.
+
+The query supports wildcard matching `*`, 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.
+
+NOTE:
+Mixing queue routing rules and queue selectors requires care to
+ensure all jobs that are scheduled and picked up by appropriate Sidekiq
+workers.
+
+## Worker matching query
+
+GitLab provides a query syntax to match a worker based on its
+attributes. This query syntax is employed by both
+[Queue routing rules](#queue-routing-rules) and
+[Queue selector](extra_sidekiq_processes.md#queue-selector). A query includes two
+components:
+
+- Attributes that can be selected.
+- Operators used to construct a query.
+
+### Available attributes
+
+> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1 (`tags`).
+
+Queue matching query works upon the worker attributes, described in
+[Sidekiq style guide](../../development/sidekiq/index.md). We support querying
+based on a subset of worker attributes:
+
+- `feature_category` - the
+ [GitLab feature category](https://about.gitlab.com/direction/maturity/#category-maturity) the
+ queue belongs to. For example, the `merge` queue belongs to the
+ `source_code_management` category.
+- `has_external_dependencies` - whether or not the queue connects to external
+ services. For example, all importers have this set to `true`.
+- `urgency` - how important it is that this queue's jobs run
+ quickly. Can be `high`, `low`, or `throttled`. For example, the
+ `authorized_projects` queue is used to refresh user permissions, and
+ is `high` urgency.
+- `worker_name` - the worker name. Use this attribute to select a specific worker.
+- `name` - the queue name generated from the worker name. Use this attribute to select a specific queue. Because this is generated from
+ the worker name, it does not change based on the result of other routing
+ rules.
+- `resource_boundary` - if the queue is bound by `cpu`, `memory`, or
+ `unknown`. For example, the `ProjectExportWorker` is memory bound as it has
+ to load data in memory before saving it for export.
+- `tags` - short-lived annotations for queues. These are expected to frequently
+ change from release to release, and may be removed entirely.
+
+`has_external_dependencies` is a boolean attribute: only the exact
+string `true` is considered true, and everything else is considered
+false.
+
+`tags` is a set, which means that `=` checks for intersecting sets, and
+`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
+that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
+neither of those tags.
+
+The attributes of each worker are hard-coded in the source code. For
+convenience, we generate a
+[list of all available attributes in GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml)
+and a
+[list of all available attributes in GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/all_queues.yml).
+
+### Available operators
+
+`queue_selector` supports the following operators, listed from highest
+to lowest precedence:
+
+- `|` - the logical `OR` operator. For example, `query_a|query_b` (where `query_a`
+ and `query_b` are queries made up of the other operators here) includes
+ queues that match either query.
+- `&` - the logical `AND` operator. For example, `query_a&query_b` (where
+ `query_a` and `query_b` are queries made up of the other operators here) will
+ only include queues that match both queries.
+- `!=` - the `NOT IN` operator. For example, `feature_category!=issue_tracking`
+ excludes all queues from the `issue_tracking` feature category.
+- `=` - the `IN` operator. For example, `resource_boundary=cpu` includes all
+ queues that are CPU bound.
+- `,` - the concatenate set operator. For example,
+ `feature_category=continuous_integration,pages` includes all queues from
+ either the `continuous_integration` category or the `pages` category. This
+ example is also possible using the OR operator, but allows greater brevity, as
+ well as being lower precedence.
+
+The operator precedence for this syntax is fixed: it's not possible to make `AND`
+have higher precedence than `OR`.
+
+[In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and
+later, as with the standard queue group syntax above, a single `*` as the
+entire queue group selects all queues.
+
+### Migration
+
+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/troubleshooting/img/sidekiq_flamegraph.png b/doc/administration/sidekiq/img/sidekiq_flamegraph.png
index 89d6e8da3ce..89d6e8da3ce 100644
--- a/doc/administration/troubleshooting/img/sidekiq_flamegraph.png
+++ b/doc/administration/sidekiq/img/sidekiq_flamegraph.png
Binary files differ
diff --git a/doc/administration/sidekiq/index.md b/doc/administration/sidekiq/index.md
new file mode 100644
index 00000000000..f4e67fcb6dd
--- /dev/null
+++ b/doc/administration/sidekiq/index.md
@@ -0,0 +1,403 @@
+---
+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
+---
+
+# Configure an external Sidekiq instance **(FREE SELF)**
+
+You can configure an external Sidekiq instance by using the Sidekiq that's bundled in the GitLab package. Sidekiq requires connection to the Redis,
+PostgreSQL, and Gitaly instances.
+
+## Configure TCP access for PostgreSQL, Gitaly, and Redis
+
+By default, GitLab uses UNIX sockets and is not set up to communicate via TCP. To change this:
+
+1. Edit the `/etc/gitlab/gitlab.rb` file on your GitLab instance, and add the following:
+
+ ```ruby
+
+ ## PostgreSQL
+
+ # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value
+ postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH'
+ postgresql['listen_address'] = '0.0.0.0'
+ postgresql['port'] = 5432
+
+ # Add the Sidekiq nodes to PostgreSQL's trusted addresses.
+ # In the following example, 10.10.1.30/32 is the private IP
+ # of the Sidekiq server.
+ postgresql['md5_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32)
+ postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32)
+
+ ## Gitaly
+
+ # Make Gitaly accept connections on all network interfaces
+ gitaly['listen_addr'] = "0.0.0.0:8075"
+ ## Set up the Gitaly token as a form of authentication since you are accessing Gitaly over the network
+ ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token
+ gitaly['auth_token'] = 'abc123secret'
+ praefect['auth_token'] = 'abc123secret'
+ gitlab_rails['gitaly_token'] = 'abc123secret'
+
+ ## Redis configuration
+
+ redis['bind'] = '0.0.0.0'
+ redis['port'] = 6379
+ # Password to Authenticate Redis
+ redis['password'] = 'redis-password-goes-here'
+ gitlab_rails['redis_password'] = 'redis-password-goes-here'
+
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. Run `reconfigure`:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. Restart the `PostgreSQL` server:
+
+ ```shell
+ sudo gitlab-ctl restart postgresql
+ ```
+
+1. After the restart, set `auto_migrate` to `true` or comment to use the default settings:
+
+ ```ruby
+ gitlab_rails['auto_migrate'] = true
+ ```
+
+1. Run `reconfigure` again:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Set up Sidekiq instance
+
+1. SSH into the Sidekiq server.
+
+1. Confirm that you can access the PostgreSQL, Gitaly, and Redis ports:
+
+ ```shell
+ telnet <GitLab host> 5432 # PostgreSQL
+ telnet <GitLab host> 8075 # Gitaly
+ telnet <GitLab host> 6379 # Redis
+ ```
+
+1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab package
+ using steps 1 and 2. **Do not complete any other steps.**
+
+1. Copy the `/etc/gitlab/gitlab.rb` file from the GitLab instance and add the following settings. Make sure
+ to replace them with your values:
+
+<!--
+Updates to example must be made at:
+- https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/sidekiq.md
+- all reference architecture pages
+-->
+
+ ```ruby
+ ########################################
+ ##### Services Disabled ###
+ ########################################
+ #
+ # When running GitLab on just one server, you have a single `gitlab.rb`
+ # to enable all services you want to run.
+ # When running GitLab on N servers, you have N `gitlab.rb` files.
+ # Enable only the services you want to run on each
+ # specific server, while disabling all others.
+ #
+ gitaly['enable'] = false
+ postgresql['enable'] = false
+ redis['enable'] = false
+ nginx['enable'] = false
+ puma['enable'] = false
+ gitlab_workhorse['enable'] = false
+ prometheus['enable'] = false
+ alertmanager['enable'] = false
+ grafana['enable'] = false
+ gitlab_exporter['enable'] = false
+ gitlab_kas['enable'] = false
+
+ ##
+ ## To maintain uniformity of links across nodes, the
+ ## `external_url` on the Sidekiq server should point to the external URL that users
+ ## use to access GitLab. This can be either:
+ ##
+ ## - The `external_url` set on your application server.
+ ## - The URL of a external load balancer, which routes traffic to the GitLab application server.
+ ##
+ external_url 'https://gitlab.example.com'
+
+ # Configure the gitlab-shell API callback URL. Without this, `git push` will
+ # fail. This can be your 'front door' GitLab URL or an internal load
+ # balancer.
+ gitlab_rails['internal_api_url'] = 'GITLAB_URL'
+ gitlab_shell['secret_token'] = 'SHELL_TOKEN'
+
+ ########################################
+ #### Redis ###
+ ########################################
+
+ ## Must be the same in every sentinel node.
+ redis['master_name'] = 'gitlab-redis' # Required if you have setup redis cluster
+ ## The same password for Redis authentication you set up for the master node.
+ redis['master_password'] = '<redis_master_password>'
+
+ ### If redis is running on the main Gitlab instance and you have opened the TCP port as above add the following
+ gitlab_rails['redis_host'] = '<gitlab_host>'
+ gitlab_rails['redis_port'] = 6379
+
+ #######################################
+ ### Gitaly ###
+ #######################################
+
+ ## Replace <gitaly_token> with the one you set up, see
+ ## https://docs.gitlab.com/ee/administration/gitaly/configure_gitaly.html#about-the-gitaly-token
+ git_data_dirs({
+ "default" => {
+ "gitaly_address" => "tcp://<gitlab_host>:8075",
+ "gitaly_token" => "<gitaly_token>"
+ }
+ })
+
+ #######################################
+ ### Postgres ###
+ #######################################
+
+ # Replace <database_host> and <database_password>
+ gitlab_rails['db_host'] = '<database_host>'
+ gitlab_rails['db_port'] = '5432'
+ gitlab_rails['db_password'] = '<database_password>'
+ ## Prevent database migrations from running on upgrade automatically
+ gitlab_rails['auto_migrate'] = false
+
+ #######################################
+ ### Sidekiq configuration ###
+ #######################################
+ sidekiq['enable'] = true
+ sidekiq['listen_address'] = "0.0.0.0"
+
+ ## Set number of Sidekiq queue processes to the same number as available CPUs
+ sidekiq['queue_groups'] = ['*'] * 4
+
+ ## Set number of Sidekiq threads per queue process to the recommend number of 10
+ sidekiq['max_concurrency'] = 10
+ ```
+
+1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the GitLab instance and replace the file in the Sidekiq instance.
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. Restart the Sidekiq instance after completing the process and finishing the database migrations.
+
+## Configure multiple Sidekiq nodes with shared storage
+
+If you run multiple Sidekiq nodes with a shared file storage, such as NFS, you must
+specify the UIDs and GIDs to ensure they match between servers. Specifying the UIDs
+and GIDs prevents permissions issues in the file system. This advice is similar to the
+[advice for Geo setups](../geo/replication/multiple_servers.md#step-4-configure-the-frontend-application-nodes-on-the-geo-secondary-site).
+
+To set up multiple Sidekiq nodes:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ user['uid'] = 9000
+ user['gid'] = 9000
+ web_server['uid'] = 9001
+ web_server['gid'] = 9001
+ registry['uid'] = 9002
+ registry['gid'] = 9002
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Configure the Container Registry when using an external Sidekiq
+
+If you're using the Container Registry and it's running on a different
+node than Sidekiq, follow the steps below.
+
+1. Edit `/etc/gitlab/gitlab.rb`, and configure the registry URL:
+
+ ```ruby
+ registry_external_url 'https://registry.example.com'
+ gitlab_rails['registry_api_url'] = "https://registry.example.com"
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+1. In the instance where Container Registry is hosted, copy the `registry.key`
+ file to the Sidekiq node.
+
+## Configure the Sidekiq metrics server
+
+If you want to collect Sidekiq metrics, enable the Sidekiq metrics server.
+To make metrics available from `localhost:8082/metrics`:
+
+To configure the metrics server:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ sidekiq['metrics_enabled'] = true
+ sidekiq['listen_address'] = "localhost"
+ sidekiq['listen_port'] = "8082"
+
+ # Optionally log all the metrics server logs to log/sidekiq_exporter.log
+ sidekiq['exporter_log_enabled'] = true
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+### Enable HTTPS
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/364771) in GitLab 15.2.
+
+To serve metrics via HTTPS instead of HTTP, enable TLS in the exporter settings:
+
+1. Edit `/etc/gitlab/gitlab.rb` to add (or find and uncomment) the following lines:
+
+ ```ruby
+ sidekiq['exporter_tls_enabled'] = true
+ sidekiq['exporter_tls_cert_path'] = "/path/to/certificate.pem"
+ sidekiq['exporter_tls_key_path'] = "/path/to/private-key.pem"
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
+
+When TLS is enabled, the same `port` and `address` are used as described above.
+The metrics server cannot serve both HTTP and HTTPS at the same time.
+
+## Configure health checks
+
+If you use health check probes to observe Sidekiq, enable the Sidekiq health check server.
+To make health checks available from `localhost:8092`:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ sidekiq['health_checks_enabled'] = true
+ sidekiq['health_checks_listen_address'] = "localhost"
+ sidekiq['health_checks_listen_port'] = "8092"
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+For more information about health checks, see the [Sidekiq health check page](sidekiq_health_check.md).
+
+## Configure LDAP and user or group synchronization
+
+If you use LDAP for user and group management, you must add the LDAP configuration to your Sidekiq node as well as the LDAP
+synchronization worker. If the LDAP configuration and LDAP synchronization worker are not applied to your Sidekiq node,
+users and groups are not automatically synchronized.
+
+For more information about configuring LDAP for GitLab, see:
+
+- [GitLab LDAP configuration documentation](../auth/ldap/index.md#configure-ldap)
+- [LDAP synchronization documentation](../auth/ldap/ldap_synchronization.md#adjust-ldap-user-sync-schedule)
+
+To enable LDAP with the synchronization worker for Sidekiq:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['ldap_enabled'] = true
+ gitlab_rails['prevent_ldap_sign_in'] = false
+ gitlab_rails['ldap_servers'] = {
+ 'main' => {
+ 'label' => 'LDAP',
+ 'host' => 'ldap.mydomain.com',
+ 'port' => 389,
+ 'uid' => 'sAMAccountName',
+ 'encryption' => 'simple_tls',
+ 'verify_certificates' => true,
+ 'bind_dn' => '_the_full_dn_of_the_user_you_will_bind_with',
+ 'password' => '_the_password_of_the_bind_user',
+ 'tls_options' => {
+ 'ca_file' => '',
+ 'ssl_version' => '',
+ 'ciphers' => '',
+ 'cert' => '',
+ 'key' => ''
+ },
+ 'timeout' => 10,
+ 'active_directory' => true,
+ 'allow_username_or_email_login' => false,
+ 'block_auto_created_users' => false,
+ 'base' => 'dc=example,dc=com',
+ 'user_filter' => '',
+ 'attributes' => {
+ 'username' => ['uid', 'userid', 'sAMAccountName'],
+ 'email' => ['mail', 'email', 'userPrincipalName'],
+ 'name' => 'cn',
+ 'first_name' => 'givenName',
+ 'last_name' => 'sn'
+ },
+ 'lowercase_usernames' => false,
+
+ # Enterprise Edition only
+ # https://docs.gitlab.com/ee/administration/auth/ldap/ldap_synchronization.html
+ 'group_base' => '',
+ 'admin_group' => '',
+ 'external_groups' => [],
+ 'sync_ssh_keys' => false
+ }
+ }
+ gitlab_rails['ldap_sync_worker_cron'] = "0 */12 * * *"
+ ```
+
+1. Reconfigure GitLab:
+
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
+
+## Disable Rugged
+
+Calls into Rugged, Ruby bindings for `libgit2`, [lock the Sidekiq processes's GVL](https://silverhammermba.github.io/emberb/c/#c-in-ruby-threads),
+blocking all jobs on that worker from proceeding. If Rugged calls performed by Sidekiq are slow, this can cause significant delays in
+background task processing.
+
+By default, Rugged is used when Git repository data is stored on local storage or on an NFS mount.
+[Using Rugged is recommended when using NFS](../nfs.md#improving-nfs-performance-with-gitlab), but if
+you are using local storage, disabling Rugged can improve Sidekiq performance:
+
+```shell
+sudo gitlab-rake gitlab:features:disable_rugged
+```
+
+## Related topics
+
+- [Extra Sidekiq processes](extra_sidekiq_processes.md)
+- [Extra Sidekiq routing](extra_sidekiq_routing.md)
+- [Sidekiq health checks](sidekiq_health_check.md)
+- [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/)
+
+## Troubleshooting
+
+See our [administrator guide to troubleshooting Sidekiq](sidekiq_troubleshooting.md).
diff --git a/doc/administration/sidekiq/sidekiq_health_check.md b/doc/administration/sidekiq/sidekiq_health_check.md
new file mode 100644
index 00000000000..3477320a2ac
--- /dev/null
+++ b/doc/administration/sidekiq/sidekiq_health_check.md
@@ -0,0 +1,58 @@
+---
+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
+---
+
+# Sidekiq Health Check **(FREE SELF)**
+
+GitLab provides liveness and readiness probes to indicate service health and
+reachability to the Sidekiq cluster. These endpoints
+[can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
+to hold traffic until the system is ready or restart the container as needed.
+
+The health check server can be set up when [configuring Sidekiq](index.md).
+
+## Readiness
+
+The readiness probe checks whether the Sidekiq workers are ready to process jobs.
+
+```plaintext
+GET /readiness
+```
+
+If the server is bound to `localhost:8092`, the process cluster can be probed for readiness as follows:
+
+```shell
+curl "http://localhost:8092/readiness"
+```
+
+On success, the endpoint returns a `200` HTTP status code, and a response like the following:
+
+```json
+{
+ "status": "ok"
+}
+```
+
+## Liveness
+
+Checks whether the Sidekiq cluster is running.
+
+```plaintext
+GET /liveness
+```
+
+If the server is bound to `localhost:8092`, the process cluster can be probed for liveness as follows:
+
+```shell
+curl "http://localhost:8092/liveness"
+```
+
+On success, the endpoint returns a `200` HTTP status code, and a response like the following:
+
+```json
+{
+ "status": "ok"
+}
+```
diff --git a/doc/administration/sidekiq/sidekiq_job_migration.md b/doc/administration/sidekiq/sidekiq_job_migration.md
new file mode 100644
index 00000000000..a3bc8b2959a
--- /dev/null
+++ b/doc/administration/sidekiq/sidekiq_job_migration.md
@@ -0,0 +1,40 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Sidekiq job migration **(FREE SELF)**
+
+WARNING:
+This operation should be very uncommon. We do not recommend it for the vast majority of GitLab instances.
+
+Sidekiq routing rules allow administrators to re-route certain background jobs from their regular queue to an alternative queue. By default, GitLab uses one queue per background job type. GitLab has over 400 background job types, and so correspondingly it has over 400 queues.
+
+Most administrators do not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to.
+
+If the Sidekiq routing rules are changed, administrators need to take care with the migration to avoid losing jobs entirely. The basic migration steps are:
+
+1. Listen to both the old and new queues.
+1. Update the routing rules.
+1. Wait until there are no publishers dispatching jobs to the old queues.
+1. Run the [Rake tasks for future jobs](#future-jobs).
+1. Wait for the old queues to be empty.
+1. Stop listening to the old queues.
+
+## Future jobs
+
+Step 4 involves rewriting some Sidekiq job data for jobs that are already stored in Redis, but due to run in future. There are two sets of jobs to run in future: scheduled jobs and jobs to be retried. We provide a separate Rake task to migrate each set:
+
+- `gitlab:sidekiq:migrate_jobs:retry` for jobs to be retried.
+- `gitlab:sidekiq:migrate_jobs:scheduled` for scheduled jobs.
+
+Most of the time, running both at the same time is the correct choice. There are two separate tasks to allow for more fine-grained control where needed. To run both at once:
+
+```shell
+# omnibus-gitlab
+sudo gitlab-rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule
+
+# source installations
+bundle exec rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule RAILS_ENV=production
+```
diff --git a/doc/administration/sidekiq/sidekiq_memory_killer.md b/doc/administration/sidekiq/sidekiq_memory_killer.md
new file mode 100644
index 00000000000..12381808523
--- /dev/null
+++ b/doc/administration/sidekiq/sidekiq_memory_killer.md
@@ -0,0 +1,82 @@
+---
+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
+---
+
+# Sidekiq MemoryKiller **(FREE SELF)**
+
+The GitLab Rails application code suffers from memory leaks. For web requests
+this problem is made manageable using
+[`puma-worker-killer`](https://github.com/schneems/puma_worker_killer) which
+restarts Puma worker processes if it exceeds a memory limit. The Sidekiq
+MemoryKiller applies the same approach to the Sidekiq processes used by GitLab
+to process background jobs.
+
+Unlike puma-worker-killer, which is enabled by default for all GitLab
+installations of GitLab 13.0 and later, the Sidekiq MemoryKiller is enabled by default
+_only_ for Omnibus packages. The reason for this is that the MemoryKiller
+relies on runit to restart Sidekiq after a memory-induced shutdown and GitLab
+installations from source do not all use runit or an equivalent.
+
+With the default settings, the MemoryKiller causes a Sidekiq restart no
+more often than once every 15 minutes, with the restart causing about one
+minute of delay for incoming background jobs.
+
+Some background jobs rely on long-running external processes. To ensure these
+are cleanly terminated when Sidekiq is restarted, each Sidekiq process should be
+run as a process group leader (for example, using `chpst -P`). If using Omnibus or the
+`bin/background_jobs` script with `runit` installed, this is handled for you.
+
+## Configuring the MemoryKiller
+
+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
+ `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.
+
+ 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
+ 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
+ often to check process RSS, default to 3 seconds.
+
+- `SIDEKIQ_MEMORY_KILLER_GRACE_TIME`: defaults to 900 seconds (15 minutes).
+ The usage of this variable is described as part of `SIDEKIQ_MEMORY_KILLER_MAX_RSS`.
+
+- `SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAIT`: defaults to 30 seconds. This defines the
+ maximum time allowed for all Sidekiq jobs to finish. No new jobs are accepted
+ during that time, and the process exits as soon as all jobs finish.
+
+ If jobs do not finish during that time, the MemoryKiller interrupts all currently
+ running jobs by sending `SIGTERM` to the Sidekiq process.
+
+ If the process hard shutdown/restart is not performed by Sidekiq,
+ the Sidekiq process is forcefully terminated after
+ `Sidekiq.options[:timeout] + 2` seconds. An external supervision mechanism
+ (for example, runit) must restart Sidekiq afterwards.
diff --git a/doc/administration/sidekiq/sidekiq_troubleshooting.md b/doc/administration/sidekiq/sidekiq_troubleshooting.md
new file mode 100644
index 00000000000..9bc8e473409
--- /dev/null
+++ b/doc/administration/sidekiq/sidekiq_troubleshooting.md
@@ -0,0 +1,381 @@
+---
+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
+---
+
+# Troubleshooting Sidekiq **(FREE SELF)**
+
+Sidekiq is the background job processor GitLab uses to asynchronously run
+tasks. When things go wrong it can be difficult to troubleshoot. These
+situations also tend to be high-pressure because a production system job queue
+may be filling up. Users will notice when this happens because new branches
+may not show up and merge requests may not be updated. The following are some
+troubleshooting steps to help you diagnose the bottleneck.
+
+GitLab administrators/users should consider working through these
+debug steps with GitLab Support so the backtraces can be analyzed by our team.
+It may reveal a bug or necessary improvement in GitLab.
+
+In any of the backtraces, be wary of suspecting cases where every
+thread appears to be waiting in the database, Redis, or waiting to acquire
+a mutex. This **may** mean there's contention in the database, for example,
+but look for one thread that is different than the rest. This other thread
+may be using all available CPU, or have a Ruby Global Interpreter Lock,
+preventing other threads from continuing.
+
+## Log arguments to Sidekiq jobs
+
+[In GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44853)
+some arguments passed to Sidekiq jobs are logged by default.
+To avoid logging sensitive information (for instance, password reset tokens),
+GitLab logs numeric arguments for all workers, with overrides for some specific
+workers where their arguments are not sensitive.
+
+Example log output:
+
+```json
+{"severity":"INFO","time":"2020-06-08T14:37:37.892Z","class":"AdminEmailsWorker","args":["[FILTERED]","[FILTERED]","[FILTERED]"],"retry":3,"queue":"admin_emails","backtrace":true,"jid":"9e35e2674ac7b12d123e13cc","created_at":"2020-06-08T14:37:37.373Z","meta.user":"root","meta.caller_id":"Admin::EmailsController#create","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:6dc94409cfdd4d77:9fbe19bdee865293:1","enqueued_at":"2020-06-08T14:37:37.410Z","pid":65011,"message":"AdminEmailsWorker JID-9e35e2674ac7b12d123e13cc: done: 0.48085 sec","job_status":"done","scheduling_latency_s":0.001012,"redis_calls":9,"redis_duration_s":0.004608,"redis_read_bytes":696,"redis_write_bytes":6141,"duration_s":0.48085,"cpu_s":0.308849,"completed_at":"2020-06-08T14:37:37.892Z","db_duration_s":0.010742}
+{"severity":"INFO","time":"2020-06-08T14:37:37.894Z","class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","wrapped":"ActionMailer::MailDeliveryJob","queue":"mailers","args":["[FILTERED]"],"retry":3,"backtrace":true,"jid":"e47a4f6793d475378432e3c8","created_at":"2020-06-08T14:37:37.884Z","meta.user":"root","meta.caller_id":"AdminEmailsWorker","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:29344de0f966446d:5c3b0e0e1bef987b:1","enqueued_at":"2020-06-08T14:37:37.885Z","pid":65011,"message":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper JID-e47a4f6793d475378432e3c8: start","job_status":"start","scheduling_latency_s":0.009473}
+{"severity":"INFO","time":"2020-06-08T14:39:50.648Z","class":"NewIssueWorker","args":["455","1"],"retry":3,"queue":"new_issue","backtrace":true,"jid":"a24af71f96fd129ec47f5d1e","created_at":"2020-06-08T14:39:50.643Z","meta.user":"root","meta.project":"h5bp/html5-boilerplate","meta.root_namespace":"h5bp","meta.caller_id":"Projects::IssuesController#create","correlation_id":"f9UCZHqhuP7","uber-trace-id":"28f65730f99f55a3:a5d2b62dec38dffc:48ddd092707fa1b7:1","enqueued_at":"2020-06-08T14:39:50.646Z","pid":65011,"message":"NewIssueWorker JID-a24af71f96fd129ec47f5d1e: start","job_status":"start","scheduling_latency_s":0.001144}
+```
+
+When using [Sidekiq JSON logging](../logs/index.md#sidekiqlog),
+arguments logs are limited to a maximum size of 10 kilobytes of text;
+any arguments after this limit are discarded and replaced with a
+single argument containing the string `"..."`.
+
+You can set `SIDEKIQ_LOG_ARGUMENTS` [environment variable](https://docs.gitlab.com/omnibus/settings/environment-variables.html)
+to `0` (false) to disable argument logging.
+
+Example:
+
+```ruby
+gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "0"}
+```
+
+In GitLab 13.5 and earlier, set `SIDEKIQ_LOG_ARGUMENTS` to `1` to start logging arguments passed to Sidekiq.
+
+## Thread dump
+
+Send the Sidekiq process ID the `TTIN` signal to output thread
+backtraces in the log file.
+
+```shell
+kill -TTIN <sidekiq_pid>
+```
+
+Check in `/var/log/gitlab/sidekiq/current` or `$GITLAB_HOME/log/sidekiq.log` for
+the backtrace output. The backtraces are lengthy and generally start with
+several `WARN` level messages. Here's an example of a single thread's backtrace:
+
+```plaintext
+2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: ActiveRecord::RecordNotFound: Couldn't find Note with 'id'=3375386
+2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/activerecord-4.2.5.2/lib/active_record/core.rb:155:in `find'
+/opt/gitlab/embedded/service/gitlab-rails/app/workers/new_note_worker.rb:7:in `perform'
+/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:150:in `execute_job'
+/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:132:in `block (2 levels) in process'
+/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
+/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/memory_killer.rb:17:in `call'
+/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
+/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/arguments_logger.rb:6:in `call'
+...
+```
+
+In some cases Sidekiq may be hung and unable to respond to the `TTIN` signal.
+Move on to other troubleshooting methods if this happens.
+
+## Ruby profiling with `rbspy`
+
+[rbspy](https://rbspy.github.io) is an easy to use and low-overhead Ruby profiler that can be used to create
+flamegraph-style diagrams of CPU usage by Ruby processes.
+
+No changes to GitLab are required to use it and it has no dependencies. To install it:
+
+1. Download the binary from the [`rbspy` releases page](https://github.com/rbspy/rbspy/releases).
+1. Make the binary executable.
+
+To profile a Sidekiq worker for one minute, run:
+
+```shell
+sudo ./rbspy record --pid <sidekiq_pid> --duration 60 --file /tmp/sidekiq_profile.svg
+```
+
+![Example rbspy flamegraph](img/sidekiq_flamegraph.png)
+
+In this example of a flamegraph generated by `rbspy`, almost all of the Sidekiq process's time is spent in `rev_parse`, a native C
+function in Rugged. In the stack, we can see `rev_parse` is being called by the `ExpirePipelineCacheWorker`.
+
+## Process profiling with `perf`
+
+Linux has a process profiling tool called `perf` that is helpful when a certain
+process is eating up a lot of CPU. If you see high CPU usage and Sidekiq isn't
+responding to the `TTIN` signal, this is a good next step.
+
+If `perf` is not installed on your system, install it with `apt-get` or `yum`:
+
+```shell
+# Debian
+sudo apt-get install linux-tools
+
+# Ubuntu (may require these additional Kernel packages)
+sudo apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`
+
+# Red Hat/CentOS
+sudo yum install perf
+```
+
+Run `perf` against the Sidekiq PID:
+
+```shell
+sudo perf record -p <sidekiq_pid>
+```
+
+Let this run for 30-60 seconds and then press Ctrl-C. Then view the `perf` report:
+
+```shell
+$ sudo perf report
+
+# Sample output
+Samples: 348K of event 'cycles', Event count (approx.): 280908431073
+ 97.69% ruby nokogiri.so [.] xmlXPathNodeSetMergeAndClear
+ 0.18% ruby libruby.so.2.1.0 [.] objspace_malloc_increase
+ 0.12% ruby libc-2.12.so [.] _int_malloc
+ 0.10% ruby libc-2.12.so [.] _int_free
+```
+
+Above you see sample output from a `perf` report. It shows that 97% of the CPU is
+being spent inside Nokogiri and `xmlXPathNodeSetMergeAndClear`. For something
+this obvious you should then go investigate what job in GitLab would use
+Nokogiri and XPath. Combine with `TTIN` or `gdb` output to show the
+corresponding Ruby code where this is happening.
+
+## The GNU Project Debugger (`gdb`)
+
+`gdb` can be another effective tool for debugging Sidekiq. It gives you a little
+more interactive way to look at each thread and see what's causing problems.
+
+Attaching to a process with `gdb` suspends the normal operation
+of the process (Sidekiq does not process jobs while `gdb` is attached).
+
+Start by attaching to the Sidekiq PID:
+
+```shell
+gdb -p <sidekiq_pid>
+```
+
+Then gather information on all the threads:
+
+```plaintext
+info threads
+
+# Example output
+30 Thread 0x7fe5fbd63700 (LWP 26060) 0x0000003f7cadf113 in poll () from /lib64/libc.so.6
+29 Thread 0x7fe5f2b3b700 (LWP 26533) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+28 Thread 0x7fe5f2a3a700 (LWP 26534) 0x0000003f7ce0ba5e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+27 Thread 0x7fe5f2939700 (LWP 26535) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+26 Thread 0x7fe5f2838700 (LWP 26537) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+25 Thread 0x7fe5f2737700 (LWP 26538) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+24 Thread 0x7fe5f2535700 (LWP 26540) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+23 Thread 0x7fe5f2434700 (LWP 26541) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+22 Thread 0x7fe5f2232700 (LWP 26543) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
+21 Thread 0x7fe5f2131700 (LWP 26544) 0x00007fe5f7b570f0 in xmlXPathNodeSetMergeAndClear ()
+from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+...
+```
+
+If you see a suspicious thread, like the Nokogiri one above, you may want
+to get more information:
+
+```plaintext
+thread 21
+bt
+
+# Example output
+#0 0x00007ff0d6afe111 in xmlXPathNodeSetMergeAndClear () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#1 0x00007ff0d6b0b836 in xmlXPathNodeCollectAndTest () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#2 0x00007ff0d6b09037 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#3 0x00007ff0d6b09017 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#4 0x00007ff0d6b092e0 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#5 0x00007ff0d6b0bc37 in xmlXPathRunEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#6 0x00007ff0d6b0be5f in xmlXPathEvalExpression () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
+#7 0x00007ff0d6a97dc3 in evaluate (argc=2, argv=0x1022d058, self=<value optimized out>) at xml_xpath_context.c:221
+#8 0x00007ff0daeab0ea in vm_call_cfunc_with_frame (th=0x1022a4f0, reg_cfp=0x1032b810, ci=<value optimized out>) at vm_insnhelper.c:1510
+```
+
+To output a backtrace from all threads at once:
+
+```plaintext
+set pagination off
+thread apply all bt
+```
+
+Once you're done debugging with `gdb`, be sure to detach from the process and
+exit:
+
+```plaintext
+detach
+exit
+```
+
+## Sidekiq kill signals
+
+TTIN was described above as the signal to print backtraces for logging, however
+Sidekiq responds to other signals as well. For example, TSTP and TERM can be used
+to gracefully shut Sidekiq down, see
+[the Sidekiq Signals docs](https://github.com/mperham/sidekiq/wiki/Signals#ttin).
+
+## Check for blocking queries
+
+Sometimes the speed at which Sidekiq processes jobs can be so fast that it can
+cause database contention. Check for blocking queries when backtraces above
+show that many threads are stuck in the database adapter.
+
+The PostgreSQL wiki has details on the query you can run to see blocking
+queries. The query is different based on PostgreSQL version. See
+[Lock Monitoring](https://wiki.postgresql.org/wiki/Lock_Monitoring) for
+the query details.
+
+## Managing Sidekiq queues
+
+It is possible to use [Sidekiq API](https://github.com/mperham/sidekiq/wiki/API)
+to perform a number of troubleshooting steps on Sidekiq.
+
+These are the administrative commands and it should only be used if currently
+administration interface is not suitable due to scale of installation.
+
+All these commands should be run using `gitlab-rails console`.
+
+### View the queue size
+
+```ruby
+Sidekiq::Queue.new("pipeline_processing:build_queue").size
+```
+
+### Enumerate all enqueued jobs
+
+```ruby
+queue = Sidekiq::Queue.new("chaos:chaos_sleep")
+queue.each do |job|
+ # job.klass # => 'MyWorker'
+ # job.args # => [1, 2, 3]
+ # job.jid # => jid
+ # job.queue # => chaos:chaos_sleep
+ # job["retry"] # => 3
+ # job.item # => {
+ # "class"=>"Chaos::SleepWorker",
+ # "args"=>[1000],
+ # "retry"=>3,
+ # "queue"=>"chaos:chaos_sleep",
+ # "backtrace"=>true,
+ # "queue_namespace"=>"chaos",
+ # "jid"=>"39bc482b823cceaf07213523",
+ # "created_at"=>1566317076.266069,
+ # "correlation_id"=>"c323b832-a857-4858-b695-672de6f0e1af",
+ # "enqueued_at"=>1566317076.26761},
+ # }
+
+ # job.delete if job.jid == 'abcdef1234567890'
+end
+```
+
+### Enumerate currently running jobs
+
+```ruby
+workers = Sidekiq::Workers.new
+workers.each do |process_id, thread_id, work|
+ # process_id is a unique identifier per Sidekiq process
+ # thread_id is a unique identifier per thread
+ # work is a Hash which looks like:
+ # {"queue"=>"chaos:chaos_sleep",
+ # "payload"=>
+ # { "class"=>"Chaos::SleepWorker",
+ # "args"=>[1000],
+ # "retry"=>3,
+ # "queue"=>"chaos:chaos_sleep",
+ # "backtrace"=>true,
+ # "queue_namespace"=>"chaos",
+ # "jid"=>"b2a31e3eac7b1a99ff235869",
+ # "created_at"=>1566316974.9215662,
+ # "correlation_id"=>"e484fb26-7576-45f9-bf21-b99389e1c53c",
+ # "enqueued_at"=>1566316974.9229589},
+ # "run_at"=>1566316974}],
+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.
+
+```ruby
+queue = Sidekiq::Queue.new('<queue name>')
+queue.each { |job| job.delete if <condition>}
+```
+
+Have a look at the section below for cancelling running jobs.
+
+In the method above, `<queue-name>` is the name of the queue that contains the jobs you want to delete and `<condition>` decides which jobs get deleted.
+
+Commonly, `<condition>` references the job arguments, which depend on the type of job in question. To find the arguments for a specific queue, you can have a look at the `perform` function of the related worker file, commonly found at `/app/workers/<queue-name>_worker.rb`.
+
+For example, `repository_import` has `project_id` as the job argument, while `update_merge_requests` has `project_id, user_id, oldrev, newrev, ref`.
+
+Arguments need to be referenced by their sequence ID using `job.args[<id>]` because `job.args` is a list of all arguments provided to the Sidekiq job.
+
+Here are some examples:
+
+```ruby
+queue = Sidekiq::Queue.new('update_merge_requests')
+# In this example, we want to remove any update_merge_requests jobs
+# for the Project with ID 125 and ref `ref/heads/my_branch`
+queue.each { |job| job.delete if job.args[0] == 125 and job.args[4] == 'ref/heads/my_branch' }
+```
+
+```ruby
+# Cancelling jobs like: `RepositoryImportWorker.new.perform_async(100)`
+id_list = [100]
+
+queue = Sidekiq::Queue.new('repository_import')
+queue.each do |job|
+ job.delete if id_list.include?(job.args[0])
+end
+```
+
+### Remove specific job ID (destructive)
+
+```ruby
+queue = Sidekiq::Queue.new('repository_import')
+queue.each do |job|
+ job.delete if job.jid == 'my-job-id'
+end
+```
+
+## Canceling running jobs (destructive)
+
+> Introduced in GitLab 12.3.
+
+This is highly risky operation and use it as last resort.
+Doing that might result in data corruption, as the job
+is interrupted mid-execution and it is not guaranteed
+that proper rollback of transactions is implemented.
+
+```ruby
+Gitlab::SidekiqDaemon::Monitor.cancel_job('job-id')
+```
+
+> This requires the Sidekiq to be run with `SIDEKIQ_MONITOR_WORKER=1`
+> environment variable.
+
+To perform of the interrupt we use `Thread.raise` which
+has number of drawbacks, as mentioned in [Why Ruby's Timeout is dangerous (and Thread.raise is terrifying)](https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/):
+
+> This is where the implications get interesting, and terrifying. This means that an exception can get raised:
+>
+> - during a network request (ok, as long as the surrounding code is prepared to catch Timeout::Error)
+> - during the cleanup for the network request
+> - during a rescue block
+> - while creating an object to save to the database afterwards
+> - in any of your code, regardless of whether it could have possibly raised an exception before
+>
+> Nobody writes code to defend against an exception being raised on literally any line. That's not even possible. So Thread.raise is basically like a sneak attack on your code that could result in almost anything. It would probably be okay if it were pure-functional code that did not modify any state. But this is Ruby, so that's unlikely :)
diff --git a/doc/administration/sidekiq_health_check.md b/doc/administration/sidekiq_health_check.md
index aaab2b7e086..3294eb663f2 100644
--- a/doc/administration/sidekiq_health_check.md
+++ b/doc/administration/sidekiq_health_check.md
@@ -1,58 +1,11 @@
---
-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
+redirect_to: 'sidekiq/sidekiq_health_check.md'
+remove_date: '2022-11-11'
---
-# Sidekiq Health Check **(FREE SELF)**
+This document was moved to [another location](sidekiq/sidekiq_health_check.md).
-GitLab provides liveness and readiness probes to indicate service health and
-reachability to the Sidekiq cluster. These endpoints
-[can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
-to hold traffic until the system is ready or restart the container as needed.
-
-The health check server can be set up when [configuring Sidekiq](sidekiq.md).
-
-## Readiness
-
-The readiness probe checks whether the Sidekiq workers are ready to process jobs.
-
-```plaintext
-GET /readiness
-```
-
-If the server is bound to `localhost:8092`, the process cluster can be probed for readiness as follows:
-
-```shell
-curl "http://localhost:8092/readiness"
-```
-
-On success, the endpoint returns a `200` HTTP status code, and a response like the following:
-
-```json
-{
- "status": "ok"
-}
-```
-
-## Liveness
-
-Checks whether the Sidekiq cluster is running.
-
-```plaintext
-GET /liveness
-```
-
-If the server is bound to `localhost:8092`, the process cluster can be probed for liveness as follows:
-
-```shell
-curl "http://localhost:8092/liveness"
-```
-
-On success, the endpoint returns a `200` HTTP status code, and a response like the following:
-
-```json
-{
- "status": "ok"
-}
-```
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/administration/terraform_state.md b/doc/administration/terraform_state.md
index 14649b82ba8..7a8d7774948 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -78,9 +78,9 @@ Terraform state files are stored locally, follow the steps below.
## Using object storage **(FREE SELF)**
-Instead of storing Terraform state files on disk, we recommend the use of [one of the supported object
-storage options](object_storage.md#options). This configuration relies on valid credentials to
-be configured already.
+Instead of storing Terraform state files on disk, we recommend the use of
+[one of the supported object storage options](object_storage.md#options).
+This configuration relies on valid credentials to be configured already.
[Read more about using object storage with GitLab](object_storage.md).
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index 7ce09252680..7390f4bc816 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -1,404 +1,11 @@
---
-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
+redirect_to: '../../integration/advanced_search/elasticsearch_troubleshooting.md'
+remove_date: '2022-11-02'
---
-# Troubleshooting Elasticsearch **(PREMIUM SELF)**
+This document was moved to [another location](../../integration/advanced_search/elasticsearch_troubleshooting.md).
-To install and configure Elasticsearch,
-visit the [administrator documentation](../../integration/advanced_search/elasticsearch.md).
-
-For troubleshooting, visit the
-[administrator troubleshooting documentation](../../integration/advanced_search/elasticsearch_troubleshooting.md).
-
-Troubleshooting Elasticsearch requires:
-
-- Knowledge of common terms.
-- Establishing within which category the problem fits.
-
-## Common terminology
-
-- **Lucene**: A full-text search library written in Java.
-- **Near real time (NRT)**: Refers to the slight latency from the time to index a
- document to the time when it becomes searchable.
-- **Cluster**: A collection of one or more nodes that work together to hold all
- the data, providing indexing and search capabilities.
-- **Node**: A single server that works as part of a cluster.
-- **Index**: A collection of documents that have somewhat similar characteristics.
-- **Document**: A basic unit of information that can be indexed.
-- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
- a Lucene index.
-- **Replicas**: Failover mechanisms that duplicate indices.
-
-## Troubleshooting workflows
-
-The type of problem will determine what steps to take. The possible troubleshooting workflows are for:
-
-- Search results.
-- Indexing.
-- Integration.
-- Performance.
-- Advanced Search Migrations.
-
-### Search Results workflow
-
-The following workflow is for Elasticsearch search results issues:
-
-```mermaid
-graph TD;
- B --> |No| B1
- B --> |Yes| B4
- B1 --> B2
- B2 --> B3
- B4 --> B5
- B5 --> |Yes| B6
- B5 --> |No| B7
- B7 --> B8
- B{Is GitLab using<br>Elasticsearch for<br>searching?}
- B1[From the Admin Area, select<br>Integrations from the left<br>sidebar to ensure the settings<br>are correct.]
- B2[Perform a search via<br>the rails console]
- B3[If all settings are correct<br>and it still doesn't show Elasticsearch<br>doing the searches, escalate<br>to GitLab support.]
- B4[Perform<br>the same search via the<br>Elasticsearch API]
- B5{Are the results<br>the same?}
- B6[This means it is working as intended.<br>Speak with GitLab support<br>to confirm if the issue lies with<br>the filters.]
- B7[Check the index status of the project<br>containing the missing search<br>results.]
- B8(Indexing Troubleshooting)
-```
-
-### Indexing workflow
-
-The following workflow is for Elasticsearch indexing issues:
-
-```mermaid
-graph TD;
- C --> |Yes| C1
- C1 --> |Yes| C2
- C1 --> |No| C3
- C3 --> |Yes| C4
- C3 --> |No| C5
- C --> |No| C6
- C6 --> |No| C10
- C7 --> |GitLab| C8
- C7 --> |Elasticsearch| C9
- C6 --> |Yes| C7
- C10 --> |No| C12
- C10 --> |Yes| C11
- C12 --> |Yes| C13
- C12 --> |No| C14
- C14 --> |Yes| C15
- C14 --> |No| C16
- C{Is the problem with<br>creating an empty<br>index?}
- C1{Does the gitlab-production<br>index exist on the<br>Elasticsearch instance?}
- C2(Try to manually<br>delete the index on the<br>Elasticsearch instance and<br>retry creating an empty index.)
- C3{Can indices be made<br>manually on the Elasticsearch<br>instance?}
- C4(Retry the creation of an empty index)
- C5(It is best to speak with an<br>Elasticsearch admin concerning the<br>instance's inability to create indices.)
- C6{Is the indexer presenting<br>errors during indexing?}
- C7{Is the error a GitLab<br>error or an Elasticsearch<br>error?}
- C8[Escalate to<br>GitLab support]
- C9[You will want<br>to speak with an<br>Elasticsearch admin.]
- C10{Does the index status<br>show 100%?}
- C11[Escalate to<br>GitLab support]
- C12{Does re-indexing the project<br> present any GitLab errors?}
- C13[Rectify the GitLab errors and<br>restart troubleshooting, or<br>escalate to GitLab support.]
- C14{Does re-indexing the project<br>present errors on the <br>Elasticsearch instance?}
- C15[It would be best<br>to speak with an<br>Elasticsearch admin.]
- C16[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
-```
-
-### Integration workflow
-
-The following workflow is for Elasticsearch integration issues:
-
-```mermaid
-graph TD;
- D --> |No| D1
- D --> |Yes| D2
- D2 --> |No| D3
- D2 --> |Yes| D4
- D4 --> |No| D5
- D4 --> |Yes| D6
- D{Is the error concerning<br>the Go indexer?}
- D1[It would be best<br>to speak with an<br>Elasticsearch admin.]
- D2{Is the ICU development<br>package installed?}
- D3>This package is required.<br>Install the package<br>and retry.]
- D4{Is the error stemming<br>from the indexer?}
- D5[This would indicate an OS level<br> issue. It would be best to<br>contact your sysadmin.]
- D6[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
-```
-
-### Performance workflow
-
-The following workflow is for Elasticsearch performance issues:
-
-```mermaid
-graph TD;
- F --> |Yes| F1
- F --> |No| F2
- F2 --> |No| F3
- F2 --> |Yes| F4
- F4 --> F5
- F5 --> |No| F6
- F5 --> |Yes| F7
- F{Is the Elasticsearch instance<br>running on the same server<br>as the GitLab instance?}
- F1(This is not advised and will cause issues.<br>We recommend moving the Elasticsearch<br>instance to a different server.)
- F2{Does the Elasticsearch<br>server have at least 8<br>GB of RAM and 2 CPU<br>cores?}
- F3(According to Elasticsearch, a non-prod<br>server needs these as a base requirement.<br>Production often requires more. We recommend<br>you increase the server specifications.)
- F4(Obtain the <br>cluster health information)
- F5(Does it show the<br>status as green?)
- F6(We recommend you speak with<br>an Elasticsearch admin<br>about implementing sharding.)
- F7(Escalate to<br>GitLab support.)
-```
-
-### Advanced Search Migrations workflow
-
-```mermaid
-graph TD;
- D --> |No| D1
- D --> |Yes| D2
- D2 --> |No| D3
- D2 --> |Yes| D4
- D4 --> |No| D5
- D4 --> |Yes| D6
- D6 --> |No| D8
- D6 --> |Yes| D7
-
- D{Is there a halted migration?}
- D1[Migrations run in the<br>background and will<br>stop when completed.]
- D2{Does the elasticsearch.log<br>file contain errors?}
- D3[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
- D4{Have the errors<br>been addressed?}
- D5[Have an Elasticsearch admin<br>review and address<br>the errors.]
- D6{Has the migration<br>been retried?}
- D7[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.]
- D8[Retry the migration from<br>the Admin > Settings ><br>Advanced Search UI.]
-```
-
-## Troubleshooting walkthrough
-
-Most Elasticsearch troubleshooting can be broken down into 4 categories:
-
-- [Troubleshooting search results](#troubleshooting-search-results)
-- [Troubleshooting indexing](#troubleshooting-indexing)
-- [Troubleshooting integration](#troubleshooting-integration)
-- [Troubleshooting performance](#troubleshooting-performance)
-- [Troubleshooting Advanced Search migrations](#troubleshooting-advanced-search-migrations)
-
-Generally speaking, if it does not fall into those four categories, it is either:
-
-- Something GitLab support needs to look into.
-- Not a true Elasticsearch issue.
-
-Exercise caution. Issues that appear to be Elasticsearch problems can be OS-level issues.
-
-### Troubleshooting search results
-
-Troubleshooting search result issues is rather straight forward on Elasticsearch.
-
-The first step is to confirm GitLab is using Elasticsearch for the search function.
-To do this:
-
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Settings > General**, and then confirm the
- integration is enabled.
-1. Confirm searches use Elasticsearch by accessing the rails console
- (`sudo gitlab-rails console`) and running the following commands:
-
- ```rails
- u = User.find_by_email('email_of_user_doing_search')
- s = SearchService.new(u, {:search => 'search_term'})
- pp s.search_objects.class
- ```
-
-The output from the last command is the key here. If it shows:
-
-- `ActiveRecord::Relation`, **it is not** using Elasticsearch.
-- `Kaminari::PaginatableArray`, **it is** using Elasticsearch.
-
-| Not using Elasticsearch | Using Elasticsearch |
-|--------------------------|------------------------------|
-| `ActiveRecord::Relation` | `Kaminari::PaginatableArray` |
-
-If all the settings look correct and it is still not using Elasticsearch for the search function, it is best to escalate to GitLab support. This could be a bug/issue.
-
-Moving past that, it is best to attempt the same [search via the Rails console](../../integration/advanced_search/elasticsearch_troubleshooting.md#i-indexed-all-the-repositories-but-i-cant-get-any-hits-for-my-search-term-in-the-ui)
-or the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html),
-and compare the results from what you see in GitLab.
-
-If the results:
-
-- Sync up, then there is not a technical "issue." Instead, it might be a problem
- with the Elasticsearch filters we are using. This can be complicated, so it is best to
- escalate to GitLab support to check these and guide you on the potential on whether or
- not a feature request is needed.
-- Do not match up, this indicates a problem with the documents generated from the
- project. It is best to re-index that project and proceed with
- [Troubleshooting indexing](#troubleshooting-indexing).
-
-### Troubleshooting indexing
-
-Troubleshooting indexing issues can be tricky. It can pretty quickly go to either GitLab
-support or your Elasticsearch administrator.
-
-The best place to start is to determine if the issue is with creating an empty index.
-If it is, check on the Elasticsearch side to determine if the `gitlab-production` (the
-name for the GitLab index) exists. If it exists, manually delete it on the Elasticsearch
-side and attempt to recreate it from the
-[`recreate_index`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks)
-Rake task.
-
-If you still encounter issues, try creating an index manually on the Elasticsearch
-instance. The details of the index aren't important here, as we want to test if indices
-can be made. If the indices:
-
-- Cannot be made, speak with your Elasticsearch administrator.
-- Can be made, Escalate this to GitLab support.
-
-If the issue is not with creating an empty index, the next step is to check for errors
-during the indexing of projects. If errors do occur, they stem from either the indexing:
-
-- On the GitLab side. You need to rectify those. If they are not
- something you are familiar with, contact GitLab support for guidance.
-- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not, speak with your Elasticsearch administrator.
-
-If the indexing process does not present errors, check the status of the indexed projects. You can do this via the following Rake tasks:
-
-- [`sudo gitlab-rake gitlab:elastic:index_projects_status`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows the overall status)
-- [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows specific projects that are not indexed)
-
-If:
-
-- Everything is showing at 100%, escalate to GitLab support. This could be a potential
- bug/issue.
-- You do see something not at 100%, attempt to reindex that project. To do this,
- run `sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=<project ID> ID_TO=<project ID>`.
-
-If reindexing the project shows:
-
-- Errors on the GitLab side, escalate those to GitLab support.
-- Elasticsearch errors or doesn't present any errors at all, reach out to your
- Elasticsearch administrator to check the instance.
-
-### Troubleshooting integration
-
-Troubleshooting integration tends to be pretty straight forward, as there really isn't
-much to "integrate" here.
-
-If the issue is:
-
-- With the Go indexer, check if the ICU development package is installed.
- This is a required package so make sure you install it.
- Go indexer was a beta indexer which can be optionally turned on/off, but in 12.3 it reached stable status and is now the default.
-- Not concerning the Go indexer, it is almost always an
- Elasticsearch-side issue. This means you should reach out to your Elasticsearch administrator
- regarding the errors you are seeing. If you are unsure here, it never hurts to reach
- out to GitLab support.
-
-Beyond that, review the error. If it is:
-
-- Specifically from the indexer, this could be a bug/issue and should be escalated to
- GitLab support.
-- An OS issue, you should reach out to your systems administrator.
-- A `Faraday::TimeoutError (execution expired)` error **and** you're using a proxy,
- [set a custom `gitlab_rails['env']` environment variable, called `no_proxy`](https://docs.gitlab.com/omnibus/settings/environment-variables.html)
- with the IP address of your Elasticsearch host.
-
-### Troubleshooting performance
-
-Troubleshooting performance can be difficult on Elasticsearch. There is a ton of tuning
-that *can* be done, but the majority of this falls on shoulders of a skilled
-Elasticsearch administrator.
-
-Generally speaking, ensure:
-
-- The Elasticsearch server **is not** running on the same node as GitLab.
-- The Elasticsearch server have enough RAM and CPU cores.
-- That sharding **is** being used.
-
-Going into some more detail here, if Elasticsearch is running on the same server as GitLab, resource contention is **very** likely to occur. Ideally, Elasticsearch, which requires ample resources, should be running on its own server (maybe coupled with Logstash and Kibana).
-
-When it comes to Elasticsearch, RAM is the key resource. Elasticsearch themselves recommend:
-
-- **At least** 8 GB of RAM for a non-production instance.
-- **At least** 16 GB of RAM for a production instance.
-- Ideally, 64 GB of RAM.
-
-For CPU, Elasticsearch recommends at least 2 CPU cores, but Elasticsearch states common
-setups use up to 8 cores. For more details on server specs, check out
-[Elasticsearch's hardware guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html).
-
-Beyond the obvious, sharding comes into play. Sharding is a core part of Elasticsearch.
-It allows for horizontal scaling of indices, which is helpful when you are dealing with
-a large amount of data.
-
-With the way GitLab does indexing, there is a **huge** amount of documents being
-indexed. By utilizing sharding, you can speed up Elasticsearch's ability to locate
-data, since each shard is a Lucene index.
-
-If you are not using sharding, you are likely to hit issues when you start using
-Elasticsearch in a production environment.
-
-Keep in mind that an index with only one shard has **no scale factor** and will
-likely encounter issues when called upon with some frequency.
-
-If you need to know how many shards, read
-[Elasticsearch's documentation on capacity planning](https://www.elastic.co/guide/en/elasticsearch/guide/2.x/capacity-planning.html),
-as the answer is not straight forward.
-
-The easiest way to determine if sharding is in use is to check the output of the
-[Elasticsearch Health API](https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html):
-
-- Red means the cluster is down.
-- Yellow means it is up with no sharding/replication.
-- Green means it is healthy (up, sharding, replicating).
-
-For production use, it should always be green.
-
-Beyond these steps, you get into some of the more complicated things to check,
-such as merges and caching. These can get complicated and it takes some time to
-learn them, so it is best to escalate/pair with an Elasticsearch expert if you need to
-dig further into these.
-
-Feel free to reach out to GitLab support, but this is likely to be something a skilled
-Elasticsearch administrator has more experience with.
-
-### Troubleshooting Advanced Search migrations
-
-Troubleshooting Advanced Search migration failures can be difficult and may
-require contacting an Elasticsearch administrator or GitLab Support.
-
-The best place to start while debugging issues with an Advanced Search
-migration is the [`elasticsearch.log` file](../logs.md#elasticsearchlog).
-Migrations log information while a migration is in progress and any
-errors encountered. Apply fixes for any errors found in the log and retry
-the migration.
-
-If you still encounter issues after retrying the migration, reach out to GitLab support.
-
-## Common issues
-
-All common issues [should be documented](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not,
-feel free to update that page with issues you encounter and solutions.
-
-## Replication
-
-Setting up Elasticsearch isn't too bad, but it can be a bit finicky and time consuming.
-
-The easiest method is to spin up a Docker container with the required version and
-bind ports 9200/9300 so it can be used.
-
-The following is an example of running a Docker container of Elasticsearch v7.2.0:
-
-```shell
-docker pull docker.elastic.co/elasticsearch/elasticsearch:7.2.0
-docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.2.0
-```
-
-From here, you can:
-
-- Grab the IP of the Docker container (use `docker inspect <container_id>`)
-- Use `<IP.add.re.ss:9200>` to communicate with it.
-
-This is a quick method to test out Elasticsearch, but by no means is this a
-production solution.
+<!-- This redirect file can be deleted after <2022-11-02>. -->
+<!-- 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/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 0ff1afa86ed..aa4dbec4f95 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -178,26 +178,6 @@ Feature.all
Feature.all.map {|f| [f.name, f.state]}
```
-## Command Line
-
-### Check the GitLab version fast
-
-```shell
-grep -m 1 gitlab /opt/gitlab/version-manifest.txt
-```
-
-### Debugging SSH
-
-```shell
-GIT_SSH_COMMAND="ssh -vvv" git clone <repository>
-```
-
-### Debugging over HTTPS
-
-```shell
-GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone <repository>
-```
-
## Projects
### Clear a project's cache
@@ -326,7 +306,7 @@ Project.find_each do |p|
end
```
-## Bulk update to change all the Jira integrations to Jira instance-level values
+### 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:
@@ -341,6 +321,25 @@ To change all Jira project to use the instance-level integration settings:
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:
@@ -424,33 +423,6 @@ 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>>]
```
-## Wikis
-
-### Recreate
-
-WARNING:
-This is a destructive operation, the Wiki becomes empty.
-
-A Projects Wiki can be recreated by this command:
-
-```ruby
-p = Project.find_by_full_path('<username-or-group>/<project-name>') ### enter your projects path
-
-GitlabShellWorker.perform_in(0, :remove_repository, p.repository_storage, p.wiki.disk_path) ### deletes the wiki project from the filesystem
-
-p.create_wiki ### creates the wiki project on the filesystem
-```
-
-## Issue boards
-
-### In case of issue boards not loading properly and it's getting time out. Call the Issue Rebalancing service to fix this
-
-```ruby
-p = Project.find_by_full_path('<username-or-group>/<project-name>')
-
-Issues::RelativePositionRebalancingService.new(p.root_namespace.all_projects).execute
-```
-
## Imports and exports
### Import a project
@@ -855,52 +827,6 @@ Gitlab::CurrentSettings.update!(password_authentication_enabled_for_web: true)
## SCIM
-### Fixing bad SCIM identities
-
-```ruby
-def delete_bad_scim(email, group_path)
- output = ""
- u = User.find_by_email(email)
- uid = u.id
- g = Group.find_by_full_path(group_path)
- saml_prov_id = SamlProvider.find_by(group_id: g.id).id
- saml = Identity.where(user_id: uid, saml_provider_id: saml_prov_id)
- scim = ScimIdentity.where(user_id: uid , group_id: g.id)
- if saml[0]
- saml_eid = saml[0].extern_uid
- output += "%s," % [email]
- output += "SAML: %s," % [saml_eid]
- if scim[0]
- scim_eid = scim[0].extern_uid
- output += "SCIM: %s" % [scim_eid]
- if saml_eid == scim_eid
- output += " Identities matched, not deleted \n"
- else
- scim[0].destroy
- output += " Deleted \n"
- end
- else
- output = "ERROR No SCIM identify found for: [%s]\n" % [email]
- puts output
- return 1
- end
- else
- output = "ERROR No SAML identify found for: [%s]\n" % [email]
- puts output
- return 1
- end
- puts output
- return 0
-end
-
-# In case of multiple emails
-emails = [email1, email2]
-
-emails.each do |e|
- delete_bad_scim(e,'<group-path>')
-end
-```
-
### Find groups using an SQL query
Find and store an array of groups based on an SQL query:
@@ -927,13 +853,13 @@ conflicting_permanent_redirects.destroy_all
## Merge requests
-### Close a merge request properly (if merged but still marked as open)
+### Close a merge request
```ruby
u = User.find_by_username('<username>')
p = Project.find_by_full_path('<namespace/project>')
m = p.merge_requests.find_by(iid: <iid>)
-MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m)
+MergeRequests::CloseService.new(project: p, current_user: u).execute(m)
```
### Delete a merge request
@@ -954,6 +880,21 @@ m = p.merge_requests.find_by(iid: <iid>)
MergeRequests::RebaseService.new(project: m.target_project, current_user: u).execute(m)
```
+### Set a merge request as merged
+
+Use when a merge request was accepted and the changes merged into the Git repository,
+but the merge request still shows as open.
+
+If the changes are not merged yet, this action causes the merge request to
+incorrectly show `merged into <branch-name>`.
+
+```ruby
+u = User.find_by_username('<username>')
+p = Project.find_by_full_path('<namespace/project>')
+m = p.merge_requests.find_by(iid: <iid>)
+MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m)
+```
+
## CI
### Cancel stuck pending pipelines
@@ -1063,6 +1004,9 @@ License.current.trial?
# License ID for lookup on CustomersDot
License.current.license_id
+
+# License data in Base64-encoded ASCII format
+License.current.data
```
### Check if a project feature is available on the instance
@@ -1378,16 +1322,6 @@ registry = Geo::SnippetRepositoryRegistry.find(registry_id)
registry.replicator.send(:sync_repository)
```
-## Gitaly
-
-### Find available and used space
-
-A Gitaly storage resource can be polled through Rails to determine the available and used space.
-
-```ruby
-Gitlab::GitalyClient::ServerService.new("default").storage_disk_statistics
-```
-
## Generate Service Ping
The [Service Ping Guide](../../development/service_ping/index.md) in our developer documentation
@@ -1429,28 +1363,6 @@ Prints the metrics saved in `conversational_development_index_metrics`.
rake gitlab:usage_data:generate_and_send
```
-## Kubernetes integration
-
-Find cluster:
-
-```ruby
-cluster = Clusters::Cluster.find(1)
-cluster = Clusters::Cluster.find_by(name: 'cluster_name')
-```
-
-Delete cluster without associated resources:
-
-```ruby
-# Find users with the administrator access
-user = User.find_by(username: 'admin_user')
-
-# Find the cluster with the ID
-cluster = Clusters::Cluster.find(1)
-
-# Delete the cluster
-Clusters::DestroyService.new(user).execute(cluster)
-```
-
## Elasticsearch
### Configuration attributes
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 145eb5f65ae..b5187504231 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -1,207 +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
-type: reference
+redirect_to: '../../user/group/saml_sso/example_saml_config.md'
+remove_date: '2022-10-29'
---
-# Troubleshooting Group SAML and SCIM **(PREMIUM SAAS)**
+This document was moved to [another location](../../user/group/saml_sso/example_saml_config.md).
-These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team's collected knowledge.
-
-Please refer to the GitLab [Group SAML](../../user/group/saml_sso/index.md) docs for information on the feature and how to set it up.
-
-When troubleshooting a SAML configuration, GitLab team members will frequently start with the [SAML troubleshooting section](../../user/group/saml_sso/index.md#troubleshooting).
-
-They may then set up a test configuration of the desired identity provider. We include example screenshots in this section.
-
-## SAML and SCIM screenshots
-
-This section includes relevant screenshots of the following example configurations of [Group SAML](../../user/group/saml_sso/index.md) and [Group SCIM](../../user/group/saml_sso/scim_setup.md):
-
-- [Azure Active Directory](#azure-active-directory)
-- [Google Workspace](#google-workspace)
-- [Okta](#okta)
-- [OneLogin](#onelogin)
-
-WARNING:
-These screenshots are updated only as needed by GitLab Support. They are **not** official documentation.
-
-If you are currently having an issue with GitLab, you may want to check your [support options](https://about.gitlab.com/support/).
-
-## Azure Active Directory
-
-Basic SAML app configuration:
-
-![Azure AD basic SAML](img/AzureAD-basic_SAML.png)
-
-User claims and attributes:
-
-![Azure AD user claims](img/AzureAD-claims.png)
-
-SCIM mapping:
-
-![Azure AD SCIM Provisioning](img/AzureAD-scim_provisioning.png)
-![Azure AD SCIM Attribute Mapping](img/AzureAD-scim_attribute_mapping.png)
-
-Group Sync:
-
-![Azure Group Claims](img/azure_configure_group_claim.png)
-
-## Google Workspace
-
-Basic SAML app configuration:
-
-![Google Workspace basic SAML](img/GoogleWorkspace-basic-SAML_v14_10.png)
-
-User claims and attributes:
-
-![Google Workspace user claims](img/GoogleWorkspace-claims_v14_10.png)
-
-IdP links and certificate:
-
-NOTE:
-Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for configuring SAML, download the certificate and calculate the SHA1 certificate
-fingerprint.
-
-![Google Workspace Links and Certificate](img/GoogleWorkspace-linkscert_v14_10.png)
-
-## Okta
-
-Basic SAML app configuration:
-
-![Okta basic SAML](img/Okta-SAMLsetup.png)
-
-User claims and attributes:
-
-![Okta Attributes](img/Okta-attributes.png)
-
-Advanced SAML app settings (defaults):
-
-![Okta Advanced Settings](img/Okta-advancedsettings.png)
-
-IdP Links and Certificate:
-
-![Okta Links and Certificate](img/Okta-linkscert.png)
-
-Sign on settings:
-
-![Okta SAML settings](img/okta_saml_settings.png)
-
-Self-managed instance example:
-
-![Okta admin panel view](img/okta_admin_panel_v13_9.png)
-
-Setting the username for the newly provisioned users when assigning them the SCIM app:
-
-![Assigning SCIM app to users on Okta](img/okta_setting_username.png)
-
-## OneLogin
-
-Application details:
-
-![OneLogin application details](img/OneLogin-app_details.png)
-
-Parameters:
-
-![OneLogin application details](img/OneLogin-parameters.png)
-
-Adding a user:
-
-![OneLogin user add](img/OneLogin-userAdd.png)
-
-SSO settings:
-
-![OneLogin SSO settings](img/OneLogin-SSOsettings.png)
-
-## SAML response example
-
-When a user signs in using SAML, GitLab receives a SAML response. The SAML response can be found in `production.log` logs as a base64-encoded message. Locate the response by
-searching for `SAMLResponse`. The decoded SAML response is in XML format. For example:
-
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="https://gitlabexample/-/saml/callback" ID="id4898983630840142426821432" InResponseTo="_c65e4c88-9425-4472-b42c-37f4186ac0ee" IssueInstant="2022-05-30T21:30:35.696Z" Version="2.0">
- <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk2y6j57o1Pdr2lI8qh7</saml2:Issuer>
- <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
- <ds:SignedInfo>
- <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
- <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
- <ds:Reference URI="#id4898983630840142426821432">
- <ds:Transforms>
- <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
- <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
- <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
- </ds:Transform>
- </ds:Transforms>
- <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
- <ds:DigestValue>neiQvv9d3OgS4GZW8Nptp4JhjpKs3GCefibn+vmRgk4=</ds:DigestValue>
- </ds:Reference>
- </ds:SignedInfo>
- <ds:SignatureValue>dMsQX8ivi...HMuKGhyLRvabGU6CuPrf7==</ds:SignatureValue>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>MIIDq...cptGr3vN9TQ==</ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </ds:Signature>
- <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
- <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
- </saml2p:Status>
- <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="id489" IssueInstant="2022-05-30T21:30:35.696Z" Version="2.0">
- <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk2y6j57o1Pdr2lI8qh7</saml2:Issuer>
- <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
- <ds:SignedInfo>
- <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
- <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
- <ds:Reference URI="#id48989836309833801859473359">
- <ds:Transforms>
- <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
- <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
- <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
- </ds:Transform>
- </ds:Transforms>
- <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
- <ds:DigestValue>MaIsoi8hbT9gsi/mNZsz449mUuAcuEWY0q3bc4asOQs=</ds:DigestValue>
- </ds:Reference>
- </ds:SignedInfo>
- <ds:SignatureValue>dMsQX8ivi...HMuKGhyLRvabGU6CuPrf7==<</ds:SignatureValue>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>MIIDq...cptGr3vN9TQ==</ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </ds:Signature>
- <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
- <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">useremail@domain.com</saml2:NameID>
- <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
- <saml2:SubjectConfirmationData InResponseTo="_c65e4c88-9425-4472-b42c-37f4186ac0ee" NotOnOrAfter="2022-05-30T21:35:35.696Z" Recipient="https://gitlab.example.com/-/saml/callback"/>
- </saml2:SubjectConfirmation>
- </saml2:Subject>
- <saml2:Conditions xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" NotBefore="2022-05-30T21:25:35.696Z" NotOnOrAfter="2022-05-30T21:35:35.696Z">
- <saml2:AudienceRestriction>
- <saml2:Audience>https://gitlab.example.com/</saml2:Audience>
- </saml2:AudienceRestriction>
- </saml2:Conditions>
- <saml2:AuthnStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" AuthnInstant="2022-05-30T21:30:35.696Z" SessionIndex="_c65e4c88-9425-4472-b42c-37f4186ac0ee">
- <saml2:AuthnContext>
- <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
- </saml2:AuthnContext>
- </saml2:AuthnStatement>
- <saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
- <saml2:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
- <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">useremail@domain.com</saml2:AttributeValue>
- </saml2:Attribute>
- <saml2:Attribute Name="firtname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
- <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John</saml2:AttributeValue>
- </saml2:Attribute>
- <saml2:Attribute Name="lastname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
- <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe</saml2:AttributeValue>
- </saml2:Attribute>
- <saml2:Attribute Name="Groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
- <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Super-awesome-group</saml2:AttributeValue>
- </saml2:Attribute>
- </saml2:AttributeStatement>
- </saml2:Assertion>
-</saml2p:Response>
-```
+<!-- This redirect file can be deleted after <2022-10-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/administration/troubleshooting/img/Okta-SAMLsetup.png b/doc/administration/troubleshooting/img/Okta-SAMLsetup.png
deleted file mode 100644
index 1bd9bf4d7e9..00000000000
--- a/doc/administration/troubleshooting/img/Okta-SAMLsetup.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/Okta-advancedsettings.png b/doc/administration/troubleshooting/img/Okta-advancedsettings.png
deleted file mode 100644
index 45e378d1d12..00000000000
--- a/doc/administration/troubleshooting/img/Okta-advancedsettings.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/Okta-attributes.png b/doc/administration/troubleshooting/img/Okta-attributes.png
deleted file mode 100644
index a3405e4de9b..00000000000
--- a/doc/administration/troubleshooting/img/Okta-attributes.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/Okta-linkscert.png b/doc/administration/troubleshooting/img/Okta-linkscert.png
deleted file mode 100644
index 38cae415f7e..00000000000
--- a/doc/administration/troubleshooting/img/Okta-linkscert.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png b/doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png
deleted file mode 100644
index 2ebb1f0112c..00000000000
--- a/doc/administration/troubleshooting/img/okta_admin_panel_v13_9.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/img/okta_saml_settings.png b/doc/administration/troubleshooting/img/okta_saml_settings.png
deleted file mode 100644
index ee275ece369..00000000000
--- a/doc/administration/troubleshooting/img/okta_saml_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/troubleshooting/index.md b/doc/administration/troubleshooting/index.md
index 7fe731bda66..429dc79e95f 100644
--- a/doc/administration/troubleshooting/index.md
+++ b/doc/administration/troubleshooting/index.md
@@ -13,15 +13,12 @@ installation.
- [SSL](ssl.md)
- [Geo](../geo/replication/troubleshooting.md)
-- [Elasticsearch](elasticsearch.md)
-- [Sidekiq](sidekiq.md)
- [GitLab Rails console cheat sheet](gitlab_rails_cheat_sheet.md)
-- [Group SAML and SCIM troubleshooting](group_saml_scim.md) **(PREMIUM SAAS)**
+- [Example group SAML and SCIM configurations](../../user/group/saml_sso/example_saml_config.md)
- [Kubernetes cheat sheet](https://docs.gitlab.com/charts/troubleshooting/kubernetes_cheat_sheet.html)
- [Linux cheat sheet](linux_cheat_sheet.md)
-- [Parsing GitLab logs with `jq`](log_parsing.md)
+- [Parsing GitLab logs with `jq`](../logs/log_parsing.md)
- [Diagnostics tools](diagnostics_tools.md)
-- [Tracing requests with correlation ID](tracing_correlation_id.md)
Some feature documentation pages also have a troubleshooting section at the end
that you can check for feature-specific help.
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index 66d5fb82936..6ff6e562a7d 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -14,7 +14,7 @@ having an issue with GitLab, you may want to check your [support options](https:
first, before attempting to use this information.
WARNING:
-It is [beyond the scope of GitLab Support to assist in systems administration](https://about.gitlab.com/support/statement-of-support.html#training). GitLab administrators are expected to know these commands for their distribution
+It is [beyond the scope of GitLab Support to assist in systems administration](https://about.gitlab.com/support/statement-of-support/#training). GitLab administrators are expected to know these commands for their distribution
of choice. If you are a GitLab Support Engineer, consider this a cross-reference to
translate `yum` -> `apt-get` and the like.
@@ -204,24 +204,39 @@ or you can build it from source if you have the Rust compiler.
#### How to use the tool
-First run the tool with no arguments other than the strace output filename to get
-a summary of the top processes sorted by time spent actively performing tasks. You
-can also sort based on total time, # of system calls made, PID #, and # of child processes
-using the `-S` or `--sort` flag. The number of results defaults to 25 processes, but
+First run the tool with `summary` flag to get a summary of the top processes sorted by time spent actively performing tasks.
+You can also sort based on total time, # of system calls made, PID #, and # of child processes
+using the `-s` or `--sort` flag. The number of results defaults to 25 processes, but
can be changed using the `-c`/`--count` option. See `--help` for full details.
```shell
-$ ./strace-parser strace.txt
+$ ./strace-parser sidekiq_trace.txt summary -c15 -s=pid
-Top 25 PIDs
+Top 15 PIDs by PID #
-----------
- pid active (ms) wait (ms) total (ms) % active syscalls
- ---------- ---------- --------- --------- --------- ---------
- 8795 689.072 45773.832 46462.902 16.89% 23018
- 13408 679.432 55910.891 56590.320 16.65% 28593
- 6423 554.822 13175.485 13730.308 13.60% 13735
-...
+ pid actv (ms) wait (ms) user (ms) total (ms) % of actv syscalls children
+ ------- ---------- ---------- ---------- ---------- --------- --------- ---------
+ 16706 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16708 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16716 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16717 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16718 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16719 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16720 0.389 9796.434 1.090 9797.912 0.02% 16 0
+ 16721 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16722 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16723 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16804 0.218 11099.535 1.881 11101.634 0.01% 36 0
+ 16813 0.000 0.000 0.000 0.000 0.00% 0 0
+ 16814 1.740 11825.640 4.616 11831.996 0.10% 57 0
+ 16815 2.364 12039.993 7.669 12050.026 0.14% 80 0
+ 16816 0.000 0.000 0.000 0.000 0.00% 0 0
+
+PIDs 93
+real 0m12.287s
+user 0m1.474s
+sys 0m1.686s
```
Based on the summary, you can then view the details of system calls made by one or more
@@ -229,36 +244,38 @@ processes using the `-p`/`--pid` for a specific process, or `-s`/`--stats` flags
a sorted list. `--stats` takes the same sorting and count options as summary.
```shell
-$ ./strace-parse strace.text -p 6423
-
-PID 6423
-13735 syscalls, active time: 554.822ms, total time: 13730.308ms
-
- syscall count total max avg min errors
- (ms) (ms) (ms) (ms)
- --------------- -------- ---------- ---------- ---------- ---------- --------
- epoll_wait 628 13175.485 21.259 20.980 0.020
- clock_gettime 7326 199.500 0.249 0.027 0.013
- stat 2101 110.768 19.056 0.053 0.017 ENOENT: 2076
- ...
+./strace-parser sidekiq_trace.txt p 16815
+
+PID 16815
+
+ 80 syscalls, active time: 2.364ms, user time: 7.669ms, total time: 12050.026ms
+ start time: 22:46:14.830267 end time: 22:46:26.880293
+
+ syscall count total (ms) max (ms) avg (ms) min (ms) errors
+ ----------------- -------- ---------- ---------- ---------- ---------- --------
+ futex 5 10100.229 5400.106 2020.046 0.022 ETIMEDOUT: 2
+ restart_syscall 1 1939.764 1939.764 1939.764 1939.764 ETIMEDOUT: 1
+ getpid 33 1.020 0.046 0.031 0.018
+ clock_gettime 14 0.420 0.038 0.030 0.021
+ stat 6 0.277 0.072 0.046 0.031
+ read 6 0.170 0.036 0.028 0.020
+ openat 3 0.126 0.045 0.042 0.038
+ close 3 0.099 0.034 0.033 0.031
+ lseek 3 0.089 0.035 0.030 0.021
+ ioctl 3 0.082 0.033 0.027 0.023 ENOTTY: 3
+ fstat 3 0.081 0.034 0.027 0.022
---------------
- Parent PID: 495
- Child PIDs: 8383, 8418, 8419, 8420, 8421
+ Slowest file open times for PID 16815:
- Slowest file access times for PID 6423:
-
- open (ms) timestamp error file name
- ----------- --------------- --------------- ----------
- 29.818 10:53:11.528954 /srv/gitlab-data/builds/2018_08/6174/954448.log
- 12.309 10:53:46.708274 /srv/gitlab-data/builds/2018_08/5342/954186.log
- 0.039 10:53:49.222110 /opt/gitlab/embedded/service/gitlab-rails/app/views/events/event/_note.html.haml
- 0.035 10:53:49.125115 /opt/gitlab/embedded/service/gitlab-rails/app/views/events/event/_push.html.haml
- ...
+ dur (ms) timestamp error file name
+ ---------- --------------- --------------- ---------
+ 0.045 22:46:16.771318 - /opt/gitlab/embedded/service/gitlab-rails/config/database.yml
+ 0.043 22:46:26.877954 - /opt/gitlab/embedded/service/gitlab-rails/config/database.yml
+ 0.038 22:46:22.174610 - /opt/gitlab/embedded/service/gitlab-rails/config/database.yml
```
-In the example above, we can see that file opening times on `/srv/gitlab-data` are
-extremely slow, about 100X slower than `/opt/gitlab`.
+In the example above, we can see which files took longer to open for `PID 16815`.
When nothing stands out in the results, a good way to get more context is to run `strace`
on your own GitLab instance while performing the action performed by the customer,
diff --git a/doc/administration/troubleshooting/log_parsing.md b/doc/administration/troubleshooting/log_parsing.md
index 0320b2e52ce..929a49494be 100644
--- a/doc/administration/troubleshooting/log_parsing.md
+++ b/doc/administration/troubleshooting/log_parsing.md
@@ -1,316 +1,11 @@
---
-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
+redirect_to: '../logs/log_parsing.md'
+remove_date: '2022-10-24'
---
-# Parsing GitLab logs with `jq` **(FREE SELF)**
+This document was moved to [another location](../logs/log_parsing.md).
-We recommend using log aggregation and search tools like Kibana and Splunk whenever possible,
-but if they are not available you can still quickly parse
-[GitLab logs](../logs.md) in JSON format
-(the default in GitLab 12.0 and later) using [`jq`](https://stedolan.github.io/jq/).
-
-NOTE:
-Specifically for summarizing error events and basic usage statistics,
-the GitLab Support Team provides the specialised
-[`fast-stats` tool](https://gitlab.com/gitlab-com/support/toolbox/fast-stats/#when-to-use-it).
-
-## What is JQ?
-
-As noted in its [manual](https://stedolan.github.io/jq/manual/), `jq` is a command-line JSON processor. The following examples
-include use cases targeted for parsing GitLab log files.
-
-## Parsing Logs
-
-The examples listed below address their respective log files by
-their relative Omnibus paths and default filenames.
-Find the respective full paths in the [GitLab logs sections](../logs.md#production_jsonlog).
-
-### General Commands
-
-#### Pipe colorized `jq` output into `less`
-
-```shell
-jq . <FILE> -C | less -R
-```
-
-#### Search for a term and pretty-print all matching lines
-
-```shell
-grep <TERM> <FILE> | jq .
-```
-
-#### Skip invalid lines of JSON
-
-```shell
-jq -cR 'fromjson?' file.json | jq <COMMAND>
-```
-
-By default `jq` errors out when it encounters a line that is not valid JSON.
-This skips over all invalid lines and parses the rest.
-
-#### Print a JSON log's time range
-
-```shell
-cat log.json | (head -1; tail -1) | jq '.time'
-```
-
-Use `zcat` if the file has been rotated and compressed:
-
-```shell
-zcat @400000006026b71d1a7af804.s | (head -1; tail -1) | jq '.time'
-
-zcat some_json.log.25.gz | (head -1; tail -1) | jq '.time'
-```
-
-#### Get activity for correlation ID across multiple JSON logs in chronological order
-
-```shell
-grep -hR <correlationID> | jq -c -R 'fromjson?' | jq -C -s 'sort_by(.time)' | less -R
-```
-
-### Parsing `gitlab-rails/production_json.log` and `gitlab-rails/api_json.log`
-
-#### Find all requests with a 5XX status code
-
-```shell
-jq 'select(.status >= 500)' <FILE>
-```
-
-#### Top 10 slowest requests
-
-```shell
-jq -s 'sort_by(-.duration_s) | limit(10; .[])' <FILE>
-```
-
-#### Find and pretty print all requests related to a project
-
-```shell
-grep <PROJECT_NAME> <FILE> | jq .
-```
-
-#### Find all requests with a total duration > 5 seconds
-
-```shell
-jq 'select(.duration_s > 5000)' <FILE>
-```
-
-#### Find all project requests with more than 5 rugged calls
-
-```shell
-grep <PROJECT_NAME> <FILE> | jq 'select(.rugged_calls > 5)'
-```
-
-#### Find all requests with a Gitaly duration > 10 seconds
-
-```shell
-jq 'select(.gitaly_duration_s > 10000)' <FILE>
-```
-
-#### Find all requests with a queue duration > 10 seconds
-
-```shell
-jq 'select(.queue_duration_s > 10000)' <FILE>
-```
-
-#### Top 10 requests by # of Gitaly calls
-
-```shell
-jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE>
-```
-
-### Parsing `gitlab-rails/production_json.log`
-
-#### Print the top three controller methods by request volume and their three longest durations
-
-```shell
-jq -s -r 'group_by(.controller+.action) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tMETHOD: \(.[0].controller)#\(.[0].action)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' production_json.log
-```
-
-**Example output**
-
-```plaintext
-CT: 2721 METHOD: SessionsController#new DURS: 844.06, 713.81, 704.66
-CT: 2435 METHOD: MetricsController#index DURS: 299.29, 284.01, 158.57
-CT: 1328 METHOD: Projects::NotesController#index DURS: 403.99, 386.29, 384.39
-```
-
-### Parsing `gitlab-rails/api_json.log`
-
-#### Print top three routes with request count and their three longest durations
-
-```shell
-jq -s -r 'group_by(.route) | sort_by(-length) | limit(3; .[]) | sort_by(-.duration_s) | "CT: \(length)\tROUTE: \(.[0].route)\tDURS: \(.[0].duration_s), \(.[1].duration_s), \(.[2].duration_s)"' api_json.log
-```
-
-**Example output**
-
-```plaintext
-CT: 2472 ROUTE: /api/:version/internal/allowed DURS: 56402.65, 38411.43, 19500.41
-CT: 297 ROUTE: /api/:version/projects/:id/repository/tags DURS: 731.39, 685.57, 480.86
-CT: 190 ROUTE: /api/:version/projects/:id/repository/commits DURS: 1079.02, 979.68, 958.21
-```
-
-### Print top API user agents
-
-```shell
-jq --raw-output '[.route, .ua] | @tsv' api_json.log | sort | uniq -c | sort -n
-```
-
-**Example output**:
-
-```plaintext
- 89 /api/:version/usage_data/increment_unique_users # plus browser details
- 567 /api/:version/jobs/:id/trace gitlab-runner # plus version details
-1234 /api/:version/internal/allowed GitLab-Shell
-```
-
-This sample response seems normal. A custom tool or script might be causing a high load
-if the output contains many:
-
-- Third party libraries like `python-requests` or `curl`.
-- [GitLab CLI clients](https://about.gitlab.com/partners/technology-partners/#cli-clients).
-
-You can also [use `fast-stats top`](#parsing-gitlab-logs-with-jq) to extract performance statistics.
-
-### Parsing `gitlab-workhorse/current`
-
-### Print top Workhorse user agents
-
-```shell
-jq --raw-output '[.uri, .user_agent] | @tsv' current | sort | uniq -c | sort -n
-```
-
-**Example output**:
-
-```plaintext
- 89 /api/graphql # plus browser details
- 567 /api/v4/internal/allowed GitLab-Shell
-1234 /api/v4/jobs/request gitlab-runner # plus version details
-```
-
-Similar to the [API `ua` data](#print-top-api-user-agents),
-deviations from this common order might indicate scripts that could be optimized.
-
-The performance impact of runners checking for new jobs can be reduced by increasing
-[the `check_interval` setting](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section),
-for example.
-
-### Parsing `gitlab-rails/geo.log`
-
-#### Find most common Geo sync errors
-
-If [the `geo:status` Rake task](../geo/replication/troubleshooting.md#sync-status-rake-task)
-repeatedly reports that some items never reach 100%,
-the following command helps to focus on the most common errors.
-
-```shell
-jq --raw-output 'select(.severity == "ERROR") | [.project_path, .message] | @tsv' geo.log | sort | uniq -c | sort | tail
-```
-
-### Parsing `gitaly/current`
-
-Use the following examples to [troubleshoot Gitaly](../gitaly/troubleshooting.md).
-
-#### Find all Gitaly requests sent from web UI
-
-```shell
-jq 'select(."grpc.meta.client_name" == "gitlab-web")' current
-```
-
-#### Find all failed Gitaly requests
-
-```shell
-jq 'select(."grpc.code" != null and ."grpc.code" != "OK")' current
-```
-
-#### Find all requests that took longer than 30 seconds
-
-```shell
-jq 'select(."grpc.time_ms" > 30000)' current
-```
-
-#### Print top ten projects by request volume and their three longest durations
-
-```shell
-jq --raw-output --slurp '
- map(
- select(
- ."grpc.request.glProjectPath" != null
- and ."grpc.request.glProjectPath" != ""
- and ."grpc.time_ms" != null
- )
- )
- | group_by(."grpc.request.glProjectPath")
- | sort_by(-length)
- | limit(10; .[])
- | sort_by(-."grpc.time_ms")
- | [
- length,
- .[0]."grpc.time_ms",
- .[1]."grpc.time_ms",
- .[2]."grpc.time_ms",
- .[0]."grpc.request.glProjectPath"
- ]
- | @sh' current \
-| awk 'BEGIN { printf "%7s %10s %10s %10s\t%s\n", "CT", "MAX DURS", "", "", "PROJECT" }
- { printf "%7u %7u ms, %7u ms, %7u ms\t%s\n", $1, $2, $3, $4, $5 }'
-```
-
-**Example output**
-
-```plaintext
- CT MAX DURS PROJECT
- 206 4898 ms, 1101 ms, 1032 ms 'groupD/project4'
- 109 1420 ms, 962 ms, 875 ms 'groupEF/project56'
- 663 106 ms, 96 ms, 94 ms 'groupABC/project123'
- ...
-```
-
-#### Find all projects affected by a fatal Git problem
-
-```shell
-grep "fatal: " current | \
- jq '."grpc.request.glProjectPath"' | \
- sort | uniq
-```
-
-### Parsing `gitlab-shell/gitlab-shell.log`
-
-For investigating Git calls via SSH, from [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/367).
-
-Find the top 20 calls by project and user:
-
-```shell
-jq --raw-output --slurp '
- map(
- select(
- .username != null and
- .gl_project_path !=null
- )
- )
- | group_by(.username+.gl_project_path)
- | sort_by(-length)
- | limit(20; .[])
- | "count: \(length)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
- gitlab-shell.log
-```
-
-Find the top 20 calls by project, user, and command:
-
-```shell
-jq --raw-output --slurp '
- map(
- select(
- .command != null and
- .username != null and
- .gl_project_path !=null
- )
- )
- | group_by(.username+.gl_project_path+.command)
- | sort_by(-length)
- | limit(20; .[])
- | "count: \(length)\tcommand: \(.[0].command)\tuser: \(.[0].username)\tproject: \(.[0].gl_project_path)" ' \
- gitlab-shell.log
-```
+<!-- This redirect file can be deleted after <2022-10-24>. -->
+<!-- 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/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 61b661d45f8..9e3d3d47a10 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -216,7 +216,7 @@ because the statement timeout was too short:
pg_dump: error: Error message from server: server closed the connection unexpectedly
```
-You may also see errors in the [PostgreSQL logs](../logs.md#postgresql-logs):
+You may also see errors in the [PostgreSQL logs](../logs/index.md#postgresql-logs):
```plaintext
canceling statement due to statement timeout
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index 40bfe22ac63..e49e0ed4f1c 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -1,395 +1,11 @@
---
-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
+redirect_to: '../sidekiq/sidekiq_troubleshooting.md'
+remove_date: '2022-11-11'
---
-# Troubleshooting Sidekiq **(FREE SELF)**
+This document was moved to [another location](../sidekiq/sidekiq_troubleshooting.md).
-Sidekiq is the background job processor GitLab uses to asynchronously run
-tasks. When things go wrong it can be difficult to troubleshoot. These
-situations also tend to be high-pressure because a production system job queue
-may be filling up. Users will notice when this happens because new branches
-may not show up and merge requests may not be updated. The following are some
-troubleshooting steps to help you diagnose the bottleneck.
-
-GitLab administrators/users should consider working through these
-debug steps with GitLab Support so the backtraces can be analyzed by our team.
-It may reveal a bug or necessary improvement in GitLab.
-
-In any of the backtraces, be wary of suspecting cases where every
-thread appears to be waiting in the database, Redis, or waiting to acquire
-a mutex. This **may** mean there's contention in the database, for example,
-but look for one thread that is different than the rest. This other thread
-may be using all available CPU, or have a Ruby Global Interpreter Lock,
-preventing other threads from continuing.
-
-## Log arguments to Sidekiq jobs
-
-[In GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44853)
-some arguments passed to Sidekiq jobs are logged by default.
-To avoid logging sensitive information (for instance, password reset tokens),
-GitLab logs numeric arguments for all workers, with overrides for some specific
-workers where their arguments are not sensitive.
-
-Example log output:
-
-```json
-{"severity":"INFO","time":"2020-06-08T14:37:37.892Z","class":"AdminEmailsWorker","args":["[FILTERED]","[FILTERED]","[FILTERED]"],"retry":3,"queue":"admin_emails","backtrace":true,"jid":"9e35e2674ac7b12d123e13cc","created_at":"2020-06-08T14:37:37.373Z","meta.user":"root","meta.caller_id":"Admin::EmailsController#create","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:6dc94409cfdd4d77:9fbe19bdee865293:1","enqueued_at":"2020-06-08T14:37:37.410Z","pid":65011,"message":"AdminEmailsWorker JID-9e35e2674ac7b12d123e13cc: done: 0.48085 sec","job_status":"done","scheduling_latency_s":0.001012,"redis_calls":9,"redis_duration_s":0.004608,"redis_read_bytes":696,"redis_write_bytes":6141,"duration_s":0.48085,"cpu_s":0.308849,"completed_at":"2020-06-08T14:37:37.892Z","db_duration_s":0.010742}
-{"severity":"INFO","time":"2020-06-08T14:37:37.894Z","class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","wrapped":"ActionMailer::MailDeliveryJob","queue":"mailers","args":["[FILTERED]"],"retry":3,"backtrace":true,"jid":"e47a4f6793d475378432e3c8","created_at":"2020-06-08T14:37:37.884Z","meta.user":"root","meta.caller_id":"AdminEmailsWorker","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:29344de0f966446d:5c3b0e0e1bef987b:1","enqueued_at":"2020-06-08T14:37:37.885Z","pid":65011,"message":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper JID-e47a4f6793d475378432e3c8: start","job_status":"start","scheduling_latency_s":0.009473}
-{"severity":"INFO","time":"2020-06-08T14:39:50.648Z","class":"NewIssueWorker","args":["455","1"],"retry":3,"queue":"new_issue","backtrace":true,"jid":"a24af71f96fd129ec47f5d1e","created_at":"2020-06-08T14:39:50.643Z","meta.user":"root","meta.project":"h5bp/html5-boilerplate","meta.root_namespace":"h5bp","meta.caller_id":"Projects::IssuesController#create","correlation_id":"f9UCZHqhuP7","uber-trace-id":"28f65730f99f55a3:a5d2b62dec38dffc:48ddd092707fa1b7:1","enqueued_at":"2020-06-08T14:39:50.646Z","pid":65011,"message":"NewIssueWorker JID-a24af71f96fd129ec47f5d1e: start","job_status":"start","scheduling_latency_s":0.001144}
-```
-
-When using [Sidekiq JSON logging](../logs.md#sidekiqlog),
-arguments logs are limited to a maximum size of 10 kilobytes of text;
-any arguments after this limit are discarded and replaced with a
-single argument containing the string `"..."`.
-
-You can set `SIDEKIQ_LOG_ARGUMENTS` [environment variable](https://docs.gitlab.com/omnibus/settings/environment-variables.html)
-to `0` (false) to disable argument logging.
-
-Example:
-
-```ruby
-gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "0"}
-```
-
-In GitLab 13.5 and earlier, set `SIDEKIQ_LOG_ARGUMENTS` to `1` to start logging arguments passed to Sidekiq.
-
-## Thread dump
-
-Send the Sidekiq process ID the `TTIN` signal to output thread
-backtraces in the log file.
-
-```shell
-kill -TTIN <sidekiq_pid>
-```
-
-Check in `/var/log/gitlab/sidekiq/current` or `$GITLAB_HOME/log/sidekiq.log` for
-the backtrace output. The backtraces are lengthy and generally start with
-several `WARN` level messages. Here's an example of a single thread's backtrace:
-
-```plaintext
-2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: ActiveRecord::RecordNotFound: Couldn't find Note with 'id'=3375386
-2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/activerecord-4.2.5.2/lib/active_record/core.rb:155:in `find'
-/opt/gitlab/embedded/service/gitlab-rails/app/workers/new_note_worker.rb:7:in `perform'
-/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:150:in `execute_job'
-/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:132:in `block (2 levels) in process'
-/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
-/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/memory_killer.rb:17:in `call'
-/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
-/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/arguments_logger.rb:6:in `call'
-...
-```
-
-In some cases Sidekiq may be hung and unable to respond to the `TTIN` signal.
-Move on to other troubleshooting methods if this happens.
-
-## Ruby profiling with `rbspy`
-
-[rbspy](https://rbspy.github.io) is an easy to use and low-overhead Ruby profiler that can be used to create
-flamegraph-style diagrams of CPU usage by Ruby processes.
-
-No changes to GitLab are required to use it and it has no dependencies. To install it:
-
-1. Download the binary from the [`rbspy` releases page](https://github.com/rbspy/rbspy/releases).
-1. Make the binary executable.
-
-To profile a Sidekiq worker for one minute, run:
-
-```shell
-sudo ./rbspy record --pid <sidekiq_pid> --duration 60 --file /tmp/sidekiq_profile.svg
-```
-
-![Example rbspy flamegraph](img/sidekiq_flamegraph.png)
-
-In this example of a flamegraph generated by `rbspy`, almost all of the Sidekiq process's time is spent in `rev_parse`, a native C
-function in Rugged. In the stack, we can see `rev_parse` is being called by the `ExpirePipelineCacheWorker`.
-
-## Process profiling with `perf`
-
-Linux has a process profiling tool called `perf` that is helpful when a certain
-process is eating up a lot of CPU. If you see high CPU usage and Sidekiq isn't
-responding to the `TTIN` signal, this is a good next step.
-
-If `perf` is not installed on your system, install it with `apt-get` or `yum`:
-
-```shell
-# Debian
-sudo apt-get install linux-tools
-
-# Ubuntu (may require these additional Kernel packages)
-sudo apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`
-
-# Red Hat/CentOS
-sudo yum install perf
-```
-
-Run `perf` against the Sidekiq PID:
-
-```shell
-sudo perf record -p <sidekiq_pid>
-```
-
-Let this run for 30-60 seconds and then press Ctrl-C. Then view the `perf` report:
-
-```shell
-$ sudo perf report
-
-# Sample output
-Samples: 348K of event 'cycles', Event count (approx.): 280908431073
- 97.69% ruby nokogiri.so [.] xmlXPathNodeSetMergeAndClear
- 0.18% ruby libruby.so.2.1.0 [.] objspace_malloc_increase
- 0.12% ruby libc-2.12.so [.] _int_malloc
- 0.10% ruby libc-2.12.so [.] _int_free
-```
-
-Above you see sample output from a `perf` report. It shows that 97% of the CPU is
-being spent inside Nokogiri and `xmlXPathNodeSetMergeAndClear`. For something
-this obvious you should then go investigate what job in GitLab would use
-Nokogiri and XPath. Combine with `TTIN` or `gdb` output to show the
-corresponding Ruby code where this is happening.
-
-## The GNU Project Debugger (`gdb`)
-
-`gdb` can be another effective tool for debugging Sidekiq. It gives you a little
-more interactive way to look at each thread and see what's causing problems.
-
-Attaching to a process with `gdb` suspends the normal operation
-of the process (Sidekiq does not process jobs while `gdb` is attached).
-
-Start by attaching to the Sidekiq PID:
-
-```shell
-gdb -p <sidekiq_pid>
-```
-
-Then gather information on all the threads:
-
-```plaintext
-info threads
-
-# Example output
-30 Thread 0x7fe5fbd63700 (LWP 26060) 0x0000003f7cadf113 in poll () from /lib64/libc.so.6
-29 Thread 0x7fe5f2b3b700 (LWP 26533) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-28 Thread 0x7fe5f2a3a700 (LWP 26534) 0x0000003f7ce0ba5e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-27 Thread 0x7fe5f2939700 (LWP 26535) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-26 Thread 0x7fe5f2838700 (LWP 26537) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-25 Thread 0x7fe5f2737700 (LWP 26538) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-24 Thread 0x7fe5f2535700 (LWP 26540) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-23 Thread 0x7fe5f2434700 (LWP 26541) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-22 Thread 0x7fe5f2232700 (LWP 26543) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
-21 Thread 0x7fe5f2131700 (LWP 26544) 0x00007fe5f7b570f0 in xmlXPathNodeSetMergeAndClear ()
-from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-...
-```
-
-If you see a suspicious thread, like the Nokogiri one above, you may want
-to get more information:
-
-```plaintext
-thread 21
-bt
-
-# Example output
-#0 0x00007ff0d6afe111 in xmlXPathNodeSetMergeAndClear () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#1 0x00007ff0d6b0b836 in xmlXPathNodeCollectAndTest () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#2 0x00007ff0d6b09037 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#3 0x00007ff0d6b09017 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#4 0x00007ff0d6b092e0 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#5 0x00007ff0d6b0bc37 in xmlXPathRunEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#6 0x00007ff0d6b0be5f in xmlXPathEvalExpression () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
-#7 0x00007ff0d6a97dc3 in evaluate (argc=2, argv=0x1022d058, self=<value optimized out>) at xml_xpath_context.c:221
-#8 0x00007ff0daeab0ea in vm_call_cfunc_with_frame (th=0x1022a4f0, reg_cfp=0x1032b810, ci=<value optimized out>) at vm_insnhelper.c:1510
-```
-
-To output a backtrace from all threads at once:
-
-```plaintext
-set pagination off
-thread apply all bt
-```
-
-Once you're done debugging with `gdb`, be sure to detach from the process and
-exit:
-
-```plaintext
-detach
-exit
-```
-
-## Sidekiq kill signals
-
-TTIN was described above as the signal to print backtraces for logging, however
-Sidekiq responds to other signals as well. For example, TSTP and TERM can be used
-to gracefully shut Sidekiq down, see
-[the Sidekiq Signals docs](https://github.com/mperham/sidekiq/wiki/Signals#ttin).
-
-## Check for blocking queries
-
-Sometimes the speed at which Sidekiq processes jobs can be so fast that it can
-cause database contention. Check for blocking queries when backtraces above
-show that many threads are stuck in the database adapter.
-
-The PostgreSQL wiki has details on the query you can run to see blocking
-queries. The query is different based on PostgreSQL version. See
-[Lock Monitoring](https://wiki.postgresql.org/wiki/Lock_Monitoring) for
-the query details.
-
-## Managing Sidekiq queues
-
-It is possible to use [Sidekiq API](https://github.com/mperham/sidekiq/wiki/API)
-to perform a number of troubleshooting steps on Sidekiq.
-
-These are the administrative commands and it should only be used if currently
-administration interface is not suitable due to scale of installation.
-
-All these commands should be run using `gitlab-rails console`.
-
-### View the queue size
-
-```ruby
-Sidekiq::Queue.new("pipeline_processing:build_queue").size
-```
-
-### Enumerate all enqueued jobs
-
-```ruby
-queue = Sidekiq::Queue.new("chaos:chaos_sleep")
-queue.each do |job|
- # job.klass # => 'MyWorker'
- # job.args # => [1, 2, 3]
- # job.jid # => jid
- # job.queue # => chaos:chaos_sleep
- # job["retry"] # => 3
- # job.item # => {
- # "class"=>"Chaos::SleepWorker",
- # "args"=>[1000],
- # "retry"=>3,
- # "queue"=>"chaos:chaos_sleep",
- # "backtrace"=>true,
- # "queue_namespace"=>"chaos",
- # "jid"=>"39bc482b823cceaf07213523",
- # "created_at"=>1566317076.266069,
- # "correlation_id"=>"c323b832-a857-4858-b695-672de6f0e1af",
- # "enqueued_at"=>1566317076.26761},
- # }
-
- # job.delete if job.jid == 'abcdef1234567890'
-end
-```
-
-### Enumerate currently running jobs
-
-```ruby
-workers = Sidekiq::Workers.new
-workers.each do |process_id, thread_id, work|
- # process_id is a unique identifier per Sidekiq process
- # thread_id is a unique identifier per thread
- # work is a Hash which looks like:
- # {"queue"=>"chaos:chaos_sleep",
- # "payload"=>
- # { "class"=>"Chaos::SleepWorker",
- # "args"=>[1000],
- # "retry"=>3,
- # "queue"=>"chaos:chaos_sleep",
- # "backtrace"=>true,
- # "queue_namespace"=>"chaos",
- # "jid"=>"b2a31e3eac7b1a99ff235869",
- # "created_at"=>1566316974.9215662,
- # "correlation_id"=>"e484fb26-7576-45f9-bf21-b99389e1c53c",
- # "enqueued_at"=>1566316974.9229589},
- # "run_at"=>1566316974}],
-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.
-
-```ruby
-queue = Sidekiq::Queue.new('<queue name>')
-queue.each { |job| job.delete if <condition>}
-```
-
-Have a look at the section below for cancelling running jobs.
-
-In the method above, `<queue-name>` is the name of the queue that contains the jobs you want to delete and `<condition>` decides which jobs get deleted.
-
-Commonly, `<condition>` references the job arguments, which depend on the type of job in question. To find the arguments for a specific queue, you can have a look at the `perform` function of the related worker file, commonly found at `/app/workers/<queue-name>_worker.rb`.
-
-For example, `repository_import` has `project_id` as the job argument, while `update_merge_requests` has `project_id, user_id, oldrev, newrev, ref`.
-
-Arguments need to be referenced by their sequence ID using `job.args[<id>]` because `job.args` is a list of all arguments provided to the Sidekiq job.
-
-Here are some examples:
-
-```ruby
-queue = Sidekiq::Queue.new('update_merge_requests')
-# In this example, we want to remove any update_merge_requests jobs
-# for the Project with ID 125 and ref `ref/heads/my_branch`
-queue.each { |job| job.delete if job.args[0] == 125 and job.args[4] == 'ref/heads/my_branch' }
-```
-
-```ruby
-# Cancelling jobs like: `RepositoryImportWorker.new.perform_async(100)`
-id_list = [100]
-
-queue = Sidekiq::Queue.new('repository_import')
-queue.each do |job|
- job.delete if id_list.include?(job.args[0])
-end
-```
-
-### Remove specific job ID (destructive)
-
-```ruby
-queue = Sidekiq::Queue.new('repository_import')
-queue.each do |job|
- job.delete if job.jid == 'my-job-id'
-end
-```
-
-## Canceling running jobs (destructive)
-
-> Introduced in GitLab 12.3.
-
-This is highly risky operation and use it as last resort.
-Doing that might result in data corruption, as the job
-is interrupted mid-execution and it is not guaranteed
-that proper rollback of transactions is implemented.
-
-```ruby
-Gitlab::SidekiqDaemon::Monitor.cancel_job('job-id')
-```
-
-> This requires the Sidekiq to be run with `SIDEKIQ_MONITOR_WORKER=1`
-> environment variable.
-
-To perform of the interrupt we use `Thread.raise` which
-has number of drawbacks, as mentioned in [Why Ruby's Timeout is dangerous (and Thread.raise is terrifying)](https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/):
-
-> This is where the implications get interesting, and terrifying. This means that an exception can get raised:
->
-> - during a network request (ok, as long as the surrounding code is prepared to catch Timeout::Error)
-> - during the cleanup for the network request
-> - during a rescue block
-> - while creating an object to save to the database afterwards
-> - in any of your code, regardless of whether it could have possibly raised an exception before
->
-> Nobody writes code to defend against an exception being raised on literally any line. That's not even possible. So Thread.raise is basically like a sneak attack on your code that could result in almost anything. It would probably be okay if it were pure-functional code that did not modify any state. But this is Ruby, so that's unlikely :)
-
-## Disable Rugged
-
-Calls into Rugged, Ruby bindings for `libgit2`, [lock the Sidekiq processes's GVL](https://silverhammermba.github.io/emberb/c/#c-in-ruby-threads),
-blocking all jobs on that worker from proceeding. If Rugged calls performed by Sidekiq are slow, this can cause significant delays in
-background task processing.
-
-By default, Rugged is used when Git repository data is stored on local storage or on an NFS mount.
-[Using Rugged is recommended when using NFS](../nfs.md#improving-nfs-performance-with-gitlab), but if
-you are using local storage, disabling Rugged can improve Sidekiq performance:
-
-```shell
-sudo gitlab-rake gitlab:features:disable_rugged
-```
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index 418dd729066..ee59b7c2504 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -1,202 +1,11 @@
---
-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
+redirect_to: '../logs/tracing_correlation_id.md'
+remove_date: '2022-11-12'
---
-# Finding relevant log entries with a correlation ID **(FREE SELF)**
+This document was moved to [another location](../logs/tracing_correlation_id.md).
-GitLab instances log a unique request tracking ID (known as the
-"correlation ID") for most requests. Each individual request to GitLab gets
-its own correlation ID, which then gets logged in each GitLab component's logs for that
-request. This makes it easier to trace behavior in a
-distributed system. Without this ID it can be difficult or
-impossible to match correlating log entries.
-
-## Identify the correlation ID for a request
-
-The correlation ID is logged in structured logs under the key `correlation_id`
-and in all response headers GitLab sends under the header `x-request-id`.
-You can find your correlation ID by searching in either place.
-
-### Getting the correlation ID in your browser
-
-You can use your browser's developer tools to monitor and inspect network
-activity with the site that you're visiting. See the links below for network monitoring
-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/)
-
-To locate a relevant request and view its correlation ID:
-
-1. Enable persistent logging in your network monitor. Some actions in GitLab redirect you quickly after you submit a form, so this helps capture all relevant activity.
-1. To help isolate the requests you are looking for, you can filter for `document` requests.
-1. Select the request of interest to view further detail.
-1. Go to the **Headers** section and look for **Response Headers**. There you should find an `x-request-id` header with a
-value that was randomly generated by GitLab for the request.
-
-See the following example:
-
-![Firefox's network monitor showing an request ID header](img/network_monitor_xid.png)
-
-### Getting the correlation ID from your logs
-
-Another approach to finding the correct correlation ID is to search or watch
-your logs and find the `correlation_id` value for the log entry that you're
-watching for.
-
-For example, let's say that you want learn what's happening or breaking when
-you reproduce an action in GitLab. You could tail the GitLab logs, filtering
-to requests by your user, and then watch the requests until you see what you're
-interested in.
-
-### Getting the correlation ID from curl
-
-If you're using `curl` then you can use the verbose option to show request and response headers, as well as other debug information.
-
-```shell
-➜ ~ curl --verbose "https://gitlab.example.com/api/v4/projects"
-# look for a line that looks like this
-< x-request-id: 4rAMkV3gof4
-```
-
-#### Using jq
-
-This example uses [jq](https://stedolan.github.io/jq/) to filter results and
-display values we most likely care about.
-
-```shell
-sudo gitlab-ctl tail gitlab-rails/production_json.log | jq 'select(.username == "bob") | "User: \(.username), \(.method) \(.path), \(.controller)#\(.action), ID: \(.correlation_id)"'
-```
-
-```plaintext
-"User: bob, GET /root/linux, ProjectsController#show, ID: U7k7fh6NpW3"
-"User: bob, GET /root/linux/commits/master/signatures, Projects::CommitsController#signatures, ID: XPIHpctzEg1"
-"User: bob, GET /root/linux/blob/master/README, Projects::BlobController#show, ID: LOt9hgi1TV4"
-```
-
-#### Using grep
-
-This example uses only `grep` and `tr`, which are more likely to be installed than `jq`.
-
-```shell
-sudo gitlab-ctl tail gitlab-rails/production_json.log | grep '"username":"bob"' | tr ',' '\n' | egrep 'method|path|correlation_id'
-```
-
-```plaintext
-{"method":"GET"
-"path":"/root/linux"
-"username":"bob"
-"correlation_id":"U7k7fh6NpW3"}
-{"method":"GET"
-"path":"/root/linux/commits/master/signatures"
-"username":"bob"
-"correlation_id":"XPIHpctzEg1"}
-{"method":"GET"
-"path":"/root/linux/blob/master/README"
-"username":"bob"
-"correlation_id":"LOt9hgi1TV4"}
-```
-
-## Searching your logs for the correlation ID
-
-Once you have the correlation ID you can start searching for relevant log
-entries. You can filter the lines by the correlation ID itself.
-Combining a `find` and `grep` should be sufficient to find the entries you are looking for.
-
-```shell
-# find <gitlab log directory> -type f -mtime -0 exec grep '<correlation ID>' '{}' '+'
-find /var/log/gitlab -type f -mtime 0 -exec grep 'LOt9hgi1TV4' '{}' '+'
-```
-
-```plaintext
-/var/log/gitlab/gitlab-workhorse/current:{"correlation_id":"LOt9hgi1TV4","duration_ms":2478,"host":"gitlab.domain.tld","level":"info","method":"GET","msg":"access","proto":"HTTP/1.1","referrer":"https://gitlab.domain.tld/root/linux","remote_addr":"68.0.116.160:0","remote_ip":"[filtered]","status":200,"system":"http","time":"2019-09-17T22:17:19Z","uri":"/root/linux/blob/master/README?format=json\u0026viewer=rich","user_agent":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","written_bytes":1743}
-/var/log/gitlab/gitaly/current:{"correlation_id":"LOt9hgi1TV4","grpc.code":"OK","grpc.meta.auth_version":"v2","grpc.meta.client_name":"gitlab-web","grpc.method":"FindCommits","grpc.request.deadline":"2019-09-17T22:17:47Z","grpc.request.fullMethod":"/gitaly.CommitService/FindCommits","grpc.request.glProjectPath":"root/linux","grpc.request.glRepository":"project-1","grpc.request.repoPath":"@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git","grpc.request.repoStorage":"default","grpc.request.topLevelGroup":"@hashed","grpc.service":"gitaly.CommitService","grpc.start_time":"2019-09-17T22:17:17Z","grpc.time_ms":2319.161,"level":"info","msg":"finished streaming call with code OK","peer.address":"@","span.kind":"server","system":"grpc","time":"2019-09-17T22:17:19Z"}
-/var/log/gitlab/gitlab-rails/production_json.log:{"method":"GET","path":"/root/linux/blob/master/README","format":"json","controller":"Projects::BlobController","action":"show","status":200,"duration":2448.77,"view":0.49,"db":21.63,"time":"2019-09-17T22:17:19.800Z","params":[{"key":"viewer","value":"rich"},{"key":"namespace_id","value":"root"},{"key":"project_id","value":"linux"},{"key":"id","value":"master/README"}],"remote_ip":"[filtered]","user_id":2,"username":"bob","ua":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","queue_duration":3.38,"gitaly_calls":1,"gitaly_duration":0.77,"rugged_calls":4,"rugged_duration_ms":28.74,"correlation_id":"LOt9hgi1TV4"}
-```
-
-### Searching in distributed architectures
-
-If you have done some horizontal scaling in your GitLab infrastructure, then
-you must search across _all_ of your GitLab nodes. You can do this with
-some sort of log aggregation software like Loki, ELK, Splunk, or others.
-
-You can use a tool like Ansible or PSSH (parallel SSH) that can execute identical commands across your servers in
-parallel, or craft your own solution.
-
-### Viewing the request in the Performance Bar
-
-You can use the [performance bar](../monitoring/performance/performance_bar.md) to view interesting data including calls made to SQL and Gitaly.
-
-To view the data, the correlation ID of the request must match the same session as the user
-viewing the performance bar. For API requests, this means that you must perform the request
-using the session cookie of the signed-in user.
-
-For example, if you want to view the database queries executed for the following API endpoint:
-
-```shell
-https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1
-```
-
-First, enable the **Developer Tools** panel. See [Getting the correlation ID in your browser](#getting-the-correlation-id-in-your-browser) for details on how to do this.
-
-After developer tools have been enabled, obtain a session cookie as follows:
-
-1. Visit <https://gitlab.com> while logged in.
-1. Optional. Select **Fetch/XHR** request filter in the **Developer Tools** panel. This step is described for Google Chrome developer tools and is not strictly necessary, it just makes it easier to find the correct request.
-1. Select the `results?request_id=<some-request-id>` request on the left hand side.
-1. The session cookie is displayed under the `Request Headers` section of the `Headers` panel. Right-click on the cookie value and select `Copy value`.
-
-![Obtaining a session cookie for request](img/obtaining-a-session-cookie-for-request_v14_3.png)
-
-You have the value of the session cookie copied to your clipboard, for example:
-
-```shell
-experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false; frequently_used_emojis=clap,thumbsup,rofl,tada,eyes,bow
-```
-
-Use the value of the session cookie to craft an API request by pasting it into a custom header of a `curl` request:
-
-```shell
-$ curl --include "https://gitlab.com/api/v4/groups/2564205/projects?with_security_reports=true&page=1&per_page=1" \
---header 'cookie: experimentation_subject_id=<subject-id>; _gitlab_session=<session-id>; event_filter=all; visitor_id=<visitor-id>; perf_bar_enabled=true; sidebar_collapsed=true; diff_view=inline; sast_entry_point_dismissed=true; auto_devops_settings_dismissed=true; cf_clearance=<cf-clearance>; collapsed_gutter=false; frequently_used_emojis=clap,thumbsup,rofl,tada,eyes,bow'
-
- date: Tue, 28 Sep 2021 03:55:33 GMT
- content-type: application/json
- ...
- x-request-id: 01FGN8P881GF2E5J91JYA338Y3
- ...
- [
- {
- "id":27497069,
- "description":"Analyzer for images used on live K8S containers based on Starboard"
- },
- "container_registry_image_prefix":"registry.gitlab.com/gitlab-org/security-products/analyzers/cluster-image-scanning",
- "..."
- ]
-```
-
-The response contains the data from the API endpoint, and a `correlation_id` value, returned in the `x-request-id` header, as described in the [Identify the correlation ID for a request](#identify-the-correlation-id-for-a-request) section.
-
-You can then view the database details for this request:
-
-1. Paste the `x-request-id` value into the `request details` field of the [performance bar](../monitoring/performance/performance_bar.md) and press <kbd>Enter/Return</kbd>. This example uses the `x-request-id` value `01FGN8P881GF2E5J91JYA338Y3`, returned by the above response:
-
- ![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:
-
- ![Select request ID from request selector drop down menu](img/select-request-id-from-request-selector-drop-down-menu_v14_3.png)
-
- <!-- vale gitlab.Substitutions = NO -->
-1. Select the `pg` link in the Progress Bar to view the database queries executed by the API request:
-
- ![View pg database details](img/view-pg-details_v14_3.png)
- <!-- vale gitlab.Substitutions = YES -->
-
- The database query dialog is displayed:
-
- ![Database query dialog](img/database-query-dialog_v14_3.png)
+<!-- This redirect file can be deleted after 2022-11-12. -->
+<!-- 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/uploads.md b/doc/administration/uploads.md
index 0bd46193d10..2dd8f1ed819 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -112,15 +112,15 @@ _The uploads are stored by default in
`/home/git/gitlab/public/uploads`._
1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following
- lines:
+ lines, making sure to use the [appropriate ones for your provider](object_storage.md#connection-settings):
```yaml
uploads:
object_store:
enabled: true
remote_directory: "uploads" # The bucket name
- connection:
- provider: AWS # Only AWS supported at the moment
+ connection: # The lines in this block depend on your provider
+ provider: AWS
aws_access_key_id: AWS_ACCESS_KEY_ID
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
region: eu-central-1
diff --git a/doc/api/appearance.md b/doc/api/appearance.md
index 7b98b226cde..7ad79fd66fe 100644
--- a/doc/api/appearance.md
+++ b/doc/api/appearance.md
@@ -104,7 +104,7 @@ PUT /application/appearance
| Attribute | Type | Required | Description |
| --------- | ------ | -------- | -------------- |
-| `logo` | string | Yes | File to upload |
+| `logo` | mixed | Yes | File to upload |
Example request:
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 753e01a15aa..80d7b23d642 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -137,12 +137,13 @@ Example response:
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events).
This API cannot retrieve project audit events.
-A user with a Owner role (or above) can retrieve group audit events of all users.
-A user with a Developer or Maintainer role is limited to group audit events based on their individual actions.
+A user with:
-This endpoint optionally supports [keyset pagination](index.md#keyset-based-pagination):
+- The Owner role can retrieve group audit events of all users.
+- The Developer or Maintainer role is limited to group audit events based on their individual actions.
-- When requesting consecutive pages of results, we recommend you use keyset pagination.
+This endpoint supports both offset-based and [keyset-based](index.md#keyset-based-pagination) pagination. Keyset-based
+pagination is recommended when requesting consecutive pages of results.
### Retrieve all group audit events
diff --git a/doc/api/bulk_imports.md b/doc/api/bulk_imports.md
index 8c5c4574206..913dc6ce4f1 100644
--- a/doc/api/bulk_imports.md
+++ b/doc/api/bulk_imports.md
@@ -27,7 +27,8 @@ POST /bulk_imports
| `entities` | Array | yes | List of entities to import. |
| `entities[source_type]` | String | yes | Source entity type (only `group_entity` is supported). |
| `entities[source_full_path]` | String | yes | Source full path of the entity to import. |
-| `entities[destination_name]` | String | yes | Destination slug for the entity. |
+| `entities[destination_name]` | String | yes | Deprecated: Use :destination_slug instead. Destination slug for the entity. |
+| `entities[destination_slug]` | String | yes | Destination slug for the entity. |
| `entities[destination_namespace]` | String | no | Destination namespace for the entity. |
```shell
@@ -41,7 +42,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
{
"source_full_path": "source/full/path",
"source_type": "group_entity",
- "destination_name": "destination_slug",
+ "destination_slug": "destination_slug",
"destination_namespace": "destination/namespace/path"
}
]
@@ -126,7 +127,7 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
"bulk_import_id": 1,
"status": "finished",
"source_full_path": "source_group",
- "destination_name": "destination_slug",
+ "destination_slug": "destination_slug",
"destination_namespace": "destination_path",
"parent_id": null,
"namespace_id": 1,
@@ -140,7 +141,7 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
"bulk_import_id": 2,
"status": "failed",
"source_full_path": "another_group",
- "destination_name": "another_slug",
+ "destination_slug": "another_slug",
"destination_namespace": "another_namespace",
"parent_id": null,
"namespace_id": null,
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 6831f86e4ea..01fa4e11884 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -458,6 +458,37 @@ Deployments created by users on GitLab Premium or higher include the `approvals`
}
```
+## Delete a specific deployment
+
+Delete a specific deployment that is not currently the last deployment for an environment or in a `running` state
+
+```plaintext
+DELETE /projects/:id/deployments/:deployment_id
+```
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `deployment_id` | integer | yes | The ID of the deployment |
+
+```shell
+curl --request "DELETE" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/1"
+```
+
+Example responses:
+
+```json
+{ "message": "202 Accepted" }
+```
+
+```json
+{ "message": "400 Cannot destroy running deployment" }
+```
+
+```json
+{ "message": "400 Deployment currently deployed to environment" }
+```
+
## List of merge requests associated with a deployment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) in GitLab 12.7.
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index c30c00cef67..a5610adad79 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -170,7 +170,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>"\
### Add note to existing issue thread
-Adds a new note to the thread. This can also [create a thread from a single comment](../user/discussions/#create-a-thread-by-replying-to-a-standard-comment).
+Adds a new note to the thread. This can also [create a thread from a single comment](../user/discussions/index.md#create-a-thread-by-replying-to-a-standard-comment).
**WARNING**
Notes can be added to other items than comments, such as system notes, making them threads.
@@ -599,7 +599,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>"\
### Add note to existing epic thread
Adds a new note to the thread. This can also
-[create a thread from a single comment](../user/discussions/#create-a-thread-by-replying-to-a-standard-comment).
+[create a thread from a single comment](../user/discussions/index.md#create-a-thread-by-replying-to-a-standard-comment).
```plaintext
POST /groups/:id/epics/:epic_id/discussions/:discussion_id/notes
@@ -1021,7 +1021,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>"\
### Add note to existing merge request thread
Adds a new note to the thread. This can also
-[create a thread from a single comment](../user/discussions/#create-a-thread-by-replying-to-a-standard-comment).
+[create a thread from a single comment](../user/discussions/index.md#create-a-thread-by-replying-to-a-standard-comment).
```plaintext
POST /projects/:id/merge_requests/:merge_request_iid/discussions/:discussion_id/notes
@@ -1103,7 +1103,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>"\
Gets a list of all discussion items for a single commit.
```plaintext
-GET /projects/:id/commits/:commit_id/discussions
+GET /projects/:id/repository/commits/:commit_id/discussions
```
| Attribute | Type | Required | Description |
@@ -1237,7 +1237,7 @@ Diff comments contain also position:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions"
```
### Get single commit discussion item
@@ -1245,7 +1245,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>"\
Returns a single discussion item for a specific project commit
```plaintext
-GET /projects/:id/commits/:commit_id/discussions/:discussion_id
+GET /projects/:id/repository/commits/:commit_id/discussions/:discussion_id
```
Parameters:
@@ -1258,7 +1258,7 @@ Parameters:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/<discussion_id>"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions/<discussion_id>"
```
### Create new commit thread
@@ -1267,7 +1267,7 @@ Creates a new thread to a single project commit. This is similar to creating
a note but other comments (replies) can be added to it later.
```plaintext
-POST /projects/:id/commits/:commit_id/discussions
+POST /projects/:id/repository/commits/:commit_id/discussions
```
Parameters:
@@ -1294,7 +1294,7 @@ Parameters:
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions?body=comment"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions?body=comment"
```
The rules for creating the API request are the same as when
@@ -1306,7 +1306,7 @@ with the exception of `base_sha`, `start_sha`, and `head_sha` attributes.
Adds a new note to the thread.
```plaintext
-POST /projects/:id/commits/:commit_id/discussions/:discussion_id/notes
+POST /projects/:id/repository/commits/:commit_id/discussions/:discussion_id/notes
```
Parameters:
@@ -1322,7 +1322,7 @@ Parameters:
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/<discussion_id>/notes?body=comment
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions/<discussion_id>/notes?body=comment
```
### Modify an existing commit thread note
@@ -1330,7 +1330,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>"\
Modify or resolve an existing thread note of a commit.
```plaintext
-PUT /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id
+PUT /projects/:id/repository/commits/:commit_id/discussions/:discussion_id/notes/:note_id
```
Parameters:
@@ -1345,14 +1345,14 @@ Parameters:
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/<discussion_id>/notes/1108?body=comment"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions/<discussion_id>/notes/1108?body=comment"
```
Resolving a note:
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/<discussion_id>/notes/1108?resolved=true"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions/<discussion_id>/notes/1108?resolved=true"
```
### Delete a commit thread note
@@ -1360,7 +1360,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>"\
Deletes an existing thread note of a commit.
```plaintext
-DELETE /projects/:id/commits/:commit_id/discussions/:discussion_id/notes/:note_id
+DELETE /projects/:id/repository/commits/:commit_id/discussions/:discussion_id/notes/:note_id
```
Parameters:
@@ -1374,5 +1374,5 @@ Parameters:
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>"\
- "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/636"
+ "https://gitlab.example.com/api/v4/projects/5/repository/commits/11/discussions/636"
```
diff --git a/doc/api/features.md b/doc/api/features.md
index d4829f72958..f006fa07188 100644
--- a/doc/api/features.md
+++ b/doc/api/features.md
@@ -97,16 +97,6 @@ Example response:
"type": "development",
"group": "group::geo",
"default_enabled": true
- },
- {
- "name": "analytics_devops_adoption_codeowners",
- "introduced_by_url": "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59874",
- "rollout_issue_url": "https://gitlab.com/gitlab-org/gitlab/-/issues/328542",
- "milestone": "13.12",
- "log_state_changes": null,
- "type": "development",
- "group": "group::optimize",
- "default_enabled": true
}
]
```
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index fbb583f5a56..b5b920ec0cd 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -495,6 +495,19 @@ Example response:
"job_artifacts_synced_in_percentage": "100.00%",
"job_artifacts_verified_in_percentage": "100.00%",
"job_artifacts_synced_missing_on_primary_count": 0,
+ "ci_secure_files_count": 5,
+ "ci_secure_files_checksum_total_count": 5,
+ "ci_secure_files_checksummed_count": 5,
+ "ci_secure_files_checksum_failed_count": 0,
+ "ci_secure_files_synced_count": 5,
+ "ci_secure_files_failed_count": 0,
+ "ci_secure_files_registry_count": 5,
+ "ci_secure_files_verification_total_count": 5,
+ "ci_secure_files_verified_count": 5,
+ "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,
},
{
"geo_node_id": 2,
@@ -830,6 +843,19 @@ Example response:
"job_artifacts_synced_in_percentage": "100.00%",
"job_artifacts_verified_in_percentage": "100.00%",
"job_artifacts_synced_missing_on_primary_count": 0,
+ "ci_secure_files_count": 5,
+ "ci_secure_files_checksum_total_count": 5,
+ "ci_secure_files_checksummed_count": 5,
+ "ci_secure_files_checksum_failed_count": 0,
+ "ci_secure_files_synced_count": 5,
+ "ci_secure_files_failed_count": 0,
+ "ci_secure_files_registry_count": 5,
+ "ci_secure_files_verification_total_count": 5,
+ "ci_secure_files_verified_count": 5,
+ "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,
}
```
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index be1bfc79aeb..eab48d65742 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -16,7 +16,7 @@ GraphQL data is arranged in types, so your client can use
to consume the API and avoid manual parsing.
There are no fixed endpoints and no data model, so you can add
-to the API without creating [breaking changes](../../development/contributing/#breaking-changes).
+to the API without creating [breaking changes](../../development/deprecation_guidelines/index.md).
This enables us to have a [versionless API](https://graphql.org/learn/best-practices/#versioning).
## Vision
@@ -69,7 +69,7 @@ However, GitLab sometimes changes the GraphQL API in a way that is not backward-
can include removing or renaming fields, arguments, or other parts of the schema.
When creating a breaking change, GitLab follows a [deprecation and removal process](#deprecation-and-removal-process).
-Learn more about [breaking changes](../../development/contributing/#breaking-changes).
+Learn more about [breaking changes](../../development/deprecation_guidelines/index.md).
Fields behind a feature flag and disabled by default do not follow the deprecation and removal process, and can be removed at any time without notice.
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index fbf6bc116f4..ab5b5a92203 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -91,7 +91,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
List of the instance's CI/CD variables.
-Returns [`CiVariableConnection`](#civariableconnection).
+Returns [`CiInstanceVariableConnection`](#ciinstancevariableconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
@@ -387,7 +387,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="queryrunnersstatus"></a>`status` | [`CiRunnerStatus`](#cirunnerstatus) | Filter runners by status. |
| <a id="queryrunnerstaglist"></a>`tagList` | [`[String!]`](#string) | Filter by tags associated with the runner (comma-separated or array). |
| <a id="queryrunnerstype"></a>`type` | [`CiRunnerType`](#cirunnertype) | Filter runners by type. |
-| <a id="queryrunnersupgradestatus"></a>`upgradeStatus` | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | Filter by upgrade status. |
+| <a id="queryrunnersupgradestatus"></a>`upgradeStatus` | [`CiRunnerUpgradeStatus`](#cirunnerupgradestatus) | Filter by upgrade status. |
### `Query.snippets`
@@ -640,6 +640,8 @@ Input type: `AdminSidekiqQueuesDeleteJobsInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationadminsidekiqqueuesdeletejobsartifactsize"></a>`artifactSize` | [`String`](#string) | Delete jobs matching artifact_size 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. |
| <a id="mutationadminsidekiqqueuesdeletejobsclientid"></a>`clientId` | [`String`](#string) | Delete jobs matching client_id in the context metadata. |
| <a id="mutationadminsidekiqqueuesdeletejobsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
@@ -951,6 +953,30 @@ Input type: `BulkEnableDevopsAdoptionNamespacesInput`
| <a id="mutationbulkenabledevopsadoptionnamespacesenablednamespaces"></a>`enabledNamespaces` | [`[DevopsAdoptionEnabledNamespace!]`](#devopsadoptionenablednamespace) | Enabled namespaces after mutation. |
| <a id="mutationbulkenabledevopsadoptionnamespaceserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.bulkRunnerDelete`
+
+WARNING:
+**Introduced** in 15.3.
+This feature is in Alpha. It can be changed or removed at any time.
+
+Input type: `BulkRunnerDeleteInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationbulkrunnerdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationbulkrunnerdeleteids"></a>`ids` | [`[CiRunnerID!]`](#cirunnerid) | IDs of the runners to delete. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationbulkrunnerdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationbulkrunnerdeletedeletedcount"></a>`deletedCount` | [`Int`](#int) | Number of records effectively deleted. Only present if operation was performed synchronously. |
+| <a id="mutationbulkrunnerdeletedeletedids"></a>`deletedIds` | [`[CiRunnerID!]`](#cirunnerid) | IDs of records effectively deleted. Only present if operation was performed synchronously. |
+| <a id="mutationbulkrunnerdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.ciCdSettingsUpdate`
WARNING:
@@ -1414,7 +1440,8 @@ Input type: `CreateDiffNoteInput`
| ---- | ---- | ----------- |
| <a id="mutationcreatediffnotebody"></a>`body` | [`String!`](#string) | Content of the note. |
| <a id="mutationcreatediffnoteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreatediffnoteconfidential"></a>`confidential` | [`Boolean`](#boolean) | Confidentiality flag of a note. Default is false. |
+| <a id="mutationcreatediffnoteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** This was renamed. Please use `internal`. Deprecated in 15.3. |
+| <a id="mutationcreatediffnoteinternal"></a>`internal` | [`Boolean`](#boolean) | Internal flag for a note. Default is false. |
| <a id="mutationcreatediffnotenoteableid"></a>`noteableId` | [`NoteableID!`](#noteableid) | Global ID of the resource to add a note to. |
| <a id="mutationcreatediffnoteposition"></a>`position` | [`DiffPositionInput!`](#diffpositioninput) | Position of this note on a diff. |
@@ -1466,7 +1493,8 @@ Input type: `CreateImageDiffNoteInput`
| ---- | ---- | ----------- |
| <a id="mutationcreateimagediffnotebody"></a>`body` | [`String!`](#string) | Content of the note. |
| <a id="mutationcreateimagediffnoteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreateimagediffnoteconfidential"></a>`confidential` | [`Boolean`](#boolean) | Confidentiality flag of a note. Default is false. |
+| <a id="mutationcreateimagediffnoteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** This was renamed. Please use `internal`. Deprecated in 15.3. |
+| <a id="mutationcreateimagediffnoteinternal"></a>`internal` | [`Boolean`](#boolean) | Internal flag for a note. Default is false. |
| <a id="mutationcreateimagediffnotenoteableid"></a>`noteableId` | [`NoteableID!`](#noteableid) | Global ID of the resource to add a note to. |
| <a id="mutationcreateimagediffnoteposition"></a>`position` | [`DiffImagePositionInput!`](#diffimagepositioninput) | Position of this note on a diff. |
@@ -1523,7 +1551,7 @@ Input type: `CreateIssueInput`
WARNING:
**Deprecated** in 14.0.
-Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
+Use iterationCreate.
Input type: `CreateIterationInput`
@@ -1535,7 +1563,7 @@ Input type: `CreateIterationInput`
| <a id="mutationcreateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
| <a id="mutationcreateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationcreateiterationgrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
-| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
+| <a id="mutationcreateiterationiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iteration cadence to be assigned to the new iteration. |
| <a id="mutationcreateiterationprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
| <a id="mutationcreateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
| <a id="mutationcreateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
@@ -1563,8 +1591,9 @@ Input type: `CreateNoteInput`
| ---- | ---- | ----------- |
| <a id="mutationcreatenotebody"></a>`body` | [`String!`](#string) | Content of the note. |
| <a id="mutationcreatenoteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcreatenoteconfidential"></a>`confidential` | [`Boolean`](#boolean) | Confidentiality flag of a note. Default is false. |
+| <a id="mutationcreatenoteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated:** This was renamed. Please use `internal`. Deprecated in 15.3. |
| <a id="mutationcreatenotediscussionid"></a>`discussionId` | [`DiscussionID`](#discussionid) | Global ID of the discussion this note is in reply to. |
+| <a id="mutationcreatenoteinternal"></a>`internal` | [`Boolean`](#boolean) | Internal flag for a note. Default is false. |
| <a id="mutationcreatenotemergerequestdiffheadsha"></a>`mergeRequestDiffHeadSha` | [`String`](#string) | SHA of the head commit which is used to ensure that the merge request has not been updated since the request was sent. |
| <a id="mutationcreatenotenoteableid"></a>`noteableId` | [`NoteableID!`](#noteableid) | Global ID of the resource to add a note to. |
@@ -3285,7 +3314,7 @@ Input type: `IterationCadenceCreateInput`
| <a id="mutationiterationcadencecreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group where the iteration cadence is created. |
| <a id="mutationiterationcadencecreateiterationsinadvance"></a>`iterationsInAdvance` | [`Int`](#int) | Upcoming iterations to be created when iteration cadence is set to automatic. |
| <a id="mutationiterationcadencecreaterollover"></a>`rollOver` | [`Boolean`](#boolean) | Whether the iteration cadence should roll over issues to the next iteration or not. |
-| <a id="mutationiterationcadencecreatestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the iteration cadence start date. |
+| <a id="mutationiterationcadencecreatestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the automation start date. |
| <a id="mutationiterationcadencecreatetitle"></a>`title` | [`String`](#string) | Title of the iteration cadence. |
#### Fields
@@ -3331,7 +3360,7 @@ Input type: `IterationCadenceUpdateInput`
| <a id="mutationiterationcadenceupdateid"></a>`id` | [`IterationsCadenceID!`](#iterationscadenceid) | Global ID of the iteration cadence. |
| <a id="mutationiterationcadenceupdateiterationsinadvance"></a>`iterationsInAdvance` | [`Int`](#int) | Upcoming iterations to be created when iteration cadence is set to automatic. |
| <a id="mutationiterationcadenceupdaterollover"></a>`rollOver` | [`Boolean`](#boolean) | Whether the iteration cadence should roll over issues to the next iteration or not. |
-| <a id="mutationiterationcadenceupdatestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the iteration cadence start date. |
+| <a id="mutationiterationcadenceupdatestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the automation start date. |
| <a id="mutationiterationcadenceupdatetitle"></a>`title` | [`String`](#string) | Title of the iteration cadence. |
#### Fields
@@ -3344,10 +3373,6 @@ Input type: `IterationCadenceUpdateInput`
### `Mutation.iterationCreate`
-WARNING:
-**Deprecated** in 14.10.
-Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
-
Input type: `iterationCreateInput`
#### Arguments
@@ -3358,7 +3383,7 @@ Input type: `iterationCreateInput`
| <a id="mutationiterationcreatedescription"></a>`description` | [`String`](#string) | Description of the iteration. |
| <a id="mutationiterationcreateduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationiterationcreategrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
-| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` **{warning-solid}** | [`IterationsCadenceID`](#iterationscadenceid) | **Deprecated:** `iterationCadenceId` is deprecated and will be removed in the future. This argument is ignored, because you can't create an iteration in a specific cadence. In the future only automatic iteration cadences will be allowed. Deprecated in 14.10. |
+| <a id="mutationiterationcreateiterationscadenceid"></a>`iterationsCadenceId` | [`IterationsCadenceID`](#iterationscadenceid) | Global ID of the iteration cadence to be assigned to the new iteration. |
| <a id="mutationiterationcreateprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
| <a id="mutationiterationcreatestartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
| <a id="mutationiterationcreatetitle"></a>`title` | [`String`](#string) | Title of the iteration. |
@@ -3373,10 +3398,6 @@ Input type: `iterationCreateInput`
### `Mutation.iterationDelete`
-WARNING:
-**Deprecated** in 14.10.
-Manual iteration management is deprecated. Only automatic iteration cadences will be supported in the future.
-
Input type: `IterationDeleteInput`
#### Arguments
@@ -3484,6 +3505,7 @@ Input type: `JobRetryInput`
| ---- | ---- | ----------- |
| <a id="mutationjobretryclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationjobretryid"></a>`id` | [`CiBuildID!`](#cibuildid) | ID of the job to mutate. |
+| <a id="mutationjobretryvariables"></a>`variables` | [`[CiVariableInput!]`](#civariableinput) | Variables to use when retrying a manual job. |
#### Fields
@@ -3608,48 +3630,6 @@ Input type: `MergeRequestCreateInput`
| <a id="mutationmergerequestcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationmergerequestcreatemergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-### `Mutation.mergeRequestRemoveAttentionRequest`
-
-Input type: `MergeRequestRemoveAttentionRequestInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationmergerequestremoveattentionrequestclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestremoveattentionrequestiid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
-| <a id="mutationmergerequestremoveattentionrequestprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
-| <a id="mutationmergerequestremoveattentionrequestuserid"></a>`userId` | [`UserID!`](#userid) | User ID of the user for attention request removal. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationmergerequestremoveattentionrequestclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestremoveattentionrequesterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationmergerequestremoveattentionrequestmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-
-### `Mutation.mergeRequestRequestAttention`
-
-Input type: `MergeRequestRequestAttentionInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationmergerequestrequestattentionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestrequestattentioniid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
-| <a id="mutationmergerequestrequestattentionprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
-| <a id="mutationmergerequestrequestattentionuserid"></a>`userId` | [`UserID!`](#userid) | User ID of the user to request attention. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationmergerequestrequestattentionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestrequestattentionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationmergerequestrequestattentionmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-
### `Mutation.mergeRequestReviewerRereview`
Input type: `MergeRequestReviewerRereviewInput`
@@ -3778,47 +3758,48 @@ Input type: `MergeRequestSetMilestoneInput`
| <a id="mutationmergerequestsetmilestoneerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationmergerequestsetmilestonemergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-### `Mutation.mergeRequestSetSubscription`
+### `Mutation.mergeRequestSetReviewers`
-Input type: `MergeRequestSetSubscriptionInput`
+Input type: `MergeRequestSetReviewersInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequestsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestsetsubscriptioniid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
-| <a id="mutationmergerequestsetsubscriptionprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
-| <a id="mutationmergerequestsetsubscriptionsubscribedstate"></a>`subscribedState` | [`Boolean!`](#boolean) | Desired state of the subscription. |
+| <a id="mutationmergerequestsetreviewersclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequestsetreviewersiid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
+| <a id="mutationmergerequestsetreviewersoperationmode"></a>`operationMode` | [`MutationOperationMode`](#mutationoperationmode) | Operation to perform. Defaults to REPLACE. |
+| <a id="mutationmergerequestsetreviewersprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
+| <a id="mutationmergerequestsetreviewersreviewerusernames"></a>`reviewerUsernames` | [`[String!]!`](#string) | Usernames of reviewers to assign. Replaces existing reviewers by default. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequestsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequestsetsubscriptionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationmergerequestsetsubscriptionmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
+| <a id="mutationmergerequestsetreviewersclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequestsetreviewerserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationmergerequestsetreviewersmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
-### `Mutation.mergeRequestToggleAttentionRequested`
+### `Mutation.mergeRequestSetSubscription`
-Input type: `MergeRequestToggleAttentionRequestedInput`
+Input type: `MergeRequestSetSubscriptionInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequesttoggleattentionrequestedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequesttoggleattentionrequestediid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
-| <a id="mutationmergerequesttoggleattentionrequestedprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
-| <a id="mutationmergerequesttoggleattentionrequesteduserid"></a>`userId` | [`UserID!`](#userid) | User ID for the user to toggle attention requested. |
+| <a id="mutationmergerequestsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequestsetsubscriptioniid"></a>`iid` | [`String!`](#string) | IID of the merge request to mutate. |
+| <a id="mutationmergerequestsetsubscriptionprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. |
+| <a id="mutationmergerequestsetsubscriptionsubscribedstate"></a>`subscribedState` | [`Boolean!`](#boolean) | Desired state of the subscription. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmergerequesttoggleattentionrequestedclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationmergerequesttoggleattentionrequestederrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationmergerequesttoggleattentionrequestedmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
+| <a id="mutationmergerequestsetsubscriptionclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationmergerequestsetsubscriptionerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationmergerequestsetsubscriptionmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request after mutation. |
### `Mutation.mergeRequestUpdate`
@@ -4815,6 +4796,28 @@ Input type: `TimelineEventUpdateInput`
| <a id="mutationtimelineeventupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationtimelineeventupdatetimelineevent"></a>`timelineEvent` | [`TimelineEventType`](#timelineeventtype) | Timeline event. |
+### `Mutation.timelogCreate`
+
+Input type: `TimelogCreateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelogcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelogcreateissuableid"></a>`issuableId` | [`IssuableID!`](#issuableid) | Global ID of the issuable (Issue, WorkItem or MergeRequest). |
+| <a id="mutationtimelogcreatespentat"></a>`spentAt` | [`Date!`](#date) | When the time was spent. |
+| <a id="mutationtimelogcreatesummary"></a>`summary` | [`String!`](#string) | Summary of time spent. |
+| <a id="mutationtimelogcreatetimespent"></a>`timeSpent` | [`String!`](#string) | Amount of time spent. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationtimelogcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationtimelogcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationtimelogcreatetimelog"></a>`timelog` | [`Timelog`](#timelog) | Timelog. |
+
### `Mutation.timelogDelete`
Input type: `TimelogDeleteInput`
@@ -4832,7 +4835,7 @@ Input type: `TimelogDeleteInput`
| ---- | ---- | ----------- |
| <a id="mutationtimelogdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationtimelogdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationtimelogdeletetimelog"></a>`timelog` | [`Timelog`](#timelog) | Deleted timelog. |
+| <a id="mutationtimelogdeletetimelog"></a>`timelog` | [`Timelog`](#timelog) | Timelog. |
### `Mutation.todoCreate`
@@ -5233,11 +5236,11 @@ Input type: `UpdateIterationInput`
| ---- | ---- | ----------- |
| <a id="mutationupdateiterationclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationupdateiterationdescription"></a>`description` | [`String`](#string) | Description of the iteration. |
-| <a id="mutationupdateiterationduedate"></a>`dueDate` **{warning-solid}** | [`String`](#string) | **Deprecated:** Manual iteration updates are deprecated, only `description` updates will be allowed in the future. Deprecated in 14.10. |
+| <a id="mutationupdateiterationduedate"></a>`dueDate` | [`String`](#string) | End date of the iteration. |
| <a id="mutationupdateiterationgrouppath"></a>`groupPath` | [`ID!`](#id) | Group of the iteration. |
| <a id="mutationupdateiterationid"></a>`id` | [`ID!`](#id) | Global ID of the iteration. |
-| <a id="mutationupdateiterationstartdate"></a>`startDate` **{warning-solid}** | [`String`](#string) | **Deprecated:** Manual iteration updates are deprecated, only `description` updates will be allowed in the future. Deprecated in 14.10. |
-| <a id="mutationupdateiterationtitle"></a>`title` **{warning-solid}** | [`String`](#string) | **Deprecated:** Manual iteration updates are deprecated, only `description` updates will be allowed in the future. Deprecated in 14.10. |
+| <a id="mutationupdateiterationstartdate"></a>`startDate` | [`String`](#string) | Start date of the iteration. |
+| <a id="mutationupdateiterationtitle"></a>`title` | [`String`](#string) | Title of the iteration. |
#### Fields
@@ -5363,6 +5366,30 @@ Input type: `UpdateSnippetInput`
| <a id="mutationupdatesnippeterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationupdatesnippetsnippet"></a>`snippet` | [`Snippet`](#snippet) | Snippet after mutation. |
+### `Mutation.uploadDelete`
+
+Deletes an upload.
+
+Input type: `UploadDeleteInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationuploaddeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationuploaddeletefilename"></a>`filename` | [`String!`](#string) | Upload filename. |
+| <a id="mutationuploaddeletegrouppath"></a>`groupPath` | [`ID`](#id) | Full path of the group with which the resource is associated. |
+| <a id="mutationuploaddeleteprojectpath"></a>`projectPath` | [`ID`](#id) | Full path of the project with which the resource is associated. |
+| <a id="mutationuploaddeletesecret"></a>`secret` | [`String!`](#string) | Secret part of upload path. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationuploaddeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationuploaddeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+| <a id="mutationuploaddeleteupload"></a>`upload` | [`FileUpload`](#fileupload) | Deleted upload. |
+
### `Mutation.userCalloutCreate`
Input type: `UserCalloutCreateInput`
@@ -5587,6 +5614,7 @@ Input type: `WorkItemCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationworkitemcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemcreateconfidential"></a>`confidential` | [`Boolean`](#boolean) | Sets the work item confidentiality. |
| <a id="mutationworkitemcreatedescription"></a>`description` | [`String`](#string) | Description of the work item. |
| <a id="mutationworkitemcreatehierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyCreateInput`](#workitemwidgethierarchycreateinput) | Input for hierarchy widget. |
| <a id="mutationworkitemcreateprojectpath"></a>`projectPath` | [`ID!`](#id) | Full path of the project the work item is associated with. |
@@ -5694,10 +5722,13 @@ Input type: `WorkItemUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="mutationworkitemupdateassigneeswidget"></a>`assigneesWidget` | [`WorkItemWidgetAssigneesInput`](#workitemwidgetassigneesinput) | Input for assignees widget. |
| <a id="mutationworkitemupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationworkitemupdateconfidential"></a>`confidential` | [`Boolean`](#boolean) | Sets the work item confidentiality. |
| <a id="mutationworkitemupdatedescriptionwidget"></a>`descriptionWidget` | [`WorkItemWidgetDescriptionInput`](#workitemwidgetdescriptioninput) | Input for description widget. |
| <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="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="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
| <a id="mutationworkitemupdateweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
@@ -6170,6 +6201,52 @@ The edge type for [`CiGroup`](#cigroup).
| <a id="cigroupedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="cigroupedgenode"></a>`node` | [`CiGroup`](#cigroup) | The item at the end of the edge. |
+#### `CiGroupVariableConnection`
+
+The connection type for [`CiGroupVariable`](#cigroupvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cigroupvariableconnectionedges"></a>`edges` | [`[CiGroupVariableEdge]`](#cigroupvariableedge) | A list of edges. |
+| <a id="cigroupvariableconnectionnodes"></a>`nodes` | [`[CiGroupVariable]`](#cigroupvariable) | A list of nodes. |
+| <a id="cigroupvariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CiGroupVariableEdge`
+
+The edge type for [`CiGroupVariable`](#cigroupvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cigroupvariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="cigroupvariableedgenode"></a>`node` | [`CiGroupVariable`](#cigroupvariable) | The item at the end of the edge. |
+
+#### `CiInstanceVariableConnection`
+
+The connection type for [`CiInstanceVariable`](#ciinstancevariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciinstancevariableconnectionedges"></a>`edges` | [`[CiInstanceVariableEdge]`](#ciinstancevariableedge) | A list of edges. |
+| <a id="ciinstancevariableconnectionnodes"></a>`nodes` | [`[CiInstanceVariable]`](#ciinstancevariable) | A list of nodes. |
+| <a id="ciinstancevariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CiInstanceVariableEdge`
+
+The edge type for [`CiInstanceVariable`](#ciinstancevariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciinstancevariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="ciinstancevariableedgenode"></a>`node` | [`CiInstanceVariable`](#ciinstancevariable) | The item at the end of the edge. |
+
#### `CiJobArtifactConnection`
The connection type for [`CiJobArtifact`](#cijobartifact).
@@ -6230,6 +6307,29 @@ The edge type for [`CiJob`](#cijob).
| <a id="cijobedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="cijobedgenode"></a>`node` | [`CiJob`](#cijob) | The item at the end of the edge. |
+#### `CiManualVariableConnection`
+
+The connection type for [`CiManualVariable`](#cimanualvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cimanualvariableconnectionedges"></a>`edges` | [`[CiManualVariableEdge]`](#cimanualvariableedge) | A list of edges. |
+| <a id="cimanualvariableconnectionnodes"></a>`nodes` | [`[CiManualVariable]`](#cimanualvariable) | A list of nodes. |
+| <a id="cimanualvariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CiManualVariableEdge`
+
+The edge type for [`CiManualVariable`](#cimanualvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cimanualvariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="cimanualvariableedgenode"></a>`node` | [`CiManualVariable`](#cimanualvariable) | The item at the end of the edge. |
+
#### `CiMinutesNamespaceMonthlyUsageConnection`
The connection type for [`CiMinutesNamespaceMonthlyUsage`](#ciminutesnamespacemonthlyusage).
@@ -6276,6 +6376,29 @@ The edge type for [`CiMinutesProjectMonthlyUsage`](#ciminutesprojectmonthlyusage
| <a id="ciminutesprojectmonthlyusageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="ciminutesprojectmonthlyusageedgenode"></a>`node` | [`CiMinutesProjectMonthlyUsage`](#ciminutesprojectmonthlyusage) | The item at the end of the edge. |
+#### `CiProjectVariableConnection`
+
+The connection type for [`CiProjectVariable`](#ciprojectvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciprojectvariableconnectionedges"></a>`edges` | [`[CiProjectVariableEdge]`](#ciprojectvariableedge) | A list of edges. |
+| <a id="ciprojectvariableconnectionnodes"></a>`nodes` | [`[CiProjectVariable]`](#ciprojectvariable) | A list of nodes. |
+| <a id="ciprojectvariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CiProjectVariableEdge`
+
+The edge type for [`CiProjectVariable`](#ciprojectvariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciprojectvariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="ciprojectvariableedgenode"></a>`node` | [`CiProjectVariable`](#ciprojectvariable) | The item at the end of the edge. |
+
#### `CiRunnerConnection`
The connection type for [`CiRunner`](#cirunner).
@@ -6302,51 +6425,51 @@ The edge type for [`CiRunner`](#cirunner).
| <a id="cirunneredgenode"></a>`node` | [`CiRunner`](#cirunner) | The item at the end of the edge. |
| <a id="cirunneredgeweburl"></a>`webUrl` | [`String`](#string) | Web URL of the runner. The value depends on where you put this field in the query. You can use it for projects or groups. |
-#### `CiStageConnection`
+#### `CiSecureFileRegistryConnection`
-The connection type for [`CiStage`](#cistage).
+The connection type for [`CiSecureFileRegistry`](#cisecurefileregistry).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="cistageconnectionedges"></a>`edges` | [`[CiStageEdge]`](#cistageedge) | A list of edges. |
-| <a id="cistageconnectionnodes"></a>`nodes` | [`[CiStage]`](#cistage) | A list of nodes. |
-| <a id="cistageconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+| <a id="cisecurefileregistryconnectionedges"></a>`edges` | [`[CiSecureFileRegistryEdge]`](#cisecurefileregistryedge) | A list of edges. |
+| <a id="cisecurefileregistryconnectionnodes"></a>`nodes` | [`[CiSecureFileRegistry]`](#cisecurefileregistry) | A list of nodes. |
+| <a id="cisecurefileregistryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-#### `CiStageEdge`
+#### `CiSecureFileRegistryEdge`
-The edge type for [`CiStage`](#cistage).
+The edge type for [`CiSecureFileRegistry`](#cisecurefileregistry).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="cistageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| <a id="cistageedgenode"></a>`node` | [`CiStage`](#cistage) | The item at the end of the edge. |
+| <a id="cisecurefileregistryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="cisecurefileregistryedgenode"></a>`node` | [`CiSecureFileRegistry`](#cisecurefileregistry) | The item at the end of the edge. |
-#### `CiVariableConnection`
+#### `CiStageConnection`
-The connection type for [`CiVariable`](#civariable).
+The connection type for [`CiStage`](#cistage).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="civariableconnectionedges"></a>`edges` | [`[CiVariableEdge]`](#civariableedge) | A list of edges. |
-| <a id="civariableconnectionnodes"></a>`nodes` | [`[CiVariable]`](#civariable) | A list of nodes. |
-| <a id="civariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+| <a id="cistageconnectionedges"></a>`edges` | [`[CiStageEdge]`](#cistageedge) | A list of edges. |
+| <a id="cistageconnectionnodes"></a>`nodes` | [`[CiStage]`](#cistage) | A list of nodes. |
+| <a id="cistageconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
-#### `CiVariableEdge`
+#### `CiStageEdge`
-The edge type for [`CiVariable`](#civariable).
+The edge type for [`CiStage`](#cistage).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="civariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
-| <a id="civariableedgenode"></a>`node` | [`CiVariable`](#civariable) | The item at the end of the edge. |
+| <a id="cistageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="cistageedgenode"></a>`node` | [`CiStage`](#cistage) | The item at the end of the edge. |
#### `ClusterAgentActivityEventConnection`
@@ -8784,6 +8907,29 @@ The edge type for [`TestSuiteSummary`](#testsuitesummary).
| <a id="testsuitesummaryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="testsuitesummaryedgenode"></a>`node` | [`TestSuiteSummary`](#testsuitesummary) | The item at the end of the edge. |
+#### `TimeTrackingTimelogCategoryConnection`
+
+The connection type for [`TimeTrackingTimelogCategory`](#timetrackingtimelogcategory).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="timetrackingtimelogcategoryconnectionedges"></a>`edges` | [`[TimeTrackingTimelogCategoryEdge]`](#timetrackingtimelogcategoryedge) | A list of edges. |
+| <a id="timetrackingtimelogcategoryconnectionnodes"></a>`nodes` | [`[TimeTrackingTimelogCategory]`](#timetrackingtimelogcategory) | A list of nodes. |
+| <a id="timetrackingtimelogcategoryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `TimeTrackingTimelogCategoryEdge`
+
+The edge type for [`TimeTrackingTimelogCategory`](#timetrackingtimelogcategory).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="timetrackingtimelogcategoryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="timetrackingtimelogcategoryedgenode"></a>`node` | [`TimeTrackingTimelogCategory`](#timetrackingtimelogcategory) | The item at the end of the edge. |
+
#### `TimelineEventTypeConnection`
The connection type for [`TimelineEventType`](#timelineeventtype).
@@ -9916,6 +10062,40 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cigroupname"></a>`name` | [`String`](#string) | Name of the job group. |
| <a id="cigroupsize"></a>`size` | [`Int`](#int) | Size of the group. |
+### `CiGroupVariable`
+
+CI/CD variables for a group.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cigroupvariableenvironmentscope"></a>`environmentScope` | [`String`](#string) | Scope defining the environments that can use the variable. |
+| <a id="cigroupvariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
+| <a id="cigroupvariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
+| <a id="cigroupvariablemasked"></a>`masked` | [`Boolean`](#boolean) | Indicates whether the variable is masked. |
+| <a id="cigroupvariableprotected"></a>`protected` | [`Boolean`](#boolean) | Indicates whether the variable is protected. |
+| <a id="cigroupvariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
+| <a id="cigroupvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="cigroupvariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
+
+### `CiInstanceVariable`
+
+CI/CD variables for a GitLab instance.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciinstancevariableenvironmentscope"></a>`environmentScope` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.3. No longer used, only available for GroupVariableType and ProjectVariableType. |
+| <a id="ciinstancevariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
+| <a id="ciinstancevariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
+| <a id="ciinstancevariablemasked"></a>`masked` | [`Boolean`](#boolean) | Indicates whether the variable is masked. |
+| <a id="ciinstancevariableprotected"></a>`protected` | [`Boolean`](#boolean) | Indicates whether the variable is protected. |
+| <a id="ciinstancevariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
+| <a id="ciinstancevariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="ciinstancevariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
+
### `CiJob`
#### Fields
@@ -9937,7 +10117,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cijobid"></a>`id` | [`JobID`](#jobid) | ID of the job. |
| <a id="cijobkind"></a>`kind` | [`CiJobKind!`](#cijobkind) | Indicates the type of job. |
| <a id="cijobmanualjob"></a>`manualJob` | [`Boolean`](#boolean) | Whether the job has a manual action. |
-| <a id="cijobmanualvariables"></a>`manualVariables` | [`CiVariableConnection`](#civariableconnection) | Variables added to a manual job when the job is triggered. (see [Connections](#connections)) |
+| <a id="cijobmanualvariables"></a>`manualVariables` | [`CiManualVariableConnection`](#cimanualvariableconnection) | Variables added to a manual job when the job is triggered. (see [Connections](#connections)) |
| <a id="cijobname"></a>`name` | [`String`](#string) | Name of the job. |
| <a id="cijobneeds"></a>`needs` | [`CiBuildNeedConnection`](#cibuildneedconnection) | References to builds that must complete before the jobs run. (see [Connections](#connections)) |
| <a id="cijobpipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline the job belongs to. |
@@ -9978,6 +10158,21 @@ Represents the total number of issues and their weights for a particular day.
| ---- | ---- | ----------- |
| <a id="cijobtokenscopetypeprojects"></a>`projects` | [`ProjectConnection!`](#projectconnection) | Allow list of projects that can be accessed by CI Job tokens created by this project. (see [Connections](#connections)) |
+### `CiManualVariable`
+
+CI/CD variables given to a manual job.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cimanualvariableenvironmentscope"></a>`environmentScope` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.3. No longer used, only available for GroupVariableType and ProjectVariableType. |
+| <a id="cimanualvariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
+| <a id="cimanualvariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
+| <a id="cimanualvariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
+| <a id="cimanualvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="cimanualvariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
+
### `CiMinutesNamespaceMonthlyUsage`
#### Fields
@@ -10000,6 +10195,23 @@ Represents the total number of issues and their weights for a particular day.
| <a id="ciminutesprojectmonthlyusagename"></a>`name` | [`String`](#string) | Name of the project. |
| <a id="ciminutesprojectmonthlyusagesharedrunnersduration"></a>`sharedRunnersDuration` | [`Int`](#int) | Total duration (in seconds) of shared runners use by the project for the month. |
+### `CiProjectVariable`
+
+CI/CD variables for a project.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="ciprojectvariableenvironmentscope"></a>`environmentScope` | [`String`](#string) | Scope defining the environments that can use the variable. |
+| <a id="ciprojectvariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
+| <a id="ciprojectvariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
+| <a id="ciprojectvariablemasked"></a>`masked` | [`Boolean`](#boolean) | Indicates whether the variable is masked. |
+| <a id="ciprojectvariableprotected"></a>`protected` | [`Boolean`](#boolean) | Indicates whether the variable is protected. |
+| <a id="ciprojectvariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
+| <a id="ciprojectvariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="ciprojectvariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
+
### `CiRunner`
#### Fields
@@ -10036,7 +10248,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
| <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
| <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. |
-| <a id="cirunnerupgradestatus"></a>`upgradeStatus` **{warning-solid}** | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | **Introduced** in 14.10. This feature is in Alpha. It can be changed or removed at any time. |
+| <a id="cirunnerupgradestatus"></a>`upgradeStatus` **{warning-solid}** | [`CiRunnerUpgradeStatus`](#cirunnerupgradestatus) | **Introduced** in 14.10. This feature is in Alpha. It can be changed or removed at any time. Availability of upgrades for the runner. |
| <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
| <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
@@ -10070,6 +10282,25 @@ Returns [`CiRunnerStatus!`](#cirunnerstatus).
| ---- | ---- | ----------- |
| <a id="cirunnerstatuslegacymode"></a>`legacyMode` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.0. Will be removed in 17.0. In GitLab 16.0 and later, the field will act as if `legacyMode` is null. |
+### `CiSecureFileRegistry`
+
+Represents the Geo replication and verification state of a ci_secure_file.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cisecurefileregistrycisecurefileid"></a>`ciSecureFileId` | [`ID!`](#id) | ID of the Ci Secure File. |
+| <a id="cisecurefileregistrycreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp when the CiSecureFileRegistry was created. |
+| <a id="cisecurefileregistryid"></a>`id` | [`ID!`](#id) | ID of the CiSecureFileRegistry. |
+| <a id="cisecurefileregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the CiSecureFileRegistry. |
+| <a id="cisecurefileregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the CiSecureFileRegistry. |
+| <a id="cisecurefileregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the CiSecureFileRegistry is resynced. |
+| <a id="cisecurefileregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the CiSecureFileRegistry. |
+| <a id="cisecurefileregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the CiSecureFileRegistry. |
+| <a id="cisecurefileregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the CiSecureFileRegistry is reverified. |
+| <a id="cisecurefileregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the CiSecureFileRegistry. |
+
### `CiStage`
#### Fields
@@ -10094,21 +10325,6 @@ GitLab CI/CD configuration template.
| <a id="citemplatecontent"></a>`content` | [`String!`](#string) | Contents of the CI template. |
| <a id="citemplatename"></a>`name` | [`String!`](#string) | Name of the CI template. |
-### `CiVariable`
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="civariableenvironmentscope"></a>`environmentScope` | [`String`](#string) | Scope defining the environments in which the variable can be used. |
-| <a id="civariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
-| <a id="civariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
-| <a id="civariablemasked"></a>`masked` | [`Boolean`](#boolean) | Indicates whether the variable is masked. |
-| <a id="civariableprotected"></a>`protected` | [`Boolean`](#boolean) | Indicates whether the variable is protected. |
-| <a id="civariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
-| <a id="civariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
-| <a id="civariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
-
### `ClusterAgent`
#### Fields
@@ -10342,6 +10558,18 @@ Connection details for an Agent.
| <a id="connectedagentconnectionid"></a>`connectionId` | [`BigInt`](#bigint) | ID of the connection. |
| <a id="connectedagentmetadata"></a>`metadata` | [`AgentMetadata`](#agentmetadata) | Information about the Agent. |
+### `ContactStateCounts`
+
+Represents the total number of contacts for the represented states.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="contactstatecountsactive"></a>`active` | [`Int`](#int) | Number of contacts with state `ACTIVE`. |
+| <a id="contactstatecountsall"></a>`all` | [`Int`](#int) | Number of contacts with state `ALL`. |
+| <a id="contactstatecountsinactive"></a>`inactive` | [`Int`](#int) | Number of contacts with state `INACTIVE`. |
+
### `ContainerExpirationPolicy`
A tag expiration policy designed to keep only the images that matter most.
@@ -11123,7 +11351,7 @@ Returns [`[DoraMetric!]`](#dorametric).
| ---- | ---- | ----------- |
| <a id="dorametricsenddate"></a>`endDate` | [`Date`](#date) | Date range to end at. Default is the current date. |
| <a id="dorametricsenvironmenttier"></a>`environmentTier` | [`DeploymentTier`](#deploymenttier) | Deployment tier of the environments to return. Deprecated, please update to `environment_tiers` param. |
-| <a id="dorametricsenvironmenttiers"></a>`environmentTiers` | [`[DeploymentTier!]`](#deploymenttier) | Deployment tiers of the environments to return. Defaults to [`PRODUCTION`]. |
+| <a id="dorametricsenvironmenttiers"></a>`environmentTiers` | [`[DeploymentTier!]`](#deploymenttier) | Deployment tiers of the environments to return. Defaults to `[PRODUCTION]`. |
| <a id="dorametricsinterval"></a>`interval` | [`DoraMetricBucketingInterval`](#dorametricbucketinginterval) | How the metric should be aggregrated. Defaults to `DAILY`. In the case of `ALL`, the `date` field in the response will be `null`. |
| <a id="dorametricsmetric"></a>`metric` | [`DoraMetricType!`](#dorametrictype) | Type of metric to return. |
| <a id="dorametricsstartdate"></a>`startDate` | [`Date`](#date) | Date range to start from. Default is 3 months ago. |
@@ -11567,7 +11795,7 @@ Represents epic board list metadata.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epiclistmetadataepicscount"></a>`epicsCount` | [`Int`](#int) | Count of epics in the list. |
-| <a id="epiclistmetadatatotalweight"></a>`totalWeight` | [`Int`](#int) | Total weight of all issues in the list. Available only when feature flag `epic_board_total_weight` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
+| <a id="epiclistmetadatatotalweight"></a>`totalWeight` **{warning-solid}** | [`Int`](#int) | **Introduced** in 14.7. This feature is in Alpha. It can be changed or removed at any time. Total weight of all issues in the list. |
### `EpicPermissions`
@@ -11637,7 +11865,7 @@ Represents an external resource to send audit events to.
| ---- | ---- | ----------- |
| <a id="externalauditeventdestinationdestinationurl"></a>`destinationUrl` | [`String!`](#string) | External destination to send audit events to. |
| <a id="externalauditeventdestinationgroup"></a>`group` | [`Group!`](#group) | Group the destination belongs to. |
-| <a id="externalauditeventdestinationheaders"></a>`headers` | [`AuditEventStreamingHeaderConnection!`](#auditeventstreamingheaderconnection) | List of additional HTTP headers sent with each event. Available only when feature flag `streaming_audit_event_headers` is enabled. This flag is enabled by default. (see [Connections](#connections)) |
+| <a id="externalauditeventdestinationheaders"></a>`headers` | [`AuditEventStreamingHeaderConnection!`](#auditeventstreamingheaderconnection) | List of additional HTTP headers sent with each event. (see [Connections](#connections)) |
| <a id="externalauditeventdestinationid"></a>`id` | [`ID!`](#id) | ID of the destination. |
| <a id="externalauditeventdestinationverificationtoken"></a>`verificationToken` | [`String!`](#string) | Verification token to validate source of event. |
@@ -11657,6 +11885,16 @@ Represents an external issue.
| <a id="externalissueupdatedat"></a>`updatedAt` | [`Time`](#time) | Timestamp of when the issue was updated. |
| <a id="externalissueweburl"></a>`webUrl` | [`String`](#string) | URL to the issue in the external tracker. |
+### `FileUpload`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="fileuploadid"></a>`id` | [`UploadID!`](#uploadid) | Global ID of the upload. |
+| <a id="fileuploadpath"></a>`path` | [`String!`](#string) | Path of the upload. |
+| <a id="fileuploadsize"></a>`size` | [`Int!`](#int) | Size of the upload in bytes. |
+
### `GeoNode`
#### Fields
@@ -11681,6 +11919,24 @@ Represents an external issue.
#### Fields with arguments
+##### `GeoNode.ciSecureFileRegistries`
+
+Find Ci Secure File registries on this Geo node.
+
+Returns [`CiSecureFileRegistryConnection`](#cisecurefileregistryconnection).
+
+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="geonodecisecurefileregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <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.groupWikiRepositoryRegistries`
Find group wiki repository registries on this Geo node.
@@ -11696,6 +11952,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodegroupwikirepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodegroupwikirepositoryregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodegroupwikirepositoryregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.jobArtifactRegistries`
@@ -11712,6 +11970,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodejobartifactregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodejobartifactregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodejobartifactregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.lfsObjectRegistries`
@@ -11728,6 +11988,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodelfsobjectregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodelfsobjectregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodelfsobjectregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.mergeRequestDiffRegistries`
@@ -11744,6 +12006,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodemergerequestdiffregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodemergerequestdiffregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodemergerequestdiffregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.packageFileRegistries`
@@ -11760,6 +12024,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodepackagefileregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodepackagefileregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodepackagefileregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.pagesDeploymentRegistries`
@@ -11776,6 +12042,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodepagesdeploymentregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodepagesdeploymentregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodepagesdeploymentregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.pipelineArtifactRegistries`
@@ -11792,6 +12060,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodepipelineartifactregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodepipelineartifactregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodepipelineartifactregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.snippetRepositoryRegistries`
@@ -11808,6 +12078,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodesnippetrepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodesnippetrepositoryregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodesnippetrepositoryregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.terraformStateVersionRegistries`
@@ -11824,6 +12096,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodeterraformstateversionregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodeterraformstateversionregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodeterraformstateversionregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
##### `GeoNode.uploadRegistries`
@@ -11840,6 +12114,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="geonodeuploadregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
+| <a id="geonodeuploadregistriesreplicationstate"></a>`replicationState` | [`ReplicationStateEnum`](#replicationstateenum) | Filters registries by their replication state. |
+| <a id="geonodeuploadregistriesverificationstate"></a>`verificationState` | [`VerificationStateEnum`](#verificationstateenum) | Filters registries by their verification state. |
### `GrafanaIntegration`
@@ -11864,7 +12140,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupallowstalerunnerpruning"></a>`allowStaleRunnerPruning` | [`Boolean!`](#boolean) | Indicates whether to regularly prune stale group runners. Defaults to false. |
| <a id="groupautodevopsenabled"></a>`autoDevopsEnabled` | [`Boolean`](#boolean) | Indicates whether Auto DevOps is enabled for all projects within this group. |
| <a id="groupavatarurl"></a>`avatarUrl` | [`String`](#string) | Avatar URL of the group. |
-| <a id="groupcivariables"></a>`ciVariables` | [`CiVariableConnection`](#civariableconnection) | List of the group's CI/CD variables. (see [Connections](#connections)) |
+| <a id="groupcivariables"></a>`ciVariables` | [`CiGroupVariableConnection`](#cigroupvariableconnection) | List of the group's CI/CD variables. (see [Connections](#connections)) |
| <a id="groupcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the group. |
| <a id="groupcontainslockedprojects"></a>`containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
| <a id="groupcrossprojectpipelineavailable"></a>`crossProjectPipelineAvailable` | [`Boolean!`](#boolean) | Indicates if the cross_project_pipeline feature is available for the namespace. |
@@ -11907,6 +12183,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupstoragesizelimit"></a>`storageSizeLimit` | [`Float`](#float) | Total storage limit of the root namespace in bytes. |
| <a id="groupsubgroupcreationlevel"></a>`subgroupCreationLevel` | [`String`](#string) | Permission level required to create subgroups within the group. |
| <a id="grouptemporarystorageincreaseendson"></a>`temporaryStorageIncreaseEndsOn` | [`Time`](#time) | Date until the temporary storage increase is active. |
+| <a id="grouptimelogcategories"></a>`timelogCategories` **{warning-solid}** | [`TimeTrackingTimelogCategoryConnection`](#timetrackingtimelogcategoryconnection) | **Introduced** in 15.3. This feature is in Alpha. It can be changed or removed at any time. Timelog categories for the namespace. |
| <a id="grouptotalrepositorysize"></a>`totalRepositorySize` | [`Float`](#float) | Total repository size of all projects in the root namespace in bytes. |
| <a id="grouptotalrepositorysizeexcess"></a>`totalRepositorySizeExcess` | [`Float`](#float) | Total excess repository size of all projects in the root namespace in bytes. |
| <a id="grouptwofactorgraceperiod"></a>`twoFactorGracePeriod` | [`Int`](#int) | Time before two-factor authentication is enforced. |
@@ -12005,6 +12282,19 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupcomplianceframeworksid"></a>`id` | [`ComplianceManagementFrameworkID`](#compliancemanagementframeworkid) | Global ID of a specific compliance framework to return. |
+##### `Group.contactStateCounts`
+
+Counts of contacts by state for the group.
+
+Returns [`ContactStateCounts`](#contactstatecounts).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="groupcontactstatecountssearch"></a>`search` | [`String`](#string) | Search term to find contacts with. |
+| <a id="groupcontactstatecountsstate"></a>`state` | [`CustomerRelationsContactState`](#customerrelationscontactstate) | State of the contacts to search for. |
+
##### `Group.contacts`
Find contacts of this group.
@@ -12021,6 +12311,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupcontactsids"></a>`ids` | [`[CustomerRelationsContactID!]`](#customerrelationscontactid) | Filter contacts by IDs. |
| <a id="groupcontactssearch"></a>`search` | [`String`](#string) | Search term to find contacts with. |
+| <a id="groupcontactssort"></a>`sort` | [`ContactSort`](#contactsort) | Criteria to sort contacts by. |
| <a id="groupcontactsstate"></a>`state` | [`CustomerRelationsContactState`](#customerrelationscontactstate) | State of the contacts to search for. |
##### `Group.containerRepositories`
@@ -12443,7 +12734,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="grouprunnersstatus"></a>`status` | [`CiRunnerStatus`](#cirunnerstatus) | Filter runners by status. |
| <a id="grouprunnerstaglist"></a>`tagList` | [`[String!]`](#string) | Filter by tags associated with the runner (comma-separated or array). |
| <a id="grouprunnerstype"></a>`type` | [`CiRunnerType`](#cirunnertype) | Filter runners by type. |
-| <a id="grouprunnersupgradestatus"></a>`upgradeStatus` | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | Filter by upgrade status. |
+| <a id="grouprunnersupgradestatus"></a>`upgradeStatus` | [`CiRunnerUpgradeStatus`](#cirunnerupgradestatus) | Filter by upgrade status. |
##### `Group.scanExecutionPolicies`
@@ -12662,9 +12953,11 @@ Represents the Geo sync and verification state of a group wiki repository.
| <a id="groupwikirepositoryregistryid"></a>`id` | [`ID!`](#id) | ID of the GroupWikiRepositoryRegistry. |
| <a id="groupwikirepositoryregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the GroupWikiRepositoryRegistry. |
| <a id="groupwikirepositoryregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the GroupWikiRepositoryRegistry. |
-| <a id="groupwikirepositoryregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the GroupWikiRepositoryRegistry should be resynced. |
+| <a id="groupwikirepositoryregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the GroupWikiRepositoryRegistry is resynced. |
| <a id="groupwikirepositoryregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the GroupWikiRepositoryRegistry. |
| <a id="groupwikirepositoryregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the GroupWikiRepositoryRegistry. |
+| <a id="groupwikirepositoryregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the GroupWikiRepositoryRegistry is reverified. |
+| <a id="groupwikirepositoryregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the GroupWikiRepositoryRegistry. |
### `HelmFileMetadata`
@@ -13030,7 +13323,7 @@ Represents an iteration cadence.
| <a id="iterationcadenceid"></a>`id` | [`IterationsCadenceID!`](#iterationscadenceid) | Global ID of the iteration cadence. |
| <a id="iterationcadenceiterationsinadvance"></a>`iterationsInAdvance` | [`Int`](#int) | Upcoming iterations to be created when iteration cadence is set to automatic. |
| <a id="iterationcadencerollover"></a>`rollOver` | [`Boolean!`](#boolean) | Whether the iteration cadence should roll over issues to the next iteration or not. |
-| <a id="iterationcadencestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the iteration cadence start date. |
+| <a id="iterationcadencestartdate"></a>`startDate` | [`Time`](#time) | Timestamp of the automation start date. |
| <a id="iterationcadencetitle"></a>`title` | [`String!`](#string) | Title of the iteration cadence. |
### `JiraImport`
@@ -13111,9 +13404,11 @@ Represents the Geo replication and verification state of a job_artifact.
| <a id="jobartifactregistryid"></a>`id` | [`ID!`](#id) | ID of the JobArtifactRegistry. |
| <a id="jobartifactregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the JobArtifactRegistry. |
| <a id="jobartifactregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the JobArtifactRegistry. |
-| <a id="jobartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the JobArtifactRegistry should be resynced. |
+| <a id="jobartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the JobArtifactRegistry is resynced. |
| <a id="jobartifactregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the JobArtifactRegistry. |
| <a id="jobartifactregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the JobArtifactRegistry. |
+| <a id="jobartifactregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the JobArtifactRegistry is reverified. |
+| <a id="jobartifactregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the JobArtifactRegistry. |
### `JobPermissions`
@@ -13163,9 +13458,11 @@ Represents the Geo sync and verification state of an LFS object.
| <a id="lfsobjectregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the LfsObjectRegistry. |
| <a id="lfsobjectregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the LfsObjectRegistry. |
| <a id="lfsobjectregistrylfsobjectid"></a>`lfsObjectId` | [`ID!`](#id) | ID of the LFS object. |
-| <a id="lfsobjectregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the LfsObjectRegistry should be resynced. |
+| <a id="lfsobjectregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the LfsObjectRegistry is resynced. |
| <a id="lfsobjectregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the LfsObjectRegistry. |
| <a id="lfsobjectregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the LfsObjectRegistry. |
+| <a id="lfsobjectregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the LfsObjectRegistry is reverified. |
+| <a id="lfsobjectregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the LfsObjectRegistry. |
### `LicenseHistoryEntry`
@@ -13231,6 +13528,7 @@ Maven metadata.
| <a id="mergerequestdefaultsquashcommitmessage"></a>`defaultSquashCommitMessage` | [`String`](#string) | Default squash commit message of the merge request. |
| <a id="mergerequestdescription"></a>`description` | [`String`](#string) | Description of the merge request (Markdown rendered as HTML for caching). |
| <a id="mergerequestdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
+| <a id="mergerequestdetailedmergestatus"></a>`detailedMergeStatus` **{warning-solid}** | [`DetailedMergeStatus`](#detailedmergestatus) | **Introduced** in 15.3. This feature is in Alpha. It can be changed or removed at any time. Detailed merge status of the merge request. |
| <a id="mergerequestdiffheadsha"></a>`diffHeadSha` | [`String`](#string) | Diff head SHA of the merge request. |
| <a id="mergerequestdiffrefs"></a>`diffRefs` | [`DiffRefs`](#diffrefs) | References of the base SHA, the head SHA, and the start SHA for this merge request. |
| <a id="mergerequestdiffstatssummary"></a>`diffStatsSummary` | [`DiffStatsSummary`](#diffstatssummary) | Summary of which files were changed in this merge request. |
@@ -13847,9 +14145,11 @@ Represents the Geo sync and verification state of a Merge Request diff.
| <a id="mergerequestdiffregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the MergeRequestDiffRegistry. |
| <a id="mergerequestdiffregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the MergeRequestDiffRegistry. |
| <a id="mergerequestdiffregistrymergerequestdiffid"></a>`mergeRequestDiffId` | [`ID!`](#id) | ID of the Merge Request diff. |
-| <a id="mergerequestdiffregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the MergeRequestDiffRegistry should be resynced. |
+| <a id="mergerequestdiffregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the MergeRequestDiffRegistry is resynced. |
| <a id="mergerequestdiffregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the MergeRequestDiffRegistry. |
| <a id="mergerequestdiffregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the MergeRequestDiffRegistry. |
+| <a id="mergerequestdiffregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the MergeRequestDiffRegistry is reverified. |
+| <a id="mergerequestdiffregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the MergeRequestDiffRegistry. |
### `MergeRequestParticipant`
@@ -14469,6 +14769,7 @@ Contains statistics about a milestone.
| <a id="namespacesharedrunnerssetting"></a>`sharedRunnersSetting` | [`SharedRunnersSetting`](#sharedrunnerssetting) | Shared runners availability for the namespace and its descendants. |
| <a id="namespacestoragesizelimit"></a>`storageSizeLimit` | [`Float`](#float) | Total storage limit of the root namespace in bytes. |
| <a id="namespacetemporarystorageincreaseendson"></a>`temporaryStorageIncreaseEndsOn` | [`Time`](#time) | Date until the temporary storage increase is active. |
+| <a id="namespacetimelogcategories"></a>`timelogCategories` **{warning-solid}** | [`TimeTrackingTimelogCategoryConnection`](#timetrackingtimelogcategoryconnection) | **Introduced** in 15.3. This feature is in Alpha. It can be changed or removed at any time. Timelog categories for the namespace. |
| <a id="namespacetotalrepositorysize"></a>`totalRepositorySize` | [`Float`](#float) | Total repository size of all projects in the root namespace in bytes. |
| <a id="namespacetotalrepositorysizeexcess"></a>`totalRepositorySizeExcess` | [`Float`](#float) | Total excess repository size of all projects in the root namespace in bytes. |
| <a id="namespacevisibility"></a>`visibility` | [`String`](#string) | Visibility of the namespace. |
@@ -14574,10 +14875,11 @@ 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` | [`Boolean`](#boolean) | Indicates if this note is confidential. |
+| <a id="noteconfidential"></a>`confidential` **{warning-solid}** | [`Boolean`](#boolean) | **Deprecated** in 15.3. 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. |
+| <a id="noteinternal"></a>`internal` | [`Boolean`](#boolean) | Indicates if this note is internal. |
| <a id="noteposition"></a>`position` | [`DiffPosition`](#diffposition) | Position of this note on a diff. |
| <a id="noteproject"></a>`project` | [`Project`](#project) | Project associated with the note. |
| <a id="noteresolvable"></a>`resolvable` | [`Boolean!`](#boolean) | Indicates if the object can be resolved. |
@@ -14794,9 +15096,11 @@ Represents the Geo sync and verification state of a package file.
| <a id="packagefileregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the PackageFileRegistry. |
| <a id="packagefileregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PackageFileRegistry. |
| <a id="packagefileregistrypackagefileid"></a>`packageFileId` | [`ID!`](#id) | ID of the PackageFile. |
-| <a id="packagefileregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PackageFileRegistry should be resynced. |
+| <a id="packagefileregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PackageFileRegistry is resynced. |
| <a id="packagefileregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PackageFileRegistry. |
| <a id="packagefileregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PackageFileRegistry. |
+| <a id="packagefileregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the PackageFileRegistry is reverified. |
+| <a id="packagefileregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the PackageFileRegistry. |
### `PackageHelmDependencyType`
@@ -14916,9 +15220,11 @@ Represents the Geo replication and verification state of a pages_deployment.
| <a id="pagesdeploymentregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the PagesDeploymentRegistry. |
| <a id="pagesdeploymentregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PagesDeploymentRegistry. |
| <a id="pagesdeploymentregistrypagesdeploymentid"></a>`pagesDeploymentId` | [`ID!`](#id) | ID of the Pages Deployment. |
-| <a id="pagesdeploymentregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PagesDeploymentRegistry should be resynced. |
+| <a id="pagesdeploymentregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PagesDeploymentRegistry is resynced. |
| <a id="pagesdeploymentregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PagesDeploymentRegistry. |
| <a id="pagesdeploymentregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PagesDeploymentRegistry. |
+| <a id="pagesdeploymentregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the PagesDeploymentRegistry is reverified. |
+| <a id="pagesdeploymentregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the PagesDeploymentRegistry. |
### `PathLock`
@@ -15085,9 +15391,11 @@ Represents the Geo sync and verification state of a pipeline artifact.
| <a id="pipelineartifactregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the PipelineArtifactRegistry. |
| <a id="pipelineartifactregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the PipelineArtifactRegistry. |
| <a id="pipelineartifactregistrypipelineartifactid"></a>`pipelineArtifactId` | [`ID!`](#id) | ID of the pipeline artifact. |
-| <a id="pipelineartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PipelineArtifactRegistry should be resynced. |
+| <a id="pipelineartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the PipelineArtifactRegistry is resynced. |
| <a id="pipelineartifactregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the PipelineArtifactRegistry. |
| <a id="pipelineartifactregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the PipelineArtifactRegistry. |
+| <a id="pipelineartifactregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the PipelineArtifactRegistry is reverified. |
+| <a id="pipelineartifactregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the PipelineArtifactRegistry. |
### `PipelineCounts`
@@ -15164,7 +15472,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcicdsettings"></a>`ciCdSettings` | [`ProjectCiCdSetting`](#projectcicdsetting) | CI/CD settings for the project. |
| <a id="projectciconfigpathordefault"></a>`ciConfigPathOrDefault` | [`String!`](#string) | Path of the CI configuration file. |
| <a id="projectcijobtokenscope"></a>`ciJobTokenScope` | [`CiJobTokenScopeType`](#cijobtokenscopetype) | The CI Job Tokens scope of access. |
-| <a id="projectcivariables"></a>`ciVariables` | [`CiVariableConnection`](#civariableconnection) | List of the project's CI/CD variables. (see [Connections](#connections)) |
+| <a id="projectcivariables"></a>`ciVariables` | [`CiProjectVariableConnection`](#ciprojectvariableconnection) | List of the project's CI/CD variables. (see [Connections](#connections)) |
| <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. |
| <a id="projectcomplianceframeworks"></a>`complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks associated with the project. (see [Connections](#connections)) |
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | Container expiration policy of the project. |
@@ -15229,6 +15537,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectsuggestioncommitmessage"></a>`suggestionCommitMessage` | [`String`](#string) | Commit message used to apply merge request suggestions. |
| <a id="projecttaglist"></a>`tagList` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.12. Use `topics`. |
| <a id="projectterraformstates"></a>`terraformStates` | [`TerraformStateConnection`](#terraformstateconnection) | Terraform states associated with the project. (see [Connections](#connections)) |
+| <a id="projecttimelogcategories"></a>`timelogCategories` **{warning-solid}** | [`TimeTrackingTimelogCategoryConnection`](#timetrackingtimelogcategoryconnection) | **Introduced** in 15.3. This feature is in Alpha. It can be changed or removed at any time. Timelog categories for the project. |
| <a id="projecttopics"></a>`topics` | [`[String!]`](#string) | List of project topics. |
| <a id="projectuserpermissions"></a>`userPermissions` | [`ProjectPermissions!`](#projectpermissions) | Permissions for the current user on the resource. |
| <a id="projectvisibility"></a>`visibility` | [`String`](#string) | Visibility of the project. |
@@ -15510,6 +15819,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectenvironmentssearch"></a>`search` | [`String`](#string) | Search query for environment name. |
| <a id="projectenvironmentsstates"></a>`states` | [`[String!]`](#string) | States of environments that should be included in result. |
+##### `Project.forkTargets`
+
+Namespaces in which the current user can fork the project into.
+
+Returns [`NamespaceConnection`](#namespaceconnection).
+
+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="projectforktargetssearch"></a>`search` | [`String`](#string) | Search query for path or name. |
+
##### `Project.incidentManagementEscalationPolicies`
Incident Management escalation policies of the project.
@@ -17252,10 +17577,12 @@ Represents the Geo sync and verification state of a snippet repository.
| <a id="snippetrepositoryregistryid"></a>`id` | [`ID!`](#id) | ID of the SnippetRepositoryRegistry. |
| <a id="snippetrepositoryregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the SnippetRepositoryRegistry. |
| <a id="snippetrepositoryregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the SnippetRepositoryRegistry. |
-| <a id="snippetrepositoryregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the SnippetRepositoryRegistry should be resynced. |
+| <a id="snippetrepositoryregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the SnippetRepositoryRegistry is resynced. |
| <a id="snippetrepositoryregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the SnippetRepositoryRegistry. |
| <a id="snippetrepositoryregistrysnippetrepositoryid"></a>`snippetRepositoryId` | [`ID!`](#id) | ID of the Snippet Repository. |
| <a id="snippetrepositoryregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the SnippetRepositoryRegistry. |
+| <a id="snippetrepositoryregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the SnippetRepositoryRegistry is reverified. |
+| <a id="snippetrepositoryregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the SnippetRepositoryRegistry. |
### `StatusAction`
@@ -17354,10 +17681,12 @@ Represents the Geo sync and verification state of a terraform state version.
| <a id="terraformstateversionregistryid"></a>`id` | [`ID!`](#id) | ID of the TerraformStateVersionRegistry. |
| <a id="terraformstateversionregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the TerraformStateVersionRegistry. |
| <a id="terraformstateversionregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the TerraformStateVersionRegistry. |
-| <a id="terraformstateversionregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the TerraformStateVersionRegistry should be resynced. |
+| <a id="terraformstateversionregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the TerraformStateVersionRegistry is resynced. |
| <a id="terraformstateversionregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the TerraformStateVersionRegistry. |
| <a id="terraformstateversionregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the TerraformStateVersionRegistry. |
| <a id="terraformstateversionregistryterraformstateversionid"></a>`terraformStateVersionId` | [`ID!`](#id) | ID of the terraform state version. |
+| <a id="terraformstateversionregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the TerraformStateVersionRegistry is reverified. |
+| <a id="terraformstateversionregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the TerraformStateVersionRegistry. |
### `TestCase`
@@ -17465,6 +17794,21 @@ Represents the time report stats for timeboxes.
| <a id="timereportstatsincomplete"></a>`incomplete` | [`TimeboxMetrics`](#timeboxmetrics) | Incomplete issues metrics. |
| <a id="timereportstatstotal"></a>`total` | [`TimeboxMetrics`](#timeboxmetrics) | Total issues metrics. |
+### `TimeTrackingTimelogCategory`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="timetrackingtimelogcategorybillable"></a>`billable` | [`Boolean`](#boolean) | Whether the category is billable or not. |
+| <a id="timetrackingtimelogcategorybillingrate"></a>`billingRate` | [`Float`](#float) | Billing rate for the category. |
+| <a id="timetrackingtimelogcategorycolor"></a>`color` | [`Color`](#color) | Color assigned to the category. |
+| <a id="timetrackingtimelogcategorycreatedat"></a>`createdAt` | [`Time!`](#time) | When the category was created. |
+| <a id="timetrackingtimelogcategorydescription"></a>`description` | [`String`](#string) | Description of the category. |
+| <a id="timetrackingtimelogcategoryid"></a>`id` | [`ID!`](#id) | Internal ID of the timelog category. |
+| <a id="timetrackingtimelogcategoryname"></a>`name` | [`String!`](#string) | Name of the category. |
+| <a id="timetrackingtimelogcategoryupdatedat"></a>`updatedAt` | [`Time!`](#time) | When the category was last updated. |
+
### `TimeboxMetrics`
Represents measured stats metrics for timeboxes.
@@ -17618,9 +17962,11 @@ Represents the Geo replication and verification state of an upload.
| <a id="uploadregistryid"></a>`id` | [`ID!`](#id) | ID of the UploadRegistry. |
| <a id="uploadregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the UploadRegistry. |
| <a id="uploadregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the UploadRegistry. |
-| <a id="uploadregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the UploadRegistry should be resynced. |
+| <a id="uploadregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the UploadRegistry is resynced. |
| <a id="uploadregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the UploadRegistry. |
| <a id="uploadregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the UploadRegistry. |
+| <a id="uploadregistryverificationretryat"></a>`verificationRetryAt` | [`Time`](#time) | Timestamp after which the UploadRegistry is reverified. |
+| <a id="uploadregistryverifiedat"></a>`verifiedAt` | [`Time`](#time) | Timestamp of the most recent successful verification of the UploadRegistry. |
### `UsageTrendsMeasurement`
@@ -18510,14 +18856,19 @@ Represents vulnerability letter grades with associated projects.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="workitemclosedat"></a>`closedAt` | [`Time`](#time) | Timestamp of when the work item was closed. |
+| <a id="workitemconfidential"></a>`confidential` | [`Boolean!`](#boolean) | Indicates the work item is confidential. |
+| <a id="workitemcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the work item was created. |
| <a id="workitemdescription"></a>`description` | [`String`](#string) | Description of the work item. |
| <a id="workitemdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| <a id="workitemid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
| <a id="workitemiid"></a>`iid` | [`ID!`](#id) | Internal ID of the work item. |
| <a id="workitemlockversion"></a>`lockVersion` | [`Int!`](#int) | Lock version of the work item. Incremented each time the work item is updated. |
+| <a id="workitemproject"></a>`project` **{warning-solid}** | [`Project!`](#project) | **Introduced** in 15.3. This feature is in Alpha. It can be changed or removed at any time. Project the work item belongs to. |
| <a id="workitemstate"></a>`state` | [`WorkItemState!`](#workitemstate) | State of the work item. |
| <a id="workitemtitle"></a>`title` | [`String!`](#string) | Title of the work item. |
| <a id="workitemtitlehtml"></a>`titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
+| <a id="workitemupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the work item was last updated. |
| <a id="workitemuserpermissions"></a>`userPermissions` | [`WorkItemPermissions!`](#workitempermissions) | Permissions for the current user on the resource. |
| <a id="workitemwidgets"></a>`widgets` | [`[WorkItemWidget!]`](#workitemwidget) | Collection of widgets that belong to the work item. |
| <a id="workitemworkitemtype"></a>`workItemType` | [`WorkItemType!`](#workitemtype) | Type assigned to the work item. |
@@ -18581,6 +18932,41 @@ Represents a hierarchy widget.
| <a id="workitemwidgethierarchyparent"></a>`parent` | [`WorkItem`](#workitem) | Parent work item. |
| <a id="workitemwidgethierarchytype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+### `WorkItemWidgetLabels`
+
+Represents the labels widget.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetlabelsallowsscopedlabels"></a>`allowsScopedLabels` | [`Boolean`](#boolean) | Indicates whether a scoped label is allowed. |
+| <a id="workitemwidgetlabelslabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels assigned to the work item. (see [Connections](#connections)) |
+| <a id="workitemwidgetlabelstype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+
+### `WorkItemWidgetStartAndDueDate`
+
+Represents a start and due date widget.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetstartandduedateduedate"></a>`dueDate` | [`Date`](#date) | Due date of the work item. |
+| <a id="workitemwidgetstartandduedatestartdate"></a>`startDate` | [`Date`](#date) | Start date of the work item. |
+| <a id="workitemwidgetstartandduedatetype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+
+### `WorkItemWidgetVerificationStatus`
+
+Represents a verification 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. |
+
### `WorkItemWidgetWeight`
Represents a weight widget.
@@ -18853,15 +19239,14 @@ Values for sorting runners.
| <a id="cirunnertypeinstance_type"></a>`INSTANCE_TYPE` | A runner that is instance type. |
| <a id="cirunnertypeproject_type"></a>`PROJECT_TYPE` | A runner that is project type. |
-### `CiRunnerUpgradeStatusType`
+### `CiRunnerUpgradeStatus`
| Value | Description |
| ----- | ----------- |
-| <a id="cirunnerupgradestatustypeavailable"></a>`AVAILABLE` | Upgrade is available for the runner. |
-| <a id="cirunnerupgradestatustypeinvalid"></a>`INVALID` | Runner version is not valid. |
-| <a id="cirunnerupgradestatustypenot_available"></a>`NOT_AVAILABLE` | Upgrade is not available for the runner. |
-| <a id="cirunnerupgradestatustyperecommended"></a>`RECOMMENDED` | Upgrade is available and recommended for the runner. |
-| <a id="cirunnerupgradestatustypeunknown"></a>`UNKNOWN` | Upgrade status is unknown. |
+| <a id="cirunnerupgradestatusavailable"></a>`AVAILABLE` | Upgrade is available for the runner. |
+| <a id="cirunnerupgradestatusinvalid"></a>`INVALID` | Runner version is not valid. |
+| <a id="cirunnerupgradestatusnot_available"></a>`NOT_AVAILABLE` | Upgrade is not available for the runner. |
+| <a id="cirunnerupgradestatusrecommended"></a>`RECOMMENDED` | Upgrade is available and recommended for the runner. |
### `CiVariableType`
@@ -18946,6 +19331,33 @@ Conan file types.
| <a id="conanmetadatumfiletypeenumpackage_file"></a>`PACKAGE_FILE` | A package file type. |
| <a id="conanmetadatumfiletypeenumrecipe_file"></a>`RECIPE_FILE` | A recipe file type. |
+### `ContactSort`
+
+Values for sorting contacts.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="contactsortcreated_asc"></a>`CREATED_ASC` | Created at ascending order. |
+| <a id="contactsortcreated_desc"></a>`CREATED_DESC` | Created at descending order. |
+| <a id="contactsortdescription_asc"></a>`DESCRIPTION_ASC` | Description by ascending order. |
+| <a id="contactsortdescription_desc"></a>`DESCRIPTION_DESC` | Description by descending order. |
+| <a id="contactsortemail_asc"></a>`EMAIL_ASC` | Email by ascending order. |
+| <a id="contactsortemail_desc"></a>`EMAIL_DESC` | Email by descending order. |
+| <a id="contactsortfirst_name_asc"></a>`FIRST_NAME_ASC` | First name by ascending order. |
+| <a id="contactsortfirst_name_desc"></a>`FIRST_NAME_DESC` | First name by descending order. |
+| <a id="contactsortlast_name_asc"></a>`LAST_NAME_ASC` | Last name by ascending order. |
+| <a id="contactsortlast_name_desc"></a>`LAST_NAME_DESC` | Last name by descending order. |
+| <a id="contactsortorganization_asc"></a>`ORGANIZATION_ASC` | Organization by ascending order. |
+| <a id="contactsortorganization_desc"></a>`ORGANIZATION_DESC` | Organization by descending order. |
+| <a id="contactsortphone_asc"></a>`PHONE_ASC` | Phone by ascending order. |
+| <a id="contactsortphone_desc"></a>`PHONE_DESC` | Phone by descending order. |
+| <a id="contactsortupdated_asc"></a>`UPDATED_ASC` | Updated at ascending order. |
+| <a id="contactsortupdated_desc"></a>`UPDATED_DESC` | Updated at descending order. |
+| <a id="contactsortcreated_asc"></a>`created_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_ASC`. |
+| <a id="contactsortcreated_desc"></a>`created_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `CREATED_DESC`. |
+| <a id="contactsortupdated_asc"></a>`updated_asc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_ASC`. |
+| <a id="contactsortupdated_desc"></a>`updated_desc` **{warning-solid}** | **Deprecated** in 13.5. This was renamed. Use: `UPDATED_DESC`. |
+
### `ContainerExpirationPolicyCadenceEnum`
| Value | Description |
@@ -19027,8 +19439,9 @@ Values for sorting tags.
| Value | Description |
| ----- | ----------- |
-| <a id="customerrelationscontactstateactive"></a>`active` | Active contact. |
-| <a id="customerrelationscontactstateinactive"></a>`inactive` | Inactive contact. |
+| <a id="customerrelationscontactstateactive"></a>`active` | Active contacts. |
+| <a id="customerrelationscontactstateall"></a>`all` | All available contacts. |
+| <a id="customerrelationscontactstateinactive"></a>`inactive` | Inactive contacts. |
### `CustomerRelationsOrganizationState`
@@ -19172,6 +19585,24 @@ Mutation event of a design within a version.
| <a id="designversioneventmodification"></a>`MODIFICATION` | A modification event. |
| <a id="designversioneventnone"></a>`NONE` | No change. |
+### `DetailedMergeStatus`
+
+Detailed representation of whether a GitLab merge request can be merged.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="detailedmergestatusblocked_status"></a>`BLOCKED_STATUS` | Merge request is blocked by another merge request. |
+| <a id="detailedmergestatusbroken_status"></a>`BROKEN_STATUS` | Can not merge the source into the target branch, potential conflict. |
+| <a id="detailedmergestatuschecking"></a>`CHECKING` | Currently checking for mergeability. |
+| <a id="detailedmergestatusci_must_pass"></a>`CI_MUST_PASS` | Pipeline must succeed before merging. |
+| <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="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. |
+| <a id="detailedmergestatuspolicies_denied"></a>`POLICIES_DENIED` | There are denied policies for the merge request. |
+| <a id="detailedmergestatusunchecked"></a>`UNCHECKED` | Merge status has not been checked. |
+
### `DiffPositionType`
Type of file the position refers to.
@@ -19451,7 +19882,7 @@ Issue type.
| <a id="issuetypeincident"></a>`INCIDENT` | Incident issue type. |
| <a id="issuetypeissue"></a>`ISSUE` | Issue issue type. |
| <a id="issuetyperequirement"></a>`REQUIREMENT` | Requirement issue type. |
-| <a id="issuetypetask"></a>`TASK` **{warning-solid}** | **Introduced** in 15.2. This feature is in Alpha. It can be changed or removed at any time. |
+| <a id="issuetypetask"></a>`TASK` **{warning-solid}** | **Introduced** in 15.2. This feature is in Alpha. It can be changed or removed at any time. Task issue type. Available only when feature flag `work_items` is enabled. |
| <a id="issuetypetest_case"></a>`TEST_CASE` | Test Case issue type. |
### `IterationSearchableField`
@@ -19508,6 +19939,7 @@ Iteration ID wildcard values.
| <a id="jobartifactfiletypecodequality"></a>`CODEQUALITY` | CODE QUALITY job artifact file type. |
| <a id="jobartifactfiletypecontainer_scanning"></a>`CONTAINER_SCANNING` | CONTAINER SCANNING job artifact file type. |
| <a id="jobartifactfiletypecoverage_fuzzing"></a>`COVERAGE_FUZZING` | COVERAGE FUZZING job artifact file type. |
+| <a id="jobartifactfiletypecyclonedx"></a>`CYCLONEDX` | CYCLONEDX job artifact file type. |
| <a id="jobartifactfiletypedast"></a>`DAST` | DAST job artifact file type. |
| <a id="jobartifactfiletypedependency_scanning"></a>`DEPENDENCY_SCANNING` | DEPENDENCY SCANNING job artifact file type. |
| <a id="jobartifactfiletypedotenv"></a>`DOTENV` | DOTENV job artifact file type. |
@@ -19917,6 +20349,15 @@ Release tag ID wildcard values.
| <a id="releasetagwildcardidany"></a>`ANY` | Release tag is assigned. |
| <a id="releasetagwildcardidnone"></a>`NONE` | No release tag is assigned. |
+### `ReplicationStateEnum`
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="replicationstateenumfailed"></a>`FAILED` | Replication process finished but failed. |
+| <a id="replicationstateenumpending"></a>`PENDING` | Replication process has not started. |
+| <a id="replicationstateenumstarted"></a>`STARTED` | Replication process is in progress. |
+| <a id="replicationstateenumsynced"></a>`SYNCED` | Replication process finished successfully. |
+
### `RequirementState`
State of a requirement.
@@ -20051,6 +20492,7 @@ State of a Sentry error.
| <a id="servicetypepipelines_email_service"></a>`PIPELINES_EMAIL_SERVICE` | PipelinesEmailService type. |
| <a id="servicetypepivotaltracker_service"></a>`PIVOTALTRACKER_SERVICE` | PivotaltrackerService type. |
| <a id="servicetypeprometheus_service"></a>`PROMETHEUS_SERVICE` | PrometheusService type. |
+| <a id="servicetypepumble_service"></a>`PUMBLE_SERVICE` | PumbleService type. |
| <a id="servicetypepushover_service"></a>`PUSHOVER_SERVICE` | PushoverService type. |
| <a id="servicetyperedmine_service"></a>`REDMINE_SERVICE` | RedmineService type. |
| <a id="servicetypeshimo_service"></a>`SHIMO_SERVICE` | ShimoService type. |
@@ -20217,6 +20659,10 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumgke_cluster_integration"></a>`GKE_CLUSTER_INTEGRATION` | Callout feature name for gke_cluster_integration. |
| <a id="usercalloutfeaturenameenumgold_trial_billings"></a>`GOLD_TRIAL_BILLINGS` | Callout feature name for gold_trial_billings. |
| <a id="usercalloutfeaturenameenummr_experience_survey"></a>`MR_EXPERIENCE_SURVEY` | Callout feature name for mr_experience_survey. |
+| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_alert_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_ALERT_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_alert_threshold. |
+| <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_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. |
@@ -20224,6 +20670,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumpipeline_needs_hover_tip"></a>`PIPELINE_NEEDS_HOVER_TIP` | Callout feature name for pipeline_needs_hover_tip. |
| <a id="usercalloutfeaturenameenumpreview_user_over_limit_free_plan_alert"></a>`PREVIEW_USER_OVER_LIMIT_FREE_PLAN_ALERT` | Callout feature name for preview_user_over_limit_free_plan_alert. |
| <a id="usercalloutfeaturenameenumprofile_personal_access_token_expiry"></a>`PROFILE_PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for profile_personal_access_token_expiry. |
+| <a id="usercalloutfeaturenameenumproject_quality_summary_feedback"></a>`PROJECT_QUALITY_SUMMARY_FEEDBACK` | Callout feature name for project_quality_summary_feedback. |
| <a id="usercalloutfeaturenameenumregistration_enabled_callout"></a>`REGISTRATION_ENABLED_CALLOUT` | Callout feature name for registration_enabled_callout. |
| <a id="usercalloutfeaturenameenumsecurity_configuration_devops_alert"></a>`SECURITY_CONFIGURATION_DEVOPS_ALERT` | Callout feature name for security_configuration_devops_alert. |
| <a id="usercalloutfeaturenameenumsecurity_configuration_upgrade_banner"></a>`SECURITY_CONFIGURATION_UPGRADE_BANNER` | Callout feature name for security_configuration_upgrade_banner. |
@@ -20259,6 +20706,16 @@ Possible states of a user.
| <a id="userstateblocked"></a>`blocked` | User has been blocked and is prevented from using the system. |
| <a id="userstatedeactivated"></a>`deactivated` | User is no longer active and is unable to use the system. |
+### `VerificationStateEnum`
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="verificationstateenumdisabled"></a>`DISABLED` | Verification process is disabled. |
+| <a id="verificationstateenumfailed"></a>`FAILED` | Verification process finished but failed. |
+| <a id="verificationstateenumpending"></a>`PENDING` | Verification process has not started. |
+| <a id="verificationstateenumstarted"></a>`STARTED` | Verification process is in progress. |
+| <a id="verificationstateenumsucceeded"></a>`SUCCEEDED` | Verification process finished successfully. |
+
### `VisibilityLevelsEnum`
| Value | Description |
@@ -20375,12 +20832,8 @@ Vulnerability sort values.
| ----- | ----------- |
| <a id="vulnerabilitysortdetected_asc"></a>`detected_asc` | Detection timestamp in ascending order. |
| <a id="vulnerabilitysortdetected_desc"></a>`detected_desc` | Detection timestamp in descending order. |
-| <a id="vulnerabilitysortreport_type_asc"></a>`report_type_asc` | Report Type in ascending order. |
-| <a id="vulnerabilitysortreport_type_desc"></a>`report_type_desc` | Report Type in descending order. |
| <a id="vulnerabilitysortseverity_asc"></a>`severity_asc` | Severity in ascending order. |
| <a id="vulnerabilitysortseverity_desc"></a>`severity_desc` | Severity in descending order. |
-| <a id="vulnerabilitysortstate_asc"></a>`state_asc` | State in ascending order. |
-| <a id="vulnerabilitysortstate_desc"></a>`state_desc` | State in descending order. |
### `VulnerabilityState`
@@ -20446,6 +20899,9 @@ Type of a work item widget.
| <a id="workitemwidgettypeassignees"></a>`ASSIGNEES` | Assignees widget. |
| <a id="workitemwidgettypedescription"></a>`DESCRIPTION` | Description widget. |
| <a id="workitemwidgettypehierarchy"></a>`HIERARCHY` | Hierarchy 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="workitemwidgettypeweight"></a>`WEIGHT` | Weight widget. |
## Scalar types
@@ -21008,6 +21464,12 @@ A regexp containing patterns sourced from user input.
### `Upload`
+### `UploadID`
+
+A `UploadID` is a global ID. It is encoded as a string.
+
+An example `UploadID` is: `"gid://gitlab/Upload/1"`.
+
### `UserID`
A `UserID` is a global ID. It is encoded as a string.
@@ -21189,6 +21651,25 @@ Implementations:
| <a id="alertmanagementintegrationtype"></a>`type` | [`AlertManagementIntegrationType!`](#alertmanagementintegrationtype) | Type of integration. |
| <a id="alertmanagementintegrationurl"></a>`url` | [`String`](#string) | Endpoint which accepts alert notifications. |
+#### `CiVariable`
+
+Implementations:
+
+- [`CiGroupVariable`](#cigroupvariable)
+- [`CiInstanceVariable`](#ciinstancevariable)
+- [`CiManualVariable`](#cimanualvariable)
+- [`CiProjectVariable`](#ciprojectvariable)
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="civariableid"></a>`id` | [`ID!`](#id) | ID of the variable. |
+| <a id="civariablekey"></a>`key` | [`String`](#string) | Name of the variable. |
+| <a id="civariableraw"></a>`raw` | [`Boolean`](#boolean) | Indicates whether the variable is raw. |
+| <a id="civariablevalue"></a>`value` | [`String`](#string) | Value of the variable. |
+| <a id="civariablevariabletype"></a>`variableType` | [`CiVariableType`](#civariabletype) | Type of the variable. |
+
#### `CurrentUserTodos`
Implementations:
@@ -21674,6 +22155,9 @@ Implementations:
- [`WorkItemWidgetAssignees`](#workitemwidgetassignees)
- [`WorkItemWidgetDescription`](#workitemwidgetdescription)
- [`WorkItemWidgetHierarchy`](#workitemwidgethierarchy)
+- [`WorkItemWidgetLabels`](#workitemwidgetlabels)
+- [`WorkItemWidgetStartAndDueDate`](#workitemwidgetstartandduedate)
+- [`WorkItemWidgetVerificationStatus`](#workitemwidgetverificationstatus)
- [`WorkItemWidgetWeight`](#workitemwidgetweight)
##### Fields
@@ -21731,6 +22215,17 @@ Field that are available while modifying the custom mapping attributes for an HT
| <a id="boardissueinputweight"></a>`weight` | [`String`](#string) | Filter by weight. |
| <a id="boardissueinputweightwildcardid"></a>`weightWildcardId` | [`WeightWildcardId`](#weightwildcardid) | Filter by weight ID wildcard. Incompatible with weight. |
+### `CiVariableInput`
+
+Attributes for defining a CI/CD variable.
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="civariableinputkey"></a>`key` | [`String!`](#string) | Name of the variable. |
+| <a id="civariableinputvalue"></a>`value` | [`String!`](#string) | Value of the variable. |
+
### `CommitAction`
#### Arguments
@@ -21799,11 +22294,11 @@ Input type for DastSiteProfile authentication.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="dastsiteprofileauthinputenabled"></a>`enabled` | [`Boolean`](#boolean) | Indicates whether authentication is enabled. |
-| <a id="dastsiteprofileauthinputpassword"></a>`password` | [`String`](#string) | Password to authenticate with on the target website. |
+| <a id="dastsiteprofileauthinputpassword"></a>`password` | [`String`](#string) | Password to authenticate with on the target. |
| <a id="dastsiteprofileauthinputpasswordfield"></a>`passwordField` | [`String`](#string) | Name of password field at the sign-in HTML form. |
| <a id="dastsiteprofileauthinputsubmitfield"></a>`submitField` | [`String`](#string) | Name or ID of sign-in submit button at the sign-in HTML form. |
| <a id="dastsiteprofileauthinputurl"></a>`url` | [`String`](#string) | The URL of the page containing the sign-in HTML form on the target website. |
-| <a id="dastsiteprofileauthinputusername"></a>`username` | [`String`](#string) | Username to authenticate with on the target website. |
+| <a id="dastsiteprofileauthinputusername"></a>`username` | [`String`](#string) | Username to authenticate with on the target. |
| <a id="dastsiteprofileauthinputusernamefield"></a>`usernameField` | [`String`](#string) | Name of username field at the sign-in HTML form. |
### `DiffImagePositionInput`
@@ -22160,12 +22655,22 @@ A time-frame defined as a closed inclusive range of two dates.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="workitemupdatedtaskinputassigneeswidget"></a>`assigneesWidget` | [`WorkItemWidgetAssigneesInput`](#workitemwidgetassigneesinput) | Input for assignees widget. |
+| <a id="workitemupdatedtaskinputconfidential"></a>`confidential` | [`Boolean`](#boolean) | Sets the work item confidentiality. |
| <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="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. |
-| <a id="workitemupdatedtaskinputweightwidget"></a>`weightWidget` | [`WorkItemWidgetWeightInput`](#workitemwidgetweightinput) | Input for weight widget. |
+
+### `WorkItemWidgetAssigneesInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetassigneesinputassigneeids"></a>`assigneeIds` | [`[UserID!]!`](#userid) | Global IDs of assignees. |
### `WorkItemWidgetDescriptionInput`
@@ -22192,10 +22697,19 @@ A time-frame defined as a closed inclusive range of two dates.
| <a id="workitemwidgethierarchyupdateinputchildrenids"></a>`childrenIds` | [`[WorkItemID!]`](#workitemid) | Global IDs of children work items. |
| <a id="workitemwidgethierarchyupdateinputparentid"></a>`parentId` | [`WorkItemID`](#workitemid) | Global ID of the parent work item. Use `null` to remove the association. |
+### `WorkItemWidgetStartAndDueDateUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetstartandduedateupdateinputduedate"></a>`dueDate` | [`Date`](#date) | Due date for the work item. |
+| <a id="workitemwidgetstartandduedateupdateinputstartdate"></a>`startDate` | [`Date`](#date) | Start date for the work item. |
+
### `WorkItemWidgetWeightInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="workitemwidgetweightinputweight"></a>`weight` | [`Int!`](#int) | Weight of the work item. |
+| <a id="workitemwidgetweightinputweight"></a>`weight` | [`Int`](#int) | Weight of the work item. |
diff --git a/doc/api/group_protected_environments.md b/doc/api/group_protected_environments.md
index 8ebd0dcd99a..0f1527f8968 100644
--- a/doc/api/group_protected_environments.md
+++ b/doc/api/group_protected_environments.md
@@ -106,7 +106,7 @@ POST /groups/:id/protected_environments
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) maintained by the authenticated user. |
| `name` | string | yes | The deployment tier of the protected environment. One of `production`, `staging`, `testing`, `development`, or `other`. Read more about [deployment tiers](../ci/environments/index.md#deployment-tier-of-environments).|
| `deploy_access_levels` | array | yes | Array of access levels allowed to deploy, 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. |
-| `required_approval_count` | integer | no | The number of approvals required to deploy to this environment. This is part of Deployment Approvals, which isn't yet available for use. For details, see [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/343864). |
+| `required_approval_count` | integer | no | The number of approvals required to deploy to this environment. |
| `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).
diff --git a/doc/api/groups.md b/doc/api/groups.md
index c51f23decb9..588ab2a5821 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -452,6 +452,7 @@ Example response:
"open_issues_count":10,
"ci_default_git_depth":50,
"ci_forward_deployment_enabled":true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project":true,
"public_jobs":true,
"build_timeout":3600,
"auto_cancel_pending_pipelines":"enabled",
@@ -901,6 +902,13 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
## Update group
+> `unique_project_download_limit`, `unique_project_download_limit_interval_in_seconds`, and `unique_project_download_limit_allowlist` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92970) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `limit_unique_project_downloads_per_namespace_user`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default `unique_project_download_limit`, `unique_project_download_limit_interval_in_seconds`, and `unique_project_download_limit_allowlist` are not available.
+To make them available, ask an administrator to [enable the feature flag](../administration/feature_flags.md)
+named `limit_unique_project_downloads_per_namespace_user`.
+
Updates the project group. Only available to group owners and administrators.
```plaintext
@@ -919,7 +927,7 @@ PUT /groups/:id
| `emails_disabled` | boolean | no | Disable email notifications. |
| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned. |
-| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
+| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/access_and_permissions.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
@@ -933,6 +941,9 @@ PUT /groups/:id
| `membership_lock` **(PREMIUM)** | boolean | no | Users cannot be added to projects in this group. |
| `prevent_forking_outside_group` **(PREMIUM)** | boolean | no | When enabled, users can **not** fork projects from this group to external namespaces. |
| `shared_runners_minutes_limit` **(PREMIUM)** | integer | no | Can be set by administrators only. Maximum number of monthly CI/CD minutes for this group. Can be `nil` (default; inherit system default), `0` (unlimited), or `> 0`. |
+| `unique_project_download_limit` **(ULTIMATE)** | integer | no | Maximum number of unique projects a user can download in the specified time period before they are banned. Available only on top-level groups. Default: 0, Maximum: 10,000. |
+| `unique_project_download_limit_interval_in_seconds` **(ULTIMATE)** | integer | no | Time period during which a user can download a maximum amount of projects before they are banned. Available only on top-level groups. Default: 0, Maximum: 864,000 seconds (10 days). |
+| `unique_project_download_limit_allowlist` **(ULTIMATE)** | array of strings | no | List of usernames excluded from the unique project download limit. Available only on top-level groups. Default: `[]`, Maximum: 100 usernames. |
NOTE:
The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
@@ -1407,6 +1418,155 @@ DELETE /groups/:id/ldap_group_links
NOTE:
To delete the LDAP group link, provide either a `cn` or a `filter`, but not both.
+## SAML Group Links **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290367) in GitLab 15.3.
+
+List, get, add, and delete SAML group links.
+
+### List SAML group links
+
+Lists SAML group links.
+
+```plaintext
+GET /groups/:id/saml_group_links
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:----------|:---------------|:---------|:-------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+
+If successful, returns [`200`](index.md#status-codes) and the following
+response attributes:
+
+| Attribute | Type | Description |
+|:-------------------|:-------|:-------------------------------------------------------------------------------------|
+| `[].name` | string | Name of the SAML group |
+| `[].access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/saml_group_links"
+```
+
+Example response:
+
+```json
+[
+ {
+ "name": "saml-group-1",
+ "access_level": "Guest"
+ },
+ {
+ "name": "saml-group-2",
+ "access_level": "Maintainer"
+ }
+]
+```
+
+### Get SAML group link
+
+Get a SAML group link for the group.
+
+```plaintext
+GET /groups/:id/saml_group_links/:saml_group_name
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:-------------------|:---------------|:---------|:-------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `saml_group_name` | string | yes | Name of an SAML group |
+
+If successful, returns [`200`](index.md#status-codes) and the following
+response attributes:
+
+| Attribute | Type | Description |
+|:---------------|:-------|:-------------------------------------------------------------------------------------|
+| `name` | string | Name of the SAML group |
+| `access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/saml_group_links/saml-group-1"
+```
+
+Example response:
+
+```json
+{
+"name": "saml-group-1",
+"access_level": "Guest"
+}
+```
+
+### Add SAML group link
+
+Adds a SAML group link for a group.
+
+```plaintext
+POST /groups/:id/saml_group_links
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:-------------------|:---------------|:---------|:-------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `saml_group_name` | string | yes | Name of a SAML group |
+| `access_level` | string | yes | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+
+If successful, returns [`201`](index.md#status-codes) and the following
+response attributes:
+
+| Attribute | Type | Description |
+|:---------------|:-------|:-------------------------------------------------------------------------------------|
+| `name` | string | Name of the SAML group |
+| `access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/saml_group_links"
+```
+
+Example response:
+
+```json
+{
+"name": "saml-group-1",
+"access_level": "Guest"
+}
+```
+
+### Delete SAML group link
+
+Deletes a SAML group link for the group.
+
+```plaintext
+DELETE /groups/:id/saml_group_links/:saml_group_name
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|:-------------------|:---------------|:---------|:-------------------------------------------------------------------------|
+| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `saml_group_name` | string | yes | Name of an SAML group |
+
+If successful, returns [`204`](index.md#status-codes) status code without any response body.
+
+Example request:
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/saml_group_links/saml-group-1"
+```
+
## Namespaces in groups
By default, groups only get 20 namespaces at a time because the API results are paginated.
@@ -1435,7 +1595,7 @@ documentation.
## Share Groups with Groups
-These endpoints create and delete links for sharing a group with another group. For more information, see the related discussion in the [GitLab Groups](../user/group/index.md#share-a-group-with-another-group) page.
+These endpoints create and delete links for sharing a group with another group. For more information, see the related discussion in the [GitLab Groups](../user/group/manage.md#share-a-group-with-another-group) page.
### Create a link to share a group with another group
@@ -1471,7 +1631,7 @@ DELETE /groups/:id/share/:group_id
### Get group push rules **(PREMIUM)**
-Get the [push rules](../user/group/index.md#group-push-rules) of a group.
+Get the [push rules](../user/group/access_and_permissions.md#group-push-rules) of a group.
Only available to group owners and administrators.
@@ -1514,7 +1674,7 @@ the `commit_committer_check` and `reject_unsigned_commits` parameters:
### Add group push rule **(PREMIUM)**
-Adds [push rules](../user/group/index.md#group-push-rules) to the specified group.
+Adds [push rules](../user/group/access_and_permissions.md#group-push-rules) to the specified group.
Only available to group owners and administrators.
@@ -1608,7 +1768,7 @@ Response:
### Delete group push rule **(PREMIUM)**
-Deletes the [push rules](../user/group/index.md#group-push-rules) of a group.
+Deletes the [push rules](../user/group/access_and_permissions.md#group-push-rules) of a group.
Only available to group owners and administrators.
diff --git a/doc/api/index.md b/doc/api/index.md
index 26447a2223d..15d0b0fd65f 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -522,11 +522,11 @@ pagination headers.
Keyset-based pagination is supported only for selected resources and ordering
options:
-| Resource | Options | Availability |
-|:---------------------------------------------------------|:---------------------------------|:------------------------------------------------------------------------------------------------------------|
-| [Projects](projects.md) | `order_by=id` only | Authenticated and unauthenticated users |
-| [Groups](groups.md) | `order_by=name`, `sort=asc` only | Unauthenticated users only |
-| [Group audit events](audit_events.md#group-audit-events) | `order_by=id`, `sort=desc` only | Authenticated users only ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/333968) in GitLab 15.2 |
+| Resource | Options | Availability |
+|:---------------------------------------------------------|:---------------------------------|:-------------------------------------------------------------------------------------------------------------|
+| [Projects](projects.md) | `order_by=id` only | Authenticated and unauthenticated users |
+| [Groups](groups.md) | `order_by=name`, `sort=asc` only | Unauthenticated users only |
+| [Group audit events](audit_events.md#group-audit-events) | `order_by=id`, `sort=desc` only | Authenticated users only ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/333968) in GitLab 15.2) |
### Pagination response headers
diff --git a/doc/api/integrations.md b/doc/api/integrations.md
index fca1d02161b..7912f3f6bf7 100644
--- a/doc/api/integrations.md
+++ b/doc/api/integrations.md
@@ -310,17 +310,15 @@ PUT /projects/:id/integrations/datadog
Parameters:
-| Parameter | Type | Required | Description |
-|:-----------------:|:------:|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `api_key` | string | true | API key used for authentication with Datadog. |
-| `api_url` | string | false | (Advanced) The full URL for your Datadog site |
-| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. |
-| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments |
-| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` |
-| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) |
-
-<!-- | `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.7) | -->
-<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
+| Parameter | Type | Required | Description |
+|------------------------|---------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `api_key` | string | true | API key used for authentication with Datadog. |
+| `api_url` | string | false | (Advanced) The full URL for your Datadog site |
+| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. |
+| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments |
+| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` |
+| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) |
+| `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3) |
### Disable Datadog integration
@@ -383,6 +381,51 @@ Get Unify Circuit integration settings for a project.
GET /projects/:id/integrations/unify-circuit
```
+## Pumble
+
+Pumble chat tool.
+
+### Create/Edit Pumble integration
+
+Set Pumble integration for a project.
+
+```plaintext
+PUT /projects/:id/integrations/pumble
+```
+
+Parameters:
+
+| Parameter | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `webhook` | string | true | The Pumble webhook. For example, `https://api.pumble.com/workspaces/x/...`. |
+| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default is `default`. |
+| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events. |
+| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. |
+| `issues_events` | boolean | false | Enable notifications for issue events. |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events. |
+| `note_events` | boolean | false | Enable notifications for note events. |
+| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
+| `pipeline_events` | boolean | false | Enable notifications for pipeline events. |
+| `push_events` | boolean | false | Enable notifications for push events. |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events. |
+| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. |
+
+### Disable Pumble integration
+
+Disable the Pumble integration for a project. Integration settings are preserved.
+
+```plaintext
+DELETE /projects/:id/integrations/pumble
+```
+
+### Get Pumble integration settings
+
+Get Pumble integration settings for a project.
+
+```plaintext
+GET /projects/:id/integrations/pumble
+```
+
## Webex Teams
Webex Teams collaboration tool.
@@ -967,7 +1010,6 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | yes | The Mattermost token |
-| `username` | string | no | The username to use to post the message |
### Disable Mattermost Slash Command integration
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 1f5f4b4c8ae..e2c9fbd878d 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -29,9 +29,9 @@ When requested across groups or projects, it's expected to be the same as the `f
## List issues
-> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
-> The `weight` property moved to GitLab Premium in 13.9.
-> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
+> - The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
+> - The `weight` property moved to GitLab Premium in 13.9.
+> - The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get all issues the authenticated user has access to. By default it
returns only issues created by the current user. To get all issues,
@@ -257,9 +257,9 @@ Please use `iid` of the `epic` attribute instead.
## List group issues
-> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
-> The `weight` property moved to GitLab Premium in 13.9.
-> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
+> - The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
+> - The `weight` property moved to GitLab Premium in 13.9.
+> - The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a group's issues.
@@ -461,9 +461,9 @@ Please use `iid` of the `epic` attribute instead.
## List project issues
-> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
-> The `weight` property moved to GitLab Premium in 13.9.
-> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
+> - The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
+> - The `weight` property moved to GitLab Premium in 13.9.
+> - The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a project's issues.
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index ee9f1678b18..31da0638d23 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -16,11 +16,11 @@ Get the job's artifacts zipped archive of a project.
GET /projects/:id/jobs/:job_id/artifacts
```
-| 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. |
-| `job_id` | integer | yes | ID of a job. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| 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. |
+| `job_id` | integer | yes | ID of a job. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only in a CI/CD job defined in the `.gitlab-ci.yml` file. The value is always `$CI_JOB_TOKEN`. The job associated with the `$CI_JOB_TOKEN` must be running when this token is used. |
Example request using the `PRIVATE-TOKEN` header:
@@ -80,12 +80,12 @@ GET /projects/:id/jobs/artifacts/:ref_name/download?job=name
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. |
-| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
-| `job` | string | yes | The name of the job. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| 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. |
+| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
+| `job` | string | yes | The name of the job. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only in a CI/CD job defined in the `.gitlab-ci.yml` file. The value is always `$CI_JOB_TOKEN`. The job associated with the `$CI_JOB_TOKEN` must be running when this token is used. |
Example request using the `PRIVATE-TOKEN` header:
@@ -141,12 +141,12 @@ GET /projects/:id/jobs/:job_id/artifacts/*artifact_path
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. |
-| `job_id` | integer | yes | The unique job identifier. |
-| `artifact_path` | string | yes | Path to a file inside the artifacts archive. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| 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. |
+| `job_id` | integer | yes | The unique job identifier. |
+| `artifact_path` | string | yes | Path to a file inside the artifacts archive. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only in a CI/CD job defined in the `.gitlab-ci.yml` file. The value is always `$CI_JOB_TOKEN`. The job associated with the `$CI_JOB_TOKEN` must be running when this token is used. |
Example request:
@@ -185,13 +185,13 @@ GET /projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name
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. |
-| `ref_name` | string | yes | Branch or tag name in repository. `HEAD` or `SHA` references are not supported. |
-| `artifact_path` | string | yes | Path to a file inside the artifacts archive. |
-| `job` | string | yes | The name of the job. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| 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. |
+| `ref_name` | string | yes | Branch or tag name in repository. `HEAD` or `SHA` references are not supported. |
+| `artifact_path` | string | yes | Path to a file inside the artifacts archive. |
+| `job` | string | yes | The name of the job. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/jobs/ci_job_token.md#download-an-artifact-from-a-different-pipeline) for multi-project pipelines. It should be invoked only in a CI/CD job defined in the `.gitlab-ci.yml` file. The value is always `$CI_JOB_TOKEN`. The job associated with the `$CI_JOB_TOKEN` must be running when this token is used. |
Example request:
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index b23c33ddc0d..647f8eafa62 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -19,7 +19,7 @@ GET /projects/:id/jobs
| Attribute | Type | Required | Description |
|-----------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
-| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --globoff --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running"
@@ -167,7 +167,7 @@ GET /projects/:id/pipelines/:pipeline_id/jobs
|-------------------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. Can also be obtained in CI jobs via the [predefined CI variable](../ci/variables/predefined_variables.md) `CI_PIPELINE_ID`. |
-| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
| `include_retried` | boolean | **{dotted-circle}** No | Include retried jobs in the response. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/272627) in GitLab 13.9. |
```shell
@@ -324,7 +324,7 @@ GET /projects/:id/pipelines/:pipeline_id/bridges
|---------------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. |
-| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
+| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/6/bridges?scope[]=pending&scope[]=running"
@@ -700,7 +700,7 @@ Example of response
"stage": "test",
"status": "canceled",
"tag": false,
- "web_url": "https://example.com/foo/bar/-/jobs/42",
+ "web_url": "https://example.com/foo/bar/-/jobs/1",
"user": null
}
```
@@ -750,7 +750,7 @@ Example of response
"stage": "test",
"status": "pending",
"tag": false,
- "web_url": "https://example.com/foo/bar/-/jobs/42",
+ "web_url": "https://example.com/foo/bar/-/jobs/1",
"user": null
}
```
@@ -805,7 +805,7 @@ Example of response
"queued_duration": 0.010,
"status": "failed",
"tag": false,
- "web_url": "https://example.com/foo/bar/-/jobs/42",
+ "web_url": "https://example.com/foo/bar/-/jobs/1",
"user": null
}
```
@@ -881,7 +881,7 @@ Example response:
"stage": "test",
"status": "pending",
"tag": false,
- "web_url": "https://example.com/foo/bar/-/jobs/42",
+ "web_url": "https://example.com/foo/bar/-/jobs/1",
"user": null
}
```
diff --git a/doc/api/lint.md b/doc/api/lint.md
index d5aa6af0e34..ff7aa2f1fb9 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -17,8 +17,7 @@ and:
- Does not have an [allowlist or denylist](../user/admin_area/settings/sign_up_restrictions.md#allow-or-deny-sign-ups-using-specific-email-domains).
- Does not [require administrator approval for new sign ups](../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups).
-- Does not have additional [sign up
- restrictions](../user/admin_area/settings/sign_up_restrictions.html#sign-up-restrictions).
+- Does not have additional [sign up restrictions](../user/admin_area/settings/sign_up_restrictions.md).
Otherwise, authentication is required.
diff --git a/doc/api/markdown.md b/doc/api/markdown.md
index c128e8512df..b66a07dc1d5 100644
--- a/doc/api/markdown.md
+++ b/doc/api/markdown.md
@@ -1,13 +1,27 @@
---
-stage: Create
-group: Source Code
+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
---
# Markdown API **(FREE)**
+Convert Markdown content to HTML.
+
Available only in APIv4.
+## Required authentication
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93727) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `authenticate_markdown_api`. Enabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is enabled and authentication is required.
+To remove the requirement to authenticate, ask an administrator to
+[disable the feature flag](../administration/feature_flags.md) named `authenticate_markdown_api`.
+On GitLab.com, this feature is available.
+
+All API calls to the Markdown API must be [authenticated](index.md#authentication).
+
## Render an arbitrary Markdown document
```plaintext
@@ -18,10 +32,12 @@ POST /markdown
| --------- | ------- | ------------- | ------------------------------------------ |
| `text` | string | yes | The Markdown text to render |
| `gfm` | boolean | no | Render text using GitLab Flavored Markdown. Default is `false` |
-| `project` | string | no | Use `project` as a context when creating references using GitLab Flavored Markdown. [Authentication](index.md#authentication) is required if a project is not public. |
+| `project` | string | no | Use `project` as a context when creating references using GitLab Flavored Markdown |
```shell
-curl --header Content-Type:application/json --data '{"text":"Hello world! :tada:", "gfm":true, "project":"group_example/project_example"}' "https://gitlab.example.com/api/v4/markdown"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type:application/json" \
+ --data '{"text":"Hello world! :tada:", "gfm":true, "project":"group_example/project_example"}' "https://gitlab.example.com/api/v4/markdown"
```
Response example:
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index 37a926366df..1d99c323946 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -79,6 +79,8 @@ POST /projects/:id/approvals
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
> - `protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab 12.7.
+> - Pagination support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31011) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `approval_rules_pagination`. Enabled by default.
+> - `applies_to_all_protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3.
You can request information about a project's approval rules using the following endpoint:
@@ -86,6 +88,8 @@ You can request information about a project's approval rules using the following
GET /projects/:id/approval_rules
```
+Use the `page` and `per_page` [pagination](index.md#offset-based-pagination) parameters to restrict the list of approval rules.
+
**Parameters:**
| Attribute | Type | Required | Description |
@@ -145,6 +149,7 @@ GET /projects/:id/approval_rules
"ldap_access": null
}
],
+ "applies_to_all_protected_branches": false,
"protected_branches": [
{
"id": 1,
@@ -177,7 +182,8 @@ GET /projects/:id/approval_rules
### Get a single project-level rule
-> Introduced in GitLab 13.7.
+> - Introduced in GitLab 13.7.
+> - `applies_to_all_protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3.
You can request information about a single project approval rules using the following endpoint:
@@ -244,6 +250,7 @@ GET /projects/:id/approval_rules/:approval_rule_id
"ldap_access": null
}
],
+ "applies_to_all_protected_branches": false,
"protected_branches": [
{
"id": 1,
@@ -278,6 +285,7 @@ GET /projects/:id/approval_rules/:approval_rule_id
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
> - [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357300) the Vulnerability-Check feature in GitLab 15.0.
+> - `applies_to_all_protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3.
You can create project approval rules using the following endpoint:
@@ -287,16 +295,17 @@ POST /projects/:id/approval_rules
**Parameters:**
-| Attribute | Type | Required | Description |
-|------------------------|---------|----------|------------------------------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `name` | string | yes | The name of the approval rule |
-| `approvals_required` | integer | yes | The number of required approvals for this rule |
-| `rule_type` | string | no | The type of rule. `any_approver` is a pre-configured default rule with `approvals_required` at `0`. Other rules are `regular`.
-| `user_ids` | Array | no | The ids of users as approvers |
-| `group_ids` | Array | no | The ids of groups as approvers |
-| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
-| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `license_scanning` and `code_coverage`.|
+| Attribute | Type | Required | Description |
+|-------------------------------------|-------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
+| `name` | string | yes | The name of the approval rule |
+| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `license_scanning` and `code_coverage`. |
+| `approvals_required` | integer | yes | The number of required approvals for this rule |
+| `rule_type` | string | no | The type of rule. `any_approver` is a pre-configured default rule with `approvals_required` at `0`. Other rules are `regular`. |
+| `user_ids` | Array | no | The ids of users as approvers |
+| `group_ids` | Array | no | The ids of groups as approvers |
+| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `applies_to_all_protected_branches` | boolean | no | Whether the rule is applied to all protected branches. If set to `true`, the value of `protected_branch_ids` is ignored. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3. |
```json
{
@@ -350,6 +359,7 @@ POST /projects/:id/approval_rules
"ldap_access": null
}
],
+ "applies_to_all_protected_branches": false,
"protected_branches": [
{
"id": 1,
@@ -401,6 +411,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11877) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
> - [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357300) the Vulnerability-Check feature in GitLab 15.0.
+> - `applies_to_all_protected_branches` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3.
You can update project approval rules using the following endpoint:
@@ -412,15 +423,16 @@ PUT /projects/:id/approval_rules/:approval_rule_id
**Parameters:**
-| Attribute | Type | Required | Description |
-|------------------------|---------|----------|------------------------------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `approval_rule_id` | integer | yes | The ID of a approval rule |
-| `name` | string | yes | The name of the approval rule |
-| `approvals_required` | integer | yes | The number of required approvals for this rule |
-| `user_ids` | Array | no | The ids of users as approvers |
-| `group_ids` | Array | no | The ids of groups as approvers |
-| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| Attribute | Type | Required | Description |
+|-------------------------------------|-------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
+| `approval_rule_id` | integer | yes | The ID of a approval rule |
+| `name` | string | yes | The name of the approval rule |
+| `approvals_required` | integer | yes | The number of required approvals for this rule |
+| `user_ids` | Array | no | The ids of users as approvers |
+| `group_ids` | Array | no | The ids of groups as approvers |
+| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `applies_to_all_protected_branches` | boolean | no | Whether the rule is applied to all protected branches. If set to `true`, the value of `protected_branch_ids` is ignored. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335316) in GitLab 15.3. |
```json
{
@@ -474,6 +486,7 @@ PUT /projects/:id/approval_rules/:approval_rule_id
"ldap_access": null
}
],
+ "applies_to_all_protected_branches": false,
"protected_branches": [
{
"id": 1,
@@ -516,10 +529,10 @@ DELETE /projects/:id/approval_rules/:approval_rule_id
**Parameters:**
-| Attribute | Type | Required | Description |
-|----------------------|---------|----------|-----------------------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `approval_rule_id` | integer | yes | The ID of a approval rule
+| Attribute | Type | Required | Description |
+|--------------------|-------------------|----------|------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
+| `approval_rule_id` | integer | yes | The ID of a approval rule |
## Merge request-level MR approvals
@@ -538,10 +551,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/approvals
**Parameters:**
-| Attribute | Type | Required | Description |
-|---------------------|---------|----------|---------------------|
+| Attribute | Type | Required | Description |
+|---------------------|-------------------|----------|------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `merge_request_iid` | integer | yes | The IID of MR |
+| `merge_request_iid` | integer | yes | The IID of MR |
```json
{
@@ -584,11 +597,11 @@ POST /projects/:id/merge_requests/:merge_request_iid/approvals
**Parameters:**
-| Attribute | Type | Required | Description |
-|----------------------|---------|----------|--------------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `merge_request_iid` | integer | yes | The IID of MR |
-| `approvals_required` | integer | yes | Approvals required before MR can be merged. Deprecated in 12.0 in favor of Approval Rules API. |
+| Attribute | Type | Required | Description |
+|----------------------|-------------------|----------|------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of MR |
+| `approvals_required` | integer | yes | Approvals required before MR can be merged. Deprecated in 12.0 in favor of Approval Rules API. |
```json
{
@@ -626,10 +639,10 @@ This includes additional information about the users who have already approved
**Parameters:**
-| Attribute | Type | Required | Description |
-|----------------------|---------|----------|---------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
-| `merge_request_iid` | integer | yes | The IID of MR |
+| Attribute | Type | Required | Description |
+|---------------------|-------------------|----------|------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of MR |
```json
{
@@ -684,6 +697,7 @@ This includes additional information about the users who have already approved
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13712) in GitLab 12.3.
> - Moved to GitLab Premium in 13.9.
+> - Pagination support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31011) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `approval_rules_pagination`. Enabled by default.
You can request information about a merge request's approval rules using the following endpoint:
@@ -691,6 +705,8 @@ You can request information about a merge request's approval rules using the fol
GET /projects/:id/merge_requests/:merge_request_iid/approval_rules
```
+Use the `page` and `per_page` [pagination](index.md#offset-based-pagination) parameters to restrict the list of approval rules.
+
**Parameters:**
| Attribute | Type | Required | Description |
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index c6714459643..a491756e5f0 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -825,6 +825,66 @@ Parameters:
]
```
+## Get single MR reviewers
+
+Get a list of merge request reviewers.
+
+```plaintext
+GET /projects/:id/merge_requests/:merge_request_iid/reviewers
+```
+
+Parameters:
+
+| 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. |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request. |
+
+```json
+[
+ {
+ "user": {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ },
+ "updated_state_by": {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ },
+ "state": "unreviewed",
+ "created_at": "2022-07-27T17:03:27.684Z"
+ },
+ {
+ "user": {
+ "id": 2,
+ "name": "John Doe2",
+ "username": "user2",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
+ "web_url": "http://localhost/user2"
+ },
+ "updated_state_by": {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ },
+ "state": "reviewed",
+ "created_at": "2022-07-27T17:03:27.684Z"
+ }
+]
+```
+
## Get single MR commits
Get a list of merge request commits.
@@ -1624,9 +1684,9 @@ This API returns specific HTTP status codes on failure:
| HTTP Status | Message | Reason |
|:------------|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
| `401` | `Unauthorized` | This user does not have permission to accept this merge request. |
-| `405` | `Method Not Allowed` | The merge request cannot be accepted because it is `Draft`, `Closed`, `Pipeline Pending Completion`, or `Failed`. `Success` is required. |
-| `406` | `Branch cannot be merged` | The merge request can not be merged. |
+| `405` | `Method Not Allowed` | The merge request is not able to be merged. |
| `409` | `SHA does not match HEAD of source branch` | The provided `sha` parameter does not match the HEAD of the source. |
+| `422` | `Branch cannot be merged` | The merge request failed to merge. |
For additional important notes on response data, read [Single merge request response notes](#single-merge-request-response-notes).
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 3972a46d7fc..50c97d55f45 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Namespaces API **(FREE)**
Usernames and group names fall under a special category called
-[namespaces](../user/group/index.md#namespaces).
+[namespaces](../user/namespace/index.md).
For users and groups supported API calls see the [users](users.md) and
[groups](groups.md) documentation respectively.
diff --git a/doc/api/notes.md b/doc/api/notes.md
index f7caae59b4d..e0799cdd380 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -11,7 +11,7 @@ Notes are comments on:
- Snippets
- Issues
- Merge requests
-- Epics **(PREMIUM)**
+- [Epics](../user/group/epics/index.md)
This includes system notes, which are notes about changes to the object (for example, when an
assignee changes, GitLab posts a system note).
@@ -80,7 +80,8 @@ GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at
"noteable_type": "Issue",
"noteable_iid": 377,
"resolvable": false,
- "confidential": false
+ "confidential": false,
+ "internal": false
},
{
"id": 305,
@@ -101,7 +102,8 @@ GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at
"noteable_type": "Issue",
"noteable_iid": 121,
"resolvable": false,
- "confidential": true
+ "confidential": true,
+ "internal": true
}
]
```
@@ -145,7 +147,8 @@ Parameters:
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `issue_iid` | integer | yes | The IID of an issue. |
| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
-| `confidential` | boolean | no | The confidential flag of a note. Default is false. |
+| `confidential` | boolean | no | **Deprecated:** will be removed in GitLab 16.0 and renamed to `internal`. The confidential flag of a note. Default is false. |
+| `internal` | boolean | no | The internal flag of a note. Overrides `confidential` when both parameters are submitted. Default is false. |
| `created_at` | string | no | Date time string, ISO 8601 formatted. It must be after 1970-01-01. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
@@ -378,7 +381,8 @@ Parameters:
"noteable_type": "MergeRequest",
"noteable_iid": 2,
"resolvable": false,
- "confidential": false
+ "confidential": false,
+ "internal": false
}
```
@@ -447,7 +451,7 @@ Parameters:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602"
```
-## Epics **(ULTIMATE)**
+## Epics **(PREMIUM)**
### List all epic notes
@@ -506,7 +510,8 @@ Parameters:
"expires_at": null,
"updated_at": "2013-10-02T07:34:20Z",
"created_at": "2013-10-02T07:34:20Z",
- "confidential": false
+ "confidential": false,
+ "internal": false
}
```
@@ -530,7 +535,8 @@ Parameters:
| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
| `epic_id` | integer | yes | The ID of an epic |
| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
-| `confidential` | boolean | no | The confidential flag of a note. Default is `false`. |
+| `confidential` | boolean | no | **Deprecated:** will be removed in GitLab 16.0 and is renamed to `internal`. The confidential flag of a note. Default is `false`. |
+| `internal` | boolean | no | The internal flag of a note. Overrides `confidential` when both parameters are submitted. Default is `false`. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/notes?body=note"
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 35c6eb4a982..12704f6fc87 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -26,9 +26,12 @@ support [CORS preflight requests](https://developer.mozilla.org/en-US/docs/Web/H
- `/oauth/token`
- `/oauth/userinfo`
-In addition to the headers listed for [simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests),
-only the `Authorization` header can be used for preflight requests. For example, the `X-Requested-With` header
-can't be used for preflight requests.
+Only certain headers can be used for preflight requests:
+
+- The headers listed for [simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests).
+- The `Authorization` header.
+
+For example, the `X-Requested-With` header can't be used for preflight requests.
## Supported OAuth 2.0 flows
@@ -258,8 +261,8 @@ Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.3) for a
detailed flow description.
NOTE:
-The Resource Owner Password Credentials is disabled for users with [two-factor
-authentication](../user/profile/account/two_factor_authentication.md) turned on.
+The Resource Owner Password Credentials is disabled for users with
+[two-factor authentication](../user/profile/account/two_factor_authentication.md) turned on.
These users can access the API using [personal access tokens](../user/profile/personal_access_tokens.md)
instead.
diff --git a/doc/api/packages.md b/doc/api/packages.md
index 9d9c21546cd..3cd93bd09c1 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Packages API **(FREE)**
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/349418) support for [GitLab CI/CD job token](../ci/jobs/ci_job_token.md) authentication for the project-level API in GitLab 15.3.
+
This is the API documentation of [GitLab Packages](../administration/packages/index.md).
## List packages
diff --git a/doc/api/packages/conan.md b/doc/api/packages/conan.md
index 1590893d006..3ac2eeb40b1 100644
--- a/doc/api/packages/conan.md
+++ b/doc/api/packages/conan.md
@@ -38,8 +38,8 @@ The examples in this document all use the instance-level prefix.
/packages/conan/v1
```
-When using the instance-level routes, be aware that there is a [naming
-restriction](../../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)
+When using the instance-level routes, be aware that there is a
+[naming restriction](../../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)
for Conan recipes.
### Project-level
diff --git a/doc/api/packages/terraform-modules.md b/doc/api/packages/terraform-modules.md
new file mode 100644
index 00000000000..24db7094a3c
--- /dev/null
+++ b/doc/api/packages/terraform-modules.md
@@ -0,0 +1,230 @@
+---
+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
+---
+
+# Terraform Registry API **(FREE)**
+
+This is the API documentation for [Terraform Modules](../../user/packages/terraform_module_registry/index.md).
+
+WARNING:
+This API is used by the [terraform cli](https://www.terraform.io/)
+and is generally not meant for manual consumption.
+
+For instructions on how to upload and install Maven packages from the GitLab
+package registry, see the [Terraform modules registry documentation](../../user/packages/terraform_module_registry/index.md).
+
+## List available versions for a specific module
+
+Get a list of available versions for a specific module.
+
+```plaintext
+GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/versions
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `module_namespace` | string | yes | The group to which Terraform module's project 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"
+```
+
+Example response:
+
+```shell
+{
+ "modules": [
+ {
+ "versions": [
+ {
+ "version": "1.0.0",
+ "submodules": [],
+ "root": {
+ "dependencies": [],
+ "providers": [
+ {
+ "name": "local",
+ "version":""
+ }
+ ]
+ }
+ },
+ {
+ "version": "0.9.3",
+ "submodules": [],
+ "root": {
+ "dependencies": [],
+ "providers": [
+ {
+ "name": "local",
+ "version":""
+ }
+ ]
+ }
+ }
+ ],
+ "source": "https://gitlab.example.com/group/hello-world"
+ }
+ ]
+}
+```
+
+## Latest version for a specific module
+
+Get information about the latest version for a given module.
+
+```plaintext
+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_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"
+```
+
+Example response:
+
+```shell
+{
+ "name": "hellow-world/local",
+ "provider": "local",
+ "providers": [
+ "local"
+ ],
+ "root": {
+ "dependencies": []
+ },
+ "source": "https://gitlab.example.com/group/hello-world",
+ "submodules": [],
+ "version": "1.0.0",
+ "versions": [
+ "1.0.0"
+ ]
+}
+```
+
+## Get specific version for a specific module
+
+Get information about the latest version for a given module.
+
+```plaintext
+GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/1.0.0
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `module_namespace` | string | yes | The group to which Terraform module's project 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/1.0.0"
+```
+
+Example response:
+
+```shell
+{
+ "name": "hellow-world/local",
+ "provider": "local",
+ "providers": [
+ "local"
+ ],
+ "root": {
+ "dependencies": []
+ },
+ "source": "https://gitlab.example.com/group/hello-world",
+ "submodules": [],
+ "version": "1.0.0",
+ "versions": [
+ "1.0.0"
+ ]
+}
+```
+
+## Get URL for downloading latest module version
+
+Get the download URL for latest module version in `X-Terraform-Get` header
+
+```plaintext
+GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/download
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `module_namespace` | string | yes | The group to which Terraform module's project 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/download"
+```
+
+Example response:
+
+```shell
+HTTP/1.1 204 No Content
+Content-Length: 0
+X-Terraform-Get: /api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file?token=&archive=tgz
+```
+
+Under the hood, this API endpoint redirects to `packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/:module_version/download`
+
+## Get URL for downloading specific module version
+
+Get the download URL for a specific module version in `X-Terraform-Get` header
+
+```plaintext
+GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/:module_version/download
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `module_namespace` | string | yes | The group to which Terraform module's project 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). |
+| `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"
+```
+
+Example response:
+
+```shell
+HTTP/1.1 204 No Content
+Content-Length: 0
+X-Terraform-Get: /api/v4/packages/terraform/modules/v1/group/hello-world/local/1.0.0/file?token=&archive=tgz
+```
+
+## Download module
+
+```plaintext
+GET packages/terraform/modules/v1/:module_namespace/:module_name/:module_system/:module_version/file
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `module_namespace` | string | yes | The group to which Terraform module's project 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). |
+| `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"
+```
+
+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
+```
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index 46a4c674560..620b5c2ed0b 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -91,7 +91,12 @@ curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
### Responses
-- `401: Unauthorized` if the user doesn't have access to the token they're requesting the ID or if the token with matching ID doesn't exist.
+> `404` HTTP status code [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93650) in GitLab 15.3.
+
+- `401: Unauthorized` if either:
+ - The user doesn't have access to the token with the specified ID.
+ - 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.
## Revoke a personal access token
diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md
index 625a92f9b89..bbaf38aaaae 100644
--- a/doc/api/pipeline_schedules.md
+++ b/doc/api/pipeline_schedules.md
@@ -101,6 +101,60 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
}
```
+## Get all pipelines triggered by a pipeline schedule
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368566) in GitLab 15.3.
+
+Get all pipelines triggered by a pipeline schedule in a project.
+
+```plaintext
+GET /projects/:id/pipeline_schedules/:pipeline_schedule_id/pipelines
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|------------------------|----------------|----------|-------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `pipeline_schedule_id` | integer | yes | The pipeline schedule ID. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/29/pipeline_schedules/13/pipelines"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 47,
+ "iid": 12,
+ "project_id": 29,
+ "status": "pending",
+ "source": "scheduled",
+ "ref": "new-pipeline",
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47",
+ "created_at": "2016-08-11T11:28:34.085Z",
+ "updated_at": "2016-08-11T11:32:35.169Z"
+ },
+ {
+ "id": 48,
+ "iid": 13,
+ "project_id": 29,
+ "status": "pending",
+ "source": "scheduled",
+ "ref": "new-pipeline",
+ "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
+ "web_url": "https://example.com/foo/bar/pipelines/48",
+ "created_at": "2016-08-12T10:06:04.561Z",
+ "updated_at": "2016-08-12T10:09:56.223Z"
+ }
+]
+```
+
## Create a new pipeline schedule
Create a new pipeline schedule of a project.
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 99009b6913d..2e601f6e24a 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -281,7 +281,7 @@ POST /projects/:id/pipeline
|-------------|---------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `ref` | string | yes | The branch or tag to run the pipeline on. |
-| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key': 'UPLOAD_TO_S3', 'variable_type': 'file', 'value': 'true' }, {'key': 'TEST', 'value': 'test variable'}]`. If `variable_type` is excluded, it defaults to `env_var`. |
+| `variables` | array | 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`. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=main"
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 635cb04e2e8..49a9b68227d 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -15,10 +15,18 @@ See also:
Start a new export.
-The endpoint also accepts an `upload` parameter. This parameter is a hash. It contains
-all the necessary information to upload the exported project to a web server or
-to any S3-compatible platform. At the moment we only support binary
-data file uploads to the final server.
+The endpoint also accepts an `upload` hash parameter. It contains all the necessary information to upload the exported
+project to a web server or to any S3-compatible platform. For exports, GitLab:
+
+- Only supports binary data file uploads to the final server.
+- Sends the `Content-Type: application/gzip` header with upload requests. Ensure that your pre-signed URL includes this
+ as part of the signature.
+- Can take some time to complete the project export process. Make sure the upload URL doesn't have a short expiration
+ time and is available throughout the export process.
+- Administrators can modify the maximum export file size. By default, the maximum is unlimited (`0`). To change this,
+ edit `max_export_size` using either:
+ - [Application settings API](settings.md#change-application-settings)
+ - [GitLab UI](../user/admin_area/settings/account_and_limit_settings.md).
The `upload[url]` parameter is required if the `upload` parameter is present.
@@ -46,15 +54,6 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
}
```
-NOTE:
-The upload request is sent with `Content-Type: application/gzip` header. Ensure that your pre-signed URL includes this as part of the signature.
-
-NOTE:
-As an administrator, you can modify the maximum export file size. By default,
-it is set to `0`, for unlimited. To change this value, edit `max_export_size`
-in the [Application settings API](settings.md#change-application-settings)
-or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md).
-
## Export status
Get the status of export.
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index 4c0a1890729..7763087e759 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -20,7 +20,7 @@ It deprecates these endpoints, which are scheduled for removal in API version 5.
In addition to templates common to the entire instance, project-specific
templates are also available from this API endpoint.
-Support is also available for [group-level file templates](../user/group/index.md#group-file-templates). **(PREMIUM)**
+Support is also available for [group-level file templates](../user/group/manage.md#group-file-templates). **(PREMIUM)**
## Get all templates of a particular type
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 8a8fe522b63..75eea394a40 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -48,7 +48,6 @@ GET /projects
| Attribute | Type | Required | Description |
|--------------------------------------------|----------|------------------------|-------------|
| `archived` | boolean | **{dotted-circle}** No | Limit by archived status. |
-| `build_coverage_regex` | string | **{dotted-circle}** No | Test coverage parsing. (`deprecated`, it is [scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/357401)) |
| `id_after` | integer | **{dotted-circle}** No | Limit results to projects with IDs greater than the specified ID. |
| `id_before` | integer | **{dotted-circle}** No | Limit results to projects with IDs less than the specified ID. |
| `imported` | boolean | **{dotted-circle}** No | Limit results to projects which were imported from external systems by current user. |
@@ -124,7 +123,7 @@ Example response:
"parent_id": null,
"avatar_url": null,
"web_url": "https://gitlab.example.com/diaspora"
- }
+ }
},
{
...
@@ -223,12 +222,12 @@ When the user is authenticated and `simple` is not set this returns something li
"open_issues_count": 0,
"ci_default_git_depth": 20,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_job_token_scope_enabled": false,
"ci_separated_caches": true,
"public_jobs": true,
"build_timeout": 3600,
"auto_cancel_pending_pipelines": "enabled",
- "build_coverage_regex": null,
"ci_config_path": "",
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
@@ -405,6 +404,7 @@ GET /users/:user_id/projects
"runners_token": "b8547b1dc37721d05889db52fa2f02",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_separated_caches": true,
"public_jobs": true,
"shared_with_groups": [],
@@ -513,6 +513,7 @@ GET /users/:user_id/projects
"runners_token": "b8547b1dc37721d05889db52fa2f02",
"ci_default_git_depth": 0,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_separated_caches": true,
"public_jobs": true,
"shared_with_groups": [],
@@ -920,6 +921,7 @@ GET /projects/:id
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_separated_caches": true,
"public_jobs": true,
"shared_with_groups": [
@@ -1360,6 +1362,7 @@ Supported attributes:
| `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. |
| `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#limit-the-number-of-changes-fetched-during-clone). |
| `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending |
+| `ci_allow_fork_pipelines_to_run_in_parent_project` | boolean | **{dotted-circle}** No | Enable or disable [running pipelines in the parent project for merge requests from forks](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project). _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325189) in GitLab 15.3.)_ |
| `ci_separated_caches` | boolean | **{dotted-circle}** No | Set whether or not caches should be [separated](../ci/caching/index.md#cache-key-names) by branch protection status. |
| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). |
| `container_registry_access_level` | string | **{dotted-circle}** No | Set visibility of container registry, for this project, to one of `disabled`, `private` or `enabled`. |
@@ -1936,6 +1939,7 @@ Example response:
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_separated_caches": true,
"public_jobs": true,
"shared_with_groups": [],
@@ -2062,6 +2066,7 @@ Example response:
"runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
+ "ci_allow_fork_pipelines_to_run_in_parent_project": true,
"ci_separated_caches": true,
"public_jobs": true,
"shared_with_groups": [],
@@ -2102,7 +2107,7 @@ This endpoint:
is applied if enabled.
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
[Premium or higher](https://about.gitlab.com/pricing/) tiers, group
- administrators can [configure](../user/group/index.md#enable-delayed-project-deletion)
+ administrators can [configure](../user/group/manage.md#enable-delayed-project-deletion)
projects within a group to be deleted after a delayed period. When enabled,
actual deletion happens after the number of days specified in the
[default deletion delay](../user/admin_area/settings/visibility_and_access_controls.md#deletion-protection).
@@ -2110,7 +2115,7 @@ This endpoint:
WARNING:
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)
in GitLab 12.6 was changed to [Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382)
-in GitLab 13.2, as discussed in [Enable delayed project deletion](../user/group/index.md#enable-delayed-project-deletion).
+in GitLab 13.2, as discussed in [Enable delayed project deletion](../user/group/manage.md#enable-delayed-project-deletion).
```plaintext
DELETE /projects/:id
@@ -2699,7 +2704,6 @@ Example response:
"public_jobs": true,
"build_timeout": 3600,
"auto_cancel_pending_pipelines": "enabled",
- "build_coverage_regex": null, // deprecated, it is scheduled to be removed https://gitlab.com/gitlab-org/gitlab/-/issues/357401
"ci_config_path": null,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index 7489d0bdc9e..1332eea26c0 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -384,7 +384,7 @@ POST /projects/:id/releases
| `assets:links` | array of hash | no | An array of assets links. |
| `assets:links:name`| string | required by: `assets:links` | The name of the link. Link names must be unique within the release. |
| `assets:links:url` | string | required by: `assets:links` | The URL of the link. Link URLs must be unique within the release. |
-| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
+| `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets).
| `assets:links:link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`.
| `released_at` | datetime | no | The date when the release is/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
@@ -740,4 +740,15 @@ Example response:
A release with a `released_at` attribute set to a future date is labeled
as an **Upcoming Release** [in the UI](../../user/project/releases/index.md#upcoming-releases).
-Additionally, if a [release is requested from the API](#list-releases), for each release with a `release_at` attribute set to a future date, an additional attribute `upcoming_release` (set to true) will be returned as part of the response.
+Additionally, if a [release is requested from the API](#list-releases), for each release with a `release_at` attribute set to a future date, an additional attribute `upcoming_release` (set to true) is returned as part of the response.
+
+## Historical releases
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199429) in GitLab 15.2.
+
+A release with a `released_at` attribute set to a past date is labeled
+as an **Historical release** [in the UI](../../user/project/releases/index.md#historical-releases).
+
+Additionally, if a [release is requested from the API](#list-releases), for each
+release with a `release_at` attribute set to a past date, an additional
+attribute `historical_release` (set to true) is returned as part of the response.
diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md
index c239d06ecfd..f9e07991948 100644
--- a/doc/api/releases/links.md
+++ b/doc/api/releases/links.md
@@ -93,14 +93,14 @@ Create an asset as a link from a Release.
POST /projects/:id/releases/:tag_name/assets/links
```
-| Attribute | Type | Required | Description |
-| ------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag associated with the Release. |
-| `name` | string | yes | The name of the link. Link names must be unique within the release. |
-| `url` | string | yes | The URL of the link. Link URLs must be unique within the release. |
-| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets). |
-| `link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. |
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|---------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../index.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag associated with the Release. |
+| `name` | string | yes | The name of the link. Link names must be unique in the release. |
+| `url` | string | yes | The URL of the link. Link URLs must be unique in the release. |
+| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets). |
+| `link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. |
Example request:
@@ -141,7 +141,7 @@ PUT /projects/:id/releases/:tag_name/assets/links/:link_id
| `link_id` | integer | yes | The ID of the link. |
| `name` | string | no | The name of the link. |
| `url` | string | no | The URL of the link. |
-| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets).
+| `filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/release_fields.md#permanent-links-to-release-assets).
| `link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. |
NOTE:
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 34b86902271..bf2ead43519 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -125,8 +125,8 @@ Supported attributes:
## Get file archive
-> Support for [including Git LFS blobs](../topics/git/lfs/index.md#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
-> Support for downloading a subfolder was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28827) in GitLab 14.4.
+> - Support for [including Git LFS blobs](../topics/git/lfs/index.md#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5.
+> - Support for downloading a subfolder was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28827) in GitLab 14.4.
Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
@@ -319,7 +319,7 @@ Supported attributes:
| `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`. |
-| `config_file` | string | no | The path of changelog configuration file in the project's Git repository, defaults to `.gitlab/changelog_config.yml`. |
+| `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. |
@@ -342,9 +342,8 @@ tags using these formats:
- `vX.Y.Z`
- `X.Y.Z`
-Where `X.Y.Z` is a version that follows [semantic
-versioning](https://semver.org/). For example, consider a project with the
-following tags:
+Where `X.Y.Z` is a version that follows [semantic versioning](https://semver.org/).
+For example, consider a project with the following tags:
- v1.0.0-pre1
- v1.0.0
diff --git a/doc/api/resource_iteration_events.md b/doc/api/resource_iteration_events.md
index f4463a4746d..37a945b140e 100644
--- a/doc/api/resource_iteration_events.md
+++ b/doc/api/resource_iteration_events.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229463) in GitLab 13.5.
> - Moved to GitLab Premium in 13.9.
-Resource iteration events keep track of what happens to GitLab [issues](../user/project/issues/).
+Resource iteration events keep track of what happens to GitLab [issues](../user/project/issues/index.md).
Use them to track which iteration was set, who did it, and when it happened.
diff --git a/doc/api/resource_milestone_events.md b/doc/api/resource_milestone_events.md
index 75ecd986e4c..448ec6e2c1d 100644
--- a/doc/api/resource_milestone_events.md
+++ b/doc/api/resource_milestone_events.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31720) in GitLab 13.1.
Resource [milestone](../user/project/milestones/index.md) events keep track of what happens to
-GitLab [issues](../user/project/issues/) and [merge requests](../user/project/merge_requests/).
+GitLab [issues](../user/project/issues/index.md) and [merge requests](../user/project/merge_requests/index.md).
Use them to track which milestone was added or removed, who did it, and when it happened.
diff --git a/doc/api/resource_state_events.md b/doc/api/resource_state_events.md
index 950d82a92a4..b2e886618d5 100644
--- a/doc/api/resource_state_events.md
+++ b/doc/api/resource_state_events.md
@@ -8,8 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35210/) in GitLab 13.2.
-Resource state events keep track of what happens to GitLab [issues](../user/project/issues/) and
-[merge requests](../user/project/merge_requests/).
+Resource state events keep track of what happens to GitLab [issues](../user/project/issues/index.md) and
+[merge requests](../user/project/merge_requests/index.md).
Use them to track which state was set, who did it, and when it happened.
diff --git a/doc/api/resource_weight_events.md b/doc/api/resource_weight_events.md
index 8f11f0c984b..faa2d543c50 100644
--- a/doc/api/resource_weight_events.md
+++ b/doc/api/resource_weight_events.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32542) in GitLab 13.2.
-Resource weight events keep track of what happens to GitLab [issues](../user/project/issues/).
+Resource weight events keep track of what happens to GitLab [issues](../user/project/issues/index.md).
Use them to track which weight was set, who did it, and when it happened.
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 28a33e4deb4..c736c0df1da 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -403,7 +403,7 @@ listed in the descriptions of the relevant settings.
| `performance_bar_enabled` | boolean | no | (Deprecated: Pass `performance_bar_allowed_group_path: nil` instead) Allow enabling the performance bar. |
| `personal_access_token_prefix` | string | no | Prefix for all generated personal access tokens. |
| `pipeline_limit_per_project_user_sha` | integer | no | Maximum number of pipeline creation requests per minute per user and commit. Disabled by default. |
-| `plantuml_enabled` | boolean | no | (**If enabled, requires:** `plantuml_url`) Enable PlantUML integration. Default is `false`. |
+| `plantuml_enabled` | boolean | no | (**If enabled, requires:** `plantuml_url`) Enable [PlantUML integration](../administration/integration/plantuml.md). Default is `false`. |
| `plantuml_url` | string | required by: `plantuml_enabled` | The PlantUML instance URL for integration. |
| `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to `0` to disable polling. |
| `project_export_enabled` | boolean | no | Enable project export. |
diff --git a/doc/api/topics.md b/doc/api/topics.md
index 78f32fb8fa0..ee88a43ff1c 100644
--- a/doc/api/topics.md
+++ b/doc/api/topics.md
@@ -20,11 +20,12 @@ GET /topics
Supported attributes:
-| Attribute | Type | Required | Description |
-| ---------- | ------- | ---------------------- | ----------- |
-| `page` | integer | **{dotted-circle}** No | Page to retrieve. Defaults to `1`. |
-| `per_page` | integer | **{dotted-circle}** No | Number of records to return per page. Defaults to `20`. |
-| `search` | string | **{dotted-circle}** No | Search topics against their `name`. |
+| Attribute | Type | Required | Description |
+| ------------------ | ------- | ---------------------- | ----------- |
+| `page` | integer | **{dotted-circle}** No | Page to retrieve. Defaults to `1`. |
+| `per_page` | integer | **{dotted-circle}** No | Number of records to return per page. Defaults to `20`. |
+| `search` | string | **{dotted-circle}** No | Search topics against their `name`. |
+| `without_projects` | boolean | **{dotted-circle}** No | Limit results to topics without assigned projects. |
Example request:
diff --git a/doc/api/users.md b/doc/api/users.md
index 06c0fadbbbf..c30bac3c542 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -39,7 +39,7 @@ GET /users
]
```
-You can also search for users by name, username or public email by using `?search=`. For example. `/users?search=John`.
+You can also search for users by name, username, or public email by using `?search=`. For example. `/users?search=John`.
In addition, you can lookup users by username:
@@ -425,9 +425,10 @@ You can include the user's [custom attributes](custom_attributes.md) in the resp
GET /users/:id?with_custom_attributes=true
```
-## User creation
+## User creation **(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.
+> - Ability to create an auditor user was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3.
Creates a new user. Note only administrators can create new
users. Either `password`, `reset_password`, or `force_random_password`
@@ -452,7 +453,8 @@ Parameters:
| Attribute | Required | Description |
| :----------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `admin` | No | User is an administrator - true or false (default) |
+| `admin` | No | User is an administrator. Valid values are `true` or `false`. Defaults to false.
+| `auditor` **(PREMIUM)** | No | User is an auditor. Valid values are `true` or `false`. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3. |
| `avatar` | No | Image file for user's avatar |
| `bio` | No | User's biography |
| `can_create_group` | No | User can create groups - true or false |
@@ -482,9 +484,10 @@ Parameters:
| `view_diffs_file_by_file` | No | Flag indicating the user sees only one file diff per page |
| `website_url` | No | Website URL |
-## User modification
+## User modification **(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.
+> - Ability to modify an auditor user was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3.
Modifies an existing user. Only administrators can change attributes of a user.
@@ -496,7 +499,8 @@ Parameters:
| Attribute | Required | Description |
| :----------------------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `admin` | No | User is an administrator - true or false (default) |
+| `admin` | No |User is an administrator. Valid values are `true` or `false`. Defaults to false.
+| `auditor` **(PREMIUM)** | No | User is an auditor. Valid values are `true` or `false`. Defaults to false. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366404) in GitLab 15.3.(default) |
| `avatar` | No | Image file for user's avatar |
| `bio` | No | User's biography |
| `can_create_group` | No | User can create groups - true or false |
@@ -531,7 +535,7 @@ Note, at the moment this method does only return a `404` error,
even in cases where a `409` (Conflict) would be more appropriate.
For example, when renaming the email address to some existing one.
-## Delete authentication identity from user
+## Delete authentication identity from user **(FREE SELF)**
Deletes a user's authentication identity using the provider name associated with that identity. Available only for administrators.
@@ -546,7 +550,7 @@ Parameters:
| `id` | integer | yes | ID of a user |
| `provider` | string | yes | External provider name |
-## User deletion
+## User deletion **(FREE SELF)**
Deletes a user. Available only for administrators.
This returns a `204 No Content` status code if the operation was successfully, `404` if the resource was not found or `409` if the user cannot be soft deleted.
@@ -753,7 +757,7 @@ PUT /user/status
| Attribute | Type | Required | Description |
| -------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `emoji` | string | no | Name of the emoji to use as status. If omitted `speech_balloon` is used. Emoji name can be one of the specified names in the [Gemojione index](https://github.com/bonusly/gemojione/blob/master/config/index.json). |
-| `message` | string | no | Message to set as a status. It can also contain emoji codes. |
+| `message` | string | no | Message to set as a status. It can also contain emoji codes. Cannot exceed 100 characters. |
| `clear_status_after` | string | no | Automatically clean up the status after a given time interval, allowed values: `30_minutes`, `3_hours`, `8_hours`, `1_day`, `3_days`, `7_days`, `30_days`
When both parameters `emoji` and `message` are empty, the status is cleared. When the `clear_status_after` parameter is missing from the request, the previously set value for `"clear_status_after` is cleared.
@@ -1069,7 +1073,7 @@ error occurs a `400 Bad Request` is returned with a message explaining the error
}
```
-## Add SSH key for user
+## Add SSH key for user **(FREE SELF)**
Create new key owned by specified user. Available only for administrator.
@@ -1104,7 +1108,7 @@ Parameters:
|-----------|---------|----------|-------------|
| `key_id` | integer | yes | SSH key ID |
-## Delete SSH key for given user
+## Delete SSH key for given user **(FREE SELF)**
Deletes key owned by a specified user. Available only for administrator.
@@ -1220,7 +1224,7 @@ Parameters:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/user/gpg_keys/1"
```
-Returns `204 No Content` on success, or `404 Not found` if the key cannot be found.
+Returns `204 No Content` on success or `404 Not Found` if the key cannot be found.
## List all GPG keys for given user
@@ -1282,7 +1286,7 @@ Example response:
}
```
-## Add a GPG key for a given user
+## Add a GPG key for a given user **(FREE SELF)**
Create new GPG key owned by the specified user. Available only for administrator.
@@ -1314,7 +1318,7 @@ Example response:
]
```
-## Delete a GPG key for a given user
+## Delete a GPG key for a given user **(FREE SELF)**
Delete a GPG key owned by a specified user. Available only for administrator.
@@ -1364,7 +1368,7 @@ Parameters:
- **none**
-## List emails for user
+## List emails for user **(FREE SELF)**
Get a list of a specified user's emails. Available only for administrator
@@ -1439,7 +1443,7 @@ error occurs a `400 Bad Request` is returned with a message explaining the error
}
```
-## Add email for user
+## Add email for user **(FREE SELF)**
Create new email owned by specified user. Available only for administrator
@@ -1470,7 +1474,7 @@ Parameters:
|------------|---------|----------|-------------|
| `email_id` | integer | yes | Email ID |
-## Delete email for given user
+## Delete email for given user **(FREE SELF)**
Deletes email owned by a specified user. Available only for administrator.
@@ -1485,7 +1489,7 @@ Parameters:
| `id` | integer | yes | ID of specified user |
| `email_id` | integer | yes | Email ID |
-## Block user
+## Block user **(FREE SELF)**
Blocks the specified user. Available only for administrator.
@@ -1507,7 +1511,7 @@ Returns:
- A user that is blocked through LDAP.
- An internal user.
-## Unblock user
+## Unblock user **(FREE SELF)**
Unblocks the specified user. Available only for administrator.
@@ -1524,7 +1528,7 @@ Parameters:
Returns `201 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
-## Deactivate user
+## Deactivate user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4.
@@ -1549,7 +1553,7 @@ Returns:
- That has any activity in past 90 days. These users cannot be deactivated.
- That is internal.
-## Activate user
+## Activate user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22257) in GitLab 12.4.
@@ -1571,7 +1575,7 @@ Returns:
- `404 User Not Found` if the user cannot be found.
- `403 Forbidden` if the user cannot be activated because they are blocked by an administrator or by LDAP synchronization.
-## Ban user
+## Ban user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327354) in GitLab 14.3.
@@ -1591,7 +1595,7 @@ Returns:
- `404 User Not Found` if user cannot be found.
- `403 Forbidden` when trying to ban a user that is not active.
-## Unban user
+## Unban user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327354) in GitLab 14.3.
@@ -1615,7 +1619,7 @@ Returns:
Please refer to the [Events API documentation](events.md#get-user-contribution-events)
-## Get all impersonation tokens of a user
+## Get all impersonation tokens of a user **(FREE SELF)**
Requires administrator access.
@@ -1670,7 +1674,7 @@ Example response:
]
```
-## Approve user
+## Approve user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263107) in GitLab 13.7.
@@ -1711,7 +1715,7 @@ Example Responses:
{ "message": "The user you are trying to approve is not pending approval" }
```
-## Reject user
+## Reject user **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339925) in GitLab 14.3.
@@ -1750,7 +1754,7 @@ Example Responses:
{ "message": "User does not have a pending request" }
```
-## Get an impersonation token of a user
+## Get an impersonation token of a user **(FREE SELF)**
> Requires administrators permissions.
@@ -1789,7 +1793,7 @@ Example response:
}
```
-## Create an impersonation token
+## Create an impersonation token **(FREE SELF)**
Requires administrator access. Token values are returned once. Make sure you save it because you can't access
it again.
@@ -1834,7 +1838,7 @@ Example response:
}
```
-## Revoke an impersonation token
+## Revoke an impersonation token **(FREE SELF)**
Requires administrator access.
@@ -1898,7 +1902,7 @@ Example response:
}
```
-## Get user activities
+## Get user activities **(FREE SELF)**
Pre-requisite:
@@ -1955,7 +1959,7 @@ Example response:
`last_activity_at` is deprecated. Use `last_activity_on` instead.
-## User memberships
+## User memberships **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20532) in GitLab 12.8.
@@ -1964,7 +1968,7 @@ Pre-requisite:
- You must be an administrator.
Lists all projects and groups a user is a member of.
-It returns the `source_id`, `source_name`, `source_type` and `access_level` of a membership.
+It returns the `source_id`, `source_name`, `source_type`, and `access_level` of a membership.
Source can be of type `Namespace` (representing a group) or `Project`. The response represents only direct memberships. Inherited memberships, for example in subgroups, are not included.
Access levels are represented by an integer value. For more details, read about the meaning of [access level values](access_requests.md#valid-access-levels).
@@ -2009,7 +2013,7 @@ Example response:
]
```
-## Disable two factor authentication
+## Disable two factor authentication **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295260) in GitLab 15.2.
diff --git a/doc/api/version.md b/doc/api/version.md
index 80269bc5697..7d072e23410 100644
--- a/doc/api/version.md
+++ b/doc/api/version.md
@@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Version API **(FREE)**
+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.
+
Retrieve version information for this GitLab instance. Responds `200 OK` for
authenticated users.
diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
index 18d97e30643..66d0579bacb 100644
--- a/doc/api/vulnerabilities.md
+++ b/doc/api/vulnerabilities.md
@@ -281,7 +281,7 @@ with the GraphQL API.
### GraphQL - Single vulnerability
-Use [`Query.vulnerability`](graphql/reference/#queryvulnerability).
+Use [`Query.vulnerability`](graphql/reference/index.md#queryvulnerability).
```graphql
{
@@ -337,7 +337,7 @@ Example response:
### GraphQL - Confirm vulnerability
-Use [`Mutation.vulnerabilityConfirm`](graphql/reference/#mutationvulnerabilityconfirm).
+Use [`Mutation.vulnerabilityConfirm`](graphql/reference/index.md#mutationvulnerabilityconfirm).
```graphql
mutation {
@@ -367,7 +367,7 @@ Example response:
### GraphQL - Resolve vulnerability
-Use [`Mutation.vulnerabilityResolve`](graphql/reference/#mutationvulnerabilityresolve).
+Use [`Mutation.vulnerabilityResolve`](graphql/reference/index.md#mutationvulnerabilityresolve).
```graphql
mutation {
@@ -397,7 +397,7 @@ Example response:
### GraphQL - Dismiss vulnerability
-Use [`Mutation.vulnerabilityDismiss`](graphql/reference/#mutationvulnerabilitydismiss).
+Use [`Mutation.vulnerabilityDismiss`](graphql/reference/index.md#mutationvulnerabilitydismiss).
```graphql
mutation {
@@ -427,7 +427,7 @@ Example response:
### GraphQL - Revert vulnerability to detected state
-Use [`Mutation.vulnerabilityRevertToDetected`](graphql/reference/#mutationvulnerabilityreverttodetected).
+Use [`Mutation.vulnerabilityRevertToDetected`](graphql/reference/index.md#mutationvulnerabilityreverttodetected).
```graphql
mutation {
diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md
index 20bbe66549d..46479009d7d 100644
--- a/doc/api/vulnerability_findings.md
+++ b/doc/api/vulnerability_findings.md
@@ -148,7 +148,7 @@ with the GraphQL API.
### GraphQL - Project vulnerabilities
-Use [`Project.vulnerabilities`](graphql/reference/#projectvulnerabilities).
+Use [`Project.vulnerabilities`](graphql/reference/index.md#projectvulnerabilities).
```graphql
{
diff --git a/doc/architecture/blueprints/ci_data_decay/index.md b/doc/architecture/blueprints/ci_data_decay/index.md
index 8808a526df0..7c0bdf299db 100644
--- a/doc/architecture/blueprints/ci_data_decay/index.md
+++ b/doc/architecture/blueprints/ci_data_decay/index.md
@@ -48,8 +48,8 @@ PostgreSQL database running on GitLab.com.
This volume contributes to significant performance problems, development
challenges and is often related to production incidents.
-We also expect a [significant growth in the number of builds executed on
-GitLab.com](../ci_scale/index.md) in the upcoming years.
+We also expect a [significant growth in the number of builds executed on GitLab.com](../ci_scale/index.md)
+in the upcoming years.
## Opportunity
@@ -61,8 +61,8 @@ pipelines that are older than a few months might help us to move this data out
of the primary database, to a different storage, that is more performant and
cost effective.
-It is already possible to prevent processing builds [that have been
-archived](../../../user/admin_area/settings/continuous_integration.md#archive-jobs).
+It is already possible to prevent processing builds
+[that have been archived](../../../user/admin_area/settings/continuous_integration.md#archive-jobs).
When a build gets archived it will not be possible to retry it, but we still do
keep all the processing metadata in the database, and it consumes resources
that are scarce in the primary database.
diff --git a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
index 60b20c50696..868dae4fc6c 100644
--- a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
+++ b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
@@ -306,9 +306,19 @@ We also need to build a proof of concept for removing data on the PostgreSQL
side (using foreign keys with `ON DELETE CASCADE`) and removing data through
Rails associations, as this might be an important area of uncertainty.
-We need to [better understand](https://gitlab.com/gitlab-org/gitlab/-/issues/360148)
-how unique constraints we are currently using will perform when using the
-partitioned schema.
+We [learned](https://gitlab.com/gitlab-org/gitlab/-/issues/360148) that `PostgreSQL`
+does not allow to create a single index (unique or otherwise) across all partitions of a table.
+
+One solution to solve this problem is to embed the partitioning key inside the uniqueness constraint.
+
+This might mean prepending the partition ID in a hexadecimal format before the token itself and storing
+the concatenated string in a database. To do that we would need to reserve an appropriate number of
+leading bytes in a token to accommodate for the maximum number of partitions we may have in the future.
+It seems that reserving four characters, what would translate into 16-bits number in base-16,
+might be sufficient. The maximum number we can encode this way would be FFFF, what is 65535 in decimal.
+
+This would provide a unique constraint per-partition which
+is sufficient for global uniqueness.
We have also designed a query analyzer that makes it possible to detect direct
usage of zero partitions, legacy tables that have been attached as first
diff --git a/doc/architecture/blueprints/ci_scale/index.md b/doc/architecture/blueprints/ci_scale/index.md
index 1c3aee2f860..5822ae2b5ed 100644
--- a/doc/architecture/blueprints/ci_scale/index.md
+++ b/doc/architecture/blueprints/ci_scale/index.md
@@ -89,8 +89,8 @@ 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
+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.
@@ -115,17 +115,14 @@ of the CI/CD Apdex score, and sometimes even causes 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.
-
-**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).
+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.
+
+**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).
### Moving big amounts of data is challenging
@@ -135,8 +132,7 @@ stores more than 600 gigabytes of data, and `ci_builds.yaml_variables` more
than 300 gigabytes (as of February 2021).
It is a lot of data that needs to be reliably moved to a different place.
-Unfortunately, right now, our [background
-migrations](https://docs.gitlab.com/ee/development/background_migrations.html)
+Unfortunately, right now, our [background migrations](../../../development/database/background_migrations.md)
are not reliable enough to migrate this amount of data at scale. We need to
build mechanisms that will give us confidence in moving this data between
columns, tables, partitions or database shards.
diff --git a/doc/architecture/blueprints/cloud_native_build_logs/index.md b/doc/architecture/blueprints/cloud_native_build_logs/index.md
index 3aba10fc758..0c941e332cb 100644
--- a/doc/architecture/blueprints/cloud_native_build_logs/index.md
+++ b/doc/architecture/blueprints/cloud_native_build_logs/index.md
@@ -12,8 +12,8 @@ Cloud native and the adoption of Kubernetes has been recognised by GitLab to be
one of the top two biggest tailwinds that are helping us grow faster as a
company behind the project.
-This effort is described in a more details [in the infrastructure team
-handbook](https://about.gitlab.com/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/).
+This effort is described in a more details
+[in the infrastructure team handbook](https://about.gitlab.com/handbook/engineering/infrastructure/production/kubernetes/gitlab-com/).
## Traditional build logs
@@ -88,9 +88,8 @@ even tried to replace NFS with
Since that time it has become apparent that the cost of operations and
maintenance of a NFS cluster is significant and that if we ever decide to
-migrate to Kubernetes [we need to decouple GitLab from a shared local storage
-and
-NFS](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/426#note_375646396).
+migrate to Kubernetes
+[we need to decouple GitLab from a shared local storage and NFS](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/426#note_375646396).
1. NFS might be a single point of failure
1. NFS can only be reliably scaled vertically
@@ -112,12 +111,10 @@ of complexity, maintenance cost and enormous, negative impact on availability.
1. ✓ Rollout the feature into production environment incrementally
The work needed to make the new architecture production ready and enabled on
-GitLab.com had been tracked in [Cloud Native Build Logs on
-GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/4275) epic.
+GitLab.com had been tracked in [Cloud Native Build Logs on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/4275) epic.
-Enabling this feature on GitLab.com is a subtask of [making the new
-architecture generally
-available](https://gitlab.com/groups/gitlab-org/-/epics/3791) for everyone.
+Enabling this feature on GitLab.com is a subtask of
+[making the new architecture generally available](https://gitlab.com/groups/gitlab-org/-/epics/3791) for everyone.
## Status
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index e545e8844ec..89c3a4cd6b4 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -17,8 +17,8 @@ Cloud Native and the adoption of Kubernetes has been recognised by GitLab to be
one of the top two biggest tailwinds that are helping us grow faster as a
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/).
+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
migration a significant change to GitLab Pages' architecture is required. This
@@ -55,9 +55,8 @@ even tried to replace NFS with
Since that time it has become apparent that the cost of operations and
maintenance of a NFS cluster is significant and that if we ever decide to
-migrate to Kubernetes [we need to decouple GitLab from a shared local storage
-and
-NFS](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/426#note_375646396).
+migrate to Kubernetes
+[we need to decouple GitLab from a shared local storage and NFS](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/426#note_375646396).
1. NFS might be a single point of failure
1. NFS can only be reliably scaled vertically
@@ -84,8 +83,8 @@ graph TD
C -- Serves static content --> E(Visitors)
```
-This new architecture has been briefly described in [the blog
-post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/)
+This new architecture has been briefly described in
+[the blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/)
too.
## Iterations
diff --git a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
index 53ea56b8724..df8686ed0aa 100644
--- a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
+++ b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
@@ -131,7 +131,7 @@ epic.
The initial iteration will provide a framework to house features under `Namespaces`. Stage groups will eventually need to migrate their own features and functionality over to `Namespaces`. This may impact these features in unexpected ways. Therefore, to minimize UX debt and maintain product consistency, stage groups will have to consider a number of factors when migrating their features over to `Namespaces`:
-1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [merge requests](https://design.gitlab.com/objects/merge-request)).
+1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [merge requests](https://design.gitlab.com/objects/merge-request/)).
1. **Merge conflicts**: What inconsistencies are there across project, group, and administrator levels? How might these be addressed? For an example of how we rationalized this for labels, please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338820).
1. **Inheritance & information flow**: How is information inherited across our container hierarchy currently? How might this be impacted if complying with the new [inheritance behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/343316) framework?
1. **Settings**: Where can settings for this feature be found currently? How will these be impacted by `Namespaces`?
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index 5105f2e08e2..9d40593d7ce 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -78,7 +78,7 @@ The single entrypoint for the registry is the [HTTP API](https://gitlab.com/gitl
| Operation | UI | Background | Observations |
| ------------------------------------------------------------ | ------------------ | ------------------------ | ------------------------------------------------------------ |
| [Check API version](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#api-version-check) | **{check-circle}** Yes | **{check-circle}** Yes | Used globally to ensure that the registry supports the Docker Distribution V2 API, as well as for identifying whether GitLab Rails is talking to the GitLab Container Registry or a third-party one (used to toggle features only available in the former). |
-| [List repository tags](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#listing-image-tags) | **{check-circle}** Yes | **{check-circle}** Yes | Used to list and show tags in the UI. Used to list tags in the background for [cleanup policies](../../../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy) and [Geo replication](../../../administration/geo/replication/docker_registry.md). |
+| [List repository tags](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#listing-image-tags) | **{check-circle}** Yes | **{check-circle}** Yes | Used to list and show tags in the UI. Used to list tags in the background for [cleanup policies](../../../user/packages/container_registry/reduce_container_registry_storage.md#cleanup-policy) and [Geo replication](../../../administration/geo/replication/container_registry.md). |
| [Check if manifest exists](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#existing-manifests) | **{check-circle}** Yes | **{dotted-circle}** No | Used to get the digest of a manifest by tag. This is then used to pull the manifest and show the tag details in the UI. |
| [Pull manifest](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#pulling-an-image-manifest) | **{check-circle}** Yes | **{dotted-circle}** No | Used to show the image size and the manifest digest in the tag details UI. |
| [Pull blob](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/spec/api.md#pulling-a-layer) | **{check-circle}** Yes | **{dotted-circle}** No | Used to show the configuration digest and the creation date in the tag details UI. |
@@ -148,7 +148,7 @@ The interaction between the registry and its clients, including GitLab Rails and
Following the GitLab [Go standards and style guidelines](../../../development/go_guide), no ORM is used to manage the database, only the [`database/sql`](https://pkg.go.dev/database/sql) package from the Go standard library, a PostgreSQL driver ([`lib/pq`](https://pkg.go.dev/github.com/lib/pq?tab=doc)) and raw SQL queries, over a TCP connection pool.
-The design and development of the registry database adhere to the GitLab [database guidelines](../../../development/database/). Being a Go application, the required tooling to support the database will have to be developed, such as for running database migrations.
+The design and development of the registry database adhere to the GitLab [database guidelines](../../../development/database/index.md). Being a Go application, the required tooling to support the database will have to be developed, such as for running database migrations.
Running *online* and [*post deployment*](../../../development/database/post_deployment_migrations.md) migrations is already supported by the registry CLI, as described in the [documentation](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/database-migrations.md).
@@ -160,7 +160,7 @@ Although blobs are shared across repositories, manifest and tag metadata are sco
#### GitLab.com
-Due to scale, performance and isolation concerns, for GitLab.com the registry database will be on a separate dedicated PostgreSQL cluster. Please see [#93](https://gitlab.com/gitlab-org/container-registry/-/issues/93) and [GitLab-com/gl-infra/infrastructure#10109](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10109) for additional context.
+Due to scale, performance and isolation concerns, for GitLab.com the registry database will be on a separate dedicated PostgreSQL cluster. Please see [#93](https://gitlab.com/gitlab-org/container-registry/-/issues/93) and [GitLab-com/gl-infra/reliability#10109](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/10109) for additional context.
The diagram below illustrates the architecture of the database cluster:
@@ -272,7 +272,7 @@ The expected registry behavior will be covered with integration tests, using a p
Apart from unusual network and systems conditions, problematic migrations and data failures can also affect the database availability and, as a consequence, the registry availability.
-Database migrations will adhere to the same [development best practices](../../../development/database/) used for GitLab Rails, except Rails-specific methods and tools, as the registry is a Go application with no ORM, and migrations are therefore expressed with raw SQL statements. Regardless, all changes will require a review and approval from the Database team.
+Database migrations will adhere to the same [development best practices](../../../development/database/index.md) used for GitLab Rails, except Rails-specific methods and tools, as the registry is a Go application with no ORM, and migrations are therefore expressed with raw SQL statements. Regardless, all changes will require a review and approval from the Database team.
Database migrations will be idempotent, with guard clauses used whenever necessary. It is also intended to guarantee that they are forward compatible. For a clustered environment, a node running registry version `N` should not cause any issues when the database schema is from version `N`+1.
@@ -280,9 +280,9 @@ Database migrations will be idempotent, with guard clauses used whenever necessa
Adding one more component to the system makes it even more critical to guarantee that we have proper observability over the registry's behavior and its dependencies. It should be guaranteed that we have all the necessary tools in place before rolling out the new registry backed by the metadata database.
-For this purpose, [error reporting with Sentry](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11297), [improved structured logging](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10933), and [improved HTTP metrics](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/10935) were already implemented and released. At the time of writing, the GitLab.com rollout is in progress.
+For this purpose, [error reporting with Sentry](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/11297), [improved structured logging](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/10933), and [improved HTTP metrics](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/10935) were already implemented and released. At the time of writing, the GitLab.com rollout is in progress.
-Additionally, the Prometheus metrics will be augmented with [details on the database connection pool](https://gitlab.com/gitlab-org/container-registry/-/issues/238). These will be added to the registry Grafana dashboards, joining the existing HTTP API, deployment, and storage metrics. The database cluster for the registry [will also have metrics and alerts](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11447).
+Additionally, the Prometheus metrics will be augmented with [details on the database connection pool](https://gitlab.com/gitlab-org/container-registry/-/issues/238). These will be added to the registry Grafana dashboards, joining the existing HTTP API, deployment, and storage metrics. The database cluster for the registry [will also have metrics and alerts](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/11447).
Together, these resources should provide an adequate level of insight into the registry's performance and behavior.
@@ -343,7 +343,7 @@ A more detailed list of all tasks, as well as periodic progress updates can be f
- [Proposal for continuous, on-demand online garbage collection](https://gitlab.com/gitlab-org/container-registry/-/issues/199)
- [Gradual migration proposal for the GitLab.com container registry](https://gitlab.com/gitlab-org/container-registry/-/issues/191)
- [Create a self-serve registry deployment](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/316)
-- [Database cluster for container registry](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/11154)
+- [Database cluster for container registry](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/11154)
## Who
diff --git a/doc/architecture/blueprints/database_scaling/size-limits.md b/doc/architecture/blueprints/database_scaling/size-limits.md
index 375c82f8833..284f6402d3c 100644
--- a/doc/architecture/blueprints/database_scaling/size-limits.md
+++ b/doc/architecture/blueprints/database_scaling/size-limits.md
@@ -136,7 +136,7 @@ As such, the target size of a physical table after refactoring depends on the si
There is no standard solution to reduce table sizes - there are many!
1. **Retention**: Delete unnecessary data, for example expire old and unneeded records.
-1. **Remove STI**: We still use [single-table inheritance](../../../development/single_table_inheritance.md) in a few places, which is considered an anti-pattern. Redesigning this, we can split data into multiple tables.
+1. **Remove STI**: We still use [single-table inheritance](../../../development/database/single_table_inheritance.md) in a few places, which is considered an anti-pattern. Redesigning this, we can split data into multiple tables.
1. **Index optimization**: Drop unnecessary indexes and consolidate overlapping indexes if possible.
1. **Optimise data types**: Review data type decisions and optimise data types where possible (example: use integer instead of text for an enum column)
1. **Partitioning**: Apply a partitioning scheme if there is a common access dimension.
@@ -167,7 +167,7 @@ The [epic for `~group::database`](https://gitlab.com/groups/gitlab-org/-/epics/6
<!-- vale gitlab.Spelling = NO -->
-Identifying solutions for offending tables is driven by the [GitLab Database Team](https://about.gitlab.com/handbook/engineering/development/enablement/database/) and respective stage groups.
+Identifying solutions for offending tables is driven by the [GitLab Database Team](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/database/) and respective stage groups.
| Role | Who
|------------------------------|-------------------------|
diff --git a/doc/architecture/blueprints/database_testing/index.md b/doc/architecture/blueprints/database_testing/index.md
index 30ebd06c81f..5bc9528d568 100644
--- a/doc/architecture/blueprints/database_testing/index.md
+++ b/doc/architecture/blueprints/database_testing/index.md
@@ -127,7 +127,7 @@ An alternative approach we have discussed and abandoned is to "scrub" and anonym
<!-- vale gitlab.Spelling = NO -->
-This effort is owned and driven by the [GitLab Database Team](https://about.gitlab.com/handbook/engineering/development/enablement/database/) with support from the [GitLab.com Reliability Datastores](https://about.gitlab.com/handbook/engineering/infrastructure/team/reliability/) team.
+This effort is owned and driven by the [GitLab Database Team](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/database/) with support from the [GitLab.com Reliability Datastores](https://about.gitlab.com/handbook/engineering/infrastructure/team/reliability/) team.
| Role | Who
|------------------------------|-------------------------|
diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md
index 94d52ea3474..eaca7da6bd7 100644
--- a/doc/architecture/blueprints/feature_flags_development/index.md
+++ b/doc/architecture/blueprints/feature_flags_development/index.md
@@ -115,9 +115,9 @@ These are reason why these changes are needed:
## Iterations
-This work is being done as part of dedicated epic: [Improve internal usage of
-Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). This epic
-describes a meta reasons for making these changes.
+This work is being done as part of dedicated epic:
+[Improve internal usage of Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551).
+This epic describes a meta reasons for making these changes.
## Who
diff --git a/doc/architecture/blueprints/graphql_api/index.md b/doc/architecture/blueprints/graphql_api/index.md
index b3ba1ad1960..eb045de491e 100644
--- a/doc/architecture/blueprints/graphql_api/index.md
+++ b/doc/architecture/blueprints/graphql_api/index.md
@@ -20,8 +20,7 @@ GraphQL development and helped to surface the need of improving tooling we use
to extend the new API.
This document describes the work that is needed to build a stable foundation that
-will support our development efforts and a large-scale usage of the [GraphQL
-API](https://docs.gitlab.com/ee/api/graphql/index.html).
+will support our development efforts and a large-scale usage of the [GraphQL API](../../../api/graphql/index.md).
## Summary
@@ -45,12 +44,12 @@ It is an opportunity to learn from our experience in evolving the REST API, for
the scale, and to apply this knowledge onto the GraphQL development efforts. We
can do that by building query-to-feature correlation mechanisms, adding
scalable state synchronization support and aligning GraphQL with other
-architectural initiatives being executed in parallel, like [the support for
-direct uploads](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
+architectural initiatives being executed in parallel, like
+[the support for direct uploads](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
GraphQL should be secure by default. We can avoid common security mistakes by
-building mechanisms that will help us to enforce [OWASP GraphQL
-recommendations](https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html)
+building mechanisms that will help us to enforce
+[OWASP GraphQL recommendations](https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html)
that are relevant to us.
Understanding what are the needs of the wider community will also allow us to
diff --git a/doc/architecture/blueprints/object_storage/index.md b/doc/architecture/blueprints/object_storage/index.md
index 3420caa325f..b70339c8b8d 100644
--- a/doc/architecture/blueprints/object_storage/index.md
+++ b/doc/architecture/blueprints/object_storage/index.md
@@ -31,9 +31,9 @@ underlying implementation for shared, distributed, highly-available
(HA) file storage.
Over time, we have built support for object storage across the
-application, solving specific problems in a [multitude of
-iterations](https://about.gitlab.com/company/team/structure/working-groups/object-storage/#company-efforts-on-uploads). This
-has led to increased complexity across the board, from development
+application, solving specific problems in a
+[multitude of iterations](https://about.gitlab.com/company/team/structure/working-groups/object-storage/#company-efforts-on-uploads).
+This has led to increased complexity across the board, from development
(new features and bug fixes) to installation:
- New GitLab installations require the creation and configuration of
@@ -67,10 +67,8 @@ has led to increased complexity across the board, from development
The following is a brief description of the main directions we can take to
remove the pain points affecting our object storage implementation.
-This is also available as [a YouTube
-video](https://youtu.be/X9V_w8hsM8E) recorded for the [Object Storage
-Working
-Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
+This is also available as [a YouTube video](https://youtu.be/X9V_w8hsM8E) recorded for the
+[Object Storage Working Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
### Simplify GitLab architecture by shipping MinIO
@@ -80,8 +78,8 @@ local storage and object storage.
With local storage, there is the assumption of a shared storage
between components. This can be achieved by having a single box
-installation, without HA, or with a NFS, which [we no longer
-recommend](../../../administration/nfs.md).
+installation, without HA, or with a NFS, which
+[we no longer recommend](../../../administration/nfs.md).
We have a testing gap on object storage. It also requires Workhorse
and MinIO, which are not present in our pipelines, so too much is
@@ -136,8 +134,8 @@ access to new features without infrastructure chores.
Our implementation is built on top of a 3rd-party framework where
every object storage client is a 3rd-party library. Unfortunately some
-of them are unmaintained. [We have customers who cannot push 5GB Git
-LFS objects](https://gitlab.com/gitlab-org/gitlab/-/issues/216442),
+of them are unmaintained.
+[We have customers who cannot push 5GB Git LFS objects](https://gitlab.com/gitlab-org/gitlab/-/issues/216442),
but with such a vital feature implemented in 3rd-party libraries we
are slowed down in fixing it, and we also rely on external maintainers
to merge and release fixes.
@@ -147,8 +145,7 @@ Before the introduction of direct upload, using the
library, _"a gem that provides a simple and extremely flexible way to
upload files from Ruby applications."_, was the boring solution.
However this is no longer our use-case, as we upload files from
-Workhorse, and we had to [patch CarrierWave's
-internals](https://gitlab.com/gitlab-org/gitlab/-/issues/285597#note_452696638)
+Workhorse, and we had to [patch CarrierWave's internals](https://gitlab.com/gitlab-org/gitlab/-/issues/285597#note_452696638)
to support direct upload.
A brief proposal covering CarrierWave removal and a new streamlined
@@ -217,7 +214,7 @@ Proposal:
DRIs:
-The DRI for this blueprint is the [Object Storage Working
-Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
+The DRI for this blueprint is the
+[Object Storage Working Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/architecture/blueprints/runner_scaling/index.md b/doc/architecture/blueprints/runner_scaling/index.md
index c4bd8433ab3..494aaa6a641 100644
--- a/doc/architecture/blueprints/runner_scaling/index.md
+++ b/doc/architecture/blueprints/runner_scaling/index.md
@@ -33,8 +33,8 @@ This design choice was crucial for the GitLab Runner success. Since that time
the auto-scaling feature has been used by many users and customers and enabled
rapid growth of CI/CD adoption on GitLab.com.
-We can not, however, continue using Docker Machine. Work on that project [was
-paused in July 2018](https://github.com/docker/machine/issues/4537) and there
+We can not, however, continue using Docker Machine. Work on that project
+[was paused in July 2018](https://github.com/docker/machine/issues/4537) and there
was no development made since that time (except for some highly important
security fixes). In 2018, after Docker Machine entered the "maintenance mode",
we decided to create [our own fork](https://gitlab.com/gitlab-org/ci-cd/docker-machine)
@@ -76,8 +76,8 @@ mechanism with a reliable and flexible mechanism. We might be unable to build a
drop-in replacement for Docker Machine, as there are presumably many reasons
why it has been deprecated. It is very difficult to maintain compatibility with
so many cloud providers, and it seems that Docker Machine has been deprecated
-in favor of Docker Desktop, which is not a viable replacement for us. [This
-issue](https://github.com/docker/roadmap/issues/245) contains a discussion
+in favor of Docker Desktop, which is not a viable replacement for us.
+[This issue](https://github.com/docker/roadmap/issues/245) contains a discussion
about how people are using Docker Machine right now, and it seems that GitLab
CI is one of the most frequent reasons for people to keep using Docker Machine.
diff --git a/doc/ci/cloud_services/aws/index.md b/doc/ci/cloud_services/aws/index.md
index dc8dfd95899..2e1abf83a11 100644
--- a/doc/ci/cloud_services/aws/index.md
+++ b/doc/ci/cloud_services/aws/index.md
@@ -62,16 +62,14 @@ After you configure the OIDC and role, the GitLab CI/CD job can retrieve a tempo
assume role:
script:
- >
- STS=($(aws sts assume-role-with-web-identity
+ export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s"
+ $(aws sts assume-role-with-web-identity
--role-arn ${ROLE_ARN}
--role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
--web-identity-token $CI_JOB_JWT_V2
--duration-seconds 3600
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
--output text))
- - export AWS_ACCESS_KEY_ID="${STS[0]}"
- - export AWS_SECRET_ACCESS_KEY="${STS[1]}"
- - export AWS_SESSION_TOKEN="${STS[2]}"
- aws sts get-caller-identity
```
diff --git a/doc/ci/cloud_services/google_cloud/index.md b/doc/ci/cloud_services/google_cloud/index.md
index f4e4a2046ba..54265816868 100644
--- a/doc/ci/cloud_services/google_cloud/index.md
+++ b/doc/ci/cloud_services/google_cloud/index.md
@@ -67,7 +67,7 @@ inside the Workload Identity Pool created in the previous step, using the follow
| `google.subject` | `assertion.sub` |
| `attribute.X` | `assertion.X` |
- You can also [build complex attributes](https://cloud.google.com/iam/help/workload-identity/attribute-mapping)
+ You can also [build complex attributes](https://cloud.google.com/iam/docs/workload-identity-federation#mapping)
using Common Expression Language (CEL).
You must map every attribute that you want to use for permission granting. For example, if you want to map permissions in the next step based on the user's email address, you must map `attribute.user_email` to `assertion.user_email`.
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index df0c7b69d46..ea4ad25637b 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -14,6 +14,9 @@ test it, and publish it to a container registry.
To run Docker commands in your CI/CD jobs, you must configure
GitLab Runner to support `docker` commands.
+If you want to build Docker images without enabling privileged mode on the runner,
+you can use a [Docker alternative](#docker-alternatives).
+
## Enable Docker commands in your CI/CD jobs
To enable Docker commands for your CI/CD jobs, you can use:
@@ -22,9 +25,6 @@ To enable Docker commands for your CI/CD jobs, you can use:
- [Docker-in-Docker](#use-docker-in-docker)
- [Docker socket binding](#use-docker-socket-binding)
-If you don't want to execute a runner in privileged mode,
-but want to use `docker build`, you can also use [`kaniko`](using_kaniko.md) or [`buildah`](https://github.com/containers/buildah).
-
If you are using shared runners on GitLab.com,
[learn more about how these runners are configured](../runners/index.md).
@@ -133,7 +133,7 @@ To use Docker-in-Docker with TLS enabled:
- This command registers a new runner to use the `docker:20.10.16` image.
To start the build and service containers, it uses the `privileged` mode.
- If you want to use [Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/),
+ If you want to use Docker-in-Docker,
you must always use `privileged = true` in your Docker containers.
- This command mounts `/certs/client` for the service and build
container, which is needed for the Docker client to use the
@@ -345,8 +345,8 @@ not without its own challenges:
root file system, you can use the job's working directory as a mount point for
child containers. For example, if you have files you want to share with a
child container, you might create a subdirectory under `/builds/$CI_PROJECT_PATH`
- and use it as your mount point. For a more detailed explanation, view [issue
- #41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227).
+ and use it as your mount point. For a more detailed explanation, view
+ [issue #41227](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41227).
```yaml
variables:
@@ -406,8 +406,8 @@ sudo gitlab-runner register -n \
##### Enable registry mirror for `docker:dind` service
When the Docker daemon starts inside of the service container, it uses
-the default configuration. You may want to configure a [registry
-mirror](https://docs.docker.com/registry/recipes/mirror/) for
+the default configuration. You may want to configure a
+[registry mirror](https://docs.docker.com/registry/recipes/mirror/) for
performance improvements and to ensure you don't reach Docker Hub rate limits.
###### The service in the `.gitlab-ci.yml` file
@@ -831,6 +831,44 @@ If you're running multiple runners, you have to modify all configuration files.
Read more about the [runner configuration](https://docs.gitlab.com/runner/configuration/)
and [using the OverlayFS storage driver](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/).
+## Docker alternatives
+
+To build Docker images without enabling privileged mode on the runner, you can
+use one of these alternatives:
+
+- [`kaniko`](using_kaniko.md).
+- [`buildah`](https://github.com/containers/buildah).
+
+For example, with `buildah`:
+
+```yaml
+# Some details from https://major.io/2019/05/24/build-containers-in-gitlab-ci-with-buildah/
+
+build:
+ stage: build
+ image: quay.io/buildah/stable
+ variables:
+ # Use vfs with buildah. Docker offers overlayfs as a default, but buildah
+ # cannot stack overlayfs on top of another overlayfs filesystem.
+ STORAGE_DRIVER: vfs
+ # Write all image metadata in the docker format, not the standard OCI format.
+ # Newer versions of docker can handle the OCI format, but older versions, like
+ # the one shipped with Fedora 30, cannot handle the format.
+ BUILDAH_FORMAT: docker
+ # You may need this workaround for some errors: https://stackoverflow.com/a/70438141/1233435
+ BUILDAH_ISOLATION: chroot
+ FQ_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/test"
+ before_script:
+ # Log in to the GitLab container registry
+ - export REGISTRY_AUTH_FILE=${HOME}/auth.json
+ - echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
+ script:
+ - buildah images
+ - buildah build -t $FQ_IMAGE_NAME
+ - buildah images
+ - buildah push $FQ_IMAGE_NAME
+```
+
## Use the GitLab Container Registry
After you've built a Docker image, you can push it up to the built-in
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index c2b18dc6467..712fd7b45d6 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -64,7 +64,7 @@ build:
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+ - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 -w 0)\"}}}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
@@ -119,6 +119,13 @@ build:
- if: $CI_COMMIT_TAG
```
+## Build a multi-arch image
+
+You can build [multi-arch images](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/)
+inside a container by using [`manifest-tool`](https://github.com/estesp/manifest-tool).
+
+For a detailed guide on how to build a multi-arch image, read [Building a multi-arch container image in unprivileged containers](https://ingenuity.siemens.com/2022/07/building-a-multi-arch-container-image-in-unprivileged-containers/).
+
## Using a registry with a custom certificate
When trying to push to a Docker registry that uses a certificate that is signed
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 6ffa68e4873..7747f5e9b78 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -21,7 +21,6 @@ GitLab:
If you have a deployment service like [Kubernetes](../../user/infrastructure/clusters/index.md)
associated with your project, you can use it to assist with your deployments.
-You can even access a [web terminal](#web-terminals-deprecated) for your environment from within GitLab.
## View environments and deployments
@@ -374,6 +373,9 @@ To retry or rollback a deployment:
### Environment URL
+> - [Fixed](https://gitlab.com/gitlab-org/gitlab/-/issues/337417) to persist arbitrary URLs in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `soft_validation_on_external_url`. Disabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/337417) in GitLab 15.3. [Feature flag `soft_validation_on_external_url`](https://gitlab.com/gitlab-org/gitlab/-/issues/367206) removed.
+
The [environment URL](../yaml/index.md#environmenturl) is displayed in a few
places in GitLab:
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 35ee4f9dd33..17eccc38747 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -70,7 +70,7 @@ Alternatively, you can use the API to protect an environment:
name: ${CI_JOB_NAME}
```
-1. Use the UI to [create a new group](../../user/group/index.md#create-a-group).
+1. Use the UI to [create a new group](../../user/group/manage.md#create-a-group).
For example, this group is called `protected-access-group` and has the group ID `9899826`. Note
that the rest of the examples in these steps use this group.
@@ -189,11 +189,14 @@ 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.
+
To maximize the effectiveness of group-level protected environments,
[group-level memberships](../../user/group/index.md) must be correctly
configured:
-- Operators should be given at least the Maintainer role
+- Operators should be given at least the Owner role
for the top-level group. They can maintain CI/CD configurations for
the higher environments (such as production) in the group-level settings page,
which includes group-level protected environments,
@@ -203,7 +206,7 @@ configured:
This ensures that only operators can configure the organization-wide
deployment ruleset.
- Developers should be given no more than the Developer role
- for the top-level group, or explicitly given the Maintainer role for a child project
+ for the top-level group, or explicitly given the Owner role for a child project
They do *not* have access to the CI/CD configurations in the
top-level group, so operators can ensure that the critical configuration won't
be accidentally changed by the developers.
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 90cbcb9e240..00025a66936 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -180,13 +180,13 @@ $ vault write auth/jwt/role/myproject-production - <<EOF
EOF
```
-This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims is allowed to authenticate.
+This example uses [bound_claims](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims is allowed to authenticate.
Combined with [protected branches](../../../user/project/protected_branches.md), you can restrict who is able to authenticate and read the secrets.
-[`token_explicit_max_ttl`](https://www.vaultproject.io/api/auth/jwt#token_explicit_max_ttl) specifies that the token issued by Vault, upon successful authentication, has a hard lifetime limit of 60 seconds.
+[`token_explicit_max_ttl`](https://www.vaultproject.io/api-docs/auth/jwt#token_explicit_max_ttl) specifies that the token issued by Vault, upon successful authentication, has a hard lifetime limit of 60 seconds.
-[`user_claim`](https://www.vaultproject.io/api/auth/jwt#user_claim) specifies the name for the Identity alias created by Vault upon a successful login.
+[`user_claim`](https://www.vaultproject.io/api-docs/auth/jwt#user_claim) specifies the name for the Identity alias created by Vault upon a successful login.
[`bound_claims_type`](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims_type) configures the interpretation of the `bound_claims` values. If set to `glob`, the values are interpreted as globs, with `*` matching any number of characters.
@@ -212,7 +212,7 @@ Role example to support the templated policy above, mapping the claim field `pro
}
```
-For the full list of options, see Vault's [Create Role documentation](https://www.vaultproject.io/api/auth/jwt#create-role).
+For the full list of options, see Vault's [Create Role documentation](https://www.vaultproject.io/api-docs/auth/jwt#create-role).
WARNING:
Always restrict your roles to project or namespace by using one of the provided claims (for example, `project_id` or `namespace_id`). Otherwise any JWT generated by this instance may be allowed to authenticate using this role.
@@ -225,14 +225,15 @@ $ vault write auth/jwt/config \
bound_issuer="gitlab.example.com"
```
-[bound_issuer](https://www.vaultproject.io/api/auth/jwt#inlinecode-bound_issuer) specifies that only a JWT with the issuer (that is, the `iss` claim) set to `gitlab.example.com` can use this method to authenticate, and that the JWKS endpoint (`https://gitlab.example.com/-/jwks`) should be used to validate the token.
+[bound_issuer](https://www.vaultproject.io/api-docs/auth/jwt#bound_issuer) specifies that only a JWT with the issuer (that is, the `iss` claim) set to `gitlab.example.com` can use this method to authenticate, and that the JWKS endpoint (`https://gitlab.example.com/-/jwks`) should be used to validate the token.
-For the full list of available configuration options, see Vault's [API documentation](https://www.vaultproject.io/api/auth/jwt#configure).
+For the full list of available configuration options, see Vault's [API documentation](https://www.vaultproject.io/api-docs/auth/jwt#configure).
The following job, when run for the default branch, is able to read secrets under `secret/myproject/staging/`, but not the secrets under `secret/myproject/production/`:
```yaml
read_secrets:
+ image: vault:latest
script:
# Check job's ref name
- echo $CI_COMMIT_REF_NAME
@@ -241,7 +242,7 @@ read_secrets:
# Vault's address can be provided here or as CI/CD variable
- export VAULT_ADDR=http://vault.example.com:8200
# Authenticate and get token. Token expiry time and other properties can be configured
- # when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
+ # when configuring JWT Auth - https://www.vaultproject.io/api-docs/auth/jwt#parameters-1
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-staging jwt=$CI_JOB_JWT)"
# Now use the VAULT_TOKEN to read the secret and store it in an environment variable
- export PASSWORD="$(vault kv get -field=password secret/myproject/staging/db)"
@@ -261,6 +262,7 @@ The following job is able to authenticate using the `myproject-production` role
```yaml
read_secrets:
+ image: vault:latest
script:
# Check job's ref name
- echo $CI_COMMIT_REF_NAME
@@ -269,7 +271,7 @@ read_secrets:
# Vault's address can be provided here or as CI/CD variable
- export VAULT_ADDR=http://vault.example.com:8200
# Authenticate and get token. Token expiry time and other properties can be configured
- # when configuring JWT Auth - https://www.vaultproject.io/api/auth/jwt#parameters-1
+ # when configuring JWT Auth - https://www.vaultproject.io/api-docs/auth/jwt#parameters-1
- export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-production jwt=$CI_JOB_JWT)"
# Now use the VAULT_TOKEN to read the secret and store it in environment variable
- export PASSWORD="$(vault kv get -field=password secret/myproject/production/db)"
@@ -288,9 +290,9 @@ and GitLab features. For example, restrict the token by:
for specific groups using `group_claim`.
- Hard coding values for Vault bound claims based on the `user_login` and `user_email`
of specific users.
-- Setting Vault time limits for TTL of the token as specified in [`token_explicit_max_ttl`](https://www.vaultproject.io/api/auth/jwt#token_explicit_max_ttl),
+- Setting Vault time limits for TTL of the token as specified in [`token_explicit_max_ttl`](https://www.vaultproject.io/api-docs/auth/jwt#token_explicit_max_ttl),
where the token expires after authentication.
-- Scoping the JWT to [GitLab projected branches](../../../user/project/protected_branches.md)
+- Scoping the JWT to [GitLab protected branches](../../../user/project/protected_branches.md)
that are restricted to a subset of project users.
-- Scoping the JWT to [GitLab projected tags](../../../user/project/protected_tags.md),
+- Scoping the JWT to [GitLab protected tags](../../../user/project/protected_tags.md),
that are restricted to a subset of project users.
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index 5f22fb894e5..fbecb1cd964 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -84,3 +84,9 @@ hidden files.
If there is no `.gitmodules` file, it's possible the submodule settings are in a
[`git config`](https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-config) file.
+
+### `fatal: run_command returned non-zero status` error
+
+This error can happen in a job when working with submodules and the `GIT_STRATEGY` is set to `fetch`.
+
+Setting the `GIT_STRATEGY` to `clone` should resolve the issue.
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index f49fdd6c39f..e6a9f1fa646 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -18,8 +18,8 @@ taken to protect the users.
NOTE:
[Shared runners on GitLab.com](../runners/index.md) do not
-provide an interactive web terminal. Follow [this
-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) for progress on
+provide an interactive web terminal. Follow
+[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) for progress on
adding support. For groups and projects hosted on GitLab.com, interactive web
terminals are available when using your own group or project runner.
@@ -27,8 +27,8 @@ terminals are available when using your own group or project runner.
Two things need to be configured for the interactive web terminal to work:
-- The runner needs to have [`[session_server]` configured
- properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
+- The runner needs to have
+ [`[session_server]` configured properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
- If you are using a reverse proxy with your GitLab instance, web terminals need to be
[enabled](../../administration/integration/terminal.md#enabling-and-disabling-terminal-support)
@@ -54,8 +54,8 @@ Not all executors are
NOTE:
The `docker` executor does not keep running
after the build script is finished. At that point, the terminal automatically
-disconnects and does not wait for the user to finish. Please follow [this
-issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3605) for updates on
+disconnects and does not wait for the user to finish. Please follow
+[this issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3605) for updates on
improving this behavior.
Sometimes, when a job is running, things don't go as you would expect, and it
@@ -63,8 +63,7 @@ would be helpful if one can have a shell to aid debugging. When a job is
running, on the right panel you can see a button `debug` that opens the terminal
for the current job.
-![Example of job running with terminal
-available](img/interactive_web_terminal_running_job.png)
+![Example of job running with terminal available](img/interactive_web_terminal_running_job.png)
When clicked, a new tab opens to the terminal page where you can access
the terminal and type commands like a normal shell.
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index 9567bc9cd65..93f22da648a 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -13,6 +13,7 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
- Packages:
- [Package Registry](../../user/packages/package_registry/index.md#use-gitlab-cicd-to-build-packages).
+ - [Packages API](../../api/packages.md) (project-level).
- [Container Registry](../../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
(the `$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`).
- [Container Registry API](../../api/container_registry.md)
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index 24133fe9a9b..0d5357e63ad 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -304,7 +304,7 @@ to add jobs to a pipeline:
```yaml
docker build:
variables:
- DOCKERFILES_DIR: 'path/to/files/'
+ DOCKERFILES_DIR: 'path/to/files'
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- changes:
@@ -567,6 +567,9 @@ In blocking manual jobs:
enabled can't be merged with a blocked pipeline.
- The pipeline shows a status of **blocked**.
+When using manual jobs in triggered pipelines with [`strategy: depend`](../yaml/index.md#triggerstrategy),
+the type of manual job can affect the trigger job's status while the pipeline runs.
+
### Run a manual job
To run a manual job, you must have permission to merge to the assigned branch:
@@ -1005,6 +1008,26 @@ Additionally, rules with `changes` always evaluate as true in [scheduled pipelin
All files are considered to have changed when a scheduled pipeline runs, so jobs
might always be added to scheduled pipelines that use `changes`.
+### File paths in CI/CD variables
+
+Be careful when using file paths in CI/CD variables. A trailing slash can appear correct
+in the variable definition, but can become invalid when expanded in `script:`, `changes:`,
+or other keywords. For example:
+
+```yaml
+docker_build:
+ variables:
+ DOCKERFILES_DIR: 'path/to/files/' # This variable should not have a trailing '/' character
+ script: echo "A docker job"
+ rules:
+ - changes:
+ - $DOCKERFILES_DIR/*
+```
+
+When the `DOCKERFILES_DIR` variable is expanded in the `changes:` section, the full
+path becomes `path/to/files//*`. The double slashes might cause unexpected behavior
+depending on the keyword used, shell and OS of the runner, and so on.
+
### `You are not allowed to download code from this project.` error message
You might see pipelines fail when a GitLab administrator runs a protected manual job
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index f3044a03e04..3904a527a8f 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -116,8 +116,7 @@ you could add [`--no-tags`](https://git-scm.com/docs/git-fetch#Documentation/git
to the extra flags to make your fetches faster and more compact.
Also in the case where you repository does _not_ contain a lot of
-tags, `--no-tags` can [make a big difference in some
-cases](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746).
+tags, `--no-tags` can [make a big difference in some cases](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/746).
If your CI builds do not depend on Git tags it is worth trying.
See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../runners/configure_runners.md#git-fetch-extra-flags)
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index 3b890458e56..7255d9aec82 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -265,7 +265,7 @@ test_async:
## Contexts and variables
-CircleCI provides [Contexts](https://circleci.com/docs/2.0/contexts/) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/index.md#add-a-cicd-variable-to-a-group) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
+CircleCI provides [Contexts](https://circleci.com/docs/contexts) to securely pass environment variables across project pipelines. In GitLab, a [Group](../../user/group/index.md) can be created to assemble related projects together. At the group level, [CI/CD variables](../variables/index.md#add-a-cicd-variable-to-a-group) can be stored outside the individual projects, and securely passed into pipelines across multiple projects.
## Orbs
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index 4fb2ec94d60..0fd8fac7741 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -40,6 +40,10 @@ is invalid, a tip is shown to help you fix the problem:
## Lint CI configuration
+NOTE:
+The **Lint** tab is replaced with the **Validate** tab in GitLab 15.3. The lint results are included
+in a successful [pipeline simulation](#simulate-a-cicd-pipeline).
+
To test the validity of your GitLab CI/CD configuration before committing the changes,
you can use the CI lint tool. To access it, go to **CI/CD > Editor** and select the **Lint** tab.
@@ -51,6 +55,15 @@ reflected in the CI lint. It displays the same results as the existing [CI Lint
![Linting errors in a CI configuration](img/pipeline_editor_lint_v13_8.png)
+## Simulate a CI/CD pipeline
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/337282) in GitLab 15.3.
+
+To look for pipeline syntax and logic issues, you can simulate the creation of a
+GitLab CI/CD pipeline in the **Validate** tab. A pipeline simulation can help find
+problems such as incorrect `rules` and `needs` job dependencies, and is similar to
+simulations in the [CI Lint tool](../lint.md#simulate-a-pipeline).
+
## View included CI/CD configuration
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7064) in GitLab 15.0 [with a flag](../../administration/feature_flags.md) named `pipeline_editor_file_tree`. Disabled by default.
diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md
index 1e862c87035..4b7d3845361 100644
--- a/doc/ci/pipelines/cicd_minutes.md
+++ b/doc/ci/pipelines/cicd_minutes.md
@@ -21,7 +21,7 @@ On GitLab.com:
- CI/CD minutes quotas are enabled for both public and private projects, but public
projects [consume CI/CD minutes at a slower rate](#cost-factor).
-- The base monthly CI/CD minutes quota for a GitLab.com [namespace](../../user/group/index.md#namespaces)
+- The base monthly CI/CD minutes quota for a GitLab.com [namespace](../../user/namespace/index.md)
is determined by its [license tier](https://about.gitlab.com/pricing/).
- You can [purchase additional CI/CD minutes](#purchase-additional-cicd-minutes)
if you need more than the number of CI/CD minutes in your monthly quota.
@@ -204,12 +204,36 @@ The cost factors for jobs running on shared runners on GitLab.com are:
- `0.008` for public projects, and 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.
- `1` for internal and private projects.
+- Calculated differently for [community contributions to GitLab projects](#cost-factor-for-community-contributions-to-gitlab-projects).
The cost factors on self-managed instances are:
- `0` for public projects, so they do not consume CI/CD minutes.
- `1` for internal and private projects.
+#### Cost factor for community contributions to GitLab projects
+
+Community contributors can use up to 300,000 minutes on shared runners when
+contributing to open source projects maintained by GitLab. The 300,000
+minutes applies to all SaaS tiers, and the cost factor calculation is:
+
+- `Monthly minute quota / 300,000 job duration minutes = Cost factor`
+
+For example, with the 10,000 CI/CD minutes per month in the Premium tier:
+
+- 10,000 / 300,000 = 0.03333333333 cost factor.
+
+For this reduced cost factor:
+
+- The merge request source project must be a fork of a GitLab-maintained project,
+ such as [`gitlab-com/www-gitlab-com`](https://gitlab.com/gitlab-com/www-gitlab-com),
+ [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab), and so on.
+- The merge request target project must be the fork's parent project.
+- The pipeline must be a merge request, merged results, or merge train pipeline.
+
+GitLab administrators can add a namespace to the reduced cost factor
+[with a flag](../../administration/feature_flags.md) named `ci_minimal_cost_factor_for_gitlab_namespaces`.
+
### Additional costs on GitLab SaaS
GitLab SaaS shared runners have different cost factors, depending on the runner type (Linux, Windows, macOS) and the virtual machine configuration.
diff --git a/doc/ci/pipelines/img/pipeline_mini_graph_v15_0.png b/doc/ci/pipelines/img/pipeline_mini_graph_v15_0.png
new file mode 100644
index 00000000000..48a0ca9d84f
--- /dev/null
+++ b/doc/ci/pipelines/img/pipeline_mini_graph_v15_0.png
Binary files differ
diff --git a/doc/ci/pipelines/merge_request_pipelines.md b/doc/ci/pipelines/merge_request_pipelines.md
index 89839de718b..5ba489c9830 100644
--- a/doc/ci/pipelines/merge_request_pipelines.md
+++ b/doc/ci/pipelines/merge_request_pipelines.md
@@ -151,7 +151,10 @@ or [**Rebase** option](../../user/project/merge_requests/methods/index.md#rebasi
Prerequisites:
-- You must be a member of the parent project and have at least the [Developer role](../../user/permissions.md).
+- The parent project's [CI/CD configuration file](../yaml/index.md) must be configured to
+ [run jobs in merge request pipelines](#prerequisites).
+- You must be a member of the parent project with [permissions to run CI/CD pipelines](../../user/permissions.md#gitlab-cicd-permissions).
+ You might need additional permissions if the branch is protected.
- The fork project must be [visible](../../user/public_access.md) to the
user running the pipeline. Otherwise, the **Pipelines** tab does not display
in the merge request.
@@ -161,6 +164,10 @@ To use the UI to run a pipeline in the parent project for a merge request from a
1. In the merge request, go to the **Pipelines** tab.
1. Select **Run pipeline**. You must read and accept the warning, or the pipeline does not run.
+You can disable this feature by using [the projects API](../../api/projects.md#edit-project)
+to disable the `ci_allow_fork_pipelines_to_run_in_parent_project` setting.
+The setting is `enabled` by default.
+
## Available predefined variables
When you use merge request pipelines, you can use:
diff --git a/doc/ci/pipelines/merge_trains.md b/doc/ci/pipelines/merge_trains.md
index ac644628f3a..2882cd378aa 100644
--- a/doc/ci/pipelines/merge_trains.md
+++ b/doc/ci/pipelines/merge_trains.md
@@ -59,9 +59,8 @@ changes that are included in the target branch, and the `C` changes that are fro
the merge request already in the train.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-Watch this video for a demonstration on [how parallel execution
-of merge trains can prevent commits from breaking the default
-branch](https://www.youtube.com/watch?v=D4qCqXgZkHQ).
+Watch this video for a demonstration on
+[how parallel execution of merge trains can prevent commits from breaking the default branch](https://www.youtube.com/watch?v=D4qCqXgZkHQ).
## Prerequisites
diff --git a/doc/ci/pipelines/multi_project_pipelines.md b/doc/ci/pipelines/multi_project_pipelines.md
index dfbd2708d8d..a71af78f410 100644
--- a/doc/ci/pipelines/multi_project_pipelines.md
+++ b/doc/ci/pipelines/multi_project_pipelines.md
@@ -45,8 +45,8 @@ To create multi-project pipelines, you can:
> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
-When you create a multi-project pipeline in your `.gitlab-ci.yml` file,
-you create what is called a *trigger job*. For example:
+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:
```yaml
rspec:
@@ -76,7 +76,7 @@ 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_.
-#### Trigger job configuration keywords
+#### Trigger job configuration limitations
Trigger jobs can use only a limited set of the GitLab CI/CD [configuration keywords](../yaml/index.md).
The keywords available for use in trigger jobs are:
@@ -90,6 +90,8 @@ The keywords available for use in trigger jobs are:
- [`extends`](../yaml/index.md#extends)
- [`needs`](../yaml/index.md#needs), but not [`needs:project`](../yaml/index.md#needsproject)
+Trigger jobs cannot use [job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables).
+
#### Specify a downstream pipeline branch
You can specify a branch name for the downstream pipeline to use.
@@ -111,6 +113,8 @@ staging:
Use:
- The `project` keyword to specify the full path to a downstream project.
+ In [GitLab 15.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/367660), variable expansion is
+ supported.
- The `branch` keyword to specify the name of a branch in the project specified by `project`.
In [GitLab 12.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/10126), variable expansion is
supported.
@@ -180,9 +184,12 @@ downstream-job:
trigger: my/project
```
-In this scenario, the `UPSTREAM_BRANCH` variable with a value related to the
-upstream pipeline is passed to the `downstream-job` job. It is available
-in the context of all downstream builds.
+In this scenario, the `UPSTREAM_BRANCH` variable with the value of the upstream pipeline's
+`$CI_COMMIT_REF_NAME` is passed to `downstream-job`. It is available in the
+context of all downstream builds.
+
+You cannot use this method to forward [job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables)
+to a downstream pipeline, as they are not available in trigger jobs.
Upstream pipelines take precedence over downstream ones. If there are two
variables with the same name defined in both upstream and downstream projects,
@@ -228,6 +235,96 @@ In the upstream pipeline:
artifacts: true
```
+#### Pass artifacts to a downstream pipeline
+
+You can pass artifacts to a downstream pipeline by using [`needs:project`](../yaml/index.md#needsproject).
+
+1. In a job in the upstream pipeline, save the artifacts using the [`artifacts`](../yaml/index.md#artifacts) keyword.
+1. Trigger the downstream pipeline with a trigger job:
+
+ ```yaml
+ build_artifacts:
+ stage: build
+ script:
+ - echo "This is a test artifact!" >> artifact.txt
+ artifacts:
+ paths:
+ - artifact.txt
+
+ deploy:
+ stage: deploy
+ trigger: my/downstream_project
+ ```
+
+1. In a job in the downstream pipeline, fetch the artifacts from the upstream pipeline
+ by using `needs:project`. Set `job` to the job in the upstream pipeline to fetch artifacts from,
+ `ref` to the branch, and `artifacts: true`.
+
+ ```yaml
+ test:
+ stage: test
+ script:
+ - cat artifact.txt
+ needs:
+ - project: my/upstream_project
+ job: build_artifacts
+ ref: main
+ artifacts: true
+ ```
+
+#### Pass artifacts to a downstream pipeline from a Merge Request pipeline
+
+When you use `needs:project` to [pass artifacts to a downstream pipeline](#pass-artifacts-to-a-downstream-pipeline),
+the `ref` value is usually a branch name, like `main` or `development`.
+
+For merge request pipelines, the `ref` value is in the form of `refs/merge-requests/<id>/head`,
+where `id` is the merge request ID. You can retrieve this ref with the [`CI_MERGE_REQUEST_REF_PATH`](../variables/predefined_variables.md#predefined-variables-for-merge-request-pipelines)
+CI/CD variable. Do not use a branch name as the `ref` with merge request pipelines,
+because the downstream pipeline attempts to fetch artifacts from the latest branch pipeline.
+
+To fetch the artifacts from the upstream `merge request` pipeline instead of the `branch` pipeline,
+pass this variable to the downstream pipeline using variable inheritance:
+
+1. In a job in the upstream pipeline, save the artifacts using the [`artifacts`](../yaml/index.md#artifacts) keyword.
+1. In the job that triggers the downstream pipeline, pass the `$CI_MERGE_REQUEST_REF_PATH` variable by using
+ [variable inheritance](#pass-cicd-variables-to-a-downstream-pipeline-by-using-the-variables-keyword):
+
+ ```yaml
+ build_artifacts:
+ stage: build
+ script:
+ - echo "This is a test artifact!" >> artifact.txt
+ artifacts:
+ paths:
+ - artifact.txt
+
+ upstream_job:
+ variables:
+ UPSTREAM_REF: $CI_MERGE_REQUEST_REF_PATH
+ trigger:
+ project: my/downstream_project
+ branch: my-branch
+ ```
+
+1. In a job in the downstream pipeline, fetch the artifacts from the upstream pipeline
+ by using `needs:project`. Set the `ref` to the `UPSTREAM_REF` variable, and `job`
+ to the job in the upstream pipeline to fetch artifacts from:
+
+ ```yaml
+ test:
+ stage: test
+ script:
+ - cat artifact.txt
+ needs:
+ - project: my/upstream_project
+ job: build_artifacts
+ ref: UPSTREAM_REF
+ artifacts: true
+ ```
+
+This method works for fetching artifacts from a regular merge request parent pipeline,
+but fetching artifacts from [merge results](merged_results_pipelines.md) pipelines is not supported.
+
#### Use `rules` or `only`/`except` with multi-project pipelines
You can use CI/CD variables or the [`rules`](../yaml/index.md#rulesif) keyword to
@@ -244,8 +341,8 @@ If you use [`only/except`](../yaml/index.md#only--except) to control job behavio
> - [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`. For example:
+You can mirror the pipeline status from the triggered pipeline to the source trigger job
+by using [`strategy: depend`](../yaml/index.md#triggerstrategy). For example:
```yaml
trigger_job:
@@ -303,11 +400,16 @@ downstream projects. On self-managed instances, an administrator can change this
## Multi-project pipeline visualization **(PREMIUM)**
-When you configure GitLab CI/CD for your project, you can visualize the stages of your
-[jobs](index.md#configure-a-pipeline) on a [pipeline graph](index.md#visualize-pipelines).
+When your pipeline triggers a downstream pipeline, the downstream pipeline displays
+to the right of the [pipeline graph](index.md#visualize-pipelines).
![Multi-project pipeline graph](img/multi_project_pipeline_graph_v14_3.png)
+In [pipeline mini graphs](index.md#pipeline-mini-graphs), the downstream pipeline
+displays to the right of the mini graph.
+
+![Multi-project pipeline mini graph](img/pipeline_mini_graph_v15_0.png)
+
## Retry or cancel multi-project pipelines
If you have permission to trigger pipelines in the downstream project, you can
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 43f20bfa9ea..34eae9828dd 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -250,8 +250,8 @@ using the [`coverage`](../yaml/index.md#coverage) keyword.
### Add test coverage results using project settings (removed)
-> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 14.8. Replaced by [`coverage` keyword](../yaml/index.md#coverage).
-> [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 15.0.
+> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 14.8. Replaced by [`coverage` keyword](../yaml/index.md#coverage).
+> - [Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 15.0.
This feature is in its end-of-life process. It was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/17633)
in GitLab 14.8. The feature is [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/17633) in GitLab 15.0.
@@ -299,22 +299,22 @@ Use this regex for commonly used test tools.
<!-- vale gitlab.Spelling = NO -->
-- Simplecov (Ruby). Example: `\(\d+.\d+\%\) covered`.
-- pytest-cov (Python). Example: `(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$`.
-- Scoverage (Scala). Example: `Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)`.
-- `phpunit --coverage-text --colors=never` (PHP). Example: `^\s*Lines:\s*\d+.\d+\%`.
-- gcovr (C/C++). Example: `^TOTAL.*\s+(\d+\%)$`.
-- `tap --coverage-report=text-summary` (NodeJS). Example: `^Statements\s*:\s*([^%]+)`.
-- `nyc npm test` (NodeJS). Example: `All files[^|]*\|[^|]*\s+([\d\.]+)`.
-- `jest --ci --coverage` (NodeJS). Example: `All files[^|]*\|[^|]*\s+([\d\.]+)`.
-- excoveralls (Elixir). Example: `\[TOTAL\]\s+(\d+\.\d+)%`.
-- `mix test --cover` (Elixir). Example: `\d+.\d+\%\s+\|\s+Total`.
-- JaCoCo (Java/Kotlin). Example: `Total.*?([0-9]{1,3})%`.
-- `go test -cover` (Go). Example: `coverage: \d+.\d+% of statements`.
-- .NET (OpenCover). Example: `(Visited Points).*\((.*)\)`.
-- .NET (`dotnet test` line coverage). Example: `Total\s*\|\s*(\d+(?:\.\d+)?)`.
-- tarpaulin (Rust). Example: `^\d+.\d+% coverage`.
-- Pester (PowerShell). Example: `Covered (\d+\.\d+%)`.
+- Simplecov (Ruby). Example: `/\(\d+.\d+\%\) covered/`.
+- pytest-cov (Python). Example: `/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/`.
+- Scoverage (Scala). Example: `/Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)/`.
+- `phpunit --coverage-text --colors=never` (PHP). Example: `/^\s*Lines:\s*\d+.\d+\%/`.
+- gcovr (C/C++). Example: `/^TOTAL.*\s+(\d+\%)$/`.
+- `tap --coverage-report=text-summary` (NodeJS). Example: `/^Statements\s*:\s*([^%]+)/`.
+- `nyc npm test` (NodeJS). Example: `/All files[^|]*\|[^|]*\s+([\d\.]+)/`.
+- `jest --ci --coverage` (NodeJS). Example: `/All files[^|]*\|[^|]*\s+([\d\.]+)/`.
+- excoveralls (Elixir). Example: `/\[TOTAL\]\s+(\d+\.\d+)%/`.
+- `mix test --cover` (Elixir). Example: `/\d+.\d+\%\s+\|\s+Total/`.
+- JaCoCo (Java/Kotlin). Example: `/Total.*?([0-9]{1,3})%/`.
+- `go test -cover` (Go). Example: `/coverage: \d+.\d+% of statements/`.
+- .NET (OpenCover). Example: `/(Visited Points).*\((.*)\)/`.
+- .NET (`dotnet test` line coverage). Example: `/Total\s*\|\s*(\d+(?:\.\d+)?)/`.
+- tarpaulin (Rust). Example: `/^\d+.\d+% coverage/`.
+- Pester (PowerShell). Example: `/Covered (\d+\.\d+%)/`.
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index efd78fac2c6..3efa697bf2f 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -722,11 +722,14 @@ variables:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28940) in GitLab Runner 15.1.
+NOTE:
+Zip archives are the only supported artifact type. Follow [the issue for details](https://gitlab.com/gitlab-org/gitlab/-/issues/367203).
+
GitLab Runner can generate and produce attestation metadata for all build artifacts. To enable this feature, you must set the `RUNNER_GENERATE_ARTIFACTS_METADATA` environment variable to `true`. This variable can either be set globally or it can be set for individual jobs. The metadata is in rendered in a plain text `.json` file that's stored with the artifact. The file name is as follows: `{JOB_ID}-artifacts-metadata.json`.
### Attestation format
-The attestation metadata is generated in the [in-toto attestation format](https://github.com/in-toto/attestation) for spec version [v0.1](https://in-toto.io/Statement/v0.1). The following fields are populated by default:
+The attestation metadata is generated in the [in-toto attestation format](https://github.com/in-toto/attestation) for spec version [v0.1](https://github.com/in-toto/attestation/tree/v0.1.0/spec). The following fields are populated by default:
| Field | Value |
| ------ | ------ |
@@ -863,7 +866,7 @@ Group runners are those that were created at the group level.
### View stale runner cleanup logs
-You can check the [Sidekiq logs](../../administration/logs.md#sidekiq-logs) to see the cleanup result. In Kibana you can use the following query:
+You can check the [Sidekiq logs](../../administration/logs/index.md#sidekiq-logs) to see the cleanup result. In Kibana you can use the following query:
```json
{
@@ -889,3 +892,23 @@ Filter entries where stale runners were removed:
}
}
```
+
+## Determine which runners need to be upgraded **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/365078) in GitLab 15.3.
+
+The version of GitLab Runner used by your runners should be
+[kept up-to-date](https://docs.gitlab.com/runner/index.html#gitlab-runner-versions).
+
+To determine which runners need to be upgraded:
+
+1. View the list of runners:
+ - For a group, on the top bar, select **Menu > Groups** and on the left sidebar, select **CI/CD > Runners**.
+ - For the instance, select **Menu > Admin** and on the left sidebar, select **Runners**.
+
+1. Above the list of runners, view the status:
+ - **Outdated - recommended**: The runner does not have the latest `PATCH` version, which may make it vulnerable
+ to security or high severity bugs. Or, the runner is one or more `MAJOR` versions behind your GitLab instance, so some features may not be available or work properly.
+ - **Outdated - available**: Newer versions are available but upgrading is not critical.
+
+1. Filter the list by status to view which individual runners need to be upgraded.
diff --git a/doc/ci/runners/img/build_isolation.png b/doc/ci/runners/img/build_isolation.png
new file mode 100644
index 00000000000..a363ef4709b
--- /dev/null
+++ b/doc/ci/runners/img/build_isolation.png
Binary files differ
diff --git a/doc/ci/runners/index.md b/doc/ci/runners/index.md
index 038bda4ab09..f69d1f0f730 100644
--- a/doc/ci/runners/index.md
+++ b/doc/ci/runners/index.md
@@ -18,5 +18,25 @@ The number of minutes you can use on these runners depends on the
[maximum number of CI/CD minutes](../pipelines/cicd_minutes.md)
in your [subscription plan](https://about.gitlab.com/pricing/).
-If you use self-managed GitLab or you use GitLab.com but want to use your own runners, you can
-[install and configure your own runners](https://docs.gitlab.com/runner/install/).
+## Security for GitLab SaaS runners
+
+GitLab SaaS runners on Linux and Windows run on Google Compute Platform. The [Google Infrastructure Security Design Overview whitepaper](https://cloud.google.com/docs/security/infrastructure/design/resources/google_infrastructure_whitepaper_fa.pdf) provides an overview of how Google designs security into its technical infrastructure. The GitLab [Trust Center](https://about.gitlab.com/security/) and [GitLab Security Compliance Controls](https://about.staging.gitlab.com/handbook/engineering/security/security-assurance/security-compliance/sec-controls.html) pages provide an overview of the Security and Compliance controls that govern the GitLab SaaS runners.
+
+The runner that serves as a Runner Manager automatically initiates the creation and deletion of the virtual machines (VMs) used for CI jobs. When the Runner Manager picks up a GitLab SaaS CI job, it automatically executes that job on a new VM. There is no human or manual intervention in this process. The following section provides an overview of the additional built-in layers that harden the security of the GitLab Runner SaaS CI build environment.
+
+### Security of CI job execution on GitLab Runner SaaS (Linux, Windows)
+
+A dedicated temporary runner VM hosts and runs each CI job. On GitLab SaaS, two CI jobs never run on the same VM.
+
+![Job isolation](img/build_isolation.png)
+
+In this example, there are three jobs in the project's pipeline. Therefore, there are three temporary VMs used to run that pipeline, or one VM per job.
+
+GitLab sends the command to remove the temporary runner VM to the Google Compute API immediately after the CI job completes. The [Google Compute Engine hypervisor](https://cloud.google.com/blog/products/gcp/7-ways-we-harden-our-kvm-hypervisor-at-google-cloud-security-in-plaintext) takes over the task of securely deleting the virtual machine and associated data.
+
+### Network security of CI job virtual machines on GitLab Runner SaaS (Linux, Windows)
+
+- Firewall rules only allow outbound communication from the temporary VM to the public internet.
+- Inbound communication from the public internet to the temporary VM is not allowed.
+- Firewall rules do not permit communication between VMs.
+- The only internal communication allowed to the temporary VMs is from the Runner Manager.
diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md
index 8b2753d26f1..9bd0b52f423 100644
--- a/doc/ci/runners/runners_scope.md
+++ b/doc/ci/runners/runners_scope.md
@@ -25,11 +25,11 @@ multiple projects.
If you are using a self-managed instance of GitLab:
- Your administrator can install and register shared runners by
- going to your project's **Settings > CI/CD**, expanding the **Runners** section,
- and clicking **Show runner installation instructions**.
+ going to your project's **Settings > CI/CD**, expanding **Runners**,
+ and selecting **Show runner installation instructions**.
These instructions are also available [in the documentation](https://docs.gitlab.com/runner/install/index.html).
-- The administrator can also configure a maximum number of shared runner [CI/CD minutes for
- each group](../pipelines/cicd_minutes.md#set-the-quota-of-cicd-minutes-for-a-specific-namespace).
+- The administrator can also configure a maximum number of shared runner
+ [CI/CD minutes for each group](../pipelines/cicd_minutes.md#set-the-quota-of-cicd-minutes-for-a-specific-namespace).
If you are using GitLab.com:
@@ -51,15 +51,19 @@ For existing projects, an administrator must
To enable shared runners for a project:
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Select **Enable shared runners for this project**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+1. Turn on the **Enable shared runners for this project** toggle.
### Enable shared runners for a group
To enable shared runners for a group:
-1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
-1. Select **Enable shared runners for this group**.
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+1. Turn on the **Enable shared runners for this group** toggle.
### Disable shared runners for a project
@@ -69,8 +73,10 @@ or group.
To disable shared runners for a project:
-1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, select **Enable shared runners for this project** so the toggle is grayed-out.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+1. In the **Shared runners** area, turn off the **Enable shared runners for this project** toggle.
Shared runners are automatically disabled for a project:
@@ -81,9 +87,11 @@ Shared runners are automatically disabled for a project:
To disable shared runners for a group:
-1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
-1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
+1. Turn off the **Enable shared runners for this group** toggle.
+1. Optional. To allow shared runners to be enabled for individual projects or subgroups,
select **Allow projects and subgroups to override the group setting**.
NOTE:
@@ -147,7 +155,7 @@ The fair usage algorithm assigns jobs in this order:
## Group runners
-Use *Group runners* when you want all projects in a group
+Use _group runners_ when you want all projects in a group
to have access to a set of runners.
Group runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
@@ -162,7 +170,7 @@ You must have the Owner role for the group.
To create a group runner:
1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
-1. Go to the group you want to make the runner work for.
+1. On the top bar, select **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/).
@@ -175,21 +183,8 @@ You can view and manage all runners for a group, its subgroups, and projects.
You can do this for your self-managed GitLab instance or for GitLab.com.
You must have the Owner role for the group.
-1. Go to the group where you want to view the runners.
+1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **CI/CD > Runners**.
-1. The following fields are displayed.
-
- | Attribute | Description |
- | ------------ | ----------- |
- | Type | Displays the runner type: `group` or `specific`, and the optional state `paused` |
- | Runner token | Token used to identify the runner, and that the runner uses to communicate with the GitLab instance |
- | Description | Description given to the runner when it was created |
- | Version | GitLab Runner version |
- | IP address | IP address of the host on which the runner is registered |
- | Projects | The count of projects to which the runner is assigned |
- | Jobs | Total of jobs run by the runner |
- | Tags | Tags associated with the runner |
- | Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
From this page, you can edit, pause, and remove runners from the group, its subgroups, and projects.
@@ -198,7 +193,7 @@ From this page, you can edit, pause, and remove runners from the group, its subg
You can pause or remove a group runner for your self-managed GitLab instance or for GitLab.com.
You must have the Owner role for the group.
-1. Go to the group you want to remove or pause the runner for.
+1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **CI/CD > Runners**.
1. Select **Pause** or **Remove runner**.
- If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
@@ -208,7 +203,7 @@ You must have the Owner role for the group.
## Specific runners
-Use *Specific runners* when you want to use runners for specific projects. For example,
+Use _specific runners_ when you want to use runners for specific projects. For example,
when you have:
- Jobs with specific requirements, like a deploy job that requires credentials.
@@ -257,9 +252,8 @@ To enable a specific runner for a project:
1. On the top bar, select **Menu > Projects** and find the project where you want to enable the runner.
1. On the left sidebar, select **Settings > CI/CD**.
-1. Expand **General pipelines**.
1. Expand **Runners**.
-1. By the runner you want, select **Enable for this project**.
+1. In the **Specific runners** area, by the runner you want, select **Enable for this project**.
You can edit a specific runner from any of the projects it's enabled for.
The modifications, which include unlocking and editing tags and the description,
@@ -275,9 +269,10 @@ but can also be changed later.
To lock or unlock a specific runner:
-1. Go to the project's **Settings > CI/CD**.
-1. Expand the **Runners** section.
+1. On the top bar, select **Menu > Projects** and find the project where you want to enable the runner.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Runners**.
1. Find the specific runner you want to lock or unlock. Make sure it's enabled. You cannot lock shared or group runners.
1. Select **Edit** (**{pencil}**).
-1. Check the **Lock to current projects** option.
+1. Select the **Lock to current projects** checkbox.
1. Select **Save changes**.
diff --git a/doc/ci/runners/saas/linux_saas_runner.md b/doc/ci/runners/saas/linux_saas_runner.md
index f1e28f7e74d..e96e89b47e5 100644
--- a/doc/ci/runners/saas/linux_saas_runner.md
+++ b/doc/ci/runners/saas/linux_saas_runner.md
@@ -24,7 +24,7 @@ The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated
Jobs handled by shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`)
**time out after 3 hours**, regardless of the timeout configured in a
-project. Check issue [#4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
+project. Check issue [#4010](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/4070) for the reference.
Jobs handled by shared runners on Windows and macOS on GitLab.com **time out after 1 hour** while this service is in the [Beta](../../../policy/alpha-beta-support.md#beta-features) stage.
diff --git a/doc/ci/runners/saas/windows_saas_runner.md b/doc/ci/runners/saas/windows_saas_runner.md
index dddb3afee7c..f9fe6290220 100644
--- a/doc/ci/runners/saas/windows_saas_runner.md
+++ b/doc/ci/runners/saas/windows_saas_runner.md
@@ -126,8 +126,7 @@ test:
## Limitations and known issues
-- All the limitations mentioned in our [beta
- definition](../../../policy/alpha-beta-support.md#beta-features).
+- All the limitations mentioned in our [beta definition](../../../policy/alpha-beta-support.md#beta-features).
- The average provisioning time for a new Windows VM is 5 minutes.
This means that you may notice slower build start times
on the Windows runner fleet during the beta. In a future
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index ba395108966..fb91aeb6240 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -88,7 +88,7 @@ To configure your Vault server:
- `VAULT_SERVER_URL` - The URL of your Vault server, such as `https://vault.example.com:8200`.
Required.
- `VAULT_AUTH_ROLE` - Optional. The role to use when attempting to authenticate.
- If no role is specified, Vault uses the [default role](https://www.vaultproject.io/api/auth/jwt#default_role)
+ If no role is specified, Vault uses the [default role](https://www.vaultproject.io/api-docs/auth/jwt#default_role)
specified when the authentication method was configured.
- `VAULT_AUTH_PATH` - Optional. The path where the authentication method is mounted, default is `jwt`.
- `VAULT_NAMESPACE` - Optional. The [Vault Enterprise namespace](https://www.vaultproject.io/docs/enterprise/namespaces) to use for reading secrets and authentication.
@@ -183,7 +183,7 @@ For a full list of `CI_JOB_JWT` claims, read the
You can also specify some attributes for the resulting Vault tokens, such as time-to-live,
IP address range, and number of uses. The full list of options is available in
-[Vault's documentation on creating roles](https://www.vaultproject.io/api/auth/jwt#create-role)
+[Vault's documentation on creating roles](https://www.vaultproject.io/api-docs/auth/jwt#create-role)
for the JSON web token method.
## Using a self-signed Vault server
diff --git a/doc/ci/secure_files/index.md b/doc/ci/secure_files/index.md
index fb421ab8944..8e141c62ef6 100644
--- a/doc/ci/secure_files/index.md
+++ b/doc/ci/secure_files/index.md
@@ -36,7 +36,7 @@ To add a secure file to a project:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > CI/CD**.
-1. In the **Secure Files** section, select **Manage**.
+1. In the **Secure Files** section, select **Expand**.
1. Select **Upload File**.
1. Find the file to upload, select **Open**, and the file upload begins immediately.
The file shows up in the list when the upload is complete.
diff --git a/doc/ci/testing/load_performance_testing.md b/doc/ci/testing/load_performance_testing.md
index ae177958beb..e15b3944c2b 100644
--- a/doc/ci/testing/load_performance_testing.md
+++ b/doc/ci/testing/load_performance_testing.md
@@ -121,7 +121,7 @@ the k6 test.
NOTE:
For Kubernetes setups a different template should be used: [`Jobs/Load-Performance-Testing.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml).
-k6 has [various options](https://k6.io/docs/using-k6/options) to configure how it will run tests, such as what throughput (RPS) to run with,
+k6 has [various options](https://k6.io/docs/using-k6/k6-options/reference/) to configure how it will run tests, such as what throughput (RPS) to run with,
how long the test should run, and so on. Almost all options can be configured in the test itself, but as
you can also pass command line options via the `K6_OPTIONS` variable.
diff --git a/doc/ci/testing/unit_test_report_examples.md b/doc/ci/testing/unit_test_report_examples.md
index a54deb254b7..b49ac29be65 100644
--- a/doc/ci/testing/unit_test_report_examples.md
+++ b/doc/ci/testing/unit_test_report_examples.md
@@ -250,7 +250,7 @@ test:
This example uses [PHPUnit](https://phpunit.de/) with the `--log-junit` flag.
You can also add this option using
-[XML](https://phpunit.readthedocs.io/en/stable/configuration.html#the-junit-element)
+[XML](https://phpunit.readthedocs.io/en/9.5/configuration.html#the-junit-element)
in the `phpunit.xml` configuration file.
```yaml
diff --git a/doc/ci/testing/unit_test_reports.md b/doc/ci/testing/unit_test_reports.md
index c8e0d6135df..6294996c703 100644
--- a/doc/ci/testing/unit_test_reports.md
+++ b/doc/ci/testing/unit_test_reports.md
@@ -46,24 +46,44 @@ comparing the head and base branch's JUnit report format XML files, where:
- The base branch is the target branch (usually the default branch).
- The head branch is the source branch (the latest pipeline in each merge request).
-The reports panel has a summary showing how many tests failed, how many had errors
+The **Test summary** panel shows how many tests failed, how many had errors,
and how many were fixed. If no comparison can be done because data for the base branch
-is not available, the panel just shows the list of failed tests for head.
+is not available, the panel shows only the list of failed tests for the source branch.
-There are four types of results:
+The types of results are:
-1. **Newly failed tests:** Test cases which passed on base branch and failed on head branch
-1. **Newly encountered errors:** Test cases which passed on base branch and failed due to a
- test error on head branch
-1. **Existing failures:** Test cases which failed on base branch and failed on head branch
-1. **Resolved failures:** Test cases which failed on base branch and passed on head branch
+- **Newly failed tests:** Test cases which passed on the base branch and failed on the head branch.
+- **Newly encountered errors:** Test cases which passed on the base branch and failed due to a
+ test error on the head branch.
+- **Existing failures:** Test cases which failed on the base branch and failed on the head branch.
+- **Resolved failures:** Test cases which failed on the base branch and passed on the head branch.
-Each entry in the panel shows the test name and its type from the list
-above. Clicking on the test name opens a modal window with details of its
-execution time and the error output.
+### View failed tests
+
+Each entry in the **Test summary** panel shows the test name and result type.
+Select the test name to open a modal window with details of its execution time and
+the error output.
![Test Reports Widget](img/junit_test_report.png)
+#### Copy failed test names
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91552) in GitLab 15.2.
+
+You can copy the name and path of failed tests when there are failed tests listed
+in the **Test summary** panel. Use name and path to find and rerun the
+test locally for verification.
+
+To copy the name of all failed tests, at the top of the **Test summary** panel,
+select **Copy failed tests**. The failed tests are listed as a string with the tests
+separated by spaces.
+
+To copy the name of a single failed test:
+
+1. Expand the **Test summary** panel by selecting **Show test summary details** (**{chevron-lg-down}**).
+1. Select the test you want to review.
+1. Select **Copy test name to rerun locally** (**{copy-to-clipboard}**).
+
### Number of recent failures
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in merge requests in GitLab 13.7.
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 6df614c1cda..f8900501244 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -82,7 +82,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_PAGES_URL` | 11.8 | all | The URL for a GitLab Pages site. Always a subdomain of `CI_PAGES_DOMAIN`. |
| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This ID is unique across all projects on the GitLab instance. |
| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique only within the current project. |
-| `CI_PIPELINE_SOURCE` | 10.0 | all | How the pipeline was triggered. Can be `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). |
+| `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. |
@@ -93,7 +93,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | The project namespace (username or group name) of the job. |
| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` in lowercase with characters that are not `a-z` or `0-9` replaced with `-` and shortened to 63 bytes. Use in URLs and domain names. |
| `CI_PROJECT_PATH` | 8.10 | 0.5 | The project namespace with the project name included. |
-| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | A comma-separated, lowercase list of the languages used in the repository. For example `ruby,javascript,html,css`. |
+| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | A comma-separated, lowercase list of the languages used in the repository. For example `ruby,javascript,html,css`. The maximum number of languages is limited to 5. An issue [proposes to increase the limit](https://gitlab.com/gitlab-org/gitlab/-/issues/368925). |
| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The root project namespace (username or group name) of the job. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` is `root-group`. |
| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. |
| `CI_PROJECT_DESCRIPTION` | 15.1 | all | The project description as displayed in the GitLab web interface. |
@@ -124,6 +124,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CI_SERVER_VERSION` | all | all | The full version of the GitLab instance. |
| `CI_SERVER` | all | all | Available for all jobs executed in CI/CD. `yes` when available. |
| `CI_SHARED_ENVIRONMENT` | all | 10.1 | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. |
+| `CI_TEMPLATE_REGISTRY_HOST` | 15.3 | all | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. |
| `GITLAB_CI` | all | all | Available for all jobs executed in CI/CD. `true` when available. |
| `GITLAB_FEATURES` | 10.6 | all | The comma-separated list of licensed features available for the GitLab instance and license. |
| `GITLAB_USER_EMAIL` | 8.12 | all | The email of the user who started the job. |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 7a1ef61f109..db83f2a14f3 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -40,6 +40,7 @@ There are two places defined variables can be used. On the:
| [`services:name`](../yaml/index.md#services) | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). |
| [`services`](../yaml/index.md#services) | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). |
| [`tags`](../yaml/index.md#tags) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35742) in GitLab 14.1. |
+| [`trigger` and `trigger:project`](../yaml/index.md#trigger) | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367660) in GitLab 15.3. |
| [`variables`](../yaml/index.md#variables) | yes | GitLab/Runner | The variable expansion is first made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab, and then any unrecognized or unavailable variables are expanded by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism). |
### `config.toml` file
@@ -131,10 +132,17 @@ These restrictions exist because `after_script` scripts are executed in a
## Persisted variables
-The following variables are known as "persisted":
+Some predefined variables are called "persisted".
+
+Pipeline-level persisted variables:
- `CI_PIPELINE_ID`
+- `CI_PIPELINE_URL`
+
+Job-level persisted variables:
+
- `CI_JOB_ID`
+- `CI_JOB_URL`
- `CI_JOB_TOKEN`
- `CI_JOB_STARTED_AT`
- `CI_REGISTRY_USER`
@@ -143,7 +151,7 @@ The following variables are known as "persisted":
- `CI_DEPLOY_USER`
- `CI_DEPLOY_PASSWORD`
-They are:
+Persisted variables are:
- Supported for definitions where the ["Expansion place"](#gitlab-ciyml-file) is:
- Runner.
@@ -152,6 +160,9 @@ They are:
- For definitions where the ["Expansion place"](#gitlab-ciyml-file) is GitLab.
- In the `only`, `except`, and `rules` [variables expressions](../jobs/job_control.md#cicd-variable-expressions).
+[Pipeline trigger jobs](../yaml/index.md#trigger) cannot use job-level persisted variables,
+but can use pipeline-level persisted variables.
+
Some of the persisted variables contain tokens and cannot be used by some definitions
due to security reasons.
diff --git a/doc/ci/yaml/artifacts_reports.md b/doc/ci/yaml/artifacts_reports.md
index 379a4b3224a..61ef8bbfab7 100644
--- a/doc/ci/yaml/artifacts_reports.md
+++ b/doc/ci/yaml/artifacts_reports.md
@@ -329,3 +329,27 @@ GitLab can display the results of one or more reports in the merge request
[terraform widget](../../user/infrastructure/iac/mr_integration.md#output-terraform-plan-information-into-a-merge-request).
For more information, see [Output `terraform plan` information into a merge request](../../user/infrastructure/iac/mr_integration.md).
+
+## `artifacts:reports:cyclonedx`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/360766) in GitLab 15.3
+
+This report is a Software Bill of Materials describing the components of a project
+following the [cyclonedx](https://cyclonedx.org/docs/1.4) protocol format.
+
+You can specify multiple cyclonedx reports per job. These can be either supplied
+as a list of filenames, a filename pattern, or both:
+
+- List of filenames: `cyclonedx: [gl-sbom-npm-npm.cdx.json, gl-sbom-bundler-gem.cdx.json]`.
+- A filename pattern: `cyclonedx: gl-sbom-*.json`.
+- Combination of both of the above: `cyclonedx: [gl-sbom-*.json, my-cyclonedx.json]`.
+
+Below is an example of a job exposing cyclonedx artifacts:
+
+```yaml
+artifacts:
+ reports:
+ cyclonedx:
+ - gl-sbom-npm-npm.cdx.json
+ - gl-sbom-bundler-gem.cdx.json
+```
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index 838710834ba..5158f80ea64 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -289,10 +289,10 @@ smoke-test-job:
In `include` sections in your `.gitlab-ci.yml` file, you can use:
-- [Project variables](../variables/index.md#add-a-cicd-variable-to-a-project)
-- [Group variables](../variables/index.md#add-a-cicd-variable-to-a-group)
-- [Instance variables](../variables/index.md#add-a-cicd-variable-to-an-instance)
-- Project [predefined variables](../variables/predefined_variables.md)
+- [Project variables](../variables/index.md#add-a-cicd-variable-to-a-project).
+- [Group variables](../variables/index.md#add-a-cicd-variable-to-a-group).
+- [Instance variables](../variables/index.md#add-a-cicd-variable-to-an-instance).
+- Project [predefined variables](../variables/predefined_variables.md).
- In GitLab 14.2 and later, the `$CI_COMMIT_REF_NAME` [predefined variable](../variables/predefined_variables.md).
When used in `include`, the `CI_COMMIT_REF_NAME` variable returns the full
@@ -322,7 +322,11 @@ include:
file: '.compliance-gitlab-ci.yml'
```
-For an example of how you can include these predefined variables, and the variables' impact on CI/CD jobs,
+You cannot use variables defined in jobs, or in a global [`variables`](../yaml/index.md#variables)
+section which defines the default variables for all jobs. Includes are evaluated before jobs,
+so these variables cannot be used with `include`.
+
+For an example of how you can include predefined variables, and the variables' impact on CI/CD jobs,
see this [CI/CD variable demo](https://youtu.be/4XR8gw3Pkos).
## Use `rules` with `include`
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 3bb2007d6e3..0b434e7013c 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -171,11 +171,11 @@ Use `include:local` instead of symbolic links.
**Possible inputs**:
-- A full path relative to the root directory (`/`).
+A full path relative to the root directory (`/`):
+
- The YAML file must have the extension `.yml` or `.yaml`.
- You can [use `*` and `**` wildcards in the file path](includes.md#use-includelocal-with-wildcard-file-paths).
-
-CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
+- You can use [certain CI/CD variables](includes.md#use-variables-with-include).
**Example of `include:local`**:
@@ -208,10 +208,10 @@ use `include:file`. You can use `include:file` in combination with `include:proj
**Possible inputs**:
-- A full path, relative to the root directory (`/`). The YAML file must have the
- extension `.yml` or `.yaml`.
+A full path, relative to the root directory (`/`):
-CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
+- The YAML file must have the extension `.yml` or `.yaml`.
+- You can use [certain CI/CD variables](includes.md#use-variables-with-include).
**Example of `include:file`**:
@@ -268,10 +268,11 @@ Use `include:remote` with a full URL to include a file from a different location
**Possible inputs**:
-- A public URL accessible by an HTTP/HTTPS `GET` request. Authentication with the
- remote URL is not supported. The YAML file must have the extension `.yml` or `.yaml`.
+A public URL accessible by an HTTP/HTTPS `GET` request:
-CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
+- Authentication with the remote URL is not supported.
+- The YAML file must have the extension `.yml` or `.yaml`.
+- You can use [certain CI/CD variables](includes.md#use-variables-with-include).
**Example of `include:remote`**:
@@ -296,9 +297,12 @@ Use `include:template` to include [`.gitlab-ci.yml` templates](https://gitlab.co
**Possible inputs**:
-- [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+A [CI/CD template](../examples/index.md#cicd-templates):
-CI/CD variables [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file).
+- Templates are stored in [`lib/gitlab/ci/templates`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+ Not all templates are designed to be used with `include:template`, so check template
+ comments before using one.
+- You can use [certain CI/CD variables](includes.md#use-variables-with-include).
**Example of `include:template`**:
@@ -2136,7 +2140,7 @@ This example creates four paths of execution:
- The maximum number of jobs that a single job can have in the `needs` array is limited:
- For GitLab.com, the limit is 50. For more information, see our
- [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
+ [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/7541).
- For self-managed instances, the default limit is 50. This limit [can be changed](../../administration/cicd.md#set-the-needs-job-limit).
- If `needs` refers to a job that uses the [`parallel`](#parallel) keyword,
it depends on all jobs created in parallel, not just one job. It also downloads
@@ -2784,11 +2788,15 @@ which must be in the `$PATH`.
If you use the [Docker executor](https://docs.gitlab.com/runner/executors/docker.html),
you can use this image from the GitLab Container Registry: `registry.gitlab.com/gitlab-org/release-cli:latest`
+If you use the [Shell executor](https://docs.gitlab.com/runner/executors/shell.html) or similar,
+[install `release-cli`](../../user/project/releases/release_cli.md) on the server where the runner is registered.
+
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**: The `release` subkeys:
- [`tag_name`](#releasetag_name)
+- [`tag_message`](#releasetag_message) (optional)
- [`name`](#releasename) (optional)
- [`description`](#releasedescription)
- [`ref`](#releaseref) (optional)
@@ -2832,8 +2840,6 @@ This example creates a release:
- The `release` section executes after the `script` keyword and before the `after_script`.
- A release is created only if the job's main script succeeds.
- If the release already exists, it is not updated and the job with the `release` keyword fails.
-- If you use the [Shell executor](https://docs.gitlab.com/runner/executors/shell.html) or similar,
- [install `release-cli`](../../user/project/releases/release_cli.md) on the server where the runner is registered.
**Related topics**:
@@ -2887,6 +2893,30 @@ job:
- if: $CI_PIPELINE_SOURCE == "schedule"
```
+#### `release:tag_message`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363024) in GitLab 15.3. Supported by `release-cli` v0.12.0 or later.
+
+If the tag does not exist, the newly created tag is annotated with the message specifed by `tag_message`.
+If omitted, a lightweight tag is created.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- A text string.
+
+**Example of `release:tag_message`**:
+
+```yaml
+ release_job:
+ stage: release
+ release:
+ tag_name: $CI_COMMIT_TAG
+ description: 'Release description'
+ tag_message: 'Annotated tag message'
+```
+
#### `release:name`
The release name. If omitted, it is populated with the value of `release: tag_name`.
@@ -2965,7 +2995,7 @@ released_at: '2021-03-15T08:00:00Z'
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271454) in GitLab 13.12.
-Use `release:assets:links` to include [asset links](../../user/project/releases/index.md#release-assets) in the release.
+Use `release:assets:links` to include [asset links](../../user/project/releases/release_fields.md#release-assets) in the release.
Requires `release-cli` version v0.4.0 or later.
@@ -3221,6 +3251,7 @@ 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).
**Example of `rules:changes`**:
@@ -3239,6 +3270,8 @@ docker build:
- If `Dockerfile` has changed, add the job to the pipeline as a manual job, and the pipeline
continues running even if the job is not triggered (`allow_failure: true`).
- If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`).
+- [`rules:changes:paths`](#ruleschangespaths) is the same as `rules:changes` without
+ any subkeys.
**Additional details**:
@@ -3250,6 +3283,74 @@ docker build:
- [Jobs or pipelines can run unexpectedly when using `rules: changes`](../jobs/job_control.md#jobs-or-pipelines-run-unexpectedly-when-using-changes).
+##### `rules:changes:paths`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90171) in GitLab 15.2.
+
+Use `rules:changes` to specify that a job only be added to a pipeline when specific
+files are changed, and use `rules:changes:paths` to specify the files.
+
+`rules:changes:paths` is the same as using [`rules:changes`](#ruleschanges) without
+any subkeys. All additional details and related topics are the same.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- An array of file paths. In GitLab 13.6 and later, [file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
+
+**Example of `rules:changes:paths`**:
+
+```yaml
+docker-build-1:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ - Dockerfile
+
+docker-build-2:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ paths:
+ - Dockerfile
+```
+
+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.
+
+Use `rules:changes:compare_to` to specify which ref to compare against for changes to the files
+listed under [`rules:changes:paths`](#ruleschangespaths).
+
+**Keyword type**: Job keyword. You can use it only as part of a job, and it must be combined with `rules:changes:paths`.
+
+**Possible inputs**:
+
+- A branch name, like `main`, `branch1`, or `refs/heads/branch1`.
+- A tag name, like `tag1` or `refs/tags/tag1`.
+- A commit SHA, like `2fg31ga14b`.
+
+**Example of `rules:changes:compare_to`**:
+
+```yaml
+docker build:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ paths:
+ - Dockerfile
+ compare_to: 'refs/heads/branch1'
+```
+
+In this example, the `docker build` job is only included when the `Dockerfile` has changed
+relative to `refs/heads/branch1` and the pipeline source is a merge request event.
+
#### `rules:exists`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
@@ -3792,7 +3893,9 @@ Use `trigger` to start a downstream pipeline that is either:
**Possible inputs**:
-- For multi-project pipelines, path to the downstream project.
+- For multi-project pipelines, path to the downstream project. CI/CD variables
+ [are supported](../variables/where_variables_can_be_used.md#gitlab-ciyml-file)
+ in GitLab 15.3 and later.
- For child pipelines, path to the child pipeline CI/CD configuration file.
**Example of `trigger` for multi-project pipeline**:
@@ -3830,6 +3933,8 @@ trigger_job:
and [scheduled pipeline variables](../pipelines/schedules.md#add-a-pipeline-schedule)
are not passed to downstream pipelines by default. Use [trigger:forward](#triggerforward)
to forward these variables to downstream pipelines.
+- [Job-level persisted variables](../variables/where_variables_can_be_used.md#persisted-variables)
+ are not available in trigger jobs.
**Related topics**:
@@ -3861,6 +3966,17 @@ trigger_job:
In this example, jobs from subsequent stages wait for the triggered pipeline to
successfully complete before starting.
+**Additional details**:
+
+- [Optional manual jobs](../jobs/job_control.md#types-of-manual-jobs) in the downstream pipeline
+ do not affect the status of the downstream pipeline or the upstream trigger job.
+ The downstream pipeline can complete successfully without running any optional manual jobs.
+- [Blocking manual jobs](../jobs/job_control.md#types-of-manual-jobs) in the downstream pipeline
+ must run before the trigger job is marked as successful or failed. The trigger job
+ shows **pending** (**{status_pending}**) if the downstream pipeline status is
+ **waiting for manual action** (**{status_manual}**) due to manual jobs. By default,
+ jobs in later stages do not start until the trigger job completes.
+
#### `trigger:forward`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213729) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `ci_trigger_forward_variables`. Disabled by default.
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index 4bffcbca1cc..f1cdcf57e64 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -258,3 +258,27 @@ pages-job:
script:
- 'curl --header "PRIVATE-TOKEN: ${PRIVATE_TOKEN}" "https://gitlab.example.com/api/v4/projects"'
```
+
+### Job does not fail when using `&&` in a script
+
+If you use `&&` to combine two commands together in a single script line, the job
+might return as successful, even if one of the commands failed. For example:
+
+```yaml
+job-does-not-fail:
+ script:
+ - invalid-command xyz && invalid-command abc
+ - echo $?
+ - echo "The job should have failed already, but this is executed unexpectedly."
+```
+
+The `&&` operator returns an exit code of `0` even though the two commands failed,
+and the job continues to run. To force the script to exit when either command fails,
+enclose the entire line in parentheses:
+
+```yaml
+job-fails:
+ script:
+ - (invalid-command xyz && invalid-command abc)
+ - echo "The job failed already, and this is not executed."
+```
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index e80bffe7c18..7ab846cce3e 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -1,314 +1,11 @@
---
-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
+redirect_to: 'database/adding_database_indexes.md'
+remove_date: '2022-11-05'
---
-# Adding Database Indexes
+This document was moved to [another location](database/adding_database_indexes.md).
-Indexes can be used to speed up database queries, but when should you add a new
-index? Traditionally the answer to this question has been to add an index for
-every column used for filtering or joining data. For example, consider the
-following query:
-
-```sql
-SELECT *
-FROM projects
-WHERE user_id = 2;
-```
-
-Here we are filtering by the `user_id` column and as such a developer may decide
-to index this column.
-
-While in certain cases indexing columns using the above approach may make sense,
-it can actually have a negative impact. Whenever you write data to a table, any
-existing indexes must also be updated. The more indexes there are, the slower this
-can potentially become. Indexes can also take up significant disk space, depending
-on the amount of data indexed and the index type. For example, PostgreSQL offers
-`GIN` indexes which can be used to index certain data types that cannot be
-indexed by regular B-tree indexes. These indexes, however, generally take up more
-data and are slower to update compared to B-tree indexes.
-
-Because of all this, it's important make the following considerations
-when adding a new index:
-
-1. Do the new queries re-use as many existing indexes as possible?
-1. Is there enough data that using an index is faster than iterating over
- rows in the table?
-1. Is the overhead of maintaining the index worth the reduction in query
- timings?
-
-## Re-using Queries
-
-The first step is to make sure your query re-uses as many existing indexes as
-possible. For example, consider the following query:
-
-```sql
-SELECT *
-FROM todos
-WHERE user_id = 123
-AND state = 'open';
-```
-
-Now imagine we already have an index on the `user_id` column but not on the
-`state` column. One may think this query performs badly due to `state` being
-unindexed. In reality the query may perform just fine given the index on
-`user_id` can filter out enough rows.
-
-The best way to determine if indexes are re-used is to run your query using
-`EXPLAIN ANALYZE`. Depending on the joined tables and the columns being used for filtering,
-you may find an extra index doesn't make much, if any, difference.
-
-In short:
-
-1. Try to write your query in such a way that it re-uses as many existing
- indexes as possible.
-1. Run the query using `EXPLAIN ANALYZE` and study the output to find the most
- ideal query.
-
-## Data Size
-
-A database may not use an index even when a regular sequence scan
-(iterating over all rows) is faster, especially for small tables.
-
-Consider adding an index if a table is expected to grow, and your query has to filter a lot of rows.
-You may _not_ want to add an index if the table size is small (<`1,000` records),
-or if existing indexes already filter out enough rows.
-
-## Maintenance Overhead
-
-Indexes have to be updated on every table write. In the case of PostgreSQL, _all_
-existing indexes are updated whenever data is written to a table. As a
-result, having many indexes on the same table slows down writes. It's therefore important
-to balance query performance with the overhead of maintaining an extra index.
-
-Let's say that adding an index reduces SELECT timings by 5 milliseconds but increases
-INSERT/UPDATE/DELETE timings by 10 milliseconds. In this case, the new index may not be worth
-it. A new index is more valuable when SELECT timings are reduced and INSERT/UPDATE/DELETE
-timings are unaffected.
-
-## Finding Unused Indexes
-
-To see which indexes are unused you can run the following query:
-
-```sql
-SELECT relname as table_name, indexrelname as index_name, idx_scan, idx_tup_read, idx_tup_fetch, pg_size_pretty(pg_relation_size(indexrelname::regclass))
-FROM pg_stat_all_indexes
-WHERE schemaname = 'public'
-AND idx_scan = 0
-AND idx_tup_read = 0
-AND idx_tup_fetch = 0
-ORDER BY pg_relation_size(indexrelname::regclass) desc;
-```
-
-This query outputs a list containing all indexes that are never used and sorts
-them by indexes sizes in descending order. This query helps in
-determining whether existing indexes are still required. More information on
-the meaning of the various columns can be found at
-<https://www.postgresql.org/docs/current/monitoring-stats.html>.
-
-To determine if an index is still being used on production, use the following
-Thanos query with your index name:
-
-```sql
-sum(rate(pg_stat_user_indexes_idx_tup_read{env="gprd", indexrelname="index_ci_name", type="patroni-ci"}[5m]))
-```
-
-Because the query output relies on the actual usage of your database, it
-may be affected by factors such as:
-
-- Certain queries never being executed, thus not being able to use certain
- indexes.
-- Certain tables having little data, resulting in PostgreSQL using sequence
- scans instead of index scans.
-
-This data is only reliable for a frequently used database with
-plenty of data, and using as many GitLab features as possible.
-
-## Requirements for naming indexes
-
-Indexes with complex definitions must be explicitly named rather than
-relying on the implicit naming behavior of migration methods. In short,
-that means you **must** provide an explicit name argument for an index
-created with one or more of the following options:
-
-- `where`
-- `using`
-- `order`
-- `length`
-- `type`
-- `opclass`
-
-### Considerations for index names
-
-Check our [Constraints naming conventions](database/constraint_naming_convention.md) page.
-
-### Why explicit names are required
-
-As Rails is database agnostic, it generates an index name only
-from the required options of all indexes: table name and column names.
-For example, imagine the following two indexes are created in a migration:
-
-```ruby
-def up
- add_index :my_table, :my_column
-
- add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
-end
-```
-
-Creation of the second index would fail, because Rails would generate
-the same name for both indexes.
-
-This naming issue is further complicated by the behavior of the `index_exists?` method.
-It considers only the table name, column names, and uniqueness specification
-of the index when making a comparison. Consider:
-
-```ruby
-def up
- unless index_exists?(:my_table, :my_column, where: 'my_column IS NOT NULL')
- add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
- end
-end
-```
-
-The call to `index_exists?` returns true if **any** index exists on
-`:my_table` and `:my_column`, and index creation is bypassed.
-
-The `add_concurrent_index` helper is a requirement for creating indexes
-on populated tables. Because it cannot be used inside a transactional
-migration, it has a built-in check that detects if the index already
-exists. In the event a match is found, index creation is skipped.
-Without an explicit name argument, Rails can return a false positive
-for `index_exists?`, causing a required index to not be created
-properly. By always requiring a name for certain types of indexes, the
-chance of error is greatly reduced.
-
-## Temporary indexes
-
-There may be times when an index is only needed temporarily.
-
-For example, in a migration, a column of a table might be conditionally
-updated. To query which columns must be updated in the
-[query performance guidelines](query_performance.md), an index is needed
-that would otherwise not be used.
-
-In these cases, consider a temporary index. To specify a
-temporary index:
-
-1. Prefix the index name with `tmp_` and follow the [naming conventions](database/constraint_naming_convention.md).
-1. Create a follow-up issue to remove the index in the next (or future) milestone.
-1. Add a comment in the migration mentioning the removal issue.
-
-A temporary migration would look like:
-
-```ruby
-INDEX_NAME = 'tmp_index_projects_on_owner_where_emails_disabled'
-
-def up
- # Temporary index to be removed in 13.9 https://gitlab.com/gitlab-org/gitlab/-/issues/1234
- add_concurrent_index :projects, :creator_id, where: 'emails_disabled = false', name: INDEX_NAME
-end
-
-def down
- remove_concurrent_index_by_name :projects, INDEX_NAME
-end
-```
-
-## Create indexes asynchronously
-
-For very large tables, index creation can be a challenge to manage.
-While `add_concurrent_index` creates indexes in a way that does not block
-normal traffic, it can still be problematic when index creation runs for
-many hours. Necessary database operations like `autovacuum` cannot run, and
-on GitLab.com, the deployment process is blocked waiting for index
-creation to finish.
-
-To limit impact on GitLab.com, a process exists to create indexes
-asynchronously during weekend hours. Due to generally lower traffic and fewer deployments,
-index creation can proceed at a lower level of risk.
-
-### Schedule index creation for a low-impact time
-
-1. [Schedule the index to be created](#schedule-the-index-to-be-created).
-1. [Verify the MR was deployed and the index exists in production](#verify-the-mr-was-deployed-and-the-index-exists-in-production).
-1. [Add a migration to create the index synchronously](#add-a-migration-to-create-the-index-synchronously).
-
-### Schedule the index to be created
-
-Create an MR with a post-deployment migration which prepares the index
-for asynchronous creation. An example of creating an index using
-the asynchronous index helpers can be seen in the block below. This migration
-enters the index name and definition into the `postgres_async_indexes`
-table. The process that runs on weekends pulls indexes from this
-table and attempt to create them.
-
-```ruby
-# in db/post_migrate/
-
-INDEX_NAME = 'index_ci_builds_on_some_column'
-
-def up
- prepare_async_index :ci_builds, :some_column, name: INDEX_NAME
-end
-
-def down
- unprepare_async_index :ci_builds, :some_column, name: INDEX_NAME
-end
-```
-
-### Verify the MR was deployed and the index exists in production
-
-You can verify if the MR was deployed to GitLab.com by executing
-`/chatops run auto_deploy status <merge_sha>`. To verify existence of
-the index, you can:
-
-- Use a meta-command in #database-lab, such as: `\d <index_name>`.
- - Ensure that the index is not [`invalid`](https://www.postgresql.org/docs/12/sql-createindex.html#:~:text=The%20psql%20%5Cd%20command%20will%20report%20such%20an%20index%20as%20INVALID).
-- Ask someone in #database to check if the index exists.
-- With proper access, you can also verify directly on production or in a
-production clone.
-
-### Add a migration to create the index synchronously
-
-After the index is verified to exist on the production database, create a second
-merge request that adds the index synchronously. The schema changes must be
-updated and committed to `structure.sql` in this second merge request.
-The synchronous migration results in a no-op on GitLab.com, but you should still add the
-migration as expected for other installations. The below block
-demonstrates how to create the second migration for the previous
-asynchronous example.
-
-**WARNING:**
-Verify that the index exists in production before merging a second migration with `add_concurrent_index`.
-If the second migration is deployed before the index has been created,
-the index is created synchronously when the second migration executes.
-
-```ruby
-# in db/post_migrate/
-
-INDEX_NAME = 'index_ci_builds_on_some_column'
-
-disable_ddl_transaction!
-
-def up
- add_concurrent_index :ci_builds, :some_column, name: INDEX_NAME
-end
-
-def down
- remove_concurrent_index_by_name :ci_builds, INDEX_NAME
-end
-```
-
-## Test database index changes locally
-
-You must test the database index changes locally before creating a merge request.
-
-### Verify indexes created asynchronously
-
-Use the asynchronous index helpers on your local environment to test changes for creating an index:
-
-1. Enable the feature flags by running `Feature.enable(:database_async_index_creation)` and `Feature.enable(:database_reindexing)` in the Rails console.
-1. Run `bundle exec rails db:migrate` so that it creates an entry in the `postgres_async_indexes` table.
-1. Run `bundle exec rails gitlab:db:reindex` so that the index is created asynchronously.
-1. To verify the index, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) command `gdk psql` and run the command `\d <index_name>` to check that your newly created index exists.
+<!-- This redirect file can be deleted after <2022-11-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/adding_service_component.md b/doc/development/adding_service_component.md
index 51c6e86bb49..c00d9da5d16 100644
--- a/doc/development/adding_service_component.md
+++ b/doc/development/adding_service_component.md
@@ -60,7 +60,7 @@ NOTE:
Code shipped with GitLab needs to use a license approved by the Legal team. See the list of [existing approved licenses](https://about.gitlab.com/handbook/engineering/open-source/#using-open-source-libraries).
-Notify the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/) when adding a new dependency that must be compiled. We must be able to compile the dependency on all supported platforms.
+Notify the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/) when adding a new dependency that must be compiled. We must be able to compile the dependency on all supported platforms.
New services to be bundled with GitLab need to be available in the following environments.
@@ -83,7 +83,7 @@ In order for a service to be bundled for end-users or GitLab.com, it needs to be
Dependencies should be kept up to date and be tracked for security updates. For the Rails codebase, the JavaScript and Ruby dependencies are
scanned for vulnerabilities using GitLab [dependency scanning](../user/application_security/dependency_scanning/index.md).
-In addition, any system dependencies used in Omnibus packages or the Cloud Native images should be added to the [dependency update automation](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/maintenance/dependencies.io.html#adding-new-dependencies).
+In addition, any system dependencies used in Omnibus packages or the Cloud Native images should be added to the [dependency update automation](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/maintenance/dependencies.io.html#adding-new-dependencies).
## Release management
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 37de7044765..0b36b9b2f2f 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -98,11 +98,8 @@ See the [deprecating schema items](#deprecating-schema-items) section for how to
### Breaking change exemptions
-Two scenarios exist where schema items are exempt from the deprecation process,
-and can be removed or changed at any time without notice. These are schema items that either:
-
-- Use the [`feature_flag` property](#feature_flag-property) _and_ the flag is disabled by default.
-- Are [marked as alpha](#marking-schema-items-as-alpha).
+Schema items [marked as alpha](#mark-schema-items-as-alpha) are exempt from the deprecation process,
+and can be removed or changed at any time without notice.
## Global IDs
@@ -216,7 +213,6 @@ Further reading:
- [GraphQL Best Practices Guide](https://graphql.org/learn/best-practices/#nullability).
- GraphQL documentation on [Object types and fields](https://graphql.org/learn/schema/#object-types-and-fields).
-- [GraphQL Best Practices Guide](https://graphql.org/learn/best-practices/#nullability)
- [Using nullability in GraphQL](https://www.apollographql.com/blog/graphql/basics/using-nullability-in-graphql/)
### Exposing Global IDs
@@ -249,8 +245,7 @@ end
NOTE:
For specifics on implementation, see [Pagination implementation](#pagination-implementation).
-GraphQL uses [cursor based
-pagination](https://graphql.org/learn/pagination/#pagination-and-edges)
+GraphQL uses [cursor based pagination](https://graphql.org/learn/pagination/#pagination-and-edges)
to expose collections of items. This provides the clients with a lot
of flexibility while also allowing the backend to use different
pagination models.
@@ -472,93 +467,38 @@ end
## Feature flags
-Developers can add [feature flags](../development/feature_flags/index.md) to GraphQL
-fields in the following ways:
-
-- Add the [`feature_flag` property](#feature_flag-property) to a field. This allows the field to be _hidden_
- from the GraphQL schema when the flag is disabled.
-- [Toggle the return value](#toggle-the-value-of-a-field) when resolving the field.
-
-You can refer to these guidelines to decide which approach to use:
-
-- If your field is experimental, and its name or type is subject to
- change, use the [`feature_flag` property](#feature_flag-property).
-- If your field is stable and its definition doesn't change, even after the flag is
- removed, [toggle the return value](#toggle-the-value-of-a-field) of the field instead. Note that
- [all fields should be nullable](#nullable-fields) anyway.
-- If your field will be accessed from frontend using the `@include` or `@skip` directive, [do not use the `feature_flag` property](#frontend-and-backend-feature-flag-strategies).
-
-### `feature_flag` property
-
-The `feature_flag` property allows you to toggle the field's
-[visibility](https://graphql-ruby.org/authorization/visibility.html)
-in the GraphQL schema. This removes the field from the schema
-when the flag is disabled.
-
-A description is [appended](https://gitlab.com/gitlab-org/gitlab/-/blob/497b556/app/graphql/types/base_field.rb#L44-53)
-to the field indicating that it is behind a feature flag.
-
-WARNING:
-If a client queries for the field when the feature flag is disabled, the query
-fails. Consider this when toggling the visibility of the feature on or off on
-production.
-
-The `feature_flag` property does not allow the use of
-[feature gates based on actors](../development/feature_flags/index.md).
-This means that the feature flag cannot be toggled only for particular
-projects, groups, or users, but instead can only be toggled globally for
-everyone.
-
-Example:
-
-```ruby
-field :test_field, type: GraphQL::Types::String,
- null: true,
- description: 'Some test field.',
- feature_flag: :my_feature_flag
-```
-
-### Frontend and Backend feature flag strategies
-
-#### Directives
-
-When feature flags are used in the frontend to control the `@include` and `@skip` directives, do not use the `feature_flag`
-property on the server-side. For the accepted backend workaround, see [Toggle the value of a field](#toggle-the-value-of-a-field). It is recommended that the feature flag used in this approach be the same for frontend and backend.
-
-Even if the frontend directives evaluate to `@include:false` / `@skip:true`, the guarded entity is sent to the backend and matched
-against the GraphQL schema. We would then get an exception due to a schema mismatch. See the [frontend GraphQL guide](../development/fe_guide/graphql.md#the-include-directive) for more guidance.
+You can implement [feature flags](../development/feature_flags/index.md) in GraphQL to toggle:
-#### Different versions of a query
+- The return value of a field.
+- The behavior of an argument or mutation.
-See the guide frontend GraphQL guide for [different versions of a query](../development/fe_guide/graphql.md#different-versions-of-a-query), and [why it is not the preferred approach](../development/fe_guide/graphql.md#avoiding-multiple-query-versions)
-
-### Toggle the value of a field
-
-This method of using feature flags for fields is to toggle the
-return value of the field. This can be done in the resolver, in the
+This can be done in a resolver, in the
type, or even in a model method, depending on your preference and
situation.
-Consider also [marking the field as Alpha](#marking-schema-items-as-alpha)
-while the value of the field can be toggled. You can
-[change or remove Alpha fields at any time](#breaking-change-exemptions) without needing to deprecate them.
-This also signals to consumers of the public GraphQL API that the field is not
+NOTE:
+It's recommended that you also [mark the item as Alpha](#mark-schema-items-as-alpha) while it is behind a feature flag.
+This signals to consumers of the public GraphQL API that the field is not
meant to be used yet.
+You can also
+[change or remove Alpha items at any time](#breaking-change-exemptions) without needing to deprecate them. When the flag is removed, "release"
+the schema item by removing its Alpha property to make it public.
-When applying a feature flag to toggle the value of a field, the
-`description` of the field must:
+### Descriptions for feature flagged items
-- State that the value of the field can be toggled by a feature flag.
+When using a feature flag to toggle the value or behavior of a schema item, the
+`description` of the item must:
+
+- State that the value or behavior can be toggled by a feature flag.
- Name the feature flag.
-- State what the field returns when the feature flag is disabled (or
+- State what the field returns, or behavior is, when the feature flag is disabled (or
enabled, if more appropriate).
-Example:
+Example of a feature-flagged field:
```ruby
-field :foo, GraphQL::Types::String,
- null: true,
- deprecated: { reason: :alpha, milestone: '10.0' },
+field :foo, GraphQL::Types::String, null: true,
+ alpha: { milestone: '10.0' },
description: 'Some test field. Returns `null`' \
'if `my_feature_flag` feature flag is disabled.'
@@ -567,6 +507,26 @@ def foo
end
```
+Example of a feature-flagged argument:
+
+```ruby
+argument :foo, type: GraphQL::Types::String, required: false,
+ alpha: { milestone: '10.0' },
+ description: 'Some test argument. Is ignored if ' \
+ '`my_feature_flag` feature flag is disabled.'
+
+def resolve(args)
+ args.delete(:foo) unless Feature.enabled?(:my_feature_flag, object)
+ # ...
+end
+```
+
+### `feature_flag` property (deprecated)
+
+NOTE:
+This property is deprecated and should no longer be used. The property
+has been temporarily renamed to `_deprecated_feature_flag` and support for it will be removed in [#369202](https://gitlab.com/gitlab-org/gitlab/-/issues/369202).
+
## Deprecating schema items
The GitLab GraphQL API is versionless, which means we maintain backwards
@@ -586,6 +546,7 @@ To deprecate a schema item in GraphQL:
See also:
- [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations).
+- [Marking schema items as Alpha](#mark-schema-items-as-alpha).
- [How to filter Kibana for queries that used deprecated fields](graphql_guide/monitoring.md#queries-that-used-a-deprecated-field).
### Create a deprecation issue
@@ -715,7 +676,7 @@ To allow clients to continue to interact with the mutation unchanged, edit the `
```ruby
DEPRECATIONS = [
- Deprecation.new(old_model_name: 'PrometheusService', new_model_name: 'Integrations::Prometheus', milestone: '14.0')
+ Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(old_name: 'PrometheusService', new_name: 'Integrations::Prometheus', milestone: '14.0')
].freeze
```
@@ -745,28 +706,37 @@ aware of the support.
The documentation will mention that the old Global ID style is now deprecated.
-## Marking schema items as Alpha
+## Mark schema items as Alpha
-Fields, arguments, enum values, and mutations can be marked as being in
-[alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga).
+You can mark GraphQL schema items (fields, arguments, enum values, and mutations) as
+[Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga).
-An item marked as "alpha" is exempt from the deprecation process and can be removed
-at any time without notice.
+An item marked as Alpha is [exempt from the deprecation process](#breaking-change-exemptions) and can be removed
+at any time without notice. Mark an item as Alpha when it is
+subject to change and not ready for public use.
-This leverages GraphQL deprecations to cause the schema item to appear as deprecated,
-and will be described as being in "alpha" in our generated docs and its GraphQL description.
+NOTE:
+Only mark new items as Alpha. Never mark existing items
+as Alpha because they're already public.
-To mark a schema item as being in "alpha", use the `deprecated:` keyword with `reason: :alpha`.
-You must provide the `milestone:` that introduced the alpha item.
+To mark a schema item as Alpha, use the `alpha:` keyword.
+You must provide the `milestone:` that introduced the Alpha item.
For example:
```ruby
field :token, GraphQL::Types::String, null: true,
- deprecated: { reason: :alpha, milestone: '10.0' },
+ alpha: { milestone: '10.0' },
description: 'Token for login.'
```
+Alpha GraphQL items is a custom GitLab feature that leverages GraphQL deprecations. An Alpha item
+appears as deprecated in the GraphQL schema. Like all deprecated schema items, you can test an
+Alpha field in [GraphiQL](../api/graphql/index.md#graphiql). However, be aware that the GraphiQL
+autocomplete editor doesn't suggest deprecated fields.
+
+The item shows as Alpha in our generated GraphQL documentation and its GraphQL schema description.
+
## Enums
GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the
@@ -816,7 +786,7 @@ Enum values can be deprecated using the
### Defining GraphQL enums dynamically from Rails enums
-If your GraphQL enum is backed by a [Rails enum](creating_enums.md), then consider
+If your GraphQL enum is backed by a [Rails enum](database/creating_enums.md), then consider
using the Rails enum to dynamically define the GraphQL enum values. Doing so
binds the GraphQL enum values to the Rails enum definition, so if values are
ever added to the Rails enum then the GraphQL enum automatically reflects the change.
@@ -1641,8 +1611,8 @@ correctly rendered to the clients.
### Errors in mutations
-We encourage following the practice of [errors as
-data](https://graphql-ruby.org/mutations/mutation_errors) for mutations, which
+We encourage following the practice of
+[errors as data](https://graphql-ruby.org/mutations/mutation_errors) for mutations, which
distinguishes errors by who they are relevant to, defined by who can deal with
them.
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index df2f3c337cd..b72ef1bffc4 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -59,7 +59,7 @@ end
## Declared parameters
-> Grape allows you to access only the parameters that have been declared by your
+Grape allows you to access only the parameters that have been declared by your
`params` block. It filters out the parameters that have been passed, but are not
allowed.
@@ -67,7 +67,7 @@ allowed.
### Exclude parameters from parent namespaces
-> By default `declared(params)`includes parameters that were defined in all
+By default `declared(params)`includes parameters that were defined in all
parent namespaces.
– <https://github.com/ruby-grape/grape#include-parent-namespaces>
@@ -110,15 +110,15 @@ Model.create(foo: params[:foo])
With Grape v1.3+, Array types must be defined with a `coerce_with`
block, or parameters, fails to validate when passed a string from an
-API request. See the [Grape upgrading
-documentation](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions)
+API request. See the
+[Grape upgrading documentation](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions)
for more details.
### Automatic coercion of nil inputs
Prior to Grape v1.3.3, Array parameters with `nil` values would
-automatically be coerced to an empty Array. However, due to [this pull
-request in v1.3.3](https://github.com/ruby-grape/grape/pull/2040), this
+automatically be coerced to an empty Array. However, due to
+[this pull request in v1.3.3](https://github.com/ruby-grape/grape/pull/2040), this
is no longer the case. For example, suppose you define a PUT `/test`
request that has an optional parameter:
@@ -259,8 +259,8 @@ In situations where the same model has multiple entities in the API
discretion with applying this scope. It may be that you optimize for the
most basic entity, with successive entities building upon that scope.
-The `with_api_entity_associations` scope also [automatically preloads
-data](https://gitlab.com/gitlab-org/gitlab/-/blob/19f74903240e209736c7668132e6a5a735954e7c/app%2Fmodels%2Ftodo.rb#L34)
+The `with_api_entity_associations` scope also
+[automatically preloads data](https://gitlab.com/gitlab-org/gitlab/-/blob/19f74903240e209736c7668132e6a5a735954e7c/app%2Fmodels%2Ftodo.rb#L34)
for `Todo` _targets_ when returned in the [to-dos API](../api/todos.md).
For more context and discussion about preloading see
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index 2826b8a3bc4..ceb3c124d1a 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -15,8 +15,7 @@ First of all, you have to gather information and decide which are the different
limits that are set for the different GitLab tiers. Coordinate with others to [document](../administration/instance_limits.md)
and communicate those limits.
-There is a guide about [introducing application
-limits](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits).
+There is a guide about [introducing application limits](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits).
## Implement plan limits
diff --git a/doc/development/application_slis/index.md b/doc/development/application_slis/index.md
index 8d7941865e1..27e69ff3445 100644
--- a/doc/development/application_slis/index.md
+++ b/doc/development/application_slis/index.md
@@ -8,16 +8,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/525) in GitLab 14.4
-It is possible to define [Service Level Indicators
-(SLIs)](https://en.wikipedia.org/wiki/Service_level_indicator)
+It is possible to define [Service Level Indicators(SLIs)](https://en.wikipedia.org/wiki/Service_level_indicator)
directly in the Ruby codebase. This keeps the definition of operations
and their success close to the implementation and allows the people
building features to easily define how these features should be
monitored.
Defining an SLI causes 2
-[Prometheus
-counters](https://prometheus.io/docs/concepts/metric_types/#counter)
+[Prometheus counters](https://prometheus.io/docs/concepts/metric_types/#counter)
to be emitted from the rails application:
- `gitlab_sli:<sli name>:total`: incremented for each operation.
@@ -47,10 +45,9 @@ for clarity, they define different metric names:
As shown in this example, they can share a base name (`foo` in this example). We
recommend this when they refer to the same operation.
-Before the first scrape, it is important to have [initialized the SLI
-with all possible
-label-combinations](https://prometheus.io/docs/practices/instrumentation/#avoid-missing-metrics). This
-avoid confusing results when using these counters in calculations.
+Before the first scrape, it is important to have
+[initialized the SLI with all possible label-combinations](https://prometheus.io/docs/practices/instrumentation/#avoid-missing-metrics).
+This avoid confusing results when using these counters in calculations.
To initialize an SLI, use the `.initialize_sli` class method, for
example:
diff --git a/doc/development/application_slis/rails_request_apdex.md b/doc/development/application_slis/rails_request_apdex.md
index 3e3cd100183..033bffbf608 100644
--- a/doc/development/application_slis/rails_request_apdex.md
+++ b/doc/development/application_slis/rails_request_apdex.md
@@ -231,8 +231,7 @@ end
### Error budget attribution and ownership
This SLI is used for service level monitoring. It feeds into the
-[error budget for stage
-groups](../stage_group_observability/index.md#error-budget). For this
+[error budget for stage groups](../stage_group_observability/index.md#error-budget). For this
particular SLI, we have opted everyone out by default to give time to
set the correct urgencies on endpoints before it affects a group's
error budget.
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index a61a891b096..10d6c0ae9c9 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -89,7 +89,7 @@ new features and services must be written to consider Kubernetes compatibility *
The simplest way to ensure this, is to add support for your feature or service to
[the official GitLab Helm chart](https://docs.gitlab.com/charts/) or reach out to
-[the Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution).
+[the Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution).
Refer to the [process for adding new service components](adding_service_component.md) for more details.
diff --git a/doc/development/audit_event_guide/index.md b/doc/development/audit_event_guide/index.md
index 14cd2fd1dc3..0c66189a6f6 100644
--- a/doc/development/audit_event_guide/index.md
+++ b/doc/development/audit_event_guide/index.md
@@ -29,13 +29,13 @@ If you have any questions, please reach out to `@gitlab-org/manage/compliance` t
To instrument an audit event, the following attributes should be provided:
-| Attribute | Type | Required? | Description |
-|:-------------|:---------------------|:----------|:-----------------------------------------------------------------|
-| `name` | String | false | Action name to be audited. Used for error tracking |
-| `author` | User | true | User who authors the change |
-| `scope` | User, Project, Group | true | Scope which the audit event belongs to |
-| `target` | Object | true | Target object being audited |
-| `message` | String | true | Message describing the action |
+| Attribute | Type | Required? | Description |
+|:-------------|:---------------------|:----------|:------------------------------------------------------------------|
+| `name` | String | false | Action name to be audited. Used for error tracking |
+| `author` | User | true | User who authors the change |
+| `scope` | User, Project, Group | true | Scope which the audit event belongs to |
+| `target` | Object | true | Target object being audited |
+| `message` | String | true | Message describing the action ([not translated](#i18n-and-the-audit-event-message-attribute)) |
| `created_at` | DateTime | false | The time when the action occurred. Defaults to `DateTime.current` |
## How to instrument new Audit Events
@@ -195,7 +195,7 @@ deactivate B
```
In addition to recording to the database, we also write these events to
-[a log file](../../administration/logs.md#audit_jsonlog).
+[a log file](../../administration/logs/index.md#audit_jsonlog).
## Event streaming
@@ -210,3 +210,10 @@ a large amount of data. See [this merge request](https://gitlab.com/gitlab-org/g
for an example.
This feature is under heavy development. Follow the [parent epic](https://gitlab.com/groups/gitlab-org/-/epics/5925) for updates on feature
development.
+
+### I18N and the Audit Event `:message` attribute
+
+We intentionally do not translate audit event messages because translated messages would be saved in the database and served to users, regardless of their locale settings.
+
+This could mean, for example, that we use the locale for the currently logged in user to record an audit event message and stream the message to an external streaming
+destination in the wrong language for that destination. Users could find that confusing.
diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md
index 2989e10a124..55ab234cc68 100644
--- a/doc/development/auto_devops.md
+++ b/doc/development/auto_devops.md
@@ -20,8 +20,8 @@ based on your project contents. When Auto DevOps is enabled for a
project, the user does not need to explicitly include any pipeline configuration
through a [`.gitlab-ci.yml` file](../ci/yaml/index.md).
-In the absence of a `.gitlab-ci.yml` file, the [Auto DevOps CI
-template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+In the absence of a `.gitlab-ci.yml` file, the
+[Auto DevOps CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
is used implicitly to configure the pipeline for the project. This
template is a top-level template that includes other sub-templates,
which then defines jobs.
diff --git a/doc/development/backend/create_source_code_be/index.md b/doc/development/backend/create_source_code_be/index.md
index ad4e25dc815..e1ee78731de 100644
--- a/doc/development/backend/create_source_code_be/index.md
+++ b/doc/development/backend/create_source_code_be/index.md
@@ -13,7 +13,7 @@ of the [Create stage](https://about.gitlab.com/handbook/product/categories/#crea
of the [DevOps lifecycle](https://about.gitlab.com/handbook/product/categories/#devops-stages).
We interface with the Gitaly and Code Review teams, and work closely with the
-[Create:Source Code Frontend team](https://about.gitlab.com/handbook/engineering/development/dev/create-source-code-fe). The features
+[Create:Source Code Frontend team](https://about.gitlab.com/handbook/engineering/development/dev/create/create-source-code-fe/). The features
we work with are listed on the
[Features by Group Page](https://about.gitlab.com/handbook/product/categories/features/#createsource-code-group).
diff --git a/doc/development/backend/ruby_style_guide.md b/doc/development/backend/ruby_style_guide.md
index c86f21d4bac..a9fee02a15a 100644
--- a/doc/development/backend/ruby_style_guide.md
+++ b/doc/development/backend/ruby_style_guide.md
@@ -16,6 +16,8 @@ document the new rule. For every new guideline, add it in a new section and link
[version history note](../documentation/versions.md#add-a-version-history-item)
to provide context and serve as a reference.
+See also [guidelines for reusing abstractions](../reusing_abstractions.md).
+
Everything listed here can be [reopened for discussion](https://about.gitlab.com/handbook/values/#disagree-commit-and-disagree).
## Instance variable access using `attr_reader`
diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md
index 89b13efc1aa..4645bd02d9e 100644
--- a/doc/development/build_test_package.md
+++ b/doc/development/build_test_package.md
@@ -13,8 +13,8 @@ pipeline that can be used to trigger a pipeline in the Omnibus GitLab repository
that will create:
- A deb package for Ubuntu 16.04, available as a build artifact, and
-- A Docker image, which is pushed to the [Omnibus GitLab container
- registry](https://gitlab.com/gitlab-org/omnibus-gitlab/container_registry)
+- A Docker image, which is pushed to the
+ [Omnibus GitLab container registry](https://gitlab.com/gitlab-org/omnibus-gitlab/container_registry)
(images titled `gitlab-ce` and `gitlab-ee` respectively and image tag is the
commit which triggered the pipeline).
diff --git a/doc/development/cached_queries.md b/doc/development/cached_queries.md
index b0bf7c7b6f5..7af4c302e93 100644
--- a/doc/development/cached_queries.md
+++ b/doc/development/cached_queries.md
@@ -1,6 +1,6 @@
---
stage: Data Stores
-group: Memory
+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
---
diff --git a/doc/development/caching.md b/doc/development/caching.md
index 7c51bd595f7..5ae6484436e 100644
--- a/doc/development/caching.md
+++ b/doc/development/caching.md
@@ -118,8 +118,8 @@ Is the cache being added "worthy"? This can be hard to measure, but you can cons
- `tail -f log/development.log | grep "Rendered "`
- After you're looking in the right place:
- Remove or comment out sections of code until you find the cause.
- - Use `binding.pry` to poke about in live requests. This requires a foreground
- web process like [Thin](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/pry.md).
+ - Use `binding.pry` to poke about in live requests. This requires a
+ [foreground web process](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/pry.md).
#### Verification
@@ -301,10 +301,10 @@ it's time to look at a custom solution:
In short: the oldest stuff is replaced with new stuff:
-- A [useful article](https://redis.io/topics/lru-cache) about configuring Redis as an LRU cache.
+- A [useful article](https://redis.io/docs/manual/eviction/) about configuring Redis as an LRU cache.
- Lots of options for different cache eviction strategies.
- You probably want `allkeys-lru`, which is functionally similar to Memcached.
-- In Redis 4.0 and later, [allkeys-lfu is available](https://redis.io/topics/lru-cache#the-new-lfu-mode),
+- In Redis 4.0 and later, [allkeys-lfu is available](https://redis.io/docs/manual/eviction/#the-new-lfu-mode),
which is similar but different.
- We handle all explicit deletes using UNLINK instead of DEL now, which allows Redis to
reclaim memory in its own time, rather than immediately.
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 83919bab671..c5b234069e3 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -190,8 +190,8 @@ editor. Once closed, Git presents you with a new text editor instance to edit
the commit message of commit B. Add the trailer, then save and quit the editor.
If all went well, commit B is now updated.
-For more information about interactive rebases, take a look at [the Git
-documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).
+For more information about interactive rebases, take a look at
+[the Git documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).
---
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index 2065021c61b..7309b92c702 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -59,5 +59,5 @@ To request access to ChatOps on GitLab.com:
## See also
- [ChatOps Usage](../ci/chatops/index.md)
-- [Understanding EXPLAIN plans](understanding_explain_plans.md)
+- [Understanding EXPLAIN plans](database/understanding_explain_plans.md)
- [Feature Groups](feature_flags/index.md#feature-groups)
diff --git a/doc/development/code_intelligence/index.md b/doc/development/code_intelligence/index.md
index 3a8845084c3..a89730383e4 100644
--- a/doc/development/code_intelligence/index.md
+++ b/doc/development/code_intelligence/index.md
@@ -35,8 +35,8 @@ sequenceDiagram
Workhorse-->>-Runner: request results
```
-1. The CI/CD job generates a document in an LSIF format (usually `dump.lsif`) using [an
- indexer](https://lsif.dev) for the language of a project. The format
+1. The CI/CD job generates a document in an LSIF format (usually `dump.lsif`) using
+ [an indexer](https://lsif.dev) for the language of a project. The format
[describes](https://github.com/sourcegraph/sourcegraph/blob/main/doc/code_intelligence/explanations/writing_an_indexer.md)
interactions between a method or function and its definitions or references. The
document is marked to be stored as an LSIF report artifact.
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 1225260e600..e9e546c6f9b 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -62,6 +62,9 @@ Team members' domain expertise can be viewed on the [engineering projects](https
### Reviewer roulette
+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
@@ -110,6 +113,12 @@ The [Roulette dashboard](https://gitlab-org.gitlab.io/gitlab-roulette) contains:
For more information, review [the roulette README](https://gitlab.com/gitlab-org/gitlab-roulette).
+As an experiment, we want to introduce a `local` reviewer status for database reviews. Local reviewers are reviewers
+focusing on work from a team/stage, but not outside of it. This helps to focus and build great domain
+knowledge. We are not introducing changes to the reviewer roulette till we evaluate the impact and feedback from this
+experiment. We ask to respect reviewers who decline reviews based on their focus on `local` reviews. For tracking purposes,
+please use in your personal YAML file entry: `- reviewer database local` instead of `- reviewer database`.
+
### Approval guidelines
As described in the section on the responsibility of the maintainer below, you
@@ -135,7 +144,7 @@ with [domain expertise](#domain-experts).
More information about license compatibility can be found in our
[GitLab Licensing and Compatibility documentation](licensing.md).
1. If your merge request includes a new dependency or a file system change, it must be
- **approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
+ **approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution) for more details.
1. If your merge request includes documentation changes, it must be **approved
by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)**,
based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
@@ -144,7 +153,7 @@ with [domain expertise](#domain-experts).
by a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)**.
1. If your merge request only includes end-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)**
1. If your merge request includes a new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**.
-1. If your merge request includes Product Intelligence (telemetry or analytics) changes, it should be reviewed and approved by a [Product Intelligence engineer](https://gitlab.com/gitlab-org/growth/product-intelligence/engineers).
+1. If your merge request includes Product Intelligence (telemetry or analytics) changes, it should be reviewed and approved by a [Product Intelligence engineer](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/engineers).
1. If your merge request includes an addition of, or changes to a [Feature spec](testing_guide/testing_levels.md#frontend-feature-tests), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa) or [Quality reviewer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_qa)**.
1. If your merge request introduces a new service to GitLab (Puma, Sidekiq, Gitaly are examples), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**. See the [process for adding a service component to GitLab](adding_service_component.md) for details.
1. If your merge request includes changes related to authentication or authorization, it must be **approved by a [Manage:Authentication and Authorization team member](https://about.gitlab.com/company/team/)**. Check the [code review section on the group page](https://about.gitlab.com/handbook/engineering/development/dev/manage/authentication-and-authorization/#additional-considerations) for more details. Patterns for files known to require review from the team are listed in the in the `Authentication and Authorization` section of the [`CODEOWNERS`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/CODEOWNERS) file, and the team will be listed in the approvers section of all merge requests that modify these files.
@@ -176,7 +185,7 @@ See the [test engineering process](https://about.gitlab.com/handbook/engineering
1. I have tested this MR in [all supported browsers](../install/requirements.md#supported-web-browsers), or determined that this testing is not needed.
1. I have confirmed that this change is [backwards compatible across updates](multi_version_compatibility.md), or I have decided that this does not apply.
1. I have properly separated EE content from FOSS, or this MR is FOSS only.
- - [Where should EE code go?](ee_features.md#separation-of-ee-code)
+ - [Where should EE code go?](ee_features.md)
1. I have considered that existing data may be surprisingly varied. For example, a new model validation can break existing records. Consider making validation on existing data optional rather than required if you haven't confirmed that existing data will pass validation.
##### Performance, reliability, and availability
@@ -278,13 +287,29 @@ This saves reviewers time and helps authors catch mistakes earlier.
### The responsibility of the reviewer
+Reviewers are responsible for reviewing the specifics of the chosen solution.
+
[Review the merge request](#reviewing-a-merge-request) thoroughly.
Verify that the merge request meets all [contribution acceptance criteria](contributing/merge_request_workflow.md#contribution-acceptance-criteria).
-If a merge request is too large, fixes more than one issue, or implements more
-than one feature, you should guide the author towards splitting the merge request
-into smaller merge requests.
+Some merge requests may require domain experts to help with the specifics.
+Reviewers, if they are not a domain expert in the area, can do any of the following:
+
+- Review the merge request and loop in a domain expert for another review. This expert
+ can either be another reviewer or a maintainer.
+- Pass the review to another reviewer they deem more suitable.
+- If no domain experts are available, review on a best-effort basis.
+
+You should guide the author towards splitting the merge request into smaller merge requests if it is:
+
+- Too large.
+- Fixes more than one issue.
+- Implements more than one feature.
+- Has a high complexity resulting in additional risk.
+
+The author may choose to request that the current maintainers and reviewers review the split MRs
+or request a new group of maintainers and reviewers.
When you are confident
that it meets all requirements, you should:
@@ -308,19 +333,6 @@ Because a maintainer's job only depends on their knowledge of the overall GitLab
codebase, and not that of any specific domain, they can review, approve, and merge
merge requests from any team and in any product area.
-A maintainer should ask the author to make a merge request smaller if it is:
-
-- Too large.
-- Fixes more than one issue.
-- Implements more than one feature.
-- Has a high complexity resulting in additional risk.
-
-The maintainer, any of the
-reviewers, or a merge request coach can step up to help the author to divide work
-into smaller iterations, and guide the author on how to split the merge request.
-The author may choose to request that the current maintainers and reviewers review the split MRs
-or request a new group of maintainers and reviewers.
-
Maintainers do their best to also review the specifics of the chosen solution
before merging, but as they are not necessarily [domain experts](#domain-experts), they may be poorly
placed to do so without an unreasonable investment of time. In those cases, they
@@ -401,7 +413,7 @@ first time.
of your shiny new branch, read through the entire diff. Does it make sense?
Did you include something unrelated to the overall purpose of the changes? Did
you forget to remove any debugging code?
-- Write a detailed description as outlined in the [merge request guidelines](contributing/merge_request_workflow.md#merge-request-guidelines).
+- Write a detailed description as outlined in the [merge request guidelines](contributing/merge_request_workflow.md#merge-request-guidelines-for-contributors).
Some reviewers may not be familiar with the product feature or area of the
codebase. Thorough descriptions help all reviewers understand your request
and test effectively.
@@ -445,7 +457,7 @@ You can also use `workflow::ready for review` label. That means that your merge
When your merge request receives an approval from the first reviewer it can be passed to a maintainer. You should default to choosing a maintainer with [domain expertise](#domain-experts), and otherwise follow the Reviewer Roulette recommendation or use the label `ready for merge`.
-Sometimes, a maintainer may not be available for review. They could be out of the office or [at capacity](#review-response-slo).
+Sometimes, a maintainer may not be available for review. They could be out of the office or [at capacity](https://about.gitlab.com/handbook/engineering/workflow/code-review/#review-response-slo).
You can and should check the maintainer's availability in their profile. If the maintainer recommended by
the roulette is not available, choose someone else from that list.
@@ -466,6 +478,8 @@ experience, refactors the existing code). Then:
- Offer alternative implementations, but assume the author already considered
them. ("What do you think about using a custom validator here?")
- Seek to understand the author's perspective.
+- Check out the branch, and test the changes locally. You can decide how much manual testing you want to perform.
+ Your testing might result in opportunities to add automated tests.
- If you don't understand a piece of code, _say so_. There's a good chance
someone else would be confused by it as well.
- Ensure the author is clear on what is required from them to address/resolve the suggestion.
@@ -494,34 +508,29 @@ Before taking the decision to merge:
- If the MR contains both Quality and non-Quality-related changes, the MR should be merged by the relevant maintainer for user-facing changes (backend, frontend, or database) after the Quality related changes are approved by a Software Engineer in Test.
If a merge request is fundamentally ready, but needs only trivial fixes (such as
-typos), consider demonstrating a [bias for
-action](https://about.gitlab.com/handbook/values/#bias-for-action) by making
-those changes directly without going back to the author. You can do this by
+typos), consider demonstrating a [bias for action](https://about.gitlab.com/handbook/values/#bias-for-action)
+by making those changes directly without going back to the author. You can do this by
using the [suggest changes](../user/project/merge_requests/reviews/suggestions.md) feature to apply
your own suggestions to the merge request. Note that:
- If the changes are not straightforward, please prefer allowing the author to make the change.
- **Before applying suggestions**, edit the merge request to make sure
- [squash and
- merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
+ [squash and merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
is enabled, otherwise, the pipeline's Danger job fails.
- If a merge request does not have squash and merge enabled, and it
has more than one commit, then see the note below about rewriting
commit history.
-As a maintainer, if a merge request that you authored has received all required approvals, it is acceptable to show a [bias for action](https://about.gitlab.com/handbook/values/#bias-for-action) and merge your own MR, if:
-
-- The last maintainer to review intended to start the merge and did not, OR
-- The last maintainer to review started the merge, but some trivial chore caused the pipeline to break. For example, the MR might need a rebase first because of unrelated pipeline issues, or some files might need to be regenerated (like `gitlab.pot`).
- - "Trivial" is a subjective measure but we expect project maintainers to exercise their judgement carefully and cautiously.
+Authors are not authorized to merge their own merge requests and need to seek another maintainer to merge.
+This policy is in place to satisfy the CHG-04 control of the GitLab
+[Change Management Controls](https://about.gitlab.com/handbook/engineering/security/security-assurance/security-compliance/guidance/change-management.html).
When ready to merge:
WARNING:
**If the merge request is from a fork, also check the [additional guidelines for community contributions](#community-contributions).**
-- Consider using the [Squash and
- merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
+- Consider using the [Squash and merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
feature when the merge request has a lot of commits.
When merging code, a maintainer should only use the squash feature if the
author has already set this option, or if the merge request clearly contains a
@@ -541,8 +550,7 @@ WARNING:
enough to `main`.
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
subsequent revisions for anything that would be spotted after that.
-- For merge requests that have had [Squash and
- merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge) set,
+- For merge requests that have had [Squash and merge](../user/project/merge_requests/squash_and_merge.md#squash-and-merge) set,
the squashed commit's default commit message is taken from the merge request title.
You're encouraged to [select a commit with a more informative commit message](../user/project/merge_requests/squash_and_merge.md) before merging.
@@ -586,7 +594,7 @@ If the MR source branch is more than 1,000 commits behind the target branch:
When an MR needs further changes but the author is not responding for a long period of time,
or is unable to finish the MR, GitLab can take it over in accordance with our
-[Closing policy for issues and merge requests](contributing/#closing-policy-for-issues-and-merge-requests).
+[Closing policy for issues and merge requests](contributing/index.md#closing-policy-for-issues-and-merge-requests).
A GitLab engineer (generally the merge request coach) will:
1. Add a comment to their MR saying you'll take it over to be able to get it merged.
@@ -683,42 +691,6 @@ Enterprise Edition instance. This has some implications:
Ensure that we support object storage for any file storage we need to perform. For more
information, see the [uploads documentation](uploads/index.md).
-### Review turnaround time
-
-Because [unblocking others is always a top priority](https://about.gitlab.com/handbook/values/#global-optimization),
-reviewers are expected to review merge requests in a timely manner,
-even when this may negatively impact their other tasks and priorities.
-
-Doing so allows everyone involved in the merge request to iterate faster as the
-context is fresh in memory, and improves contributors' experience significantly.
-
-#### Review-response SLO
-
-To ensure swift feedback to ready-to-review code, we maintain a `Review-response` Service-level Objective (SLO). The SLO is defined as:
-
-> Review-response SLO = (time when first review is provided) - (time MR is assigned to reviewer) < 2 business days
-
-If you don't think you can review a merge request in the `Review-response` SLO
-time frame, let the author know as soon as possible in the comments
-(no later than 36 hours after first receiving the review request)
-and try to help them find another reviewer or maintainer who is able to, so that they can be unblocked
-and get on with their work quickly. Remove yourself as a reviewer.
-
-If you think you are at capacity and are unable to accept any more reviews until
-some have been completed, communicate this through your GitLab status by setting
-the 🔴 `:red_circle:` emoji and mentioning that you are at capacity in the status
-text. This guides contributors to pick a different reviewer, helping us to
-meet the SLO.
-
-Of course, if you are out of office and have
-[communicated](https://about.gitlab.com/handbook/paid-time-off/#communicating-your-time-off)
-this through your GitLab.com Status, authors are expected to realize this and
-find a different reviewer themselves.
-
-When a merge request author has been blocked for longer than
-the `Review-response` SLO, they are free to remind the reviewer through Slack or add
-another reviewer.
-
### Customer critical merge requests
A merge request may benefit from being considered a customer critical priority because there is a significant benefit to the business in doing so.
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index ce013a9254b..04915985dc8 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -68,9 +68,9 @@ Check states using your browser's _styles inspector_ to toggle CSS pseudo-classe
like `:hover` and others ([Chrome](https://developer.chrome.com/docs/devtools/css/reference/#pseudo-class),
[Firefox](https://firefox-source-docs.mozilla.org/devtools-user/page_inspector/how_to/examine_and_edit_css/index.html#viewing-common-pseudo-classes)).
-- Account for all applicable states ([error](https://design.gitlab.com/content/error-messages),
+- Account for all applicable states ([error](https://design.gitlab.com/content/error-messages/),
rest, loading, focus, hover, selected, disabled).
-- Account for states dependent on data size ([empty](https://design.gitlab.com/regions/empty-states),
+- Account for states dependent on data size ([empty](https://design.gitlab.com/regions/empty-states/),
some data, and lots of data).
- Account for states dependent on user role, user preferences, and subscription.
- Consider animations and transitions, and follow their [guidelines](https://design.gitlab.com/product-foundations/motion/).
@@ -113,7 +113,7 @@ When the design is ready, _before_ starting its implementation:
At any moment, but usually _during_ or _after_ the design's implementation:
-- Contribute [issues to Pajamas](https://design.gitlab.com/get-started/contribute#contribute-an-issue)
+- Contribute [issues to Pajamas](https://design.gitlab.com/get-started/contribute/#contribute-an-issue)
for additions or enhancements to the design system.
- Create issues with the [`~UX debt`](issue_workflow.md#technical-and-ux-debt)
label for intentional deviations from the agreed-upon UX requirements due to
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index 12fd7c3dc12..6999ffe810e 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -186,21 +186,11 @@ reasons for including it.
Mention a maintainer in merge requests that contain:
- More than 500 changes.
-- Any major [breaking changes](#breaking-changes).
+- Any major [breaking changes](../deprecation_guidelines/index.md).
- External libraries.
If you are not sure who to mention, the reviewer will do this for you early in the merge request process.
-#### Breaking changes
-
-A "breaking change" is any change that requires users to make a corresponding change to their code, settings, or workflow. "Users" might be humans, API clients, or even code classes that "use" another class. Examples of breaking changes include:
-
-- Removing a user-facing feature without a replacement/workaround.
-- Changing the definition of an existing API (by doing things like re-naming query parameters or changing routes).
-- Removing a public method from a code class.
-
-A breaking change can be considered "major" if it affects many users, or represents a significant change in behavior.
-
#### Issues workflow
This [documentation](issue_workflow.md) outlines the current issue workflow:
@@ -218,7 +208,7 @@ This [documentation](issue_workflow.md) outlines the current issue workflow:
This [documentation](merge_request_workflow.md) outlines the current merge request process.
-- [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines)
+- [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines-for-contributors)
- [Contribution acceptance criteria](merge_request_workflow.md#contribution-acceptance-criteria)
- [Definition of done](merge_request_workflow.md#definition-of-done)
- [Dependencies](merge_request_workflow.md#dependencies)
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index c6d977cf5ad..d557319b41f 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -53,7 +53,7 @@ Most issues will have labels for at least one of the following:
- Priority: `~"priority::1"`, `~"priority::2"`, `~"priority::3"`, `~"priority::4"`
- Severity: ~`"severity::1"`, `~"severity::2"`, `~"severity::3"`, `~"severity::4"`
-Please add `~"breaking change"` label if the issue can be considered as a [breaking change](index.md#breaking-changes).
+Please add `~"breaking change"` label if the issue can be considered as a [breaking change](../deprecation_guidelines/index.md).
Please add `~security` label if the issue is related to application security.
@@ -161,7 +161,7 @@ For instance, the "DevOps Reports" category is represented by the
`devops_reports.name` value is "DevOps Reports".
If a category's label doesn't respect this naming convention, it should be specified
-with [the `label` attribute](https://about.gitlab.com/handbook/marketing/inbound-marketing/digital-experience/website/#category-attributes)
+with [the `label` attribute](https://about.gitlab.com/handbook/marketing/digital-experience/website/#category-attributes)
in <https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml>.
### Feature labels
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index eff1d2e671d..faa1642d50a 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -33,7 +33,7 @@ some potentially easy issues.
To start developing GitLab, download the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit)
and see the [Development section](../../index.md) for the required guidelines.
-## Merge request guidelines
+## Merge request guidelines for contributors
If you find an issue, please submit a merge request with a fix or improvement, if
you can, and include tests. If you don't know how to fix the issue but can write a test
@@ -45,20 +45,10 @@ request is as follows:
1. [Fork](../../user/project/repository/forking_workflow.md) the project into
your personal namespace (or group) on GitLab.com.
1. Create a feature branch in your fork (don't work off your [default branch](../../user/project/repository/branches/default.md)).
-1. Write [tests](../rake_tasks.md#run-tests) and code.
-1. [Ensure a changelog is created](../changelog.md).
-1. If you are writing documentation, make sure to follow the
- [documentation guidelines](../documentation/index.md).
1. Follow the [commit messages guidelines](#commit-messages-guidelines).
-1. If you have multiple commits, combine them into a few logically organized
- commits by [squashing them](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing),
- but do not change the commit history if you're working on shared branches though.
+1. If you have multiple commits, combine them into a few logically organized commits.
1. Push the commits to your working branch in your fork.
-1. Submit a merge request (MR) to the `main` branch in the main GitLab project.
- 1. Your merge request needs at least 1 approval, but depending on your changes
- you might need additional approvals. Refer to the [Approval guidelines](../code_review.md#approval-guidelines).
- 1. You don't have to select any specific approvers, but you can if you really want
- specific people to approve your merge request.
+1. Submit a merge request (MR) against the default branch of the upstream project.
1. The MR title should describe the change you want to make.
1. The MR description should give a reason for your change.
1. If you are contributing code, fill in the description according to the default
@@ -68,58 +58,15 @@ request is as follows:
1. Use the syntax `Solves #XXX`, `Closes #XXX`, or `Refs #XXX` to mention the issues your merge
request addresses. Referenced issues do not [close automatically](../../user/project/issues/managing_issues.md#closing-issues-automatically).
You must close them manually once the merge request is merged.
- 1. The MR must include *Before* and *After* screenshots if UI changes are made.
- 1. Include any steps or setup required to ensure reviewers can view the changes you've made (for example, include any information about feature flags).
1. If you're allowed to, set a relevant milestone and [labels](issue_workflow.md).
MR labels should generally match the corresponding issue (if there is one).
The group label should reflect the group that executed or coached the work,
not necessarily the group that owns the feature.
-1. UI changes should use available components from the GitLab Design System,
- [Pajamas](https://design.gitlab.com/).
-1. If the MR changes CSS classes, please include the list of affected pages, which
- can be found by running `grep css-class ./app -R`.
-1. If your MR touches code that executes shell commands, reads or opens files, or
- handles paths to files on disk, make sure it adheres to the
- [shell command guidelines](../shell_commands.md)
-1. [Code changes should include observability instrumentation](../code_review.md#observability-instrumentation).
-1. If your code needs to handle file storage, see the [uploads documentation](../uploads/index.md).
-1. If your merge request adds one or more migrations, make sure to execute all
- migrations on a fresh database before the MR is reviewed. If the review leads
- to large changes in the MR, execute the migrations again once the review is complete.
-1. Write tests for more complex migrations.
-1. If your merge request adds new validations to existing models, to make sure the
- data processing is backwards compatible:
-
- - Ask in the [`#database`](https://gitlab.slack.com/archives/CNZ8E900G) Slack channel
- for assistance to execute the database query that checks the existing rows to
- ensure existing rows aren't impacted by the change.
- - Add the necessary validation with a feature flag to be gradually rolled out
- following [the rollout steps](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#rollout).
-
- If this merge request is urgent, the code owners should make the final call on
- whether reviewing existing rows should be included as an immediate follow-up task
- to the merge request.
-
- NOTE:
- There isn't a way to know anything about our customers' data on their
- [self-managed instances](../../subscriptions/self_managed/index.md), so keep
- that in mind for any data implications with your merge request.
-
-1. Merge requests **must** adhere to the [merge request performance guidelines](../merge_request_performance_guidelines.md).
-1. For tests that use Capybara, read
- [how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
-1. If your merge request introduces changes that require additional steps when
- installing GitLab from source, add them to `doc/install/installation.md` in
- the same merge request.
-1. If your merge request introduces changes that require additional steps when
- upgrading GitLab from source, add them to
- `doc/update/upgrading_from_source.md` in the same merge request. If these
- instructions are specific to a version, add them to the "Version specific
- upgrading instructions" section.
1. Read and adhere to
[The responsibility of the merge request author](../code_review.md#the-responsibility-of-the-merge-request-author).
1. Read and follow
[Having your merge request reviewed](../code_review.md#having-your-merge-request-reviewed).
+1. Make sure the merge request meets the [Definition of done](#definition-of-done).
If you would like quick feedback on your merge request feel free to mention someone
from the [core team](https://about.gitlab.com/community/core-team/) or one of the
@@ -172,7 +119,7 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
#### Why these standards matter
1. Consistent commit messages that follow these guidelines make the history more readable.
-1. Concise standard commit messages helps to identify [breaking changes](index.md#breaking-changes) for a deployment or ~"master:broken" quicker when
+1. Concise standard commit messages helps to identify [breaking changes](../deprecation_guidelines/index.md) for a deployment or ~"master:broken" quicker when
reviewing commits between two points in time.
#### Commit message template
@@ -218,12 +165,12 @@ the contribution acceptance criteria below:
exposing a bug in existing code). Every new class should have corresponding
unit tests, even if the class is exercised at a higher level, such as a feature test.
- If a failing CI build seems to be unrelated to your contribution, you can try
- restarting the failing CI job, rebasing from `main` to bring in updates that
+ restarting the failing CI job, rebasing on top of target branch to bring in updates that
may resolve the failure, or if it has not been fixed yet, ask a developer to
help you fix the test.
-1. The MR initially contains a few logically organized commits.
+1. The MR contains a few logically organized commits, or has [squashing commits enabled](../../user/project/merge_requests/squash_and_merge.md#squash-and-merge).
1. The changes can merge without problems. If not, you should rebase if you're the
- only one working on your feature branch, otherwise merge `main`.
+ only one working on your feature branch, otherwise merge the default branch into the MR branch.
1. Only one specific issue is fixed or one specific feature is implemented. Do not
combine things; send separate merge requests for each issue or feature.
1. Migrations should do only one thing (for example, create a table, move data to a new
@@ -258,13 +205,60 @@ requirements.
### MR Merge
-1. Clear description explaining the relevancy of the contribution.
+1. Clear title and description explaining the relevancy of the contribution.
1. Working and clean code that is commented where needed.
-1. [Unit, integration, and system tests](../testing_guide/index.md) that all pass
- on the CI server.
-1. Peer member testing is optional but recommended when the risk of a change is high. This includes when the changes are [far-reaching](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work) or are for [components critical for security](../code_review.md#security).
-1. Regressions and bugs are covered with tests that reduce the risk of the issue happening
- again.
+1. The change is evaluated to [limit the impact of far-reaching work](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work).
+1. Testing:
+
+ - [Unit, integration, and system tests](../testing_guide/index.md) that all pass
+ on the CI server.
+ - Peer member testing is optional but recommended when the risk of a change is high.
+ This includes when the changes are [far-reaching](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work)
+ or are for [components critical for security](../code_review.md#security).
+ - Description includes any steps or setup required to ensure reviewers can view the changes you've made (for example, include any information about feature flags).
+ - Regressions and bugs are covered with tests that reduce the risk of the issue happening
+ again.
+ - For tests that use Capybara, read
+ [how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
+ - [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-at-the-system-level-aka-end-to-end-tests)
+ added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams)
+ with any questions.
+ - The change is tested in a review app where possible and if appropriate.
+1. In case of UI changes:
+
+ - Use available components from the GitLab Design System,
+ [Pajamas](https://design.gitlab.com/).
+ - The MR must include *Before* and *After* screenshots if UI changes are made.
+ - If the MR changes CSS classes, please include the list of affected pages, which
+ can be found by running `grep css-class ./app -R`.
+1. If your MR touches code that executes shell commands, reads or opens files, or
+ handles paths to files on disk, make sure it adheres to the
+ [shell command guidelines](../shell_commands.md)
+1. [Code changes should include observability instrumentation](../code_review.md#observability-instrumentation).
+1. If your code needs to handle file storage, see the [uploads documentation](../uploads/index.md).
+1. If your merge request adds one or more migrations:
+ - Make sure to execute all migrations on a fresh database before the MR is reviewed.
+ If the review leads to large changes in the MR, execute the migrations again
+ after the review is complete.
+ - Write tests for more complex migrations.
+1. If your merge request adds new validations to existing models, to make sure the
+ data processing is backwards compatible:
+
+ - Ask in the [`#database`](https://gitlab.slack.com/archives/CNZ8E900G) Slack channel
+ for assistance to execute the database query that checks the existing rows to
+ ensure existing rows aren't impacted by the change.
+ - Add the necessary validation with a feature flag to be gradually rolled out
+ following [the rollout steps](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#rollout).
+
+ If this merge request is urgent, the code owners should make the final call on
+ whether reviewing existing rows should be included as an immediate follow-up task
+ to the merge request.
+
+ NOTE:
+ There isn't a way to know anything about our customers' data on their
+ [self-managed instances](../../subscriptions/self_managed/index.md), so keep
+ that in mind for any data implications with your merge request.
+
1. Code affected by a feature flag is covered by [automated tests with the feature flag enabled and disabled](../feature_flags/index.md#feature-flags-in-tests), or both
states are tested as part of peer member testing or as part of the rollout plan.
1. [Performance guidelines](../merge_request_performance_guidelines.md) have been followed.
@@ -272,16 +266,22 @@ requirements.
1. [Application and rate limit guidelines](../merge_request_application_and_rate_limit_guidelines.md) have been followed.
1. [Documented](../documentation/index.md) in the `/doc` directory.
1. [Changelog entry added](../changelog.md), if necessary.
+1. If your merge request introduces changes that require additional steps when
+ installing GitLab from source, add them to `doc/install/installation.md` in
+ the same merge request.
+1. If your merge request introduces changes that require additional steps when
+ upgrading GitLab from source, add them to
+ `doc/update/upgrading_from_source.md` in the same merge request. If these
+ instructions are specific to a version, add them to the "Version specific
+ upgrading instructions" section.
1. Reviewed by relevant reviewers, and all concerns are addressed for Availability, Regressions, and Security. Documentation reviews should take place as soon as possible, but they should not block a merge request.
1. The [MR acceptance checklist](../code_review.md#acceptance-checklist) has been checked as confirmed in the MR.
-1. Create an issue in the [infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues) to inform the Infrastructure department when your contribution is changing default settings or introduces a new setting, if relevant.
-1. [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-at-the-system-level-aka-end-to-end-tests)
- added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams)
- with any questions.
-1. The change is tested in a review app where possible and if appropriate.
-1. The new feature does not degrade the user experience of the product.
-1. The change is evaluated to [limit the impact of far-reaching work](https://about.gitlab.com/handbook/engineering/development/#reducing-the-impact-of-far-reaching-work).
+1. Create an issue in the [infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues) to inform the Infrastructure department when your contribution is changing default settings or introduces a new setting, if relevant.
1. An agreed-upon [rollout plan](https://about.gitlab.com/handbook/engineering/development/processes/rollout-plans/).
+1. Your merge request has at least 1 approval, but depending on your changes
+ you might need additional approvals. Refer to the [Approval guidelines](../code_review.md#approval-guidelines).
+ - You don't have to select any specific approvers, but you can if you really want
+ specific people to approve your merge request.
1. Merged by a project maintainer.
### Production use
@@ -319,8 +319,8 @@ request:
We allow engineering time to fix small problems (with or without an
issue) that are incremental improvements, such as:
-1. Unprioritized bug fixes (for example, [Banner alerting of project move is
-showing up everywhere](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18985))
+1. Unprioritized bug fixes (for example,
+ [Banner alerting of project move is showing up everywhere](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18985))
1. Documentation improvements
1. RuboCop or Code Quality improvements
diff --git a/doc/development/creating_enums.md b/doc/development/creating_enums.md
index 450cb97d978..d3892c4c44e 100644
--- a/doc/development/creating_enums.md
+++ b/doc/development/creating_enums.md
@@ -1,154 +1,11 @@
---
-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
+redirect_to: 'database/creating_enums.md'
+remove_date: '2022-11-06'
---
-# Creating enums
+This document was moved to [another location](database/creating_enums.md).
-When creating a new enum, it should use the database type `SMALLINT`.
-The `SMALLINT` type size is 2 bytes, which is sufficient for an enum.
-This would help to save space in the database.
-
-To use this type, add `limit: 2` to the migration that creates the column.
-
-Example:
-
-```ruby
-def change
- add_column :ci_job_artifacts, :file_format, :integer, limit: 2
-end
-```
-
-## All of the key/value pairs should be defined in FOSS
-
-**Summary:** All enums needs to be defined in FOSS, if a model is also part of the FOSS.
-
-```ruby
-class Model < ApplicationRecord
- enum platform: {
- aws: 0,
- gcp: 1 # EE-only
- }
-end
-```
-
-When you add a new key/value pair to a `enum` and if it's EE-specific, you might be
-tempted to organize the `enum` as the following:
-
-```ruby
-# Define `failure_reason` enum in `Pipeline` model:
-class Pipeline < ApplicationRecord
- enum failure_reason: Enums::Pipeline.failure_reasons
-end
-```
-
-```ruby
-# Define key/value pairs that used in FOSS and EE:
-module Enums
- module Pipeline
- def self.failure_reasons
- { unknown_failure: 0, config_error: 1 }
- end
- end
-end
-
-Enums::Pipeline.prepend_mod_with('Enums::Pipeline')
-```
-
-```ruby
-# Define key/value pairs that used in EE only:
-module EE
- module Enums
- module Pipeline
- override :failure_reasons
- def failure_reasons
- super.merge(activity_limit_exceeded: 2)
- end
- end
- end
-end
-```
-
-This works as-is, however, it has a couple of downside that:
-
-- Someone could define a key/value pair in EE that is **conflicted** with a value defined in FOSS.
- For example, define `activity_limit_exceeded: 1` in `EE::Enums::Pipeline`.
-- When it happens, the feature works totally different.
- For example, we cannot figure out `failure_reason` is either `config_error` or `activity_limit_exceeded`.
-- When it happens, we have to ship a database migration to fix the data integrity,
- which might be impossible if you cannot recover the original value.
-
-Also, you might observe a workaround for this concern by setting an offset in EE's values.
-For example, this example sets `1000` as the offset:
-
-```ruby
-module EE
- module Enums
- module Pipeline
- override :failure_reasons
- def failure_reasons
- super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
- end
- end
- end
-end
-```
-
-This looks working as a workaround, however, this approach has some downsides that:
-
-- Features could move from EE to FOSS or vice versa. Therefore, the offset might be mixed between FOSS and EE in the future.
- For example, when you move `activity_limit_exceeded` to FOSS, you see `{ unknown_failure: 0, config_error: 1, activity_limit_exceeded: 1_000 }`.
-- The integer column for the `enum` is likely created [as `SMALLINT`](#creating-enums).
- 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:
-
-```ruby
-class Pipeline < ApplicationRecord
- enum failure_reason: {
- unknown_failure: 0,
- config_error: 1,
- activity_limit_exceeded: 2
- }
-end
-```
-
-## Add new values in the gap
-
-After merging some EE and FOSS enums, there might be a gap between the two groups of values:
-
-```ruby
-module Enums
- module Ci
- module CommitStatus
- def self.failure_reasons
- {
- # ...
- data_integrity_failure: 12,
- forward_deployment_failure: 13,
- insufficient_bridge_permissions: 1_001,
- downstream_bridge_project_not_found: 1_002,
- # ...
- }
- end
- end
- end
-end
-```
-
-To add new values, you should fill the gap first.
-In the example above add `14` instead of `1_003`:
-
-```ruby
-{
- # ...
- data_integrity_failure: 12,
- forward_deployment_failure: 13,
- a_new_value: 14,
- insufficient_bridge_permissions: 1_001,
- downstream_bridge_project_not_found: 1_002,
- # ...
-}
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/database/add_foreign_key_to_existing_column.md b/doc/development/database/add_foreign_key_to_existing_column.md
index 7a18da2223f..8a8fe3c0a1e 100644
--- a/doc/development/database/add_foreign_key_to_existing_column.md
+++ b/doc/development/database/add_foreign_key_to_existing_column.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Add a foreign key constraint to an existing column
-Foreign keys ensure consistency between related database tables. The current database review process **always** encourages you to add [foreign keys](../foreign_keys.md) when creating tables that reference records from other tables.
+Foreign keys ensure consistency between related database tables. The current database review process **always** encourages you to add [foreign keys](foreign_keys.md) when creating tables that reference records from other tables.
Starting with Rails version 4, Rails includes migration helpers to add foreign key constraints
to database tables. Before Rails 4, the only way for ensuring some level of consistency was the
@@ -95,7 +95,7 @@ The approach here depends on the data volume and the cleanup strategy. If we can
records by doing a database query and the record count is not high, then the data migration can
be executed in a Rails migration.
-In case the data volume is higher (>1000 records), it's better to create a background migration. If unsure, please contact the database team for advice.
+In case the data volume is higher (>1000 records), it's better to create a background migration. If unsure, contact the database team for advice.
Example for cleaning up records in the `emails` table in a database migration:
diff --git a/doc/development/database/adding_database_indexes.md b/doc/development/database/adding_database_indexes.md
new file mode 100644
index 00000000000..8abd7c8298e
--- /dev/null
+++ b/doc/development/database/adding_database_indexes.md
@@ -0,0 +1,410 @@
+---
+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
+---
+
+# Adding Database Indexes
+
+Indexes can be used to speed up database queries, but when should you add a new
+index? Traditionally the answer to this question has been to add an index for
+every column used for filtering or joining data. For example, consider the
+following query:
+
+```sql
+SELECT *
+FROM projects
+WHERE user_id = 2;
+```
+
+Here we are filtering by the `user_id` column and as such a developer may decide
+to index this column.
+
+While in certain cases indexing columns using the above approach may make sense,
+it can actually have a negative impact. Whenever you write data to a table, any
+existing indexes must also be updated. The more indexes there are, the slower this
+can potentially become. Indexes can also take up significant disk space, depending
+on the amount of data indexed and the index type. For example, PostgreSQL offers
+`GIN` indexes which can be used to index certain data types that cannot be
+indexed by regular B-tree indexes. These indexes, however, generally take up more
+data and are slower to update compared to B-tree indexes.
+
+Because of all this, it's important make the following considerations
+when adding a new index:
+
+1. Do the new queries re-use as many existing indexes as possible?
+1. Is there enough data that using an index is faster than iterating over
+ rows in the table?
+1. Is the overhead of maintaining the index worth the reduction in query
+ timings?
+
+## Re-using Queries
+
+The first step is to make sure your query re-uses as many existing indexes as
+possible. For example, consider the following query:
+
+```sql
+SELECT *
+FROM todos
+WHERE user_id = 123
+AND state = 'open';
+```
+
+Now imagine we already have an index on the `user_id` column but not on the
+`state` column. One may think this query performs badly due to `state` being
+unindexed. In reality the query may perform just fine given the index on
+`user_id` can filter out enough rows.
+
+The best way to determine if indexes are re-used is to run your query using
+`EXPLAIN ANALYZE`. Depending on the joined tables and the columns being used for filtering,
+you may find an extra index doesn't make much, if any, difference.
+
+In short:
+
+1. Try to write your query in such a way that it re-uses as many existing
+ indexes as possible.
+1. Run the query using `EXPLAIN ANALYZE` and study the output to find the most
+ ideal query.
+
+## Data Size
+
+A database may not use an index even when a regular sequence scan
+(iterating over all rows) is faster, especially for small tables.
+
+Consider adding an index if a table is expected to grow, and your query has to filter a lot of rows.
+You may _not_ want to add an index if the table size is small (<`1,000` records),
+or if existing indexes already filter out enough rows.
+
+## Maintenance Overhead
+
+Indexes have to be updated on every table write. In the case of PostgreSQL, _all_
+existing indexes are updated whenever data is written to a table. As a
+result, having many indexes on the same table slows down writes. It's therefore important
+to balance query performance with the overhead of maintaining an extra index.
+
+Let's say that adding an index reduces SELECT timings by 5 milliseconds but increases
+INSERT/UPDATE/DELETE timings by 10 milliseconds. In this case, the new index may not be worth
+it. A new index is more valuable when SELECT timings are reduced and INSERT/UPDATE/DELETE
+timings are unaffected.
+
+## Finding Unused Indexes
+
+To see which indexes are unused you can run the following query:
+
+```sql
+SELECT relname as table_name, indexrelname as index_name, idx_scan, idx_tup_read, idx_tup_fetch, pg_size_pretty(pg_relation_size(indexrelname::regclass))
+FROM pg_stat_all_indexes
+WHERE schemaname = 'public'
+AND idx_scan = 0
+AND idx_tup_read = 0
+AND idx_tup_fetch = 0
+ORDER BY pg_relation_size(indexrelname::regclass) desc;
+```
+
+This query outputs a list containing all indexes that are never used and sorts
+them by indexes sizes in descending order. This query helps in
+determining whether existing indexes are still required. More information on
+the meaning of the various columns can be found at
+<https://www.postgresql.org/docs/current/monitoring-stats.html>.
+
+To determine if an index is still being used on production, use the following
+Thanos query with your index name:
+
+```sql
+sum(rate(pg_stat_user_indexes_idx_tup_read{env="gprd", indexrelname="index_ci_name", type="patroni-ci"}[5m]))
+```
+
+Because the query output relies on the actual usage of your database, it
+may be affected by factors such as:
+
+- Certain queries never being executed, thus not being able to use certain
+ indexes.
+- Certain tables having little data, resulting in PostgreSQL using sequence
+ scans instead of index scans.
+
+This data is only reliable for a frequently used database with
+plenty of data, and using as many GitLab features as possible.
+
+## Requirements for naming indexes
+
+Indexes with complex definitions must be explicitly named rather than
+relying on the implicit naming behavior of migration methods. In short,
+that means you **must** provide an explicit name argument for an index
+created with one or more of the following options:
+
+- `where`
+- `using`
+- `order`
+- `length`
+- `type`
+- `opclass`
+
+### Considerations for index names
+
+Check our [Constraints naming conventions](constraint_naming_convention.md) page.
+
+### Why explicit names are required
+
+As Rails is database agnostic, it generates an index name only
+from the required options of all indexes: table name and column names.
+For example, imagine the following two indexes are created in a migration:
+
+```ruby
+def up
+ add_index :my_table, :my_column
+
+ add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
+end
+```
+
+Creation of the second index would fail, because Rails would generate
+the same name for both indexes.
+
+This naming issue is further complicated by the behavior of the `index_exists?` method.
+It considers only the table name, column names, and uniqueness specification
+of the index when making a comparison. Consider:
+
+```ruby
+def up
+ unless index_exists?(:my_table, :my_column, where: 'my_column IS NOT NULL')
+ add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
+ end
+end
+```
+
+The call to `index_exists?` returns true if **any** index exists on
+`:my_table` and `:my_column`, and index creation is bypassed.
+
+The `add_concurrent_index` helper is a requirement for creating indexes
+on populated tables. Because it cannot be used inside a transactional
+migration, it has a built-in check that detects if the index already
+exists. In the event a match is found, index creation is skipped.
+Without an explicit name argument, Rails can return a false positive
+for `index_exists?`, causing a required index to not be created
+properly. By always requiring a name for certain types of indexes, the
+chance of error is greatly reduced.
+
+## Temporary indexes
+
+There may be times when an index is only needed temporarily.
+
+For example, in a migration, a column of a table might be conditionally
+updated. To query which columns must be updated in the
+[query performance guidelines](query_performance.md), an index is needed
+that would otherwise not be used.
+
+In these cases, consider a temporary index. To specify a
+temporary index:
+
+1. Prefix the index name with `tmp_` and follow the [naming conventions](constraint_naming_convention.md).
+1. Create a follow-up issue to remove the index in the next (or future) milestone.
+1. Add a comment in the migration mentioning the removal issue.
+
+A temporary migration would look like:
+
+```ruby
+INDEX_NAME = 'tmp_index_projects_on_owner_where_emails_disabled'
+
+def up
+ # Temporary index to be removed in 13.9 https://gitlab.com/gitlab-org/gitlab/-/issues/1234
+ add_concurrent_index :projects, :creator_id, where: 'emails_disabled = false', name: INDEX_NAME
+end
+
+def down
+ remove_concurrent_index_by_name :projects, INDEX_NAME
+end
+```
+
+## Create indexes asynchronously
+
+For very large tables, index creation can be a challenge to manage.
+While `add_concurrent_index` creates indexes in a way that does not block
+normal traffic, it can still be problematic when index creation runs for
+many hours. Necessary database operations like `autovacuum` cannot run, and
+on GitLab.com, the deployment process is blocked waiting for index
+creation to finish.
+
+To limit impact on GitLab.com, a process exists to create indexes
+asynchronously during weekend hours. Due to generally lower traffic and fewer deployments,
+index creation can proceed at a lower level of risk.
+
+### Schedule index creation for a low-impact time
+
+1. [Schedule the index to be created](#schedule-the-index-to-be-created).
+1. [Verify the MR was deployed and the index exists in production](#verify-the-mr-was-deployed-and-the-index-exists-in-production).
+1. [Add a migration to create the index synchronously](#add-a-migration-to-create-the-index-synchronously).
+
+### Schedule the index to be created
+
+Create an MR with a post-deployment migration which prepares the index
+for asynchronous creation. An example of creating an index using
+the asynchronous index helpers can be seen in the block below. This migration
+enters the index name and definition into the `postgres_async_indexes`
+table. The process that runs on weekends pulls indexes from this
+table and attempt to create them.
+
+```ruby
+# in db/post_migrate/
+
+INDEX_NAME = 'index_ci_builds_on_some_column'
+
+def up
+ prepare_async_index :ci_builds, :some_column, name: INDEX_NAME
+end
+
+def down
+ unprepare_async_index :ci_builds, :some_column, name: INDEX_NAME
+end
+```
+
+### Verify the MR was deployed and the index exists in production
+
+You can verify if the post-deploy migration was executed on GitLab.com by:
+
+- Executing `/chatops run auto_deploy status <merge_sha>`. If the output returns `db/gprd`,
+ the post-deploy migration has been executed in the production database. More details in this
+ [guide](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md#how-to-determine-if-a-post-deploy-migration-has-been-executed-on-gitlabcom).
+- Use a meta-command in #database-lab, such as: `\d <index_name>`.
+ - Ensure that the index is not [`invalid`](https://www.postgresql.org/docs/12/sql-createindex.html#:~:text=The%20psql%20%5Cd%20command%20will%20report%20such%20an%20index%20as%20INVALID).
+- Ask someone in #database to check if the index exists.
+- With proper access, you can also verify directly on production or in a
+ production clone.
+
+### Add a migration to create the index synchronously
+
+After the index is verified to exist on the production database, create a second
+merge request that adds the index synchronously. The schema changes must be
+updated and committed to `structure.sql` in this second merge request.
+The synchronous migration results in a no-op on GitLab.com, but you should still add the
+migration as expected for other installations. The below block
+demonstrates how to create the second migration for the previous
+asynchronous example.
+
+**WARNING:**
+Verify that the index exists in production before merging a second migration with `add_concurrent_index`.
+If the second migration is deployed before the index has been created,
+the index is created synchronously when the second migration executes.
+
+```ruby
+# in db/post_migrate/
+
+INDEX_NAME = 'index_ci_builds_on_some_column'
+
+disable_ddl_transaction!
+
+def up
+ add_concurrent_index :ci_builds, :some_column, name: INDEX_NAME
+end
+
+def down
+ remove_concurrent_index_by_name :ci_builds, INDEX_NAME
+end
+```
+
+## Test database index changes locally
+
+You must test the database index changes locally before creating a merge request.
+
+### Verify indexes created asynchronously
+
+Use the asynchronous index helpers on your local environment to test changes for creating an index:
+
+1. Enable the feature flags by running `Feature.enable(:database_async_index_creation)` and `Feature.enable(:database_reindexing)` in the Rails console.
+1. Run `bundle exec rails db:migrate` so that it creates an entry in the `postgres_async_indexes` table.
+1. Run `bundle exec rails gitlab:db:reindex` so that the index is created asynchronously.
+1. To verify the index, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) command `gdk psql` and run the command `\d <index_name>` to check that your newly created index exists.
+
+## Drop indexes asynchronously
+
+For very large tables, index destruction can be a challenge to manage.
+While `remove_concurrent_index` removes indexes in a way that does not block
+normal traffic, it can still be problematic if index destruction runs for
+during autovacuum. Necessary database operations like `autovacuum` cannot run, and
+the deployment process on GitLab.com is blocked while waiting for index
+destruction to finish.
+
+To limit the impact on GitLab.com, use the following process to remove indexes
+asynchronously during weekend hours. Due to generally lower traffic and fewer deployments,
+index destruction can proceed at a lower level of risk.
+
+1. [Schedule the index to be removed](#schedule-the-index-to-be-removed).
+1. [Verify the MR was deployed and the index exists in production](#verify-the-mr-was-deployed-and-the-index-exists-in-production).
+1. [Add a migration to create the index synchronously](#add-a-migration-to-create-the-index-synchronously).
+
+### Schedule the index to be removed
+
+Create an MR with a post-deployment migration which prepares the index
+for asynchronous destruction. For example. to destroy an index using
+the asynchronous index helpers:
+
+```ruby
+# in db/post_migrate/
+
+INDEX_NAME = 'index_ci_builds_on_some_column'
+
+def up
+ prepare_async_index_removal :ci_builds, :some_column, name: INDEX_NAME
+end
+
+def down
+ unprepare_async_index :ci_builds, :some_column, name: INDEX_NAME
+end
+```
+
+This migration enters the index name and definition into the `postgres_async_indexes`
+table. The process that runs on weekends pulls indexes from this table and attempt
+to remove them.
+
+You must test the database index changes locally before creating a merge request.
+
+### Verify the MR was deployed and the index exists in production
+
+You can verify if the MR was deployed to GitLab.com with
+`/chatops run auto_deploy status <merge_sha>`. To verify the existence of
+the index, you can:
+
+- Use a meta-command in `#database-lab`, for example: `\d <index_name>`.
+ - Make sure the index is not [`invalid`](https://www.postgresql.org/docs/12/sql-createindex.html#:~:text=The%20psql%20%5Cd%20command%20will%20report%20such%20an%20index%20as%20INVALID).
+- Ask someone in `#database` to check if the index exists.
+- If you have access, you can verify directly on production or in a
+ production clone.
+
+### Add a migration to destroy the index synchronously
+
+After you verify the index exists in the production database, create a second
+merge request that removes the index synchronously. The schema changes must be
+updated and committed to `structure.sql` in this second merge request.
+The synchronous migration results in a no-op on GitLab.com, but you should still add the
+migration as expected for other installations. For example, to
+create the second migration for the previous asynchronous example:
+
+**WARNING:**
+Verify that the index no longer exist in production before merging a second migration with `remove_concurrent_index_by_name`.
+If the second migration is deployed before the index has been destroyed,
+the index is destroyed synchronously when the second migration executes.
+
+```ruby
+# in db/post_migrate/
+
+INDEX_NAME = 'index_ci_builds_on_some_column'
+
+disable_ddl_transaction!
+
+def up
+ remove_concurrent_index_by_name :ci_builds, name: INDEX_NAME
+end
+
+def down
+ add_concurrent_index :ci_builds, :some_column, INDEX_NAME
+end
+```
+
+### Verify indexes removed asynchronously
+
+To test changes for removing an index, use the asynchronous index helpers on your local environment:
+
+1. Enable the feature flags by running `Feature.enable(:database_async_index_destruction)` and `Feature.enable(:database_reindexing)` in the Rails console.
+1. Run `bundle exec rails db:migrate` which should create an entry in the `postgres_async_indexes` table.
+1. Run `bundle exec rails gitlab:db:reindex` destroy the index asynchronously.
+1. To verify the index, open the PostgreSQL console by using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md)
+ command `gdk psql` and run `\d <index_name>` to check that the destroyed index no longer exists.
diff --git a/doc/development/database/avoiding_downtime_in_migrations.md b/doc/development/database/avoiding_downtime_in_migrations.md
index 2d079656e23..79c76b351c8 100644
--- a/doc/development/database/avoiding_downtime_in_migrations.md
+++ b/doc/development/database/avoiding_downtime_in_migrations.md
@@ -93,9 +93,8 @@ class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[2.0]
end
```
-You can consider [enabling lock retries](
-https://docs.gitlab.com/ee/development/migration_style_guide.html#usage-with-transactional-migrations
-) when you run a migration on big tables, because it might take some time to
+You can consider [enabling lock retries](../migration_style_guide.md#usage-with-transactional-migrations)
+when you run a migration on big tables, because it might take some time to
acquire a lock on this table.
#### B. The removed column has an index or constraint that belongs to it
@@ -104,7 +103,7 @@ If the `down` method requires adding back any dropped indexes or constraints, th
be done within a transactional migration, then the migration would look like this:
```ruby
-class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[1.0]
+class RemoveUsersUpdatedAtColumn < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -126,13 +125,11 @@ end
In the `down` method, we check to see if the column already exists before adding it again.
We do this because the migration is non-transactional and might have failed while it was running.
-The [`disable_ddl_transaction!`](
-https://docs.gitlab.com/ee/development/migration_style_guide.html#usage-with-non-transactional-migrations-disable_ddl_transaction
-) is used to disable the transaction that wraps the whole migration.
+The [`disable_ddl_transaction!`](../migration_style_guide.md#usage-with-non-transactional-migrations-disable_ddl_transaction)
+is used to disable the transaction that wraps the whole migration.
-You can refer to the page [Migration Style Guide](
-https://docs.gitlab.com/ee/development/migration_style_guide.html
-) for more information about database migrations.
+You can refer to the page [Migration Style Guide](../migration_style_guide.md)
+for more information about database migrations.
### Step 3: Removing the ignore rule (release M+2)
@@ -145,9 +142,13 @@ the `remove_after` date has passed.
## Renaming Columns
Renaming columns the normal way requires downtime as an application may continue
-using the old column name during/after a database migration. To rename a column
-without requiring downtime we need two migrations: a regular migration, and a
-post-deployment migration. Both these migration can go in the same release.
+to use the old column names during or after a database migration. To rename a column
+without requiring downtime, we need two migrations: a regular migration and a
+post-deployment migration. Both these migrations can go in the same release.
+
+NOTE:
+It's not possible to rename columns with default values. For more details, see
+[this merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52032#default-values).
### Step 1: Add The Regular Migration
@@ -157,7 +158,7 @@ renaming. For example
```ruby
# A regular migration in db/migrate
-class RenameUsersUpdatedAtToUpdatedAtTimestamp < Gitlab::Database::Migration[1.0]
+class RenameUsersUpdatedAtToUpdatedAtTimestamp < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -185,7 +186,7 @@ We can perform this cleanup using
```ruby
# A post-deployment migration in db/post_migrate
-class CleanupUsersUpdatedAtRename < Gitlab::Database::Migration[1.0]
+class CleanupUsersUpdatedAtRename < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -198,7 +199,7 @@ class CleanupUsersUpdatedAtRename < Gitlab::Database::Migration[1.0]
end
```
-If you're renaming a [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3), please carefully consider the state when the first migration has run but the second cleanup migration hasn't been run yet.
+If you're renaming a [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3), carefully consider the state when the first migration has run but the second cleanup migration hasn't been run yet.
With [Canary](https://gitlab.com/gitlab-com/gl-infra/readiness/-/tree/master/library/canary/) it is possible that the system runs in this state for a significant amount of time.
## Changing Column Constraints
@@ -232,7 +233,7 @@ as follows:
```ruby
# A regular migration in db/migrate
-class ChangeUsersUsernameStringToText < Gitlab::Database::Migration[1.0]
+class ChangeUsersUsernameStringToText < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -251,7 +252,7 @@ Next we need to clean up our changes using a post-deployment migration:
```ruby
# A post-deployment migration in db/post_migrate
-class ChangeUsersUsernameStringToTextCleanup < Gitlab::Database::Migration[1.0]
+class ChangeUsersUsernameStringToTextCleanup < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def up
@@ -295,8 +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 background migrations](background_migrations.md#cleaning-up).
## Adding Indexes
diff --git a/doc/development/database/background_migrations.md b/doc/development/database/background_migrations.md
index 0124dbae51f..9b596eb7379 100644
--- a/doc/development/database/background_migrations.md
+++ b/doc/development/database/background_migrations.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
Background migrations are strongly discouraged in favor of the new [batched background migrations framework](batched_background_migrations.md).
-Please check that documentation and determine if that framework suits your needs and fall back
+Check that documentation and determine if that framework suits your needs and fall back
to these only if required.
Background migrations should be used to perform data migrations whenever a
@@ -368,9 +368,9 @@ A strategy to make the migration run faster is to schedule larger batches, and t
within the background migration to perform multiple statements.
The background migration helpers that queue multiple jobs such as
-`queue_background_migration_jobs_by_range_at_intervals` use [`EachBatch`](../iterating_tables_in_batches.md).
+`queue_background_migration_jobs_by_range_at_intervals` use [`EachBatch`](iterating_tables_in_batches.md).
The example above has batches of 1000, where each queued job takes two seconds. If the query has been optimized
-to make the time for the delete statement within the [query performance guidelines](../query_performance.md),
+to make the time for the delete statement within the [query performance guidelines](query_performance.md),
1000 may be the largest number of records that can be deleted in a reasonable amount of time.
The minimum and most common interval for delaying jobs is two minutes. This results in two seconds
diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md
index f3ea82b5c61..edb22fcf436 100644
--- a/doc/development/database/batched_background_migrations.md
+++ b/doc/development/database/batched_background_migrations.md
@@ -105,11 +105,16 @@ for more details.
## Batched background migrations for EE-only features
-All the background migration classes for EE-only features should be present in GitLab CE.
-For this purpose, create an empty class for GitLab CE, and extend it for GitLab EE
+All the background migration classes for EE-only features should be present in GitLab FOSS.
+For this purpose, create an empty class for GitLab FOSS, and extend it for GitLab EE
as explained in the guidelines for
[implementing Enterprise Edition features](../ee_features.md#code-in-libgitlabbackground_migration).
+NOTE:
+Background migration classes for EE-only features that use job arguments should define them
+in the GitLab FOSS class. This is required to prevent job arguments validation from failing when
+migration is scheduled in GitLab FOSS context.
+
Batched Background migrations are simple classes that define a `perform` method. A
Sidekiq worker then executes such a class, passing any arguments to it. All
migration classes must be defined in the namespace
@@ -132,6 +137,10 @@ queue_batched_background_migration(
)
```
+NOTE:
+This helper raises an error if the number of provided job arguments does not match
+the number of [job arguments](#job-arguments) defined in `JOB_CLASS_NAME`.
+
Make sure the newly-created data is either migrated, or
saved in both the old and new version upon creation. Removals in
turn can be handled by defining foreign keys with cascading deletes.
@@ -186,6 +195,115 @@ Bump to the [import/export version](../../user/project/settings/import_export.md
be required, if importing a project from a prior version of GitLab requires the
data to be in the new format.
+## Job arguments
+
+`BatchedMigrationJob` provides the `job_arguments` helper method for job classes to define the job arguments they need.
+
+Batched migrations scheduled with `queue_batched_background_migration` **must** use the helper to define the job arguments:
+
+```ruby
+queue_batched_background_migration(
+ 'CopyColumnUsingBackgroundMigrationJob',
+ TABLE_NAME,
+ 'name', 'name_convert_to_text',
+ job_interval: DELAY_INTERVAL
+)
+```
+
+NOTE:
+If the number of defined job arguments does not match the number of job arguments provided when
+scheduling the migration, `queue_batched_background_migration` raises an error.
+
+In this example, `copy_from` returns `name`, and `copy_to` returns `name_convert_to_text`:
+
+```ruby
+class CopyColumnUsingBackgroundMigrationJob < BatchedMigrationJob
+ job_arguments :copy_from, :copy_to
+
+ def perform
+ from_column = connection.quote_column_name(copy_from)
+ to_column = connection.quote_column_name(copy_to)
+
+ assignment_clause = "#{to_column} = #{from_column}"
+
+ each_sub_batch(operation_name: :update_all) do |relation|
+ relation.update_all(assignment_clause)
+ end
+ end
+end
+```
+
+### Additional filters
+
+By default, when creating background jobs to perform the migration, batched background migrations
+iterate over the full specified table. This iteration is done using the
+[`PrimaryKeyBatchingStrategy`](https://gitlab.com/gitlab-org/gitlab/-/blob/c9dabd1f4b8058eece6d8cb4af95e9560da9a2ee/lib/gitlab/database/migrations/batched_background_migration_helpers.rb#L17). If the table has 1000 records
+and the batch size is 100, the work is batched into 10 jobs. For illustrative purposes,
+`EachBatch` is used like this:
+
+```ruby
+# PrimaryKeyBatchingStrategy
+Namespace.each_batch(of: 100) do |relation|
+ relation.where(type: nil).update_all(type: 'User') # this happens in each background job
+end
+```
+
+In some cases, only a subset of records must be examined. If only 10% of the 1000 records
+need examination, apply a filter to the initial relation when the jobs are created:
+
+```ruby
+Namespace.where(type: nil).each_batch(of: 100) do |relation|
+ relation.update_all(type: 'User')
+end
+```
+
+In the first example, we don't know how many records will be updated in each batch.
+In the second (filtered) example, we know exactly 100 will be updated with each batch.
+
+`BatchedMigrationJob` provides a `scope_to` helper method to apply additional filters and achieve this:
+
+1. Create a new migration job class that inherits from `BatchedMigrationJob` and defines the additional filter:
+
+ ```ruby
+ class BackfillNamespaceType < BatchedMigrationJob
+ scope_to ->(relation) { relation.where(type: nil) }
+
+ def perform
+ each_sub_batch(operation_name: :update_all) do |sub_batch|
+ sub_batch.update_all(type: 'User')
+ end
+ end
+ end
+ ```
+
+1. In the post-deployment migration, enqueue the batched background migration:
+
+ ```ruby
+ class BackfillNamespaceType < Gitlab::Database::Migration[2.0]
+ MIGRATION = 'BackfillNamespaceType'
+ DELAY_INTERVAL = 2.minutes
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ queue_batched_background_migration(
+ MIGRATION,
+ :namespaces,
+ :id,
+ job_interval: DELAY_INTERVAL
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :namespaces, :id, [])
+ end
+ end
+ ```
+
+NOTE:
+When applying additional filters, it is important to ensure they are properly covered by an index to optimize `EachBatch` performance.
+In the example above we need an index on `(type, id)` to support the filters. See [the `EachBatch` docs for more information](../iterating_tables_in_batches.md).
+
## Example
The `routes` table has a `source_type` field that's used for a polymorphic relationship.
@@ -221,8 +339,6 @@ background migration.
correctly handled by the batched migration framework. Any subclass of
`BatchedMigrationJob` is initialized with necessary arguments to
execute the batch, as well as a connection to the tracking database.
- Additional `job_arguments` set on the migration are passed to the
- job's `perform` method.
1. Add a new trigger to the database to update newly created and updated routes,
similar to this example:
@@ -320,7 +436,7 @@ The default batching strategy provides an efficient way to iterate over primary
However, if you need to iterate over columns where values are not unique, you must use a
different batching strategy.
-The `LooseIndexScanBatchingStrategy` batching strategy uses a special version of [`EachBatch`](../iterating_tables_in_batches.md#loose-index-scan-with-distinct_each_batch)
+The `LooseIndexScanBatchingStrategy` batching strategy uses a special version of [`EachBatch`](iterating_tables_in_batches.md#loose-index-scan-with-distinct_each_batch)
to provide efficient and stable iteration over the distinct column values.
This example shows a batched background migration where the `issues.project_id` column is used as
@@ -374,76 +490,8 @@ module Gitlab
end
```
-### Adding filters to the initial batching
-
-By default, when creating background jobs to perform the migration, batched background migrations will iterate over the full specified table. This is done using the [`PrimaryKeyBatchingStrategy`](https://gitlab.com/gitlab-org/gitlab/-/blob/c9dabd1f4b8058eece6d8cb4af95e9560da9a2ee/lib/gitlab/database/migrations/batched_background_migration_helpers.rb#L17). This means if there are 1000 records in the table and the batch size is 100, there will be 10 jobs. For illustrative purposes, `EachBatch` is used like this:
-
-```ruby
-# PrimaryKeyBatchingStrategy
-Projects.all.each_batch(of: 100) do |relation|
- relation.where(foo: nil).update_all(foo: 'bar') # this happens in each background job
-end
-```
-
-There are cases where we only need to look at a subset of records. Perhaps we only need to update 1 out of every 10 of those 1000 records. It would be best if we could apply a filter to the initial relation when the jobs are created:
-
-```ruby
-Projects.where(foo: nil).each_batch(of: 100) do |relation|
- relation.update_all(foo: 'bar')
-end
-```
-
-In the `PrimaryKeyBatchingStrategy` example, we do not know how many records will be updated in each batch. In the filtered example, we know exactly 100 will be updated with each batch.
-
-The `PrimaryKeyBatchingStrategy` contains [a method that can be overwritten](https://gitlab.com/gitlab-org/gitlab/-/blob/dd1e70d3676891025534dc4a1e89ca9383178fe7/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb#L38-52) to apply additional filtering on the initial `EachBatch`.
-
-We can accomplish this by:
-
-1. Create a new class that inherits from `PrimaryKeyBatchingStrategy` and overrides the method using the desired filter (this may be the same filter used in the sub-batch):
-
- ```ruby
- # frozen_string_literal: true
-
- module GitLab
- module BackgroundMigration
- module BatchingStrategies
- class FooStrategy < PrimaryKeyBatchingStrategy
- def apply_additional_filters(relation, job_arguments: [], job_class: nil)
- relation.where(foo: nil)
- end
- end
- end
- end
- end
- ```
-
-1. In the post-deployment migration that queues the batched background migration, specify the new batching strategy using the `batch_class_name` parameter:
-
- ```ruby
- class BackfillProjectsFoo < Gitlab::Database::Migration[2.0]
- MIGRATION = 'BackfillProjectsFoo'
- DELAY_INTERVAL = 2.minutes
- BATCH_CLASS_NAME = 'FooStrategy'
-
- restrict_gitlab_migration gitlab_schema: :gitlab_main
-
- def up
- queue_batched_background_migration(
- MIGRATION,
- :routes,
- :id,
- job_interval: DELAY_INTERVAL,
- batch_class_name: BATCH_CLASS_NAME
- )
- end
-
- def down
- delete_batched_background_migration(MIGRATION, :routes, :id, [])
- end
- end
- ```
-
-When applying a batching strategy, it is important to ensure the filter properly covered by an index to optimize `EachBatch` performance. See [the `EachBatch` docs for more information](../iterating_tables_in_batches.md).
+NOTE:
+[Additional filters](#additional-filters) defined with `scope_to` will be ignored by `LooseIndexScanBatchingStrategy` and `distinct_each_batch`.
## Testing
diff --git a/doc/development/database/ci_mirrored_tables.md b/doc/development/database/ci_mirrored_tables.md
new file mode 100644
index 00000000000..06f0087fafe
--- /dev/null
+++ b/doc/development/database/ci_mirrored_tables.md
@@ -0,0 +1,156 @@
+---
+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
+---
+
+# CI mirrored tables
+
+## Problem statement
+
+As part of the database [decomposition work](https://gitlab.com/groups/gitlab-org/-/epics/6168),
+which had the goal of splitting the single database GitLab is using, into two databases: `main` and
+`ci`, came the big challenge of
+[removing all joins between the `main` and the `ci` tables](multiple_databases.md#removing-joins-between-ci-and-non-ci-tables).
+That is because PostgreSQL doesn't support joins between tables that belong to different databases.
+However, some core application models in the main database are queried very often by the CI side.
+For example:
+
+- `Namespace`, in the `namespaces` table.
+- `Project`, in the `projects` table.
+
+Not being able to do `joins` on these tables brings a great challenge. The team chose to perform logical
+replication of those tables from the main database to the CI database, in the new tables:
+
+- `ci_namespace_mirrors`, as a mirror of the `namespaces` table
+- `ci_project_mirrors`, as a mirror of the `projects` table
+
+This logical replication means two things:
+
+1. The `main` database tables can be queried and joined to the `namespaces` and `projects` tables.
+1. The `ci` database tables can be joined with the `ci_namespace_mirrors` and `ci_project_mirrors` tables.
+
+```mermaid
+graph LR
+
+ subgraph "Main database (tables)"
+ A[namespaces] -->|updates| B[namespaces_sync_events]
+ A -->|deletes| C[loose_foreign_keys_deleted_records]
+ D[projects] -->|deletes| C
+ D -->|updates| E[projects_sync_events]
+ end
+
+ B --> F
+ C --> G
+ E --> H
+
+ subgraph "Sidekiq worker jobs"
+ F[Namespaces::ProcessSyncEventsWorker]
+ G[LooseForeignKeys::CleanupWorker]
+ H[Projects::ProcessSyncEventsWorker]
+ end
+
+ F -->|do update| I
+ G -->|delete records| I
+ G -->|delete records| J
+ H -->|do update| J
+
+ subgraph "CI database (tables)"
+ I[ci_namespace_mirrors]
+ J[ci_project_mirrors]
+ end
+```
+
+This replication was restricted only to a few attributes that are needed from each model:
+
+- From `Namespace` we replicate `traversal_ids`.
+- From `Project` we replicate only the `namespace_id`, which represents the group which the project belongs to.
+
+## Keeping the CI mirrored tables in sync with the source tables
+
+We must care about two type 3 events to keep
+the source and the target tables in sync:
+
+1. Creation of new namespaces or projects.
+1. Updating the namespaces or projects.
+1. Deleting namespaces/projects.
+
+```mermaid
+graph TD
+
+ subgraph "CI database (tables)"
+ E[other CI tables]
+ F{queries with joins allowed}
+ G[ci_project_mirrors]
+ H[ci_namespace_mirrors]
+
+ E---F
+ F---G
+ F---H
+ end
+
+ A---B
+ B---C
+ B---D
+
+L["⛔ ↠Joins are not allowed → ⛔"]
+
+ subgraph "Main database (tables)"
+ A[other main tables]
+ B{queries with joins allowed}
+ C[projects]
+ D[namespaces]
+ end
+```
+
+### Create and update
+
+Syncing the data of newly created or updated namespaces or projects happens in this
+order:
+
+1. **On the `main` database**: Any `INSERT` or `UPDATE` on the `namespaces` or `projects` tables
+ adds an entry to the tables `namespaces_sync_events`, and `projects_sync_events`. These tables
+ also exist on the `main` database. These entries are added by triggers on both of the tables.
+1. **On the model level**: After a commit happens on either of the source models `Namespace` or
+ `Project`, it schedules the corresponding Sidekiq jobs `Namespaces::ProcessSyncEventsWorker`
+ or `Projects::ProcessSyncEventsWorker` to run.
+1. These workers then:
+ 1. Read the entries from the tables `(namespaces/project)_sync_events`
+ from the `main` database, to check which namespaces or projects to sync.
+ 1. Copy the data for any updated records into the target
+ tables `ci_namespace_mirrors`, `ci_project_mirrors`.
+
+### Delete
+
+When any of `namespaces` or `projects` are deleted, the target records on the mirrored
+CI tables are deleted using the [loose foreign keys](loose_foreign_keys.md) (LFK) mechanism.
+
+By having these items in the `config/gitlab_loose_foreign_keys.yml`, the LFK mechanism
+was already working as expected. It deleted any records on the CI mirrored
+tables that mapped to deleted `namespaces` or `projects` in the `main` database.
+
+```yaml
+ci_namespace_mirrors:
+ - table: namespaces
+ column: namespace_id
+ on_delete: async_delete
+ci_project_mirrors:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+```
+
+## Consistency Checking
+
+To make sure that both syncing mechanisms work as expected, we deploy
+two extra worker jobs, triggered by cron jobs every few minutes:
+
+1. `Database::CiNamespaceMirrorsConsistencyCheckWorker`
+1. `Database::CiProjectMirrorsConsistencyCheckWorker`
+
+These jobs:
+
+1. Scan both of the source tables on the `main` database, using a cursor.
+1. Compare the items in the `namespaces` and `projects` with the target tables on the `ci` database.
+1. Report the items that are not in sync to Kibana and Prometheus.
+1. Corrects any discrepancies.
diff --git a/doc/development/database/client_side_connection_pool.md b/doc/development/database/client_side_connection_pool.md
index dc52a551407..3cd0e836a8d 100644
--- a/doc/development/database/client_side_connection_pool.md
+++ b/doc/development/database/client_side_connection_pool.md
@@ -10,8 +10,8 @@ Ruby processes accessing the database through
ActiveRecord, automatically calculate the connection-pool size for the
process based on the concurrency.
-Because of the way [Ruby on Rails manages database
-connections](#connection-lifecycle), it is important that we have at
+Because of the way [Ruby on Rails manages database connections](#connection-lifecycle),
+it is important that we have at
least as many connections as we have threads. While there is a 'pool'
setting in [`database.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/database.yml.postgresql), it is not very practical because you need to
maintain it in tandem with the number of application threads. For this
@@ -28,9 +28,8 @@ because connections are instantiated lazily.
## Troubleshooting connection-pool issues
-The connection-pool usage can be seen per environment in the [connection-pool
-saturation
-dashboard](https://dashboards.gitlab.net/d/alerts-sat_rails_db_connection_pool/alerts-rails_db_connection_pool-saturation-detail?orgId=1).
+The connection-pool usage can be seen per environment in the
+[connection-pool saturation dashboard](https://dashboards.gitlab.net/d/alerts-sat_rails_db_connection_pool/alerts-rails_db_connection_pool-saturation-detail?orgId=1).
If the connection-pool is too small, this would manifest in
`ActiveRecord::ConnectionTimeoutError`s from the application. Because we alert
@@ -41,8 +40,8 @@ hardcoded value (10).
At this point, we need to investigate what is using more connections
than we anticipated. To do that, we can use the
-`gitlab_ruby_threads_running_threads` metric. For example, [this
-graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
+`gitlab_ruby_threads_running_threads` metric. For example,
+[this graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
shows all running threads that connect to the database by their
name. Threads labeled `puma worker` or `sidekiq_worker_thread` are
the threads that define `Gitlab::Runtime.max_threads` so those are
diff --git a/doc/development/database/creating_enums.md b/doc/development/database/creating_enums.md
new file mode 100644
index 00000000000..450cb97d978
--- /dev/null
+++ b/doc/development/database/creating_enums.md
@@ -0,0 +1,154 @@
+---
+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
+---
+
+# Creating enums
+
+When creating a new enum, it should use the database type `SMALLINT`.
+The `SMALLINT` type size is 2 bytes, which is sufficient for an enum.
+This would help to save space in the database.
+
+To use this type, add `limit: 2` to the migration that creates the column.
+
+Example:
+
+```ruby
+def change
+ add_column :ci_job_artifacts, :file_format, :integer, limit: 2
+end
+```
+
+## All of the key/value pairs should be defined in FOSS
+
+**Summary:** All enums needs to be defined in FOSS, if a model is also part of the FOSS.
+
+```ruby
+class Model < ApplicationRecord
+ enum platform: {
+ aws: 0,
+ gcp: 1 # EE-only
+ }
+end
+```
+
+When you add a new key/value pair to a `enum` and if it's EE-specific, you might be
+tempted to organize the `enum` as the following:
+
+```ruby
+# Define `failure_reason` enum in `Pipeline` model:
+class Pipeline < ApplicationRecord
+ enum failure_reason: Enums::Pipeline.failure_reasons
+end
+```
+
+```ruby
+# Define key/value pairs that used in FOSS and EE:
+module Enums
+ module Pipeline
+ def self.failure_reasons
+ { unknown_failure: 0, config_error: 1 }
+ end
+ end
+end
+
+Enums::Pipeline.prepend_mod_with('Enums::Pipeline')
+```
+
+```ruby
+# Define key/value pairs that used in EE only:
+module EE
+ module Enums
+ module Pipeline
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 2)
+ end
+ end
+ end
+end
+```
+
+This works as-is, however, it has a couple of downside that:
+
+- Someone could define a key/value pair in EE that is **conflicted** with a value defined in FOSS.
+ For example, define `activity_limit_exceeded: 1` in `EE::Enums::Pipeline`.
+- When it happens, the feature works totally different.
+ For example, we cannot figure out `failure_reason` is either `config_error` or `activity_limit_exceeded`.
+- When it happens, we have to ship a database migration to fix the data integrity,
+ which might be impossible if you cannot recover the original value.
+
+Also, you might observe a workaround for this concern by setting an offset in EE's values.
+For example, this example sets `1000` as the offset:
+
+```ruby
+module EE
+ module Enums
+ module Pipeline
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
+ end
+ end
+ end
+end
+```
+
+This looks working as a workaround, however, this approach has some downsides that:
+
+- Features could move from EE to FOSS or vice versa. Therefore, the offset might be mixed between FOSS and EE in the future.
+ For example, when you move `activity_limit_exceeded` to FOSS, you see `{ unknown_failure: 0, config_error: 1, activity_limit_exceeded: 1_000 }`.
+- The integer column for the `enum` is likely created [as `SMALLINT`](#creating-enums).
+ 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:
+
+```ruby
+class Pipeline < ApplicationRecord
+ enum failure_reason: {
+ unknown_failure: 0,
+ config_error: 1,
+ activity_limit_exceeded: 2
+ }
+end
+```
+
+## Add new values in the gap
+
+After merging some EE and FOSS enums, there might be a gap between the two groups of values:
+
+```ruby
+module Enums
+ module Ci
+ module CommitStatus
+ def self.failure_reasons
+ {
+ # ...
+ data_integrity_failure: 12,
+ forward_deployment_failure: 13,
+ insufficient_bridge_permissions: 1_001,
+ downstream_bridge_project_not_found: 1_002,
+ # ...
+ }
+ end
+ end
+ end
+end
+```
+
+To add new values, you should fill the gap first.
+In the example above add `14` instead of `1_003`:
+
+```ruby
+{
+ # ...
+ data_integrity_failure: 12,
+ forward_deployment_failure: 13,
+ a_new_value: 14,
+ insufficient_bridge_permissions: 1_001,
+ downstream_bridge_project_not_found: 1_002,
+ # ...
+}
+```
diff --git a/doc/development/database/database_debugging.md b/doc/development/database/database_debugging.md
new file mode 100644
index 00000000000..5921dc942f2
--- /dev/null
+++ b/doc/development/database/database_debugging.md
@@ -0,0 +1,177 @@
+---
+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
+---
+
+# Troubleshooting and Debugging Database
+
+This section is to help give some copy-pasta you can use as a reference when you
+run into some head-banging database problems.
+
+A first step is to search for your error in Slack, or search for `GitLab <my error>` with Google.
+
+Available `RAILS_ENV`:
+
+- `production` (generally not for your main GDK database, but you may need this for other installations such as Omnibus).
+- `development` (this is your main GDK db).
+- `test` (used for tests like RSpec).
+
+## Delete everything and start over
+
+If you just want to delete everything and start over with an empty DB (approximately 1 minute):
+
+```shell
+bundle exec rake db:reset RAILS_ENV=development
+```
+
+If you want to seed the empty DB with sample data (approximately 4 minutes):
+
+```shell
+bundle exec rake dev:setup
+```
+
+If you just want to delete everything and start over with sample data (approximately 4 minutes). This
+also does `db:reset` and runs DB-specific migrations:
+
+```shell
+bundle exec rake db:setup RAILS_ENV=development
+```
+
+If your test DB is giving you problems, it is safe to delete everything because it doesn't contain important
+data:
+
+```shell
+bundle exec rake db:reset RAILS_ENV=test
+```
+
+## Migration wrangling
+
+- `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR
+- `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down`
+- `bundle exec rake db:migrate:down VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration
+- `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Set up a migration
+- `bundle exec rake db:migrate:redo VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration
+
+## Manually access the database
+
+Access the database via one of these commands (they all get you to the same place)
+
+```shell
+gdk psql -d gitlabhq_development
+bundle exec rails dbconsole -e development
+bundle exec rails db -e development
+```
+
+- `\q`: Quit/exit
+- `\dt`: List all tables
+- `\d+ issues`: List columns for `issues` table
+- `CREATE TABLE board_labels();`: Create a table called `board_labels`
+- `SELECT * FROM schema_migrations WHERE version = '20170926203418';`: Check if a migration was run
+- `DELETE FROM schema_migrations WHERE version = '20170926203418';`: Manually remove a migration
+
+## Access the database with a GUI
+
+Most GUIs (DataGrip, RubyMine, DBeaver) require a TCP connection to the database, but by default
+the database runs on a UNIX socket. To be able to access the database from these tools, some steps
+are needed:
+
+1. On the GDK root directory, run:
+
+ ```shell
+ gdk config set postgresql.host localhost
+ ```
+
+1. Open your `gdk.yml`, and confirm that it has the following lines:
+
+ ```yaml
+ postgresql:
+ host: localhost
+ ```
+
+1. Reconfigure GDK:
+
+ ```shell
+ gdk reconfigure
+ ```
+
+1. On your database GUI, select `localhost` as host, `5432` as port and `gitlabhq_development` as database.
+ Alternatively, you can use the connection string `postgresql://localhost:5432/gitlabhq_development`.
+
+The new connection should be working now.
+
+## Access the GDK database with Visual Studio Code
+
+Use these instructions for exploring the GitLab database while developing with the GDK:
+
+1. Install or open [Visual Studio Code](https://code.visualstudio.com/download).
+1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres).
+1. In Visual Studio Code select **PostgreSQL Explorer** in the left toolbar.
+1. In the top bar of the new window, select `+` to **Add Database Connection**, and follow the prompts to fill in the details:
+ 1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`).
+ 1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation.
+ 1. **Password of the PostgreSQL user**: the password you set when installing PostgreSQL.
+ 1. **Port number to connect to**: `5432` (default).
+ 1. **Use an SSL connection?** This depends on your installation. Options are:
+ - **Use Secure Connection**
+ - **Standard Connection** (default)
+ 1. **Optional. The database to connect to**: `gitlabhq_development`.
+ 1. **The display name for the database connection**: `gitlabhq_development`.
+
+Your database connection should now be displayed in the PostgreSQL Explorer pane and
+you can explore the `gitlabhq_development` database. If you cannot connect, ensure
+that GDK is running. For further instructions on how to use the PostgreSQL Explorer
+Extension for Visual Studio Code, read the [usage section](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres#usage)
+of the extension documentation.
+
+## FAQ
+
+### `ActiveRecord::PendingMigrationError` with Spring
+
+When running specs with the [Spring pre-loader](../rake_tasks.md#speed-up-tests-rake-tasks-and-migrations),
+the test database can get into a corrupted state. Trying to run the migration or
+dropping/resetting the test database has no effect.
+
+```shell
+$ bundle exec spring rspec some_spec.rb
+...
+Failure/Error: ActiveRecord::Migration.maintain_test_schema!
+
+ActiveRecord::PendingMigrationError:
+
+
+ Migrations are pending. To resolve this issue, run:
+
+ bin/rake db:migrate RAILS_ENV=test
+# ~/.rvm/gems/ruby-2.3.3/gems/activerecord-4.2.10/lib/active_record/migration.rb:392:in `check_pending!'
+...
+0 examples, 0 failures, 1 error occurred outside of examples
+```
+
+To resolve, you can kill the spring server and app that lives between spec runs.
+
+```shell
+$ ps aux | grep spring
+eric 87304 1.3 2.9 3080836 482596 ?? Ss 10:12AM 4:08.36 spring app | gitlab | started 6 hours ago | test mode
+eric 37709 0.0 0.0 2518640 7524 s006 S Wed11AM 0:00.79 spring server | gitlab | started 29 hours ago
+$ kill 87304
+$ kill 37709
+```
+
+### db:migrate `database version is too old to be migrated` error
+
+Users receive this error when `db:migrate` detects that the current schema version
+is older than the `MIN_SCHEMA_VERSION` defined in the `Gitlab::Database` library
+module.
+
+Over time we cleanup/combine old migrations in the codebase, so it is not always
+possible to migrate GitLab from every previous version.
+
+In some cases you may want to bypass this check. For example, if you were on a version
+of GitLab schema later than the `MIN_SCHEMA_VERSION`, and then rolled back the
+to an older migration, from before. In this case, to migrate forward again,
+you should set the `SKIP_SCHEMA_VERSION_CHECK` environment variable.
+
+```shell
+bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
+```
diff --git a/doc/development/database/database_dictionary.md b/doc/development/database/database_dictionary.md
new file mode 100644
index 00000000000..c330c5e67bd
--- /dev/null
+++ b/doc/development/database/database_dictionary.md
@@ -0,0 +1,51 @@
+---
+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
+---
+
+# Database Dictionary
+
+This page documents the database schema for GitLab, so data analysts and other groups can
+locate the feature categories responsible for specific database tables.
+
+## Location
+
+Database dictionary metadata files are stored in the `gitlab` project under `db/docs/`.
+
+## Example dictionary file
+
+```yaml
+---
+table_name: terraform_states
+classes:
+- Terraform::State
+feature_categories:
+- infrastructure_as_code
+description: Represents a Terraform state backend
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26619
+milestone: '13.0'
+```
+
+## Schema
+
+| Attribute | Type | Required | Description |
+|----------------------|---------------|----------|--------------------------------------------------------------------------|
+| `table_name` | String | yes | Database table name |
+| `classes` | Array(String) | no | List of classes that respond to `.table_name` with the `table_name` |
+| `feature_categories` | Array(String) | yes | List of feature categories using this table |
+| `description` | String | no | Text description of the information stored in the table and it's purpose |
+| `introduced_by_url` | URL | no | URL to the merge request or commit which introduced this table |
+| `milestone` | String | no | The milestone that introduced this table |
+
+## Adding tables
+
+When adding a new table, create a new file under `db/docs/` named
+`<table_name>.yml` containing as much information as you know about the table.
+
+Include this file in the commit with the migration that creates the table.
+
+## Dropping tables
+
+When dropping a table, you must remove the metadata file from `db/docs/`
+in the same commit with the migration that drops the table.
diff --git a/doc/development/database/database_lab.md b/doc/development/database/database_lab.md
index 5346df2690d..1d584a4ec6f 100644
--- a/doc/development/database/database_lab.md
+++ b/doc/development/database/database_lab.md
@@ -95,7 +95,7 @@ To connect to a clone using `psql`:
1. In the **Clone details** page of the Postgres.ai web interface, copy and run
the command to start SSH port forwarding for the clone.
1. In the **Clone details** page of the Postgres.ai web interface, copy and run the `psql` connection string.
- Use the password provided at setup.
+ Use the password provided at setup and set the `dbname` to `gitlabhq_dblab` (or check what databases are available by using `psql -l` with the same query string but `dbname=postgres`).
After you connect, use clone like you would any `psql` console in production, but with
the added benefit and safety of an isolated writeable environment.
diff --git a/doc/development/database/database_query_comments.md b/doc/development/database/database_query_comments.md
new file mode 100644
index 00000000000..2798071bc06
--- /dev/null
+++ b/doc/development/database/database_query_comments.md
@@ -0,0 +1,62 @@
+---
+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
+---
+
+# Database query comments with Marginalia
+
+The [Marginalia gem](https://github.com/basecamp/marginalia) is used to add
+query comments containing application related context information to PostgreSQL
+queries generated by ActiveRecord.
+
+It is very useful for tracing problematic queries back to the application source.
+
+An engineer during an on-call incident has the full context of a query
+and its application source from the comments.
+
+## Metadata information in comments
+
+Queries generated from **Rails** include the following metadata in comments:
+
+- `application`
+- `correlation_id`
+- `endpoint_id`
+- `line`
+
+Queries generated from **Sidekiq** workers include the following metadata
+in comments:
+
+- `application`
+- `jid`
+- `correlation_id`
+- `endpoint_id`
+- `line`
+
+`endpoint_id` is a single field that can represent any endpoint in the application:
+
+- For Rails controllers, it's the controller and action. For example, `Projects::BlobController#show`.
+- For Grape API endpoints, it's the route. For example, `/api/:version/users/:id`.
+- For Sidekiq workers, it's the worker class name. For example, `UserStatusCleanup::BatchWorker`.
+
+`line` is not present in production logs due to the additional overhead required.
+
+Examples of queries with comments:
+
+- Rails:
+
+ ```sql
+ /*application:web,controller:blob,action:show,correlation_id:01EZVMR923313VV44ZJDJ7PMEZ,endpoint_id:Projects::BlobController#show*/ SELECT "routes".* FROM "routes" WHERE "routes"."source_id" = 75 AND "routes"."source_type" = 'Namespace' LIMIT 1
+ ```
+
+- Grape:
+
+ ```sql
+ /*application:web,correlation_id:01EZVN0DAYGJF5XHG9N4VX8FAH,endpoint_id:/api/:version/users/:id*/ SELECT COUNT(*) FROM "users" INNER JOIN "user_follow_users" ON "users"."id" = "user_follow_users"."followee_id" WHERE "user_follow_users"."follower_id" = 1
+ ```
+
+- Sidekiq:
+
+ ```sql
+ /*application:sidekiq,correlation_id:df643992563683313bc0a0288fb55e23,jid:15fbc506590c625d7664b074,endpoint_id:UserStatusCleanup::BatchWorker,line:/app/workers/user_status_cleanup/batch_worker.rb:19:in `perform'*/ SELECT $1 AS one FROM "user_statuses" WHERE "user_statuses"."clear_status_at" <= $2 LIMIT $3
+ ```
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index b6bbfe690c1..a85f399a447 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -36,7 +36,7 @@ projects:
Create the merge request [using the "Database reviewer" template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/merge_request_templates/Database%20reviewer.md),
adding your expertise your profile YAML file. Assign to a database maintainer or the
-[Database Team's Engineering Manager](https://about.gitlab.com/handbook/engineering/development/enablement/database/).
+[Database Team's Engineering Manager](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/database/).
After the `team.yml` update is merged, the [Reviewer roulette](../code_review.md#reviewer-roulette)
may recommend you as a database reviewer.
@@ -53,17 +53,17 @@ that require a more in-depth discussion between the database reviewers and maint
- [Database Office Hours Agenda](https://docs.google.com/document/d/1wgfmVL30F8SdMg-9yY6Y8djPSxWNvKmhR5XmsvYX1EI/edit).
- <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [YouTube playlist with past recordings](https://www.youtube.com/playlist?list=PL05JrBw4t0Kp-kqXeiF7fF7cFYaKtdqXM).
-You should also join the [#database-lab](../understanding_explain_plans.md#database-lab-engine)
+You should also join the [#database-lab](understanding_explain_plans.md#database-lab-engine)
Slack channel and get familiar with how to use Joe, the Slackbot that provides developers
with their own clone of the production database.
Understanding and efficiently using `EXPLAIN` plans is at the core of the database review process.
The following guides provide a quick introduction and links to follow on more advanced topics:
-- Guide on [understanding EXPLAIN plans](../understanding_explain_plans.md).
+- Guide on [understanding EXPLAIN plans](understanding_explain_plans.md).
- [Explaining the unexplainable series in `depesz`](https://www.depesz.com/tag/unexplainable/).
-We also have licensed access to The Art of PostgreSQL available, if you are interested in getting access please check out the
+We also have licensed access to The Art of PostgreSQL. If you are interested in getting access, check out the
[issue (confidential)](https://gitlab.com/gitlab-org/database-team/team-tasks/-/issues/23).
Finally, you can find various guides in the [Database guides](index.md) page that cover more specific
@@ -95,7 +95,7 @@ are three times as likely to be picked by the [Danger bot](../dangerbot.md) as o
## What to do if you feel overwhelmed
Similar to all types of reviews, [unblocking others is always a top priority](https://about.gitlab.com/handbook/values/#global-optimization).
-Database reviewers are expected to [review assigned merge requests in a timely manner](../code_review.md#review-turnaround-time)
+Database reviewers are expected to [review assigned merge requests in a timely manner](https://about.gitlab.com/handbook/engineering/workflow/code-review/#review-turnaround-time)
or let the author know as soon as possible and help them find another reviewer or maintainer.
We are doing reviews to help the rest of the GitLab team and, at the same time, get exposed
diff --git a/doc/development/database/db_dump.md b/doc/development/database/db_dump.md
new file mode 100644
index 00000000000..f2076cbc410
--- /dev/null
+++ b/doc/development/database/db_dump.md
@@ -0,0 +1,56 @@
+---
+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
+---
+
+# Importing a database dump into a staging environment
+
+Sometimes it is useful to import the database from a production environment
+into a staging environment for testing. The procedure below assumes you have
+SSH and `sudo` access to both the production environment and the staging VM.
+
+**Destroy your staging VM** when you are done with it. It is important to avoid
+data leaks.
+
+On the staging VM, add the following line to `/etc/gitlab/gitlab.rb` to speed up
+large database imports.
+
+```shell
+# On STAGING
+echo "postgresql['checkpoint_segments'] = 64" | sudo tee -a /etc/gitlab/gitlab.rb
+sudo touch /etc/gitlab/skip-auto-reconfigure
+sudo gitlab-ctl reconfigure
+sudo gitlab-ctl stop puma
+sudo gitlab-ctl stop sidekiq
+```
+
+Next, we let the production environment stream a compressed SQL dump to our
+local machine via SSH, and redirect this stream to a `psql` client on the staging
+VM.
+
+```shell
+# On LOCAL MACHINE
+ssh -C gitlab.example.com sudo -u gitlab-psql /opt/gitlab/embedded/bin/pg_dump -Cc gitlabhq_production |\
+ ssh -C staging-vm sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql -d template1
+```
+
+## Recreating directory structure
+
+If you need to re-create some directory structure on the staging server you can
+use this procedure.
+
+First, on the production server, create a list of directories you want to
+re-create.
+
+```shell
+# On PRODUCTION
+(umask 077; sudo find /var/opt/gitlab/git-data/repositories -maxdepth 1 -type d -print0 > directories.txt)
+```
+
+Copy `directories.txt` to the staging server and create the directories there.
+
+```shell
+# On STAGING
+sudo -u git xargs -0 mkdir -p < directories.txt
+```
diff --git a/doc/development/database/filtering_by_label.md b/doc/development/database/filtering_by_label.md
new file mode 100644
index 00000000000..29b0c75298e
--- /dev/null
+++ b/doc/development/database/filtering_by_label.md
@@ -0,0 +1,179 @@
+---
+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
+---
+# Filtering by label
+
+## Introduction
+
+GitLab has [labels](../../user/project/labels.md) that can be assigned to issues,
+merge requests, and epics. Labels on those objects are a many-to-many relation
+through the polymorphic `label_links` table.
+
+To filter these objects by multiple labels - for instance, 'all open
+issues with the label ~Plan and the label ~backend' - we generate a
+query containing a `GROUP BY` clause. In a simple form, this looks like:
+
+```sql
+SELECT
+ issues.*
+FROM
+ issues
+ INNER JOIN label_links ON label_links.target_id = issues.id
+ AND label_links.target_type = 'Issue'
+ INNER JOIN labels ON labels.id = label_links.label_id
+WHERE
+ issues.project_id = 13083
+ AND (issues.state IN ('opened'))
+ AND labels.title IN ('Plan',
+ 'backend')
+GROUP BY
+ issues.id
+HAVING (COUNT(DISTINCT labels.title) = 2)
+ORDER BY
+ issues.updated_at DESC,
+ issues.id DESC
+LIMIT 20 OFFSET 0
+```
+
+In particular, note that:
+
+1. We `GROUP BY issues.id` so that we can ...
+1. Use the `HAVING (COUNT(DISTINCT labels.title) = 2)` condition to ensure that
+ all matched issues have both labels.
+
+This is more complicated than is ideal. It makes the query construction more
+prone to errors (such as
+[issue #15557](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15557)).
+
+## Attempt A: `WHERE EXISTS`
+
+### Attempt A1: use multiple subqueries with `WHERE EXISTS`
+
+In [issue #37137](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37137)
+and its associated [merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14022),
+we tried to replace the `GROUP BY` with multiple uses of `WHERE EXISTS`. For the
+example above, this would give:
+
+```sql
+WHERE (EXISTS (
+ SELECT
+ TRUE
+ FROM
+ label_links
+ INNER JOIN labels ON labels.id = label_links.label_id
+ WHERE
+ labels.title = 'Plan'
+ AND target_type = 'Issue'
+ AND target_id = issues.id))
+AND (EXISTS (
+ SELECT
+ TRUE
+ FROM
+ label_links
+ INNER JOIN labels ON labels.id = label_links.label_id
+ WHERE
+ labels.title = 'backend'
+ AND target_type = 'Issue'
+ AND target_id = issues.id))
+```
+
+While this worked without schema changes, and did improve readability somewhat,
+it did not improve query performance.
+
+### Attempt A2: use label IDs in the `WHERE EXISTS` clause
+
+In [merge request #34503](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503), we followed a similar approach to A1. But this time, we
+did a separate query to fetch the IDs of the labels used in the filter so that we avoid the `JOIN` in the `EXISTS` clause and filter directly by
+`label_links.label_id`. We also added a new index on `label_links` for the `target_id`, `label_id`, and `target_type` columns to speed up this query.
+
+Finding the label IDs wasn't straightforward because there could be multiple labels with the same title within a single root namespace. We solved
+this by grouping the label IDs by title and then using the array of IDs in the `EXISTS` clauses.
+
+This resulted in a significant performance improvement. However, this optimization could not be applied to the dashboard pages
+where we do not have a project or group context. We could not easily search for the label IDs here because that would mean searching across all
+projects and groups that the user has access to.
+
+## Attempt B: Denormalize using an array column
+
+Having [removed MySQL support in GitLab 12.1](https://about.gitlab.com/blog/2019/06/27/removing-mysql-support/),
+using [PostgreSQL's arrays](https://www.postgresql.org/docs/11/arrays.html) became more
+tractable as we didn't have to support two databases. We discussed denormalizing
+the `label_links` table for querying in
+[issue #49651](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49651),
+with two options: label IDs and titles.
+
+We can think of both of those as array columns on `issues`, `merge_requests`,
+and `epics`: `issues.label_ids` would be an array column of label IDs, and
+`issues.label_titles` would be an array of label titles.
+
+These array columns can be complemented with
+[GIN indexes](https://www.postgresql.org/docs/11/gin-intro.html) to improve
+matching.
+
+### Attempt B1: store label IDs for each object
+
+This has some strong advantages over titles:
+
+1. Unless a label is deleted, or a project is moved, we never need to
+ bulk-update the denormalized column.
+1. It uses less storage than the titles.
+
+Unfortunately, our application design makes this hard. If we were able to query
+just by label ID easily, we wouldn't need the `INNER JOIN labels` in the initial
+query at the start of this document. GitLab allows users to filter by label
+title across projects and even across groups, so a filter by the label ~Plan may
+include labels with multiple distinct IDs.
+
+We do not want users to have to know about the different IDs, which means that
+given this data set:
+
+| Project | ~Plan label ID | ~backend label ID |
+| ------- | -------------- | ----------------- |
+| A | 11 | 12 |
+| B | 21 | 22 |
+| C | 31 | 32 |
+
+We would need something like:
+
+```sql
+WHERE
+ label_ids @> ARRAY[11, 12]
+ OR label_ids @> ARRAY[21, 22]
+ OR label_ids @> ARRAY[31, 32]
+```
+
+This can get even more complicated when we consider that in some cases, there
+might be two ~backend labels - with different IDs - that could apply to the same
+object, so the number of combinations would balloon further.
+
+### Attempt B2: store label titles for each object
+
+From the perspective of updating the object, this is the worst
+option. We have to bulk update the objects when:
+
+1. The objects are moved from one project to another.
+1. The project is moved from one group to another.
+1. The label is renamed.
+1. The label is deleted.
+
+It also uses much more storage. Querying is simple, though:
+
+```sql
+WHERE
+ label_titles @> ARRAY['Plan', 'backend']
+```
+
+And our [tests in issue #49651](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49651#note_188777346)
+showed that this could be fast.
+
+However, at present, the disadvantages outweigh the advantages.
+
+## Conclusion
+
+We found a method A2 that does not need denormalization and improves the query performance significantly. This
+did not apply to all cases, but we were able to apply method A1 to the rest of the cases so that we remove the
+`GROUP BY` and `HAVING` clauses in all scenarios.
+
+This simplified the query and improved the performance in the most common cases.
diff --git a/doc/development/database/foreign_keys.md b/doc/development/database/foreign_keys.md
new file mode 100644
index 00000000000..7834e7d53c3
--- /dev/null
+++ b/doc/development/database/foreign_keys.md
@@ -0,0 +1,199 @@
+---
+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
+---
+
+# Foreign Keys & Associations
+
+When adding an association to a model you must also add a foreign key. For
+example, say you have the following model:
+
+```ruby
+class User < ActiveRecord::Base
+ has_many :posts
+end
+```
+
+Add a foreign key here on column `posts.user_id`. This ensures
+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
+
+Foreign keys can be added concurrently using `add_concurrent_foreign_key` as
+defined in `Gitlab::Database::MigrationHelpers`. See the
+[Migration Style Guide](../migration_style_guide.md) for more information.
+
+Keep in mind that you can only safely add foreign keys to existing tables after
+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
+
+Sometimes a foreign key constraint must be changed, preserving the column
+but updating the constraint condition. For example, moving from
+`ON DELETE CASCADE` to `ON DELETE SET NULL` or vice-versa.
+
+PostgreSQL does not prevent you from adding overlapping foreign keys. It
+honors the most recently added constraint. This allows us to replace foreign keys without
+ever losing foreign key protection on a column.
+
+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.
+
+ ```ruby
+ class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ 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 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'
+
+ # 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
+ ```
+
+1. Remove the old foreign key:
+
+ ```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
+
+ 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
+
+Every foreign key must define an `ON DELETE` clause, and in 99% of the cases
+this should be set to `CASCADE`.
+
+## Indexes
+
+When adding a foreign key in PostgreSQL the column is not indexed automatically,
+thus you must also add a concurrent index. Not doing so results in cascading
+deletes being very slow.
+
+## Naming foreign keys
+
+By default Ruby on Rails uses the `_id` suffix for foreign keys. So we should
+only use this suffix for associations between two tables. If you want to
+reference an ID on a third party platform the `_xid` suffix is recommended.
+
+The spec `spec/db/schema_spec.rb` tests if all columns with the `_id` suffix
+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
+
+Don't define options such as `dependent: :destroy` or `dependent: :delete` when
+defining an association. Defining these options means Rails handles the
+removal of data, instead of letting the database handle this in the most
+efficient way possible.
+
+In other words, this is bad and should be avoided at all costs:
+
+```ruby
+class User < ActiveRecord::Base
+ has_many :posts, dependent: :destroy
+end
+```
+
+Should you truly have a need for this it should be approved by a database
+specialist first.
+
+You should also not define any `before_destroy` or `after_destroy` callbacks on
+your models _unless_ absolutely required and only when approved by database
+specialists. For example, if each row in a table has a corresponding file on a
+file system it may be tempting to add a `after_destroy` hook. This however
+introduces non database logic to a model, and means we can no longer rely on
+foreign keys to remove the data as this would result in the file system data
+being left behind. In such a case you should use a service class instead that
+takes care of removing non database data.
+
+In cases where the relation spans multiple databases you have even
+further problems using `dependent: :destroy` or the above hooks. You can
+read more about alternatives at
+[Avoid `dependent: :nullify` and `dependent: :destroy` across databases](multiple_databases.md#avoid-dependent-nullify-and-dependent-destroy-across-databases).
+
+## Alternative primary keys with `has_one` associations
+
+Sometimes a `has_one` association is used to create a one-to-one relationship:
+
+```ruby
+class User < ActiveRecord::Base
+ has_one :user_config
+end
+
+class UserConfig < ActiveRecord::Base
+ belongs_to :user
+end
+```
+
+In these cases, there may be an opportunity to remove the unnecessary `id`
+column on the associated table, `user_config.id` in this example. Instead,
+the originating table ID can be used as the primary key for the associated
+table:
+
+```ruby
+create_table :user_configs, id: false do |t|
+ t.references :users, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
+ ...
+end
+```
+
+Setting `default: nil` ensures a primary key sequence is not created, and since 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:
+
+```ruby
+class UserConfig < ActiveRecord::Base
+ self.primary_key = :user_id
+
+ belongs_to :user
+end
+```
+
+Using a foreign key as primary key saves space but can make
+[batch counting](../service_ping/implement.md#batch-counters) in [Service Ping](../service_ping/index.md) less efficient.
+Consider using a regular `id` column if the table is relevant for Service Ping.
diff --git a/doc/development/database/hash_indexes.md b/doc/development/database/hash_indexes.md
new file mode 100644
index 00000000000..731639b6f06
--- /dev/null
+++ b/doc/development/database/hash_indexes.md
@@ -0,0 +1,26 @@
+---
+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
+---
+
+# Hash Indexes
+
+PostgreSQL supports hash indexes besides the regular B-tree
+indexes. Hash indexes however are to be avoided at all costs. While they may
+_sometimes_ provide better performance the cost of rehashing can be very high.
+More importantly: at least until PostgreSQL 10.0 hash indexes are not
+WAL-logged, meaning they are not replicated to any replicas. From the PostgreSQL
+documentation:
+
+> Hash index operations are not presently WAL-logged, so hash indexes might need
+> to be rebuilt with REINDEX after a database crash if there were unwritten
+> changes. Also, changes to hash indexes are not replicated over streaming or
+> file-based replication after the initial base backup, so they give wrong
+> answers to queries that subsequently use them. For these reasons, hash index
+> use is presently discouraged.
+
+RuboCop is configured to register an offense when it detects the use of a hash
+index.
+
+Instead of using hash indexes you should use regular B-tree indexes.
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index b427f54ff3c..8cf9a2eec04 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -16,52 +16,62 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Tooling
-- [Understanding EXPLAIN plans](../understanding_explain_plans.md)
+- [Understanding EXPLAIN plans](understanding_explain_plans.md)
- [explain.depesz.com](https://explain.depesz.com/) or [explain.dalibo.com](https://explain.dalibo.com/) for visualizing the output of `EXPLAIN`
- [pgFormatter](https://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier
- [db:check-migrations job](dbcheck-migrations-job.md)
## Migrations
+- [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)
+- [Batched background migrations guidelines](batched_background_migrations.md)
+- [Deleting migrations](deleting_migrations.md)
+- [Running database migrations](database_debugging.md#migration-wrangling)
- [Migrations for multiple databases](migrations_for_multiple_databases.md)
- [Avoiding downtime in migrations](avoiding_downtime_in_migrations.md)
-- [SQL guidelines](../sql.md) for working with SQL queries
+- [When and how to write Rails migrations tests](../testing_guide/testing_migrations_guide.md)
- [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)
+- [Swapping tables](swapping_tables.md)
- [Deleting migrations](deleting_migrations.md)
+- [SQL guidelines](../sql.md) for working with SQL queries
- [Partitioning tables](table_partitioning.md)
## Debugging
-- Tracing the source of an SQL query using query comments with [Marginalia](../database_query_comments.md)
+- [Resetting the database](database_debugging.md#delete-everything-and-start-over)
+- [Accessing the database](database_debugging.md#manually-access-the-database)
+- [Troubleshooting and debugging the database](database_debugging.md)
+- Tracing the source of an SQL query using query comments with [Marginalia](database_query_comments.md)
- Tracing the source of an SQL query in Rails console using [Verbose Query Logs](https://guides.rubyonrails.org/debugging_rails_applications.html#verbose-query-logs)
## Best practices
-- [Adding database indexes](../adding_database_indexes.md)
-- [Foreign keys & associations](../foreign_keys.md)
+- [Adding database indexes](adding_database_indexes.md)
+- [Foreign keys & associations](foreign_keys.md)
- [Adding a foreign key constraint to an existing column](add_foreign_key_to_existing_column.md)
- [`NOT NULL` constraints](not_null_constraints.md)
- [Strings and the Text data type](strings_and_the_text_data_type.md)
-- [Single table inheritance](../single_table_inheritance.md)
-- [Polymorphic associations](../polymorphic_associations.md)
-- [Serializing data](../serializing_data.md)
-- [Hash indexes](../hash_indexes.md)
-- [Storing SHA1 hashes as binary](../sha1_as_binary.md)
-- [Iterating tables in batches](../iterating_tables_in_batches.md)
-- [Insert into tables in batches](../insert_into_tables_in_batches.md)
-- [Ordering table columns](../ordering_table_columns.md)
-- [Verifying database capabilities](../verifying_database_capabilities.md)
-- [Database Debugging and Troubleshooting](../database_debugging.md)
-- [Query Count Limits](../query_count_limits.md)
-- [Creating enums](../creating_enums.md)
+- [Single table inheritance](single_table_inheritance.md)
+- [Polymorphic associations](polymorphic_associations.md)
+- [Serializing data](serializing_data.md)
+- [Hash indexes](hash_indexes.md)
+- [Storing SHA1 hashes as binary](sha1_as_binary.md)
+- [Iterating tables in batches](iterating_tables_in_batches.md)
+- [Insert into tables in batches](insert_into_tables_in_batches.md)
+- [Ordering table columns](ordering_table_columns.md)
+- [Verifying database capabilities](verifying_database_capabilities.md)
+- [Query Count Limits](query_count_limits.md)
+- [Creating enums](creating_enums.md)
- [Client-side connection-pool](client_side_connection_pool.md)
- [Updating multiple values](setting_multiple_values.md)
- [Constraints naming conventions](constraint_naming_convention.md)
-- [Query performance guidelines](../query_performance.md)
+- [Query performance guidelines](query_performance.md)
- [Pagination guidelines](pagination_guidelines.md)
- [Pagination performance guidelines](pagination_performance_guidelines.md)
- [Efficient `IN` operator queries](efficient_in_operator_queries.md)
@@ -69,8 +79,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Case studies
-- [Database case study: Filtering by label](../filtering_by_label.md)
-- [Database case study: Namespaces storage statistics](../namespaces_storage_statistics.md)
+- [Database case study: Filtering by label](filtering_by_label.md)
+- [Database case study: Namespaces storage statistics](namespaces_storage_statistics.md)
## Miscellaneous
diff --git a/doc/development/database/insert_into_tables_in_batches.md b/doc/development/database/insert_into_tables_in_batches.md
new file mode 100644
index 00000000000..ebed3d16319
--- /dev/null
+++ b/doc/development/database/insert_into_tables_in_batches.md
@@ -0,0 +1,196 @@
+---
+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
+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
+of APIs that make it safe and simple to insert ActiveRecord objects in bulk."
+---
+
+# Insert into tables in batches
+
+Sometimes it is necessary to store large amounts of records at once, which can be inefficient
+when iterating collections and saving each record individually. With the arrival of
+[`insert_all`](https://apidock.com/rails/ActiveRecord/Persistence/ClassMethods/insert_all)
+in Rails 6, which operates at the row level (that is, using `Hash` objects), GitLab has added a set
+of APIs that make it safe and simple to insert `ActiveRecord` objects in bulk.
+
+## Prepare `ApplicationRecord`s for bulk insertion
+
+In order for a model class to take advantage of the bulk insertion API, it has to include the
+`BulkInsertSafe` concern first:
+
+```ruby
+class MyModel < ApplicationRecord
+ # other includes here
+ # ...
+ include BulkInsertSafe # include this last
+
+ # ...
+end
+```
+
+The `BulkInsertSafe` concern has two functions:
+
+- It performs checks against your model class to ensure that it does not use ActiveRecord
+ APIs that are not safe to use with respect to bulk insertions (more on that below).
+- It adds new class methods `bulk_insert!` and `bulk_upsert!`, which you can use to insert many records at once.
+
+## Insert records with `bulk_insert!` and `bulk_upsert!`
+
+If the target class passes the checks performed by `BulkInsertSafe`, you can insert an array of
+ActiveRecord model objects as follows:
+
+```ruby
+records = [MyModel.new, ...]
+
+MyModel.bulk_insert!(records)
+```
+
+Calls to `bulk_insert!` always attempt to insert _new records_. If instead
+you would like to replace existing records with new values, while still inserting those
+that do not already exist, then you can use `bulk_upsert!`:
+
+```ruby
+records = [MyModel.new, existing_model, ...]
+
+MyModel.bulk_upsert!(records, unique_by: [:name])
+```
+
+In this example, `unique_by` specifies the columns by which records are considered to be
+unique and as such are updated if they existed prior to insertion. For example, if
+`existing_model` has a `name` attribute, and if a record with the same `name` value already
+exists, its fields are updated with those of `existing_model`.
+
+The `unique_by` parameter can also be passed as a `Symbol`, in which case it specifies
+a database index by which a column is considered unique:
+
+```ruby
+MyModel.bulk_insert!(records, unique_by: :index_on_name)
+```
+
+### Record validation
+
+The `bulk_insert!` method guarantees that `records` are inserted transactionally, and
+runs validations on each record prior to insertion. If any record fails to validate,
+an error is raised and the transaction is rolled back. You can turn off validations via
+the `:validate` option:
+
+```ruby
+MyModel.bulk_insert!(records, validate: false)
+```
+
+### Batch size configuration
+
+In those cases where the number of `records` is above a given threshold, insertions
+occur in multiple batches. The default batch size is defined in
+[`BulkInsertSafe::DEFAULT_BATCH_SIZE`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/bulk_insert_safe.rb).
+Assuming a default threshold of 500, inserting 950 records
+would result in two batches being written sequentially (of size 500 and 450 respectively.)
+You can override the default batch size via the `:batch_size` option:
+
+```ruby
+MyModel.bulk_insert!(records, batch_size: 100)
+```
+
+Assuming the same number of 950 records, this would result in 10 batches being written instead.
+Since this also affects the number of `INSERT` statements that occur, make sure you measure the
+performance impact this might have on your code. There is a trade-off between the number of
+`INSERT` statements the database has to process and the size and cost of each `INSERT`.
+
+### Handling duplicate records
+
+NOTE:
+This parameter applies only to `bulk_insert!`. If you intend to update existing
+records, use `bulk_upsert!` instead.
+
+It may happen that some records you are trying to insert already exist, which would result in
+primary key conflicts. There are two ways to address this problem: failing fast by raising an
+error or skipping duplicate records. The default behavior of `bulk_insert!` is to fail fast
+and raise an `ActiveRecord::RecordNotUnique` error.
+
+If this is undesirable, you can instead skip duplicate records with the `skip_duplicates` flag:
+
+```ruby
+MyModel.bulk_insert!(records, skip_duplicates: true)
+```
+
+### Requirements for safe bulk insertions
+
+Large parts of ActiveRecord's persistence API are built around the notion of callbacks. Many
+of these callbacks fire in response to model life cycle events such as `save` or `create`.
+These callbacks cannot be used with bulk insertions, since they are meant to be called for
+every instance that is saved or created. Since these events do not fire when
+records are inserted in bulk, we currently prevent their use.
+
+The specifics around which callbacks are explicitly allowed are defined in
+[`BulkInsertSafe`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/bulk_insert_safe.rb).
+Consult the module source code for details. If your class uses callbacks that are not explicitly designated
+safe and you `include BulkInsertSafe` the application fails with an error.
+
+### `BulkInsertSafe` versus `InsertAll`
+
+Internally, `BulkInsertSafe` is based on `InsertAll`, and you may wonder when to choose
+the former over the latter. To help you make the decision,
+the key differences between these classes are listed in the table below.
+
+| | Input type | Validates input | Specify batch size | Can bypass callbacks | Transactional |
+|--------------- | -------------------- | --------------- | ------------------ | --------------------------------- | ------------- |
+| `bulk_insert!` | ActiveRecord objects | Yes (optional) | Yes (optional) | No (prevents unsafe callback use) | Yes |
+| `insert_all!` | Attribute hashes | No | No | Yes | Yes |
+
+To summarize, `BulkInsertSafe` moves bulk inserts closer to how ActiveRecord objects
+and inserts would normally behave. However, if all you need is to insert raw data in bulk, then
+`insert_all` is more efficient.
+
+## Insert `has_many` associations in bulk
+
+A common use case is to save collections of associated relations through the owner side of the relation,
+where the owned relation is associated to the owner through the `has_many` class method:
+
+```ruby
+owner = OwnerModel.new(owned_relations: array_of_owned_relations)
+# saves all `owned_relations` one-by-one
+owner.save!
+```
+
+This issues a single `INSERT`, and transaction, for every record in `owned_relations`, which is inefficient if
+`array_of_owned_relations` is large. To remedy this, the `BulkInsertableAssociations` concern can be
+used to declare that the owner defines associations that are safe for bulk insertion:
+
+```ruby
+class OwnerModel < ApplicationRecord
+ # other includes here
+ # ...
+ include BulkInsertableAssociations # include this last
+
+ has_many :my_models
+end
+```
+
+Here `my_models` must be declared `BulkInsertSafe` (as described previously) for bulk insertions
+to happen. You can now insert any yet unsaved records as follows:
+
+```ruby
+BulkInsertableAssociations.with_bulk_insert do
+ owner = OwnerModel.new(my_models: array_of_my_model_instances)
+ # saves `my_models` using a single bulk insert (possibly via multiple batches)
+ owner.save!
+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.
+
+## Known limitations
+
+There are a few restrictions to how these APIs can be used:
+
+- `BulkInsertableAssociations`:
+ - It is currently only compatible with `has_many` relations.
+ - It does not yet support `has_many through: ...` relations.
+
+Moreover, input data should either be limited to around 1000 records at most,
+or already batched prior to calling bulk insert. The `INSERT` statement runs in a single
+transaction, so for large amounts of records it may negatively affect database stability.
diff --git a/doc/development/database/iterating_tables_in_batches.md b/doc/development/database/iterating_tables_in_batches.md
new file mode 100644
index 00000000000..6d7a57ecacb
--- /dev/null
+++ b/doc/development/database/iterating_tables_in_batches.md
@@ -0,0 +1,598 @@
+---
+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
+---
+
+# Iterating tables in batches
+
+Rails provides a method called `in_batches` that can be used to iterate over
+rows in batches. For example:
+
+```ruby
+User.in_batches(of: 10) do |relation|
+ relation.update_all(updated_at: Time.now)
+end
+```
+
+Unfortunately, this method is implemented in a way that is not very efficient,
+both query and memory usage wise.
+
+To work around this you can include the `EachBatch` module into your models,
+then use the `each_batch` class method. For example:
+
+```ruby
+class User < ActiveRecord::Base
+ include EachBatch
+end
+
+User.each_batch(of: 10) do |relation|
+ relation.update_all(updated_at: Time.now)
+end
+```
+
+This produces queries such as:
+
+```plaintext
+User Load (0.7ms) SELECT "users"."id" FROM "users" WHERE ("users"."id" >= 41654) ORDER BY "users"."id" ASC LIMIT 1 OFFSET 1000
+ (0.7ms) SELECT COUNT(*) FROM "users" WHERE ("users"."id" >= 41654) AND ("users"."id" < 42687)
+```
+
+The API of this method is similar to `in_batches`, though it doesn't support
+all of the arguments that `in_batches` supports. You should always use
+`each_batch` _unless_ you have a specific need for `in_batches`.
+
+## Iterating over non-unique columns
+
+One should proceed with extra caution. When you iterate over an attribute that is not unique,
+even with the applied max batch size, there is no guarantee that the resulting batches do not
+surpass it. The following snippet demonstrates this situation when one attempt to select
+`Ci::Build` entries for users with `id` between `1` and `10,000`, the database returns
+`1 215 178` matching rows.
+
+```ruby
+[ gstg ] production> Ci::Build.where(user_id: (1..10_000)).size
+=> 1215178
+```
+
+This happens because the built relation is translated into the following query:
+
+```ruby
+[ gstg ] production> puts Ci::Build.where(user_id: (1..10_000)).to_sql
+SELECT "ci_builds".* FROM "ci_builds" WHERE "ci_builds"."type" = 'Ci::Build' AND "ci_builds"."user_id" BETWEEN 1 AND 10000
+=> nil
+```
+
+`And` queries which filter non-unique column by range `WHERE "ci_builds"."user_id" BETWEEN ? AND ?`,
+even though the range size is limited to a certain threshold (`10,000` in the previous example) this
+threshold does not translate to the size of the returned dataset. That happens because when taking
+`n` possible values of attributes, one can't tell for sure that the number of records that contains
+them is less than `n`.
+
+### Loose-index scan with `distinct_each_batch`
+
+When iterating over a non-unique column is necessary, use the `distinct_each_batch` helper
+method. The helper uses the [loose-index scan technique](https://wiki.postgresql.org/wiki/Loose_indexscan)
+(skip-index scan) to skip duplicated values within a database index.
+
+Example: iterating over distinct `author_id` in the Issue model
+
+```ruby
+Issue.distinct_each_batch(column: :author_id, of: 1000) do |relation|
+ users = User.where(id: relation.select(:author_id)).to_a
+end
+```
+
+The technique provides stable performance between the batches regardless of the data distribution.
+The `relation` object returns an ActiveRecord scope where only the given `column` is available.
+Other columns are not loaded.
+
+The underlying database queries use recursive CTEs, which adds extra overhead. We therefore advise to use
+smaller batch sizes than those used for a standard `each_batch` iteration.
+
+## Column definition
+
+`EachBatch` uses the primary key of the model by default for the iteration. This works most of the
+cases, however in some cases, you might want to use a different column for the iteration.
+
+```ruby
+Project.distinct.each_batch(column: :creator_id, of: 10) do |relation|
+ puts User.where(id: relation.select(:creator_id)).map(&:id)
+end
+```
+
+The query above iterates over the project creators and prints them out without duplications.
+
+NOTE:
+In case the column is not unique (no unique index definition), calling the `distinct` method on
+the relation is necessary. Using not unique column without `distinct` may result in `each_batch`
+falling into an endless loop as described in following
+[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/285097).
+
+## `EachBatch` in data migrations
+
+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)
+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`.
+
+## Efficient usage of `each_batch`
+
+`EachBatch` helps to iterate over large tables. It's important to highlight that `EachBatch`
+does not magically solve all iteration-related performance problems, and it might not help at
+all in some scenarios. From the database point of view, correctly configured database indexes are
+also necessary to make `EachBatch` perform well.
+
+### Example 1: Simple iteration
+
+Let's consider that we want to iterate over the `users` table and print the `User` records to the
+standard output. The `users` table contains millions of records, thus running one query to fetch
+the users likely times out.
+
+![Users table overview](../img/each_batch_users_table_v13_7.png)
+
+This is a simplified version of the `users` table which contains several rows. We have a few
+smaller gaps in the `id` column to make the example a bit more realistic (a few records were
+already deleted). Currently, we have one index on the `id` field.
+
+Loading all users into memory (avoid):
+
+```ruby
+users = User.all
+
+users.each { |user| puts user.inspect }
+```
+
+Use `each_batch`:
+
+```ruby
+# Note: for this example I picked 5 as the batch size, the default is 1_000
+User.each_batch(of: 5) do |relation|
+ relation.each { |user| puts user.inspect }
+end
+```
+
+#### How `each_batch` works
+
+As the first step, it finds the lowest `id` (start `id`) in the table by executing the following
+database query:
+
+```sql
+SELECT "users"."id" FROM "users" ORDER BY "users"."id" ASC LIMIT 1
+```
+
+![Reading the start ID value](../img/each_batch_users_table_iteration_1_v13_7.png)
+
+Notice that the query only reads data from the index (`INDEX ONLY SCAN`), the table is not
+accessed. Database indexes are sorted so taking out the first item is a very cheap operation.
+
+The next step is to find the next `id` (end `id`) which should respect the batch size
+configuration. In this example we used a batch size of 5. `EachBatch` uses the `OFFSET` clause
+to get a "shifted" `id` value.
+
+```sql
+SELECT "users"."id" FROM "users" WHERE "users"."id" >= 1 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
+```
+
+![Reading the end ID value](../img/each_batch_users_table_iteration_2_v13_7.png)
+
+Again, the query only looks into the index. The `OFFSET 5` takes out the sixth `id` value: this
+query reads a maximum of six items from the index regardless of the table size or the iteration
+count.
+
+At this point, we know the `id` range for the first batch. Now it's time to construct the query
+for the `relation` block.
+
+```sql
+SELECT "users".* FROM "users" WHERE "users"."id" >= 1 AND "users"."id" < 302
+```
+
+![Reading the rows from the `users` table](../img/each_batch_users_table_iteration_3_v13_7.png)
+
+Notice the `<` sign. Previously six items were read from the index and in this query, the last
+value is "excluded". The query looks at the index to get the location of the five `user`
+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.
+
+```sql
+SELECT "users"."id" FROM "users" WHERE "users"."id" >= 302 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
+```
+
+![Reading the second end ID value](../img/each_batch_users_table_iteration_4_v13_7.png)
+
+Now we can easily construct the `users` query for the second iteration.
+
+```sql
+SELECT "users".* FROM "users" WHERE "users"."id" >= 302 AND "users"."id" < 353
+```
+
+![Reading the rows for the second iteration from the users table](../img/each_batch_users_table_iteration_5_v13_7.png)
+
+### Example 2: Iteration with filters
+
+Building on top of the previous example, we want to print users with zero sign-in count. We keep
+track of the number of sign-ins in the `sign_in_count` column so we write the following code:
+
+```ruby
+users = User.where(sign_in_count: 0)
+
+users.each_batch(of: 5) do |relation|
+ relation.each { |user| puts user.inspect }
+end
+```
+
+`each_batch` produces the following SQL query for the start `id` value:
+
+```sql
+SELECT "users"."id" FROM "users" WHERE "users"."sign_in_count" = 0 ORDER BY "users"."id" ASC LIMIT 1
+```
+
+Selecting only the `id` column and ordering by `id` forces the database to use the
+index on the `id` (primary key index) column however, we also have an extra condition on the
+`sign_in_count` column. The column is not part of the index, so the database needs to look into
+the actual table to find the first matching row.
+
+![Reading the index with extra filter](../img/each_batch_users_table_filter_v13_7.png)
+
+NOTE:
+The number of scanned rows depends on the data distribution in the table.
+
+- Best case scenario: the first user was never logged in. The database reads only one row.
+- Worst case scenario: all users were logged in at least once. The database reads all rows.
+
+In this particular example, the database had to read 10 rows (regardless of our batch size setting)
+to determine the first `id` value. In a "real-world" application it's hard to predict whether the
+filtering causes problems or not. In the case of GitLab, verifying the data on a
+production replica is a good start, but keep in mind that data distribution on GitLab.com can be
+different from self-managed instances.
+
+#### Improve filtering with `each_batch`
+
+##### Specialized conditional index
+
+```sql
+CREATE INDEX index_on_users_never_logged_in ON users (id) WHERE sign_in_count = 0
+```
+
+This is how our table and the newly created index looks like:
+
+![Reading the specialized index](../img/each_batch_users_table_filtered_index_v13_7.png)
+
+This index definition covers the conditions on the `id` and `sign_in_count` columns thus makes the
+`each_batch` queries very effective (similar to the simple iteration example).
+
+It's rare when a user was never signed in so we a anticipate small index size. Including only the
+`id` in the index definition also helps to keep the index size small.
+
+##### Index on columns
+
+Later on, we might want to iterate over the table filtering for different `sign_in_count` values, in
+those cases we cannot use the previously suggested conditional index because the `WHERE` condition
+does not match with our new filter (`sign_in_count > 10`).
+
+To address this problem, we have two options:
+
+- Create another, conditional index to cover the new query.
+- Replace the index with a more generalized configuration.
+
+NOTE:
+Having multiple indexes on the same table and on the same columns could be a performance bottleneck
+when writing data.
+
+Let's consider the following index (avoid):
+
+```sql
+CREATE INDEX index_on_users_never_logged_in ON users (id, sign_in_count)
+```
+
+The index definition starts with the `id` column which makes the index very inefficient from data
+selectivity point of view.
+
+```sql
+SELECT "users"."id" FROM "users" WHERE "users"."sign_in_count" = 0 ORDER BY "users"."id" ASC LIMIT 1
+```
+
+Executing the query above results in an `INDEX ONLY SCAN`. However, the query still needs to
+iterate over an unknown number of entries in the index, and then find the first item where the
+`sign_in_count` is `0`.
+
+![Reading an ineffective index](../img/each_batch_users_table_bad_index_v13_7.png)
+
+We can improve the query significantly by swapping the columns in the index definition (prefer).
+
+```sql
+CREATE INDEX index_on_users_never_logged_in ON users (sign_in_count, id)
+```
+
+![Reading a good index](../img/each_batch_users_table_good_index_v13_7.png)
+
+The following index definition does not work well with `each_batch` (avoid).
+
+```sql
+CREATE INDEX index_on_users_never_logged_in ON users (sign_in_count)
+```
+
+Since `each_batch` builds range queries based on the `id` column, this index cannot be used
+efficiently. The DB reads the rows from the table or uses a bitmap search where the primary
+key index is also read.
+
+##### "Slow" iteration
+
+Slow iteration means that we use a good index configuration to iterate over the table and
+apply filtering on the yielded relation.
+
+```ruby
+User.each_batch(of: 5) do |relation|
+ relation.where(sign_in_count: 0).each { |user| puts user inspect }
+end
+```
+
+The iteration uses the primary key index (on the `id` column) which makes it safe from statement
+timeouts. The filter (`sign_in_count: 0`) is applied on the `relation` where the `id` is already
+constrained (range). The number of rows is limited.
+
+Slow iteration generally takes more time to finish. The iteration count is higher and
+one iteration could yield fewer records than the batch size. Iterations may even yield
+0 records. This is not an optimal solution; however, in some cases (especially when
+dealing with large tables) this is the only viable option.
+
+### Using Subqueries
+
+Using subqueries in your `each_batch` query does not work well in most cases. Consider the following example:
+
+```ruby
+projects = Project.where(creator_id: Issue.where(confidential: true).select(:author_id))
+
+projects.each_batch do |relation|
+ # do something
+end
+```
+
+The iteration uses the `id` column of the `projects` table. The batching does not affect the
+subquery. This means for each iteration, the subquery is executed by the database. This adds a
+constant "load" on the query which often ends up in statement timeouts. We have an unknown number
+of [confidential issues](../../user/project/issues/confidential_issues.md), the execution time
+and the accessed database rows depend on the data distribution in the `issues` table.
+
+NOTE:
+Using subqueries works only when the subquery returns a small number of rows.
+
+#### Improving Subqueries
+
+When dealing with subqueries, a slow iteration approach could work: the filter on `creator_id`
+can be part of the generated `relation` object.
+
+```ruby
+projects = Project.all
+
+projects.each_batch do |relation|
+ relation.where(creator_id: Issue.where(confidential: true).select(:author_id))
+end
+```
+
+If the query on the `issues` table itself is not performant enough, a nested loop could be
+constructed. Try to avoid it when possible.
+
+```ruby
+projects = Project.all
+
+projects.each_batch do |relation|
+ issues = Issue.where(confidential: true)
+
+ issues.each_batch do |issues_relation|
+ relation.where(creator_id: issues_relation.select(:author_id))
+ end
+end
+```
+
+If we know that the `issues` table has many more rows than `projects`, it would make sense to flip
+the queries, where the `issues` table is batched first.
+
+### Using `JOIN` and `EXISTS`
+
+When to use `JOINS`:
+
+- When there's a 1:1 or 1:N relationship between the tables where we know that the joined record
+(almost) always exists. This works well for "extension-like" tables:
+ - `projects` - `project_settings`
+ - `users` - `user_details`
+ - `users` - `user_statuses`
+- `LEFT JOIN` works well in this case. Conditions on the joined table need to go to the yielded
+relation so the iteration is not affected by the data distribution in the joined table.
+
+Example:
+
+```ruby
+users = User.joins("LEFT JOIN personal_access_tokens on personal_access_tokens.user_id = users.id")
+
+users.each_batch do |relation|
+ relation.where("personal_access_tokens.name = 'name'")
+end
+```
+
+`EXISTS` queries should be added only to the inner `relation` of the `each_batch` query:
+
+```ruby
+User.each_batch do |relation|
+ relation.where("EXISTS (SELECT 1 FROM ...")
+end
+```
+
+### Complex queries on the relation object
+
+When the `relation` object has several extra conditions, the execution plans might become
+"unstable".
+
+Example:
+
+```ruby
+Issue.each_batch do |relation|
+ relation
+ .joins(:metrics)
+ .joins(:merge_requests_closing_issues)
+ .where("id IN (SELECT ...)")
+ .where(confidential: true)
+end
+```
+
+Here, we expect that the `relation` query reads the `BATCH_SIZE` of user records and then
+filters down the results according to the provided queries. The planner might decide that
+using a bitmap index lookup with the index on the `confidential` column is a better way to
+execute the query. This can cause an unexpectedly high amount of rows to be read and the
+query could time out.
+
+Problem: we know for sure that the relation is returning maximum `BATCH_SIZE` of records
+however, the planner does not know this.
+
+Common table expression (CTE) trick to force the range query to execute first:
+
+```ruby
+Issue.each_batch(of: 1000) do |relation|
+ cte = Gitlab::SQL::CTE.new(:batched_relation, relation.limit(1000))
+
+ scope = cte
+ .apply_to(Issue.all)
+ .joins(:metrics)
+ .joins(:merge_requests_closing_issues)
+ .where("id IN (SELECT ...)")
+ .where(confidential: true)
+
+ puts scope.to_a
+end
+```
+
+### `EachBatch` vs `BatchCount`
+
+When adding new counters for Service Ping, the preferred way to count records is using the
+`Gitlab::Database::BatchCount` class. The iteration logic implemented in `BatchCount`
+has similar performance characteristics like `EachBatch`. Most of the tips and suggestions
+for improving `BatchCount` mentioned above applies to `BatchCount` as well.
+
+## Iterate with keyset pagination
+
+There are a few special cases where iterating with `EachBatch` does not work. `EachBatch`
+requires one distinct column (usually the primary key), which makes the iteration impossible
+for timestamp columns and tables with composite primary keys.
+
+Where `EachBatch` does not work, you can use
+[keyset pagination](pagination_guidelines.md#keyset-pagination) to iterate over the
+table or a range of rows. The scaling and performance characteristics are very similar to
+`EachBatch`.
+
+Examples:
+
+- Iterate over the table in a specific order (timestamp columns) in combination with a tie-breaker
+if column user to sort by does not contain unique values.
+- Iterate over the table with composite primary keys.
+
+### Iterate over the issues in a project by creation date
+
+You can use keyset pagination to iterate over any database column in a specific order (for example,
+`created_at DESC`). To ensure consistent order of the returned records with the same values for
+`created_at`, use a tie-breaker column with unique values (for example, `id`).
+
+Assume you have the following index in the `issues` table:
+
+```sql
+idx_issues_on_project_id_and_created_at_and_id" btree (project_id, created_at, id)
+```
+
+### Fetching records for further processing
+
+The following snippet iterates over issue records within the project using the specified order
+(`created_at, id`).
+
+```ruby
+scope = Issue.where(project_id: 278964).order(:created_at, :id) # id is the tie-breaker
+
+iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
+
+iterator.each_batch(of: 100) do |records|
+ puts records.map(&:id)
+end
+```
+
+You can add extra filters to the query. This example only lists the issue IDs created in the last
+30 days:
+
+```ruby
+scope = Issue.where(project_id: 278964).where('created_at > ?', 30.days.ago).order(:created_at, :id) # id is the tie-breaker
+
+iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
+
+iterator.each_batch(of: 100) do |records|
+ puts records.map(&:id)
+end
+```
+
+### Updating records in the batch
+
+For complex `ActiveRecord` queries, the `.update_all` method does not work well, because it
+generates an incorrect `UPDATE` statement.
+You can use raw SQL for updating records in batches:
+
+```ruby
+scope = Issue.where(project_id: 278964).order(:created_at, :id) # id is the tie-breaker
+
+iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
+
+iterator.each_batch(of: 100) do |records|
+ ApplicationRecord.connection.execute("UPDATE issues SET updated_at=NOW() WHERE issues.id in (#{records.dup.reselect(:id).to_sql})")
+end
+```
+
+NOTE:
+To keep the iteration stable and predictable, avoid updating the columns in the `ORDER BY` clause.
+
+### Iterate over the `merge_request_diff_commits` table
+
+The `merge_request_diff_commits` table uses a composite primary key (`merge_request_diff_id,
+relative_order`), which makes `EachBatch` impossible to use efficiently.
+
+To paginate over the `merge_request_diff_commits` table, you can use the following snippet:
+
+```ruby
+# Custom order object configuration:
+order = Gitlab::Pagination::Keyset::Order.build([
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'merge_request_diff_id',
+ order_expression: MergeRequestDiffCommit.arel_table[:merge_request_diff_id].asc,
+ nullable: :not_nullable,
+ distinct: false,
+ ),
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'relative_order',
+ order_expression: MergeRequestDiffCommit.arel_table[:relative_order].asc,
+ nullable: :not_nullable,
+ distinct: false,
+ )
+])
+MergeRequestDiffCommit.include(FromUnion) # keyset pagination generates UNION queries
+
+scope = MergeRequestDiffCommit.order(order)
+
+iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
+
+iterator.each_batch(of: 100) do |records|
+ puts records.map { |record| [record.merge_request_diff_id, record.relative_order] }.inspect
+end
+```
+
+### Order object configuration
+
+Keyset pagination works well with simple `ActiveRecord` `order` scopes
+([first example](#iterate-over-the-issues-in-a-project-by-creation-date).
+However, in special cases, you need to describe the columns in the `ORDER BY` clause (second example)
+for the underlying keyset pagination library. When the `ORDER BY` configuration cannot be
+automatically determined by the keyset pagination library, an error is raised.
+
+The code comments of the
+[`Gitlab::Pagination::Keyset::Order`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/pagination/keyset/order.rb)
+and [`Gitlab::Pagination::Keyset::ColumnOrderDefinition`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/pagination/keyset/column_order_definition.rb)
+classes give an overview of the possible options for configuring the `ORDER BY` clause. You can
+also find a few code examples in the
+[keyset pagination](keyset_pagination.md#complex-order-configuration) documentation.
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
index 6aa1b9c40ff..8dbccf048d7 100644
--- a/doc/development/database/loose_foreign_keys.md
+++ b/doc/development/database/loose_foreign_keys.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
In relational databases (including PostgreSQL), foreign keys provide a way to link
two database tables together, and ensure data-consistency between them. In GitLab,
-[foreign keys](../foreign_keys.md) are vital part of the database design process.
+[foreign keys](foreign_keys.md) are vital part of the database design process.
Most of our database tables have foreign keys.
With the ongoing database [decomposition work](https://gitlab.com/groups/gitlab-org/-/epics/6168),
@@ -221,8 +221,8 @@ ON DELETE CASCADE;
```
The migration must run after the `DELETE` trigger is installed and the loose
-foreign key definition is deployed. As such, it must be a [post-deployment
-migration](post_deployment_migrations.md) dated after the migration for the
+foreign key definition is deployed. As such, it must be a
+[post-deployment migration](post_deployment_migrations.md) dated after the migration for the
trigger. If the foreign key is deleted earlier, there is a good chance of
introducing data inconsistency which needs manual cleanup:
@@ -251,8 +251,8 @@ When the loose foreign key definition is no longer needed (parent table is remov
we need to remove the definition from the YAML file and ensure that we don't leave pending deleted
records in the database.
-1. Remove the loose foreign key definition from the configuration (`config/gitlab_loose_foreign_keys.yml`).
1. Remove the deletion tracking trigger from the parent table (if the parent table is still there).
+1. Remove the loose foreign key definition from the configuration (`config/gitlab_loose_foreign_keys.yml`).
1. Remove leftover deleted records from the `loose_foreign_keys_deleted_records` table.
Migration for removing the trigger:
@@ -395,8 +395,7 @@ We considered using these Rails features as an alternative to foreign keys but t
For non-trivial objects that need to clean up data outside the
database (for example, object storage) where you might wish to use `dependent: :destroy`,
see alternatives in
-[Avoid `dependent: :nullify` and `dependent: :destroy` across
-databases](./multiple_databases.md#avoid-dependent-nullify-and-dependent-destroy-across-databases).
+[Avoid `dependent: :nullify` and `dependent: :destroy` across databases](multiple_databases.md#avoid-dependent-nullify-and-dependent-destroy-across-databases).
## Risks of loose foreign keys and possible mitigations
diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md
index 9641ea37002..31fc454f8a7 100644
--- a/doc/development/database/multiple_databases.md
+++ b/doc/development/database/multiple_databases.md
@@ -1,15 +1,14 @@
---
stage: Data Stores
-group: Sharding
+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
---
# Multiple Databases
To allow GitLab to scale further we
-[decomposed the GitLab application database into multiple
-databases](https://gitlab.com/groups/gitlab-org/-/epics/6168). The two databases
-are `main` and `ci`. GitLab supports being run with either one database or two databases.
+[decomposed the GitLab application database into multiple databases](https://gitlab.com/groups/gitlab-org/-/epics/6168).
+The two databases are `main` and `ci`. GitLab supports being run with either one database or two databases.
On GitLab.com we are using two separate databases.
## GitLab Schema
@@ -246,7 +245,7 @@ where projects_with_ci_feature_usage.ci_feature = 'code_coverage'
```
The above example uses as a text column for simplicity but we should probably
-use an [enum](../creating_enums.md) to save space.
+use an [enum](creating_enums.md) to save space.
The downside of this new design is that this may need to be
updated (removed if the `ci_daily_build_group_report_results` is deleted).
diff --git a/doc/development/database/namespaces_storage_statistics.md b/doc/development/database/namespaces_storage_statistics.md
new file mode 100644
index 00000000000..702129b9ddb
--- /dev/null
+++ b/doc/development/database/namespaces_storage_statistics.md
@@ -0,0 +1,193 @@
+---
+stage: none
+group: unassigned
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Database case study: Namespaces storage statistics
+
+## Introduction
+
+On [Storage and limits management for groups](https://gitlab.com/groups/gitlab-org/-/epics/886),
+we want to facilitate a method for easily viewing the amount of
+storage consumed by a group, and allow easy management.
+
+## Proposal
+
+1. Create a new ActiveRecord model to hold the namespaces' statistics in an aggregated form (only for root [namespaces](../../user/namespace/index.md)).
+1. Refresh the statistics in this model every time a project belonging to this namespace is changed.
+
+## Problem
+
+In GitLab, we update the project storage statistics through a
+[callback](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/project.rb#L97)
+every time the project is saved.
+
+The summary of those statistics per namespace is then retrieved
+by [`Namespaces#with_statistics`](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/namespace.rb#L70) scope. Analyzing this query we noticed that:
+
+- It takes up to `1.2` seconds for namespaces with over `15k` projects.
+- It can't be analyzed with [ChatOps](../chatops_on_gitlabcom.md), as it times out.
+
+Additionally, the pattern that is currently used to update the project statistics
+(the callback) doesn't scale adequately. It is currently one of the largest
+[database queries transactions on production](https://gitlab.com/gitlab-org/gitlab/-/issues/29070)
+that takes the most time overall. We can't add one more query to it as
+it increases the transaction's length.
+
+Because of all of the above, we can't apply the same pattern to store
+and update the namespaces statistics, as the `namespaces` table is one
+of the largest tables on GitLab.com. Therefore we needed to find a performant and
+alternative method.
+
+## Attempts
+
+### Attempt A: PostgreSQL materialized view
+
+Model can be updated through a refresh strategy based on a project routes SQL and a [materialized view](https://www.postgresql.org/docs/11/rules-materializedviews.html):
+
+```sql
+SELECT split_part("rs".path, '/', 1) as root_path,
+ COALESCE(SUM(ps.storage_size), 0) AS storage_size,
+ COALESCE(SUM(ps.repository_size), 0) AS repository_size,
+ COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
+ COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
+ COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
+ COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
+ COALESCE(SUM(ps.packages_size), 0) AS packages_size,
+ COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
+ COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
+FROM "projects"
+ INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
+ INNER JOIN project_statistics ps ON ps.project_id = projects.id
+GROUP BY root_path
+```
+
+We could then execute the query with:
+
+```sql
+REFRESH MATERIALIZED VIEW root_namespace_storage_statistics;
+```
+
+While this implied a single query update (and probably a fast one), it has some downsides:
+
+- Materialized views syntax varies from PostgreSQL and MySQL. While this feature was worked on, MySQL was still supported by GitLab.
+- Rails does not have native support for materialized views. We'd need to use a specialized gem to take care of the management of the database views, which implies additional work.
+
+### Attempt B: An update through a CTE
+
+Similar to Attempt A: Model update done through a refresh strategy with a [Common Table Expression](https://www.postgresql.org/docs/9.1/queries-with.html)
+
+```sql
+WITH refresh AS (
+ SELECT split_part("rs".path, '/', 1) as root_path,
+ COALESCE(SUM(ps.storage_size), 0) AS storage_size,
+ COALESCE(SUM(ps.repository_size), 0) AS repository_size,
+ COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
+ COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
+ COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
+ COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
+ COALESCE(SUM(ps.packages_size), 0) AS packages_size,
+ COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
+ COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
+ FROM "projects"
+ INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
+ INNER JOIN project_statistics ps ON ps.project_id = projects.id
+ GROUP BY root_path)
+UPDATE namespace_storage_statistics
+SET storage_size = refresh.storage_size,
+ repository_size = refresh.repository_size,
+ wiki_size = refresh.wiki_size,
+ lfs_objects_size = refresh.lfs_objects_size,
+ build_artifacts_size = refresh.build_artifacts_size,
+ pipeline_artifacts_size = refresh.pipeline_artifacts_size,
+ packages_size = refresh.packages_size,
+ snippets_size = refresh.snippets_size,
+ uploads_size = refresh.uploads_size
+FROM refresh
+ INNER JOIN routes rs ON rs.path = refresh.root_path AND rs.source_type = 'Namespace'
+WHERE namespace_storage_statistics.namespace_id = rs.source_id
+```
+
+Same benefits and downsides as attempt A.
+
+### Attempt C: Get rid of the model and store the statistics on Redis
+
+We could get rid of the model that stores the statistics in aggregated form and instead use a Redis Set.
+This would be the [boring solution](https://about.gitlab.com/handbook/values/#boring-solutions) and the fastest one
+to implement, as GitLab already includes Redis as part of its [Architecture](../architecture.md#redis).
+
+The downside of this approach is that Redis does not provide the same persistence/consistency guarantees as PostgreSQL,
+and this is information we can't afford to lose in a Redis failure.
+
+### Attempt D: Tag the root namespace and its child namespaces
+
+Directly relate the root namespace to its child namespaces, so
+whenever a namespace is created without a parent, this one is tagged
+with the root namespace ID:
+
+| ID | root ID | parent ID |
+|:---|:--------|:----------|
+| 1 | 1 | NULL |
+| 2 | 1 | 1 |
+| 3 | 1 | 2 |
+
+To aggregate the statistics inside a namespace we'd execute something like:
+
+```sql
+SELECT COUNT(...)
+FROM projects
+WHERE namespace_id IN (
+ SELECT id
+ FROM namespaces
+ WHERE root_id = X
+)
+```
+
+Even though this approach would make aggregating much easier, it has some major downsides:
+
+- We'd have to migrate **all namespaces** by adding and filling a new column. Because of the size of the table, dealing with time/cost would be significant. The background migration would take approximately `153h`, see <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29772>.
+- Background migration has to be shipped one release before, delaying the functionality by another milestone.
+
+### Attempt E (final): Update the namespace storage statistics asynchronously
+
+This approach consists of continuing to use the incremental statistics updates we already have,
+but we refresh them through Sidekiq jobs and in different transactions:
+
+1. Create a second table (`namespace_aggregation_schedules`) with two columns `id` and `namespace_id`.
+1. Whenever the statistics of a project changes, insert a row into `namespace_aggregation_schedules`
+ - We don't insert a new row if there's already one related to the root namespace.
+ - Keeping in mind the length of the transaction that involves updating `project_statistics`(<https://gitlab.com/gitlab-org/gitlab/-/issues/29070>), the insertion should be done in a different transaction and through a Sidekiq Job.
+1. After inserting the row, we schedule another worker to be executed asynchronously at two different moments:
+ - One enqueued for immediate execution and another one scheduled in `1.5h` hours.
+ - We only schedule the jobs, if we can obtain a `1.5h` lease on Redis on a key based on the root namespace ID.
+ - If we can't obtain the lease, it indicates there's another aggregation already in progress, or scheduled in no more than `1.5h`.
+1. This worker will:
+ - Update the root namespace storage statistics by querying all the namespaces through a service.
+ - Delete the related `namespace_aggregation_schedules` after the update.
+1. Another Sidekiq job is also included to traverse any remaining rows on the `namespace_aggregation_schedules` table and schedule jobs for every pending row.
+ - This job is scheduled with cron to run every night (UTC).
+
+This implementation has the following benefits:
+
+- All the updates are done asynchronously, so we're not increasing the length of the transactions for `project_statistics`.
+- We're doing the update in a single SQL query.
+- It is compatible with PostgreSQL and MySQL.
+- No background migration required.
+
+The only downside of this approach is that namespaces' statistics are updated up to `1.5` hours after the change is done,
+which means there's a time window in which the statistics are inaccurate. Because we're still not
+[enforcing storage limits](https://gitlab.com/gitlab-org/gitlab/-/issues/17664), this is not a major problem.
+
+## Conclusion
+
+Updating the storage statistics asynchronously, was the less problematic and
+performant approach of aggregating the root namespaces.
+
+All the details regarding this use case can be found on:
+
+- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62214>
+- Merge Request with the implementation: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28996>
+
+Performance of the namespace storage statistics were measured in staging and production (GitLab.com). All results were posted
+on <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64092>: No problem has been reported so far.
diff --git a/doc/development/database/not_null_constraints.md b/doc/development/database/not_null_constraints.md
index 3962307f80d..9b3d017b09f 100644
--- a/doc/development/database/not_null_constraints.md
+++ b/doc/development/database/not_null_constraints.md
@@ -135,7 +135,7 @@ post-deployment migration or a background data migration:
- If the data volume is less than `1000` records, then the data migration can be executed within the post-migration.
- If the data volume is higher than `1000` records, it's advised to create a background migration.
-When unsure about which option to use, please contact the Database team for advice.
+When unsure about which option to use, contact the Database team for advice.
Back to our example, the epics table is not considerably large nor frequently accessed,
so we add a post-deployment migration for the 13.0 milestone (current),
@@ -206,6 +206,6 @@ In that rare case you need 3 releases end-to-end:
1. Release `N.M+1` - Cleanup the background migration.
1. Release `N.M+2` - Validate the `NOT NULL` constraint.
-For these cases, please consult the database team early in the update cycle. The `NOT NULL`
+For these cases, consult the database team early in the update cycle. The `NOT NULL`
constraint may not be required or other options could exist that do not affect really large
or frequently accessed tables.
diff --git a/doc/development/database/ordering_table_columns.md b/doc/development/database/ordering_table_columns.md
new file mode 100644
index 00000000000..7cd3d4fb208
--- /dev/null
+++ b/doc/development/database/ordering_table_columns.md
@@ -0,0 +1,152 @@
+---
+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
+---
+
+# Ordering Table Columns in PostgreSQL
+
+For GitLab we require that columns of new tables are ordered to use the
+least amount of space. An easy way of doing this is to order them based on the
+type size in descending order with variable sizes (`text`, `varchar`, arrays,
+`json`, `jsonb`, and so on) at the end.
+
+Similar to C structures the space of a table is influenced by the order of
+columns. This is because the size of columns is aligned depending on the type of
+the following column. Let's consider an example:
+
+- `id` (integer, 4 bytes)
+- `name` (text, variable)
+- `user_id` (integer, 4 bytes)
+
+The first column is a 4-byte integer. The next is text of variable length. The
+`text` data type requires 1-word alignment, and on 64-bit platform, 1 word is 8
+bytes. To meet the alignment requirements, four zeros are to be added right
+after the first column, so `id` occupies 4 bytes, then 4 bytes of alignment
+padding, and only next `name` is being stored. Therefore, in this case, 8 bytes
+are spent for storing a 4-byte integer.
+
+The space between rows is also subject to alignment padding. The `user_id`
+column takes only 4 bytes, and on 64-bit platform, 4 zeroes are added for
+alignment padding, to allow storing the next row beginning with the "clear" word.
+
+As a result, the actual size of each column would be (omitting variable length
+data and 24-byte tuple header): 8 bytes, variable, 8 bytes. This means that
+each row requires at least 16 bytes for the two 4-byte integers. If a table
+has a few rows this is not an issue. However, once you start storing millions of
+rows you can save space by using a different order. For the above example, the
+ideal column order would be the following:
+
+- `id` (integer, 4 bytes)
+- `user_id` (integer, 4 bytes)
+- `name` (text, variable)
+
+or
+
+- `name` (text, variable)
+- `id` (integer, 4 bytes)
+- `user_id` (integer, 4 bytes)
+
+In these examples, the `id` and `user_id` columns are packed together, which
+means we only need 8 bytes to store _both_ of them. This in turn means each row
+requires 8 bytes less space.
+
+Since Ruby on Rails 5.1, the default data type for IDs is `bigint`, which uses 8 bytes.
+We are using `integer` in the examples to showcase a more realistic reordering scenario.
+
+## Type Sizes
+
+While the [PostgreSQL documentation](https://www.postgresql.org/docs/current/datatype.html) contains plenty
+of information we list the sizes of common types here so it's easier to
+look them up. Here "word" refers to the word size, which is 4 bytes for a 32
+bits platform and 8 bytes for a 64 bits platform.
+
+| Type | Size | Alignment needed |
+|:-----------------|:-------------------------------------|:-----------|
+| `smallint` | 2 bytes | 1 word |
+| `integer` | 4 bytes | 1 word |
+| `bigint` | 8 bytes | 8 bytes |
+| `real` | 4 bytes | 1 word |
+| `double precision` | 8 bytes | 8 bytes |
+| `boolean` | 1 byte | not needed |
+| `text` / `string` | variable, 1 byte plus the data | 1 word |
+| `bytea` | variable, 1 or 4 bytes plus the data | 1 word |
+| `timestamp` | 8 bytes | 8 bytes |
+| `timestamptz` | 8 bytes | 8 bytes |
+| `date` | 4 bytes | 1 word |
+
+A "variable" size means the actual size depends on the value being stored. If
+PostgreSQL determines this can be embedded directly into a row it may do so, but
+for very large values it stores the data externally and store a pointer (of
+1 word in size) in the column. Because of this variable sized columns should
+always be at the end of a table.
+
+## Real Example
+
+Let's use the `events` table as an example, which currently has the following
+layout:
+
+| Column | Type | Size |
+|:--------------|:----------------------------|:---------|
+| `id` | integer | 4 bytes |
+| `target_type` | character varying | variable |
+| `target_id` | integer | 4 bytes |
+| `title` | character varying | variable |
+| `data` | text | variable |
+| `project_id` | integer | 4 bytes |
+| `created_at` | timestamp without time zone | 8 bytes |
+| `updated_at` | timestamp without time zone | 8 bytes |
+| `action` | integer | 4 bytes |
+| `author_id` | integer | 4 bytes |
+
+After adding padding to align the columns this would translate to columns being
+divided into fixed size chunks as follows:
+
+| Chunk Size | Columns |
+|:-----------|:----------------------|
+| 8 bytes | `id` |
+| variable | `target_type` |
+| 8 bytes | `target_id` |
+| variable | `title` |
+| variable | `data` |
+| 8 bytes | `project_id` |
+| 8 bytes | `created_at` |
+| 8 bytes | `updated_at` |
+| 8 bytes | `action`, `author_id` |
+
+This means that excluding the variable sized data and tuple header, we need at
+least 8 * 6 = 48 bytes per row.
+
+We can optimise this by using the following column order instead:
+
+| Column | Type | Size |
+|:--------------|:----------------------------|:---------|
+| `created_at` | timestamp without time zone | 8 bytes |
+| `updated_at` | timestamp without time zone | 8 bytes |
+| `id` | integer | 4 bytes |
+| `target_id` | integer | 4 bytes |
+| `project_id` | integer | 4 bytes |
+| `action` | integer | 4 bytes |
+| `author_id` | integer | 4 bytes |
+| `target_type` | character varying | variable |
+| `title` | character varying | variable |
+| `data` | text | variable |
+
+This would produce the following chunks:
+
+| Chunk Size | Columns |
+|:-----------|:-----------------------|
+| 8 bytes | `created_at` |
+| 8 bytes | `updated_at` |
+| 8 bytes | `id`, `target_id` |
+| 8 bytes | `project_id`, `action` |
+| 8 bytes | `author_id` |
+| variable | `target_type` |
+| variable | `title` |
+| variable | `data` |
+
+Here we only need 40 bytes per row excluding the variable sized data and 24-byte
+tuple header. 8 bytes being saved may not sound like much, but for tables as
+large as the `events` table it does begin to matter. For example, when storing
+80 000 000 rows this translates to a space saving of at least 610 MB, all by
+just changing the order of a few columns.
diff --git a/doc/development/database/pagination_guidelines.md b/doc/development/database/pagination_guidelines.md
index 1641708ce01..fe2e3b46939 100644
--- a/doc/development/database/pagination_guidelines.md
+++ b/doc/development/database/pagination_guidelines.md
@@ -192,7 +192,7 @@ The query execution plan shows that this query is efficient, the database only r
(6 rows)
```
-See the [Understanding EXPLAIN plans](../understanding_explain_plans.md) to find more information about reading execution plans.
+See the [Understanding EXPLAIN plans](understanding_explain_plans.md) to find more information about reading execution plans.
Let's visit the 50_000th page:
diff --git a/doc/development/database/pagination_performance_guidelines.md b/doc/development/database/pagination_performance_guidelines.md
index b5040e499e4..0fef246f133 100644
--- a/doc/development/database/pagination_performance_guidelines.md
+++ b/doc/development/database/pagination_performance_guidelines.md
@@ -12,11 +12,11 @@ The following document gives a few ideas for improving the pagination (sorting)
When ordering the columns it's advised to order by distinct columns only. Consider the following example:
-|`id`|`created_at`|
-|-|-|
-|1|2021-01-04 14:13:43|
-|2|2021-01-05 19:03:12|
-|3|2021-01-05 19:03:12|
+| `id` | `created_at` |
+|------|-----------------------|
+| `1` | `2021-01-04 14:13:43` |
+| `2` | `2021-01-05 19:03:12` |
+| `3` | `2021-01-05 19:03:12` |
If we order by `created_at`, the result would likely depend on how the records are located on the disk.
diff --git a/doc/development/database/polymorphic_associations.md b/doc/development/database/polymorphic_associations.md
new file mode 100644
index 00000000000..ac4dc7720a5
--- /dev/null
+++ b/doc/development/database/polymorphic_associations.md
@@ -0,0 +1,152 @@
+---
+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
+---
+
+# Polymorphic Associations
+
+**Summary:** always use separate tables instead of polymorphic associations.
+
+Rails makes it possible to define so called "polymorphic associations". This
+usually works by adding two columns to a table: a target type column, and a
+target ID. For example, at the time of writing we have such a setup for
+`members` with the following columns:
+
+- `source_type`: a string defining the model to use, can be either `Project` or
+ `Namespace`.
+- `source_id`: the ID of the row to retrieve based on `source_type`. For
+ example, when `source_type` is `Project` then `source_id` contains a
+ project ID.
+
+While such a setup may appear to be useful, it comes with many drawbacks; enough
+that you should avoid this at all costs.
+
+## Space Wasted
+
+Because this setup relies on string values to determine the model to use, it
+wastes a lot of space. For example, for `Project` and `Namespace` the
+maximum size is 9 bytes, plus 1 extra byte for every string when using
+PostgreSQL. While this may only be 10 bytes per row, given enough tables and
+rows using such a setup we can end up wasting quite a bit of disk space and
+memory (for any indexes).
+
+## Indexes
+
+Because our associations are broken up into two columns this may result in
+requiring composite indexes for queries to be performed efficiently. While
+composite indexes are not wrong at all, they can be tricky to set up as the
+ordering of columns in these indexes is important to ensure optimal performance.
+
+## Consistency
+
+One really big problem with polymorphic associations is being unable to enforce
+data consistency on the database level using foreign keys. For consistency to be
+enforced on the database level one would have to write their own foreign key
+logic to support polymorphic associations.
+
+Enforcing consistency on the database level is absolutely crucial for
+maintaining a healthy environment, and thus is another reason to avoid
+polymorphic associations.
+
+## Query Overhead
+
+When using polymorphic associations you always need to filter using both
+columns. For example, you may end up writing a query like this:
+
+```sql
+SELECT *
+FROM members
+WHERE source_type = 'Project'
+AND source_id = 13083;
+```
+
+Here PostgreSQL can perform the query quite efficiently if both columns are
+indexed. As the query gets more complex, it may not be able to use these
+indexes effectively.
+
+## Mixed Responsibilities
+
+Similar to functions and classes, a table should have a single responsibility:
+storing data with a certain set of pre-defined columns. When using polymorphic
+associations, you are storing different types of data (possibly with
+different columns set) in the same table.
+
+## The Solution
+
+Fortunately, there is a solution to these problems: use a
+separate table for every type you would otherwise store in the same table. Using
+a separate table allows you to use everything a database may provide to ensure
+consistency and query data efficiently, without any additional application logic
+being necessary.
+
+Let's say you have a `members` table storing both approved and pending members,
+for both projects and groups, and the pending state is determined by the column
+`requested_at` being set or not. Schema wise such a setup can lead to various
+columns only being set for certain rows, wasting space. It's also possible that
+certain indexes are only set for certain rows, again wasting space. Finally,
+querying such a table requires less than ideal queries. For example:
+
+```sql
+SELECT *
+FROM members
+WHERE requested_at IS NULL
+AND source_type = 'GroupMember'
+AND source_id = 4
+```
+
+Instead such a table should be broken up into separate tables. For example, you
+may end up with 4 tables in this case:
+
+- project_members
+- group_members
+- pending_project_members
+- pending_group_members
+
+This makes querying data trivial. For example, to get the members of a group
+you'd run:
+
+```sql
+SELECT *
+FROM group_members
+WHERE group_id = 4
+```
+
+To get all the pending members of a group in turn you'd run:
+
+```sql
+SELECT *
+FROM pending_group_members
+WHERE group_id = 4
+```
+
+If you want to get both you can use a `UNION`, though you need to be explicit
+about what columns you want to `SELECT` as otherwise the result set uses the
+columns of the first query. For example:
+
+```sql
+SELECT id, 'Group' AS target_type, group_id AS target_id
+FROM group_members
+
+UNION ALL
+
+SELECT id, 'Project' AS target_type, project_id AS target_id
+FROM project_members
+```
+
+The above example is perhaps a bit silly, but it shows that there's nothing
+stopping you from merging the data together and presenting it on the same page.
+Selecting columns explicitly can also speed up queries as the database has to do
+less work to get the data (compared to selecting all columns, even ones you're
+not using).
+
+Our schema also becomes easier. No longer do we need to both store and index the
+`source_type` column, we can define foreign keys easily, and we don't need to
+filter rows using the `IS NULL` condition.
+
+To summarize: using separate tables allows us to use foreign keys effectively,
+create indexes only where necessary, conserve space, query data more
+efficiently, and scale these tables more easily (for example, by storing them on
+separate disks). A nice side effect of this is that code can also become easier,
+as a single model isn't responsible for handling different kinds of
+data.
diff --git a/doc/development/database/post_deployment_migrations.md b/doc/development/database/post_deployment_migrations.md
index a49c77ca047..8166fcc8905 100644
--- a/doc/development/database/post_deployment_migrations.md
+++ b/doc/development/database/post_deployment_migrations.md
@@ -25,6 +25,10 @@ This however skips post deployment migrations:
SKIP_POST_DEPLOYMENT_MIGRATIONS=true bundle exec rake db:migrate
```
+For GitLab.com, these migrations are executed on a daily basis at the discretion of
+release managers through the
+[post-deploy migration pipeline](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md).
+
## Deployment Integration
Say you're using Chef for deploying new versions of GitLab and you'd like to run
diff --git a/doc/development/database/query_count_limits.md b/doc/development/database/query_count_limits.md
new file mode 100644
index 00000000000..a888bbfc6e7
--- /dev/null
+++ b/doc/development/database/query_count_limits.md
@@ -0,0 +1,70 @@
+---
+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
+---
+
+# Query Count Limits
+
+Each controller or API endpoint is allowed to execute up to 100 SQL queries and
+in test environments we raise an error when this threshold is exceeded.
+
+## Solving Failing Tests
+
+When a test fails because it executes more than 100 SQL queries there are two
+solutions to this problem:
+
+- Reduce the number of SQL queries that are executed.
+- Disable query limiting for the controller or API endpoint.
+
+You should only resort to disabling query limits when an existing controller or endpoint
+is to blame as in this case reducing the number of SQL queries can take a lot of
+effort. Newly added controllers and endpoints are not allowed to execute more
+than 100 SQL queries and no exceptions are made for this rule. _If_ a large
+number of SQL queries is necessary to perform certain work it's best to have
+this work performed by Sidekiq instead of doing this directly in a web request.
+
+## Disable query limiting
+
+In the event that you _have_ to disable query limits for a controller, you must first
+create an issue. This issue should (preferably in the title) mention the
+controller or endpoint and include the appropriate labels (`database`,
+`performance`, and at least a team specific label such as `Discussion`).
+
+After the issue has been created, you can disable query limits on the code in question. For
+Rails controllers it's best to create a `before_action` hook that runs as early
+as possible. The called method in turn should call
+`Gitlab::QueryLimiting.disable!('issue URL here')`. For example:
+
+```ruby
+class MyController < ApplicationController
+ before_action :disable_query_limiting, only: [:show]
+
+ def index
+ # ...
+ end
+
+ def show
+ # ...
+ end
+
+ def disable_query_limiting
+ Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/...')
+ end
+end
+```
+
+By using a `before_action` you don't have to modify the controller method in
+question, reducing the likelihood of merge conflicts.
+
+For Grape API endpoints there unfortunately is not a reliable way of running a
+hook before a specific endpoint. This means that you have to add the allowlist
+call directly into the endpoint like so:
+
+```ruby
+get '/projects/:id/foo' do
+ Gitlab::QueryLimiting.disable!('...')
+
+ # ...
+end
+```
diff --git a/doc/development/database/query_performance.md b/doc/development/database/query_performance.md
new file mode 100644
index 00000000000..41dbd08d726
--- /dev/null
+++ b/doc/development/database/query_performance.md
@@ -0,0 +1,74 @@
+---
+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
+---
+
+# Query performance guidelines
+
+This document describes various guidelines to follow when optimizing SQL queries.
+
+When you are optimizing your SQL queries, there are two dimensions to pay attention to:
+
+1. The query execution time. This is paramount as it reflects how the user experiences GitLab.
+1. The query plan. Optimizing the query plan is important in allowing queries to independently scale over time. Realizing that an index keeps a query performing well as the table grows before the query degrades is an example of why we analyze these plans.
+
+## Timing guidelines for queries
+
+| Query Type | Maximum Query Time | Notes |
+|----|----|---|
+| General queries | `100ms` | This is not a hard limit, but if a query is getting above it, it is important to spend time understanding why it can or cannot be optimized. |
+| Queries in a migration | `100ms` | This is different than the total [migration time](../migration_style_guide.md#how-long-a-migration-should-take). |
+| Concurrent operations in a migration | `5min` | Concurrent operations do not block the database, but they block the GitLab update. This includes operations such as `add_concurrent_index` and `add_concurrent_foreign_key`. |
+| Background migrations | `1s` | |
+| Service Ping | `1s` | See the [Service Ping docs](../service_ping/implement.md) for more details. |
+
+- When analyzing your query's performance, pay attention to if the time you are seeing is on a [cold or warm cache](#cold-and-warm-cache). These guidelines apply for both cache types.
+- When working with batched queries, change the range and batch size to see how it effects the query timing and caching.
+- If an existing query is not performing well, make an effort to improve it. If it is too complex or would stall development, create a follow-up so it can be addressed in a timely manner. You can always ask the database reviewer or maintainer for help and guidance.
+
+## Cold and warm cache
+
+When evaluating query performance it is important to understand the difference between
+cold and warm cached queries.
+
+The first time a query is made, it is made on a "cold cache". Meaning it needs
+to read from disk. If you run the query again, the data can be read from the
+cache, or what PostgreSQL calls shared buffers. This is the "warm cache" query.
+
+When analyzing an [`EXPLAIN` plan](understanding_explain_plans.md), you can see
+the difference not only in the timing, but by looking at the output for `Buffers`
+by running your explain with `EXPLAIN(analyze, buffers)`. [Database Lab](understanding_explain_plans.md#database-lab-engine)
+automatically includes these options.
+
+If you are making a warm cache query, you see only the `shared hits`.
+
+For example in #database-lab:
+
+```plaintext
+Shared buffers:
+ - hits: 36467 (~284.90 MiB) from the buffer pool
+ - reads: 0 from the OS file cache, including disk I/O
+```
+
+Or in the explain plan from `psql`:
+
+```sql
+Buffers: shared hit=7323
+```
+
+If the cache is cold, you also see `reads`.
+
+In #database-lab:
+
+```plaintext
+Shared buffers:
+ - hits: 17204 (~134.40 MiB) from the buffer pool
+ - reads: 15229 (~119.00 MiB) from the OS file cache, including disk I/O
+```
+
+In `psql`:
+
+```sql
+Buffers: shared hit=7202 read=121
+```
diff --git a/doc/development/database/query_recorder.md b/doc/development/database/query_recorder.md
new file mode 100644
index 00000000000..da5c6c8e6cb
--- /dev/null
+++ b/doc/development/database/query_recorder.md
@@ -0,0 +1,145 @@
+---
+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
+---
+
+# QueryRecorder
+
+QueryRecorder is a tool for detecting the [N+1 queries problem](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) from tests.
+
+> Implemented in [spec/support/query_recorder.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/query_recorder.rb) via [9c623e3e](https://gitlab.com/gitlab-org/gitlab-foss/commit/9c623e3e5d7434f2e30f7c389d13e5af4ede770a)
+
+As a rule, merge requests [should not increase query counts](../merge_request_performance_guidelines.md#query-counts). If you find yourself adding something like `.includes(:author, :assignee)` to avoid having `N+1` queries, consider using QueryRecorder to enforce this with a test. Without this, a new feature which causes an additional model to be accessed can silently reintroduce the problem.
+
+## How it works
+
+This style of test works by counting the number of SQL queries executed by ActiveRecord. First a control count is taken, then you add new records to the database and rerun the count. If the number of queries has significantly increased then an `N+1` queries problem exists.
+
+```ruby
+it "avoids N+1 database queries" do
+ control = ActiveRecord::QueryRecorder.new { visit_some_page }
+ create_list(:issue, 5)
+ expect { visit_some_page }.not_to exceed_query_limit(control)
+end
+```
+
+You can if you wish, have both the expectation and the control as
+`QueryRecorder` instances:
+
+```ruby
+it "avoids N+1 database queries" do
+ control = ActiveRecord::QueryRecorder.new { visit_some_page }
+ create_list(:issue, 5)
+ action = ActiveRecord::QueryRecorder.new { visit_some_page }
+
+ expect(action).not_to exceed_query_limit(control)
+end
+```
+
+As an example you might create 5 issues in between counts, which would cause the query count to increase by 5 if an N+1 problem exists.
+
+In some cases the query count might change slightly between runs for unrelated reasons. In this case you might need to test `exceed_query_limit(control_count + acceptable_change)`, but this should be avoided if possible.
+
+If this test fails, and the control was passed as a `QueryRecorder`, then the
+failure message indicates where the extra queries are by matching queries on
+the longest common prefix, grouping similar queries together.
+
+## Cached queries
+
+By default, QueryRecorder ignores [cached queries](../merge_request_performance_guidelines.md#cached-queries) in the count. However, it may be better to count
+all queries to avoid introducing an N+1 query that may be masked by the statement cache.
+To do this, this requires the `:use_sql_query_cache` flag to be set.
+You should pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
+
+```ruby
+it "avoids N+1 database queries", :use_sql_query_cache do
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }
+ create_list(:issue, 5)
+ expect { visit_some_page }.not_to exceed_all_query_limit(control)
+end
+```
+
+## Use request specs instead of controller specs
+
+Use a [request spec](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/spec/requests) when writing a N+1 test on the controller level.
+
+Controller specs should not be used to write N+1 tests as the controller is only initialized once per example.
+This could lead to false successes where subsequent "requests" could have queries reduced (for example, because of memoization).
+
+## Finding the source of the query
+
+There are multiple ways to find the source of queries.
+
+- Inspect the `QueryRecorder` `data` attribute. It stores queries by `file_name:line_number:method_name`.
+ Each entry is a `hash` with the following fields:
+
+ - `count`: the number of times a query from this `file_name:line_number:method_name` was called
+ - `occurrences`: the actual `SQL` of each call
+ - `backtrace`: the stack trace of each call (if either of the two following options were enabled)
+
+ `QueryRecorder#find_query` allows filtering queries by their `file_name:line_number:method_name` and
+ `count` attributes. For example:
+
+ ```ruby
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }
+ control.find_query(/.*note.rb.*/, 0, first_only: true)
+ ```
+
+ `QueryRecorder#occurrences_by_line_method` returns a sorted array based on `data`, sorted by `count`.
+
+- View the call backtrace for the specific `QueryRecorder` instance you want
+ by using `ActiveRecord::QueryRecorder.new(query_recorder_debug: true)`. The output
+ is stored in file `test.log`.
+
+- Enable the call backtrace for all tests using the `QUERY_RECORDER_DEBUG` environment variable.
+
+ To enable this, run the specs with the `QUERY_RECORDER_DEBUG` environment variable set. For example:
+
+ ```shell
+ QUERY_RECORDER_DEBUG=1 bundle exec rspec spec/requests/api/projects_spec.rb
+ ```
+
+ This logs calls to QueryRecorder into the `test.log` file. For example:
+
+ ```sql
+ QueryRecorder SQL: SELECT COUNT(*) FROM "issues" WHERE "issues"."deleted_at" IS NULL AND "issues"."project_id" = $1 AND ("issues"."state" IN ('opened')) AND "issues"."confidential" = $2
+ --> /home/user/gitlab/gdk/gitlab/spec/support/query_recorder.rb:19:in `callback'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:127:in `finish'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `block in finish'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `each'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `finish'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/instrumenter.rb:36:in `finish'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/instrumenter.rb:25:in `instrument'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql_adapter.rb:601:in `exec_cache'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql_adapter.rb:585:in `execute_and_clear'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in `exec_query'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:356:in `select'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `block in select_all'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:83:in `cache_sql'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `select_all'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:270:in `execute_simple_calculation'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:227:in `perform_calculation'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:133:in `calculate'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:48:in `count'
+ --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:20:in `uncached_count'
+ --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:12:in `block in count'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:299:in `block in fetch'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:585:in `block in save_block_result_to_cache'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:547:in `block in instrument'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications.rb:166:in `instrument'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:547:in `instrument'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:584:in `save_block_result_to_cache'
+ --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:299:in `fetch'
+ --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:12:in `count'
+ --> /home/user/gitlab/gdk/gitlab/app/models/project.rb:1296:in `open_issues_count'
+ ```
+
+## See also
+
+- [Bullet](../profiling.md#bullet) For finding `N+1` query problems
+- [Performance guidelines](../performance.md)
+- [Merge request performance guidelines - Query counts](../merge_request_performance_guidelines.md#query-counts)
+- [Merge request performance guidelines - Cached queries](../merge_request_performance_guidelines.md#cached-queries)
diff --git a/doc/development/database/rename_database_tables.md b/doc/development/database/rename_database_tables.md
index cbcbd507204..d6827cb9e03 100644
--- a/doc/development/database/rename_database_tables.md
+++ b/doc/development/database/rename_database_tables.md
@@ -81,10 +81,10 @@ Execute a standard migration (not a post-migration):
when naming indexes, so there is a possibility that not all indexes are properly renamed. After running
the migration locally, check if there are inconsistently named indexes (`db/structure.sql`). Those can be
renamed manually in a separate migration, which can be also part of the release M.N+1.
-- Foreign key columns might still contain the old table name. For smaller tables, follow our [standard column
-rename process](avoiding_downtime_in_migrations.md#renaming-columns)
+- Foreign key columns might still contain the old table name. For smaller tables, follow our
+ [standard column rename process](avoiding_downtime_in_migrations.md#renaming-columns)
- Avoid renaming database tables which are using with triggers.
-- Table modifications (add or remove columns) are not allowed during the rename process, please make sure that all changes to the table happen before the rename migration is started (or in the next release).
+- Table modifications (add or remove columns) are not allowed during the rename process. Make sure that all changes to the table happen before the rename migration is started (or in the next release).
- As the index names might change, verify that the model does not use bulk insert
(for example, `insert_all` and `upsert_all`) with the `unique_by: index_name` option.
Renaming an index while using these methods may break functionality.
diff --git a/doc/development/database/serializing_data.md b/doc/development/database/serializing_data.md
new file mode 100644
index 00000000000..97e6f665484
--- /dev/null
+++ b/doc/development/database/serializing_data.md
@@ -0,0 +1,90 @@
+---
+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
+---
+
+# Serializing Data
+
+**Summary:** don't store serialized data in the database, use separate columns
+and/or tables instead. This includes storing of comma separated values as a
+string.
+
+Rails makes it possible to store serialized data in JSON, YAML or other formats.
+Such a field can be defined as follows:
+
+```ruby
+class Issue < ActiveRecord::Model
+ serialize :custom_fields
+end
+```
+
+While it may be tempting to store serialized data in the database there are many
+problems with this. This document outlines these problems and provide an
+alternative.
+
+## Serialized Data Is Less Powerful
+
+When using a relational database you have the ability to query individual
+fields, change the schema, index data, and so forth. When you use serialized data
+all of that becomes either very difficult or downright impossible. While
+PostgreSQL does offer the ability to query JSON fields it is mostly meant for
+very specialized use cases, and not for more general use. If you use YAML in
+turn there's no way to query the data at all.
+
+## Waste Of Space
+
+Storing serialized data such as JSON or YAML ends up wasting a lot of space.
+This is because these formats often include additional characters (for example, double
+quotes or newlines) besides the data that you are storing.
+
+## Difficult To Manage
+
+There comes a time where you must add a new field to the serialized
+data, or change an existing one. Using serialized data this becomes difficult
+and very time consuming as the only way of doing so is to re-write all the
+stored values. To do so you would have to:
+
+1. Retrieve the data
+1. Parse it into a Ruby structure
+1. Mutate it
+1. Serialize it back to a String
+1. Store it in the database
+
+On the other hand, if one were to use regular columns adding a column would be:
+
+```sql
+ALTER TABLE table_name ADD COLUMN column_name type;
+```
+
+Such a query would take very little to no time and would immediately apply to
+all rows, without having to re-write large JSON or YAML structures.
+
+Finally, there comes a time when the JSON or YAML structure is no longer
+sufficient and you must migrate away from it. When storing only a few rows
+this may not be a problem, but when storing millions of rows such a migration
+can take hours or even days to complete.
+
+## Relational Databases Are Not Document Stores
+
+When storing data as JSON or YAML you're essentially using your database as if
+it were a document store (for example, MongoDB), except you're not using any of the
+powerful features provided by a typical RDBMS _nor_ are you using any of the
+features provided by a typical document store (for example, the ability to index fields
+of documents with variable fields). In other words, it's a waste.
+
+## Consistent Fields
+
+One argument sometimes made in favour of serialized data is having to store
+widely varying fields and values. Sometimes this is truly the case, and then
+perhaps it might make sense to use serialized data. However, in 99% of the cases
+the fields and types stored tend to be the same for every row. Even if there is
+a slight difference you can still use separate columns and just not set the ones
+you don't need.
+
+## The Solution
+
+The solution is to use separate columns and/or separate tables.
+This allows you to use all the features provided by your database, it
+makes it easier to manage and migrate the data, you conserve space, you can
+index the data efficiently and so forth.
diff --git a/doc/development/database/sha1_as_binary.md b/doc/development/database/sha1_as_binary.md
new file mode 100644
index 00000000000..dab9b0fe72e
--- /dev/null
+++ b/doc/development/database/sha1_as_binary.md
@@ -0,0 +1,42 @@
+---
+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
+---
+
+# Storing SHA1 Hashes As Binary
+
+Storing SHA1 hashes as strings is not very space efficient. A SHA1 as a string
+requires at least 40 bytes, an additional byte to store the encoding, and
+perhaps more space depending on the internals of PostgreSQL.
+
+On the other hand, if one were to store a SHA1 as binary one would only need 20
+bytes for the actual SHA1, and 1 or 4 bytes of additional space (again depending
+on database internals). This means that in the best case scenario we can reduce
+the space usage by 50%.
+
+To make this easier to work with you can include the concern `ShaAttribute` into
+a model and define a SHA attribute using the `sha_attribute` class method. For
+example:
+
+```ruby
+class Commit < ActiveRecord::Base
+ include ShaAttribute
+
+ sha_attribute :sha
+end
+```
+
+This allows you to use the value of the `sha` attribute as if it were a string,
+while storing it as binary. This means that you can do something like this,
+without having to worry about converting data to the right binary format:
+
+```ruby
+commit = Commit.find_by(sha: '88c60307bd1f215095834f09a1a5cb18701ac8ad')
+commit.sha = '971604de4cfa324d91c41650fabc129420c8d1cc'
+commit.save
+```
+
+There is however one requirement: the column used to store the SHA has _must_ be
+a binary type. For Rails this means you need to use the `:binary` type instead
+of `:text` or `:string`.
diff --git a/doc/development/database/single_table_inheritance.md b/doc/development/database/single_table_inheritance.md
new file mode 100644
index 00000000000..c8d082e8a67
--- /dev/null
+++ b/doc/development/database/single_table_inheritance.md
@@ -0,0 +1,63 @@
+---
+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
+---
+
+# Single Table Inheritance
+
+**Summary:** don't use Single Table Inheritance (STI), use separate tables
+instead.
+
+Rails makes it possible to have multiple models stored in the same table and map
+these rows to the correct models using a `type` column. This can be used to for
+example store two different types of SSH keys in the same table.
+
+While tempting to use one should avoid this at all costs for the same reasons as
+outlined in the document ["Polymorphic Associations"](polymorphic_associations.md).
+
+## Solution
+
+The solution is very simple: just use a separate table for every type you'd
+otherwise store in the same table. For example, instead of having a `keys` table
+with `type` set to either `Key` or `DeployKey` you'd have two separate tables:
+`keys` and `deploy_keys`.
+
+## In migrations
+
+Whenever a model is used in a migration, single table inheritance should be disabled.
+Due to the way Rails loads associations (even in migrations), failing to disable STI
+could result in loading unexpected code or associations which may cause unintended
+side effects or failures during upgrades.
+
+```ruby
+class SomeMigration < Gitlab::Database::Migration[2.0]
+ class Services < MigrationRecord
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def up
+ ...
+```
+
+If nothing needs to be added to the model other than disabling STI or `EachBatch`,
+use the helper `define_batchable_model` instead of defining the class.
+This ensures that the migration loads the columns for the migration in isolation,
+and the helper disables STI by default.
+
+```ruby
+class EnqueueSomeBackgroundMigration < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ define_batchable_model('services').select(:id).in_batches do |relation|
+ jobs = relation.pluck(:id).map do |id|
+ ['ExtractServicesUrl', [id]]
+ end
+
+ BackgroundMigrationWorker.bulk_perform_async(jobs)
+ end
+ end
+ ...
+```
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 73e023f8d45..e2e1191018b 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -148,8 +148,9 @@ to update the `title_html` with a title that has more than 1024 characters, the
a database error.
Adding or removing a constraint to an existing attribute requires that any application changes are
-deployed _first_, [otherwise servers still in the old version of the application may try to update the
-attribute with invalid values](../multi_version_compatibility.md#ci-artifact-uploads-were-failing).
+deployed _first_,
+otherwise servers still in the old version of the application
+[may try to update the attribute with invalid values](../multi_version_compatibility.md#ci-artifact-uploads-were-failing).
For these reasons, `add_text_limit` should run in a post-deployment migration.
Still in our example, for the 13.0 milestone (current), consider that the following validation
@@ -188,7 +189,7 @@ migration or a background data migration:
- If the data volume is less than `1,000` records, then the data migration can be executed within the post-migration.
- If the data volume is higher than `1,000` records, it's advised to create a background migration.
-When unsure about which option to use, please contact the Database team for advice.
+When unsure about which option to use, contact the Database team for advice.
Back to our example, the issues table is considerably large and frequently accessed, so we are going
to add a background migration for the 13.0 milestone (current),
diff --git a/doc/development/database/swapping_tables.md b/doc/development/database/swapping_tables.md
new file mode 100644
index 00000000000..efb481ccf35
--- /dev/null
+++ b/doc/development/database/swapping_tables.md
@@ -0,0 +1,51 @@
+---
+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
+---
+
+# Swapping Tables
+
+Sometimes you need to replace one table with another. For example, when
+migrating data in a very large table it's often better to create a copy of the
+table and insert & migrate the data into this new table in the background.
+
+Let's say you want to swap the table `events` with `events_for_migration`. In
+this case you need to follow 3 steps:
+
+1. Rename `events` to `events_temporary`
+1. Rename `events_for_migration` to `events`
+1. Rename `events_temporary` to `events_for_migration`
+
+Rails allows you to do this using the `rename_table` method:
+
+```ruby
+rename_table :events, :events_temporary
+rename_table :events_for_migration, :events
+rename_table :events_temporary, :events_for_migration
+```
+
+This does not require any downtime as long as the 3 `rename_table` calls are
+executed in the _same_ database transaction. Rails by default uses database
+transactions for migrations, but if it doesn't you need to start one
+manually:
+
+```ruby
+Event.transaction do
+ rename_table :events, :events_temporary
+ rename_table :events_for_migration, :events
+ rename_table :events_temporary, :events_for_migration
+end
+```
+
+Once swapped you _have to_ reset the primary key of the new table. For
+PostgreSQL you can use the `reset_pk_sequence!` method like so:
+
+```ruby
+reset_pk_sequence!('events')
+```
+
+Failure to reset the primary keys results in newly created rows starting
+with an ID value of 1. Depending on the existing data this can then lead to
+duplicate key constraints from popping up, preventing users from creating new
+data.
diff --git a/doc/development/database/transaction_guidelines.md b/doc/development/database/transaction_guidelines.md
index 255de19a420..1583bbc02c2 100644
--- a/doc/development/database/transaction_guidelines.md
+++ b/doc/development/database/transaction_guidelines.md
@@ -12,7 +12,7 @@ For further reference, check PostgreSQL documentation about [transactions](https
## Database decomposition and sharding
-The [sharding group](https://about.gitlab.com/handbook/engineering/development/enablement/sharding/) plans
+The [Pods Group](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/pods/) plans
to split the main GitLab database and move some of the database tables to other database servers.
We start decomposing the `ci_*`-related database tables first. To maintain the current application
diff --git a/doc/development/database/understanding_explain_plans.md b/doc/development/database/understanding_explain_plans.md
new file mode 100644
index 00000000000..446a84d5232
--- /dev/null
+++ b/doc/development/database/understanding_explain_plans.md
@@ -0,0 +1,829 @@
+---
+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
+---
+
+# Understanding EXPLAIN plans
+
+PostgreSQL allows you to obtain query plans using the `EXPLAIN` command. This
+command can be invaluable when trying to determine how a query performs.
+You can use this command directly in your SQL query, as long as the query starts
+with it:
+
+```sql
+EXPLAIN
+SELECT COUNT(*)
+FROM projects
+WHERE visibility_level IN (0, 20);
+```
+
+When running this on GitLab.com, we are presented with the following output:
+
+```sql
+Aggregate (cost=922411.76..922411.77 rows=1 width=8)
+ -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+```
+
+When using _just_ `EXPLAIN`, PostgreSQL does not actually execute our query,
+instead it produces an _estimated_ execution plan based on the available
+statistics. This means the actual plan can differ quite a bit. Fortunately,
+PostgreSQL provides us with the option to execute the query as well. To do so,
+we need to use `EXPLAIN ANALYZE` instead of just `EXPLAIN`:
+
+```sql
+EXPLAIN ANALYZE
+SELECT COUNT(*)
+FROM projects
+WHERE visibility_level IN (0, 20);
+```
+
+This produces:
+
+```sql
+Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
+ -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 65677
+Planning time: 2.861 ms
+Execution time: 3428.596 ms
+```
+
+As we can see this plan is quite different, and includes a lot more data. Let's
+discuss this step by step.
+
+Because `EXPLAIN ANALYZE` executes the query, care should be taken when using a
+query that writes data or might time out. If the query modifies data,
+consider wrapping it in a transaction that rolls back automatically like so:
+
+```sql
+BEGIN;
+EXPLAIN ANALYZE
+DELETE FROM users WHERE id = 1;
+ROLLBACK;
+```
+
+The `EXPLAIN` command also takes additional options, such as `BUFFERS`:
+
+```sql
+EXPLAIN (ANALYZE, BUFFERS)
+SELECT COUNT(*)
+FROM projects
+WHERE visibility_level IN (0, 20);
+```
+
+This then produces:
+
+```sql
+Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
+ Buffers: shared hit=208846
+ -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 65677
+ Buffers: shared hit=208846
+Planning time: 2.861 ms
+Execution time: 3428.596 ms
+```
+
+For more information, refer to the official
+[`EXPLAIN` documentation](https://www.postgresql.org/docs/current/sql-explain.html)
+and [using `EXPLAIN` guide](https://www.postgresql.org/docs/current/using-explain.html).
+
+## Nodes
+
+Every query plan consists of nodes. Nodes can be nested, and are executed from
+the inside out. This means that the innermost node is executed before an outer
+node. This can be best thought of as nested function calls, returning their
+results as they unwind. For example, a plan starting with an `Aggregate`
+followed by a `Nested Loop`, followed by an `Index Only scan` can be thought of
+as the following Ruby code:
+
+```ruby
+aggregate(
+ nested_loop(
+ index_only_scan()
+ index_only_scan()
+ )
+)
+```
+
+Nodes are indicated using a `->` followed by the type of node taken. For
+example:
+
+```sql
+Aggregate (cost=922411.76..922411.77 rows=1 width=8)
+ -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+```
+
+Here the first node executed is `Seq scan on projects`. The `Filter:` is an
+additional filter applied to the results of the node. A filter is very similar
+to Ruby's `Array#select`: it takes the input rows, applies the filter, and
+produces a new list of rows. After the node is done, we perform the `Aggregate`
+above it.
+
+Nested nodes look like this:
+
+```sql
+Aggregate (cost=176.97..176.98 rows=1 width=8) (actual time=0.252..0.252 rows=1 loops=1)
+ Buffers: shared hit=155
+ -> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1)
+ Buffers: shared hit=155
+ -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1)
+ Index Cond: (id < 100)
+ Heap Fetches: 0
+ -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36)
+ Index Cond: (id = users_1.id)
+ Heap Fetches: 0
+Planning time: 2.585 ms
+Execution time: 0.310 ms
+```
+
+Here we first perform two separate "Index Only" scans, followed by performing a
+"Nested Loop" on the result of these two scans.
+
+## Node statistics
+
+Each node in a plan has a set of associated statistics, such as the cost, the
+number of rows produced, the number of loops performed, and more. For example:
+
+```sql
+Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
+```
+
+Here we can see that our cost ranges from `0.00..908044.47` (we cover this in
+a moment), and we estimate (since we're using `EXPLAIN` and not `EXPLAIN
+ANALYZE`) a total of 5,746,914 rows to be produced by this node. The `width`
+statistics describes the estimated width of each row, in bytes.
+
+The `costs` field specifies how expensive a node was. The cost is measured in
+arbitrary units determined by the query planner's cost parameters. What
+influences the costs depends on a variety of settings, such as `seq_page_cost`,
+`cpu_tuple_cost`, and various others.
+The format of the costs field is as follows:
+
+```sql
+STARTUP COST..TOTAL COST
+```
+
+The startup cost states how expensive it was to start the node, with the total
+cost describing how expensive the entire node was. In general: the greater the
+values, the more expensive the node.
+
+When using `EXPLAIN ANALYZE`, these statistics also include the actual time
+(in milliseconds) spent, and other runtime statistics (for example, the actual number of
+produced rows):
+
+```sql
+Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
+```
+
+Here we can see we estimated 5,746,969 rows to be returned, but in reality we
+returned 5,746,940 rows. We can also see that _just_ this sequential scan took
+2.98 seconds to run.
+
+Using `EXPLAIN (ANALYZE, BUFFERS)` also gives us information about the
+number of rows removed by a filter, the number of buffers used, and more. For
+example:
+
+```sql
+Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 65677
+ Buffers: shared hit=208846
+```
+
+Here we can see that our filter has to remove 65,677 rows, and that we use
+208,846 buffers. Each buffer in PostgreSQL is 8 KB (8192 bytes), meaning our
+above node uses *1.6 GB of buffers*. That's a lot!
+
+Keep in mind that some statistics are per-loop averages, while others are total values:
+
+| Field name | Value type |
+| --- | --- |
+| Actual Total Time | per-loop average |
+| Actual Rows | per-loop average |
+| Buffers Shared Hit | total value |
+| Buffers Shared Read | total value |
+| Buffers Shared Dirtied | total value |
+| Buffers Shared Written | total value |
+| I/O Read Time | total value |
+| I/O Read Write | total value |
+
+For example:
+
+```sql
+ -> Index Scan using users_pkey on public.users (cost=0.43..3.44 rows=1 width=1318) (actual time=0.025..0.025 rows=1 loops=888)
+ Index Cond: (users.id = issues.author_id)
+ Buffers: shared hit=3543 read=9
+ I/O Timings: read=17.760 write=0.000
+```
+
+Here we can see that this node used 3552 buffers (3543 + 9), returned 888 rows (`888 * 1`), and the actual duration was 22.2 milliseconds (`888 * 0.025`).
+17.76 milliseconds of the total duration was spent in reading from disk, to retrieve data that was not in the cache.
+
+## Node types
+
+There are quite a few different types of nodes, so we only cover some of the
+more common ones here.
+
+A full list of all the available nodes and their descriptions can be found in
+the [PostgreSQL source file `plannodes.h`](https://gitlab.com/postgres/postgres/blob/master/src/include/nodes/plannodes.h).
+pgMustard's [EXPLAIN docs](https://www.pgmustard.com/docs/explain) also offer detailed look into nodes and their fields.
+
+### Seq Scan
+
+A sequential scan over (a chunk of) a database table. This is like using
+`Array#each`, but on a database table. Sequential scans can be quite slow when
+retrieving lots of rows, so it's best to avoid these for large tables.
+
+### Index Only Scan
+
+A scan on an index that did not require fetching anything from the table. In
+certain cases an index only scan may still fetch data from the table, in this
+case the node includes a `Heap Fetches:` statistic.
+
+### Index Scan
+
+A scan on an index that required retrieving some data from the table.
+
+### Bitmap Index Scan and Bitmap Heap scan
+
+Bitmap scans fall between sequential scans and index scans. These are typically
+used when we would read too much data from an index scan, but too little to
+perform a sequential scan. A bitmap scan uses what is known as a
+[bitmap index](https://en.wikipedia.org/wiki/Bitmap_index) to perform its work.
+
+The [source code of PostgreSQL](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)
+states the following on bitmap scans:
+
+> Bitmap Index Scan delivers a bitmap of potential tuple locations; it does not
+> access the heap itself. The bitmap is used by an ancestor Bitmap Heap Scan
+> node, possibly after passing through intermediate Bitmap And and/or Bitmap Or
+> nodes to combine it with the results of other Bitmap Index Scans.
+
+### Limit
+
+Applies a `LIMIT` on the input rows.
+
+### Sort
+
+Sorts the input rows as specified using an `ORDER BY` statement.
+
+### Nested Loop
+
+A nested loop executes its child nodes for every row produced by a node that
+precedes it. For example:
+
+```sql
+-> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1)
+ Buffers: shared hit=155
+ -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1)
+ Index Cond: (id < 100)
+ Heap Fetches: 0
+ -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36)
+ Index Cond: (id = users_1.id)
+ Heap Fetches: 0
+```
+
+Here the first child node (`Index Only Scan using users_pkey on users users_1`)
+produces 36 rows, and is executed once (`rows=36 loops=1`). The next node
+produces 1 row (`rows=1`), but is repeated 36 times (`loops=36`). This is
+because the previous node produced 36 rows.
+
+This means that nested loops can quickly slow the query down if the various
+child nodes keep producing many rows.
+
+## Optimising queries
+
+With that out of the way, let's see how we can optimise a query. Let's use the
+following query as an example:
+
+```sql
+SELECT COUNT(*)
+FROM users
+WHERE twitter != '';
+```
+
+This query counts the number of users that have a Twitter profile set.
+Let's run this using `EXPLAIN (ANALYZE, BUFFERS)`:
+
+```sql
+EXPLAIN (ANALYZE, BUFFERS)
+SELECT COUNT(*)
+FROM users
+WHERE twitter != '';
+```
+
+This produces the following plan:
+
+```sql
+Aggregate (cost=845110.21..845110.22 rows=1 width=8) (actual time=1271.157..1271.158 rows=1 loops=1)
+ Buffers: shared hit=202662
+ -> Seq Scan on users (cost=0.00..844969.99 rows=56087 width=0) (actual time=0.019..1265.883 rows=51833 loops=1)
+ Filter: ((twitter)::text <> ''::text)
+ Rows Removed by Filter: 2487813
+ Buffers: shared hit=202662
+Planning time: 0.390 ms
+Execution time: 1271.180 ms
+```
+
+From this query plan we can see the following:
+
+1. We need to perform a sequential scan on the `users` table.
+1. This sequential scan filters out 2,487,813 rows using a `Filter`.
+1. We use 202,622 buffers, which equals 1.58 GB of memory.
+1. It takes us 1.2 seconds to do all of this.
+
+Considering we are just counting users, that's quite expensive!
+
+Before we start making any changes, let's see if there are any existing indexes
+on the `users` table that we might be able to use. We can obtain this
+information by running `\d users` in a `psql` console, then scrolling down to
+the `Indexes:` section:
+
+```sql
+Indexes:
+ "users_pkey" PRIMARY KEY, btree (id)
+ "index_users_on_confirmation_token" UNIQUE, btree (confirmation_token)
+ "index_users_on_email" UNIQUE, btree (email)
+ "index_users_on_reset_password_token" UNIQUE, btree (reset_password_token)
+ "index_users_on_static_object_token" UNIQUE, btree (static_object_token)
+ "index_users_on_unlock_token" UNIQUE, btree (unlock_token)
+ "index_on_users_name_lower" btree (lower(name::text))
+ "index_users_on_accepted_term_id" btree (accepted_term_id)
+ "index_users_on_admin" btree (admin)
+ "index_users_on_created_at" btree (created_at)
+ "index_users_on_email_trigram" gin (email gin_trgm_ops)
+ "index_users_on_feed_token" btree (feed_token)
+ "index_users_on_group_view" btree (group_view)
+ "index_users_on_incoming_email_token" btree (incoming_email_token)
+ "index_users_on_managing_group_id" btree (managing_group_id)
+ "index_users_on_name" btree (name)
+ "index_users_on_name_trigram" gin (name gin_trgm_ops)
+ "index_users_on_public_email" btree (public_email) WHERE public_email::text <> ''::text
+ "index_users_on_state" btree (state)
+ "index_users_on_state_and_user_type" btree (state, user_type)
+ "index_users_on_unconfirmed_email" btree (unconfirmed_email) WHERE unconfirmed_email IS NOT NULL
+ "index_users_on_user_type" btree (user_type)
+ "index_users_on_username" btree (username)
+ "index_users_on_username_trigram" gin (username gin_trgm_ops)
+ "tmp_idx_on_user_id_where_bio_is_filled" btree (id) WHERE COALESCE(bio, ''::character varying)::text IS DISTINCT FROM ''::text
+```
+
+Here we can see there is no index on the `twitter` column, which means
+PostgreSQL has to perform a sequential scan in this case. Let's try to fix this
+by adding the following index:
+
+```sql
+CREATE INDEX CONCURRENTLY twitter_test ON users (twitter);
+```
+
+If we now re-run our query using `EXPLAIN (ANALYZE, BUFFERS)` we get the
+following plan:
+
+```sql
+Aggregate (cost=61002.82..61002.83 rows=1 width=8) (actual time=297.311..297.312 rows=1 loops=1)
+ Buffers: shared hit=51854 dirtied=19
+ -> Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1)
+ Filter: ((twitter)::text <> ''::text)
+ Rows Removed by Filter: 2487830
+ Heap Fetches: 26037
+ Buffers: shared hit=51854 dirtied=19
+Planning time: 0.191 ms
+Execution time: 297.334 ms
+```
+
+Now it takes just under 300 milliseconds to get our data, instead of 1.2
+seconds. However, we still use 51,854 buffers, which is about 400 MB of memory.
+300 milliseconds is also quite slow for such a simple query. To understand why
+this query is still expensive, let's take a look at the following:
+
+```sql
+Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1)
+ Filter: ((twitter)::text <> ''::text)
+ Rows Removed by Filter: 2487830
+```
+
+We start with an index only scan on our index, but we somehow still apply a
+`Filter` that filters out 2,487,830 rows. Why is that? Well, let's look at how
+we created the index:
+
+```sql
+CREATE INDEX CONCURRENTLY twitter_test ON users (twitter);
+```
+
+We told PostgreSQL to index all possible values of the `twitter` column,
+even empty strings. Our query in turn uses `WHERE twitter != ''`. This means
+that the index does improve things, as we don't need to do a sequential scan,
+but we may still encounter empty strings. This means PostgreSQL _has_ to apply a
+Filter on the index results to get rid of those values.
+
+Fortunately, we can improve this even further using "partial indexes". Partial
+indexes are indexes with a `WHERE` condition that is applied when indexing data.
+For example:
+
+```sql
+CREATE INDEX CONCURRENTLY some_index ON users (email) WHERE id < 100
+```
+
+This index would only index the `email` value of rows that match `WHERE id <
+100`. We can use partial indexes to change our Twitter index to the following:
+
+```sql
+CREATE INDEX CONCURRENTLY twitter_test ON users (twitter) WHERE twitter != '';
+```
+
+After being created, if we run our query again we are given the following plan:
+
+```sql
+Aggregate (cost=1608.26..1608.27 rows=1 width=8) (actual time=19.821..19.821 rows=1 loops=1)
+ Buffers: shared hit=44036
+ -> Index Only Scan using twitter_test on users (cost=0.41..1479.71 rows=51420 width=0) (actual time=0.023..15.514 rows=51833 loops=1)
+ Heap Fetches: 1208
+ Buffers: shared hit=44036
+Planning time: 0.123 ms
+Execution time: 19.848 ms
+```
+
+That's _a lot_ better! Now it only takes 20 milliseconds to get the data, and we
+only use about 344 MB of buffers (instead of the original 1.58 GB). The reason
+this works is that now PostgreSQL no longer needs to apply a `Filter`, as the
+index only contains `twitter` values that are not empty.
+
+Keep in mind that you shouldn't just add partial indexes every time you want to
+optimise a query. Every index has to be updated for every write, and they may
+require quite a bit of space, depending on the amount of indexed data. As a
+result, first check if there are any existing indexes you may be able to reuse.
+If there aren't any, check if you can perhaps slightly change an existing one to
+fit both the existing and new queries. Only add a new index if none of the
+existing indexes can be used in any way.
+
+When comparing execution plans, don't take timing as the only important metric.
+Good timing is the main goal of any optimization, but it can be too volatile to
+be used for comparison (for example, it depends a lot on the state of cache).
+When optimizing a query, we usually need to reduce the amount of data we're
+dealing with. Indexes are the way to work with fewer pages (buffers) to get the
+result, so, during optimization, look at the number of buffers used (read and hit),
+and work on reducing these numbers. Reduced timing is the consequence of reduced
+buffer numbers. [Database Lab Engine](#database-lab-engine) guarantees that the plan is structurally
+identical to production (and overall number of buffers is the same as on production),
+but difference in cache state and I/O speed may lead to different timings.
+
+## Queries that can't be optimised
+
+Now that we have seen how to optimise a query, let's look at another query that
+we might not be able to optimise:
+
+```sql
+EXPLAIN (ANALYZE, BUFFERS)
+SELECT COUNT(*)
+FROM projects
+WHERE visibility_level IN (0, 20);
+```
+
+The output of `EXPLAIN (ANALYZE, BUFFERS)` is as follows:
+
+```sql
+Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
+ Buffers: shared hit=208846
+ -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 65677
+ Buffers: shared hit=208846
+Planning time: 2.861 ms
+Execution time: 3428.596 ms
+```
+
+Looking at the output we see the following Filter:
+
+```sql
+Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+Rows Removed by Filter: 65677
+```
+
+Looking at the number of rows removed by the filter, we may be tempted to add an
+index on `projects.visibility_level` to somehow turn this Sequential scan +
+filter into an index-only scan.
+
+Unfortunately, doing so is unlikely to improve anything. Contrary to what some
+might believe, an index being present _does not guarantee_ that PostgreSQL
+actually uses it. For example, when doing a `SELECT * FROM projects` it is much
+cheaper to just scan the entire table, instead of using an index and then
+fetching data from the table. In such cases PostgreSQL may decide to not use an
+index.
+
+Second, let's think for a moment what our query does: it gets all projects with
+visibility level 0 or 20. In the above plan we can see this produces quite a lot
+of rows (5,745,940), but how much is that relative to the total? Let's find out
+by running the following query:
+
+```sql
+SELECT visibility_level, count(*) AS amount
+FROM projects
+GROUP BY visibility_level
+ORDER BY visibility_level ASC;
+```
+
+For GitLab.com this produces:
+
+```sql
+ visibility_level | amount
+------------------+---------
+ 0 | 5071325
+ 10 | 65678
+ 20 | 674801
+```
+
+Here the total number of projects is 5,811,804, and 5,746,126 of those are of
+level 0 or 20. That's 98% of the entire table!
+
+So no matter what we do, this query retrieves 98% of the entire table. Since
+most time is spent doing exactly that, there isn't really much we can do to
+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 optimise something you do not understand.
+
+### Cardinality and selectivity
+
+Earlier we saw that our query had to retrieve 98% of the rows in the table.
+There are two terms commonly used for databases: cardinality, and selectivity.
+Cardinality refers to the number of unique values in a particular column in a
+table.
+
+Selectivity is the number of unique values produced by an operation (for example, an
+index scan or filter), relative to the total number of rows. The higher the
+selectivity, the more likely PostgreSQL is able to use an index.
+
+In the above example, there are only 3 unique values: 0, 10, and 20. This means
+the cardinality is 3. The selectivity in turn is also very low: 0.0000003% (2 /
+5,811,804), because our `Filter` only filters using two values (`0` and `20`).
+With such a low selectivity value it's not surprising that PostgreSQL decides
+using an index is not worth it, because it would produce almost no unique rows.
+
+## Rewriting queries
+
+So the above query can't really be optimised as-is, or at least not much. But
+what if we slightly change the purpose of it? What if instead of retrieving all
+projects with `visibility_level` 0 or 20, we retrieve those that a user
+interacted with somehow?
+
+Fortunately, GitLab has an answer for this, and it's a table called
+`user_interacted_projects`. This table has the following schema:
+
+```sql
+Table "public.user_interacted_projects"
+ Column | Type | Modifiers
+------------+---------+-----------
+ user_id | integer | not null
+ project_id | integer | not null
+Indexes:
+ "index_user_interacted_projects_on_project_id_and_user_id" UNIQUE, btree (project_id, user_id)
+ "index_user_interacted_projects_on_user_id" btree (user_id)
+Foreign-key constraints:
+ "fk_rails_0894651f08" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+ "fk_rails_722ceba4f7" FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
+```
+
+Let's rewrite our query to `JOIN` this table onto our projects, and get the
+projects for a specific user:
+
+```sql
+EXPLAIN ANALYZE
+SELECT COUNT(*)
+FROM projects
+INNER JOIN user_interacted_projects ON user_interacted_projects.project_id = projects.id
+WHERE projects.visibility_level IN (0, 20)
+AND user_interacted_projects.user_id = 1;
+```
+
+What we do here is the following:
+
+1. Get our projects.
+1. `INNER JOIN` `user_interacted_projects`, meaning we're only left with rows in
+ `projects` that have a corresponding row in `user_interacted_projects`.
+1. Limit this to the projects with `visibility_level` of 0 or 20, and to
+ projects that the user with ID 1 interacted with.
+
+If we run this query we get the following plan:
+
+```sql
+ Aggregate (cost=871.03..871.04 rows=1 width=8) (actual time=9.763..9.763 rows=1 loops=1)
+ -> Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1)
+ -> Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1)
+ Index Cond: (user_id = 1)
+ -> Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
+ Index Cond: (id = user_interacted_projects.project_id)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 0
+ Planning time: 2.614 ms
+ Execution time: 9.809 ms
+```
+
+Here it only took us just under 10 milliseconds to get the data. We can also see
+we're retrieving far fewer projects:
+
+```sql
+Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
+ Index Cond: (id = user_interacted_projects.project_id)
+ Filter: (visibility_level = ANY ('{0,20}'::integer[]))
+ Rows Removed by Filter: 0
+```
+
+Here we see we perform 145 loops (`loops=145`), with every loop producing 1 row
+(`rows=1`). This is much less than before, and our query performs much better!
+
+If we look at the plan we also see our costs are very low:
+
+```sql
+Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
+```
+
+Here our cost is only 3.45, and it takes us 7.25 milliseconds to do so (0.05 * 145).
+The next index scan is a bit more expensive:
+
+```sql
+Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1)
+```
+
+Here the cost is 160.71 (`cost=0.43..160.71`), taking about 2.5 milliseconds
+(based on the output of `actual time=....`).
+
+The most expensive part here is the "Nested Loop" that acts upon the result of
+these two index scans:
+
+```sql
+Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1)
+```
+
+Here we had to perform 870.52 disk page fetches for 203 rows, 9.748
+milliseconds, producing 143 rows in a single loop.
+
+The key takeaway here is that sometimes you have to rewrite (parts of) a query
+to make it better. Sometimes that means having to slightly change your feature
+to accommodate for better performance.
+
+## What makes a bad plan
+
+This is a bit of a difficult question to answer, because the definition of "bad"
+is relative to the problem you are trying to solve. However, some patterns are
+best avoided in most cases, such as:
+
+- Sequential scans on large tables
+- Filters that remove a lot of rows
+- Performing a certain step that requires _a lot_ of
+ buffers (for example, an index scan for GitLab.com that requires more than 512 MB).
+
+As a general guideline, aim for a query that:
+
+1. Takes no more than 10 milliseconds. Our target time spent in SQL per request
+ is around 100 milliseconds, so every query should be as fast as possible.
+1. Does not use an excessive number of buffers, relative to the workload. For
+ example, retrieving ten rows shouldn't require 1 GB of buffers.
+1. Does not spend a long amount of time performing disk IO operations. The
+ setting `track_io_timing` must be enabled for this data to be included in the
+ output of `EXPLAIN ANALYZE`.
+1. Applies a `LIMIT` when retrieving rows without aggregating them, such as
+ `SELECT * FROM users`.
+1. Doesn't use a `Filter` to filter out too many rows, especially if the query
+ does not use a `LIMIT` to limit the number of returned rows. Filters can
+ usually be removed by adding a (partial) index.
+
+These are _guidelines_ and not hard requirements, as different needs may require
+different queries. The only _rule_ is that you _must always measure_ your query
+(preferably using a production-like database) using `EXPLAIN (ANALYZE, BUFFERS)`
+and related tools such as:
+
+- [`explain.depesz.com`](https://explain.depesz.com/).
+- [`explain.dalibo.com/`](https://explain.dalibo.com/).
+
+## Producing query plans
+
+There are a few ways to get the output of a query plan. Of course you
+can directly run the `EXPLAIN` query in the `psql` console, or you can
+follow one of the other options below.
+
+### Database Lab Engine
+
+GitLab team members can use [Database Lab Engine](https://gitlab.com/postgres-ai/database-lab), and the companion
+SQL optimization tool - [Joe Bot](https://gitlab.com/postgres-ai/joe).
+
+Database Lab Engine provides developers with their own clone of the production database, while Joe Bot helps with exploring execution plans.
+
+Joe Bot is available in the [`#database-lab`](https://gitlab.slack.com/archives/CLJMDRD8C) channel on Slack,
+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:
+
+Create the column:
+
+```sql
+exec ALTER TABLE projects ADD COLUMN last_at timestamp without time zone
+```
+
+Create the index:
+
+```sql
+exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL
+```
+
+Analyze the table to update its statistics:
+
+```sql
+exec ANALYZE projects
+```
+
+Get the query plan:
+
+```sql
+explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE
+```
+
+Once done you can rollback your changes:
+
+```sql
+reset
+```
+
+For more information about the available options, run:
+
+```sql
+help
+```
+
+The web interface comes with the following execution plan visualizers included:
+
+- [Depesz](https://explain.depesz.com/)
+- [PEV2](https://github.com/dalibo/pev2)
+- [FlameGraph](https://github.com/mgartner/pg_flame)
+
+#### Tips & Tricks
+
+The database connection is now maintained during your whole session, so you can use `exec set ...` for any session variables (such as `enable_seqscan` or `work_mem`). These settings are applied to all subsequent commands until you reset them. For example you can disable parallel queries with
+
+```sql
+exec SET max_parallel_workers_per_gather = 0
+```
+
+### Rails console
+
+Using the [`activerecord-explain-analyze`](https://github.com/6/activerecord-explain-analyze)
+you can directly generate the query plan from the Rails console:
+
+```ruby
+pry(main)> require 'activerecord-explain-analyze'
+=> true
+pry(main)> Project.where('build_timeout > ?', 3600).explain(analyze: true)
+ Project Load (1.9ms) SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
+ ↳ (pry):12
+=> EXPLAIN for: SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
+Seq Scan on public.projects (cost=0.00..2.17 rows=1 width=742) (actual time=0.040..0.041 rows=0 loops=1)
+ Output: id, name, path, description, created_at, updated_at, creator_id, namespace_id, ...
+ Filter: (projects.build_timeout > 3600)
+ Rows Removed by Filter: 14
+ Buffers: shared hit=2
+Planning time: 0.411 ms
+Execution time: 0.113 ms
+```
+
+### ChatOps
+
+GitLab team members can also use our ChatOps solution, available in Slack
+using the [`/chatops` slash command](../chatops_on_gitlabcom.md).
+
+NOTE:
+While ChatOps is still available, the recommended way to generate execution plans is to use [Database Lab Engine](#database-lab-engine).
+
+You can use ChatOps to get a query plan by running the following:
+
+```sql
+/chatops run explain SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20)
+```
+
+Visualising the plan using <https://explain.depesz.com/> is also supported:
+
+```sql
+/chatops run explain --visual SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20)
+```
+
+Quoting the query is not necessary.
+
+For more information about the available options, run:
+
+```sql
+/chatops run explain --help
+```
+
+## Further reading
+
+A more extensive guide on understanding query plans can be found in
+the [presentation](https://public.dalibo.com/exports/conferences/_archives/_2012/201211_explain/understanding_explain.pdf)
+from [Dalibo.org](https://www.dalibo.com/en/).
+
+Depesz's blog also has a good [section](https://www.depesz.com/tag/unexplainable/) dedicated to query plans.
diff --git a/doc/development/database/verifying_database_capabilities.md b/doc/development/database/verifying_database_capabilities.md
new file mode 100644
index 00000000000..55347edf4ec
--- /dev/null
+++ b/doc/development/database/verifying_database_capabilities.md
@@ -0,0 +1,38 @@
+---
+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
+---
+
+# Verifying Database Capabilities
+
+Sometimes certain bits of code may only work on a certain database
+version. While we try to avoid such code as much as possible sometimes it is
+necessary to add database (version) specific behavior.
+
+To facilitate this we have the following methods that you can use:
+
+- `ApplicationRecord.database.version`: returns the PostgreSQL version number as a string
+ in the format `X.Y.Z`.
+
+This allows you to write code such as:
+
+```ruby
+if ApplicationRecord.database.version.to_f >= 11.7
+ run_really_fast_query
+else
+ run_fast_query
+end
+```
+
+## Read-only database
+
+The database can be used in read-only mode. In this case we have to
+make sure all GET requests don't attempt any write operations to the
+database. If one of those requests wants to write to the database, it needs
+to be wrapped in a `Gitlab::Database.read_only?` or `Gitlab::Database.read_write?`
+guard, to make sure it doesn't for read-only databases.
+
+We have a Rails Middleware that filters any potentially writing
+operations (the `CUD` operations of CRUD) and prevent the user from trying
+to update the database and getting a 500 error (see `Gitlab::Middleware::ReadOnly`).
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index 5d46ade98bb..f18830ee7ca 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -1,177 +1,11 @@
---
-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
+redirect_to: 'database/database_debugging.md'
+remove_date: '2022-11-06'
---
-# Troubleshooting and Debugging Database
+This document was moved to [another location](database/database_debugging.md).
-This section is to help give some copy-pasta you can use as a reference when you
-run into some head-banging database problems.
-
-A first step is to search for your error in Slack, or search for `GitLab <my error>` with Google.
-
-Available `RAILS_ENV`:
-
-- `production` (generally not for your main GDK database, but you may need this for other installations such as Omnibus).
-- `development` (this is your main GDK db).
-- `test` (used for tests like RSpec).
-
-## Delete everything and start over
-
-If you just want to delete everything and start over with an empty DB (approximately 1 minute):
-
-```shell
-bundle exec rake db:reset RAILS_ENV=development
-```
-
-If you want to seed the empty DB with sample data (approximately 4 minutes):
-
-```shell
-bundle exec rake dev:setup
-```
-
-If you just want to delete everything and start over with sample data (approximately 4 minutes). This
-also does `db:reset` and runs DB-specific migrations:
-
-```shell
-bundle exec rake db:setup RAILS_ENV=development
-```
-
-If your test DB is giving you problems, it is safe to delete everything because it doesn't contain important
-data:
-
-```shell
-bundle exec rake db:reset RAILS_ENV=test
-```
-
-## Migration wrangling
-
-- `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR
-- `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down`
-- `bundle exec rake db:migrate:down VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration
-- `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Set up a migration
-- `bundle exec rake db:migrate:redo VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration
-
-## Manually access the database
-
-Access the database via one of these commands (they all get you to the same place)
-
-```shell
-gdk psql -d gitlabhq_development
-bundle exec rails dbconsole -e development
-bundle exec rails db -e development
-```
-
-- `\q`: Quit/exit
-- `\dt`: List all tables
-- `\d+ issues`: List columns for `issues` table
-- `CREATE TABLE board_labels();`: Create a table called `board_labels`
-- `SELECT * FROM schema_migrations WHERE version = '20170926203418';`: Check if a migration was run
-- `DELETE FROM schema_migrations WHERE version = '20170926203418';`: Manually remove a migration
-
-## Access the database with a GUI
-
-Most GUIs (DataGrip, RubyMine, DBeaver) require a TCP connection to the database, but by default
-the database runs on a UNIX socket. To be able to access the database from these tools, some steps
-are needed:
-
-1. On the GDK root directory, run:
-
- ```shell
- gdk config set postgresql.host localhost
- ```
-
-1. Open your `gdk.yml`, and confirm that it has the following lines:
-
- ```yaml
- postgresql:
- host: localhost
- ```
-
-1. Reconfigure GDK:
-
- ```shell
- gdk reconfigure
- ```
-
-1. On your database GUI, select `localhost` as host, `5432` as port and `gitlabhq_development` as database.
- Alternatively, you can use the connection string `postgresql://localhost:5432/gitlabhq_development`.
-
-The new connection should be working now.
-
-## Access the GDK database with Visual Studio Code
-
-Use these instructions for exploring the GitLab database while developing with the GDK:
-
-1. Install or open [Visual Studio Code](https://code.visualstudio.com/download).
-1. Install the [PostgreSQL VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres).
-1. In Visual Studio Code select **PostgreSQL Explorer** in the left toolbar.
-1. In the top bar of the new window, select `+` to **Add Database Connection**, and follow the prompts to fill in the details:
- 1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`).
- 1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation.
- 1. **Password of the PostgreSQL user**: the password you set when installing PostgreSQL.
- 1. **Port number to connect to**: `5432` (default).
- 1. **Use an SSL connection?** This depends on your installation. Options are:
- - **Use Secure Connection**
- - **Standard Connection** (default)
- 1. **Optional. The database to connect to**: `gitlabhq_development`.
- 1. **The display name for the database connection**: `gitlabhq_development`.
-
-Your database connection should now be displayed in the PostgreSQL Explorer pane and
-you can explore the `gitlabhq_development` database. If you cannot connect, ensure
-that GDK is running. For further instructions on how to use the PostgreSQL Explorer
-Extension for Visual Studio Code, read the [usage section](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres#usage)
-of the extension documentation.
-
-## FAQ
-
-### `ActiveRecord::PendingMigrationError` with Spring
-
-When running specs with the [Spring pre-loader](rake_tasks.md#speed-up-tests-rake-tasks-and-migrations),
-the test database can get into a corrupted state. Trying to run the migration or
-dropping/resetting the test database has no effect.
-
-```shell
-$ bundle exec spring rspec some_spec.rb
-...
-Failure/Error: ActiveRecord::Migration.maintain_test_schema!
-
-ActiveRecord::PendingMigrationError:
-
-
- Migrations are pending. To resolve this issue, run:
-
- bin/rake db:migrate RAILS_ENV=test
-# ~/.rvm/gems/ruby-2.3.3/gems/activerecord-4.2.10/lib/active_record/migration.rb:392:in `check_pending!'
-...
-0 examples, 0 failures, 1 error occurred outside of examples
-```
-
-To resolve, you can kill the spring server and app that lives between spec runs.
-
-```shell
-$ ps aux | grep spring
-eric 87304 1.3 2.9 3080836 482596 ?? Ss 10:12AM 4:08.36 spring app | gitlab | started 6 hours ago | test mode
-eric 37709 0.0 0.0 2518640 7524 s006 S Wed11AM 0:00.79 spring server | gitlab | started 29 hours ago
-$ kill 87304
-$ kill 37709
-```
-
-### db:migrate `database version is too old to be migrated` error
-
-Users receive this error when `db:migrate` detects that the current schema version
-is older than the `MIN_SCHEMA_VERSION` defined in the `Gitlab::Database` library
-module.
-
-Over time we cleanup/combine old migrations in the codebase, so it is not always
-possible to migrate GitLab from every previous version.
-
-In some cases you may want to bypass this check. For example, if you were on a version
-of GitLab schema later than the `MIN_SCHEMA_VERSION`, and then rolled back the
-to an older migration, from before. In this case, to migrate forward again,
-you should set the `SKIP_SCHEMA_VERSION_CHECK` environment variable.
-
-```shell
-bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/database_query_comments.md b/doc/development/database_query_comments.md
index 2798071bc06..7f9def7e567 100644
--- a/doc/development/database_query_comments.md
+++ b/doc/development/database_query_comments.md
@@ -1,62 +1,11 @@
---
-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
+redirect_to: 'database/database_query_comments.md'
+remove_date: '2022-11-05'
---
-# Database query comments with Marginalia
+This document was moved to [another location](database/database_query_comments.md).
-The [Marginalia gem](https://github.com/basecamp/marginalia) is used to add
-query comments containing application related context information to PostgreSQL
-queries generated by ActiveRecord.
-
-It is very useful for tracing problematic queries back to the application source.
-
-An engineer during an on-call incident has the full context of a query
-and its application source from the comments.
-
-## Metadata information in comments
-
-Queries generated from **Rails** include the following metadata in comments:
-
-- `application`
-- `correlation_id`
-- `endpoint_id`
-- `line`
-
-Queries generated from **Sidekiq** workers include the following metadata
-in comments:
-
-- `application`
-- `jid`
-- `correlation_id`
-- `endpoint_id`
-- `line`
-
-`endpoint_id` is a single field that can represent any endpoint in the application:
-
-- For Rails controllers, it's the controller and action. For example, `Projects::BlobController#show`.
-- For Grape API endpoints, it's the route. For example, `/api/:version/users/:id`.
-- For Sidekiq workers, it's the worker class name. For example, `UserStatusCleanup::BatchWorker`.
-
-`line` is not present in production logs due to the additional overhead required.
-
-Examples of queries with comments:
-
-- Rails:
-
- ```sql
- /*application:web,controller:blob,action:show,correlation_id:01EZVMR923313VV44ZJDJ7PMEZ,endpoint_id:Projects::BlobController#show*/ SELECT "routes".* FROM "routes" WHERE "routes"."source_id" = 75 AND "routes"."source_type" = 'Namespace' LIMIT 1
- ```
-
-- Grape:
-
- ```sql
- /*application:web,correlation_id:01EZVN0DAYGJF5XHG9N4VX8FAH,endpoint_id:/api/:version/users/:id*/ SELECT COUNT(*) FROM "users" INNER JOIN "user_follow_users" ON "users"."id" = "user_follow_users"."followee_id" WHERE "user_follow_users"."follower_id" = 1
- ```
-
-- Sidekiq:
-
- ```sql
- /*application:sidekiq,correlation_id:df643992563683313bc0a0288fb55e23,jid:15fbc506590c625d7664b074,endpoint_id:UserStatusCleanup::BatchWorker,line:/app/workers/user_status_cleanup/batch_worker.rb:19:in `perform'*/ SELECT $1 AS one FROM "user_statuses" WHERE "user_statuses"."clear_status_at" <= $2 LIMIT $3
- ```
+<!-- This redirect file can be deleted after <2022-11-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/database_review.md b/doc/development/database_review.md
index 2b215190e6d..2decd304103 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -113,6 +113,7 @@ the following preparations into account.
- Ensure `db/structure.sql` is updated as [documented](migration_style_guide.md#schema-changes), and additionally ensure that the relevant version files under
`db/schema_migrations` were added or removed.
+- Ensure that the Database Dictionary is updated as [documented](database/database_dictionary.md).
- Make migrations reversible by using the `change` method or include a `down` method when using `up`.
- Include either a rollback procedure or describe how to rollback changes.
- Add the output of both migrating (`db:migrate`) and rolling back (`db:rollback`) for all migrations into the MR description.
@@ -179,7 +180,7 @@ Include in the MR description:
- [explain.depesz.com](https://explain.depesz.com) or [explain.dalibo.com](https://explain.dalibo.com): Paste both the plan and the query used in the form.
- When providing query plans, make sure it hits enough data:
- You can use a GitLab production replica to test your queries on a large scale,
- through the `#database-lab` Slack channel or through [ChatOps](understanding_explain_plans.md#chatops).
+ through the `#database-lab` Slack channel or through [ChatOps](database/understanding_explain_plans.md#chatops).
- Usually, the `gitlab-org` namespace (`namespace_id = 9970`) and the
`gitlab-org/gitlab-foss` (`project_id = 13083`) or the `gitlab-org/gitlab` (`project_id = 278964`)
projects provide enough data to serve as a good example.
@@ -187,7 +188,7 @@ Include in the MR description:
- If your queries belong to a new feature in GitLab.com and thus they don't return data in production:
- You may analyze the query and to provide the plan from a local environment.
- `#database-lab` and [postgres.ai](https://postgres.ai/) both allow updates to data (`exec UPDATE issues SET ...`) and creation of new tables and columns (`exec ALTER TABLE issues ADD COLUMN ...`).
- - More information on how to find the number of actual returned records in [Understanding EXPLAIN plans](understanding_explain_plans.md)
+ - More information on how to find the number of actual returned records in [Understanding EXPLAIN plans](database/understanding_explain_plans.md)
- For query changes, it is best to provide both the SQL queries along with the
plan _before_ and _after_ the change. This helps spot differences quickly.
- Include data that shows the performance improvement, preferably in
@@ -200,7 +201,7 @@ Include in the MR description:
#### Preparation when adding tables
-- Order columns based on the [Ordering Table Columns](ordering_table_columns.md) guidelines.
+- Order columns based on the [Ordering Table Columns](database/ordering_table_columns.md) guidelines.
- Add foreign keys to any columns pointing to data in other tables, including [an index](migration_style_guide.md#adding-foreign-key-constraints).
- Add indexes for fields that are used in statements such as `WHERE`, `ORDER BY`, `GROUP BY`, and `JOIN`s.
- New tables and columns are not necessarily risky, but over time some access patterns are inherently
@@ -225,7 +226,7 @@ Include in the MR description:
- Consider [access patterns and data layout](database/layout_and_access_patterns.md) if new tables or columns are added.
- Review migrations follow [database migration style guide](migration_style_guide.md),
for example
- - [Check ordering of columns](ordering_table_columns.md)
+ - [Check ordering of columns](database/ordering_table_columns.md)
- [Check indexes are present for foreign keys](migration_style_guide.md#adding-foreign-key-constraints)
- Ensure that migrations execute in a transaction or only contain
concurrent index/foreign key helpers (with transactions disabled)
@@ -247,16 +248,16 @@ Include in the MR description:
- Making numerous SQL queries per record in a dataset.
- Review queries (for example, make sure batch sizes are fine)
- Because execution time can be longer than for a regular migration,
- it's suggested to treat background migrations as post migrations:
- place them in `db/post_migrate` instead of `db/migrate`. Keep in mind
- that post migrations are executed post-deployment in production.
+ 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:
- Are the stated access patterns and volume reasonable? Do the assumptions they're based on seem sound? Do these patterns pose risks to stability?
- - Are the columns [ordered to conserve space](ordering_table_columns.md)?
+ - Are the columns [ordered to conserve space](database/ordering_table_columns.md)?
- Are there foreign keys for references to other tables?
- Check data migrations:
- Establish a time estimate for execution on GitLab.com.
@@ -267,10 +268,10 @@ Include in the MR description:
- Check for any overly complex queries and queries the author specifically
points out for review (if any)
- If not present, ask the author to provide SQL queries and query plans
- (for example, by using [ChatOps](understanding_explain_plans.md#chatops) or direct
+ (for example, by using [ChatOps](database/understanding_explain_plans.md#chatops) or direct
database access)
- For given queries, review parameters regarding data distribution
- - [Check query plans](understanding_explain_plans.md) and suggest improvements
+ - [Check query plans](database/understanding_explain_plans.md) and suggest improvements
to queries (changing the query, schema or adding indexes and similar)
- - General guideline is for queries to come in below [100ms execution time](query_performance.md#timing-guidelines-for-queries)
+ - General guideline is for queries to come in below [100ms execution time](database/query_performance.md#timing-guidelines-for-queries)
- Avoid N+1 problems and minimize the [query count](merge_request_performance_guidelines.md#query-counts).
diff --git a/doc/development/db_dump.md b/doc/development/db_dump.md
index f2076cbc410..c632302329a 100644
--- a/doc/development/db_dump.md
+++ b/doc/development/db_dump.md
@@ -1,56 +1,11 @@
---
-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
+redirect_to: 'database/db_dump.md'
+remove_date: '2022-11-06'
---
-# Importing a database dump into a staging environment
+This document was moved to [another location](database/db_dump.md).
-Sometimes it is useful to import the database from a production environment
-into a staging environment for testing. The procedure below assumes you have
-SSH and `sudo` access to both the production environment and the staging VM.
-
-**Destroy your staging VM** when you are done with it. It is important to avoid
-data leaks.
-
-On the staging VM, add the following line to `/etc/gitlab/gitlab.rb` to speed up
-large database imports.
-
-```shell
-# On STAGING
-echo "postgresql['checkpoint_segments'] = 64" | sudo tee -a /etc/gitlab/gitlab.rb
-sudo touch /etc/gitlab/skip-auto-reconfigure
-sudo gitlab-ctl reconfigure
-sudo gitlab-ctl stop puma
-sudo gitlab-ctl stop sidekiq
-```
-
-Next, we let the production environment stream a compressed SQL dump to our
-local machine via SSH, and redirect this stream to a `psql` client on the staging
-VM.
-
-```shell
-# On LOCAL MACHINE
-ssh -C gitlab.example.com sudo -u gitlab-psql /opt/gitlab/embedded/bin/pg_dump -Cc gitlabhq_production |\
- ssh -C staging-vm sudo -u gitlab-psql /opt/gitlab/embedded/bin/psql -d template1
-```
-
-## Recreating directory structure
-
-If you need to re-create some directory structure on the staging server you can
-use this procedure.
-
-First, on the production server, create a list of directories you want to
-re-create.
-
-```shell
-# On PRODUCTION
-(umask 077; sudo find /var/opt/gitlab/git-data/repositories -maxdepth 1 -type d -print0 > directories.txt)
-```
-
-Copy `directories.txt` to the staging server and create the directories there.
-
-```shell
-# On STAGING
-sudo -u git xargs -0 mkdir -p < directories.txt
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index 4e1d2e22e78..f0364f60d38 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -4,10 +4,10 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Deprecation guidelines
+# Deprecating GitLab features
-This page includes information about how and when to remove or make [breaking
-changes](../contributing/index.md#breaking-changes) to GitLab features.
+This page includes information about how and when to remove or make breaking changes
+to GitLab features.
## Terminology
@@ -37,6 +37,16 @@ changes](../contributing/index.md#breaking-changes) to GitLab features.
![Deprecation, End of Support, Removal process](img/deprecation_removal_process.png)
+**Breaking change**:
+
+A "breaking change" is any change that requires users to make a corresponding change to their code, settings, or workflow. "Users" might be humans, API clients, or even code classes that "use" another class. Examples of breaking changes include:
+
+- Removing a user-facing feature without a replacement/workaround.
+- Changing the definition of an existing API (by doing things like re-naming query parameters or changing routes).
+- Removing a public method from a code class.
+
+A breaking change can be considered major if it affects many users, or represents a significant change in behavior.
+
## When can a feature be deprecated?
Deprecations should be announced on the [Deprecated feature removal schedule](../../update/deprecations.md).
@@ -45,6 +55,12 @@ Do not include the deprecation announcement in the merge request that introduces
Use a separate MR to create a deprecation entry. For steps to create a deprecation entry, see
[Deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations).
+## How are Community Contributions to a deprecated feature handled?
+
+Development on deprecated features is restricted to Priority 1 / Severity 1 bug fixes. Any community contributions to deprecated features are unlikely to be prioritized during milestone planning.
+
+However, at GitLab, we [give agency](https://about.gitlab.com/handbook/values/#give-agency) to our team members. So, a member of the team associated with the contribution may decide to review and merge it at their discretion.
+
## When can a feature be removed/changed?
Generally, feature or configuration can be removed/changed only on major release.
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index 116071cdfd9..f49d024095d 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -73,14 +73,14 @@ In this example, we have the following hypothetical values:
- `driver`: the driver such a Jaeger.
- `param_name`, `param_value`: these are driver specific configuration values. Configuration
- parameters for Jaeger are documented [further on in this
- document](#2-configure-the-gitlab_tracing-environment-variable) they should be URL encoded.
+ parameters for Jaeger are documented [further on in this document](#2-configure-the-gitlab_tracing-environment-variable)
+ they should be URL encoded.
Multiple values should be separated by `&` characters like a URL.
## Using Jaeger in the GitLab Development Kit
-The first tracing implementation that GitLab supports is Jaeger, and the [GitLab Development
-Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/) supports distributed tracing with
+The first tracing implementation that GitLab supports is Jaeger, and the
+[GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/) supports distributed tracing with
Jaeger out-of-the-box.
The easiest way to access tracing from a GDK environment is through the
@@ -116,8 +116,8 @@ Jaeger has many configuration options, but is very easy to start in an "all-in-o
memory for trace storage (and is therefore non-persistent). The main advantage of "all-in-one" mode
being ease of use.
-For more detailed configuration options, refer to the [Jaeger
-documentation](https://www.jaegertracing.io/docs/1.9/getting-started/).
+For more detailed configuration options, refer to the
+[Jaeger documentation](https://www.jaegertracing.io/docs/1.9/getting-started/).
#### Using Docker
@@ -201,8 +201,8 @@ If `GITLAB_TRACING` is not configured correctly, this issue is logged:
```
By default, GitLab ships with the Jaeger tracer, but other tracers can be included at compile time.
-Details of how this can be done are included in the [LabKit tracing
-documentation](https://pkg.go.dev/gitlab.com/gitlab-org/labkit/tracing).
+Details of how this can be done are included in the
+[LabKit tracing documentation](https://pkg.go.dev/gitlab.com/gitlab-org/labkit/tracing).
If no log messages about tracing are emitted, the `GITLAB_TRACING` environment variable is likely
not set.
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index 92c34c01e5d..bf1461a810d 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -5,7 +5,7 @@ group: unassigned
description: 'Writing styles, markup, formatting, and other standards for the GitLab RESTful APIs.'
---
-# RESTful API
+# Documenting REST API resources
REST API resources are documented in Markdown under
[`/doc/api`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/api). Each
@@ -104,6 +104,9 @@ for the section. For example:
> `widget_message` [introduced](<link-to-issue>) in GitLab 14.3.
```
+If the API or attribute is deployed behind a feature flag,
+[include the feature flag information](feature_flags.md) in the version history.
+
## Deprecations
To document the deprecation of an API endpoint, follow the steps to
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index 5203ca52922..5f6076f3195 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -142,6 +142,20 @@ graph LR
B--"Unpacked documentation uploaded"-->C
```
+### Manually deploy to production
+
+GitLab Docs is deployed to production whenever the `Build docs.gitlab.com every 4 hours` scheduled pipeline runs. By
+default, this pipeline runs every four hours.
+
+Maintainers can [manually](../../../ci/pipelines/schedules.md#run-manually) run this pipeline to force a deployment to
+production:
+
+1. Go to the [scheduled pipelines](https://gitlab.com/gitlab-org/gitlab-docs/-/pipeline_schedules) for `gitlab-docs`.
+1. Next to `Build docs.gitlab.com every 4 hours`, select **Play** (**{play}**).
+
+The updated documentation is available in production after the `pages` and `pages:deploy` jobs
+complete in the new pipeline.
+
## Docker files
The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/) contains all needed
@@ -150,10 +164,10 @@ Dockerfiles to build and deploy <https://docs.gitlab.com>. It is heavily inspire
| Dockerfile | Docker image | Description |
|:---------------------------------------------------------------------------------------------------------------------------|:------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
-| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
-| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch) |
-| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
+| [`bootstrap.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/bootstrap.Dockerfile) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. |
+| [`builder.onbuild.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/builder.onbuild.Dockerfile) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. |
+| [`nginx.onbuild.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/nginx.onbuild.Dockerfile) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch) |
+| [`archives.Dockerfile`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/dockerfiles/archives.Dockerfile) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. |
### How to build the images
diff --git a/doc/development/documentation/site_architecture/folder_structure.md b/doc/development/documentation/site_architecture/folder_structure.md
index 0e8065d794f..7f29d3fba9e 100644
--- a/doc/development/documentation/site_architecture/folder_structure.md
+++ b/doc/development/documentation/site_architecture/folder_structure.md
@@ -85,7 +85,7 @@ place for it.
Do not include the same information in multiple places.
[Link to a single source of truth instead.](../styleguide/index.md#link-instead-of-repeating-text)
-For example, if you have code in a repository other than the [primary repositories](index.md#architecture),
+For example, if you have code in a repository other than the [primary repositories](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/architecture.md),
and documentation in the same repository, you can keep the documentation in that repository.
Then you can either:
diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md
index e1e0da03abc..05e697869b9 100644
--- a/doc/development/documentation/site_architecture/global_nav.md
+++ b/doc/development/documentation/site_architecture/global_nav.md
@@ -22,7 +22,7 @@ At the highest level, our global nav is workflow-based. Navigation needs to help
The levels under each of the higher workflow-based topics are the names of features.
For example:
-**Use GitLab** (_workflow_) **> Build your application** (_workflow_) **> CI/CD** (_feature_) **> Pipelines** (_feature)
+**Use GitLab** (_workflow_) **> Build your application** (_workflow_) **> CI/CD** (_feature_) **> Pipelines** (_feature_)
## Choose the right words for your navigation entry
@@ -39,20 +39,36 @@ as helpful as **Get started with runners**.
## Add a navigation entry
-All topics should be included in the left nav.
-
To add a topic to the global nav, edit
[`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/content/_data/navigation.yaml)
and add your item.
-All new pages need a navigation item. Without a navigation, the page becomes "orphaned." That
-is:
+Without a navigation entry:
+
+- The navigation closes when the page is opened, and the reader loses their place.
+- The page isn't visible in a group with other pages.
+
+### Pages you don't need to add
+
+Exclude these pages from the global nav:
+
+- Legal notices.
+- Pages in the `architecture/blueprints` directory.
+- Pages in the `user/application_security/dast/checks/` directory.
+
+The following pages should probably be in the global nav, but the technical writers
+do not actively work to add them:
+
+- Pages in the `/development` directory.
+- Pages authored by the support team, which are under the `doc/administration/troubleshooting` directory.
+
+Sometimes pages for deprecated features are not in the global nav, depending on how long ago the feature was deprecated.
-- The navigation shuts when the page is opened, and the reader loses their place.
-- The page doesn't belong in a group with other pages.
+All other pages should be in the global nav.
-This means the decision to create a new page is a decision to create new navigation item and vice
-versa.
+The technical writing team runs a report to determine which pages are not in the nav.
+For now this report is manual, but [an issue exists](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/1212)
+to automate it.
### Where to add
@@ -283,7 +299,7 @@ The [layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/global_
is fed by the [data file](#data-file), builds the global nav, and is rendered by the
[default](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/layouts/default.html) layout.
-The global nav contains links from all [four upstream projects](index.md#architecture).
+The global nav contains links from all [four upstream projects](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/architecture.md).
The [global nav URL](#urls) has a different prefix depending on the documentation file you change.
| Repository | Link prefix | Final URL |
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index af24fbe303b..2864bbe7404 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -11,247 +11,30 @@ the repository which is used to generate the GitLab documentation website and
is deployed to <https://docs.gitlab.com>. It uses the [Nanoc](https://nanoc.app/)
static site generator.
-## Architecture
+View the [`gitlab-docs` architecture page](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/architecture.md)
+for more information.
-While the source of the documentation content is stored in the repositories for
-each GitLab product, the source that is used to build the documentation
-site _from that content_ is located at <https://gitlab.com/gitlab-org/gitlab-docs>.
+## Documentation in other repositories
-The following diagram illustrates the relationship between the repositories
-from where content is sourced, the `gitlab-docs` project, and the published output.
-
-```mermaid
- graph LR
- A[gitlab-org/gitlab/doc]
- B[gitlab-org/gitlab-runner/docs]
- C[gitlab-org/omnibus-gitlab/doc]
- D[gitlab-org/charts/gitlab/doc]
- E[gitlab-org/cloud-native/gitlab-operator/doc]
- Y[gitlab-org/gitlab-docs]
- A --> Y
- B --> Y
- C --> Y
- D --> Y
- E --> Y
- Y -- Build pipeline --> Z
- Z[docs.gitlab.com]
- M[//ee/]
- N[//runner/]
- O[//omnibus/]
- P[//charts/]
- Q[//operator/]
- Z --> M
- Z --> N
- Z --> O
- Z --> P
- Z --> Q
-```
-
-GitLab docs content isn't kept in the `gitlab-docs` repository.
-All documentation files are hosted in the respective repository of each
-product, and all together are pulled to generate the docs website:
-
-- [GitLab](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc)
-- [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/tree/master/doc)
-- [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/tree/main/docs)
-- [GitLab Chart](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc)
-- [GitLab Operator](https://gitlab.com/gitlab-org/cloud-native/gitlab-operator/-/tree/master/doc)
-
-Learn more about [the docs folder structure](folder_structure.md).
-
-### Documentation in other repositories
-
-If you have code and documentation in a repository other than the [primary repositories](#architecture),
+If you have code and documentation in a repository other than the [primary repositories](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/architecture.md),
you should keep the documentation with the code in that repository.
-Then you can either:
+Then you can use one of these approaches:
-- [Add the repository to the list of products](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/development.md#add-a-new-product)
- published at <https://docs.gitlab.com>.
-- [Add an entry in the global navigation](global_nav.md#add-a-navigation-entry) for
- <https://docs.gitlab.com> that links to the documentation in that repository.
+- Recommended. [Add the repository to the list of products](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/development.md#add-a-new-product)
+ published at <https://docs.gitlab.com>. The source of the documentation pages remains
+ in the external repository, but the resulting pages are indexed and searchable on <https://docs.gitlab.com>.
+- Recommended. [Add an entry in the global navigation](global_nav.md#add-a-navigation-entry) for
+ <https://docs.gitlab.com> that links directly to the documentation in that external repository.
+ The documentation pages are not indexed or searchable on <https://docs.gitlab.com>.
View [an example](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/fedb6378a3c92274ba3b6031df0d34455594e4cc/content/_data/navigation.yaml#L2944-L2946).
-
-## Assets
-
-To provide an optimized site structure, design, and a search-engine friendly
-website, along with a discoverable documentation, we use a few assets for
-the GitLab Documentation website.
-
-### External libraries
-
-GitLab Docs is built with a combination of external:
-
-- [JavaScript libraries](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/package.json).
-- [Ruby libraries](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/Gemfile).
-
-### SEO
-
-- [Schema.org](https://schema.org/)
-- [Google Analytics](https://marketingplatform.google.com/about/analytics/)
-- [Google Tag Manager](https://developers.google.com/tag-platform/tag-manager)
-
-## Global navigation
-
-Read through [the global navigation documentation](global_nav.md) to understand:
-
-- How the global navigation is built.
-- How to add new navigation items.
-
-<!--
-## Helpers
-
-TBA
--->
-
-## Pipelines
-
-The pipeline in the `gitlab-docs` project:
-
-- Tests changes to the docs site code.
-- Builds the Docker images used in various pipeline jobs.
-- Builds and deploys the docs site itself.
-- Generates the review apps when the `review-docs-deploy` job is triggered.
-
-### Rebuild the docs site Docker images
-
-Once a week on Mondays, a scheduled pipeline runs and rebuilds the Docker images
-used in various pipeline jobs, like `docs-lint`. The Docker image configuration files are
-located in the [Dockerfiles directory](https://gitlab.com/gitlab-org/gitlab-docs/-/tree/main/dockerfiles).
-
-If you need to rebuild the Docker images immediately (must have maintainer level permissions):
-
-WARNING:
-If you change the Dockerfile configuration and rebuild the images, you can break the main
-pipeline in the main `gitlab` repository as well as in `gitlab-docs`. Create an image with
-a different name first and test it to ensure you do not break the pipelines.
-
-1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Pipelines**.
-1. Select **Run pipeline**.
-1. See that a new pipeline is running. The jobs that build the images are in the first
- stage, `build-images`. You can select the pipeline number to see the larger pipeline
- graph, or select the first (`build-images`) stage in the mini pipeline graph to
- expose the jobs that build the images.
-1. Select the **play** (**{play}**) button next to the images you want to rebuild.
- - Normally, you do not need to rebuild the `image:gitlab-docs-base` image, as it
- rarely changes. If it does need to be rebuilt, be sure to only run `image:docs-lint`
- after it is finished rebuilding.
-
-### Deploy the docs site
-
-Every four hours a scheduled pipeline builds and deploys the docs site. The pipeline
-fetches the current docs from the main project's main branch, builds it with Nanoc
-and deploys it to <https://docs.gitlab.com>.
-
-To build and deploy the site immediately (must have the Maintainer role):
-
-1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI/CD > Schedules**.
-1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, select the **play** (**{play}**) button.
-
-Read more about [documentation deployments](deployment_process.md).
-
-## Using YAML data files
-
-The easiest way to achieve something similar to
-[Jekyll's data files](https://jekyllrb.com/docs/datafiles/) in Nanoc is by
-using the [`@items`](https://nanoc.app/doc/reference/variables/#items-and-layouts)
-variable.
-
-The data file must be placed inside the `content/` directory and then it can
-be referenced in an ERB template.
-
-Suppose we have the `content/_data/versions.yaml` file with the content:
-
-```yaml
-versions:
- - 10.6
- - 10.5
- - 10.4
-```
-
-We can then loop over the `versions` array with something like:
-
-```erb
-<% @items['/_data/versions.yaml'][:versions].each do | version | %>
-
-<h3><%= version %></h3>
-
-<% end &>
-```
-
-Note that the data file must have the `yaml` extension (not `yml`) and that
-we reference the array with a symbol (`:versions`).
-
-## Archived documentation banner
-
-A banner is displayed on archived documentation pages with the text `This is archived documentation for
-GitLab. Go to the latest.` when either:
-
-- The version of the documentation displayed is not the first version entry in `online` in
- `content/_data/versions.yaml`.
-- The documentation was built from the default branch (`main`).
-
-For example, if the `online` entries for `content/_data/versions.yaml` are:
-
-```yaml
-online:
- - "14.4"
- - "14.3"
- - "14.2"
-```
-
-In this case, the archived documentation banner isn't displayed:
-
-- For 14.4, the docs built from the `14.4` branch. The branch name is the first entry in `online`.
-- For 14.5-pre, the docs built from the default project branch (`main`).
-
-The archived documentation banner is displayed:
-
-- For 14.3.
-- For 14.2.
-- For any other version.
-
-## Bumping versions of CSS and JavaScript
-
-Whenever the custom CSS and JavaScript files under `content/assets/` change,
-make sure to bump their version in the front matter. This method guarantees that
-your changes take effect by clearing the cache of previous files.
-
-Always use Nanoc's way of including those files, do not hardcode them in the
-layouts. For example use:
-
-```erb
-<script async type="application/javascript" src="<%= @items['/assets/javascripts/badges.*'].path %>"></script>
-
-<link rel="stylesheet" href="<%= @items['/assets/stylesheets/toc.*'].path %>">
-```
-
-The links pointing to the files should be similar to:
-
-```erb
-<%= @items['/path/to/assets/file.*'].path %>
-```
-
-Nanoc then builds and renders those links correctly according with what's
-defined in [`Rules`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/Rules).
-
-## Linking to source files
-
-A helper called [`edit_on_gitlab`](https://gitlab.com/gitlab-org/gitlab-docs/blob/main/lib/helpers/edit_on_gitlab.rb) can be used
-to link to a page's source file. We can link to both the simple editor and the
-web IDE. Here's how you can use it in a Nanoc layout:
-
-- Default editor: `<a href="<%= edit_on_gitlab(@item, editor: :simple) %>">Simple editor</a>`
-- Web IDE: `<a href="<%= edit_on_gitlab(@item, editor: :webide) %>">Web IDE</a>`
-
-If you don't specify `editor:`, the simple one is used by default.
-
-## Algolia search engine
-
-The docs site uses [Algolia DocSearch](https://community.algolia.com/docsearch/)
-for its search function.
-
-Learn more in <https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/doc/docsearch.md>.
+- Create a landing page for the product in the `gitlab` repository, and add the landing page
+ [to the global navigation](global_nav.md#add-a-navigation-entry), but keep the rest
+ of the documentation in the external repository. The landing page is indexed and
+ searchable on <https://docs.gitlab.com>, but the rest of the documentation is not.
+ For example, the [GitLab Workflow extension for VS Code](../../../user/project/repository/vscode.md).
+ We do not encourage the use of [pages with lists of links](../structure.md#topics-and-resources-pages),
+ so only use this option if the recommended options are not feasible.
## Monthly release process (versions)
@@ -260,5 +43,5 @@ For more information, read about the [monthly release process](https://gitlab.co
## Review Apps for documentation merge requests
-If you are contributing to GitLab docs read how to [create a Review App with each
-merge request](../index.md#previewing-the-changes-live).
+If you are contributing to GitLab docs read how to
+[create a Review App with each merge request](../index.md#previewing-the-changes-live).
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index a02046d4466..a5d1290a17a 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -148,35 +148,60 @@ Avoid these heading titles:
## Troubleshooting
-Troubleshooting can be one of two categories:
+Troubleshooting topics should be the last topics on a page.
-- **Troubleshooting task.** This information is written the same way as a [standard task](#task).
+Troubleshooting can be one of three categories:
+
+- **An introductory topic.** This topic introduces the troubleshooting section of a page.
+ For example:
+
+ ```markdown
+ ## Troubleshooting
+
+ When working with <x feature>, you might encounter the following issues.
+ ```
+
+- **Troubleshooting task.** The title should be similar to a [standard task](#task).
For example, "Run debug tools" or "Verify syntax."
-- **Troubleshooting reference.** This information has a specific format.
-Troubleshooting reference information should be in this format:
+- **Troubleshooting reference.** This information includes the error message. For example:
-```markdown
-# Title (the error message or a description of it)
+ ```markdown
+ ### The error message or a description of it
-You might get an error that states <error message>.
+ You might get an error that states <error message>.
-This issue occurs when...
+ This issue occurs when...
-The workaround is...
-```
+ The workaround is...
+ ```
-If multiple causes or workarounds exist, consider putting them into a table format.
+ If multiple causes or workarounds exist, consider putting them into a table format.
+ If you use the exact error message, surround it in backticks so it's styled as code.
+
+If a page has more than five troubleshooting topics, put the content on a separate page that has troubleshooting information exclusively. Name the page `Troubleshooting <featurename>`.
### Troubleshooting headings
-For the heading:
+For the heading of a **Troubleshooting reference** topic:
- Consider including at least a partial error message.
- Use fewer than 70 characters.
If you do not put the full error in the title, include it in the body text.
+### Related topics
+
+If inline links are not sufficient, you can create a topic called **Related topics**
+and include an unordered list of related topics. This topic should be above the Troubleshooting section.
+
+```markdown
+# Related topics
+
+- [Configure your pipeline](link-to-topic)
+- [Trigger a pipeline manually](link-to-topic)
+```
+
## General heading text guidelines
In general, for heading text:
@@ -272,18 +297,6 @@ If you need to add more than one task,
consider using subsections for each distinct task.
```
-### Related topics
-
-If inline links are not sufficient, you can create a topic called **Related topics**
-and include an unordered list of related topics. This topic should be above the Troubleshooting section.
-
-```markdown
-# Related topics
-
-- [Configure your pipeline](link-to-topic)
-- [Trigger a pipeline manually](link-to-topic)
-```
-
### Topics and resources pages
This page has a list of links that point to important sections
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 1af0cb72055..709e6b2d0d9 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -150,6 +150,8 @@ the page is rendered to HTML. There can be only **one** level 1 heading per page
- For each subsection, increment the heading level. In other words, increment the number of `#` characters
in front of the heading.
+- Avoid headings greater than `H5` (`#####`). If you need more than five heading levels, move the topics to a new page instead.
+ Headings greater than `H5` do not display in the right sidebar navigation.
- Do not skip a level. For example: `##` > `####`.
- Leave one blank line before and after the heading.
@@ -162,6 +164,13 @@ Also, do not use links as part of heading text.
See also [heading guidelines for specific topic types](../structure.md).
+### Backticks in Markdown
+
+Use backticks for:
+
+- [Code blocks](#code-blocks).
+- Error messages.
+
### Markdown Rules
GitLab ensures that the Markdown used across all documentation is consistent, as
@@ -722,10 +731,12 @@ We include guidance for links in these categories:
- 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
@@ -787,45 +798,15 @@ section of GitLab.
### Links to external documentation
-When describing interactions with external software, it's often helpful to
-include links to external documentation. When possible, make sure that you're
-linking to an [**authoritative** source](#authoritative-sources). For example,
-if you're describing a feature in Microsoft's Active Directory, include a link
-to official Microsoft documentation.
-
-### Authoritative sources
-
-When citing external information, use sources that are written by the people who
-created the item or product in question. These sources are the most likely to be
-accurate and remain up to date.
-
-Examples of authoritative sources include:
-
-- Specifications, such as a [Request for Comments](https://www.ietf.org/standards/rfcs/)
- document from the Internet Engineering Task Force.
-- Official documentation for a product. For example, if you're setting up an
- interface with the Google OAuth 2 authorization server, include a link to
- Google's documentation.
-- Official documentation for a project. For example, if you're citing NodeJS
- functionality, refer directly to [NodeJS documentation](https://nodejs.org/en/docs/).
-- Books from an authoritative publisher.
+When possible, avoid links to external documentation. These links can easily become outdated, and are difficult to maintain.
-Examples of sources to avoid include:
+- [They lead to link rot](https://en.wikipedia.org/wiki/Link_rot).
+- [They create issues with maintenance](https://gitlab.com/gitlab-org/gitlab/-/issues/368300).
-- Personal blog posts.
-- Wikipedia.
-- Non-trustworthy articles.
-- Discussions on forums such as Stack Overflow.
-- Documentation from a company that describes another company's product.
+Sometimes links are required. They might clarify troubleshooting steps or help prevent duplication of content.
+Sometimes they are more precise and will be maintained more actively.
-While many of these sources to avoid can help you learn skills and or features,
-they can become obsolete quickly. Nobody is obliged to maintain any of these
-sites. Therefore, we should avoid using them as reference literature.
-
-NOTE:
-Non-authoritative sources are acceptable only if there is no equivalent
-authoritative source. Even then, focus on non-authoritative sources that are
-extensively cited or peer-reviewed.
+For each external link you add, weigh the customer benefit with the maintenance difficulties.
### Links requiring permissions
@@ -950,6 +931,16 @@ For example:
1. Optional. Enter a description for the job.
```
+### Recommended steps
+
+If a step is recommended, start the step with the word `Recommended` followed by a period.
+
+For example:
+
+```markdown
+1. Recommended. Enter a description for the job.
+```
+
### Documenting multiple fields at once
If the UI text sufficiently explains the fields in a section, do not include a task step for every field.
@@ -1106,6 +1097,36 @@ include a visual representation to help readers understand it, you can:
an area of the screen.
- Create a short video of the interaction and link to it.
+## Emojis
+
+Don't use the Markdown emoji format, for example `:smile:`, for any purpose. Use
+[GitLab SVG icons](#gitlab-svg-icons) instead.
+
+Use of emoji in Markdown requires GitLab Flavored Markdown, which is not supported by Kramdown,
+the Markdown rendering engine used for GitLab documentation.
+
+## GitLab SVG icons
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) in GitLab 12.7.
+
+You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/)
+directly in the documentation. For example, `**{tanuki}**` renders as: **{tanuki}**.
+
+In most cases, you should avoid using the icons in text.
+However, you can use an icon when hover text is the only
+available way to describe a UI element. For example, **Delete** or **Edit** buttons
+often have hover text only.
+
+When you do use an icon, start with the hover text and follow it with the SVG reference in parentheses.
+
+- Avoid: `Select **{pencil}** **Edit**.` This generates as: Select **{pencil}** **Edit**.
+- Use instead: `Select **Edit** (**{pencil}**).` This generates as: Select **Edit** (**{pencil}**).
+
+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}**).
+
## Videos
Adding GitLab YouTube video tutorials to the documentation is highly
@@ -1187,28 +1208,6 @@ different mobile devices.
`/help`, because the GitLab Markdown processor doesn't support iframes. It's
hidden on the documentation site, but is displayed by `/help`.
-## GitLab SVG icons
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) in GitLab 12.7.
-
-You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/)
-directly in the documentation. For example, `**{tanuki}**` renders as: **{tanuki}**.
-
-In most cases, you should avoid using the icons in text.
-However, you can use an icon when hover text is the only
-available way to describe a UI element. For example, **Delete** or **Edit** buttons
-often have hover text only.
-
-When you do use an icon, start with the hover text and follow it with the SVG reference in parentheses.
-
-- Avoid: `Select **{pencil}** **Edit**.` This generates as: Select **{pencil}** **Edit**.
-- Use instead: `Select **Edit** (**{pencil}**).` This generates as: Select **Edit** (**{pencil}**).
-
-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}**).
-
## Alert boxes
Use alert boxes to call attention to information. Use them sparingly, and never have an alert box immediately follow another alert box.
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index c753c39b727..1976caefc8e 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -239,6 +239,13 @@ Use **CI/CD minutes** instead of **CI minutes**, **pipeline minutes**, **pipelin
Do not use **click**. Instead, use **select** with buttons, links, menu items, and lists.
**Select** applies to more devices, while **click** is more specific to a mouse.
+## cloud native
+
+When you're talking about using a Kubernetes cluster to host GitLab, you're talking about a **cloud-native version of GitLab**.
+This version is different than the larger, more monolithic **Omnibus package** that is used to deploy GitLab.
+
+You can also use **cloud-native GitLab** for short. It should be hyphenated and lowercase.
+
## collapse
Use **collapse** instead of **close** when you are talking about expanding or collapsing a section in the UI.
@@ -434,6 +441,17 @@ Do not make **GitLab** possessive (GitLab's). This guidance follows [GitLab Trad
**GitLab.com** refers to the GitLab instance managed by GitLab itself.
+## GitLab Helm chart, GitLab chart
+
+To deploy a cloud-native version of GitLab, use:
+
+- The GitLab Helm chart (long version)
+- The GitLab chart (short version)
+
+Do not use **the `gitlab` chart**, **the GitLab Chart**, or **the cloud-native chart**.
+
+You use the **GitLab Helm chart** to deploy **cloud-native GitLab** in a Kubernetes cluster.
+
## GitLab Flavored Markdown
When possible, spell out [**GitLab Flavored Markdown**](../../../user/markdown.md).
@@ -1127,7 +1145,7 @@ in present tense, active voice.
## you, your, yours
Use **you**, **your**, and **yours** instead of [**the user** and **the user's**](#user-users).
-Documentation should be from the [point of view](https://design.gitlab.com/content/voice-tone#point-of-view) of the reader.
+Documentation should be from the [point of view](https://design.gitlab.com/content/voice-tone/#point-of-view) of the reader.
Use:
diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md
index d55cbe28d9b..428a57a11fb 100644
--- a/doc/development/documentation/testing.md
+++ b/doc/development/documentation/testing.md
@@ -81,6 +81,36 @@ This requires you to either:
### Documentation link tests
+Merge requests containing changes to Markdown (`.md`) files run a `docs-lint links`
+job, which runs two types of link checks. In both cases, links with destinations
+that begin with `http` or `https` are considered external links, and skipped:
+
+- `bundle exec nanoc check internal_links`: Tests links to internal pages.
+- `bundle exec nanoc check internal_anchors`: Tests links to subheadings (anchors) on internal pages.
+
+Failures from these tests are displayed at the end of the test results in the **Issues found!** area.
+For example, failures in the `internal_anchors` test follow this format:
+
+```plaintext
+[ ERROR ] internal_anchors - Broken anchor detected!
+ - source file `/tmp/gitlab-docs/public/ee/user/application_security/api_fuzzing/index.html`
+ - destination `/tmp/gitlab-docs/public/ee/development/code_review.html`
+ - link `../../../development/code_review.html#review-response-slo`
+ - anchor `#review-response-slo`
+```
+
+- **Source file**: The full path to the file containing the error. To find the
+ file in the `gitlab` repository, replace `/tmp/gitlab-docs/public/ee` with `doc`, and `.html` with `.md`.
+- **Destination**: The full path to the file not found by the test. To find the
+ file in the `gitlab` repository, replace `/tmp/gitlab-docs/public/ee` with `doc`, and `.html` with `.md`.
+- **Link**: The actual link the script attempted to find.
+- **Anchor**: If present, the subheading (anchor) the script attempted to find.
+
+Check for multiple instances of the same broken link on each page reporting an error.
+Even if a specific broken link appears multiple times on a page, the test reports it only once.
+
+#### Run document link tests locally
+
To execute documentation link tests locally:
1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory.
@@ -219,12 +249,12 @@ You can use markdownlint:
### Vale
-[Vale](https://docs.errata.ai/vale/about/) is a grammar, style, and word usage linter for the
+[Vale](https://vale.sh/) is a grammar, style, and word usage linter for the
English language. Vale's configuration is stored in the
[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.vale.ini) file located in the root
directory of projects.
-Vale supports creating [custom tests](https://docs.errata.ai/vale/styles) that extend any of
+Vale supports creating [custom tests](https://vale.sh/docs/topics/styles/) that extend any of
several types of checks, which we store in the `.linting/vale/styles/gitlab` directory in the
documentation directory of projects.
@@ -241,7 +271,7 @@ This configuration is also used in build pipelines, where
You can use Vale:
-- [On the command line](https://docs.errata.ai/vale/cli).
+- [On the command line](https://vale.sh/docs/vale-cli/structure/).
- [In a code editor](#configure-editors).
- [In a Git hook](#configure-pre-push-hooks). Vale only reports errors in the Git hook (the same
configuration as the CI/CD pipelines), and does not report suggestions or warnings.
@@ -250,7 +280,8 @@ You can use Vale:
Vale returns three types of results:
-- **Error** - For branding and trademark issues, and words or phrases with ambiguous meanings.
+- **Error** - For branding guidelines, trademark guidelines, and anything that causes content on
+ the docs site to render incorrectly.
- **Warning** - For Technical Writing team style preferences.
- **Suggestion** - For basic technical writing tenets and best practices.
@@ -304,7 +335,30 @@ For example, a page that scores `12` before a set of changes, and `9` after, ind
general complexity level of the page.
The readability score is calculated based on the number of words per sentence, and the number
-of syllables per word. For more information, see [the Vale documentation](https://docs.errata.ai/vale/styles#metric).
+of syllables per word. For more information, see [the Vale documentation](https://vale.sh/docs/topics/styles/#metric).
+
+#### When to add a new Vale rule
+
+It's tempting to add a Vale rule for every style guide rule. However, we should be
+mindful of the effort to create and enforce a Vale rule, and the noise it creates.
+
+In general, follow these guidelines:
+
+- If you add an [error-level Vale rule](#vale-result-types), you must fix
+ the existing occurrences of the issue in the documentation before you can add the rule.
+
+ If there are too many issues to fix in a single merge request, add the rule at a
+ `warning` level. Then, fix the existing issues in follow-up merge requests.
+ When the issues are fixed, promote the rule to an `error`.
+
+- If you add a warning-level or suggestion-level rule, consider:
+
+ - How many more warnings or suggestions it creates in the Vale output. If the
+ number of additional warnings is significant, the rule might be too broad.
+
+ - How often an author might ignore it because it's acceptable in the context.
+ If the rule is too subjective, it cannot be adequately enforced and creates
+ unnecessary additional warnings.
### Install linters
@@ -399,8 +453,6 @@ To configure Vale in your editor, install one of the following as appropriate:
In this setup the `markdownlint` checker is set as a "next" checker from the defined `vale` checker.
Enabling this custom Vale checker provides error linting from both Vale and markdownlint.
-We don't use [Vale Server](https://docs.errata.ai/vale-server/install).
-
### Configure pre-push hooks
Git [pre-push hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) allow Git users to:
@@ -479,7 +531,7 @@ document:
Whenever possible, exclude only the problematic rule and lines.
For more information, see
-[Vale's documentation](https://docs.errata.ai/vale/scoping#markup-based-configuration).
+[Vale's documentation](https://vale.sh/docs/topics/scoping/).
### Disable markdownlint tests
diff --git a/doc/development/documentation/versions.md b/doc/development/documentation/versions.md
index 067c37d30aa..3679c731a77 100644
--- a/doc/development/documentation/versions.md
+++ b/doc/development/documentation/versions.md
@@ -182,7 +182,7 @@ GitLab supports the current major version and two previous major versions.
For example, if 15.0 is the current major version, all major and minor releases of
GitLab 15.0, 14.0, and 13.0 are supported.
-[View the list of supported versions](https://about.gitlab.com/support/statement-of-support.html#version-support).
+[View the list of supported versions](https://about.gitlab.com/support/statement-of-support/#version-support).
If you see version history items or inline text that refers to unsupported versions, you can remove it.
@@ -198,8 +198,8 @@ We cannot guarantee future feature work, and promises
like these can raise legal issues. Instead, say that an issue exists.
For example:
-- Support for improvements is tracked `[in this issue](LINK)`.
-- You cannot do this thing, but `[an issue exists](LINK)` to change this behavior.
+- Support for improvements is proposed in issue `[issue-number](LINK-TO-ISSUE)`.
+- You cannot do this thing, but issue `[issue-number](LINK-TO-ISSUE)` proposes to change this behavior.
You can say that we plan to remove a feature.
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 28cf6d4e1e3..777bc77875e 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -6,8 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Guidelines for implementing Enterprise Edition features
-- **Write the code and the tests.**: As with any code, EE features should have
- good test coverage to prevent regressions.
+- **Place code in `ee/`**: Put all Enterprise Edition (EE) inside the `ee/` top-level directory. The
+ rest of the code must be as close to the Community Edition (CE) files as possible.
+- **Write tests**: As with any code, EE features must have good test coverage to prevent
+ regressions. All `ee/` code must have corresponding tests in `ee/`.
- **Write documentation.**: Add documentation to the `doc/` directory. Describe
the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide/index.md#product-tier-badges)
the feature applies to.
@@ -16,54 +18,72 @@ info: To determine the technical writer assigned to the Stage/Group associated w
[EE features list](https://about.gitlab.com/features/).
<!-- markdownlint-enable MD044 -->
-## Act as SaaS
+## Implement a new EE feature
-When developing locally, there are times when you need your instance to act like the SaaS version of the product.
-In those instances, you can simulate SaaS by exporting an environment variable as seen below:
+If you're developing a GitLab Starter, GitLab Premium, or GitLab Ultimate licensed feature, use these steps to
+add your new feature or extend it.
-```shell
-export GITLAB_SIMULATE_SAAS=1
-```
+GitLab license features are added to [`ee/app/models/gitlab_subscriptions/features.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/gitlab_subscriptions/features.rb). To determine how
+to modify this file, first discuss how your feature fits into our licensing with your Product Manager.
-There are many ways to pass an environment variable to your local GitLab instance.
-For example, you can create a `env.runit` file in the root of your GDK with the above snippet.
+Use the following questions to guide you:
-## Act as CE when unlicensed
+1. Is this a new feature, or are you extending an existing licensed feature?
+ - If your feature already exists, you don't have to modify `features.rb`, but you
+ must locate the existing feature identifier to [guard it](#guard-your-ee-feature).
+ - If this is a new feature, decide on an identifier, such as `my_feature_name`, to add to the
+ `features.rb` file.
+1. Is this a **GitLab Starter**, **GitLab Premium**, or **GitLab Ultimate** feature?
+ - Based on the plan you choose to use the feature in, add the feature identifier to `STARTER_FEATURES`,
+ `PREMIUM_FEATURES`, or `ULTIMATE_FEATURES`.
+1. Will this feature be available globally (system-wide at the GitLab instance level)?
+ - Features such as [Geo](../administration/geo/index.md) and
+ [Database Load Balancing](../administration/postgresql/database_load_balancing.md) are used by the entire instance
+ and cannot be restricted to individual user namespaces. These features are defined in the instance license.
+ Add these features to `GLOBAL_FEATURES`.
-Since the implementation of
-[GitLab CE features to work with unlicensed EE instance](https://gitlab.com/gitlab-org/gitlab/-/issues/2500)
-GitLab Enterprise Edition should work like GitLab Community Edition
-when no license is active. So EE features always should be guarded by
-`project.feature_available?` or `group.licensed_feature_available?` (or
-`License.feature_available?` if it is a system-wide feature).
+### Guard your EE feature
-Frontend features should be guarded by pushing a flag from the backend by [using `push_licensed_feature`](licensed_feature_availability.md#restricting-frontend-features), and checked using `this.glFeatures.someFeature` in the frontend. For example:
+A licensed feature can only be available to licensed users. You must add a check or guard
+to determine if users have access to the feature.
-```html
-<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+To guard your licensed feature:
-export default {
- mixins: [glFeatureFlagMixin()],
- components: {
- EEComponent: () => import('ee_component/components/test.vue'),
- },
- computed: {
- shouldRenderComponent() {
- return this.glFeatures.myEEFeature;
- }
- },
-};
-</script>
+1. Locate your feature identifier in `ee/app/models/gitlab_subscriptions/features.rb`.
+1. Use the following methods, where `my_feature_name` is your feature
+ identifier:
-<template>
- <div>
- <ee-component v-if="shouldRenderComponent"/>
- </div>
-</template>
-```
+ - In a project context:
+
+ ```ruby
+ my_project.licensed_feature_available?(:my_feature_name) # true if available for my_project
+ ```
+
+ - In a group or user namespace context:
+
+ ```ruby
+ my_group.licensed_feature_available?(:my_feature_name) # true if available for my_group
+ ```
-Look in `ee/app/models/license.rb` for the names of the licensed features.
+ - For a global (system-wide) feature:
+
+ ```ruby
+ License.feature_available?(:my_feature_name) # true if available in this instance
+ ```
+
+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:
+
+ ```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
+ ```
+
+### Simulate a CE instance when unlicensed
+
+After the implementation of
+[GitLab CE features to work with unlicensed EE instance](https://gitlab.com/gitlab-org/gitlab/-/issues/2500)
+GitLab Enterprise Edition works like GitLab Community Edition
+when no license is active.
CE specs should remain untouched as much as possible and extra specs
should be added for EE. Licensed features can be stubbed using the
@@ -74,7 +94,7 @@ setting the [`FOSS_ONLY` environment variable](https://gitlab.com/gitlab-org/git
to something that evaluates as `true`. The same works for running tests
(for example `FOSS_ONLY=1 yarn jest`).
-### Running feature specs as CE
+#### Run feature specs as CE
When running [feature specs](testing_guide/best_practices.md#system--feature-tests)
as CE, you should ensure that the edition of backend and frontend match.
@@ -98,7 +118,28 @@ To do so:
bin/rspec spec/features/<path_to_your_spec>
```
-## CI pipelines in a FOSS context
+### Simulate a SaaS instance
+
+If you're developing locally and need your instance to act like the SaaS version of the product,
+you can simulate SaaS by exporting an environment variable:
+
+```shell
+export GITLAB_SIMULATE_SAAS=1
+```
+
+There are many ways to pass an environment variable to your local GitLab instance.
+For example, you can create a `env.runit` file in the root of your GDK with the above snippet.
+
+#### Allow use of licensed EE feature
+
+To enable plans per namespace turn on the `Allow use of licensed EE features` option from the settings page.
+This will make licensed EE features available to projects only if the project namespace's plan includes the feature
+or if the project is public. To enable it:
+
+1. If you are developing locally, follow the steps in [Simulate a SaaS instance](#simulate-a-saas-instance) to make the option available.
+1. Visit Admin > Settings > General > "Account and limit" and enable "Allow use of licensed EE features".
+
+### Run CI pipelines in a FOSS context
By default, merge request pipelines for development run in an EE-context only. If you are
developing features that differ between FOSS and EE, you may wish to run pipelines in a
@@ -108,10 +149,7 @@ To run pipelines in both contexts, add the `~"pipeline:run-as-if-foss"` label to
See the [As-if-FOSS jobs](pipelines.md#as-if-foss-jobs) pipelines documentation for more information.
-## Separation of EE code
-
-All EE code should be put inside the `ee/` top-level directory. The
-rest of the code should be as close to the CE files as possible.
+## Separation of EE code in the backend
### EE-only features
@@ -144,7 +182,7 @@ To test an EE class that doesn't exist in CE, create the spec file as you normal
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`.
-### EE features based on CE features
+### Extend CE features with EE backend code
For features that build on existing CE features, write a module in the `EE`
namespace and inject it in the CE class, on the last line of the file that the
@@ -243,8 +281,8 @@ There are a few gotchas with it:
overriding the method, because we can't know when the overridden method
(that is, calling `super` in the overriding method) would want to stop early.
In this case, we shouldn't just override it, but update the original method
- to make it call the other method we want to extend, like a [template method
- pattern](https://en.wikipedia.org/wiki/Template_method_pattern).
+ to make it call the other method we want to extend, like a
+ [template method pattern](https://en.wikipedia.org/wiki/Template_method_pattern).
For example, given this base:
```ruby
@@ -633,7 +671,7 @@ might need different strategies to extend it. To apply different strategies
easily, we would use `extend ActiveSupport::Concern` in the EE module.
Put the EE module files following
-[EE features based on CE features](#ee-features-based-on-ce-features).
+[Extend CE features with EE backend code](#extend-ce-features-with-ee-backend-code).
#### EE API routes
@@ -1009,9 +1047,9 @@ FactoryBot.define do
end
```
-## JavaScript code in `assets/javascripts/`
+## Separate of EE code in the frontend
-To separate EE-specific JS-files we should also move the files into an `ee` folder.
+To separate EE-specific JS-files, move the files into an `ee` folder.
For example there can be an
`app/assets/javascripts/protected_branches/protected_branches_bundle.js` and an
@@ -1032,40 +1070,123 @@ import bundle from 'ee/protected_branches/protected_branches_bundle.js';
import bundle from 'ee_else_ce/protected_branches/protected_branches_bundle.js';
```
-See the frontend guide [performance section](fe_guide/performance.md) for
-information on managing page-specific JavaScript within EE.
+### Add new EE-only features in the frontend
+
+If the feature being developed is not present in CE, add your entry point in
+`ee/`. For example:
+
+```shell
+# Add HTML element to mount
+ee/app/views/admin/geo/designs/index.html.haml
+
+# Init the application
+ee/app/assets/javascripts/pages/ee_only_feature/index.js
+
+# Mount the feature
+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
+
+Add your EE tests to `ee/spec/frontend/` following the same directory structure you use for CE.
+
+### Extend CE features with EE frontend code
+
+Use the [`push_licensed_feature`](#guard-your-ee-feature) to guard frontend features that extend
+existing views:
+
+```ruby
+# ee/app/controllers/ee/admin/my_controller.rb
+before_action do
+ push_licensed_feature(:my_feature_name) # for global features
+end
+```
+
+```ruby
+# ee/app/controllers/ee/group/my_controller.rb
+before_action do
+ push_licensed_feature(:my_feature_name, @group) # for group pages
+end
+```
+
+```ruby
+# ee/app/controllers/ee/project/my_controller.rb
+before_action do
+ push_licensed_feature(:my_feature_name, @group) # for group pages
+ push_licensed_feature(:my_feature_name, @project) # for project pages
+end
+```
+
+Verify your feature appears in `gon.licensed_features` in the browser console.
-## Vue code in `assets/javascript`
+#### Extend Vue applications with EE Vue components
-### script tag
+EE licensed features that enhance existing functionality in the UI add new
+elements or interactions to your Vue application as components.
-#### Child Component only used in EE
+To separate template differences, use a child EE component to separate Vue template differences.
+You must import the EE component [asynchronously](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
-To separate Vue template differences we should [import the components asynchronously](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
+This allows GitLab to load the correct component in EE, while in CE GitLab loads an empty component
+that renders nothing. This code **must** exist in the CE repository, in addition to the EE repository.
-Doing this allows for us to load the correct component in EE while in CE
-we can load a empty component that renders nothing. This code **should**
-exist in the CE repository as well as the EE repository.
+A CE component acts as the entry point to your EE feature. To add a EE component,
+locate it the `ee/` directory and add it with `import('ee_component/...')`:
```html
<script>
+// app/assets/javascripts/feature/components/form.vue
+
export default {
+ mixins: [glFeatureFlagMixin()],
components: {
- EEComponent: () => import('ee_component/components/test.vue'),
+ // Import an EE component from CE
+ MyEeComponent: () => import('ee_component/components/my_ee_component.vue'),
},
};
</script>
<template>
<div>
- <ee-component />
+ <!-- ... -->
+ <my-ee-component/>
+ <!-- ... -->
</div>
</template>
```
-#### For JS code that is EE only, like props, computed properties, methods, etc
+Check `glFeatures` to ensure that the Vue components are guarded. The components render only when
+the license is present.
-- Please do not use mixins unless ABSOLUTELY NECESSARY. Please try to find an alternative pattern.
+```html
+<script>
+// ee/app/assets/javascripts/feature/components/special_component.vue
+
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+export default {
+ mixins: [glFeatureFlagMixin()],
+ computed: {
+ shouldRenderComponent() {
+ // Comes from gon.licensed_features as a camel-case version of `my_feature_name`
+ return this.glFeatures.myFeatureName;
+ }
+ },
+};
+</script>
+
+<template>
+ <div v-if="shouldRenderComponent">
+ <!-- EE licensed feature UI -->
+ </div>
+</template>
+```
+
+NOTE:
+Do not use mixins unless ABSOLUTELY NECESSARY. Try to find an alternative pattern.
##### Recommended alternative approach (named/scoped slots)
@@ -1138,11 +1259,65 @@ export default {
**For EE components that need different results for the same computed values, we can pass in props to the CE wrapper as seen in the example.**
- **EE Child components**
- - Since we are using the asynchronous loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
+ - Since we are using the asynchronous loading to check which component to load, we'd still use the component's name, check [this example](#extend-vue-applications-with-ee-vue-components).
- **EE extra HTML**
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
+#### Extend other JS code
+
+To extend JS files, complete the following steps:
+
+1. Use the `ee_else_ce` helper, where that EE only code must be inside the `ee/` folder.
+ 1. Create an EE file with only the EE, and extend the CE counterpart.
+ 1. For code inside functions that can't be extended, move the code to a new file and use `ee_else_ce` helper:
+
+```javascript
+ import eeCode from 'ee_else_ce/ee_code';
+
+ function test() {
+ const test = 'a';
+
+ eeCode();
+
+ return test;
+ }
+```
+
+In some cases, you'll need to extend other logic in your application. To extend your JS
+modules, create an EE version of the file and extend it with your custom logic:
+
+```javascript
+// app/assets/javascripts/feature/utils.js
+
+export const myFunction = () => {
+ // ...
+};
+
+// ... other CE functions ...
+```
+
+```javascript
+// ee/app/assets/javascripts/feature/utils.js
+import {
+ myFunction as ceMyFunction,
+} from '~/feature/utils';
+
+/* eslint-disable import/export */
+
+// Export same utils as CE
+export * from '~/feature/utils';
+
+// Only override `myFunction`
+export const myFunction = () => {
+ const result = ceMyFunction();
+ // add EE feature logic
+ return result;
+};
+
+/* eslint-enable import/export */
+```
+
#### Testing modules using EE/CE aliases
When writing Frontend tests, if the module under test imports other modules with `ee_else_ce/...` and these modules are also needed by the relevant test, then the relevant test **must** import these modules with `ee_else_ce/...`. This avoids unexpected EE or FOSS failures, and helps ensure the EE behaves like CE when it is unlicensed.
@@ -1185,29 +1360,7 @@ describe('ComponentUnderTest', () => {
```
-### Non Vue Files
-
-For regular JS files, the approach is similar.
-
-1. We keep using the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) helper, this means that EE only code should be inside the `ee/` folder.
- 1. An EE file should be created with the EE only code, and it should extend the CE counterpart.
- 1. For code inside functions that can't be extended, the code should be moved into a new file and we should use `ee_else_ce` helper:
-
-#### Example
-
-```javascript
- import eeCode from 'ee_else_ce/ee_code';
-
- function test() {
- const test = 'a';
-
- eeCode();
-
- return test;
- }
-```
-
-## SCSS code in `assets/stylesheets`
+#### SCSS code in `assets/stylesheets`
If a component you're adding styles for is limited to EE, it is better to have a
separate SCSS file in an appropriate directory within `app/assets/stylesheets`.
@@ -1218,9 +1371,8 @@ styles are usually kept in a stylesheet that is common for both CE and EE, and i
to isolate such ruleset from rest of CE rules (along with adding comment describing the same)
to avoid conflicts during CE to EE merge.
-### Bad
-
```scss
+// Bad
.section-body {
.section-title {
background: $gl-header-color;
@@ -1234,9 +1386,8 @@ to avoid conflicts during CE to EE merge.
}
```
-### Good
-
```scss
+// Good
.section-body {
.section-title {
background: $gl-header-color;
@@ -1252,7 +1403,7 @@ to avoid conflicts during CE to EE merge.
// EE-specific end
```
-## GitLab-svgs
+### GitLab-svgs
Conflicts in `app/assets/images/icons.json` or `app/assets/images/icons.svg` can
be resolved simply by regenerating those assets with
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index d32ceb43ce9..47942817790 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -38,7 +38,7 @@ Additionally, if you need large repositories or multiple forks for testing, plea
The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a Rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [`/ee/app/models/concerns/elastic/application_versioned_search.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/concerns/elastic/application_versioned_search.rb).
-After initial indexing is complete, create, update, and delete operations for all models except projects (see [#207494](https://gitlab.com/gitlab-org/gitlab/-/issues/207494)) are tracked in a Redis [`ZSET`](https://redis.io/topics/data-types#sorted-sets). A regular `sidekiq-cron` `ElasticIndexBulkCronWorker` processes this queue, updating many Elasticsearch documents at a time with the [Bulk Request API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html).
+After initial indexing is complete, create, update, and delete operations for all models except projects (see [#207494](https://gitlab.com/gitlab-org/gitlab/-/issues/207494)) are tracked in a Redis [`ZSET`](https://redis.io/docs/manual/data-types/#sorted-sets). A regular `sidekiq-cron` `ElasticIndexBulkCronWorker` processes this queue, updating many Elasticsearch documents at a time with the [Bulk Request API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html).
Search queries are generated by the concerns found in [`ee/app/models/concerns/elastic`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/app/models/concerns/elastic). These concerns are also in charge of access control, and have been a historic source of security bugs so please pay close attention to them!
@@ -277,8 +277,8 @@ These Advanced Search migrations, like any other GitLab changes, need to support
Depending on the order of deployment, it's possible that the migration
has started or finished and there's still a server running the application code from before the
-migration. We need to take this into consideration until we can [ensure all Advanced Search migrations
-start after the deployment has finished](https://gitlab.com/gitlab-org/gitlab/-/issues/321619).
+migration. We need to take this into consideration until we can
+[ensure all Advanced Search migrations start after the deployment has finished](https://gitlab.com/gitlab-org/gitlab/-/issues/321619).
### Reverting a migration
@@ -317,9 +317,8 @@ safely can.
We choose to use GitLab major version upgrades as a safe time to remove
backwards compatibility for indices that have not been fully migrated. We
-[document this in our upgrade
-documentation](../update/index.md#upgrading-to-a-new-major-version). We also
-choose to replace the migration code with the halted migration
+[document this in our upgrade documentation](../update/index.md#upgrading-to-a-new-major-version).
+We also choose to replace the migration code with the halted migration
and remove tests so that:
- We don't need to maintain any code that is called from our Advanced Search
@@ -381,7 +380,7 @@ the volume of updates.
All of the indexing happens in Sidekiq, so much of the relevant logs for the
Elasticsearch integration can be found in
-[`sidekiq.log`](../administration/logs.md#sidekiqlog). In particular, all
+[`sidekiq.log`](../administration/logs/index.md#sidekiqlog). In particular, all
Sidekiq workers that make requests to Elasticsearch in any way will log the
number of requests and time taken querying/writing to Elasticsearch. This can
be useful to understand whether or not your cluster is keeping up with
@@ -390,26 +389,25 @@ indexing.
Searching Elasticsearch is done via ordinary web workers handling requests. Any
requests to load a page or make an API request, which then make requests to
Elasticsearch, will log the number of requests and the time taken to
-[`production_json.log`](../administration/logs.md#production_jsonlog). These
+[`production_json.log`](../administration/logs/index.md#production_jsonlog). These
logs will also include the time spent on Database and Gitaly requests, which
may help to diagnose which part of the search is performing poorly.
There are additional logs specific to Elasticsearch that are sent to
-[`elasticsearch.log`](../administration/logs.md#elasticsearchlog)
+[`elasticsearch.log`](../administration/logs/index.md#elasticsearchlog)
that may contain information to help diagnose performance issues.
### Performance Bar
-Elasticsearch requests will be displayed in the [`Performance
-Bar`](../administration/monitoring/performance/performance_bar.md), which can
+Elasticsearch requests will be displayed in the
+[`Performance Bar`](../administration/monitoring/performance/performance_bar.md), which can
be used both locally in development and on any deployed GitLab instance to
diagnose poor search performance. This will show the exact queries being made,
which is useful to diagnose why a search might be slow.
### Correlation ID and `X-Opaque-Id`
-Our [correlation
-ID](distributed_tracing.md#developer-guidelines-for-working-with-correlation-ids)
+Our [correlation ID](distributed_tracing.md#developer-guidelines-for-working-with-correlation-ids)
is forwarded by all requests from Rails to Elasticsearch as the
[`X-Opaque-Id`](https://www.elastic.co/guide/en/elasticsearch/reference/current/tasks.html#_identifying_running_tasks)
header which allows us to track any
@@ -477,13 +475,13 @@ documented here in case it is useful for others. The relevant logs that could
theoretically be used to figure out what needs to be replayed are:
1. All non-repository updates that were synced can be found in
- [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by
+ [`elasticsearch.log`](../administration/logs/index.md#elasticsearchlog) by
searching for
[`track_items`](https://gitlab.com/gitlab-org/gitlab/-/blob/1e60ea99bd8110a97d8fc481e2f41cab14e63d31/ee/app/services/elastic/process_bookkeeping_service.rb#L25)
and these can be replayed by sending these items again through
`::Elastic::ProcessBookkeepingService.track!`
1. All repository updates that occurred can be found in
- [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by
+ [`elasticsearch.log`](../administration/logs/index.md#elasticsearchlog) by
searching for
[`indexing_commit_range`](https://gitlab.com/gitlab-org/gitlab/-/blob/6f9d75dd3898536b9ec2fb206e0bd677ab59bd6d/ee/lib/gitlab/elastic/indexer.rb#L41).
Replaying these requires resetting the
@@ -492,13 +490,13 @@ theoretically be used to figure out what needs to be replayed are:
the project using
[`ElasticCommitIndexerWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_commit_indexer_worker.rb)
1. All project deletes that occurred can be found in
- [`sidekiq.log`](../administration/logs.md#sidekiqlog) by searching for
+ [`sidekiq.log`](../administration/logs/index.md#sidekiqlog) by searching for
[`ElasticDeleteProjectWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_delete_project_worker.rb).
These updates can be replayed by triggering another
`ElasticDeleteProjectWorker`.
-With the above methods and taking regular [Elasticsearch
-snapshots](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html)
+With the above methods and taking regular
+[Elasticsearch snapshots](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html)
we should be able to recover from different kinds of data loss issues in a
relatively short period of time compared to indexing everything from
scratch.
diff --git a/doc/development/emails.md b/doc/development/emails.md
index a5c2789a3ea..1b3c9226dd8 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -60,7 +60,7 @@ See the [Rails guides](https://guides.rubyonrails.org/action_mailer_basics.html#
# The email address including the %{key} placeholder that will be replaced to reference the
# item being replied to. This %{key} should be included in its entirety within the email
# address and not replaced by another value.
- # For example: emailadress+%{key}@gmail.com.
+ # For example: emailaddress+%{key}@gmail.com.
# The placeholder must appear in the "user" part of the address (before the `@`). It can be omitted but some features,
# including Service Desk, may not work properly.
address: "gitlab-incoming+%{key}@gmail.com"
@@ -160,9 +160,10 @@ and Helm Chart configuration (see [example merge request](https://gitlab.com/git
#### Rationale
This was done because to avoid [thread deadlocks](https://github.com/ruby/net-imap/issues/14), `MailRoom` needs
-an updated version of the `net-imap` gem. However, this [version of the net-imap cannot be installed by an unprivileged
-user](https://github.com/ruby/net-imap/issues/14) due to [an error installing the digest
-gem](https://github.com/ruby/digest/issues/14). [This bug in the Ruby interpreter](https://bugs.ruby-lang.org/issues/17761) was fixed in Ruby
+an updated version of the `net-imap` gem. However, this
+[version of the net-imap cannot be installed by an unprivileged user](https://github.com/ruby/net-imap/issues/14) due to
+[an error installing the digest gem](https://github.com/ruby/digest/issues/14).
+[This bug in the Ruby interpreter](https://bugs.ruby-lang.org/issues/17761) was fixed in Ruby
3.0.2.
Updating the gem directly in the GitLab Rails `Gemfile` caused a [production incident](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4053)
diff --git a/doc/development/event_store.md b/doc/development/event_store.md
index ffde51216cf..37035083e23 100644
--- a/doc/development/event_store.md
+++ b/doc/development/event_store.md
@@ -223,6 +223,15 @@ Gitlab::EventStore.publish(
)
```
+Events should be dispatched from the relevant Service class whenever possible. Some
+exceptions exist where we may allow models to publish events, like in state machine transitions.
+For example, instead of scheduling `Ci::BuildFinishedWorker`, which runs a collection of side effects,
+we could publish a `Ci::BuildFinishedEvent` and let other domains react asynchronously.
+
+`ActiveRecord` callbacks are too low-level to represent a domain event. They represent more database
+record changes. There might be cases where it would make sense, but we should consider
+those exceptions.
+
## Create a subscriber
A subscriber is a Sidekiq worker that includes the `Gitlab::EventStore::Subscriber` module.
@@ -320,7 +329,7 @@ it 'publishes a ProjectCreatedEvent with project id and namespace id' do
# The project ID will only be generated when the `create_project`
# is called in the expect block.
expected_data = { project_id: kind_of(Numeric), namespace_id: group_id }
-
+
expect { create_project(user, name: 'Project', path: 'project', namespace_id: group_id) }
.to publish_event(Projects::ProjectCreatedEvent)
.with(expected_data)
diff --git a/doc/development/fe_guide/accessibility.md b/doc/development/fe_guide/accessibility.md
index 2a1083d031f..bdd6c5d6e84 100644
--- a/doc/development/fe_guide/accessibility.md
+++ b/doc/development/fe_guide/accessibility.md
@@ -13,7 +13,7 @@ This page contains guidelines we should follow.
## Quick summary
-Since [no ARIA is better than bad ARIA](https://www.w3.org/TR/wai-aria-practices/#no_aria_better_bad_aria),
+Since [no ARIA is better than bad ARIA](https://w3c.github.io/aria-practices/#no_aria_better_bad_aria),
review the following recommendations before using `aria-*`, `role`, and `tabindex`.
Use semantic HTML, which has accessibility semantics baked in, and ideally test with
[relevant combinations of screen readers and browsers](https://www.accessibility-developer-guide.com/knowledge/screen-readers/relevant-combinations/).
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index afaf6df8f8a..1d08296eafc 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -11,7 +11,7 @@ When developing a feature that requires architectural design, or changing the fu
A Frontend Architect is an expert who makes high-level Frontend design decisions
and decides on technical standards, including coding standards and frameworks.
-Architectural decisions should be accessible to everyone, so please document
+Architectural decisions should be accessible to everyone, so document
them in the relevant Merge Request discussion or by updating our documentation
when appropriate.
@@ -19,7 +19,7 @@ You can find the Frontend Architecture experts on the [team page](https://about.
## Widget Architecture
-The [Plan stage](https://about.gitlab.com/handbook/engineering/development/dev/fe-plan/)
+The [Plan stage](https://about.gitlab.com/handbook/engineering/development/dev/plan-project-management/)
is refactoring the right sidebar to consist of **widgets**. They have a specific architecture to be
reusable and to expose an interface that can be used by external Vue applications on the page.
Learn more about the [widget architecture](widgets.md).
diff --git a/doc/development/fe_guide/content_editor.md b/doc/development/fe_guide/content_editor.md
index d4c29cb8a24..f262e48b6da 100644
--- a/doc/development/fe_guide/content_editor.md
+++ b/doc/development/fe_guide/content_editor.md
@@ -296,6 +296,7 @@ const builtInContentEditorExtensions = [
Dropcursor,
Emoji,
// Other extensions
+]
```
### The Markdown serializer
diff --git a/doc/development/fe_guide/design_anti_patterns.md b/doc/development/fe_guide/design_anti_patterns.md
index b7238bb2813..580f488bd33 100644
--- a/doc/development/fe_guide/design_anti_patterns.md
+++ b/doc/development/fe_guide/design_anti_patterns.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Anti-patterns may seem like good approaches at first, but it has been shown that they bring more ills than benefits. These should
generally be avoided.
-Throughout the GitLab codebase, there may be historic uses of these anti-patterns. Please [use discretion](https://about.gitlab.com/handbook/engineering/development/principles/#balance-refactoring-and-velocity)
+Throughout the GitLab codebase, there may be historic uses of these anti-patterns. [Use discretion](https://about.gitlab.com/handbook/engineering/development/principles/#balance-refactoring-and-velocity)
when figuring out whether or not to refactor, when touching code that uses one of these legacy patterns.
NOTE:
@@ -62,7 +62,7 @@ could be appropriate:
- When a responsibility is truly global and should be referenced across the application
(for example, an application-wide Event Bus).
-Even in these scenarios, please consider avoiding the Shared Global Object pattern because the
+Even in these scenarios, consider avoiding the Shared Global Object pattern because the
side-effects can be notoriously difficult to reason with.
### References
@@ -140,7 +140,7 @@ that a Singleton could be appropriate in the following rare cases:
- We need to manage some resource that **MUST** have just 1 instance (that is, some hardware restriction).
- There is a real [cross-cutting concern](https://en.wikipedia.org/wiki/Cross-cutting_concern) (for example, logging) and a Singleton provides the simplest API.
-Even in these scenarios, please consider avoiding the Singleton pattern.
+Even in these scenarios, consider avoiding the Singleton pattern.
### What alternatives are there to the Singleton pattern?
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index b4893fd4ef9..3273263de3b 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -16,7 +16,7 @@ Copy the content over to your issue or merge request and if something doesn't ap
This checklist is intended to help us during development of bigger features/refactorings. It is not a "use it always and every point always matches" list.
-Please use your best judgment when to use it and please contribute new points through merge requests if something comes to your mind.
+Use your best judgment when to use it and contribute new points through merge requests if something comes to your mind.
```markdown
### Frontend development
@@ -39,7 +39,7 @@ Please use your best judgment when to use it and please contribute new points th
- [ ] **Cookie Mode** Think about hiding the feature behind a cookie flag if the implementation is on top of existing features
- [ ] **New route** Are you refactoring something big then you might consider adding a new route where you implement the new feature and when finished delete the current route and rename the new one. (for example 'merge_request' and 'new_merge_request')
- [ ] **Setup** Is there any specific setup needed for your implementation (for example a kubernetes cluster)? Then let everyone know if it is not already mentioned where they can find documentation (if it doesn't exist - create it)
-- [ ] **Security** Are there any new security relevant implementations? Then please contact the security team for an app security review. If you are not sure ask our [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts)
+- [ ] **Security** Are there any new security relevant implementations? Then contact the security team for an app security review. If you are not sure ask our [domain expert](https://about.gitlab.com/handbook/engineering/frontend/#frontend-domain-experts)
#### During development
@@ -90,7 +90,7 @@ code that is unused:
### Merge Request Review
-With the purpose of being [respectful of others' time](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time) please follow these guidelines when asking for a review:
+With the purpose of being [respectful of others' time](https://about.gitlab.com/handbook/values/#be-respectful-of-others-time), follow these guidelines when asking for a review:
- Make sure your Merge Request:
- milestone is set
@@ -101,7 +101,7 @@ With the purpose of being [respectful of others' time](https://about.gitlab.com/
- includes tests
- includes a changelog entry (when necessary)
- Before assigning to a maintainer, assign to a reviewer.
-- If you assigned a merge request or pinged someone directly, be patient because we work in different timezones and asynchronously. Unless the merge request is urgent (like fixing a broken default branch), please don't DM or reassign the merge request before waiting for a 24-hour window.
+- If you assigned a merge request or pinged someone directly, be patient because we work in different timezones and asynchronously. Unless the merge request is urgent (like fixing a broken default branch), don't DM or reassign the merge request before waiting for a 24-hour window.
- If you have a question regarding your merge request/issue, make it on the merge request/issue. When we DM each other, we no longer have a SSOT and [no one else is able to contribute](https://about.gitlab.com/handbook/values/#public-by-default).
- When you have a big **Draft** merge request with many changes, you're advised to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewers/maintainers would always prioritize reviewing finished MRs before the **Draft** ones.
- Make sure to remove the `Draft:` title before the last round of review.
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index 39c39894dac..6a645416c0a 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Rules of Frontend FAQ
1. **You talk about Frontend FAQ.**
- Please share links to it whenever applicable, so more eyes catch when content
+ Share links to it whenever applicable, so more eyes catch when content
gets outdated.
1. **Keep it short and simple.**
Whenever an answer needs more than two sentences it does not belong here.
@@ -17,7 +17,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Linking to relevant source code, issue / epic, or other documentation helps
to understand the answer.
1. **If you see something, do something.**
- Please remove or update any content that is outdated as soon as you see it.
+ Remove or update any content that is outdated as soon as you see it.
## FAQ
@@ -101,7 +101,7 @@ axios.get(joinPaths(gon.gitlab_url, '-', 'foo'))
axios.get(joinPaths(gon.relative_url_root, '-', 'foo'))
```
-Also, please try not to hardcode paths in the Frontend, but instead receive them from the Backend (see next section).
+Also, try not to hardcode paths in the Frontend, but instead receive them from the Backend (see next section).
When referencing Backend rails paths, avoid using `*_url`, and use `*_path` instead.
Example:
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 10db332d64c..442dda20d23 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -14,7 +14,7 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
**General resources**:
- [📚 Official Introduction to GraphQL](https://graphql.org/learn/)
-- [📚 Official Introduction to Apollo](https://www.apollographql.com/docs/tutorial/introduction/)
+- [📚 Official Introduction to Apollo](https://www.apollographql.com/tutorials/fullstack-quickstart/introduction)
**GraphQL at GitLab**:
@@ -109,7 +109,7 @@ Default client accepts two parameters: `resolvers` and `config`.
If you are making multiple queries to the same Apollo client object you might encounter the following error: `Cache data may be lost when replacing the someProperty field of a Query object. To address this problem, either ensure all objects of SomeEntityhave an id or a custom merge function`. We are already checking `ID` presence for every GraphQL type that has an `ID`, so this shouldn't be the case. Most likely, the `SomeEntity` type doesn't have an `ID` property, and to fix this warning we need to define a custom merge function.
-We have some client-wide types with `merge: true` defined in the default client as [typePolicies](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/graphql.js) (this means that Apollo will merge existing and incoming responses in the case of subsequent queries). Please consider adding `SomeEntity` there or defining a custom merge function for it.
+We have some client-wide types with `merge: true` defined in the default client as [typePolicies](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/graphql.js) (this means that Apollo will merge existing and incoming responses in the case of subsequent queries). Consider adding `SomeEntity` there or defining a custom merge function for it.
## GraphQL Queries
@@ -212,7 +212,7 @@ with a **new and updated** object.
To facilitate the process of updating the cache and returning the new object we
use the library [Immer](https://immerjs.github.io/immer/).
-Please, follow these conventions:
+Follow these conventions:
- The updated cache is named `data`.
- The original cache data is named `sourceData`.
@@ -597,7 +597,7 @@ export default {
Note that, even if the directive evaluates to `false`, the guarded entity is sent to the backend and
matched against the GraphQL schema. So this approach requires that the feature-flagged entity
exists in the schema, even if the feature flag is disabled. When the feature flag is turned off, it
-is recommended that the resolver returns `null` at the very least using the same feature flag as the frontend. See the [API GraphQL guide](../api_graphql_styleguide.md#frontend-and-backend-feature-flag-strategies).
+is recommended that the resolver returns `null` at the very least using the same feature flag as the frontend. See the [API GraphQL guide](../api_graphql_styleguide.md#feature-flags).
##### Different versions of a query
@@ -729,8 +729,9 @@ In this case, we can either:
- Skip passing a cursor.
- Pass `null` explicitly to `after`.
-After data is fetched, we can use the `update`-hook as an opportunity [to customize
-the data that is set in the Vue component property](https://apollo.vuejs.org/api/smart-query.html#options). This allows us to get a hold of the `pageInfo` object among other data.
+After data is fetched, we can use the `update`-hook as an opportunity
+[to customize the data that is set in the Vue component property](https://apollo.vuejs.org/api/smart-query.html#options).
+This allows us to get a hold of the `pageInfo` object among other data.
In the `result`-hook, we can inspect the `pageInfo` object to see if we need to fetch
the next page. Note that we also keep a `requestCount` to ensure that the application
@@ -895,6 +896,51 @@ export default new VueApollo({
This is similar to the `DesignCollection` example above as new page results are appended to the
previous ones.
+For some cases, it's hard to define the correct `keyArgs` for the field because all
+the fields are updated. In this case, we can set `keyArgs` to `false`. This instructs
+Apollo Client to not perform any automatic merge, and fully rely on the logic we
+put into the `merge` function.
+
+For example, we have a query like this:
+
+```javascript
+query searchGroupsWhereUserCanTransfer {
+ currentUser {
+ id
+ groups {
+ nodes {
+ id
+ fullName
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
+```
+
+Here, the `groups` field doesn't have a good candidate for `keyArgs`: both
+`nodes` and `pageInfo` will be updated when we're fetching a second page.
+Setting `keyArgs` to `false` makes the update work as intended:
+
+```javascript
+typePolicies: {
+ UserCore: {
+ fields: {
+ groups: {
+ keyArgs: false,
+ },
+ },
+ },
+ GroupConnection: {
+ fields: {
+ nodes: concatPagination(),
+ },
+ },
+}
+```
+
#### Using a recursive query in components
When it is necessary to fetch all paginated data initially an Apollo query can do the trick for us.
@@ -1444,7 +1490,7 @@ describe('Some component', () => {
When mocking resolved values, ensure the structure of the response is the same
as the actual API response. For example, root property should be `data`.
-When testing queries, please keep in mind they are promises, so they need to be _resolved_ to render a result. Without resolving, we can check the `loading` state of the query:
+When testing queries, keep in mind they are promises, so they need to be _resolved_ to render a result. Without resolving, we can check the `loading` state of the query:
```javascript
it('renders a loading state', () => {
@@ -2001,11 +2047,15 @@ relative to `app/graphql/queries` folder: for example, if we need a
### Mocked client returns empty objects instead of mock response
-If your unit test is failing because response contains empty objects instead of mock data, you would need to add `__typename` field to the mocked response. This happens because mocked client (unlike the real one) does not populate the response with typenames and in some cases we need to do it manually so the client is able to recognize a GraphQL type.
+If your unit test is failing because the response contains empty objects instead of mock data, add
+`__typename` field to the mocked responses.
+
+Alternatively, [GraphQL query fixtures](../testing_guide/frontend_testing.md#graphql-query-fixtures)
+automatically adds the `__typename` for you upon generation.
### Warning about losing cache data
-Sometimes you can see a warning in the console: `Cache data may be lost when replacing the someProperty field of a Query object. To address this problem, either ensure all objects of SomeEntityhave an id or a custom merge function`. Please check section about [multiple queries](#multiple-client-queries-for-the-same-object) to resolve an issue.
+Sometimes you can see a warning in the console: `Cache data may be lost when replacing the someProperty field of a Query object. To address this problem, either ensure all objects of SomeEntityhave an id or a custom merge function`. Check section about [multiple queries](#multiple-client-queries-for-the-same-object) to resolve an issue.
```yaml
- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index d107af156db..73f196ef51f 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -81,7 +81,7 @@ export default {
### Usage in HTML/JS
-Please use the following function inside JS to render an icon:
+Use the following function inside JS to render an icon:
`gl.utils.spriteIcon(iconName)`
## Loading icon
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 544985d7edc..02086ec5f1b 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -147,7 +147,7 @@ Best practices for [client-side logging](logging.md) for GitLab frontend develop
## [Internationalization (i18n) and Translations](../i18n/externalization.md)
-Frontend internationalization support is described in [this document](../i18n/).
+Frontend internationalization support is described in [this document](../i18n/index.md).
The [externalization part of the guide](../i18n/externalization.md) explains the helpers/methods available.
## [Troubleshooting](troubleshooting.md)
diff --git a/doc/development/fe_guide/merge_request_widget_extensions.md b/doc/development/fe_guide/merge_request_widget_extensions.md
new file mode 100644
index 00000000000..a2ff10cc57f
--- /dev/null
+++ b/doc/development/fe_guide/merge_request_widget_extensions.md
@@ -0,0 +1,437 @@
+---
+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
+---
+
+# Merge request widget extensions **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.
+
+Extensions in the merge request widget enable you to add new features
+into the merge request widget that match the design framework.
+With extensions we get a lot of benefits out of the box without much effort required, like:
+
+- A consistent look and feel.
+- Tracking when the extension is opened.
+- Virtual scrolling for performance.
+
+## Usage
+
+To use extensions you must first create a new extension object to fetch the
+data to render in the extension. For a working example, refer to the example file in
+`app/assets/javascripts/vue_merge_request_widget/extensions/issues.js`.
+
+The basic object structure:
+
+```javascript
+export default {
+ name: '', // Required: This helps identify the widget
+ props: [], // Required: Props passed from the widget state
+ i18n: { // Required: Object to hold i18n text
+ label: '', // Required: Used for tooltips and aria-labels
+ loading: '', // Required: Loading text for when data is loading
+ },
+ expandEvent: '', // Optional: RedisHLL event name to track expanding content
+ enablePolling: false, // Optional: Tells extension to poll for data
+ modalComponent: null, // Optional: The component to use for the modal
+ telemetry: true, // Optional: Reports basic telemetry for the extension. Set to false to disable telemetry
+ computed: {
+ summary(data) {}, // Required: Level 1 summary text
+ statusIcon(data) {}, // Required: Level 1 status icon
+ tertiaryButtons() {}, // Optional: Level 1 action buttons
+ shouldCollapse() {}, // Optional: Add logic to determine if the widget can expand or not
+ },
+ methods: {
+ fetchCollapsedData(props) {}, // Required: Fetches data required for collapsed state
+ fetchFullData(props) {}, // Required: Fetches data for the full expanded content
+ fetchMultiData() {}, // Optional: Works in conjunction with `enablePolling` and allows polling multiple endpoints
+ },
+};
+```
+
+By following the same data structure, each extension can follow the same registering structure,
+but each extension can manage its data sources.
+
+After creating this structure, you must register it. You can register the extension at any
+point _after_ the widget has been created. To register a extension:
+
+```javascript
+// Import the register method
+import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
+
+// Import the new extension
+import issueExtension from '~/vue_merge_request_widget/extensions/issues';
+
+// Register the imported extension
+registerExtension(issueExtension);
+```
+
+## Data fetching
+
+Each extension must fetch data. Fetching is handled when registering the extension,
+not by the core component itself. This approach allows for various different
+data fetching methods to be used, such as GraphQL or REST API calls.
+
+### API calls
+
+For performance reasons, it is best if the collapsed state fetches only the data required to
+render the collapsed state. This fetching happens in the `fetchCollapsedData` method.
+This method is called with the props as an argument, so you can easily access
+any paths set in the state.
+
+To allow the extension to set the data, this method **must** return the data. No
+special formatting is required. When the extension receives this data,
+it is set to `collapsedData`. You can access `collapsedData` in any computed property or
+method.
+
+When the user clicks **Expand**, the `fetchFullData` method is called. This method
+also gets called with the props as an argument. This method **must** also return
+the full data. However, this data must be correctly formatted to match the format
+mentioned in the data structure section.
+
+#### Technical debt
+
+For some of the current extensions, there is no split in data fetching. All the data
+is fetched through the `fetchCollapsedData` method. While less performant,
+it allows for faster iteration.
+
+To handle this the `fetchFullData` returns the data set through
+the `fetchCollapsedData` method call. In these cases, the `fetchFullData` must
+return a promise:
+
+```javascript
+fetchCollapsedData() {
+ return ['Some data'];
+},
+fetchFullData() {
+ return Promise.resolve(this.collapsedData)
+},
+```
+
+### Data structure
+
+The data returned from `fetchFullData` must match the format below. This format
+allows the core component to render the data in a way that matches
+the design framework. Any text properties can use the styling placeholders
+mentioned below:
+
+```javascript
+{
+ id: data.id, // Required: ID used as a key for each row
+ header: 'Header' || ['Header', 'sub-header'], // Required: String or array can be used for the header text
+ text: '', // Required: Main text for the row
+ subtext: '', // Optional: Smaller sub-text to be displayed below the main text
+ icon: { // Optional: Icon object
+ name: EXTENSION_ICONS.success, // Required: The icon name for the row
+ },
+ badge: { // Optional: Badge displayed after text
+ text: '', // Required: Text to be displayed inside badge
+ variant: '', // Optional: GitLab UI badge variant, defaults to info
+ },
+ link: { // Optional: Link to a URL displayed after text
+ text: '', // Required: Text of the link
+ href: '', // Optional: URL for the link
+ },
+ modal: { // Optional: Link to open a modal displayed after text
+ text: '', // Required: Text of the link
+ onClick: () => {} // Optional: Function to run when link is clicked, i.e. to set this.modalData
+ }
+ actions: [], // Optional: Action button for row
+ children: [], // Optional: Child content to render, structure matches the same structure
+}
+```
+
+### Polling
+
+To enable polling for an extension, an options flag must be present in the extension:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+};
+```
+
+This flag tells the base component we should poll the `fetchCollapsedData()`
+defined in the extension. Polling stops if the response has data, or if an error is present.
+
+When writing the logic for `fetchCollapsedData()`, a complete Axios response must be returned
+from the method. The polling utility needs data like polling headers to work correctly:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath)
+ },
+ },
+};
+```
+
+Most of the time the data returned from the extension's endpoint is not in the format
+the UI needs. We must format the data before setting the collapsed data in the base component.
+
+If the computed property `summary` can rely on `collapsedData`, you can format the data
+when `fetchFullData` is invoked:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath)
+ },
+ fetchFullData() {
+ return Promise.resolve(this.prepareReports());
+ },
+ // custom method
+ prepareReports() {
+ // unpack values from collapsedData
+ const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+
+ // perform data formatting
+
+ return [...newErrors, ...existingErrors, ...resolvedErrors]
+ }
+ },
+};
+```
+
+If the extension relies on `collapsedData` being formatted before invoking `fetchFullData()`,
+then `fetchCollapsedData()` must return the Axios response as well as the formatted data:
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchCollapsedData() {
+ return axios.get(this.reportPath).then(res => {
+ const formattedData = this.prepareReports(res.data)
+
+ return {
+ ...res,
+ data: formattedData,
+ }
+ })
+ },
+ // Custom method
+ prepareReports() {
+ // Unpack values from collapsedData
+ const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+
+ // Perform data formatting
+
+ return [...newErrors, ...existingErrors, ...resolvedErrors]
+ }
+ },
+};
+```
+
+If the extension must poll multiple endpoints at the same time, then `fetchMultiData`
+can be used to return an array of functions. A new `poll` object is created for each
+endpoint and they are polled separately. After all endpoints are resolved, polling is
+stopped and `setCollapsedData` is called with an array of `response.data`.
+
+```javascript
+export default {
+ //...
+ enablePolling: true
+ methods: {
+ fetchMultiData() {
+ return [
+ () => axios.get(this.reportPath1),
+ () => axios.get(this.reportPath2),
+ () => axios.get(this.reportPath3)
+ },
+ },
+};
+```
+
+WARNING:
+The function must return a `Promise` that resolves the `response` object.
+The implementation relies on the `POLL-INTERVAL` header to keep polling, therefore it is
+important not to alter the status code and headers.
+
+### Errors
+
+If `fetchCollapsedData()` or `fetchFullData()` methods throw an error:
+
+- The loading state of the extension is updated to `LOADING_STATES.collapsedError`
+ and `LOADING_STATES.expandedError` respectively.
+- The extensions header displays an error icon and updates the text to be either:
+ - The text defined in `$options.i18n.error`.
+ - "Failed to load" if `$options.i18n.error` is not defined.
+- The error is sent to Sentry to log that it occurred.
+
+To customise the error text, add it to the `i18n` object in your extension:
+
+```javascript
+export default {
+ //...
+ i18n: {
+ //...
+ error: __('Your error text'),
+ },
+};
+```
+
+## Telemetry
+
+The base implementation of the widget extension framework includes some telemetry events.
+Each widget reports:
+
+- `view`: When it is rendered to the screen.
+- `expand`: When it is expanded.
+- `full_report_clicked`: When an (optional) input is clicked to view the full report.
+- Outcome (`expand_success`, `expand_warning`, or `expand_failed`): One of three
+ additional events relating to the status of the widget when it was expanded.
+
+### Add new widgets
+
+When adding new widgets, the above events must be marked as `known`, and have metrics
+created, to be reportable.
+
+NOTE:
+Events that are only for EE should include `--ee` at the end of both shell commands below.
+
+To generate these known events for a single widget:
+
+1. Widgets should be named `Widget${CamelName}`.
+ - For example: a widget for **Test Reports** should be `WidgetTestReports`.
+1. Compute the widget name slug by converting the `${CamelName}` to lower-, snake-case.
+ - The previous example would be `test_reports`.
+1. Add the new widget name slug to `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`
+ in the `WIDGETS` list.
+1. Ensure the GDK is running (`gdk start`).
+1. Generate known events on the command line with the following command.
+ Replace `test_reports` with your appropriate name slug:
+
+ ```shell
+ bundle exec rails generate gitlab:usage_metric_definition \
+ counts.i_code_review_merge_request_widget_test_reports_count_view \
+ counts.i_code_review_merge_request_widget_test_reports_count_full_report_clicked \
+ counts.i_code_review_merge_request_widget_test_reports_count_expand \
+ counts.i_code_review_merge_request_widget_test_reports_count_expand_success \
+ counts.i_code_review_merge_request_widget_test_reports_count_expand_warning \
+ counts.i_code_review_merge_request_widget_test_reports_count_expand_failed \
+ --dir=all
+ ```
+
+1. Modify each newly generated file to match the existing files for the merge request widget extension telemetry.
+ - Find existing examples by doing a glob search, like: `metrics/**/*_i_code_review_merge_request_widget_*`
+ - Roughly speaking, each file should have these values:
+ 1. `description` = A plain English description of this value. Review existing widget extension telemetry files for examples.
+ 1. `product_section` = `dev`
+ 1. `product_stage` = `create`
+ 1. `product_group` = `code_review`
+ 1. `product_category` = `code_review`
+ 1. `introduced_by_url` = `'[your MR]'`
+ 1. `options.events` = (the event in the command from above that generated this file, like `i_code_review_merge_request_widget_test_reports_count_view`)
+ - This value is how the telemetry events are linked to "metrics" so this is probably one of the more important values.
+ 1. `data_source` = `redis`
+ 1. `data_category` = `optional`
+1. Generate known HLL events on the command line with the following command.
+ Replace `test_reports` with your appropriate name slug.
+
+ ```shell
+ bundle exec rails generate gitlab:usage_metric_definition:redis_hll code_review \
+ i_code_review_merge_request_widget_test_reports_view \
+ i_code_review_merge_request_widget_test_reports_full_report_clicked \
+ i_code_review_merge_request_widget_test_reports_expand \
+ i_code_review_merge_request_widget_test_reports_expand_success \
+ i_code_review_merge_request_widget_test_reports_expand_warning \
+ i_code_review_merge_request_widget_test_reports_expand_failed \
+ --class_name=RedisHLLMetric
+ ```
+
+1. Repeat step 6, but change the `data_source` to `redis_hll`.
+1. Add each of the HLL metrics to `lib/gitlab/usage_data_counters/known_events/code_review_events.yml`:
+ 1. `name` = (the event)
+ 1. `redis_slot` = `code_review`
+ 1. `category` = `code_review`
+ 1. `aggregation` = `weekly`
+1. Add each event to the appropriate aggregates in `config/metrics/aggregates/code_review.yml`
+
+### Add new events
+
+If you are adding a new event to our known events, include the new event in the
+`KNOWN_EVENTS` list in `lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb`.
+
+## Icons
+
+Level 1 and all subsequent levels can have their own status icons. To keep with
+the design framework, import the `EXTENSION_ICONS` constant
+from the `constants.js` file:
+
+```javascript
+import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants.js';
+```
+
+This constant has the below icons available for use. Per the design framework,
+only some of these icons should be used on level 1:
+
+- `failed`
+- `warning`
+- `success`
+- `neutral`
+- `error`
+- `notice`
+- `severityCritical`
+- `severityHigh`
+- `severityMedium`
+- `severityLow`
+- `severityInfo`
+- `severityUnknown`
+
+## Text styling
+
+Any area that has text can be styled with the placeholders below. This
+technique follows the same technique as `sprintf`. However, instead of specifying
+these through `sprintf`, the extension does this automatically.
+
+Every placeholder contains starting and ending tags. For example, `success` uses
+`Hello %{success_start}world%{success_end}`. The extension then
+adds the start and end tags with the correct styling classes.
+
+| Placeholder | Style |
+|-------------|-----------------------------------------|
+| success | `gl-font-weight-bold gl-text-green-500` |
+| danger | `gl-font-weight-bold gl-text-red-500` |
+| critical | `gl-font-weight-bold gl-text-red-800` |
+| same | `gl-font-weight-bold gl-text-gray-700` |
+| strong | `gl-font-weight-bold` |
+| small | `gl-font-sm` |
+
+## Action buttons
+
+You can add action buttons to all level 1 and 2 in each extension. These buttons
+are meant as a way to provide links or actions for each row:
+
+- Action buttons for level 1 can be set through the `tertiaryButtons` computed property.
+ This property should return an array of objects for each action button.
+- Action buttons for level 2 can be set by adding the `actions` key to the level 2 rows object.
+ The value for this key must also be an array of objects for each action button.
+
+Links must follow this structure:
+
+```javascript
+{
+ text: 'Click me',
+ href: this.someLinkHref,
+ target: '_blank', // Optional
+}
+```
+
+For internal action buttons, follow this structure:
+
+```javascript
+{
+ text: 'Click me',
+ onClick() {}
+}
+```
diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md
index bcdc49a1070..2e1fabd739c 100644
--- a/doc/development/fe_guide/performance.md
+++ b/doc/development/fe_guide/performance.md
@@ -8,6 +8,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Performance is an essential part and one of the main areas of concern for any modern application.
+## Monitoring
+
+We have a performance dashboard available in one of our [Grafana instances](https://dashboards.gitlab.net/d/000000043/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://www.sitespeed.io/) every 4 hours. These changes are displayed after a set number of pages are aggregated.
+
+These pages can be found inside text files in the [`sitespeed-measurement-setup` repository](https://gitlab.com/gitlab-org/frontend/sitespeed-measurement-setup) called [`gitlab`](https://gitlab.com/gitlab-org/frontend/sitespeed-measurement-setup/-/tree/master/gitlab)
+Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing URLs of pages to the text files. The changes are pushed live on the next scheduled run after the changes are merged into `main`.
+
+There are 3 recommended high impact metrics (core web vitals) to review on each page:
+
+- [Largest Contentful Paint](https://web.dev/lcp/)
+- [First Input Delay](https://web.dev/fid/)
+- [Cumulative Layout Shift](https://web.dev/cls/)
+
+For these metrics, lower numbers are better as it means that the website is more performant.
+
## User Timing API
[User Timing API](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API) is a web API
@@ -77,9 +92,9 @@ performance.getEntriesByType('mark');
performance.getEntriesByType('measure');
```
-Using `getEntriesByName()` or `getEntriesByType()` returns an Array of [the PerformanceMeasure
-objects](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure) which contain
-information about the measurement's start time and duration.
+Using `getEntriesByName()` or `getEntriesByType()` returns an Array of
+[the PerformanceMeasure objects](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure)
+which contain information about the measurement's start time and duration.
### User Timing API utility
@@ -220,7 +235,7 @@ Use the following rules when creating real-time solutions.
A `Poll-Interval: -1` means you should disable polling, and this must be implemented.
1. A response with HTTP status different from 2XX should disable polling as well.
1. Use a common library for polling.
-1. Poll on active tabs only. Please use [Visibility](https://github.com/ai/visibilityjs).
+1. Poll on active tabs only. Use [Visibility](https://github.com/ai/visibilityjs).
1. Use regular polling intervals, do not use backoff polling or jitter, as the interval is
controlled by the server.
1. The backend code is likely to be using ETags. You do not and should not check for status
@@ -434,7 +449,7 @@ Use `webpackChunkName` when generating dynamic imports as
it provides a deterministic filename for the chunk which can then be cached
in the browser across GitLab versions.
-More information is available in [webpack's code splitting documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports) and [vue's dynamic component documentation](https://vuejs.org/v2/guide/components-dynamic-async.html).
+More information is available in [webpack's code splitting documentation](https://webpack.js.org/guides/code-splitting/#dynamic-imports) and [vue's dynamic component documentation](https://v2.vuejs.org/v2/guide/components-dynamic-async.html).
### Minimizing page size
diff --git a/doc/development/fe_guide/source_editor.md b/doc/development/fe_guide/source_editor.md
index b06e341630f..88508e94380 100644
--- a/doc/development/fe_guide/source_editor.md
+++ b/doc/development/fe_guide/source_editor.md
@@ -129,7 +129,7 @@ with additional functions on the instance level:
Source Editor provides a universal, extensible editing tool to the whole product,
and doesn't depend on any particular group. Even though the Source Editor's core is owned by
-[Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/),
+[Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create/editor/),
any group can own the extensions—the main functional elements. The goal of
Source Editor extensions is to keep the editor's core slim and stable. Any
needed features can be added as extensions to this core. Any group can
diff --git a/doc/development/fe_guide/storybook.md b/doc/development/fe_guide/storybook.md
index 4c0e7b2612b..45342eb6d72 100644
--- a/doc/development/fe_guide/storybook.md
+++ b/doc/development/fe_guide/storybook.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Storybook
-The Storybook for the `gitlab-org/gitlab` project is available on our [GitLab Pages site](https://gitlab-org.gitlab.io/gitlab/storybook).
+The Storybook for the `gitlab-org/gitlab` project is available on our [GitLab Pages site](https://gitlab-org.gitlab.io/gitlab/storybook/).
## Storybook in local development
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index d93dc8292d4..b86bdfafa21 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -123,7 +123,8 @@ things.map(parseInt);
things.map(Number);
```
-**PLEASE NOTE:** If the String could represent a non-integer (i.e., it includes a decimal), **do not** use `parseInt`. Consider `Number` or `parseFloat` instead.
+NOTE:
+If the String could represent a non-integer (i.e., it includes a decimal), **do not** use `parseInt`. Consider `Number` or `parseFloat` instead.
## CSS Selectors - Use `js-` prefix
diff --git a/doc/development/fe_guide/style/scss.md b/doc/development/fe_guide/style/scss.md
index 451b0c8a4c6..17e80762a38 100644
--- a/doc/development/fe_guide/style/scss.md
+++ b/doc/development/fe_guide/style/scss.md
@@ -12,7 +12,7 @@ easy to maintain, and performant for the end-user.
## Rules
-Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you are likely to run into exceptions, where following the guide is difficult to impossible without major effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Please endeavor to limit these cases.
+Our CSS is a mixture of current and legacy approaches. That means sometimes it may be difficult to follow this guide to the letter; it means you are likely to run into exceptions, where following the guide is difficult to impossible without major effort. In those cases, you may work with your reviewers and maintainers to identify an approach that does not fit these rules. Try to limit these cases.
### Utility Classes
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index 5c79d47e7b0..c9bd0e1b35a 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Linting
We default to [eslint-vue-plugin](https://github.com/vuejs/eslint-plugin-vue), with the `plugin:vue/recommended`.
-Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) for more documentation.
+Check the [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) for more documentation.
## Basic Rules
@@ -448,9 +448,9 @@ Typically, when testing a Vue component, the component should be "re-mounted" in
To achieve this:
1. Create a mutable `wrapper` variable inside the top-level `describe` block.
-1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/
-[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount).
-1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper)
+1. Mount the component using [`mount`](https://v1.test-utils.vuejs.org/api/#mount)/
+[`shallowMount`](https://v1.test-utils.vuejs.org/api/#shallowMount).
+1. Reassign the resulting [`Wrapper`](https://v1.test-utils.vuejs.org/api/wrapper/#wrapper)
instance to our `wrapper` variable.
Creating a global, mutable wrapper provides a number of advantages, including the ability to:
@@ -476,8 +476,8 @@ Creating a global, mutable wrapper provides a number of advantages, including th
To avoid duplicating our mounting logic, it's useful to define a `createComponent` factory function
that we can reuse in each test block. This is a closure which should reassign our `wrapper` variable
-to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and
-[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount):
+to the result of [`mount`](https://v1.test-utils.vuejs.org/api/#mount) and
+[`shallowMount`](https://v1.test-utils.vuejs.org/api/#shallowMount):
```javascript
import MyComponent from '~/path/to/my_component.vue';
@@ -579,9 +579,9 @@ the mounting function (`mount` or `shallowMount`) to be used to mount the compon
### Setting component state
-1. Avoid using [`setProps`](https://vue-test-utils.vuejs.org/api/wrapper/#setprops) to set
+1. Avoid using [`setProps`](https://v1.test-utils.vuejs.org/api/wrapper/#setprops) to set
component state wherever possible. Instead, set the component's
-[`propsData`](https://vue-test-utils.vuejs.org/api/options.html#propsdata) when mounting the component:
+[`propsData`](https://v1.test-utils.vuejs.org/api/options.html#propsdata) when mounting the component:
```javascript
// bad
@@ -659,7 +659,7 @@ The goal of this accord is to make sure we are all on the same page.
1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use
jQuery event listeners.
1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery
- events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
+ events take a look at [different methods to do the same task](https://v2.vuejs.org/v2/api/#vm-emit).
1. You may query the `window` object one time, while bootstrapping your application for application
specific data (for example, `scrollTo` is ok to access anytime). Do this access during the
bootstrapping of your application.
diff --git a/doc/development/fe_guide/tooling.md b/doc/development/fe_guide/tooling.md
index 1c32647eefd..2bb6cbfaf7a 100644
--- a/doc/development/fe_guide/tooling.md
+++ b/doc/development/fe_guide/tooling.md
@@ -175,7 +175,7 @@ preferred editor (all major editors are supported) accordingly. We suggest
setting up Prettier to run when each file is saved. For instructions about using
Prettier in your preferred editor, see the [Prettier documentation](https://prettier.io/docs/en/editors.html).
-Please take care that you only let Prettier format the same file types as the global Yarn script does (`.js`, `.vue`, `.graphql`, and `.scss`). For example, you can exclude file formats in your Visual Studio Code settings file:
+Take care that you only let Prettier format the same file types as the global Yarn script does (`.js`, `.vue`, `.graphql`, and `.scss`). For example, you can exclude file formats in your Visual Studio Code settings file:
```json
"prettier.disableLanguages": [
diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md
index 14943cca3ac..c0894621ed1 100644
--- a/doc/development/fe_guide/troubleshooting.md
+++ b/doc/development/fe_guide/troubleshooting.md
@@ -12,7 +12,7 @@ Running into a problem? Maybe this will help ¯\_(ツ)_/¯.
### This guide doesn't contain the issue I ran into
-If you run into a Frontend development issue that is not in this guide, please consider updating this guide with your issue and possible remedies. This way future adventurers can face these dragons with more success, being armed with your experience and knowledge.
+If you run into a Frontend development issue that is not in this guide, consider updating this guide with your issue and possible remedies. This way future adventurers can face these dragons with more success, being armed with your experience and knowledge.
## Testing issues
diff --git a/doc/development/fe_guide/view_component.md b/doc/development/fe_guide/view_component.md
index f4bb7ac3a2e..2e373e6933b 100644
--- a/doc/development/fe_guide/view_component.md
+++ b/doc/development/fe_guide/view_component.md
@@ -13,18 +13,24 @@ They are rendered server-side and can be seamlessly used with template languages
Refer to the official [documentation](https://viewcomponent.org/) to learn more or
watch this [introduction video](https://youtu.be/akRhUbvtnmo).
+## Browse components with Lookbook
+
+We have a [Lookbook](https://github.com/allmarkedup/lookbook) in [http://gdk.test:3000/rails/lookbook](http://gdk.test:3000/rails/lookbook) (only available in development mode) to browse and interact with ViewComponent previews.
+
## Pajamas components
Some of the components of our [Pajamas](https://design.gitlab.com) design system are
available as a ViewComponent in `app/components/pajamas`.
NOTE:
-We have a small but growing number of Pajamas components. Reach out to the
-[Foundations team](https://about.gitlab.com/handbook/engineering/development/dev/ecosystem/foundations/)
+We are still in the process of creating these components, so not every Pajamas component is available as ViewComponent.
+Reach out to the [Foundations team](https://about.gitlab.com/handbook/engineering/development/dev/ecosystem/foundations/)
if the component you are looking for is not yet available.
### Available components
+Consider this list a best effort. The full list can be found in [`app/components/pajamas`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/app/components/pajamas). Also see [our Lookbook](http://gdk.test:3000/rails/lookbook) for a more interactive way to browse our components.
+
#### Alert
The `Pajamas::AlertComponent` follows the [Pajamas Alert](https://design.gitlab.com/components/alert) specification.
@@ -147,6 +153,39 @@ If you want to add custom attributes to any of these or the card itself, use the
For the full list of options, see its
[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/card_component.rb).
+#### Checkbox tag
+
+The `Pajamas::CheckboxTagComponent` follows the [Pajamas Checkbox](https://design.gitlab.com/components/checkbox) specification.
+
+The `name` argument and `label` slot are required.
+
+For example:
+
+```haml
+= render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_sast]',
+ checkbox_options: { data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' } }) do |c|
+ = c.label do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ = c.help_text do
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed' }
+```
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/checkbox_tag_component.rb).
+
+#### Checkbox
+
+The `Pajamas::CheckboxComponent` follows the [Pajamas Checkbox](https://design.gitlab.com/components/checkbox) specification.
+
+NOTE:
+`Pajamas::CheckboxComponent` is used internally by the [GitLab UI form builder](haml.md#use-the-gitlab-ui-form-builder) and requires an instance of [ActionView::Helpers::FormBuilder](https://api.rubyonrails.org/v6.1.0/classes/ActionView/Helpers/FormBuilder.html) to be passed as the `form` argument.
+It is preferred to use the [gitlab_ui_checkbox_component](haml.md#gitlab_ui_checkbox_component) method to render this ViewComponent.
+To use a checkbox without an instance of [ActionView::Helpers::FormBuilder](https://api.rubyonrails.org/v6.1.0/classes/ActionView/Helpers/FormBuilder.html) use [CheckboxTagComponent](#checkbox-tag).
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/checkbox_component.rb).
+
#### Toggle
The `Pajamas::ToggleComponent` follows the [Pajamas Toggle](https://design.gitlab.com/components/toggle) specification.
@@ -172,3 +211,5 @@ For the full list of options, see its
over creating plain Haml tags with CSS classes.
- If you are making changes to an existing Haml view and see, for example, a
button that is still implemented with plain Haml, consider migrating it to use a ViewComponent.
+- If you decide to create a new component, consider creating [previews](https://viewcomponent.org/guide/previews.html) for it, too.
+ This will help others to discover your component with Lookbook, also it makes it much easier to test its different states.
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 7943ae119be..27660c0f5f7 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -71,7 +71,7 @@ component, is that you avoid creating a fixture or an HTML element in the unit t
##### `provide` and `inject`
-Vue supports dependency injection through [`provide` and `inject`](https://vuejs.org/v2/api/#provide-inject).
+Vue supports dependency injection through [`provide` and `inject`](https://v2.vuejs.org/v2/api/#provide-inject).
In the component the `inject` configuration accesses the values `provide` passes down.
This example of a Vue app initialization shows how the `provide` configuration passes a value from HAML to the component:
@@ -266,7 +266,7 @@ return new Vue({
#### Accessing feature flags
-Use the [`provide` and `inject`](https://vuejs.org/v2/api/#provide-inject) mechanisms
+Use the [`provide` and `inject`](https://v2.vuejs.org/v2/api/#provide-inject) mechanisms
in Vue to make feature flags available to any descendant components in a Vue
application. The `glFeatures` object is already provided in `commons/vue.js`, so
only the mixin is required to use the flags:
@@ -339,7 +339,7 @@ Check this [page](vuex.md) for more details.
### Mixing Vue and JavaScript classes (in the data function)
-In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
+In the [Vue documentation](https://v2.vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows:
> The data object for the Vue instance. Vue recursively converts its properties into getter/setters
to make it "reactive". The object must be plain: native objects such as browser API objects and
@@ -348,7 +348,7 @@ recommended to observe objects with their own stateful behavior.
Based on the Vue guidance:
-- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data),
+- **Do not** use or create a JavaScript class in your [data function](https://v2.vuejs.org/v2/api/#data),
such as `user: new User()`.
- **Do not** add new JavaScript class implementations.
- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if
@@ -531,7 +531,7 @@ Each Vue component has a unique output. This output is always present in the ren
Although each method of a Vue component can be tested individually, our goal is to test the output
of the render function, which represents the state at all times.
-Visit the [Vue testing guide](https://vuejs.org/v2/guide/testing.html#Unit-Testing) for help
+Visit the [Vue testing guide](https://v2.vuejs.org/v2/guide/testing.html#Unit-Testing) for help
testing the rendered output.
Here's an example of a well structured unit test for [this Vue component](#appendix---vue-component-subject-under-test):
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 064f01c8195..8bfb912161a 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -165,7 +165,7 @@ Instead of creating an mutation to toggle the loading state, we should:
As a result, we can dispatch the `fetchNamespace` action from the component and it is responsible to commit `REQUEST_NAMESPACE`, `RECEIVE_NAMESPACE_SUCCESS` and `RECEIVE_NAMESPACE_ERROR` mutations.
-> Previously, we were dispatching actions from the `fetchNamespace` action instead of committing mutation, so please don't be confused if you find a different pattern in the older parts of the codebase. However, we encourage leveraging a new pattern whenever you write new Vuex stores.
+> Previously, we were dispatching actions from the `fetchNamespace` action instead of committing mutation, so don't be confused if you find a different pattern in the older parts of the codebase. However, we encourage leveraging a new pattern whenever you write new Vuex stores.
By following this pattern we guarantee:
@@ -364,8 +364,8 @@ export default initialState => ({
We made the conscious decision to avoid this pattern to improve the ability to
discover and search our frontend codebase. The same applies
-when [providing data to a Vue app](vue.md#providing-data-from-haml-to-javascript). The reasoning for this is described in [this
-discussion](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865):
+when [providing data to a Vue app](vue.md#providing-data-from-haml-to-javascript). The reasoning for this is described in
+[this discussion](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865):
> Consider a `someStateKey` is being used in the store state. You _may_ not be
> able to grep for it directly if it was provided only by `el.dataset`. Instead,
diff --git a/doc/development/fe_guide/widgets.md b/doc/development/fe_guide/widgets.md
index 02876afe597..b54f9add97d 100644
--- a/doc/development/fe_guide/widgets.md
+++ b/doc/development/fe_guide/widgets.md
@@ -141,3 +141,7 @@ methods: {
```
[View an example of such a component.](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/notes/components/sidebar_subscription.vue)
+
+## Merge request widgets
+
+Refer to the documentation specific to the [merge request widget extension framework](merge_request_widget_extensions.md).
diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md
index b2d141798fa..a93ed58336d 100644
--- a/doc/development/feature_categorization/index.md
+++ b/doc/development/feature_categorization/index.md
@@ -10,8 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Each Sidekiq worker, controller action, or API endpoint
must declare a `feature_category` attribute. This attribute maps each
-of these to a [feature
-category](https://about.gitlab.com/handbook/product/categories/). This
+of these to a [feature category](https://about.gitlab.com/handbook/product/categories/). This
is done for error budgeting, alert routing, and team attribution.
The list of feature categories can be found in the file `config/feature_categories.yml`.
@@ -29,8 +28,7 @@ product categories. When this occurs, you can automatically update
and generate a new version of the file, which needs to be committed to
the repository.
-The [Scalability
-team](https://about.gitlab.com/handbook/engineering/infrastructure/team/scalability/)
+The [Scalability team](https://about.gitlab.com/handbook/engineering/infrastructure/team/scalability/)
currently maintains the `feature_categories.yml` file. They will automatically be
notified on Slack when the file becomes outdated.
diff --git a/doc/development/feature_development.md b/doc/development/feature_development.md
index a5d74a0bfd9..e50c1edd282 100644
--- a/doc/development/feature_development.md
+++ b/doc/development/feature_development.md
@@ -71,9 +71,9 @@ Consult these topics for information on contributing to specific GitLab features
- [Developing against interacting components or features](interacting_components.md)
- [Manage feature flags](feature_flags/index.md)
-- [Licensed feature availability](licensed_feature_availability.md)
+- [Implementing Enterprise Edition features](ee_features.md)
- [Accessing session data](session.md)
-- [How to dump production data to staging](db_dump.md)
+- [How to dump production data to staging](database/db_dump.md)
- [Geo development](geo.md)
- [Redis guidelines](redis.md)
- [Adding a new Redis instance](redis/new_redis_instance.md)
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 07c3c83912a..8a862e5f7cd 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -310,7 +310,7 @@ Changes to the issue format can be submitted in the
#### Instance level
Any feature flag change that affects any GitLab instance is automatically logged in
-[features_json.log](../../administration/logs.md#features_jsonlog).
+[features_json.log](../../administration/logs/index.md#features_jsonlog).
You can search the change history in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html).
You can also access the feature flag change history for GitLab.com [in Kibana](https://log.gprd.gitlab.net/goto/d060337c017723084c6d97e09e591fc6).
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 140d5f826cf..502a028f089 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -170,7 +170,7 @@ Each feature flag is defined in a separate YAML file consisting of a number of f
| `default_enabled` | yes | The default state of the feature flag. |
| `introduced_by_url` | no | The URL to the merge request that introduced the feature flag. |
| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. |
-| `milestone` | no | Milestone in which the feature was added. |
+| `milestone` | no | Milestone in which the feature flag was created. |
| `group` | no | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the feature flag. |
NOTE:
@@ -178,6 +178,9 @@ All validations are skipped when running in `RAILS_ENV=production`.
## Create a new feature flag
+NOTE:
+GitLab Pages uses [a different process](../pages/index.md#feature-flags) for feature flags.
+
The GitLab codebase provides [`bin/feature-flag`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/bin/feature-flag),
a dedicated tool to create new feature flag definitions.
The tool asks various questions about the new feature flag, then creates
@@ -423,6 +426,21 @@ Feature.enabled?(:a_feature, project) && Feature.disabled?(:a_feature_override,
/chatops run feature set --project=gitlab-org/gitlab a_feature_override true
```
+#### Percentage-based actor selection
+
+When using the percentage rollout of actors on multiple feature flags, the actors for each feature flag are selected separately.
+
+For example, the following feature flags are enabled for a certain percentage of actors:
+
+```plaintext
+/chatops run chatops feature set feature-set-1 25 --actors
+/chatops run chatops feature set feature-set-2 25 --actors
+```
+
+If a project A has `:feature-set-1` enabled, there is no guarantee that project A also has `:feature-set-2` enabled.
+
+For more detail, see [This is how percentages work in Flipper](https://www.hackwithpassion.com/this-is-how-percentages-work-in-flipper).
+
#### Use actors for verifying in production
WARNING:
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index ca7dbd6adde..f30a041931e 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -14,8 +14,8 @@ When implementing new features, please refer to these existing features to avoid
- [Merge request Templates](../user/project/description_templates.md#create-a-merge-request-template): `.gitlab/merge_request_templates/`.
- [GitLab agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
- [CODEOWNERS](../user/project/code_owners.md#set-up-code-owners): `.gitlab/CODEOWNERS`.
-- [Route Maps](../ci/review_apps/#route-maps): `.gitlab/route-map.yml`.
+- [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`.
- [Service Desk Templates](../user/project/service_desk.md#using-customized-email-templates): `.gitlab/service_desk_templates/`.
-- [Web IDE](../user/project/web_ide/#web-ide-configuration-file): `.gitlab/.gitlab-webide.yml`.
+- [Web IDE](../user/project/web_ide/index.md#web-ide-configuration-file): `.gitlab/.gitlab-webide.yml`.
diff --git a/doc/development/filtering_by_label.md b/doc/development/filtering_by_label.md
index 9e759744a1a..675fe004c22 100644
--- a/doc/development/filtering_by_label.md
+++ b/doc/development/filtering_by_label.md
@@ -1,179 +1,11 @@
---
-stage: Plan
-group: Project Management
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'database/filtering_by_label.md'
+remove_date: '2022-11-05'
---
-# Filtering by label
-## Introduction
+This document was moved to [another location](database/filtering_by_label.md).
-GitLab has [labels](../user/project/labels.md) that can be assigned to issues,
-merge requests, and epics. Labels on those objects are a many-to-many relation
-through the polymorphic `label_links` table.
-
-To filter these objects by multiple labels - for instance, 'all open
-issues with the label ~Plan and the label ~backend' - we generate a
-query containing a `GROUP BY` clause. In a simple form, this looks like:
-
-```sql
-SELECT
- issues.*
-FROM
- issues
- INNER JOIN label_links ON label_links.target_id = issues.id
- AND label_links.target_type = 'Issue'
- INNER JOIN labels ON labels.id = label_links.label_id
-WHERE
- issues.project_id = 13083
- AND (issues.state IN ('opened'))
- AND labels.title IN ('Plan',
- 'backend')
-GROUP BY
- issues.id
-HAVING (COUNT(DISTINCT labels.title) = 2)
-ORDER BY
- issues.updated_at DESC,
- issues.id DESC
-LIMIT 20 OFFSET 0
-```
-
-In particular, note that:
-
-1. We `GROUP BY issues.id` so that we can ...
-1. Use the `HAVING (COUNT(DISTINCT labels.title) = 2)` condition to ensure that
- all matched issues have both labels.
-
-This is more complicated than is ideal. It makes the query construction more
-prone to errors (such as
-[issue #15557](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15557)).
-
-## Attempt A: `WHERE EXISTS`
-
-### Attempt A1: use multiple subqueries with `WHERE EXISTS`
-
-In [issue #37137](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37137)
-and its associated [merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14022),
-we tried to replace the `GROUP BY` with multiple uses of `WHERE EXISTS`. For the
-example above, this would give:
-
-```sql
-WHERE (EXISTS (
- SELECT
- TRUE
- FROM
- label_links
- INNER JOIN labels ON labels.id = label_links.label_id
- WHERE
- labels.title = 'Plan'
- AND target_type = 'Issue'
- AND target_id = issues.id))
-AND (EXISTS (
- SELECT
- TRUE
- FROM
- label_links
- INNER JOIN labels ON labels.id = label_links.label_id
- WHERE
- labels.title = 'backend'
- AND target_type = 'Issue'
- AND target_id = issues.id))
-```
-
-While this worked without schema changes, and did improve readability somewhat,
-it did not improve query performance.
-
-### Attempt A2: use label IDs in the `WHERE EXISTS` clause
-
-In [merge request #34503](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503), we followed a similar approach to A1. But this time, we
-did a separate query to fetch the IDs of the labels used in the filter so that we avoid the `JOIN` in the `EXISTS` clause and filter directly by
-`label_links.label_id`. We also added a new index on `label_links` for the `target_id`, `label_id`, and `target_type` columns to speed up this query.
-
-Finding the label IDs wasn't straightforward because there could be multiple labels with the same title within a single root namespace. We solved
-this by grouping the label IDs by title and then using the array of IDs in the `EXISTS` clauses.
-
-This resulted in a significant performance improvement. However, this optimization could not be applied to the dashboard pages
-where we do not have a project or group context. We could not easily search for the label IDs here because that would mean searching across all
-projects and groups that the user has access to.
-
-## Attempt B: Denormalize using an array column
-
-Having [removed MySQL support in GitLab 12.1](https://about.gitlab.com/blog/2019/06/27/removing-mysql-support/),
-using [PostgreSQL's arrays](https://www.postgresql.org/docs/11/arrays.html) became more
-tractable as we didn't have to support two databases. We discussed denormalizing
-the `label_links` table for querying in
-[issue #49651](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49651),
-with two options: label IDs and titles.
-
-We can think of both of those as array columns on `issues`, `merge_requests`,
-and `epics`: `issues.label_ids` would be an array column of label IDs, and
-`issues.label_titles` would be an array of label titles.
-
-These array columns can be complemented with [GIN
-indexes](https://www.postgresql.org/docs/11/gin-intro.html) to improve
-matching.
-
-### Attempt B1: store label IDs for each object
-
-This has some strong advantages over titles:
-
-1. Unless a label is deleted, or a project is moved, we never need to
- bulk-update the denormalized column.
-1. It uses less storage than the titles.
-
-Unfortunately, our application design makes this hard. If we were able to query
-just by label ID easily, we wouldn't need the `INNER JOIN labels` in the initial
-query at the start of this document. GitLab allows users to filter by label
-title across projects and even across groups, so a filter by the label ~Plan may
-include labels with multiple distinct IDs.
-
-We do not want users to have to know about the different IDs, which means that
-given this data set:
-
-| Project | ~Plan label ID | ~backend label ID |
-| ------- | -------------- | ----------------- |
-| A | 11 | 12 |
-| B | 21 | 22 |
-| C | 31 | 32 |
-
-We would need something like:
-
-```sql
-WHERE
- label_ids @> ARRAY[11, 12]
- OR label_ids @> ARRAY[21, 22]
- OR label_ids @> ARRAY[31, 32]
-```
-
-This can get even more complicated when we consider that in some cases, there
-might be two ~backend labels - with different IDs - that could apply to the same
-object, so the number of combinations would balloon further.
-
-### Attempt B2: store label titles for each object
-
-From the perspective of updating the object, this is the worst
-option. We have to bulk update the objects when:
-
-1. The objects are moved from one project to another.
-1. The project is moved from one group to another.
-1. The label is renamed.
-1. The label is deleted.
-
-It also uses much more storage. Querying is simple, though:
-
-```sql
-WHERE
- label_titles @> ARRAY['Plan', 'backend']
-```
-
-And our [tests in issue #49651](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49651#note_188777346)
-showed that this could be fast.
-
-However, at present, the disadvantages outweigh the advantages.
-
-## Conclusion
-
-We found a method A2 that does not need denormalization and improves the query performance significantly. This
-did not apply to all cases, but we were able to apply method A1 to the rest of the cases so that we remove the
-`GROUP BY` and `HAVING` clauses in all scenarios.
-
-This simplified the query and improved the performance in the most common cases.
+<!-- This redirect file can be deleted after <2022-11-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/fips_compliance.md b/doc/development/fips_compliance.md
index 6261b2fda6f..c690408ee60 100644
--- a/doc/development/fips_compliance.md
+++ b/doc/development/fips_compliance.md
@@ -12,12 +12,9 @@ to ensure a certain security floor is met by vendors selling products to U.S.
Federal institutions.
WARNING:
-GitLab is not FIPS compliant, even when built and run on a FIPS-enforcing
-system. Large parts of the build are broken, and many features use forbidden
-cryptographic primitives. Running GitLab on a FIPS-enforcing system is not
-supported and may result in data loss. This document is intended to help
-engineers looking to develop FIPS-related fixes. It is not intended to be used
-to run a production GitLab instance.
+You can build a FIPS-compliant instance of GitLab, but [not all features are included](#unsupported-features-in-fips-mode).
+A FIPS-compliant instance must be configured following the [FIPS install instructions](#install-gitlab-with-fips-compliance)
+exactly.
There are two current FIPS standards: [140-2](https://en.wikipedia.org/wiki/FIPS_140-2)
and [140-3](https://en.wikipedia.org/wiki/FIPS_140-3). At GitLab we usually
@@ -25,10 +22,7 @@ mean FIPS 140-2.
## Current status
-Read [Epic &5104](https://gitlab.com/groups/gitlab-org/-/epics/5104) for more
-information on the status of the investigation.
-
-GitLab is actively working towards FIPS compliance.
+GitLab is actively working towards FIPS compliance. Progress on this initiative can be tracked with this [FIPS compliance Epic](https://gitlab.com/groups/gitlab-org/-/epics/6452).
## FIPS compliance at GitLab
@@ -46,15 +40,40 @@ when FIPS mode is enabled.
| Ubuntu 20.04 Libgcrypt Cryptographic Module | [3902](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3902) | EC2 instances | `gpg`, `sshd` |
| Amazon Linux 2 Kernel Crypto API Cryptographic Module | [3709](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3709) | EKS nodes | Linux kernel |
| Amazon Linux 2 OpenSSL Cryptographic Module | [3553](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3553) | EKS nodes | NGINX |
-| RedHat Enterprise Linux 8 OpenSSL Cryptographic Module | [3852](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3852) | EKS nodes | UBI containers: Workhorse, Pages, Container Registry, Rails (Puma/Sidekiq), Security Analyzers |
+| RedHat Enterprise Linux 8 OpenSSL Cryptographic Module | [4271](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4271) | EKS nodes | UBI containers: Workhorse, Pages, Container Registry, Rails (Puma/Sidekiq), Security Analyzers |
| RedHat Enterprise Linux 8 Libgcrypt Cryptographic Module | [3784](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3784) | EKS nodes | UBI containers: GitLab Shell, `gpg` |
### Supported Operating Systems
-The supported hybrid environments are:
+The supported hybrid platforms are:
+
+- Omnibus GitLab: Ubuntu 20.04 LTS
+- Cloud Native GitLab: Amazon Linux 2 (EKS)
+
+### Unsupported features in FIPS mode
+
+Some GitLab features may not work when FIPS mode is enabled. The following features
+are known to not work in FIPS mode. However, there may be additional features not
+listed here that also do not work properly in FIPS mode:
+
+- [Container Scanning](../user/application_security/container_scanning/index.md) support for scanning images in repositories that require authentication.
+- [Code Quality](../ci/testing/code_quality.md) does not support operating in FIPS-compliant mode.
+- [Dependency scanning](../user/application_security/dependency_scanning/index.md) support for Gradle.
+- [Dynamic Application Security Testing (DAST)](../user/application_security/dast/index.md)
+ does not support operating in FIPS-compliant mode.
+- [License compliance](../user/compliance/license_compliance/index.md).
+- [Solutions for vulnerabilities](../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability)
+ for yarn projects.
+- [Static Application Security Testing (SAST)](../user/application_security/sast/index.md)
+ supports a reduced set of [analyzers](../user/application_security/sast/#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.
+- [Gravatar or Libravatar-based profile images](../administration/libravatar.md) are not FIPS-compliant.
+
+Additionally, these package repositories are disabled in FIPS mode:
-- Omnibus: Ubuntu 20.04 FIPS
-- EKS: Amazon Linux 2
+- [Conan package repository](../user/packages/conan_repository/index.md).
+- [Debian package repository](../user/packages/debian_repository/index.md).
## FIPS validation at GitLab
@@ -281,6 +300,9 @@ gitlab:
gitlab-mailroom:
image:
tag: master-fips
+ gitlab-pages:
+ image:
+ tag: master-fips
migrations:
image:
tag: master-fips
@@ -299,18 +321,17 @@ gitlab:
nginx-ingress:
controller:
image:
- repository: registry.gitlab.com/stanhu/gitlab-test-images/k8s-staging-ingress-nginx/controller
- tag: v1.2.0-beta.1
+ repository: registry.gitlab.com/gitlab-org/cloud-native/charts/gitlab-ingress-nginx/controller
+ tag: v1.2.1-fips
pullPolicy: Always
- digest: sha256:ace38833689ad34db4a46bc1e099242696eb800def88f02200a8615530734116
+ digest: sha256:c4222b7ab3836b9be2a7649cff4b2e6ead34286dfdf3a7b04eb34fdd3abb0334
```
The above example shows a FIPS-enabled [`nginx-ingress`](https://github.com/kubernetes/ingress-nginx) image.
-See [this issue](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/3153#note_917782207) for more details on
-how to build NGINX and the Ingress Controller.
+See our [Charts documentation on FIPS](https://docs.gitlab.com/charts/advanced/fips/index.html) for more details.
You can also use release tags, but the versioning is tricky because each
-component may use its own versioning scheme. For example, for GitLab v15.1:
+component may use its own versioning scheme. For example, for GitLab v15.2:
```yaml
global:
@@ -324,30 +345,33 @@ global:
gitlab:
gitaly:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
gitlab-exporter:
image:
- tag: 11.15.2-fips
+ tag: 11.17.1-fips
gitlab-shell:
image:
- tag: v15.1.0-fips
+ tag: v14.9.0-fips
gitlab-mailroom:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
+ gitlab-pages:
+ image:
+ tag: v1.61.0-fips
migrations:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
sidekiq:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
toolbox:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
webservice:
image:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
workhorse:
- tag: v15.1.0-fips
+ tag: v15.2.0-fips
```
## FIPS Performance Benchmarking
@@ -417,29 +441,6 @@ def default_min_key_size(name)
end
```
-#### Unsupported features in FIPS mode
-
-Some GitLab features may not work when FIPS mode is enabled. The following features
-are known to not work in FIPS mode. However, there may be additional features not
-listed here that also do not work properly in FIPS mode:
-
-- [Container Scanning](../user/application_security/container_scanning/index.md) support for scanning images in repositories that require authentication.
-- [Code Quality](../ci/testing/code_quality.md) does not support operating in FIPS-compliant mode.
-- [Dependency scanning](../user/application_security/dependency_scanning/index.md) support for Gradle.
-- [Dynamic Application Security Testing (DAST)](../user/application_security/dast/index.md)
- does not support operating in FIPS-compliant mode.
-- [License compliance](../user/compliance/license_compliance/index.md).
-- [Solutions for vulnerabilities](../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability)
- for yarn projects.
-- [Static Application Security Testing (SAST)](../user/application_security/sast/index.md)
- supports a reduced set of [analyzers](../user/application_security/sast/#fips-enabled-images)
- when operating in FIPS-compliant mode.
-
-Additionally, these package repositories are disabled in FIPS mode:
-
-- [Conan package repository](../user/packages/conan_repository/index.md).
-- [Debian package repository](../user/packages/debian_repository/index.md).
-
## Nightly Omnibus FIPS builds
The Distribution team has created [nightly FIPS Omnibus builds](https://packages.gitlab.com/gitlab/nightly-fips-builds). These
diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md
index e0dd0fe8e7c..cdf655bf0bf 100644
--- a/doc/development/foreign_keys.md
+++ b/doc/development/foreign_keys.md
@@ -1,200 +1,11 @@
---
-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
+redirect_to: 'database/foreign_keys.md'
+remove_date: '2022-11-05'
---
-# Foreign Keys & Associations
+This document was moved to [another location](database/foreign_keys.md).
-When adding an association to a model you must also add a foreign key. For
-example, say you have the following model:
-
-```ruby
-class User < ActiveRecord::Base
- has_many :posts
-end
-```
-
-Add a foreign key here on column `posts.user_id`. This ensures
-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
-
-Foreign keys can be added concurrently using `add_concurrent_foreign_key` as
-defined in `Gitlab::Database::MigrationHelpers`. See the [Migration Style
-Guide](migration_style_guide.md) for more information.
-
-Keep in mind that you can only safely add foreign keys to existing tables after
-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](database/add_foreign_key_to_existing_column.md).
-
-## 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
-`ON DELETE CASCADE` to `ON DELETE SET NULL` or vice-versa.
-
-PostgreSQL does not prevent you from adding overlapping foreign keys. It
-honors the most recently added constraint. This allows us to replace foreign keys without
-ever losing foreign key protection on a column.
-
-To replace a foreign key:
-
-1. [Add the new foreign key without validation](database/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.
-
- ```ruby
- class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
- disable_ddl_transaction!
-
- 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 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](database/add_foreign_key_to_existing_column.md#validate-the-foreign-key)
-
- ```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
-
- 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'
-
- # 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
- ```
-
-## Cascading Deletes
-
-Every foreign key must define an `ON DELETE` clause, and in 99% of the cases
-this should be set to `CASCADE`.
-
-## Indexes
-
-When adding a foreign key in PostgreSQL the column is not indexed automatically,
-thus you must also add a concurrent index. Not doing so results in cascading
-deletes being very slow.
-
-## Naming foreign keys
-
-By default Ruby on Rails uses the `_id` suffix for foreign keys. So we should
-only use this suffix for associations between two tables. If you want to
-reference an ID on a third party platform the `_xid` suffix is recommended.
-
-The spec `spec/db/schema_spec.rb` tests if all columns with the `_id` suffix
-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
-
-Don't define options such as `dependent: :destroy` or `dependent: :delete` when
-defining an association. Defining these options means Rails handles the
-removal of data, instead of letting the database handle this in the most
-efficient way possible.
-
-In other words, this is bad and should be avoided at all costs:
-
-```ruby
-class User < ActiveRecord::Base
- has_many :posts, dependent: :destroy
-end
-```
-
-Should you truly have a need for this it should be approved by a database
-specialist first.
-
-You should also not define any `before_destroy` or `after_destroy` callbacks on
-your models _unless_ absolutely required and only when approved by database
-specialists. For example, if each row in a table has a corresponding file on a
-file system it may be tempting to add a `after_destroy` hook. This however
-introduces non database logic to a model, and means we can no longer rely on
-foreign keys to remove the data as this would result in the file system data
-being left behind. In such a case you should use a service class instead that
-takes care of removing non database data.
-
-In cases where the relation spans multiple databases you have even
-further problems using `dependent: :destroy` or the above hooks. You can
-read more about alternatives at [Avoid `dependent: :nullify` and
-`dependent: :destroy` across
-databases](database/multiple_databases.md#avoid-dependent-nullify-and-dependent-destroy-across-databases).
-
-## Alternative primary keys with `has_one` associations
-
-Sometimes a `has_one` association is used to create a one-to-one relationship:
-
-```ruby
-class User < ActiveRecord::Base
- has_one :user_config
-end
-
-class UserConfig < ActiveRecord::Base
- belongs_to :user
-end
-```
-
-In these cases, there may be an opportunity to remove the unnecessary `id`
-column on the associated table, `user_config.id` in this example. Instead,
-the originating table ID can be used as the primary key for the associated
-table:
-
-```ruby
-create_table :user_configs, id: false do |t|
- t.references :users, primary_key: true, default: nil, index: false, foreign_key: { on_delete: :cascade }
- ...
-end
-```
-
-Setting `default: nil` ensures a primary key sequence is not created, and since 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:
-
-```ruby
-class UserConfig < ActiveRecord::Base
- self.primary_key = :user_id
-
- belongs_to :user
-end
-```
-
-Using a foreign key as primary key saves space but can make
-[batch counting](service_ping/implement.md#batch-counters) in [Service Ping](service_ping/index.md) less efficient.
-Consider using a regular `id` column if the table is relevant for Service Ping.
+<!-- This redirect file can be deleted after <2022-11-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/gemfile.md b/doc/development/gemfile.md
index 0fcfb88c9cd..f9cf69020bb 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -61,8 +61,7 @@ to a gem, go through these steps:
1. Follow the [instructions for new projects](https://about.gitlab.com/handbook/engineering/gitlab-repositories/#creating-a-new-project).
1. Follow the instructions for setting up a [CI/CD configuration](https://about.gitlab.com/handbook/engineering/gitlab-repositories/#cicd-configuration).
1. Follow the instructions for [publishing a project](https://about.gitlab.com/handbook/engineering/gitlab-repositories/#publishing-a-project).
- - See [issue
- #325463](https://gitlab.com/gitlab-org/gitlab/-/issues/325463)
+ - See [issue #325463](https://gitlab.com/gitlab-org/gitlab/-/issues/325463)
for an example.
- In some cases we may want to move a gem to its own namespace. Some
examples might be that it will naturally have more than one project
@@ -74,8 +73,8 @@ to a gem, go through these steps:
apply if someone who currently works at GitLab wants to maintain
the gem beyond their time working at GitLab.
-When publishing a gem to RubyGems.org, also note the section on [gem
-owners](https://about.gitlab.com/handbook/developer-onboarding/#ruby-gems)
+When publishing a gem to RubyGems.org, also note the section on
+[gem owners](https://about.gitlab.com/handbook/developer-onboarding/#ruby-gems)
in the handbook.
## Upgrade Rails
@@ -113,8 +112,7 @@ gem 'thor', '>= 1.1.1'
```
Here we're using the operator `>=` (greater than or equal to) rather
-than `~>` ([pessimistic
-operator](https://thoughtbot.com/blog/rubys-pessimistic-operator))
+than `~>` ([pessimistic operator](https://thoughtbot.com/blog/rubys-pessimistic-operator))
making it possible to upgrade `license_finder` or any other gem to a
version that depends on `thor 1.2`.
@@ -134,15 +132,14 @@ that also relied on `thor` but had its version pinned to a vulnerable
one. These changes are easy to miss in the `Gemfile.lock`. Pinning the
version would result in a conflict that would need to be solved.
-To avoid upgrading indirect dependencies, we can use [`bundle update
---conservative`](https://bundler.io/man/bundle-update.1.html#OPTIONS).
+To avoid upgrading indirect dependencies, we can use
+[`bundle update --conservative`](https://bundler.io/man/bundle-update.1.html#OPTIONS).
When submitting a merge request including a dependency update,
include a link to the Gem diff between the 2 versions in the merge request
description. You can find this link on `rubygems.org`, select
**Review Changes** to generate a comparison
between the versions on `diffend.io`. For example, this is the gem
-diff for [`thor` 1.0.0 vs
-1.0.1](https://my.diffend.io/gems/thor/1.0.0/1.0.1). Use the
+diff for [`thor` 1.0.0 vs 1.0.1](https://my.diffend.io/gems/thor/1.0.0/1.0.1). Use the
links directly generated from RubyGems, since the links from GitLab or other code-hosting
platforms might not reflect the code that's actually published.
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 9e9bd85ecd8..f042af42de5 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -576,7 +576,7 @@ See `Gitlab::Geo.enabled?` and `Gitlab::Geo.license_allows?` methods.
All Geo **secondary** sites are read-only.
-The general principle of a [read-only database](verifying_database_capabilities.md#read-only-database)
+The general principle of a [read-only database](database/verifying_database_capabilities.md#read-only-database)
applies to all Geo **secondary** sites. So the
`Gitlab::Database.read_only?` method will always return `true` on a
**secondary** site.
diff --git a/doc/development/geo/proxying.md b/doc/development/geo/proxying.md
index 41c7f426c6f..2f0226c489c 100644
--- a/doc/development/geo/proxying.md
+++ b/doc/development/geo/proxying.md
@@ -128,8 +128,8 @@ Secondary-->>Client: admin/geo/replication/projects logged in response (session
## Git pull
-For historical reasons, the `push_from_secondary` path is used to forward a Git pull. There is [an issue proposing to
-rename this route](https://gitlab.com/gitlab-org/gitlab/-/issues/292690) to avoid confusion.
+For historical reasons, the `push_from_secondary` path is used to forward a Git pull. There is
+[an issue proposing to rename this route](https://gitlab.com/gitlab-org/gitlab/-/issues/292690) to avoid confusion.
### Git pull over HTTP(s)
diff --git a/doc/development/git_object_deduplication.md b/doc/development/git_object_deduplication.md
index 1a864ef81f0..a6b359769f8 100644
--- a/doc/development/git_object_deduplication.md
+++ b/doc/development/git_object_deduplication.md
@@ -18,8 +18,8 @@ GitLab implements Git object deduplication.
### Understanding Git alternates
-At the Git level, we achieve deduplication by using [Git
-alternates](https://git-scm.com/docs/gitrepository-layout#gitrepository-layout-objects).
+At the Git level, we achieve deduplication by using
+[Git alternates](https://git-scm.com/docs/gitrepository-layout#gitrepository-layout-objects).
Git alternates is a mechanism that lets a repository borrow objects from
another repository on the same machine.
@@ -44,8 +44,8 @@ reliable decide if an object is no longer needed.
### Git alternates in GitLab: pool repositories
-GitLab organizes this object borrowing by [creating special **pool
-repositories**](../administration/repository_storage_types.md) which are hidden from the user. We then use Git
+GitLab organizes this object borrowing by [creating special **pool repositories**](../administration/repository_storage_types.md)
+which are hidden from the user. We then use Git
alternates to let a collection of project repositories borrow from a
single pool repository. We call such a collection of project
repositories a pool. Pools form star-shaped networks of repositories
@@ -99,9 +99,8 @@ are as follows:
### Assumptions
-- All repositories in a pool must use [hashed
- storage](../administration/repository_storage_types.md). This is so
- that we don't have to ever worry about updating paths in
+- All repositories in a pool must use [hashed storage](../administration/repository_storage_types.md).
+ This is so that we don't have to ever worry about updating paths in
`object/info/alternates` files.
- All repositories in a pool must be on the same Gitaly storage shard.
The Git alternates mechanism relies on direct disk access across
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 8a0cf8e7717..66b535682f5 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -79,8 +79,7 @@ During RSpec tests, the Gitaly instance writes logs to `gitlab/log/gitaly-test.l
While Gitaly can handle all Git access, many of GitLab customers still
run Gitaly atop NFS. The legacy Rugged implementation for Git calls may
be faster than the Gitaly RPC due to N+1 Gitaly calls and other
-reasons. See [the
-issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57317) for more
+reasons. See [the issue](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/57317) for more
details.
Until GitLab has eliminated most of these inefficiencies or the use of
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 57cb74a6159..0aa1bad711d 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -71,8 +71,8 @@ This worker imports all pull requests. For every pull request a job for the
### 5. Stage::ImportPullRequestsMergedByWorker
-This worker imports the pull requests' _merged-by_ user information. The [_List pull
-requests_](https://docs.github.com/en/rest/reference/pulls#list-pull-requests)
+This worker imports the pull requests' _merged-by_ user information. The
+[_List pull requests_](https://docs.github.com/en/rest/pulls#list-pull-requests)
API doesn't provide this information. Therefore, this stage must fetch each merged pull request
individually to import this information. A
`Gitlab::GithubImport::ImportPullRequestMergedByWorker` job is scheduled for each fetched pull
diff --git a/doc/development/gitlab_flavored_markdown/specification_guide/index.md b/doc/development/gitlab_flavored_markdown/specification_guide/index.md
index 80837506037..756b87cd407 100644
--- a/doc/development/gitlab_flavored_markdown/specification_guide/index.md
+++ b/doc/development/gitlab_flavored_markdown/specification_guide/index.md
@@ -54,7 +54,7 @@ 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)
-which is committed to the `gitlab` repo and used as input to the
+which is committed to the `gitlab` repository and used as input to the
[`update_specification.rb` script](#update-specificationrb-script).
The original CommonMark specification is referred to as _CommonMark_ (no acronym).
@@ -86,6 +86,51 @@ it does not have a static, hardcoded, manually updated `spec.txt`. Instead, the
GLFM `spec.txt` is automatically generated based on other input files. This process
is explained in detail in the [Implementation](#implementation) sections below.
+#### Official specifications vs internal extensions
+
+Within GFM and GLFM respectively, both GitHub and GitLab have two "sets" of Markdown they support:
+
+- Official specification
+- Internal extensions
+
+The following taxonomy chart shows the taxonomy and terminology of the various specifications:
+
+```mermaid
+graph TD
+CM[CommonMark - spec.txt - e.g. headings] --- GFMS[GFM Specification - spec.txt - e.g. strikethrough extension]
+GFMS --- GLFM[GLFM Specification - e.g. color chips]
+GFMS --- GFMI[GFM internal extensions - e.g. GitHub-specific references]
+GLFM --- GLFS[GLFM internal extensions - e.g. GitLab-specific references]
+```
+
+##### Official specifications
+
+GFM and GLFM each have an official specification, which includes both:
+
+1. The CommonMark standard.
+1. Generic extensions to the CommonMark standard.
+
+For example, GFM adds the
+[`strikethrough` extension](https://github.github.com/gfm/#strikethrough-extension-),
+and GLFM adds the
+[`color chips` extension](../../../user/markdown.md#colors).
+These extensions in the official specifications are not dependent upon any specific
+implementation or environment. They can be implemented in any third-party Markdown rendering engine.
+
+##### Internal extensions
+
+GFM and GLFM each also have a set of internal extensions. These extensions are not part of the GFM or GLFM
+official specifications, but are part of the GitHub and GitLab internal Markdown renderer and parser
+implementations. These internal extensions are often dependent upon the GitHub or GitLab
+implementations or environments, and may depend upon metadata which is only available via
+interacting with those environments. For example,
+[GitHub supports GitHub-specific autolinked references](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls),
+and
+[GitLab also supports GitLab-specific references](../../../user/markdown.md#gitlab-specific-references).
+These may also be implemented by third-party Markdown rendering engines which integrate with
+GitHub or GitLab. For example, editor or IDE plugins which enable the user to directly edit
+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
@@ -136,7 +181,7 @@ NOTE:
#### Markdown snapshot testing
_Markdown snapshot testing_ refers to the automated testing performed in
-the GitLab codebase, which is driven by "example_snapshots" fixture data derived from all of
+the GitLab codebase, which is driven by `example_snapshots` fixture data derived from all of
the examples in the GLFM specification. It consists of both backend RSpec tests and frontend Jest
tests which use the fixture data. This fixture data is contained in YAML files. These files
are generated and updated based on the Markdown examples in the specification,
diff --git a/doc/development/go_guide/dependencies.md b/doc/development/go_guide/dependencies.md
index 0c2ce4f2b48..2a53fa590e3 100644
--- a/doc/development/go_guide/dependencies.md
+++ b/doc/development/go_guide/dependencies.md
@@ -44,9 +44,9 @@ end with a timestamp and the first 12 characters of the commit identifier:
If a VCS tag matches one of these patterns, it is ignored.
-For a complete understanding of Go modules and versioning, see [this series of
-blog posts](https://go.dev/blog/using-go-modules) on the official Go
-website.
+For a complete understanding of Go modules and versioning, see
+[this series of blog posts](https://go.dev/blog/using-go-modules)
+on the official Go website.
## 'Module' vs 'Package'
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 1a11321b70f..711b0662a8c 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -145,18 +145,16 @@ Go GitLab linter plugins are maintained in the [`gitlab-org/language-tools/go/li
## Dependencies
Dependencies should be kept to the minimum. The introduction of a new
-dependency should be argued in the merge request, as per our [Approval
-Guidelines](../code_review.md#approval-guidelines). Both [License
-Scanning](../../user/compliance/license_compliance/index.md)
-**(ULTIMATE)** and [Dependency
-Scanning](../../user/application_security/dependency_scanning/index.md)
-**(ULTIMATE)** should be activated on all projects to ensure new dependencies
+dependency should be argued in the merge request, as per our [Approval Guidelines](../code_review.md#approval-guidelines).
+Both [License Scanning](../../user/compliance/license_compliance/index.md)
+and [Dependency Scanning](../../user/application_security/dependency_scanning/index.md)
+should be activated on all projects to ensure new dependencies
security status and license compatibility.
### Modules
-In Go 1.11 and later, a standard dependency system is available behind the name [Go
-Modules](https://github.com/golang/go/wiki/Modules). It provides a way to
+In Go 1.11 and later, a standard dependency system is available behind the name
+[Go Modules](https://github.com/golang/go/wiki/Modules). It provides a way to
define and lock dependencies for reproducible builds. It should be used
whenever possible.
@@ -168,8 +166,8 @@ projects, and makes merge requests easier to review.
In some cases, such as building a Go project for it to act as a dependency of a
CI run for another project, removing the `vendor/` directory means the code must
be downloaded repeatedly, which can lead to intermittent problems due to rate
-limiting or network failures. In these circumstances, you should [cache the
-downloaded code between](../../ci/caching/index.md#cache-go-dependencies).
+limiting or network failures. In these circumstances, you should
+[cache the downloaded code between](../../ci/caching/index.md#cache-go-dependencies).
There was a
[bug on modules checksums](https://github.com/golang/go/issues/29278) in Go versions earlier than v1.11.4, so make
@@ -330,18 +328,15 @@ A few things to keep in mind when adding context:
### References for working with errors
- [Go 1.13 errors](https://go.dev/blog/go1.13-errors).
-- [Programing with
- errors](https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html).
-- [Don't just check errors, handle them
- gracefully](https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully).
+- [Programing with errors](https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html).
+- [Don't just check errors, handle them gracefully](https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully).
## CLIs
Every Go program is launched from the command line.
[`cli`](https://github.com/urfave/cli) is a convenient package to create command
line apps. It should be used whether the project is a daemon or a simple CLI
-tool. Flags can be mapped to [environment
-variables](https://github.com/urfave/cli#values-from-the-environment) directly,
+tool. Flags can be mapped to [environment variables](https://github.com/urfave/cli#values-from-the-environment) directly,
which documents and centralizes at the same time all the possible command line
interactions with the program. Don't use `os.GetEnv`, it hides variables deep
in the code.
@@ -362,8 +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 simply 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
@@ -414,8 +408,7 @@ should be used in functions that can block and passed as the first parameter.
Every project should have a `Dockerfile` at the root of their repository, to
build and run the project. Since Go program are static binaries, they should
not require any external dependency, and shells in the final image are useless.
-We encourage [Multistage
-builds](https://docs.docker.com/develop/develop-images/multistage-build/):
+We encourage [Multistage builds](https://docs.docker.com/develop/develop-images/multistage-build/):
- They let the user build the project with the right Go version and
dependencies.
@@ -448,36 +441,28 @@ up to run `goimports -local gitlab.com/gitlab-org` so that it's applied to every
If initializing a slice, provide a capacity where possible to avoid extra
allocations.
-<table>
-<tr><th>:white_check_mark: Do</th><th>:x: Don't</th></tr>
-<tr>
- <td>
+**Don't:**
- ```golang
- s2 := make([]string, 0, size)
- for _, val := range s1 {
- s2 = append(s2, val)
- }
- ```
+```golang
+var s2 []string
+for _, val := range s1 {
+ s2 = append(s2, val)
+}
+```
- </td>
- <td>
+**Do:**
- ```golang
- var s2 []string
- for _, val := range s1 {
- s2 = append(s2, val)
- }
- ```
-
- </td>
-</tr>
-</table>
+```golang
+s2 := make([]string, 0, size)
+for _, val := range s1 {
+ s2 = append(s2, val)
+}
+```
If no capacity is passed to `make` when creating a new slice, `append`
will continuously resize the slice's backing array if it cannot hold
the values. Providing the capacity ensures that allocations are kept
-to a minimum. It is recommended that the [`prealloc`](https://github.com/alexkohler/prealloc)
+to a minimum. It's recommended that the [`prealloc`](https://github.com/alexkohler/prealloc)
golanci-lint rule automatically check for this.
### Analyzer Tests
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index d89dbbcf904..af11340737f 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -200,8 +200,7 @@ refresh_service.execute(oldrev, newrev, ref)
See ["Why is it bad style to `rescue Exception => e` in Ruby?"](https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby).
-This rule is [enforced automatically by
-RuboCop](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-4-stable/.rubocop.yml#L911-914)._
+This rule is [enforced automatically by RuboCop](https://gitlab.com/gitlab-org/gitlab-foss/blob/8-4-stable/.rubocop.yml#L911-914)._
## Do not use inline JavaScript in views
diff --git a/doc/development/hash_indexes.md b/doc/development/hash_indexes.md
index 731639b6f06..2a9f7e5a25d 100644
--- a/doc/development/hash_indexes.md
+++ b/doc/development/hash_indexes.md
@@ -1,26 +1,11 @@
---
-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
+redirect_to: 'database/hash_indexes.md'
+remove_date: '2022-11-06'
---
-# Hash Indexes
+This document was moved to [another location](database/hash_indexes.md).
-PostgreSQL supports hash indexes besides the regular B-tree
-indexes. Hash indexes however are to be avoided at all costs. While they may
-_sometimes_ provide better performance the cost of rehashing can be very high.
-More importantly: at least until PostgreSQL 10.0 hash indexes are not
-WAL-logged, meaning they are not replicated to any replicas. From the PostgreSQL
-documentation:
-
-> Hash index operations are not presently WAL-logged, so hash indexes might need
-> to be rebuilt with REINDEX after a database crash if there were unwritten
-> changes. Also, changes to hash indexes are not replicated over streaming or
-> file-based replication after the initial base backup, so they give wrong
-> answers to queries that subsequently use them. For these reasons, hash index
-> use is presently discouraged.
-
-RuboCop is configured to register an offense when it detects the use of a hash
-index.
-
-Instead of using hash indexes you should use regular B-tree indexes.
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/i18n/externalization.md b/doc/development/i18n/externalization.md
index 18704fc2b60..ea22b33f1bc 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -85,7 +85,7 @@ Or:
hello = _("Hello world!")
```
-Be careful when translating strings at the class or module level since these are only evaluated once
+Be careful when translating strings at the class or module level because these are only evaluated once
at class load time. For example:
```ruby
@@ -299,16 +299,16 @@ use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. Make sure to
- In Ruby/HAML:
```ruby
- _("Hello %{name}") % { name: 'Joe' } => 'Hello Joe'
+ format(_("Hello %{name}"), name: 'Joe') => 'Hello Joe'
```
- In Vue:
Use the [`GlSprintf`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/docs/utilities-sprintf--sentence-with-link) component if:
- - You need to include child components in the translation string.
- - You need to include HTML in your translation string.
- - You're using `sprintf` and need to pass `false` as the third argument to
+ - You are including child components in the translation string.
+ - You are including HTML in your translation string.
+ - You are using `sprintf` and are passing `false` as the third argument to
prevent it from escaping placeholder values.
For example:
@@ -482,7 +482,7 @@ Instead of this:
```ruby
# incorrect usage example
-n_("%{project_name}", "%d projects selected", count) % { project_name: 'GitLab' }
+format(n_("%{project_name}", "%d projects selected", count), project_name: 'GitLab')
```
### Namespaces
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index cee078ca891..f986a852567 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -34,6 +34,7 @@ are very appreciative of the work done by translators and proofreaders!
- Weizhe Ding - [GitLab](https://gitlab.com/d.weizhe), [Crowdin](https://crowdin.com/profile/d.weizhe)
- Yi-Jyun Pan - [GitLab](https://gitlab.com/pan93412), [Crowdin](https://crowdin.com/profile/pan93412)
- Victor Wu - [GitLab](https://gitlab.com/_victorwu_), [Crowdin](https://crowdin.com/profile/victorwu)
+ - Hansel Wang - [GitLab](https://gitlab.com/airness), [Crowdin](https://crowdin.com/profile/airness)
- Chinese Traditional, Hong Kong ç¹é«”中文 (香港)
- Victor Wu - [GitLab](https://gitlab.com/_victorwu_), [Crowdin](https://crowdin.com/profile/victorwu)
- Ivan Ip - [GitLab](https://gitlab.com/lifehome), [Crowdin](https://crowdin.com/profile/lifehome)
@@ -63,7 +64,6 @@ are very appreciative of the work done by translators and proofreaders!
- German
- 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)
- - Justman10000 - [GitLab](https://gitlab.com/Justman10000), [Crowdin](https://crowdin.com/profile/Justman10000)
- Vladislav Wanner - [GitLab](https://gitlab.com/RumBugen), [Crowdin](https://crowdin.com/profile/RumBugen)
- Greek
- Proofreaders needed.
diff --git a/doc/development/image_scaling.md b/doc/development/image_scaling.md
index 93575429369..2078db8294c 100644
--- a/doc/development/image_scaling.md
+++ b/doc/development/image_scaling.md
@@ -1,6 +1,6 @@
---
stage: Data Stores
-group: Memory
+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
---
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index 2a29df380de..6cbbb6bf716 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -113,8 +113,8 @@ Marked stuck import jobs as failed. JIDs: xyz
While the performance problems are not tackled, there is a process to workaround
importing big projects, using a foreground import:
-[Foreground import](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/5384) of big projects for customers.
-(Using the import template in the [infrastructure tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/))
+[Foreground import](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/5384) of big projects for customers.
+(Using the import template in the [infrastructure tracker](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues))
## Security
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index c63ba229921..7c55d2e2668 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -144,7 +144,7 @@ project files on disk.
##### Import is successful, but with a `Total number of not imported relations: XX` message, and issues are not created during the import
If you receive a `Total number of not imported relations: XX` message, and issues
-aren't created during the import, check [exceptions_json.log](../administration/logs.md#exceptions_jsonlog).
+aren't created during the import, check [exceptions_json.log](../administration/logs/index.md#exceptions_jsonlog).
You might see an error like `N is out of range for ActiveModel::Type::Integer with limit 4 bytes`,
where `N` is the integer exceeding the 4-byte integer limit. If that's the case, you
are likely hitting the issue with rebalancing of `relative_position` field of the issues.
diff --git a/doc/development/index.md b/doc/development/index.md
index 1b897db5097..34e6f466664 100644
--- a/doc/development/index.md
+++ b/doc/development/index.md
@@ -7,9 +7,9 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
description: "Development Guidelines: learn how to contribute to GitLab."
---
-# Contributor and Development Docs
+# Contribute to the development of GitLab
-Learn the processes and technical information needed for contributing to GitLab.
+Learn how to contribute to the development of the GitLab product.
This content is intended for members of the GitLab Team as well as community
contributors. Content specific to the GitLab Team should instead be included in
diff --git a/doc/development/insert_into_tables_in_batches.md b/doc/development/insert_into_tables_in_batches.md
index ebed3d16319..ced5332e880 100644
--- a/doc/development/insert_into_tables_in_batches.md
+++ b/doc/development/insert_into_tables_in_batches.md
@@ -1,196 +1,11 @@
---
-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
-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
-of APIs that make it safe and simple to insert ActiveRecord objects in bulk."
+redirect_to: 'database/insert_into_tables_in_batches.md'
+remove_date: '2022-11-05'
---
-# Insert into tables in batches
+This document was moved to [another location](database/insert_into_tables_in_batches.md).
-Sometimes it is necessary to store large amounts of records at once, which can be inefficient
-when iterating collections and saving each record individually. With the arrival of
-[`insert_all`](https://apidock.com/rails/ActiveRecord/Persistence/ClassMethods/insert_all)
-in Rails 6, which operates at the row level (that is, using `Hash` objects), GitLab has added a set
-of APIs that make it safe and simple to insert `ActiveRecord` objects in bulk.
-
-## Prepare `ApplicationRecord`s for bulk insertion
-
-In order for a model class to take advantage of the bulk insertion API, it has to include the
-`BulkInsertSafe` concern first:
-
-```ruby
-class MyModel < ApplicationRecord
- # other includes here
- # ...
- include BulkInsertSafe # include this last
-
- # ...
-end
-```
-
-The `BulkInsertSafe` concern has two functions:
-
-- It performs checks against your model class to ensure that it does not use ActiveRecord
- APIs that are not safe to use with respect to bulk insertions (more on that below).
-- It adds new class methods `bulk_insert!` and `bulk_upsert!`, which you can use to insert many records at once.
-
-## Insert records with `bulk_insert!` and `bulk_upsert!`
-
-If the target class passes the checks performed by `BulkInsertSafe`, you can insert an array of
-ActiveRecord model objects as follows:
-
-```ruby
-records = [MyModel.new, ...]
-
-MyModel.bulk_insert!(records)
-```
-
-Calls to `bulk_insert!` always attempt to insert _new records_. If instead
-you would like to replace existing records with new values, while still inserting those
-that do not already exist, then you can use `bulk_upsert!`:
-
-```ruby
-records = [MyModel.new, existing_model, ...]
-
-MyModel.bulk_upsert!(records, unique_by: [:name])
-```
-
-In this example, `unique_by` specifies the columns by which records are considered to be
-unique and as such are updated if they existed prior to insertion. For example, if
-`existing_model` has a `name` attribute, and if a record with the same `name` value already
-exists, its fields are updated with those of `existing_model`.
-
-The `unique_by` parameter can also be passed as a `Symbol`, in which case it specifies
-a database index by which a column is considered unique:
-
-```ruby
-MyModel.bulk_insert!(records, unique_by: :index_on_name)
-```
-
-### Record validation
-
-The `bulk_insert!` method guarantees that `records` are inserted transactionally, and
-runs validations on each record prior to insertion. If any record fails to validate,
-an error is raised and the transaction is rolled back. You can turn off validations via
-the `:validate` option:
-
-```ruby
-MyModel.bulk_insert!(records, validate: false)
-```
-
-### Batch size configuration
-
-In those cases where the number of `records` is above a given threshold, insertions
-occur in multiple batches. The default batch size is defined in
-[`BulkInsertSafe::DEFAULT_BATCH_SIZE`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/bulk_insert_safe.rb).
-Assuming a default threshold of 500, inserting 950 records
-would result in two batches being written sequentially (of size 500 and 450 respectively.)
-You can override the default batch size via the `:batch_size` option:
-
-```ruby
-MyModel.bulk_insert!(records, batch_size: 100)
-```
-
-Assuming the same number of 950 records, this would result in 10 batches being written instead.
-Since this also affects the number of `INSERT` statements that occur, make sure you measure the
-performance impact this might have on your code. There is a trade-off between the number of
-`INSERT` statements the database has to process and the size and cost of each `INSERT`.
-
-### Handling duplicate records
-
-NOTE:
-This parameter applies only to `bulk_insert!`. If you intend to update existing
-records, use `bulk_upsert!` instead.
-
-It may happen that some records you are trying to insert already exist, which would result in
-primary key conflicts. There are two ways to address this problem: failing fast by raising an
-error or skipping duplicate records. The default behavior of `bulk_insert!` is to fail fast
-and raise an `ActiveRecord::RecordNotUnique` error.
-
-If this is undesirable, you can instead skip duplicate records with the `skip_duplicates` flag:
-
-```ruby
-MyModel.bulk_insert!(records, skip_duplicates: true)
-```
-
-### Requirements for safe bulk insertions
-
-Large parts of ActiveRecord's persistence API are built around the notion of callbacks. Many
-of these callbacks fire in response to model life cycle events such as `save` or `create`.
-These callbacks cannot be used with bulk insertions, since they are meant to be called for
-every instance that is saved or created. Since these events do not fire when
-records are inserted in bulk, we currently prevent their use.
-
-The specifics around which callbacks are explicitly allowed are defined in
-[`BulkInsertSafe`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/concerns/bulk_insert_safe.rb).
-Consult the module source code for details. If your class uses callbacks that are not explicitly designated
-safe and you `include BulkInsertSafe` the application fails with an error.
-
-### `BulkInsertSafe` versus `InsertAll`
-
-Internally, `BulkInsertSafe` is based on `InsertAll`, and you may wonder when to choose
-the former over the latter. To help you make the decision,
-the key differences between these classes are listed in the table below.
-
-| | Input type | Validates input | Specify batch size | Can bypass callbacks | Transactional |
-|--------------- | -------------------- | --------------- | ------------------ | --------------------------------- | ------------- |
-| `bulk_insert!` | ActiveRecord objects | Yes (optional) | Yes (optional) | No (prevents unsafe callback use) | Yes |
-| `insert_all!` | Attribute hashes | No | No | Yes | Yes |
-
-To summarize, `BulkInsertSafe` moves bulk inserts closer to how ActiveRecord objects
-and inserts would normally behave. However, if all you need is to insert raw data in bulk, then
-`insert_all` is more efficient.
-
-## Insert `has_many` associations in bulk
-
-A common use case is to save collections of associated relations through the owner side of the relation,
-where the owned relation is associated to the owner through the `has_many` class method:
-
-```ruby
-owner = OwnerModel.new(owned_relations: array_of_owned_relations)
-# saves all `owned_relations` one-by-one
-owner.save!
-```
-
-This issues a single `INSERT`, and transaction, for every record in `owned_relations`, which is inefficient if
-`array_of_owned_relations` is large. To remedy this, the `BulkInsertableAssociations` concern can be
-used to declare that the owner defines associations that are safe for bulk insertion:
-
-```ruby
-class OwnerModel < ApplicationRecord
- # other includes here
- # ...
- include BulkInsertableAssociations # include this last
-
- has_many :my_models
-end
-```
-
-Here `my_models` must be declared `BulkInsertSafe` (as described previously) for bulk insertions
-to happen. You can now insert any yet unsaved records as follows:
-
-```ruby
-BulkInsertableAssociations.with_bulk_insert do
- owner = OwnerModel.new(my_models: array_of_my_model_instances)
- # saves `my_models` using a single bulk insert (possibly via multiple batches)
- owner.save!
-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.
-
-## Known limitations
-
-There are a few restrictions to how these APIs can be used:
-
-- `BulkInsertableAssociations`:
- - It is currently only compatible with `has_many` relations.
- - It does not yet support `has_many through: ...` relations.
-
-Moreover, input data should either be limited to around 1000 records at most,
-or already batched prior to calling bulk insert. The `INSERT` statement runs in a single
-transaction, so for large amounts of records it may negatively affect database stability.
+<!-- This redirect file can be deleted after <2022-11-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/integrations/index.md b/doc/development/integrations/index.md
index 5d1bd5ad61c..0387ba2e4dd 100644
--- a/doc/development/integrations/index.md
+++ b/doc/development/integrations/index.md
@@ -273,7 +273,7 @@ When developing a new integration, we also recommend you gate the availability b
You can provide help text in the integration form, including links to off-site documentation,
as described above in [Customize the frontend form](#customize-the-frontend-form). Refer to
-our [usability guidelines](https://design.gitlab.com/usability/helping-users) for help text.
+our [usability guidelines](https://design.gitlab.com/usability/helping-users/) for help text.
For more detailed documentation, provide a page in `doc/user/project/integrations`,
and link it from the [Integrations overview](../../user/project/integrations/index.md).
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 0a0c5e4d2a6..55e57a3c2ee 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -151,7 +151,7 @@ Depending on the CI infrastructure,
the CI may have to fetch the Docker image every time the job runs.
For the scanning job to run fast and avoid wasting bandwidth, Docker images should be as small as
possible. You should aim for 50MB or smaller. If that isn't possible, try to keep it below 1.46 GB,
-which is the size of a CD-ROM.
+which is the size of a DVD-ROM.
If the scanner requires a fully functional Linux environment,
it is recommended to use a [Debian](https://www.debian.org/intro/about) "slim" distribution or [Alpine Linux](https://www.alpinelinux.org/).
@@ -253,6 +253,10 @@ then `artifacts:reports:dependency_scanning` must be set to `depscan.json`.
Following the POSIX exit code standard, the scanner exits with 0 for success and any number from 1 to 255 for anything else.
Success also includes the case when vulnerabilities are found.
+When a CI job fails, security report results are not ingested by GitLab, even if the job
+[allows failure](../../ci/yaml/#allow_failure). The report artifacts are still uploaded to GitLab and available
+for [download in the pipeline security tab](../../user/application_security/vulnerability_report/pipeline.md#download-security-scan-outputs).
+
When executing a scanning job using the [Docker-in-Docker privileged mode](../../user/application_security/sast/index.md#requirements),
we reserve the following standard exit codes.
@@ -310,7 +314,7 @@ This documentation gives an overview of the report JSON format,
as well as recommendations and examples to help integrators set its fields.
The format is extensively described in the documentation of
[SAST](../../user/application_security/sast/index.md#reports-json-format),
-[DAST](../../user/application_security/dast/#reports),
+[DAST](../../user/application_security/dast/index.md#reports),
[Dependency Scanning](../../user/application_security/dependency_scanning/index.md#reports-json-format),
and [Container Scanning](../../user/application_security/container_scanning/index.md#reports-json-format)
@@ -493,19 +497,20 @@ We recommend that you use the identifiers the GitLab scanners already define:
|------------|------|---------------|
| [CVE](https://cve.mitre.org/cve/) | `cve` | CVE-2019-10086 |
| [CWE](https://cwe.mitre.org/data/index.html) | `cwe` | CWE-1026 |
+| [ELSA](https://linux.oracle.com/security/) | `elsa` | ELSA-2020-0085 |
| [OSVD](https://cve.mitre.org/data/refs/refmap/source-OSVDB.html) | `osvdb` | OSVDB-113928 |
+| [OWASP](https://owasp.org/Top10/) | `owasp` | A01:2021–Broken Access Control Design |
+| [RHSA](https://access.redhat.com/errata-search/#/) | `rhsa` | RHSA-2020:0111 |
| [USN](https://ubuntu.com/security/notices) | `usn` | USN-4234-1 |
| [WASC](http://projects.webappsec.org/Threat-Classification-Reference-Grid) | `wasc` | WASC-19 |
-| [RHSA](https://access.redhat.com/errata/#/) | `rhsa` | RHSA-2020:0111 |
-| [ELSA](https://linux.oracle.com/security/) | `elsa` | ELSA-2020-0085 |
The generic identifiers listed above are defined in the [common library](https://gitlab.com/gitlab-org/security-products/analyzers/common),
which is shared by some of the analyzers that GitLab maintains. You can [contribute](https://gitlab.com/gitlab-org/security-products/analyzers/common/blob/master/issue/identifier.go)
new generic identifiers to if needed. Analyzers may also produce vendor-specific or product-specific
identifiers, which don't belong in the [common library](https://gitlab.com/gitlab-org/security-products/analyzers/common).
-The first item of the `identifiers` array is called the [primary
-identifier](../../user/application_security/terminology/#primary-identifier).
+The first item of the `identifiers` array is called the
+[primary identifier](../../user/application_security/terminology/index.md#primary-identifier).
The primary identifier is particularly important, because it is used to
[track vulnerabilities](#tracking-and-merging-vulnerabilities) as new commits are pushed to the repository.
Identifiers are also used to [merge duplicate vulnerabilities](#tracking-and-merging-vulnerabilities)
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index 13e095b4a83..9b29af3e433 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -148,8 +148,8 @@ curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
## Authorized Keys Check
This endpoint is called by the GitLab Shell authorized keys
-check. Which is called by OpenSSH for [fast SSH key
-lookup](../../administration/operations/fast_ssh_key_lookup.md).
+check. Which is called by OpenSSH for
+[fast SSH key lookup](../../administration/operations/fast_ssh_key_lookup.md).
| Attribute | Type | Required | Description |
|:----------|:-------|:---------|:------------|
@@ -494,10 +494,15 @@ curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
Called from GitLab agent server (`kas`) to increase the usage
metric counters.
-| Attribute | Type | Required | Description |
-|:----------|:-------|:---------|:------------|
-| `gitops_sync_count` | integer| no | The number to increase the `gitops_sync_count` counter by |
-| `k8s_api_proxy_request_count` | integer| no | The number to increase the `k8s_api_proxy_request_count` counter by |
+| Attribute | Type | Required | Description |
+|:---------------------------------------------------------------------------|:--------------|:---------|:-----------------------------------------------------------------------------------------------------------------|
+| `gitops_sync_count` (DEPRECATED) | integer | no | The number to increase the `gitops_sync` counter by |
+| `k8s_api_proxy_request_count` (DEPRECATED) | integer | no | The number to increase the `k8s_api_proxy_request` counter by |
+| `counters` | hash | no | The number to increase the `k8s_api_proxy_request` counter by |
+| `counters["k8s_api_proxy_request"]` | integer | no | The number to increase the `k8s_api_proxy_request` counter by |
+| `counters["gitops_sync"]` | integer | no | The number to increase the `gitops_sync` counter by |
+| `unique_counters` | hash | no | The number to increase the `k8s_api_proxy_request` counter by |
+| `unique_counters["agent_users_using_ci_tunnel"]` | integer array | no | The set of unique user ids that have interacted a CI Tunnel to track the `agent_users_using_ci_tunnel` metric event |
```plaintext
POST /internal/kubernetes/usage_metrics
@@ -624,6 +629,40 @@ Example response:
}
```
+### Policy Configuration
+
+Called from GitLab agent server (`kas`) to retrieve `policies_configuration`
+configured for the project belonging to the agent token. GitLab `kas` uses
+this to configure the agent to scan images in the Kubernetes cluster based on the configuration.
+
+```plaintext
+GET /internal/kubernetes/modules/starboard_vulnerability/policies_configuration
+```
+
+Example Request:
+
+```shell
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
+ --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/modules/starboard_vulnerability/policies_configuration"
+```
+
+Example response:
+
+```json
+{
+ "configurations": [
+ {
+ "cadence": "30 2 * * *",
+ "namespaces": [
+ "namespace-a",
+ "namespace-b"
+ ],
+ "updated_at": "2022-06-02T05:36:26+00:00"
+ }
+ ]
+}
+```
+
## Subscriptions
The subscriptions endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`)
diff --git a/doc/development/issue_types.md b/doc/development/issue_types.md
index e6047c62827..820c37aeb14 100644
--- a/doc/development/issue_types.md
+++ b/doc/development/issue_types.md
@@ -13,10 +13,8 @@ Sometimes when a new resource type is added it's not clear if it should be only
"extension" of Issue (Issue Type) or if it should be a new first-class resource type
(similar to issue, epic, merge request, snippet).
-The idea of Issue Types was first proposed in [this
-issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8767) and its usage was
-discussed few times since then, for example in [incident
-management](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55532).
+The idea of Issue Types was first proposed in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8767) and its usage was
+discussed few times since then, for example in [incident management](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55532).
## What is an Issue Type
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 1159e3755e5..589e38a5cb0 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -1,598 +1,11 @@
---
-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
+redirect_to: 'database/iterating_tables_in_batches.md'
+remove_date: '2022-11-06'
---
-# Iterating tables in batches
+This document was moved to [another location](database/iterating_tables_in_batches.md).
-Rails provides a method called `in_batches` that can be used to iterate over
-rows in batches. For example:
-
-```ruby
-User.in_batches(of: 10) do |relation|
- relation.update_all(updated_at: Time.now)
-end
-```
-
-Unfortunately, this method is implemented in a way that is not very efficient,
-both query and memory usage wise.
-
-To work around this you can include the `EachBatch` module into your models,
-then use the `each_batch` class method. For example:
-
-```ruby
-class User < ActiveRecord::Base
- include EachBatch
-end
-
-User.each_batch(of: 10) do |relation|
- relation.update_all(updated_at: Time.now)
-end
-```
-
-This produces queries such as:
-
-```plaintext
-User Load (0.7ms) SELECT "users"."id" FROM "users" WHERE ("users"."id" >= 41654) ORDER BY "users"."id" ASC LIMIT 1 OFFSET 1000
- (0.7ms) SELECT COUNT(*) FROM "users" WHERE ("users"."id" >= 41654) AND ("users"."id" < 42687)
-```
-
-The API of this method is similar to `in_batches`, though it doesn't support
-all of the arguments that `in_batches` supports. You should always use
-`each_batch` _unless_ you have a specific need for `in_batches`.
-
-## Iterating over non-unique columns
-
-One should proceed with extra caution. When you iterate over an attribute that is not unique,
-even with the applied max batch size, there is no guarantee that the resulting batches do not
-surpass it. The following snippet demonstrates this situation when one attempt to select
-`Ci::Build` entries for users with `id` between `1` and `10,000`, the database returns
-`1 215 178` matching rows.
-
-```ruby
-[ gstg ] production> Ci::Build.where(user_id: (1..10_000)).size
-=> 1215178
-```
-
-This happens because the built relation is translated into the following query:
-
-```ruby
-[ gstg ] production> puts Ci::Build.where(user_id: (1..10_000)).to_sql
-SELECT "ci_builds".* FROM "ci_builds" WHERE "ci_builds"."type" = 'Ci::Build' AND "ci_builds"."user_id" BETWEEN 1 AND 10000
-=> nil
-```
-
-`And` queries which filter non-unique column by range `WHERE "ci_builds"."user_id" BETWEEN ? AND ?`,
-even though the range size is limited to a certain threshold (`10,000` in the previous example) this
-threshold does not translate to the size of the returned dataset. That happens because when taking
-`n` possible values of attributes, one can't tell for sure that the number of records that contains
-them is less than `n`.
-
-### Loose-index scan with `distinct_each_batch`
-
-When iterating over a non-unique column is necessary, use the `distinct_each_batch` helper
-method. The helper uses the [loose-index scan technique](https://wiki.postgresql.org/wiki/Loose_indexscan)
-(skip-index scan) to skip duplicated values within a database index.
-
-Example: iterating over distinct `author_id` in the Issue model
-
-```ruby
-Issue.distinct_each_batch(column: :author_id, of: 1000) do |relation|
- users = User.where(id: relation.select(:author_id)).to_a
-end
-```
-
-The technique provides stable performance between the batches regardless of the data distribution.
-The `relation` object returns an ActiveRecord scope where only the given `column` is available.
-Other columns are not loaded.
-
-The underlying database queries use recursive CTEs, which adds extra overhead. We therefore advise to use
-smaller batch sizes than those used for a standard `each_batch` iteration.
-
-## Column definition
-
-`EachBatch` uses the primary key of the model by default for the iteration. This works most of the
-cases, however in some cases, you might want to use a different column for the iteration.
-
-```ruby
-Project.distinct.each_batch(column: :creator_id, of: 10) do |relation|
- puts User.where(id: relation.select(:creator_id)).map(&:id)
-end
-```
-
-The query above iterates over the project creators and prints them out without duplications.
-
-NOTE:
-In case the column is not unique (no unique index definition), calling the `distinct` method on
-the relation is necessary. Using not unique column without `distinct` may result in `each_batch`
-falling into an endless loop as described in following
-[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/285097).
-
-## `EachBatch` in data migrations
-
-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](database/background_migrations.md#scheduling)
-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`.
-
-## Efficient usage of `each_batch`
-
-`EachBatch` helps to iterate over large tables. It's important to highlight that `EachBatch`
-does not magically solve all iteration-related performance problems, and it might not help at
-all in some scenarios. From the database point of view, correctly configured database indexes are
-also necessary to make `EachBatch` perform well.
-
-### Example 1: Simple iteration
-
-Let's consider that we want to iterate over the `users` table and print the `User` records to the
-standard output. The `users` table contains millions of records, thus running one query to fetch
-the users likely times out.
-
-![Users table overview](img/each_batch_users_table_v13_7.png)
-
-This is a simplified version of the `users` table which contains several rows. We have a few
-smaller gaps in the `id` column to make the example a bit more realistic (a few records were
-already deleted). Currently, we have one index on the `id` field.
-
-Loading all users into memory (avoid):
-
-```ruby
-users = User.all
-
-users.each { |user| puts user.inspect }
-```
-
-Use `each_batch`:
-
-```ruby
-# Note: for this example I picked 5 as the batch size, the default is 1_000
-User.each_batch(of: 5) do |relation|
- relation.each { |user| puts user.inspect }
-end
-```
-
-#### How `each_batch` works
-
-As the first step, it finds the lowest `id` (start `id`) in the table by executing the following
-database query:
-
-```sql
-SELECT "users"."id" FROM "users" ORDER BY "users"."id" ASC LIMIT 1
-```
-
-![Reading the start ID value](img/each_batch_users_table_iteration_1_v13_7.png)
-
-Notice that the query only reads data from the index (`INDEX ONLY SCAN`), the table is not
-accessed. Database indexes are sorted so taking out the first item is a very cheap operation.
-
-The next step is to find the next `id` (end `id`) which should respect the batch size
-configuration. In this example we used a batch size of 5. `EachBatch` uses the `OFFSET` clause
-to get a "shifted" `id` value.
-
-```sql
-SELECT "users"."id" FROM "users" WHERE "users"."id" >= 1 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
-```
-
-![Reading the end ID value](img/each_batch_users_table_iteration_2_v13_7.png)
-
-Again, the query only looks into the index. The `OFFSET 5` takes out the sixth `id` value: this
-query reads a maximum of six items from the index regardless of the table size or the iteration
-count.
-
-At this point, we know the `id` range for the first batch. Now it's time to construct the query
-for the `relation` block.
-
-```sql
-SELECT "users".* FROM "users" WHERE "users"."id" >= 1 AND "users"."id" < 302
-```
-
-![Reading the rows from the `users` table](img/each_batch_users_table_iteration_3_v13_7.png)
-
-Notice the `<` sign. Previously six items were read from the index and in this query, the last
-value is "excluded". The query looks at the index to get the location of the five `user`
-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.
-
-```sql
-SELECT "users"."id" FROM "users" WHERE "users"."id" >= 302 ORDER BY "users"."id" ASC LIMIT 1 OFFSET 5
-```
-
-![Reading the second end ID value](img/each_batch_users_table_iteration_4_v13_7.png)
-
-Now we can easily construct the `users` query for the second iteration.
-
-```sql
-SELECT "users".* FROM "users" WHERE "users"."id" >= 302 AND "users"."id" < 353
-```
-
-![Reading the rows for the second iteration from the users table](img/each_batch_users_table_iteration_5_v13_7.png)
-
-### Example 2: Iteration with filters
-
-Building on top of the previous example, we want to print users with zero sign-in count. We keep
-track of the number of sign-ins in the `sign_in_count` column so we write the following code:
-
-```ruby
-users = User.where(sign_in_count: 0)
-
-users.each_batch(of: 5) do |relation|
- relation.each { |user| puts user.inspect }
-end
-```
-
-`each_batch` produces the following SQL query for the start `id` value:
-
-```sql
-SELECT "users"."id" FROM "users" WHERE "users"."sign_in_count" = 0 ORDER BY "users"."id" ASC LIMIT 1
-```
-
-Selecting only the `id` column and ordering by `id` forces the database to use the
-index on the `id` (primary key index) column however, we also have an extra condition on the
-`sign_in_count` column. The column is not part of the index, so the database needs to look into
-the actual table to find the first matching row.
-
-![Reading the index with extra filter](img/each_batch_users_table_filter_v13_7.png)
-
-NOTE:
-The number of scanned rows depends on the data distribution in the table.
-
-- Best case scenario: the first user was never logged in. The database reads only one row.
-- Worst case scenario: all users were logged in at least once. The database reads all rows.
-
-In this particular example, the database had to read 10 rows (regardless of our batch size setting)
-to determine the first `id` value. In a "real-world" application it's hard to predict whether the
-filtering causes problems or not. In the case of GitLab, verifying the data on a
-production replica is a good start, but keep in mind that data distribution on GitLab.com can be
-different from self-managed instances.
-
-#### Improve filtering with `each_batch`
-
-##### Specialized conditional index
-
-```sql
-CREATE INDEX index_on_users_never_logged_in ON users (id) WHERE sign_in_count = 0
-```
-
-This is how our table and the newly created index looks like:
-
-![Reading the specialized index](img/each_batch_users_table_filtered_index_v13_7.png)
-
-This index definition covers the conditions on the `id` and `sign_in_count` columns thus makes the
-`each_batch` queries very effective (similar to the simple iteration example).
-
-It's rare when a user was never signed in so we a anticipate small index size. Including only the
-`id` in the index definition also helps to keep the index size small.
-
-##### Index on columns
-
-Later on, we might want to iterate over the table filtering for different `sign_in_count` values, in
-those cases we cannot use the previously suggested conditional index because the `WHERE` condition
-does not match with our new filter (`sign_in_count > 10`).
-
-To address this problem, we have two options:
-
-- Create another, conditional index to cover the new query.
-- Replace the index with a more generalized configuration.
-
-NOTE:
-Having multiple indexes on the same table and on the same columns could be a performance bottleneck
-when writing data.
-
-Let's consider the following index (avoid):
-
-```sql
-CREATE INDEX index_on_users_never_logged_in ON users (id, sign_in_count)
-```
-
-The index definition starts with the `id` column which makes the index very inefficient from data
-selectivity point of view.
-
-```sql
-SELECT "users"."id" FROM "users" WHERE "users"."sign_in_count" = 0 ORDER BY "users"."id" ASC LIMIT 1
-```
-
-Executing the query above results in an `INDEX ONLY SCAN`. However, the query still needs to
-iterate over an unknown number of entries in the index, and then find the first item where the
-`sign_in_count` is `0`.
-
-![Reading an ineffective index](img/each_batch_users_table_bad_index_v13_7.png)
-
-We can improve the query significantly by swapping the columns in the index definition (prefer).
-
-```sql
-CREATE INDEX index_on_users_never_logged_in ON users (sign_in_count, id)
-```
-
-![Reading a good index](img/each_batch_users_table_good_index_v13_7.png)
-
-The following index definition does not work well with `each_batch` (avoid).
-
-```sql
-CREATE INDEX index_on_users_never_logged_in ON users (sign_in_count)
-```
-
-Since `each_batch` builds range queries based on the `id` column, this index cannot be used
-efficiently. The DB reads the rows from the table or uses a bitmap search where the primary
-key index is also read.
-
-##### "Slow" iteration
-
-Slow iteration means that we use a good index configuration to iterate over the table and
-apply filtering on the yielded relation.
-
-```ruby
-User.each_batch(of: 5) do |relation|
- relation.where(sign_in_count: 0).each { |user| puts user inspect }
-end
-```
-
-The iteration uses the primary key index (on the `id` column) which makes it safe from statement
-timeouts. The filter (`sign_in_count: 0`) is applied on the `relation` where the `id` is already
-constrained (range). The number of rows is limited.
-
-Slow iteration generally takes more time to finish. The iteration count is higher and
-one iteration could yield fewer records than the batch size. Iterations may even yield
-0 records. This is not an optimal solution; however, in some cases (especially when
-dealing with large tables) this is the only viable option.
-
-### Using Subqueries
-
-Using subqueries in your `each_batch` query does not work well in most cases. Consider the following example:
-
-```ruby
-projects = Project.where(creator_id: Issue.where(confidential: true).select(:author_id))
-
-projects.each_batch do |relation|
- # do something
-end
-```
-
-The iteration uses the `id` column of the `projects` table. The batching does not affect the
-subquery. This means for each iteration, the subquery is executed by the database. This adds a
-constant "load" on the query which often ends up in statement timeouts. We have an unknown number
-of [confidential issues](../user/project/issues/confidential_issues.md), the execution time
-and the accessed database rows depend on the data distribution in the `issues` table.
-
-NOTE:
-Using subqueries works only when the subquery returns a small number of rows.
-
-#### Improving Subqueries
-
-When dealing with subqueries, a slow iteration approach could work: the filter on `creator_id`
-can be part of the generated `relation` object.
-
-```ruby
-projects = Project.all
-
-projects.each_batch do |relation|
- relation.where(creator_id: Issue.where(confidential: true).select(:author_id))
-end
-```
-
-If the query on the `issues` table itself is not performant enough, a nested loop could be
-constructed. Try to avoid it when possible.
-
-```ruby
-projects = Project.all
-
-projects.each_batch do |relation|
- issues = Issue.where(confidential: true)
-
- issues.each_batch do |issues_relation|
- relation.where(creator_id: issues_relation.select(:author_id))
- end
-end
-```
-
-If we know that the `issues` table has many more rows than `projects`, it would make sense to flip
-the queries, where the `issues` table is batched first.
-
-### Using `JOIN` and `EXISTS`
-
-When to use `JOINS`:
-
-- When there's a 1:1 or 1:N relationship between the tables where we know that the joined record
-(almost) always exists. This works well for "extension-like" tables:
- - `projects` - `project_settings`
- - `users` - `user_details`
- - `users` - `user_statuses`
-- `LEFT JOIN` works well in this case. Conditions on the joined table need to go to the yielded
-relation so the iteration is not affected by the data distribution in the joined table.
-
-Example:
-
-```ruby
-users = User.joins("LEFT JOIN personal_access_tokens on personal_access_tokens.user_id = users.id")
-
-users.each_batch do |relation|
- relation.where("personal_access_tokens.name = 'name'")
-end
-```
-
-`EXISTS` queries should be added only to the inner `relation` of the `each_batch` query:
-
-```ruby
-User.each_batch do |relation|
- relation.where("EXISTS (SELECT 1 FROM ...")
-end
-```
-
-### Complex queries on the relation object
-
-When the `relation` object has several extra conditions, the execution plans might become
-"unstable".
-
-Example:
-
-```ruby
-Issue.each_batch do |relation|
- relation
- .joins(:metrics)
- .joins(:merge_requests_closing_issues)
- .where("id IN (SELECT ...)")
- .where(confidential: true)
-end
-```
-
-Here, we expect that the `relation` query reads the `BATCH_SIZE` of user records and then
-filters down the results according to the provided queries. The planner might decide that
-using a bitmap index lookup with the index on the `confidential` column is a better way to
-execute the query. This can cause an unexpectedly high amount of rows to be read and the
-query could time out.
-
-Problem: we know for sure that the relation is returning maximum `BATCH_SIZE` of records
-however, the planner does not know this.
-
-Common table expression (CTE) trick to force the range query to execute first:
-
-```ruby
-Issue.each_batch(of: 1000) do |relation|
- cte = Gitlab::SQL::CTE.new(:batched_relation, relation.limit(1000))
-
- scope = cte
- .apply_to(Issue.all)
- .joins(:metrics)
- .joins(:merge_requests_closing_issues)
- .where("id IN (SELECT ...)")
- .where(confidential: true)
-
- puts scope.to_a
-end
-```
-
-### `EachBatch` vs `BatchCount`
-
-When adding new counters for Service Ping, the preferred way to count records is using the
-`Gitlab::Database::BatchCount` class. The iteration logic implemented in `BatchCount`
-has similar performance characteristics like `EachBatch`. Most of the tips and suggestions
-for improving `BatchCount` mentioned above applies to `BatchCount` as well.
-
-## Iterate with keyset pagination
-
-There are a few special cases where iterating with `EachBatch` does not work. `EachBatch`
-requires one distinct column (usually the primary key), which makes the iteration impossible
-for timestamp columns and tables with composite primary keys.
-
-Where `EachBatch` does not work, you can use
-[keyset pagination](database/pagination_guidelines.md#keyset-pagination) to iterate over the
-table or a range of rows. The scaling and performance characteristics are very similar to
-`EachBatch`.
-
-Examples:
-
-- Iterate over the table in a specific order (timestamp columns) in combination with a tie-breaker
-if column user to sort by does not contain unique values.
-- Iterate over the table with composite primary keys.
-
-### Iterate over the issues in a project by creation date
-
-You can use keyset pagination to iterate over any database column in a specific order (for example,
-`created_at DESC`). To ensure consistent order of the returned records with the same values for
-`created_at`, use a tie-breaker column with unique values (for example, `id`).
-
-Assume you have the following index in the `issues` table:
-
-```sql
-idx_issues_on_project_id_and_created_at_and_id" btree (project_id, created_at, id)
-```
-
-### Fetching records for further processing
-
-The following snippet iterates over issue records within the project using the specified order
-(`created_at, id`).
-
-```ruby
-scope = Issue.where(project_id: 278964).order(:created_at, :id) # id is the tie-breaker
-
-iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
-
-iterator.each_batch(of: 100) do |records|
- puts records.map(&:id)
-end
-```
-
-You can add extra filters to the query. This example only lists the issue IDs created in the last
-30 days:
-
-```ruby
-scope = Issue.where(project_id: 278964).where('created_at > ?', 30.days.ago).order(:created_at, :id) # id is the tie-breaker
-
-iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
-
-iterator.each_batch(of: 100) do |records|
- puts records.map(&:id)
-end
-```
-
-### Updating records in the batch
-
-For complex `ActiveRecord` queries, the `.update_all` method does not work well, because it
-generates an incorrect `UPDATE` statement.
-You can use raw SQL for updating records in batches:
-
-```ruby
-scope = Issue.where(project_id: 278964).order(:created_at, :id) # id is the tie-breaker
-
-iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
-
-iterator.each_batch(of: 100) do |records|
- ApplicationRecord.connection.execute("UPDATE issues SET updated_at=NOW() WHERE issues.id in (#{records.dup.reselect(:id).to_sql})")
-end
-```
-
-NOTE:
-To keep the iteration stable and predictable, avoid updating the columns in the `ORDER BY` clause.
-
-### Iterate over the `merge_request_diff_commits` table
-
-The `merge_request_diff_commits` table uses a composite primary key (`merge_request_diff_id,
-relative_order`), which makes `EachBatch` impossible to use efficiently.
-
-To paginate over the `merge_request_diff_commits` table, you can use the following snippet:
-
-```ruby
-# Custom order object configuration:
-order = Gitlab::Pagination::Keyset::Order.build([
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'merge_request_diff_id',
- order_expression: MergeRequestDiffCommit.arel_table[:merge_request_diff_id].asc,
- nullable: :not_nullable,
- distinct: false,
- ),
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'relative_order',
- order_expression: MergeRequestDiffCommit.arel_table[:relative_order].asc,
- nullable: :not_nullable,
- distinct: false,
- )
-])
-MergeRequestDiffCommit.include(FromUnion) # keyset pagination generates UNION queries
-
-scope = MergeRequestDiffCommit.order(order)
-
-iterator = Gitlab::Pagination::Keyset::Iterator.new(scope: scope)
-
-iterator.each_batch(of: 100) do |records|
- puts records.map { |record| [record.merge_request_diff_id, record.relative_order] }.inspect
-end
-```
-
-### Order object configuration
-
-Keyset pagination works well with simple `ActiveRecord` `order` scopes
-([first example](iterating_tables_in_batches.md#iterate-over-the-issues-in-a-project-by-creation-date).
-However, in special cases, you need to describe the columns in the `ORDER BY` clause (second example)
-for the underlying keyset pagination library. When the `ORDER BY` configuration cannot be
-automatically determined by the keyset pagination library, an error is raised.
-
-The code comments of the
-[`Gitlab::Pagination::Keyset::Order`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/pagination/keyset/order.rb)
-and [`Gitlab::Pagination::Keyset::ColumnOrderDefinition`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/pagination/keyset/column_order_definition.rb)
-classes give an overview of the possible options for configuring the `ORDER BY` clause. You can
-also find a few code examples in the
-[keyset pagination](database/keyset_pagination.md#complex-order-configuration) documentation.
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/jh_features_review.md b/doc/development/jh_features_review.md
index 88830a80bf1..7b81ecfe8f5 100644
--- a/doc/development/jh_features_review.md
+++ b/doc/development/jh_features_review.md
@@ -62,7 +62,8 @@ For features that build on existing CE/EE features, a module in the `JH`
namespace injected in the CE/EE class/module is needed. This aligns with
what we're doing with EE features.
-See [EE features based on CE features](ee_features.md#ee-features-based-on-ce-features) for more details.
+See [Extend CE features with EE backend code](ee_features.md#extend-ce-features-with-ee-backend-code)
+for more details.
For example, to prepend a module into the `User` class you would use
the following approach:
diff --git a/doc/development/kubernetes.md b/doc/development/kubernetes.md
index ee261769d82..1c83bef5620 100644
--- a/doc/development/kubernetes.md
+++ b/doc/development/kubernetes.md
@@ -155,7 +155,7 @@ Mitigation strategies include:
## Debugging Kubernetes integrations
Logs related to the Kubernetes integration can be found in
-[`kubernetes.log`](../administration/logs.md#kuberneteslog). On a local
+[`kubernetes.log`](../administration/logs/index.md#kuberneteslog). On a local
GDK install, these logs are present in `log/kubernetes.log`.
Some services such as
diff --git a/doc/development/lfs.md b/doc/development/lfs.md
index 9b78c8869b1..5900eb68294 100644
--- a/doc/development/lfs.md
+++ b/doc/development/lfs.md
@@ -76,14 +76,13 @@ process, which writes the contents to the standard output.
1. The archive data is sent back to the client.
In step 7, the `gitaly-lfs-smudge` filter must talk to Workhorse, not to
-Rails, or an invalid LFS blob is saved. To support this, GitLab
-13.5 [changed the default Omnibus configuration to have Gitaly talk to
-the Workhorse](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4592)
+Rails, or an invalid LFS blob is saved. To support this, GitLab 13.5
+[changed the default Omnibus configuration to have Gitaly talk to the Workhorse](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4592)
instead of Rails.
One side effect of this change: the correlation ID of the original
request is not preserved for the internal API requests made by Gitaly
(or `gitaly-lfs-smudge`), such as the one made in step 8. The
-correlation IDs for those API requests are random values until [this
-Workhorse issue](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/309) is
+correlation IDs for those API requests are random values until
+[this Workhorse issue](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/309) is
resolved.
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index 21b07ae89b5..b007df8f1da 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -1,72 +1,11 @@
---
-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
+redirect_to: 'ee_features.md'
+remove_date: '2022-10-08'
---
-# Licensed feature availability
+This document was moved to [another location](ee_features.md).
-As of GitLab 9.4, we've been supporting a simplified version of licensed
-feature availability checks via `ee/app/models/license.rb`, both for
-on-premise or GitLab.com plans and features.
-
-## Restricting features scoped by namespaces or projects
-
-GitLab.com plans are persisted on user groups and namespaces, therefore, if you're adding a
-feature such as [Related issues](../user/project/issues/related_issues.md) or
-[Service Desk](../user/project/service_desk.md),
-it should be restricted on namespace scope.
-
-1. Add the feature symbol on `STARTER_FEATURES`, `PREMIUM_FEATURES`, or `ULTIMATE_FEATURES` constants in
- `ee/app/models/gitlab_subscriptions/features.rb`.
-1. Check using:
-
-```ruby
-project.licensed_feature_available?(:feature_symbol)
-```
-
-or
-
-```ruby
-group.licensed_feature_available?(:feature_symbol)
-```
-
-For projects, `licensed_feature_available` delegates to its associated `namespace`.
-
-## Restricting global features (instance)
-
-However, for features such as [Geo](../administration/geo/index.md) and
-[Database Load Balancing](../administration/postgresql/database_load_balancing.md), which cannot be restricted
-to only a subset of projects or namespaces, the check is made directly in
-the instance license.
-
-1. Add the feature symbol to `STARTER_FEATURES`, `PREMIUM_FEATURES` or `ULTIMATE_FEATURES` constants in
- `ee/app/models/gitlab_subscriptions/features.rb`.
-1. Add the same feature symbol to `GLOBAL_FEATURES`.
-1. Check using:
-
-```ruby
-License.feature_available?(:feature_symbol)
-```
-
-## Restricting frontend features
-
-To restrict frontend features based on the license, use `push_licensed_feature`.
-The frontend can then access this via `this.glFeatures`:
-
-```ruby
-before_action do
- push_licensed_feature(:feature_symbol)
- # or by project/namespace
- push_licensed_feature(:feature_symbol, project)
-end
-```
-
-## Allow use of licensed EE features
-
-To enable plans per namespace turn on the `Allow use of licensed EE features` option from the settings page.
-This will make licensed EE features available to projects only if the project namespace's plan includes the feature
-or if the project is public. To enable it:
-
-1. If you are developing locally, follow the steps in [simulate SaaS](ee_features.md#act-as-saas) to make the option available.
-1. Select Admin > Settings > General > "Account and limit" and enable "Allow use of licensed EE features".
+<!-- This redirect file can be deleted after <2022-10-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 (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/logging.md b/doc/development/logging.md
index 749f85c9e2d..f1fa7f4c8c9 100644
--- a/doc/development/logging.md
+++ b/doc/development/logging.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Developers Guide to Logging **(FREE)**
-[GitLab Logs](../administration/logs.md) play a critical role for both
+[GitLab Logs](../administration/logs/index.md) play a critical role for both
administrators and GitLab team members to diagnose problems in the field.
## Don't use `Rails.logger`
@@ -44,8 +44,7 @@ These logs suffer from a number of problems:
Note that currently on GitLab.com, any messages in `production.log` aren't
indexed by Elasticsearch due to the sheer volume and noise. They
do end up in Google Stackdriver, but it is still harder to search for
-logs there. See the [GitLab.com logging
-documentation](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging)
+logs there. See the [GitLab.com logging documentation](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging)
for more details.
## Use structured (JSON) logging
@@ -66,7 +65,7 @@ Suppose you want to log the events that happen in a project
importer. You want to log issues created, merge requests, and so on, as the
importer progresses. Here's what to do:
-1. Look at [the list of GitLab Logs](../administration/logs.md) to see
+1. Look at [the list of GitLab Logs](../administration/logs/index.md) to see
if your log message might belong with one of the existing log files.
1. If there isn't a good place, consider creating a new filename, but
check with a maintainer if it makes sense to do so. A log file should
@@ -386,18 +385,18 @@ end
## Additional steps with new log files
1. Consider log retention settings. By default, Omnibus rotates any
- logs in `/var/log/gitlab/gitlab-rails/*.log` every hour and [keep at
- most 30 compressed files](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate).
+ logs in `/var/log/gitlab/gitlab-rails/*.log` every hour and
+ [keep at most 30 compressed files](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate).
On GitLab.com, that setting is only 6 compressed files. These settings should suffice
for most users, but you may need to tweak them in [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab).
-1. If you add a new file, submit an issue to the [production
- tracker](https://gitlab.com/gitlab-com/gl-infra/production/-/issues) or
+1. If you add a new file, submit an issue to the
+ [production tracker](https://gitlab.com/gitlab-com/gl-infra/production/-/issues) or
a merge request to the [`gitlab_fluentd`](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd)
project. See [this example](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd/-/merge_requests/51/diffs).
-1. Be sure to update the [GitLab CE/EE documentation](../administration/logs.md) and the [GitLab.com
- runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/docs/logging/README.md).
+1. Be sure to update the [GitLab CE/EE documentation](../administration/logs/index.md) and the
+ [GitLab.com runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/docs/logging/README.md).
## Control logging visibility
diff --git a/doc/development/merge_request_concepts/index.md b/doc/development/merge_request_concepts/index.md
index 8df0da5123e..331f0e01579 100644
--- a/doc/development/merge_request_concepts/index.md
+++ b/doc/development/merge_request_concepts/index.md
@@ -5,13 +5,11 @@ 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"
---
-# Merge Request Concepts
+# Merge request concepts
-**NOTE**:
+NOTE:
The documentation below is the single source of truth for the merge request terminology and functionality.
-## Overview
-
The merge request is made up of several different key components and ideas that encompass the overall merge request experience. These concepts sometimes have competing and confusing terminology or overlap with other concepts. The concepts this will cover are:
1. Merge widget
@@ -19,7 +17,12 @@ The merge request is made up of several different key components and ideas that
1. Merge checks
1. Approval rules
-### Merge widget
+When developing new merge request widgets, read the
+[merge request widget extension framework](../fe_guide/merge_request_widget_extensions.md)
+documentation. All new widgets should use this framework, and older widgets should
+be ported to use it.
+
+## Merge widget
The merge widget is the component of the merge request where the `merge` button exists:
@@ -27,27 +30,27 @@ The merge widget is the component of the merge request where the `merge` button
This area of the merge request is where all of the options and commit messages are defined prior to merging. It also contains information about what is in the merge request, what issues may be closed, and other important information to the merging process.
-### Report widgets
+## Report widgets
Reports are widgets within the merge request that report information about changes within the merge request. These widgets provide information to better help the author understand the changes and further improvements to the proposed changes.
-[Design Documentation](https://design.gitlab.com/regions/merge-request-reports)
+[Design Documentation](https://design.gitlab.com/regions/merge-request-reports/)
![merge request reports](../img/merge_request_reports_v14_7.png)
-### Merge checks
+## Merge checks
Merge checks are statuses that can either pass or fail and conditionally control the availability of the merge button being available within a merge request. The key distinguishing factor in a merge check is that users **do not** interact with the merge checks inside of the merge request, but are able to influence whether or not the check passes or fails. Results from the check are processed as true/false to determine whether or not a merge request can be merged. Examples include:
-1. merge conflicts
-1. pipeline success
-1. threads resolution
-1. [external status checks](../../user/project/merge_requests/status_checks.md)
-1. required approvals
+- Merge conflicts.
+- Pipeline success.
+- Threads resolution.
+- [External status checks](../../user/project/merge_requests/status_checks.md).
+- Required approvals.
When all of the required merge checks are satisfied a merge request becomes mergeable.
-### Approvals
+## Approvals
Approval rules specify users that are required to or can optionally approve a merge request based on some kind of organizational policy. When approvals are required, they effectively become a required merge check. The key differentiator between merge checks and approval rules is that users **do** interact with approval rules, by deciding to approve the merge request.
diff --git a/doc/development/merge_request_concepts/widget_extensions.md b/doc/development/merge_request_concepts/widget_extensions.md
new file mode 100644
index 00000000000..097e9155f2b
--- /dev/null
+++ b/doc/development/merge_request_concepts/widget_extensions.md
@@ -0,0 +1,11 @@
+---
+redirect_to: '../fe_guide/merge_request_widget_extensions.md'
+remove_date: '2022-10-27'
+---
+
+This document was moved to [another location](../fe_guide/merge_request_widget_extensions.md).
+
+<!-- This redirect file can be deleted after <2022-10-27>. -->
+<!-- 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/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 5e7fe9cc8fb..7ff25705ae6 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -193,7 +193,7 @@ costly, time-consuming query to the replicas.
## Use CTEs wisely
-Read about [complex queries on the relation object](iterating_tables_in_batches.md#complex-queries-on-the-relation-object) for considerations on how to use CTEs. We have found in some situations that CTEs can become problematic in use (similar to the n+1 problem above). In particular, hierarchical recursive CTE queries such as the CTE in [AuthorizedProjectsWorker](https://gitlab.com/gitlab-org/gitlab/-/issues/325688) are very difficult to optimize and don't scale. We should avoid them when implementing new features that require any kind of hierarchical structure.
+Read about [complex queries on the relation object](database/iterating_tables_in_batches.md#complex-queries-on-the-relation-object) for considerations on how to use CTEs. We have found in some situations that CTEs can become problematic in use (similar to the n+1 problem above). In particular, hierarchical recursive CTE queries such as the CTE in [AuthorizedProjectsWorker](https://gitlab.com/gitlab-org/gitlab/-/issues/325688) are very difficult to optimize and don't scale. We should avoid them when implementing new features that require any kind of hierarchical structure.
CTEs have been effectively used as an optimization fence in many simpler cases,
such as this [example](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43242#note_61416277).
@@ -394,8 +394,8 @@ query for every mention of `@alice`.
Caching data per transaction can be done using
[RequestStore](https://github.com/steveklabnik/request_store) (use
`Gitlab::SafeRequestStore` to avoid having to remember to check
-`RequestStore.active?`). Caching data in Redis can be done using [Rails' caching
-system](https://guides.rubyonrails.org/caching_with_rails.html).
+`RequestStore.active?`). Caching data in Redis can be done using
+[Rails' caching system](https://guides.rubyonrails.org/caching_with_rails.html).
## Pagination
@@ -414,8 +414,7 @@ The main styles of pagination are:
The ultimately scalable solution for pagination is to use Keyset-based pagination.
However, we don't have support for that at GitLab at that moment. You
-can follow the progress looking at [API: Keyset Pagination
-](https://gitlab.com/groups/gitlab-org/-/epics/2039).
+can follow the progress looking at [API: Keyset Pagination](https://gitlab.com/groups/gitlab-org/-/epics/2039).
Take into consideration the following when choosing a pagination strategy:
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index e0e21319f47..64d8b22f1b8 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -45,9 +45,12 @@ work it needs to perform and how long it takes to complete:
One exception is a migration that takes longer but is absolutely critical for the application to operate correctly.
For example, you might have indices that enforce unique tuples, or that are needed for query performance in critical parts of the application. In cases where the migration would be unacceptably slow, however, a better option might be to guard the feature with a [feature flag](feature_flags/index.md)
and perform a post-deployment migration instead. The feature can then be turned on after the migration finishes.
+
+ Migrations used to add new models are also part of these regular schema migrations. The only differences are the Rails command used to generate the migrations and the additional generated files, one for the model and one for the model's spec.
1. [**Post-deployment migrations.**](database/post_deployment_migrations.md) These are Rails migrations in `db/post_migrate` and
- run _after_ new application code has been deployed (for GitLab.com after the production deployment has finished).
- They can be used for schema changes that aren't critical for the application to operate, or data migrations that take at most a few minutes.
+ are run independently from the GitLab.com deployments. Pending post migrations are executed on a daily basis at the discretion
+ of release manager through the [post-deploy migration pipeline](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/post_deploy_migration/readme.md#how-to-determine-if-a-post-deploy-migration-has-been-executed-on-gitlabcom).
+ These migrations can be used for schema changes that aren't critical for the application to operate, or data migrations that take at most a few minutes.
Common examples for schema changes that should run post-deploy include:
- Clean-ups, like removing unused columns.
- Adding non-critical indices on high-traffic tables.
@@ -88,7 +91,7 @@ Keep in mind that all durations should be measured against GitLab.com.
|----|----|---|
| Regular migrations | `<= 3 minutes` | A valid exception are changes without which application functionality or performance would be severely degraded and which cannot be delayed. |
| Post-deployment migrations | `<= 10 minutes` | A valid exception are schema changes, since they must not happen in background migrations. |
-| Background migrations | `> 10 minutes` | Since these are suitable for larger tables, it's not possible to set a precise timing guideline, however, any single query must stay below [`1 second` execution time](query_performance.md#timing-guidelines-for-queries) with cold caches. |
+| Background migrations | `> 10 minutes` | Since these are suitable for larger tables, it's not possible to set a precise timing guideline, however, any single query must stay below [`1 second` execution time](database/query_performance.md#timing-guidelines-for-queries) with cold caches. |
## Decide which database to target
@@ -108,6 +111,20 @@ bundle exec rails g migration migration_name_here
This generates the migration file in `db/migrate`.
+### Regular schema migrations to add new models
+
+To create a new model you can use the following Rails generator:
+
+```shell
+bundle exec rails g model model_name_here
+```
+
+This will generate:
+
+- the migration file in `db/migrate`
+- the model file in `app/models`
+- the spec file in `spec/models`
+
## Schema Changes
Changes to the schema should be committed to `db/structure.sql`. This
@@ -119,7 +136,7 @@ columns manually for existing tables as this causes confusion to
other people using `db/structure.sql` generated by Rails.
NOTE:
-[Creating an index asynchronously requires two merge requests.](adding_database_indexes.md#add-a-migration-to-create-the-index-synchronously)
+[Creating an index asynchronously requires two merge requests.](database/adding_database_indexes.md#add-a-migration-to-create-the-index-synchronously)
When done, commit the schema change in the merge request
that adds the index with `add_concurrent_index`.
@@ -245,7 +262,7 @@ When using a single-transaction migration, a transaction holds a database connec
for the duration of the migration, so you must make sure the actions in the migration
do not take too much time: GitLab.com's production database has a `15s` timeout, so
in general, the cumulative execution time in a migration should aim to fit comfortably
-in that limit. Singular query timings should fit within the [standard limit](query_performance.md#timing-guidelines-for-queries)
+in that limit. Singular query timings should fit within the [standard limit](database/query_performance.md#timing-guidelines-for-queries)
In case you need to insert, update, or delete a significant amount of data, you:
@@ -268,7 +285,7 @@ which is a "versioned" class. For new migrations, the latest version should be u
can be looked up in `Gitlab::Database::Migration::MIGRATION_CLASSES`) to use the latest version
of migration helpers.
-In this example, we use version 1.0 of the migration class:
+In this example, we use version 2.0 of the migration class:
```ruby
class TestMigration < Gitlab::Database::Migration[2.0]
@@ -580,7 +597,7 @@ end
Verify the index is not being used anymore with this Thanos query:
```sql
-sum(rate(pg_stat_user_indexes_idx_tup_read{env="gprd", indexrelname="index_ci_name", type="patroni-ci"}[5m]))
+sum by (type)(rate(pg_stat_user_indexes_idx_scan{env="gprd", indexrelname="index_groups_on_parent_id_id"}[5m]))
```
Note that it is not necessary to check if the index exists prior to
@@ -611,7 +628,7 @@ might not be required, like:
Additionally, wide indexes are not required to match all filter criteria of queries, we just need
to cover enough columns so that the index lookup has a small enough selectivity. Please review our
-[Adding Database indexes](adding_database_indexes.md) guide for more details.
+[Adding Database indexes](database/adding_database_indexes.md) guide for more details.
When adding an index to a non-empty table make sure to use the method
`add_concurrent_index` instead of the regular `add_index` method.
@@ -640,7 +657,7 @@ end
You must explicitly name indexes that are created with more complex
definitions beyond table name, column names, and uniqueness constraint.
-Consult the [Adding Database Indexes](adding_database_indexes.md#requirements-for-naming-indexes)
+Consult the [Adding Database Indexes](database/adding_database_indexes.md#requirements-for-naming-indexes)
guide for more details.
If you need to add a unique index, please keep in mind there is the possibility
@@ -658,7 +675,7 @@ If a migration requires conditional logic based on the absence or
presence of an index, you must test for existence of that index using
its name. This helps avoids problems with how Rails compares index definitions,
which can lead to unexpected results. For more details, review the
-[Adding Database Indexes](adding_database_indexes.md#why-explicit-names-are-required)
+[Adding Database Indexes](database/adding_database_indexes.md#why-explicit-names-are-required)
guide.
The easiest way to test for existence of an index by name is to use the
@@ -739,6 +756,21 @@ If a backport adding a column with a default value is needed for %12.9 or earlie
it should use `add_column_with_default` helper. If a [large table](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3)
is involved, backporting to %12.9 is contraindicated.
+## Removing the column default for non-nullable columns
+
+If you have added a non-nullable column, and used the default value to populate
+existing data, you need to keep that default value around until at least after
+the application code is updated. You cannot remove the default value in the
+same migration, as the migrations run before the model code is updated and
+models will have an old schema cache, meaning they won't know about this column
+and won't be able to set it. In this case it's recommended to:
+
+1. Add the column with default value in a normal migration.
+1. Remove the default in a post-deployment migration.
+
+The post-deployment migration happens after the application restarts,
+ensuring the new column has been discovered.
+
## Changing the column default
One might think that changing a default column with `change_column_default` is an
@@ -1196,8 +1228,8 @@ If using a model in the migrations, you should first
[clear the column cache](https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-reset_column_information)
using `reset_column_information`.
-If using a model that leverages single table inheritance (STI), there are [special
-considerations](single_table_inheritance.md#in-migrations).
+If using a model that leverages single table inheritance (STI), there are
+[special considerations](database/single_table_inheritance.md#in-migrations).
This avoids problems where a column that you are using was altered and cached
in a previous migration.
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 0f910f20534..8e39186d396 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -35,12 +35,10 @@ one of the variables. Everything could touch anything.
People are saying multiple inheritance is bad. Mixing multiple modules with
multiple instance variables scattering everywhere suffer from the same issue.
The same applies to `ActiveSupport::Concern`. See:
-[Consider replacing concerns with dedicated classes & composition](
-https://gitlab.com/gitlab-org/gitlab/-/issues/16270)
+[Consider replacing concerns with dedicated classes & composition](https://gitlab.com/gitlab-org/gitlab/-/issues/16270)
There's also a similar idea:
-[Use decorators and interface segregation to solve overgrowing models problem](
-https://gitlab.com/gitlab-org/gitlab/-/issues/14235)
+[Use decorators and interface segregation to solve overgrowing models problem](https://gitlab.com/gitlab-org/gitlab/-/issues/14235)
Note that `included` doesn't solve the whole issue. They define the
dependencies, but they still allow each modules to talk implicitly via the
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index bdab92f5185..0f3531cf5dd 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -270,7 +270,7 @@ and set this column to `false`. The old servers were still updating the old colu
that updated the new column from the old one. For the new servers though, they were only updating the new column and that same trigger
was now working against us and setting it back to the wrong value.
-For more information, see [the relevant issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9176).
+For more information, see [the relevant issue](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/9176).
### Sidebar wasn't loading for some users
diff --git a/doc/development/namespaces_storage_statistics.md b/doc/development/namespaces_storage_statistics.md
index e5263288210..75e79d1f693 100644
--- a/doc/development/namespaces_storage_statistics.md
+++ b/doc/development/namespaces_storage_statistics.md
@@ -1,193 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'database/namespaces_storage_statistics.md'
+remove_date: '2022-11-05'
---
-# Database case study: Namespaces storage statistics
+This document was moved to [another location](database/namespaces_storage_statistics.md).
-## Introduction
-
-On [Storage and limits management for groups](https://gitlab.com/groups/gitlab-org/-/epics/886),
-we want to facilitate a method for easily viewing the amount of
-storage consumed by a group, and allow easy management.
-
-## Proposal
-
-1. Create a new ActiveRecord model to hold the namespaces' statistics in an aggregated form (only for root [namespaces](../user/group/index.md#namespaces)).
-1. Refresh the statistics in this model every time a project belonging to this namespace is changed.
-
-## Problem
-
-In GitLab, we update the project storage statistics through a
-[callback](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/project.rb#L97)
-every time the project is saved.
-
-The summary of those statistics per namespace is then retrieved
-by [`Namespaces#with_statistics`](https://gitlab.com/gitlab-org/gitlab/-/blob/4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e/app/models/namespace.rb#L70) scope. Analyzing this query we noticed that:
-
-- It takes up to `1.2` seconds for namespaces with over `15k` projects.
-- It can't be analyzed with [ChatOps](chatops_on_gitlabcom.md), as it times out.
-
-Additionally, the pattern that is currently used to update the project statistics
-(the callback) doesn't scale adequately. It is currently one of the largest
-[database queries transactions on production](https://gitlab.com/gitlab-org/gitlab/-/issues/29070)
-that takes the most time overall. We can't add one more query to it as
-it increases the transaction's length.
-
-Because of all of the above, we can't apply the same pattern to store
-and update the namespaces statistics, as the `namespaces` table is one
-of the largest tables on GitLab.com. Therefore we needed to find a performant and
-alternative method.
-
-## Attempts
-
-### Attempt A: PostgreSQL materialized view
-
-Model can be updated through a refresh strategy based on a project routes SQL and a [materialized view](https://www.postgresql.org/docs/11/rules-materializedviews.html):
-
-```sql
-SELECT split_part("rs".path, '/', 1) as root_path,
- COALESCE(SUM(ps.storage_size), 0) AS storage_size,
- COALESCE(SUM(ps.repository_size), 0) AS repository_size,
- COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
- COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
- COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
- COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
- COALESCE(SUM(ps.packages_size), 0) AS packages_size,
- COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
- COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
-FROM "projects"
- INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
- INNER JOIN project_statistics ps ON ps.project_id = projects.id
-GROUP BY root_path
-```
-
-We could then execute the query with:
-
-```sql
-REFRESH MATERIALIZED VIEW root_namespace_storage_statistics;
-```
-
-While this implied a single query update (and probably a fast one), it has some downsides:
-
-- Materialized views syntax varies from PostgreSQL and MySQL. While this feature was worked on, MySQL was still supported by GitLab.
-- Rails does not have native support for materialized views. We'd need to use a specialized gem to take care of the management of the database views, which implies additional work.
-
-### Attempt B: An update through a CTE
-
-Similar to Attempt A: Model update done through a refresh strategy with a [Common Table Expression](https://www.postgresql.org/docs/9.1/queries-with.html)
-
-```sql
-WITH refresh AS (
- SELECT split_part("rs".path, '/', 1) as root_path,
- COALESCE(SUM(ps.storage_size), 0) AS storage_size,
- COALESCE(SUM(ps.repository_size), 0) AS repository_size,
- COALESCE(SUM(ps.wiki_size), 0) AS wiki_size,
- COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size,
- COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size,
- COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size,
- COALESCE(SUM(ps.packages_size), 0) AS packages_size,
- COALESCE(SUM(ps.snippets_size), 0) AS snippets_size,
- COALESCE(SUM(ps.uploads_size), 0) AS uploads_size
- FROM "projects"
- INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'
- INNER JOIN project_statistics ps ON ps.project_id = projects.id
- GROUP BY root_path)
-UPDATE namespace_storage_statistics
-SET storage_size = refresh.storage_size,
- repository_size = refresh.repository_size,
- wiki_size = refresh.wiki_size,
- lfs_objects_size = refresh.lfs_objects_size,
- build_artifacts_size = refresh.build_artifacts_size,
- pipeline_artifacts_size = refresh.pipeline_artifacts_size,
- packages_size = refresh.packages_size,
- snippets_size = refresh.snippets_size,
- uploads_size = refresh.uploads_size
-FROM refresh
- INNER JOIN routes rs ON rs.path = refresh.root_path AND rs.source_type = 'Namespace'
-WHERE namespace_storage_statistics.namespace_id = rs.source_id
-```
-
-Same benefits and downsides as attempt A.
-
-### Attempt C: Get rid of the model and store the statistics on Redis
-
-We could get rid of the model that stores the statistics in aggregated form and instead use a Redis Set.
-This would be the [boring solution](https://about.gitlab.com/handbook/values/#boring-solutions) and the fastest one
-to implement, as GitLab already includes Redis as part of its [Architecture](architecture.md#redis).
-
-The downside of this approach is that Redis does not provide the same persistence/consistency guarantees as PostgreSQL,
-and this is information we can't afford to lose in a Redis failure.
-
-### Attempt D: Tag the root namespace and its child namespaces
-
-Directly relate the root namespace to its child namespaces, so
-whenever a namespace is created without a parent, this one is tagged
-with the root namespace ID:
-
-| ID | root ID | parent ID |
-|:---|:--------|:----------|
-| 1 | 1 | NULL |
-| 2 | 1 | 1 |
-| 3 | 1 | 2 |
-
-To aggregate the statistics inside a namespace we'd execute something like:
-
-```sql
-SELECT COUNT(...)
-FROM projects
-WHERE namespace_id IN (
- SELECT id
- FROM namespaces
- WHERE root_id = X
-)
-```
-
-Even though this approach would make aggregating much easier, it has some major downsides:
-
-- We'd have to migrate **all namespaces** by adding and filling a new column. Because of the size of the table, dealing with time/cost would be significant. The background migration would take approximately `153h`, see <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29772>.
-- Background migration has to be shipped one release before, delaying the functionality by another milestone.
-
-### Attempt E (final): Update the namespace storage statistics asynchronously
-
-This approach consists of continuing to use the incremental statistics updates we already have,
-but we refresh them through Sidekiq jobs and in different transactions:
-
-1. Create a second table (`namespace_aggregation_schedules`) with two columns `id` and `namespace_id`.
-1. Whenever the statistics of a project changes, insert a row into `namespace_aggregation_schedules`
- - We don't insert a new row if there's already one related to the root namespace.
- - Keeping in mind the length of the transaction that involves updating `project_statistics`(<https://gitlab.com/gitlab-org/gitlab/-/issues/29070>), the insertion should be done in a different transaction and through a Sidekiq Job.
-1. After inserting the row, we schedule another worker to be executed asynchronously at two different moments:
- - One enqueued for immediate execution and another one scheduled in `1.5h` hours.
- - We only schedule the jobs, if we can obtain a `1.5h` lease on Redis on a key based on the root namespace ID.
- - If we can't obtain the lease, it indicates there's another aggregation already in progress, or scheduled in no more than `1.5h`.
-1. This worker will:
- - Update the root namespace storage statistics by querying all the namespaces through a service.
- - Delete the related `namespace_aggregation_schedules` after the update.
-1. Another Sidekiq job is also included to traverse any remaining rows on the `namespace_aggregation_schedules` table and schedule jobs for every pending row.
- - This job is scheduled with cron to run every night (UTC).
-
-This implementation has the following benefits:
-
-- All the updates are done asynchronously, so we're not increasing the length of the transactions for `project_statistics`.
-- We're doing the update in a single SQL query.
-- It is compatible with PostgreSQL and MySQL.
-- No background migration required.
-
-The only downside of this approach is that namespaces' statistics are updated up to `1.5` hours after the change is done,
-which means there's a time window in which the statistics are inaccurate. Because we're still not
-[enforcing storage limits](https://gitlab.com/gitlab-org/gitlab/-/issues/17664), this is not a major problem.
-
-## Conclusion
-
-Updating the storage statistics asynchronously, was the less problematic and
-performant approach of aggregating the root namespaces.
-
-All the details regarding this use case can be found on:
-
-- <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62214>
-- Merge Request with the implementation: <https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/28996>
-
-Performance of the namespace storage statistics were measured in staging and production (GitLab.com). All results were posted
-on <https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64092>: No problem has been reported so far.
+<!-- This redirect file can be deleted after <2022-11-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/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md
index 65485104efe..9575acd20c7 100644
--- a/doc/development/new_fe_guide/development/accessibility.md
+++ b/doc/development/new_fe_guide/development/accessibility.md
@@ -1,52 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/accessibility.md'
+remove_date: '2022-11-15'
---
-# Accessibility
+This document was moved to [another location](../../fe_guide/accessibility.md).
-Using semantic HTML plays a key role when it comes to accessibility.
-
-## Accessible Rich Internet Applications - ARIA
-
-WAI-ARIA (the Accessible Rich Internet Applications specification) defines a way to make Web content and Web applications more accessible to people with disabilities.
-
-The W3C recommends [using semantic elements](https://www.w3.org/TR/using-aria/#notes2) as the primary method to achieve accessibility rather than adding aria attributes. Adding aria attributes should be seen as a secondary method for creating accessible elements.
-
-### Role
-
-The `role` attribute describes the role the element plays in the context of the document.
-
-Review the list of [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#landmark_roles).
-
-## Icons
-
-When using icons or images that aren't absolutely needed to understand the context, we should use `aria-hidden="true"`.
-
-On the other hand, if an icon is crucial to understand the context we should do one of the following:
-
-1. Use `aria-label` in the element with a meaningful description
-1. Use `aria-labelledby` to point to an element that contains the explanation for that icon
-
-## Form inputs
-
-In forms we should use the `for` attribute in the label statement:
-
-```html
-<div>
- <label for="name">Fill in your name:</label>
- <input type="text" id="name" name="name">
-</div>
-```
-
-## Testing
-
-1. On MacOS you can use [VoiceOver](https://www.apple.com/accessibility/vision/) by pressing `cmd+F5`.
-1. On Windows you can use [Narrator](https://www.microsoft.com/en-us/accessibility/windows) by pressing Windows logo key + Control + Enter.
-
-## Online resources
-
-- [Chrome Accessibility Developer Tools](https://github.com/GoogleChrome/accessibility-developer-tools) for testing accessibility
-- [Audit Rules Page](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules) for best practices
-- [Lighthouse Accessibility Score](https://web.dev/performance-scoring/) for accessibility audits
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/development/components.md b/doc/development/new_fe_guide/development/components.md
index ec714c9c26f..9ad742272d1 100644
--- a/doc/development/new_fe_guide/development/components.md
+++ b/doc/development/new_fe_guide/development/components.md
@@ -1,27 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Components
+This document was moved to [another location](../../fe_guide/index.md).
-## Graphs
-
-We have a lot of graphing libraries in our codebase to render graphs. In an effort to improve maintainability, new graphs should use [D3.js](https://d3js.org/). If a new graph is fairly simple, consider implementing it in SVGs or HTML5 canvas.
-
-We chose D3 as our library going forward because of the following features:
-
-- [Tree shaking webpack capabilities](https://github.com/d3/d3/blob/master/CHANGES.md#changes-in-d3-40).
-- [Compatible with vue.js as well as vanilla JavaScript](https://github.com/d3/d3/blob/master/CHANGES.md#changes-in-d3-40).
-
-D3 is very popular across many projects outside of GitLab:
-
-- [The New York Times](https://archive.nytimes.com/www.nytimes.com/interactive/2012/02/13/us/politics/2013-budget-proposal-graphic.html)
-- [plot.ly](https://plotly.com/)
-- [Ayoa](https://www.ayoa.com/previously-droptask/)
-
-Within GitLab, D3 has been used for the following notable features
-
-- [Prometheus graphs](../../../user/project/integrations/prometheus.md)
-- Contribution calendars
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/development/index.md b/doc/development/new_fe_guide/development/index.md
index 5922c3aeeed..9ad742272d1 100644
--- a/doc/development/new_fe_guide/development/index.md
+++ b/doc/development/new_fe_guide/development/index.md
@@ -1,23 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Development
+This document was moved to [another location](../../fe_guide/index.md).
-## [Components](components.md)
-
-Documentation on existing components and how to best create a new component.
-
-## [Accessibility](accessibility.md)
-
-Learn how to implement an accessible frontend.
-
-## [Performance](performance.md)
-
-Learn how to keep our frontend performant.
-
-## [Testing](../../testing_guide/frontend_testing.md)
-
-Learn how to keep our frontend tested.
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index ee853942cb9..c72f3ded896 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -1,22 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/performance.md'
+remove_date: '2022-11-15'
---
-# Performance
+This document was moved to [another location](../../fe_guide/performance.md).
-## Monitoring
-
-We have a performance dashboard available in one of our [Grafana instances](https://dashboards.gitlab.net/d/000000043/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://www.sitespeed.io/) every 4 hours. These changes are displayed after a set number of pages are aggregated.
-
-These pages can be found inside text files in the [`sitespeed-measurement-setup` repository](https://gitlab.com/gitlab-org/frontend/sitespeed-measurement-setup) called [`gitlab`](https://gitlab.com/gitlab-org/frontend/sitespeed-measurement-setup/-/tree/master/gitlab)
-Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing URLs of pages to the text files. The changes are pushed live on the next scheduled run after the changes are merged into `main`.
-
-There are 3 recommended high impact metrics (core web vitals) to review on each page:
-
-- [Largest Contentful Paint](https://web.dev/lcp/)
-- [First Input Delay](https://web.dev/fid/)
-- [Cumulative Layout Shift](https://web.dev/cls/)
-
-For these metrics, lower numbers are better as it means that the website is more performant.
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index 4d4098844b2..83c1db696b4 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -1,22 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Frontend Development Guidelines
+This document was moved to [another location](../fe_guide/index.md).
-This guide contains all the information to successfully contribute to the GitLab frontend.
-This is a living document, and we welcome contributions, feedback, and suggestions.
-
-## [Development](development/index.md)
-
-Guidance on topics related to development.
-
-## [Modules](modules/index.md)
-
-Learn about all the internal JavaScript modules that make up our frontend.
-
-## [Tips](tips.md)
-
-Tips from our frontend team to develop more efficiently and effectively.
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md
index 6e1062aa72e..9ad742272d1 100644
--- a/doc/development/new_fe_guide/modules/dirty_submit.md
+++ b/doc/development/new_fe_guide/modules/dirty_submit.md
@@ -1,28 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Dirty Submit
+This document was moved to [another location](../../fe_guide/index.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21115) in GitLab 11.3.
-
-## Summary
-
-Prevent submitting forms with no changes.
-
-Currently handles `input`, `textarea` and `select` elements.
-
-Also, see [the code](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/dirty_submit/)
-within the GitLab project.
-
-## Usage
-
-```javascript
-import dirtySubmitFactory from './dirty_submit/dirty_submit_form';
-
-new DirtySubmitForm(document.querySelector('form'));
-// or
-new DirtySubmitForm(document.querySelectorAll('form'));
-```
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/modules/index.md b/doc/development/new_fe_guide/modules/index.md
index a9bdcda4a2d..9ad742272d1 100644
--- a/doc/development/new_fe_guide/modules/index.md
+++ b/doc/development/new_fe_guide/modules/index.md
@@ -1,15 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Modules
+This document was moved to [another location](../../fe_guide/index.md).
-- [DirtySubmit](dirty_submit.md)
-
- Disable form submits until there are unsaved changes.
-
-- [Merge Request widget extensions](widget_extensions.md)
-
- Easily add extensions into the merge request widget
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md
index 4bae0ac70c4..3741ee8c38a 100644
--- a/doc/development/new_fe_guide/modules/widget_extensions.md
+++ b/doc/development/new_fe_guide/modules/widget_extensions.md
@@ -1,355 +1,11 @@
---
-stage: Create
-group: Code Review
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../../fe_guide/merge_request_widget_extensions.md'
+remove_date: '2022-11-15'
---
-# Merge request widget extensions **(FREE)**
+This document was moved to [another location](../../fe_guide/merge_request_widget_extensions.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.
-
-## Summary
-
-Extensions in the merge request widget enable you to add new features
-into the merge request widget that match the design framework.
-With extensions we get a lot of benefits out of the box without much effort required, like:
-
-- A consistent look and feel.
-- Tracking when the extension is opened.
-- Virtual scrolling for performance.
-
-## Usage
-
-To use extensions you must first create a new extension object to fetch the
-data to render in the extension. For a working example, refer to the example file in
-`app/assets/javascripts/vue_merge_request_widget/extensions/issues.js`.
-
-The basic object structure:
-
-```javascript
-export default {
- name: '', // Required: This helps identify the widget
- props: [], // Required: Props passed from the widget state
- i18n: { // Required: Object to hold i18n text
- label: '', // Required: Used for tooltips and aria-labels
- loading: '', // Required: Loading text for when data is loading
- },
- expandEvent: '', // Optional: RedisHLL event name to track expanding content
- enablePolling: false, // Optional: Tells extension to poll for data
- modalComponent: null, // Optional: The component to use for the modal
- computed: {
- summary(data) {}, // Required: Level 1 summary text
- statusIcon(data) {}, // Required: Level 1 status icon
- tertiaryButtons() {}, // Optional: Level 1 action buttons
- shouldCollapse() {}, // Optional: Add logic to determine if the widget can expand or not
- },
- methods: {
- fetchCollapsedData(props) {}, // Required: Fetches data required for collapsed state
- fetchFullData(props) {}, // Required: Fetches data for the full expanded content
- fetchMultiData() {}, // Optional: Works in conjunction with `enablePolling` and allows polling multiple endpoints
- },
-};
-```
-
-By following the same data structure, each extension can follow the same registering structure,
-but each extension can manage its data sources.
-
-After creating this structure, you must register it. You can register the extension at any
-point _after_ the widget has been created. To register a extension:
-
-```javascript
-// Import the register method
-import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
-
-// Import the new extension
-import issueExtension from '~/vue_merge_request_widget/extensions/issues';
-
-// Register the imported extension
-registerExtension(issueExtension);
-```
-
-## Data fetching
-
-Each extension must fetch data. Fetching is handled when registering the extension,
-not by the core component itself. This approach allows for various different
-data fetching methods to be used, such as GraphQL or REST API calls.
-
-### API calls
-
-For performance reasons, it is best if the collapsed state fetches only the data required to
-render the collapsed state. This fetching happens within the `fetchCollapsedData` method.
-This method is called with the props as an argument, so you can easily access
-any paths set in the state.
-
-To allow the extension to set the data, this method **must** return the data. No
-special formatting is required. When the extension receives this data,
-it is set to `collapsedData`. You can access `collapsedData` in any computed property or
-method.
-
-When the user clicks **Expand**, the `fetchFullData` method is called. This method
-also gets called with the props as an argument. This method **must** also return
-the full data. However, this data needs to be correctly formatted to match the format
-mentioned in the data structure section.
-
-#### Technical debt
-
-For some of the current extensions, there is no split in data fetching. All the data
-is fetched through the `fetchCollapsedData` method. While less performant,
-it allows for faster iteration.
-
-To handle this the `fetchFullData` returns the data set through
-the `fetchCollapsedData` method call. In these cases, the `fetchFullData` must
-return a promise:
-
-```javascript
-fetchCollapsedData() {
- return ['Some data'];
-},
-fetchFullData() {
- return Promise.resolve(this.collapsedData)
-},
-```
-
-### Data structure
-
-The data returned from `fetchFullData` must match the format below. This format
-allows the core component to render the data in a way that matches
-the design framework. Any text properties can use the styling placeholders
-mentioned below:
-
-```javascript
-{
- id: data.id, // Required: ID used as a key for each row
- header: 'Header' || ['Header', 'sub-header'], // Required: String or array can be used for the header text
- text: '', // Required: Main text for the row
- subtext: '', // Optional: Smaller sub-text to be displayed below the main text
- icon: { // Optional: Icon object
- name: EXTENSION_ICONS.success, // Required: The icon name for the row
- },
- badge: { // Optional: Badge displayed after text
- text: '', // Required: Text to be displayed inside badge
- variant: '', // Optional: GitLab UI badge variant, defaults to info
- },
- link: { // Optional: Link to a URL displayed after text
- text: '', // Required: Text of the link
- href: '', // Optional: URL for the link
- },
- modal: { // Optional: Link to open a modal displayed after text
- text: '', // Required: Text of the link
- onClick: () => {} // Optional: Function to run when link is clicked, i.e. to set this.modalData
- }
- actions: [], // Optional: Action button for row
- children: [], // Optional: Child content to render, structure matches the same structure
-}
-```
-
-### Polling
-
-To enable polling for an extension, an options flag must be present in the extension:
-
-```javascript
-export default {
- //...
- enablePolling: true
-};
-```
-
-This flag tells the base component we should poll the `fetchCollapsedData()`
-defined in the extension. Polling stops if the response has data, or if an error is present.
-
-When writing the logic for `fetchCollapsedData()`, a complete Axios response must be returned
-from the method. The polling utility needs data like polling headers to work correctly:
-
-```javascript
-export default {
- //...
- enablePolling: true
- methods: {
- fetchCollapsedData() {
- return axios.get(this.reportPath)
- },
- },
-};
-```
-
-Most of the time the data returned from the extension's endpoint is not in the format
-the UI needs. We must format the data before setting the collapsed data in the base component.
-
-If the computed property `summary` can rely on `collapsedData`, you can format the data
-when `fetchFullData` is invoked:
-
-```javascript
-export default {
- //...
- enablePolling: true
- methods: {
- fetchCollapsedData() {
- return axios.get(this.reportPath)
- },
- fetchFullData() {
- return Promise.resolve(this.prepareReports());
- },
- // custom method
- prepareReports() {
- // unpack values from collapsedData
- const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
-
- // perform data formatting
-
- return [...newErrors, ...existingErrors, ...resolvedErrors]
- }
- },
-};
-```
-
-If the extension relies on `collapsedData` being formatted before invoking `fetchFullData()`,
-then `fetchCollapsedData()` must return the Axios response as well as the formatted data:
-
-```javascript
-export default {
- //...
- enablePolling: true
- methods: {
- fetchCollapsedData() {
- return axios.get(this.reportPath).then(res => {
- const formattedData = this.prepareReports(res.data)
-
- return {
- ...res,
- data: formattedData,
- }
- })
- },
- // Custom method
- prepareReports() {
- // Unpack values from collapsedData
- const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
-
- // Perform data formatting
-
- return [...newErrors, ...existingErrors, ...resolvedErrors]
- }
- },
-};
-```
-
-If the extension needs to poll multiple endpoints at the same time, then `fetchMultiData`
-can be used to return an array of functions. A new `poll` object is created for each
-endpoint and they are polled separately. After all endpoints are resolved, polling is
-stopped and `setCollapsedData` is called with an array of `response.data`.
-
-```javascript
-export default {
- //...
- enablePolling: true
- methods: {
- fetchMultiData() {
- return [
- () => axios.get(this.reportPath1),
- () => axios.get(this.reportPath2),
- () => axios.get(this.reportPath3)
- },
- },
-};
-```
-
-**Important** The function needs to return a `Promise` that resolves the `response` object.
-The implementation relies on the `POLL-INTERVAL` header to keep polling, therefore it is
-important not to alter the status code and headers.
-
-### Errors
-
-If `fetchCollapsedData()` or `fetchFullData()` methods throw an error:
-
-- The loading state of the extension is updated to `LOADING_STATES.collapsedError`
- and `LOADING_STATES.expandedError` respectively.
-- The extensions header displays an error icon and updates the text to be either:
- - The text defined in `$options.i18n.error`.
- - "Failed to load" if `$options.i18n.error` is not defined.
-- The error is sent to Sentry to log that it occurred.
-
-To customise the error text, add it to the `i18n` object in your extension:
-
-```javascript
-export default {
- //...
- i18n: {
- //...
- error: __('Your error text'),
- },
-};
-```
-
-## Icons
-
-Level 1 and all subsequent levels can have their own status icons. To keep with
-the design framework, import the `EXTENSION_ICONS` constant
-from the `constants.js` file:
-
-```javascript
-import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants.js';
-```
-
-This constant has the below icons available for use. Per the design framework,
-only some of these icons should be used on level 1:
-
-- `failed`
-- `warning`
-- `success`
-- `neutral`
-- `error`
-- `notice`
-- `severityCritical`
-- `severityHigh`
-- `severityMedium`
-- `severityLow`
-- `severityInfo`
-- `severityUnknown`
-
-## Text styling
-
-Any area that has text can be styled with the placeholders below. This
-technique follows the same technique as `sprintf`. However, instead of specifying
-these through `sprintf`, the extension does this automatically.
-
-Every placeholder contains starting and ending tags. For example, `success` uses
-`Hello %{success_start}world%{success_end}`. The extension then
-adds the start and end tags with the correct styling classes.
-
-| Placeholder | Style |
-|---|---|
-| success | `gl-font-weight-bold gl-text-green-500` |
-| danger | `gl-font-weight-bold gl-text-red-500` |
-| critical | `gl-font-weight-bold gl-text-red-800` |
-| same | `gl-font-weight-bold gl-text-gray-700` |
-| strong | `gl-font-weight-bold` |
-| small | `gl-font-sm` |
-
-## Action buttons
-
-You can add action buttons to all level 1 and 2 in each extension. These buttons
-are meant as a way to provide links or actions for each row:
-
-- Action buttons for level 1 can be set through the `tertiaryButtons` computed property.
- This property should return an array of objects for each action button.
-- Action buttons for level 2 can be set by adding the `actions` key to the level 2 rows object.
- The value for this key must also be an array of objects for each action button.
-
-Links must follow this structure:
-
-```javascript
-{
- text: 'Click me',
- href: this.someLinkHref,
- target: '_blank', // Optional
-}
-```
-
-For internal action buttons, follow this structure:
-
-```javascript
-{
- text: 'Click me',
- onClick() {}
-}
-```
+<!-- This redirect file can be deleted after <2022-11-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/development/new_fe_guide/tips.md b/doc/development/new_fe_guide/tips.md
index 5d4c0fc019f..83c1db696b4 100644
--- a/doc/development/new_fe_guide/tips.md
+++ b/doc/development/new_fe_guide/tips.md
@@ -1,35 +1,11 @@
---
-stage: none
-group: Development
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../fe_guide/index.md'
+remove_date: '2022-11-15'
---
-# Tips
+This document was moved to [another location](../fe_guide/index.md).
-## Clearing production compiled assets
-
-To clear production compiled assets created with `yarn webpack-prod` you can run:
-
-```shell
-yarn clean
-```
-
-## Creating feature flags in development
-
-The process for creating a feature flag is the same as [enabling a feature flag in development](../feature_flags/index.md#enabling-a-feature-flag-locally-in-development).
-
-Your feature flag can now be:
-
-- [Made available to the frontend](../feature_flags/index.md#frontend) via the `gon`
-- Queried in [tests](../feature_flags/index.md#feature-flags-in-tests)
-- Queried in HAML templates and Ruby files via the `Feature.enabled?(:my_shiny_new_feature_flag)` method
-
-### More on feature flags
-
-- [Deleting a feature flag](../../api/features.md#delete-a-feature)
-- [Manage feature flags](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/)
-- [Feature flags API](../../api/features.md)
-
-## Running tests locally
-
-This can be done as outlined by the [frontend testing guide](../testing_guide/frontend_testing.md#running-frontend-tests).
+<!-- This redirect file can be deleted after <2022-11-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/development/ordering_table_columns.md b/doc/development/ordering_table_columns.md
index 7cd3d4fb208..b665cb0d4c7 100644
--- a/doc/development/ordering_table_columns.md
+++ b/doc/development/ordering_table_columns.md
@@ -1,152 +1,11 @@
---
-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
+redirect_to: 'database/ordering_table_columns.md'
+remove_date: '2022-11-04'
---
-# Ordering Table Columns in PostgreSQL
+This document was moved to [another location](database/ordering_table_columns.md).
-For GitLab we require that columns of new tables are ordered to use the
-least amount of space. An easy way of doing this is to order them based on the
-type size in descending order with variable sizes (`text`, `varchar`, arrays,
-`json`, `jsonb`, and so on) at the end.
-
-Similar to C structures the space of a table is influenced by the order of
-columns. This is because the size of columns is aligned depending on the type of
-the following column. Let's consider an example:
-
-- `id` (integer, 4 bytes)
-- `name` (text, variable)
-- `user_id` (integer, 4 bytes)
-
-The first column is a 4-byte integer. The next is text of variable length. The
-`text` data type requires 1-word alignment, and on 64-bit platform, 1 word is 8
-bytes. To meet the alignment requirements, four zeros are to be added right
-after the first column, so `id` occupies 4 bytes, then 4 bytes of alignment
-padding, and only next `name` is being stored. Therefore, in this case, 8 bytes
-are spent for storing a 4-byte integer.
-
-The space between rows is also subject to alignment padding. The `user_id`
-column takes only 4 bytes, and on 64-bit platform, 4 zeroes are added for
-alignment padding, to allow storing the next row beginning with the "clear" word.
-
-As a result, the actual size of each column would be (omitting variable length
-data and 24-byte tuple header): 8 bytes, variable, 8 bytes. This means that
-each row requires at least 16 bytes for the two 4-byte integers. If a table
-has a few rows this is not an issue. However, once you start storing millions of
-rows you can save space by using a different order. For the above example, the
-ideal column order would be the following:
-
-- `id` (integer, 4 bytes)
-- `user_id` (integer, 4 bytes)
-- `name` (text, variable)
-
-or
-
-- `name` (text, variable)
-- `id` (integer, 4 bytes)
-- `user_id` (integer, 4 bytes)
-
-In these examples, the `id` and `user_id` columns are packed together, which
-means we only need 8 bytes to store _both_ of them. This in turn means each row
-requires 8 bytes less space.
-
-Since Ruby on Rails 5.1, the default data type for IDs is `bigint`, which uses 8 bytes.
-We are using `integer` in the examples to showcase a more realistic reordering scenario.
-
-## Type Sizes
-
-While the [PostgreSQL documentation](https://www.postgresql.org/docs/current/datatype.html) contains plenty
-of information we list the sizes of common types here so it's easier to
-look them up. Here "word" refers to the word size, which is 4 bytes for a 32
-bits platform and 8 bytes for a 64 bits platform.
-
-| Type | Size | Alignment needed |
-|:-----------------|:-------------------------------------|:-----------|
-| `smallint` | 2 bytes | 1 word |
-| `integer` | 4 bytes | 1 word |
-| `bigint` | 8 bytes | 8 bytes |
-| `real` | 4 bytes | 1 word |
-| `double precision` | 8 bytes | 8 bytes |
-| `boolean` | 1 byte | not needed |
-| `text` / `string` | variable, 1 byte plus the data | 1 word |
-| `bytea` | variable, 1 or 4 bytes plus the data | 1 word |
-| `timestamp` | 8 bytes | 8 bytes |
-| `timestamptz` | 8 bytes | 8 bytes |
-| `date` | 4 bytes | 1 word |
-
-A "variable" size means the actual size depends on the value being stored. If
-PostgreSQL determines this can be embedded directly into a row it may do so, but
-for very large values it stores the data externally and store a pointer (of
-1 word in size) in the column. Because of this variable sized columns should
-always be at the end of a table.
-
-## Real Example
-
-Let's use the `events` table as an example, which currently has the following
-layout:
-
-| Column | Type | Size |
-|:--------------|:----------------------------|:---------|
-| `id` | integer | 4 bytes |
-| `target_type` | character varying | variable |
-| `target_id` | integer | 4 bytes |
-| `title` | character varying | variable |
-| `data` | text | variable |
-| `project_id` | integer | 4 bytes |
-| `created_at` | timestamp without time zone | 8 bytes |
-| `updated_at` | timestamp without time zone | 8 bytes |
-| `action` | integer | 4 bytes |
-| `author_id` | integer | 4 bytes |
-
-After adding padding to align the columns this would translate to columns being
-divided into fixed size chunks as follows:
-
-| Chunk Size | Columns |
-|:-----------|:----------------------|
-| 8 bytes | `id` |
-| variable | `target_type` |
-| 8 bytes | `target_id` |
-| variable | `title` |
-| variable | `data` |
-| 8 bytes | `project_id` |
-| 8 bytes | `created_at` |
-| 8 bytes | `updated_at` |
-| 8 bytes | `action`, `author_id` |
-
-This means that excluding the variable sized data and tuple header, we need at
-least 8 * 6 = 48 bytes per row.
-
-We can optimise this by using the following column order instead:
-
-| Column | Type | Size |
-|:--------------|:----------------------------|:---------|
-| `created_at` | timestamp without time zone | 8 bytes |
-| `updated_at` | timestamp without time zone | 8 bytes |
-| `id` | integer | 4 bytes |
-| `target_id` | integer | 4 bytes |
-| `project_id` | integer | 4 bytes |
-| `action` | integer | 4 bytes |
-| `author_id` | integer | 4 bytes |
-| `target_type` | character varying | variable |
-| `title` | character varying | variable |
-| `data` | text | variable |
-
-This would produce the following chunks:
-
-| Chunk Size | Columns |
-|:-----------|:-----------------------|
-| 8 bytes | `created_at` |
-| 8 bytes | `updated_at` |
-| 8 bytes | `id`, `target_id` |
-| 8 bytes | `project_id`, `action` |
-| 8 bytes | `author_id` |
-| variable | `target_type` |
-| variable | `title` |
-| variable | `data` |
-
-Here we only need 40 bytes per row excluding the variable sized data and 24-byte
-tuple header. 8 bytes being saved may not sound like much, but for tables as
-large as the `events` table it does begin to matter. For example, when storing
-80 000 000 rows this translates to a space saving of at least 610 MB, all by
-just changing the order of a few columns.
+<!-- This redirect file can be deleted after <2022-11-04>. -->
+<!-- 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/pages/index.md b/doc/development/pages/index.md
index 02019db48ba..af9d4d33683 100644
--- a/doc/development/pages/index.md
+++ b/doc/development/pages/index.md
@@ -10,8 +10,8 @@ description: "GitLab's development guidelines for GitLab Pages"
## Configuring GitLab Pages hostname
-GitLab Pages needs a hostname or domain, as each different GitLab Pages site is accessed via a
-subdomain. GitLab Pages hostname can be set in different manners:
+GitLab Pages need a hostname or domain, as each different GitLab Pages site is accessed via a
+subdomain. You can set the GitLab Pages hostname:
- [Without wildcard, editing your hosts file](#without-wildcard-editing-your-hosts-file).
- [With DNS wildcard alternatives](#with-dns-wildcard-alternatives).
@@ -96,7 +96,7 @@ it with commands like:
### Running GitLab Pages manually
-You can also build and start the app independent of GDK processes management.
+You can also build and start the app independently of GDK processes management.
For any changes in the code, you must run `make` to build the app. It's best to just always run
it before you start the app. It's quick to build so don't worry!
@@ -114,9 +114,9 @@ FIPS_MODE=1 make && ./gitlab-pages -config=gitlab-pages.conf
### Creating GitLab Pages site
To build a GitLab Pages site locally you must
-[configure `gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/runner.md)
+[configure `gitlab-runner`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/runner.md).
-Check the [user manual](../../user/project/pages/index.md).
+For more information, refer to the [user manual](../../user/project/pages/index.md).
### Enabling access control
@@ -125,8 +125,9 @@ who have access to your GitLab project.
GitLab Pages access control is disabled by default. To enable it:
-1. Enable the GitLab Pages access control in GitLab itself, which can be done by either:
- - If you're not using GDK, editing `gitlab.yml`:
+1. Enable the GitLab Pages access control in GitLab itself. You can do this in two ways:
+
+ - If you're not using GDK, edit `gitlab.yml`:
```yaml
# gitlab/config/gitlab.yml
@@ -134,7 +135,7 @@ GitLab Pages access control is disabled by default. To enable it:
access_control: true
```
- - Editing `gdk.yml` if you're using GDK:
+ - If you're using GDK, edit `gdk.yml`:
```yaml
# $GDK_ROOT/gdk.yml
@@ -149,8 +150,9 @@ GitLab Pages access control is disabled by default. To enable it:
1. Create an [Instance-wide OAuth application](../../integration/oauth_provider.md#instance-wide-applications)
with the `api` scope.
1. Set the value of your `redirect-uri` to the `pages-domain` authorization endpoint
- - `http://pages.gdk.test:3010/auth`, for example
- - The `redirect-uri` must not contain any GitLab Pages site domain.
+(for example, `http://pages.gdk.test:3010/auth`).
+The `redirect-uri` must not contain any GitLab Pages site domain.
+
1. Add the auth client configuration:
- With GDK, in `gdk.yml`:
@@ -236,3 +238,29 @@ make acceptance
# so we want to have the latest changes in the build that is tested
make && go test ./ -run TestRedirect
```
+
+## Contributing
+
+### Feature flags
+
+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).
+
+Consider adding a [feature flag](../feature_flags/index.md) for any non-trivial changes.
+Feature flags can make the release and rollback of these changes easier, avoiding
+incidents and downtime. To add a new feature flag to GitLab Pages:
+
+1. Create the feature flag in
+ [`internal/feature/feature.go`](https://gitlab.com/gitlab-org/gitlab-pages/-/blob/master/internal/feature/feature.go),
+ which must be **off** by default.
+1. Create an issue to track the feature flag using the `Feature Flag` template.
+1. Add the `~"feature flag"` label to any merge requests that handle feature flags.
+
+For GitLab Pages, the feature flags are controlled by environment variables at a global level.
+A deployment at the service level is required to change the state of a feature flag.
+Example of a merge request enabling a GitLab Pages feature flag:
+[Enforce GitLab Pages rate limits](https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1500)
+
+## Related topics
+
+- [Feature flags in the development of GitLab](../feature_flags/index.md)
diff --git a/doc/development/performance.md b/doc/development/performance.md
index d7cbef0a211..479782e0ccf 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -18,14 +18,13 @@ consistent performance of GitLab. Refer to the [Index](#performance-documentatio
- Backend:
- [Tooling](#tooling)
- Database:
- - [Query performance guidelines](../development/query_performance.md)
+ - [Query performance guidelines](database/query_performance.md)
- [Pagination performance guidelines](../development/database/pagination_performance_guidelines.md)
- [Keyset pagination performance](../development/database/keyset_pagination.md#performance)
- [Troubleshooting import/export performance issues](../development/import_export.md#troubleshooting-performance-issues)
- [Pipelines performance in the `gitlab` project](../development/pipelines.md#performance)
- Frontend:
- - [Performance guidelines](../development/fe_guide/performance.md)
- - [Performance dashboards and monitoring guidelines](../development/new_fe_guide/development/performance.md)
+ - [Performance guidelines and monitoring](../development/fe_guide/performance.md)
- [Browser performance testing guidelines](../ci/testing/browser_performance_testing.md)
- [`gdk measure` and `gdk measure-workflow`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/gdk_commands.md#measure-performance)
- QA:
@@ -927,12 +926,11 @@ SOME_CONSTANT = 'bar'
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
-do this by hand with SQL commands or using [Mass Inserting Rails
-Models](mass_insert.md) functionality.
+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:
-- [Insert records in batches](insert_into_tables_in_batches.md)
+- [Insert records in batches](database/insert_into_tables_in_batches.md)
- [BulkInsert gem](https://github.com/jamis/bulk_insert)
- [ActiveRecord::PgGenerateSeries gem](https://github.com/ryu39/active_record-pg_generate_series)
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index ed95456c4f9..8e517b8577c 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -87,7 +87,7 @@ module):
- Owner (`50`)
If a user is the member of both a project and the project parent groups, the
-higher permission is taken into account for the project.
+highest permission is the applied access level for the project.
If a user is the member of a project, but not the parent groups, they
can still view the groups and their entities (like epics).
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 2bf1e5a315a..d57e5bbeb26 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -221,8 +221,9 @@ that includes `rspec-profile` in their name.
### Logging
-- Rails logging to `log/test.log` is disabled by default in CI [for
- performance reasons](https://jtway.co/speed-up-your-rails-test-suite-by-6-in-1-line-13fedb869ec4). To override this setting, provide the
+- Rails logging to `log/test.log` is disabled by default in CI
+ [for performance reasons](https://jtway.co/speed-up-your-rails-test-suite-by-6-in-1-line-13fedb869ec4).
+ To override this setting, provide the
`RAILS_ENABLE_TEST_LOG` environment variable.
## Review app jobs
@@ -247,6 +248,9 @@ The intent is to ensure that a change doesn't introduce a failure after `gitlab-
## As-if-JH jobs
+NOTE:
+This is disabled for now.
+
The `* as-if-jh` jobs run the GitLab test suite "as if JiHu", meaning as if the jobs would run in the context
of [GitLab JH](jh_features_review.md). These jobs are only created in the following cases:
@@ -261,12 +265,18 @@ The intent is to ensure that a change doesn't introduce a failure after `gitlab-
### When to consider applying `pipeline:run-as-if-jh` label
+NOTE:
+This is disabled for now.
+
If a Ruby file is renamed and there's a corresponding [`prepend_mod` line](jh_features_review.md#jh-features-based-on-ce-or-ee-features),
it's likely that GitLab JH is relying on it and requires a corresponding
change to rename the module or class it's prepending.
### Corresponding JH branch
+NOTE:
+This is disabled for now.
+
You can create a corresponding JH branch on [GitLab JH](https://jihulab.com/gitlab-cn/gitlab) by
appending `-jh` to the branch name. If a corresponding JH branch is found,
`* as-if-jh` jobs grab the `jh` folder from the respective branch,
diff --git a/doc/development/policies.md b/doc/development/policies.md
index c9e4fdb4350..f0c9d0ec5f9 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -74,8 +74,7 @@ Do not use boolean operators such as `&&` and `||` within the rule DSL,
as conditions within rule blocks are objects, not booleans. The same
applies for ternary operators (`condition ? ... : ...`), and `if`
blocks. These operators cannot be overridden, and are hence banned via a
-[custom
-cop](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49771).
+[custom cop](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49771).
## Scores, Order, Performance
diff --git a/doc/development/polymorphic_associations.md b/doc/development/polymorphic_associations.md
index bbeaab40a90..6b9158b8408 100644
--- a/doc/development/polymorphic_associations.md
+++ b/doc/development/polymorphic_associations.md
@@ -1,152 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'database/polymorphic_associations.md'
+remove_date: '2022-11-04'
---
-# Polymorphic Associations
+This document was moved to [another location](database/polymorphic_associations.md).
-**Summary:** always use separate tables instead of polymorphic associations.
-
-Rails makes it possible to define so called "polymorphic associations". This
-usually works by adding two columns to a table: a target type column, and a
-target ID. For example, at the time of writing we have such a setup for
-`members` with the following columns:
-
-- `source_type`: a string defining the model to use, can be either `Project` or
- `Namespace`.
-- `source_id`: the ID of the row to retrieve based on `source_type`. For
- example, when `source_type` is `Project` then `source_id` contains a
- project ID.
-
-While such a setup may appear to be useful, it comes with many drawbacks; enough
-that you should avoid this at all costs.
-
-## Space Wasted
-
-Because this setup relies on string values to determine the model to use, it
-wastes a lot of space. For example, for `Project` and `Namespace` the
-maximum size is 9 bytes, plus 1 extra byte for every string when using
-PostgreSQL. While this may only be 10 bytes per row, given enough tables and
-rows using such a setup we can end up wasting quite a bit of disk space and
-memory (for any indexes).
-
-## Indexes
-
-Because our associations are broken up into two columns this may result in
-requiring composite indexes for queries to be performed efficiently. While
-composite indexes are not wrong at all, they can be tricky to set up as the
-ordering of columns in these indexes is important to ensure optimal performance.
-
-## Consistency
-
-One really big problem with polymorphic associations is being unable to enforce
-data consistency on the database level using foreign keys. For consistency to be
-enforced on the database level one would have to write their own foreign key
-logic to support polymorphic associations.
-
-Enforcing consistency on the database level is absolutely crucial for
-maintaining a healthy environment, and thus is another reason to avoid
-polymorphic associations.
-
-## Query Overhead
-
-When using polymorphic associations you always need to filter using both
-columns. For example, you may end up writing a query like this:
-
-```sql
-SELECT *
-FROM members
-WHERE source_type = 'Project'
-AND source_id = 13083;
-```
-
-Here PostgreSQL can perform the query quite efficiently if both columns are
-indexed. As the query gets more complex, it may not be able to use these
-indexes effectively.
-
-## Mixed Responsibilities
-
-Similar to functions and classes, a table should have a single responsibility:
-storing data with a certain set of pre-defined columns. When using polymorphic
-associations, you are storing different types of data (possibly with
-different columns set) in the same table.
-
-## The Solution
-
-Fortunately, there is a solution to these problems: use a
-separate table for every type you would otherwise store in the same table. Using
-a separate table allows you to use everything a database may provide to ensure
-consistency and query data efficiently, without any additional application logic
-being necessary.
-
-Let's say you have a `members` table storing both approved and pending members,
-for both projects and groups, and the pending state is determined by the column
-`requested_at` being set or not. Schema wise such a setup can lead to various
-columns only being set for certain rows, wasting space. It's also possible that
-certain indexes are only set for certain rows, again wasting space. Finally,
-querying such a table requires less than ideal queries. For example:
-
-```sql
-SELECT *
-FROM members
-WHERE requested_at IS NULL
-AND source_type = 'GroupMember'
-AND source_id = 4
-```
-
-Instead such a table should be broken up into separate tables. For example, you
-may end up with 4 tables in this case:
-
-- project_members
-- group_members
-- pending_project_members
-- pending_group_members
-
-This makes querying data trivial. For example, to get the members of a group
-you'd run:
-
-```sql
-SELECT *
-FROM group_members
-WHERE group_id = 4
-```
-
-To get all the pending members of a group in turn you'd run:
-
-```sql
-SELECT *
-FROM pending_group_members
-WHERE group_id = 4
-```
-
-If you want to get both you can use a `UNION`, though you need to be explicit
-about what columns you want to `SELECT` as otherwise the result set uses the
-columns of the first query. For example:
-
-```sql
-SELECT id, 'Group' AS target_type, group_id AS target_id
-FROM group_members
-
-UNION ALL
-
-SELECT id, 'Project' AS target_type, project_id AS target_id
-FROM project_members
-```
-
-The above example is perhaps a bit silly, but it shows that there's nothing
-stopping you from merging the data together and presenting it on the same page.
-Selecting columns explicitly can also speed up queries as the database has to do
-less work to get the data (compared to selecting all columns, even ones you're
-not using).
-
-Our schema also becomes easier. No longer do we need to both store and index the
-`source_type` column, we can define foreign keys easily, and we don't need to
-filter rows using the `IS NULL` condition.
-
-To summarize: using separate tables allows us to use foreign keys effectively,
-create indexes only where necessary, conserve space, query data more
-efficiently, and scale these tables more easily (for example, by storing them on
-separate disks). A nice side effect of this is that code can also become easier,
-as a single model isn't responsible for handling different kinds of
-data.
+<!-- This redirect file can be deleted after <2022-11-04>. -->
+<!-- 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/query_count_limits.md b/doc/development/query_count_limits.md
index 49509727337..f16c8cfc6cd 100644
--- a/doc/development/query_count_limits.md
+++ b/doc/development/query_count_limits.md
@@ -1,70 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'database/query_count_limits.md'
+remove_date: '2022-11-06'
---
-# Query Count Limits
+This document was moved to [another location](database/query_count_limits.md).
-Each controller or API endpoint is allowed to execute up to 100 SQL queries and
-in test environments we raise an error when this threshold is exceeded.
-
-## Solving Failing Tests
-
-When a test fails because it executes more than 100 SQL queries there are two
-solutions to this problem:
-
-- Reduce the number of SQL queries that are executed.
-- Disable query limiting for the controller or API endpoint.
-
-You should only resort to disabling query limits when an existing controller or endpoint
-is to blame as in this case reducing the number of SQL queries can take a lot of
-effort. Newly added controllers and endpoints are not allowed to execute more
-than 100 SQL queries and no exceptions are made for this rule. _If_ a large
-number of SQL queries is necessary to perform certain work it's best to have
-this work performed by Sidekiq instead of doing this directly in a web request.
-
-## Disable query limiting
-
-In the event that you _have_ to disable query limits for a controller, you must first
-create an issue. This issue should (preferably in the title) mention the
-controller or endpoint and include the appropriate labels (`database`,
-`performance`, and at least a team specific label such as `Discussion`).
-
-After the issue has been created, you can disable query limits on the code in question. For
-Rails controllers it's best to create a `before_action` hook that runs as early
-as possible. The called method in turn should call
-`Gitlab::QueryLimiting.disable!('issue URL here')`. For example:
-
-```ruby
-class MyController < ApplicationController
- before_action :disable_query_limiting, only: [:show]
-
- def index
- # ...
- end
-
- def show
- # ...
- end
-
- def disable_query_limiting
- Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/...')
- end
-end
-```
-
-By using a `before_action` you don't have to modify the controller method in
-question, reducing the likelihood of merge conflicts.
-
-For Grape API endpoints there unfortunately is not a reliable way of running a
-hook before a specific endpoint. This means that you have to add the allowlist
-call directly into the endpoint like so:
-
-```ruby
-get '/projects/:id/foo' do
- Gitlab::QueryLimiting.disable!('...')
-
- # ...
-end
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/query_performance.md b/doc/development/query_performance.md
index 4fe27d42c38..618d007f766 100644
--- a/doc/development/query_performance.md
+++ b/doc/development/query_performance.md
@@ -1,74 +1,11 @@
---
-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
+redirect_to: 'database/query_performance.md'
+remove_date: '2022-11-06'
---
-# Query performance guidelines
+This document was moved to [another location](database/query_performance.md).
-This document describes various guidelines to follow when optimizing SQL queries.
-
-When you are optimizing your SQL queries, there are two dimensions to pay attention to:
-
-1. The query execution time. This is paramount as it reflects how the user experiences GitLab.
-1. The query plan. Optimizing the query plan is important in allowing queries to independently scale over time. Realizing that an index keeps a query performing well as the table grows before the query degrades is an example of why we analyze these plans.
-
-## Timing guidelines for queries
-
-| Query Type | Maximum Query Time | Notes |
-|----|----|---|
-| General queries | `100ms` | This is not a hard limit, but if a query is getting above it, it is important to spend time understanding why it can or cannot be optimized. |
-| Queries in a migration | `100ms` | This is different than the total [migration time](migration_style_guide.md#how-long-a-migration-should-take). |
-| Concurrent operations in a migration | `5min` | Concurrent operations do not block the database, but they block the GitLab update. This includes operations such as `add_concurrent_index` and `add_concurrent_foreign_key`. |
-| Background migrations | `1s` | |
-| Service Ping | `1s` | See the [Service Ping docs](service_ping/implement.md) for more details. |
-
-- When analyzing your query's performance, pay attention to if the time you are seeing is on a [cold or warm cache](#cold-and-warm-cache). These guidelines apply for both cache types.
-- When working with batched queries, change the range and batch size to see how it effects the query timing and caching.
-- If an existing query is not performing well, make an effort to improve it. If it is too complex or would stall development, create a follow-up so it can be addressed in a timely manner. You can always ask the database reviewer or maintainer for help and guidance.
-
-## Cold and warm cache
-
-When evaluating query performance it is important to understand the difference between
-cold and warm cached queries.
-
-The first time a query is made, it is made on a "cold cache". Meaning it needs
-to read from disk. If you run the query again, the data can be read from the
-cache, or what PostgreSQL calls shared buffers. This is the "warm cache" query.
-
-When analyzing an [`EXPLAIN` plan](understanding_explain_plans.md), you can see
-the difference not only in the timing, but by looking at the output for `Buffers`
-by running your explain with `EXPLAIN(analyze, buffers)`. [Database Lab](understanding_explain_plans.md#database-lab-engine)
-automatically includes these options.
-
-If you are making a warm cache query, you see only the `shared hits`.
-
-For example in #database-lab:
-
-```plaintext
-Shared buffers:
- - hits: 36467 (~284.90 MiB) from the buffer pool
- - reads: 0 from the OS file cache, including disk I/O
-```
-
-Or in the explain plan from `psql`:
-
-```sql
-Buffers: shared hit=7323
-```
-
-If the cache is cold, you also see `reads`.
-
-In #database-lab:
-
-```plaintext
-Shared buffers:
- - hits: 17204 (~134.40 MiB) from the buffer pool
- - reads: 15229 (~119.00 MiB) from the OS file cache, including disk I/O
-```
-
-In `psql`:
-
-```sql
-Buffers: shared hit=7202 read=121
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/query_recorder.md b/doc/development/query_recorder.md
index 371d6e0e49e..cb05bc604af 100644
--- a/doc/development/query_recorder.md
+++ b/doc/development/query_recorder.md
@@ -1,145 +1,11 @@
---
-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
+redirect_to: 'database/query_recorder.md'
+remove_date: '2022-11-06'
---
-# QueryRecorder
+This document was moved to [another location](database/query_recorder.md).
-QueryRecorder is a tool for detecting the [N+1 queries problem](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations) from tests.
-
-> Implemented in [spec/support/query_recorder.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/query_recorder.rb) via [9c623e3e](https://gitlab.com/gitlab-org/gitlab-foss/commit/9c623e3e5d7434f2e30f7c389d13e5af4ede770a)
-
-As a rule, merge requests [should not increase query counts](merge_request_performance_guidelines.md#query-counts). If you find yourself adding something like `.includes(:author, :assignee)` to avoid having `N+1` queries, consider using QueryRecorder to enforce this with a test. Without this, a new feature which causes an additional model to be accessed can silently reintroduce the problem.
-
-## How it works
-
-This style of test works by counting the number of SQL queries executed by ActiveRecord. First a control count is taken, then you add new records to the database and rerun the count. If the number of queries has significantly increased then an `N+1` queries problem exists.
-
-```ruby
-it "avoids N+1 database queries" do
- control = ActiveRecord::QueryRecorder.new { visit_some_page }
- create_list(:issue, 5)
- expect { visit_some_page }.not_to exceed_query_limit(control)
-end
-```
-
-You can if you wish, have both the expectation and the control as
-`QueryRecorder` instances:
-
-```ruby
-it "avoids N+1 database queries" do
- control = ActiveRecord::QueryRecorder.new { visit_some_page }
- create_list(:issue, 5)
- action = ActiveRecord::QueryRecorder.new { visit_some_page }
-
- expect(action).not_to exceed_query_limit(control)
-end
-```
-
-As an example you might create 5 issues in between counts, which would cause the query count to increase by 5 if an N+1 problem exists.
-
-In some cases the query count might change slightly between runs for unrelated reasons. In this case you might need to test `exceed_query_limit(control_count + acceptable_change)`, but this should be avoided if possible.
-
-If this test fails, and the control was passed as a `QueryRecorder`, then the
-failure message indicates where the extra queries are by matching queries on
-the longest common prefix, grouping similar queries together.
-
-## Cached queries
-
-By default, QueryRecorder ignores [cached queries](merge_request_performance_guidelines.md#cached-queries) in the count. However, it may be better to count
-all queries to avoid introducing an N+1 query that may be masked by the statement cache.
-To do this, this requires the `:use_sql_query_cache` flag to be set.
-You should pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
-
-```ruby
-it "avoids N+1 database queries", :use_sql_query_cache do
- control = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }
- create_list(:issue, 5)
- expect { visit_some_page }.not_to exceed_all_query_limit(control)
-end
-```
-
-## Use request specs instead of controller specs
-
-Use a [request spec](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/spec/requests) when writing a N+1 test on the controller level.
-
-Controller specs should not be used to write N+1 tests as the controller is only initialized once per example.
-This could lead to false successes where subsequent "requests" could have queries reduced (for example, because of memoization).
-
-## Finding the source of the query
-
-There are multiple ways to find the source of queries.
-
-- Inspect the `QueryRecorder` `data` attribute. It stores queries by `file_name:line_number:method_name`.
- Each entry is a `hash` with the following fields:
-
- - `count`: the number of times a query from this `file_name:line_number:method_name` was called
- - `occurrences`: the actual `SQL` of each call
- - `backtrace`: the stack trace of each call (if either of the two following options were enabled)
-
- `QueryRecorder#find_query` allows filtering queries by their `file_name:line_number:method_name` and
- `count` attributes. For example:
-
- ```ruby
- control = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }
- control.find_query(/.*note.rb.*/, 0, first_only: true)
- ```
-
- `QueryRecorder#occurrences_by_line_method` returns a sorted array based on `data`, sorted by `count`.
-
-- View the call backtrace for the specific `QueryRecorder` instance you want
- by using `ActiveRecord::QueryRecorder.new(query_recorder_debug: true)`. The output
- is stored in file `test.log`.
-
-- Enable the call backtrace for all tests using the `QUERY_RECORDER_DEBUG` environment variable.
-
- To enable this, run the specs with the `QUERY_RECORDER_DEBUG` environment variable set. For example:
-
- ```shell
- QUERY_RECORDER_DEBUG=1 bundle exec rspec spec/requests/api/projects_spec.rb
- ```
-
- This logs calls to QueryRecorder into the `test.log` file. For example:
-
- ```sql
- QueryRecorder SQL: SELECT COUNT(*) FROM "issues" WHERE "issues"."deleted_at" IS NULL AND "issues"."project_id" = $1 AND ("issues"."state" IN ('opened')) AND "issues"."confidential" = $2
- --> /home/user/gitlab/gdk/gitlab/spec/support/query_recorder.rb:19:in `callback'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:127:in `finish'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `block in finish'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `each'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/fanout.rb:46:in `finish'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/instrumenter.rb:36:in `finish'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications/instrumenter.rb:25:in `instrument'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract_adapter.rb:478:in `log'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql_adapter.rb:601:in `exec_cache'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql_adapter.rb:585:in `execute_and_clear'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in `exec_query'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:356:in `select'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `block in select_all'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:83:in `cache_sql'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:68:in `select_all'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:270:in `execute_simple_calculation'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:227:in `perform_calculation'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:133:in `calculate'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/relation/calculations.rb:48:in `count'
- --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:20:in `uncached_count'
- --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:12:in `block in count'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:299:in `block in fetch'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:585:in `block in save_block_result_to_cache'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:547:in `block in instrument'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/notifications.rb:166:in `instrument'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:547:in `instrument'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:584:in `save_block_result_to_cache'
- --> /home/user/.rbenv/versions/2.3.5/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/cache.rb:299:in `fetch'
- --> /home/user/gitlab/gdk/gitlab/app/services/base_count_service.rb:12:in `count'
- --> /home/user/gitlab/gdk/gitlab/app/models/project.rb:1296:in `open_issues_count'
- ```
-
-## See also
-
-- [Bullet](profiling.md#bullet) For finding `N+1` query problems
-- [Performance guidelines](performance.md)
-- [Merge request performance guidelines - Query counts](merge_request_performance_guidelines.md#query-counts)
-- [Merge request performance guidelines - Cached queries](merge_request_performance_guidelines.md#cached-queries)
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/rails_update.md b/doc/development/rails_update.md
index 36ffae97377..9907a78421f 100644
--- a/doc/development/rails_update.md
+++ b/doc/development/rails_update.md
@@ -27,8 +27,8 @@ We strive to run GitLab using the latest Rails releases to benefit from performa
1. Run `yarn patch-package @rails/ujs` after updating this to ensure our local patch file version matches.
1. Create an MR with the `pipeline:run-all-rspec` label and see if pipeline breaks.
1. To resolve and debug spec failures use `git bisect` against the rails repository. See the [debugging section](#git-bisect-against-rails) below.
-1. Include links to the Gem diffs between the two versions in the merge request description. For example, this is the gem diff for [`activesupport` 6.1.3.2 to
-6.1.4.1](https://my.diffend.io/gems/activerecord/6.1.3.2/6.1.4.1).
+1. Include links to the Gem diffs between the two versions in the merge request description. For example, this is the gem diff for
+ [`activesupport` 6.1.3.2 to 6.1.4.1](https://my.diffend.io/gems/activerecord/6.1.3.2/6.1.4.1).
### Prepare an MR for Gitaly
diff --git a/doc/development/real_time.md b/doc/development/real_time.md
index df725a36a93..21f3ee1f3b2 100644
--- a/doc/development/real_time.md
+++ b/doc/development/real_time.md
@@ -60,8 +60,8 @@ downstream services.
To mitigate this, ensure that the code establishing the new WebSocket connection
is feature flagged and defaulted to `off`. A careful, percentage-based roll-out
-of the feature flag ensures that effects can be observed on the [WebSocket
-dashboard](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?orgId=1)
+of the feature flag ensures that effects can be observed on the
+[WebSocket dashboard](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?orgId=1)
1. Create a
[feature flag roll-out](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md)
diff --git a/doc/development/redis/new_redis_instance.md b/doc/development/redis/new_redis_instance.md
index 4900755b58c..efaf1e5a6d0 100644
--- a/doc/development/redis/new_redis_instance.md
+++ b/doc/development/redis/new_redis_instance.md
@@ -169,7 +169,7 @@ MultiStore uses two feature flags to control the actual migration:
- `use_primary_and_secondary_stores_for_[store_name]`
- `use_primary_store_as_default_for_[store_name]`
-For example, if our new Redis instance is called `Gitlab::Redis::Foo`, we can [create](../../../ee/development/feature_flags/#create-a-new-feature-flag) two feature flags by executing:
+For example, if our new Redis instance is called `Gitlab::Redis::Foo`, we can [create](../feature_flags/index.md#create-a-new-feature-flag) two feature flags by executing:
```shell
bin/feature-flag use_primary_and_secondary_stores_for_foo
@@ -265,7 +265,7 @@ instances to cope without this functional partition.
If we decide to keep the migration code:
- We should document the migration steps.
-- If we used a feature flag, we should ensure it's an [ops type feature
- flag](../feature_flags/index.md#ops-type), as these are long-lived flags.
+- If we used a feature flag, we should ensure it's an
+ [ops type feature flag](../feature_flags/index.md#ops-type), as these are long-lived flags.
Otherwise, we can remove the flags and conclude the project.
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index f3eb1ebcc0c..ef4e8b0310f 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -109,7 +109,7 @@ the various abstractions and what they can (not) reuse:
| Abstraction | Service classes | Finders | Presenters | Serializers | Model instance method | Model class methods | Active Record | Worker
|:-----------------------|:-----------------|:---------|:------------|:--------------|:------------------------|:----------------------|:----------------|:--------
-| Controller | Yes | Yes | Yes | Yes | Yes | No | No | No
+| Controller/API endpoint| Yes | Yes | Yes | Yes | Yes | No | No | No
| Service class | Yes | Yes | No | No | Yes | No | No | Yes
| Finder | No | No | No | No | Yes | Yes | No | No
| Presenter | No | Yes | No | No | Yes | Yes | No | No
@@ -125,9 +125,11 @@ Everything in `app/controllers`.
Controllers should not do much work on their own, instead they simply pass input
to other classes and present the results.
-### Grape endpoint
+### API endpoints
-Everything in `lib/api`.
+Everything in `lib/api` (the REST API) and `app/graphql` (the GraphQL API).
+
+API endpoints have the same abstraction level as controllers.
### Service classes
@@ -145,6 +147,27 @@ 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`.
#### ServiceResponse
@@ -206,7 +229,27 @@ See [the documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/p
Everything in `app/serializers`, used for presenting the response to a request,
typically in JSON.
-### Model class methods
+### Models
+
+Classes and modules in `app/models` represent domain concepts that encapsulate both
+[data and behavior](https://en.wikipedia.org/wiki/Domain_model).
+
+These classes can interact directly with a data store (like ActiveRecord models) or
+can be a thin wrapper (Plain Old Ruby Objects) on top of ActiveRecord models to express a
+richer domain concept.
+
+[Entities and Value Objects](https://martinfowler.com/bliki/EvansClassification.html)
+that represent domain concepts are considered domain models.
+
+Some examples:
+
+- [`DesignManagement::DesignAtVersion`](https://gitlab.com/gitlab-org/gitlab/-/blob/b62ce98cff8e0530210670f9cb0314221181b77f/app/models/design_management/design_at_version.rb)
+ is a model that leverages validations to combine designs and versions.
+- [`Ci::Minutes::Usage`](https://gitlab.com/gitlab-org/gitlab/-/blob/ec52f19f7325410177c00fef06379f55ab7cab67/ee/app/models/ci/minutes/usage.rb)
+ is a Value Object that provides [CI/CD minutes usage](../ci/pipelines/cicd_minutes.md)
+ for a given namespace.
+
+#### Model class methods
These are class methods defined by _GitLab itself_, including the following
methods provided by Active Record:
@@ -220,7 +263,7 @@ methods provided by Active Record:
Any other methods such as `find_by(some_column: X)` are not included, and
instead fall under the "Active Record" abstraction.
-### Model instance methods
+#### Model instance methods
Instance methods defined on Active Record models by _GitLab itself_. Methods
provided by Active Record are not included, except for the following methods:
@@ -230,7 +273,7 @@ provided by Active Record are not included, except for the following methods:
- `destroy`
- `delete`
-### Active Record
+#### Active Record
The API provided by Active Record itself, such as the `where` method, `save`,
`delete_all`, and so on.
diff --git a/doc/development/routing.md b/doc/development/routing.md
index 2b3ecd8127b..3d5857b4237 100644
--- a/doc/development/routing.md
+++ b/doc/development/routing.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Routing
-The GitLab backend is written primarily with Rails so it uses [Rails
-routing](https://guides.rubyonrails.org/routing.html). Beside Rails best
+The GitLab backend is written primarily with Rails so it uses
+[Rails routing](https://guides.rubyonrails.org/routing.html). Beside Rails best
practices, there are few rules unique to the GitLab application. To
support subgroups, GitLab project and group routes use the wildcard
character to match project and group routes. For example, we might have
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index 39cd0ecfcdd..b7ee0ca1167 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -35,8 +35,8 @@ The application has a tight coupling to the database schema. When the
application starts, Rails queries the database schema, caching the tables and
column types for the data requested. Because of this schema cache, dropping a
column or table while the application is running can produce 500 errors to the
-user. This is why we have a [process for dropping columns and other
-no-downtime changes](database/avoiding_downtime_in_migrations.md).
+user. This is why we have a
+[process for dropping columns and other no-downtime changes](database/avoiding_downtime_in_migrations.md).
#### Multi-tenancy
@@ -61,11 +61,11 @@ There are two ways to deal with this:
- Sharding. Distribute data across multiple databases.
Partitioning is a built-in PostgreSQL feature and requires minimal changes
-in the application. However, it [requires PostgreSQL
-11](https://www.2ndquadrant.com/en/blog/partitioning-evolution-postgresql-11/).
+in the application. However, it
+[requires PostgreSQL 11](https://www.2ndquadrant.com/en/blog/partitioning-evolution-postgresql-11/).
-For example, a natural way to partition is to [partition tables by
-dates](https://gitlab.com/groups/gitlab-org/-/epics/2023). For example,
+For example, a natural way to partition is to
+[partition tables by dates](https://gitlab.com/groups/gitlab-org/-/epics/2023). For example,
the `events` and `audit_events` table are natural candidates for this
kind of partitioning.
@@ -77,10 +77,10 @@ to abstract data access into API calls that abstract the database from
the application, but this is a significant amount of work.
There are solutions that may help abstract the sharding to some extent
-from the application. For example, we want to look at [Citus
-Data](https://www.citusdata.com/product/community) closely. Citus Data
-provides a Rails plugin that adds a [tenant ID to ActiveRecord
-models](https://www.citusdata.com/blog/2017/01/05/easily-scale-out-multi-tenant-apps/).
+from the application. For example, we want to look at
+[Citus Data](https://www.citusdata.com/product/community) closely. Citus Data
+provides a Rails plugin that adds a
+[tenant ID to ActiveRecord models](https://www.citusdata.com/blog/2017/01/05/easily-scale-out-multi-tenant-apps/).
Sharding can also be done based on feature verticals. This is the
microservice approach to sharding, where each service represents a
@@ -97,12 +97,12 @@ systems.
#### Database size
-A recent [database checkup shows a breakdown of the table sizes on
-GitLab.com](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/8022#master-1022016101-8).
+A recent
+[database checkup shows a breakdown of the table sizes on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/8022#master-1022016101-8).
Since `merge_request_diff_files` contains over 1 TB of data, we want to
-reduce/eliminate this table first. GitLab has support for [storing diffs in
-object storage](../administration/merge_request_diffs.md), which we [want to do on
-GitLab.com](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7356).
+reduce/eliminate this table first. GitLab has support for
+[storing diffs in object storage](../administration/merge_request_diffs.md), which we
+[want to do on GitLab.com](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/7356).
#### High availability
@@ -128,8 +128,7 @@ some actions that aren't traditionally available in standard load balancers. For
example, the application considers a replica only if its replication lag is low
(for example, WAL data behind by less than 100 MB).
-More [details are in a blog
-post](https://about.gitlab.com/blog/2017/10/02/scaling-the-gitlab-database/).
+More [details are in a blog post](https://about.gitlab.com/blog/2017/10/02/scaling-the-gitlab-database/).
### PgBouncer
@@ -148,10 +147,10 @@ limitation:
- Run multiple PgBouncer instances.
- Use a multi-threaded connection pooler (for example,
- [Odyssey](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7776).
+ [Odyssey](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/7776).
-On some Linux systems, it's possible to run [multiple PgBouncer instances on
-the same port](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4796).
+On some Linux systems, it's possible to run
+[multiple PgBouncer instances on the same port](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4796).
On GitLab.com, we run multiple PgBouncer instances on different ports to
avoid saturating a single core.
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 9048da77071..8053b4285e6 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -196,7 +196,7 @@ Go's [`regexp`](https://pkg.go.dev/regexp) package uses `re2` and isn't vulnerab
- [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps.
- [Runaway Regular Expressions](https://www.regular-expressions.info/catastrophic.html)
-- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](https://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities.
+- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](https://davisjam.github.io/files/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities.
- [Freezing the web: A study of ReDoS vulnerabilities in JavaScript-based web servers](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-staicu.pdf). Another research paper about detecting ReDoS vulnerabilities.
## Server Side Request Forgery (SSRF)
diff --git a/doc/development/serializing_data.md b/doc/development/serializing_data.md
index 97e6f665484..aa8b20eded7 100644
--- a/doc/development/serializing_data.md
+++ b/doc/development/serializing_data.md
@@ -1,90 +1,11 @@
---
-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
+redirect_to: 'database/serializing_data.md'
+remove_date: '2022-11-06'
---
-# Serializing Data
+This document was moved to [another location](database/serializing_data.md).
-**Summary:** don't store serialized data in the database, use separate columns
-and/or tables instead. This includes storing of comma separated values as a
-string.
-
-Rails makes it possible to store serialized data in JSON, YAML or other formats.
-Such a field can be defined as follows:
-
-```ruby
-class Issue < ActiveRecord::Model
- serialize :custom_fields
-end
-```
-
-While it may be tempting to store serialized data in the database there are many
-problems with this. This document outlines these problems and provide an
-alternative.
-
-## Serialized Data Is Less Powerful
-
-When using a relational database you have the ability to query individual
-fields, change the schema, index data, and so forth. When you use serialized data
-all of that becomes either very difficult or downright impossible. While
-PostgreSQL does offer the ability to query JSON fields it is mostly meant for
-very specialized use cases, and not for more general use. If you use YAML in
-turn there's no way to query the data at all.
-
-## Waste Of Space
-
-Storing serialized data such as JSON or YAML ends up wasting a lot of space.
-This is because these formats often include additional characters (for example, double
-quotes or newlines) besides the data that you are storing.
-
-## Difficult To Manage
-
-There comes a time where you must add a new field to the serialized
-data, or change an existing one. Using serialized data this becomes difficult
-and very time consuming as the only way of doing so is to re-write all the
-stored values. To do so you would have to:
-
-1. Retrieve the data
-1. Parse it into a Ruby structure
-1. Mutate it
-1. Serialize it back to a String
-1. Store it in the database
-
-On the other hand, if one were to use regular columns adding a column would be:
-
-```sql
-ALTER TABLE table_name ADD COLUMN column_name type;
-```
-
-Such a query would take very little to no time and would immediately apply to
-all rows, without having to re-write large JSON or YAML structures.
-
-Finally, there comes a time when the JSON or YAML structure is no longer
-sufficient and you must migrate away from it. When storing only a few rows
-this may not be a problem, but when storing millions of rows such a migration
-can take hours or even days to complete.
-
-## Relational Databases Are Not Document Stores
-
-When storing data as JSON or YAML you're essentially using your database as if
-it were a document store (for example, MongoDB), except you're not using any of the
-powerful features provided by a typical RDBMS _nor_ are you using any of the
-features provided by a typical document store (for example, the ability to index fields
-of documents with variable fields). In other words, it's a waste.
-
-## Consistent Fields
-
-One argument sometimes made in favour of serialized data is having to store
-widely varying fields and values. Sometimes this is truly the case, and then
-perhaps it might make sense to use serialized data. However, in 99% of the cases
-the fields and types stored tend to be the same for every row. Even if there is
-a slight difference you can still use separate columns and just not set the ones
-you don't need.
-
-## The Solution
-
-The solution is to use separate columns and/or separate tables.
-This allows you to use all the features provided by your database, it
-makes it easier to manage and migrate the data, you conserve space, you can
-index the data efficiently and so forth.
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/service_measurement.md b/doc/development/service_measurement.md
index 82fb9731bcb..17e509672f2 100644
--- a/doc/development/service_measurement.md
+++ b/doc/development/service_measurement.md
@@ -19,7 +19,7 @@ The measuring module is a tool that allows to measure a service's execution, and
- RSS memory usage
- Server worker ID
-The measuring module logs these measurements into a structured log called [`service_measurement.log`](../administration/logs.md#service_measurementlog),
+The measuring module logs these measurements into a structured log called [`service_measurement.log`](../administration/logs/index.md#service_measurementlog),
as a single entry for each service execution.
For GitLab.com, `service_measurement.log` is ingested in Elasticsearch and Kibana as part of our monitoring solution.
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index 3263ba6458e..0ebc58dd669 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Service Ping consists of two kinds of data:
- **Counters**: Track how often a certain event happened over time, such as how many CI/CD pipelines have run.
- They are monotonic and always trend up.
+ They are monotonic and usually trend up.
- **Observations**: Facts collected from one or more GitLab instances and can carry arbitrary data.
There are no general guidelines for how to collect those, due to the individual nature of that data.
@@ -94,7 +94,7 @@ add_metric('CountUsersAssociatingMilestonesToReleasesMetric', time_frame: 'all')
```
WARNING:
-Counting over non-unique columns can lead to performance issues. For more information, see the [iterating tables in batches](../iterating_tables_in_batches.md) guide.
+Counting over non-unique columns can lead to performance issues. For more information, see the [iterating tables in batches](../database/iterating_tables_in_batches.md) guide.
Examples:
@@ -269,9 +269,15 @@ Arguments:
#### Ordinary Redis counters
-Example of implementation:
+Example of implementation: [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb), using Redis methods [`INCR`](https://redis.io/commands/incr) and [`GET`](https://redis.io/commands/get).
-Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
+Events are handled by counter classes in the `Gitlab::UsageDataCounters` namespace, inheriting from `BaseCounter`, that are either:
+
+1. Listed in [`Gitlab::UsageDataCounters::COUNTERS`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters.rb#L5) to be then included in `Gitlab::UsageData`.
+
+1. Specified in the metric definition using the `RedisMetric` instrumentation class as a `counter_class` option to be picked up using the [metric instrumentation](metrics_instrumentation.md) framework. Refer to the [Redis metrics](metrics_instrumentation.md#redis-metrics) documentation for an example implementation.
+
+Inheriting classes are expected to override `KNOWN_EVENTS` and `PREFIX` constants to build event names and associated metrics. For example, for prefix `issues` and events array `%w[create, update, delete]`, three metrics will be added to the Service Ping payload: `counts.issues_create`, `counts.issues_update` and `counts.issues_delete`.
##### `UsageData` API
@@ -316,7 +322,7 @@ Enabled by default in GitLab 13.7 and later.
#### Redis HLL counters
WARNING:
-HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount), data from
+HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount/), data from
used HLL implementation is "approximated with a standard error of 0.81%".
NOTE:
@@ -324,7 +330,7 @@ NOTE:
With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values.
-Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount).
+Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd/) and [PFCOUNT](https://redis.io/commands/pfcount/).
##### Add new events
@@ -371,14 +377,15 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
- In the controller using the `RedisTracking` module and the following format:
```ruby
- track_redis_hll_event(*controller_actions, name:, if: nil, &block)
+ track_event(*controller_actions, name:, conditions: nil, destinations: [:redis_hll], &block)
```
Arguments:
- `controller_actions`: the controller actions to track.
- `name`: the event name.
- - `if`: optional custom conditions. Uses the same format as Rails callbacks.
+ - `conditions`: optional custom conditions. Uses the same format as Rails callbacks.
+ - `destinations`: optional list of destinations. Currently supports `:redis_hll` and `:snowplow`. Default: [:redis_hll].
- `&block`: optional block that computes and returns the `custom_id` that we want to track. This overrides the `visitor_id`.
Example:
@@ -389,7 +396,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
include RedisTracking
skip_before_action :authenticate_user!, only: :show
- track_redis_hll_event :index, :show, name: 'users_visiting_projects'
+ track_event :index, :show, name: 'users_visiting_projects'
def index
render html: 'index'
@@ -688,7 +695,7 @@ pry(main)> Gitlab::UsageData.count(User.active)
Paste the SQL query into `#database-lab` to see how the query performs at scale.
- GitLab.com's production database has a 15 second timeout.
-- Any single query must stay below the [1 second execution time](../query_performance.md#timing-guidelines-for-queries) with cold caches.
+- Any single query must stay below the [1 second execution time](../database/query_performance.md#timing-guidelines-for-queries) with cold caches.
- Add a specialized index on columns involved to reduce the execution time.
To understand the query's execution, we add the following information
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index cd8af3e9152..4481fe33bda 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -22,9 +22,7 @@ and sales teams understand how GitLab is used. The data helps to:
Service Ping information is not anonymous. It's linked to the instance's hostname, but does
not contain project names, usernames, or any other specific data.
-Sending a Service Ping payload is optional and you can [disable](../../user/admin_area/settings/usage_statistics.md#enable-or-disable-usage-statistics) it on any
-self-managed instance. When Service Ping is enabled, GitLab gathers data from the other instances
-and can show your instance's usage statistics to your users.
+Service Ping is enabled by default. However, you can [disable](../../user/admin_area/settings/usage_statistics.md#enable-or-disable-usage-statistics) it on any self-managed instance. When Service Ping is enabled, GitLab gathers data from the other instances and can show your instance's usage statistics to your users.
## Service Ping terminology
@@ -113,7 +111,7 @@ sequenceDiagram
1. Finally, the timing metadata information that is used for diagnostic purposes is submitted to the Versions application. It consists of a list of metric identifiers and the time it took to calculate the metrics:
- > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911) in GitLab 15.0 [with a flag(../../user/feature_flags.md), enabled by default.
+ > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911) in GitLab 15.0 [with a flag](../../user/feature_flags.md), enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/295289) in GitLab 15.2. [Feature flag `measure_service_ping_metric_collection`](https://gitlab.com/gitlab-org/gitlab/-/issues/358128) removed.
```ruby
diff --git a/doc/development/service_ping/metrics_dictionary.md b/doc/development/service_ping/metrics_dictionary.md
index 2adba5d8095..d063c4c7601 100644
--- a/doc/development/service_ping/metrics_dictionary.md
+++ b/doc/development/service_ping/metrics_dictionary.md
@@ -205,8 +205,8 @@ instance unique identifier.
key_path: uuid
description: GitLab instance unique identifier
product_category: collection
-product_section: growth
-product_stage: growth
+product_section: analytics
+product_stage: analytics
product_group: product_intelligence
value_type: string
status: active
@@ -301,7 +301,7 @@ bundle exec rails generate gitlab:usage_metric_definition:redis_hll issues users
## Metrics Dictionary
-[Metrics Dictionary is a separate application](https://gitlab.com/gitlab-org/growth/product-intelligence/metric-dictionary).
+[Metrics Dictionary is a separate application](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/metric-dictionary).
All metrics available in Service Ping are in the [Metrics Dictionary](https://metrics.gitlab.com/).
diff --git a/doc/development/service_ping/metrics_instrumentation.md b/doc/development/service_ping/metrics_instrumentation.md
index e1c51713f3c..9dc37386111 100644
--- a/doc/development/service_ping/metrics_instrumentation.md
+++ b/doc/development/service_ping/metrics_instrumentation.md
@@ -29,7 +29,7 @@ A metric definition has the [`instrumentation_class`](metrics_dictionary.md) fie
The defined instrumentation class should inherit one of the existing metric classes: `DatabaseMetric`, `RedisMetric`, `RedisHLLMetric`, `NumbersMetric` or `GenericMetric`.
-The current convention is that a single instrumentation class corresponds to a single metric. On a rare occasions, there are exceptions to that convention like [Redis metrics](#redis-metrics). To use a single instrumentation class for more than one metric, please reach out to one of the `@gitlab-org/growth/product-intelligence/engineers` members to consult about your case.
+The current convention is that a single instrumentation class corresponds to a single metric. On rare occasions, there are exceptions to that convention like [Redis metrics](#redis-metrics). To use a single instrumentation class for more than one metric, please reach out to one of the `@gitlab-org/analytics-section/product-intelligence/engineers` members to consult about your case.
Using the instrumentation classes ensures that metrics can fail safe individually, without breaking the entire
process of Service Ping generation.
@@ -38,12 +38,15 @@ We have built a domain-specific language (DSL) to define the metrics instrumenta
## Database metrics
+You can use database metrics to track data kept in the database, for example, a count of issues that exist on a given instance.
+
- `operation`: Operations for the given `relation`, one of `count`, `distinct_count`, `sum`, and `average`.
- `relation`: `ActiveRecord::Relation` for the objects we want to perform the `operation`.
- `start`: Specifies the start value of the batch counting, by default is `relation.minimum(:id)`.
- `finish`: Specifies the end value of the batch counting, by default is `relation.maximum(:id)`.
- `cache_start_and_finish_as`: Specifies the cache key for `start` and `finish` values and sets up caching them. Use this call when `start` and `finish` are expensive queries that should be reused between different metric calculations.
- `available?`: Specifies whether the metric should be reported. The default is `true`.
+- `timestamp_column`: Optionally specifies timestamp column for metric used to filter records for time constrained metrics. The default is `created_at`.
[Example of a merge request that adds a database metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60022).
@@ -149,6 +152,8 @@ end
## Redis metrics
+You can use Redis metrics to track events not kept in the database, for example, a count of how many times the search bar has been used.
+
[Example of a merge request that adds a `Redis` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66582).
Count unique values for `source_code_pushes` event.
@@ -199,6 +204,9 @@ options:
```
## Redis HyperLogLog metrics
+
+You can use Redis HyperLogLog metrics to track events not kept in the database and incremented for unique values such as unique users,
+for example, a count of how many different users used the search bar.
[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685).
@@ -283,6 +291,8 @@ instrumentation_class: 'IssuesBoardsCountMetric'
## Generic metrics
+You can use generic metrics for other metrics, for example, an instance's database version. Observations type of data will always have a Generic metric counter type.
+
- `value`: Specifies the value of the metric.
- `available?`: Specifies whether the metric should be reported. The default is `true`.
diff --git a/doc/development/service_ping/performance_indicator_metrics.md b/doc/development/service_ping/performance_indicator_metrics.md
index bdd4c319d41..d2abc597a22 100644
--- a/doc/development/service_ping/performance_indicator_metrics.md
+++ b/doc/development/service_ping/performance_indicator_metrics.md
@@ -10,8 +10,7 @@ This guide describes how to use metrics definitions to define [performance indic
To use a metric definition to manage a performance indicator:
-1. Create a new issue and use the [Performance Indicator Metric issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Performance%20Indicator%20Metric).
+1. Create a merge request that includes related changes.
1. Use labels `~"product intelligence"`, `"~Data Warehouse::Impact Check"`.
-1. Create a merge request that includes changes related only to the metric performance indicator.
1. Update the metric definition `performance_indicator_type` [field](metrics_dictionary.md#metrics-definition-and-validation).
-1. Create an issue in GitLab Data Team project with the [Product Performance Indicator template](https://gitlab.com/gitlab-data/analytics/-/issues/new?issuable_template=Product%20Performance%20Indicator%20Template).
+1. Create an issue in GitLab Product Data Insights project with the [PI Chart Help template](https://gitlab.com/gitlab-data/product-analytics/-/issues/new?issuable_template=PI%20Chart%20Help) to have the new metric visualized.
diff --git a/doc/development/service_ping/review_guidelines.md b/doc/development/service_ping/review_guidelines.md
index 4ce5b2d577c..1b00858be7e 100644
--- a/doc/development/service_ping/review_guidelines.md
+++ b/doc/development/service_ping/review_guidelines.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Service Ping review guidelines
This page includes introductory material for a
-[Product Intelligence](https://about.gitlab.com/handbook/engineering/development/growth/product-intelligence/)
+[Product Intelligence](https://about.gitlab.com/handbook/engineering/development/analytics/product-intelligence/)
review, and is specific to Service Ping related reviews. For broader advice and
general best practices for code reviews, refer to our [code review guide](../code_review.md).
@@ -42,7 +42,7 @@ are regular backend changes.
- Assign both the `~backend` and `~product intelligence` reviews to another Product Intelligence team member.
- Assign the maintainer review to someone outside of the Product Intelligence group.
- Assign an
- [engineer](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) from the Product Intelligence team for a review.
+ [engineer](https://gitlab.com/groups/gitlab-org/analytics-section/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) from the Product Intelligence team for a review.
- Set the correct attributes in the metric's YAML definition:
- `product_section`, `product_stage`, `product_group`, `product_category`
- Provide a clear description of the metric.
@@ -76,7 +76,7 @@ are regular backend changes.
[Danger bot](../dangerbot.md) adds the list of changed Product Intelligence files
and pings the
-[`@gitlab-org/growth/product-intelligence/engineers`](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) group for merge requests
+[`@gitlab-org/analytics-section/product-intelligence/engineers`](https://gitlab.com/groups/gitlab-org/analytics-section/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) group for merge requests
that are not drafts.
Any of the Product Intelligence engineers can be assigned for the Product Intelligence review.
diff --git a/doc/development/service_ping/usage_data.md b/doc/development/service_ping/usage_data.md
index a659bbf2265..4181bd90a02 100644
--- a/doc/development/service_ping/usage_data.md
+++ b/doc/development/service_ping/usage_data.md
@@ -59,7 +59,7 @@ Arguments:
- `end`: custom end of the batch counting to avoid complex min calculations
WARNING:
-Counting over non-unique columns can lead to performance issues. For more information, see the [iterating tables in batches](../iterating_tables_in_batches.md) guide.
+Counting over non-unique columns can lead to performance issues. For more information, see the [iterating tables in batches](../database/iterating_tables_in_batches.md) guide.
Examples:
diff --git a/doc/development/sha1_as_binary.md b/doc/development/sha1_as_binary.md
index a7bb3001ddb..7f928d09470 100644
--- a/doc/development/sha1_as_binary.md
+++ b/doc/development/sha1_as_binary.md
@@ -1,42 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'database/sha1_as_binary.md'
+remove_date: '2022-11-06'
---
-# Storing SHA1 Hashes As Binary
+This document was moved to [another location](database/sha1_as_binary.md).
-Storing SHA1 hashes as strings is not very space efficient. A SHA1 as a string
-requires at least 40 bytes, an additional byte to store the encoding, and
-perhaps more space depending on the internals of PostgreSQL.
-
-On the other hand, if one were to store a SHA1 as binary one would only need 20
-bytes for the actual SHA1, and 1 or 4 bytes of additional space (again depending
-on database internals). This means that in the best case scenario we can reduce
-the space usage by 50%.
-
-To make this easier to work with you can include the concern `ShaAttribute` into
-a model and define a SHA attribute using the `sha_attribute` class method. For
-example:
-
-```ruby
-class Commit < ActiveRecord::Base
- include ShaAttribute
-
- sha_attribute :sha
-end
-```
-
-This allows you to use the value of the `sha` attribute as if it were a string,
-while storing it as binary. This means that you can do something like this,
-without having to worry about converting data to the right binary format:
-
-```ruby
-commit = Commit.find_by(sha: '88c60307bd1f215095834f09a1a5cb18701ac8ad')
-commit.sha = '971604de4cfa324d91c41650fabc129420c8d1cc'
-commit.save
-```
-
-There is however one requirement: the column used to store the SHA has _must_ be
-a binary type. For Rails this means you need to use the `:binary` type instead
-of `:text` or `:string`.
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/shell_commands.md b/doc/development/shell_commands.md
index fcb8c20bdd3..d8a3f86685e 100644
--- a/doc/development/shell_commands.md
+++ b/doc/development/shell_commands.md
@@ -17,7 +17,7 @@ These guidelines are meant to make your code more reliable _and_ secure.
## Use File and FileUtils instead of shell commands
-Sometimes we invoke basic Unix commands via the shell when there is also a Ruby API for doing it. Use the Ruby API if it exists. <https://www.ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions>
+Sometimes we invoke basic Unix commands via the shell when there is also a Ruby API for doing it. Use [the Ruby API](https://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html#module-FileUtils-label-Module+Functions) if it exists.
```ruby
# Wrong
diff --git a/doc/development/sidekiq/compatibility_across_updates.md b/doc/development/sidekiq/compatibility_across_updates.md
index 96a3573d11a..1d369b5a970 100644
--- a/doc/development/sidekiq/compatibility_across_updates.md
+++ b/doc/development/sidekiq/compatibility_across_updates.md
@@ -18,18 +18,17 @@ several possible situations:
## Adding new workers
-On GitLab.com, we [do not currently have a Sidekiq deployment in the
-canary stage](https://gitlab.com/gitlab-org/gitlab/-/issues/19239). This
-means that a new worker than can be scheduled from an HTTP endpoint may
+On GitLab.com, we
+[do not currently have a Sidekiq deployment in the canary stage](https://gitlab.com/gitlab-org/gitlab/-/issues/19239).
+This means that a new worker than can be scheduled from an HTTP endpoint may
be scheduled from canary but not run on Sidekiq until the full
production deployment is complete. This can be several hours later than
scheduling the job. For some workers, this will not be a problem. For
-others - particularly [latency-sensitive
-jobs](worker_attributes.md#latency-sensitive-jobs) - this will result in a poor user
-experience.
+others - particularly [latency-sensitive jobs](worker_attributes.md#latency-sensitive-jobs) -
+this will result in a poor user experience.
This only applies to new worker classes when they are first introduced.
-As we recommend [using feature flags](../feature_flags/) as a general
+As we recommend [using feature flags](../feature_flags/index.md) as a general
development process, it's best to control the entire change (including
scheduling of the new Sidekiq worker) with a feature flag.
diff --git a/doc/development/sidekiq/idempotent_jobs.md b/doc/development/sidekiq/idempotent_jobs.md
index a5ae8737ad1..5d1ebce763e 100644
--- a/doc/development/sidekiq/idempotent_jobs.md
+++ b/doc/development/sidekiq/idempotent_jobs.md
@@ -78,9 +78,8 @@ GitLab supports two deduplication strategies:
- `until_executing`, which is the default strategy
- `until_executed`
-More [deduplication strategies have been
-suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195). If
-you are implementing a worker that could benefit from a different
+More [deduplication strategies have been suggested](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/195).
+If you are implementing a worker that could benefit from a different
strategy, please comment in the issue.
#### Until Executing
diff --git a/doc/development/sidekiq/index.md b/doc/development/sidekiq/index.md
index c9906c4c768..003f54d48b5 100644
--- a/doc/development/sidekiq/index.md
+++ b/doc/development/sidekiq/index.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
We use [Sidekiq](https://github.com/mperham/sidekiq) as our background
job processor. These guides are for writing jobs that will work well on
GitLab.com and be consistent with our existing worker classes. For
-information on administering GitLab, see [configuring Sidekiq](../../administration/sidekiq.md).
+information on administering GitLab, see [configuring Sidekiq](../../administration/sidekiq/index.md).
There are pages with additional detail on the following topics:
@@ -27,12 +27,11 @@ There are pages with additional detail on the following topics:
All workers should include `ApplicationWorker` instead of `Sidekiq::Worker`,
which adds some convenience methods and automatically sets the queue based on
-the [routing rules](../../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
+the [routing rules](../../administration/sidekiq/extra_sidekiq_routing.md#queue-routing-rules).
## Retries
-Sidekiq defaults to using [25
-retries](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry),
+Sidekiq defaults to using [25 retries](https://github.com/mperham/sidekiq/wiki/Error-Handling#automatic-job-retry),
with back-off between each retry. 25 retries means that the last retry
would happen around three weeks after the first attempt (assuming all 24
prior retries failed).
@@ -64,7 +63,7 @@ error rate.
Previously, each worker had its own queue, which was automatically set based on the
worker class name. For a worker named `ProcessSomethingWorker`, the queue name
would be `process_something`. You can now route workers to a specific queue using
-[queue routing rules](../../administration/operations/extra_sidekiq_routing.md#queue-routing-rules).
+[queue routing rules](../../administration/sidekiq/extra_sidekiq_routing.md#queue-routing-rules).
In GDK, new workers are routed to a queue named `default`.
If you're not sure what queue a worker uses,
@@ -75,7 +74,7 @@ After adding a new worker, run `bin/rake
gitlab:sidekiq:all_queues_yml:generate` to regenerate
`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
it can be picked up by
-[`sidekiq-cluster`](../../administration/operations/extra_sidekiq_processes.md)
+[`sidekiq-cluster`](../../administration/sidekiq/extra_sidekiq_processes.md)
in installations that don't use routing rules. To learn more about potential changes,
read [Use routing rules by default and deprecate queue selectors for self-managed](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/596).
@@ -176,11 +175,10 @@ available in Sidekiq. There are possible workarounds such as:
Some jobs have a weight declared. This is only used when running Sidekiq
in the default execution mode - using
-[`sidekiq-cluster`](../../administration/operations/extra_sidekiq_processes.md)
+[`sidekiq-cluster`](../../administration/sidekiq/extra_sidekiq_processes.md)
does not account for weights.
-As we are [moving towards using `sidekiq-cluster` in
-Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
+As we are [moving towards using `sidekiq-cluster` in Free](https://gitlab.com/gitlab-org/gitlab/-/issues/34396), newly-added
workers do not need to have weights specified. They can use the
default weight, which is 1.
diff --git a/doc/development/sidekiq/logging.md b/doc/development/sidekiq/logging.md
index 474ea5de951..b461047ea47 100644
--- a/doc/development/sidekiq/logging.md
+++ b/doc/development/sidekiq/logging.md
@@ -11,8 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/9) in GitLab 12.8.
To have some more information about workers in the logs, we add
-[metadata to the jobs in the form of an
-`ApplicationContext`](../logging.md#logging-context-metadata-through-rails-or-grape-requests).
+[metadata to the jobs in the form of an `ApplicationContext`](../logging.md#logging-context-metadata-through-rails-or-grape-requests).
In most cases, when scheduling a job from a request, this context is already
deducted from the request and added to the scheduled job.
@@ -128,7 +127,7 @@ blocks:
## Arguments logging
-As of GitLab 13.6, Sidekiq job arguments are logged by default, unless [`SIDEKIQ_LOG_ARGUMENTS`](../../administration/troubleshooting/sidekiq.md#log-arguments-to-sidekiq-jobs)
+As of GitLab 13.6, Sidekiq job arguments are logged by default, unless [`SIDEKIQ_LOG_ARGUMENTS`](../../administration/sidekiq/sidekiq_troubleshooting.md#log-arguments-to-sidekiq-jobs)
is disabled.
By default, the only arguments logged are numeric arguments, because
diff --git a/doc/development/sidekiq/worker_attributes.md b/doc/development/sidekiq/worker_attributes.md
index 6820627f761..a1d24d0c392 100644
--- a/doc/development/sidekiq/worker_attributes.md
+++ b/doc/development/sidekiq/worker_attributes.md
@@ -86,13 +86,11 @@ but that always reduces work.
To do this, we want to calculate the expected increase in total execution time
and RPS (throughput) for the new shard. We can get these values from:
-- The [Queue Detail
- dashboard](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)
+- The [Queue Detail dashboard](https://dashboards.gitlab.net/d/sidekiq-queue-detail/sidekiq-queue-detail)
has values for the queue itself. For a new queue, we can look for
queues that have similar patterns or are scheduled in similar
circumstances.
-- The [Shard Detail
- dashboard](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)
+- The [Shard Detail dashboard](https://dashboards.gitlab.net/d/sidekiq-shard-detail/sidekiq-shard-detail)
has Total Execution Time and Throughput (RPS). The Shard Utilization
panel displays if there is currently any excess capacity for this
shard.
diff --git a/doc/development/single_table_inheritance.md b/doc/development/single_table_inheritance.md
index c8d082e8a67..da8d48f2a42 100644
--- a/doc/development/single_table_inheritance.md
+++ b/doc/development/single_table_inheritance.md
@@ -1,63 +1,11 @@
---
-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
+redirect_to: 'database/single_table_inheritance.md'
+remove_date: '2022-11-06'
---
-# Single Table Inheritance
+This document was moved to [another location](database/single_table_inheritance.md).
-**Summary:** don't use Single Table Inheritance (STI), use separate tables
-instead.
-
-Rails makes it possible to have multiple models stored in the same table and map
-these rows to the correct models using a `type` column. This can be used to for
-example store two different types of SSH keys in the same table.
-
-While tempting to use one should avoid this at all costs for the same reasons as
-outlined in the document ["Polymorphic Associations"](polymorphic_associations.md).
-
-## Solution
-
-The solution is very simple: just use a separate table for every type you'd
-otherwise store in the same table. For example, instead of having a `keys` table
-with `type` set to either `Key` or `DeployKey` you'd have two separate tables:
-`keys` and `deploy_keys`.
-
-## In migrations
-
-Whenever a model is used in a migration, single table inheritance should be disabled.
-Due to the way Rails loads associations (even in migrations), failing to disable STI
-could result in loading unexpected code or associations which may cause unintended
-side effects or failures during upgrades.
-
-```ruby
-class SomeMigration < Gitlab::Database::Migration[2.0]
- class Services < MigrationRecord
- self.table_name = 'services'
- self.inheritance_column = :_type_disabled
- end
-
- def up
- ...
-```
-
-If nothing needs to be added to the model other than disabling STI or `EachBatch`,
-use the helper `define_batchable_model` instead of defining the class.
-This ensures that the migration loads the columns for the migration in isolation,
-and the helper disables STI by default.
-
-```ruby
-class EnqueueSomeBackgroundMigration < Gitlab::Database::Migration[1.0]
- disable_ddl_transaction!
-
- def up
- define_batchable_model('services').select(:id).in_batches do |relation|
- jobs = relation.pluck(:id).map do |id|
- ['ExtractServicesUrl', [id]]
- end
-
- BackgroundMigrationWorker.bulk_perform_async(jobs)
- end
- end
- ...
-```
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/snowplow/implementation.md b/doc/development/snowplow/implementation.md
index f8e37aee1e0..9a923b115a2 100644
--- a/doc/development/snowplow/implementation.md
+++ b/doc/development/snowplow/implementation.md
@@ -431,7 +431,7 @@ To test backend Snowplow events, use the `expect_snowplow_event` helper. For mor
### Performance
-We use the [AsyncEmitter](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/ruby-tracker/emitters/#the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
+We use the [AsyncEmitter](https://snowplow.github.io/snowplow-ruby-tracker/SnowplowTracker/AsyncEmitter.html) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development.
## Develop and test Snowplow
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index 155ce87b8d9..24cd9093267 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -89,10 +89,10 @@ 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. |
+| 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`. |
-| label | text | false | The specific element or object to act on. This can be one of the following: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or the name or title attribute of a record being created. |
-| property | text | false | Any additional property of the element, or object being acted on. |
+| 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. |
### Examples
@@ -106,6 +106,7 @@ Each click event provides attributes that describe the event.
| `[projects:blob:show]` | `congratulate_first_pipeline` | `click_button` | `[human_access]` | - |
| `[projects:clusters:new]` | `chart_options` | `generate_link` | `[chart_link]` | - |
| `[projects:clusters:new]` | `chart_options` | `click_add_label_button` | `[label_id]` | - |
+| `API::NpmPackages` | `counts.package_events_i_package_push_package_by_deploy_token` | `push_package` | `npm` | - |
_* If you choose to omit the category you can use the default._<br>
_** Use property for variable strings._
diff --git a/doc/development/snowplow/infrastructure.md b/doc/development/snowplow/infrastructure.md
index 758c850e89f..ea4653dc91d 100644
--- a/doc/development/snowplow/infrastructure.md
+++ b/doc/development/snowplow/infrastructure.md
@@ -50,7 +50,7 @@ See [Snowplow technology 101](https://github.com/snowplow/snowplow/#snowplow-tec
### Pseudonymization
-In contrast to a typical Snowplow pipeline, after enrichment, GitLab Snowplow events go through a [pseudonymization service](https://gitlab.com/gitlab-org/growth/product-intelligence/snowplow-pseudonymization) in the form of an AWS Lambda service before they are stored in S3 storage.
+In contrast to a typical Snowplow pipeline, after enrichment, GitLab Snowplow events go through a [pseudonymization service](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/snowplow-pseudonymization) in the form of an AWS Lambda service before they are stored in S3 storage.
#### Why events need to be pseudonymized
@@ -85,7 +85,7 @@ There are several tools that monitor Snowplow events tracking in different stage
- The number of events that successfully reach Snowplow collectors.
- The number of events that failed to reach Snowplow collectors.
- The number of backend events that were sent.
-- [AWS CloudWatch dashboard](https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#dashboards:name=SnowPlow;start=P3D) monitors the state of the events in a processing pipeline. The pipeline starts from Snowplow collectors, goes through to enrichers and pseudonymization, and then up to persistence in an S3 bucket. From S3, the events are imported into the Snowflake Data Warehouse. You must have AWS access rights to view this dashboard. For more information, see [monitoring](https://gitlab.com/gitlab-org/growth/product-intelligence/snowplow-pseudonymization#monitoring) in the Snowplow Events pseudonymization service documentation.
+- [AWS CloudWatch dashboard](https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#dashboards:name=SnowPlow;start=P3D) monitors the state of the events in a processing pipeline. The pipeline starts from Snowplow collectors, goes through to enrichers and pseudonymization, and then up to persistence in an S3 bucket. From S3, the events are imported into the Snowflake Data Warehouse. You must have AWS access rights to view this dashboard. For more information, see [monitoring](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/snowplow-pseudonymization#monitoring) in the Snowplow Events pseudonymization service documentation.
- [Sisense dashboard](https://app.periscopedata.com/app/gitlab/417669/Snowplow-Summary-Dashboard) provides information about the number of good and bad events imported into the Data Warehouse, in addition to the total number of imported Snowplow events.
For more information, see this [video walk-through](https://www.youtube.com/watch?v=NxPS0aKa_oU).
@@ -93,7 +93,7 @@ For more information, see this [video walk-through](https://www.youtube.com/watc
## Related topics
- [Snowplow technology 101](https://github.com/snowplow/snowplow/#snowplow-technology-101)
-- [Snowplow pseudonymization AWS Lambda project](https://gitlab.com/gitlab-org/growth/product-intelligence/snowplow-pseudonymization)
+- [Snowplow pseudonymization AWS Lambda project](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/snowplow-pseudonymization)
- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
- [Data Infrastructure](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/)
- [Snowplow architecture overview (internal)](https://www.youtube.com/watch?v=eVYJjzspsLU)
diff --git a/doc/development/snowplow/review_guidelines.md b/doc/development/snowplow/review_guidelines.md
index 673166452b7..44de849792c 100644
--- a/doc/development/snowplow/review_guidelines.md
+++ b/doc/development/snowplow/review_guidelines.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Snowplow review guidelines
This page includes introductory material for a
-[Product Intelligence](https://about.gitlab.com/handbook/engineering/development/growth/product-intelligence/)
+[Product Intelligence](https://about.gitlab.com/handbook/engineering/development/analytics/product-intelligence/)
review, and is specific to Snowplow related reviews. For broader advice and
general best practices for code reviews, refer to our [code review guide](../code_review.md).
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 8553e2a5500..7101bf7fb4b 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -79,8 +79,9 @@ ON table_name
USING GIN(column_name gin_trgm_ops);
```
-The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a [GIN
-index](https://www.postgresql.org/docs/current/gin.html) with the operator class set to `gin_trgm_ops`. These indexes
+The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a
+[GIN index](https://www.postgresql.org/docs/current/gin.html)
+with the operator class set to `gin_trgm_ops`. These indexes
_can_ be used by `ILIKE` / `LIKE` and can lead to greatly improved performance.
One downside of these indexes is that they can easily get quite large (depending
on the amount of data indexed).
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 c1831cfce69..c8c18b93a8f 100644
--- a/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
+++ b/doc/development/stage_group_observability/dashboards/stage_group_dashboard.md
@@ -56,7 +56,7 @@ description, note the following:
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](https://grafana.com/docs/grafana/latest/panels/inspect-panel/).
+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.
Grafana consumes the data returned from queries to backend Prometheus data source, then presents it
diff --git a/doc/development/swapping_tables.md b/doc/development/swapping_tables.md
index efb481ccf35..eaa6568dc36 100644
--- a/doc/development/swapping_tables.md
+++ b/doc/development/swapping_tables.md
@@ -1,51 +1,11 @@
---
-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
+redirect_to: 'database/swapping_tables.md'
+remove_date: '2022-11-04'
---
-# Swapping Tables
+This document was moved to [another location](database/swapping_tables.md).
-Sometimes you need to replace one table with another. For example, when
-migrating data in a very large table it's often better to create a copy of the
-table and insert & migrate the data into this new table in the background.
-
-Let's say you want to swap the table `events` with `events_for_migration`. In
-this case you need to follow 3 steps:
-
-1. Rename `events` to `events_temporary`
-1. Rename `events_for_migration` to `events`
-1. Rename `events_temporary` to `events_for_migration`
-
-Rails allows you to do this using the `rename_table` method:
-
-```ruby
-rename_table :events, :events_temporary
-rename_table :events_for_migration, :events
-rename_table :events_temporary, :events_for_migration
-```
-
-This does not require any downtime as long as the 3 `rename_table` calls are
-executed in the _same_ database transaction. Rails by default uses database
-transactions for migrations, but if it doesn't you need to start one
-manually:
-
-```ruby
-Event.transaction do
- rename_table :events, :events_temporary
- rename_table :events_for_migration, :events
- rename_table :events_temporary, :events_for_migration
-end
-```
-
-Once swapped you _have to_ reset the primary key of the new table. For
-PostgreSQL you can use the `reset_pk_sequence!` method like so:
-
-```ruby
-reset_pk_sequence!('events')
-```
-
-Failure to reset the primary keys results in newly created rows starting
-with an ID value of 1. Depending on the existing data this can then lead to
-duplicate key constraints from popping up, preventing users from creating new
-data.
+<!-- This redirect file can be deleted after <2022-11-04>. -->
+<!-- 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/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index ea36214f6b7..79a72981e3f 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -422,8 +422,8 @@ Use the coverage reports to ensure your tests cover 100% of your code.
### System / Feature tests
NOTE:
-Before writing a new system test, [please consider **not**
-writing one](testing_levels.md#consider-not-writing-a-system-test)!
+Before writing a new system test,
+[please consider **not** writing one](testing_levels.md#consider-not-writing-a-system-test)!
- Feature specs should be named `ROLE_ACTION_spec.rb`, such as
`user_changes_password_spec.rb`.
@@ -909,8 +909,8 @@ By default, Sidekiq jobs are enqueued into a jobs array and aren't processed.
If a test queues Sidekiq jobs and need them to be processed, the
`:sidekiq_inline` trait can be used.
-The `:sidekiq_might_not_need_inline` trait was added when [Sidekiq inline mode was
-changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479)
+The `:sidekiq_might_not_need_inline` trait was added when
+[Sidekiq inline mode was changed to fake mode](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15479)
to all the tests that needed Sidekiq to actually process jobs. Tests with
this trait should be either fixed to not rely on Sidekiq processing jobs, or their
`:sidekiq_might_not_need_inline` trait should be updated to `:sidekiq_inline` if
@@ -1239,8 +1239,7 @@ The `match_schema` matcher allows validating that the subject matches a
a JSON string or a JSON-compatible data structure.
`match_response_schema` is a convenience matcher for using with a
-response object. from a [request
-spec](testing_levels.md#integration-tests).
+response object. from a [request spec](testing_levels.md#integration-tests).
Examples:
diff --git a/doc/development/testing_guide/contract/consumer_tests.md b/doc/development/testing_guide/contract/consumer_tests.md
index df7c9ee0abd..46f4f446ad9 100644
--- a/doc/development/testing_guide/contract/consumer_tests.md
+++ b/doc/development/testing_guide/contract/consumer_tests.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Writing consumer tests
-This tutorial guides you through writing a consumer test from scratch. To start, the consumer tests are written using [`jest-pact`](https://github.com/pact-foundation/jest-pact) that builds on top of [`pact-js`](https://github.com/pact-foundation/pact-js). This tutorial shows you how to write a consumer test for the `/discussions.json` endpoint, which is actually `/:namespace_name/:project_name/-/merge_requests/:id/discussions.json`.
+This tutorial guides you through writing a consumer test from scratch. To start, the consumer tests are written using [`jest-pact`](https://github.com/pact-foundation/jest-pact) that builds on top of [`pact-js`](https://github.com/pact-foundation/pact-js). This tutorial shows you how to write a consumer test for the `/discussions.json` REST API endpoint, which is actually `/:namespace_name/:project_name/-/merge_requests/:id/discussions.json`. For an example of a GraphQL consumer test, see [`spec/contracts/consumer/specs/project/pipeline/show.spec.js`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/spec/contracts/consumer/specs/project/pipeline/show.spec.js).
## Create the skeleton
@@ -24,7 +24,7 @@ To learn more about how the contract test directory is structured, see the contr
The Pact consumer test is defined through the `pactWith` function that takes `PactOptions` and the `PactFn`.
```javascript
-const { pactWith } = require('jest-pact');
+import { pactWith } from 'jest-pact';
pactWith(PactOptions, PactFn);
```
@@ -34,7 +34,7 @@ pactWith(PactOptions, PactFn);
`PactOptions` with `jest-pact` introduces [additional options](https://github.com/pact-foundation/jest-pact/blob/dce370c1ab4b7cb5dff12c4b62246dc229c53d0e/README.md#defaults) that build on top of the ones [provided in `pact-js`](https://github.com/pact-foundation/pact-js#constructor). In most cases, you define the `consumer`, `provider`, `log`, and `dir` options for these tests.
```javascript
-const { pactWith } = require('jest-pact');
+import { pactWith } from 'jest-pact';
pactWith(
{
@@ -54,7 +54,7 @@ To learn more about how to name the consumers and providers, see contract testin
The `PactFn` is where your tests are defined. This is where you set up the mock provider and where you can use the standard Jest methods like [`Jest.describe`](https://jestjs.io/docs/api#describename-fn), [`Jest.beforeEach`](https://jestjs.io/docs/api#beforeeachfn-timeout), and [`Jest.it`](https://jestjs.io/docs/api#testname-fn-timeout). For more information, see [https://jestjs.io/docs/api](https://jestjs.io/docs/api).
```javascript
-const { pactWith } = require('jest-pact');
+import { pactWith } from 'jest-pact';
pactWith(
{
@@ -70,7 +70,7 @@ pactWith(
});
- it('return a successful body', () => {
+ it('return a successful body', async () => {
});
});
@@ -92,8 +92,8 @@ For this tutorial, define four attributes for the `Interaction`:
After you define the `Interaction`, add that interaction to the mock provider by calling `addInteraction`.
```javascript
-const { pactWith } = require('jest-pact');
-const { Matchers } = require('@pact-foundation/pact');
+import { pactWith } from 'jest-pact';
+import { Matchers } from '@pact-foundation/pact';
pactWith(
{
@@ -132,7 +132,7 @@ pactWith(
provider.addInteraction(interaction);
});
- it('return a successful body', () => {
+ it('return a successful body', async () => {
});
});
@@ -142,38 +142,36 @@ pactWith(
### Response body `Matchers`
-Notice how we use `Matchers` in the `body` of the expected response. This allows us to be flexible enough to accept different values but still be strict enough to distinguish between valid and invalid values. We must ensure that we have a tight definition that is neither too strict nor too lax. Read more about the [different types of `Matchers`](https://github.com/pact-foundation/pact-js#using-the-v3-matching-rules).
+Notice how we use `Matchers` in the `body` of the expected response. This allows us to be flexible enough to accept different values but still be strict enough to distinguish between valid and invalid values. We must ensure that we have a tight definition that is neither too strict nor too lax. Read more about the [different types of `Matchers`](https://github.com/pact-foundation/pact-js/blob/master/docs/matching.md). We are currently using the V2 matching rules.
## Write the test
After the mock provider is set up, you can write the test. For this test, you make a request and expect a particular response.
-First, set up the client that makes the API request. To do that, create `spec/contracts/consumer/endpoints/project/merge_requests.js` and add the following API request.
+First, set up the client that makes the API request. To do that, create `spec/contracts/consumer/resources/api/project/merge_requests.js` and add the following API request. If the endpoint is a GraphQL, then we create it under `spec/contracts/consumer/resources/graphql` instead.
```javascript
-const axios = require('axios');
-
-exports.getDiscussions = (endpoint) => {
- const url = endpoint.url;
-
- return axios
- .request({
- method: 'GET',
- baseURL: url,
- url: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
- headers: { Accept: '*/*' },
- })
- .then((response) => response.data);
-};
+import axios from 'axios';
+
+export async function getDiscussions(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'GET',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
+ headers: { Accept: '*/*' },
+ })
+}
```
After that's set up, import it to the test file and call it to make the request. Then, you can make the request and define your expectations.
```javascript
-const { pactWith } = require('jest-pact');
-const { Matchers } = require('@pact-foundation/pact');
+import { pactWith } from 'jest-pact';
+import { Matchers } from '@pact-foundation/pact';
-const { getDiscussions } = require('../endpoints/project/merge_requests');
+import { getDiscussions } from '../../../resources/api/project/merge_requests';
pactWith(
{
@@ -211,17 +209,17 @@ pactWith(
};
});
- it('return a successful body', () => {
- return getDiscussions({
+ it('return a successful body', async () => {
+ const discussions = await getDiscussions({
url: provider.mockService.baseUrl,
- }).then((discussions) => {
- expect(discussions).toEqual(Matchers.eachLike({
- id: 'fd73763cbcbf7b29eb8765d969a38f7d735e222a',
- project_id: 6954442,
- ...
- resolved: true
- }));
});
+
+ expect(discussions).toEqual(Matchers.eachLike({
+ id: 'fd73763cbcbf7b29eb8765d969a38f7d735e222a',
+ project_id: 6954442,
+ ...
+ resolved: true
+ }));
});
});
},
@@ -237,7 +235,7 @@ As you may have noticed, the request and response definitions can get large. Thi
Create a file under `spec/contracts/consumer/fixtures/project/merge_request` called `discussions.fixture.js` where you will place the `request` and `response` definitions.
```javascript
-const { Matchers } = require('@pact-foundation/pact');
+import { Matchers } from '@pact-foundation/pact';
const body = Matchers.eachLike({
id: Matchers.string('fd73763cbcbf7b29eb8765d969a38f7d735e222a'),
@@ -254,11 +252,15 @@ const Discussions = {
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
- body: body,
+ body,
},
- request: {
+ scenario: {
+ state: 'a merge request with discussions exists',
uponReceiving: 'a request for discussions',
+ },
+
+ request: {
withRequest: {
method: 'GET',
path: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
@@ -275,36 +277,41 @@ exports.Discussions = Discussions;
With all of that moved to the `fixture`, you can simplify the test to the following:
```javascript
-const { pactWith } = require('jest-pact');
+import { pactWith } from 'jest-pact';
+
+import { Discussions } from '../../../fixtures/project/merge_request/discussions.fixture';
+import { getDiscussions } from '../../../resources/api/project/merge_requests';
-const { Discussions } = require('../fixtures/discussions.fixture');
-const { getDiscussions } = require('../endpoints/project/merge_requests');
+const CONSUMER_NAME = 'MergeRequest#show';
+const PROVIDER_NAME = 'Merge Request Discussions Endpoint';
+const CONSUMER_LOG = '../logs/consumer.log';
+const CONTRACT_DIR = '../contracts/project/merge_request/show';
pactWith(
{
- consumer: 'MergeRequest#show',
- provider: 'Merge Request Discussions Endpoint',
- log: '../logs/consumer.log',
- dir: '../contracts/project/merge_request/show',
+ consumer: CONSUMER_NAME,
+ provider: PROVIDER_NAME,
+ log: CONSUMER_LOG,
+ dir: CONTRACT_DIR,
},
(provider) => {
- describe('Merge Request Discussions Endpoint', () => {
+ describe(PROVIDER_NAME, () => {
beforeEach(() => {
const interaction = {
- state: 'a merge request with discussions exists',
+ ...Discussions.scenario,
...Discussions.request,
willRespondWith: Discussions.success,
};
- return provider.addInteraction(interaction);
+ provider.addInteraction(interaction);
});
- it('return a successful body', () => {
- return getDiscussions({
+ it('return a successful body', async () => {
+ const discussions = await getDiscussions({
url: provider.mockService.baseUrl,
- }).then((discussions) => {
- expect(discussions).toEqual(Discussions.body);
});
+
+ expect(discussions).toEqual(Discussions.body);
});
});
},
diff --git a/doc/development/testing_guide/contract/index.md b/doc/development/testing_guide/contract/index.md
index 8e12eea2874..30a4adaca44 100644
--- a/doc/development/testing_guide/contract/index.md
+++ b/doc/development/testing_guide/contract/index.md
@@ -28,14 +28,14 @@ Before running the consumer tests, go to `spec/contracts/consumer` and run `npm
### Run the provider tests
-Before running the provider tests, make sure your GDK (GitLab Development Kit) is fully set up and running. You can follow the setup instructions detailed in the [GDK repository](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main). To run the provider tests, you use Rake tasks that are defined in [`./lib/tasks/contracts.rake`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/tasks/contracts.rake). To get a list of all the Rake tasks related to the provider tests, run `bundle exec rake -T contracts`. For example:
+Before running the provider tests, make sure your GDK (GitLab Development Kit) is fully set up and running. You can follow the setup instructions detailed in the [GDK repository](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main). To run the provider tests, you use Rake tasks that can be found in [`./lib/tasks/contracts`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/tasks/contracts). To get a list of all the Rake tasks related to the provider tests, run `bundle exec rake -T contracts`. For example:
```shell
$ bundle exec rake -T contracts
-rake contracts:mr:pact:verify:diffs # Verify provider against the consumer pacts for diffs
-rake contracts:mr:pact:verify:discussions # Verify provider against the consumer pacts for discussions
-rake contracts:mr:pact:verify:metadata # Verify provider against the consumer pacts for metadata
-rake contracts:mr:test:merge_request[contract_mr] # Run all merge request contract tests
+rake contracts:merge_requests:pact:verify:diffs_batch # Verify provider against the consumer pacts for diffs_batch
+rake contracts:merge_requests:pact:verify:diffs_metadata # Verify provider against the consumer pacts for diffs_metadata
+rake contracts:merge_requests:pact:verify:discussions # Verify provider against the consumer pacts for discussions
+rake contracts:merge_requests:test:merge_requests[contract_merge_requests] # Run all merge request contract tests
```
## Test suite folder structure and naming conventions
@@ -50,11 +50,11 @@ Having an organized and sensible folder structure for the test suite makes it ea
The consumer tests are grouped according to the different pages in the application. Each file contains various types of requests found in a page. As such, the consumer test files are named using the Rails standards of how pages are referenced. For example, the project pipelines page would be the `Project::Pipeline#index` page so the equivalent consumer test would be located in `consumer/specs/project/pipelines/index.spec.js`.
-When defining the location to output the contract generated by the test, we want to follow the same file structure which would be `contracts/project/pipelines/` for this example. This is the structure in `consumer/endpoints` and `consumer/fixtures` as well.
+When defining the location to output the contract generated by the test, we want to follow the same file structure which would be `contracts/project/pipelines/` for this example. This is the structure in `consumer/resources` and `consumer/fixtures` as well.
#### Provider tests
-The provider tests are grouped similarly to our controllers. Each of these tests contains various tests for an API endpoint. For example, the API endpoint to get a list of pipelines for a project would be located in `provider/pact_helpers/project/pipelines/get_list_project_pipelines_helper.rb`. The provider states are structured the same way.
+The provider tests are grouped similarly to our controllers. Each of these tests contains various tests for an API endpoint. For example, the API endpoint to get a list of pipelines for a project would be located in `provider/pact_helpers/project/pipelines/get_list_project_pipelines_helper.rb`. The provider states are grouped according to the different pages in the application similar to the consumer tests.
### Naming conventions
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 00b843ffdbe..bfda94b1f1d 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -415,8 +415,8 @@ except(page).to have_no_text('hidden')
Unfortunately, that's not automatically the case for the predicate methods that we add to our
[page objects](page_objects.md). We need to [create our own negatable matchers](https://relishapp.com/rspec/rspec-expectations/v/3-9/docs/custom-matchers/define-a-custom-matcher#matcher-with-separate-logic-for-expect().to-and-expect().not-to).
-The initial example uses the `have_job` matcher which is derived from the [`has_job?` predicate
-method of the `Page::Project::Pipeline::Show` page object](https://gitlab.com/gitlab-org/gitlab/-/blob/87864b3047c23b4308f59c27a3757045944af447/qa/qa/page/project/pipeline/show.rb#L53).
+The initial example uses the `have_job` matcher which is derived from the
+[`has_job?` predicate method of the `Page::Project::Pipeline::Show` page object](https://gitlab.com/gitlab-org/gitlab/-/blob/87864b3047c23b4308f59c27a3757045944af447/qa/qa/page/project/pipeline/show.rb#L53).
To create a negatable matcher, we use `has_no_job?` for the negative case:
```ruby
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 cb4c8e8a6e8..33f73304a26 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -217,8 +217,8 @@ If enabling the feature flag results in E2E test failures, you can browse the ar
If an end-to-end test enables a feature flag, the end-to-end test suite can be used to test changes in a merge request
by running the `package-and-qa` job in the merge request pipeline. If the feature flag and relevant changes have already been merged, you can confirm that the tests
-pass on the default branch. The end-to-end tests run on the default branch every two hours, and the results are posted to a [Test
-Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amain).
+pass on the default branch. The end-to-end tests run on the default branch every two hours, and the results are posted to a
+[Test Session Report, which is available in the testcase-sessions project](https://gitlab.com/gitlab-org/quality/testcase-sessions/-/issues?label_name%5B%5D=found%3Amain).
If the relevant tests do not enable the feature flag themselves, you can check if the tests will need to be updated by opening
a draft merge request that enables the flag by default via a [feature flag definition file](../../feature_flags/index.md#feature-flag-definition-and-validation).
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index 06359d612ad..989d090d581 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -140,8 +140,8 @@ 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,
-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)
+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:
| Variable | Description |
@@ -150,8 +150,9 @@ as well as these:
| `QA_TESTS` | The tests to run (no default, which means run all the tests in the scenario). Use file paths as you would when running tests via RSpec, for example, `qa/specs/features/ee/browser_ui` would include all the `EE` UI tests. |
| `QA_RSPEC_TAGS` | The RSpec tags to add (no default) |
-For now, [manual jobs with custom variables don't use the same variable
-when retried](https://gitlab.com/gitlab-org/gitlab/-/issues/31367), so if you want to run the same tests multiple times,
+For now,
+[manual jobs with custom variables don't use the same variable when retried](https://gitlab.com/gitlab-org/gitlab/-/issues/31367),
+so if you want to run the same tests multiple times,
specify the same variables in each `custom-parallel` job (up to as
many of the 10 available jobs that you want to run).
@@ -164,8 +165,8 @@ automatically started: it runs the QA smoke suite against the
You can also manually start the `review-qa-all`: it runs the full QA suite
against the [Review App](../review_apps.md).
-**This runs end-to-end tests against a Review App based on [the official GitLab
-Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/), itself deployed with custom
+**This runs end-to-end tests against a Review App based on
+[the official GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/), itself deployed with custom
[Cloud Native components](https://gitlab.com/gitlab-org/build/CNG) built from your merge request's changes.**
See [Review Apps](../review_apps.md) for more details about Review Apps.
@@ -235,7 +236,7 @@ Each type of scheduled pipeline generates a static link for the latest test repo
- [`staging-sanity`](https://storage.googleapis.com/gitlab-qa-allure-reports/staging-sanity/master/index.html)
- [`staging-sanity-no-admin`](https://storage.googleapis.com/gitlab-qa-allure-reports/staging-sanity-no-admin/master/index.html)
- [`canary-sanity`](https://storage.googleapis.com/gitlab-qa-allure-reports/canary-sanity/master/index.html)
-- [`production`](https://storage.googleapis.com/gitlab-qa-allure-reports/production/master/index.html)
+- [`production`](https://storage.googleapis.com/gitlab-qa-allure-reports/production-full/master/index.html)
- [`production-sanity`](https://storage.googleapis.com/gitlab-qa-allure-reports/production-sanity/master/index.html)
## How do I run the tests?
@@ -243,8 +244,8 @@ Each type of scheduled pipeline generates a static link for the latest test repo
If you are not [testing code in a merge request](#testing-code-in-merge-requests),
there are two main options for running the tests. If you want to run
the existing tests against a live GitLab instance or against a pre-built Docker image,
-use the [GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md). See also [examples
-of the test scenarios you can run via the orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#examples).
+use the [GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md). See also
+[examples of the test scenarios you can run via the orchestrator](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#examples).
On the other hand, if you would like to run against a local development GitLab
environment, you can use the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/).
@@ -262,8 +263,8 @@ architecture. See the [documentation about it](https://gitlab.com/gitlab-org/git
Once you decided where to put [test environment orchestration scenarios](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario) and
[instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features), take a look at the [GitLab QA README](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa/README.md),
-the [GitLab QA orchestrator README](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md), and [the already existing
-instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features).
+the [GitLab QA orchestrator README](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md),
+and [the already existing instance-level scenarios](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/qa/qa/specs/features).
### Consider **not** writing an end-to-end test
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 591d03db7b8..322f2412e5b 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
@@ -30,6 +30,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:ldap_no_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS not enabled. |
| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
+| `:metrics` | The test requires a GitLab instance where [dedicated metrics exporters](../../../administration/monitoring/prometheus/web_exporter.md) are running alongside Puma and Sidekiq. |
| `:mixed_env` | The test should only be executed in environments that have a paired canary version available through traffic routing based on the existence of the `gitlab_canary=true` cookie. Tests in this category are switching the cookie mid-test to validate mixed deployment environments. |
| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
| `:only` | The test is only to be run in specific execution contexts. See [test execution context selection](execution_context_selection.md) for more information. |
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 438294161ac..322f108783f 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
@@ -8,11 +8,20 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Jenkins spec
-The [`jenkins_build_status_spec`](https://gitlab.com/gitlab-org/gitlab/-/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb) spins up a Jenkins instance in a Docker container based on an image stored in the [GitLab-QA container registry](https://gitlab.com/gitlab-org/gitlab-qa/container_registry).
-The Docker image it uses is preconfigured with some base data and plugins.
-The test then configures the GitLab plugin in Jenkins with a URL of the GitLab instance that are used
-to run the tests. Unfortunately, the GitLab Jenkins plugin does not accept ports so `http://localhost:3000` would
-not be accepted. Therefore, this requires us to run GitLab on port 80 or inside a Docker container.
+The [`jenkins_build_status_spec`](https://gitlab.com/gitlab-org/gitlab/-/blob/24a86debf49f3aed6f2ecfd6e8f9233b3a214181/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb)
+spins up a Jenkins instance in a Docker container with the Jenkins GitLab plugin pre-installed. Due to a license restriction we are unable to distribute this image.
+To build a QA compatible image, please visit the [third party images project](https://gitlab.com/gitlab-org/quality/third-party-docker-public), where third party Dockerfiles can be found.
+The project also has instructions for forking and building the images automatically in CI.
+
+Some extra environment variables for the location of the forked repository are also needed.
+
+- `QA_THIRD_PARTY_DOCKER_REGISTRY` (the container registry where the repository/images are hosted, eg `registry.gitlab.com`)
+- `QA_THIRD_PARTY_DOCKER_REPOSITORY` (the base repository path where the images are hosted, eg `registry.gitlab.com/<project path>`)
+- `QA_THIRD_PARTY_DOCKER_USER` (a username that has access to the container registry for this repository)
+- `QA_THIRD_PARTY_DOCKER_PASSWORD` (a password/token for the username to authenticate with)
+
+The test configures the GitLab plugin in Jenkins with a URL of the GitLab instance that are used
+to run the tests. Bi-directional networking is needed between a GitLab instance and Jenkins, so GitLab can also be started in a Docker container.
To start a Docker container for GitLab based on the nightly image:
@@ -21,34 +30,25 @@ docker run \
--publish 80:80 \
--name gitlab \
--hostname localhost \
+ --network test
gitlab/gitlab-ee:nightly
```
To run the tests from the `/qa` directory:
```shell
-WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost -- qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
+export QA_THIRD_PARTY_DOCKER_REGISTRY=<registry>
+export QA_THIRD_PARTY_DOCKER_REPOSITORY=<repository>
+export QA_THIRD_PARTY_DOCKER_USER=<user with registry access>
+export QA_THIRD_PARTY_DOCKER_PASSWORD=<password for user>
+export WEBDRIVER_HEADLESS=0
+bin/qa Test::Instance::All http://localhost -- qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
```
The test automatically spins up a Docker container for Jenkins and tear down once the test completes.
-However, if you need to run Jenkins manually outside of the tests, use this command:
-
-```shell
-docker run \
- --hostname localhost \
- --name jenkins-server \
- --env JENKINS_HOME=jenkins_home \
- --publish 8080:8080 \
- registry.gitlab.com/gitlab-org/gitlab-qa/jenkins-gitlab:version1
-```
-
-Jenkins is available on `http://localhost:8080`.
-
-Administrator username is `admin` and password is `password`.
-
-It is worth noting that this is not an orchestrated test. It is [tagged with the `:orchestrated` meta](https://gitlab.com/gitlab-org/gitlab/-/blob/163c8a8c814db26d11e104d1cb2dcf02eb567dbe/qa/qa/specs/features/ee/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb#L5)
-only to prevent it from running in the pipelines for live environments such as Staging.
+If you need to run Jenkins manually outside of the tests, please refer to the README for the
+[third party images project](https://gitlab.com/gitlab-org/quality/third-party-docker-public/-/blob/main/jenkins/README.md)
### Troubleshooting
@@ -385,6 +385,43 @@ To run the LDAP tests on your local with TLS disabled, follow these steps:
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_LOG_LEVEL=debug WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
```
+## SMTP tests
+
+Tests that are tagged with `:smtp` meta tag are orchestrated tests that ensure email notifications are received by a user.
+
+These tests require a GitLab instance with SMTP enabled and integrated with an SMTP server, [MailHog](https://github.com/mailhog/MailHog).
+
+To run these tests locally against the GDK:
+
+1. Add these settings to your `gitlab.yml` file:
+
+ ```yaml
+ smtp:
+ enabled: true
+ address: "mailhog.test"
+ port: 1025
+ ```
+
+1. Start MailHog in a Docker container:
+
+ ```shell
+ docker network create test && docker run \
+ --network test \
+ --hostname mailhog.test \
+ --name mailhog \
+ --publish 1025:1025 \
+ --publish 8025:8025 \
+ mailhog/mailhog:v1.0.0
+ ```
+
+1. Run the test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory:
+
+ ```shell
+ QA_LOG_LEVEL=debug WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost:3000 qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb -- --tag orchestrated
+ ```
+
+For instructions on how to run these tests using the `gitlab-qa` gem, please refer to [the GitLab QA documentation](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#testintegrationsmtp-ceeefull-image-address).
+
## Guide to the mobile suite
### What are mobile tests
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index d91c53823e2..2845dde9a24 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -51,15 +51,12 @@ The default timeout for Jest is set in
If your test exceeds that time, it fails.
If you cannot improve the performance of the tests, you can increase the timeout
-for a specific test using
-[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__/timeout.js).
+for a specific test using [`jest.setTimeout`](https://jestjs.io/docs/27.x/jest-object#jestsettimeouttimeout)
```javascript
-import { setTestTimeout } from 'helpers/timeout';
-
describe('Component', () => {
it('does something amazing', () => {
- setTestTimeout(500);
+ jest.setTimeout(500);
// ...
});
});
@@ -466,7 +463,7 @@ it('waits for an Ajax call', () => {
#### Vue rendering
-Use [`nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) to wait until a Vue component is
+Use [`nextTick()`](https://v2.vuejs.org/v2/api/#Vue-nextTick) to wait until a Vue component is
re-rendered.
**in Jest:**
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index fa9f1f1ac3e..cd7c70e2eaa 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -9,8 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
This document describes various guidelines and best practices for automated
testing of the GitLab project.
-It is meant to be an _extension_ of the [Thoughtbot testing
-style guide](https://github.com/thoughtbot/guides/tree/master/testing-rspec). If
+It is meant to be an _extension_ of the
+[Thoughtbot testing style guide](https://github.com/thoughtbot/guides/tree/master/testing-rspec). If
this guide defines a rule that contradicts the Thoughtbot guide, this guide
takes precedence. Some guidelines may be repeated verbatim to stress their
importance.
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 532bb9fcdef..b272d23522e 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -25,7 +25,7 @@ For any of the following scenarios, the `start-review-app-pipeline` job would be
On every [pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730) in the `qa` stage (which comes after the
`review` stage), the `review-qa-smoke` and `review-qa-reliable` jobs are automatically started. The `review-qa-smoke` runs
-the QA smoke suite and the `review-qa-reliable` executes E2E tests identified as [reliable](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/reliable-tests).
+the QA smoke suite and the `review-qa-reliable` executes E2E tests identified as [reliable](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/reliable-tests/).
`review-qa-*` jobs ensure that end-to-end tests for the changes in the merge request pass in a live environment. This shifts the identification of e2e failures from an environment on the path to production to the merge request, to prevent breaking features on GitLab.com or costly GitLab.com deployment blockers. `review-qa-*` failures should be investigated with counterpart SET involvement if needed to help determine the root cause of the error.
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 02f32a031dc..c1bf3609b53 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -115,7 +115,7 @@ graph RL
Testing the value of a constant means copying it, resulting in extra effort without additional confidence that the value is correct.
- **Vue components**:
Computed properties, methods, and lifecycle hooks can be considered an implementation detail of components, are implicitly covered by component tests, and don't need to be tested.
- For more information, see the [official Vue guidelines](https://vue-test-utils.vuejs.org/guides/#getting-started).
+ For more information, see the [official Vue guidelines](https://v1.test-utils.vuejs.org/guides/#getting-started).
#### What to mock in unit tests
@@ -208,7 +208,7 @@ graph RL
Similar to unit tests, background operations cannot be stopped or waited on. This means they continue running in the following tests and cause side effects.
- **Child components**:
Every component is tested individually, so child components are mocked.
- See also [`shallowMount()`](https://vue-test-utils.vuejs.org/api/#shallowmount)
+ See also [`shallowMount()`](https://v1.test-utils.vuejs.org/api/#shallowmount)
#### What *not* to mock in component tests
diff --git a/doc/development/testing_guide/testing_migrations_guide.md b/doc/development/testing_guide/testing_migrations_guide.md
index d71788e21f3..261a4f4a27e 100644
--- a/doc/development/testing_guide/testing_migrations_guide.md
+++ b/doc/development/testing_guide/testing_migrations_guide.md
@@ -317,8 +317,8 @@ To test these you usually have to:
- Verify that the expected jobs were scheduled, with the correct set
of records, the correct batch size, interval, etc.
-The behavior of the background migration itself needs to be verified in a [separate
-test for the background migration class](#example-background-migration-test).
+The behavior of the background migration itself needs to be verified in a
+[separate test for the background migration class](#example-background-migration-test).
This spec tests the
[`db/post_migrate/20210701111909_backfill_issues_upvotes_count.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/v14.1.0-ee/db/post_migrate/20210701111909_backfill_issues_upvotes_count.rb)
diff --git a/doc/development/understanding_explain_plans.md b/doc/development/understanding_explain_plans.md
index 17fcd5b3e88..72c3df11a96 100644
--- a/doc/development/understanding_explain_plans.md
+++ b/doc/development/understanding_explain_plans.md
@@ -1,829 +1,11 @@
---
-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
+redirect_to: 'database/understanding_explain_plans.md'
+remove_date: '2022-11-04'
---
-# Understanding EXPLAIN plans
+This document was moved to [another location](database/understanding_explain_plans.md).
-PostgreSQL allows you to obtain query plans using the `EXPLAIN` command. This
-command can be invaluable when trying to determine how a query performs.
-You can use this command directly in your SQL query, as long as the query starts
-with it:
-
-```sql
-EXPLAIN
-SELECT COUNT(*)
-FROM projects
-WHERE visibility_level IN (0, 20);
-```
-
-When running this on GitLab.com, we are presented with the following output:
-
-```sql
-Aggregate (cost=922411.76..922411.77 rows=1 width=8)
- -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
-```
-
-When using _just_ `EXPLAIN`, PostgreSQL does not actually execute our query,
-instead it produces an _estimated_ execution plan based on the available
-statistics. This means the actual plan can differ quite a bit. Fortunately,
-PostgreSQL provides us with the option to execute the query as well. To do so,
-we need to use `EXPLAIN ANALYZE` instead of just `EXPLAIN`:
-
-```sql
-EXPLAIN ANALYZE
-SELECT COUNT(*)
-FROM projects
-WHERE visibility_level IN (0, 20);
-```
-
-This produces:
-
-```sql
-Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
- -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 65677
-Planning time: 2.861 ms
-Execution time: 3428.596 ms
-```
-
-As we can see this plan is quite different, and includes a lot more data. Let's
-discuss this step by step.
-
-Because `EXPLAIN ANALYZE` executes the query, care should be taken when using a
-query that writes data or might time out. If the query modifies data,
-consider wrapping it in a transaction that rolls back automatically like so:
-
-```sql
-BEGIN;
-EXPLAIN ANALYZE
-DELETE FROM users WHERE id = 1;
-ROLLBACK;
-```
-
-The `EXPLAIN` command also takes additional options, such as `BUFFERS`:
-
-```sql
-EXPLAIN (ANALYZE, BUFFERS)
-SELECT COUNT(*)
-FROM projects
-WHERE visibility_level IN (0, 20);
-```
-
-This then produces:
-
-```sql
-Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
- Buffers: shared hit=208846
- -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 65677
- Buffers: shared hit=208846
-Planning time: 2.861 ms
-Execution time: 3428.596 ms
-```
-
-For more information, refer to the official
-[`EXPLAIN` documentation](https://www.postgresql.org/docs/current/sql-explain.html)
-and [using `EXPLAIN` guide](https://www.postgresql.org/docs/current/using-explain.html).
-
-## Nodes
-
-Every query plan consists of nodes. Nodes can be nested, and are executed from
-the inside out. This means that the innermost node is executed before an outer
-node. This can be best thought of as nested function calls, returning their
-results as they unwind. For example, a plan starting with an `Aggregate`
-followed by a `Nested Loop`, followed by an `Index Only scan` can be thought of
-as the following Ruby code:
-
-```ruby
-aggregate(
- nested_loop(
- index_only_scan()
- index_only_scan()
- )
-)
-```
-
-Nodes are indicated using a `->` followed by the type of node taken. For
-example:
-
-```sql
-Aggregate (cost=922411.76..922411.77 rows=1 width=8)
- -> Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
-```
-
-Here the first node executed is `Seq scan on projects`. The `Filter:` is an
-additional filter applied to the results of the node. A filter is very similar
-to Ruby's `Array#select`: it takes the input rows, applies the filter, and
-produces a new list of rows. After the node is done, we perform the `Aggregate`
-above it.
-
-Nested nodes look like this:
-
-```sql
-Aggregate (cost=176.97..176.98 rows=1 width=8) (actual time=0.252..0.252 rows=1 loops=1)
- Buffers: shared hit=155
- -> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1)
- Buffers: shared hit=155
- -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1)
- Index Cond: (id < 100)
- Heap Fetches: 0
- -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36)
- Index Cond: (id = users_1.id)
- Heap Fetches: 0
-Planning time: 2.585 ms
-Execution time: 0.310 ms
-```
-
-Here we first perform two separate "Index Only" scans, followed by performing a
-"Nested Loop" on the result of these two scans.
-
-## Node statistics
-
-Each node in a plan has a set of associated statistics, such as the cost, the
-number of rows produced, the number of loops performed, and more. For example:
-
-```sql
-Seq Scan on projects (cost=0.00..908044.47 rows=5746914 width=0)
-```
-
-Here we can see that our cost ranges from `0.00..908044.47` (we cover this in
-a moment), and we estimate (since we're using `EXPLAIN` and not `EXPLAIN
-ANALYZE`) a total of 5,746,914 rows to be produced by this node. The `width`
-statistics describes the estimated width of each row, in bytes.
-
-The `costs` field specifies how expensive a node was. The cost is measured in
-arbitrary units determined by the query planner's cost parameters. What
-influences the costs depends on a variety of settings, such as `seq_page_cost`,
-`cpu_tuple_cost`, and various others.
-The format of the costs field is as follows:
-
-```sql
-STARTUP COST..TOTAL COST
-```
-
-The startup cost states how expensive it was to start the node, with the total
-cost describing how expensive the entire node was. In general: the greater the
-values, the more expensive the node.
-
-When using `EXPLAIN ANALYZE`, these statistics also include the actual time
-(in milliseconds) spent, and other runtime statistics (for example, the actual number of
-produced rows):
-
-```sql
-Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
-```
-
-Here we can see we estimated 5,746,969 rows to be returned, but in reality we
-returned 5,746,940 rows. We can also see that _just_ this sequential scan took
-2.98 seconds to run.
-
-Using `EXPLAIN (ANALYZE, BUFFERS)` also gives us information about the
-number of rows removed by a filter, the number of buffers used, and more. For
-example:
-
-```sql
-Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 65677
- Buffers: shared hit=208846
-```
-
-Here we can see that our filter has to remove 65,677 rows, and that we use
-208,846 buffers. Each buffer in PostgreSQL is 8 KB (8192 bytes), meaning our
-above node uses *1.6 GB of buffers*. That's a lot!
-
-Keep in mind that some statistics are per-loop averages, while others are total values:
-
-| Field name | Value type |
-| --- | --- |
-| Actual Total Time | per-loop average |
-| Actual Rows | per-loop average |
-| Buffers Shared Hit | total value |
-| Buffers Shared Read | total value |
-| Buffers Shared Dirtied | total value |
-| Buffers Shared Written | total value |
-| I/O Read Time | total value |
-| I/O Read Write | total value |
-
-For example:
-
-```sql
- -> Index Scan using users_pkey on public.users (cost=0.43..3.44 rows=1 width=1318) (actual time=0.025..0.025 rows=1 loops=888)
- Index Cond: (users.id = issues.author_id)
- Buffers: shared hit=3543 read=9
- I/O Timings: read=17.760 write=0.000
-```
-
-Here we can see that this node used 3552 buffers (3543 + 9), returned 888 rows (`888 * 1`), and the actual duration was 22.2 milliseconds (`888 * 0.025`).
-17.76 milliseconds of the total duration was spent in reading from disk, to retrieve data that was not in the cache.
-
-## Node types
-
-There are quite a few different types of nodes, so we only cover some of the
-more common ones here.
-
-A full list of all the available nodes and their descriptions can be found in
-the [PostgreSQL source file `plannodes.h`](https://gitlab.com/postgres/postgres/blob/master/src/include/nodes/plannodes.h).
-pgMustard's [EXPLAIN docs](https://www.pgmustard.com/docs/explain) also offer detailed look into nodes and their fields.
-
-### Seq Scan
-
-A sequential scan over (a chunk of) a database table. This is like using
-`Array#each`, but on a database table. Sequential scans can be quite slow when
-retrieving lots of rows, so it's best to avoid these for large tables.
-
-### Index Only Scan
-
-A scan on an index that did not require fetching anything from the table. In
-certain cases an index only scan may still fetch data from the table, in this
-case the node includes a `Heap Fetches:` statistic.
-
-### Index Scan
-
-A scan on an index that required retrieving some data from the table.
-
-### Bitmap Index Scan and Bitmap Heap scan
-
-Bitmap scans fall between sequential scans and index scans. These are typically
-used when we would read too much data from an index scan, but too little to
-perform a sequential scan. A bitmap scan uses what is known as a [bitmap
-index](https://en.wikipedia.org/wiki/Bitmap_index) to perform its work.
-
-The [source code of PostgreSQL](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)
-states the following on bitmap scans:
-
-> Bitmap Index Scan delivers a bitmap of potential tuple locations; it does not
-> access the heap itself. The bitmap is used by an ancestor Bitmap Heap Scan
-> node, possibly after passing through intermediate Bitmap And and/or Bitmap Or
-> nodes to combine it with the results of other Bitmap Index Scans.
-
-### Limit
-
-Applies a `LIMIT` on the input rows.
-
-### Sort
-
-Sorts the input rows as specified using an `ORDER BY` statement.
-
-### Nested Loop
-
-A nested loop executes its child nodes for every row produced by a node that
-precedes it. For example:
-
-```sql
--> Nested Loop (cost=0.86..176.75 rows=87 width=0) (actual time=0.035..0.249 rows=36 loops=1)
- Buffers: shared hit=155
- -> Index Only Scan using users_pkey on users users_1 (cost=0.43..4.95 rows=87 width=4) (actual time=0.029..0.123 rows=36 loops=1)
- Index Cond: (id < 100)
- Heap Fetches: 0
- -> Index Only Scan using users_pkey on users (cost=0.43..1.96 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=36)
- Index Cond: (id = users_1.id)
- Heap Fetches: 0
-```
-
-Here the first child node (`Index Only Scan using users_pkey on users users_1`)
-produces 36 rows, and is executed once (`rows=36 loops=1`). The next node
-produces 1 row (`rows=1`), but is repeated 36 times (`loops=36`). This is
-because the previous node produced 36 rows.
-
-This means that nested loops can quickly slow the query down if the various
-child nodes keep producing many rows.
-
-## Optimising queries
-
-With that out of the way, let's see how we can optimise a query. Let's use the
-following query as an example:
-
-```sql
-SELECT COUNT(*)
-FROM users
-WHERE twitter != '';
-```
-
-This query counts the number of users that have a Twitter profile set.
-Let's run this using `EXPLAIN (ANALYZE, BUFFERS)`:
-
-```sql
-EXPLAIN (ANALYZE, BUFFERS)
-SELECT COUNT(*)
-FROM users
-WHERE twitter != '';
-```
-
-This produces the following plan:
-
-```sql
-Aggregate (cost=845110.21..845110.22 rows=1 width=8) (actual time=1271.157..1271.158 rows=1 loops=1)
- Buffers: shared hit=202662
- -> Seq Scan on users (cost=0.00..844969.99 rows=56087 width=0) (actual time=0.019..1265.883 rows=51833 loops=1)
- Filter: ((twitter)::text <> ''::text)
- Rows Removed by Filter: 2487813
- Buffers: shared hit=202662
-Planning time: 0.390 ms
-Execution time: 1271.180 ms
-```
-
-From this query plan we can see the following:
-
-1. We need to perform a sequential scan on the `users` table.
-1. This sequential scan filters out 2,487,813 rows using a `Filter`.
-1. We use 202,622 buffers, which equals 1.58 GB of memory.
-1. It takes us 1.2 seconds to do all of this.
-
-Considering we are just counting users, that's quite expensive!
-
-Before we start making any changes, let's see if there are any existing indexes
-on the `users` table that we might be able to use. We can obtain this
-information by running `\d users` in a `psql` console, then scrolling down to
-the `Indexes:` section:
-
-```sql
-Indexes:
- "users_pkey" PRIMARY KEY, btree (id)
- "index_users_on_confirmation_token" UNIQUE, btree (confirmation_token)
- "index_users_on_email" UNIQUE, btree (email)
- "index_users_on_reset_password_token" UNIQUE, btree (reset_password_token)
- "index_users_on_static_object_token" UNIQUE, btree (static_object_token)
- "index_users_on_unlock_token" UNIQUE, btree (unlock_token)
- "index_on_users_name_lower" btree (lower(name::text))
- "index_users_on_accepted_term_id" btree (accepted_term_id)
- "index_users_on_admin" btree (admin)
- "index_users_on_created_at" btree (created_at)
- "index_users_on_email_trigram" gin (email gin_trgm_ops)
- "index_users_on_feed_token" btree (feed_token)
- "index_users_on_group_view" btree (group_view)
- "index_users_on_incoming_email_token" btree (incoming_email_token)
- "index_users_on_managing_group_id" btree (managing_group_id)
- "index_users_on_name" btree (name)
- "index_users_on_name_trigram" gin (name gin_trgm_ops)
- "index_users_on_public_email" btree (public_email) WHERE public_email::text <> ''::text
- "index_users_on_state" btree (state)
- "index_users_on_state_and_user_type" btree (state, user_type)
- "index_users_on_unconfirmed_email" btree (unconfirmed_email) WHERE unconfirmed_email IS NOT NULL
- "index_users_on_user_type" btree (user_type)
- "index_users_on_username" btree (username)
- "index_users_on_username_trigram" gin (username gin_trgm_ops)
- "tmp_idx_on_user_id_where_bio_is_filled" btree (id) WHERE COALESCE(bio, ''::character varying)::text IS DISTINCT FROM ''::text
-```
-
-Here we can see there is no index on the `twitter` column, which means
-PostgreSQL has to perform a sequential scan in this case. Let's try to fix this
-by adding the following index:
-
-```sql
-CREATE INDEX CONCURRENTLY twitter_test ON users (twitter);
-```
-
-If we now re-run our query using `EXPLAIN (ANALYZE, BUFFERS)` we get the
-following plan:
-
-```sql
-Aggregate (cost=61002.82..61002.83 rows=1 width=8) (actual time=297.311..297.312 rows=1 loops=1)
- Buffers: shared hit=51854 dirtied=19
- -> Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1)
- Filter: ((twitter)::text <> ''::text)
- Rows Removed by Filter: 2487830
- Heap Fetches: 26037
- Buffers: shared hit=51854 dirtied=19
-Planning time: 0.191 ms
-Execution time: 297.334 ms
-```
-
-Now it takes just under 300 milliseconds to get our data, instead of 1.2
-seconds. However, we still use 51,854 buffers, which is about 400 MB of memory.
-300 milliseconds is also quite slow for such a simple query. To understand why
-this query is still expensive, let's take a look at the following:
-
-```sql
-Index Only Scan using twitter_test on users (cost=0.43..60873.13 rows=51877 width=0) (actual time=279.184..293.532 rows=51833 loops=1)
- Filter: ((twitter)::text <> ''::text)
- Rows Removed by Filter: 2487830
-```
-
-We start with an index only scan on our index, but we somehow still apply a
-`Filter` that filters out 2,487,830 rows. Why is that? Well, let's look at how
-we created the index:
-
-```sql
-CREATE INDEX CONCURRENTLY twitter_test ON users (twitter);
-```
-
-We told PostgreSQL to index all possible values of the `twitter` column,
-even empty strings. Our query in turn uses `WHERE twitter != ''`. This means
-that the index does improve things, as we don't need to do a sequential scan,
-but we may still encounter empty strings. This means PostgreSQL _has_ to apply a
-Filter on the index results to get rid of those values.
-
-Fortunately, we can improve this even further using "partial indexes". Partial
-indexes are indexes with a `WHERE` condition that is applied when indexing data.
-For example:
-
-```sql
-CREATE INDEX CONCURRENTLY some_index ON users (email) WHERE id < 100
-```
-
-This index would only index the `email` value of rows that match `WHERE id <
-100`. We can use partial indexes to change our Twitter index to the following:
-
-```sql
-CREATE INDEX CONCURRENTLY twitter_test ON users (twitter) WHERE twitter != '';
-```
-
-After being created, if we run our query again we are given the following plan:
-
-```sql
-Aggregate (cost=1608.26..1608.27 rows=1 width=8) (actual time=19.821..19.821 rows=1 loops=1)
- Buffers: shared hit=44036
- -> Index Only Scan using twitter_test on users (cost=0.41..1479.71 rows=51420 width=0) (actual time=0.023..15.514 rows=51833 loops=1)
- Heap Fetches: 1208
- Buffers: shared hit=44036
-Planning time: 0.123 ms
-Execution time: 19.848 ms
-```
-
-That's _a lot_ better! Now it only takes 20 milliseconds to get the data, and we
-only use about 344 MB of buffers (instead of the original 1.58 GB). The reason
-this works is that now PostgreSQL no longer needs to apply a `Filter`, as the
-index only contains `twitter` values that are not empty.
-
-Keep in mind that you shouldn't just add partial indexes every time you want to
-optimise a query. Every index has to be updated for every write, and they may
-require quite a bit of space, depending on the amount of indexed data. As a
-result, first check if there are any existing indexes you may be able to reuse.
-If there aren't any, check if you can perhaps slightly change an existing one to
-fit both the existing and new queries. Only add a new index if none of the
-existing indexes can be used in any way.
-
-When comparing execution plans, don't take timing as the only important metric.
-Good timing is the main goal of any optimization, but it can be too volatile to
-be used for comparison (for example, it depends a lot on the state of cache).
-When optimizing a query, we usually need to reduce the amount of data we're
-dealing with. Indexes are the way to work with fewer pages (buffers) to get the
-result, so, during optimization, look at the number of buffers used (read and hit),
-and work on reducing these numbers. Reduced timing is the consequence of reduced
-buffer numbers. [Database Lab Engine](#database-lab-engine) guarantees that the plan is structurally
-identical to production (and overall number of buffers is the same as on production),
-but difference in cache state and I/O speed may lead to different timings.
-
-## Queries that can't be optimised
-
-Now that we have seen how to optimise a query, let's look at another query that
-we might not be able to optimise:
-
-```sql
-EXPLAIN (ANALYZE, BUFFERS)
-SELECT COUNT(*)
-FROM projects
-WHERE visibility_level IN (0, 20);
-```
-
-The output of `EXPLAIN (ANALYZE, BUFFERS)` is as follows:
-
-```sql
-Aggregate (cost=922420.60..922420.61 rows=1 width=8) (actual time=3428.535..3428.535 rows=1 loops=1)
- Buffers: shared hit=208846
- -> Seq Scan on projects (cost=0.00..908053.18 rows=5746969 width=0) (actual time=0.041..2987.606 rows=5746940 loops=1)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 65677
- Buffers: shared hit=208846
-Planning time: 2.861 ms
-Execution time: 3428.596 ms
-```
-
-Looking at the output we see the following Filter:
-
-```sql
-Filter: (visibility_level = ANY ('{0,20}'::integer[]))
-Rows Removed by Filter: 65677
-```
-
-Looking at the number of rows removed by the filter, we may be tempted to add an
-index on `projects.visibility_level` to somehow turn this Sequential scan +
-filter into an index-only scan.
-
-Unfortunately, doing so is unlikely to improve anything. Contrary to what some
-might believe, an index being present _does not guarantee_ that PostgreSQL
-actually uses it. For example, when doing a `SELECT * FROM projects` it is much
-cheaper to just scan the entire table, instead of using an index and then
-fetching data from the table. In such cases PostgreSQL may decide to not use an
-index.
-
-Second, let's think for a moment what our query does: it gets all projects with
-visibility level 0 or 20. In the above plan we can see this produces quite a lot
-of rows (5,745,940), but how much is that relative to the total? Let's find out
-by running the following query:
-
-```sql
-SELECT visibility_level, count(*) AS amount
-FROM projects
-GROUP BY visibility_level
-ORDER BY visibility_level ASC;
-```
-
-For GitLab.com this produces:
-
-```sql
- visibility_level | amount
-------------------+---------
- 0 | 5071325
- 10 | 65678
- 20 | 674801
-```
-
-Here the total number of projects is 5,811,804, and 5,746,126 of those are of
-level 0 or 20. That's 98% of the entire table!
-
-So no matter what we do, this query retrieves 98% of the entire table. Since
-most time is spent doing exactly that, there isn't really much we can do to
-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 optimise something you do not understand.
-
-### Cardinality and selectivity
-
-Earlier we saw that our query had to retrieve 98% of the rows in the table.
-There are two terms commonly used for databases: cardinality, and selectivity.
-Cardinality refers to the number of unique values in a particular column in a
-table.
-
-Selectivity is the number of unique values produced by an operation (for example, an
-index scan or filter), relative to the total number of rows. The higher the
-selectivity, the more likely PostgreSQL is able to use an index.
-
-In the above example, there are only 3 unique values: 0, 10, and 20. This means
-the cardinality is 3. The selectivity in turn is also very low: 0.0000003% (2 /
-5,811,804), because our `Filter` only filters using two values (`0` and `20`).
-With such a low selectivity value it's not surprising that PostgreSQL decides
-using an index is not worth it, because it would produce almost no unique rows.
-
-## Rewriting queries
-
-So the above query can't really be optimised as-is, or at least not much. But
-what if we slightly change the purpose of it? What if instead of retrieving all
-projects with `visibility_level` 0 or 20, we retrieve those that a user
-interacted with somehow?
-
-Fortunately, GitLab has an answer for this, and it's a table called
-`user_interacted_projects`. This table has the following schema:
-
-```sql
-Table "public.user_interacted_projects"
- Column | Type | Modifiers
-------------+---------+-----------
- user_id | integer | not null
- project_id | integer | not null
-Indexes:
- "index_user_interacted_projects_on_project_id_and_user_id" UNIQUE, btree (project_id, user_id)
- "index_user_interacted_projects_on_user_id" btree (user_id)
-Foreign-key constraints:
- "fk_rails_0894651f08" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
- "fk_rails_722ceba4f7" FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
-```
-
-Let's rewrite our query to `JOIN` this table onto our projects, and get the
-projects for a specific user:
-
-```sql
-EXPLAIN ANALYZE
-SELECT COUNT(*)
-FROM projects
-INNER JOIN user_interacted_projects ON user_interacted_projects.project_id = projects.id
-WHERE projects.visibility_level IN (0, 20)
-AND user_interacted_projects.user_id = 1;
-```
-
-What we do here is the following:
-
-1. Get our projects.
-1. `INNER JOIN` `user_interacted_projects`, meaning we're only left with rows in
- `projects` that have a corresponding row in `user_interacted_projects`.
-1. Limit this to the projects with `visibility_level` of 0 or 20, and to
- projects that the user with ID 1 interacted with.
-
-If we run this query we get the following plan:
-
-```sql
- Aggregate (cost=871.03..871.04 rows=1 width=8) (actual time=9.763..9.763 rows=1 loops=1)
- -> Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1)
- -> Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1)
- Index Cond: (user_id = 1)
- -> Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
- Index Cond: (id = user_interacted_projects.project_id)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 0
- Planning time: 2.614 ms
- Execution time: 9.809 ms
-```
-
-Here it only took us just under 10 milliseconds to get the data. We can also see
-we're retrieving far fewer projects:
-
-```sql
-Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
- Index Cond: (id = user_interacted_projects.project_id)
- Filter: (visibility_level = ANY ('{0,20}'::integer[]))
- Rows Removed by Filter: 0
-```
-
-Here we see we perform 145 loops (`loops=145`), with every loop producing 1 row
-(`rows=1`). This is much less than before, and our query performs much better!
-
-If we look at the plan we also see our costs are very low:
-
-```sql
-Index Scan using projects_pkey on projects (cost=0.43..3.45 rows=1 width=4) (actual time=0.049..0.050 rows=1 loops=145)
-```
-
-Here our cost is only 3.45, and it takes us 7.25 milliseconds to do so (0.05 * 145).
-The next index scan is a bit more expensive:
-
-```sql
-Index Scan using index_user_interacted_projects_on_user_id on user_interacted_projects (cost=0.43..160.71 rows=205 width=4) (actual time=0.939..2.508 rows=145 loops=1)
-```
-
-Here the cost is 160.71 (`cost=0.43..160.71`), taking about 2.5 milliseconds
-(based on the output of `actual time=....`).
-
-The most expensive part here is the "Nested Loop" that acts upon the result of
-these two index scans:
-
-```sql
-Nested Loop (cost=0.86..870.52 rows=203 width=0) (actual time=1.072..9.748 rows=143 loops=1)
-```
-
-Here we had to perform 870.52 disk page fetches for 203 rows, 9.748
-milliseconds, producing 143 rows in a single loop.
-
-The key takeaway here is that sometimes you have to rewrite (parts of) a query
-to make it better. Sometimes that means having to slightly change your feature
-to accommodate for better performance.
-
-## What makes a bad plan
-
-This is a bit of a difficult question to answer, because the definition of "bad"
-is relative to the problem you are trying to solve. However, some patterns are
-best avoided in most cases, such as:
-
-- Sequential scans on large tables
-- Filters that remove a lot of rows
-- Performing a certain step that requires _a lot_ of
- buffers (for example, an index scan for GitLab.com that requires more than 512 MB).
-
-As a general guideline, aim for a query that:
-
-1. Takes no more than 10 milliseconds. Our target time spent in SQL per request
- is around 100 milliseconds, so every query should be as fast as possible.
-1. Does not use an excessive number of buffers, relative to the workload. For
- example, retrieving ten rows shouldn't require 1 GB of buffers.
-1. Does not spend a long amount of time performing disk IO operations. The
- setting `track_io_timing` must be enabled for this data to be included in the
- output of `EXPLAIN ANALYZE`.
-1. Applies a `LIMIT` when retrieving rows without aggregating them, such as
- `SELECT * FROM users`.
-1. Doesn't use a `Filter` to filter out too many rows, especially if the query
- does not use a `LIMIT` to limit the number of returned rows. Filters can
- usually be removed by adding a (partial) index.
-
-These are _guidelines_ and not hard requirements, as different needs may require
-different queries. The only _rule_ is that you _must always measure_ your query
-(preferably using a production-like database) using `EXPLAIN (ANALYZE, BUFFERS)`
-and related tools such as:
-
-- [`explain.depesz.com`](https://explain.depesz.com/).
-- [`explain.dalibo.com/`](https://explain.dalibo.com/).
-
-## Producing query plans
-
-There are a few ways to get the output of a query plan. Of course you
-can directly run the `EXPLAIN` query in the `psql` console, or you can
-follow one of the other options below.
-
-### Database Lab Engine
-
-GitLab team members can use [Database Lab Engine](https://gitlab.com/postgres-ai/database-lab), and the companion
-SQL optimization tool - [Joe Bot](https://gitlab.com/postgres-ai/joe).
-
-Database Lab Engine provides developers with their own clone of the production database, while Joe Bot helps with exploring execution plans.
-
-Joe Bot is available in the [`#database-lab`](https://gitlab.slack.com/archives/CLJMDRD8C) channel on Slack,
-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:
-
-Create the column:
-
-```sql
-exec ALTER TABLE projects ADD COLUMN last_at timestamp without time zone
-```
-
-Create the index:
-
-```sql
-exec CREATE INDEX index_projects_last_activity ON projects (last_activity_at) WHERE last_activity_at IS NOT NULL
-```
-
-Analyze the table to update its statistics:
-
-```sql
-exec ANALYZE projects
-```
-
-Get the query plan:
-
-```sql
-explain SELECT * FROM projects WHERE last_activity_at < CURRENT_DATE
-```
-
-Once done you can rollback your changes:
-
-```sql
-reset
-```
-
-For more information about the available options, run:
-
-```sql
-help
-```
-
-The web interface comes with the following execution plan visualizers included:
-
-- [Depesz](https://explain.depesz.com/)
-- [PEV2](https://github.com/dalibo/pev2)
-- [FlameGraph](https://github.com/mgartner/pg_flame)
-
-#### Tips & Tricks
-
-The database connection is now maintained during your whole session, so you can use `exec set ...` for any session variables (such as `enable_seqscan` or `work_mem`). These settings are applied to all subsequent commands until you reset them. For example you can disable parallel queries with
-
-```sql
-exec SET max_parallel_workers_per_gather = 0
-```
-
-### Rails console
-
-Using the [`activerecord-explain-analyze`](https://github.com/6/activerecord-explain-analyze)
-you can directly generate the query plan from the Rails console:
-
-```ruby
-pry(main)> require 'activerecord-explain-analyze'
-=> true
-pry(main)> Project.where('build_timeout > ?', 3600).explain(analyze: true)
- Project Load (1.9ms) SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
- ↳ (pry):12
-=> EXPLAIN for: SELECT "projects".* FROM "projects" WHERE (build_timeout > 3600)
-Seq Scan on public.projects (cost=0.00..2.17 rows=1 width=742) (actual time=0.040..0.041 rows=0 loops=1)
- Output: id, name, path, description, created_at, updated_at, creator_id, namespace_id, ...
- Filter: (projects.build_timeout > 3600)
- Rows Removed by Filter: 14
- Buffers: shared hit=2
-Planning time: 0.411 ms
-Execution time: 0.113 ms
-```
-
-### ChatOps
-
-[GitLab team members can also use our ChatOps solution, available in Slack using the
-`/chatops` slash command](chatops_on_gitlabcom.md).
-
-NOTE:
-While ChatOps is still available, the recommended way to generate execution plans is to use [Database Lab Engine](#database-lab-engine).
-
-You can use ChatOps to get a query plan by running the following:
-
-```sql
-/chatops run explain SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20)
-```
-
-Visualising the plan using <https://explain.depesz.com/> is also supported:
-
-```sql
-/chatops run explain --visual SELECT COUNT(*) FROM projects WHERE visibility_level IN (0, 20)
-```
-
-Quoting the query is not necessary.
-
-For more information about the available options, run:
-
-```sql
-/chatops run explain --help
-```
-
-## Further reading
-
-A more extensive guide on understanding query plans can be found in
-the [presentation](https://public.dalibo.com/exports/conferences/_archives/_2012/201211_explain/understanding_explain.pdf)
-from [Dalibo.org](https://www.dalibo.com/en/).
-
-Depesz's blog also has a good [section](https://www.depesz.com/tag/unexplainable/) dedicated to query plans.
+<!-- This redirect file can be deleted after <2022-11-04>. -->
+<!-- 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/working_with_uploads.md b/doc/development/uploads/working_with_uploads.md
index d44f2f69168..5a5f987c37c 100644
--- a/doc/development/uploads/working_with_uploads.md
+++ b/doc/development/uploads/working_with_uploads.md
@@ -6,92 +6,295 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Uploads guide: Adding new uploads
-Here, we describe how to add a new upload route [accelerated](index.md#workhorse-assisted-uploads) by Workhorse.
-
-Upload routes belong to one of these categories:
-
-1. Rails controllers: uploads handled by Rails controllers.
-1. Grape API: uploads handled by a Grape API endpoint.
-1. GraphQL API: uploads handled by a GraphQL resolve function.
-
-WARNING:
-GraphQL uploads do not support [direct upload](index.md#direct-upload). Depending on the use case, the feature may not work on installations without NFS (like GitLab.com or Kubernetes installations). Uploading to object storage inside the GraphQL resolve function may result in timeout errors. For more details, follow [issue #280819](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
-
-## Update Workhorse for the new route
-
-For both the Rails controller and Grape API uploads, Workhorse must be updated to get the
-support for the new upload route.
-
-1. Open a new issue in the [Workhorse tracker](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/new) describing precisely the new upload route:
- - The route's URL.
- - The upload encoding.
- - If possible, provide a dump of the upload request.
-1. Implement and get the MR merged for this issue above.
-1. Ask the Maintainers of [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) to create a new release. You can do that in the merge request
- directly during the maintainer review, or ask for it in the `#workhorse` Slack channel.
-1. Bump the [Workhorse version file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_WORKHORSE_VERSION)
- to the version you have from the previous points, or bump it in the same merge request that contains
- the Rails changes. Refer to [Implementing the new route with a Rails controller](#implementing-the-new-route-with-a-rails-controller) or [Implementing the new route with a Grape API endpoint](#implementing-the-new-route-with-a-grape-api-endpoint) below.
-
-## Implementing the new route with a Rails controller
-
-For a Rails controller upload, we usually have a `multipart/form-data` upload and there are a
-few things to do:
-
-1. The upload is available under the parameter name you're using. For example, it could be an `artifact`
- or a nested parameter such as `user[avatar]`. If you have the upload under the
- `file` parameter, reading `params[:file]` should get you an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) instance.
-1. Generally speaking, it's a good idea to check if the instance is from the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) class. For example, see how we checked
-[that the parameter is indeed an `UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/commit/ea30fe8a71bf16ba07f1050ab4820607b5658719#51c0cc7a17b7f12c32bc41cfab3649ff2739b0eb_79_77).
-
-WARNING:
-**Do not** call `UploadedFile#from_params` directly! Do not build an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
-instance using `UploadedFile#from_params`! This method can be unsafe to use depending on the `params`
-passed. Instead, use the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
-instance that [`multipart.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/middleware/multipart.rb)
-builds automatically for you.
-
-## Implementing the new route with a Grape API endpoint
-
-For a Grape API upload, we can have a body or multipart upload. Things are slightly more complicated: two endpoints are needed. One for the
-Workhorse pre-upload authorization and one for accepting the upload metadata from Workhorse:
-
-1. Implement an endpoint with the URL + `/authorize` suffix that will:
- - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the [API helpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/helpers.rb).
- - Check user permissions.
- - Set the status to `200` with `status 200`.
- - Set the content type with `content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE`.
- - Use your dedicated `Uploader` class (let's say that it's `FileUploader`) to build the response with `FileUploader.workhorse_authorize(params)`.
-1. Implement the endpoint for the upload request that will:
- - Require all the `UploadedFile` objects as parameters.
- - For example, if we expect a single parameter `file` to be an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) instance,
-use `requires :file, type: ::API::Validations::Types::WorkhorseFile`.
- - Body upload requests have their upload available under the parameter `file`.
- - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the
-[API helpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/api/helpers.rb).
- - Check the user permissions.
- - The remaining code of the processing. In this step, the code must read the parameter. For
-our example, it would be `params[:file]`.
-
-WARNING:
-**Do not** call `UploadedFile#from_params` directly! Do not build an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
-object using `UploadedFile#from_params`! This method can be unsafe to use depending on the `params`
-passed. Instead, use the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
-object that [`multipart.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/middleware/multipart.rb)
-builds automatically for you.
-
-## Document Object Storage buckets and CarrierWave integration
-
-When using Object Storage, GitLab expects each kind of upload to maintain its own bucket in the respective
-Object Storage destination. Moreover, the integration with CarrierWave is not used all the time.
-The [Object Storage Working Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/)
-is investigating an approach that unifies Object Storage buckets into a single one and removes CarrierWave
-so as to simplify implementation and administration of uploads.
-
-Therefore, document new uploads here by slotting them into the following tables:
-
-- [Feature bucket details](#feature-bucket-details)
-- [CarrierWave integration](#carrierwave-integration)
+## Recommendations
+
+- When creating an uploader, [make it a subclass](#where-should-i-store-my-files) of `AttachmentUploader`
+- Add your uploader to the [tables](#tables) in this document
+- Do not add [new object storage buckets](#where-should-i-store-my-files)
+- Implement [direct upload](#implementing-direct-upload-support)
+- If you need to process your uploads, decide [where to do that](#processing-uploads)
+
+## Background information
+
+- [CarrierWave Uploaders](#carrierwave-uploaders)
+- [GitLab modifications to CarrierWave](#gitlab-modifications-to-carrierwave)
+
+## Where should I store my files?
+
+CarrierWave Uploaders determine where files get
+stored. When you create a new Uploader class you are deciding where to store the files of your new
+feature.
+
+First of all, ask yourself if you need a new Uploader class. It is OK
+to use the same Uploader class for different mountpoints or different
+models.
+
+If you do want or need your own Uploader class then you should make it
+a **subclass of `AttachmentUploader`**. You then inherit the storage
+location and directory scheme from that class. The directory scheme
+is:
+
+```ruby
+File.join(model.class.underscore, mounted_as.to_s, model.id.to_s)
+```
+
+If you look around in the GitLab code base you will find quite a few
+Uploaders that have their own storage location. For object storage,
+this means Uploaders have their own buckets. We now **discourage**
+adding new buckets for the following reasons:
+
+- Using a new bucket adds to development time because you need to make downstream changes in [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit), [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab) and [CNG](https://gitlab.com/gitlab-org/build/CNG).
+- Using a new bucket requires GitLab.com Infrastructure changes, which slows down the roll-out of your new feature
+- Using a new bucket slows down adoption of your new feature for self-managed GitLab installation: people cannot start using your new feature until their local GitLab administrator has configured the new bucket.
+
+By using an existing bucket you avoid all this extra work
+and friction. The `Gitlab.config.uploads` storage location, which is what
+`AttachmentUploader` uses, is guaranteed to already be configured.
+
+## Implementing Direct Upload support
+
+Below we will outline how to implement [direct upload](#direct-upload-via-workhorse) support.
+
+Using direct upload is not always necessary but it is usually a good
+idea. Unless the uploads handled by your feature are both infrequent
+and small, you probably want to implement direct upload. An example of
+a feature with small and infrequent uploads is project avatars: these
+rarely change and the application imposes strict size limits on them.
+
+If your feature handles uploads that are not both infrequent and small,
+then not implementing direct upload support means that you are taking on
+technical debt. At the very least, you should make sure that you _can_
+add direct upload support later.
+
+To support Direct Upload you need two things:
+
+1. A pre-authorization endpoint in Rails
+1. A Workhorse routing rule
+
+Workhorse does not know where to store your upload. To find out it
+makes a pre-authorization request. It also does not know whether or
+where to make a pre-authorization request. For that you need the
+routing rule.
+
+A note to those of us who remember,
+[Workhorse used to be a separate project](https://gitlab.com/groups/gitlab-org/-/epics/4826):
+it is not necessary anymore to break these two steps into separate merge
+requests. In fact it is probably easier to do both in one merge
+request.
+
+### Adding a Workhorse routing rule
+
+Routing rules are defined in
+[workhorse/internal/upstream/routes.go](https://gitlab.com/gitlab-org/gitlab/-/blob/adf99b5327700cf34a845626481d7d6fcc454e57/workhorse/internal/upstream/routes.go).
+They consist of:
+
+- An HTTP verb (usually "POST" or "PUT")
+- A path regular expression
+- An upload type: MIME multipart or "full request body"
+- Optionally, you can also match on HTTP headers like `Content-Type`
+
+Example:
+
+```golang
+u.route("PUT", apiProjectPattern+`packages/nuget/`, mimeMultipartUploader),
+```
+
+You should add a test for your routing rule to `TestAcceleratedUpload`
+in
+[workhorse/upload_test.go](https://gitlab.com/gitlab-org/gitlab/-/blob/adf99b5327700cf34a845626481d7d6fcc454e57/workhorse/upload_test.go).
+
+You should also manually verify that when you perform an upload
+request for your new feature, Workhorse makes a pre-authorization
+request. You can check this by looking at the Rails access logs. This
+is necessary because if you make a mistake in your routing rule you
+won't get a hard failure: you just end up using the less efficient
+default path.
+
+### Adding a pre-authorization endpoint
+
+We distinguish three cases: Rails controllers, Grape API endpoints and
+GraphQL resources.
+
+To start with the bad news: direct upload for GraphQL is currently not
+supported. The reason for this is that Workhorse does not parse
+GraphQL queries. Also see [issue #280819](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
+Consider accepting your file upload via Grape instead.
+
+For Grape pre-authorization endpoints, look for existing examples that
+implement `/authorize` routes. One example is the
+[POST `:id/uploads/authorize` endpoint](https://gitlab.com/gitlab-org/gitlab/-/blob/9ad53d623eecebb799ce89eada951e4f4a59c116/lib/api/projects.rb#L642-651).
+Note that this particular example is using FileUploader, which means
+that the upload will be stored in the storage location (bucket) of
+that Uploader class.
+
+For Rails endpoints you can use the
+[WorkhorseAuthorization concern](https://gitlab.com/gitlab-org/gitlab/-/blob/adf99b5327700cf34a845626481d7d6fcc454e57/app/controllers/concerns/workhorse_authorization.rb).
+
+## Processing uploads
+
+Some features require us to process uploads, for example to extract
+metadata from the uploaded file. There are a couple of different ways
+you can implement this. The main choice is _where_ to implement the
+processing, or "who is the processor".
+
+|Processor|Direct Upload possible?|Can reject HTTP request?|Implementation|
+|---|---|---|---|
+|Sidekiq|yes|no|Straightforward|
+|Workhorse|yes|yes|Complex|
+|Rails|no|yes|Easy|
+
+Processing in Rails looks appealing but it tends to lead to scaling
+problems down the road because you cannot use direct upload. You are
+then forced to rebuild your feature with processing in Workhorse. So
+if the requirements of your feature allows it, doing the processing in
+Sidekiq strikes a good balance between complexity and the ability to
+scale.
+
+## CarrierWave Uploaders
+
+GitLab uses a modified version of
+[CarrierWave](https://github.com/carrierwaveuploader/carrierwave) to
+manage uploads. Below we will describe how we use CarrierWave and how
+we modified it.
+
+The central concept of CarrierWave is the **Uploader** class. The
+Uploader defines where files get stored, and optionally contains
+validation and processing logic. To use an Uploader you must associate
+it with a text column on an ActiveRecord model. This called "mounting"
+and the column is called the "mountpoint". For example:
+
+```ruby
+class Project < ApplicationRecord
+ mount_uploader :avatar, AttachmentUploader
+end
+```
+
+Now if I upload an avatar called `tanuki.png` the idea is that in the
+`projects.avatar` column for my project, CarrierWave stores the string
+`tanuki.png`, and that the AttachmentUploader class contains the
+configuration data and directory schema. For example if the project ID
+is 123, the actual file may be in
+`/var/opt/gitlab/gitlab-rails/uploads/-/system/project/avatar/123/tanuki.png`.
+The directory
+`/var/opt/gitlab/gitlab-rails/uploads/-/system/project/avatar/123/`
+was chosen by the Uploader using among others configuration
+(`/var/opt/gitlab/gitlab-rails/uploads`), the model name (`project`),
+the model ID (`123`) and the mountpoint (`avatar`).
+
+> The Uploader determines the individual storage directory of your
+> upload. The mountpoint column in your model contains the filename.
+
+You never access the mountpoint column directly because CarrierWave
+defines a getter and setter on your model that operates on file handle
+objects.
+
+### Optional Uploader behaviors
+
+Besides determining the storage directory for your upload, a
+CarrierWave Uploader can implement several other behaviors via
+callbacks. Not all of these behaviors are usable in GitLab. In
+particular, you currently cannot use the `version` mechanism of
+CarrierWave. Things you can do include:
+
+- Filename validation
+- **Incompatible with direct upload:** One time pre-processing of file contents, e.g. image resizing
+- **Incompatible with direct upload:** Encryption at rest
+
+Note that CarrierWave pre-processing behaviors such as image resizing
+or encryption require local access to the uploaded file. This forces
+you to upload the processed file from Ruby. This flies against direct
+upload, which is all about _not_ doing the upload in Ruby. If you use
+direct upload with an Uploader with pre-processing behaviors then the
+pre-processing behaviors will be skipped silently.
+
+### CarrierWave Storage engines
+
+CarrierWave has 2 storage engines:
+
+|CarrierWave class|GitLab name|Description|
+|---|---|---|
+|`CarrierWave::Storage::File`|`ObjectStorage::Store::LOCAL` |Local files, accessed through the Ruby stdlib|
+| `CarrierWave::Storage::Fog`|`ObjectStorage::Store::REMOTE`|Cloud files, accessed through the [Fog gem](https://github.com/fog/fog)|
+
+GitLab uses both of these engines, depending on configuration.
+
+The normal way to choose a storage engine in CarrierWave is to use the
+`Uploader.storage` class method. In GitLab we do not do this; we have
+overridden `Uploader#storage` instead. This allows us to vary the
+storage engine file by file.
+
+### CarrierWave file lifecycle
+
+An Uploader is associated with two storage areas: regular storage and
+cache storage. Each has its own storage engine. If you assign a file
+to a mountpoint setter (`project.avatar =
+File.open('/tmp/tanuki.png')`) you will copy/move the file to cache
+storage as a side effect via the `cache!` method. To persist the file
+you must somehow call the `store!` method. This either happens via
+[ActiveRecord callbacks](https://github.com/carrierwaveuploader/carrierwave/blob/v1.3.2/lib/carrierwave/orm/activerecord.rb#L55)
+or by calling `store!` on an Uploader instance.
+
+Normally you do not need to interact with `cache!` and `store!` but if
+you need to debug GitLab CarrierWave modifications it is useful to
+know that they are there and that they always get called.
+Specifically, it is good to know that CarrierWave pre-processing
+behaviors (`process` etc.) are implemented as `before :cache` hooks,
+and in the case of direct upload, these hooks are ignored and do not
+run.
+
+> Direct upload skips all CarrierWave `before :cache` hooks.
+
+## GitLab modifications to CarrierWave
+
+GitLab uses a modified version of CarrierWave to make a number of things possible.
+
+### Migrating data between storage engines
+
+In
+[app/uploaders/object_storage.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/adf99b5327700cf34a845626481d7d6fcc454e57/app/uploaders/object_storage.rb)
+there is code for migrating user data between local storage and object
+storage. This code exists because for a long time, GitLab.com stored
+uploads on local storage via NFS. This changed when as part of an infrastructure
+migration we had to move the uploads to object storage.
+
+This is why the CarrierWave `storage` varies from upload to upload in
+GitLab, and why we have database columns like `uploads.store` or
+`ci_job_artifacts.file_store`.
+
+### Direct Upload via Workhorse
+
+Workhorse direct upload is a mechanism that lets us accept large
+uploads without spending a lot of Ruby CPU time. Workhorse is written
+in Go and goroutines have a much lower resource footprint than Ruby
+threads.
+
+Direct upload works as follows.
+
+1. Workhorse accepts a user upload request
+1. Workhorse pre-authenticates the request with Rails, and receives a temporary upload location
+1. Workhorse stores the file upload in the user's request to the temporary upload location
+1. Workhorse propagates the request to Rails
+1. Rails issues a remote copy operation to copy the uploaded file from its temporary location to the final location
+1. Rails deletes the temporary upload
+1. Workhorse deletes the temporary upload a second time in case Rails timed out
+
+Normally, `cache!` returns an instance of
+`CarrierWave::SanitizedFile`, and `store!` then
+[uploads that file using Fog](https://github.com/carrierwaveuploader/carrierwave/blob/v1.3.2/lib/carrierwave/storage/fog.rb#L327-L335).
+
+In the case of object storage, with the modifications specific to GitLab, the
+copying from the temporary location to the final location is
+implemented by Rails fooling CarrierWave. When CarrierWave tries to
+`cache!` the upload, we
+[return](https://gitlab.com/gitlab-org/gitlab/-/blob/59b441d578e41cb177406a9799639e7a5aa9c7e1/app/uploaders/object_storage.rb#L367)
+a `CarrierWave::Storage::Fog::File` file handle which points to the
+temporary file. During the `store!` phase, CarrierWave then
+[copies](https://github.com/carrierwaveuploader/carrierwave/blob/v1.3.2/lib/carrierwave/storage/fog.rb#L325)
+this file to its intended location.
+
+## Tables
+
+The Scalability::Frameworks team is going to make object storage and uploads more easy to use and more robust. If you add or change uploaders, it helps us if you update this table too. This helps us keep an overview of where and how uploaders are used.
### Feature bucket details
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index b9b4c6448e2..3f6187a4c2e 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -188,6 +188,24 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/maste
end
```
+ Alternatively, use the `strong_memoize_attr` helper to memoize the method for you:
+
+ ```ruby
+ class Find
+ include Gitlab::Utils::StrongMemoize
+
+ def result
+ search
+ end
+ strong_memoize_attr :result
+
+ strong_memoize_attr :enabled?, :enabled
+ def enabled?
+ Feature.enabled?(:some_feature)
+ end
+ end
+ ```
+
- Clear memoization
```ruby
diff --git a/doc/development/verifying_database_capabilities.md b/doc/development/verifying_database_capabilities.md
index 55347edf4ec..0217eb96e5a 100644
--- a/doc/development/verifying_database_capabilities.md
+++ b/doc/development/verifying_database_capabilities.md
@@ -1,38 +1,11 @@
---
-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
+redirect_to: 'database/verifying_database_capabilities.md'
+remove_date: '2022-11-06'
---
-# Verifying Database Capabilities
+This document was moved to [another location](database/verifying_database_capabilities.md).
-Sometimes certain bits of code may only work on a certain database
-version. While we try to avoid such code as much as possible sometimes it is
-necessary to add database (version) specific behavior.
-
-To facilitate this we have the following methods that you can use:
-
-- `ApplicationRecord.database.version`: returns the PostgreSQL version number as a string
- in the format `X.Y.Z`.
-
-This allows you to write code such as:
-
-```ruby
-if ApplicationRecord.database.version.to_f >= 11.7
- run_really_fast_query
-else
- run_fast_query
-end
-```
-
-## Read-only database
-
-The database can be used in read-only mode. In this case we have to
-make sure all GET requests don't attempt any write operations to the
-database. If one of those requests wants to write to the database, it needs
-to be wrapped in a `Gitlab::Database.read_only?` or `Gitlab::Database.read_write?`
-guard, to make sure it doesn't for read-only databases.
-
-We have a Rails Middleware that filters any potentially writing
-operations (the `CUD` operations of CRUD) and prevent the user from trying
-to update the database and getting a 500 error (see `Gitlab::Middleware::ReadOnly`).
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- 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/windows.md b/doc/development/windows.md
index 3eed9c057ab..17dfaddef36 100644
--- a/doc/development/windows.md
+++ b/doc/development/windows.md
@@ -37,8 +37,7 @@ A list of software preinstalled on the Windows images is available at: [Preinsta
## GCP Windows image for development
-The [shared Windows GitLab
-runners](https://about.gitlab.com/releases/2020/01/22/gitlab-12-7-released/#windows-shared-runners-on-gitlabcom-beta)
+The [shared Windows GitLab runners](https://about.gitlab.com/releases/2020/01/22/gitlab-12-7-released/#windows-shared-runners-on-gitlabcom-beta)
are built with [Packer](https://www.packer.io/).
The Infrastructure as Code repository for building the Google Cloud images is available at:
diff --git a/doc/development/work_items.md b/doc/development/work_items.md
index 9a17a152525..3625f85eb82 100644
--- a/doc/development/work_items.md
+++ b/doc/development/work_items.md
@@ -36,14 +36,12 @@ Here are some problems with current issues usage and why we are looking into wor
differences in common interactions that the user needs to hold a complicated mental
model of how they each behave.
- Issues are not extensible enough to support all of the emerging jobs they need to facilitate.
-- Codebase maintainability and feature development become bigger challenges as we grow the Issue type
+- Codebase maintainability and feature development becomes a bigger challenge as we grow the Issue type.
beyond its core role of issue tracking into supporting the different work item types and handling
logic and structure differences.
- New functionality is typically implemented with first class objects that import behavior from issues via
shared concerns. This leads to duplicated effort and ultimately small differences between common interactions. This
leads to inconsistent UX.
-- Codebase maintainability and feature development becomes a bigger challenges as we grow issues
- beyond its core role of issue tracking into supporting the different types and subtle differences between them.
## Work item terminology
diff --git a/doc/development/workhorse/configuration.md b/doc/development/workhorse/configuration.md
index b86bb824ea1..a94ba2b4fc6 100644
--- a/doc/development/workhorse/configuration.md
+++ b/doc/development/workhorse/configuration.md
@@ -211,7 +211,7 @@ Workhorse supports distributed tracing through [LabKit](https://gitlab.com/gitla
using [OpenTracing APIs](https://opentracing.io).
By default, no tracing implementation is linked into the binary. You can link in
-different OpenTracing providers with [build tags](https://golang.org/pkg/go/build/#hdr-Build_Constraints)
+different OpenTracing providers with [build tags](https://pkg.go.dev/go/build#hdr-Build_Constraints)
or build constraints by setting the `BUILD_TAGS` make variable.
For more details of the supported providers, refer to LabKit. For an example of
@@ -234,7 +234,7 @@ When a user makes an HTTP request, such as creating a new project, the
initial request is routed through Workhorse to another service, which
may in turn, make other requests. To help trace the request as it flows
across services, Workhorse generates a random value called a
-[correlation ID](../../administration/troubleshooting/tracing_correlation_id.md).
+[correlation ID](../../administration/logs/tracing_correlation_id.md).
Workhorse sends this correlation ID via the `X-Request-Id` HTTP header.
Some GitLab services, such as GitLab Shell, generate their own
@@ -278,9 +278,9 @@ trusted_cidrs_for_x_forwarded_for = ["10.0.0.0/8", "127.0.0.1/32"]
## Continuous profiling
Workhorse supports continuous profiling through [LabKit](https://gitlab.com/gitlab-org/labkit/)
-using [Stackdriver Profiler](https://cloud.google.com/profiler). By default, the
+using [Stackdriver Profiler](https://cloud.google.com/products/operations). By default, the
Stackdriver Profiler implementation is linked in the binary using
-[build tags](https://golang.org/pkg/go/build/#hdr-Build_Constraints), though it's not
+[build tags](https://pkg.go.dev/go/build#hdr-Build_Constraints), though it's not
required and can be skipped. For example:
```shell
diff --git a/doc/development/workhorse/gitlab_features.md b/doc/development/workhorse/gitlab_features.md
index 365cc7991d8..3b240d4cbc6 100644
--- a/doc/development/workhorse/gitlab_features.md
+++ b/doc/development/workhorse/gitlab_features.md
@@ -70,4 +70,4 @@ memory than it costs to have Workhorse look after it.
- Workhorse does not clean up idle client connections.
- We assume that all requests to Rails pass through Workhorse.
-For more information see ['A brief history of GitLab Workhorse'](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/).
+For more information see ['A brief history of GitLab Workhorse'](https://about.gitlab.com/blog/2016/04/12/a-brief-history-of-gitlab-workhorse/).
diff --git a/doc/development/workhorse/index.md b/doc/development/workhorse/index.md
index 3aa7e945f53..962124248ef 100644
--- a/doc/development/workhorse/index.md
+++ b/doc/development/workhorse/index.md
@@ -10,8 +10,8 @@ GitLab Workhorse is a smart reverse proxy for GitLab. It handles
"large" HTTP requests such as file downloads, file uploads, Git
push/pull and Git archive downloads.
-Workhorse itself is not a feature, but there are [several features in
-GitLab](gitlab_features.md) that would not work efficiently without Workhorse.
+Workhorse itself is not a feature, but there are
+[several features in GitLab](gitlab_features.md) that would not work efficiently without Workhorse.
The canonical source for Workhorse is
[`gitlab-org/gitlab/workhorse`](https://gitlab.com/gitlab-org/gitlab/tree/master/workhorse).
@@ -21,7 +21,7 @@ but that repository is no longer used for development.
## Install Workhorse
-To install GitLab Workhorse you need [Go 1.15 or newer](https://golang.org/dl) and
+To install GitLab Workhorse you need [Go 1.15 or newer](https://go.dev/dl) and
[GNU Make](https://www.gnu.org/software/make/).
To install into `/usr/local/bin` run `make install`.
@@ -44,7 +44,7 @@ On some operating systems, such as FreeBSD, you may have to use
### Run time dependencies
-Workhorse uses [ExifTool](https://www.sno.phy.queensu.ca/~phil/exiftool/) for
+Workhorse uses [ExifTool](https://exiftool.org/) for
removing EXIF data (which may contain sensitive information) from uploaded
images. If you installed GitLab:
diff --git a/doc/downgrade_ee_to_ce/index.md b/doc/downgrade_ee_to_ce/index.md
index ca8d6f87809..2aa99eae084 100644
--- a/doc/downgrade_ee_to_ce/index.md
+++ b/doc/downgrade_ee_to_ce/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Downgrading from EE to CE
If you ever decide to downgrade your Enterprise Edition back to the
-Community Edition, there are a few steps you need take beforehand. On Omnibus GitLab
+Community Edition, there are a few steps you need to take beforehand. On Omnibus GitLab
installations, these steps are made before installing the CE package on top of
the current EE package. On installations from source, they are done before
you change remotes and fetch the latest CE code.
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 65680227ad0..c6de723246c 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -391,7 +391,7 @@ git checkout <default-branch>
git merge <feature-branch>
```
-In GitLab, you typically use a [merge request](../user/project/merge_requests/) to merge your changes, instead of using the command line.
+In GitLab, you typically use a [merge request](../user/project/merge_requests/index.md) to merge your changes, instead of using the command line.
To create a merge request from a fork to an upstream repository, see the
[forking workflow](../user/project/repository/forking_workflow.md).
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index bc811cab3bf..b7a01cf61f4 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -32,15 +32,18 @@ Amazon provides a managed Kubernetes service offering known as [Amazon Elastic K
## Available Infrastructure as Code for GitLab Cloud Native Hybrid
+The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions. GET is where GitLab is investing its resources as the primary option for Infrastructure as Code, and is being actively used in production as a part of [GitLab Dedicated](../../subscriptions/gitlab_dedicated/index.md).
+
+Read the [GitLab Environment Toolkit (GET) direction](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md#direction) to learn more about the project and where it is going.
+
The [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) is developed by AWS, GitLab, and the community that contributes to AWS Quick Starts, whether directly to the GitLab Quick Start or to the underlying Quick Start dependencies GitLab inherits (for example, EKS Quick Start).
+GET is recommended for most deployments. The AWS Quick Start can be used if the IaC language of choice is CloudFormation, integration with AWS services like Control Tower is desired, or preference for a UI-driven configuration experience or when any aspect in the below table is an overriding concern.
+
NOTE:
This automation is in **[Open Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#open-beta)**. GitLab is working with AWS on resolving [the outstanding issues](https://github.com/aws-quickstart/quickstart-eks-gitlab/issues?q=is%3Aissue+is%3Aopen+%5BHL%5D) before it is fully released. You can subscribe to this issue to be notified of progress and release announcements: [AWS Quick Start for GitLab Cloud Native Hybrid on EKS Status: Beta](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues/11).<br><br>
The Beta version deploys Aurora PostgreSQL, but the release version will deploy Amazon RDS PostgreSQL due to [known issues](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) with Aurora. All performance testing results will also be redone after this change has been made.
-The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/tree/main) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions.
-It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/issues) to understand if any of them may affect your provisioning plans.
-
| | [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| Overview and Vision | [AWS Quick Start](https://aws.amazon.com/quickstart/) | [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/README.md) |
@@ -56,9 +59,11 @@ It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gi
| Results in a Ready-to-Use instance | Yes | Manual Actions or <br />Supplemental IaC Required |
| **<u>Configuration Features</u>** | | |
| Can deploy Omnibus GitLab (non-Kubernetes) | No | Yes |
-| Results in a self-healing Gitaly Cluster configuration | Yes | No |
+| Can deploy Single Instance Omnibus GitLab (non-Kubernetes) | No | Yes |
| Complete Internal Encryption | 85%, Targeting 100% | Manual |
| AWS GovCloud Support | Yes | TBD |
+| No Code Form-Based Deployment User Experience Available | Yes | No |
+| Full IaC User Experience Available | Yes | Yes |
### Two and Three Zone High Availability
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 0d621217dd8..7f155a78140 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -233,8 +233,8 @@ The first thing that appears is the sign-in page. GitLab creates an administrato
The credentials are:
- Username: `root`
-- Password: the password is automatically created, and there are [two ways to
- find it](https://docs.bitnami.com/azure/faq/get-started/find-credentials/).
+- 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).
diff --git a/doc/install/docker.md b/doc/install/docker.md
index 356c025e168..7ec1b7c741a 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -166,7 +166,7 @@ install, and upgrade your Docker-based GitLab installation:
GitLab:
```shell
- docker-compose up -d
+ docker compose up -d
```
NOTE:
@@ -510,8 +510,8 @@ To upgrade GitLab that was [installed using Docker Compose](#install-gitlab-usin
1. Download the newest release and upgrade your GitLab instance:
```shell
- docker-compose pull
- docker-compose up -d
+ docker compose pull
+ docker compose up -d
```
If you have used [tags](#use-tagged-versions-of-gitlab) instead, you'll need
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 2f2ae016edd..2f6adb06322 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -129,8 +129,8 @@ sudo apt-get install libkrb5-dev
### Git
-From GitLab 13.6, we recommend you use the [Git version provided by
-Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
+From GitLab 13.6, we recommend you use the
+[Git version provided by Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
that:
- Is always at the version required by GitLab.
@@ -239,8 +239,8 @@ sudo make install
GitLab has several daemons written in Go. To install
GitLab we need a Go compiler. The instructions below assume you use 64-bit
-Linux. You can find downloads for other platforms at the [Go download
-page](https://go.dev/dl).
+Linux. You can find downloads for other platforms at the
+[Go download page](https://go.dev/dl).
```shell
# Remove former Go installation folder
@@ -556,19 +556,6 @@ sudo -u git -H cp config/puma.rb.example config/puma.rb
# cores you have available. You can get that number via the `nproc` command.
sudo -u git -H editor config/puma.rb
-# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed
-sudo -u git -H git config --global gc.auto 0
-
-# Enable packfile bitmaps
-sudo -u git -H git config --global repack.writeBitmaps true
-
-# Enable push options
-# Refer to https://docs.gitlab.com/ee/user/project/push_options.html for more information.
-sudo -u git -H git config --global receive.advertisePushOptions true
-
-# Enable fsyncObjectFiles to reduce risk of repository corruption if the server crashes
-sudo -u git -H git config --global core.fsyncObjectFiles true
-
# Configure Redis connection settings
sudo -u git -H cp config/resque.yml.example config/resque.yml
sudo -u git -H cp config/cable.yml.example config/cable.yml
@@ -1064,7 +1051,7 @@ See the [OmniAuth integration documentation](../integration/omniauth.md).
### Build your projects
GitLab can build your projects. To enable that feature, you need runners to do that for you.
-See the [GitLab Runner section](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/#gitlab-runner) to install it.
+See the [GitLab Runner section](https://docs.gitlab.com/runner/) to install it.
### Adding your Trusted Proxies
diff --git a/doc/install/next_steps.md b/doc/install/next_steps.md
index 4defb62d254..4df2da875a6 100644
--- a/doc/install/next_steps.md
+++ b/doc/install/next_steps.md
@@ -28,7 +28,7 @@ installation.
## Security
-- [Secure GitLab](../security/index.md#securing-your-gitlab-installation):
+- [Secure GitLab](../security/index.md):
Recommended practices to secure your GitLab instance.
- Sign up for the GitLab [Security Newsletter](https://about.gitlab.com/company/preference-center/) to get notified for security updates upon release.
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 27148e06ccb..93d66dc92a9 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -65,7 +65,7 @@ Because file system performance may affect the overall performance of GitLab,
[we don't recommend using cloud-based file systems for storage](../administration/nfs.md#avoid-using-cloud-based-file-systems).
NOTE:
-[NFS for Git repository storage is deprecated](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#nfs-for-git-repository-storage-deprecated). See our official [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for further information.
+[NFS for Git repository storage is deprecated](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#nfs-for-git-repository-storage-deprecated). See our official [Statement of Support](https://about.gitlab.com/support/statement-of-support/#gitaly-and-nfs) for further information.
### CPU
@@ -84,7 +84,7 @@ Memory requirements are dependent on the number of users and expected workload.
The following is the recommended minimum Memory hardware guidance for a handful of example GitLab user base sizes.
- **4GB RAM** is the **required** minimum memory size and supports up to 500 users
- - Our [Memory Team](https://about.gitlab.com/handbook/engineering/development/enablement/memory/) is working to reduce the memory requirement.
+ - Our [Memory Team](https://about.gitlab.com/handbook/engineering/development/enablement/data_stores/memory/) is working to reduce the memory requirement.
- 8GB RAM supports up to 1000 users
- More users? Consult the [reference architectures page](../administration/reference_architectures/index.md)
@@ -326,7 +326,7 @@ GitLab supports the following web browsers:
- [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/new/)
- [Google Chrome](https://www.google.com/chrome/)
-- [Chromium](https://www.chromium.org/getting-involved/dev-channel)
+- [Chromium](https://www.chromium.org/getting-involved/dev-channel/)
- [Apple Safari](https://www.apple.com/safari/)
- [Microsoft Edge](https://www.microsoft.com/en-us/edge)
diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md
index 5eac6ab7c84..dc3dc4d2012 100644
--- a/doc/integration/advanced_search/elasticsearch.md
+++ b/doc/integration/advanced_search/elasticsearch.md
@@ -35,6 +35,10 @@ before we remove them.
|-----------------------|--------------------------|
| GitLab 15.0 or later | OpenSearch 1.x or later |
+If your version of Elasticsearch or OpenSearch is incompatible, to prevent data loss, indexing pauses and
+a message is logged in the
+[`elasticsearch.log`](../../administration/logs/index.md#elasticsearchlog) file.
+
If you are using a compatible version and after connecting to OpenSearch, you get the message `Elasticsearch version not compatible`, [unpause indexing](#unpause-indexing).
## System requirements
@@ -53,7 +57,7 @@ each node should have:
## Install Elasticsearch
Elasticsearch is *not* included in the Omnibus packages or when you install from
-source. You must [install it separately](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/install-elasticsearch.html "Elasticsearch 7.x installation documentation") and ensure you select your version. Detailed information on how to install Elasticsearch is out of the scope of this page.
+source. You must [install it separately](https://www.elastic.co/guide/en/elasticsearch/reference/7.16/install-elasticsearch.html "Elasticsearch 7.x installation documentation") and ensure you select your version. Detailed information on how to install Elasticsearch is out of the scope of this page.
You can install Elasticsearch yourself, or use a cloud hosted offering such as [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (available on AWS, GCP, or Azure) or the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/gsg.html)
service.
@@ -159,6 +163,12 @@ If you see an error such as `Permission denied - /home/git/gitlab-elasticsearch-
may need to set the `production -> elasticsearch -> indexer_path` setting in your `gitlab.yml` file to
`/usr/local/bin/gitlab-elasticsearch-indexer`, which is where the binary is installed.
+### View indexing errors
+
+Errors from the [GitLab Elasticsearch Indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer) are reported in
+the [`sidekiq.log`](../../administration/logs/index.md#sidekiqlog) file with a `json.exception.class` of `Gitlab::Elastic::Indexer::Error`.
+These errors may occur when indexing Git repository data.
+
## Enable Advanced Search
For GitLab instances with more than 50GB repository data you can follow the instructions for [how to index large instances efficiently](#how-to-index-large-instances-efficiently) below.
@@ -212,7 +222,7 @@ The following Elasticsearch settings are available:
| `Password` | The password of your Elasticsearch instance. |
| `Number of Elasticsearch shards` | Elasticsearch indices are split into multiple shards for performance reasons. In general, you should use at least 5 shards, and indices with tens of millions of documents need to have more shards ([see below](#guidance-on-choosing-optimal-cluster-configuration)). Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html). |
| `Number of Elasticsearch replicas` | Each Elasticsearch shard can have a number of replicas. These are a complete copy of the shard, and can provide increased query performance or resilience against hardware failure. Increasing this value increases total disk space required by the index. |
-| `Limit the number of namespaces and projects that can be indexed` | Enabling this allows you to select namespaces and projects to index. All other namespaces and projects use database search instead. If you enable this option but do not select any namespaces or projects, none are indexed. [Read more below](#limit-the-number-of-namespaces-and-projects-that-can-be-indexed).
+| `Limit the number of namespaces and projects that can be indexed` | Enabling this allows you to select namespaces and projects to index. All other namespaces and projects use database search instead. If you enable this option but do not select any namespaces or projects, none are indexed. [Read more below](#limit-the-number-of-namespaces-and-projects-that-can-be-indexed).|
| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). Please refer to [Identity and Access Management in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ac.html) for details of AWS hosted OpenSearch domain access policy configuration. |
| `AWS Region` | The AWS region in which your OpenSearch Service is located. |
| `AWS Access Key` | The AWS access key. |
@@ -438,13 +448,13 @@ This should return something similar to:
}
```
-In order to debug issues with the migrations you can check the [`elasticsearch.log` file](../../administration/logs.md#elasticsearchlog).
+In order to debug issues with the migrations you can check the [`elasticsearch.log` file](../../administration/logs/index.md#elasticsearchlog).
### Retry a halted migration
Some migrations are built with a retry limit. If the migration cannot finish within the retry limit,
it is halted and a notification is displayed in the Advanced Search integration settings.
-It is recommended to check the [`elasticsearch.log` file](../../administration/logs.md#elasticsearchlog) to
+It is recommended to check the [`elasticsearch.log` file](../../administration/logs/index.md#elasticsearchlog) to
debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
fixed the cause of the failure, select "Retry migration", and the migration is scheduled to be retried
in the background.
@@ -462,8 +472,7 @@ Before doing a major version GitLab upgrade, you should have completed all
migrations that exist up until the latest minor version before that major
version. If you have halted migrations, these need to be resolved and
[retried](#retry-a-halted-migration) before proceeding with a major version
-upgrade. Read more about [upgrading to a new major
-version](../../update/index.md#upgrading-to-a-new-major-version).
+upgrade. Read more about [upgrading to a new major version](../../update/index.md#upgrading-to-a-new-major-version).
## GitLab Advanced Search Rake tasks
@@ -573,9 +582,9 @@ due to large volumes of data being indexed.
WARNING:
Indexing a large instance generates a lot of Sidekiq jobs.
-Make sure to prepare for this task by having a [Scalable and Highly Available
-Setup](../../administration/reference_architectures/index.md) or creating [extra
-Sidekiq processes](../../administration/operations/extra_sidekiq_processes.md).
+Make sure to prepare for this task by having a
+[scalable setup](../../administration/reference_architectures/index.md) or creating
+[extra Sidekiq processes](../../administration/sidekiq/extra_sidekiq_processes.md).
1. [Configure your Elasticsearch host and port](#enable-advanced-search).
1. Create empty indices:
@@ -774,8 +783,8 @@ additional process dedicated to indexing a set of queues (or queue group). This
ensure that indexing queues always have a dedicated worker, while the rest of the queues have
another dedicated worker to avoid contention.
-For this purpose, use the [queue selector](../../administration/operations/extra_sidekiq_processes.md#queue-selector)
-option that allows a more general selection of queue groups using a [worker matching query](../../administration/operations/extra_sidekiq_routing.md#worker-matching-query).
+For this purpose, use the [queue selector](../../administration/sidekiq/extra_sidekiq_processes.md#queue-selector)
+option that allows a more general selection of queue groups using a [worker matching query](../../administration/sidekiq/extra_sidekiq_routing.md#worker-matching-query).
To handle these two queue groups, we generally recommend one of the following two options. You can either:
@@ -809,7 +818,7 @@ WARNING:
When starting multiple processes, the number of processes cannot exceed the number of CPU
cores you want to dedicate to Sidekiq. Each Sidekiq process can use only one CPU core, subject
to the available workload and concurrency settings. For more details, see how to
-[run multiple Sidekiq processes](../../administration/operations/extra_sidekiq_processes.md).
+[run multiple Sidekiq processes](../../administration/sidekiq/extra_sidekiq_processes.md).
### Two nodes, one process for each
diff --git a/doc/integration/advanced_search/elasticsearch_troubleshooting.md b/doc/integration/advanced_search/elasticsearch_troubleshooting.md
index 97abf456baa..fb558441d6a 100644
--- a/doc/integration/advanced_search/elasticsearch_troubleshooting.md
+++ b/doc/integration/advanced_search/elasticsearch_troubleshooting.md
@@ -14,16 +14,30 @@ Use the following information to troubleshoot Elasticsearch issues.
One of the most valuable tools for identifying issues with the Elasticsearch
integration are logs. The most relevant logs for this integration are:
-1. [`sidekiq.log`](../../administration/logs.md#sidekiqlog) - All of the
+1. [`sidekiq.log`](../../administration/logs/index.md#sidekiqlog) - All of the
indexing happens in Sidekiq, so much of the relevant logs for the
Elasticsearch integration can be found in this file.
-1. [`elasticsearch.log`](../../administration/logs.md#elasticsearchlog) - There
+1. [`elasticsearch.log`](../../administration/logs/index.md#elasticsearchlog) - There
are additional logs specific to Elasticsearch that are sent to this file
that may contain useful diagnostic information about searching,
indexing or migrations.
Here are some common pitfalls and how to overcome them.
+## Common terminology
+
+- **Lucene**: A full-text search library written in Java.
+- **Near real time (NRT)**: Refers to the slight latency from the time to index a
+ document to the time when it becomes searchable.
+- **Cluster**: A collection of one or more nodes that work together to hold all
+ the data, providing indexing and search capabilities.
+- **Node**: A single server that works as part of a cluster.
+- **Index**: A collection of documents that have somewhat similar characteristics.
+- **Document**: A basic unit of information that can be indexed.
+- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
+ a Lucene index.
+- **Replicas**: Failover mechanisms that duplicate indices.
+
## How can I verify that my GitLab instance is using Elasticsearch?
There are a couple of ways to achieve that:
@@ -44,6 +58,20 @@ There are a couple of ways to achieve that:
::Gitlab::CurrentSettings.elasticsearch_limit_indexing? # Whether or not Elasticsearch is limited only to certain projects/namespaces
```
+- Confirm searches use Elasticsearch by accessing the [rails console]
+ (../../administration/operations/rails_console.md) and running the following commands:
+
+ ```rails
+ u = User.find_by_email('email_of_user_doing_search')
+ s = SearchService.new(u, {:search => 'search_term'})
+ pp s.search_objects.class
+ ```
+
+ The output from the last command is the key here. If it shows:
+
+ - `ActiveRecord::Relation`, **it is not** using Elasticsearch.
+ - `Kaminari::PaginatableArray`, **it is** using Elasticsearch.
+
- If Elasticsearch is limited to specific namespaces and you need to know if
Elasticsearch is being used for a specific project or namespace, you can use
the Rails console:
@@ -53,13 +81,57 @@ There are a couple of ways to achieve that:
::Gitlab::CurrentSettings.search_using_elasticsearch?(scope: Project.find_by_full_path("/my-namespace/my-project"))
```
-## I updated GitLab and now I can't find anything
+## Troubleshooting indexing
+
+Troubleshooting indexing issues can be tricky. It can pretty quickly go to either GitLab
+support or your Elasticsearch administrator.
+
+The best place to start is to determine if the issue is with creating an empty index.
+If it is, check on the Elasticsearch side to determine if the `gitlab-production` (the
+name for the GitLab index) exists. If it exists, manually delete it on the Elasticsearch
+side and attempt to recreate it from the
+[`recreate_index`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks)
+Rake task.
+
+If you still encounter issues, try creating an index manually on the Elasticsearch
+instance. The details of the index aren't important here, as we want to test if indices
+can be made. If the indices:
+
+- Cannot be made, speak with your Elasticsearch administrator.
+- Can be made, Escalate this to GitLab support.
+
+If the issue is not with creating an empty index, the next step is to check for errors
+during the indexing of projects. If errors do occur, they stem from either the indexing:
+
+- On the GitLab side. You need to rectify those. If they are not
+ something you are familiar with, contact GitLab support for guidance.
+- Within the Elasticsearch instance itself. See if the error is [documented and has a fix](../../integration/advanced_search/elasticsearch_troubleshooting.md). If not, speak with your Elasticsearch administrator.
+
+If the indexing process does not present errors, check the status of the indexed projects. You can do this via the following Rake tasks:
+
+- [`sudo gitlab-rake gitlab:elastic:index_projects_status`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows the overall status)
+- [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](../../integration/advanced_search/elasticsearch.md#gitlab-advanced-search-rake-tasks) (shows specific projects that are not indexed)
+
+If:
+
+- Everything is showing at 100%, escalate to GitLab support. This could be a potential
+ bug/issue.
+- You do see something not at 100%, attempt to reindex that project. To do this,
+ run `sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=<project ID> ID_TO=<project ID>`.
+
+If reindexing the project shows:
+
+- Errors on the GitLab side, escalate those to GitLab support.
+- Elasticsearch errors or doesn't present any errors at all, reach out to your
+ Elasticsearch administrator to check the instance.
+
+### I updated GitLab and now I can't find anything
We continuously make updates to our indexing strategies and aim to support
newer versions of Elasticsearch. When indexing changes are made, it may
be necessary for you to [reindex](elasticsearch.md#zero-downtime-reindexing) after updating GitLab.
-## I indexed all the repositories but I can't get any hits for my search term in the UI
+### I indexed all the repositories but I can't get any hits for my search term in the UI
Make sure you [indexed all the database data](elasticsearch.md#enable-advanced-search).
@@ -79,26 +151,29 @@ curl --request GET <elasticsearch_server_ip>:9200/gitlab-production/_search?q=<s
More [complex Elasticsearch API calls](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html) are also possible.
-It is important to understand at which level the problem is manifesting (UI, Rails code, Elasticsearch side) to be able to [troubleshoot further](../../administration/troubleshooting/elasticsearch.md#search-results-workflow).
+If the results:
+
+- Sync up, please check that you are using [supported syntax](../../user/search/global_search/advanced_search_syntax.md). Note that Advanced Search does not support [exact substring matching](https://gitlab.com/gitlab-org/gitlab/-/issues/325234).
+- Do not match up, this indicates a problem with the documents generated from the project. It is best to [re-index that project](../advanced_search/elasticsearch.md#indexing-a-range-of-projects-or-a-specific-project)
NOTE:
The above instructions are not to be used for scenarios that only index a [subset of namespaces](elasticsearch.md#limit-the-number-of-namespaces-and-projects-that-can-be-indexed).
See [Elasticsearch Index Scopes](elasticsearch.md#advanced-search-index-scopes) for more information on searching for specific types of data.
-## I indexed all the repositories but then switched Elasticsearch servers and now I can't find anything
+### I indexed all the repositories but then switched Elasticsearch servers and now I can't find anything
You must re-run all the Rake tasks to reindex the database, repositories, and wikis.
-## The indexing process is taking a very long time
+### The indexing process is taking a very long time
The more data present in your GitLab instance, the longer the indexing process takes.
-## There are some projects that weren't indexed, but I don't know which ones
+### There are some projects that weren't indexed, but I don't know which ones
You can run `sudo gitlab-rake gitlab:elastic:projects_not_indexed` to display projects that aren't indexed.
-## No new data is added to the Elasticsearch index when I push code
+### No new data is added to the Elasticsearch index when I push code
NOTE:
This was [fixed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35936) in GitLab 13.2 and the Rake task is not available for versions greater than that.
@@ -109,6 +184,116 @@ When performing the initial indexing of blobs, we lock all projects until the pr
sudo gitlab-rake gitlab:elastic:clear_locked_projects
```
+### Indexing fails with `error: elastic: Error 429 (Too Many Requests)`
+
+If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error during indexing, it usually means that Elasticsearch is unable to keep up with the concurrency of indexing request. To address change the following settings:
+
+- To decrease the indexing throughput you can decrease `Bulk request concurrency` (see [Advanced Search settings](elasticsearch.md#advanced-search-configuration)). This is set to `10` by default, but you change it to as low as 1 to reduce the number of concurrent indexing operations.
+- If changing `Bulk request concurrency` didn't help, you can use the [queue selector](../../administration/sidekiq/extra_sidekiq_processes.md#queue-selector) option to [limit indexing jobs only to specific Sidekiq nodes](elasticsearch.md#index-large-instances-with-dedicated-sidekiq-nodes-or-processes), which should reduce the number of indexing requests.
+
+### Indexing is very slow or fails with `rejected execution of coordinating operation` messages
+
+Bulk requests getting rejected by the Elasticsearch nodes are likely due to load and lack of available memory.
+Ensure that your Elasticsearch cluster meets the [system requirements](elasticsearch.md#system-requirements) and has enough resources
+to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests).
+
+### Last resort to recreate an index
+
+There may be cases where somehow data never got indexed and it's not in the
+queue, or the index is somehow in a state where migrations just cannot
+proceed. It is always best to try to troubleshoot the root cause of the problem
+by [viewing the logs](#view-logs).
+
+If there are no other options, then you always have the option of recreating the
+entire index from scratch. If you have a small GitLab installation, this can
+sometimes be a quick way to resolve a problem, but if you have a large GitLab
+installation, then this might take a very long time to complete. Until the
+index is fully recreated, your index does not serve correct search results,
+so you may want to disable **Search with Elasticsearch** while it is running.
+
+If you are sure you've read the above caveats and want to proceed, then you
+should run the following Rake task to recreate the entire index from scratch:
+
+**For Omnibus installations**
+
+```shell
+# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
+sudo gitlab-rake gitlab:elastic:index
+```
+
+**For installations from source**
+
+```shell
+# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
+cd /home/git/gitlab
+sudo -u git -H bundle exec rake gitlab:elastic:index
+```
+
+### Troubleshooting performance
+
+Troubleshooting performance can be difficult on Elasticsearch. There is a ton of tuning
+that *can* be done, but the majority of this falls on shoulders of a skilled
+Elasticsearch administrator.
+
+Generally speaking, ensure:
+
+- The Elasticsearch server **is not** running on the same node as GitLab.
+- The Elasticsearch server have enough RAM and CPU cores.
+- That sharding **is** being used.
+
+Going into some more detail here, if Elasticsearch is running on the same server as GitLab, resource contention is **very** likely to occur. Ideally, Elasticsearch, which requires ample resources, should be running on its own server (maybe coupled with Logstash and Kibana).
+
+When it comes to Elasticsearch, RAM is the key resource. Elasticsearch themselves recommend:
+
+- **At least** 8 GB of RAM for a non-production instance.
+- **At least** 16 GB of RAM for a production instance.
+- Ideally, 64 GB of RAM.
+
+For CPU, Elasticsearch recommends at least 2 CPU cores, but Elasticsearch states common
+setups use up to 8 cores. For more details on server specs, check out
+[Elasticsearch's hardware guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html).
+
+Beyond the obvious, sharding comes into play. Sharding is a core part of Elasticsearch.
+It allows for horizontal scaling of indices, which is helpful when you are dealing with
+a large amount of data.
+
+With the way GitLab does indexing, there is a **huge** amount of documents being
+indexed. By utilizing sharding, you can speed up Elasticsearch's ability to locate
+data, since each shard is a Lucene index.
+
+If you are not using sharding, you are likely to hit issues when you start using
+Elasticsearch in a production environment.
+
+Keep in mind that an index with only one shard has **no scale factor** and will
+likely encounter issues when called upon with some frequency.
+
+If you need to know how many shards, read
+[Elasticsearch's documentation on capacity planning](https://www.elastic.co/guide/en/elasticsearch/guide/2.x/capacity-planning.html),
+as the answer is not straight forward.
+
+The easiest way to determine if sharding is in use is to check the output of the
+[Elasticsearch Health API](https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html):
+
+- Red means the cluster is down.
+- Yellow means it is up with no sharding/replication.
+- Green means it is healthy (up, sharding, replicating).
+
+For production use, it should always be green.
+
+Beyond these steps, you get into some of the more complicated things to check,
+such as merges and caching. These can get complicated and it takes some time to
+learn them, so it is best to escalate/pair with an Elasticsearch expert if you need to
+dig further into these.
+
+Feel free to reach out to GitLab support, but this is likely to be something a skilled
+Elasticsearch administrator has more experience with.
+
+## Issues with migrations
+
+Please ensure you've read about [Elasticsearch Migrations](../advanced_search/elasticsearch.md#advanced-search-migrations).
+
+If there is a halted migration and your [`elasticsearch.log`](../../administration/logs/index.md#elasticsearchlog) file contain errors, this could potentially be a bug/issue. Escalate to GitLab support if retrying migrations does not succeed.
+
## `Can't specify parent if no parent field has been configured` error
If you enabled Elasticsearch before GitLab 8.12 and have not rebuilt indices, you get
@@ -146,6 +331,10 @@ This exception is seen when your Elasticsearch cluster is configured to reject r
AWS has [fixed limits](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/limits.html#network-limits) for this setting ("Maximum size of HTTP request payloads"), based on the size of the underlying instance.
+## `Faraday::TimeoutError (execution expired)` error when using a proxy
+
+Set a custom `gitlab_rails['env']` environment variable, called [`no_proxy`](https://docs.gitlab.com/omnibus/settings/environment-variables.html) with the IP address of your Elasticsearch host.
+
## My single node Elasticsearch cluster status never goes from `yellow` to `green` even though everything seems to be running properly
**For a single node Elasticsearch cluster the functional cluster health status is yellow** (never green) because the primary shard is allocated but replicas cannot be as there is no other node to which Elasticsearch can assign a replica. This also applies if you are using the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) service.
@@ -182,10 +371,6 @@ reason may be incompatible with our integration. You should try disabling
plugins so you can rule out the possibility that the plugin is causing the
problem.
-## Low-level troubleshooting
-
-There is a [more structured, lower-level troubleshooting document](../../administration/troubleshooting/elasticsearch.md) for when you experience other issues, including poor performance.
-
## Elasticsearch `code_analyzer` doesn't account for all code cases
The `code_analyzer` pattern and filter configuration is being evaluated for improvement. We have fixed [most edge cases](https://gitlab.com/groups/gitlab-org/-/epics/3621#note_363429094) that were not returning expected search results due to our pattern and filter configuration.
@@ -196,38 +381,6 @@ Improvements to the `code_analyzer` pattern and filters are being discussed in [
In GitLab 13.9, a change was made where [binary file names are being indexed](https://gitlab.com/gitlab-org/gitlab/-/issues/301083). However, without indexing all projects' data from scratch, only binary files that are added or updated after the GitLab 13.9 release are searchable.
-## Last resort to recreate an index
-
-There may be cases where somehow data never got indexed and it's not in the
-queue, or the index is somehow in a state where migrations just cannot
-proceed. It is always best to try to troubleshoot the root cause of the problem
-by [viewing the logs](#view-logs).
-
-If there are no other options, then you always have the option of recreating the
-entire index from scratch. If you have a small GitLab installation, this can
-sometimes be a quick way to resolve a problem, but if you have a large GitLab
-installation, then this might take a very long time to complete. Until the
-index is fully recreated, your index does not serve correct search results,
-so you may want to disable **Search with Elasticsearch** while it is running.
-
-If you are sure you've read the above caveats and want to proceed, then you
-should run the following Rake task to recreate the entire index from scratch:
-
-**For Omnibus installations**
-
-```shell
-# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
-sudo gitlab-rake gitlab:elastic:index
-```
-
-**For installations from source**
-
-```shell
-# WARNING: DO NOT RUN THIS UNTIL YOU READ THE DESCRIPTION ABOVE
-cd /home/git/gitlab
-sudo -u git -H bundle exec rake gitlab:elastic:index
-```
-
## How does Advanced Search handle private projects?
Advanced Search stores all the projects in the same Elasticsearch indices,
@@ -235,19 +388,6 @@ however, searches only surface results that can be viewed by the user.
Advanced Search honors all permission checks in the application by
filtering out projects that a user does not have access to at search time.
-## Indexing fails with `error: elastic: Error 429 (Too Many Requests)`
-
-If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error during indexing, it usually means that Elasticsearch is unable to keep up with the concurrency of indexing request. To address change the following settings:
-
-- To decrease the indexing throughput you can decrease `Bulk request concurrency` (see [Advanced Search settings](elasticsearch.md#advanced-search-configuration)). This is set to `10` by default, but you change it to as low as 1 to reduce the number of concurrent indexing operations.
-- If changing `Bulk request concurrency` didn't help, you can use the [queue selector](../../administration/operations/extra_sidekiq_processes.md#queue-selector) option to [limit indexing jobs only to specific Sidekiq nodes](elasticsearch.md#index-large-instances-with-dedicated-sidekiq-nodes-or-processes), which should reduce the number of indexing requests.
-
-## Indexing is very slow or fails with `rejected execution of coordinating operation` messages
-
-Bulk requests getting rejected by the Elasticsearch nodes are likely due to load and lack of available memory.
-Ensure that your Elasticsearch cluster meets the [system requirements](elasticsearch.md#system-requirements) and has enough resources
-to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests).
-
## Access requirements for the self-managed AWS OpenSearch Service
To use the self-managed AWS OpenSearch Service with GitLab, configure your instance's domain access policies
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index 515e7406545..da1aa574bd6 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -107,6 +107,24 @@ Alternatively, add the `User.Read.All` application permission.
]
```
+ For [alternative Azure clouds](https://docs.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
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "azure_activedirectory_v2",
+ "label" => "Provider name", # optional label for login button, defaults to "Azure AD v2"
+ "args" => {
+ "client_id" => "CLIENT ID",
+ "client_secret" => "CLIENT SECRET",
+ "tenant_id" => "TENANT ID",
+ "base_azure_url" => "https://login.microsoftonline.us"
+ }
+ }
+ ]
+ ```
+
- **For installations from source**
For the v1.0 endpoint:
@@ -115,8 +133,8 @@ 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_secret: 'CLIENT SECRET',
+ tenant_id: 'TENANT ID' } }
```
For the v2.0 endpoint:
@@ -125,14 +143,25 @@ 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_secret: "CLIENT SECRET",
+ tenant_id: "TENANT ID" } }
+ ```
+
+ For [alternative Azure clouds](https://docs.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",
+ base_azure_url: "https://login.microsoftonline.us" } }
```
- You can optionally add the following parameters:
+ In addition, you can optionally add the following parameters to the `args` section:
- - `base_azure_url` for different locales. For example, `base_azure_url: "https://login.microsoftonline.de"`.
- - `scope`, which you add to `args`. The default is `openid profile email`.
+ - `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`.
1. Save the configuration file.
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index a0cb6bd98cd..38305967246 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -4,7 +4,11 @@ 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
---
-# CAS OmniAuth Provider **(FREE SELF)**
+# CAS OmniAuth provider (deprecated) **(FREE SELF)**
+
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/369127) in GitLab 15.3 and is planned for
+removal in 16.0.
To enable the CAS OmniAuth provider you must register your application with your
CAS instance. This requires the service URL GitLab supplies to CAS. It should be
diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md
index a9be7754cb9..b8624545c41 100644
--- a/doc/integration/datadog.md
+++ b/doc/integration/datadog.md
@@ -33,8 +33,7 @@ project, group, or instance level:
1. Select **Active** to enable the integration.
1. Specify the [**Datadog site**](https://docs.datadoghq.com/getting_started/site/) to send data to.
1. Provide your Datadog **API key**.
-<!-- 1. Optional. Select **Enable logs collection** to enable logs collection for the output of jobs. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 14.8.) -->
-<!-- TODO: uncomment the archive_trace_events field once :datadog_integration_logs_collection is rolled out. Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/346339 -->
+1. Optional. Select **Enable logs collection** to enable logs collection for the output of jobs. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3.)
1. Optional. To override the API URL used to send data directly, provide an **API URL**.
Used only in advanced scenarios.
1. Optional. If you use more than one GitLab instance, provide a unique **Service** name
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 3011155f825..ad90c714dac 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -157,13 +157,29 @@ To fix this issue, you must disable SSL verification:
1. Change the global Git `sslVerify` option to `false` on the GitLab server.
- - **For Omnibus installations**
+ - **For Omnibus installations in [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later**:
+
+ ```ruby
+ gitaly['gitconfig'] = [
+ {key: "http.sslVerify", value: "false"},
+ ]
+ ```
+
+ - **For Omnibus installations in GitLab 15.2 and earlier (legacy method)**:
```ruby
omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
```
- - **For installations from source**
+ - **For installations from source in [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later**, edit the Gitaly configuration (`gitaly.toml`):
+
+ ```toml
+ [[git.config]]
+ key = "http.sslVerify"
+ value = "false"
+ ```
+
+ - **For installations from source in GitLab 15.2 and earlier (legacy method)**:
```shell
git config --global http.sslVerify false
@@ -180,7 +196,7 @@ GitLab instance and GitHub Enterprise.
To check for a connectivity issue:
-1. Go to the [`production.log`](../administration/logs.md#productionlog)
+1. Go to the [`production.log`](../administration/logs/index.md#productionlog)
on your GitLab server and look for the following error:
``` plaintext
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 02705d9dec3..fee1e573384 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -77,7 +77,7 @@ GitLab.com generates an application ID and secret key for you to use.
app_id: "YOUR_APP_ID",
app_secret: "YOUR_APP_SECRET",
args: { scope: "read_user" # optional: defaults to the scopes of the application
- , client_options: { site: "https://gitlab.example.com/api/v4" } }
+ , client_options: { site: "https://gitlab.example.com" } }
}
]
```
@@ -98,9 +98,13 @@ GitLab.com generates an application ID and secret key for you to use.
label: 'Provider name', # optional label for login button, defaults to "GitLab.com"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
- args: { "client_options": { "site": 'https://gitlab.example.com/api/v4' } }
+ args: { "client_options": { "site": 'https://gitlab.example.com' } }
```
+ NOTE:
+ In GitLab 15.1 and earlier, the `site` parameter requires an `/api/v4` suffix.
+ We recommend you drop this suffix after you upgrade to GitLab 15.2 or later.
+
1. Change `'YOUR_APP_ID'` to the Application ID from the GitLab.com application page.
1. Change `'YOUR_APP_SECRET'` to the secret from the GitLab.com application page.
1. Save the configuration file.
diff --git a/doc/integration/img/jenkins_gitlab_service.png b/doc/integration/img/jenkins_gitlab_service.png
deleted file mode 100644
index 682a5ae8ee2..00000000000
--- a/doc/integration/img/jenkins_gitlab_service.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/jenkins_project.png b/doc/integration/img/jenkins_project.png
deleted file mode 100644
index 126b05c8879..00000000000
--- a/doc/integration/img/jenkins_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/img/omniauth_providers_v_14_6.png b/doc/integration/img/omniauth_providers_v_14_6.png
deleted file mode 100644
index b434e9a210b..00000000000
--- a/doc/integration/img/omniauth_providers_v_14_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/index.md b/doc/integration/index.md
index 85ebac5b40c..f5b088b47f7 100644
--- a/doc/integration/index.md
+++ b/doc/integration/index.md
@@ -20,7 +20,6 @@ GitLab can be configured to authenticate access requests with the following auth
- Enable the [Auth0 OmniAuth](auth0.md) provider.
- Enable sign in with [Bitbucket](bitbucket.md) accounts.
-- Configure GitLab to sign in using [CAS](cas.md).
- Integrate with [Kerberos](kerberos.md).
- Enable sign in via [LDAP](../administration/auth/ldap/index.md).
- Enable [OAuth2 provider](oauth_provider.md) application creation.
diff --git a/doc/integration/jenkins_deprecated.md b/doc/integration/jenkins_deprecated.md
index 57219b18047..5010545b73a 100644
--- a/doc/integration/jenkins_deprecated.md
+++ b/doc/integration/jenkins_deprecated.md
@@ -2,62 +2,12 @@
stage: Ecosystem
group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+remove_date: '2022-10-29'
+redirect_to: 'jenkins.md'
---
-# Jenkins CI (deprecated) service **(FREE)**
+# Jenkins CI service (removed) **(FREE)**
-NOTE:
-In GitLab 8.3, Jenkins integration using the
-[GitLab Hook Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
-was deprecated in favor of the
-[GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin).
-Please use documentation for the new [Jenkins CI service](jenkins.md).
-
-NOTE:
-This service was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/1600) in GitLab 13.0
-
-Integration includes:
-
-- Trigger Jenkins build after push to repository
-- Show build status on Merge request page
-
-Requirements:
-
-- [Jenkins GitLab Hook plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
-- Git clone access for Jenkins from GitLab repository (via SSH key)
-
-## Jenkins
-
-1. Install [GitLab Hook plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Hook+Plugin)
-1. Set up Jenkins project
-
-![screen](img/jenkins_project.png)
-
-## GitLab
-
-In GitLab, perform the following steps.
-
-### Read access to repository
-
-Jenkins needs read access to the GitLab repository. We already specified a
-private key to use in Jenkins, now we must add a public one to the GitLab
-project. For that case we need a Deploy key. Read the documentation on
-[how to set up a Deploy key](../user/project/deploy_keys/index.md).
-
-### Jenkins service
-
-Now navigate to GitLab services page and activate Jenkins
-
-![screen](img/jenkins_gitlab_service.png)
-
-Done! When you push to GitLab, it creates a build for Jenkins. You can view the
-merge request build status with a link to the Jenkins build.
-
-### Multi-project Configuration
-
-The GitLab Hook plugin in Jenkins supports the automatic creation of a project
-for each feature branch. After configuration GitLab triggers feature branch
-builds and a corresponding project is created in Jenkins.
-
-Configure the GitLab Hook plugin in Jenkins. Go to 'Manage Jenkins' and then
-'Configure System'. Find the 'GitLab Web Hook' section and configure as shown below.
+This feature was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/1600)
+in GitLab 13.0.
+Use the [Jenkins integration](jenkins.md) instead.
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index d35c21f6187..43a5349e0e5 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -261,7 +261,7 @@ resynchronize the information:
- To complete a *full sync*, press `Shift` and select the sync icon.
For more information, read
-[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
+[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/integrate-with-development-tools/).
### `Sync Failed` error when refreshing repository data
diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 1a60ca3a5fe..3293732b59b 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -229,53 +229,60 @@ sudo gitlab-ctl start mattermost
### Mattermost Command Line Tools (CLI)
-NOTE:
-This CLI will be replaced in a future release with the new [`mmctl` Command Line Tool](https://docs.mattermost.com/manage/mmctl-command-line-tool.html).
+[`mmctl`](https://docs.mattermost.com/manage/mmctl-command-line-tool.html) is a CLI tool for the Mattermost server which is installed locally and uses the Mattermost API, but may also be used remotely. You must configure Mattermost either for local connections or authenticate as an administrator with local login credentials (not through GitLab SSO). The executable is located at `/opt/gitlab/embedded/bin/mmctl`.
-To use the [Mattermost Command Line Tools (CLI)](https://docs.mattermost.com/administration/command-line-tools.html), ensure that you are in the `/opt/gitlab/embedded/service/mattermost` directory when you run the CLI commands and that you specify the location of the configuration file. The executable is `/opt/gitlab/embedded/bin/mattermost`.
+#### Use `mmctl` through a local connection
-```shell
-cd /opt/gitlab/embedded/service/mattermost
+For local connections, the `mmctl` binary and Mattermost must be run from the same server. To enable the local socket:
-sudo /opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/mattermost/env -P -U mattermost:mattermost -u mattermost:mattermost /opt/gitlab/embedded/bin/mattermost --config=/var/opt/gitlab/mattermost/config.json version
-```
+1. Edit `/var/opt/gitlab/mattermost/config.json`, and add the following lines:
+
+ ```json
+ {
+ "ServiceSettings": {
+ ...
+ "EnableLocalMode": true,
+ "LocalModeSocketLocation": "/var/tmp/mattermost_local.socket",
+ ...
+ }
+ }
+ ```
+
+1. Restart Mattermost:
+
+ ```shell
+ sudo gitlab-ctl restart mattermost
+ ```
-Until [#4745](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4745) has been implemented, the command requires quite of bit typing and is hard to remember, so let's make a bash or Zsh alias to make it a bit easier to remember. Add the following to your `~/.bashrc` or `~/.zshrc` file:
+You can then use `/opt/gitlab/embedded/bin/mmctl --local` to run `mmctl` commands
+on your Mattermost instance.
+
+For example, to show the list of users:
```shell
-alias mattermost-cli="cd /opt/gitlab/embedded/service/mattermost && sudo /opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/mattermost/env -P -U mattermost:mattermost -u mattermost:mattermost /opt/gitlab/embedded/bin/mattermost --config=/var/opt/gitlab/mattermost/config.json $1"
+$ /opt/gitlab/embedded/bin/mmctl --local user list
+
+13dzo5bmg7fu8rdox347hbfxde: appsbot (appsbot@localhost)
+tbnkwjdug3dejcoddboo4yuomr: boards (boards@localhost)
+wd3g5zpepjgbfjgpdjaas7yj6a: feedbackbot (feedbackbot@localhost)
+8d3zzgpurp85zgf1q88pef73eo: playbooks (playbooks@localhost)
+There are 4 users on local instance
```
-Then source `~/.zshrc` or `~/.bashrc` with `source ~/.zshrc` or `source ~/.bashrc`.
+#### Use `mmctl` through a remote connection
-If successful, you can now run any Mattermost CLI command with your new shell alias `mattermost-cli`:
+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
+can then be used to authenticate `mmctl`:
```shell
-$ mattermost-cli version
-
-[sudo] password for username:
-{"level":"info","ts":1569614421.9058893,"caller":"utils/i18n.go:83","msg":"Loaded system translations for 'en' from '/opt/gitlab/embedded/service/mattermost/i18n/en.json'"}
-{"level":"info","ts":1569614421.9062793,"caller":"app/server_app_adapters.go:58","msg":"Server is initializing..."}
-{"level":"info","ts":1569614421.90976,"caller":"sqlstore/supplier.go:223","msg":"Pinging SQL master database"}
-{"level":"info","ts":1569614422.0515099,"caller":"mlog/log.go:165","msg":"Starting up plugins"}
-{"level":"info","ts":1569614422.0515954,"caller":"app/plugin.go:193","msg":"Syncing plugins from the file store"}
-{"level":"info","ts":1569614422.086005,"caller":"app/plugin.go:228","msg":"Found no files in plugins file store"}
-{"level":"info","ts":1569614423.9337213,"caller":"sqlstore/post_store.go:1301","msg":"Post.Message supports at most 16383 characters (65535 bytes)"}
-{"level":"error","ts":1569614425.6317747,"caller":"go-plugin/stream.go:15","msg":" call to OnConfigurationChange failed, error: Must have a GitLab oauth client id","plugin_id":"com.github.manland.mattermost-plugin-gitlab","source":"plugin_stderr"}
-{"level":"info","ts":1569614425.6875598,"caller":"mlog/sugar.go:19","msg":"Ensuring Surveybot exists","plugin_id":"com.mattermost.nps"}
-{"level":"info","ts":1569614425.6953356,"caller":"app/server.go:216","msg":"Current version is 5.14.0 (5.14.2/Fri Aug 30 20:20:48 UTC 2019/817ee89711bf26d33f840ce7f59fba14da1ed168/none)"}
-{"level":"info","ts":1569614425.6953766,"caller":"app/server.go:217","msg":"Enterprise Enabled: false"}
-{"level":"info","ts":1569614425.6954057,"caller":"app/server.go:219","msg":"Current working directory is /opt/gitlab/embedded/service/mattermost/i18n"}
-{"level":"info","ts":1569614425.6954265,"caller":"app/server.go:220","msg":"Loaded config","source":"file:///var/opt/gitlab/mattermost/config.json"}
-Version: 5.14.0
-Build Number: 5.14.2
-Build Date: Fri Aug 30 20:20:48 UTC 2019
-Build Hash: 817ee89711bf26d33f840ce7f59fba14da1ed168
-Build Enterprise Ready: false
-DB Version: 5.14.0
-```
+$ /opt/gitlab/embedded/bin/mmctl auth login http://mattermost.example.com
-For more details see [Mattermost Command Line Tools (CLI)](https://docs.mattermost.com/administration/command-line-tools.html) and the [Troubleshooting Mattermost CLI](#troubleshooting-the-mattermost-cli) below.
+Connection name: test
+Username: local-user
+Password:
+ credentials for "test": "local-user@http://mattermost.example.com" stored
+```
## Configuring GitLab and Mattermost integrations
@@ -440,8 +447,7 @@ mattermost['env'] = {
}
```
-Refer to the [Mattermost Configuration Settings
-documentation](https://docs.mattermost.com/administration/config-settings.html)
+Refer to the [Mattermost Configuration Settings documentation](https://docs.mattermost.com/administration/config-settings.html)
for details about categories and configuration values.
There are a few exceptions to this rule:
@@ -512,14 +518,6 @@ sequenceDiagram
Mattermost->>User: Mattermost/GitLab user ready
```
-## Troubleshooting the Mattermost CLI
-
-### Failed to ping DB retrying in 10 seconds err=dial tcp: lookup dockerhost: no such host
-
-As of version 11.0, majority of the Mattermost settings are now configured via environmental variables. The error is mainly due to the database connection string being commented out in `gitlab.rb` and the database connection settings being set in environmental variables. Additionally, the connection string in the `gitlab.rb` is for MySQL which is no longer supported as of 12.1.
-
-You can fix this by setting up a `mattermost-cli` [shell alias](#mattermost-command-line-tools-cli).
-
## Community support resources
For help and support around your GitLab Mattermost deployment please see:
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index aac2820a69e..e297c13a2da 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -7,13 +7,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# OmniAuth **(FREE SELF)**
Users can sign in to GitLab by using their credentials from Twitter, GitHub, and other popular services.
-[OmniAuth](https://rubygems.org/gems/omniauth/) is the Rack
-framework that GitLab uses to provide this authentication.
+[OmniAuth](https://rubygems.org/gems/omniauth/) is the Rack framework that GitLab uses to provide this authentication.
-![OmniAuth providers on sign-in page](img/omniauth_providers_v_14_6.png)
-
-If you configure OmniAuth, users can continue to sign in using other
-mechanisms, including standard GitLab authentication or LDAP (if configured).
+When configured, additional sign-in options are displayed on the sign-in page.
## Supported providers
@@ -22,7 +18,6 @@ GitLab supports the following OmniAuth providers.
| Provider documentation | OmniAuth provider name |
|---------------------------------------------------------------------|----------------------------|
| [AliCloud](alicloud.md) | `alicloud` |
-| [Atlassian Crowd](../administration/auth/crowd.md) | `crowd` |
| [Atlassian](../administration/auth/atlassian.md) | `atlassian_oauth2` |
| [Auth0](auth0.md) | `auth0` |
| [Authentiq](../administration/auth/authentiq.md) | `authentiq` |
@@ -30,7 +25,6 @@ GitLab supports the following OmniAuth providers.
| [Azure v2](azure.md) | `azure_activedirectory_v2` |
| [Azure v1](azure.md) | `azure_oauth2` |
| [Bitbucket Cloud](bitbucket.md) | `bitbucket` |
-| [CAS](cas.md) | `cas3` |
| [DingTalk](ding_talk.md) | `dingtalk` |
| [Facebook](facebook.md) | `facebook` |
| [Generic OAuth 2.0](oauth2_generic.md) | `oauth2_generic` |
@@ -53,7 +47,7 @@ Setting | Description | Default value
---------------------------|-------------|--------------
`allow_single_sign_on` | Enables you to list the providers that automatically create a GitLab account. The provider names are available in the **OmniAuth provider name** column in the [supported providers table](#supported-providers). | The default is `false`. If `false`, users must be created manually, or they can't sign in using OmniAuth.
`auto_link_ldap_user` | If enabled, creates an LDAP identity in GitLab for users that are created through an OmniAuth provider. You can enable this setting if you have the [LDAP (ActiveDirectory)](../administration/auth/ldap/index.md) integration enabled. Requires the `uid` of the user to be the same in both LDAP and the OmniAuth provider. | The default is `false`.
-`block_auto_created_users` | If enabled, blocks users that are automatically created from signing in until they are approved by an administrator. | The default is `true`. If you set the value to `false`, make sure you only define providers for `allow_single_sign_on` that you can control, like SAML, Crowd, or Google. Otherwise, any user on the internet can sign in to GitLab without an administrator's approval.
+`block_auto_created_users` | If enabled, blocks users that are automatically created from signing in until they are approved by an administrator. | The default is `true`. If you set the value to `false`, make sure you only define providers for `allow_single_sign_on` that you can control, like SAML or Google. Otherwise, any user on the internet can sign in to GitLab without an administrator's approval.
To change these settings:
@@ -111,6 +105,65 @@ To change these settings:
After configuring these settings, you can configure
your chosen [provider](#supported-providers).
+### Per-provider configuration
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89379) in GitLab 15.3.
+
+If `allow_single_sign_on` is set, GitLab uses one of the following fields returned in the OmniAuth `auth_hash` to establish a username in GitLab for the user signing in,
+choosing the first that exists:
+
+- `username`.
+- `nickname`.
+- `email`.
+
+You can create GitLab configuration on a per-provider basis, which is supplied to the [provider](#supported-providers) using `args`. If you set the `gitlab_username_claim`
+variable in `args` for a provider, you can select another claim to use for the GitLab username. The chosen claim must be unique to avoid collisions.
+
+- **For Omnibus installations**
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+
+ # The generic pattern for configuring a provider with name PROVIDER_NAME
+
+ gitlab_rails['omniauth_providers'] = {
+ name: "PROVIDER_NAME"
+ ...
+ args: { gitlab_username_claim: 'sub' } # For users signing in with the provider you configure, the GitLab username will be set to the "sub" received from the provider
+ },
+
+ # Here are examples using GitHub and Kerberos
+
+ gitlab_rails['omniauth_providers'] = {
+ name: "github"
+ ...
+ args: { gitlab_username_claim: 'name' } # For users signing in with GitHub, the GitLab username will be set to the "name" received from GitHub
+ },
+ {
+ name: "kerberos"
+ ...
+ args: { gitlab_username_claim: 'uid' } # For users signing in with Kerberos, the GitLab username will be set to the "uid" received from Kerberos
+ },
+ ]
+ ```
+
+- **For installations from source**
+
+ ```yaml
+ - { name: 'PROVIDER_NAME',
+ ...
+ args: { gitlab_username_claim: 'sub' }
+ }
+ - { name: 'github',
+ ...
+ args: { gitlab_username_claim: 'name' }
+ }
+ - { name: 'kerberos',
+ ...
+ args: { gitlab_username_claim: 'uid' }
+ }
+ ```
+
### Passwords for users created via OmniAuth
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md)
@@ -387,5 +440,4 @@ then override the icon in one of two ways:
## Limitations
Most supported OmniAuth providers don't support Git over HTTP password authentication.
-The only exception is [Atlassian Crowd](../administration/auth/crowd.md) (since GitLab [13.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46935)).
As a workaround, you can authenticate using a [personal access token](../user/profile/personal_access_tokens.md).
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 9f707ba9bc6..0c517d07f41 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -709,7 +709,6 @@ args: {
security: {
authn_requests_signed: true, # enable signature on AuthNRequest
want_assertions_signed: true, # enable the requirement of signed assertion
- embed_sign: true, # embedded signature or HTTP GET parameter signature
metadata_signed: false, # enable signature on Metadata
signature_method: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
digest_method: 'http://www.w3.org/2001/04/xmlenc#sha256',
@@ -756,7 +755,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende
[instance-wide SAML](../user/group/saml_sso/index.md). The recommended solution allows you to take advantage of:
- [LDAP compatibility](../administration/auth/ldap/index.md).
-- [LDAP Group Sync](../user/group/index.md#manage-group-memberships-via-ldap).
+- [LDAP Group Sync](../user/group/access_and_permissions.md#manage-group-memberships-via-ldap).
- [Required groups](#required-groups).
- [Administrator groups](#administrator-groups).
- [Auditor groups](#auditor-groups).
@@ -801,8 +800,6 @@ If you have any questions on configuring the SAML app, please contact your provi
### Okta setup notes
-The following guidance is based on this Okta article, on adding a [SAML Application with an Okta Developer account](https://support.okta.com/help/s/article/Why-can-t-I-add-a-SAML-Application-with-an-Okta-Developer-account?language=en_US):
-
1. In the Okta administrator section, make sure to select Classic UI view in the top left corner. From there, choose to **Add an App**.
1. When the app screen comes up you see another button to **Create an App** and
choose SAML 2.0 on the next screen.
@@ -864,7 +861,7 @@ connect to the Google Workspace SAML app.
### SAML Response
-You can find the base64-encoded SAML Response in the [`production_json.log`](../administration/logs.md#production_jsonlog). This response is sent from the IdP, and contains user information that is consumed by GitLab. Many errors in the SAML integration can be solved by decoding this response and comparing it to the SAML settings in the GitLab configuration file.
+You can find the base64-encoded SAML Response in the [`production_json.log`](../administration/logs/index.md#production_jsonlog). This response is sent from the IdP, and contains user information that is consumed by GitLab. Many errors in the SAML integration can be solved by decoding this response and comparing it to the SAML settings in the GitLab configuration file.
### GitLab+SAML Testing Environments
@@ -907,7 +904,7 @@ the SAML request, but in GitLab 11.7 and earlier this error never reaches GitLab
the CSRF check.
To bypass this you can add `skip_before_action :verify_authenticity_token` to the
-`omniauth_callbacks_controller.rb` file immediately after the `class` line and
+`omniauth_callbacks_controller.rb` file immediately before the `after_action :verify_known_sign_in` line and
comment out the `protect_from_forgery` line using a `#`. Restart Puma for this
change to take effect. This allows the error to hit GitLab, where it can then
be seen in the usual logs, or as a flash message on the login screen.
@@ -941,8 +938,8 @@ Make sure this information is provided.
Another issue that can result in this error is when the correct information is being sent by
the IdP, but the attributes don't match the names in the OmniAuth `info` hash. In this case,
-you must set `attribute_statements` in the SAML configuration to [map the attribute names in
-your SAML Response to the corresponding OmniAuth `info` hash names](#attribute_statements).
+you must set `attribute_statements` in the SAML configuration to
+[map the attribute names in your SAML Response to the corresponding OmniAuth `info` hash names](#attribute_statements).
### Key validation error, Digest mismatch or Fingerprint mismatch
diff --git a/doc/integration/security_partners/index.md b/doc/integration/security_partners/index.md
index 50a7b3b717b..507157f9326 100644
--- a/doc/integration/security_partners/index.md
+++ b/doc/integration/security_partners/index.md
@@ -12,18 +12,18 @@ each security partner:
<!-- vale gitlab.Spelling = NO -->
-- [Anchore](https://docs.anchore.com/current/docs/using/integration/ci_cd/gitlab/)
+- [Anchore](https://docs.anchore.com/current/docs/configuration/integration/ci_cd/gitlab/)
- [Bridgecrew](https://docs.bridgecrew.io/docs/integrate-with-gitlab-self-managed)
- [Checkmarx](https://checkmarx.atlassian.net/wiki/spaces/SD/pages/1929937052/GitLab+Integration)
- [Deepfactor](https://docs.deepfactor.io/hc/en-us/articles/1500008981941)
- [GrammaTech](https://www.grammatech.com/codesonar-gitlab-integration)
- [Indeni](https://docs.cloudrail.app/#/integrations/gitlab)
- [JScrambler](https://docs.jscrambler.com/code-integrity/documentation/gitlab-ci-integration)
+- [Mend](https://www.mend.io/gitlab/)
- [Semgrep](https://semgrep.dev/for/gitlab)
- [StackHawk](https://docs.stackhawk.com/continuous-integration/gitlab.html)
- [Tenable](https://docs.tenable.com/tenableio/Content/ContainerSecurity/GetStarted.htm)
- [Venafi](https://marketplace.venafi.com/details/gitlab-ci-cd/)
- [Veracode](https://community.veracode.com/s/knowledgeitem/gitlab-ci-MCEKSYPRWL35BRTGOVI55SK5RI4A)
-- [WhiteSource](https://www.whitesourcesoftware.com/gitlab/)
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index f3b66f8c12d..2218529a729 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -12,7 +12,7 @@ Twitter OAuth 2.0 support is [not yet supported](https://gitlab.com/gitlab-org/g
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.
-1. Sign in to [Twitter Application Management](https://apps.twitter.com).
+1. Sign in to [Twitter Application Management](https://developer.twitter.com/apps).
1. Select "Create new app".
diff --git a/doc/operations/incident_management/img/linked_resources_list_v15_3.png b/doc/operations/incident_management/img/linked_resources_list_v15_3.png
new file mode 100644
index 00000000000..2a7b56391a4
--- /dev/null
+++ b/doc/operations/incident_management/img/linked_resources_list_v15_3.png
Binary files differ
diff --git a/doc/operations/incident_management/img/timeline_events_v15_1.png b/doc/operations/incident_management/img/timeline_events_v15_1.png
index 3241f35764c..67bc727bc22 100644
--- a/doc/operations/incident_management/img/timeline_events_v15_1.png
+++ b/doc/operations/incident_management/img/timeline_events_v15_1.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index f1628cb64ca..c1a4c1eb93e 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -13,7 +13,7 @@ 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
+## Incident creation
You can create an incident manually or automatically.
@@ -205,10 +205,10 @@ field populated.
### 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 on GitLab.com. Disabled on self-managed.
+> [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 not available. To make it available, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `incident_timeline`.
+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.
Incident timelines are an important part of record keeping for incidents.
@@ -297,7 +297,7 @@ as a column in the Incidents List, and as a field on newly created Incidents. If
the incident isn't closed before the SLA period ends, GitLab adds a `missed::SLA`
label to the incident.
-## Incident Actions
+## Incident actions
There are different actions available to help triage and respond to incidents.
@@ -376,6 +376,15 @@ for synchronous communication during incident management. After starting a Zoom
call for an incident, you can associate the conference call with an issue. Your
team members can join the Zoom call without requesting a link.
+### Linked resources
+
+In an incident, you can [links to various resources](linked_resources.md),
+for example:
+
+- The incident Slack channel
+- Zoom meeting
+- Resources for resolving the incidents
+
### Embed metrics in incidents
You can embed metrics anywhere [GitLab Markdown](../../user/markdown.md) is
diff --git a/doc/operations/incident_management/linked_resources.md b/doc/operations/incident_management/linked_resources.md
new file mode 100644
index 00000000000..d2254a30f91
--- /dev/null
+++ b/doc/operations/incident_management/linked_resources.md
@@ -0,0 +1,66 @@
+---
+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
+---
+
+# Linked resources in incidents **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230852) in GitLab 15.3 [with a flag](../../administration/feature_flags.md) named `incident_resource_links_widget`. Enabled on GitLab.com. Disabled on self-managed.
+
+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 `incident_resource_links_widget`.
+On GitLab.com, this feature is available.
+
+To help your team members find the important links without having to search through many comments,
+you can add linked resources to an incident issue.
+
+Resources you might want link to:
+
+- Zoom meetings
+- Slack channels or threads
+- Google Docs
+
+## View linked resources of an incident
+
+Linked resources for an incident are listed under the **Summary** tab.
+
+![Linked resources list](img/linked_resources_list_v15_3.png)
+
+To view the linked resources of an incident:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Monitor > Incidents**.
+1. Select an incident.
+
+## Add a linked resource
+
+Add a linked resource manually from an incident.
+
+Prerequisites:
+
+- You must have at least the Reporter role for the project.
+
+To add a linked resource:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Monitor > Incidents**.
+1. Select an incident.
+1. In the **Linked resources** section, select the plus icon (**{plus-square}**).
+1. Complete the required fields.
+1. Select **Add**.
+
+## Remove a linked resource
+
+You can also remove a linked resource.
+
+Prerequisities:
+
+- You must have at least the Reporter role for the project.
+
+To remove a linked resource:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Monitor > Incidents**.
+1. Select an incident.
+1. In the **Linked resources** section, select **Remove** (**{close}**).
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 2229ba22be7..17ff0ff01a3 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -14,8 +14,8 @@ embed Grafana panels using either:
## Use Grafana-rendered images
-You can embed live [Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html) panels as a
-[direct linked rendered image](https://grafana.com/docs/grafana/latest/reference/share_panel/#direct-link-rendered-image).
+You can embed live [Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html) panels as
+[a direct link](https://grafana.com/docs/grafana/v7.5/sharing/share-panel/#use-direct-link).
Your Grafana instance must:
- Be available to the target user, either as a public dashboard or on the same network.
@@ -46,7 +46,7 @@ format. To embed panels from a Grafana instance, the data source must be:
To set up the Grafana API in Grafana:
-1. In Grafana, [generate an Admin-level API Token](https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-token).
+1. In Grafana, [generate an Admin-level API Token](https://grafana.com/docs/grafana/next/developers/http_api/auth/#create-api-token).
1. In your GitLab project, go to **Settings > Monitor** and expand the **Grafana authentication**
section.
1. To enable the integration, check the **Active** checkbox.
diff --git a/doc/policy/alpha-beta-support.md b/doc/policy/alpha-beta-support.md
index 45f14e4f9a2..6b0bd66041e 100644
--- a/doc/policy/alpha-beta-support.md
+++ b/doc/policy/alpha-beta-support.md
@@ -4,7 +4,7 @@ group: Distribution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-<!-- any changes made to this page should be reflected in https://about.gitlab.com/support/statement-of-support.html#alpha--beta-features and https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga -->
+<!-- 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 -->
# Support for Alpha, Beta, Limited Availability, and Generally Available Features **(PREMIUM)**
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index e831303988b..e77a0459150 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -16,8 +16,8 @@ Our current policy is:
- Backporting security fixes **to the previous two monthly releases in addition to the current stable release**. (See [security releases](#security-releases).)
In rare cases, release managers may make an exception and backport to more than
-the last two monthly releases. See [Backporting to older
-releases](#backporting-to-older-releases) for more information.
+the last two monthly releases. See
+[Backporting to older releases](#backporting-to-older-releases) for more information.
## Versioning
diff --git a/doc/raketasks/backup_gitlab.md b/doc/raketasks/backup_gitlab.md
index 8d5ae14a043..4629364ce3d 100644
--- a/doc/raketasks/backup_gitlab.md
+++ b/doc/raketasks/backup_gitlab.md
@@ -452,8 +452,9 @@ gitlab_rails['backup_upload_storage_options'] = {
##### SSE-KMS
-To enable SSE-KMS, you'll need the [KMS key via its Amazon Resource Name (ARN)
-in the `arn:aws:kms:region:acct-id:key/key-id` format](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html). Under the `backup_upload_storage_options` configuration setting, set:
+To enable SSE-KMS, you'll need the
+[KMS key via its Amazon Resource Name (ARN) in the `arn:aws:kms:region:acct-id:key/key-id` format](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html).
+Under the `backup_upload_storage_options` configuration setting, set:
- `server_side_encryption` to `aws:kms`.
- `server_side_encryption_kms_key_id` to the ARN of the key.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 33917ca9410..878511b3e14 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -12,8 +12,8 @@ An application data backup creates an archive file that contains the database,
all repositories and all attachments.
You can only restore a backup to **exactly the same version and type (CE/EE)**
-of GitLab on which it was created. The best way to [migrate your projects
-from one server to another](#migrate-to-a-new-server) is through a backup and restore.
+of GitLab on which it was created. The best way to
+[migrate your projects from one server to another](#migrate-to-a-new-server) is through a backup and restore.
WARNING:
GitLab doesn't back up items that aren't stored on the file system. If you're
@@ -184,14 +184,14 @@ ActiveRecord::StatementInvalid: PG::UndefinedTable
```
Each time the GitLab backup runs, GitLab starts generating 500 errors and errors about missing
-tables will [be logged by PostgreSQL](../administration/logs.md#postgresql-logs):
+tables will [be logged by PostgreSQL](../administration/logs/index.md#postgresql-logs):
```plaintext
ERROR: relation "tablename" does not exist at character 123
```
-This happens because the task uses `pg_dump`, which [sets a null search
-path and explicitly includes the schema in every SQL query](https://gitlab.com/gitlab-org/gitlab/-/issues/23211)
+This happens because the task uses `pg_dump`, which
+[sets a null search path and explicitly includes the schema in every SQL query](https://gitlab.com/gitlab-org/gitlab/-/issues/23211)
to address [CVE-2018-1058](https://www.postgresql.org/about/news/postgresql-103-968-9512-9417-and-9322-released-1834/).
Since connections are reused with PgBouncer in transaction pooling mode,
@@ -266,7 +266,7 @@ To prepare the new server:
[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079)
from the old server to avoid man-in-the-middle attack warnings.
See [Manually replicate the primary site's SSH host keys](../administration/geo/replication/configuration.md#step-2-manually-replicate-the-primary-sites-ssh-host-keys) for example steps.
-1. [Install and configure GitLab](https://about.gitlab.com/install) except
+1. [Install and configure GitLab](https://about.gitlab.com/install/) except
[incoming email](../administration/incoming_email.md):
1. Install GitLab.
1. Configure by copying `/etc/gitlab` files from the old server to the new server, and update as necessary.
@@ -775,7 +775,7 @@ Truncating filenames to resolve the error involves:
#### Clean up remote uploaded files
-A [known issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/45425) caused object store uploads to remain after a parent resource was deleted. This issue was [resolved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18698).
+A [known issue](https://gitlab.com/gitlab-org/gitlab-foss/issues/45425) caused object store uploads to remain after a parent resource was deleted. This issue was [resolved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18698).
To fix these files, you must clean up all remote uploaded files that are in the storage but not tracked in the `uploads` database table.
diff --git a/doc/raketasks/sidekiq_job_migration.md b/doc/raketasks/sidekiq_job_migration.md
index a3bc8b2959a..45a0cbaa267 100644
--- a/doc/raketasks/sidekiq_job_migration.md
+++ b/doc/raketasks/sidekiq_job_migration.md
@@ -1,40 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../administration/sidekiq/sidekiq_job_migration.md'
+remove_date: '2022-11-11'
---
-# Sidekiq job migration **(FREE SELF)**
+This document was moved to [another location](../administration/sidekiq/sidekiq_job_migration.md).
-WARNING:
-This operation should be very uncommon. We do not recommend it for the vast majority of GitLab instances.
-
-Sidekiq routing rules allow administrators to re-route certain background jobs from their regular queue to an alternative queue. By default, GitLab uses one queue per background job type. GitLab has over 400 background job types, and so correspondingly it has over 400 queues.
-
-Most administrators do not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to.
-
-If the Sidekiq routing rules are changed, administrators need to take care with the migration to avoid losing jobs entirely. The basic migration steps are:
-
-1. Listen to both the old and new queues.
-1. Update the routing rules.
-1. Wait until there are no publishers dispatching jobs to the old queues.
-1. Run the [Rake tasks for future jobs](#future-jobs).
-1. Wait for the old queues to be empty.
-1. Stop listening to the old queues.
-
-## Future jobs
-
-Step 4 involves rewriting some Sidekiq job data for jobs that are already stored in Redis, but due to run in future. There are two sets of jobs to run in future: scheduled jobs and jobs to be retried. We provide a separate Rake task to migrate each set:
-
-- `gitlab:sidekiq:migrate_jobs:retry` for jobs to be retried.
-- `gitlab:sidekiq:migrate_jobs:scheduled` for scheduled jobs.
-
-Most of the time, running both at the same time is the correct choice. There are two separate tasks to allow for more fine-grained control where needed. To run both at once:
-
-```shell
-# omnibus-gitlab
-sudo gitlab-rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule
-
-# source installations
-bundle exec rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule RAILS_ENV=production
-```
+<!-- This redirect file can be deleted after <2022-11-11>. -->
+<!-- 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/raketasks/spdx.md b/doc/raketasks/spdx.md
index 18f058f695e..81da52bc327 100644
--- a/doc/raketasks/spdx.md
+++ b/doc/raketasks/spdx.md
@@ -19,6 +19,6 @@ sudo gitlab-rake gitlab:spdx:import
bundle exec rake gitlab:spdx:import RAILS_ENV=production
```
-To perform this task in the [offline environment](../user/application_security/offline_deployments/#defining-offline-environments),
+To perform this task in the [offline environment](../user/application_security/offline_deployments/index.md#defining-offline-environments),
an outbound connection to [`licenses.json`](https://spdx.org/licenses/licenses.json) should be
allowed.
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
index 7956e692887..5a6578f218b 100644
--- a/doc/security/crime_vulnerability.md
+++ b/doc/security/crime_vulnerability.md
@@ -32,7 +32,7 @@ Although SPDY is enabled in Omnibus installations, CRIME relies on compression
## Nessus
-The Nessus scanner, [reports a possible CRIME vulnerability](https://www.tenable.com/plugins/index.php?view=single&id=62565) in GitLab
+The Nessus scanner, [reports a possible CRIME vulnerability](https://www.tenable.com/plugins/nessus/62565) in GitLab
similar to the following format:
```plaintext
@@ -59,7 +59,7 @@ vulnerability.
## References
- NGINX ["Module `ngx_http_spdy_module`"](https://nginx.org/en/docs/http/ngx_http_spdy_module.html)
-- Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"](https://www.tenable.com/plugins/index.php?view=single&id=62565)
+- Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"](https://www.tenable.com/plugins/nessus/62565)
- Wikipedia contributors, ["CRIME"](https://en.wikipedia.org/wiki/CRIME) Wikipedia, The Free Encyclopedia
<!-- ## Troubleshooting
diff --git a/doc/security/index.md b/doc/security/index.md
index 73ac5028db5..9e05621333b 100644
--- a/doc/security/index.md
+++ b/doc/security/index.md
@@ -28,8 +28,6 @@ type: index
- [Project Import decompressed archive size limits](project_import_decompressed_archive_size_limits.md)
- [Responding to security incidents](responding_to_security_incidents.md)
-## Securing your GitLab installation
+To harden your GitLab instance and minimize the risk of unwanted user account creation, consider access control features like [Sign up restrictions](../user/admin_area/settings/sign_up_restrictions.md) and [Authentication options](../topics/authentication/index.md) .
-Consider access control features like [Sign up restrictions](../user/admin_area/settings/sign_up_restrictions.md) and [Authentication options](../topics/authentication/) to harden your GitLab instance and minimize the risk of unwanted user account creation.
-
-Self-hosting GitLab customers and administrators are responsible for the security of their underlying hosts, and for keeping GitLab itself up to date. It is important to [regularly patch GitLab](../policy/maintenance.md), patch your operating system and its software, and harden your hosts in accordance with vendor guidance.
+Self-managed GitLab customers and administrators are responsible for the security of their underlying hosts, and for keeping GitLab itself up to date. It is important to [regularly patch GitLab](../policy/maintenance.md), patch your operating system and its software, and harden your hosts in accordance with vendor guidance.
diff --git a/doc/security/information_exclusivity.md b/doc/security/information_exclusivity.md
index 0d55881c147..754d5fff843 100644
--- a/doc/security/information_exclusivity.md
+++ b/doc/security/information_exclusivity.md
@@ -24,8 +24,8 @@ limitation.
You can take steps to prevent unintentional sharing and information
destruction. This limitation is the reason why only certain people are allowed
to [add users to a project](../user/project/members/index.md)
-and why only a GitLab administrator can [force push a protected
-branch](../user/project/protected_branches.md).
+and why only a GitLab administrator can
+[force push a protected branch](../user/project/protected_branches.md).
<!-- ## Troubleshooting
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index 06934b187c1..992a8585a47 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -81,7 +81,15 @@ If you know the username, user ID, or email address, you can use the Rails conso
new_password = ::User.random_password
user.password = new_password
user.password_confirmation = new_password
- ```
+ ```
+
+ To set a specific value for the new password:
+
+ ```ruby
+ new_password = 'examplepassword'
+ user.password = new_password
+ user.password_confirmation = new_password
+ ```
1. Optional. Notify the user that an administrator changed their password:
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index 5907860f5cc..93d77a69f0e 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -71,7 +71,7 @@ The following are important notes about 2FA:
2FA for the project. For example, if project *P* belongs to 2FA-enabled group *A* and
is shared with 2FA-disabled group *B*, members of group *B* can access project *P*
without 2FA. To ensure this scenario doesn't occur,
- [prevent sharing of projects](../user/group/index.md#prevent-a-project-from-being-shared-with-groups)
+ [prevent sharing of projects](../user/group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups)
for the 2FA-enabled group.
- If you add additional members to a project within a group or subgroup that has
2FA enabled, 2FA is **not** required for those individually added members.
@@ -129,6 +129,7 @@ sudo -u git -H bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_EN
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/270554) in GitLab 13.7.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/299088) from GitLab Free to GitLab Premium in 13.9.
> - It's deployed behind a feature flag, disabled by default.
+> - Push notification support [introduced](https://gitlab.com/gitlab-org/gitlab-shell/-/issues/506) in GitLab 15.3.
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 `two_factor_for_cli`. On GitLab.com, this feature is not available. The feature is not ready for production use. This feature flag also affects [session duration for Git Operations when 2FA is enabled](../user/admin_area/settings/account_and_limit_settings.md#customize-session-duration-for-git-operations-when-2fa-is-enabled).
@@ -136,14 +137,20 @@ On self-managed GitLab, by default this feature is not available. To make it ava
Two-factor authentication can be enforced for Git over SSH operations. However, we recommend using
[ED25519_SK](../user/ssh.md#ed25519_sk-ssh-keys) or [ECDSA_SK](../user/ssh.md#ecdsa_sk-ssh-keys) SSH keys instead.
-The one-time password (OTP) verification can be done using a command:
+To perform one-time password (OTP) verification, run:
```shell
ssh git@<hostname> 2fa_verify
```
-After the OTP is verified, Git over SSH operations can be used for a session duration of
-15 minutes (default) with the associated SSH key.
+Then authenticate by either:
+
+- Entering the correct OTP.
+- In GitLab 15.3 and later, responding to a device push notification if
+ [FortiAuthenticator is enabled](../user/profile/account/two_factor_authentication.md#enable-one-time-password-using-fortiauthenticator).
+
+After successful authentication, you can perform Git over SSH operations for 15 minutes (default) with the associated
+SSH key.
### Security limitation
diff --git a/doc/security/user_file_uploads.md b/doc/security/user_file_uploads.md
index dcdd18a9f0b..7c11d01396d 100644
--- a/doc/security/user_file_uploads.md
+++ b/doc/security/user_file_uploads.md
@@ -5,21 +5,45 @@ 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
---
-# User File Uploads **(FREE)**
+# User file uploads **(FREE)**
-Images that are attached to issues, merge requests, or comments
-do not require authentication to be viewed if they are accessed directly by URL.
-This direct URL contains a random 32-character ID that prevents unauthorized
-people from guessing the URL for an image, thus there is some protection if an
-image contains sensitive information.
+> - Enforced authorization checks [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80117) in GitLab 14.8 [with a flag](../administration/feature_flags.md) named `enforce_auth_checks_on_uploads`. Disabled by default.
+> - Enforced authorization checks became [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/352291) in GitLab 15.3. Feature flag `enforce_auth_checks_on_uploads` removed.
+> - Project settings in the user interface [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88567) in GitLab 15.3.
-Authentication is not enabled because images must be visible in the body of
-notification emails, which are often read from email clients that are not
-authenticated with GitLab, such as Outlook, Apple Mail, or the Mail app on your
-mobile device.
+In private or internal projects, GitLab restricts access to uploaded files (such as PDFs)
+to authenticated users only. By default, image files are not subject to the same
+restriction, and unauthenticated users can use the URL to view the
+file. If you enable authorization checks for all media files, images
+receive the same protection and are viewable only by authenticated users.
-NOTE:
-Non-image attachments do require authentication to be viewed.
+Users can upload files to issues, merge requests, or comments in a project. Direct URLs
+to these images in GitLab contain a random 32-character ID to help prevent
+unauthorized users from guessing image URLs. This randomization provides some protection
+if an image contains sensitive information.
+
+Authentication checks for images can cause display issues in the body of notification emails.
+Emails are frequently read from clients (such as Outlook, Apple Mail, or your mobile device)
+not authenticated with GitLab. Images in emails appear broken and unavailable if
+the client is not authorized to GitLab.
+
+## Enable authorization checks for all media files
+
+Non-image attachments (including PDFs) always require authentication to be viewed.
+You can use this setting to extend this protection to image files.
+
+Prerequisite:
+
+- You must have the Maintainer or Owner role for the project.
+- Your project visibility settings must be **Private** or **Internal**.
+
+To configure authentication settings for all media files:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Visibility, project features, permissions**.
+1. Scroll to **Project visibility** and select **Require authentication to view media files**.
+ You cannot select this option for projects with **Public** visibility.
<!-- ## Troubleshooting
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index c3d445103c4..f2066ee4a42 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -74,7 +74,7 @@ allowlist:
The allowed entries can be separated by semicolons, commas or whitespaces
(including newlines) and be in different formats like hostnames, IP addresses and/or
IP ranges. IPv6 is supported. Hostnames that contain Unicode characters should
-use [Internationalized Domain Names in Applications](https://www.icann.org/resources/pages/glossary-2014-02-04-en#i)
+use [Internationalized Domain Names in Applications](https://www.icann.org/en/icann-acronyms-and-terms/internationalized-domain-names-in-applications-en)
(IDNA) encoding.
The allowlist can hold a maximum of 1000 entries. Each entry can be a maximum of
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index f936e230a3d..62e045a7593 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -23,11 +23,11 @@ the tiers are no longer mentioned in GitLab documentation:
- [Setting a default template for merge requests and issues](../user/project/description_templates.md#set-a-default-template-for-merge-requests-and-issues)
- [Email from GitLab](../user/admin_area/email_from_gitlab.md)
- Groups:
- - [Creating group memberships via CN](../user/group/index.md#create-group-links-via-cn)
- - [Group push rules](../user/group/index.md#group-push-rules)
- - [Managing group memberships via LDAP](../user/group/index.md#manage-group-memberships-via-ldap)
- - [Member locking](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group)
- - [Overriding user permissions](../user/group/index.md#override-user-permissions)
+ - [Creating group memberships via CN](../user/group/access_and_permissions.md#create-group-links-via-cn)
+ - [Group push rules](../user/group/access_and_permissions.md#group-push-rules)
+ - [Managing group memberships via LDAP](../user/group/access_and_permissions.md#manage-group-memberships-via-ldap)
+ - [Member locking](../user/group/access_and_permissions.md#prevent-members-from-being-added-to-projects-in-a-group)
+ - [Overriding user permissions](../user/group/access_and_permissions.md#override-user-permissions)
- [User contribution analytics](../user/group/contribution_analytics/index.md)
- [Kerberos integration](../integration/kerberos.md)
- Issue boards:
@@ -60,8 +60,8 @@ the tiers are no longer mentioned in GitLab documentation:
- Rake tasks for [LDAP tasks](../administration/raketasks/ldap.md), including
[syncing groups](../administration/raketasks/ldap.md#run-a-group-sync)
- Logging:
- - [`audit_json.log`](../administration/logs.md#audit_jsonlog) (specific entries)
- - [`elasticsearch.log`](../administration/logs.md#elasticsearchlog)
+ - [`audit_json.log`](../administration/logs/index.md#audit_jsonlog) (specific entries)
+ - [`elasticsearch.log`](../administration/logs/index.md#elasticsearchlog)
- Merge requests:
- [Full code quality reports in the code quality tab](../ci/testing/code_quality.md#code-quality-reports)
- [Merge request approvals](../user/project/merge_requests/approvals/index.md)
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index da84cc6211e..6b83a00cac1 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -33,10 +33,10 @@ To subscribe to GitLab SaaS:
and decide which tier you want.
1. Create a user account for yourself by using the
[sign up page](https://gitlab.com/users/sign_up).
-1. Create a [group](../../user/group/index.md#create-a-group). Your license tier applies to the top-level group, its subgroups, and projects.
+1. Create a [group](../../user/group/manage.md#create-a-group). Your subscription tier applies to the top-level group, its subgroups, and projects.
1. Create additional users and
- [add them to the group](../../user/group/index.md#add-users-to-a-group). The users in this group, its subgroups, and projects can use
- the features of your license tier, and they consume a seat in your subscription.
+ [add them to the group](../../user/group/manage.md#add-users-to-a-group). The users in this group, its subgroups, and projects can use
+ the features of your subscription tier, and they consume a seat in your subscription.
1. On the left sidebar, select **Billing** and choose a tier.
1. Fill out the form to complete your purchase.
@@ -73,7 +73,7 @@ subscription according to the maximum number of users assigned to the top-level
add and remove users during the subscription period, as long as the total users
at any given time doesn't exceed the subscription count.
-A top-level group can be [changed](../../user/group/index.md#change-a-groups-path) like any other group.
+A top-level group can be [changed](../../user/group/manage.md#change-a-groups-path) like any other group.
Every user is included in seat usage, with the following exceptions:
@@ -185,7 +185,7 @@ To remove a billable user from your subscription:
1. In the row for the user you want to remove, on the right side, select the ellipsis and **Remove user**.
1. Re-type the username and select **Remove user**.
-If you add a member to a group by using the [share a group with another group](../../user/group/index.md#share-a-group-with-another-group) feature, you can't remove the member by using this method. Instead, you can either:
+If you add a member to a group by using the [share a group with another group](../../user/group/manage.md#share-a-group-with-another-group) feature, you can't remove the member by using this method. Instead, you can either:
- Remove the member from the shared group. You must be a group owner to do this.
- From the group's membership page, remove access from the entire shared group.
@@ -297,10 +297,10 @@ for your personal or group namespace. CI/CD minutes are a **one-time purchase**,
## Add-on subscription for additional Storage and Transfer
NOTE:
-Free namespaces are subject to a 5GB storage and 10GB transfer [soft limit](https://about.gitlab.com/pricing). Once all storage is available to view in the usage quota workflow, GitLab will automatically enforce the namespace storage limit and the project limit will be removed. This change will be announced separately. The storage and transfer add-on can be purchased to increase the limits.
+Free namespaces are subject to a 5GB storage and 10GB transfer [soft limit](https://about.gitlab.com/pricing/). Once all storage is available to view in the usage quota workflow, GitLab will automatically enforce the namespace storage limit and the project limit will be removed. This change will be announced separately. The storage and transfer add-on can be purchased to increase the limits.
-Projects have a free storage quota of 10 GB. To exceed this quota you must first [purchase one or
-more storage subscription units](#purchase-more-storage-and-transfer). Each unit provides 10 GB of additional
+Projects have a free storage quota of 10 GB. To exceed this quota you must first
+[purchase one or more storage subscription units](#purchase-more-storage-and-transfer). Each unit provides 10 GB of additional
storage per namespace. A storage subscription is renewed annually. For more details, see
[Usage Quotas](../../user/usage_quotas.md).
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 4caf69d6015..ed96fbd91ef 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -109,8 +109,8 @@ Purchases in the Customers Portal require a credit card on record as a payment m
multiple credit cards to your account, so that purchases for different products are charged to the
correct card.
-If you would like to use an alternative method to pay, please [contact our Sales
-team](https://about.gitlab.com/sales/).
+If you would like to use an alternative method to pay, please
+[contact our Sales team](https://about.gitlab.com/sales/).
To change your payment method:
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index c1a11ce7d12..758b472d67b 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -255,7 +255,7 @@ It also displays the following information:
| Field | Description |
|:-------------------|:------------|
| Users in License | The number of users you've paid for in the current license loaded on the system. The number does not change unless you [add seats](#add-seats-to-a-subscription) during your current subscription period. |
-| Billable users | The daily count of billable users on your system. The count may change as you block or add users to your instance. |
+| Billable users | The daily count of billable users on your system. The count may change as you block, deactivate, or add users to your instance. |
| Maximum users | The highest number of billable users on your system during the term of the loaded license. |
| Users over license | Calculated as `Maximum users` - `Users in License` for the current license term. This number incurs a retroactive charge that must be paid before renewal. |
@@ -274,18 +274,18 @@ This file contains the information GitLab uses to manually process quarterly rec
The **License Usage** CSV includes the following details:
- License key
-- Email
+- Licensee email
- License start date
- License end date
- Company
- Generated at (the timestamp for when the file was exported)
- Table of historical user counts for each day in the period:
- - Date the count was recorded
- - Active user count
+ - Timestamp the count was recorded
+ - Billable user count
NOTES:
-- All timestamps are displayed in UTC.
+- All date timestamps are displayed in UTC.
- A custom format is used for [dates](https://gitlab.com/gitlab-org/gitlab/blob/3be39f19ac3412c089be28553e6f91b681e5d739/config/initializers/date_time_formats.rb#L7) and [times](https://gitlab.com/gitlab-org/gitlab/blob/3be39f19ac3412c089be28553e6f91b681e5d739/config/initializers/date_time_formats.rb#L13) in CSV files.
## Renew your subscription
@@ -312,7 +312,7 @@ the contact person who manages your subscription.
It's important to regularly review your user accounts, because:
-- Stale user accounts that are not blocked count as billable users. You may pay more than you should
+- Stale user accounts may count as billable users. You may pay more than you should
if you renew for too many users.
- Stale user accounts can be a security risk. A regular review helps reduce this risk.
@@ -329,7 +329,7 @@ To view the number of _users over license_ go to the **Admin Area**.
You purchase a license for 10 users.
-| Event | Billable members | Maximum users |
+| Event | Billable users | Maximum users |
|:---------------------------------------------------|:-----------------|:--------------|
| Ten users occupy all 10 seats. | 10 | 10 |
| Two new users join. | 12 | 12 |
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 b3ce2aa1683..1fea573faa1 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
@@ -35,7 +35,7 @@ you need a [Google Cloud Platform account](https://console.cloud.google.com).
Sign in with an existing Google account, such as the one you use to access Gmail
or Google Drive, or create a new one.
-1. Follow the steps described in the ["Before you begin" section](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)
+1. Follow the steps described in the ["Before you begin" section](https://cloud.google.com/kubernetes-engine/docs/deploy-app-cluster#before-you-begin)
of the Kubernetes Engine documentation to enable the required APIs and related services.
1. Ensure you've created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account)
with Google Cloud Platform.
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index d8734ab5b13..7f9707a6939 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -460,7 +460,7 @@ The following table lists variables used to disable jobs.
| **Job Name** | **CI/CDVariable** | **GitLab version** | **Description** |
|----------------------------------------|---------------------------------|-----------------------|-----------------|
-| `.fuzz_base` | `COVFUZZ_DISABLED` | [From GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34984) | [Read more](../../user/application_security/coverage_fuzzing/) about how `.fuzz_base` provide capability for your own jobs. If the variable is present, your jobs aren't created. |
+| `.fuzz_base` | `COVFUZZ_DISABLED` | [From GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34984) | [Read more](../../user/application_security/coverage_fuzzing/index.md) about how `.fuzz_base` provide capability for your own jobs. If the variable is present, your jobs aren't created. |
| `apifuzzer_fuzz` | `API_FUZZING_DISABLED` | [From GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39135) | If the variable is present, the job isn't created. |
| `build` | `BUILD_DISABLED` | | If the variable is present, the job isn't created. |
| `build_artifact` | `BUILD_DISABLED` | | If the variable is present, the job isn't created. |
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 6d4f6eb698e..dc58f42f30e 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -267,7 +267,10 @@ 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`](https://v1-19.docs.kubernetes.io/docs/concepts/workloads/pods/podpreset/):
+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
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 8d35fd245d5..4e8d0e08eff 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -199,7 +199,7 @@ see the documentation.
## Auto Secret Detection
> - Introduced in GitLab 13.1.
-> - Select functionality [made available](../../user/application_security/secret_detection/#making-secret-detection-available-to-all-gitlab-tiers) in all tiers in GitLab 13.3
+> - Select functionality [made available](../../user/application_security/secret_detection/index.md#making-secret-detection-available-to-all-gitlab-tiers) in all tiers in GitLab 13.3
Secret Detection uses the
[Secret Detection Docker image](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) to run Secret Detection on the current code, and checks for leaked secrets. Auto Secret Detection requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or above.
@@ -458,8 +458,8 @@ To use Auto Deploy on a Kubernetes 1.16+ cluster:
```
1. If you have an in-cluster PostgreSQL database installed with
- `AUTO_DEVOPS_POSTGRES_CHANNEL` set to `1`, follow the [guide to upgrade
- PostgreSQL](upgrading_postgresql.md).
+ `AUTO_DEVOPS_POSTGRES_CHANNEL` set to `1`, follow the
+ [guide to upgrade PostgreSQL](upgrading_postgresql.md).
1. If you are deploying your application for the first time and are using
GitLab 12.9 or 12.10, set `AUTO_DEVOPS_POSTGRES_CHANNEL` to `2`.
diff --git a/doc/topics/autodevops/troubleshooting.md b/doc/topics/autodevops/troubleshooting.md
index cee4ba68b49..045f843be44 100644
--- a/doc/topics/autodevops/troubleshooting.md
+++ b/doc/topics/autodevops/troubleshooting.md
@@ -100,7 +100,7 @@ WARNING:
Setting `POSTGRES_ENABLED` to `false` permanently deletes any existing
channel 1 database for your environment.
-## Error: unable to recognize "": no matches for kind "Deployment" in version "extensions/v1beta1"
+## `Error: unable to recognize "": no matches for kind "Deployment" in version "extensions/v1beta1"`
After upgrading your Kubernetes cluster to [v1.16+](stages.md#kubernetes-116),
you may encounter this message when deploying with Auto DevOps:
@@ -148,7 +148,7 @@ that works for this problem. Follow these steps to use the tool in Auto DevOps:
1. Continue the deployments as usual.
-## Error: error initializing: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached
+## `Error: error initializing: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached`
As [announced in the official CNCF blog post](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/),
the stable Helm chart repository was deprecated and removed on November 13th, 2020.
@@ -197,7 +197,7 @@ To fix your custom chart:
You can find more information in
[issue #263778, "Migrate PostgreSQL from stable Helm repository"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778).
-## Error: release .... failed: timed out waiting for the condition
+## `Error: release .... failed: timed out waiting for the condition`
When getting started with Auto DevOps, you may encounter this error when first
deploying your application:
diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
index b0814ac5076..5772a891b41 100644
--- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
+++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md
@@ -68,8 +68,7 @@ The v1 chart is backward compatible with the v0 chart, so no configuration chang
### Upgrade deployments to the v2 `auto-deploy-image`
The v2 auto-deploy-image contains multiple dependency and architectural changes.
-If your Auto DevOps project has an active environment deployed with the v1 `auto-deploy-image`,
-please proceed with the following upgrade guide. Otherwise, you can skip this process.
+If your Auto DevOps project has an active environment deployed with the v1 `auto-deploy-image`, proceed with the following upgrade guide. Otherwise, you can skip this process.
#### Kubernetes 1.16+
@@ -276,4 +275,4 @@ you might encounter the following error:
- `Error: rendered manifests contain a resource that already exists. Unable to continue with install: Secret "production-postgresql" in namespace "<project-name>-production" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "production-postgresql"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "<project-name>-production"`
This is because the previous deployment was deployed with Helm2, which is not compatible with Helm3.
-To resolve the problem, please follow the [upgrade guide](#upgrade-deployments-to-the-v2-auto-deploy-image).
+To resolve the problem, follow the [upgrade guide](#upgrade-deployments-to-the-v2-auto-deploy-image).
diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md
index 258195bb89f..0d8d8cd6579 100644
--- a/doc/topics/autodevops/upgrading_postgresql.md
+++ b/doc/topics/autodevops/upgrading_postgresql.md
@@ -131,8 +131,7 @@ being modified after the database dump is created.
## Retain persistent volumes
-By default the [persistent
-volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)
+By default the [persistent volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)
used to store the underlying data for PostgreSQL is marked as `Delete`
when the pods and pod claims that use the volume is deleted.
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index d40690d86c6..6fd7f4a5207 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -50,7 +50,8 @@ repository with Git LFS. For example, if you want to upload a very large file an
check it into your Git repository:
```shell
-git clone git@gitlab.example.com:group/project.git
+git clone git@gitlab.example.com:group/my-sample-project.git
+cd my-sample-project
git lfs install # initialize the Git LFS project
git lfs track "*.iso" # select the file extensions that you want to treat as large files
```
@@ -70,6 +71,8 @@ LFS doesn't work properly for people cloning the project:
```shell
git add .gitattributes
+git commit -am "Added .gitattributes to capture LFS tracking"
+git push origin main
```
Cloning the repository works the same as before. Git automatically detects the
@@ -78,7 +81,7 @@ command with a SSH URL, you have to enter your GitLab credentials for HTTP
authentication.
```shell
-git clone git@gitlab.example.com:group/project.git
+git clone git@gitlab.example.com:group/my-sample-project.git
```
If you already cloned the repository and you want to get the latest LFS object
@@ -93,7 +96,7 @@ and are not pushed to the remote repository.
### Migrate an existing repository to Git LFS
-Read the documentation on how to [migrate an existing Git repository with Git LFS](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.1.ronn).
+Read the documentation on how to [migrate an existing Git repository with Git LFS](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc).
### Removing objects from LFS
@@ -112,8 +115,7 @@ See the documentation on [File Locking](../../../user/project/file_lock.md).
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46572) in GitLab 13.6.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62539) in GitLab 14.0. Feature flag `include_lfs_blobs_in_archive` removed.
-Prior to GitLab 13.5, [project source
-downloads](../../../user/project/repository/index.md) would include Git
+Prior to GitLab 13.5, [project source downloads](../../../user/project/repository/index.md) would include Git
LFS pointers instead of the actual objects. For example, LFS pointers
look like the following:
@@ -214,7 +216,7 @@ This behavior is caused by Git LFS using HTTPS connections by default when a
To prevent this from happening, set the LFS URL in project Git configuration:
```shell
-git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
+git config --add lfs.url "http://gitlab.example.com/group/my-sample-project.git/info/lfs"
```
### Credentials are always required when pushing an object
diff --git a/doc/topics/git/terminology.md b/doc/topics/git/terminology.md
index 4ce87aa2d11..f64e614c253 100644
--- a/doc/topics/git/terminology.md
+++ b/doc/topics/git/terminology.md
@@ -31,7 +31,7 @@ This copy is called a [**fork**](../../user/project/repository/forking_workflow.
The process is called "creating a fork."
When you fork a repository, you create a copy of the project in your own
-[namespace](../../user/group/#namespaces). You then have write permissions to modify the project files
+[namespace](../../user/namespace/index.md). You then have write permissions to modify the project files
and settings.
For example, you can fork this project, <https://gitlab.com/gitlab-tests/sample-project/>, into your namespace.
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index 13962ad0376..36c26a02064 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -212,10 +212,10 @@ apply more than one:
[`gitlab.rb`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/13.5.1+ee.0/files/gitlab-config-template/gitlab.rb.template#L1435-1455) file:
```shell
- omnibus_gitconfig['system'] = {
+ gitaly['gitconfig'] = [
# Set the http.postBuffer size, in bytes
- "http" => ["postBuffer = 524288000"]
- }
+ {key: "http.postBuffer", value: "524288000"},
+ ]
```
1. After applying this change, apply the configuration change:
diff --git a/doc/topics/offline/quick_start_guide.md b/doc/topics/offline/quick_start_guide.md
index aa923eb6dc6..353ba094d1e 100644
--- a/doc/topics/offline/quick_start_guide.md
+++ b/doc/topics/offline/quick_start_guide.md
@@ -139,8 +139,7 @@ sudo cp /etc/gitlab/ssl/my-host.internal.crt /etc/gitlab-runner/certs/ca.crt
## Enabling GitLab Runner
-[Following a similar process to the steps for installing our GitLab Runner as a
-Docker service](https://docs.gitlab.com/runner/install/docker.html#docker-image-installation), we must first register our runner:
+[Following a similar process to the steps for installing our GitLab Runner as a Docker service](https://docs.gitlab.com/runner/install/docker.html#install-the-docker-image-and-start-the-container), we must first register our runner:
```shell
$ sudo docker run --rm -it -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner register
diff --git a/doc/topics/release_your_application.md b/doc/topics/release_your_application.md
index 6c94e9e78f9..61ca1468dca 100644
--- a/doc/topics/release_your_application.md
+++ b/doc/topics/release_your_application.md
@@ -30,14 +30,14 @@ to Kubernetes clusters using the [GitLab agent](../user/clusters/agent/install/i
#### GitOps deployments **(PREMIUM)**
-With the [GitLab agent for Kubernetes](../user/clusters/agent/install/index.md), you can perform [pull-based
-deployments of Kubernetes manifests](../user/clusters/agent/gitops.md). This provides a scalable, secure, and cloud-native
-approach to manage Kubernetes deployments.
+With the [GitLab agent for Kubernetes](../user/clusters/agent/install/index.md), you can perform
+[pull-based deployments of Kubernetes manifests](../user/clusters/agent/gitops.md). This provides a scalable, secure,
+and cloud-native approach to manage Kubernetes deployments.
#### Deploy to Kubernetes from GitLab CI/CD
-With the [GitLab agent for Kubernetes](../user/clusters/agent/install/index.md), you can perform [push-based
-deployments](../user/clusters/agent/ci_cd_workflow.md) from GitLab CI/CD. The agent provides
+With the [GitLab agent for Kubernetes](../user/clusters/agent/install/index.md), you can perform
+[push-based deployments](../user/clusters/agent/ci_cd_workflow.md) from GitLab CI/CD. The agent provides
a secure and reliable connection between GitLab and your Kubernetes cluster.
### Deploy to AWS with GitLab CI/CD
diff --git a/doc/topics/set_up_organization.md b/doc/topics/set_up_organization.md
index c8183a0757e..b6cacf0b14e 100644
--- a/doc/topics/set_up_organization.md
+++ b/doc/topics/set_up_organization.md
@@ -9,6 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Configure your organization and its users. Determine user roles
and give everyone access to the projects they need.
+- [Namespaces](../user/namespace/index.md)
- [Members](../user/project/members/index.md)
- [Workspace](../user/workspace/index.md) _(In development)_
- [Groups](../user/group/index.md)
diff --git a/doc/tutorials/make_your_first_git_commit.md b/doc/tutorials/make_your_first_git_commit.md
index a35137e158b..be9023c6ae0 100644
--- a/doc/tutorials/make_your_first_git_commit.md
+++ b/doc/tutorials/make_your_first_git_commit.md
@@ -37,7 +37,7 @@ Each time you push a change, Git records it as a unique *commit*. These commits
the history of when and how a file changed, and who changed it.
```mermaid
-graph LR
+graph TB
subgraph Repository commit history
A(Author: Alex<br>Date: 3 Jan at 1PM<br>Commit message: Added sales figures for January<br> Commit ID: 123abc12) ---> B
B(Author: Sam<br>Date: 4 Jan at 10AM<br>Commit message: Removed outdated marketing information<br> Commit ID: aabb1122) ---> C
@@ -54,7 +54,7 @@ of a repository are in a default branch. To make changes, you:
1. When you're ready, *merge* your branch into the default branch.
```mermaid
-flowchart LR
+flowchart TB
subgraph Default branch
A[Commit] --> B[Commit] --> C[Commit] --> D[Commit]
end
diff --git a/doc/tutorials/move_personal_project_to_a_group.md b/doc/tutorials/move_personal_project_to_a_group.md
index fdda42be3fa..5ebbf813ab9 100644
--- a/doc/tutorials/move_personal_project_to_a_group.md
+++ b/doc/tutorials/move_personal_project_to_a_group.md
@@ -24,7 +24,7 @@ A group gives you some great benefits. For example, you can:
However, if you're working in a [personal project](../user/project/working_with_projects.md#view-personal-projects),
you can't use these features. Personal projects are created under your
-[personal namespace](../user/group/index.md#namespaces). They're not part of a group,
+[personal namespace](../user/namespace/index.md). They're not part of a group,
so you can't get any of the benefits and features of a group.
But don't worry! You can move your existing personal project to a group.
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 81b98b95068..b69f8de2947 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -45,6 +45,98 @@ sole discretion of GitLab Inc.
<div class="announcement-milestone">
+## Announced in 15.8
+
+<div class="deprecation removal-160 breaking-change">
+
+### Security report schemas version 14.x.x
+
+End of Support: GitLab <span class="removal-milestone">15.8</span> (2023-01-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.
+
+All [security report schema](https://gitlab.com/gitlab-org/security-products/security-report-schemas) versions before 15.0.0 are considered deprecated in GitLab %15.8. Specifically, all [schemas](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/lib/ee/gitlab/ci/parsers/security/validators/schemas) that match 14.*.* will be deprecated.
+
+Please note that any [security report scanner integration](https://docs.gitlab.com/ee/development/integrations/secure.html) with GitLab using a deprecated schema version will result in a deprecation warning as a result of [report validation](https://docs.gitlab.com/ee/development/integrations/secure.html#report-validation).
+
+See [Security report validation](https://docs.gitlab.com/ee/user/application_security/#security-report-validation) for more information.
+
+</div>
+</div>
+
+<div class="announcement-milestone">
+
+## Announced in 15.3
+
+<div class="deprecation removal-160 breaking-change">
+
+### Atlassian Crowd OmniAuth provider
+
+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 `omniauth_crowd` gem that provides GitLab with the Atlassian Crowd OmniAuth provider will be removed in our
+next major release, GitLab 16.0. This gem sees very little use and its
+[lack of compatibility](https://github.com/robdimarco/omniauth_crowd/issues/37) with OmniAuth 2.0 is
+[blocking our upgrade](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
+
+</div>
+
+<div class="deprecation removal-160 breaking-change">
+
+### CAS OmniAuth provider
+
+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 `omniauth-cas3` gem that provides GitLab with the CAS OmniAuth provider will be removed in our next major
+release, GitLab 16.0. This gem sees very little use and its lack of upstream maintenance is preventing GitLab's
+[upgrade to OmniAuth 2.0](https://gitlab.com/gitlab-org/gitlab/-/issues/30073).
+
+</div>
+
+<div class="deprecation removal-160">
+
+### Maximum number of active pipelines per project limit (`ci_active_pipelines`)
+
+Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
+
+The [**Maximum number of active pipelines per project** limit](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#set-cicd-limits) was never enabled by default and will be removed in GitLab 16.0. This limit can also be configured in the Rails console under [`ci_active_pipelines`](https://docs.gitlab.com/ee/administration/instance_limits.html#number-of-pipelines-running-concurrently). Instead, use the other recommended rate limits that offer similar protection:
+
+- [**Pipelines rate limits**](https://docs.gitlab.com/ee/user/admin_area/settings/rate_limit_on_pipelines_creation.html).
+- [**Total number of jobs in currently active pipelines**](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#set-cicd-limits).
+
+</div>
+
+<div class="deprecation removal-160 breaking-change">
+
+### Redis 5 deprecated
+
+End of Support: GitLab <span class="removal-milestone">15.6</span> (2022-11-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.
+
+With GitLab 13.9, in the Omnibus GitLab package and GitLab Helm chart 4.9, the Redis version [was updated to Redis 6](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#omnibus-improvements).
+Redis 5 has reached the end of life in April 2022 and will no longer be supported as of GitLab 15.6.
+If you are using your own Redis 5.0 instance, you should upgrade it to Redis 6.0 or higher before upgrading to GitLab 16.0 or higher.
+
+</div>
+</div>
+
+<div class="announcement-milestone">
+
## Announced in 15.2
<div class="deprecation removal-160 breaking-change">
@@ -54,7 +146,7 @@ sole discretion of GitLab Inc.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `job_age` parameter, returned from the `POST /jobs/request` API endpoint used in communication with GitLab Runner, was never used by any GitLab or Runner feature. This parameter will be removed in GitLab 16.0.
@@ -75,7 +167,7 @@ This could be a breaking change for anyone that developed their own runner that
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [Jira DVCS Connector](https://docs.gitlab.com/ee/integration/jira/dvcs.html) (which enables the [Jira Development Panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)), will no longer support Jira Cloud users starting with GitLab 16.0. The [GitLab for Jira App](https://docs.gitlab.com/ee/integration/jira/connect-app.html) has always been recommended for Jira Cloud users, and it will be required instead of the DVCS connector. If you are a Jira Cloud user, we recommended you begin migrating to the GitLab for Jira App.
@@ -90,7 +182,7 @@ Any Jira Server and Jira Data Center users will need to confirm they are not usi
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Previously, the [PipelineSecurityReportFinding GraphQL type was updated](https://gitlab.com/gitlab-org/gitlab/-/issues/335372) to include a new `title` field. This field is an alias for the current `name` field, making the less specific `name` field redundant. The `name` field will be removed from the PipelineSecurityReportFinding type in GitLab 16.0.
@@ -104,7 +196,7 @@ Previously, the [PipelineSecurityReportFinding GraphQL type was updated](https:/
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [`project_fingerprint`](https://gitlab.com/groups/gitlab-org/-/epics/2791) attribute of vulnerability findings is being deprecated in favor of a `uuid` attribute. By using UUIDv5 values to identify findings, we can easily associate any related entity with a finding. The `project_fingerprint` attribute is no longer being used to track findings, and will be removed in GitLab 16.0.
@@ -118,7 +210,7 @@ The [`project_fingerprint`](https://gitlab.com/groups/gitlab-org/-/epics/2791) a
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `maintainer_note` argument in the `POST /runners` REST endpoint was deprecated in GitLab 14.8 and replaced with the `maintenance_note` argument.
@@ -146,7 +238,7 @@ GitLab 15.3 to simplify the codebase and prevent any unwanted performance degrad
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Previous work helped [align the vulnerabilities calls for pipeline security tabs](https://gitlab.com/gitlab-org/gitlab/-/issues/343469) to match the vulnerabilities calls for project-level and group-level vulnerability reports. This helped the frontend have a more consistent interface. The old `project.pipeline.securityReportFindings` query was formatted differently than other vulnerability data calls. Now that it has been replaced with the new `project.pipeline.vulnerabilities` field, the old `project.pipeline.securityReportFindings` is being deprecated and will be removed in GitLab 16.0.
@@ -165,7 +257,7 @@ Previous work helped [align the vulnerabilities calls for pipeline security tabs
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `CiCdSettingsUpdate` mutation was renamed to `ProjectCiCdSettingsUpdate` in GitLab 15.0.
@@ -182,7 +274,7 @@ instead.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `legacyMode` argument to the `status` field in `RunnerType` will be rendered non-functional in the 16.0 release
@@ -201,7 +293,7 @@ be present during the 16.x cycle to avoid breaking the API signature, and will b
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Support for PostgreSQL 12 is scheduled for removal in GitLab 16.0.
@@ -214,16 +306,15 @@ Upgrading to PostgreSQL 13 is not yet supported for GitLab instances with Geo en
</div>
-<div class="deprecation removal-152">
+<div class="deprecation removal-153">
### Vulnerability Report sort by State
-Planned removal: GitLab <span class="removal-milestone">15.2</span> (2022-07-22)
+Planned removal: GitLab <span class="removal-milestone">15.3</span> (2022-08-22)
The ability to sort the Vulnerability Report by the `State` column was disabled and put behind a feature flag in GitLab 14.10 due to a refactor
of the underlying data model. The feature flag has remained off by default as further refactoring will be required to ensure sorting
-by this value remains performant. Due to very low usage of the `State` column for sorting, the feature flag will instead be removed in
-GitLab 15.2 to simplify the codebase and prevent any unwanted performance degradation.
+by this value remains performant. Due to very low usage of the `State` column for sorting, the feature flag will instead be removed to simplify the codebase and prevent any unwanted performance degradation.
</div>
</div>
@@ -239,7 +330,7 @@ GitLab 15.2 to simplify the codebase and prevent any unwanted performance degrad
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 15.0, for Dependency Scanning, the default version of Java that the scanner expects will be updated from 11 to 17. Java 17 is [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). Dependency scanning continues to support the same [range of versions (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers), only the default version is changing. If your project uses the previous default of Java 11, be sure to [set the `DS_Java_Version` variable to match](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning).
@@ -253,7 +344,7 @@ In GitLab 15.0, for Dependency Scanning, the default version of Java that the sc
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Manual iteration management is deprecated and only automatic iteration cadences will be supported in the future.
@@ -285,7 +376,7 @@ For more information about iteration cadences, you can refer to
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As Advanced Search migrations usually require support multiple code paths for a long period of time, it’s important to clean those up when we safely can. We use GitLab major version upgrades as a safe time to remove backward compatibility for indices that have not been fully migrated. See the [upgrade documentation](https://docs.gitlab.com/ee/update/index.html#upgrading-to-a-new-major-version) for details.
@@ -299,7 +390,7 @@ As Advanced Search migrations usually require support multiple code paths for a
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Toggling notes confidentiality with REST and GraphQL APIs is being deprecated. Updating notes confidential attribute is no longer supported by any means. We are changing this to simplify the experience and prevent private information from being unintentionally exposed.
@@ -318,7 +409,7 @@ Toggling notes confidentiality with REST and GraphQL APIs is being deprecated. U
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To reduce the overall complexity and maintenance burden of GitLab's [object storage feature](https://docs.gitlab.com/ee/administration/object_storage.html), support for using `background_upload` to upload files is deprecated and will be fully removed in GitLab 15.0. Review the [15.0 specific changes](https://docs.gitlab.com/omnibus/update/gitlab_15_changes.html) for the [removed background uploads settings for object storage](https://docs.gitlab.com/omnibus/update/gitlab_15_changes.html#removed-background-uploads-settings-for-object-storage).
@@ -359,7 +450,7 @@ In 15.0, support for daemon mode for GitLab Pages will be removed.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab self-monitoring gives administrators of self-hosted GitLab instances the tools to monitor the health of their instances. This feature is deprecated in GitLab 14.9, and is scheduled for removal in 16.0.
@@ -373,7 +464,7 @@ GitLab self-monitoring gives administrators of self-hosted GitLab instances the
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GitLab Package stage offers a Package Registry, Container Registry, and Dependency Proxy to help you manage all of your dependencies using GitLab. Each of these product categories has a variety of settings that can be adjusted using the API.
@@ -404,7 +495,7 @@ The [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.
Planned removal: GitLab <span class="removal-milestone">14.10</span> (2022-04-22)
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GitLab Composer repository can be used to push, search, fetch metadata about, and download PHP dependencies. All these actions require authentication, except for downloading dependencies.
@@ -420,7 +511,7 @@ Downloading Composer dependencies without authentication is deprecated in GitLab
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Container Registry supports [authentication](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/configuration.md#auth) with `htpasswd`. It relies on an [Apache `htpasswd` file](https://httpd.apache.org/docs/2.4/programs/htpasswd.html), with passwords hashed using `bcrypt`.
@@ -436,7 +527,7 @@ Since it isn't used in the context of GitLab (the product), `htpasswd` authentic
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `user_email_lookup_limit` [API field](https://docs.gitlab.com/ee/api/settings.html) is deprecated and will be removed in GitLab 15.0. Until GitLab 15.0, `user_email_lookup_limit` is aliased to `search_rate_limit` and existing workflows will continue to work.
@@ -470,7 +561,7 @@ This change is part of regular maintenance to keep our codebase clean.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
All functionality related to GitLab's Container Network Security and Container Host Security categories is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to evaluate the following open source projects as potential solutions that can be installed and managed outside of GitLab: [AppArmor](https://gitlab.com/apparmor/apparmor), [Cilium](https://github.com/cilium/cilium), [Falco](https://github.com/falcosecurity/falco), [FluentD](https://github.com/fluent/fluentd), [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/). To integrate these technologies into GitLab, add the desired Helm charts into your copy of the [Cluster Management Project Template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Deploy these Helm charts in production by calling commands through GitLab [CI/CD](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).
@@ -493,7 +584,7 @@ For additional context, or to provide feedback regarding this change, please ref
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
For those using Dependency Scanning for Python projects, we are deprecating the default `gemnasium-python:2` image which uses Python 3.6 as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).
@@ -564,7 +655,7 @@ The following `geo:db:*` tasks will be replaced with their corresponding `db:*:g
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
@@ -578,7 +669,7 @@ The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 1
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Using environment variables `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configure Gitaly is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/352609).
@@ -596,7 +687,7 @@ GitLab instances that use `GIT_CONFIG_SYSTEM` and `GIT_CONFIG_GLOBAL` to configu
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Elasticsearch 6.8 is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
@@ -614,7 +705,7 @@ Elasticsearch 6.8 is also incompatible with Amazon OpenSearch, which we [plan to
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [external status check API](https://docs.gitlab.com/ee/api/status_checks.html) was originally implemented to
@@ -642,7 +733,7 @@ To align with this change, API calls to list external status checks will also re
Planned removal: GitLab <span class="removal-milestone">15.0</span> (2022-04-22)
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We are removing a non-standard extension to our GraphQL processor, which we added for backwards compatibility. This extension modifies the validation of GraphQL queries, allowing the use of the `ID` type for arguments where it would normally be rejected.
@@ -706,7 +797,7 @@ an inline argument expression).
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and earlier, OAuth access tokens
@@ -728,7 +819,7 @@ tokens before GitLab 15.0 is released:
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The feature to disable enforcement of PAT expiration is unusual from a security perspective.
@@ -744,7 +835,7 @@ Unexpected behavior in a security feature is inherently dangerous, so we have de
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The feature to disable enforcement of SSH expiration is unusual from a security perspective.
@@ -760,7 +851,7 @@ Unexpected behavior in a security feature is inherently dangerous, so we have de
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [GitLab SAST SpotBugs analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) scans [Java, Scala, Groovy, and Kotlin code](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks) for security vulnerabilities.
@@ -785,7 +876,7 @@ If you rely on Java 8 being present in the analyzer environment, you must take a
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `instanceStatisticsMeasurements` GraphQL node has been renamed to `usageTrendsMeasurements` in 13.10 and the old field name has been marked as deprecated. To fix the existing GraphQL queries, replace `instanceStatisticsMeasurements` with `usageTrendsMeasurements`.
@@ -799,7 +890,7 @@ The `instanceStatisticsMeasurements` GraphQL node has been renamed to `usageTren
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/contributing/#breaking-changes).
+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.
@@ -819,7 +910,7 @@ When checking for active runners, specify `paused=false`.
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/contributing/#breaking-changes).
+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.
@@ -833,7 +924,7 @@ The `GET /groups/:id/runners?type=project_type` endpoint will be removed in GitL
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/contributing/#breaking-changes).
+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
@@ -865,7 +956,7 @@ existing runners.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
@@ -885,7 +976,7 @@ For more information, check the [summary section of the deprecation issue](https
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [required pipeline configuration](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#required-pipeline-configuration) feature is deprecated in GitLab 14.8 for Premium customers and is scheduled for removal in GitLab 15.0. This feature is not deprecated for GitLab Ultimate customers.
@@ -904,7 +995,7 @@ This change will also help GitLab remain consistent in its tiering strategy with
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As of 14.8 the retire.js job is being deprecated from Dependency Scanning. It will continue to be included in our CI/CD template while deprecated. We are removing retire.js from Dependency Scanning on May 22, 2022 in GitLab 15.0. JavaScript scanning functionality will not be affected as it is still being covered by Gemnasium.
@@ -920,7 +1011,7 @@ If you have explicitly excluded retire.js using DS_EXCLUDED_ANALYZERS you will n
Planned removal: GitLab <span class="removal-milestone">15.4</span> (2022-09-22)
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab SAST uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/sast/analyzers/) to scan code for vulnerabilities.
@@ -963,7 +1054,7 @@ If you applied customizations to any of the affected analyzers or if you current
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GitLab SAST Security Code Scan analyzer scans .NET code for security vulnerabilities.
@@ -1020,7 +1111,7 @@ For further details, see [the deprecation issue for this change](https://gitlab.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab uses various [analyzers](https://docs.gitlab.com/ee/user/application_security/terminology/#analyzer) to [scan for security vulnerabilities](https://docs.gitlab.com/ee/user/application_security/).
@@ -1048,7 +1139,7 @@ See the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352564
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Secure and Protect stages will be bumping the major versions of their analyzers in tandem with the GitLab 15.0 release. This major bump will enable a clear delineation for analyzers, between:
@@ -1093,7 +1184,7 @@ Specifically, the following are being deprecated and will no longer be updated a
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Although not recommended or documented, it was possible to deploy a gRPC-aware proxy between Gitaly and
@@ -1117,7 +1208,7 @@ the [relevant epic](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/463).
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To simplify setting a test coverage pattern, in GitLab 15.0 the
@@ -1136,7 +1227,7 @@ testing coverage results in merge requests.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The vulnerability check feature is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0. We encourage you to migrate to the new security approvals feature instead. You can do so by navigating to **Security & Compliance > Policies** and creating a new Scan Result Policy.
@@ -1157,7 +1248,7 @@ The new security approvals feature is similar to vulnerability check. For exampl
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The predefined CI/CD variables that start with `CI_BUILD_*` were deprecated in GitLab 9.0, and will be removed in GitLab 16.0. If you still use these variables, be sure to change to the replacement [predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) which are functionally identical:
@@ -1186,7 +1277,7 @@ The predefined CI/CD variables that start with `CI_BUILD_*` were deprecated in G
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `projectFingerprint` field in the [PipelineSecurityReportFinding](https://docs.gitlab.com/ee/api/graphql/reference/index.html#pipelinesecurityreportfinding)
@@ -1203,7 +1294,7 @@ exposed in the UUID field. Data previously available in the projectFingerprint f
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
@@ -1342,7 +1433,7 @@ and will remove it in GitLab 15.0
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The logging features in GitLab allow users to install the ELK stack (Elasticsearch, Logstash, and Kibana) to aggregate and manage application logs. Users can search for relevant logs in GitLab. However, since deprecating certificate-based integration with Kubernetes clusters and GitLab Managed Apps, we don't have a recommended solution for logging within GitLab. For more information, you can follow the issue for [integrating Opstrace with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
@@ -1356,7 +1447,7 @@ The logging features in GitLab allow users to install the ELK stack (Elasticsear
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
By displaying data stored in a Prometheus instance, GitLab allows users to view performance metrics. GitLab also displays visualizations of these metrics in dashboards. The user can connect to a previously-configured external Prometheus instance, or set up Prometheus as a GitLab Managed App.
@@ -1428,7 +1519,7 @@ in the Vulnerability Report.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Exporting Sidekiq metrics and health checks using a single process and port is deprecated.
@@ -1472,19 +1563,23 @@ Current users of the Static Site Editor can view the [documentation](https://doc
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users can navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab is deprecated in GitLab 14.7, and scheduled for removal in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
</div>
-<div class="deprecation removal-150">
+<div class="deprecation removal-150 breaking-change">
### `artifacts:reports:cobertura` keyword
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.
+
Currently, test coverage visualizations in GitLab only support Cobertura reports. Starting 15.0, the
`artifacts:reports:cobertura` keyword will be replaced by
[`artifacts:reports:coverage_report`](https://gitlab.com/gitlab-org/gitlab/-/issues/344533). Cobertura will be the
@@ -1499,7 +1594,7 @@ only supported report file in 15.0, but this is the first step towards GitLab su
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `merge_user` field (already present in GraphQL) which more correctly identifies who merged a merge request when performing actions (merge when pipeline succeeds, add to merge train) other than a simple merge.
@@ -1518,7 +1613,7 @@ The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 15.0 we are going to limit the number of characters in CI/CD job names to 255. Any pipeline with job names that exceed the 255 character limit will stop working after the 15.0 release.
@@ -1532,7 +1627,7 @@ In GitLab 15.0 we are going to limit the number of characters in CI/CD job names
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We deprecated legacy names for approval status of license policy (blacklisted, approved) in the `managed_licenses` API but they are still used in our API queries and responses. They will be removed in 15.0.
@@ -1548,7 +1643,7 @@ If you are using our License Compliance API you should stop using the `approved`
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `type` and `types` CI/CD keywords will be removed in GitLab 15.0. Pipelines that use these keywords will stop working, so you must switch to `stage` and `stages`, which have the same behavior.
@@ -1562,7 +1657,7 @@ The `type` and `types` CI/CD keywords will be removed in GitLab 15.0. Pipelines
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The API Fuzzing configuration snippet is now being generated client-side and does not require an
@@ -1578,7 +1673,7 @@ which isn't being used in GitLab anymore.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As of 14.6 bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
@@ -1599,7 +1694,7 @@ If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you wi
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 15.0, you can no longer change an instance (shared) runner to a project (specific) runner.
@@ -1617,7 +1712,7 @@ Administrators who need to add runners for multiple projects can register a runn
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/contributing/#breaking-changes).
+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.
@@ -1633,7 +1728,7 @@ In GitLab 15.0 and later, the default value for this configuration option will c
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/contributing/#breaking-changes).
+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.
@@ -1649,7 +1744,7 @@ In milestone 16.0, we will remove the `pipelines` attribute from the API respons
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/contributing/#breaking-changes).
+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.
@@ -1669,7 +1764,7 @@ When checking if a runner is `paused`, API users are advised to check the boolea
Planned removal: GitLab <span class="removal-milestone">15.6</span> (2022-11-22)
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The certificate-based integration with Kubernetes will be [deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/). As a GitLab SaaS customer, on new namespaces, you will no longer be able to integrate GitLab and your cluster using the certificate-based approach as of GitLab 15.0. The integration for current users will be enabled per namespace. The integrations are expected to be switched off completely on GitLab SaaS around 2022 November 22.
@@ -1690,7 +1785,7 @@ GitLab self-managed customers can still use the feature [with a feature flag](ht
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
@@ -1713,7 +1808,7 @@ For updates and details about this deprecation, follow [this epic](https://gitla
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
@@ -1727,7 +1822,7 @@ Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
@@ -1743,7 +1838,7 @@ The `GET /groups/:id/registry/repositories` endpoint will remain, but won't retu
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
@@ -1759,7 +1854,7 @@ If you monitor Value Stream Analytics metrics and rely on the date filter, to av
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
@@ -1775,7 +1870,7 @@ In milestone 15.0, we will completely remove `Version` from `PackageType`.
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
@@ -1789,7 +1884,7 @@ The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprec
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We added a feature flag because [GitLab-#11582](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) changed how public groups use the Dependency Proxy. Prior to this change, you could use the Dependency Proxy without authentication. The change requires authentication to use the Dependency Proxy.
@@ -1805,7 +1900,7 @@ In milestone 15.0, we will remove the feature flag entirely. Moving forward, you
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:
@@ -1824,7 +1919,7 @@ To mitigate possible performance problems, we will remove the `versions` field's
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
@@ -1838,7 +1933,7 @@ In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Ge
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
@@ -1869,7 +1964,7 @@ Starting in 14.5 we are providing packages for openSUSE Leap 15.3, and will stop
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#removed-events) are now deprecated and will be removed in GitLab 15.0.
@@ -1887,7 +1982,7 @@ dramatically slow down GitLab instances. For this reason, they are being removed
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[GitLab Serverless](https://docs.gitlab.com/ee/user/project/clusters/serverless/) is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
@@ -1903,7 +1998,7 @@ We decided to remove the GitLab Serverless features as they never really resonat
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The syntax of [GitLabs database](https://docs.gitlab.com/omnibus/settings/database.html)
@@ -1921,7 +2016,7 @@ This deprecation mainly impacts users compiling GitLab from source because Omnib
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `omniauth-kerberos` gem will be removed in our next major release, GitLab 15.0.
@@ -1970,7 +2065,7 @@ This will result in the rename of the sub-chart: `gitlab/task-runner` to `gitlab
Planned removal: GitLab <span class="removal-milestone">15.6</span> (2022-11-22)
-With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS on November 22, 2022. This was originally planned for May 22, 2022, but in an effort to allow continued maturity of Gitaly Cluster, we have chosen to extend our deprecation of support date. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for further information.
+With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS on November 22, 2022. This was originally planned for May 22, 2022, but in an effort to allow continued maturity of Gitaly Cluster, we have chosen to extend our deprecation of support date. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support/#gitaly-and-nfs) for further information.
Gitaly Cluster offers tremendous benefits for our customers such as:
@@ -1989,7 +2084,7 @@ We encourage customers currently using NFS for Git repositories to plan their mi
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/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The OAuth implicit grant authorization flow will be removed in our next major release, GitLab 15.0. Any applications that use OAuth implicit grant should switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).
diff --git a/doc/update/index.md b/doc/update/index.md
index e9fa2321450..d4412d85355 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -12,11 +12,6 @@ GitLab version is, if you're upgrading to a major version, and so on.
Make sure to read the whole page as it contains information related to every upgrade method.
-NOTE:
-Upgrade GitLab to the latest available patch release, for example `13.8.8` rather than `13.8.0`.
-This includes [versions you must stop at on the upgrade path](#upgrade-paths) as there may
-be fixes for issues relating to the upgrade process.
-
The [maintenance policy documentation](../policy/maintenance.md)
has additional information about upgrading, including:
@@ -46,9 +41,8 @@ There are also instructions when you want to
### Installation from source
-- [Upgrading Community Edition and Enterprise Edition from
- source](upgrading_from_source.md) - The guidelines for upgrading Community
- Edition and Enterprise Edition from source.
+- [Upgrading Community Edition and Enterprise Edition from source](upgrading_from_source.md) -
+ The guidelines for upgrading Community Edition and Enterprise Edition from source.
- [Patch versions](patch_versions.md) guide includes the steps needed for a
patch version, such as 13.2.0 to 13.2.1, and apply to both Community and Enterprise
Editions.
@@ -89,7 +83,7 @@ Background migrations and batched migrations are not the same, so you should che
complete before updating.
Decrease the time required to complete these migrations by increasing the number of
-[Sidekiq workers](../administration/operations/extra_sidekiq_processes.md)
+[Sidekiq workers](../administration/sidekiq/extra_sidekiq_processes.md)
that can process jobs in the `background_migration` queue.
### Background migrations
@@ -118,13 +112,13 @@ sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::Ba
For GitLab 14.0-14.9:
```shell
-sudo gitlab-rails runner -e production 'Gitlab::Database::BackgroundMigration::BatchedMigration.failed.count'
+sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.failed.count'
```
For GitLab 14.10 and later:
```shell
-sudo gitlab-rails runner -e production 'Gitlab::Database::BackgroundMigration::BatchedMigration.with_status(:failed).count'
+sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.with_status(:failed).count'
```
**For installations from source:**
@@ -133,14 +127,14 @@ For GitLab 14.0-14.9:
```shell
cd /home/git/gitlab
-sudo -u git -H bundle exec rails runner -e production 'Gitlab::Database::BackgroundMigration::BatchedMigration.failed.count'
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.failed.count'
```
For GitLab 14.10 and later:
```shell
cd /home/git/gitlab
-sudo -u git -H bundle exec rails runner -e production 'Gitlab::Database::BackgroundMigration::BatchedMigration.with_status(:failed).count'
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.with_status(:failed).count'
```
### Batched background migrations
@@ -333,7 +327,14 @@ sudo -u git -H bundle exec rake gitlab:elastic:list_pending_migrations
### What do you do if your Advanced Search migrations are stuck?
-See [how to retry a halted migration](../integration/advanced_search/elasticsearch.md#retry-a-halted-migration).
+In GitLab 15.0, an Advanced Search migration named `DeleteOrphanedCommit` can be permanently stuck
+in a pending state across upgrades. This issue
+[is corrected in GitLab 15.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89539).
+
+If you are a self-managed customer who uses GitLab 15.0 with Advanced Search, you will experience performance degradation.
+To clean up the migration, upgrade to 15.1 or later.
+
+For other Advanced Search migrations stuck in pending, see [how to retry a halted migration](../integration/advanced_search/elasticsearch.md#retry-a-halted-migration).
### What do you do for the error `Elasticsearch version not compatible`
@@ -381,6 +382,12 @@ accordingly, while also consulting the
`8.11.Z` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> [`11.11.8`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> [`12.10.14`](#12100) -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [`13.12.15`](#13120) -> [`14.0.12`](#1400) -> [`14.3.6`](#1430) -> [`14.9.5`](#1490) -> [`14.10.Z`](#14100) -> [`15.0.Z`](#1500) -> [latest `15.Y.Z`](https://gitlab.com/gitlab-org/gitlab/-/releases)
+NOTE:
+When not explicitly specified, upgrade GitLab to the latest available patch
+release rather than the first patch release, for example `13.8.8` instead of `13.8.0`.
+This includes versions you must stop at on the upgrade path as there may
+be fixes for issues relating to the upgrade process.
+
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.
@@ -458,13 +465,13 @@ NOTE:
Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
-### 15.2.0 (unreleased)
+### 15.2.0
- GitLab installations that have multiple web nodes should be
[upgraded to 15.1](#1510) before upgrading to 15.2 (and later) due to a
configuration change in Rails that can result in inconsistent ETag key
generation.
-- Some Sidekiq workers were renamed in this release. To avoid any disruption, [run the Rake tasks to migrate any pending jobs](../raketasks/sidekiq_job_migration.md#future-jobs) before starting the upgrade to GitLab 15.2.0.
+- Some Sidekiq workers were renamed in this release. To avoid any disruption, [run the Rake tasks to migrate any pending jobs](../administration/sidekiq/sidekiq_job_migration.md#future-jobs) before starting the upgrade to GitLab 15.2.0.
### 15.1.0
@@ -1033,8 +1040,8 @@ In 13.1.0, you must upgrade to either:
Failure to do so results in internal errors in the Gitaly service in some RPCs due
to the use of the new `--end-of-options` Git flag.
-Additionally, in GitLab 13.1.0, the version of [Rails was upgraded from 6.0.3 to
-6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454).
+Additionally, in GitLab 13.1.0, the version of
+[Rails was upgraded from 6.0.3 to 6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454).
The Rails upgrade included a change to CSRF token generation which is
not backwards-compatible - GitLab servers with the new Rails version
generate CSRF tokens that are not recognizable by GitLab servers
diff --git a/doc/update/package/convert_to_ee.md b/doc/update/package/convert_to_ee.md
index 9f8e56c460c..2bf6d2c580b 100644
--- a/doc/update/package/convert_to_ee.md
+++ b/doc/update/package/convert_to_ee.md
@@ -22,6 +22,8 @@ that may require Support intervention.
The steps can be summed up to:
+1. Make a [GitLab backup](../../raketasks/backup_gitlab.md).
+
1. Find the currently installed GitLab version:
**For Debian/Ubuntu**
@@ -67,7 +69,7 @@ The steps can be summed up to:
If you want to use `dpkg`/`rpm` instead of `apt-get`/`yum`, go through the first
step to find the current GitLab version, then follow
[Update using a manually-downloaded package](index.md#upgrade-using-a-manually-downloaded-package),
- and then [add your license](../../user/admin_area/license.md).
+ and then [add your license](../../user/admin_area/license.md).
1. Install the `gitlab-ee` package. The install automatically
uninstalls the `gitlab-ce` package on your GitLab server. `reconfigure`
@@ -114,5 +116,7 @@ The steps can be summed up to:
sudo rm /etc/yum.repos.d/gitlab_gitlab-ce.repo
```
+1. Optional. [Set up the Elasticsearch integration](../../integration/advanced_search/elasticsearch.md) to enable [Advanced Search](../../user/search/advanced_search.md).
+
That's it! You can now use GitLab Enterprise Edition! To update to a newer
version, follow [Update using the official repositories](index.md#upgrade-using-the-official-repositories).
diff --git a/doc/update/package/index.md b/doc/update/package/index.md
index bf1154d1cf5..12a8b6f3190 100644
--- a/doc/update/package/index.md
+++ b/doc/update/package/index.md
@@ -196,20 +196,6 @@ see how to [upgrade to a later version](../../administration/docs_self_host.md#u
## Troubleshooting
-### GitLab 13.7 and later unavailable on Amazon Linux 2
-
-Amazon Linux 2 is not an [officially supported operating system](../../administration/package_information/supported_os.md).
-However, in past the [official package installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
-installed the `el/6` package repository if run on Amazon Linux. From GitLab 13.7, we no longer
-provide `el/6` packages so administrators must run the [installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
-again to update the repository to `el/7`:
-
-```shell
-curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh" | sudo bash
-```
-
-See the [epic on support for GitLab on Amazon Linux 2](https://gitlab.com/groups/gitlab-org/-/epics/2195) for the latest details on official Amazon Linux 2 support.
-
### Get the status of a GitLab installation
```shell
diff --git a/doc/update/plan_your_upgrade.md b/doc/update/plan_your_upgrade.md
index 2374856ff0c..0947bab855f 100644
--- a/doc/update/plan_your_upgrade.md
+++ b/doc/update/plan_your_upgrade.md
@@ -14,7 +14,7 @@ General notes:
- If possible, we recommend you test out the upgrade in a test environment before
updating your production instance. Ideally, your test environment should mimic
your production environment as closely as possible.
-- If [working with Support](https://about.gitlab.com/support/scheduling-upgrade-assistance.html)
+- If [working with Support](https://about.gitlab.com/support/scheduling-upgrade-assistance/)
to create your plan, share details of your architecture, including:
- How is GitLab installed?
- What is the operating system of the node?
@@ -125,12 +125,11 @@ to your instance and then upgrade it for any relevant features you're using.
- Account for any [version-specific update instructions](index.md#version-specific-upgrading-instructions).
- Account for any [version-specific changes](package/index.md#version-specific-changes).
- Check the [OS compatibility with the target GitLab version](../administration/package_information/supported_os.md).
-- Due to background migrations, plan to pause any further upgrades after upgrading
- to a new major version.
+- Due to background migrations, plan to pause before any further upgrades.
[All migrations must finish running](index.md#checking-for-background-migrations-before-upgrading)
before the next upgrade.
- If available in your starting version, consider
- [turning on maintenance mode](../administration/maintenance_mode/) during the
+ [turning on maintenance mode](../administration/maintenance_mode/index.md) during the
upgrade.
- About PostgreSQL:
- On the top bar, select **Menu > Admin**, and look for the version of
@@ -167,6 +166,10 @@ If you're using Geo:
After updating GitLab, upgrade your runners to match
[your new GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions).
+#### GitLab agent for Kubernetes
+
+If you have Kubernetes clusters connected with GitLab, [upgrade your GitLab agents for Kubernetes](../user/clusters/agent/install/index.md#update-the-agent-version) to match your new GitLab version.
+
#### Elasticsearch
After updating GitLab, you may have to upgrade
@@ -185,7 +188,7 @@ If anything doesn't go as planned:
- [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) if
you installed GitLab using the Helm Charts.
- For support:
- - [Contact GitLab Support](https://support.gitlab.com/hc) and,
+ - [Contact GitLab Support](https://support.gitlab.com) and,
if you have one, your Technical Account Manager.
- If [the situation qualifies](https://about.gitlab.com/support/#definitions-of-support-impact)
and [your plan includes emergency support](https://about.gitlab.com/support/#priority-support),
diff --git a/doc/update/removals.md b/doc/update/removals.md
index fa5c016d3ab..cdb35b5faa0 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -55,7 +55,7 @@ The minimum supported browser versions are:
### API: `stale` status returned instead of `offline` or `not_connected`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Runner [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints have changed in 15.0.
@@ -68,7 +68,7 @@ The `not_connected` status is no longer valid. It was replaced with `never_conta
### Audit events for repository push events
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#removed-events) are removed as of GitLab 15.0.
@@ -81,7 +81,7 @@ Please note that we will add high-volume audit events in the future as part of [
### Background upload for object storage
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To reduce the overall complexity and maintenance burden of GitLab's [object storage feature](https://docs.gitlab.com/ee/administration/object_storage.html), support for using `background_upload` has been removed in GitLab 15.0.
@@ -127,7 +127,7 @@ This workaround will be dropped, so we encourage migrating to consolidated objec
### Container Network and Host Security
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
All functionality related to the Container Network Security and Container Host Security categories was deprecated in GitLab 14.8 and is scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to evaluate the following open source projects as potential solutions that can be installed and managed outside of GitLab: [AppArmor](https://gitlab.com/apparmor/apparmor), [Cilium](https://github.com/cilium/cilium), [Falco](https://github.com/falcosecurity/falco), [FluentD](https://github.com/fluent/fluentd), [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/). To integrate these technologies with GitLab, add the desired Helm charts in your copy of the [Cluster Management Project Template](https://docs.gitlab.com/ee/user/clusters/management_project_template.html). Deploy these Helm charts in production by calling commands through GitLab [CI/CD](https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_workflow.html).
@@ -144,7 +144,7 @@ For additional context, or to provide feedback regarding this change, please ref
### Container registry authentication with htpasswd
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Container Registry supports [authentication](https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs/configuration.md#auth) with `htpasswd`. It relies on an [Apache `htpasswd` file](https://httpd.apache.org/docs/2.4/programs/htpasswd.html), with passwords hashed using `bcrypt`.
@@ -177,7 +177,7 @@ The following `geo:db:*` tasks have been removed from GitLab 15.0 and have been
### DS_DEFAULT_ANALYZERS environment variable
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We are removing the `DS_DEFAULT_ANALYZERS` environment variable from Dependency Scanning on May 22, 2022 in 15.0. After this removal, this variable's value will be ignored. To configure which analyzers to run with the default configuration, you should use the `DS_EXCLUDED_ANALYZERS` variable instead.
@@ -185,7 +185,7 @@ We are removing the `DS_DEFAULT_ANALYZERS` environment variable from Dependency
### Dependency Scanning default Java version changed to 17
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
For Dependency Scanning, the default version of Java that the scanner expects will be updated from 11 to 17. Java 17 is [the most up-to-date Long Term Support (LTS) version](https://en.wikipedia.org/wiki/Java_version_history). Dependency Scanning continues to support the same [range of versions (8, 11, 13, 14, 15, 16, 17)](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#supported-languages-and-package-managers), only the default version is changing. If your project uses the previous default of Java 11, be sure to [set the `DS_JAVA_VERSION` variable to match](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning). Please note that consequently the default version of Gradle is now 7.3.3.
@@ -193,7 +193,7 @@ For Dependency Scanning, the default version of Java that the scanner expects wi
### ELK stack logging
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The logging features in GitLab allow users to install the ELK stack (Elasticsearch, Logstash, and Kibana) to aggregate and manage application logs. Users could search for relevant logs in GitLab directly. However, since deprecating certificate-based integration with Kubernetes clusters and GitLab Managed Apps, this feature is no longer available. For more information on the future of logging and observability, you can follow the issue for [integrating Opstrace with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
@@ -201,7 +201,7 @@ The logging features in GitLab allow users to install the ELK stack (Elasticsear
### Elasticsearch 6.8.x in GitLab 15.0
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Elasticsearch 6.8 support has been removed in GitLab 15.0. Elasticsearch 6.8 has reached [end of life](https://www.elastic.co/support/eol).
@@ -213,7 +213,7 @@ View the [version requirements](https://docs.gitlab.com/ee/integration/elasticse
### End of support for Python 3.6 in Dependency Scanning
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
For those using Dependency Scanning for Python projects, we are removing support for the default `gemnasium-python:2` image which uses Python 3.6, as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).
@@ -221,7 +221,7 @@ For those using Dependency Scanning for Python projects, we are removing support
### External status check API breaking changes
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [external status check API](https://docs.gitlab.com/ee/api/status_checks.html) was originally implemented to
@@ -243,7 +243,7 @@ To align with this change, API calls to list external status checks also return
### GitLab Serverless
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
All functionality related to GitLab Serverless was deprecated in GitLab 14.3 and is scheduled for removal in GitLab 15.0. Users who need a replacement for this functionality are encouraged to explore using the following technologies with GitLab CI/CD:
@@ -256,7 +256,7 @@ For additional context, or to provide feedback regarding this change, please ref
### Gitaly nodes in virtual storage
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Configuring the Gitaly nodes directly in the virtual storage's root configuration object has been deprecated in GitLab 13.12 and is no longer supported in GitLab 15.0. You must move the Gitaly nodes under the `'nodes'` key as described in [the Praefect configuration](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#praefect).
@@ -264,7 +264,7 @@ Configuring the Gitaly nodes directly in the virtual storage's root configuratio
### GraphQL permissions change for Package settings
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GitLab Package stage offers a Package Registry, Container Registry, and Dependency Proxy to help you manage all of your dependencies using GitLab. Each of these product categories has a variety of settings that can be adjusted using the API.
@@ -281,7 +281,7 @@ The issue for this removal is [GitLab-#350682](https://gitlab.com/gitlab-org/git
### Jaeger integration
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users could previously navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab was deprecated in GitLab 14.7, and removed in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
@@ -289,7 +289,7 @@ Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distr
### Known host required for GitLab Runner SSH executor
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+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`. 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.
@@ -307,7 +307,7 @@ We have now removed the deprecated legacy names for approval status of license p
### Move Gitaly Cluster Praefect `database_host_no_proxy` and `database_port_no_proxy configs`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Gitaly Cluster configuration keys for `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']` are replaced with `praefect['database_direct_host']` and `praefect['database_direct_port']`.
@@ -315,7 +315,7 @@ The Gitaly Cluster configuration keys for `praefect['database_host_no_proxy']` a
### Move `custom_hooks_dir` setting from GitLab Shell to Gitaly
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.html#create-a-global-server-hook-for-all-repositories) setting is now configured in Gitaly, and is removed from GitLab Shell in GitLab 15.0.
@@ -323,7 +323,7 @@ The [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.
### OAuth implicit grant
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The OAuth implicit grant authorization flow is no longer supported. Any applications that use OAuth implicit grant must switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).
@@ -331,7 +331,7 @@ The OAuth implicit grant authorization flow is no longer supported. Any applicat
### OAuth tokens without an expiration
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab no longer supports OAuth tokens [without an expiration](https://docs.gitlab.com/ee/integration/oauth_provider.html#expiring-access-tokens).
@@ -341,7 +341,7 @@ Any existing token without an expiration has one automatically generated and app
### Optional enforcement of SSH expiration
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Disabling SSH expiration enforcement is unusual from a security perspective and could create unusual situations where an expired
@@ -351,7 +351,7 @@ expiration on all SSH keys.
### Optional enforcement of personal access token expiration
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Allowing expired personal access tokens to be used is unusual from a security perspective and could create unusual situations where an
@@ -376,7 +376,7 @@ If you rely on Java 8 being present in the analyzer environment, you must take a
### Pipelines field from the version field
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:
@@ -389,7 +389,7 @@ To mitigate possible performance problems, we will remove the `versions` field's
### Pseudonymizer
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Pseudonymizer feature is generally unused, can cause production issues with large databases, and can interfere with object storage development.
@@ -398,7 +398,7 @@ It was removed in GitLab 15.0.
### Request profiling
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) has been removed in GitLab 15.0.
@@ -412,7 +412,7 @@ For more information, check the [summary section of the deprecation issue](https
### Required pipeline configurations in Premium tier
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Required pipeline configuration](https://docs.gitlab.com/ee/user/admin_area/settings/continuous_integration.html#required-pipeline-configuration) helps to define and mandate organization-wide pipeline configurations and is a requirement at an executive and organizational level. To align better with our [pricing philosophy](https://about.gitlab.com/company/pricing/#three-tiers), this feature is removed from the Premium tier in GitLab 15.0. This feature continues to be available in the GitLab Ultimate tier.
@@ -427,7 +427,7 @@ This change also helps GitLab remain consistent in our tiering strategy with the
### Retire-JS Dependency Scanning tool
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We have removed support for retire.js from Dependency Scanning as of May 22, 2022 in GitLab 15.0. JavaScript scanning functionality will not be affected as it is still being covered by Gemnasium.
@@ -437,7 +437,7 @@ If you have explicitly excluded retire.js using the `DS_EXCLUDED_ANALYZERS` vari
### Runner status `not_connected` API value
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+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](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints
@@ -470,7 +470,7 @@ If you rely on .NET 2.1 support being present in the analyzer image by default,
### SUSE Linux Enterprise Server 12 SP2
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
@@ -496,7 +496,7 @@ For further details, see [the deprecation issue for this change](https://gitlab.
### Self-managed certificate-based integration with Kubernetes feature flagged
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 15.0 the certificate-based integration with Kubernetes will be disabled by default.
@@ -512,7 +512,7 @@ For updates and details, follow [this epic](https://gitlab.com/groups/gitlab-org
### Sidekiq configuration for metrics and health checks
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 15.0, you can no longer serve Sidekiq metrics and health checks over a single address and port.
@@ -536,7 +536,7 @@ The Static Site Editor was deprecated in GitLab 14.7 and the feature is being re
### Support for `gitaly['internal_socket_dir']`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Gitaly introduced a new directory that holds all runtime data Gitaly requires to operate correctly. This new directory replaces the old internal socket directory, and consequentially the usage of `gitaly['internal_socket_dir']` was deprecated in favor of `gitaly['runtime_dir']`.
@@ -544,7 +544,7 @@ Gitaly introduced a new directory that holds all runtime data Gitaly requires to
### Support for legacy format of `config/database.yml`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The syntax of [GitLab's database](https://docs.gitlab.com/omnibus/settings/database.html)
@@ -558,7 +558,7 @@ Instructions are available [in the source update documentation](https://docs.git
### Test coverage project CI/CD setting
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To specify a test coverage pattern, in GitLab 15.0 the
@@ -571,7 +571,7 @@ To set test coverage parsing, use the project’s `.gitlab-ci.yml` file by provi
### The `promote-db` command is no longer available from `gitlab-ctl`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. The `gitlab-ctl promote-db` command has been removed in GitLab 15.0.
@@ -579,7 +579,7 @@ In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Ge
### Update to the Container Registry group-level API
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
@@ -589,7 +589,7 @@ The `GET /groups/:id/registry/repositories` endpoint will remain, but won't retu
### Versions from `PackageType`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
@@ -599,7 +599,7 @@ In GitLab 15.0, we will completely remove `Version` from `PackageType`.
### Vulnerability Check
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The vulnerability check feature was deprecated in GitLab 14.8 and is scheduled for removal in GitLab 15.0. We encourage you to migrate to the new security approvals feature instead. You can do so by navigating to **Security & Compliance > Policies** and creating a new Scan Result Policy.
@@ -614,13 +614,17 @@ The new security approvals feature is similar to vulnerability check. For exampl
### `Managed-Cluster-Applications.gitlab-ci.yml`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `Managed-Cluster-Applications.gitlab-ci.yml` CI/CD template is being removed. If you need an alternative, try the [Cluster Management project template](https://gitlab.com/gitlab-org/gitlab/-/issues/333610) instead. If your are not ready to move, you can copy the [last released version](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/v14.10.1/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml) of the template into your project.
### `artifacts:reports:cobertura` keyword
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
As of GitLab 15.0, the [`artifacts:reports:cobertura`](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscobertura-removed)
keyword has been [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/344533) by
[`artifacts:reports:coverage_report`](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report).
@@ -629,7 +633,7 @@ Cobertura is the only supported report file, but this is the first step towards
### `defaultMergeCommitMessageWithDescription` GraphQL API field
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
@@ -637,7 +641,7 @@ The GraphQL API field `defaultMergeCommitMessageWithDescription` has been remove
### `dependency_proxy_for_private_groups` feature flag
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
A feature flag was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) in GitLab 13.7 as part of the change to require authentication to use the Dependency Proxy. Before GitLab 13.7, you could use the Dependency Proxy without authentication.
@@ -647,7 +651,7 @@ In GitLab 15.0, we will remove the feature flag, and you must always authenticat
### `omniauth-kerberos` gem
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `omniauth-kerberos` gem is no longer supported. This gem has not been maintained and has very little usage. Therefore, we
@@ -660,7 +664,7 @@ We are not removing Kerberos SPNEGO integration. We are removing the old passwor
### `promote-to-primary-node` command from `gitlab-ctl`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` has been removed in GitLab 15.0.
@@ -668,7 +672,7 @@ In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Ge
### `push_rules_supersede_code_owners` feature flag
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `push_rules_supersede_code_owners` feature flag has been removed in GitLab 15.0. From now on, push rules will supersede the `CODEOWNERS` file. The code owners feature is no longer available for access control.
@@ -676,7 +680,7 @@ The `push_rules_supersede_code_owners` feature flag has been removed in GitLab 1
### `type` and `types` keyword from CI/CD configuration
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `type` and `types` CI/CD keywords is removed in GitLab 15.0, so pipelines that use these keywords fail with a syntax error. Switch to `stage` and `stages`, which have the same behavior.
@@ -684,7 +688,7 @@ The `type` and `types` CI/CD keywords is removed in GitLab 15.0, so pipelines th
### bundler-audit Dependency Scanning tool
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal, Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
@@ -696,7 +700,7 @@ If you have explicitly excluded bundler-audit using the `DS_EXCLUDED_ANALYZERS`
### Permissions change for downloading Composer dependencies
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The GitLab Composer repository can be used to push, search, fetch metadata about, and download PHP dependencies. All these actions require authentication, except for downloading dependencies.
@@ -708,7 +712,7 @@ Downloading Composer dependencies without authentication is deprecated in GitLab
### Integrated error tracking disabled by default
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.4, GitLab released an integrated error tracking backend that replaces Sentry. This feature caused database performance issues. In GitLab 14.9, integrated error tracking is removed from GitLab.com, and turned off by default in GitLab self-managed. While we explore the future development of this feature, please consider switching to the Sentry backend by [changing your error tracking to Sentry in your project settings](https://docs.gitlab.com/ee/operations/error_tracking.html#sentry-error-tracking).
@@ -779,7 +783,7 @@ The minimum supported browser versions are:
### Auto Deploy CI template v1
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.0, we will update the [Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/stages.html#auto-deploy) CI template to the latest version. This includes new features, bug fixes, and performance improvements with a dependency on the v2 [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image). Auto Deploy CI template v1 is deprecated going forward.
@@ -789,7 +793,7 @@ Since the v1 and v2 versions are not backward-compatible, your project might enc
### Breaking changes to Terraform CI template
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab 14.0 renews the Terraform CI template to the latest version. The new template is set up for the GitLab Managed Terraform state, with a dependency on the GitLab `terraform-images` image, to provide a good user experience around GitLab's Infrastructure-as-Code features.
@@ -799,7 +803,7 @@ The current stable and latest templates are not compatible, and the current late
### Code Quality RuboCop support changed
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#rubocop-errors).
@@ -809,7 +813,7 @@ Relevant Issue: [Default `codeclimate-rubocop` engine does not support Ruby 2.6+
### Container Scanning Engine Clair
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Clair, the default container scanning engine, was deprecated in GitLab 13.9 and is removed from GitLab 14.0 and replaced by Trivy. We advise customers who are customizing variables for their container scanning job to [follow these instructions](https://docs.gitlab.com/ee/user/application_security/container_scanning/#change-scanners) to ensure that their container scanning jobs continue to work.
@@ -817,7 +821,7 @@ Clair, the default container scanning engine, was deprecated in GitLab 13.9 and
### DAST default template stages
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.0, we've removed the stages defined in the current `DAST.gitlab-ci.yml` template to avoid the situation where the template overrides manual changes made by DAST users. We're making this change in response to customer issues where the stages in the template cause problems when used with customized DAST configurations. Because of this removal, `gitlab-ci.yml` configurations that do not specify a `dast` stage must be updated to include this stage.
@@ -825,7 +829,7 @@ In GitLab 14.0, we've removed the stages defined in the current `DAST.gitlab-ci.
### DAST environment variable renaming and removal
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab 13.8 renamed multiple environment variables to support their broader usage in different workflows. In GitLab 14.0, the old variables have been permanently removed and will no longer work. Any configurations using these variables must be updated to the new variable names. Any scans using these variables in GitLab 14.0 and later will fail to be configured correctly. These variables are:
@@ -842,7 +846,7 @@ GitLab 13.8 renamed multiple environment variables to support their broader usag
### Default Browser Performance testing job renamed in GitLab 14.0
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
@@ -852,7 +856,7 @@ Relevant Issue: [Rename default Browser Performance Testing job](https://gitlab.
### Default DAST spider begins crawling at target URL
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab 14.0, DAST has removed the current method of resetting the scan to the hostname when starting to spider. Prior to GitLab 14.0, the spider would not begin at the specified target path for the URL but would instead reset the URL to begin crawling at the host root. GitLab 14.0 changes the default for the new variable `DAST_SPIDER_START_AT_HOST` to `false` to better support users' intention of beginning spidering and scanning at the specified target URL, rather than the host root URL. This change has an added benefit: scans can take less time, if the specified path does not contain links to the entire site. This enables easier scanning of smaller sections of an application, rather than crawling the entire app during every scan.
@@ -860,7 +864,7 @@ In GitLab 14.0, DAST has removed the current method of resetting the scan to the
### Default branch name for new repositories now `main`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Every Git repository has an initial branch, which is named `master` by default. It's the first branch to be created automatically when you create a new repository. Future [Git versions](https://lore.kernel.org/git/pull.656.v4.git.1593009996.gitgitgadget@gmail.com/) will change the default branch name in Git from `master` to `main`. In coordination with the Git project and the broader community, [GitLab has changed the default branch name](https://gitlab.com/gitlab-org/gitlab/-/issues/223789) for new projects on both our SaaS (GitLab.com) and self-managed offerings starting with GitLab 14.0. This will not affect existing projects.
@@ -872,7 +876,7 @@ For more information, check out our [blog post](https://about.gitlab.com/blog/20
### Dependency Scanning
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As mentioned in [13.9](https://about.gitlab.com/releases/2021/02/22/gitlab-13-9-released/#deprecations-for-dependency-scanning) and [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/) several removals for Dependency Scanning take effect.
@@ -884,7 +888,7 @@ Previously, to prevent the Gemnasium analyzers to fetch the advisory database at
### Deprecated GraphQL fields
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In accordance with our [GraphQL deprecation and removal process](https://docs.gitlab.com/ee/api/graphql/#deprecation-process), the following fields that were deprecated prior to 13.7 are [fully removed in 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/267966):
@@ -899,7 +903,7 @@ In accordance with our [GraphQL deprecation and removal process](https://docs.gi
### DevOps Adoption API Segments
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The first release of the DevOps Adoption report had a concept of **Segments**. Segments were [quickly removed from the report](https://gitlab.com/groups/gitlab-org/-/epics/5251) because they introduced an additional layer of complexity on top of **Groups** and **Projects**. Subsequent iterations of the DevOps Adoption report focus on comparing adoption across groups rather than segments. GitLab 14.0 removes all references to **Segments** [from the GraphQL API](https://gitlab.com/gitlab-org/gitlab/-/issues/324414) and replaces them with **Enabled groups**.
@@ -907,7 +911,7 @@ The first release of the DevOps Adoption report had a concept of **Segments**. S
### Disk source configuration for GitLab Pages
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration/pages/#gitlab-api-based-configuration) has been available since GitLab 13.0. It replaces the unsupported `disk` source configuration removed in GitLab 14.0, which can no longer be chosen. You should stop using `disk` source configuration, and move to `gitlab` for an API-based configuration. To migrate away from the 'disk' source configuration, set `gitlab_pages['domain_config_source'] = "gitlab"` in your `/etc/gitlab/gitlab.rb` file. We recommend you migrate before updating to GitLab 14.0, to identify and troubleshoot any potential problems before upgrading.
@@ -915,7 +919,7 @@ GitLab Pages [API-based configuration](https://docs.gitlab.com/ee/administration
### Experimental prefix in Sidekiq queue selector options
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab supports a [queue selector](https://docs.gitlab.com/ee/administration/operations/extra_sidekiq_processes.html#queue-selector) to run only a subset of background jobs for a given process. When it was introduced, this option had an 'experimental' prefix (`experimental_queue_selector` in Omnibus, `experimentalQueueSelector` in Helm charts).
@@ -925,7 +929,7 @@ As announced in the [13.6 release post](https://about.gitlab.com/releases/2020/1
### External Pipeline Validation Service Code Changes
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
For self-managed instances using the experimental [external pipeline validation service](https://docs.gitlab.com/ee/administration/external_pipeline_validation.html), the range of error codes GitLab accepts will be reduced. Currently, pipelines are invalidated when the validation service returns a response code from `400` to `499`. In GitLab 14.0 and later, pipelines will be invalidated for the `406: Not Accepted` response code only.
@@ -933,7 +937,7 @@ For self-managed instances using the experimental [external pipeline validation
### Geo Foreign Data Wrapper settings
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As [announced in GitLab 13.3](https://about.gitlab.com/releases/2020/08/22/gitlab-13-3-released/#geo-foreign-data-wrapper-settings-deprecated), the following configuration settings in `/etc/gitlab/gitlab.rb` have been removed in 14.0:
@@ -946,7 +950,7 @@ As [announced in GitLab 13.3](https://about.gitlab.com/releases/2020/08/22/gitla
### GitLab OAuth implicit grant
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab is deprecating the [OAuth 2 implicit grant flow](https://docs.gitlab.com/ee/api/oauth2.html#implicit-grant-flow) as it has been removed for [OAuth 2.1](https://oauth.net/2.1/).
@@ -956,7 +960,7 @@ Migrate your existing applications to other supported [OAuth2 flows](https://doc
### GitLab Runner helper image in GitLab.com Container Registry
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 14.0, we are now pulling the GitLab Runner [helper image](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#helper-image) from the GitLab Container Registry instead of Docker Hub. Refer to [issue #27218](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27218) for details.
@@ -964,7 +968,7 @@ In 14.0, we are now pulling the GitLab Runner [helper image](https://docs.gitlab
### GitLab Runner installation to ignore the `skel` directory
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab Runner 14.0, the installation process will ignore the `skel` directory by default when creating the user home directory. Refer to [issue #4845](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4845) for details.
@@ -972,7 +976,7 @@ In GitLab Runner 14.0, the installation process will ignore the `skel` directory
### Gitaly Cluster SQL primary elector
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Now that Praefect supports a [primary election strategy](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#repository-specific-primary-nodes) for each repository, we have removed the `sql` election strategy.
@@ -983,7 +987,7 @@ If you had configured the `sql` election strategy, you must follow the [migratio
### Global `SAST_ANALYZER_IMAGE_TAG` in SAST CI template
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
With the maturity of GitLab Secure scanning tools, we've needed to add more granularity to our release process. Previously, GitLab shared a major version number for [all analyzers and tools](https://docs.gitlab.com/ee/user/application_security/sast/#supported-languages-and-frameworks). This requires all tools to share a major version, and prevents the use of [semantic version numbering](https://semver.org/). In GitLab 14.0, SAST removes the `SAST_ANALYZER_IMAGE_TAG` global variable in our [managed `SAST.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml) CI template, in favor of the analyzer job variable setting the `major.minor` tag in the SAST vendored template.
@@ -995,7 +999,7 @@ This deprecation and removal changes our [previously announced plan](https://abo
### Hardcoded `master` in CI/CD templates
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Our CI/CD templates have been updated to no longer use hard-coded references to a `master` branch. In 14.0, they all use a variable that points to your project's configured default branch instead. If your CI/CD pipeline relies on our built-in templates, verify that this change works with your current configuration. For example, if you have a `master` branch and a different default branch, the updates to the templates may cause changes to your pipeline behavior. For more information, [read the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324131).
@@ -1003,7 +1007,7 @@ Our CI/CD templates have been updated to no longer use hard-coded references to
### Helm v2 support
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Helm v2 was [officially deprecated](https://helm.sh/blog/helm-v2-deprecation-timeline/) in November of 2020, with the `stable` repository being [de-listed from the Helm Hub](https://about.gitlab.com/blog/2020/11/09/ensure-auto-devops-work-after-helm-stable-repo/) shortly thereafter. With the release of GitLab 14.0, which will include the 5.0 release of the [GitLab Helm chart](https://docs.gitlab.com/charts/), Helm v2 will no longer be supported.
@@ -1013,7 +1017,7 @@ Users of the chart should [upgrade to Helm v3](https://helm.sh/docs/topics/v2_v3
### Legacy DAST domain validation
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The legacy method of DAST Domain Validation for CI/CD scans was deprecated in GitLab 13.8, and is removed in GitLab 14.0. This method of domain validation only disallows scans if the `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` environment variable is set to `true` in the `gitlab-ci.yml` file, and a `Gitlab-DAST-Permission` header on the site is not set to `allow`. This two-step method required users to opt in to using the variable before they could opt out from using the header.
@@ -1023,7 +1027,7 @@ For more information, see the [removal issue](https://gitlab.com/gitlab-org/gitl
### Legacy feature flags
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Legacy feature flags became read-only in GitLab 13.4. GitLab 14.0 removes support for legacy feature flags, so you must migrate them to the [new version](https://docs.gitlab.com/ee/operations/feature_flags.html). You can do this by first taking a note (screenshot) of the legacy flag, then deleting the flag through the API or UI (you don't need to alter the code), and finally create a new Feature Flag with the same name as the legacy flag you deleted. Also, make sure the strategies and environments match the deleted flag. We created a [video tutorial](https://www.youtube.com/watch?v=CAJY2IGep7Y) to help with this migration.
@@ -1031,7 +1035,7 @@ Legacy feature flags became read-only in GitLab 13.4. GitLab 14.0 removes suppor
### Legacy fields from DAST report
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As a part of the migration to a common report format for all of the Secure scanners in GitLab, DAST is making changes to the DAST JSON report. Certain legacy fields were deprecated in 13.8 and have been completely removed in 14.0. These fields are `@generated`, `@version`, `site`, and `spider`. This should not affect any normal DAST operation, but does affect users who consume the JSON report in an automated way and use these fields. Anyone affected by these changes, and needs these fields for business reasons, is encouraged to open a new GitLab issue and explain the need.
@@ -1041,7 +1045,7 @@ For more information, see [the removal issue](https://gitlab.com/gitlab-org/gitl
### Legacy storage
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As [announced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#planned-removal-of-legacy-storage-in-14.0), [legacy storage](https://docs.gitlab.com/ee/administration/repository_storage_types.html#legacy-storage) has been removed in GitLab 14.0.
@@ -1049,7 +1053,7 @@ As [announced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitla
### License Compliance
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 13.0, we deprecated the License-Management CI template and renamed it License-Scanning. We have been providing backward compatibility by warning users of the old template to switch. Now in 14.0, we are completely removing the License-Management CI template. Read about it in [issue #216261](https://gitlab.com/gitlab-org/gitlab/-/issues/216261) or [this blog post](https://about.gitlab.com/blog/2021/02/08/composition-analysis-14-deprecations-and-removals/).
@@ -1057,7 +1061,7 @@ In 13.0, we deprecated the License-Management CI template and renamed it License
### Limit projects returned in `GET /groups/:id/`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To improve performance, we are limiting the number of projects returned from the `GET /groups/:id/` API call to 100. A complete list of projects can still be retrieved with the `GET /groups/:id/projects` API call.
@@ -1065,7 +1069,7 @@ To improve performance, we are limiting the number of projects returned from the
### Make `pwsh` the default shell for newly-registered Windows Runners
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab Runner 13.2, PowerShell Core support was added to the Shell executor. In 14.0, PowerShell Core, `pwsh` is now the default shell for newly-registered Windows runners. Windows `CMD` will still be available as a shell option for Windows runners. Refer to [issue #26419](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26419) for details.
@@ -1073,7 +1077,7 @@ In GitLab Runner 13.2, PowerShell Core support was added to the Shell executor.
### Migrate from `SAST_DEFAULT_ANALYZERS` to `SAST_EXCLUDED_ANALYZERS`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Until GitLab 13.9, if you wanted to avoid running one particular GitLab SAST analyzer, you needed to remove it from the [long string of analyzers in the `SAST.gitlab-ci.yml` file](https://gitlab.com/gitlab-org/gitlab/-/blob/390afc431e7ce1ac253b35beb39f19e49c746bff/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml#L12) and use that to set the [`SAST_DEFAULT_ANALYZERS`](https://docs.gitlab.com/ee/user/application_security/sast/#docker-images) variable in your project's CI file. If you did this, it would exclude you from future new analyzers because this string hard codes the list of analyzers to execute. We avoid this problem by inverting this variable's logic to exclude, rather than choose default analyzers.
@@ -1082,7 +1086,7 @@ Beginning with 13.9, [we migrated](https://gitlab.com/gitlab-org/gitlab/-/blob/1
### Off peak time mode configuration for Docker Machine autoscaling
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab Runner 13.0, [issue #5069](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/5069), we introduced new timing options for the GitLab Docker Machine executor. In GitLab Runner 14.0, we have removed the old configuration option, [off peak time mode](https://docs.gitlab.com/runner/configuration/autoscale.html#off-peak-time-mode-configuration-deprecated).
@@ -1090,7 +1094,7 @@ In GitLab Runner 13.0, [issue #5069](https://gitlab.com/gitlab-org/gitlab-runner
### OpenSUSE Leap 15.1
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Support for [OpenSUSE Leap 15.1 is being deprecated](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5135). Support for 15.1 will be dropped in 14.0. We are now providing support for openSUSE Leap 15.2 packages.
@@ -1098,7 +1102,7 @@ Support for [OpenSUSE Leap 15.1 is being deprecated](https://gitlab.com/gitlab-o
### PostgreSQL 11 support
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab 14.0 requires PostgreSQL 12 or later. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits.
@@ -1108,7 +1112,7 @@ Starting in GitLab 13.7, all new installations default to PostgreSQL version 12.
### Redundant timestamp field from DORA metrics API payload
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
@@ -1116,7 +1120,7 @@ The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora
### Release description in the Tags API
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab 14.0 removes support for the release description in the Tags API. You can no longer add a release description when [creating a new tag](https://docs.gitlab.com/ee/api/tags.html#create-a-new-tag). You also can no longer [create](https://docs.gitlab.com/ee/api/tags.html#create-a-new-release) or [update](https://docs.gitlab.com/ee/api/tags.html#update-a-release) a release through the Tags API. Please migrate to use the [Releases API](https://docs.gitlab.com/ee/api/releases/#create-a-release) instead.
@@ -1124,7 +1128,7 @@ GitLab 14.0 removes support for the release description in the Tags API. You can
### Ruby version changed in `Ruby.gitlab-ci.yml`
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
By default, the `Ruby.gitlab-ci.yml` file has included Ruby 2.5.
@@ -1136,7 +1140,7 @@ Relevant Issue: [Updates Ruby version 2.5 to 3.0](https://gitlab.com/gitlab-org/
### SAST analyzer `SAST_GOSEC_CONFIG` variable
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
With the release of [SAST Custom Rulesets](https://docs.gitlab.com/ee/user/application_security/sast/#customize-rulesets) in GitLab 13.5 we allow greater flexibility in configuration options for our Go analyzer (GoSec). As a result we no longer plan to support our less flexible [`SAST_GOSEC_CONFIG`](https://docs.gitlab.com/ee/user/application_security/sast/#analyzer-settings) analyzer setting. This variable was deprecated in GitLab 13.10.
@@ -1145,7 +1149,7 @@ GitLab 14.0 removes the old `SAST_GOSEC_CONFIG variable`. If you use or override
### Service Templates
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Service Templates are [removed in GitLab 14.0](https://gitlab.com/groups/gitlab-org/-/epics/5672). They were used to apply identical settings to a large number of projects, but they only did so at the time of project creation.
@@ -1155,7 +1159,7 @@ While they solved part of the problem, _updating_ those values later proved to b
### Success and failure for finished build metric conversion
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab Runner 13.5, we introduced `failed` and `success` states for a job. To support Prometheus rules, we chose to convert `success/failure` to `finished` for the metric. In 14.0, the conversion has now been removed. Refer to [issue #26900](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26900) for details.
@@ -1163,7 +1167,7 @@ In GitLab Runner 13.5, we introduced `failed` and `success` states for a job. To
### Terraform template version
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
As we continuously [develop GitLab's Terraform integrations](https://gitlab.com/gitlab-org/gitlab/-/issues/325312), to minimize customer disruption, we maintain two GitLab CI/CD templates for Terraform:
@@ -1182,7 +1186,7 @@ To check the new changes, see the [new "major version" template](https://gitlab.
### Ubuntu 16.04 support
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Ubuntu 16.04 [reached end-of-life in April 2021](https://ubuntu.com/about/release-cycle), and no longer receives maintenance updates. We strongly recommend users to upgrade to a newer release, such as 20.04.
@@ -1192,7 +1196,7 @@ GitLab 13.12 will be the last release with Ubuntu 16.04 support.
### Ubuntu 19.10 (Eoan Ermine) package
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Ubuntu 19.10 (Eoan Ermine) reached end of life on Friday, July 17, 2020. In GitLab Runner 14.0, Ubuntu 19.10 (Eoan Ermine) is no longer available from our package distribution. Refer to [issue #26036](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26036) for details.
@@ -1200,7 +1204,7 @@ Ubuntu 19.10 (Eoan Ermine) reached end of life on Friday, July 17, 2020. In GitL
### Unicorn in GitLab self-managed
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Support for Unicorn](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6078) has been removed in GitLab 14.0 in favor of Puma. [Puma has a multi-threaded architecture](https://docs.gitlab.com/ee/administration/operations/puma.html) which uses less memory than a multi-process application server like Unicorn. On GitLab.com, we saw a 40% reduction in memory consumption by using Puma.
@@ -1208,7 +1212,7 @@ Review the details carefully before upgrading.
### WIP merge requests renamed 'draft merge requests'
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The WIP (work in progress) status for merge requests signaled to reviewers that the merge request in question wasn't ready to merge. We've renamed the WIP feature to **Draft**, a more inclusive and self-explanatory term. **Draft** clearly communicates the merge request in question isn't ready for review, and makes no assumptions about the progress being made toward it. **Draft** also reduces the cognitive load for new users, non-English speakers, and anyone unfamiliar with the WIP acronym.
@@ -1216,7 +1220,7 @@ The WIP (work in progress) status for merge requests signaled to reviewers that
### Web Application Firewall (WAF)
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The Web Application Firewall (WAF) was deprecated in GitLab 13.6 and is removed from GitLab 14.0. The WAF had limitations inherent in the architectural design that made it difficult to meet the requirements traditionally expected of a WAF. By removing the WAF, GitLab is able to focus on improving other areas in the product where more value can be provided to users. Users who currently rely on the WAF can continue to use the free and open source [ModSecurity](https://github.com/SpiderLabs/ModSecurity) project, which is independent from GitLab. Additional details are available in the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271276).
@@ -1224,7 +1228,7 @@ The Web Application Firewall (WAF) was deprecated in GitLab 13.6 and is removed
### Windows Server 1903 image support
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 14.0, we have removed Windows Server 1903. Microsoft ended support for this version on 2020-08-12. Refer to [issue #27551](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27551) for details.
@@ -1232,7 +1236,7 @@ In 14.0, we have removed Windows Server 1903. Microsoft ended support for this v
### Windows Server 1909 image support
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 14.0, we have removed Windows Server 1909. Microsoft ended support for this version on 2021-05-11. Refer to [issue #27899](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27899) for details.
@@ -1240,7 +1244,7 @@ In 14.0, we have removed Windows Server 1909. Microsoft ended support for this v
### `/usr/lib/gitlab-runner` symlink from package
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In GitLab Runner 13.3, a symlink was added from `/user/lib/gitlab-runner/gitlab-runner` to `/usr/bin/gitlab-runner`. In 14.0, the symlink has been removed and the runner is now installed in `/usr/bin/gitlab-runner`. Refer to [issue #26651](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26651) for details.
@@ -1248,7 +1252,7 @@ In GitLab Runner 13.3, a symlink was added from `/user/lib/gitlab-runner/gitlab-
### `?w=1` URL parameter to ignore whitespace changes
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To create a consistent experience for users based on their preferences, support for toggling whitespace changes via URL parameter has been removed in GitLab 14.0.
@@ -1256,7 +1260,7 @@ To create a consistent experience for users based on their preferences, support
### `CI_PROJECT_CONFIG_PATH` variable
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `CI_PROJECT_CONFIG_PATH` [predefined project variable](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
@@ -1268,7 +1272,7 @@ please update them to use `CI_CONFIG_PATH` instead.
### `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In 14.0, we have deactivated the `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag. Refer to issue [#26679](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/26679) for details.
@@ -1276,7 +1280,7 @@ In 14.0, we have deactivated the `FF_RESET_HELPER_IMAGE_ENTRYPOINT` feature flag
### `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL` feature flag
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
In [GitLab Runner 13.1](https://docs.gitlab.com/runner/executors/shell.html#gitlab-131-and-later), [issue #3376](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3376), we introduced `sigterm` and then `sigkill` to a process in the Shell executor. We also introduced a new feature flag, `FF_SHELL_EXECUTOR_USE_LEGACY_PROCESS_KILL`, so you can use the previous process termination sequence. In GitLab Runner 14.0, [issue #6413](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6413), the feature flag has been removed.
@@ -1284,7 +1288,7 @@ In [GitLab Runner 13.1](https://docs.gitlab.com/runner/executors/shell.html#gitl
### `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab Runner 14.0 removes the `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature flag. Refer to [issue #27175](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27175) for details.
@@ -1292,7 +1296,7 @@ GitLab Runner 14.0 removes the `FF_USE_GO_CLOUD_WITH_CACHE_ARCHIVER` feature fla
### `secret_detection_default_branch` job
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
To ensure Secret Detection was scanning both default branches and feature branches, we introduced two separate secret detection CI jobs (`secret_detection_default_branch` and `secret_detection`) in our managed [`Secret-Detection.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml) template. These two CI jobs created confusion and complexity in the CI rules logic. This deprecation moves the `rule` logic into the `script` section, which then determines how the `secret_detection` job is run (historic, on a branch, commits, etc).
@@ -1301,7 +1305,7 @@ If you override or maintain custom versions of `SAST.gitlab-ci.yml` or `Secret-D
### `trace` parameter in `jobs` API
WARNING:
-This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
GitLab Runner was updated in GitLab 13.4 to internally stop passing the `trace` parameter to the `/api/jobs/:id` endpoint. GitLab 14.0 deprecates the `trace` parameter entirely for all other requests of this endpoint. Make sure your [GitLab Runner version matches your GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions) to ensure consistent behavior.
diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md
index b953194b4cf..55561abc009 100644
--- a/doc/update/upgrading_from_ce_to_ee.md
+++ b/doc/update/upgrading_from_ce_to_ee.md
@@ -10,8 +10,7 @@ comments: false
NOTE:
In the past we used separate documents for upgrading from
Community Edition to Enterprise Edition. These documents can be found in the
-[`doc/update` directory of Enterprise Edition's source
-code](https://gitlab.com/gitlab-org/gitlab/-/tree/11-8-stable-ee/doc/update).
+[`doc/update` directory of Enterprise Edition's source code](https://gitlab.com/gitlab-org/gitlab/-/tree/11-8-stable-ee/doc/update).
If you want to upgrade the version only, for example 11.8 to 11.9, *without* changing the
GitLab edition you are using (Community or Enterprise), see the
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 8b921f6d0ce..2df11e8f741 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -119,8 +119,8 @@ rm go1.17.10.linux-amd64.tar.gz
To check you are running the minimum required Git version, see
[Git versions](../install/installation.md#software-requirements).
-From GitLab 13.6, we recommend you use the [Git version provided by
-Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
+From GitLab 13.6, we recommend you use the
+[Git version provided by Gitaly](https://gitlab.com/gitlab-org/gitaly/-/issues/2729)
that:
- Is always at the version required by GitLab.
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index 3cdc6177a4d..0abdd769a6b 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -53,8 +53,8 @@ migrating data. Background migrations are only added in the monthly releases.
Certain major/minor releases may require a set of background migrations to be
finished. To guarantee this, such a release processes any remaining jobs
before continuing the upgrading procedure. While this doesn't require downtime
-(if the above conditions are met) we require that you [wait for background
-migrations to complete](index.md#checking-for-background-migrations-before-upgrading)
+(if the above conditions are met) we require that you
+[wait for background migrations to complete](index.md#checking-for-background-migrations-before-upgrading)
between each major/minor release upgrade.
The time necessary to complete these migrations can be reduced by
increasing the number of Sidekiq workers that can process jobs in the
@@ -395,7 +395,7 @@ HA.
#### In the application node
-According to [official Redis documentation](https://redis.io/topics/admin#upgrading-or-restarting-a-redis-instance-without-downtime),
+According to [official Redis documentation](https://redis.io/docs/manual/admin/#upgrading-or-restarting-a-redis-instance-without-downtime),
the easiest way to update an HA instance using Sentinel is to upgrade the
secondaries one after the other, perform a manual failover from current
primary (running old version) to a recently upgraded secondary (running a new
diff --git a/doc/user/admin_area/broadcast_messages.md b/doc/user/admin_area/broadcast_messages.md
index 959331c16de..a6e6a839912 100644
--- a/doc/user/admin_area/broadcast_messages.md
+++ b/doc/user/admin_area/broadcast_messages.md
@@ -7,7 +7,8 @@ type: reference, howto
# Broadcast messages **(FREE SELF)**
-> Target roles [introduced](https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/461) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `role_targeted_broadcast_messages`. Disabled by default.
+> - Target roles [introduced](https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/461) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `role_targeted_broadcast_messages`. Disabled by default.
+> - Theme [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83251) and background color removed in GitLab 14.10.
GitLab can display broadcast messages to users of a GitLab instance. There are two types of broadcast messages:
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 5fd44cf8697..c689d61ad68 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -169,6 +169,20 @@ By default, impersonation is enabled. GitLab can be configured to [disable imper
![user impersonation button](img/impersonate_user_button_v13_8.png)
+#### User identities
+
+> The ability to see a user's SCIM identity was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294608) in GitLab 15.3.
+
+When using authentication providers, administrators can see the identities for a user:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Overview > Users**.
+1. From the list of users, select a user.
+1. Select **Identities**.
+
+This list shows the user's identities, including SCIM identities. Administrators can use this information to troubleshoot SCIM-related issues and confirm
+the identities being used for an account.
+
#### User Permission Export **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1772) in GitLab 13.8.
@@ -221,7 +235,7 @@ The [Cohorts](user_cohorts.md) tab displays the monthly cohorts of new users and
### Prevent a user from creating groups
-By default, users can create groups. To prevent a user from creating groups:
+By default, users can create groups. To prevent a user from creating a top level group:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users** (`/admin/users`).
@@ -230,6 +244,8 @@ By default, users can create groups. To prevent a user from creating groups:
1. Clear the **Can create group** checkbox.
1. Select **Save changes**.
+It is also possible to [limit which roles can create a subgroup within a group](../group/subgroups/index.md#change-who-can-create-subgroups).
+
### Administering Groups
You can administer all groups in the GitLab instance from the Admin Area's Groups page.
@@ -250,7 +266,7 @@ sort order is by **Last created**.
To search for groups by name, enter your criteria in the search field. The group search is case
insensitive, and applies partial matching.
-To [Create a new group](../group/index.md#create-a-group) select **New group**.
+To [Create a new group](../group/manage.md#create-a-group) select **New group**.
### Administering Topics
@@ -421,7 +437,7 @@ For multi-node systems we recommend ingesting the logs into services like Elasti
The contents of these log files can be useful when troubleshooting a problem.
-For details of these log files and their contents, see [Log system](../../administration/logs.md).
+For details of these log files and their contents, see [Log system](../../administration/logs/index.md).
The content of each log file is listed in chronological order. To minimize performance issues, a maximum 2000 lines of each log file are shown.
diff --git a/doc/user/admin_area/merge_requests_approvals.md b/doc/user/admin_area/merge_requests_approvals.md
index 526e8cd17da..e090d4e7f88 100644
--- a/doc/user/admin_area/merge_requests_approvals.md
+++ b/doc/user/admin_area/merge_requests_approvals.md
@@ -38,4 +38,4 @@ Merge request approval settings that can be set at an instance level are:
See also the following, which are affected by instance-level rules:
- [Project merge request approval rules](../project/merge_requests/approvals/index.md).
-- [Group merge request approval settings](../group/index.md#group-merge-request-approval-settings) available in GitLab 13.9 and later.
+- [Group merge request approval settings](../group/manage.md#group-merge-request-approval-settings) available in GitLab 13.9 and later.
diff --git a/doc/user/admin_area/monitoring/background_migrations.md b/doc/user/admin_area/monitoring/background_migrations.md
index 02d32099c63..87374849674 100644
--- a/doc/user/admin_area/monitoring/background_migrations.md
+++ b/doc/user/admin_area/monitoring/background_migrations.md
@@ -48,6 +48,50 @@ To disable it:
Feature.disable(:execute_batched_migrations_on_schedule)
```
+### Pause batched background migrations in GitLab 14.x
+
+To pause an ongoing batched background migration, use the `disable` command above.
+This command causes the migration to complete the current batch, and then wait to start the next batch.
+
+Use the following database queries to see the state of the current batched background migration:
+
+1. Obtain the ID of the running migration:
+
+ ```sql
+ SELECT
+ id job_class_name,
+ table_name,
+ column_name,
+ job_arguments
+ FROM batched_background_migrations
+ WHERE status <> 3;
+ ```
+
+1. Run this query, replacing `XX` with the ID you obtained in the previous step,
+ to see the status of the migration:
+
+ ```sql
+ SELECT
+ started_at,
+ finished_at,
+ finished_at - started_at AS duration,
+ min_value,
+ max_value,
+ batch_size,
+ sub_batch_size
+ FROM batched_background_migration_jobs
+ WHERE batched_background_migration_id = XX
+ ORDER BY id DESC
+ limit 10;
+ ```
+
+1. Run the query multiple times within a few minutes to ensure no new row has been added.
+ If no new row has been added, the migration has been paused.
+
+1. After confirming the migration has paused, restart the migration (using the `enable`
+ command above) to proceed with the batch when ready. On larger instances,
+ background migrations can take as long as 48 hours to complete each batch.
+
## Automatic batch size optimization
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60133) in GitLab 13.12.
diff --git a/doc/user/admin_area/review_abuse_reports.md b/doc/user/admin_area/review_abuse_reports.md
index ec8e6f2dda4..a5e7fcb1b8e 100644
--- a/doc/user/admin_area/review_abuse_reports.md
+++ b/doc/user/admin_area/review_abuse_reports.md
@@ -26,8 +26,8 @@ The notification email address can also be set and retrieved
## Reporting abuse
-To find out more about reporting abuse, see [abuse reports user
-documentation](../report_abuse.md).
+To find out more about reporting abuse, see
+[abuse reports user documentation](../report_abuse.md).
## Resolving abuse reports
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 bedd648b3e7..e33cf4a9082 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -318,7 +318,7 @@ nginx['client_max_body_size'] = "200m"
### This repository has exceeded its size limit
-If you receive intermittent push errors in your [Rails exceptions log](../../../administration/logs.md#exceptions_jsonlog), like this:
+If you receive intermittent push errors in your [Rails exceptions log](../../../administration/logs/index.md#exceptions_jsonlog), like this:
```plaintext
Your push has been rejected, because this repository has exceeded its size limit.
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 65712a9a85c..afb937494e0 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -48,7 +48,7 @@ tier. Users can continue to access the features in a paid tier without sharing u
### Features available in 14.4 and later
- [Repository size limit](../settings/account_and_limit_settings.md#repository-size-limit).
-- [Group access restriction by IP address](../../group/index.md#group-access-restriction-by-ip-address).
+- [Group access restriction by IP address](../../group/access_and_permissions.md#restrict-group-access-by-ip-address).
NOTE:
Registration is not yet required for participation, but may be added in a future milestone.
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 bb3ee64abac..a35cbe5381a 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
@@ -144,7 +144,7 @@ Note that the bypass only works if the header is set to `1`.
Requests that bypassed the rate limiter because of the bypass header
are marked with `"throttle_safelist":"throttle_bypass_header"` in
-[`production_json.log`](../../../administration/logs.md#production_jsonlog).
+[`production_json.log`](../../../administration/logs/index.md#production_jsonlog).
To disable the bypass mechanism, make sure the environment variable
`GITLAB_THROTTLE_BYPASS_HEADER` is unset or empty.
@@ -170,9 +170,9 @@ the allowlist configuration would be `1,53,217`.
Requests that bypassed the rate limiter because of the user allowlist
are marked with `"throttle_safelist":"throttle_user_allowlist"` in
-[`production_json.log`](../../../administration/logs.md#production_jsonlog).
+[`production_json.log`](../../../administration/logs/index.md#production_jsonlog).
-At application startup, the allowlist is logged in [`auth.log`](../../../administration/logs.md#authlog).
+At application startup, the allowlist is logged in [`auth.log`](../../../administration/logs/index.md#authlog).
## Try out throttling settings before enforcing them
@@ -208,7 +208,7 @@ non-protected paths can be done by setting
To enable dry run mode for all throttles, the variable can be set to `*`.
Setting a throttle to dry run mode logs a message to the
-[`auth.log`](../../../administration/logs.md#authlog) when it would hit the limit, while letting the
+[`auth.log`](../../../administration/logs/index.md#authlog) when it would hit the limit, while letting the
request continue as normal. The log message contains an `env` field set to `track`. The `matched`
field contains the name of throttle that was hit.
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 8a9db68b34f..118d375da01 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -20,7 +20,7 @@ To access the visibility and access control options:
## Define which roles can create projects
Instance-level protections for project creation define which roles can
-[add projects to a group](../../group/index.md#specify-who-can-add-projects-to-a-group)
+[add projects to a group](../../group/manage.md#specify-who-can-add-projects-to-a-group)
on the instance. To alter which roles have permission to create projects:
1. Sign in to GitLab as a user with Administrator access level.
@@ -53,6 +53,7 @@ By default both administrators and anyone with the **Owner** role can delete a p
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2 for groups created after August 12, 2021.
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/352960) from default delayed project deletion in GitLab 15.1.
> - [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89466) in GitLab 15.1.
+> - [Disabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95495) in GitLab 15.3.
Instance-level protection against accidental deletion of groups and projects.
@@ -102,9 +103,9 @@ In GitLab 15.1 and later, delayed group deletion can be enabled by setting **Del
Alternatively, projects that are marked for removal can be deleted immediately. To do so:
-1. [Restore the project](../../project/settings/#restore-a-project).
+1. [Restore the project](../../project/settings/index.md#restore-a-project).
1. Delete the project as described in the
- [Administering Projects page](../../admin_area/#administering-projects).
+ [Administering Projects page](../../admin_area/index.md#administering-projects).
## Configure project visibility defaults
diff --git a/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png b/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
deleted file mode 100644
index 2bfde7beead..00000000000
--- a/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png b/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
deleted file mode 100644
index 0b30aff2c7a..00000000000
--- a/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png b/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
deleted file mode 100644
index e0b3c54dee2..00000000000
--- a/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index f699fa6d0fb..41547430e88 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -8,8 +8,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Instance-level analytics
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab 12.2.
-
Instance-level analytics make it possible to aggregate analytics across
GitLab, so that users can view information across multiple projects and groups
in one place.
@@ -18,8 +16,7 @@ in one place.
## Group-level analytics
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) in GitLab 12.8.
-> - Moved to GitLab Premium in 13.9.
+> Moved to GitLab Premium in 13.9.
GitLab provides several analytics features at the group level. Some of these features require you to use a higher tier than GitLab Free.
@@ -50,7 +47,7 @@ You can use GitLab to review analytics at the project level. Some of these featu
The following analytics features are available for users to create personalized views:
-- [Application Security](../application_security/security_dashboard/#security-center)
+- [Application Security](../application_security/security_dashboard/index.md#security-center)
Be sure to review the documentation page for this feature for GitLab tier requirements.
@@ -124,14 +121,14 @@ To retrieve metrics for change failure rate, use the [GraphQL](../../api/graphql
### Supported DORA metrics in GitLab
-| Metric | Level | API | UI chart | Comments |
-|---------------------------|-------------------------|-------------------------------------|---------------------------------------|-------------------------------|
-| `deployment_frequency` | Project | [GitLab 13.7 and later](../../api/dora/metrics.md) | GitLab 14.8 and later | The previous API endpoint was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
-| `deployment_frequency` | Group | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 13.12 and later | |
-| `lead_time_for_changes` | Project | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 13.11 and later | Unit in seconds. Aggregation method is median. |
-| `lead_time_for_changes` | Group | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 14.0 and later | Unit in seconds. Aggregation method is median. |
-| `time_to_restore_service` | Project and group | [GitLab 14.9 and later](../../api/dora/metrics.md) | GitLab 15.1 and later | Unit in days. Aggregation method is median. |
-| `change_failure_rate` | Project and group | [GitLab 14.10 and later](../../api/dora/metrics.md) | GitLab 15.2 and later | Percentage of deployments. | |
+| Metric | Level | API | UI chart | Comments |
+|---------------------------|-------------------|-----------------------------------------------------|------------------------|----------|
+| `deployment_frequency` | Project | [GitLab 13.7 and later](../../api/dora/metrics.md) | GitLab 14.8 and later | The previous API endpoint was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
+| `deployment_frequency` | Group | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 13.12 and later | |
+| `lead_time_for_changes` | Project | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 13.11 and later | Unit in seconds. Aggregation method is median. |
+| `lead_time_for_changes` | Group | [GitLab 13.10 and later](../../api/dora/metrics.md) | GitLab 14.0 and later | Unit in seconds. Aggregation method is median. |
+| `time_to_restore_service` | Project and group | [GitLab 14.9 and later](../../api/dora/metrics.md) | GitLab 15.1 and later | Unit in days. Aggregation method is median. |
+| `change_failure_rate` | Project and group | [GitLab 14.10 and later](../../api/dora/metrics.md) | GitLab 15.2 and later | Percentage of deployments. |
## Definitions
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 29f2ec79800..038b2f0c97e 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -31,12 +31,12 @@ To view merge request analytics:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Merge request**.
-## View merge requests merged per month
+## View the number of merge requests in a date range
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232651) in GitLab 13.3.
> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229266) in GitLab 13.4
-To view the number of merge requests merged per month:
+To view the number of merge requests merged during a specific date range:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Merge request**.
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index be710f8cbd7..f8b28ead155 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -4,103 +4,65 @@ 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
---
-# Productivity Analytics **(PREMIUM)**
+# Productivity analytics **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12079) in GitLab 12.3.
+You can use productivity analytics to identify:
-Track development velocity with Productivity Analytics.
+- Your development velocity based on how long it takes for a merge request to merge.
+- The most time consuming merge requests and potential causes.
+- Authors, labels, or milestones with the longest time to merge, or most changes.
-For many companies, the development cycle is a black box and getting an estimate of how
-long, on average, it takes to deliver features is an enormous endeavor.
+Use productivity analytics to view the following merge request statistics for your groups:
-While [Value Stream Analytics](../analytics/value_stream_analytics.md) focuses on the entire
-Software Development Life Cycle (SDLC) process, Productivity Analytics provides a way for Engineering Management to drill down in a systematic way to uncover patterns and causes for success or failure at an individual, project, or group level.
+- Amount of time between merge request creation and merge.
+- Amount of time between commits, comments, and merge.
+- Complexity of changes, like number of lines of code per commit and number of files.
-Productivity can slow down for many reasons ranging from degrading codebase to quickly growing teams. To investigate, department or team leaders can start by visualizing the time it takes for merge requests to be merged.
+To view merge request data for projects, use [Merge request analytics](../analytics/merge_request_analytics.md).
-## Visualizations and metrics
+## View productivity analytics
-With Productivity Analytics, GitLab users can:
+Prerequisite:
-- Visualize typical merge request (MR) lifetime and statistics. A histogram shows the distribution of the time elapsed between creating and merging merge requests.
-- Drill down into the most time consuming merge requests, select outliers, and filter subsequent charts to investigate potential causes.
-- Filter by group, project, author, label, milestone, or a specific date range. For example, filter down to the merge requests of a specific author in a group or project during a milestone or specific date range.
-- Measure velocity over time. To observe progress, visualize the trends of each metric from the charts over time. Zoom in on a particular date range if you notice outliers.
+- You must have at least the Reporter role for the group.
-## Metrics charts
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Analytics > Productivity**.
+1. Optional. Filter results:
+ 1. Select a project from the dropdown list.
+ 1. To filter results by author, milestone, or label,
+ select **Filter results...** and enter a value.
+ 1. To adjust the date range:
+ - In the **From** field, select a start date.
+ - In the **To** field, select an end date.
-To access the charts, navigate to a group's sidebar and select **Analytics > Productivity Analytics**.
-Metrics and visualizations of **merged** merge requests are available on a project or group level.
+## View time metrics for merge requests
-### Time to merge
+Use the following charts in productivity analytics to view the velocity of your merge requests:
-The **Time to merge** histogram shows the number of merge requests and the number
-of days it took to merge after creation. Select a column to filter subsequent charts.
+- **Time to merge**: number of days it took for a
+merge requests to merge after they were created.
+- **Trendline**: number of merge requests that were merged in a specific time period.
-![Metrics for number of days merge requests per number of days](img/productivity_analytics_time_to_merge_v14_4.png)
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Analytics > Productivity**.
-### Trendline
+To filter time metrics:
-The **Trendline** scatterplot shows all merge requests on a certain date,
-and the days it took to complete the action and a 30 day rolling median. Select the dropdown to view:
+1. To filter the **Trendline** chart, in the **Time to merge** chart, select a column.
+1. To view a specific merge request, below the charts, select a merge request from the **List**.
-- Time from first commit to first comment.
-- Time from first comment until last commit.
-- Time from last commit to merge.
-- Number of commits per merge request.
-- Number of lines of code (LOC) per commit.
-- Number of files touched.
+## View commit statistics
-![Metrics for amount of merge requests merged on a certain date](img/productivity_analytics_trendline_v14_4.png)
+To view commit statistics for your group:
-### Commits and merge request size
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Analytics > Productivity**.
+1. Under the **Trendline** scatterplot, view the commit statistics:
+ - The left histogram shows the number of hours between commits, comments, and merges.
+ - The right histogram shows the number of commits and changes per merge request.
-Under the **Trendline** scatterplot, the left-side histogram shows
-the time taken (in hours) between commits and comments until the merge
-request is merged. Select the dropdown to view:
+To filter commit statistics:
-- Time from first commit to first comment.
-- Time from first comment until last commit.
-- Time from last commit to merge.
-
-The right-side histogram shows the size or complexity of a merge request.
-Select the dropdown to view:
-
-- Number of commits per merge request.
-- Number of lines of code (LOC) per commit.
-- Number of files touched.
-
-![Metrics for amount of commits and complexity of changes per merge request.](img/product_analytics_commits_per_mr_v14_4.png)
-
-### Merge request list
-
-The **List** table shows a list of merge requests with their respective time duration metrics.
-
-Sort metrics by:
-
-- Time from first commit to first comment.
-- Time from first comment until last commit.
-- Time from last commit to merge.
-
-Filter metrics by:
-
-- Number of commits per merge request.
-- Number of lines of code per commit.
-- Number of files touched.
-
-## Filter by date range
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13188) in GitLab 12.4.
-
-You can filter analytics based on a date range. To filter results:
-
-1. Select a group.
-1. Optional. Select a project.
-1. Select a date range by using the available date pickers.
-
-## Permissions
-
-The **Productivity Analytics** dashboard can be accessed only:
-
-- On [GitLab Premium](https://about.gitlab.com/pricing/) and above.
-- By users with at least the Reporter role.
+1. To view different types of commit data, select the dropdown list next to each histogram.
+1. To view a specific merge request, below the charts, select a merge request from the **List**.
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 96236f60417..80e4700c34c 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -1677,7 +1677,7 @@ For more information, see [Offline environments](../offline_deployments/index.md
## Troubleshooting
-### Error waiting for API Security 'http://127.0.0.1:5000' to become available
+### `Error waiting for API Security 'http://127.0.0.1:5000' to become available`
A bug exists in versions of the API Fuzzing analyzer prior to v1.6.196 that can cause a background process to fail under certain conditions. The solution is to update to a newer version of the DAST API analyzer.
@@ -1690,7 +1690,7 @@ If the issue is occurring with versions v1.6.196 or greater, please contact Supp
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.
-### Error, the OpenAPI document is not valid. Errors were found during validation of the document using the published OpenAPI schema
+### `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.
@@ -1719,7 +1719,7 @@ For OpenAPI Specifications that are generated automatically validation errors ar
1. Alternatively, you can check the log output and look for schema validation warnings. They are prefixed with messages such as `OpenAPI 2.0 schema validation error` or `OpenAPI 3.0.x schema validation error`. Each failed validation provides extra information about `location` and `description`. Correct each of the validation failures and then resubmit the OpenAPI doc. Note that JSON Schema validation message might not be easy to understand. This is why we recommend the use of editors to validate document.
1. Once the validation issues are resolved, re-run your pipeline.
-### Failed to start scanner session (version header not found)
+### `Failed to start scanner session (version header not found)`
The API Fuzzing engine outputs an error message when it cannot establish a connection with the scanner application component. The error message is shown in the job output window of the `apifuzzer_fuzz` job. A common cause of this issue is changing the `FUZZAPI_API` variable from its default.
@@ -1733,7 +1733,7 @@ The API Fuzzing engine outputs an error message when it cannot establish a conne
- Remove the `FUZZAPI_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the API Fuzzing CI/CD template. We recommend this method instead of manually setting a value.
- If removing the variable is not possible, check to see if this value has changed in the latest version of the [API Fuzzing CI/CD template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
-### Application cannot determine the base URL for the target API
+### `Application cannot determine the base URL for the target API`
The API Fuzzing analyzer 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.
@@ -1802,7 +1802,7 @@ To detect and correct elements that don't comply with the OpenAPI specifications
| Editor | OpenAPI 2.0 | OpenAPI 3.0.x | OpenAPI 3.1.x |
| -- | -- | -- | -- |
| [Swagger Editor](https://editor.swagger.io/) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{dotted-circle}** YAML, JSON |
-| [Stoplight Studio](https://stoplight.io/studio/) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON |
+| [Stoplight Studio](https://stoplight.io/studio) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON |
If your OpenAPI document is generated manually, load your document in the editor and fix anything that is non-compliant. If your document is generated automatically, load it in your editor to identify the issues in the schema, then go to the application and perform the corrections based on the framework you are using.
@@ -1826,7 +1826,7 @@ API Security can still try to consume an OpenAPI document that does not fully co
FUZZAPI_OPENAPI_RELAXED_VALIDATION: On
```
-### No operation in the OpenAPI document is consuming any supported media type
+### `No operation in the OpenAPI document is consuming any supported media type`
API Security uses the specified media types in the OpenAPI document to generate requests. If no request can be created due to the lack of supported media types, then an error will be thrown.
@@ -1844,7 +1844,7 @@ API Security uses the specified media types in the OpenAPI document to generate
To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and API Fuzzing.
-Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding API fuzzing to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding API fuzzing to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](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.
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index cf864068e44..7bb3cb4f64c 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -7,7 +7,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Scanning **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in GitLab 10.4.
+> - Improved support for FIPS [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263482) in GitLab 13.6 by upgrading `CS_MAJOR_VERSION` from `2` to `3`.
+> - Integration with Trivy [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322656) in GitLab 13.9 by upgrading `CS_MAJOR_VERSION` from `3` to `4`.
+> - Integration with Clair [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/321451) in GitLab 13.9.
+> - Default container scanning with Trivy [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61850) in GitLab 14.0.
+> - Integration with Grype as an alternative scanner [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326279) in GitLab 14.0.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86092) the major analyzer version from `4` to `5` in GitLab 15.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86783) from GitLab Ultimate to GitLab Free in 15.0.
Your application's Docker image may itself be based on Docker images that contain known
vulnerabilities. By including an extra Container Scanning job in your pipeline that scans for those
@@ -19,7 +25,7 @@ aspects of inspecting the items your code uses. These items typically include ap
dependencies that are almost always imported from external sources, rather than sourced from items
you wrote yourself.
-GitLab offers both Container Scanning and [Dependency Scanning](../dependency_scanning/)
+GitLab offers both Container Scanning and [Dependency Scanning](../dependency_scanning/index.md)
to ensure coverage for all of these dependency types. To cover as much of your risk area as
possible, we encourage you to use all of our security scanners.
@@ -68,7 +74,7 @@ information directly in the merge request.
To enable container scanning in your pipeline, you need the following:
-- Container Scanning runs in the `test` stage, which is available by default. If you redefine the stages in the `.gitlab-ci.yml` file, the `test` stage is required.
+- GitLab CI/CD pipeline must include the `test` stage, which is available unless overridden with the [`stages`](../../../ci/yaml/index.md#stages) keyword.
- [GitLab Runner](https://docs.gitlab.com/runner/) with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html)
or [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor on Linux/amd64.
- Docker `18.09.03` or higher installed on the same computer as the runner. If you're using the
@@ -79,7 +85,6 @@ To enable container scanning in your pipeline, you need the following:
- If you're using a third-party container registry, you might need to provide authentication
credentials through the `DOCKER_USER` and `DOCKER_PASSWORD` [configuration variables](#available-cicd-variables).
For more details on how to use these variables, see [authenticate to a remote registry](#authenticate-to-a-remote-registry).
-- GitLab CI/CD pipeline must include the `test` stage, which is available unless overridden with the [`stages`](../../../ci/yaml/index.md#stages) keyword.
## Configuration
@@ -224,7 +229,7 @@ container_scanning:
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: "false"
```
-When you enable this feature, you may see [duplicate findings](../terminology/#duplicate-finding)
+When you enable this feature, you may see [duplicate findings](../terminology/index.md#duplicate-finding)
in the [Vulnerability Report](../vulnerability_report/)
if [Dependency Scanning](../dependency_scanning/)
is enabled for your project. This happens because GitLab can't automatically deduplicate findings
@@ -680,7 +685,7 @@ It's possible to run the [GitLab container scanning tool](https://gitlab.com/git
against a Docker container without needing to run it within the context of a CI job. To scan an
image directly, follow these steps:
-1. Run [Docker Desktop](https://www.docker.com/products/docker-desktop)
+1. Run [Docker Desktop](https://www.docker.com/products/docker-desktop/)
or [Docker Machine](https://github.com/docker/machine).
1. Run the analyzer's Docker image, passing the image and tag you want to analyze in the
@@ -700,101 +705,21 @@ The results are stored in `gl-container-scanning-report.json`.
## Reports JSON format
-The container scanning tool emits a JSON report file. For more information, see the
-[schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
-
-Here's an example container scanning report:
-
-```json-doc
-{
- "version": "14.0.0",
- "vulnerabilities": [
- {
- "id": "df52bc8ce9a2ae56bbcb0c4ecda62123fbd6f69b",
- "category": "container_scanning",
- "message": "CVE-2019-3462 in apt-1.4.8",
- "description": "Incorrect sanitation of the 302 redirect field in HTTP transport method of apt versions 1.4.8 and earlier can lead to content injection by a MITM attacker, potentially leading to remote code execution on the target machine.",
- "severity": "High",
- "confidence": "Unknown",
- "solution": "Upgrade apt from 1.4.8 to 1.4.9",
- "scanner": {
- "id": "trivy",
- "name": "trivy"
- },
- "location": {
- "dependency": {
- "package": {
- "name": "apt"
- },
- "version": "1.4.8"
- },
- "operating_system": "debian:9.4",
- "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e",
- "default_branch_image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0:latest"
- },
- "identifiers": [
- {
- "type": "cve",
- "name": "CVE-2019-3462",
- "value": "CVE-2019-3462",
- "url": "http://www.securityfocus.com/bid/106690"
- }
- ],
- "links": [
- {
- "url": "http://www.securityfocus.com/bid/106690"
- },
- {
- "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3462"
- },
- {
- "url": "https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E"
- },
- {
- "url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00013.html"
- },
- {
- "url": "https://lists.debian.org/debian-lts-announce/2019/01/msg00014.html"
- },
- {
- "url": "https://security.netapp.com/advisory/ntap-20190125-0002/"
- },
- {
- "url": "https://usn.ubuntu.com/3863-1/"
- },
- {
- "url": "https://usn.ubuntu.com/3863-2/"
- },
- {
- "url": "https://usn.ubuntu.com/usn/usn-3863-1"
- },
- {
- "url": "https://usn.ubuntu.com/usn/usn-3863-2"
- },
- {
- "url": "https://www.debian.org/security/2019/dsa-4371"
- }
- ]
- }
- ],
- "remediations": []
- "scan": {
- "scanner": {
- "id": "trivy",
- "name": "Trivy",
- "url": "https://github.com/aquasecurity/trivy/",
- "vendor": {
- "name": "GitLab"
- },
- "version": "0.16.0"
- },
- "type": "container_scanning",
- "start_time": "2021-04-14T19:45:58",
- "end_time": "2021-04-14T19:46:18",
- "status": "success"
- }
-}
-```
+The container scanning tool emits JSON reports which the [GitLab Runner](https://docs.gitlab.com/runner/)
+recognizes through the [`artifacts:reports`](../../../ci/yaml/#artifactsreports)
+keyword in the CI configuration file.
+
+Once the CI job finishes, the Runner uploads these reports to GitLab, which are then available in
+the CI Job artifacts. In GitLab Ultimate, these reports can be viewed in the corresponding [pipeline](../vulnerability_report/pipeline.md)
+and become part of the [Vulnerability Report](../vulnerability_report/).
+
+These reports must follow a format defined in the
+[security report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/). See:
+
+- [Latest schema for the container scanning report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json).
+- [Example container scanning report](https://gitlab.com/gitlab-examples/security/security-reports/-/blob/master/samples/container-scanning.json)
+
+For more information, see [Security scanner integration](../../../development/integrations/secure.md).
## Security Dashboard
@@ -878,27 +803,5 @@ For information on this, see the [general Application Security troubleshooting s
## Changes
-- GitLab 13.6 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/263482) better support for
- [FIPS](https://csrc.nist.gov/publications/detail/fips/140/2/final) by upgrading the
- `CS_MAJOR_VERSION` from `2` to `3`. Version `3` of the `container_scanning` Docker image uses
- [`centos:centos8`](https://hub.docker.com/_/centos)
- as the new base. It also removes the use of the [start.sh](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/merge_requests/77)
- script and instead executes the analyzer by default. Any customizations made to the
- `container_scanning` job's [`before_script`](../../../ci/yaml/index.md#before_script)
- and [`after_script`](../../../ci/yaml/index.md#after_script)
- blocks may not work with the new version. To roll back to the previous [`alpine:3.11.3`](https://hub.docker.com/_/alpine)-based
- Docker image, you can specify the major version through the [`CS_MAJOR_VERSION`](#available-cicd-variables)
- variable.
-- GitLab 13.9 [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/322656) integration with
- [Trivy](https://github.com/aquasecurity/trivy) by upgrading `CS_MAJOR_VERSION` from `3` to `4`.
-- GitLab 13.9 [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/321451) the integration with
- [Clair](https://github.com/quay/clair/).
-- GitLab 14.0 [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61850)
- an integration with [Trivy](https://github.com/aquasecurity/trivy)
- as the default for container scanning, and also [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326279)
- an integration with [Grype](https://github.com/anchore/grype)
- as an alternative scanner.
-- GitLab 15.0 changed the major analyzer version from `4` to `5`.
-
-Other changes to the container scanning analyzer can be found in the project's
+Changes to the container scanning analyzer can be found in the project's
[changelog](https://gitlab.com/gitlab-org/security-products/analyzers/container-scanning/-/blob/master/CHANGELOG.md).
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index ac3b266ad48..154884c16e7 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -367,12 +367,12 @@ vulnerability:
## Troubleshooting
-### Error "Unable to extract corpus folder from artifacts zip file"
+### Error `Unable to extract corpus folder from artifacts zip file`
If you see this error message, and `COVFUZZ_USE_REGISTRY` is set to `true`, ensure that the uploaded
corpus file extracts into a folder named `corpus`.
-### Error "400 Bad request - Duplicate package is not allowed"
+### Error `400 Bad request - Duplicate package is not allowed`
If you see this error message when running the fuzzing job with `COVFUZZ_USE_REGISTRY` set to `true`,
ensure that duplicates are allowed. For more details, see
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index ffcd496e2c3..e8373b0c0b7 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -5,34 +5,42 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# DAST browser-based crawler **(ULTIMATE)**
+# DAST browser-based analyzer **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/323423) in GitLab 13.12.
WARNING:
This product is in an early-access stage and is considered a [beta](../../../policy/alpha-beta-support.md#beta-features) feature.
-GitLab DAST's new browser-based crawler is a crawl engine built by GitLab to test Single Page Applications (SPAs) and traditional web applications.
-Due to the reliance of modern web applications on JavaScript, handling SPAs or applications that are dependent on JavaScript is paramount to ensuring proper coverage of an application for Dynamic Application Security Testing (DAST).
+GitLab DAST's browser-based analyzer was built by GitLab to test Single Page Applications (SPAs) and
+traditional web applications. It both crawls the web application and analyzes the resulting output
+for vulnerabilities. Analysis of modern applications, heavily reliant on JavaScript, is vital to
+ensuring DAST coverage.
-The browser-based crawler 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 crawler 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 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
+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
+interact with the target application much like a real user would, identifying complex flows that
+traditional web crawlers don't understand. This results in better coverage of the website.
-The benefit of crawling by following user actions in a browser is that the crawler can interact with the target application much like a real user would, identifying complex flows that traditional web crawlers don't understand. This results in better coverage of the website.
+The browser-based scanner should provide greater coverage for most web applications, compared
+with the current DAST AJAX crawler. While both crawlers are
+used together with the current DAST scanner, the combination of the browser-based crawler with the
+current DAST scanner is much more effective at finding and testing every page in an application.
-Using the browser-based crawler should provide greater coverage for most web applications, compared with the current DAST AJAX crawler. The new crawler replaces the AJAX crawler and is specifically designed to maximize crawl coverage in modern web applications. While both crawlers are currently used in conjunction with the existing DAST scanner, the combination of the browser-based crawler with the current DAST scanner is much more effective at finding and testing every page in an application.
+## Enable browser-based analyzer
-## Enable browser-based crawler
-
-The browser-based crawler is an extension to the GitLab DAST product. DAST should be included in the CI/CD configuration and the browser-based crawler enabled using CI/CD variables:
+To enable the browser-based analyzer:
1. Ensure the DAST [prerequisites](index.md#prerequisites) are met.
-1. Include the [DAST CI template](index.md#include-the-dast-template).
-1. Set the target website using the `DAST_WEBSITE` CI/CD variable.
+1. Include the [DAST CI/CD template](index.md#include-the-dast-template).
+1. Set the target website using the [`DAST_WEBSITE` CI/CD variable](index.md#available-cicd-variables).
1. Set the CI/CD variable `DAST_BROWSER_SCAN` to `true`.
-An example configuration might look like the following:
+Example extract of `.gitlab-ci.yml` file:
```yaml
include:
@@ -77,13 +85,20 @@ The [DAST variables](index.md#available-cicd-variables) `SECURE_ANALYZERS_PREFIX
## Vulnerability detection
-While the browser-based crawler crawls modern web applications efficiently, vulnerability detection is still managed by the standard DAST/Zed Attack Proxy (ZAP) solution.
+Vulnerability detection is gradually being migrated from the default Zed Attack Proxy (ZAP) solution
+to the browser-based analyzer. For details of the vulnerability detection already migrated, see
+[browser-based vulnerability checks](checks/index.md).
-The crawler runs the target website in a browser with DAST/ZAP configured as the proxy server. This ensures that all requests and responses made by the browser are passively scanned by DAST/ZAP.
-When running a full scan, active vulnerability checks executed by DAST/ZAP do not use a browser. This difference in how vulnerabilities are checked can cause issues that require certain features of the target website to be disabled to ensure the scan works as intended.
+The crawler runs the target website in a browser with DAST/ZAP configured as the proxy server. This
+ensures that all requests and responses made by the browser are passively scanned by DAST/ZAP. When
+running a full scan, active vulnerability checks executed by DAST/ZAP do not use a browser. This
+difference in how vulnerabilities are checked can cause issues that require certain features of the
+target website to be disabled to ensure the scan works as intended.
-For example, for a target website that contains forms with Anti-CSRF tokens, a passive scan works as intended because the browser displays pages and forms as if a user is viewing the page.
-However, active vulnerability checks that run in a full scan cannot submit forms containing Anti-CSRF tokens. In such cases, we recommend you disable Anti-CSRF tokens when running a full scan.
+For example, for a target website that contains forms with Anti-CSRF tokens, a passive scan works as
+intended because the browser displays pages and forms as if a user is viewing the page. However,
+active vulnerability checks that run in a full scan cannot submit forms containing Anti-CSRF tokens.
+In such cases, we recommend you disable Anti-CSRF tokens when running a full scan.
## Managing scan time
diff --git a/doc/user/application_security/dast/checks/16.7.md b/doc/user/application_security/dast/checks/16.7.md
index a02fb3a451f..2e6607575db 100644
--- a/doc/user/application_security/dast/checks/16.7.md
+++ b/doc/user/application_security/dast/checks/16.7.md
@@ -25,8 +25,8 @@ Only three directives are applicable for the `Strict-Transport-Security` header.
Note that invalid directives, or the `Strict-Transport-Security` header appearing more than once (if the values are
different) is considered invalid.
-Prior to adding to this security configuration to your website, it is recommended you review the hstspreload.org [Deployment
-Recommendations](https://hstspreload.org/#deployment-recommendations).
+Prior to adding to this security configuration to your website, it is recommended you review the hstspreload.org
+[Deployment Recommendations](https://hstspreload.org/#deployment-recommendations).
## Details
diff --git a/doc/user/application_security/dast/checks/601.1.md b/doc/user/application_security/dast/checks/601.1.md
index 60249c2562d..c51b00cdd36 100644
--- a/doc/user/application_security/dast/checks/601.1.md
+++ b/doc/user/application_security/dast/checks/601.1.md
@@ -30,5 +30,5 @@ then be used to redirect the user, using the 301 response code and `Location` he
## Links
-- [OWASP](https://owasp.org/www-project-cheat-sheets/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)
+- [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html)
- [CWE](https://cwe.mitre.org/data/definitions/601.html)
diff --git a/doc/user/application_security/dast/checks/798.45.md b/doc/user/application_security/dast/checks/798.45.md
deleted file mode 100644
index a800063f15d..00000000000
--- a/doc/user/application_security/dast/checks/798.45.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token Finicity Public Key
-
-## Description
-
-The response body contains content that matches the pattern of a Finicity Public Key.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.45 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.51.md b/doc/user/application_security/dast/checks/798.51.md
deleted file mode 100644
index f131d31ae65..00000000000
--- a/doc/user/application_security/dast/checks/798.51.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token GCP API key
-
-## Description
-
-The response body contains content that matches the pattern of a GCP API key.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.51 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.71.md b/doc/user/application_security/dast/checks/798.71.md
deleted file mode 100644
index f0bcc43940d..00000000000
--- a/doc/user/application_security/dast/checks/798.71.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token Lob Publishable API Key
-
-## Description
-
-The response body contains content that matches the pattern of a Lob Publishable API Key.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.71 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.73.md b/doc/user/application_security/dast/checks/798.73.md
deleted file mode 100644
index eae41a49782..00000000000
--- a/doc/user/application_security/dast/checks/798.73.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token Mailgun public validation key
-
-## Description
-
-The response body contains content that matches the pattern of a Mailgun public validation key.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.73 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.76.md b/doc/user/application_security/dast/checks/798.76.md
deleted file mode 100644
index 87e6364184f..00000000000
--- a/doc/user/application_security/dast/checks/798.76.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token MapBox API token
-
-## Description
-
-The response body contains content that matches the pattern of a MapBox API token.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.76 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.79.md b/doc/user/application_security/dast/checks/798.79.md
deleted file mode 100644
index 9a580658a72..00000000000
--- a/doc/user/application_security/dast/checks/798.79.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token MessageBird client ID
-
-## Description
-
-The response body contains content that matches the pattern of a MessageBird client ID.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.79 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/798.85.md b/doc/user/application_security/dast/checks/798.85.md
deleted file mode 100644
index 0726bdc7fd8..00000000000
--- a/doc/user/application_security/dast/checks/798.85.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-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
----
-
-# Exposure of confidential secret or token Nytimes Access Token
-
-## Description
-
-The response body contains content that matches the pattern of a Nytimes Access Token.
-Exposing this value could allow attackers to gain access to all resources granted by this token.
-
-## Remediation
-
-Review the response body content and remove any exposed values.
-
-## Details
-
-| ID | Aggregated | CWE | Type | Risk |
-|:---|:--------|:--------|:--------|:--------|
-| 798.85 | false | 798 | Passive | High |
-
-## Links
-
-- [CWE](https://cwe.mitre.org/data/definitions/798.html)
diff --git a/doc/user/application_security/dast/checks/index.md b/doc/user/application_security/dast/checks/index.md
index cdfebc07ef2..387682318e6 100644
--- a/doc/user/application_security/dast/checks/index.md
+++ b/doc/user/application_security/dast/checks/index.md
@@ -81,13 +81,11 @@ The [DAST browser-based crawler](../browser_based.md) provides a number of vulne
| [798.42](798.42.md) | Exposure of confidential secret or token Finicity API token | High | Passive |
| [798.43](798.43.md) | Exposure of confidential secret or token Flickr Access Token | High | Passive |
| [798.44](798.44.md) | Exposure of confidential secret or token Finnhub Access Token | High | Passive |
-| [798.45](798.45.md) | Exposure of confidential secret or token Finicity Public Key | High | Passive |
| [798.46](798.46.md) | Exposure of confidential secret or token Flutterwave Secret Key | High | Passive |
| [798.47](798.47.md) | Exposure of confidential secret or token Flutterwave Encryption Key | High | Passive |
| [798.48](798.48.md) | Exposure of confidential secret or token Frame.io API token | High | Passive |
| [798.49](798.49.md) | Exposure of confidential secret or token Freshbooks Access Token | High | Passive |
| [798.50](798.50.md) | Exposure of confidential secret or token GoCardless API token | High | Passive |
-| [798.51](798.51.md) | Exposure of confidential secret or token GCP API key | High | Passive |
| [798.52](798.52.md) | Exposure of confidential secret or token GitHub Personal Access Token | High | Passive |
| [798.53](798.53.md) | Exposure of confidential secret or token GitHub OAuth Access Token | High | Passive |
| [798.54](798.54.md) | Exposure of confidential secret or token GitHub App Token | High | Passive |
@@ -107,21 +105,16 @@ The [DAST browser-based crawler](../browser_based.md) provides a number of vulne
| [798.68](798.68.md) | Exposure of confidential secret or token LinkedIn Client ID | High | Passive |
| [798.69](798.69.md) | Exposure of confidential secret or token LinkedIn Client secret | High | Passive |
| [798.70](798.70.md) | Exposure of confidential secret or token Lob API Key | High | Passive |
-| [798.71](798.71.md) | Exposure of confidential secret or token Lob Publishable API Key | High | Passive |
| [798.72](798.72.md) | Exposure of confidential secret or token Mailchimp API key | High | Passive |
-| [798.73](798.73.md) | Exposure of confidential secret or token Mailgun public validation key | High | Passive |
| [798.74](798.74.md) | Exposure of confidential secret or token Mailgun private API token | High | Passive |
| [798.75](798.75.md) | Exposure of confidential secret or token Mailgun webhook signing key | High | Passive |
-| [798.76](798.76.md) | Exposure of confidential secret or token MapBox API token | High | Passive |
| [798.77](798.77.md) | Exposure of confidential secret or token Mattermost Access Token | High | Passive |
| [798.78](798.78.md) | Exposure of confidential secret or token MessageBird API token | High | Passive |
-| [798.79](798.79.md) | Exposure of confidential secret or token MessageBird client ID | High | Passive |
| [798.80](798.80.md) | Exposure of confidential secret or token Netlify Access Token | High | Passive |
| [798.81](798.81.md) | Exposure of confidential secret or token New Relic user API Key | High | Passive |
| [798.82](798.82.md) | Exposure of confidential secret or token New Relic user API ID | High | Passive |
| [798.83](798.83.md) | Exposure of confidential secret or token New Relic ingest browser API token | High | Passive |
| [798.84](798.84.md) | Exposure of confidential secret or token npm access token | High | Passive |
-| [798.85](798.85.md) | Exposure of confidential secret or token Nytimes Access Token | High | Passive |
| [798.86](798.86.md) | Exposure of confidential secret or token Okta Access Token | High | Passive |
| [798.87](798.87.md) | Exposure of confidential secret or token Plaid Client ID | High | Passive |
| [798.88](798.88.md) | Exposure of confidential secret or token Plaid Secret key | High | Passive |
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index f8aa2e3d1c6..a49dd8fd646 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -351,7 +351,7 @@ include:
- template: DAST-API.gitlab-ci.yml
variables:
- DAST_API_OPENAPI: http://my.api/api-specification.yml
+ DAST_API_SPECIFICATION: http://my.api/api-specification.yml
```
#### Import API specification from a file
@@ -366,7 +366,7 @@ dast:
- cp api-specification.yml /zap/wrk/api-specification.yml
variables:
GIT_STRATEGY: fetch
- DAST_API_OPENAPI: api-specification.yml
+ DAST_API_SPECIFICATION: api-specification.yml
```
#### Full API scan
@@ -402,7 +402,7 @@ include:
- template: DAST-API.gitlab-ci.yml
variables:
- DAST_API_OPENAPI: http://api-test.host.com/api-specification.yml
+ DAST_API_SPECIFICATION: http://api-test.host.com/api-specification.yml
DAST_API_HOST_OVERRIDE: api-test.host.com
```
@@ -417,7 +417,7 @@ include:
- template: DAST-API.gitlab-ci.yml
variables:
- DAST_API_OPENAPI: http://api-test.api.com/api-specification.yml
+ DAST_API_SPECIFICATION: http://api-test.api.com/api-specification.yml
DAST_REQUEST_HEADERS: "Authorization: Bearer my.token"
```
@@ -633,8 +633,7 @@ including a large number of false positives.
| `DAST_ADVERTISE_SCAN` | boolean | Set to `true` to add a `Via` header to every request sent, advertising that the request was sent as part of a GitLab DAST scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334947) in GitLab 14.1. |
| `DAST_AGGREGATE_VULNERABILITIES` | boolean | Vulnerability aggregation is set to `true` by default. To disable this feature and see each vulnerability individually set to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254043) in GitLab 14.0. |
| `DAST_API_HOST_OVERRIDE` <sup>1</sup> | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080`. |
-| `DAST_API_OPENAPI` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
-| `DAST_API_SPECIFICATION` <sup>1</sup> | URL or string | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/290241)** in GitLab 15.0. Replaced by `DAST_API_OPENAPI`. The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
+| `DAST_API_SPECIFICATION` <sup>1</sup> | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. The variable `DAST_WEBSITE` must be specified if this is omitted. |
| `DAST_AUTH_REPORT` <sup>2</sup> | boolean | Used in combination with exporting the `gl-dast-debug-auth-report.html` artifact to aid in debugging authentication issues. |
| `DAST_AUTH_EXCLUDE_URLS` <sup>2</sup> | URLs | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289959)** in GitLab 14.0. Replaced by `DAST_EXCLUDE_URLS`. The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. |
| `DAST_AUTH_URL` <sup>1,2</sup> | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. Example: `https://login.example.com`. |
@@ -671,7 +670,7 @@ including a large number of false positives.
| `DAST_USERNAME` <sup>1,2</sup> | string | The username to authenticate to in the website. Example: `admin` |
| `DAST_USERNAME_FIELD` <sup>1,2</sup> | string | The selector of username field at the sign-in HTML form. Example: `name:username` |
| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
-| `DAST_WEBSITE` <sup>1</sup> | URL | The URL of the website to scan. The variable `DAST_API_OPENAPI` must be specified if this is omitted. |
+| `DAST_WEBSITE` <sup>1</sup> | URL | The URL of the website to scan. The variable `DAST_API_SPECIFICATION` must be specified if this is omitted. |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. Example: `logger.httpsender.name=org.parosproxy.paros.network.HttpSender;logger.httpsender.level=debug;logger.sitemap.name=org.parosproxy.paros.model.SiteMap;logger.sitemap.level=debug;` |
| `SECURE_ANALYZERS_PREFIX` | URL | Set the Docker registry base address from which to download the analyzer. |
@@ -995,8 +994,7 @@ An on-demand scan can be run in active or passive mode:
- _Passive mode_ is the default and runs a ZAP Baseline Scan.
- _Active mode_ runs a ZAP Full Scan which is potentially harmful to the site being scanned. To
- minimize the risk of accidental damage, running an active scan requires a [validated site
- profile](#site-profile-validation).
+ minimize the risk of accidental damage, running an active scan requires a [validated site profile](#site-profile-validation).
### View on-demand DAST scans
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index fdca02267e4..1f86f2ffa49 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -1524,7 +1524,7 @@ For more information, see [Offline environments](../offline_deployments/index.md
## Troubleshooting
-### Error waiting for API Security 'http://127.0.0.1:5000' to become available
+### `Error waiting for API Security 'http://127.0.0.1:5000' to become available`
A bug exists in versions of the DAST API analyzer prior to v1.6.196 that can cause a background process to fail under certain conditions. The solution is to update to a newer version of the DAST API analyzer.
@@ -1537,7 +1537,7 @@ If the issue is occurring with versions v1.6.196 or greater, please contact Supp
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 `dast_api` job definition from your `.gitlab-ci.yml` file.
-### Failed to start scanner session (version header not found)
+### `Failed to start scanner session (version header not found)`
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 of this issue is changing the `DAST_API_API` variable from its default.
@@ -1551,7 +1551,7 @@ 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.
-### Application cannot determine the base URL for the target API
+### `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.
@@ -1612,7 +1612,7 @@ To detect and correct elements that don't comply with the OpenAPI specifications
| Editor | OpenAPI 2.0 | OpenAPI 3.0.x | OpenAPI 3.1.x |
| -- | -- | -- | -- |
| [Swagger Editor](https://editor.swagger.io/) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{dotted-circle}** YAML, JSON |
-| [Stoplight Studio](https://stoplight.io/studio/) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON |
+| [Stoplight Studio](https://stoplight.io/studio) | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON | **{check-circle}** YAML, JSON |
If your OpenAPI document is generated manually, load your document in the editor and fix anything that is non-compliant. If your document is generated automatically, load it in your editor to identify the issues in the schema, then go to the application and perform the corrections based on the framework you are using.
@@ -1636,7 +1636,7 @@ API Security can still try to consume an OpenAPI document that does not fully co
DAST_API_OPENAPI_RELAXED_VALIDATION: On
```
-### No operation in the OpenAPI document is consuming any supported media type
+### `No operation in the OpenAPI document is consuming any supported media type`
API Security uses the specified media types in the OpenAPI document to generate requests. If no request can be created due to the lack of supported media types, then an error will be thrown.
@@ -1654,7 +1654,7 @@ API Security uses the specified media types in the OpenAPI document to generate
To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and DAST API.
-Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding DAST API to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+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.
[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.
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index d0a91ab664e..521bb6adbf0 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -109,6 +109,8 @@ maximum of two directory levels from the repository's root. For example, the
`gemnasium-dependency_scanning` job is enabled if a repository contains either `Gemfile`,
`api/Gemfile`, or `api/client/Gemfile`, but not if the only supported dependency file is `api/v1/client/Gemfile`.
+For Java and Python, when a supported depedency file is detected, Dependency Scanning attempts to build the project and execute some Java or Python commands to get the list of dependencies. For all other projects, the lock file is parsed to obtain the list of dependencies without needing to build the project first.
+
When a supported dependency file is detected, all dependencies, including transitive dependencies are analyzed. There is no limit to the depth of nested or transitive dependencies that are analyzed.
The following languages and dependency managers are supported:
@@ -148,14 +150,13 @@ table.supported-languages ul {
<th>Language Versions</th>
<th>Package Manager</th>
<th>Supported files</th>
- <th>Analyzer</th>
<th><a href="#how-multiple-files-are-processed">Processes multiple files?</a></th>
</tr>
</thead>
<tbody>
<tr>
<td>Ruby</td>
- <td>Not applicable</td>
+ <td>All versions</td>
<td><a href="https://bundler.io/">Bundler</a></td>
<td>
<ul>
@@ -163,23 +164,20 @@ table.supported-languages ul {
<li><code>gems.locked</code></li>
</ul>
</td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td>PHP</td>
- <td>Not applicable</td>
+ <td>All versions</td>
<td><a href="https://getcomposer.org/">Composer</a></td>
<td><code>composer.lock</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td>C</td>
- <td rowspan="2">Not applicable</td>
+ <td rowspan="2">All versions</td>
<td rowspan="2"><a href="https://conan.io/">Conan</a></td>
<td rowspan="2"><a href="https://docs.conan.io/en/latest/versioning/lockfiles.html"><code>conan.lock</code></a></td>
- <td rowspan="2"><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td rowspan="2">Y</td>
</tr>
<tr>
@@ -187,10 +185,9 @@ table.supported-languages ul {
</tr>
<tr>
<td>Go</td>
- <td>Not applicable</td>
+ <td>All versions</td>
<td><a href="https://go.dev/">Go</a></td>
<td><code>go.sum</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
@@ -211,41 +208,36 @@ table.supported-languages ul {
<li><code>build.gradle.kts</code></li>
</ul>
</td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td><a href="https://maven.apache.org/">Maven</a></td>
<td><code>pom.xml</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td rowspan="2">JavaScript</td>
- <td>Not applicable</td>
+ <td>All versions</td>
<td><a href="https://www.npmjs.com/">npm</a></td>
<td>
<ul>
- <li><code>package-lock.json</code></li>
+ <li><code>package-lock.json</code><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-3">3</a></b></sup></li>
<li><code>npm-shrinkwrap.json</code></li>
</ul>
</td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
- <td>Not applicable</td>
+ <td>All versions</td>
<td><a href="https://classic.yarnpkg.com/en/">yarn</a></td>
<td><code>yarn.lock</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
</tr>
<tr>
<td>.NET</td>
- <td rowspan="2">Not applicable</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://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td rowspan="2">Y</td>
</tr>
<tr>
@@ -256,7 +248,6 @@ table.supported-languages ul {
<td rowspan="4">3.9</td>
<td><a href="https://setuptools.readthedocs.io/en/latest/">setuptools</a></td>
<td><code>setup.py</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
@@ -268,7 +259,6 @@ table.supported-languages ul {
<li><code>requires.txt</code></li>
</ul>
</td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
@@ -276,24 +266,21 @@ table.supported-languages ul {
<td>
<ul>
<li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile</code></a></li>
- <li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile.lock</code></a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-3">3</a></b></sup></li>
+ <li><a href="https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock"><code>Pipfile.lock</code></a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-4">4</a></b></sup></li>
</ul>
</td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td><a href="https://python-poetry.org/">Poetry</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-5">5</a></b></sup></td>
<td><code>poetry.lock</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td>Scala</td>
- <td>Not applicable</td>
- <td><a href="https://www.scala-sbt.org/">sbt</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-4">4</a></b></sup></td>
+ <td>All versions</td>
+ <td><a href="https://www.scala-sbt.org/">sbt</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-6">6</a></b></sup></td>
<td><code>build.sbt</code></td>
- <td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
</tbody>
@@ -311,12 +298,18 @@ table.supported-languages ul {
<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
- Scanning (gemnasium-maven)</a> for more details. Also, Gradle is not supported when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is enabled.
+ 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>
<li>
<a id="notes-regarding-supported-languages-and-package-managers-3"></a>
<p>
+ npm is only supported when `lockfileVersion = 1` or `lockfileVersion = 2`. Work to add support for `lockfileVersion = 3` is being tracked in issue <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/365176">GitLab#365176</a>.
+ </p>
+ </li>
+ <li>
+ <a id="notes-regarding-supported-languages-and-package-managers-4"></a>
+ <p>
The presence of a <code>Pipfile.lock</code> file alone will <i>not</i> trigger the analyzer; the presence of a <code>Pipfile</code> is
still required in order for the analyzer to be executed. However, if a <code>Pipfile.lock</code> file is found, it will be used by
<code>Gemnasium</code> to scan the exact package versions listed in this file.
@@ -328,12 +321,6 @@ table.supported-languages ul {
</p>
</li>
<li>
- <a id="notes-regarding-supported-languages-and-package-managers-4"></a>
- <p>
- Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.
- </p>
- </li>
- <li>
<a id="notes-regarding-supported-languages-and-package-managers-5"></a>
<p>
Support for <a href="https://python-poetry.org/">Poetry</a> projects with a <code>poetry.lock</code> file was <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/7006">added in GitLab 15.0</a>.
@@ -341,6 +328,12 @@ table.supported-languages ul {
<a href="https://gitlab.com/gitlab-org/gitlab/-/issues/32774">Poetry's pyproject.toml support for dependency scanning.</a>
</p>
</li>
+ <li>
+ <a id="notes-regarding-supported-languages-and-package-managers-6"></a>
+ <p>
+ Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.
+ </p>
+ </li>
</ol>
<!-- markdownlint-enable MD044 -->
@@ -601,7 +594,7 @@ The following variables allow configuration of global dependency scanning settin
| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. |
| `DS_EXCLUDED_ANALYZERS` | Specify the analyzers (by name) to exclude from Dependency Scanning. For more information, see [Dependency Scanning Analyzers](analyzers.md). |
| `DS_DEFAULT_ANALYZERS` | This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/287691) in GitLab 14.0 and [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/333299) in 15.0. Use `DS_EXCLUDED_ANALYZERS` instead. |
-| `DS_EXCLUDED_PATHS` | Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
+| `DS_EXCLUDED_PATHS` | Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
| `DS_IMAGE_SUFFIX` | Suffix added to the image name. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/354796) in GitLab 14.10.) Automatically set to `"-fips"` when FIPS mode is enabled. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357922) in GitLab 15.0.) |
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info`. |
@@ -924,8 +917,7 @@ Please check the [Release Process documentation](https://gitlab.com/gitlab-org/s
## Contributing to the vulnerability database
-You can search the [`gemnasium-db`](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project
-to find a vulnerability in the GitLab Advisory Database.
+To find a vulnerability, you can search the [`GitLab Advisory Database`](https://advisories.gitlab.com/).
You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md).
## Running dependency scanning in an offline environment
diff --git a/doc/user/application_security/get-started-security.md b/doc/user/application_security/get-started-security.md
new file mode 100644
index 00000000000..4c2b971b5fa
--- /dev/null
+++ b/doc/user/application_security/get-started-security.md
@@ -0,0 +1,34 @@
+---
+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
+---
+
+# Get started with GitLab application security **(ULTIMATE)**
+
+Complete the following steps to get the most from GitLab application security tools.
+
+1. Enable [Secret Detection](secret_detection/index.md) scanning for your default branch.
+1. Enable [Dependency Scanning](dependency_scanning/index.md) for your default branch so you can start identifying existing
+ vulnerable packages in your codebase.
+1. Add security scans to feature branch pipelines. The same scans should be enabled as are running
+ on your default branch. Subsequent scans will show only new vulnerabilities by comparing the feature branch to the default branch results.
+1. Let your team get comfortable with [vulnerability reports](vulnerability_report/index.md) and
+ establish a vulnerability triage workflow.
+1. Consider creating [labels](../project/labels.md) and [issue boards](../project/issue_board.md) to
+ help manage issues created from vulnerabilities. Issue boards allow all stakeholders to have a
+ common view of all issues.
+1. Create a [scan result policy](policies/index.md) to limit new vulnerabilities from being merged
+ into your default branch.
+1. Monitor the [Security Dashboard](security_dashboard/index.md) trends to gauge success in
+ 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).
+ Be sure to add the same scan types to both feature pipelines and default branch pipelines.
+1. Use [Compliance Pipelines](../../user/project/settings/index.md#compliance-pipeline-configuration)
+ 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
+ and [Web API fuzzing](api_fuzzing/index.md) on ephemeral test environments.
+1. Enable [operational container scanning](../../user/clusters/agent/vulnerabilities.md) to scan
+ container images in your production cluster for security vulnerabilities.
diff --git a/doc/user/application_security/iac_scanning/index.md b/doc/user/application_security/iac_scanning/index.md
index 35968a6361f..16f08de738b 100644
--- a/doc/user/application_security/iac_scanning/index.md
+++ b/doc/user/application_security/iac_scanning/index.md
@@ -64,7 +64,7 @@ variables:
SAST_IMAGE_SUFFIX: '-fips'
include:
- - template: Security/SAST-IaC.latest.gitlab-ci.yml
+ - template: Jobs/SAST-IaC.gitlab-ci.yml
```
### Making IaC analyzers available to all GitLab tiers
@@ -98,11 +98,11 @@ To configure IaC Scanning for a project you can:
### Configure IaC Scanning manually
To enable IaC Scanning you must [include](../../../ci/yaml/index.md#includetemplate) the
-[`SAST-IaC.latest.gitlab-ci.yml template`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/SAST-IaC.latest.gitlab-ci.yml) provided as part of your GitLab installation. Here is an example of how to include it:
+[`SAST-IaC.gitlab-ci.yml template`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml) provided as part of your GitLab installation. Here is an example of how to include it:
```yaml
include:
- - template: Security/SAST-IaC.latest.gitlab-ci.yml
+ - template: Jobs/SAST-IaC.gitlab-ci.yml
```
The included template creates IaC scanning jobs in your CI/CD pipeline and scans
@@ -130,3 +130,24 @@ The IaC tool emits a JSON report file in the existing SAST report format. For mo
The JSON report file can be downloaded from the CI pipelines page, or the
pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/yaml/index.md#artifactspaths) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md).
+
+## Troubleshooting
+
+### IaC debug logging
+
+To help troubleshoot IaC jobs, you can increase the [Secure scanner log verbosity](../sast/index.md#logging-level)
+by using a global CI/CD variable set to `debug`:
+
+```yaml
+variables:
+ SECURE_LOG_LEVEL: "debug"
+```
+
+### IaC Scanning findings show as `No longer detected` unexpectedly
+
+If a previously detected finding unexpectedly shows as `No longer detected`, it might
+be due to an update to the scanner. An update can disable rules that are found to
+be ineffective or false positives, and the findings are marked as `No longer detected`:
+
+- In GitLab 15.3, [secret detection in the KICS SAST IaC scanner was disabled](https://gitlab.com/gitlab-org/gitlab/-/issues/346181),
+ so IaC findings in the "Passwords and Secrets" family show as `No longer detected`.
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index e3a419ea771..7c7d5380a24 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -149,19 +149,8 @@ base address for Docker images. You can override this for most scanners by setti
The [Container Scanning](container_scanning/index.md) analyzer is an exception, and it
does not use the `SECURE_ANALYZERS_PREFIX` variable. To override its Docker image, see
-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 may need to override the default `rules:` configuration to add:
-
-```yaml
-rules:
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-```
+the instructions for
+[Running container scanning in an offline environment](container_scanning/index.md#running-container-scanning-in-an-offline-environment).
## Default behavior of GitLab security scanning tools
@@ -401,8 +390,10 @@ Validation depends on the schema version declared in the security report artifac
- If your security report specifies a supported schema version, GitLab uses this version to validate.
- If your security report uses a deprecated version, GitLab attempts validation against that version and adds a deprecation warning to the validation result.
-- If your security report uses a version that is not supported, GitLab attempts to validate it against the latest schema version available in GitLab.
-- If your security report does not specify a schema version, GitLab attempts to validate it against the lastest schema version available in GitLab. Since the `version` property is required, validation always fails in this case, but other validation errors may also be present.
+- If your security report uses a supported MAJOR-MINOR version of the report schema but the PATCH version doesn't match any vendored versions, GitLab attempts to validate it against latest vendored PATCH version of the schema.
+ - Example: security report uses version 14.1.1 but the latest vendored version is 14.1.0. GitLab would validate against schema version 14.1.0.
+- If your security report uses a version that is not supported, GitLab attempts to validate it against the latest schema version available in your installation but doesn't ingest the report.
+- If your security report does not specify a schema version, GitLab attempts to validate it against the latest schema version available in GitLab. Because the `version` property is required, validation always fails in this case, but other validation errors may also be present.
You can always find supported and deprecated schema versions in the [source code](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/parsers/security/validators/schema_validator.rb).
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 81a9cef885d..53f9c400259 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -137,3 +137,13 @@ See [Scan result policies](scan-result-policies.md).
See the [Category Direction page](https://about.gitlab.com/direction/protect/security_orchestration/)
for more information on the product direction of security policies within GitLab.
+
+## Troubleshooting
+
+### `Branch name does not follow the pattern 'update-policy-<timestamp>'`
+
+When you create a new security policy or change an existing policy, a new branch is automatically created with the branch name following the pattern `update-policy-<timestamp>`. For example: `update-policy-1659094451`.
+
+If you have group or instance push rules that do not allow branch name patterns that contain the text `update-policy-<timestamp>`, you will get an error that states `Branch name does not follow the pattern 'update-policy-<timestamp>'`.
+
+The workaround is to amend your group or instance push rules to allow branches following the pattern `update-policy-` followed by an integer timestamp.
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 0f9e3343072..cbd64e278c8 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -47,7 +47,7 @@ For an analyzer to be considered Generally Available, it is expected to minimall
support the following features:
- [Customizable configuration](index.md#available-cicd-variables)
-- [Customizable rulesets](index.md#customize-rulesets)
+- [Customizable rulesets](customize_rulesets.md#customize-rulesets)
- [Scan projects](index.md#supported-languages-and-frameworks)
- [Multi-project support](index.md#multi-project-support)
- [Offline support](index.md#running-sast-in-an-offline-environment)
diff --git a/doc/user/application_security/sast/customize_rulesets.md b/doc/user/application_security/sast/customize_rulesets.md
new file mode 100644
index 00000000000..919a3565d88
--- /dev/null
+++ b/doc/user/application_security/sast/customize_rulesets.md
@@ -0,0 +1,381 @@
+---
+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
+---
+
+# Customize rulesets **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
+> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8.
+
+You can customize the default scanning rules provided by our SAST analyzers.
+Ruleset customization supports the following that can be used
+simultaneously:
+
+- [Disabling predefined rules](#disable-predefined-analyzer-rules). Available for all analyzers.
+- [Overriding predefined rules](#override-predefined-analyzer-rules). Available for all analyzers.
+- Modifying the default behavior of a given analyzer by [synthesizing and passing a custom configuration](#synthesize-a-custom-configuration). Available for only `nodejs-scan`, `gosec`, and `semgrep`.
+
+To customize the default scanning rules, create a file containing custom rules. These rules
+are passed through to the analyzer's underlying scanner tools.
+
+To create a custom ruleset:
+
+1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist.
+1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory.
+
+## Disable predefined analyzer rules
+
+To disable analyzer rules:
+
+1. Set the `disabled` flag to `true` in the context of a `ruleset` section
+
+1. In one or more `ruleset.identifier` sub sections, list the rules that you want disabled. Every `ruleset.identifier` section has:
+
+- a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
+- a `value` field, to name the rule to be disabled.
+
+### Example: Disable predefined rules of SAST analyzers
+
+In the following example, the disabled rules are assigned to `eslint`
+and `sobelow` by matching the `type` and `value` of identifiers:
+
+```toml
+[eslint]
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "eslint_rule_id"
+ value = "security/detect-object-injection"
+
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "cwe"
+ value = "185"
+
+[sobelow]
+ [[sobelow.ruleset]]
+ disable = true
+ [sobelow.ruleset.identifier]
+ type = "sobelow_rule_id"
+ value = "sql_injection"
+```
+
+Those vulnerabilities containing the provided type and value are now disabled, meaning
+they won't be displayed in Merge Request nor the Vulnerability Report.
+
+## Override predefined analyzer rules
+
+To override analyzer rules:
+
+1. In one or more `ruleset.identifier` subsections, list the rules that you want to override. Every `ruleset.identifier` section has:
+
+ - a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
+ - a `value` field, to name the rule to be overridden.
+
+1. In the `ruleset.override` context of a `ruleset` section,
+ provide the keys to override. Any combination of keys can be
+ overridden. Valid keys are:
+
+ - description
+ - message
+ - name
+ - severity (valid options are: Critical, High, Medium, Low, Unknown, Info)
+
+### Example: Override predefined rules of SAST analyzers
+
+Before adding a ruleset, we verify which vulnerability will be overwritten by viewing the [`gl-sast-report.json`](index.md#reports-json-format):
+
+```json
+"identifiers": [
+ {
+ "type": "gosec_rule_id",
+ "name": "Gosec Rule ID G307",
+ "value": "G307"
+ },
+ {
+ "type": "CWE",
+ "name": "CWE-703",
+ "value": "703",
+ "url": "https://cwe.mitre.org/data/definitions/703.html"
+ }
+ ]
+```
+
+In the following example, rules from `gosec` are matched by the `type`
+and `value` of identifiers and then overridden:
+
+```toml
+[gosec]
+ [[gosec.ruleset]]
+ [gosec.ruleset.identifier]
+ type = "CWE"
+ value = "703"
+ [gosec.ruleset.override]
+ severity = "Critical"
+```
+
+If a vulnerability is found with a type `CWE` with a value of `703` then
+the vulnerability severity is overwritten to `Critical`.
+
+## Synthesize a custom configuration
+
+To create a custom configuration, you can use passthrough chains.
+
+A passthrough is a single step in a passthrough chain. The passthrough is evaluated
+in a sequence to incrementally build a configuration. The configuration is then
+passed to the target analyzer.
+
+A configuration section for an analyzer has the following
+parameters:
+
+| Parameter | Explanation |
+| ------------- | ------ |
+| `description` | Description about the analyzer configuration section. |
+| `targetdir` | The `targetdir` parameter defines the directory where the final configuration is located. If `targetdir` is empty, the analyzer uses a random directory. The maximum size of `targetdir` is 100MB. |
+| `validate` | If set to `true`, the target files for passthroughs (`raw`, `file` and `url`) are validated. The validation works for `yaml`, `xml`, `json` and `toml` files. The proper validator is identified based on the extension of the target file. By default, `validate` is set to `false`. |
+| `interpolate` | If set to `true`, environment variable interpolation is enabled so that the configuration uses secrets/tokens. We advise using this feature with caution to not leak any secrets. By default, `interpolate` is set to `false`. |
+| `timeout` | The total `timeout` for the evaluation of a passthrough chain is set to 60 seconds. If `timeout` is not set, the default timeout is 60 seconds. The timeout cannot exceed 300 seconds. |
+
+A configuration section can include one or more passthrough sections. The maximum number of passthrough sections is 20.
+There are several types of passthroughs:
+
+| Type | Description |
+| ------ | ------ |
+| `file` | Use a file that is already available in the Git repository. |
+| `raw` | Provide the configuration inline. |
+| `git` | Pull the configuration from a remote Git repository. |
+| `url` | Fetch the analyzer configuration through HTTP. |
+
+If multiple passthrough sections are defined in a passthrough chain, their
+position in the chain defines the order in which they are evaluated.
+
+- Passthroughs listed later in the chain sequence have a higher precedence.
+- Passthroughs with a higher precedence overwrite (default) and append data
+ yielded by previous passthroughs. This is useful for cases where you need to
+ use or modify an existing configuration.
+
+Configure a passthrough these parameters:
+
+| Parameter | Explanation |
+| ------------ | ----------- |
+| `type` | One of `file`, `raw`, `git` or `url`. |
+| `target` | The target file that contains the data written by the passthrough evaluation. If no value is provided, a random target file is generated. |
+| `mode` | `overwrite`: if `target` exists, overwrites the file; `append`: append to file instead. The default is `overwrite`. |
+| `ref` | This option only applies to the `git` passthrough type and contains the name of the branch or the SHA to be used. |
+| `subdir` | This option only applies to the `git` passthrough type and can be used to only consider a certain subdirectory of the source Git repository. |
+| `value` | For the `file` `url` and `git` types, `value` defines the source location of the file/Git repository; for the `raw` type, `value` carries the raw content to be passed through. |
+| `validator` | Can be used to explicitly invoke validators (`xml`, `yaml`, `json`, `toml`) on the target files after the application of a passthrough. Per default, no validator is set. |
+
+The amount of data generated by a single passthrough is limited to 1MB.
+
+## Passthrough configuration examples
+
+### Raw passthrough for nodejs-scan
+
+Define a custom analyzer configuration. In this example, customized rules are
+defined for the `nodejs-scan` scanner:
+
+```toml
+[nodejs-scan]
+ description = 'custom ruleset for nodejs-scan'
+
+ [[nodejs-scan.passthrough]]
+ type = "raw"
+ value = '''
+- nodejs-extensions:
+ - .js
+
+ template-extensions:
+ - .new
+ - .hbs
+ - ''
+
+ ignore-filenames:
+- skip.js
+
+ ignore-paths:
+ - __MACOSX
+ - skip_dir
+ - node_modules
+
+ ignore-extensions:
+ - .hbs
+
+ ignore-rules:
+ - regex_injection_dos
+ - pug_jade_template
+ - express_xss
+
+'''
+```
+
+### File passthrough for Gosec
+
+Provide the name of the file containing a custom analyzer configuration. In
+this example, customized rules for the `gosec` scanner are contained in the
+file `gosec-config.json`:
+
+```toml
+[gosec]
+ description = 'custom ruleset for gosec'
+
+ [[gosec.passthrough]]
+ type = "file"
+ value = "gosec-config.json"
+```
+
+### Passthrough chain for Semgrep
+
+In the below example, we generate a custom configuration under the `/sgrules`
+target directory with a total `timeout` of 60 seconds.
+
+Several passthrouh types generate a configuration for the target analyzer:
+
+- Two `git` passthrough sections pull the head of branch
+ `refs/remotes/origin/test` from the `myrules` Git repository, and revision
+ `97f7686` from the `sast-rules` Git 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
+ the configuration.
+ - If there is a filename collision between files in both repositories, files
+ from the `sast` repository overwrite files from the `myrules` repository,
+ as `sast-rules` has higher precedence.
+- The `raw` entry creates a file named `insecure.yml` under `/sgrules`. The
+ full path is `/sgrules/insecure.yml`.
+- The `url` entry fetches a configuration made available through a URL and
+ stores it in the `/sgrules/gosec.yml` file.
+
+Afterwards, Semgrep is invoked with the final configuration located under
+`/sgrules`.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ timeout = 60
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "https://gitlab.com/user/myrules.git"
+ ref = "refs/remotes/origin/test"
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
+ ref = "97f7686db058e2141c0806a477c1e04835c4f395"
+ subdir = "go"
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ target = "insecure.yml"
+ value = """
+rules:
+- id: "insecure"
+ patterns:
+ - pattern: "func insecure() {...}"
+ message: |
+ Insecure function insecure detected
+ metadata:
+ cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
+ severity: "ERROR"
+ languages:
+ - "go"
+ """
+
+ [[semgrep.passthrough]]
+ type = "url"
+ value = "https://semgrep.dev/c/p/gosec"
+ target = "gosec.yml"
+```
+
+### Interpolation
+
+The code snippet below shows an example configuration that uses an environment
+variable `$GITURL` to access a private repositories with a Git URL. The variable contains
+a username and token in the `value` field (for example `https://user:token@url`).
+It does not explicitly store credentials in the configuration file. To reduce the risk of leaking secrets through created paths and files, use this feature with caution.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ interpolate = true
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "$GITURL"
+ ref = "refs/remotes/origin/main"
+```
+
+### Configure the append mode for passthroughs
+
+To append data to previous passthroughs, use the `append` mode for the
+passthrough types `file`, `url`, and `raw`.
+
+Passthroughs in `override` mode overwrite files
+created when preceding passthroughs in the chain find a naming
+collision. If `mode` is set to `append`, a passthrough appends data to the
+files created by its predecessors instead of overwriting.
+
+In the below Semgrep configuration,`/sgrules/insecure.yml` assembles two passthroughs. The rules are:
+
+- `insecure`
+- `secret`
+
+These rules add a search pattern to the analyzer and extends Semgrep capabilities.
+
+For passthrough chains we recommend that you enable validation. To enable validation,
+you can either:
+
+- set `validate` to `true`
+
+- set a passthrough `validator` to `xml`, `json`, `yaml`, or `toml`.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ validate = true
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ target = "insecure.yml"
+ value = """
+rules:
+- id: "insecure"
+ patterns:
+ - pattern: "func insecure() {...}"
+ message: |
+ Insecure function insecure detected
+ metadata:
+ cwe: "...
+ severity: "ERROR"
+ languages:
+ - "go"
+"""
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ mode = "append"
+ target = "insecure.yml"
+ value = """
+- id: "secret"
+ patterns:
+ - pattern-either:
+ - pattern: "$MASK = \"...\""
+ - metavariable-regex:
+ metavariable: "$MASK"
+ regex: "(password|pass|passwd|pwd|secret|token)"
+ message: |
+ Use of Hard-coded Password
+ cwe: "..."
+ severity: "ERROR"
+ languages:
+ - "go"
+"""
+```
diff --git a/doc/user/application_security/sast/img/sast_vulnerability_page_fp_detection_v15_2.png b/doc/user/application_security/sast/img/sast_vulnerability_page_fp_detection_v15_2.png
new file mode 100644
index 00000000000..2a3e6e7e45f
--- /dev/null
+++ b/doc/user/application_security/sast/img/sast_vulnerability_page_fp_detection_v15_2.png
Binary files differ
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index 92dc795afe5..d4b0d5b972c 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -176,18 +176,18 @@ All open source (OSS) analyzers have been moved to the GitLab Free tier as of Gi
Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
as shown in the following table:
-| Capability | In Free & Premium | In Ultimate |
-|:----------------------------------------------------------------|:--------------------|:-------------------|
-| [Configure SAST scanners](#configuration) | **{check-circle}** | **{check-circle}** |
-| [Customize SAST settings](#available-cicd-variables) | **{check-circle}** | **{check-circle}** |
-| Download [JSON Report](#reports-json-format) | **{check-circle}** | **{check-circle}** |
-| See new findings in merge request widget | **{dotted-circle}** | **{check-circle}** |
-| [Manage vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
-| [Access the Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
-| [Configure SAST in the UI](#configure-sast-in-the-ui) | **{dotted-circle}** | **{check-circle}** |
-| [Customize SAST rulesets](#customize-rulesets) | **{dotted-circle}** | **{check-circle}** |
-| [Detect False Positives](#false-positive-detection) | **{dotted-circle}** | **{check-circle}** |
-| [Track moved vulnerabilities](#advanced-vulnerability-tracking) | **{dotted-circle}** | **{check-circle}** |
+| Capability | In Free & Premium | In Ultimate |
+|:---------------------------------------------------------------- -|:--------------------|:-------------------|
+| [Configure SAST scanners](#configuration) | **{check-circle}** | **{check-circle}** |
+| [Customize SAST settings](#available-cicd-variables) | **{check-circle}** | **{check-circle}** |
+| Download [JSON Report](#reports-json-format) | **{check-circle}** | **{check-circle}** |
+| See new findings in merge request widget | **{dotted-circle}** | **{check-circle}** |
+| [Manage vulnerabilities](../vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
+| [Access the Security Dashboard](../security_dashboard/index.md) | **{dotted-circle}** | **{check-circle}** |
+| [Configure SAST in the UI](#configure-sast-in-the-ui) | **{dotted-circle}** | **{check-circle}** |
+| [Customize SAST rulesets](customize_rulesets.md) | **{dotted-circle}** | **{check-circle}** |
+| [Detect False Positives](#false-positive-detection) | **{dotted-circle}** | **{check-circle}** |
+| [Track moved vulnerabilities](#advanced-vulnerability-tracking) | **{dotted-circle}** | **{check-circle}** |
## Contribute your scanner
@@ -320,382 +320,6 @@ brakeman-sast:
SAST_ANALYZER_IMAGE_TAG: "2.21.1"
```
-### Customize rulesets **(ULTIMATE)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
-> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
-> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
-> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8.
-
-You can customize the default scanning rules provided by our SAST analyzers.
-Ruleset customization supports the following that can be used
-simultaneously:
-
-- [Disabling predefined rules](index.md#disable-predefined-analyzer-rules). Available for all analyzers.
-- [Overriding predefined rules](index.md#override-predefined-analyzer-rules). Available for all analyzers.
-- Modifying the default behavior of a given analyzer by [synthesizing and passing a custom configuration](index.md#synthesize-a-custom-configuration). Available for only `nodejs-scan`, `gosec`, and `semgrep`.
-
-To customize the default scanning rules, create a file containing custom rules. These rules
-are passed through to the analyzer's underlying scanner tools.
-
-To create a custom ruleset:
-
-1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist.
-1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory.
-
-#### Disable predefined analyzer rules
-
-To disable analyzer rules:
-
-1. Set the `disabled` flag to `true` in the context of a `ruleset` section
-
-1. In one or more `ruleset.identifier` sub sections, list the rules that you want disabled. Every `ruleset.identifier` section has:
-
-- a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
-- a `value` field, to name the rule to be disabled.
-
-##### Example: Disable predefined rules of SAST analyzers
-
-In the following example, the disabled rules are assigned to `eslint`
-and `sobelow` by matching the `type` and `value` of identifiers:
-
-```toml
-[eslint]
- [[eslint.ruleset]]
- disable = true
- [eslint.ruleset.identifier]
- type = "eslint_rule_id"
- value = "security/detect-object-injection"
-
- [[eslint.ruleset]]
- disable = true
- [eslint.ruleset.identifier]
- type = "cwe"
- value = "185"
-
-[sobelow]
- [[sobelow.ruleset]]
- disable = true
- [sobelow.ruleset.identifier]
- type = "sobelow_rule_id"
- value = "sql_injection"
-```
-
-Those vulnerabilities containing the provided type and value are now disabled, meaning
-they won't be displayed in Merge Request nor the Vulnerability Report.
-
-#### Override predefined analyzer rules
-
-To override analyzer rules:
-
-1. In one or more `ruleset.identifier` subsections, list the rules that you want to override. Every `ruleset.identifier` section has:
-
- - a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
- - a `value` field, to name the rule to be overridden.
-
-1. In the `ruleset.override` context of a `ruleset` section,
- provide the keys to override. Any combination of keys can be
- overridden. Valid keys are:
-
- - description
- - message
- - name
- - severity (valid options are: Critical, High, Medium, Low, Unknown, Info)
-
-##### Example: Override predefined rules of SAST analyzers
-
-Before adding a ruleset, we verify which vulnerability will be overwritten by viewing the [`gl-sast-report.json`](#reports-json-format):
-
-```json
-"identifiers": [
- {
- "type": "gosec_rule_id",
- "name": "Gosec Rule ID G307",
- "value": "G307"
- },
- {
- "type": "CWE",
- "name": "CWE-703",
- "value": "703",
- "url": "https://cwe.mitre.org/data/definitions/703.html"
- }
- ]
-```
-
-In the following example, rules from `gosec` are matched by the `type`
-and `value` of identifiers and then overridden:
-
-```toml
-[gosec]
- [[gosec.ruleset]]
- [gosec.ruleset.identifier]
- type = "CWE"
- value = "703"
- [gosec.ruleset.override]
- severity = "Critical"
-```
-
-If a vulnerability is found with a type `CWE` with a value of `703` then
-the vulnerability severity is overwritten to `Critical`.
-
-#### Synthesize a custom configuration
-
-To create a custom configuration, you can use passthrough chains.
-
-A passthrough is a single step in a passthrough chain. The passthrough is evaluated
-in a sequence to incrementally build a configuration. The configuration is then
-passed to the target analyzer.
-
-A configuration section for an analyzer has the following
-parameters:
-
-| Parameter | Explanation |
-| ------------- | ------ |
-| `description` | Description about the analyzer configuration section. |
-| `targetdir` | The `targetdir` parameter defines the directory where the final configuration is located. If `targetdir` is empty, the analyzer uses a random directory. The maximum size of `targetdir` is 100MB. |
-| `validate` | If set to `true`, the target files for passthroughs (`raw`, `file` and `url`) are validated. The validation works for `yaml`, `xml`, `json` and `toml` files. The proper validator is identified based on the extension of the target file. By default, `validate` is set to `false`. |
-| `interpolate` | If set to `true`, environment variable interpolation is enabled so that the configuration uses secrets/tokens. We advise using this feature with caution to not leak any secrets. By default, `interpolate` is set to `false`. |
-| `timeout` | The total `timeout` for the evaluation of a passthrough chain is set to 60 seconds. If `timeout` is not set, the default timeout is 60 seconds. The timeout cannot exceed 300 seconds. |
-
-A configuration section can include one or more passthrough sections. The maximum number of passthrough sections is 20.
-There are several types of passthroughs:
-
-| Type | Description |
-| ------ | ------ |
-| `file` | Use a file that is already available in the Git repository. |
-| `raw` | Provide the configuration inline. |
-| `git` | Pull the configuration from a remote Git repository. |
-| `url` | Fetch the analyzer configuration through HTTP. |
-
-If multiple passthrough sections are defined in a passthrough chain, their
-position in the chain defines the order in which they are evaluated.
-
-- Passthroughs listed later in the chain sequence have a higher precedence.
-- Passthroughs with a higher precedence overwrite (default) and append data
- yielded by previous passthroughs. This is useful for cases where you need to
- use or modify an existing configuration.
-
-Configure a passthrough these parameters:
-
-| Parameter | Explanation |
-| ------------ | ----------- |
-| `type` | One of `file`, `raw`, `git` or `url`. |
-| `target` | The target file that contains the data written by the passthrough evaluation. If no value is provided, a random target file is generated. |
-| `mode` | `overwrite`: if `target` exists, overwrites the file; `append`: append to file instead. The default is `overwrite`. |
-| `ref` | This option only applies to the `git` passthrough type and contains the name of the branch or the SHA to be used. |
-| `subdir` | This option only applies to the `git` passthrough type and can be used to only consider a certain subdirectory of the source Git repository. |
-| `value` | For the `file` `url` and `git` types, `value` defines the source location of the file/Git repository; for the `raw` type, `value` carries the raw content to be passed through. |
-| `validator` | Can be used to explicitly invoke validators (`xml`, `yaml`, `json`, `toml`) on the target files after the application of a passthrough. Per default, no validator is set. |
-
-The amount of data generated by a single passthrough is limited to 1MB.
-
-#### Passthrough configuration examples
-
-##### Raw passthrough for nodejs-scan
-
-Define a custom analyzer configuration. In this example, customized rules are
-defined for the `nodejs-scan` scanner:
-
-```toml
-[nodejs-scan]
- description = 'custom ruleset for nodejs-scan'
-
- [[nodejs-scan.passthrough]]
- type = "raw"
- value = '''
-- nodejs-extensions:
- - .js
-
- template-extensions:
- - .new
- - .hbs
- - ''
-
- ignore-filenames:
-- skip.js
-
- ignore-paths:
- - __MACOSX
- - skip_dir
- - node_modules
-
- ignore-extensions:
- - .hbs
-
- ignore-rules:
- - regex_injection_dos
- - pug_jade_template
- - express_xss
-
-'''
-```
-
-##### File passthrough for Gosec
-
-Provide the name of the file containing a custom analyzer configuration. In
-this example, customized rules for the `gosec` scanner are contained in the
-file `gosec-config.json`:
-
-```toml
-[gosec]
- description = 'custom ruleset for gosec'
-
- [[gosec.passthrough]]
- type = "file"
- value = "gosec-config.json"
-```
-
-##### Passthrough chain for Semgrep
-
-In the below example, we generate a custom configuration under the `/sgrules`
-target directory with a total `timeout` of 60 seconds.
-
-Several passthrouh types generate a configuration for the target analyzer:
-
-- Two `git` passthrough sections pull the head of branch
- `refs/remotes/origin/test` from the `myrules` Git repository, and revision
- `97f7686` from the `sast-rules` Git 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
- the configuration.
- - If there is a filename collision between files in both repositories, files
- from the `sast` repository overwrite files from the `myrules` repository,
- as `sast-rules` has higher precedence.
-- The `raw` entry creates a file named `insecure.yml` under `/sgrules`. The
- full path is `/sgrules/insecure.yml`.
-- The `url` entry fetches a configuration made available through a URL and
- stores it in the `/sgrules/gosec.yml` file.
-
-Afterwards, Semgrep is invoked with the final configuration located under
-`/sgrules`.
-
-```toml
-[semgrep]
- description = 'semgrep custom rules configuration'
- targetdir = "/sgrules"
- timeout = 60
-
- [[semgrep.passthrough]]
- type = "git"
- value = "https://gitlab.com/user/myrules.git"
- ref = "refs/remotes/origin/test"
-
- [[semgrep.passthrough]]
- type = "git"
- value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
- ref = "97f7686db058e2141c0806a477c1e04835c4f395"
- subdir = "go"
-
- [[semgrep.passthrough]]
- type = "raw"
- target = "insecure.yml"
- value = """
-rules:
-- id: "insecure"
- patterns:
- - pattern: "func insecure() {...}"
- message: |
- Insecure function insecure detected
- metadata:
- cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
- severity: "ERROR"
- languages:
- - "go"
- """
-
- [[semgrep.passthrough]]
- type = "url"
- value = "https://semgrep.dev/c/p/gosec"
- target = "gosec.yml"
-```
-
-##### Interpolation
-
-The code snippet below shows an example configuration that uses an environment
-variable `$GITURL` to access a private repositories with a Git URL. The variable contains
-a username and token in the `value` field (for example `https://user:token@url`).
-It does not explicitly store credentials in the configuration file. To reduce the risk of leaking secrets through created paths and files, use this feature with caution.
-
-```toml
-[semgrep]
- description = 'semgrep custom rules configuration'
- targetdir = "/sgrules"
- interpolate = true
-
- [[semgrep.passthrough]]
- type = "git"
- value = "$GITURL"
- ref = "refs/remotes/origin/main"
-```
-
-##### Configure the append mode for passthroughs
-
-To append data to previous passthroughs, use the `append` mode for the
-passthrough types `file`, `url`, and `raw`.
-
-Passthroughs in `override` mode overwrite files
-created when preceding passthroughs in the chain find a naming
-collision. If `mode` is set to `append`, a passthrough appends data to the
-files created by its predecessors instead of overwriting.
-
-In the below Semgrep configuration,`/sgrules/insecure.yml` assembles two passthroughs. The rules are:
-
-- `insecure`
-- `secret`
-
-These rules add a search pattern to the analyzer and extends Semgrep capabilities.
-
-For passthrough chains we recommend that you enable validation. To enable validation,
-you can either:
-
-- set `validate` to `true`
-
-- set a passthrough `validator` to `xml`, `json`, `yaml`, or `toml`.
-
-```toml
-[semgrep]
- description = 'semgrep custom rules configuration'
- targetdir = "/sgrules"
- validate = true
-
- [[semgrep.passthrough]]
- type = "raw"
- target = "insecure.yml"
- value = """
-rules:
-- id: "insecure"
- patterns:
- - pattern: "func insecure() {...}"
- message: |
- Insecure function insecure detected
- metadata:
- cwe: "...
- severity: "ERROR"
- languages:
- - "go"
-"""
-
- [[semgrep.passthrough]]
- type = "raw"
- mode = "append"
- target = "insecure.yml"
- value = """
-- id: "secret"
- patterns:
- - pattern-either:
- - pattern: "$MASK = \"...\""
- - metavariable-regex:
- metavariable: "$MASK"
- regex: "(password|pass|passwd|pwd|secret|token)"
- message: |
- Use of Hard-coded Password
- cwe: "..."
- severity: "ERROR"
- languages:
- - "go"
-"""
-```
-
### False Positive Detection **(ULTIMATE)**
> Introduced in GitLab 14.2.
@@ -706,6 +330,8 @@ False positive detection is available in a subset of the [supported languages](#
- Ruby, in the Brakeman-based analyzer
+![SAST false-positives show in Vulnerability Pages](img/sast_vulnerability_page_fp_detection_v15_2.png)
+
### Advanced vulnerability tracking **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5144) in GitLab 14.2.
@@ -829,7 +455,7 @@ spotbugs-sast:
dependencies:
- build
variables:
- MAVEN_REPO_PATH: ./.m2/repository
+ MAVEN_REPO_PATH: $CI_PROJECT_DIR/.m2/repository
COMPILE: "false"
artifacts:
reports:
@@ -907,7 +533,7 @@ Some analyzers make it possible to filter out vulnerabilities under a given thre
| CI/CD variable | Default value | Description |
|------------------------------|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. You might need to exclude temporary directories used by your build tool as these can generate false positives. To exclude paths, copy and paste the default excluded paths, then **add** your own paths to be excluded. If you don't specify the default excluded paths, you will override the defaults and _only_ paths you specify will be excluded from the SAST scans. |
+| `SAST_EXCLUDED_PATHS` | `spec, test, tests, tmp` | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. You might need to exclude temporary directories used by your build tool as these can generate false positives. To exclude paths, copy and paste the default excluded paths, then **add** your own paths to be excluded. If you don't specify the default excluded paths, you will override the defaults and _only_ paths you specify will be excluded from the SAST scans. |
| `SEARCH_MAX_DEPTH` | 4 | SAST searches the repository to detect the programming languages used, and selects the matching analyzers. Set the value of `SEARCH_MAX_DEPTH` to specify how many directory levels the search phase should span. After the analyzers have been selected, the _entire_ repository is analyzed. |
| `SAST_BANDIT_EXCLUDED_PATHS` | | Comma-separated list of paths to exclude from scan. Uses Python's [`fnmatch` syntax](https://docs.python.org/2/library/fnmatch.html); For example: `'*/tests/*, */venv/*'` |
| `SAST_BRAKEMAN_LEVEL` | 1 | Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low 3=High. |
@@ -963,6 +589,8 @@ removed, or promoted to regular features at any time.
Experimental features available are:
- Enable scanning of iOS and Android apps using the [MobSF analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/mobsf/).
+- Disable the following rules in the [Semgrep analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep) that are known to cause a high rate of false positives:
+ - [`eslint.detect-object-injection`](https://gitlab.com/gitlab-org/security-products/analyzers/semgrep/-/blob/6c4764567d9854f5e4a4a35dacf5a68def7fb4c1/rules/eslint.yml#L751-773)
#### Enable experimental features
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 02d50b0a857..93c32f998fa 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -200,7 +200,7 @@ Secret Detection can be customized by defining available CI/CD variables:
| CI/CD variable | Default value | Description |
|-----------------------------------|---------------|-------------|
-| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
+| `SECRET_DETECTION_EXCLUDED_PATHS` | "" | Exclude vulnerabilities from output based on the paths. This is a comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec` ). Parent directories also match patterns. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225273) in GitLab 13.3. |
| `SECRET_DETECTION_HISTORIC_SCAN` | false | Flag to enable a historic Gitleaks scan. |
| `SECRET_DETECTION_IMAGE_SUFFIX` | "" | Suffix added to the image name. If set to `-fips`, `FIPS-enabled` images are used for scan. See [FIPS-enabled images](#fips-enabled-images) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355519) in GitLab 14.10. |
| `SECRET_DETECTION_LOG_OPTIONS` | "" | [`git log`](https://git-scm.com/docs/git-log) options used to define commit ranges. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350660) in GitLab 15.1.|
@@ -224,9 +224,9 @@ You can customize the default secret detection rules provided with GitLab.
Ruleset customization supports the following capabilities that can be used
simultaneously:
-- [Disabling predefined rules](index.md#disable-predefined-analyzer-rules).
-- [Overriding predefined rules](index.md#override-predefined-analyzer-rules).
-- Modifying the default behavior of the Secret Detection analyzer by [synthesizing and passing a custom configuration](index.md#synthesize-a-custom-configuration).
+- [Disabling predefined rules](#disable-predefined-analyzer-rules).
+- [Overriding predefined rules](#override-predefined-analyzer-rules).
+- Modifying the default behavior of the Secret Detection analyzer by [synthesizing and passing a custom configuration](#synthesize-a-custom-configuration).
Customization allows replacing the default secret detection rules with rules that you define.
@@ -334,7 +334,7 @@ To create a custom configuration, you can use passthrough chains.
```
Passthroughs can also be chained to build more complex configurations.
-For more details, see [SAST Customize ruleset section](../sast/index.md#customize-rulesets).
+For more details, see [SAST Customize ruleset section](../sast/customize_rulesets.md).
### Logging level
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index f0ac01000ef..ad397c3fe04 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -152,8 +152,8 @@ includes a **Resolve with merge request** option.
The following scanners are supported by this feature:
- [Dependency Scanning](../dependency_scanning/index.md).
- Automatic Patch creation is only available for Node.js projects managed with
- `yarn` when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is disabled.
+ Automatic patch creation is only available for Node.js projects managed with
+ `yarn`. Also, Automatic patch creation is only supported when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is disabled.
- [Container Scanning](../container_scanning/index.md).
To resolve a vulnerability, you can either:
diff --git a/doc/user/application_security/vulnerability_report/pipeline.md b/doc/user/application_security/vulnerability_report/pipeline.md
index 14c13f74a5e..32916f4c9c7 100644
--- a/doc/user/application_security/vulnerability_report/pipeline.md
+++ b/doc/user/application_security/vulnerability_report/pipeline.md
@@ -60,14 +60,14 @@ To download a security scan output:
## Scan results
This shows a list of the combined results for all security report artifacts. The filters work like the
-[Vulnerability Report filters](index.md#vulnerability-report-filters), but they are limited to **Severity** and **Tool**, with
+[Vulnerability Report filters](index.md#vulnerability-report-filters), but they are limited to **Severity** and **Tool**, with
the addition of a **Hide dismissed** toggle.
-When you review the vulnerability findings reported in the pipeline, you can select one or more entries for dismissal,
+When you review the vulnerability findings reported in the pipeline, you can select one or more entries for dismissal,
similar to [Dismissing a vulnerability](index.md#dismissing-a-vulnerability) in the Vulnerability Report.
When you merge the branch corresponding to the pipeline into the default branch, all reported findings are combined into
-the [Vulnerability Report](index.md). Scan results in pipelines executed on the default branch are
+the [Vulnerability Report](index.md). Scan results in pipelines executed on the default branch are
incorporated once the pipeline finishes.
| Existing vulnerability status | Dismissed in pipeline? | New vulnerability status |
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index b55a55eebe5..8de777672ff 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -477,8 +477,8 @@ digraph G {
#### PlantUML
-To make PlantUML available in GitLab, a GitLab administrator needs to enable it first.
-Read more in [PlantUML & GitLab](../administration/integration/plantuml.md).
+PlantUML integration is enabled on GitLab.com. To make PlantUML available in self-managed
+installation of GitLab, a GitLab administrator [must enable it](../administration/integration/plantuml.md).
After PlantUML is enabled, enter your text in a `plantuml` block:
diff --git a/doc/user/clusters/agent/ci_cd_workflow.md b/doc/user/clusters/agent/ci_cd_workflow.md
index dce02a72300..16b92eb92a3 100644
--- a/doc/user/clusters/agent/ci_cd_workflow.md
+++ b/doc/user/clusters/agent/ci_cd_workflow.md
@@ -25,7 +25,7 @@ To ensure access to your cluster is safe:
- Each agent has a separate context (`kubecontext`).
- Only the project where the agent is configured, and any additional projects you authorize, can access the agent in your cluster.
-You do not need to have a runner in the cluster with the agent.
+The CI/CD workflow requires runners to be registered with GitLab, but these runners do not have to be in the cluster where the agent is.
## GitLab CI/CD workflow steps
@@ -127,8 +127,8 @@ Run `kubectl config get-contexts`.
### Environments with both certificate-based and agent-based connections
-When you deploy to an environment that has both a [certificate-based
-cluster](../../infrastructure/clusters/index.md) (deprecated) and an agent connection:
+When you deploy to an environment that has both a
+[certificate-based cluster](../../infrastructure/clusters/index.md) (deprecated) and an agent connection:
- The certificate-based cluster's context is called `gitlab-deploy`. This context
is always selected by default.
diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md
index 73a35ffbc64..4978b56917b 100644
--- a/doc/user/clusters/agent/gitops.md
+++ b/doc/user/clusters/agent/gitops.md
@@ -4,10 +4,11 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Using GitOps with a Kubernetes cluster **(PREMIUM)**
+# Using GitOps with a Kubernetes cluster **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0, the `resource_inclusions` and `resource_exclusions` attributes were removed and `reconcile_timeout`, `dry_run_strategy`, `prune`, `prune_timeout`, `prune_propagation_policy`, and `inventory_policy` attributes were added.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/346567) from GitLab Premium to GitLab Free in 15.3.
With GitOps, you can manage containerized clusters and applications from a Git repository that:
diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md
index 9282ac7fb40..4b0d8b77493 100644
--- a/doc/user/clusters/agent/install/index.md
+++ b/doc/user/clusters/agent/install/index.md
@@ -17,7 +17,7 @@ To connect a Kubernetes cluster to GitLab, you must install an agent in your clu
Before you can install the agent in your cluster, you need:
- An existing Kubernetes cluster. If you don't have a cluster, you can create one on a cloud provider, like:
- - [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/docs/quickstart)
+ - [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/docs/deploy-app-cluster)
- [Amazon Elastic Kubernetes Service (EKS)](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)
- [Digital Ocean](https://docs.digitalocean.com/products/kubernetes/quickstart/)
- On self-managed GitLab instances, a GitLab administrator must set up the
diff --git a/doc/user/clusters/agent/vulnerabilities.md b/doc/user/clusters/agent/vulnerabilities.md
index 3b80a7a0f81..5afe3ccec2b 100644
--- a/doc/user/clusters/agent/vulnerabilities.md
+++ b/doc/user/clusters/agent/vulnerabilities.md
@@ -16,6 +16,9 @@ You can also configure your agent so the vulnerabilities are displayed with othe
You can use operational container scanning
to scan container images in your cluster for security vulnerabilities.
+NOTE:
+In GitLab 15.0 and later, you do not need to install Starboard operator in the Kubernetes cluster.
+
To begin scanning all resources in your cluster, add a `starboard`
configuration block to your agent configuration with a `cadence` field
containing a CRON expression for when the scans will be run.
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 47dc9c42797..3dcec32b90c 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -61,7 +61,7 @@ this dashboard.
You can customize the cost dashboard by editing the `.gitlab/dashboards/default_costs.yml`
file or creating similar dashboard configuration files. To learn more, read about
-[customizing dashboards in our documentation](/ee/operations/metrics/dashboards/).
+[customizing dashboards in our documentation](../../operations/metrics/dashboards/index.md).
#### Available metrics
diff --git a/doc/user/clusters/environments.md b/doc/user/clusters/environments.md
index b7732a7abf8..cf71729b517 100644
--- a/doc/user/clusters/environments.md
+++ b/doc/user/clusters/environments.md
@@ -33,8 +33,8 @@ With cluster environments, you can gain insight into:
![Cluster environments page](img/cluster_environments_table_v12_3.png)
-Access to cluster environments is restricted to [group maintainers and
-owners](../permissions.md#group-members-permissions)
+Access to cluster environments is restricted to
+[group maintainers and owners](../permissions.md#group-members-permissions)
## Usage
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index d59edb1e2c2..361276194b0 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -81,8 +81,7 @@ configure cluster:
### Setting the environment scope
-[Environment
-scopes](../project/clusters/multiple_kubernetes_clusters.md#setting-the-environment-scope)
+[Environment scopes](../project/clusters/multiple_kubernetes_clusters.md#setting-the-environment-scope)
are usable when associating multiple clusters to the same management
project.
diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md
index 7ab77c67bcc..4b00784a7ae 100644
--- a/doc/user/clusters/management_project_template.md
+++ b/doc/user/clusters/management_project_template.md
@@ -15,6 +15,9 @@ to create a project. The project includes cluster applications that integrate wi
and extend GitLab functionality. You can use the pattern shown in the project to extend
your custom cluster applications.
+NOTE:
+The project template works on GitLab.com without modifications. If you're on a self-managed instance, you must modify the `.gitlab-ci.yml` file.
+
## Use one project for the agent and your manifests
If you **have not yet** used the agent to connect your cluster with GitLab:
@@ -47,10 +50,7 @@ To create a project from the cluster management project template:
1. From the list of templates, next to **GitLab Cluster Management**, select **Use template**.
1. Enter the project details.
1. Select **Create project**.
-
-If you use self-managed GitLab, your instance might not include the latest version of the template.
-In that case, select **Import project**, **Repository by URL** and for the **Git repository URL**, enter
-`https://gitlab.com/gitlab-org/project-templates/cluster-management.git`.
+1. In the new project, [configure the files](#configure-the-project) as needed.
## Configure the project
@@ -73,6 +73,11 @@ The base image used in the pipeline is built by the
[cluster-applications](https://gitlab.com/gitlab-org/cluster-integration/cluster-applications) project.
This image contains a set of Bash utility scripts to support [Helm v3 releases](https://helm.sh/docs/intro/using_helm/#three-big-concepts).
+If you are on a self-managed instance of GitLab, you must modify the `.gitlab-ci.yml` file.
+Specifically, the section that starts with the comment `Automatic package upgrades` will not
+work on a self-managed instance, because the `include` refers to a GitLab.com project.
+If you remove everything below this comment, the pipeline will succeed.
+
### The main `helmfile.yml` file
The template contains a [Helmfile](https://github.com/roboll/helmfile) you can use to manage
diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md
index f547e5f146f..4cd2705e917 100644
--- a/doc/user/compliance/compliance_report/index.md
+++ b/doc/user/compliance/compliance_report/index.md
@@ -92,30 +92,49 @@ Our criteria for the separation of duties is as follows:
## Chain of Custody report
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213364) in GitLab 13.3.
+> - Chain of Custody reports sent using email [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342594) in GitLab 15.3 with a flag named `async_chain_of_custody_report`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default sending Chain of Custody reports through email is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `async_chain_of_custody_report`. On GitLab.com, this feature is not available.
The Chain of Custody report allows customers to export a list of merge commits within the group.
The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
merge request author, merge request ID, merge user, date merged, pipeline ID, group name, project name, and merge request approvers.
Depending on the merge strategy, the merge commit SHA can be a merge commit, squash commit, or a diff head commit.
-To download the Chain of Custody report:
+To generate the Chain of Custody report:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Security & Compliance > Compliance report**.
1. Select **List of all merge commits**.
-### Commit-specific Chain of Custody Report
+The Chain of Custody report is either:
+
+- Available for download.
+- Sent through email. Requires GitLab 15.3 and later with `async_chain_of_custody_report` feature flag enabled.
+
+### Commit-specific Chain of Custody report
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267629) in GitLab 13.6.
-You can generate a commit-specific Chain of Custody report for a given commit SHA.
+Authenticated group owners can generate a commit-specific Chain of Custody report for a given commit SHA, either:
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Security & Compliance > Compliance report**.
-1. At the top of the compliance report, to the right of **List of all merge commits**, select the down arrow (**{chevron-lg-down}**).
-1. Enter the merge commit SHA, and then select **Export commit custody report**.
- SHA and then select **Export commit custody report**.
+- Using the GitLab UI:
+
+ 1. On the top bar, select **Menu > Groups** and find your group.
+ 1. On the left sidebar, select **Security & Compliance > Compliance report**.
+ 1. At the top of the compliance report, to the right of **List of all merge commits**, select the down arrow (**{chevron-lg-down}**).
+ 1. Enter the merge commit SHA, and then select **Export commit custody report**.
+ SHA and then select **Export commit custody report**.
+
+The Chain of Custody report is either:
+
+- Available for download.
+- Sent through email. Requires GitLab 15.3 and later with `async_chain_of_custody_report` feature flag enabled.
+
+- Using a direct link: `https://gitlab.com/groups/<group-name>/-/security/merge_commit_reports.csv?commit_sha={optional_commit_sha}`, passing in an optional value to the
+ `commit_sha` query parameter.
NOTE:
The Chain of Custody report download is a CSV file, with a maximum size of 15 MB.
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 8c57220068b..1c9f9e85ab7 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -71,13 +71,11 @@ Gradle 1.x projects are not supported. The minimum supported version of Maven is
|------------|----------------------------------------------------------------------------------------------|-------|
| JavaScript | [Bower](https://bower.io/), [npm](https://www.npmjs.com/) (7 and earlier) | |
| Go | [Godep](https://github.com/tools/godep) ([deprecated](../../../update/deprecations.md#godep-support-in-license-compliance)), [go mod](https://github.com/golang/go/wiki/Modules) | |
-| Java | [Gradle](https://gradle.org/) <sup>1</sup>, [Maven](https://maven.apache.org/) | |
+| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) | |
| .NET | [NuGet](https://www.nuget.org/) | The .NET Framework is supported via the [mono project](https://www.mono-project.com/). There are, however, some limitations. The scanner doesn't support Windows-specific dependencies and doesn't report dependencies of your project's listed dependencies. Also, the scanner always marks detected licenses for all dependencies as `unknown`. |
| Python | [pip](https://pip.pypa.io/en/stable/) | Python is supported through [requirements.txt](https://pip.pypa.io/en/stable/user_guide/#requirements-files) and [Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock). |
| Ruby | [gem](https://rubygems.org/) | |
-1. Gradle 7 and later is not supported as dependencies are not discovered when included with the `implementation` directive. Please see [GitLab#341222](https://gitlab.com/gitlab-org/gitlab/-/issues/341222) for more details.
-
### Experimental support
The following languages and package managers are [supported experimentally](https://github.com/pivotal/LicenseFinder#experimental-project-types).
@@ -468,7 +466,7 @@ package manager. For a comprehensive list, consult [the Conan documentation](htt
The default [Conan](https://conan.io/) configuration sets [`CONAN_LOGIN_USERNAME`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)
to `ci_user`, and binds [`CONAN_PASSWORD`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-password-conan-password-remote-name)
to the [`CI_JOB_TOKEN`](../../../ci/variables/predefined_variables.md)
-for the running job. This allows Conan projects to fetch packages from a [GitLab Conan Repository](../../packages/conan_repository/#fetch-conan-package-information-from-the-package-registry)
+for the running job. This allows Conan projects to fetch packages from a [GitLab Conan Repository](../../packages/conan_repository/index.md#fetch-conan-package-information-from-the-package-registry)
if a GitLab remote is specified in the `.conan/remotes.json` file.
To override the default credentials specify a [`CONAN_LOGIN_USERNAME_{REMOTE_NAME}`](https://docs.conan.io/en/latest/reference/env_vars.html#conan-login-username-conan-login-username-remote-name)
diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md
index a2cfdf61a8d..e71a983ccfd 100644
--- a/doc/user/crm/index.md
+++ b/doc/user/crm/index.md
@@ -169,7 +169,7 @@ You can also add, remove, or replace issue contacts using the
[GraphQL](../../api/graphql/reference/index.md#mutationissuesetcrmcontacts)
API.
-## Autocomplete contacts **(FREE SELF)**
+## Autocomplete contacts
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `contacts_autocomplete`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/352123) in GitLab 15.0.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 1f34d182718..3fb0be6480c 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -47,7 +47,19 @@ in a different color.
Avoid mentioning `@all` in issues and merge requests, because it sends an email notification
to all the members of that project's group. This might be interpreted as spam.
Notifications and mentions can be disabled in
-[a group's settings](../group/index.md#disable-email-notifications).
+[a group's settings](../group/manage.md#disable-email-notifications).
+
+### Mention a group in an issue or merge request
+
+When you mention a group in a comment, every member of the group gets a to-do item
+added to their To-do list.
+
+1. Open the MR or issue.
+1. In a comment, type `@` followed by the user, group, or subgroup namespace.
+ For example, `@alex`, `@alex-team`, or `@alex-team/marketing`.
+1. Select **Comment**.
+
+A to-do item is created for all the group and subgroup members.
## Add a comment to a merge request diff
@@ -347,3 +359,19 @@ with a new push.
Threads are now resolved if a push makes a diff section outdated.
Threads on lines that don't change and top-level resolvable threads are not resolved.
+
+## Display paginated merge request discussions
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340172) in GitLab 15.1 [with a flag](../../administration/feature_flags.md) named `paginated_mr_discussions`. Disabled by default.
+> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/364497) in GitLab 15.2.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/364497) in GitLab 15.3.
+
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature
+per project or for your entire instance, ask an administrator to
+[disable the feature flag](../../administration/feature_flags.md) named `paginated_mr_discussions`.
+On GitLab.com, this feature is available.
+
+A merge request can have many discussions. Loading them all in a single request
+can be slow. To improve the performance of loading discussions, they are split into multiple
+pages, loading sequentially.
diff --git a/doc/user/feature_highlight.md b/doc/user/feature_highlight.md
index e5f0369a0f6..ef96d2524a6 100644
--- a/doc/user/feature_highlight.md
+++ b/doc/user/feature_highlight.md
@@ -1,15 +1,11 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'index.md'
+remove_date: '2022-10-29'
---
-# Feature highlight
+This document was moved to [another location](index.md).
-Feature highlights are represented by a pulsing blue dot. Hovering over the dot
-displays more information. They're used to emphasize certain features and
-highlight helpful information to the user.
-
-You can dismiss any feature highlight permanently by clicking the **Got it** link
-at the bottom of the information window. You cannot restore a feature highlight
-after you dismiss it.
+<!-- This redirect file can be deleted after <2022-10-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 (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/free_user_limit.md b/doc/user/free_user_limit.md
index b848128b160..a62b9c9e363 100644
--- a/doc/user/free_user_limit.md
+++ b/doc/user/free_user_limit.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Free user limit **(FREE SAAS)**
-From September 15, 2022, namespaces in GitLab.com on the Free tier
-will be limited to five (5) members per [namespace](group/index.md#namespaces).
+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 groups and personal namespaces.
In a personal namespace, the limit applies across all projects in your personal
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 529b81e2645..53e459f7a09 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -96,7 +96,7 @@ Projects are permanently deleted after a seven-day delay.
If you are on:
-- Premium tier and above, you can disable this by changing the [group setting](../group/index.md#enable-delayed-project-deletion).
+- Premium tier and above, you can disable this by changing the [group setting](../group/manage.md#enable-delayed-project-deletion).
- Free tier, you cannot disable this setting or restore projects.
## Inactive project deletion
@@ -322,7 +322,7 @@ The list of GitLab.com specific settings (and their defaults) is as follows:
Some of these settings are in the process being adjusted. For example, the value
for `shared_buffers` is quite high, and we are
-[considering adjusting it](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/4985).
+[considering adjusting it](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/4985).
## Puma
@@ -336,8 +336,8 @@ documentation.
When a request is rate limited, GitLab responds with a `429` status
code. The client should wait before attempting the request again. There
-are also informational headers with this response detailed in [rate
-limiting responses](#rate-limiting-responses).
+are also informational headers with this response detailed in
+[rate limiting responses](#rate-limiting-responses).
The following table describes the rate limits for GitLab.com, both before and
after the limits change in January, 2021:
@@ -358,9 +358,9 @@ after the limits change in January, 2021:
| **Pipeline creation** requests (for a given **project, user, and commit**) | | **25** requests per minute |
| **Alert integration endpoint** requests (for a given **project**) | | **3600** requests per hour |
-More details are available on the rate limits for [protected
-paths](#protected-paths-throttle) and [raw
-endpoints](../../user/admin_area/settings/rate_limits_on_raw_endpoints.md).
+More details are available on the rate limits for
+[protected paths](#protected-paths-throttle) and
+[raw endpoints](../../user/admin_area/settings/rate_limits_on_raw_endpoints.md).
GitLab can rate-limit requests at several layers. The rate limits listed here
are configured in the application. These limits are the most
@@ -398,7 +398,7 @@ following section.
If you receive a `403 Forbidden` error for all requests to GitLab.com,
check for any automated processes that may be triggering a block. For
-assistance, contact [GitLab Support](https://support.gitlab.com/hc/en-us)
+assistance, contact [GitLab Support](https://support.gitlab.com)
with details, such as the affected IP address.
#### Git and container registry failed authentication ban
@@ -424,13 +424,9 @@ For performance reasons, if a query returns more than 10,000 records, [GitLab ex
### Visibility settings
-If created before GitLab 12.2 (July 2019), these items have the
+Projects, groups, and snippets have the
[Internal visibility](../public_access.md#internal-projects-and-groups)
-setting [disabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/12388):
-
-- Projects
-- Groups
-- Snippets
+setting [disabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/12388).
### SSH maximum number of connections
diff --git a/doc/user/group/access_and_permissions.md b/doc/user/group/access_and_permissions.md
new file mode 100644
index 00000000000..c469d6c2f6d
--- /dev/null
+++ b/doc/user/group/access_and_permissions.md
@@ -0,0 +1,260 @@
+---
+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
+---
+
+# Group access and permissions
+
+Configure your groups to control group permissions and access.
+
+## Group push rules **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in GitLab 12.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
+
+Group push rules allow group maintainers to set
+[push rules](../project/repository/push_rules.md) for newly created projects in the specific group.
+
+To configure push rules for a group:
+
+1. Go to the groups's **Push Rules** page.
+1. Select the settings you want.
+1. Select **Save Push Rules**.
+
+The group's new subgroups have push rules set for them based on either:
+
+- The closest parent group with push rules defined.
+- Push rules set at the instance level, if no parent groups have push rules defined.
+
+## Restrict group access by IP address **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in GitLab 12.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) from GitLab Ultimate to GitLab Premium in 13.1.
+
+To ensure only people from your organization can access particular
+resources, you can restrict access to groups by IP address. This group-level setting
+applies to:
+
+- The GitLab UI, including subgroups, projects, and issues.
+- [In GitLab 12.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/12874), the API.
+
+### Security implications
+
+You should consider some security implications before configuring IP address restrictions.
+
+- Restricting HTTP traffic on GitLab.com with IP address restrictions causes SSH requests (including Git operations over
+ SSH) to fail. For more information, see [the relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/271673).
+- Administrators and group owners can access group settings from any IP address, regardless of IP restriction. However:
+ - Groups owners cannot access projects belonging to the group when accessing from a disallowed IP address.
+ - Administrators can access projects belonging to the group when accessing from a disallowed IP address.
+ Access to projects includes cloning code from them.
+ - Users can still see group and project names and hierarchies. Only the following are restricted:
+ - [Groups](../../api/groups.md), including all [group resources](../../api/api_resources.md#group-resources).
+ - [Project](../../api/projects.md), including all [project resources](../../api/api_resources.md#project-resources).
+- When you register a runner, it is not bound by the IP restrictions. When the runner requests a new job or an update to
+ a job's state, it is also not bound by the IP restrictions. But when the running CI/CD job sends Git requests from a
+ restricted IP address, the IP restriction prevents code from being cloned.
+- Users may still see some events from the IP restricted groups and projects on their dashboard. Activity may include
+ push, merge, issue, or comment events.
+
+### Restrict group access by IP address
+
+To restrict group access by IP address:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. In the **Allow access to the following IP addresses** field, enter IPv4 or IPv6 address ranges in CIDR notation.
+1. Select **Save changes**.
+
+In self-managed installations of GitLab 15.1 and later, you can also configure
+[globally-allowed IP address ranges](../admin_area/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges)
+at the group level.
+
+## Restrict group access by domain **(PREMIUM)**
+
+> - Support for specifying multiple email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1.
+> - Support for restricting access to projects in the group [added](https://gitlab.com/gitlab-org/gitlab/-/issues/14004) in GitLab 14.1.2.
+> - Support for restricting group memberships to groups with a subset of the allowed email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/354791) in GitLab 15.1.1
+
+You can prevent users with email addresses in specific domains from being added to a group and its projects.
+
+To restrict group access by domain:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. In the **Restrict membership by email** field, enter the domain names.
+1. Select **Save changes**.
+
+Any time you attempt to add a new user, the user's [primary email](../profile/index.md#change-your-primary-email) is compared against this list.
+Only users with a [primary email](../profile/index.md#change-your-primary-email) that matches any of the configured email domain restrictions
+can be added to the group.
+
+The most popular public email domains cannot be restricted, such as:
+
+- `gmail.com`, `yahoo.com`, `aol.com`, `icloud.com`
+- `hotmail.com`, `hotmail.co.uk`, `hotmail.fr`
+- `msn.com`, `live.com`, `outlook.com`
+
+When you share a group, both the source and target namespaces must allow the domains of the members' email addresses.
+
+NOTE:
+Removing a domain from the **Restrict membership by email** list does not remove the users with this email domain from the groups and projects under this group.
+Also, if you share a group or project with another group, the target group can add more email domains to its list that are not in the list of the source group.
+Hence, this feature does not ensure that the current members always conform to the **Restrict membership by email** list.
+
+## Prevent group sharing outside the group hierarchy
+
+You can configure a top-level group so its subgroups and projects
+cannot invite other groups outside of the top-level group's hierarchy.
+This option is only available for top-level groups.
+
+For example, in the following group and project hierarchy:
+
+- **Animals > Dogs > Dog Project**
+- **Animals > Cats**
+- **Plants > Trees**
+
+If you prevent group sharing outside the hierarchy for the **Animals** group:
+
+- **Dogs** can invite the group **Cats**.
+- **Dogs** cannot invite the group **Trees**.
+- **Dog Project** can invite the group **Cats**.
+- **Dog Project** cannot invite the group **Trees**.
+
+To prevent sharing outside of the group's hierarchy:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Permissions and group features**.
+1. Select **Prevent members from sending invitations to groups outside of `<group_name>` and its subgroups**.
+1. Select **Save changes**.
+
+## Prevent a project from being shared with groups
+
+Prevent projects in a group from
+[sharing a project with another group](../project/members/share_project_with_groups.md)
+to enable tighter control over project access.
+
+To prevent a project from being shared with other groups:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Select **Prevent sharing a project in `<group_name>` with other groups**.
+1. Select **Save changes**.
+
+This setting applies to all subgroups unless overridden by a group owner. Groups already
+added to a project lose access when the setting is enabled.
+
+## Prevent users from requesting access to a group
+
+As a group owner, you can prevent non-members from requesting access to
+your group.
+
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Find the group and select it.
+1. From the left menu, select **Settings > General**.
+1. Expand the **Permissions and group features** section.
+1. Clear the **Allow users to request access** checkbox.
+1. Select **Save changes**.
+
+## Prevent project forking outside group **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
+
+By default, projects in a group can be forked.
+Optionally, on [GitLab Premium](https://about.gitlab.com/pricing/) or higher tiers,
+you can prevent the projects in a group from being forked outside of the current top-level group.
+
+This setting will be removed from the SAML setting page, and migrated to the
+group settings page. In the interim period, both of these settings are taken into consideration.
+If even one is set to `true`, then the group does not allow outside forks.
+
+To prevent projects from being forked outside the group:
+
+1. Go to the top-level group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Check **Prevent project forking outside current group**.
+1. Select **Save changes**.
+
+Existing forks are not removed.
+
+## Prevent members from being added to projects in a group **(PREMIUM)**
+
+As a group owner, you can prevent any new project membership for all
+projects in a group, allowing tighter control over project membership.
+
+For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
+you can guarantee that project membership cannot be modified during the audit.
+
+You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group.
+
+The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group.
+
+To prevent members from being added to projects in a group:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Under **Membership**, select **Prevent adding new members to projects within this group**.
+1. Select **Save changes**.
+
+All users who previously had permissions can no longer add members to a group.
+API requests to add a new user to a project are not possible.
+
+## Manage group memberships via LDAP **(PREMIUM SELF)**
+
+Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that are associated with GitLab groups.
+
+Group links can be created by using either a CN or a filter. To create these group links, go to the group's **Settings > LDAP Synchronization** page. After configuring the link, it may take more than an hour for the users to sync with the GitLab group.
+
+For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/ldap_synchronization.md#group-sync).
+
+NOTE:
+When you add LDAP synchronization, if an LDAP user is a group member and they are not part of the LDAP group, they are removed from the group.
+
+### Create group links via CN **(PREMIUM SELF)**
+
+To create group links via CN:
+
+<!-- vale gitlab.Spelling = NO -->
+
+1. Select the **LDAP Server** for the link.
+1. As the **Sync method**, select `LDAP Group cn`.
+1. In the **LDAP Group cn** field, begin typing the CN of the group. There is a dropdown list with matching CNs in the configured `group_base`. Select your CN from this list.
+1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
+1. Select **Add Synchronization**.
+
+<!-- vale gitlab.Spelling = YES -->
+
+### Create group links via filter **(PREMIUM SELF)**
+
+To create group links via filter:
+
+1. Select the **LDAP Server** for the link.
+1. As the **Sync method**, select `LDAP user filter`.
+1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter).
+1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
+1. Select **Add Synchronization**.
+
+### Override user permissions **(PREMIUM SELF)**
+
+LDAP user permissions can be manually overridden by an administrator. To override a user's permissions:
+
+1. Go to your group's **Group information > Members** page.
+1. In the row for the user you are editing, select the pencil (**{pencil}**) icon.
+1. Select **Edit permissions** in the modal.
+
+Now you can edit the user's permissions from the **Members** page.
+
+## Troubleshooting
+
+### Verify if access is blocked by IP restriction
+
+If a user sees a 404 when they would normally expect access, and the problem is limited to a specific group, search the `auth.log` rails log for one or more of the following:
+
+- `json.message`: `'Attempting to access IP restricted group'`
+- `json.allowed`: `false`
+
+In viewing the log entries, compare the `remote.ip` with the list of
+[allowed IPs](#restrict-group-access-by-ip-address) for the group.
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 6755bf9ffb9..43587dd54ef 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -30,7 +30,7 @@ To set up custom project templates in a group, add the subgroup that contains th
project templates to the group settings:
1. In the group, create a [subgroup](subgroups/index.md).
-1. [Add projects to the new subgroup](index.md#add-projects-to-a-group) as your templates.
+1. [Add projects to the new subgroup](manage.md#add-projects-to-a-group) as your templates.
1. In the left menu for the group, select **Settings > General**.
1. Expand **Custom project templates** and select the subgroup.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 56d1569c908..c7d92af8ee8 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -18,17 +18,9 @@ You can use groups to communicate with all of the members of the group at once.
For larger organizations, you can also create [subgroups](subgroups/index.md).
-## View groups
+For more information about creating and managing your groups, see [Manage groups](manage.md).
-To view groups:
-
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**. All groups you are a member of are displayed.
-1. To view a list of public groups, select **Explore public groups**.
-
-You can also view groups by namespace.
-
-### Group visibility
+## Group visibility
Like projects, a group can be configured to limit the visibility of it to:
@@ -43,816 +35,6 @@ empty for anonymous users. The group page has a visibility level icon.
Administrator users cannot create a subgroup or project with a higher visibility level than that of
the immediate parent group.
-### Namespaces
-
-In GitLab, a *namespace* organizes related projects together.
-GitLab has two types of namespaces:
-
-- A *personal* namespace, which is based on your username. Projects under a personal namespace must be configured one at a time.
-- A *group* or *subgroup* namespace. In these namespaces, you can manage multiple projects at once.
-
-To determine whether you're viewing a group or personal namespace, you can view the URL. For example:
-
-| Namespace for | URL | Namespace |
-| ------------- | --- | --------- |
-| A user named `alex`. | `https://gitlab.example.com/alex` | `alex` |
-| A group named `alex-team`. | `https://gitlab.example.com/alex-team` | `alex-team` |
-| A group named `alex-team` with a subgroup named `marketing`. | `https://gitlab.example.com/alex-team/marketing` | `alex-team/marketing` |
-
-## Create a group
-
-To create a group:
-
-1. On the top bar, either:
- - Select **Menu > Groups**, and on the right, select **Create group**.
- - To the left of the search box, select the plus sign and then **New group**.
-1. Select **Create group**.
-1. Enter a name for the group in **Group name**. For a list of words that cannot be used as group names, see
- [reserved names](../reserved_names.md).
-1. Enter a path for the group in **Group URL**, which is used for the [namespace](#namespaces).
-1. Choose the [visibility level](../public_access.md).
-1. Personalize your GitLab experience by answering the following questions:
- - What is your role?
- - Who will be using this group?
- - What will you use this group for?
-1. Invite GitLab members or other users to join the group.
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-For details about groups, watch [GitLab Namespaces (users, groups and subgroups)](https://youtu.be/r0sJgjR2f5A).
-
-## Add users to a group
-
-You can give a user access to all projects in a group.
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Group information > Members**.
-1. Select **Invite members**.
-1. Fill in the fields.
- - The role applies to all projects in the group. [Learn more about permissions](../permissions.md).
- - On the **Access expiration date**, the user can no longer access projects in the group.
-1. Select **Invite**.
-
-Members that are not automatically added are displayed on the **Invited** tab.
-Users can be on this tab because they:
-
-- Have not yet accepted the invitation.
-- Are waiting for [approval from an administrator](../admin_area/moderate_users.md).
-- [Exceed the group user cap](#user-cap-for-groups).
-
-## Request access to a group
-
-As a user, you can request to be a member of a group, if an administrator allows it.
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. Under the group name, select **Request Access**.
-
-As many as ten of the most-recently-active group owners receive an email with your request.
-Any group owner can approve or decline the request.
-
-If you change your mind before your request is approved, select
-**Withdraw Access Request**.
-
-## Prevent users from requesting access to a group
-
-As a group owner, you can prevent non-members from requesting access to
-your group.
-
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**.
-1. Find the group and select it.
-1. From the left menu, select **Settings > General**.
-1. Expand the **Permissions and group features** section.
-1. Clear the **Allow users to request access** checkbox.
-1. Select **Save changes**.
-
-## Change the owner of a group
-
-You can change the owner of a group. Each group must always have at least one
-member with the Owner role.
-
-- As an administrator:
- 1. Go to the group and from the left menu, select **Group information > Members**.
- 1. Give a different member the **Owner** role.
- 1. Refresh the page. You can now remove the **Owner** role from the original owner.
-- As the current group's owner:
- 1. Go to the group and from the left menu, select **Group information > Members**.
- 1. Give a different member the **Owner** role.
- 1. Have the new owner sign in and remove the **Owner** role from you.
-
-## Remove a member from the group
-
-Prerequisites:
-
-- You must have the Owner role.
-- The member must have direct membership in the group. If
- membership is inherited from a parent group, then the member can be removed
- from the parent group only.
-
-To remove a member from a group:
-
-1. Go to the group.
-1. From the left menu, select **Group information > Members**.
-1. Next to the member you want to remove, select **Delete**.
-1. Optional. On the **Remove member** confirmation box, select the
- **Also unassign this user from linked issues and merge requests** checkbox.
-1. Select **Remove member**.
-
-## Filter and sort members in a group
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6.
-> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8.
-
-To find members in a group, you can sort, filter, or search.
-
-### Filter a group
-
-Filter a group to find members. By default, all members in the group and subgroups are displayed.
-
-1. Go to the group and select **Group information > Members**.
-1. Above the list of members, in the **Filter members** box, enter filter criteria.
- - To view members in the group only, select **Membership = Direct**.
- - To view members of the group and its subgroups, select **Membership = Inherited**.
- - To view members with two-factor authentication enabled or disabled, select **2FA = Enabled** or **Disabled**.
- - [In GitLab 14.0 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/349887), to view GitLab users created by [SAML SSO](saml_sso/index.md) or [SCIM provisioning](saml_sso/scim_setup.md) select **Enterprise = true**.
-
-### Search a group
-
-You can search for members by name, username, or email.
-
-1. Go to the group and select **Group information > Members**.
-1. Above the list of members, in the **Filter members** box, enter search criteria.
-1. To the right of the **Filter members** box, select the magnifying glass (**{search}**).
-
-### Sort members in a group
-
-You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in**.
-
-1. Go to the group and select **Group information > Members**.
-1. Above the list of members, on the top right, from the **Account** list, select
- the criteria to filter by.
-1. To switch the sort between ascending and descending, to the right of the **Account** list, select the
- arrow (**{sort-lowest}** or **{sort-highest}**).
-
-## Mention a group in an issue or merge request
-
-When you mention a group in a comment, every member of the group gets a to-do item
-added to their To-do list.
-
-1. Open the MR or issue.
-1. In a comment, type `@` followed by the user, group, or subgroup namespace.
- For example, `@alex`, `@alex-team`, or `@alex-team/marketing`.
-1. Select **Comment**.
-
-A to-do item is created for all the group and subgroup members.
-
-## Change the default branch protection of a group
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9.
-> - [Settings moved and renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/340403) in GitLab 14.9.
-
-By default, every group inherits the branch protection set at the global level.
-
-To change this setting for a specific group, see [group level default branch protection](../project/repository/branches/default.md#group-level-default-branch-protection).
-
-To change this setting globally, see [initial default branch protection](../project/repository/branches/default.md#instance-level-default-branch-protection).
-
-NOTE:
-In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab administrators can choose to [disable group owners from updating the default branch protection](../project/repository/branches/default.md#prevent-overrides-of-default-branch-protection).
-
-## Add projects to a group
-
-There are two different ways to add a new project to a group:
-
-- Select a group, and then select **New project**. You can then continue [creating your project](../../user/project/working_with_projects.md#create-a-project).
-- While you are creating a project, select a group from the dropdown list.
-
- ![Select group](img/select_group_dropdown_13_10.png)
-
-### Specify who can add projects to a group
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) in GitLab 10.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) from GitLab Premium to GitLab Free in 11.10.
-
-By default, users with at least the Developer role can create projects under a group.
-
-To change this setting for a specific group:
-
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**.
-1. Find the group and select it.
-1. From the left menu, select **Settings > General**.
-1. Expand the **Permissions and group features** section.
-1. Select the desired option in the **Roles allowed to create projects** dropdown list.
-1. Select **Save changes**.
-
-To change this setting globally, see [Default project creation protection](../admin_area/settings/visibility_and_access_controls.md#define-which-roles-can-create-projects).
-
-## Group activity analytics **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) in GitLab 12.10 as a [Beta feature](../../policy/alpha-beta-support.md#beta-features).
-
-For a group, you can view how many merge requests, issues, and members were created in the last 90 days.
-
-These Group Activity Analytics can be enabled with the `group_activity_analytics` [feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development).
-
-![Recent Group Activity](img/group_activity_analytics_v13_10.png)
-
-Changes to [group wikis](../project/wiki/group.md) do not appear in group activity analytics.
-
-### View group activity
-
-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 **Menu > Groups**.
-1. Select **Your Groups**.
-1. Find the group and select it.
-1. On the left sidebar, select **Group information > Activity**.
-
-To view the activity feed in Atom format, select the
-**RSS** (**{rss}**) icon.
-
-## Share a group with another group
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
-> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../feature_flags.md). Disabled by default.
-> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
-> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) in GitLab 14.9.
- [Feature flag `invite_members_group_modal`](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) removed.
-
-Similar to how you [share a project with a group](../project/members/share_project_with_groups.md),
-you can share a group with another group. To invite a group, you must be a member of it. Members get direct access
-to the shared group. This includes members who inherited group membership from a parent group.
-
-To share a given group, for example, `Frontend` with another group, for example,
-`Engineering`:
-
-1. Go to the `Frontend` group.
-1. On the left sidebar, select **Group information > Members**.
-1. Select **Invite a group**.
-1. In the **Select a group to invite** list, select `Engineering`.
-1. Select a [role](../permissions.md) as maximum access level.
-1. Select **Invite**.
-
-After sharing the `Frontend` group with the `Engineering` group:
-
-- The **Groups** tab lists the `Engineering` group.
-- The **Groups** tab lists a group regardless of whether it is a public or private group.
-- All members of the `Engineering` group have access to the `Frontend` group. The same access levels of the members apply up to the maximum access level selected when sharing the group.
-
-## Manage group memberships via LDAP **(PREMIUM SELF)**
-
-Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that are associated with GitLab groups.
-
-Group links can be created by using either a CN or a filter. To create these group links, go to the group's **Settings > LDAP Synchronization** page. After configuring the link, it may take more than an hour for the users to sync with the GitLab group.
-
-For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/ldap_synchronization.md#group-sync).
-
-NOTE:
-When you add LDAP synchronization, if an LDAP user is a group member and they are not part of the LDAP group, they are removed from the group.
-
-### Create group links via CN **(PREMIUM SELF)**
-
-To create group links via CN:
-
-<!-- vale gitlab.Spelling = NO -->
-
-1. Select the **LDAP Server** for the link.
-1. As the **Sync method**, select `LDAP Group cn`.
-1. In the **LDAP Group cn** field, begin typing the CN of the group. There is a dropdown list with matching CNs in the configured `group_base`. Select your CN from this list.
-1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
-1. Select **Add Synchronization**.
-
-<!-- vale gitlab.Spelling = YES -->
-
-### Create group links via filter **(PREMIUM SELF)**
-
-To create group links via filter:
-
-1. Select the **LDAP Server** for the link.
-1. As the **Sync method**, select `LDAP user filter`.
-1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter).
-1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
-1. Select **Add Synchronization**.
-
-### Override user permissions **(PREMIUM SELF)**
-
-LDAP user permissions can be manually overridden by an administrator. To override a user's permissions:
-
-1. Go to your group's **Group information > Members** page.
-1. In the row for the user you are editing, select the pencil (**{pencil}**) icon.
-1. Select **Edit permissions** in the modal.
-
-Now you can edit the user's permissions from the **Members** page.
-
-## Transfer a group
-
-You can transfer groups in the following ways:
-
-- Transfer a subgroup to a new parent group.
-- Convert a top-level group into a subgroup by transferring it to the desired group.
-- Convert a subgroup into a top-level group by transferring it out of its current group.
-
-When transferring groups, note:
-
-- Changing a group's parent can have unintended side effects. See [what happens when a repository path changes](../project/repository/index.md#what-happens-when-a-repository-path-changes).
-- You can only transfer groups to groups you manage.
-- You must update your local repositories to point to the new location.
-- If the immediate parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects change to match the new parent group's visibility.
-- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this leaves the group without an owner. In this case, the user transferring the group becomes the group's owner.
-- Transfers fail if [packages](../packages/index.md) exist in any of the projects in the group, or in any of its subgroups.
-
-## Change a group's path
-
-Changing a group's path (group URL) can have unintended side effects. Read
-[how redirects behave](../project/repository/index.md#what-happens-when-a-repository-path-changes)
-before you proceed.
-
-If you are changing the path so it can be claimed by another group or user,
-you must rename the group too. Both names and paths must
-be unique.
-
-To retain ownership of the original namespace and protect the URL redirects,
-create a new group and transfer projects to it instead.
-
-To change your group path (group URL):
-
-1. Go to your group's **Settings > General** page.
-1. Expand the **Advanced** section.
-1. Under **Change group URL**, enter a new name.
-1. Select **Change group URL**.
-
-WARNING:
-It is not possible to rename a namespace if it contains a
-project with [Container Registry](../packages/container_registry/index.md) tags,
-because the project cannot be moved.
-
-## Use a custom name for the initial branch
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
-
-When you create a new project in GitLab, a default branch is created with the
-first push. The group owner can
-[customize the initial branch](../project/repository/branches/default.md#group-level-custom-initial-branch-name)
-for the group's projects to meet your group's needs.
-
-## Remove a group
-
-To remove a group and its contents:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Settings > General**.
-1. Expand the **Advanced** section.
-1. In the **Remove group** section, select **Remove group**.
-1. Type the group name.
-1. Select **Confirm**.
-
-A group can also be removed from the groups dashboard:
-
-1. On the top bar, select **Menu > Groups**.
-1. Select **Your Groups**.
-1. Select (**{ellipsis_v}**) for the group you want to delete.
-1. Select **Delete**.
-1. In the Remove group section, select **Remove group**.
-1. Type the group name.
-1. Select **Confirm**.
-
-This action removes the group. It also adds a background job to delete all projects in the group.
-
-Specifically:
-
-- In [GitLab 12.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [GitLab Premium](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#deletion-protection).
-- In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/39504), if the user who sets up the deletion is removed from the group before the
-deletion happens, the job is cancelled, and the group is no longer scheduled for deletion.
-
-## Remove a group immediately **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336985) in GitLab 14.2.
-
-If you don't want to wait, you can remove a group immediately.
-
-Prerequisites:
-
-- You must have at least the Owner role for a group.
-- You have [marked the group for deletion](#remove-a-group).
-
-To immediately remove a group marked for deletion:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Settings > General**.
-1. Expand **Advanced**.
-1. In the "Permanently remove group" section, select **Remove group**.
-1. Confirm the action when asked to.
-
-Your group, its subgroups, projects, and all related resources, including issues and merge requests,
-are deleted.
-
-## Restore a group **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) in GitLab 12.8.
-
-To restore a group that is marked for deletion:
-
-1. Go to your group's **Settings > General** page.
-1. Expand the **Path, transfer, remove** section.
-1. In the Restore group section, select **Restore group**.
-
-## Prevent group sharing outside the group hierarchy
-
-You can configure a top-level group so its subgroups and projects
-cannot invite other groups outside of the top-level group's hierarchy.
-This option is only available for top-level groups.
-
-For example, in the following group and project hierarchy:
-
-- **Animals > Dogs > Dog Project**
-- **Animals > Cats**
-- **Plants > Trees**
-
-If you prevent group sharing outside the hierarchy for the **Animals** group:
-
-- **Dogs** can invite the group **Cats**.
-- **Dogs** cannot invite the group **Trees**.
-- **Dog Project** can invite the group **Cats**.
-- **Dog Project** cannot invite the group **Trees**.
-
-To prevent sharing outside of the group's hierarchy:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Settings > General**.
-1. Expand **Permissions and group features**.
-1. Select **Members cannot invite groups outside of `<group_name>` and its subgroups**.
-1. Select **Save changes**.
-
-## Prevent a project from being shared with groups
-
-Prevent projects in a group from [sharing
-a project with another group](../project/members/share_project_with_groups.md) to enable tighter control over project access.
-
-To prevent a project from being shared with other groups:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Select **Projects in `<group_name>` cannot be shared with other groups**.
-1. Select **Save changes**.
-
-This setting applies to all subgroups unless overridden by a group owner. Groups already
-added to a project lose access when the setting is enabled.
-
-## User cap for groups
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330027) in GitLab 14.7.
-
-FLAG:
-On self-managed GitLab, this feature is not available. On GitLab.com, this feature is available for some groups.
-This feature is not ready for production use.
-
-When the number of billable members reaches the user cap, new users can't be added to the group
-without being approved by the group owner.
-
-Groups with the user cap feature enabled have [group sharing](#share-a-group-with-another-group)
-disabled for the group and its subgroups.
-
-### Specify a user cap for a group
-
-Prerequisite:
-
-- You must be assigned the Owner role) for the group.
-
-To specify a user cap:
-
-1. On the top bar, select **Menu > Groups** and find your group.
- You can set a cap on the top-level group only.
-1. On the left sidebar, select **Settings > General**.
-1. Expand **Permissions and group features**.
-1. In the **User cap** box, enter the desired number of users.
-1. Select **Save changes**.
-
-If you already have more users in the group than the user cap value, users
-are not removed. However, you can't add more without approval.
-
-Increasing the user cap does not approve pending members.
-
-### Remove the user cap for a group
-
-You can remove the user cap, so there is no limit on the number of members you can add to a group.
-
-Prerequisite:
-
-- You must be assigned the Owner role) for the group.
-
-To remove the user cap:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Settings > General**.
-1. Expand **Permissions and group features**.
-1. In the **User cap** box, delete the value.
-1. Select **Save changes**.
-
-Decreasing the user cap does not approve pending members.
-
-### Approve pending members for a group
-
-When the number of billable users reaches the user cap, any new member is put in a pending state
-and must be approved.
-
-Pending members do not count as billable. Members count as billable only after they have been approved and are no longer in a pending state.
-
-Prerequisite:
-
-- You must be assigned the Owner role) for the group.
-
-To approve members that are pending because they've exceeded the user cap:
-
-1. On the top bar, select **Menu > Groups** and find your group.
-1. On the left sidebar, select **Settings > Usage Quotas**.
-1. On the **Seats** tab, under the alert, select **View pending approvals**.
-1. For each member you want to approve, select **Approve**.
-
-## Prevent members from being added to projects in a group **(PREMIUM)**
-
-As a group owner, you can prevent any new project membership for all
-projects in a group, allowing tighter control over project membership.
-
-For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
-you can guarantee that project membership cannot be modified during the audit.
-
-You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group.
-
-The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group.
-
-To prevent members from being added to projects in a group:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Under **Membership**, select **Users cannot be added to projects in this group**.
-1. Select **Save changes**.
-
-All users who previously had permissions can no longer add members to a group.
-API requests to add a new user to a project are not possible.
-
-## Export members as CSV **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/336520) in GitLab 14.5.
-
-You can export a list of members in a group or subgroup as a CSV.
-
-1. Go to your group or subgroup and select either **Group information > Members** or **Subgroup information > Members**.
-1. Select **Export as CSV**.
-1. After the CSV file has been generated, it is emailed as an attachment to the user that requested it.
-
-## Group access restriction by IP address **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in GitLab 12.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) from GitLab Ultimate to GitLab Premium in 13.1.
-
-To ensure only people from your organization can access particular
-resources, you can restrict access to groups by IP address. This group-level setting
-applies to:
-
-- The GitLab UI, including subgroups, projects, issues, and pages.
-- [In GitLab 12.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/12874), the API.
-- Using Git over SSH on GitLab.com.
-
-### Security implications
-
-You should consider some security implications before configuring IP address restrictions.
-
-- Administrators and group owners can access group settings from any IP address, regardless of IP restriction. However:
- - Groups owners cannot access projects belonging to the group when accessing from a disallowed IP address.
- - Administrators can access projects belonging to the group when accessing from a disallowed IP address.
- Access to projects includes cloning code from them.
- - Users can still see group and project names and hierarchies. Only the following are restricted:
- - [Groups](../../api/groups.md), including all [group resources](../../api/api_resources.md#group-resources).
- - [Project](../../api/projects.md), including all [project resources](../../api/api_resources.md#project-resources).
-- When you register a runner, it is not bound by the IP restrictions. When the runner requests a new job or an update to
- a job's state, it is also not bound by the IP restrictions. But when the running CI/CD job sends Git requests from a
- restricted IP address, the IP restriction prevents code from being cloned.
-- Users may still see some events from the IP restricted groups and projects on their dashboard. Activity may include
- push, merge, issue, or comment events.
-- IP access restrictions for Git operations via SSH are supported only on GitLab SaaS.
- IP access restrictions applied to self-managed instances block SSH completely.
-
-### Restrict group access by IP address
-
-To restrict group access by IP address:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. In the **Restrict access by IP address** field, enter IPv4 or IPv6 address ranges in CIDR notation.
-1. Select **Save changes**.
-
-In self-managed installations of GitLab 15.1 and later, you can also configure
-[globally-allowed IP address ranges](../admin_area/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges)
-at the group level.
-
-## Restrict group access by domain **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7297) in GitLab 12.2.
-> - Support for specifying multiple email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/33143) in GitLab 13.1.
-> - Support for restricting access to projects in the group [added](https://gitlab.com/gitlab-org/gitlab/-/issues/14004) in GitLab 14.1.2.
-> - Support for restricting group memberships to groups with a subset of the allowed email domains [added](https://gitlab.com/gitlab-org/gitlab/-/issues/354791) in GitLab 15.0.1
-
-You can prevent users with email addresses in specific domains from being added to a group and its projects.
-
-To restrict group access by domain:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. In the **Restrict membership by email** field, enter the domain names.
-1. Select **Save changes**.
-
-Any time you attempt to add a new user, the user's [primary email](../profile/index.md#change-your-primary-email) is compared against this list.
-Only users with a [primary email](../profile/index.md#change-your-primary-email) that matches any of the configured email domain restrictions
-can be added to the group.
-
-The most popular public email domains cannot be restricted, such as:
-
-- `gmail.com`, `yahoo.com`, `aol.com`, `icloud.com`
-- `hotmail.com`, `hotmail.co.uk`, `hotmail.fr`
-- `msn.com`, `live.com`, `outlook.com`
-
-When you share a group, both the source and target namespaces must allow the domains of the members' email addresses.
-
-## Restrict Git access protocols
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/365601) in GitLab 15.1 [with a flag](../../administration/feature_flags.md) named `group_level_git_protocol_control`. 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 `group_level_git_protocol_control`. On GitLab.com,
-this feature is available.
-
-You can set the permitted protocols used to access a group's repositories to either SSH, HTTPS, or both. This setting
-is disabled when the [instance setting](../admin_area/settings/visibility_and_access_controls.md#configure-enabled-git-access-protocols) is
-configured by an administrator.
-
-To change the permitted Git access protocols for a group:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Choose the permitted protocols from **Enabled Git access protocols**.
-1. Select **Save changes**.
-
-## Group file templates **(PREMIUM)**
-
-Use group file templates to share a set of templates for common file
-types with every project in a group. It is analogous to the
-[instance template repository](../admin_area/settings/instance_template_repository.md).
-The selected project should follow the same naming conventions as
-are documented on that page.
-
-You can only choose projects in the group as the template source.
-This includes projects shared with the group, but it **excludes** projects in
-subgroups or parent groups of the group being configured.
-
-You can configure this feature for both subgroups and immediate parent groups. A project
-in a subgroup has access to the templates for that subgroup, as well as
-any immediate parent groups.
-
-To learn how to create templates for issues and merge requests, see
-[Description templates](../project/description_templates.md).
-
-Define project templates at a group level by setting a group as the template source.
-[Learn more about group-level project templates](custom_project_templates.md).
-
-### Enable group file template **(PREMIUM)**
-
-To enable group file templates:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Templates** section.
-1. Choose a project to act as the template repository.
-1. Select **Save changes**.
-
-## Disable email notifications
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23585) in GitLab 12.2.
-
-You can disable all email notifications related to the group, which includes its subgroups and projects.
-
-To disable email notifications:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Select **Email notifications are disabled**.
-1. Select **Save changes**.
-
-## Disable group mentions
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21301) in GitLab 12.6.
-
-You can prevent users from being added to a conversation and getting notified when
-anyone [mentions a group](../discussions/index.md#mentions)
-in which those users are members.
-
-Groups with disabled mentions are visualized accordingly in the autocompletion dropdown list.
-
-This is particularly helpful for groups with a large number of users.
-
-To disable group mentions:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Select **Group mentions are disabled**.
-1. Select **Save changes**.
-
-## Enable delayed project deletion **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
-> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11.
-> - [Instance setting to enable by default added](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2.
-> - [Instance setting is inherited and enforced when disabled](https://gitlab.com/gitlab-org/gitlab/-/issues/352960) in GitLab 15.1.
-> - [User interface changed](https://gitlab.com/gitlab-org/gitlab/-/issues/352961) in GitLab 15.1.
-
-[Delayed project deletion](../project/settings/index.md#delayed-project-deletion) is locked and disabled unless the instance-level settings for
-[deletion protection](../admin_area/settings/visibility_and_access_controls.md#deletion-protection) are enabled for either groups only or groups and projects.
-When enabled on groups, projects in the group are deleted after a period of delay. During this period, projects are in a read-only state and can be restored.
-The default period is seven days but [is configurable at the instance level](../admin_area/settings/visibility_and_access_controls.md#retention-period).
-
-On self-managed GitLab, projects are deleted immediately by default.
-In GitLab 14.2 and later, an administrator can
-[change the default setting](../admin_area/settings/visibility_and_access_controls.md#deletion-protection)
-for projects in newly-created groups.
-
-On GitLab.com, see the [GitLab.com settings page](../gitlab_com/index.md#delayed-project-deletion) for
-the default setting.
-
-To enable delayed deletion of projects in a group:
-
-1. Go to the group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Scroll to:
- - (GitLab 15.1 and later) **Deletion protection** and select **Keep deleted projects**.
- - (GitLab 15.0 and earlier) **Enable delayed project deletion** and tick the checkbox.
-1. Optional. To prevent subgroups from changing this setting, select:
- - (GitLab 15.1 and later), **Enforce deletion protection for all subgroups**
- - (GitLab 15.0 and earlier), **Enforce for all subgroups**.
-1. Select **Save changes**.
-
-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.
-
-## Prevent project forking outside group **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
-
-By default, projects in a group can be forked.
-Optionally, on [GitLab Premium](https://about.gitlab.com/pricing/) or higher tiers,
-you can prevent the projects in a group from being forked outside of the current top-level group.
-
-This setting will be removed from the SAML setting page, and migrated to the
-group settings page. In the interim period, both of these settings are taken into consideration.
-If even one is set to `true`, then the group does not allow outside forks.
-
-To prevent projects from being forked outside the group:
-
-1. Go to the top-level group's **Settings > General** page.
-1. Expand the **Permissions and group features** section.
-1. Check **Prevent project forking outside current group**.
-1. Select **Save changes**.
-
-Existing forks are not removed.
-
-## Group push rules **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in GitLab 12.8.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
-
-Group push rules allow group maintainers to set
-[push rules](../project/repository/push_rules.md) for newly created projects in the specific group.
-
-To configure push rules for a group:
-
-1. Go to the groups's **Push Rules** page.
-1. Select the settings you want.
-1. Select **Save Push Rules**.
-
-The group's new subgroups have push rules set for them based on either:
-
-- The closest parent group with push rules defined.
-- Push rules set at the instance level, if no parent groups have push rules defined.
-
-## Group merge request approval settings **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285458) in GitLab 13.9. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md), disabled by default.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
-> - [Feature flag `group_merge_request_approval_settings_feature_flag`](https://gitlab.com/gitlab-org/gitlab/-/issues/343872) removed in GitLab 14.9.
-
-Group approval settings manage [project merge request approval settings](../project/merge_requests/approvals/settings.md)
-at the top-level group level. These settings [cascade to all projects](../project/merge_requests/approvals/settings.md#settings-cascading)
-that belong to the group.
-
-To view the merge request approval settings for a group:
-
-1. Go to the top-level group's **Settings > General** page.
-1. Expand the **Merge request approvals** section.
-1. Select the settings you want.
-1. Select **Save changes**.
-
-Support for group-level settings for merge request approval rules is tracked in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/4367).
-
## Related topics
- [Group wikis](../project/wiki/index.md)
@@ -874,31 +56,8 @@ Support for group-level settings for merge request approval rules is tracked in
- [Integrations](../admin_area/settings/project_integration_management.md).
- [Transfer a project into a group](../project/settings/index.md#transfer-a-project-to-another-namespace).
- [Share a project with a group](../project/members/share_project_with_groups.md): Give all group members access to the project at once.
-- [Lock the sharing with group feature](#prevent-a-project-from-being-shared-with-groups).
+- [Lock the sharing with group feature](access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).
- [Enforce two-factor authentication (2FA)](../../security/two_factor_authentication.md#enforce-2fa-for-all-users-in-a-group): Enforce 2FA
for all group members.
- Namespaces [API](../../api/namespaces.md) and [Rake tasks](../../raketasks/index.md).
- [Control access and visibility](../admin_area/settings/visibility_and_access_controls.md).
-
-## Troubleshooting
-
-### Verify if access is blocked by IP restriction
-
-If a user sees a 404 when they would normally expect access, and the problem is limited to a specific group, search the `auth.log` rails log for one or more of the following:
-
-- `json.message`: `'Attempting to access IP restricted group'`
-- `json.allowed`: `false`
-
-In viewing the log entries, compare the `remote.ip` with the list of
-[allowed IPs](#group-access-restriction-by-ip-address) for the group.
-
-### Validation errors on namespaces and groups
-
-[GitLab 14.4 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70365) performs
-the following checks when creating or updating namespaces or groups:
-
-- Namespaces must not have parents.
-- Group parents must be groups and not namespaces.
-
-In the unlikely event that you see these errors in your GitLab installation,
-[contact Support](https://about.gitlab.com/support/) so that we can improve this validation.
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 858b13b87b8..530635802a6 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -35,10 +35,22 @@ In GitLab, iterations are similar to milestones, with a few differences:
## View the iterations list
-To view the iterations list, go to **{issues}** **Issues > Iterations**.
+To view the iterations list:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. Select **Issues > Iterations**.
+
To view all the iterations in a cadence, ordered by descending date, select that iteration cadence.
From there you can create a new iteration or select an iteration to get a more detailed view.
+NOTE:
+If a project has issue tracking
+[turned off](../../project/settings/index.md#configure-project-visibility-features-and-permissions),
+you can view the iterations list
+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
> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/356069) in GitLab 14.10.
@@ -175,6 +187,7 @@ To group issues by label:
> - [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.3: 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 automate iteration scheduling. You can use them to
automate creating iterations every 1, 2, 3, or 4 weeks. You can also
@@ -195,7 +208,7 @@ To create an iteration cadence:
1. Select **New iteration cadence**.
1. Complete the fields.
- Enter the title and description of the iteration cadence.
- - Enter the first iteration start date of the iteration cadence. Iterations will be scheduled to
+ - 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
@@ -215,10 +228,9 @@ To edit an iteration cadence:
1. On the left sidebar, select **Issues > Iterations**.
1. Select **Edit iteration cadence**.
-When you edit the **Duration**, **Upcoming iterations**, or **First iteration start date** fields,
-only upcoming iterations are affected.
-
-You can edit the first iteration start date of a cadence if the cadence has not started yet.
+When you 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`
@@ -261,25 +273,12 @@ To upgrade the iteration cadence to use the automation features:
1. On the top bar, select **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 you want to upgrade.
-1. Complete the required fields **Duration** and **Upcoming iterations**.
+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**.
-#### Start dates of converted cadences
-
-The first iteration start date of your converted cadence is set to the start date of its
-**first** existing iteration.
-
-If you attempt to set a new start date, the conversion fails with an error message.
-If your manual cadence is empty, converting it to use automatic scheduling is effectively
-the same as creating a new automated cadence.
-
-GitLab will start scheduling new iterations on the same day of the week as the start date,
-starting from the nearest such day from the current date.
-
-During the conversion process GitLab does not delete or modify existing **ongoing** or
-**closed** iterations. If you have iterations with start dates in the future,
-they are updated to fit your cadence settings.
-
#### Converted cadences example
For example, suppose it's Friday, April 15, and you have three iterations in a manual cadence:
@@ -288,20 +287,21 @@ For example, suppose it's Friday, April 15, and you have three iterations in a m
- Tuesday, April 12 - Friday, April 15 (ongoing)
- Tuesday, May 3 - Friday, May 6 (upcoming)
-On Friday, April 15, you convert the manual cadence
-to automate scheduling iterations every week, up to two upcoming iterations.
-
-The first iteration is closed, and the second iteration is ongoing,
-so they aren't deleted or modified in the conversion process.
-
-To observe the weekly duration, the third iteration is updated so that it:
+The earliest possible **Automation start date** you can choose
+is Saturday, April 16 in this scenario, because April 15 overlaps with
+the ongoing iteration.
-- Starts on Monday, April 18 - which is the nearest date that is Monday.
-- Ends on Sunday, April 24.
-
-Finally, to always have two upcoming iterations, an additional iteration is scheduled:
+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.
diff --git a/doc/user/group/manage.md b/doc/user/group/manage.md
new file mode 100644
index 00000000000..a9cc6cc8432
--- /dev/null
+++ b/doc/user/group/manage.md
@@ -0,0 +1,570 @@
+---
+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
+---
+
+# Manage groups
+
+Use groups to manage one or more related projects at the same time.
+
+## View groups
+
+1. On the top bar, select **Menu > Groups**.
+1. Select **Explore groups**.
+
+The **Groups** page shows a list of groups, sorted by last updated date.
+
+- To explore all public groups, select **Explore groups**.
+- To view groups where you have a direct or indirect membership, select **Your groups**. This tab shows groups that you are a member of:
+ - Through membership of a subgroup's parent group.
+ - Through direct or inherited membership of a project in the group or subgroup.
+
+## Create a group
+
+To create a group:
+
+1. On the top bar, either:
+ - Select **Menu > Groups**, and on the right, select **Create group**.
+ - To the left of the search box, select the plus sign and then **New group**.
+1. Select **Create group**.
+1. Enter a name for the group in **Group name**. For a list of words that cannot be used as group names, see
+ [reserved names](../reserved_names.md).
+1. Enter a path for the group in **Group URL**, which is used for the [namespace](../namespace/index.md).
+1. Choose the [visibility level](../public_access.md).
+1. Personalize your GitLab experience by answering the following questions:
+ - What is your role?
+ - Who will be using this group?
+ - What will you use this group for?
+1. Invite GitLab members or other users to join the group.
+
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For details about groups, watch [GitLab Namespaces (users, groups and subgroups)](https://youtu.be/r0sJgjR2f5A).
+
+## Remove a group
+
+To remove a group and its contents:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Advanced** section.
+1. In the **Remove group** section, select **Remove group**.
+1. Type the group name.
+1. Select **Confirm**.
+
+A group can also be removed from the groups dashboard:
+
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Select (**{ellipsis_v}**) for the group you want to delete.
+1. Select **Delete**.
+1. In the Remove group section, select **Remove group**.
+1. Type the group name.
+1. Select **Confirm**.
+
+This action removes the group. It also adds a background job to delete all projects in the group.
+
+Specifically:
+
+- In [GitLab 12.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [GitLab Premium](https://about.gitlab.com/pricing/premium/) or higher tiers, this action adds a background job to mark a group for deletion. By default, the job schedules the deletion 7 days in the future. You can modify this waiting period through the [instance settings](../admin_area/settings/visibility_and_access_controls.md#deletion-protection).
+- In [GitLab 13.6 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/39504), if the user who sets up the deletion is removed from the group before the
+deletion happens, the job is cancelled, and the group is no longer scheduled for deletion.
+
+## Remove a group immediately **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336985) in GitLab 14.2.
+
+If you don't want to wait, you can remove a group immediately.
+
+Prerequisites:
+
+- You must have at least the Owner role for a group.
+- You have [marked the group for deletion](#remove-a-group).
+
+To immediately remove a group marked for deletion:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Advanced**.
+1. In the "Permanently remove group" section, select **Remove group**.
+1. Confirm the action when asked to.
+
+Your group, its subgroups, projects, and all related resources, including issues and merge requests,
+are deleted.
+
+## Restore a group **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33257) in GitLab 12.8.
+
+To restore a group that is marked for deletion:
+
+1. Go to your group's **Settings > General** page.
+1. Expand the **Path, transfer, remove** section.
+1. In the Restore group section, select **Restore group**.
+
+## Request access to a group
+
+As a user, you can request to be a member of a group, if an administrator allows it.
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. Under the group name, select **Request Access**.
+
+As many as ten of the most-recently-active group owners receive an email with your request.
+Any group owner can approve or decline the request.
+
+If you change your mind before your request is approved, select
+**Withdraw Access Request**.
+
+## Filter and sort members in a group
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8.
+
+To find members in a group, you can sort, filter, or search.
+
+### Filter a group
+
+Filter a group to find members. By default, all members in the group and subgroups are displayed.
+
+1. Go to the group and select **Group information > Members**.
+1. Above the list of members, in the **Filter members** box, enter filter criteria.
+ - To view members in the group only, select **Membership = Direct**.
+ - To view members of the group and its subgroups, select **Membership = Inherited**.
+ - To view members with two-factor authentication enabled or disabled, select **2FA = Enabled** or **Disabled**.
+ - [In GitLab 14.0 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/349887), to view GitLab users created by [SAML SSO](saml_sso/index.md) or [SCIM provisioning](saml_sso/scim_setup.md) select **Enterprise = true**.
+
+### Search a group
+
+You can search for members by name, username, or email.
+
+1. Go to the group and select **Group information > Members**.
+1. Above the list of members, in the **Filter members** box, enter search criteria.
+1. To the right of the **Filter members** box, select the magnifying glass (**{search}**).
+
+### Sort members in a group
+
+You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in**.
+
+1. Go to the group and select **Group information > Members**.
+1. Above the list of members, on the top right, from the **Account** list, select
+ the criteria to filter by.
+1. To switch the sort between ascending and descending, to the right of the **Account** list, select the
+ arrow (**{sort-lowest}** or **{sort-highest}**).
+
+## Add users to a group
+
+You can give a user access to all projects in a group.
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Group information > Members**.
+1. Select **Invite members**.
+1. Fill in the fields.
+ - The role applies to all projects in the group. [Learn more about permissions](../permissions.md).
+ - On the **Access expiration date**, the user can no longer access projects in the group.
+1. Select **Invite**.
+
+Members that are not automatically added are displayed on the **Invited** tab.
+Users can be on this tab because they:
+
+- Have not yet accepted the invitation.
+- Are waiting for [approval from an administrator](../admin_area/moderate_users.md).
+- [Exceed the group user cap](#user-cap-for-groups).
+
+## Remove a member from the group
+
+Prerequisites:
+
+- You must have the Owner role.
+- The member must have direct membership in the group. If
+ membership is inherited from a parent group, then the member can be removed
+ from the parent group only.
+
+To remove a member from a group:
+
+1. Go to the group.
+1. From the left menu, select **Group information > Members**.
+1. Next to the member you want to remove, select **Delete**.
+1. Optional. On the **Remove member** confirmation box, select the
+ **Also unassign this user from linked issues and merge requests** checkbox.
+1. Select **Remove member**.
+
+## Add projects to a group
+
+There are two different ways to add a new project to a group:
+
+- Select a group, and then select **New project**. You can then continue [creating your project](../../user/project/working_with_projects.md#create-a-project).
+- While you are creating a project, select a group from the dropdown list.
+
+ ![Select group](img/select_group_dropdown_13_10.png)
+
+### Specify who can add projects to a group
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2534) in GitLab 10.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25975) from GitLab Premium to GitLab Free in 11.10.
+
+By default, users with at least the Developer role can create projects under a group.
+
+To change this setting for a specific group:
+
+1. On the top bar, select **Menu > Groups**.
+1. Select **Your Groups**.
+1. Find the group and select it.
+1. From the left menu, select **Settings > General**.
+1. Expand the **Permissions and group features** section.
+1. Select the desired option in the **Allowed to create projects** dropdown list.
+1. Select **Save changes**.
+
+To change this setting globally, see [Default project creation protection](../admin_area/settings/visibility_and_access_controls.md#define-which-roles-can-create-projects).
+
+## Change the owner of a group
+
+You can change the owner of a group. Each group must always have at least one
+member with the Owner role.
+
+- As an administrator:
+ 1. Go to the group and from the left menu, select **Group information > Members**.
+ 1. Give a different member the **Owner** role.
+ 1. Refresh the page. You can now remove the **Owner** role from the original owner.
+- As the current group's owner:
+ 1. Go to the group and from the left menu, select **Group information > Members**.
+ 1. Give a different member the **Owner** role.
+ 1. Have the new owner sign in and remove the **Owner** role from you.
+
+## Change a group's path
+
+Changing a group's path (group URL) can have unintended side effects. Read
+[how redirects behave](../project/repository/index.md#what-happens-when-a-repository-path-changes)
+before you proceed.
+
+If you are changing the path so it can be claimed by another group or user,
+you must rename the group too. Both names and paths must
+be unique.
+
+To retain ownership of the original namespace and protect the URL redirects,
+create a new group and transfer projects to it instead.
+
+To change your group path (group URL):
+
+1. Go to your group's **Settings > General** page.
+1. Expand the **Advanced** section.
+1. Under **Change group URL**, enter a new name.
+1. Select **Change group URL**.
+
+WARNING:
+It is not possible to rename a namespace if it contains a
+project with [Container Registry](../packages/container_registry/index.md) tags,
+because the project cannot be moved.
+
+## Change the default branch protection of a group
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9.
+> - [Settings moved and renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/340403) in GitLab 14.9.
+
+By default, every group inherits the branch protection set at the global level.
+
+To change this setting for a specific group, see [group level default branch protection](../project/repository/branches/default.md#group-level-default-branch-protection).
+
+To change this setting globally, see [initial default branch protection](../project/repository/branches/default.md#instance-level-default-branch-protection).
+
+NOTE:
+In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab administrators can choose to [disable group owners from updating the default branch protection](../project/repository/branches/default.md#prevent-overrides-of-default-branch-protection).
+
+## Use a custom name for the initial branch
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/43290) in GitLab 13.6.
+
+When you create a new project in GitLab, a default branch is created with the
+first push. The group owner can
+[customize the initial branch](../project/repository/branches/default.md#group-level-custom-initial-branch-name)
+for the group's projects to meet your group's needs.
+
+## Share a group with another group
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../feature_flags.md). Disabled by default.
+> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) in GitLab 14.9.
+ [Feature flag `invite_members_group_modal`](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) removed.
+
+Similar to how you [share a project with a group](../project/members/share_project_with_groups.md),
+you can share a group with another group. To invite a group, you must be a member of it. Members get direct access
+to the shared group. This includes members who inherited group membership from a parent group.
+
+To share a given group, for example, `Frontend` with another group, for example,
+`Engineering`:
+
+1. Go to the `Frontend` group.
+1. On the left sidebar, select **Group information > Members**.
+1. Select **Invite a group**.
+1. In the **Select a group to invite** list, select `Engineering`.
+1. Select a [role](../permissions.md) as maximum access level.
+1. Select **Invite**.
+
+After sharing the `Frontend` group with the `Engineering` group:
+
+- The **Groups** tab lists the `Engineering` group.
+- The **Groups** tab lists a group regardless of whether it is a public or private group.
+- All members of the `Engineering` group have access to the `Frontend` group. The same access levels of the members apply up to the maximum access level selected when sharing the group.
+
+## Transfer a group
+
+You can transfer groups in the following ways:
+
+- Transfer a subgroup to a new parent group.
+- Convert a top-level group into a subgroup by transferring it to the desired group.
+- Convert a subgroup into a top-level group by transferring it out of its current group.
+
+When transferring groups, note:
+
+- Changing a group's parent can have unintended side effects. See [what happens when a repository path changes](../project/repository/index.md#what-happens-when-a-repository-path-changes).
+- You can only transfer groups to groups you manage.
+- You must update your local repositories to point to the new location.
+- If the immediate parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects change to match the new parent group's visibility.
+- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this leaves the group without an owner. In this case, the user transferring the group becomes the group's owner.
+- Transfers fail if [packages](../packages/index.md) exist in any of the projects in the group, or in any of its subgroups.
+
+To transfer a group:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Advanced** section.
+1. In the **Remove group** section, select **Transfer group**.
+1. Select the group name in the drop down menu.
+1. Select **Transfer group**.
+
+## Enable delayed project deletion **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
+> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11.
+> - [Instance setting to enable by default added](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2.
+> - [Instance setting is inherited and enforced when disabled](https://gitlab.com/gitlab-org/gitlab/-/issues/352960) in GitLab 15.1.
+> - [User interface changed](https://gitlab.com/gitlab-org/gitlab/-/issues/352961) in GitLab 15.1.
+
+[Delayed project deletion](../project/settings/index.md#delayed-project-deletion) is locked and disabled unless the instance-level settings for
+[deletion protection](../admin_area/settings/visibility_and_access_controls.md#deletion-protection) is enabled for either groups only or groups and projects.
+When enabled on groups, projects in the group are deleted after a period of delay. During this period, projects are in a read-only state and can be restored.
+The default period is seven days but [is configurable at the instance level](../admin_area/settings/visibility_and_access_controls.md#retention-period).
+
+On self-managed GitLab, projects are deleted immediately by default.
+In GitLab 14.2 and later, an administrator can
+[change the default setting](../admin_area/settings/visibility_and_access_controls.md#deletion-protection)
+for projects in newly-created groups.
+
+On GitLab.com, see the [GitLab.com settings page](../gitlab_com/index.md#delayed-project-deletion) for
+the default setting.
+
+To enable delayed deletion of projects in a group:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Scroll to:
+ - (GitLab 15.1 and later) **Deletion protection** and select **Keep deleted projects**.
+ - (GitLab 15.0 and earlier) **Enable delayed project deletion** and tick the checkbox.
+1. Optional. To prevent subgroups from changing this setting, select:
+ - (GitLab 15.1 and later), **Enforce deletion protection for all subgroups**
+ - (GitLab 15.0 and earlier), **Enforce for all subgroups**.
+1. Select **Save changes**.
+
+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.
+
+## Disable email notifications
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23585) in GitLab 12.2.
+
+You can disable all email notifications related to the group, which includes its subgroups and projects.
+
+To disable email notifications:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Select **Disable email notifications**.
+1. Select **Save changes**.
+
+## Disable group mentions
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21301) in GitLab 12.6.
+
+You can prevent users from being added to a conversation and getting notified when
+anyone [mentions a group](../discussions/index.md#mentions)
+in which those users are members.
+
+Groups with disabled mentions are visualized accordingly in the autocompletion dropdown list.
+
+This is particularly helpful for groups with a large number of users.
+
+To disable group mentions:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Permissions and group features** section.
+1. Select **Disable group mentions**.
+1. Select **Save changes**.
+
+## Export members as CSV **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/336520) in GitLab 14.5.
+
+You can export a list of members in a group or subgroup as a CSV.
+
+1. Go to your group or subgroup and select either **Group information > Members** or **Subgroup information > Members**.
+1. Select **Export as CSV**.
+1. After the CSV file has been generated, it is emailed as an attachment to the user that requested it.
+
+## User cap for groups
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330027) in GitLab 14.7.
+
+FLAG:
+On self-managed GitLab, this feature is not available. On GitLab.com, this feature is available for some groups.
+This feature is not ready for production use.
+
+When the number of billable members reaches the user cap, new users can't be added to the group
+without being approved by the group owner.
+
+Groups with the user cap feature enabled have [group sharing](#share-a-group-with-another-group)
+disabled for the group and its subgroups.
+
+### Specify a user cap for a group
+
+Prerequisite:
+
+- You must be assigned the Owner role) for the group.
+
+To specify a user cap:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+ You can set a cap on the top-level group only.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Permissions and group features**.
+1. In the **User cap** box, enter the desired number of users.
+1. Select **Save changes**.
+
+If you already have more users in the group than the user cap value, users
+are not removed. However, you can't add more without approval.
+
+Increasing the user cap does not approve pending members.
+
+### Remove the user cap for a group
+
+You can remove the user cap, so there is no limit on the number of members you can add to a group.
+
+Prerequisite:
+
+- You must be assigned the Owner role) for the group.
+
+To remove the user cap:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Permissions and group features**.
+1. In the **User cap** box, delete the value.
+1. Select **Save changes**.
+
+Decreasing the user cap does not approve pending members.
+
+### Approve pending members for a group
+
+When the number of billable users reaches the user cap, any new member is put in a pending state
+and must be approved.
+
+Pending members do not count as billable. Members count as billable only after they have been approved and are no longer in a pending state.
+
+Prerequisite:
+
+- You must be assigned the Owner role) for the group.
+
+To approve members that are pending because they've exceeded the user cap:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > Usage Quotas**.
+1. On the **Seats** tab, under the alert, select **View pending approvals**.
+1. For each member you want to approve, select **Approve**.
+
+## Group file templates **(PREMIUM)**
+
+Use group file templates to share a set of templates for common file
+types with every project in a group. It is analogous to the
+[instance template repository](../admin_area/settings/instance_template_repository.md).
+The selected project should follow the same naming conventions as
+are documented on that page.
+
+You can only choose projects in the group as the template source.
+This includes projects shared with the group, but it **excludes** projects in
+subgroups or parent groups of the group being configured.
+
+You can configure this feature for both subgroups and immediate parent groups. A project
+in a subgroup has access to the templates for that subgroup, as well as
+any immediate parent groups.
+
+To learn how to create templates for issues and merge requests, see
+[Description templates](../project/description_templates.md).
+
+Define project templates at a group level by setting a group as the template source.
+[Learn more about group-level project templates](custom_project_templates.md).
+
+### Enable group file template **(PREMIUM)**
+
+To enable group file templates:
+
+1. Go to the group's **Settings > General** page.
+1. Expand the **Templates** section.
+1. Choose a project to act as the template repository.
+1. Select **Save changes**.
+
+## Group merge request approval settings **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285458) in GitLab 13.9. [Deployed behind the `group_merge_request_approval_settings_feature_flag` flag](../../administration/feature_flags.md), disabled by default.
+> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/285410) in GitLab 14.5.
+> - [Feature flag `group_merge_request_approval_settings_feature_flag`](https://gitlab.com/gitlab-org/gitlab/-/issues/343872) removed in GitLab 14.9.
+
+Group approval settings manage [project merge request approval settings](../project/merge_requests/approvals/settings.md)
+at the top-level group level. These settings [cascade to all projects](../project/merge_requests/approvals/settings.md#settings-cascading)
+that belong to the group.
+
+To view the merge request approval settings for a group:
+
+1. Go to the top-level group's **Settings > General** page.
+1. Expand the **Merge request approvals** section.
+1. Select the settings you want.
+1. Select **Save changes**.
+
+Support for group-level settings for merge request approval rules is tracked in this [epic](https://gitlab.com/groups/gitlab-org/-/epics/4367).
+
+## Group activity analytics **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207164) in GitLab 12.10 as a [Beta feature](../../policy/alpha-beta-support.md#beta-features).
+
+For a group, you can view how many merge requests, issues, and members were created in the last 90 days.
+
+These Group Activity Analytics can be enabled with the `group_activity_analytics` [feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development).
+
+![Recent Group Activity](img/group_activity_analytics_v13_10.png)
+
+Changes to [group wikis](../project/wiki/group.md) do not appear in group activity analytics.
+
+### View group activity
+
+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 **Menu > Groups**.
+1. Select **Your Groups**.
+1. Find the group and select it.
+1. On the left sidebar, select **Group information > Activity**.
+
+To view the activity feed in Atom format, select the
+**RSS** (**{rss}**) icon.
+
+## Troubleshooting
+
+### Validation errors on namespaces and groups
+
+[GitLab 14.4 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70365) performs
+the following checks when creating or updating namespaces or groups:
+
+- Namespaces must not have parents.
+- Group parents must be groups and not namespaces.
+
+In the unlikely event that you see these errors in your GitLab installation,
+[contact Support](https://about.gitlab.com/support/) so that we can improve this validation.
diff --git a/doc/user/group/saml_sso/example_saml_config.md b/doc/user/group/saml_sso/example_saml_config.md
new file mode 100644
index 00000000000..97e8f9c54a3
--- /dev/null
+++ b/doc/user/group/saml_sso/example_saml_config.md
@@ -0,0 +1,211 @@
+---
+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
+type: reference
+---
+
+# Example group SAML and SCIM configurations **(PREMIUM SAAS)**
+
+These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team's collected knowledge.
+
+Please refer to the GitLab [Group SAML](index.md) docs 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).
+
+They may then set up a test configuration of the desired identity provider. We include example screenshots in this section.
+
+## SAML and SCIM screenshots
+
+This section includes relevant screenshots of the following example configurations of [Group SAML](index.md) and [Group SCIM](scim_setup.md):
+
+- [Azure Active Directory](#azure-active-directory)
+- [Google Workspace](#google-workspace)
+- [Okta](#okta)
+- [OneLogin](#onelogin)
+
+WARNING:
+These screenshots are updated only as needed by GitLab Support. They are **not** official documentation.
+
+If you are currently having an issue with GitLab, you may want to check your [support options](https://about.gitlab.com/support/).
+
+## Azure Active Directory
+
+Basic SAML app configuration:
+
+![Azure AD basic SAML](img/AzureAD-basic_SAML.png)
+
+User claims and attributes:
+
+![Azure AD user claims](img/AzureAD-claims.png)
+
+SCIM mapping:
+
+![Azure AD SCIM Provisioning](img/AzureAD-scim_provisioning.png)
+![Azure AD SCIM Attribute Mapping](img/AzureAD-scim_attribute_mapping.png)
+
+Group Sync:
+
+![Azure Group Claims](img/azure_configure_group_claim.png)
+
+## Google Workspace
+
+Basic SAML app configuration:
+
+![Google Workspace basic SAML](img/GoogleWorkspace-basic-SAML_v14_10.png)
+
+User claims and attributes:
+
+![Google Workspace user claims](img/GoogleWorkspace-claims_v14_10.png)
+
+IdP links and certificate:
+
+NOTE:
+Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for configuring SAML, download the certificate and calculate the SHA1 certificate
+fingerprint.
+
+![Google Workspace Links and Certificate](img/GoogleWorkspace-linkscert_v14_10.png)
+
+## Okta
+
+Basic SAML app configuration for GitLab.com groups:
+
+![Okta basic SAML](img/Okta-GroupSAML.png)
+
+Basic SAML app configuration for GitLab self-managed:
+
+![Okta admin panel view](img/Okta-SM.png)
+
+User claims and attributes:
+
+![Okta Attributes](img/Okta-attributes.png)
+
+Groups attribute:
+
+![Okta Group attribute](img/Okta-GroupAttribute.png)
+
+Advanced SAML app settings (defaults):
+
+![Okta Advanced Settings](img/Okta-advancedsettings.png)
+
+IdP Links and Certificate:
+
+![Okta Links and Certificate](img/Okta-linkscert.png)
+
+Sign on settings:
+
+![Okta SAML settings](img/okta_saml_settings.png)
+
+Setting the username for the newly provisioned users when assigning them the SCIM app:
+
+![Assigning SCIM app to users on Okta](img/okta_setting_username.png)
+
+## OneLogin
+
+Application details:
+
+![OneLogin application details](img/OneLogin-app_details.png)
+
+Parameters:
+
+![OneLogin application details](img/OneLogin-parameters.png)
+
+Adding a user:
+
+![OneLogin user add](img/OneLogin-userAdd.png)
+
+SSO settings:
+
+![OneLogin SSO settings](img/OneLogin-SSOsettings.png)
+
+## SAML response example
+
+When a user signs in using SAML, GitLab receives a SAML response. The SAML response can be found in `production.log` logs as a base64-encoded message. Locate the response by
+searching for `SAMLResponse`. The decoded SAML response is in XML format. For example:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="https://gitlabexample/-/saml/callback" ID="id4898983630840142426821432" InResponseTo="_c65e4c88-9425-4472-b42c-37f4186ac0ee" IssueInstant="2022-05-30T21:30:35.696Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk2y6j57o1Pdr2lI8qh7</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#id4898983630840142426821432">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
+ </ds:Transform>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>neiQvv9d3OgS4GZW8Nptp4JhjpKs3GCefibn+vmRgk4=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>dMsQX8ivi...HMuKGhyLRvabGU6CuPrf7==</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDq...cptGr3vN9TQ==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="id489" IssueInstant="2022-05-30T21:30:35.696Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk2y6j57o1Pdr2lI8qh7</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
+ <ds:Reference URI="#id48989836309833801859473359">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
+ </ds:Transform>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
+ <ds:DigestValue>MaIsoi8hbT9gsi/mNZsz449mUuAcuEWY0q3bc4asOQs=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>dMsQX8ivi...HMuKGhyLRvabGU6CuPrf7==<</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>MIIDq...cptGr3vN9TQ==</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">useremail@domain.com</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="_c65e4c88-9425-4472-b42c-37f4186ac0ee" NotOnOrAfter="2022-05-30T21:35:35.696Z" Recipient="https://gitlab.example.com/-/saml/callback"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" NotBefore="2022-05-30T21:25:35.696Z" NotOnOrAfter="2022-05-30T21:35:35.696Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>https://gitlab.example.com/</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" AuthnInstant="2022-05-30T21:30:35.696Z" SessionIndex="_c65e4c88-9425-4472-b42c-37f4186ac0ee">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
+ <saml2:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
+ <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">useremail@domain.com</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute Name="firtname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
+ <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute Name="lastname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
+ <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute Name="Groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
+ <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Super-awesome-group</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
+```
diff --git a/doc/user/group/saml_sso/group_sync.md b/doc/user/group/saml_sso/group_sync.md
index b8b7a16b31b..8bc316f9396 100644
--- a/doc/user/group/saml_sso/group_sync.md
+++ b/doc/user/group/saml_sso/group_sync.md
@@ -28,7 +28,7 @@ To configure SAML Group Sync:
1. Ensure your SAML identity provider sends an attribute statement with the same name as the value of the `groups_attribute` setting.
- For GitLab.com:
1. See [SAML SSO for GitLab.com groups](index.md).
- 1. Ensure your SAML identity provider sends an attribute statement named `Groups` or `groups`.
+ 1. Ensure your SAML identity provider sends an attribute statement named `Groups` or `groups`.
NOTE:
The value for `Groups` or `groups` in the SAML response can be either the group name or the group ID.
@@ -44,8 +44,8 @@ The value for `Groups` or `groups` in the SAML response can be either the group
Other attribute names such as `http://schemas.microsoft.com/ws/2008/06/identity/claims/groups`
are not accepted as a source of groups.
-See the [SAML troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md)
-for examples on configuring the required attribute name in the SAML identity provider's settings.
+See [examples](../../../user/group/saml_sso/example_saml_config.md)
+for configuring the required attribute name in the SAML identity provider's settings.
## Configure SAML Group Links
@@ -161,3 +161,9 @@ graph TB
GitLabGroupD --> |Member|GitLabUserC
GitLabGroupD --> |Member|GitLabUserD
```
+
+### Use the API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290367) in GitLab 15.3.
+
+You can use the GitLab API to [list, add, and delete](../../../api/groups.md#saml-group-links) SAML group links.
diff --git a/doc/administration/troubleshooting/img/AzureAD-basic_SAML.png b/doc/user/group/saml_sso/img/AzureAD-basic_SAML.png
index 7a0d83ab2dd..7a0d83ab2dd 100644
--- a/doc/administration/troubleshooting/img/AzureAD-basic_SAML.png
+++ b/doc/user/group/saml_sso/img/AzureAD-basic_SAML.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/AzureAD-claims.png b/doc/user/group/saml_sso/img/AzureAD-claims.png
index 576040be337..576040be337 100644
--- a/doc/administration/troubleshooting/img/AzureAD-claims.png
+++ b/doc/user/group/saml_sso/img/AzureAD-claims.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/AzureAD-scim_attribute_mapping.png b/doc/user/group/saml_sso/img/AzureAD-scim_attribute_mapping.png
index 5ad82003eed..5ad82003eed 100644
--- a/doc/administration/troubleshooting/img/AzureAD-scim_attribute_mapping.png
+++ b/doc/user/group/saml_sso/img/AzureAD-scim_attribute_mapping.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png b/doc/user/group/saml_sso/img/AzureAD-scim_provisioning.png
index b2c385151a6..b2c385151a6 100644
--- a/doc/administration/troubleshooting/img/AzureAD-scim_provisioning.png
+++ b/doc/user/group/saml_sso/img/AzureAD-scim_provisioning.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/GoogleWorkspace-basic-SAML_v14_10.png b/doc/user/group/saml_sso/img/GoogleWorkspace-basic-SAML_v14_10.png
index e002503ddc0..e002503ddc0 100644
--- a/doc/administration/troubleshooting/img/GoogleWorkspace-basic-SAML_v14_10.png
+++ b/doc/user/group/saml_sso/img/GoogleWorkspace-basic-SAML_v14_10.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/GoogleWorkspace-claims_v14_10.png b/doc/user/group/saml_sso/img/GoogleWorkspace-claims_v14_10.png
index 2b827e122a8..2b827e122a8 100644
--- a/doc/administration/troubleshooting/img/GoogleWorkspace-claims_v14_10.png
+++ b/doc/user/group/saml_sso/img/GoogleWorkspace-claims_v14_10.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/GoogleWorkspace-linkscert_v14_10.png b/doc/user/group/saml_sso/img/GoogleWorkspace-linkscert_v14_10.png
index 8d6c5010670..8d6c5010670 100644
--- a/doc/administration/troubleshooting/img/GoogleWorkspace-linkscert_v14_10.png
+++ b/doc/user/group/saml_sso/img/GoogleWorkspace-linkscert_v14_10.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-GroupAttribute.png b/doc/user/group/saml_sso/img/Okta-GroupAttribute.png
new file mode 100644
index 00000000000..54c69053754
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-GroupAttribute.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-GroupSAML.png b/doc/user/group/saml_sso/img/Okta-GroupSAML.png
new file mode 100644
index 00000000000..7871e4ff82b
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-GroupSAML.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-SM.png b/doc/user/group/saml_sso/img/Okta-SM.png
new file mode 100644
index 00000000000..b335009fed9
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-SM.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-advancedsettings.png b/doc/user/group/saml_sso/img/Okta-advancedsettings.png
new file mode 100644
index 00000000000..1478dc58ccd
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-advancedsettings.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-attributes.png b/doc/user/group/saml_sso/img/Okta-attributes.png
new file mode 100644
index 00000000000..38af72474d8
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-attributes.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/Okta-linkscert.png b/doc/user/group/saml_sso/img/Okta-linkscert.png
new file mode 100644
index 00000000000..62db5d2b7e3
--- /dev/null
+++ b/doc/user/group/saml_sso/img/Okta-linkscert.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/OneLogin-SSOsettings.png b/doc/user/group/saml_sso/img/OneLogin-SSOsettings.png
index 58f936d8567..58f936d8567 100644
--- a/doc/administration/troubleshooting/img/OneLogin-SSOsettings.png
+++ b/doc/user/group/saml_sso/img/OneLogin-SSOsettings.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/OneLogin-app_details.png b/doc/user/group/saml_sso/img/OneLogin-app_details.png
index 77618960897..77618960897 100644
--- a/doc/administration/troubleshooting/img/OneLogin-app_details.png
+++ b/doc/user/group/saml_sso/img/OneLogin-app_details.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/OneLogin-parameters.png b/doc/user/group/saml_sso/img/OneLogin-parameters.png
index a2fa734152c..a2fa734152c 100644
--- a/doc/administration/troubleshooting/img/OneLogin-parameters.png
+++ b/doc/user/group/saml_sso/img/OneLogin-parameters.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/OneLogin-userAdd.png b/doc/user/group/saml_sso/img/OneLogin-userAdd.png
index 54c1ecd2e68..54c1ecd2e68 100644
--- a/doc/administration/troubleshooting/img/OneLogin-userAdd.png
+++ b/doc/user/group/saml_sso/img/OneLogin-userAdd.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/azure_configure_group_claim.png b/doc/user/group/saml_sso/img/azure_configure_group_claim.png
index 9d8c5348273..9d8c5348273 100644
--- a/doc/administration/troubleshooting/img/azure_configure_group_claim.png
+++ b/doc/user/group/saml_sso/img/azure_configure_group_claim.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/okta_saml_settings.png b/doc/user/group/saml_sso/img/okta_saml_settings.png
new file mode 100644
index 00000000000..9c774b72d66
--- /dev/null
+++ b/doc/user/group/saml_sso/img/okta_saml_settings.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/okta_setting_username.png b/doc/user/group/saml_sso/img/okta_setting_username.png
index 5f87d14bb8b..5f87d14bb8b 100644
--- a/doc/administration/troubleshooting/img/okta_setting_username.png
+++ b/doc/user/group/saml_sso/img/okta_setting_username.png
Binary files differ
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 80e7a5903fa..25060f8e749 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -99,7 +99,7 @@ After you set up your identity provider to work with GitLab, you must configure
![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_12.png)
NOTE:
-The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider, use a secure signature algorithm.
+The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm.
### SSO enforcement
@@ -131,6 +131,8 @@ SSO has the following effects when enabled:
- Git activity originating from CI/CD jobs do not have the SSO check enforced.
- Credentials that are not tied to regular users (for example, project and group access tokens, and deploy keys) do not have the SSO check enforced.
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
+- When the **Enforce SSO-only authentication for Git and Dependency Proxy activity for this group** option is enabled, any API endpoint that involves Git activity is under SSO
+ enforcement. For example, creating or deleting a branch, commit, or tag.
When SSO is enforced, users are not immediately revoked. If the user:
@@ -174,7 +176,7 @@ The recommended attributes and claims settings are:
If using [Group Sync](#group-sync), customize the name of the group claim to match the required attribute.
-See the [troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory) for an example configuration.
+See our [example configuration page](example_saml_config.md#azure-active-directory).
### Google Workspace setup notes
@@ -191,7 +193,7 @@ with the notes below for consideration.
NOTE:
Google Workspace displays a SHA256 fingerprint. To retrieve the SHA1 fingerprint required by GitLab for [configuring SAML](#configure-gitlab), download the certificate and calculate
-the SHA1 certificate fingerprint.
+the SHA1 certificate fingerprint using this sample command: `openssl x509 -noout -fingerprint -sha1 -inform pem -in "GoogleIDPCertificate-domain.com.pem"`.
The recommended attributes and claims settings are:
@@ -206,7 +208,7 @@ For NameID, the following settings are recommended:
When selecting **Verify SAML Configuration** on the GitLab SAML SSO page, disregard the warning recommending setting the NameID format to "persistent".
-See the [troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md#google-workspace) for an example configuration.
+See our [example configuration page](example_saml_config.md#google-workspace).
### Okta setup notes
@@ -445,7 +447,7 @@ To generate a SAML Response:
### Verifying configuration
-For convenience, we've included some [example resources](../../../administration/troubleshooting/group_saml_scim.md) used by our Support Team. While they may help you verify the SAML app configuration, they are not guaranteed to reflect the current state of third-party products.
+For convenience, we've included some [example resources](../../../user/group/saml_sso/example_saml_config.md) used by our Support Team. While they may help you verify the SAML app configuration, they are not guaranteed to reflect the current state of third-party products.
### Verifying NameID
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 04aa99e08af..7962f171166 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -82,7 +82,7 @@ For a list of required attributes, refer to the [SCIM API documentation](../../.
| `userPrincipalName` | `emails[type eq "work"].value` | |
| `mailNickname` | `userName` | |
-For guidance, you can view [an example configuration in the troubleshooting reference](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory).
+For guidance, you can view [an example configuration](example_saml_config.md#azure-active-directory).
1. Below the mapping list select **Show advanced options > Edit attribute list for AppName**.
1. Ensure the `id` is the primary and required field, and `externalId` is also required.
@@ -106,7 +106,7 @@ Before you start this section:
- 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](#gitlab-configuration) process.
-- Complete the setup for SAML application for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/), as described in the [Okta setup notes](index.md#okta-setup-notes).
+- 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.
After the above steps are complete:
@@ -220,6 +220,8 @@ It is important that this SCIM `id` and SCIM `externalId` are configured to the
### 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/#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`.
diff --git a/doc/user/group/settings/group_access_tokens.md b/doc/user/group/settings/group_access_tokens.md
index 9e8fc120731..c3098bb56c2 100644
--- a/doc/user/group/settings/group_access_tokens.md
+++ b/doc/user/group/settings/group_access_tokens.md
@@ -154,5 +154,8 @@ to groups instead of projects. Bot users for groups:
- Do not count as licensed seats.
- Can have a maximum role of Owner for a group. For more information, see
[Create a group access token](../../../api/group_access_tokens.md#create-a-group-access-token).
+- The username is set to `group_{project_id}_bot` for the first access token. For example, `project_123_bot`.
+- The email is set to `group{group_id}_bot@noreply.{Gitlab.config.gitlab.host}`. For example, `group123_bot@noreply.example.com`.
+- All other properties are similar to [bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects)
For more information, see [Bot users for projects](../../project/settings/project_access_tokens.md#bot-users-for-projects).
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index bf4e13779fd..12434de5efc 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -47,6 +47,28 @@ graph TD
end
```
+## View subgroups of a group
+
+Prerequisite:
+
+- To view private nested subgroups, you must be a direct or inherited member of
+the private subgroup.
+
+To view the subgroups of a group:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. Select the **Subgroups and projects** tab.
+1. To view a nested subgroup, expand a subgroup in the hierarchy list.
+
+### Private subgroups in public parent groups
+
+In the hierarchy list, public groups with a private subgroup have an expand option (**{chevron-down}**)
+for all users that indicate there is a subgroup. When users who are not direct or inherited members of
+the private subgroup select expand (**{chevron-down}**), the nested subgroup does not display.
+
+If you prefer to keep information about the presence of nested subgroups private, we advise that you only
+add private subgroups to private parent groups.
+
## Create a subgroup
Prerequisites:
@@ -102,7 +124,7 @@ Subgroup members can:
1. Be [direct members](../../project/members/index.md#add-users-to-a-project) of the subgroup.
1. [Inherit membership](../../project/members/index.md#inherited-membership) of the subgroup from the subgroup's parent group.
-1. Be a member of a group that was [shared with the subgroup's top-level group](../index.md#share-a-group-with-another-group).
+1. Be a member of a group that was [shared with the subgroup's top-level group](../manage.md#share-a-group-with-another-group).
```mermaid
flowchart RL
@@ -161,7 +183,7 @@ In the screenshot above:
- Administrator has the Owner role on group _Four_ and is a member of all subgroups. For that reason, as with User 3,
the **Source** column indicates they are a direct member.
-Members can be [filtered by inherited or direct membership](../index.md#filter-a-group).
+Members can be [filtered by inherited or direct membership](../manage.md#filter-a-group).
### Override ancestor group membership
diff --git a/doc/user/img/completed_tasks_v13_3.png b/doc/user/img/completed_tasks_v13_3.png
deleted file mode 100644
index b12d95f0a23..00000000000
--- a/doc/user/img/completed_tasks_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/img/completed_tasks_v15_3.png b/doc/user/img/completed_tasks_v15_3.png
new file mode 100644
index 00000000000..c1619e70839
--- /dev/null
+++ b/doc/user/img/completed_tasks_v15_3.png
Binary files differ
diff --git a/doc/user/infrastructure/clusters/connect/new_civo_cluster.md b/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
index fad75ca6cab..ecf93958b1e 100644
--- a/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_civo_cluster.md
@@ -90,7 +90,7 @@ Refer to the [Civo Terraform provider](https://registry.terraform.io/providers/c
After configuring your project, manually trigger the provisioning of your cluster. In GitLab:
1. On the left sidebar, go to **CI/CD > Pipelines**.
-1. Next to **Play** (**{play}**), select the dropdown icon (**{angle-down}**).
+1. Next to **Play** (**{play}**), select the dropdown icon (**{chevron-lg-down}**).
1. Select **Deploy** to manually trigger the deployment job.
When the pipeline finishes successfully, you can see your new cluster:
diff --git a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
index 798e02ab9b4..2f5967bd7ee 100644
--- a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md
@@ -122,12 +122,13 @@ To remove all resources:
stages:
- init
- validate
+ - test
- build
- deploy
- cleanup
destroy:
- extends: .destroy
+ extends: .terraform:destroy
needs: []
```
diff --git a/doc/user/infrastructure/clusters/deploy/inventory_object.md b/doc/user/infrastructure/clusters/deploy/inventory_object.md
index d184d969ace..fc3b86776f0 100644
--- a/doc/user/infrastructure/clusters/deploy/inventory_object.md
+++ b/doc/user/infrastructure/clusters/deploy/inventory_object.md
@@ -4,9 +4,10 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Tracking cluster resources managed by GitLab **(PREMIUM)**
+# Tracking cluster resources managed by GitLab **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/346567) from GitLab Premium to GitLab Free in 15.3.
GitLab uses an inventory object to track the resources you deploy to your cluster.
The inventory object is a `ConfigMap` that contains a list of controlled objects.
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 5ad1fb81a39..51fd626ce0f 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md
@@ -18,19 +18,28 @@ uncomment this line from your `helmfile.yaml`:
- path: applications/cert-manager/helmfile.yaml
```
+And update the `applications/cert-manager/helmfile.yaml` with a valid email address.
+
+```yaml
+ values:
+ - letsEncryptClusterIssuer:
+ #
+ # IMPORTANT: This value MUST be set to a valid email.
+ #
+ email: example@example.com
+```
+
NOTE:
-If your Kubernetes version is earlier than 1.20 and you are [migrating from GitLab
-Managed Apps to a cluster management
-project](../../../../clusters/migrating_from_gma_to_project_template.md), then
-you can instead use `- path: applications/cert-manager-legacy/helmfile.yaml` to
+If your Kubernetes version is earlier than 1.20 and you are
+[migrating from GitLab Managed Apps to a cluster management project](../../../../clusters/migrating_from_gma_to_project_template.md),
+then you can instead use `- path: applications/cert-manager-legacy/helmfile.yaml` to
take over an existing release of cert-manager v0.10.
cert-manager:
- Is installed by default into the `gitlab-managed-apps` namespace of your cluster.
- Includes a
- [Let's Encrypt
- `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/) enabled by
+ [Let's Encrypt `ClusterIssuer`](https://cert-manager.io/docs/configuration/acme/) enabled by
default. In the `certmanager-issuer` release, the issuer requires a valid email address
for `letsEncryptClusterIssuer.email`. Let's Encrypt uses this email address to
contact you about expiring certificates and issues related to your account.
diff --git a/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
index 383e857bb20..64d325dedc6 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md
@@ -1,27 +1,11 @@
---
-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
+redirect_to: '../../../../../operations/metrics/index.md'
+remove_date: '2022-11-03'
---
-# Install Prometheus with a cluster management project **(FREE)**
+This document was moved to [another location](../../../../../operations/metrics/index.md).
-> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
-
-[Prometheus](https://prometheus.io/docs/introduction/overview/) is an
-open-source monitoring and alerting system for supervising your
-deployed applications.
-
-Assuming you already have a project created from a
-[management project template](../../../../../user/clusters/management_project_template.md), to install Prometheus you should
-uncomment this line from your `helmfile.yaml`:
-
-```yaml
- - path: applications/prometheus/helmfile.yaml
-```
-
-You can customize the installation of Prometheus by updating the
-`applications/prometheus/values.yaml` file in your cluster
-management project. Refer to the
-[Configuration section](https://github.com/helm/charts/tree/master/stable/prometheus#configuration)
-of the Prometheus chart's README for the available configuration options.
+<!-- This redirect file can be deleted after <2022-11-03>. -->
+<!-- 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/infrastructure/clusters/manage/management_project_applications/sentry.md b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
index d2d314b649e..f42e9c83120 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md
@@ -1,70 +1,11 @@
---
-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
+redirect_to: '../../../../../operations/error_tracking.md'
+remove_date: '2022-11-03'
---
-# Install Sentry with a cluster management project **(FREE)**
+This document was moved to [another location](../../../../../operations/error_tracking.md).
-> [Introduced](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/5) in GitLab 14.0.
-
-The Sentry Helm chart [recommends](https://github.com/helm/charts/blob/f6e5784f265dd459c5a77430185d0302ed372665/stable/sentry/values.yaml#L284-L285)
-at least 3 GB of available RAM for database migrations.
-
-Assuming you already have a project created from a
-[management project template](../../../../../user/clusters/management_project_template.md), to install Sentry you should
-uncomment this line from your `helmfile.yaml`:
-
-```yaml
- - path: applications/sentry/helmfile.yaml
-```
-
-Sentry is installed by default into the `gitlab-managed-apps` namespace
-of your cluster.
-
-You can customize the installation of Sentry by defining
-`applications/sentry/values.yaml` file in your cluster
-management project. Refer to the
-[chart](https://github.com/helm/charts/tree/master/stable/sentry)
-for the available configuration options.
-
-We recommend you pay close attention to the following configuration options:
-
-- `email`. Needed to invite users to your Sentry instance and to send error emails.
-- `user`. Where you can set the login credentials for the default administrator user.
-- `postgresql`. For a PostgreSQL password that can be used when running future updates.
-
-When upgrading, it's important to provide the existing PostgreSQL password (given
-using the `postgresql.postgresqlPassword` key) to avoid authentication errors.
-Read the [PostgreSQL chart documentation](https://github.com/helm/charts/tree/master/stable/postgresql#upgrade)
-for more information.
-
-Here is an example configuration for Sentry:
-
-```yaml
-# Admin user to create
-user:
- # Indicated to create the admin user or not,
- # Default is true as the initial installation.
- create: true
- email: "<your email>"
- password: "<your password>"
-
-email:
- from_address: "<your from email>"
- host: smtp
- port: 25
- use_tls: false
- user: "<your email username>"
- password: "<your email password>"
- enable_replies: false
-
-ingress:
- enabled: true
- hostname: "<sentry.example.com>"
-
-# Needs to be here between runs.
-# See https://github.com/helm/charts/tree/master/stable/postgresql#upgrade for more info
-postgresql:
- postgresqlPassword: example-postgresql-password
-```
+<!-- This redirect file can be deleted after <2022-11-03>. -->
+<!-- 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/infrastructure/clusters/manage/management_project_applications/vault.md b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
index 06e67b78c91..31a22a240d9 100644
--- a/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
+++ b/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md
@@ -35,7 +35,7 @@ Vault application causes downtime.
To optimally use Vault in a production environment, it's ideal to have a good understanding
of the internals of Vault and how to configure it. This can be done by reading
-the [Vault Configuration guide](../../../../../ci/secrets/#configure-your-vault-server),
+the [Vault Configuration guide](../../../../../ci/secrets/index.md#configure-your-vault-server),
the [Vault documentation](https://www.vaultproject.io/docs/internals) and
the Vault Helm chart [`values.yaml` file](https://github.com/hashicorp/vault-helm/blob/v0.3.3/values.yaml).
diff --git a/doc/user/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index 24203e8d922..4e78e0bbed5 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -68,17 +68,34 @@ To configure GitLab CI/CD as a backend:
}
```
-1. In the root directory of your project repository, create a `.gitlab-ci.yml` file. Use
- [this file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml)
- to populate it.
-
+1. In the root directory of your project repository, create a `.gitlab-ci.yml` file. Use the
+ [`Terraform.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml)
+ template to populate it.
1. Push your project to GitLab. This action triggers a pipeline, which
runs the `gitlab-terraform init`, `gitlab-terraform validate`, and
`gitlab-terraform plan` commands.
-1. Trigger the manual `terraform apply` job from the previous pipeline to provision the defined infrastructure.
+1. Trigger the manual `deploy` job from the previous pipeline, which runs `gitlab-terraform apply` command, to provision the defined infrastructure.
The output from the above `terraform` commands should be viewable in the job logs.
+The `gitlab-terraform` CLI is a wrapper around the `terraform` CLI. You can [view the source code of `gitlab-terraform`](https://gitlab.com/gitlab-org/terraform-images/-/blob/master/src/bin/gitlab-terraform.sh) if you're interested.
+
+If you prefer to call the `terraform` commands explicitly, you can override
+the template, and instead, use it as reference for what you can achieve.
+
+### Customizing your Terraform environment variables
+
+When you use the `Terraform.gitlab-ci.yml` template, you can use [Terraform HTTP configuration variables](https://www.terraform.io/language/settings/backends/http#configuration-variables) when you define your CI/CD jobs.
+
+To customize your `terraform init` and override the Terraform configuration,
+use environment variables instead of the `terraform init -backend-config=...` approach.
+When you use `-backend-config`, the configuration is:
+
+- Cached in the output of the `terraform plan` command.
+- Usually passed forward to the `terraform apply` command.
+
+This configuration can lead to problems like [being unable to lock Terraform state files in CI jobs](troubleshooting.md#unable-to-lock-terraform-state-files-in-ci-jobs-for-terraform-apply-using-a-plan-created-in-a-previous-job).
+
## Access the state from your local machine
You can access the GitLab-managed Terraform state from your local machine.
@@ -109,66 +126,6 @@ You should use a local terminal to run the commands needed for migrating to GitL
The following example demonstrates how to change the state name. The same workflow is needed to migrate to GitLab-managed Terraform state from a different state storage backend.
-## Use your GitLab backend as a remote data source
-
-You can use a GitLab-managed Terraform state backend as a
-[Terraform data source](https://www.terraform.io/language/state/remote-state-data).
-
-1. In your `main.tf` or other relevant file, declare these variables. Leave the values empty.
-
- ```hcl
- variable "example_remote_state_address" {
- type = string
- description = "Gitlab remote state file address"
- }
-
- variable "example_username" {
- type = string
- description = "Gitlab username to query remote state"
- }
-
- variable "example_access_token" {
- type = string
- description = "GitLab access token to query remote state"
- }
- ```
-
-1. To override the values from the previous step, create a file named `example.auto.tfvars`. This file should **not** be versioned in your project repository.
-
- ```plaintext
- example_remote_state_address = "https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>"
- example_username = "<GitLab username>"
- example_access_token = "<GitLab Personal Access Token>"
- ```
-
-1. In a `.tf` file, define the data source by using [Terraform input variables](https://www.terraform.io/language/values/variables):
-
- ```hcl
- data "terraform_remote_state" "example" {
- backend = "http"
-
- config = {
- address = var.example_remote_state_address
- username = var.example_username
- password = var.example_access_token
- }
- }
- ```
-
- - **address**: The URL of the remote state backend you want to use as a data source.
- For example, `https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>`.
- - **username**: The username to authenticate with the data source. If you are using
- a [Personal Access Token](../../profile/personal_access_tokens.md) for
- authentication, this value is your GitLab username. If you are using GitLab CI/CD, this value is `'gitlab-ci-token'`.
- - **password**: The password to authenticate with the data source. If you are using a Personal Access Token for
- authentication, this value is the token value (the token must have the **API** scope).
- If you are using GitLab CI/CD, this value is the contents of the `${CI_JOB_TOKEN}` CI/CD variable.
-
-Outputs from the data source can now be referenced in your Terraform resources
-using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
-
-To read the Terraform state in the target project, you need at least the Developer role.
-
### Set up the initial backend
```shell
@@ -264,6 +221,66 @@ commands will detect it and remind you to do so if necessary.
If you type `yes`, it copies your state from the old location to the new
location. You can then go back to running it in GitLab CI/CD.
+## Use your GitLab backend as a remote data source
+
+You can use a GitLab-managed Terraform state backend as a
+[Terraform data source](https://www.terraform.io/language/state/remote-state-data).
+
+1. In your `main.tf` or other relevant file, declare these variables. Leave the values empty.
+
+ ```hcl
+ variable "example_remote_state_address" {
+ type = string
+ description = "Gitlab remote state file address"
+ }
+
+ variable "example_username" {
+ type = string
+ description = "Gitlab username to query remote state"
+ }
+
+ variable "example_access_token" {
+ type = string
+ description = "GitLab access token to query remote state"
+ }
+ ```
+
+1. To override the values from the previous step, create a file named `example.auto.tfvars`. This file should **not** be versioned in your project repository.
+
+ ```plaintext
+ example_remote_state_address = "https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>"
+ example_username = "<GitLab username>"
+ example_access_token = "<GitLab Personal Access Token>"
+ ```
+
+1. In a `.tf` file, define the data source by using [Terraform input variables](https://www.terraform.io/language/values/variables):
+
+ ```hcl
+ data "terraform_remote_state" "example" {
+ backend = "http"
+
+ config = {
+ address = var.example_remote_state_address
+ username = var.example_username
+ password = var.example_access_token
+ }
+ }
+ ```
+
+ - **address**: The URL of the remote state backend you want to use as a data source.
+ For example, `https://gitlab.com/api/v4/projects/<TARGET-PROJECT-ID>/terraform/state/<TARGET-STATE-NAME>`.
+ - **username**: The username to authenticate with the data source. If you are using
+ a [Personal Access Token](../../profile/personal_access_tokens.md) for
+ authentication, this value is your GitLab username. If you are using GitLab CI/CD, this value is `'gitlab-ci-token'`.
+ - **password**: The password to authenticate with the data source. If you are using a Personal Access Token for
+ authentication, this value is the token value (the token must have the **API** scope).
+ If you are using GitLab CI/CD, this value is the contents of the `${CI_JOB_TOKEN}` CI/CD variable.
+
+Outputs from the data source can now be referenced in your Terraform resources
+using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`.
+
+To read the Terraform state in the target project, you need at least the Developer role.
+
## Manage Terraform state files
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273592) in GitLab 13.8.
diff --git a/doc/user/infrastructure/iac/troubleshooting.md b/doc/user/infrastructure/iac/troubleshooting.md
index 5817337223f..e187fe54136 100644
--- a/doc/user/infrastructure/iac/troubleshooting.md
+++ b/doc/user/infrastructure/iac/troubleshooting.md
@@ -97,6 +97,8 @@ As a result, to create a plan and later use the same plan in another CI job, you
`Error: Error acquiring the state lock` errors when using `-backend-config=password=$CI_JOB_TOKEN`.
This happens because the value of `$CI_JOB_TOKEN` is only valid for the duration of the current job.
+Another possible error message for the same problem could be: `Error: Error loading state: HTTP remote state endpoint requires auth`.
+
As a workaround, use [http backend configuration variables](https://www.terraform.io/docs/language/settings/backends/http.html#configuration-variables) in your CI job,
which is what happens behind the scenes when following the
[Get started using GitLab CI](terraform_state.md#initialize-a-terraform-state-as-a-backend-by-using-gitlab-cicd) instructions.
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index b1e6fcb2f4e..6a524fe206a 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -190,8 +190,8 @@ end
#### PlantUML
-To make PlantUML available in GitLab, a GitLab administrator must enable it. For more information, see the
-[PlantUML & GitLab](../administration/integration/plantuml.md) page.
+PlantUML integration is enabled on GitLab.com. To make PlantUML available in self-managed
+installation of GitLab, a GitLab administrator [must enable it](../administration/integration/plantuml.md).
#### Kroki
@@ -376,6 +376,8 @@ the [Asciidoctor user manual](https://asciidoctor.org/docs/user-manual/#activati
### Task lists
+> Inapplicable checkboxes [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85982) in GitLab 15.3.
+
[View this topic in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#task-lists).
You can add task lists anywhere Markdown is supported.
@@ -384,22 +386,28 @@ You can add task lists anywhere Markdown is supported.
- In all other places, you cannot select the boxes. You must edit the Markdown manually
by adding or removing an `x` in the brackets.
+Besides complete and incomplete, tasks can also be **inapplicable**. Selecting an inapplicable checkbox
+in an issue, merge request, or comment has no effect.
+
To create a task list, follow the format of an ordered or unordered list:
```markdown
- [x] Completed task
+- [~] Inapplicable task
- [ ] Incomplete task
- - [ ] Sub-task 1
- - [x] Sub-task 2
+ - [x] Sub-task 1
+ - [~] Sub-task 2
- [ ] Sub-task 3
1. [x] Completed task
+1. [~] Inapplicable task
1. [ ] Incomplete task
- 1. [ ] Sub-task 1
- 1. [x] Sub-task 2
+ 1. [x] Sub-task 1
+ 1. [~] Sub-task 2
+ 1. [ ] Sub-task 3
```
-![Task list as rendered by GitLab](img/completed_tasks_v13_3.png)
+![Task list as rendered by GitLab](img/completed_tasks_v15_3.png)
### Table of contents
@@ -1398,6 +1406,42 @@ For example:
1. Another item
+---
+
+Ordered lists that are the first sub-item of an unordered list item must have a preceding blank line if they don't start with `1.`.
+
+**Good**
+
+```markdown
+- Unordered list item
+
+ 5. First ordered list item
+```
+
+**Bad**
+
+```markdown
+- Unordered list item
+ 5. First ordered list item
+```
+
+---
+
+CommonMark ignores blank lines between ordered and unordered list items, and considers them part of a single list. These are rendered as a
+_[loose](https://spec.commonmark.org/0.30/#loose)_ list. Each list item is enclosed in a paragraph tag and, therefore, has paragraph spacing and margins.
+This makes the list look like there is extra spacing between each item.
+
+For example:
+
+```markdown
+- First list item
+- Second list item
+
+- A different list
+```
+
+CommonMark ignores the blank line and renders this as one list with paragraph spacing.
+
### Superscripts / Subscripts
CommonMark and GitLab Flavored Markdown don't support the Redcarpet superscript syntax ( `x^2` ).
diff --git a/doc/user/namespace/index.md b/doc/user/namespace/index.md
new file mode 100644
index 00000000000..9ffc65a4e8e
--- /dev/null
+++ b/doc/user/namespace/index.md
@@ -0,0 +1,21 @@
+---
+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
+---
+
+# Namespaces
+
+In GitLab, a *namespace* organizes related projects together.
+GitLab has two types of namespaces:
+
+- A *personal* namespace, which is based on your username. Projects under a personal namespace must be configured one at a time.
+- A *group* or *subgroup* namespace. In these namespaces, you can manage multiple projects at once.
+
+To determine whether you're viewing a group or personal namespace, you can view the URL. For example:
+
+| Namespace for | URL | Namespace |
+| ------------- | --- | --------- |
+| A user named `alex`. | `https://gitlab.example.com/alex` | `alex` |
+| A group named `alex-team`. | `https://gitlab.example.com/alex-team` | `alex-team` |
+| A group named `alex-team` with a subgroup named `marketing`. | `https://gitlab.example.com/alex-team/marketing` | `alex-team/marketing` |
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 901fb740717..4fc55d18253 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -44,7 +44,7 @@ a group's namespace, rather than a user's namespace. Composer packages
1. Run [`composer init`](https://getcomposer.org/doc/03-cli.md#init) and answer the prompts.
- For namespace, enter your unique [namespace](../../../user/group/index.md#namespaces), like your GitLab username or group name.
+ For namespace, enter your unique [namespace](../../../user/namespace/index.md), like your GitLab username or group name.
A file called `composer.json` is created:
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index d0c771ecc41..a203de2ed2c 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -555,6 +555,12 @@ this setting. However, disabling the Container Registry disables all Container R
## Troubleshooting the GitLab Container Registry
+## Migrating OCI container images to GitLab Container Registry
+
+Migrating built container images to the GitLab registry is not a current feature. However, an [epic](https://gitlab.com/groups/gitlab-org/-/epics/5210) is open to track the work on this feature.
+
+Some third-party tools can help migrate container images, for example, [skopeo](https://github.com/containers/skopeo), which can [copy container images](https://github.com/containers/skopeo#copying-images) between various storage mechanisms. You can use skopeo to copy from container registries, container storage backends, local directories, and local OCI-layout directories to the GitLab Container Registry.
+
### Docker connection error
A Docker connection error can occur when there are special characters in either the group,
@@ -563,7 +569,7 @@ project or branch name. Special characters can include:
- Leading underscore
- Trailing hyphen/dash
-To get around this, you can [change the group path](../../group/index.md#change-a-groups-path),
+To get around this, you can [change the group path](../../group/manage.md#change-a-groups-path),
[change the project path](../../project/settings/index.md#rename-a-repository) or change the branch
name.
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 3e41a260854..788e57b6410 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -16,9 +16,26 @@ 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,
-which doesn't include the Container Registry. To track work on this, see the epic
-[Storage management for the Container Registry](https://gitlab.com/groups/gitlab-org/-/epics/7226).
+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.
+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).
+
+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.
+
+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.
+
+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
+corresponding [image manifest](https://github.com/opencontainers/image-spec/blob/main/manifest.md#example-image-manifest).
## Cleanup policy
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index 4770057e4ea..ea9435de12a 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -316,6 +316,28 @@ services:
alias: docker
```
+### Issues when authenticating to the Dependency Proxy from CI/CD jobs
+
+GitLab Runner will automatically authenticate to the Dependency Proxy. However, the underlying Docker engine is still subject to its [authorization resolving process](https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/docs/configuration/advanced-configuration.md#precedence-of-docker-authorization-resolving).
+
+Misconfigurations in the authentication mechanism may cause `HTTP Basic: Access denied` and `403: Access forbidden` errors.
+
+You can use the job logs to view the authentication mechanism used to authenticate against the Dependency Proxy:
+
+```plaintext
+Authenticating with credentials from $DOCKER_AUTH_CONFIG
+```
+
+```plaintext
+Authenticating with credentials from /root/.docker/config.json
+```
+
+```plaintext
+Authenticating with credentials from job payload (GitLab Registry)
+```
+
+Make sure you are using the expected authentication mechanism.
+
### "Not Found" error when pulling image
Docker errors similar to the following may indicate that the user running the build job doesn't have
diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md
index 8d5fc73ad4e..d4acb14b9ca 100644
--- a/doc/user/packages/generic_packages/index.md
+++ b/doc/user/packages/generic_packages/index.md
@@ -73,6 +73,7 @@ Example request with attribute `select = package_file`:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" \
+ --user "<username>:<Project Access Token>" \
--upload-file path/to/file.txt \
"https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt?select=package_file"
```
diff --git a/doc/user/packages/helm_repository/index.md b/doc/user/packages/helm_repository/index.md
index 07e853fa18c..f64a269938f 100644
--- a/doc/user/packages/helm_repository/index.md
+++ b/doc/user/packages/helm_repository/index.md
@@ -71,7 +71,7 @@ Once built, a chart can be uploaded to the desired channel with `curl` or `helm
### Release channels
-You can publish Helm charts to channels in GitLab. Channels are a method you can use to differentiate Helm chart repositories.
+You can publish Helm charts to channels in GitLab. Channels are a method you can use to differentiate Helm chart repositories.
For example, you can use `stable` and `devel` as channels to allow users to add the `stable` repo while `devel` charts are isolated.
## Use CI/CD to publish a Helm package
@@ -129,7 +129,7 @@ See [Using Helm](https://helm.sh/docs/intro/using_helm/) for more information.
### The chart is not visible in the Package Registry after uploading
-Check the [Sidekiq log](../../../administration/logs.md#sidekiqlog)
+Check the [Sidekiq log](../../../administration/logs/index.md#sidekiqlog)
for any related errors. If you see `Validation failed: Version is invalid`, it means that the
version in your `Chart.yaml` file does not follow [Helm Chart versioning specifications](https://helm.sh/docs/topics/charts/#charts-and-versioning).
To fix the error, use the correct version syntax and upload the chart again.
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 7ea3c1aa0c8..28de06b2d8a 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -585,7 +585,7 @@ NPM_TOKEN=<your_token> npm install
If you get this error, ensure that:
- The Package Registry is enabled in your project settings. Although the Package Registry is enabled
- by default, it's possible to [disable it](../package_registry/#disable-the-package-registry).
+ by default, it's possible to [disable it](../package_registry/index.md#disable-the-package-registry).
- Your token is not expired and has appropriate permissions.
- A package with the same name or version doesn't already exist within the given scope.
- The scoped packages URL includes a trailing slash:
@@ -634,7 +634,7 @@ This might be accompanied by another error:
This is usually a permissions issue with either:
- `'packages_storage_path'` default `/var/opt/gitlab/gitlab-rails/shared/packages/`.
-- The remote bucket if [object storage](../../../administration/packages/#using-object-storage)
+- The remote bucket if [object storage](../../../administration/packages/index.md#using-object-storage)
is used.
In the latter case, ensure the bucket exists and GitLab has write access to it.
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index d68c7218ca5..7748780d0e4 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -60,11 +60,8 @@ For most package types, the following credential types are valid:
allows access to packages in the project running the job for the users running the pipeline.
Access to other external projects can be configured.
- NOTE:
- There's an open issue,
- [GitLab-#333444](https://gitlab.com/gitlab-org/gitlab/-/issues/333444),
- which prevents you from using a job token with internal projects. This bug only impacts self-managed
- GitLab instances.
+NOTE:
+If you have not activated the "Packages" feature for your project at **Settings > General > Project features**, you will receive a 403 Forbidden response.
## Use GitLab CI/CD to build packages
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 4a03bd9e8a0..cd7dd062f60 100644
--- a/doc/user/packages/package_registry/reduce_package_registry_storage.md
+++ b/doc/user/packages/package_registry/reduce_package_registry_storage.md
@@ -53,7 +53,7 @@ The package files are permanently deleted.
## Cleanup policy
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346153) in GitLab 15.2.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346153) in GitLab 15.2.
Depending on the number of packages to remove, the process of manually deleting the packages can take a long time to finish.
A cleanup policy defines a set of rules that, applied to a project, defines which package files you can automatically delete.
diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md
index 2668b8b35ac..436c55f9ee0 100644
--- a/doc/user/packages/terraform_module_registry/index.md
+++ b/doc/user/packages/terraform_module_registry/index.md
@@ -101,7 +101,7 @@ module "<module>" {
}
```
-Where `<namespace>` is the [namespace](../../../user/group/index.md#namespaces) of the Terraform module registry.
+Where `<namespace>` is the [namespace](../../../user/namespace/index.md) of the Terraform module registry.
## Publish a Terraform module by using CI/CD
@@ -125,7 +125,7 @@ upload:
script:
- TERRAFORM_MODULE_NAME=$(echo "${TERRAFORM_MODULE_NAME}" | tr " _" -) # module-name must not have spaces or underscores, so translate them to hyphens
- tar -vczf ${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz -C ${TERRAFORM_MODULE_DIR} --exclude=./.git .
- - 'curl --location --header "JOB-TOKEN: ${CI_JOB_TOKEN}"
+ - 'curl --location --header "JOB-TOKEN: ${CI_JOB_TOKEN}"
--upload-file ${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz
${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/terraform/modules/${TERRAFORM_MODULE_NAME}/${TERRAFORM_MODULE_SYSTEM}/${TERRAFORM_MODULE_VERSION}/file'
rules:
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index b01bfbef3aa..c89dd3f65f7 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -39,10 +39,10 @@ usernames. A GitLab administrator can configure the GitLab instance to
A user's role determines what permissions they have on a project. The Owner role provides all permissions but is
available only:
-- For group owners. The role is inherited for a group's projects.
+- For group and project Owners. In GitLab 14.8 and earlier, the role is inherited for a group's projects.
- For Administrators.
-Personal [namespace](group/index.md#namespaces) owners:
+Personal [namespace](namespace/index.md) owners:
- Are displayed as having the Maintainer role on projects in the namespace, but have the same permissions as a user with the Owner role.
- In GitLab 14.9 and later, for new projects in the namespace, are displayed as having the Owner role.
@@ -95,6 +95,7 @@ The following table lists project permissions available for each role:
| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>View [related issues](project/issues/related_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Set [weight](project/issues/issue_weight.md) | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues]](project/issues/index.md):<br>Set [parent epic](group/epics/manage_epics.md#add-an-existing-issue-to-an-epic) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Close / reopen (*19*) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
@@ -214,18 +215,18 @@ The following table lists project permissions available for each role:
[GitLab.com visibility settings](gitlab_com/index.md#visibility-settings).
2. Guest users can only view the [confidential issues](project/issues/confidential_issues.md) they created themselves or are assigned to.
3. Not allowed for Guest, Reporter, Developer, Maintainer, or Owner. See [protected branches](project/protected_branches.md).
-4. If the [branch is protected](project/protected_branches.md), this depends on the access Developers and Maintainers are given.
+4. If the [branch is protected](project/protected_branches.md), this depends on the access given to Developers and Maintainers.
5. Guest users can access GitLab [**Releases**](project/releases/index.md) for downloading assets but are not allowed to download the source code nor see [repository information like commits and release evidence](project/releases/index.md#view-a-release-and-download-assets).
6. Actions are limited only to records owned (referenced) by user.
-7. When [Share Group Lock](group/index.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
+7. When [Share Group Lock](group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups) is enabled the project can't be shared with other groups. It does not affect group with group sharing.
8. For information on eligible approvers for merge requests, see
[Eligible approvers](project/merge_requests/approvals/rules.md#eligible-approvers).
9. Applies only to comments on [Design Management](project/issues/design_management.md) designs.
10. Users can only view events based on their individual actions.
11. Project access tokens are supported for self-managed instances on Free and above. They are also
supported on GitLab SaaS Premium and above (excluding [trial licenses](https://about.gitlab.com/free-trial/)).
-12. If the [tag is protected](#release-permissions-with-protected-tags), this depends on the access Developers and Maintainers are given.
-13. A Maintainer can't change project features visibility level if
+12. If the [tag is protected](#release-permissions-with-protected-tags), this depends on the access given to Developers and Maintainers.
+13. A Maintainer or Owner can't change project features visibility level if
[project visibility](public_access.md) is set to private.
14. Attached design files are moved together with the issue even if the user doesn't have the
Developer role.
@@ -333,10 +334,9 @@ which visibility level you select on project settings.
### Protected branches
Additional restrictions can be applied on a per-branch basis with [protected branches](project/protected_branches.md).
-Additionally, you can customize permissions to allow or prevent project
-Maintainers and Developers from pushing to a protected branch. Read through the documentation on
-[protected branches](project/protected_branches.md)
-to learn more.
+Additionally, you can customize permissions to allow or prevent project Developers or Maintainers
+from pushing to a protected branch. Read through the documentation on
+[protected branches](project/protected_branches.md) to learn more.
### Value stream analytics permissions
@@ -412,7 +412,7 @@ The following table lists group permissions available for each role:
| Delete [group wiki](project/wiki/group.md) pages | | | ✓ | ✓ | ✓ |
| Edit [epic](group/epics/index.md) comments (posted by any user) | | | | ✓ (2) | ✓ (2) |
| List group deploy tokens | | | | ✓ | ✓ |
-| Manage [group push rules](group/index.md#group-push-rules) | | | | ✓ | ✓ |
+| Manage [group push rules](group/access_and_permissions.md#group-push-rules) | | | | ✓ | ✓ |
| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
| Create and manage compliance frameworks | | | | | ✓ |
| Create/Delete group deploy tokens | | | | | ✓ |
@@ -439,9 +439,9 @@ The following table lists group permissions available for each role:
2. Introduced in GitLab 12.2.
3. Default project creation role can be changed at:
- The [instance level](admin_area/settings/visibility_and_access_controls.md#define-which-roles-can-create-projects).
- - The [group level](group/index.md#specify-who-can-add-projects-to-a-group).
+ - The [group level](group/manage.md#specify-who-can-add-projects-to-a-group).
4. Does not apply to subgroups.
-5. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#change-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected".
+5. 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".
6. In addition, if your group is public or internal, all users who can see the group can also see group wiki pages.
7. Users can only view events based on their individual actions.
@@ -600,7 +600,7 @@ for more information.
## LDAP users permissions
LDAP user permissions can be manually overridden by an administrator.
-Read through the documentation on [LDAP users permissions](group/index.md#manage-group-memberships-via-ldap) to learn more.
+Read through the documentation on [LDAP users permissions](group/access_and_permissions.md#manage-group-memberships-via-ldap) to learn more.
## Project aliases
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 3f5554b80ac..5ec29814e06 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -78,7 +78,7 @@ in users not being deleted, and the following error generated:
ERROR: null value in column "user_id" violates not-null constraint
```
-The error can be found in the [PostgreSQL log](../../../administration/logs.md#postgresql-logs) and
+The error can be found in the [PostgreSQL log](../../../administration/logs/index.md#postgresql-logs) and
in the **Retries** section of the [background jobs view](../../admin_area/index.md#background-jobs) in the Admin Area.
If the user being deleted used the [iterations](../../group/iterations/index.md) feature, such
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 4563cfe5648..3af033c7130 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -59,15 +59,12 @@ To enable 2FA with a one-time password:
1. Select **Enable Two-factor Authentication**.
1. **On your device (usually your phone):**
1. Install a compatible application. For example:
- - [Aegis](https://getaegis.app/)
- - [Raivo OTP](https://apps.apple.com/us/app/raivo-otp/id1459042137#platform=iphone)
- - [Authy](https://authy.com/)
- - [Duo Mobile](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app)
- - [LastPass Authenticator](https://lastpass.com/auth/)
- - [Authenticator](https://mattrubin.me/authenticator/)
- - [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en)
- - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app)
- - [SailOTP](https://openrepos.net/content/seiichiro0185/sailotp)
+ - Cloud-based (recommended because you can restore access if you lose the hardware device):
+ - [Authy](https://authy.com/)
+ - [Duo Mobile](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app)
+ - Other:
+ - [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en)
+ - [Microsoft Authenticator](https://www.microsoft.com/en-us/security/mobile-authenticator-app)
1. In the application, add a new entry in one of two ways:
- Scan the code displayed by GitLab with your device's camera to add the entry automatically.
- Enter the details provided to add the entry manually.
@@ -358,8 +355,7 @@ After you use a recovery code, you cannot re-use it. You can still use the other
### Generate new recovery codes using SSH
-Users often forget to save their recovery codes when enabling 2FA. If you added an SSH key to your
-GitLab account, you can generate a new set of recovery codes with SSH:
+If you forget to save your recovery codes when enabling 2FA, and you added an SSH key to your GitLab account, you can generate a new set of recovery codes with SSH:
1. In a terminal, run:
@@ -403,10 +399,9 @@ After signing in, immediately set up 2FA with a new device.
### Have two-factor authentication disabled on your account **(PREMIUM SAAS)**
-If other methods are unavailable, submit a [support ticket](https://support.gitlab.com/hc/en-us/requests/new) to request
+If other methods are unavailable, have a GitLab support contact submit a [support ticket](https://support.gitlab.com) to request
a GitLab global administrator disable 2FA for your account:
-- Only the owner of the account can make this request.
- This service is only available for accounts that have a GitLab.com subscription. For more information, see our
[blog post](https://about.gitlab.com/blog/2020/08/04/gitlab-support-no-longer-processing-mfa-resets-for-free-users/).
- Disabling this setting temporarily leaves your account in a less secure state. You should sign in and re-enable two-factor
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index bf696310158..4c859d98004 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -36,11 +36,11 @@ To change your 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.
+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](../group/index.md#namespaces),
+Your username has a unique [namespace](../namespace/index.md),
which is updated when you change your username. Before you change your username, read about
[how redirects behave](../project/repository/index.md#what-happens-when-a-repository-path-changes).
If you do not want to update the namespace, you can create a new user or group and transfer projects to it instead.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 3eda363d108..0245f0615e0 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -7,9 +7,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Notification emails **(FREE)**
-> Enhanced email styling [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78604) in GitLab 14.9 [with a feature flag](../../administration/feature_flags.md) named `enhanced_notify_css`. Disabled by default.
-> Enhanced email styling [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/355907) in GitLab 14.9.
-> Enhanced email styling [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/355907) in GitLab 15.0.
+> - Enhanced email styling [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78604) in GitLab 14.9 [with a feature flag](../../administration/feature_flags.md) named `enhanced_notify_css`. Disabled by default.
+> - Enhanced email styling [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/355907) in GitLab 14.9.
+> - Enhanced email styling [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/355907) in GitLab 15.0.
Stay informed about what's happening in GitLab with email notifications.
You can receive updates about activity in issues, merge requests, epics, and designs.
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index a76517a7341..f8494116655 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -38,9 +38,9 @@ want to make sure the performance stays the same, or improves. Developers need
to be careful when using canaries with user-facing changes, because by default,
requests from the same user are randomly distributed between canary and
non-canary pods, which could result in confusion or even errors. If needed, you
-may want to consider [setting `service.spec.sessionAffinity` to `ClientIP` in
-your Kubernetes service definitions](https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies), but that is beyond the scope of
-this document.
+may want to consider
+[setting `service.spec.sessionAffinity` to `ClientIP` in your Kubernetes service definitions](https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies),
+but that is beyond the scope of this document.
## Advanced traffic control with Canary Ingress
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index 2e1c8766ae3..bfaf9aab7b7 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -37,7 +37,7 @@ Prerequisites:
set up with access.
- Kubernetes Engine API and related services enabled. It should work immediately but may
take up to 10 minutes after you create a project. For more information see the
- ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin).
+ ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/deploy-app-cluster#before-you-begin).
Note the following:
@@ -51,8 +51,8 @@ Note the following:
cluster's pod address IP range is set to `/16` instead of the regular `/14`. `/16` is a CIDR
notation.
- GitLab requires basic authentication enabled and a client certificate issued for the cluster to
- set up an [initial service account](cluster_access.md). In [GitLab versions
- 11.10 and later](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58208), the cluster creation process
+ set up an [initial service account](cluster_access.md). In
+ [GitLab versions 11.10 and later](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58208), the cluster creation process
explicitly requests GKE to create clusters with basic authentication enabled and a client
certificate.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 95d8064b380..f1004a40a13 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -46,3 +46,27 @@ To remove the Kubernetes cluster integration:
1. Go to your cluster details page.
1. Select the **Advanced Settings** tab.
1. Select either **Remove integration** or **Remove integration and resources**.
+
+### Remove clusters by using the Rails console **(FREE SELF)**
+
+[Start a Rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session).
+
+To find a cluster:
+
+``` ruby
+cluster = Clusters::Cluster.find(1)
+cluster = Clusters::Cluster.find_by(name: 'cluster_name')
+```
+
+To delete a cluster but not the associated resources:
+
+```ruby
+# Find users who have administrator access
+user = User.find_by(username: 'admin_user')
+
+# Find the cluster with the ID
+cluster = Clusters::Cluster.find(1)
+
+# Delete the cluster
+Clusters::DestroyService.new(user).execute(cluster)
+```
diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md
index fc41533b17c..0a574b9afe2 100644
--- a/doc/user/project/clusters/deploy_to_cluster.md
+++ b/doc/user/project/clusters/deploy_to_cluster.md
@@ -131,7 +131,7 @@ However, sometimes GitLab cannot create them. In such instances, your job can fa
This job failed because the necessary resources were not successfully created.
```
-To find the cause of this error when creating a namespace and service account, check the [logs](../../../administration/logs.md#kuberneteslog).
+To find the cause of this error when creating a namespace and service account, check the [logs](../../../administration/logs/index.md#kuberneteslog).
Reasons for failure include:
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index adea5dad7b8..fd2df96308c 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -8,21 +8,37 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> Moved to GitLab Premium in 13.9.
-Code Owners define who owns specific files or directories in a repository.
+Code Owners define who develops and maintains a feature, and own the resulting
+files or directories in a repository.
- The users you define as Code Owners are displayed in the UI when you browse directories.
- You can set your merge requests so they must be approved by Code Owners before merge.
- You can protect a branch and allow only Code Owners to approve changes to the branch.
-If you don't want to use Code Owners for approvals, you can
-[configure rules](merge_requests/approvals/rules.md) instead.
+Use Code Owners and approvers together with
+[approval rules](merge_requests/approvals/rules.md) to build a flexible approval
+workflow:
-## Set up Code Owners
+- Use **Code Owners** to define the users who have domain expertise for specific paths in your repository.
+- Use **Approvers** and **Approval rules** to define domains of expertise (such as a security team)
+ that are not scoped to specific file paths in your repository.
+ - **Approvers** define the users.
+ - **Approval rules** define when these users can approve work, and whether or not their approval is required.
+
+For example:
+
+| Type | Name | Scope | Comment |
+|------|------|--------|------------|
+| Approval rule | UX | All files | A user experience (UX) team member reviews the user experience of all changes made in your project. |
+| Approval rule | Security | All files | A security team member reviews all changes for vulnerabilities. |
+| Code Owner approval rule | Frontend: Code Style | `*.css` files | A frontend engineer reviews CSS file changes for adherence to project style standards. |
+| Code Owner approval rule | Backend: Code Review | `*.rb` files | A backend engineer reviews the logic and code style of Ruby files. |
-You can use Code Owners to specify users or [shared groups](members/share_project_with_groups.md)
-that are responsible for specific files and directories in a repository.
+## Set up Code Owners
-To set up Code Owners:
+Create a `CODEOWNERS` file to specify users or [shared groups](members/share_project_with_groups.md)
+that are responsible for specific files and directories in a repository. Each repository
+can have a single `CODEOWNERS` file. To create it:
1. Choose the location where you want to specify Code Owners:
- In the root directory of the repository
@@ -59,24 +75,38 @@ Next steps:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab 12.1.
> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in GitLab 13.0.
-You can use members of groups and subgroups as Code Owners for a project.
+You can use members of groups and subgroups as Code Owners for projects:
-For example, if you have these groups:
+```mermaid
+graph TD
+ A[Parent group X] -->|owns| B[Project A]
+ A -->|contains| C[Subgroup Y]
+ C -->|owns| D[Project B]
+ A-. inherits ownership .-> D
+```
-- **Group X** (`group-x`) with **Project A** in it.
-- **Subgroup Y** (`group-x/subgroup-y`), which belongs to **Group X**, with **Project B** in it.
+In this example:
-The eligible Code Owners:
+- **Parent group X** (`group-x`) owns **Project A**.
+- **Parent group X** also contains a subgroup, **Subgroup Y**. (`group-x/subgroup-y`)
+- **Subgroup Y** owns **Project B**.
-- For **Project A** are the members of **Group X** only, because **Project A** doesn't belong to **Subgroup Y**.
-- For **Project B** are the members of both **Group X** and **Subgroup Y**.
+The eligible Code Owners are:
-![Eligible Code Owners](img/code_owners_members_v13_4.png)
+- **Project A**: the members of **Group X** only, because **Project A** doesn't belong to **Subgroup Y**.
+- **Project B**: the members of both **Group X** and **Subgroup Y**.
You can [invite](members/share_project_with_groups.md) **Subgroup Y** to **Project A**
so that their members also become eligible Code Owners.
-![Invite subgroup members to become eligible Code Owners](img/code_owners_invite_members_v13_4.png)
+```mermaid
+graph LR
+ A[Parent group X] -->|owns| B[Project A]
+ A -->|also contains| C[Subgroup Y]
+ C -.->D{Invite Subgroup Y<br/>to Project A?} -.->|yes| F[Approvals can be<br/> required] -.-> B
+ D{Invite Subgroup Y<br/>to Project A?} -.->|no| I[Subgroup Y cannot be<br /> an approver] -.-> B
+ C -.->E{Add Subgroup Y<br/>as Code Owners<br/>to Project A?} -.->|yes| H[Approvals can only<br/>be optional] -.-> B
+```
If you do not invite **Subgroup Y** to **Project A**, but make them Code Owners, their approval
of the merge request becomes optional.
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index a90ffbe5796..41afbdada6b 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -116,8 +116,8 @@ To display the deploy boards for a specific [environment](../../ci/environments/
Kubernetes.
NOTE:
- Matching based on the Kubernetes `app` label was removed in [GitLab
- 12.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14020).
+ 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
re-deploy your application. If you are using Auto DevOps, this will
be done automatically and no action is necessary.
diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md
index c64afd95d8d..a9f19d27416 100644
--- a/doc/user/project/deploy_keys/index.md
+++ b/doc/user/project/deploy_keys/index.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Use deploy keys to access repositories that are hosted in GitLab. In most cases, you use deploy keys
to access a repository from an external host, like a build server or Continuous Integration (CI) server.
-Depending on your needs, you might want to use a [deploy token](../deploy_tokens/) to access a repository instead.
+Depending on your needs, you might want to use a [deploy token](../deploy_tokens/index.md) to access a repository instead.
| Attribute | Deploy key | Deploy token |
|------------------|-------------|--------------|
@@ -146,8 +146,8 @@ What happens to the deploy key when it is disabled depends on the following:
### Deploy key cannot push to a protected branch
-There are a few scenarios where a deploy key will fail to push to a [protected
-branch](../protected_branches.md).
+There are a few scenarios where a deploy key will fail to push to a
+[protected branch](../protected_branches.md).
- The owner associated to a deploy key does not have access to the protected branch.
- The owner associated to a deploy key does not have [membership](../members/index.md) to the project of the protected branch.
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 42287ff84ce..5df3a973cca 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -112,7 +112,7 @@ To re-use templates [you've created](../project/description_templates.md#create-
![Group template settings](../group/img/group_file_template_settings.png)
You might also be interested in templates for various
-[file types in groups](../group/index.md#group-file-templates).
+[file types in groups](../group/manage.md#group-file-templates).
### Set a default template for merge requests and issues
diff --git a/doc/user/project/git_attributes.md b/doc/user/project/git_attributes.md
index 11d1db195e1..90f64b7262c 100644
--- a/doc/user/project/git_attributes.md
+++ b/doc/user/project/git_attributes.md
@@ -23,5 +23,5 @@ ignored.
## Syntax Highlighting
The `.gitattributes` file can be used to define which language to use when
-syntax highlighting files and diffs. See ["Syntax
-Highlighting"](highlighting.md) for more information.
+syntax highlighting files and diffs. See
+["Syntax Highlighting"](highlighting.md) for more information.
diff --git a/doc/user/project/img/code_owners_invite_members_v13_4.png b/doc/user/project/img/code_owners_invite_members_v13_4.png
deleted file mode 100644
index 852a5f68b36..00000000000
--- a/doc/user/project/img/code_owners_invite_members_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/code_owners_members_v13_4.png b/doc/user/project/img/code_owners_members_v13_4.png
deleted file mode 100644
index e37fe72cd6e..00000000000
--- a/doc/user/project/img/code_owners_members_v13_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
index 867477c83b2..d9ad0c57d79 100644
--- a/doc/user/project/import/clearcase.md
+++ b/doc/user/project/import/clearcase.md
@@ -11,8 +11,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
tools developed by IBM which also include a centralized version control system
similar to Git.
-A good read of ClearCase's basic concepts is can be found in this [StackOverflow
-post](https://stackoverflow.com/a/645771/974710).
+A good read of ClearCase's basic concepts is can be found in this
+[StackOverflow post](https://stackoverflow.com/a/645771/974710).
The following table illustrates the main differences between ClearCase and Git:
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index a190edb179d..a3dfa3edff0 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -241,3 +241,35 @@ Feature.disable(:github_importer_lower_per_page_limit, group)
For information on automating user, group, and project import API calls, see
[Automate group and project import](index.md#automate-group-and-project-import).
+
+## Troubleshooting
+
+### Manually continue a previously failed import process
+
+In some cases, the GitHub import process can fail to import the repository. This causes GitLab to abort the project import process and requires the
+repository to be imported manually. Administrators can manually import the repository for a failed import process:
+
+1. Open a Rails console.
+1. Run the following series of commands in the console:
+
+ ```ruby
+ project_id = <PROJECT_ID>
+ github_access_token = <GITHUB_ACCESS_TOKEN>
+ github_repository_path = '<GROUP>/<REPOSITORY>'
+
+ github_repository_url = "https://#{github_access_token}@github.com/#{github_repository_path}.git"
+
+ # Find project by ID
+ project = Project.find(project_id)
+ # Set import URL and credentials
+ project.import_url = github_repository_url
+ project.import_type = 'github'
+ project.import_source = github_repository_path
+ project.save!
+ # Create an import state if the project was created manually and not from a failed import
+ project.create_import_state if project.import_state.blank?
+ # Set state to start
+ project.import_state.force_start
+ # Trigger import from second step
+ Gitlab::GithubImport::Stage::ImportRepositoryWorker.perform_async(project.id)
+ ```
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 0609b843e86..53547e69e00 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -68,12 +68,14 @@ bugsCharts:
description: "Open bugs created per month"
type: bar
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- group_by: month
- period_limit: 24
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
```
Each chart definition is made up of a hash composed of key-value pairs.
@@ -85,12 +87,14 @@ For example, here's single chart definition:
description: "Open bugs created per month"
type: bar
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- group_by: month
- period_limit: 24
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
```
## Configuration parameters
@@ -104,7 +108,7 @@ The following table lists available parameters for charts:
| [`title`](#title) | The title of the chart. This displays on the Insights page. |
| [`description`](#description) | A description for the individual chart. This displays above the relevant chart. |
| [`type`](#type) | The type of chart: `bar`, `line` or `stacked-bar`. |
-| [`query`](#query) | A hash that defines the conditions for issues / merge requests to be part of the chart. |
+| [`query`](#query) | A hash that defines the data source and filtering conditions for the chart. |
## Parameter details
@@ -153,10 +157,12 @@ Supported values are:
| `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 only supports the `bar` chart type.
+
### `query`
-`query` allows to define the conditions for issues / merge requests to be part
-of the chart.
+`query` allows to define the data source and various filtering conditions for the chart.
Example:
@@ -166,6 +172,29 @@ monthlyBugsCreated:
description: "Open bugs created per month"
type: bar
query:
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
+ group_by: week
+ period_limit: 104
+```
+
+The legacy format without the `data_source` parameter is still supported:
+
+```yaml
+monthlyBugsCreated:
+ title: "Monthly bugs created"
+ description: "Open bugs created per month"
+ type: bar
+ query:
issuable_type: issue
issuable_state: opened
filter_labels:
@@ -179,7 +208,20 @@ monthlyBugsCreated:
period_limit: 104
```
-#### `query.issuable_type`
+#### `query.data_source`
+
+> [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.
+
+Supported values are:
+
+- `issuables`: Exposes merge request or issue data.
+- `dora`: Exposes DORA metrics data.
+
+#### `Issuable` query parameters
+
+##### `query.params.issuable_type`
Defines the type of "issuable" you want to create a chart for.
@@ -188,7 +230,7 @@ Supported values are:
- `issue`: The chart displays issues' data.
- `merge_request`: The chart displays merge requests' data.
-#### `query.issuable_state`
+##### `query.params.issuable_state`
Filter by the current state of the queried "issuable".
@@ -202,7 +244,7 @@ Supported values are:
- `merged`: Merged merge requests.
- `all`: Issues / merge requests in all states
-#### `query.filter_labels`
+##### `query.params.filter_labels`
Filter by labels currently applied to the queried "issuable".
@@ -216,14 +258,16 @@ monthlyBugsCreated:
title: "Monthly regressions created"
type: bar
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- - regression
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ - regression
```
-#### `query.collection_labels`
+##### `query.params.collection_labels`
Group "issuable" by the configured labels.
@@ -237,18 +281,20 @@ weeklyBugsBySeverity:
title: "Weekly bugs by severity"
type: stacked-bar
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- collection_labels:
- - S1
- - S2
- - S3
- - S4
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
```
-#### `query.group_by`
+##### `query.group_by`
Define the X-axis of your chart.
@@ -258,7 +304,7 @@ Supported values are:
- `week`: Group data per week.
- `month`: Group data per month.
-#### `query.period_limit`
+##### `query.period_limit`
Define how far "issuables" are queried in the past (using the `query.period_field`).
@@ -295,6 +341,68 @@ NOTE:
Until [this bug](https://gitlab.com/gitlab-org/gitlab/-/issues/26911), is resolved,
you may see `created_at` in place of `merged_at`. `created_at` is used instead.
+#### `DORA` query parameters
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/367248) in GitLab 15.3.
+
+An example DORA chart definition:
+
+```yaml
+dora:
+ title: "DORA charts"
+ charts:
+ - title: "DORA deployment frequency"
+ type: bar # only bar chart is supported at the moment
+ query:
+ data_source: dora
+ params:
+ metric: deployment_frequency
+ group_by: day
+ period_limit: 10
+ projects:
+ only:
+ - 38
+ - title: "DORA lead time for changes"
+ description: "DORA lead time for changes"
+ type: bar
+ query:
+ data_source: dora
+ params:
+ metric: lead_time_for_changes
+ group_by: day
+ environment_tiers:
+ - staging
+ period_limit: 30
+```
+
+##### `query.metric`
+
+Defines which DORA metric to query. The available values are:
+
+- `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.
+
+Supported values are:
+
+- `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.
+
+##### `query.environment_tiers`
+
+An array of environments to include into the calculation (default: production). Available options: `production`, `staging`, `testing`, `development`, `other`.
+
### `projects`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10904) in GitLab 12.4.
@@ -325,10 +433,12 @@ monthlyBugsCreated:
description: "Open bugs created per month"
type: bar
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
projects:
only:
- 3 # You can use the project ID
@@ -355,41 +465,47 @@ bugsCharts:
type: bar
<<: *projectsOnly
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- group_by: month
- period_limit: 24
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ group_by: month
+ period_limit: 24
- title: "Weekly bugs by severity"
type: stacked-bar
<<: *projectsOnly
query:
- issuable_type: issue
- issuable_state: opened
- filter_labels:
- - bug
- collection_labels:
- - S1
- - S2
- - S3
- - S4
- group_by: week
- period_limit: 104
+ data_source: issuables
+ params:
+ issuable_type: issue
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - S1
+ - S2
+ - S3
+ - S4
+ group_by: week
+ period_limit: 104
- title: "Monthly bugs by team"
type: line
<<: *projectsOnly
query:
- issuable_type: merge_request
- issuable_state: opened
- filter_labels:
- - bug
- collection_labels:
- - Manage
- - Plan
- - Create
- group_by: month
- period_limit: 24
+ data_source: issuables
+ params:
+ issuable_type: merge_request
+ issuable_state: opened
+ filter_labels:
+ - bug
+ collection_labels:
+ - Manage
+ - Plan
+ - Create
+ group_by: month
+ period_limit: 24
```
diff --git a/doc/user/project/integrations/harbor.md b/doc/user/project/integrations/harbor.md
index 1319c9e74cd..da35f0dc226 100644
--- a/doc/user/project/integrations/harbor.md
+++ b/doc/user/project/integrations/harbor.md
@@ -39,7 +39,7 @@ GitLab supports integrating Harbor projects at the group or project level. Compl
After the Harbor integration is activated:
-- The global variables `$HARBOR_USERNAME`, `$HARBOR_PASSWORD`, `$HARBOR_URL`, and `$HARBOR_PROJECT` are created for CI/CD use.
+- The global variables `$HARBOR_USERNAME`, `$HARBOR_HOST`, `$HARBOR_OCI`, `$HARBOR_PASSWORD`, `$HARBOR_URL`, and `$HARBOR_PROJECT` are created for CI/CD use.
- The project-level integration settings override the group-level integration settings.
## Secure your requests to the Harbor APIs
@@ -50,3 +50,51 @@ the `username:password` combination. The following are suggestions for safe use:
- Use TLS on the Harbor APIs you connect to.
- Follow the principle of least privilege (for access on Harbor) with your credentials.
- Have a rotation policy on your credentials.
+
+## Examples of Harbor variables in CI/CD
+
+### Push a Docker image with kaniko
+
+For more information, see [Use kaniko to build Docker images](../../../ci/docker/using_kaniko.md).
+
+```yaml
+docker:
+ stage: docker
+ image:
+ name: gcr.io/kaniko-project/executor:debug
+ entrypoint: ['']
+ script:
+ - mkdir -p /kaniko/.docker
+ - echo "{\"auths\":{\"${HARBOR_HOST}\":{\"auth\":\"$(echo -n ${HARBOR_USERNAME}:${HARBOR_PASSWORD} | base64)\"}}}" > /kaniko/.docker/config.json
+ - >-
+ /kaniko/executor
+ --context "${CI_PROJECT_DIR}"
+ --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
+ --destination "${HARBOR_HOST}/${HARBOR_PROJECT}/${CI_PROJECT_NAME}:${CI_COMMIT_TAG}"
+ rules:
+ - if: $CI_COMMIT_TAG
+```
+
+### Push a Helm chart with an OCI registry
+
+Helm supports OCI registries by default. OCI is supported in [Harbor 2.0](https://github.com/goharbor/harbor/releases/tag/v2.0.0) and later.
+Read more about OCI in Helm's [blog](https://helm.sh/blog/storing-charts-in-oci/) and [documentation](https://helm.sh/docs/topics/registries/#enabling-oci-support).
+
+```yaml
+helm:
+ stage: helm
+ image:
+ name: dtzar/helm-kubectl:latest
+ entrypoint: ['']
+ variables:
+ # Enable OCI support (not required since Helm v3.8.0)
+ HELM_EXPERIMENTAL_OCI: 1
+ script:
+ # Log in to the Helm registry
+ - helm registry login "${HARBOR_URL}" -u "${HARBOR_USERNAME}" -p "${HARBOR_PASSWORD}"
+ # Package your Helm chart, which is in the `test` directory
+ - helm package test
+ # Your helm chart is created with <chart name>-<chart release>.tgz
+ # You can push all building charts to your Harbor repository
+ - helm push test-*.tgz ${HARBOR_OCI}/${HARBOR_PROJECT}
+```
diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md
index 7af2e431157..3ef40fdfe44 100644
--- a/doc/user/project/integrations/index.md
+++ b/doc/user/project/integrations/index.md
@@ -73,6 +73,7 @@ You can configure the following integrations.
| [Pipelines emails](pipeline_status_emails.md) | Send the pipeline status to a list of recipients by email. | **{dotted-circle}** No |
| [Pivotal Tracker](pivotal_tracker.md) | Add commit messages as comments to Pivotal Tracker stories. | **{dotted-circle}** No |
| [Prometheus](prometheus.md) | Monitor application metrics. | **{dotted-circle}** No |
+| [Pumble](pumble.md) | Send event notifications to a Pumble channel. | **{dotted-circle}** No |
| Pushover | Get real-time notifications on your device. | **{dotted-circle}** No |
| [Redmine](redmine.md) | Use Redmine as the issue tracker. | **{dotted-circle}** No |
| [Slack application](gitlab_slack_application.md) | Use Slack's official GitLab application. | **{dotted-circle}** No |
diff --git a/doc/user/project/integrations/pumble.md b/doc/user/project/integrations/pumble.md
new file mode 100644
index 00000000000..cd28a7c0048
--- /dev/null
+++ b/doc/user/project/integrations/pumble.md
@@ -0,0 +1,39 @@
+---
+stage: Ecosystem
+group: Integrations
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Pumble **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93623) in GitLab 15.3.
+
+You can configure GitLab to send notifications to a Pumble channel:
+
+1. Create a webhook for the channel.
+1. Add the webhook to GitLab.
+
+## Create a webhook for your Pumble channel
+
+1. Follow the steps in [Incoming Webhooks for Pumble](https://pumble.com/help/integrations/custom-apps/incoming-webhooks-for-pumble/) in the Pumble documentation.
+1. Copy the webhook URL.
+
+## Configure settings in GitLab
+
+After you have a webhook URL for your Pumble channel, configure GitLab to send
+notifications:
+
+1. To enable the integration for your group or project:
+ 1. In your group or project, on the left sidebar, select **Settings > Integrations**.
+1. To enable the integration for your instance:
+ 1. On the top bar, select **Menu > Admin**.
+ 1. On the left sidebar, select **Settings > Integrations**.
+1. Select the **Pumble** integration.
+1. Ensure that the **Active** toggle is enabled.
+1. Select the checkboxes corresponding to the GitLab events you want to receive in Pumble.
+1. Paste the **Webhook** URL for the Pumble channel.
+1. Configure the remaining options.
+1. Optional. To test the integration, select **Test settings**.
+1. Select **Save changes**.
+
+The Pumble channel begins to receive all applicable GitLab events.
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index bd93fbcbcbc..dd0f57570aa 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -77,13 +77,13 @@ The following triggers are available for Slack notifications:
## Troubleshooting
If your Slack integration is not working, start troubleshooting by
-searching through the [Sidekiq logs](../../../administration/logs.md#sidekiqlog)
+searching through the [Sidekiq logs](../../../administration/logs/index.md#sidekiqlog)
for errors relating to your Slack service.
### Something went wrong on our end
You might get this generic error message in the GitLab UI.
-Review [the logs](../../../administration/logs.md#productionlog) to find
+Review [the logs](../../../administration/logs/index.md#productionlog) to find
the error message and keep troubleshooting from there.
### `certificate verify failed`
diff --git a/doc/user/project/integrations/webhook_events.md b/doc/user/project/integrations/webhook_events.md
index 32e5f949c15..51049f156b8 100644
--- a/doc/user/project/integrations/webhook_events.md
+++ b/doc/user/project/integrations/webhook_events.md
@@ -878,7 +878,9 @@ Payload example:
"source_branch": "ms-viewport",
"source_project_id": 14,
"author_id": 51,
+ "assignee_ids": [6],
"assignee_id": 6,
+ "reviewer_ids": [6],
"title": "MS-Viewport",
"created_at": "2013-12-03T17:23:34Z",
"updated_at": "2013-12-03T17:23:34Z",
@@ -945,12 +947,7 @@ Payload example:
"type": "ProjectLabel",
"group_id": 41
}],
- "action": "open",
- "assignee": {
- "name": "User1",
- "username": "user1",
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
- }
+ "action": "open"
},
"labels": [{
"id": 206,
@@ -999,7 +996,23 @@ Payload example:
"group_id": 41
}]
}
- }
+ },
+ "assignees": [
+ {
+ "id": 6,
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ }
+ ],
+ "reviewers": [
+ {
+ "id": 6,
+ "name": "User1",
+ "username": "user1",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
+ }
+ ]
}
```
@@ -1614,7 +1627,7 @@ Payload example:
### Remove a subgroup from a group
-This webhook is not triggered when a [subgroup is transferred to a new parent group](../../group/index.md#transfer-a-group).
+This webhook is not triggered when a [subgroup is transferred to a new parent group](../../group/manage.md#transfer-a-group).
Request header:
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index e4ce736684b..1de7440a15d 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -137,7 +137,7 @@ For example, to test `push events`, your project should have at least one commit
To test a webhook:
-1. In your project, on the left sidebar, select **Settings > Webhooks**.
+1. In your project or group, on the left sidebar, select **Settings > Webhooks**.
1. Scroll down to the list of configured webhooks.
1. From the **Test** dropdown list, select the type of event to test.
@@ -236,12 +236,14 @@ For more information about supported events for Webhooks, go to [Webhook events]
## Troubleshoot webhooks
+> **Recent events** for group webhooks [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325642) in GitLab 15.3.
+
GitLab records the history of each webhook request.
You can view requests made in the last 2 days in the **Recent events** table.
To view the table:
-1. In your project, on the left sidebar, select **Settings > Webhooks**.
+1. In your project or group, on the left sidebar, select **Settings > Webhooks**.
1. Scroll down to the webhooks.
1. Each [failing webhook](#failing-webhooks) has a badge listing it as:
@@ -261,10 +263,6 @@ The table includes the following details about each request:
![Recent deliveries](img/webhook_logs.png)
-NOTE:
-The **Recent events** table is unavailable for group-level webhooks. For more information, read
-[issue #325642](https://gitlab.com/gitlab-org/gitlab/-/issues/325642).
-
Each webhook event has a corresponding **Details** page. This page details the data that GitLab sent (request headers and body) and received (response headers and body).
To view the **Details** page, select **View details** for the webhook event.
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index c8ecb2fd2e6..787e990526d 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -642,3 +642,20 @@ A few things to remember:
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues, start scrolling down and the next
20 appear.
+
+## Troubleshooting issue boards
+
+### Use Rails console to fix issue boards not loading and timing out
+
+If you see issue board not loading and timing out in UI, use Rails console to call the Issue Rebalancing service to fix it:
+
+1. [Start a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session).
+1. Run these commands:
+
+ ```ruby
+ p = Project.find_by_full_path('<username-or-group>/<project-name>')
+
+ Issues::RelativePositionRebalancingService.new(p.root_namespace.all_projects).execute
+ ```
+
+1. To exit the Rails console, type `quit`.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index d1b27f6eab0..bf3cd13f3f0 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -276,7 +276,7 @@ It's rendered as:
User activity events on designs (creation, deletion, and updates) are tracked by GitLab and
displayed on the [user profile](../../profile/index.md#access-your-user-profile),
-[group](../../group/index.md#view-group-activity),
+[group](../../group/manage.md#view-group-activity),
and [project](../working_with_projects.md#view-project-activity) activity pages.
## GitLab-Figma plugin
diff --git a/doc/user/project/issues/img/related_issue_block_v12_8.png b/doc/user/project/issues/img/related_issue_block_v12_8.png
deleted file mode 100644
index ce261f26ce6..00000000000
--- a/doc/user/project/issues/img/related_issue_block_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/related_issue_block_v15_3.png b/doc/user/project/issues/img/related_issue_block_v15_3.png
new file mode 100644
index 00000000000..827ddeabf10
--- /dev/null
+++ b/doc/user/project/issues/img/related_issue_block_v15_3.png
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_add_v12_8.png b/doc/user/project/issues/img/related_issues_add_v12_8.png
deleted file mode 100644
index 8a06d005a5f..00000000000
--- a/doc/user/project/issues/img/related_issues_add_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_add_v15_3.png b/doc/user/project/issues/img/related_issues_add_v15_3.png
new file mode 100644
index 00000000000..7c6edf61427
--- /dev/null
+++ b/doc/user/project/issues/img/related_issues_add_v15_3.png
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_remove_v12_8.png b/doc/user/project/issues/img/related_issues_remove_v12_8.png
deleted file mode 100644
index a8dff4c7052..00000000000
--- a/doc/user/project/issues/img/related_issues_remove_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/related_issues_remove_v15_3.png b/doc/user/project/issues/img/related_issues_remove_v15_3.png
new file mode 100644
index 00000000000..577bbed9df3
--- /dev/null
+++ b/doc/user/project/issues/img/related_issues_remove_v15_3.png
Binary files differ
diff --git a/doc/user/project/issues/issue_weight.md b/doc/user/project/issues/issue_weight.md
index 756fe9699f1..fcc53a239dc 100644
--- a/doc/user/project/issues/issue_weight.md
+++ b/doc/user/project/issues/issue_weight.md
@@ -17,6 +17,7 @@ You can set the weight of an issue during its creation, by changing the
value in the dropdown menu. You can set it to a non-negative integer
value from 0, 1, 2, and so on.
You can remove weight from an issue as well.
+A user with a Reporter role (or above) can set the weight.
This value appears on the right sidebar of an individual issue, as well as
in the issues page next to a weight icon (**{weight}**).
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index 15d8da7f544..40e5a6d6a92 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -123,8 +123,8 @@ example, if the list is scoped to a label `Frontend`, the new issue also has thi
### By sending an email
-> Generated email address format changed in GitLab 11.7.
-> The older format is still supported, so existing aliases and contacts still work.
+> - Generated email address format changed in GitLab 11.7.
+> - The older format is still supported, so existing aliases and contacts still work.
You can send an email to create an issue in a project on the project's
**Issues List** page.
@@ -731,4 +731,4 @@ You can do the following **only by using quick actions**:
- [Publish an issue](#publish-an-issue) (`/publish`).
- Clone an issue to the same or another project (`/clone`).
- Close an issue and mark as a duplicate of another issue (`/duplicate`).
-- Copy labels and milestone from another merge request in the project (`/copy_metadata`).
+- Copy labels and milestone from another merge request or issue in the project (`/copy_metadata`).
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index 028dd2ea473..9dc361b403f 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -37,7 +37,7 @@ To link one issue to another:
- **[is blocked by](#blocking-issues)**
1. Input the issue number or paste in the full URL of the issue.
- ![Adding a related issue](img/related_issues_add_v12_8.png)
+ ![Adding a related issue](img/related_issues_add_v15_3.png)
Issues of the same project can be specified just by the reference number.
Issues from a different project require additional information like the
@@ -54,7 +54,7 @@ To link one issue to another:
When you have finished adding all linked issues, you can see
them categorized so their relationships can be better understood visually.
-![Related issue block](img/related_issue_block_v12_8.png)
+![Related issue block](img/related_issue_block_v15_3.png)
You can also add a linked issue from a commit message or the description in another issue or MR.
[Learn more about crosslinking issues](crosslinking_issues.md).
@@ -66,7 +66,7 @@ right-side of each issue token to remove.
Due to the bi-directional relationship, the relationship no longer appears in either issue.
-![Removing a related issue](img/related_issues_remove_v12_8.png)
+![Removing a related issue](img/related_issues_remove_v15_3.png)
Access our [permissions](../../permissions.md) page for more information.
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 333b073ee40..62c5489d9c3 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -446,12 +446,13 @@ To learn what happens when you sort by priority or label priority, see
## Real-time changes to labels
-> [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.
+> - [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.
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 GitLab.com, this feature is unavailable.
+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 ff5f2ac8cb6..4a6272a0ca3 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -15,7 +15,7 @@ Project members can:
1. Be [direct members](#add-users-to-a-project) of the project.
1. [Inherit membership](#inherited-membership) of the project from the project's group.
1. Be a member of a group that was [shared](share_project_with_groups.md) with the project.
-1. Be a member of a group that was [shared with the project's group](../../group/index.md#share-a-group-with-another-group).
+1. Be a member of a group that was [shared with the project's group](../../group/manage.md#share-a-group-with-another-group).
```mermaid
flowchart RL
@@ -49,11 +49,22 @@ flowchart RL
[Feature flag `invite_members_group_modal`](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) removed.
Add users to a project so they become members and have permission
-to perform actions. The Owner [role](../../permissions.md#project-members-permissions) can only be added at the group level.
+to perform actions.
+
+The maximum role (access level) you set depends on if you have the Owner or Maintainer role for the group. For example, the maximum
+role that can be set is:
+
+- Owner (`50`), if you have the Owner role for the project.
+- Maintainer (`40`), if you have the Maintainer role on the project.
+
+In GitLab 14.8 and earlier, direct members of a project have a maximum role of Maintainer.
+The Owner [role](../../permissions.md#project-members-permissions) can only be added at the group level.
Prerequisite:
-- You must have the Maintainer or Owner role.
+- You must have the Maintainer or Owner role:
+ - To remove direct members with the Maintainer role and below, you must have the Maintainer role.
+ - To remove members with the Owner role, you must have the Owner role.
To add a user to a project:
@@ -91,7 +102,7 @@ Each user's access is based on:
Prerequisite:
- You must have the Maintainer or Owner role.
-- Sharing the project with other groups must not be [prevented](../../group/index.md#prevent-a-project-from-being-shared-with-groups).
+- Sharing the project with other groups must not be [prevented](../../group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).
To add groups to a project:
@@ -107,7 +118,7 @@ The members of the group are not displayed on the **Members** tab.
The **Members** tab shows:
- Members who are directly assigned to the project.
-- If the project was created in a group [namespace](../../group/index.md#namespaces), members of that group.
+- If the project was created in a group [namespace](../../namespace/index.md), members of that group.
## Import users from another project
@@ -173,7 +184,7 @@ To remove a member from a project:
user has not forked the private repository or created webhooks. Existing forks continue to receive
changes from the upstream project, and webhooks continue to receive updates. You may also want to configure your project
to prevent projects in a group
- [from being forked outside their group](../../group/index.md#prevent-project-forking-outside-group).
+ [from being forked outside their group](../../group/access_and_permissions.md#prevent-project-forking-outside-group).
1. Select **Remove member**.
## Filter and sort members
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index c4ae00f3c6c..3d5b855a9d3 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -29,7 +29,7 @@ You can share a project only with:
- Groups for which you have an explicitly defined [membership](index.md).
- Groups that contain a nested subgroup or project for which you have an explicitly defined role.
-Administrators can share projects with any group in the namespace.
+Administrators can share projects with any group in the instance.
The primary mechanism to give a group of users, say 'Engineering', access to a project,
say 'Project Acme', in GitLab is to make the 'Engineering' group the owner of 'Project
@@ -52,7 +52,7 @@ After sharing 'Project Acme' with 'Engineering':
When you share a project, be aware of the following restrictions and outcomes:
- [Maximum access level](#maximum-access-level)
-- [Sharing a public project with a private group](#share-a-public-project-with-private-group)
+- [Sharing projects with groups of a higher restrictive visibility level](#sharing-projects-with-groups-of-a-higher-restrictive-visibility-level)
- [Sharing project with group lock](#share-project-with-group-lock)
## Maximum access level
@@ -67,18 +67,24 @@ in. That means you can only share down the hierarchy. For example, `group/subgro
- Can not be shared with `group`.
- Can be shared with `group/subgroup02` or `group/subgroup01/subgroup03`.
-## Share a public project with private group
+## Sharing projects with groups of a higher restrictive visibility level
-When you share a public project with a private group, be aware of the following outcomes:
+There are several outcomes you must be aware of when you share a project with a group that has a more restrictive [visibility level](../../public_access.md#project-and-group-visibility) than the project. For example, when you:
-- The name of the group is no longer private and is visible to all users in the project members page.
-- Owners of the project have access to members of the private group when they mention them in issues or merge requests.
-- Project members who are direct or indirect members of the private group can see private group members listed in addition to members of the project.
+- Share a public project with a private group.
+- Share a public project with an internal group.
+- Share an internal project with a private group.
+
+The following outcomes occur:
+
+- The group name is visible to all users that can view the project members page.
+- Owners of the project have access to members of the group when they mention them in issues or merge requests.
+- Project members who are direct or indirect members of the group can see group members listed in addition to members of the project.
## Share project with group lock
-It is possible to prevent projects in a group from [sharing
-a project with another group](../members/share_project_with_groups.md).
+It is possible to prevent projects in a group from
+[sharing a project with another group](../members/share_project_with_groups.md).
This allows for tighter control over project access.
-Learn more about [Share with group lock](../../group/index.md#prevent-a-project-from-being-shared-with-groups).
+Learn more about [Share with group lock](../../group/access_and_permissions.md#prevent-a-project-from-being-shared-with-groups).
diff --git a/doc/user/project/merge_requests/approvals/img/scoped_to_protected_branch_v13_10.png b/doc/user/project/merge_requests/approvals/img/scoped_to_protected_branch_v13_10.png
deleted file mode 100644
index a6636f0bc7f..00000000000
--- a/doc/user/project/merge_requests/approvals/img/scoped_to_protected_branch_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index 014936208c6..9f33ed6807b 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -23,7 +23,7 @@ flexibility:
and require their approval before work can merge.
You can configure merge request approvals on a per-project basis, and
-[on the group level](../../../group/index.md#group-merge-request-approval-settings). Administrators of
+[on the group level](../../../group/manage.md#group-merge-request-approval-settings). Administrators of
[GitLab Premium](https://about.gitlab.com/pricing/) and
[GitLab Ultimate](https://about.gitlab.com/pricing/) self-managed GitLab instances
can also configure approvals
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index b79c8ee867f..c9278c19322 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -7,7 +7,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Merge request approval rules **(PREMIUM)**
Approval rules define how many [approvals](index.md) a merge request must receive before it can
-be merged, and which users should do the approving. You can define approval rules:
+be merged, and which users should do the approving. They can be used in conjunction
+with [Code owners](#code-owners-as-eligible-approvers) to ensure that changes are
+reviewed both by the group maintaining the feature, and any groups responsible
+for specific areas of oversight.
+
+You can define approval rules:
- [As project defaults](#add-an-approval-rule).
- [Per merge request](#edit-or-override-merge-request-approval-rules).
@@ -127,7 +132,7 @@ users were not explicitly listed in the approval rules.
### Group approvers
You can add a group of users as approvers, but those users count as approvers only if
-they have direct membership to the group. Group approvers are
+they have **direct membership** to the group. Inherited members do not count. Group approvers are
restricted to only groups [with share access to the project](../../members/share_project_with_groups.md).
A user's membership in an approvers group affects their individual ability to
@@ -172,15 +177,15 @@ oversight on proposed work. To enable approval permissions for these users witho
granting them push access:
1. [Create a protected branch](../../protected_branches.md)
-1. [Create a new group](../../../group/index.md#create-a-group).
-1. [Add the user to the group](../../../group/index.md#add-users-to-a-group),
+1. [Create a new group](../../../group/manage.md#create-a-group).
+1. [Add the user to the group](../../../group/manage.md#add-users-to-a-group),
and select the Reporter role for the user.
1. [Share the project with your group](../../members/share_project_with_groups.md#share-a-project-with-a-group-of-users),
based on the Reporter role.
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
1. Select **Add approval rule** or **Update approval rule** and target the protected branch.
-1. [Add the group](../../../group/index.md#create-a-group) to the permission list.
+1. [Add the group](../../../group/manage.md#create-a-group) to the permission list.
![Update approval rule](img/update_approval_rule_v13_10.png)
@@ -213,7 +218,8 @@ appreciated, but not required. To make an approval rule optional:
## Approvals for protected branches
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460) in GitLab 12.8.
+> - **All protected branches** target branch option [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/360930) in GitLab 15.3.
Approval rules are often relevant only to specific branches, like your
[default branch](../../repository/branches/default.md). To configure an
@@ -223,10 +229,10 @@ approval rule for certain branches:
1. Go to your project and select **Settings**.
1. Expand **Merge request (MR) approvals**.
1. Select a **Target branch**:
- - To protect all branches, select **All branches**.
- - To select a specific branch, select it from the list:
+ - To apply the rule to all branches, select **All branches**.
+ - To apply the rule to all protected branches, select **All protected branches** (GitLab 15.3 and later).
+ - To apply the rule to a specific branch, select it from the list:
- ![Scoped to protected branch](img/scoped_to_protected_branch_v13_10.png)
1. To enable this configuration, read
[Code Owner's approvals for protected branches](../../protected_branches.md#require-code-owner-approval-on-a-protected-branch).
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 7b865a91106..3ca8ddb508a 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -19,7 +19,9 @@ To view or edit merge request approval settings:
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**.
-In this section of general settings, you can configure the following settings:
+### Approval settings
+
+These settings limit who can approve merge requests.
| Setting | Description |
| ------ | ------ |
@@ -27,7 +29,14 @@ In this section of general settings, you can configure the following settings:
| [Prevent approvals by users who add commits](#prevent-approvals-by-users-who-add-commits) | When enabled, users who have committed to a merge request cannot approve it. |
| [Prevent editing approval rules in merge requests](#prevent-editing-approval-rules-in-merge-requests) | When enabled, users can't override the project's approval rules on merge requests. |
| [Require user password to approve](#require-user-password-to-approve) | Force potential approvers to first authenticate with a password. |
-| [Remove all approvals when commits are added to the source branch](#remove-all-approvals-when-commits-are-added-to-the-source-branch) | When enabled, remove all existing approvals on a merge request when more changes are added to it. |
+
+You can further define what happens to existing approvals when commits are added to the merge request.
+
+| Setting | Description |
+| ------ | ------ |
+| Keep approvals | Do not remove approvals. |
+| [Remove all approvals](#remove-all-approvals-when-commits-are-added-to-the-source-branch) | Remove all existing approvals. |
+| [Remove approvals by Code Owners if their files changed](#remove-approvals-by-code-owners-if-their-files-changed) | If a Code Owner has approved the merge request, and the commit changes files they are the Code Owner for, their approval is removed. |
## Prevent approval by author
@@ -119,9 +128,27 @@ when more changes are added to it:
1. Select the **Remove all approvals when commits are added to the source branch** checkbox.
1. Select **Save changes**.
-Approvals aren't reset when a merge request is [rebased from the UI](../methods/index.md#rebasing-in-semi-linear-merge-methods).
+Approvals aren't removed when a merge request is [rebased from the UI](../methods/index.md#rebasing-in-semi-linear-merge-methods)
However, approvals are reset if the target branch is changed.
+## Remove approvals by Code Owners if their files changed
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90578) in GitLab 15.3.
+
+If you only want to remove approvals by Code Owners whose files have been changed:
+
+Prerequisite:
+
+- You must have at least the Maintainer role for a project.
+
+To do this:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Merge request approvals**.
+1. Select **Remove approvals by Code Owners if their files changed**.
+1. Select **Save changes**.
+
## Code coverage check approvals
You can require specific approvals if a merge request would result in a decline in code test
@@ -139,7 +166,7 @@ You can also enforce merge request approval settings:
- At the [instance level](../../../admin_area/merge_requests_approvals.md), which apply to all groups
on an instance and, therefore, all projects.
-- On a [top-level group](../../../group/index.md#group-merge-request-approval-settings), which apply to all subgroups
+- On a [top-level group](../../../group/manage.md#group-merge-request-approval-settings), which apply to all subgroups
and projects.
If the settings are inherited by a group or project, they cannot be changed in the group or project
diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md
index 2adcc4d4575..893b2bc6811 100644
--- a/doc/user/project/merge_requests/csv_export.md
+++ b/doc/user/project/merge_requests/csv_export.md
@@ -8,13 +8,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3619) in GitLab 13.6.
-Exporting merge requests CSV enables you and your team to export all the data collected from merge requests into a comma-separated values (CSV) file, which stores tabular data in plain text.
+Export all the data collected from a project's merge requests into a comma-separated values (CSV) file.
-To export merge requests to CSV, navigate to your **Merge requests** from the sidebar of a project and select **Export as CSV**.
+To export merge requests to a CSV file:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Merge requests** .
+1. Add any searches or filters. This can help you keep the size of the CSV file under the 15MB limit. The limit ensures
+ the file can be emailed to a variety of email providers.
+1. Select **Export as CSV** (**{export}**).
+1. Confirm the correct number of merge requests are to be exported.
+1. Select **Export merge requests**.
## CSV Output
-The following table shows what attributes will be present in the CSV.
+The following table shows the attributes in the CSV file.
| Column | Description |
|--------------------|--------------------------------------------------------------|
@@ -42,8 +50,3 @@ The following table shows what attributes will be present in the CSV.
In GitLab 14.7 and earlier, the first two columns were `MR ID` and `URL`,
which [caused an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/34769)
when importing back into GitLab.
-
-## Limitations
-
-- Export merge requests to CSV is not available at the Group's merge request list.
-- As the merge request CSV file is sent as an email attachment, the size is limited to 15MB to ensure successful delivery across a range of email providers. If you need to minimize the size of the file, you can narrow the search before export. For example, you can set up exports of open and closed merge requests in separate files.
diff --git a/doc/user/project/merge_requests/img/license_compliance_widget_v15_3.png b/doc/user/project/merge_requests/img/license_compliance_widget_v15_3.png
new file mode 100644
index 00000000000..a9f73d40f82
--- /dev/null
+++ b/doc/user/project/merge_requests/img/license_compliance_widget_v15_3.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_widget_passed_v14_0.png b/doc/user/project/merge_requests/img/status_checks_widget_passed_v14_0.png
deleted file mode 100644
index de61ca8b553..00000000000
--- a/doc/user/project/merge_requests/img/status_checks_widget_passed_v14_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/img/status_checks_widget_pending_v14_0.png b/doc/user/project/merge_requests/img/status_checks_widget_pending_v14_0.png
deleted file mode 100644
index c4e606bd2f4..00000000000
--- a/doc/user/project/merge_requests/img/status_checks_widget_pending_v14_0.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 a7a669d3b75..35ec075c674 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -41,7 +41,7 @@ To view merge requests for all projects in a group:
If your group contains subgroups, this view also displays merge requests from the subgroup projects.
-## View all merge requests assigned to you
+### View all merge requests assigned to you
To view all merge requests assigned to you:
@@ -52,13 +52,14 @@ To view all merge requests assigned to you:
<!-- vale gitlab.FirstPerson = YES -->
-Or:
+or:
- To use a [keyboard shortcut](../../shortcuts.md), press <kbd>Shift</kbd> + <kbd>m</kbd>.
-- On the top bar, on the top right, select **{merge-request-open}** **Merge requests**.
- Then select one of the following:
- - [Review requests](reviews/index.md).
- - Merge requests assigned.
+
+or:
+
+1. On the top bar, on the top right, select **{merge-request-open}** **Merge requests**.
+1. From the dropdown list, select **Assigned to you**.
## Filter the list of merge requests
diff --git a/doc/user/project/merge_requests/methods/index.md b/doc/user/project/merge_requests/methods/index.md
index 63b464e5ff4..c4e4b40dc48 100644
--- a/doc/user/project/merge_requests/methods/index.md
+++ b/doc/user/project/merge_requests/methods/index.md
@@ -150,12 +150,8 @@ considered equivalent to rebasing.
### Rebase without CI/CD pipeline
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118825) in GitLab 14.7 [with a flag](../../../../administration/feature_flags.md) named `rebase_without_ci_ui`. Disabled by default.
-
-FLAG:
-On GitLab.com and 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 `rebase_without_ci_ui`.
-The feature is not ready for production use.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118825) in GitLab 14.7 [with a flag](../../../../administration/feature_flags.md) named `rebase_without_ci_ui`. Disabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350262) in GitLab 15.3. Feature flag `rebase_without_ci_ui` removed.
To rebase a merge request's branch without triggering a CI/CD pipeline, select
**Rebase without pipeline** from the merge request reports section.
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v13_11.png b/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v13_11.png
deleted file mode 100644
index 6b4899bf67f..00000000000
--- a/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v15_3.png b/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v15_3.png
new file mode 100644
index 00000000000..b73dbb50cd2
--- /dev/null
+++ b/doc/user/project/merge_requests/reviews/img/mr_review_new_comment_v15_3.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_resolve.png b/doc/user/project/merge_requests/reviews/img/mr_review_resolve.png
deleted file mode 100644
index ced33682459..00000000000
--- a/doc/user/project/merge_requests/reviews/img/mr_review_resolve.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_resolve2.png b/doc/user/project/merge_requests/reviews/img/mr_review_resolve2.png
deleted file mode 100644
index 2f0be3b6d06..00000000000
--- a/doc/user/project/merge_requests/reviews/img/mr_review_resolve2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_start.png b/doc/user/project/merge_requests/reviews/img/mr_review_start.png
deleted file mode 100644
index 08b4c6bb82b..00000000000
--- a/doc/user/project/merge_requests/reviews/img/mr_review_start.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_review_unresolve.png b/doc/user/project/merge_requests/reviews/img/mr_review_unresolve.png
deleted file mode 100644
index 4bef38f7808..00000000000
--- a/doc/user/project/merge_requests/reviews/img/mr_review_unresolve.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/img/mr_summary_comment_v15_3.png b/doc/user/project/merge_requests/reviews/img/mr_summary_comment_v15_3.png
new file mode 100644
index 00000000000..38e18115803
--- /dev/null
+++ b/doc/user/project/merge_requests/reviews/img/mr_summary_comment_v15_3.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index a8f43dd9c02..27b223c48ec 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -36,13 +36,9 @@ To start your review:
1. Select the **{comment}** **comment** icon in the gutter to expand the diff lines
and display a comment box. In GitLab version 13.2 and later, you can
[select multiple lines](#comment-on-multiple-lines).
-1. Write your first comment, and select **Start a review** below your comment:
- ![Starting a review](img/mr_review_start.png)
-1. Continue adding comments to lines of code, and select the appropriate button after
- you write a comment:
- - **Add to review**: Keep this comment private and add to the current review.
- These review comments are marked **Pending** and are visible only to you.
- - **Add comment now**: Submits the specific comment as a regular comment instead of as part of the review.
+1. In the text area, write your first comment, then select **Start a review** below your comment.
+1. Continue adding comments to lines of code. After each comment, select **Add to review**.
+ Comments made as part of a review are visible only to you until you submit your review.
1. Optional. You can use [quick actions](../../quick_actions.md) inside review comments.
The comment shows the actions to perform after publication, but does not perform them
until you submit your review.
@@ -60,8 +56,12 @@ displays next to your name.
You can submit your completed review in multiple ways:
- Use the `/submit_review` [quick action](../../quick_actions.md) in the text of a non-review comment.
-- When creating a review comment, select **Submit review**.
-- Scroll to the bottom of the screen and select **Submit review**.
+- Select **Finish review** and then **Submit review** in the footer at the bottom of the screen.
+
+Selecting **Finish review** opens a modal window to add an optional comment to summarize your review.
+You can also include quick actions:
+
+![Finish review with comment](img/mr_summary_comment_v15_3.png)
When you submit your review, GitLab:
@@ -73,25 +73,25 @@ When you submit your review, GitLab:
### Resolve or unresolve thread with a comment
Review comments can also resolve or unresolve [resolvable threads](../../../discussions/index.md#resolve-a-thread).
-When replying to a comment, a checkbox is displayed to resolve or unresolve
-the thread after publication.
-
-![Resolve checkbox](img/mr_review_resolve.png)
+To resolve or unresolve a thread when replying to a comment:
-If a particular pending comment resolves or unresolves the thread, this is shown on the pending
-comment itself.
+1. In the comment text area, write your comment.
+1. Select or clear **Resolve thread**.
+1. Select **Add comment now** or **Add to review**.
-![Resolve status](img/mr_review_resolve2.png)
+Pending comments display information about the action to be taken when the comment is published:
-![Unresolve status](img/mr_review_unresolve.png)
+- **{check-circle-filled}** Thread will be resolved.
+- **{check-circle}** Thread stays unresolved.
### Add a new comment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8225) in GitLab 13.10.
-If you have a review in progress, you are presented with the option to **Add to review**:
+If you have a review in progress, you can also add a comment from the **Overview** tab by selecting
+ **Add to review**:
-![New thread](img/mr_review_new_comment_v13_11.png)
+![New thread](img/mr_review_new_comment_v15_3.png)
### Approval Rule information for Reviewers **(PREMIUM)**
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index 423179325d3..0d7794a3ebd 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -10,6 +10,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/user/project/merge_requests/statu
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3869) in GitLab 14.0, disabled behind the `:ff_external_status_checks` feature flag.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/320783) in GitLab 14.1.
+> - `failed` status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329636) in GitLab 14.9.
You can create a status check that sends merge request data to third-party tools.
When users create, change, or close merge requests, GitLab sends a notification. The users or automated workflows
@@ -50,9 +51,8 @@ Merge requests return a `409 Conflict` error to any responses that do not refer
External status checks have the following states:
- `pending` - The default state. No response can been received by the merge request from the external service.
-- `response received` - A response from the external service has been received and approved by it.
-
-Support for adding a `failed` state is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338827).
+- `passed` - A response from the external service has been received and approved by it.
+- `failed` - A response from the external service has been received and denied by it.
If something changes outside of GitLab, you can [set the status of an external status check](../../../api/status_checks.md#set-status-of-an-external-status-check)
using the API. You don't need to wait for a merge request webhook payload to be sent first.
@@ -138,24 +138,18 @@ the status check and it **will not** be recoverable.
## Status checks widget
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327634) in GitLab 14.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/327634) in GitLab 14.1.
+> - UI [updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91504) in GitLab 15.2.
-The status checks widget displays in merge requests and shows the status of external
-status checks:
+The status checks widget displays in merge requests and displays the following statuses:
-![Status checks widget](img/status_checks_widget_passed_v14_0.png)
+- **pending** (**{status-neutral}**), while GitLab waits for a response from an external status check.
+- **success** (**{status-success}**) or **failed** (**{status-failed}**), when GitLab receives a response from an external status check.
An organization might have a policy that does not allow merging merge requests if
external status checks do not pass. However, the details in the widget are for informational
purposes only. GitLab does not prevent merging of merge requests that fail status checks.
-
-While GitLab waits for a response from the external status check, the widget shows
-the status checks as `pending`:
-
-![Status checks widget pending](img/status_checks_widget_pending_v14_0.png)
-
-After GitLab [receives a response](../../../api/status_checks.md#set-status-of-an-external-status-check)
-from the external status check, the widget updates accordingly.
+Support to allow merges to be blocked when external status checks fail is proposed in epic [&8516](https://gitlab.com/groups/gitlab-org/-/epics/8516).
NOTE:
GitLab cannot guarantee that the external status checks are properly processed by
diff --git a/doc/user/project/merge_requests/widgets.md b/doc/user/project/merge_requests/widgets.md
index b0464f3f972..0e179415192 100644
--- a/doc/user/project/merge_requests/widgets.md
+++ b/doc/user/project/merge_requests/widgets.md
@@ -63,6 +63,12 @@ faster to preview proposed modifications.
[Read more about Review Apps](../../../ci/review_apps/index.md).
+## License compliance **(ULTIMATE)**
+
+If you have configured [License Compliance](../../compliance/license_compliance/index.md) for your project, then you can view a list of licenses that are detected for your project's dependencies.
+
+![Merge request pipeline](img/license_compliance_widget_v15_3.png)
+
## External status checks **(ULTIMATE)**
If you have configured [external status checks](status_checks.md) you can
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index ba48876d4fd..ef734225fb4 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -44,6 +44,14 @@ To view the milestone list:
In a project, GitLab displays milestones that belong to the project.
In a group, GitLab displays milestones that belong to the group and all projects in the group.
+NOTE:
+If a project has issue tracking
+[turned off](../settings/index.md#configure-project-visibility-features-and-permissions),
+you can get to the milestones page
+by going to its URL. To do so, add: `/-/milestones` to your project or group URL.
+For example `https://gitlab.com/gitlab-org/sample-data-templates/sample-gitlab-project/-/milestones`.
+This is tracked in [issue 339009](https://gitlab.com/gitlab-org/gitlab/-/issues/339009).
+
### View all milestones
You can view all the milestones you have access to in the entire GitLab namespace.
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 6daf671a751..c4c30dbdab4 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
@@ -32,6 +32,7 @@ for the most popular hosting services:
<!-- vale gitlab.Spelling = NO -->
+- [123-reg](https://www.123-reg.co.uk/support/domains/domain-name-server-dns-management-guide/)
- [Amazon](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)
- [Bluehost](https://www.bluehost.com/help/article/dns-management-add-edit-or-delete-dns-entries)
- [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/201720164-Creating-a-Cloudflare-account-and-adding-a-website)
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 184e4f345c1..0cc6cb808d1 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
@@ -79,8 +79,6 @@ If you get an error **Something went wrong while obtaining the Let's Encrypt cer
1. Make sure [your domain is verified](index.md#1-add-a-custom-domain-to-pages).
1. Go to step 1.
-Another possible cause of this error is the `_redirects` file because the current implementation relies on an HTTP ACME challenge. If you redirect the `.acme-challenge/` endpoint Let's Encrypt cannot validate the domain. Make sure you don't have a wildcard (`*`) redirect either as that too breaks validation. The problem with wildcard redirects is tracked in the [Wildcard redirects break Let's Encrypt integration](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/649) issue.
-
### Message "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later." hangs for more than an hour
If you've enabled Let's Encrypt integration, but a certificate is absent after an hour and you see the message, "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.", try to remove and add the domain for GitLab Pages again by following these steps:
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 5fd17b5c07e..68a2a6a80ad 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -420,10 +420,10 @@ Now GitLab CI/CD not only builds the website, but also:
For more information, see the following blog posts.
-- [Use GitLab CI/CD `environments` to deploy your
- web app to staging and production](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/).
-- Learn [how to run jobs sequentially,
- in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/).
+- Use GitLab CI/CD `environments` to
+ [deploy your web app to staging and production](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/).
+- Learn how to run jobs
+ [sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/).
- Learn [how to pull specific directories from different projects](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
to deploy this website, <https://docs.gitlab.com>.
- Learn [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/).
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 54b843945cd..29712a82be1 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -18,7 +18,7 @@ replace the Pages wildcard domain on GitLab.com (`*.gitlab.io`) with your own.
If you set up a GitLab Pages project on GitLab,
it's automatically accessible under a
subdomain of `namespace.example.io`.
-The [`namespace`](../../group/index.md#namespaces)
+The [`namespace`](../../namespace/index.md)
is defined by your username on GitLab.com,
or the group name you created this project under.
For GitLab self-managed instances, replace `example.io`
diff --git a/doc/user/project/pages/img/remove_pages.png b/doc/user/project/pages/img/remove_pages.png
deleted file mode 100644
index d6c37ef30cd..00000000000
--- a/doc/user/project/pages/img/remove_pages.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/pages/img/remove_pages_v15_3.png b/doc/user/project/pages/img/remove_pages_v15_3.png
new file mode 100644
index 00000000000..f740daf5c0b
--- /dev/null
+++ b/doc/user/project/pages/img/remove_pages_v15_3.png
Binary files differ
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 1ea7500273e..3bd16a17f23 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -74,7 +74,7 @@ to your project's settings through the gear icon in the top right, and then
navigating to **Pages**. Select the **Remove pages** button to delete your Pages
website.
-![Remove pages](img/remove_pages.png)
+![Remove pages](img/remove_pages_v15_3.png)
## Subdomains of subdomains
@@ -297,9 +297,6 @@ A 404 can also be related to incorrect permissions. If [Pages Access Control](pa
navigates to the Pages URL and receives a 404 response, it is possible that the user does not have permission to view the site.
To fix this, verify that the user is a member of the project.
-For Geo instances, 404 errors on Pages occur after promoting a secondary to a primary.
-Find more details in the [Pages administration documentation](../../../administration/pages/index.md#404-error-after-promoting-a-geo-secondary-to-a-primary-node)
-
### 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)
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index eb897c176fa..e6446c34bf0 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Pages access control **(FREE)**
-> Available on GitLab.com in GitLab 12.4.
-
You can enable Pages access control on your project
if your administrator has [enabled the access control feature](../../../administration/pages/index.md#access-control)
on your GitLab instance. When enabled, only authenticated
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index 6ef8477b6b6..d02609cbdc7 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -95,15 +95,15 @@ git push -o merge_request.create -o merge_request.target=my-target-branch -o mer
## Useful Git aliases
As shown above, Git push options can cause Git commands to grow very long. If
-you use the same push options frequently, it's useful to create [Git
-aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases). Git aliases
+you use the same push options frequently, it's useful to create
+[Git aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases). Git aliases
are command line shortcuts for Git which can significantly simplify the use of
long Git commands.
### Merge when pipeline succeeds alias
-To set up a Git alias for the [merge when pipeline succeeds Git push
-option](#push-options-for-merge-requests):
+To set up a Git alias for the
+[merge when pipeline succeeds Git push option](#push-options-for-merge-requests):
```shell
git config --global alias.mwps "push -o merge_request.create -o merge_request.target=master -o merge_request.merge_when_pipeline_succeeds"
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 96e51b061ee..216d040734d 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -56,6 +56,7 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users as reviewers. |
| `/assign_reviewer me` or `/reviewer me` or `/request_review me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself as a reviewer. |
| `/award :emoji:` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Toggle emoji award. |
+| `/cc @user` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Mention a user. In GitLab 15.0 and later, this command performs no action. You can instead type `CC @user` or only `@user`. [In GitLab 14.9 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/31200), mentioning a user at the start of a line created a specific type of to-do item notification. |
| `/child_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Add child epic to `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7330) in GitLab 12.0). |
| `/clear_health_status` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Clear [health status](issues/managing_issues.md#health-status) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213814) in GitLab 14.7). |
| `/clear_weight` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Clear weight. |
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 1d448ca5c94..d3456e086ce 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -32,12 +32,10 @@ When you create a release, or after, you can:
- Add release notes.
- Add a message for the Git tag associated with the release.
- [Associate milestones with it](#associate-milestones-with-a-release).
-- Attach [release assets](#release-assets), like runbooks or packages.
+- Attach [release assets](release_fields.md#release-assets), like runbooks or packages.
## View releases
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36667) in GitLab 12.8.
-
To view a list of releases:
- On the left sidebar, select **Deployments > Releases**, or
@@ -81,18 +79,18 @@ To create a release in the Releases page:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Deployments > Releases** and select **New release**.
-1. From the [**Tag name**](#tag-name) dropdown, either:
+1. From the [**Tag name**](release_fields.md#tag-name) dropdown, either:
- Select an existing Git tag. Selecting an existing tag that is already associated with a release
results in a validation error.
- Enter a new Git tag name.
1. From the **Create from** dropdown, select a branch or commit SHA to use when creating the
new tag.
1. Optional. Enter additional information about the release, including:
- - [Title](#title).
+ - [Title](release_fields.md#title).
- [Milestones](#associate-milestones-with-a-release).
- - [Release notes](#release-notes-description).
+ - [Release notes](release_fields.md#release-notes-description).
- Whether or not to include the [Tag message](../../../topics/git/tags.md).
- - [Asset links](#links).
+ - [Asset links](release_fields.md#links).
1. Select **Create release**.
### Create a release in the Tags page
@@ -126,99 +124,8 @@ You can create a release directly as part of the GitLab CI/CD pipeline by using
The release is created only if the job processes without error. If the API returns an error during
release creation, the release job fails.
-Methods for creating a release using a CI/CD job include:
-
-- Create a release when a Git tag is created.
-- Create a release when a commit is merged to the default branch.
-
-#### Create a release when a Git tag is created
-
-In this CI/CD example, pushing a Git tag to the repository, or creating a Git tag in the UI triggers
-the release. You can use this method if you prefer to create the Git tag manually, and create a
-release as a result.
-
-NOTE:
-Do not provide Release notes when you create the Git tag in the UI. Providing release notes
-creates a release, resulting in the pipeline failing.
-
-Key points in the following _extract_ of an example `.gitlab-ci.yml` file:
-
-- The `rules` stanza defines when the job is added to the pipeline.
-- The Git tag is used in the release's name and description.
-
-```yaml
-release_job:
- stage: release
- image: registry.gitlab.com/gitlab-org/release-cli:latest
- rules:
- - if: $CI_COMMIT_TAG # Run this job when a tag is created
- script:
- - echo "running release_job"
- release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
- tag_name: '$CI_COMMIT_TAG'
- description: '$CI_COMMIT_TAG'
-```
-
-#### Create a release when a commit is merged to the default branch
-
-In this CI/CD example, merging a commit to the default branch triggers the pipeline. You can use
-this method if your release workflow does not create a tag manually.
-
-Key points in the following _extract_ of an example `.gitlab-ci.yml` file:
-
-- The Git tag, description, and reference are created automatically in the pipeline.
-- If you manually create a tag, the `release_job` job does not run.
-
-```yaml
-release_job:
- stage: release
- image: registry.gitlab.com/gitlab-org/release-cli:latest
- rules:
- - if: $CI_COMMIT_TAG
- when: never # Do not run this job when a tag is created manually
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
- script:
- - echo "running release_job for $TAG"
- release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
- tag_name: 'v0.$CI_PIPELINE_IID' # The version is incremented per pipeline.
- description: 'v0.$CI_PIPELINE_IID'
- ref: '$CI_COMMIT_SHA' # The tag is created from the pipeline SHA.
-```
-
-NOTE:
-Environment variables set in `before_script` or `script` are not available for expanding
-in the same job. Read more about
-[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
-
-#### Skip multiple pipelines when creating a release
-
-Creating a release using a CI/CD job could potentially trigger multiple pipelines if the associated tag does not exist already. To understand how this might happen, consider the following workflows:
-
-- Tag first, release second:
- 1. A tag is created via UI or pushed.
- 1. A tag pipeline is triggered, and runs `release` job.
- 1. A release is created.
-
-- Release first, tag second:
- 1. A pipeline is triggered when commits are pushed or merged to default branch. The pipeline runs `release` job.
- 1. A release is created.
- 1. A tag is created.
- 1. A tag pipeline is triggered. The pipeline also runs `release` job.
-
-In the second workflow, the `release` job runs in multiple pipelines. To prevent this, you can use the [`workflow:rules` keyword](../../../ci/yaml/index.md#workflowrules) to determine if a release job should run in a tag pipeline:
-
-```yaml
-release_job:
- rules:
- - if: $CI_COMMIT_TAG
- when: never # Do not run this job in a tag pipeline
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
- script:
- - echo "Create release"
- release:
- name: 'My awesome release'
- tag_name: '$CI_COMMIT_TAG'
-```
+For examples of how you can create a release of your application in the CI/CD pipeline,
+see [Release CI/CD examples](release_cicd_examples.md).
### Use a custom SSL CA certificate authority
@@ -250,18 +157,6 @@ The `ADDITIONAL_CA_CERT_BUNDLE` value can also be configured as a
either as a `file`, which requires the path to the certificate, or as a variable,
which requires the text representation of the certificate.
-### `release-cli` command line
-
-The entries under the `release` node are transformed into Bash commands and sent
-to the Docker container, which contains the [release-cli](https://gitlab.com/gitlab-org/release-cli).
-You can also call the `release-cli` directly from a `script` entry.
-
-For example, if you use the YAML described previously:
-
-```shell
-release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\"}
-```
-
### Create multiple releases in a single pipeline
A pipeline can have multiple `release` jobs, for example:
@@ -298,10 +193,17 @@ release tag. When the `released_at` date and time has passed, the badge is autom
![An upcoming release](img/upcoming_release_v12_7.png)
-## Edit a release
+## Historical releases
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199429) in GitLab 15.2.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) in GitLab 12.6.
-> - Asset link editing [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9427) in GitLab 12.10.
+You can create a release in the past using either the
+[Releases API](../../../api/releases/index.md#historical-releases) or the UI. When you set
+a past `released_at` date, an **Historical release** badge is displayed next to
+the release tag. Due to being released in the past, [release evidence](#release-evidence)
+is not available.
+
+## Edit a release
Only users with at least the Developer role can edit releases.
Read more about [Release permissions](#release-permissions).
@@ -430,277 +332,6 @@ complete overlapping period.
For more information, see [Deployment safety](../../../ci/environments/deployment_safety.md).
-## Release fields
-
-The following fields are available when you create or edit a release.
-
-### Title
-
-The release title can be customized using the **Release title** field when
-creating or editing a release. If no title is provided, the release's tag name
-is used instead.
-
-### Tag name
-
-The release tag name should include the release version. GitLab uses [Semantic Versioning](https://semver.org/)
-for our releases, and we recommend you do too. Use `(Major).(Minor).(Patch)`, as detailed in the
-[GitLab Policy for Versioning](../../../policy/maintenance.md#versioning).
-
-For example, for GitLab version `10.5.7`:
-
-- `10` represents the major version. The major release was `10.0.0`, but often referred to as `10.0`.
-- `5` represents the minor version. The minor release was `10.5.0`, but often referred to as `10.5`.
-- `7` represents the patch number.
-
-Any part of the version number can be multiple digits, for example, `13.10.11`.
-
-### Release notes description
-
-Every release has a description. You can add any text you like, but we recommend
-including a changelog to describe the content of your release. This helps users
-quickly scan the differences between each release you publish.
-
-[Git's tagging messages](https://git-scm.com/book/en/v2/Git-Basics-Tagging) can
-be included in Release note descriptions by selecting **Include tag message in
-the release notes**.
-
-Description supports [Markdown](../../markdown.md).
-
-### Release assets
-
-A release contains the following types of assets:
-
-- [Source code](#source-code)
-- [Link](#links)
-
-#### Source code
-
-GitLab automatically generates `zip`, `tar.gz`, `tar.bz2`, and `tar`
-archived source code from the given Git tag. These are read-only assets.
-
-#### Links
-
-A link is any URL which can point to whatever you like: documentation, built
-binaries, or other related materials. These can be both internal or external
-links from your GitLab instance.
-Each link as an asset has the following attributes:
-
-| Attribute | Description | Required |
-| ---- | ----------- | --- |
-| `name` | The name of the link. | Yes |
-| `url` | The URL to download a file. | Yes |
-| `filepath` | The redirect link to the `url`. See [this section](#permanent-links-to-release-assets) for more information. | No |
-| `link_type` | The content kind of what users can download via `url`. See [this section](#link-types) for more information. | No |
-
-##### Permanent link to latest release
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16821) in GitLab 14.9.
-
-Latest release page is accessible through a permanent URL.
-GitLab will redirect to the latest release page URL when it is visited.
-
-The format of the URL is:
-
-```plaintext
-https://host/namespace/project/-/releases/permalink/latest
-```
-
-We also support, suffix path carry forward on the redirect to the latest release.
-Example if release `v14.8.0-ee` is the latest release and has a readable link `https://host/namespace/project/-/releases/v14.8.0-ee#release` then it can be addressed as `https://host/namespace/project/-/releases/permalink/latest#release`.
-
-Refer [permanent links to latest release assets](#permanent-links-to-latest-release-assets) section to understand more about the suffix path carry forward usage.
-
-###### Sorting preferences
-
-By default, GitLab fetches the release using `released_at` time. The use of the query parameter `?order_by=released_at` is optional, and support for `?order_by=semver` is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352945).
-
-##### Permanent links to release assets
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27300) in GitLab 12.9.
-
-The assets associated with a release are accessible through a permanent URL.
-GitLab always redirects this URL to the actual asset
-location, so even if the assets move to a different location, you can continue
-to use the same URL. This is defined during [link creation](../../../api/releases/links.md#create-a-link) or [updating](../../../api/releases/links.md#update-a-link) using the `filepath` API attribute.
-
-The format of the URL is:
-
-```plaintext
-https://host/namespace/project/-/releases/:release/downloads/:filepath
-```
-
-If you have an asset for the `v11.9.0-rc2` release in the `gitlab-org`
-namespace and `gitlab-runner` project on `gitlab.com`, for example:
-
-```json
-{
- "name": "linux amd64",
- "filepath": "/binaries/gitlab-runner-linux-amd64",
- "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64",
- "link_type": "other"
-}
-```
-
-This asset has a direct link of:
-
-```plaintext
-https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64
-```
-
-The physical location of the asset can change at any time and the direct link remains unchanged.
-
-##### Permanent links to latest release assets
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16821) in GitLab 14.9.
-
-The `filepath` from [permanent links to release assets](#permanent-links-to-release-assets) can be used in combination with [permanent link to the latest release](#permanent-link-to-latest-release). It is useful when we want to link a permanent URL to download an asset from the *latest release*.
-
-The format of the URL is:
-
-```plaintext
-https://host/namespace/project/-/releases/permalink/latest/downloads/:filepath
-```
-
-If you have an asset with [`filepath`](../../../api/releases/links.md#create-a-link) for the `v11.9.0-rc2` latest release in the `gitlab-org`
-namespace and `gitlab-runner` project on `gitlab.com`, for example:
-
-```json
-{
- "name": "linux amd64",
- "filepath": "/binaries/gitlab-runner-linux-amd64",
- "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64",
- "link_type": "other"
-}
-```
-
-This asset has a direct link of:
-
-```plaintext
-https://gitlab.com/gitlab-org/gitlab-runner/-/releases/permalink/latest/downloads/binaries/gitlab-runner-linux-amd64
-```
-
-##### Link Types
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207257) in GitLab 13.1.
-
-The four types of links are "Runbook," "Package," "Image," and "Other."
-The `link_type` parameter accepts one of the following four values:
-
-- `runbook`
-- `package`
-- `image`
-- `other` (default)
-
-This field has no effect on the URL and it's only used for visual purposes in the Releases page of your project.
-
-##### Use a generic package for attaching binaries
-
-You can use [generic packages](../../packages/generic_packages/index.md)
-to store any artifacts from a release or tag pipeline,
-that can also be used for attaching binary files to an individual release entry.
-You basically need to:
-
-1. [Push the artifacts to the Generic Package Registry](../../packages/generic_packages/index.md#publish-a-package-file).
-1. [Attach the package link to the release](#links).
-
-The following example generates release assets, publishes them
-as a generic package, and then creates a release:
-
-```yaml
-stages:
- - build
- - upload
- - release
-
-variables:
- # Package version can only contain numbers (0-9), and dots (.).
- # Must be in the format of X.Y.Z, i.e. should match /\A\d+\.\d+\.\d+\z/ regular expresion.
- # See https://docs.gitlab.com/ee/user/packages/generic_packages/#publish-a-package-file
- PACKAGE_VERSION: "1.2.3"
- DARWIN_AMD64_BINARY: "myawesomerelease-darwin-amd64-${PACKAGE_VERSION}"
- LINUX_AMD64_BINARY: "myawesomerelease-linux-amd64-${PACKAGE_VERSION}"
- PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/myawesomerelease/${PACKAGE_VERSION}"
-
-build:
- stage: build
- image: alpine:latest
- rules:
- - if: $CI_COMMIT_TAG
- script:
- - mkdir bin
- - echo "Mock binary for ${DARWIN_AMD64_BINARY}" > bin/${DARWIN_AMD64_BINARY}
- - echo "Mock binary for ${LINUX_AMD64_BINARY}" > bin/${LINUX_AMD64_BINARY}
- artifacts:
- paths:
- - bin/
-
-upload:
- stage: upload
- image: curlimages/curl:latest
- rules:
- - if: $CI_COMMIT_TAG
- script:
- - |
- curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/${DARWIN_AMD64_BINARY} "${PACKAGE_REGISTRY_URL}/${DARWIN_AMD64_BINARY}"
- - |
- curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/${LINUX_AMD64_BINARY} "${PACKAGE_REGISTRY_URL}/${LINUX_AMD64_BINARY}"
-
-release:
- # Caution, as of 2021-02-02 these assets links require a login, see:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/299384
- stage: release
- image: registry.gitlab.com/gitlab-org/release-cli:latest
- rules:
- - if: $CI_COMMIT_TAG
- script:
- - |
- release-cli create --name "Release $CI_COMMIT_TAG" --tag-name $CI_COMMIT_TAG \
- --assets-link "{\"name\":\"${DARWIN_AMD64_BINARY}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${DARWIN_AMD64_BINARY}\"}" \
- --assets-link "{\"name\":\"${LINUX_AMD64_BINARY}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${LINUX_AMD64_BINARY}\"}"
-```
-
-PowerShell users may need to escape the double quote `"` inside a JSON
-string with a `` ` `` (back tick) for `--assets-link` and `ConvertTo-Json`
-before passing on to the `release-cli`.
-For example:
-
-```yaml
-release:
- script:
- - $env:asset = "{`"name`":`"MyFooAsset`",`"url`":`"https://gitlab.com/upack/artifacts/download/$env:UPACK_GROUP/$env:UPACK_NAME/$($env:GitVersion_SemVer)?contentOnly=zip`"}"
- - $env:assetjson = $env:asset | ConvertTo-Json
- - release-cli create --name $CI_COMMIT_TAG --description "Release $CI_COMMIT_TAG" --ref $CI_COMMIT_TAG --tag-name $CI_COMMIT_TAG --assets-link=$env:assetjson
-```
-
-NOTE:
-Directly attaching [job artifacts](../../../ci/pipelines/job_artifacts.md)
-links to a release is not recommended, because artifacts are ephemeral and
-are used to pass data in the same pipeline. This means there's a risk that
-they could either expire or someone might manually delete them.
-
-#### Number of new and total features **(FREE SAAS)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235618) in GitLab 13.5.
-
-On [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/releases), you can view the number of new and total features in the project.
-
-![Feature count](img/feature_count_v14_6.png "Number of features in a release")
-
-The totals are displayed on [shields](https://shields.io/) and are generated per release by
-[a Rake task in the `www-gitlab-com` repository](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/lib/tasks/update_gitlab_project_releases_page.rake).
-
-| Item | Formula |
-| ------ | ------ |
-| `New features` | Total count of release posts across all tiers for a single release in the project. |
-| `Total features` | Total count of release posts in reverse order for all releases in the project. |
-
-The counts are also shown by license tier.
-
-| Item | Formula |
-| ------ | ------ |
-| `New features` | Total count of release posts across a single tier for a single release in the project. |
-| `Total features` | Total count of release posts across a single tier in reverse order for all releases in the project. |
-
## Release evidence
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.6.
@@ -828,10 +459,11 @@ keyword. Learn more in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issue
In the API:
-- If you specify a future `released_at` date, the release becomes an **Upcoming Release**
+- If you specify a future `released_at` date, the release becomes an **Upcoming release**
and the evidence is collected on the date of the release. You cannot collect
release evidence before then.
-- If you use a past `released_at` date, no evidence is collected.
+- If you specify a past `released_at` date, the release becomes an **Historical
+ release** and no evidence is collected.
- If you do not specify a `released_at` date, release evidence is collected on the
date the release is created.
@@ -848,7 +480,7 @@ In the API:
- Users with the Guest role
have read and download access to the project releases.
This includes associated Git-tag-names, release description, author information of the releases.
- However, other repository-related information, such as [source code](#source-code), [release evidence](#release-evidence) are redacted.
+ However, other repository-related information, such as [source code](release_fields.md#source-code), [release evidence](#release-evidence) are redacted.
### Create, update, and delete a release and its assets
@@ -862,19 +494,6 @@ users with at least the Maintainer role
to create, update, and delete releases by protecting the tag with a wildcard (`*`),
and set **Maintainer** in the **Allowed to create** column.
-## Release Command Line
-
-> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/6) in GitLab 12.10.
-
-The Release CLI is a command-line tool for managing GitLab Releases from the command line or from
-the GitLab CI/CD configuration file, `.gitlab-ci.yml`.
-
-With it, you can create, update, modify, and delete releases right through the
-terminal.
-
-Read the [Release CLI documentation](https://gitlab.com/gitlab-org/release-cli/-/blob/master/docs/index.md)
-for details.
-
## Release Metrics **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259703) in GitLab Premium 13.9.
diff --git a/doc/user/project/releases/release_cicd_examples.md b/doc/user/project/releases/release_cicd_examples.md
new file mode 100644
index 00000000000..f1d3e55a707
--- /dev/null
+++ b/doc/user/project/releases/release_cicd_examples.md
@@ -0,0 +1,100 @@
+---
+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
+---
+
+# Release CI/CD examples
+
+GitLab release functionality is flexible, able to be configured to match your workflow. This page
+features example CI/CD release jobs. Each example demonstrates a method of creating a release in a
+CI/CD pipeline.
+
+## Create a release when a Git tag is created
+
+In this CI/CD example, pushing a Git tag to the repository, or creating a Git tag in the UI triggers
+the release. You can use this method if you prefer to create the Git tag manually, and create a
+release as a result.
+
+NOTE:
+Do not provide Release notes when you create the Git tag in the UI. Providing release notes
+creates a release, resulting in the pipeline failing.
+
+Key points in the following _extract_ of an example `.gitlab-ci.yml` file:
+
+- The `rules` stanza defines when the job is added to the pipeline.
+- The Git tag is used in the release's name and description.
+
+```yaml
+release_job:
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG # Run this job when a tag is created
+ script:
+ - echo "running release_job"
+ release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
+ tag_name: '$CI_COMMIT_TAG'
+ description: '$CI_COMMIT_TAG'
+```
+
+## Create a release when a commit is merged to the default branch
+
+In this CI/CD example, merging a commit to the default branch triggers the pipeline. You can use
+this method if your release workflow does not create a tag manually.
+
+Key points in the following _extract_ of an example `.gitlab-ci.yml` file:
+
+- The Git tag, description, and reference are created automatically in the pipeline.
+- If you manually create a tag, the `release_job` job does not run.
+
+```yaml
+release_job:
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG
+ when: never # Do not run this job when a tag is created manually
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
+ script:
+ - echo "running release_job for $TAG"
+ release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
+ tag_name: 'v0.$CI_PIPELINE_IID' # The version is incremented per pipeline.
+ description: 'v0.$CI_PIPELINE_IID'
+ ref: '$CI_COMMIT_SHA' # The tag is created from the pipeline SHA.
+```
+
+NOTE:
+Environment variables set in `before_script` or `script` are not available for expanding
+in the same job. Read more about
+[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
+
+## Skip multiple pipelines when creating a release
+
+Creating a release using a CI/CD job could potentially trigger multiple pipelines if the associated tag does not exist already. To understand how this might happen, consider the following workflows:
+
+- Tag first, release second:
+ 1. A tag is created via UI or pushed.
+ 1. A tag pipeline is triggered, and runs `release` job.
+ 1. A release is created.
+
+- Release first, tag second:
+ 1. A pipeline is triggered when commits are pushed or merged to default branch. The pipeline runs `release` job.
+ 1. A release is created.
+ 1. A tag is created.
+ 1. A tag pipeline is triggered. The pipeline also runs `release` job.
+
+In the second workflow, the `release` job runs in multiple pipelines. To prevent this, you can use the [`workflow:rules` keyword](../../../ci/yaml/index.md#workflowrules) to determine if a release job should run in a tag pipeline:
+
+```yaml
+release_job:
+ rules:
+ - if: $CI_COMMIT_TAG
+ when: never # Do not run this job in a tag pipeline
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
+ script:
+ - echo "Create release"
+ release:
+ name: 'My awesome release'
+ tag_name: '$CI_COMMIT_TAG'
+```
diff --git a/doc/user/project/releases/release_cli.md b/doc/user/project/releases/release_cli.md
index b55f0b0a734..9e65ab4bc01 100644
--- a/doc/user/project/releases/release_cli.md
+++ b/doc/user/project/releases/release_cli.md
@@ -4,16 +4,38 @@ group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Install the `release-cli` for the Shell executor **(FREE)**
+
+# GitLab Release CLI tool
+
+The [GitLab Release CLI (`release-cli`)](https://gitlab.com/gitlab-org/release-cli) tool
+is a command-line tool for managing releases from the command line or from a CI/CD pipeline.
+You can use the release CLI to create, update, modify, and delete releases.
+
+When you [use a CI/CD job to create a release](index.md#creating-a-release-by-using-a-cicd-job),
+the `release` keyword entries are transformed into Bash commands and sent to the Docker
+container containing the `release-cli` tool. The tool then creates the release.
+
+You can also call the `release-cli` tool directly from a [`script`](../../../ci/yaml/index.md#script).
+For example:
+
+```shell
+release-cli create --name "Release $CI_COMMIT_SHA" --description \
+ "Created using the release-cli $EXTRA_DESCRIPTION" \
+ --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" \
+ --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" \
+ --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\"}
+```
+
+## Install the `release-cli` for the Shell executor **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
-> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108) in GitLab 14.2, the `release-cli` binaries are also [available in the Package Registry](https://gitlab.com/jaime/release-cli/-/packages).
+> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108) in GitLab 14.2, the `release-cli` binaries are also [available in the Package Registry](https://gitlab.com/gitlab-org/release-cli/-/packages).
When you use a runner with the Shell executor, you can download and install
the `release-cli` manually for your [supported OS and architecture](https://release-cli-downloads.s3.amazonaws.com/latest/index.html).
Once installed, [the `release` keyword](../../../ci/yaml/index.md#release) is available to use in your CI/CD jobs.
-## Install on Unix/Linux
+### Install on Unix/Linux
1. Download the binary for your system from S3, in the following example for amd64 systems:
@@ -41,7 +63,7 @@ Once installed, [the `release` keyword](../../../ci/yaml/index.md#release) is av
release-cli version 0.6.0
```
-## Install on Windows PowerShell
+### Install on Windows PowerShell
1. Create a folder somewhere in your system, for example `C:\GitLab\Release-CLI\bin`
diff --git a/doc/user/project/releases/release_fields.md b/doc/user/project/releases/release_fields.md
new file mode 100644
index 00000000000..647cac9c38e
--- /dev/null
+++ b/doc/user/project/releases/release_fields.md
@@ -0,0 +1,274 @@
+---
+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
+---
+
+# Release fields
+
+The following fields are available when you create or edit a release.
+
+## Title
+
+The release title can be customized using the **Release title** field when
+creating or editing a release. If no title is provided, the release's tag name
+is used instead.
+
+## Tag name
+
+The release tag name should include the release version. GitLab uses [Semantic Versioning](https://semver.org/)
+for our releases, and we recommend you do too. Use `(Major).(Minor).(Patch)`, as detailed in the
+[GitLab Policy for Versioning](../../../policy/maintenance.md#versioning).
+
+For example, for GitLab version `10.5.7`:
+
+- `10` represents the major version. The major release was `10.0.0`, but often referred to as `10.0`.
+- `5` represents the minor version. The minor release was `10.5.0`, but often referred to as `10.5`.
+- `7` represents the patch number.
+
+Any part of the version number can be multiple digits, for example, `13.10.11`.
+
+## Release notes description
+
+Every release has a description. You can add any text you like, but we recommend
+including a changelog to describe the content of your release. This helps users
+quickly scan the differences between each release you publish.
+
+[Git's tagging messages](https://git-scm.com/book/en/v2/Git-Basics-Tagging) can
+be included in Release note descriptions by selecting **Include tag message in
+the release notes**.
+
+Description supports [Markdown](../../markdown.md).
+
+## Release assets
+
+A release contains the following types of assets:
+
+- [Source code](#source-code)
+- [Link](#links)
+
+### Source code
+
+GitLab automatically generates `zip`, `tar.gz`, `tar.bz2`, and `tar`
+archived source code from the given Git tag. These are read-only assets.
+
+### Links
+
+A link is any URL which can point to whatever you like: documentation, built
+binaries, or other related materials. These can be both internal or external
+links from your GitLab instance.
+Each link as an asset has the following attributes:
+
+| Attribute | Description | Required |
+|-------------|--------------------------------------------------------------------------------------------------------------|----------|
+| `name` | The name of the link. | Yes |
+| `url` | The URL to download a file. | Yes |
+| `filepath` | The redirect link to the `url`. See [this section](#permanent-links-to-release-assets) for more information. | No |
+| `link_type` | The content kind of what users can download via `url`. See [this section](#link-types) for more information. | No |
+
+#### Permanent link to latest release
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16821) in GitLab 14.9.
+
+Latest release page is accessible through a permanent URL.
+GitLab redirects to the latest release page URL when it is visited.
+
+The format of the URL is:
+
+```plaintext
+https://host/namespace/project/-/releases/permalink/latest
+```
+
+We also support, suffix path carry forward on the redirect to the latest release.
+Example if release `v14.8.0-ee` is the latest release and has a readable link `https://host/namespace/project/-/releases/v14.8.0-ee#release` then it can be addressed as `https://host/namespace/project/-/releases/permalink/latest#release`.
+
+Refer [permanent links to latest release assets](#permanent-links-to-latest-release-assets) section to understand more about the suffix path carry forward usage.
+
+##### Sorting preferences
+
+By default, GitLab fetches the release using `released_at` time. The use of the query parameter `?order_by=released_at` is optional, and support for `?order_by=semver` is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/352945).
+
+#### Permanent links to release assets
+
+The assets associated with a release are accessible through a permanent URL.
+GitLab always redirects this URL to the actual asset
+location, so even if the assets move to a different location, you can continue
+to use the same URL. This is defined during [link creation](../../../api/releases/links.md#create-a-link) or [updating](../../../api/releases/links.md#update-a-link) using the `filepath` API attribute.
+
+The format of the URL is:
+
+```plaintext
+https://host/namespace/project/-/releases/:release/downloads/:filepath
+```
+
+If you have an asset for the `v11.9.0-rc2` release in the `gitlab-org`
+namespace and `gitlab-runner` project on `gitlab.com`, for example:
+
+```json
+{
+ "name": "linux amd64",
+ "filepath": "/binaries/gitlab-runner-linux-amd64",
+ "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64",
+ "link_type": "other"
+}
+```
+
+This asset has a direct link of:
+
+```plaintext
+https://gitlab.com/gitlab-org/gitlab-runner/-/releases/v11.9.0-rc2/downloads/binaries/gitlab-runner-linux-amd64
+```
+
+The physical location of the asset can change at any time and the direct link remains unchanged.
+
+#### Permanent links to latest release assets
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16821) in GitLab 14.9.
+
+The `filepath` from [permanent links to release assets](#permanent-links-to-release-assets) can be used in combination with [permanent link to the latest release](#permanent-link-to-latest-release). It is useful when we want to link a permanent URL to download an asset from the *latest release*.
+
+The format of the URL is:
+
+```plaintext
+https://host/namespace/project/-/releases/permalink/latest/downloads/:filepath
+```
+
+If you have an asset with [`filepath`](../../../api/releases/links.md#create-a-link) for the `v11.9.0-rc2` latest release in the `gitlab-org`
+namespace and `gitlab-runner` project on `gitlab.com`, for example:
+
+```json
+{
+ "name": "linux amd64",
+ "filepath": "/binaries/gitlab-runner-linux-amd64",
+ "url": "https://gitlab-runner-downloads.s3.amazonaws.com/v11.9.0-rc2/binaries/gitlab-runner-linux-amd64",
+ "link_type": "other"
+}
+```
+
+This asset has a direct link of:
+
+```plaintext
+https://gitlab.com/gitlab-org/gitlab-runner/-/releases/permalink/latest/downloads/binaries/gitlab-runner-linux-amd64
+```
+
+#### Link Types
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207257) in GitLab 13.1.
+
+The four types of links are "Runbook," "Package," "Image," and "Other."
+The `link_type` parameter accepts one of the following four values:
+
+- `runbook`
+- `package`
+- `image`
+- `other` (default)
+
+This field has no effect on the URL and it's only used for visual purposes in the Releases page of your project.
+
+#### Use a generic package for attaching binaries
+
+You can use [generic packages](../../packages/generic_packages/index.md)
+to store any artifacts from a release or tag pipeline,
+that can also be used for attaching binary files to an individual release entry.
+You basically need to:
+
+1. [Push the artifacts to the Generic Package Registry](../../packages/generic_packages/index.md#publish-a-package-file).
+1. [Attach the package link to the release](#links).
+
+The following example generates release assets, publishes them
+as a generic package, and then creates a release:
+
+```yaml
+stages:
+ - build
+ - upload
+ - release
+
+variables:
+ # Package version can only contain numbers (0-9), and dots (.).
+ # Must be in the format of X.Y.Z, i.e. should match /\A\d+\.\d+\.\d+\z/ regular expresion.
+ # See https://docs.gitlab.com/ee/user/packages/generic_packages/#publish-a-package-file
+ PACKAGE_VERSION: "1.2.3"
+ DARWIN_AMD64_BINARY: "myawesomerelease-darwin-amd64-${PACKAGE_VERSION}"
+ LINUX_AMD64_BINARY: "myawesomerelease-linux-amd64-${PACKAGE_VERSION}"
+ PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/myawesomerelease/${PACKAGE_VERSION}"
+
+build:
+ stage: build
+ image: alpine:latest
+ rules:
+ - if: $CI_COMMIT_TAG
+ script:
+ - mkdir bin
+ - echo "Mock binary for ${DARWIN_AMD64_BINARY}" > bin/${DARWIN_AMD64_BINARY}
+ - echo "Mock binary for ${LINUX_AMD64_BINARY}" > bin/${LINUX_AMD64_BINARY}
+ artifacts:
+ paths:
+ - bin/
+
+upload:
+ stage: upload
+ image: curlimages/curl:latest
+ rules:
+ - if: $CI_COMMIT_TAG
+ script:
+ - |
+ curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/${DARWIN_AMD64_BINARY} "${PACKAGE_REGISTRY_URL}/${DARWIN_AMD64_BINARY}"
+ - |
+ curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/${LINUX_AMD64_BINARY} "${PACKAGE_REGISTRY_URL}/${LINUX_AMD64_BINARY}"
+
+release:
+ # Caution, as of 2021-02-02 these assets links require a login, see:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/299384
+ stage: release
+ image: registry.gitlab.com/gitlab-org/release-cli:latest
+ rules:
+ - if: $CI_COMMIT_TAG
+ script:
+ - |
+ release-cli create --name "Release $CI_COMMIT_TAG" --tag-name $CI_COMMIT_TAG \
+ --assets-link "{\"name\":\"${DARWIN_AMD64_BINARY}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${DARWIN_AMD64_BINARY}\"}" \
+ --assets-link "{\"name\":\"${LINUX_AMD64_BINARY}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${LINUX_AMD64_BINARY}\"}"
+```
+
+PowerShell users may need to escape the double quote `"` inside a JSON
+string with a `` ` `` (back tick) for `--assets-link` and `ConvertTo-Json`
+before passing on to the `release-cli`.
+For example:
+
+```yaml
+release:
+ script:
+ - $env:asset = "{`"name`":`"MyFooAsset`",`"url`":`"https://gitlab.com/upack/artifacts/download/$env:UPACK_GROUP/$env:UPACK_NAME/$($env:GitVersion_SemVer)?contentOnly=zip`"}"
+ - $env:assetjson = $env:asset | ConvertTo-Json
+ - release-cli create --name $CI_COMMIT_TAG --description "Release $CI_COMMIT_TAG" --ref $CI_COMMIT_TAG --tag-name $CI_COMMIT_TAG --assets-link=$env:assetjson
+```
+
+NOTE:
+Directly attaching [job artifacts](../../../ci/pipelines/job_artifacts.md)
+links to a release is not recommended, because artifacts are ephemeral and
+are used to pass data in the same pipeline. This means there's a risk that
+they could either expire or someone might manually delete them.
+
+### Number of new and total features **(FREE SAAS)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235618) in GitLab 13.5.
+
+On [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/releases), you can view the number of new and total features in the project.
+
+![Feature count](img/feature_count_v14_6.png "Number of features in a release")
+
+The totals are displayed on [shields](https://shields.io/) and are generated per release by
+[a Rake task in the `www-gitlab-com` repository](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/lib/tasks/update_gitlab_project_releases_page.rake).
+
+| Item | Formula |
+|------------------|------------------------------------------------------------------------------------|
+| `New features` | Total count of release posts across all tiers for a single release in the project. |
+| `Total features` | Total count of release posts in reverse order for all releases in the project. |
+
+The counts are also shown by license tier.
+
+| Item | Formula |
+|------------------|-----------------------------------------------------------------------------------------------------|
+| `New features` | Total count of release posts across a single tier for a single release in the project. |
+| `Total features` | Total count of release posts across a single tier in reverse order for all releases in the project. |
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index 747da817195..3083ca5da3c 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -110,7 +110,7 @@ This setting applies only to each repository's default branch. To protect other
you must either:
- Configure [branch protection in the repository](../../../project/protected_branches.md).
-- Configure [branch protection for groups](../../../group/index.md#change-the-default-branch-protection-of-a-group).
+- Configure [branch protection for groups](../../../group/manage.md#change-the-default-branch-protection-of-a-group).
Administrators of self-managed instances can customize the initial default branch protection for projects hosted on that instance. Individual
groups and subgroups can override this instance-wide setting for their projects.
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index 85bea80f777..df75f19ea6c 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -26,7 +26,7 @@ To fork an existing project in GitLab:
1. On the project's home page, in the top right, select **{fork}** **Fork**:
![Fork this project](img/forking_workflow_fork_button_v13_10.png)
1. Optional. Edit the **Project name**.
-1. For **Project URL**, select the [namespace](../../group/index.md#namespaces)
+1. For **Project URL**, select the [namespace](../../namespace/index.md)
your fork should belong to.
1. Add a **Project slug**. This value becomes part of the URL to your fork.
It must be unique in the namespace.
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index a8937d4f705..8e1286548b9 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -232,7 +232,7 @@ When a repository path changes, GitLab handles the transition from the
old location to the new one with a redirect.
When you [rename a user](../../profile/index.md#change-your-username),
-[change a group path](../../group/index.md#change-a-groups-path), or [rename a repository](../settings/index.md#rename-a-repository):
+[change a group path](../../group/manage.md#change-a-groups-path), or [rename a repository](../settings/index.md#rename-a-repository):
- URLs for the namespace and everything under it, like projects, are
redirected to the new URLs.
diff --git a/doc/user/project/repository/managing_large_repositories.md b/doc/user/project/repository/managing_large_repositories.md
index 93b94ac0641..ba425ae3dc7 100644
--- a/doc/user/project/repository/managing_large_repositories.md
+++ b/doc/user/project/repository/managing_large_repositories.md
@@ -16,6 +16,8 @@ On this page we detail several best practices to improve performance with these
It's *strongly* recommended in any Git system that binary or blob files (for example, packages, audio, video, graphics, etc.) 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.
+To analyze if the repository has these sorts of objects, it's recommended to run [`git-sizer`](https://github.com/github/git-sizer) to get a detailed analysis. This tool shows in detail what makes up the repository as well as highlights any areas of concern.
+
Refer to the [Git LFS documentation for more information](../../../topics/git/lfs/index.md).
## Gitaly Pack Objects Cache
@@ -32,7 +34,7 @@ In these types of setups it's recommended that the GitLab environment used match
## Gitaly Cluster
-Gitaly Cluster can notably improve large repository performance as it holds multiple replicas of the repository across several nodes. As a result, Gitaly Cluster can load balance read requests against those repositories and is also fault tolerant.
+Gitaly Cluster can notably improve large repository performance as it holds multiple replicas of the repository across several nodes. As a result, Gitaly Cluster can load balance read requests against those repositories and is also fault-tolerant.
It's recommended for large repositories, however, Gitaly Cluster is a large solution with additional complexity of setup, and management. Refer to the [Gitaly Cluster documentation for more information](../../../administration/gitaly/index.md), specifically the [Before deploying Gitaly Cluster](../../../administration/gitaly/index.md#before-deploying-gitaly-cluster) section.
diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md
index 4537f8520cd..b08530c34b3 100644
--- a/doc/user/project/repository/mirror/index.md
+++ b/doc/user/project/repository/mirror/index.md
@@ -17,8 +17,8 @@ Subscribe to the issue to follow its progress.
Several mirroring methods exist:
-- [Push](push.md): for mirroring a GitLab repository to another location.
-- [Pull](pull.md): for mirroring a repository from another location to GitLab.
+- [Push](push.md): Mirror a repository from GitLab to another location.
+- [Pull](pull.md): Mirror a repository from another location to a GitLab Premium instance.
- [Bidirectional](bidirectional.md) mirroring is also available, but can cause conflicts.
Mirror a repository when:
@@ -113,6 +113,11 @@ GitLab supports these authentication methods:
- [SSH authentication](#ssh-authentication).
- Password.
+When using password authentication, ensure you specify the username.
+For a [project access token](../../settings/project_access_tokens.md) or
+[group access token](../../../group/settings/group_access_tokens.md),
+use the username (not token name) and the token as the password.
+
### SSH authentication
SSH authentication is mutual:
@@ -226,7 +231,7 @@ This error can occur when a firewall performs a `Deep SSH Inspection` on outgoin
### Could not read username: terminal prompts disabled
If you receive this error after creating a new project using
-[GitLab CI/CD for external repositories](../../../../ci/ci_cd_for_external_repos/):
+[GitLab CI/CD for external repositories](../../../../ci/ci_cd_for_external_repos/index.md):
- In Bitbucket Cloud:
diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md
index 88104e34eb4..d0f2b9a8088 100644
--- a/doc/user/project/repository/mirror/pull.md
+++ b/doc/user/project/repository/mirror/pull.md
@@ -28,6 +28,11 @@ local repository, GitLab stops updating the branch. This prevents data loss.
Deleted branches and tags in the upstream repository are not reflected in the
downstream repository.
+NOTE:
+Items deleted from the downstream pull mirror repository, but still in the upstream repository,
+are restored upon the next pull. For example: a branch deleted _only_ in the mirrored repository
+reappears after the next pull.
+
## How pull mirroring works
After you configure a GitLab repository as a pull mirror:
diff --git a/doc/user/project/repository/push_rules.md b/doc/user/project/repository/push_rules.md
index 592aff85434..46a9585604e 100644
--- a/doc/user/project/repository/push_rules.md
+++ b/doc/user/project/repository/push_rules.md
@@ -25,7 +25,7 @@ For custom push rules use [server hooks](../../../administration/server_hooks.md
## Enable global push rules
You can create push rules for all new projects to inherit, but they can be overridden
-at the project level or the [group level](../../group/index.md#group-push-rules).
+at the project level or the [group level](../../group/access_and_permissions.md#group-push-rules).
All projects created after you configure global push rules inherit this
configuration. However, each existing project must be updated manually, using the
process described in [Override global push rules per project](#override-global-push-rules-per-project).
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 b0ae1b7d1e0..344c288b607 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
@@ -46,8 +46,8 @@ To purge files from a GitLab repository:
[`git-sizer`](https://github.com/github/git-sizer#getting-started)
using a supported package manager or from source.
-1. Generate a fresh [export from the
- project](../settings/import_export.html#export-a-project-and-its-data) and download it.
+1. Generate a fresh
+ [export from the project](../settings/import_export.md#export-a-project-and-its-data) and download it.
This project export contains a backup copy of your repository *and* refs
we can use to purge files from your repository.
@@ -195,8 +195,8 @@ When using repository cleanup, note:
- Project statistics are cached. You may need to wait 5-10 minutes to see a reduction in storage utilization.
- The cleanup prunes loose objects older than 30 minutes. This means objects added or referenced in the last 30 minutes
- are not be removed immediately. If you have access to the
- [Gitaly](../../../administration/gitaly/index.md) server, you may slip that delay and run `git gc --prune=now` to
+ are not removed immediately. If you have access to the
+ [Gitaly](../../../administration/gitaly/index.md) server, you may skip that delay and run `git gc --prune=now` to
prune all loose objects immediately.
- This process removes some copies of the rewritten commits from the GitLab cache and database,
but there are still numerous gaps in coverage and some of the copies may persist indefinitely.
@@ -207,7 +207,7 @@ When using repository cleanup, note:
Repository size limits:
-- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings)
+- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings).
- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md) on self-managed instances.
- Are [set for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings).
diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md
index 17e55b7aac2..f32035102bb 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -307,8 +307,7 @@ In these issues, you can also see our friendly neighborhood [Support Bot](#suppo
### As an end user (issue creator)
-> Support for additional email headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346600) in GitLab 14.6.
-> In earlier versions, the Service Desk email address had to be in the "To" field.
+> Support for additional email headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346600) in GitLab 14.6. In earlier versions, the Service Desk email address had to be in the "To" field.
To create a Service Desk issue, an end user does not need to know anything about
the GitLab instance. They just send an email to the address they are given, and
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 7d1bfcaab59..b973a0f56d1 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -253,7 +253,7 @@ Use the toggles to enable or disable features in the project.
| **Security & Compliance** | ✓ | Control access to [security features](../../application_security/index.md). |
| **Wiki** | ✓ | Enables a separate system for [documentation](../wiki/). |
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md). |
-| **Pages** | ✓ | Allows you to [publish static websites](../pages/). |
+| **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). |
@@ -392,7 +392,7 @@ When you transfer a project to another namespace, you move the project to a diff
Prerequisites:
-- You must have at least the Maintainer role for the [group](../../group/index.md#create-a-group) to which you are transferring.
+- You must have at least the Maintainer role for the [group](../../group/manage.md#create-a-group) to which you are transferring.
- You must be the Owner of the project you transfer.
- The group must allow creation of new projects.
- The project must not contain any [container images](../../packages/container_registry/index.md#limitations).
@@ -447,15 +447,16 @@ in GitLab 12.6, and then to [immediate deletion](https://gitlab.com/gitlab-org/g
### Delayed project deletion **(PREMIUM)**
-> [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89466) in GitLab 15.1.
+> - [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89466) in GitLab 15.1.
+> - [Disabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95495) in GitLab 15.3.
-Projects can be deleted after a delay period. Multiple settings can affect whether
+Projects in a group (not a personal namespace) can be deleted after a delay period. Multiple settings can affect whether
delayed project deletion is enabled for a particular project:
- Self-managed instance [settings](../../admin_area/settings/visibility_and_access_controls.md#delayed-project-deletion).
You can enable delayed project deletion as the default setting for new groups, and configure the number of days for the
delay. For GitLab.com, see the [GitLab.com settings](../../gitlab_com/index.md#delayed-project-deletion).
-- Group [settings](../../group/index.md#enable-delayed-project-deletion) to enabled delayed project deletion for all
+- Group [settings](../../group/manage.md#enable-delayed-project-deletion) to enabled delayed project deletion for all
projects in the group.
### Delete a project immediately
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index facaba45aec..5a4e300a210 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -16,15 +16,18 @@ Use the <kbd>.</kbd> [keyboard shortcut](../../shortcuts.md) to open the Web IDE
You can also open the Web IDE when viewing a file, from the repository file list,
and from merge requests:
-- *When viewing a file, or the repository file list* -
+### When viewing a file or the repository file list
+
1. In the upper right corner of the page, select **Open in Web IDE** if it is visible.
1. If **Open in Web IDE** is not visible:
1. Select the (**{chevron-lg-down}**) next to **Edit** or **Gitpod**, depending on your configuration.
1. Select **Open in Web IDE** from the list to display it as the editing option.
1. Select **Open in Web IDE** to open the editor.
-- *When viewing a merge request* -
+
+### When viewing a merge request
+
1. Go to your merge request.
- 1. In the upper right corner, select **Code**, then select **Open in Gitpod**.
+ 1. In the upper right corner, select **Code > Open in Web IDE**.
## File finder
@@ -86,7 +89,7 @@ You can pick a theme from your [profile preferences](../../profile/preferences.m
## Highlight lines
-WebIDE is built with the [Web Editor](../repository/web_editor.md). This enables WebIDE to share the
+The Web IDE is built with the [Web Editor](../repository/web_editor.md). This enables the Web IDE to share the
same core features for highlighting and linking to particular lines in the edited files
[described for the Web Editor](../repository/web_editor.md#highlight-lines).
diff --git a/doc/user/project/wiki/group.md b/doc/user/project/wiki/group.md
index dc448fed970..a3ba5789d39 100644
--- a/doc/user/project/wiki/group.md
+++ b/doc/user/project/wiki/group.md
@@ -15,7 +15,7 @@ Group wikis are similar to [project wikis](index.md), with a few limitations:
- [Git LFS](../../../topics/git/lfs/index.md) is not supported.
- Group wikis are not included in [global search](../../search/advanced_search.md).
-- Changes to group wikis don't show up in the [group's activity feed](../../group/index.md#group-activity-analytics).
+- Changes to group wikis don't show up in the [group's activity feed](../../group/manage.md#group-activity-analytics).
- Group wikis are enabled by default for GitLab Premium and higher tiers.
You [can't turn them off from the GitLab user interface](https://gitlab.com/gitlab-org/gitlab/-/issues/208413).
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 6e320923496..c7f675417bb 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -6,6 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Wiki **(FREE)**
+> - Page loading [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/336792) to asynchronous in GitLab 14.9.
+> - Page slug encoding method [changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71753) to `ERB::Util.url_encode` in GitLab 14.9.
+
If you don't want to keep your documentation in your repository, but you want
to keep it in the same project as your code, you can use the wiki GitLab provides
in each GitLab project. Every wiki is a separate Git repository, so you can create
@@ -230,7 +233,7 @@ GitLab tracks wiki creation, deletion, and update events. These events are displ
- [User profile](../../profile/index.md#access-your-user-profile).
- Activity pages, depending on the type of wiki:
- - [Group activity](../../group/index.md#view-group-activity).
+ - [Group activity](../../group/manage.md#view-group-activity).
- [Project activity](../working_with_projects.md#view-project-activity).
Commits to wikis are not counted in [repository analytics](../../analytics/repository_analytics.md).
@@ -337,7 +340,7 @@ Support includes:
- List formatting for unordered, numbered, and checklists.
- Creating and editing the structure of tables.
- Inserting and formatting code blocks with syntax highlighting.
-- Live preview of Mermaid, PlantUML, and Kroki diagrams ([Introduced]<https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86701> in GitLab 15.2).
+- Live preview of Mermaid, PlantUML, and Kroki diagrams ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86701) in GitLab 15.2).
### Use the Content Editor
@@ -370,3 +373,35 @@ For the status of the ongoing development for CommonMark and GitLab Flavored Mar
- [Group repository storage moves API](../../../api/group_repository_storage_moves.md)
- [Group wikis API](../../../api/group_wikis.md)
- [Wiki keyboard shortcuts](../../shortcuts.md#wiki-pages)
+
+## Troubleshooting
+
+### Page slug rendering with Apache reverse proxy
+
+In GitLab 14.9 and later, page slugs are now encoded using the
+[`ERB::Util.url_encode`](https://www.rubydoc.info/stdlib/erb/ERB%2FUtil.url_encode) method.
+If you use an Apache reverse proxy, you can add a `nocanon` argument to the `ProxyPass`
+line of your Apache configuration to ensure your page slugs render correctly.
+
+### Recreate a project wiki with the Rails console **(FREE SELF)**
+
+WARNING:
+This operation deletes all data in the wiki.
+
+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).
+1. Run these commands:
+
+ ```ruby
+ # Enter your project's path
+ p = Project.find_by_full_path('<username-or-group>/<project-name>')
+
+ # This command deletes the wiki project from the filesystem.
+ GitlabShellWorker.perform_in(0, :remove_repository, p.repository_storage, p.wiki.disk_path)
+
+ # Refresh the wiki repository state.
+ p.wiki.repository.expire_exists_cache
+ ```
+
+All data from the wiki has been cleared, and the wiki is ready for use.
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index 9572bc241fc..2501fa8b45c 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -233,7 +233,7 @@ To push your repository and create a project:
```
- For `gitlab.example.com`, use the domain name of the machine that hosts your Git repository.
- - For `namespace`, use the name of your [namespace](../group/index.md#namespaces).
+ - For `namespace`, use the name of your [namespace](../namespace/index.md).
- For `myproject`, use the name of your project.
- Optional. To export existing repository tags, append the `--tags` flag to your `git push` command.
1. Optional. To configure the remote:
@@ -290,7 +290,7 @@ To view your personal projects:
## Delete a project
After you delete a project, projects in personal namespaces are deleted immediately. To delay deletion of projects in a group
-you can [enable delayed project removal](../group/index.md#enable-delayed-project-deletion).
+you can [enable delayed project removal](../group/manage.md#enable-delayed-project-deletion).
To delete a project:
@@ -310,7 +310,7 @@ To delete a project:
> - [Available to all users](https://gitlab.com/gitlab-org/gitlab/-/issues/346976) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `project_owners_list_project_pending_deletion`. Enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/351556) in GitLab 14.9. [Feature flag `project_owners_list_project_pending_deletion`](https://gitlab.com/gitlab-org/gitlab/-/issues/351556) removed.
-When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-deletion),
+When delayed project deletion is [enabled for a group](../group/manage.md#enable-delayed-project-deletion),
projects within that group are not deleted immediately, but only after a delay.
To view a list of all projects that are pending deletion:
@@ -371,7 +371,7 @@ To leave a project:
1. Select a project.
1. Select **Leave project**. The **Leave project** option only displays
on the project dashboard when a project is part of a group under a
-[group namespace](../group/index.md#namespaces).
+[group namespace](../namespace/index.md).
## Use a project as a Go package
diff --git a/doc/user/ssh.md b/doc/user/ssh.md
index e884d762379..5667890757a 100644
--- a/doc/user/ssh.md
+++ b/doc/user/ssh.md
@@ -304,8 +304,10 @@ Verify that your SSH key was added correctly.
The following commands use the example hostname `gitlab.example.com`. Replace this example hostname with your GitLab instance's hostname, for example, `git@gitlab.com`.
-1. For GitLab.com, to ensure you're connecting to the correct server, confirm the
- [SSH host keys fingerprints](gitlab_com/index.md#ssh-host-keys-fingerprints).
+1. To ensure you're connecting to the correct server, check the server's SSH host keys fingerprint. For:
+ - GitLab.com, see the [SSH host keys fingerprints](gitlab_com/index.md#ssh-host-keys-fingerprints) documentation.
+ - GitLab.com or another GitLab instance, see `gitlab.example.com/help/instance_configuration#ssh-host-keys-fingerprints` where `gitlab.example.com` is `gitlab.com` (for
+ GitLab.com) or the address of the GitLab instance.
1. Open a terminal and run this command, replacing `gitlab.example.com` with your
GitLab instance URL:
diff --git a/doc/user/tasks.md b/doc/user/tasks.md
index 36236f2969e..b5c2c4eb3a5 100644
--- a/doc/user/tasks.md
+++ b/doc/user/tasks.md
@@ -8,12 +8,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334812) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `work_items`. Disabled by default.
> - [Creating, editing, and deleting tasks](https://gitlab.com/groups/gitlab-org/-/epics/7169) introduced in GitLab 15.0.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/334812) in GitLab 15.3.
+
+WARNING:
+Tasks are in [**Alpha**](../policy/alpha-beta-support.md#alpha-features).
+
+The following list are the known limitations:
+
+- [Tasks currently cannot be accessed via REST API.](https://gitlab.com/gitlab-org/gitlab/-/issues/368055)
+- An issue's tasks can only currently be accessed via a reference within a description, comment, or direct URL (`.../-/work_items/[global_id]`).
+
+For the latest updates, check the [Tasks Roadmap](https://gitlab.com/groups/gitlab-org/-/epics/7103).
FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available,
-ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `work_items`.
-On GitLab.com, this feature is not available.
-The feature is not ready for production use.
+On self-managed GitLab, by default this feature is available. To hide the feature,
+ask an administrator to [disable the feature flags](../administration/feature_flags.md) named `work_items` and `work_items_hierarchy`.
+On GitLab.com, this feature is available.
Use tasks to track steps needed for the [issue](project/issues/index.md) to be closed.
diff --git a/doc/user/upgrade_email_bypass.md b/doc/user/upgrade_email_bypass.md
index 6401828270d..1b267a0569b 100644
--- a/doc/user/upgrade_email_bypass.md
+++ b/doc/user/upgrade_email_bypass.md
@@ -83,7 +83,7 @@ You have the following options to help your users:
- They can confirm their address through the email that they received.
- They can confirm the subject email address themselves by navigating to `https://gitlab.example.com/users/confirmation/new`.
-As an administrator, you may also confirm a user in the [Admin Area](admin_area/#administering-users).
+As an administrator, you may also confirm a user in the [Admin Area](admin_area/index.md#administering-users).
## What do I do if I am an administrator and I am locked out?
diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md
index c863a9d8270..5d78b4bb795 100644
--- a/doc/user/usage_quotas.md
+++ b/doc/user/usage_quotas.md
@@ -12,8 +12,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Namespace storage limit
-Namespaces on a GitLab SaaS Free tier have a 5 GB storage limit. For more information, see our [pricing page](https://about.gitlab.com/pricing/).
-This limit is not visible on the storage quota page, but we plan to make it visible and enforced starting October 19, 2022.
+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.
Storage types that add to the total namespace storage are:
@@ -22,7 +22,7 @@ Storage types that add to the total namespace storage are:
- Artifacts
- Container registry
- Package registry
-- Dependecy proxy
+- Dependency proxy
- Wiki
- Snippets
@@ -30,27 +30,18 @@ If your total namespace storage exceeds the available namespace storage quota, a
To prevent exceeding the namespace storage quota, you can:
-1. [Purchase more storage](../subscriptions/gitlab_com/index.md#purchase-more-storage-and-transfer).
-1. [Upgrade to a paid tier](../subscriptions/gitlab_com/#upgrade-your-gitlab-saas-subscription-tier).
-1. [Reduce storage usage](#manage-your-storage-usage).
+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/) 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.
### Namespace storage limit enforcement schedule
-Starting October 19, 2022, a storage limit will be enforced on all GitLab Free namespaces.
-We will start with a large limit enforcement and eventually reduce it to 5 GB.
+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.
-The following table describes the enforcement schedule, which is subject to change.
-
-| Target enforcement date | Limit | Expected Impact | Status |
-| ------ | ------ | ------ | ------ |
-| October 19, 2022 | 45,000 GB | LOW | Pending (**{hourglass}**)|
-| October 20, 2022 | 7,500 GB | LOW | Pending (**{hourglass}**)|
-| October 24, 2022 | 500 GB | MEDIUM | Pending (**{hourglass}**)|
-| October 27, 2022 | 75 GB | MEDIUM HIGH | Pending (**{hourglass}**)|
-| November 2, 2022 | 10 GB | HIGH | Pending (**{hourglass}**)|
-| November 9, 2022 | 5 GB | VERY HIGH | Pending (**{hourglass}**)|
-
-Namespaces that reach the enforced limit will have their projects locked. To unlock your project, you will have to [manage its storage](#manage-your-storage-usage).
+Impacted users are notified via email and in-app notifications at least 60 days prior to enforcement.
### Project storage limit
@@ -67,7 +58,7 @@ you must purchase additional storage. For more details, see [Excess storage usag
## View storage usage
-You can view storage usage for your project or [namespace](../user/group/#namespaces).
+You can view storage usage for your project or [namespace](../user/namespace/index.md).
1. Go to your project or namespace:
- For a project, on the top bar, select **Menu > Projects** and find your project.
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index 0ef3eb8b6fe..1c5a77c1f0c 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -17,14 +17,14 @@ sole discretion of GitLab Inc.
NOTE:
Workspace is currently in development.
-Workspace will be above the [top-level namespaces](../group/index.md#namespaces) for you to manage
+Workspace will be above the [top-level namespaces](../namespace/index.md) for you to manage
everything you do as a GitLab administrator, including:
- Defining and applying settings to all of your groups, subgroups, and projects.
- Aggregating data from all your groups, subgroups, and projects.
Our goal is to reach feature parity between SaaS and self-managed installations, with all
-[Admin Area settings](/ee/user/admin_area/settings/) moving to either:
+[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.
- Hardware Controls. For functionality that does not apply to groups, Hardware Controls are only
diff --git a/glfm_specification/example_snapshots/examples_index.yml b/glfm_specification/example_snapshots/examples_index.yml
index 9b601460b1d..5778819e024 100644
--- a/glfm_specification/example_snapshots/examples_index.yml
+++ b/glfm_specification/example_snapshots/examples_index.yml
@@ -2015,3 +2015,30 @@
07_01__gitlab_specific_markdown__footnotes__001:
spec_txt_example_position: 674
source_specification: gitlab
+07_02__gitlab_specific_markdown__task_list_items__001:
+ spec_txt_example_position: 675
+ source_specification: gitlab
+07_02__gitlab_specific_markdown__task_list_items__002:
+ spec_txt_example_position: 676
+ source_specification: gitlab
+07_02__gitlab_specific_markdown__task_list_items__003:
+ spec_txt_example_position: 677
+ source_specification: gitlab
+07_02__gitlab_specific_markdown__task_list_items__004:
+ spec_txt_example_position: 678
+ source_specification: gitlab
+07_03__gitlab_specific_markdown__front_matter__001:
+ spec_txt_example_position: 679
+ source_specification: gitlab
+07_03__gitlab_specific_markdown__front_matter__002:
+ spec_txt_example_position: 680
+ source_specification: gitlab
+07_03__gitlab_specific_markdown__front_matter__003:
+ spec_txt_example_position: 681
+ source_specification: gitlab
+07_03__gitlab_specific_markdown__front_matter__004:
+ spec_txt_example_position: 682
+ source_specification: gitlab
+07_03__gitlab_specific_markdown__front_matter__005:
+ spec_txt_example_position: 683
+ source_specification: gitlab
diff --git a/glfm_specification/example_snapshots/html.yml b/glfm_specification/example_snapshots/html.yml
index 6c05fbe744b..eda78a29da4 100644
--- a/glfm_specification/example_snapshots/html.yml
+++ b/glfm_specification/example_snapshots/html.yml
@@ -813,8 +813,7 @@
<a id="user-content-bar" class="anchor" href="#bar" aria-hidden="true"></a>Bar</h2>
<p data-sourcepos="6:1-6:3" dir="auto">Baz</p>
wysiwyg: |-
- <hr>
- <h2>Foo</h2>
+ <pre language="yaml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>Foo</code></pre>
<h2>Bar</h2>
<p>Baz</p>
04_03__leaf_blocks__setext_headings__018:
@@ -834,8 +833,7 @@
<copy-code></copy-code>
</div>
wysiwyg: |-
- <hr>
- <hr>
+ <pre language="yaml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code></code></pre>
04_03__leaf_blocks__setext_headings__020:
canonical: |
<ul>
@@ -2144,6 +2142,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url "title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__002:
canonical: |
@@ -2151,6 +2150,7 @@
static: |-
<p data-sourcepos="5:1-5:5" dir="auto"><a href="/url" title="the title">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url "the title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="the title">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__003:
canonical: |
@@ -2158,6 +2158,7 @@
static: |-
<p data-sourcepos="3:1-3:11" dir="auto"><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
wysiwyg: |-
+ <pre>[foo*bar\]]: my_(url) "title (with parens)"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
04_07__leaf_blocks__link_reference_definitions__004:
canonical: |
@@ -2165,6 +2166,7 @@
static: |-
<p data-sourcepos="5:1-5:9" dir="auto"><a href="my%20url" title="title">Foo bar</a></p>
wysiwyg: |-
+ <pre>[foo bar]: my url "title"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="my%20url" title="title">Foo bar</a></p>
04_07__leaf_blocks__link_reference_definitions__005:
canonical: |
@@ -2180,6 +2182,11 @@
line2
">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url "
+ title
+ line1
+ line2
+ "</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="
title
line1
@@ -2204,6 +2211,7 @@
static: |-
<p data-sourcepos="4:1-4:5" dir="auto"><a href="/url">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__008:
canonical: |
@@ -2221,6 +2229,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: </pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__010:
canonical: |
@@ -2238,6 +2247,7 @@
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url%5Cbar*baz" title='foo"bar\baz'>foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url\bar*baz "foo"bar\baz"</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__012:
canonical: |
@@ -2246,6 +2256,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="url">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="url">foo</a></p>
+ <pre>[foo]: url</pre>
04_07__leaf_blocks__link_reference_definitions__013:
canonical: |
<p><a href="first">foo</a></p>
@@ -2253,12 +2264,15 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="first">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="first">foo</a></p>
+ <pre>[foo]: first</pre>
+ <pre>[foo]: second</pre>
04_07__leaf_blocks__link_reference_definitions__014:
canonical: |
<p><a href="/url">Foo</a></p>
static: |-
<p data-sourcepos="3:1-3:5" dir="auto"><a href="/url">Foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></p>
04_07__leaf_blocks__link_reference_definitions__015:
canonical: |
@@ -2266,18 +2280,20 @@
static: |-
<p data-sourcepos="3:1-3:8" dir="auto"><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
wysiwyg: |-
+ <pre>[αγω]: /φου</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/%CF%86%CE%BF%CF%85">αγω</a></p>
04_07__leaf_blocks__link_reference_definitions__016:
canonical: ""
static: ""
wysiwyg: |-
- <p></p>
+ <pre>[foo]: /url</pre>
04_07__leaf_blocks__link_reference_definitions__017:
canonical: |
<p>bar</p>
static: |-
<p data-sourcepos="1:1-4:3" dir="auto">bar</p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<p>bar</p>
04_07__leaf_blocks__link_reference_definitions__018:
canonical: |
@@ -2292,6 +2308,7 @@
static: |-
<p data-sourcepos="1:1-2:10" dir="auto">"title" ok</p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<p>"title" ok</p>
04_07__leaf_blocks__link_reference_definitions__020:
canonical: |
@@ -2349,6 +2366,7 @@
</blockquote>
wysiwyg: |-
<h1><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></h1>
+ <pre>[foo]: /url</pre>
<blockquote multiline="false"><p>bar</p></blockquote>
04_07__leaf_blocks__link_reference_definitions__024:
canonical: |
@@ -2359,6 +2377,7 @@
<a id="user-content-bar" class="anchor" href="#bar" aria-hidden="true"></a>bar</h1>
<p data-sourcepos="4:1-4:5" dir="auto"><a href="/url">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<h1>bar</h1>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__025:
@@ -2369,6 +2388,7 @@
<p data-sourcepos="1:1-3:5" dir="auto">===
<a href="/url">foo</a></p>
wysiwyg: |-
+ <pre>[foo]: /url</pre>
<p>===
<a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
04_07__leaf_blocks__link_reference_definitions__026:
@@ -2381,6 +2401,9 @@
<a href="/bar-url" title="bar">bar</a>,
<a href="/baz-url">baz</a></p>
wysiwyg: |-
+ <pre>[foo]: /foo-url "foo"</pre>
+ <pre>[bar]: /bar-url "bar"</pre>
+ <pre>[baz]: /baz-url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/foo-url" title="foo">foo</a>,
<a target="_blank" rel="noopener noreferrer nofollow" href="/bar-url" title="bar">bar</a>,
<a target="_blank" rel="noopener noreferrer nofollow" href="/baz-url">baz</a></p>
@@ -2395,12 +2418,12 @@
</blockquote>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
- <blockquote multiline="false"><p></p></blockquote>
+ <blockquote multiline="false"><pre>[foo]: /url</pre></blockquote>
04_07__leaf_blocks__link_reference_definitions__028:
canonical: ""
static: ""
wysiwyg: |-
- <p></p>
+ <pre>[foo]: /url</pre>
04_08__leaf_blocks__paragraphs__001:
canonical: |
<p>aaa</p>
@@ -4543,7 +4566,7 @@
</li>
</ul>
wysiwyg: |-
- <ul bullet="*"><li><p>a</p></li><li><p>b</p></li><li><p>d</p></li></ul>
+ <ul bullet="*"><li><p>a</p></li><li><p>b</p><pre>[ref]: /url</pre></li><li><p>d</p></li></ul>
05_04__container_blocks__lists__018:
canonical: |
<ul>
@@ -4880,6 +4903,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/bar*" title="ti*tle">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/bar*" title="ti*tle">foo</a></p>
+ <pre>[foo]: /bar* "ti*tle"</pre>
06_02__inlines__backslash_escapes__013:
canonical: |
<pre><code class="language-foo+bar">foo
@@ -4969,6 +4993,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+ <pre>[foo]: /föö "föö"</pre>
06_03__inlines__entity_and_numeric_character_references__010:
canonical: |
<pre><code class="language-föö">foo
@@ -6475,6 +6500,7 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+ <pre>[bar]: /url "title"</pre>
06_07__inlines__links__044:
canonical: |
<p><a href="/uri">link [foo [bar]]</a></p>
@@ -6482,6 +6508,7 @@
<p data-sourcepos="1:1-1:23" dir="auto"><a href="/uri">link [foo [bar]]</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [foo [bar]]</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__045:
canonical: |
<p><a href="/uri">link [bar</a></p>
@@ -6489,6 +6516,7 @@
<p data-sourcepos="1:1-1:17" dir="auto"><a href="/uri">link [bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [bar</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__046:
canonical: |
<p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
@@ -6496,6 +6524,7 @@
<p data-sourcepos="1:1-1:29" dir="auto"><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__047:
canonical: |
<p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
@@ -6503,6 +6532,7 @@
<p data-sourcepos="1:1-1:24" dir="auto"><a href="/uri"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="moon" decoding="async" class="lazy" data-src="moon.jpg"></a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><img src="moon.jpg" alt="moon"></a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__048:
canonical: |
<p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
@@ -6510,6 +6540,7 @@
<p data-sourcepos="1:1-1:22" dir="auto">[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
wysiwyg: |-
<p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar</a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__049:
canonical: |
<p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
@@ -6517,6 +6548,7 @@
<p data-sourcepos="1:1-1:27" dir="auto">[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
wysiwyg: |-
<p>[foo <em>bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><em>baz</em></a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__050:
canonical: |
<p>*<a href="/uri">foo*</a></p>
@@ -6524,6 +6556,7 @@
<p data-sourcepos="1:1-1:12" dir="auto">*<a href="/uri">foo*</a></p>
wysiwyg: |-
<p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo*</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__051:
canonical: |
<p><a href="/uri">foo *bar</a></p>
@@ -6531,6 +6564,7 @@
<p data-sourcepos="1:1-1:15" dir="auto"><a href="/uri">foo *bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo *bar</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__052:
canonical: |
<p>[foo <bar attr="][ref]"></p>
@@ -6538,6 +6572,7 @@
<p data-sourcepos="1:1-1:24" dir="auto">[foo </p>
wysiwyg: |-
<p>[foo </p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__053:
canonical: |
<p>[foo<code>][ref]</code></p>
@@ -6545,6 +6580,7 @@
<p data-sourcepos="1:1-1:12" dir="auto">[foo<code>][ref]</code></p>
wysiwyg: |-
<p>[foo<code>][ref]</code></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__054:
canonical: |
<p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
@@ -6552,6 +6588,7 @@
<p data-sourcepos="1:1-1:39" dir="auto">[foo<a href="http://example.com/?search=%5D%5Bref%5D" rel="nofollow noreferrer noopener" target="_blank">http://example.com/?search=][ref]</a></p>
wysiwyg: |-
<p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
+ <pre>[ref]: /uri</pre>
06_07__inlines__links__055:
canonical: |
<p><a href="/url" title="title">foo</a></p>
@@ -6559,6 +6596,7 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+ <pre>[bar]: /url "title"</pre>
06_07__inlines__links__056:
canonical: |
<p><a href="/url">Толпой</a> is a Russian word.</p>
@@ -6566,12 +6604,14 @@
<p data-sourcepos="1:1-1:47" dir="auto"><a href="/url">Толпой</a> is a Russian word.</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Толпой</a> is a Russian word.</p>
+ <pre>[толпой]: /url</pre>
06_07__inlines__links__057:
canonical: |
<p><a href="/url">Baz</a></p>
static: |-
<p data-sourcepos="4:1-4:14" dir="auto"><a href="/url">Baz</a></p>
wysiwyg: |-
+ <pre>[foo bar]: /url</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Baz</a></p>
06_07__inlines__links__058:
canonical: |
@@ -6580,6 +6620,7 @@
<p data-sourcepos="1:1-1:11" dir="auto">[foo] <a href="/url" title="title">bar</a></p>
wysiwyg: |-
<p>[foo] <a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
+ <pre>[bar]: /url "title"</pre>
06_07__inlines__links__059:
canonical: |
<p>[foo]
@@ -6590,12 +6631,15 @@
wysiwyg: |-
<p>[foo]
<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
+ <pre>[bar]: /url "title"</pre>
06_07__inlines__links__060:
canonical: |
<p><a href="/url1">bar</a></p>
static: |-
<p data-sourcepos="5:1-5:10" dir="auto"><a href="/url1">bar</a></p>
wysiwyg: |-
+ <pre>[foo]: /url1</pre>
+ <pre>[foo]: /url2</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
06_07__inlines__links__061:
canonical: |
@@ -6604,6 +6648,7 @@
<p data-sourcepos="1:1-1:32" dir="auto">[bar][foo<span>!</span>]</p>
wysiwyg: |-
<p>[bar][foo!]</p>
+ <pre>[foo!]: /url</pre>
06_07__inlines__links__062:
canonical: |
<p>[foo][ref[]</p>
@@ -6641,12 +6686,14 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a href="/uri">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo</a></p>
+ <pre>[ref\[]: /uri</pre>
06_07__inlines__links__066:
canonical: |
<p><a href="/uri">bar\</a></p>
static: |-
<p data-sourcepos="3:1-3:7" dir="auto"><a href="/uri">bar\</a></p>
wysiwyg: |-
+ <pre>[bar\\]: /uri</pre>
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar\</a></p>
06_07__inlines__links__067:
canonical: |
@@ -6681,6 +6728,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__070:
canonical: |
<p><a href="/url" title="title"><em>foo</em> bar</a></p>
@@ -6688,6 +6736,7 @@
<p data-sourcepos="1:1-1:13" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
+ <pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__071:
canonical: |
<p><a href="/url" title="title">Foo</a></p>
@@ -6695,6 +6744,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">Foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__072:
canonical: |
<p><a href="/url" title="title">foo</a>
@@ -6705,6 +6755,7 @@
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a>
[]</p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__073:
canonical: |
<p><a href="/url" title="title">foo</a></p>
@@ -6712,6 +6763,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__074:
canonical: |
<p><a href="/url" title="title"><em>foo</em> bar</a></p>
@@ -6719,6 +6771,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
+ <pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__075:
canonical: |
<p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
@@ -6726,6 +6779,7 @@
<p data-sourcepos="1:1-1:13" dir="auto">[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
wysiwyg: |-
<p>[<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a>]</p>
+ <pre>[*foo* bar]: /url "title"</pre>
06_07__inlines__links__076:
canonical: |
<p>[[bar <a href="/url">foo</a></p>
@@ -6733,6 +6787,7 @@
<p data-sourcepos="1:1-1:11" dir="auto">[[bar <a href="/url">foo</a></p>
wysiwyg: |-
<p>[[bar <a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+ <pre>[foo]: /url</pre>
06_07__inlines__links__077:
canonical: |
<p><a href="/url" title="title">Foo</a></p>
@@ -6740,6 +6795,7 @@
<p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">Foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__078:
canonical: |
<p><a href="/url">foo</a> bar</p>
@@ -6747,6 +6803,7 @@
<p data-sourcepos="1:1-1:9" dir="auto"><a href="/url">foo</a> bar</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a> bar</p>
+ <pre>[foo]: /url</pre>
06_07__inlines__links__079:
canonical: |
<p>[foo]</p>
@@ -6754,12 +6811,14 @@
<p data-sourcepos="1:1-1:6" dir="auto">[foo]</p>
wysiwyg: |-
<p>[foo]</p>
+ <pre>[foo]: /url "title"</pre>
06_07__inlines__links__080:
canonical: |
<p>*<a href="/url">foo*</a></p>
static: |-
<p data-sourcepos="3:1-3:7" dir="auto">*<a href="/url">foo*</a></p>
wysiwyg: |-
+ <pre>[foo*]: /url</pre>
<p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo*</a></p>
06_07__inlines__links__081:
canonical: |
@@ -6768,6 +6827,8 @@
<p data-sourcepos="1:1-1:10" dir="auto"><a href="/url2">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a></p>
+ <pre>[foo]: /url1</pre>
+ <pre>[bar]: /url2</pre>
06_07__inlines__links__082:
canonical: |
<p><a href="/url1">foo</a></p>
@@ -6775,6 +6836,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="/url1">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a></p>
+ <pre>[foo]: /url1</pre>
06_07__inlines__links__083:
canonical: |
<p><a href="">foo</a></p>
@@ -6782,6 +6844,7 @@
<p data-sourcepos="1:1-1:7" dir="auto"><a href="">foo</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
+ <pre>[foo]: /url1</pre>
06_07__inlines__links__084:
canonical: |
<p><a href="/url1">foo</a>(not a link)</p>
@@ -6789,6 +6852,7 @@
<p data-sourcepos="1:1-1:17" dir="auto"><a href="/url1">foo</a>(not a link)</p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a>(not a link)</p>
+ <pre>[foo]: /url1</pre>
06_07__inlines__links__085:
canonical: |
<p>[foo]<a href="/url">bar</a></p>
@@ -6796,6 +6860,7 @@
<p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url">bar</a></p>
wysiwyg: |-
<p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url">bar</a></p>
+ <pre>[baz]: /url</pre>
06_07__inlines__links__086:
canonical: |
<p><a href="/url2">foo</a><a href="/url1">baz</a></p>
@@ -6803,6 +6868,8 @@
<p data-sourcepos="1:1-1:15" dir="auto"><a href="/url2">foo</a><a href="/url1">baz</a></p>
wysiwyg: |-
<p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">baz</a></p>
+ <pre>[baz]: /url1</pre>
+ <pre>[bar]: /url2</pre>
06_07__inlines__links__087:
canonical: |
<p>[foo]<a href="/url1">bar</a></p>
@@ -6810,6 +6877,8 @@
<p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url1">bar</a></p>
wysiwyg: |-
<p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
+ <pre>[baz]: /url1</pre>
+ <pre>[foo]: /url2</pre>
06_08__inlines__images__001:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@@ -6824,6 +6893,7 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+ <pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__003:
canonical: |
<p><img src="/url2" alt="foo bar" /></p>
@@ -6845,6 +6915,7 @@
<p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+ <pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__006:
canonical: |
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
@@ -6852,6 +6923,7 @@
<p data-sourcepos="1:1-1:20" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
wysiwyg: |-
<p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+ <pre>[foobar]: train.jpg "train &amp; tracks"</pre>
06_08__inlines__images__007:
canonical: |
<p><img src="train.jpg" alt="foo" /></p>
@@ -6887,6 +6959,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo"></p>
+ <pre>[bar]: /url</pre>
06_08__inlines__images__012:
canonical: |
<p><img src="/url" alt="foo" /></p>
@@ -6894,6 +6967,7 @@
<p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo"></p>
+ <pre>[bar]: /url</pre>
06_08__inlines__images__013:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@@ -6901,6 +6975,7 @@
<p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo" title="title"></p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__014:
canonical: |
<p><img src="/url" alt="foo bar" title="title" /></p>
@@ -6908,6 +6983,7 @@
<p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo bar" title="title"></p>
+ <pre>[*foo* bar]: /url "title"</pre>
06_08__inlines__images__015:
canonical: |
<p><img src="/url" alt="Foo" title="title" /></p>
@@ -6915,6 +6991,7 @@
<p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="Foo" title="title"></p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__016:
canonical: |
<p><img src="/url" alt="foo" title="title" />
@@ -6925,6 +7002,7 @@
wysiwyg: |-
<p><img src="/url" alt="foo" title="title">
[]</p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__017:
canonical: |
<p><img src="/url" alt="foo" title="title" /></p>
@@ -6932,6 +7010,7 @@
<p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo" title="title"></p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__018:
canonical: |
<p><img src="/url" alt="foo bar" title="title" /></p>
@@ -6939,6 +7018,7 @@
<p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="foo bar" title="title"></p>
+ <pre>[*foo* bar]: /url "title"</pre>
06_08__inlines__images__019:
canonical: |
<p>![[foo]]</p>
@@ -6956,6 +7036,7 @@
<p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
wysiwyg: |-
<p><img src="/url" alt="Foo" title="title"></p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__021:
canonical: |
<p>![foo]</p>
@@ -6963,6 +7044,7 @@
<p data-sourcepos="1:1-1:7" dir="auto">![foo]</p>
wysiwyg: |-
<p>![foo]</p>
+ <pre>[foo]: /url "title"</pre>
06_08__inlines__images__022:
canonical: |
<p>!<a href="/url" title="title">foo</a></p>
@@ -6970,6 +7052,7 @@
<p data-sourcepos="1:1-1:27" dir="auto"><span>!</span><a href="/url" title="title">foo</a></p>
wysiwyg: |-
<p>!<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+ <pre>[foo]: /url "title"</pre>
06_09__inlines__autolinks__001:
canonical: |
<p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
@@ -6990,7 +7073,7 @@
static: |-
<p data-sourcepos="1:1-1:24" dir="auto"><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
+ <p><a target="_blank" rel="noopener noreferrer nofollow">irc://foo.bar:2233/baz</a></p>
06_09__inlines__autolinks__004:
canonical: |
<p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
@@ -7004,14 +7087,14 @@
static: |-
<p data-sourcepos="1:1-1:9" dir="auto"><a href="a+b+c:d">a+b+c:d</a></p>
wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="a+b+c:d">a+b+c:d</a></p>
+ <p><a target="_blank" rel="noopener noreferrer nofollow">a+b+c:d</a></p>
06_09__inlines__autolinks__006:
canonical: |
<p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
static: |-
<p data-sourcepos="1:1-1:26" dir="auto"><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
+ <p><a target="_blank" rel="noopener noreferrer nofollow">made-up-scheme://foo,bar</a></p>
06_09__inlines__autolinks__007:
canonical: |
<p><a href="http://../">http://../</a></p>
@@ -7025,7 +7108,7 @@
static: |-
<p data-sourcepos="1:1-1:20" dir="auto"><a href="localhost:5001/foo">localhost:5001/foo</a></p>
wysiwyg: |-
- <p><a target="_blank" rel="noopener noreferrer nofollow" href="localhost:5001/foo">localhost:5001/foo</a></p>
+ <p><a target="_blank" rel="noopener noreferrer nofollow">localhost:5001/foo</a></p>
06_09__inlines__autolinks__009:
canonical: |
<p>&lt;http://foo.bar/baz bim&gt;</p>
@@ -7556,16 +7639,180 @@
wysiwyg: |-
<p>Multiple spaces</p>
07_01__gitlab_specific_markdown__footnotes__001:
- canonical: ""
+ canonical: |
+ <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>
static: |-
- <p data-sourcepos="1:1-1:27" dir="auto">footnote reference tag <sup class="footnote-ref"><a href="#fn-1-9034" id="fnref-1-9034" data-footnote-ref>1</a></sup></p>
+ <p data-sourcepos="1:1-1:34" dir="auto">footnote reference tag <sup class="footnote-ref"><a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref>1</a></sup></p>
<section data-footnotes class="footnotes">
<ol>
- <li id="fn-1-9034">
- <p data-sourcepos="3:7-3:19">footnote text <a href="#fnref-1-9034" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <li id="fn-fortytwo-42">
+ <p data-sourcepos="3:14-3:26">footnote text <a href="#fnref-fortytwo-42" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
</ol>
</section>
wysiwyg: |-
- <p>footnote reference tag <sup identifier="1">1</sup></p>
+ <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__gitlab_specific_markdown__task_list_items__001:
+ canonical: |
+ <ul>
+ <li>
+ <task-button/>
+ <input type="checkbox" disabled/>
+ incomplete
+ </li>
+ </ul>
+ static: |-
+ <ul data-sourcepos="1:1-1:16" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:16" class="task-list-item">
+ <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" disabled> incomplete</li>
+ </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__gitlab_specific_markdown__task_list_items__002:
+ canonical: |
+ <ul>
+ <li>
+ <task-button/>
+ <input type="checkbox" checked disabled/>
+ completed
+ </li>
+ </ul>
+ static: |-
+ <ul data-sourcepos="1:1-1:15" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:15" class="task-list-item">
+ <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" checked disabled> completed</li>
+ </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__gitlab_specific_markdown__task_list_items__003:
+ canonical: |
+ <ul>
+ <li>
+ <task-button/>
+ <input type="checkbox" data-inapplicable disabled>
+ <s>
+ inapplicable
+ </s>
+ </li>
+ </ul>
+ static: |-
+ <ul data-sourcepos="1:1-1:18" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:18" class="task-list-item inapplicable">
+ <task-button></task-button><input type="checkbox" class="task-list-item-checkbox" data-inapplicable disabled> <s>inapplicable</s>
+ </li>
+ </ul>
+07_02__gitlab_specific_markdown__task_list_items__004:
+ canonical: |
+ <ul>
+ <li>
+ <p>
+ <task-button/>
+ <input type="checkbox" data-inapplicable disabled>
+ <s>
+ inapplicable
+ </s>
+ </p>
+ <p>
+ text in loose list
+ </p>
+ </li>
+ </ul>
+ static: |-
+ <ul data-sourcepos="1:1-3:20" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-3:20" class="task-list-item inapplicable">
+ <p data-sourcepos="1:3-1:18"><task-button></task-button><input type="checkbox" class="task-list-item-checkbox" data-inapplicable disabled> <s>inapplicable</s></p>
+ <p data-sourcepos="3:3-3:20">text in loose list</p>
+ </li>
+ </ul>
+07_03__gitlab_specific_markdown__front_matter__001:
+ canonical: |
+ <pre>
+ <code>
+ title: YAML front matter
+ </code>
+ </pre>
+ static: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">YAML front matter</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+ wysiwyg: |-
+ <pre language="yaml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>title: YAML front matter</code></pre>
+07_03__gitlab_specific_markdown__front_matter__002:
+ canonical: |
+ <pre>
+ <code>
+ title: TOML front matter
+ </code>
+ </pre>
+ static: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-toml" lang="toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="err">title:</span> <span class="err">TOML</span> <span class="err">front</span> <span class="err">matter</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+ wysiwyg: |-
+ <pre language="toml" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>title: TOML front matter</code></pre>
+07_03__gitlab_specific_markdown__front_matter__003:
+ canonical: |
+ <pre>
+ <code>
+ {
+ "title": "JSON front matter"
+ }
+ </code>
+ </pre>
+ static: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-5:3" class="code highlight js-syntax-highlight language-json" lang="json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
+ <span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"JSON front matter"</span></span>
+ <span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+ wysiwyg: |-
+ <pre language="json" class="content-editor-code-block undefined code highlight" isfrontmatter="true"><code>{
+ "title": "JSON front matter"
+ }</code></pre>
+07_03__gitlab_specific_markdown__front_matter__004:
+ canonical: |
+ <p>text</p>
+ <hr>
+ <h2>title: YAML front matter</h2>
+ static: |-
+ <p data-sourcepos="1:1-1:4" dir="auto">text</p>
+ <hr data-sourcepos="3:1-3:3">
+ <h2 data-sourcepos="4:1-5:3" dir="auto">
+ <a id="user-content-title-yaml-front-matter" class="anchor" href="#title-yaml-front-matter" aria-hidden="true"></a>title: YAML front matter</h2>
+ wysiwyg: |-
+ <p>text</p>
+ <hr>
+ <h2>title: YAML front matter</h2>
+07_03__gitlab_specific_markdown__front_matter__005:
+ canonical: |
+ <hr>
+ <h2>title: YAML front matter</h2>
+ static: |-
+ <hr data-sourcepos="1:2-1:4">
+ <h2 data-sourcepos="2:1-3:3" dir="auto">
+ <a id="user-content-title-yaml-front-matter" class="anchor" href="#title-yaml-front-matter" aria-hidden="true"></a>title: YAML front matter</h2>
+ wysiwyg: |-
+ <hr>
+ <h2>title: YAML front matter</h2>
diff --git a/glfm_specification/example_snapshots/markdown.yml b/glfm_specification/example_snapshots/markdown.yml
index de0e66f7e08..c875beb77f5 100644
--- a/glfm_specification/example_snapshots/markdown.yml
+++ b/glfm_specification/example_snapshots/markdown.yml
@@ -2190,6 +2190,40 @@
06_15__inlines__textual_content__003: |
Multiple spaces
07_01__gitlab_specific_markdown__footnotes__001: |
- footnote reference tag [^1]
+ footnote reference tag [^fortytwo]
+
+ [^fortytwo]: footnote text
+07_02__gitlab_specific_markdown__task_list_items__001: |
+ - [ ] incomplete
+07_02__gitlab_specific_markdown__task_list_items__002: |
+ - [x] completed
+07_02__gitlab_specific_markdown__task_list_items__003: |
+ - [~] inapplicable
+07_02__gitlab_specific_markdown__task_list_items__004: |
+ - [~] inapplicable
+
+ text in loose list
+07_03__gitlab_specific_markdown__front_matter__001: |
+ ---
+ title: YAML front matter
+ ---
+07_03__gitlab_specific_markdown__front_matter__002: |
+ +++
+ title: TOML front matter
+ +++
+07_03__gitlab_specific_markdown__front_matter__003: |
+ ;;;
+ {
+ "title": "JSON front matter"
+ }
+ ;;;
+07_03__gitlab_specific_markdown__front_matter__004: |
+ text
- [^1]: footnote text
+ ---
+ title: YAML front matter
+ ---
+07_03__gitlab_specific_markdown__front_matter__005: |2
+ ---
+ title: YAML front matter
+ ---
diff --git a/glfm_specification/example_snapshots/prosemirror_json.yml b/glfm_specification/example_snapshots/prosemirror_json.yml
index 0a8c15e9650..9f0d462aed3 100644
--- a/glfm_specification/example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/example_snapshots/prosemirror_json.yml
@@ -1702,12 +1702,11 @@
"type": "doc",
"content": [
{
- "type": "horizontalRule"
- },
- {
- "type": "heading",
+ "type": "frontmatter",
"attrs": {
- "level": 2
+ "language": "yaml",
+ "class": "code highlight",
+ "isFrontmatter": true
},
"content": [
{
@@ -1759,10 +1758,12 @@
"type": "doc",
"content": [
{
- "type": "horizontalRule"
- },
- {
- "type": "horizontalRule"
+ "type": "frontmatter",
+ "attrs": {
+ "language": "yaml",
+ "class": "code highlight",
+ "isFrontmatter": true
+ }
}
]
}
@@ -3149,7 +3150,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": false
}
}
],
@@ -3234,7 +3236,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": false
}
}
],
@@ -3752,7 +3755,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": false
}
}
],
@@ -3884,6 +3888,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -3896,7 +3914,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -3911,6 +3930,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "the title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"the title\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -3923,7 +3956,8 @@
"target": "_blank",
"class": null,
"title": "the title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -3938,6 +3972,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo*bar\\]",
+ "url": "my_(url)",
+ "title": "title (with parens)"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo*bar\\]]: my_(url) \"title (with parens)\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -3950,7 +3998,8 @@
"target": "_blank",
"class": null,
"title": "title (with parens)",
- "canonicalSrc": null
+ "canonicalSrc": "foo*bar\\]",
+ "isReference": true
}
}
],
@@ -3965,6 +4014,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo bar",
+ "url": "my url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo bar]: my url \"title\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -3977,7 +4040,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo bar",
+ "isReference": true
}
}
],
@@ -3992,6 +4056,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "\ntitle\nline1\nline2\n"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"\ntitle\nline1\nline2\n\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4004,7 +4082,8 @@
"target": "_blank",
"class": null,
"title": "\ntitle\nline1\nline2\n",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4052,6 +4131,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4064,7 +4157,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4103,6 +4197,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: "
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4115,7 +4223,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4154,6 +4263,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url\\bar*baz",
+ "title": "foo\"bar\\baz"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url\\bar*baz \"foo\"bar\\baz\""
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4166,7 +4289,8 @@
"target": "_blank",
"class": null,
"title": "foo\"bar\\baz",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4193,13 +4317,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: url"
+ }
+ ]
}
]
}
@@ -4220,13 +4359,42 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "first",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: first"
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "second",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: second"
+ }
+ ]
}
]
}
@@ -4235,6 +4403,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4247,7 +4429,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4262,6 +4445,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "αγω",
+ "url": "/φου",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[αγω]: /φου"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4274,7 +4471,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "αγω",
+ "isReference": true
}
}
],
@@ -4289,7 +4487,18 @@
"type": "doc",
"content": [
{
- "type": "paragraph"
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
}
]
}
@@ -4298,6 +4507,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4328,6 +4551,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4438,7 +4675,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4447,6 +4685,20 @@
]
},
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "blockquote",
"attrs": {
"multiline": false
@@ -4470,6 +4722,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "heading",
"attrs": {
"level": 1
@@ -4494,7 +4760,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4509,6 +4776,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4525,7 +4806,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4540,6 +4822,48 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/foo-url",
+ "title": "foo"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /foo-url \"foo\""
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/bar-url",
+ "title": "bar"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /bar-url \"bar\""
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "baz",
+ "url": "/baz-url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[baz]: /baz-url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -4552,7 +4876,8 @@
"target": "_blank",
"class": null,
"title": "foo",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4572,7 +4897,8 @@
"target": "_blank",
"class": null,
"title": "bar",
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
@@ -4592,7 +4918,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "baz",
+ "isReference": true
}
}
],
@@ -4619,7 +4946,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -4634,7 +4962,18 @@
},
"content": [
{
- "type": "paragraph"
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
}
]
}
@@ -4645,7 +4984,18 @@
"type": "doc",
"content": [
{
- "type": "paragraph"
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
}
]
}
@@ -9572,6 +9922,20 @@
"text": "b"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /url"
+ }
+ ]
}
]
},
@@ -10346,7 +10710,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com?find=%5C*",
+ "isReference": false
}
}
],
@@ -10382,7 +10747,8 @@
"target": "_blank",
"class": null,
"title": "ti*tle",
- "canonicalSrc": null
+ "canonicalSrc": "/bar*",
+ "isReference": false
}
}
],
@@ -10409,13 +10775,28 @@
"target": "_blank",
"class": null,
"title": "ti*tle",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/bar*",
+ "title": "ti*tle"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /bar* \"ti*tle\""
+ }
+ ]
}
]
}
@@ -10554,7 +10935,8 @@
"target": "_blank",
"class": null,
"title": "föö",
- "canonicalSrc": null
+ "canonicalSrc": "/f%C3%B6%C3%B6",
+ "isReference": false
}
}
],
@@ -10581,13 +10963,28 @@
"target": "_blank",
"class": null,
"title": "föö",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/föö",
+ "title": "föö"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /föö \"föö\""
+ }
+ ]
}
]
}
@@ -11101,7 +11498,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "`",
+ "isReference": false
}
}
],
@@ -11152,7 +11550,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar.%60baz",
+ "isReference": false
}
}
],
@@ -12308,7 +12707,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
},
{
@@ -12778,7 +13178,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
},
{
@@ -12847,7 +13248,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
},
{
@@ -13206,7 +13608,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
},
{
@@ -14112,7 +14515,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
],
@@ -14143,7 +14547,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
],
@@ -14171,7 +14576,8 @@
"alt": null,
"title": "*",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": false
}
}
]
@@ -14293,7 +14699,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar/?q=**",
+ "isReference": false
}
}
],
@@ -14324,7 +14731,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar/?q=__",
+ "isReference": false
}
}
],
@@ -14399,7 +14807,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -14426,7 +14835,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -14453,7 +14863,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "",
+ "isReference": false
}
}
],
@@ -14480,7 +14891,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "",
+ "isReference": false
}
}
],
@@ -14522,7 +14934,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/my%20uri",
+ "isReference": false
}
}
],
@@ -14579,7 +14992,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "b)c",
+ "isReference": false
}
}
],
@@ -14645,7 +15059,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "(foo)",
+ "isReference": false
}
}
],
@@ -14672,7 +15087,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo(and(bar))",
+ "isReference": false
}
}
],
@@ -14699,7 +15115,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo(and(bar)",
+ "isReference": false
}
}
],
@@ -14726,7 +15143,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo(and(bar)",
+ "isReference": false
}
}
],
@@ -14753,7 +15171,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo):",
+ "isReference": false
}
}
],
@@ -14780,7 +15199,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "#fragment",
+ "isReference": false
}
}
],
@@ -14801,7 +15221,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com#fragment",
+ "isReference": false
}
}
],
@@ -14822,7 +15243,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com?foo=3#frag",
+ "isReference": false
}
}
],
@@ -14849,7 +15271,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo%5Cbar",
+ "isReference": false
}
}
],
@@ -14876,7 +15299,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo%20b%C3%A4",
+ "isReference": false
}
}
],
@@ -14903,7 +15327,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "%22title%22",
+ "isReference": false
}
}
],
@@ -14930,7 +15355,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
],
@@ -14957,7 +15383,8 @@
"target": "_blank",
"class": null,
"title": "title \"\"",
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
],
@@ -14984,7 +15411,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/url%C2%A0%22title%22",
+ "isReference": false
}
}
],
@@ -15026,7 +15454,8 @@
"target": "_blank",
"class": null,
"title": "title \"and\" title",
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
],
@@ -15053,7 +15482,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15095,7 +15525,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15141,7 +15572,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15168,7 +15600,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15195,7 +15628,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15211,7 +15645,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
},
{
@@ -15230,7 +15665,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
},
{
@@ -15252,7 +15688,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
},
{
@@ -15285,7 +15722,8 @@
"alt": "moon",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "moon.jpg",
+ "isReference": false
},
"marks": [
{
@@ -15295,7 +15733,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
]
@@ -15325,7 +15764,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15369,7 +15809,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
},
{
@@ -15409,7 +15850,8 @@
"alt": "[foo](uri2)",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "uri3",
+ "isReference": false
}
}
]
@@ -15437,7 +15879,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15464,7 +15907,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "baz*",
+ "isReference": false
}
}
],
@@ -15558,7 +16002,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com/?search=%5D(uri)",
+ "isReference": false
}
}
],
@@ -15585,13 +16030,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -15612,13 +16072,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "link [foo [bar]]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15639,13 +16114,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "link [bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15666,7 +16156,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
@@ -15682,7 +16173,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
},
{
@@ -15701,7 +16193,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
},
{
@@ -15723,7 +16216,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
},
{
@@ -15739,6 +16233,20 @@
"text": "#"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15756,7 +16264,8 @@
"alt": "moon",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "moon.jpg",
+ "isReference": false
},
"marks": [
{
@@ -15766,12 +16275,27 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
]
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15796,7 +16320,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "/uri",
+ "isReference": false
}
}
],
@@ -15816,13 +16341,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "ref"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15856,7 +16396,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
},
{
@@ -15879,13 +16420,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "ref"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15910,13 +16466,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "foo*"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15937,13 +16508,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref",
+ "isReference": true
}
}
],
"text": "foo *bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15959,6 +16545,20 @@
"text": "[foo "
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -15983,6 +16583,20 @@
"text": "][ref]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -16007,13 +16621,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com/?search=%5D%5Bref%5D",
+ "isReference": false
}
}
],
"text": "http://example.com/?search=][ref]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref]: /uri"
+ }
+ ]
}
]
}
@@ -16034,13 +16663,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16061,7 +16705,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "толпой",
+ "isReference": true
}
}
],
@@ -16072,6 +16717,20 @@
"text": " is a Russian word."
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "толпой",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[толпой]: /url"
+ }
+ ]
}
]
}
@@ -16080,6 +16739,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo bar",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo bar]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -16092,7 +16765,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo bar",
+ "isReference": true
}
}
],
@@ -16123,13 +16797,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
"text": "bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16154,13 +16843,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
"text": "bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16169,6 +16873,34 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url1"
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url2",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url2"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -16181,7 +16913,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -16203,6 +16936,20 @@
"text": "[bar][foo!]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo!",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo!]: /url"
+ }
+ ]
}
]
}
@@ -16295,13 +17042,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "ref\\[",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "ref\\[",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[ref\\[]: /uri"
+ }
+ ]
}
]
}
@@ -16310,6 +17072,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar\\\\",
+ "url": "/uri",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar\\\\]: /uri"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -16322,7 +17098,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "bar\\\\",
+ "isReference": true
}
}
],
@@ -16397,13 +17174,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16424,7 +17216,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
},
{
@@ -16443,13 +17236,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
}
],
"text": " bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "*foo* bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[*foo* bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16470,13 +17278,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "Foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16497,7 +17320,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -16508,6 +17332,20 @@
"text": "\n[]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16528,13 +17366,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16555,7 +17408,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
},
{
@@ -16574,13 +17428,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
}
],
"text": " bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "*foo* bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[*foo* bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16605,7 +17474,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
},
{
@@ -16624,7 +17494,8 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
}
],
@@ -16635,6 +17506,20 @@
"text": "]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "*foo* bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[*foo* bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16659,13 +17544,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
}
]
}
@@ -16686,13 +17586,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "Foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16713,7 +17628,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -16724,6 +17640,20 @@
"text": " bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url"
+ }
+ ]
}
]
}
@@ -16739,6 +17669,20 @@
"text": "[foo]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -16747,6 +17691,20 @@
"type": "doc",
"content": [
{
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo*",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo*]: /url"
+ }
+ ]
+ },
+ {
"type": "paragraph",
"content": [
{
@@ -16763,7 +17721,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo*",
+ "isReference": true
}
}
],
@@ -16790,13 +17749,42 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url1"
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url2",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url2"
+ }
+ ]
}
]
}
@@ -16817,13 +17805,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url1"
+ }
+ ]
}
]
}
@@ -16844,13 +17847,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "",
+ "isReference": false
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url1"
+ }
+ ]
}
]
}
@@ -16871,7 +17889,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
@@ -16882,6 +17901,20 @@
"text": "(not a link)"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url1"
+ }
+ ]
}
]
}
@@ -16906,13 +17939,28 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "baz",
+ "isReference": true
}
}
],
"text": "bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "baz",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[baz]: /url"
+ }
+ ]
}
]
}
@@ -16933,7 +17981,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
],
@@ -16949,13 +17998,42 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "baz",
+ "isReference": true
}
}
],
"text": "baz"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "baz",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[baz]: /url1"
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url2",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url2"
+ }
+ ]
}
]
}
@@ -16980,13 +18058,42 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "baz",
+ "isReference": true
}
}
],
"text": "bar"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "baz",
+ "url": "/url1",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[baz]: /url1"
+ }
+ ]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url2",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url2"
+ }
+ ]
}
]
}
@@ -17004,7 +18111,8 @@
"alt": "foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
]
@@ -17025,10 +18133,25 @@
"alt": "foo bar",
"title": "train & tracks",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo *bar*",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo *bar*",
+ "url": "train.jpg",
+ "title": "train & tracks"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo *bar*]: train.jpg \"train & tracks\""
+ }
+ ]
}
]
}
@@ -17046,7 +18169,8 @@
"alt": "foo bar",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "/url2",
+ "isReference": false
}
}
]
@@ -17067,7 +18191,8 @@
"alt": "foo bar",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "/url2",
+ "isReference": false
}
}
]
@@ -17088,10 +18213,25 @@
"alt": "foo bar",
"title": "train & tracks",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo *bar*",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo *bar*",
+ "url": "train.jpg",
+ "title": "train & tracks"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo *bar*]: train.jpg \"train & tracks\""
+ }
+ ]
}
]
}
@@ -17109,10 +18249,25 @@
"alt": "foo bar",
"title": "train & tracks",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foobar",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foobar",
+ "url": "train.jpg",
+ "title": "train & tracks"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foobar]: train.jpg \"train & tracks\""
+ }
+ ]
}
]
}
@@ -17130,7 +18285,8 @@
"alt": "foo",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "train.jpg",
+ "isReference": false
}
}
]
@@ -17155,7 +18311,8 @@
"alt": "foo bar",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "/path/to/train.jpg",
+ "isReference": false
}
}
]
@@ -17176,7 +18333,8 @@
"alt": "foo",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "url",
+ "isReference": false
}
}
]
@@ -17197,7 +18355,8 @@
"alt": "",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "/url",
+ "isReference": false
}
}
]
@@ -17218,10 +18377,25 @@
"alt": "foo",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url"
+ }
+ ]
}
]
}
@@ -17239,10 +18413,25 @@
"alt": "foo",
"title": null,
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "bar",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "bar",
+ "url": "/url",
+ "title": null
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[bar]: /url"
+ }
+ ]
}
]
}
@@ -17260,10 +18449,25 @@
"alt": "foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17281,10 +18485,25 @@
"alt": "foo bar",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "*foo* bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[*foo* bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17302,10 +18521,25 @@
"alt": "Foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17323,7 +18557,8 @@
"alt": "foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
},
{
@@ -17331,6 +18566,20 @@
"text": "\n[]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17348,10 +18597,25 @@
"alt": "foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17369,10 +18633,25 @@
"alt": "foo bar",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "*foo* bar",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "*foo* bar",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[*foo* bar]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17414,10 +18693,25 @@
"alt": "Foo",
"title": "title",
"uploading": false,
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17433,6 +18727,20 @@
"text": "![foo]"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17457,13 +18765,28 @@
"target": "_blank",
"class": null,
"title": "title",
- "canonicalSrc": null
+ "canonicalSrc": "foo",
+ "isReference": true
}
}
],
"text": "foo"
}
]
+ },
+ {
+ "type": "referenceDefinition",
+ "attrs": {
+ "identifier": "foo",
+ "url": "/url",
+ "title": "title"
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "[foo]: /url \"title\""
+ }
+ ]
}
]
}
@@ -17484,7 +18807,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar.baz",
+ "isReference": false
}
}
],
@@ -17511,7 +18835,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar.baz/test?q=hello&id=22&boolean",
+ "isReference": false
}
}
],
@@ -17534,11 +18859,12 @@
{
"type": "link",
"attrs": {
- "href": "irc://foo.bar:2233/baz",
+ "href": null,
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": null,
+ "isReference": false
}
}
],
@@ -17565,7 +18891,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "MAILTO:FOO@BAR.BAZ",
+ "isReference": false
}
}
],
@@ -17588,11 +18915,12 @@
{
"type": "link",
"attrs": {
- "href": "a+b+c:d",
+ "href": null,
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": null,
+ "isReference": false
}
}
],
@@ -17615,11 +18943,12 @@
{
"type": "link",
"attrs": {
- "href": "made-up-scheme://foo,bar",
+ "href": null,
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": null,
+ "isReference": false
}
}
],
@@ -17646,7 +18975,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://../",
+ "isReference": false
}
}
],
@@ -17669,11 +18999,12 @@
{
"type": "link",
"attrs": {
- "href": "localhost:5001/foo",
+ "href": null,
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": null,
+ "isReference": false
}
}
],
@@ -17704,7 +19035,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar/baz",
+ "isReference": false
}
}
],
@@ -17735,7 +19067,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com/%5C%5B%5C",
+ "isReference": false
}
}
],
@@ -17762,7 +19095,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:foo@bar.example.com",
+ "isReference": false
}
}
],
@@ -17789,7 +19123,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:foo+special@Bar.baz-bar0.com",
+ "isReference": false
}
}
],
@@ -17820,7 +19155,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:foo+@bar.example.com",
+ "isReference": false
}
}
],
@@ -17870,7 +19206,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://foo.bar",
+ "isReference": false
}
}
],
@@ -17931,7 +19268,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://example.com",
+ "isReference": false
}
}
],
@@ -17958,7 +19296,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:foo@bar.example.com",
+ "isReference": false
}
}
],
@@ -17985,7 +19324,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.commonmark.org",
+ "isReference": false
}
}
],
@@ -18016,7 +19356,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.commonmark.org/help",
+ "isReference": false
}
}
],
@@ -18051,7 +19392,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.commonmark.org",
+ "isReference": false
}
}
],
@@ -18080,7 +19422,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.commonmark.org/a.b",
+ "isReference": false
}
}
],
@@ -18111,7 +19454,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
+ "isReference": false
}
}
],
@@ -18132,7 +19476,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
+ "isReference": false
}
}
],
@@ -18161,7 +19506,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
+ "isReference": false
}
}
],
@@ -18190,7 +19536,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
+ "isReference": false
}
}
],
@@ -18217,7 +19564,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=(business))+ok",
+ "isReference": false
}
}
],
@@ -18244,7 +19592,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=commonmark&hl=en",
+ "isReference": false
}
}
],
@@ -18265,7 +19614,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.google.com/search?q=commonmark",
+ "isReference": false
}
}
],
@@ -18296,7 +19646,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://www.commonmark.org/he",
+ "isReference": false
}
}
],
@@ -18327,7 +19678,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "http://commonmark.org",
+ "isReference": false
}
}
],
@@ -18352,7 +19704,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "https://encrypted.google.com/search?q=Markup+(business)",
+ "isReference": false
}
}
],
@@ -18392,7 +19745,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:foo@bar.baz",
+ "isReference": false
}
}
],
@@ -18423,7 +19777,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:hello+xyz@mail.example",
+ "isReference": false
}
}
],
@@ -18454,7 +19809,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:a.b-c_d@a.b",
+ "isReference": false
}
}
],
@@ -18475,7 +19831,8 @@
"target": "_blank",
"class": null,
"title": null,
- "canonicalSrc": null
+ "canonicalSrc": "mailto:a.b-c_d@a.b",
+ "isReference": false
}
}
],
@@ -19218,8 +20575,8 @@
{
"type": "footnoteReference",
"attrs": {
- "identifier": "1",
- "label": "1"
+ "identifier": "fortytwo",
+ "label": "fortytwo"
}
}
]
@@ -19227,8 +20584,8 @@
{
"type": "footnoteDefinition",
"attrs": {
- "identifier": "1",
- "label": "1"
+ "identifier": "fortytwo",
+ "label": "fortytwo"
},
"content": [
{
@@ -19244,3 +20601,184 @@
}
]
}
+07_02__gitlab_specific_markdown__task_list_items__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "taskList",
+ "attrs": {
+ "numeric": false,
+ "start": 1,
+ "parens": false
+ },
+ "content": [
+ {
+ "type": "taskItem",
+ "attrs": {
+ "checked": false
+ },
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "incomplete"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+07_02__gitlab_specific_markdown__task_list_items__002: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "taskList",
+ "attrs": {
+ "numeric": false,
+ "start": 1,
+ "parens": false
+ },
+ "content": [
+ {
+ "type": "taskItem",
+ "attrs": {
+ "checked": true
+ },
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "completed"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+07_02__gitlab_specific_markdown__task_list_items__003: |-
+ Inapplicable task list items not yet implemented for WYSYWIG
+07_02__gitlab_specific_markdown__task_list_items__004: |-
+ Inapplicable task list items not yet implemented for WYSYWIG
+07_03__gitlab_specific_markdown__front_matter__001: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "frontmatter",
+ "attrs": {
+ "language": "yaml",
+ "class": "code highlight",
+ "isFrontmatter": true
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "title: YAML front matter"
+ }
+ ]
+ }
+ ]
+ }
+07_03__gitlab_specific_markdown__front_matter__002: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "frontmatter",
+ "attrs": {
+ "language": "toml",
+ "class": "code highlight",
+ "isFrontmatter": true
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "title: TOML front matter"
+ }
+ ]
+ }
+ ]
+ }
+07_03__gitlab_specific_markdown__front_matter__003: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "frontmatter",
+ "attrs": {
+ "language": "json",
+ "class": "code highlight",
+ "isFrontmatter": true
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "{\n \"title\": \"JSON front matter\"\n}"
+ }
+ ]
+ }
+ ]
+ }
+07_03__gitlab_specific_markdown__front_matter__004: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "paragraph",
+ "content": [
+ {
+ "type": "text",
+ "text": "text"
+ }
+ ]
+ },
+ {
+ "type": "horizontalRule"
+ },
+ {
+ "type": "heading",
+ "attrs": {
+ "level": 2
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "title: YAML front matter"
+ }
+ ]
+ }
+ ]
+ }
+07_03__gitlab_specific_markdown__front_matter__005: |-
+ {
+ "type": "doc",
+ "content": [
+ {
+ "type": "horizontalRule"
+ },
+ {
+ "type": "heading",
+ "attrs": {
+ "level": 2
+ },
+ "content": [
+ {
+ "type": "text",
+ "text": "title: YAML front matter"
+ }
+ ]
+ }
+ ]
+ }
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt b/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
index e4d01b4a813..332b311dff2 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
@@ -14,7 +14,188 @@ 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
-footnote reference tag [^1]
+footnote reference tag [^fortytwo]
-[^1]: footnote text
+[^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 tasklist
+- [ ] incomplete
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" disabled/>
+incomplete
+</li>
+</ul>
+````````````````````````````````
+
+Completed task:
+
+```````````````````````````````` example gitlab tasklist
+- [x] completed
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" checked disabled/>
+completed
+</li>
+</ul>
+````````````````````````````````
+
+Inapplicable task:
+
+```````````````````````````````` example gitlab tasklist
+- [~] 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 tasklist
+- [~] 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 frontmatter
+---
+title: YAML front matter
+---
+.
+<pre>
+<code>
+title: YAML front matter
+</code>
+</pre>
+````````````````````````````````
+
+TOML front matter:
+
+```````````````````````````````` example gitlab frontmatter
++++
+title: TOML front matter
++++
+.
+<pre>
+<code>
+title: TOML front matter
+</code>
+</pre>
+````````````````````````````````
+
+JSON front matter:
+
+```````````````````````````````` example gitlab frontmatter
+;;;
+{
+ "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 frontmatter
+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 frontmatter
+ ---
+title: YAML front matter
+---
+.
+<hr>
+<h2>title: YAML front matter</h2>
````````````````````````````````
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 b09a092c02a..3881819e38a 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml
@@ -12,3 +12,15 @@
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__gitlab_specific_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__gitlab_specific_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
diff --git a/glfm_specification/output/spec.txt b/glfm_specification/output/spec.txt
index c81daf7f689..32cb6a0594e 100644
--- a/glfm_specification/output/spec.txt
+++ b/glfm_specification/output/spec.txt
@@ -9616,9 +9616,190 @@ 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
-footnote reference tag [^1]
+footnote reference tag [^fortytwo]
-[^1]: footnote text
+[^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 tasklist
+- [ ] incomplete
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" disabled/>
+incomplete
+</li>
+</ul>
+````````````````````````````````
+
+Completed task:
+
+```````````````````````````````` example gitlab tasklist
+- [x] completed
+.
+<ul>
+<li>
+<task-button/>
+<input type="checkbox" checked disabled/>
+completed
+</li>
+</ul>
+````````````````````````````````
+
+Inapplicable task:
+
+```````````````````````````````` example gitlab tasklist
+- [~] 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 tasklist
+- [~] 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 frontmatter
+---
+title: YAML front matter
+---
+.
+<pre>
+<code>
+title: YAML front matter
+</code>
+</pre>
+````````````````````````````````
+
+TOML front matter:
+
+```````````````````````````````` example gitlab frontmatter
++++
+title: TOML front matter
++++
+.
+<pre>
+<code>
+title: TOML front matter
+</code>
+</pre>
+````````````````````````````````
+
+JSON front matter:
+
+```````````````````````````````` example gitlab frontmatter
+;;;
+{
+ "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 frontmatter
+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 frontmatter
+ ---
+title: YAML front matter
+---
+.
+<hr>
+<h2>title: YAML front matter</h2>
````````````````````````````````
<!-- END TESTS -->
diff --git a/jest.config.base.js b/jest.config.base.js
index d4b1ace3b2c..d90a3b9825e 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -146,9 +146,11 @@ module.exports = (path, options = {}) => {
'monaco-yaml',
'fast-mersenne-twister',
'prosemirror-markdown',
+ 'marked',
'fault',
'dateformat',
'lowlight',
+ 'vscode-languageserver-types',
...gfmParserDependencies,
];
@@ -168,21 +170,23 @@ module.exports = (path, options = {}) => {
resolver: './jest_resolver.js',
setupFilesAfterEnv: [`<rootDir>/${path}/test_setup.js`, 'jest-canvas-mock'],
restoreMocks: true,
+ slowTestThreshold: process.env.CI ? 6000 : 500,
transform: {
'^.+\\.(gql|graphql)$': 'jest-transform-graphql',
'^.+_worker\\.js$': './spec/frontend/__helpers__/web_worker_transformer.js',
'^.+\\.js$': 'babel-jest',
- '^.+\\.vue$': 'vue-jest',
+ '^.+\\.vue$': '@vue/vue2-jest',
'spec/frontend/editor/schema/ci/yaml_tests/.+\\.(yml|yaml)$':
'./spec/frontend/__helpers__/yaml_transformer.js',
'^.+\\.(md|zip|png|yml|yaml)$': 'jest-raw-loader',
},
transformIgnorePatterns: [`node_modules/(?!(${transformIgnoreNodeModules.join('|')}))`],
- timers: 'fake',
+ timers: 'legacy',
testEnvironment: '<rootDir>/spec/frontend/environment.js',
testEnvironmentOptions: {
IS_EE,
IS_JH,
},
+ testRunner: 'jest-jasmine2',
};
};
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 8827371546c..e4158eee37f 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -22,6 +22,7 @@ module API
Gitlab::GrapeLogging::Loggers::ClientEnvLogger.new,
Gitlab::GrapeLogging::Loggers::RouteLogger.new,
Gitlab::GrapeLogging::Loggers::UserLogger.new,
+ Gitlab::GrapeLogging::Loggers::TokenLogger.new,
Gitlab::GrapeLogging::Loggers::ExceptionLogger.new,
Gitlab::GrapeLogging::Loggers::QueueDurationLogger.new,
Gitlab::GrapeLogging::Loggers::PerfLogger.new,
@@ -47,6 +48,12 @@ module API
before do
header['X-Frame-Options'] = 'SAMEORIGIN'
header['X-Content-Type-Options'] = 'nosniff'
+
+ if Rails.application.config.content_security_policy && !Rails.application.config.content_security_policy_report_only
+ policy = ActionDispatch::ContentSecurityPolicy.new { |p| p.default_src :none }
+ end
+
+ request.env[ActionDispatch::ContentSecurityPolicy::Request::POLICY] = policy
end
before do
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 8822a30d4a1..df550f12c0d 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -48,7 +48,9 @@ module API
include Gitlab::Auth::AuthFinders
def access_token
- super || find_personal_access_token_from_http_basic_auth
+ strong_memoize(:api_guard_access_token) do
+ super || find_personal_access_token_from_http_basic_auth
+ end
end
def find_current_user!
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 346bd6ccfe4..70488621f33 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -17,8 +17,10 @@ module API
requires :redirect_uri, type: String, desc: 'Application redirect URI'
requires :scopes, type: String, desc: 'Application scopes', allow_blank: false
- optional :confidential, type: Boolean, default: true,
- desc: 'Application will be used where the client secret is confidential'
+ optional :confidential,
+ type: Boolean,
+ default: true,
+ desc: 'Application will be used where the client secret is confidential'
end
post do
application = Doorkeeper::Application.new(declared_params)
diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb
index e818cad0d03..6af7c3b4804 100644
--- a/lib/api/broadcast_messages.rb
+++ b/lib/api/broadcast_messages.rb
@@ -37,8 +37,11 @@ module API
optional :ends_at, type: DateTime, desc: 'Ending time', default: -> { 1.hour.from_now }
optional :color, type: String, desc: 'Background color'
optional :font, type: String, desc: 'Foreground color'
- optional :target_access_levels, type: Array[Integer], coerce_with: Validations::Types::CommaSeparatedToIntegerArray.coerce,
- values: BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS, desc: 'Target user roles'
+ optional :target_access_levels,
+ type: Array[Integer],
+ coerce_with: Validations::Types::CommaSeparatedToIntegerArray.coerce,
+ values: BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS,
+ desc: 'Target user roles'
optional :target_path, type: String, desc: 'Target path'
optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast type. Defaults to banner', default: -> { 'banner' }
optional :dismissable, type: Boolean, desc: 'Is dismissable'
@@ -79,8 +82,11 @@ module API
optional :ends_at, type: DateTime, desc: 'Ending time'
optional :color, type: String, desc: 'Background color'
optional :font, type: String, desc: 'Foreground color'
- optional :target_access_levels, type: Array[Integer], coerce_with: Validations::Types::CommaSeparatedToIntegerArray.coerce,
- values: BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS, desc: 'Target user roles'
+ optional :target_access_levels,
+ type: Array[Integer],
+ coerce_with: Validations::Types::CommaSeparatedToIntegerArray.coerce,
+ values: BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS,
+ desc: 'Target user roles'
optional :target_path, type: String, desc: 'Target path'
optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast Type'
optional :dismissable, type: Boolean, desc: 'Is dismissable'
diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb
index b1cb84c97cb..2c6adc0f37b 100644
--- a/lib/api/bulk_imports.rb
+++ b/lib/api/bulk_imports.rb
@@ -44,14 +44,29 @@ module API
requires :access_token, type: String, desc: 'Access token to the source GitLab instance'
end
requires :entities, type: Array, desc: 'List of entities to import' do
- requires :source_type, type: String, desc: 'Source entity type (only `group_entity` is supported)',
+ requires :source_type,
+ type: String,
+ desc: 'Source entity type (only `group_entity` is supported)',
values: %w[group_entity]
requires :source_full_path, type: String, desc: 'Source full path of the entity to import'
- requires :destination_name, type: String, desc: 'Destination slug for the entity'
requires :destination_namespace, type: String, desc: 'Destination namespace for the entity'
+ optional :destination_slug, type: String, desc: 'Destination slug for the entity'
+ optional :destination_name,
+ type: String,
+ desc: 'Deprecated: Use :destination_slug instead. Destination slug for the entity'
+
+ mutually_exclusive :destination_slug, :destination_name
+ at_least_one_of :destination_slug, :destination_name
end
end
post do
+ params[:entities].each do |entity|
+ if entity[:destination_name]
+ entity[:destination_slug] ||= entity[:destination_name]
+ entity.delete(:destination_name)
+ end
+ end
+
response = ::BulkImports::CreateService.new(
current_user,
params[:entities],
@@ -72,9 +87,9 @@ module API
params do
use :pagination
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.'
+ desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.'
optional :status, type: String, values: BulkImport.all_human_statuses,
- desc: 'Return GitLab Migrations with specified status'
+ desc: 'Return GitLab Migrations with specified status'
end
get do
present paginate(bulk_imports), with: Entities::BulkImport
@@ -86,9 +101,9 @@ module API
params do
use :pagination
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.'
+ desc: 'Return GitLab Migrations sorted in created by `asc` or `desc` order.'
optional :status, type: String, values: ::BulkImports::Entity.all_human_statuses,
- desc: "Return all GitLab Migrations' entities with specified status"
+ desc: "Return all GitLab Migrations' entities with specified status"
end
get :entities do
entities = ::BulkImports::EntitiesFinder.new(
@@ -115,7 +130,7 @@ module API
params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
optional :status, type: String, values: ::BulkImports::Entity.all_human_statuses,
- desc: 'Return import entities with specified status'
+ desc: 'Return import entities with specified status'
use :pagination
end
get ':import_id/entities' do
diff --git a/lib/api/ci/helpers/runner.rb b/lib/api/ci/helpers/runner.rb
index fe49074afed..269f2fa7ddc 100644
--- a/lib/api/ci/helpers/runner.rb
+++ b/lib/api/ci/helpers/runner.rb
@@ -138,17 +138,13 @@ module API
def set_application_context
return unless current_job
- Gitlab::ApplicationContext.push(job: current_job)
+ Gitlab::ApplicationContext.push(job: current_job, runner: current_runner)
end
def track_ci_minutes_usage!(_build, _runner)
# noop: overridden in EE
end
- def log_artifact_size(artifact)
- Gitlab::ApplicationContext.push(artifact: artifact)
- end
-
private
def get_runner_config_from_request
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb
index 8b332f96be0..b843404e9d7 100644
--- a/lib/api/ci/job_artifacts.rb
+++ b/lib/api/ci/job_artifacts.rb
@@ -30,15 +30,16 @@ module API
requires :job, type: String, desc: 'The name for the job'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/artifacts/:ref_name/download', urgency: :low,
- requirements: { ref_name: /.+/ } do
- authorize_download_artifacts!
+ get ':id/jobs/artifacts/:ref_name/download',
+ urgency: :low,
+ requirements: { ref_name: /.+/ } do
+ authorize_download_artifacts!
- latest_build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
- authorize_read_job_artifacts!(latest_build)
+ 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)
- end
+ present_artifacts_file!(latest_build.artifacts_file)
+ end
desc 'Download a specific file from artifacts archive from a ref' do
detail 'This feature was introduced in GitLab 11.5'
@@ -49,21 +50,22 @@ module API
requires :artifact_path, type: String, desc: 'Artifact path'
end
route_setting :authentication, job_token_allowed: true
- get ':id/jobs/artifacts/:ref_name/raw/*artifact_path', urgency: :low,
- format: false,
- requirements: { ref_name: /.+/ } do
- authorize_download_artifacts!
+ get ':id/jobs/artifacts/:ref_name/raw/*artifact_path',
+ urgency: :low,
+ format: false,
+ requirements: { ref_name: /.+/ } do
+ authorize_download_artifacts!
- build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
- authorize_read_job_artifacts!(build)
+ build = user_project.latest_successful_build_for_ref!(params[:job], params[:ref_name])
+ authorize_read_job_artifacts!(build)
- path = Gitlab::Ci::Build::Artifacts::Path
- .new(params[:artifact_path])
+ path = Gitlab::Ci::Build::Artifacts::Path
+ .new(params[:artifact_path])
- bad_request! unless path.valid?
+ bad_request! unless path.valid?
- send_artifacts_entry(build.artifacts_file, path)
- end
+ send_artifacts_entry(build.artifacts_file, path)
+ end
desc 'Download the artifacts archive from a job' do
detail 'This feature was introduced in GitLab 8.5'
diff --git a/lib/api/ci/jobs.rb b/lib/api/ci/jobs.rb
index 97471d3c96e..cd5f1f77ced 100644
--- a/lib/api/ci/jobs.rb
+++ b/lib/api/ci/jobs.rb
@@ -152,8 +152,8 @@ module API
end
params do
requires :job_id, type: Integer, desc: 'The ID of a Job'
- optional :job_variables_attributes, type: Array,
- desc: 'User defined variables that will be included when running the job' do
+ optional :job_variables_attributes,
+ type: Array, desc: 'User defined variables that will be included when running the job' do
requires :key, type: String, desc: 'The name of the variable'
requires :value, type: String, desc: 'The value of the variable'
end
diff --git a/lib/api/ci/pipeline_schedules.rb b/lib/api/ci/pipeline_schedules.rb
index 4b522f37524..886c3509c51 100644
--- a/lib/api/ci/pipeline_schedules.rb
+++ b/lib/api/ci/pipeline_schedules.rb
@@ -42,6 +42,16 @@ module API
present pipeline_schedule, with: Entities::Ci::PipelineScheduleDetails, user: current_user
end
+ desc 'Get all pipelines triggered from a pipeline schedule' do
+ success Entities::Ci::PipelineBasic
+ end
+ params do
+ requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule ID'
+ end
+ get ':id/pipeline_schedules/:pipeline_schedule_id/pipelines' do
+ present paginate(pipeline_schedule.pipelines), with: Entities::Ci::PipelineBasic
+ end
+
desc 'Create a new pipeline schedule' do
success Entities::Ci::PipelineScheduleDetails
end
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index cd686a28dd2..72a81330e71 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -21,17 +21,17 @@ module API
helpers do
params :optional_scope do
optional :scope, types: [String, Array[String]], desc: 'The scope of builds to show',
- values: ::CommitStatus::AVAILABLE_STATUSES,
- coerce_with: ->(scope) {
- case scope
- when String
- [scope]
- when ::Array
- scope
- else
- ['unknown']
- end
- }
+ values: ::CommitStatus::AVAILABLE_STATUSES,
+ coerce_with: ->(scope) {
+ case scope
+ when String
+ [scope]
+ when ::Array
+ scope
+ else
+ ['unknown']
+ end
+ }
end
end
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 65dc002e67d..9e4a700d0f3 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -38,7 +38,8 @@ module API
attributes[:maintenance_note] ||= deprecated_note if deprecated_note
attributes[:active] = !attributes.delete(:paused) if attributes.include?(:paused)
- @runner = ::Ci::Runners::RegisterRunnerService.new.execute(params[:token], attributes)
+ result = ::Ci::Runners::RegisterRunnerService.new.execute(params[:token], attributes)
+ @runner = result.success? ? result.payload[:runner] : nil
forbidden! unless @runner
if @runner.persisted?
@@ -255,7 +256,7 @@ module API
optional :filesize, type: Integer, desc: %q(Artifacts filesize)
optional :artifact_type, type: String, desc: %q(The type of artifact),
- default: 'archive', values: ::Ci::JobArtifact.file_types.keys
+ default: 'archive', values: ::Ci::JobArtifact.file_types.keys
end
post '/:id/artifacts/authorize', feature_category: :build_artifacts, urgency: :low do
not_allowed! unless Gitlab.config.artifacts.enabled
@@ -288,9 +289,9 @@ module API
optional :token, type: String, desc: %q(Job's authentication token)
optional :expire_in, type: String, desc: %q(Specify when artifacts should expire)
optional :artifact_type, type: String, desc: %q(The type of artifact),
- default: 'archive', values: ::Ci::JobArtifact.file_types.keys
+ default: 'archive', values: ::Ci::JobArtifact.file_types.keys
optional :artifact_format, type: String, desc: %q(The format of artifact),
- default: 'zip', values: ::Ci::JobArtifact.file_formats.keys
+ default: 'zip', values: ::Ci::JobArtifact.file_formats.keys
optional :metadata, type: ::API::Validations::Types::WorkhorseFile, desc: %(The artifact metadata to store (generated by Multipart middleware))
end
post '/:id/artifacts', feature_category: :build_artifacts, urgency: :low do
@@ -305,7 +306,8 @@ module API
result = ::Ci::JobArtifacts::CreateService.new(job).execute(artifacts, params, metadata_file: metadata)
if result[:status] == :success
- log_artifact_size(result[:artifact])
+ log_artifacts_filesize(result[:artifact])
+
status :created
body "201"
else
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index 06bfee59140..ec9b09a3419 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -16,7 +16,7 @@ module API
end
params do
optional :scope, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
- desc: 'The scope of specific runners to show'
+ desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
@@ -38,7 +38,7 @@ module API
end
params do
optional :scope, type: String, values: ::Ci::Runner::AVAILABLE_SCOPES,
- desc: 'The scope of specific runners to show'
+ desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
@@ -159,7 +159,7 @@ module API
end
params do
optional :scope, type: String, values: ::Ci::Runner::AVAILABLE_SCOPES,
- desc: 'The scope of specific runners to show'
+ desc: 'The scope of specific runners to show'
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
desc: 'The type of the runners to show'
optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
@@ -188,7 +188,7 @@ module API
runner = get_runner(params[:runner_id])
authenticate_enable_runner!(runner)
- if ::Ci::Runners::AssignRunnerService.new(runner, user_project, current_user).execute
+ if ::Ci::Runners::AssignRunnerService.new(runner, user_project, current_user).execute.success?
present runner, with: Entities::Ci::Runner
else
render_validation_error!(runner)
@@ -225,10 +225,10 @@ module API
end
params do
optional :type, type: String, values: ::Ci::Runner::AVAILABLE_TYPES,
- desc: 'The type of the runners to show'
+ desc: 'The type of the runners to show'
optional :paused, type: Boolean, desc: 'Whether to include only runners that are accepting or ignoring new jobs'
optional :status, type: String, values: ::Ci::Runner::AVAILABLE_STATUSES,
- desc: 'The status of the runners to show'
+ desc: 'The status of the runners to show'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show'
use :pagination
end
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 5fd9a8e3278..7a6c3e4d53f 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -10,6 +10,8 @@ module API
before do
require_repository_enabled!
authorize! :download_code, user_project
+
+ verify_pagination_params!
end
helpers do
@@ -86,7 +88,7 @@ module API
requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide either `start_branch` or `start_sha`, and optionally `start_project`.', allow_blank: false
requires :commit_message, type: String, desc: 'Commit message'
requires :actions, type: Array, desc: 'Actions to perform in commit' do
- requires :action, type: String, desc: 'The action to perform, `create`, `delete`, `move`, `update`, `chmod`', values: %w[create update move delete chmod].freeze
+ requires :action, type: String, desc: 'The action to perform, `create`, `delete`, `move`, `update`, `chmod`', values: %w[create update move delete chmod].freeze, allow_blank: false
requires :file_path, type: String, desc: 'Full path to the file. Ex. `lib/class.rb`'
given action: ->(action) { action == 'move' } do
requires :previous_path, type: String, desc: 'Original full path to the file being moved. Ex. `lib/class1.rb`'
@@ -302,8 +304,8 @@ module API
not_found!('Commit') unless commit
refs = []
- refs.concat(user_project.repository.branch_names_contains(commit.id).map {|name| { type: 'branch', name: name }}) unless params[:type] == 'tag'
- refs.concat(user_project.repository.tag_names_contains(commit.id).map {|name| { type: 'tag', name: name }}) unless params[:type] == 'branch'
+ refs.concat(user_project.repository.branch_names_contains(commit.id).map { |name| { type: 'branch', name: name } }) unless params[:type] == 'tag'
+ refs.concat(user_project.repository.tag_names_contains(commit.id).map { |name| { type: 'tag', name: name } }) unless params[:type] == 'branch'
refs = Kaminari.paginate_array(refs)
present paginate(refs), with: Entities::BasicRef
diff --git a/lib/api/concerns/packages/debian_distribution_endpoints.rb b/lib/api/concerns/packages/debian_distribution_endpoints.rb
index e01f3adbb06..380966136df 100644
--- a/lib/api/concerns/packages/debian_distribution_endpoints.rb
+++ b/lib/api/concerns/packages/debian_distribution_endpoints.rb
@@ -33,13 +33,13 @@ module API
optional :valid_time_duration_seconds, type: Integer, desc: 'The duration before the Release file should be considered expired by the client'
optional :components, type: Array[String],
- coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
- regexp: Gitlab::Regex.debian_component_regex,
- desc: 'The list of Components'
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ regexp: Gitlab::Regex.debian_component_regex,
+ desc: 'The list of Components'
optional :architectures, type: Array[String],
- coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
- regexp: Gitlab::Regex.debian_architecture_regex,
- desc: 'The list of Architectures'
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ regexp: Gitlab::Regex.debian_architecture_regex,
+ desc: 'The list of Architectures'
end
end
diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb
index ca576254c3d..06846d8f36e 100644
--- a/lib/api/debian_project_packages.rb
+++ b/lib/api/debian_project_packages.rb
@@ -73,10 +73,10 @@ module API
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)
file_params = {
- file: params['file'],
- file_name: params['file_name'],
- file_sha1: params['file.sha1'],
- file_md5: params['file.md5']
+ file: params['file'],
+ file_name: params['file_name'],
+ file_sha1: params['file.sha1'],
+ file_md5: params['file.md5']
}
package = ::Packages::Debian::FindOrCreateIncomingService.new(authorized_user_project, current_user).execute
diff --git a/lib/api/deploy_tokens.rb b/lib/api/deploy_tokens.rb
index 3e0411d2e91..3955e29621f 100644
--- a/lib/api/deploy_tokens.rb
+++ b/lib/api/deploy_tokens.rb
@@ -71,8 +71,11 @@ module API
params do
requires :name, type: String, desc: "New deploy token's name"
- requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
- desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".'
+ requires :scopes,
+ type: Array[String],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
+ desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".'
optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided.'
optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`'
end
@@ -152,8 +155,11 @@ module API
params do
requires :name, type: String, desc: 'The name of the deploy token'
- requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
- desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".'
+ requires :scopes,
+ type: Array[String],
+ coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
+ desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".'
optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided.'
optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`'
end
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 8db5f54b45a..ee0a026d7ac 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -119,9 +119,9 @@ module API
end
params do
requires :status,
- type: String,
- desc: 'The new status of the deployment',
- values: %w[running success failed canceled]
+ type: String,
+ desc: 'The new status of the deployment',
+ values: %w[running success failed canceled]
end
put ':id/deployments/:deployment_id' do
authorize!(:read_deployment, user_project)
@@ -143,6 +143,27 @@ module API
end
end
+ desc 'Deletes an existing deployment' do
+ detail 'This feature was introduced in GitLab 15.3'
+ http_codes [[204, 'Deployment was deleted'], [403, 'Forbidden'], [400, 'Cannot destroy']]
+ end
+ params do
+ requires :deployment_id, type: Integer, desc: 'The deployment ID'
+ end
+ delete ':id/deployments/:deployment_id' do
+ deployment = user_project.deployments.find(params[:deployment_id])
+
+ authorize!(:destroy_deployment, deployment)
+
+ destroy_conditionally!(deployment) do
+ result = ::Ci::Deployments::DestroyService.new(user_project, current_user).execute(deployment)
+
+ if result[:status] == :error
+ render_api_error!(result[:message], result[:http_status] || 400)
+ end
+ end
+ end
+
helpers Helpers::MergeRequestsHelpers
desc 'Get all merge requests of a deployment' do
diff --git a/lib/api/entities/bulk_imports/entity.rb b/lib/api/entities/bulk_imports/entity.rb
index e8c31256b17..142bfaf2149 100644
--- a/lib/api/entities/bulk_imports/entity.rb
+++ b/lib/api/entities/bulk_imports/entity.rb
@@ -8,7 +8,8 @@ module API
expose :bulk_import_id
expose :status_name, as: :status
expose :source_full_path
- expose :destination_name
+ expose :destination_name # deprecated
+ expose :destination_slug
expose :destination_namespace
expose :parent_id
expose :namespace_id
diff --git a/lib/api/entities/group_detail.rb b/lib/api/entities/group_detail.rb
index e521de0d572..7b05984421a 100644
--- a/lib/api/entities/group_detail.rb
+++ b/lib/api/entities/group_detail.rb
@@ -7,7 +7,8 @@ module API
SharedGroupWithGroup.represent(group.shared_with_group_links_visible_to_user(options[:current_user]))
end
expose :runners_token, if: ->(_, options) { options[:user_can_admin_group] }
- expose :prevent_sharing_groups_outside_hierarchy, if: ->(group) { group.root? }
+ expose :prevent_sharing_groups_outside_hierarchy,
+ if: ->(group) { group.root? && group.namespace_settings.present? }
expose :projects,
if: ->(_, options) { options[:with_projects] },
diff --git a/lib/api/entities/merge_request_reviewer.rb b/lib/api/entities/merge_request_reviewer.rb
new file mode 100644
index 00000000000..3bf2ccc36aa
--- /dev/null
+++ b/lib/api/entities/merge_request_reviewer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class MergeRequestReviewer < Grape::Entity
+ expose :reviewer, as: :user, using: Entities::UserBasic
+ expose :updated_state_by, using: Entities::UserBasic
+ expose :state
+ expose :created_at
+ end
+ end
+end
diff --git a/lib/api/entities/note.rb b/lib/api/entities/note.rb
index a597aa7bb4a..a92f534bbdc 100644
--- a/lib/api/entities/note.rb
+++ b/lib/api/entities/note.rb
@@ -26,6 +26,7 @@ module API
expose :resolved_at, if: ->(note, options) { note.resolvable? }
expose :confidential?, as: :confidential
+ expose :confidential?, as: :internal
# Avoid N+1 queries as much as possible
expose(:noteable_iid) { |note| note.noteable.iid if NOTEABLE_TYPES_WITH_IID.include?(note.noteable_type) }
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 906c252d7f9..1739bdd639e 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -47,8 +47,9 @@ module API
expose :visibility
expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group }
expose :resolve_outdated_diff_discussions
- expose :container_expiration_policy, using: Entities::ContainerExpirationPolicy,
- if: -> (project, _) { project.container_expiration_policy }
+ expose :container_expiration_policy,
+ using: Entities::ContainerExpirationPolicy,
+ if: -> (project, _) { project.container_expiration_policy }
# Expose old field names with the new permissions methods to keep API compatible
# TODO: remove in API v5, replaced by *_access_level
@@ -67,18 +68,18 @@ module API
Ability.allowed?(options[:current_user], :create_merge_request_in, project)
end
- expose(:issues_access_level) { |project, options| project.project_feature.string_access_level(:issues) }
- expose(:repository_access_level) { |project, options| project.project_feature.string_access_level(:repository) }
- expose(:merge_requests_access_level) { |project, options| project.project_feature.string_access_level(:merge_requests) }
- expose(:forking_access_level) { |project, options| project.project_feature.string_access_level(:forking) }
- expose(:wiki_access_level) { |project, options| project.project_feature.string_access_level(:wiki) }
- expose(:builds_access_level) { |project, options| project.project_feature.string_access_level(:builds) }
- expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) }
- expose(:pages_access_level) { |project, options| project.project_feature.string_access_level(:pages) }
- expose(:operations_access_level) { |project, options| project.project_feature.string_access_level(:operations) }
- expose(:analytics_access_level) { |project, options| project.project_feature.string_access_level(:analytics) }
- expose(:container_registry_access_level) { |project, options| project.project_feature.string_access_level(:container_registry) }
- expose(:security_and_compliance_access_level) { |project, options| project.project_feature.string_access_level(:security_and_compliance) }
+ expose(:issues_access_level) { |project, options| project_feature_string_access_level(project, :issues) }
+ expose(:repository_access_level) { |project, options| project_feature_string_access_level(project, :repository) }
+ expose(:merge_requests_access_level) { |project, options| project_feature_string_access_level(project, :merge_requests) }
+ expose(:forking_access_level) { |project, options| project_feature_string_access_level(project, :forking) }
+ expose(:wiki_access_level) { |project, options| project_feature_string_access_level(project, :wiki) }
+ expose(:builds_access_level) { |project, options| project_feature_string_access_level(project, :builds) }
+ expose(:snippets_access_level) { |project, options| project_feature_string_access_level(project, :snippets) }
+ expose(:pages_access_level) { |project, options| project_feature_string_access_level(project, :pages) }
+ expose(:operations_access_level) { |project, options| project_feature_string_access_level(project, :operations) }
+ 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 :emails_disabled
expose :shared_runners_enabled
@@ -105,13 +106,13 @@ module API
expose :ci_job_token_scope_enabled
expose :ci_separated_caches
expose :ci_opt_in_jwt
+ expose :ci_allow_fork_pipelines_to_run_in_parent_project
expose :public_builds, as: :public_jobs
expose :build_git_strategy, if: lambda { |project, options| options[:user_can_admin_project] } do |project, options|
project.build_allow_git_fetch ? 'fetch' : 'clone'
end
expose :build_timeout
expose :auto_cancel_pending_pipelines
- expose :build_coverage_regex
expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) }
expose :shared_with_groups do |project, options|
user = options[:current_user]
diff --git a/lib/api/feature_flags.rb b/lib/api/feature_flags.rb
index 42050888c14..67e96284449 100644
--- a/lib/api/feature_flags.rb
+++ b/lib/api/feature_flags.rb
@@ -24,8 +24,10 @@ module API
success ::API::Entities::FeatureFlag
end
params do
- optional :scope, type: String, desc: 'The scope of feature flags',
- values: %w[enabled disabled]
+ optional :scope,
+ type: String,
+ desc: 'The scope of feature flags',
+ values: %w[enabled disabled]
use :pagination
end
get do
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 13a6aedc2df..f89da48acea 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -69,11 +69,14 @@ module API
optional :key, type: String, desc: '`percentage_of_actors` or the default `percentage_of_time`'
optional :feature_group, type: String, desc: 'A Feature group name'
optional :user, type: String, desc: 'A GitLab username or comma-separated multiple usernames'
- optional :group, type: String,
+ optional :group,
+ type: String,
desc: "A GitLab group's path, such as 'gitlab-org', or comma-separated multiple group paths"
- optional :namespace, type: String,
+ optional :namespace,
+ type: String,
desc: "A GitLab group or user namespace path, such as 'john-doe', or comma-separated multiple namespace paths"
- optional :project, type: String,
+ optional :project,
+ type: String,
desc: "A projects path, such as `gitlab-org/gitlab-ce`, or comma-separated multiple project paths"
optional :force, type: Boolean, desc: 'Skip feature flag validation checks, ie. YAML definition'
diff --git a/lib/api/group_labels.rb b/lib/api/group_labels.rb
index e4cbe442f58..a8c48a6f4fe 100644
--- a/lib/api/group_labels.rb
+++ b/lib/api/group_labels.rb
@@ -19,15 +19,24 @@ module API
success Entities::GroupLabel
end
params do
- optional :with_counts, type: Boolean, default: false,
+ optional :with_counts,
+ type: Boolean,
+ default: false,
desc: 'Include issue and merge request counts'
- optional :include_ancestor_groups, type: Boolean, default: true,
+ optional :include_ancestor_groups,
+ type: Boolean,
+ default: true,
desc: 'Include ancestor groups'
- optional :include_descendant_groups, type: Boolean, default: false,
+ optional :include_descendant_groups,
+ type: Boolean,
+ default: false,
desc: 'Include descendant groups. This feature was added in GitLab 13.6'
- optional :only_group_labels, type: Boolean, default: true,
+ optional :only_group_labels,
+ type: Boolean,
+ default: true,
desc: 'Toggle to include only group labels or also project labels. This feature was added in GitLab 13.6'
- optional :search, type: String,
+ optional :search,
+ type: String,
desc: 'Keyword to filter labels by. This feature was added in GitLab 13.6'
use :pagination
end
@@ -40,11 +49,17 @@ module API
success Entities::GroupLabel
end
params do
- optional :include_ancestor_groups, type: Boolean, default: true,
+ optional :include_ancestor_groups,
+ type: Boolean,
+ default: true,
desc: 'Include ancestor groups'
- optional :include_descendant_groups, type: Boolean, default: false,
+ optional :include_descendant_groups,
+ type: Boolean,
+ default: false,
desc: 'Include descendant groups. This feature was added in GitLab 13.6'
- optional :only_group_labels, type: Boolean, default: true,
+ optional :only_group_labels,
+ type: Boolean,
+ default: true,
desc: 'Toggle to include only group labels or also project labels. This feature was added in GitLab 13.6'
end
get ':id/labels/:name' do
diff --git a/lib/api/group_packages.rb b/lib/api/group_packages.rb
index af6e2b1e422..72d67b41c31 100644
--- a/lib/api/group_packages.rb
+++ b/lib/api/group_packages.rb
@@ -24,17 +24,29 @@ module API
end
params do
use :pagination
- optional :order_by, type: String, values: %w[created_at name version type project_path], default: 'created_at',
- desc: 'Return packages ordered by `created_at`, `name`, `version` or `type` fields.'
- optional :sort, type: String, values: %w[asc desc], default: 'asc',
- desc: 'Return packages sorted in `asc` or `desc` order.'
- optional :package_type, type: String, values: Packages::Package.package_types.keys,
- desc: 'Return packages of a certain type'
- optional :package_name, type: String,
- desc: 'Return packages with this name'
- optional :include_versionless, type: Boolean,
- desc: 'Returns packages without a version'
- optional :status, type: String, values: Packages::Package.statuses.keys,
+ optional :order_by,
+ type: String,
+ values: %w[created_at name version type project_path],
+ default: 'created_at',
+ desc: 'Return packages ordered by `created_at`, `name`, `version` or `type` fields.'
+ optional :sort,
+ type: String,
+ values: %w[asc desc],
+ default: 'asc',
+ desc: 'Return packages sorted in `asc` or `desc` order.'
+ optional :package_type,
+ type: String,
+ values: Packages::Package.package_types.keys,
+ desc: 'Return packages of a certain type'
+ optional :package_name,
+ type: String,
+ desc: 'Return packages with this name'
+ optional :include_versionless,
+ type: Boolean,
+ desc: 'Returns packages without a version'
+ optional :status,
+ type: String,
+ values: Packages::Package.statuses.keys,
desc: 'Return packages with specified status'
end
get ':id/packages' do
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index b63396ed073..82bbab5d7d4 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -394,9 +394,10 @@ module API
desc 'Transfer a group to a new parent group or promote a subgroup to a root group'
params do
- optional :group_id, type: Integer,
- desc: 'The ID of the target group to which the group needs to be transferred to.'\
- 'If not provided, the source group will be promoted to a root group.'
+ optional :group_id,
+ type: Integer,
+ desc: 'The ID of the target group to which the group needs to be transferred to.'\
+ 'If not provided, the source group will be promoted to a root group.'
end
post ':id/transfer', feature_category: :subgroups do
group = find_group!(params[:id])
diff --git a/lib/api/helm_packages.rb b/lib/api/helm_packages.rb
index e0e4e02fa55..a1b265bc8f3 100644
--- a/lib/api/helm_packages.rb
+++ b/lib/api/helm_packages.rb
@@ -100,7 +100,7 @@ module API
).execute(:helm, name: ::Packages::Helm::TEMPORARY_PACKAGE_NAME)
chart_params = {
- file: params[:chart],
+ file: params[:chart],
file_name: PACKAGE_FILENAME
}
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index fdb0fbf820d..1d0f0c6e7bb 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -6,11 +6,13 @@ module API
include Helpers::Caching
include Helpers::Pagination
include Helpers::PaginationStrategies
+ include Gitlab::Ci::Artifacts::Logger
SUDO_HEADER = "HTTP_SUDO"
GITLAB_SHARED_SECRET_HEADER = "Gitlab-Shared-Secret"
SUDO_PARAM = :sudo
API_USER_ENV = 'gitlab.api.user'
+ API_TOKEN_ENV = 'gitlab.api.token'
API_EXCEPTION_ENV = 'gitlab.api.exception'
API_RESPONSE_STATUS_CODE = 'gitlab.api.response_status_code'
@@ -20,7 +22,11 @@ module API
end
def check_unmodified_since!(last_modified)
- if_unmodified_since = Time.parse(headers['If-Unmodified-Since']) rescue nil
+ if_unmodified_since = begin
+ Time.parse(headers['If-Unmodified-Since'])
+ rescue StandardError
+ nil
+ end
if if_unmodified_since && last_modified && last_modified > if_unmodified_since
render_api_error!('412 Precondition Failed', 412)
@@ -74,6 +80,8 @@ module API
save_current_user_in_env(@current_user) if @current_user
+ save_current_token_in_env
+
if @current_user
::ApplicationRecord
.sticking
@@ -88,6 +96,13 @@ module API
env[API_USER_ENV] = { user_id: user.id, username: user.username }
end
+ def save_current_token_in_env
+ token = access_token
+ env[API_TOKEN_ENV] = { token_id: token.id, token_type: token.class } if token
+
+ rescue Gitlab::Auth::UnauthorizedError
+ end
+
def sudo?
initial_current_user != current_user
end
@@ -574,12 +589,8 @@ module API
end
end
- def log_artifact_file_size(file)
- Gitlab::ApplicationContext.push(artifact: file.model)
- end
-
def present_artifacts_file!(file, **args)
- log_artifact_file_size(file) if file
+ log_artifacts_filesize(file&.model)
present_carrierwave_file!(file, **args)
end
diff --git a/lib/api/helpers/groups_helpers.rb b/lib/api/helpers/groups_helpers.rb
index 72bdb32d38c..2b10eebb009 100644
--- a/lib/api/helpers/groups_helpers.rb
+++ b/lib/api/helpers/groups_helpers.rb
@@ -9,8 +9,8 @@ module API
params :optional_params_ce do
optional :description, type: String, desc: 'The description of the group'
optional :visibility, type: String,
- values: Gitlab::VisibilityLevel.string_values,
- desc: 'The visibility of the group'
+ values: Gitlab::VisibilityLevel.string_values,
+ desc: 'The visibility of the group'
# TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960
optional :avatar, type: File, desc: 'Avatar image for the group' # rubocop:disable Scalability/FileUploads
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb
index 0b0100c7d7f..99273e81730 100644
--- a/lib/api/helpers/integrations_helpers.rb
+++ b/lib/api/helpers/integrations_helpers.rb
@@ -328,14 +328,12 @@ module API
type: String,
desc: '(Advanced) The full URL for your Datadog site'
},
- # TODO: uncomment this field once :datadog_integration_logs_collection is rolled out
- # https://gitlab.com/gitlab-org/gitlab/-/issues/346339
- # {
- # required: false,
- # name: :archive_trace_events,
- # type: Boolean,
- # desc: 'When enabled, job logs will be collected by Datadog and shown along pipeline execution traces'
- # },
+ {
+ required: false,
+ name: :archive_trace_events,
+ type: Boolean,
+ desc: 'When enabled, job logs will be collected by Datadog and shown along pipeline execution traces'
+ },
{
required: false,
name: :datadog_service,
@@ -678,6 +676,15 @@ module API
desc: 'Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'
}
],
+ 'pumble' => [
+ {
+ required: true,
+ name: :webhook,
+ type: String,
+ desc: 'The Pumble chat webhook. For example, https://api.pumble.com/workspaces/x/...'
+ },
+ chat_notification_events
+ ].flatten,
'pushover' => [
{
required: true,
diff --git a/lib/api/helpers/merge_requests_helpers.rb b/lib/api/helpers/merge_requests_helpers.rb
index 00d9f49adf0..85648cd166d 100644
--- a/lib/api/helpers/merge_requests_helpers.rb
+++ b/lib/api/helpers/merge_requests_helpers.rb
@@ -17,7 +17,9 @@ module API
types: [Integer, String],
integer_none_any: true,
desc: 'Return merge requests which are assigned to the user with the given ID'
- optional :assignee_username, type: Array[String], check_assignees_count: true,
+ optional :assignee_username,
+ type: Array[String],
+ check_assignees_count: true,
coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
desc: 'Return merge requests which are assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
@@ -129,7 +131,7 @@ module API
end
def self.sort_options_help
- sort_options.map {|y| "`#{y}`" }.to_sentence(last_word_connector: ' or ')
+ sort_options.map { |y| "`#{y}`" }.to_sentence(last_word_connector: ' or ')
end
end
end
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 3a518959b2c..628182ad1ab 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -96,6 +96,7 @@ module API
params :optional_update_params_ce do
optional :ci_forward_deployment_enabled, type: Boolean, desc: 'Skip older deployment jobs that are still pending'
+ optional :ci_allow_fork_pipelines_to_run_in_parent_project, type: Boolean, desc: 'Allow fork merge request pipelines to run in parent project'
optional :ci_separated_caches, type: Boolean, desc: 'Enable or disable separated caches based on branch protection.'
optional :restrict_user_defined_variables, type: Boolean, desc: 'Restrict use of user-defined variables when triggering a pipeline'
end
@@ -130,6 +131,7 @@ module API
:builds_access_level,
:ci_config_path,
:ci_default_git_depth,
+ :ci_allow_fork_pipelines_to_run_in_parent_project,
:ci_forward_deployment_enabled,
:ci_separated_caches,
:container_registry_access_level,
diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb
index d0eda68bf52..27fcc0a68fb 100644
--- a/lib/api/helpers/related_resources_helpers.rb
+++ b/lib/api/helpers/related_resources_helpers.rb
@@ -9,6 +9,10 @@ module API
available?(:issues, project, options[:current_user])
end
+ def project_feature_string_access_level(project, feature)
+ project.project_feature&.string_access_level(feature)
+ end
+
def mrs_available?(project, options)
available?(:merge_requests, project, options[:current_user])
end
diff --git a/lib/api/helpers/snippets_helpers.rb b/lib/api/helpers/snippets_helpers.rb
index 2d8c761101a..fe20fb3cbe2 100644
--- a/lib/api/helpers/snippets_helpers.rb
+++ b/lib/api/helpers/snippets_helpers.rb
@@ -29,9 +29,10 @@ module API
params :update_file_params do |options|
optional :files, type: Array, desc: 'An array of files to update' do
- requires :action, type: String,
- values: SnippetInputAction::ACTIONS.map(&:to_s),
- desc: "The type of action to perform on the file, must be one of: #{SnippetInputAction::ACTIONS.join(", ")}"
+ requires :action,
+ type: String,
+ values: SnippetInputAction::ACTIONS.map(&:to_s),
+ desc: "The type of action to perform on the file, must be one of: #{SnippetInputAction::ACTIONS.join(", ")}"
optional :content, type: String, desc: 'The content of a snippet'
optional :file_path, file_path: true, type: String, desc: 'The file path of a snippet file'
optional :previous_path, file_path: true, type: String, desc: 'The previous path of a snippet file'
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index b53f855c3a2..6f475fa8d74 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -39,6 +39,7 @@ module API
container.lfs_http_url_to_repo
end
+ # rubocop: disable Metrics/AbcSize
def check_allowed(params)
# This is a separate method so that EE can alter its behaviour more
# easily.
@@ -47,6 +48,14 @@ module API
check_rate_limit!(:gitlab_shell_operation, scope: [params[:action], params[:project], actor.key_or_user])
end
+ if Feature.enabled?(:rate_limit_gitlab_shell_by_ip, actor.user)
+ rate_limiter = Gitlab::Auth::IpRateLimiter.new(request.ip)
+
+ unless rate_limiter.trusted_ip?
+ check_rate_limit!(:gitlab_shell_operation, scope: [params[:action], params[:project], rate_limiter.ip])
+ end
+ end
+
# Stores some Git-specific env thread-safely
env = parse_env
Gitlab::Git::HookEnv.set(gl_repository, env) if container
@@ -101,6 +110,7 @@ module API
response_with_status(code: 500, success: false, message: UNKNOWN_CHECK_RESULT_ERROR)
end
end
+ # rubocop: enable Metrics/AbcSize
def send_git_audit_streaming_event(msg)
# Defined in EE
diff --git a/lib/api/internal/error_tracking.rb b/lib/api/internal/error_tracking.rb
index bad790b0e43..1680ac8afb5 100644
--- a/lib/api/internal/error_tracking.rb
+++ b/lib/api/internal/error_tracking.rb
@@ -12,7 +12,7 @@ module API
input = params['error_tracking_token']
if headers.key?(GITLAB_ERROR_TRACKING_TOKEN_HEADER)
- input ||= Base64.decode64(headers[GITLAB_ERROR_TRACKING_TOKEN_HEADER])
+ input ||= headers[GITLAB_ERROR_TRACKING_TOKEN_HEADER]
end
input&.chomp!
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index f7c6e48e54f..6f964d5636b 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -4,6 +4,8 @@ module API
# Kubernetes Internal API
module Internal
class Kubernetes < ::API::Base
+ include Gitlab::Utils::StrongMemoize
+
feature_category :kubernetes_management
before do
check_feature_enabled
@@ -54,6 +56,27 @@ module API
::Clusters::AgentTokens::TrackUsageService.new(agent_token).execute
end
+
+ def agent_has_access_to_project?(project)
+ Guest.can?(:download_code, project) || agent.has_access_to?(project)
+ end
+
+ def count_events
+ strong_memoize(:count_events) do
+ events = params.slice(:gitops_sync_count, :k8s_api_proxy_request_count)
+ events.transform_keys! { |event| event.to_s.chomp('_count') }
+ events = params[:counters]&.slice(:gitops_sync, :k8s_api_proxy_request) unless events.present?
+ events
+ end
+ end
+
+ def increment_unique_events
+ events = params[:unique_counters]&.slice(:agent_users_using_ci_tunnel)
+
+ events&.each do |event, entity_ids|
+ increment_unique_values(event, entity_ids)
+ end
+ end
end
namespace 'internal' do
@@ -79,6 +102,24 @@ module API
default_branch: project.default_branch_or_main
}
end
+
+ desc 'Gets project info' do
+ detail 'Retrieves project info (if authorized)'
+ end
+ route_setting :authentication, cluster_agent_token_allowed: true
+ get '/project_info', urgency: :low do
+ project = find_project(params[:id])
+
+ not_found! unless agent_has_access_to_project?(project)
+
+ status 200
+ {
+ project_id: project.id,
+ gitaly_info: gitaly_info(project),
+ gitaly_repository: gitaly_repository(project),
+ default_branch: project.default_branch_or_main
+ }
+ end
end
namespace 'kubernetes/agent_configuration', urgency: :low do
@@ -103,14 +144,27 @@ module API
detail 'Updates usage metrics for agent'
end
params do
+ # Todo: Remove gitops_sync_count and k8s_api_proxy_request_count in the next milestone
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/369489
+ # We're only keeping it for backwards compatibility until KAS is released
+ # using `counts:` instead
optional :gitops_sync_count, type: Integer, desc: 'The count to increment the gitops_sync metric by'
optional :k8s_api_proxy_request_count, type: Integer, desc: 'The count to increment the k8s_api_proxy_request_count metric by'
+ optional :counters, type: Hash do
+ optional :gitops_sync, type: Integer, desc: 'The count to increment the gitops_sync metric by'
+ optional :k8s_api_proxy_request, type: Integer, desc: 'The count to increment the k8s_api_proxy_request_count metric by'
+ end
+ mutually_exclusive :counters, :gitops_sync_count
+ mutually_exclusive :counters, :k8s_api_proxy_request_count
+
+ optional :unique_counters, type: Hash do
+ optional :agent_users_using_ci_tunnel, type: Set[Integer], desc: 'A set of user ids that have interacted a CI Tunnel to'
+ end
end
post '/' do
- events = params.slice(:gitops_sync_count, :k8s_api_proxy_request_count)
- events.transform_keys! { |event| event.to_s.chomp('_count') }
+ Gitlab::UsageDataCounters::KubernetesAgentCounter.increment_event_counts(count_events) if count_events
- Gitlab::UsageDataCounters::KubernetesAgentCounter.increment_event_counts(events)
+ increment_unique_events
no_content!
rescue ArgumentError => e
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
index c07c2c1994e..563fb3358ed 100644
--- a/lib/api/issue_links.rb
+++ b/lib/api/issue_links.rb
@@ -37,7 +37,7 @@ module API
requires :target_project_id, type: String, desc: 'The ID of the target project'
requires :target_issue_iid, type: Integer, desc: 'The IID of the target issue'
optional :link_type, type: String, values: IssueLink.link_types.keys,
- desc: 'The type of the relation'
+ desc: 'The type of the relation'
end
# rubocop: disable CodeReuse/ActiveRecord
post ':id/issues/:issue_iid/links' do
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 971163c18db..b6ad34424a6 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -16,7 +16,7 @@ module API
optional :labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :milestone, type: String, desc: 'Milestone title'
optional :milestone_id, types: String, values: %w[Any None Upcoming Started],
- desc: 'Return issues assigned to milestones without the specified timebox value ("Any", "None", "Upcoming" or "Started")'
+ desc: 'Return issues assigned to milestones without the specified timebox value ("Any", "None", "Upcoming" or "Started")'
mutually_exclusive :milestone_id, :milestone
optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IID array of issues'
@@ -27,8 +27,8 @@ module API
optional :assignee_id, type: Integer, desc: 'Return issues which are not assigned to the user with the given ID'
optional :assignee_username, type: Array[String], check_assignees_count: true,
- coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
- desc: 'Return issues which are not assigned to the user with the given username'
+ coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
+ desc: 'Return issues which are not assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
use :negatable_issue_filter_params_ee
@@ -40,7 +40,7 @@ module API
# 'milestone_id' only accepts wildcard values 'Any', 'None', 'Upcoming', 'Started'
# the param has '_id' in the name to keep consistency (ex. assignee_id accepts id and wildcard values).
optional :milestone_id, types: String, values: %w[Any None Upcoming Started],
- desc: 'Return issues assigned to milestones with the specified timebox value ("Any", "None", "Upcoming" or "Started")'
+ desc: 'Return issues assigned to milestones with the specified timebox value ("Any", "None", "Upcoming" or "Started")'
optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IID array of issues'
optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these'
optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma'
@@ -51,10 +51,10 @@ module API
mutually_exclusive :author_id, :author_username
optional :assignee_id, types: [Integer, String], integer_none_any: true,
- desc: 'Return issues which are assigned to the user with the given ID'
+ desc: 'Return issues which are assigned to the user with the given ID'
optional :assignee_username, type: Array[String], check_assignees_count: true,
- coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
- desc: 'Return issues which are assigned to the user with the given username'
+ coerce_with: Validations::Validators::CheckAssigneesCount.coerce,
+ desc: 'Return issues which are assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
@@ -77,13 +77,13 @@ module API
params :issues_params do
optional :with_labels_details, type: Boolean, desc: 'Return titles of labels and other details', default: false
optional :state, type: String, values: %w[opened closed all], default: 'all',
- desc: 'Return opened, closed, or all issues'
+ desc: 'Return opened, closed, or all issues'
optional :order_by, type: String, values: Helpers::IssuesHelpers.sort_options, default: 'created_at',
- desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
+ desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return issues sorted in `asc` or `desc` order.'
+ desc: 'Return issues sorted in `asc` or `desc` order.'
optional :due_date, type: String, values: %w[0 any today tomorrow overdue week month next_month_and_previous_two_weeks] << '',
- desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
+ desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}"
use :issues_stats_params
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index e2d4f5d823a..0a107a96d61 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -23,11 +23,11 @@ module API
end
params do
optional :with_counts, type: Boolean, default: false,
- desc: 'Include issue and merge request counts'
+ desc: 'Include issue and merge request counts'
optional :include_ancestor_groups, type: Boolean, default: true,
- desc: 'Include ancestor groups'
+ desc: 'Include ancestor groups'
optional :search, type: String,
- desc: 'Keyword to filter labels by. This feature was added in GitLab 13.6'
+ desc: 'Keyword to filter labels by. This feature was added in GitLab 13.6'
use :pagination
end
get ':id/labels' do
@@ -40,7 +40,7 @@ module API
end
params do
optional :include_ancestor_groups, type: Boolean, default: true,
- desc: 'Include ancestor groups'
+ desc: 'Include ancestor groups'
end
get ':id/labels/:name' do
get_label(user_project, Entities::ProjectLabel, declared_params)
diff --git a/lib/api/markdown.rb b/lib/api/markdown.rb
index c465087c4a2..1f8255fd6a4 100644
--- a/lib/api/markdown.rb
+++ b/lib/api/markdown.rb
@@ -2,7 +2,9 @@
module API
class Markdown < ::API::Base
- feature_category :not_owned # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned
+ before { authenticate! if Feature.enabled?(:authenticate_markdown_api, type: :ops) }
+
+ feature_category :team_planning
params do
requires :text, type: String, desc: "The markdown text to render"
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index e2481dcb8c1..fb0221ee907 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -43,6 +43,9 @@ module API
end
end
+ # The sha verification done by the maven api is between:
+ # - the sha256 set by workhorse helpers
+ # - the sha256 of the sha1 of the uploaded package file
def verify_package_file(package_file, uploaded_file)
stored_sha256 = Digest::SHA256.hexdigest(package_file.file_sha1)
expected_sha256 = uploaded_file.sha256
@@ -50,6 +53,16 @@ module API
if stored_sha256 == expected_sha256
no_content!
else
+ # Track sha1 conflicts.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/367356
+ Gitlab::ErrorTracking.log_exception(
+ ArgumentError.new,
+ message: 'maven package file sha1 conflict',
+ stored_sha1: package_file.file_sha1,
+ received_sha256: uploaded_file.sha256,
+ sha256_hexdigest_of_stored_sha1: stored_sha256
+ )
+
conflict!
end
end
@@ -270,12 +283,12 @@ module API
''
else
file_params = {
- file: params[:file],
- size: params['file.size'],
+ file: params[:file],
+ size: params['file.size'],
file_name: file_name,
file_type: params['file.type'],
file_sha1: params['file.sha1'],
- file_md5: params['file.md5']
+ file_md5: params['file.md5']
}
::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job)).execute
diff --git a/lib/api/members.rb b/lib/api/members.rb
index b94f68f60b5..d26fdd09ee7 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -91,7 +91,7 @@ module API
authorize_read_source_member!(source_type, source)
- members = find_all_members(source)
+ members = find_all_members(source).order(access_level: :desc)
member = members.find_by!(user_id: params[:user_id])
present_members member
@@ -156,9 +156,9 @@ module API
params do
requires :user_id, type: Integer, desc: 'The user ID of the member'
optional :skip_subresources, type: Boolean, default: false,
- desc: 'Flag indicating if the deletion of direct memberships of the removed member in subgroups and projects should be skipped'
+ desc: 'Flag indicating if the deletion of direct memberships of the removed member in subgroups and projects should be skipped'
optional :unassign_issuables, type: Boolean, default: false,
- desc: 'Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project'
+ desc: 'Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project'
end
# rubocop: disable CodeReuse/ActiveRecord
delete ":id/members/:user_id", feature_category: feature_category do
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 156a92802b0..a8f58e91067 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -121,6 +121,10 @@ module API
merge_request.permits_force_push?
end
+ def recheck_mergeability_of(merge_requests:)
+ merge_requests.each { |mr| mr.check_mergeability(async: true) }
+ end
+
params :merge_requests_params do
use :merge_requests_base_params
use :optional_merge_requests_search_params
@@ -155,7 +159,7 @@ module API
params do
use :merge_requests_params
optional :non_archived, type: Boolean, desc: 'Return merge requests from non archived projects',
- default: true
+ default: true
end
get ":id/merge_requests", feature_category: :code_review, urgency: :low do
validate_anonymous_search_access! if declared_params[:search].present?
@@ -206,7 +210,9 @@ module API
options = serializer_options_for(merge_requests).merge(project: user_project)
options[:project] = user_project
- present_cached merge_requests, expires_in: 2.days, **options
+ recheck_mergeability_of(merge_requests: merge_requests) unless options[:skip_merge_status_recheck]
+
+ present_cached merge_requests, expires_in: 8.hours, cache_context: -> (mr) { "#{current_user&.cache_key}:#{mr.merge_status}" }, **options
end
desc 'Create a merge request' do
@@ -283,6 +289,17 @@ module API
present paginate(participants), with: Entities::UserBasic
end
+ desc 'Get the reviewers of a merge request' do
+ success Entities::MergeRequestReviewer
+ end
+ get ':id/merge_requests/:merge_request_iid/reviewers', feature_category: :code_review, urgency: :low do
+ merge_request = find_merge_request_with_access(params[:merge_request_iid])
+
+ reviewers = ::Kaminari.paginate_array(merge_request.merge_request_reviewers)
+
+ present paginate(reviewers), with: Entities::MergeRequestReviewer
+ end
+
desc 'Get the commits of a merge request' do
success Entities::Commit
end
@@ -455,11 +472,7 @@ module API
not_allowed! if !immediately_mergeable && !automatically_mergeable
- if Feature.enabled?(:change_response_code_merge_status, user_project)
- render_api_error!('Branch cannot be merged', 422) unless merge_request.mergeable?(skip_ci_check: automatically_mergeable)
- else
- render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable?(skip_ci_check: automatically_mergeable)
- end
+ render_api_error!('Branch cannot be merged', 422) unless merge_request.mergeable?(skip_ci_check: automatically_mergeable)
check_sha_param!(params, merge_request)
@@ -481,7 +494,11 @@ module API
.execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
end
- present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
+ if immediately_mergeable && !merge_request.merged?
+ render_api_error!("Branch cannot be merged", 422)
+ else
+ present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
+ end
end
desc 'Returns the up to date merge-ref HEAD commit'
diff --git a/lib/api/metrics/dashboard/annotations.rb b/lib/api/metrics/dashboard/annotations.rb
index 6fc90da87d4..478adcdce70 100644
--- a/lib/api/metrics/dashboard/annotations.rb
+++ b/lib/api/metrics/dashboard/annotations.rb
@@ -20,11 +20,11 @@ module API
resource annotations_source[:resource] do
params do
requires :starting_at, type: DateTime,
- desc: 'Date time indicating starting moment to which the annotation relates.'
+ desc: 'Date time indicating starting moment to which the annotation relates.'
optional :ending_at, type: DateTime,
- desc: 'Date time indicating ending moment to which the annotation relates.'
+ desc: 'Date time indicating ending moment to which the annotation relates.'
requires :dashboard_path, type: String, coerce_with: -> (val) { CGI.unescape(val) },
- desc: 'The path to a file defining the dashboard on which the annotation should be added'
+ desc: 'The path to a file defining the dashboard on which the annotation should be added'
requires :description, type: String, desc: 'The description of the annotation'
end
diff --git a/lib/api/metrics/user_starred_dashboards.rb b/lib/api/metrics/user_starred_dashboards.rb
index 83d95f8b062..4d5396acccb 100644
--- a/lib/api/metrics/user_starred_dashboards.rb
+++ b/lib/api/metrics/user_starred_dashboards.rb
@@ -13,7 +13,7 @@ module API
params do
requires :dashboard_path, type: String, allow_blank: false, coerce_with: ->(val) { CGI.unescape(val) },
- desc: 'Url encoded path to a file defining the dashboard to which the star should be added'
+ desc: 'Url encoded path to a file defining the dashboard to which the star should be added'
end
post ':id/metrics/user_starred_dashboards' do
@@ -30,7 +30,7 @@ module API
params do
optional :dashboard_path, type: String, allow_blank: false, coerce_with: ->(val) { CGI.unescape(val) },
- desc: 'Url encoded path to a file defining the dashboard from which the star should be removed'
+ desc: 'Url encoded path to a file defining the dashboard from which the star should be removed'
end
delete ':id/metrics/user_starred_dashboards' do
diff --git a/lib/api/milestone_responses.rb b/lib/api/milestone_responses.rb
index d75ed3a48d7..2fd3239b44a 100644
--- a/lib/api/milestone_responses.rb
+++ b/lib/api/milestone_responses.rb
@@ -14,12 +14,12 @@ module API
params :list_params do
optional :state, type: String, values: %w[active closed all], default: 'all',
- desc: 'Return "active", "closed", or "all" milestones'
+ desc: 'Return "active", "closed", or "all" milestones'
optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IIDs of the milestones'
optional :title, type: String, desc: 'The title of the milestones'
optional :search, type: String, desc: 'The search criteria for the title or description of the milestone'
optional :include_parent_milestones, type: Grape::API::Boolean, default: false,
- desc: 'Include group milestones from parent and its ancestors'
+ desc: 'Include group milestones from parent and its ancestors'
use :pagination
end
@@ -27,7 +27,7 @@ module API
requires :milestone_id, type: Integer, desc: 'The milestone ID number'
optional :title, type: String, desc: 'The title of the milestone'
optional :state_event, type: String, values: %w[close activate],
- desc: 'The state event of the milestone '
+ desc: 'The state event of the milestone '
use :optional_params
at_least_one_of :title, :description, :start_date, :due_date, :state_event
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 2a854bd785e..77c479c529a 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -30,7 +30,7 @@ module API
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return notes sorted in `asc` or `desc` order.'
optional :activity_filter, type: String, values: UserPreference::NOTES_FILTERS.stringify_keys.keys, default: 'all_notes',
- desc: 'The type of notables which are returned.'
+ desc: 'The type of notables which are returned.'
use :pagination
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -73,7 +73,8 @@ 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: 'Confidentiality note flag, default is false'
+ optional :confidential, type: Boolean, desc: '[Deprecated in 15.3] 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'
end
@@ -87,7 +88,7 @@ module API
note: params[:body],
noteable_type: noteables_str.classify,
noteable_id: noteable.id,
- confidential: params[:confidential],
+ internal: params[:internal] || params[:confidential],
created_at: params[:created_at],
merge_request_diff_head_sha: params[:merge_request_diff_head_sha]
}
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 2e7f8475509..34d3a5150da 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -97,7 +97,7 @@ module API
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
optional :auto_ssl_enabled, allow_blank: false, type: Boolean, default: false,
- desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
+ desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
# rubocop:enable Scalability/FileUploads
all_or_none_of :user_provided_certificate, :user_provided_key
end
@@ -123,7 +123,7 @@ module API
optional :certificate, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
optional :key, types: [File, String], desc: 'The key', as: :user_provided_key
optional :auto_ssl_enabled, allow_blank: true, type: Boolean,
- desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
+ desc: "Enables automatic generation of SSL certificates issued by Let's Encrypt for custom domains."
# rubocop:enable Scalability/FileUploads
end
put ":id/pages/domains/:domain", requirements: PAGES_DOMAINS_ENDPOINT_REQUIREMENTS do
diff --git a/lib/api/pagination_params.rb b/lib/api/pagination_params.rb
index 85ac50d5bec..bdb69d0ba44 100644
--- a/lib/api/pagination_params.rb
+++ b/lib/api/pagination_params.rb
@@ -20,6 +20,26 @@ module API
optional :page, type: Integer, default: 1, desc: 'Current page number'
optional :per_page, type: Integer, default: 20, desc: 'Number of items per page', except_values: [0]
end
+
+ def verify_pagination_params!
+ return if Feature.disabled?(:only_positive_pagination_values)
+
+ page = begin
+ Integer(params[:page])
+ rescue ArgumentError, TypeError
+ nil
+ end
+
+ return render_structured_api_error!({ error: 'page does not have a valid value' }, 400) if page&.< 1
+
+ per_page = begin
+ Integer(params[:per_page])
+ rescue ArgumentError, TypeError
+ nil
+ end
+
+ return render_structured_api_error!({ error: 'per_page does not have a valid value' }, 400) if per_page&.< 1
+ end
end
end
end
diff --git a/lib/api/personal_access_tokens.rb b/lib/api/personal_access_tokens.rb
index f8b744bb14b..0d7d2dc6a0c 100644
--- a/lib/api/personal_access_tokens.rb
+++ b/lib/api/personal_access_tokens.rb
@@ -57,9 +57,14 @@ module API
get ':id' do
token = PersonalAccessToken.find_by_id(params[:id])
- unauthorized! unless token && Ability.allowed?(current_user, :read_user_personal_access_tokens, token.user)
-
- present token, with: Entities::PersonalAccessToken
+ allowed = Ability.allowed?(current_user, :read_user_personal_access_tokens, token&.user)
+
+ if allowed
+ present token, with: Entities::PersonalAccessToken
+ else
+ # Only admins should be informed if the token doesn't exist
+ current_user.admin? ? not_found! : unauthorized!
+ end
end
delete 'self' do
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index 79a5ca531e1..800966408fc 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -32,10 +32,11 @@ module API
optional :package_name, type: String,
desc: 'Return packages with this name'
optional :include_versionless, type: Boolean,
- desc: 'Returns packages without a version'
+ desc: 'Returns packages without a version'
optional :status, type: String, values: Packages::Package.statuses.keys,
- desc: 'Return packages with specified status'
+ desc: 'Return packages with specified status'
end
+ route_setting :authentication, job_token_allowed: true
get ':id/packages' do
packages = ::Packages::PackagesFinder.new(
user_project,
@@ -52,6 +53,7 @@ module API
params do
requires :package_id, type: Integer, desc: 'The ID of a package'
end
+ route_setting :authentication, job_token_allowed: true
get ':id/packages/:package_id' do
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
@@ -65,6 +67,7 @@ module API
params do
requires :package_id, type: Integer, desc: 'The ID of a package'
end
+ route_setting :authentication, job_token_allowed: true
delete ':id/packages/:package_id' do
authorize_destroy_package!(user_project)
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
index fe0e837c596..f6e1286d616 100644
--- a/lib/api/project_templates.rb
+++ b/lib/api/project_templates.rb
@@ -37,7 +37,7 @@ module API
params do
requires :name, type: String, desc: 'The name of the template'
optional :source_template_project_id, type: Integer,
- desc: 'The project id where a given template is being stored. This is useful when multiple templates from different projects have the same name'
+ desc: 'The project id where a given template is being stored. This is useful when multiple templates from different projects have the same name'
optional :project, type: String, desc: 'The project name to use when expanding placeholders in the template. Only affects licenses'
optional :fullname, type: String, desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses'
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 6530887c1c3..6ed480518ee 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -688,11 +688,11 @@ module API
optional :search, type: String, desc: 'Return list of groups matching the search criteria'
optional :skip_groups, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of group ids to exclude from list'
optional :with_shared, type: Boolean, default: false,
- desc: 'Include shared groups'
+ desc: 'Include shared groups'
optional :shared_visible_only, type: Boolean, default: false,
- desc: 'Limit to shared groups user has access to'
+ desc: 'Limit to shared groups user has access to'
optional :shared_min_access_level, type: Integer, values: Gitlab::Access.all_values,
- desc: 'Limit returned shared groups by minimum access level to the project'
+ desc: 'Limit returned shared groups by minimum access level to the project'
use :pagination
end
get ':id/groups', feature_category: :source_code_management do
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index a4f5dfefae6..38bafac25b2 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -61,8 +61,8 @@ module API
values: ProtectedBranch::MergeAccessLevel.allowed_access_levels,
desc: 'Access levels allowed to merge (defaults: `40`, maintainer access level)'
optional :allow_force_push, type: Boolean,
- default: false,
- desc: 'Allow force push for all users with push access.'
+ default: false,
+ desc: 'Allow force push for all users with push access.'
use :optional_params_ee
end
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index aecd6f9eef8..10e879ec70b 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -23,9 +23,9 @@ module API
params do
requires :id, type: Integer, desc: 'The ID of the group to get releases for'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return projects sorted in ascending and descending order by released_at'
+ desc: 'Return projects sorted in ascending and descending order by released_at'
optional :simple, type: Boolean, default: false,
- desc: 'Return only the ID, URL, name, and path of each project'
+ desc: 'Return only the ID, URL, name, and path of each project'
use :pagination
end
@@ -61,7 +61,7 @@ module API
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return releases sorted in `asc` or `desc` order.'
optional :include_html_description, type: Boolean,
- desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
+ desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
route_setting :authentication, job_token_allowed: true
get ':id/releases' do
@@ -89,7 +89,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
optional :include_html_description, type: Boolean,
- desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
+ desc: 'If `true`, a response includes HTML rendered markdown of the release description.'
end
route_setting :authentication, job_token_allowed: true
get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
@@ -186,6 +186,8 @@ module API
.execute
if result[:status] == :success
+ log_release_deleted_audit_event
+
present result[:release], with: Entities::Release, current_user: current_user
else
render_api_error!(result[:message], result[:http_status])
@@ -238,6 +240,10 @@ module API
# extended in EE
end
+ def log_release_deleted_audit_event
+ # extended in EE
+ end
+
def log_release_milestones_updated_audit_event
# extended in EE
end
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 4c7cc6be8b6..cef72d898e6 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -99,11 +99,17 @@ module API
optional :recursive, type: Boolean, default: false, desc: 'Used to get a recursive tree'
use :pagination
- optional :pagination, type: String, values: %w(legacy keyset), default: 'legacy', desc: 'Specify the pagination method'
+ optional :pagination, type: String, values: %w(legacy keyset none), default: 'legacy', desc: 'Specify the pagination method ("none" is only valid if "recursive" is true)'
- given pagination: -> (value) { value == 'keyset' } do
+ given pagination: ->(value) { value == 'keyset' } do
optional :page_token, type: String, desc: 'Record from which to start the keyset pagination'
end
+
+ given pagination: ->(value) { value == 'none' } do
+ given recursive: ->(value) { value == false } do
+ validates([:pagination], except_values: { value: 'none', message: 'cannot be "none" unless "recursive" is true' })
+ end
+ end
end
get ':id/repository/tree', urgency: :low do
tree_finder = ::Repositories::TreeFinder.new(user_project, declared_params(include_missing: false))
diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb
index e6c54faebd9..85bbd0879b7 100644
--- a/lib/api/rubygem_packages.rb
+++ b/lib/api/rubygem_packages.rb
@@ -109,7 +109,7 @@ module API
).execute(:rubygems, name: ::Packages::Rubygems::TEMPORARY_PACKAGE_NAME)
file_params = {
- file: params[:file],
+ file: params[:file],
file_name: PACKAGE_FILENAME
}
diff --git a/lib/api/search.rb b/lib/api/search.rb
index fd4d46cf77d..c78aff705ab 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -59,11 +59,15 @@ module API
end
def search(additional_params = {})
- results = search_service(additional_params).search_objects(preload_method)
+ @search_duration_s = Benchmark.realtime do
+ @results = search_service(additional_params).search_objects(preload_method)
+ end
+
+ set_global_search_log_information
Gitlab::UsageDataCounters::SearchCounter.count(:all_searches)
- paginate(results)
+ paginate(@results)
end
def snippets?
@@ -83,6 +87,23 @@ module API
# Defining this method here as a noop allows us to easily extend it in
# EE, without having to modify this file directly.
end
+
+ def search_type
+ 'basic'
+ end
+
+ def search_scope
+ params[:scope]
+ end
+
+ def set_global_search_log_information
+ Gitlab::Instrumentation::GlobalSearchApi.set_information(
+ type: search_type,
+ level: search_service.level,
+ scope: search_scope,
+ search_duration_s: @search_duration_s
+ )
+ end
end
resource :search do
diff --git a/lib/api/sidekiq_metrics.rb b/lib/api/sidekiq_metrics.rb
index bca1376d489..e279e63181d 100644
--- a/lib/api/sidekiq_metrics.rb
+++ b/lib/api/sidekiq_metrics.rb
@@ -22,14 +22,14 @@ module API
def process_metrics
Sidekiq::ProcessSet.new(false).map do |process|
{
- hostname: process['hostname'],
- pid: process['pid'],
- tag: process['tag'],
- started_at: Time.at(process['started_at']),
- queues: process['queues'],
- labels: process['labels'],
+ hostname: process['hostname'],
+ pid: process['pid'],
+ tag: process['tag'],
+ started_at: Time.at(process['started_at']),
+ queues: process['queues'],
+ labels: process['labels'],
concurrency: process['concurrency'],
- busy: process['busy']
+ busy: process['busy']
}
end
end
diff --git a/lib/api/support/git_access_actor.rb b/lib/api/support/git_access_actor.rb
index 71395086ac2..f450630afdd 100644
--- a/lib/api/support/git_access_actor.rb
+++ b/lib/api/support/git_access_actor.rb
@@ -32,6 +32,10 @@ module API
key || user
end
+ def deploy_key_or_user
+ key.instance_of?(DeployKey) ? key : user
+ end
+
def username
user&.username
end
diff --git a/lib/api/topics.rb b/lib/api/topics.rb
index 15f79e75be3..a08b4c6c107 100644
--- a/lib/api/topics.rb
+++ b/lib/api/topics.rb
@@ -12,6 +12,7 @@ module API
end
params do
optional :search, type: String, desc: 'Return list of topics matching the search criteria'
+ optional :without_projects, type: Boolean, desc: 'Return list of topics without assigned projects'
use :pagination
end
get 'topics' do
diff --git a/lib/api/unleash.rb b/lib/api/unleash.rb
index 2d528ad47a2..1fbd7cf5afc 100644
--- a/lib/api/unleash.rb
+++ b/lib/api/unleash.rb
@@ -33,8 +33,10 @@ module API
end
end
+ # We decrease the urgency of this endpoint until the maxmemory issue of redis-cache has been resolved.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/365575#note_1033611872 for more information.
desc 'Get a list of features'
- get 'client/features' do
+ get 'client/features', urgency: :low do
if ::Feature.enabled?(:cache_unleash_client_api, project)
present_feature_flags
else
diff --git a/lib/api/user_counts.rb b/lib/api/user_counts.rb
index d0b1e458a27..388aa5e375c 100644
--- a/lib/api/user_counts.rb
+++ b/lib/api/user_counts.rb
@@ -12,19 +12,13 @@ module API
get do
unauthorized! unless current_user
- counts = {
+ {
merge_requests: current_user.assigned_open_merge_requests_count, # @deprecated
assigned_issues: current_user.assigned_open_issues_count,
assigned_merge_requests: current_user.assigned_open_merge_requests_count,
review_requested_merge_requests: current_user.review_requested_open_merge_requests_count,
todos: current_user.todos_pending_count
}
-
- if current_user&.mr_attention_requests_enabled?
- counts[:attention_requests] = current_user.attention_requested_open_merge_requests_count
- end
-
- counts
end
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index d66d86a9055..c93c0f601a0 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -68,9 +68,9 @@ module API
params :sort_params do
optional :order_by, type: String, values: %w[id name username created_at updated_at],
- default: 'id', desc: 'Return users ordered by a field'
+ default: 'id', desc: 'Return users ordered by a field'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
- desc: 'Return users sorted in ascending and descending order'
+ desc: 'Return users sorted in ascending and descending order'
end
end
@@ -940,7 +940,7 @@ module API
params do
requires :name, type: String, desc: 'The name of the personal access token'
requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::Gitlab::Auth.all_available_scopes.map(&:to_s),
- desc: 'The array of scopes of the personal access token'
+ desc: 'The array of scopes of the personal access token'
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token'
end
post feature_category: :authentication_and_authorization do
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index 3cbe3cf7d88..cf19b4fa8ff 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -18,9 +18,10 @@ module Backup
].freeze
IGNORED_ERRORS_REGEXP = Regexp.union(IGNORED_ERRORS).freeze
- def initialize(progress, force:)
+ def initialize(database_name, progress, force:)
super(progress)
- @config = ActiveRecord::Base.configurations.find_db_config(Rails.env).configuration_hash
+ @database_name = database_name
+ @config = base_model.connection_db_config.configuration_hash
@force = force
end
@@ -67,6 +68,13 @@ module Backup
override :restore
def restore(db_file_name)
+ unless File.exist?(db_file_name)
+ raise(Backup::Error, "Source database file does not exist #{db_file_name}") if main_database?
+
+ progress.puts "Source backup for the database #{@database_name} doesn't exist. Skipping the task"
+ return
+ end
+
unless force
progress.puts 'Removing all tables. Press `Ctrl-C` within 5 seconds to abort'.color(:yellow)
sleep(5)
@@ -140,6 +148,14 @@ module Backup
@config[:database]
end
+ def base_model
+ Gitlab::Database.database_base_models[@database_name]
+ end
+
+ def main_database?
+ @database_name == :main
+ end
+
def ignore_error?(line)
IGNORED_ERRORS_REGEXP.match?(line)
end
diff --git a/lib/backup/gitaly_backup.rb b/lib/backup/gitaly_backup.rb
index a995f308c2b..57dd74c7950 100644
--- a/lib/backup/gitaly_backup.rb
+++ b/lib/backup/gitaly_backup.rb
@@ -32,15 +32,12 @@ module Backup
raise Error, "unknown backup type: #{type}"
end
- args = []
+ args = ['-layout', 'pointer']
args += ['-parallel', @max_parallelism.to_s] if @max_parallelism
args += ['-parallel-storage', @storage_parallelism.to_s] if @storage_parallelism
- if Feature.enabled?(:incremental_repository_backup)
- args += ['-layout', 'pointer']
- if type == :create
- args += ['-incremental'] if incremental?
- args += ['-id', backup_id] if backup_id
- end
+ if type == :create
+ args += ['-incremental'] if incremental?
+ args += ['-id', backup_id] if backup_id
end
@input_stream, stdout, @thread = Open3.popen2(build_env, bin_path, command, '-path', backup_repos_path, *args)
@@ -97,7 +94,7 @@ module Backup
def build_env
{
'SSL_CERT_FILE' => Gitlab::X509::Certificate.default_cert_file,
- 'SSL_CERT_DIR' => Gitlab::X509::Certificate.default_cert_dir
+ 'SSL_CERT_DIR' => Gitlab::X509::Certificate.default_cert_dir
}.merge(ENV)
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 16b8f21c9e9..902eb8f6659 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -22,6 +22,7 @@ module Backup
:destination_optional, # `true` if the destination might not exist on a successful backup.
:cleanup_path, # Path to remove after a successful backup. Uses `destination_path` when not specified.
:task,
+ :task_group,
keyword_init: true
) do
def enabled?
@@ -33,11 +34,7 @@ module Backup
def initialize(progress, definitions: nil)
@progress = progress
-
- @incremental = Feature.feature_flags_available? &&
- Feature.enabled?(:incremental_repository_backup) &&
- Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
-
+ @incremental = Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
@definitions = definitions
end
@@ -122,13 +119,22 @@ module Backup
@definitions ||= build_definitions
end
- def build_definitions
+ def build_definitions # rubocop:disable Metrics/AbcSize
{
- 'db' => TaskDefinition.new(
- human_name: _('database'),
+ 'main_db' => TaskDefinition.new(
+ human_name: _('main_database'),
destination_path: 'db/database.sql.gz',
cleanup_path: 'db',
- task: build_db_task
+ task: build_db_task(:main),
+ task_group: 'db'
+ ),
+ 'ci_db' => TaskDefinition.new(
+ human_name: _('ci_database'),
+ destination_path: 'db/ci_database.sql.gz',
+ cleanup_path: 'db',
+ task: build_db_task(:ci),
+ enabled: Gitlab::Database.has_config?(:ci),
+ task_group: 'db'
),
'repositories' => TaskDefinition.new(
human_name: _('repositories'),
@@ -180,10 +186,11 @@ module Backup
}.freeze
end
- def build_db_task
- force = Gitlab::Utils.to_boolean(ENV['force'], default: false)
+ def build_db_task(database_name)
+ return unless Gitlab::Database.has_config?(database_name) # It will be disabled for a single db setup
- Database.new(progress, force: force)
+ force = Gitlab::Utils.to_boolean(ENV['force'], default: false)
+ Database.new(database_name, progress, force: force)
end
def build_repositories_task
@@ -233,7 +240,9 @@ module Backup
verify_backup_version
definitions.keys.each do |task_name|
- run_restore_task(task_name) if !skipped?(task_name) && enabled_task?(task_name)
+ if !skipped?(task_name) && enabled_task?(task_name)
+ run_restore_task(task_name)
+ end
end
Rake::Task['gitlab:shell:setup'].invoke
@@ -254,7 +263,9 @@ module Backup
def write_backup_information
# Make sure there is a connection
- ActiveRecord::Base.connection.reconnect!
+ ::Gitlab::Database.database_base_models.values.each do |base_model|
+ base_model.connection.reconnect!
+ end
Dir.chdir(backup_path) do
File.open("#{backup_path}/#{MANIFEST_NAME}", "w+") do |file|
@@ -472,7 +483,7 @@ module Backup
end
def skipped?(item)
- skipped.include?(item)
+ skipped.include?(item) || skipped.include?(definitions[item]&.task_group)
end
def skipped
@@ -483,6 +494,7 @@ module Backup
list = ENV.fetch(LIST_ENVS[name], '').split(',')
list += backup_information[name].split(',') if backup_information[name]
list.uniq!
+ list.compact!
list
end
@@ -507,7 +519,7 @@ module Backup
end
def available_timestamps
- @backup_file_list.map {|item| item.gsub("#{FILE_NAME_SUFFIX}", "")}
+ @backup_file_list.map { |item| item.gsub("#{FILE_NAME_SUFFIX}", "") }
end
def object_storage_config
diff --git a/lib/banzai/filter/custom_emoji_filter.rb b/lib/banzai/filter/custom_emoji_filter.rb
index ae95c7f66b6..b589d264526 100644
--- a/lib/banzai/filter/custom_emoji_filter.rb
+++ b/lib/banzai/filter/custom_emoji_filter.rb
@@ -29,7 +29,7 @@ module Banzai
@emoji_pattern ||=
/(?<=[^[:alnum:]:]|\n|^)
:(#{CustomEmoji::NAME_REGEXP}):
- (?=[^[:alnum:]:]|$)/x
+ (?=[^[:alnum:]:]|$)/xo
end
def custom_emoji_name_element_filter(text)
@@ -58,7 +58,7 @@ module Banzai
end
def custom_emoji_candidates
- doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/).flatten
+ doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/o).flatten
end
def all_custom_emoji
diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb
index 521fd7bf4cc..1ca38d2612d 100644
--- a/lib/banzai/filter/references/abstract_reference_filter.rb
+++ b/lib/banzai/filter/references/abstract_reference_filter.rb
@@ -240,11 +240,11 @@ module Banzai
object_parent_type = parent.is_a?(Group) ? :group : :project
{
- original: escape_html_entities(text),
- link: link_content,
- link_reference: link_reference,
+ original: escape_html_entities(text),
+ link: link_content,
+ link_reference: link_reference,
object_parent_type => parent.id,
- object_sym => object.id
+ object_sym => object.id
}
end
diff --git a/lib/banzai/filter/references/label_reference_filter.rb b/lib/banzai/filter/references/label_reference_filter.rb
index a019ae0108e..6020c7b7f58 100644
--- a/lib/banzai/filter/references/label_reference_filter.rb
+++ b/lib/banzai/filter/references/label_reference_filter.rb
@@ -12,13 +12,13 @@ module Banzai
return Label.none unless parent.is_a?(Project) || parent.is_a?(Group)
labels = find_labels(parent)
- label_ids = ids.map {|y| y[:label_id]}.compact
+ label_ids = ids.map { |y| y[:label_id] }.compact
unless label_ids.empty?
id_relation = labels.where(id: label_ids)
end
- label_names = ids.map {|y| y[:label_name]}.compact
+ label_names = ids.map { |y| y[:label_name] }.compact
unless label_names.empty?
label_relation = labels.where(title: label_names)
end
diff --git a/lib/banzai/filter/references/milestone_reference_filter.rb b/lib/banzai/filter/references/milestone_reference_filter.rb
index 609aaf885ba..77658f72d34 100644
--- a/lib/banzai/filter/references/milestone_reference_filter.rb
+++ b/lib/banzai/filter/references/milestone_reference_filter.rb
@@ -11,12 +11,12 @@ module Banzai
def parent_records(parent, ids)
return Milestone.none unless valid_context?(parent)
- milestone_iids = ids.map {|y| y[:milestone_iid]}.compact
+ milestone_iids = ids.map { |y| y[:milestone_iid] }.compact
unless milestone_iids.empty?
iid_relation = find_milestones(parent, true).where(iid: milestone_iids)
end
- milestone_names = ids.map {|y| y[:milestone_name]}.compact
+ milestone_names = ids.map { |y| y[:milestone_name] }.compact
unless milestone_names.empty?
milestone_relation = find_milestones(parent, false).where(name: milestone_names)
end
diff --git a/lib/banzai/filter/task_list_filter.rb b/lib/banzai/filter/task_list_filter.rb
index 896f67cb875..e8a7677b102 100644
--- a/lib/banzai/filter/task_list_filter.rb
+++ b/lib/banzai/filter/task_list_filter.rb
@@ -8,9 +8,93 @@ require 'task_list/filter'
# - app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
module Banzai
module Filter
+ # TaskList filter replaces task list item markers (`[ ]`, `[x]`, and `[~]`)
+ # with checkboxes, marked up with metadata and behavior.
+ #
+ # This should be run on the HTML generated by the Markdown filter, after the
+ # SanitizationFilter.
+ #
+ # Syntax
+ # ------
+ #
+ # Task list items must be in a list format:
+ #
+ # ```
+ # - [ ] incomplete
+ # - [x] complete
+ # - [~] inapplicable
+ # ```
+ #
+ # This class overrides TaskList::Filter in the `deckar01-task_list` gem
+ # to add support for inapplicable task items
class TaskListFilter < TaskList::Filter
+ extend ::Gitlab::Utils::Override
+
+ XPATH = 'descendant-or-self::li[input[@data-inapplicable]] | descendant-or-self::li[p[input[@data-inapplicable]]]'
+ INAPPLICABLE = '[~]'
+ INAPPLICABLEPATTERN = /\[~\]/.freeze
+
+ # Pattern used to identify all task list items.
+ # Useful when you need iterate over all items.
+ NEWITEMPATTERN = /
+ ^
+ (?:\s*[-+*]|(?:\d+\.))? # optional list prefix
+ \s* # optional whitespace prefix
+ ( # checkbox
+ #{CompletePattern}|
+ #{IncompletePattern}|
+ #{INAPPLICABLEPATTERN}
+ )
+ (?=\s) # followed by whitespace
+ /x.freeze
+
+ # Force the gem's constant to use our new one
+ superclass.send(:remove_const, :ItemPattern) # rubocop: disable GitlabSecurity/PublicSend
+ superclass.const_set(:ItemPattern, NEWITEMPATTERN)
+
+ def inapplicable?(item)
+ !!(item.checkbox_text =~ INAPPLICABLEPATTERN)
+ end
+
+ override :render_item_checkbox
def render_item_checkbox(item)
- "<task-button></task-button>#{super}"
+ %(<task-button></task-button><input type="checkbox"
+ class="task-list-item-checkbox"
+ #{'checked="checked"' if item.complete?}
+ #{'data-inapplicable' if inapplicable?(item)}
+ disabled="disabled"/>)
+ end
+
+ override :render_task_list_item
+ def render_task_list_item(item)
+ source = item.source
+
+ if inapplicable?(item)
+ # Add a `<s>` tag around the list item text. However because of the
+ # way tasks are built, the source can include an embedded sublist, like
+ # `[~] foobar\n<ol><li....`
+ # The `<s>` should only be added to the main text.
+ source = source.partition("#{INAPPLICABLE} ")
+ text = source.last.partition(/\<(ol|ul)/)
+ text[0] = "<s>#{text[0]}</s>"
+ source[-1] = text.join
+ source = source.join
+ end
+
+ Nokogiri::HTML.fragment \
+ source.sub(ItemPattern, render_item_checkbox(item)), 'utf-8'
+ end
+
+ override :call
+ def call
+ super
+
+ # add class to li for any inapplicable checkboxes
+ doc.xpath(XPATH).each do |li|
+ li.add_class('inapplicable')
+ end
+
+ doc
end
end
end
diff --git a/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb b/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
index 01ee3f5d9e8..eef2b2674dd 100644
--- a/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
+++ b/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
@@ -11,9 +11,9 @@ module Banzai
def self.filters
@filters ||= FilterArray[
*super,
+ Filter::SanitizationFilter,
*Banzai::Pipeline::GfmPipeline.reference_filters,
Filter::EmojiFilter,
- Filter::SanitizationFilter,
Filter::ExternalLinkFilter,
Filter::ImageLinkFilter
]
diff --git a/lib/banzai/reference_redactor.rb b/lib/banzai/reference_redactor.rb
index c19f992078a..0c031ace977 100644
--- a/lib/banzai/reference_redactor.rb
+++ b/lib/banzai/reference_redactor.rb
@@ -41,8 +41,8 @@ module Banzai
nodes_for_document = entry[:nodes]
doc_data = {
- document: entry[:document],
- total_reference_count: nodes_for_document.count,
+ document: entry[:document],
+ total_reference_count: nodes_for_document.count,
visible_reference_count: nodes_for_document.count
}
diff --git a/lib/bitbucket/representation/base.rb b/lib/bitbucket/representation/base.rb
index bb8dcd91ad5..afd20d788c2 100644
--- a/lib/bitbucket/representation/base.rb
+++ b/lib/bitbucket/representation/base.rb
@@ -10,7 +10,7 @@ module Bitbucket
end
def self.decorate(entries)
- entries.map { |entry| new(entry)}
+ entries.map { |entry| new(entry) }
end
end
end
diff --git a/lib/bitbucket_server/representation/base.rb b/lib/bitbucket_server/representation/base.rb
index a1961bae6ef..d1a3089b7f5 100644
--- a/lib/bitbucket_server/representation/base.rb
+++ b/lib/bitbucket_server/representation/base.rb
@@ -10,7 +10,7 @@ module BitbucketServer
end
def self.decorate(entries)
- entries.map { |entry| new(entry)}
+ entries.map { |entry| new(entry) }
end
def self.convert_timestamp(time_usec)
diff --git a/lib/bulk_imports/clients/http.rb b/lib/bulk_imports/clients/http.rb
index 037da5e0816..1d77757c4af 100644
--- a/lib/bulk_imports/clients/http.rb
+++ b/lib/bulk_imports/clients/http.rb
@@ -35,7 +35,7 @@ module BulkImports
end
def each_page(method, resource, query = {}, &block)
- return to_enum(__method__, method, resource, query) unless block_given?
+ return to_enum(__method__, method, resource, query) unless block
next_page = @page
@@ -101,22 +101,19 @@ module BulkImports
def default_options
{
- headers: request_headers,
- follow_redirects: false
+ headers: { 'Content-Type' => 'application/json' },
+ query: request_query,
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
}
end
def request_query
{
page: @page,
- per_page: @per_page
- }
- end
-
- def request_headers
- {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{@token}"
+ per_page: @per_page,
+ private_token: @token
}
end
diff --git a/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
index 3067e0997c2..d9efcdb1ba5 100644
--- a/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
+++ b/lib/bulk_imports/groups/transformers/group_attributes_transformer.rb
@@ -38,7 +38,7 @@ module BulkImports
end
def transform_path(import_entity, data)
- data['path'] = import_entity.destination_name.parameterize
+ data['path'] = import_entity.destination_slug.parameterize
data
end
diff --git a/lib/bulk_imports/pipeline.rb b/lib/bulk_imports/pipeline.rb
index dc2ebdddd14..68b86c68619 100644
--- a/lib/bulk_imports/pipeline.rb
+++ b/lib/bulk_imports/pipeline.rb
@@ -12,7 +12,7 @@ module BulkImports
FailedError = Class.new(StandardError)
CACHE_KEY_EXPIRATION = 2.hours
- NDJSON_EXPORT_TIMEOUT = 30.minutes
+ NDJSON_EXPORT_TIMEOUT = 90.minutes
def initialize(context)
@context = context
diff --git a/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb b/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
index 38730a7723b..205c3185f72 100644
--- a/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
+++ b/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
@@ -11,8 +11,8 @@ module BulkImports
entity = context.entity
visibility = data.delete('visibility')
- project[:name] = entity.destination_name
- project[:path] = entity.destination_name.parameterize
+ project[:name] = entity.destination_slug
+ project[:path] = entity.destination_slug.parameterize
project[:created_at] = data['created_at']
project[:import_type] = PROJECT_IMPORT_TYPE
project[:visibility_level] = Gitlab::VisibilityLevel.string_options[visibility] if visibility.present?
diff --git a/lib/container_registry/gitlab_api_client.rb b/lib/container_registry/gitlab_api_client.rb
index c68b222af97..be99fa75ffe 100644
--- a/lib/container_registry/gitlab_api_client.rb
+++ b/lib/container_registry/gitlab_api_client.rb
@@ -21,6 +21,8 @@ module ContainerRegistry
REGISTRY_GITLAB_V1_API_FEATURE = 'gitlab_v1_api'
+ MAX_TAGS_PAGE_SIZE = 1000
+
def self.supports_gitlab_api?
with_dummy_client(return_value_if_disabled: false) do |client|
client.supports_gitlab_api?
@@ -86,6 +88,7 @@ module ContainerRegistry
end
end
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#get-repository-details
def repository_details(path, sizing: nil)
with_token_faraday do |faraday_client|
req = faraday_client.get("/gitlab/v1/repositories/#{path}/") do |req|
@@ -98,6 +101,26 @@ module ContainerRegistry
end
end
+ # https://gitlab.com/gitlab-org/container-registry/-/blob/master/docs-gitlab/api.md#list-repository-tags
+ 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|
+ req.params['n'] = limited_page_size
+ req.params['last'] = last if last
+ end
+
+ break {} unless response.success?
+
+ link_parser = Gitlab::Utils::LinkHeaderParser.new(response.headers['link'])
+
+ {
+ pagination: link_parser.parse,
+ response_body: response_body(response)
+ }
+ end
+ end
+
private
def start_import_for(path, pre:)
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
index 04a8e1d2e8f..76188a937c0 100644
--- a/lib/container_registry/tag.rb
+++ b/lib/container_registry/tag.rb
@@ -75,15 +75,28 @@ module ContainerRegistry
def created_at
return @created_at if @created_at
- return unless config
strong_memoize(:memoized_created_at) do
+ next unless config
+
DateTime.rfc3339(config['created'])
rescue ArgumentError
nil
end
end
+ # this function will set and memoize a created_at
+ # to avoid a #config_blob call.
+ def force_created_at_from_iso8601(string_value)
+ date =
+ begin
+ DateTime.iso8601(string_value)
+ rescue ArgumentError
+ nil
+ end
+ instance_variable_set(ivar(:memoized_created_at), date)
+ end
+
def layers
return unless manifest
diff --git a/lib/feature.rb b/lib/feature.rb
index ca91d86c199..f317e8cb2c5 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -31,7 +31,11 @@ module Feature
def feature_flags_available?
# When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised
- active_db_connection = ActiveRecord::Base.connection.active? rescue false # rubocop:disable Database/MultipleDatabases
+ active_db_connection = begin
+ ActiveRecord::Base.connection.active? # rubocop:disable Database/MultipleDatabases
+ rescue StandardError
+ false
+ end
active_db_connection && Feature::FlipperFeature.table_exists?
rescue ActiveRecord::NoDatabaseError
diff --git a/lib/gitlab/alert_management/payload/base.rb b/lib/gitlab/alert_management/payload/base.rb
index 5e535ded439..2d769148c5f 100644
--- a/lib/gitlab/alert_management/payload/base.rb
+++ b/lib/gitlab/alert_management/payload/base.rb
@@ -102,19 +102,19 @@ module Gitlab
# AlertManagement::Alert directly for read operations.
def alert_params
{
- description: description&.truncate(::AlertManagement::Alert::DESCRIPTION_MAX_LENGTH),
+ description: truncate(description, ::AlertManagement::Alert::DESCRIPTION_MAX_LENGTH),
ended_at: ends_at,
environment: environment,
fingerprint: gitlab_fingerprint,
hosts: truncate_hosts(Array(hosts).flatten),
- monitoring_tool: monitoring_tool&.truncate(::AlertManagement::Alert::TOOL_MAX_LENGTH),
+ monitoring_tool: truncate(monitoring_tool, ::AlertManagement::Alert::TOOL_MAX_LENGTH),
payload: payload,
project_id: project.id,
prometheus_alert: gitlab_alert,
- service: service&.truncate(::AlertManagement::Alert::SERVICE_MAX_LENGTH),
+ service: truncate(service, ::AlertManagement::Alert::SERVICE_MAX_LENGTH),
severity: severity,
started_at: starts_at,
- title: title&.truncate(::AlertManagement::Alert::TITLE_MAX_LENGTH)
+ title: truncate(title, ::AlertManagement::Alert::TITLE_MAX_LENGTH)
}.transform_values(&:presence).compact
end
@@ -161,6 +161,10 @@ module Gitlab
SEVERITY_MAPPING
end
+ def truncate(value, length)
+ value.to_s.truncate(length)
+ end
+
def truncate_hosts(hosts)
return hosts if hosts.join.length <= ::AlertManagement::Alert::HOSTS_MAX_LENGTH
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index 3e095585b18..0f0ecd82a32 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -21,6 +21,8 @@ module Gitlab
:related_class,
:feature_category,
:artifact_size,
+ :artifacts_dependencies_size,
+ :artifacts_dependencies_count,
:root_caller_id
].freeze
private_constant :KNOWN_KEYS
@@ -36,6 +38,8 @@ module Gitlab
Attribute.new(:related_class, String),
Attribute.new(:feature_category, String),
Attribute.new(:artifact, ::Ci::JobArtifact),
+ Attribute.new(:artifacts_dependencies_size, Integer),
+ Attribute.new(:artifacts_dependencies_count, Integer),
Attribute.new(:root_caller_id, String)
].freeze
@@ -82,15 +86,18 @@ module Gitlab
# rubocop: disable Metrics/PerceivedComplexity
def to_lazy_hash
{}.tap do |hash|
- hash[:user] = -> { username } if include_user?
- hash[:project] = -> { project_path } if include_project?
- hash[:root_namespace] = -> { root_namespace_path } if include_namespace?
- hash[:client_id] = -> { client } if include_client?
assign_hash_if_value(hash, :caller_id)
assign_hash_if_value(hash, :root_caller_id)
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, :artifacts_dependencies_size)
+ assign_hash_if_value(hash, :artifacts_dependencies_count)
+
+ hash[:user] = -> { username } if include_user?
+ hash[:project] = -> { project_path } if include_project?
+ hash[:root_namespace] = -> { root_namespace_path } if include_namespace?
+ hash[:client_id] = -> { client } if include_client?
hash[:pipeline_id] = -> { job&.pipeline_id } if set_values.include?(:job)
hash[:job_id] = -> { job&.id } if set_values.include?(:job)
hash[:artifact_size] = -> { artifact&.size } if set_values.include?(:artifact)
@@ -112,7 +119,9 @@ module Gitlab
end
def assign_hash_if_value(hash, attribute_name)
- raise ArgumentError unless KNOWN_KEYS.include?(attribute_name)
+ unless KNOWN_KEYS.include?(attribute_name)
+ raise ArgumentError, "unknown attribute `#{attribute_name}`"
+ end
# rubocop:disable GitlabSecurity/PublicSend
hash[attribute_name] = public_send(attribute_name) if set_values.include?(attribute_name)
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 0c52ce8aba4..a2d79b189a3 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -65,6 +65,8 @@ module Gitlab
# per user (scope))
# @param threshold [Integer] Optional threshold value to override default
# one registered in `.rate_limits`
+ # @param interval [Integer] Optional interval value to override default
+ # one registered in `.rate_limits`
# @param users_allowlist [Array<String>] Optional list of usernames to
# exclude from the limit. This param will only be functional if Scope
# includes a current user.
@@ -72,7 +74,7 @@ module Gitlab
# incremented but the current throttled state will be returned.
#
# @return [Boolean] Whether or not a request should be throttled
- def throttled?(key, scope:, resource: nil, threshold: nil, users_allowlist: nil, peek: false)
+ def throttled?(key, scope:, resource: nil, threshold: nil, interval: nil, users_allowlist: nil, peek: false)
raise InvalidKeyError unless rate_limits[key]
strategy = resource.present? ? IncrementPerActionedResource.new(resource.id) : IncrementPerAction.new
@@ -85,7 +87,7 @@ module Gitlab
return false if threshold_value == 0
- interval_value = interval(key)
+ interval_value = interval || interval(key)
return false if interval_value == 0
@@ -112,11 +114,12 @@ module Gitlab
# @param key [Symbol] Key attribute registered in `.rate_limits`
# @param scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
# @param threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
+ # @param interval [Integer] Optional interval value to override default one registered in `.rate_limits`
# @param users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
#
# @return [Boolean] Whether or not a request is currently throttled
- def peek(key, scope:, threshold: nil, users_allowlist: nil)
- throttled?(key, peek: true, scope: scope, threshold: threshold, users_allowlist: users_allowlist)
+ def peek(key, scope:, threshold: nil, interval: nil, users_allowlist: nil)
+ throttled?(key, peek: true, scope: scope, threshold: threshold, interval: interval, users_allowlist: users_allowlist)
end
# Logs request using provided logger
diff --git a/lib/gitlab/audit/auditor.rb b/lib/gitlab/audit/auditor.rb
new file mode 100644
index 00000000000..c96be19f02d
--- /dev/null
+++ b/lib/gitlab/audit/auditor.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Audit
+ class Auditor
+ attr_reader :scope, :name
+
+ # Record audit events
+ #
+ # @param [Hash] context
+ # @option context [String] :name the operation name to be audited, used for error tracking
+ # @option context [User] :author the user who authors the change
+ # @option context [User, Project, Group] :scope the scope which audit event belongs to
+ # @option context [Object] :target the target object being audited
+ # @option context [String] :message the message describing the action
+ # @option context [Hash] :additional_details the additional details we want to merge into audit event details.
+ # @option context [Time] :created_at the time that the event occurred (defaults to the current time)
+ #
+ # @example Using block (useful when events are emitted deep in the call stack)
+ # i.e. multiple audit events
+ #
+ # audit_context = {
+ # name: 'merge_approval_rule_updated',
+ # author: current_user,
+ # scope: project_alpha,
+ # target: merge_approval_rule,
+ # message: 'a user has attempted to update an approval rule'
+ # }
+ #
+ # # in the initiating service
+ # Gitlab::Audit::Auditor.audit(audit_context) do
+ # service.execute
+ # end
+ #
+ # # in the model
+ # Auditable.push_audit_event('an approver has been added')
+ # Auditable.push_audit_event('an approval group has been removed')
+ #
+ # @example Using standard method call
+ # i.e. single audit event
+ #
+ # merge_approval_rule.save
+ # Gitlab::Audit::Auditor.audit(audit_context)
+ #
+ # @return result of block execution
+ def self.audit(context, &block)
+ auditor = new(context)
+
+ return unless auditor.audit_enabled?
+
+ if block
+ auditor.multiple_audit(&block)
+ else
+ auditor.single_audit
+ end
+ end
+
+ def initialize(context = {})
+ @context = context
+
+ @name = @context.fetch(:name, 'audit_operation')
+ @stream_only = @context.fetch(:stream_only, false)
+ @author = @context.fetch(:author)
+ @scope = @context.fetch(:scope)
+ @target = @context.fetch(:target)
+ @created_at = @context.fetch(:created_at, DateTime.current)
+ @message = @context.fetch(:message, '')
+ @additional_details = @context.fetch(:additional_details, {})
+ @ip_address = @context[:ip_address]
+ @target_details = @context[:target_details]
+ @authentication_event = @context.fetch(:authentication_event, false)
+ @authentication_provider = @context[:authentication_provider]
+ end
+
+ def single_audit
+ events = [build_event(@message)]
+
+ record(events)
+ end
+
+ def multiple_audit
+ # For now we dont have any need to implement multiple audit event functionality in CE
+ # Defined in EE
+ end
+
+ def record(events)
+ log_events(events) unless @stream_only
+ send_to_stream(events)
+ end
+
+ def log_events(events)
+ log_authentication_event
+ log_to_database(events)
+ log_to_file(events)
+ end
+
+ def audit_enabled?
+ authentication_event?
+ end
+
+ def authentication_event?
+ @authentication_event
+ end
+
+ def log_authentication_event
+ return unless Gitlab::Database.read_write? && authentication_event?
+
+ event = AuthenticationEvent.new(authentication_event_payload)
+ event.save!
+ rescue ActiveRecord::RecordInvalid => e
+ ::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name)
+ end
+
+ def authentication_event_payload
+ {
+ # @author can be a User or various Gitlab::Audit authors.
+ # Only capture real users for successful authentication events.
+ user: author_if_user,
+ user_name: @author.name,
+ ip_address: @ip_address,
+ result: AuthenticationEvent.results[:success],
+ provider: @authentication_provider
+ }
+ end
+
+ def author_if_user
+ @author if @author.is_a?(User)
+ end
+
+ def send_to_stream(events)
+ # Defined in EE
+ end
+
+ def build_event(message)
+ AuditEvents::BuildService.new(
+ author: @author,
+ scope: @scope,
+ target: @target,
+ created_at: @created_at,
+ message: message,
+ additional_details: @additional_details,
+ ip_address: @ip_address,
+ target_details: @target_details
+ ).execute
+ end
+
+ def log_to_database(events)
+ AuditEvent.bulk_insert!(events)
+ rescue ActiveRecord::RecordInvalid => e
+ ::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name)
+ end
+
+ def log_to_file(events)
+ file_logger = ::Gitlab::AuditJsonLogger.build
+
+ events.each { |event| file_logger.info(log_payload(event)) }
+ end
+
+ private
+
+ def log_payload(event)
+ payload = event.as_json
+ details = formatted_details(event.details)
+ payload["details"] = details
+ payload.merge!(details).as_json
+ end
+
+ def formatted_details(details)
+ details.merge(details.slice(:from, :to).transform_values(&:to_s))
+ end
+ end
+ end
+end
+
+Gitlab::Audit::Auditor.prepend_mod_with("Gitlab::Audit::Auditor")
diff --git a/lib/gitlab/audit/deploy_key_author.rb b/lib/gitlab/audit/deploy_key_author.rb
new file mode 100644
index 00000000000..53029e9cc1c
--- /dev/null
+++ b/lib/gitlab/audit/deploy_key_author.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Audit
+ class DeployKeyAuthor < Gitlab::Audit::NullAuthor
+ def initialize(name: nil)
+ super(id: -3, name: name)
+ end
+
+ def name
+ @name || _('Deploy Key')
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/audit/null_author.rb b/lib/gitlab/audit/null_author.rb
index 08be6ae6d9f..cb0dfe45aef 100644
--- a/lib/gitlab/audit/null_author.rb
+++ b/lib/gitlab/audit/null_author.rb
@@ -24,6 +24,8 @@ module Gitlab
Gitlab::Audit::UnauthenticatedAuthor.new(name: name)
elsif id == -2
Gitlab::Audit::DeployTokenAuthor.new(name: name)
+ elsif id == -3
+ Gitlab::Audit::DeployKeyAuthor.new(name: name)
else
Gitlab::Audit::DeletedAuthor.new(id: id, name: name)
end
diff --git a/lib/gitlab/audit/null_target.rb b/lib/gitlab/audit/null_target.rb
new file mode 100644
index 00000000000..ed3a50e9067
--- /dev/null
+++ b/lib/gitlab/audit/null_target.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Audit
+ class NullTarget
+ def id
+ nil
+ end
+
+ def type
+ nil
+ end
+
+ def details
+ nil
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/audit/target.rb b/lib/gitlab/audit/target.rb
new file mode 100644
index 00000000000..b9cb54aece8
--- /dev/null
+++ b/lib/gitlab/audit/target.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Audit
+ class Target
+ delegate :id, to: :@object
+
+ def initialize(object)
+ @object = object
+ end
+
+ def type
+ @object.class.name
+ end
+
+ def details
+ @object.try(:name) || @object.try(:audit_details) || 'unknown'
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 6c3487c28ea..6213dd203c4 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -92,7 +92,7 @@ module Gitlab
return unless authenticate_using_internal_or_ldap_password?
Gitlab::Auth::UniqueIpsLimiter.limit_user! do
- user = User.by_login(login)
+ user = User.find_by_login(login)
break if user && !user.can_log_in_with_non_expired_password?
@@ -279,7 +279,7 @@ module Gitlab
if deploy_key_matches
DeployKey.find(deploy_key_matches[1])
else
- User.by_login(login)
+ User.find_by_login(login)
end
return unless actor
diff --git a/lib/gitlab/auth/auth_finders.rb b/lib/gitlab/auth/auth_finders.rb
index 7adaaef86e4..c994f179b66 100644
--- a/lib/gitlab/auth/auth_finders.rb
+++ b/lib/gitlab/auth/auth_finders.rb
@@ -103,7 +103,7 @@ module Gitlab
return unless has_basic_credentials?(current_request)
login, token = user_name_and_password(current_request)
- user = User.by_login(login)
+ user = User.find_by_login(login)
user if user && Gitlab::LfsToken.new(user).token_valid?(token)
end
diff --git a/lib/gitlab/auth/ip_rate_limiter.rb b/lib/gitlab/auth/ip_rate_limiter.rb
index f301a2ec2e8..0d50420b9f5 100644
--- a/lib/gitlab/auth/ip_rate_limiter.rb
+++ b/lib/gitlab/auth/ip_rate_limiter.rb
@@ -33,6 +33,10 @@ module Gitlab
Rack::Attack::Allow2Ban.banned?(ip)
end
+ def trusted_ip?
+ trusted_ips.any? { |netmask| netmask.include?(ip) }
+ end
+
private
def skip_rate_limit?
@@ -47,10 +51,6 @@ module Gitlab
Gitlab.config.rack_attack.git_basic_auth
end
- def trusted_ip?
- trusted_ips.any? { |netmask| netmask.include?(ip) }
- end
-
def trusted_ips
strong_memoize(:trusted_ips) do
config.ip_whitelist.map do |proxy|
diff --git a/lib/gitlab/auth/o_auth/auth_hash.rb b/lib/gitlab/auth/o_auth/auth_hash.rb
index a45778159c7..37f92792d2d 100644
--- a/lib/gitlab/auth/o_auth/auth_hash.rb
+++ b/lib/gitlab/auth/o_auth/auth_hash.rb
@@ -59,14 +59,43 @@ module Gitlab
auth_hash['info']
end
- def get_info(key)
- value = info[key]
+ def coerce_utf8(value)
value.is_a?(String) ? Gitlab::Utils.force_utf8(value) : value
end
+ def get_info(key)
+ coerce_utf8(info[key])
+ end
+
+ def provider_config
+ Gitlab::Auth::OAuth::Provider.config_for(@provider) || {}
+ end
+
+ def provider_args
+ @provider_args ||= provider_config['args'].presence || {}
+ end
+
+ def get_from_auth_hash_or_info(key)
+ coerce_utf8(auth_hash[key]) || get_info(key)
+ end
+
+ # Allow for configuring a custom username claim per provider from
+ # the auth hash or use the canonical username or nickname fields
+ def gitlab_username_claim
+ provider_args.dig('gitlab_username_claim')&.to_sym
+ end
+
+ def username_claims
+ [gitlab_username_claim, :username, :nickname].compact
+ end
+
+ def get_username
+ username_claims.map { |claim| get_from_auth_hash_or_info(claim) }.find { |name| name.presence }
+ end
+
def username_and_email
@username_and_email ||= begin
- username = get_info(:username).presence || get_info(:nickname).presence
+ username = get_username
email = get_info(:email).presence
username ||= generate_username(email) if email
diff --git a/lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb b/lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb
deleted file mode 100644
index 2247747ba08..00000000000
--- a/lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # A job to create ci_namespace_mirrors entries in batches
- class BackfillCiNamespaceMirrors
- class Namespace < ActiveRecord::Base # rubocop:disable Style/Documentation
- include ::EachBatch
-
- self.table_name = 'namespaces'
- self.inheritance_column = nil
-
- scope :base_query, -> do
- select(:id, :parent_id)
- end
- end
-
- PAUSE_SECONDS = 0.1
- SUB_BATCH_SIZE = 500
-
- def perform(start_id, end_id)
- batch_query = Namespace.base_query.where(id: start_id..end_id)
- batch_query.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('MIN(id), MAX(id)')).first
- ranged_query = Namespace.unscoped.base_query.where(id: first..last)
-
- update_sql = <<~SQL
- INSERT INTO ci_namespace_mirrors (namespace_id, traversal_ids)
- #{insert_values(ranged_query)}
- ON CONFLICT (namespace_id) DO NOTHING
- SQL
- # We do nothing on conflict because we consider they were already filled.
-
- Namespace.connection.execute(update_sql)
-
- sleep PAUSE_SECONDS
- end
-
- mark_job_as_succeeded(start_id, end_id)
- end
-
- private
-
- def insert_values(batch)
- calculated_traversal_ids(
- batch.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
- )
- end
-
- # Copied from lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb
- def calculated_traversal_ids(batch)
- <<~SQL
- WITH RECURSIVE cte(source_id, namespace_id, parent_id, height) AS (
- (
- SELECT batch.id, batch.id, batch.parent_id, 1
- FROM (#{batch.to_sql}) AS batch
- )
- UNION ALL
- (
- SELECT cte.source_id, n.id, n.parent_id, cte.height+1
- FROM namespaces n, cte
- WHERE n.id = cte.parent_id
- )
- )
- SELECT flat_hierarchy.source_id as namespace_id,
- array_agg(flat_hierarchy.namespace_id ORDER BY flat_hierarchy.height DESC) as traversal_ids
- FROM (SELECT * FROM cte FOR UPDATE) flat_hierarchy
- GROUP BY flat_hierarchy.source_id
- SQL
- end
-
- def mark_job_as_succeeded(*arguments)
- Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillCiNamespaceMirrors', arguments)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_ci_project_mirrors.rb b/lib/gitlab/background_migration/backfill_ci_project_mirrors.rb
deleted file mode 100644
index ff6ab9928b0..00000000000
--- a/lib/gitlab/background_migration/backfill_ci_project_mirrors.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # A job to create ci_project_mirrors entries in batches
- class BackfillCiProjectMirrors
- class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
- include ::EachBatch
-
- self.table_name = 'projects'
-
- scope :base_query, -> do
- select(:id, :namespace_id)
- end
- end
-
- PAUSE_SECONDS = 0.1
- SUB_BATCH_SIZE = 500
-
- def perform(start_id, end_id)
- batch_query = Project.base_query.where(id: start_id..end_id)
- batch_query.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('MIN(id), MAX(id)')).first
- ranged_query = Project.unscoped.base_query.where(id: first..last)
-
- update_sql = <<~SQL
- INSERT INTO ci_project_mirrors (project_id, namespace_id)
- #{insert_values(ranged_query)}
- ON CONFLICT (project_id) DO NOTHING
- SQL
- # We do nothing on conflict because we consider they were already filled.
-
- Project.connection.execute(update_sql)
-
- sleep PAUSE_SECONDS
- end
-
- mark_job_as_succeeded(start_id, end_id)
- end
-
- private
-
- def insert_values(batch)
- batch.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433').to_sql
- end
-
- def mark_job_as_succeeded(*arguments)
- Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillCiProjectMirrors', arguments)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_ci_runner_semver.rb b/lib/gitlab/background_migration/backfill_ci_runner_semver.rb
deleted file mode 100644
index 0901649f789..00000000000
--- a/lib/gitlab/background_migration/backfill_ci_runner_semver.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # A job to update semver column in ci_runners in batches based on existing version values
- class BackfillCiRunnerSemver < Gitlab::BackgroundMigration::BatchedMigrationJob
- def perform
- each_sub_batch(
- operation_name: :backfill_ci_runner_semver,
- batching_scope: ->(relation) { relation.where('semver::cidr IS NULL') }
- ) do |sub_batch|
- ranged_query = sub_batch.select(
- %q(id AS r_id,
- substring(ci_runners.version FROM 'v?(\d+\.\d+\.\d+)') AS extracted_semver)
- )
-
- update_sql = <<~SQL
- UPDATE
- ci_runners
- SET semver = extracted_semver
- FROM (#{ranged_query.to_sql}) v
- WHERE id = v.r_id
- AND v.extracted_semver IS NOT NULL
- SQL
-
- connection.execute(update_sql)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_group_features.rb b/lib/gitlab/background_migration/backfill_group_features.rb
index 4c3af7be319..35b5282360f 100644
--- a/lib/gitlab/background_migration/backfill_group_features.rb
+++ b/lib/gitlab/background_migration/backfill_group_features.rb
@@ -4,19 +4,21 @@ module Gitlab
module BackgroundMigration
# Backfill group_features for an array of groups
class BackfillGroupFeatures < ::Gitlab::BackgroundMigration::BatchedMigrationJob
- def perform(batch_size)
+ job_arguments :batch_size
+
+ def perform
each_sub_batch(
operation_name: :upsert_group_features,
batching_arguments: { order_hint: :type },
batching_scope: ->(relation) { relation.where(type: 'Group') }
) do |sub_batch|
- upsert_group_features(sub_batch, batch_size)
+ upsert_group_features(sub_batch)
end
end
private
- def upsert_group_features(relation, batch_size)
+ def upsert_group_features(relation)
connection.execute(
<<~SQL
INSERT INTO group_features (group_id, created_at, updated_at)
diff --git a/lib/gitlab/background_migration/backfill_integrations_type_new.rb b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
index 6f33472af7d..b07d9371c19 100644
--- a/lib/gitlab/background_migration/backfill_integrations_type_new.rb
+++ b/lib/gitlab/background_migration/backfill_integrations_type_new.rb
@@ -27,7 +27,7 @@ module Gitlab
def process_sub_batch(sub_batch)
# Extract the start/stop IDs from the current sub-batch
- sub_start_id, sub_stop_id = sub_batch.pluck(Arel.sql('MIN(id), MAX(id)')).first
+ sub_start_id, sub_stop_id = sub_batch.pick(Arel.sql('MIN(id), MAX(id)'))
# This matches the mapping from the INSERT trigger added in
# db/migrate/20210721135638_add_triggers_to_integrations_type_new.rb
diff --git a/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads.rb b/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads.rb
new file mode 100644
index 00000000000..cd349bf3ae1
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Sets the `namespace_id` of the existing `vulnerability_reads` records
+ class BackfillNamespaceIdOfVulnerabilityReads < BatchedMigrationJob
+ UPDATE_SQL = <<~SQL
+ UPDATE
+ vulnerability_reads
+ SET
+ namespace_id = sub_query.namespace_id
+ FROM
+ (%<subquery>s) as sub_query
+ WHERE
+ vulnerability_reads.vulnerability_id = sub_query.vulnerability_id
+ SQL
+
+ def perform
+ each_sub_batch(operation_name: :set_namespace_id) do |sub_batch|
+ update_query = update_query_for(sub_batch)
+
+ connection.execute(update_query)
+ end
+ end
+
+ private
+
+ def update_query_for(sub_batch)
+ subquery = sub_batch.select("vulnerability_reads.vulnerability_id, projects.namespace_id")
+ .joins("INNER JOIN projects ON projects.id = vulnerability_reads.project_id")
+
+ format(UPDATE_SQL, subquery: subquery.to_sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb b/lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb
index 587de1bcb5a..3b8a452b855 100644
--- a/lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb
+++ b/lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb
@@ -19,7 +19,7 @@ module Gitlab
def perform(start_id, end_id, sub_batch_size)
batch_query = Namespace.base_query.where(id: start_id..end_id)
batch_query.each_batch(of: sub_batch_size) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
ranged_query = Namespace.unscoped.base_query.where(id: first..last)
update_sql = <<~SQL
diff --git a/lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb b/lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb
index 1c0a83285a6..c69289fb91f 100644
--- a/lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb
+++ b/lib/gitlab/background_migration/backfill_namespace_traversal_ids_roots.rb
@@ -22,7 +22,7 @@ module Gitlab
.where("traversal_ids = '{}'")
ranged_query.each_batch(of: sub_batch_size) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
# The query need to be reconstructed because .each_batch modifies the default scope
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/330510
diff --git a/lib/gitlab/background_migration/backfill_project_import_level.rb b/lib/gitlab/background_migration/backfill_project_import_level.rb
new file mode 100644
index 00000000000..06706b729ea
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_project_import_level.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+module Gitlab
+ module BackgroundMigration
+ class BackfillProjectImportLevel < BatchedMigrationJob
+ LEVEL = {
+ Gitlab::Access::NO_ACCESS => [0],
+ Gitlab::Access::DEVELOPER => [2],
+ Gitlab::Access::MAINTAINER => [1],
+ Gitlab::Access::OWNER => [nil]
+ }.freeze
+
+ def perform
+ each_sub_batch(operation_name: :update_import_level) do |sub_batch|
+ update_import_level(sub_batch)
+ end
+ end
+
+ private
+
+ def update_import_level(relation)
+ LEVEL.each do |import_level, creation_level|
+ namespace_ids = relation
+ .where(type: 'Group', project_creation_level: creation_level)
+
+ NamespaceSetting.where(
+ namespace_id: namespace_ids
+ ).update_all(project_import_level: import_level)
+ end
+ end
+ end
+ end
+end
+
+# rubocop:enable Style/Documentation
diff --git a/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent.rb b/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent.rb
new file mode 100644
index 00000000000..728b60f7a0e
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Backfills the `vulnerability_reads.casted_cluster_agent_id` column
+ class BackfillVulnerabilityReadsClusterAgent < Gitlab::BackgroundMigration::BatchedMigrationJob
+ CLUSTER_AGENTS_JOIN = <<~SQL
+ INNER JOIN cluster_agents
+ ON CAST(vulnerability_reads.cluster_agent_id AS bigint) = cluster_agents.id AND
+ vulnerability_reads.project_id = cluster_agents.project_id
+ SQL
+
+ RELATION = ->(relation) do
+ relation
+ .where(report_type: 7)
+ end
+
+ def perform
+ each_sub_batch(
+ operation_name: :update_all,
+ batching_scope: RELATION
+ ) do |sub_batch|
+ sub_batch
+ .joins(CLUSTER_AGENTS_JOIN)
+ .update_all('casted_cluster_agent_id = CAST(vulnerability_reads.cluster_agent_id AS bigint)')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb b/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb
index a16efa4222b..32962f2bb89 100644
--- a/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb
+++ b/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues.rb
@@ -20,7 +20,7 @@ module Gitlab
parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id, base_type)
parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
# The query need to be reconstructed because .each_batch modifies the default scope
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/330510
diff --git a/lib/gitlab/background_migration/batched_migration_job.rb b/lib/gitlab/background_migration/batched_migration_job.rb
index c47b1735ccf..11d15804344 100644
--- a/lib/gitlab/background_migration/batched_migration_job.rb
+++ b/lib/gitlab/background_migration/batched_migration_job.rb
@@ -3,22 +3,62 @@
module Gitlab
module BackgroundMigration
# Base class for batched background migrations. Subclasses should implement the `#perform`
- # method as the entry point for the job's execution, which will be called with the migration
- # arguments (if any).
+ # method as the entry point for the job's execution.
+ #
+ # Job arguments needed must be defined explicitly,
+ # see https://docs.gitlab.com/ee/development/database/batched_background_migrations.html#job-arguments.
class BatchedMigrationJob
include Gitlab::Database::DynamicModelHelpers
- def initialize(start_id:, end_id:, batch_table:, batch_column:, sub_batch_size:, pause_ms:, connection:)
+ def initialize(
+ start_id:, end_id:, batch_table:, batch_column:, sub_batch_size:, pause_ms:, job_arguments: [], connection:
+ )
+
@start_id = start_id
@end_id = end_id
@batch_table = batch_table
@batch_column = batch_column
@sub_batch_size = sub_batch_size
@pause_ms = pause_ms
+ @job_arguments = job_arguments
@connection = connection
end
- def perform(*job_arguments)
+ def self.generic_instance(batch_table:, batch_column:, job_arguments: [], connection:)
+ new(
+ batch_table: batch_table, batch_column: batch_column,
+ job_arguments: job_arguments, connection: connection,
+ start_id: 0, end_id: 0, sub_batch_size: 0, pause_ms: 0
+ )
+ end
+
+ def self.job_arguments_count
+ 0
+ end
+
+ def self.job_arguments(*args)
+ args.each.with_index do |arg, index|
+ define_method(arg) do
+ @job_arguments[index]
+ end
+ end
+
+ define_singleton_method(:job_arguments_count) do
+ args.count
+ end
+ end
+
+ def self.scope_to(scope)
+ define_method(:filter_batch) do |relation|
+ instance_exec(relation, &scope)
+ end
+ end
+
+ def filter_batch(relation)
+ relation
+ end
+
+ def perform
raise NotImplementedError, "subclasses of #{self.class.name} must implement #{__method__}"
end
@@ -33,9 +73,10 @@ module Gitlab
def each_sub_batch(operation_name: :default, batching_arguments: {}, batching_scope: nil)
all_batching_arguments = { column: batch_column, of: sub_batch_size }.merge(batching_arguments)
- parent_relation = parent_batch_relation(batching_scope)
+ relation = filter_batch(base_relation)
+ sub_batch_relation = filter_sub_batch(relation, batching_scope)
- parent_relation.each_batch(**all_batching_arguments) do |relation|
+ sub_batch_relation.each_batch(**all_batching_arguments) do |relation|
batch_metrics.instrument_operation(operation_name) do
yield relation
end
@@ -45,9 +86,13 @@ module Gitlab
end
def distinct_each_batch(operation_name: :default, batching_arguments: {})
+ if base_relation != filter_batch(base_relation)
+ raise 'distinct_each_batch can not be used when additional filters are defined with scope_to'
+ end
+
all_batching_arguments = { column: batch_column, of: sub_batch_size }.merge(batching_arguments)
- parent_batch_relation.distinct_each_batch(**all_batching_arguments) do |relation|
+ base_relation.distinct_each_batch(**all_batching_arguments) do |relation|
batch_metrics.instrument_operation(operation_name) do
yield relation
end
@@ -56,13 +101,15 @@ module Gitlab
end
end
- def parent_batch_relation(batching_scope = nil)
- parent_relation = define_batchable_model(batch_table, connection: connection)
+ def base_relation
+ define_batchable_model(batch_table, connection: connection)
.where(batch_column => start_id..end_id)
+ end
- return parent_relation unless batching_scope
+ def filter_sub_batch(relation, batching_scope = nil)
+ return relation unless batching_scope
- batching_scope.call(parent_relation)
+ batching_scope.call(relation)
end
end
end
diff --git a/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb
index 68be42dc0a0..12fd9ae7161 100644
--- a/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb
+++ b/lib/gitlab/background_migration/batching_strategies/backfill_project_namespace_per_group_batching_strategy.rb
@@ -25,7 +25,7 @@ module Gitlab
relation = model_class.where(projects_table[:namespace_id].in(hierarchy_cte_sql)).where("#{quoted_column_name} >= ?", batch_min_value)
relation.each_batch(of: batch_size, column: column_name) do |batch| # rubocop:disable Lint/UnreachableLoop
- next_batch_bounds = batch.pluck(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})")).first
+ next_batch_bounds = batch.pick(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})"))
break
end
diff --git a/lib/gitlab/background_migration/batching_strategies/backfill_vulnerability_reads_cluster_agent_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/backfill_vulnerability_reads_cluster_agent_batching_strategy.rb
new file mode 100644
index 00000000000..f0d015198dc
--- /dev/null
+++ b/lib/gitlab/background_migration/batching_strategies/backfill_vulnerability_reads_cluster_agent_batching_strategy.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module BatchingStrategies
+ # Batching class to use for back-filling vulnerability_read's casted_cluster_agent_id from cluster_agent_id.
+ # Batches will be scoped to records where the report_type belongs to cluster_image_scanning.
+ #
+ # If no more batches exist in the table, returns nil.
+ class BackfillVulnerabilityReadsClusterAgentBatchingStrategy < PrimaryKeyBatchingStrategy
+ CLUSTER_IMAGE_SCANNING_REPORT_TYPE = 7
+
+ def apply_additional_filters(relation, job_arguments: [], job_class: nil)
+ relation.where(report_type: CLUSTER_IMAGE_SCANNING_REPORT_TYPE)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb
index 5cad9d2e3c4..fc08d2b0ab6 100644
--- a/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb
+++ b/lib/gitlab/background_migration/batching_strategies/loose_index_scan_batching_strategy.rb
@@ -24,7 +24,7 @@ module Gitlab
next_batch_bounds = nil
relation.distinct_each_batch(of: batch_size, column: column_name) do |batch| # rubocop:disable Lint/UnreachableLoop
- next_batch_bounds = batch.pluck(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})")).first
+ next_batch_bounds = batch.pick(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})"))
break
end
diff --git a/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb b/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
index c2f59bf9c76..1ffa4a052e5 100644
--- a/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
+++ b/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy.rb
@@ -24,11 +24,19 @@ module Gitlab
quoted_column_name = model_class.connection.quote_column_name(column_name)
relation = model_class.where("#{quoted_column_name} >= ?", batch_min_value)
+
+ if job_class
+ relation = filter_batch(relation,
+ table_name: table_name, column_name: column_name,
+ job_class: job_class, job_arguments: job_arguments
+ )
+ end
+
relation = apply_additional_filters(relation, job_arguments: job_arguments, job_class: job_class)
next_batch_bounds = nil
relation.each_batch(of: batch_size, column: column_name) do |batch| # rubocop:disable Lint/UnreachableLoop
- next_batch_bounds = batch.pluck(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})")).first
+ next_batch_bounds = batch.pick(Arel.sql("MIN(#{quoted_column_name}), MAX(#{quoted_column_name})"))
break
end
@@ -36,13 +44,27 @@ module Gitlab
next_batch_bounds
end
+ # Deprecated
+ #
+ # Use `scope_to` to define additional filters on the migration job class.
+ #
+ # see https://docs.gitlab.com/ee/development/database/batched_background_migrations.html#adding-additional-filters.
def apply_additional_filters(relation, job_arguments: [], job_class: nil)
- if job_class.respond_to?(:batching_scope)
- return job_class.batching_scope(relation, job_arguments: job_arguments)
- end
-
relation
end
+
+ private
+
+ def filter_batch(relation, table_name:, column_name:, job_class:, job_arguments: [])
+ return relation unless job_class.respond_to?(:generic_instance)
+
+ job = job_class.generic_instance(
+ batch_table: table_name, batch_column: column_name,
+ job_arguments: job_arguments, connection: connection
+ )
+
+ job.filter_batch(relation)
+ end
end
end
end
diff --git a/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb b/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb
index cb9b0e88ef4..4da120769a0 100644
--- a/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb
+++ b/lib/gitlab/background_migration/cleanup_orphaned_lfs_objects_projects.rb
@@ -62,7 +62,7 @@ module Gitlab
batch = LfsObjectsProject.where(id: start_id..end_id)
batch.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(lfs_objects_projects.id), max(lfs_objects_projects.id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(lfs_objects_projects.id), max(lfs_objects_projects.id)'))
lfs_objects_without_association =
LfsObjectsProject
diff --git a/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb b/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb
deleted file mode 100644
index 107ac9b0c3b..00000000000
--- a/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class CopyCiBuildsColumnsToSecurityScans
- extend ::Gitlab::Utils::Override
-
- UPDATE_BATCH_SIZE = 500
-
- def perform(start_id, stop_id)
- (start_id..stop_id).step(UPDATE_BATCH_SIZE).each do |offset|
- batch_start = offset
- batch_stop = offset + UPDATE_BATCH_SIZE - 1
-
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE
- security_scans
- SET
- project_id = ci_builds.project_id,
- pipeline_id = ci_builds.commit_id
- FROM ci_builds
- WHERE ci_builds.type='Ci::Build'
- AND ci_builds.id=security_scans.build_id
- AND security_scans.id BETWEEN #{Integer(batch_start)} AND #{Integer(batch_stop)}
- SQL
- end
-
- mark_job_as_succeeded(start_id, stop_id)
- rescue StandardError => error
- Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
- end
-
- private
-
- def mark_job_as_succeeded(*arguments)
- Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
- 'CopyCiBuildsColumnsToSecurityScans',
- arguments
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
index 826845935b8..15e54431a44 100644
--- a/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
+++ b/lib/gitlab/background_migration/copy_column_using_background_migration_job.rb
@@ -14,7 +14,9 @@ module Gitlab
# - The table that is migrated does _not_ need `id` as the primary key
# We use the provided primary_key column to perform the update.
class CopyColumnUsingBackgroundMigrationJob < BatchedMigrationJob
- def perform(copy_from, copy_to)
+ job_arguments :copy_from, :copy_to
+
+ def perform
assignment_clauses = build_assignment_clauses(copy_from, copy_to)
each_sub_batch(operation_name: :update_all) do |relation|
diff --git a/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb
new file mode 100644
index 00000000000..019c3d15b3e
--- /dev/null
+++ b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Set `project_settings.legacy_open_source_license_available` to false for public projects with no issues & no repo
+ class DisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects < ::Gitlab::BackgroundMigration::BatchedMigrationJob
+ PUBLIC = 20
+
+ # Migration only version of `project_settings` table
+ class ProjectSetting < ApplicationRecord
+ self.table_name = 'project_settings'
+ end
+
+ def perform
+ each_sub_batch(
+ operation_name: :disable_legacy_open_source_license_for_no_issues_no_repo_projects,
+ batching_scope: ->(relation) { relation.where(visibility_level: PUBLIC) }
+ ) do |sub_batch|
+ no_issues_no_repo_projects =
+ sub_batch
+ .joins('LEFT OUTER JOIN project_statistics ON project_statistics.project_id = projects.id')
+ .joins('LEFT OUTER JOIN project_settings ON project_settings.project_id = projects.id')
+ .joins('LEFT OUTER JOIN issues ON issues.project_id = projects.id')
+ .where('project_statistics.repository_size' => 0,
+ 'project_settings.legacy_open_source_license_available' => true)
+ .group('projects.id')
+ .having('COUNT(issues.id) = 0')
+
+ ProjectSetting
+ .where(project_id: no_issues_no_repo_projects)
+ .update_all(legacy_open_source_license_available: false)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects.rb b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects.rb
new file mode 100644
index 00000000000..3a9049b1f19
--- /dev/null
+++ b/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Set `project_settings.legacy_open_source_license_available` to false for public projects with 1 member and no repo
+ class DisableLegacyOpenSourceLicenseForOneMemberNoRepoProjects < ::Gitlab::BackgroundMigration::BatchedMigrationJob
+ PUBLIC = 20
+
+ # Migration only version of `project_settings` table
+ class ProjectSetting < ApplicationRecord
+ self.table_name = 'project_settings'
+ end
+
+ def perform
+ each_sub_batch(
+ operation_name: :disable_legacy_open_source_license_for_one_member_no_repo_projects,
+ batching_scope: ->(relation) { relation.where(visibility_level: PUBLIC) }
+ ) do |sub_batch|
+ one_member_no_repo_projects =
+ sub_batch
+ .joins('LEFT OUTER JOIN project_statistics ON project_statistics.project_id = projects.id')
+ .joins('LEFT OUTER JOIN project_settings ON project_settings.project_id = projects.id')
+ .joins('LEFT OUTER JOIN project_authorizations ON project_authorizations.project_id = projects.id')
+ .where('project_statistics.repository_size' => 0,
+ 'project_settings.legacy_open_source_license_available' => true)
+ .group('projects.id')
+ .having('COUNT(project_authorizations.user_id) = 1')
+
+ ProjectSetting
+ .where(project_id: one_member_no_repo_projects)
+ .update_all(legacy_open_source_license_available: false)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/drop_invalid_security_findings.rb b/lib/gitlab/background_migration/drop_invalid_security_findings.rb
index 87551bb1b1e..000628e109c 100644
--- a/lib/gitlab/background_migration/drop_invalid_security_findings.rb
+++ b/lib/gitlab/background_migration/drop_invalid_security_findings.rb
@@ -19,7 +19,7 @@ module Gitlab
.no_uuid
ranged_query.each_batch(of: sub_batch_size) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
# The query need to be reconstructed because .each_batch modifies the default scope
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/330510
diff --git a/lib/gitlab/background_migration/encrypt_static_object_token.rb b/lib/gitlab/background_migration/encrypt_static_object_token.rb
index a087d2529eb..e1805d40bab 100644
--- a/lib/gitlab/background_migration/encrypt_static_object_token.rb
+++ b/lib/gitlab/background_migration/encrypt_static_object_token.rb
@@ -23,7 +23,7 @@ module Gitlab
.without_static_object_token_encrypted
ranged_query.each_batch(of: BATCH_SIZE) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
batch_query = User.unscoped
.where(id: first..last)
diff --git a/lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb b/lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb
index 8f785476aa0..6de2187b8e3 100644
--- a/lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb
+++ b/lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb
@@ -29,7 +29,7 @@ module Gitlab
def perform(start_id, end_id)
scope(start_id, end_id).each_batch(of: SUB_BATCH_SIZE, column: :issue_id) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(issue_id), max(issue_id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(issue_id), max(issue_id)'))
# The query need to be reconstructed because .each_batch modifies the default scope
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/330510
diff --git a/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb b/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
index 496ec0bd0a1..97a9913fa74 100644
--- a/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
+++ b/lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb
@@ -137,7 +137,7 @@ module Gitlab
def create_sql(from_id, to_id)
<<~SQL
WITH created_records AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- INSERT INTO services (project_id, #{DEFAULTS.keys.map { |key| %("#{key}")}.join(',')}, created_at, updated_at)
+ INSERT INTO services (project_id, #{DEFAULTS.keys.map { |key| %("#{key}") }.join(',')}, created_at, updated_at)
#{select_insert_values_sql(from_id, to_id)}
RETURNING *
)
diff --git a/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb b/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb
new file mode 100644
index 00000000000..bea0120f093
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_shared_vulnerability_scanners.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class MigrateSharedVulnerabilityScanners < BatchedMigrationJob
+ def perform
+ end
+ end
+ # rubocop: enable Style/Documentation
+ end
+end
+
+# rubocop: disable Layout/LineLength
+Gitlab::BackgroundMigration::MigrateSharedVulnerabilityScanners.prepend_mod_with("Gitlab::BackgroundMigration::MigrateSharedVulnerabilityScanners")
+# rubocop: enable Layout/LineLength
diff --git a/lib/gitlab/background_migration/populate_status_column_of_security_scans.rb b/lib/gitlab/background_migration/populate_status_column_of_security_scans.rb
deleted file mode 100644
index 9740bcaa86b..00000000000
--- a/lib/gitlab/background_migration/populate_status_column_of_security_scans.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- class PopulateStatusColumnOfSecurityScans # rubocop:disable Style/Documentation
- def perform(_start_id, _end_id)
- # no-op
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PopulateStatusColumnOfSecurityScans.prepend_mod
diff --git a/lib/gitlab/background_migration/populate_vulnerability_reads.rb b/lib/gitlab/background_migration/populate_vulnerability_reads.rb
index 5e6475a3d1a..656c62d9ee5 100644
--- a/lib/gitlab/background_migration/populate_vulnerability_reads.rb
+++ b/lib/gitlab/background_migration/populate_vulnerability_reads.rb
@@ -10,7 +10,7 @@ module Gitlab
def perform(start_id, end_id, sub_batch_size)
vulnerability_model.where(id: start_id..end_id).each_batch(of: sub_batch_size) do |sub_batch|
- first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+ first, last = sub_batch.pick(Arel.sql('min(id), max(id)'))
connection.execute(insert_query(first, last))
sleep PAUSE_SECONDS
diff --git a/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
index 2b27bad3497..845a3c16bbe 100644
--- a/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
+++ b/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb
@@ -105,9 +105,11 @@ module Gitlab
.joins("INNER JOIN namespaces n2 ON namespaces.parent_id = n2.id")
.select("namespaces.id as project_namespace_id, n2.traversal_ids")
+ # some customers have namespaces.id column type as bigint, which makes array_append(integer[], bigint) to fail
+ # so we just explicitly cast arguments to compatible types
ApplicationRecord.connection.execute <<~SQL
UPDATE namespaces
- SET traversal_ids = array_append(project_namespaces.traversal_ids, project_namespaces.project_namespace_id)
+ SET traversal_ids = array_append(project_namespaces.traversal_ids::bigint[], project_namespaces.project_namespace_id::bigint)
FROM (#{namespaces.to_sql}) as project_namespaces(project_namespace_id, traversal_ids)
WHERE id = project_namespaces.project_namespace_id
SQL
diff --git a/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb b/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb
index bba1ca26b35..e9a38916999 100644
--- a/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb
+++ b/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb
@@ -1,42 +1,74 @@
# frozen_string_literal: true
# rubocop: disable Style/Documentation
-class Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeBasedOnUrl
- # rubocop: disable Gitlab/NamespacedClass
- class JiraTrackerData < ActiveRecord::Base
- self.table_name = "jira_tracker_data"
- self.inheritance_column = :_type_disabled
+module Gitlab
+ module BackgroundMigration
+ class UpdateJiraTrackerDataDeploymentTypeBasedOnUrl < Gitlab::BackgroundMigration::BatchedMigrationJob
+ # rubocop: disable Gitlab/NamespacedClass
+ class JiraTrackerData < ActiveRecord::Base
+ self.table_name = "jira_tracker_data"
+ self.inheritance_column = :_type_disabled
- include ::Integrations::BaseDataFields
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
+ include ::Integrations::BaseDataFields
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
- enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
- end
- # rubocop: enable Gitlab/NamespacedClass
+ enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
+ end
+ # rubocop: enable Gitlab/NamespacedClass
- # https://rubular.com/r/uwgK7k9KH23efa
- JIRA_CLOUD_REGEX = %r{^https?://[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.atlassian\.net$}ix.freeze
+ # https://rubular.com/r/uwgK7k9KH23efa
+ JIRA_CLOUD_REGEX = %r{^https?://[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.atlassian\.net$}ix.freeze
- # rubocop: disable CodeReuse/ActiveRecord
- def perform(start_id, end_id)
- trackers_data = JiraTrackerData
- .where(deployment_type: 'unknown')
- .where(id: start_id..end_id)
+ def perform
+ cloud = []
+ server = []
+ unknown = []
- cloud, server = trackers_data.partition { |tracker_data| tracker_data.url.match?(JIRA_CLOUD_REGEX) }
+ trackers_data.each do |tracker_data|
+ client_url = tracker_data.api_url.presence || tracker_data.url
- cloud_mappings = cloud.each_with_object({}) do |tracker_data, hash|
- hash[tracker_data] = { deployment_type: 2 }
- end
+ if client_url.blank?
+ unknown << tracker_data
+ elsif client_url.match?(JIRA_CLOUD_REGEX)
+ cloud << tracker_data
+ else
+ server << tracker_data
+ end
+ end
- server_mapppings = server.each_with_object({}) do |tracker_data, hash|
- hash[tracker_data] = { deployment_type: 1 }
- end
+ cloud_mappings = cloud.each_with_object({}) do |tracker_data, hash|
+ hash[tracker_data] = { deployment_type: 2 }
+ end
+
+ server_mappings = server.each_with_object({}) do |tracker_data, hash|
+ hash[tracker_data] = { deployment_type: 1 }
+ end
+
+ unknown_mappings = unknown.each_with_object({}) do |tracker_data, hash|
+ hash[tracker_data] = { deployment_type: 0 }
+ end
- mappings = cloud_mappings.merge(server_mapppings)
+ mappings = cloud_mappings.merge(server_mappings, unknown_mappings)
- ::Gitlab::Database::BulkUpdate.execute(%i[deployment_type], mappings)
+ update_records(mappings)
+ end
+
+ private
+
+ def update_records(mappings)
+ return if mappings.empty?
+
+ ::Gitlab::Database::BulkUpdate.execute(%i[deployment_type], mappings)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def trackers_data
+ @trackers_data ||= JiraTrackerData
+ .where(deployment_type: 'unknown')
+ .where(batch_column => start_id..end_id)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
index 38932e52bb0..b61f2ee7f4c 100644
--- a/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
+++ b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
@@ -12,7 +12,7 @@ module Gitlab
define_batchable_model('timelogs', connection: connection)
.where(spent_at: nil, id: start_id..stop_id)
.each_batch(of: 100) do |subbatch|
- batch_start, batch_end = subbatch.pluck('min(id), max(id)').first
+ batch_start, batch_end = subbatch.pick('min(id), max(id)')
update_timelogs(batch_start, batch_end)
end
diff --git a/lib/gitlab/background_task.rb b/lib/gitlab/background_task.rb
new file mode 100644
index 00000000000..1f03e32844c
--- /dev/null
+++ b/lib/gitlab/background_task.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # Used to run small workloads concurrently to other threads in the current process.
+ # This may be necessary when accessing process state, which cannot be done via
+ # Sidekiq jobs.
+ #
+ # Since the given task is put on its own thread, use instances sparingly and only
+ # for fast computations since they will compete with other threads such as Puma
+ # or Sidekiq workers for CPU time and memory.
+ #
+ # Good examples:
+ # - Polling and updating process counters
+ # - Observing process or thread state
+ # - Enforcing process limits at the application level
+ #
+ # Bad examples:
+ # - Running database queries
+ # - Running CPU bound work loads
+ #
+ # As a guideline, aim to yield frequently if tasks execute logic in loops by
+ # making each iteration cheap. If life-cycle callbacks like start and stop
+ # aren't necessary and the task does not loop, consider just using Thread.new.
+ #
+ # rubocop: disable Gitlab/NamespacedClass
+ class BackgroundTask
+ AlreadyStartedError = Class.new(StandardError)
+
+ attr_reader :name
+
+ def running?
+ @state == :running
+ end
+
+ # Possible options:
+ # - name [String] used to identify the task in thread listings and logs (defaults to 'background_task')
+ # - synchronous [Boolean] if true, turns `start` into a blocking call
+ def initialize(task, **options)
+ @task = task
+ @synchronous = options[:synchronous]
+ @name = options[:name] || self.class.name.demodulize.underscore
+ # We use a monitor, not a Mutex, because monitors allow for re-entrant locking.
+ @mutex = ::Monitor.new
+ @state = :idle
+ end
+
+ def start
+ @mutex.synchronize do
+ raise AlreadyStartedError, "background task #{name} already running on #{@thread}" if running?
+
+ start_task = @task.respond_to?(:start) ? @task.start : true
+
+ if start_task
+ @state = :running
+
+ at_exit { stop }
+
+ @thread = Thread.new do
+ Thread.current.name = name
+ @task.call
+ end
+
+ @thread.join if @synchronous
+ end
+ end
+
+ self
+ end
+
+ def stop
+ @mutex.synchronize do
+ break unless running?
+
+ if @thread
+ # If thread is not in a stopped state, interrupt it because it may be sleeping.
+ # This is so we process a stop signal ASAP.
+ @thread.wakeup if @thread.alive?
+ begin
+ # Propagate stop event if supported.
+ @task.stop if @task.respond_to?(:stop)
+
+ # join will rethrow any error raised on the background thread
+ @thread.join unless Thread.current == @thread
+ rescue Exception => ex # rubocop:disable Lint/RescueException
+ Gitlab::ErrorTracking.track_exception(ex, extra: { reported_by: name })
+ end
+ @thread = nil
+ end
+
+ @state = :stopped
+ end
+ end
+ end
+ # rubocop: enable Gitlab/NamespacedClass
+end
diff --git a/lib/gitlab/batch_pop_queueing.rb b/lib/gitlab/batch_pop_queueing.rb
index 62fc8cd048e..103ce644f2b 100644
--- a/lib/gitlab/batch_pop_queueing.rb
+++ b/lib/gitlab/batch_pop_queueing.rb
@@ -73,7 +73,7 @@ module Gitlab
begin
all_args = pop_all
- yield all_args if block_given?
+ yield all_args if block
{ status: :finished, new_items: peek_all }
ensure
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index 3ad919fbba8..13b4cace08a 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -15,7 +15,7 @@ module Gitlab
attr_accessor :request_cache_key_block
def request_cache_key(&block)
- if block_given?
+ if block
self.request_cache_key_block = block
else
request_cache_key_block
diff --git a/lib/gitlab/chat_name_token.rb b/lib/gitlab/chat_name_token.rb
index 9b4cb9d0134..76f2a4ae38c 100644
--- a/lib/gitlab/chat_name_token.rb
+++ b/lib/gitlab/chat_name_token.rb
@@ -16,7 +16,9 @@ module Gitlab
def get
Gitlab::Redis::SharedState.with do |redis|
data = redis.get(redis_shared_state_key)
- Gitlab::Json.parse(data, symbolize_names: true) if data
+ params = Gitlab::Json.parse(data, symbolize_names: true) if data
+ params[:integration_id] ||= params.delete(:service_id) if params && params[:service_id]
+ params
end
end
diff --git a/lib/gitlab/ci/artifacts/logger.rb b/lib/gitlab/ci/artifacts/logger.rb
new file mode 100644
index 00000000000..628f4129df4
--- /dev/null
+++ b/lib/gitlab/ci/artifacts/logger.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Artifacts
+ module Logger
+ def log_artifacts_filesize(artifact_file)
+ return if artifact_file.nil?
+
+ unless artifact_file.is_a?(::Ci::Artifactable)
+ raise ArgumentError, "unknown artifact file class `#{artifact_file.class}`"
+ end
+
+ ::Gitlab::ApplicationContext.push(artifact: artifact_file)
+ end
+
+ def log_artifacts_context(job)
+ ::Gitlab::ApplicationContext.push(
+ namespace: job&.project&.namespace,
+ project: job&.project,
+ job: job
+ )
+ end
+
+ def log_build_dependencies(size:, count: 0)
+ ::Gitlab::ApplicationContext.push(
+ artifacts_dependencies_size: size,
+ artifacts_dependencies_count: count
+ )
+ end
+
+ def self.log_created(artifact)
+ payload = Gitlab::ApplicationContext.current.merge(
+ message: 'Artifact created',
+ job_artifact_id: artifact.id,
+ size: artifact.size,
+ type: artifact.file_type,
+ build_id: artifact.job_id,
+ project_id: artifact.project_id
+ )
+
+ Gitlab::AppLogger.info(payload)
+ end
+
+ def self.log_deleted(job_artifacts, method)
+ Array(job_artifacts).each do |artifact|
+ payload = Gitlab::ApplicationContext.current.merge(
+ message: 'Artifact deleted',
+ job_artifact_id: artifact.id,
+ expire_at: artifact.expire_at,
+ size: artifact.size,
+ type: artifact.file_type,
+ build_id: artifact.job_id,
+ project_id: artifact.project_id,
+ method: method
+ )
+
+ Gitlab::AppLogger.info(payload)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/artifacts/metrics.rb b/lib/gitlab/ci/artifacts/metrics.rb
index 03459c4bf36..59930426cd5 100644
--- a/lib/gitlab/ci/artifacts/metrics.rb
+++ b/lib/gitlab/ci/artifacts/metrics.rb
@@ -6,6 +6,13 @@ module Gitlab
class Metrics
include Gitlab::Utils::StrongMemoize
+ def self.build_completed_report_type_counter(report_type)
+ name = "artifact_report_#{report_type}_builds_completed_total".to_sym
+ comment = "Number of completed builds with #{report_type} report artifacts"
+
+ ::Gitlab::Metrics.counter(name, comment)
+ end
+
def increment_destroyed_artifacts_count(size)
destroyed_artifacts_counter.increment({}, size.to_i)
end
diff --git a/lib/gitlab/ci/build/artifacts/adapters/zip_stream.rb b/lib/gitlab/ci/build/artifacts/adapters/zip_stream.rb
new file mode 100644
index 00000000000..690a47097c6
--- /dev/null
+++ b/lib/gitlab/ci/build/artifacts/adapters/zip_stream.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Artifacts
+ module Adapters
+ class ZipStream
+ MAX_DECOMPRESSED_SIZE = 100.megabytes
+ MAX_FILES_PROCESSED = 50
+
+ attr_reader :stream
+
+ InvalidStreamError = Class.new(StandardError)
+
+ def initialize(stream)
+ raise InvalidStreamError, "Stream is required" unless stream
+
+ @stream = stream
+ @files_processed = 0
+ end
+
+ def each_blob
+ Zip::InputStream.open(stream) do |zio|
+ while entry = zio.get_next_entry
+ break if at_files_processed_limit?
+ next unless should_process?(entry)
+
+ @files_processed += 1
+
+ yield entry.get_input_stream.read
+ end
+ end
+ end
+
+ private
+
+ def should_process?(entry)
+ file?(entry) && !too_large?(entry)
+ end
+
+ def file?(entry)
+ # Check the file name as a workaround for incorrect
+ # file type detection when using InputStream
+ # https://github.com/rubyzip/rubyzip/issues/533
+ entry.file? && !entry.name.end_with?('/')
+ end
+
+ def too_large?(entry)
+ entry.size > MAX_DECOMPRESSED_SIZE
+ end
+
+ def at_files_processed_limit?
+ @files_processed >= MAX_FILES_PROCESSED
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/releaser.rb b/lib/gitlab/ci/build/releaser.rb
index 9720bb1123a..09717516aa4 100644
--- a/lib/gitlab/ci/build/releaser.rb
+++ b/lib/gitlab/ci/build/releaser.rb
@@ -5,7 +5,7 @@ module Gitlab
module Build
class Releaser
BASE_COMMAND = 'release-cli create'
- SINGLE_FLAGS = %i[name description tag_name ref released_at].freeze
+ SINGLE_FLAGS = %i[name description tag_name tag_message ref released_at].freeze
ARRAY_FLAGS = %i[milestones].freeze
attr_reader :config
diff --git a/lib/gitlab/ci/build/rules.rb b/lib/gitlab/ci/build/rules.rb
index 2d4f9cf635b..dee95534b07 100644
--- a/lib/gitlab/ci/build/rules.rb
+++ b/lib/gitlab/ci/build/rules.rb
@@ -6,7 +6,7 @@ module Gitlab
class Rules
include ::Gitlab::Utils::StrongMemoize
- Result = Struct.new(:when, :start_in, :allow_failure, :variables) do
+ Result = Struct.new(:when, :start_in, :allow_failure, :variables, :errors) do
def build_attributes
{
when: self.when,
@@ -38,6 +38,8 @@ module Gitlab
else
Result.new('never')
end
+ rescue Rule::Clause::ParseError => e
+ Result.new('never', nil, nil, nil, [e.message])
end
private
diff --git a/lib/gitlab/ci/build/rules/rule/clause.rb b/lib/gitlab/ci/build/rules/rule/clause.rb
index 6d4bbbb8c21..503f2a87361 100644
--- a/lib/gitlab/ci/build/rules/rule/clause.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause.rb
@@ -11,6 +11,7 @@ module Gitlab
# Used for job's inclusion rules configuration.
#
UnknownClauseError = Class.new(StandardError)
+ ParseError = Class.new(StandardError)
def self.fabricate(type, value)
"#{self}::#{type.to_s.camelize}".safe_constantize&.new(value)
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 1bcd87c9d93..1034f5eacef 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -11,10 +11,12 @@ module Gitlab
end
def satisfied_by?(pipeline, context)
- return true unless pipeline&.modified_paths
+ modified_paths = find_modified_paths(pipeline)
+
+ return true unless modified_paths
expanded_globs = expand_globs(context)
- pipeline.modified_paths.any? do |path|
+ modified_paths.any? do |path|
expanded_globs.any? do |glob|
File.fnmatch?(glob, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
end
@@ -33,13 +35,31 @@ module Gitlab
def paths
strong_memoize(:paths) do
- if @globs.is_a?(Array)
- @globs
- else
- Array(@globs[:paths])
- end
+ Array(@globs[:paths])
end
end
+
+ 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)
+
+ if compare_to_sha
+ pipeline.modified_paths_since(compare_to_sha)
+ else
+ pipeline.modified_paths
+ end
+ end
+
+ def find_compare_to_sha(pipeline)
+ return unless @globs.include?(:compare_to)
+
+ commit = pipeline.project.commit(@globs[:compare_to])
+ raise Rules::Rule::Clause::ParseError, 'rules:changes:compare_to is not a valid ref' unless commit
+
+ commit.sha
+ end
end
end
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 15a4ff91c1b..438fa1cb3b2 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -81,6 +81,10 @@ module Gitlab
root.jobs_value
end
+ def workflow_rules
+ root.workflow_entry.rules_value
+ end
+
def normalized_jobs
@normalized_jobs ||= Ci::Config::Normalizer.new(jobs).normalize_jobs
end
diff --git a/lib/gitlab/ci/config/entry/image.rb b/lib/gitlab/ci/config/entry/image.rb
index 96ac959a3f4..613f7ff3370 100644
--- a/lib/gitlab/ci/config/entry/image.rb
+++ b/lib/gitlab/ci/config/entry/image.rb
@@ -8,37 +8,13 @@ module Gitlab
# Entry that represents a Docker image.
#
class Image < ::Gitlab::Config::Entry::Node
- include ::Gitlab::Config::Entry::Validatable
- include ::Gitlab::Config::Entry::Attributable
- include ::Gitlab::Config::Entry::Configurable
-
- ALLOWED_KEYS = %i[name entrypoint ports pull_policy].freeze
- LEGACY_ALLOWED_KEYS = %i[name entrypoint ports].freeze
+ include ::Gitlab::Ci::Config::Entry::Imageable
validations do
- validates :config, hash_or_string: true
- validates :config, allowed_keys: ALLOWED_KEYS, if: :ci_docker_image_pull_policy_enabled?
- validates :config, allowed_keys: LEGACY_ALLOWED_KEYS, unless: :ci_docker_image_pull_policy_enabled?
- validates :config, disallowed_keys: %i[ports], unless: :with_image_ports?
-
- validates :name, type: String, presence: true
- validates :entrypoint, array_of_strings: true, allow_nil: true
- end
-
- entry :ports, Entry::Ports,
- description: 'Ports used to expose the image'
-
- entry :pull_policy, Entry::PullPolicy,
- description: 'Pull policy for the image'
-
- attributes :ports, :pull_policy
-
- def name
- value[:name]
- end
-
- def entrypoint
- value[:entrypoint]
+ validates :config, allowed_keys: IMAGEABLE_ALLOWED_KEYS,
+ if: :ci_docker_image_pull_policy_enabled?
+ validates :config, allowed_keys: IMAGEABLE_LEGACY_ALLOWED_KEYS,
+ unless: :ci_docker_image_pull_policy_enabled?
end
def value
@@ -55,18 +31,6 @@ module Gitlab
{}
end
end
-
- def with_image_ports?
- opt(:with_image_ports)
- end
-
- def ci_docker_image_pull_policy_enabled?
- ::Feature.enabled?(:ci_docker_image_pull_policy)
- end
-
- def skip_config_hash_validation?
- true
- end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/imageable.rb b/lib/gitlab/ci/config/entry/imageable.rb
new file mode 100644
index 00000000000..f045ee3d549
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/imageable.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Represents Imageable concern shared by Image and Service.
+ module Imageable
+ extend ActiveSupport::Concern
+
+ include ::Gitlab::Config::Entry::Attributable
+ include ::Gitlab::Config::Entry::Configurable
+
+ IMAGEABLE_ALLOWED_KEYS = %i[name entrypoint ports pull_policy].freeze
+ IMAGEABLE_LEGACY_ALLOWED_KEYS = %i[name entrypoint ports].freeze
+
+ included do
+ include ::Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, hash_or_string: true
+ validates :config, disallowed_keys: %i[ports], unless: :with_image_ports?
+
+ validates :name, type: String, presence: true
+ validates :entrypoint, array_of_strings: true, allow_nil: true
+ end
+
+ attributes :ports, :pull_policy
+
+ entry :ports, Entry::Ports,
+ description: 'Ports used to expose the image/service'
+
+ entry :pull_policy, Entry::PullPolicy,
+ description: 'Pull policy for the image/service'
+ end
+
+ def name
+ value[:name]
+ end
+
+ def entrypoint
+ value[:entrypoint]
+ end
+
+ def with_image_ports?
+ opt(:with_image_ports)
+ end
+
+ def ci_docker_image_pull_policy_enabled?
+ ::Feature.enabled?(:ci_docker_image_pull_policy)
+ end
+
+ def skip_config_hash_validation?
+ true
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 78794f524f4..975da8662e1 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -120,7 +120,7 @@ module Gitlab
stage: stage_value,
extends: extends,
rules: rules_value,
- job_variables: variables_value.to_h,
+ job_variables: variables_entry.value_with_data,
root_variables_inheritance: root_variables_inheritance,
only: only_value,
except: except_value,
diff --git a/lib/gitlab/ci/config/entry/release.rb b/lib/gitlab/ci/config/entry/release.rb
index 7e504c24ade..2be0eae120b 100644
--- a/lib/gitlab/ci/config/entry/release.rb
+++ b/lib/gitlab/ci/config/entry/release.rb
@@ -12,8 +12,8 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[tag_name name description ref released_at milestones assets].freeze
- attributes %i[tag_name name ref milestones assets].freeze
+ ALLOWED_KEYS = %i[tag_name tag_message name description ref released_at milestones assets].freeze
+ attributes %i[tag_name tag_message name ref milestones assets].freeze
attr_reader :released_at
# Attributable description conflicts with
@@ -31,6 +31,7 @@ module Gitlab
validations do
validates :config, allowed_keys: ALLOWED_KEYS
validates :tag_name, type: String, presence: true
+ validates :tag_message, type: String, allow_blank: true
validates :description, type: String, presence: true
validates :milestones, array_of_strings_or_string: true, allow_blank: true
validate do
diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb
index d5d204bb995..f77876cc926 100644
--- a/lib/gitlab/ci/config/entry/reports.rb
+++ b/lib/gitlab/ci/config/entry/reports.rb
@@ -17,7 +17,7 @@ module Gitlab
dast performance browser_performance load_performance license_scanning metrics lsif
dotenv terraform accessibility
requirements coverage_fuzzing api_fuzzing cluster_image_scanning
- coverage_report].freeze
+ coverage_report cyclonedx].freeze
attributes ALLOWED_KEYS
@@ -48,6 +48,7 @@ module Gitlab
validates :terraform, array_of_strings_or_string: true
validates :accessibility, array_of_strings_or_string: true
validates :requirements, array_of_strings_or_string: true
+ validates :cyclonedx, array_of_strings_or_string: true
end
end
diff --git a/lib/gitlab/ci/config/entry/rules/rule/changes.rb b/lib/gitlab/ci/config/entry/rules/rule/changes.rb
index a56b928450a..107e7c228af 100644
--- a/lib/gitlab/ci/config/entry/rules/rule/changes.rb
+++ b/lib/gitlab/ci/config/entry/rules/rule/changes.rb
@@ -30,7 +30,7 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[paths].freeze
+ ALLOWED_KEYS = %i[paths compare_to].freeze
REQUIRED_KEYS = %i[paths].freeze
attributes ALLOWED_KEYS
@@ -43,6 +43,7 @@ module Gitlab
validates :paths,
array_of_strings: true,
length: { maximum: 50, too_long: "has too many entries (maximum %{count})" }
+ validates :compare_to, type: String, allow_nil: true
end
end
end
diff --git a/lib/gitlab/ci/config/entry/service.rb b/lib/gitlab/ci/config/entry/service.rb
index 1a35f7de6cf..0e19447dff8 100644
--- a/lib/gitlab/ci/config/entry/service.rb
+++ b/lib/gitlab/ci/config/entry/service.rb
@@ -7,41 +7,28 @@ module Gitlab
##
# Entry that represents a configuration of Docker service.
#
- # TODO: remove duplication with Image superclass by defining a common
- # Imageable concern.
- # https://gitlab.com/gitlab-org/gitlab/issues/208774
class Service < ::Gitlab::Config::Entry::Node
- include ::Gitlab::Config::Entry::Validatable
- include ::Gitlab::Config::Entry::Attributable
- include ::Gitlab::Config::Entry::Configurable
+ include ::Gitlab::Ci::Config::Entry::Imageable
- ALLOWED_KEYS = %i[name entrypoint command alias ports variables pull_policy].freeze
- LEGACY_ALLOWED_KEYS = %i[name entrypoint command alias ports variables].freeze
+ ALLOWED_KEYS = %i[command alias variables].freeze
+ LEGACY_ALLOWED_KEYS = %i[command alias variables].freeze
validations do
- validates :config, hash_or_string: true
- validates :config, allowed_keys: ALLOWED_KEYS, if: :ci_docker_image_pull_policy_enabled?
- validates :config, allowed_keys: LEGACY_ALLOWED_KEYS, unless: :ci_docker_image_pull_policy_enabled?
- validates :config, disallowed_keys: %i[ports], unless: :with_image_ports?
- validates :name, type: String, presence: true
- validates :entrypoint, array_of_strings: true, allow_nil: true
+ validates :config, allowed_keys: ALLOWED_KEYS + IMAGEABLE_ALLOWED_KEYS,
+ if: :ci_docker_image_pull_policy_enabled?
+ validates :config, allowed_keys: LEGACY_ALLOWED_KEYS + IMAGEABLE_LEGACY_ALLOWED_KEYS,
+ unless: :ci_docker_image_pull_policy_enabled?
validates :command, array_of_strings: true, allow_nil: true
validates :alias, type: String, allow_nil: true
validates :alias, type: String, presence: true, unless: ->(record) { record.ports.blank? }
end
- entry :ports, Entry::Ports,
- description: 'Ports used to expose the service'
-
- entry :pull_policy, Entry::PullPolicy,
- description: 'Pull policy for the service'
-
entry :variables, ::Gitlab::Ci::Config::Entry::Variables,
description: 'Environment variables available for this service.',
inherit: false
- attributes :ports, :pull_policy, :variables
+ attributes :variables
def alias
value[:alias]
@@ -51,14 +38,6 @@ module Gitlab
value[:command]
end
- def name
- value[:name]
- end
-
- def entrypoint
- value[:entrypoint]
- end
-
def value
if string?
{ name: @config }
@@ -70,18 +49,6 @@ module Gitlab
{}
end
end
-
- def with_image_ports?
- opt(:with_image_ports)
- end
-
- def ci_docker_image_pull_policy_enabled?
- ::Feature.enabled?(:ci_docker_image_pull_policy)
- end
-
- def skip_config_hash_validation?
- true
- end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index efb469ee32a..3130aec0446 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -18,7 +18,9 @@ module Gitlab
end
def value
- @config.to_h { |key, value| [key.to_s, expand_value(value)[:value]] }
+ @config.to_h do |key, data|
+ [key.to_s, expand_data(data)[:value]]
+ end
end
def self.default(**)
@@ -26,7 +28,9 @@ module Gitlab
end
def value_with_data
- @config.to_h { |key, value| [key.to_s, expand_value(value)] }
+ @config.to_h do |key, data|
+ [key.to_s, expand_data(data)]
+ end
end
def use_value_data?
@@ -35,11 +39,11 @@ module Gitlab
private
- def expand_value(value)
- if value.is_a?(Hash)
- { value: value[:value].to_s, description: value[:description] }
+ def expand_data(data)
+ if data.is_a?(Hash)
+ { value: data[:value].to_s, description: data[:description] }.compact
else
- { value: value.to_s, description: nil }
+ { value: data.to_s }
end
end
end
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index c294291e538..d3e7210b820 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -65,7 +65,7 @@ module Gitlab
fields.merge!(
environment: environment.name,
environment_protected: environment_protected?.to_s,
- deployment_tier: build.environment_deployment_tier || environment.tier
+ deployment_tier: build.environment_tier
)
end
diff --git a/lib/gitlab/ci/parsers.rb b/lib/gitlab/ci/parsers.rb
index 1223d664214..b52e2d8f613 100644
--- a/lib/gitlab/ci/parsers.rb
+++ b/lib/gitlab/ci/parsers.rb
@@ -13,7 +13,8 @@ module Gitlab
accessibility: ::Gitlab::Ci::Parsers::Accessibility::Pa11y,
codequality: ::Gitlab::Ci::Parsers::Codequality::CodeClimate,
sast: ::Gitlab::Ci::Parsers::Security::Sast,
- secret_detection: ::Gitlab::Ci::Parsers::Security::SecretDetection
+ secret_detection: ::Gitlab::Ci::Parsers::Security::SecretDetection,
+ cyclonedx: ::Gitlab::Ci::Parsers::Sbom::Cyclonedx
}
end
diff --git a/lib/gitlab/ci/parsers/sbom/cyclonedx.rb b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
new file mode 100644
index 00000000000..deb20a2138c
--- /dev/null
+++ b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Sbom
+ class Cyclonedx
+ SUPPORTED_SPEC_VERSIONS = %w[1.4].freeze
+ COMPONENT_ATTRIBUTES = %w[type name version].freeze
+
+ def parse!(blob, sbom_report)
+ @report = sbom_report
+ @data = Gitlab::Json.parse(blob)
+
+ return unless valid?
+
+ parse_report
+ rescue JSON::ParserError => e
+ report.add_error("Report JSON is invalid: #{e}")
+ end
+
+ private
+
+ attr_reader :json_data, :report, :data
+
+ def schema_validator
+ @schema_validator ||= Validators::CyclonedxSchemaValidator.new(data)
+ end
+
+ def valid?
+ valid_schema? && supported_spec_version?
+ end
+
+ def supported_spec_version?
+ return true if SUPPORTED_SPEC_VERSIONS.include?(data['specVersion'])
+
+ report.add_error(
+ "Unsupported CycloneDX spec version. Must be one of: %{versions}" \
+ % { versions: SUPPORTED_SPEC_VERSIONS.join(', ') }
+ )
+
+ false
+ end
+
+ def valid_schema?
+ return true if schema_validator.valid?
+
+ schema_validator.errors.each { |error| report.add_error(error) }
+
+ false
+ end
+
+ def parse_report
+ parse_metadata_properties
+ parse_components
+ end
+
+ def parse_metadata_properties
+ properties = data.dig('metadata', 'properties')
+ source = CyclonedxProperties.parse_source(properties)
+ report.set_source(source) if source
+ end
+
+ def parse_components
+ data['components']&.each do |component|
+ next unless supported_component_type?(component['type'])
+
+ report.add_component(component.slice(*COMPONENT_ATTRIBUTES))
+ end
+ end
+
+ def supported_component_type?(type)
+ ::Enums::Sbom.component_types.include?(type.to_sym)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/parsers/sbom/cyclonedx_properties.rb b/lib/gitlab/ci/parsers/sbom/cyclonedx_properties.rb
new file mode 100644
index 00000000000..3dc73544208
--- /dev/null
+++ b/lib/gitlab/ci/parsers/sbom/cyclonedx_properties.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Sbom
+ # Parses GitLab CycloneDX metadata properties which are defined by the taxonomy at
+ # https://gitlab.com/gitlab-org/security-products/gitlab-cyclonedx-property-taxonomy
+ #
+ # This parser knows how to process schema version 1 and will not attempt to parse
+ # later versions. Each source type has it's own namespace in the property schema,
+ # and is also given its own parser. Properties are filtered by namespace,
+ # and then passed to each source parser for processing.
+ class CyclonedxProperties
+ SUPPORTED_SCHEMA_VERSION = '1'
+ GITLAB_PREFIX = 'gitlab:'
+ SOURCE_PARSERS = {
+ 'dependency_scanning' => ::Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning
+ }.freeze
+ SUPPORTED_PROPERTIES = %w[
+ meta:schema_version
+ dependency_scanning:category
+ dependency_scanning:input_file:path
+ dependency_scanning:source_file:path
+ dependency_scanning:package_manager:name
+ dependency_scanning:language:name
+ ].freeze
+
+ def self.parse_source(...)
+ new(...).parse_source
+ end
+
+ def initialize(properties)
+ @properties = properties
+ end
+
+ def parse_source
+ return unless properties.present?
+ return unless supported_schema_version?
+
+ source
+ end
+
+ private
+
+ attr_reader :properties
+
+ def property_data
+ @property_data ||= properties
+ .each_with_object({}) { |property, data| parse_property(property, data) }
+ end
+
+ def parse_property(property, data)
+ name = property['name']
+ value = property['value']
+
+ # The specification permits the name or value to be absent.
+ return unless name.present? && value.present?
+ return unless name.start_with?(GITLAB_PREFIX)
+
+ namespaced_name = name.delete_prefix(GITLAB_PREFIX)
+
+ return unless SUPPORTED_PROPERTIES.include?(namespaced_name)
+
+ parse_name_value_pair(namespaced_name, value, data)
+ end
+
+ def parse_name_value_pair(name, value, data)
+ # Each namespace in the property name reflects a key in the hash.
+ # A property with the name `dependency_scanning:input_file:path`
+ # and the value `package-lock.json` should be transformed into
+ # this data:
+ # {"dependency_scanning": {"input_file": {"path": "package-lock.json"}}}
+ keys = name.split(':')
+
+ # Remove last item from the keys and use it to create
+ # the initial object.
+ last = keys.pop
+
+ # Work backwards. For each key, create a new hash wrapping the previous one.
+ # Using `dependency_scanning:input_file:path` as an example:
+ #
+ # 1. memo = { "path" => "package-lock.json" } (arguments given to reduce)
+ # 2. memo = { "input_file" => memo }
+ # 3. memo = { "dependency_scanning" => memo }
+ property = keys.reverse.reduce({ last => value }) do |memo, key|
+ { key => memo }
+ end
+
+ data.deep_merge!(property)
+ end
+
+ def schema_version
+ @schema_version ||= property_data.dig('meta', 'schema_version')
+ end
+
+ def supported_schema_version?
+ schema_version == SUPPORTED_SCHEMA_VERSION
+ end
+
+ def source
+ @source ||= property_data
+ .slice(*SOURCE_PARSERS.keys)
+ .lazy
+ .filter_map { |namespace, data| SOURCE_PARSERS[namespace].source(data) }
+ .first
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb b/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb
new file mode 100644
index 00000000000..ad04b3257f9
--- /dev/null
+++ b/lib/gitlab/ci/parsers/sbom/source/dependency_scanning.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Sbom
+ module Source
+ class DependencyScanning
+ REQUIRED_ATTRIBUTES = [
+ %w[input_file path]
+ ].freeze
+
+ def self.source(...)
+ new(...).source
+ end
+
+ def initialize(data)
+ @data = data
+ end
+
+ def source
+ return unless required_attributes_present?
+
+ {
+ 'type' => :dependency_scanning,
+ 'data' => data,
+ 'fingerprint' => fingerprint
+ }
+ end
+
+ private
+
+ attr_reader :data
+
+ def required_attributes_present?
+ REQUIRED_ATTRIBUTES.all? do |keys|
+ data.dig(*keys).present?
+ end
+ end
+
+ def fingerprint
+ Digest::SHA256.hexdigest(data.to_json)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator.rb b/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator.rb
new file mode 100644
index 00000000000..9d56e001c2f
--- /dev/null
+++ b/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Sbom
+ module Validators
+ class CyclonedxSchemaValidator
+ SCHEMA_PATH = Rails.root.join('app', 'validators', 'json_schemas', 'cyclonedx_report.json').freeze
+
+ def initialize(report_data)
+ @report_data = report_data
+ end
+
+ def valid?
+ errors.empty?
+ end
+
+ def errors
+ @errors ||= pretty_errors
+ end
+
+ private
+
+ def raw_errors
+ JSONSchemer.schema(SCHEMA_PATH).validate(@report_data)
+ end
+
+ def pretty_errors
+ raw_errors.map { |error| JSONSchemer::Errors.pretty(error) }
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
index ee7733a081d..c075ada725a 100644
--- a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
+++ b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
@@ -38,13 +38,14 @@ module Gitlab
def initialize(report_type, report_version)
@report_type = report_type.to_sym
@report_version = report_version.to_s
+ @supported_versions = SUPPORTED_VERSIONS[@report_type]
end
delegate :validate, to: :schemer
private
- attr_reader :report_type, :report_version
+ attr_reader :report_type, :report_version, :supported_versions
def schemer
JSONSchemer.schema(pathname)
@@ -60,10 +61,24 @@ module Gitlab
report_declared_version = File.join(root_path, report_version, file_name)
return report_declared_version if File.file?(report_declared_version)
+ if latest_vendored_patch_version
+ latest_vendored_patch_version_file = File.join(root_path, latest_vendored_patch_version, file_name)
+ return latest_vendored_patch_version_file if File.file?(latest_vendored_patch_version)
+ end
+
earliest_supported_version = SUPPORTED_VERSIONS[report_type].min
File.join(root_path, earliest_supported_version, file_name)
end
+ def latest_vendored_patch_version
+ ::Security::ReportSchemaVersionMatcher.new(
+ report_declared_version: report_version,
+ supported_versions: supported_versions
+ ).call
+ rescue ArgumentError
+ nil
+ end
+
def file_name
report_type == :api_fuzzing ? "dast-report-format.json" : "#{report_type.to_s.dasherize}-report-format.json"
end
@@ -79,29 +94,85 @@ module Gitlab
@warnings = []
@deprecation_warnings = []
- populate_errors
- populate_warnings
+ populate_schema_version_errors
+ populate_validation_errors
populate_deprecation_warnings
end
- def valid?
- errors.empty?
+ def populate_schema_version_errors
+ add_schema_version_errors if add_schema_version_error?
end
- def populate_errors
- schema_validation_errors = schema.validate(report_data).map { |error| JSONSchemer::Errors.pretty(error) }
+ def add_schema_version_errors
+ if report_version.nil?
+ template = _("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")
+ message = format(template, report_type: report_type, supported_schema_versions: supported_schema_versions)
+ else
+ template = _("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")
+ message = format(template, report_version: report_version, report_type: report_type, supported_schema_versions: supported_schema_versions)
+ end
- log_warnings(problem_type: 'schema_validation_fails') unless schema_validation_errors.empty?
+ log_warnings(problem_type: 'using_unsupported_schema_version')
+ add_message_as(level: :error, message: message)
+ end
+
+ def add_schema_version_error?
+ !report_uses_supported_schema_version? &&
+ !report_uses_deprecated_schema_version? &&
+ !report_uses_supported_major_and_minor_schema_version?
+ end
+
+ def report_uses_deprecated_schema_version?
+ DEPRECATED_VERSIONS[report_type].include?(report_version)
+ end
+
+ def report_uses_supported_schema_version?
+ SUPPORTED_VERSIONS[report_type].include?(report_version)
+ end
- if Feature.enabled?(:enforce_security_report_validation, @project)
- @errors += schema_validation_errors
+ def report_uses_supported_major_and_minor_schema_version?
+ if !find_latest_patch_version.nil?
+ add_supported_major_minor_behavior_warning
+ true
else
- @warnings += schema_validation_errors
+ false
end
end
- def populate_warnings
- add_unsupported_report_version_message if !report_uses_supported_schema_version? && !report_uses_deprecated_schema_version?
+ def find_latest_patch_version
+ ::Security::ReportSchemaVersionMatcher.new(
+ report_declared_version: report_version,
+ supported_versions: SUPPORTED_VERSIONS[report_type]
+ ).call
+ rescue ArgumentError
+ nil
+ end
+
+ def add_supported_major_minor_behavior_warning
+ template = _("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}")
+
+ message = format(template, find_latest_patch_version: find_latest_patch_version)
+
+ add_message_as(
+ level: :warning,
+ message: message
+ )
+ end
+
+ def populate_validation_errors
+ schema_validation_errors = schema.validate(report_data).map { |error| JSONSchemer::Errors.pretty(error) }
+
+ log_warnings(problem_type: 'schema_validation_fails') unless schema_validation_errors.empty?
+
+ @errors += schema_validation_errors
end
def populate_deprecation_warnings
@@ -111,10 +182,19 @@ module Gitlab
def add_deprecated_report_version_message
log_warnings(problem_type: 'using_deprecated_schema_version')
- message = "Version #{report_version} for report type #{report_type} has been deprecated, supported versions for this report type are: #{supported_schema_versions}"
+ template = _("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.")
+
+ message = format(template, report_version: report_version, report_type: report_type, supported_schema_versions: supported_schema_versions)
+
add_message_as(level: :deprecation_warning, message: message)
end
+ def valid?
+ errors.empty?
+ end
+
def log_warnings(problem_type:)
Gitlab::AppLogger.info(
message: 'security report schema validation problem',
@@ -127,34 +207,6 @@ module Gitlab
)
end
- def add_unsupported_report_version_message
- log_warnings(problem_type: 'using_unsupported_schema_version')
-
- if Feature.enabled?(:enforce_security_report_validation, @project)
- handle_unsupported_report_version(treat_as: :error)
- else
- handle_unsupported_report_version(treat_as: :warning)
- end
- end
-
- def report_uses_deprecated_schema_version?
- DEPRECATED_VERSIONS[report_type].include?(report_version)
- end
-
- def report_uses_supported_schema_version?
- SUPPORTED_VERSIONS[report_type].include?(report_version)
- end
-
- def handle_unsupported_report_version(treat_as:)
- if report_version.nil?
- message = "Report version not provided, #{report_type} report type supports versions: #{supported_schema_versions}"
- else
- message = "Version #{report_version} for report type #{report_type} is unsupported, supported versions for this report type are: #{supported_schema_versions}"
- end
-
- add_message_as(level: treat_as, message: message)
- end
-
def supported_schema_versions
SUPPORTED_VERSIONS[report_type].join(", ")
end
diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
index f637001f9f8..9c12d46cede 100644
--- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
+++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb
@@ -40,7 +40,13 @@ module Gitlab
::Ci::Pipeline
.id_in(pipeline_ids)
.with_only_interruptible_builds
- .each { |cancelable| cancelable.auto_cancel_running(pipeline) }
+ .each do |cancelable_pipeline|
+ # cascade_to_children not needed because we iterate through descendants here
+ cancelable_pipeline.cancel_running(
+ auto_canceled_by_pipeline_id: pipeline.id,
+ cascade_to_children: false
+ )
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index 8177502be1d..6e95c7988fc 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -101,7 +101,8 @@ module Gitlab
ref: pipeline.ref,
type: pipeline.source
},
- builds: builds_validation_payload
+ builds: builds_validation_payload,
+ total_builds_count: current_user.pipelines.jobs_count_in_alive_pipelines
}
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
index 6efb3a4f16a..c4f06c4686d 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
@@ -14,11 +14,9 @@ module Gitlab
return false unless regexp
- if ::Feature.enabled?(:ci_fix_rules_if_comparison_with_regexp_variable)
- # All variables are evaluated as strings, even if they are regexp strings.
- # So, we need to convert them to regexp objects.
- regexp = Lexeme::Pattern.build_and_evaluate(regexp, variables)
- end
+ # All variables are evaluated as strings, even if they are regexp strings.
+ # So, we need to convert them to regexp objects.
+ regexp = Lexeme::Pattern.build_and_evaluate(regexp, variables)
regexp.scan(text.to_s).present?
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb
index a72e5dbc822..99d9206da74 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb
@@ -14,11 +14,9 @@ module Gitlab
return true unless regexp
- if ::Feature.enabled?(:ci_fix_rules_if_comparison_with_regexp_variable)
- # All variables are evaluated as strings, even if they are regexp strings.
- # So, we need to convert them to regexp objects.
- regexp = Lexeme::Pattern.build_and_evaluate(regexp, variables)
- end
+ # All variables are evaluated as strings, even if they are regexp strings.
+ # So, we need to convert them to regexp objects.
+ regexp = Lexeme::Pattern.build_and_evaluate(regexp, variables)
regexp.scan(text.to_s).empty?
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 901208f325a..93106b96af2 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -54,9 +54,11 @@ module Gitlab
end
def errors
- return unless included?
-
strong_memoize(:errors) do
+ # We check rules errors before checking "included?" because rules affects its inclusion status.
+ next rules_errors if rules_errors
+ next unless included?
+
[needs_errors, variable_expansion_errors].compact.flatten
end
end
@@ -168,6 +170,12 @@ module Gitlab
end
end
+ def rules_errors
+ strong_memoize(:rules_errors) do
+ ["Failed to parse rule for #{name}: #{rules_result.errors.join(', ')}"] if rules_result.errors.present?
+ end
+ end
+
def evaluate_context
strong_memoize(:evaluate_context) do
Gitlab::Ci::Build::Context::Build.new(@pipeline, @seed_attributes)
diff --git a/lib/gitlab/ci/pipeline/seed/environment.rb b/lib/gitlab/ci/pipeline/seed/environment.rb
index c8795840e5f..6bcc71a808b 100644
--- a/lib/gitlab/ci/pipeline/seed/environment.rb
+++ b/lib/gitlab/ci/pipeline/seed/environment.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def deployment_tier
- job.environment_deployment_tier
+ job.environment_tier_from_options
end
def expanded_environment_name
diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb
index bc56fe9bef9..7cf6466cf4b 100644
--- a/lib/gitlab/ci/pipeline/seed/stage.rb
+++ b/lib/gitlab/ci/pipeline/seed/stage.rb
@@ -36,7 +36,7 @@ module Gitlab
def errors
strong_memoize(:errors) do
- seeds.flat_map(&:errors).compact
+ @builds.flat_map(&:errors).compact
end
end
diff --git a/lib/gitlab/ci/reports/coverage_report_generator.rb b/lib/gitlab/ci/reports/coverage_report_generator.rb
index 76992a48b0a..6d57e05aa63 100644
--- a/lib/gitlab/ci/reports/coverage_report_generator.rb
+++ b/lib/gitlab/ci/reports/coverage_report_generator.rb
@@ -20,7 +20,7 @@ module Gitlab
coverage_report.tap do |coverage_report|
report_builds.find_each do |build|
- build.each_report(::Ci::JobArtifact::COVERAGE_REPORT_FILE_TYPES) do |file_type, blob|
+ build.each_report(::Ci::JobArtifact.file_types_for_report(:coverage)) do |file_type, blob|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
blob,
coverage_report,
diff --git a/lib/gitlab/ci/reports/sbom/component.rb b/lib/gitlab/ci/reports/sbom/component.rb
new file mode 100644
index 00000000000..86b9be274cc
--- /dev/null
+++ b/lib/gitlab/ci/reports/sbom/component.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ module Sbom
+ class Component
+ attr_reader :component_type, :name, :version
+
+ def initialize(component = {})
+ @component_type = component['type']
+ @name = component['name']
+ @version = component['version']
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/sbom/report.rb b/lib/gitlab/ci/reports/sbom/report.rb
new file mode 100644
index 00000000000..dc6b3153e51
--- /dev/null
+++ b/lib/gitlab/ci/reports/sbom/report.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ module Sbom
+ class Report
+ attr_reader :components, :source, :errors
+
+ def initialize
+ @components = []
+ @errors = []
+ end
+
+ def add_error(error)
+ errors << error
+ end
+
+ def set_source(source)
+ self.source = Source.new(source)
+ end
+
+ def add_component(component)
+ components << Component.new(component)
+ end
+
+ private
+
+ attr_writer :source
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/sbom/reports.rb b/lib/gitlab/ci/reports/sbom/reports.rb
new file mode 100644
index 00000000000..efb772cb818
--- /dev/null
+++ b/lib/gitlab/ci/reports/sbom/reports.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ module Sbom
+ class Reports
+ attr_reader :reports
+
+ def initialize
+ @reports = []
+ end
+
+ def add_report(report)
+ @reports << report
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/sbom/source.rb b/lib/gitlab/ci/reports/sbom/source.rb
new file mode 100644
index 00000000000..60bf30b65a5
--- /dev/null
+++ b/lib/gitlab/ci/reports/sbom/source.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ module Sbom
+ class Source
+ attr_reader :source_type, :data, :fingerprint
+
+ def initialize(source = {})
+ @source_type = source['type']
+ @data = source['data']
+ @fingerprint = source['fingerprint']
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/runner_releases.rb b/lib/gitlab/ci/runner_releases.rb
index 8773ecbf09e..dab24bfd501 100644
--- a/lib/gitlab/ci/runner_releases.rb
+++ b/lib/gitlab/ci/runner_releases.rb
@@ -36,6 +36,9 @@ module Gitlab
reset_backoff!
extract_releases(response)
+ rescue Errno::ETIMEDOUT
+ @backoff_expire_time = next_backoff.from_now
+ break nil
end
end
@@ -74,7 +77,7 @@ module Gitlab
releases = response.parsed_response
.map { |release| parse_runner_release(release) }
.select(&:valid?)
- .sort!
+ .sort
return if releases.empty? && response.parsed_response.present?
diff --git a/lib/gitlab/ci/runner_upgrade_check.rb b/lib/gitlab/ci/runner_upgrade_check.rb
index 10a89bb15d4..03130addd6a 100644
--- a/lib/gitlab/ci/runner_upgrade_check.rb
+++ b/lib/gitlab/ci/runner_upgrade_check.rb
@@ -3,57 +3,70 @@
module Gitlab
module Ci
class RunnerUpgradeCheck
- include Singleton
+ def initialize(gitlab_version, runner_releases_store = nil)
+ @gitlab_version = ::Gitlab::VersionInfo.parse(gitlab_version, parse_suffix: true)
+ @releases_store = runner_releases_store
+ end
+
+ def check_runner_upgrade_suggestion(runner_version)
+ check_runner_upgrade_suggestions(runner_version).first
+ end
- def check_runner_upgrade_status(runner_version)
+ private
+
+ def runner_releases_store
+ @releases_store ||= RunnerReleases.instance
+ end
+
+ def add_suggestion(suggestions, runner_version, version, status)
+ return false unless version && version > runner_version
+
+ suggestions[version] = status
+ true
+ end
+
+ def check_runner_upgrade_suggestions(runner_version)
runner_version = ::Gitlab::VersionInfo.parse(runner_version, parse_suffix: true)
- return { invalid_version: runner_version } unless runner_version.valid?
- return { error: runner_version } unless runner_releases_store.releases
+ return { runner_version => :invalid_version } unless runner_version.valid?
+ return { runner_version => :error } unless runner_releases_store.releases
- # Recommend update if outside of backport window
- recommended_version = recommendation_if_outside_backport_window(runner_version)
- return { recommended: recommended_version } if recommended_version
+ suggestions = {}
- # Recommend patch update if there's a newer release in a same minor branch as runner
- recommended_version = recommended_runner_release_update(runner_version)
- return { recommended: recommended_version } if recommended_version
+ # Recommend update if outside of backport window
+ unless add_recommendation_if_outside_backport_window(runner_version, suggestions)
+ # Recommend patch update if there's a newer release in a same minor branch as runner
+ add_recommended_runner_release_update(runner_version, suggestions)
+ end
# Consider update if there's a newer release within the currently deployed GitLab version
- available_version = available_runner_release(runner_version)
- return { available: available_version } if available_version
+ add_available_runner_release(runner_version, suggestions)
- { not_available: runner_version }
- end
+ suggestions[runner_version] = :not_available if suggestions.empty?
- private
+ suggestions
+ end
- def recommended_runner_release_update(runner_version)
+ def add_recommended_runner_release_update(runner_version, suggestions)
recommended_release = runner_releases_store.releases_by_minor[runner_version.without_patch]
- return recommended_release if recommended_release && recommended_release > runner_version
+ return true if add_suggestion(suggestions, runner_version, recommended_release, :recommended)
# Consider the edge case of pre-release runner versions that get registered, but are never published.
# In this case, suggest the latest compatible runner version
- latest_release = runner_releases_store.releases_by_minor.values.select { |v| v < gitlab_version }.max
- latest_release if latest_release && latest_release > runner_version
- end
-
- def available_runner_release(runner_version)
- available_release = runner_releases_store.releases_by_minor[gitlab_version.without_patch]
- available_release if available_release && available_release > runner_version
+ latest_release = runner_releases_store.releases_by_minor.values.select { |v| v < @gitlab_version }.max
+ add_suggestion(suggestions, runner_version, latest_release, :recommended)
end
- def gitlab_version
- @gitlab_version ||= ::Gitlab::VersionInfo.parse(::Gitlab::VERSION, parse_suffix: true)
- end
-
- def runner_releases_store
- RunnerReleases.instance
+ def add_available_runner_release(runner_version, suggestions)
+ available_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
+ unless suggestions.include?(available_version)
+ add_suggestion(suggestions, runner_version, available_version, :available)
+ end
end
- def recommendation_if_outside_backport_window(runner_version)
- return if runner_releases_store.releases.empty?
- return if runner_version >= runner_releases_store.releases.last # return early if runner version is too new
+ def add_recommendation_if_outside_backport_window(runner_version, suggestions)
+ return false if runner_releases_store.releases.empty?
+ return false if runner_version >= runner_releases_store.releases.last # return early if runner version is too new
minor_releases_with_index = runner_releases_store.releases_by_minor.keys.each_with_index.to_h
runner_minor_version_index = minor_releases_with_index[runner_version.without_patch]
@@ -62,14 +75,15 @@ module Gitlab
outside_window = minor_releases_with_index.count - runner_minor_version_index > 3
if outside_window
- recommended_release = runner_releases_store.releases_by_minor[gitlab_version.without_patch]
-
- recommended_release if recommended_release && recommended_release > runner_version
+ recommended_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
+ return add_suggestion(suggestions, runner_version, recommended_version, :recommended)
end
else
# If unknown runner version, then recommend the latest version for the GitLab instance
- recommended_runner_release_update(gitlab_version)
+ return add_recommended_runner_release_update(@gitlab_version, suggestions)
end
+
+ false
end
end
end
diff --git a/lib/gitlab/ci/status/bridge/common.rb b/lib/gitlab/ci/status/bridge/common.rb
index 263fd9d1052..d66d4b20bba 100644
--- a/lib/gitlab/ci/status/bridge/common.rb
+++ b/lib/gitlab/ci/status/bridge/common.rb
@@ -16,11 +16,7 @@ module Gitlab
def details_path
return unless can?(user, :read_pipeline, downstream_pipeline)
- if Feature.enabled?(:ci_retry_downstream_pipeline, subject.project)
- project_job_path(subject.project, subject)
- else
- project_pipeline_path(downstream_project, downstream_pipeline)
- end
+ project_pipeline_path(downstream_project, downstream_pipeline)
end
def has_action?
diff --git a/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml b/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml
index 71f38ededd9..bb88bee9137 100644
--- a/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/5-Minute-Production-App.gitlab-ci.yml
@@ -39,7 +39,7 @@ cache:
terraform_apply:
stage: provision
- image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ image: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/5-minute-production-app/deploy-template/stable"
extends: .needs_aws_vars
resource_group: terraform
before_script:
@@ -53,7 +53,7 @@ terraform_apply:
deploy:
stage: deploy
- image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ image: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/5-minute-production-app/deploy-template/stable"
extends: .needs_aws_vars
resource_group: deploy
before_script:
@@ -74,7 +74,7 @@ terraform_destroy:
variables:
GIT_STRATEGY: none
stage: destroy
- image: registry.gitlab.com/gitlab-org/5-minute-production-app/deploy-template/stable
+ image: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/5-minute-production-app/deploy-template/stable"
before_script:
- cp /*.tf .
- cp /deploy.sh .
diff --git a/lib/gitlab/ci/templates/Dart.gitlab-ci.yml b/lib/gitlab/ci/templates/Dart.gitlab-ci.yml
index 35401e62fe2..4e011bb325d 100644
--- a/lib/gitlab/ci/templates/Dart.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Dart.gitlab-ci.yml
@@ -6,25 +6,86 @@
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Dart.gitlab-ci.yml
-# https://hub.docker.com/r/google/dart
-image: google/dart:2.8.4
+# https://hub.docker.com/_/dart
+image: dart:2.17
variables:
- # Use to learn more:
- # pub run test --help
+ # To learn more go to https://dart.dev/tools/dart-test
+ # Or run `dart test --help`
PUB_VARS: "--platform vm --timeout 30s --concurrency=6 --test-randomize-ordering-seed=random --reporter=expanded"
+.use-pub-cache-bin:
+ # Define commands that need to be executed before each job.
+ before_script:
+ # Set PUB_CACHE either here or in the CI/CD Settings if you have multiple jobs that use dart commands.
+ # PUB_CACHE is used by the `dart pub` command, it needs to be set so package dependencies are stored at the project-level for CI/CD operations.
+ - export PUB_CACHE=".pub-cache"
+ - export PATH="$PATH:$HOME/$PUB_CACHE/bin"
+
+# Cache generated files and plugins between builds.
+.upload-cache:
+ cache:
+ when: 'on_success'
+ paths:
+ - .pub-cache/bin/
+ - .pub-cache/global_packages/
+ - .pub-cache/hosted/
+ - .dart_tool/
+ - .packages
+
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
-cache:
- paths:
- - .pub-cache/global_packages
+.download-cache:
+ cache:
+ paths:
+ - .dart_tool/
+ - .packages
+ policy: pull
+
+install-dependencies:
+ stage: .pre
+ extends:
+ - .use-pub-cache-bin
+ - .upload-cache
+ script:
+ - dart pub get --no-precompile
+
+build:
+ stage: build
+ needs:
+ - install-dependencies
+ extends:
+ - .use-pub-cache-bin
+ - .upload-cache
+ script:
+ - dart pub get --offline --precompile
-before_script:
- - export PATH="$PATH:$HOME/.pub-cache/bin"
- - pub get --no-precompile
+unit-test:
+ stage: test
+ needs:
+ - build
+ extends:
+ - .use-pub-cache-bin
+ - .download-cache
+ script:
+ - dart test $PUB_VARS
+
+lint-test:
+ stage: test
+ needs:
+ - install-dependencies
+ extends:
+ - .use-pub-cache-bin
+ - .download-cache
+ script:
+ - dart analyze .
-test:
+format-test:
stage: test
+ needs:
+ - install-dependencies
+ extends:
+ - .use-pub-cache-bin
+ - .download-cache
script:
- - pub run test $PUB_VARS
+ - dart format --set-exit-if-changed bin/ lib/ test/
diff --git a/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml b/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
index 464b81965f2..dc55277318b 100644
--- a/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
@@ -42,6 +42,7 @@ lint-test-job: # This job also runs in the test stage.
deploy-job: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
+ environment: production
script:
- echo "Deploying application..."
- echo "Application successfully deployed."
diff --git a/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml
index 7f33d048c1e..34988fcdcde 100644
--- a/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Indeni.Cloudrail.gitlab-ci.yml
@@ -31,7 +31,7 @@ default:
init_and_plan:
stage: build
- image: registry.gitlab.com/gitlab-org/terraform-images/releases/0.13
+ image: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/terraform-images/releases/0.13"
rules:
- if: $SAST_DISABLED
when: never
diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
index 8c63019d743..ce227bad19a 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
@@ -3,7 +3,7 @@ variables:
build:
stage: build
- image: 'registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:${AUTO_BUILD_IMAGE_VERSION}'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-build-image:${AUTO_BUILD_IMAGE_VERSION}'
variables:
DOCKER_TLS_CERTDIR: ''
services:
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 8c63019d743..ce227bad19a 100644
--- a/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Build.latest.gitlab-ci.yml
@@ -3,7 +3,7 @@ variables:
build:
stage: build
- image: 'registry.gitlab.com/gitlab-org/cluster-integration/auto-build-image:${AUTO_BUILD_IMAGE_VERSION}'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-build-image:${AUTO_BUILD_IMAGE_VERSION}'
variables:
DOCKER_TLS_CERTDIR: ''
services:
diff --git a/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
index 11f8376f0b4..6e8cf15204a 100644
--- a/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/CF-Provision.gitlab-ci.yml
@@ -2,7 +2,7 @@ stages:
- provision
cloud_formation:
- image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-cloudformation:latest'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cloud-deploy/aws-cloudformation:latest'
stage: provision
script:
- gl-cloudformation create-stack
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 86e3ace84c5..e278539d214 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: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.29"
+ CODE_QUALITY_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/ci-cd/codequality:0.85.29"
needs: []
script:
- export SOURCE_CODE=$PWD
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 b41e92e3a56..f0ddc4b4916 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,8 +1,8 @@
variables:
- DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.30.0'
+ DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.33.0'
.dast-auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"
.common_rules: &common_rules
- if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME
@@ -57,7 +57,7 @@ stop_dast_environment:
when: always
.ecs_image:
- image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cloud-deploy/aws-ecs:latest'
.ecs_rules: &ecs_rules
- if: $AUTO_DEVOPS_PLATFORM_TARGET != "ECS"
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 a9d9c400a34..7cbc8e40b47 100644
--- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
@@ -11,7 +11,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
DS_EXCLUDED_ANALYZERS: ""
DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
DS_MAJOR_VERSION: 3
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index f9c0d4333ff..1a2a8b4edb4 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -1,8 +1,8 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.30.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.33.0'
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
dependencies: []
review:
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
index 36f1b6981c4..cb8818357a2 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -1,8 +1,8 @@
variables:
- AUTO_DEPLOY_IMAGE_VERSION: 'v2.30.0'
+ AUTO_DEPLOY_IMAGE_VERSION: 'v2.33.0'
.auto-deploy:
- image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"
dependencies: []
review:
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
index ab3bc511cba..8a349f751ea 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml
@@ -3,7 +3,7 @@ stages:
- production
.push-and-deploy:
- image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ec2:latest'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cloud-deploy/aws-ec2:latest'
script:
- gl-ec2 push-to-s3
- gl-ec2 deploy-to-ec2
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
index c2d31fd9669..43dc44312da 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
@@ -7,9 +7,8 @@
# then result in potentially breaking your future pipelines.
#
# More about including CI templates: https://docs.gitlab.com/ee/ci/yaml/#includetemplate
-
.ecs_image:
- image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest'
+ image: '${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cloud-deploy/aws-ecs:latest'
.deploy_to_ecs:
extends: .ecs_image
diff --git a/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
index d55c126eeb7..b7735068680 100644
--- a/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Helm-2to3.gitlab-ci.yml
@@ -3,9 +3,8 @@
#
# To use, set the CI variable MIGRATE_HELM_2TO3 to "true".
# For more details, go to https://docs.gitlab.com/ee/topics/autodevops/upgrading_auto_deploy_dependencies.html#helm-v3
-
.helm-2to3-migrate:
- image: registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/helm-2to3-2.17.0-3.5.3-kube-1.16.15-alpine-3.12
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/helm-install-image/releases/helm-2to3-2.17.0-3.5.3-kube-1.16.15-alpine-3.12"
# NOTE: We use the deploy stage because:
# - It exists in all versions of Auto DevOps.
# - It is _empty_.
@@ -54,7 +53,7 @@
done
.helm-2to3-cleanup:
- image: registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/helm-2to3-2.17.0-3.5.3-kube-1.16.15-alpine-3.12
+ image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/helm-install-image/releases/helm-2to3-2.17.0-3.5.3-kube-1.16.15-alpine-3.12"
stage: cleanup
environment:
action: prepare
diff --git a/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
index f7945b46a59..f8668699fe5 100644
--- a/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
@@ -11,7 +11,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
LICENSE_MANAGEMENT_VERSION: 4
diff --git a/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml
index b6358eb0831..c195ecd8ee5 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml
@@ -6,7 +6,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SAST_IMAGE_SUFFIX: ""
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
@@ -31,7 +31,7 @@ kics-iac-sast:
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
- SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE_TAG: 3
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
rules:
- if: $SAST_DISABLED
diff --git a/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
index b6358eb0831..0513aae00a8 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
@@ -6,7 +6,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SAST_IMAGE_SUFFIX: ""
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
@@ -31,11 +31,14 @@ kics-iac-sast:
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
- SAST_ANALYZER_IMAGE_TAG: 2
+ SAST_ANALYZER_IMAGE_TAG: 3
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
rules:
- if: $SAST_DISABLED
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /kics/
when: never
- - if: $CI_COMMIT_BRANCH
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+ when: never
+ - if: $CI_COMMIT_BRANCH # If there's no open merge request, add it to a *branch* pipeline instead.
diff --git a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
index be41553450c..dd164c00724 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST.gitlab-ci.yml
@@ -6,7 +6,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SAST_IMAGE_SUFFIX: ""
SAST_EXCLUDED_ANALYZERS: ""
diff --git a/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml
index f8e6e152ab9..c6938920ea4 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST.latest.gitlab-ci.yml
@@ -6,7 +6,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SAST_IMAGE_SUFFIX: ""
SAST_EXCLUDED_ANALYZERS: ""
@@ -46,7 +46,7 @@ bandit-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /bandit/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.py'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -67,7 +67,7 @@ brakeman-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.rb'
- '**/Gemfile'
@@ -90,7 +90,7 @@ eslint-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /eslint/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.html'
- '**/*.js'
@@ -119,7 +119,7 @@ flawfinder-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /flawfinder/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.c'
- '**/*.cc'
@@ -151,7 +151,7 @@ kubesec-sast:
- if: $SAST_EXCLUDED_ANALYZERS =~ /kubesec/
when: never
# Add the job to merge request pipelines if there's an open merge request.
- - if: $CI_MERGE_REQUEST_IID &&
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
$SCAN_KUBERNETES_MANIFESTS == 'true'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
when: never
@@ -171,7 +171,7 @@ gosec-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /gosec/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.go'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -196,7 +196,7 @@ mobsf-android-sast:
- if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
when: never
# Add the job to merge request pipelines if there's an open merge request.
- - if: $CI_MERGE_REQUEST_IID &&
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/*.apk'
@@ -218,7 +218,7 @@ mobsf-ios-sast:
- if: $SAST_EXCLUDED_ANALYZERS =~ /mobsf/
when: never
# Add the job to merge request pipelines if there's an open merge request.
- - if: $CI_MERGE_REQUEST_IID &&
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
$SAST_EXPERIMENTAL_FEATURES == 'true'
exists:
- '**/*.ipa'
@@ -244,7 +244,7 @@ nodejs-scan-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /nodejs-scan/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/package.json'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -265,7 +265,7 @@ phpcs-security-audit-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /phpcs-security-audit/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.php'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -286,7 +286,7 @@ pmd-apex-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /pmd-apex/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.cls'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -307,7 +307,7 @@ security-code-scan-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /security-code-scan/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.csproj'
- '**/*.vbproj'
@@ -331,7 +331,7 @@ semgrep-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.py'
- '**/*.js'
@@ -366,7 +366,7 @@ sobelow-sast:
when: never
- if: $SAST_EXCLUDED_ANALYZERS =~ /sobelow/
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- 'mix.exs'
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
@@ -391,7 +391,7 @@ spotbugs-sast:
when: never
- if: $SAST_DISABLED
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
exists:
- '**/*.groovy'
- '**/*.java'
diff --git a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
index 3f18237a525..b7a9dbf7bc6 100644
--- a/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Secret-Detection.gitlab-ci.yml
@@ -5,7 +5,7 @@
# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SECRET_DETECTION_IMAGE_SUFFIX: ""
SECRETS_ANALYZER_VERSION: "4"
diff --git a/lib/gitlab/ci/templates/Jobs/Secret-Detection.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Secret-Detection.latest.gitlab-ci.yml
index e81e06d1a1d..e6eba6f6406 100644
--- a/lib/gitlab/ci/templates/Jobs/Secret-Detection.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Secret-Detection.latest.gitlab-ci.yml
@@ -5,8 +5,9 @@
# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SECRET_DETECTION_IMAGE_SUFFIX: ""
+
SECRETS_ANALYZER_VERSION: "4"
SECRET_DETECTION_EXCLUDED_PATHS: ""
@@ -28,7 +29,7 @@ secret_detection:
rules:
- if: $SECRET_DETECTION_DISABLED
when: never
- - if: $CI_MERGE_REQUEST_IID # Add the job to merge request pipelines if there's an open merge request.
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Add the job to merge request pipelines if there's an open merge request.
- if: $CI_OPEN_MERGE_REQUESTS # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
when: never
- if: $CI_COMMIT_BRANCH # If there's no open merge request, add it to a *branch* pipeline instead.
diff --git a/lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml b/lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml
index 64a063388b2..30767e66649 100644
--- a/lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml
@@ -3,31 +3,45 @@
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/MATLAB.gitlab-ci.yml
-# Use this template to run MATLAB and Simulink as part of your CI/CD pipeline. The template has three jobs:
+# Use this template to run MATLAB and Simulink as part of your CI/CD pipeline. The template includes three jobs:
# - `command`: Run MATLAB scripts, functions, and statements.
# - `test`: Run tests authored using the MATLAB unit testing framework or Simulink Test.
# - `test_artifacts`: Run MATLAB and Simulink tests, and generate test and coverage artifacts.
#
+# The jobs in the template use the `matlab -batch` syntax to start MATLAB. The `-batch` option is supported
+# in MATLAB R2019a and later.
+#
# You can copy and paste one or more jobs in this template into your `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
-# - To run MATLAB and Simulink, MATLAB must be installed on the runner that will run the jobs.
-# The runner will use the topmost MATLAB version on the system path.
-# The build fails if the operating system cannot find MATLAB on the path.
-# - The jobs in this template use the `matlab -batch` syntax to start MATLAB. The `-batch` option is supported
-# in MATLAB R2019a and later.
+
+# Your runner must use the Docker executor to run MATLAB within a container. The [MATLAB Container on Docker Hub][1]
+# lets you run your build using MATLAB R2020b or a later release. If your build requires additional toolboxes, use a
+# custom MATLAB container instead. For more information on how to create and use a custom MATLAB container,
+# see [Create a Custom MATLAB Container][2].
+#
+# [1] https://www.mathworks.com/help/cloudcenter/ug/matlab-container-on-docker-hub.html
+# [2] https://www.mathworks.com/help/cloudcenter/ug/create-a-custom-matlab-container.html
+
+# The jobs in this template incorporate the contents of a hidden `.matlab_defaults` job. You need to
+# configure this job before running the `command`, `test`, and `test_artifacts` jobs. To configure the job:
+# - Specify the name of the MATLAB container image you want to use.
+# - Set the `MLM_LICENSE_FILE` environment variable using the port number and DNS address for your network license manager.
+#
+.matlab_defaults:
+ image:
+ name: mathworks/matlab:latest # Replace the value with the name of the MATLAB container image you want to use
+ entrypoint: [""]
+ variables:
+ MLM_LICENSE_FILE: 27000@MyLicenseServer # Replace the value with the port number and DNS address for your network license manager
# The `command` job runs MATLAB scripts, functions, and statements. To use the job in your pipeline,
# substitute `mycommand` with the code you want to run.
#
command:
+ extends: .matlab_defaults
script: matlab -batch mycommand
-# If the value of `mycommand` is the name of a MATLAB script or function, do not specify the file extension.
-# For example, to run a script named `myscript.m` in the root of your repository, specify `mycommand` like this:
-#
-# "myscript"
-#
# If you specify more than one script, function, or statement, use a comma or semicolon to separate them.
# For example, to run `myscript.m` in a folder named `myfolder` located in the root of the repository,
# you can specify `mycommand` like this:
@@ -36,51 +50,51 @@ command:
#
# MATLAB exits with exit code 0 if the specified script, function, or statement executes successfully without
# error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the job to fail. To have the
-# job fail in certain conditions, use the [`assert`][1] or [`error`][2] functions.
+# job fail in certain conditions, use the [`assert`][3] or [`error`][4] functions.
#
-# [1] https://www.mathworks.com/help/matlab/ref/assert.html
-# [2] https://www.mathworks.com/help/matlab/ref/error.html
+# [3] https://www.mathworks.com/help/matlab/ref/assert.html
+# [4] https://www.mathworks.com/help/matlab/ref/error.html
-# The `test` job runs the MATLAB and Simulink tests in your project. It calls the [`runtests`][3] function
-# to run the tests and then the [`assertSuccess`][4] method to fail the job if any of the tests fail.
+# The `test` job runs the MATLAB and Simulink tests in your project. It calls the [`runtests`][5] function
+# to run the tests and then the [`assertSuccess`][6] method to fail the job if any of the tests fail.
#
test:
+ extends: .matlab_defaults
script: matlab -batch "results = runtests('IncludeSubfolders',true), assertSuccess(results);"
-# By default, the job includes any files in your [MATLAB Project][5] that have a `Test` label. If your repository
+# By default, the job includes any files in your [MATLAB Project][7] that have a `Test` label. If your repository
# does not have a MATLAB project, then the job includes all tests in the root of your repository or in any of
# its subfolders.
#
-# [3] https://www.mathworks.com/help/matlab/ref/runtests.html
-# [4] https://www.mathworks.com/help/matlab/ref/matlab.unittest.testresult.assertsuccess.html
-# [5] https://www.mathworks.com/help/matlab/projects.html
+# [5] https://www.mathworks.com/help/matlab/ref/runtests.html
+# [6] https://www.mathworks.com/help/matlab/ref/matlab.unittest.testresult.assertsuccess.html
+# [7] https://www.mathworks.com/help/matlab/projects.html
# The `test_artifacts` job runs your tests and additionally generates test and coverage artifacts.
-# It uses the plugin classes in the [`matlab.unittest.plugins`][6] package to generate a JUnit test results
+# It uses the plugin classes in the [`matlab.unittest.plugins`][8] package to generate a JUnit test results
# report and a Cobertura code coverage report. Like the `test` job, this job runs all the tests in your
# project and fails the build if any of the tests fail.
#
test_artifacts:
+ extends: .matlab_defaults
script: |
- matlab -batch "
- import matlab.unittest.TestRunner
- import matlab.unittest.Verbosity
- import matlab.unittest.plugins.CodeCoveragePlugin
- import matlab.unittest.plugins.XMLPlugin
- import matlab.unittest.plugins.codecoverage.CoberturaFormat
-
- suite = testsuite(pwd,'IncludeSubfolders',true);
-
- [~,~] = mkdir('artifacts');
-
- runner = TestRunner.withTextOutput('OutputDetail',Verbosity.Detailed);
- runner.addPlugin(XMLPlugin.producingJUnitFormat('artifacts/results.xml'))
- runner.addPlugin(CodeCoveragePlugin.forFolder(pwd,'IncludingSubfolders',true, ...
- 'Producing',CoberturaFormat('artifacts/cobertura.xml')))
-
- results = runner.run(suite)
- assertSuccess(results);"
-
+ cat <<- 'BLOCK' > runAllTests.m
+ import matlab.unittest.TestRunner
+ import matlab.unittest.Verbosity
+ import matlab.unittest.plugins.CodeCoveragePlugin
+ import matlab.unittest.plugins.XMLPlugin
+ import matlab.unittest.plugins.codecoverage.CoberturaFormat
+ suite = testsuite(pwd,'IncludeSubfolders',true);
+ [~,~] = mkdir('artifacts')
+ runner = TestRunner.withTextOutput('OutputDetail',Verbosity.Detailed);
+ runner.addPlugin(XMLPlugin.producingJUnitFormat('artifacts/results.xml'))
+ % Replace `pwd` with the location of the folder containing source code
+ runner.addPlugin(CodeCoveragePlugin.forFolder(pwd,'IncludingSubfolders',true, ...
+ 'Producing',CoberturaFormat('artifacts/cobertura.xml')))
+ results = runner.run(suite)
+ assertSuccess(results);
+ BLOCK
+ matlab -batch runAllTests
artifacts:
reports:
junit: "./artifacts/results.xml"
@@ -92,7 +106,7 @@ test_artifacts:
# You can modify the contents of the `test_artifacts` job depending on your goals. For more
# information on how to customize the test runner and generate various test and coverage artifacts,
-# see [Generate Artifacts Using MATLAB Unit Test Plugins][7].
+# see [Generate Artifacts Using MATLAB Unit Test Plugins][9].
#
-# [6] https://www.mathworks.com/help/matlab/ref/matlab.unittest.plugins-package.html
-# [7] https://www.mathworks.com/help/matlab/matlab_prog/generate-artifacts-using-matlab-unit-test-plugins.html
+# [8] https://www.mathworks.com/help/matlab/ref/matlab.unittest.plugins-package.html
+# [9] https://www.mathworks.com/help/matlab/matlab_prog/generate-artifacts-using-matlab-unit-test-plugins.html
diff --git a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
index cfc4a1d904a..591eebf9cd6 100644
--- a/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
@@ -6,7 +6,7 @@
---
# All available Hugo versions are listed here:
# https://gitlab.com/pages/hugo/container_registry
-image: registry.gitlab.com/pages/hugo:latest
+image: "${CI_TEMPLATE_REGISTRY_HOST}/pages/hugo:latest"
variables:
GIT_SUBMODULE_STRATEGY: recursive
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
index 2fd5b409f5e..cdfa4556769 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
@@ -24,7 +24,7 @@
variables:
# Setting this variable affects all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
#
FUZZAPI_VERSION: "2"
FUZZAPI_IMAGE_SUFFIX: ""
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 450969fcdab..8d6c191edc4 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
@@ -24,7 +24,7 @@
variables:
# Setting this variable affects all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
#
FUZZAPI_VERSION: "2"
FUZZAPI_IMAGE_SUFFIX: ""
diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
index bec269e2933..3d7883fb87a 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -22,7 +22,7 @@
# List of available variables: https://docs.gitlab.com/ee/user/application_security/container_scanning/#available-variables
variables:
- CS_ANALYZER_IMAGE: registry.gitlab.com/security-products/container-scanning:5
+ CS_ANALYZER_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/security-products/container-scanning:5"
container_scanning:
image: "$CS_ANALYZER_IMAGE$CS_IMAGE_SUFFIX"
diff --git a/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
index 893098d33c4..1b33596baa0 100644
--- a/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml
@@ -24,7 +24,7 @@
variables:
# Setting this variable affects all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
#
DAST_API_VERSION: "2"
DAST_API_IMAGE_SUFFIX: ""
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 3acc3b06031..8aabf20c5df 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
@@ -24,7 +24,7 @@
variables:
# Setting this variable affects all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
#
DAST_API_VERSION: "2"
DAST_API_IMAGE_SUFFIX: ""
diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
index 4a72f5e72b1..1bd527a6ec0 100644
--- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-API-Scan.gitlab-ci.yml
@@ -10,7 +10,7 @@ stages:
- dast
variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
DAST_API_VERSION: "2"
DAST_API_IMAGE_SUFFIX: ""
DAST_API_IMAGE: api-security
diff --git a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
index c71a1b1873a..701e08ba56d 100644
--- a/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-On-Demand-Scan.gitlab-ci.yml
@@ -13,7 +13,7 @@ variables:
DAST_VERSION: 3
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
dast:
stage: dast
diff --git a/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml
index d27a08db181..5b6af37977e 100644
--- a/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST-Runner-Validation.gitlab-ci.yml
@@ -15,7 +15,7 @@ variables:
validation:
stage: dast
image:
- name: "registry.gitlab.com/security-products/dast-runner-validation:$DAST_RUNNER_VALIDATION_VERSION"
+ name: "$CI_TEMPLATE_REGISTRY_HOST/security-products/dast-runner-validation:$DAST_RUNNER_VALIDATION_VERSION"
variables:
GIT_STRATEGY: none
allow_failure: false
diff --git a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
index 3bc44fe5e1b..40060e96dff 100644
--- a/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
@@ -25,7 +25,7 @@ variables:
DAST_VERSION: 3
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
dast:
stage: dast
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 10549b56856..9d3b1f4316e 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -25,7 +25,7 @@ variables:
DAST_VERSION: 3
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
dast:
stage: dast
@@ -39,6 +39,8 @@ dast:
- if [ -z "$DAST_WEBSITE$DAST_API_SPECIFICATION" ]; then echo "Either DAST_WEBSITE or DAST_API_SPECIFICATION must be set. See https://docs.gitlab.com/ee/user/application_security/dast/#configuration for more details." && exit 1; fi
- /analyze
artifacts:
+ paths:
+ - dast_artifacts/*
reports:
dast: gl-dast-report.json
rules:
@@ -55,3 +57,7 @@ dast:
$GITLAB_FEATURES =~ /\bdast\b/
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdast\b/
+ after_script:
+ # Remove any debug.log files because they might contain secrets.
+ - rm -f /zap/wrk/**/debug.log
+ - cp -r /zap/wrk dast_artifacts
diff --git a/lib/gitlab/ci/templates/Security/Fortify-FoD-sast.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Fortify-FoD-sast.gitlab-ci.yml
new file mode 100644
index 00000000000..acd532132f4
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/Fortify-FoD-sast.gitlab-ci.yml
@@ -0,0 +1,52 @@
+# This template is provided and maintained by Fortify, an official Technology Partner with GitLab.
+# 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.
+
+################################################################################################################################################
+# Fortify lets you build secure software fast with an appsec platform that automates testing throughout the DevSecOps pipeline. Fortify static,#
+# dynamic, interactive, and runtime security testing is available on premises or as a service. To learn more about Fortify, start a free trial #
+# or contact our sales team, visit microfocus.com/appsecurity. #
+# #
+# Use this pipeline template as a basis for integrating Fortify on Demand Static Application Security Testing(SAST) into your GitLab pipelines.#
+# This template demonstrates the steps to prepare the code+dependencies and initiate a scan. As an option, it also supports waiting for the #
+# SAST scan to complete and optinally failing the job. Software Composition Analysis can be also be performed in conjunection with the SAST #
+# scan if that service has been purchased. Users should review inputs and environment variables below to configure scanning for an existing #
+# application in your Fortify on Demand tenant. Additional information is available in the comments throughout the template and the Fortify on #
+# Demand, FoD Uploader and ScanCentral Client product documentation. If you need additional assistance with configuration, feel free to create #
+# a help ticket in the Fortify on Demand portal. #
+################################################################################################################################################
+
+fortify_fod_sast:
+ image: fortifydocker/fortify-ci-tools:3-jdk-8
+ variables:
+ # Update/override PACKAGE_OPTS based on the ScanCentral Client documentation for your project's included tech stack(s). Helpful hints:
+ # ScanCentral Client will download dependencies for maven (-bt mvn) and gradle (-bt gradle).
+ # The current fortify-ci-tools image is Linux only at this time. Msbuild integration is not currently supported.
+ # ScanCentral has additional options that should be set for PHP and Python projects.
+ # For other build tools (-bt none), add your build commands to download necessary dependencies and prepare according to Fortify on Demand Packaging documentation.
+ # ScanCentral Client documentation is located at https://www.microfocus.com/documentation/fortify-software-security-center/
+ PACKAGE_OPTS: "-bt mvn"
+
+ # Update/override the FoDUploader environment variables as needed. For more information on FoDUploader commands, see https://github.com/fod-dev/fod-uploader-java. Helpful hints:
+ # Credentials (FOD_USERNAME, FOD_PAT, FOD_TENANT) are expected as GitLab CICD Variables in the template (masking recommended).
+ # Static scan settings should be configured in Fortify on Demand portal (Automated Audit preference strongly recommended).
+ # FOD_RELEASE_ID is expected as a GitLab CICD Variable.
+ # FOD_UPLOADER_OPTS can be adjusted to wait for scan completion/pull results (-I 1) and control whether to fail the job (-apf).
+ FOD_URL: "https://ams.fortify.com"
+ FOD_API_URL: "https://api.ams.fortify.com/"
+ FOD_UPLOADER_OPTS: "-ep 2 -pp 0"
+ FOD_NOTES: "Triggered by Gitlab Pipeline IID $CI_PIPELINE_IID: $CI_PIPELINE_URL"
+
+ script:
+ # Package source code and dependencies using Fortify ScanCentral client
+ - 'scancentral package $PACKAGE_OPTS -o package.zip'
+ # Start Fortify on Demand SAST scan
+ - 'FoDUpload -z package.zip -aurl $FOD_API_URL -purl $FOD_URL -rid "$FOD_RELEASE" -tc "$FOD_TENANT" -uc "$FOD_USERNAME" "$FOD_PAT" $FOD_UPLOADER_OPTS -I 1 -n "$FOD_NOTES"'
+ # Generate GitLab reports
+ - 'FortifyVulnerabilityExporter FoDToGitLabSAST --fod.baseUrl=$FOD_URL --fod.tenant="$FOD_TENANT" --fod.userName="$FOD_USERNAME" --fod.password="$FOD_PAT" --fod.release.id=$FOD_RELEASE'
+ # Change to false to fail the entire pipeline if the scan fails and/or the result of a scan causes security policy failure (see "-apf" option in FoDUploader documentation)
+ allow_failure: true
+ # Report SAST vulnerabilities back to GitLab
+ artifacts:
+ reports:
+ sast: gl-fortify-sast.json
diff --git a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
index c414e70bfa3..fd04c86e6c7 100644
--- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml
@@ -16,7 +16,7 @@
variables:
# Setting this variable will affect all Security templates
# (SAST, Dependency Scanning, ...)
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"
+ SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
SECURE_BINARIES_ANALYZERS: >-
bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, secrets, sobelow, pmd-apex, kics, kubesec, semgrep, gemnasium, gemnasium-maven, gemnasium-python,
license-finder,
@@ -246,7 +246,7 @@ dast-runner-validation:
extends: .download_images
variables:
SECURE_BINARIES_ANALYZER_VERSION: "1"
- SECURE_BINARIES_IMAGE: "registry.gitlab.com/security-products/${CI_JOB_NAME}:${SECURE_BINARIES_ANALYZER_VERSION}"
+ SECURE_BINARIES_IMAGE: "${CI_TEMPLATE_REGISTRY_HOST}/security-products/${CI_JOB_NAME}:${SECURE_BINARIES_ANALYZER_VERSION}"
only:
variables:
- $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" &&
diff --git a/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
index 6f9a9c5133c..3a956ebfc49 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
@@ -9,7 +9,7 @@
# There is a more opinionated template which we suggest the users to abide,
# which is the lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
image:
- name: registry.gitlab.com/gitlab-org/terraform-images/releases/terraform:1.1.9
+ name: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/terraform-images/releases/terraform:1.1.9"
variables:
TF_ROOT: ${CI_PROJECT_DIR} # The relative path to the root directory of the Terraform project
diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
index 9ba009a5bca..4579f31d7ac 100644
--- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml
@@ -10,7 +10,7 @@
# which is the lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml
image:
- name: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
+ name: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/terraform-images/stable:latest"
variables:
TF_ROOT: ${CI_PROJECT_DIR} # The relative path to the root directory of the Terraform project
diff --git a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
index 2b5e86f4066..488b035d189 100644
--- a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
@@ -4,7 +4,6 @@
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_testing.html
-
stages:
- build
- test
@@ -13,7 +12,7 @@ stages:
a11y:
stage: accessibility
- image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:6.2.3
+ image: "$CI_TEMPLATE_REGISTRY_HOST/gitlab-org/ci-cd/accessibility:6.2.3"
script:
- /gitlab-accessibility.sh "$a11y_urls"
allow_failure: true
diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb
index 9f24ba99201..32f64948635 100644
--- a/lib/gitlab/ci/trace/chunked_io.rb
+++ b/lib/gitlab/ci/trace/chunked_io.rb
@@ -22,7 +22,7 @@ module Gitlab
@chunks_cache = []
@tell = 0
@size = calculate_size
- yield self if block_given?
+ yield self if block
end
def close
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index a00c1da97ea..52673d03e69 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -72,24 +72,32 @@ module Gitlab
Collection.new(@variables.reject(&block))
end
- def expand_value(value, keep_undefined: false)
+ def expand_value(value, keep_undefined: false, expand_file_vars: true)
value.gsub(Item::VARIABLES_REGEXP) do
- match = Regexp.last_match
- if match[:key]
- # we matched variable
- if variable = self[match[:key]]
- variable.value
- elsif keep_undefined
- match[0]
- end
+ match = Regexp.last_match # it is either a valid variable definition or a ($$ / %%)
+ full_match = match[0]
+ variable_name = match[:key]
+
+ next full_match unless variable_name # it is a ($$ / %%), so we don't touch it
+
+ # now we know that it is a valid variable definition: $VARIABLE_NAME / %VARIABLE_NAME / ${VARIABLE_NAME}
+
+ # we are trying to find a variable with key VARIABLE_NAME
+ variable = self[variable_name]
+
+ if variable # VARIABLE_NAME is an existing variable
+ next variable.value unless variable.file?
+
+ expand_file_vars ? variable.value : full_match
+ elsif keep_undefined
+ full_match # we do not touch the variable definition
else
- # we escape sequence
- match[0]
+ nil # we remove the variable definition
end
end
end
- def sort_and_expand_all(keep_undefined: false)
+ def sort_and_expand_all(keep_undefined: false, expand_file_vars: true)
sorted = Sort.new(self)
return self.class.new(self, sorted.errors) unless sorted.valid?
@@ -103,7 +111,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)
+ variable[:value] = new_collection.expand_value(variable[:value], keep_undefined: keep_undefined,
+ expand_file_vars: expand_file_vars)
new_collection.append(variable)
end
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index 0217e6129ca..ea2aa8f2db8 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -25,6 +25,10 @@ module Gitlab
@variable.fetch(:raw)
end
+ def file?
+ @variable.fetch(:file)
+ end
+
def [](key)
@variable.fetch(key)
end
diff --git a/lib/gitlab/ci/variables/helpers.rb b/lib/gitlab/ci/variables/helpers.rb
index 3a62f01e2e3..300b2708e6d 100644
--- a/lib/gitlab/ci/variables/helpers.rb
+++ b/lib/gitlab/ci/variables/helpers.rb
@@ -6,24 +6,22 @@ module Gitlab
module Helpers
class << self
def merge_variables(current_vars, new_vars)
- current_vars = transform_from_yaml_variables(current_vars)
- new_vars = transform_from_yaml_variables(new_vars)
+ return current_vars if new_vars.blank?
- transform_to_yaml_variables(
- current_vars.merge(new_vars)
- )
- end
+ current_vars = transform_to_array(current_vars) if current_vars.is_a?(Hash)
+ new_vars = transform_to_array(new_vars) if new_vars.is_a?(Hash)
- def transform_to_yaml_variables(vars)
- vars.to_h.map do |key, value|
- { key: key.to_s, value: value, public: true }
- end
+ (new_vars + current_vars).uniq { |var| var[:key] }
end
- def transform_from_yaml_variables(vars)
- return vars.stringify_keys if vars.is_a?(Hash)
-
- vars.to_a.to_h { |var| [var[:key].to_s, var[:value]] }
+ def transform_to_array(vars)
+ vars.to_h.map do |key, data|
+ if data.is_a?(Hash)
+ { key: key.to_s, **data.except(:key) }
+ else
+ { key: key.to_s, value: data }
+ end
+ end
end
def inherit_yaml_variables(from:, to:, inheritance:)
@@ -35,7 +33,7 @@ module Gitlab
def apply_inheritance(variables, inheritance)
case inheritance
when true then variables
- when false then {}
+ when false then []
when Array then variables.select { |var| inheritance.include?(var[:key]) }
end
end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index 576fb509d47..f203f88442d 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -39,11 +39,11 @@ module Gitlab
end
def workflow_rules
- @workflow_rules ||= hash_config.dig(:workflow, :rules)
+ @workflow_rules ||= @ci_config.workflow_rules
end
def root_variables
- @root_variables ||= transform_to_yaml_variables(variables)
+ @root_variables ||= transform_to_array(variables)
end
def jobs
@@ -70,7 +70,7 @@ module Gitlab
environment: job[:environment_name],
coverage_regex: job[:coverage],
# yaml_variables is calculated with using job_variables in Seed::Build
- job_variables: transform_to_yaml_variables(job[:job_variables]),
+ job_variables: transform_to_array(job[:job_variables]),
root_variables_inheritance: job[:root_variables_inheritance],
needs_attributes: job.dig(:needs, :job),
interruptible: job[:interruptible],
@@ -114,7 +114,7 @@ module Gitlab
Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
from: root_variables,
- to: transform_to_yaml_variables(job[:job_variables]),
+ to: job[:job_variables],
inheritance: job.fetch(:root_variables_inheritance, true)
)
end
@@ -133,16 +133,12 @@ module Gitlab
@variables ||= @ci_config.variables
end
- def hash_config
- @hash_config ||= @ci_config.to_hash
- end
-
def release(job)
job[:release]
end
- def transform_to_yaml_variables(variables)
- ::Gitlab::Ci::Variables::Helpers.transform_to_yaml_variables(variables)
+ def transform_to_array(variables)
+ ::Gitlab::Ci::Variables::Helpers.transform_to_array(variables)
end
end
end
diff --git a/lib/gitlab/cleanup/project_uploads.rb b/lib/gitlab/cleanup/project_uploads.rb
index ed4b363416c..7f24b2f78b0 100644
--- a/lib/gitlab/cleanup/project_uploads.rb
+++ b/lib/gitlab/cleanup/project_uploads.rb
@@ -56,7 +56,7 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def move_to_lost_and_found(path, dry_run)
- new_path = path.sub(/\A#{ProjectUploadFileFinder::ABSOLUTE_UPLOAD_DIR}/, LOST_AND_FOUND)
+ new_path = path.sub(/\A#{ProjectUploadFileFinder::ABSOLUTE_UPLOAD_DIR}/o, LOST_AND_FOUND)
move(path, new_path, 'move to lost and found', dry_run)
end
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 4d289a59a6a..a45380aca6c 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -43,7 +43,7 @@ module Gitlab
.group(:date)
.map(&:attributes)
- @activity_dates = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities|
+ @activity_dates = events.each_with_object(Hash.new { |h, k| h[k] = 0 }) do |event, activities|
activities[event["date"]] += event["num_events"]
end
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 8ef4977177a..5c4899da11f 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -84,7 +84,11 @@ module Gitlab
def connect_to_db?
# When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised
- active_db_connection = ::ApplicationSetting.connection.active? rescue false
+ active_db_connection = begin
+ ::ApplicationSetting.connection.active?
+ rescue StandardError
+ false
+ end
active_db_connection &&
ApplicationSetting.database.cached_table_exists?
diff --git a/lib/gitlab/daemon.rb b/lib/gitlab/daemon.rb
index 04d13778499..49828e54d7e 100644
--- a/lib/gitlab/daemon.rb
+++ b/lib/gitlab/daemon.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
module Gitlab
+ # DEPRECATED. Use Gitlab::BackgroundTask for new code instead.
class Daemon
# Options:
# - recreate: We usually only allow a single instance per process to exist;
diff --git a/lib/gitlab/data_builder/issuable.rb b/lib/gitlab/data_builder/issuable.rb
index d12537c4874..9a7b4d0e2aa 100644
--- a/lib/gitlab/data_builder/issuable.rb
+++ b/lib/gitlab/data_builder/issuable.rb
@@ -26,6 +26,10 @@ module Gitlab
hook_data[:assignees] = issuable.assignees.map(&:hook_attrs) if issuable.assignees.any?
+ if issuable.allows_reviewers? && issuable.reviewers.any?
+ hook_data[:reviewers] = issuable.reviewers.map(&:hook_attrs)
+ end
+
hook_data
end
diff --git a/lib/gitlab/database/async_indexes.rb b/lib/gitlab/database/async_indexes.rb
index d89d5238356..6f301a66803 100644
--- a/lib/gitlab/database/async_indexes.rb
+++ b/lib/gitlab/database/async_indexes.rb
@@ -6,10 +6,16 @@ module Gitlab
DEFAULT_INDEXES_PER_INVOCATION = 2
def self.create_pending_indexes!(how_many: DEFAULT_INDEXES_PER_INVOCATION)
- PostgresAsyncIndex.order(:id).limit(how_many).each do |async_index|
+ PostgresAsyncIndex.to_create.order(:id).limit(how_many).each do |async_index|
IndexCreator.new(async_index).perform
end
end
+
+ def self.drop_pending_indexes!(how_many: DEFAULT_INDEXES_PER_INVOCATION)
+ PostgresAsyncIndex.to_drop.order(:id).limit(how_many).each do |async_index|
+ IndexDestructor.new(async_index).perform
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/async_indexes/index_destructor.rb b/lib/gitlab/database/async_indexes/index_destructor.rb
new file mode 100644
index 00000000000..fe05872b87a
--- /dev/null
+++ b/lib/gitlab/database/async_indexes/index_destructor.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module AsyncIndexes
+ class IndexDestructor
+ include ExclusiveLeaseGuard
+
+ TIMEOUT_PER_ACTION = 1.day
+
+ def initialize(async_index)
+ @async_index = async_index
+ end
+
+ def perform
+ try_obtain_lease do
+ if !index_exists?
+ log_index_info('Skipping dropping as the index does not exist')
+ else
+ log_index_info('Dropping async index')
+
+ retries = Gitlab::Database::WithLockRetriesOutsideTransaction.new(
+ connection: connection,
+ timing_configuration: Gitlab::Database::Reindexing::REMOVE_INDEX_RETRY_CONFIG,
+ klass: self.class,
+ logger: Gitlab::AppLogger
+ )
+
+ retries.run(raise_on_exhaustion: false) do
+ connection.execute(async_index.definition)
+ end
+
+ log_index_info('Finished dropping async index')
+ end
+
+ async_index.destroy
+ end
+ end
+
+ private
+
+ attr_reader :async_index
+
+ def index_exists?
+ connection.indexes(async_index.table_name).any? { |index| index.name == async_index.name }
+ end
+
+ def connection
+ @connection ||= async_index.connection
+ end
+
+ def lease_timeout
+ TIMEOUT_PER_ACTION
+ end
+
+ def lease_key
+ [super, async_index.connection_db_config.name].join('/')
+ end
+
+ def log_index_info(message)
+ Gitlab::AppLogger.info(message: message, table_name: async_index.table_name, index_name: async_index.name)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/async_indexes/migration_helpers.rb b/lib/gitlab/database/async_indexes/migration_helpers.rb
index e9846dd4e85..c8f6761534c 100644
--- a/lib/gitlab/database/async_indexes/migration_helpers.rb
+++ b/lib/gitlab/database/async_indexes/migration_helpers.rb
@@ -77,6 +77,38 @@ module Gitlab
async_index
end
+ # Prepares an index for asynchronous destruction.
+ #
+ # Stores the index information in the postgres_async_indexes table to be removed later. The
+ # index will be always be removed CONCURRENTLY, so that option does not need to be given.
+ #
+ # If the requested index has already been removed, it is not stored in the table for
+ # asynchronous destruction.
+ def prepare_async_index_removal(table_name, column_name, options = {})
+ index_name = options.fetch(:name)
+ raise 'prepare_async_index_removal must get an index name defined' if index_name.blank?
+
+ unless index_exists?(table_name, column_name, **options)
+ Gitlab::AppLogger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, index_name: #{index_name}"
+ return
+ end
+
+ definition = "DROP INDEX CONCURRENTLY #{quote_column_name(index_name)}"
+
+ async_index = PostgresAsyncIndex.find_or_create_by!(name: index_name) do |rec|
+ rec.table_name = table_name
+ rec.definition = definition
+ end
+
+ Gitlab::AppLogger.info(
+ message: 'Prepared index for async destruction',
+ table_name: async_index.table_name,
+ index_name: async_index.name
+ )
+
+ async_index
+ end
+
def async_index_creation_available?
connection.table_exists?(:postgres_async_indexes)
end
diff --git a/lib/gitlab/database/async_indexes/postgres_async_index.rb b/lib/gitlab/database/async_indexes/postgres_async_index.rb
index 6cb40729061..dc932482d40 100644
--- a/lib/gitlab/database/async_indexes/postgres_async_index.rb
+++ b/lib/gitlab/database/async_indexes/postgres_async_index.rb
@@ -13,6 +13,9 @@ module Gitlab
validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH }
validates :definition, presence: true, length: { maximum: MAX_DEFINITION_LENGTH }
+ scope :to_create, -> { where("definition ILIKE 'CREATE%'") }
+ scope :to_drop, -> { where("definition ILIKE 'DROP%'") }
+
def to_s
definition
end
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 72aa1cfe00b..81898a59da7 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -112,7 +112,7 @@ module Gitlab
end
def can_split?(exception)
- attempts >= MAX_ATTEMPTS && TIMEOUT_EXCEPTIONS.include?(exception&.class) && batch_size > sub_batch_size
+ attempts >= MAX_ATTEMPTS && TIMEOUT_EXCEPTIONS.include?(exception&.class) && batch_size > sub_batch_size && batch_size > 1
end
def split_and_retry!
@@ -121,7 +121,7 @@ module Gitlab
new_batch_size = batch_size / 2
- raise SplitAndRetryError, 'Job cannot be split further' if new_batch_size < 1
+ break update!(attempts: 0) if new_batch_size < 1
batching_strategy = batched_migration.batch_class.new(connection: self.class.connection)
next_batch_bounds = batching_strategy.next_batch(
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index 9c8db2243f9..6aed1eed994 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -206,7 +206,7 @@ module Gitlab
end
def health_context
- HealthStatus::Context.new([table_name])
+ HealthStatus::Context.new(connection, [table_name])
end
def hold!(until_time: 10.minutes.from_now)
@@ -231,6 +231,12 @@ module Gitlab
"BatchedMigration[id: #{id}]"
end
+ def progress
+ return unless total_tuple_count.to_i > 0
+
+ 100 * migrated_tuple_count / total_tuple_count
+ end
+
private
def validate_batched_jobs_status
diff --git a/lib/gitlab/database/background_migration/batched_migration_runner.rb b/lib/gitlab/database/background_migration/batched_migration_runner.rb
index 1bc2e931391..7224ff2b517 100644
--- a/lib/gitlab/database/background_migration/batched_migration_runner.rb
+++ b/lib/gitlab/database/background_migration/batched_migration_runner.rb
@@ -144,9 +144,9 @@ module Gitlab
end
def adjust_migration(active_migration)
- signal = HealthStatus.evaluate(active_migration)
+ signals = HealthStatus.evaluate(active_migration)
- if signal.is_a?(HealthStatus::Signals::Stop)
+ if signals.any?(&:stop?)
active_migration.hold!
else
active_migration.optimize!
diff --git a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
index 5f4b2be3da8..ad747a8131d 100644
--- a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
+++ b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb
@@ -64,9 +64,10 @@ module Gitlab
batch_column: tracking_record.migration_column_name,
sub_batch_size: tracking_record.sub_batch_size,
pause_ms: tracking_record.pause_ms,
+ job_arguments: tracking_record.migration_job_arguments,
connection: connection)
- job_instance.perform(*tracking_record.migration_job_arguments)
+ job_instance.perform
job_instance
end
diff --git a/lib/gitlab/database/background_migration/health_status.rb b/lib/gitlab/database/background_migration/health_status.rb
index 01f9c5eb5fd..9a283074b32 100644
--- a/lib/gitlab/database/background_migration/health_status.rb
+++ b/lib/gitlab/database/background_migration/health_status.rb
@@ -4,21 +4,29 @@ module Gitlab
module Database
module BackgroundMigration
module HealthStatus
+ DEFAULT_INIDICATORS = [
+ Indicators::AutovacuumActiveOnTable,
+ Indicators::WriteAheadLog
+ ].freeze
+
# Rather than passing along the migration, we use a more explicitly defined context
- Context = Struct.new(:tables)
+ Context = Struct.new(:connection, :tables)
- def self.evaluate(migration, indicator = Indicators::AutovacuumActiveOnTable)
- signal = begin
- indicator.new(migration.health_context).evaluate
- rescue StandardError => e
- Gitlab::ErrorTracking.track_exception(e, migration_id: migration.id,
- job_class_name: migration.job_class_name)
- Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})")
- end
+ def self.evaluate(migration, indicators = DEFAULT_INIDICATORS)
+ indicators.map do |indicator|
+ signal = begin
+ indicator.new(migration.health_context).evaluate
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, migration_id: migration.id,
+ job_class_name: migration.job_class_name)
- log_signal(signal, migration) if signal.log_info?
+ Signals::Unknown.new(indicator, reason: "unexpected error: #{e.message} (#{e.class})")
+ end
- signal
+ log_signal(signal, migration) if signal.log_info?
+
+ signal
+ end
end
def self.log_signal(signal, migration)
diff --git a/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb b/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb
new file mode 100644
index 00000000000..d2fb0a8b751
--- /dev/null
+++ b/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module BackgroundMigration
+ module HealthStatus
+ module Indicators
+ class WriteAheadLog
+ include Gitlab::Utils::StrongMemoize
+
+ LIMIT = 42
+ PENDING_WAL_COUNT_SQL = <<~SQL
+ WITH
+ current_wal_file AS (
+ SELECT pg_walfile_name(pg_current_wal_insert_lsn()) AS pg_walfile_name
+ ),
+ current_wal AS (
+ SELECT
+ ('x' || substring(pg_walfile_name, 9, 8))::bit(32)::int AS log,
+ ('x' || substring(pg_walfile_name, 17, 8))::bit(32)::int AS seg,
+ pg_walfile_name
+ FROM current_wal_file
+ ),
+ archive_wal AS (
+ SELECT
+ ('x' || substring(last_archived_wal, 9, 8))::bit(32)::int AS log,
+ ('x' || substring(last_archived_wal, 17, 8))::bit(32)::int AS seg,
+ last_archived_wal
+ FROM pg_stat_archiver
+ )
+ SELECT ((current_wal.log - archive_wal.log) * 256) + (current_wal.seg - archive_wal.seg) AS pending_wal_count
+ FROM current_wal, archive_wal
+ SQL
+
+ def initialize(context)
+ @connection = context.connection
+ end
+
+ def evaluate
+ return Signals::NotAvailable.new(self.class, reason: 'indicator disabled') unless enabled?
+
+ unless pending_wal_count
+ return Signals::NotAvailable.new(self.class, reason: 'WAL archive queue can not be calculated')
+ end
+
+ if pending_wal_count > LIMIT
+ Signals::Stop.new(self.class, reason: "WAL archive queue is too big")
+ else
+ Signals::Normal.new(self.class, reason: 'WAL archive queue is within limit')
+ end
+ end
+
+ private
+
+ attr_reader :connection
+
+ def enabled?
+ Feature.enabled?(:batched_migrations_health_status_wal, type: :ops)
+ end
+
+ # Returns number of WAL segments pending archival
+ def pending_wal_count
+ strong_memoize(:pending_wal_count) do
+ Gitlab::Database::LoadBalancing::Session.current.use_primary do
+ connection.execute(PENDING_WAL_COUNT_SQL).to_a.first&.fetch('pending_wal_count')
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/background_migration/health_status/signals.rb b/lib/gitlab/database/background_migration/health_status/signals.rb
index 6cd0ebd1bd0..be741a9d91b 100644
--- a/lib/gitlab/database/background_migration/health_status/signals.rb
+++ b/lib/gitlab/database/background_migration/health_status/signals.rb
@@ -22,6 +22,10 @@ module Gitlab
def log_info?
false
end
+
+ def stop?
+ false
+ end
# :nocov:
private
@@ -38,6 +42,10 @@ module Gitlab
def log_info?
true
end
+
+ def stop?
+ true
+ end
# :nocov:
end
diff --git a/lib/gitlab/database/bulk_update.rb b/lib/gitlab/database/bulk_update.rb
index b1f9da30585..d68be19047e 100644
--- a/lib/gitlab/database/bulk_update.rb
+++ b/lib/gitlab/database/bulk_update.rb
@@ -157,7 +157,7 @@ module Gitlab
def self.execute(columns, mapping, &to_class)
raise ArgumentError if mapping.blank?
- entries_by_class = mapping.group_by { |k, v| block_given? ? to_class.call(k) : k.class }
+ entries_by_class = mapping.group_by { |k, v| to_class ? to_class.call(k) : k.class }
entries_by_class.each do |model, entries|
Setter.new(model, columns, entries).update!
diff --git a/lib/gitlab/database/dynamic_model_helpers.rb b/lib/gitlab/database/dynamic_model_helpers.rb
index ad7dea8f0d9..2deb89a0b84 100644
--- a/lib/gitlab/database/dynamic_model_helpers.rb
+++ b/lib/gitlab/database/dynamic_model_helpers.rb
@@ -32,7 +32,7 @@ module Gitlab
def each_batch_range(table_name, connection:, scope: ->(table) { table.all }, of: BATCH_SIZE)
each_batch(table_name, connection: connection, scope: scope, of: of) do |batch|
- yield batch.pluck('MIN(id), MAX(id)').first
+ yield batch.pick('MIN(id), MAX(id)')
end
end
end
diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml
index 4a467d18f0a..d05eee7d6e6 100644
--- a/lib/gitlab/database/gitlab_schemas.yml
+++ b/lib/gitlab/database/gitlab_schemas.yml
@@ -300,6 +300,7 @@ licenses: :gitlab_main
lists: :gitlab_main
list_user_preferences: :gitlab_main
loose_foreign_keys_deleted_records: :gitlab_shared
+member_roles: :gitlab_main
member_tasks: :gitlab_main
members: :gitlab_main
merge_request_assignees: :gitlab_main
@@ -323,6 +324,10 @@ metrics_dashboard_annotations: :gitlab_main
metrics_users_starred_dashboards: :gitlab_main
milestone_releases: :gitlab_main
milestones: :gitlab_main
+ml_candidates: :gitlab_main
+ml_experiments: :gitlab_main
+ml_candidate_metrics: :gitlab_main
+ml_candidate_params: :gitlab_main
namespace_admin_notes: :gitlab_main
namespace_aggregation_schedules: :gitlab_main
namespace_bans: :gitlab_main
@@ -331,6 +336,7 @@ namespace_package_settings: :gitlab_main
namespace_root_storage_statistics: :gitlab_main
namespace_ci_cd_settings: :gitlab_main
namespace_settings: :gitlab_main
+namespace_details: :gitlab_main
namespaces: :gitlab_main
namespaces_sync_events: :gitlab_main
namespace_statistics: :gitlab_main
@@ -529,6 +535,7 @@ user_custom_attributes: :gitlab_main
user_details: :gitlab_main
user_follow_users: :gitlab_main
user_group_callouts: :gitlab_main
+user_project_callouts: :gitlab_main
user_highest_roles: :gitlab_main
user_interacted_projects: :gitlab_main
user_permission_export_uploads: :gitlab_main
diff --git a/lib/gitlab/database/lock_writes_manager.rb b/lib/gitlab/database/lock_writes_manager.rb
new file mode 100644
index 00000000000..cd483d616bb
--- /dev/null
+++ b/lib/gitlab/database/lock_writes_manager.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class LockWritesManager
+ TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write'
+
+ def initialize(table_name:, connection:, database_name:, logger: nil)
+ @table_name = table_name
+ @connection = connection
+ @database_name = database_name
+ @logger = logger
+ end
+
+ def lock_writes
+ logger&.info "Database: '#{database_name}', Table: '#{table_name}': Lock Writes".color(:yellow)
+ sql = <<-SQL
+ DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name};
+ CREATE TRIGGER #{write_trigger_name(table_name)}
+ BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE
+ ON #{table_name}
+ FOR EACH STATEMENT EXECUTE FUNCTION #{TRIGGER_FUNCTION_NAME}();
+ SQL
+
+ with_retries(connection) do
+ connection.execute(sql)
+ end
+ end
+
+ def unlock_writes
+ logger&.info "Database: '#{database_name}', Table: '#{table_name}': Allow Writes".color(:green)
+ sql = <<-SQL
+ DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name}
+ SQL
+
+ with_retries(connection) do
+ connection.execute(sql)
+ end
+ end
+
+ private
+
+ attr_reader :table_name, :connection, :database_name, :logger
+
+ def with_retries(connection, &block)
+ with_statement_timeout_retries do
+ with_lock_retries(connection) do
+ yield
+ end
+ end
+ end
+
+ def with_statement_timeout_retries(times = 5)
+ current_iteration = 1
+ begin
+ yield
+ rescue ActiveRecord::QueryCanceled => err # rubocop:disable Database/RescueQueryCanceled
+ if current_iteration <= times
+ current_iteration += 1
+ retry
+ else
+ raise err
+ end
+ end
+ end
+
+ def with_lock_retries(connection, &block)
+ Gitlab::Database::WithLockRetries.new(
+ klass: "gitlab:db:lock_writes",
+ logger: logger || Gitlab::AppLogger,
+ connection: connection
+ ).run(&block)
+ end
+
+ def write_trigger_name(table_name)
+ "gitlab_schema_write_trigger_for_#{table_name}"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 4bb1d71ce18..db39524f4f6 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -505,14 +505,14 @@ module Gitlab
# case another unique integer column can be used. Example: :user_id
#
# rubocop: disable Metrics/AbcSize
- def update_column_in_batches(table, column, value, batch_size: nil, batch_column_name: :id)
+ def update_column_in_batches(table_name, column, value, batch_size: nil, batch_column_name: :id, disable_lock_writes: false)
if transaction_open?
raise 'update_column_in_batches can not be run inside a transaction, ' \
'you can disable transactions by calling disable_ddl_transaction! ' \
'in the body of your migration class'
end
- table = Arel::Table.new(table)
+ table = Arel::Table.new(table_name)
count_arel = table.project(Arel.star.count.as('count'))
count_arel = yield table, count_arel if block_given?
@@ -559,7 +559,10 @@ module Gitlab
update_arel = yield table, update_arel if block_given?
- execute(update_arel.to_sql)
+ transaction do
+ execute("SELECT set_config('lock_writes.#{table_name}', 'false', true)") if disable_lock_writes
+ execute(update_arel.to_sql)
+ end
# There are no more rows left to update.
break unless stop_row
@@ -1666,7 +1669,9 @@ into similar problems in the future (e.g. when new tables are created).
end
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
- update_column_in_batches(table, new, old_value, batch_column_name: batch_column_name)
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do
+ update_column_in_batches(table, new, old_value, batch_column_name: batch_column_name, disable_lock_writes: true)
+ end
end
add_not_null_constraint(table, new) unless old_col.null
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb
index 9bffed43077..25e75a10bb3 100644
--- a/lib/gitlab/database/migrations/background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/background_migration_helpers.rb
@@ -76,7 +76,7 @@ module Gitlab
max = relation.arel_table[primary_column_name].maximum
min = relation.arel_table[primary_column_name].minimum
- start_id, end_id = relation.pluck(min, max).first
+ start_id, end_id = relation.pick(min, max)
# `SingleDatabaseWorker.bulk_perform_in` schedules all jobs for
# the same time, which is not helpful in most cases where we wish to
diff --git a/lib/gitlab/database/migrations/base_background_runner.rb b/lib/gitlab/database/migrations/base_background_runner.rb
index 2772502140e..a9440cafd30 100644
--- a/lib/gitlab/database/migrations/base_background_runner.rb
+++ b/lib/gitlab/database/migrations/base_background_runner.rb
@@ -38,7 +38,7 @@ module Gitlab
per_background_migration_result_dir = File.join(@result_dir, migration_name)
instrumentation = Instrumentation.new(result_dir: per_background_migration_result_dir)
- batch_names = (1..).each.lazy.map { |i| "batch_#{i}"}
+ batch_names = (1..).each.lazy.map { |i| "batch_#{i}" }
jobs.shuffle.each do |j|
break if run_until <= Time.current
diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
index 936b986ea07..363fd0598f9 100644
--- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
@@ -24,7 +24,7 @@ module Gitlab
# class must be present in the Gitlab::BackgroundMigration module, and the batch class (if specified) must be
# present in the Gitlab::BackgroundMigration::BatchingStrategies module.
#
- # If migration with same job_class_name, table_name, column_name, and job_aruments already exists, this helper
+ # If migration with same job_class_name, table_name, column_name, and job_arguments already exists, this helper
# will log an warning and not create a new one.
#
# job_class_name - The background migration job class as a string
@@ -107,6 +107,11 @@ module Gitlab
status_event: status_event
)
+ if migration.job_class.respond_to?(:job_arguments_count) && migration.job_class.job_arguments_count != job_arguments.count
+ raise "Wrong number of job arguments for #{migration.job_class_name} " \
+ "(given #{job_arguments.count}, expected #{migration.job_class.job_arguments_count})"
+ end
+
# Below `BatchedMigration` attributes were introduced after the
# initial `batched_background_migrations` table was created, so any
# migrations that ran relying on initial table schema would not know
diff --git a/lib/gitlab/database/partitioning/sliding_list_strategy.rb b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
index 5cf32d3272c..4b5349f0327 100644
--- a/lib/gitlab/database/partitioning/sliding_list_strategy.rb
+++ b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
@@ -77,7 +77,6 @@ module Gitlab
end
def validate_and_fix
- return unless Feature.enabled?(:fix_sliding_list_partitioning)
return if no_partitions_exist?
old_default_value = current_default_value
diff --git a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
index 9cab2c51b3f..dcf457b9d63 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
@@ -25,7 +25,7 @@ module Gitlab
parent_batch_relation = relation_scoped_to_range(source_table, source_column, start_id, stop_id)
parent_batch_relation.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
- sub_start_id, sub_stop_id = sub_batch.pluck(Arel.sql("MIN(#{source_column}), MAX(#{source_column})")).first
+ sub_start_id, sub_stop_id = sub_batch.pick(Arel.sql("MIN(#{source_column}), MAX(#{source_column})"))
bulk_copy.copy_between(sub_start_id, sub_stop_id)
sleep(PAUSE_SECONDS)
diff --git a/lib/gitlab/database/postgres_hll/buckets.rb b/lib/gitlab/database/postgres_hll/buckets.rb
index 76818bbf340..cbc9544d905 100644
--- a/lib/gitlab/database/postgres_hll/buckets.rb
+++ b/lib/gitlab/database/postgres_hll/buckets.rb
@@ -38,7 +38,7 @@ module Gitlab
#
# @param other_buckets_hash hash with HyperLogLog structure representation
def merge_hash!(other_buckets_hash)
- buckets.merge!(other_buckets_hash) {|_key, old, new| new > old ? new : old }
+ buckets.merge!(other_buckets_hash) { |_key, old, new| new > old ? new : old }
end
# Serialize instance underlying HyperLogLog structure to JSON format, that can be stored in various persistence layers
@@ -61,7 +61,7 @@ module Gitlab
num_uniques = (
((TOTAL_BUCKETS**2) * (0.7213 / (1 + 1.079 / TOTAL_BUCKETS))) /
- (num_zero_buckets + buckets.values.sum { |bucket_hash| 2**(-1 * bucket_hash)} )
+ (num_zero_buckets + buckets.values.sum { |bucket_hash| 2**(-1 * bucket_hash) } )
).to_i
if num_zero_buckets > 0 && num_uniques < 2.5 * TOTAL_BUCKETS
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index e13dd3b2058..b96dffc99ac 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -27,6 +27,7 @@ module Gitlab
# Hack: Before we do actual reindexing work, create async indexes
Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops)
+ Gitlab::Database::AsyncIndexes.drop_pending_indexes! if Feature.enabled?(:database_async_index_destruction, type: :ops)
automatic_reindexing
end
diff --git a/lib/gitlab/database/reindexing/reindex_concurrently.rb b/lib/gitlab/database/reindexing/reindex_concurrently.rb
index 152935bd734..60fa4deda39 100644
--- a/lib/gitlab/database/reindexing/reindex_concurrently.rb
+++ b/lib/gitlab/database/reindexing/reindex_concurrently.rb
@@ -20,7 +20,7 @@ module Gitlab
def perform
raise ReindexError, 'indexes serving an exclusion constraint are currently not supported' if index.exclusion?
- raise ReindexError, 'index is a left-over temporary index from a previous reindexing run' if index.name =~ /#{TEMPORARY_INDEX_PATTERN}/
+ raise ReindexError, 'index is a left-over temporary index from a previous reindexing run' if index.name =~ /#{TEMPORARY_INDEX_PATTERN}/o
# Expression indexes require additional statistics in `pg_statistic`:
# select * from pg_statistic where starelid = (select oid from pg_class where relname = 'some_index');
@@ -81,10 +81,10 @@ module Gitlab
# Example lingering index name: some_index_ccnew1
# Example prefix: 'some_index'
- prefix = lingering_index.name.gsub(/#{TEMPORARY_INDEX_PATTERN}/, '')
+ prefix = lingering_index.name.gsub(/#{TEMPORARY_INDEX_PATTERN}/o, '')
# Example suffix: '_ccnew1'
- suffix = lingering_index.name.match(/#{TEMPORARY_INDEX_PATTERN}/)[0]
+ suffix = lingering_index.name.match(/#{TEMPORARY_INDEX_PATTERN}/o)[0]
# Only remove if the lingering index name could have been chosen
# as a result of a REINDEX operation (considering that PostgreSQL
diff --git a/lib/gitlab/database/with_lock_retries.rb b/lib/gitlab/database/with_lock_retries.rb
index f2c5bb9088f..3206c5626c3 100644
--- a/lib/gitlab/database/with_lock_retries.rb
+++ b/lib/gitlab/database/with_lock_retries.rb
@@ -83,7 +83,7 @@ module Gitlab
# @param [Boolean] raise_on_exhaustion whether to raise `AttemptsExhaustedError` when exhausting max attempts
# @param [Proc] block of code that will be executed
def run(raise_on_exhaustion: false, &block)
- raise 'no block given' unless block_given?
+ raise 'no block given' unless block
@block = block
diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb
index 76855f2950d..6d114de8ae8 100644
--- a/lib/gitlab/dependency_linker/base_linker.rb
+++ b/lib/gitlab/dependency_linker/base_linker.rb
@@ -34,9 +34,9 @@ module Gitlab
return if external_ref =~ GIT_INVALID_URL_REGEX
case external_ref
- when /\A#{URL_REGEX}\z/
+ when /\A#{URL_REGEX}\z/o
external_ref
- when /\A#{REPO_REGEX}\z/
+ when /\A#{REPO_REGEX}\z/o
github_url(external_ref)
else
package_url(name)
diff --git a/lib/gitlab/dependency_linker/cargo_toml_linker.rb b/lib/gitlab/dependency_linker/cargo_toml_linker.rb
index 57e0a5f4699..cba4319ce83 100644
--- a/lib/gitlab/dependency_linker/cargo_toml_linker.rb
+++ b/lib/gitlab/dependency_linker/cargo_toml_linker.rb
@@ -39,7 +39,11 @@ module Gitlab
end
def toml
- @toml ||= TomlRB.parse(plain_text) rescue nil
+ @toml ||= begin
+ TomlRB.parse(plain_text)
+ rescue StandardError
+ nil
+ end
end
end
end
diff --git a/lib/gitlab/dependency_linker/composer_json_linker.rb b/lib/gitlab/dependency_linker/composer_json_linker.rb
index 4b8862b31ee..965ed8bb95e 100644
--- a/lib/gitlab/dependency_linker/composer_json_linker.rb
+++ b/lib/gitlab/dependency_linker/composer_json_linker.rb
@@ -13,7 +13,7 @@ module Gitlab
end
def package_url(name)
- "https://packagist.org/packages/#{name}" if name =~ /\A#{REPO_REGEX}\z/
+ "https://packagist.org/packages/#{name}" if name =~ /\A#{REPO_REGEX}\z/o
end
end
end
diff --git a/lib/gitlab/dependency_linker/godeps_json_linker.rb b/lib/gitlab/dependency_linker/godeps_json_linker.rb
index 9166e9091ac..049a807b760 100644
--- a/lib/gitlab/dependency_linker/godeps_json_linker.rb
+++ b/lib/gitlab/dependency_linker/godeps_json_linker.rb
@@ -12,10 +12,10 @@ module Gitlab
def link_dependencies
link_json('ImportPath') do |path|
case path
- when %r{\A(?<repo>github\.com/#{REPO_REGEX})/(?<path>.+)\z}
+ when %r{\A(?<repo>github\.com/#{REPO_REGEX})/(?<path>.+)\z}o
"https://#{$~[:repo]}/tree/master/#{$~[:path]}"
- when %r{\A(?<repo>gitlab\.com/#{NESTED_REPO_REGEX})\.git/(?<path>.+)\z},
- %r{\A(?<repo>gitlab\.com/#{REPO_REGEX})/(?<path>.+)\z}
+ when %r{\A(?<repo>gitlab\.com/#{NESTED_REPO_REGEX})\.git/(?<path>.+)\z}o,
+ %r{\A(?<repo>gitlab\.com/#{REPO_REGEX})/(?<path>.+)\z}o
"https://#{$~[:repo]}/-/tree/master/#{$~[:path]}"
when /\Agolang\.org/
diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb
index 86dc7efb0d9..15c17132283 100644
--- a/lib/gitlab/dependency_linker/json_linker.rb
+++ b/lib/gitlab/dependency_linker/json_linker.rb
@@ -39,7 +39,11 @@ module Gitlab
end
def json
- @json ||= Gitlab::Json.parse(plain_text) rescue nil
+ @json ||= begin
+ Gitlab::Json.parse(plain_text)
+ rescue StandardError
+ nil
+ end
end
end
end
diff --git a/lib/gitlab/dependency_linker/podspec_linker.rb b/lib/gitlab/dependency_linker/podspec_linker.rb
index 14abd3999c4..f6da17efff4 100644
--- a/lib/gitlab/dependency_linker/podspec_linker.rb
+++ b/lib/gitlab/dependency_linker/podspec_linker.rb
@@ -14,10 +14,10 @@ module Gitlab
def link_dependencies
link_method_call('homepage', URL_REGEX, &:itself)
- link_regex(/(git:|:git\s*=>)\s*['"](?<name>#{URL_REGEX})['"]/, &:itself)
+ link_regex(/(git:|:git\s*=>)\s*['"](?<name>#{URL_REGEX})['"]/o, &:itself)
link_method_call('license', &method(:license_url))
- link_regex(/license\s*=\s*\{\s*(type:|:type\s*=>)\s*#{STRING_REGEX}/, &method(:license_url))
+ link_regex(/license\s*=\s*\{\s*(type:|:type\s*=>)\s*#{STRING_REGEX}/o, &method(:license_url))
link_method_call('dependency', &method(:package_url))
end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 8c55652da43..5583c896803 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -41,8 +41,7 @@ module Gitlab
@unfolded = false
# Ensure items are collected in the the batch
- new_blob_lazy
- old_blob_lazy
+ add_blobs_to_batch_loader
end
def use_semantic_ipynb_diff?
@@ -382,6 +381,11 @@ module Gitlab
file_path.ends_with?('.ipynb')
end
+ def add_blobs_to_batch_loader
+ new_blob_lazy
+ old_blob_lazy
+ end
+
private
def diffable_by_attribute?
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 8e9dc3a305f..7cfe0086f57 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -6,7 +6,7 @@ module Gitlab
include Gitlab::Utils::Gzip
include Gitlab::Utils::StrongMemoize
- EXPIRATION = 1.week
+ EXPIRATION = 1.day
VERSION = 2
delegate :diffable, to: :@diff_collection
@@ -69,14 +69,14 @@ module Gitlab
def key
strong_memoize(:redis_key) do
- [
- 'highlighted-diff-files',
- diffable.cache_key,
- VERSION,
+ options = [
diff_options,
Feature.enabled?(:use_marker_ranges, diffable.project),
Feature.enabled?(:diff_line_syntax_highlighting, diffable.project)
- ].join(":")
+ ]
+ options_for_key = OpenSSL::Digest::SHA256.hexdigest(options.join)
+
+ ['highlighted-diff-files', diffable.cache_key, VERSION, options_for_key].join(":")
end
end
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index adb711ca89f..924c28e3db5 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -28,9 +28,11 @@ module Gitlab
if line =~ /^@@ -/
type = "match"
- line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
- line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
+ diff_hunk = Gitlab::WordDiff::Segments::DiffHunk.new(line)
+ line_old = diff_hunk.pos_old
+ line_new = diff_hunk.pos_new
+ # not using diff_hunk.first_line? because of defaults
next if line_old <= 1 && line_new <= 1 # top of file
yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, parent_file: diff_file)
diff --git a/lib/gitlab/diff/rendered/notebook/diff_file.rb b/lib/gitlab/diff/rendered/notebook/diff_file.rb
index 3e1652bd318..31cbdc156cf 100644
--- a/lib/gitlab/diff/rendered/notebook/diff_file.rb
+++ b/lib/gitlab/diff/rendered/notebook/diff_file.rb
@@ -56,7 +56,7 @@ module Gitlab
)
lines.zip(line_positions_at_source_diff(lines, transformed_blocks))
- .map { |line, positions| mutate_line(line, positions, lines_in_source)}
+ .map { |line, positions| mutate_line(line, positions, lines_in_source) }
end
end
diff --git a/lib/gitlab/diff/rendered/notebook/diff_file_helper.rb b/lib/gitlab/diff/rendered/notebook/diff_file_helper.rb
index f381792953e..ad709a79f30 100644
--- a/lib/gitlab/diff/rendered/notebook/diff_file_helper.rb
+++ b/lib/gitlab/diff/rendered/notebook/diff_file_helper.rb
@@ -77,8 +77,8 @@ module Gitlab
def lines_in_source_diff(source_diff_lines, is_deleted_file, is_added_file)
{
- from: is_added_file ? Set[] : source_diff_lines.map {|l| l.old_pos}.to_set,
- to: is_deleted_file ? Set[] : source_diff_lines.map {|l| l.new_pos}.to_set
+ from: is_added_file ? Set[] : source_diff_lines.map { |l| l.old_pos }.to_set,
+ to: is_deleted_file ? Set[] : source_diff_lines.map { |l| l.new_pos }.to_set
}
end
diff --git a/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512.rb b/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512.rb
new file mode 100644
index 00000000000..4bfb5f9e64c
--- /dev/null
+++ b/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module DoorkeeperSecretStoring
+ class Pbkdf2Sha512 < ::Doorkeeper::SecretStoring::Base
+ STRETCHES = 20_000
+ # An empty salt is used because we need to look tokens up solely by
+ # their hashed value. Additionally, tokens are always cryptographically
+ # pseudo-random and unique, therefore salting provides no
+ # additional security.
+ SALT = ''
+
+ def self.transform_secret(plain_secret)
+ return plain_secret unless Feature.enabled?(:hash_oauth_tokens)
+
+ Devise::Pbkdf2Encryptable::Encryptors::Pbkdf2Sha512.digest(plain_secret, STRETCHES, SALT)
+ end
+
+ ##
+ # Determines whether this strategy supports restoring
+ # secrets from the database. This allows detecting users
+ # trying to use a non-restorable strategy with +reuse_access_tokens+.
+ def self.allows_restoring_secrets?
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/email/message/in_product_marketing/helper.rb b/lib/gitlab/email/message/in_product_marketing/helper.rb
index 0a0e55c2999..73d1e0743cc 100644
--- a/lib/gitlab/email/message/in_product_marketing/helper.rb
+++ b/lib/gitlab/email/message/in_product_marketing/helper.rb
@@ -67,7 +67,7 @@ module Gitlab
def list(array)
case format
when :html
- tag.ul { array.map { |item| tag.li item} }
+ tag.ul { array.map { |item| tag.li item } }
else
'- ' + array.join("\n- ")
end
diff --git a/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb b/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb
index e3eae20c520..cc822e4c10b 100644
--- a/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb
+++ b/lib/gitlab/error_tracking/error_repository/open_api_strategy.rb
@@ -13,6 +13,7 @@ module Gitlab
config.scheme = api_url.scheme
config.host = [api_url.host, api_url.port].compact.join(':')
config.server_index = nil
+ config.api_key['internalToken'] = api_key
config.logger = Gitlab::AppLogger
end
end
@@ -25,7 +26,7 @@ module Gitlab
end
def find_error(id)
- api = open_api::ErrorsApi.new
+ api = build_api_client
error = api.get_error(project_id, id)
to_sentry_detailed_error(error)
@@ -43,7 +44,7 @@ module Gitlab
limit: limit
}.compact
- api = open_api::ErrorsApi.new
+ api = build_api_client
errors, _status, headers = api.list_errors_with_http_info(project_id, opts)
pagination = pagination_from_headers(headers)
@@ -64,7 +65,7 @@ module Gitlab
event = newest_event_for(id)
return unless event
- api = open_api::ErrorsApi.new
+ api = build_api_client
error = api.get_error(project_id, id)
return unless error
@@ -79,7 +80,7 @@ module Gitlab
body = open_api::ErrorUpdatePayload.new(opts)
- api = open_api::ErrorsApi.new
+ api = build_api_client
api.update_error(project_id, id, body)
true
@@ -100,7 +101,7 @@ module Gitlab
config.base_path
].join('')
- "#{base_url}/projects/api/#{project_id}"
+ "#{base_url}/projects/#{project_id}"
end
private
@@ -108,7 +109,7 @@ module Gitlab
def event_for(id, sort:)
opts = { sort: sort, limit: 1 }
- api = open_api::ErrorsApi.new
+ api = build_api_client
api.list_events(project_id, id, opts).first
rescue ErrorTrackingOpenAPI::ApiError => e
log_exception(e)
@@ -234,6 +235,14 @@ module Gitlab
URI(url)
end
+ def api_key
+ Gitlab::CurrentSettings.current_application_settings.error_tracking_access_token
+ end
+
+ def build_api_client
+ open_api::ErrorsApi.new
+ end
+
def log_exception(exception)
params = {
http_code: exception.code,
diff --git a/lib/gitlab/event_store.rb b/lib/gitlab/event_store.rb
index 4955e873688..b45970cb45a 100644
--- a/lib/gitlab/event_store.rb
+++ b/lib/gitlab/event_store.rb
@@ -40,6 +40,17 @@ module Gitlab
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Pages::PageDeletedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectDeletedEvent
store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Projects::ProjectCreatedEvent
+ 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: ::Groups::GroupTransferedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupPathChangedEvent
+ store.subscribe ::Pages::InvalidateDomainCacheWorker, to: ::Groups::GroupDeletedEvent
+
+ store.subscribe ::MergeRequests::CreateApprovalEventWorker, to: ::MergeRequests::ApprovedEvent
+ store.subscribe ::MergeRequests::CreateApprovalNoteWorker, to: ::MergeRequests::ApprovedEvent
+ store.subscribe ::MergeRequests::ResolveTodosAfterApprovalWorker, to: ::MergeRequests::ApprovedEvent
+ store.subscribe ::MergeRequests::ExecuteApprovalHooksWorker, to: ::MergeRequests::ApprovedEvent
end
private_class_method :configure!
end
diff --git a/lib/gitlab/exclusive_lease_helpers/sleeping_lock.rb b/lib/gitlab/exclusive_lease_helpers/sleeping_lock.rb
index 52035220a71..7ef3e738481 100644
--- a/lib/gitlab/exclusive_lease_helpers/sleeping_lock.rb
+++ b/lib/gitlab/exclusive_lease_helpers/sleeping_lock.rb
@@ -5,6 +5,8 @@ module Gitlab
# Wrapper around ExclusiveLease that adds retry logic
class SleepingLock
delegate :cancel, to: :@lease
+ MAX_ATTEMPTS = 65
+ DEFAULT_ATTEMPTS = 10
def initialize(key, timeout:, delay:)
@lease = ::Gitlab::ExclusiveLease.new(key, timeout: timeout)
@@ -12,9 +14,9 @@ module Gitlab
@attempts = 0
end
- def obtain(max_attempts)
+ def obtain(max_attempts = DEFAULT_ATTEMPTS)
until held?
- raise FailedToObtainLockError, 'Failed to obtain a lock' if attempts >= max_attempts
+ raise FailedToObtainLockError, 'Failed to obtain a lock' if attempts >= [max_attempts, MAX_ATTEMPTS].min
sleep(sleep_sec) unless first_attempt?
try_obtain
diff --git a/lib/gitlab/form_builders/gitlab_ui_form_builder.rb b/lib/gitlab/form_builders/gitlab_ui_form_builder.rb
index 9174ca165cd..ea98f6b2eec 100644
--- a/lib/gitlab/form_builders/gitlab_ui_form_builder.rb
+++ b/lib/gitlab/form_builders/gitlab_ui_form_builder.rb
@@ -3,6 +3,20 @@
module Gitlab
module FormBuilders
class GitlabUiFormBuilder < ActionView::Helpers::FormBuilder
+ def submit(value = nil, options = {})
+ if options[:pajamas_button]
+ @template.render Pajamas::ButtonComponent.new(
+ variant: :confirm,
+ type: :submit,
+ button_options: options.except(:pajamas_button)
+ ) do
+ value
+ end
+ else
+ super
+ end
+ end
+
def gitlab_ui_checkbox_component(
method,
label = nil,
@@ -45,6 +59,10 @@ module Gitlab
).render_in(@template, &block)
end
+ def gitlab_ui_datepicker(method, options = {})
+ @template.text_field @object_name, method, options.merge(class: "datepicker form-control gl-form-input")
+ end
+
private
def format_options(options)
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 882bd57eb1d..4b9f2ababc8 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -47,11 +47,11 @@ module Gitlab
end
def tag_ref?(ref)
- ref =~ /^#{TAG_REF_PREFIX}.+/
+ ref =~ /^#{TAG_REF_PREFIX}.+/o
end
def branch_ref?(ref)
- ref =~ /^#{BRANCH_REF_PREFIX}.+/
+ ref =~ /^#{BRANCH_REF_PREFIX}.+/o
end
def blank_ref?(ref)
diff --git a/lib/gitlab/git/remote_repository.rb b/lib/gitlab/git/remote_repository.rb
deleted file mode 100644
index 0ea009930b0..00000000000
--- a/lib/gitlab/git/remote_repository.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Git
- #
- # When a Gitaly call involves two repositories instead of one we cannot
- # assume that both repositories are on the same Gitaly server. In this
- # case we need to make a distinction between the repository that the
- # call is being made on (a Repository instance), and the "other"
- # repository (a RemoteRepository instance). This is the reason why we
- # have the RemoteRepository class in Gitlab::Git.
- #
- # When you make changes, be aware that gitaly-ruby sub-classes this
- # class.
- #
- class RemoteRepository
- attr_reader :relative_path, :gitaly_repository
-
- def initialize(repository)
- @relative_path = repository.relative_path
- @gitaly_repository = repository.gitaly_repository
-
- # These instance variables will not be available in gitaly-ruby, where
- # we have no disk access to this repository.
- @repository = repository
- end
-
- def empty?
- # We will override this implementation in gitaly-ruby because we cannot
- # use '@repository' there.
- #
- # Caches and memoization used on the Rails side
- !@repository.exists? || @repository.empty?
- end
-
- def commit_id(revision)
- # We will override this implementation in gitaly-ruby because we cannot
- # use '@repository' there.
- @repository.commit(revision)&.sha
- end
-
- def branch_exists?(name)
- # We will override this implementation in gitaly-ruby because we cannot
- # use '@repository' there.
- @repository.branch_exists?(name)
- end
-
- # Compares self to a Gitlab::Git::Repository. This implementation uses
- # 'self.gitaly_repository' so that it will also work in the
- # GitalyRemoteRepository subclass defined in gitaly-ruby.
- def same_repository?(other_repository)
- gitaly_repository.storage_name == other_repository.storage &&
- gitaly_repository.relative_path == other_repository.relative_path
- end
-
- def path
- @repository.path
- end
-
- private
-
- # Must return an object that responds to 'address' and 'storage'.
- def gitaly_client
- Gitlab::GitalyClient
- end
-
- def storage
- gitaly_repository.storage_name
- end
- end
- end
-end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index d7f892ae9d9..ad655fedb6d 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -135,6 +135,13 @@ module Gitlab
gitaly_ref_client.find_tag(name)
end
rescue CommandError
+ # Gitaly used to return an `Internal` error in case the tag wasn't found, which is being translated to
+ # `CommandError` by the wrapper. This has been converted in v15.3.0 to instead return a structured
+ # error with a `tag_not_found` error, so rescuing from `Internal` errors can be removed in v15.4.0 and
+ # later.
+ rescue Gitlab::Git::UnknownRef
+ # This is the new error returned by `find_tag`, which knows to translate the structured error returned
+ # by Gitaly when the tag does not exist.
end
def local_branches(sort_by: nil, pagination_params: nil)
@@ -910,7 +917,7 @@ module Gitlab
def multi_action(
user, branch_name:, message:, actions:,
author_email: nil, author_name: nil,
- start_branch_name: nil, start_sha: nil, start_repository: self,
+ start_branch_name: nil, start_sha: nil, start_repository: nil,
force: false)
wrapped_gitaly_errors do
@@ -930,6 +937,12 @@ module Gitlab
gitaly_repository_client.set_full_path(full_path)
end
+ def full_path
+ wrapped_gitaly_errors do
+ gitaly_repository_client.full_path
+ end
+ end
+
def disconnect_alternates
wrapped_gitaly_errors do
gitaly_repository_client.disconnect_alternates
diff --git a/lib/gitlab/git/rugged_impl/use_rugged.rb b/lib/gitlab/git/rugged_impl/use_rugged.rb
index dae208e6955..632b4133f2e 100644
--- a/lib/gitlab/git/rugged_impl/use_rugged.rb
+++ b/lib/gitlab/git/rugged_impl/use_rugged.rb
@@ -10,6 +10,7 @@ module Gitlab
# Disable Rugged auto-detect(can_use_disk?) when Puma threads>1
# https://gitlab.com/gitlab-org/gitlab/issues/119326
return false if running_puma_with_multiple_threads?
+ return false if Feature.enabled?(:skip_rugged_auto_detect, type: :ops)
Gitlab::GitalyClient.can_use_disk?(repo.storage)
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 66fd7aaedea..1c5ad650678 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -446,6 +446,7 @@ module Gitlab
when Key
actor.user
when :ci
+ Gitlab::AppJsonLogger.info(message: 'Actor was :ci', project_id: project.id)
nil
end
end
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 35d3ddf5d7f..c5c6ec1cdfa 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -44,8 +44,26 @@ module Gitlab
end
Gitlab::Git::Tag.new(@repository, response.tag)
- rescue GRPC::FailedPrecondition => e
- raise Gitlab::Git::Repository::InvalidRef, e
+ rescue GRPC::BadStatus => e
+ detailed_error = GitalyClient.decode_detailed_error(e)
+
+ case detailed_error&.error
+ when :access_check
+ access_check_error = detailed_error.access_check
+ # These messages were returned from internal/allowed API calls
+ raise Gitlab::Git::PreReceiveError.new(fallback_message: access_check_error.error_message)
+ when :custom_hook
+ raise Gitlab::Git::PreReceiveError.new(custom_hook_error_message(detailed_error.custom_hook),
+ fallback_message: e.details)
+ when :reference_exists
+ raise Gitlab::Git::Repository::TagExistsError
+ else
+ if e.code == GRPC::Core::StatusCodes::FAILED_PRECONDITION
+ raise Gitlab::Git::Repository::InvalidRef, e
+ end
+
+ raise
+ end
end
def user_create_branch(branch_name, user, start_point)
@@ -394,7 +412,7 @@ module Gitlab
response = GitalyClient.call(@repository.storage, :operation_service,
:user_commit_files, req_enum, timeout: GitalyClient.long_timeout,
- remote_storage: start_repository.storage)
+ remote_storage: start_repository&.storage)
if (pre_receive_error = response.pre_receive_error.presence)
raise Gitlab::Git::PreReceiveError, pre_receive_error
@@ -517,7 +535,7 @@ module Gitlab
commit_author_name: encode_binary(author_name),
commit_author_email: encode_binary(author_email),
start_branch_name: encode_binary(start_branch_name),
- start_repository: start_repository.gitaly_repository,
+ start_repository: start_repository&.gitaly_repository,
force: force,
start_sha: encode_binary(start_sha),
timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.utc.to_i)
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 31e1406356f..42f9c165610 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -120,6 +120,16 @@ module Gitlab
return unless tag
Gitlab::Git::Tag.new(@repository, tag)
+ rescue GRPC::BadStatus => e
+ detailed_error = GitalyClient.decode_detailed_error(e)
+
+ case detailed_error&.error
+ when :tag_not_found
+ raise Gitlab::Git::UnknownRef, "tag does not exist: #{tag_name}"
+ else
+ # When this is not a know structured error we simply re-raise the exception.
+ raise e
+ end
end
def delete_refs(refs: [], except_with_prefixes: [])
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 5adb8d946a0..04d6f92e8d8 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -271,6 +271,18 @@ module Gitlab
nil
end
+ def full_path
+ response = GitalyClient.call(
+ @storage,
+ :repository_service,
+ :full_path,
+ Gitaly::FullPathRequest.new(repository: @gitaly_repo),
+ timeout: GitalyClient.fast_timeout
+ )
+
+ response.path.presence
+ end
+
def license_short_name
request = Gitaly::FindLicenseRequest.new(repository: @gitaly_repo)
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index d2495b32800..11a41149274 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -107,7 +107,7 @@ module Gitlab
#
# rubocop: disable GitlabSecurity/PublicSend
def each_page(method, *args, &block)
- return to_enum(__method__, method, *args) unless block_given?
+ return to_enum(__method__, method, *args) unless block
page =
if args.last.is_a?(Hash) && args.last[:page]
@@ -134,7 +134,7 @@ module Gitlab
# method - The method to send to Octokit for querying data.
# args - Any arguments to pass to the Octokit method.
def each_object(method, *args, &block)
- return to_enum(__method__, method, *args) unless block_given?
+ return to_enum(__method__, method, *args) unless block
each_page(method, *args) do |page|
page.objects.each do |object|
diff --git a/lib/gitlab/github_import/importer/events/base_importer.rb b/lib/gitlab/github_import/importer/events/base_importer.rb
new file mode 100644
index 00000000000..9ab1d916d33
--- /dev/null
+++ b/lib/gitlab/github_import/importer/events/base_importer.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Events
+ # Base class for importing issue events during project import from GitHub
+ class BaseImporter
+ # project - An instance of `Project`.
+ # client - An instance of `Gitlab::GithubImport::Client`.
+ def initialize(project, client)
+ @project = project
+ @user_finder = UserFinder.new(project, client)
+ end
+
+ # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
+ def execute(issue_event)
+ raise NotImplementedError
+ end
+
+ private
+
+ attr_reader :project, :user_finder
+
+ def author_id(issue_event, author_key: :actor)
+ user_finder.author_id_for(issue_event, author_key: author_key).first
+ end
+
+ def issuable_db_id(object)
+ IssuableFinder.new(project, object).database_id
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/events/changed_assignee.rb b/lib/gitlab/github_import/importer/events/changed_assignee.rb
new file mode 100644
index 00000000000..c8f6335e4a8
--- /dev/null
+++ b/lib/gitlab/github_import/importer/events/changed_assignee.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Events
+ class ChangedAssignee < BaseImporter
+ def execute(issue_event)
+ assignee_id = author_id(issue_event, author_key: :assignee)
+ assigner_id = author_id(issue_event, author_key: :assigner)
+
+ note_body = parse_body(issue_event, assigner_id, assignee_id)
+
+ create_note(issue_event, note_body, assigner_id)
+ end
+
+ private
+
+ def create_note(issue_event, note_body, assigner_id)
+ Note.create!(
+ system: true,
+ noteable_type: Issue.name,
+ noteable_id: issuable_db_id(issue_event),
+ project: project,
+ author_id: assigner_id,
+ note: note_body,
+ system_note_metadata: SystemNoteMetadata.new(
+ {
+ action: "assignee",
+ created_at: issue_event.created_at,
+ updated_at: issue_event.created_at
+ }
+ ),
+ created_at: issue_event.created_at,
+ updated_at: issue_event.created_at
+ )
+ end
+
+ def parse_body(issue_event, assigner_id, assignee_id)
+ Gitlab::I18n.with_default_locale do
+ if issue_event.event == "unassigned"
+ "unassigned #{User.find(assigner_id).to_reference}"
+ else
+ "assigned to #{User.find(assignee_id).to_reference}"
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/events/changed_label.rb b/lib/gitlab/github_import/importer/events/changed_label.rb
index 6c408158b02..818a9202745 100644
--- a/lib/gitlab/github_import/importer/events/changed_label.rb
+++ b/lib/gitlab/github_import/importer/events/changed_label.rb
@@ -4,25 +4,17 @@ module Gitlab
module GithubImport
module Importer
module Events
- class ChangedLabel
- def initialize(project, user_id)
- @project = project
- @user_id = user_id
- end
-
- # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
+ class ChangedLabel < BaseImporter
def execute(issue_event)
create_event(issue_event)
end
private
- attr_reader :project, :user_id
-
def create_event(issue_event)
ResourceLabelEvent.create!(
- issue_id: issue_event.issue_db_id,
- user_id: user_id,
+ issue_id: issuable_db_id(issue_event),
+ user_id: author_id(issue_event),
label_id: label_finder.id_for(issue_event.label_title),
action: action(issue_event.event),
created_at: issue_event.created_at
diff --git a/lib/gitlab/github_import/importer/events/changed_milestone.rb b/lib/gitlab/github_import/importer/events/changed_milestone.rb
new file mode 100644
index 00000000000..3164c041dc3
--- /dev/null
+++ b/lib/gitlab/github_import/importer/events/changed_milestone.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ module Events
+ class ChangedMilestone < BaseImporter
+ # GitHub API doesn't provide the historical state of an issue for
+ # de/milestoned issue events. So we'll assign the default state to
+ # those events that are imported from GitHub.
+ DEFAULT_STATE = Issue.available_states[:opened]
+
+ def execute(issue_event)
+ create_event(issue_event)
+ end
+
+ private
+
+ def create_event(issue_event)
+ ResourceMilestoneEvent.create!(
+ issue_id: issuable_db_id(issue_event),
+ user_id: author_id(issue_event),
+ created_at: issue_event.created_at,
+ milestone_id: project.milestones.find_by_title(issue_event.milestone_title)&.id,
+ action: action(issue_event.event),
+ state: DEFAULT_STATE
+ )
+ end
+
+ def action(event_type)
+ return ResourceMilestoneEvent.actions[:remove] if event_type == 'demilestoned'
+
+ ResourceMilestoneEvent.actions[:add]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/events/closed.rb b/lib/gitlab/github_import/importer/events/closed.rb
index 8b2136c9b24..ca8730d0f27 100644
--- a/lib/gitlab/github_import/importer/events/closed.rb
+++ b/lib/gitlab/github_import/importer/events/closed.rb
@@ -4,15 +4,7 @@ module Gitlab
module GithubImport
module Importer
module Events
- class Closed
- attr_reader :project, :user_id
-
- def initialize(project, user_id)
- @project = project
- @user_id = user_id
- end
-
- # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
+ class Closed < BaseImporter
def execute(issue_event)
create_event(issue_event)
create_state_event(issue_event)
@@ -23,10 +15,10 @@ module Gitlab
def create_event(issue_event)
Event.create!(
project_id: project.id,
- author_id: user_id,
+ author_id: author_id(issue_event),
action: 'closed',
target_type: Issue.name,
- target_id: issue_event.issue_db_id,
+ target_id: issuable_db_id(issue_event),
created_at: issue_event.created_at,
updated_at: issue_event.created_at
)
@@ -34,8 +26,8 @@ module Gitlab
def create_state_event(issue_event)
ResourceStateEvent.create!(
- user_id: user_id,
- issue_id: issue_event.issue_db_id,
+ user_id: author_id(issue_event),
+ issue_id: issuable_db_id(issue_event),
source_commit: issue_event.commit_id,
state: 'closed',
close_after_error_tracking_resolve: false,
diff --git a/lib/gitlab/github_import/importer/events/cross_referenced.rb b/lib/gitlab/github_import/importer/events/cross_referenced.rb
index 20b902cfe50..89fc1bdeb09 100644
--- a/lib/gitlab/github_import/importer/events/cross_referenced.rb
+++ b/lib/gitlab/github_import/importer/events/cross_referenced.rb
@@ -4,15 +4,7 @@ module Gitlab
module GithubImport
module Importer
module Events
- class CrossReferenced
- attr_reader :project, :user_id
-
- def initialize(project, user_id)
- @project = project
- @user_id = user_id
- end
-
- # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
+ class CrossReferenced < BaseImporter
def execute(issue_event)
mentioned_in_record_class = mentioned_in_type(issue_event)
mentioned_in_number = issue_event.source.dig(:issue, :number)
@@ -21,14 +13,15 @@ module Gitlab
)
return if mentioned_in_record.nil?
+ user_id = author_id(issue_event)
note_body = cross_reference_note_content(mentioned_in_record.gfm_reference(project))
- track_activity(mentioned_in_record_class)
- create_note(issue_event, note_body)
+ track_activity(mentioned_in_record_class, user_id)
+ create_note(issue_event, note_body, user_id)
end
private
- def track_activity(mentioned_in_class)
+ def track_activity(mentioned_in_class, user_id)
return if mentioned_in_class != Issue
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(
@@ -37,11 +30,11 @@ module Gitlab
)
end
- def create_note(issue_event, note_body)
+ def create_note(issue_event, note_body, user_id)
Note.create!(
system: true,
noteable_type: Issue.name,
- noteable_id: issue_event.issue_db_id,
+ noteable_id: issuable_db_id(issue_event),
project: project,
author_id: user_id,
note: note_body,
@@ -73,7 +66,7 @@ module Gitlab
iid: number, issuable_type: record_class.name
)
- Gitlab::GithubImport::IssuableFinder.new(project, mentioned_in_adapter).database_id
+ issuable_db_id(mentioned_in_adapter)
end
def cross_reference_note_content(gfm_reference)
diff --git a/lib/gitlab/github_import/importer/events/renamed.rb b/lib/gitlab/github_import/importer/events/renamed.rb
index 6a11c492210..96d112b04c6 100644
--- a/lib/gitlab/github_import/importer/events/renamed.rb
+++ b/lib/gitlab/github_import/importer/events/renamed.rb
@@ -4,27 +4,19 @@ module Gitlab
module GithubImport
module Importer
module Events
- class Renamed
- def initialize(project, user_id)
- @project = project
- @user_id = user_id
- end
-
- # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`
+ class Renamed < BaseImporter
def execute(issue_event)
Note.create!(note_params(issue_event))
end
private
- attr_reader :project, :user_id
-
def note_params(issue_event)
{
- noteable_id: issue_event.issue_db_id,
+ noteable_id: issuable_db_id(issue_event),
noteable_type: Issue.name,
project_id: project.id,
- author_id: user_id,
+ author_id: author_id(issue_event),
note: parse_body(issue_event),
system: true,
created_at: issue_event.created_at,
diff --git a/lib/gitlab/github_import/importer/events/reopened.rb b/lib/gitlab/github_import/importer/events/reopened.rb
index c0f3802bc46..b75344bf817 100644
--- a/lib/gitlab/github_import/importer/events/reopened.rb
+++ b/lib/gitlab/github_import/importer/events/reopened.rb
@@ -4,15 +4,7 @@ module Gitlab
module GithubImport
module Importer
module Events
- class Reopened
- attr_reader :project, :user_id
-
- def initialize(project, user_id)
- @project = project
- @user_id = user_id
- end
-
- # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
+ class Reopened < BaseImporter
def execute(issue_event)
create_event(issue_event)
create_state_event(issue_event)
@@ -23,10 +15,10 @@ module Gitlab
def create_event(issue_event)
Event.create!(
project_id: project.id,
- author_id: user_id,
+ author_id: author_id(issue_event),
action: 'reopened',
target_type: Issue.name,
- target_id: issue_event.issue_db_id,
+ target_id: issuable_db_id(issue_event),
created_at: issue_event.created_at,
updated_at: issue_event.created_at
)
@@ -34,8 +26,8 @@ module Gitlab
def create_state_event(issue_event)
ResourceStateEvent.create!(
- user_id: user_id,
- issue_id: issue_event.issue_db_id,
+ user_id: author_id(issue_event),
+ issue_id: issuable_db_id(issue_event),
state: 'reopened',
created_at: issue_event.created_at
)
diff --git a/lib/gitlab/github_import/importer/issue_event_importer.rb b/lib/gitlab/github_import/importer/issue_event_importer.rb
index e451af61ec3..ef456e56ee1 100644
--- a/lib/gitlab/github_import/importer/issue_event_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_event_importer.rb
@@ -4,7 +4,7 @@ module Gitlab
module GithubImport
module Importer
class IssueEventImporter
- attr_reader :issue_event, :project, :client, :user_finder
+ attr_reader :issue_event, :project, :client
# issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`.
# project - An instance of `Project`.
@@ -13,26 +13,16 @@ module Gitlab
@issue_event = issue_event
@project = project
@client = client
- @user_finder = UserFinder.new(project, client)
end
+ # TODO: Add MergeRequest events support
+ # https://gitlab.com/groups/gitlab-org/-/epics/7673
def execute
- case issue_event.event
- when 'closed'
- Gitlab::GithubImport::Importer::Events::Closed.new(project, author_id)
- .execute(issue_event)
- when 'reopened'
- Gitlab::GithubImport::Importer::Events::Reopened.new(project, author_id)
- .execute(issue_event)
- when 'labeled', 'unlabeled'
- Gitlab::GithubImport::Importer::Events::ChangedLabel.new(project, author_id)
- .execute(issue_event)
- when 'renamed'
- Gitlab::GithubImport::Importer::Events::Renamed.new(project, author_id)
- .execute(issue_event)
- when 'cross-referenced'
- Gitlab::GithubImport::Importer::Events::CrossReferenced.new(project, author_id)
- .execute(issue_event)
+ return if issue_event.issuable_type == 'MergeRequest'
+
+ importer = event_importer_class(issue_event)
+ if importer
+ importer.new(project, client).execute(issue_event)
else
Gitlab::GithubImport::Logger.debug(
message: 'UNSUPPORTED_EVENT_TYPE',
@@ -43,9 +33,23 @@ module Gitlab
private
- def author_id
- id, _status = user_finder.author_id_for(issue_event, author_key: :actor)
- id
+ def event_importer_class(issue_event)
+ case issue_event.event
+ when 'closed'
+ Gitlab::GithubImport::Importer::Events::Closed
+ when 'reopened'
+ Gitlab::GithubImport::Importer::Events::Reopened
+ when 'labeled', 'unlabeled'
+ Gitlab::GithubImport::Importer::Events::ChangedLabel
+ when 'renamed'
+ Gitlab::GithubImport::Importer::Events::Renamed
+ when 'milestoned', 'demilestoned'
+ Gitlab::GithubImport::Importer::Events::ChangedMilestone
+ when 'cross-referenced'
+ Gitlab::GithubImport::Importer::Events::CrossReferenced
+ when 'assigned', 'unassigned'
+ Gitlab::GithubImport::Importer::Events::ChangedAssignee
+ end
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
new file mode 100644
index 00000000000..71dd99f91f9
--- /dev/null
+++ b/lib/gitlab/github_import/importer/issue_events_importer.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GithubImport
+ module Importer
+ class IssueEventsImporter
+ include ParallelScheduling
+
+ def importer_class
+ IssueEventImporter
+ end
+
+ def representation_class
+ Representation::IssueEvent
+ end
+
+ def sidekiq_worker_class
+ ImportIssueEventWorker
+ end
+
+ def object_type
+ :issue_event
+ end
+
+ def collection_method
+ :repository_issue_events
+ end
+
+ def id_for_already_imported_cache(event)
+ event.id
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb
index e7d41856b04..d964bae3dd2 100644
--- a/lib/gitlab/github_import/importer/issue_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_importer.rb
@@ -56,7 +56,8 @@ module Gitlab
milestone_id: milestone_finder.id_for(issue),
state_id: ::Issue.available_states[issue.state],
created_at: issue.created_at,
- updated_at: issue.updated_at
+ updated_at: issue.updated_at,
+ work_item_type_id: issue.work_item_type_id
}
insert_and_return_id(attributes, project.issues)
diff --git a/lib/gitlab/github_import/importer/issues_importer.rb b/lib/gitlab/github_import/importer/issues_importer.rb
index 6cc1a61b332..21d9ce8cd2d 100644
--- a/lib/gitlab/github_import/importer/issues_importer.rb
+++ b/lib/gitlab/github_import/importer/issues_importer.rb
@@ -6,6 +6,12 @@ module Gitlab
class IssuesImporter
include ParallelScheduling
+ def initialize(project, client, parallel: true)
+ super
+
+ @work_item_type_id = ::WorkItems::Type.default_issue_type.id
+ end
+
def importer_class
IssueAndLabelLinksImporter
end
@@ -33,6 +39,12 @@ module Gitlab
def collection_options
{ state: 'all', sort: 'created', direction: 'asc' }
end
+
+ private
+
+ def additional_object_data
+ { work_item_type_id: @work_item_type_id }
+ 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 7241e1ef703..51d364772d2 100644
--- a/lib/gitlab/github_import/importer/releases_importer.rb
+++ b/lib/gitlab/github_import/importer/releases_importer.rb
@@ -27,9 +27,10 @@ module Gitlab
def build(release)
existing_tags.add(release.tag_name)
- build_hash = {
+ {
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,
@@ -37,12 +38,6 @@ module Gitlab
released_at: release.published_at || Time.current,
project_id: project.id
}
-
- if Feature.enabled?(:import_release_authors_from_github, project)
- build_hash[:author_id] = fetch_author_id(release)
- end
-
- build_hash
end
def each_release
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 45bbc25e637..8e4015acbbc 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
@@ -18,13 +18,16 @@ module Gitlab
{ project: project.id, collection: collection_method }
end
+ # In single endpoint there is no issue info to which associated related
+ # 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)
compose_associated_id!(parent_record, associated)
return if already_imported?(associated)
Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched)
- associated.issue_db_id = parent_record.id
+ associated.issue = { 'number' => parent_record.iid }
yield(associated)
mark_as_imported(associated)
diff --git a/lib/gitlab/github_import/issuable_finder.rb b/lib/gitlab/github_import/issuable_finder.rb
index da205ebd345..e7a1b7b3368 100644
--- a/lib/gitlab/github_import/issuable_finder.rb
+++ b/lib/gitlab/github_import/issuable_finder.rb
@@ -69,6 +69,8 @@ module Gitlab
object.noteable_id
elsif object.respond_to?(:iid)
object.iid
+ elsif object.respond_to?(:issuable_id)
+ object.issuable_id
else
raise(
TypeError,
diff --git a/lib/gitlab/github_import/parallel_scheduling.rb b/lib/gitlab/github_import/parallel_scheduling.rb
index ab20b372d53..a8c18c74d24 100644
--- a/lib/gitlab/github_import/parallel_scheduling.rb
+++ b/lib/gitlab/github_import/parallel_scheduling.rb
@@ -63,7 +63,7 @@ module Gitlab
# Imports all the objects in sequence in the current thread.
def sequential_import
each_object_to_import do |object|
- repr = representation_class.from_api_response(object)
+ repr = representation_class.from_api_response(object, additional_object_data)
importer_class.new(repr, project, client).execute
end
@@ -72,26 +72,9 @@ module Gitlab
# Imports all objects in parallel by scheduling a Sidekiq job for every
# individual object.
def parallel_import
- if parallel_import_batch.present?
- spread_parallel_import
- else
- parallel_import_deprecated
- end
- end
-
- def parallel_import_deprecated
- waiter = JobWaiter.new
-
- each_object_to_import do |object|
- repr = representation_class.from_api_response(object)
-
- sidekiq_worker_class
- .perform_async(project.id, repr.to_hash, waiter.key)
+ raise 'Batch settings must be defined for parallel import' if parallel_import_batch.blank?
- waiter.jobs_remaining += 1
- end
-
- waiter
+ spread_parallel_import
end
def spread_parallel_import
@@ -100,7 +83,7 @@ module Gitlab
import_arguments = []
each_object_to_import do |object|
- repr = representation_class.from_api_response(object)
+ repr = representation_class.from_api_response(object, additional_object_data)
import_arguments << [project.id, repr.to_hash, waiter.key]
@@ -223,6 +206,10 @@ module Gitlab
private
+ def additional_object_data
+ {}
+ end
+
def info(project_id, extra = {})
Logger.info(log_attributes(project_id, extra))
end
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index 883abef9bdb..64aa6ea5cb4 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -20,7 +20,7 @@ module Gitlab
# Builds a diff note from a GitHub API response.
#
# note - An instance of `Sawyer::Resource` containing the note details.
- def self.from_api_response(note)
+ def self.from_api_response(note, additional_data = {})
matches = note.html_url.match(NOTEABLE_ID_REGEX)
unless matches
diff --git a/lib/gitlab/github_import/representation/issue.rb b/lib/gitlab/github_import/representation/issue.rb
index db4a8188c03..9d457ec1c2f 100644
--- a/lib/gitlab/github_import/representation/issue.rb
+++ b/lib/gitlab/github_import/representation/issue.rb
@@ -11,13 +11,13 @@ module Gitlab
expose_attribute :iid, :title, :description, :milestone_number,
:created_at, :updated_at, :state, :assignees,
- :label_names, :author
+ :label_names, :author, :work_item_type_id
# Builds an issue from a GitHub API response.
#
# issue - An instance of `Sawyer::Resource` containing the issue
# details.
- def self.from_api_response(issue)
+ def self.from_api_response(issue, additional_data = {})
user =
if issue.user
Representation::User.from_api_response(issue.user)
@@ -36,7 +36,8 @@ module Gitlab
author: user,
created_at: issue.created_at,
updated_at: issue.updated_at,
- pull_request: issue.pull_request ? true : false
+ pull_request: issue.pull_request ? true : false,
+ work_item_type_id: additional_data[:work_item_type_id]
}
new(hash)
diff --git a/lib/gitlab/github_import/representation/issue_event.rb b/lib/gitlab/github_import/representation/issue_event.rb
index 9016338db3b..67a5df73a97 100644
--- a/lib/gitlab/github_import/representation/issue_event.rb
+++ b/lib/gitlab/github_import/representation/issue_event.rb
@@ -10,34 +10,7 @@ module Gitlab
attr_reader :attributes
expose_attribute :id, :actor, :event, :commit_id, :label_title, :old_title, :new_title,
- :source, :created_at
- expose_attribute :issue_db_id # set in SingleEndpointIssueEventsImporter#each_associated
-
- # Builds a event from a GitHub API response.
- #
- # event - An instance of `Sawyer::Resource` containing the event details.
- def self.from_api_response(event)
- new(
- id: event.id,
- actor: event.actor && Representation::User.from_api_response(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],
- source: event.source,
- issue_db_id: event.issue_db_id,
- created_at: event.created_at
- )
- end
-
- # Builds a event using a Hash that was built from a JSON payload.
- def self.from_json_hash(raw_hash)
- hash = Representation.symbolize_hash(raw_hash)
- hash[:actor] &&= Representation::User.from_json_hash(hash[:actor])
-
- new(hash)
- end
+ :milestone_title, :issue, :source, :assignee, :assigner, :created_at
# attributes - A Hash containing the event details. The keys of this
# Hash (and any nested hashes) must be symbols.
@@ -48,6 +21,60 @@ module Gitlab
def github_identifiers
{ id: id }
end
+
+ def issuable_type
+ issue && issue[:pull_request].present? ? 'MergeRequest' : 'Issue'
+ end
+
+ def issuable_id
+ issue && issue[:number]
+ end
+
+ class << self
+ # Builds an event from a GitHub API response.
+ #
+ # event - An instance of `Sawyer::Resource` 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),
+ assigner: user_representation(event.assigner),
+ created_at: event.created_at
+ )
+ end
+
+ # Builds an event using a Hash that was built from a JSON payload.
+ def from_json_hash(raw_hash)
+ hash = Representation.symbolize_hash(raw_hash)
+ hash[:actor] = user_representation(hash[:actor], source: :hash)
+ hash[:assignee] = user_representation(hash[:assignee], source: :hash)
+ hash[:assigner] = user_representation(hash[:assigner], source: :hash)
+
+ new(hash)
+ end
+
+ private
+
+ def user_representation(data, source: :api_response)
+ return unless data
+
+ case source
+ when :api_response
+ Representation::User.from_api_response(data)
+ when :hash
+ Representation::User.from_json_hash(data)
+ end
+ end
+ end
end
end
end
diff --git a/lib/gitlab/github_import/representation/lfs_object.rb b/lib/gitlab/github_import/representation/lfs_object.rb
index 18737bfcde3..cd614db2161 100644
--- a/lib/gitlab/github_import/representation/lfs_object.rb
+++ b/lib/gitlab/github_import/representation/lfs_object.rb
@@ -12,7 +12,7 @@ module Gitlab
expose_attribute :oid, :link, :size
# Builds a lfs_object
- def self.from_api_response(lfs_object)
+ def self.from_api_response(lfs_object, additional_data = {})
new(
oid: lfs_object.oid,
link: lfs_object.link,
diff --git a/lib/gitlab/github_import/representation/note.rb b/lib/gitlab/github_import/representation/note.rb
index bbf20b7e9e6..ae56c370b19 100644
--- a/lib/gitlab/github_import/representation/note.rb
+++ b/lib/gitlab/github_import/representation/note.rb
@@ -17,7 +17,7 @@ module Gitlab
# Builds a note from a GitHub API response.
#
# note - An instance of `Sawyer::Resource` containing the note details.
- def self.from_api_response(note)
+ def self.from_api_response(note, additional_data = {})
matches = note.html_url.match(NOTEABLE_TYPE_REGEX)
if !matches || !matches[:type]
diff --git a/lib/gitlab/github_import/representation/pull_request.rb b/lib/gitlab/github_import/representation/pull_request.rb
index 82bcdee8b2b..2adac2af502 100644
--- a/lib/gitlab/github_import/representation/pull_request.rb
+++ b/lib/gitlab/github_import/representation/pull_request.rb
@@ -18,7 +18,7 @@ module Gitlab
# Builds a PR from a GitHub API response.
#
# issue - An instance of `Sawyer::Resource` containing the PR details.
- def self.from_api_response(pr)
+ 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
diff --git a/lib/gitlab/github_import/representation/pull_request_review.rb b/lib/gitlab/github_import/representation/pull_request_review.rb
index 70c1e51ffdd..8a7ecf0c588 100644
--- a/lib/gitlab/github_import/representation/pull_request_review.rb
+++ b/lib/gitlab/github_import/representation/pull_request_review.rb
@@ -11,7 +11,7 @@ module Gitlab
expose_attribute :author, :note, :review_type, :submitted_at, :merge_request_id, :review_id
- def self.from_api_response(review)
+ def self.from_api_response(review, additional_data = {})
user = Representation::User.from_api_response(review.user) if review.user
new(
diff --git a/lib/gitlab/github_import/representation/user.rb b/lib/gitlab/github_import/representation/user.rb
index fac8920a3f2..4ef916cc41c 100644
--- a/lib/gitlab/github_import/representation/user.rb
+++ b/lib/gitlab/github_import/representation/user.rb
@@ -14,7 +14,7 @@ module Gitlab
# Builds a user from a GitHub API response.
#
# user - An instance of `Sawyer::Resource` containing the user details.
- def self.from_api_response(user)
+ def self.from_api_response(user, additional_data = {})
new(
id: user.id,
login: user.login
diff --git a/lib/gitlab/github_import/user_finder.rb b/lib/gitlab/github_import/user_finder.rb
index efaa2ce3002..6d6a00d260d 100644
--- a/lib/gitlab/github_import/user_finder.rb
+++ b/lib/gitlab/github_import/user_finder.rb
@@ -40,7 +40,17 @@ module Gitlab
# If the object has no author ID we'll use the ID of the GitLab ghost
# user.
def author_id_for(object, author_key: :author)
- user_info = author_key == :actor ? object&.actor : object&.author
+ user_info = case author_key
+ when :actor
+ object&.actor
+ when :assignee
+ object&.assignee
+ when :assigner
+ object&.assigner
+ else
+ object&.author
+ end
+
id = user_info ? user_id_for(user_info) : GithubImport.ghost_user_id
if id
@@ -148,7 +158,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def query_id_for_github_email(email)
- User.by_any_email(email).pluck(:id).first
+ User.by_any_email(email).pick(:id)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/global_id/deprecations.rb b/lib/gitlab/global_id/deprecations.rb
index 2753e2b8372..b68aac8f862 100644
--- a/lib/gitlab/global_id/deprecations.rb
+++ b/lib/gitlab/global_id/deprecations.rb
@@ -3,46 +3,27 @@
module Gitlab
module GlobalId
module Deprecations
- Deprecation = Struct.new(:old_model_name, :new_model_name, :milestone, keyword_init: true)
-
# Contains the deprecations in place.
# Example:
#
# DEPRECATIONS = [
- # Deprecation.new(old_model_name: 'PrometheusService', new_model_name: 'Integrations::Prometheus', milestone: '14.1')
+ # Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(old_name: 'PrometheusService', new_name: 'Integrations::Prometheus', milestone: '14.1')
# ].freeze
DEPRECATIONS = [
# This works around an accidentally released argument named as `"EEIterationID"` in 7000489db.
- Deprecation.new(old_model_name: 'EEIteration', new_model_name: 'Iteration', milestone: '13.3'),
- Deprecation.new(old_model_name: 'PrometheusService', new_model_name: 'Integrations::Prometheus', milestone: '14.1')
+ Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(
+ old_name: 'EEIteration', new_name: 'Iteration', milestone: '13.3'
+ ),
+ Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(
+ old_name: 'PrometheusService', new_name: 'Integrations::Prometheus', milestone: '14.1'
+ )
].freeze
- # Maps of the DEPRECATIONS Hash for quick access.
- OLD_NAME_MAP = DEPRECATIONS.index_by(&:old_model_name).freeze
- NEW_NAME_MAP = DEPRECATIONS.index_by(&:new_model_name).freeze
- OLD_GRAPHQL_NAME_MAP = DEPRECATIONS.index_by do |d|
- Types::GlobalIDType.model_name_to_graphql_name(d.old_model_name)
- end.freeze
-
- def self.deprecated?(old_model_name)
- OLD_NAME_MAP.key?(old_model_name)
- end
-
- def self.deprecation_for(old_model_name)
- OLD_NAME_MAP[old_model_name]
+ def self.map_graphql_name(model_name)
+ Types::GlobalIDType.model_name_to_graphql_name(model_name)
end
- def self.deprecation_by(new_model_name)
- NEW_NAME_MAP[new_model_name]
- end
-
- # Returns the new `graphql_name` (Type#graphql_name) of a deprecated GID,
- # or the `graphql_name` argument given if no deprecation applies.
- def self.apply_to_graphql_name(graphql_name)
- return graphql_name unless deprecation = OLD_GRAPHQL_NAME_MAP[graphql_name]
-
- Types::GlobalIDType.model_name_to_graphql_name(deprecation.new_model_name)
- end
+ include Gitlab::Graphql::DeprecationsBase
end
end
end
diff --git a/lib/gitlab/grape_logging/loggers/token_logger.rb b/lib/gitlab/grape_logging/loggers/token_logger.rb
new file mode 100644
index 00000000000..a7c1b42ec96
--- /dev/null
+++ b/lib/gitlab/grape_logging/loggers/token_logger.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module GrapeLogging
+ module Loggers
+ class TokenLogger < ::GrapeLogging::Loggers::Base
+ def parameters(request, _)
+ params = request.env[::API::Helpers::API_TOKEN_ENV]
+
+ return {} unless params
+
+ params.slice(:token_type, :token_id)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/deprecation.rb b/lib/gitlab/graphql/deprecation.rb
index d30751fe46e..9b17962f9ec 100644
--- a/lib/gitlab/graphql/deprecation.rb
+++ b/lib/gitlab/graphql/deprecation.rb
@@ -21,8 +21,18 @@ module Gitlab
validate :milestone_is_string
validate :reason_known_or_string
- def self.parse(options)
- new(**options) if options
+ def self.parse(alpha: nil, deprecated: nil)
+ options = alpha || deprecated
+ return unless options
+
+ if alpha
+ raise ArgumentError, '`alpha` and `deprecated` arguments cannot be passed at the same time' \
+ if deprecated
+
+ options[:reason] = :alpha
+ end
+
+ new(**options)
end
def initialize(reason: nil, milestone: nil, replacement: nil)
@@ -84,6 +94,10 @@ module Gitlab
].compact.join(' ')
end
+ def alpha?
+ reason == REASON_ALPHA
+ end
+
private
attr_reader :reason, :milestone, :replacement
@@ -117,7 +131,7 @@ module Gitlab
# Retruns 'Introduced in <milestone>' for :alpha deprecations.
# Formatted to markdown or plain format.
def changed_in_milestone(format: :plain)
- verb = if reason == REASON_ALPHA
+ verb = if alpha?
'Introduced'
else
'Deprecated'
diff --git a/lib/gitlab/graphql/deprecations_base.rb b/lib/gitlab/graphql/deprecations_base.rb
new file mode 100644
index 00000000000..2ee14620907
--- /dev/null
+++ b/lib/gitlab/graphql/deprecations_base.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ # include DeprecationsBase at the end of the target module
+ module DeprecationsBase
+ NameDeprecation = Struct.new(:old_name, :new_name, :milestone, keyword_init: true)
+
+ def self.included(klass)
+ klass.extend(ClassMethods)
+
+ klass.const_set('OLD_GRAPHQL_NAME_MAP', klass::DEPRECATIONS.index_by do |d|
+ klass.map_graphql_name(d.old_name)
+ end.freeze)
+ klass.const_set('OLD_NAME_MAP', klass::DEPRECATIONS.index_by(&:old_name).freeze)
+ klass.const_set('NEW_NAME_MAP', klass::DEPRECATIONS.index_by(&:new_name).freeze)
+ end
+
+ module ClassMethods
+ def deprecated?(old_name)
+ self::OLD_NAME_MAP.key?(old_name)
+ end
+
+ def deprecation_for(old_name)
+ self::OLD_NAME_MAP[old_name]
+ end
+
+ def deprecation_by(new_name)
+ self::NEW_NAME_MAP[new_name]
+ end
+
+ # Returns the new `graphql_name` (Type#graphql_name) of a deprecated GID,
+ # or the `graphql_name` argument given if no deprecation applies.
+ def apply_to_graphql_name(graphql_name)
+ return graphql_name unless deprecation = self::OLD_GRAPHQL_NAME_MAP[graphql_name]
+
+ self.map_graphql_name(deprecation.new_name)
+ end
+
+ private
+
+ def map_graphql_name(name)
+ raise NotImplementedError, "Implement `#{__method__}` in #{self.name}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
deleted file mode 100644
index 6645dac36fa..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- module Conditions
- class BaseCondition
- # @param [Arel::Table] arel_table for the relation being ordered
- # @param [Array<OrderInfo>] order_list of extracted orderings
- # @param [Array] values from the decoded cursor
- # @param [Array<String>] operators determining sort comparison
- # @param [Symbol] before_or_after indicates whether we want
- # items :before the cursor or :after the cursor
- def initialize(arel_table, order_list, values, operators, before_or_after)
- @arel_table = arel_table
- @order_list = order_list
- @values = values
- @operators = operators
- @before_or_after = before_or_after
-
- @before_or_after = :after unless [:after, :before].include?(@before_or_after)
- end
-
- def build
- raise NotImplementedError
- end
-
- private
-
- attr_reader :arel_table, :order_list, :values, :operators, :before_or_after
-
- def table_condition(order_info, value, operator)
- if order_info.named_function
- target = order_info.named_function
-
- if target.try(:name)&.casecmp('lower') == 0
- value = value&.downcase
- end
- else
- target = arel_table[order_info.attribute_name]
- end
-
- case operator
- when '>'
- target.gt(value)
- when '<'
- target.lt(value)
- when '='
- target.eq(value)
- when 'is_null'
- target.eq(nil)
- when 'is_not_null'
- target.not_eq(nil)
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb
deleted file mode 100644
index ec70f5c5a24..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- module Conditions
- class NotNullCondition < BaseCondition
- def build
- conditions = [first_attribute_condition]
-
- # If there is only one order field, we can assume it
- # does not contain NULLs, and don't need additional
- # conditions
- unless order_list.count == 1
- conditions << [second_attribute_condition, final_condition]
- end
-
- conditions.join
- end
-
- private
-
- # ex: "(relative_position > 23)"
- def first_attribute_condition
- <<~SQL
- (#{table_condition(order_list.first, values.first, operators.first).to_sql})
- SQL
- end
-
- # ex: " OR (relative_position = 23 AND id > 500)"
- def second_attribute_condition
- <<~SQL
- OR (
- #{table_condition(order_list.first, values.first, '=').to_sql}
- AND
- #{table_condition(order_list[1], values[1], operators[1]).to_sql}
- )
- SQL
- end
-
- # ex: " OR (relative_position IS NULL)"
- def final_condition
- if before_or_after == :after
- <<~SQL
- OR (#{table_condition(order_list.first, nil, 'is_null').to_sql})
- SQL
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb
deleted file mode 100644
index 1aae1020e79..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- module Conditions
- class NullCondition < BaseCondition
- def build
- [first_attribute_condition, final_condition].join
- end
-
- private
-
- # ex: "(relative_position IS NULL AND id > 500)"
- def first_attribute_condition
- <<~SQL
- (
- #{table_condition(order_list.first, nil, 'is_null').to_sql}
- AND
- #{table_condition(order_list[1], values[1], operators[1]).to_sql}
- )
- SQL
- end
-
- # ex: " OR (relative_position IS NOT NULL)"
- def final_condition
- if before_or_after == :before
- <<~SQL
- OR (#{table_condition(order_list.first, nil, 'is_not_null').to_sql})
- SQL
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb
index 3e119a39e6d..b074c273996 100644
--- a/lib/gitlab/graphql/pagination/keyset/connection.rb
+++ b/lib/gitlab/graphql/pagination/keyset/connection.rb
@@ -29,7 +29,6 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
include ::Gitlab::Graphql::ConnectionCollectionMethods
prepend ::Gitlab::Graphql::ConnectionRedaction
- prepend GenericKeysetPagination
# rubocop: disable Naming/PredicateName
# https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields
@@ -58,19 +57,13 @@ module Gitlab
def has_next_page
strong_memoize(:has_next_page) do
if before
- # If `before` is specified, that points to a specific record,
- # even if it's the last one. Since we're asking for `before`,
- # then the specific record we're pointing to is in the
- # next page
true
elsif first
case sliced_nodes
when Array
sliced_nodes.size > limit_value
else
- # If we count the number of requested items plus one (`limit_value + 1`),
- # then if we get `limit_value + 1` then we know there is a next page
- relation_count(set_limit(sliced_nodes, limit_value + 1)) == limit_value + 1
+ sliced_nodes.limit(1).offset(limit_value).exists? # rubocop: disable CodeReuse/ActiveRecord
end
else
false
@@ -80,20 +73,15 @@ module Gitlab
# rubocop: enable Naming/PredicateName
def cursor_for(node)
- encoded_json_from_ordering(node)
+ order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(items)
+ encode(order.cursor_attributes_for_node(node).to_json)
end
def sliced_nodes
- @sliced_nodes ||=
- begin
- OrderInfo.validate_ordering(ordered_items, order_list) unless loaded?(ordered_items)
-
- sliced = ordered_items
- sliced = slice_nodes(sliced, before, :before) if before.present?
- sliced = slice_nodes(sliced, after, :after) if after.present?
-
- sliced
- end
+ sliced = ordered_items
+ sliced = slice_nodes(sliced, before, :before) if before.present?
+ sliced = slice_nodes(sliced, after, :after) if after.present?
+ sliced
end
def nodes
@@ -104,6 +92,20 @@ module Gitlab
@nodes ||= limited_nodes.to_a
end
+ def items
+ original_items = super
+ return original_items if Gitlab::Pagination::Keyset::Order.keyset_aware?(original_items)
+
+ strong_memoize(:keyset_pagination_items) do
+ rebuilt_items_with_keyset_order, success =
+ Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(original_items)
+
+ raise(Gitlab::Pagination::Keyset::UnsupportedScopeOrder) unless success
+
+ rebuilt_items_with_keyset_order
+ end
+ end
+
private
# Apply `first` and `last` to `sliced_nodes`
@@ -129,11 +131,11 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def slice_nodes(sliced, encoded_cursor, before_or_after)
- decoded_cursor = ordering_from_encoded_json(encoded_cursor)
- builder = QueryBuilder.new(arel_table, order_list, decoded_cursor, before_or_after)
- ordering = builder.conditions
+ order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(sliced)
+ order = order.reversed_order if before_or_after == :before
- sliced.where(*ordering).where.not(id: decoded_cursor['id'])
+ decoded_cursor = ordering_from_encoded_json(encoded_cursor)
+ order.apply_cursor_conditions(sliced, decoded_cursor)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -157,57 +159,10 @@ module Gitlab
raise ArgumentError, 'Relation must have a primary key'
end
- list = OrderInfo.build_order_list(items)
-
- if loaded?(items) && !before.present? && !after.present?
- @order_list = list.presence || [OrderInfo.new(items.primary_key)]
-
- # already sorted, or trivially sorted
- next items if list.present? || items.size <= 1
-
- pkey = items.primary_key.to_sym
- next items.sort_by { |item| item[pkey] }.reverse
- end
-
- # ensure there is a primary key ordering
- if list&.last&.attribute_name != items.primary_key
- items.order(arel_table[items.primary_key].desc) # rubocop: disable CodeReuse/ActiveRecord
- else
- items
- end
- end
- end
-
- def order_list
- strong_memoize(:order_list) do
- OrderInfo.build_order_list(ordered_items)
+ items
end
end
- def arel_table
- items.arel_table
- end
-
- # Storing the current order values in the cursor allows us to
- # make an intelligent decision on handling NULL values.
- # Otherwise we would either need to fetch the record first,
- # or fetch it in the SQL, significantly complicating it.
- def encoded_json_from_ordering(node)
- ordering = { 'id' => node[:id].to_s }
-
- order_list.each do |field|
- field_name = field.try(:attribute_name) || field
- field_value = node[field_name]
- ordering[field_name] = if field_value.is_a?(Time)
- field_value.to_s(:inspect)
- else
- field_value.to_s
- end
- end
-
- encode(ordering.to_json)
- end
-
def ordering_from_encoded_json(cursor)
Gitlab::Json.parse(decode(cursor))
rescue JSON::ParserError
diff --git a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
deleted file mode 100644
index 9beb40ddd7e..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- # https://gitlab.com/gitlab-org/gitlab/-/issues/334973
- # Use the generic keyset implementation if the given ActiveRecord scope supports it.
- # Note: this module is temporary, at some point it will be merged with Keyset::Connection
- module GenericKeysetPagination
- extend ActiveSupport::Concern
-
- # rubocop: disable Naming/PredicateName
- # rubocop: disable CodeReuse/ActiveRecord
- def has_next_page
- return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
-
- strong_memoize(:generic_keyset_pagination_has_next_page) do
- if before
- true
- elsif first
- case sliced_nodes
- when Array
- sliced_nodes.size > limit_value
- else
- sliced_nodes.limit(1).offset(limit_value).exists?
- end
- else
- false
- end
- end
- end
-
- # rubocop: enable CodeReuse/ActiveRecord
- def ordered_items
- raise ArgumentError, 'Relation must have a primary key' unless items.primary_key.present?
-
- return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
-
- items
- end
-
- def cursor_for(node)
- return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
-
- order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(items)
- encode(order.cursor_attributes_for_node(node).to_json)
- end
-
- def slice_nodes(sliced, encoded_cursor, before_or_after)
- return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(sliced)
-
- order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(sliced)
- order = order.reversed_order if before_or_after == :before
-
- decoded_cursor = ordering_from_encoded_json(encoded_cursor)
- order.apply_cursor_conditions(sliced, decoded_cursor)
- end
-
- def sliced_nodes
- return super unless Gitlab::Pagination::Keyset::Order.keyset_aware?(items)
-
- sliced = ordered_items
- sliced = slice_nodes(sliced, before, :before) if before.present?
- sliced = slice_nodes(sliced, after, :after) if after.present?
- sliced
- end
-
- def items
- original_items = super
- return original_items if Feature.disabled?(:new_graphql_keyset_pagination) || Gitlab::Pagination::Keyset::Order.keyset_aware?(original_items)
-
- strong_memoize(:generic_keyset_pagination_items) do
- rebuilt_items_with_keyset_order, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(original_items)
-
- if success
- rebuilt_items_with_keyset_order
- else
- if original_items.is_a?(ActiveRecord::Relation)
- old_keyset_pagination_usage.increment({ model: original_items.model.to_s })
- end
-
- original_items
- end
- end
- end
-
- def old_keyset_pagination_usage
- @old_keyset_pagination_usage ||= Gitlab::Metrics.counter(
- :old_keyset_pagination_usage,
- 'The number of times the old keyset pagination code was used'
- )
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/pagination/keyset/order_info.rb b/lib/gitlab/graphql/pagination/keyset/order_info.rb
deleted file mode 100644
index 57e85ebe7f6..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/order_info.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- class OrderInfo
- attr_reader :attribute_name, :sort_direction, :named_function
-
- def initialize(order_value)
- @attribute_name, @sort_direction, @named_function =
- if order_value.is_a?(String)
- extract_nulls_last_order(order_value)
- else
- extract_attribute_values(order_value)
- end
- end
-
- def operator_for(before_or_after)
- case before_or_after
- when :before
- sort_direction == :asc ? '<' : '>'
- when :after
- sort_direction == :asc ? '>' : '<'
- end
- end
-
- # Only allow specific node types
- def self.build_order_list(relation)
- order_list = relation.order_values.select do |value|
- supported_order_value?(value)
- end
-
- order_list.map { |info| OrderInfo.new(info) }
- end
-
- def self.validate_ordering(relation, order_list)
- if order_list.empty?
- raise ArgumentError, 'A minimum of 1 ordering field is required'
- end
-
- if order_list.count > 2
- # Keep in mind an order clause for primary key is added if one is not present
- # lib/gitlab/graphql/pagination/keyset/connection.rb:97
- raise ArgumentError, 'A maximum of 2 ordering fields are allowed'
- end
-
- # make sure the last ordering field is non-nullable
- attribute_name = order_list.last&.attribute_name
-
- if relation.columns_hash[attribute_name].null
- raise ArgumentError, "Column `#{attribute_name}` must not allow NULL"
- end
-
- if order_list.last.attribute_name != relation.primary_key
- raise ArgumentError, "Last ordering field must be the primary key, `#{relation.primary_key}`"
- end
- end
-
- def self.supported_order_value?(order_value)
- return true if order_value.is_a?(Arel::Nodes::Ascending) || order_value.is_a?(Arel::Nodes::Descending)
- return false unless order_value.is_a?(String)
-
- tokens = order_value.downcase.split
-
- tokens.last(2) == %w(nulls last) && tokens.count == 4
- end
-
- private
-
- def extract_nulls_last_order(order_value)
- tokens = order_value.downcase.split
-
- column_reference = tokens.first
- sort_direction = tokens[1] == 'asc' ? :asc : :desc
-
- # Handles the case when the order value is coming from another table.
- # Example: table_name.column_name
- # Query the value using the fully qualified column name: pass table_name.column_name as the named_function
- if fully_qualified_column_reference?(column_reference)
- [column_reference, sort_direction, Arel.sql(column_reference)]
- else
- [column_reference, sort_direction, nil]
- end
- end
-
- # Example: table_name.column_name
- def fully_qualified_column_reference?(attribute)
- attribute.to_s.count('.') == 1
- end
-
- def extract_attribute_values(order_value)
- if ordering_by_lower?(order_value)
- [order_value.expr.expressions[0].name.to_s, order_value.direction, order_value.expr]
- elsif ordering_by_case?(order_value)
- ['case_order_value', order_value.direction, order_value.expr]
- elsif ordering_by_array_position?(order_value)
- ['array_position', order_value.direction, order_value.expr]
- else
- [order_value.expr.name, order_value.direction, nil]
- end
- end
-
- # determine if ordering using LOWER, eg. "ORDER BY LOWER(boards.name)"
- def ordering_by_lower?(order_value)
- order_value.expr.is_a?(Arel::Nodes::NamedFunction) && order_value.expr&.name&.downcase == 'lower'
- end
-
- # determine if ordering using ARRAY_POSITION, eg. "ORDER BY ARRAY_POSITION(Array[4,3,1,2]::smallint, state)"
- def ordering_by_array_position?(order_value)
- order_value.expr.is_a?(Arel::Nodes::NamedFunction) && order_value.expr&.name&.downcase == 'array_position'
- end
-
- # determine if ordering using CASE
- def ordering_by_case?(order_value)
- order_value.expr.is_a?(Arel::Nodes::Case)
- end
- end
- end
- end
- end
-end
-
-Gitlab::Graphql::Pagination::Keyset::OrderInfo.prepend_mod_with('Gitlab::Graphql::Pagination::Keyset::OrderInfo')
diff --git a/lib/gitlab/graphql/pagination/keyset/query_builder.rb b/lib/gitlab/graphql/pagination/keyset/query_builder.rb
deleted file mode 100644
index a2f53ae83dd..00000000000
--- a/lib/gitlab/graphql/pagination/keyset/query_builder.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Graphql
- module Pagination
- module Keyset
- class QueryBuilder
- def initialize(arel_table, order_list, decoded_cursor, before_or_after)
- @arel_table = arel_table
- @order_list = order_list
- @decoded_cursor = decoded_cursor
- @before_or_after = before_or_after
-
- if order_list.empty?
- raise ArgumentError, 'No ordering scopes have been supplied'
- end
- end
-
- # Based on whether the main field we're ordering on is NULL in the
- # cursor, we can more easily target our query condition.
- # We assume that the last ordering field is unique, meaning
- # it will not contain NULLs.
- # We currently only support two ordering fields.
- #
- # Example of the conditions for
- # relation: Issue.order(relative_position: :asc).order(id: :asc)
- # after cursor: relative_position: 1500, id: 500
- #
- # when cursor[relative_position] is not NULL
- #
- # ("issues"."relative_position" > 1500)
- # OR (
- # "issues"."relative_position" = 1500
- # AND
- # "issues"."id" > 500
- # )
- # OR ("issues"."relative_position" IS NULL)
- #
- # when cursor[relative_position] is NULL
- #
- # "issues"."relative_position" IS NULL
- # AND
- # "issues"."id" > 500
- #
- def conditions
- attr_values = order_list.map do |field|
- name = field.try(:attribute_name) || field
- decoded_cursor[name]
- end
-
- if order_list.count == 1 && attr_values.first.nil?
- raise Gitlab::Graphql::Errors::ArgumentError, 'Before/after cursor invalid: `nil` was provided as only sortable value'
- end
-
- if order_list.count == 1 || attr_values.first.present?
- Keyset::Conditions::NotNullCondition.new(arel_table, order_list, attr_values, operators, before_or_after).build
- else
- Keyset::Conditions::NullCondition.new(arel_table, order_list, attr_values, operators, before_or_after).build
- end
- end
-
- private
-
- attr_reader :arel_table, :order_list, :decoded_cursor, :before_or_after
-
- def operators
- order_list.map { |field| field.operator_for(before_or_after) }
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/graphql/type_name_deprecations.rb b/lib/gitlab/graphql/type_name_deprecations.rb
new file mode 100644
index 00000000000..c27ad1d54f5
--- /dev/null
+++ b/lib/gitlab/graphql/type_name_deprecations.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module TypeNameDeprecations
+ # Contains the deprecations in place.
+ # Example:
+ #
+ # DEPRECATIONS = [
+ # Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(
+ # old_name: 'CiRunnerUpgradeStatusType', new_name: 'CiRunnerUpgradeStatus', milestone: '15.3'
+ # )
+ # ].freeze
+ DEPRECATIONS = [
+ Gitlab::Graphql::DeprecationsBase::NameDeprecation.new(
+ old_name: 'CiRunnerUpgradeStatusType', new_name: 'CiRunnerUpgradeStatus', milestone: '15.3'
+ )
+ ].freeze
+
+ def self.map_graphql_name(name)
+ name
+ end
+
+ include Gitlab::Graphql::DeprecationsBase
+ end
+ end
+end
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index b4f90715293..65c623c5d7d 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -22,6 +22,7 @@ module Gitlab
merge_user_id
merge_when_pipeline_succeeds
milestone_id
+ reviewer_ids
source_branch
source_project_id
state_id
@@ -38,6 +39,7 @@ module Gitlab
%i[
assignees
labels
+ reviewers
total_time_spent
time_change
].freeze
@@ -60,6 +62,7 @@ module Gitlab
human_time_estimate: merge_request.human_time_estimate,
assignee_ids: merge_request.assignee_ids,
assignee_id: merge_request.assignee_ids.first, # This key is deprecated
+ reviewer_ids: merge_request.reviewer_ids,
labels: merge_request.labels_hook_attrs,
state: merge_request.state, # This key is deprecated
blocking_discussions_resolved: merge_request.mergeable_discussions_state?,
diff --git a/lib/gitlab/http_io.rb b/lib/gitlab/http_io.rb
index bd3ac139168..25b86fbf22f 100644
--- a/lib/gitlab/http_io.rb
+++ b/lib/gitlab/http_io.rb
@@ -153,7 +153,7 @@ module Gitlab
http.request(request)
end
- raise FailedToGetChunkError unless response.code == '200' || response.code == '206'
+ raise FailedToGetChunkError, "Unexpected response code: #{response.code}" unless response.code == '200' || response.code == '206'
@chunk = response.body.force_encoding(Encoding::BINARY)
@chunk_range = response.content_range
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index cad0e773b05..30465ff5f74 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -44,30 +44,30 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 0,
'cs_CZ' => 0,
- 'da_DK' => 40,
- 'de' => 15,
+ 'da_DK' => 39,
+ 'de' => 17,
'en' => 100,
'eo' => 0,
- 'es' => 37,
+ 'es' => 38,
'fil_PH' => 0,
'fr' => 11,
'gl_ES' => 0,
'id_ID' => 0,
'it' => 1,
- 'ja' => 33,
- 'ko' => 11,
+ 'ja' => 32,
+ 'ko' => 12,
'nb_NO' => 26,
'nl_NL' => 0,
'pl_PL' => 4,
'pt_BR' => 55,
'ro_RO' => 100,
- 'ru' => 28,
- 'si_LK' => 11,
+ 'ru' => 27,
+ 'si_LK' => 10,
'tr_TR' => 12,
- 'uk' => 49,
+ 'uk' => 50,
'zh_CN' => 99,
- 'zh_HK' => 2,
- 'zh_TW' => 4
+ 'zh_HK' => 1,
+ 'zh_TW' => 100
}.freeze
private_constant :TRANSLATION_LEVELS
diff --git a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
index e38496ecf67..34e75755dec 100644
--- a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
@@ -12,12 +12,13 @@ module Gitlab
private
- attr_reader :project, :current_user, :lock_file
+ attr_reader :project, :current_user, :lock_file, :logger
public
def initialize(attributes = {})
@options = attributes
+ @logger = Gitlab::Export::Logger.build
end
def method_missing(method, *args)
@@ -43,6 +44,10 @@ module Gitlab
true
rescue StandardError => e
+ payload = { message: "After export strategy failed" }
+ Gitlab::ExceptionLogFormatter.format!(e, payload)
+ log_error(payload)
+
project.import_export_shared.error(e)
false
ensure
@@ -108,6 +113,18 @@ module Gitlab
def log_validation_errors
errors.full_messages.each { |msg| project.import_export_shared.add_error_message(msg) }
end
+
+ def log_info(params)
+ logger.info(log_default_params.merge(params))
+ end
+
+ def log_error(params)
+ logger.error(log_default_params.merge(params))
+ end
+
+ def log_default_params
+ { project_name: project.name, project_id: project.id }
+ end
end
end
end
diff --git a/lib/gitlab/import_export/after_export_strategies/move_file_strategy.rb b/lib/gitlab/import_export/after_export_strategies/move_file_strategy.rb
index 2e3136936f8..bddbe7862cb 100644
--- a/lib/gitlab/import_export/after_export_strategies/move_file_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/move_file_strategy.rb
@@ -5,6 +5,7 @@ module Gitlab
module AfterExportStrategies
class MoveFileStrategy < BaseAfterExportStrategy
def initialize(archive_path:)
+ super
@archive_path = archive_path
end
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 78608a946de..6c5fba37d7b 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
@@ -23,7 +23,17 @@ module Gitlab
protected
def strategy_execute
- handle_response_error(send_file)
+ 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
+ handle_response_error(send_file)
+ end
+ end
+
+ log_info(message: "Finished uploading project", export_size: export_size, upload_duration: upload_duration)
end
def handle_response_error(response)
@@ -44,8 +54,22 @@ module Gitlab
export_file.close if export_file
end
+ def upload_project_as_remote_stream
+ Gitlab::ImportExport::RemoteStreamUpload.new(
+ download_url: project.export_file.url,
+ upload_url: url,
+ options: {
+ upload_method: http_method.downcase.to_sym,
+ upload_content_type: 'application/gzip'
+ }).execute
+ rescue Gitlab::ImportExport::RemoteStreamUpload::StreamError => e
+ log_error(message: e.message, response_body: e.response_body.truncate(3000))
+
+ raise
+ end
+
def export_file
- project.export_file.open
+ @export_file ||= project.export_file.open
end
def send_file_options
diff --git a/lib/gitlab/import_export/after_export_strategy_builder.rb b/lib/gitlab/import_export/after_export_strategy_builder.rb
index d7b30f46903..90618922dfe 100644
--- a/lib/gitlab/import_export/after_export_strategy_builder.rb
+++ b/lib/gitlab/import_export/after_export_strategy_builder.rb
@@ -9,7 +9,11 @@ module Gitlab
return default_strategy.new unless strategy_klass
attributes ||= {}
- klass = strategy_klass.constantize rescue nil
+ klass = begin
+ strategy_klass.constantize
+ rescue StandardError
+ nil
+ end
unless klass && klass < AfterExportStrategies::BaseAfterExportStrategy
raise StrategyNotFoundError, "Strategy #{strategy_klass} not found"
diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb
index 53dd6f8cd55..1cbfcbdb595 100644
--- a/lib/gitlab/import_export/base/relation_factory.rb
+++ b/lib/gitlab/import_export/base/relation_factory.rb
@@ -126,12 +126,19 @@ module Gitlab
end
end
+ # When an assignee (or any other listed association) did not exist in the members mapper, the importer is
+ # assigned. We only need to assign each user once.
def remove_duplicate_assignees
- return unless @relation_hash['issue_assignees']
+ associations = %w[issue_assignees merge_request_assignees merge_request_reviewers approvals]
- # When an assignee did not exist in the members mapper, the importer is
- # assigned. We only need to assign each user once.
- @relation_hash['issue_assignees'].uniq!(&:user_id)
+ associations.each do |association|
+ next unless @relation_hash.key?(association)
+ next unless @relation_hash[association].is_a?(Array)
+ next if @relation_hash[association].empty?
+
+ @relation_hash[association].select! { |record| record.respond_to?(:user_id) }
+ @relation_hash[association].uniq!(&:user_id)
+ end
end
def generate_imported_object
diff --git a/lib/gitlab/import_export/base/relation_object_saver.rb b/lib/gitlab/import_export/base/relation_object_saver.rb
index d0fae2cbb95..ea989487ebd 100644
--- a/lib/gitlab/import_export/base/relation_object_saver.rb
+++ b/lib/gitlab/import_export/base/relation_object_saver.rb
@@ -15,7 +15,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
BATCH_SIZE = 100
- MIN_RECORDS_SIZE = 5
+ MIN_RECORDS_SIZE = 1
# @param relation_object [Object] Object of a project/group, e.g. an issue
# @param relation_key [String] Name of the object association to group/project, e.g. :issues
diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
index a185eb4df1c..c98dcf7b848 100644
--- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb
+++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb
@@ -28,25 +28,26 @@ module Gitlab
private
def validate
- pgrp = nil
+ pgrps = nil
valid_archive = true
validate_archive_path
Timeout.timeout(TIMEOUT_LIMIT) do
- stdin, stdout, stderr, wait_thr = Open3.popen3(command, pgroup: true)
- stdin.close
+ stderr_r, stderr_w = IO.pipe
+ stdout, wait_threads = Open3.pipeline_r(*command, pgroup: true, err: stderr_w )
# When validation is performed on a small archive (e.g. 100 bytes)
# `wait_thr` finishes before we can get process group id. Do not
# raise exception in this scenario.
- pgrp = begin
+ pgrps = wait_threads.map do |wait_thr|
Process.getpgid(wait_thr[:pid])
rescue Errno::ESRCH
nil
end
+ pgrps.compact!
- status = wait_thr.value
+ status = wait_threads.last.value
if status.success?
result = stdout.readline
@@ -64,20 +65,21 @@ module Gitlab
ensure
stdout.close
- stderr.close
+ stderr_w.close
+ stderr_r.close
end
valid_archive
rescue Timeout::Error
log_error('Timeout reached during archive decompression')
- Process.kill(-1, pgrp) if pgrp
+ pgrps.each { |pgrp| Process.kill(-1, pgrp) } if pgrps
false
rescue StandardError => e
log_error(e.message)
- Process.kill(-1, pgrp) if pgrp
+ pgrps.each { |pgrp| Process.kill(-1, pgrp) } if pgrps
false
end
@@ -91,7 +93,7 @@ module Gitlab
end
def command
- "gzip -dc #{@archive_path} | wc -c"
+ [['gzip', '-dc', @archive_path], ['wc', '-c']]
end
def log_error(error)
diff --git a/lib/gitlab/import_export/group/relation_tree_restorer.rb b/lib/gitlab/import_export/group/relation_tree_restorer.rb
index 4b28dd831fc..fab677bd772 100644
--- a/lib/gitlab/import_export/group/relation_tree_restorer.rb
+++ b/lib/gitlab/import_export/group/relation_tree_restorer.rb
@@ -89,7 +89,7 @@ module Gitlab
end
def save_relation_object(relation_object, relation_key, relation_definition, relation_index)
- if Feature.enabled?(:import_relation_object_persistence) && relation_object.new_record?
+ if relation_object.new_record?
Gitlab::ImportExport::Base::RelationObjectSaver.new(
relation_object: relation_object,
relation_key: relation_key,
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index 59396c6bad2..78f43f79072 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -18,11 +18,12 @@ module Gitlab
end
end
- def initialize(exportable, relations_schema, json_writer, exportable_path:)
+ def initialize(exportable, relations_schema, json_writer, exportable_path:, logger: Gitlab::Export::Logger)
@exportable = exportable
@exportable_path = exportable_path
@relations_schema = relations_schema
@json_writer = json_writer
+ @logger = logger
end
def execute
@@ -36,6 +37,8 @@ module Gitlab
end
def serialize_root(exportable_path = @exportable_path)
+ log_relation_export('root')
+
attributes = exportable.as_json(
relations_schema.merge(include: nil, preloads: nil, unsafe: true))
@@ -60,9 +63,11 @@ module Gitlab
private
- attr_reader :json_writer, :relations_schema, :exportable
+ attr_reader :json_writer, :relations_schema, :exportable, :logger
def serialize_many_relations(key, records, options)
+ log_relation_export(key, records.size)
+
enumerator = Enumerator.new do |items|
key_preloads = preloads&.dig(key)
@@ -106,6 +111,8 @@ module Gitlab
end
def serialize_many_each(key, records, options)
+ log_relation_export(key, records.size)
+
enumerator = Enumerator.new do |items|
records.each do |record|
items << Raw.new(record.to_json(options))
@@ -116,6 +123,8 @@ module Gitlab
end
def serialize_single_relation(key, record, options)
+ log_relation_export(key)
+
json = Raw.new(record.to_json(options))
json_writer.write_relation(@exportable_path, key, json)
@@ -186,6 +195,18 @@ module Gitlab
record.merge_request_diff&.remove_cached_external_diff
end
+
+ def log_base_data
+ log = { importer: 'Import/Export' }
+ log.merge!(Gitlab::ImportExport::LogUtil.exportable_to_log_payload(exportable))
+ log
+ end
+
+ def log_relation_export(relation, size = nil)
+ message = "Exporting #{relation} relation"
+ message += ". Number of records to export: #{size}" if size
+ logger.info(message: message, **log_base_data)
+ end
end
end
end
diff --git a/lib/gitlab/import_export/log_util.rb b/lib/gitlab/import_export/log_util.rb
new file mode 100644
index 00000000000..d3a3dce47ba
--- /dev/null
+++ b/lib/gitlab/import_export/log_util.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ class LogUtil
+ def self.exportable_to_log_payload(exportable)
+ attribute_base_name = exportable.class.name.underscore
+
+ return {} unless %w[project group].include?(attribute_base_name)
+
+ {}.tap do |log|
+ log[:"#{attribute_base_name}_id"] = exportable.id
+ log[:"#{attribute_base_name}_name"] = exportable.name
+ log[:"#{attribute_base_name}_path"] = exportable.full_path
+ end.compact
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index 50ff6146174..c5b8f3fd35b 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -53,8 +53,11 @@ tree:
- project_members:
- :user
- merge_requests:
+ - :approvals
- :metrics
- :award_emoji
+ - :merge_request_assignees
+ - :merge_request_reviewers
- notes:
- :author
- :award_emoji
@@ -120,6 +123,10 @@ included_attributes:
- :username
author:
- :name
+ approvals:
+ - :user_id
+ - :created_at
+ - :updated_at
ci_cd_settings:
- :group_runners_enabled
- :runner_token_expiration_interval
@@ -284,6 +291,9 @@ included_attributes:
- :security_and_compliance_access_level
- :container_registry_access_level
- :package_registry_access_level
+ - :environments_access_level
+ - :feature_flags_access_level
+ - :releases_access_level
prometheus_metrics:
- :created_at
- :updated_at
@@ -328,7 +338,6 @@ included_attributes:
- :source_branch
- :source_project_id
- :author_id
- - :assignee_id
- :title
- :created_at
- :updated_at
@@ -587,6 +596,14 @@ included_attributes:
- :author_id
issue_assignees:
- :user_id
+ merge_request_assignees:
+ - :user_id
+ - :created_at
+ - :state
+ merge_request_reviewers:
+ - :user_id
+ - :created_at
+ - :state
sentry_issue:
- :sentry_issue_identifier
zoom_meetings:
@@ -640,7 +657,6 @@ included_attributes:
- :auto_cancel_pending_pipelines
- :autoclose_referenced_issues
- :build_allow_git_fetch
- - :build_coverage_regex
- :build_timeout
- :delete_error
- :description
@@ -686,6 +702,9 @@ included_attributes:
- :security_and_compliance_access_level
- :container_registry_access_level
- :package_registry_access_level
+ - :environments_access_level
+ - :feature_flags_access_level
+ - :releases_access_level
- :allow_merge_on_skipped_pipeline
- :auto_devops_deploy_strategy
- :auto_devops_enabled
@@ -762,6 +781,9 @@ excluded_attributes:
- :repository_size_limit
- :external_webhook_token
- :incident_management_issuable_escalation_statuses
+ approvals:
+ - :id
+ - :merge_request_id
namespaces:
- :runners_token
- :runners_token_encrypted
diff --git a/lib/gitlab/import_export/project/relation_saver.rb b/lib/gitlab/import_export/project/relation_saver.rb
new file mode 100644
index 00000000000..b40827e36f8
--- /dev/null
+++ b/lib/gitlab/import_export/project/relation_saver.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ImportExport
+ module Project
+ class RelationSaver
+ def initialize(project:, shared:, relation:)
+ @project = project
+ @relation = relation
+ @shared = shared
+ end
+
+ def save
+ if root_relation?
+ serializer.serialize_root
+ else
+ serializer.serialize_relation(relation_schema)
+ end
+
+ true
+ rescue StandardError => e
+ shared.error(e)
+ false
+ end
+
+ private
+
+ attr_reader :project, :relation, :shared
+
+ def serializer
+ @serializer ||= ::Gitlab::ImportExport::Json::StreamingSerializer.new(
+ project,
+ reader.project_tree,
+ json_writer,
+ exportable_path: 'project'
+ )
+ end
+
+ def root_relation?
+ relation == Projects::ImportExport::RelationExport::ROOT_RELATION
+ end
+
+ def relation_schema
+ reader.project_tree[:include].find { |include| include[relation.to_sym] }
+ end
+
+ def reader
+ @reader ||= ::Gitlab::ImportExport::Reader.new(shared: shared)
+ end
+
+ def json_writer
+ @json_writer ||= ::Gitlab::ImportExport::Json::NdjsonWriter.new(shared.export_path)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/project/tree_saver.rb b/lib/gitlab/import_export/project/tree_saver.rb
index 05dcfa5282c..1b54e4b975e 100644
--- a/lib/gitlab/import_export/project/tree_saver.rb
+++ b/lib/gitlab/import_export/project/tree_saver.rb
@@ -8,7 +8,7 @@ module Gitlab
attr_reader :full_path
- def initialize(project:, current_user:, shared:, params: {}, logger: Gitlab::Import::Logger)
+ def initialize(project:, current_user:, shared:, params: {}, logger: Gitlab::Export::Logger)
@params = params
@project = project
@current_user = current_user
@@ -49,7 +49,8 @@ module Gitlab
exportable,
reader.project_tree,
json_writer,
- exportable_path: "project"
+ exportable_path: "project",
+ logger: @logger
)
Retriable.retriable(on: Net::OpenTimeout, on_retry: on_retry) do
diff --git a/lib/gitlab/import_export/remote_stream_upload.rb b/lib/gitlab/import_export/remote_stream_upload.rb
new file mode 100644
index 00000000000..f3bd241c0bd
--- /dev/null
+++ b/lib/gitlab/import_export/remote_stream_upload.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+# This class downloads a file from one URL and uploads it to another URL
+# without having to save the file on the disk and loading the whole file in
+# memory. The download and upload are performed in chunks size of
+# `buffer_size`. A chunk is downloaded, then uploaded, then a next chunk is
+# downloaded and uploaded. This repeats until all the file is processed.
+
+module Gitlab
+ module ImportExport
+ class RemoteStreamUpload
+ def initialize(download_url:, upload_url:, options: {})
+ @download_url = download_url
+ @upload_url = upload_url
+ @upload_method = options[:upload_method] || :post
+ @upload_content_type = options[:upload_content_type] || 'application/gzip'
+ end
+
+ def execute
+ receive_data(download_url) do |response, chunks|
+ send_data(upload_url, response.content_length, chunks) do |response|
+ if response.code != '200'
+ raise StreamError.new("Invalid response code while uploading file. Code: #{response.code}", response.body)
+ end
+ end
+ end
+ end
+ class StreamError < StandardError
+ attr_reader :response_body
+
+ def initialize(message, response_body = '')
+ super(message)
+ @response_body = response_body
+ end
+ end
+ class ChunkStream
+ DEFAULT_BUFFER_SIZE = 128.kilobytes
+
+ def initialize(chunks)
+ @chunks = chunks
+ @last_chunk = nil
+ @end_of_chunks = false
+ end
+
+ def read(n1 = nil, n2 = nil)
+ ensure_chunk&.read(n1, n2)
+ end
+
+ private
+
+ def ensure_chunk
+ return @last_chunk if @last_chunk && !@last_chunk.eof?
+ return if @end_of_chunks
+
+ @last_chunk = read_next_chunk
+ end
+
+ def read_next_chunk
+ next_chunk = StringIO.new
+
+ begin
+ next_chunk.write(@chunks.next) until next_chunk.size > DEFAULT_BUFFER_SIZE
+ rescue StopIteration
+ @end_of_chunks = true
+ end
+
+ next_chunk.rewind
+
+ next_chunk
+ end
+ end
+
+ private
+
+ attr_reader :download_url, :upload_url, :upload_method, :upload_content_type, :logger
+
+ def receive_data(uri)
+ http = Gitlab::HTTPConnectionAdapter.new(URI(uri), {}).connection
+
+ http.start do
+ request = Net::HTTP::Get.new(uri)
+ http.request(request) do |response|
+ if response.code == '200'
+ yield(response, response.enum_for(:read_body))
+ else
+ raise StreamError.new(
+ "Invalid response code while downloading file. Code: #{response.code}",
+ response.body
+ )
+ end
+ end
+ end
+ end
+
+ def send_data(uri, content_length, chunks)
+ http = Gitlab::HTTPConnectionAdapter.new(URI(uri), {}).connection
+
+ http.start do
+ request = upload_request_class(upload_method).new(uri)
+ request.body_stream = ChunkStream.new(chunks)
+ request.content_length = content_length
+ request.content_type = upload_content_type
+
+ http.request(request) do |response|
+ yield(response)
+ end
+ end
+ end
+
+ def upload_request_class(upload_method)
+ return Net::HTTP::Put if upload_method == :put
+
+ Net::HTTP::Post
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index 5cb1c1f8981..6337842255d 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -95,14 +95,9 @@ module Gitlab
end
def log_base_data
- log = {
- importer: 'Import/Export',
- exportable_id: @exportable&.id,
- exportable_path: @exportable&.full_path
- }
-
+ log = { importer: 'Import/Export' }
+ log.merge!(Gitlab::ImportExport::LogUtil.exportable_to_log_payload(@exportable))
log[:import_jid] = @exportable&.import_state&.jid if exportable_type == 'Project'
-
log
end
diff --git a/lib/gitlab/instrumentation/global_search_api.rb b/lib/gitlab/instrumentation/global_search_api.rb
new file mode 100644
index 00000000000..ea2f5702364
--- /dev/null
+++ b/lib/gitlab/instrumentation/global_search_api.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Instrumentation
+ class GlobalSearchApi
+ TYPE = 'meta.search.type'
+ LEVEL = 'meta.search.level'
+ SCOPE = 'meta.search.scope'
+ SEARCH_DURATION_S = :global_search_duration_s
+
+ def self.get_type
+ ::Gitlab::SafeRequestStore[TYPE]
+ end
+
+ def self.get_level
+ ::Gitlab::SafeRequestStore[LEVEL]
+ end
+
+ def self.get_scope
+ ::Gitlab::SafeRequestStore[SCOPE]
+ end
+
+ def self.get_search_duration_s
+ ::Gitlab::SafeRequestStore[SEARCH_DURATION_S]
+ end
+
+ def self.payload
+ {
+ TYPE => get_type,
+ LEVEL => get_level,
+ SCOPE => get_scope,
+ SEARCH_DURATION_S => get_search_duration_s
+ }.compact
+ end
+
+ def self.set_information(type:, level:, scope:, search_duration_s:)
+ if ::Gitlab::SafeRequestStore.active?
+ ::Gitlab::SafeRequestStore[TYPE] = type
+ ::Gitlab::SafeRequestStore[LEVEL] = level
+ ::Gitlab::SafeRequestStore[SCOPE] = scope
+ ::Gitlab::SafeRequestStore[SEARCH_DURATION_S] = search_duration_s
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/instrumentation_helper.rb b/lib/gitlab/instrumentation_helper.rb
index b8d8deb3418..b8a2567b775 100644
--- a/lib/gitlab/instrumentation_helper.rb
+++ b/lib/gitlab/instrumentation_helper.rb
@@ -34,6 +34,7 @@ module Gitlab
instrument_worker_id(payload)
instrument_uploads(payload)
instrument_rate_limiting_gates(payload)
+ instrument_global_search_api(payload)
end
def instrument_gitaly(payload)
@@ -131,6 +132,10 @@ module Gitlab
payload.merge!(::Gitlab::Instrumentation::RateLimitingGates.payload)
end
+ def instrument_global_search_api(payload)
+ payload.merge!(::Gitlab::Instrumentation::GlobalSearchApi.payload)
+ end
+
# Returns the queuing duration for a Sidekiq job in seconds, as a float, if the
# `enqueued_at` field or `created_at` field is available.
#
diff --git a/lib/gitlab/issues/rebalancing/state.rb b/lib/gitlab/issues/rebalancing/state.rb
index 3d3fd9419b2..abb50281f7a 100644
--- a/lib/gitlab/issues/rebalancing/state.rb
+++ b/lib/gitlab/issues/rebalancing/state.rb
@@ -38,10 +38,10 @@ module Gitlab
def rebalance_in_progress?
is_running = case rebalanced_container_type
when NAMESPACE
- namespace_ids = self.class.current_rebalancing_containers.map {|string| string.split("#{NAMESPACE}/").second.to_i }.compact
+ namespace_ids = self.class.current_rebalancing_containers.map { |string| string.split("#{NAMESPACE}/").second.to_i }.compact
namespace_ids.include?(root_namespace.id)
when PROJECT
- project_ids = self.class.current_rebalancing_containers.map {|string| string.split("#{PROJECT}/").second.to_i }.compact
+ project_ids = self.class.current_rebalancing_containers.map { |string| string.split("#{PROJECT}/").second.to_i }.compact
project_ids.include?(projects.take.id) # rubocop:disable CodeReuse/ActiveRecord
else
false
@@ -90,11 +90,11 @@ module Gitlab
end
def issue_count
- @issue_count ||= with_redis { |redis| redis.zcard(issue_ids_key)}
+ @issue_count ||= with_redis { |redis| redis.zcard(issue_ids_key) }
end
def remove_current_project_id_cache
- with_redis { |redis| redis.del(current_project_key)}
+ with_redis { |redis| redis.del(current_project_key) }
end
def refresh_keys_expiration
diff --git a/lib/gitlab/jira_import/issues_importer.rb b/lib/gitlab/jira_import/issues_importer.rb
index f1ead57c911..25dffcbe0ee 100644
--- a/lib/gitlab/jira_import/issues_importer.rb
+++ b/lib/gitlab/jira_import/issues_importer.rb
@@ -7,6 +7,10 @@ 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
@@ -66,6 +70,10 @@ module Gitlab
@issue_type_id,
{ 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
@@ -89,6 +97,27 @@ 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/job_waiter.rb b/lib/gitlab/job_waiter.rb
index 2cede524cac..52234b50a1f 100644
--- a/lib/gitlab/job_waiter.rb
+++ b/lib/gitlab/job_waiter.rb
@@ -35,7 +35,7 @@ module Gitlab
end
def self.key?(key)
- key.is_a?(String) && key =~ /\A#{KEY_PREFIX}:\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/
+ key.is_a?(String) && key =~ /\A#{KEY_PREFIX}:\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/o
end
attr_reader :key, :finished, :worker_label
diff --git a/lib/gitlab/kubernetes.rb b/lib/gitlab/kubernetes.rb
index 22bd00751bc..15163bd4a57 100644
--- a/lib/gitlab/kubernetes.rb
+++ b/lib/gitlab/kubernetes.rb
@@ -63,7 +63,11 @@ module Gitlab
return unless containers.present? && pod_name.present? && phase == "Running"
- created_at = DateTime.parse(metadata["creationTimestamp"]) rescue nil
+ created_at = begin
+ DateTime.parse(metadata["creationTimestamp"])
+ rescue StandardError
+ nil
+ end
containers.map do |container|
{
diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb
index 7a9dae3a3de..7d78c8dee25 100644
--- a/lib/gitlab/legacy_github_import/client.rb
+++ b/lib/gitlab/legacy_github_import/client.rb
@@ -136,7 +136,7 @@ module Gitlab
last_response = api.last_response
- if block_given?
+ if block
yield data
# api.last_response could change while we're yielding (e.g. fetching labels for each PR)
# so we cache our own last response
diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb
index ef5ca56a13b..f7cd28df5c9 100644
--- a/lib/gitlab/mail_room.rb
+++ b/lib/gitlab/mail_room.rb
@@ -33,11 +33,11 @@ module Gitlab
# fetched from YML config file.
MAILBOX_SPECIFIC_CONFIGS = {
incoming_email: {
- queue: 'email_receiver',
+ queue: 'default',
worker: 'EmailReceiverWorker'
},
service_desk_email: {
- queue: 'service_desk_email_receiver',
+ queue: 'default',
worker: 'ServiceDeskEmailReceiverWorker'
}
}.freeze
diff --git a/lib/gitlab/memory/jemalloc.rb b/lib/gitlab/memory/jemalloc.rb
index 454c54569de..7163a70a5cb 100644
--- a/lib/gitlab/memory/jemalloc.rb
+++ b/lib/gitlab/memory/jemalloc.rb
@@ -14,6 +14,8 @@ module Gitlab
STATS_DEFAULT_FORMAT = :json
+ FILENAME_PREFIX = 'jemalloc_stats'
+
# Return jemalloc stats as a string.
def stats(format: STATS_DEFAULT_FORMAT)
verify_format!(format)
@@ -23,16 +25,24 @@ module Gitlab
end
end
- # Write jemalloc stats to the given directory.
- def dump_stats(path:, format: STATS_DEFAULT_FORMAT)
+ # Write jemalloc stats to the given directory
+ # @param [String] path Directory path the dump will be put into
+ # @param [String] format `json` or `txt`
+ # @param [String] filename_label Optional custom string that will be injected into the file name, e.g. `worker_0`
+ # @return [String] Full path to the resulting dump file
+ def dump_stats(path:, format: STATS_DEFAULT_FORMAT, filename_label: nil)
verify_format!(format)
+ format_settings = STATS_FORMATS[format]
+ file_path = File.join(path, file_name(format_settings[:extension], filename_label))
+
with_malloc_stats_print do |stats_print|
- format_settings = STATS_FORMATS[format]
- File.open(File.join(path, file_name(format_settings[:extension])), 'wb') do |io|
+ File.open(file_path, 'wb') do |io|
write_stats(stats_print, io, format_settings)
end
end
+
+ file_path
end
private
@@ -80,8 +90,8 @@ module Gitlab
stats_print.call(callback, nil, format[:options])
end
- def file_name(extension)
- "jemalloc_stats.#{$$}.#{Time.current.to_i}.#{extension}"
+ def file_name(extension, filename_label)
+ [FILENAME_PREFIX, $$, filename_label, Time.current.to_i, extension].reject(&:blank?).join('.')
end
end
end
diff --git a/lib/gitlab/memory/reports/jemalloc_stats.rb b/lib/gitlab/memory/reports/jemalloc_stats.rb
new file mode 100644
index 00000000000..b99bec4ac3e
--- /dev/null
+++ b/lib/gitlab/memory/reports/jemalloc_stats.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ module Reports
+ class JemallocStats
+ # On prod, Jemalloc reports sizes were ~2.5 MB:
+ # https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/15993#note_1014767214
+ # We configured 1GB emptyDir per pod:
+ # https://gitlab.com/gitlab-com/gl-infra/k8s-workloads/gitlab-com/-/merge_requests/1949
+ # The pod will be evicted when the size limit is exceeded. We never want this to happen, for availability.
+ #
+ # With the default, we have a headroom (250*2.5MB=625<1000 MB) to fit into configured emptyDir.
+ # It would allow us to keep 3+ days worth of reports for 6 workers running every 2 hours: 3*6*12=216<250
+ #
+ # The cleanup logic will be redundant after we'll implement the uploads, which would perform the cleanup.
+ DEFAULT_MAX_REPORTS_STORED = 250
+
+ def initialize(reports_path:)
+ @reports_path = reports_path
+ end
+
+ def run
+ return unless active?
+
+ Gitlab::Memory::Jemalloc.dump_stats(path: reports_path, filename_label: worker_id).tap { cleanup }
+ end
+
+ def active?
+ Feature.enabled?(:report_jemalloc_stats, type: :ops)
+ end
+
+ private
+
+ attr_reader :reports_path
+
+ def cleanup
+ reports_files_modified_order[0...-max_reports_stored].each do |f|
+ File.unlink(f) if File.exist?(f)
+ rescue Errno::ENOENT
+ # Path does not exist: Ignore. We already check `File.exist?`
+ # Rescue to be extra safe, because each worker could perform a cleanup
+ end
+ end
+
+ def reports_files_modified_order
+ pattern = File.join(reports_path, "#{Gitlab::Memory::Jemalloc::FILENAME_PREFIX}*")
+
+ Dir.glob(pattern).sort_by do |f|
+ test('M', f)
+ rescue Errno::ENOENT
+ # Path does not exist: Return any timestamp to proceed with the sort
+ Time.current
+ end
+ end
+
+ def worker_id
+ ::Prometheus::PidProvider.worker_id
+ end
+
+ def max_reports_stored
+ ENV["GITLAB_DIAGNOSTIC_REPORTS_JEMALLOC_MAX_REPORTS_STORED"] || DEFAULT_MAX_REPORTS_STORED
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/reports_daemon.rb b/lib/gitlab/memory/reports_daemon.rb
new file mode 100644
index 00000000000..ed1da8baab5
--- /dev/null
+++ b/lib/gitlab/memory/reports_daemon.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ class ReportsDaemon < Daemon
+ DEFAULT_SLEEP_S = 7200 # 2 hours
+ DEFAULT_SLEEP_MAX_DELTA_S = 600 # 0..10 minutes
+ DEFAULT_SLEEP_BETWEEN_REPORTS_S = 120 # 2 minutes
+
+ DEFAULT_REPORTS_PATH = '/tmp'
+
+ def initialize(**options)
+ super
+
+ @alive = true
+
+ @sleep_s =
+ ENV['GITLAB_DIAGNOSTIC_REPORTS_SLEEP_S']&.to_i || DEFAULT_SLEEP_S
+ @sleep_max_delta_s =
+ ENV['GITLAB_DIAGNOSTIC_REPORTS_SLEEP_MAX_DELTA_S']&.to_i || DEFAULT_SLEEP_MAX_DELTA_S
+ @sleep_between_reports_s =
+ ENV['GITLAB_DIAGNOSTIC_REPORTS_SLEEP_BETWEEN_REPORTS_S']&.to_i || DEFAULT_SLEEP_BETWEEN_REPORTS_S
+
+ @reports_path =
+ ENV["GITLAB_DIAGNOSTIC_REPORTS_PATH"] || DEFAULT_REPORTS_PATH
+
+ @reports = [Gitlab::Memory::Reports::JemallocStats.new(reports_path: reports_path)]
+
+ init_prometheus_metrics
+ end
+
+ attr_reader :sleep_s, :sleep_max_delta_s, :sleep_between_reports_s, :reports_path
+
+ def run_thread
+ while alive
+ sleep interval_with_jitter
+
+ reports.select(&:active?).each do |report|
+ start_monotonic_time = Gitlab::Metrics::System.monotonic_time
+ start_thread_cpu_time = Gitlab::Metrics::System.thread_cpu_time
+
+ file_path = report.run
+
+ cpu_s = Gitlab::Metrics::System.thread_cpu_duration(start_thread_cpu_time)
+ duration_s = Gitlab::Metrics::System.monotonic_time - start_monotonic_time
+
+ log_report(label: report_label(report), cpu_s: cpu_s, duration_s: duration_s, size: file_size(file_path))
+ @report_duration_counter.increment({ report: report_label(report) }, duration_s)
+
+ sleep sleep_between_reports_s
+ end
+ end
+ end
+
+ private
+
+ attr_reader :alive, :reports
+
+ # Returns the sleep interval with a random adjustment.
+ # The random adjustment is put in place to ensure continued availability.
+ def interval_with_jitter
+ sleep_s + rand(sleep_max_delta_s)
+ end
+
+ def log_report(label:, duration_s:, cpu_s:, size:)
+ Gitlab::AppLogger.info(
+ message: 'finished',
+ pid: $$,
+ worker_id: worker_id,
+ perf_report: label,
+ duration_s: duration_s.round(2),
+ cpu_s: cpu_s.round(2),
+ perf_report_size_bytes: size
+ )
+ end
+
+ def worker_id
+ ::Prometheus::PidProvider.worker_id
+ end
+
+ def report_label(report)
+ report.class.to_s.demodulize.underscore
+ end
+
+ def stop_working
+ @alive = false
+ end
+
+ def init_prometheus_metrics
+ default_labels = { pid: worker_id }
+
+ @report_duration_counter = Gitlab::Metrics.counter(
+ :gitlab_diag_report_duration_seconds_total,
+ 'Total time elapsed for running diagnostic report',
+ default_labels
+ )
+ end
+
+ def file_size(file_path)
+ File.size(file_path.to_s)
+ rescue Errno::ENOENT
+ 0
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog.rb b/lib/gitlab/memory/watchdog.rb
index db75ba8a47d..91edb68ad66 100644
--- a/lib/gitlab/memory/watchdog.rb
+++ b/lib/gitlab/memory/watchdog.rb
@@ -15,7 +15,7 @@ module Gitlab
#
# The duration for which a process may be above a given fragmentation
# threshold is computed as `max_strikes * sleep_time_seconds`.
- class Watchdog < Daemon
+ class Watchdog
DEFAULT_SLEEP_TIME_SECONDS = 60
DEFAULT_HEAP_FRAG_THRESHOLD = 0.5
DEFAULT_MAX_STRIKES = 5
@@ -91,7 +91,7 @@ module Gitlab
attr_reader :strikes, :max_heap_fragmentation, :max_strikes, :sleep_time_seconds
- def run_thread
+ def call
@logger.info(log_labels.merge(message: 'started'))
while @alive
@@ -103,6 +103,10 @@ module Gitlab
@logger.info(log_labels.merge(message: 'stopped'))
end
+ def stop
+ @alive = false
+ end
+
private
def monitor_heap_fragmentation
@@ -141,10 +145,6 @@ module Gitlab
@handler
end
- def stop_working
- @alive = false
- end
-
def log_labels
{
pid: $$,
@@ -167,15 +167,13 @@ module Gitlab
end
def init_prometheus_metrics(max_heap_fragmentation)
- default_labels = { pid: worker_id }
-
@heap_frag_limit = Gitlab::Metrics.gauge(
:gitlab_memwd_heap_frag_limit,
- 'The configured limit for how fragmented the Ruby heap is allowed to be',
- default_labels
+ 'The configured limit for how fragmented the Ruby heap is allowed to be'
)
@heap_frag_limit.set({}, max_heap_fragmentation)
+ default_labels = { pid: worker_id }
@heap_frag_violations = Gitlab::Metrics.counter(
:gitlab_memwd_heap_frag_violations_total,
'Total number of times heap fragmentation in a Ruby process exceeded its allowed maximum',
diff --git a/lib/gitlab/merge_requests/mergeability/check_result.rb b/lib/gitlab/merge_requests/mergeability/check_result.rb
index 5284d20d423..a25156661af 100644
--- a/lib/gitlab/merge_requests/mergeability/check_result.rb
+++ b/lib/gitlab/merge_requests/mergeability/check_result.rb
@@ -13,11 +13,11 @@ module Gitlab
end
def self.success(payload: {})
- new(status: SUCCESS_STATUS, payload: default_payload.merge(payload))
+ new(status: SUCCESS_STATUS, payload: default_payload.merge(**payload))
end
def self.failed(payload: {})
- new(status: FAILED_STATUS, payload: default_payload.merge(payload))
+ new(status: FAILED_STATUS, payload: default_payload.merge(**payload))
end
def self.from_hash(data)
diff --git a/lib/gitlab/metrics/dashboard/url.rb b/lib/gitlab/metrics/dashboard/url.rb
index 6dcc73c0f6a..d4f779ad79d 100644
--- a/lib/gitlab/metrics/dashboard/url.rb
+++ b/lib/gitlab/metrics/dashboard/url.rb
@@ -42,7 +42,7 @@ module Gitlab
#{DASH_PATTERN}?
/grafana
/metrics_dashboard
- }x
+ }xo
)
end
end
@@ -64,7 +64,7 @@ module Gitlab
/(?<cluster_id>\d+)
/?
( (/metrics) | ( /metrics_dashboard\.json ) )?
- }x
+ }xo
)
end
end
@@ -82,7 +82,7 @@ module Gitlab
/alerts
/(?<alert>\d+)
/metrics_dashboard(\.json)?
- }x
+ }xo
)
end
end
@@ -112,7 +112,7 @@ module Gitlab
/environments
/(?<environment>\d+)
/(metrics_dashboard|metrics)
- }x
+ }xo
end
def non_environment_metrics_regex
@@ -125,7 +125,7 @@ module Gitlab
environment=(?<environment>\d+)
.*
)
- }x
+ }xo
end
def regex_for_project_metrics(path_suffix_pattern)
diff --git a/lib/gitlab/metrics/methods/metric_options.rb b/lib/gitlab/metrics/methods/metric_options.rb
index 1e488df3e99..e93a90415c7 100644
--- a/lib/gitlab/metrics/methods/metric_options.rb
+++ b/lib/gitlab/metrics/methods/metric_options.rb
@@ -61,7 +61,7 @@ module Gitlab
end
def evaluate(&block)
- instance_eval(&block) if block_given?
+ instance_eval(&block) if block
self
end
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 65c08664a2b..69e2ae55cb0 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -83,7 +83,11 @@ module Gitlab
end
def route_hash
- @route_hash ||= Rails.application.routes.recognize_path(request_url, { method: request.request_method }) rescue {}
+ @route_hash ||= begin
+ Rails.application.routes.recognize_path(request_url, { method: request.request_method })
+ rescue StandardError
+ {}
+ end
end
def request_url
diff --git a/lib/gitlab/null_request_store.rb b/lib/gitlab/null_request_store.rb
index 8db331dcb9f..4642dcf9e91 100644
--- a/lib/gitlab/null_request_store.rb
+++ b/lib/gitlab/null_request_store.rb
@@ -35,7 +35,7 @@ module Gitlab
end
def delete(key, &block)
- yield(key) if block_given?
+ yield(key) if block
end
end
end
diff --git a/lib/gitlab/object_hierarchy.rb b/lib/gitlab/object_hierarchy.rb
index 9a850246221..0576aed811c 100644
--- a/lib/gitlab/object_hierarchy.rb
+++ b/lib/gitlab/object_hierarchy.rb
@@ -65,7 +65,8 @@ module Gitlab
# Note: By default the order is breadth-first
# rubocop: disable CodeReuse/ActiveRecord
def base_and_ancestors(upto: nil, hierarchy_order: nil)
- cte = base_and_ancestors_cte(upto, hierarchy_order)
+ upto_id = upto.try(:id) || upto
+ cte = base_and_ancestors_cte(upto_id, hierarchy_order)
recursive_query = if hierarchy_order
# othewise depth won't be available for outer query
diff --git a/lib/gitlab/pagination/gitaly_keyset_pager.rb b/lib/gitlab/pagination/gitaly_keyset_pager.rb
index 8bbc9a93610..1f1061fe4f1 100644
--- a/lib/gitlab/pagination/gitaly_keyset_pager.rb
+++ b/lib/gitlab/pagination/gitaly_keyset_pager.rb
@@ -12,9 +12,11 @@ module Gitlab
@project = project
end
- # It is expected that the given finder will respond to `execute` method with `gitaly_pagination: true` option
+ # It is expected that the given finder will respond to `execute` method with `gitaly_pagination:` option
# and supports pagination via gitaly.
def paginate(finder)
+ return finder.execute(gitaly_pagination: false) if no_pagination?
+
return paginate_via_gitaly(finder) if keyset_pagination_enabled?(finder)
return paginate_first_page_via_gitaly(finder) if paginate_first_page?(finder)
@@ -26,6 +28,10 @@ module Gitlab
private
+ def no_pagination?
+ params[:pagination] == 'none'
+ end
+
def keyset_pagination_enabled?(finder)
return false unless params[:pagination] == "keyset"
diff --git a/lib/gitlab/patch/global_id.rb b/lib/gitlab/patch/global_id.rb
index 145a7bfe842..9b093186aec 100644
--- a/lib/gitlab/patch/global_id.rb
+++ b/lib/gitlab/patch/global_id.rb
@@ -9,7 +9,7 @@ module Gitlab
super
if deprecation = Gitlab::GlobalId::Deprecations.deprecation_for(model_name)
- @new_model_name = deprecation.new_model_name
+ @new_model_name = deprecation.new_name
end
end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index b05d7160a4b..b0804c2ff66 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -204,7 +204,7 @@ module Gitlab
end
def namespace_format_regex
- @namespace_format_regex ||= /\A#{NAMESPACE_FORMAT_REGEX}\z/.freeze
+ @namespace_format_regex ||= /\A#{NAMESPACE_FORMAT_REGEX}\z/o.freeze
end
def namespace_format_message
@@ -213,7 +213,7 @@ module Gitlab
end
def project_path_format_regex
- @project_path_format_regex ||= /\A#{PROJECT_PATH_FORMAT_REGEX}\z/.freeze
+ @project_path_format_regex ||= /\A#{PROJECT_PATH_FORMAT_REGEX}\z/o.freeze
end
def project_path_format_message
diff --git a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
index ac5c907465e..fbc77113875 100644
--- a/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
+++ b/lib/gitlab/performance_bar/redis_adapter_when_peek_enabled.rb
@@ -17,7 +17,7 @@ module Gitlab
# to a structured log
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def enqueue_stats_job(request_id)
- return unless Feature.enabled?(:performance_bar_stats)
+ return unless Feature.enabled?(:performance_bar_stats, type: :ops)
@client.sadd(GitlabPerformanceBarStatsWorker::STATS_KEY, request_id)
diff --git a/lib/gitlab/process_management.rb b/lib/gitlab/process_management.rb
index 25a198e4a6a..f8a1a3a97de 100644
--- a/lib/gitlab/process_management.rb
+++ b/lib/gitlab/process_management.rb
@@ -43,7 +43,9 @@ module Gitlab
# Waits for the given process to complete using a separate thread.
def self.wait_async(pid)
Thread.new do
- Process.wait(pid) rescue Errno::ECHILD
+ Process.wait(pid)
+ rescue StandardError
+ nil # There is no reason to return `Errno::ECHILD` if it catches a `TypeError`
end
end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index d15b57eb888..fd9f73d18c1 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -146,7 +146,7 @@ module Gitlab
if user
API::Helpers::CommonHelpers.send(:define_method, :find_current_user!) { user } # rubocop:disable GitlabSecurity/PublicSend
ApplicationController.send(:define_method, :current_user) { user } # rubocop:disable GitlabSecurity/PublicSend
- ApplicationController.send(:define_method, :authenticate_user!) { } # rubocop:disable GitlabSecurity/PublicSend
+ ApplicationController.send(:define_method, :authenticate_user!) {} # rubocop:disable GitlabSecurity/PublicSend
end
yield.tap do
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 0ab6055408f..6673940ccf3 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -49,7 +49,7 @@ module Gitlab
ProjectTemplate.new('spring', 'Spring', _('Includes an MVC structure, mvnw and pom.xml to help you get started'), 'https://gitlab.com/gitlab-org/project-templates/spring', 'illustrations/logos/spring.svg'),
ProjectTemplate.new('express', 'NodeJS Express', _('Includes an MVC structure to help you get started'), 'https://gitlab.com/gitlab-org/project-templates/express', 'illustrations/logos/express.svg'),
ProjectTemplate.new('iosswift', 'iOS (Swift)', _('A ready-to-go template for use with iOS Swift apps'), 'https://gitlab.com/gitlab-org/project-templates/iosswift', 'illustrations/logos/swift.svg'),
- ProjectTemplate.new('dotnetcore', '.NET Core', _('A .NET Core console application template, customizable for any .NET Core project'), 'https://gitlab.com/gitlab-org/project-templates/dotnetcore', 'illustrations/logos/dotnet.svg'),
+ ProjectTemplate.new('dotnetcore', '.NET Core', _('A .NET Core console application template, customizable for any .NET Core project'), 'https://gitlab.com/gitlab-org/project-templates/dotnetcore', 'illustrations/third-party-logos/dotnet.svg'),
ProjectTemplate.new('android', 'Android', _('A ready-to-go template for use with Android apps'), 'https://gitlab.com/gitlab-org/project-templates/android', 'illustrations/logos/android.svg'),
ProjectTemplate.new('gomicro', 'Go Micro', _('Go Micro is a framework for micro service development'), 'https://gitlab.com/gitlab-org/project-templates/go-micro', 'illustrations/logos/gomicro.svg'),
ProjectTemplate.new('gatsby', 'Pages/Gatsby', _('Everything you need to create a GitLab Pages site using Gatsby'), 'https://gitlab.com/pages/gatsby', 'illustrations/third-party-logos/gatsby.svg'),
diff --git a/lib/gitlab/query_limiting/middleware.rb b/lib/gitlab/query_limiting/middleware.rb
index 76de547b14f..0ee700caf5b 100644
--- a/lib/gitlab/query_limiting/middleware.rb
+++ b/lib/gitlab/query_limiting/middleware.rb
@@ -46,7 +46,11 @@ module Gitlab
def action_for_grape(env)
endpoint = env[ENDPOINT_KEY]
- route = endpoint.route rescue nil
+ route = begin
+ endpoint.route
+ rescue StandardError
+ nil
+ end
"#{route.request_method} #{route.path}" if route
end
diff --git a/lib/gitlab/quick_actions/command_definition.rb b/lib/gitlab/quick_actions/command_definition.rb
index fcb7bc967ca..d9135d1bacb 100644
--- a/lib/gitlab/quick_actions/command_definition.rb
+++ b/lib/gitlab/quick_actions/command_definition.rb
@@ -89,17 +89,29 @@ module Gitlab
def to_h(context)
desc = description
if desc.respond_to?(:call)
- desc = context.instance_exec(&desc) rescue ''
+ desc = begin
+ context.instance_exec(&desc)
+ rescue StandardError
+ ''
+ end
end
warn = warning
if warn.respond_to?(:call)
- warn = context.instance_exec(&warn) rescue ''
+ warn = begin
+ context.instance_exec(&warn)
+ rescue StandardError
+ ''
+ end
end
prms = params
if prms.respond_to?(:call)
- prms = Array(context.instance_exec(&prms)) rescue params
+ prms = begin
+ Array(context.instance_exec(&prms))
+ rescue StandardError
+ params
+ end
end
{
diff --git a/lib/gitlab/quick_actions/dsl.rb b/lib/gitlab/quick_actions/dsl.rb
index a2dfcc6de9a..dfbc00ef847 100644
--- a/lib/gitlab/quick_actions/dsl.rb
+++ b/lib/gitlab/quick_actions/dsl.rb
@@ -30,11 +30,11 @@ module Gitlab
# # Awesome code block
# end
def desc(text = '', &block)
- @description = block_given? ? block : text
+ @description = block || text
end
def warning(text = '', &block)
- @warning = block_given? ? block : text
+ @warning = block || text
end
def icon(string = '')
@@ -51,7 +51,7 @@ module Gitlab
# # Awesome code block
# end
def params(*params, &block)
- @params = block_given? ? block : params
+ @params = block || params
end
# Allows to give an explanation of what the command will do when
@@ -67,7 +67,7 @@ module Gitlab
# # Awesome code block
# end
def explanation(text = '', &block)
- @explanation = block_given? ? block : text
+ @explanation = block || text
end
# Allows to provide a message about quick action execution result, success or failure.
@@ -96,7 +96,7 @@ module Gitlab
# end
#
def execution_message(text = '', &block)
- @execution_message = block_given? ? block : text
+ @execution_message = block || text
end
# Allows to define type(s) that must be met in order for the command
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index 167e7ad67a9..3cb01db1491 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -292,76 +292,6 @@ module Gitlab
@updates[:reviewer_ids] = []
end
end
-
- desc do
- if quick_action_target.allows_multiple_reviewers?
- _('Request attention from assignee(s) or reviewer(s)')
- else
- _('Request attention from assignee or reviewer')
- end
- end
- explanation do |users|
- _('Request attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
- end
- execution_message do |users = nil|
- if users.blank?
- _("Failed to request attention because no user was found.")
- else
- _('Requested attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
- end
- end
- params do
- quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
- end
- types MergeRequest
- condition do
- current_user.mr_attention_requests_enabled? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
- end
- parse_params do |attention_param|
- extract_users(attention_param)
- end
- command :attention, :attn do |users|
- next if users.empty?
-
- users.each do |user|
- ::MergeRequests::ToggleAttentionRequestedService.new(project: quick_action_target.project, merge_request: quick_action_target, current_user: current_user, user: user).execute
- end
- end
-
- desc do
- if quick_action_target.allows_multiple_reviewers?
- _('Remove attention request(s)')
- else
- _('Remove attention request')
- end
- end
- explanation do |users|
- _('Removes attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
- end
- execution_message do |users = nil|
- if users.blank?
- _("Failed to remove attention because no user was found.")
- else
- _('Removed attention from %{users_sentence}.') % { users_sentence: reviewer_users_sentence(users) }
- end
- end
- params do
- quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
- end
- types MergeRequest
- condition do
- current_user.mr_attention_requests_enabled? &&
- current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
- end
- parse_params do |attention_param|
- extract_users(attention_param)
- end
- command :remove_attention do |users|
- next if users.empty?
-
- ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: quick_action_target.project, merge_request: quick_action_target, current_user: current_user, users: users).execute
- end
end
def reviewer_users_sentence(users)
diff --git a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
index 03b2a1086bb..3794f2f8818 100644
--- a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
+++ b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
@@ -43,7 +43,11 @@ module Gitlab
def valid_date?
string_date = @spend_arg.match(DATE_REGEX)[0]
- date = Date.parse(string_date) rescue nil
+ date = begin
+ Date.parse(string_date)
+ rescue StandardError
+ nil
+ end
date_past_or_today?(date)
end
diff --git a/lib/gitlab/redis/cache.rb b/lib/gitlab/redis/cache.rb
index a2c7b5e29db..4ab1024d528 100644
--- a/lib/gitlab/redis/cache.rb
+++ b/lib/gitlab/redis/cache.rb
@@ -12,7 +12,7 @@ module Gitlab
redis: pool,
compress: Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_REDIS_CACHE_COMPRESSION', '1')),
namespace: CACHE_NAMESPACE,
- expires_in: 2.weeks # Cache should not grow forever
+ expires_in: ENV.fetch('GITLAB_RAILS_CACHE_DEFAULT_TTL_SECONDS', 2.weeks).to_i # Cache should not grow forever
}
end
end
diff --git a/lib/gitlab/redis/multi_store.rb b/lib/gitlab/redis/multi_store.rb
index 94f06e957cf..cdd2ac6100e 100644
--- a/lib/gitlab/redis/multi_store.rb
+++ b/lib/gitlab/redis/multi_store.rb
@@ -274,7 +274,7 @@ module Gitlab
# rubocop:disable GitlabSecurity/PublicSend
def send_command(redis_instance, command_name, *args, **kwargs, &block)
- if block_given?
+ if block
# Make sure that block is wrapped and executed only on the redis instance that is executing the block
redis_instance.send(command_name, *args, **kwargs) do |*params|
with_instance(redis_instance, *params, &block)
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 551750f9798..10c03103899 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -70,7 +70,7 @@ module Gitlab
end
def npm_package_name_regex
- @npm_package_name_regex ||= %r{\A(?:@(#{Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX})/)?[-+\.\_a-zA-Z0-9]+\z}
+ @npm_package_name_regex ||= %r{\A(?:@(#{Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX})/)?[-+\.\_a-zA-Z0-9]+\z}o
end
def nuget_package_name_regex
@@ -128,15 +128,15 @@ module Gitlab
def debian_architecture_regex
# See official parser: https://git.dpkg.org/cgit/dpkg/dpkg.git/tree/lib/dpkg/arch.c?id=9e0c88ec09475f4d1addde9cdba1ad7849720356#n43
# But we limit to lower case
- @debian_architecture_regex ||= %r{\A#{::Packages::Debian::ARCHITECTURE_REGEX}\z}.freeze
+ @debian_architecture_regex ||= %r{\A#{::Packages::Debian::ARCHITECTURE_REGEX}\z}o.freeze
end
def debian_distribution_regex
- @debian_distribution_regex ||= %r{\A#{::Packages::Debian::DISTRIBUTION_REGEX}\z}i.freeze
+ @debian_distribution_regex ||= %r{\A#{::Packages::Debian::DISTRIBUTION_REGEX}\z}io.freeze
end
def debian_component_regex
- @debian_component_regex ||= %r{\A#{::Packages::Debian::COMPONENT_REGEX}\z}.freeze
+ @debian_component_regex ||= %r{\A#{::Packages::Debian::COMPONENT_REGEX}\z}o.freeze
end
def helm_channel_regex
diff --git a/lib/gitlab/relative_positioning/item_context.rb b/lib/gitlab/relative_positioning/item_context.rb
index ac0598d8d34..a9966c0f3fb 100644
--- a/lib/gitlab/relative_positioning/item_context.rb
+++ b/lib/gitlab/relative_positioning/item_context.rb
@@ -91,8 +91,7 @@ module Gitlab
relation = yield relation if block_given?
relation
- .pluck(grouping_column, Arel.sql("#{calculation}(relative_position) AS position"))
- .first&.last
+ .pick(grouping_column, Arel.sql("#{calculation}(relative_position) AS position"))&.last
end
def grouping_column
@@ -163,9 +162,7 @@ module Gitlab
gap = model_class
.from(items_with_next_pos, :items)
.where('next_pos IS NULL OR ABS(pos::bigint - next_pos::bigint) >= ?', MIN_GAP)
- .limit(1)
- .pluck(:pos, :next_pos)
- .first
+ .pick(:pos, :next_pos)
return if gap.nil? || gap.first == default_end
diff --git a/lib/gitlab/saas.rb b/lib/gitlab/saas.rb
index 4683f611444..16a7a697e6a 100644
--- a/lib/gitlab/saas.rb
+++ b/lib/gitlab/saas.rb
@@ -52,6 +52,10 @@ module Gitlab
def self.doc_url
'https://docs.gitlab.com'
end
+
+ def self.community_forum_url
+ 'https://forum.gitlab.com'
+ end
end
end
diff --git a/lib/gitlab/safe_request_loader.rb b/lib/gitlab/safe_request_loader.rb
index 89eca16c272..4fc88322210 100644
--- a/lib/gitlab/safe_request_loader.rb
+++ b/lib/gitlab/safe_request_loader.rb
@@ -14,7 +14,7 @@ module Gitlab
end
def execute(&block)
- raise ArgumentError, 'Block is mandatory' unless block_given?
+ raise ArgumentError, 'Block is mandatory' unless block
load_resource_data
remove_loaded_resource_ids
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb
index 97ee7c7817d..4c5fae87420 100644
--- a/lib/gitlab/search/query.rb
+++ b/lib/gitlab/search/query.rb
@@ -13,7 +13,7 @@ module Gitlab
@filters = []
@filter_options = { default_parser: :downcase.to_proc }.merge(filter_opts)
- self.instance_eval(&block) if block_given?
+ self.instance_eval(&block) if block
@query = Gitlab::Search::ParsedQuery.new(*extract_filters)
# set the ParsedQuery as our default delegator thanks to SimpleDelegator
diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb
index ec514adafc8..2450ad88bbb 100644
--- a/lib/gitlab/seeder.rb
+++ b/lib/gitlab/seeder.rb
@@ -151,6 +151,48 @@ module Gitlab
model.logger = old_loggers[connection_name]
end
end
+
+ module Ci
+ class DailyBuildGroupReportResult
+ DEFAULT_BRANCH = 'master'
+ COUNT_OF_DAYS = 5
+
+ def initialize(project)
+ @project = project
+ @last_pipeline = project.last_pipeline
+ end
+
+ def seed
+ COUNT_OF_DAYS.times do |count|
+ date = Time.now.utc - count.day
+ create_report(date)
+ end
+ end
+
+ private
+
+ attr_reader :project, :last_pipeline
+
+ def create_report(date)
+ last_pipeline.builds.uniq(&:group_name).each do |build|
+ ::Ci::DailyBuildGroupReportResult.create(
+ project: project,
+ last_pipeline: last_pipeline,
+ date: date,
+ ref_path: last_pipeline.source_ref_path,
+ group_name: build.group_name,
+ data: {
+ 'coverage' => rand(20..99)
+ },
+ group: project.group,
+ default_branch: last_pipeline.default_branch?
+ )
+ rescue ActiveRecord::RecordNotUnique
+ return false
+ end
+ end
+ end
+ end
end
end
# :nocov:
diff --git a/lib/gitlab/sidekiq_daemon/memory_killer.rb b/lib/gitlab/sidekiq_daemon/memory_killer.rb
index cb7d9c6f8a7..ca92fed9c40 100644
--- a/lib/gitlab/sidekiq_daemon/memory_killer.rb
+++ b/lib/gitlab/sidekiq_daemon/memory_killer.rb
@@ -44,7 +44,8 @@ module Gitlab
sidekiq_current_rss: ::Gitlab::Metrics.gauge(:sidekiq_current_rss, 'Current RSS of Sidekiq Worker'),
sidekiq_memory_killer_soft_limit_rss: ::Gitlab::Metrics.gauge(:sidekiq_memory_killer_soft_limit_rss, 'Current soft_limit_rss of Sidekiq Worker'),
sidekiq_memory_killer_hard_limit_rss: ::Gitlab::Metrics.gauge(:sidekiq_memory_killer_hard_limit_rss, 'Current hard_limit_rss of Sidekiq Worker'),
- sidekiq_memory_killer_phase: ::Gitlab::Metrics.gauge(:sidekiq_memory_killer_phase, 'Current phase of Sidekiq Worker')
+ sidekiq_memory_killer_phase: ::Gitlab::Metrics.gauge(:sidekiq_memory_killer_phase, 'Current phase of Sidekiq Worker'),
+ sidekiq_memory_killer_running_jobs: ::Gitlab::Metrics.counter(:sidekiq_memory_killer_running_jobs_total, 'Current running jobs when limit was reached')
}
end
@@ -166,6 +167,8 @@ module Gitlab
@soft_limit_rss,
deadline_exceeded)
+ running_jobs = fetch_running_jobs
+
Sidekiq.logger.warn(
class: self.class.to_s,
pid: pid,
@@ -175,9 +178,17 @@ module Gitlab
hard_limit_rss: @hard_limit_rss,
reason: reason,
running_jobs: running_jobs)
+
+ increment_worker_counters(running_jobs, deadline_exceeded)
+ end
+
+ def increment_worker_counters(running_jobs, deadline_exceeded)
+ running_jobs.each do |job|
+ @metrics[:sidekiq_memory_killer_running_jobs].increment( { worker_class: job[:worker_class], deadline_exceeded: deadline_exceeded } )
+ end
end
- def running_jobs
+ def fetch_running_jobs
jobs = []
Gitlab::SidekiqDaemon::Monitor.instance.jobs_mutex.synchronize do
jobs = Gitlab::SidekiqDaemon::Monitor.instance.jobs.map do |jid, job|
diff --git a/lib/gitlab/sidekiq_logging/logs_jobs.rb b/lib/gitlab/sidekiq_logging/logs_jobs.rb
index de08de6632b..3e6e6e05e95 100644
--- a/lib/gitlab/sidekiq_logging/logs_jobs.rb
+++ b/lib/gitlab/sidekiq_logging/logs_jobs.rb
@@ -12,7 +12,6 @@ module Gitlab
# Error information from the previous try is in the payload for
# displaying in the Sidekiq UI, but is very confusing in logs!
job = job.except(
- 'error_backtrace', 'error_class', 'error_message',
'exception.backtrace', 'exception.class', 'exception.message', 'exception.sql'
)
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index ea2b405c934..180cdad916b 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -35,7 +35,8 @@ module Gitlab
sidekiq_redis_requests_total: ::Gitlab::Metrics.counter(:sidekiq_redis_requests_total, 'Redis requests during a Sidekiq job execution'),
sidekiq_elasticsearch_requests_total: ::Gitlab::Metrics.counter(:sidekiq_elasticsearch_requests_total, 'Elasticsearch requests during a Sidekiq job execution'),
sidekiq_running_jobs: ::Gitlab::Metrics.gauge(:sidekiq_running_jobs, 'Number of Sidekiq jobs running', {}, :all),
- sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all)
+ sidekiq_concurrency: ::Gitlab::Metrics.gauge(:sidekiq_concurrency, 'Maximum number of Sidekiq jobs', {}, :all),
+ sidekiq_mem_total_bytes: ::Gitlab::Metrics.gauge(:sidekiq_mem_total_bytes, 'Number of bytes allocated for both objects consuming an object slot and objects that required a malloc', {}, :all)
}
end
@@ -123,6 +124,7 @@ module Gitlab
@metrics[:sidekiq_redis_requests_duration_seconds].observe(labels, get_redis_time(instrumentation))
@metrics[:sidekiq_elasticsearch_requests_total].increment(labels, get_elasticsearch_calls(instrumentation))
@metrics[:sidekiq_elasticsearch_requests_duration_seconds].observe(labels, get_elasticsearch_time(instrumentation))
+ @metrics[:sidekiq_mem_total_bytes].set(labels, get_thread_memory_total_allocations(instrumentation))
with_load_balancing_settings(job) do |settings|
load_balancing_labels = {
@@ -160,6 +162,10 @@ module Gitlab
payload.fetch(:elasticsearch_duration_s, 0)
end
+ def get_thread_memory_total_allocations(payload)
+ payload.fetch(:mem_total_bytes, 0)
+ end
+
def get_elasticsearch_calls(payload)
payload.fetch(:elasticsearch_calls, 0)
end
diff --git a/lib/gitlab/ssh/commit.rb b/lib/gitlab/ssh/commit.rb
new file mode 100644
index 00000000000..bfeefc47f13
--- /dev/null
+++ b/lib/gitlab/ssh/commit.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ssh
+ class Commit < Gitlab::SignedCommit
+ private
+
+ def signature_class
+ CommitSignatures::SshSignature
+ end
+
+ def attributes
+ signature = ::Gitlab::Ssh::Signature.new(signature_text, signed_text, @commit.committer_email)
+
+ {
+ commit_sha: @commit.sha,
+ project: @commit.project,
+ key_id: signature.signed_by_key&.id,
+ verification_status: signature.verification_status
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ssh/signature.rb b/lib/gitlab/ssh/signature.rb
index 1a236e1a70c..3b4df9a8d0c 100644
--- a/lib/gitlab/ssh/signature.rb
+++ b/lib/gitlab/ssh/signature.rb
@@ -26,6 +26,14 @@ module Gitlab
end
end
+ def signed_by_key
+ strong_memoize(:signed_by_key) do
+ next unless key_fingerprint
+
+ Key.find_by_fingerprint_sha256(key_fingerprint)
+ end
+ end
+
private
def all_attributes_present?
@@ -61,14 +69,6 @@ module Gitlab
def key_fingerprint
strong_memoize(:key_fingerprint) { signature&.public_key&.fingerprint }
end
-
- def signed_by_key
- strong_memoize(:signed_by_key) do
- next unless key_fingerprint
-
- Key.find_by_fingerprint_sha256(key_fingerprint)
- end
- end
end
end
end
diff --git a/lib/gitlab/string_placeholder_replacer.rb b/lib/gitlab/string_placeholder_replacer.rb
index 62621255a53..f77bd8e2d9f 100644
--- a/lib/gitlab/string_placeholder_replacer.rb
+++ b/lib/gitlab/string_placeholder_replacer.rb
@@ -10,7 +10,7 @@ module Gitlab
# placeholder will be returned.
def self.replace_string_placeholders(string, placeholder_regex = nil, &block)
- return string if string.blank? || placeholder_regex.blank? || !block_given?
+ return string if string.blank? || placeholder_regex.blank? || !block
replace_placeholders(string, placeholder_regex, &block)
end
diff --git a/lib/gitlab/terraform/state_migration_helper.rb b/lib/gitlab/terraform/state_migration_helper.rb
index 04c1cbd0373..e86144f91a5 100644
--- a/lib/gitlab/terraform/state_migration_helper.rb
+++ b/lib/gitlab/terraform/state_migration_helper.rb
@@ -22,7 +22,7 @@ module Gitlab
versions.find_each(batch_size: batch_size) do |version| # rubocop:disable CodeReuse/ActiveRecord
version.file.migrate!(store)
- yield version if block_given?
+ yield version if block
end
end
end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 04745bafe7c..3b46b4c5498 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -41,7 +41,7 @@ module Gitlab
def snowplow_micro_enabled?
Rails.env.development? && Gitlab.config.snowplow_micro.enabled
rescue Settingslogic::MissingSetting
- Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE'])
+ false
end
private
diff --git a/lib/gitlab/tracking/destinations/snowplow_micro.rb b/lib/gitlab/tracking/destinations/snowplow_micro.rb
index c7a95e88d0b..09480f26106 100644
--- a/lib/gitlab/tracking/destinations/snowplow_micro.rb
+++ b/lib/gitlab/tracking/destinations/snowplow_micro.rb
@@ -54,7 +54,7 @@ module Gitlab
scheme = Gitlab.config.gitlab.https ? 'https' : 'http'
"#{scheme}://#{url}"
rescue Settingslogic::MissingSetting
- ENV['SNOWPLOW_MICRO_URI'] || DEFAULT_URI
+ DEFAULT_URI
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index f76ed1753b2..5e20766b1b4 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -13,7 +13,7 @@ module Gitlab
class << self
def available?(&block)
- return @metric_available = block if block_given?
+ return @metric_available = block if block
return @metric_available.call if instance_variable_defined?('@metric_available')
diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
index 3b09100f3ff..6dec0349a38 100644
--- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
@@ -23,42 +23,48 @@ module Gitlab
private_constant :IMPLEMENTED_OPERATIONS
def start(&block)
- return @metric_start&.call unless block_given?
+ return @metric_start&.call unless block
@metric_start = block
end
def finish(&block)
- return @metric_finish&.call unless block_given?
+ return @metric_finish&.call unless block
@metric_finish = block
end
def relation(&block)
- return @metric_relation&.call unless block_given?
+ return @metric_relation&.call unless block
@metric_relation = block
end
def metric_options(&block)
- return @metric_options&.call.to_h unless block_given?
+ return @metric_options&.call.to_h unless block
@metric_options = block
end
+ def timestamp_column(symbol)
+ @metric_timestamp_column = symbol
+ end
+
def operation(symbol, column: nil, &block)
raise UnimplementedOperationError unless symbol.in?(IMPLEMENTED_OPERATIONS)
@metric_operation = symbol
@column = column
- @metric_operation_block = block if block_given?
+ @metric_operation_block = block if block
end
def cache_start_and_finish_as(cache_key)
@cache_key = cache_key
end
- attr_reader :metric_operation, :metric_relation, :metric_start, :metric_finish, :metric_operation_block, :column, :cache_key
+ attr_reader :metric_operation, :metric_relation, :metric_start,
+ :metric_finish, :metric_operation_block,
+ :column, :cache_key, :metric_timestamp_column
end
def value
@@ -106,7 +112,7 @@ module Gitlab
def time_constraints
case time_frame
when '28d'
- monthly_time_range_db_params
+ monthly_time_range_db_params(column: self.class.metric_timestamp_column)
when 'all'
{}
when 'none'
diff --git a/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb b/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb
index 8504ee368fc..3b20e6ad100 100644
--- a/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/numbers_metric.rb
@@ -26,7 +26,7 @@ module Gitlab
private_constant :IMPLEMENTED_OPERATIONS
def data(&block)
- return @metric_data&.call unless block_given?
+ return @metric_data&.call unless block
@metric_data = block
end
diff --git a/lib/gitlab/usage/time_frame.rb b/lib/gitlab/usage/time_frame.rb
index 966a087ee07..39b0855b917 100644
--- a/lib/gitlab/usage/time_frame.rb
+++ b/lib/gitlab/usage/time_frame.rb
@@ -6,6 +6,7 @@ module Gitlab
ALL_TIME_TIME_FRAME_NAME = "all"
SEVEN_DAYS_TIME_FRAME_NAME = "7d"
TWENTY_EIGHT_DAYS_TIME_FRAME_NAME = "28d"
+ DEFAULT_TIMESTAMP_COLUMN = :created_at
def weekly_time_range
{ start_date: 7.days.ago.to_date, end_date: Date.current }
@@ -17,8 +18,8 @@ module Gitlab
# This time range is skewed for batch counter performance.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42972
- def monthly_time_range_db_params(column: :created_at)
- { column => 30.days.ago..2.days.ago }
+ def monthly_time_range_db_params(column: nil)
+ { (column || DEFAULT_TIMESTAMP_COLUMN) => 30.days.ago..2.days.ago }
end
end
end
diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb
index 2a3dcf267c6..224897ed758 100644
--- a/lib/gitlab/usage_data_counters.rb
+++ b/lib/gitlab/usage_data_counters.rb
@@ -16,7 +16,8 @@ module Gitlab
DesignsCounter,
KubernetesAgentCounter,
DiffsCounter,
- ServiceUsageDataCounter
+ ServiceUsageDataCounter,
+ MergeRequestWidgetExtensionCounter
].freeze
UsageDataCounterError = Class.new(StandardError)
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 40581bda81b..a5db8ba4dcc 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -32,7 +32,6 @@ module Gitlab
issues_edit
pipeline_authoring
quickactions
- search
user_packages
].freeze
@@ -42,7 +41,9 @@ module Gitlab
ide_edit
importer
incident_management_alerts
+ kubernetes_agent
pipeline_authoring
+ search
secure
snippets
source_code
@@ -114,6 +115,10 @@ module Gitlab
@categories ||= known_events.map { |event| event[:category] }.uniq
end
+ def categories_collected_from_metrics_definitions
+ CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS
+ end
+
# @param category [String] the category name
# @return [Array<String>] list of event names for given category
def events_for_category(category)
@@ -163,11 +168,7 @@ module Gitlab
private
def categories_pending_migration
- if ::Feature.enabled?(:use_redis_hll_instrumentation_classes)
- (categories - CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
- else
- categories
- end
+ (categories - categories_collected_from_metrics_definitions)
end
def track(values, event_name, context: '', time: Time.zone.now)
diff --git a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
index 9d463e11772..316d9bb3dc1 100644
--- a/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -4,6 +4,8 @@ module Gitlab
module UsageDataCounters
module IssueActivityUniqueCounter
ISSUE_CATEGORY = 'issues_edit'
+ ISSUE_ACTION = 'perform_issue_action'
+ ISSUE_LABEL = 'redis_hll_counters.issues_edit.issues_edit_total_unique_counts_monthly'
ISSUE_ASSIGNEE_CHANGED = 'g_project_management_issue_assignee_changed'
ISSUE_CREATED = 'g_project_management_issue_created'
@@ -126,42 +128,48 @@ module Gitlab
track_unique_action(ISSUE_TIME_SPENT_CHANGED, author)
end
- def track_issue_comment_added_action(author:)
+ def track_issue_comment_added_action(author:, project:)
+ track_snowplow_action(ISSUE_COMMENT_ADDED, author, project)
track_unique_action(ISSUE_COMMENT_ADDED, author)
end
- def track_issue_comment_edited_action(author:)
+ def track_issue_comment_edited_action(author:, project:)
+ track_snowplow_action(ISSUE_COMMENT_EDITED, author, project)
track_unique_action(ISSUE_COMMENT_EDITED, author)
end
- def track_issue_comment_removed_action(author:)
+ def track_issue_comment_removed_action(author:, project:)
+ track_snowplow_action(ISSUE_COMMENT_REMOVED, author, project)
track_unique_action(ISSUE_COMMENT_REMOVED, author)
end
- def track_issue_cloned_action(author:)
+ def track_issue_cloned_action(author:, project:)
+ track_snowplow_action(ISSUE_CLONED, author, project)
track_unique_action(ISSUE_CLONED, author)
end
private
- def track_unique_action(action, author)
- return unless author
-
- Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id)
- end
-
def track_snowplow_action(action, author, project)
- return unless Feature.enabled?(:route_hll_to_snowplow_phase2, project&.namespace)
+ return unless Feature.enabled?(:route_hll_to_snowplow_phase2, project.namespace)
return unless author
Gitlab::Tracking.event(
ISSUE_CATEGORY,
- action.to_s,
+ ISSUE_ACTION,
+ label: ISSUE_LABEL,
+ property: action,
project: project,
- namespace: project&.namespace,
+ namespace: project.namespace,
user: author
)
end
+
+ def track_unique_action(action, author)
+ return unless author
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(action, values: author.id)
+ end
end
end
end
diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
index 3b883e505f8..a8f1bab1f20 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -147,6 +147,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_fortify_fod_sast
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_sast_iac_latest
category: ci_templates
redis_slot: ci_templates
@@ -639,6 +643,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_security_fortify_fod_sast
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_security_sast_iac_latest
category: ci_templates
redis_slot: ci_templates
diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
index 267b7fe673d..c21b99ba834 100644
--- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml
@@ -299,3 +299,154 @@
redis_slot: code_review
category: code_review
aggregation: weekly
+# MR Widget Extensions
+## Test Summary
+- name: i_code_review_merge_request_widget_test_summary_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_test_summary_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_test_summary_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_test_summary_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_test_summary_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_test_summary_expand_failed
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+## Accessibility
+- name: i_code_review_merge_request_widget_accessibility_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_accessibility_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_accessibility_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_accessibility_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_accessibility_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_accessibility_expand_failed
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+## Code Quality
+- name: i_code_review_merge_request_widget_code_quality_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_code_quality_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_code_quality_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_code_quality_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_code_quality_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_code_quality_expand_failed
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+## Terraform
+- name: i_code_review_merge_request_widget_terraform_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_terraform_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_terraform_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_terraform_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_terraform_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_terraform_expand_failed
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+## Metrics
+- name: i_code_review_merge_request_widget_metrics_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_metrics_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_metrics_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_metrics_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_metrics_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_metrics_expand_failed
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+## Status Checks
+- name: i_code_review_merge_request_widget_status_checks_view
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_status_checks_full_report_clicked
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_status_checks_expand
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_status_checks_expand_success
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_status_checks_expand_warning
+ redis_slot: code_review
+ category: code_review
+ aggregation: weekly
+- name: i_code_review_merge_request_widget_status_checks_expand_failed
+ redis_slot: code_review
+ category: code_review
+ 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 88c9f44c165..6c4754ae19f 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -1,25 +1,5 @@
---
# Compliance category
-- name: g_compliance_dashboard
- redis_slot: compliance
- category: compliance
- aggregation: weekly
-- name: g_compliance_audit_events
- category: compliance
- redis_slot: compliance
- aggregation: weekly
-- name: i_compliance_audit_events
- category: compliance
- redis_slot: compliance
- aggregation: weekly
-- name: i_compliance_credential_inventory
- category: compliance
- redis_slot: compliance
- aggregation: weekly
-- name: a_compliance_audit_events_api
- category: compliance
- redis_slot: compliance
- aggregation: weekly
- name: g_edit_by_web_ide
category: ide_edit
redis_slot: edit
@@ -44,14 +24,6 @@
category: search
redis_slot: search
aggregation: weekly
-- name: i_search_advanced
- category: search
- redis_slot: search
- aggregation: weekly
-- name: i_search_paid
- category: search
- redis_slot: search
- aggregation: weekly
- name: wiki_action
category: source_code
aggregation: daily
@@ -142,6 +114,19 @@
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
diff --git a/lib/gitlab/usage_data_counters/known_events/kubernetes_agent.yml b/lib/gitlab/usage_data_counters/known_events/kubernetes_agent.yml
new file mode 100644
index 00000000000..e1de74a3d07
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/known_events/kubernetes_agent.yml
@@ -0,0 +1,5 @@
+- name: agent_users_using_ci_tunnel
+ category: kubernetes_agent
+ redis_slot: agent
+ aggregation: weekly
+ feature_flag: track_agent_users_using_ci_tunnel
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 0c9c6026c46..6cd7836ea94 100644
--- a/lib/gitlab/usage_data_counters/known_events/work_items.yml
+++ b/lib/gitlab/usage_data_counters/known_events/work_items.yml
@@ -9,3 +9,8 @@
redis_slot: users
aggregation: weekly
feature_flag: track_work_items_activity
+- name: users_updating_work_item_dates
+ category: work_items
+ redis_slot: users
+ aggregation: weekly
+ feature_flag: track_work_items_activity
diff --git a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb
new file mode 100644
index 00000000000..dafc36ab7ce
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ class MergeRequestWidgetExtensionCounter < BaseCounter
+ KNOWN_EVENTS = %w[view full_report_clicked expand expand_success expand_warning expand_failed].freeze
+ PREFIX = 'i_code_review_merge_request_widget'
+ WIDGETS = %w[accessibility code_quality status_checks terraform test_summary metrics].freeze
+
+ class << self
+ private
+
+ def known_events
+ self::WIDGETS.product(self::KNOWN_EVENTS).map { |name_parts| name_parts.join('_count_') }
+ end
+ end
+ end
+ end
+end
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 51bca8b51fe..99b4c082310 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
@@ -5,6 +5,7 @@ module Gitlab
module WorkItemActivityUniqueCounter
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'
class << self
def track_work_item_created_action(author:)
@@ -15,6 +16,10 @@ module Gitlab
track_unique_action(WORK_ITEM_TITLE_CHANGED, author)
end
+ def track_work_item_date_changed_action(author:)
+ track_unique_action(WORK_ITEM_DATE_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 fef5cd680cb..c2983779603 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -53,7 +53,7 @@ module Gitlab
end
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
- if block_given?
+ if block
{ alt_usage_data_block: "non-SQL usage data block" }
else
{ alt_usage_data_value: value }
@@ -61,7 +61,7 @@ module Gitlab
end
def redis_usage_data(counter = nil, &block)
- if block_given?
+ if block
{ redis_usage_data_block: "non-SQL usage data block" }
elsif counter.present?
{ redis_usage_data_counter: counter.to_s }
diff --git a/lib/gitlab/utils/batch_loader.rb b/lib/gitlab/utils/batch_loader.rb
new file mode 100644
index 00000000000..67ade0633e2
--- /dev/null
+++ b/lib/gitlab/utils/batch_loader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ module BatchLoader
+ # Clears batched items under the specified batch key
+ # https://github.com/exAspArk/batch-loader#batch-key
+ def self.clear_key(batch_key)
+ return if ::BatchLoader::Executor.current.nil?
+
+ items_to_clear = ::BatchLoader::Executor.current.items_by_block.select do |k, v|
+ # The Hash key here is [source_location, batch_key], so we just check k[1]
+ k[1] == batch_key
+ end
+
+ items_to_clear.each do |k, v|
+ ::BatchLoader::Executor.current.items_by_block.delete(k)
+ ::BatchLoader::Executor.current.loaded_values_by_block.delete(k)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/link_header_parser.rb b/lib/gitlab/utils/link_header_parser.rb
new file mode 100644
index 00000000000..d98c237baf3
--- /dev/null
+++ b/lib/gitlab/utils/link_header_parser.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ # Parses Link http headers (as defined in https://www.rfc-editor.org/rfc/rfc5988.txt)
+ #
+ # The URI-references with their relation type are extracted and returned as a hash
+ # Example:
+ #
+ # header = '<http://test.org/TheBook/chapter2>; rel="previous", <http://test.org/TheBook/chapter4>; rel="next"'
+ #
+ # Gitlab::Utils::LinkHeaderParser.new(header).parse
+ # {
+ # previous: {
+ # uri: #<URI::HTTP http://test.org/TheBook/chapter2>
+ # },
+ # next: {
+ # uri: #<URI::HTTP http://test.org/TheBook/chapter4>
+ # }
+ # }
+ class LinkHeaderParser
+ REL_PATTERN = %r{rel="(\w+)"}.freeze
+ # to avoid parse really long URIs we limit the amount of characters allowed
+ URI_PATTERN = %r{<(.{1,500})>}.freeze
+
+ def initialize(header)
+ @header = header
+ end
+
+ def parse
+ return {} if @header.blank?
+
+ links = @header.split(',')
+ result = {}
+ links.each do |link|
+ direction = link[REL_PATTERN, 1]&.to_sym
+ uri = link[URI_PATTERN, 1]
+
+ result[direction] = { uri: URI(uri) } if direction && uri
+ end
+
+ result
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index 3c954f817a7..50b8428113d 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -21,6 +21,20 @@ module Gitlab
# end
# end
#
+ # Or like:
+ #
+ # include Gitlab::Utils::StrongMemoize
+ #
+ # def trigger_from_token
+ # Ci::Trigger.find_by_token(params[:token].to_s)
+ # end
+ # strong_memoize_attr :trigger_from_token
+ #
+ # strong_memoize_attr :enabled?, :enabled
+ # def enabled?
+ # Feature.enabled?(:some_feature)
+ # end
+ #
def strong_memoize(name)
key = ivar(name)
@@ -40,6 +54,34 @@ module Gitlab
remove_instance_variable(key) if instance_variable_defined?(key)
end
+ module StrongMemoizeClassMethods
+ def strong_memoize_attr(method_name, member_name = nil)
+ member_name ||= method_name
+
+ if method_defined?(method_name) || private_method_defined?(method_name)
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :do_strong_memoize, self, method_name, member_name)
+ else
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :queue_strong_memoize, self, method_name, member_name)
+ end
+ end
+
+ def method_added(method_name)
+ super
+
+ if member_name = StrongMemoize
+ .send(:strong_memoize_queue, self).delete(method_name) # rubocop:disable GitlabSecurity/PublicSend
+ StrongMemoize.send( # rubocop:disable GitlabSecurity/PublicSend
+ :do_strong_memoize, self, method_name, member_name)
+ end
+ end
+ end
+
+ def self.included(base)
+ base.singleton_class.prepend(StrongMemoizeClassMethods)
+ end
+
private
# Convert `"name"`/`:name` into `:@name`
@@ -54,6 +96,37 @@ module Gitlab
raise ArgumentError, "Invalid type of '#{name}'"
end
end
+
+ class <<self
+ private
+
+ def strong_memoize_queue(klass)
+ klass.instance_variable_get(:@strong_memoize_queue) || klass.instance_variable_set(:@strong_memoize_queue, {})
+ end
+
+ def queue_strong_memoize(klass, method_name, member_name)
+ strong_memoize_queue(klass)[method_name] = member_name
+ end
+
+ def do_strong_memoize(klass, method_name, member_name)
+ method = klass.instance_method(method_name)
+
+ # Methods defined within a class method are already public by default, so we don't need to
+ # explicitly make them public.
+ scope = %i[private protected].find do |scope|
+ klass.send("#{scope}_instance_methods") # rubocop:disable GitlabSecurity/PublicSend
+ .include? method_name
+ end
+
+ klass.define_method(method_name) do |*args, &block|
+ strong_memoize(member_name) do
+ method.bind_call(self, *args, &block)
+ end
+ end
+
+ klass.send(scope, method_name) if scope # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
end
end
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 4d1b234ae54..19bdeefed7e 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -196,7 +196,7 @@ module Gitlab
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
with_duration do
- if block_given?
+ if block
yield
else
value
@@ -209,7 +209,7 @@ module Gitlab
def redis_usage_data(counter = nil, &block)
with_duration do
- if block_given?
+ if block
redis_usage_counter(&block)
elsif counter.present?
redis_usage_data_totals(counter)
diff --git a/lib/gitlab/version_info.rb b/lib/gitlab/version_info.rb
index f967a12b959..61de003c28d 100644
--- a/lib/gitlab/version_info.rb
+++ b/lib/gitlab/version_info.rb
@@ -9,7 +9,7 @@ module Gitlab
VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/.freeze
def self.parse(str, parse_suffix: false)
- if str.is_a?(self.class)
+ if str.is_a?(self)
str
elsif str && m = str.match(VERSION_REGEX)
VersionInfo.new(m[1].to_i, m[2].to_i, m[3].to_i, parse_suffix ? m.post_match : nil)
@@ -62,6 +62,10 @@ module Gitlab
end
end
+ def to_json(*_args)
+ { major: @major, minor: @minor, patch: @patch }.to_json
+ end
+
def suffix
@suffix ||= @suffix_s.strip.gsub('-', '.pre.').scan(/\d+|[a-z]+/i).map do |s|
/^\d+$/ =~ s ? s.to_i : s
diff --git a/lib/gitlab/word_diff/segments/diff_hunk.rb b/lib/gitlab/word_diff/segments/diff_hunk.rb
index 88b6817676f..13f71f2bc04 100644
--- a/lib/gitlab/word_diff/segments/diff_hunk.rb
+++ b/lib/gitlab/word_diff/segments/diff_hunk.rb
@@ -16,11 +16,15 @@ module Gitlab
end
def pos_old
- line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
+ line.match(/\-[0-9]*/)[0].to_i.abs
+ rescue StandardError
+ 0
end
def pos_new
- line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
+ line.match(/\+[0-9]*/)[0].to_i.abs
+ rescue StandardError
+ 0
end
def first_line?
diff --git a/lib/gitlab/zentao/client.rb b/lib/gitlab/zentao/client.rb
index 4da4631eecf..0c2b3049670 100644
--- a/lib/gitlab/zentao/client.rb
+++ b/lib/gitlab/zentao/client.rb
@@ -15,7 +15,11 @@ module Gitlab
end
def ping
- response = fetch_product(zentao_product_xid) rescue {}
+ response = begin
+ fetch_product(zentao_product_xid)
+ rescue StandardError
+ {}
+ end
active = response['deleted'] == '0'
if active
{ success: true }
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index c46ca2783bf..39cf994ca3f 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -101,7 +101,7 @@ module GoogleApi
result.append(project)
end
- result
+ result.sort_by(&:project_id)
end
def create_service_account(gcp_project_id, display_name, description)
@@ -148,16 +148,36 @@ module GoogleApi
enable_service(gcp_project_id, 'cloudbuild.googleapis.com')
end
+ def enable_cloud_sql_admin(gcp_project_id)
+ enable_service(gcp_project_id, 'sqladmin.googleapis.com')
+ end
+
+ def enable_compute(gcp_project_id)
+ enable_service(gcp_project_id, 'compute.googleapis.com')
+ end
+
+ def enable_service_networking(gcp_project_id)
+ enable_service(gcp_project_id, 'servicenetworking.googleapis.com')
+ end
+
def revoke_authorizations
uri = URI(REVOKE_URL)
Gitlab::HTTP.post(uri, body: { 'token' => access_token })
end
+ def list_cloudsql_databases(gcp_project_id, instance_name)
+ sql_admin_service.list_databases(gcp_project_id, instance_name, options: user_agent_header)
+ end
+
def create_cloudsql_database(gcp_project_id, instance_name, database_name)
database = Google::Apis::SqladminV1beta4::Database.new(name: database_name)
sql_admin_service.insert_database(gcp_project_id, instance_name, database)
end
+ def list_cloudsql_users(gcp_project_id, instance_name)
+ sql_admin_service.list_users(gcp_project_id, instance_name, options: user_agent_header)
+ end
+
def create_cloudsql_user(gcp_project_id, instance_name, username, password)
user = Google::Apis::SqladminV1beta4::User.new
user.name = username
@@ -169,6 +189,18 @@ module GoogleApi
sql_admin_service.get_instance(gcp_project_id, instance_name)
end
+ def create_cloudsql_instance(gcp_project_id, instance_name, root_password, database_version, region, tier)
+ database_instance = Google::Apis::SqladminV1beta4::DatabaseInstance.new(
+ name: instance_name,
+ root_password: root_password,
+ database_version: database_version,
+ region: region,
+ settings: Google::Apis::SqladminV1beta4::Settings.new(tier: tier)
+ )
+
+ sql_admin_service.insert_instance(gcp_project_id, database_instance)
+ end
+
private
def enable_service(gcp_project_id, service_name)
diff --git a/lib/kramdown/converter/commonmark.rb b/lib/kramdown/converter/commonmark.rb
index 4abb34cc008..33ec9dd1fbc 100644
--- a/lib/kramdown/converter/commonmark.rb
+++ b/lib/kramdown/converter/commonmark.rb
@@ -34,7 +34,7 @@ module Kramdown
def convert_codeblock(el, _opts)
# Although tildes are supported in CommonMark, backticks are more common
"```#{el.options[:lang]}\n" +
- el.value.split(/\n/).map {|l| l.empty? ? "" : "#{l}" }.join("\n") +
+ el.value.split(/\n/).map { |l| l.empty? ? "" : "#{l}" }.join("\n") +
"\n```\n\n"
end
@@ -43,7 +43,7 @@ module Kramdown
if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent]
if el.children.size == 1 && @stack.last.children.last == el &&
- (@stack.last.children.any? {|c| c.children.first.type != :p } || @stack.last.children.size == 1)
+ (@stack.last.children.any? { |c| c.children.first.type != :p } || @stack.last.children.size == 1)
# replace the end of block character
res.sub!(/\^\n\z/m, "#{END_OF_BLOCK}\n")
end
@@ -82,7 +82,7 @@ module Kramdown
def convert_tr(el, opts)
return super unless @options[:html_tables]
- "<tr>\n#{el.children.map {|c| convert(c, opts) }.join}</tr>\n"
+ "<tr>\n#{el.children.map { |c| convert(c, opts) }.join}</tr>\n"
end
def convert_td(el, opts)
diff --git a/lib/release_highlights/validator/entry.rb b/lib/release_highlights/validator/entry.rb
index dff55eead2f..2b4889e0131 100644
--- a/lib/release_highlights/validator/entry.rb
+++ b/lib/release_highlights/validator/entry.rb
@@ -5,16 +5,16 @@ module ReleaseHighlights
include ActiveModel::Validations
include ActiveModel::Validations::Callbacks
- PACKAGES = %w(Free Premium Ultimate).freeze
+ AVAILABLE_IN = %w(Free Premium Ultimate).freeze
attr_reader :entry
- validates :title, :body, :stage, presence: true
+ validates :name, :description, :stage, presence: true
validates :'self-managed', :'gitlab-com', inclusion: { in: [true, false], message: "must be a boolean" }
- validates :url, :image_url, public_url: { dns_rebind_protection: true }
+ validates :documentation_link, :image_url, public_url: { dns_rebind_protection: true }
validates :release, numericality: true
validate :validate_published_at
- validate :validate_packages
+ validate :validate_available_in
after_validation :add_line_numbers_to_errors!
@@ -30,11 +30,11 @@ module ReleaseHighlights
errors.add(:published_at, 'must be valid Date')
end
- def validate_packages
- packages = value_for('packages')
+ def validate_available_in
+ available_in = value_for('available_in')
- if !packages.is_a?(Array) || packages.empty? || packages.any? { |p| PACKAGES.exclude?(p) }
- errors.add(:packages, "must be one of #{PACKAGES}")
+ if !available_in.is_a?(Array) || available_in.empty? || available_in.any? { |p| AVAILABLE_IN.exclude?(p) }
+ errors.add(:available_in, "must be one of #{AVAILABLE_IN}")
end
end
@@ -71,7 +71,7 @@ module ReleaseHighlights
end
def find_node(key)
- entry.children.find {|node| node.try(:value) == key.to_s }
+ entry.children.find { |node| node.try(:value) == key.to_s }
end
end
end
diff --git a/lib/security/ci_configuration/sast_build_action.rb b/lib/security/ci_configuration/sast_build_action.rb
index 73298bcd070..448d4fbeacb 100644
--- a/lib/security/ci_configuration/sast_build_action.rb
+++ b/lib/security/ci_configuration/sast_build_action.rb
@@ -33,8 +33,8 @@ module Security
analyzer_variables = analyzer_variables_for(config, key)
analyzer_variables['SAST_EXCLUDED_ANALYZERS'] = if key == :value
config[:analyzers]
- &.reject {|a| a[:enabled] }
- &.collect {|a| a[:name] }
+ &.reject { |a| a[:enabled] }
+ &.collect { |a| a[:name] }
&.sort
&.join(', ')
else
@@ -46,9 +46,9 @@ module Security
def analyzer_variables_for(config, key)
config[:analyzers]
- &.select {|a| a[:enabled] && a[:variables] }
- &.flat_map {|a| a[:variables] }
- &.collect {|v| [v[:field], v[key]] }.to_h
+ &.select { |a| a[:enabled] && a[:variables] }
+ &.flat_map { |a| a[:variables] }
+ &.collect { |v| [v[:field], v[key]] }.to_h
end
def update_existing_content!
diff --git a/lib/security/report_schema_version_matcher.rb b/lib/security/report_schema_version_matcher.rb
new file mode 100644
index 00000000000..d8eb5b8f490
--- /dev/null
+++ b/lib/security/report_schema_version_matcher.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+module Security
+ class ReportSchemaVersionMatcher
+ def initialize(report_declared_version:, supported_versions:)
+ @report_version = Gem::Version.new(report_declared_version)
+ @supported_versions = supported_versions.sort.map { |version| Gem::Version.new(version) }
+ end
+
+ attr_reader :report_version, :supported_versions
+
+ def call
+ find_matching_versions
+ end
+
+ private
+
+ def find_matching_versions
+ dependency = Gem::Dependency.new('', approximate_version)
+ matches = supported_versions.map do |supported_version|
+ exact_version = ['', supported_version.to_s]
+ [supported_version.to_s, dependency.match?(*exact_version)]
+ end
+ matches.to_h.select { |_, matches_dependency| matches_dependency == true }.keys.max
+ end
+
+ def approximate_version
+ "~> #{generate_patch_version}"
+ end
+
+ def generate_patch_version
+ # We can't use #approximate_recommendation here because
+ # for "14.0.32" it would yield "~> 14.0" and according to
+ # https://www.rubydoc.info/github/rubygems/rubygems/Gem/Version#label-Preventing+Version+Catastrophe-3A
+ # "~> 3.0" covers [3.0...4.0)
+ # and version 14.1.0 would fall within that range
+ #
+ # Instead we replace the patch number with 0 and get "~> 14.0.0"
+ # Which will work as we want it to
+ (report_version.segments[0...2] << 0).join('.')
+ end
+ end
+end
diff --git a/lib/tasks/contracts/merge_requests.rake b/lib/tasks/contracts/merge_requests.rake
index 05ed9c30495..2ee7ec07a96 100644
--- a/lib/tasks/contracts/merge_requests.rake
+++ b/lib/tasks/contracts/merge_requests.rake
@@ -4,38 +4,36 @@ return if Rails.env.production?
require 'pact/tasks/verification_task'
-contracts = File.expand_path('../../../spec/contracts', __dir__)
-provider = File.expand_path('provider', contracts)
+contracts = File.expand_path('../../../spec/contracts/contracts/project/merge_request', __dir__)
+provider = File.expand_path('../../../spec/contracts/provider', __dir__)
-# rubocop:disable Rails/RakeEnvironment
namespace :contracts do
namespace :merge_requests do
Pact::VerificationTask.new(:diffs_batch) do |pact|
pact.uri(
- "#{contracts}/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_batch_endpoint.json",
- pact_helper: "#{provider}/pact_helpers/project/merge_request/diffs_batch_helper.rb"
+ "#{contracts}/show/mergerequest#show-merge_request_diffs_batch_endpoint.json",
+ pact_helper: "#{provider}/pact_helpers/project/merge_request/show/diffs_batch_helper.rb"
)
end
Pact::VerificationTask.new(:diffs_metadata) do |pact|
pact.uri(
- "#{contracts}/contracts/project/merge_request/show/" \
- "mergerequest#show-merge_request_diffs_metadata_endpoint.json",
- pact_helper: "#{provider}/pact_helpers/project/merge_request/diffs_metadata_helper.rb"
+ "#{contracts}/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json",
+ pact_helper: "#{provider}/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb"
)
end
Pact::VerificationTask.new(:discussions) do |pact|
pact.uri(
- "#{contracts}/contracts/project/merge_request/show/mergerequest#show-merge_request_discussions_endpoint.json",
- pact_helper: "#{provider}/pact_helpers/project/merge_request/discussions_helper.rb"
+ "#{contracts}/show/mergerequest#show-merge_request_discussions_endpoint.json",
+ pact_helper: "#{provider}/pact_helpers/project/merge_request/show/discussions_helper.rb"
)
end
desc 'Run all merge request contract tests'
- task 'test:merge_requests', :contract_mr do |_t, arg|
+ task 'test:merge_requests', :contract_merge_requests do |_t, arg|
errors = %w[diffs_batch diffs_metadata discussions].each_with_object([]) do |task, err|
- Rake::Task["contracts:mr:pact:verify:#{task}"].execute
+ Rake::Task["contracts:merge_requests:pact:verify:#{task}"].execute
rescue StandardError, SystemExit
err << "contracts:merge_requests:pact:verify:#{task}"
end
@@ -44,4 +42,3 @@ namespace :contracts do
end
end
end
-# rubocop:enable Rails/RakeEnvironment
diff --git a/lib/tasks/contracts/pipeline_schedules.rake b/lib/tasks/contracts/pipeline_schedules.rake
new file mode 100644
index 00000000000..75080d41ebe
--- /dev/null
+++ b/lib/tasks/contracts/pipeline_schedules.rake
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+return if Rails.env.production?
+
+require 'pact/tasks/verification_task'
+
+contracts = File.expand_path('../../../spec/contracts/contracts/project/pipeline_schedule', __dir__)
+provider = File.expand_path('../../../spec/contracts/provider', __dir__)
+
+namespace :contracts do
+ namespace :pipeline_schedules do
+ Pact::VerificationTask.new(:update_pipeline_schedule) do |pact|
+ pact.uri(
+ "#{contracts}/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb"
+ )
+ end
+
+ desc 'Run all pipeline schedule contract tests'
+ task 'test:pipeline_schedules', :contract_pipeline_schedules do |_t, arg|
+ errors = %w[
+ update_pipeline_schedule
+ ].each_with_object([]) do |task, err|
+ Rake::Task["contracts:pipeline_schedules:pact:verify:#{task}"].execute
+ rescue StandardError, SystemExit
+ err << "contracts:pipeline_schedule:pact:verify:#{task}"
+ end
+
+ raise StandardError, "Errors in tasks #{errors.join(', ')}" unless errors.empty?
+ end
+ end
+end
diff --git a/lib/tasks/contracts/pipelines.rake b/lib/tasks/contracts/pipelines.rake
index c018645722e..3163791460f 100644
--- a/lib/tasks/contracts/pipelines.rake
+++ b/lib/tasks/contracts/pipelines.rake
@@ -4,29 +4,47 @@ return if Rails.env.production?
require 'pact/tasks/verification_task'
-contracts = File.expand_path('../../../spec/contracts', __dir__)
-provider = File.expand_path('provider', contracts)
+contracts = File.expand_path('../../../spec/contracts/contracts/project/pipeline', __dir__)
+provider = File.expand_path('../../../spec/contracts/provider', __dir__)
-# rubocop:disable Rails/RakeEnvironment
namespace :contracts do
namespace :pipelines do
+ Pact::VerificationTask.new(:create_a_new_pipeline) do |pact|
+ pact.uri(
+ "#{contracts}/new/pipelines#new-post_create_a_new_pipeline.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb"
+ )
+ end
+
Pact::VerificationTask.new(:get_list_project_pipelines) do |pact|
pact.uri(
- "#{contracts}/contracts/project/pipeline/index/pipelines#index-get_list_project_pipelines.json",
- pact_helper: "#{provider}/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb"
+ "#{contracts}/index/pipelines#index-get_list_project_pipelines.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb"
)
end
Pact::VerificationTask.new(:get_pipeline_header_data) do |pact|
pact.uri(
- "#{contracts}/contracts/project/pipeline/show/pipelines#show-get_pipeline_header_data.json",
- pact_helper: "#{provider}/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb"
+ "#{contracts}/show/pipelines#show-get_pipeline_header_data.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb"
+ )
+ end
+
+ Pact::VerificationTask.new(:delete_pipeline) do |pact|
+ pact.uri(
+ "#{contracts}/show/pipelines#show-delete_pipeline.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb"
)
end
desc 'Run all pipeline contract tests'
- task 'test:pipelines', :contract_mr do |_t, arg|
- errors = %w[get_list_project_pipelines get_pipeline_header_data].each_with_object([]) do |task, err|
+ task 'test:pipelines', :contract_pipelines do |_t, arg|
+ errors = %w[
+ create_a_new_pipeline
+ get_list_project_pipelines
+ get_pipeline_header_data
+ delete_pipeline
+ ].each_with_object([]) do |task, err|
Rake::Task["contracts:pipelines:pact:verify:#{task}"].execute
rescue StandardError, SystemExit
err << "contracts:pipelines:pact:verify:#{task}"
@@ -36,4 +54,3 @@ namespace :contracts do
end
end
end
-# rubocop:enable Rails/RakeEnvironment
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index 48bf49ff284..129f4c0ff0e 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -27,6 +27,21 @@ namespace :dev do
Rails.application.eager_load!
end
+ desc "GitLab | Dev | Load specific fixture"
+ task 'fixtures:load', [:fixture_name] => :environment do |_, args|
+ fixture_name = args.fixture_name
+
+ if fixture_name.nil?
+ puts "No fixture name was provided"
+ next
+ end
+
+ ENV['FIXTURE_PATH'] = 'db/fixtures/development/'
+ ENV['FILTER'] = args.fixture_name
+
+ Rake::Task['db:seed_fu'].invoke
+ end
+
# If there are any clients connected to the DB, PostgreSQL won't let
# you drop the database. It's possible that Sidekiq, Puma, or
# some other client will be hanging onto a connection, preventing
diff --git a/lib/tasks/gems.rake b/lib/tasks/gems.rake
index c6be6d9eead..fc70048ea6d 100644
--- a/lib/tasks/gems.rake
+++ b/lib/tasks/gems.rake
@@ -4,7 +4,6 @@ namespace :gems do
# :nocov:
namespace :error_tracking_open_api do
desc 'Generate OpenAPI client for Error Tracking'
- # rubocop:disable Rails/RakeEnvironment
task :generate do |task|
# Configuration
api_url = 'https://gitlab.com/gitlab-org/opstrace/opstrace/-/raw/main/go/pkg/errortracking/swagger.yaml'
@@ -28,7 +27,6 @@ namespace :gems do
post_process(gem_dir: gem_dir, gem_name: gem_name, task: task)
end
- # rubocop:enable Rails/RakeEnvironment
def root_directory
File.expand_path('../../vendor/gems', __dir__)
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 78cb7d72d4f..ff43a36d930 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -32,11 +32,13 @@ namespace :gitlab do
namespace :db do
task create: :gitlab_environment do
- Backup::Manager.new(progress).run_create_task('db')
+ Backup::Manager.new(progress).run_create_task('main_db')
+ Backup::Manager.new(progress).run_create_task('ci_db')
end
task restore: :gitlab_environment do
- Backup::Manager.new(progress).run_restore_task('db')
+ Backup::Manager.new(progress).run_restore_task('main_db')
+ Backup::Manager.new(progress).run_restore_task('ci_db')
end
end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 5ed54bb6921..30e0e3e72ff 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -294,7 +294,7 @@ namespace :gitlab do
# gc = Gitlab::CurrentSettings.current_application_settings
seed_projects = [Gitlab::CurrentSettings.current_application_settings.self_monitoring_project]
- if (Project.count - seed_projects.count {|x| !x.nil? }).eql?(0)
+ if (Project.count - seed_projects.count { |x| !x.nil? }).eql?(0)
puts "No user created projects. Database not active"
exit 1
end
diff --git a/lib/tasks/gitlab/db/lock_writes.rake b/lib/tasks/gitlab/db/lock_writes.rake
index 3a083036781..eb6d257cac5 100644
--- a/lib/tasks/gitlab/db/lock_writes.rake
+++ b/lib/tasks/gitlab/db/lock_writes.rake
@@ -2,22 +2,25 @@
namespace :gitlab do
namespace :db do
- TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write'
-
desc "GitLab | DB | Install prevent write triggers on all databases"
task lock_writes: [:environment, 'gitlab:db:validate_config'] do
- Gitlab::Database::EachDatabase.each_database_connection do |connection, database_name|
- create_write_trigger_function(connection)
-
+ Gitlab::Database::EachDatabase.each_database_connection(include_shared: false) do |connection, database_name|
schemas_for_connection = Gitlab::Database.gitlab_schemas_for_connection(connection)
Gitlab::Database::GitlabSchema.tables_to_schema.each do |table_name, schema_name|
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/366834
next if schema_name == :gitlab_geo
+ lock_writes_manager = Gitlab::Database::LockWritesManager.new(
+ table_name: table_name,
+ connection: connection,
+ database_name: database_name,
+ logger: Logger.new($stdout)
+ )
+
if schemas_for_connection.include?(schema_name.to_sym)
- drop_write_trigger(database_name, connection, table_name)
+ lock_writes_manager.unlock_writes
else
- create_write_trigger(database_name, connection, table_name)
+ lock_writes_manager.lock_writes
end
end
end
@@ -30,96 +33,16 @@ namespace :gitlab do
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/366834
next if schema_name == :gitlab_geo
- drop_write_trigger(database_name, connection, table_name)
- end
- drop_write_trigger_function(connection)
- end
- end
-
- def create_write_trigger_function(connection)
- sql = <<-SQL
- CREATE OR REPLACE FUNCTION #{TRIGGER_FUNCTION_NAME}()
- RETURNS TRIGGER AS
- $$
- BEGIN
- RAISE EXCEPTION 'Table: "%" is write protected within this Gitlab database.', TG_TABLE_NAME
- USING ERRCODE = 'modifying_sql_data_not_permitted',
- HINT = 'Make sure you are using the right database connection';
- END
- $$ LANGUAGE PLPGSQL
- SQL
-
- connection.execute(sql)
- end
-
- def drop_write_trigger_function(connection)
- sql = <<-SQL
- DROP FUNCTION IF EXISTS #{TRIGGER_FUNCTION_NAME}()
- SQL
-
- connection.execute(sql)
- end
-
- def create_write_trigger(database_name, connection, table_name)
- puts "#{database_name}: '#{table_name}'... Lock Writes".color(:yellow)
- sql = <<-SQL
- DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name};
- CREATE TRIGGER #{write_trigger_name(table_name)}
- BEFORE INSERT OR UPDATE OR DELETE OR TRUNCATE
- ON #{table_name}
- FOR EACH STATEMENT EXECUTE FUNCTION #{TRIGGER_FUNCTION_NAME}();
- SQL
-
- with_retries(connection) do
- connection.execute(sql)
- end
- end
-
- def drop_write_trigger(database_name, connection, table_name)
- puts "#{database_name}: '#{table_name}'... Allow Writes".color(:green)
- sql = <<-SQL
- DROP TRIGGER IF EXISTS #{write_trigger_name(table_name)} ON #{table_name}
- SQL
-
- with_retries(connection) do
- connection.execute(sql)
- end
- end
+ lock_writes_manager = Gitlab::Database::LockWritesManager.new(
+ table_name: table_name,
+ connection: connection,
+ database_name: database_name,
+ logger: Logger.new($stdout)
+ )
- def with_retries(connection, &block)
- with_statement_timeout_retries do
- with_lock_retries(connection) do
- yield
+ lock_writes_manager.unlock_writes
end
end
end
-
- def with_statement_timeout_retries(times = 5)
- current_iteration = 1
- begin
- yield
- rescue ActiveRecord::QueryCanceled => err
- puts "Retrying after #{err.message}"
-
- if current_iteration <= times
- current_iteration += 1
- retry
- else
- raise err
- end
- end
- end
-
- def with_lock_retries(connection, &block)
- Gitlab::Database::WithLockRetries.new(
- klass: "gitlab:db:lock_writes",
- logger: Gitlab::AppLogger,
- connection: connection
- ).run(&block)
- end
-
- def write_trigger_name(table_name)
- "gitlab_schema_write_trigger_for_#{table_name}"
- end
end
end
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index 18c68615637..960d0e51a47 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -34,7 +34,7 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
env["BUNDLE_DEPLOYMENT"] = 'false'
end
- output, status = Gitlab::Popen.popen([make_cmd, 'all', 'git'], nil, env)
+ output, status = Gitlab::Popen.popen([make_cmd, 'clean-build', 'all', 'git'], nil, env)
raise "Gitaly failed to compile: #{output}" unless status&.zero?
end
end
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index 6f42bf8c946..161c7dd38ac 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -19,7 +19,7 @@ namespace :gitlab do
# check for system defined proxies
if Gitlab.ee?
- proxies = Gitlab::Proxy.detect_proxy.map {|k, v| "#{k}: #{v}"}.join("\n\t\t")
+ proxies = Gitlab::Proxy.detect_proxy.map { |k, v| "#{k}: #{v}" }.join("\n\t\t")
end
# check Go version
diff --git a/lib/tasks/gitlab/praefect.rake b/lib/tasks/gitlab/praefect.rake
index 28b70f8986e..6874a55e08a 100644
--- a/lib/tasks/gitlab/praefect.rake
+++ b/lib/tasks/gitlab/praefect.rake
@@ -3,7 +3,9 @@
namespace :gitlab do
namespace :praefect do
def int?(string)
- true if Integer(string) rescue false
+ true if Integer(string)
+ rescue StandardError
+ false
end
def print_checksums(header, row)
@@ -43,7 +45,7 @@ namespace :gitlab do
header.concat(sorted_replicas.map { |r| r.repository.storage_name })
row = [project.name] << replicas_resp.primary.checksum
- row.concat(sorted_replicas.map {|r| r.checksum})
+ row.concat(sorted_replicas.map { |r| r.checksum })
rescue StandardError
puts 'Something went wrong when getting replicas.'
next
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 8627a326247..cf9876366aa 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -27,7 +27,7 @@ namespace :gitlab do
}.stringify_keys
# Generate config.yml based on existing gitlab settings
- File.open("config.yml", "w+") {|f| f.puts config.to_yaml }
+ File.open("config.yml", "w+") { |f| f.puts config.to_yaml }
[
%w(bin/install) + repository_storage_paths_args,
diff --git a/lib/tasks/gitlab/tw/codeowners.rake b/lib/tasks/gitlab/tw/codeowners.rake
index 40d88ea8a5b..f6c518784a9 100644
--- a/lib/tasks/gitlab/tw/codeowners.rake
+++ b/lib/tasks/gitlab/tw/codeowners.rake
@@ -46,12 +46,12 @@ namespace :tw do
CodeOwnerRule.new('Fuzz Testing', '@rdickenson'),
CodeOwnerRule.new('Geo', '@axil'),
CodeOwnerRule.new('Gitaly', '@eread'),
- CodeOwnerRule.new('Global Search', '@sselhorn'),
+ CodeOwnerRule.new('Global Search', '@ashrafkhamis'),
CodeOwnerRule.new('Import', '@eread'),
CodeOwnerRule.new('Infrastructure', '@sselhorn'),
- CodeOwnerRule.new('Integrations', '@kpaizee'),
+ CodeOwnerRule.new('Integrations', '@ashrafkhamis'),
CodeOwnerRule.new('Knowledge', '@aqualls'),
- CodeOwnerRule.new('Memory', '@sselhorn'),
+ CodeOwnerRule.new('Application Performance', '@sselhorn'),
CodeOwnerRule.new('Monitor', '@msedlakjakubowski'),
CodeOwnerRule.new('Observability', 'msedlakjakubowski'),
CodeOwnerRule.new('Optimize', '@fneill'),
@@ -69,7 +69,7 @@ namespace :tw do
CodeOwnerRule.new('Release', '@rdickenson'),
CodeOwnerRule.new('Respond', '@msedlakjakubowski'),
CodeOwnerRule.new('Runner', '@sselhorn'),
- CodeOwnerRule.new('Sharding', '@sselhorn'),
+ CodeOwnerRule.new('Pods', '@sselhorn'),
CodeOwnerRule.new('Source Code', '@aqualls'),
CodeOwnerRule.new('Static Analysis', '@rdickenson'),
CodeOwnerRule.new('Style Guide', '@sselhorn'),
@@ -128,7 +128,7 @@ namespace :tw do
if errors.present?
puts "-----"
puts "ERRORS - the following files are missing the correct metadata:"
- errors.map { |file| puts file.gsub(Dir.pwd, ".")}
+ errors.map { |file| puts file.gsub(Dir.pwd, ".") }
end
end
end
diff --git a/lib/tasks/gitlab/web_hook.rake b/lib/tasks/gitlab/web_hook.rake
index fc17c7d0177..9aa0f07de5f 100644
--- a/lib/tasks/gitlab/web_hook.rake
+++ b/lib/tasks/gitlab/web_hook.rake
@@ -22,11 +22,13 @@ namespace :gitlab do
end
end
- desc "GitLab | Webhook | Remove a webhook from the projects"
- task rm: :environment do
+ desc "GitLab | Webhook | Remove a webhook from a namespace"
+ task rm: :environment do |task|
web_hook_url = ENV['URL']
namespace_path = ENV['NAMESPACE']
+ raise ArgumentError, 'URL is required' unless web_hook_url
+
web_hooks = find_web_hooks(namespace_path)
puts "Removing webhooks with the url '#{web_hook_url}' ... "
@@ -36,11 +38,12 @@ namespace :gitlab do
# we could consider storing a hash of the URL alongside the encrypted
# value to speed up searches
count = 0
+ service = WebHooks::AdminDestroyService.new(rake_task: task)
+
web_hooks.find_each do |hook|
next unless hook.url == web_hook_url
- user = hook.parent.owners.first
- result = WebHooks::DestroyService.new(user).execute(hook)
+ result = service.execute(hook)
raise "Unable to destroy Web hook" unless result[:status] == :success
diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake
index 28c370e5ca6..e993035aa65 100644
--- a/lib/tasks/rubocop.rake
+++ b/lib/tasks/rubocop.rake
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-# rubocop:disable Rails/RakeEnvironment
unless Rails.env.production?
require 'rubocop/rake_task'
@@ -63,5 +62,3 @@ unless Rails.env.production?
end
end
end
-
-# rubocop:enable Rails/RakeEnvironment
diff --git a/lib/unnested_in_filters/rewriter.rb b/lib/unnested_in_filters/rewriter.rb
index cba002a5632..bf7be177a0d 100644
--- a/lib/unnested_in_filters/rewriter.rb
+++ b/lib/unnested_in_filters/rewriter.rb
@@ -25,7 +25,7 @@ module UnnestedInFilters
attr_reader :model, :attribute, :values
delegate :connection, :columns, :attribute_types, to: :model, private: true
- delegate :quote, :quote_table_name, :quote_column_name, to: :connection
+ delegate :quote, :quote_table_name, :quote_column_name, :visitor, to: :connection
def table_name
quote_table_name(attribute.pluralize)
@@ -36,8 +36,17 @@ module UnnestedInFilters
end
def serialized_values
- array_type.serialize(values)
- .then { |array| quote(array) }
+ values.is_a?(Arel::Nodes::SelectStatement) ? "ARRAY(#{serialized_arel_value})" : serialized_array_values
+ end
+
+ def serialized_arel_value
+ visitor.compile(values, unprepared_statement_collector)
+ end
+
+ def serialized_array_values
+ values.map(&:value)
+ .then { array_type.serialize(_1) }
+ .then { |array| quote(array) }
end
def array_type
@@ -51,6 +60,13 @@ module UnnestedInFilters
def column
columns.find { _1.name == attribute }
end
+
+ def unprepared_statement_collector
+ Arel::Collectors::SubstituteBinds.new(
+ connection,
+ Arel::Collectors::SQLString.new
+ )
+ end
end
def initialize(relation)
@@ -125,7 +141,7 @@ module UnnestedInFilters
attr_reader :relation
- delegate :model, :order_values, :limit_value, :where_values_hash, to: :relation, private: true
+ delegate :model, :order_values, :limit_value, :where_values_hash, :where_clause, to: :relation, private: true
def log_rewrite
::Gitlab::AppLogger.info(message: 'Query is being rewritten by `UnnestedInFilters`', model: model.name)
@@ -150,7 +166,28 @@ module UnnestedInFilters
end
def in_filters
- @in_filters ||= where_values_hash.select { _2.is_a?(Array) }
+ @in_filters ||= arel_in_nodes.each_with_object({}) { |node, memo| memo[node.left.name] = node.right }
+ end
+
+ def arel_in_nodes
+ where_clause_arel_nodes.select(&method(:in_predicate?))
+ end
+
+ # `ActiveRecord::WhereClause#ast` is returning a single node when there is only one
+ # predicate but returning an `Arel::Nodes::And` node if there are more than one predicates.
+ # This is why we are checking the returned object responds to `children` or not.
+ def where_clause_arel_nodes
+ return [where_clause_ast] unless where_clause_ast.respond_to?(:children)
+
+ where_clause_ast.children
+ end
+
+ def where_clause_ast
+ @where_clause_ast ||= where_clause.ast
+ end
+
+ def in_predicate?(arel_node)
+ arel_node.is_a?(Arel::Nodes::HomogeneousIn) || arel_node.is_a?(Arel::Nodes::In)
end
def has_index_coverage?
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index c4e606170ca..f1cb18db5ab 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-07-14 17:11\n"
+"PO-Revision-Date: 2022-08-12 18:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,15 +763,15 @@ 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 "%{label_for_message} አáˆá‰°áŒˆáŠ˜áˆ"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 037bf20daa7..480680d3f12 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -760,6 +760,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -820,8 +823,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -1027,6 +1030,9 @@ 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 ""
@@ -1078,6 +1084,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -1090,13 +1099,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1216,6 +1225,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1306,6 +1327,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1348,9 +1387,6 @@ msgstr[5] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1999,15 +2035,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -2035,9 +2065,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2614,6 +2641,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2653,9 +2683,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2683,9 +2710,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2731,6 +2755,9 @@ 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 ""
@@ -4255,6 +4282,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4546,9 +4576,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4594,6 +4621,9 @@ 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 ""
@@ -4681,9 +4711,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -5098,13 +5125,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -5131,6 +5170,18 @@ 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 ""
@@ -5296,28 +5347,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5335,6 +5389,9 @@ 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 ""
@@ -5362,9 +5419,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5710,9 +5764,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5758,7 +5809,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5776,12 +5827,6 @@ msgstr[5] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5842,6 +5887,12 @@ 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 ""
@@ -5860,6 +5911,9 @@ 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 ""
@@ -5875,18 +5929,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5899,6 +5968,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -6115,7 +6187,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6304,6 +6376,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6655,6 +6730,9 @@ 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 ""
@@ -6748,17 +6826,20 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
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 ""
@@ -6775,6 +6856,9 @@ 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 ""
@@ -6790,13 +6874,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -7141,9 +7222,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7756,9 +7879,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8455,9 +8575,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8884,6 +9001,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8902,6 +9022,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8959,12 +9085,18 @@ 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 ""
@@ -10807,9 +10939,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -11248,9 +11377,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11701,6 +11827,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -12091,6 +12220,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -12109,6 +12241,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -12124,6 +12259,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -12169,6 +12307,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -12205,9 +12346,21 @@ 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 ""
@@ -12907,6 +13060,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12931,6 +13087,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12988,6 +13150,15 @@ 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 ""
@@ -13012,9 +13183,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -13246,6 +13414,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13501,7 +13672,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14326,9 +14497,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14737,9 +14905,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -15061,9 +15226,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15562,6 +15724,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16549,22 +16714,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16582,6 +16744,9 @@ 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 ""
@@ -16627,9 +16792,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16876,6 +17038,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -17293,6 +17458,15 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Freeze end"
msgstr ""
@@ -17317,11 +17491,23 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17380,6 +17566,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17437,6 +17626,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17611,9 +17803,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17671,9 +17860,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17929,9 +18115,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -18115,6 +18298,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -18139,9 +18325,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -18235,6 +18418,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -18286,6 +18472,9 @@ 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 ""
@@ -18298,6 +18487,9 @@ 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 ""
@@ -18310,6 +18502,9 @@ 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 ""
@@ -18628,16 +18823,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18859,9 +19051,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -19015,7 +19204,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -19180,7 +19369,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -19228,6 +19417,9 @@ 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 ""
@@ -19240,15 +19432,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -19267,9 +19453,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -19294,15 +19477,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19420,6 +19597,9 @@ 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 ""
@@ -19438,6 +19618,9 @@ 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 ""
@@ -19483,6 +19666,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19561,6 +19747,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19579,7 +19774,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19699,12 +19894,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19933,6 +20122,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -20002,6 +20194,9 @@ 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 ""
@@ -20185,6 +20380,9 @@ 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 ""
@@ -20212,6 +20410,9 @@ 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 ""
@@ -20503,6 +20704,9 @@ msgstr[5] ""
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 ""
@@ -20548,9 +20752,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20608,9 +20809,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20653,9 +20851,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20665,18 +20860,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20695,9 +20884,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20866,9 +21052,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20941,9 +21124,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -21016,12 +21196,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -21037,9 +21211,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -22066,7 +22237,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -22147,7 +22318,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -22162,9 +22333,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22570,6 +22738,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22585,12 +22756,36 @@ 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 ""
@@ -22612,6 +22807,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22642,10 +22840,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22654,6 +22852,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22681,9 +22882,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22711,13 +22909,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -23203,6 +23401,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -23326,7 +23527,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23602,15 +23803,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23893,19 +24088,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -24190,7 +24385,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -24202,6 +24400,48 @@ 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 ""
@@ -24529,9 +24769,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24793,7 +25030,7 @@ 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_whitelist}."
+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"
@@ -26203,12 +26440,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -26233,7 +26464,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26422,9 +26653,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26698,6 +26926,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26728,9 +26959,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -27034,9 +27262,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -27157,6 +27382,9 @@ 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 ""
@@ -27310,6 +27538,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27475,6 +27712,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "On track"
msgstr ""
@@ -27952,9 +28198,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -28048,6 +28291,9 @@ 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 ""
@@ -28369,6 +28615,15 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -28378,6 +28633,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -28387,6 +28645,9 @@ 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 ""
@@ -28444,6 +28705,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28462,9 +28726,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28483,6 +28753,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28540,6 +28813,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28591,18 +28867,33 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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 ""
@@ -28858,6 +29149,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28963,6 +29257,18 @@ 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 ""
@@ -29119,6 +29425,9 @@ 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 ""
@@ -29137,6 +29446,15 @@ 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 ""
@@ -29158,6 +29476,12 @@ 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 ""
@@ -29179,6 +29503,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -29191,6 +29518,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29437,6 +29767,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29605,9 +29938,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29620,12 +29962,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29644,6 +29992,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29680,6 +30031,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29695,6 +30052,9 @@ 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 ""
@@ -29707,6 +30067,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29806,6 +30169,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29908,6 +30274,9 @@ 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 ""
@@ -30154,7 +30523,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30868,6 +31237,9 @@ 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 ""
@@ -30877,6 +31249,12 @@ 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 ""
@@ -30955,6 +31333,9 @@ 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 ""
@@ -30967,6 +31348,9 @@ 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 ""
@@ -30994,6 +31378,9 @@ 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 ""
@@ -32182,18 +32569,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -32320,6 +32725,12 @@ 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 ""
@@ -32590,12 +33001,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32629,6 +33034,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32803,9 +33211,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32824,6 +33229,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32896,6 +33304,9 @@ 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 ""
@@ -32959,12 +33370,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -33106,12 +33511,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -33160,9 +33559,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -33271,6 +33667,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -33283,6 +33682,9 @@ 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 ""
@@ -33460,6 +33862,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33661,15 +34066,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33694,24 +34090,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33796,6 +34180,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33940,10 +34327,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -34054,12 +34441,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -34135,6 +34516,15 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -34198,6 +34588,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -34366,6 +34759,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -34393,6 +34789,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34501,6 +34900,9 @@ 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 ""
@@ -34564,9 +34966,18 @@ 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|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 ""
@@ -34612,6 +35023,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34627,6 +35041,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34642,6 +35059,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34684,6 +35104,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34693,6 +35116,9 @@ 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 ""
@@ -34771,6 +35197,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -35134,6 +35575,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -35194,6 +35641,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35467,6 +35917,12 @@ 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 ""
@@ -35632,6 +36088,9 @@ 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 group"
msgstr ""
@@ -35650,9 +36109,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35809,6 +36265,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35863,6 +36322,15 @@ 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 ""
@@ -36217,9 +36685,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -36403,9 +36868,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -36421,9 +36883,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36916,7 +37375,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -37003,6 +37462,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -37012,6 +37474,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -37246,9 +37711,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -38365,9 +38827,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38716,9 +39175,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38821,6 +39277,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38893,6 +39352,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38911,7 +39373,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -39010,9 +39472,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -39445,9 +39904,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39748,9 +40204,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39910,6 +40363,9 @@ 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 ""
@@ -40024,6 +40480,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -40096,6 +40555,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -40198,9 +40660,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -40279,9 +40738,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -40333,9 +40789,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40516,6 +40969,9 @@ 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 ""
@@ -40873,6 +41329,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -41185,6 +41647,9 @@ 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 ""
@@ -41275,9 +41740,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -41353,7 +41815,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41587,6 +42049,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41893,6 +42358,9 @@ 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 ""
@@ -41977,6 +42445,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -42097,6 +42568,9 @@ 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 ""
@@ -42160,6 +42634,9 @@ 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 ""
@@ -42205,9 +42682,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -42400,9 +42874,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -42430,6 +42901,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -42454,9 +42928,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42517,10 +42988,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42592,6 +43063,9 @@ 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 ""
@@ -42619,6 +43093,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42889,6 +43375,15 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42982,6 +43477,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -43090,6 +43588,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -43171,6 +43672,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -43336,15 +43840,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -43399,10 +43894,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -43492,6 +43993,12 @@ 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 ""
@@ -44113,6 +44620,9 @@ 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 ""
@@ -44158,9 +44668,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -44170,6 +44677,9 @@ 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 ""
@@ -44470,6 +44980,12 @@ 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 ""
@@ -44533,6 +45049,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "When:"
msgstr ""
@@ -44569,6 +45094,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44695,12 +45226,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44800,10 +45325,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44812,10 +45340,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44833,6 +45364,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44845,24 +45379,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44872,18 +45421,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -45169,8 +45739,14 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -45178,9 +45754,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -45235,7 +45808,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -45247,15 +45820,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -45286,11 +45853,14 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45628,6 +46198,9 @@ 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 ""
@@ -45640,9 +46213,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45655,7 +46225,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45829,6 +46399,24 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Your groups"
msgstr ""
@@ -45925,9 +46513,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45955,14 +46540,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+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 ""
@@ -46123,6 +46702,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -46207,6 +46789,9 @@ 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 ""
@@ -46312,9 +46897,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -46330,6 +46921,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46618,6 +47212,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46645,6 +47242,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46684,9 +47284,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46789,6 +47386,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46879,9 +47479,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46936,6 +47533,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -47116,6 +47716,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -47167,12 +47770,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -47293,9 +47890,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -47305,9 +47899,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -47347,9 +47938,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -47383,9 +47971,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -47470,21 +48055,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47821,6 +48394,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47833,6 +48409,9 @@ msgstr ""
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 ""
@@ -47944,13 +48523,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47971,6 +48550,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index b73d600d2cb..309ebf04f2a 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-07-14 17:11\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 124d05a99f5..4fd1b55aea9 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 7b12881f384..c4de825f476 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-07-14 17:12\n"
+"PO-Revision-Date: 2022-08-12 18:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ 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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28201,6 +28483,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 ""
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index a148084e806..02a44448c21 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Клони"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Създаване на нова папка"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "ВнедрÑване"
msgstr[1] "ВнедрÑваниÑ"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Планът за Ñхема не може да бъде премахнат"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "От Ñъздаването на проблема до внедрÑването в крайната верÑиÑ"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr "Въведете кратко опиÑание за тази Ñхема"
@@ -28399,6 +28690,9 @@ msgstr "Цел"
msgid "PipelineSchedules|Variables"
msgstr "Променливи"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr "ЗаÑвка за доÑтъп"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Задайте парола на акаунта Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Качване на файл"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 5444939edc8..b7c7fd055e3 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 2548033e4d5..25ec416ed92 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-07-14 17:12\n"
+"PO-Revision-Date: 2022-08-12 18:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index d9c3f3163ac..90218484012 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -685,6 +685,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -742,8 +745,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -943,6 +946,9 @@ 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 ""
@@ -994,6 +1000,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -1006,13 +1015,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1131,6 +1140,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1218,6 +1239,22 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1259,9 +1296,6 @@ msgstr[4] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1874,15 +1908,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1910,9 +1938,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2489,6 +2514,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2528,9 +2556,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2558,9 +2583,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2606,6 +2628,9 @@ 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 ""
@@ -4130,6 +4155,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4421,9 +4449,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4469,6 +4494,9 @@ 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 ""
@@ -4556,9 +4584,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4970,13 +4995,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -5003,6 +5040,18 @@ 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 ""
@@ -5163,28 +5212,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5202,6 +5254,9 @@ 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 ""
@@ -5229,9 +5284,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5576,9 +5628,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5623,7 +5672,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5640,12 +5689,6 @@ msgstr[4] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5706,6 +5749,12 @@ 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 ""
@@ -5724,6 +5773,9 @@ 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 ""
@@ -5739,18 +5791,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5763,6 +5830,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5979,7 +6049,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6168,6 +6238,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6519,6 +6592,9 @@ 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 ""
@@ -6612,17 +6688,19 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
+msgstr[4] ""
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 ""
@@ -6639,6 +6717,9 @@ 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 ""
@@ -6654,13 +6735,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -7002,9 +7080,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7616,9 +7736,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8313,9 +8430,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8741,6 +8855,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8759,6 +8876,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8816,12 +8939,18 @@ 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 ""
@@ -10659,9 +10788,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -11100,9 +11226,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11553,6 +11676,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11942,6 +12068,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11960,6 +12089,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11975,6 +12107,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -12020,6 +12155,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -12056,9 +12194,21 @@ 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 ""
@@ -12757,6 +12907,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12781,6 +12934,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12838,6 +12997,15 @@ 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 ""
@@ -12862,9 +13030,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -13090,6 +13255,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13345,7 +13513,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14164,9 +14332,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14575,9 +14740,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14899,9 +15061,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15400,6 +15559,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16384,22 +16546,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16417,6 +16576,9 @@ 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 ""
@@ -16462,9 +16624,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16710,6 +16869,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -17127,6 +17289,14 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Freeze end"
msgstr ""
@@ -17151,11 +17321,21 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17214,6 +17394,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17269,6 +17452,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17443,9 +17629,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17503,9 +17686,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17761,9 +17941,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17947,6 +18124,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17971,9 +18151,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -18067,6 +18244,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -18118,6 +18298,9 @@ 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 ""
@@ -18130,6 +18313,9 @@ 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 ""
@@ -18142,6 +18328,9 @@ 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 ""
@@ -18460,16 +18649,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18691,9 +18877,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18847,7 +19030,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -19012,7 +19195,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -19060,6 +19243,9 @@ 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 ""
@@ -19072,15 +19258,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -19099,9 +19279,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -19126,15 +19303,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19252,6 +19423,9 @@ 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 ""
@@ -19270,6 +19444,9 @@ 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 ""
@@ -19315,6 +19492,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19393,6 +19573,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19411,7 +19600,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19529,12 +19718,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19761,6 +19944,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19830,6 +20016,9 @@ 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 ""
@@ -20013,6 +20202,9 @@ 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 ""
@@ -20040,6 +20232,9 @@ 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 ""
@@ -20328,6 +20523,9 @@ msgstr[4] ""
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 ""
@@ -20373,9 +20571,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20433,9 +20628,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20478,9 +20670,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20490,18 +20679,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20520,9 +20703,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20691,9 +20871,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20766,9 +20943,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20841,12 +21015,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20862,9 +21030,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21890,7 +22055,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21970,7 +22135,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21985,9 +22150,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22393,6 +22555,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22408,12 +22573,36 @@ 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 ""
@@ -22435,6 +22624,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22465,10 +22657,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22477,6 +22669,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22504,9 +22699,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22534,13 +22726,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -23026,6 +23218,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -23149,7 +23344,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23423,15 +23618,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23714,19 +23903,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -24005,7 +24194,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -24017,6 +24209,48 @@ 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 ""
@@ -24344,9 +24578,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24608,7 +24839,7 @@ 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_whitelist}."
+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"
@@ -26014,12 +26245,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -26044,7 +26269,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26232,9 +26457,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26507,6 +26729,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26537,9 +26762,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26842,9 +27064,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26965,6 +27184,9 @@ 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 ""
@@ -27114,6 +27336,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27279,6 +27510,14 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "On track"
msgstr ""
@@ -27755,9 +27994,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27851,6 +28087,9 @@ 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 ""
@@ -28172,6 +28411,14 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -28181,6 +28428,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -28190,6 +28440,9 @@ 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 ""
@@ -28247,6 +28500,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28265,9 +28521,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28285,6 +28547,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28342,6 +28607,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28393,18 +28661,32 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
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 ""
@@ -28660,6 +28942,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28765,6 +29050,18 @@ 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 ""
@@ -28921,6 +29218,9 @@ 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 ""
@@ -28939,6 +29239,15 @@ 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 ""
@@ -28960,6 +29269,12 @@ 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 ""
@@ -28981,6 +29296,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28993,6 +29311,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29239,6 +29560,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29407,9 +29731,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29422,12 +29755,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29446,6 +29785,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29482,6 +29824,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29497,6 +29845,9 @@ 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 ""
@@ -29509,6 +29860,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29608,6 +29962,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29710,6 +30067,9 @@ 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 ""
@@ -29956,7 +30316,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30670,6 +31030,9 @@ 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 ""
@@ -30679,6 +31042,12 @@ 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 ""
@@ -30757,6 +31126,9 @@ 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 ""
@@ -30769,6 +31141,9 @@ 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 ""
@@ -30796,6 +31171,9 @@ 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 ""
@@ -31984,18 +32362,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -32122,6 +32518,12 @@ 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 ""
@@ -32392,12 +32794,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32431,6 +32827,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32604,9 +33003,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32624,6 +33020,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32696,6 +33095,9 @@ 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 ""
@@ -32759,12 +33161,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32906,12 +33302,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32960,9 +33350,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -33071,6 +33458,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -33083,6 +33473,9 @@ 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 ""
@@ -33255,6 +33648,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33454,15 +33850,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33487,24 +33874,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33587,6 +33962,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33731,10 +34109,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33843,12 +34221,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33924,6 +34296,14 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33985,6 +34365,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -34152,6 +34535,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -34178,6 +34564,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34286,6 +34675,9 @@ 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 ""
@@ -34348,9 +34740,18 @@ 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|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 ""
@@ -34396,6 +34797,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34411,6 +34815,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34426,6 +34833,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34468,6 +34878,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34477,6 +34890,9 @@ 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 ""
@@ -34555,6 +34971,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34907,6 +35338,12 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34967,6 +35404,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35240,6 +35680,12 @@ 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 ""
@@ -35405,6 +35851,9 @@ 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 group"
msgstr ""
@@ -35423,9 +35872,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35582,6 +36028,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35636,6 +36085,15 @@ 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 ""
@@ -35990,9 +36448,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -36176,9 +36631,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -36194,9 +36646,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36687,7 +37136,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36774,6 +37223,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36783,6 +37235,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -37017,9 +37472,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -38136,9 +38588,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38486,9 +38935,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38591,6 +39037,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38663,6 +39112,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38681,7 +39133,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38780,9 +39232,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -39209,9 +39658,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39509,9 +39955,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39671,6 +40114,9 @@ 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 ""
@@ -39785,6 +40231,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39857,6 +40306,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39959,9 +40411,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -40040,9 +40489,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -40094,9 +40540,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40277,6 +40720,9 @@ 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 ""
@@ -40634,6 +41080,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40946,6 +41398,9 @@ 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 ""
@@ -41034,9 +41489,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -41112,7 +41564,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41346,6 +41798,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41652,6 +42107,9 @@ 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 ""
@@ -41736,6 +42194,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41856,6 +42317,9 @@ 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 ""
@@ -41919,6 +42383,9 @@ 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 ""
@@ -41964,9 +42431,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -42159,9 +42623,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -42189,6 +42650,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -42213,9 +42677,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42276,10 +42737,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42351,6 +42812,9 @@ 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 ""
@@ -42378,6 +42842,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42648,6 +43124,14 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42741,6 +43225,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42849,6 +43336,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42930,6 +43420,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -43095,14 +43588,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -43157,10 +43642,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43250,6 +43741,12 @@ 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 ""
@@ -43868,6 +44365,9 @@ 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 ""
@@ -43913,9 +44413,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43925,6 +44422,9 @@ 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 ""
@@ -44225,6 +44725,12 @@ 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 ""
@@ -44287,6 +44793,14 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "When:"
msgstr ""
@@ -44323,6 +44837,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44449,12 +44969,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44554,10 +45068,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44566,10 +45083,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44586,6 +45106,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44598,24 +45121,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44625,18 +45163,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44921,8 +45480,13 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44930,9 +45494,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44987,7 +45548,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44999,15 +45560,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -45038,11 +45593,13 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45379,6 +45936,9 @@ 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 ""
@@ -45391,9 +45951,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45406,7 +45963,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45580,6 +46137,22 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
+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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "Your groups"
msgstr ""
@@ -45676,9 +46249,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45705,13 +46275,8 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
+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 ""
@@ -45870,6 +46435,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45953,6 +46521,9 @@ 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 ""
@@ -46057,9 +46628,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -46075,6 +46652,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46358,6 +46938,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46385,6 +46968,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46424,9 +47010,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46527,6 +47110,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46615,9 +47201,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46671,6 +47254,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46850,6 +47436,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46899,12 +47488,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -47024,9 +47607,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -47036,9 +47616,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -47077,9 +47654,6 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -47113,9 +47687,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -47200,21 +47771,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47546,6 +48105,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47558,6 +48120,9 @@ msgstr ""
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 ""
@@ -47669,13 +48234,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47696,6 +48261,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index ac1909adac0..8df0fb8d47f 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -535,6 +535,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -586,8 +589,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -775,6 +778,9 @@ 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 ""
@@ -826,6 +832,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -838,13 +847,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -961,6 +970,18 @@ msgstr "%{openedEpics} otvoreno, %{closedEpics} zatvoreno"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} otvoreno, %{closedIssues} zatvoreno"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1042,6 +1063,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1081,9 +1114,6 @@ msgstr[2] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1624,15 +1654,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 dana"
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr "30 minuta"
@@ -1660,9 +1684,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2239,6 +2260,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2278,9 +2302,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2308,9 +2329,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2356,6 +2374,9 @@ 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 ""
@@ -3880,6 +3901,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4171,9 +4195,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4219,6 +4240,9 @@ 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 ""
@@ -4306,9 +4330,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4714,13 +4735,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4747,6 +4780,18 @@ 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 ""
@@ -4897,28 +4942,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4936,6 +4984,9 @@ 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 ""
@@ -4963,9 +5014,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5308,9 +5356,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Zaduženi"
@@ -5353,7 +5398,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5368,12 +5413,6 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5434,6 +5473,12 @@ 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 ""
@@ -5452,6 +5497,9 @@ 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 ""
@@ -5467,18 +5515,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5491,6 +5554,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5707,7 +5773,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5896,6 +5962,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6247,6 +6316,9 @@ 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 ""
@@ -6340,17 +6412,17 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
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 ""
@@ -6367,6 +6439,9 @@ 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 ""
@@ -6382,13 +6457,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6724,9 +6796,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Grane"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7336,9 +7450,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8029,9 +8140,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8455,6 +8563,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8473,6 +8584,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8530,12 +8647,18 @@ 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 ""
@@ -10363,9 +10486,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10804,9 +10924,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11257,6 +11374,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11644,6 +11764,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11662,6 +11785,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11677,6 +11803,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11722,6 +11851,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11758,9 +11890,21 @@ 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 ""
@@ -12457,6 +12601,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12481,6 +12628,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12538,6 +12691,15 @@ 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 ""
@@ -12562,9 +12724,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12778,6 +12937,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13033,7 +13195,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13840,9 +14002,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14251,9 +14410,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14575,9 +14731,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15076,6 +15229,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16054,22 +16210,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16087,6 +16240,9 @@ 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 ""
@@ -16132,9 +16288,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16378,6 +16531,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16795,6 +16951,12 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16819,11 +16981,17 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16882,6 +17050,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16933,6 +17104,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17107,9 +17281,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17167,9 +17338,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17425,9 +17593,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17611,6 +17776,9 @@ msgstr "GitLab Zadatak"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17635,9 +17803,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17731,6 +17896,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17782,6 +17950,9 @@ 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 ""
@@ -17794,6 +17965,9 @@ 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 ""
@@ -17806,6 +17980,9 @@ 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 ""
@@ -18124,16 +18301,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18355,9 +18529,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18511,7 +18682,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18676,7 +18847,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18724,6 +18895,9 @@ 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 ""
@@ -18736,15 +18910,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18763,9 +18931,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18790,15 +18955,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18916,6 +19075,9 @@ 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 ""
@@ -18934,6 +19096,9 @@ 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 ""
@@ -18979,6 +19144,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19057,6 +19225,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19075,7 +19252,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19189,12 +19366,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19417,6 +19588,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19486,6 +19660,9 @@ 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 ""
@@ -19669,6 +19846,9 @@ 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 ""
@@ -19696,6 +19876,9 @@ 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 ""
@@ -19978,6 +20161,9 @@ msgstr[2] ""
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 ""
@@ -20023,9 +20209,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20083,9 +20266,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20128,9 +20308,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20140,18 +20317,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20170,9 +20341,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20341,9 +20509,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20416,9 +20581,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20491,12 +20653,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20512,9 +20668,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21538,7 +21691,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21616,7 +21769,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21631,9 +21784,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22039,6 +22189,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22054,12 +22207,36 @@ 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 ""
@@ -22081,6 +22258,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22111,10 +22291,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22123,6 +22303,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22150,9 +22333,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22180,13 +22360,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22672,6 +22852,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22795,7 +22978,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23065,15 +23248,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23356,19 +23533,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23635,7 +23812,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23647,6 +23827,48 @@ 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 ""
@@ -23974,9 +24196,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24238,7 +24457,7 @@ 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_whitelist}."
+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"
@@ -25636,12 +25855,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25666,7 +25879,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25852,9 +26065,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26125,6 +26335,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26155,9 +26368,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26458,9 +26668,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26581,6 +26788,9 @@ 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 ""
@@ -26722,6 +26932,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26887,6 +27106,12 @@ 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] ""
+msgstr[2] ""
+
msgid "On track"
msgstr ""
@@ -27361,9 +27586,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27457,6 +27679,9 @@ 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 ""
@@ -27778,6 +28003,12 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27787,6 +28018,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27796,6 +28030,9 @@ 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 ""
@@ -27853,6 +28090,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27871,9 +28111,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27889,6 +28135,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27946,6 +28195,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27997,18 +28249,30 @@ 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}, this operation is irreversible, 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[2] ""
+
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 ""
@@ -28264,6 +28528,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28369,6 +28636,18 @@ 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 ""
@@ -28525,6 +28804,9 @@ 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 ""
@@ -28543,6 +28825,15 @@ 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 ""
@@ -28564,6 +28855,12 @@ 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 ""
@@ -28585,6 +28882,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28597,6 +28897,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28843,6 +29146,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29011,9 +29317,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29026,12 +29341,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29050,6 +29371,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29086,6 +29410,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29101,6 +29431,9 @@ 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 ""
@@ -29113,6 +29446,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29212,6 +29548,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29314,6 +29653,9 @@ 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 ""
@@ -29560,7 +29902,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30274,6 +30616,9 @@ 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 ""
@@ -30283,6 +30628,12 @@ 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 ""
@@ -30361,6 +30712,9 @@ 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 ""
@@ -30373,6 +30727,9 @@ 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 ""
@@ -30400,6 +30757,9 @@ 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 ""
@@ -31588,18 +31948,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31726,6 +32104,12 @@ 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 ""
@@ -31996,12 +32380,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32035,6 +32413,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32206,9 +32587,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32224,6 +32602,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32296,6 +32677,9 @@ 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 ""
@@ -32359,12 +32743,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32506,12 +32884,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr "Zadatak uklonjen iz epika."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32560,9 +32932,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr "Uklanja zadatak iz epika."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32671,6 +33040,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32683,6 +33055,9 @@ 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 ""
@@ -32845,6 +33220,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33040,15 +33418,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33073,24 +33442,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33169,6 +33526,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33313,10 +33673,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33421,12 +33781,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33502,6 +33856,12 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33559,6 +33919,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33724,6 +34087,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33748,6 +34114,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33856,6 +34225,9 @@ 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 ""
@@ -33916,9 +34288,18 @@ 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|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 ""
@@ -33964,6 +34345,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33979,6 +34363,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33994,6 +34381,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34036,6 +34426,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34045,6 +34438,9 @@ 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 ""
@@ -34123,6 +34519,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34453,6 +34864,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34513,6 +34930,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34786,6 +35206,12 @@ 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 ""
@@ -34951,6 +35377,9 @@ 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 group"
msgstr ""
@@ -34969,9 +35398,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35128,6 +35554,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35182,6 +35611,15 @@ 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 ""
@@ -35536,9 +35974,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35722,9 +36157,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35740,9 +36172,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36229,7 +36658,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36316,6 +36745,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36325,6 +36757,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36559,9 +36994,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37678,9 +38110,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38026,9 +38455,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38131,6 +38557,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38203,6 +38632,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38221,7 +38653,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38320,9 +38752,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38737,9 +39166,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39031,9 +39457,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39193,6 +39616,9 @@ 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 ""
@@ -39307,6 +39733,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39379,6 +39808,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39481,9 +39913,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39562,9 +39991,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39616,9 +40042,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39799,6 +40222,9 @@ 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 ""
@@ -40156,6 +40582,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40468,6 +40900,9 @@ 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 ""
@@ -40552,9 +40987,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40630,7 +41062,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40864,6 +41296,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41170,6 +41605,9 @@ 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 ""
@@ -41254,6 +41692,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41374,6 +41815,9 @@ 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 ""
@@ -41437,6 +41881,9 @@ 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 ""
@@ -41482,9 +41929,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41677,9 +42121,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41707,6 +42148,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41731,9 +42175,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41794,10 +42235,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41869,6 +42310,9 @@ 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 ""
@@ -41896,6 +42340,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42166,6 +42622,12 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42259,6 +42721,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42367,6 +42832,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42448,6 +42916,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42613,12 +43084,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42673,10 +43138,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42766,6 +43237,12 @@ 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 ""
@@ -43378,6 +43855,9 @@ 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 ""
@@ -43423,9 +43903,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43435,6 +43912,9 @@ 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 ""
@@ -43735,6 +44215,12 @@ 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 ""
@@ -43795,6 +44281,12 @@ 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] ""
+msgstr[2] ""
+
msgid "When:"
msgstr ""
@@ -43831,6 +44323,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43957,12 +44455,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44062,10 +44554,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44074,10 +44569,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44092,6 +44590,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44104,24 +44605,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44131,18 +44647,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44425,8 +44962,11 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44434,9 +44974,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44491,7 +45028,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44503,15 +45040,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44542,11 +45073,11 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44881,6 +45412,9 @@ 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 ""
@@ -44893,9 +45427,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44908,7 +45439,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45082,6 +45613,18 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+
+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[2] ""
+
msgid "Your groups"
msgstr ""
@@ -45178,9 +45721,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45205,11 +45745,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+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 ""
@@ -45364,6 +45901,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45445,6 +45985,9 @@ 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 ""
@@ -45547,9 +46090,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45565,6 +46114,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45838,6 +46390,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45865,6 +46420,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45904,9 +46462,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46003,6 +46558,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46087,9 +46645,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46141,6 +46696,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46318,6 +46876,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46363,12 +46924,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46486,9 +47041,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46498,9 +47050,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46537,9 +47086,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46573,9 +47119,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46660,21 +47203,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46996,6 +47527,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47008,6 +47542,9 @@ msgstr ""
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 ""
@@ -47119,14 +47656,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "sljedeći zadaci"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr ""
@@ -47146,6 +47683,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 664b4999869..1b709efa5dc 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,15 +763,15 @@ 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 "%{label_for_message} no disponible"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Afegeix una taula"
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "ag."
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branques"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Actives"
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Domini"
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "Adreça electrònica"
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "feb."
msgid "February"
msgstr "febrer"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "Estat desconegut"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Historial"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 322a9695608..3ef93060c95 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -664,8 +667,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -859,6 +862,9 @@ 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 ""
@@ -910,6 +916,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -922,13 +931,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1046,6 +1055,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2481,6 +2501,9 @@ 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 ""
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "Srp"
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Větve"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Aktivní"
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 7cbfa52bc81..620d1c0859c 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-07-14 17:15\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -760,6 +760,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -820,8 +823,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -1027,6 +1030,9 @@ 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 ""
@@ -1078,6 +1084,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -1090,13 +1099,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1216,6 +1225,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1306,6 +1327,24 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1348,9 +1387,6 @@ msgstr[5] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1999,15 +2035,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -2035,9 +2065,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2614,6 +2641,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2653,9 +2683,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2683,9 +2710,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2731,6 +2755,9 @@ 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 ""
@@ -4255,6 +4282,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4546,9 +4576,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4594,6 +4621,9 @@ 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 ""
@@ -4681,9 +4711,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -5098,13 +5125,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -5131,6 +5170,18 @@ 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 ""
@@ -5296,28 +5347,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5335,6 +5389,9 @@ 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 ""
@@ -5362,9 +5419,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5710,9 +5764,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5758,7 +5809,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5776,12 +5827,6 @@ msgstr[5] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5842,6 +5887,12 @@ 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 ""
@@ -5860,6 +5911,9 @@ 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 ""
@@ -5875,18 +5929,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5899,6 +5968,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -6115,7 +6187,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6304,6 +6376,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6655,6 +6730,9 @@ 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 ""
@@ -6748,17 +6826,20 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
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 ""
@@ -6775,6 +6856,9 @@ 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 ""
@@ -6790,13 +6874,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -7141,9 +7222,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7756,9 +7879,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8455,9 +8575,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8884,6 +9001,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8902,6 +9022,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8959,12 +9085,18 @@ 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 ""
@@ -10807,9 +10939,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -11248,9 +11377,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11701,6 +11827,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -12091,6 +12220,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -12109,6 +12241,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -12124,6 +12259,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -12169,6 +12307,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -12205,9 +12346,21 @@ 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 ""
@@ -12907,6 +13060,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12931,6 +13087,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12988,6 +13150,15 @@ 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 ""
@@ -13012,9 +13183,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -13246,6 +13414,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13501,7 +13672,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14326,9 +14497,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14737,9 +14905,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -15061,9 +15226,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15562,6 +15724,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16549,22 +16714,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16582,6 +16744,9 @@ 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 ""
@@ -16627,9 +16792,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16876,6 +17038,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -17293,6 +17458,15 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Freeze end"
msgstr ""
@@ -17317,11 +17491,23 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17380,6 +17566,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17437,6 +17626,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17611,9 +17803,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17671,9 +17860,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17929,9 +18115,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -18115,6 +18298,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -18139,9 +18325,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -18235,6 +18418,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -18286,6 +18472,9 @@ 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 ""
@@ -18298,6 +18487,9 @@ 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 ""
@@ -18310,6 +18502,9 @@ 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 ""
@@ -18628,16 +18823,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18859,9 +19051,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -19015,7 +19204,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -19180,7 +19369,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -19228,6 +19417,9 @@ 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 ""
@@ -19240,15 +19432,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -19267,9 +19453,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -19294,15 +19477,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19420,6 +19597,9 @@ 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 ""
@@ -19438,6 +19618,9 @@ 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 ""
@@ -19483,6 +19666,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19561,6 +19747,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19579,7 +19774,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19699,12 +19894,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19933,6 +20122,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -20002,6 +20194,9 @@ 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 ""
@@ -20185,6 +20380,9 @@ 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 ""
@@ -20212,6 +20410,9 @@ 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 ""
@@ -20503,6 +20704,9 @@ msgstr[5] ""
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 ""
@@ -20548,9 +20752,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20608,9 +20809,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20653,9 +20851,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20665,18 +20860,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20695,9 +20884,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20866,9 +21052,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20941,9 +21124,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -21016,12 +21196,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -21037,9 +21211,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -22066,7 +22237,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -22147,7 +22318,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -22162,9 +22333,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22570,6 +22738,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22585,12 +22756,36 @@ 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 ""
@@ -22612,6 +22807,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22642,10 +22840,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22654,6 +22852,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22681,9 +22882,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22711,13 +22909,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -23203,6 +23401,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -23326,7 +23527,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23602,15 +23803,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23893,19 +24088,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -24190,7 +24385,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -24202,6 +24400,48 @@ 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 ""
@@ -24529,9 +24769,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24793,7 +25030,7 @@ 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_whitelist}."
+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"
@@ -26203,12 +26440,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -26233,7 +26464,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26422,9 +26653,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26698,6 +26926,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26728,9 +26959,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -27034,9 +27262,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -27157,6 +27382,9 @@ 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 ""
@@ -27310,6 +27538,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27475,6 +27712,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "On track"
msgstr ""
@@ -27952,9 +28198,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -28048,6 +28291,9 @@ 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 ""
@@ -28369,6 +28615,15 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -28378,6 +28633,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -28387,6 +28645,9 @@ 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 ""
@@ -28444,6 +28705,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28462,9 +28726,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28483,6 +28753,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28540,6 +28813,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28591,18 +28867,33 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
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 ""
@@ -28858,6 +29149,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28963,6 +29257,18 @@ 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 ""
@@ -29119,6 +29425,9 @@ 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 ""
@@ -29137,6 +29446,15 @@ 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 ""
@@ -29158,6 +29476,12 @@ 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 ""
@@ -29179,6 +29503,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -29191,6 +29518,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29437,6 +29767,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29605,9 +29938,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29620,12 +29962,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29644,6 +29992,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29680,6 +30031,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29695,6 +30052,9 @@ 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 ""
@@ -29707,6 +30067,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29806,6 +30169,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29908,6 +30274,9 @@ 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 ""
@@ -30154,7 +30523,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30868,6 +31237,9 @@ 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 ""
@@ -30877,6 +31249,12 @@ 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 ""
@@ -30955,6 +31333,9 @@ 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 ""
@@ -30967,6 +31348,9 @@ 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 ""
@@ -30994,6 +31378,9 @@ 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 ""
@@ -32182,18 +32569,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -32320,6 +32725,12 @@ 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 ""
@@ -32590,12 +33001,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32629,6 +33034,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32803,9 +33211,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32824,6 +33229,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32896,6 +33304,9 @@ 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 ""
@@ -32959,12 +33370,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -33106,12 +33511,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -33160,9 +33559,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -33271,6 +33667,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -33283,6 +33682,9 @@ 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 ""
@@ -33460,6 +33862,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33661,15 +34066,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33694,24 +34090,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33796,6 +34180,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33940,10 +34327,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -34054,12 +34441,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -34135,6 +34516,15 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -34198,6 +34588,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -34366,6 +34759,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -34393,6 +34789,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34501,6 +34900,9 @@ 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 ""
@@ -34564,9 +34966,18 @@ 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|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 ""
@@ -34612,6 +35023,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34627,6 +35041,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34642,6 +35059,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34684,6 +35104,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34693,6 +35116,9 @@ 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 ""
@@ -34771,6 +35197,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -35134,6 +35575,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -35194,6 +35641,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35467,6 +35917,12 @@ 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 ""
@@ -35632,6 +36088,9 @@ 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 group"
msgstr ""
@@ -35650,9 +36109,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35809,6 +36265,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35863,6 +36322,15 @@ 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 ""
@@ -36217,9 +36685,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -36403,9 +36868,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -36421,9 +36883,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36916,7 +37375,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -37003,6 +37462,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -37012,6 +37474,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -37246,9 +37711,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -38365,9 +38827,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38716,9 +39175,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38821,6 +39277,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38893,6 +39352,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38911,7 +39373,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -39010,9 +39472,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -39445,9 +39904,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39748,9 +40204,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39910,6 +40363,9 @@ 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 ""
@@ -40024,6 +40480,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -40096,6 +40555,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -40198,9 +40660,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -40279,9 +40738,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -40333,9 +40789,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40516,6 +40969,9 @@ 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 ""
@@ -40873,6 +41329,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -41185,6 +41647,9 @@ 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 ""
@@ -41275,9 +41740,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -41353,7 +41815,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41587,6 +42049,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41893,6 +42358,9 @@ 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 ""
@@ -41977,6 +42445,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -42097,6 +42568,9 @@ 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 ""
@@ -42160,6 +42634,9 @@ 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 ""
@@ -42205,9 +42682,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -42400,9 +42874,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -42430,6 +42901,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -42454,9 +42928,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42517,10 +42988,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42592,6 +43063,9 @@ 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 ""
@@ -42619,6 +43093,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42889,6 +43375,15 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42982,6 +43477,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -43090,6 +43588,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -43171,6 +43672,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -43336,15 +43840,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -43399,10 +43894,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -43492,6 +43993,12 @@ 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 ""
@@ -44113,6 +44620,9 @@ 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 ""
@@ -44158,9 +44668,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -44170,6 +44677,9 @@ 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 ""
@@ -44470,6 +44980,12 @@ 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 ""
@@ -44533,6 +45049,15 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "When:"
msgstr ""
@@ -44569,6 +45094,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44695,12 +45226,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44800,10 +45325,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44812,10 +45340,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44833,6 +45364,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44845,24 +45379,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44872,18 +45421,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -45169,8 +45739,14 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -45178,9 +45754,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -45235,7 +45808,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -45247,15 +45820,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -45286,11 +45853,14 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45628,6 +46198,9 @@ 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 ""
@@ -45640,9 +46213,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45655,7 +46225,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45829,6 +46399,24 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+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[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Your groups"
msgstr ""
@@ -45925,9 +46513,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45955,14 +46540,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+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 ""
@@ -46123,6 +46702,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -46207,6 +46789,9 @@ 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 ""
@@ -46312,9 +46897,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -46330,6 +46921,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46618,6 +47212,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46645,6 +47242,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46684,9 +47284,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46789,6 +47386,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46879,9 +47479,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46936,6 +47533,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -47116,6 +47716,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -47167,12 +47770,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -47293,9 +47890,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -47305,9 +47899,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -47347,9 +47938,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -47383,9 +47971,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -47470,21 +48055,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47821,6 +48394,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47833,6 +48409,9 @@ msgstr ""
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 ""
@@ -47944,13 +48523,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47971,6 +48550,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index cb14bce855e..aad3f354200 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr "%{address} er et ugyldigt IP-adresseområde"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} klonede %{original_issue} til %{new_issue}."
@@ -508,10 +511,10 @@ msgstr "%{commit_author_link} forfattede %{commit_authored_timeago} og %{commit_
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} fuldført vægt"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} af %{count} opgave fuldført"
-msgstr[1] "%{completedCount} af %{count} opgaver fuldført"
+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 "%{completedWeight} af %{totalWeight} vægt fuldført"
@@ -691,6 +694,9 @@ msgstr "%{integrations_link_start}Integreringer%{link_end} giver dig mulighed fo
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} fjernes! Er du sikker?"
+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 ""
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Metode:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Navnerum:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Skanner:%{labelEnd} %{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Alvorlighed:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Værktøj:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Uændret svar:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} utilgængelig"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 time"
@@ -876,6 +885,18 @@ msgstr "%{openedEpics} åbne, %{closedEpics} lukkede"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} åbne, %{closedIssues} lukkede"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "%{securityScanner} resultat er ikke tilgængeligt fordi en pipeline ikke er blevet kørt siden den blev aktiveret. %{linkStart}Kør en pipeline%{linkEnd}"
msgstr[1] "%{securityScanner} resultater er ikke tilgængelige fordi en pipeline ikke er blevet kørt siden de blev aktiverede. %{linkStart}Kør en pipeline%{linkEnd}"
+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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ 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."
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Registreret"
-msgid "3 days"
-msgstr "3 dage"
-
msgid "3 hours"
msgstr "3 timer"
-msgid "30 days"
-msgstr "30 dage"
-
msgid "30 minutes"
msgstr "30 minutter"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 dage"
-
msgid "8 hours"
msgstr "8 timer"
@@ -2114,6 +2133,9 @@ msgstr "Tilføj en aftale om vilkår for tjeneste og privatlivspolitik til bruge
msgid "Add a bullet list"
msgstr "Tilføj en punktliste"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Tilføj et afsnit som kan foldes sammen"
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Tilføj en tabel"
-msgid "Add a task list"
-msgstr "Tilføj en opgaveliste"
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr "Tilføj godkendelsesregel"
msgid "Add approvers"
msgstr "Tilføj godkendere"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Tilføj broadcastmeddelelse"
@@ -2231,6 +2247,9 @@ msgstr "Tilføj miljø"
msgid "Add existing confidential %{issuableType}"
msgstr "Tilføj eksisterende fortrolig %{issuableType}"
+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 ""
@@ -3755,6 +3774,9 @@ msgstr "Alle grene"
msgid "All changes are committed"
msgstr "Alle ændringer er committed"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "Alle e-mailadresser vil blive brugt til at identificere dine commits."
@@ -4046,9 +4068,6 @@ msgstr "Der opstod en fejl under hentning af Markdown-forhåndsvisning"
msgid "An error occurred while fetching ancestors"
msgstr "Der opstod en fejl under hentning af forfædre"
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ msgstr "Der opstod en fejl under hentning af projekternes autofuldfør."
msgid "An error occurred while fetching reference"
msgstr "Der opstod en fejl under hentning af reference"
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr "Der opstod en fejl under hentning af mærkater. Prøv søgningen igen."
@@ -4181,9 +4203,6 @@ msgstr "Der opstod en fejl under indlæsning af fanebladet Behov."
msgid "An error occurred while loading the Test Reports tab."
msgstr "Der opstod en fejl under indlæsning af fanebladet Testrapporter."
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Der opstod en fejl under indlæsning af formularen til adgangstokens. Prøv venligst igen."
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ msgstr ""
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr "Kræv administratorgodkendelse ved nye tilmeldinger"
+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 "Gem ændringer"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 "domain.com"
@@ -4764,28 +4807,31 @@ msgstr "MÃ¥lgren"
msgid "ApprovalRule|Try for free"
msgstr ""
+msgid "ApprovalSettings|Keep approvals"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Godkendelsesindstillinger for sammenlægningsanmodning er blevet opdateret."
msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
-msgstr "Forhindr godkendelse af forfatter."
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
-msgstr "Forhindr godkendelse af brugere som tilføjer commits."
-
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 "Forhindr redigering af godkendelsesregler i projekter og sammenlægningsanmodninger."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ msgstr "Indstillingen er konfigureret på instansniveau og kan kun ændres af en
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 "Godkendelser er valgfrie."
@@ -4830,9 +4879,6 @@ msgstr "Godkendte den nuværende sammenlægningsanmodning."
msgid "Approved-By"
msgstr "Godkendt-af"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Godkender"
@@ -5174,9 +5220,6 @@ msgstr "Tildelt til mig"
msgid "Assigned to you"
msgstr "Tildelt til dig"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Tildeler"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr "I fare"
-msgid "Attach a file"
-msgstr "Vedhæft en fil"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr "Vedhæfter fil - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] "Vedhæfter %d filer"
msgid "Attaching the file failed."
msgstr "Kunne ikke vedhæfte filen."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "Aug."
@@ -5571,8 +5635,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Automatisk løst"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Opdater automatisk projektets grene og mærkater fra upstream-depotet hver time."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr ""
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr "Brugeren med API-adgang til Bamboo-serveren."
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ msgstr "Forlæng plan"
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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr "Eksportér liste"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr "Gruppeinvitation"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ msgstr "Projektinvitation"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Fjern brugeren %{username} fra dit abonnement"
+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 "Sædedetaljer til/fra"
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Grene"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Aktiv"
@@ -7196,9 +7307,6 @@ msgstr "Kan ikke finde HEAD-commit for grenen"
msgid "Can't find variable: ZiteReader"
msgstr "Kan ikke finde variabel: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "Kan koden ikke skannes?"
@@ -7887,9 +7995,6 @@ msgstr "Underepicen findes ikke."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr "Understøttelse af kinesisk sprog med"
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr "Du kan tilføje et aftryk til registeret med følgende kommandoer:"
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr "Indholdsfortegnelse"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr "Opret %{type}"
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Opret ny mappe"
@@ -11109,6 +11223,9 @@ msgstr "Kreditkort:"
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr "DAST-konfiguration"
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Dato"
@@ -11528,6 +11651,9 @@ msgstr "Udsendelseshyppighed"
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr "Diagrammet viser mediantiden mellem en sammenlægningsanmodning, der sam
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 "Generer kodeudklip"
+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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr "Slet fil"
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr "Slet projekt"
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr "Slet række"
@@ -12388,6 +12538,15 @@ msgstr "Kunne ikke fjerne webhooks. Prøv venligst igen eller kontakt administra
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "Kunne ikke fjerne wikidepot. Prøv venligst igen eller kontakt administrator."
+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 "Value Stream'et '%{name}' slettet"
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr "Sletter"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Udsendelse"
msgstr[1] "Udsendelser"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Udsendelsesnøgler"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr "URL for dokumentationssider"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "Dokumenter genindekseret: %{processed_documents} (%{percentage} %%)"
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Domæne"
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr "Kvalificerede brugere"
-
msgid "Email"
msgstr "E-mail"
@@ -14413,9 +14566,6 @@ msgstr "Aktivér Git-adgangsprotokoller"
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr "Stødte på en fejl under gengivelse: %{err}"
-
msgid "End Time"
msgstr "Sluttidspunkt"
@@ -14914,6 +15064,9 @@ msgstr "Fejl ved oprettelse af depot for udklip med id'et %{snippet_id}"
msgid "Error creating the snippet"
msgstr "Fejl ved oprettelse af udklippet"
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr "Fejl ved sletning af projekt. Tjek loggene for fejldetaljer."
@@ -15889,24 +16042,21 @@ msgstr "Kunne ikke fjerne et Zoom-møde"
msgid "Failed to remove a to-do item for the design."
msgstr "Kunne ikke fjerne et gøremålselement for designet."
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Kunne ikke fjerne pipelineplanlægningen"
+msgid "Failed to remove timelog"
+msgstr ""
+
msgid "Failed to remove user identity."
msgstr "Kunne ikke fjerne brugeridentitet."
msgid "Failed to remove user key."
msgstr "Kunne ikke fjerne brugernøgle."
-msgid "Failed to request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr "Kunne ikke hente side"
@@ -15922,6 +16072,9 @@ msgstr "Kunne ikke gemme præferencer (%{error_message})."
msgid "Failed to save preferences."
msgstr "Kunne ikke gemme præferencer."
+msgid "Failed to save timelog"
+msgstr ""
+
msgid "Failed to set due date because the date format is invalid."
msgstr ""
@@ -15967,9 +16120,6 @@ msgstr "Falsk positiv"
msgid "Fast timeout"
msgstr "Hurtig timeout"
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr "Hurtigere udgivelser. Bedre kode. Mindre smerte."
@@ -16212,6 +16362,9 @@ msgstr "Feb."
msgid "February"
msgstr "Februar"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr "Framework slettet"
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Gratis prøveperiode af GitLab.com Ultimate"
+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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr "Fra %{code_open}%{source_title}%{code_close} ind i"
msgid "From %{providerTitle}"
msgstr "Fra %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr "Generisk"
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr "%{component} verificeret"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} må ikke være tomt"
@@ -16939,9 +17107,6 @@ msgstr "Hvis du vil foretage ændringer, så skal du besøge det primære webste
msgid "Geo|In progress"
msgstr "I gang"
-msgid "Geo|In sync"
-msgstr "Er synkroniseret"
-
msgid "Geo|Internal URL"
msgstr "Intern URL"
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr "Ingen tilgængelige replikationspladser"
-msgid "Geo|Not synced yet"
-msgstr "Ikke synkroniseret endnu"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr "Usund"
msgid "Geo|Unknown"
msgstr "Ukendt"
-msgid "Geo|Unknown state"
-msgstr "Ukendt tilstand"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "Opdateret %{timeAgo}"
@@ -17443,6 +17602,9 @@ msgstr "GitLab-problemstilling"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Certifikat: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr "Konfigurer sider"
@@ -17614,6 +17776,9 @@ msgstr "Gem ændringer"
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 "Noget fik galt under indhentning af Let's Encrypt-certifikatet til %{domain}. Besøg dine %{link_start}domænedetaljer%{link_end} for at prøve igen."
+msgid "GitLabPages|Start over"
+msgstr ""
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -17626,6 +17791,9 @@ msgstr ""
msgid "GitLabPages|Verified"
msgstr "Verificeret"
+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 ""
@@ -17638,6 +17806,9 @@ 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 "Dine sider leveres under:"
@@ -17956,16 +18127,13 @@ msgstr "GÃ¥ til dine udklip"
msgid "Google Cloud"
msgstr "Google Cloud"
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr "Gruppenavigation"
msgid "Group overview content"
msgstr "Indhold for gruppeoversigt"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ msgstr ""
msgid "GroupSettings|Export group"
msgstr "Eksportér gruppe"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr ""
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr "Forhindr forgrening uden for gruppen"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "Indstillingen forhindr forgrening blev ikke gemt"
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "Auto DevOps-pipelinen kører hvis ingen alternativ CI-konfigurationsfil bliver fundet."
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ msgstr "Opret gruppe"
msgid "GroupsNew|Create new group"
msgstr "Opret ny gruppe"
+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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "Upload fil"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "f.eks. h8d3f016698e ..."
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "Retningslinje"
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr "Headerlogo"
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Historik"
@@ -19314,6 +19482,9 @@ msgstr "Hvordan bruger jeg er webterminal?"
msgid "How do I use file templates?"
msgstr "Hvordan bruger jeg filskabeloner?"
+msgid "How does pull mirroring work?"
+msgstr ""
+
msgid "How many seconds an IP counts toward the IP address limit."
msgstr ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ msgstr[1] "Importerer %d depoter"
msgid "Importing..."
msgstr "Importerer ..."
+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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr "%{strong_start}Flere godkendelsesroller%{strong_end} — herunder kodeejere og krævede sammenlægningsgodkendelser"
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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 "Ved at aktivere kodeejere og krævede sammenlægningsgodkendelser vil den korrekte person kontrollere den rette sammenlægningsanmodning. Det har flere fordele: renere kode og en mere effektiv kontrolproces."
-msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr "Svært"
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-msgstr "Har du et øjeblik?"
-
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr ""
msgid "InProductMarketing|Dynamic application security testing"
msgstr ""
-msgid "InProductMarketing|Easy"
-msgstr "Nemt"
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr "Feedback fra brugere som dig forbedrer virkelig vores produkt. Tak for din hjælp!"
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr "Har du brug for et alternativ til at importere?"
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr "Ingen kreditkort kræves."
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr "Meget svært"
-
-msgid "InProductMarketing|Very easy"
-msgstr "Meget nemt"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ msgstr "Inviter dine kollegaer"
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 "Vi har bemærket at du ikke har inviteret nogen til gruppen. Invitér dine kollegaer, så du kan debattere problemstillinger, samarbejde på sammenlægningsanmodninger og dele din viden."
-msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "Du inviterer en gruppe til gruppen %{strongStart}%{name}%{strongEnd}."
@@ -21862,6 +22006,9 @@ msgstr "Kursiv tekst"
msgid "Iteration"
msgstr "Gennemløb"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Gennemløb ændret til"
@@ -21877,12 +22024,36 @@ msgstr "Gennemløb opdateret"
msgid "Iterations"
msgstr "Gennemløb"
+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 "Tilføj gennemløb"
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 ""
@@ -21904,6 +22075,9 @@ msgstr "Opret kadence"
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr "Slet kadence"
@@ -21934,18 +22108,21 @@ msgstr "Rediger gennemløb"
msgid "Iterations|Edit iteration cadence"
msgstr "Rediger gennemløbskadence"
+msgid "Iterations|Enable roll over"
+msgstr ""
+
msgid "Iterations|Error loading iteration cadences."
msgstr "Fejl ved indlæsning af gennemløbskadencer."
-msgid "Iterations|First iteration start date"
-msgstr ""
-
msgid "Iterations|Iteration cadences"
msgstr "Gennemløbskadencer"
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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr "Ingen gennemløb i kadence."
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr "Ingen åbne gennemløb."
@@ -22003,13 +22177,13 @@ msgstr "Vælg startdato"
msgid "Iterations|Start date"
msgstr "Startdato"
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Rul nederst"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Rul øverst"
@@ -22618,8 +22795,8 @@ msgstr "Nøgle"
msgid "Key (PEM)"
msgstr "Nøgle (PEM)"
-msgid "Key: %{key}"
-msgstr "Nøgle: %{key}"
+msgid "Key:"
+msgstr ""
msgid "Keyboard shortcuts"
msgstr "Tastaturgenveje"
@@ -22886,15 +23063,9 @@ msgstr "Sidste indlognings-IP:"
msgid "Last sign-in at:"
msgstr "Sidste indlogning kl.:"
-msgid "Last successful sync"
-msgstr "Sidste synkronisering som lykkedes"
-
msgid "Last successful update"
msgstr "Sidste opdatering som lykkedes"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt accepterer ikke e-mails på example.com"
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 "Let's Encrypt er en gratis automatiserede open source certifikatmyndighed (CA) som giver digitale certifikater for at gøre det muligt at bruge HTTPS (SSL/TLS) på websteder. Lær mere om konfigurationen af Let's Encrypt ved at følge %{docs_link_start}dokumentationen på GitLab Pages%{docs_link_end}."
-msgid "Let's talk!"
-msgstr ""
-
msgid "License Compliance"
msgstr "Licensoverholdelse"
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,8 +23621,11 @@ msgstr "Linkede e-mails (%{email_count})"
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Linkede problemstillinger"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr ""
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23462,6 +23636,48 @@ msgstr "LinkedIn:"
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 "Links"
@@ -23789,9 +24005,6 @@ msgstr "Manifest-import"
msgid "Manual"
msgstr "Manuelt"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,8 +24266,8 @@ msgstr ""
msgid "Maximum file size indexed (KiB)"
msgstr "Maksimale filstørrelse indekseret (KiB)"
-msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}."
-msgstr "Den maksimale filstørrelse er 1 MB. Billedstørrelsen skal være 32 x 32 pixels. Tilladte billedformater er %{favicon_extension_whitelist}."
+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 ""
@@ -25447,12 +25660,6 @@ msgstr "Stop miljø"
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr "Multiprojekt"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr "Log ud og log ind med en anden konto"
msgid "Need help?"
msgstr "Brug for hjælp?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr "Behov"
@@ -25934,6 +26138,9 @@ msgstr "Ingen CSV-data at vise."
msgid "No Epic"
msgstr "Ingen epic"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr "Ingen artefakter fundet"
msgid "No assignee"
msgstr "Ingen tildeler"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr "Normal tekst"
-msgid "Not Implemented"
-msgstr "Ikke implementeret"
-
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 ""
@@ -26389,6 +26590,9 @@ 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 "Intet at forhåndsvise."
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ msgstr ""
msgid "On"
msgstr "Til"
+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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ msgstr "Mere information"
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 "Driftbetjeningspanelet giver en opsummering over hvert projekts driftssundhed, herunder pipeline- og alertbeskedstatusser."
@@ -27581,6 +27799,11 @@ msgstr "Oprettet af committen %{link} på grenen %{branch}"
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr "Slet pakkefil"
@@ -27590,6 +27813,9 @@ msgstr "Slet pakkeversion"
msgid "PackageRegistry|Delete package"
msgstr "Slet pakke"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr "Lær at %{noPackagesLinkStart}udgive og dele dine pakker%{noPackagesLink
msgid "PackageRegistry|License information located at %{link}"
msgstr "Licensinformation placeret på %{link}"
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr "Udgivet manuelt"
@@ -27674,9 +27906,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "NuGet-kommando"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Pip-kommando"
@@ -27748,6 +27989,9 @@ msgstr "Vis PyPi-kommandoer"
msgid "PackageRegistry|Show Yarn commands"
msgstr "Vis Yarn-kommandoer"
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr "Noget gik galt under sletning af pakkefilen."
@@ -27799,18 +28043,29 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Kan ikke indlæse pakke"
+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 "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 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 "Du er ved at slette version %{version} af %{name}. Er du sikker?"
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 "npm"
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "Udfør almindelige operationer på GitLab-projekt"
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "Ydelsesoptimering"
@@ -28171,6 +28429,18 @@ msgstr "Personlige projekter"
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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Næste kørsel"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Angiv en kort beskrivelse til pipelinen"
@@ -28399,6 +28690,9 @@ msgstr "MÃ¥l"
msgid "PipelineSchedules|Variables"
msgstr "Variabler"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28645,6 +28939,9 @@ msgstr "Ejer"
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Projektmellemlager nulstillet."
@@ -28813,9 +29110,18 @@ msgstr "Løsrevet sammenlægningsanmodningspipeline"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr "I gang"
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr "Afventer"
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -28852,6 +29164,9 @@ msgstr "Rå tekstsøgning understøttes ikke i øjeblikket. Brug venligst de til
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr "Kør pipeline"
@@ -28888,6 +29203,12 @@ msgstr "Mærkatnavn"
msgid "Pipeline|Test coverage"
msgstr "Testdækning"
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 "Udløserforfatter"
@@ -28915,6 +29239,9 @@ msgstr "Variabler"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "Vis pipeline"
@@ -29014,6 +29341,9 @@ msgstr "Tjek venligst din e-mail %{email} for at bekræfte din konto"
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 "Tjek venligst din e-mail (%{email}) for at bekræfte at du ejer adressen og lås op for styrken i CI/CD. Har du ikke modtages den? %{resend_link}. Forkert e-mailadresse? %{update_link}."
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ msgstr "Angiv venligst attributter for at opdatere"
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 ""
@@ -29362,8 +29695,8 @@ msgstr "Forrige"
msgid "Prevent auto-stopping"
msgstr "Forhindr automatisk stop"
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr "Forhindr redigering af godkendelsesregler i projekter og sammenlægningsanmodninger."
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr ""
msgid "Prevent environment from auto-stopping"
msgstr "Forhindr automatisk stop af miljø"
@@ -30076,6 +30409,9 @@ msgstr "Projektslug"
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 ""
@@ -30085,6 +30421,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Projekt: %{name}"
+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 "Abonner"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 " eller gruppe"
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} vil være skrivbar for udviklere. Er du sikker?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "MÃ¥ udsende"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Miljø"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+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 "Beskyt"
@@ -31528,6 +31897,12 @@ msgstr "Pull-anmodninger fra forgrening understøttes ikke"
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 "Køb flere minutter"
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr "Recaptcha verificeret?"
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr "Modtag underretninger fra GitLab."
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr "Genkonfigurer"
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr "Gendannelseskoder"
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr "Relaterede funktionsflag"
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr "Relaterede problemstillinger"
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] "Udgivelse"
msgstr[1] "Udgivelser"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr "Udgivelsesmaterialer"
@@ -32096,6 +32468,9 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release."
msgstr "Noget gik galt under oprettelse af en ny udgivelse."
+msgid "Release|Something went wrong while deleting the release."
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details."
msgstr "Noget gik galt under hentning af udgivelsesdetaljerne."
@@ -32159,12 +32534,6 @@ msgstr "Fjern materialelink"
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Fjern avatar"
@@ -32306,12 +32675,6 @@ msgstr "Fjernede alle etiketter."
msgid "Removed an issue from an epic."
msgstr "Fjernede en problemstilling fra en epic."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr "Fjerner alle etiketter."
msgid "Removes an issue from an epic."
msgstr "Fjerner en problemstilling fra en epic."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Fjerner forælderepicen %{epic_ref}."
@@ -32471,6 +32831,9 @@ msgstr "Besvar e-mailen direkte eller %{view_it_on_gitlab}."
msgid "Reply…"
msgstr "Besvar …"
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Rapportér misbrug"
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr "SÃ¥rbarhed"
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr "Anmod om adgang"
msgid "Request a new one"
msgstr "Anmod om en ny"
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr "Anmodet"
msgid "Requested %{time_ago}"
msgstr "Anmodet %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr "Send igen"
msgid "Resend Request"
msgstr "Send anmodning igen"
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "Send bekræftelses e-mail igen"
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr "Prøv igen"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr "Kopiér e-mailadresse"
msgid "RightSidebar|Issue email"
msgstr "Problemstillings e-mail"
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr "sletter"
-
msgid "Roadmap"
msgstr "Vejkort"
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr "Egenskabsnavn"
msgid "Runners|Protected"
msgstr "Beskyttet"
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 "Noget gik galt under hentning af runnerdata."
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr "gruppe"
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr "sat på pause"
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr "delt"
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "Kører"
@@ -33820,6 +34200,9 @@ msgstr "SAST-konfiguration"
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "SSH-nøgle"
@@ -33829,6 +34212,9 @@ msgstr "SSH-nøgler"
msgid "SSH Keys Help"
msgstr "Hjælp for SSH-nøgler"
+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 ""
@@ -33907,6 +34293,21 @@ msgstr "Gemmer"
msgid "Saving project."
msgstr "Gemmer projekt."
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] "wikiresultat"
msgstr[1] "wikiresultater"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr "Søgning efter både forfatter og meddelelse understøttes ikke i øjeblikket."
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr "Sikkerhedsbetjeningspanel"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Sikkerhedsbetjeningspanel"
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr "Kunne ikke hente sikkerhedsrapportinformation. Genindlæs venligst siden
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Problemstilling oprettet"
@@ -34955,6 +35374,15 @@ 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 "Projekt"
@@ -35309,9 +35737,6 @@ 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 "Valgte niveauer kan ikke bruges af brugere som ikke er administratorer for grupper, projekter og udklip. Hvis det offentlige niveau er begrænset, så er brugerprofiler kun synlige for brugere som er logget ind."
-msgid "Selected projects"
-msgstr "Valgte projekter"
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr "Session-id"
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Indstil en adgangskode på din konto for at bruge pull eller push via %{protocol}."
-msgid "Set access permissions for this token."
-msgstr "Indstil adgangstilladelser for tokenen."
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr "Viser seneste version"
msgid "Showing version #%{versionNumber}"
msgstr "Viser version #%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr "Antal indlogninger:"
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr "Indlogningsside"
@@ -36096,6 +36518,9 @@ msgstr "Begrænsninger for indlogning"
msgid "Sign-in text"
msgstr "Indlogningstekst"
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr "URL for udlogningsside"
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr "Løsning"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr "Nogle ændringer vises ikke"
@@ -37449,9 +37871,6 @@ msgstr "Fratrækker"
msgid "Succeeded"
msgstr "Lykkedes"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr "URL for supportside"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr "Systemmålinger (Kubernetes)"
msgid "System output"
msgstr "Systemoutput"
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr "Indholdsfortegnelse"
@@ -37973,6 +38392,9 @@ msgstr "Annuller"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Opret mærkat"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Rediger udgivelsesnoter"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Eksisterende grennavn, mærkat eller commit-SHA"
@@ -38090,9 +38512,6 @@ msgstr "Opgave-id: %{elastic_task}"
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr "Tekststil"
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr "Tak for din feedback!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Tak for din rapport. En GitLab-administrator vil undersøge det om kort tid."
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ msgstr "Depotet skal kunne tilgås over %{code_open}http://%{code_close}, %{code
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 ""
@@ -39068,6 +39484,9 @@ msgstr "Der er ingen arkiverede krav"
msgid "There are no archived test cases"
msgstr "Der er ingen arkiverede testsager"
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr "Der er ingen ændringer"
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr "Der var problemer med at sende bekræftelses e-mailen"
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr "Der opstod en fejl ved tilføjelse af et gøremål."
@@ -39323,9 +39742,6 @@ msgstr "Der opstod en fejl ved fortolkning af dataene til grafen."
msgid "There was an error removing the e-mail."
msgstr "Der opstod en fejl ved fjernelse af e-mailen."
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "Der opstod en fejl med reCAPTCHA'en. Løs venligst reCAPTCHA'en igen."
@@ -39560,6 +39973,9 @@ msgstr "Mappen"
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 ""
@@ -39917,6 +40333,12 @@ msgstr "Projektet vil blive slettet %{date} eftersom dets forældergruppe '%{par
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Depotet"
@@ -40229,6 +40651,9 @@ 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 "Timeout"
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr "Opret en ny sammenlægningsanmodning for at holde projektet i gang"
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr "GÃ¥ tilbage"
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Type"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "U2F-enheder (%{length})"
@@ -41133,6 +41564,9 @@ msgstr "Kan ikke indlæse diff'en. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
+msgid "Unable to parse JSON"
+msgstr ""
+
msgid "Unable to parse the vulnerability report's options."
msgstr ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr "Ukendt format"
msgid "Unknown response text"
msgstr "Ukendt svartekst"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr "Ukendt bruger"
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr "Opdaterer"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr "Opdaterer …"
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Upload fil"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr "Upstream"
-msgid "Uptime"
-msgstr "Oppetid"
-
msgid "Upvotes"
msgstr "Opstemmer"
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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."
@@ -41655,6 +42089,18 @@ msgstr "Lagertype"
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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ msgstr ""
msgid "Used"
msgstr "Brugt"
+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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "Brugeren blev fjernet fra projektet."
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr "Botaktivitet"
msgid "UserProfile|Contributed projects"
msgstr "Projekter med bidrag"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "Rediger profil"
@@ -42207,6 +42664,9 @@ msgstr "Brugeren følger ikke andre brugere."
msgid "UserProfile|Unconfirmed user"
msgstr "Ubekræftet bruger"
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Vis alle"
@@ -42372,11 +42832,6 @@ msgstr "Vi har ikke nok data til at vise stadiet."
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr "%{stageCount}+ elementer"
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr "Antal nye problemstillinger oprettet."
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -42524,6 +42985,12 @@ msgstr ""
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 ""
+
+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 "Version %{versionNumber}"
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 "Vi sendte dig en e-mail med instruktioner til at nulstille adgangskoden"
@@ -43490,6 +43960,12 @@ 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 "Hvad gør kommandoen?"
@@ -43549,6 +44025,11 @@ msgstr "NÃ¥r protokollerne %{code_open}http://%{code_close} eller %{code_open}ht
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 "NÃ¥r:"
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr "Opret %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Opret side"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr "Format"
@@ -43816,10 +44297,13 @@ msgstr "Igangværende arbejde (åbne og tildelte)"
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr "Vil du oprette en ny gren?"
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Du kan invitere et nyt medlem til %{project_name} eller invitere en anden gruppe."
@@ -44186,9 +44714,6 @@ msgstr "Du kan invitere et nyt medlem til %{project_name} eller invitere en ande
msgid "You can invite a new member to %{project_name}."
msgstr "Du kan invitere et nyt medlem til %{project_name}."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "Du kan invitere et nyt medlem til %{strong_start}%{group_name}%{strong_end}."
-
msgid "You can invite another group to %{project_name}."
msgstr "Du kan invitere en anden gruppe til %{project_name}."
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr "Du kan ikke tilgå den rå fil. Vent venligst et øjeblik."
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr "Du kan ikke efterligne en blokeret bruger"
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "Du kunne ikke oprette en ny udløser."
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr "Du har afvist %{user}"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr "Din fil skal indeholde en kolonne ved navn %{codeStart}title%{codeEnd}.
msgid "Your first project"
msgstr "Dit første projekt"
+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 "Dine grupper"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr "Din søgning matchede ikke nogen commits."
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] "Dit abonnement vil udløbe om %{remaining_days} dag."
-msgstr[1] "Dit abonnement vil udløbe om %{remaining_days} dage."
+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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr "tildel dig selv"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr "kl."
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr "API-fuzzing"
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Alle projekter"
@@ -45578,6 +46116,9 @@ msgstr "indlæser"
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr "lukket"
@@ -45605,6 +46146,9 @@ msgstr "committed"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr "oprettet af"
msgid "data"
msgstr "data"
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr "datoen må ikke være efter 9999-12-31"
@@ -45741,6 +46282,9 @@ msgstr "%{slash_command} overskriver den samlede estimerede tid."
msgid "example.com"
msgstr "example.com"
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr "gruppemedlemmer"
-msgid "group's CI/CD settings."
-msgstr "gruppens CI-/CD-indstillinger."
-
msgid "groups"
msgstr "grupper"
@@ -45876,6 +46417,9 @@ msgstr "https://din-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr "%{language} (%{percent_translated} %% oversat)"
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr "indlæser"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "låst af %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "manuelt"
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 sammenlægningscommit"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr "Opret problemstilling for at løse alle tråde"
msgid "mrWidget|Delete source branch"
msgstr "Slet kildegren"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Udsendelsesstatistik er ikke tilgængelig i øjeblikket"
@@ -46229,9 +46767,6 @@ msgstr "Lukkede ikke"
msgid "mrWidget|Dismiss"
msgstr "Afskedig"
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Kunne ikke indlæse udsendelsesstatistik"
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] "Nævner problemstilling"
msgstr[1] "Nævner problemstillinger"
-msgid "mrWidget|Merge"
-msgstr "Sammenlæg"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Sammenlagt af"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "Sammenlægger! Ændringer er ved at blive sendt afsted …"
@@ -46390,21 +46919,9 @@ msgstr "Vis %{widget}-detaljer"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Ændringerne blev sammenlagt i"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Ændringerne blev ikke sammenlagt i"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Kildegrenen er blevet slettet"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "Kildegrenen er %{link} målgrenen"
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Kildegrenen er ved at blive slettet"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Sammenlægningsanmodningen kunne ikke sammenlægges automatisk"
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr "depot:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr "opfyldt"
@@ -46733,6 +47253,9 @@ msgstr ""
msgid "security Reports|There was an error creating the merge request"
msgstr "Der opstod en fejl ved oprettelse af sammenlægningsanmodningen"
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr ""
+
msgid "severity|Blocker"
msgstr ""
@@ -46844,14 +47367,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "følgende problemstillinger"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr "wikien"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "sammenfold til/fra"
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "udløst"
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 9fb864b9dee..1bdf999e7f5 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-07-14 19:57\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -250,8 +250,8 @@ msgstr[1] "%d Dateien"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d korrigiertes Testergebnis"
+msgstr[1] "%d korrigierte Testergebnisse"
msgid "%d fork"
msgid_plural "%d forks"
@@ -460,6 +460,9 @@ msgstr "%{actionText} & wieder öffnen %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} ist ein ungültiger IP-Adressbereich"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} muss zwischen %{min} und %{max} liegen"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} hat %{original_issue} zu %{new_issue} geklont."
@@ -473,7 +476,7 @@ msgid "%{authorsName}'s thread"
msgstr "%{authorsName}s Unterhaltung"
msgid "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
-msgstr ""
+msgstr "%{author} hat %{created_at} angefordert, %{source_branch} %{copy_button} in %{target_branch} zusammenzuführen"
msgid "%{board_target} not found"
msgstr "%{board_target} nicht gefunden"
@@ -508,16 +511,16 @@ msgstr "%{commit_author_link} verfasste %{commit_authored_timeago} und %{commit_
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} fertige Gewichtung"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} von %{count} Aufgaben erledigt"
-msgstr[1] "%{completedCount} von %{count} Aufgaben erledigt"
+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 "%{completedWeight} von %{totalWeight} Gewichtung abgeschlossen"
msgid "%{completed} of %{total} issues closed"
-msgstr "%{completed} von %{total} Problemen geschlossen"
+msgstr ""
msgid "%{completed} of %{total} weight completed"
msgstr ""
@@ -691,9 +694,12 @@ msgstr "%{integrations_link_start}Integrationen%{link_end} ermöglichen es dir,
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wird entfernt! Bist du sicher?"
-msgid "%{issuable}(s) already assigned"
+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 "%{issuable}(s) bereits zugewiesen"
+
msgid "%{issueType} actions"
msgstr "%{issueType}-Aktionen"
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Methode:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Namensraum:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Scanner:%{labelEnd} %{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Schweregrad:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Tool:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Unveränderte Antwort:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} nicht verfügbar"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 Stunde"
@@ -806,13 +815,13 @@ msgid "%{milliseconds}ms"
msgstr "%{milliseconds}ms"
msgid "%{minutesUsed} minutes"
-msgstr ""
+msgstr "%{minutesUsed} Minuten"
msgid "%{model_name} not found"
msgstr "%{model_name} nicht gefunden"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr "%{mrText}, dieses Problem wird automatisch geschlossen werden."
+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 "%{name_with_link} Namespace hat %{percent} oder weniger Pipeline-Minuten auf geteilten Runnern übrig. Sind diese abgelaufen, werden keine Jobs oder Pipelines mehr in den Projekten ausgeführt."
@@ -833,7 +842,7 @@ msgid "%{name} is already being used for another emoji"
msgstr "%{name} wird bereits für ein anderes Emoji verwendet"
msgid "%{name} is reserved for %{type} report type"
-msgstr ""
+msgstr "%{name} ist für %{type} Berichtstyp reserviert"
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} ist geplant für %{action}"
@@ -876,11 +885,23 @@ msgstr "%{openedEpics} offen, %{closedEpics} geschlossen"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} offen, %{closedIssues} geschlossen"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
msgid "%{percentage}%% issues closed"
-msgstr "%{percentage}%% Probleme geschlossen"
+msgstr ""
msgid "%{percentage}%% weight completed"
msgstr "%{percentage}%% Gewichtung abgeschlossen"
@@ -901,7 +922,7 @@ msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})
msgstr ""
msgid "%{project_name}"
-msgstr ""
+msgstr "%{project_name}"
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 ""
@@ -936,7 +957,7 @@ msgid "%{rotation} has been recalculated with the remaining participants. Please
msgstr "%{rotation} wurde mit den verbliebenen Beteiligten neu errechnet. Bitte die neue Einrichtung für %{rotation} überprüfen. Wir empfehlen, sich mit den aktuellen Bereitschaftsverantwortlichen in Verbindung zu setzen, um eine kontinuierliche Anrufbereitschaft sicherzustellen."
msgid "%{runner} created %{timeago}"
-msgstr ""
+msgstr "%{runner} erstellt %{timeago}"
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} Ergebnisse für Suchwort '%{term}'"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "Kein Ergebnis aus %{securityScanner} verfügbar, da keine Pipeline seit der Aktivierung ausgeführt wurde. %{linkStart}Eine Pipeline ausführen%{linkEnd}"
msgstr[1] "%{securityScanner}-Ergebnisse sind nicht verfügbar, da keine Pipeline seit der Aktivierung ausgeführt wurde. %{linkStart}Eine Pipeline ausführen%{linkEnd}"
+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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ 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."
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr "%{strongStart}Tipp:%{strongEnd} Du kannst Merge Requests auch lokal auschecken. %{linkStart}Mehr erfahren. %{linkEnd}"
@@ -1010,8 +1038,8 @@ 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}Genehmigungsregel%{strong_end} erfordert vor dem Zusammenführen die Genehmigung von berechtigten Mitgliedern."
+msgstr[1] "%{strong_start}%{count}Genehmigungsregeln%{strong_end} erfordern vor Zusammenführung, die Genehmigung von berechtigten Mitgliedern."
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."
@@ -1020,8 +1048,8 @@ 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] ""
+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}%{human_size}%{strong_end} Project Storage"
msgstr ""
@@ -1321,7 +1349,7 @@ msgid "- Not available to run jobs."
msgstr ""
msgid "- Push code to the repository."
-msgstr ""
+msgstr "- Code in das Repository pushen"
msgid "- Select -"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Registriert am"
-msgid "3 days"
-msgstr "3 Tage"
-
msgid "3 hours"
msgstr "3 Stunden"
-msgid "30 days"
-msgstr "30 Tage"
-
msgid "30 minutes"
msgstr "30 Minuten"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 Tage"
-
msgid "8 hours"
msgstr "8 Stunden"
@@ -1590,7 +1609,7 @@ msgid "A deleted user"
msgstr "Ein(e) gelöschte(r) Benutzer(in)"
msgid "A different reason"
-msgstr ""
+msgstr "Ein anderer Grund"
msgid "A file has been changed."
msgstr "Eine Datei wurde geändert."
@@ -1710,7 +1729,7 @@ msgid "API key"
msgstr ""
msgid "API?"
-msgstr ""
+msgstr "API?"
msgid "APIFuzzing|$VARIABLE_WITH_PASSWORD"
msgstr ""
@@ -1767,7 +1786,7 @@ msgid "APIFuzzing|Predefined profiles"
msgstr ""
msgid "APIFuzzing|Scan mode"
-msgstr ""
+msgstr "Scanmodus"
msgid "APIFuzzing|Scan profile"
msgstr ""
@@ -1776,7 +1795,7 @@ msgid "APIFuzzing|Show code snippet for the profile"
msgstr ""
msgid "APIFuzzing|Target URL"
-msgstr ""
+msgstr "Ziel-URL"
msgid "APIFuzzing|There are three ways to perform scans."
msgstr ""
@@ -1818,10 +1837,10 @@ msgid "AWS Secret Access Key"
msgstr "AWS Geheimer Zugangsschlüssel"
msgid "AWS access key ID (Optional)"
-msgstr ""
+msgstr "AWS-Zugriffsschlüssel-ID (optional)"
msgid "AWS secret access key (Optional)"
-msgstr ""
+msgstr "Geheimer AWS-Zugriffsschlüssel (optional)"
msgid "AWS service error: %{error}"
msgstr "AWS-Servicefehler: %{error}"
@@ -1839,7 +1858,7 @@ msgid "About this feature"
msgstr "Ãœber dieses Feature"
msgid "About your company"
-msgstr ""
+msgstr "Ãœber dein Unternehmen"
msgid "Abuse Reports"
msgstr "Missbrauchsmeldungen"
@@ -1863,7 +1882,7 @@ msgid "Access Git repositories or the API."
msgstr ""
msgid "Access Token"
-msgstr ""
+msgstr "Zugangstoken"
msgid "Access Tokens"
msgstr "Zugangs-Token"
@@ -1875,7 +1894,7 @@ msgid "Access denied: %{error}"
msgstr "Zugriff verweigert: %{error}"
msgid "Access expires"
-msgstr ""
+msgstr "Zugriff läuft ab"
msgid "Access forbidden. Check your access level."
msgstr "Zugriff verboten. Überprüfe deine Zugriffsebene."
@@ -1971,7 +1990,7 @@ msgid "AccessTokens|Your static object token authenticates you when repository s
msgstr ""
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "Mehr erfahren"
msgid "AccessibilityReport|Message: %{message}"
msgstr "Nachricht: %{message}"
@@ -1998,7 +2017,7 @@ msgid "Account and limit"
msgstr "Konto und Limit"
msgid "Account:"
-msgstr ""
+msgstr "Account:"
msgid "Account: %{account}"
msgstr "Konto: %{account}"
@@ -2028,7 +2047,7 @@ msgid "Acknowledge"
msgstr ""
msgid "Action"
-msgstr ""
+msgstr "Aktion"
msgid "Action to take when receiving an alert. %{docsLink}"
msgstr ""
@@ -2085,10 +2104,10 @@ msgid "Add LICENSE"
msgstr "LIZENZ hinzufügen"
msgid "Add License"
-msgstr ""
+msgstr "Lizenz hinzufügen"
msgid "Add New Site"
-msgstr ""
+msgstr "Neue Seite hinzufügen"
msgid "Add README"
msgstr "README hinzufügen"
@@ -2097,10 +2116,10 @@ msgid "Add Zoom meeting"
msgstr "Zoom-Besprechung hinzufügen"
msgid "Add a %{type}"
-msgstr ""
+msgstr "%{type} hinzufügen"
msgid "Add a GCP region"
-msgstr ""
+msgstr "Eine GCP-Region hinzufügen"
msgid "Add a GPG key"
msgstr "GPG-Schlüssel hinzufügen"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Aufzählungsliste hinzufügen"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Einen zusammenklappbaren Abschnitt hinzufügen"
@@ -2136,16 +2158,16 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "Füge zu deinem Wiki eine Startseite mit Informationen zu deinem GitLab-Project hinzu und GitLab wird sie hier anstatt dieser Meldung anzeigen."
msgid "Add a new issue"
-msgstr ""
+msgstr "Neues Ticket hinzufügen"
msgid "Add a numbered list"
msgstr "Eine nummerierte Liste hinzufügen"
msgid "Add a related epic"
-msgstr ""
+msgstr "Verwandtes Epic hinzufügen"
msgid "Add a related issue"
-msgstr ""
+msgstr "Verwandtes Problem hinzufügen"
msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Tabelle hinzufügen"
-msgid "Add a task list"
-msgstr "Eine Aufgabenliste hinzufügen"
-
msgid "Add a title..."
msgstr ""
@@ -2181,10 +2200,7 @@ msgid "Add approval rule"
msgstr "Füge Zustimmungsregel hinzu"
msgid "Add approvers"
-msgstr ""
-
-msgid "Add attention request"
-msgstr ""
+msgstr "Genehmigungsberechtigte hinzufügen"
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ msgstr "Umgebung hinzufügen"
msgid "Add existing confidential %{issuableType}"
msgstr "Bestehende vertrauliche %{issuableType} hinzufügen"
+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 "Kopf- und Fußzeile zu E-Mails hinzufügen. Bitte beachte, dass Farbeinstellungen nur innerhalb des Anwendungs-Interfaces angewendet werden"
@@ -2370,7 +2389,7 @@ msgid "Added %{label_references} %{label_text}."
msgstr "%{label_references} %{label_text} hinzugefügt."
msgid "Added a to do."
-msgstr ""
+msgstr "Aufgabe hinzugefügt."
msgid "Added an issue to an epic."
msgstr "Ein Ticket zu einem Epic hinzugefügt."
@@ -2403,7 +2422,7 @@ msgid "Additional text to show on the sign-in page"
msgstr ""
msgid "Address"
-msgstr ""
+msgstr "Adresse"
msgid "Adds"
msgstr "Fügt hinzu"
@@ -2442,19 +2461,19 @@ msgid "Admin Area"
msgstr "Adminbereich"
msgid "Admin Mode"
-msgstr ""
+msgstr "Administrator-Modus"
msgid "Admin Note"
msgstr ""
msgid "Admin Notifications"
-msgstr ""
+msgstr "Admin-Benachrichtigungen"
msgid "Admin Overview"
msgstr "Admin-Ãœbersicht"
msgid "Admin Section"
-msgstr ""
+msgstr "Admin-Bereich"
msgid "Admin mode already enabled"
msgstr "Adminmodus bereits aktiviert"
@@ -2487,7 +2506,7 @@ msgid "AdminArea|Blocked users"
msgstr ""
msgid "AdminArea|Bots"
-msgstr ""
+msgstr "Bots"
msgid "AdminArea|Components"
msgstr ""
@@ -2505,7 +2524,7 @@ msgid "AdminArea|Groups"
msgstr ""
msgid "AdminArea|Guest"
-msgstr ""
+msgstr "Gast"
msgid "AdminArea|Included Free in license"
msgstr ""
@@ -2532,7 +2551,7 @@ msgid "AdminArea|Minimal access"
msgstr ""
msgid "AdminArea|New group"
-msgstr ""
+msgstr "Neue Gruppe"
msgid "AdminArea|New project"
msgstr ""
@@ -2550,7 +2569,7 @@ msgid "AdminArea|Projects"
msgstr ""
msgid "AdminArea|Reporter"
-msgstr "AdminArea|Reporter"
+msgstr "Reporter"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
msgstr ""
@@ -2634,7 +2653,7 @@ msgid "AdminSettings|Auto DevOps domain"
msgstr "Auto-DevOps-Domain"
msgid "AdminSettings|Automatically ban users who download more than a specified number of repositories in a given time."
-msgstr "AdminSettings|Automatisches Sperren von Benutzern, die mehr als eine festgelegte Anzahl von Repositories in einem bestimmten Zeitraum herunterladen."
+msgstr "Automatisches Sperren von Benutzern, die mehr als eine festgelegte Anzahl von Repositories in einem bestimmten Zeitraum herunterladen."
msgid "AdminSettings|CI/CD limits"
msgstr ""
@@ -2916,10 +2935,10 @@ msgid "AdminUsers|(Banned)"
msgstr ""
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(Blockiert)"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "(Deaktiviert)"
msgid "AdminUsers|(Internal)"
msgstr ""
@@ -2928,7 +2947,7 @@ msgid "AdminUsers|(Locked)"
msgstr ""
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "(Ausstehende Genehmigung)"
msgid "AdminUsers|2FA Disabled"
msgstr "2FA deaktiviert"
@@ -2937,22 +2956,22 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA aktiviert"
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 "AdminUsers|Ein Benutzer kann sich selbst validieren, indem er eine Kredit-/Debitkarte eingibt, oder ein Administrator kann einen Benutzer manuell validieren. Validierte Benutzer können kostenlose CI-Minuten für gemeinsam genutzte Läufer verwenden."
+msgstr "Ein Benutzer kann sich selbst validieren, indem er eine Kredit-/Debitkarte eingibt, oder ein Administrator kann einen Benutzer manuell validieren. Validierte Benutzer können kostenlose CI-Minuten für gemeinsam genutzte Läufer verwenden."
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "Zugriff"
msgid "AdminUsers|Access Git repositories"
msgstr ""
msgid "AdminUsers|Access level"
-msgstr "AdminUsers|Zugriffslevel"
+msgstr "Zugriffslevel"
msgid "AdminUsers|Access the API"
msgstr ""
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "Aktivieren"
msgid "AdminUsers|Activate user %{username}?"
msgstr ""
@@ -2991,7 +3010,7 @@ msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
msgid "AdminUsers|Avatar"
-msgstr "AdminUsers|Avatar"
+msgstr "Avatar"
msgid "AdminUsers|Ban user"
msgstr ""
@@ -3021,7 +3040,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Benutzer(in) zu blockieren hat folgende Auswirkungen:"
msgid "AdminUsers|Can create group"
-msgstr "AdminUsers|Kann Gruppe erstellen"
+msgstr "Kann Gruppe erstellen"
msgid "AdminUsers|Cannot sign in or access instance information"
msgstr ""
@@ -3066,7 +3085,7 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "Benutzer(in) und Beiträge löschen"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "Berechtigungen als CSV exportieren (max. 100.000 Benutzer)"
msgid "AdminUsers|External"
msgstr "Extern"
@@ -3099,10 +3118,10 @@ msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
msgid "AdminUsers|Limits"
-msgstr "AdminBenutzer|Grenzen"
+msgstr "Grenzen"
msgid "AdminUsers|Linkedin"
-msgstr "AdminUsers|Linkedin"
+msgstr "Linkedin"
msgid "AdminUsers|Locked"
msgstr ""
@@ -3132,7 +3151,7 @@ msgid "AdminUsers|Personal projects, group and user history will be left intact"
msgstr "Persönliche Projekte, Gruppen- und Benutzerhistorie werden intakt gelassen"
msgid "AdminUsers|Quota of CI/CD minutes"
-msgstr "AdminUsers|Quote der CI/CD-Minuten"
+msgstr "Quote der CI/CD-Minuten"
msgid "AdminUsers|Reactivating a user will:"
msgstr "Benutzer(in) zu reaktivieren, wird:"
@@ -3153,7 +3172,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 "AdminUsers|Reset-Link wird generiert und an den Benutzer gesendet. Der Benutzer wird gezwungen, das Passwort bei der ersten Anmeldung festzulegen."
+msgstr "Reset-Link wird generiert und an den Benutzer gesendet. Der Benutzer wird gezwungen, das Passwort bei der ersten Anmeldung festzulegen."
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr "Zugriff auf das Konto wiederherstellen, einschließlich Web, Git und API."
@@ -3168,13 +3187,13 @@ msgid "AdminUsers|Send email to users"
msgstr "E-Mail an Benutzer(innen) senden"
msgid "AdminUsers|Skype"
-msgstr "AdminUsers|Skype"
+msgstr "Skype"
msgid "AdminUsers|Sort by"
msgstr "Sortiert nach"
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 "AdminUsers|Die maximale Anzahl von CI/CD-Minuten auf gemeinsam genutzten Läufern, die eine Gruppe jeden Monat verwenden kann. 0 für unbegrenzt setzen. Leer setzen, um die globale Einstellung von %{minutes} zu übernehmen"
+msgstr "Die maximale Anzahl von CI/CD-Minuten auf gemeinsam genutzten Läufern, die eine Gruppe jeden Monat verwenden kann. 0 für unbegrenzt setzen. Leer setzen, um die globale Einstellung von %{minutes} zu übernehmen"
msgid "AdminUsers|The user can't access git repositories."
msgstr ""
@@ -3243,7 +3262,7 @@ msgid "AdminUsers|View pending member requests"
msgstr ""
msgid "AdminUsers|Website URL"
-msgstr "AdminUsers|Website-URL"
+msgstr "Website-URL"
msgid "AdminUsers|What can I do?"
msgstr "Was kann ich tun?"
@@ -3402,7 +3421,7 @@ msgid "AlertManagement|Alert"
msgstr "Alarm"
msgid "AlertManagement|Alert assignee(s): %{assignees}"
-msgstr "AlertManagement|Alarm-Beauftragte(r): %{assignees}"
+msgstr "Alarm-Beauftragte(r): %{assignees}"
msgid "AlertManagement|Alert detail"
msgstr "Alarm-Details"
@@ -3755,6 +3774,9 @@ msgstr "Alle Branches"
msgid "All changes are committed"
msgstr "Alle Änderungen sind committed"
+msgid "All eligible users"
+msgstr "Alle berechtigten Benutzer"
+
msgid "All email addresses will be used to identify your commits."
msgstr "Alle E-Mail-Adressen werden verwendet, um deine Commits zu identifizieren."
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr "Beim Abrufen von Branches ist ein Fehler aufgetreten."
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ msgstr "Beim Abrufen der Projekt-Autovervollständigung ist ein Fehler aufgetret
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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4511,7 +4530,7 @@ msgid "ApplicationSettings|A Metrics Dashboard menu item appears in the Monitori
msgstr ""
msgid "ApplicationSettings|Add a link to Grafana"
-msgstr "ApplicationSettings|Link zu Grafana hinzufügen"
+msgstr "Link zu Grafana hinzufügen"
msgid "ApplicationSettings|After sign-up text"
msgstr ""
@@ -4586,14 +4605,26 @@ msgstr ""
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr ""
+msgid "ApplicationSettings|Require lowercase letters"
+msgstr "Kleinbuchstaben erforderlich"
+
+msgid "ApplicationSettings|Require numbers"
+msgstr "Zahlen erforderlich"
+
+msgid "ApplicationSettings|Require symbols"
+msgstr "Symbole erforderlich"
+
+msgid "ApplicationSettings|Require uppercase letters"
+msgstr "Großbuchstaben erforderlich"
+
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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr ""
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr "Siehe %{linkStart}Passwortrichtlinien%{linkEnd}."
msgid "ApplicationSettings|Send confirmation email on sign-up"
msgstr ""
@@ -4619,6 +4650,18 @@ 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 "Wenn aktiviert, müssen neue Passwörter mindestens einen Kleinbuchstaben (a-z) enthalten."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
+msgstr "Wenn aktiviert, müssen neue Passwörter mindestens eine Zahl (0-9) enthalten."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one symbol."
+msgstr "Wenn aktiviert, müssen neue Passwörter mindestens ein Symbol enthalten."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one uppercase letter (A-Z)."
+msgstr "Wenn aktiviert, müssen neue Passwörter mindestens einen Großbuchstaben (A-Z) enthalten."
+
msgid "ApplicationSettings|domain.com"
msgstr ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
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 "Bearbeiten von Genehmigungsregeln in Projekten und Zusammenführen von Anfragen verhindern"
+
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4828,13 +4877,10 @@ msgid "Approved the current merge request."
msgstr "Der aktuelle Merge-Request wurde genehmigt."
msgid "Approved-By"
-msgstr ""
-
-msgid "Approved. Your attention request was removed."
-msgstr ""
+msgstr "Genehmigt von"
msgid "Approver"
-msgstr ""
+msgstr "Genehmiger"
msgid "Approvers"
msgstr ""
@@ -5004,7 +5050,7 @@ 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 "Möchtest du den Zugriffstoken für die Fehlerverfolgung wirklich zurücksetzen?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Bist du sicher, dass du den Health-Check-Token zurücksetzen willst?"
@@ -5091,7 +5137,7 @@ msgid "Ask again later"
msgstr ""
msgid "Ask someone with write access to resolve it."
-msgstr "Bitte jemanden mit Schreibzugriff, das Problem zu beheben."
+msgstr ""
msgid "Ask your group owner to set up a group runner."
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr "Mir zugewiesen"
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Beauftragte(r)"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
-msgstr "Datei anhängen"
+msgid "Attach a file or image"
+msgstr "Datei oder Bild anhängen"
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5232,12 +5275,6 @@ msgstr[1] "%d Dateien anhängen"
msgid "Attaching the file failed."
msgstr "Die Datei konnte nicht angehängt werden."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Audit-Ereignisse"
@@ -5298,6 +5335,12 @@ msgstr ""
msgid "AuditStreams|Active"
msgstr ""
+msgid "AuditStreams|Add a custom header"
+msgstr "Benutzerdefinierte Kopfzeile hinzufügen"
+
+msgid "AuditStreams|Add a custom value"
+msgstr "Benutzerdefinierten Wert hinzufügen"
+
msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party systems."
msgstr ""
@@ -5316,6 +5359,9 @@ 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 "Beim Aktualisieren des Ziels des externen Audit-Ereignisstreams ist ein Fehler aufgetreten. Bitte erneut versuchen."
+
msgid "AuditStreams|Cancel editing"
msgstr ""
@@ -5331,18 +5377,33 @@ msgstr ""
msgid "AuditStreams|Destinations receive all audit event data"
msgstr ""
+msgid "AuditStreams|Edit %{link}"
+msgstr "%{link} bearbeiten"
+
msgid "AuditStreams|Header"
msgstr ""
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
msgstr ""
+msgid "AuditStreams|Save external stream destination"
+msgstr "Externes Stream-Ziel speichern"
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr "Stream erfolgreich hinzugefügt"
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr "Stream erfolgreich gelöscht"
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr "Stream erfolgreich aktualisiert"
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr "Bestätigungstoken"
+
msgid "Aug"
msgstr "Aug"
@@ -5571,8 +5635,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Automatisch aufgelöst"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Aktualisiere die Branches und Tags des Projektes stündlich aus dem Upstream Repository."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Notiz"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr "Gesperrt"
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr ""
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "Ab dem 19. Oktober 2022 sind kostenlose Gruppen auf 5 Mitglieder begrenzt"
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,14 +6318,11 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr "Billing|Du kannst jetzt damit beginnen, Mitglieder in %{namespaceName} zu verschieben. Ein Mitglied verliert den Zugriff auf die Gruppe, wenn du %{strongStart}In a seat%{strongEnd} deaktivierst. Wenn nach dem 22. Juni 2022 mehr als 5 Mitglieder %{strongStart}In a seat%{strongEnd} aktiviert haben, wählen wir die 5 Mitglieder aus, die weiterhin Zugriff haben. Wir zählen zuerst Mitglieder mit Eigentümer- und Betreuerrollen, dann die zuletzt aktiven Mitglieder, bis wir 5 Mitglieder erreicht haben. Die verbleibenden Mitglieder erhalten den Status Limit überschritten und verlieren den Zugriff auf die Gruppe."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgstr "Du kannst jetzt damit beginnen, Mitglieder in %{namespaceName} zu verschieben. Ein Mitglied verliert den Zugriff auf die Gruppe, wenn du %{strongStart}In a seat%{strongEnd} deaktivierst. Wenn nach dem 19. Oktober 2022 mehr als 5 Mitglieder %{strongStart}In a seat%{strongEnd} aktiviert haben, wählen wir die 5 Mitglieder aus, die weiterhin Zugriff haben. Wir zählen zuerst Mitglieder mit Eigentümer- und Betreuerrollen, dann die zuletzt aktiven Mitglieder, bis wir 5 Mitglieder erreicht haben. Die verbleibenden Mitglieder erhalten den Status Limit überschritten und verlieren den Zugriff auf die Gruppe."
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr "Billing|Deine kostenlose Gruppe ist jetzt auf %{free_user_limit} Mitglieder beschränkt"
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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 "Billing|Deine Gruppe hat kürzlich auf den kostenlosen Plan umgestellt. Kostenlose Gruppen sind auf %{free_user_limit} Mitglieder beschränkt und die verbleibenden Mitglieder erhalten den Status „Überschreitung“ und verlieren den Zugriff auf die Gruppe. Du kannst Speicherplatz für neue Mitglieder freigeben, indem du diejenigen entfernst, die keinen Zugriff mehr benötigen, oder sie auf Überlimit umschalten. Um eine unbegrenzte Anzahl von Mitgliedern zu erhalten, kannst du ein %{link_start}Upgrade%{link_end} auf eine kostenpflichtige Stufe durchführen."
+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 "Bitbucket-Server-Import"
@@ -6303,31 +6372,31 @@ msgid "Board scope affects which issues are displayed for anyone who visits this
msgstr "Der Board-Bereich beeinflusst, welche Themen für jeden angezeigt werden, der dieses Board besucht"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "Gruppen"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Gruppen laden"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Keine zutreffenden Ergebnisse"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "Gruppen suchen"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "Gruppe auswählen"
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "Keine zutreffenden Ergebnisse"
msgid "BoardNewIssue|Projects"
-msgstr ""
+msgstr "Projekte"
msgid "BoardNewIssue|Search projects"
-msgstr ""
+msgstr "Projekte durchsuchen"
msgid "BoardNewIssue|Select a project"
-msgstr ""
+msgstr "Projekt auswählen"
msgid "BoardScope|%{iterationTitle} iteration in %{iterationCadence}"
msgstr ""
@@ -6351,7 +6420,7 @@ msgid "BoardScope|Any assignee"
msgstr ""
msgid "BoardScope|Any iteration"
-msgstr "BoardScope|Beliebige Iteration"
+msgstr "Beliebige Iteration"
msgid "BoardScope|Any label"
msgstr ""
@@ -6366,7 +6435,7 @@ msgid "BoardScope|Current iteration"
msgstr ""
msgid "BoardScope|Don't filter milestone"
-msgstr "BoardScope|Meilenstein nicht filtern"
+msgstr "Meilenstein nicht filtern"
msgid "BoardScope|Edit"
msgstr ""
@@ -6378,7 +6447,7 @@ msgid "BoardScope|Labels"
msgstr ""
msgid "BoardScope|Milestone"
-msgstr "BoardScope|Meilenstein"
+msgstr "Meilenstein"
msgid "BoardScope|No iteration"
msgstr ""
@@ -6496,7 +6565,7 @@ msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
msgid "Boards|New board"
-msgstr ""
+msgstr "Neues Board"
msgid "Boards|New epic"
msgstr ""
@@ -6523,7 +6592,7 @@ msgid "Board|Create board"
msgstr ""
msgid "Board|Create new board"
-msgstr ""
+msgstr "Neues Board erstellen"
msgid "Board|Delete board"
msgstr ""
@@ -6585,9 +6654,51 @@ msgstr "Branch nicht geladen - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branches"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Aktiv"
@@ -6634,7 +6745,7 @@ msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
msgstr "Löschen der zusammengeführten Branches kann nicht rückgängig gemacht werden. Bist du sicher?"
msgid "Branches|Filter by branch name"
-msgstr "Filtern nach dem Branch-Namen"
+msgstr "Nach Zweignamen filtern"
msgid "Branches|Merged into %{default_branch}"
msgstr "In %{default_branch} zusammengeführt"
@@ -6709,7 +6820,7 @@ msgid "Branches|diverged from upstream"
msgstr "weicht vom Upstream ab"
msgid "Branches|merged"
-msgstr "merged"
+msgstr "zusammengeführt"
msgid "Branches|protected"
msgstr "geschützt"
@@ -6832,7 +6943,7 @@ msgid "BulkImport|Project import history"
msgstr ""
msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
-msgstr ""
+msgstr "Beim erneuten Importieren wird eine neue Gruppe erstellt. Es wird nicht mit der bestehenden Gruppe synchronisiert."
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -6895,7 +7006,7 @@ msgid "Business metrics (Custom)"
msgstr "Business-Metriken (benutzerdefiniert)"
msgid "Busy"
-msgstr ""
+msgstr "Beschäftigt"
msgid "Buy CI Minutes"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
msgid "Can't find variable: ZiteReader"
msgstr "Kann Variable nicht finden: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7389,7 +7497,7 @@ msgid "Change Failure Rate"
msgstr ""
msgid "Change assignee"
-msgstr ""
+msgstr "Beauftragte(n) ändern"
msgid "Change assignee(s)"
msgstr "Zuweisung(en) ändern"
@@ -7452,7 +7560,7 @@ msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-Pick"
msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab erstellt einen Branch in deinem Fork und startet eine Merge-Anfrage."
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -7491,7 +7599,7 @@ msgid "Changed"
msgstr ""
msgid "Changed assignee(s)."
-msgstr ""
+msgstr "Beauftragte(n) geändert."
msgid "Changed merge method to %{merge_method}"
msgstr ""
@@ -7720,7 +7828,7 @@ msgid "Checkout|Country"
msgstr ""
msgid "Checkout|Create a new group"
-msgstr ""
+msgstr "Neue Gruppe erstellen"
msgid "Checkout|Credit card form failed to load. Please try again."
msgstr ""
@@ -7780,7 +7888,7 @@ msgid "Checkout|Name: %{errors}"
msgstr ""
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
-msgstr ""
+msgstr "Benötigst du weitere Benutzer? Kaufe GitLab für deine %{company}."
msgid "Checkout|Number of users"
msgstr ""
@@ -7837,7 +7945,7 @@ msgid "Checkout|Users"
msgstr ""
msgid "Checkout|You'll create your new group after checkout"
-msgstr ""
+msgstr "Du erstellst deine neue Gruppe nach der Kaufabwicklung"
msgid "Checkout|Your organization"
msgstr ""
@@ -7855,7 +7963,7 @@ msgid "Checkout|a storage subscription"
msgstr ""
msgid "Checkout|company or team"
-msgstr ""
+msgstr "Firma oder Team"
msgid "Checkout|minutes"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr "Untergeordnetes Epic existiert nicht."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8211,13 +8316,13 @@ msgid "Clone with KRB5"
msgstr "Mit KRB5 klonen"
msgid "Clone with SSH"
-msgstr ""
+msgstr "Mit SSH klonen"
msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
msgstr ""
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
-msgstr "CloneIssue|Das Problem kann nicht in das Zielprojekt kopiert werden, da es zur Löschung ansteht."
+msgstr "Das Problem kann nicht in das Zielprojekt kopiert werden, da es zur Löschung ansteht."
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
msgstr ""
@@ -8265,7 +8370,7 @@ msgid "Closed MRs"
msgstr ""
msgid "Closed date"
-msgstr "Geschlossen am"
+msgstr "Schließdatum"
msgid "Closed issues"
msgstr "Geschlossene Tickets"
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr "Konfiguration"
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr "Datenbanken"
+
+msgid "CloudSeed|Deployments"
+msgstr "Bereitstellung"
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ msgstr ""
msgid "CloudSeed|Refs"
msgstr ""
+msgid "CloudSeed|Regions"
+msgstr "Regionen"
+
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
msgstr ""
msgid "CloudSeed|Service"
msgstr ""
+msgid "CloudSeed|Service Account"
+msgstr "Dienstkonto"
+
msgid "CloudSeed|Services"
msgstr ""
@@ -9382,10 +9502,10 @@ msgid "Community forum"
msgstr "Community-Forum"
msgid "Company"
-msgstr ""
+msgstr "Unternehmen"
msgid "Company Name"
-msgstr ""
+msgstr "Unternehmensname"
msgid "Compare"
msgstr "Vergleichen"
@@ -9625,7 +9745,7 @@ msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if
msgstr ""
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "Fehlerverfolgung konfigurieren"
msgid "Configure GitLab"
msgstr ""
@@ -9899,10 +10019,10 @@ msgid "ContainerRegistry|-- tags"
msgstr ""
msgid "ContainerRegistry|Build an image"
-msgstr ""
+msgstr "Builde ein Image"
msgid "ContainerRegistry|CLI Commands"
-msgstr ""
+msgstr "CLI-Befehle"
msgid "ContainerRegistry|Clean up image tags"
msgstr ""
@@ -10055,7 +10175,7 @@ msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at
msgstr ""
msgid "ContainerRegistry|Push an image"
-msgstr ""
+msgstr "Ein Image pushen"
msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
msgstr ""
@@ -10087,7 +10207,7 @@ msgid "ContainerRegistry|Set up cleanup"
msgstr ""
msgid "ContainerRegistry|Show full path"
-msgstr "ContainerRegistry|Vollständigen Pfad anzeigen"
+msgstr "Vollständigen Pfad anzeigen"
msgid "ContainerRegistry|Some tags were not deleted"
msgstr ""
@@ -10120,7 +10240,7 @@ msgid "ContainerRegistry|Something went wrong while updating the cleanup policy.
msgstr ""
msgid "ContainerRegistry|Sorry, your filter produced no results."
-msgstr "ContainerRegistry|Dein Filter hat leider keine Ergebnisse geliefert."
+msgstr "Dein Filter hat leider keine Ergebnisse geliefert."
msgid "ContainerRegistry|Tag successfully marked for deletion."
msgstr ""
@@ -10150,7 +10270,7 @@ msgid "ContainerRegistry|The cleanup will continue within %{time}. %{linkStart}L
msgstr ""
msgid "ContainerRegistry|The filter returned no results"
-msgstr ""
+msgstr "Der Filter hat keine Ergebnisse zurückgegeben"
msgid "ContainerRegistry|The image repository could not be found."
msgstr ""
@@ -10189,7 +10309,7 @@ msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
msgstr ""
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
-msgstr "ContainerRegistry|Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
+msgstr "Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
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 ""
@@ -10207,7 +10327,7 @@ 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 "Du bist dabei, das Repository %{title} zu entfernen. Sobald du bestätigst, wird dieses Repository dauerhaft gelöscht."
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
msgstr ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Erstelle neues Verzeichnis"
@@ -10723,7 +10837,7 @@ msgid "Create commit"
msgstr "Commit erstellen"
msgid "Create commit..."
-msgstr ""
+msgstr "Commit erstellen..."
msgid "Create common files more quickly, and standardize their format."
msgstr ""
@@ -10762,7 +10876,7 @@ msgid "Create issue"
msgstr "Ticket erstellen"
msgid "Create issue to resolve all threads"
-msgstr "Problem erstellen, um alle Diskussionen zu lösen."
+msgstr ""
msgid "Create iteration"
msgstr ""
@@ -10813,7 +10927,7 @@ msgid "Create new label"
msgstr "Neues Label erstellen"
msgid "Create new project"
-msgstr ""
+msgstr "Neues Projekt erstellen"
msgid "Create new..."
msgstr "Neu erstellen"
@@ -10900,10 +11014,10 @@ msgid "CreateValueStreamForm|Code stage start"
msgstr ""
msgid "CreateValueStreamForm|Create from default template"
-msgstr ""
+msgstr "Aus Standardvorlage erstellen"
msgid "CreateValueStreamForm|Create from no template"
-msgstr ""
+msgstr "Ohne Vorlage erstellen"
msgid "CreateValueStreamForm|Create new Value Stream"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11131,7 +11248,7 @@ msgid "Crm|Edit contact"
msgstr ""
msgid "Crm|Edit organization"
-msgstr ""
+msgstr "Organisation bearbeiten"
msgid "Crm|New contact"
msgstr ""
@@ -11377,7 +11494,7 @@ msgid "CycleAnalyticsStage|Code"
msgstr "Code"
msgid "CycleAnalyticsStage|Issue"
-msgstr "CycleAnalyticsStage|Probleme"
+msgstr "Probleme"
msgid "CycleAnalyticsStage|Plan"
msgstr "Planung"
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr "DAST-Konfiguration nicht gefunden"
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11511,13 +11631,16 @@ msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Change failure rate"
-msgstr "DORA4Metrics|Fehlerrate ändern"
+msgstr "Fehlerrate ändern"
+
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
msgid "DORA4Metrics|Date"
msgstr ""
msgid "DORA4Metrics|Days for an open incident"
-msgstr "DORA4Metrics|Tage für einen offenen Vorfall"
+msgstr "Tage für einen offenen Vorfall"
msgid "DORA4Metrics|Days from merge to deploy"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11535,7 +11661,7 @@ 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 "DORA4Metrics|Mediane Zeit, in der ein Incident in einer Produktionsumgebung im angegebenen Zeitraum offen war."
+msgstr "Mediane Zeit, in der ein Incident in einer Produktionsumgebung im angegebenen Zeitraum offen war."
msgid "DORA4Metrics|No incidents during this period"
msgstr "Keine Vorfälle in diesem Zeitraum"
@@ -11547,13 +11673,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 "DORA4Metrics|Anzahl der Vorfälle geteilt durch die Anzahl der Bereitstellungen in einer Produktionsumgebung im angegebenen Zeitraum."
+msgstr "Anzahl der Vorfälle geteilt durch die Anzahl der Bereitstellungen in einer Produktionsumgebung im angegebenen Zeitraum."
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr "DORA4Metrics|Prozentsatz fehlgeschlagener Bereitstellungen"
+msgstr "Prozentsatz fehlgeschlagener Bereitstellungen"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr "DORA4Metrics|Beim Abrufen der Daten zur Änderungsfehlerrate ist etwas schief gelaufen."
+msgstr "Beim Abrufen der Daten zur Änderungsfehlerrate ist etwas schief gelaufen."
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12086,7 +12227,7 @@ msgid "Date"
msgstr ""
msgid "Date merged"
-msgstr ""
+msgstr "Datum zusammengeführt"
msgid "Date range"
msgstr ""
@@ -12185,16 +12326,16 @@ msgid "DefaultBranchLabel|default"
msgstr ""
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
-msgstr "DefaultBranchProtection|Sowohl Entwickler als auch Betreuer können neue Commits pushen, aber Pushen nicht erzwingen."
+msgstr "Sowohl Entwickler als auch Betreuer können neue Commits pushen, aber Pushen nicht erzwingen."
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
-msgstr "DefaultBranchProtection|Sowohl Entwickler als auch Betreuer können neue Commits pushen, Push erzwingen oder den Branch löschen."
+msgstr "Sowohl Entwickler als auch Betreuer können neue Commits pushen, Push erzwingen oder den Branch löschen."
msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
-msgstr "DefaultBranchProtection|Entwickler können keine neuen Commits pushen, dürfen aber Merge-Anfragen an den Branch annehmen. Betreuer können auf den Zweig pushen."
+msgstr "Entwickler können keine neuen Commits pushen, dürfen aber Merge-Anfragen an den Branch annehmen. Betreuer können auf den Zweig pushen."
msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
-msgstr "DefaultBranchProtection|Entwickler können keine neuen Commits pushen, Betreuer hingegen schon. Push kann niemand erzwingen."
+msgstr "Entwickler können keine neuen Commits pushen, Betreuer hingegen schon. Push kann niemand erzwingen."
msgid "DefaultBranchProtection|Fully protected"
msgstr ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr "Release löschen"
+
+msgid "Delete release %{release}?"
+msgstr "Release %{release} löschen?"
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 "Möchtest du diese Version wirklich löschen?"
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr "Weitere Einzelheiten findest du unter %{docsPathStart}Eine Version löschen%{docsPathEnd}."
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr "Du bist im Begriff, Release %{release} und seine Assets zu löschen. Das Git-Tag %{tag} wird nicht gelöscht."
+
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
msgstr ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12458,7 +12614,7 @@ msgid "Denied"
msgstr ""
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "Berechtigung für Chat-Nickname %{user_name} abgelehnt."
msgid "Deny"
msgstr "Verweigern"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Bereitstellung"
msgstr[1] "Bereitstellungen"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Bereitstellungsschlüssel"
@@ -12752,7 +12911,7 @@ msgid "DeployTokens|Allows read-only access to the package registry."
msgstr ""
msgid "DeployTokens|Allows read-only access to the repository."
-msgstr ""
+msgstr "Ermöglicht schreibgeschützten Zugriff auf das Repository."
msgid "DeployTokens|Allows write access to registry images."
msgstr ""
@@ -12839,10 +12998,10 @@ msgid "Deployed to"
msgstr "Bereitgestellt für"
msgid "Deployed-after"
-msgstr ""
+msgstr "Bereitgestellt nach"
msgid "Deployed-before"
-msgstr ""
+msgstr "Bereitgestellt vor"
msgid "Deploying to"
msgstr "Bereitstellung für"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13006,16 +13165,16 @@ msgid "Deprecations|Feature deprecation and removal"
msgstr ""
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
-msgstr ""
+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 ""
+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 ""
+msgstr "Die Metrikfunktion wurde in GitLab 14.7 eingestellt."
msgid "Deprioritize label"
msgstr "Label entpriorisieren"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Domäne"
@@ -13775,7 +13931,7 @@ msgid "Downvotes"
msgstr "Negativ bewertet"
msgid "Draft"
-msgstr ""
+msgstr "Entwurf"
msgid "Draft: %{filename}"
msgstr ""
@@ -13862,22 +14018,22 @@ msgid "Duration|%s years"
msgstr ""
msgid "Duration|1 day"
-msgstr ""
+msgstr "1 Tag"
msgid "Duration|1 hour"
-msgstr ""
+msgstr "1 Stunde"
msgid "Duration|1 minute"
-msgstr ""
+msgstr "1 Minute"
msgid "Duration|1 month"
-msgstr ""
+msgstr "1 Monat"
msgid "Duration|1 week"
-msgstr ""
+msgstr "1 Woche"
msgid "Duration|1 year"
-msgstr ""
+msgstr "1 Jahr"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
msgstr "Während dieses Vorgangs wirst du nach URLs von GitLab gefragt. Verwende die unten angezeigten URLs."
@@ -13973,7 +14129,7 @@ msgid "Edit files in the editor and commit changes here"
msgstr "Bearbeite Dateien im Editor und committe die Änderungen hier"
msgid "Edit fork in Web IDE"
-msgstr ""
+msgstr "Fork in Web IDE bearbeiten"
msgid "Edit group application"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr "Keine. Wähle Projekte zum Indexieren aus."
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "E-Mail"
@@ -14186,7 +14339,7 @@ msgid "Emails sent from Service Desk have this name."
msgstr ""
msgid "Emails sent to %{email} are also supported."
-msgstr ""
+msgstr "An %{email} gesendete E-Mails werden ebenfalls unterstützt."
msgid "EmailsOnPushService|Disable code diffs"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14531,7 +14681,7 @@ msgid "Enterprise"
msgstr ""
msgid "Environment"
-msgstr ""
+msgstr "Umgebung"
msgid "Environment is required for Stages::MetricEndpointInserter"
msgstr ""
@@ -14648,7 +14798,7 @@ msgid "Environments|Deploy to..."
msgstr "Bereitstellen für..."
msgid "Environments|Deployment"
-msgstr "Environments|Bereitstellung"
+msgstr "Bereitstellung"
msgid "Environments|Deployment %{status}"
msgstr ""
@@ -14864,7 +15014,7 @@ 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 "Epics|Die Farbe für das Epic, wenn es visualisiert wird, z. B. auf Roadmap-Zeitleisten."
+msgstr "Die Farbe für das Epic, wenn es visualisiert wird, z. B. auf Roadmap-Zeitleisten."
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 ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr "Fehler beim Erstellen der Schwachstellensuche: %{errors}"
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15095,7 +15248,7 @@ msgid "Error: Unable to find AWS role for current user"
msgstr ""
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "Zugriffstoken ist %{token_in_code_tag}"
msgid "ErrorTracking|Active"
msgstr ""
@@ -15269,7 +15422,7 @@ msgid "Even if you reach the number of seats in your subscription, you can conti
msgstr ""
msgid "EventFilterBy|Filter by all"
-msgstr "EventFilterBy|Nach allem filtern"
+msgstr "Nach allem filtern"
msgid "EventFilterBy|Filter by comments"
msgstr "Filtere nach Kommentaren"
@@ -15550,7 +15703,7 @@ msgid "Export %{requirementsCount} requirements?"
msgstr ""
msgid "Export as CSV"
-msgstr ""
+msgstr "Als CSV exportieren"
msgid "Export commit custody report"
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Fehler beim Entfernen des Mirrors."
msgid "Failed to remove the pipeline schedule"
msgstr "Entfernung der Pipelineplanung fehlgeschlagen"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ msgstr "Speichern der Einstellungen fehlgeschlagen (%{error_message})."
msgid "Failed to save preferences."
msgstr "Speichern der Einstellungen fehlgeschlagen."
+msgid "Failed to save timelog"
+msgstr ""
+
msgid "Failed to set due date because the date format is invalid."
msgstr "Konnte Fälligkeitsdatum wegen ungültigen Formats nicht festlegen."
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr "Schnellere Releases. Besserer Code. Weniger Schmerzen."
@@ -15986,7 +16136,7 @@ msgid "Feature Flags"
msgstr "Feature Flags"
msgid "Feature deprecation"
-msgstr ""
+msgstr "Funktion veraltet"
msgid "Feature flag status"
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "Feb"
msgid "February"
msgstr "Februar"
+msgid "Feedback issue"
+msgstr "Feedback-Problem"
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16321,10 +16474,10 @@ msgid "Filter by milestone"
msgstr ""
msgid "Filter by milestone name"
-msgstr ""
+msgstr "Nach Meilensteinnamen filtern"
msgid "Filter by name"
-msgstr "Nach Name filtern"
+msgstr "Nach Namen filtern"
msgid "Filter by test cases that are currently archived."
msgstr ""
@@ -16342,16 +16495,16 @@ msgid "Filter pipelines"
msgstr ""
msgid "Filter results"
-msgstr ""
+msgstr "Ergebnisse filtern"
msgid "Filter results by group"
-msgstr ""
+msgstr "Ergebnisse nach Gruppe filtern"
msgid "Filter results by project"
-msgstr ""
+msgstr "Ergebnisse nach Projekt filtern"
msgid "Filter results..."
-msgstr ""
+msgstr "Ergebnisse filtern"
msgid "Filter users"
msgstr ""
@@ -16492,7 +16645,7 @@ msgid "For additional information, review your group membership: %{link_to} or c
msgstr ""
msgid "For each job, clone the repository."
-msgstr ""
+msgstr "Für jeden Job das Repository klonen."
msgid "For each job, re-use the project workspace. If the workspace doesn't exist, use %{code_open}git clone%{code_close}."
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "Von der Ticketbeschreibung bis zur Bereitstellung"
@@ -16672,7 +16834,7 @@ msgid "Full log"
msgstr ""
msgid "Full name"
-msgstr ""
+msgstr "Vollständiger Name"
msgid "GCP region configured"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16883,7 +17051,7 @@ msgid "Geo|Edit your search and try again."
msgstr ""
msgid "Geo|Errors:"
-msgstr ""
+msgstr "Fehler:"
msgid "Geo|Failed"
msgstr "Fehlgeschlagen"
@@ -16895,7 +17063,7 @@ msgid "Geo|Filter Geo sites"
msgstr ""
msgid "Geo|Filter by name"
-msgstr ""
+msgstr "Nach Name filtern"
msgid "Geo|Filter by status"
msgstr "Nach Status filtern"
@@ -16904,7 +17072,7 @@ msgid "Geo|Full details"
msgstr ""
msgid "Geo|Geo Settings"
-msgstr ""
+msgstr "Geo Einstellungen"
msgid "Geo|Geo Status"
msgstr "Geo-Status"
@@ -16916,7 +17084,7 @@ msgid "Geo|Geo can replicate objects stored in Object Storage (AWS S3, or other
msgstr ""
msgid "Geo|Geo sites"
-msgstr ""
+msgstr "Geo-Seiten"
msgid "Geo|Geo sites are paused using a command run on the site"
msgstr ""
@@ -16939,14 +17107,11 @@ msgstr ""
msgid "Geo|In progress"
msgstr "In Bearbeitung"
-msgid "Geo|In sync"
-msgstr "Wird synchronisiert"
-
msgid "Geo|Internal URL"
msgstr ""
msgid "Geo|Internal URL (optional)"
-msgstr ""
+msgstr "Interne URL (optional)"
msgid "Geo|Last event ID from primary"
msgstr ""
@@ -16967,7 +17132,7 @@ msgid "Geo|Last time verified"
msgstr "Zuletzt überprüft"
msgid "Geo|Learn more about Geo"
-msgstr ""
+msgstr "Mehr über Geo erfahren"
msgid "Geo|Learn more about Geo site statuses"
msgstr ""
@@ -16979,7 +17144,7 @@ msgid "Geo|Make everyone on your team more productive regardless of their locati
msgstr ""
msgid "Geo|Minimum interval in days"
-msgstr ""
+msgstr "Minimales Intervall (in Tagen)"
msgid "Geo|Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
@@ -16994,14 +17159,11 @@ msgid "Geo|Next sync scheduled at"
msgstr "Nächste Synchronisierung geplant um"
msgid "Geo|No Geo site found"
-msgstr ""
+msgstr "Keine Geo-Seite gefunden"
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Noch nicht synchronisiert"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "Unbekannter Status"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17321,7 +17480,7 @@ msgid "Get started with error tracking"
msgstr ""
msgid "Get started with performance monitoring"
-msgstr ""
+msgstr "Erste Schritte zum Performance-Monitoring"
msgid "Get started!"
msgstr "Loslegen!"
@@ -17369,40 +17528,40 @@ msgid "Git version"
msgstr "Git-Version"
msgid "GitAbuse|Excluded users"
-msgstr "GitAbuse|Ausgeschlossene Benutzer"
+msgstr "Ausgeschlossene Benutzer"
msgid "GitAbuse|Number of repositories"
-msgstr "GitAbuse|Anzahl der Repositories"
+msgstr "Anzahl der Repositories"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr "GitAbuse|Anzahl der Repositories darf nicht leer sein. Auf 0 setzen für keine Begrenzung."
+msgstr "Anzahl der Repositories darf nicht leer sein. Auf 0 setzen für keine Begrenzung."
msgid "GitAbuse|Number of repositories must be a number."
-msgstr "GitAbuse|Anzahl der Repositories muss eine Zahl sein."
+msgstr "Anzahl der Repositories muss eine Zahl sein."
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr "GitAbuse|Anzahl der Repositories sollte zwischen %{minNumRepos}-%{maxNumRepos} liegen"
+msgstr "Anzahl der Repositories sollte zwischen %{minNumRepos}-%{maxNumRepos} liegen"
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr "GitAbuse|Berichtszeitraum (Sekunden)"
+msgstr "Berichtszeitraum (Sekunden)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr "GitAbuse|Berichtszeitraum darf nicht leer sein. Auf 0 setzen für keine Begrenzung."
+msgstr "Berichtszeitraum darf nicht leer sein. Auf 0 setzen für keine Begrenzung."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr "GitAbuse|Berichtszeitraum muss eine Zahl sein."
+msgstr "Berichtszeitraum muss eine Zahl sein."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr "GitAbuse|Berichtszeitraum sollte zwischen %{minTimePeriod}-%{maxTimePeriod} Sekunden liegen."
+msgstr "Berichtszeitraum sollte zwischen %{minTimePeriod}-%{maxTimePeriod} Sekunden liegen."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr "GitAbuse|Die maximale Anzahl eindeutiger Repositories, die ein Benutzer in einem bestimmten Zeitraum herunterladen kann, bevor er gesperrt wird."
+msgstr "Die maximale Anzahl eindeutiger Repositories, die ein Benutzer in einem bestimmten Zeitraum herunterladen kann, bevor er gesperrt wird."
msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
-msgstr "GitAbuse|Benutzer, die von der Begrenzung der Git-Missbrauchsrate ausgeschlossen sind."
+msgstr "Benutzer, die von der Begrenzung der Git-Missbrauchsrate ausgeschlossen sind."
msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
-msgstr "GitAbuse|Du kannst nicht mehr als %{maxExcludedUsers} ausgeschlossene Benutzer angeben."
+msgstr "Du kannst nicht mehr als %{maxExcludedUsers} ausgeschlossene Benutzer angeben."
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17531,7 +17690,7 @@ msgid "GitLab version"
msgstr ""
msgid "GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab erstellt einen Branch in deinem Fork und startet eine Merge-Anfrage."
msgid "GitLab.com"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "Pipeline-Status überprüfen"
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 "Von vorn anfangen"
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -17621,11 +17786,14 @@ msgid "GitLabPages|Unverified"
msgstr ""
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr "GitLabPages|Deine Pages-Konfiguration wird aktualisiert..."
+msgstr "Deine Pages-Konfiguration wird aktualisiert..."
msgid "GitLabPages|Verified"
msgstr ""
+msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
+msgstr "Warten, bis die Pages-Pipeline abgeschlossen ist..."
+
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 ""
@@ -17638,6 +17806,9 @@ 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 "Dein Projekt wurde für Seiten konfiguriert. Jetzt müssen wir warten, bis die Pipeline zum ersten Mal erfolgreich ist."
+
msgid "GitLabPages|Your pages are served under:"
msgstr ""
@@ -17753,13 +17924,13 @@ msgid "GlobalSearch|Merge requests that I'm a reviewer"
msgstr ""
msgid "GlobalSearch|Projects"
-msgstr ""
+msgstr "Projekte"
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 "GlobalSearch|GitLab durchsuchen"
+msgstr "GitLab durchsuchen"
msgid "GlobalSearch|Search for projects, issues, etc."
msgstr ""
@@ -17936,7 +18107,7 @@ msgid "Go to your To-Do list"
msgstr ""
msgid "Go to your fork"
-msgstr ""
+msgstr "Gehe zu deinem Fork"
msgid "Go to your groups"
msgstr ""
@@ -17956,18 +18127,15 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
+msgid "Google Cloud Error - %{error}"
+msgstr "Google Cloud-Fehler – %{error}"
+
msgid "Google Cloud Project"
msgstr ""
msgid "Google Cloud authorizations required"
msgstr ""
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18092,7 +18260,7 @@ msgid "Group Hooks"
msgstr "Gruppen-Hooks"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
-msgstr ""
+msgstr "Der Gruppenbesitzer muss sich mit SAML angemeldet haben, bevor er gruppenverwaltete Konten aktiviert"
msgid "Group SAML must be enabled to test"
msgstr "Gruppen-SAML muss zum Testen aktiviert sein"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr "Inhalt der Gruppenübersicht"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ msgstr ""
msgid "GroupSettings|Export group"
msgstr "Gruppe exportieren"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr ""
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr "Lege eine Größenbeschränkung für alle Inhalte in jeder Pages-Seite i
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,14 +18901,17 @@ msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff au
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|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+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 "Mit %{linkStart}Gruppen%{linkEnd} kannst du mehrere Projekte verwalten und zusammenarbeiten. Mitglieder einer Gruppe haben Zugriff auf alle ihre Projekte."
+
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Verwandte Projekte zusammenfassen und Mitgliedern gleichzeitig Zugriff auf mehrere Projekte gewähren."
msgid "GroupsNew|Connect instance"
-msgstr ""
+msgstr "Instanz verbinden"
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
msgstr ""
@@ -18766,51 +18922,57 @@ msgstr ""
msgid "GroupsNew|Create new group"
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."
+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 "Erstelle dies in den %{pat_link_start}Benutzereinstellungen%{pat_link_end} der GitLab-Quellinstanz. Verwende aus %{short_living_link_start}Sicherheitsgründen%{short_living_link_end} beim Erstellen des Tokens ein kurzes Ablaufdatum."
+
msgid "GroupsNew|GitLab source URL"
-msgstr ""
+msgstr "GitLab-Quell-URL"
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 ""
+msgstr "Gruppe und zugehörige Daten aus einer anderen GitLab-Instanz importieren."
msgid "GroupsNew|Import group"
msgstr ""
msgid "GroupsNew|Import groups from another instance of GitLab"
-msgstr ""
+msgstr "Gruppen von einer anderen GitLab Instanz importieren"
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 "Nicht alle zugehörigen Objekte werden migriert. %{docs_link_start}Weitere Informationen%{docs_link_end}."
msgid "GroupsNew|Personal access token"
msgstr ""
msgid "GroupsNew|Please fill in GitLab source URL."
-msgstr ""
+msgstr "Bitte gebe die GitLab-Quell-URL ein."
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 ""
+msgstr "Gebe Anmeldedaten für eine andere Instanz von GitLab an, um deine Gruppen direkt zu importieren."
msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
-msgstr ""
+msgstr "Diese Funktion ist veraltet und wurde durch %{docs_link_start}Gruppenmigration%{docs_link_end} ersetzt."
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 "Um eine Gruppe zu importieren, navigiere zu den Gruppeneinstellungen für die GitLab-Quellinstanz, %{link_start}erzeuge eine Exportdatei%{link_end}und lade sie hier hoch."
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18881,7 +19043,7 @@ msgid "Groups|Learn more"
msgstr ""
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
-msgstr ""
+msgstr "Muss mit einem Buchstaben, einer Ziffer, einem Emoji oder einem Unterstrich beginnen. Kann auch Punkte, Bindestriche, Leerzeichen und Klammern enthalten."
msgid "Groups|Remove avatar"
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18984,10 +19155,10 @@ msgid "HarborRegistry|Root image"
msgstr ""
msgid "HarborRegistry|Sorry, your filter produced no results."
-msgstr "HarborRegistry|Entschuldigung, dein Filter hat keine Ergebnisse geliefert."
+msgstr "Entschuldigung, dein Filter hat keine Ergebnisse geliefert."
msgid "HarborRegistry|The filter returned no results"
-msgstr ""
+msgstr "Der Filter hat keine Ergebnisse zurückgegeben"
msgid "HarborRegistry|The image repository could not be found."
msgstr ""
@@ -19002,7 +19173,7 @@ msgid "HarborRegistry|This image has no active tags"
msgstr ""
msgid "HarborRegistry|To widen your search, change or remove the filters above."
-msgstr "HarborRegistry|Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
+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}."
msgstr ""
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr "Historische Veröffentlichung"
+
msgid "History"
msgstr "Verlauf"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19327,19 +19498,19 @@ msgid "I forgot my password"
msgstr ""
msgid "I want to explore GitLab to see if it’s worth switching to"
-msgstr ""
+msgstr "Ich möchte GitLab erkunden, um zu sehen, ob es sich lohnt, zu wechseln"
msgid "I want to learn the basics of Git"
-msgstr ""
+msgstr "Ich möchte die Grundlagen von Git lernen"
msgid "I want to move my repository to GitLab from somewhere else"
-msgstr ""
+msgstr "Ich möchte mein Repository von woanders zu GitLab verschieben"
msgid "I want to store my code"
-msgstr ""
+msgstr "Ich möchte meinen Code ablegen"
msgid "I want to use GitLab CI with my existing repository"
-msgstr ""
+msgstr "Ich möchte GitLab CI mit meinem bestehenden Repository verwenden"
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 "Wenn keine der Optionen funktioniert, wende dich an einen GitLab-Administrator."
+
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 ""
@@ -19576,7 +19753,7 @@ 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 ""
+msgstr "Wenn du dich kürzlich angemeldet hast und die IP-Adresse erkennst, kannst du diese E-Mail ignorieren."
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -19667,10 +19844,10 @@ msgid "Import from Jira"
msgstr "Aus Jira importieren"
msgid "Import group"
-msgstr ""
+msgstr "Gruppe importieren"
msgid "Import group from file"
-msgstr ""
+msgstr "Gruppe aus Datei importieren"
msgid "Import groups"
msgstr ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19813,7 +19993,7 @@ msgid "In a seat"
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 ""
+msgstr "Im Falle einer Pull-Spiegelung ist Ihr Benutzer der Autor aller Ereignisse im Aktivitäts-Feed, die das Ergebnis einer Aktualisierung sind, wie z. B. das Erstellen neuer Zweige oder das Pushen neuer Commits an vorhandene Zweige."
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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20608,13 +20755,13 @@ msgid "Incident|Alert details"
msgstr ""
msgid "Incident|Are you sure you want to delete this event?"
-msgstr "Incident|Dieses Ereignis wirklich löschen?"
+msgstr "Dieses Ereignis wirklich löschen?"
msgid "Incident|Are you sure you wish to delete this image?"
msgstr ""
msgid "Incident|Delete event"
-msgstr "Incident|Ereignis löschen"
+msgstr "Ereignis löschen"
msgid "Incident|Delete image"
msgstr ""
@@ -20629,10 +20776,10 @@ msgid "Incident|Editing %{filename}"
msgstr ""
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr "Incident|Fehler beim Erstellen des Ereignisses auf der Zeitachse des Vorfalls: %{error}"
+msgstr "Fehler beim Erstellen des Ereignisses auf der Zeitachse des Vorfalls: %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr "Incident|Fehler beim Löschen des Ereignisses auf der Zeitachse des Vorfalls: %{error}"
+msgstr "Fehler beim Löschen des Ereignisses auf der Zeitachse des Vorfalls: %{error}"
msgid "Incident|Metrics"
msgstr ""
@@ -20641,13 +20788,13 @@ msgid "Incident|No timeline items have been added yet."
msgstr ""
msgid "Incident|Save and add another event"
-msgstr "Incident|Speichern und ein weiteres Ereignis hinzufügen"
+msgstr "Speichern und ein weiteres Ereignis hinzufügen"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr "Incident|Beim Erstellen des Vorfall-Zeitachsenereignisses ist ein Fehler aufgetreten."
+msgstr "Beim Erstellen des Vorfall-Zeitachsenereignisses ist ein Fehler aufgetreten."
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr "Incident|Beim Löschen des Vorfall-Zeitachsenereignisses ist ein Fehler aufgetreten."
+msgstr "Beim Löschen des Vorfall-Zeitachsenereignisses ist ein Fehler aufgetreten."
msgid "Incident|Something went wrong while fetching incident timeline events."
msgstr ""
@@ -20665,10 +20812,10 @@ msgid "Incident|Timeline"
msgstr ""
msgid "Incident|Timeline text"
-msgstr "Incident|Zeitleistentext"
+msgstr "Zeitleistentext"
msgid "Incident|Timeline text..."
-msgstr "Incident|Zeitleistentext..."
+msgstr "Zeitleistentext..."
msgid "Include author name in notification email body"
msgstr ""
@@ -20839,7 +20986,7 @@ msgid "Install GitLab Runner and ensure it's running."
msgstr ""
msgid "Install on clusters"
-msgstr ""
+msgstr "Auf Cluster installieren"
msgid "Installation"
msgstr ""
@@ -20892,7 +21039,7 @@ msgid "IntegrationEvents|A confidential issue is created, updated, or closed"
msgstr ""
msgid "IntegrationEvents|A merge request is created, updated, or merged"
-msgstr ""
+msgstr "Eine Zusammenführungsanforderung wird erstellt, aktualisiert oder zusammengeführt"
msgid "IntegrationEvents|A pipeline status changes"
msgstr ""
@@ -21138,7 +21285,7 @@ msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
-msgstr "Integrationen|Du musst Inhaber sein oder Betreuerberechtigungen haben, um Namespaces zu verknüpfen."
+msgstr "Du musst Inhaber sein oder Betreuerberechtigungen haben, um Namespaces zu verknüpfen."
msgid "Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app."
msgstr ""
@@ -21312,7 +21459,7 @@ msgid "Invite a group"
msgstr ""
msgid "Invite members"
-msgstr ""
+msgstr "Mitglieder einladen"
msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
msgstr ""
@@ -21324,7 +21471,7 @@ msgid "InviteEmail|%{project_or_group} details"
msgstr ""
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "Gruppen stellen verwandte Projekte zusammen und gewähren Mitgliedern gleichzeitig Zugriff auf mehrere Projekte."
msgid "InviteEmail|Join now"
msgstr ""
@@ -21362,14 +21509,14 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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 ""
+msgstr "Ablaufdatum des Zugriffs (optional)"
msgid "InviteMembersModal|Cancel"
msgstr ""
@@ -21411,7 +21558,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr ""
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr "InviteMembersModal|Einladungsfehler überprüfen und erneut versuchen:"
+msgstr "Einladungsfehler überprüfen und erneut versuchen:"
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -21430,8 +21577,8 @@ msgstr ""
msgid "InviteMembersModal|The following member couldn't be invited"
msgid_plural "InviteMembersModal|The following %d members couldn't be invited"
-msgstr[0] "InviteMembersModal|Das folgende Mitglied konnte nicht eingeladen werden"
-msgstr[1] "InviteMembersModal|Das folgenden %d Mitglieder konnten nicht eingeladen werden"
+msgstr[0] "Das folgende Mitglied konnte nicht eingeladen werden"
+msgstr[1] "Das folgenden %d Mitglieder konnten nicht eingeladen werden"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
msgstr ""
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21485,10 +21629,10 @@ msgid "InviteMember|Add members to this project and start collaborating with you
msgstr ""
msgid "InviteMember|Invite Members (optional)"
-msgstr ""
+msgstr "Mitglieder einladen (optional)"
msgid "InviteMember|Invite another member"
-msgstr ""
+msgstr "Ein weiteres Mitglied einladen"
msgid "InviteMember|Invite members"
msgstr ""
@@ -21497,7 +21641,7 @@ 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 "Eingeladene Benutzer werden mit Berechtigungen auf Entwicklerebene hinzugefügt. %{linkStart}Sehe ir die Dokumentation an%{linkEnd}, um zu sehen, wie du dies später ändern kannst."
msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
msgstr ""
@@ -21608,7 +21752,7 @@ msgid "IssuableStatus|promoted"
msgstr "hochgestuft"
msgid "Issue"
-msgstr "Problem"
+msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
@@ -21698,10 +21842,10 @@ msgid "IssueBoards|Board"
msgstr "Board"
msgid "IssueBoards|Boards"
-msgstr "IssueBoards|Boards"
+msgstr "Boards"
msgid "IssueBoards|Create new board"
-msgstr ""
+msgstr "Neues Board erstellen"
msgid "IssueBoards|Delete board"
msgstr ""
@@ -21767,7 +21911,7 @@ msgid "IssueTracker|Use a custom issue tracker that is not in the integration li
msgstr ""
msgid "Issues"
-msgstr "Probleme"
+msgstr ""
msgid "Issues Rate Limits"
msgstr ""
@@ -21818,7 +21962,7 @@ msgid "IssuesAnalytics|Last 12 months"
msgstr "Letzten 12 Monate"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr "IssuesAnalytics|Dein Filter hat leider keine Ergebnisse geliefert"
+msgstr "Dein Filter hat leider keine Ergebnisse geliefert"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
msgstr "Es gibt keine Tickets für die Projekte in deiner Gruppe"
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ msgstr "Iteration aktualisiert"
msgid "Iterations"
msgstr "Iterationen"
+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 "Automatische Planung"
+
+msgid "Iterations|Automation start date"
+msgstr ""
+
msgid "Iterations|Cadence configuration is invalid."
msgstr ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "Iterationen automatisch nach einem regelmäßigen Zeitplan erstellen."
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
-msgstr ""
+msgid "Iterations|Enable roll over"
+msgstr "Rollover aktivieren"
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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 "Iterationen sollen am %{weekday}s beginnen."
+
msgid "Iterations|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22019,7 +22193,7 @@ msgid "Iterations|This will delete the cadence as well as all of the iterations
msgstr ""
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
-msgstr "Iterations|Dies entfernt die Iteration von allen Problemen, die ihr zugewiesen sind."
+msgstr "Dies entfernt die Iteration von allen Problemen, die ihr zugewiesen sind."
msgid "Iterations|Title"
msgstr ""
@@ -22304,7 +22478,7 @@ 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 "JiraService|Wenn ein Jira-Problem in einer Commit- oder Merge-Anfrage erwähnt wird, werden ein Remote-Link und ein Kommentar (falls aktiviert) erstellt."
+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 ""
@@ -22421,7 +22595,7 @@ msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
msgstr ""
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr "Job|%{searchLength} Ergebnisse gefunden für %{searchTerm}"
+msgstr "%{searchLength} Ergebnisse gefunden für %{searchTerm}"
msgid "Job|Are you sure you want to erase this job log and artifacts?"
msgstr ""
@@ -22463,7 +22637,7 @@ msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Job log search"
-msgstr "Job|Job-Log-Suche"
+msgstr "Job-Log-Suche"
msgid "Job|Keep"
msgstr "Behalten"
@@ -22472,7 +22646,7 @@ msgid "Job|Manual"
msgstr ""
msgid "Job|No search results found"
-msgstr "Job|Keine Suchergebnisse gefunden"
+msgstr "Keine Suchergebnisse gefunden"
msgid "Job|Passed"
msgstr ""
@@ -22495,14 +22669,17 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Zum Seitenende scrollen"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Scrolle nach oben"
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 "Job|Suche in deiner Auftragsprotokollausgabe nach Teilzeichenfolgen. Derzeit wird die Suche nur für die sichtbare Auftragsprotokollausgabe unterstützt, nicht für Protokollausgaben, die aufgrund ihrer Größe abgeschnitten werden."
+msgstr "Suche in deiner Auftragsprotokollausgabe nach Teilzeichenfolgen. Derzeit wird die Suche nur für die sichtbare Auftragsprotokollausgabe unterstützt, nicht für Protokollausgaben, die aufgrund ihrer Größe abgeschnitten werden."
msgid "Job|Search job log"
-msgstr "Job|Jobprotokoll durchsuchen"
+msgstr "Jobprotokoll durchsuchen"
msgid "Job|Show complete raw"
msgstr "Zeige komplette Rohdaten"
@@ -22541,7 +22718,7 @@ msgid "Job|Waiting for resource"
msgstr ""
msgid "Job|We could not find this element"
-msgstr "Job|Wir konnten dieses Element nicht finden"
+msgstr "Wir konnten dieses Element nicht finden"
msgid "Job|allowed to fail"
msgstr ""
@@ -22589,7 +22766,7 @@ msgid "June"
msgstr "Juni"
msgid "Just me"
-msgstr ""
+msgstr "Nur ich"
msgid "K8s pod health"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,20 +23348,20 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr "Weniger einschränkende Sicht"
+
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 "Let's talk!"
-msgstr ""
-
msgid "License Compliance"
msgstr ""
-msgid "License Compliance| Used by"
-msgstr ""
+msgid "License Compliance| Used by %{dependencies}"
+msgstr "Verwendet von %{dependencies}"
msgid "License compliance"
msgstr ""
@@ -23450,8 +23621,11 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Verknüpfte Probleme"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr "Verknüpfte Einträge"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23462,6 +23636,48 @@ msgstr ""
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
+msgid "LinkedResources|Add"
+msgstr "Hinzufügen"
+
+msgid "LinkedResources|Add a resource link"
+msgstr "Ressourcenlink hinzufügen"
+
+msgid "LinkedResources|Cancel"
+msgstr "Abbrechen"
+
+msgid "LinkedResources|Error creating resource link for the incident: %{error}"
+msgstr "Fehler beim Erstellen des Ressourcenlinks für den Vorfall: %{error}"
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr "Fehler beim Löschen der verknüpften Ressource für den Vorfall: %{error}"
+
+msgid "LinkedResources|Fetching linked resources"
+msgstr "Abrufen verknüpfter Ressourcen"
+
+msgid "LinkedResources|Link"
+msgstr "Link"
+
+msgid "LinkedResources|Linked resources"
+msgstr "Verknüpfte Ressourcen"
+
+msgid "LinkedResources|Remove"
+msgstr "Entfernen"
+
+msgid "LinkedResources|Something went wrong while creating the resource link for the incident."
+msgstr "Beim Erstellen des Ressourcenlinks für den Vorfall ist ein Fehler aufgetreten."
+
+msgid "LinkedResources|Something went wrong while deleting the linked resource for the incident."
+msgstr "Beim Löschen der verknüpften Ressource für den Vorfall ist ein Fehler aufgetreten."
+
+msgid "LinkedResources|Something went wrong while fetching linked resources for the incident."
+msgstr "Beim Abrufen verknüpfter Ressourcen für den Vorfall ist ein Fehler aufgetreten."
+
+msgid "LinkedResources|Text (Optional)"
+msgstr "Text (Optional)"
+
+msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
+msgstr "Verwende diesen Bereich, um Links zu den Ressourcen hinzuzufügen, die dein Team benötigt, um den Vorfall zu lösen."
+
msgid "Links"
msgstr ""
@@ -23652,7 +23868,7 @@ msgid "MD5"
msgstr "MD5"
msgid "MERGED"
-msgstr ""
+msgstr "ZUSAMMENGEFÃœHRT"
msgid "MR widget|Back to the merge request"
msgstr ""
@@ -23709,7 +23925,7 @@ 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 ""
+msgstr "Änderungen im Browser mit der Web-IDE vornehmen und überprüfen"
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 "Mache alle in deinem Team unabhängig von ihrem Standort produktiver. GitLab Geo erstellt schreibgeschützte Mirror deiner GitLab-Instanz, sodass du die Zeit zum Klonen und Abrufen großer Repos reduzieren kannst."
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23808,7 +24021,7 @@ msgid "March"
msgstr "März"
msgid "Mark as done"
-msgstr ""
+msgstr "Als erledigt markieren"
msgid "Mark as draft"
msgstr "Als Entwurf markieren"
@@ -23835,31 +24048,31 @@ msgid "Markdown supported."
msgstr ""
msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
-msgstr "MarkdownEditor|Link hinzufügen (%{modifierKey}K)"
+msgstr "Link hinzufügen (%{modifierKey}K)"
msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
msgstr "Link hinzufügen (%{modifier_key}K)"
msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
-msgstr "MarkdownEditor|Fetten Text hinzufügen (%{modifierKey}B)"
+msgstr "Fetten Text hinzufügen (%{modifierKey}B)"
msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
-msgstr "MarkdownEditor|Fetten Text hinzufügen (%{modifier_key}B)"
+msgstr "Fetten Text hinzufügen (%{modifier_key}B)"
msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
-msgstr "MarkdownEditor|Kursiven Text hinzufügen (%{modifierKey}I)"
+msgstr "Kursiven Text hinzufügen (%{modifierKey}I)"
msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
-msgstr "MarkdownEditor|Kursiven Text hinzufügen (%{modifier_key}I)"
+msgstr "Kursiven Text hinzufügen (%{modifier_key}I)"
msgid "MarkdownEditor|Add strikethrough text (%{modifierKey}⇧X)"
-msgstr "MarkdownEditor|Durchgestrichenen Text hinzufügen (%{modifierKey}⇧X)"
+msgstr "Durchgestrichenen Text hinzufügen (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Durchgestrichenen Text hinzufügen (%{modifier_key}⇧X)"
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
-msgstr "MarkdownToolbar|Unterstützt %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
+msgstr "Unterstützt %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -24301,7 +24514,7 @@ msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail}
msgstr ""
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
-msgstr ""
+msgstr "Möchtest du deine Zugriffsanfrage für \"%{source}\" wirklich widerrufen?"
msgid "Members|Direct"
msgstr ""
@@ -24529,7 +24742,7 @@ msgid "MergeRequestAnalytics|Assignees"
msgstr ""
msgid "MergeRequestAnalytics|Date Merged"
-msgstr ""
+msgstr "Datum der Zusammenführung"
msgid "MergeRequestAnalytics|Line changes"
msgstr ""
@@ -24643,7 +24856,7 @@ msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
msgstr ""
msgid "Merged"
-msgstr "Merged"
+msgstr "Zusammengeführt"
msgid "Merged MRs"
msgstr ""
@@ -24805,7 +25018,7 @@ msgid "Metrics|Add metric"
msgstr ""
msgid "Metrics|Add panel"
-msgstr ""
+msgstr "Panel hinzufügen"
msgid "Metrics|Avg"
msgstr ""
@@ -24838,7 +25051,7 @@ msgid "Metrics|Create metric"
msgstr "Metrik erstellen"
msgid "Metrics|Create new dashboard"
-msgstr ""
+msgstr "Neues Dashboard erstellen"
msgid "Metrics|Create your dashboard configuration file"
msgstr ""
@@ -24868,7 +25081,7 @@ msgid "Metrics|Duplicate dashboard"
msgstr ""
msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
-msgstr ""
+msgstr "Dupliziere dieses Zeigwerk/Dashboard, um ein Paneel hinzuzufügen oder die Dashboard-YAML zu bearbeiten."
msgid "Metrics|Duplicating..."
msgstr ""
@@ -24993,7 +25206,7 @@ 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 ""
+msgstr "Um ein neues Dashboard zu erstellen, füge eine neue YAML-Datei zu %{codeStart}.gitlab/dashboards%{codeEnd} im Stammverzeichnis dieses Projekts hinzu."
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "Unerwartete Bereitstellungs-Datenantwort vom Prometheus-Endpunkt"
@@ -25067,7 +25280,7 @@ msgstr[0] "Meilenstein"
msgstr[1] "Meilensteine"
msgid "Milestone due date"
-msgstr ""
+msgstr "Fälligkeitsdatum des Meilensteins"
msgid "Milestone lists not available with your current license"
msgstr "Meilensteinlisten ist mit deiner momentanen Lizenz nicht verfügbar"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25496,16 +25703,16 @@ msgid "My awesome group"
msgstr ""
msgid "My company or team"
-msgstr "Meine Firma oder Team"
+msgstr "Meine Firma oder mein Team"
msgid "My topic"
msgstr ""
msgid "My-Reaction"
-msgstr ""
+msgstr "Meine Reaktion"
msgid "NEW"
-msgstr ""
+msgstr "NEU"
msgid "Name"
msgstr "Name"
@@ -25662,9 +25869,6 @@ msgstr "Abmelden und mit einem anderen Konto anmelden"
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25788,7 +25992,7 @@ msgid "New epic title"
msgstr ""
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "Ein neuer Zugriffstoken für die Fehlerverfolgung wurde generiert!"
msgid "New file"
msgstr "Neue Datei"
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "Keine Google Cloud-Projekte – Du benötigst mindestens ein Google Cloud-Projekt"
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26043,7 +26247,7 @@ msgid "No estimate or time spent"
msgstr "Weder Schätzung noch Zeitaufwand eingetragen"
msgid "No file chosen."
-msgstr ""
+msgstr "Keine Datei ausgewählt."
msgid "No file hooks found."
msgstr "Keine Datei-Hooks gefunden."
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26342,7 +26543,7 @@ msgid "NoteForm|Note"
msgstr ""
msgid "NoteToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd}, type %{keyboardStart}/%{keyboardEnd}."
-msgstr "NoteToolbar|Unterstützt %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. Gebe für %{quickActionsDocsLinkStart}Schnellaktionen%{quickActionsDocsLinkEnd} %{keyboardStart}/%{keyboardEnd} ein."
+msgstr "Unterstützt %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. Gebe für %{quickActionsDocsLinkStart}Schnellaktionen%{quickActionsDocsLinkEnd} %{keyboardStart}/%{keyboardEnd} ein."
msgid "Notes"
msgstr ""
@@ -26363,13 +26564,13 @@ 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 "Notes|Interne Notizen sind nur für den Autor, Beauftragte und Mitglieder mit der Rolle Reporter oder höher sichtbar"
+msgstr "Interne Notizen sind nur für den Autor, Beauftragte und Mitglieder mit der Rolle Reporter oder höher sichtbar"
msgid "Notes|Last reply by %{name}"
msgstr ""
msgid "Notes|Make this an internal note"
-msgstr "Notes|Dies zu einer internen Notiz festlegen"
+msgstr "Dies zu einer internen Notiz festlegen"
msgid "Notes|Show all activity"
msgstr "Alle Aktivitäten anzeigen"
@@ -26389,6 +26590,9 @@ 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 "Das angegebene Erstellungsdatum liegt zu weit in der Vergangenheit."
+
msgid "Nothing to preview."
msgstr ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{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|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26536,10 +26749,10 @@ msgid "Notify|Author: %{author_name}"
msgstr ""
msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
-msgstr "Notify|Die automatische DevOps-Pipeline wurde für %{project} deaktiviert"
+msgstr "Die automatische DevOps-Pipeline wurde für %{project} deaktiviert"
msgid "Notify|CI/CD project settings"
-msgstr "Notify|CI/CD-Projekteinstellungen"
+msgstr "CI/CD-Projekteinstellungen"
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 ""
@@ -26551,7 +26764,7 @@ msgid "Notify|Issue was moved to another project."
msgstr ""
msgid "Notify|Learn more about Auto DevOps"
-msgstr "Notify|Mehr über Auto-DevOps erfahren"
+msgstr "Mehr über Auto-DevOps erfahren"
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26581,7 +26794,7 @@ msgid "Notify|Pipeline %{pipeline_link} triggered by"
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 "Notify|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}."
+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|This issue is due on: %{issue_due_date}"
msgstr ""
@@ -26593,10 +26806,10 @@ msgid "Notify|You don't have access to the project."
msgstr ""
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
-msgstr "Notify|Deine Anfrage, dem %{target_to_join} %{target_type} beizutreten, wurde %{denied_tag}."
+msgstr "Deine Anfrage, dem %{target_to_join} %{target_type} beizutreten, wurde %{denied_tag}."
msgid "Notify|currently supported languages"
-msgstr "Notify|Aktuell unterstützte Sprachen"
+msgstr "Aktuell unterstützte Sprachen"
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -26608,7 +26821,7 @@ msgid "November"
msgstr "November"
msgid "Now, personalize your GitLab experience"
-msgstr ""
+msgstr "Personalisiere jetzt dein GitLab-Erlebnis"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27111,7 +27329,7 @@ msgid "Only 1 appearances row can exist"
msgstr ""
msgid "Only HTTP(S)"
-msgstr ""
+msgstr "Nur HTTP(S)"
msgid "Only Issue ID or merge request ID is required"
msgstr ""
@@ -27120,7 +27338,7 @@ msgid "Only Project Members"
msgstr ""
msgid "Only SSH"
-msgstr ""
+msgstr "Nur SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
msgstr "Nur zugänglich für %{membersPageLinkStart}Projektmitglieder%{membersPageLinkEnd}. Die Mitgliedschaft muss jedem Benutzer explizit gewährt werden."
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27378,7 +27596,7 @@ msgid "Owner"
msgstr "Eigentümer(in)"
msgid "Owners and administrators"
-msgstr ""
+msgstr "Eigentümer und Administratoren"
msgid "Owners can modify this selection."
msgstr ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ msgstr ""
msgid "PackageRegistry|Error publishing"
msgstr ""
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr "Beispiele für Assets sind unter anderem .pom & .jar Dateien"
+
msgid "PackageRegistry|Failed to load the package data"
msgstr ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr "Speicher verwalten, der von Paketdateien verwendet wird"
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "Anzahl der zu behaltenden doppelten Assets"
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27761,7 +28005,7 @@ msgid "PackageRegistry|Something went wrong while fetching the package metadata.
msgstr ""
msgid "PackageRegistry|Sorry, your filter produced no results"
-msgstr "PackageRegistry|Leider hat dein Filter keine Ergebnisse geliefert"
+msgstr "Leider hat dein Filter keine Ergebnisse geliefert"
msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
@@ -27788,7 +28032,7 @@ msgid "PackageRegistry|This NuGet package has no dependencies."
msgstr ""
msgid "PackageRegistry|To widen your search, change or remove the filters above."
-msgstr "PackageRegistry|Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
+msgstr "Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
msgid "PackageRegistry|Type"
msgstr ""
@@ -27799,18 +28043,29 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Paket konnte nicht geladen werden"
+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 "Wenn ein Paket mit dem gleichen Namen und der gleichen Version zum Registry hochgeladen wird, werden weitere Assets zum Paket hinzugefügt. Um Speicherplatz zu sparen, solltest du nur die neuesten Assets behalten."
+
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 ""
+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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr "Leistungseinblicke"
+
msgid "Performance optimization"
msgstr "Leistungsoptimierung"
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28280,7 +28550,7 @@ msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{l
msgstr ""
msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
-msgstr ""
+msgstr "Übertrage die Datei in dein Repository. Die Pipeline wird dann automatisch ausgeführt."
msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
msgstr ""
@@ -28327,6 +28597,9 @@ msgstr ""
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr ""
+msgid "PipelineEditor|Configuration content has changed. Re-run validation for updated results."
+msgstr "Der Konfigurationsinhalt hat sich geändert. Führe die Validierung für aktualisierte Ergebnisse erneut aus."
+
msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
msgstr ""
@@ -28345,6 +28618,15 @@ 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 "Pipeline-Simulation mit Fehlern abgeschlossen"
+
+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 "Simulierte ein %{codeStart}git push%{codeEnd}-Ereignis für einen Standard-Branch. Die Jobabhängigkeitslogik %{codeStart}Rules%{codeEnd}, %{codeStart}only%{codeEnd}, %{codeStart}außer%{codeEnd} und %{codeStart}needs%{codeEnd} wurde ausgewertet. %{linkStart}Mehr erfahren%{linkEnd}"
+
+msgid "PipelineEditor|Simulation completed successfully"
+msgstr "Simulation erfolgreich abgeschlossen"
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -28366,6 +28648,12 @@ msgstr ""
msgid "PipelineEditor|Validate pipeline under simulated conditions"
msgstr ""
+msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
+msgstr "Validierung der Pipeline... Dies kann bis zu einer Minute dauern."
+
+msgid "PipelineEditor|Waiting for CI content to load..."
+msgstr "Warten auf Laden von CI-Inhalten..."
+
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
msgstr ""
@@ -28387,6 +28675,9 @@ msgstr "Nächste Durchführung"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Gib eine kurze Beschreibung für diese Pipeline ein"
@@ -28399,6 +28690,9 @@ msgstr "Ziel"
msgid "PipelineSchedules|Variables"
msgstr "Variablen"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "Die Pipeline-Syntax ist korrekt."
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Der Projekt-Cache wurde erfolgreich zurückgesetzt."
@@ -28808,14 +29105,23 @@ msgid "Pipeline|Date"
msgstr ""
msgid "Pipeline|Detached merge request pipeline"
-msgstr "Pipeline|Getrennte Pipeline für Zusammenführungsanforderungen"
+msgstr "Getrennte Pipeline für Zusammenführungsanforderungen"
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr "Die fünf langsamsten Jobs"
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr "Zuletzt ausgeführter Job"
+
+msgid "Pipeline|Longest queued job"
+msgstr "Längster Job in der Warteschlange"
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "Es können nur die ersten 100 Ergebnisse angezeigt werden"
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr "Leistungseinblicke"
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "Der zuletzt ausgeführte Job ist der letzte Job, der in der Pipeline gestartet wird."
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "Der Job mit der längsten Warteschlange ist der Job, der die längste Zeit im ausstehenden Zustand verbracht hat und darauf wartete, von einem Runner abgeholt zu werden"
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr "Variabeln"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr "Abhängigkeit anzeigen"
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29177,7 +29510,7 @@ 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 "Bitte warte, während wir uns mit deinem Repository verbinden. Aktualisiere nach Belieben."
+msgstr "Bitte warte, während wir uns mit deinem Repository verbinden. Nach Belieben aktualisieren."
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."
@@ -29288,7 +29621,7 @@ msgid "Preferences|Failed to save preferences."
msgstr ""
msgid "Preferences|For example: 30 minutes ago."
-msgstr "Preferences|Beispiel: Vor 30 Minuten."
+msgstr "Beispiel: Vor 30 Minuten."
msgid "Preferences|Gitpod"
msgstr ""
@@ -29362,8 +29695,8 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr "Bearbeiten von Genehmigungsregeln in Projekten und Zusammenführen von Anfragen verhindern"
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -29390,13 +29723,13 @@ msgid "Preview changes"
msgstr ""
msgid "Preview diagram"
-msgstr ""
+msgstr "Diagrammvorschau"
msgid "Preview payload"
msgstr "Vorschau der Nutzdaten"
msgid "Previous Artifacts"
-msgstr ""
+msgstr "Vorherige Artefakte"
msgid "Previous commit"
msgstr ""
@@ -29516,7 +29849,7 @@ msgid "ProductivityAnalytics|Trendline"
msgstr ""
msgid "ProductivityAnalytics|is earlier than the given merged at after date"
-msgstr ""
+msgstr "vor dem angegebenen Zusammenführungsdatum liegt"
msgid "Profile"
msgstr "Profil"
@@ -29570,7 +29903,7 @@ msgid "Profiles|An error occurred while updating your username, please try again
msgstr ""
msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
+msgstr "Neben deinem Namen und Avatar erscheint ein Indikator."
msgid "Profiles|Avatar cropper"
msgstr "Avatar zuschneiden"
@@ -29612,7 +29945,7 @@ msgid "Profiles|Connect %{provider}"
msgstr ""
msgid "Profiles|Connect a service for sign-in."
-msgstr "Profiles|Einen Dienst für die Anmeldung verbinden."
+msgstr ""
msgid "Profiles|Connected Accounts"
msgstr "Verbundene Konten"
@@ -29654,13 +29987,13 @@ msgid "Profiles|Enter how your name is pronounced to help people address you cor
msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you."
-msgstr ""
+msgstr "Gebe deinen Namen ein, damit Personen, die du kennst, dich erkennen können."
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 "Gebe deine Pronomen ein, damit die Leute wissen, wie sie sich auf dich beziehen können"
msgid "Profiles|Example: MacBook key"
msgstr ""
@@ -29693,7 +30026,7 @@ msgid "Profiles|Incoming email token was successfully reset"
msgstr ""
msgid "Profiles|Increase your account's security by enabling two-factor authentication (2FA)."
-msgstr "Profiles|Die Sicherheit deines Kontos erhöhen, indem du die Zwei-Faktor-Authentifizierung (2FA) aktivierst."
+msgstr "Die Sicherheit deines Kontos erhöhen, indem du die Zwei-Faktor-Authentifizierung (2FA) aktivierst."
msgid "Profiles|Invalid password"
msgstr "Ungültiges Kennwort"
@@ -29750,7 +30083,7 @@ msgid "Profiles|Position and size your new avatar"
msgstr "Lege Position und Größe deines neuen Avatars fest"
msgid "Profiles|Primary email"
-msgstr ""
+msgstr "Primäre E-Mail"
msgid "Profiles|Private contributions"
msgstr "Private Beiträge"
@@ -29759,10 +30092,10 @@ msgid "Profiles|Profile was successfully updated"
msgstr ""
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "Pronomen"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "Aussprache"
msgid "Profiles|Public avatar"
msgstr ""
@@ -29780,13 +30113,13 @@ msgid "Profiles|Select a service to sign in with."
msgstr ""
msgid "Profiles|Service sign-in"
-msgstr "Profiles|Dienstanmeldung"
+msgstr "Dienstanmeldung"
msgid "Profiles|Set new profile picture"
msgstr "Neues Profilbild festlegen"
msgid "Profiles|Set your local time zone."
-msgstr ""
+msgstr "Lege deine lokale Zeitzone fest."
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr "Einige Optionen sind für LDAP-Accounts nicht verfügbar"
@@ -29804,7 +30137,7 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "Die maximal zulässige Dateigröße beträgt 200KB."
msgid "Profiles|This email will be displayed on your public profile."
-msgstr ""
+msgstr "Diese E-Mail wird in deinem öffentlichen Profil angezeigt."
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 ""
@@ -29813,7 +30146,7 @@ msgid "Profiles|This emoji and message will appear on your profile and throughou
msgstr "Dieses Emoji und diese Nachricht werden in deinem Profil und auf der gesamten Benutzeroberfläche angezeigt."
msgid "Profiles|This information will appear on your profile."
-msgstr ""
+msgstr "Diese Informationen werden in deinem Profil angezeigt."
msgid "Profiles|Time settings"
msgstr "Zeiteinstellungen"
@@ -29822,7 +30155,7 @@ msgid "Profiles|Title"
msgstr ""
msgid "Profiles|Two-factor authentication"
-msgstr "Profiles|Zwei-Faktor-Authentifizierung"
+msgstr "Zwei-Faktor-Authentifizierung"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Gib deinen %{confirmationValue} zur Bestätigung ein:"
@@ -29852,7 +30185,7 @@ msgid "Profiles|Using emojis in names seems fun, but please try to set a status
msgstr ""
msgid "Profiles|Website url"
-msgstr ""
+msgstr "Webadresse"
msgid "Profiles|What's your status?"
msgstr "Was ist dein Status?"
@@ -29885,7 +30218,7 @@ msgid "Profiles|You must transfer ownership or delete these groups before you ca
msgstr "Du musst die Eigentumsrechte dieser Gruppen übertragen oder die Gruppen löschen, bevor du dein Konto löschen kannst."
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr ""
+msgstr "Dein LinkedIn-Profilname von linkedin.com/in/profilename"
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Dein Konto ist derzeit ein Besitzer in diesen Gruppen:"
@@ -29960,7 +30293,7 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "Das Projekt '%{project_name}' wurde erfolgreich aktualisiert."
msgid "Project '%{project_name}' will be deleted on %{date}"
-msgstr ""
+msgstr "Projekt '%{project_name}' wird am %{date} gelöscht"
msgid "Project Access Tokens"
msgstr ""
@@ -30076,6 +30409,9 @@ msgstr "Projekt-Slug"
msgid "Project uploads"
msgstr ""
+msgid "Project visibility level is less restrictive than the group settings."
+msgstr "Die Sichtbarkeitsebene des Projekts ist weniger restriktiv als die Gruppeneinstellungen."
+
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
@@ -30085,6 +30421,12 @@ 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 "Abonnieren"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -30311,7 +30662,7 @@ 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 ""
+msgstr "Löst ein Ereignis aus, wenn eine Zusammenführungsanforderung erstellt, aktualisiert oder zusammengeführt wird."
msgid "ProjectService|Trigger event when a new, unique alert is recorded."
msgstr ""
@@ -30899,7 +31250,7 @@ msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
msgstr ""
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
-msgstr ""
+msgstr "Dein externes Repository mit der Gitlab CI/CD verbinden"
msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
msgstr ""
@@ -30908,19 +31259,19 @@ 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 ""
+msgstr "Ein leeres Projekt erstellen, um unter anderem deine Dateien zu speichern, deine Arbeit zu planen und gemeinsam am Code zu arbeiten."
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
+msgstr "Ein Projekt erstellen, das mit den erforderlichen Dateien vorbelegt ist, damit du schnell loslegen kannst."
msgid "ProjectsNew|Create blank project"
-msgstr ""
+msgstr "Leeres Projekt anlegen"
msgid "ProjectsNew|Create from template"
-msgstr ""
+msgstr "Aus Vorlage erstellen"
msgid "ProjectsNew|Create new project"
-msgstr ""
+msgstr "Neues Projekt erstellen"
msgid "ProjectsNew|Description format"
msgstr ""
@@ -30941,7 +31292,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 "Deine Daten von einer externen Quelle wie GitHub, Bitbucket oder einer anderen Instanz von GitLab migrieren."
msgid "ProjectsNew|No import options available"
msgstr ""
@@ -30962,7 +31313,7 @@ msgid "ProjectsNew|Recommended if you're new to GitLab"
msgstr ""
msgid "ProjectsNew|Run CI/CD for external repository"
-msgstr ""
+msgstr "CI/CD für externes Repository ausführen"
msgid "ProjectsNew|Visibility Level"
msgstr ""
@@ -31247,7 +31598,7 @@ 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 "Promotions|Du kannst den Zugriff auf geschützte Branches einschränken, indem du eine Rolle (Betreuer, Entwickler) sowie bestimmte Benutzer auswählst."
+msgstr "Du kannst den Zugriff auf geschützte Branches einschränken, indem du eine Rolle (Betreuer, Entwickler) sowie bestimmte Benutzer auswählst."
msgid "Promotions|description templates"
msgstr ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} wird für Entwickler änderbar sein. Bist du sicher?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Für Bereitstellung zugelassen"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Umgebung"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+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 "Schützen"
@@ -31511,7 +31880,7 @@ msgid "Publish to status page"
msgstr ""
msgid "Published"
-msgstr ""
+msgstr "Veröffentlicht"
msgid "Published on status page"
msgstr ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr "Passwort wiederherstellen"
+
msgid "Recovery Codes"
msgstr ""
@@ -32002,14 +32374,11 @@ msgid "Rejected (closed)"
msgstr ""
msgid "Relate to %{issuable_type} %{add_related_issue_link}"
-msgstr ""
+msgstr "Bezug zu %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr "Ähnliche Vorfälle oder Probleme"
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "Release %{deletedRelease} wurde erfolgreich gelöscht."
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release."
msgstr ""
+msgid "Release|Something went wrong while deleting the release."
+msgstr "Beim Löschen des Releases ist ein Fehler aufgetreten."
+
msgid "Release|Something went wrong while getting the release details."
msgstr ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Avatar entfernen"
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "Entfernte Gruppe kann nicht wiederhergestellt werden!"
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Entfernt übergeordnetes Epic %{epic_ref}."
@@ -32471,6 +32831,9 @@ msgstr "Antworte direkt auf diese E-Mail oder %{view_it_on_gitlab}."
msgid "Reply…"
msgstr "Antworten…"
+msgid "Report Finding not found"
+msgstr "Berichtsergebnis nicht gefunden"
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 "Melde deine Lizenznutzungsdaten an GitLab"
@@ -32547,10 +32913,10 @@ msgid "Reports|Classname"
msgstr ""
msgid "Reports|Copy failed test names to run locally"
-msgstr "Reports|Namen fehlgeschlagener Tests kopieren, um sie lokal auszuführen"
+msgstr "Namen fehlgeschlagener Tests kopieren, um sie lokal auszuführen"
msgid "Reports|Copy failed tests"
-msgstr "Reports|Fehlgeschlagene Tests kopieren"
+msgstr "Fehlgeschlagene Tests kopieren"
msgid "Reports|Execution time"
msgstr "Ausführungszeit"
@@ -32640,6 +33006,9 @@ msgstr "Sicherheitslücke"
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "Keine geänderten Testergebnisse"
@@ -32828,20 +33197,11 @@ msgid "Request"
msgstr ""
msgid "Request Access"
-msgstr "Anfrage auf Zugriff"
+msgstr "Zugriff anfragen"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr "Aufmerksamkeit des Zuständigen oder Prüfers anfordern"
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr "Aufmerksamkeit von Beauftragten oder Prüfern anfordern"
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32952,7 +33300,7 @@ msgid "Requires you to deploy or set up cloud-hosted Sentry."
msgstr ""
msgid "Requires your primary GitLab email address."
-msgstr ""
+msgstr "Erfordert deine primäre GitLab-E-Mail-Adresse."
msgid "Resend"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32976,7 +33327,7 @@ msgid "Reset"
msgstr ""
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "Zugriffstoken für die Fehlerverfolgung zurücksetzen"
msgid "Reset file"
msgstr ""
@@ -33012,7 +33363,7 @@ msgid "Resolve these conflicts or ask someone with write access to this reposito
msgstr ""
msgid "Resolve thread"
-msgstr ""
+msgstr "Diskussion lösen"
msgid "Resolved"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr "Wiederholen"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33174,8 +33525,8 @@ msgstr ""
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Prüfer"
+msgstr[1] "%d Prüfer"
msgid "Reviewer(s)"
msgstr ""
@@ -33190,7 +33541,7 @@ msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr "Überprüfung (Merge-Request !%{mergeRequestId})"
msgid "Revoke"
-msgstr "Zurücknehmen"
+msgstr "Widerrufen"
msgid "Revoked"
msgstr ""
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr "Roadmap"
@@ -33226,7 +33571,7 @@ msgid "Roadmap view"
msgstr ""
msgid "Role"
-msgstr ""
+msgstr "Rolle"
msgid "Rollback"
msgstr ""
@@ -33247,10 +33592,10 @@ msgid "Run %{code_start}git fsck%{code_end} periodically in all project and wiki
msgstr ""
msgid "Run CI/CD pipelines for external repositories"
-msgstr "Führe CI/CD-Pipelines für externe Repositories aus"
+msgstr "CI/CD-Pipelines für externe Repositories ausführen"
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 "CI/CD-Pipelines mit Jenkins ausführen, wenn du in ein Repository pushst oder eine Zusammenführungsanforderung erstellst, aktualisierst oder zusammengeführt wird. %{docs_link}"
msgid "Run CI/CD pipelines with Jenkins."
msgstr ""
@@ -33291,6 +33636,11 @@ msgstr ""
msgid "Runners page."
msgstr "Runners-Seite."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr "Verfügbar"
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr "Empfohlen"
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|Up to date"
+msgstr "Aktuell"
+
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 "Upgrade-Status"
+
msgid "Runners|Upgrade available"
msgstr ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr "Upgrade verfügbar"
msgid "Runners|upgrade recommended"
msgstr "Upgrade empfohlen"
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "Laufend"
@@ -33800,7 +34180,7 @@ msgid "SAML for %{group_name}"
msgstr ""
msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
-msgstr ""
+msgstr "Wenn du \"Autorisieren\" auswählen, wird die Inhaberschaft deines GitLab-Kontos \"%{username}\" (%{email}) auf deiner Organisation übertragen."
msgid "SAML|Sign in to GitLab to connect your organization's account"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ msgstr "SSH-Schlüssel"
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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34088,13 +34489,13 @@ msgid "Search or create tag"
msgstr ""
msgid "Search or filter results..."
-msgstr "Suche oder filtere Ergebnisse..."
+msgstr "Ergebnisse suchen oder filtern..."
msgid "Search or filter results…"
-msgstr "Suchen oder Ergebnisse filtern…"
+msgstr "Ergebnisse suchen oder filtern…"
msgid "Search page"
-msgstr ""
+msgstr "Seite durchsuchen"
msgid "Search project"
msgstr "Projekt suchen"
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr "Sicherheits-Dashboard"
+msgid "Security Finding not found"
+msgstr "Sicherheitsergebnis nicht gefunden"
+
msgid "Security dashboard"
msgstr ""
@@ -34467,7 +34877,7 @@ msgid "SecurityOrchestration|+%{count} more"
msgstr ""
msgid "SecurityOrchestration|, and %{count} more"
-msgstr "SecurityOrchestration|, und %{count} mehr"
+msgstr ", und %{count} mehr"
msgid "SecurityOrchestration|.yaml mode"
msgstr ""
@@ -34530,7 +34940,7 @@ msgid "SecurityOrchestration|Description"
msgstr ""
msgid "SecurityOrchestration|Direct"
-msgstr "SecurityOrchestration|Direkt"
+msgstr "Direkt"
msgid "SecurityOrchestration|Don't show the alert anymore"
msgstr ""
@@ -34559,11 +34969,17 @@ 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 "SecurityOrchestration|Vererbt"
+msgstr "Vererbt"
msgid "SecurityOrchestration|Inherited from %{namespace}"
msgstr ""
@@ -34701,7 +35117,7 @@ msgid "SecurityOrchestration|Something went wrong, unable to fetch policies"
msgstr ""
msgid "SecurityOrchestration|Sorry, your filter produced no results."
-msgstr "SecurityOrchestration|Dein Filter hat leider keine Ergebnisse geliefert."
+msgstr "Dein Filter hat leider keine Ergebnisse geliefert."
msgid "SecurityOrchestration|Source"
msgstr ""
@@ -34724,6 +35140,9 @@ msgstr ""
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "Dieser %{namespaceType} enthält keine Sicherheitsrichtlinien."
+
msgid "SecurityOrchestration|This group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ msgstr ""
msgid "SecurityReports|Operational vulnerabilities"
msgstr ""
+msgid "SecurityReports|Parsing errors and warnings in pipeline"
+msgstr "Analysieren von Fehlern und Warnungen in der Pipeline"
+
+msgid "SecurityReports|Parsing errors in pipeline"
+msgstr "Parsing-Fehler in der Pipeline"
+
+msgid "SecurityReports|Parsing warnings in pipeline"
+msgstr "Parsing-Warnungen in der Pipeline"
+
msgid "SecurityReports|Project"
msgstr ""
@@ -35004,7 +35432,7 @@ msgid "SecurityReports|Sometimes a scanner can't determine a finding's severity.
msgstr ""
msgid "SecurityReports|Sorry, your filter produced no results"
-msgstr "SecurityReports|Leider hat dein Filter keine Ergebnisse geliefert"
+msgstr "Leider hat dein Filter keine Ergebnisse geliefert"
msgid "SecurityReports|Status"
msgstr ""
@@ -35052,10 +35480,10 @@ 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 ""
+msgstr "Diese Schwachstellen wurden in externen Quellen entdeckt. Sie sind nicht unbedingt an dein GitLab-Projekt gebunden. Beispielsweise das Ausführen von Containern, URLs usw."
msgid "SecurityReports|To widen your search, change or remove filters above"
-msgstr "SecurityReports|Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
+msgstr "Um deine Suche zu erweitern, änder oder entferne die obigen Filter."
msgid "SecurityReports|Tool"
msgstr ""
@@ -35145,7 +35573,7 @@ msgid "Select a branch to compare"
msgstr ""
msgid "Select a color"
-msgstr ""
+msgstr "Wähle eine Farbe"
msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
msgstr ""
@@ -35181,7 +35609,7 @@ msgid "Select a template type"
msgstr ""
msgid "Select a time zone"
-msgstr ""
+msgstr "Zeitzone auswählen"
msgid "Select a timezone"
msgstr "Zeitzone auswählen"
@@ -35247,7 +35675,7 @@ msgid "Select project to create %{type}"
msgstr ""
msgid "Select project to create issue"
-msgstr "Projekt auswählen, um ein Problem zu erstellen"
+msgstr ""
msgid "Select projects"
msgstr ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35376,7 +35801,7 @@ msgid "Send email notification"
msgstr ""
msgid "Send emails to help guide new users through the onboarding process."
-msgstr ""
+msgstr "E-Mails senden, um neue Benutzer durch den Onboarding-Prozess zu führen."
msgid "Send emails to users upon account deactivation."
msgstr ""
@@ -35478,7 +35903,7 @@ msgid "ServiceDesk|To enable Service Desk on this instance, an instance administ
msgstr ""
msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
-msgstr ""
+msgstr "Verwende Service Desk, um dich mit deinen Benutzern zu verbinden und Kundensupport per E-Mail direkt in GitLab anzubieten"
msgid "ServiceDesk|Your users can send emails to this address:"
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr "Dienste"
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Lege ein Passwort für dein Konto fest, um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr "Anmeldung fehlgeschlagen, weil %{error}."
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr "Anmeldebeschränkungen"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr "Anmeldung mit %{provider}-Authentifizierung fehlgeschlagen"
+
msgid "Sign-out page URL"
msgstr ""
@@ -36124,16 +36549,16 @@ msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
msgstr ""
msgid "Signed in"
-msgstr ""
+msgstr "Angemeldet"
msgid "Signed in to GitLab"
-msgstr ""
+msgstr "Bei GitLab angemeldet"
msgid "Signed in to GitLab as %{user_link}"
-msgstr ""
+msgstr "Bei GitLab als %{user_link} angemeldet"
msgid "Signed in with %{authentication} authentication"
-msgstr ""
+msgstr "Mit %{authentication} Authentifizierung angemeldet"
msgid "Signing in using %{label} has been disabled"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -36553,7 +36975,7 @@ msgid "Sort by"
msgstr "Sortieren nach"
msgid "Sort direction"
-msgstr ""
+msgstr "Richtung der Sortierung"
msgid "Sort direction: Ascending"
msgstr ""
@@ -36613,7 +37035,7 @@ msgid "SortOptions|Manual"
msgstr ""
msgid "SortOptions|Merged date"
-msgstr ""
+msgstr "Zusammenführungsdatum"
msgid "SortOptions|Merged earlier"
msgstr ""
@@ -36781,7 +37203,7 @@ 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 "Konfiguriere die URL zu einer Sourcegraph-Instanz, die deine GitLab-Projekte lesen kann."
msgid "SourcegraphAdmin|Enable Sourcegraph"
msgstr ""
@@ -37150,7 +37572,7 @@ 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 ""
+msgstr "Bleibe über die Leistung und den Zustand Ihrer Umgebung auf dem Laufenden, indem du Prometheus für die Überwachung deiner Bereitstellungen konfigurierst."
msgid "Step %{currentStep} of %{stepCount}"
msgstr ""
@@ -37285,7 +37707,7 @@ msgid "Subscribe at project level"
msgstr "Abonniere auf Projektebene"
msgid "Subscribe to RSS feed"
-msgstr ""
+msgstr "RSS-Feed abonnieren"
msgid "Subscribe to calendar"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr "Erfolgreich"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37636,7 +38055,7 @@ msgid "SuperSonics|Buy subscription"
msgstr ""
msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr ""
+msgstr "Die Instanz kann aufgrund eines Verbindungsproblems nicht aktiviert werden."
msgid "SuperSonics|Cloud licensing"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr "Systemmetriken (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr "System gestartet"
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr "Abbrechen"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr "Release erstellen"
+
msgid "TagsPage|Create tag"
msgstr "Tag erstellen"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Versionshinweise bearbeiten"
+msgid "TagsPage|Edit release"
+msgstr "Release bearbeiten"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Existierender Branch, Tag oder Commit-SHA"
@@ -38007,7 +38429,7 @@ msgid "TagsPage|New tag"
msgstr "Neuer Tag"
msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
-msgstr "TagsPage|Nur ein Projektbetreuer oder -besitzer kann ein geschütztes Tag löschen"
+msgstr "Nur ein Projektbetreuer oder -besitzer kann ein geschütztes Tag löschen"
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
msgstr ""
@@ -38025,7 +38447,7 @@ msgid "TagsPage|Repository has no tags yet."
msgstr "Repository hat noch keine Tags."
msgid "TagsPage|Sorry, your filter produced no results."
-msgstr "TagsPage|Dein Filter hat leider keine Ergebnisse geliefert."
+msgstr "Dein Filter hat leider keine Ergebnisse geliefert."
msgid "TagsPage|Tags"
msgstr "Tags"
@@ -38079,7 +38501,7 @@ msgid "Target roles"
msgstr ""
msgid "Target-Branch"
-msgstr ""
+msgstr "Zielbranch"
msgid "Task"
msgstr ""
@@ -38088,10 +38510,7 @@ msgid "Task ID: %{elastic_task}"
msgstr ""
msgid "Task list"
-msgstr ""
-
-msgid "Task with ID: %{id} could not be found."
-msgstr "Aufgabe mit ID: %{id} konnte nicht gefunden werden."
+msgstr "Aufgabenliste"
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38442,7 +38861,7 @@ msgid "TestReports|Attachment"
msgstr ""
msgid "TestReports|Copy test name to rerun locally"
-msgstr "TestReports|Testnamen kopieren, um ihn lokal erneut auszuführen"
+msgstr "Testnamen kopieren, um ihn lokal erneut auszuführen"
msgid "TestReports|Job artifacts are expired"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Vielen Dank für deine Meldung. Ein:e GitLab-Admin wird sich der Sache in Kürze widmen."
@@ -38537,7 +38953,7 @@ 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 ""
+msgstr "Der CSV-Export wird im Hintergrund erstellt. Wenn du fertig bist, wird es in einem Anhang an %{email} gesendet."
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 ""
@@ -38739,10 +39155,10 @@ msgid "The group and any internal projects can be viewed by any logged in user e
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "Die Gruppe und alle öffentlichen Projekte können ohne Authentifizierung gesehen werden."
msgid "The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "Die Gruppe und ihre Projekte können nur von Mitgliedern gesehen werden."
msgid "The group export can be downloaded from:"
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -38973,7 +39389,7 @@ 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 ""
+msgstr "Das Quellprojekt dieser Zusammenführungsanforderung wurde entfernt."
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ msgstr "Dieses Verzeichnis"
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 ""
@@ -39648,7 +40064,7 @@ 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 ""
+msgstr "Diese Einladung wurde an %{mail_to_invite_email} gesendet, doch du bist als %{link_to_current_user} mit der E-Mail-Adresse %{mail_to_current_user} angemeldet."
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 ""
@@ -39663,7 +40079,7 @@ msgid "This is a delayed job to run in %{remainingTime}"
msgstr "Dies ist ein in %{remainingTime} auszuführender verzögerter Job"
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
-msgstr ""
+msgstr "Dies ist eine Liste der Geräte, die sich bei deinem Konto angemeldet haben. Widerrufe alle Sitzungen, die du nicht erkennst."
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 ""
@@ -39684,7 +40100,7 @@ msgid "This is the number of %{billable_users_link_start}billable users%{link_en
msgstr ""
msgid "This is your current session"
-msgstr ""
+msgstr "Dies ist deine aktuelle Sitzung"
msgid "This issue cannot be assigned to a confidential epic because it is public."
msgstr ""
@@ -39693,7 +40109,7 @@ msgid "This issue cannot be made public because it belongs to a confidential epi
msgstr ""
msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
-msgstr "Dieses Problem ist vertraulich und sollte nur für Teammitglieder mit mindestens Reporter-Zugriff sichtbar sein."
+msgstr ""
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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."
+
+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 "Dieses Repository"
@@ -39981,7 +40403,7 @@ msgid "This user has the %{access} role in the %{name} project."
msgstr ""
msgid "This user is the author of this %{noteable}."
-msgstr ""
+msgstr "Dieser Benutzer ist der Autor dieses/dieser/diesem %{noteable}."
msgid "This variable can not be masked."
msgstr ""
@@ -40074,7 +40496,7 @@ msgid "Time until first merge request"
msgstr "Zeit bis zum ersten Merge-Request"
msgid "Time zone"
-msgstr ""
+msgstr "Zeitzone"
msgid "TimeTrackingEstimated|Est"
msgstr "Geschätzt"
@@ -40113,7 +40535,7 @@ msgid "Timeago|%s hours remaining"
msgstr "%s Stunden verbleibend"
msgid "Timeago|%s minutes ago"
-msgstr "Timeago|vor %s Minuten"
+msgstr "vor %s Minuten"
msgid "Timeago|%s minutes remaining"
msgstr "%s Minuten verbleibend"
@@ -40229,6 +40651,9 @@ 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 "Zeitüberschreitung"
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40465,7 +40887,7 @@ 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 ""
+msgstr "Um alle %{scannedResourcesCount} gescannten URLs anzuzeigen, %{linkStart}lade bitte die CSV-Datei herunter%{linkEnd}"
msgid "To view usage, refresh this page in a few minutes."
msgstr ""
@@ -40510,7 +40932,7 @@ msgid "Todos|Mark all as done"
msgstr ""
msgid "Todos|Nothing is on your to-do list. Nice work!"
-msgstr ""
+msgstr "Nichts steht auf Ihrer To-do-Liste. Gute Arbeit!"
msgid "Todos|Undo mark all as done"
msgstr ""
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40909,7 +41334,7 @@ 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 ""
+msgstr "Vertrauenswürdige Anwendungen werden automatisch im GitLab OAuth-Flow autorisiert. Für die Sicherheit der Benutzer wird dringend empfohlen, dass bei vertrauenswürdigen Anwendungen die Einstellung \"Vertraulich\" auf \"true\" gesetzt ist."
msgid "Try again"
msgstr "Wiederholen"
@@ -40929,6 +41354,9 @@ 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 "Versuche, dich mit deinem Benutzernamen oder deiner E-Mail-Adresse anzumelden. Wenn du dein Passwort vergessen hast, versuche es wiederherzustellen"
+
msgid "Try out GitLab Pipelines"
msgstr ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Typ"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41035,7 +41466,7 @@ 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 ""
+msgstr "Die URL wird ausgelöst, wenn eine Zusammenführungsanforderung erstellt, aktualisiert oder zusammengeführt wird"
msgid "URL is triggered when a new tag is pushed to the repository"
msgstr ""
@@ -41133,6 +41564,9 @@ msgstr "Der Diff konnten nicht geladen werden. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "Das Merge-Request-Widget konnte nicht geladen werden. Versuchen Sie die Seite neu zu laden."
+msgid "Unable to parse JSON"
+msgstr ""
+
msgid "Unable to parse the vulnerability report's options."
msgstr "Die Optionen des Schwachstellenberichts können nicht analysiert werden."
@@ -41196,6 +41630,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
+msgid "Unban"
+msgstr "Entsperren"
+
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41419,10 +41853,10 @@ msgid "UpdateProject|Project could not be updated!"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
-msgstr ""
+msgstr "Repository-Prüfsumme von %{type} konnte nicht von %{old} bis %{new} verifiziert werden"
msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
-msgstr ""
+msgstr "Zeitüberschreitung beim Warten auf %{type}-Repository-Pushs"
msgid "Updated"
msgstr "Aktualisiert"
@@ -41436,9 +41870,6 @@ msgstr "Aktualisiert am"
msgid "Updating"
msgstr "Aktualisiere"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41455,7 +41886,7 @@ msgid "Upload CSV file"
msgstr ""
msgid "Upload File"
-msgstr ""
+msgstr "Datei hochladen"
msgid "Upload New File"
msgstr "Neue Datei hochladen"
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Datei hochladen"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr "Uptime"
-
msgid "Upvotes"
msgstr "Upvotes"
@@ -41521,7 +41952,7 @@ msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
msgstr ""
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
-msgstr ""
+msgstr "Hörbeispiele, Videos, Datensätze und Grafiken."
msgid "UsageQuota|Buy additional minutes"
msgstr ""
@@ -41553,14 +41984,14 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Git-Repository."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
msgstr ""
@@ -41569,7 +42000,7 @@ msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker
msgstr ""
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
-msgstr ""
+msgstr "Umfasst Artefakte, Repositories, Wiki, Uploads und andere Elemente."
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
@@ -41581,10 +42012,10 @@ msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
-msgstr ""
+msgstr "Mehr über Nutzungsquoten erfahren"
msgid "UsageQuota|Learn more about usage quotas."
-msgstr ""
+msgstr "Mehr über Nutzungsquoten erfahren."
msgid "UsageQuota|Local proxy used for frequently-accessed upstream Docker images. %{linkStart}More information%{linkEnd}"
msgstr ""
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41650,11 +42084,23 @@ msgid "UsageQuota|Storage"
msgstr ""
msgid "UsageQuota|Storage type"
-msgstr ""
+msgstr "Speichertyp"
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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41695,10 +42141,10 @@ msgid "UsageQuota|Usage"
msgstr ""
msgid "UsageQuota|Usage Quotas"
-msgstr ""
+msgstr "Nutzungsquoten"
msgid "UsageQuota|Usage breakdown"
-msgstr ""
+msgstr "Nutzungsaufschlüsselung"
msgid "UsageQuota|Usage by month"
msgstr ""
@@ -41707,16 +42153,16 @@ 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 ""
+msgstr "Nutzung von Gruppenressourcen in den Projekten in der Gruppe %{strong_start}%{group_name}%{strong_end}"
msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project"
-msgstr ""
+msgstr "Nutzung von Projektressourcen im gesamten Projekt %{strong_start}%{project_name}%{strong_end}"
msgid "UsageQuota|Usage of resources across your projects"
-msgstr ""
+msgstr "Nutzung von Ressourcen in deinen Projekten"
msgid "UsageQuota|Usage quotas help link"
-msgstr ""
+msgstr "Hilfelink zu Nutzungsquoten"
msgid "UsageQuota|Usage since %{usageSince}"
msgstr ""
@@ -41884,7 +42330,7 @@ msgid "Use one line per URI"
msgstr "Verwende eine Zeile pro URI"
msgid "Use primary email (%{email})"
-msgstr ""
+msgstr "Primäre E-Mail-Adresse verwenden (%{email})"
msgid "Use shortcuts"
msgstr ""
@@ -41908,7 +42354,7 @@ msgid "Use the public cloud instance URL (%{kroki_public_url}) or %{install_link
msgstr ""
msgid "Use the search bar on the top of this page"
-msgstr ""
+msgstr "Verwende die Suchleiste oben auf dieser Seite"
msgid "Use this token to validate received payloads."
msgstr ""
@@ -41925,6 +42371,11 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "Wird von %d Paket verwendet"
+msgstr[1] "Wird von %d Paketen verwendet"
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Wird von Mitgliedern verwendet, um sich in GitLab in deiner Gruppe anzumelden"
@@ -41950,7 +42401,7 @@ msgid "User %{user} was removed from %{group}."
msgstr ""
msgid "User ID"
-msgstr ""
+msgstr "Benutzer ID"
msgid "User OAuth applications"
msgstr ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "Benutzer(in) wurde erfolgreich von dem Projekt entfernt."
+msgid "User was successfully unbanned."
+msgstr "Benutzer wurde erfolgreich entsperrt."
+
msgid "User was successfully updated."
msgstr "Benutzer:in erfolgreich aktualisiert."
@@ -42124,7 +42578,10 @@ msgid "UserProfile|Bot activity"
msgstr ""
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "Projektbeteiligungen"
+
+msgid "UserProfile|Copy user ID"
+msgstr "Benutzer-ID kopieren"
msgid "UserProfile|Edit profile"
msgstr "Profil bearbeiten"
@@ -42160,7 +42617,7 @@ msgid "UserProfile|Personal projects"
msgstr "Persönliche Projekte"
msgid "UserProfile|Pronounced as: %{pronunciation}"
-msgstr ""
+msgstr "Ausgesprochen als: %{pronunciation}"
msgid "UserProfile|Report abuse"
msgstr "Missbrauch melden"
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr "Benutzer-ID: %{id}"
+
msgid "UserProfile|View all"
msgstr "Alles anzeigen"
@@ -42238,7 +42698,7 @@ msgid "UserProfile|made a private contribution"
msgstr ""
msgid "Username"
-msgstr ""
+msgstr "Benutzername"
msgid "Username (optional)"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -42524,6 +42985,12 @@ msgstr "Konfiguration verifizieren"
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 ""
+
+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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43212,7 +43682,7 @@ msgid "We'll continuously validate your pipeline configuration. The validation r
msgstr ""
msgid "We'll use this to help surface the right features and information to you."
-msgstr ""
+msgstr "Wir verwenden dies, um dir die richtigen Funktionen und Informationen anzuzeigen."
msgid "We're experiencing difficulties and this tab content is currently unavailable."
msgstr ""
@@ -43245,7 +43715,7 @@ msgid "WebIDE|Fork project"
msgstr ""
msgid "WebIDE|Go to fork"
-msgstr ""
+msgstr "Zum Fork gehen"
msgid "WebIDE|Merge request"
msgstr ""
@@ -43257,10 +43727,10 @@ msgid "WebIDE|This project does not accept unsigned commits. You can’t commit
msgstr ""
msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "Du kannst Dateien in diesem Projekt nicht direkt bearbeiten. Verzweige dieses Projekt und reiche eine Zusammenführungsanfrage mit deinen Änderungen ein."
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 "Du kannst Dateien in diesem Projekt nicht direkt bearbeiten. Gehe zu deinem Fork und reiche eine Merge-Anfrage mit deinen Änderungen ein."
msgid "WebIDE|You need permission to edit files directly in this project."
msgstr ""
@@ -43317,7 +43787,7 @@ msgid "Webhooks|A job's status changes."
msgstr ""
msgid "Webhooks|A merge request is created, updated, or merged."
-msgstr ""
+msgstr "Eine Zusammenführungsanforderung wird erstellt, aktualisiert oder zusammengeführt."
msgid "Webhooks|A new tag is pushed to the repository."
msgstr ""
@@ -43490,9 +43960,15 @@ msgstr ""
msgid "What are project audit events?"
msgstr ""
-msgid "What does this command do?"
+msgid "What are some examples?"
msgstr ""
+msgid "What does the setting affect?"
+msgstr ""
+
+msgid "What does this command do?"
+msgstr "Was bewirkt dieser Befehl?"
+
msgid "What is Markdown?"
msgstr ""
@@ -43509,7 +43985,7 @@ msgid "What templates can I create?"
msgstr ""
msgid "What will you use this group for?"
-msgstr ""
+msgstr "Wofür wirst du diese Gruppe verwenden?"
msgid "What would you like to do?"
msgstr "Was möchtest du gerne tun?"
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43577,7 +44058,7 @@ msgid "Who will be using this GitLab trial?"
msgstr ""
msgid "Who will be using this group?"
-msgstr ""
+msgstr "Wer wird diese Gruppe verwenden?"
msgid "Why are you signing up? (optional)"
msgstr ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,23 +44297,29 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
-msgstr ""
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "Eine Aufgabe bietet die Möglichkeit, deine Arbeit in kleinere Teile zu zerlegen, die mit einem Problem verbunden sind. Aufgaben sind die ersten Elemente, die unsere neuen %{workItemsLink}-Objekte verwenden. Weitere Arbeitselementtypen werden in Kürze verfügbar sein."
+
+msgid "WorkItem|Add a task"
+msgstr "EIne Aufgabe hinzufügen"
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
-msgstr "WorkItem|Beauftragte(n) hinzufügen"
+msgstr "Beauftragte(n) hinzufügen"
msgid "WorkItem|Add assignees"
-msgstr "WorkItem|Beauftragte hinzufügen"
+msgstr "Beauftragte hinzufügen"
+
+msgid "WorkItem|Add task"
+msgstr "Aufgabe hinzufügen"
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr ""
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
-msgstr ""
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "Möchtest du die Aufgabe wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden."
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
-msgstr ""
+msgid "WorkItem|Delete task"
+msgstr "Aufgabe löschen"
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr "Aufgaben vorstellen"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "Aufgaben kennenlernen"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "Beim Erstellen einer Aufgabe ist etwas schiefgelaufen. Bitte erneut versuchen"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "Beim Löschen der Aufgabe ist etwas schief gelaufen. Bitteerneut versuchen"
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 "Beim Versuch, ein child hinzuzufügen, ist ein Fehler aufgetreten. Bitte erneut versuchen."
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr "Aufgabe gelöscht"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr "Arbeitsgegenstände"
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44007,7 +44533,7 @@ msgid "You are going to remove %{group_name}. This will also delete all of its s
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Du wirst die Fork-Beziehung von %{project_full_name} entfernen. Bist du dir ABSOLUT sicher?"
msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
@@ -44177,18 +44703,17 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "Du kannst ein neues Mitglied oder eine andere Gruppe zu %{project_name} einladen."
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44202,7 +44727,7 @@ msgid "You can now close this window."
msgstr ""
msgid "You can now export your security dashboard to a CSV report."
-msgstr ""
+msgstr "Du kannst dein Sicherheits-Dashboard jetzt in einen CSV-Bericht exportieren."
msgid "You can now submit a merge request to get this change into the original branch."
msgstr ""
@@ -44243,7 +44768,7 @@ msgstr "Du kannst deine .gitlab-ci.yml mit %{linkStart}CI Lint%{linkEnd} testen.
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr "Du hast noch keine Abonnements"
@@ -44525,7 +45043,7 @@ 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 "Du musst zuerst deine primäre E-Mail-Adresse bestätigen, bevor du die Zwei-Faktor-Authentifizierung aktivierst."
msgid "You successfully declined the invitation"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,14 +45165,11 @@ msgstr "Du hast %{user} abgelehnt"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
msgid "Your %{host} account was signed in to from a new location"
-msgstr ""
+msgstr "Dein %{host}-Konto wurde von einem neuen Standort aus angemeldet"
msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44669,13 +45187,13 @@ msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more detail
msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
-msgstr ""
+msgstr "Dein CSV-Export hat begonnen. Es wird nach Abschluss per E-Mail an %{email} gesendet."
msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "Der CSV-Export von %{count} aus dem Projekt %{project_link} wurde dieser E-Mail als Anhang hinzugefügt."
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
-msgstr ""
+msgstr "Der CSV-Export von %{written_count} aus dem Projekt %{project_name} (%{project_url}) wurde dieser E-Mail als Anhang hinzugefügt."
msgid "Your CSV import for project"
msgstr ""
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 "Deine Gruppen"
@@ -44894,7 +45422,7 @@ 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 ""
+msgstr "Deine primäre E-Mail-Adresse wird für die Avatar-Erkennung verwendet. Du kannst es in deinen %{openingTag}Profileinstellungen%{closingTag} ändern."
msgid "Your profile"
msgstr ""
@@ -44912,7 +45440,7 @@ msgid "Your projects"
msgstr "Deine Projekte"
msgid "Your public email will be displayed on your public profile."
-msgstr ""
+msgstr "Deine öffentliche E-Mail-Adresse wird in deinem öffentlichen Profil angezeigt."
msgid "Your request for access could not be processed: %{error_message}"
msgstr ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr "Deine Suche hat keine Commits gefunden."
@@ -44945,7 +45470,7 @@ msgid "Your sign-in page is %{url}."
msgstr ""
msgid "Your snippets"
-msgstr ""
+msgstr "Deine Codeausschnitte"
msgid "Your subscription expired!"
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 "Deine Aktualisierung ist fehlgeschlagen. Du kannst nur ein Design hochladen, wenn du es auf ein vorhandenes Design ziehst."
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr "%{reportType}: Beim Laden trat ein Fehler auf"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,9 +46116,12 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
-msgid "closed"
+msgid "ci_database"
msgstr ""
+msgid "closed"
+msgstr "geschlossen"
+
msgid "closed %{timeago}"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr "überschreitet die maximale Länge (100 Benutzernamen)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45757,7 +46301,7 @@ msgid "expires on %{timebox_due_date}"
msgstr ""
msgid "failed"
-msgstr ""
+msgstr "fehlgeschlagen"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "Gruppen"
@@ -45876,6 +46417,9 @@ msgstr "https://dein-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr "Bildunterschied"
@@ -45984,7 +46528,7 @@ msgid "is too long (maximum is 1000 entries)"
msgstr "ist zu lang (mehr als 1000 Einträge)"
msgid "issue"
-msgstr "Problem"
+msgstr ""
msgid "issues at risk"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "gesperrt durch %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "manuell"
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 Merge-Commit"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46212,14 +46753,11 @@ msgstr[0] ""
msgstr[1] ""
msgid "mrWidget|Create issue to resolve all threads"
-msgstr "mrWidget|Problem erstellen, um alle Threads zu lösen"
+msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Quellbranch löschen"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Bereitstellungsstatistiken derzeit nicht verfügbar"
@@ -46229,9 +46767,6 @@ msgstr "Wurde nicht geschlossen"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Fehler beim Laden der Bereitstellungsstatistiken"
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "Merge"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Merged von"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Die Änderungen wurden gemerged nach"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Die Änderungen wurden nicht gemerged nach"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Der Quellbranch wurde gelöscht"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Der Quellbranch wird gerade gelöscht"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
@@ -46475,7 +46992,7 @@ msgid "must match %{association}.project_id"
msgstr ""
msgid "my-awesome-group"
-msgstr ""
+msgstr "meine-tolle-gruppe"
msgid "my-channel"
msgstr ""
@@ -46538,7 +47055,7 @@ msgid "on track"
msgstr ""
msgid "only %{parent_types} can be parent of Task."
-msgstr ""
+msgstr "nur %{parent_types} kann der Aufgabe übergeordnet sein."
msgid "only Task can be assigned as a child in hierarchy."
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
msgid "security Reports|There was an error creating the merge request"
msgstr "Fehler während der Merge-Request-Erstellung"
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr ""
+
msgid "severity|Blocker"
msgstr ""
@@ -46844,14 +47367,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "die folgenden Ticket(s)"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr ""
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "ausgelöst"
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 3cedef347ad..faef3f3d1d6 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/en_GB/gitlab.po b/locale/en_GB/gitlab.po
index c3cef09f041..adb778cec8f 100644
--- a/locale/en_GB/gitlab.po
+++ b/locale/en_GB/gitlab.po
@@ -14,766 +14,775 @@ 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:08\n"
msgid " %{start} to %{end}"
-msgstr ""
+msgstr " %{start} to %{end}"
msgid " (from %{timeoutSource})"
-msgstr ""
+msgstr " (from %{timeoutSource})"
msgid " Collected %{time}"
-msgstr ""
+msgstr " Collected %{time}"
msgid " Please sign in."
-msgstr ""
+msgstr " Please sign in."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Try to %{action} this file again."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " You need to do this before %{grace_period_deadline}."
msgid " and "
-msgstr ""
+msgstr " and "
msgid " and %{sliced}"
-msgstr ""
+msgstr " and %{sliced}"
msgid " or "
-msgstr ""
+msgstr " or "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgid " or %{emphasisStart}#id%{emphasisEnd}"
-msgstr ""
+msgstr " or %{emphasisStart}#id%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr " or %{emphasisStart}#issue id%{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr " or %{emphasisStart}&epic id%{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
-msgstr ""
+msgstr " or references (e.g. path/to/project!merge_request_id)"
msgid " reacted with :%{name}:"
-msgstr ""
+msgstr " reacted with :%{name}:"
msgid "\"%{path}\" did not exist on \"%{ref}\""
-msgstr ""
+msgstr "\"%{path}\" did not exist on \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (closed)"
msgid "#general, #development"
-msgstr ""
+msgstr "#general, #development"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alert"
+msgstr[1] "%d Alerts"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alert:"
+msgstr[1] "%d Alerts:"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Approval"
+msgstr[1] "%d Approvals"
msgid "%d Module"
msgid_plural "%d Modules"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Module"
+msgstr[1] "%d Modules"
msgid "%d Other"
msgid_plural "%d Others"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Other"
+msgstr[1] "%d Others"
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Package"
+msgstr[1] "%d Packages"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Scanned URL"
+msgstr[1] "%d Scanned URLs"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d URL scanned"
+msgstr[1] "%d URLs scanned"
msgid "%d additional approver"
msgid_plural "%d additional approvers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d additional approver"
+msgstr[1] "%d additional approvers"
msgid "%d additional assignee"
msgid_plural "%d additional assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d additional assignee"
+msgstr[1] "%d additional assignees"
msgid "%d additional commenter"
msgid_plural "%d additional commenters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d additional commenter"
+msgstr[1] "%d additional commenters"
msgid "%d additional committer"
msgid_plural "%d additional committers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d additional committer"
+msgstr[1] "%d additional committers"
msgid "%d approver"
msgid_plural "%d approvers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d approver"
+msgstr[1] "%d approvers"
msgid "%d approver (you've approved)"
msgid_plural "%d approvers (you've approved)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d approver (you've approved)"
+msgstr[1] "%d approvers (you've approved)"
msgid "%d assigned issue"
msgid_plural "%d assigned issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d assigned issue"
+msgstr[1] "%d assigned issues"
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d changed file"
+msgstr[1] "%d changed files"
msgid "%d character remaining"
msgid_plural "%d characters remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d character remaining"
+msgstr[1] "%d characters remaining"
msgid "%d child epic"
msgid_plural "%d child epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d child epic"
+msgstr[1] "%d child epics"
msgid "%d code quality issue"
msgid_plural "%d code quality issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d code quality issue"
+msgstr[1] "%d code quality issues"
msgid "%d comment"
msgid_plural "%d comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d comment"
+msgstr[1] "%d comments"
msgid "%d comment on this commit"
msgid_plural "%d comments on this commit"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d comment on this commit"
+msgstr[1] "%d comments on this commit"
msgid "%d commenter"
msgid_plural "%d commenters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commenter"
+msgstr[1] "%d commenters"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit"
+msgstr[1] "%d commits"
msgid "%d commit author"
msgid_plural "%d commit authors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit author"
+msgstr[1] "%d commit authors"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit behind"
+msgstr[1] "%d commits behind"
msgid "%d commit,"
msgid_plural "%d commits,"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commit,"
+msgstr[1] "%d commits,"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d completed issue"
+msgstr[1] "%d completed issues"
msgid "%d contribution"
msgid_plural "%d contributions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d contribution"
+msgstr[1] "%d contributions"
msgid "%d day"
msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d day"
+msgstr[1] "%d days"
msgid "%d epic"
msgid_plural "%d epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d epic"
+msgstr[1] "%d epics"
msgid "%d error"
msgid_plural "%d errors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d error"
+msgstr[1] "%d errors"
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d exporter"
+msgstr[1] "%d exporters"
msgid "%d failed"
msgid_plural "%d failed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d failed"
+msgstr[1] "%d failed"
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d failed security job"
+msgstr[1] "%d failed security jobs"
msgid "%d file"
msgid_plural "%d files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d file"
+msgstr[1] "%d files"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fixed test result"
+msgstr[1] "%d fixed test results"
msgid "%d fork"
msgid_plural "%d forks"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fork"
+msgstr[1] "%d forks"
msgid "%d group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d group"
+msgstr[1] "%d groups"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d hour"
+msgstr[1] "%d hours"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d inaccessible merge request"
+msgstr[1] "%d inaccessible merge requests"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d issue"
+msgstr[1] "%d issues"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d issue in this group"
+msgstr[1] "%d issues in this group"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d issue successfully imported with the label"
+msgstr[1] "%d issues successfully imported with the label"
msgid "%d job"
msgid_plural "%d jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d job"
+msgstr[1] "%d jobs"
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d layer"
+msgstr[1] "%d layers"
msgid "%d merge request"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d merge request"
+msgstr[1] "%d merge requests"
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] ""
+msgstr[0] "%d merge request that you don't have access to."
+msgstr[1] "%d merge requests that you don't have access to."
msgid "%d merge requests"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d merge request"
+msgstr[1] "%d merge requests"
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d metric"
+msgstr[1] "%d metrics"
msgid "%d milestone"
msgid_plural "%d milestones"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d milestone"
+msgstr[1] "%d milestones"
msgid "%d minute"
msgid_plural "%d minutes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d minute"
+msgstr[1] "%d minutes"
msgid "%d more comment"
msgid_plural "%d more comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d more comment"
+msgstr[1] "%d more comments"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d pending comment"
+msgstr[1] "%d pending comments"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d personal project will be removed and cannot be restored."
+msgstr[1] "%d personal projects will be removed and cannot be restored."
msgid "%d point"
msgid_plural "%d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d point"
+msgstr[1] "%d points"
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d previously merged commit"
+msgstr[1] "%d previously merged commits"
msgid "%d project"
msgid_plural "%d projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d project"
+msgstr[1] "%d projects"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d project selected"
+msgstr[1] "%d projects selected"
msgid "%d remaining"
msgid_plural "%d remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d remaining"
+msgstr[1] "%d remaining"
msgid "%d reply"
msgid_plural "%d replies"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d reply"
+msgstr[1] "%d replies"
msgid "%d second"
msgid_plural "%d seconds"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d second"
+msgstr[1] "%d seconds"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d stage"
+msgstr[1] "%d stages"
msgid "%d star"
msgid_plural "%d stars"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d star"
+msgstr[1] "%d stars"
msgid "%d tag"
msgid_plural "%d tags"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tag"
+msgstr[1] "%d tags"
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tag per image name"
+msgstr[1] "%d tags per image name"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d unassigned issue"
+msgstr[1] "%d unassigned issues"
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d unresolved thread"
+msgstr[1] "%d unresolved threads"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability"
+msgstr[1] "%d vulnerabilities"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability dismissed"
+msgstr[1] "%d vulnerabilities dismissed"
msgid "%d vulnerability set to confirmed"
msgid_plural "%d vulnerabilities set to confirmed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability set to confirmed"
+msgstr[1] "%d vulnerabilities set to confirmed"
msgid "%d vulnerability set to dismissed"
msgid_plural "%d vulnerabilities set to dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability set to dismissed"
+msgstr[1] "%d vulnerabilities set to dismissed"
msgid "%d vulnerability set to needs triage"
msgid_plural "%d vulnerabilities set to needs triage"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability set to needs triage"
+msgstr[1] "%d vulnerabilities set to needs triage"
msgid "%d vulnerability set to resolved"
msgid_plural "%d vulnerabilities set to resolved"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerability set to resolved"
+msgstr[1] "%d vulnerabilities set to resolved"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d warning found:"
+msgstr[1] "%d warnings found:"
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] ""
+msgstr[0] "%s additional commit has been omitted to prevent performance issues."
+msgstr[1] "%s additional commits have been omitted to prevent performance issues."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} & %{openOrClose} %{noteable}"
msgid "%{actionText} & close %{noteable}"
-msgstr ""
+msgstr "%{actionText} & close %{noteable}"
msgid "%{actionText} & reopen %{noteable}"
-msgstr ""
+msgstr "%{actionText} & reopen %{noteable}"
msgid "%{address} is an invalid IP address range"
-msgstr ""
+msgstr "%{address} is an invalid IP address range"
+
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} must be between %{min} and %{max}"
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
-msgstr ""
+msgstr "%{author_link} cloned %{original_issue} to %{new_issue}."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
-msgstr ""
+msgstr "%{author_link} cloned %{original_issue}. You don't have access to the new project."
msgid "%{author_link} wrote:"
-msgstr ""
+msgstr "%{author_link} wrote:"
msgid "%{authorsName}'s thread"
-msgstr ""
+msgstr "%{authorsName}'s thread"
msgid "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
-msgstr ""
+msgstr "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
msgid "%{board_target} not found"
-msgstr ""
+msgstr "%{board_target} not found"
msgid "%{bold_start}%{count}%{bold_end} issue"
msgid_plural "%{bold_start}%{count}%{bold_end} issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} issue"
+msgstr[1] "%{bold_start}%{count}%{bold_end} issues"
msgid "%{bold_start}%{count}%{bold_end} member"
msgid_plural "%{bold_start}%{count}%{bold_end} members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} member"
+msgstr[1] "%{bold_start}%{count}%{bold_end} members"
msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} opened merge request"
+msgstr[1] "%{bold_start}%{count}%{bold_end} opened merge requests"
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
-msgstr ""
+msgstr "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags."
-msgstr ""
+msgstr "%{code_open}Protected:%{code_close} Only exposed to protected branches or protected tags."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} authored %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
-msgstr ""
+msgstr "%{completedCount} completed weight"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+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 ""
+msgstr "%{completedWeight} of %{totalWeight} weight completed"
msgid "%{completed} of %{total} issues closed"
-msgstr ""
+msgstr "%{completed} of %{total} issues closed"
msgid "%{completed} of %{total} weight completed"
-msgstr ""
+msgstr "%{completed} of %{total} weight completed"
msgid "%{cores} cores"
-msgstr ""
+msgstr "%{cores} cores"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{count} %{scope} for term '%{term}'"
msgid "%{count} LOC/commit"
-msgstr ""
+msgstr "%{count} LOC/commit"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} approval required from %{name}"
+msgstr[1] "%{count} approvals required from %{name}"
msgid "%{count} approvals from %{name}"
-msgstr ""
+msgstr "%{count} approvals from %{name}"
msgid "%{count} contact"
msgid_plural "%{count} contacts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} contact"
+msgstr[1] "%{count} contacts"
msgid "%{count} files touched"
-msgstr ""
+msgstr "%{count} files touched"
msgid "%{count} item"
msgid_plural "%{count} items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} item"
+msgstr[1] "%{count} items"
msgid "%{count} items per page"
-msgstr ""
+msgstr "%{count} items per page"
msgid "%{count} more"
-msgstr ""
+msgstr "%{count} more"
msgid "%{count} more assignees"
-msgstr ""
+msgstr "%{count} more assignees"
msgid "%{count} more release"
msgid_plural "%{count} more releases"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} more release"
+msgstr[1] "%{count} more releases"
msgid "%{count} of %{required} approvals from %{name}"
-msgstr ""
+msgstr "%{count} of %{required} approvals from %{name}"
msgid "%{count} of %{total}"
-msgstr ""
+msgstr "%{count} of %{total}"
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} participant"
+msgstr[1] "%{count} participants"
msgid "%{count} related %{pluralized_subject}: %{links}"
-msgstr ""
+msgstr "%{count} related %{pluralized_subject}: %{links}"
msgid "%{count} selected"
-msgstr ""
+msgstr "%{count} selected"
msgid "%{count} total weight"
-msgstr ""
+msgstr "%{count} total weight"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
-msgstr ""
+msgstr "%{dashboard_path} could not be found."
msgid "%{days} days until tags are automatically removed"
-msgstr ""
+msgstr "%{days} days until tags are automatically removed"
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 ""
+msgstr "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
-msgstr ""
+msgstr "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
-msgstr ""
+msgstr "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_elem} is not the default branch. %{docs_link}"
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
msgid "%{due_date} (Past due)"
-msgstr ""
+msgstr "%{due_date} (Past due)"
msgid "%{duration}ms"
-msgstr ""
+msgstr "%{duration}ms"
msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Try to create a new directory again."
msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Try to revert this commit again."
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
-msgstr ""
+msgstr "%{edit_in_new_fork_notice} Try to upload a file again."
msgid "%{emailPrefix}@company.com"
-msgstr ""
+msgstr "%{emailPrefix}@company.com"
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 ""
+msgstr "%{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."
msgid "%{extra} more downstream pipelines"
-msgstr ""
+msgstr "%{extra} more downstream pipelines"
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} deleted"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} more"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
-msgstr ""
+msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
msgid "%{gitlab_experience_text}. We won't share this information with anyone."
-msgstr ""
+msgstr "%{gitlab_experience_text}. We won't share this information with anyone."
msgid "%{global_id} is not a valid ID for %{expected_types}."
-msgstr ""
+msgstr "%{global_id} is not a valid ID for %{expected_types}."
msgid "%{group_name} activity"
-msgstr ""
+msgstr "%{group_name} activity"
msgid "%{group_name} group members"
-msgstr ""
+msgstr "%{group_name} group members"
msgid "%{group_name} is approaching the limit of available seats"
-msgstr ""
+msgstr "%{group_name} is approaching the limit of available seats"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
-msgstr ""
+msgstr "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
-msgstr ""
+msgstr "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgid "%{hook_type} was deleted"
-msgstr ""
+msgstr "%{hook_type} was deleted"
msgid "%{hook_type} was scheduled for deletion"
-msgstr ""
+msgstr "%{hook_type} was scheduled for deletion"
msgid "%{host} sign-in from new location"
-msgstr ""
+msgstr "%{host} sign-in from new location"
msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
-msgstr ""
+msgstr "%{integrations_link_start}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}."
msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} will be removed! Are you sure?"
+
+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 ""
+msgstr "%{issuable}(s) already assigned"
msgid "%{issueType} actions"
-msgstr ""
+msgstr "%{issueType} actions"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{issuesSize} with a limit of %{maxIssueCount}"
msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
-msgstr ""
+msgstr "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Actual response:%{labelEnd} %{headers}"
msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
-msgstr ""
+msgstr "%{labelStart}Assert:%{labelEnd} %{assertion}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
-msgstr ""
+msgstr "%{labelStart}Class:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
-msgstr ""
+msgstr "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
-msgstr ""
+msgstr "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}File:%{labelEnd} %{file}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
-msgstr ""
+msgstr "%{labelStart}Image:%{labelEnd} %{image}"
msgid "%{labelStart}Method:%{labelEnd} %{method}"
-msgstr ""
+msgstr "%{labelStart}Method:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+msgstr "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
msgstr ""
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Sent request:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}Severity:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Tool:%{labelEnd} %{reportType}"
+
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
-msgstr ""
-
-msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{label_for_message} unavailable"
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 hour"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
-msgstr ""
+msgstr "%{level_name} is not allowed in a %{group_level_name} group."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
-msgstr ""
+msgstr "%{level_name} is not allowed since the fork source project has lower visibility."
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 ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -892,7 +913,7 @@ msgid "%{percent}%{percentSymbol} complete"
msgstr ""
msgid "%{placeholder} is not a valid color scheme"
-msgstr ""
+msgstr "%{placeholder} is not a valid colour scheme"
msgid "%{placeholder} is not a valid theme"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1027,7 +1055,7 @@ msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr ""
msgid "%{strong_start}%{project_name}%{strong_end} is a personal project, so you can’t upgrade to a paid plan or start a free trial to lift these limits. We recommend %{move_to_group_link}moving this project to a group%{end_link} to unlock these options. You can %{manage_members_link}manage the members of this project%{end_link}, but don’t forget that all unique members in your personal namespace %{strong_start}%{namespace_name}%{strong_end} count towards total seats in use."
-msgstr ""
+msgstr "%{strong_start}%{project_name}%{strong_end} is a personal project, so you can’t upgrade to a paid plan or start a free trial to lift these limits. We recommend %{move_to_group_link}moving this project to a group%{end_link} to unlock these options. You can %{manage_members_link}manage the members of this project%{end_link}, but don’t forget that all unique members in your personal namespace %{strong_start}%{namespace_name}%{strong_end} count towards total seats in use."
msgid "%{strong_start}%{release_count}%{strong_end} Release"
msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
@@ -1067,7 +1095,7 @@ msgid "%{timebox_type} must have a start and due date"
msgstr ""
msgid "%{time} UTC"
-msgstr ""
+msgstr "%{time} UTC"
msgid "%{title} %{operator} %{threshold}"
msgstr ""
@@ -1357,8 +1385,8 @@ msgstr ""
msgid "1 Code quality finding"
msgid_plural "%d Code quality findings"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Code quality finding"
+msgstr[1] "%d Code quality findings"
msgid "1 Day"
msgid_plural "%d Days"
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1572,7 +1591,7 @@ 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 "A Work Item can be a parent or a child, but not both."
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@@ -1863,7 +1882,7 @@ msgid "Access Git repositories or the API."
msgstr ""
msgid "Access Token"
-msgstr ""
+msgstr "Access Token"
msgid "Access Tokens"
msgstr ""
@@ -1983,10 +2002,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 by any user who is logged in."
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "Accessible by anyone, regardless of authentication."
msgid "Account"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,9 +2247,12 @@ msgstr ""
msgid "Add existing confidential %{issuableType}"
msgstr ""
-msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+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 "Add header and footer to emails. Please note that colour settings will only be applied within the application interface"
+
msgid "Add image comment"
msgstr ""
@@ -2634,7 +2653,7 @@ msgid "AdminSettings|Auto DevOps domain"
msgstr ""
msgid "AdminSettings|Automatically ban users who download more than a specified number of repositories in a given time."
-msgstr ""
+msgstr "Automatically ban users who download more than a specified number of repositories in a given time."
msgid "AdminSettings|CI/CD limits"
msgstr ""
@@ -2709,7 +2728,7 @@ msgid "AdminSettings|Feed token"
msgstr ""
msgid "AdminSettings|Git abuse rate limit"
-msgstr ""
+msgstr "Git abuse rate limit"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
msgstr ""
@@ -2937,7 +2956,7 @@ 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 "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."
msgid "AdminUsers|Access"
msgstr ""
@@ -2946,7 +2965,7 @@ msgid "AdminUsers|Access Git repositories"
msgstr ""
msgid "AdminUsers|Access level"
-msgstr ""
+msgstr "Access level"
msgid "AdminUsers|Access the API"
msgstr ""
@@ -2991,7 +3010,7 @@ msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
msgid "AdminUsers|Avatar"
-msgstr ""
+msgstr "Avatar"
msgid "AdminUsers|Ban user"
msgstr ""
@@ -3021,7 +3040,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr ""
msgid "AdminUsers|Can create group"
-msgstr ""
+msgstr "Can create group"
msgid "AdminUsers|Cannot sign in or access instance information"
msgstr ""
@@ -3099,10 +3118,10 @@ msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
msgstr ""
msgid "AdminUsers|Limits"
-msgstr ""
+msgstr "Limits"
msgid "AdminUsers|Linkedin"
-msgstr ""
+msgstr "Linkedin"
msgid "AdminUsers|Locked"
msgstr ""
@@ -3132,7 +3151,7 @@ msgid "AdminUsers|Personal projects, group and user history will be left intact"
msgstr ""
msgid "AdminUsers|Quota of CI/CD minutes"
-msgstr ""
+msgstr "Quota of CI/CD minutes"
msgid "AdminUsers|Reactivating a user will:"
msgstr ""
@@ -3153,7 +3172,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 "Reset link will be generated and sent to the user. User will be forced to set the password on first sign in."
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
@@ -3168,13 +3187,13 @@ 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 "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}"
msgid "AdminUsers|The user can't access git repositories."
msgstr ""
@@ -3243,7 +3262,7 @@ msgid "AdminUsers|View pending member requests"
msgstr ""
msgid "AdminUsers|Website URL"
-msgstr ""
+msgstr "Website URL"
msgid "AdminUsers|What can I do?"
msgstr ""
@@ -3312,7 +3331,7 @@ msgid "Administration"
msgstr ""
msgid "Administrators"
-msgstr ""
+msgstr "Administrators"
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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr "All eligible users"
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3795,7 +3817,7 @@ msgid "All threads resolved!"
msgstr ""
msgid "All users in this group must set up two-factor authentication"
-msgstr ""
+msgstr "All users in this group must set up two-factor authentication"
msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
msgstr ""
@@ -3876,7 +3898,7 @@ msgid "Allowed to create:"
msgstr ""
msgid "Allowed to delete projects"
-msgstr ""
+msgstr "Allowed to delete projects"
msgid "Allowed to fail"
msgstr ""
@@ -3885,7 +3907,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 "Allows projects to track errors using an Opstrace integration."
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4077,7 +4096,7 @@ msgid "An error occurred while fetching issues."
msgstr ""
msgid "An error occurred while fetching label colors."
-msgstr ""
+msgstr "An error occurred while fetching label colours."
msgid "An error occurred while fetching participants"
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4269,7 +4288,7 @@ msgid "An error occurred while retrieving projects."
msgstr ""
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "An error occurred while retrieving your settings. Reload the page to try again."
msgid "An error occurred while saving changes: %{error}"
msgstr ""
@@ -4280,7 +4299,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "An error occurred while saving your settings. Try saving them again."
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4490,7 +4509,7 @@ msgid "Application settings saved successfully"
msgstr ""
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "Application settings saved successfully."
msgid "Application settings update failed"
msgstr ""
@@ -4586,13 +4605,25 @@ msgstr ""
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr ""
+msgid "ApplicationSettings|Require lowercase letters"
+msgstr "Require lowercase letters"
+
+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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -4879,7 +4925,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 "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}"
msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
msgstr ""
@@ -4983,7 +5029,7 @@ msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
msgid "Are you sure you want to remove %{topic_name}?"
-msgstr ""
+msgstr "Are you sure you want to remove %{topic_name}?"
msgid "Are you sure you want to remove the attachment?"
msgstr ""
@@ -5004,7 +5050,7 @@ 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 "Are you sure you want to reset the error tracking access token?"
msgid "Are you sure you want to reset the health check token?"
msgstr ""
@@ -5115,7 +5161,7 @@ msgid "Assign To"
msgstr ""
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "Assign custom colour like #FF0000"
msgid "Assign labels"
msgstr ""
@@ -5124,7 +5170,7 @@ msgid "Assign milestone"
msgstr ""
msgid "Assign myself"
-msgstr ""
+msgstr "Assign myself"
msgid "Assign reviewer"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5293,11 +5330,17 @@ msgid "AuditLogs|User Events"
msgstr ""
msgid "AuditStreams|A header with this name already exists."
-msgstr ""
+msgstr "A header with this name already exists."
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 ""
@@ -5316,11 +5359,14 @@ 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"
-msgstr ""
+msgstr "Custom HTTP headers"
msgid "AuditStreams|Delete %{link}"
msgstr ""
@@ -5331,18 +5377,33 @@ msgstr ""
msgid "AuditStreams|Destinations receive all audit event data"
msgstr ""
-msgid "AuditStreams|Header"
+msgid "AuditStreams|Edit %{link}"
msgstr ""
+msgid "AuditStreams|Header"
+msgstr "Header"
+
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
+msgstr "Maximum of %{number} HTTP headers has been reached."
+
+msgid "AuditStreams|Save external stream destination"
msgstr ""
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5353,6 +5414,9 @@ msgid "AuditStreams|This is great for keeping everything one place."
msgstr ""
msgid "AuditStreams|Value"
+msgstr "Value"
+
+msgid "AuditStreams|Verification token"
msgstr ""
msgid "Aug"
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5623,7 +5687,7 @@ msgid "Back to page %{number}"
msgstr ""
msgid "Background Color"
-msgstr ""
+msgstr "Background Colour"
msgid "Background Jobs"
msgstr ""
@@ -5632,7 +5696,7 @@ msgid "Background Migrations"
msgstr ""
msgid "Background color"
-msgstr ""
+msgstr "Background colour"
msgid "BackgroundMigrations|Background Migrations"
msgstr ""
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6550,7 +6619,7 @@ msgid "Bold text"
msgstr ""
msgid "Both SSH and HTTP(S)"
-msgstr ""
+msgstr "Both SSH and HTTP(S)"
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -6874,7 +6985,7 @@ msgid "BulkImport|must be a group"
msgstr ""
msgid "Bullet list"
-msgstr ""
+msgstr "Bullet list"
msgid "Burndown chart"
msgstr ""
@@ -6973,7 +7084,7 @@ msgid "CICDAnalytics|All time"
msgstr ""
msgid "CICDAnalytics|Change failure rate"
-msgstr ""
+msgstr "Change failure rate"
msgid "CICDAnalytics|Deployment frequency"
msgstr ""
@@ -7017,7 +7128,7 @@ msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
msgid "CICDAnalytics|Time to restore service"
-msgstr ""
+msgstr "Time to restore service"
msgid "CICDAnalytics|What is shared runner duration?"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7347,7 +7455,7 @@ msgid "Card number:"
msgstr ""
msgid "CascadingSettings|Enforce deletion protection for all subgroups"
-msgstr ""
+msgstr "Enforce deletion protection for all subgroups"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -7768,10 +7876,10 @@ msgid "Checkout|Group"
msgstr ""
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use) or more."
-msgstr ""
+msgstr "Must be %{minimumNumberOfUsers} (your seats in use) or more."
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 "Must be %{minimumNumberOfUsers} (your seats in use, plus all over limit members) or more. To buy fewer seats, remove members from the group."
msgid "Checkout|Name of company or organization using GitLab"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -7912,7 +8017,7 @@ msgid "Choose a type..."
msgstr ""
msgid "Choose any color."
-msgstr ""
+msgstr "Choose any colour."
msgid "Choose file…"
msgstr ""
@@ -8265,7 +8370,7 @@ msgid "Closed MRs"
msgstr ""
msgid "Closed date"
-msgstr ""
+msgstr "Closed date"
msgid "Closed issues"
msgstr ""
@@ -8286,121 +8391,136 @@ msgid "Cloud Storage"
msgstr ""
msgid "CloudSeed|All"
-msgstr ""
+msgstr "All"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "AlloyDB for Postgres"
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "Available database services through which instances may be created"
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "Cancel"
msgid "CloudSeed|Cloud Firestore"
-msgstr ""
+msgstr "Cloud Firestore"
msgid "CloudSeed|Cloud SQL for MySQL"
-msgstr ""
+msgstr "Cloud SQL for MySQL"
msgid "CloudSeed|Cloud SQL for Postgres"
-msgstr ""
+msgstr "Cloud SQL for Postgres"
msgid "CloudSeed|Cloud SQL for SQL Server"
-msgstr ""
+msgstr "Cloud SQL for SQL Server"
msgid "CloudSeed|CloudSQL Instance"
+msgstr "CloudSQL Instance"
+
+msgid "CloudSeed|Configuration"
msgstr ""
msgid "CloudSeed|Create cluster"
-msgstr ""
+msgstr "Create cluster"
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "Create database"
msgid "CloudSeed|Create instance"
-msgstr ""
+msgstr "Create instance"
msgid "CloudSeed|Database instance is generated within the selected Google Cloud project"
-msgstr ""
+msgstr "Database instance is generated within the selected Google Cloud project"
msgid "CloudSeed|Database instances associated with this project"
-msgstr ""
+msgstr "Database instances associated with this project"
msgid "CloudSeed|Database version"
+msgstr "Database version"
+
+msgid "CloudSeed|Databases"
msgstr ""
-msgid "CloudSeed|Description"
+msgid "CloudSeed|Deployments"
msgstr ""
+msgid "CloudSeed|Description"
+msgstr "Description"
+
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
-msgstr ""
+msgstr "Determines memory and virtual cores available to your instance"
msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
msgid "CloudSeed|Environment"
-msgstr ""
+msgstr "Environment"
msgid "CloudSeed|Flexible, scalable NoSQL cloud database for client- and server-side development"
-msgstr ""
+msgstr "Flexible, scalable NoSQL cloud database for client- and server-side development"
msgid "CloudSeed|Fully managed PostgreSQL-compatible service for high-demand workloads"
-msgstr ""
+msgstr "Fully managed PostgreSQL-compatible service for high-demand workloads"
msgid "CloudSeed|Fully managed relational database service for MySQL"
-msgstr ""
+msgstr "Fully managed relational database service for MySQL"
msgid "CloudSeed|Fully managed relational database service for PostgreSQL"
-msgstr ""
+msgstr "Fully managed relational database service for PostgreSQL"
msgid "CloudSeed|Fully managed relational database service for SQL Server"
-msgstr ""
+msgstr "Fully managed relational database service for SQL Server"
msgid "CloudSeed|Generated database instance is linked to the selected branch or tag"
-msgstr ""
+msgstr "Generated database instance is linked to the selected branch or tag"
msgid "CloudSeed|Google Cloud Project"
-msgstr ""
+msgstr "Google Cloud Project"
msgid "CloudSeed|Google Cloud project"
-msgstr ""
+msgstr "Google Cloud project"
msgid "CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances"
-msgstr ""
+msgstr "I accept Google Cloud pricing and responsibilities involved with managing database instances"
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 "Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{cloudsqlPricingEnd}, %{alloydbPricingStart}Alloy DB%{alloydbPricingEnd}, %{memorystorePricingStart}Memorystore%{memorystorePricingEnd} and %{firestorePricingStart}Firestore%{firestorePricingEnd}."
msgid "CloudSeed|Machine type"
-msgstr ""
+msgstr "Machine type"
msgid "CloudSeed|Memorystore for Redis"
-msgstr ""
+msgstr "Memorystore for Redis"
msgid "CloudSeed|No instances"
-msgstr ""
+msgstr "No instances"
msgid "CloudSeed|Refs"
+msgstr "Refs"
+
+msgid "CloudSeed|Regions"
msgstr ""
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
-msgstr ""
+msgstr "Scalable, secure, and highly available in-memory service for Redis"
msgid "CloudSeed|Service"
+msgstr "Service"
+
+msgid "CloudSeed|Service Account"
msgstr ""
msgid "CloudSeed|Services"
-msgstr ""
+msgstr "Services"
msgid "CloudSeed|There are no instances to display."
-msgstr ""
+msgstr "There are no instances to display."
msgid "CloudSeed|Version"
-msgstr ""
+msgstr "Version"
msgid "Cluster"
msgstr ""
@@ -8816,7 +8936,7 @@ msgid "ClusterIntegration|Choose which of your environments will use this cluste
msgstr ""
msgid "ClusterIntegration|Civo Kubernetes"
-msgstr ""
+msgstr "Civo Kubernetes"
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -9041,16 +9161,16 @@ 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 November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
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 ""
+msgstr "The namespace associated with your project. This will be used for deploy boards, and Web terminals."
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr ""
@@ -9146,10 +9266,10 @@ msgid "Code Review Analytics displays a table of open merge requests considered
msgstr ""
msgid "Code block"
-msgstr ""
+msgstr "Code block"
msgid "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
-msgstr ""
+msgstr "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr ""
@@ -9233,22 +9353,22 @@ msgid "Collector hostname"
msgstr ""
msgid "Color"
-msgstr ""
+msgstr "Colour"
msgid "ColorWidget|An error occurred while updating color."
-msgstr ""
+msgstr "An error occurred while updating colour."
msgid "ColorWidget|Assign epic color"
-msgstr ""
+msgstr "Assign epic colour"
msgid "ColorWidget|Color"
-msgstr ""
+msgstr "Colour"
msgid "ColorWidget|Error fetching epic color."
-msgstr ""
+msgstr "Error fetching epic colour."
msgid "Colorize messages"
-msgstr ""
+msgstr "Colourise messages"
msgid "ComboSearch is not defined"
msgstr ""
@@ -9484,7 +9604,7 @@ msgid "ComplianceFrameworks|Add framework"
msgstr ""
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "Background colour"
msgid "ComplianceFrameworks|Cancel"
msgstr ""
@@ -9625,7 +9745,7 @@ msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if
msgstr ""
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "Configure Error Tracking"
msgid "Configure GitLab"
msgstr ""
@@ -9667,7 +9787,7 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr ""
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
-msgstr ""
+msgstr "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
@@ -9905,7 +10025,7 @@ msgid "ContainerRegistry|CLI Commands"
msgstr ""
msgid "ContainerRegistry|Clean up image tags"
-msgstr ""
+msgstr "Clean up image tags"
msgid "ContainerRegistry|Cleanup disabled"
msgstr ""
@@ -10081,13 +10201,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 "Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
msgid "ContainerRegistry|Set up cleanup"
msgstr ""
msgid "ContainerRegistry|Show full path"
-msgstr ""
+msgstr "Show full path"
msgid "ContainerRegistry|Some tags were not deleted"
msgstr ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10816,7 +10930,7 @@ msgid "Create new project"
msgstr ""
msgid "Create new..."
-msgstr ""
+msgstr "Create new..."
msgid "Create one"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11284,7 +11401,7 @@ msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job
msgstr ""
msgid "Customize colors"
-msgstr ""
+msgstr "Customise colours"
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 ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11511,13 +11631,16 @@ msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Change failure rate"
+msgstr "Change failure rate"
+
+msgid "DORA4Metrics|Change failure rate (percentage)"
msgstr ""
msgid "DORA4Metrics|Date"
msgstr ""
msgid "DORA4Metrics|Days for an open incident"
-msgstr ""
+msgstr "Days for an open incident"
msgid "DORA4Metrics|Days from merge to deploy"
msgstr ""
@@ -11528,17 +11651,20 @@ 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 ""
+msgstr "Median time (last %{days}d)"
msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
-msgstr ""
+msgstr "Median time an incident was open in a production environment over the given time period."
msgid "DORA4Metrics|No incidents during this period"
-msgstr ""
+msgstr "No incidents during this period"
msgid "DORA4Metrics|No merge requests were deployed during this period"
msgstr ""
@@ -11547,13 +11673,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 "Number of incidents divided by the number of deployments to a production environment in the given time period."
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr ""
+msgstr "Percentage of failed deployments"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr ""
+msgstr "Something went wrong while getting change failure rate data."
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
msgstr ""
@@ -11562,7 +11688,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 "Something went wrong while getting time to restore service data."
msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
@@ -11571,6 +11697,9 @@ msgid "DORA4Metrics|The chart displays the median time between a merge request b
msgstr ""
msgid "DORA4Metrics|Time to restore service"
+msgstr "Time to restore service"
+
+msgid "DORA4Metrics|Time to restore service (median days)"
msgstr ""
msgid "DSN"
@@ -11604,14 +11733,26 @@ msgid "DastConfig|Customize DAST settings to suit your requirements. Configurati
msgstr ""
msgid "DastConfig|DAST CI/CD configuration"
-msgstr ""
+msgstr "DAST CI/CD configuration"
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 "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}."
+
+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 ""
@@ -11742,7 +11883,7 @@ msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
msgid "DastProfiles|Manage %{profileType} profiles"
-msgstr ""
+msgstr "Manage %{profileType} profiles"
msgid "DastProfiles|Manage profiles"
msgstr ""
@@ -11955,7 +12096,7 @@ msgid "DastSiteValidation|Meta tag validation"
msgstr ""
msgid "DastSiteValidation|Not validated"
-msgstr ""
+msgstr "Not validated"
msgid "DastSiteValidation|Retry validation"
msgstr ""
@@ -12230,7 +12371,7 @@ msgid "Definition"
msgstr ""
msgid "Delay 2FA enforcement (hours)"
-msgstr ""
+msgstr "Delay 2FA enforcement (hours)"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
msgstr ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12314,7 +12458,7 @@ msgid "Delete image repository"
msgstr ""
msgid "Delete internal note"
-msgstr ""
+msgstr "Delete internal note"
msgid "Delete label"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12428,31 +12584,31 @@ msgid "Deletion pending. This project will be deleted on %{date}. Repository and
msgstr ""
msgid "DeletionSettings|All projects are deleted immediately."
-msgstr ""
+msgstr "All projects are deleted immediately."
msgid "DeletionSettings|Deletion protection"
-msgstr ""
+msgstr "Deletion protection"
msgid "DeletionSettings|Keep deleted"
-msgstr ""
+msgstr "Keep deleted"
msgid "DeletionSettings|Keep deleted projects for %{number} days"
-msgstr ""
+msgstr "Keep deleted projects for %{number} days"
msgid "DeletionSettings|Keep deleted projects for 1 day"
-msgstr ""
+msgstr "Keep deleted projects for 1 day"
msgid "DeletionSettings|None, delete immediately"
-msgstr ""
+msgstr "None, delete immediately"
msgid "DeletionSettings|Only administrators can delete projects."
-msgstr ""
+msgstr "Only administrators can delete projects."
msgid "DeletionSettings|Owners and administrators can delete projects."
-msgstr ""
+msgstr "Owners and administrators can delete projects."
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 "Retention period that deleted groups and projects will remain restorable. Personal projects are always deleted immediately. Some groups can opt-out their projects."
msgid "Denied"
msgstr ""
@@ -12590,7 +12746,7 @@ msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
-msgstr ""
+msgstr "Enable the Dependency Proxy and settings for clearing the cache."
msgid "DependencyProxy|Image list"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13203,7 +13362,7 @@ msgid "Details (default)"
msgstr ""
msgid "Details block"
-msgstr ""
+msgstr "Details block"
msgid "Detect host keys"
msgstr ""
@@ -13407,7 +13566,7 @@ msgid "DevopsReport|Your usage"
msgstr ""
msgid "Diagram (%{language})"
-msgstr ""
+msgstr "Diagram (%{language})"
msgid "Did not delete the source branch."
msgstr ""
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13898,7 +14054,7 @@ msgid "Edit %{name}"
msgstr ""
msgid "Edit %{profileType} profile"
-msgstr ""
+msgstr "Edit %{profileType} profile"
msgid "Edit Comment"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14231,7 +14384,7 @@ msgid "Enable Auto DevOps"
msgstr ""
msgid "Enable GitLab Error Tracking"
-msgstr ""
+msgstr "Enable GitLab Error Tracking"
msgid "Enable Gitpod"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14462,10 +14612,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 "Enter any colour or choose one of the suggested colours below."
msgid "Enter any color."
-msgstr ""
+msgstr "Enter any colour."
msgid "Enter at least three characters to search"
msgstr ""
@@ -14696,7 +14846,7 @@ msgid "Environments|Open live environment"
msgstr ""
msgid "Environments|Re-deploy environment"
-msgstr ""
+msgstr "Re-deploy environment"
msgid "Environments|Re-deploy environment %{name}?"
msgstr ""
@@ -14726,10 +14876,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 "This action will %{docsStart}retry the latest deployment%{docsEnd} with the commit %{commitId}, for this environment. Are you sure you want to continue?"
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 "This action will %{docsStart}roll back this environment%{docsEnd} to a previously successful deployment for commit %{commitId}. Are you sure you want to continue?"
msgid "Environments|Upcoming"
msgstr ""
@@ -14864,7 +15014,7 @@ 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 ""
+msgstr "The colour for the epic when it's visualised, such as on roadmap timeline bars."
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 ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15095,7 +15248,7 @@ msgid "Error: Unable to find AWS role for current user"
msgstr ""
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "Access token is %{token_in_code_tag}"
msgid "ErrorTracking|Active"
msgstr ""
@@ -15266,7 +15419,7 @@ 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 ""
+msgstr "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."
msgid "EventFilterBy|Filter by all"
msgstr ""
@@ -15361,7 +15514,7 @@ msgid "Everyone With Access"
msgstr ""
msgid "Everyone can access the wiki."
-msgstr ""
+msgstr "Everyone can access the wiki."
msgid "Everyone can contribute"
msgstr ""
@@ -15502,7 +15655,7 @@ msgid "Expires"
msgstr ""
msgid "Expires %{preposition} %{expires_at}"
-msgstr ""
+msgstr "Expires %{preposition} %{expires_at}"
msgid "Expires on"
msgstr ""
@@ -15667,7 +15820,7 @@ msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
msgstr ""
msgid "ExternalWikiService|Enter the URL to the external wiki."
-msgstr ""
+msgstr "Enter the URL to the external wiki."
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -15692,8 +15845,8 @@ msgstr ""
msgid "Failed job"
msgid_plural "Failed jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Failed job"
+msgstr[1] "Failed jobs"
msgid "Failed on"
msgstr ""
@@ -15827,7 +15980,7 @@ msgid "Failed to load groups, users and deploy keys."
msgstr ""
msgid "Failed to load groups."
-msgstr ""
+msgstr "Failed to load groups."
msgid "Failed to load iteration cadences."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16375,10 +16528,10 @@ msgid "Find file"
msgstr ""
msgid "Fingerprint (MD5)"
-msgstr ""
+msgstr "Fingerprint (MD5)"
msgid "Fingerprint (SHA256)"
-msgstr ""
+msgstr "Fingerprint (SHA256)"
msgid "Fingerprints"
msgstr ""
@@ -16387,7 +16540,7 @@ msgid "Finish editing this message first!"
msgstr ""
msgid "Finish review"
-msgstr ""
+msgstr "Finish review"
msgid "Finish setting up your dedicated account for %{group_name}."
msgstr ""
@@ -16477,7 +16630,7 @@ msgid "Followed users"
msgstr ""
msgid "Font Color"
-msgstr ""
+msgstr "Font Colour"
msgid "Footer message"
msgstr ""
@@ -16588,7 +16741,7 @@ msgid "ForkProject|Visibility level"
msgstr ""
msgid "ForkProject|Want to organize several dependent projects under the same namespace?"
-msgstr ""
+msgstr "Want to organise several dependent projects under the same namespace?"
msgid "ForkSuggestion|Cancel"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17369,40 +17528,40 @@ msgid "Git version"
msgstr ""
msgid "GitAbuse|Excluded users"
-msgstr ""
+msgstr "Excluded users"
msgid "GitAbuse|Number of repositories"
-msgstr ""
+msgstr "Number of repositories"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "Number of repositories can't be blank. Set to 0 for no limit."
msgid "GitAbuse|Number of repositories must be a number."
-msgstr ""
+msgstr "Number of repositories must be a number."
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr ""
+msgstr "Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "Reporting time period (seconds)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "Reporting time period can't be blank. Set to 0 for no limit."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "Reporting time period must be a number."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr ""
+msgstr "The maximum number of unique repositories a user can download in the specified time period before they're banned."
msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
-msgstr ""
+msgstr "Users who are excluded from the Git abuse rate limit."
msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
-msgstr ""
+msgstr "You cannot specify more than %{maxExcludedUsers} excluded users."
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
msgstr ""
@@ -17432,7 +17591,7 @@ msgid "GitLab Billing Team."
msgstr ""
msgid "GitLab Error Tracking"
-msgstr ""
+msgstr "GitLab Error Tracking"
msgid "GitLab Import"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17507,7 +17666,7 @@ msgid "GitLab is open source software to collaborate on code."
msgstr ""
msgid "GitLab is undergoing maintenance"
-msgstr ""
+msgstr "GitLab is undergoing maintenance"
msgid "GitLab logo"
msgstr ""
@@ -17558,11 +17717,14 @@ 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 "Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17582,7 +17744,7 @@ msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable th
msgstr ""
msgid "GitLabPages|Maximum size (MB)"
-msgstr ""
+msgstr "Maximum size (MB)"
msgid "GitLabPages|New Domain"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17621,11 +17786,14 @@ msgid "GitLabPages|Unverified"
msgstr ""
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "Updating your Pages configuration..."
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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17729,13 +17900,13 @@ msgid "Global notification settings"
msgstr ""
msgid "GlobalSearch| %{search} %{description} %{scope}"
-msgstr ""
+msgstr " %{search} %{description} %{scope}"
msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
msgstr ""
msgid "GlobalSearch|Groups"
-msgstr ""
+msgstr "Groups"
msgid "GlobalSearch|Issues I've created"
msgstr ""
@@ -17753,7 +17924,7 @@ msgid "GlobalSearch|Merge requests that I'm a reviewer"
msgstr ""
msgid "GlobalSearch|Projects"
-msgstr ""
+msgstr "Projects"
msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
msgstr ""
@@ -17777,22 +17948,22 @@ msgid "GlobalSearch|Type for new suggestions to appear below."
msgstr ""
msgid "GlobalSearch|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
-msgstr ""
+msgstr "Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
msgid "GlobalSearch|What are you searching for?"
msgstr ""
msgid "GlobalSearch|all GitLab"
-msgstr ""
+msgstr "all GitLab"
msgid "GlobalSearch|group"
-msgstr ""
+msgstr "group"
msgid "GlobalSearch|in %{scope}"
-msgstr ""
+msgstr "in %{scope}"
msgid "GlobalSearch|project"
-msgstr ""
+msgstr "project"
msgid "Globally-allowed IP ranges"
msgstr ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18068,7 +18236,7 @@ msgid "Group"
msgstr ""
msgid "Group \"%{group_name}\" was successfully updated."
-msgstr ""
+msgstr "Group \"%{group_name}\" was successfully updated."
msgid "Group %{group_name} couldn't be exported."
msgstr ""
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18224,7 +18389,7 @@ msgid "Group wikis"
msgstr ""
msgid "Group-level wiki is disabled."
-msgstr ""
+msgstr "Group-level wiki is disabled."
msgid "Group: %{group_name}"
msgstr ""
@@ -18236,7 +18401,7 @@ msgid "GroupActivityMetrics|Issues created"
msgstr ""
msgid "GroupActivityMetrics|Last 30 days"
-msgstr ""
+msgstr "Last 30 days"
msgid "GroupActivityMetrics|Members added"
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18542,7 +18707,7 @@ msgid "GroupSettings|Custom project templates"
msgstr ""
msgid "GroupSettings|Customer relations is enabled"
-msgstr ""
+msgstr "Customer relations is enabled"
msgid "GroupSettings|Customize this group's badges."
msgstr ""
@@ -18551,16 +18716,19 @@ msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within thi
msgstr ""
msgid "GroupSettings|Email notifications are disabled"
-msgstr ""
+msgstr "Email notifications are disabled"
msgid "GroupSettings|Export group"
msgstr ""
-msgid "GroupSettings|Group members are not notified if the group is mentioned."
+msgid "GroupSettings|Git abuse rate limit"
msgstr ""
+msgid "GroupSettings|Group members are not notified if the group is mentioned."
+msgstr "Group members are not notified if the group is mentioned."
+
msgid "GroupSettings|Group mentions are disabled"
-msgstr ""
+msgstr "Group mentions are disabled"
msgid "GroupSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr ""
@@ -18568,17 +18736,11 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
-msgstr ""
-
-msgid "GroupSettings|Number of projects"
-msgstr ""
+msgstr "Members cannot invite groups outside of %{group} and its subgroups"
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
-msgstr ""
+msgstr "Organisations and contacts can be created and associated with issues."
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
@@ -18595,14 +18757,11 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
-msgstr ""
+msgstr "Projects in %{group} cannot be shared with other groups"
msgid "GroupSettings|Reporting"
-msgstr ""
+msgstr "Reporting"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
@@ -18611,26 +18770,20 @@ msgid "GroupSettings|Select parent group"
msgstr ""
msgid "GroupSettings|Select the project containing the %{code_start}.gitlab/insights.yml%{code_end} file"
-msgstr ""
+msgstr "Select the project containing the %{code_start}.gitlab/insights.yml%{code_end} file"
msgid "GroupSettings|Select the project containing your custom Insights file. %{help_link_start}What is Insights?%{help_link_end}"
-msgstr ""
+msgstr "Select the project containing your custom Insights file. %{help_link_start}What is 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 "Set a size limit for all content in each Pages site in this group. %{link_start}Learn more.%{link_end}"
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18653,7 +18806,7 @@ 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 "Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group"
msgid "GroupSettings|What are badges?"
msgstr ""
@@ -18722,13 +18875,13 @@ msgid "GroupsEmptyState|A group is a collection of several projects."
msgstr ""
msgid "GroupsEmptyState|Create new project"
-msgstr ""
+msgstr "Create new project"
msgid "GroupsEmptyState|Create new subgroup"
-msgstr ""
+msgstr "Create new subgroup"
msgid "GroupsEmptyState|Groups are the best way to manage multiple projects and members."
-msgstr ""
+msgstr "Groups are the best way to manage multiple projects and members."
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
msgstr ""
@@ -18737,15 +18890,18 @@ msgid "GroupsEmptyState|No groups found"
msgstr ""
msgid "GroupsEmptyState|No subgroups or projects."
-msgstr ""
+msgstr "No subgroups or projects."
msgid "GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab."
-msgstr ""
+msgstr "Projects are where you can store your code, access issues, wiki, and other features of 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 "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."
+
+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."
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19267,7 +19435,7 @@ msgid "Hook was successfully updated."
msgstr ""
msgid "Horizontal rule"
-msgstr ""
+msgstr "Horizontal rule"
msgid "Hostname"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19387,7 +19558,7 @@ msgid "IDE|Review"
msgstr ""
msgid "IDE|Start a new merge request"
-msgstr ""
+msgstr "Start a new merge request"
msgid "IDE|Successful commit"
msgstr ""
@@ -19438,49 +19609,49 @@ msgid "IdentityVerification|Before you create your group, we need you to verify
msgstr ""
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
-msgstr ""
+msgstr "Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
msgid "IdentityVerification|Create a project"
msgstr ""
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
-msgstr ""
+msgstr "For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
msgid "IdentityVerification|Help us protect your account"
-msgstr ""
+msgstr "Help us protect your account"
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 "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."
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 "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."
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 "If you have lost access to the email address associated with this account, or are having trouble with the code, %{link_start}here are some other steps you can take.%{link_end}"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
-msgstr ""
+msgstr "Maximum login attempts exceeded. Wait %{interval} and try again."
msgid "IdentityVerification|Please enter a valid code"
-msgstr ""
+msgstr "Please enter a valid code"
msgid "IdentityVerification|Resend code"
-msgstr ""
+msgstr "Resend code"
msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgstr "The code has expired. Resend a new code and try again."
msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgstr "The code is incorrect. Enter it again, or resend a new code."
msgid "IdentityVerification|Verification code"
-msgstr ""
+msgstr "Verification code"
msgid "IdentityVerification|Verification successful"
-msgstr ""
+msgstr "Verification successful"
msgid "IdentityVerification|Verify code"
-msgstr ""
+msgstr "Verify code"
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19489,12 +19660,15 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr ""
msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+msgstr "You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
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 ""
+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|Your verification code expires after %{expires_in_minutes} minutes."
+msgstr "Your verification code expires after %{expires_in_minutes} minutes."
+
+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."
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20608,13 +20755,13 @@ msgid "Incident|Alert details"
msgstr ""
msgid "Incident|Are you sure you want to delete this event?"
-msgstr ""
+msgstr "Are you sure you want to delete this event?"
msgid "Incident|Are you sure you wish to delete this image?"
msgstr ""
msgid "Incident|Delete event"
-msgstr ""
+msgstr "Delete event"
msgid "Incident|Delete image"
msgstr ""
@@ -20629,10 +20776,10 @@ msgid "Incident|Editing %{filename}"
msgstr ""
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr ""
+msgstr "Error creating incident timeline event: %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr ""
+msgstr "Error deleting incident timeline event: %{error}"
msgid "Incident|Metrics"
msgstr ""
@@ -20641,16 +20788,16 @@ msgid "Incident|No timeline items have been added yet."
msgstr ""
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "Save and add another event"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr ""
+msgstr "Something went wrong while creating the incident timeline event."
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr ""
+msgstr "Something went wrong while deleting the incident timeline event."
msgid "Incident|Something went wrong while fetching incident timeline events."
-msgstr ""
+msgstr "Something went wrong while fetching incident timeline events."
msgid "Incident|Summary"
msgstr ""
@@ -20665,10 +20812,10 @@ msgid "Incident|Timeline"
msgstr ""
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "Timeline text"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "Timeline text..."
msgid "Include author name in notification email body"
msgstr ""
@@ -20940,7 +21087,7 @@ msgid "Integrations|An error occurred while loading projects using custom settin
msgstr ""
msgid "Integrations|An event will be triggered when one of the following items happen."
-msgstr ""
+msgstr "An event will be triggered when one of the following items happen."
msgid "Integrations|Branches for which notifications are to be sent"
msgstr ""
@@ -20955,13 +21102,13 @@ msgid "Integrations|Comment settings:"
msgstr ""
msgid "Integrations|Configure the scope of notifications."
-msgstr ""
+msgstr "Configure the scope of notifications."
msgid "Integrations|Connection details"
msgstr ""
msgid "Integrations|Connection failed. Check your integration settings."
-msgstr ""
+msgstr "Connection failed. Check your integration settings."
msgid "Integrations|Connection successful."
msgstr ""
@@ -21054,7 +21201,7 @@ msgid "Integrations|No linked namespaces"
msgstr ""
msgid "Integrations|Notification settings"
-msgstr ""
+msgstr "Notification settings"
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -21072,7 +21219,7 @@ msgid "Integrations|Resetting this integration will clear the settings and deact
msgstr ""
msgid "Integrations|Restrict to branch (optional)"
-msgstr ""
+msgstr "Restrict to branch (optional)"
msgid "Integrations|Return to GitLab for Jira"
msgstr ""
@@ -21120,7 +21267,7 @@ msgid "Integrations|To keep this project going, create a new issue."
msgstr ""
msgid "Integrations|Trigger"
-msgstr ""
+msgstr "Trigger"
msgid "Integrations|Use custom settings"
msgstr ""
@@ -21204,7 +21351,7 @@ msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid"
-msgstr ""
+msgstr "Invalid"
msgid "Invalid Insights config file detected"
msgstr ""
@@ -21270,7 +21417,7 @@ msgid "Invalid repository path"
msgstr ""
msgid "Invalid rule"
-msgstr ""
+msgstr "Invalid rule"
msgid "Invalid server response"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21411,7 +21558,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr ""
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "Review the invite errors and try again:"
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -21430,8 +21577,8 @@ 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] ""
+msgstr[0] "The following member couldn't be invited"
+msgstr[1] "The following %d members couldn't be invited"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
msgstr ""
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21545,7 +21689,7 @@ 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 "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'."
msgid "IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}"
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22088,13 +22262,13 @@ msgid "Jira-GitLab user mapping template"
msgstr ""
msgid "JiraConnect|Cannot find namespace. Make sure you have sufficient permissions."
-msgstr ""
+msgstr "Cannot find namespace. Make sure you have sufficient permissions."
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 ""
+msgstr "Could not fetch user information from Jira. Check the permissions in Jira and try again."
msgid "JiraConnect|Create branch for Jira issue %{jiraIssue}"
msgstr ""
@@ -22115,7 +22289,7 @@ 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 ""
+msgstr "The Jira user is not a site administrator. Check the permissions in Jira and try again."
msgid "JiraConnect|You can now close this window and return to Jira."
msgstr ""
@@ -22421,7 +22595,7 @@ msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
msgstr ""
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr ""
+msgstr "%{searchLength} results found for %{searchTerm}"
msgid "Job|Are you sure you want to erase this job log and artifacts?"
msgstr ""
@@ -22463,7 +22637,7 @@ msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Job log search"
-msgstr ""
+msgstr "Job log search"
msgid "Job|Keep"
msgstr ""
@@ -22472,7 +22646,7 @@ msgid "Job|Manual"
msgstr ""
msgid "Job|No search results found"
-msgstr ""
+msgstr "No search results found"
msgid "Job|Passed"
msgstr ""
@@ -22495,14 +22669,17 @@ 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 ""
+msgstr "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."
msgid "Job|Search job log"
-msgstr ""
+msgstr "Search job log"
msgid "Job|Show complete raw"
msgstr ""
@@ -22541,7 +22718,7 @@ msgid "Job|Waiting for resource"
msgstr ""
msgid "Job|We could not find this element"
-msgstr ""
+msgstr "We could not find this element"
msgid "Job|allowed to fail"
msgstr ""
@@ -22556,7 +22733,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 "Join GitLab today! You and your team can plan, build, and ship secure code all in one application. Get started here for free!"
msgid "Join Zoom meeting"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22737,8 +22914,8 @@ msgstr ""
msgid "Label added: %{labels}"
msgid_plural "Labels added: %{labels}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Label added: %{labels}"
+msgstr[1] "Labels added: %{labels}"
msgid "Label priority"
msgstr ""
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23040,13 +23211,13 @@ msgid "LearnGitLab|Add code owners"
msgstr ""
msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
-msgstr ""
+msgstr "Analyse your application for vulnerabilities with DAST"
msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
msgstr ""
msgid "LearnGitLab|Create a repository"
-msgstr ""
+msgstr "Create a repository"
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
msgstr ""
@@ -23097,10 +23268,10 @@ msgid "LearnGitLab|Save time by automating your integration and deployment tasks
msgstr ""
msgid "LearnGitLab|Scan dependencies for licenses"
-msgstr ""
+msgstr "Scan dependencies for licences"
msgid "LearnGitLab|Scan dependencies for vulnerabilities"
-msgstr ""
+msgstr "Scan dependencies for vulnerabilities"
msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
msgstr ""
@@ -23109,13 +23280,13 @@ msgid "LearnGitLab|Set up CI/CD"
msgstr ""
msgid "LearnGitLab|Set up your first project's CI/CD"
-msgstr ""
+msgstr "Set up your first project's CI/CD"
msgid "LearnGitLab|Set up your workspace"
msgstr ""
msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "Start a free trial of GitLab Ultimate"
msgid "LearnGitLab|Submit a merge request (MR)"
msgstr ""
@@ -23133,7 +23304,7 @@ msgid "LearnGitLab|Your team is growing! You've successfully invited new team me
msgstr ""
msgid "LearnGitlab|- Included in trial"
-msgstr ""
+msgstr "- Included in trial"
msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23874,7 +24087,7 @@ msgid "Marked this %{noun} as a draft."
msgstr ""
msgid "Marked this %{noun} as ready."
-msgstr ""
+msgstr "Marked this %{noun} as ready."
msgid "Marked this issue as a duplicate of %{duplicate_param}."
msgstr ""
@@ -23889,7 +24102,7 @@ msgid "Marks this %{noun} as a draft."
msgstr ""
msgid "Marks this %{noun} as ready."
-msgstr ""
+msgstr "Marks this %{noun} as ready."
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -24463,7 +24676,7 @@ msgid "Merge request events"
msgstr ""
msgid "Merge request locked."
-msgstr ""
+msgstr "Merge request locked."
msgid "Merge request not merged"
msgstr ""
@@ -24472,7 +24685,7 @@ msgid "Merge request reports"
msgstr ""
msgid "Merge request unlocked."
-msgstr ""
+msgstr "Merge request unlocked."
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -24640,7 +24853,7 @@ msgid "MergeRequest|No files found"
msgstr ""
msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
-msgstr ""
+msgstr "Search (e.g. *.vue) (%{modifier_key}P)"
msgid "Merged"
msgstr ""
@@ -24667,7 +24880,7 @@ msgid "Merging immediately isn't recommended as it may negatively impact the exi
msgstr ""
msgid "Mermaid diagram"
-msgstr ""
+msgstr "Mermaid diagram"
msgid "Message"
msgstr ""
@@ -25447,29 +25660,23 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{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 ""
+msgstr "By continuing, you acknowledge that responses will be used to improve GitLab and in accordance with the %{linkStart}GitLab Privacy Policy%{linkEnd}."
msgid "MrSurvey|How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
-msgstr ""
+msgstr "How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
msgid "MrSurvey|Merge request experience survey"
-msgstr ""
+msgstr "Merge request experience survey"
msgid "MrSurvey|Overall, how satisfied are you with merge requests?"
-msgstr ""
+msgstr "Overall, how satisfied are you with merge requests?"
msgid "MrSurvey|Thank you for your feedback!"
-msgstr ""
+msgstr "Thank you for your feedback!"
msgid "Multi-project"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25505,7 +25712,7 @@ msgid "My-Reaction"
msgstr ""
msgid "NEW"
-msgstr ""
+msgstr "NEW"
msgid "Name"
msgstr ""
@@ -25621,7 +25828,7 @@ msgid "NavigationTheme|Dark Mode (alpha)"
msgstr ""
msgid "NavigationTheme|Gray"
-msgstr ""
+msgstr "Grey"
msgid "NavigationTheme|Green"
msgstr ""
@@ -25633,7 +25840,7 @@ msgid "NavigationTheme|Light Blue"
msgstr ""
msgid "NavigationTheme|Light Gray"
-msgstr ""
+msgstr "Light Grey"
msgid "NavigationTheme|Light Green"
msgstr ""
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25788,7 +25992,7 @@ msgid "New epic title"
msgstr ""
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "New error tracking access token has been generated!"
msgid "New file"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25944,7 +26151,7 @@ msgid "No Scopes"
msgstr ""
msgid "No Work Item Link found"
-msgstr ""
+msgstr "No Work Item Link found"
msgid "No active admin user found"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -25977,7 +26181,7 @@ msgid "No branches found"
msgstr ""
msgid "No change to this %{noun}'s draft status."
-msgstr ""
+msgstr "No change to this %{noun}'s draft status."
msgid "No changes"
msgstr ""
@@ -26094,7 +26298,7 @@ msgid "No matches found"
msgstr ""
msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} ID."
-msgstr ""
+msgstr "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} ID."
msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} URL."
msgstr ""
@@ -26178,7 +26382,7 @@ msgid "No repository"
msgstr ""
msgid "No results"
-msgstr ""
+msgstr "No results"
msgid "No runner executable"
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26360,13 +26561,13 @@ msgid "Notes|Collapse replies"
msgstr ""
msgid "Notes|Expand replies"
-msgstr ""
+msgstr "Expand replies"
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 ""
+msgstr "Last reply by %{name}"
msgid "Notes|Make this an internal note"
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26512,10 +26716,10 @@ msgid "Notifications on"
msgstr ""
msgid "Notifications turned off."
-msgstr ""
+msgstr "Notifications turned off."
msgid "Notifications turned on."
-msgstr ""
+msgstr "Notifications turned on."
msgid "Notify users by email when sign-in location is not recognized."
msgstr ""
@@ -26524,25 +26728,34 @@ msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
+msgstr "%{commit_link} in %{mr_link}"
+
+msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
-msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
+msgid "Notify|%{invited_user} has %{highlight_start}declined%{highlight_end} your invitation to join the %{target_link} %{target_name}."
msgstr ""
-msgid "Notify|Assignee changed to %{toNames}"
+msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
msgstr ""
+msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
+msgstr "Assignee changed from %{fromNames} to %{toNames}"
+
+msgid "Notify|Assignee changed to %{toNames}"
+msgstr "Assignee changed to %{toNames}"
+
msgid "Notify|Author: %{author_name}"
msgstr ""
msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
-msgstr ""
+msgstr "Auto DevOps pipeline was disabled for %{project}"
msgid "Notify|CI/CD project settings"
-msgstr ""
+msgstr "CI/CD project settings"
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 "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."
msgid "Notify|Issue was %{issue_status} by %{updated_by}"
msgstr ""
@@ -26551,7 +26764,7 @@ msgid "Notify|Issue was moved to another project."
msgstr ""
msgid "Notify|Learn more about Auto DevOps"
-msgstr ""
+msgstr "Learn more about Auto DevOps"
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
msgstr ""
@@ -26566,40 +26779,40 @@ msgid "Notify|Merge request %{merge_request} was merged"
msgstr ""
msgid "Notify|Merge request %{mr_link} was closed by %{closed_by}"
-msgstr ""
+msgstr "Merge request %{mr_link} was closed by %{closed_by}"
msgid "Notify|Merge request URL: %{merge_request_url}"
msgstr ""
msgid "Notify|Milestone changed to %{milestone}"
-msgstr ""
+msgstr "Milestone changed to %{milestone}"
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
msgid "Notify|Pipeline %{pipeline_link} triggered by"
-msgstr ""
+msgstr "Pipeline %{pipeline_link} triggered by"
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 ""
+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|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."
-msgstr ""
+msgstr "Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
msgid "Notify|You don't have access to the project."
msgstr ""
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
-msgstr ""
+msgstr "Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
msgid "Notify|currently supported languages"
-msgstr ""
+msgstr "currently supported languages"
msgid "Notify|successfully completed %{jobs} in %{stages}."
-msgstr ""
+msgstr "successfully completed %{jobs} in %{stages}."
msgid "Nov"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27075,7 +27293,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "One or more arguments are invalid: %{args}."
-msgstr ""
+msgstr "One or more arguments are invalid: %{args}."
msgid "One or more contacts were successfully added."
msgstr ""
@@ -27102,7 +27320,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 "Only %{workspaceType} members with %{permissions} can view or be notified about this %{issuableType}."
msgid "Only 'Reporter' roles and above on tiers Premium and above can see Value Stream Analytics."
msgstr ""
@@ -27111,7 +27329,7 @@ msgid "Only 1 appearances row can exist"
msgstr ""
msgid "Only HTTP(S)"
-msgstr ""
+msgstr "Only HTTP(S)"
msgid "Only Issue ID or merge request ID is required"
msgstr ""
@@ -27120,10 +27338,10 @@ msgid "Only Project Members"
msgstr ""
msgid "Only SSH"
-msgstr ""
+msgstr "Only SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
-msgstr ""
+msgstr "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
msgid "Only active projects show up in the search and on the dashboard."
msgstr ""
@@ -27135,13 +27353,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 "Only group members with at least the Reporter role can view or be notified about this epic"
msgid "Only include features new to your current subscription tier."
msgstr ""
msgid "Only members of this group can access the wiki."
-msgstr ""
+msgstr "Only members of this group can access the wiki."
msgid "Only policy:"
msgstr ""
@@ -27164,11 +27382,8 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Productivity Analytics."
msgstr ""
@@ -27260,11 +27475,14 @@ 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 ""
+msgstr "Opstrace endpoint for Error Tracking integration"
msgid "Optimize your workflow with CI/CD Pipelines"
msgstr ""
@@ -27282,10 +27500,10 @@ msgid "Options"
msgstr ""
msgid "Or you can choose one of the suggested colors below"
-msgstr ""
+msgstr "Or you can choose one of the suggested colours below"
msgid "Ordered list"
-msgstr ""
+msgstr "Ordered list"
msgid "Organizations"
msgstr ""
@@ -27378,7 +27596,7 @@ msgid "Owner"
msgstr ""
msgid "Owners and administrators"
-msgstr ""
+msgstr "Owners and administrators"
msgid "Owners can modify this selection."
msgstr ""
@@ -27483,10 +27701,10 @@ msgid "PackageRegistry|Add composer registry"
msgstr ""
msgid "PackageRegistry|Additional metadata"
-msgstr ""
+msgstr "Additional metadata"
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 "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."
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,15 +27813,21 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
msgid "PackageRegistry|Duplicate packages"
-msgstr ""
+msgstr "Duplicate packages"
msgid "PackageRegistry|Error publishing"
msgstr ""
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr ""
+
msgid "PackageRegistry|Failed to load the package data"
msgstr ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27713,7 +27954,7 @@ msgid "PackageRegistry|Registry setup"
msgstr ""
msgid "PackageRegistry|Reject packages with the same name and version"
-msgstr ""
+msgstr "Reject packages with the same name and version"
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27758,7 +28002,7 @@ msgid "PackageRegistry|Something went wrong while fetching the package history."
msgstr ""
msgid "PackageRegistry|Something went wrong while fetching the package metadata."
-msgstr ""
+msgstr "Something went wrong while fetching the package metadata."
msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -27983,7 +28238,7 @@ msgid "Paste issue link"
msgstr ""
msgid "Paste link"
-msgstr ""
+msgstr "Paste link"
msgid "Paste project path (i.e. gitlab-org/gitlab)"
msgstr ""
@@ -28049,7 +28304,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 "Per your subscription agreement with GitLab, you must report your licence usage data on a monthly basis. GitLab uses this data to keep your subscription up to date. To report your licence usage data, export your licence usage file and email it to %{renewal_service_email}. If you need an updated licence, GitLab will send the licence to the email address registered in the %{customers_dot}, and you can upload this licence to your instance."
msgid "Percent rollout must be an integer number between 0 and 100"
msgstr ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,22 +28597,34 @@ msgstr ""
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr ""
-msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
+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 "Current content in the Edit tab will be used for the simulation."
+
msgid "PipelineEditor|Git push event to the default branch"
-msgstr ""
+msgstr "Git push event to the default branch"
msgid "PipelineEditor|Other pipeline sources are not available yet."
-msgstr ""
+msgstr "Other pipeline sources are not available yet."
msgid "PipelineEditor|Pipeline Source"
-msgstr ""
+msgstr "Pipeline Source"
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 "Pipeline behaviour will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies."
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 "Pipeline behaviour will be simulated including the %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} and %{codeStart}needs%{codeEnd} job dependencies. %{linkStart}Learn more%{linkEnd}"
+
+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."
@@ -28358,12 +28640,18 @@ msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file
msgstr ""
msgid "PipelineEditor|Validate pipeline"
-msgstr ""
+msgstr "Validate pipeline"
msgid "PipelineEditor|Validate pipeline under selected conditions"
-msgstr ""
+msgstr "Validate pipeline under selected conditions"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
+msgstr "Validate pipeline under simulated conditions"
+
+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})"
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28733,7 +29030,7 @@ msgid "Pipelines|Use template"
msgstr ""
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "Validate"
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28973,7 +29300,7 @@ msgid "PlantUML URL"
msgstr ""
msgid "PlantUML diagram"
-msgstr ""
+msgstr "PlantUML diagram"
msgid "Play"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29063,7 +29393,7 @@ 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 ""
+msgstr "Please enter a valid hex (#RRGGBB or #RGB) colour value"
msgid "Please enter a valid number"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29252,13 +29585,13 @@ msgid "Preferences|Choose what content you want to see on your homepage."
msgstr ""
msgid "Preferences|Color for added lines"
-msgstr ""
+msgstr "Colour for added lines"
msgid "Preferences|Color for removed lines"
-msgstr ""
+msgstr "Colour for removed lines"
msgid "Preferences|Color theme"
-msgstr ""
+msgstr "Colour theme"
msgid "Preferences|Configure how dates and times display for you."
msgstr ""
@@ -29267,13 +29600,13 @@ msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the color of GitLab."
-msgstr ""
+msgstr "Customise the colour of GitLab."
msgid "Preferences|Customize the colors of removed and added lines in diffs."
-msgstr ""
+msgstr "Customise the colours of removed and added lines in diffs."
msgid "Preferences|Diff colors"
-msgstr ""
+msgstr "Diff colours"
msgid "Preferences|Display time in 24-hour format"
msgstr ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29390,7 +29723,7 @@ msgid "Preview changes"
msgstr ""
msgid "Preview diagram"
-msgstr ""
+msgstr "Preview diagram"
msgid "Preview payload"
msgstr ""
@@ -29570,7 +29903,7 @@ msgid "Profiles|An error occurred while updating your username, please try again
msgstr ""
msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
+msgstr "An indicator appears next to your name and avatar."
msgid "Profiles|Avatar cropper"
msgstr ""
@@ -29597,7 +29930,7 @@ 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 "Choose to show contributions of private projects on your public profile without any project, repository or organisation information."
msgid "Profiles|City, country"
msgstr ""
@@ -29612,7 +29945,7 @@ msgid "Profiles|Connect %{provider}"
msgstr ""
msgid "Profiles|Connect a service for sign-in."
-msgstr ""
+msgstr "Connect a service for sign-in."
msgid "Profiles|Connected Accounts"
msgstr ""
@@ -29642,7 +29975,7 @@ msgid "Profiles|Do not show on profile"
msgstr ""
msgid "Profiles|Don't display activity-related personal information on your profile."
-msgstr ""
+msgstr "Don't display activity-related personal information on your profile."
msgid "Profiles|Edit Profile"
msgstr ""
@@ -29651,16 +29984,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 "Enter how your name is pronounced to help people address you correctly."
msgid "Profiles|Enter your name, so people you know can recognize you."
-msgstr ""
+msgstr "Enter your name, so people you know can recognise you."
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 "Enter your pronouns to let people know how to refer to you."
msgid "Profiles|Example: MacBook key"
msgstr ""
@@ -29693,7 +30026,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 "Increase your account's security by enabling two-factor authentication (2FA)."
msgid "Profiles|Invalid password"
msgstr ""
@@ -29780,13 +30113,13 @@ msgid "Profiles|Select a service to sign in with."
msgstr ""
msgid "Profiles|Service sign-in"
-msgstr ""
+msgstr "Service sign-in"
msgid "Profiles|Set new profile picture"
msgstr ""
msgid "Profiles|Set your local time zone."
-msgstr ""
+msgstr "Set your local time zone."
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
@@ -29795,7 +30128,7 @@ msgid "Profiles|Static object token was successfully reset"
msgstr ""
msgid "Profiles|Tell us about yourself in fewer than 250 characters."
-msgstr ""
+msgstr "Tell us about yourself in fewer than 250 characters."
msgid "Profiles|The ability to update your name has been disabled by your administrator."
msgstr ""
@@ -29804,16 +30137,16 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
msgid "Profiles|This email will be displayed on your public profile."
-msgstr ""
+msgstr "This email will be displayed on your public profile."
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 "This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more.%{commit_email_link_end}"
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 ""
+msgstr "This information will appear on your profile."
msgid "Profiles|Time settings"
msgstr ""
@@ -29822,7 +30155,7 @@ msgid "Profiles|Title"
msgstr ""
msgid "Profiles|Two-factor authentication"
-msgstr ""
+msgstr "Two-factor authentication"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
@@ -29858,7 +30191,7 @@ msgid "Profiles|What's your status?"
msgstr ""
msgid "Profiles|Who you represent or work for."
-msgstr ""
+msgstr "Who you represent or work for."
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -29900,7 +30233,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 ""
+msgstr "Your name was automatically set based on your %{provider_label} account, so people you know can recognise you."
msgid "Profiles|Your status"
msgstr ""
@@ -29981,7 +30314,7 @@ 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 ""
+msgstr "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."
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 ""
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30104,7 +30446,7 @@ msgid "ProjectCreationLevel|No one"
msgstr ""
msgid "ProjectCreationLevel|Roles allowed to create projects"
-msgstr ""
+msgstr "Roles allowed to create projects"
msgid "ProjectFileTree|Name"
msgstr ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -30218,7 +30569,7 @@ msgid "ProjectSelect|Select a project"
msgstr ""
msgid "ProjectSelect|Something went wrong while fetching projects"
-msgstr ""
+msgstr "Something went wrong while fetching projects"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
msgstr ""
@@ -30698,7 +31049,7 @@ msgid "ProjectSettings|What are merge trains?"
msgstr ""
msgid "ProjectSettings|What is squashing?"
-msgstr ""
+msgstr "What is squashing?"
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 ""
@@ -30839,7 +31190,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 "Projects in this group can use Git LFS"
msgid "Projects shared with %{group_name}"
msgstr ""
@@ -30908,7 +31259,7 @@ 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 ""
+msgstr "Create a blank project to store your files, plan your work, and collaborate on code, among other things."
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
msgstr ""
@@ -30968,7 +31319,7 @@ 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 "Want to organise several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
msgid "PrometheusAlerts|exceeded"
msgstr ""
@@ -31127,7 +31478,7 @@ msgid "Promotions|Buy GitLab Enterprise Edition"
msgstr ""
msgid "Promotions|Configure Service Desk"
-msgstr ""
+msgstr "Configure Service Desk"
msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -31142,7 +31493,7 @@ msgid "Promotions|Description templates allow you to define context-specific tem
msgstr ""
msgid "Promotions|Dismiss Service Desk promotion"
-msgstr ""
+msgstr "Dismiss Service Desk promotion"
msgid "Promotions|Dismiss burndown charts promotion"
msgstr ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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|Only specified groups can execute deployments in protected environments."
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
msgstr ""
+msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
+msgstr "Only specified groups can execute deployments in protected environments."
+
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
msgstr ""
+msgid "ProtectedEnvironment|Parent group"
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr ""
@@ -31418,7 +31787,7 @@ msgid "ProtectedEnvironment|Select an environment"
msgstr ""
msgid "ProtectedEnvironment|Select groups"
-msgstr ""
+msgstr "Select groups"
msgid "ProtectedEnvironment|Select users"
msgstr ""
@@ -31466,7 +31835,7 @@ msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to dep
msgstr ""
msgid "Provide Feedback"
-msgstr ""
+msgstr "Provide Feedback"
msgid "Provide a number our sales team can use to call you."
msgstr ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31781,7 +32156,7 @@ msgid "Rebase"
msgstr ""
msgid "Rebase completed"
-msgstr ""
+msgstr "Rebase completed"
msgid "Rebase in progress"
msgstr ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32031,7 +32403,7 @@ msgid "Release assets documentation"
msgstr ""
msgid "Release date"
-msgstr ""
+msgstr "Release date"
msgid "Release does not have the same project as the milestone"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32454,7 +32814,7 @@ msgid "Replication"
msgstr ""
msgid "Reply"
-msgstr ""
+msgstr "Reply"
msgid "Reply by email"
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,9 +32846,12 @@ msgstr ""
msgid "Report for the scan has been removed from the database."
msgstr ""
-msgid "Report your license usage data to GitLab"
+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 "Report your licence usage data to GitLab"
+
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
@@ -32547,10 +32913,10 @@ msgid "Reports|Classname"
msgstr ""
msgid "Reports|Copy failed test names to run locally"
-msgstr ""
+msgstr "Copy failed test names to run locally"
msgid "Reports|Copy failed tests"
-msgstr ""
+msgstr "Copy failed tests"
msgid "Reports|Execution time"
msgstr ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32976,7 +33327,7 @@ msgid "Reset"
msgstr ""
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "Reset error tracking access token"
msgid "Reset file"
msgstr ""
@@ -33081,7 +33432,7 @@ msgid "Restoring the project will prevent the project from being removed on this
msgstr ""
msgid "Restrict access by IP address"
-msgstr ""
+msgstr "Restrict access by IP address"
msgid "Restrict membership by email domain"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33308,7 +33658,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 "A new version is available"
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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33412,7 +33765,7 @@ msgid "Runners|Download latest binary"
msgstr ""
msgid "Runners|Edit your search and try again"
-msgstr ""
+msgstr "Edit your search and try again"
msgid "Runners|Enable stale runner cleanup"
msgstr ""
@@ -33427,13 +33780,13 @@ msgid "Runners|Executor"
msgstr ""
msgid "Runners|Get started with runners"
-msgstr ""
+msgstr "Get started with runners"
msgid "Runners|Group"
msgstr ""
msgid "Runners|How do we upgrade GitLab runner?"
-msgstr ""
+msgstr "How do we upgrade GitLab runner?"
msgid "Runners|IP Address"
msgstr ""
@@ -33481,7 +33834,7 @@ msgid "Runners|New registration token generated!"
msgstr ""
msgid "Runners|No results found"
-msgstr ""
+msgstr "No results found"
msgid "Runners|No spot. Default choice for Windows Shell executor."
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33624,7 +33983,7 @@ 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."
-msgstr ""
+msgstr "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|Runs untagged jobs"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33692,7 +34054,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 "This runner is outdated, an upgrade is recommended"
msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
msgstr ""
@@ -33700,14 +34062,23 @@ 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|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 "Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
+
+msgid "Runners|Upgrade Status"
msgstr ""
msgid "Runners|Upgrade available"
-msgstr ""
+msgstr "Upgrade available"
msgid "Runners|Upgrade recommended"
-msgstr ""
+msgstr "Upgrade recommended"
msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
msgstr ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33773,9 +34150,12 @@ msgid "Runners|stale"
msgstr ""
msgid "Runners|upgrade available"
-msgstr ""
+msgstr "upgrade available"
msgid "Runners|upgrade recommended"
+msgstr "upgrade recommended"
+
+msgid "Runner|Owner"
msgstr ""
msgid "Running"
@@ -33800,19 +34180,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 "Selecting \"Authorise\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organisation."
msgid "SAML|Sign in to GitLab to connect your organization's account"
-msgstr ""
+msgstr "Sign in to GitLab to connect your organisation's account"
msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
-msgstr ""
+msgstr "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
-msgstr ""
+msgstr "To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
-msgstr ""
+msgstr "Your organisation's SSO has been connected to your GitLab account"
msgid "SAST Configuration"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34464,10 +34874,10 @@ msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request
msgstr ""
msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
+msgstr "+%{count} more"
msgid "SecurityOrchestration|, and %{count} more"
-msgstr ""
+msgstr ", and %{count} more"
msgid "SecurityOrchestration|.yaml mode"
msgstr ""
@@ -34485,7 +34895,7 @@ msgid "SecurityOrchestration|After dismissing the alert, the information will ne
msgstr ""
msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group."
-msgstr ""
+msgstr "After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group."
msgid "SecurityOrchestration|All policies"
msgstr ""
@@ -34530,7 +34940,7 @@ msgid "SecurityOrchestration|Description"
msgstr ""
msgid "SecurityOrchestration|Direct"
-msgstr ""
+msgstr "Direct"
msgid "SecurityOrchestration|Don't show the alert anymore"
msgstr ""
@@ -34557,13 +34967,19 @@ msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More
msgstr ""
msgid "SecurityOrchestration|Failed to load cluster agents."
+msgstr "Failed to load cluster agents."
+
+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 ""
+msgstr "Inherited"
msgid "SecurityOrchestration|Inherited from %{namespace}"
msgstr ""
@@ -34724,17 +35140,20 @@ 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 group"
msgstr ""
msgid "SecurityOrchestration|This is a group-level policy"
-msgstr ""
+msgstr "This is a group-level policy"
msgid "SecurityOrchestration|This is a project-level policy"
-msgstr ""
+msgstr "This is a project-level policy"
msgid "SecurityOrchestration|This policy is inherited from %{namespace}"
-msgstr ""
+msgstr "This policy is inherited from %{namespace}"
msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34761,7 +35177,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 "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."
msgid "SecurityOrchestration|Use a scan result policy to create rules that ensure security issues are checked before merging a merge request."
msgstr ""
@@ -34836,7 +35252,7 @@ msgid "SecurityReports|Check the messages generated while parsing the following
msgstr ""
msgid "SecurityReports|Cluster"
-msgstr ""
+msgstr "Cluster"
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
msgstr ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35142,10 +35570,10 @@ msgid "Select a branch"
msgstr ""
msgid "Select a branch to compare"
-msgstr ""
+msgstr "Select a branch to compare"
msgid "Select a color"
-msgstr ""
+msgstr "Select a colour"
msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
msgstr ""
@@ -35262,7 +35690,7 @@ msgid "Select source branch"
msgstr ""
msgid "Select source project"
-msgstr ""
+msgstr "Select source project"
msgid "Select start date"
msgstr ""
@@ -35286,7 +35714,7 @@ msgid "Select target branch or tag"
msgstr ""
msgid "Select target project"
-msgstr ""
+msgstr "Select target project"
msgid "Select timezone"
msgstr ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35574,7 +35993,7 @@ msgid "Set target branch to %{branch_name}."
msgstr ""
msgid "Set the Ready status"
-msgstr ""
+msgstr "Set the Ready status"
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 ""
@@ -35640,7 +36059,7 @@ msgid "Set up your project to automatically push and/or pull changes to/from ano
msgstr ""
msgid "Set visibility of project contents. Configure import sources and Git access protocols."
-msgstr ""
+msgstr "Set visibility of project contents. Configure import sources and Git access protocols."
msgid "Set weight"
msgstr ""
@@ -35906,64 +36325,64 @@ msgid "Show whitespace changes"
msgstr ""
msgid "ShowcaseSecurity|Access a dedicated area for vulnerability management. This includes a security dashboard, vulnerability report, and settings."
-msgstr ""
+msgstr "Access a dedicated area for vulnerability management. This includes a security dashboard, vulnerability report, and settings."
msgid "ShowcaseSecurity|Audit your Docker-based app. Scan for known vulnerabilities in the Docker images where your code is shipped."
-msgstr ""
+msgstr "Audit your Docker-based app. Scan for known vulnerabilities in the Docker images where your code is shipped."
msgid "ShowcaseSecurity|Container scanning"
-msgstr ""
+msgstr "Container scanning"
msgid "ShowcaseSecurity|Dependency scanning"
-msgstr ""
+msgstr "Dependency scanning"
msgid "ShowcaseSecurity|Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "Dynamic Application Security Testing (DAST)"
msgid "ShowcaseSecurity|Dynamically examine your application for vulnerabilities in deployed environments."
-msgstr ""
+msgstr "Dynamically examine your application for vulnerabilities in deployed environments."
msgid "ShowcaseSecurity|Enable SAST"
-msgstr ""
+msgstr "Enable SAST"
msgid "ShowcaseSecurity|Enable Secret Detection"
-msgstr ""
+msgstr "Enable Secret Detection"
msgid "ShowcaseSecurity|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "Enable Static Application Security Testing (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 "Find out if your external libraries are safe. Run dependency scanning jobs that check for known vulnerabilities in your external libraries."
msgid "ShowcaseSecurity|Identify vulnerabilities in your code now"
-msgstr ""
+msgstr "Identify vulnerabilities in your code now"
msgid "ShowcaseSecurity|Scan your code to detect unintentionally committed secrets, like keys, passwords, and API tokens."
-msgstr ""
+msgstr "Scan your code to detect unintentionally committed secrets, like keys, passwords, and API tokens."
msgid "ShowcaseSecurity|Scan your source code using GitLab CI/CD and uncover vulnerabilities before deploying."
-msgstr ""
+msgstr "Scan your source code using GitLab CI/CD and uncover vulnerabilities before deploying."
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 "Start a free 30-day Ultimate trial or upgrade your instance to access organisation-wide security and compliance features. See the other features of the Ultimate plan."
msgid "ShowcaseSecurity|Start a free trial"
-msgstr ""
+msgstr "Start a free trial"
msgid "ShowcaseSecurity|Take your security to the next level"
-msgstr ""
+msgstr "Take your security to the next level"
msgid "ShowcaseSecurity|Upgrade now"
-msgstr ""
+msgstr "Upgrade now"
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 "Use GitLab CI/CD to analyse your source code for known vulnerabilities. Compare the found vulnerabilities between your source and target branches."
msgid "ShowcaseSecurity|Vulnerability management"
-msgstr ""
+msgstr "Vulnerability management"
msgid "Showing %{conflict}"
-msgstr ""
+msgstr "Showing %{conflict}"
msgid "Showing %{count} of %{total} projects"
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36325,14 +36750,11 @@ msgid "Snowplow"
msgstr ""
msgid "Solid"
-msgstr ""
+msgstr "Solid"
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -36850,7 +37272,7 @@ msgid "Speed up your pipelines with Needs relationships"
msgstr ""
msgid "Spent at"
-msgstr ""
+msgstr "Spent at"
msgid "Squash commit message"
msgstr ""
@@ -37195,7 +37617,7 @@ msgid "StorageSize|Unknown"
msgstr ""
msgid "Store your files, plan your work, collaborate on code, and more."
-msgstr ""
+msgstr "Store your files, plan your work, collaborate on code, and more."
msgid "Strikethrough"
msgstr ""
@@ -37219,7 +37641,7 @@ msgid "Subgroup navigation"
msgstr ""
msgid "SubgroupCreationLevel|Roles allowed to create subgroups"
-msgstr ""
+msgstr "Roles allowed to create subgroups"
msgid "SubgroupCreationlevel|Allowed to create subgroups"
msgstr ""
@@ -37237,7 +37659,7 @@ msgid "Subgroups and projects"
msgstr ""
msgid "Subgroups can set up their own two-factor authentication rules"
-msgstr ""
+msgstr "Subgroups can set up their own two-factor authentication rules"
msgid "Subject Key Identifier:"
msgstr ""
@@ -37303,7 +37725,7 @@ msgid "Subscribes to this %{quick_action_target}."
msgstr ""
msgid "Subscript"
-msgstr ""
+msgstr "Subscript"
msgid "Subscription"
msgstr ""
@@ -37333,7 +37755,7 @@ msgid "SubscriptionBanner|Export license usage file"
msgstr ""
msgid "SubscriptionBanner|Upload new license"
-msgstr ""
+msgstr "Upload new licence"
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37507,88 +37926,88 @@ msgid "Suggested change"
msgstr ""
msgid "SuggestedColors|Aztec Gold"
-msgstr ""
+msgstr "Aztec Gold"
msgid "SuggestedColors|Blue"
-msgstr ""
+msgstr "Blue"
msgid "SuggestedColors|Blue-gray"
-msgstr ""
+msgstr "Blue-grey"
msgid "SuggestedColors|Carrot orange"
-msgstr ""
+msgstr "Carrot orange"
msgid "SuggestedColors|Champagne"
-msgstr ""
+msgstr "Champagne"
msgid "SuggestedColors|Charcoal grey"
-msgstr ""
+msgstr "Charcoal grey"
msgid "SuggestedColors|Crimson"
-msgstr ""
+msgstr "Crimson"
msgid "SuggestedColors|Current addition color"
-msgstr ""
+msgstr "Current addition colour"
msgid "SuggestedColors|Current removal color"
-msgstr ""
+msgstr "Current removal colour"
msgid "SuggestedColors|Dark coral"
-msgstr ""
+msgstr "Dark coral"
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "Dark green"
msgid "SuggestedColors|Dark sea green"
-msgstr ""
+msgstr "Dark sea green"
msgid "SuggestedColors|Dark violet"
-msgstr ""
+msgstr "Dark violet"
msgid "SuggestedColors|Deep violet"
-msgstr ""
+msgstr "Deep violet"
msgid "SuggestedColors|Default addition color"
-msgstr ""
+msgstr "Default addition colour"
msgid "SuggestedColors|Default removal color"
-msgstr ""
+msgstr "Default removal colour"
msgid "SuggestedColors|Gray"
-msgstr ""
+msgstr "Grey"
msgid "SuggestedColors|Green"
-msgstr ""
+msgstr "Green"
msgid "SuggestedColors|Green screen"
-msgstr ""
+msgstr "Green screen"
msgid "SuggestedColors|Green-cyan"
-msgstr ""
+msgstr "Green-cyan"
msgid "SuggestedColors|Lavendar"
-msgstr ""
+msgstr "Lavender"
msgid "SuggestedColors|Magenta-pink"
-msgstr ""
+msgstr "Magenta-pink"
msgid "SuggestedColors|Medium sea green"
-msgstr ""
+msgstr "Medium sea green"
msgid "SuggestedColors|Orange"
-msgstr ""
+msgstr "Orange"
msgid "SuggestedColors|Purple"
-msgstr ""
+msgstr "Purple"
msgid "SuggestedColors|Red"
-msgstr ""
+msgstr "Red"
msgid "SuggestedColors|Rose red"
-msgstr ""
+msgstr "Rose red"
msgid "SuggestedColors|Titanium yellow"
-msgstr ""
+msgstr "Titanium yellow"
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
@@ -37612,10 +38031,10 @@ msgid "Summary"
msgstr ""
msgid "Summary / note"
-msgstr ""
+msgstr "Summary / note"
msgid "Summary comment (optional)"
-msgstr ""
+msgstr "Summary comment (optional)"
msgid "Sunday"
msgstr ""
@@ -37785,7 +38204,7 @@ msgid "SuperSonics|past subscriptions"
msgstr ""
msgid "Superscript"
-msgstr ""
+msgstr "Superscript"
msgid "Support"
msgstr ""
@@ -37796,23 +38215,20 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
-msgstr ""
+msgstr "Delighted"
msgid "Surveys|Happy"
-msgstr ""
+msgstr "Happy"
msgid "Surveys|Neutral"
-msgstr ""
+msgstr "Neutral"
msgid "Surveys|Sad"
-msgstr ""
+msgstr "Sad"
msgid "Surveys|Unhappy"
-msgstr ""
+msgstr "Unhappy"
msgid "Switch Branches"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38088,10 +38510,7 @@ msgid "Task ID: %{elastic_task}"
msgstr ""
msgid "Task list"
-msgstr ""
-
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
+msgstr "Task list"
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38442,7 +38861,7 @@ msgid "TestReports|Attachment"
msgstr ""
msgid "TestReports|Copy test name to rerun locally"
-msgstr ""
+msgstr "Copy test name to rerun locally"
msgid "TestReports|Job artifacts are expired"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38630,7 +39046,7 @@ msgid "The current epic"
msgstr ""
msgid "The current incident"
-msgstr ""
+msgstr "The current incident"
msgid "The current issue"
msgstr ""
@@ -38645,7 +39061,7 @@ msgid "The data source is connected, but there is no data to display. %{document
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 ""
+msgstr "The date when the release is ready. A release with a date in the future is labelled as an %{linkStart}Upcoming Release%{linkEnd}."
msgid "The default CI/CD configuration file and path for new projects."
msgstr ""
@@ -38672,7 +39088,7 @@ msgid "The download link will expire in 24 hours."
msgstr ""
msgid "The environment tiers must be from %{environment_tiers}."
-msgstr ""
+msgstr "The environment tiers must be from %{environment_tiers}."
msgid "The errors we encountered were:"
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38826,7 +39239,7 @@ 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 ""
+msgstr "The maximum amount of time users have to set up two-factor authentication before it's enforced."
msgid "The maximum file size allowed is %{size}."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39120,7 +39539,7 @@ msgid "There are no projects shared with this group yet"
msgstr ""
msgid "There are no secure files yet."
-msgstr ""
+msgstr "There are no secure files yet."
msgid "There are no topics to show."
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39168,10 +39590,10 @@ msgid "There was a problem communicating with your device."
msgstr ""
msgid "There was a problem fetching CRM contacts."
-msgstr ""
+msgstr "There was a problem fetching CRM contacts."
msgid "There was a problem fetching CRM organizations."
-msgstr ""
+msgstr "There was a problem fetching CRM organisations."
msgid "There was a problem fetching branches."
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39915,6 +40331,12 @@ msgid "This project will be deleted on %{date} since its parent group '%{parent_
msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+msgstr "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+
+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"
@@ -39939,7 +40361,7 @@ 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 ""
+msgstr "This setting has been configured at the instance level and cannot be overridden per group"
msgid "This setting is allowed for forked projects only"
msgstr ""
@@ -40083,10 +40505,10 @@ msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
msgstr ""
msgid "TimeTracking|An error occurred while removing the timelog."
-msgstr ""
+msgstr "An error occurred while removing the timelog."
msgid "TimeTracking|Delete time spent"
-msgstr ""
+msgstr "Delete time spent"
msgid "TimeTracking|Estimated:"
msgstr ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40573,7 +40995,7 @@ msgid "Toggle sidebar"
msgstr ""
msgid "Toggle the Draft status"
-msgstr ""
+msgstr "Toggle the Draft status"
msgid "Toggle the Performance Bar"
msgstr ""
@@ -40615,19 +41037,22 @@ 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 ""
+msgstr "Too many references. Quick actions are limited to at most %{max_count} user references"
msgid "Too many users found. Quick actions are limited to at most %{max_count} users"
-msgstr ""
+msgstr "Too many users found. Quick actions are limited to at most %{max_count} users"
msgid "TopNav|Go back"
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 ""
+msgstr "Topic %{topic_name} was successfully removed."
msgid "Topic avatar"
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -40993,7 +41421,7 @@ msgid "Two-factor authentication disabled"
msgstr ""
msgid "Two-factor authentication grace period"
-msgstr ""
+msgstr "Two-factor authentication grace period"
msgid "Two-factor authentication has been disabled for this user"
msgstr ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,9 +41564,12 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to parse the vulnerability report's options."
+msgid "Unable to parse JSON"
msgstr ""
+msgid "Unable to parse the vulnerability report's options."
+msgstr "Unable to parse the vulnerability report's options."
+
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -41179,7 +41613,7 @@ 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 "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}"
msgid "Unassign from commenting user"
msgstr ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41479,7 +41913,7 @@ msgid "Upload object map"
msgstr ""
msgid "Uploaded date"
-msgstr ""
+msgstr "Uploaded date"
msgid "Uploading changes to terminal"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41518,7 +41949,7 @@ msgid "UsageQuota|Artifacts"
msgstr ""
msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
-msgstr ""
+msgstr "Artefacts is a sum of build and pipeline artefacts."
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41644,7 +42078,7 @@ msgid "UsageQuota|Something went wrong while fetching project storage statistics
msgstr ""
msgid "UsageQuota|Something went wrong while loading usage details"
-msgstr ""
+msgstr "Something went wrong while loading usage details"
msgid "UsageQuota|Storage"
msgstr ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41863,7 +42309,7 @@ msgid "Use cURL"
msgstr ""
msgid "Use custom color #FF0000"
-msgstr ""
+msgstr "Use custom colour #FF0000"
msgid "Use double quotes for multiple keywords, such as %{code_open}\"your search\"%{code_close}"
msgstr ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42274,10 +42734,10 @@ msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Te
msgstr ""
msgid "Users can request access (if visibility is public or internal)"
-msgstr ""
+msgstr "Users can request access (if visibility is public or internal)"
msgid "Users cannot be added to projects in this group"
-msgstr ""
+msgstr "Users cannot be added to projects in this group"
msgid "Users in License"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43200,7 +43670,7 @@ 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 ""
+msgstr "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."
msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
msgstr ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43796,7 +44277,7 @@ msgid "Will deploy to"
msgstr ""
msgid "Wireframe"
-msgstr ""
+msgstr "Wireframe"
msgid "With requirements, you can set criteria to check your products against."
msgstr ""
@@ -43816,28 +44297,34 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add assignee"
+msgid "WorkItem|Add a title"
msgstr ""
+msgid "WorkItem|Add assignee"
+msgstr "Add assignee"
+
msgid "WorkItem|Add assignees"
+msgstr "Add assignees"
+
+msgid "WorkItem|Add task"
msgstr ""
msgid "WorkItem|Are you sure you want to cancel editing?"
-msgstr ""
+msgstr "Are you sure you want to cancel editing?"
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Assignee"
+msgstr[1] "Assignees"
msgid "WorkItem|Cancel"
msgstr ""
@@ -43845,36 +44332,54 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
-msgid "WorkItem|Closed"
+msgid "WorkItem|Child removed"
msgstr ""
+msgid "WorkItem|Closed"
+msgstr "Closed"
+
msgid "WorkItem|Collapse child items"
msgstr ""
msgid "WorkItem|Create task"
-msgstr ""
+msgstr "Create task"
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
-msgstr ""
+msgstr "Open"
+
+msgid "WorkItem|Remove"
+msgstr "Remove"
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "Something went wrong when creating a task. Please try again"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "Something went wrong when deleting the task. Please try again."
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 "Something went wrong when trying to add a child. Please try again."
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr "Task deleted"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr "Undo"
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr "work items"
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44019,7 +44545,7 @@ msgid "You are going to turn off the confidentiality. This means %{strongStart}e
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 ""
+msgstr "You are going to turn on confidentiality. Only %{context} members with %{strongStart}%{permissions}%{strongEnd} can view or be notified about this %{issuableType}."
msgid "You are not allowed to %{action} a user"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44417,7 +44935,7 @@ msgid "You have insufficient permissions to create an on-call schedule for this
msgstr ""
msgid "You have insufficient permissions to manage resource links for this incident"
-msgstr ""
+msgstr "You have insufficient permissions to manage resource links for this incident"
msgid "You have insufficient permissions to manage timeline events for this incident"
msgstr ""
@@ -44432,7 +44950,7 @@ msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
msgid "You have insufficient permissions to remove this Namespace Ban"
-msgstr ""
+msgstr "You have insufficient permissions to remove this Namespace Ban"
msgid "You have insufficient permissions to set customer relations contacts for this issue"
msgstr ""
@@ -44603,33 +45121,36 @@ 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 ""
+msgstr "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}"
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 "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}"
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 ""
+msgstr "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}"
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 ""
+msgstr "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}"
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 ""
+msgstr "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}"
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 ""
+msgstr "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}"
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 "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}"
+
+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."
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44657,9 +45175,9 @@ msgid "Your %{spammable_entity_type} has been recognized as spam and has been di
msgstr ""
msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "Your %{spammable_entity_type} has been recognised as spam. Please, change the content or solve the reCAPTCHA to proceed."
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44900,7 +45428,7 @@ msgid "Your profile"
msgstr ""
msgid "Your project has limited quotas and features"
-msgstr ""
+msgstr "Your project has limited quotas and features"
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
msgstr ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44952,19 +45477,17 @@ 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] ""
+msgstr[0] "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seat remaining."
+msgstr[1] "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
+msgstr "Your update failed. You can only upload one design when dropping onto an existing design."
msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
-msgstr ""
+msgstr "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
msgid "Your username is %{username}."
msgstr ""
@@ -45039,7 +45562,7 @@ msgid "`start_time` should precede `end_time`"
msgstr ""
msgid "`work_items_hierarchy` feature flag disabled for this project"
-msgstr ""
+msgstr "`work_items_hierarchy` feature flag disabled for this project"
msgid "a deleted user"
msgstr ""
@@ -45071,7 +45594,7 @@ msgid "allowed to fail"
msgstr ""
msgid "already banned from namespace"
-msgstr ""
+msgstr "already banned from namespace"
msgid "already being used for another group or project %{timebox_name}."
msgstr ""
@@ -45106,19 +45629,22 @@ msgid "archived:"
msgstr ""
msgid "artifacts"
-msgstr ""
+msgstr "artefacts"
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
msgid "at least the Reporter role"
-msgstr ""
+msgstr "at least the Reporter role"
msgid "at least the Reporter role, the author, and assignees"
-msgstr ""
+msgstr "at least the Reporter role, the author, and assignees"
msgid "at risk"
msgstr ""
@@ -45174,7 +45700,7 @@ msgid "can only have one escalation policy"
msgstr ""
msgid "can't be enabled when delayed group deletion is disabled"
-msgstr ""
+msgstr "can't be enabled when delayed group deletion is disabled"
msgid "can't be nil"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45219,7 +45748,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 "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
msgid "cannot be used for user namespace"
msgstr ""
@@ -45292,11 +45821,17 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
+msgstr ""
+
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
+msgstr "%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
+
+msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
msgstr ""
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
-msgstr ""
+msgstr "%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
msgid "ciReport|: Loading resulted in an error"
msgstr ""
@@ -45308,6 +45843,9 @@ msgid "ciReport|API fuzzing"
msgstr ""
msgid "ciReport|All clusters"
+msgstr "All clusters"
+
+msgid "ciReport|All images"
msgstr ""
msgid "ciReport|All projects"
@@ -45326,7 +45864,7 @@ msgid "ciReport|Automatically apply the patch in a new branch"
msgstr ""
msgid "ciReport|Base pipeline codequality artifact not found"
-msgstr ""
+msgstr "Base pipeline codequality artefact not found"
msgid "ciReport|Browser Performance"
msgstr ""
@@ -45446,13 +45984,13 @@ msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
msgid "ciReport|License Compliance"
-msgstr ""
+msgstr "Licence Compliance"
msgid "ciReport|License Compliance failed loading results"
-msgstr ""
+msgstr "Licence Compliance failed loading results"
msgid "ciReport|License Compliance test metrics results are being parsed"
-msgstr ""
+msgstr "Licence Compliance test metrics results are being parsed"
msgid "ciReport|Load Performance"
msgstr ""
@@ -45478,10 +46016,10 @@ msgid "ciReport|Loading Code Quality report"
msgstr ""
msgid "ciReport|Manage Licenses"
-msgstr ""
+msgstr "Manage Licences"
msgid "ciReport|Manage licenses"
-msgstr ""
+msgstr "Manage licences"
msgid "ciReport|Manually Added"
msgstr ""
@@ -45578,11 +46116,14 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
msgid "closed %{timeago}"
-msgstr ""
+msgstr "closed %{timeago}"
msgid "closed issue"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45665,7 +46206,7 @@ msgid "deleted"
msgstr ""
msgid "denied"
-msgstr ""
+msgstr "denied"
msgid "deploy"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45780,7 +46324,7 @@ msgid "following"
msgstr ""
msgid "for"
-msgstr ""
+msgstr "for"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
msgstr ""
@@ -45823,22 +46367,19 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
msgid "groups and projects"
-msgstr ""
+msgstr "groups and projects"
msgid "groups only"
-msgstr ""
+msgstr "groups only"
msgid "had %{count} failed job"
msgid_plural "had %{count} failed jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "had %{count} failed job"
+msgstr[1] "had %{count} failed jobs"
msgid "has already been linked to another vulnerability"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45972,7 +46516,7 @@ msgid "is read-only"
msgstr ""
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
-msgstr ""
+msgstr "is too long (%{current_value}). The maximum size is %{max_size}."
msgid "is too long (maximum is %{count} characters)"
msgstr ""
@@ -45999,7 +46543,7 @@ msgid "it is larger than %{limit}"
msgstr ""
msgid "it is stored as a job artifact"
-msgstr ""
+msgstr "it is stored as a job artefact"
msgid "it is stored externally"
msgstr ""
@@ -46014,7 +46558,7 @@ msgid "jigsaw is not defined"
msgstr ""
msgid "kuromoji custom analyzer"
-msgstr ""
+msgstr "kuromoji custom analyser"
msgid "last commit:"
msgstr ""
@@ -46052,14 +46596,17 @@ 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 ""
+msgstr "Displaying this maths block may cause performance issues on this page"
msgid "math|There was an error rendering this math block"
-msgstr ""
+msgstr "There was an error rendering this maths block"
msgid "member"
msgid_plural "members"
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46117,7 +46658,7 @@ msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHead
msgstr ""
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "%{linkStart}Set up now%{linkEnd} to analyse your source code for known security vulnerabilities."
msgid "mrWidget|%{mergeError}."
msgstr ""
@@ -46162,10 +46703,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 "Approval rule %{rules} is invalid. GitLab has approved this rule automatically to unblock the merge request. %{link}"
msgid "mrWidget|Approval rules %{rules} are invalid. GitLab has approved these rules automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "Approval rules %{rules} are invalid. GitLab has approved these rules automatically to unblock the merge request. %{link}"
msgid "mrWidget|Approve"
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,17 +46802,14 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
-msgstr ""
+msgstr "Merge blocked: All required approvals must be given."
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
msgid "mrWidget|Merge blocked: denied licenses must be removed."
-msgstr ""
+msgstr "Merge blocked: denied licences must be removed."
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46337,7 +46866,7 @@ msgid "mrWidget|More information"
msgstr ""
msgid "mrWidget|No users match the rule's criteria."
-msgstr ""
+msgstr "No users match the rule's criteria."
msgid "mrWidget|Please restore it or use a different %{type} branch."
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46514,10 +47031,10 @@ msgid "none"
msgstr ""
msgid "not authorized to create member"
-msgstr ""
+msgstr "not authorised to create member"
msgid "not authorized to update member"
-msgstr ""
+msgstr "not authorised to update member"
msgid "not found"
msgstr ""
@@ -46538,10 +47055,10 @@ msgid "on track"
msgstr ""
msgid "only %{parent_types} can be parent of Task."
-msgstr ""
+msgstr "only %{parent_types} can be parent of Task."
msgid "only Task can be assigned as a child in hierarchy."
-msgstr ""
+msgstr "only Task can be assigned as a child in hierarchy."
msgid "only available on top-level groups."
msgstr ""
@@ -46553,7 +47070,7 @@ msgid "or"
msgstr ""
msgid "organizations can only be added to root groups"
-msgstr ""
+msgstr "organisations can only be added to root groups"
msgid "other card matches"
msgstr ""
@@ -46575,10 +47092,10 @@ msgstr[0] ""
msgstr[1] ""
msgid "parent already has maximum number of children."
-msgstr ""
+msgstr "parent already has maximum number of children."
msgid "parent must be in the same project as child."
-msgstr ""
+msgstr "parent must be in the same project as child."
msgid "password"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46767,7 +47290,7 @@ msgid "should be an array of %{object_name} objects"
msgstr ""
msgid "should be an array of existing usernames. %{invalid} does not exist"
-msgstr ""
+msgstr "should be an array of existing usernames. %{invalid} does not exist"
msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr ""
@@ -46785,7 +47308,7 @@ msgid "sign in"
msgstr ""
msgid "smartcn custom analyzer"
-msgstr ""
+msgstr "smartcn custom analyser"
msgid "source"
msgstr ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
@@ -46991,10 +47517,10 @@ msgid "yaml invalid"
msgstr ""
msgid "your GitLab instance"
-msgstr ""
+msgstr "your GitLab instance"
msgid "your group (%{group_name})"
-msgstr ""
+msgstr "your group (%{group_name})"
msgid "your settings"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index e9ea2884d93..ae440d85a4c 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-07-14 17:15\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branĉoj"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Krei novan dosierujon"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Disponigado"
msgstr[1] "Disponigadoj"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ne eblas forigi la ĉenstablan planon"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "De la kreado de la problemo Äis la disponigado en la publika versio"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Sekvanta plenumo"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"
@@ -28399,6 +28690,9 @@ msgstr "Celo"
msgid "PipelineSchedules|Variables"
msgstr "Variabloj"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr "Peti atingeblon"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuÅi per %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "AlÅuti dosieron"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index abbc4881d6d..9058121a8ad 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -380,8 +380,8 @@ msgstr[1] "%d segundos"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d etapa"
+msgstr[1] "%d etapas"
msgid "%d star"
msgid_plural "%d stars"
@@ -425,8 +425,8 @@ msgstr[1] "%d vulnerabilidades marcadas como confirmadas"
msgid "%d vulnerability set to dismissed"
msgid_plural "%d vulnerabilities set to dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnerabilidad marcada como descartada"
+msgstr[1] "%d vulnerabilidades marcadas como descartadas"
msgid "%d vulnerability set to needs triage"
msgid_plural "%d vulnerabilities set to needs triage"
@@ -460,6 +460,9 @@ msgstr "%{actionText} y reabrir %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} no es en un rango de direcciones IP válido"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} debe estar entre %{min} y %{max}"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} ha clonado %{original_issue} a %{new_issue}."
@@ -508,19 +511,19 @@ msgstr "%{commit_author_link} creado %{commit_authored_timeago} y %{commit_commi
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} peso completado"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} de %{count} tarea completada"
-msgstr[1] "%{completedCount} de %{count} tareas completadas"
+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 "%{completedWeight} de %{totalWeight} del peso completado"
msgid "%{completed} of %{total} issues closed"
-msgstr ""
+msgstr "%{completed} de %{total} incidencias cerrados"
msgid "%{completed} of %{total} weight completed"
-msgstr ""
+msgstr "%{completed} de %{total} peso completado"
msgid "%{cores} cores"
msgstr "%{cores} núcleos"
@@ -614,7 +617,7 @@ msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
msgstr "%{docs_link_start}¿Qué es el almacenamiento para grandes ficheros?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}¿Qué es la autenticación de dos factores?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (vencido)"
@@ -691,6 +694,9 @@ msgstr "Las %{integrations_link_start}integraciones%{link_end} le permiten utili
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "¡Va a eliminar %{issuableType}! ¿Está seguro de que desea realizar esta acción?"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} no existe o no tiene permiso para añadir un registro de tiempo."
+
msgid "%{issuable}(s) already assigned"
msgstr ""
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Método:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Espacio de nombres:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}Proyecto:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Análisis:%{labelEnd} %{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Gravedad:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Herramienta:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Respuesta sin modificar:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} no disponible"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 hora"
@@ -876,12 +885,24 @@ msgstr "%{openedEpics} abiertas, %{closedEpics} cerradas"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} abiertas, %{closedIssues} cerradas"
-msgid "%{percentageUsed}%% used"
+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 "%{percentage}%% issues closed"
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
msgstr ""
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{percentageUsed}%% used"
+msgstr "%{percentageUsed}%% usado"
+
+msgid "%{percentage}%% issues closed"
+msgstr "%{percentage}%% incidencias cerradas"
+
msgid "%{percentage}%% weight completed"
msgstr "%{percentage}%% del peso completado"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} etiqueta"
+msgstr[1] "%{selectedLabelsCount} etiquetas"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} proyecto"
+msgstr[1] "%{selectedProjectsCount} proyectos"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -986,15 +1017,12 @@ msgstr "%{start} hasta %{end}"
msgid "%{strongOpen}%{errors}%{strongClose} point"
msgid_plural "%{strongOpen}%{errors}%{strongClose} points"
-msgstr[0] ""
-msgstr[1] ""
+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 ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1031,8 +1059,8 @@ 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} Versión"
+msgstr[1] "%{strong_start}%{release_count}%{strong_end} Versiones"
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Registrado En"
-msgid "3 days"
-msgstr "3 días"
-
msgid "3 hours"
msgstr "3 horas"
-msgid "30 days"
-msgstr "30 días"
-
msgid "30 minutes"
msgstr "30 minutos"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 días"
-
msgid "8 hours"
msgstr "8 horas"
@@ -1863,7 +1882,7 @@ msgid "Access Git repositories or the API."
msgstr "Acceder a los repositorios Git o a la API."
msgid "Access Token"
-msgstr ""
+msgstr "Token de acceso"
msgid "Access Tokens"
msgstr "Tokens de acceso"
@@ -1983,10 +2002,10 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr ""
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "Accesible por cualquier usuario que haya iniciado sesión."
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "Accesible por cualquier persona, independientemente de la autenticación."
msgid "Account"
msgstr "Cuenta"
@@ -2019,7 +2038,7 @@ msgid "AccountValidation|Looks like you’ll need to validate your account to us
msgstr ""
msgid "AccountValidation|Validate your account"
-msgstr ""
+msgstr "Validar su cuenta"
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 ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Añadir una lista de viñetas"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Añadir una sección colapsable"
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Añadir tabla"
-msgid "Add a task list"
-msgstr "Añadir una lista de tareas"
-
msgid "Add a title..."
msgstr "Añadir un título..."
@@ -2183,9 +2202,6 @@ msgstr "Añadir una regla de aprobación"
msgid "Add approvers"
msgstr "Añadir aprobadores"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Añadir mensaje de difusión"
@@ -2231,6 +2247,9 @@ msgstr "Añadir entorno"
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 "Añadir encabezado y pie de página a los correos electrónicos. Tenga en cuenta que la configuración de los colores solo se aplicará dentro de la interfaz de la aplicación"
@@ -2265,7 +2284,7 @@ msgid "Add or subtract spent time"
msgstr "Añadir o restar tiempo consumido"
msgid "Add people"
-msgstr ""
+msgstr "Añadir personas"
msgid "Add previously merged commits"
msgstr ""
@@ -2541,7 +2560,7 @@ msgid "AdminArea|New user"
msgstr "Nuevo usuario"
msgid "AdminArea|No applications found"
-msgstr ""
+msgstr "No se han encontrado aplicaciones"
msgid "AdminArea|Owner"
msgstr "Propietario"
@@ -2802,7 +2821,7 @@ msgid "AdminSettings|Restrict group access by IP address. %{link_start}Learn mor
msgstr ""
msgid "AdminSettings|Save %{name} limits"
-msgstr ""
+msgstr "Guardar %{name} límites"
msgid "AdminSettings|Search with Elasticsearch enabled"
msgstr ""
@@ -3755,6 +3774,9 @@ msgstr "Todas las ramas"
msgid "All changes are committed"
msgstr "Se ha realizado commit de todos los cambios"
+msgid "All eligible users"
+msgstr "Todos los usuarios elegibles"
+
msgid "All email addresses will be used to identify your commits."
msgstr "Todas las direcciones de correo electrónico se utilizarán para identificar sus commits."
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr "Se ha producido un error al obtener los ancestros"
-msgid "An error occurred while fetching branches."
-msgstr "Se ha producido un error al obtener las ramas."
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ msgstr "Se ha producido un error al obtener la información de autocompletado de
msgid "An error occurred while fetching reference"
msgstr "Se ha producido un error al obtener referencias"
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr "Se ha producido un error al recuperar los tags. Por favor, vuelva a intentar la búsqueda."
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr "Se ha producido un error al cargar la pestaña de informes de prueba."
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Se ha producido un error al cargar el formulario de tokens de acceso. Por favor, inténtelo de nuevo."
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ msgstr ""
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr ""
+msgid "ApplicationSettings|Require lowercase letters"
+msgstr "Requiere letras minúsculas"
+
+msgid "ApplicationSettings|Require numbers"
+msgstr "Requiere números"
+
+msgid "ApplicationSettings|Require symbols"
+msgstr "Requiere símbolos"
+
+msgid "ApplicationSettings|Require uppercase letters"
+msgstr "Requiere letras mayúsculas"
+
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 "Guardar cambios"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 "dominio.com"
@@ -4764,28 +4807,31 @@ msgstr "Branch de destino"
msgid "ApprovalRule|Try for free"
msgstr "Pruébelo gratis"
+msgid "ApprovalSettings|Keep approvals"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
msgid "ApprovalSettings|Prevent approval by author"
msgstr "Evitar la aprobación por parte del autor"
-msgid "ApprovalSettings|Prevent approval by author."
-msgstr ""
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr "Aprobado el merge request actual."
msgid "Approved-By"
msgstr "Aprobado por"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Aprobador"
@@ -5174,9 +5220,6 @@ msgstr "Asignado a mí"
msgid "Assigned to you"
msgstr "Asignado a ti"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Asignado"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr "En riesgo"
-msgid "Attach a file"
-msgstr "Adjuntar un archivo"
+msgid "Attach a file or image"
+msgstr "Adjuntar un archivo o imagen"
msgid "Attaching File - %{progress}"
msgstr "Adjuntando archivo - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] "Adjuntar %d archivos"
msgid "Attaching the file failed."
msgstr "Se ha producido un error al adjuntar el archivo."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Eventos de auditoría"
@@ -5298,6 +5335,12 @@ msgstr "AuditStreams|Ya existe un cabecera con este nombre."
msgid "AuditStreams|Active"
msgstr ""
+msgid "AuditStreams|Add a custom header"
+msgstr "AuditStreams|Agregar un encabezado personalizado"
+
+msgid "AuditStreams|Add a custom value"
+msgstr "Agregar un valor personalizado"
+
msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party systems."
msgstr ""
@@ -5316,6 +5359,9 @@ 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 "Cancelar edición"
@@ -5331,18 +5377,33 @@ msgstr "URL de destino"
msgid "AuditStreams|Destinations receive all audit event data"
msgstr "Los destinos reciben todos los datos del evento de auditoría"
+msgid "AuditStreams|Edit %{link}"
+msgstr "Editar %{link}"
+
msgid "AuditStreams|Header"
msgstr "AuditStreams|Cabecera"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
+msgstr "Se alcanzó el número máximo de %{number} encabezados HTTP."
+
+msgid "AuditStreams|Save external stream destination"
msgstr ""
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr "Streams"
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr "AuditStreams|Valor"
+msgid "AuditStreams|Verification token"
+msgstr "Token de verificación"
+
msgid "Aug"
msgstr "Ago"
@@ -5571,8 +5635,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Resuelto automáticamente"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Actualizar automáticamente las ramas y las etiquetas desde el repositorio upstream cada hora."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Nota"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr "Bloqueado"
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ msgstr "Extender el periodo de prueba"
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 ""
@@ -6204,17 +6274,16 @@ msgstr "Explorar todos los planes"
msgid "Billing|Export list"
msgstr "Exportar lista"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr ""
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "A partir del 19 de octubre de 2022, los grupos gratuitos estarán limitados a 5 miembros"
msgid "Billing|Group invite"
msgstr "Invitación de grupo"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ msgstr "Invitación al proyecto"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Eliminar al usuario %{username} de su suscripción"
+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 ""
@@ -6246,13 +6318,10 @@ msgstr ""
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
msgstr "Está a punto de eliminar al usuario %{username} de su suscripción. Si continua, el usuario será eliminado del grupo %{namespace} y todos sus subgrupos y proyectos. Esta acción no se puede deshacer."
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr "Branch no cargada - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+msgstr ""
+
+msgid "BranchRules|Protections"
+msgstr "Protecciones"
+
+msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr ""
+
+msgid "BranchRules|Require approval from code owners."
+msgstr ""
+
msgid "Branches"
msgstr "Ramas"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Activo"
@@ -7196,9 +7307,6 @@ msgstr "No se puede encontrar el commit HEAD para este 'branch'"
msgid "Can't find variable: ZiteReader"
msgstr "No se puede encontrar la variable: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr "No se puede cargar el módulo de Mermaid: %{err}"
-
msgid "Can't scan the code?"
msgstr "¿No puede analizar el código?"
@@ -7887,9 +7995,6 @@ msgstr "La subtarea épica no existe."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr "Hijos"
-
msgid "Chinese language support using"
msgstr "Soporte para el idioma chino utilizando"
@@ -8312,6 +8417,9 @@ msgstr "CloudSeed|Cloud SQL para SQL Server"
msgid "CloudSeed|CloudSQL Instance"
msgstr "CloudSeed|Instancia de CloudSQL"
+msgid "CloudSeed|Configuration"
+msgstr "Configuración"
+
msgid "CloudSeed|Create cluster"
msgstr "CloudSeed|Crear clúster"
@@ -8322,19 +8430,25 @@ msgid "CloudSeed|Create instance"
msgstr "CloudSeed|Crear instancia"
msgid "CloudSeed|Database instance is generated within the selected Google Cloud project"
-msgstr ""
+msgstr "La instancia de base de datos se genera dentro del proyecto de Google Cloud seleccionado"
msgid "CloudSeed|Database instances associated with this project"
-msgstr ""
+msgstr "Instancias de base de datos asociadas a este proyecto"
msgid "CloudSeed|Database version"
msgstr "CloudSeed|Versión de la base de datos"
+msgid "CloudSeed|Databases"
+msgstr "Bases de datos"
+
+msgid "CloudSeed|Deployments"
+msgstr "Despliegues"
+
msgid "CloudSeed|Description"
msgstr "CloudSeed|Descripción"
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
-msgstr ""
+msgstr "Determina la memoria y los núcleos virtuales disponibles en su instancia"
msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
msgstr ""
@@ -8387,12 +8501,18 @@ msgstr "CloudSeed|Sin instancias"
msgid "CloudSeed|Refs"
msgstr "CloudSeed|Referencias"
+msgid "CloudSeed|Regions"
+msgstr "Regiones"
+
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
msgstr ""
msgid "CloudSeed|Service"
msgstr "CloudSeed|Servicio"
+msgid "CloudSeed|Service Account"
+msgstr "Cuenta de servicio"
+
msgid "CloudSeed|Services"
msgstr "CloudSeed|Servicios"
@@ -9239,13 +9359,13 @@ msgid "ColorWidget|An error occurred while updating color."
msgstr "Se ha producido un error al actualizar el color."
msgid "ColorWidget|Assign epic color"
-msgstr ""
+msgstr "Asignar color a la tarea épica"
msgid "ColorWidget|Color"
msgstr "Color"
msgid "ColorWidget|Error fetching epic color."
-msgstr ""
+msgstr "Se ha producido un error al obtener el color asignado a la tarea épica"
msgid "Colorize messages"
msgstr "Colorear mensajes"
@@ -9905,7 +10025,7 @@ msgid "ContainerRegistry|CLI Commands"
msgstr "Comandos del CLI"
msgid "ContainerRegistry|Clean up image tags"
-msgstr ""
+msgstr "Limpiar las etiquetas de la imágenes"
msgid "ContainerRegistry|Cleanup disabled"
msgstr ""
@@ -10215,9 +10335,6 @@ msgstr "Puede añadir una imagen a este registro utilizando los siguientes coman
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr "Crear %{type}"
msgid "Create %{workspace} label"
msgstr "Crear etiqueta de %{workspace}"
-msgid "Create Google Cloud project"
-msgstr "Crear proyecto de Google Cloud"
-
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
@@ -11109,6 +11223,9 @@ msgstr "Tarjeta de crédito:"
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr "Configuración DAST"
+msgid "DAST configuration not found"
+msgstr "Configuración de DAST no encontrada"
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11511,13 +11631,16 @@ msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Change failure rate"
+msgstr "Cambiar tasa de fallo"
+
+msgid "DORA4Metrics|Change failure rate (percentage)"
msgstr ""
msgid "DORA4Metrics|Date"
msgstr "Fecha"
msgid "DORA4Metrics|Days for an open incident"
-msgstr ""
+msgstr "Días para un incidente abierto"
msgid "DORA4Metrics|Days from merge to deploy"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11535,7 +11661,7 @@ msgid "DORA4Metrics|Median time (last %{days}d)"
msgstr "Tiempo medio (últimos %{days} días)"
msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
-msgstr ""
+msgstr "La mediana de tiempo en el que se abrió un incidente en un entorno de producción a lo largo de un período determinado."
msgid "DORA4Metrics|No incidents during this period"
msgstr "Sin incidencias durante este periodo"
@@ -11547,10 +11673,10 @@ 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 "Número de incidentes divididos por el número de depliegues en un entorno de producción en el período de tiempo determinado."
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr ""
+msgstr "Porcentaje de depliegues fallidos"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr "DORA4Metrics|Tiempo para restaurar el servicio"
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr "DSN"
@@ -11609,9 +11738,21 @@ msgstr "DastConfig|Configuración 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 ""
+msgid "DastConfig|Enabled"
+msgstr "Habilitado"
+
msgid "DastConfig|Generate code snippet"
msgstr "Generar fragmento de código"
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr ""
+
+msgid "DastConfig|No previous scans found for this project"
+msgstr ""
+
+msgid "DastConfig|Not enabled"
+msgstr "Deshabilitado"
+
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 ""
@@ -11742,7 +11883,7 @@ msgid "DastProfiles|Include debug messages in the DAST console output."
msgstr ""
msgid "DastProfiles|Manage %{profileType} profiles"
-msgstr ""
+msgstr "Gestionar %{profileType} perfiles"
msgid "DastProfiles|Manage profiles"
msgstr "Administrar perfiles"
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr "Eliminar el archivo"
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr "Eliminar proyecto"
+msgid "Delete release"
+msgstr "Eliminar la versión"
+
+msgid "Delete release %{release}?"
+msgstr "¿Eliminar la versión %{release}?"
+
msgid "Delete row"
msgstr "Eliminar fila"
@@ -12388,6 +12538,15 @@ msgstr ""
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "Se ha producido un error al eliminar el repositorio de wiki. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
+msgid "DeleteRelease|Are you sure you want to delete this release?"
+msgstr "¿Está seguro que desea eliminar esta versión?"
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr "Para más detalles, consulte la información sobre como %{docsPathStart}borrar una versión%{docsPathEnd}."
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr "Está a punto de eliminar la versión %{release} y sus activos. El tag de Git %{tag} no será eliminado."
+
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
msgstr ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr "Eliminando"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Despliegue"
msgstr[1] "Despliegues"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Claves de despliegue"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "Documentos reindexados: %{processed_documents} (%{percentage}%%)"
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Dominio"
@@ -14089,9 +14245,6 @@ msgstr "Ninguno. Seleccione los espacios de nombres a indexar."
msgid "Elastic|None. Select projects to index."
msgstr "Ninguno. Seleccione los proyectos a indexar."
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "Correo electrónico"
@@ -14231,7 +14384,7 @@ msgid "Enable Auto DevOps"
msgstr "Activar Auto DevOps"
msgid "Enable GitLab Error Tracking"
-msgstr ""
+msgstr "Habilitar el seguimiento de errores de GitLab"
msgid "Enable Gitpod"
msgstr "Habilitar Gitpod"
@@ -14413,9 +14566,6 @@ msgstr "Protocolos de acceso Git habilitados"
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr "Se ha producido un error al renderizar: %{err}"
-
msgid "End Time"
msgstr ""
@@ -14696,7 +14846,7 @@ msgid "Environments|Open live environment"
msgstr "Entorno abierto"
msgid "Environments|Re-deploy environment"
-msgstr ""
+msgstr "Redesplegar el entorno"
msgid "Environments|Re-deploy environment %{name}?"
msgstr "¿Desea redesplegar el entorno %{name}?"
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,24 +16042,21 @@ msgstr "Se ha producido un error al eliminar una reunión de Zoom"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Se ha producido un error al eliminar el mirror."
msgid "Failed to remove the pipeline schedule"
msgstr "Error al eliminar la programación del pipeline"
+msgid "Failed to remove timelog"
+msgstr ""
+
msgid "Failed to remove user identity."
msgstr "Se ha producido un error al eliminar la identidad del usuario."
msgid "Failed to remove user key."
msgstr "Se ha producido un error al eliminar la clave del usuario."
-msgid "Failed to request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr "Se ha producido un error al recuperar la página"
@@ -15922,6 +16072,9 @@ msgstr "Se ha producido un error al guardar las preferencias (%{error_message}).
msgid "Failed to save preferences."
msgstr "Se ha producido un error al guardar las preferencias."
+msgid "Failed to save timelog"
+msgstr ""
+
msgid "Failed to set due date because the date format is invalid."
msgstr "Se ha producido un error al establecer la fecha de vencimiento debido a que el formato de fecha no es válido."
@@ -15967,9 +16120,6 @@ msgstr "Falso positivo"
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr "Fast-forward merge sin hacer merge commit"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Lanzamientos más rápidos. Mejor código. Menos dolor."
@@ -16212,6 +16362,9 @@ msgstr "Feb"
msgid "February"
msgstr "Febrero"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr "De %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "Desde la creación de la incidencia hasta el despliegue a producción"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr "Geo|%{component} sincronizado"
msgid "Geo|%{component} verified"
msgstr "Geo|%{component} verificado"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} no puede estar en blanco"
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr "En curso"
-msgid "Geo|In sync"
-msgstr "Sincronizado"
-
msgid "Geo|Internal URL"
msgstr "URL interna"
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Sin sincronizar aún"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr "No saludable"
msgid "Geo|Unknown"
msgstr "Desconocido"
-msgid "Geo|Unknown state"
-msgstr "Estado desconocido"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17384,16 +17543,16 @@ msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNum
msgstr "El número de repositorios debe estar entre %{minNumRepos}-%{maxNumRepos}."
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "Período de tiempo del informe (segundos)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "El período de tiempo del informe no puede estar en blanco. Establézcalo en 0 para no tener límite."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "El período de tiempo del informe debe ser un número."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "El período de tiempo del informe debe estar entre %{minTimePeriod}y%{maxTimePeriod} segundos."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr "Incidencia de GitLab"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17467,9 +17629,6 @@ msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
msgstr "Solicitud de cuenta de GitLab rechazada"
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr "GitLab commit"
@@ -17558,11 +17717,14 @@ msgid "GitLabPages|Are you sure?"
msgstr "¿Está seguro?"
msgid "GitLabPages|Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
-msgstr ""
+msgstr "Se puede sobrescribir por proyecto. Para no tener límite, introduzca el valor 0. Para heredar el valor, deje vacío."
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Certificado: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr "Configurar páginas"
@@ -17614,6 +17776,9 @@ msgstr "Guardar los cambios"
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 ""
@@ -17621,11 +17786,14 @@ msgid "GitLabPages|Unverified"
msgstr "Sin verificar"
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "Actualizando su configuración de Pages..."
msgid "GitLabPages|Verified"
msgstr "Verificado"
+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 ""
@@ -17638,6 +17806,9 @@ 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 "Sus páginas se sirven desde:"
@@ -17956,18 +18127,15 @@ msgstr "Ir a sus fragmentos de código"
msgid "Google Cloud"
msgstr ""
+msgid "Google Cloud Error - %{error}"
+msgstr "Error de Google Cloud - %{error}"
+
msgid "Google Cloud Project"
msgstr "Projecto de Google Cloud"
msgid "Google Cloud authorizations required"
msgstr ""
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18068,7 +18236,7 @@ msgid "Group"
msgstr "Grupo"
msgid "Group \"%{group_name}\" was successfully updated."
-msgstr ""
+msgstr "El grupo %{group_name} se actualizó correctamente."
msgid "Group %{group_name} couldn't be exported."
msgstr "No se puede exportar el grupo %{group_name} ."
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr "Resumen del contenido del grupo"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "El pipeline Auto DevOps se actualizó para el grupo"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ msgstr "GroupSettings|Las notificaciones por correo electrónico están deshabil
msgid "GroupSettings|Export group"
msgstr "Exportar grupo"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr ""
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr "GroupSettings|Intervalo (segundos)"
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr "GroupSettings|Número de proyectos"
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr "GroupSettings|Límite de velocidad de descarga del proyecto"
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr "GroupSettings|Establézcalo en 0 para deshabilitar la limitación."
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ msgstr "Puede administrar los permisos y el acceso de cada miembro del grupo a c
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 ""
@@ -18766,6 +18922,9 @@ msgstr "Crear grupo"
msgid "GroupsNew|Create new group"
msgstr "Crear nuevo grupo"
+msgid "GroupsNew|Create subgroup"
+msgstr "Crear subgrupo"
+
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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "Subir archivo"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "También puede %{linkStart}importar un grupo existente%{linkEnd}."
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "Por ejemplo, h8d3f016698..."
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr "URL del subgrupo"
+
+msgid "Groups|Subgroup name"
+msgstr "Nombre del subgrupo"
+
+msgid "Groups|Subgroup slug"
+msgstr "Slug del subgrupo"
+
msgid "Guideline"
msgstr "Guía"
@@ -18907,7 +19078,7 @@ msgstr "HTTP básico: Acceso denegado\\nDebe utilizar un token de acceso persona
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr "¿Tiene más cosas que decir sobre GitLab?"
-
msgid "Header logo"
msgstr "Logo de cabecera"
@@ -19245,6 +19410,9 @@ msgstr "Alerta original:"
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Historial"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19447,7 +19618,7 @@ msgid "IdentityVerification|For added security, you'll need to verify your ident
msgstr ""
msgid "IdentityVerification|Help us protect your account"
-msgstr ""
+msgstr "Ayúdenos a proteger su cuenta"
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 ""
@@ -19456,10 +19627,10 @@ msgid "IdentityVerification|If you have not recently tried to sign into GitLab,
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 ""
+msgstr "Si ha perdido el acceso al correo electrónico asociado a esta cuenta o tiene problemas con el código, %{link_start}aquí se indican algunos pasos que puede dar.%{link_end}"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
-msgstr ""
+msgstr "Se han superado el número máximo de intentos de inicio de sesión. Espere %{interval} y vuelva a intentarlo."
msgid "IdentityVerification|Please enter a valid code"
msgstr "Por favor, introduzca un código válido"
@@ -19497,6 +19668,9 @@ msgstr "Su cuenta ha sido verificada correctamente. Será redirigido a su cuenta
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."
+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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-msgstr "¿Tiene un minuto?"
-
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr "¿Tiene un compañero que sería perfecto para esta tarea?"
msgid "InProductMarketing|Dynamic application security testing"
msgstr ""
-msgid "InProductMarketing|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr "InProductMarketing|Neutral"
-
msgid "InProductMarketing|No credit card required."
msgstr "No es necesaria una tarjeta de crédito."
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr "Muy difícil"
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20608,13 +20755,13 @@ msgid "Incident|Alert details"
msgstr "Detalles de la alerta"
msgid "Incident|Are you sure you want to delete this event?"
-msgstr ""
+msgstr "¿Está seguro de que desea eliminar este evento?"
msgid "Incident|Are you sure you wish to delete this image?"
msgstr "¿Está seguro que desea eliminar esta imagen?"
msgid "Incident|Delete event"
-msgstr ""
+msgstr "Borrar evento"
msgid "Incident|Delete image"
msgstr ""
@@ -20632,7 +20779,7 @@ msgid "Incident|Error creating incident timeline event: %{error}"
msgstr "Se ha producido un error al crear el evento de la linea de tiempo del incidente: %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr ""
+msgstr "Se ha producido un error al eliminar el evento de la línea de tiempo del incidente: %{error}"
msgid "Incident|Metrics"
msgstr "Métricas"
@@ -20644,10 +20791,10 @@ msgid "Incident|Save and add another event"
msgstr "Guardar y añadir otro evento"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr ""
+msgstr "Se ha producido un error al crear el evento de la línea de tiempo del incidente."
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr ""
+msgstr "Se ha producido un error al eliminar el evento de la línea de tiempo del incidente."
msgid "Incident|Something went wrong while fetching incident timeline events."
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21411,7 +21558,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr "Los miembros se han añadido correctamente"
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "Revise los errores de invitación y vuelva a intentarlo:"
msgid "InviteMembersModal|Search for a group to invite"
msgstr "Buscar un grupo para invitar"
@@ -21430,8 +21577,8 @@ msgstr "Algo salió mal"
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] "No se pudo invitar al siguiente miembro"
+msgstr[1] "Los siguientes %d miembros no pudieron ser invitados"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
msgstr ""
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr "Texto en cursiva"
msgid "Iteration"
msgstr "Iteración"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Iteración cambiada a"
@@ -21877,12 +22024,36 @@ msgstr "Iteración actualizada"
msgid "Iterations"
msgstr "Iteraciones"
+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 "Añadir iteración"
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 "La configuración de la cadencia no es válida."
@@ -21904,6 +22075,9 @@ msgstr "Crear cadencia"
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr "Eliminar cadencia"
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr "Seleccionar la fecha de inicio"
msgid "Iterations|Start date"
msgstr "Fecha de inicio"
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Desplazar hacia abajo"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Desplazar hacia arriba"
@@ -22618,8 +22795,8 @@ msgstr "Clave"
msgid "Key (PEM)"
msgstr "Clave (PEM)"
-msgid "Key: %{key}"
-msgstr "Clave: %{key}"
+msgid "Key:"
+msgstr ""
msgid "Keyboard shortcuts"
msgstr "Atajos de teclado"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr "Última sincronización correcta"
-
msgid "Last successful update"
msgstr "Última actualización con éxito"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr "Verficado por última vez"
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr "Visibilidad menos restrictiva"
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt no acepta correos electrónicos de example.com"
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 "Let's encrypt es una autoridad de certificación (CA) gratuita y automatizada, que proporciona certificados HTTPS (SSL/TLS) para sitios web. Para saber cómo configurarlo consulte el enlace de la documentación %{docs_link_start} en GitLab Pages%{docs_link_end}."
-msgid "Let's talk!"
-msgstr ""
-
msgid "License Compliance"
msgstr "License Compliance"
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,8 +23621,11 @@ msgstr "Correos electrónicos vinculados (%{email_count})"
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Incidencias relacionadas"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr "Elementos vinculados"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23462,6 +23636,48 @@ msgstr ""
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
+msgid "LinkedResources|Add"
+msgstr "Agregar"
+
+msgid "LinkedResources|Add a resource link"
+msgstr "Agregar un enlace a un recurso"
+
+msgid "LinkedResources|Cancel"
+msgstr "Cancelar"
+
+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 "Enlace"
+
+msgid "LinkedResources|Linked resources"
+msgstr "Recursos vinculados"
+
+msgid "LinkedResources|Remove"
+msgstr "Eliminar"
+
+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 "Texto (opcional)"
+
+msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
+msgstr "Utilice este espacio para agregar enlaces a los recursos que su equipo necesita mientras ellos trabajan para resolver el incidente."
+
msgid "Links"
msgstr "Enlaces"
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "No ha sido posible guardar el orden de las incidencias"
@@ -24053,7 +24266,7 @@ msgstr "Longitud máxima del campo"
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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr "Detener entorno"
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr "Multi-proyecto"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr "Cerrar la sesión actual e iniciar sesión con una cuenta diferente"
msgid "Need help?"
msgstr "¿Necesita ayuda?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr "No hay tarea épica"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "No hay proyectos de Google Cloud: necesita al menos un proyecto de Google Cloud"
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr "Sin asignar"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "No hay métodos de autenticación configurados."
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr "¡No se ha implementado!"
-
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 ""
@@ -26389,6 +26590,9 @@ 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 "Nada para previsualizar."
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} en %{mr_link}"
+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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26572,13 +26785,13 @@ msgid "Notify|Merge request URL: %{merge_request_url}"
msgstr ""
msgid "Notify|Milestone changed to %{milestone}"
-msgstr ""
+msgstr "Hito cambiado a %{milestone}"
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
msgid "Notify|Pipeline %{pipeline_link} triggered by"
-msgstr ""
+msgstr "Pipeline %{pipeline_link} activado por"
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 ""
@@ -26596,10 +26809,10 @@ msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been
msgstr ""
msgid "Notify|currently supported languages"
-msgstr ""
+msgstr "lenguajes soportados actualmente"
msgid "Notify|successfully completed %{jobs} in %{stages}."
-msgstr ""
+msgstr "%{jobs} completado con éxito en %{stages}."
msgid "Nov"
msgstr "Nov"
@@ -26691,6 +26904,11 @@ msgstr "OmniAuth"
msgid "On"
msgstr "En"
+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 track"
msgstr ""
@@ -27075,7 +27293,7 @@ msgstr[0] "Un elemento más"
msgstr[1] "%d elementos más"
msgid "One or more arguments are invalid: %{args}."
-msgstr ""
+msgstr "Uno o más argumentos no son válidos: %{args}."
msgid "One or more contacts were successfully added."
msgstr ""
@@ -27141,7 +27359,7 @@ msgid "Only include features new to your current subscription tier."
msgstr ""
msgid "Only members of this group can access the wiki."
-msgstr ""
+msgstr "Sólo los miembros de este grupo pueden acceder al wiki."
msgid "Only policy:"
msgstr "Sólo la política:"
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ msgstr "Más información"
msgid "OperationsDashboard|Operations Dashboard"
msgstr "OperationsDashboard|Tablero de operaciones"
+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 "OperationsDashboard|El tablero de operaciones proporciona un resumen del estado operativo de cada proyecto, incluidos los estados de los pipelines y de las alertas."
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr "Eliminar la versión del paquete"
msgid "PackageRegistry|Delete package"
msgstr "Eliminar paquete"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr "Eliminar este paquete"
@@ -27599,6 +27825,9 @@ msgstr "PackageRegistry|Paquetes duplicados"
msgid "PackageRegistry|Error publishing"
msgstr ""
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr ""
+
msgid "PackageRegistry|Failed to load the package data"
msgstr ""
@@ -27656,6 +27885,9 @@ msgstr "Aprenda a %{noPackagesLinkStart}publicar y compartir sus paquetes%{noPac
msgid "PackageRegistry|License information located at %{link}"
msgstr "La información de licencia se encuentra en %{link}"
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr "Publicado manualmente"
@@ -27674,9 +27906,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "Comando NuGet"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr "Registro de paquetes"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr "Paquete eliminado correctamente"
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Comando Pip"
@@ -27748,6 +27989,9 @@ 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."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ msgstr "No se ha podido obtener la información de la versión del paquete."
msgid "PackageRegistry|Unable to load package"
msgstr "Se ha producido un error al cargar el paquete"
+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 "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 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 "Está a punto de eliminar la versión %{version} de %{name}. ¿Está seguro?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "Puede que también necesite configurar la autenticación utilizando un token de autentificación. %{linkStart} Vea la documentación%{linkEnd} para obtener más información."
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
msgid "PackageRegistry|npm"
msgstr "npm"
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "Realice operaciones comunes en el proyecto GitLab"
+msgid "Performance insights"
+msgstr "Performance insights"
+
msgid "Performance optimization"
msgstr "Optimización del rendimiento"
@@ -28171,6 +28429,18 @@ msgstr "Proyectos personales"
msgid "Personal projects limit:"
msgstr "Límite de los proyectos personales:"
+msgid "PersonalProject|Learn to move a project to a group"
+msgstr "Aprenda a mover un proyecto a un grupo"
+
+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 "Importar servidor Phabricator"
@@ -28327,6 +28597,9 @@ msgstr ""
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr ""
+msgid "PipelineEditor|Configuration content has changed. Re-run validation for updated results."
+msgstr "El contenido de la configuración ha cambiado. Vuelva a ejecutar la validación para ver los resultados actualizados."
+
msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
msgstr ""
@@ -28345,6 +28618,15 @@ 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 "Simulación de pipelines completada con errores"
+
+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 "Simulación completada correctamente"
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr ""
@@ -28366,6 +28648,12 @@ msgstr "Validar pipeline bajo unas condiciones seleccionadas"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
msgstr "Validar pipeline bajo unas condiciones simuladas"
+msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
+msgstr "Validando el pipeline... Esta acción puede tardar hasta un minuto."
+
+msgid "PipelineEditor|Waiting for CI content to load..."
+msgstr "Esperando que se cargue el contenido de CI..."
+
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
msgstr ""
@@ -28387,6 +28675,9 @@ msgstr "Próxima Ejecución"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Proporcione una descripción breve para este pipeline"
@@ -28399,6 +28690,9 @@ msgstr "Destino"
msgid "PipelineSchedules|Variables"
msgstr "Variables"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28645,6 +28939,9 @@ msgstr "Propietario"
msgid "Pipelines|Pipeline Editor"
msgstr "Editor de pipeline"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "La sintaxis del pipeline es correcta."
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Caché del proyecto restablecida correctamente."
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr "Fallido"
+msgid "Pipeline|Five slowest jobs"
+msgstr "Los cinco trabajos más lentos"
+
msgid "Pipeline|In progress"
msgstr "En progreso"
+msgid "Pipeline|Last executed job"
+msgstr "Último trabajo ejecutado"
+
+msgid "Pipeline|Longest queued job"
+msgstr "El trabajo más largo en cola"
+
msgid "Pipeline|Manual"
msgstr "Manual"
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "Sólo se pueden mostrar los 100 primeros resultados"
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr "Pendiente"
+msgid "Pipeline|Performance insights"
+msgstr "Performance insights"
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr "Ejecutar pipeline"
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "El último trabajo ejecutado es el último trabajo que se inicia en el pipeline."
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "El trabajo más largo en cola es el que más tiempo pasó en el estado pendiente, esperando a ser elegido por un ejecutor de Gitlab"
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr "Variables"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr "Ver dependencia"
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "Por favor revise su correo electrónico (%{email}) para verificar que es el propietario de esta dirección y desbloquear la potencia de CI/CD. ¿No lo ha recibido? %{resend_link}. ¿Ha utilizado una dirección de correo electrónico incorrecta? %{update_link}."
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr "Por favor, complete su perfil con una dirección de correo electrónico"
@@ -29116,6 +29446,9 @@ msgstr "Por favor, proporcione atributos para actualizar"
msgid "Please reach out if you have any questions and we'll be happy to assist."
msgstr "Contacte con nosotros si tiene alguna pregunta y estaremos encantados de ayudarle."
+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 ""
@@ -29362,7 +29695,7 @@ msgstr "Previo"
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29612,7 +29945,7 @@ msgid "Profiles|Connect %{provider}"
msgstr ""
msgid "Profiles|Connect a service for sign-in."
-msgstr ""
+msgstr "Conectar un servicio para iniciar sesión."
msgid "Profiles|Connected Accounts"
msgstr "Cuentas conectadas"
@@ -29804,7 +30137,7 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr "El tamaño máximo de archivo permitido es 200KB."
msgid "Profiles|This email will be displayed on your public profile."
-msgstr ""
+msgstr "Esta dirección de correo electrónico se mostrará en su perfil público."
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 ""
@@ -30076,6 +30409,9 @@ msgstr "Slug del proyecto"
msgid "Project uploads"
msgstr "Proyectos subidos"
+msgid "Project visibility level is less restrictive than the group settings."
+msgstr "El nivel de visibilidad del proyecto es menos restrictivo que la configuración del grupo."
+
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "Se modificará el nivel de visibilidad del proyecto para hacerlo coincidir con las reglas del espacio de nombres al transferirlo a un grupo."
@@ -30085,6 +30421,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Proyecto: %{name}"
+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 "Suscribirse"
@@ -30163,6 +30505,9 @@ msgstr "Error"
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 ""
@@ -30175,6 +30520,9 @@ 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 "Ver informe completo"
@@ -30202,6 +30550,9 @@ 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 "o grupo"
@@ -31013,7 +31364,7 @@ msgid "PrometheusService|Finding custom metrics..."
msgstr "Buscar métricas personalizadas..."
msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
-msgstr ""
+msgstr "IAP_CLIENT_ID.apps.googleusercontent.com"
msgid "PrometheusService|Manage clusters"
msgstr "Administrar clústeres"
@@ -31070,7 +31421,7 @@ msgid "PrometheusService|You have a cluster with the Prometheus integration enab
msgstr ""
msgid "PrometheusService|https://prometheus.example.com/"
-msgstr ""
+msgstr "https://prometheus.example.com/"
msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
msgstr ""
@@ -31127,7 +31478,7 @@ msgid "Promotions|Buy GitLab Enterprise Edition"
msgstr "Comprar GitLab Enterprise Edition"
msgid "Promotions|Configure Service Desk"
-msgstr ""
+msgstr "Configurar Service Desk"
msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
msgstr ""
@@ -31142,7 +31493,7 @@ msgid "Promotions|Description templates allow you to define context-specific tem
msgstr ""
msgid "Promotions|Dismiss Service Desk promotion"
-msgstr ""
+msgstr "Descartar promoción de Service Desk"
msgid "Promotions|Dismiss burndown charts promotion"
msgstr ""
@@ -31390,18 +31741,36 @@ msgstr "Por defecto"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} podrá modificarse por los desarrolladores. ¿Estás seguro de que desea continuar?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Permitido desplegar"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Entorno"
-msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
msgstr ""
+msgid "ProtectedEnvironment|No environments in this project are projected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
+msgstr "Sólo los grupos especificados pueden realizar depliegues en entornos protegidos."
+
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
msgstr ""
+msgid "ProtectedEnvironment|Parent group"
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
@@ -31528,6 +31897,12 @@ 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 "Comprar más minutos"
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr "Reconfigurar"
+msgid "Recover password"
+msgstr "Recuperar contraseña"
+
msgid "Recovery Codes"
msgstr "Codigos de recuperacion"
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr "Incidentes o problemas relacionados"
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] "Versión"
msgstr[1] "Versiones"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "La versión %{deletedRelease} se ha eliminado correctamente."
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release."
msgstr ""
+msgid "Release|Something went wrong while deleting the release."
+msgstr "Se ha producido un error al eliminar la versión."
+
msgid "Release|Something went wrong while getting the release details."
msgstr ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "Eliminar el usuario asignado"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Eliminar avatar"
@@ -32306,12 +32675,6 @@ msgstr "Eliminar todas las etiquetas."
msgid "Removed an issue from an epic."
msgstr "Se eliminó la incidencia de la tarea épica."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "¡No se puede restaurar un grupo eliminado!"
@@ -32360,9 +32723,6 @@ msgstr "Elimina todas las etiquetas."
msgid "Removes an issue from an epic."
msgstr "Eliminar una incidencia de una tarea épica."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Elimina la tarea épica padre %{epic_ref}."
@@ -32471,6 +32831,9 @@ msgstr "Responda a este correo directamente o %{view_it_on_gitlab}."
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Informar de un abuso"
@@ -32483,6 +32846,9 @@ 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 "Informe de los datos de uso de su licencia a GitLab"
@@ -32547,10 +32913,10 @@ msgid "Reports|Classname"
msgstr "Nombre de la clase"
msgid "Reports|Copy failed test names to run locally"
-msgstr ""
+msgstr "Copiar los nombres de los pruebas fallidas para ejecutarlos localmente"
msgid "Reports|Copy failed tests"
-msgstr ""
+msgstr "Copiar las pruebas fallidas"
msgid "Reports|Execution time"
msgstr "Tiempo de ejecución"
@@ -32640,6 +33006,9 @@ msgstr "Vulnerabilidad"
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "no hay cambios en los resultados de las pruebas"
@@ -32833,15 +33202,6 @@ msgstr "Solicitar acceso"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Solicitado %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr "Revisión solicitada"
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr "Volver a enviar"
msgid "Resend Request"
msgstr "Reenviar solicitud"
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "Reenviar correo electrónico de confirmación"
@@ -33104,11 +33455,11 @@ msgstr ""
msgid "Retry"
msgstr "Reintentar"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
-msgstr "Reintentar trabajos fallidos"
+msgid "Retry downstream pipeline"
+msgstr ""
msgid "Retry job"
msgstr "Reintentar trabajo"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr "Añadir a"
-
-msgid "RightSidebar|deleting the"
-msgstr "Eliminar el"
-
msgid "Roadmap"
msgstr "Hoja de ruta"
@@ -33291,6 +33636,11 @@ msgstr ""
msgid "Runners page."
msgstr "Página de ejecutores."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr "Asociado con uno o más proyectos"
+msgid "Runners|Available"
+msgstr "Disponible"
+
msgid "Runners|Available to all projects"
msgstr "Disponible para todos los proyectos"
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr "Obsoleto"
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr "Recomendado"
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33624,7 +33983,7 @@ 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."
-msgstr ""
+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."
msgid "Runners|Runs untagged jobs"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ msgstr ""
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
msgstr ""
-msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
+msgid "Runners|To register them, go to the %{link_start}group's Runners page%{link_end}."
msgstr ""
+msgid "Runners|Up to date"
+msgstr "Hasta la fecha"
+
+msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
+msgstr "Actualice sus ejecutores de GitLab para que coincidan con la versión de GitLab que está ejecutando. Deben coincidir tanto la versión %{linkStart}principal como la secundaria%{linkEnd}."
+
+msgid "Runners|Upgrade Status"
+msgstr "Actualizar estado"
+
msgid "Runners|Upgrade available"
msgstr "Runners|Actualización disponible"
@@ -33748,6 +34119,9 @@ msgstr "Ha utilizado %{quotaUsed} de %{quotaLimit} de sus minutos de ejecución
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr "disponible"
+
msgid "Runners|group"
msgstr "grupo"
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr "recomendado"
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr "Runners|actualización disponible"
msgid "Runners|upgrade recommended"
msgstr "Runners|actualización recomendada"
+msgid "Runner|Owner"
+msgstr "Propietario"
+
msgid "Running"
msgstr "En ejecución"
@@ -33800,16 +34180,16 @@ msgid "SAML for %{group_name}"
msgstr "SAML para %{group_name}"
msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
-msgstr ""
+msgstr "Al seleccionar \"Autorizar\" se transferirá la propiedad de su cuenta de GitLab \"%{username}(%{email}) a su organización."
msgid "SAML|Sign in to GitLab to connect your organization's account"
-msgstr ""
+msgstr "Inicie sesión en GitLab para conectar la cuenta de su organización"
msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
-msgstr ""
+msgstr "El grupo \"%{group_path}\" le permite iniciar sesión con su cuenta de inicio de sesión único."
msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
-msgstr ""
+msgstr "Debe iniciar sesión con su cuenta Single Sign-On, a través de una página de inicio de sesión externa para acceder a \"%{group_name}\" ."
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "Clave SSH"
@@ -33829,6 +34212,9 @@ msgstr "Claves SSH"
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 "Huella digital de la clave SSH del host"
@@ -33907,6 +34293,21 @@ msgstr "Guardando"
msgid "Saving project."
msgstr "Guardar proyecto."
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] "Resultado de la wiki"
msgstr[1] "Resultados de la wiki"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34286,6 +34693,9 @@ msgstr "Configuración de seguridad"
msgid "Security Dashboard"
msgstr "Tablero de seguridad"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Tablero de seguridad"
@@ -34530,7 +34940,7 @@ msgid "SecurityOrchestration|Description"
msgstr ""
msgid "SecurityOrchestration|Direct"
-msgstr ""
+msgstr "Directo"
msgid "SecurityOrchestration|Don't show the alert anymore"
msgstr ""
@@ -34559,11 +34969,17 @@ msgstr "Forzar la seguridad para este proyecto. %{linkStart}Más información%{l
msgid "SecurityOrchestration|Failed to load cluster agents."
msgstr "Se ha producido un error al cargar los agentes del clúster."
+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 ""
+msgstr "Heredado"
msgid "SecurityOrchestration|Inherited from %{namespace}"
msgstr ""
@@ -34724,6 +35140,9 @@ msgstr ""
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "Este %{namespaceType} no contiene ninguna política de seguridad."
+
msgid "SecurityOrchestration|This group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr "Este proyecto"
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34773,13 +35189,13 @@ msgid "SecurityOrchestration|You don't have any security policies yet"
msgstr ""
msgid "SecurityOrchestration|a"
-msgstr ""
+msgstr "un"
msgid "SecurityOrchestration|all branches"
msgstr ""
msgid "SecurityOrchestration|an"
-msgstr ""
+msgstr "un"
msgid "SecurityOrchestration|branch"
msgstr ""
@@ -34857,7 +35273,7 @@ msgid "SecurityReports|Create issue"
msgstr "Crear incidencia"
msgid "SecurityReports|Development vulnerabilities"
-msgstr ""
+msgstr "vulnerabilidades de desarrollo"
msgid "SecurityReports|Dismiss vulnerability"
msgstr "Descartar vulnerabilidad"
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar descartados"
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Incidencia creada"
@@ -34955,6 +35374,15 @@ msgstr "Oops, algo parece que no está correcto."
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 "Proyecto"
@@ -35309,9 +35737,6 @@ 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 "Los niveles seleccionados no pueden ser utilizados por usuarios que no tengan permisos de admnistración para grupos, proyectos o fragmentos de código. Si el nivel público está restringido, los perfiles de usuario solo son visibles para los usuarios registrados."
-msgid "Selected projects"
-msgstr "Seleccionar proyectos"
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35340,19 +35765,19 @@ msgid "SelfMonitoring|Activate self monitoring to create a project to use to mon
msgstr ""
msgid "SelfMonitoring|Deactivate self monitoring?"
-msgstr ""
+msgstr "¿Desactivar auto monitorización?"
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 ""
+msgstr " Auto monitorización"
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 ""
+msgstr "Proyecto de auto monitorización creado con correctamente."
msgid "SelfMonitoring|Self monitoring project successfully deleted."
msgstr ""
@@ -35397,7 +35822,7 @@ msgid "Send report"
msgstr "Enviar informe"
msgid "Send service data"
-msgstr ""
+msgstr "Enviar datos de servicio"
msgid "Sentry"
msgstr "Sentry"
@@ -35457,7 +35882,7 @@ msgid "Service accounts"
msgstr "Cuentas de servicio"
msgid "Service usage data"
-msgstr ""
+msgstr "Datos de uso del servicio"
msgid "ServiceDesk|Enable Service Desk"
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr "Servicios"
-
msgid "Session ID"
msgstr "ID de sesión"
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Establezca una contraseña en su cuenta para hacer pull o push vía %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35649,7 +36068,7 @@ msgid "Set weight to %{weight}."
msgstr "Establecer el peso a %{weight}."
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Aparece un indicador junto a su nombre y su avatar"
msgid "SetStatusModal|Busy"
msgstr ""
@@ -35765,10 +36184,10 @@ msgid "Shared runners are disabled for the parent group"
msgstr ""
msgid "Shared runners are disabled on group level"
-msgstr ""
+msgstr "Los ejecutores compartidos están deshabilitados a nivel de grupo"
msgid "Shared runners details"
-msgstr ""
+msgstr "Detalles de los ejecutores compartidos"
msgid "Shared runners enabled cannot be enabled until a valid credit card is on file"
msgstr ""
@@ -35980,7 +36399,7 @@ msgid "Showing %{pageSize} of %{total} %{issuableType}"
msgstr "Mostrando %{pageSize} de %{total} %{issuableType}"
msgid "Showing all epics"
-msgstr ""
+msgstr "Mostrar todas las tareas épicas"
msgid "Showing all issues"
msgstr "Mostrar todas las incidencias"
@@ -35998,16 +36417,16 @@ msgid "Showing latest version"
msgstr ""
msgid "Showing version #%{versionNumber}"
-msgstr ""
+msgstr "Mostrando la versión #%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
msgstr "En paralelo"
msgid "Sidebar|%{name}: %{value}"
-msgstr ""
+msgstr "%{name}: %{value}"
msgid "Sidebar|Assign health status"
msgstr "Asignar estado de salud"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr "Página de inicio de sesión"
@@ -36096,6 +36518,9 @@ msgstr "Restricciones de inicio de sesión"
msgid "Sign-in text"
msgstr "Texto de inicio de sesión"
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr "URL de la página de cierre de sesión"
@@ -36235,10 +36660,10 @@ msgid "SlackIntegration|Verification token"
msgstr "Token de verificación"
msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
-msgstr ""
+msgstr "Ahora puede cerrar esta ventana e ir a su espacio de trabajo de Slack."
msgid "SlackIntegration|You may need to reinstall the Slack application when we %{linkStart}make updates or change permissions%{linkEnd}."
-msgstr ""
+msgstr "Es posible que deba reinstalar de nuevo la aplicación Slack cuando %{linkStart}realicemos actualizaciones o cambiemos los permisos%{linkEnd}."
msgid "SlackService|1. %{slash_command_link_start}Add a slash command%{slash_command_link_end} in your Slack team using this information:"
msgstr ""
@@ -36330,20 +36755,17 @@ msgstr "Sólido"
msgid "Solution"
msgstr "Solución"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
msgid "Some child epics may be hidden due to applied filters"
-msgstr ""
+msgstr "Algunas tareas épicas pueden estar ocultas debido a los filtros aplicados"
msgid "Some common domains are not allowed. %{learn_more_link}."
-msgstr ""
+msgstr "Algunos dominios comunes no están permitidos. %{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 "Alguien editó este archivo al mismo tiempo que usted. Por favor revise %{link_start} el archivo %{icon}%{link_end}} y asegúrese de que los cambios que ha realizado no eliminen sin querer los cambios realizados por la otra persona."
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 "Alguien editó esta incidencia al mismo tiempo que usted. Por favor revise %{linkStart} esta incidencia%{linkEnd} y asegúrese de que los cambios que ha realizado no eliminen sin querer los cambios realizados por la otra persona."
@@ -36355,10 +36777,10 @@ msgid "Someone edited this merge request at the same time you did. Please refres
msgstr "Alguien editó este merge request al mismo tiempo que lo hizo usted. Por favor, actualice la página para ver los cambios."
msgid "Someone edited this test case at the same time you did. The description has been updated and you will need to make your changes again."
-msgstr ""
+msgstr "Alguien editó este caso de prueba al mismo tiempo que usted. Se ha actualizado la descripción y deberá hacer sus cambios de nuevo."
msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
-msgstr ""
+msgstr "Alguien, esperemos que usted, ha solicitado restablecer la contraseña de su cuenta de GitLab en %{link_to_gitlab}."
msgid "Something went wrong"
msgstr ""
@@ -36379,7 +36801,7 @@ msgid "Something went wrong trying to change the locked state of this %{issuable
msgstr "Algo salió mal al intentar cambiar el estado de bloqueo de este %{issuableDisplayName}. ¡Por favor, inténtelo de nuevo!"
msgid "Something went wrong trying to load issue contacts."
-msgstr ""
+msgstr "Se ha producido un error al intentar cargar los contactos de la incidencia."
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -36394,19 +36816,19 @@ msgid "Something went wrong while applying the suggestion. Please try again."
msgstr "Se ha producido un error al aplicar la sugerencia. Por favor, inténtelo de nuevo."
msgid "Something went wrong while archiving a requirement."
-msgstr ""
+msgstr "Se ha producido un error al archivar un requisito."
msgid "Something went wrong while closing the epic. Please try again later."
-msgstr ""
+msgstr "Se ha producido un error al cerrar la tarea épica . ¡Por favor, inténtelo de nuevo más tarde!"
msgid "Something went wrong while closing the merge request. Please try again later."
msgstr ""
msgid "Something went wrong while creating a requirement."
-msgstr ""
+msgstr "Se ha producido un error al crear un requisito."
msgid "Something went wrong while deleting description changes. Please try again."
-msgstr ""
+msgstr "Se ha producido un error al borrar los cambios de descripción. Por favor, inténtelo de nuevo."
msgid "Something went wrong while deleting the source branch. Please try again."
msgstr "Se ha producido un error al eliminar la rama origen. Por favor, inténtelo de nuevo."
@@ -36421,7 +36843,7 @@ msgid "Something went wrong while editing your comment. Please try again."
msgstr "Se ha producido un error al editar su comentario. Por favor, inténtalo de nuevo."
msgid "Something went wrong while exporting requirements"
-msgstr ""
+msgstr "Se ha producido un error al exportar los requisitos."
msgid "Something went wrong while fetching branches"
msgstr ""
@@ -36433,7 +36855,7 @@ msgid "Something went wrong while fetching description changes. Please try again
msgstr "Se ha producido un error al recuperar los cambios de descripción. Por favor, inténtelo de nuevo."
msgid "Something went wrong while fetching details"
-msgstr ""
+msgstr "Se ha producido un error al obtener los detalles"
msgid "Something went wrong while fetching group member contributions"
msgstr "Algo salió mal al obtener las contribuciones de los miembros del grupo. ¡Por favor, inténtelo de nuevo!"
@@ -36451,10 +36873,10 @@ msgid "Something went wrong while fetching related merge requests."
msgstr "Se ha producido un error al obtener los merge request relacionados."
msgid "Something went wrong while fetching requirements count."
-msgstr ""
+msgstr "Se ha producido un error al obtener el recuento de requisitos."
msgid "Something went wrong while fetching requirements list."
-msgstr ""
+msgstr "Se ha producido un error al obtener la lista de requisitos."
msgid "Something went wrong while fetching source branches."
msgstr ""
@@ -36475,7 +36897,7 @@ msgid "Something went wrong while promoting the issue to an epic. Please try aga
msgstr ""
msgid "Something went wrong while reopening a requirement."
-msgstr ""
+msgstr "Se ha producido un error al reabrir un requisito."
msgid "Something went wrong while reopening the epic. Please try again later."
msgstr ""
@@ -36508,10 +36930,10 @@ msgid "Something went wrong while stopping this environment. Please try again."
msgstr "Se ha producido un error al detener este entorno. Por favor, inténtalo de nuevo."
msgid "Something went wrong while updating a requirement."
-msgstr ""
+msgstr "Se ha producido un error al actualizar un requisito."
msgid "Something went wrong while updating assignees"
-msgstr ""
+msgstr "Se ha producido un error mientras se actualizaban los asignados"
msgid "Something went wrong while updating your list settings"
msgstr ""
@@ -36523,7 +36945,7 @@ msgid "Something went wrong, unable to add %{project} to dashboard"
msgstr "Se ha producido un erro al añadir %{project} al tablero"
msgid "Something went wrong, unable to delete project"
-msgstr ""
+msgstr "Se ha producido un error, no se puede eliminar el proyecto"
msgid "Something went wrong, unable to get projects"
msgstr "Se ha producido un error al obtener los proyectos"
@@ -36565,10 +36987,10 @@ msgid "SortOptions|Blocking"
msgstr ""
msgid "SortOptions|Closed date"
-msgstr ""
+msgstr "Fecha de cierre"
msgid "SortOptions|Closed earlier"
-msgstr ""
+msgstr "Cerrado antes"
msgid "SortOptions|Closed recently"
msgstr ""
@@ -36748,7 +37170,7 @@ msgid "Source project cannot be found."
msgstr "No se puede encontrar el proyecto."
msgid "SourceEditor|\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "El parámetro \"el\" es requerido para createInstance()"
msgid "SourceEditor|%{name} is not registered."
msgstr "%{name} no está registrado."
@@ -36919,10 +37341,10 @@ msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
msgid "Start a Free Ultimate Trial"
-msgstr ""
+msgstr "Iniciar la versión de prueba de GitLab Ultimate"
msgid "Start a new discussion…"
-msgstr ""
+msgstr "Comenzar una nueva discusión"
msgid "Start a new merge request with these changes"
msgstr ""
@@ -36946,7 +37368,7 @@ msgid "Start inputting changes and we will generate a YAML-file for you to add t
msgstr ""
msgid "Start internal thread"
-msgstr ""
+msgstr "Comenzar hilo interno"
msgid "Start merge train"
msgstr ""
@@ -36964,7 +37386,7 @@ msgid "Start thread"
msgstr "Iniciar un hilo"
msgid "Start your Free Ultimate Trial"
-msgstr ""
+msgstr "Iniciar su versión de prueba de GitLab Ultimate"
msgid "Start your free trial"
msgstr "Comience su prueba gratuita"
@@ -36979,13 +37401,13 @@ msgid "Started asynchronous removal of all repository check states."
msgstr "Se inició la eliminación asíncrona de todos los estados de verificación del repositorio."
msgid "Started escalation for this incident."
-msgstr ""
+msgstr "Comenzó la escalada para este incidente."
msgid "Starting..."
msgstr "Iniciando..."
msgid "Starts"
-msgstr ""
+msgstr "Comienza"
msgid "Starts %{startsIn}"
msgstr "Comienza %{startsIn}"
@@ -36994,7 +37416,7 @@ msgid "Starts at (UTC)"
msgstr "Comienza a las (UTC)"
msgid "Starts escalations for this incident"
-msgstr ""
+msgstr "Comenzar la escalada para este incidente."
msgid "Starts on"
msgstr ""
@@ -37039,19 +37461,19 @@ msgid "StatusCheck|%{pending} pending"
msgstr "%{pending} pendiente"
msgid "StatusCheck|API to check"
-msgstr ""
+msgstr "API a comprobar"
msgid "StatusCheck|Add status check"
-msgstr ""
+msgstr "Añadir una verificación de estado"
msgid "StatusCheck|All passed"
msgstr "Todo superado"
msgid "StatusCheck|An error occurred deleting the %{name} status check."
-msgstr ""
+msgstr "Se ha producido un error al eliminar la comprobación de estado %{name}."
msgid "StatusCheck|An error occurred fetching the status checks."
-msgstr ""
+msgstr "Se ha producido un error al obtener las comprobaciones de estado."
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
@@ -37060,7 +37482,7 @@ msgid "StatusCheck|Check for a status response in merge requests. Failures do no
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
-msgstr ""
+msgstr "Ejemplos: QA, Seguridad."
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
@@ -37078,10 +37500,10 @@ msgid "StatusCheck|No status checks are defined yet."
msgstr ""
msgid "StatusCheck|Remove status check"
-msgstr ""
+msgstr "Eliminar la verificación de estado"
msgid "StatusCheck|Remove status check?"
-msgstr ""
+msgstr "¿Eliminar la verificación de estado?"
msgid "StatusCheck|Service name"
msgstr ""
@@ -37096,7 +37518,7 @@ msgid "StatusCheck|Status checks are being fetched"
msgstr ""
msgid "StatusCheck|Status to check"
-msgstr ""
+msgstr "Comprobaciones de estado"
msgid "StatusCheck|Target branch"
msgstr ""
@@ -37201,7 +37623,7 @@ msgid "Strikethrough"
msgstr ""
msgid "Strikethrough text"
-msgstr ""
+msgstr "Texto tachado"
msgid "Sub-batch size"
msgstr ""
@@ -37297,7 +37719,7 @@ msgid "Subscribed to this %{quick_action_target}."
msgstr "Suscrito a este %{quick_action_target}."
msgid "Subscribed to this project"
-msgstr ""
+msgstr "Suscrito a este proyecto"
msgid "Subscribes to this %{quick_action_target}."
msgstr "Se suscribe a este %{quick_action_target}."
@@ -37381,7 +37803,7 @@ msgid "SubscriptionTable|Seats owed"
msgstr "Número máximo de puestos adeudados"
msgid "SubscriptionTable|See usage"
-msgstr ""
+msgstr "Ver uso"
msgid "SubscriptionTable|Something went wrong trying to refresh seats"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr "Sustraer"
msgid "Succeeded"
msgstr "Éxito"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "Activado correctamente"
@@ -37474,7 +37893,7 @@ msgid "Successfully deleted U2F device."
msgstr "Dispositivo U2F eliminado con éxito."
msgid "Successfully deleted WebAuthn device."
-msgstr ""
+msgstr "Se ha eliminado correctamente el dispositivo WebAuthn."
msgid "Successfully removed email."
msgstr "Correo electrónico eliminado con éxito."
@@ -37483,7 +37902,7 @@ msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_star
msgstr "Se ha programado un pipeline a ejecutar. Vaya a la página %{pipelines_link_start}Pipelines%{pipelines_link_end} para obtener más detalles."
msgid "Successfully synced %{synced_timeago}."
-msgstr ""
+msgstr "sincronizado correctamente hace %{synced_timeago} ."
msgid "Successfully unbanned"
msgstr "Desbloqueado con éxito"
@@ -37495,7 +37914,7 @@ msgid "Successfully unlocked"
msgstr "Desbloqueado con éxito"
msgid "Successfully updated %{last_updated_timeago}."
-msgstr ""
+msgstr "Actualizado correctamente %{last_updated_timeago}."
msgid "Successfully updated the environment."
msgstr "Entorno actualizado correctamente."
@@ -37567,10 +37986,10 @@ msgid "SuggestedColors|Green-cyan"
msgstr ""
msgid "SuggestedColors|Lavendar"
-msgstr ""
+msgstr "Lavanda"
msgid "SuggestedColors|Magenta-pink"
-msgstr ""
+msgstr "Magenta-rosa"
msgid "SuggestedColors|Medium sea green"
msgstr ""
@@ -37585,10 +38004,10 @@ msgid "SuggestedColors|Red"
msgstr "Rojo"
msgid "SuggestedColors|Rose red"
-msgstr ""
+msgstr "Rojo rosado"
msgid "SuggestedColors|Titanium yellow"
-msgstr ""
+msgstr "Amarillo titanio"
msgid "Suggestion is not applicable as the suggestion was not found."
msgstr ""
@@ -37630,25 +38049,25 @@ msgid "SuperSonics|An error occurred while adding your subscription."
msgstr "Se ha producido un error al añadir su suscripción."
msgid "SuperSonics|Billable users"
-msgstr ""
+msgstr "Usuarios facturables"
msgid "SuperSonics|Buy subscription"
msgstr "Comprar suscripción"
msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr ""
+msgstr "Se ha producido un error al activar la instancia debido a un problema de conectividad."
msgid "SuperSonics|Cloud licensing"
-msgstr ""
+msgstr "Licencias en la nube"
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 ""
+msgstr "Introduzca el código de activación"
msgid "SuperSonics|Export license usage file"
-msgstr ""
+msgstr "Exportar archivo de uso de licencia"
msgid "SuperSonics|Free trial"
msgstr "Prueba gratuita"
@@ -37663,13 +38082,13 @@ msgid "SuperSonics|Learn more about %{activationLinkStart}activating your subscr
msgstr ""
msgid "SuperSonics|Licensed to"
-msgstr ""
+msgstr "Licenciado a "
msgid "SuperSonics|Manage"
msgstr "Gestionar"
msgid "SuperSonics|Maximum users"
-msgstr ""
+msgstr "Usuarios máximos"
msgid "SuperSonics|Offline license"
msgstr "Licencia sin conexión"
@@ -37681,13 +38100,13 @@ msgid "SuperSonics|Paste your activation code"
msgstr "Pegue su código de activación"
msgid "SuperSonics|Please agree to the Subscription Agreement"
-msgstr ""
+msgstr "Por favor, acepte el acuerdo de suscripción"
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 ""
+msgstr "Iniciar prueba gratuita"
msgid "SuperSonics|Subscription details"
msgstr "Detalles de la suscripción"
@@ -37702,13 +38121,13 @@ 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 ""
+msgstr "El código de activación no es válido. Por favor, asegúrese de copiarlo exactamente desde el Portal del Cliente o desde el correo electrónico de confirmación. En el siguiente enlace puede obtener más información sobre como %{linkStart}activar su suscripción%{linkEnd}."
msgid "SuperSonics|The activation code should be a 24-character alphanumeric string"
-msgstr ""
+msgstr "El código de activación debe ser una cadena alfanumérica de 24 caracteres"
msgid "SuperSonics|There is a connectivity issue."
-msgstr ""
+msgstr "Hay un problema de conectividad."
msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -37776,10 +38195,10 @@ msgid "SuperSonics|Your subscription was successfully activated. You can see the
msgstr ""
msgid "SuperSonics|current subscription"
-msgstr ""
+msgstr "suscripción actual"
msgid "SuperSonics|future subscriptions"
-msgstr ""
+msgstr "suscripciones futuras"
msgid "SuperSonics|past subscriptions"
msgstr "Suscripciones anteriores"
@@ -37796,9 +38215,6 @@ msgstr "El soporte para certificados personalizados está deshabilitado. Pida al
msgid "Support page URL"
msgstr "URL de la página de soporte"
-msgid "Survey Response"
-msgstr "Respuesta de la encuesta"
-
msgid "Surveys|Delighted"
msgstr "Surveys|Encantado"
@@ -37901,6 +38317,9 @@ msgstr "Métricas del sistema (Kubernetes)"
msgid "System output"
msgstr "Salida del sistema"
+msgid "System started"
+msgstr "Sistema iniciado"
+
msgid "Table of Contents"
msgstr "Tabla de contenidos"
@@ -37973,6 +38392,9 @@ msgstr "Cancelar"
msgid "TagsPage|Cancel, keep tag"
msgstr "Cancelar, mantener etiqueta"
+msgid "TagsPage|Create release"
+msgstr "Create versión"
+
msgid "TagsPage|Create tag"
msgstr "Crear etiqueta"
@@ -37980,19 +38402,19 @@ msgid "TagsPage|Delete protected tag"
msgstr "Eliminar etiqueta protegida"
msgid "TagsPage|Delete protected tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Eliminar la etiqueta protegida. ¿Está ABSOLUTAMENTE SEGURO?"
msgid "TagsPage|Delete tag"
msgstr "Eliminar etiqueta"
msgid "TagsPage|Delete tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Eliminar la etiqueta. ¿Está ABSOLUTAMENTE SEGURO?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Editar las notas de la versión"
+msgid "TagsPage|Edit release"
+msgstr "Editar versión"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Nombre de la rama, del tag o commit SHA existente"
@@ -38090,9 +38512,6 @@ msgstr "ID de tarea: %{elastic_task}"
msgid "Task list"
msgstr "Lista de tareas"
-msgid "Task with ID: %{id} could not be found."
-msgstr "No se ha encontrado la tarea con el ID: %{id}."
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38130,19 +38549,19 @@ msgid "Templates"
msgstr "Plantillas"
msgid "TemporaryStorageIncrease|can only be set once"
-msgstr ""
+msgstr "solo se puede configurar una vez"
msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
-msgstr ""
+msgstr "solo se puede configurar con más de un %{percentage}%% de uso"
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 ""
+msgstr "Aumentar el almacenamiento temporalmente"
msgid "TemporaryStorage|Temporarily increase storage now?"
-msgstr ""
+msgstr "¿Aumentar temporalmente el almacenamiento ahora?"
msgid "Terminal"
msgstr "Terminal"
@@ -38179,8 +38598,8 @@ msgstr "%{name} eliminado correctamente"
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{number} No se puede generar el informe de Terraform"
+msgstr[1] "%{number} No se pueden generar los informes de Terraform"
msgid "Terraform|%{number} Terraform report was generated in your pipelines"
msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
@@ -38243,7 +38662,7 @@ msgid "Terraform|Download JSON"
msgstr "Descargar JSON"
msgid "Terraform|Failed to load Terraform reports"
-msgstr ""
+msgstr "Se ha producido un error al cargar los informes de Terraform"
msgid "Terraform|Generating the report caused an error."
msgstr "La generación del informe provocó un error."
@@ -38279,7 +38698,7 @@ msgid "Terraform|Remove"
msgstr "Eliminar"
msgid "Terraform|Remove state file and versions"
-msgstr ""
+msgstr "Eliminar el archivo de estado y sus versiones"
msgid "Terraform|Removed"
msgstr "Eliminado"
@@ -38300,10 +38719,10 @@ msgid "Terraform|Terraform reports"
msgstr "Informes de Terraform"
msgid "Terraform|The job %{name} failed to generate a report."
-msgstr ""
+msgstr "El trabajo %{name} no pudo generar un informe."
msgid "Terraform|The job %{name} generated a report."
-msgstr ""
+msgstr "El trabajo %{name} generó un informe."
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
msgstr ""
@@ -38339,10 +38758,10 @@ msgid "Test"
msgstr "Probar"
msgid "Test Cases"
-msgstr ""
+msgstr "Casos de prueba"
msgid "Test case"
-msgstr ""
+msgstr "Caso de prueba"
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."
@@ -38358,19 +38777,19 @@ msgid "Test settings"
msgstr ""
msgid "TestCases|Move test case"
-msgstr ""
+msgstr "Mover caso de prueba"
msgid "TestCases|Moving test case"
-msgstr ""
+msgstr "Moviendo caso de prueba"
msgid "TestCases|New Test Case"
-msgstr ""
+msgstr "Nuevo caso de prueba"
msgid "TestCases|New test case"
-msgstr ""
+msgstr "Nuevo caso de prueba"
msgid "TestCases|Search test cases"
-msgstr ""
+msgstr "Buscar casos de prueba"
msgid "TestCases|Something went wrong while adding test case to a to-do item."
msgstr ""
@@ -38442,7 +38861,7 @@ msgid "TestReports|Attachment"
msgstr "Adjunto"
msgid "TestReports|Copy test name to rerun locally"
-msgstr ""
+msgstr "Copiar el nombre de la prueba para volver a ejecutarla localmente"
msgid "TestReports|Job artifacts are expired"
msgstr "Los artefactos del trabajo han caducado"
@@ -38501,9 +38920,6 @@ msgstr "Estilo del texto"
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr "¡Gracias por sus comentarios!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Gracias por su informe. Un administrador de GitLab lo examinará en breve."
@@ -38618,7 +39034,7 @@ msgid "The content for this wiki page failed to load. To fix this error, reload
msgstr ""
msgid "The content for this wiki page failed to render."
-msgstr ""
+msgstr "No se ha podido procesar el contenido de esta página wiki."
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
msgstr "El contenido de esta página no está codificado en UTF-8. Las ediciones sobre este contenido, solo se pueden realizar a través del repositorio Git."
@@ -38627,7 +39043,7 @@ msgid "The contents of this group, its subgroups and projects will be permanentl
msgstr ""
msgid "The current epic"
-msgstr ""
+msgstr "La tarea épica actual"
msgid "The current incident"
msgstr "La incidencia actual"
@@ -38636,7 +39052,7 @@ msgid "The current issue"
msgstr "La incidencia actual"
msgid "The current user is not authorized to access the job log."
-msgstr ""
+msgstr "El usuario actual no está autorizado a acceder al registro de ejecución del trabajo."
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 ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38835,7 +39248,7 @@ msgid "The maximum file size for job artifacts."
msgstr "El tamaño máximo de archivo para los artefactos del trabajo."
msgid "The maximum file size in megabytes for individual job artifacts."
-msgstr ""
+msgstr "El tamaño máximo de archivo en megabytes para los artefactos de trabajo individuales."
msgid "The maximum file size is %{size}."
msgstr "El tamaño máximo del archivo es %{size}."
@@ -38934,7 +39347,7 @@ msgid "The report artifact provided by the CI build couldn't be parsed."
msgstr ""
msgid "The report has been successfully prepared."
-msgstr ""
+msgstr "El informe se ha preparado correctamente."
msgid "The repository can be committed to, and issues, comments and other entities can be created."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 "El recurso al que está intentando acceder no existe o no tiene permiso para realizar esta acción."
+
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 ""
@@ -38979,7 +39395,7 @@ msgid "The specified tab is invalid, please select another"
msgstr "La pestaña especificada no es válida, por favor seleccione otra"
msgid "The start date must be ealier than the end date."
-msgstr ""
+msgstr "La fecha de inicio debe ser anterior a la fecha de finalización."
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 ""
@@ -39030,10 +39446,10 @@ msgid "The vulnerability is no longer detected. Verify the vulnerability has bee
msgstr ""
msgid "Theme"
-msgstr ""
+msgstr "Tema"
msgid "There are currently no events."
-msgstr ""
+msgstr "Actualmente no hay eventos."
msgid "There are merge conflicts"
msgstr ""
@@ -39063,9 +39479,12 @@ msgid "There are no archived projects yet"
msgstr "Aún no hay proyectos archivados"
msgid "There are no archived requirements"
-msgstr ""
+msgstr "No hay requisitos archivados"
msgid "There are no archived test cases"
+msgstr "No hay casos de prueba archivados"
+
+msgid "There are no changed labels"
msgstr ""
msgid "There are no changes"
@@ -39075,7 +39494,7 @@ msgid "There are no charts configured for this page"
msgstr "No hay gráficas configuradas para esta página"
msgid "There are no closed epics"
-msgstr ""
+msgstr "No hay tareas epicas cerradas"
msgid "There are no closed issues"
msgstr "No hay ninguna incidencia cerrada"
@@ -39084,7 +39503,7 @@ msgid "There are no closed merge requests"
msgstr "No hay merge request cerrados"
msgid "There are no commits yet."
-msgstr ""
+msgstr "Aún no hay commits."
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 "No hay plantillas de proyecto personalizadas para esta instancia de GitLab. Estas plantillas se habilitan desde el área de administración de GitLab. Por favor, póngase en contacto con el administrador de la instancia de GitLab para configurar plantillas de proyecto personalizadas."
@@ -39093,13 +39512,13 @@ msgid "There are no issues to show"
msgstr "Aún no hay incidencias que mostrar"
msgid "There are no issues with the selected labels"
-msgstr ""
+msgstr "No hay incidencias con las etiquetas seleccionadas"
msgid "There are no matching files"
msgstr "No hay archivos coincidentes"
msgid "There are no open epics"
-msgstr ""
+msgstr "No hay tareas epicas abiertas"
msgid "There are no open issues"
msgstr "No hay ninguna incidencia abierta"
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "Ya hay un repositorio con ese nombre en el disco"
@@ -39195,7 +39617,7 @@ msgid "There was a problem fetching linked pipelines."
msgstr ""
msgid "There was a problem fetching milestones."
-msgstr ""
+msgstr "Se ha producido un problema al recuperar los hitos."
msgid "There was a problem fetching project branches."
msgstr ""
@@ -39207,13 +39629,13 @@ msgid "There was a problem fetching project users."
msgstr "Se ha producido un problema al recuperar los usuarios del proyecto."
msgid "There was a problem fetching recent groups."
-msgstr ""
+msgstr "Se ha producido un problema al recuperar los grupos recientes."
msgid "There was a problem fetching recent projects."
-msgstr ""
+msgstr "Se ha producido un problema al recuperar los projectos recientes."
msgid "There was a problem fetching releases."
-msgstr ""
+msgstr "Se ha producido un problema al recuperar las versiones."
msgid "There was a problem fetching the job token scope value"
msgstr ""
@@ -39228,7 +39650,7 @@ msgid "There was a problem fetching the pipeline stages."
msgstr ""
msgid "There was a problem fetching the projects"
-msgstr ""
+msgstr "Se ha producido un problema al recuperar los projectos"
msgid "There was a problem fetching users."
msgstr "Se ha producido un error al recuperar los usuarios."
@@ -39242,9 +39664,6 @@ msgstr "Se ha producido un error al enviar el correo electrónico de confirmaciÃ
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr "Se ha producido un error al añadir la tarea a la lista de tareas pendientes."
@@ -39323,14 +39742,11 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Se ha producido un error al eliminar el correo electrónico."
-msgid "There was an error resetting group pipeline minutes."
-msgstr "Se ha producido un error al restablecer los minutos de ejecución de los pipelines del grupo."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "Se ha producido un error al restablecer los minutos de ejecución de los pipelines del usuario."
msgid "There was an error retrieving the Jira users."
-msgstr ""
+msgstr "Se ha producido un error al recuperar los usuarios de Jira."
msgid "There was an error saving your changes."
msgstr "Se ha producido un error al guardar sus cambios."
@@ -39339,10 +39755,10 @@ msgid "There was an error subscribing to this label."
msgstr "Se ha producido un error al subscribirse a esta etiqueta."
msgid "There was an error syncing project %{name}"
-msgstr ""
+msgstr "Se ha producido un error al sincronizar el proyecto %{name}"
msgid "There was an error syncing the %{replicableType}"
-msgstr ""
+msgstr "Se ha producido un error al sincronizar el %{replicableType}"
msgid "There was an error trying to validate your query"
msgstr "Se ha producido un error al intentar validar su consulta"
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "Se ha producido un error con reCAPTCHA. Por favor, resuelva el reCAPTCHA de nuevo."
@@ -39560,6 +39973,9 @@ msgstr "Este directorio"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "Este dominio no está verificado. Es necesario verificar la propiedad del mismo antes de activar el acceso."
+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 ""
@@ -39654,10 +40070,10 @@ msgid "This is a \"Ghost User\", created to hold all issues authored by users th
msgstr "Este es un usuario \"fantasma\", creado para mantener todas las incidencias creadass por usuarios de Gitlab que ya han sido eliminados. Este usuario no se puede eliminar."
msgid "This is a Jira user."
-msgstr ""
+msgstr "Este es un usuario de Jira."
msgid "This is a confidential %{noteableTypeText}."
-msgstr ""
+msgstr "Este es un %{noteableTypeText} confidencial."
msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
@@ -39861,7 +40277,7 @@ msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{
msgstr "Este pipeline utiliza una configuración de CI/CD predefinida habilitada por %{strongStart}Auto DevOps.%{strongEnd}"
msgid "This pipeline was triggered by a schedule."
-msgstr ""
+msgstr "Este pipeline se ejecutó mediante una programación."
msgid "This process deletes the project repository and all related resources."
msgstr ""
@@ -39909,14 +40325,20 @@ msgid "This project path either does not exist or you do not have access."
msgstr ""
msgid "This project will be deleted on %{date}"
-msgstr ""
+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 ""
+msgstr "Este proyecto se eliminará el %{date} , ya que se programó la eliminación de su grupo principal '%{parent_group_name}'."
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Este repositorio"
@@ -40229,6 +40651,9 @@ 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 "Tiempo de espera"
@@ -40311,9 +40736,6 @@ 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."
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr "Para mantener este proyecto en marcha, cree un nuevo merge request"
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40618,11 +41040,14 @@ msgid "Too many references. Quick actions are limited to at most %{max_count} us
msgstr "Demasiadas referencias. Las acciones rápidas están limitadas a un máximo de %{max_count} referencias de usuario"
msgid "Too many users found. Quick actions are limited to at most %{max_count} users"
-msgstr ""
+msgstr "Se encontraron demasiados usuarios. Las acciones rápidas están limitadas a un máximo de %{max_count} usuarios"
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ msgstr "Intente cambiar o quitar los filtros."
msgid "Try grouping with different labels"
msgstr "Intente agrupar con diferentes etiquetas"
+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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Tipo"
+msgid "Type to search"
+msgstr "Teclee para buscar"
+
msgid "U2F Devices (%{length})"
msgstr "Dispositivos U2F (%{length})"
@@ -41133,6 +41564,9 @@ msgstr "No se puede cargar el fichero diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
+msgid "Unable to parse JSON"
+msgstr "No se puede analizar JSON"
+
msgid "Unable to parse the vulnerability report's options."
msgstr "No se pueden analizar las opciones del informe de vulnerabilidades."
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr "Formato desconocido"
msgid "Unknown response text"
msgstr "Texto de respuesta desconocido"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr "Actualizando"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr "Suba un certificado para su dominio con todos los certificados intermedi
msgid "Upload a private key for your certificate"
msgstr "Suba una clave privada para su certificado"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Subir archivo"
@@ -41479,7 +41913,7 @@ msgid "Upload object map"
msgstr "Subir un mapa de objetos"
msgid "Uploaded date"
-msgstr ""
+msgstr "Fecha de subida"
msgid "Uploading changes to terminal"
msgstr "Subir los cambios al terminal"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr "Upstream"
-msgid "Uptime"
-msgstr "Tiempo de funcionamiento"
-
msgid "Upvotes"
msgstr "Votos positivos"
@@ -41553,14 +41984,14 @@ msgstr "Periodo actual de uso"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Repositorio Git."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
msgstr ""
@@ -41575,7 +42006,7 @@ msgid "UsageQuota|Increase storage temporarily"
msgstr ""
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "Almacenamiento LFS"
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ msgstr "Utilice su tarjeta inteligente para autenticarse contra el servidor LDAP
msgid "Used"
msgstr "Utilizado"
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "Utilizado por %d paquete"
+msgstr[1] "Utilizado por %d paquetes"
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilizado por los miembros para iniciar sesión en su grupo en GitLab"
@@ -41968,10 +42419,10 @@ msgid "User cap cannot be enabled. The group or one of its subgroups or projects
msgstr ""
msgid "User created at"
-msgstr ""
+msgstr "Usuario creado el"
msgid "User does not have a pending request"
-msgstr ""
+msgstr "El usuario no tiene una solicitudes pendientes"
msgid "User identity was successfully created."
msgstr "La identidad de usuario se ha creado correctamente."
@@ -41986,7 +42437,7 @@ msgid "User is not allowed to resolve thread"
msgstr "El usuario no está autorizado a resolver el hilo"
msgid "User key"
-msgstr ""
+msgstr "Clave de usuario"
msgid "User key was successfully removed."
msgstr "La clave de usuario se ha eliminado correctamente."
@@ -42018,6 +42469,9 @@ msgstr "El usuario fue eliminado correctamente del grupo."
msgid "User was successfully removed from project."
msgstr "Se ha eliminado el usuario correctamente del proyecto."
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "Usuario actualizado correctamente."
@@ -42126,6 +42580,9 @@ msgstr "Actividad del bot"
msgid "UserProfile|Contributed projects"
msgstr "Proyectos contribuidos"
+msgid "UserProfile|Copy user ID"
+msgstr "Copiar ID de usuario"
+
msgid "UserProfile|Edit profile"
msgstr "Editar perfil"
@@ -42207,6 +42664,9 @@ msgstr "Este usuario no está siguiendo a otros usuarios."
msgid "UserProfile|Unconfirmed user"
msgstr "Usuario no confirmado"
+msgid "UserProfile|User ID: %{id}"
+msgstr "ID del usuario: %{id}"
+
msgid "UserProfile|View all"
msgstr "Ver todo"
@@ -42274,7 +42734,7 @@ msgid "Users can render diagrams in AsciiDoc, Markdown, reStructuredText, and Te
msgstr ""
msgid "Users can request access (if visibility is public or internal)"
-msgstr ""
+msgstr "Los usuarios pueden solicitar acceso (si la visibilidad es pública o interna)"
msgid "Users cannot be added to projects in this group"
msgstr "No se pueden añadir usuarios a proyectos en este grupo"
@@ -42328,7 +42788,7 @@ msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their
msgstr ""
msgid "Valid From"
-msgstr ""
+msgstr "Valido desde"
msgid "Validate"
msgstr "Validar"
@@ -42340,13 +42800,13 @@ msgid "Validate your GitLab CI configuration file"
msgstr "Valide su archivo de configuración de GitLab CI"
msgid "Validated at"
-msgstr ""
+msgstr "Validado el"
msgid "Validated at:"
-msgstr ""
+msgstr "Validado el:"
msgid "Validated:"
-msgstr ""
+msgstr "Validado:"
msgid "Validations failed."
msgstr "La validación ha fallado."
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ msgstr "Verificar la configuración"
msgid "Version"
msgstr "Versión"
+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 "Versión %{versionNumber}"
@@ -42531,19 +42998,19 @@ msgid "Version %{versionNumber} (latest)"
msgstr "Versión %{versionNumber} (última)"
msgid "VersionCheck|Up to date"
-msgstr ""
+msgstr "Actualizado"
msgid "VersionCheck|Update ASAP"
-msgstr ""
+msgstr "Actualizar lo antes posible"
msgid "VersionCheck|Update available"
-msgstr ""
+msgstr "Actualización disponible"
msgid "VersionCheck|Your GitLab Version"
-msgstr ""
+msgstr "Su versión de GitLab"
msgid "View Stage: %{title}"
-msgstr ""
+msgstr "Ver etapa: %{title}"
msgid "View alert details at"
msgstr "Ver los detalles de la alerta en"
@@ -42558,7 +43025,7 @@ msgid "View all issues"
msgstr "Ver todas las incidencias"
msgid "View all personal projects"
-msgstr ""
+msgstr "Ver todos sus proyectos personales"
msgid "View blame"
msgstr ""
@@ -42655,7 +43122,7 @@ msgid "View logs"
msgstr "Ver los logs"
msgid "View milestones"
-msgstr ""
+msgstr "Ver hitos"
msgid "View on %{url}"
msgstr "Ver en %{url}"
@@ -42673,15 +43140,15 @@ msgid "View project"
msgstr "Ver proyecto"
msgid "View project in admin area"
-msgstr ""
+msgstr "Ver el proyecto en el área de administración"
msgid "View project labels"
msgstr "Ver etiquetas de proyectos"
msgid "View public GPG key"
msgid_plural "View public GPG keys"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ver la clave pública GPG"
+msgstr[1] "Ver las claves públicas GPG"
msgid "View replaced file @ "
msgstr "Ver archivo reemplazado @ "
@@ -42720,7 +43187,7 @@ msgid "Viewing projects and designs data from a primary site is not possible whe
msgstr ""
msgid "Violation"
-msgstr ""
+msgstr "Violación"
msgid "Visibility"
msgstr "Visibilidad"
@@ -42756,10 +43223,10 @@ msgid "VisibilityLevel|Unknown"
msgstr "Desconocido"
msgid "Visual Studio Code (HTTPS)"
-msgstr ""
+msgstr "Visual Studio Code (HTTPS)"
msgid "Visual Studio Code (SSH)"
-msgstr ""
+msgstr "Visual Studio Code (SSH)"
msgid "Vulnerabilities"
msgstr "Vulnerabilidades"
@@ -42768,7 +43235,7 @@ msgid "Vulnerabilities over time"
msgstr "Vulnerabilidades a lo largo del tiempo"
msgid "Vulnerability"
-msgstr ""
+msgstr "Vulnerabilidad"
msgid "Vulnerability Report"
msgstr "Informe de vulnerabilidad"
@@ -42777,7 +43244,7 @@ msgid "Vulnerability remediated. Review before resolving."
msgstr ""
msgid "Vulnerability report"
-msgstr ""
+msgstr "Informe de vulnerabilidad"
msgid "Vulnerability resolved in %{branch}"
msgstr "Vulnerabilidad resuelta en %{branch}"
@@ -42870,7 +43337,7 @@ msgid "VulnerabilityManagement|Select a severity level"
msgstr ""
msgid "VulnerabilityManagement|Select a status"
-msgstr ""
+msgstr "Seleccione un estado"
msgid "VulnerabilityManagement|Severity is a required field"
msgstr ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 "Le enviamos un correo electrónico con las instrucciones para restablecer la contraseña"
@@ -43490,6 +43960,12 @@ msgstr "¿Qué son los eventos de auditoría de las instancias?"
msgid "What are project audit events?"
msgstr "¿Qué son los eventos de auditoría de los proyectos?"
+msgid "What are some examples?"
+msgstr ""
+
+msgid "What does the setting affect?"
+msgstr ""
+
msgid "What does this command do?"
msgstr "¿Qué hace este comando?"
@@ -43549,6 +44025,11 @@ 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 "Cuando:"
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr "Crear %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Crear página"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr "Formato"
@@ -43816,23 +44297,29 @@ msgstr "Trabajo en curso (abierto y sin asignar)"
msgid "Work in progress Limit"
msgstr "Límite de trabajo en progreso"
-msgid "WorkItem|Add"
-msgstr ""
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "Una tarea proporciona la capacidad de dividir su trabajo en piezas más pequeñas ligadas a una incidencia. Las tareas son los primeros elementos que utilizan nuestros nuevos objetos %{workItemsLink} . Pronto habrá más tipos de objetos de trabajo."
+
+msgid "WorkItem|Add a task"
+msgstr "Añadir una tarea"
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
-msgstr ""
+msgstr "Agregar asignado"
msgid "WorkItem|Add assignees"
-msgstr ""
+msgstr "Agregar asignados"
+
+msgid "WorkItem|Add task"
+msgstr "Añadir tarea"
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr "¿Está seguro que desea cancelar la edición?"
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
-msgstr ""
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "¿Está seguro que desea eliminar esta tarea? Esta acción no se puede deshacer."
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr "Elemento hijo eliminado"
+
msgid "WorkItem|Closed"
msgstr "Cerrado"
@@ -43857,24 +44347,39 @@ msgstr "Crear tarea"
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
-msgstr ""
+msgid "WorkItem|Delete task"
+msgstr "Eliminar tarea"
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr "Introducción de tareas"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "Más información sobre las tareas"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr "Abrir"
+msgid "WorkItem|Remove"
+msgstr "Eliminar"
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "Se ha producido un error al actualizar el crear una tarea. Por favor, inténtelo de nuevo"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "Se ha producido un error aleliminar una tarea. Por favor, inténtelo de nuevo."
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 "Se ha producido un error al intentar añadir un trabajo hijo. Por favor, inténtelo de nuevo."
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr "Tarea eliminada"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr "Deshacer"
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr "Elementos de trabajo"
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ msgstr "Puede probar su archivo .gitlab-ci.yml en %{linkStart}CI Lint%{linkEnd}.
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr "No puede acceder al archivo sin formato. Por favor, espere un minuto."
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr "No puede editar este evento de la línea de tiempo."
-
msgid "You cannot impersonate a blocked user"
msgstr "No puede suplantar a un usuario bloqueado"
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "No es posible crear un nuevo disparador."
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr "Aún no tiene ninguna suscripción"
@@ -44632,6 +45150,9 @@ 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 "Ya ha habilitado la autenticación de dos pasos utilizando una contraseña de un solo uso. Para registrar un dispositivo diferente, primero debe desactivar la autenticación de dos factores."
@@ -44644,9 +45165,6 @@ msgstr "Ha rechazado a %{user}"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
msgstr "Su primer proyecto"
+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 "Tus grupos"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr "Su respuesta ha sido registrada."
-
msgid "Your search didn't match any commits."
msgstr "Su búsqueda no coincide con ningún commit."
@@ -44955,16 +45480,14 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
+msgstr "Su actualización ha fallado. Solo puede cargar un diseño cuando lo coloca en un diseño existente."
msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
-msgstr ""
+msgstr "Su actualización ha fallado. Debe cargar un archivo con el mismo nombre al soltarlo sobre un diseño existente."
msgid "Your username is %{username}."
msgstr "Su nombre de usuario es %{username}."
@@ -45071,7 +45594,7 @@ msgid "allowed to fail"
msgstr "permitido fallar"
msgid "already banned from namespace"
-msgstr ""
+msgstr "ya está baneado de este espacio de nombres"
msgid "already being used for another group or project %{timebox_name}."
msgstr "ya se está utilizando para otro grupo o proyecto %{timebox_name}."
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr "asignar a ti mismo"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr "en"
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr "%{reportType}: La carga finalizó con errores"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr "Todos los clústeres"
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Todos los proyectos"
@@ -45478,7 +46016,7 @@ msgid "ciReport|Loading Code Quality report"
msgstr ""
msgid "ciReport|Manage Licenses"
-msgstr ""
+msgstr "Administrar licencias"
msgid "ciReport|Manage licenses"
msgstr "Administrar licencias"
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr "cerrado"
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr "dato"
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr "la fecha no puede ser superior a 9999-12-31"
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr "excede la longitud máxima (100 nombres de usuario)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "grupos"
@@ -45876,6 +46417,9 @@ msgstr "https://tu-servidor-bitbucket"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr "si"
+
msgid "image diff"
msgstr "imagen dif"
@@ -46052,6 +46596,9 @@ msgstr "cargando"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "manual"
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Eliminar la rama de origen"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Las estadísticas de los despliegues no están disponibles actualmente"
@@ -46229,9 +46767,6 @@ msgstr "No se cerró"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Error al cargar las estadísticas de despliegue"
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "Merge"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Merge realizado por"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46337,7 +46866,7 @@ msgid "mrWidget|More information"
msgstr "Más información"
msgid "mrWidget|No users match the rule's criteria."
-msgstr ""
+msgstr "Ningún usuario coincide con los criterios de la regla."
msgid "mrWidget|Please restore it or use a different %{type} branch."
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Los cambios se fusionaron en"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Los cambios no se fusionaron en"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Se ha eliminado el branch de origen"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "El branch de origen está siendo eliminado"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Esta merge request no se realizó automáticamente"
@@ -46575,10 +47092,10 @@ msgstr[0] "padre"
msgstr[1] "padres"
msgid "parent already has maximum number of children."
-msgstr ""
+msgstr "el padre ya tiene el número máximo de hijos."
msgid "parent must be in the same project as child."
-msgstr ""
+msgstr "el padre debe estar en el mismo proyecto que el hijo."
msgid "password"
msgstr "contraseña"
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr "repositorio:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr "satisfecho"
@@ -46733,6 +47253,9 @@ msgstr ""
msgid "security Reports|There was an error creating the merge request"
msgstr "Se ha producido un error al crear el merge request"
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr ""
+
msgid "severity|Blocker"
msgstr ""
@@ -46767,7 +47290,7 @@ msgid "should be an array of %{object_name} objects"
msgstr ""
msgid "should be an array of existing usernames. %{invalid} does not exist"
-msgstr ""
+msgstr "debe ser una matriz de nombres de usuario existentes. %{invalid} no existe"
msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
msgstr "debe ser mayor o igual que %{access} el nivel de acceso heredado del grupo %{group_name}"
@@ -46844,14 +47367,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
-msgstr "los siguientes incidentes o problemas"
+msgid "the following incidents or issues"
+msgstr ""
-msgid "the following issue(s)"
-msgstr "la siguiente incidencia(s)"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr ""
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "Colapsar/Expandir"
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "disparado"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 09a71424128..5ece8fd290c 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 16f80372ced..33d40ab8f70 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 9d391b685bf..93f5adc9513 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 644c759f8b0..9d50bc223d1 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-07-14 17:15\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index fb60dea983b..058e600554b 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr " %{start} à %{end}"
@@ -460,6 +460,9 @@ msgstr "%{actionText} et réouvrir %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} est une plage d'adresses IP non valide"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} a cloné %{original_issue} vers %{new_issue}."
@@ -508,10 +511,10 @@ msgstr "%{commit_author_link} a écrit %{commit_authored_timeago} et %{commit_co
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} poids complété"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} tâche terminée sur %{count}"
-msgstr[1] "%{completedCount} tâches terminées sur %{count}"
+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 "%{completedWeight} sur %{totalWeight} du poids complété"
@@ -691,6 +694,9 @@ msgstr "Les %{integrations_link_start}Intégrations%{link_end} vous permettent d
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 ""
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(s) déjà assigné(s)"
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Méthode :%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Espace de noms :%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Scanner :%{labelEnd} %{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Gravité :%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Outil :%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Réponse non modifiée :%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponible"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 heure"
@@ -876,6 +885,18 @@ msgstr "%{openedEpics} ouvertes, %{closedEpics} fermées"
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 ""
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed} %% utilisé(s)"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "Le résultat de %{securityScanner} n’est pas disponible, car aucun pipeline n’a pas été exécuté depuis son activation. %{linkStart}Exécuter un pipeline%{linkEnd}"
msgstr[1] "Les résultats de %{securityScanner} ne sont pas disponibles, car aucun pipeline n’a pas été exécuté depuis son activation. %{linkStart}Exécuter un pipeline%{linkEnd}"
+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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "Authentification à deux facteurs"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Ajouter une liste à puces"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,14 +2175,11 @@ msgstr ""
msgid "Add a table"
msgstr "Ajouter un tableau"
-msgid "Add a task list"
-msgstr "Ajouter une liste de tâches"
-
msgid "Add a title..."
msgstr "Ajouter un titre..."
msgid "Add a to do"
-msgstr ""
+msgstr "Ajouter une tâche"
msgid "Add an SSH key"
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 "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"
@@ -3345,7 +3364,7 @@ msgid "Advanced"
msgstr ""
msgid "Advanced Search"
-msgstr ""
+msgstr "Recherche avancée"
msgid "Advanced Settings"
msgstr ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr "Toutes les modifications sont validées"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -4906,7 +4952,7 @@ msgid "Are you sure you want to attempt to merge?"
msgstr ""
msgid "Are you sure you want to cancel editing this %{commentType}?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir annuler la modification de ce %{commentType} ?"
msgid "Are you sure you want to close this blocked issue?"
msgstr ""
@@ -5142,10 +5188,10 @@ msgid "Assign to"
msgstr "Assigner à"
msgid "Assign to commenting user"
-msgstr ""
+msgstr "Assigner à l'utilisateur qui commente"
msgid "Assign to me"
-msgstr ""
+msgstr "Me l'assigner"
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr "Assigné à moi"
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
-msgstr "Joindre un fichier"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr "Ajout du fichier en pièce-jointe - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Événements d’audit"
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "août"
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6324,7 +6393,7 @@ msgid "BoardNewIssue|Projects"
msgstr ""
msgid "BoardNewIssue|Search projects"
-msgstr ""
+msgstr "Rechercher des projets"
msgid "BoardNewIssue|Select a project"
msgstr ""
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branches"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Active"
@@ -7196,9 +7307,6 @@ msgstr "Impossible de trouver le dernier commit (HEAD) pour cette branche"
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8265,7 +8370,7 @@ msgid "Closed MRs"
msgstr ""
msgid "Closed date"
-msgstr ""
+msgstr "Date de fermeture"
msgid "Closed issues"
msgstr "Tickets clos"
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -9712,7 +9832,7 @@ msgid "Configure the %{link} integration."
msgstr "Configurez l’intégration de %{link}."
msgid "Configure the default first day of the week and time tracking units."
-msgstr ""
+msgstr "Configurer le premier jour par défaut de la semaine et les unités de suivi du temps."
msgid "Configure the way a user creates a new account."
msgstr "Configurez la manière dont une personne crée un nouveau compte."
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Créer un nouveau dossier"
@@ -11008,16 +11122,16 @@ msgid "Created"
msgstr "Créé"
msgid "Created %{epicTimeagoDate}"
-msgstr ""
+msgstr "Créée %{epicTimeagoDate}"
msgid "Created %{timestamp}"
-msgstr ""
+msgstr "Créé %{timestamp}"
msgid "Created At"
msgstr "Créé à"
msgid "Created On"
-msgstr ""
+msgstr "Créé le"
msgid "Created a branch and a merge request to resolve this issue."
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12167,7 +12308,7 @@ msgid "Default description template for merge requests"
msgstr ""
msgid "Default first day of the week"
-msgstr ""
+msgstr "Premier jour de la semaine par défaut"
msgid "Default first day of the week in calendars and date pickers."
msgstr ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Déploiement"
msgstr[1] "Déploiements"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Clefs de déploiement"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Domaine"
@@ -13706,7 +13862,7 @@ msgid "Don't show again"
msgstr "Ne plus afficher"
msgid "Done"
-msgstr "Effectué"
+msgstr "Terminé"
msgid "Dormant users"
msgstr ""
@@ -13901,7 +14057,7 @@ msgid "Edit %{profileType} profile"
msgstr ""
msgid "Edit Comment"
-msgstr ""
+msgstr "Modifier le commentaire"
msgid "Edit Deploy Key"
msgstr ""
@@ -13949,7 +14105,7 @@ msgid "Edit audio description"
msgstr ""
msgid "Edit comment"
-msgstr ""
+msgstr "Modifier le commentaire"
msgid "Edit commit message"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "Courriel"
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Impossible de supprimer le miroir."
msgid "Failed to remove the pipeline schedule"
msgstr "Échec de la suppression du pipeline programmé"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ msgstr "Impossible d'enregistrer les préférences (%{error_message})."
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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "févr."
msgid "February"
msgstr "février"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16318,7 +16471,7 @@ msgid "Filter by merge requests that are currently merged."
msgstr ""
msgid "Filter by milestone"
-msgstr ""
+msgstr "Filtrer par jalon"
msgid "Filter by milestone name"
msgstr "Filtrer par nom de jalon"
@@ -16402,7 +16555,7 @@ msgid "First Seen"
msgstr ""
msgid "First day of the week"
-msgstr ""
+msgstr "Premier jour de la semaine"
msgid "First name"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16639,7 +16797,7 @@ msgid "Frequency"
msgstr ""
msgid "Frequently searched"
-msgstr ""
+msgstr "Fréquemment recherché"
msgid "Friday"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "Depuis la création du ticket jusqu’au déploiement en production"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr "Synchronisé"
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Pas encore synchronisé"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "État inconnu"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "Mis à jour %{timeAgo}"
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17729,7 +17900,7 @@ msgid "Global notification settings"
msgstr ""
msgid "GlobalSearch| %{search} %{description} %{scope}"
-msgstr ""
+msgstr " %{search} %{description} %{scope}"
msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
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."
@@ -17753,7 +17924,7 @@ msgid "GlobalSearch|Merge requests that I'm a reviewer"
msgstr "Demandes de fusion dont je suis un relecteur"
msgid "GlobalSearch|Projects"
-msgstr ""
+msgstr "Projets"
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."
@@ -17777,22 +17948,22 @@ msgid "GlobalSearch|Type for new suggestions to appear below."
msgstr "Écrivez pour faire apparaître de nouvelles suggestions ci-dessous"
msgid "GlobalSearch|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
-msgstr ""
+msgstr "Utilisez le raccourci-clavier %{kbdOpen}/%{kbdClose} pour lancer une recherche"
msgid "GlobalSearch|What are you searching for?"
msgstr "Que recherchez-vous ?"
msgid "GlobalSearch|all GitLab"
-msgstr ""
+msgstr "tout GitLab"
msgid "GlobalSearch|group"
-msgstr ""
+msgstr "groupe"
msgid "GlobalSearch|in %{scope}"
msgstr ""
msgid "GlobalSearch|project"
-msgstr ""
+msgstr "projet"
msgid "Globally-allowed IP ranges"
msgstr ""
@@ -17813,7 +17984,7 @@ msgid "Go back to configuration"
msgstr ""
msgid "Go full screen"
-msgstr ""
+msgstr "Plein écran"
msgid "Go to %{source_name}"
msgstr ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accÃ
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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Historique"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21686,7 +21830,7 @@ msgid "IssueAnalytics|Issue"
msgstr ""
msgid "IssueAnalytics|Milestone"
-msgstr ""
+msgstr "Jalon"
msgid "IssueAnalytics|Status"
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22472,7 +22646,7 @@ msgid "Job|Manual"
msgstr ""
msgid "Job|No search results found"
-msgstr ""
+msgstr "Aucun résultat de recherche trouvé"
msgid "Job|Passed"
msgstr ""
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Faire défiler vers le bas"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Faire défiler vers le haut"
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22786,7 +22963,7 @@ msgid "Labels|Promoting %{labelTitle} will make it available for all projects in
msgstr ""
msgid "Language"
-msgstr ""
+msgstr "Langue"
msgid "Language type"
msgstr ""
@@ -22851,7 +23028,7 @@ msgid "Last edited %{date}"
msgstr "Dernière modification le %{date}"
msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
-msgstr ""
+msgstr "Dernière modification par %{link_start}%{avatar} %{name}%{link_end}"
msgid "Last event"
msgstr ""
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,8 +23621,11 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Tickets liés"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr ""
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23541,7 +23757,7 @@ msgid "Loading…"
msgstr ""
msgid "Localization"
-msgstr ""
+msgstr "Localisation"
msgid "Location"
msgstr ""
@@ -23757,7 +23973,7 @@ msgid "Manage members"
msgstr ""
msgid "Manage milestones"
-msgstr ""
+msgstr "Gérer les jalons"
msgid "Manage project labels"
msgstr "Gérer les étiquettes de projet"
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr "Manuel"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23808,7 +24021,7 @@ msgid "March"
msgstr "mars"
msgid "Mark as done"
-msgstr "Marquer comme fait"
+msgstr "Marquer comme terminé"
msgid "Mark as draft"
msgstr ""
@@ -23823,7 +24036,7 @@ msgid "Mark this issue as related to another issue"
msgstr ""
msgid "Mark to do as done"
-msgstr "Marquer comme fait"
+msgstr "Marquer une tâche comme terminé"
msgid "Markdown Help"
msgstr ""
@@ -23841,16 +24054,16 @@ msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
msgstr ""
msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
-msgstr ""
+msgstr "Ajouter du texte en gras (%{modifierKey}B)"
msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
-msgstr ""
+msgstr "Ajouter du texte en gras (%{modifier_key}B)"
msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
-msgstr ""
+msgstr "Ajouter du texte en italique (%{modifierKey}I)"
msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
-msgstr ""
+msgstr "Ajouter du texte en italique (%{modifier_key}I)"
msgid "MarkdownEditor|Add strikethrough text (%{modifierKey}⇧X)"
msgstr ""
@@ -23883,7 +24096,7 @@ msgid "Marked this issue as related to %{issue_ref}."
msgstr ""
msgid "Marked to do as done."
-msgstr "Marqué comme fait."
+msgstr "Marqué comme terminé."
msgid "Marks this %{noun} as a draft."
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25079,22 +25292,22 @@ msgid "MilestoneCombobox|Group milestones"
msgstr ""
msgid "MilestoneCombobox|Milestone"
-msgstr ""
+msgstr "Jalon"
msgid "MilestoneCombobox|No matching results"
msgstr ""
msgid "MilestoneCombobox|No milestone"
-msgstr ""
+msgstr "Aucun jalon"
msgid "MilestoneCombobox|Project milestones"
-msgstr ""
+msgstr "Jalons du projet"
msgid "MilestoneCombobox|Search Milestones"
-msgstr ""
+msgstr "Rechercher des jalons"
msgid "MilestoneCombobox|Select milestone"
-msgstr ""
+msgstr "Sélectionner le jalon"
msgid "MilestoneSidebar|Closed:"
msgstr "Fermé:"
@@ -25112,7 +25325,7 @@ msgid "MilestoneSidebar|From"
msgstr ""
msgid "MilestoneSidebar|Issues"
-msgstr ""
+msgstr "Tickets"
msgid "MilestoneSidebar|Merge requests"
msgstr ""
@@ -25121,10 +25334,10 @@ msgid "MilestoneSidebar|Merged:"
msgstr ""
msgid "MilestoneSidebar|New Issue"
-msgstr ""
+msgstr "Nouveau ticket"
msgid "MilestoneSidebar|New issue"
-msgstr ""
+msgstr "Nouveau ticket"
msgid "MilestoneSidebar|No due date"
msgstr "Aucune date d'échéance"
@@ -25193,7 +25406,7 @@ msgid "Milestones|Organize issues and merge requests into a cohesive group, and
msgstr ""
msgid "Milestones|Project Milestone"
-msgstr ""
+msgstr "Jalon du projet"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
msgstr "Promouvoir %{milestoneTitle} en tant que jalon de groupe ?"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr "Se déconnecter et se reconnecter avec un autre compte"
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25824,7 +26028,7 @@ msgid "New merge request"
msgstr "Nouvelle demande de fusion"
msgid "New milestone"
-msgstr ""
+msgstr "Nouveau jalon"
msgid "New name"
msgstr ""
@@ -25934,11 +26138,14 @@ 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 ""
+msgstr "Aucun jalon"
msgid "No Scopes"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr "Aucune personne assignée"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26124,7 +26328,7 @@ msgid "No messages were logged"
msgstr "Aucun message n’a été enregistré"
msgid "No milestone"
-msgstr ""
+msgstr "Aucun jalon"
msgid "No namespace"
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26366,7 +26567,7 @@ msgid "Notes|Internal notes are only visible to the author, assignees, and membe
msgstr ""
msgid "Notes|Last reply by %{name}"
-msgstr ""
+msgstr "Dernière réponse apportée par %{name}"
msgid "Notes|Make this an internal note"
msgstr "Rendre ce commentaire interne"
@@ -26389,9 +26590,12 @@ msgstr ""
msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
msgstr ""
-msgid "Nothing to preview."
+msgid "Note|The created date provided is too far in the past."
msgstr ""
+msgid "Nothing to preview."
+msgstr "Rien à prévisualiser."
+
msgid "Notification events"
msgstr "Événement de notifications"
@@ -26526,6 +26730,15 @@ msgstr "Le ticket de %{author_link} arrive bientôt à échéance %{issue_refere
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} dans %{mr_link}"
+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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "L'assignation est passée de %{fromNames} à %{toNames}"
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 "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."
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "Optimisation des performances"
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Prochaine exécution"
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 ""
+
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Indiquez une courte description"
@@ -28399,6 +28690,9 @@ msgstr "Cible"
msgid "PipelineSchedules|Variables"
msgstr "Variables"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Réinitialisation du cache de projet réussie."
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr "Variables"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29267,13 +29600,13 @@ msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the color of GitLab."
-msgstr ""
+msgstr "Personnaliser les couleurs de GitLab."
msgid "Preferences|Customize the colors of removed and added lines in diffs."
-msgstr ""
+msgstr "Personnaliser les couleurs de l'affichage des diffs."
msgid "Preferences|Diff colors"
-msgstr ""
+msgstr "Couleurs des diff"
msgid "Preferences|Display time in 24-hour format"
msgstr "Afficher l'heure au format 24 heures"
@@ -29330,7 +29663,7 @@ msgid "Preferences|Surround text selection when typing quotes or brackets"
msgstr ""
msgid "Preferences|Syntax highlighting theme"
-msgstr ""
+msgstr "Thème de coloration syntaxique"
msgid "Preferences|Tab width"
msgstr ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29765,7 +30098,7 @@ msgid "Profiles|Pronunciation"
msgstr ""
msgid "Profiles|Public avatar"
-msgstr ""
+msgstr "Avatar public"
msgid "Profiles|Public email"
msgstr ""
@@ -30050,7 +30383,7 @@ msgid "Project members"
msgstr ""
msgid "Project milestone"
-msgstr ""
+msgstr "Jalon du projet"
msgid "Project name"
msgstr "Nom du projet"
@@ -30076,6 +30409,9 @@ msgstr "Identifiant « slug » du projet"
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 ""
@@ -30085,6 +30421,12 @@ 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 "S’abonner"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
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 specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Autorisé à déployer"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Environnement"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+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 "Protéger"
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31832,11 +32201,14 @@ msgid "Recent searches"
msgstr "Recherches récentes"
msgid "Recently used"
-msgstr ""
+msgstr "Récemment utilisé"
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Supprimer l’avatar"
@@ -32306,12 +32675,6 @@ msgstr "Tous les labels ont été supprimés."
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "Un groupe supprimé ne peut être restauré !"
@@ -32360,9 +32723,6 @@ msgstr "Supprime toutes les étiquettes."
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32454,7 +32814,7 @@ msgid "Replication"
msgstr ""
msgid "Reply"
-msgstr ""
+msgstr "Répondre"
msgid "Reply by email"
msgstr ""
@@ -32463,7 +32823,7 @@ msgid "Reply internally"
msgstr ""
msgid "Reply to comment"
-msgstr ""
+msgstr "Répondre au commentaire"
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
@@ -32471,6 +32831,9 @@ msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Signaler un abus"
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr "Vulnérabilité"
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "aucun résultat de test modifié"
@@ -32833,15 +33202,6 @@ msgstr "Demander l’accès"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr "Réessayer"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr "Feuille de route"
@@ -33291,6 +33636,11 @@ msgstr ""
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] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "En cours d’exécution"
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ msgstr "Clefs SSH"
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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] ""
msgstr[1] ""
+msgid "SearchToken|Assignee"
+msgstr "Assigné"
+
+msgid "SearchToken|Reviewer"
+msgstr "Relecteur"
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr "Tableau de bord de sécurité"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -34998,7 +35426,7 @@ msgid "SecurityReports|Severity"
msgstr ""
msgid "SecurityReports|Show %{pageSize} items"
-msgstr ""
+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 ""
@@ -35157,7 +35585,7 @@ msgid "Select a label"
msgstr "Sélectionnez une étiquette"
msgid "Select a milestone"
-msgstr ""
+msgstr "Sélectionner un jalon"
msgid "Select a new namespace"
msgstr ""
@@ -35208,7 +35636,7 @@ msgid "Select branches"
msgstr ""
msgid "Select due date"
-msgstr ""
+msgstr "Sélectionner la date d'échéance"
msgid "Select epic"
msgstr ""
@@ -35235,7 +35663,7 @@ msgid "Select merge moment"
msgstr ""
msgid "Select milestone"
-msgstr ""
+msgstr "Sélectionner un jalon"
msgid "Select private project"
msgstr ""
@@ -35247,7 +35675,7 @@ msgid "Select project to create %{type}"
msgstr ""
msgid "Select project to create issue"
-msgstr "Sélectionnez un projet pour créer un ticket"
+msgstr "Sélectionner un projet pour créer un ticket"
msgid "Select projects"
msgstr ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
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 access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr "Restrictions de connexion"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr "Métriques du système (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr "Annuler"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Créer l’étiquette"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Modifier les notes de version"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Branche, étiquette ou condensat SHA d’un commit"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ msgstr "Ce répertoire"
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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Ce dépôt"
@@ -40229,6 +40651,9 @@ 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 "Délai d’attente"
@@ -40270,7 +40695,7 @@ msgid "Title"
msgstr "Titre"
msgid "Title (required)"
-msgstr ""
+msgstr "Titre (obligatoire)"
msgid "Title:"
msgstr ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40480,7 +40902,7 @@ msgid "To-Do"
msgstr ""
msgid "To-Do List"
-msgstr ""
+msgstr "Liste de tâches"
msgid "To-do item successfully marked as done."
msgstr ""
@@ -40510,7 +40932,7 @@ msgid "Todos|Mark all as done"
msgstr "Tout marquer comme terminé"
msgid "Todos|Nothing is on your to-do list. Nice work!"
-msgstr ""
+msgstr "Il n'y a rien sur votre liste de tâches. Beau travail !"
msgid "Todos|Undo mark all as done"
msgstr "Annuler tout marquer comme fait"
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Type"
+msgid "Type to search"
+msgstr "Tapez pour rechercher"
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ msgstr "Impossible de charger le diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
+msgid "Unable to parse JSON"
+msgstr ""
+
msgid "Unable to parse the vulnerability report's options."
msgstr ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41365,7 +41799,7 @@ msgid "Update Scheduled…"
msgstr ""
msgid "Update all"
-msgstr ""
+msgstr "Tout mettre à jour"
msgid "Update appearance settings"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr "Date de mise à jour"
msgid "Updating"
msgstr "Mise à jour en cours"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Téléverser un fichier"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr "Votes positifs"
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 "Utilisé par les membres pour se connecter à votre groupe dans GitLab"
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "A contribué aux projets"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "Modifier le profil"
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Tout afficher"
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -42524,6 +42985,12 @@ msgstr ""
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 ""
+
+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 ""
@@ -42540,7 +43007,7 @@ msgid "VersionCheck|Update available"
msgstr ""
msgid "VersionCheck|Your GitLab Version"
-msgstr ""
+msgstr "Votre Version de GitLab"
msgid "View Stage: %{title}"
msgstr ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,9 +44332,12 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
-msgid "WorkItem|Closed"
+msgid "WorkItem|Child removed"
msgstr ""
+msgid "WorkItem|Closed"
+msgstr "Fermé"
+
msgid "WorkItem|Collapse child items"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43906,7 +44432,7 @@ msgid "Write"
msgstr "Rédiger"
msgid "Write a comment or drag your files here…"
-msgstr ""
+msgstr "Rédigez un commentaire ou faites glisser vos fichiers ici…"
msgid "Write a comment…"
msgstr "Écrire un commentaire…"
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ msgstr "Vous pouvez tester votre fichier « .gitlab-ci.yml » avec %{linkStart
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
@@ -44624,7 +45142,7 @@ msgid "You're receiving this email because you have been assigned an item on %{h
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}"
msgid "You're receiving this email because you have been mentioned on %{host}."
-msgstr ""
+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 ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44720,7 +45238,7 @@ msgid "Your SSH keys (%{count})"
msgstr ""
msgid "Your To-Do List"
-msgstr ""
+msgstr "Votre liste de tâches"
msgid "Your U2F device did not send a valid JSON response."
msgstr ""
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 "Vos groupes"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr "%{reportType} : le chargement a généré une erreur"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,11 +46116,14 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
msgid "closed %{timeago}"
-msgstr ""
+msgstr "fermé %{timeago}"
msgid "closed issue"
msgstr "ticket fermé"
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr "https://votre-serveur-bitbucket"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Les statistiques de déploiement ne sont pas disponibles pour le moment"
@@ -46229,9 +46767,6 @@ msgstr "N’a pas résolu"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Impossible de charger les statistiques de déploiement"
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "Fusionner"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Fusionnée par"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Les modifications ont été fusionnées dans"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Les modifications n’ont pas été fusionnées dans"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e51f434bb55..b86d02d5627 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -22,6 +22,11 @@ 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 ""
@@ -398,11 +403,6 @@ msgid_plural "%d tags per image name"
msgstr[0] ""
msgstr[1] ""
-msgid "%d unassigned issue"
-msgid_plural "%d unassigned issues"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
msgstr[0] ""
@@ -460,9 +460,6 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
-msgid "%{attribute} must be between %{min} and %{max}"
-msgstr ""
-
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -511,8 +508,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -694,6 +691,9 @@ 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 ""
@@ -745,6 +745,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -766,9 +769,6 @@ msgstr ""
msgid "%{label_for_message} unavailable"
msgstr ""
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -882,6 +882,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -960,6 +972,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -998,8 +1020,10 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-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 ""
@@ -1242,11 +1266,6 @@ msgstr ""
msgid "(revoked)"
msgstr ""
-msgid "(squashes %d commit)"
-msgid_plural "(squashes %d commits)"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "(this user)"
msgstr ""
@@ -1505,15 +1524,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1541,9 +1554,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2120,6 +2130,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2132,7 +2145,7 @@ 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 in group and project CI/CD settings, in the Runners section. Markdown is supported."
+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}."
@@ -2159,9 +2172,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2189,9 +2199,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2237,6 +2244,9 @@ 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 ""
@@ -3962,6 +3972,9 @@ 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 ""
@@ -4055,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4103,6 +4113,9 @@ 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 ""
@@ -4190,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4797,6 +4807,9 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
+msgid "ApprovalSettings|Keep approvals"
+msgstr ""
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
@@ -4815,7 +4828,10 @@ msgstr ""
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr ""
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
+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"
@@ -4833,6 +4849,9 @@ 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 ""
@@ -4860,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5204,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5248,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5262,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5322,19 +5329,36 @@ 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 stream"
+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."
@@ -5346,10 +5370,13 @@ 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"
+msgid "AuditStreams|Custom HTTP headers (optional)"
msgstr ""
msgid "AuditStreams|Delete %{link}"
@@ -5370,13 +5397,22 @@ 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 count icon"
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
msgstr ""
msgid "AuditStreams|Streams"
@@ -5610,7 +5646,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6153,6 +6189,9 @@ 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 ""
@@ -6246,17 +6285,13 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr ""
-
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6273,6 +6308,9 @@ 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 ""
@@ -6288,13 +6326,7 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6627,9 +6659,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7040,21 +7114,12 @@ msgstr ""
msgid "CICDAnalytics|Releases"
msgstr ""
-msgid "CICDAnalytics|Shared Runners Usage"
-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|Shared runner usage"
-msgstr ""
-
-msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
-msgstr ""
-
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
msgstr ""
@@ -7064,9 +7129,6 @@ msgstr ""
msgid "CICDAnalytics|What is shared runner duration?"
msgstr ""
-msgid "CICDAnalytics|What is shared runner usage?"
-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 ""
@@ -7238,9 +7300,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7929,9 +7988,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -10272,9 +10328,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -11163,6 +11216,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11454,6 +11510,9 @@ 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 ""
@@ -11478,6 +11537,9 @@ 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 ""
@@ -11487,11 +11549,20 @@ 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 ""
@@ -11555,6 +11626,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11570,6 +11644,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11615,6 +11692,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11651,9 +11731,21 @@ 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 ""
@@ -12349,6 +12441,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12469,9 +12564,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12679,6 +12771,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12934,7 +13029,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13735,9 +13830,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13837,6 +13929,9 @@ 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 ""
@@ -14467,9 +14562,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14968,6 +15060,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15943,22 +16038,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15976,6 +16068,9 @@ 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 ""
@@ -16021,9 +16116,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16686,6 +16778,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16710,11 +16807,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-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 June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16773,6 +16874,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16822,6 +16926,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16996,9 +17103,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17056,9 +17160,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17314,9 +17415,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17500,6 +17598,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17617,6 +17718,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17668,6 +17772,9 @@ 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 ""
@@ -17680,6 +17787,9 @@ 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 ""
@@ -17692,6 +17802,9 @@ 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 ""
@@ -18118,9 +18231,6 @@ msgstr ""
msgid "Group"
msgstr ""
-msgid "Group \"%{group_name}\" was successfully updated."
-msgstr ""
-
msgid "Group %{group_name} couldn't be exported."
msgstr ""
@@ -18238,9 +18348,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18394,7 +18501,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18559,7 +18666,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18607,6 +18714,9 @@ 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 ""
@@ -18619,15 +18729,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18646,9 +18750,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18673,15 +18774,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18799,6 +18894,9 @@ 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 ""
@@ -18817,6 +18915,9 @@ 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 ""
@@ -18862,6 +18963,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18940,6 +19044,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18958,7 +19071,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19290,6 +19403,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19332,9 +19448,6 @@ msgstr ""
msgid "How do I configure Akismet?"
msgstr ""
-msgid "How do I configure runners?"
-msgstr ""
-
msgid "How do I configure this integration?"
msgstr ""
@@ -19359,6 +19472,9 @@ 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 ""
@@ -19542,6 +19658,9 @@ 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 ""
@@ -19851,6 +19970,9 @@ 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 ""
@@ -20844,6 +20966,9 @@ 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 ""
@@ -21377,7 +21502,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21440,6 +21565,12 @@ 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 ""
@@ -21454,7 +21585,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21469,9 +21600,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21607,12 +21735,18 @@ msgstr ""
msgid "Is using seat"
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 ""
@@ -21877,6 +22011,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21892,15 +22029,36 @@ 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 ""
@@ -21961,9 +22119,6 @@ msgstr ""
msgid "Iterations|Error loading iteration cadences."
msgstr ""
-msgid "Iterations|First iteration start date"
-msgstr ""
-
msgid "Iterations|Iteration cadences"
msgstr ""
@@ -22027,13 +22182,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22519,6 +22674,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22642,7 +22800,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22794,7 +22952,7 @@ 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."
+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:"
@@ -22910,15 +23068,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23474,7 +23626,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23495,18 +23650,39 @@ 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|Read more about linked resources"
+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 ""
@@ -23834,9 +24010,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24098,7 +24271,7 @@ 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_whitelist}."
+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"
@@ -25492,12 +25665,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25522,7 +25689,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25707,9 +25874,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26012,9 +26176,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26314,9 +26475,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26577,6 +26735,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26742,6 +26909,11 @@ 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 track"
msgstr ""
@@ -27215,9 +27387,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27311,6 +27480,9 @@ 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 ""
@@ -27632,6 +27804,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27641,6 +27818,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27737,6 +27917,9 @@ msgstr ""
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27751,6 +27934,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27808,6 +27994,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27868,12 +28057,20 @@ msgstr ""
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, 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 ""
@@ -28237,6 +28434,18 @@ 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 ""
@@ -28471,6 +28680,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28483,6 +28695,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28954,6 +29169,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29011,6 +29229,9 @@ 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 ""
@@ -29125,6 +29346,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29227,6 +29451,9 @@ 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 ""
@@ -30199,6 +30426,12 @@ 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 ""
@@ -30277,6 +30510,9 @@ 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 ""
@@ -30289,6 +30525,9 @@ 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 ""
@@ -30316,6 +30555,9 @@ 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 ""
@@ -30523,6 +30765,9 @@ msgstr ""
msgid "ProjectSettings|Encourage"
msgstr ""
+msgid "ProjectSettings|Environments"
+msgstr ""
+
msgid "ProjectSettings|Every merge creates a merge commit."
msgstr ""
@@ -30535,6 +30780,9 @@ 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 ""
@@ -31504,18 +31752,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31642,6 +31908,12 @@ 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 ""
@@ -31807,9 +32079,6 @@ msgstr ""
msgid "Quick range"
msgstr ""
-msgid "Quickly and easily edit multiple files in your project."
-msgstr ""
-
msgid "Quota of CI/CD minutes"
msgstr ""
@@ -32118,9 +32387,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32276,12 +32542,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32423,12 +32683,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32477,9 +32731,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32588,6 +32839,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32600,6 +32854,9 @@ 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 ""
@@ -32757,6 +33014,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32950,15 +33210,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32983,24 +33234,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33077,6 +33316,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33221,10 +33463,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33327,12 +33569,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33408,6 +33644,11 @@ 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 ""
@@ -33630,6 +33871,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33764,6 +34008,9 @@ 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 ""
@@ -33823,6 +34070,9 @@ 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|Up to date"
msgstr ""
@@ -33877,6 +34127,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33892,6 +34145,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33907,6 +34163,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33949,6 +34208,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33958,6 +34220,9 @@ 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 ""
@@ -34036,6 +34301,24 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require a %{scan} scan to run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34355,6 +34638,12 @@ 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 ""
@@ -34415,6 +34704,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34607,6 +34899,9 @@ msgstr ""
msgid "SecurityOrchestration|Actions"
msgstr ""
+msgid "SecurityOrchestration|Add action"
+msgstr ""
+
msgid "SecurityOrchestration|Add rule"
msgstr ""
@@ -34688,6 +34983,12 @@ 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 ""
@@ -35030,6 +35331,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35084,6 +35388,15 @@ 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 ""
@@ -35438,9 +35751,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35639,9 +35949,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36126,10 +36433,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} label for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr ""
-
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36465,9 +36769,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37008,9 +37309,6 @@ msgstr ""
msgid "Standard"
msgstr ""
-msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
-msgstr ""
-
msgid "Star labels to start sorting by priority"
msgstr ""
@@ -38129,9 +38427,6 @@ msgstr ""
msgid "TagsPage|Edit release"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr ""
-
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr ""
@@ -38924,9 +39219,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39086,6 +39378,9 @@ 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 ""
@@ -39200,6 +39495,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39272,6 +39570,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39374,9 +39675,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39455,9 +39753,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39509,9 +39804,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39656,7 +39948,7 @@ msgstr ""
msgid "This commit was signed with a different user's verified signature."
msgstr ""
-msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
+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."
@@ -39692,6 +39984,9 @@ 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 ""
@@ -40049,6 +40344,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40361,6 +40662,9 @@ 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 ""
@@ -40443,9 +40747,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40521,7 +40822,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40755,6 +41056,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41148,6 +41452,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41268,6 +41575,9 @@ 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 ""
@@ -41331,6 +41641,9 @@ 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 ""
@@ -41568,9 +41881,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41598,6 +41908,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41682,10 +41995,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41757,6 +42070,9 @@ 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 ""
@@ -41784,6 +42100,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42152,6 +42480,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42512,11 +42843,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42571,10 +42897,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42664,6 +42996,12 @@ 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 ""
@@ -43273,6 +43611,9 @@ 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 ""
@@ -43318,9 +43659,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43330,6 +43668,9 @@ 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 ""
@@ -43390,6 +43731,12 @@ 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 ""
@@ -43630,9 +43977,18 @@ 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 ""
@@ -43689,6 +44045,11 @@ 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 ""
@@ -43725,6 +44086,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43851,12 +44218,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43962,6 +44323,9 @@ msgstr ""
msgid "WorkItem|Add a task"
msgstr ""
+msgid "WorkItem|Add a title"
+msgstr ""
+
msgid "WorkItem|Add assignee"
msgstr ""
@@ -44009,21 +44373,36 @@ msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Incident"
+msgstr ""
+
msgid "WorkItem|Introducing tasks"
msgstr ""
+msgid "WorkItem|Issue"
+msgstr ""
+
msgid "WorkItem|Learn about tasks"
msgstr ""
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
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 ""
@@ -44039,6 +44418,9 @@ msgstr ""
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
+msgid "WorkItem|Something went wrong when fetching the items list. Please refresh this page."
+msgstr ""
+
msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
msgstr ""
@@ -44048,12 +44430,27 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task"
+msgstr ""
+
msgid "WorkItem|Task deleted"
msgstr ""
+msgid "WorkItem|Test case"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
@@ -44290,6 +44687,11 @@ 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 ""
@@ -44350,8 +44752,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44359,9 +44763,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44416,7 +44817,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44428,9 +44829,6 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
@@ -44464,8 +44862,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44799,6 +45199,9 @@ 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 ""
@@ -44811,9 +45214,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44826,7 +45226,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44847,6 +45247,12 @@ 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 ""
@@ -45000,6 +45406,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -45119,10 +45535,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45275,6 +45689,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45355,6 +45772,9 @@ 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 ""
@@ -45456,9 +45876,15 @@ 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 ""
@@ -45474,6 +45900,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45742,6 +46171,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45769,6 +46201,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45808,9 +46243,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45905,6 +46337,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45987,9 +46422,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46040,6 +46472,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46216,6 +46651,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46235,7 +46673,7 @@ msgid_plural "merge requests"
msgstr[0] ""
msgstr[1] ""
-msgid "mergedCommitsAdded|(commits were squashed)"
+msgid "mergedCommitsAdded| (commits were squashed)"
msgstr ""
msgid "metric_id must be unique across a project"
@@ -46256,13 +46694,7 @@ msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit"
msgstr ""
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
@@ -46381,9 +46813,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46393,9 +46822,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46431,9 +46857,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46467,9 +46890,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46554,21 +46974,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46885,6 +47293,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46897,6 +47308,9 @@ msgstr ""
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 ""
@@ -47008,13 +47422,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47035,6 +47449,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 011ed0c06ea..cac341bddcf 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr " %{start} a %{end}"
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 763a6fed51f..c6071a9b352 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -664,8 +667,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -859,6 +862,9 @@ 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 ""
@@ -910,6 +916,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -922,13 +931,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1046,6 +1055,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr "×ימות דו־שלבי"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 ימי×"
-
msgid "3 hours"
msgstr "3 שעות"
-msgid "30 days"
-msgstr "30 ימי×"
-
msgid "30 minutes"
msgstr "חצי שעה"
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 ימי×"
-
msgid "8 hours"
msgstr "8 שעות"
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr "הוספת טבלה"
-msgid "Add a task list"
-msgstr "הוספת רשימת משימות"
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr ""
msgid "Add approvers"
msgstr "הוספת מ×שרי×"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2481,6 +2501,9 @@ 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 ""
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 758f11ef1b4..cf8a3e8806b 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-07-14 17:11\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index c50d35140ef..ac59f344271 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -535,6 +535,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -586,8 +589,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -775,6 +778,9 @@ 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 ""
@@ -826,6 +832,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -838,13 +847,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -961,6 +970,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1042,6 +1063,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1081,9 +1114,6 @@ msgstr[2] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1624,15 +1654,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1660,9 +1684,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2239,6 +2260,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2278,9 +2302,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2308,9 +2329,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2356,6 +2374,9 @@ 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 ""
@@ -3880,6 +3901,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4171,9 +4195,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4219,6 +4240,9 @@ 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 ""
@@ -4306,9 +4330,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4714,13 +4735,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4747,6 +4780,18 @@ 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 ""
@@ -4897,28 +4942,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4936,6 +4984,9 @@ 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 ""
@@ -4963,9 +5014,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5308,9 +5356,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5353,7 +5398,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5368,12 +5413,6 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5434,6 +5473,12 @@ 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 ""
@@ -5452,6 +5497,9 @@ 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 ""
@@ -5467,18 +5515,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5491,6 +5554,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5707,7 +5773,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5896,6 +5962,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6247,6 +6316,9 @@ 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 ""
@@ -6340,17 +6412,17 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
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 ""
@@ -6367,6 +6439,9 @@ 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 ""
@@ -6382,13 +6457,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6724,9 +6796,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7336,9 +7450,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8029,9 +8140,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8455,6 +8563,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8473,6 +8584,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8530,12 +8647,18 @@ 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 ""
@@ -10363,9 +10486,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10804,9 +10924,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11257,6 +11374,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11644,6 +11764,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11662,6 +11785,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11677,6 +11803,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11722,6 +11851,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11758,9 +11890,21 @@ 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 ""
@@ -12457,6 +12601,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12481,6 +12628,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12538,6 +12691,15 @@ 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 ""
@@ -12562,9 +12724,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12778,6 +12937,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13033,7 +13195,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13840,9 +14002,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14251,9 +14410,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14575,9 +14731,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15076,6 +15229,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16054,22 +16210,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16087,6 +16240,9 @@ 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 ""
@@ -16132,9 +16288,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16378,6 +16531,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16795,6 +16951,12 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16819,11 +16981,17 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16882,6 +17050,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16933,6 +17104,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17107,9 +17281,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17167,9 +17338,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17425,9 +17593,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17611,6 +17776,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17635,9 +17803,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17731,6 +17896,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17782,6 +17950,9 @@ 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 ""
@@ -17794,6 +17965,9 @@ 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 ""
@@ -17806,6 +17980,9 @@ 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 ""
@@ -18124,16 +18301,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18355,9 +18529,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18511,7 +18682,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18676,7 +18847,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18724,6 +18895,9 @@ 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 ""
@@ -18736,15 +18910,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18763,9 +18931,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18790,15 +18955,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18916,6 +19075,9 @@ 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 ""
@@ -18934,6 +19096,9 @@ 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 ""
@@ -18979,6 +19144,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19057,6 +19225,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19075,7 +19252,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19189,12 +19366,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19417,6 +19588,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19486,6 +19660,9 @@ 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 ""
@@ -19669,6 +19846,9 @@ 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 ""
@@ -19696,6 +19876,9 @@ 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 ""
@@ -19978,6 +20161,9 @@ msgstr[2] ""
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 ""
@@ -20023,9 +20209,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20083,9 +20266,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20128,9 +20308,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20140,18 +20317,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20170,9 +20341,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20341,9 +20509,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20416,9 +20581,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20491,12 +20653,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20512,9 +20668,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21538,7 +21691,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21616,7 +21769,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21631,9 +21784,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22039,6 +22189,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22054,12 +22207,36 @@ 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 ""
@@ -22081,6 +22258,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22111,10 +22291,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22123,6 +22303,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22150,9 +22333,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22180,13 +22360,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22672,6 +22852,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22795,7 +22978,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23065,15 +23248,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23356,19 +23533,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23635,7 +23812,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23647,6 +23827,48 @@ 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 ""
@@ -23974,9 +24196,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24238,7 +24457,7 @@ 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_whitelist}."
+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"
@@ -25636,12 +25855,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25666,7 +25879,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25852,9 +26065,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26125,6 +26335,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26155,9 +26368,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26458,9 +26668,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26581,6 +26788,9 @@ 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 ""
@@ -26722,6 +26932,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26887,6 +27106,12 @@ 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] ""
+msgstr[2] ""
+
msgid "On track"
msgstr ""
@@ -27361,9 +27586,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27457,6 +27679,9 @@ 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 ""
@@ -27778,6 +28003,12 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27787,6 +28018,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27796,6 +28030,9 @@ 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 ""
@@ -27853,6 +28090,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27871,9 +28111,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27889,6 +28135,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27946,6 +28195,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27997,18 +28249,30 @@ 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}, this operation is irreversible, 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[2] ""
+
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 ""
@@ -28264,6 +28528,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28369,6 +28636,18 @@ 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 ""
@@ -28525,6 +28804,9 @@ 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 ""
@@ -28543,6 +28825,15 @@ 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 ""
@@ -28564,6 +28855,12 @@ 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 ""
@@ -28585,6 +28882,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28597,6 +28897,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28843,6 +29146,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29011,9 +29317,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29026,12 +29341,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29050,6 +29371,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29086,6 +29410,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29101,6 +29431,9 @@ 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 ""
@@ -29113,6 +29446,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29212,6 +29548,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29314,6 +29653,9 @@ 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 ""
@@ -29560,7 +29902,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30274,6 +30616,9 @@ 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 ""
@@ -30283,6 +30628,12 @@ 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 ""
@@ -30361,6 +30712,9 @@ 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 ""
@@ -30373,6 +30727,9 @@ 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 ""
@@ -30400,6 +30757,9 @@ 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 ""
@@ -31588,18 +31948,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31726,6 +32104,12 @@ 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 ""
@@ -31996,12 +32380,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32035,6 +32413,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32206,9 +32587,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32224,6 +32602,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32296,6 +32677,9 @@ 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 ""
@@ -32359,12 +32743,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32506,12 +32884,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32560,9 +32932,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32671,6 +33040,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32683,6 +33055,9 @@ 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 ""
@@ -32845,6 +33220,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33040,15 +33418,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33073,24 +33442,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33169,6 +33526,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33313,10 +33673,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33421,12 +33781,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33502,6 +33856,12 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33559,6 +33919,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33724,6 +34087,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33748,6 +34114,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33856,6 +34225,9 @@ 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 ""
@@ -33916,9 +34288,18 @@ 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|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 ""
@@ -33964,6 +34345,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33979,6 +34363,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33994,6 +34381,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34036,6 +34426,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34045,6 +34438,9 @@ 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 ""
@@ -34123,6 +34519,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34453,6 +34864,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34513,6 +34930,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34786,6 +35206,12 @@ 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 ""
@@ -34951,6 +35377,9 @@ 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 group"
msgstr ""
@@ -34969,9 +35398,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35128,6 +35554,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35182,6 +35611,15 @@ 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 ""
@@ -35536,9 +35974,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35722,9 +36157,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35740,9 +36172,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36229,7 +36658,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36316,6 +36745,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36325,6 +36757,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36559,9 +36994,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37678,9 +38110,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38026,9 +38455,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38131,6 +38557,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38203,6 +38632,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38221,7 +38653,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38320,9 +38752,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38737,9 +39166,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39031,9 +39457,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39193,6 +39616,9 @@ 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 ""
@@ -39307,6 +39733,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39379,6 +39808,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39481,9 +39913,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39562,9 +39991,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39616,9 +40042,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39799,6 +40222,9 @@ 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 ""
@@ -40156,6 +40582,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40468,6 +40900,9 @@ 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 ""
@@ -40552,9 +40987,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40630,7 +41062,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40864,6 +41296,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41170,6 +41605,9 @@ 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 ""
@@ -41254,6 +41692,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41374,6 +41815,9 @@ 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 ""
@@ -41437,6 +41881,9 @@ 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 ""
@@ -41482,9 +41929,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41677,9 +42121,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41707,6 +42148,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41731,9 +42175,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41794,10 +42235,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41869,6 +42310,9 @@ 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 ""
@@ -41896,6 +42340,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42166,6 +42622,12 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42259,6 +42721,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42367,6 +42832,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42448,6 +42916,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42613,12 +43084,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42673,10 +43138,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42766,6 +43237,12 @@ 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 ""
@@ -43378,6 +43855,9 @@ 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 ""
@@ -43423,9 +43903,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43435,6 +43912,9 @@ 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 ""
@@ -43735,6 +44215,12 @@ 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 ""
@@ -43795,6 +44281,12 @@ 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] ""
+msgstr[2] ""
+
msgid "When:"
msgstr ""
@@ -43831,6 +44323,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43957,12 +44455,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44062,10 +44554,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44074,10 +44569,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44092,6 +44590,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44104,24 +44605,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44131,18 +44647,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44425,8 +44962,11 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44434,9 +44974,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44491,7 +45028,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44503,15 +45040,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44542,11 +45073,11 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44881,6 +45412,9 @@ 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 ""
@@ -44893,9 +45427,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44908,7 +45439,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45082,6 +45613,18 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+
+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[2] ""
+
msgid "Your groups"
msgstr ""
@@ -45178,9 +45721,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45205,11 +45745,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+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 ""
@@ -45364,6 +45901,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45445,6 +45985,9 @@ 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 ""
@@ -45547,9 +46090,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45565,6 +46114,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45838,6 +46390,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45865,6 +46420,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45904,9 +46462,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46003,6 +46558,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46087,9 +46645,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46141,6 +46696,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46318,6 +46876,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46363,12 +46924,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46486,9 +47041,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46498,9 +47050,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46537,9 +47086,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46573,9 +47119,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46660,21 +47203,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46996,6 +47527,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47008,6 +47542,9 @@ msgstr ""
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 ""
@@ -47119,13 +47656,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47146,6 +47683,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 84804fe769f..2189e0ed07b 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index 61ca48e3c68..dcf9f697d6f 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 253338aebae..b2cfc89ce46 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ 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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28201,6 +28483,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 ""
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index a9581697c8a..b71ff51ef79 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-07-14 17:11\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ 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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28201,6 +28483,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 ""
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index ec84c5ec1f8..f353eb5c427 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 94a2ecb748d..62cc12c7a2e 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} sarà rimosso! Sei sicuro?"
+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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,15 +763,15 @@ 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 "%{label_for_message} non disponibile"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 giorni"
-
msgid "3 hours"
msgstr "3 ore"
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr "30 minuti"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr "8 ore"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 "Aggiungi intestazione e footer alle e-mail. Le impostazioni dei colori verranno applicate solo nell'interfaccia dell'applicazione"
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "Ago"
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branch"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Crea una nuova cartella"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Rilascio"
msgstr[1] "Rilasci"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Chiavi di Deploy (rilascio)"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Impossibile rimuovere la pipeline pianificata"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "Feb"
msgid "February"
msgstr "Febbraio"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr "Dalla creazione di un issue fino al rilascio in produzione"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Cronologia"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Prossima esecuzione"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Fornisci una breve descrizione per questa pipeline"
@@ -28399,6 +28690,9 @@ msgstr "Target"
msgid "PipelineSchedules|Variables"
msgstr "Variabili"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 "Iscriviti"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr "Richiedi accesso"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ msgstr "Chiavi SSH"
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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Carica file"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 2fe056ee2a7..c935b49294b 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} ã¾ã§"
@@ -385,6 +385,9 @@ msgstr "%{actionText} ãã—㦠%{noteable} ã‚’å†ã³é–‹ã"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} ã¯ç„¡åŠ¹ãªIPアドレス範囲ã§ã™"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} ㌠%{original_issue} ã‚’ %{new_issue} ã«è¤‡è£½ã—ã¾ã—ãŸã€‚"
@@ -430,9 +433,9 @@ msgstr "%{commit_author_link} ㌠%{commit_authored_timeago} ã«ä½œæˆã—〠%{c
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{count} 件中 %{completedCount} 件ã®ã‚¿ã‚¹ã‚¯ãŒå®Œäº†ã—ã¾ã—ãŸ"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight}/%{totalWeight} ウェイトãŒå®Œäº†ã—ã¾ã—ãŸ"
@@ -607,6 +610,9 @@ msgstr "%{integrations_link_start}インテグレーション%{link_end} を利ç
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}を削除ã—ã¾ã™ï¼ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+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 ""
@@ -658,6 +664,9 @@ msgstr "%{labelStart}メソッド:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}åå‰ç©ºé–“:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}スキャナー:%{labelEnd} %{scanner}"
@@ -670,15 +679,15 @@ msgstr "%{labelStart}é‡è¦åº¦:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart} ツール:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}修正ã•ã‚Œã¦ã„ãªã„レスãƒãƒ³ã‚¹:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} ã¯åˆ©ç”¨ä¸å¯"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}。"
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1時間"
@@ -791,6 +800,18 @@ msgstr "%{openedEpics} オープン, %{closedEpics} 完了"
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 ""
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] "%{securityScanner} ã®çµæžœã¯åˆ©ç”¨ã§ãã¾ã›ã‚“。パイプラインãŒæœ‰åŠ¹ã«ãªã£ã¦ã‹ã‚‰ã¾ã å®Ÿè¡Œã•ã‚Œã¦ã„ãªã„ãŸã‚ã§ã™ã€‚ %{linkStart}パイプラインを実行%{linkEnd}"
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}警告:%{strongClose} SAML グループ リンクã«ã‚ˆã‚Šã€GitLab ã¯ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰ãƒ¡ãƒ³ãƒãƒ¼ã‚’自動的ã«å‰Šé™¤ã—ã¾ã™ã€‚"
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "登録済ã¿"
-msgid "3 days"
-msgstr "3 æ—¥"
-
msgid "3 hours"
msgstr "3 時間"
-msgid "30 days"
-msgstr "30 æ—¥"
-
msgid "30 minutes"
msgstr "30 分"
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 æ—¥"
-
msgid "8 hours"
msgstr "8 時間"
@@ -1989,6 +2006,9 @@ msgstr "ã“ã® GitLab インスタンスã®ãƒ¦ãƒ¼ã‚¶ã«å¯¾ã—ã¦ã€åˆ©ç”¨è¦ç´„ã
msgid "Add a bullet list"
msgstr "箇æ¡æ›¸ãリストを追加"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "折りãŸãŸã¿å¯èƒ½ãªã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’追加"
@@ -2028,9 +2048,6 @@ msgstr "サービスデスクã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ã‚µãƒ•ã‚£ãƒƒã‚¯ã‚¹ã‚’追
msgid "Add a table"
msgstr "テーブルを追加ã™ã‚‹"
-msgid "Add a task list"
-msgstr "タスクリストを追加"
-
msgid "Add a title..."
msgstr "タイトルを追加..."
@@ -2058,9 +2075,6 @@ msgstr "承èªãƒ«ãƒ¼ãƒ«ã®è¿½åŠ "
msgid "Add approvers"
msgstr "承èªè€…を追加"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "ブロードキャストメッセージを追加"
@@ -2106,6 +2120,9 @@ msgstr "環境ã®è¿½åŠ "
msgid "Add existing confidential %{issuableType}"
msgstr "既存ã®éžå…¬é–‹ %{issuableType} を追加"
+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 "メールã«ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’追加ã—ã¾ã™ã€‚色設定ã¯ã‚¢ãƒ—リケーションインターフェース内ã§ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -3630,6 +3647,9 @@ msgstr "ã™ã¹ã¦ã®ãƒ–ランãƒ"
msgid "All changes are committed"
msgstr "ã™ã¹ã¦ã®å¤‰æ›´ãŒã‚³ãƒŸãƒƒãƒˆã•ã‚Œã¦ã„ã¾ã™"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã‚ãªãŸã®ã‚³ãƒŸãƒƒãƒˆã‚’識別ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr "ターゲットブランãƒ"
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr "ç¾åœ¨ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯æ‰¿èªæ¸ˆã§ã™ã€‚"
msgid "Approved-By"
msgstr "承èªè€…"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "承èªè€…"
@@ -5040,9 +5084,6 @@ msgstr "自分ã«å‰²ã‚Šå½“ã¦ã‚‹"
msgid "Assigned to you"
msgstr "ã‚ãªãŸã®æ‹…当"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,8 +5124,8 @@ msgstr ""
msgid "At risk"
msgstr "å±é™º"
-msgid "Attach a file"
-msgstr "ファイルを添付"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5096,12 +5137,6 @@ msgstr[0] "%d 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付"
msgid "Attaching the file failed."
msgstr "ファイルã®æ·»ä»˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "監査イベント"
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "8月"
@@ -5435,8 +5497,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "自動解決"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "ã“ã®ãƒ—ロジェクトã®ãƒ–ランãƒã¨ã‚¿ã‚°ã‚’upstreamリãƒã‚¸ãƒˆãƒªã‹ã‚‰æ¯Žæ™‚自動的ã«æ›´æ–°ã—ã¾ã™ã€‚"
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "注æ„"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr "Explore all plans"
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr "%{branchId} ブランãƒã¯ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Branch rules"
msgstr "ブランãƒãƒ«ãƒ¼ãƒ«"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "ブランãƒ"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "アクティブ"
@@ -7056,9 +7164,6 @@ msgstr "ã“ã®ãƒ–ランãƒã«ã¯ HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "Can't find variable: ZiteReader"
msgstr "ZiteReader 変数ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
-msgid "Can't load mermaid module: %{err}"
-msgstr "Mermaid モジュールをロードã§ãã¾ã›ã‚“: %{err} "
-
msgid "Can't scan the code?"
msgstr "コードをスキャンã§ãã¾ã™ã‹ï¼Ÿ"
@@ -7745,9 +7850,6 @@ msgstr "å­ã‚¨ãƒ”ックãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr "次ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’使用ã—ã¦ã€ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã«ã‚¤ãƒ¡ãƒ¼ã‚¸
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ"
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr "é‡å¤§ãªè„†å¼±æ€§ã®å­˜åœ¨"
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr "DAGã®å¯è¦–化ã«ã¯ã€å°‘ãªãã¨ã‚‚3ã¤ã®ä¾å­˜æ€§ã®ã‚るジョãƒ
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr "プロジェクトã®å‰Šé™¤"
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ msgstr ""
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "プロジェクトã®wikiリãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
+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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "デプロイ"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "デプロイキー"
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "ドメイン"
@@ -13927,9 +14080,6 @@ msgstr "ãªã—。インデックスã«åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„"
msgid "Elastic|None. Select projects to index."
msgstr "ãªã—。インデックスã™ã‚‹ãƒ—ロジェクトをé¸æŠžã—ã¦ãã ã•ã„"
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "メール"
@@ -14251,9 +14401,6 @@ msgstr "有効ãªGitアクセスプロトコル"
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr "レンダリング中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ: %{err}"
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr "プロジェクトã®å‰Šé™¤ã§ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã™ã€‚エラーã®è©³ç´°ã«ã¤ã„ã¦ã¯ãƒ­ã‚°ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -15724,24 +15874,21 @@ msgstr "Zoom ミーティングã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-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 request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr ""
@@ -15757,6 +15904,9 @@ msgstr "設定をä¿å­˜ã§ãã¾ã›ã‚“ã§ã—㟠(%{error_message})。"
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 "日付ã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆãŒç„¡åŠ¹ãªãŸã‚ã€æœŸæ—¥ã®è¨­å®šã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr "マージコミットã®ãªã„æ—©é€ã‚Šãƒžãƒ¼ã‚¸"
-
msgid "Faster releases. Better code. Less pain."
msgstr "より速ã„リリース。より良ã„コード。å•é¡Œã®æ¸›å°‘"
@@ -16046,6 +16193,9 @@ msgstr "2月"
msgid "February"
msgstr "2月"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr "%{providerTitle} ã‹ã‚‰"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr "イシューãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr "åŒæœŸ"
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "ã¾ã åŒæœŸã—ã¦ã„ã¾ã›ã‚“。"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "ä¸æ˜ŽãªçŠ¶æ…‹"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr "GitLabイシュー"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr "GitLab ã®ã‚³ãƒŸãƒƒãƒˆ"
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr "証明書:%{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr "ページを設定"
@@ -17446,6 +17602,9 @@ 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 "%{domain} ã® Let's Encrypt 証明書をå–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã™ã‚‹ã«ã¯ã€ %{link_start} ドメインã®è©³ç´° %{link_end} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。"
+msgid "GitLabPages|Start over"
+msgstr ""
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 "ã‚ãªãŸã®ãƒšãƒ¼ã‚¸ã¯ä»¥ä¸‹ã§æä¾›ã•ã‚Œã¾ã™ :"
@@ -17788,16 +17953,13 @@ msgstr "ã‚ãªãŸã®ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¸ç§»å‹•"
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr "グループ概è¦ã‚³ãƒ³ãƒ†ãƒ³ãƒ„"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr "グループオーナーã«ã‚ˆã£ã¦ä¸Šæ›¸ãã•ã‚Œãªã„é™ã‚Šã€ã™ã¹
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Auto DevOps パイプラインãŒã‚°ãƒ«ãƒ¼ãƒ—用ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸ"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—外ã§ã®ãƒ•ã‚©ãƒ¼ã‚¯ã‚’防止"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "フォーク防止ã®è¨­å®šã‚’ä¿å­˜ã—ã¾ã›ã‚“ã§ã—ãŸ"
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®å„ページサイトã®ã™ã¹ã¦ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
msgid "Groups|Save changes"
msgstr "変更をä¿å­˜"
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "ガイドライン"
@@ -18739,7 +18904,7 @@ msgstr "HTTP Basic: ã‚¢ã‚¯ã‚»ã‚¹æ‹’å¦ \\n Git over HTTPã«ã¯ 'api' スコーãƒ
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ‘スã®ãƒãƒƒã‚·ãƒ¥"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "履歴"
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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 "コードオーナーã¨ãƒžãƒ¼ã‚¸æ‰¿èªå¿…須化を有効化ã™ã‚‹ã“ã¨ã§ã€å€‹ã€…ã®MRã‚’é©åˆ‡ãªäººãŒãƒ¬ãƒ“ューã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç°¡æ½”ãªã‚³ãƒ¼ãƒ‰ã¨åŠ¹çŽ‡çš„ãªãƒ¬ãƒ“ュープロセスãŒå®Ÿç¾ã—ã¾ã™ã€‚"
-msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr "GitLab CI/CDã®ãƒ‘ワーを探索"
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "グループを %{strongStart}%{name}%{strongEnd} グループã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚"
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr "イテレーション"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "イテレーションを変更ã—ã¾ã—ãŸ"
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "最下部ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "最上部ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
@@ -22441,8 +22612,8 @@ msgstr "キー"
msgid "Key (PEM)"
msgstr "キー (PEM)"
-msgid "Key: %{key}"
-msgstr "キー: %{key}"
+msgid "Key:"
+msgstr ""
msgid "Keyboard shortcuts"
msgstr "キーボード ショートカット"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr "最後ã«æˆåŠŸã—ãŸåŒæœŸ"
-
msgid "Last successful update"
msgstr "最後ã®æˆåŠŸã—ãŸæ›´æ–°"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr "å‰å›žã®ç¢ºèªæ—¥æ™‚"
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encryptã¯example.comã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å—ã‘付ã‘ã¾ã›ã‚“"
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 "Let's Encryptã¯ã€Webサイトã§HTTPS (SSL/TLS) を有効ã«ã™ã‚‹ãŸã‚ã«ãƒ‡ã‚¸ã‚¿ãƒ«è¨¼æ˜Žæ›¸ã‚’発行ã™ã‚‹ã€ç„¡æ–™ã®è‡ªå‹•åŒ–ã•ã‚ŒãŸã‚ªãƒ¼ãƒ—ンãªèªè¨¼å±€ (CA) ã§ã™ã€‚ %{docs_link_start} GitLab Pages ã®æ–‡æ›¸ %{docs_link_end} ã«å¾“ã£ã¦ã€Let's Encryptã®è¨­å®šã®è©³ç´°ã‚’学んã§ãã ã•ã„。"
-msgid "Let's talk!"
-msgstr ""
-
msgid "License Compliance"
msgstr "ライセンスコンプライアンス"
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,8 +23430,11 @@ msgstr "リンクã•ã‚ŒãŸãƒ¡ãƒ¼ãƒ« (%{email_count})"
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "リンクã•ã‚ŒãŸã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr ""
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23277,6 +23445,48 @@ msgstr ""
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr "ã•ã‚‰ã« %{counterLabel} 個ã®ãƒ€ã‚¦ãƒ³ã‚¹ãƒˆãƒªãƒ¼ãƒ ãƒ‘イプライン"
+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 "リンク"
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr "手動ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚±ã‚¤ãƒ‡ãƒ³ã‚¹ã¯å»ƒæ­¢ã•ã‚Œã¾ã—ãŸã€‚自動ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚±ã‚¤ãƒ‡ãƒ³ã‚¹ã®ã¿åˆ©ç”¨ã§ãã¾ã™ã€‚"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã®é †åºã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr "別ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹"
msgid "Need help?"
msgstr "ãŠå›°ã‚Šã§ã™ã‹?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr "Epicã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "èªè¨¼æ–¹æ³•ãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
@@ -26074,9 +26272,6 @@ msgstr "リリースã¨åŒã˜ãƒ—ロジェクトをæŒã¤ã‚°ãƒ«ãƒ¼ãƒ—マイルス
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr "未実装"
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 "プレビューã§ãã‚‹ã‚‚ã®ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“。"
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ msgstr "OmniAuth"
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] ""
+
msgid "On track"
msgstr "順調"
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 "オペレーションダッシュボードã¯å„プロジェクトé‹ç”¨çŠ¶æ…‹ï¼ˆãƒ‘イプライン&アラート状態ãªã©ï¼‰ã‚’表示ã•ã‚Œã¾ã™ã€‚"
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr "パッケージãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®å‰Šé™¤"
msgid "PackageRegistry|Delete package"
msgstr "パッケージã®å‰Šé™¤"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr "GitLabã§%{noPackagesLinkStart}ã‚ãªãŸã®ãƒ‘ッケージを公開ã—å…
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "NuGet コマンド"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "pip コマンド"
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 "èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦èªè¨¼ã‚’設定ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細ã«ã¤ã„ã¦ã¯ã€æ–‡æ›¸ %{linkEnd} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
msgid "PackageRegistry|npm"
msgstr ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "GitLabプロジェクトã§ä¸€èˆ¬çš„ãªæ“作を実施"
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "パフォーマンスã®æœ€é©åŒ–"
@@ -27973,6 +28222,18 @@ 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 "Phabricator サーãƒãƒ¼ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr "ã“ã®ãƒ‘イプラインã«ã¤ã„ã¦ç°¡å˜ã«è¨˜è¿°ã—ã¦ãã ã•ã„。"
@@ -28201,6 +28483,9 @@ msgstr "ターゲット"
msgid "PipelineSchedules|Variables"
msgstr "変数"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "プロジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’正常ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã—ãŸã€‚"
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "マージçµæžœãƒ‘イプライン"
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "パイプライン"
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr "変数"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "é›»å­ãƒ¡ãƒ¼ãƒ«ï¼ˆ%{email})をãƒã‚§ãƒƒã‚¯ã—ã¦ã€ã“ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’所有ã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã€CI/CDã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¦ãã ã•ã„。電å­ãƒ¡ãƒ¼ãƒ«ã‚’å—ã‘å–ã£ã¦ã„ãªã„? %{resend_link} メールアドレスを間é•ã£ã¦ã„ã¾ã›ã‚“ã‹ï¼Ÿ %{update_link}"
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr "ã‚ãªãŸã®ãƒ—ロフィールã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’記入ã—ã¦ã€ãƒ—ロファイルを完了ã—ã¦ãã ã•ã„"
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr "å‰ã¸"
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ msgstr "プロジェクトslug"
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 "プロジェクトをグループã«è»¢é€ã—ãŸå ´åˆã€ãƒ—ロジェクトã®å¯è¦–性レベルãŒåå‰ç©ºé–“ã®ãƒ«ãƒ¼ãƒ«ã«åˆã‚ã›ã¦å¤‰æ›´ã•ã‚Œã¾ã™ã€‚"
@@ -29887,6 +30214,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "プロジェクト: %{name}"
+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 "講読"
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 "ã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—"
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} ã¯é–‹ç™ºè€…権é™ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒæ›¸ãè¾¼ã¿å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 "ä¿è­·"
@@ -31330,6 +31690,12 @@ 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 "追加分数を購入ã™ã‚‹"
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr "リカãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰"
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] "リリース"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr "アセットをリリース"
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "担当者ã®å‰Šé™¤"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
@@ -32106,12 +32466,6 @@ msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除済ã¿"
msgid "Removed an issue from an epic."
msgstr "イシューをエピックã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚"
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯ãƒªã‚¹ãƒˆã‚¢ã§ãã¾ã›ã‚“ï¼"
@@ -32160,9 +32514,6 @@ msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除"
msgid "Removes an issue from an epic."
msgstr "エピックã‹ã‚‰ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’削除"
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "親エピック %{epic_ref} を削除ã—ã¾ã™ã€‚"
@@ -32271,6 +32622,9 @@ msgstr "ã“ã®ãƒ¡ãƒ¼ãƒ«ã«ç›´æŽ¥è¿”ä¿¡ã™ã‚‹ã‹ã€ %{view_it_on_gitlab} ã‚’å‚ç…
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "ä¸æ­£åˆ©ç”¨ã‚’報告"
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr "脆弱性"
msgid "Reports|Vulnerability Name"
msgstr "脆弱性å"
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "テストçµæžœã«å¤‰æ›´ã‚ã‚Šã¾ã›ã‚“。"
@@ -32626,15 +32986,6 @@ msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "%{time_ago} ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr "è¦æ±‚ã•ã‚ŒãŸãƒ‡ã‚¶ã‚¤ãƒ³ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“。"
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr "リクエストã•ã‚ŒãŸçŠ¶æ…‹ã¯ç„¡åŠ¹ã§ã™"
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "確èªãƒ¡ãƒ¼ãƒ«ã®å†é€ä¿¡"
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr "å†è©¦è¡Œ"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr "追加中"
-
-msgid "RightSidebar|deleting the"
-msgstr "削除中"
-
msgid "Roadmap"
msgstr "ロードマップ"
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr "Runner ã®ãƒšãƒ¼ã‚¸ã€‚"
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr "共有ランナーパイプラインã®%{quotaLimit} ã®ã†ã¡%{quotaUse
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr "利用å¯èƒ½ãªã‚¢ãƒƒãƒ—グレード"
msgid "Runners|upgrade recommended"
msgstr "アップグレードをãŠå‹§ã‚ã—ã¾ã™"
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "稼åƒä¸­"
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "SSH キー"
@@ -33613,6 +33986,9 @@ msgstr "SSH キー"
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 "SSH ホストキーã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—リント"
@@ -33691,6 +34067,21 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "プロジェクトをä¿å­˜"
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] "Wikiã®çµæžœ"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr "セキュリティ設定"
msgid "Security Dashboard"
msgstr "セキュリティダッシュボード"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "セキュリティダッシュボード"
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "é¸æŠžã—ãŸãƒ¬ãƒ™ãƒ«ã¯ã€ç®¡ç†è€…以外ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚°ãƒ«ãƒ¼ãƒ—ã€ãƒ—ロジェクトã€ã¾ãŸã¯ã‚¹ãƒ‹ãƒšãƒƒãƒˆã«ä½¿ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。公開レベルãŒåˆ¶é™ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ—ロファイルã¯ãƒ­ã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã®ã¿è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "%{protocol} プロコトル経由ã§ãƒ—ルã€ãƒ—ッシュã™ã‚‹ãŸã‚ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを設定。"
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr "サインインã®åˆ¶é™"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr "解決策"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr "減算"
msgid "Succeeded"
msgstr "æˆåŠŸã—ã¾ã—ãŸ"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "有効化ã«æˆåŠŸã—ã¾ã—ãŸ"
@@ -37566,9 +37975,6 @@ msgstr "カスタム証明書ã®ã‚µãƒãƒ¼ãƒˆã¯ç„¡åŠ¹ã§ã™ã€‚有効ã«ã™ã‚‹ã«
msgid "Support page URL"
msgstr "サãƒãƒ¼ãƒˆãƒšãƒ¼ã‚¸URL"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr "システムメトリクス (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr "目次"
@@ -37743,6 +38152,9 @@ msgstr "キャンセル"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "タグ作æˆ"
@@ -37761,8 +38173,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "リリースノートを編集"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "æ—¢ã«å­˜åœ¨ã™ã‚‹ãƒ–ランãƒãƒ»ã‚¿ã‚°ãƒ»ã‚³ãƒŸãƒƒãƒˆãƒãƒƒã‚·ãƒ¥ã§ã™"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "ã”報告ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚ GitLabã®ç®¡ç†è€…ãŒã¾ã‚‚ãªããれを調ã¹ã¾ã™ã€‚"
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "ãã®åå‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ã™ã§ã«ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã«ã‚ã‚Šã¾ã™"
@@ -39003,9 +39415,6 @@ msgstr "確èªãƒ¡ãƒ¼ãƒ«ã®é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr "To Doã®è¿½åŠ ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "メールã®å‰Šé™¤ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "There was an error resetting group pipeline minutes."
-msgstr "グループã®ãƒ‘イプライン時間ã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
msgid "There was an error resetting user pipeline minutes."
msgstr "ユーザーã®ãƒ‘イプライン時間ã®ãƒªã‚»ãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -39138,9 +39544,6 @@ msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžãƒ‡ãƒ¼ã‚¿ã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™º
msgid "There was an error while fetching value stream analytics duration data."
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®æœŸé–“データをå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚ reCAPTCHA ã‚’ã‚‚ã†ä¸€åº¦å®Ÿæ–½ã—ã¦ãã ã•ã„。"
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "リãƒã‚¸ãƒˆãƒª"
@@ -39990,6 +40402,9 @@ 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 "タイムアウト"
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "エントリーを手動ã§è¿½åŠ ã™ã‚‹ã«ã¯ã€ã‚¹ãƒžãƒ¼ãƒˆãƒ•ã‚©ãƒ³ã®ã‚¢ãƒ—リケーションã«æ¬¡ã®è©³ç´°ã‚’入力ã—ã¦ãã ã•ã„"
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr "ã“ã®ãƒ—ロジェクトを継続ã™ã‚‹ã«ã¯ã€æ–°ã—ã„マージリク
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr "タイプ"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "2è¦ç´ èªè¨¼ãƒ‡ãƒã‚¤ã‚¹ (%{length})"
@@ -40892,6 +41313,9 @@ msgstr "差分を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。%{button_try_again}"
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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr "ä¸æ˜Žãªå½¢å¼ã§ã™"
msgid "Unknown response text"
msgstr "応答テキストãŒä¸æ˜Žã§ã™ã€‚"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr "更新日時"
msgid "Updating"
msgstr "更新中"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr "ドメインã®è¨¼æ˜Žæ›¸ã¨ä¸­é–“証明書をアップロード"
msgid "Upload a private key for your certificate"
msgstr "証明書ã®ç§˜å¯†éµã‚’アップロード"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "ファイルをアップロード"
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr "Upstream"
-msgid "Uptime"
-msgstr "稼åƒæ™‚é–“"
-
msgid "Upvotes"
msgstr "ã„ã„ã­"
@@ -41312,10 +41733,10 @@ msgstr "ç¾åœ¨ã®ä½¿ç”¨çŠ¶æ³"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr "スマートカードを使ã£ã¦ã€LDAPサーãƒãƒ¼ã«ã‚ˆã‚Šèªè¨¼ã—ã
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "メンãƒãƒ¼ãŒ GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™"
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "ユーザーã¯æ­£å¸¸ã«ãƒ—ロジェクトã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "ユーザーを正常ã«æ›´æ–°ã—ã¾ã—ãŸã€‚"
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "貢献ã—ãŸãƒ—ロジェクト"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "プロフィールを編集"
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "ã™ã¹ã¦è¡¨ç¤º"
@@ -42131,10 +42580,6 @@ msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã®ã«å分ãªãƒ‡ãƒ¼ã‚¿ãŒã‚ã‚Šã¾ã›
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 "パスワードリセット方法ã«ã¤ã„ã¦ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã—ãŸ"
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr "日付"
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr "%{pageTitle} を作æˆ"
msgid "WikiPage|Create page"
msgstr "ページを作æˆ"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr "作業中(オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦ï¼‰"
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr "種類をé¸æŠž"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã™ã‚‹ã‹ã€åˆ¥ã®ã‚°ãƒ«ãƒ¼ãƒ—を招待ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -43938,9 +44454,6 @@ msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã™ã‚‹ã‹ã€åˆ¥ã®ã‚°ãƒ
msgid "You can invite a new member to %{project_name}."
msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr "ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’%{project_name} ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
@@ -43995,7 +44508,7 @@ msgstr "%{linkStart} CI Lint %{linkEnd} ã§.gitlab-ci.ymlをテストã™ã‚‹ã“ã
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。ã—ã°ã‚‰ããŠ
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr "ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ãªã‚Šã™ã¾ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“"
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "æ–°ã—ã„トリガーを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr "ã‚ãªãŸã«ã¯ã‚µãƒ–スクリプションãŒã‚ã‚Šã¾ã›ã‚“"
@@ -44383,6 +44888,9 @@ 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 "ワンタイムパスワードèªè¨¼ã‚’使用ã—ãŸ2è¦ç´ èªè¨¼ã¯æ—¢ã«æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚別ã®ãƒ‡ãƒã‚¤ã‚¹ã‚’登録ã™ã‚‹ã«ã¯ã€ã¾ãš2è¦ç´ èªè¨¼ã‚’無効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr "所属グループ"
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr "ã©ã®ã‚³ãƒŸãƒƒãƒˆã«ã‚‚一致ã—ã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr "自分ã«å‰²ã‚Šå½“ã¦"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr "%{reportType}:読ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr "コミット済ã¿"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr "日付㯠9999-12-31 よりå‰ã‚’指定ã—ã¦ä¸‹ã•ã„"
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "グループ"
@@ -45611,6 +46138,9 @@ msgstr "https://your-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr "ç”»åƒã®å·®åˆ†"
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "%{path_lock_user_name} ã«ã‚ˆã£ã¦ %{created_at} ã«ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "マニュアル"
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1マージコミット"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "ソースブランãƒã‚’削除"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "デプロイ統計ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“"
@@ -45960,9 +46484,6 @@ msgstr "クローズã—ãªã‹ã£ãŸ"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "デプロイ統計ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr "マージ"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "マージ作業者"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã—ãŸ"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã‚ˆã†ã¨ã—ã¦ã„ã¾ã™"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,14 +47078,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "次ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr ""
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "表示・éžè¡¨ç¤ºåˆ‡ã‚Šæ›¿ãˆ"
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "トリガーã•ã‚ŒãŸ"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 27f459ea162..38635719feb 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index e7399898784..097e1d4e0e7 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-07-14 17:15\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index af51effc951..b579cdb1eb5 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -23,7 +23,7 @@ msgid " (from %{timeoutSource})"
msgstr " (%{timeoutSource} 로부터)"
msgid " Collected %{time}"
-msgstr ""
+msgstr " %{time}ì— ìˆ˜ì§‘í–ˆìŠµë‹ˆë‹¤"
msgid " Please sign in."
msgstr " ë¡œê·¸ì¸ í•´ì£¼ì„¸ìš”."
@@ -47,7 +47,7 @@ msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
msgid " or %{emphasisStart}#id%{emphasisEnd}"
-msgstr ""
+msgstr " ë˜ëŠ” %{emphasisStart}#id%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
@@ -65,7 +65,7 @@ msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\"는 \"%{ref}\"ì— ì¡´ìž¬í•˜ì§€ 않습니다"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
+msgstr "\"%{repository_name}\"ì˜ í¬ê¸° %{repository_size}는 최대 ì œí•œì¸ %{limit}보다 í½ë‹ˆë‹¤."
msgid "#%{issueIid} (closed)"
msgstr "#%{issueIid} (닫힘)"
@@ -119,7 +119,7 @@ msgstr[0] "%dê°œì˜ ì¶”ê°€ ì˜ê²¬"
msgid "%d additional committer"
msgid_plural "%d additional committers"
-msgstr[0] ""
+msgstr[0] "추가 커미터 %d"
msgid "%d approver"
msgid_plural "%d approvers"
@@ -307,7 +307,7 @@ msgstr[0] "%dê°œì˜ í”„ë¡œì íŠ¸ê°€ ì„ íƒë¨"
msgid "%d remaining"
msgid_plural "%d remaining"
-msgstr[0] ""
+msgstr[0] "%d 남ìŒ"
msgid "%d reply"
msgid_plural "%d replies"
@@ -359,7 +359,7 @@ msgstr[0] "%dê°œì˜ ì·¨ì•½ì ì´ 무시로 설정ë¨"
msgid "%d vulnerability set to needs triage"
msgid_plural "%d vulnerabilities set to needs triage"
-msgstr[0] ""
+msgstr[0] "%dê°œì˜ ì·¨ì•½ì ì´ 분류가 필요함"
msgid "%d vulnerability set to resolved"
msgid_plural "%d vulnerabilities set to resolved"
@@ -385,6 +385,9 @@ msgstr "%{actionText} & %{noteable} 다시 열기"
msgid "%{address} is an invalid IP address range"
msgstr "%{address}ì€(는) 유효하지 ì•Šì€ IP 주소 범위입니다"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} ì€ %{min} ê³¼ %{max}사ì´ì—¬ì•¼ 합니다."
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link}(ì´)ê°€ %{original_issue}를 %{new_issue}ì— ë³µì œí–ˆìŠµë‹ˆë‹¤."
@@ -430,9 +433,9 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] ""
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] "%{count}ê°œ 중 %{completedCount}ê°œì˜ ì²´í¬ ë¦¬ìŠ¤íŠ¸ ì•„ì´í…œ 완료"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -607,6 +610,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType}ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
+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 ""
@@ -658,6 +664,9 @@ msgstr "%{labelStart}메소드:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}네임 스페ì´ìŠ¤ :%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}스ìºë„ˆ:%{labelEnd} %{scanner}"
@@ -670,15 +679,15 @@ msgstr "%{labelStart}심ê°ì„±:%{labelEnd} %{severity}"
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 "%{label_for_message} 사용할 수 ì—†ìŒ"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1시간"
@@ -791,6 +800,18 @@ msgstr "%{openedEpics}개 열림, %{closedEpics}개 닫힘"
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 ""
+
+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}ë¡œ 업그레ì´ë“œí•˜ì‹­ì‹œì˜¤."
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}경고:%{strongClose} SAML 그룹 ë§í¬ë¡œ ì¸í•´ GitLabì´ ê·¸ë£¹ì—ì„œ 구성ì›ì„ ìžë™ìœ¼ë¡œ 제거할 수 있습니다."
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1256,7 +1282,7 @@ msgstr ""
msgid "1 Code quality finding"
msgid_plural "%d Code quality findings"
-msgstr[0] ""
+msgstr[0] "%d ê°œì˜ ì½”ë“œ 품질 ê²€ì¦ ê²°ê³¼"
msgid "1 Day"
msgid_plural "%d Days"
@@ -1374,15 +1400,9 @@ msgstr "2단계 ì¸ì¦(2FA)"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 ì¼"
-
msgid "3 hours"
msgstr "3 시간"
-msgid "30 days"
-msgstr "30ì¼"
-
msgid "30 minutes"
msgstr "30 분"
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7ì¼"
-
msgid "8 hours"
msgstr "8 시간"
@@ -1522,7 +1539,7 @@ msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
msgstr ""
msgid "A page with that title already exists"
-msgstr ""
+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 ""
@@ -1723,7 +1740,7 @@ msgid "Abuse reports"
msgstr "악용 사례 보고서"
msgid "Abuse reports notification email"
-msgstr ""
+msgstr "ì•…ìš© ì‹ ê³  알림 ì´ë©”ì¼"
msgid "Accept invitation"
msgstr "초대 수ë½"
@@ -1738,7 +1755,7 @@ msgid "Access Git repositories or the API."
msgstr "Git 저장소 ë˜ëŠ” APIì— ì•¡ì„¸ìŠ¤í•©ë‹ˆë‹¤."
msgid "Access Token"
-msgstr ""
+msgstr "액세스 토í°"
msgid "Access Tokens"
msgstr "액세스 토í°"
@@ -1858,10 +1875,10 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr "접근성 검사ì—ì„œ ë‹¤ìŒ ìœ í˜•ì˜ ì˜¤ë¥˜ë¥¼ 발견했습니다: %{code}"
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "로그ì¸í•œ 모든 사용ìžê°€ 액세스할 수 있습니다."
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "ì¸ì¦ ì—¬ë¶€ì— ê´€ê³„ì—†ì´ ëˆ„êµ¬ë‚˜ 액세스할 수 있습니다."
msgid "Account"
msgstr "계정"
@@ -1873,7 +1890,7 @@ msgid "Account and limit"
msgstr "계정과 제한"
msgid "Account:"
-msgstr ""
+msgstr "계정:"
msgid "Account: %{account}"
msgstr "계정: %{account}"
@@ -1888,7 +1905,7 @@ msgid "AccountValidation|In order to use free CI/CD minutes on shared runners, y
msgstr ""
msgid "AccountValidation|Learn more."
-msgstr ""
+msgstr "ìžì„¸ížˆ 보기"
msgid "AccountValidation|Looks like you’ll need to validate your account to use free CI/CD minutes"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr "ì²´í¬ë¦¬ìŠ¤íŠ¸ì— 추가하기"
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr "í…Œì´ë¸” 추가"
-msgid "Add a task list"
-msgstr "ìž‘ì—… ëª©ë¡ ì¶”ê°€"
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr "ìŠ¹ì¸ ê·œì¹™ 추가"
msgid "Add approvers"
msgstr "승ì¸ìž 추가"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 "ë©”ì¼ ë¨¸ë¦¬ë§ ë° ê¼¬ë¦¬ë§ì„ 추가하십시오. 단, ìƒ‰ìƒ ì„¤ì •ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ ì¸í„°íŽ˜ì´ìŠ¤ 안ì—서만 ì ìš©ë˜ëŠ” ì ì„ 참고해 주십시오."
@@ -2866,7 +2883,7 @@ msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
msgid "AdminUsers|Avatar"
-msgstr ""
+msgstr "아바타"
msgid "AdminUsers|Ban user"
msgstr ""
@@ -2896,7 +2913,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "사용ìžë¥¼ 차단하면 다ìŒê³¼ ê°™ì€ íš¨ê³¼ê°€ 있습니다."
msgid "AdminUsers|Can create group"
-msgstr ""
+msgstr "그룹 ìƒì„± 가능"
msgid "AdminUsers|Cannot sign in or access instance information"
msgstr ""
@@ -2977,7 +2994,7 @@ msgid "AdminUsers|Limits"
msgstr ""
msgid "AdminUsers|Linkedin"
-msgstr ""
+msgstr "LinkedIn"
msgid "AdminUsers|Locked"
msgstr ""
@@ -3007,7 +3024,7 @@ msgid "AdminUsers|Personal projects, group and user history will be left intact"
msgstr ""
msgid "AdminUsers|Quota of CI/CD minutes"
-msgstr ""
+msgstr "CI/CD 할당량(분)"
msgid "AdminUsers|Reactivating a user will:"
msgstr ""
@@ -3118,7 +3135,7 @@ msgid "AdminUsers|View pending member requests"
msgstr ""
msgid "AdminUsers|Website URL"
-msgstr ""
+msgstr "웹사ì´íŠ¸ URL"
msgid "AdminUsers|What can I do?"
msgstr ""
@@ -3187,7 +3204,7 @@ msgid "Administration"
msgstr "관리"
msgid "Administrators"
-msgstr ""
+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 ""
@@ -3630,6 +3647,9 @@ msgstr "모든 브랜치"
msgid "All changes are committed"
msgstr "모든 ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "All eligible users"
+msgstr "ìžê²©ì´ 있는 모든 사용ìž"
+
msgid "All email addresses will be used to identify your commits."
msgstr "모든 ì´ë©”ì¼ ì£¼ì†ŒëŠ” ì»¤ë°‹ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë©ë‹ˆë‹¤."
@@ -3751,7 +3771,7 @@ msgid "Allowed to create:"
msgstr ""
msgid "Allowed to delete projects"
-msgstr ""
+msgstr "프로ì íŠ¸ ì‚­ì œ 허용ë¨"
msgid "Allowed to fail"
msgstr "실패 허용ë¨"
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 "태그를 가져오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 검색해 보세요."
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4144,7 +4161,7 @@ msgid "An error occurred while retrieving projects."
msgstr ""
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "ì„¤ì •ì„ ê°€ì ¸ì˜¤ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하려면 페ì´ì§€ë¥¼ 새로고침하세요."
msgid "An error occurred while saving changes: %{error}"
msgstr ""
@@ -4154,7 +4171,7 @@ msgid_plural "An error occurred while saving the settings"
msgstr[0] ""
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "ì„¤ì •ì„ ì €ìž¥í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 저장해 보세요."
msgid "An error occurred while subscribing to notifications."
msgstr "ì•Œë¦¼ì„ êµ¬ë…하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -4364,7 +4381,7 @@ msgid "Application settings saved successfully"
msgstr "어플리케ì´ì…˜ ì„¤ì •ì´ ì„±ê³µì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "어플리케ì´ì…˜ ì„¤ì •ì´ ì„±ê³µì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Application settings update failed"
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ 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 approval by author."
-msgstr ""
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr "ì´ ë¨¸ì§€ 리퀘스트를 승ì¸í–ˆìŠµë‹ˆë‹¤."
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "승ì¸ìž"
@@ -4849,7 +4893,7 @@ msgid "Are you sure you want to remove %{group_name}?"
msgstr "ì •ë§ë¡œ %{group_name}(ì„)를 ì‚­ì œ 하시겠습니까?"
msgid "Are you sure you want to remove %{topic_name}?"
-msgstr ""
+msgstr "ì •ë§ë¡œ %{topic_name} 를 ì‚­ì œ 하시겠습니까?"
msgid "Are you sure you want to remove the attachment?"
msgstr "첨부 파ì¼ì´ 지워집니다. ê³„ì† í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
@@ -4870,7 +4914,7 @@ 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 "오류 ì¶”ì  ì•¡ì„¸ìŠ¤ 토í°ì„ 재설정하시겠습니까?"
msgid "Are you sure you want to reset the health check token?"
msgstr "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
@@ -5040,9 +5084,6 @@ msgstr "나ì—게 할당 ë¨"
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,8 +5124,8 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
-msgstr "íŒŒì¼ ì²¨ë¶€"
+msgid "Attach a file or image"
+msgstr "íŒŒì¼ ë˜ëŠ” ì´ë¯¸ì§€ 첨부"
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr "íŒŒì¼ ì²¨ë¶€ê°€ 실패했습니다."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
@@ -5157,11 +5192,17 @@ msgid "AuditLogs|User Events"
msgstr ""
msgid "AuditStreams|A header with this name already exists."
-msgstr ""
+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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "8ì›”"
@@ -5435,8 +5497,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "ìžë™ìœ¼ë¡œ í•´ê²°ë¨"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr "업스트림 저장소ì—ì„œ ì´ í”„ë¡œì íŠ¸ì˜ 분기와 태그를 ìžë™ìœ¼ë¡œ ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤."
msgid "Autosave|Note"
msgstr "참고"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 "Billings|무료 요금제 ë° í‰ê°€íŒì—ì„œ ê·¸ë£¹ì€ í•˜ë£¨ì— ìµœëŒ€ 20ëª…ì˜ íšŒì›ì„ 초대할 수 있습니다."
+
msgid "Billings|In a seat"
msgstr ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] "Billings|프리 ìš”ê¸ˆì œì˜ ê·¸ë£¹ì€ %d 명으로 제한ë©ë‹ˆë‹¤."
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 ""
@@ -6095,6 +6161,9 @@ 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 "Billings|í‰ê°€íŒì´ ì¢…ë£Œë  ë•Œ 모든 구성ì›ì´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 있ë„ë¡ í•˜ë ¤ë©´ 유료 등급으로 업그레ì´ë“œí•´ì•¼ 합니다."
+
msgid "Billing|Toggle seat details"
msgstr ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "브랜치"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "브랜치들: %{source_branch} ì—ì„œ %{target_branch} ë¡œ"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "브랜치들: %{source_branch} → %{target_branch} "
+
msgid "Branches|Active"
msgstr "활성"
@@ -7056,9 +7164,6 @@ msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "코드를 스캔할 수 없습니까?"
@@ -7357,7 +7462,7 @@ msgid "Changed merge method to %{merge_method}"
msgstr ""
msgid "Changed reviewer(s)."
-msgstr ""
+msgstr "리뷰어 변경ë¨"
msgid "Changed squash option to %{squash_option}"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr "하위 ì—í”½ì´ ì¡´ìž¬í•˜ì§€ 않습니다."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8122,7 +8224,7 @@ msgid "Closed MRs"
msgstr ""
msgid "Closed date"
-msgstr ""
+msgstr "마ê°ì¼"
msgid "Closed issues"
msgstr "닫힌 ì´ìŠˆ"
@@ -8169,11 +8271,14 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr "설정"
+
msgid "CloudSeed|Create cluster"
msgstr ""
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "ë°ì´í„°ë² ì´ìŠ¤ ìƒì„±"
msgid "CloudSeed|Create instance"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8239,15 +8350,21 @@ msgid "CloudSeed|Memorystore for Redis"
msgstr ""
msgid "CloudSeed|No instances"
-msgstr ""
+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"
@@ -9089,7 +9206,7 @@ msgid "Collector hostname"
msgstr ""
msgid "Color"
-msgstr ""
+msgstr "색ìƒ"
msgid "ColorWidget|An error occurred while updating color."
msgstr ""
@@ -9480,7 +9597,7 @@ msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if
msgstr ""
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "오류 ì¶”ì  ì„¤ì •"
msgid "Configure GitLab"
msgstr ""
@@ -9522,7 +9639,7 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr ""
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
-msgstr ""
+msgstr "고급 권한, 대용량 íŒŒì¼ ì €ìž¥ì†Œ, 2단계 ì¸ì¦ ë° CI/CD ì„¤ì •ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr "DAST ì„¤ì •ì„ ì°¾ì„ ìˆ˜ 없습니다."
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr "DORA4Metrics|실패율(í¼ì„¼íŠ¸) 변경"
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr "DORA4Metrics|변경 리드 타임 (median days)"
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr "DORA4Metrics|서비스 ë³µì› ì‹œê°„ (median days)"
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr "ì•„ì´ë”” ì‚­ì œ"
+
msgid "Delete image"
msgstr ""
@@ -12164,7 +12305,7 @@ msgid "Delete image repository"
msgstr ""
msgid "Delete internal note"
-msgstr ""
+msgstr "내부 노트 삭제"
msgid "Delete label"
msgstr "ë¼ë²¨ ì‚­ì œ"
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr "프로ì íŠ¸ ì‚­ì œ"
+msgid "Delete release"
+msgstr "릴리스 삭제"
+
+msgid "Delete release %{release}?"
+msgstr "릴리스 %{release}ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "ë°°í¬"
+msgid "Deploy Key"
+msgstr "ë°°í¬ í‚¤"
+
msgid "Deploy Keys"
msgstr "ë°°í¬ í‚¤"
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "ë„ë©”ì¸"
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "ì´ë©”ì¼"
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "미러를 제거하지 못했습니다."
msgid "Failed to remove the pipeline schedule"
msgstr "파ì´í”„ë¼ì¸ ìŠ¤ì¼€ì¤„ì„ ì œê±°í•˜ì§€ 못했습니다."
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr "2ì›”"
msgid "February"
msgstr "2ì›”"
+msgid "Feedback issue"
+msgstr "ì´ìŠˆ 피드백"
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16209,10 +16359,10 @@ msgid "Find file"
msgstr "íŒŒì¼ ì°¾ê¸°"
msgid "Fingerprint (MD5)"
-msgstr ""
+msgstr "핑거프린트 (MD5) "
msgid "Fingerprint (SHA256)"
-msgstr ""
+msgstr "핑거프린트 (SHA256)"
msgid "Fingerprints"
msgstr "지문"
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr "ì´ìŠˆ ìƒì„±ì—ì„œ 프로ë•ì…˜ ë°°í¬ê¹Œì§€"
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr "Geo|%{label} %{timeAgo}"
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16619,7 +16781,7 @@ msgid "Geo|%{title} checksum progress"
msgstr ""
msgid "Geo|Add New Site"
-msgstr ""
+msgstr "새 사ì´íŠ¸ 추가"
msgid "Geo|Add site"
msgstr "사ì´íŠ¸ 추가"
@@ -16646,16 +16808,16 @@ msgid "Geo|Allow this secondary site to replicate content on Object Storage"
msgstr ""
msgid "Geo|Allowed Geo IP"
-msgstr ""
+msgstr "í—ˆìš©ëœ Geo IP"
msgid "Geo|Allowed Geo IP can't be blank"
-msgstr ""
+msgstr "í—ˆìš©ëœ ì§€ì—­ IP는 비워둘 수 없습니다."
msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
-msgstr ""
+msgstr "허용ë˜ëŠ” 지역 IP는 1~255ìž ì‚¬ì´ì—¬ì•¼ 합니다."
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
-msgstr ""
+msgstr "í—ˆìš©ëœ ì§€ì—­ IPì—는 유효한 IP 주소가 í¬í•¨ë˜ì–´ì•¼ 합니다."
msgid "Geo|Checksummed"
msgstr ""
@@ -16664,13 +16826,13 @@ 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 "쉼표로 구분ë¨(예시: '1.1.1.1, 2.2.2.0/24')"
msgid "Geo|Configure various settings for your %{siteType} site. %{linkStart}Learn more%{linkEnd}"
msgstr ""
msgid "Geo|Connection timeout"
-msgstr ""
+msgstr "연결 시간 초과"
msgid "Geo|Connection timeout can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "ì•Œ 수 없는 ìƒíƒœ"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "%{timeAgo} ì „ ì—…ë°ì´íŠ¸ ë¨"
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr "GitLab 로고"
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,18 +17953,15 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
+msgid "Google Cloud Error - %{error}"
+msgstr "Google í´ë¼ìš°ë“œ 오류 - %{error}"
+
msgid "Google Cloud Project"
msgstr ""
msgid "Google Cloud authorizations required"
msgstr ""
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,8 +18334,8 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
-msgstr ""
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
+msgstr "GroupSAML|모든 사용ìžì˜ Git 활ë™ì— 대해 SSO ì „ìš© ì¸ì¦ì„ 시행하기 ì „ì— ì›¹ 활ë™ì— 대해 SSO ì „ìš© ì¸ì¦ì„ 활성화하십시오."
msgid "GroupSAML|Certificate fingerprint"
msgstr ""
@@ -18340,8 +18499,8 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
-msgstr ""
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
+msgstr "GroupSettings|주어진 ì‹œê°„ì— ì§€ì •ëœ ìˆ˜ ì´ìƒì˜ 리í¬ì§€í† ë¦¬ë¥¼ 다운로드하는 사용ìžë¥¼ ìžë™ìœ¼ë¡œ 차단합니다."
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 ""
@@ -18388,6 +18547,9 @@ msgstr ""
msgid "GroupSettings|Export group"
msgstr ""
+msgid "GroupSettings|Git abuse rate limit"
+msgstr "GroupSettings|Git 악용 비율 제한"
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "ê°€ì´ë“œë¼ì¸"
@@ -18739,7 +18904,7 @@ msgstr "HTTP Basic: ì ‘ê·¼ 거부\\nGit over HTTPì—서는 'api' 스코프를 ê°
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "ì´ë ¥"
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr ""
+msgid "Identity|Provider ID"
+msgstr "Identity|ì œê³µìž ID"
+
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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
msgid "Importing..."
msgstr ""
+msgid "Import|The repository could not be imported."
+msgstr "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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20454,7 +20595,7 @@ msgid "Incident|Editing %{filename}"
msgstr ""
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr ""
+msgstr "Incident|ì¸ì‹œë˜íŠ¸ 타임ë¼ì¸ ì´ë²¤íŠ¸ ìƒì„± 오류: %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
msgstr ""
@@ -20466,7 +20607,7 @@ msgid "Incident|No timeline items have been added yet."
msgstr ""
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "Incident|다른 ì´ë²¤íŠ¸ 저장 ë° ì¶”ê°€"
msgid "Incident|Something went wrong while creating the incident timeline event."
msgstr ""
@@ -20490,10 +20631,10 @@ msgid "Incident|Timeline"
msgstr ""
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "Incident|타임ë¼ì¸ í…스트"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "Incident|타임ë¼ì¸ í…스트..."
msgid "Include author name in notification email body"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr "ì´í„°ë ˆì´ì…˜"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 "IterationsCadence|ìžë™í™” 시작 날짜는 활성 반복 %{iteration_dates}ì´í›„여야 합니다."
+
+msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
+msgstr "IterationsCadence|ìžë™í™” 시작 날짜는 ì´ì „ 반복 %{iteration_dates}ì´í›„여야 합니다."
+
+msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
+msgstr "IterationsCadence|ìžë™í™” 시작 날짜는 소급하여 ì´ì „ ë°˜ë³µì„ ìƒì„±í•©ë‹ˆë‹¤. %{start_date} ì€ ê°€ëŠ¥í•œ 가장 빠른 시작 날짜입니다."
+
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 "Iterations|ì˜ˆì•½ëœ ëª¨ë“  ë°˜ë³µì€ ë” ì ì€ 수를 사용하ë”ë¼ë„ ì˜ˆì•½ëœ ìƒíƒœë¡œ 유지ë©ë‹ˆë‹¤."
+
+msgid "Iterations|Automatic scheduling"
+msgstr ""
+
+msgid "Iterations|Automation start date"
+msgstr "Iterations|ìžë™í™” 시작 날짜"
+
msgid "Iterations|Cadence configuration is invalid."
msgstr ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,15 +21994,15 @@ 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 "Iterations|스케줄ìƒì˜ 첫 번째 ë°˜ë³µì˜ ë‚ ì§œìž…ë‹ˆë‹¤. ì´ ë‚ ì§œëŠ” ê° ë°˜ë³µì´ ì‹œìž‘ë˜ëŠ” ìš”ì¼ì„ 결정합니다."
+
msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
msgid "Iterations|The iteration has been deleted."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
-msgstr ""
-
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr ""
@@ -22244,7 +22412,7 @@ msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
msgstr ""
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr ""
+msgstr "Job|%{searchTerm}ì— ëŒ€í•´%{searchLength} ê°œì˜ ê²°ê³¼ë¥¼ 찾았습니다."
msgid "Job|Are you sure you want to erase this job log and artifacts?"
msgstr ""
@@ -22286,7 +22454,7 @@ msgid "Job|Job has been erased by %{userLink}"
msgstr ""
msgid "Job|Job log search"
-msgstr ""
+msgstr "Job|작업 로그 검색"
msgid "Job|Keep"
msgstr "유지"
@@ -22295,7 +22463,7 @@ msgid "Job|Manual"
msgstr ""
msgid "Job|No search results found"
-msgstr ""
+msgstr "Job|검색결과가 없습니다."
msgid "Job|Passed"
msgstr ""
@@ -22318,14 +22486,17 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "맨 아래로 스í¬ë¡¤"
+msgid "Job|Scroll to next failure"
+msgstr "Job|ë‹¤ìŒ ì‹¤íŒ¨ë¡œ 스í¬ë¡¤"
+
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 ""
+msgstr "Job|ìž‘ì—… 로그 출력ì—ì„œ 하위 문ìžì—´ì„ 검색합니다. 현재 ê²€ìƒ‰ì€ ë³´ì´ëŠ” ìž‘ì—… 로그 ì¶œë ¥ì— ëŒ€í•´ì„œë§Œ 지ì›ë˜ë©° í¬ê¸°ë¡œ ì¸í•´ 잘린 로그 ì¶œë ¥ì— ëŒ€í•´ì„œëŠ” 지ì›ë˜ì§€ 않습니다."
msgid "Job|Search job log"
-msgstr ""
+msgstr "Job|작업 로그 검색"
msgid "Job|Show complete raw"
msgstr ""
@@ -22364,7 +22535,7 @@ msgid "Job|Waiting for resource"
msgstr ""
msgid "Job|We could not find this element"
-msgstr ""
+msgstr "Job|ì´ ìš”ì†Œë¥¼ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Job|allowed to fail"
msgstr ""
@@ -22441,8 +22612,8 @@ msgstr ""
msgid "Key (PEM)"
msgstr "키 (PEM)"
-msgid "Key: %{key}"
-msgstr ""
+msgid "Key:"
+msgstr "Key:"
msgid "Keyboard shortcuts"
msgstr "키보드 단축키"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ 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 "Let's talk!"
-msgstr ""
-
msgid "License Compliance"
msgstr ""
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr "ì—°ê²°ëœ ì‚¬ê±´ ë˜ëŠ” ì´ìŠˆ"
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ msgstr ""
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
+msgid "LinkedResources|Add"
+msgstr "LinkedResources|추가"
+
+msgid "LinkedResources|Add a resource link"
+msgstr "LinkedResources|리소스 ë§í¬ 추가"
+
+msgid "LinkedResources|Cancel"
+msgstr "LinkedResources|취소"
+
+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 "LinkedResources|ì—°ê²°ëœ ë¦¬ì†ŒìŠ¤ 가져오기"
+
+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 "ë§í¬"
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,8 +24075,8 @@ 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_whitelist}."
-msgstr ""
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr "최대 íŒŒì¼ í¬ê¸°ëŠ” 1MB입니다. ì´ë¯¸ì§€ í¬ê¸°ëŠ” 32 x 32픽셀ì´ì–´ì•¼ 합니다. 허용ë˜ëŠ” ì´ë¯¸ì§€ 형ì‹ì€ %{favicon_extension_allowlist}입니다."
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
msgstr ""
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,8 +25489,8 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
-msgstr ""
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "여러 IP 주소 범위가 지ì›ë©ë‹ˆë‹¤. 그룹 ì„¤ì •ì— ëŒ€í•œ 액세스ì—는 ì˜í–¥ì„ 미치지 않습니다."
msgid "Multiple Prometheus integrations are not supported"
msgstr ""
@@ -25472,9 +25673,6 @@ msgstr "로그아웃하고 다른 계정으로 로그ì¸"
msgid "Need help?"
msgstr "ë„ì›€ì´ í•„ìš”í•˜ì‹ ê°€ìš”?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr "ì—픽 ì—†ìŒ"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "Google Cloud 프로ì íŠ¸ ì—†ìŒ - Google Cloud 프로ì íŠ¸ê°€ 하나 ì´ìƒ 필요합니다."
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -25987,7 +26185,7 @@ msgid "No repository"
msgstr "저장소 ì—†ìŒ"
msgid "No results"
-msgstr ""
+msgstr "ê²°ê³¼ ì—†ìŒ"
msgid "No runner executable"
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26223,7 +26421,7 @@ msgstr[0] "리뷰어"
msgid "NotificationEmail|Reviewer: %{users}"
msgid_plural "NotificationEmail|Reviewers: %{users}"
-msgstr[0] ""
+msgstr[0] "리뷰어: %{users}"
msgid "NotificationEvent|Change reviewer merge request"
msgstr ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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 "Notify|%{invited_user} ì€ %{highlight_start}ì—ì„œ %{highlight_end} ì„ ê±°ë¶€ 했습니다. ê·€í•˜ì˜ ê°€ìž… 초대 %{target_link} %{target_name} 입니다."
+
+msgid "Notify|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] "%{end_date}ì— í‰ê°€íŒì´ 종료ë˜ê³  %{namespace_name} ì€ %{free_user_limit} 명으로 제한ë©ë‹ˆë‹¤."
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 "OperationsDashboard|ìš´ì˜ ë° í™˜ê²½ 대시보드는 ë™ì¼í•œ 프로ì íŠ¸ 목ë¡ì„ 공유합니다. í•œ 프로ì íŠ¸ì—ì„œ 프로ì íŠ¸ë¥¼ 추가하거나 제거하면 GitLabì€ ë‹¤ë¥¸ 프로ì íŠ¸ì—ì„œ 프로ì íŠ¸ë¥¼ 추가하거나 제거합니다. %{linkStart}추가 ì •ë³´%{linkEnd}"
+
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "ìž‘ì—… 대시보드는 파ì´í”„ë¼ì¸ê³¼ 경고 ìƒíƒœë¥¼ í¬í•¨í•˜ì—¬ ê° í”„ë¡œì íŠ¸ì˜ ìš´ì˜ ìƒíƒœì— 대한 ìš”ì•½ì„ ì œê³µí•©ë‹ˆë‹¤."
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr "성능 개선 ë„우미"
+
msgid "Performance optimization"
msgstr "성능 최ì í™”"
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ì— 대한 간단한 설명 제공"
@@ -28201,6 +28483,9 @@ msgstr "대ìƒ"
msgid "PipelineSchedules|Variables"
msgstr "변수"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "프로ì íŠ¸ ìºì‹œê°€ 성공ì ìœ¼ë¡œ 재설정ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr "Pipeline|가장 ëŠë¦° 5ê°œì˜ ìž‘ì—…"
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr "Pipeline|마지막으로 ì‹¤í–‰ëœ ìž‘ì—…"
+
+msgid "Pipeline|Longest queued job"
+msgstr "Pipeline|ëŒ€ê¸°ì‹œê°„ì´ ê°€ìž¥ 긴 ìž‘ì—…"
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "Pipeline|ì²˜ìŒ 100ê°œì˜ ê²°ê³¼ë§Œ 표시할 수 있ìŒ"
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr "Pipeline|성능개선 ë„우미"
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "Pipeline|마지막으로 ì‹¤í–‰ëœ ìž‘ì—…ì€ íŒŒì´í”„ë¼ì¸ì—ì„œ 시작할 마지막 작업입니다."
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "Pipelines|대기 ì‹œê°„ì´ ê°€ìž¥ 긴 ìž‘ì—…ì€ ëŒ€ê¸° ìƒíƒœì—ì„œ 가장 오랜 ì‹œê°„ì„ ë³´ë‚¸ 작업으로 ëŸ¬ë„ˆì— ì˜í•´ ì„ íƒë˜ê¸°ë¥¼ 기다리고 있습니다."
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr "변수"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr "Pipeline|종ì†ì„± 보기"
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr "계ì†í•˜ê¸° ì „ì— í™•ì¸ ì´ë©”ì¼ì˜ ë§í¬ë¥¼ í´ë¦­í•˜ì‹­ì‹œì˜¤. ë‹¤ìŒ ì£¼ì†Œë¡œ 보냈습니다 "
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 "ì´ í”„ë¡œì íŠ¸ì— 대한 %{linkStart}기여 지침%{linkEnd} ì„ ê²€í† í•˜ì‹­ì‹œì˜¤."
+
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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29189,10 +29513,10 @@ msgid "Preview Markdown"
msgstr "마í¬ë‹¤ìš´ 미리보기"
msgid "Preview changes"
-msgstr ""
+msgstr "변경 내용 미리보기"
msgid "Preview diagram"
-msgstr ""
+msgstr "다ì´ì–´ê·¸ëž¨ 미리보기"
msgid "Preview payload"
msgstr "페ì´ë¡œë“œ 미리보기"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr ""
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr "프로ì íŠ¸: 브랜치들: %{source_project_path}:%{source_branch} ì—ì„œ %{target_project_path}:%{target_branch} ë¡œ"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr "프로ì íŠ¸: 브랜치들: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "구ë…"
@@ -29965,6 +30298,9 @@ 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 "ProjectQualitySummary|ì´ íŽ˜ì´ì§€ë¥¼ 개선하는 ë° ë„ì›€ì„ ì£¼ì„¸ìš”."
+
msgid "ProjectQualitySummary|Latest pipeline results"
msgstr ""
@@ -29977,6 +30313,9 @@ msgstr ""
msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
msgstr ""
+msgid "ProjectQualitySummary|Provide feedback"
+msgstr "ProjectQualitySummary|피드백 제공"
+
msgid "ProjectQualitySummary|See full report"
msgstr ""
@@ -30004,6 +30343,9 @@ 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 "ProjectQualitySummary|ì´ íŽ˜ì´ì§€ëŠ” 프로ì íŠ¸ì˜ 코드 테스트 추세를 ì´í•´í•˜ëŠ” ë° ë„ì›€ì´ ë©ë‹ˆë‹¤. 개선할 수 있는 ë°©ë²•ì„ ì•Œë ¤ì£¼ì„¸ìš”!"
+
msgid "ProjectSelect| or group"
msgstr ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr "ProtectedEnvironment|아래 ë°°í¬ ê³„ì¸µìœ¼ë¡œ ì§€ì •ëœ ëª¨ë“  í™˜ê²½ì€ ìƒìœ„ ê·¸ë£¹ì— ì˜í•´ 보호ë©ë‹ˆë‹¤. %{link_start}ìžì„¸ížˆ 알아보기%{link_end}."
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr ""
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr "ProtectedEnvironment|%{project} / %{environment}ì— ë°°í¬ í—ˆìš©"
+
msgid "ProtectedEnvironment|Environment"
msgstr "환경"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr "ProtectedEnvironment|ë³´í˜¸ëœ ì—…ìŠ¤íŠ¸ë¦¼ 환경"
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr "ProtectedEnvironment|ì´ ê·¸ë£¹ì— ëŒ€í•œ 세부 정보를 로드하지 못했습니다."
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+msgstr "ProtectedEnvironment|ì´ í”„ë¡œì íŠ¸ì—는 ë³´í˜¸ëœ í™˜ê²½ì´ ì—†ìŠµë‹ˆë‹¤."
+
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 "ProtectedEnvironment|ìƒìœ„ 그룹"
+
msgid "ProtectedEnvironment|Protect"
msgstr "보호"
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr "복구 코드"
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "릴리스 %{deletedRelease} ì´ ì„±ê³µì ìœ¼ë¡œ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ msgstr ""
msgid "Release|Something went wrong while creating a new release."
msgstr ""
+msgid "Release|Something went wrong while deleting the release."
+msgstr "Release|릴리스를 삭제하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
msgid "Release|Something went wrong while getting the release details."
msgstr ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "아바타 제거"
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr "취약ì "
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr "Reports|메트릭 보고서"
+
msgid "Reports|no changed test results"
msgstr "ë³€ê²½ëœ í…ŒìŠ¤íŠ¸ ê²°ê³¼ ì—†ìŒ"
@@ -32626,15 +32986,6 @@ msgstr "액세스 요청"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr "í™•ì¸ ì´ë©”ì¼ ìž¬ì „ì†¡"
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr "재시ë„"
-msgid "Retry downstream pipeline"
-msgstr ""
+msgid "Retry all failed or cancelled jobs"
+msgstr "실패하거나 ì·¨ì†Œëœ ëª¨ë“  ìž‘ì—… 재시ë„"
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr "로드맵"
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr "Runners 페ì´ì§€."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr "Runners|가용"
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr "Runners|추천ë¨"
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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 "Runners|등ë¡í•˜ë ¤ë©´ %{link_start}ê·¸ë£¹ì˜ ëŸ¬ë„ˆ 페ì´ì§€%{link_end}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
+
+msgid "Runners|Up to date"
+msgstr "Runners|최신"
+
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 "Runners|업그레ì´ë“œ ìƒíƒœ"
+
msgid "Runners|Upgrade available"
msgstr ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr "Runner|소유ìž"
+
msgid "Running"
msgstr "실행중"
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr "SSH 지문"
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ msgstr "SSH 키"
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 "SSH ì§€ë¬¸ì€ í´ë¼ì´ì–¸íŠ¸ê°€ 올바른 í˜¸ìŠ¤íŠ¸ì— ì—°ê²°ë˜ì–´ 있는지 확ì¸í•©ë‹ˆë‹¤. %{config_link_start}현재 ì¸ìŠ¤í„´ìŠ¤ êµ¬ì„±ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤%{config_link_end}."
+
msgid "SSH host key fingerprints"
msgstr ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr "SearchToken|담당ìž"
+
+msgid "SearchToken|Reviewer"
+msgstr "SearchToken|검토ìž"
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr "보안 대시보드"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ msgstr ""
msgid "SecurityOrchestration|Failed to load cluster agents."
msgstr ""
+msgid "SecurityOrchestration|Failed to load images."
+msgstr "SecurityOrchestration|ì´ë¯¸ì§€ë¥¼ 로드하지 못했습니다."
+
+msgid "SecurityOrchestration|Failed to load vulnerability scanners."
+msgstr "SecurityOrchestration|ì·¨ì•½ì  ìŠ¤ìºë„ˆë¥¼ 로드하지 못했습니다."
+
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 ""
@@ -34497,6 +34903,9 @@ msgstr ""
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "SecurityOrchestration|ì´ %{namespaceType} ì—는 보안 ì •ì±…ì´ í¬í•¨ë˜ì–´ 있지 않습니다."
+
msgid "SecurityOrchestration|This group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr "SecurityReports|ì´ë¯¸ì§€"
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "%{protocol} í”„ë¡œí† ì½œì„ í†µí•´ Pull 하거나 Push하려면 ê³„ì •ì— íŒ¨ìŠ¤ì›Œë“œë¥¼ 설정하십시오."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr "ë¡œê·¸ì¸ ì œí•œ"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37020,7 +37432,7 @@ msgid "Submit"
msgstr ""
msgid "Submit a review"
-msgstr ""
+msgstr "리뷰 제출"
msgid "Submit as ham"
msgstr ""
@@ -37032,7 +37444,7 @@ msgid "Submit feedback"
msgstr "피드백 보내기"
msgid "Submit review"
-msgstr ""
+msgstr "리뷰 제출"
msgid "Submit search"
msgstr "검색 제출"
@@ -37104,7 +37516,7 @@ msgid "SubscriptionBanner|Export license usage file"
msgstr ""
msgid "SubscriptionBanner|Upload new license"
-msgstr ""
+msgstr "새 ë¼ì´ì„ ìŠ¤ 업로드"
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "성공ì ìœ¼ë¡œ 활성화ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr "ì§€ì› íŽ˜ì´ì§€ URL"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr "시스템 시작ë¨"
+
msgid "Table of Contents"
msgstr "목차"
@@ -37743,6 +38152,9 @@ msgstr "취소"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr "TagsPage|릴리즈 ìƒì„±"
+
msgid "TagsPage|Create tag"
msgstr "태그 ìƒì„±"
@@ -37761,8 +38173,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Release Note 편집"
+msgid "TagsPage|Edit release"
+msgstr "TagsPage|릴리즈 수정"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "기존 브랜치 ì´ë¦„, 태그 ë˜ëŠ” 커밋 SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr "ë³€ê²½ëœ ë ˆì´ë¸”ì´ ì—†ìŠµë‹ˆë‹¤."
+
msgid "There are no changes"
msgstr ""
@@ -38881,7 +39290,7 @@ msgid "There are no projects shared with this group yet"
msgstr ""
msgid "There are no secure files yet."
-msgstr ""
+msgstr "ì•„ì§ ë³´ì•ˆ 파ì¼ì´ 없습니다."
msgid "There are no topics to show."
msgstr "표시할 주제가 없습니다."
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "ì´ ì €ìž¥ì†Œ"
@@ -39990,6 +40402,9 @@ 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 "시간 초과"
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr "토픽 %{source_topic} ì´ %{target_topic} í† í”½ì— ì„±ê³µì ìœ¼ë¡œ 병합ë˜ì—ˆìŠµë‹ˆë‹¤."
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,9 +41313,12 @@ msgstr "ì°¨ì´ì ì„ ì½ì–´ë“¤ì¼ 수 없습니다. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to parse the vulnerability report's options."
+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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr "ì—…ë°ì´íŠ¸ì¤‘..."
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
@@ -41238,7 +41662,7 @@ msgid "Upload object map"
msgstr ""
msgid "Uploaded date"
-msgstr ""
+msgstr "업로드 날짜"
msgid "Uploading changes to terminal"
msgstr "터미ë„ì— ë³€ê²½ 사항 업로드 중"
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr "추천"
@@ -41312,10 +41733,10 @@ msgstr "ì´ë²ˆ ê²°ì œ 주기 사용량"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
-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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}"
+msgstr "UsageQuota|네임스페ì´ìŠ¤ëŠ” 현재 %{strong_start}%{used_storage}%{strong_end} 네임스페ì´ìŠ¤ 저장소를 사용하고 있습니다. 그룹 소유ìžëŠ” 네임스페ì´ìŠ¤ 스토리지 ì‚¬ìš©ëŸ‰ì„ ë³´ê³  %{strong_start}그룹 설정 &gt; 사용량 할당량%{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}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "기여한 프로ì íŠ¸"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "프로필 수정"
@@ -41966,6 +42412,9 @@ msgstr "ì´ ì‚¬ìš©ìžëŠ” 다른 사용ìžë¥¼ 팔로우하고 있지 않습니다
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "ëª¨ë‘ ë³´ê¸°"
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 "비밀번호 재설정 ë°©ë²•ì´ ë‹´ê¸´ ì´ë©”ì¼ì„ 보냈습니다."
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] "í‰ê°€íŒì´ 종료ë˜ë©´ %{free_user_limit} ì„으로 제한ë˜ëŠ” 프리 요금제로 ì´ë™í•©ë‹ˆë‹¤. %{free_user_limit} 시트는 활성 ìƒíƒœë¡œ 유지ë˜ë©°, 시트를 차지하지 않는 구성ì›ì€ %{link_start}제한 초과 ìƒíƒœ%{link_end} ì´ ë˜ì–´ ì´ ê·¸ë£¹ì— ì•¡ì„¸ìŠ¤í•  수 없게 ë©ë‹ˆë‹¤."
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr "위키"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,11 +44040,14 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
-msgstr ""
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "WorkItem|ìž‘ì—…ì€ ìž‘ì—…ì„ ë¬¸ì œì™€ ì—°ê²°ëœ ë” ìž‘ì€ ì¡°ê°ìœ¼ë¡œ 나누는 ê¸°ëŠ¥ì„ ì œê³µí•©ë‹ˆë‹¤. ìž‘ì—…ì€ ìƒˆë¡œìš´ %{workItemsLink} 개체를 사용하는 첫 번째 항목입니다. 추가 ìž‘ì—… 항목 ìœ í˜•ì´ ê³§ ì œê³µë  ì˜ˆì •ìž…ë‹ˆë‹¤."
-msgid "WorkItem|Add a child"
-msgstr ""
+msgid "WorkItem|Add a task"
+msgstr "WorkItem|작업 추가"
+
+msgid "WorkItem|Add a title"
+msgstr "WorkItem|제목 추가"
msgid "WorkItem|Add assignee"
msgstr ""
@@ -43582,11 +44055,14 @@ msgstr ""
msgid "WorkItem|Add assignees"
msgstr ""
+msgid "WorkItem|Add task"
+msgstr "WorkItem|작업 추가"
+
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr ""
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
-msgstr ""
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "WorkItem|ì •ë§ ìž‘ì—…ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다."
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
-msgstr ""
+msgid "WorkItem|Delete task"
+msgstr "WorkItem|작업 삭제"
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr "WorkItem|작업 소개"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "WorkItem|ìž‘ì—…ì— ëŒ€í•´ 알아보기"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "WorkItem|ìž‘ì—…ì„ ìƒì„±í•  ë•Œ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "WorkItem|ìž‘ì—…ì„ ì‚­ì œí•  ë•Œ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 "WorkItem|하위 ìž‘ì—…ì„ ì¶”ê°€í•˜ëŠ” ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr "WorkItem|ìžì‹ì„ ìƒì„±í•˜ëŠ” ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
+
msgid "WorkItem|Something went wrong while updating the work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr "WorkItem|ìž‘ì—… ì‚­ì œë¨"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr "WorkItem|작업 항목"
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "%{project_name} ì— ìƒˆ 회ì›ì„ 초대하거나 다른 ê·¸ë£¹ì„ ì´ˆëŒ€í•  수 있습니다."
@@ -43938,9 +44454,6 @@ msgstr "%{project_name} ì— ìƒˆ 회ì›ì„ 초대하거나 다른 ê·¸ë£¹ì„ ì´ˆëŒ
msgid "You can invite a new member to %{project_name}."
msgstr "%{project_name} ì— ìƒˆ 회ì›ì„ 초대할 수 있습니다."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "%{strong_start}%{group_name}%{strong_end} ì— ìƒˆ 회ì›ì„ 초대할 수 있습니다."
-
msgid "You can invite another group to %{project_name}."
msgstr "%{project_name} ì— ë‹¤ë¥¸ ê·¸ë£¹ì„ ì´ˆëŒ€í•  수 있습니다.."
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 "ì´ë¯¸ ì¼íšŒìš© ì¸ì¦ê¸°ë¥¼ ì´ìš©í•˜ì—¬ ì´ì¤‘ ì¸ì¦ì„ 활성화했습니다. 다른 기기를 등ë¡í•˜ë ¤ë©´ ì´ì¤‘ ì¸ì¦ì„ 먼저 비활성화해야 합니다."
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,8 +44915,8 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
-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 "ê·€í•˜ì˜ %{strong}%{plan_name}%{strong_close} 구ë…ì€ %{strong}%{expires_on}%{strong_close}ì— ë§Œë£Œë©ë‹ˆë‹¤. 갱신하지 않으면 %{strong}%{downgrades_on}%{strong_close}ì— ìœ ë£Œ ê¸°ëŠ¥ì— ì•¡ì„¸ìŠ¤í•  수 없게 ë©ë‹ˆë‹¤. ê·¸ 날짜 ì´í›„ì—는 ì´ìŠˆë¥¼ ìƒì„±í•˜ê±°ë‚˜ 병합 요청 ë“±ì˜ ë‹¤ë¥¸ ë§Žì€ ê¸°ëŠ¥ì„ ì‚¬ìš©í•  수 없습니다."
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr ""
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+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] ""
+
msgid "Your groups"
msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "구ë…ì´ %{expires_on}ì— ë§Œë£Œë©ë‹ˆë‹¤."
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
msgstr ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr "ì—°ê²°ëœ ë¶€ëª¨ëŠ” 기밀ì´ë©° ê¸°ë°€ì´ ì•„ë‹Œ ìžë…€ë¥¼ 가질 수 없습니다."
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
+msgstr "ciReport|%{scanner}ê°€ 새로운 잠재 %{vulnStr}를 %{boldStart}%{number}%{boldEnd} ì—ì„œ íƒì§€í•¨"
+
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
msgstr ""
+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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr "ciReport|모든 ì´ë¯¸ì§€"
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr "ci_database"
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr "커밋ë¨"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr "ê¸°ë°€ì´ ì•„ë‹Œ ìžì‹ì´ 있는 경우 기밀 부모를 사용할 수 없습니다."
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr "example.com"
+msgid "exceeds maximum length (100 usernames)"
+msgstr "최대 ê¸¸ì´ ì´ˆê³¼ (ì‚¬ìš©ìž ì´ë¦„ 100ê°œ)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "그룹"
@@ -45611,6 +46138,9 @@ msgstr "https://나ì˜-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr "main_database"
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "소스 브랜치 삭제"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "ë°°í¬ í†µê³„ëŠ” ì•„ì§ ì‚¬ìš©í•  수 없습니다."
@@ -45960,9 +46484,6 @@ msgstr "닫히지 ì•ŠìŒ"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "ë°°í¬ í†µê³„ë¥¼ ë¡œë“œí•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -45997,11 +46518,8 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr "머지"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
-msgstr ""
+msgstr "mrWidget|병합 차단ë¨: 요구ë˜ëŠ” 모든 승ì¸ì´ 제공ë˜ì–´ì•¼ 합니다."
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "머지:"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì—ˆìŠµë‹ˆë‹¤."
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì§€ 않았습니다."
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "소스 브랜치가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr "저장소:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr "ì—­í• ì˜ ê¸°ë³¸ 액세스 ìˆ˜ì¤€ì´ ë©¤ë²„ì‹­ì˜ ì•¡ì„¸ìŠ¤ 수준과 ì¼ì¹˜í•˜ì§€ 않습니다."
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,14 +47078,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
-msgstr ""
+msgid "the following epics"
+msgstr "ë‹¤ìŒ ì—픽"
-msgid "the following incident(s) or issue(s)"
-msgstr ""
+msgid "the following incidents or issues"
+msgstr "ë‹¤ìŒ ì¸ì‹œë˜íŠ¸ í˜¹ì€ ì´ìŠˆ"
-msgid "the following issue(s)"
-msgstr ""
+msgid "the following issues"
+msgstr "ë‹¤ìŒ ì´ìŠˆ"
msgid "the wiki"
msgstr ""
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr "합계는 %{size} 보다 작거나 같아야 함"
+
msgid "triggered"
msgstr ""
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 46948375dd1..3ddac00b5c3 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index d2da2dcfed0..3d2e13e3701 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-07-14 17:11\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index ccacc8594a7..1ab9d4fac70 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-07-14 17:09\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -664,8 +667,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -859,6 +862,9 @@ 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 ""
@@ -910,6 +916,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -922,13 +931,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1046,6 +1055,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2481,6 +2501,9 @@ 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 ""
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index bbdb8af48a8..bb0d0640262 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-07-14 17:10\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ml_IN/gitlab.po b/locale/ml_IN/gitlab.po
index 13516539a6a..ee614356863 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 596726bc6c7..4b41257f19f 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-07-14 17:10\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 0ab69246777..309a49f40b7 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-07-14 17:13\n"
+"PO-Revision-Date: 2022-08-12 18:07\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -71,7 +71,7 @@ msgid "#%{issueIid} (closed)"
msgstr "#%{issueIid} (lukket)"
msgid "#general, #development"
-msgstr ""
+msgstr "#general, #development"
msgid "%d Alert"
msgid_plural "%d Alerts"
@@ -120,18 +120,18 @@ msgstr[1] ""
msgid "%d additional assignee"
msgid_plural "%d additional assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ekstra tilordnet"
+msgstr[1] "%d ekstra tilordnede"
msgid "%d additional commenter"
msgid_plural "%d additional commenters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ekstra kommentator"
+msgstr[1] "%d ekstra kommentatorer"
msgid "%d additional committer"
msgid_plural "%d additional committers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ekstra committer"
+msgstr[1] "%d ekstra committere"
msgid "%d approver"
msgid_plural "%d approvers"
@@ -145,8 +145,8 @@ msgstr[1] "%d godkjennere (du har godkjent)"
msgid "%d assigned issue"
msgid_plural "%d assigned issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tildelt sak"
+msgstr[1] "%d tildelte saker"
msgid "%d changed file"
msgid_plural "%d changed files"
@@ -365,8 +365,8 @@ msgstr[1] "%d prosjekter valgt"
msgid "%d remaining"
msgid_plural "%d remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d gjenstående"
+msgstr[1] "%d gjenstående"
msgid "%d reply"
msgid_plural "%d replies"
@@ -420,23 +420,23 @@ msgstr[1] "%d sårbarheter avvist"
msgid "%d vulnerability set to confirmed"
msgid_plural "%d vulnerabilities set to confirmed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d sårbarhet satt til bekreftet"
+msgstr[1] "%d sårbarheter satt til bekreftet"
msgid "%d vulnerability set to dismissed"
msgid_plural "%d vulnerabilities set to dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d sårbarhet satt til avvist"
+msgstr[1] "%d sårbarheter satt til avvist"
msgid "%d vulnerability set to needs triage"
msgid_plural "%d vulnerabilities set to needs triage"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d sårbarhet satt til å trenge triage"
+msgstr[1] "%d sårbarheter satt til å trenge triage"
msgid "%d vulnerability set to resolved"
msgid_plural "%d vulnerabilities set to resolved"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d sårbarhet satt til oppklart"
+msgstr[1] "%d sårbarheter satt til oppklart"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
@@ -452,14 +452,17 @@ msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} og %{openOrClose} %{noteable}"
msgid "%{actionText} & close %{noteable}"
-msgstr ""
+msgstr "%{actionText} og lukk %{noteable}"
msgid "%{actionText} & reopen %{noteable}"
-msgstr ""
+msgstr "%{actionText} og gjenåpne %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} er et ugyldig IP-adresseområde"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} klonet %{original_issue} til %{new_issue}."
@@ -473,7 +476,7 @@ msgid "%{authorsName}'s thread"
msgstr "%{authorsName} sin tråd"
msgid "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
-msgstr ""
+msgstr "%{author} ba om å flette %{source_branch}%{copy_button} inn i %{target_branch} %{created_at}"
msgid "%{board_target} not found"
msgstr "%{board_target} ble ikke funnet"
@@ -500,7 +503,7 @@ msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or
msgstr ""
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} forfattet for %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
msgstr ""
@@ -508,10 +511,10 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} fullført vektlegging"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} av %{count} oppgave fullført"
-msgstr[1] "%{completedCount} av %{count} oppgaver fullført"
+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 "%{completedWeight} av %{totalWeight} vektlegging fullført"
@@ -614,7 +617,7 @@ 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 ""
+msgstr "%{docs_link_start}Hva er 2-trinnsautentisering?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (Forbi måldatoen)"
@@ -691,6 +694,9 @@ msgstr "%{integrations_link_start}Integrasjoner%{link_end} lar deg gjøre tredje
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} vil bli fjernet! Er du sikker?"
+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 ""
@@ -701,7 +707,7 @@ msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr "%{issuesSize} med en grense på %{maxIssueCount}"
msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
-msgstr ""
+msgstr "%{italic_start}Hva er nytt%{italic_end} er inaktiv og kan ikke vises."
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
msgstr "%{itemsCount} saker med en grense på %{maxIssueCount}"
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Metode:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Navnefelt:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Skanner:%{labelEnd} %{scanner}"
@@ -752,6 +761,9 @@ msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr "%{labelStart}Alvorlighet:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
+msgstr "%{labelStart}Verktøy:%{labelEnd} %{reportType}"
+
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
@@ -760,14 +772,11 @@ msgstr "%{labelStart}Uendret svar:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} utilgjengelig"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 time"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} er en gratis, automatisert og åpen sertifikatmyndighet (CA) som utsteder digitale sertifikater for å aktivere HTTPS (SSL/TLS) for nettsteder."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
msgstr "%{level_name} er ikke tillatt i en %{group_level_name}-gruppe."
@@ -779,10 +788,10 @@ msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title
msgstr "%{link_start}Fjern %{draft_snippet} prefiksen%{link_end} fra tittelen for å tillate at denne fletteforespørselen blir innflettet når den er klar."
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
-msgstr ""
+msgstr "%{link_start}Start tittelen med %{draft_snippet}%{link_end} for å hindre at et utkast til sammenslåingsforespørsel benyttes før den er klar."
msgid "%{listToShow}, and %{awardsListLength} more"
-msgstr ""
+msgstr "%{listToShow}, og %{awardsListLength} til"
msgid "%{location} is missing required keys: %{keys}"
msgstr "%{location} mangler nødvendige nøkler: %{keys}"
@@ -806,7 +815,7 @@ msgid "%{milliseconds}ms"
msgstr "%{milliseconds}ms"
msgid "%{minutesUsed} minutes"
-msgstr ""
+msgstr "%{minutesUsed} minutter"
msgid "%{model_name} not found"
msgstr "%{model_name} ble ikke funnet"
@@ -833,7 +842,7 @@ msgid "%{name} is already being used for another emoji"
msgstr "%{name} brukes allerede for en annen emoji"
msgid "%{name} is reserved for %{type} report type"
-msgstr ""
+msgstr "%{name} er reservert for %{type}-rapporttypen"
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} er planlagt for %{action}"
@@ -851,7 +860,7 @@ msgid "%{name}, confirm your email address now!"
msgstr "%{name}, vennligst bekreft e-postadressen din nå!"
msgid "%{name}: %{resultsString}"
-msgstr ""
+msgstr "%{name}: %{resultsString}"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
@@ -876,12 +885,24 @@ msgstr "%{openedEpics} åpne, %{closedEpics} lukket"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} åpne, %{closedIssues} lukket"
-msgid "%{percentageUsed}%% used"
+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 "%{percentage}%% issues closed"
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
msgstr ""
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{percentageUsed}%% used"
+msgstr "%{percentageUsed}%% brukt"
+
+msgid "%{percentage}%% issues closed"
+msgstr "%{percentage}%% saker lukket"
+
msgid "%{percentage}%% weight completed"
msgstr "%{percentage}%% vektlegging fullført"
@@ -898,13 +919,13 @@ msgid "%{placeholder} is not a valid theme"
msgstr "%{placeholder} er ikke et gyldig tema"
msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
-msgstr ""
+msgstr "%{policy_link} (varsler etter %{elapsed_time} minutt med mindre %{status})"
msgid "%{project_name}"
-msgstr ""
+msgstr "%{project_name}"
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 ""
+msgstr "%{project_path} er et prosjekt som du kan bruke til å legge til en README til GitLab-profilen din. Opprett et offentlig prosjekt og initialiser kodelageret med en README for å komme i gang. %{help_link_start}Lær mer.%{help_link_end}"
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} kan ikke bli lagt til: %{error}"
@@ -924,7 +945,7 @@ msgid "%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnM
msgstr "%{reportType} oppdaget %{totalStart}%{total}%{totalEnd} potensial %{vulnMessage}"
msgid "%{reportType} detected no %{totalStart}new%{totalEnd} vulnerabilities."
-msgstr ""
+msgstr "%{reportType} oppdaget ingen %{totalStart}nye%{totalEnd} sårbarheter."
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}."
msgstr "%{retryButtonStart}Prøv igjen%{retryButtonEnd} eller %{newFileButtonStart}legg ved en ny fil%{newFileButtonEnd}."
@@ -936,10 +957,10 @@ msgid "%{rotation} has been recalculated with the remaining participants. Please
msgstr ""
msgid "%{runner} created %{timeago}"
-msgstr ""
+msgstr "%{runner} opprettet %{timeago}"
msgid "%{scope} results for term '%{term}'"
-msgstr ""
+msgstr "%{scope} resultater for begrepet '%{term}'"
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] "%{securityScanner}-resultatet er ikke tilgjengelig fordi en rørledning ikke er kjørt siden den ble aktivert. %{linkStart}Kjør en rørledning%{linkEnd}"
msgstr[1] "%{securityScanner}-resultater er ikke tilgjengelige fordi en rørledning ikke er kjørt siden den ble aktivert. %{linkStart}Kjør en rørledning%{linkEnd}"
+msgid "%{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 "%{size} %{unit}"
@@ -990,10 +1021,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
-msgstr ""
-
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
+msgstr "%{strongOpen}!%{strongClose} SAML-gruppelenker kan føre til at GitLab automatisk fjerner medlemmer fra grupper."
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1024,7 +1052,7 @@ msgstr[0] "%{strong_start}%{count} medlem%{strong_end} må godkjenne sammenslåi
msgstr[1] "%{strong_start}%{count} medlemmer%{strong_end} må godkjenne sammenslåing. Alle med «Utvikler»-rollen eller høyere kan godkjenne."
msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
-msgstr ""
+msgstr "%{strong_start}%{human_size}%{strong_end} prosjektlagring"
msgid "%{strong_start}%{project_name}%{strong_end} is a personal project, so you can’t upgrade to a paid plan or start a free trial to lift these limits. We recommend %{move_to_group_link}moving this project to a group%{end_link} to unlock these options. You can %{manage_members_link}manage the members of this project%{end_link}, but don’t forget that all unique members in your personal namespace %{strong_start}%{namespace_name}%{strong_end} count towards total seats in use."
msgstr ""
@@ -1061,7 +1089,7 @@ 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 ""
+msgstr "%{timebox_type} støtter ikke utbrenningskart"
msgid "%{timebox_type} must have a start and due date"
msgstr "%{timebox_type} må ha start- og forfallsdato"
@@ -1088,7 +1116,7 @@ msgid "%{total_warnings} warning(s) found:"
msgstr "%{total_warnings} advarsel(er) funnet:"
msgid "%{total} remaining issue weight"
-msgstr ""
+msgstr "%{total} saksvekt gjenstår"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advarsler funnet: viser første %{warningsDisplayed}"
@@ -1103,19 +1131,19 @@ msgid "%{userName}'s avatar"
msgstr "%{userName} sin avatar"
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) ble fjernet fra %{rotation} i %{schedule} i %{project}. "
msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project_link}: "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) ble fjernet fra følgende eskaleringspolicyer i %{project_link}: "
msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project}:"
-msgstr ""
+msgstr "%{user_name} (%{user_username}) ble fjernet fra følgende eskaleringspolicyer i %{project}:"
msgid "%{user_name} profile page"
msgstr "%{user_name} sin profilside"
msgid "%{username} changed the draft status of merge request %{mr_link}"
-msgstr ""
+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}:"
@@ -1148,7 +1176,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} lar deg sende varsler til nettapplikasjoner som svar på hendelser i en gruppe eller et prosjekt. Vi anbefaler at du bruker en %{integrations_link_start}integrasjon%{link_end} som det foretrukne fremfor en webhook."
msgid "%{widget} options"
-msgstr ""
+msgstr "%{widget} alternativer"
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "%{wildcards_link_start}Jokertegn%{wildcards_link_end} slik som %{code_tag_start}v*%{code_tag_end} eller %{code_tag_start}*-release%{code_tag_end} er støttet."
@@ -1181,7 +1209,7 @@ msgid "'%{name}' Value Stream deleted"
msgstr "'%{name}' Verdistrøm slettet"
msgid "'%{name}' Value Stream saved"
-msgstr ""
+msgstr "'%{name}' verdistrøm lagret"
msgid "'%{source}' is not a import source"
msgstr "'%{source}' er ikke en importkilde"
@@ -1204,7 +1232,7 @@ msgid "(+%{count}&nbsp;rules)"
msgstr "(+%{count}&nbsp;regler)"
msgid "(Group Managed Account)"
-msgstr ""
+msgstr "(Gruppestyrt konto)"
msgid "(No changes)"
msgstr "(Ingen endringer)"
@@ -1222,13 +1250,13 @@ msgid "(expired)"
msgstr "(utløpt)"
msgid "(leave blank if you don't want to change it)"
-msgstr ""
+msgstr "(la stå tomt hvis du ikke vil endre det)"
msgid "(max size 15 MB)"
msgstr "(maks størrelse 15 MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(valgfritt)"
msgid "(removed)"
msgstr "(fjernet)"
@@ -1238,17 +1266,17 @@ msgstr "(tilbakekalt)"
msgid "(squashes %d commit)"
msgid_plural "(squashes %d commits)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "(squash %d commit)"
+msgstr[1] "(squasher %d commits)"
msgid "(this user)"
msgstr "(denne brukeren)"
msgid "(we need your current password to confirm your changes)"
-msgstr ""
+msgstr "(vi trenger ditt nåværende passord for å bekrefte endringene dine)"
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* Alle tider er i UTC med mindre annet er angitt"
msgid "*Required"
msgstr "*Obligatorisk"
@@ -1301,7 +1329,7 @@ msgid "- Available to run jobs."
msgstr ""
msgid "- Create or close an issue."
-msgstr ""
+msgstr "- Opprett eller lukk en sak"
msgid "- Create, update, or delete a merge request."
msgstr ""
@@ -1324,7 +1352,7 @@ msgid "- Push code to the repository."
msgstr ""
msgid "- Select -"
-msgstr ""
+msgstr "- Velg -"
msgid "- User"
msgid_plural "- Users"
@@ -1335,7 +1363,7 @@ msgid "- View the last_activity_at attribute for %{project_name} using the Proje
msgstr ""
msgid "- of - issues closed"
-msgstr ""
+msgstr "- av - saker lukket"
msgid "- of - weight completed"
msgstr "- av - vektlegging fullført"
@@ -1350,7 +1378,7 @@ msgid "/"
msgstr "/"
msgid "/day"
-msgstr ""
+msgstr "/dag"
msgid "0 bytes"
msgstr "0 byte"
@@ -1485,7 +1513,7 @@ msgid "1000+"
msgstr "1000+"
msgid "192.168.0.0/24 or 2001:0DB8:1234::/48"
-msgstr ""
+msgstr "192.168.0.0/24 eller 2001:0DB8:1234::/48"
msgid "1st contribution!"
msgstr "Første bidrag!"
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Registrert den"
-msgid "3 days"
-msgstr "3 dager"
-
msgid "3 hours"
msgstr "3 timer"
-msgid "30 days"
-msgstr "30 dager"
-
msgid "30 minutes"
msgstr "30 minutter"
@@ -1530,14 +1552,11 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Ta kontakt med din GitLab-administrator hvis du mener dette er en feil."
msgid "409|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "409|Vennligst kontakt din GitLab-administrator hvis du tror dette er en feil."
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 dager"
-
msgid "8 hours"
msgstr "8 timer"
@@ -1602,7 +1621,7 @@ msgid "A file with '%{file_name}' already exists in %{branch} branch"
msgstr "En fil med '%{file_name}' finnes allerede i %{branch}-grenen"
msgid "A file with this name already exists."
-msgstr ""
+msgstr "En fil med dette navnet eksisterer allerede."
msgid "A group is a collection of several projects"
msgstr "En gruppe er en samling av flere prosjekter"
@@ -1647,7 +1666,7 @@ msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
msgstr ""
msgid "A page with that title already exists"
-msgstr ""
+msgstr "En side med den tittelen finnes allerede"
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr ""
@@ -1839,7 +1858,7 @@ msgid "About this feature"
msgstr "Om denne funksjonen"
msgid "About your company"
-msgstr ""
+msgstr "Om selskapet"
msgid "Abuse Reports"
msgstr "Rapporter over misbruk"
@@ -2085,7 +2104,7 @@ msgid "Add LICENSE"
msgstr "Legg til LICENSE"
msgid "Add License"
-msgstr ""
+msgstr "Legg til lisens"
msgid "Add New Site"
msgstr "Legg til nytt nettsted"
@@ -2100,7 +2119,7 @@ msgid "Add a %{type}"
msgstr "Legg til en %{type}"
msgid "Add a GCP region"
-msgstr ""
+msgstr "Legg til en GCP-region"
msgid "Add a GPG key"
msgstr "Legg til en GPG-nøkkel"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Legg til en punktliste"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Legg til en sammenklappbar seksjon"
@@ -2153,11 +2175,8 @@ msgstr ""
msgid "Add a table"
msgstr "Legg til ny tabell"
-msgid "Add a task list"
-msgstr "Legg til en oppgaveliste"
-
msgid "Add a title..."
-msgstr ""
+msgstr "Legg til en tittel …"
msgid "Add a to do"
msgstr "Legg til en oppgave"
@@ -2183,9 +2202,6 @@ msgstr "Legg til godkjenningsregel"
msgid "Add approvers"
msgstr "Legg til godkjennere"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2199,7 +2215,7 @@ msgid "Add comment to design"
msgstr "Legg til kommentar til design"
msgid "Add comment..."
-msgstr ""
+msgstr "Legg til kommentar …"
msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
msgstr ""
@@ -2231,6 +2247,9 @@ msgstr "Legg til miljø"
msgid "Add existing confidential %{issuableType}"
msgstr "Legg til eksisterende konfidensiell %{issuableType}"
+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 ""
@@ -2265,7 +2284,7 @@ msgid "Add or subtract spent time"
msgstr "Legg til eller trekk fra brukt tid"
msgid "Add people"
-msgstr ""
+msgstr "Legg til personer"
msgid "Add previously merged commits"
msgstr "Legg til tidligere innflettede commiter"
@@ -2415,7 +2434,7 @@ msgid "Adds %{labels} %{label_text}."
msgstr "Legger til %{labels} %{label_text}."
msgid "Adds a Zoom meeting."
-msgstr ""
+msgstr "Legger til et Zoom-møte."
msgid "Adds a to do."
msgstr "Legger til en oppgave."
@@ -2424,7 +2443,7 @@ msgid "Adds an issue to an epic."
msgstr "Legger til en sak i en epos."
msgid "Adds email participant(s)."
-msgstr ""
+msgstr "Legger til e-postdeltaker(e)."
msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
msgstr ""
@@ -3381,7 +3400,7 @@ 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 "Akismet-API-nøkkel"
@@ -3755,6 +3774,9 @@ msgstr "Alle grener"
msgid "All changes are committed"
msgstr "Alle endringer er loggført"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "Alle e-postadressene vil bli brukt til å identifisere dine commiter."
@@ -3765,7 +3787,7 @@ msgid "All groups and projects"
msgstr "Alle grupper og prosjekter"
msgid "All issues"
-msgstr ""
+msgstr "Alle saker"
msgid "All issues for this milestone are closed."
msgstr "Alle saker for denne milepælen er lukket."
@@ -3900,7 +3922,7 @@ msgid "Already blocked"
msgstr "Allerede blokkert"
msgid "Already have login and password?"
-msgstr ""
+msgstr "Har du allerede brukernavn og passord?"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ msgstr "En feill oppstod under innhenting av autofullføring av prosjekter."
msgid "An error occurred while fetching reference"
msgstr ""
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr "Det oppstod en feil under innhenting av etiketter. Prøv søket på nytt."
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 "Lagre endringer"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 "example.org"
@@ -4764,28 +4807,31 @@ msgstr "MÃ¥lgren"
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 "Godkjenninger er valgfrie."
@@ -4830,9 +4879,6 @@ msgstr "Godkjente den nåværende fletteforespørselen."
msgid "Approved-By"
msgstr "Godkjent av"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Godkjenner"
@@ -4885,7 +4931,7 @@ msgid "Are you ABSOLUTELY SURE you wish to remove this group?"
msgstr "Er du HELT SIKKER på at du vil fjerne denne gruppen?"
msgid "Are you absolutely sure?"
-msgstr ""
+msgstr "Er du helt sikker?"
msgid "Are you sure that you want to archive this project?"
msgstr "Er du sikker på at du vil arkivere dette prosjektet?"
@@ -4933,7 +4979,7 @@ msgid "Are you sure you want to delete this device? This action cannot be undone
msgstr "Er du sikker på at du vil slette denne enheten? Denne handlingen kan ikke angres på."
msgid "Are you sure you want to delete this label?"
-msgstr ""
+msgstr "Er du sikker på at du vil slette dette stempelet?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Er du sikker på at du vil slette denne rørledningsplanleggingen?"
@@ -4974,7 +5020,7 @@ msgid "Are you sure you want to re-deploy this environment?"
msgstr "Er du sikker på at du vil distribuere dette miljøet på nytt?"
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "Er du sikker på at du vil indeksere på nytt?"
msgid "Are you sure you want to remove %{email}?"
msgstr ""
@@ -5133,7 +5179,7 @@ msgid "Assign reviewer(s)"
msgstr "Tilordne godkjenner(e)"
msgid "Assign severity"
-msgstr ""
+msgstr "Tilordne alvorlighetsgrad"
msgid "Assign some issues to this milestone."
msgstr "Tildel noen saker til denne milepælen."
@@ -5145,7 +5191,7 @@ msgid "Assign to commenting user"
msgstr "Tilordne til den kommenterende brukeren"
msgid "Assign to me"
-msgstr ""
+msgstr "Tilordne meg"
msgid "Assigned %{assignee_users_sentence}."
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr "Tilordnet meg"
msgid "Assigned to you"
msgstr "Tilordnet deg"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Tilordnet"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr "I faresonen"
-msgid "Attach a file"
-msgstr "Legg ved en fil"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5232,12 +5275,6 @@ msgstr[1] "Legger ved %d filer"
msgid "Attaching the file failed."
msgstr "Vedlegging av filen mislyktes."
-msgid "Attention"
-msgstr "Oppmerksomhet"
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "Aug"
@@ -5571,8 +5635,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Automatisk oppklart"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Oppdater automatisk dette prosjektets grener og etiketter fra oppstrømskodelageret hver time."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Notis"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ msgstr "Forleng prøveperioden"
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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr "Eksporter liste"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr "Gruppeinvitasjon"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ 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|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr ""
+
+msgid "BranchRules|Allowed to merge"
+msgstr ""
+
+msgid "BranchRules|Allowed to push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Grener"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Aktiv"
@@ -6916,13 +7027,13 @@ msgid "By default, all projects and groups will use the global notifications set
msgstr ""
msgid "By month"
-msgstr ""
+msgstr "Etter måned"
msgid "By quarter"
-msgstr ""
+msgstr "Etter kvartal"
msgid "By week"
-msgstr ""
+msgstr "Etter uke"
msgid "ByAuthor|by"
msgstr "av"
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr "Kan ikke finne variabel: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr "Kan ikke laste inn \"mermaid\"-modul: %{err}"
-
msgid "Can't scan the code?"
msgstr "Kan du ikke skanne koden?"
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8235,7 +8340,7 @@ msgid "Close %{issueType}"
msgstr "Lukk %{issueType}"
msgid "Close %{noteable}"
-msgstr ""
+msgstr "Lukk %{noteable}"
msgid "Close %{tabname}"
msgstr "Lukk %{tabname}"
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -9269,7 +9389,7 @@ msgid "Commands did not apply"
msgstr ""
msgid "Comment"
-msgstr "Kommentar"
+msgstr "Kommenter"
msgid "Comment & resolve thread"
msgstr "Kommenter og oppklar tråden"
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr "Opprett %{type}"
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Opprett ny katalog"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Kritiske sårbarheter til stede"
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr "DAST-oppsett"
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Dato"
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr "Slett fil"
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr "Slett prosjekt"
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr "Slett rad"
@@ -12388,6 +12538,15 @@ 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 "'%{name}' Verdistrøm slettet"
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr "Sletter"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Distribuering"
msgstr[1] "Distribueringer"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Domene"
@@ -14089,9 +14245,6 @@ msgstr "Ingen. Velg navneområder å indeksere."
msgid "Elastic|None. Select projects to index."
msgstr "Ingen. Velg prosjekter å indeksere."
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "E-post"
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr "Sluttid"
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr "Feil under opprettelse av utdrag"
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15845,7 +15998,7 @@ msgid "Failed to load milestones. Please try again."
msgstr "Mislyktes i å laste inn milepæler. Vennligst prøv igjen."
msgid "Failed to load projects"
-msgstr ""
+msgstr "Mislyktes i å laste inn prosjekter"
msgid "Failed to load related branches"
msgstr "Klarte ikke å laste inn relaterte grener"
@@ -15889,24 +16042,21 @@ msgstr "Mislyktes i å fjerne et Zoom-møte"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Mislyktes i å fjerne speilvendingen."
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to remove timelog"
+msgstr ""
+
msgid "Failed to remove user identity."
msgstr "Mislyktes i å fjerne brukeridentitet."
msgid "Failed to remove user key."
msgstr "Mislyktes i å fjerne brukernøkkel."
-msgid "Failed to request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr ""
@@ -15922,6 +16072,9 @@ msgstr "Mislyktes i å lagre preferanser (%{error_message})."
msgid "Failed to save preferences."
msgstr "Mislyktes i å lagre preferanser."
+msgid "Failed to save timelog"
+msgstr ""
+
msgid "Failed to set due date because the date format is invalid."
msgstr ""
@@ -15967,14 +16120,11 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr "Raskere utgivelser. Bedre kode. Mindre smerte."
msgid "Favicon"
-msgstr ""
+msgstr "Favicon"
msgid "Favicon was successfully removed."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "Feb"
msgid "February"
msgstr "Februar"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr "Fra %{code_open}%{source_title}%{code_close} til"
msgid "From %{providerTitle}"
msgstr "Fra %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr "Generisk"
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr "%{component} verifisert"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} kan ikke være tom"
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr "Pågår"
-msgid "Geo|In sync"
-msgstr "Synkronisert"
-
msgid "Geo|Internal URL"
msgstr "Intern URL"
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Ikke synkronisert enda"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr "Usunn"
msgid "Geo|Unknown"
msgstr "Ukjent"
-msgid "Geo|Unknown state"
-msgstr "Ukjent tilstand"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr "Gitlab-sak"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr "GitLab-sider"
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr "GitLab-commit"
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Sertifikat: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr "Sett opp sider"
@@ -17614,6 +17776,9 @@ msgstr "Lagre endringer"
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 "Noe gikk galt under innhenting av Let's Encrypt-sertifikatet for %{domain}. Gå til dine %{link_start}domenedetaljer%{link_end} for å prøve på nytt."
+msgid "GitLabPages|Start over"
+msgstr ""
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -17626,6 +17791,9 @@ msgstr ""
msgid "GitLabPages|Verified"
msgstr "Verifisert"
+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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17759,13 +17930,13 @@ msgid "GlobalSearch|Results updated. %{count} results available. Use the up and
msgstr "Resultatene er oppdatert. %{count} resultater tilgjengelig. Bruk ↑- og ↓-piltastene for å navigere i søkeresultatlisten, eller ENTER for å sende inn."
msgid "GlobalSearch|Search GitLab"
-msgstr ""
+msgstr "GlobalSearch|Søk på GitLab"
msgid "GlobalSearch|Search for projects, issues, etc."
-msgstr ""
+msgstr "GlobalSearch|Søk etter prosjekter, problemer, osv."
msgid "GlobalSearch|Search results are loading"
-msgstr ""
+msgstr "GlobalSearch|Søkeresultater lastes inn"
msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
msgstr "Det oppsto en feil under henting av forslag til autofullføring av søk."
@@ -17789,7 +17960,7 @@ msgid "GlobalSearch|group"
msgstr ""
msgid "GlobalSearch|in %{scope}"
-msgstr ""
+msgstr "GlobalSearch|i %{scope}"
msgid "GlobalSearch|project"
msgstr ""
@@ -17956,16 +18127,13 @@ msgstr "GÃ¥ til utdragene dine"
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18047,7 +18215,7 @@ msgid "Graph"
msgstr "Diagram"
msgid "GraphViewType|Job dependencies"
-msgstr ""
+msgstr "GraphViewType|Jobbavhengigheter"
msgid "GraphViewType|Show dependencies"
msgstr "Vis avhengigheter"
@@ -18187,9 +18355,6 @@ msgstr "Gruppenavigasjon"
msgid "Group overview content"
msgstr "Gruppeoversikts-innhold"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ msgstr ""
msgid "GroupSettings|Export group"
msgstr "Eksporter gruppe"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr ""
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr "Forhindre utgreining utenfor gruppen"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "Innstilling for forhindring av utgreining ble ikke lagret"
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ msgstr "Opprett gruppe"
msgid "GroupsNew|Create new group"
msgstr "Opprett ny gruppe"
+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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "Last opp fil"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "f.eks. h8d3f016698e …"
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "Retningslinje"
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr "Toppområdelogo"
@@ -19245,6 +19410,9 @@ msgstr "Opprinnelig alarm:"
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Historie"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ msgstr[1] "Importerer %d kodelagre"
msgid "Importing..."
msgstr "Importerer …"
+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 ""
@@ -19848,9 +20028,6 @@ msgstr "%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Franc
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr "Kodeeiere"
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr "Vanskelig"
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-msgstr "Har du et minutt?"
-
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr ""
msgid "InProductMarketing|Dynamic application security testing"
msgstr ""
-msgid "InProductMarketing|Easy"
-msgstr "Enkelt"
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr "Utforsk kraften til GitLab CI/CD"
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr "Nøytral"
-
msgid "InProductMarketing|No credit card required."
msgstr "Ingen bankkort behøves."
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr "Ta dine første skritt med GitLab"
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr "Veldig vanskelig"
-
-msgid "InProductMarketing|Very easy"
-msgstr "Veldig enkelt"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20392,7 +20539,7 @@ msgid "InProductMarketing|testing browser performance"
msgstr ""
msgid "InProductMarketing|unsubscribe"
-msgstr ""
+msgstr "InProductMarketing|avabonner"
msgid "InProductMarketing|update your preferences"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr "Kursiv tekst"
msgid "Iteration"
msgstr "Iterasjon"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Iterasjonen ble endret til"
@@ -21877,12 +22024,36 @@ msgstr "Iterasjonen ble oppdatert"
msgid "Iterations"
msgstr "Iterasjoner"
+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 "Legg til iterasjon"
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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr "Rediger iterasjon"
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr "Velg startdato"
msgid "Iterations|Start date"
msgstr "Startdato"
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Bla til bunn"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Bla til toppen"
@@ -22618,8 +22795,8 @@ msgstr "Nøkkel"
msgid "Key (PEM)"
msgstr "Nøkkel (PEM)"
-msgid "Key: %{key}"
-msgstr "Nøkkel: %{key}"
+msgid "Key:"
+msgstr ""
msgid "Keyboard shortcuts"
msgstr "Tastatursnarveier"
@@ -22886,15 +23063,9 @@ msgstr "IP-en ved nyligste pålogging:"
msgid "Last sign-in at:"
msgstr "Nyligst pålogget kl.:"
-msgid "Last successful sync"
-msgstr "Seneste vellykkede synkronisering"
-
msgid "Last successful update"
msgstr "Forrige vellykkede oppdatering"
-msgid "Last time checked"
-msgstr "Senest sjekket"
-
msgid "Last time verified"
msgstr "Senest verifisert"
@@ -23177,19 +23348,19 @@ 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 "Let's Encrypt er en gratis, automatisert og åpen sertifikatmyndighet (CA) som gir digitale sertifikater for å kunne aktivere HTTPS (SSL/TLS) på nettsteder. Lær mer om Let's Encrypt-oppsett ved å følge %{docs_link_start}dokumentasjonen på GitLab Pages%{docs_link_end}."
-msgid "Let's talk!"
-msgstr "La oss ta en prat!"
-
msgid "License Compliance"
msgstr "Lisensoverensstemmelse"
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,8 +23621,11 @@ msgstr "Lenkede e-postadresser (%{email_count})"
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Lenkede saker"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr ""
msgid "LinkedIn"
msgstr "Linkedin"
@@ -23462,6 +23636,48 @@ msgstr "LinkedIn:"
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 "Lenker"
@@ -23789,9 +24005,6 @@ msgstr "Manifest-importering"
msgid "Manual"
msgstr "Manuell"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ msgstr "Maksimal feltlengde"
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_whitelist}."
+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"
@@ -24403,13 +24616,13 @@ 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 ""
+msgstr "Innflettingen er forhindret: fletteforespørselen må merkes som klar. Den er fortsatt merket som et utkast."
msgid "Merge blocked: new changes were just added."
-msgstr ""
+msgstr "Innflettingen er blokkert: nye endringer ble nettopp lagt til."
msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
-msgstr ""
+msgstr "Innflettingen er forhindret: rørledningen må lykkes. Den venter på at en manuell jobb skal fortsette."
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr ""
@@ -24421,7 +24634,7 @@ msgid "Merge commit message"
msgstr "Innflettingscommit-melding"
msgid "Merge details"
-msgstr ""
+msgstr "Flettedetaljer"
msgid "Merge events"
msgstr "Flett hendelser"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr "Multi-prosjekt"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr "Logg ut og logg inn med en annen konto"
msgid "Need help?"
msgstr "Trenger du hjelp?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr "Ingen epos"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr "Ingen samsvarende resultater"
@@ -25964,9 +26171,6 @@ msgstr "Ingen artefakter ble funnet"
msgid "No assignee"
msgstr "Ingen er tilordnet"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "Ingen autentiseringsmetoder er satt opp."
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr "Normal tekst"
-msgid "Not Implemented"
-msgstr "Ikke implementert"
-
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 ""
@@ -26389,6 +26590,9 @@ 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 "Ingenting å forhåndsvise."
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{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|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ msgstr "OmniAuth"
msgid "On"
msgstr "Den"
+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 track"
msgstr "I rute"
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ msgstr "Mer informasjon"
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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr "Slett pakkeversjonen"
msgid "PackageRegistry|Delete package"
msgstr "Slett pakke"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr "Lær hvordan man %{noPackagesLinkStart}publiserer og deler pakkene dine%
msgid "PackageRegistry|License information located at %{link}"
msgstr "Lisensinformasjonen er hos %{link}"
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr "Manuelt publisert"
@@ -27674,9 +27906,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "NuGet-kommando"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr "Pakkeregister"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Pip-kommando"
@@ -27748,6 +27989,9 @@ msgstr "Vis PyPi-kommandoer"
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ msgstr ""
msgid "PackageRegistry|Unable to load package"
msgstr "Klarte ikke å laste inn pakke"
+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}, this operation is irreversible, 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 "npm"
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "Optimalisering av ytelsen"
@@ -28171,6 +28429,18 @@ msgstr "Personlige prosjekter"
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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Neste kjøring"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr "MÃ¥l"
msgid "PipelineSchedules|Variables"
msgstr "Variabler"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr "Eier"
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr "Mislyktes"
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr "Pågår"
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr "Manuelt"
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Bestått"
msgid "Pipeline|Pending"
msgstr "Avventer"
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Rørledning"
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr "Kjør rørledning"
@@ -28888,6 +29203,12 @@ msgstr "Etikettnavn"
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr "Variabler"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "Vis rørledning"
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr "Forrige"
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ msgstr ""
msgid "Project uploads"
msgstr "Prosjektopplastinger"
+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 ""
@@ -30085,6 +30421,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Prosjekt: %{name}"
+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 "Abonner"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 "eller gruppe"
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} vil være skrivbar for utviklere. Er du sikker?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Tillatt å distribuere"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Miljø"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+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 "Beskytt"
@@ -31528,6 +31897,12 @@ msgstr "Kodeforespørsler fra utgreininger er ikke støttet"
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 "Kjøp flere minutter"
@@ -31769,7 +32144,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 "Klar til å slås sammen av medlemmer som kan skrive til målgrenen."
msgid "Ready to merge!"
msgstr "Klar til å innflette!"
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr "Nylig brukt"
msgid "Reconfigure"
msgstr "Sett opp på nytt"
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr "Gjenopprettingskoder"
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr "Relaterte saker"
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] "Utgave"
msgstr[1] "Utgivelser"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "Fjern tilordnet"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Fjern avatar"
@@ -32190,7 +32559,7 @@ msgid "Remove due date"
msgstr "Fjern måldato"
msgid "Remove favicon"
-msgstr ""
+msgstr "Fjern favicon"
msgid "Remove file"
msgstr "Fjern fil"
@@ -32306,12 +32675,6 @@ msgstr "Fjernet alle stempler."
msgid "Removed an issue from an epic."
msgstr "Fjernet en sak fra et epos."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr "Fjerner alle stempler."
msgid "Removes an issue from an epic."
msgstr "Fjerner en sak fra et epos."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr "Svar …"
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Rapporter misbruk"
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr "SÃ¥rbarhet"
msgid "Reports|Vulnerability Name"
msgstr "SÃ¥rbarhetsnavn"
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "Ingen endrede testresultater"
@@ -32833,15 +33202,6 @@ msgstr "Be om tilgang"
msgid "Request a new one"
msgstr "Be om en ny en"
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr "Forespurt"
msgid "Requested %{time_ago}"
msgstr "Forespurt %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr "De forespurte tilstandene er ugyldige"
@@ -32960,6 +33308,9 @@ msgstr "Send på nytt"
msgid "Resend Request"
msgstr "Send forespørsel på nytt"
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "Send e-postbekreftelse på nytt"
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr "Forsøk igjen"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr "Kopier E-postadressen"
msgid "RightSidebar|Issue email"
msgstr "Sakens E-post"
-msgid "RightSidebar|adding a"
-msgstr "legge til en"
-
-msgid "RightSidebar|deleting the"
-msgstr "sletter"
-
msgid "Roadmap"
msgstr "Veikart"
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr "Egenskapsnavn"
msgid "Runners|Protected"
msgstr "Beskyttet"
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr "gruppe"
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr "satt på pause"
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr "delt"
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "Kjører"
@@ -33820,6 +34200,9 @@ msgstr "SAST-oppsett"
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "SSH-nøkkel"
@@ -33829,6 +34212,9 @@ msgstr "SSH-nøkler"
msgid "SSH Keys Help"
msgstr "SSH-nøkkelhjelp"
+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 ""
@@ -33907,6 +34293,21 @@ msgstr "Lagrer"
msgid "Saving project."
msgstr "Lagrer prosjekt."
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] "wiki-resultat"
msgstr[1] "wiki-resultater"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34286,6 +34693,9 @@ msgstr "Sikkerhetsoppsett"
msgid "Security Dashboard"
msgstr "Sikkerhetskontrollpanel"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Sikkerhetskontrollpanel"
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34845,7 +35261,7 @@ msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "SecurityReports|Kommentar redigert på '%{vulnerabilityName}'"
msgid "SecurityReports|Configure security testing"
msgstr ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr "Sak opprettet"
@@ -34955,6 +35374,15 @@ msgstr "Oi sann, noe ser ikke riktig ut."
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 "Prosjekt"
@@ -35309,9 +35737,6 @@ 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 "De valgte nivåene kan ikke brukes av ikke-administratorbrukere for grupper, prosjekter eller utdrag. Hvis det offentlige nivået er begrenset, er brukerprofilene bare synlige for påloggede brukere."
-msgid "Selected projects"
-msgstr "Utvalgte prosjekter"
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr "Tjenester"
-
msgid "Session ID"
msgstr "Økt-ID"
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr "Viser den nyeste versjonen"
msgid "Showing version #%{versionNumber}"
msgstr "Viser versjon â„–%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr "Antall pålogginger:"
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr "PÃ¥loggingsside"
@@ -36096,6 +36518,9 @@ msgstr "PÃ¥loggingsbegrensninger"
msgid "Sign-in text"
msgstr "PÃ¥loggingstekst"
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr "Løsning"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr "Noen endringer vises ikke"
@@ -36730,10 +37152,10 @@ msgid "Source branch"
msgstr "Kildegren"
msgid "Source branch will be deleted."
-msgstr ""
+msgstr "Kildegrenen vil bli slettet."
msgid "Source branch will not be deleted."
-msgstr ""
+msgstr "Kildegrenen vil ikke bli slettet."
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr "Kildegren: %{source_branch_open}%{source_branch}%{source_branch_close}"
@@ -37449,9 +37871,6 @@ msgstr "Trekker fra"
msgid "Succeeded"
msgstr "Lyktes"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "Aktivering vellykket"
@@ -37519,7 +37938,7 @@ msgid "SuggestedColors|Carrot orange"
msgstr "Gulrotsoransje"
msgid "SuggestedColors|Champagne"
-msgstr ""
+msgstr "GraphViewType|Champagne"
msgid "SuggestedColors|Charcoal grey"
msgstr "Koksgrå"
@@ -37537,10 +37956,10 @@ msgid "SuggestedColors|Dark coral"
msgstr ""
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "GraphViewType|Mørkegrønn"
msgid "SuggestedColors|Dark sea green"
-msgstr ""
+msgstr "GraphViewType|Mørkesjøgrønn"
msgid "SuggestedColors|Dark violet"
msgstr "Mørkefiolett"
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr "Støtteside-URL"
-msgid "Survey Response"
-msgstr "Undersøkelsessvar"
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr "Systemmåltall (Kubernetes)"
msgid "System output"
msgstr "System-utdata"
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr "Innholdsfortegnelse"
@@ -37973,6 +38392,9 @@ msgstr "Avbryt"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Opprett tag"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Rediger utgivelsesbeskrivelser"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Eksisterende greinnavn, etikett, eller commit-SHA"
@@ -38090,9 +38512,6 @@ msgstr "Oppgave-ID: %{elastic_task}"
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr "Tekststil"
msgid "Thank you for your business."
msgstr "Takk for handelen."
-msgid "Thank you for your feedback!"
-msgstr "Takk for din tilbakemelding!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Takk for rapporten din. En GitLab-administrator vil se nærmere på det innen kort tid."
@@ -38511,7 +38927,7 @@ msgid "Thank you for your support request! We are tracking your request as ticke
msgstr ""
msgid "Thanks for signing up to GitLab!"
-msgstr ""
+msgstr "Takk for at du registrerte deg på GitLab!"
msgid "Thanks for your purchase!"
msgstr "Takk for handelen!"
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ msgstr "Kodelageret må være tilgjengelig over %{code_open}http://%{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 "Kodelageret må være tilgjengelig over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} eller %{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 ""
+
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 ""
@@ -39068,6 +39484,9 @@ msgstr "Det er ingen arkiverte krav"
msgid "There are no archived test cases"
msgstr "Det er ingen arkiverte testtilfeller"
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr "Det er ingen endringer"
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Det oppstod en feil under fjerning av e-posten."
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "Det oppstod en feil med reCAPTCHA-en. Vennligst løs reCAPTCHA-en på nytt."
@@ -39560,6 +39973,9 @@ msgstr "Denne mappen"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "Dette domenet er ikke bekreftet. Du må bekrefte eierskapet før tilgang aktiveres."
+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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Dette kodelageret"
@@ -40229,6 +40651,9 @@ 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 "Tidsavbrudd"
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr "For å holde dette prosjektet gående, opprett en ny fletteforespørsel"
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr "GÃ¥ tilbake"
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ msgstr "Prøv å endre eller fjerne filtre."
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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Type"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "U2F-enheter (%{length})"
@@ -41133,6 +41564,9 @@ msgstr "Klarte ikke å laste inn forskjellen. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
+msgid "Unable to parse JSON"
+msgstr ""
+
msgid "Unable to parse the vulnerability report's options."
msgstr ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr "Ukjent format"
msgid "Unknown response text"
msgstr "Ukjent responstekst"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr "Ukjent bruker"
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr "Oppdaterer"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr "Oppdaterer …"
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr "Last opp en privat nøkkel til sertifikatet ditt"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Last opp fil"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr "Oppstrøms"
-msgid "Uptime"
-msgstr "Oppetid"
-
msgid "Upvotes"
msgstr "Plusstemmer"
@@ -41553,10 +41984,10 @@ msgstr "Bruk i nåværende periode"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ msgstr ""
msgid "Used"
msgstr "Brukt"
+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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "Brukeren ble vellykket fjernet fra prosjektet."
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "Brukeren ble vellykket oppdatert."
@@ -42126,6 +42580,9 @@ msgstr "Bot-aktivitet"
msgid "UserProfile|Contributed projects"
msgstr "Bidratte prosjekter"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "Rediger profil"
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr "Ubekreftet bruker"
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Vis alle"
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr "%{value}mnd"
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ msgstr "Verifiser oppsettet"
msgid "Version"
msgstr "Versjon"
+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 "Versjon %{versionNumber}"
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ msgstr "NÃ¥r du bruker %{code_open}http: //%{code_close} eller %{code_open}https
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 "NÃ¥r:"
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr "Opprett side"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr "Format"
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Du kan invitere et nytt medlem til %{project_name} eller invitere en annen gruppe."
@@ -44186,9 +44714,6 @@ msgstr "Du kan invitere et nytt medlem til %{project_name} eller invitere en ann
msgid "You can invite a new member to %{project_name}."
msgstr "Du kan invitere et nytt medlem til %{project_name}."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr "Du kan invitere en annen gruppe til %{project_name}."
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr "Du kan ikke få tilgang til denne råfilen. Vennligst vent et minutt."
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr "Du har ikke noen abonnementer enda"
@@ -44632,6 +45150,9 @@ 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 "Du har allerede aktivert 2-trinnsautentisering ved hjelp av éngangspassord-autentikatorer. For å kunne registrere en annen enhet, må du først deaktivere 2-trinnsautentisering."
@@ -44644,9 +45165,6 @@ msgstr "Du har avvist %{user}"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
msgstr "Ditt første prosjekt"
+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 "Dine grupper"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr "Søket ditt samsvarte ikke med noen commiter."
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr "tildel deg selv"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr "kl."
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr "%{reportType}: Innlasting førte til en feil"
msgid "ciReport|%{sameNum} same"
msgstr "%{sameNum} samme"
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Alle prosjekter"
@@ -45578,6 +46116,9 @@ msgstr "laster inn"
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr "lukket"
@@ -45605,6 +46146,9 @@ msgstr "forpliktet"
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr "laget av"
msgid "data"
msgstr "data"
-msgid "database"
-msgstr "database"
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45786,7 +46330,7 @@ msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
msgstr "for %{link_to_merge_request} med %{link_to_merge_request_source_branch}"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
+msgstr "for %{link_to_merge_request} med %{link_to_merge_request_source_branch} til %{link_to_merge_request_target_branch}"
msgid "for %{link_to_pipeline_ref}"
msgstr "for %{link_to_pipeline_ref}"
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr "gruppemedlemmer"
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "grupper"
@@ -45876,6 +46417,9 @@ msgstr "https://din-bitbucket-tjener"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr "%{language} (%{percent_translated}%% oversatt)"
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr "bilde-diff"
@@ -46052,6 +46596,9 @@ msgstr "laster"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "låst av %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "manual"
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 innflettings-commit"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Slett kildegrenen"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr "Lukket ikke"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46260,21 +46795,18 @@ msgid "mrWidget|Mark as ready"
msgstr "Merk som klar"
msgid "mrWidget|Members who can merge are allowed to add commits."
-msgstr ""
+msgstr "mrWidget|Medlemmer som kan flette, har lov til å legge til commiter."
msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "Flett"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
-msgstr ""
+msgstr "mrWidget|Innflettingen er forhindret: alle tråder må oppklares."
msgid "mrWidget|Merge blocked: denied licenses must be removed."
msgstr ""
@@ -46283,7 +46815,7 @@ msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this
msgstr ""
msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
-msgstr ""
+msgstr "mrWidget|Innflettingen er forhindret: flettekonflikter må oppklares."
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Flettet av"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Endringene ble flettet inn i"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Endringene ble ikke flettet inn i"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Kildegrenen har blitt slettet"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Kildegrenen ble slettet"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Denne fletteforespørsel ble ikke flettet automatisk"
@@ -46424,7 +46941,7 @@ msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or des
msgstr ""
msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
-msgstr ""
+msgstr "mrWidget|Brukere som kan skrive til kilde- eller målgrenene kan oppklare konfliktene."
msgid "mrWidget|What is a merge train?"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr "kodelagre"
msgid "repository:"
msgstr "kodelager:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr "tilfredsstilt"
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,14 +47367,14 @@ msgstr ""
msgid "the correct format."
msgstr "det riktige formatet."
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "de(n) følgende sak(en)"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr "wikien"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "utløst"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 93619c9eaaf..73809756b5a 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-07-14 17:10\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} wordt verwijderd! Weet je het zeker?"
+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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Branches"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/or_IN/gitlab.po b/locale/or_IN/gitlab.po
index cf45265727c..feb57e1c1c0 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-07-14 17:13\n"
+"PO-Revision-Date: 2022-08-12 18:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index e5fd64e0c34..06a0933a0d1 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-07-14 17:10\n"
+"PO-Revision-Date: 2022-08-12 18:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 72b70d4e745..a5d6f8e9f0f 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-07-14 17:08\n"
+"PO-Revision-Date: 2022-08-12 18:05\n"
msgid " %{start} to %{end}"
msgstr " %{start} do %{end}"
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr "%{address} nie jest prawidłowym zakresem adresów IP"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} sklonował(a) %{original_issue} do %{new_issue}."
@@ -664,12 +667,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} ukończonej wagi"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} z %{count} zadań ukończono"
-msgstr[1] "%{completedCount} z %{count} zadań ukończono"
-msgstr[2] "%{completedCount} z %{count} zadań ukończono"
-msgstr[3] "%{completedCount} z %{count} zadania ukończono"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "Ukończono %{completedWeight} z %{totalWeight} wagi"
@@ -859,6 +862,9 @@ msgstr "%{integrations_link_start}Integracje:%{link_end} pozwalają Ci użyć ap
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} zostanie usunięty! Jesteś pewny?"
+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 ""
@@ -910,6 +916,9 @@ msgstr "%{labelStart}Metoda:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Przestrzeń nazw:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Skaner:%{labelEnd} %{scanner}"
@@ -922,15 +931,15 @@ msgstr "%{labelStart}Ranga:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Zniezmodyfikowana odpowiedź:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} niedostępne"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -1046,6 +1055,18 @@ msgstr "%{openedEpics} otwarte, %{closedEpics} zamknięte"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} otwarte, %{closedIssues} zamknięte"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] "Wyniki %{securityScanner} są niedostępne, ponieważ potok nie zosta
msgstr[2] "Wyniki %{securityScanner} są niedostępne, ponieważ potok nie został uruchomiony od czasu jego włączenia. %{linkStart}Uruchom potok%{linkEnd}"
msgstr[3] "Wyniki %{securityScanner} jest niedostępnych, ponieważ potok nie został uruchomiony od czasu jego włączenia. %{linkStart}Uruchom potok%{linkEnd}"
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr "Dwustopniowe uwierzytelnianie (2FA)"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 dni"
-
msgid "3 hours"
msgstr "3 godziny"
-msgid "30 days"
-msgstr "30 dni"
-
msgid "30 minutes"
msgstr "30 minut"
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 dni"
-
msgid "8 hours"
msgstr "8 godzin"
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Dodaj listÄ™ wypunktowanÄ…"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr "Dodaj tabelÄ™"
-msgid "Add a task list"
-msgstr "Dodaj listę zadań"
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr "Dodaj regułę zatwierdzania"
msgid "Add approvers"
msgstr "Dodaj zatwierdzajÄ…cych"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Dodaj wiadomość rozgłoszeniową"
@@ -2481,6 +2501,9 @@ msgstr "Dodaj środowisko"
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 "Dodaj nagłówek i stopkę do e-maili. Należy pamiętać, że ustawienia kolorów będą stosowane tylko w interfejsie aplikacji"
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Wystąpił błąd podczas ładowania formularza tokenów dostępu, proszę, spróbuj ponownie."
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 "Zapisz zmiany"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 "domena.com"
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr "Wrażliwość"
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "brak zmienionych wyników testów"
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr "Harmonogram"
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr "Strona robotników."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr "Metryki systemowe (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 3e6cf2babe1..a7542a71150 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-07-14 19:57\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr " %{start} até %{end}"
@@ -370,8 +370,8 @@ msgstr[1] "%d restantes"
msgid "%d reply"
msgid_plural "%d replies"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resposta"
+msgstr[1] "%d respostas"
msgid "%d second"
msgid_plural "%d seconds"
@@ -460,6 +460,9 @@ msgstr "%{actionText} e reabrir %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} é uma faixa de IP inválida"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} clonou %{original_issue} para %{new_issue}."
@@ -508,10 +511,10 @@ msgstr "%{commit_author_link} criou %{commit_authored_timeago} e %{commit_commit
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} peso concluído"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} de %{count} tarefa concluída"
-msgstr[1] "%{completedCount} de %{count} tarefas concluídas"
+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 "%{completedWeight} de %{totalWeight} peso concluído"
@@ -691,6 +694,9 @@ msgstr "%{integrations_link_start}Integrações%{link_end} permitem que aplicati
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} será removido! Você tem certeza?"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} não existe ou você não tem permissão para adicionar registro de tempo a ele."
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(s) já está atribuída(s)"
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Método:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Espaço de nome:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}Projeto:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Verificar:%{labelEnd} %{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Severidade:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Ferramenta:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Resposta não modificada:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponível"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 hora"
@@ -876,6 +885,18 @@ msgstr "%{openedEpics} abertos, %{closedEpics} fechados"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} aberta, %{closedIssues} fechada"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed}%% usados"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} etiqueta"
+msgstr[1] "%{selectedLabelsCount} etiquetas"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} projeto"
+msgstr[1] "%{selectedProjectsCount} projetos"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "A2F"
msgid "2FADevice|Registered On"
msgstr "Registrado em"
-msgid "3 days"
-msgstr "3 dias"
-
msgid "3 hours"
msgstr "3 horas"
-msgid "30 days"
-msgstr "30 dias"
-
msgid "30 minutes"
msgstr "30 minutos"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 dias"
-
msgid "8 hours"
msgstr "8 horas"
@@ -2114,6 +2133,9 @@ msgstr "Adicione um contrato de termos de serviço e política de privacidade pa
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
+msgid "Add a checklist"
+msgstr "Adicionar uma lista de verificação"
+
msgid "Add a collapsible section"
msgstr "Adicionar uma seção resolvível"
@@ -2153,9 +2175,6 @@ msgstr "Adicione um sufixo ao endereço de e-mail da Central de serviços. %{lin
msgid "Add a table"
msgstr "Adicionar uma tabela"
-msgid "Add a task list"
-msgstr "Adicionar uma lista de tarefas"
-
msgid "Add a title..."
msgstr "Adicionar um título..."
@@ -2183,9 +2202,6 @@ msgstr "Adicionar regra de aprovação"
msgid "Add approvers"
msgstr "Adicionar aprovadores"
-msgid "Add attention request"
-msgstr "Adicionar requisição de atenção"
-
msgid "Add broadcast message"
msgstr "Adicionar mensagem de transmissão"
@@ -2231,6 +2247,9 @@ msgstr "Adicionar ambiente"
msgid "Add existing confidential %{issuableType}"
msgstr "Adicionar %{issuableType} confidencial existente"
+msgid "Add existing issue"
+msgstr "Adicionar issue existente"
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Adicione cabeçalho e rodapé aos emails. Por favor, note que as configurações de cor só serão aplicadas dentro da interface do aplicativo"
@@ -2526,7 +2545,7 @@ msgid "AdminArea|Maintainer"
msgstr "Mantenedor"
msgid "AdminArea|Manage applications for your instance that can use GitLab as an %{docs_link_start}OAuth provider%{docs_link_end}."
-msgstr ""
+msgstr "Gerencie aplicativos para sua instância que podem usar o GitLab como um provedor OAuth %{docs_link_start}%{docs_link_end}."
msgid "AdminArea|Minimal access"
msgstr "Acesso mínimo"
@@ -2610,7 +2629,7 @@ 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 ""
+msgstr "Você está prestes a excluir permanentemente o projeto %{projectName}, seu repositório e todos os recursos relacionados, incluindo problemas e solicitações de mesclagem. Depois de confirmar e pressionar %{strong_start}Excluir projeto%{strong_end}, ele não pode ser desfeito ou recuperado."
msgid "AdminProjects|Delete"
msgstr "Excluir"
@@ -3102,7 +3121,7 @@ msgid "AdminUsers|Limits"
msgstr "Límites"
msgid "AdminUsers|Linkedin"
-msgstr ""
+msgstr "Linkedin"
msgid "AdminUsers|Locked"
msgstr "Bloqueado"
@@ -3168,7 +3187,7 @@ msgid "AdminUsers|Send email to users"
msgstr "Enviar e-mail para usuários"
msgid "AdminUsers|Skype"
-msgstr ""
+msgstr "Skype"
msgid "AdminUsers|Sort by"
msgstr "Ordenar por"
@@ -3755,6 +3774,9 @@ msgstr "Todas as ramificações"
msgid "All changes are committed"
msgstr "Houve commit com todas as mudanças"
+msgid "All eligible users"
+msgstr "Todos os usuários elegíveis"
+
msgid "All email addresses will be used to identify your commits."
msgstr "Todos os endereços de e-mail serão usados para identificar seus commits."
@@ -4046,9 +4068,6 @@ msgstr "Um erro ocorreu ao obter a pré-visualização em Markdown"
msgid "An error occurred while fetching ancestors"
msgstr "Ocorreu um erro ao obter antepassados"
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr "Ocorreu um erro ao obter as ramificações. Tente novamente a pesquisa."
@@ -4094,6 +4113,9 @@ msgstr "Ocorreu um erro ao buscar o autocomplemento de projetos."
msgid "An error occurred while fetching reference"
msgstr "Ocorreu um erro ao obter referência"
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr "Ocorreu um erro ao obter as tags. Tente novamente a pesquisa."
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Ocorreu um erro ao carregar o formulário de tokens de acesso. Por favor, tente novamente."
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4490,7 +4509,7 @@ msgid "Application settings saved successfully"
msgstr "As configurações do aplicativo foram salvas com sucesso"
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "As configurações do aplicativo foram salvas com sucesso."
msgid "Application settings update failed"
msgstr "Falha na atualização de configurações da aplicação"
@@ -4586,14 +4605,26 @@ msgstr "Somente usuários com endereços de e-mail que correspondam a esses domÃ
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr "Requer aprovação do administrador para novos cadastros"
+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 "Restringe cadastros para endereços de e-mail que correspondem ao regex fornecido. %{linkStart}Qual é a sintaxe suportada?%{linkEnd}"
msgid "ApplicationSettings|Save changes"
msgstr "Salvar mudanças"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr "Consulte o %{linkStart}regulamento da política de senha%{linkEnd} do GitLab."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
msgstr "Enviar e-mail de confirmação no cadastro"
@@ -4619,6 +4650,18 @@ msgstr "Usuários com endereços de e-mail que correspondem a esses domínios nÃ
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 "Usuários com endereços de e-mail que correspondem a esses domínios não podem se cadastrar. Caracteres curinga permitidos. Use linhas ou vírgulas separadas para várias entradas."
+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 "domínio.com"
@@ -4764,29 +4807,32 @@ msgstr "Ramificação de destino"
msgid "ApprovalRule|Try for free"
msgstr "Experimente gratuitamente"
+msgid "ApprovalSettings|Keep approvals"
+msgstr "Manter aprovações"
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "As configurações de solicitação de mesclagem foram atualizadas"
msgid "ApprovalSettings|Prevent approval by author"
msgstr "Evitar a aprovação por autor"
-msgid "ApprovalSettings|Prevent approval by author."
-msgstr "Evitar a aprovação por autor."
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr "Evitar aprovações por usuários que adicionarem commits"
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
-msgstr "Evitar aprovações por usuários que adicionarem commits."
-
msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr "Evitar a edição de regras de aprovação em solicitações de mesclagem"
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests"
+msgstr ""
+
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Evitar a edição de regras de aprovação em projetos e solicitações de mesclagem."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
-msgstr "Remover todas as aprovações quando commits forem adicionados a ramificação de origem"
+msgid "ApprovalSettings|Remove all approvals"
+msgstr "Remover todas as aprovações"
+
+msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
+msgstr "Remover aprovações de proprietários de código se seus arquivos foram alterados"
msgid "ApprovalSettings|Require user password to approve"
msgstr "Exigir senha do usuário para aprovar"
@@ -4803,6 +4849,9 @@ msgstr "Esta configuração está caracterizada no nível de instância e pode s
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 "Quando um commit é adicionado:"
+
msgid "Approvals are optional."
msgstr "As aprovações são opcionais."
@@ -4830,9 +4879,6 @@ msgstr "Aprovou o merge request atual."
msgid "Approved-By"
msgstr "Aprovado por"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Aprovador"
@@ -5174,9 +5220,6 @@ msgstr "Atribuído a mim"
msgid "Assigned to you"
msgstr "Atribuídos a você"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr "Usuário(s) atribuído(s). Sua solicitação de atenção foi removida."
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Responsável"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr "Em risco"
-msgid "Attach a file"
-msgstr "Anexar um arquivo"
+msgid "Attach a file or image"
+msgstr "Anexar um arquivo ou imagem"
msgid "Attaching File - %{progress}"
msgstr "Anexando arquivo - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] "Anexando %d arquivos"
msgid "Attaching the file failed."
msgstr "Falha ao anexar o arquivo."
-msgid "Attention"
-msgstr "Atenção"
-
-msgid "Attention requested"
-msgstr "Atenção solicitada"
-
msgid "Audit Events"
msgstr "Eventos de auditoria"
@@ -5293,13 +5330,19 @@ msgid "AuditLogs|User Events"
msgstr "Eventos do Usuário"
msgid "AuditStreams|A header with this name already exists."
-msgstr ""
+msgstr "Já existe um cabeçalho com este nome."
msgid "AuditStreams|Active"
msgstr "Ativo"
+msgid "AuditStreams|Add a custom header"
+msgstr "Adicionar um cabeçalho personalizado"
+
+msgid "AuditStreams|Add a custom value"
+msgstr "Adicionar um valor personalizado"
+
msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party systems."
-msgstr ""
+msgstr "Adicione um HTTP final para gerenciar registros de auditoria em sistemas de terceiros."
msgid "AuditStreams|Add external stream destination"
msgstr "Adicionar destino para stream externo"
@@ -5308,19 +5351,22 @@ msgid "AuditStreams|Add stream"
msgstr "Adicionar stream"
msgid "AuditStreams|An error occurred when creating external audit event stream destination. Please try it again."
-msgstr ""
+msgstr "Ocorreu um erro ao criar um destino para fluxo de eventos de auditoria externo. Por favor, tente novamente."
msgid "AuditStreams|An error occurred when deleting external audit event stream destination. Please try it again."
-msgstr ""
+msgstr "Ocorreu um erro ao deletar um destino para fluxo de eventos de auditoria externa. Por favor, tente novamente."
msgid "AuditStreams|An error occurred when fetching external audit event streams. Please try it again"
+msgstr "Ocorreu um erro ao buscar streams de eventos de auditoria externa. Por favor, tente novamente."
+
+msgid "AuditStreams|An error occurred when updating external audit event stream destination. Please try it again."
msgstr ""
msgid "AuditStreams|Cancel editing"
msgstr "Cancelar edição"
msgid "AuditStreams|Custom HTTP headers"
-msgstr ""
+msgstr "Cabeçalhos HTTP personalizados"
msgid "AuditStreams|Delete %{link}"
msgstr "Excluir %{link}"
@@ -5329,7 +5375,10 @@ msgid "AuditStreams|Destination URL"
msgstr "URL de destino"
msgid "AuditStreams|Destinations receive all audit event data"
-msgstr ""
+msgstr "Destinatário recebeu todos os dados do eventos de auditoria"
+
+msgid "AuditStreams|Edit %{link}"
+msgstr "Editar %{link}"
msgid "AuditStreams|Header"
msgstr "Cabeçalho"
@@ -5337,24 +5386,39 @@ msgstr "Cabeçalho"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
msgstr ""
+msgid "AuditStreams|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
+msgstr "Configurar streaming para eventos de auditoria"
+
+msgid "AuditStreams|Stream added successfully"
msgstr ""
msgid "AuditStreams|Stream count icon"
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 ""
+msgstr "Isso pode incluir informações confidenciais. Certifique-se de confiar no seu destino final."
msgid "AuditStreams|This is great for keeping everything one place."
-msgstr ""
+msgstr "Isso é ótimo para manter tudo em um só lugar."
msgid "AuditStreams|Value"
msgstr "Valor"
+msgid "AuditStreams|Verification token"
+msgstr "Token de verificação"
+
msgid "Aug"
msgstr "Ago"
@@ -5571,8 +5635,8 @@ msgstr "O incidente associado fecha automaticamente quando uma notificação de
msgid "Automatically resolved"
msgstr "Resolvido automaticamente"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Atualiza automaticamente os branches e tags deste projeto do repositório upstream a cada hora."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr "Atualiza automaticamente os branches e tags deste projeto do repositório upstream."
msgid "Autosave|Note"
msgstr "Nota"
@@ -5760,6 +5824,9 @@ msgstr "Executa CI/CD pipelines com Atlassian Bamboo. Você deve configurar a ro
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr "Banido"
+
msgid "Banner message"
msgstr ""
@@ -6046,7 +6113,7 @@ msgid "BillingPlans|While GitLab is ending availability of the Bronze plan, you
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 ""
+msgstr "Você não tem nenhum grupo. Você precisará %{create_group_link_start}criar um%{create_group_link_end} e %{move_link_start}mover este projeto para ele%{move_link_end}."
msgid "BillingPlans|You'll have to %{move_link_start}move this project%{move_link_end} to one of your groups."
msgstr "Você terá que %{move_link_start}mover este projeto%{move_link_end} para um de seus grupos."
@@ -6111,6 +6178,9 @@ msgstr "Estender avaliação"
msgid "Billings|Free groups are limited to %{number} seats."
msgstr "Grupos gratuitos são limitados a %{number} assentos."
+msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
+msgstr ""
+
msgid "Billings|In a seat"
msgstr "Em um assento"
@@ -6148,7 +6218,7 @@ msgid "Billings|Validate user account"
msgstr "Validar conta de usuário"
msgid "Billings|You can't change the seat status of a user who was invited via a group or project."
-msgstr ""
+msgstr "Você não pode alterar o status da licença de um usuário que foi convidado por meio de um grupo ou projeto."
msgid "Billings|You can't remove yourself from a seat, but you can leave the group."
msgstr ""
@@ -6204,17 +6274,16 @@ msgstr "Explorar todos os planos"
msgid "Billing|Export list"
msgstr "Exportar lista"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr "Grupos gratuitos no GitLab são limitados a %{maxNamespaceSeats} assentos"
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr "A partir de 22 de junho de 2022 (GitLab 15.1), os grupos gratuitos serão limitados a 5 membros"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "A partir de 19 de outubro de 2022, os grupos gratuitos serão limitados a 5 membros"
msgid "Billing|Group invite"
msgstr "Convite de grupo"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] "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 ""
@@ -6231,6 +6300,9 @@ msgstr "Convite de projeto"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Remover usuário %{username} da sua assinatura"
+msgid "Billing|To ensure all members can access the group when your trial ends, you can upgrade to a paid tier."
+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 ""
@@ -6246,13 +6318,10 @@ msgstr "Ver aprovações pendentes"
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 "Você está prestes a remover o usuário %{username} de sua assinatura. Se você continuar, o usuário será removido do %{namespace} grupo e de todos os seus subgrupos e projetos. Esta ação não pode ser desfeita."
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr "Seu grupo gratuito agora está limitado a %{free_user_limit} membros"
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6550,7 +6619,7 @@ msgid "Bold text"
msgstr "Texto em negrito"
msgid "Both SSH and HTTP(S)"
-msgstr ""
+msgstr "Ambos SSH e HTTP(S)"
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -6585,9 +6654,51 @@ 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|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 push"
+msgstr "Permitido push"
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Ramificações"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "Ramificações: %{source_branch} para %{target_branch}"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "Ramificações: %{source_branch} → %{target_branch}"
+
msgid "Branches|Active"
msgstr "Ativos"
@@ -7196,9 +7307,6 @@ msgstr "Não é possível encontrar o commit HEAD para este branch"
msgid "Can't find variable: ZiteReader"
msgstr "Não foi possível encontrar a variável: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "Não consegue escanear o código?"
@@ -7386,7 +7494,7 @@ msgid "Certificate Subject"
msgstr "Assunto do certificado"
msgid "Change Failure Rate"
-msgstr ""
+msgstr "Mudança de taxa de falha"
msgid "Change assignee"
msgstr "Alterar responsável"
@@ -7590,7 +7698,7 @@ msgid "Check feature availability on namespace plan"
msgstr "Verificar disponibilidade de funcionalidades no plano de espaço de nome"
msgid "Check out branch"
-msgstr ""
+msgstr "Verificar ramificação de filial"
msgid "Check out, review, and merge locally"
msgstr ""
@@ -7768,7 +7876,7 @@ msgid "Checkout|Group"
msgstr "Grupo"
msgid "Checkout|Must be %{minimumNumberOfUsers} (your seats in use) or more."
-msgstr ""
+msgstr "Deve ser %{minimumNumberOfUsers} (seus assentos em uso) ou mais."
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 ""
@@ -7777,7 +7885,7 @@ msgid "Checkout|Name of company or organization using GitLab"
msgstr "Nome da empresa ou organização usando GitLab"
msgid "Checkout|Name: %{errors}"
-msgstr ""
+msgstr "Nome: %{errors}"
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
msgstr "Necessita de mais usuários? Compre o GitLab para a sua %{company}."
@@ -7887,9 +7995,6 @@ msgstr "O épico filho não existe."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8265,7 +8370,7 @@ msgid "Closed MRs"
msgstr "MRs fechados"
msgid "Closed date"
-msgstr ""
+msgstr "Data de finalização"
msgid "Closed issues"
msgstr "Issues fechadas"
@@ -8286,13 +8391,13 @@ msgid "Cloud Storage"
msgstr "Armazenamento em nuvem"
msgid "CloudSeed|All"
-msgstr ""
+msgstr "Todos"
msgid "CloudSeed|AlloyDB for Postgres"
msgstr ""
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "Serviços de banco de dados disponíveis através dos quais as instâncias podem ser criadas"
msgid "CloudSeed|Cancel"
msgstr "Cancelar"
@@ -8312,11 +8417,14 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr "Configuração"
+
msgid "CloudSeed|Create cluster"
-msgstr ""
+msgstr "Criar cluster"
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "Criar banco de dados"
msgid "CloudSeed|Create instance"
msgstr "Criar instância"
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr "Versão do banco de dados"
+msgid "CloudSeed|Databases"
+msgstr "Bancos de dados"
+
+msgid "CloudSeed|Deployments"
+msgstr "Implantações"
+
msgid "CloudSeed|Description"
msgstr "Descrição"
@@ -8376,23 +8490,29 @@ msgid "CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{
msgstr ""
msgid "CloudSeed|Machine type"
-msgstr ""
+msgstr "Tipo de máquina"
msgid "CloudSeed|Memorystore for Redis"
msgstr ""
msgid "CloudSeed|No instances"
-msgstr ""
+msgstr "Nenhuma instância"
msgid "CloudSeed|Refs"
msgstr ""
+msgid "CloudSeed|Regions"
+msgstr "Regiões"
+
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
msgstr ""
msgid "CloudSeed|Service"
msgstr "Serviço"
+msgid "CloudSeed|Service Account"
+msgstr "Conta de serviço"
+
msgid "CloudSeed|Services"
msgstr "Serviços"
@@ -8852,7 +8972,7 @@ msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr "Copiar nome do cluster Kubernetes"
msgid "ClusterIntegration|Create a Kubernetes cluster"
-msgstr ""
+msgstr "Criar um cluster 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 "Implante cada ambiente em seu próprio namespace. Caso contrário, os ambientes dentro de um projeto compartilham um namespace para todo o projeto. Note que qualquer pessoa que possa acionar a implantação de um namespace pode ler seus segredos. Se modificados, os ambientes existentes usarão seus namespaces atuais até que o cache do cluster seja limpo."
@@ -9953,7 +10073,7 @@ msgid "ContainerRegistry|Copy build command"
msgstr "Copiar comando de construção"
msgid "ContainerRegistry|Copy image path"
-msgstr ""
+msgstr "Copiar caminho da imagem"
msgid "ContainerRegistry|Copy login command"
msgstr "Copiar comando de entrada"
@@ -10215,9 +10335,6 @@ msgstr "Você pode adicionar uma imagem a este registro com os seguintes comando
msgid "Content parsed with %{link}."
msgstr "Conteúdo analisado com %{link}."
-msgid "ContentEditor|Table of Contents"
-msgstr "Ãndice"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr "Criar %{type}"
msgid "Create %{workspace} label"
msgstr "Criar etiqueta para %{workspace}"
-msgid "Create Google Cloud project"
-msgstr "Criar projeto no Google Cloud"
-
msgid "Create New Directory"
msgstr "Criar Novo Diretório"
@@ -10678,7 +10792,7 @@ msgid "Create a cluster"
msgstr "Criar um cluster"
msgid "Create a group"
-msgstr ""
+msgstr "Criar um grupo"
msgid "Create a merge request"
msgstr ""
@@ -10705,7 +10819,7 @@ msgid "Create a personal access token on your account to pull or push via %{prot
msgstr "Crie um token de acesso pessoal na sua conta para dar pull ou push via %{protocol}."
msgid "Create a project"
-msgstr ""
+msgstr "Crie um projeto"
msgid "Create an account using:"
msgstr "Criar uma conta usando:"
@@ -10816,7 +10930,7 @@ msgid "Create new project"
msgstr "Criar novo projeto"
msgid "Create new..."
-msgstr ""
+msgstr "Criar novo..."
msgid "Create one"
msgstr "Criar um"
@@ -11109,6 +11223,9 @@ msgstr "Cartão de crédito:"
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
+msgid "Crm|Active"
+msgstr "Ativo"
+
msgid "Crm|Contact"
msgstr "Contato"
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr "Cconfiguração de DAST"
+msgid "DAST configuration not found"
+msgstr "Configuração do DAST não encontrada"
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr "Alterar taxa de falha"
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr "Alterar taxa de falha (porcentagem)"
+
msgid "DORA4Metrics|Date"
msgstr "Data"
@@ -11528,6 +11651,9 @@ msgstr "Frequência de implantação"
msgid "DORA4Metrics|Lead time for changes"
msgstr "Tempo de espera para mudanças"
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr "Tempo de espera para mudanças (mediana dos dias)"
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr "O gráfico exibe a mediana de tempo entre uma solicitação de mesclagem
msgid "DORA4Metrics|Time to restore service"
msgstr "Tempo para restaurar o serviço"
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr "Tempo para restaurar o serviço (mediana dos dias)"
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 "Ativado"
+
msgid "DastConfig|Generate code snippet"
msgstr "Gerar snippet de código"
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr ""
+
+msgid "DastConfig|No previous scans found for this project"
+msgstr "Nenhuma verificação anterior encontrada para este projeto"
+
+msgid "DastConfig|Not enabled"
+msgstr "Não ativado"
+
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 ""
@@ -11826,7 +11967,7 @@ msgid "DastProfiles|Scanner name"
msgstr "Nome da verificação"
msgid "DastProfiles|Scanner profiles define the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Os perfis de verificação definem os detalhes de configuração de uma verificação de segurança. %{linkStart}Saiba mais%{linkEnd}."
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"
@@ -11856,7 +11997,7 @@ msgid "DastProfiles|Site name"
msgstr "Nome do site"
msgid "DastProfiles|Site profiles define the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "Os perfis do site definem os atributos e detalhes de configuração do seu aplicativo implantado, site ou API. %{linkStart}Saiba mais%{linkEnd}."
msgid "DastProfiles|Site type"
msgstr "Tipo de site"
@@ -12307,6 +12448,9 @@ msgstr "Excluir chave de implantação"
msgid "Delete file"
msgstr "Excluir arquivo"
+msgid "Delete identity"
+msgstr "Excluir identidade"
+
msgid "Delete image"
msgstr "Excluir imagem"
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr "Excluir projeto"
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr "Excluir linha"
@@ -12388,6 +12538,15 @@ msgstr "Falha ao remover os webhooks. Por favor, tente novamente ou entre em con
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "Falha ao remover o repositório wiki. Por favor, tente novamente ou entre em contato com o administrador."
+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 "%{name}' Fluxo de Valor excluído"
@@ -12407,14 +12566,11 @@ msgid "Deleted projects cannot be restored!"
msgstr "Projetos excluídos não podem ser restaurados!"
msgid "Deleted the source branch."
-msgstr ""
+msgstr "Excluir a ramificação de origem."
msgid "Deletes the source branch"
msgstr "Excluir ramificação de origem"
-msgid "Deletes the source branch."
-msgstr "Excluir ramificação de origem"
-
msgid "Deleting"
msgstr "Excluíndo"
@@ -12590,7 +12746,7 @@ msgid "DependencyProxy|Enable Dependency Proxy"
msgstr "Ativar proxy de dependências"
msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
-msgstr ""
+msgstr "Ative o proxy de dependências e as configurações para limpar o cache."
msgid "DependencyProxy|Image list"
msgstr "Lista de imagens"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Implantar"
msgstr[1] "Implantações"
+msgid "Deploy Key"
+msgstr "Chave de implantação"
+
msgid "Deploy Keys"
msgstr "Chave de implantação"
@@ -12877,7 +13036,7 @@ msgstr "Opções de aprovação"
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13030,7 +13189,7 @@ msgid "Description"
msgstr "Descrição"
msgid "Description (alt text)"
-msgstr ""
+msgstr "Descrição (texto alternativo)"
msgid "Description (optional)"
msgstr "Descrição (opcional)"
@@ -13678,9 +13837,6 @@ msgstr "URL das páginas de documentação"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr "Não exclui a ramificação de origem."
-
msgid "Domain"
msgstr "Domínio"
@@ -14089,9 +14245,6 @@ msgstr "Nenhum. Selecione espaços de nome para indexar."
msgid "Elastic|None. Select projects to index."
msgstr "Nenhum. Selecione projetos para indexar."
-msgid "Eligible users"
-msgstr "Usuários elegíveis"
-
msgid "Email"
msgstr "E-mail"
@@ -14413,9 +14566,6 @@ msgstr "Protocolos de acesso do Git habilitados"
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr "Horário de término"
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr "Erro ao criar o snippet"
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,24 +16042,21 @@ msgstr "Falha ao remover uma reunião do Zoom"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr "Falha ao remover a espelho."
msgid "Failed to remove the pipeline schedule"
msgstr "Erro ao excluir o agendamento do pipeline"
+msgid "Failed to remove timelog"
+msgstr "Falha ao remover registro de tempo"
+
msgid "Failed to remove user identity."
msgstr "Falha ao remover a identidade do usuário."
msgid "Failed to remove user key."
msgstr "Falha ao remover a chave do usuário."
-msgid "Failed to request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr "Falha ao recuperar a página"
@@ -15922,6 +16072,9 @@ msgstr "Falha ao salvar preferências (%{error_message})."
msgid "Failed to save preferences."
msgstr "Falha ao salvar preferências."
+msgid "Failed to save timelog"
+msgstr "Falha ao salvar registro de tempo"
+
msgid "Failed to set due date because the date format is invalid."
msgstr "Falha ao definir data limite porque o formato da data é inválido."
@@ -15967,9 +16120,6 @@ msgstr "Falso positivo"
msgid "Fast timeout"
msgstr "Tempo limite rápido"
-msgid "Fast-forward merge without a merge commit"
-msgstr "Fast-forward merge sem um merge commit"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Lançamentos mais rápidos. Melhor código. Menos dor."
@@ -16212,6 +16362,9 @@ msgstr "Fev"
msgid "February"
msgstr "Fevereiro"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16504,13 +16657,13 @@ msgid "For files larger than this limit, only index the file name. The file cont
msgstr "Para arquivos maiores que este limite indexam apenas o nome do arquivo. O conteúdo do arquivo não é indexado nem pesquisável."
msgid "For general work"
-msgstr ""
+msgstr "Para trabalhos gerais"
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 ""
+msgstr "Para investigar interrupções ou interrupções de serviço de TI"
msgid "For more info, read the documentation."
msgstr "Para mais informações, leia a documentação."
@@ -16588,7 +16741,7 @@ msgid "ForkProject|Visibility level"
msgstr "Nível de visibilidade"
msgid "ForkProject|Want to organize several dependent projects under the same namespace?"
-msgstr ""
+msgstr "Quer organizar vários projetos dependentes no mesmo espaço de nome?"
msgid "ForkSuggestion|Cancel"
msgstr "Cancelar"
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Avaliação gratuita do GitLab.com Ultimate"
+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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr "De %{code_open}%{source_title}%{code_close} em"
msgid "From %{providerTitle}"
msgstr "Do %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr "A partir de 22 de junho de 2022 (GitLab 15.1), espaços de nomes pessoais gratuitos e grupos de nível superior serão limitados a %{free_limit} membros"
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] "A partir de 19 de outubro de 2022, os grupos gratuitos serão limitados a %d membros"
+msgstr[1] "A partir de 19 de outubro de 2022, os grupos gratuitos serão limitados a %d membros"
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] "A partir de 19 de outubro de 2022, você poderá ter no máximo %d membro único em todos os seus projetos pessoais"
+msgstr[1] "A partir de 19 de outubro de 2022, você poderá ter no máximo %d membros únicos em todos os seus projetos pessoais"
msgid "From issue creation until deploy to production"
msgstr "Da abertura de tarefas até a implantação para a produção"
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr "Gerado com dados JSON"
+
msgid "Generic"
msgstr "Genérico"
@@ -16765,6 +16930,9 @@ msgstr "%{component} sincronizado"
msgid "Geo|%{component} verified"
msgstr "%{component} verificado"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} não pode estar em branco"
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr "Em andamento"
-msgid "Geo|In sync"
-msgstr "Em sincronia"
-
msgid "Geo|Internal URL"
msgstr "URL interna"
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Ainda não sincronizado"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr "Insalubre"
msgid "Geo|Unknown"
msgstr "Desconhecido"
-msgid "Geo|Unknown state"
-msgstr "Estado desconhecido"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "Atualizado em %{timeAgo}"
@@ -17443,6 +17602,9 @@ msgstr "Issue do GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
+msgid "GitLab Logo"
+msgstr "Logotipo do GitLab"
+
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr "Solicitação de conta do GitLab rejeitada"
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Certificado: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "Verifique o status do pipeline"
+
msgid "GitLabPages|Configure pages"
msgstr "Configurar páginas"
@@ -17614,6 +17776,9 @@ msgstr "Salvar alterações"
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 "Ocorreu um erro ao obter o certificado Let's Encrypt para %{domain}. Para tentar novamente, visite os seus %{link_start}detalhes de domínio%{link_end}."
+msgid "GitLabPages|Start over"
+msgstr "Começar novamente"
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr ""
@@ -17621,11 +17786,14 @@ msgid "GitLabPages|Unverified"
msgstr "Não verificado"
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "Atualizando a configuração de suas páginas..."
msgid "GitLabPages|Verified"
msgstr "Verificado"
+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 "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}"
@@ -17638,6 +17806,9 @@ msgstr "Com GitLab Pages, você pode hospedar seu site estático diretamente do
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 "O site da sua página ainda não está configurado. Consulte a documentação %{docs_link_start}GitLab Pages%{link_end} para saber como enviar seu site estático e fazer com que o GitLab o sirva. Você também pode se inspirar nos %{samples_link_start}exemplos de projetos do 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 ""
+
msgid "GitLabPages|Your pages are served under:"
msgstr "Suas páginas são servidas sob:"
@@ -17956,18 +18127,15 @@ msgstr "Ir para seus snippets"
msgid "Google Cloud"
msgstr "Google Cloud"
+msgid "Google Cloud Error - %{error}"
+msgstr ""
+
msgid "Google Cloud Project"
msgstr "Projeto de Google Cloud"
msgid "Google Cloud authorizations required"
msgstr ""
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr "Conteúdo da visão geral do grupo"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,8 +18508,8 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
-msgstr ""
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
+msgstr "Antes de aplicar a autenticação somente SSO para a atividade do Git de todos os usuários, ative a autenticação somente SSO para a atividade da web."
msgid "GroupSAML|Certificate fingerprint"
msgstr "Impressão digital do certificado"
@@ -18485,7 +18650,7 @@ msgid "GroupSaml|Copy SCIM API endpoint URL"
msgstr ""
msgid "GroupSaml|Copy SCIM token"
-msgstr ""
+msgstr "Copiar token SCIM"
msgid "GroupSaml|SCIM API endpoint URL"
msgstr ""
@@ -18508,8 +18673,8 @@ msgstr "Aplicado a todos os subgrupos, a menos que seja substituído por um prop
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Pipeline de Auto DevOps foi atualizado para o grupo"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
-msgstr "Banir automaticamente os usuários que baixam mais do que o número especificado de projetos dentro do intervalo especificado."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
+msgstr "Banir automaticamente usuários que baixam mais do que um número especificado de repositórios em um determinado momento."
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 "Disponível apenas no grupo de nível superior. Aplica-se a todos os subgrupos. Grupos já compartilhados com um grupo fora de %{group} ainda são compartilhados, a menos que sejam removidos manualmente."
@@ -18556,6 +18721,9 @@ msgstr "As notificações por e-mail estão desativadas"
msgid "GroupSettings|Export group"
msgstr "Exportar grupo"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr "Limite de taxa de abuso do Git"
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr "Os membros do grupo não são notificados se o grupo for mencionado."
@@ -18568,15 +18736,9 @@ msgstr "Se não for especificado no nível de grupo ou instância, o padrão é
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 "Se a visibilidade do grupo pai for menor que a visibilidade atual do grupo, os níveis de visibilidade para subgrupos e projetos serão mudados para corresponder à visibilidade do novo grupo pai."
-msgid "GroupSettings|Interval (seconds)"
-msgstr "Intervalo (segundos)"
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr "Os membros não podem convidar grupos fora de %{group} e seus subgrupos"
-msgid "GroupSettings|Number of projects"
-msgstr "Número de projetos"
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr "Organizações e contatos podem ser criados e associados a issues."
@@ -18595,9 +18757,6 @@ msgstr "Evitar fork fora do grupo"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "A configuração de prevenção de fork não foi salva"
-msgid "GroupSettings|Project download rate limit"
-msgstr "Limite de taxa de download do projeto"
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr "Projetos em %{group} não podem ser compartilhados com outros grupos"
@@ -18622,15 +18781,9 @@ msgstr "Defina um limite de tamanho para todo o conteúdo em cada site do Pages
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr "Defina o nome inicial e as proteções para a ramificação padrão dos novos repositórios criados no grupo."
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr "Defina como 0 para desativar a limitação."
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "O pipeline de Auto DevOps é executado se nenhum arquivo de configuração de CI for encontrado."
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-msgstr "O número máximo de projetos únicos que um usuário pode baixar dentro do intervalo especificado antes de ser banido. Defina como 0 para desabilitar a limitação."
-
msgid "GroupSettings|The projects in this subgroup can be selected as templates for new projects created in the group. %{link_start}Learn more.%{link_end}"
msgstr "Os projetos neste subgrupo podem ser selecionados como modelos para novos projetos criados no grupo. %{link_start}Saiba mais.%{link_end}"
@@ -18748,6 +18901,9 @@ msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para c
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 "%{linkStart}Grupos%{linkEnd} permitem que você gerencie e colabore em vários projetos. Os membros de um grupo têm acesso a todos os seus projetos."
@@ -18766,6 +18922,9 @@ msgstr "Criar grupo"
msgid "GroupsNew|Create new group"
msgstr "Criar novo grupo"
+msgid "GroupsNew|Create subgroup"
+msgstr "Criar subgrupo"
+
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 ""
@@ -18811,6 +18970,9 @@ msgstr "Para importar um grupo, navegue até as configurações do grupo para a
msgid "GroupsNew|Upload file"
msgstr "Enviar arquivo"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "Você também pode %{linkStart}importar um grupo existente%{linkEnd}."
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr "Remover avatar"
msgid "Groups|Save changes"
msgstr "Salvar mudanças"
+msgid "Groups|Subgroup URL"
+msgstr "URL do subgrupo"
+
+msgid "Groups|Subgroup name"
+msgstr "Nome do subgrupo"
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "Diretriz"
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr "Logotipo de cabeçalho"
@@ -19149,7 +19314,7 @@ msgid "Hide"
msgstr "Ocultar"
msgid "Hide Live Preview"
-msgstr ""
+msgstr "Ocultar pré-visualização ao vivo"
msgid "Hide archived projects"
msgstr "Ocultar projetos arquivados"
@@ -19245,6 +19410,9 @@ msgstr "Alerta original:"
msgid "HighlightBar|Time to SLA:"
msgstr "Tempo para SLA:"
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Histórico"
@@ -19314,6 +19482,9 @@ msgstr "Como uso um terminal web?"
msgid "How do I use file templates?"
msgstr ""
+msgid "How does pull mirroring work?"
+msgstr "Como funciona o espelhamento de pull?"
+
msgid "How many seconds an IP counts toward the IP address limit."
msgstr ""
@@ -19477,10 +19648,10 @@ msgid "IdentityVerification|Verification code"
msgstr ""
msgid "IdentityVerification|Verification successful"
-msgstr ""
+msgstr "Verificação bem-sucedida"
msgid "IdentityVerification|Verify code"
-msgstr ""
+msgstr "Verificar código"
msgid "IdentityVerification|Verify your identity"
msgstr "Verificar sua identidade"
@@ -19497,6 +19668,9 @@ msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr ""
+msgid "Identity|Provider ID"
+msgstr "ID do provedor"
+
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 ""
@@ -19524,6 +19698,9 @@ msgstr "Se ativado, apenas ramificações protegidas serão espelhados."
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 ""
@@ -19803,6 +19980,9 @@ msgstr[1] "Importando %d repositórios"
msgid "Importing..."
msgstr "Importando..."
+msgid "Import|The repository could not be imported."
+msgstr "O repositório não pôde ser importado."
+
msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
msgstr "Não há um repositório de Git válido neste URL. Se seu repositório HTTP não for acessível publicamente, verifique suas credenciais."
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ msgstr "Gravar gráficos para cima/para baixo"
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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr "Proprietários de código"
@@ -19953,9 +20127,6 @@ msgstr "Verificação de dependência"
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr "Difícil"
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr "Descubra Premium e Ultimate"
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr "Descubra Premium e Ultimate."
-msgid "InProductMarketing|Do you have a minute?"
-msgstr "Você tem um minuto?"
-
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr ""
msgid "InProductMarketing|Dynamic application security testing"
msgstr "Testes dinâmicos de segurança de aplicativos"
-msgid "InProductMarketing|Easy"
-msgstr "Fácil"
-
msgid "InProductMarketing|Epics"
msgstr "Épicos"
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr "Vários aprovadores necessários"
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr "Muito difícil"
-
-msgid "InProductMarketing|Very easy"
-msgstr "Muito fácil"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr "Visualize seus épicos e marcos em uma linha do tempo."
@@ -20337,9 +20487,6 @@ msgstr "Assista a construção do iOS em ação."
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|We want your GitLab experience to be great"
-msgstr "Queremos que sua experiência com o GitLab seja ótima"
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20602,7 +20749,7 @@ msgid "Incidents|Must start with http or https"
msgstr "Deve começar com http ou https"
msgid "Incident|Add new timeline event"
-msgstr ""
+msgstr "Adicionar novo evento na linha do tempo"
msgid "Incident|Alert details"
msgstr "Detalhes do alerta"
@@ -20611,7 +20758,7 @@ msgid "Incident|Are you sure you want to delete this event?"
msgstr "Tem certeza de que deseja excluir este evento?"
msgid "Incident|Are you sure you wish to delete this image?"
-msgstr ""
+msgstr "Tem certeza de que deseja excluir esta imagem?"
msgid "Incident|Delete event"
msgstr "Excluir evento"
@@ -20620,7 +20767,7 @@ msgid "Incident|Delete image"
msgstr "Excluir imagem"
msgid "Incident|Deleting %{filename}"
-msgstr ""
+msgstr "Excluindo %{filename}"
msgid "Incident|Edit image text or link"
msgstr "Editar texto ou link da imagem"
@@ -20638,10 +20785,10 @@ msgid "Incident|Metrics"
msgstr "Métricas"
msgid "Incident|No timeline items have been added yet."
-msgstr ""
+msgstr "Nenhum item da linha do tempo foi adicionado ainda."
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "Salvar e adicionar outro evento"
msgid "Incident|Something went wrong while creating the incident timeline event."
msgstr ""
@@ -20656,19 +20803,19 @@ msgid "Incident|Summary"
msgstr "Resumo"
msgid "Incident|There was an issue loading alert data. Please try again."
-msgstr ""
+msgstr "Ocorreu um problema ao carregar os dados de alerta. Por favor, tente novamente."
msgid "Incident|There was an issue loading incident data. Please try again."
-msgstr ""
+msgstr "Ocorreu um problema ao carregar os dados do incidente. Por favor, tente novamente."
msgid "Incident|Timeline"
-msgstr ""
+msgstr "Linha do tempo"
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "Texto da linha do tempo"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "Texto da linha do tempo..."
msgid "Include author name in notification email body"
msgstr "Incluir o nome do autor no corpo do e-mail de notificação"
@@ -21054,7 +21201,7 @@ msgid "Integrations|No linked namespaces"
msgstr ""
msgid "Integrations|Notification settings"
-msgstr ""
+msgstr "Configurações de notificação"
msgid "Integrations|Projects using custom settings"
msgstr "Projetos usando configurações personalizadas"
@@ -21204,7 +21351,7 @@ msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid"
-msgstr ""
+msgstr "Inválido"
msgid "Invalid Insights config file detected"
msgstr "Arquivo de configuração de Insights inválido detectado"
@@ -21362,8 +21509,8 @@ msgstr "Convide seus colegas"
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 "Percebemos que você não convidou ninguém para este grupo. Convide seus colegas para que você possa discutir problemas, colaborar em solicitações de mesclagem e compartilhar seu conhecimento."
-msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of this namespace can start a trial or upgrade to a paid tier."
-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 "Para obter mais membros e acesso a recursos pagos adicionais, o proprietário do grupo pode iniciar uma avaliação ou atualizar para um nível pago."
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
msgstr "%{linkStart}Leia mais%{linkEnd} sobre as permissões de cargos"
@@ -21411,7 +21558,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr "Membros foram adicionados com sucesso"
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "Revise os erros de convite e tente novamente:"
msgid "InviteMembersModal|Search for a group to invite"
msgstr "Pesquisar um grupo para convidar"
@@ -21430,8 +21577,8 @@ 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] ""
+msgstr[0] "O seguinte membro não pôde ser convidado"
+msgstr[1] "Os seguintes %d membros não puderam ser convidados"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
msgstr ""
@@ -21439,8 +21586,8 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-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 "Para obter mais membros, um proprietário do grupo pode %{trialLinkStart}iniciar uma avaliação%{trialLinkEnd} ou %{upgradeLinkStart}atualizar%{upgradeLinkEnd} para um nível pago."
msgid "InviteMembersModal|To make more space, you can remove members who no longer need access."
msgstr ""
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "Você está convidando membros para o grupo %{strongStart}%{name}%{strongEnd}."
@@ -21862,6 +22006,9 @@ msgstr "Texto em itálico"
msgid "Iteration"
msgstr "Iteração"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Interação alterada para"
@@ -21877,12 +22024,36 @@ msgstr "Iteração atualizada"
msgid "Iterations"
msgstr "Iterações"
+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 "Adicionar iteração"
msgid "Iterations|All"
msgstr "Todos"
+msgid "Iterations|All scheduled iterations will remain scheduled even if you use a smaller number."
+msgstr ""
+
+msgid "Iterations|Automatic scheduling"
+msgstr "Agendamento automático"
+
+msgid "Iterations|Automation start date"
+msgstr "Data de início da automação"
+
msgid "Iterations|Cadence configuration is invalid."
msgstr "A configuração de cadência é inválida."
@@ -21904,6 +22075,9 @@ msgstr "Criar cadência"
msgid "Iterations|Create iteration"
msgstr "Criar iteração"
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "Crie iterações automaticamente em uma programação regular."
+
msgid "Iterations|Delete cadence"
msgstr "Excluir cadência"
@@ -21934,18 +22108,21 @@ msgstr "Editar iteração"
msgid "Iterations|Edit iteration cadence"
msgstr "Editar cadência de iteração"
+msgid "Iterations|Enable roll over"
+msgstr ""
+
msgid "Iterations|Error loading iteration cadences."
msgstr "Erro ao carregar cadências de iteração."
-msgid "Iterations|First iteration start date"
-msgstr ""
-
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 ""
+msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
+msgstr ""
+
msgid "Iterations|Learn more about automatic scheduling"
msgstr "Saiba mais sobre agendamento automático"
@@ -21973,9 +22150,6 @@ msgstr "Nenhuma iteração encontrada"
msgid "Iterations|No iterations in cadence."
msgstr "Nenhuma integrações em cadência"
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr "Sem iterações abertas."
@@ -22003,15 +22177,15 @@ msgstr "Selecionar data de início"
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 ""
+
msgid "Iterations|The duration of each iteration (in weeks)."
msgstr "A duração de cada iteração (em semanas)."
msgid "Iterations|The iteration has been deleted."
msgstr "A iteração foi excluída."
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
-msgstr ""
-
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr ""
@@ -22424,7 +22598,7 @@ msgid "Job|%{searchLength} results found for %{searchTerm}"
msgstr ""
msgid "Job|Are you sure you want to erase this job log and artifacts?"
-msgstr ""
+msgstr "Tem certeza de que deseja apagar este registro de tarefa e artefatos?"
msgid "Job|Browse"
msgstr "Navegar"
@@ -22445,7 +22619,7 @@ msgid "Job|Download"
msgstr "Baixar"
msgid "Job|Erase job log and artifacts"
-msgstr ""
+msgstr "Apagar registro de tarefa e artefatos"
msgid "Job|Failed"
msgstr ""
@@ -22484,7 +22658,7 @@ msgid "Job|Preparing"
msgstr "Preparando"
msgid "Job|Retry"
-msgstr ""
+msgstr "Repetir"
msgid "Job|Running"
msgstr "Executando"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Rolar para baixo"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Rolar para o topo"
@@ -22618,8 +22795,8 @@ msgstr "Chave"
msgid "Key (PEM)"
msgstr "Chave (PEM)"
-msgid "Key: %{key}"
-msgstr "Chave: %{key}"
+msgid "Key:"
+msgstr "Chave:"
msgid "Keyboard shortcuts"
msgstr "Atalhos de teclado"
@@ -22886,15 +23063,9 @@ msgstr "Último IP de entrada:"
msgid "Last sign-in at:"
msgstr "Última data de entrada:"
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr "Última atualização bem-sucedida"
-msgid "Last time checked"
-msgstr "Última vez verificado"
-
msgid "Last time verified"
msgstr ""
@@ -23040,13 +23211,13 @@ msgid "LearnGitLab|Add code owners"
msgstr ""
msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
-msgstr ""
+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 ""
msgid "LearnGitLab|Create a repository"
-msgstr ""
+msgstr "Criar um repositório"
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
msgstr "Crie um fluxo de trabalho para seu novo espaço de trabalho e aprenda como os recursos do GitLab funcionam juntos:"
@@ -23109,13 +23280,13 @@ msgid "LearnGitLab|Set up CI/CD"
msgstr ""
msgid "LearnGitLab|Set up your first project's CI/CD"
-msgstr ""
+msgstr "Configure o CI/CD do seu primeiro projeto"
msgid "LearnGitLab|Set up your workspace"
msgstr ""
msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "Comece uma avaliação gratuita do GitLab Ultimate"
msgid "LearnGitLab|Submit a merge request (MR)"
msgstr ""
@@ -23133,7 +23304,7 @@ msgid "LearnGitLab|Your team is growing! You've successfully invited new team me
msgstr ""
msgid "LearnGitlab|- Included in trial"
-msgstr ""
+msgstr "- Incluído na avaliação"
msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
msgstr "Entre em contato com seu administrador para iniciar uma avaliação gratuita do Ultimate."
@@ -23177,20 +23348,20 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "O Let's Encrypt não aceita e-mails de example.com"
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 "Let's Encrypt é uma autoridade certificadora (CA) gratuita, automatizada e aberta, que fornece certificados digitais, afim de habilitar o HTTPS (SSL/TLS) para sites. Saiba mais sobre a configuração do Let's Encrypt seguindo a %{docs_link_start}documentação nas Páginas GitLab %{docs_link_end}."
-msgid "Let's talk!"
-msgstr "Vamos conversar!"
-
msgid "License Compliance"
msgstr "Conformidade de licença"
-msgid "License Compliance| Used by"
-msgstr "Usado por"
+msgid "License Compliance| Used by %{dependencies}"
+msgstr ""
msgid "License compliance"
msgstr "Conformidade de licença"
@@ -23450,8 +23621,11 @@ msgstr "E-mails vinculados (%{email_count})"
msgid "Linked epics"
msgstr "Épicos vinculados"
-msgid "Linked issues"
-msgstr "Issues vinculadas"
+msgid "Linked incidents or issues"
+msgstr "Incidentes ou issues vinculadas"
+
+msgid "Linked items"
+msgstr ""
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23462,6 +23636,48 @@ msgstr "LinkedIn:"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr ""
+msgid "LinkedResources|Add"
+msgstr "Adicionar"
+
+msgid "LinkedResources|Add a resource link"
+msgstr "Adicionar um link de recurso"
+
+msgid "LinkedResources|Cancel"
+msgstr "Cancelar"
+
+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 "Buscando recursos vinculados"
+
+msgid "LinkedResources|Link"
+msgstr "Link"
+
+msgid "LinkedResources|Linked resources"
+msgstr "Recursos vinculados"
+
+msgid "LinkedResources|Remove"
+msgstr "Remover"
+
+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 "Texto (Opcional)"
+
+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 "Links"
@@ -23562,7 +23778,7 @@ msgid "Lock memberships to LDAP synchronization"
msgstr ""
msgid "Lock merge request"
-msgstr ""
+msgstr "Bloquear solicitação de mesclagem"
msgid "Lock not found"
msgstr "Bloqueio não encontrado"
@@ -23789,9 +24005,6 @@ msgstr "Importação de manifest"
msgid "Manual"
msgstr "Manual"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23820,7 +24033,7 @@ msgid "Mark this issue as a duplicate of another issue"
msgstr "Marcar esta issue como uma duplicata de outra issue"
msgid "Mark this issue as related to another issue"
-msgstr ""
+msgstr "Marcar esta issue como relacionada a outra issue"
msgid "Mark to do as done"
msgstr "Marcar tarefa como concluída"
@@ -23880,7 +24093,7 @@ msgid "Marked this issue as a duplicate of %{duplicate_param}."
msgstr ""
msgid "Marked this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "Marcado como uma issue relacionada a %{issue_ref}."
msgid "Marked to do as done."
msgstr "Marcou tarefa como concluída."
@@ -23895,7 +24108,7 @@ msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr ""
msgid "Marks this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "Marca esta issue como relacionada a %{issue_ref}."
msgid "Marks to do as done."
msgstr "Marca tarefa como concluída."
@@ -24053,8 +24266,8 @@ 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_whitelist}."
-msgstr ""
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr "O tamanho máximo do arquivo é 1 MB. O tamanho da imagem deve ser 32 x 32 pixels. Os formatos de imagem permitidos são %{favicon_extension_allowlist}."
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
msgstr ""
@@ -25447,29 +25660,23 @@ msgstr "Parar ambiente"
msgid "MrList|Assigned to %{name}"
msgstr "Atribuído a %{name}"
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{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 ""
+msgstr "Ao continuar, você reconhece que as respostas serão usadas para melhorar o GitLab e de acordo com a %{linkStart}Política de Privacidade do GitLab%{linkEnd}."
msgid "MrSurvey|How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
-msgstr ""
+msgstr "Qual é seu nível de satisfação com %{strongStart}velocidade/desempenho%{strongEnd} de solicitações de mesclagem?"
msgid "MrSurvey|Merge request experience survey"
-msgstr ""
+msgstr "Pesquisa de experiência de solicitação de mesclagem"
msgid "MrSurvey|Overall, how satisfied are you with merge requests?"
-msgstr ""
+msgstr "No geral, qual é seu nível de satisfação com as solicitações de mesclagem?"
msgid "MrSurvey|Thank you for your feedback!"
-msgstr ""
+msgstr "Obrigado pela sua opinião!"
msgid "Multi-project"
msgstr ""
@@ -25477,8 +25684,8 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
-msgstr ""
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "Vários intervalos de endereços IP são suportados. Não afeta o acesso às configurações do grupo."
msgid "Multiple Prometheus integrations are not supported"
msgstr ""
@@ -25621,7 +25828,7 @@ msgid "NavigationTheme|Dark Mode (alpha)"
msgstr "Modo escuro (alpha)"
msgid "NavigationTheme|Gray"
-msgstr ""
+msgstr "Cinza"
msgid "NavigationTheme|Green"
msgstr "Verde"
@@ -25633,7 +25840,7 @@ msgid "NavigationTheme|Light Blue"
msgstr "Azul claro"
msgid "NavigationTheme|Light Gray"
-msgstr ""
+msgstr "Cinza claro"
msgid "NavigationTheme|Light Green"
msgstr "Verde claro"
@@ -25662,9 +25869,6 @@ msgstr "Saia e entre com uma conta diferente"
msgid "Need help?"
msgstr "Precisa de ajuda?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr "Nenhum dado CSV para exibir."
msgid "No Epic"
msgstr "Nenhuma épico"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr "Nenhum resultado correspondente"
@@ -25964,9 +26171,6 @@ msgstr "Nenhum artefato encontrado"
msgid "No assignee"
msgstr "Nenhum responsável"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "Nenhum método de autenticação configurado."
@@ -26178,7 +26382,7 @@ msgid "No repository"
msgstr "Nenhum repositório"
msgid "No results"
-msgstr ""
+msgstr "Nenhum resultado"
msgid "No runner executable"
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr "Texto normal"
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr "Nem todos os navegadores suportam dispositivos U2F. Portanto, exigimos que você configure um aplicativo de autenticação de dois fatores primeiro. Dessa forma, você sempre será capaz de entrar - mesmo quando você estiver usando um navegador não suportado."
@@ -26360,13 +26561,13 @@ msgid "Notes|Collapse replies"
msgstr "Recolher respostas"
msgid "Notes|Expand replies"
-msgstr ""
+msgstr "Expandir respostas"
msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
msgstr "As notas internas são visíveis apenas para o autor, cessionários e membros com a função de Repórter ou superior"
msgid "Notes|Last reply by %{name}"
-msgstr ""
+msgstr "Última resposta por %{name}"
msgid "Notes|Make this an internal note"
msgstr "Tornar disso uma nota interna"
@@ -26389,6 +26590,9 @@ msgstr "Esta nota interna será sempre confidencial"
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 "A data de criação fornecida está muito distante no passado."
+
msgid "Nothing to preview."
msgstr "Nada para pré-visualizar."
@@ -26512,10 +26716,10 @@ msgid "Notifications on"
msgstr "Notificações ligadas"
msgid "Notifications turned off."
-msgstr ""
+msgstr "Notificações desativadas."
msgid "Notifications turned on."
-msgstr ""
+msgstr "Notificações ativadas."
msgid "Notify users by email when sign-in location is not recognized."
msgstr "Notificar usuários por e-mail quando o local de login não for reconhecido"
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} em %{mr_link}"
+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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr "Responsável alterado de %{fromNames} para %{toNames}"
@@ -26691,6 +26904,11 @@ msgstr "OmniAuth"
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 track"
msgstr "Sob controle"
@@ -27123,7 +27341,7 @@ msgid "Only SSH"
msgstr "Apenas SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
-msgstr ""
+msgstr "Acessível apenas por %{membersPageLinkStart}membros do projeto%{membersPageLinkEnd}. A adesão deve ser explicitamente concedida a cada usuário."
msgid "Only active projects show up in the search and on the dashboard."
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ msgstr "Mais informações"
msgid "OperationsDashboard|Operations Dashboard"
msgstr "Painel de operações"
+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 "O painel de operações fornece um resumo da integridade operacional de cada projeto, incluindo status de pipeline e alerta."
@@ -27285,7 +27503,7 @@ msgid "Or you can choose one of the suggested colors below"
msgstr "Ou você pode escolher uma das cores sugeridas abaixo"
msgid "Ordered list"
-msgstr ""
+msgstr "Lista ordenada"
msgid "Organizations"
msgstr "Organizações"
@@ -27483,10 +27701,10 @@ msgid "PackageRegistry|Add composer registry"
msgstr ""
msgid "PackageRegistry|Additional metadata"
-msgstr ""
+msgstr "Metadados adicionais"
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 "Permitir que pacotes com o mesmo nome e versão sejam carregados no registro. A versão mais recente de um pacote é sempre usada durante a instalação."
msgid "PackageRegistry|App group: %{group}"
msgstr ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,15 +27813,21 @@ msgstr "Excluir versão do pacote"
msgid "PackageRegistry|Delete package"
msgstr "Excluir pacote"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr "Excluir esse pacote"
msgid "PackageRegistry|Duplicate packages"
-msgstr ""
+msgstr "Pacotes duplicados"
msgid "PackageRegistry|Error publishing"
msgstr "Erro ao publicar"
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr "Exemplos de ativos incluem arquivos .pom e .jar"
+
msgid "PackageRegistry|Failed to load the package data"
msgstr ""
@@ -27618,7 +27847,7 @@ msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}se
msgstr ""
msgid "PackageRegistry|Generic"
-msgstr ""
+msgstr "Genérico"
msgid "PackageRegistry|Gradle Groovy DSL"
msgstr ""
@@ -27656,6 +27885,9 @@ msgstr "Saiba como %{noPackagesLinkStart}publicar e compartilhar seus pacotes%{n
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr "Gerenciar armazenamento usado por ativos de pacote"
+
msgid "PackageRegistry|Manually Published"
msgstr "Publicado manualmente"
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr "Comando NuGet"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "Número de ativos duplicados a serem mantidos"
+
msgid "PackageRegistry|Package Registry"
msgstr "Registro de pacote"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27698,7 +27939,7 @@ msgid "PackageRegistry|Project-level"
msgstr "Nível do projeto"
msgid "PackageRegistry|Publish packages if their name or version matches this regex."
-msgstr ""
+msgstr "Publique pacotes se seu nome ou versão corresponder a este regex."
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
@@ -27713,7 +27954,7 @@ msgid "PackageRegistry|Registry setup"
msgstr ""
msgid "PackageRegistry|Reject packages with the same name and version"
-msgstr ""
+msgstr "Rejeitar pacotes com o mesmo nome e versão"
msgid "PackageRegistry|Remove package"
msgstr "Remover pacote"
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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 "Quando um pacote com o mesmo nome e versão é carregado no registro, mais ativos são adicionados ao pacote. Para economizar espaço de armazenamento, mantenha apenas os ativos mais recentes."
+
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 ""
+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 ""
@@ -27971,7 +28226,7 @@ msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
msgstr "Cole uma chave pública aqui. %{link_start}Como eu gero?%{link_end}"
msgid "Paste confidential epic link"
-msgstr ""
+msgstr "Colar link de épico confidencial"
msgid "Paste confidential issue link"
msgstr "Colar link de issue confidencial"
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr "Insights de desempenho"
+
msgid "Performance optimization"
msgstr "Otimização de performance"
@@ -28171,6 +28429,18 @@ msgstr "Projetos pessoais"
msgid "Personal projects limit:"
msgstr ""
+msgid "PersonalProject|Learn to move a project to a group"
+msgstr "Aprenda a mover um projeto para um grupo"
+
+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 "Temos algumas instruções para ajudá-lo a criar um grupo e mover seu projeto para ele."
+
+msgid "PersonalProject|Your project %{projectName} is not in a group"
+msgstr "Seu projeto %{projectName} não está em um grupo"
+
msgid "Phabricator Server Import"
msgstr ""
@@ -28327,6 +28597,9 @@ msgstr "💡 Dica: Visualize e valide seu pipeline"
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr "🚀 Execute seu primeiro pipeline"
+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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Próxima Execução"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Digite uma descrição curta para esta pipeline"
@@ -28399,6 +28690,9 @@ msgstr "Destino"
msgid "PipelineSchedules|Variables"
msgstr "Variáveis"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28645,6 +28939,9 @@ msgstr "Proprietário"
msgid "Pipelines|Pipeline Editor"
msgstr "Editor de pipeline"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Cache do projeto redefinido com sucesso."
@@ -28813,9 +29110,18 @@ msgstr "Pipeline de solicitação de mesclagem desanexada"
msgid "Pipeline|Failed"
msgstr "Falhou"
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr "Em progresso"
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr "Manual"
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "Pipeline de resultado mesclado"
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Passou"
msgid "Pipeline|Pending"
msgstr "Pendente"
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr "Executar para o nome da ramificação ou tag"
+msgid "Pipeline|Run merge request pipeline"
+msgstr "Executar pipeline de solicitação de mesclagem"
+
msgid "Pipeline|Run pipeline"
msgstr "Executar pipeline"
@@ -28888,6 +29203,12 @@ msgstr "Nome da tag"
msgid "Pipeline|Test coverage"
msgstr "Cobertura de teste"
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr "Variáveis"
msgid "Pipeline|View commit"
msgstr "Ver commit"
+msgid "Pipeline|View dependency"
+msgstr "Ver dependência"
+
msgid "Pipeline|View pipeline"
msgstr "Ver pipeline"
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr "Por favor, complete seu perfil com endereço de e-mail"
@@ -29116,6 +29446,9 @@ msgstr "Por favor, forneça atributos para atualizar"
msgid "Please reach out if you have any questions and we'll be happy to assist."
msgstr "Por favor, entre em contato se você tiver alguma dúvida, e nós ficaremos felizes em ajudar."
+msgid "Please review the %{linkStart}contribution guidelines%{linkEnd} for this project."
+msgstr "Por favor, revise as %{linkStart}diretrizes de contribuição%{linkEnd} para este projeto."
+
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 ""
@@ -29210,7 +29543,7 @@ msgid "PolicyRuleMultiSelect|Select %{itemTypeName}"
msgstr ""
msgid "PolicyRuleMultiSelect|Select all"
-msgstr ""
+msgstr "Selecionar tudo"
msgid "Polling interval multiplier"
msgstr ""
@@ -29362,8 +29695,8 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr "Evitar a parada automática"
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr "Evitar a edição de regras de aprovação em projetos e solicitações de mesclagem."
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr "Impedir a edição de regras de aprovação em projetos e solicitações de mesclagem"
msgid "Prevent environment from auto-stopping"
msgstr "Evitar que o ambiente pare automaticamente"
@@ -30076,6 +30409,9 @@ msgstr "Slug do projeto"
msgid "Project uploads"
msgstr "Projetos enviados"
+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 "O nível de visibilidade do projeto será alterado para coincidir com as regras do espaço de nome ao transferir para um grupo."
@@ -30085,6 +30421,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Projeto: %{name}"
+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 "Inscreva-se"
@@ -30163,6 +30505,9 @@ msgstr "Falha"
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 "Ajude-nos a melhorar esta página"
+
msgid "ProjectQualitySummary|Latest pipeline results"
msgstr "Últimos resultados do pipeline"
@@ -30175,6 +30520,9 @@ msgstr "Saiba mais sobre relatórios de teste"
msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
msgstr ""
+msgid "ProjectQualitySummary|Provide feedback"
+msgstr "Fornecer feedback"
+
msgid "ProjectQualitySummary|See full report"
msgstr "Ver relatório completo"
@@ -30202,6 +30550,9 @@ msgstr ""
msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
msgstr "A porcentagem de testes bem-sucedidos, reprovados ou ignorados."
+msgid "ProjectQualitySummary|This page helps you understand the code testing trends for your project. Let us know how we can improve it!"
+msgstr "Esta página ajuda você a entender as tendências de teste de código para seu projeto. Deixe-nos saber como podemos melhorá-lo!"
+
msgid "ProjectSelect| or group"
msgstr " ou grupo"
@@ -30968,7 +31319,7 @@ msgid "ProjectsNew|Visibility Level"
msgstr "Nível de visibilidade"
msgid "ProjectsNew|Want to organize several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
-msgstr ""
+msgstr "Quer organizar vários projetos dependentes no mesmo espaço de nome? %{link_start}Crie um grupo.%{link_end}"
msgid "PrometheusAlerts|exceeded"
msgstr ""
@@ -31390,18 +31741,36 @@ msgstr "padrão"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} poderá ser editado por desenvolvedores. Tem certeza disso?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Permitido para implantar"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr ""
+
msgid "ProtectedEnvironment|Environment"
msgstr "Ambiente"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr ""
+
+msgid "ProtectedEnvironment|Failed to load details for this group."
+msgstr ""
+
+msgid "ProtectedEnvironment|No environments in this project are projected."
+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 "Apenas usuários especificados podem executar implantações em um ambiente protegido."
+msgid "ProtectedEnvironment|Parent group"
+msgstr ""
+
msgid "ProtectedEnvironment|Protect"
msgstr "Proteger"
@@ -31528,6 +31897,12 @@ 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 "Comprar mais minutos"
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr "Receber qualquer notificações do GitLab."
@@ -31837,6 +32206,9 @@ msgstr "Usado recentemente"
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr "Recuperar senha"
+
msgid "Recovery Codes"
msgstr "Códigos de recuperação"
@@ -32002,14 +32374,11 @@ msgid "Rejected (closed)"
msgstr "Rejeitado (fechado)"
msgid "Relate to %{issuable_type} %{add_related_issue_link}"
-msgstr ""
+msgstr "Relacionar com %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
msgstr "Feature flags relacionados"
-msgid "Related incidents or issues"
-msgstr "Incidentes ou issues relacionadas"
-
msgid "Related issues"
msgstr "Issues relacionadas"
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] "Versão"
msgstr[1] "Versões"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "Remover responsável"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Remover imagem"
@@ -32306,12 +32675,6 @@ msgstr "Todas as etiquetas foram removidas."
msgid "Removed an issue from an epic."
msgstr "Uma issue foi removida de um épico."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "O grupo removido não pode ser restaurado!"
@@ -32360,9 +32723,6 @@ msgstr "Remover todas etiquetas."
msgid "Removes an issue from an epic."
msgstr "Remover uma issue de um épico."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Remove o épico pai %{epic_ref}."
@@ -32471,6 +32831,9 @@ msgstr "Responda a este e-mail diretamente ou %{view_it_on_gitlab}."
msgid "Reply…"
msgstr "Responder…"
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Denunciar abuso"
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32602,7 +32968,7 @@ msgid "Reports|Metrics reports failed to load results"
msgstr ""
msgid "Reports|Metrics reports: %{strong_start}%{numberOfChanges}%{strong_end} %{changes}"
-msgstr ""
+msgstr "Relatórios de métricas: %{strong_start}%{numberOfChanges}%{strong_end} %{changes}"
msgid "Reports|New"
msgstr "Novo"
@@ -32640,6 +33006,9 @@ msgstr "Vulnerabilidade"
msgid "Reports|Vulnerability Name"
msgstr "Nome da vulnerabilidade"
+msgid "Reports|metrics report"
+msgstr "relatório de métricas"
+
msgid "Reports|no changed test results"
msgstr "sem resultados de teste alterados"
@@ -32833,15 +33202,6 @@ msgstr "Solicitar acesso"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr "Requisitado"
msgid "Requested %{time_ago}"
msgstr "Solicitado %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr "Revisão requisitada"
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr "Reenviar"
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr "Reenviar e-mail de confirmação"
+
msgid "Resend confirmation email"
msgstr "Reenviar e-mail de confirmação"
@@ -33104,10 +33455,10 @@ msgstr "A recuperação do relatório de conformidade falhou. Atualize a página
msgid "Retry"
msgstr "Tentar novamente"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr "Copiar endereço de e-mail"
msgid "RightSidebar|Issue email"
msgstr "E-mail de issue"
-msgid "RightSidebar|adding a"
-msgstr "adicionar uma"
-
-msgid "RightSidebar|deleting the"
-msgstr "excluir a"
-
msgid "Roadmap"
msgstr "Planejamento"
@@ -33291,6 +33636,11 @@ msgstr "Executores são processos que selecionam e executam Tarefas de CI /CD pa
msgid "Runners page."
msgstr "Página de executores."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] "%d executor selecionado excluído"
+msgstr[1] "%d executores selecionados excluídos"
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr "Disponível"
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr "Executores online"
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr "Desatualizado"
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr "Nome da propriedade"
msgid "Runners|Protected"
msgstr "Protegido"
+msgid "Runners|Recommended"
+msgstr "Recomendado"
+
msgid "Runners|Register a group runner"
msgstr "Registrar um executor de grupo"
@@ -33624,7 +33983,7 @@ msgid "Runners|Runners"
msgstr "Executores"
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 "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."
msgid "Runners|Runs untagged jobs"
msgstr ""
@@ -33641,6 +34000,9 @@ msgstr "Mostrar instruções de instalação e registro do executor"
msgid "Runners|Show runner installation instructions"
msgstr "Mostrar instruções de instalação do executor"
+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 ""
@@ -33700,9 +34062,18 @@ 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|Up to date"
+msgstr "Atualizado"
+
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 "Status de atualização"
+
msgid "Runners|Upgrade available"
msgstr "Atualização disponível"
@@ -33748,6 +34119,9 @@ msgstr "Você usou %{quotaUsed} dos seus %{quotaLimit} minutos dos executores co
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr "disponível"
+
msgid "Runners|group"
msgstr "grupo"
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr "pausado"
+msgid "Runners|recommended"
+msgstr "recomendado"
+
msgid "Runners|shared"
msgstr "compartilhado"
@@ -33778,6 +34155,9 @@ msgstr "atualização disponível"
msgid "Runners|upgrade recommended"
msgstr "atualização recomendada"
+msgid "Runner|Owner"
+msgstr "Proprietário"
+
msgid "Running"
msgstr "Executando"
@@ -33800,19 +34180,19 @@ msgid "SAML for %{group_name}"
msgstr "SAML para %{group_name}"
msgid "SAML|Selecting \"Authorize\" will transfer ownership of your GitLab account \"%{username}\" (%{email}) to your organization."
-msgstr ""
+msgstr "Selecionar \"Autorizar\" transferirá a propriedade de sua conta do GitLab \"%{username}\" (%{email}) para sua organização."
msgid "SAML|Sign in to GitLab to connect your organization's account"
-msgstr ""
+msgstr "Entrar no GitLab para conectar a conta da sua organização"
msgid "SAML|The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account."
-msgstr ""
+msgstr "O grupo \"%{group_path}\" permite que você entre com sua conta de entrada única."
msgid "SAML|To access \"%{group_name}\" you must sign in with your Single Sign-On account, through an external sign-in page."
-msgstr ""
+msgstr "Para acessar \"%{group_name}\" você deve entrar com sua conta Single Sign-On, através de uma página de entrada externa."
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
-msgstr ""
+msgstr "O SSO da sua organização foi conectado à sua conta do GitLab"
msgid "SAST Configuration"
msgstr "Configuração de SAST"
@@ -33820,6 +34200,9 @@ msgstr "Configuração de SAST"
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr "Impressões digitais SSH"
+
msgid "SSH Key"
msgstr "Chave SSH"
@@ -33829,6 +34212,9 @@ msgstr "Chaves SSH"
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 ""
@@ -33907,12 +34293,27 @@ msgstr "Salvando"
msgid "Saving project."
msgstr "Salvando projeto."
-msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
msgstr ""
-msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval from %{approvalsRequired} of the following approvers:"
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
msgstr ""
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
+msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
+msgstr "%{ifLabelStart}se%{ifLabelEnd} %{scanners} encontrar mais de %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilidades em uma solicitação de mesclagem aberta visando %{branches}"
+
+msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval from %{approvalsRequired} of the following approvers:"
+msgstr "%{thenLabelStart}Então%{thenLabelEnd} Requer aprovação de %{approvalsRequired} dos seguintes aprovadores:"
+
msgid "ScanResultPolicy|add an approver"
msgstr "adicionar um aprovador"
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] "resultado em wiki"
msgstr[1] "resultados em wiki"
+msgid "SearchToken|Assignee"
+msgstr "Responsável"
+
+msgid "SearchToken|Reviewer"
+msgstr "Revisor"
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34286,6 +34693,9 @@ msgstr "Configurações de segurança"
msgid "Security Dashboard"
msgstr "Painel de segurança"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Painel de segurança"
@@ -34559,6 +34969,12 @@ msgstr "Aplicar segurança para este projeto. %{linkStart}Mais informações.%{l
msgid "SecurityOrchestration|Failed to load cluster agents."
msgstr ""
+msgid "SecurityOrchestration|Failed to load images."
+msgstr "Falha ao carregar imagens."
+
+msgid "SecurityOrchestration|Failed to load vulnerability scanners."
+msgstr "Falha ao carregar as verificações de vulnerabilidade."
+
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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr "Este grupo"
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-msgstr "Este projeto não contém nenhuma política de segurança."
-
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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar dispensados"
+msgid "SecurityReports|Image"
+msgstr "Imagem"
+
msgid "SecurityReports|Issue Created"
msgstr "Issue criada"
@@ -34955,6 +35374,15 @@ 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 "Projeto"
@@ -35309,9 +35737,6 @@ 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 "Os níveis selecionados não podem ser usados por usuários não administradores para grupos, projetos ou snippets. Se o nível público for restrito, os perfis de usuário só serão visíveis para usuários conectados."
-msgid "Selected projects"
-msgstr "Projetos selecionados"
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr "Serviços"
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr "Defina um modelo de descrição padrão para ser usado para as novas iss
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35948,13 +36367,13 @@ msgid "ShowcaseSecurity|Start a free 30-day Ultimate trial or upgrade your insta
msgstr ""
msgid "ShowcaseSecurity|Start a free trial"
-msgstr ""
+msgstr "Iniciar uma avaliação gratuita"
msgid "ShowcaseSecurity|Take your security to the next level"
-msgstr ""
+msgstr "Leve sua segurança para o próximo nível"
msgid "ShowcaseSecurity|Upgrade now"
-msgstr ""
+msgstr "Atualize agora"
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 ""
@@ -36000,7 +36419,7 @@ msgstr "Mostrando a última versão"
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr "Página de entrada e ajuda"
msgid "Sign-in count:"
msgstr "Contagem de entrada:"
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr "Página de entrada"
@@ -36096,6 +36518,9 @@ msgstr "Restrições de entrada"
msgid "Sign-in text"
msgstr "Texto da entrada"
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr "URL da página de saída"
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr "Solução"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr "Algumas alterações não são exibidas"
@@ -36850,7 +37272,7 @@ msgid "Speed up your pipelines with Needs relationships"
msgstr ""
msgid "Spent at"
-msgstr ""
+msgstr "Gasto em"
msgid "Squash commit message"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "Ativado com sucesso"
@@ -37796,23 +38215,20 @@ msgstr "O suporte a certificados personalizados está desativado. Peça ao admin
msgid "Support page URL"
msgstr "URL da página de suporte"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
-msgstr ""
+msgstr "Encantado"
msgid "Surveys|Happy"
-msgstr ""
+msgstr "Feliz"
msgid "Surveys|Neutral"
-msgstr ""
+msgstr "Neutro"
msgid "Surveys|Sad"
-msgstr ""
+msgstr "Triste"
msgid "Surveys|Unhappy"
-msgstr ""
+msgstr "Insatisfeito"
msgid "Switch Branches"
msgstr "Trocar ramificações"
@@ -37901,6 +38317,9 @@ msgstr "Métricas do sistema (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr "Sistema iniciado"
+
msgid "Table of Contents"
msgstr "Tabela de conteúdos"
@@ -37973,6 +38392,9 @@ msgstr "Cancelar"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr "Criar versão"
+
msgid "TagsPage|Create tag"
msgstr "Criar tag"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Editar o release notes"
+msgid "TagsPage|Edit release"
+msgstr "Editar versão"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Nome de branch, tag ou SHA do commit existente"
@@ -38090,9 +38512,6 @@ msgstr "ID da tarefa: %{elastic_task}"
msgid "Task list"
msgstr "Listas de tarefas"
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr "Estilo do texto"
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr "Obrigado pela sua opinião!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Obrigado pelo seu relatório. Um administrador do GitLab irá analisá-lo em breve."
@@ -38792,9 +39208,6 @@ msgstr ""
msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
msgstr "Os artefatos mais recentes criados por tarefas no pipeline mais recente e bem-sucedido serão armazenados."
-msgid "The latest pipeline for this merge request did not complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ msgstr "O repositório deve ser acessível em %{code_open}http://%{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 "O repositório deve ser acessível em %{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 ""
+
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 ""
@@ -39068,6 +39484,9 @@ msgstr "Não há requisitos arquivados"
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr "Existem vários limites de tamanho em vigor."
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "Já existe um repositório com esse nome no disco"
@@ -39242,9 +39664,6 @@ msgstr "Houve um problema ao enviar o e-mail de confirmação"
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr "Houve um erro ao redefinir os minutos de pipeline do grupo."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "Houve um erro ao redefinir os minutos de pipeline do usuário."
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ msgstr "Esse diretório"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "Este domínio não foi verificado. Você precisará verificar a propriedade antes de o acesso seja permitido."
+msgid "This email address does not look right, are you sure you typed it correctly?"
+msgstr "Este endereço de e-mail não parece correto. Tem certeza de que o digitou corretamente?"
+
msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_link}."
msgstr ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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."
+
+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 "Este repositório"
@@ -40229,6 +40651,9 @@ 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 "Tempo limite"
@@ -40311,9 +40736,6 @@ 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."
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr "Para manter este projeto em andamento, crie uma nova solicitação de me
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr "Muitos usuários encontrados. Ações rápidas são limitadas a no máxi
msgid "TopNav|Go back"
msgstr "Voltar"
+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}."
+
msgid "Topic %{topic_name} was successfully created."
msgstr "O trópico %{topic_name} foi criado com sucesso."
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr "Período de tolerância de dois fatores"
msgid "Type"
msgstr "Tipo"
+msgid "Type to search"
+msgstr "Digite para pesquisar"
+
msgid "U2F Devices (%{length})"
msgstr "Dispositivos U2F (%{length})"
@@ -41133,6 +41564,9 @@ msgstr "Não é possível carregar o diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
+msgid "Unable to parse JSON"
+msgstr "Não foi possível analisar JSON"
+
msgid "Unable to parse the vulnerability report's options."
msgstr "Não é possível analisar as opções do relatório de vulnerabilidade."
@@ -41196,6 +41630,9 @@ msgstr "Solicitações não autenticadas"
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 ""
@@ -41241,9 +41678,6 @@ msgstr "Formato desconhecido"
msgid "Unknown response text"
msgstr "Texto de resposta desconhecido."
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr "Usuario desconhecido"
@@ -41436,9 +41870,6 @@ msgstr "Data de atualização"
msgid "Updating"
msgstr "Atualizando"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr "Atualizando…"
@@ -41466,6 +41897,9 @@ msgstr "Envie um certificado para o seu domínio com todos os intermediários"
msgid "Upload a private key for your certificate"
msgstr "Envie uma chave privada do seu certificado"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Enviar arquivo"
@@ -41490,9 +41924,6 @@ msgstr "Enviando..."
msgid "Upstream"
msgstr "Upstream"
-msgid "Uptime"
-msgstr "Tempo de atividade"
-
msgid "Upvotes"
msgstr "Votos positivos"
@@ -41553,20 +41984,20 @@ 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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
-msgstr ""
-
msgid "UsageQuota|Git repository."
msgstr "Repositório Gif."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
-msgstr ""
+msgstr "Docker de registro de contêiner integrado ao Gitlab para armazenar imagens do Docker."
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Docker de registro de contêiner integrado ao Gitlab para armazenar imagens do Docker. %{linkStart}Mais informações%{linkEnd}"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
msgstr "Inclui artefatos, repositórios, wiki, envios e outros itens."
@@ -41628,6 +42059,9 @@ 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."
@@ -41655,6 +42089,18 @@ msgstr "Tipo de armazenamento"
msgid "UsageQuota|Storage used"
msgstr "Armazenamento usado"
+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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 "A tabela abaixo mostra o uso do período atual"
@@ -41925,6 +42371,11 @@ msgstr ""
msgid "Used"
msgstr "Usado"
+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 "Utilizado pelos membros para entrar em seu grupo no GitLab"
@@ -42018,6 +42469,9 @@ msgstr "Usuário removido com sucesso do grupo."
msgid "User was successfully removed from project."
msgstr "Usuário removido com sucesso do projeto."
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "O usuário foi atualizado com sucesso."
@@ -42126,6 +42580,9 @@ msgstr "Atividade de bot"
msgid "UserProfile|Contributed projects"
msgstr "Projetos contribuídos"
+msgid "UserProfile|Copy user ID"
+msgstr "Copiar ID do usuário"
+
msgid "UserProfile|Edit profile"
msgstr "Editar perfil"
@@ -42207,6 +42664,9 @@ msgstr "Este usuário não está seguindo outros usuários."
msgid "UserProfile|Unconfirmed user"
msgstr "Usuário não confirmado"
+msgid "UserProfile|User ID: %{id}"
+msgstr "ID de usuário: %{id}"
+
msgid "UserProfile|View all"
msgstr "Ver tudo"
@@ -42372,11 +42832,6 @@ msgstr "Não temos dados suficientes para mostrar este estágio."
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr "%{stageCount}+ itens"
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42399,7 +42854,7 @@ msgid "ValueStreamAnalytics|Average number of deployments to production per day.
msgstr "Número médio de implantações para produção por dia."
msgid "ValueStreamAnalytics|DORA metrics"
-msgstr ""
+msgstr "Métricas DORA"
msgid "ValueStreamAnalytics|Dashboard"
msgstr "Painel"
@@ -42431,10 +42886,16 @@ msgstr "Número de novas issues criadas."
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr "Porcentagem de implantações que causam um incidente na produção."
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ msgstr "Verificar configuração"
msgid "Version"
msgstr "Versão"
+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 "Versão %{versionNumber}"
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr "Recomendamos aplicativos de autenticação móvel baseados em nuvem, como Authy, Duo Mobile e LastPass. Podem restaurar o acesso se você perder seu dispositivo de hardware."
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 "Recomendamos o uso de aplicativos autenticadores baseados em nuvem que podem restaurar o acesso se você perder seu dispositivo de hardware."
+
msgid "We sent you an email with reset password instructions"
msgstr "Enviamos um e-mail com instruções de redefinição de senha"
@@ -43490,6 +43960,12 @@ msgstr "O que são eventos de auditoria de instância?"
msgid "What are project audit events?"
msgstr "O que são eventos de auditoria de projetos?"
+msgid "What are some examples?"
+msgstr "Quais são alguns exemplos?"
+
+msgid "What does the setting affect?"
+msgstr "O que a configuração afeta?"
+
msgid "What does this command do?"
msgstr "O que este comando faz?"
@@ -43549,6 +44025,11 @@ msgstr "Quando usar os protocolos %{code_open}http://%{code_close} ou %{code_ope
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 "Ao transferir seu projeto para um grupo, você pode gerenciar facilmente vários projetos, visualizar cotas de uso para armazenamento, minutos de pipeline e usuários e iniciar uma avaliação ou atualizar para um nível pago."
+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 "Quando:"
@@ -43585,6 +44066,12 @@ 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"
@@ -43711,12 +44198,6 @@ msgstr "Criar %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Criar página"
-msgid "WikiPage|Edit rich text"
-msgstr "Editar texto rico"
-
-msgid "WikiPage|Edit source"
-msgstr "Editar fonte"
-
msgid "WikiPage|Format"
msgstr "Formato"
@@ -43793,7 +44274,7 @@ msgid "Will be mapped to"
msgstr ""
msgid "Will deploy to"
-msgstr ""
+msgstr "Será implantado para"
msgid "Wireframe"
msgstr ""
@@ -43816,28 +44297,34 @@ msgstr "Trabalho em andamento (aberto e não atribuído)"
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
-msgstr "Adicionar"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
msgstr ""
+msgid "WorkItem|Add a title"
+msgstr "Adicionar um título"
+
msgid "WorkItem|Add assignee"
msgstr "Adicionar responsável"
msgid "WorkItem|Add assignees"
msgstr "Adicionar responsáveis"
+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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Responsável"
+msgstr[1] "Responsáveis"
msgid "WorkItem|Cancel"
msgstr ""
@@ -43845,36 +44332,54 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
-msgid "WorkItem|Closed"
+msgid "WorkItem|Child removed"
msgstr ""
+msgid "WorkItem|Closed"
+msgstr "Fechado"
+
msgid "WorkItem|Collapse child items"
msgstr ""
msgid "WorkItem|Create task"
-msgstr ""
+msgstr "Criar tarefa"
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
-msgstr ""
+msgid "WorkItem|Delete task"
+msgstr "Excluir tarefa"
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr "Introdução de tarefas"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "Saiba mais sobre tarefas"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
-msgstr ""
+msgstr "Abrir"
+
+msgid "WorkItem|Remove"
+msgstr "Remover"
msgid "WorkItem|Select type"
msgstr "Selecione o tipo"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr "Tarefa excluída"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr "Desfazer"
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr "itens de trabalho"
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 "Você pode agrupar casos de teste usando etiquetas. Para saber mais sobre a direção futura desse recurso, visite %{linkStart}direção de gerenciamento de qualidade página%{linkEnd}."
-msgid "You can have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Você pode convidar um novo membro para %{project_name} ou convidar outro grupo."
@@ -44186,9 +44714,6 @@ msgstr "Você pode convidar um novo membro para %{project_name} ou convidar outr
msgid "You can invite a new member to %{project_name}."
msgstr "Você pode convidar um novo membro para %{project_name}."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "Você pode convidar um novo membro para %{strong_start}%{group_name}%{strong_end}."
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ msgstr "Você pode testar o seu .gitlab-ci.yml no %{linkStart}CI Lint%{linkEnd}.
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
msgstr "Você pode ver a fonte ou %{linkStart}%{cloneIcon} clonar o repositório%{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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr "Você não pode acessar o arquivo bruto. Por favor, aguarde um minuto."
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr "Você não pode se passar por um usuário bloqueado"
@@ -44294,11 +44813,10 @@ msgstr "Você não pode editar arquivos diretamente nesse projeto. Faça um fork
msgid "You could not create a new trigger."
msgstr "Você não pôde criar um novo gatilho."
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr "Você ainda não tem nenhuma inscrição"
@@ -44632,6 +45150,9 @@ 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 "Você já ativou a autenticação de dois fatores usando autenticadores de senha única. Para registrar um dispositivo diferente, você deve primeiro desativar a autenticação de dois fatores."
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr "Seu arquivo deve conter uma coluna chamada %{codeStart}title%{codeEnd}.
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] "Seu grupo gratuito agora está limitado a %d membro"
+msgstr[1] "Seu grupo gratuito agora está limitado a %d membros"
+
+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 "Seus grupos"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "Sua assinatura irá expirar em %{expires_on}"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
msgstr ""
@@ -45111,6 +45634,9 @@ msgstr "artefatos"
msgid "assign yourself"
msgstr "atribuir a si mesmo"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr "%{reportType}: Carregamento resultou em um erro"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr "Todos os clusters"
+msgid "ciReport|All images"
+msgstr "Todas as imagens"
+
msgid "ciReport|All projects"
msgstr "Todos os projetos"
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr "ci_database"
+
msgid "closed"
msgstr "fechado"
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr "criado por"
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr "data não deve ser após 9999-12-31"
@@ -45741,6 +46282,9 @@ msgstr "%{slash_command} substitui o tempo total estimado."
msgid "example.com"
msgstr "example.com"
+msgid "exceeds maximum length (100 usernames)"
+msgstr "excede o comprimento máximo (100 nomes de usuários)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr "tokens de acesso de grupo"
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr "https://seu-servidor-do-bitbucket"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr "se"
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueador por %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr "main_database"
+
msgid "manual"
msgstr ""
@@ -46095,17 +46642,11 @@ msgstr "%{commitCount} será adicionado à %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr "Adiciona %{commitCount} e %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr "Adiciona %{commitCount} para %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
-msgstr ""
+msgstr "Alterações mescladas em %{targetBranch} com %{mergeCommitSha}%{squashedCommits}."
msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
-msgstr ""
+msgstr "As alterações não foram mescladas em %{targetBranch}."
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Essa solicitação de mesclagem não contém alterações"
@@ -46217,9 +46758,6 @@ msgstr "Criar uma issue para resolver todos os tópicos"
msgid "mrWidget|Delete source branch"
msgstr "Excluir branch de origem"
-msgid "mrWidget|Deletes the source branch"
-msgstr "Excluir ramificação de origem"
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Estatísticas de implantação não estão disponíveis atualmente"
@@ -46229,9 +46767,6 @@ msgstr "Não foi possível fechar"
msgid "mrWidget|Dismiss"
msgstr "Dispensar"
-msgid "mrWidget|Does not delete the source branch"
-msgstr "Não exclui a ramificação de origem"
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Falha ao carregar estatísticas de implantação"
@@ -46267,11 +46802,8 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] "Issue mencionada"
msgstr[1] "Issues mencionadas"
-msgid "mrWidget|Merge"
-msgstr "Mesclar"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
-msgstr ""
+msgstr "Mesclagem bloqueada: todas as aprovações necessárias devem ser dadas."
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr "Mesclagem bloqueada: todos os tópicos devem ser resolvidos."
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "Mesclado por"
-msgid "mrWidget|Merges changes into"
-msgstr "Mescla as alterações em"
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "Mesclando! As alterações estão sendo enviadas…"
@@ -46390,21 +46919,9 @@ msgstr "Exibir detalhes de %{widget}"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr "A ramificação %{type} %{codeStart}%{name}%{codeEnd} não existe."
-msgid "mrWidget|The changes were merged into"
-msgstr "Houve merge das alterações em"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Não houve merge para as mudanças em"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "O branch de origem foi excluído"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "A ramificação de origem é %{link} da ramificação de destino"
-msgid "mrWidget|The source branch is being deleted"
-msgstr "A ramificação de origem está sendo excluído"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Falha ao realizar merge automaticamente"
@@ -46721,6 +47238,9 @@ msgstr "repositórios"
msgid "repository:"
msgstr "repositório:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr "satisfeito"
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,14 +47367,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
-msgstr ""
+msgid "the following epics"
+msgstr "os seguintes épicos"
-msgid "the following incident(s) or issue(s)"
-msgstr ""
+msgid "the following incidents or issues"
+msgstr "os seguintes incidentes ou issues"
-msgid "the following issue(s)"
-msgstr ""
+msgid "the following issues"
+msgstr "as seguintes issues"
msgid "the wiki"
msgstr "a wiki"
@@ -46871,6 +47394,9 @@ msgstr "hoje"
msgid "toggle collapse"
msgstr "Ocultar/Expandir"
+msgid "total must be less than or equal to %{size}"
+msgstr "total deve ser menor ou igual a %{size}"
+
msgid "triggered"
msgstr "disparado"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 7edff0a17e9..dca9287dbf0 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} será removido! Tens a certeza?"
+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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,15 +763,15 @@ 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 "%{label_for_message} indisponível"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "A2F"
msgid "2FADevice|Registered On"
msgstr "Registado Em"
-msgid "3 days"
-msgstr "3 dias"
-
msgid "3 hours"
msgstr "3 horas"
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr "30 minutos"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr "8 horas"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Adicionar uma lista de marcadores"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Adicionar uma tabela"
-msgid "Add a task list"
-msgstr "Adicionar uma lista de tarefas"
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 "Adicionaa cabeçalho e rodapé aos emails. Por favor, nota que as definições de cor só serão aplicadas dentro da interface da aplicação"
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr "Todas as alterações foram enviadas"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "Todos os endereços de email serão usados para identificar os teus envios."
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ msgstr "Ocorreu um erro ao buscar projetos de conclusão automática."
msgid "An error occurred while fetching reference"
msgstr ""
+msgid "An error occurred while fetching reviewers."
+msgstr ""
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr "Atribuído a mim"
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
-msgstr "Anexar um ficheiro"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5232,12 +5275,6 @@ msgstr[1] "Anexar %d ficheiros"
msgid "Attaching the file failed."
msgstr "Falha ao anexar o ficheiro."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Eventos de Auditoria"
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "ago"
@@ -5571,8 +5635,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Resolvido automaticamente"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Atualizar, automaticamente, os ramos e tags deste projeto do repositório upstream a cada hora."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Nota"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ 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|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr ""
+
+msgid "BranchRules|Allowed to merge"
+msgstr ""
+
+msgid "BranchRules|Allowed to push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Ramos"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Ativo"
@@ -7196,9 +7307,6 @@ msgstr "Não é possível encontrar o envio HEAD para este ramo"
msgid "Can't find variable: ZiteReader"
msgstr "Não foi possível encontrar a variável: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "Não consegues digitalizar o código?"
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Não foi possível guardar a ordem dos problemas"
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr "Página URL de suporte"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr "A atualizar"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr "Enviar um certificado para o teu domínio com todos os intermediários"
msgid "Upload a private key for your certificate"
msgstr "Enviar uma chave privada do teu certificado"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Enviar ficheiro"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 4daa9fba10e..7ed3e9ccf4e 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:19\n"
msgid " %{start} to %{end}"
msgstr " de la %{start} până la %{end}"
@@ -535,6 +535,9 @@ msgstr "%{actionText} & redeschide %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} este un interval de adrese IP invalid"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} trebuie să fie între %{min} și %{max}"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} a clonat %{original_issue} în %{new_issue}."
@@ -586,11 +589,11 @@ msgstr "%{commit_author_link} a redactat %{commit_authored_timeago} și %{commit
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} greutate finalizată"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} din %{count} sarcini completată"
-msgstr[1] "%{completedCount} din %{count} sarcini completate"
-msgstr[2] "%{completedCount} din %{count} de sarcini completate"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] "%{completedCount} din %{count} (de) element(e) din lista de verificare completate"
+msgstr[1] "%{completedCount} din %{count} (de) elemente din lista de verificare completate"
+msgstr[2] "%{completedCount} din %{count} de elemente din lista de verificare completate"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} din %{totalWeight} din greutate finalizată"
@@ -775,6 +778,9 @@ msgstr "%{integrations_link_start}Integrările%{link_end} vă permit să faceți
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} va fi înlăturat! Sunteți sigur?"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} nu există, sau nu există permisiunea de a adăuga jurnalul de timp la aceasta."
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(s) s-a/s-au atribuit deja"
@@ -826,6 +832,9 @@ msgstr "%{labelStart}Metodă:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}Spațiu de nume:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}Proiect:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Scaner:%{labelEnd} %{scanner}"
@@ -838,15 +847,15 @@ msgstr "%{labelStart}Severitate:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Instrument:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Răspuns nemodificat:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponibil"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 oră"
@@ -961,6 +970,18 @@ msgstr "%{openedEpics} deschise, %{closedEpics} închise"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} deschise, %{closedIssues} închise"
+msgid "%{over_limit_message} To get more members, an owner of the group can start a trial or upgrade to a paid tier."
+msgstr "%{over_limit_message} Pentru obținerea mai multor membri, proprietarul grupului poate să înceapă o perioadă de probă sau să treacă la un nivel plătit."
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr "%{over_limit_message} Pentru a obține mai multe seat-uri, %{link_start}faceți upgrade la un nivel plătit%{link_end}."
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} Dacă doriți să vizualizați și să gestionați membrii, consultați pagina membrilor fiecărui proiect personal. Este recomandat să vă %{link_start}mutați proiectele într-un grup%{link_end} pentru a putea administra cu ușurință utilizatorii și funcțiile."
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} Dacă doriți să vizualizați și să gestionați membrii, consultați pagina membrilor fiecărui proiect personal din spațiul de nume personal. Este recomandat să vă %{link_start}mutați proiectele într-un grup%{link_end} pentru a putea administra cu ușurință utilizatorii și funcțiile."
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed}%% utilizat"
@@ -1042,6 +1063,18 @@ msgstr[0] "Rezultatul %{securityScanner} nu este disponibil deoarece nu a fost r
msgstr[1] "Rezultatele %{securityScanner} nu sunt disponibile deoarece nu a fost rulat niciun pipeline de când a fost activat. %{linkStart}Rulați un pipeline%{linkEnd}"
msgstr[2] "Rezultatele %{securityScanner} nu sunt disponibile deoarece nu a fost rulat niciun pipeline de când a fost activat. %{linkStart}Rulați un pipeline%{linkEnd}"
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} etichetă"
+msgstr[1] "%{selectedLabelsCount} etichete"
+msgstr[2] "%{selectedLabelsCount} de etichete"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} proiect"
+msgstr[1] "%{selectedProjectsCount} proiecte"
+msgstr[2] "%{selectedProjectsCount} de proiecte"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1081,9 +1114,6 @@ 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."
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr "%{strongStart}Trebuie să acordați atenție%{strongEnd} merge request-urile care au nevoie de ajutorul dvs. pentru a merge mai departe, în calitate de responsabil sau recenzent."
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr "%{strongStart}Sfat:%{strongEnd} De asemenea, puteți verifica merge request-urile la nivel local. %{linkStart}Aflați mai multe.%{linkEnd}"
@@ -1624,15 +1654,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "ÃŽnregistrat pe"
-msgid "3 days"
-msgstr "3 zile"
-
msgid "3 hours"
msgstr "3 ore"
-msgid "30 days"
-msgstr "30 de zile"
-
msgid "30 minutes"
msgstr "30 de minute"
@@ -1660,9 +1684,6 @@ msgstr "Vă rugăm să contactați administratorul GitLab dacă sunteți de păr
msgid "409|There was a conflict with your request."
msgstr "A apărut un conflict cu solicitarea dumneavoastră."
-msgid "7 days"
-msgstr "7 zile"
-
msgid "8 hours"
msgstr "8 ore"
@@ -1988,7 +2009,7 @@ msgid "Access Git repositories or the API."
msgstr "Accesați repozitoriile Git sau API."
msgid "Access Token"
-msgstr ""
+msgstr "Token de acces"
msgid "Access Tokens"
msgstr "Tokenuri de acces"
@@ -2108,10 +2129,10 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr "Scanarea de accesibilitate a găsit o eroare de tipul următor: %{code}"
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "Accesibil oricărui utilizator care este autentificat."
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "Accesibil pentru oricine, indiferent de autentificare."
msgid "Account"
msgstr "Cont"
@@ -2239,6 +2260,9 @@ msgstr "Adăugați un acord privind Termenii și condițiile de utilizare și Po
msgid "Add a bullet list"
msgstr "Adăugați o listă cu marcatori"
+msgid "Add a checklist"
+msgstr "Adăugați o listă de verificare"
+
msgid "Add a collapsible section"
msgstr "Adăugați o secțiune pliabilă"
@@ -2278,9 +2302,6 @@ msgstr "Adăugați un sufix la adresa de e-mail Service Desk. %{linkStart}Aflaț
msgid "Add a table"
msgstr "Adăugați un tabel"
-msgid "Add a task list"
-msgstr "Adăugați o listă de sarcini"
-
msgid "Add a title..."
msgstr "Adăugați un titlu..."
@@ -2308,9 +2329,6 @@ msgstr "Adăugare regulă de aprobare"
msgid "Add approvers"
msgstr "Adăugare aprobatori"
-msgid "Add attention request"
-msgstr "Adăugare cerere de atenție"
-
msgid "Add broadcast message"
msgstr "Adăugare mesaj de difuzare"
@@ -2356,6 +2374,9 @@ msgstr "Adăugați mediu"
msgid "Add existing confidential %{issuableType}"
msgstr "Adăugați %{issuableType} confidențial existent"
+msgid "Add existing issue"
+msgstr "Adăugați problema existentă"
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Adăugați antet și subsol la e-mailuri. Vă rugăm să rețineți că setările de culoare vor fi aplicate numai în interfața aplicației"
@@ -3880,6 +3901,9 @@ msgstr "Toate ramurile"
msgid "All changes are committed"
msgstr "Toate schimbările sunt comise"
+msgid "All eligible users"
+msgstr "Toți utilizatorii eligibili"
+
msgid "All email addresses will be used to identify your commits."
msgstr "Toate adresele de e-mail vor fi folosite pentru identificarea commit-urilor dumneavoastră."
@@ -4171,9 +4195,6 @@ msgstr "S-a produs o eroare la preluarea previzualizării Markdown"
msgid "An error occurred while fetching ancestors"
msgstr "A apărut o eroare în timpul preluării predecesorilor"
-msgid "An error occurred while fetching branches."
-msgstr "A apărut o eroare în timpul preluării ramurilor."
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr "A apărut o eroare în timpul preluării ramurilor. Reîncercați căutarea."
@@ -4219,6 +4240,9 @@ msgstr "A apărut o eroare în timpul preluării autocompletării proiectelor."
msgid "An error occurred while fetching reference"
msgstr "A apărut o eroare în timpul preluării referinței"
+msgid "An error occurred while fetching reviewers."
+msgstr "A apărut o eroare în timpul căutării recenzorilor."
+
msgid "An error occurred while fetching tags. Retry the search."
msgstr "A apărut o eroare în timpul căutării etichetelor. Reîncercați căutarea."
@@ -4306,9 +4330,6 @@ msgstr "A apărut o eroare la încărcarea filei „Needsâ€"
msgid "An error occurred while loading the Test Reports tab."
msgstr "A apărut o eroare la încărcarea filei Rapoarte de testare."
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "A apărut o eroare în timpul încărcării formularului cu tokenuri de acces, vă rugăm să încercați din nou."
-
msgid "An error occurred while loading the blob controls."
msgstr "A apărut o eroare în timpul încărcării controalelor pentru blob."
@@ -4394,7 +4415,7 @@ msgid "An error occurred while retrieving projects."
msgstr "A apărut o eroare în timpul recuperării proiectelor."
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "S-a produs o eroare în timpul recuperării setărilor. Reîncărcați pagina pentru a încerca din nou."
msgid "An error occurred while saving changes: %{error}"
msgstr "A apărut o eroare în timpul salvării modificărilor: %{error}"
@@ -4406,7 +4427,7 @@ msgstr[1] "A apărut o eroare în timpul salvării setărilor"
msgstr[2] "A apărut o eroare în timpul salvării setărilor"
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "S-a produs o eroare în timpul salvării setărilor. Încercați să le salvați din nou."
msgid "An error occurred while subscribing to notifications."
msgstr "A apărut o eroare în timp ce vă abonați la notificări."
@@ -4616,7 +4637,7 @@ msgid "Application settings saved successfully"
msgstr "Setările aplicației au fost salvate cu succes"
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "Setările aplicației au fost salvate cu succes."
msgid "Application settings update failed"
msgstr "Actualizarea setărilor aplicației a eșuat"
@@ -4714,14 +4735,26 @@ msgstr "Numai utilizatorii cu adrese de e-mail care corespund acestor domenii se
msgid "ApplicationSettings|Require admin approval for new sign-ups"
msgstr "Necesită aprobarea administratorului pentru noile înscrieri"
+msgid "ApplicationSettings|Require lowercase letters"
+msgstr "Necesită litere minuscule"
+
+msgid "ApplicationSettings|Require numbers"
+msgstr "Necesită numere"
+
+msgid "ApplicationSettings|Require symbols"
+msgstr "Necesită simboluri"
+
+msgid "ApplicationSettings|Require uppercase letters"
+msgstr "Necesită litere majuscule"
+
msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. %{linkStart}What is the supported syntax?%{linkEnd}"
msgstr "Restricționează înscrierile pentru adresele de e-mail care se potrivesc cu regex-ul dat. %{linkStart}Care este sintaxa acceptată?%{linkEnd}"
msgid "ApplicationSettings|Save changes"
msgstr "Salvați modificările"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr "Consultați %{linkStart}Instrucțiunile privind politica de parole%{linkEnd} GitLab."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr "Consultați %{linkStart}instrucțiunile privind politica parolelor%{linkEnd}."
msgid "ApplicationSettings|Send confirmation email on sign-up"
msgstr "Trimiteți un e-mail de confirmare la înscriere"
@@ -4747,6 +4780,18 @@ msgstr "Utilizatorii cu adrese de e-mail care corespund acestor domenii nu se po
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 "Utilizatorii cu adrese de e-mail care corespund acestor domenii nu se pot înscrie. Sunt permise caractere wildcard. Folosiți linii separate sau virgule pentru intrări multiple."
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one lowercase letter (a-z)."
+msgstr "Atunci când este activată, noile parole trebuie să conțină cel puțin o literă minusculă (a-z)."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
+msgstr "Atunci când este activată, noile parole trebuie să conțină cel puțin un număr (0-9)."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one symbol."
+msgstr "Atunci când este activată, noile parole trebuie să conțină cel puțin un simbol."
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one uppercase letter (A-Z)."
+msgstr "Atunci când este activată, noile parole trebuie să conțină cel puțin o literă majusculă (A-Z)."
+
msgid "ApplicationSettings|domain.com"
msgstr "domain.com"
@@ -4897,29 +4942,32 @@ msgstr "Ramura țintă"
msgid "ApprovalRule|Try for free"
msgstr "Încercați gratuit"
+msgid "ApprovalSettings|Keep approvals"
+msgstr "Păstrați aprobările"
+
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "Setările de aprobare a merge request-urilor au fost actualizate."
msgid "ApprovalSettings|Prevent approval by author"
msgstr "Împiedicați aprobarea de către autor"
-msgid "ApprovalSettings|Prevent approval by author."
-msgstr "Împiedicați aprobarea de către autor."
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr "Împiedicați aprobările de către utilizatorii care adaugă commit-uri"
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
-msgstr "Împiedicați aprobările de către utilizatorii care adaugă commit-uri."
-
msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr "Împiedicați editarea regulilor de aprobare în merge request-uri"
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests"
+msgstr "Preveniți modificarea regulilor de aprobare în proiecte și merge request-uri"
+
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
msgstr "Împiedicați editarea regulilor de aprobare în proiecte și merge request-uri."
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
-msgstr "Înlăturați toate aprobările atunci când se adaugă commit-uri la ramura sursă"
+msgid "ApprovalSettings|Remove all approvals"
+msgstr "Înlăturați toate aprobările"
+
+msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
+msgstr "Înlăturați aprobările proprietarilor de coduri dacă fișierele lor au fost modificate"
msgid "ApprovalSettings|Require user password to approve"
msgstr "Solicitați parola utilizatorului pentru a aproba"
@@ -4936,6 +4984,9 @@ msgstr "Această setare este configurată la nivel de instanță și poate fi mo
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed in the group settings by an administrator or group owner."
msgstr "Această setare este configurată în %{groupName} și poate fi modificată în setările grupului numai de către un administrator sau proprietarul grupului."
+msgid "ApprovalSettings|When a commit is added:"
+msgstr "Atunci când se adaugă un commit:"
+
msgid "Approvals are optional."
msgstr "Aprobările sunt opționale."
@@ -4963,9 +5014,6 @@ msgstr "A fost aprobat merge request-ul actual."
msgid "Approved-By"
msgstr "Aprobat-de"
-msgid "Approved. Your attention request was removed."
-msgstr "S-a aprobat. Solicitarea dvs. de atenție a fost înlăturată."
-
msgid "Approver"
msgstr "Aprobator"
@@ -5138,7 +5186,7 @@ msgid "Are you sure you want to remove this nickname?"
msgstr "Sunteți sigur că doriți să înlăturați această poreclă?"
msgid "Are you sure you want to reset the error tracking access token?"
-msgstr ""
+msgstr "Sunteți sigur că doriți să resetați tokenul de acces pentru urmărirea erorilor?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Sunteți sigur că doriți să resetați tokenul pentru verificarea de sănătate?"
@@ -5308,9 +5356,6 @@ msgstr "Atribuit mie"
msgid "Assigned to you"
msgstr "Atribuit d-voastră"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr "Utilizator(i) desemnat(i). Solicitarea dvs. de atenție a fost înlăturată."
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Responsabil"
@@ -5353,8 +5398,8 @@ msgstr "Cel puțin unul dintre Tokenurile de acces personal va expira în curân
msgid "At risk"
msgstr "La risc"
-msgid "Attach a file"
-msgstr "Atașați un fișier"
+msgid "Attach a file or image"
+msgstr "Atașați un fișier sau o imagine"
msgid "Attaching File - %{progress}"
msgstr "Atașarea fișierului - %{progress}"
@@ -5368,12 +5413,6 @@ msgstr[2] "Se atașează %d de fișiere"
msgid "Attaching the file failed."
msgstr "Atașarea fișierului a eșuat."
-msgid "Attention"
-msgstr "Atenție"
-
-msgid "Attention requested"
-msgstr "Se solicită atenție"
-
msgid "Audit Events"
msgstr "Evenimente de audit"
@@ -5434,6 +5473,12 @@ msgstr "Un antet cu acest nume există deja."
msgid "AuditStreams|Active"
msgstr "Activ"
+msgid "AuditStreams|Add a custom header"
+msgstr "Adăugați un antet personalizat"
+
+msgid "AuditStreams|Add a custom value"
+msgstr "Adăugați o valoare personalizată"
+
msgid "AuditStreams|Add an HTTP endpoint to manage audit logs in third-party systems."
msgstr "Adăugați un punct final HTTP pentru a gestiona jurnalele de audit în sistemele terților."
@@ -5452,6 +5497,9 @@ msgstr "S-a produs o eroare la ștergerea destinației fluxului de evenimente de
msgid "AuditStreams|An error occurred when fetching external audit event streams. Please try it again"
msgstr "S-a produs o eroare la preluarea fluxurilor de evenimente de audit extern. Vă rugăm să încercați din nou."
+msgid "AuditStreams|An error occurred when updating external audit event stream destination. Please try it again."
+msgstr "A apărut o eroare la actualizarea destinației fluxului de evenimente de audit extern. Vă rugăm să încercați din nou."
+
msgid "AuditStreams|Cancel editing"
msgstr "Anulați editarea"
@@ -5467,18 +5515,33 @@ msgstr "URL-ul de destinație"
msgid "AuditStreams|Destinations receive all audit event data"
msgstr "Destinațiile primesc toate datele evenimentelor de audit"
+msgid "AuditStreams|Edit %{link}"
+msgstr "Editați %{link}"
+
msgid "AuditStreams|Header"
msgstr "Antet"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
msgstr "A fost atins numărul maxim de %{number} (de) anteturi HTTP."
+msgid "AuditStreams|Save external stream destination"
+msgstr "Salvați destinația fluxului extern"
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr "Configurați streamingul pentru evenimentele de audit"
+msgid "AuditStreams|Stream added successfully"
+msgstr "Flux adăugat cu succes"
+
msgid "AuditStreams|Stream count icon"
msgstr "Pictograma numărului de fluxuri"
+msgid "AuditStreams|Stream deleted successfully"
+msgstr "Flux șters cu succes"
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr "Flux actualizat cu succes"
+
msgid "AuditStreams|Streams"
msgstr "Fluxuri"
@@ -5491,6 +5554,9 @@ msgstr "Acest lucru este excelent pentru a păstra totul într-un singur loc."
msgid "AuditStreams|Value"
msgstr "Valoare"
+msgid "AuditStreams|Verification token"
+msgstr "Token de verificare"
+
msgid "Aug"
msgstr "Aug"
@@ -5707,8 +5773,8 @@ msgstr "Închideți automat incidentul asociat atunci când o notificare de aler
msgid "Automatically resolved"
msgstr "S-a rezolvat automat"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Actualizați automat din oră în oră ramurile și etichetele acestui proiect din repozitoriul din amonte."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr "Actualizați automat ramurile și etichetele acestui proiect din repozitoriul din amonte."
msgid "Autosave|Note"
msgstr "Notă"
@@ -5896,6 +5962,9 @@ msgstr "RulaÈ›i pipeline-urile CI/CD cu Atlassian Bamboo. Trebuie să configuraÈ
msgid "BambooService|The user with API access to the Bamboo server."
msgstr "Utilizatorul cu acces API la serverul Bamboo."
+msgid "Banned"
+msgstr "Interzis"
+
msgid "Banner message"
msgstr "Mesaj banner"
@@ -6247,6 +6316,9 @@ msgstr "Extindeți perioada de încercare"
msgid "Billings|Free groups are limited to %{number} seats."
msgstr "Grupurile gratuite sunt limitate la %{number} seats."
+msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
+msgstr "Grupurile de nivel gratuit și de probă pot invita maximum 20 de membri pe zi."
+
msgid "Billings|In a seat"
msgstr "ÃŽntr-un seat"
@@ -6340,17 +6412,17 @@ msgstr "Explorați toate planurile"
msgid "Billing|Export list"
msgstr "Exportați lista"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr "Grupurile gratuite de pe GitLab sunt limitate la %{maxNamespaceSeats} seat-uri"
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr "Din 22 iunie 2022 (GitLab 15.1), grupurile gratuite vor fi limitate la 5 membri."
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "Începând cu 19 octombrie 2022, grupurile gratuite vor fi limitate la 5 membri."
msgid "Billing|Group invite"
msgstr "Invitație de grup"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-msgstr "În cazul în care grupul conține peste %{maxNamespaceSeats} (de) membri, numai cei care ocupă un seat pot avea acces la spațiul de nume. Pentru a vă asigura că toți membrii (activi și %{linkStart}peste limită%{linkEnd}) pot accesa spațiul de nume, puteți începe o perioadă de încercare sau puteți face upgrade la un nivel plătit."
+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] "Grupurile din nivelul gratuit sunt limitate la %d seat"
+msgstr[1] "Grupurile din nivelul gratuit sunt limitate la %d seat-uri"
+msgstr[2] "Grupurile din nivelul gratuit sunt limitate la %d de seat-uri"
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 "Membrii care au fost invitați printr-o invitație de grup nu pot fi înlăturați. Puteți fie să înlăturați întregul grup, fie să solicitați unui proprietar al grupului invitat să înlăture membrul."
@@ -6367,6 +6439,9 @@ msgstr "Invitație la proiect"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Înlăturați utilizatorul %{username} din abonament"
+msgid "Billing|To ensure all members can access the group when your trial ends, you can upgrade to a paid tier."
+msgstr "Pentru a asigura accesul la grup pentru toți membrii după perioada de probă, se poate trece la un nivel plătit."
+
msgid "Billing|Toggle seat details"
msgstr "Comutare detalii seat on/off"
@@ -6382,14 +6457,11 @@ msgstr "Vizualizați aprobările în așteptare"
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 "Sunteți pe cale să înlăturați utilizatorul %{username} din abonament. Dacă veți continua, utilizatorul va fi înlăturat din grupul %{namespace} și din toate subgrupurile și proiectele acestuia. Această acțiune nu poate fi anulată."
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr "Puteți începe acum să mutați membrii în %{namespaceName}. Un membru își pierde accesul la grup atunci când dezactivați %{strongStart}Într-un seat%{strongEnd}. Dacă mai mult de 5 membri au activată opțiunea %{strongStart}Într-un seat%{strongEnd} după 22 iunie 2022, vom selecta cei 5 membri care își păstrează accesul. Vom număra mai întâi membrii care au roluri de Proprietar și Întreținător, apoi pe cei mai recent activi membri până când vom ajunge la 5 membri. Membrii rămași vor primi un statut de „Peste limită†și își vor pierde accesul la grup."
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr "Grupul dvs. gratuit este acum limitat la %{free_user_limit} membri"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgstr "Puteți începe acum să mutați membrii în %{namespaceName}. Un membru își pierde accesul la grup atunci când dezactivați %{strongStart}Într-un seat%{strongEnd}. Dacă mai mult de 5 membri au activat %{strongStart}Într-un seat%{strongEnd} după 19 octombrie 2022, vom selecta cei 5 membri care își păstrează accesul. Vom număra mai întâi membrii care au roluri Proprietar și Întreținător, apoi pe cei mai recent activi membri până când vom ajunge la 5 membri. Membrii rămași vor primi un statut de „Peste limită†și își vor pierde accesul la grup."
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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 "Grupul dvs. a trecut recent la utilizarea planului gratuit. Grupurile gratuite sunt limitate la %{free_user_limit} membri, iar membrii rămaÈ™i vor primi un statut de „Peste limită†și vor pierde accesul la grup. PuteÈ›i elibera spaÈ›iu pentru noii membri eliminându-i pe cei care nu mai au nevoie de acces sau trecându-i la „Peste limităâ€. Pentru a obÈ›ine un număr nelimitat de membri, puteÈ›i %{link_start}face upgrade%{link_end} la un nivel plătit."
+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 "Recent, grupul dvs. a retrogradat la planul gratuit. %{over_limit_message} Puteți elibera spațiu pentru noii membri, înlăturându-i pe cei care nu mai au nevoie de acces sau trecându-i la peste-limită. %{link_start}Actualizați%{link_end} la un nivel plătit pentru a profita de un număr nelimitat de membri."
msgid "Bitbucket Server Import"
msgstr "Importul din Serverul Bitbucket"
@@ -6724,9 +6796,51 @@ 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 "Sunt acceptate wildcard-uri %{linkStart}%{linkEnd}, cum ar fi *-stable sau production/*."
+
+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 push"
+msgstr "Permise pentru push"
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr "A apărut o eroare în timpul preluării ramurilor."
+
+msgid "BranchRules|Branch"
+msgstr "Ramura"
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr "Creați un wildcard: %{searchTerm}"
+
+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|No matching results"
+msgstr "Nu există rezultate care să corespundă"
+
+msgid "BranchRules|Protections"
+msgstr "Protecții"
+
+msgid "BranchRules|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."
+
+msgid "BranchRules|Require approval from code owners."
+msgstr "Necesită aprobarea proprietarilor de coduri."
+
msgid "Branches"
msgstr "Ramuri"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "Ramuri: %{source_branch} la %{target_branch}"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "Ramuri: %{source_branch} → %{target_branch}"
+
msgid "Branches|Active"
msgstr "Active"
@@ -7336,9 +7450,6 @@ msgstr "Nu se poate găsi commit-ul HEAD pentru această ramură"
msgid "Can't find variable: ZiteReader"
msgstr "Nu se poate găsi variabila: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr "Nu se poate încărca modulul mermaid: %{err}"
-
msgid "Can't scan the code?"
msgstr "Nu puteți scana codul?"
@@ -8029,9 +8140,6 @@ msgstr "Epica copil nu există."
msgid "Child issues and epics"
msgstr "Probleme și epice copii"
-msgid "Children"
-msgstr "Copii"
-
msgid "Chinese language support using"
msgstr "Suport pentru limba chineză folosind"
@@ -8455,6 +8563,9 @@ msgstr "Cloud SQL pentru SQL Server"
msgid "CloudSeed|CloudSQL Instance"
msgstr "Instanța CloudSQL"
+msgid "CloudSeed|Configuration"
+msgstr "Configurare"
+
msgid "CloudSeed|Create cluster"
msgstr "Creați un cluster"
@@ -8473,6 +8584,12 @@ msgstr "Instanțele bazei de date asociate cu acest proiect"
msgid "CloudSeed|Database version"
msgstr "Versiunea bazei de date"
+msgid "CloudSeed|Databases"
+msgstr "Baze de date"
+
+msgid "CloudSeed|Deployments"
+msgstr "Implementări"
+
msgid "CloudSeed|Description"
msgstr "Descriere"
@@ -8530,12 +8647,18 @@ msgstr "Nu există instanțe"
msgid "CloudSeed|Refs"
msgstr "Referințe"
+msgid "CloudSeed|Regions"
+msgstr "Regiuni"
+
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
msgstr "Serviciu în memorie scalabil, sigur și extrem de disponibil pentru Redis"
msgid "CloudSeed|Service"
msgstr "Serviciu"
+msgid "CloudSeed|Service Account"
+msgstr "Contul de servicii"
+
msgid "CloudSeed|Services"
msgstr "Servicii"
@@ -9293,7 +9416,7 @@ msgid "Code block"
msgstr "Bloc de cod"
msgid "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
-msgstr ""
+msgstr "Codul poate fi importat din surse activate în timpul creării proiectului. OmniAuth trebuie să fie configurat pentru GitHub."
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr "Statisticile de coverage de cod pentru %{ref} %{start_date} - %{end_date}"
@@ -9770,7 +9893,7 @@ msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if
msgstr "ConfiguraÈ›i Scanarea dependenÈ›elor în „.gitlab-ci.ymlâ€, creând acest fiÈ™ier dacă nu există deja"
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "Configurați urmărirea erorilor"
msgid "Configure GitLab"
msgstr "Configurați GitLab"
@@ -9812,7 +9935,7 @@ msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeSt
msgstr "Configurați un fișier %{codeStart}.gitlab-webide.yml%{codeEnd} în directorul %{codeStart}.gitlab%{codeEnd} pentru a începe să utilizați Terminalul Web. %{helpStart}Aflați mai multe.%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
-msgstr ""
+msgstr "Configurați permisiunile avansate, Large File Storage, autentificarea cu doi factori și setările CI/CD."
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
msgstr "Configurați permisiunile avansate, Large File Storage, autentificarea cu doi factori și setările privind relațiile cu clienții."
@@ -10235,7 +10358,7 @@ msgid "ContainerRegistry|Set up cleanup"
msgstr "Configurați curățarea"
msgid "ContainerRegistry|Show full path"
-msgstr ""
+msgstr "Afișați calea completă"
msgid "ContainerRegistry|Some tags were not deleted"
msgstr "Unele etichete nu au fost șterse"
@@ -10363,9 +10486,6 @@ msgstr "Puteți adăuga o imagine în acest registru cu ajutorul următoarelor c
msgid "Content parsed with %{link}."
msgstr "Conținut analizat cu %{link}."
-msgid "ContentEditor|Table of Contents"
-msgstr "Cuprins"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr "Trebuie să furnizați o funcție renderMarkdown sau un serializator personalizat"
@@ -10804,9 +10924,6 @@ msgstr "Creați %{type}"
msgid "Create %{workspace} label"
msgstr "Creați eticheta %{workspace}"
-msgid "Create Google Cloud project"
-msgstr "Creați proiectul Google Cloud"
-
msgid "Create New Directory"
msgstr "Creați un nou director"
@@ -11257,6 +11374,9 @@ msgstr "Card de credit:"
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilități critice prezente"
+msgid "Crm|Active"
+msgstr "Activ"
+
msgid "Crm|Contact"
msgstr "Contact"
@@ -11644,6 +11764,9 @@ msgstr "Vizualizarea DAG necesită cel puțin 3 joburi dependente."
msgid "DAST Configuration"
msgstr "Configurația DAST"
+msgid "DAST configuration not found"
+msgstr "Configurația DAST nu a fost găsită"
+
msgid "DAST profile not found: %{name}"
msgstr "Profilul DAST nu a fost găsit: %{name}"
@@ -11662,6 +11785,9 @@ msgstr "Media (ultimele %{days}d)"
msgid "DORA4Metrics|Change failure rate"
msgstr "Rata de eșec a modificărilor"
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr "Rata de eșec a modificării (procentaj)"
+
msgid "DORA4Metrics|Date"
msgstr "Data"
@@ -11677,6 +11803,9 @@ msgstr "Frecvența de implementare"
msgid "DORA4Metrics|Lead time for changes"
msgstr "Timpul necesar pentru modificări"
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr "Durata de executare a modificărilor (zile medii)"
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr "Media (ultimele %{days}d)"
@@ -11722,6 +11851,9 @@ msgstr "Graficul afișează timpul mediu dintre îmbinarea și implementarea unu
msgid "DORA4Metrics|Time to restore service"
msgstr "Timpul pentru restabilirea serviciului"
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr "Timpul de restabilire a serviciului ( zile medii)"
+
msgid "DSN"
msgstr "DSN"
@@ -11758,9 +11890,21 @@ msgstr "Configurația 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 "Activați DAST pentru a testa automat vulnerabilitățile din aplicația, site-ul web sau API-ul care rulează în proiectul, în pipeline-ul CI/CD. Modificările de configurare trebuie aplicate în fișierul .gitlab-ci.yml pentru a intra în vigoare. Pentru detalii despre toate opțiunile de configurare, consultați %{linkStart}documentația GitLab DAST%{linkEnd}."
+msgid "DastConfig|Enabled"
+msgstr "Activat"
+
msgid "DastConfig|Generate code snippet"
msgstr "Generați un fragment de cod"
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr "Ultima scanare a fost declanșată %{runTimeAgo} în pipeline "
+
+msgid "DastConfig|No previous scans found for this project"
+msgstr "Nu au fost găsite scanări anterioare pentru acest proiect"
+
+msgid "DastConfig|Not enabled"
+msgstr "Neactivat"
+
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 "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."
@@ -12457,6 +12601,9 @@ msgstr "Ștergeți cheia de implementare"
msgid "Delete file"
msgstr "Ștergeți fișierul"
+msgid "Delete identity"
+msgstr "Ștergeți identitatea"
+
msgid "Delete image"
msgstr "Ștergeți imaginea"
@@ -12481,6 +12628,12 @@ msgstr "Ștergeți programul de pipeline"
msgid "Delete project"
msgstr "Ștergeți proiectul"
+msgid "Delete release"
+msgstr "Ștergeți versiunea"
+
+msgid "Delete release %{release}?"
+msgstr "Ștergeți versiunea %{release}?"
+
msgid "Delete row"
msgstr "Ștergeți rândul"
@@ -12538,6 +12691,15 @@ msgstr "Nu s-a reușit eliminarea webhook-urilor. Vă rugăm să încercați din
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "Nu s-a putut înlătura repozitoriul wiki. Vă rugăm să încercați din nou sau să contactați administratorul."
+msgid "DeleteRelease|Are you sure you want to delete this release?"
+msgstr "Sunteți sigur că doriți să ștergeți această versiune?"
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr "Pentru mai multe detalii, consultați %{docsPathStart}Ștergerea unei versiuni%{docsPathEnd}."
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr "Sunteți pe cale să ștergeți versiunea %{release} și activele acesteia. Eticheta Git %{tag} nu va fi ștearsă."
+
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
msgstr "Fluxul de valori „%{name}†a fost șters"
@@ -12562,9 +12724,6 @@ msgstr "S-a șters ramura sursă."
msgid "Deletes the source branch"
msgstr "Șterge ramura sursă"
-msgid "Deletes the source branch."
-msgstr "Șterge ramura sursă."
-
msgid "Deleting"
msgstr "Ștergerea"
@@ -12778,6 +12937,9 @@ msgstr[0] "Desfășurare"
msgstr[1] "Desfășurări"
msgstr[2] "Desfășurări"
+msgid "Deploy Key"
+msgstr "Cheie de implementare"
+
msgid "Deploy Keys"
msgstr "Chei de implementare"
@@ -13033,8 +13195,8 @@ msgstr "Opțiuni de aprobare"
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr "Aprobați sau respingeți implementarea #%{deploymentIid}"
-msgid "DeploymentApproval|Approved by %{user} %{time}"
-msgstr "Aprobat de %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
+msgstr "Aprobat la %{time}"
msgid "DeploymentApproval|Approved by you %{time}"
msgstr "Aprobat de d-voastră %{time}"
@@ -13840,9 +14002,6 @@ msgstr "Url-ul paginilor de documentație"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "Documente reindexate: %{processed_documents} (%{percentage}%%)"
-msgid "Does not delete the source branch."
-msgstr "Nu șterge ramura sursă."
-
msgid "Domain"
msgstr "Domeniu"
@@ -14066,7 +14225,7 @@ msgid "Edit Comment"
msgstr "Editați comentariul"
msgid "Edit Deploy Key"
-msgstr "Editați cheia de distribuire"
+msgstr "Editați cheia de implementare"
msgid "Edit Geo Site"
msgstr "Editați site-ul Geo"
@@ -14251,9 +14410,6 @@ msgstr "Niciunul. Selectați spațiile de nume pentru indexare."
msgid "Elastic|None. Select projects to index."
msgstr "Niciunul. Selectați proiectele de indexat."
-msgid "Eligible users"
-msgstr "Utilizatori eligibili"
-
msgid "Email"
msgstr "E-mail"
@@ -14575,9 +14731,6 @@ msgstr "Protocoale de acces Git activate"
msgid "Enabled OAuth authentication sources"
msgstr "Surse de autentificare OAuth activate"
-msgid "Encountered an error while rendering: %{err}"
-msgstr "A apărut o eroare în timpul redării: %{err}"
-
msgid "End Time"
msgstr "Ora de terminare"
@@ -15076,6 +15229,9 @@ msgstr "Eroare la crearea repozitoriului pentru fragmentul de cod cu ID-ul %{sni
msgid "Error creating the snippet"
msgstr "Eroare la crearea fragmentului de cod"
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr "Eroare de creare a detectării vulnerabilității: %{errors}"
+
msgid "Error deleting project. Check logs for error details."
msgstr "Eroare la ștergerea proiectului. Verificați jurnalele pentru detalii despre eroare."
@@ -15257,7 +15413,7 @@ msgid "Error: Unable to find AWS role for current user"
msgstr "Eroare: nu se poate găsi rolul AWS pentru utilizatorul curent"
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "Tokenul de acces este %{token_in_code_tag}"
msgid "ErrorTracking|Active"
msgstr "Activ"
@@ -16054,24 +16210,21 @@ msgstr "Nu s-a reușit înlăturarea unei ședințe Zoom"
msgid "Failed to remove a to-do item for the design."
msgstr "Nu s-a reușit înlăturarea unei sarcini de-făcut pentru elementul de design"
-msgid "Failed to remove attention because no user was found."
-msgstr "Nu s-a reușit înlăturarea atenției deoarece nu a fost găsit niciun utilizator."
-
msgid "Failed to remove mirror."
msgstr "Nu s-a reușit eliminarea replicii"
msgid "Failed to remove the pipeline schedule"
msgstr "Nu s-a reușit înlăturarea programului pipeline-ului"
+msgid "Failed to remove timelog"
+msgstr "Nu s-a reușit înlăturarea jurnalului de timp"
+
msgid "Failed to remove user identity."
msgstr "Nu s-a reușit înlăturarea identității utilizatorului."
msgid "Failed to remove user key."
msgstr "Nu s-a reușit înlăturarea cheii utilizatorului."
-msgid "Failed to request attention because no user was found."
-msgstr "Nu s-a reușit solicitarea atenției deoarece nu a fost găsit niciun utilizator."
-
msgid "Failed to retrieve page"
msgstr "Nu s-a reușit recuperarea paginii"
@@ -16087,6 +16240,9 @@ msgstr "Nu s-a reușit salvarea preferințelor (%{error_message})."
msgid "Failed to save preferences."
msgstr "Nu s-a reușit salvarea preferințelor."
+msgid "Failed to save timelog"
+msgstr "Nu s-a reușit salvarea jurnalului de timp"
+
msgid "Failed to set due date because the date format is invalid."
msgstr "Nu s-a reușit setarea datei scadente deoarece formatul datei nu este valid."
@@ -16132,9 +16288,6 @@ msgstr "Fals pozitiv"
msgid "Fast timeout"
msgstr "Timeout rapid"
-msgid "Fast-forward merge without a merge commit"
-msgstr "Îmbinare fast-forward fără un commit de îmbinare"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Lansări mai rapide. Cod mai bun. Mai puțină bătaie de cap."
@@ -16378,6 +16531,9 @@ msgstr "Feb"
msgid "February"
msgstr "Februarie"
+msgid "Feedback issue"
+msgstr "Problemă de feedback"
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr "Obțineți și verificați această ramură de caracteristică a merge request-ului:"
@@ -16541,10 +16697,10 @@ msgid "Find file"
msgstr "Căutați un fișier"
msgid "Fingerprint (MD5)"
-msgstr ""
+msgstr "Amprentă (MD5)"
msgid "Fingerprint (SHA256)"
-msgstr ""
+msgstr "Amprentă (SHA256)"
msgid "Fingerprints"
msgstr "Amprente"
@@ -16795,6 +16951,12 @@ msgstr "Framework-ul a fost eliminat cu succes"
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Versiune de încercare gratuită a GitLab.com Ultimate"
+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 "Freeze end"
msgstr "Înghețul se termină"
@@ -16819,11 +16981,17 @@ msgstr "De la %{code_open}%{source_title}%{code_close} în"
msgid "From %{providerTitle}"
msgstr "De la %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr "Începând cu 22 iunie 2022 (GitLab 15.1), spațiile de nume personale gratuite și grupurile de nivel superior vor fi limitate la %{free_limit} (de) membri"
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] "Începând cu 19 octombrie 2022, grupurile gratuite vor fi limitate la %d membru."
+msgstr[1] "Începând cu 19 octombrie 2022, grupurile gratuite vor fi limitate la %d membri."
+msgstr[2] "Începând cu 19 octombrie 2022, grupurile gratuite vor fi limitate la %d membri."
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr "Începând cu 22 iunie 2022 (GitLab 15.1), puteți avea maxim %{free_limit} membri unici în toate proiectele personale."
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] "Începând cu 19 octombrie 2022, puteți avea maximum %d membru unic în toate proiectele personale."
+msgstr[1] "Începând cu 19 octombrie 2022, puteți avea maximum %d membri unici în toate proiectele personale."
+msgstr[2] "Începând cu 19 octombrie 2022, puteți avea maximum %d de membri unici în toate proiectele personale."
msgid "From issue creation until deploy to production"
msgstr "De la crearea problemei până la implementarea în producție"
@@ -16882,6 +17050,9 @@ msgstr "Generați tokenuri de acces de proiect cu scopuri specifice acestui proi
msgid "Generate site and private keys at"
msgstr "Generați site-ul și cheile private la"
+msgid "Generated with JSON data"
+msgstr "Generat cu date JSON"
+
msgid "Generic"
msgstr "Generic"
@@ -16933,6 +17104,9 @@ msgstr "%{component} s-a sincronizat"
msgid "Geo|%{component} verified"
msgstr "%{component} s-a verificat"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr "%{label} %{timeAgo}"
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} nu poate fi necompletat(ă)"
@@ -17107,9 +17281,6 @@ msgstr "Dacă doriți să faceți modificări, trebuie să vizitați site-ul pri
msgid "Geo|In progress"
msgstr "În curs de desfășurare"
-msgid "Geo|In sync"
-msgstr "ÃŽn sincronizare"
-
msgid "Geo|Internal URL"
msgstr "URL intern"
@@ -17167,9 +17338,6 @@ msgstr "Nu s-a găsit niciun site Geo"
msgid "Geo|No available replication slots"
msgstr "Nu există sloturi de replicare disponibile"
-msgid "Geo|Not synced yet"
-msgstr "Nu a fost încă sincronizat"
-
msgid "Geo|Nothing found…"
msgstr "Nu s-a găsit nimic…"
@@ -17425,9 +17593,6 @@ msgstr "Nesănătos"
msgid "Geo|Unknown"
msgstr "Necunoscut"
-msgid "Geo|Unknown state"
-msgstr "Stare necunoscută"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "Actualizat %{timeAgo}"
@@ -17537,40 +17702,40 @@ msgid "Git version"
msgstr "Versiunea Git"
msgid "GitAbuse|Excluded users"
-msgstr ""
+msgstr "Utilizatori excluși"
msgid "GitAbuse|Number of repositories"
-msgstr ""
+msgstr "Numărul de repozitorii"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "Numărul de repozitorii nu poate fi gol. Setați la 0 pentru nicio limită."
msgid "GitAbuse|Number of repositories must be a number."
-msgstr ""
+msgstr "Numărul de repozitorii trebuie să fie un număr."
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr ""
+msgstr "Numărul de repozitorii trebuie să fie cuprins între %{minNumRepos}-%{maxNumRepos}."
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "Perioada de timp de raportare (secunde)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "Perioada de raportare nu poate fi goală. Setați la 0 pentru nicio limită."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "Perioada de raportare trebuie să fie un număr."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "Perioada de raportare trebuie să fie cuprinsă între %{minTimePeriod}-%{maxTimePeriod} (de) secunde."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr ""
+msgstr "Numărul maxim de repozitorii unice pe care un utilizator le poate descărca în perioada de timp specificată înainte de a fi interzis."
msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
-msgstr ""
+msgstr "Utilizatorii care sunt excluși de la limita ratei de abuz Git."
msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
-msgstr ""
+msgstr "Nu puteți specifica mai mult de %{maxExcludedUsers} (de) utilizatori excluși"
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
msgstr "Limita ratei API GitHub a fost depășită. Încercați din nou după %{reset_time}"
@@ -17611,6 +17776,9 @@ msgstr "Problema GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
+msgid "GitLab Logo"
+msgstr "Logoul GitLab"
+
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17635,9 +17803,6 @@ msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
msgstr "Solicitarea contului GitLab a fost respinsă"
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr "Configurația GitLab și Google Cloud pare să fie incompletă. Acest lucru poate fi probabil rezolvat de către echipa de administrare GitLab. Puteți partaja aceste jurnale cu ei:"
-
msgid "GitLab commit"
msgstr "Commit GitLab"
@@ -17731,6 +17896,9 @@ msgstr "Poate fi suprascrisă pentru fiecare proiect. Pentru nicio limită, intr
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Certificat: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "Verificați starea pipeline-ului"
+
msgid "GitLabPages|Configure pages"
msgstr "Configurare pages"
@@ -17782,6 +17950,9 @@ msgstr "Salvați modificările"
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 "Ceva nu a funcționat bine la obținerea certificatului Let's Encrypt pentru %{domain}. Pentru a încerca din nou, vizitați %{link_start}detaliile domeniului%{link_end}."
+msgid "GitLabPages|Start over"
+msgstr "Începeți din nou"
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr "Suportul pentru domenii și certificate este dezactivat. Solicitați administratorului sistemului dvs. să-l activeze."
@@ -17789,11 +17960,14 @@ msgid "GitLabPages|Unverified"
msgstr "Neconfirmat"
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "Actualizarea configurației Pages..."
msgid "GitLabPages|Verified"
msgstr "Verificat"
+msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
+msgstr "Așteptând ca Pipeline-ul Pages să se finalizeze..."
+
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 "Când este activată, toate încercările de a vă vizita site-ul web prin HTTP sunt redirecționate automat către HTTPS utilizând un răspuns cu codul de stare 301. Necesită un certificat valid pentru toate domeniile. %{docs_link_start}Aflați mai multe.%{link_end}"
@@ -17806,6 +17980,9 @@ msgstr "Cu GitLab Pages puteți găzdui site-ul dvs. static direct din repozitor
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 "Site-ul Pages nu este configurat încă. Consultați %{docs_link_start}documentația GitLab Pages%{link_end} pentru a afla cum să încărcați site-ul static și să solicitați ca GitLab să îl servească. De asemenea, vă puteți inspira din %{samples_link_start}exemplele de proiecte 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 "Proiectul dvs. a fost configurat pentru Pages. Acum trebuie să așteptăm ca Pipeline-ul să reușească pentru prima dată."
+
msgid "GitLabPages|Your pages are served under:"
msgstr "Site-urile dvs. pages sunt servite sub:"
@@ -18124,18 +18301,15 @@ msgstr "Mergeți la fragmentele dvs. de cod"
msgid "Google Cloud"
msgstr "Google Cloud"
+msgid "Google Cloud Error - %{error}"
+msgstr "Eroare Google Cloud - %{error}"
+
msgid "Google Cloud Project"
msgstr "Proiectul Google Cloud"
msgid "Google Cloud authorizations required"
msgstr "Sunt necesare autorizări Google Cloud"
-msgid "Google Cloud project misconfigured"
-msgstr "Proiectul Google Cloud este configurat greșit"
-
-msgid "Google Cloud project required"
-msgstr "Este necesar un proiect Google Cloud"
-
msgid "GoogleCloud|Cancel"
msgstr "Anulare"
@@ -18355,9 +18529,6 @@ msgstr "Navigare în grup"
msgid "Group overview content"
msgstr "Conținutul general al grupului"
-msgid "Group owners can register group runners in the %{link}"
-msgstr "Proprietarii grupului pot înregistra executorii de grup în %{link}"
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr "Calea grupului este deja luată. Vă sugerăm una care este disponibilă."
@@ -18511,8 +18682,8 @@ msgstr "Sunteți sigur că doriți să resetați tokenul SCIM? Provizionarea SCI
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr "Înainte de a impune SSO, activați autentificarea SAML."
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
-msgstr "Înainte de a impune autentificarea exclusiv SSO pentru activitatea Git, activați autentificarea exclusiv SSO pentru activitatea web."
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
+msgstr "Înainte de a impune autentificarea exclusiv SSO pentru activitatea Git pentru toți utilizatorii, autentificarea exclusiv SSO trebuie să fie activată pentru activitatea web."
msgid "GroupSAML|Certificate fingerprint"
msgstr "Amprenta digitală a certificatului"
@@ -18676,8 +18847,8 @@ msgstr "Se aplică tuturor subgrupurilor, cu excepția cazului în care este în
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Pipeline-ul Auto DevOps a fost actualizat pentru grup"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
-msgstr "Interziceți automat utilizatorii care descarcă mai mult decât numărul specificat de proiecte în intervalul specificat."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
+msgstr "Interziceți automat utilizatorii care descarcă mai mult de un anumit număr de repozitorii într-un anumit interval de timp."
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 "Este disponibil numai pentru grupul de nivel superior. Se aplică la toate subgrupurile. Grupurile deja partajate cu un grup din afara %{group} sunt în continuare partajate, doar dacă nu sunt eliminate manual."
@@ -18724,6 +18895,9 @@ msgstr "Notificările prin e-mail sunt dezactivate"
msgid "GroupSettings|Export group"
msgstr "Export de grup"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr "Limita ratei de abuz Git"
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr "Membrii grupului nu sunt notificați în cazul în care grupul este menționat."
@@ -18736,15 +18910,9 @@ msgstr "Dacă nu este specificată la nivel de grup sau de instanță, valoarea
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 "Dacă vizibilitatea grupului părinte este mai mică decât vizibilitatea curentă a grupului, nivelele de vizibilitate pentru subgrupuri și proiecte vor fi modificate pentru a corespunde vizibilității noului grup părinte."
-msgid "GroupSettings|Interval (seconds)"
-msgstr "Interval (secunde)"
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr "Membrii nu pot invita grupuri din afara grupului %{group} și a subgrupurilor sale"
-msgid "GroupSettings|Number of projects"
-msgstr "Numărul de proiecte"
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr "Organizațiile și contactele pot fi create și asociate cu probleme."
@@ -18763,9 +18931,6 @@ msgstr "Împiedicați forkingul în afara grupului"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "Setarea prevenirii forkingului nu a fost salvată"
-msgid "GroupSettings|Project download rate limit"
-msgstr "Limita ratei de descărcare a proiectelor"
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr "Proiectele din %{group} nu pot fi partajate cu alte grupuri"
@@ -18790,15 +18955,9 @@ msgstr "Setați o dimensiune limită pentru tot conținutul din fiecare site Pag
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr "Setați numele și protecțiile inițiale pentru ramura implicită a noilor repozitorii create în grup."
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr "Setați la 0 pentru a dezactiva limitarea."
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "Pipeline-ul Auto DevOps se execută dacă nu se găsește niciun fișier de configurare CI alternativ."
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-msgstr "Numărul maxim de proiecte unice pe care un utilizator le poate descărca în intervalul specificat înainte de a fi interzis. Setați la 0 pentru a dezactiva limitarea."
-
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 "Proiectele din acest subgrup pot fi selectate ca șabloane pentru proiecte noi create în grup. %{link_start}Aflați mai multe.%{link_end}"
@@ -18916,6 +19075,9 @@ msgstr "Puteți gestiona permisiunile și accesul membrilor grupului dvs. la fie
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 "Nu aveți permisiunile necesare pentru a crea un subgrup sau un proiect în acest grup. Vă rugăm să contactați un proprietar al acestui grup pentru a crea un nou subgrup sau proiect."
+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 "%{groupsLinkStart}Grupurile%{groupsLinkEnd} și %{subgroupsLinkStart}subgrupurile%{subgroupsLinkEnd} vă permit să gestionați și să colaborați în cadrul mai multor proiecte. Membrii unui grup au acces la toate proiectele acestuia."
+
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 "%{linkStart}Grupurile%{linkEnd} vă permit să gestionați și să colaborați în cadrul mai multor proiecte. Membrii unui grup au acces la toate proiectele sale."
@@ -18934,6 +19096,9 @@ msgstr "Creați un grup"
msgid "GroupsNew|Create new group"
msgstr "Creați un grup nou"
+msgid "GroupsNew|Create subgroup"
+msgstr "Creați un subgrup"
+
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 "Creați aceasta în %{pat_link_start}setările de utilizator%{pat_link_end} ale instanței GitLab sursă. Din %{short_living_link_start}motive de securitate%{short_living_link_end}, utilizați o dată de expirare scurtă atunci când creați tokenul."
@@ -18979,6 +19144,9 @@ msgstr "Pentru a importa un grup, navigați la setările de grup pentru instanț
msgid "GroupsNew|Upload file"
msgstr "Încărcați fișierul"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "De asemenea, puteți %{linkStart}importa un grup existent%{linkEnd}."
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "de exemplu, h8d3f01016698e..."
@@ -19057,6 +19225,15 @@ msgstr "Înlăturați avatarul"
msgid "Groups|Save changes"
msgstr "Salvați modificările"
+msgid "Groups|Subgroup URL"
+msgstr "URL-ul subgrupului"
+
+msgid "Groups|Subgroup name"
+msgstr "Numele subgrupului"
+
+msgid "Groups|Subgroup slug"
+msgstr "Slug-ul subgrupului"
+
msgid "Guideline"
msgstr "Ghid"
@@ -19075,8 +19252,8 @@ msgstr "HTTP Basic: Acces refuzat\\n Trebuie să folosiți un token de acces per
msgid "Harbor Registry"
msgstr "Registrul Harbor"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$HARBOR_PASSWORD’, ‘$HARBOR_URL’ and ‘$HARBOR_PROJECT’ will be created for CI/CD use."
-msgstr "După ce integrarea Harbor este activată, variabilele globale \"$HARBOR_USERNAME\", \"$HARBOR_PASSWORD\", \"$HARBOR_URL\" și \"$HARBOR_PROJECT\" vor fi create 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 "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|Base URL of the Harbor instance."
msgstr "URL-ul de bază al instanței Harbor."
@@ -19189,12 +19366,6 @@ msgstr "Căile de stocare ale repozitoriilor hash"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr "Stocarea hash nu mai poate fi dezactivată pentru proiectele noi"
-msgid "Have a quick chat with us about your experience."
-msgstr "Vă invităm să discutați cu noi pe scurt despre experiența dumneavoastră."
-
-msgid "Have more to say about GitLab?"
-msgstr "Mai aveți și altceva de spus despre GitLab?"
-
msgid "Header logo"
msgstr "Logoul de antet"
@@ -19417,6 +19588,9 @@ msgstr "Alerta originală:"
msgid "HighlightBar|Time to SLA:"
msgstr "Timp până la SLA:"
+msgid "Historical release"
+msgstr "Lansare istorică"
+
msgid "History"
msgstr "Istoric"
@@ -19486,6 +19660,9 @@ msgstr "Cum se utilizează un terminal web?"
msgid "How do I use file templates?"
msgstr "Cum pot utiliza șabloanele de fișiere?"
+msgid "How does pull mirroring work?"
+msgstr "Cum funcționează replicarea pull?"
+
msgid "How many seconds an IP counts toward the IP address limit."
msgstr "Câte secunde contează un IP pentru limita de adrese IP."
@@ -19669,6 +19846,9 @@ msgstr "Contul dvs. a fost verificat cu succes. Veți fi redirecționat către c
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "Codul dvs. de verificare expiră după %{expires_in_minutes} (de) minute."
+msgid "Identity|Provider ID"
+msgstr "ID-ul furnizorului"
+
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 "Dacă un câmp indexat depășește această limită, acesta este trunchiat la acest număr de caractere. Restul conținutului nu este nici indexat și nici nu poate fi căutat. Acest lucru nu se aplică la indexarea depozitelor și a wiki-urilor. Pentru caractere nelimitate, setați această valoare la 0."
@@ -19696,6 +19876,9 @@ msgstr "Dacă este activată, numai ramurile protejate vor fi replicate."
msgid "If no options are selected, only administrators can register runners."
msgstr "Dacă nu este selectată nicio opțiune, numai administratorii pot înregistra executorii."
+msgid "If none of the options work, try contacting a GitLab administrator."
+msgstr "Dacă nu funcționează niciuna dintre aceste opțiuni, încercați să contactați un administrator 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 "Dacă numărul de utilizatori activi depășește limita de utilizator, veți fi taxat pentru numărul de %{users_over_license_link} la următoarea reconciliere a licenței."
@@ -19978,6 +20161,9 @@ msgstr[2] "Se importă %d de repozitorii"
msgid "Importing..."
msgstr "Importarea..."
+msgid "Import|The repository could not be imported."
+msgstr "Repozitoriul nu a putut fi importat."
+
msgid "Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials."
msgstr "Nu există un repozitoriu Git valid la această adresă URL. Dacă depozitul HTTP nu este accesibil publicului, verificați-vă acreditările."
@@ -20023,9 +20209,6 @@ msgstr "%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Franc
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr "%{strong_start}Roluri multiple de aprobare%{strong_end} — inclusiv proprietarii de coduri și aprobările de îmbinare necesare"
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr "%{strong_start}În general, cât de dificil sau ușor a fost să începeți cu GitLab?%{strong_end}"
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr "*GitLab*, substantiv: un sinonim pentru echipe eficiente"
@@ -20083,9 +20266,6 @@ msgstr "Grafice Burn up/down"
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 "Prin activarea proprietarilor de coduri și necesitatea aprobărilor de îmbinare, persoana potrivită va revizui MR-ul potrivit. Acest lucru este avantajos pentru ambele părți: un cod mai curat și un proces de revizuire mai eficient."
-msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr "Faceți clic pe numărul de mai jos care corespunde răspunsului dvs. — 1 fiind foarte dificil, 5 fiind foarte ușor."
-
msgid "InProductMarketing|Code owners"
msgstr "Proprietarii de coduri"
@@ -20128,9 +20308,6 @@ msgstr "Scanarea dependențelor"
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr "Știați că echipele care utilizează GitLab sunt mult mai eficiente?"
-msgid "InProductMarketing|Difficult"
-msgstr "Dificil"
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr "Dați-i drumul și creați un proiect și un repo"
@@ -20140,18 +20317,12 @@ msgstr "Descoperiți Premium & Ultimate"
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr "Descoperiți Premium & Ultimate."
-msgid "InProductMarketing|Do you have a minute?"
-msgstr "Aveți un minut?"
-
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
msgstr "Aveți un coechipier care ar fi perfect pentru această sarcină?"
msgid "InProductMarketing|Dynamic application security testing"
msgstr "Testarea dinamică a securității aplicațiilor"
-msgid "InProductMarketing|Easy"
-msgstr "Ușor"
-
msgid "InProductMarketing|Epics"
msgstr "Epice"
@@ -20170,9 +20341,6 @@ msgstr "Descoperiți potențialul GitLab CI/CD"
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr "Feedbackul de la utilizatori ca dvs. îmbunătățește cu adevărat produsul nostru. Vă mulțumim pentru ajutor!"
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr "Simțiți nevoia de viteză?"
@@ -20341,9 +20509,6 @@ msgstr "Mai mulți aprobatori necesari"
msgid "InProductMarketing|Need an alternative to importing?"
msgstr "Aveți nevoie de o alternativă la import?"
-msgid "InProductMarketing|Neutral"
-msgstr "Neutru"
-
msgid "InProductMarketing|No credit card required."
msgstr "Nu este nevoie de card de credit."
@@ -20416,9 +20581,6 @@ msgstr "Nu vă mai întrebați și folosiți GitLab pentru a răspunde la între
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 "Simplificați revizuirea codului, aflați dintr-o privire cine nu este disponibil, comunicați prin comentarii sau prin e-mail și integrați cu Slack pentru ca toată lumea să fie pe aceeași pagină."
-msgid "InProductMarketing|Take this 1-question survey!"
-msgstr "Participați la acest sondaj cu 1 întrebare!"
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr "Faceți primii pași cu GitLab"
@@ -20491,12 +20653,6 @@ msgstr "Utilizați șablonul nostru AWS cloudformation pentru a vă instala exec
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr "Utilizat de peste 100.000 de organizații din întreaga lume:"
-msgid "InProductMarketing|Very difficult"
-msgstr "Foarte dificil"
-
-msgid "InProductMarketing|Very easy"
-msgstr "Foarte ușor"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr "Vizualizați-vă epicele și obiectivele în ordine cronologică."
@@ -20512,9 +20668,6 @@ msgstr "Urmăriți dezvoltarea iOS în acțiune."
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 "Știm un lucru sau două despre eficiență și nu vrem să păstrăm acest lucru pentru noi. Înscrieți-vă pentru o versiune de încercare gratuită a GitLab Ultimate, iar echipele dvs. îl vor folosi din prima zi."
-msgid "InProductMarketing|We want your GitLab experience to be great"
-msgstr "Vrem ca experiența dvs. GitLab să fie grozavă"
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr "Cum arată cronologia fluxului nostru de valori, de la produs la dezvoltare, revizuire și producție?"
@@ -20783,13 +20936,13 @@ msgid "Incident|Alert details"
msgstr "Detalii de alertă"
msgid "Incident|Are you sure you want to delete this event?"
-msgstr ""
+msgstr "Sunteți sigur că doriți să ștergeți acest eveniment?"
msgid "Incident|Are you sure you wish to delete this image?"
msgstr "Sunteți sigur că doriți să ștergeți această imagine?"
msgid "Incident|Delete event"
-msgstr ""
+msgstr "Ștergeți evenimentul"
msgid "Incident|Delete image"
msgstr "Ștergeți imaginea"
@@ -20804,10 +20957,10 @@ msgid "Incident|Editing %{filename}"
msgstr "Se editează %{filename}"
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr ""
+msgstr "Eroare la crearea unui eveniment cronologic al incidentului: %{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr ""
+msgstr "Eroare la ștergerea evenimentului cronologic al incidentului: %{error}"
msgid "Incident|Metrics"
msgstr "Metrici"
@@ -20816,13 +20969,13 @@ msgid "Incident|No timeline items have been added yet."
msgstr "Încă nu au fost adăugate elemente de cronologie."
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "Salvați și adăugați un alt eveniment"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr ""
+msgstr "Ceva nu a mers bine în timpul creării evenimentului cronologic al incidentului."
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr ""
+msgstr "Ceva nu a mers bine la ștergerea evenimentului cronologic al incidentului."
msgid "Incident|Something went wrong while fetching incident timeline events."
msgstr "Ceva nu a mers bine în timpul preluării evenimentelor din cronologia incidentelor."
@@ -20840,10 +20993,10 @@ msgid "Incident|Timeline"
msgstr "Cronologie"
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "Text cronologic"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "Text cronologic..."
msgid "Include author name in notification email body"
msgstr "Includeți numele autorului în corpul e-mailului de notificare"
@@ -21538,8 +21691,8 @@ msgstr "Invitați-vă colegii"
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 "Am observat că nu ați invitat pe nimeni în acest grup. Invitați-vă colegii pentru a putea discuta probleme, colabora la merge request-uri și pentru a vă împărtăși cunoștințele."
-msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of this namespace can start a trial or upgrade to a paid tier."
-msgstr "Pentru a obține mai mulți membri și acces la caracteristici suplimentare plătite, proprietarul acestui spațiu de nume poate începe o perioadă de evaluare sau poate actualiza la un nivel plătit."
+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 " Se pot obține mai mulți membri și acces la funcții suplimentare plătite dacă proprietarul grupului începe o perioadă de probă sau trece la un nivel plătit."
msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
msgstr "%{linkStart}Citiți mai multe%{linkEnd} despre permisiunile rolurilor"
@@ -21587,7 +21740,7 @@ msgid "InviteMembersModal|Members were successfully added"
msgstr "Membrii au fost adăugați cu succes"
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "Examinați erorile de invitație și încercați din nou:"
msgid "InviteMembersModal|Search for a group to invite"
msgstr "Căutați un grup pe care să-l invitați"
@@ -21606,9 +21759,9 @@ msgstr "Ceva nu a mers bine"
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[2] ""
+msgstr[0] "Următorul membru nu a putut fi invitat"
+msgstr[1] "Următorii %d membri nu au putut fi invitați"
+msgstr[2] "Următorii %d de membri nu au putut fi invitați"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
msgstr "Această caracteristică este dezactivată până când acest grup are loc pentru mai mulți membri."
@@ -21616,8 +21769,8 @@ msgstr "Această caracteristică este dezactivată până când acest grup are l
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 "Pentru a atribui probleme unui nou membru al echipei, aveți nevoie de un proiect pentru problemele respective. %{linkStart}Creați un proiect pentru a începe.%{linkEnd}"
-msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-msgstr "Pentru a obține mai mulți membri, un proprietar al acestui namespace poate %{trialLinkStart}începe o perioadă de încercare%{trialLinkEnd} sau %{upgradeLinkStart}poate face upgrade%{upgradeLinkEnd} la un nivel plătit."
+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 "Se pot obține mai mulți membri dacă un proprietar al grupului %{trialLinkStart}începe o perioadă de probă%{trialLinkEnd} sau %{upgradeLinkStart}actualizează%{upgradeLinkEnd} la un nivel plătit."
msgid "InviteMembersModal|To make more space, you can remove members who no longer need access."
msgstr "Pentru a face mai mult spațiu, puteți înlătura membrii care nu mai au nevoie de acces."
@@ -21631,9 +21784,6 @@ msgstr "Nu puteți adăuga alți membri, dar puteți înlătura membrii care nu
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr "Mai aveți loc doar pentru încă %{count} %{members} în %{name}"
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr "Mai aveți loc doar pentru încă %{count} %{members} în proiectele dvs. personale"
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "Invitați un grup la grupul %{strongStart}%{name}%{strongEnd}."
@@ -22039,6 +22189,9 @@ msgstr "Text italic"
msgid "Iteration"
msgstr "iterație"
+msgid "Iteration cannot be created for cadence"
+msgstr "Iterația nu poate fi creată pentru cadență"
+
msgid "Iteration changed to"
msgstr "Iterația s-a schimbat în"
@@ -22054,12 +22207,36 @@ msgstr "Iterația actualizată"
msgid "Iterations"
msgstr "Iterații"
+msgid "Iterations cadence not found"
+msgstr "Cadența iterațiilor nu a fost găsită"
+
+msgid "Iterations cannot be manually added to cadences that use automatic scheduling"
+msgstr "Nu se pot adăuga manual iterații la cadențele care utilizează programarea automată."
+
+msgid "IterationsCadence|The automation start date must come after the active iteration %{iteration_dates}."
+msgstr "Data de începere a automatizării trebuie să fie ulterioară datei iterației active, %{iteration_dates}."
+
+msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
+msgstr "Data de începere a automatizării trebuie să fie ulterioară iterației trecute %{iteration_dates}."
+
+msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
+msgstr "Data de începere a automatizării ar crea retroactiv o iterație anterioară. %{start_date} este cea mai veche dată de începere posibilă."
+
msgid "Iterations|Add iteration"
msgstr "Adăugare iterație"
msgid "Iterations|All"
msgstr "Toate"
+msgid "Iterations|All scheduled iterations will remain scheduled even if you use a smaller number."
+msgstr "Toate iterațiile programate vor rămâne programate chiar dacă utilizați un număr mai mic."
+
+msgid "Iterations|Automatic scheduling"
+msgstr "Programare automată"
+
+msgid "Iterations|Automation start date"
+msgstr "Data de începere a automatizării"
+
msgid "Iterations|Cadence configuration is invalid."
msgstr "Configurația cadenței nu este valabilă."
@@ -22081,6 +22258,9 @@ msgstr "Creați cadență"
msgid "Iterations|Create iteration"
msgstr "Creați o iterație"
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "Creați iterații automat, după un program regulat."
+
msgid "Iterations|Delete cadence"
msgstr "Ștergeți cadența"
@@ -22111,18 +22291,21 @@ msgstr "Editați iterația"
msgid "Iterations|Edit iteration cadence"
msgstr "Editați cadența de iterație"
+msgid "Iterations|Enable roll over"
+msgstr "Activați roll over"
+
msgid "Iterations|Error loading iteration cadences."
msgstr "Eroare la încărcarea cadențelor de iterație."
-msgid "Iterations|First iteration start date"
-msgstr "Data de începere a primei iterații"
-
msgid "Iterations|Iteration cadences"
msgstr "Cadențe de iterație"
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
msgstr "Iterațiile sunt o modalitate de a urmări problemele pe un interval de timp, permițând echipelor să urmărească, de asemenea, velocitatea și volatilitatea metricilor."
+msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
+msgstr "Iterațiile sunt programate să înceapă în zilele de %{weekday}."
+
msgid "Iterations|Learn more about automatic scheduling"
msgstr "Aflați mai multe despre programarea automată"
@@ -22150,9 +22333,6 @@ msgstr "Nu s-au găsit iterații"
msgid "Iterations|No iterations in cadence."
msgstr "Nicio iterație în cadență."
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr "Nimeni nu poate schimba această dată după ce a început cadența."
-
msgid "Iterations|No open iterations."
msgstr "Nicio iterație deschisă."
@@ -22180,15 +22360,15 @@ msgstr "Selectați data de începere"
msgid "Iterations|Start date"
msgstr "Data de începere"
+msgid "Iterations|The date of the first iteration to schedule. This date determines the day of the week when each iteration starts."
+msgstr "Data primei iterații care trebuie programată. Această dată determină ziua din săptămână în care începe fiecare iterație."
+
msgid "Iterations|The duration of each iteration (in weeks)."
msgstr "Durata fiecărei iterații (în săptămâni)."
msgid "Iterations|The iteration has been deleted."
msgstr "Iterația a fost ștearsă."
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
-msgstr "Data de începere a primei iterații determină momentul în care începe cadența."
-
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr "Această cadență poate fi convertită pentru a utiliza programarea automată"
@@ -22598,7 +22778,7 @@ msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
msgstr "%{boldStart}Pipeline%{boldEnd} %{id} pentru %{ref}"
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr ""
+msgstr "%{searchLength} (de) rezultate găsite pentru %{searchTerm}"
msgid "Job|Are you sure you want to erase this job log and artifacts?"
msgstr "Sunteți sigur că doriți să ștergeți acest jurnal de job și artefactele?"
@@ -22640,7 +22820,7 @@ msgid "Job|Job has been erased by %{userLink}"
msgstr "Jobul a fost șters de %{userLink}"
msgid "Job|Job log search"
-msgstr ""
+msgstr "Căutarea în jurnalul de joburi"
msgid "Job|Keep"
msgstr "Păstrați"
@@ -22649,7 +22829,7 @@ msgid "Job|Manual"
msgstr "Manual"
msgid "Job|No search results found"
-msgstr ""
+msgstr "Nu s-au găsit rezultate ale căutării"
msgid "Job|Passed"
msgstr "A trecut"
@@ -22672,14 +22852,17 @@ msgstr "Programat"
msgid "Job|Scroll to bottom"
msgstr "Derulați până jos"
+msgid "Job|Scroll to next failure"
+msgstr "Derulați la următorul eșec"
+
msgid "Job|Scroll to top"
msgstr "Derulați până sus"
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 "Căutați subșiruri în ieșirea jurnalului de job. În prezent, căutarea este acceptată numai pentru ieșirea vizibilă a jurnalului de job, nu și pentru orice ieșire de jurnal care este trunchiată din cauza dimensiunii."
msgid "Job|Search job log"
-msgstr ""
+msgstr "Căutați jurnalul de joburi"
msgid "Job|Show complete raw"
msgstr "Afișați brut complet"
@@ -22718,7 +22901,7 @@ msgid "Job|Waiting for resource"
msgstr "În așteptare de resurse"
msgid "Job|We could not find this element"
-msgstr ""
+msgstr "Nu s-a putut găsi acest element"
msgid "Job|allowed to fail"
msgstr "permis să eșueze"
@@ -22795,8 +22978,8 @@ msgstr "Cheie"
msgid "Key (PEM)"
msgstr "Cheie (PEM)"
-msgid "Key: %{key}"
-msgstr "Cheie: %{key}"
+msgid "Key:"
+msgstr "Cheie:"
msgid "Keyboard shortcuts"
msgstr "Scurtături de la tastatură"
@@ -23065,15 +23248,9 @@ msgstr "Ultimul IP de conectare:"
msgid "Last sign-in at:"
msgstr "Ultima conectare la:"
-msgid "Last successful sync"
-msgstr "Ultima sincronizare reușită"
-
msgid "Last successful update"
msgstr "Ultima actualizare reușită"
-msgid "Last time checked"
-msgstr "Ultima dată verificat(ă)"
-
msgid "Last time verified"
msgstr "Ultima dată verificat(ă)"
@@ -23356,20 +23533,20 @@ msgstr "Licență legacy"
msgid "Less Details"
msgstr "Mai puține detalii"
+msgid "Less restrictive visibility"
+msgstr "Vizibilitate mai puțin restrictivă"
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt nu acceptă e-mailuri pe example.com"
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 "Let's Encrypt este o autoritate de certificare (CA) gratuită, automatizată și deschisă care oferă certificate digitale pentru a activa HTTPS (SSL/TLS) pentru site-urile web. Aflați mai multe despre configurarea Let's Encrypt urmărind %{docs_link_start}documentația de pe GitLab Pages%{docs_link_end}."
-msgid "Let's talk!"
-msgstr "Hai să vorbim!"
-
msgid "License Compliance"
msgstr "Conformitatea licenței"
-msgid "License Compliance| Used by"
-msgstr "Folosită de"
+msgid "License Compliance| Used by %{dependencies}"
+msgstr " Folosit de %{dependencies}"
msgid "License compliance"
msgstr "Conformitatea licenței"
@@ -23635,8 +23812,11 @@ msgstr "E-mailuri legate (%{email_count})"
msgid "Linked epics"
msgstr "Epice legate"
-msgid "Linked issues"
-msgstr "Probleme legate"
+msgid "Linked incidents or issues"
+msgstr "Incidente sau probleme legate"
+
+msgid "Linked items"
+msgstr "Articole legate"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23647,6 +23827,48 @@ msgstr "LinkedIn:"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr "%{counterLabel} alte pipeline-uri în aval"
+msgid "LinkedResources|Add"
+msgstr "Adăugați"
+
+msgid "LinkedResources|Add a resource link"
+msgstr "Adăugați un link de resurse"
+
+msgid "LinkedResources|Cancel"
+msgstr "Anulare"
+
+msgid "LinkedResources|Error creating resource link for the incident: %{error}"
+msgstr "Eroare la crearea linkului de resurse pentru incident: %{error}"
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr "Eroare la ștergerea resursei legate pentru incident: %{error}"
+
+msgid "LinkedResources|Fetching linked resources"
+msgstr "Preluarea resurselor legate"
+
+msgid "LinkedResources|Link"
+msgstr "Link"
+
+msgid "LinkedResources|Linked resources"
+msgstr "Resurse conexe"
+
+msgid "LinkedResources|Remove"
+msgstr "Înlăturați"
+
+msgid "LinkedResources|Something went wrong while creating the resource link for the incident."
+msgstr "Ceva nu a funcționat în timpul creării linkului de resurse pentru incident."
+
+msgid "LinkedResources|Something went wrong while deleting the linked resource for the incident."
+msgstr "Ceva nu a mers bine la ștergerea resursei legate pentru incident."
+
+msgid "LinkedResources|Something went wrong while fetching linked resources for the incident."
+msgstr "Ceva nu a mers bine în timpul obținerii resurselor legate pentru acest incident."
+
+msgid "LinkedResources|Text (Optional)"
+msgstr "Text (opțional)"
+
+msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
+msgstr "Folosiți acest spațiu pentru a adăuga linkuri către resursele de care echipa dumneavoastră are nevoie în timp ce lucrează la rezolvarea incidentului."
+
msgid "Links"
msgstr "Linkuri"
@@ -23974,9 +24196,6 @@ msgstr "Importul cu un manifest"
msgid "Manual"
msgstr "Manual"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr "Cadențele de iterație manuală sunt depășite. Sunt permise numai cadențele automate de iterație."
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Ordinea problemelor nu a putut fi salvată"
@@ -24238,8 +24457,8 @@ msgstr "Lungimea maximă a câmpului"
msgid "Maximum file size indexed (KiB)"
msgstr "Mărimea maximă a fișierului indexată (KiB)"
-msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}."
-msgstr "Mărimea maximă a fișierului este de 1 MB. Dimensiunea imaginii trebuie să fie de 32 x 32 pixeli. Formatele de imagine permise sunt %{favicon_extension_whitelist}."
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr "Mărimea maximă a fișierului este de 1 MB. Imaginea trebuie să aibă mărimea de 32 x 32 pixeli. Formatele de imagine permise sunt %{favicon_extension_allowlist}."
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
msgstr "Mărimea maximă a fișierului este de 1 MB. Paginile sunt optimizate pentru un logo de antet înalt de 24px."
@@ -25636,12 +25855,6 @@ msgstr "Opriți mediul"
msgid "MrList|Assigned to %{name}"
msgstr "Atribuit lui %{name}"
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr "Se solicită atenție din partea responsabilului %{name}"
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr "Atenție solicitată de la revizorul %{name}"
-
msgid "MrList|Review requested from %{name}"
msgstr "Revizuire solicitată de la %{name}"
@@ -25666,8 +25879,8 @@ msgstr "Multi-proiect"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr "Integrările HTTP multiple nu sunt acceptate pentru acest proiect"
-msgid "Multiple IP address ranges are supported."
-msgstr "Sunt acceptate mai multe intervale de adrese IP."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "Sunt acceptate mai multe intervale de adrese IP. Nu afectează accesul la setările de grup."
msgid "Multiple Prometheus integrations are not supported"
msgstr "Integrările multiple Prometheus nu sunt acceptate"
@@ -25852,9 +26065,6 @@ msgstr "Deconectați-vă și conectați-vă cu un alt cont"
msgid "Need help?"
msgstr "Aveți nevoie de ajutor?"
-msgid "Need your attention"
-msgstr "Necesită atenția dvs."
-
msgid "Needs"
msgstr "Needs"
@@ -25979,7 +26189,7 @@ msgid "New epic title"
msgstr "Titlu nou de epică"
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "A fost generat un nou token de acces pentru urmărirea erorilor!"
msgid "New file"
msgstr "Fișier nou"
@@ -26125,6 +26335,9 @@ msgstr "Nu există date CSV de afișat."
msgid "No Epic"
msgstr "Nicio epică"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "Niciun proiect Google Cloud - Aveți nevoie de cel puțin un proiect Google Cloud"
+
msgid "No Matching Results"
msgstr "Nicio potrivire de rezultate"
@@ -26135,7 +26348,7 @@ msgid "No Scopes"
msgstr "Fără scopuri"
msgid "No Work Item Link found"
-msgstr ""
+msgstr "Nu s-a găsit niciun link cu elementul de lucru"
msgid "No active admin user found"
msgstr "Nu s-a găsit niciun utilizator administrator activ"
@@ -26155,9 +26368,6 @@ msgstr "Nu s-au găsit artefacte"
msgid "No assignee"
msgstr "Niciun responsabil"
-msgid "No attention request"
-msgstr "Nicio solicitare de atenție"
-
msgid "No authentication methods configured."
msgstr "Nu sunt configurate metode de autentificare."
@@ -26369,7 +26579,7 @@ msgid "No repository"
msgstr "Niciun repozitoriu"
msgid "No results"
-msgstr ""
+msgstr "Niciun rezultat"
msgid "No runner executable"
msgstr "Niciun executor disponibil"
@@ -26458,9 +26668,6 @@ msgstr "Niciunul dintre obiectivele grupului nu are același proiect ca și vers
msgid "Normal text"
msgstr "Text normal"
-msgid "Not Implemented"
-msgstr "Neimplementat"
-
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 "Nu toate browserele sunt compatibile cu dispozitivele U2F. Prin urmare, vă solicităm să configurați mai întâi o aplicație de autentificare cu doi factori. În acest fel, veți putea să vă conectați întotdeauna - chiar și atunci când utilizați un browser neacceptat."
@@ -26581,6 +26788,9 @@ msgstr "Această notă internă va rămâne întotdeauna confidențială."
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 "Vedeți doar %{boldStart}alte activități%{boldEnd} în flux. Pentru a adăuga un comentariu, treceți la una dintre următoarele opțiuni."
+msgid "Note|The created date provided is too far in the past."
+msgstr "Data de creare furnizată este cu mult prea îndepărtată în trecut."
+
msgid "Nothing to preview."
msgstr "Nimic de previzualizat."
@@ -26722,6 +26932,15 @@ msgstr "Problema creată de %{author_link} %{issue_reference_link} va expira în
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} în %{mr_link}"
+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}."
+
+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|%{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|Assignee changed from %{fromNames} to %{toNames}"
msgstr "Responsabilul a fost schimbat de la %{fromNames} la %{toNames}"
@@ -26732,10 +26951,10 @@ msgid "Notify|Author: %{author_name}"
msgstr "Autor: %{author_name}"
msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
-msgstr ""
+msgstr "Pipeline-ul Auto DevOps a fost dezactivat pentru %{project}"
msgid "Notify|CI/CD project settings"
-msgstr ""
+msgstr "Setări de proiect CI/CD"
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 "Dacă nu mai doriți să utilizați acest domeniu cu GitLab Pages, vă rugăm să-l înlăturați din proiectul dumneavoastră GitLab și să ștergeți toate înregistrările DNS aferente."
@@ -26747,7 +26966,7 @@ msgid "Notify|Issue was moved to another project."
msgstr "Problema a fost mutată la un alt proiect."
msgid "Notify|Learn more about Auto DevOps"
-msgstr ""
+msgstr "Aflați mai multe despre Auto DevOps"
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."
@@ -26777,7 +26996,7 @@ msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr "Pipeline-ul %{pipeline_link} declanșat de"
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 ""
+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|This issue is due on: %{issue_due_date}"
msgstr "Această problemă expiră pe: %{issue_due_date}"
@@ -26792,7 +27011,7 @@ msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been
msgstr "Solicitarea dvs. de a vă alătura la %{target_to_join} %{target_type} a fost %{denied_tag}."
msgid "Notify|currently supported languages"
-msgstr ""
+msgstr "limbaje acceptate în prezent"
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr "s-a(u) finalizat cu succes %{jobs} în %{stages}."
@@ -26887,6 +27106,12 @@ msgstr "OmniAuth"
msgid "On"
msgstr "Pornit"
+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] "La %{end_date}, perioada de probă se va încheia și %{namespace_name} va fi limitat la %{free_user_limit} membru."
+msgstr[1] "La %{end_date}, perioada de probă se va încheia, iar %{namespace_name} va fi limitat la %{free_user_limit} membri."
+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 track"
msgstr "Conform planului"
@@ -27272,7 +27497,7 @@ msgstr[1] "%d elemente mai mult"
msgstr[2] "%d de elemente mai mult"
msgid "One or more arguments are invalid: %{args}."
-msgstr ""
+msgstr "Unul sau mai multe argumente nu sunt valide: %{args}."
msgid "One or more contacts were successfully added."
msgstr "Una sau mai multe contacte au fost adăugate cu succes."
@@ -27320,7 +27545,7 @@ msgid "Only SSH"
msgstr "Numai SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
-msgstr ""
+msgstr "Accesibil numai %{membersPageLinkStart}membrilor proiectului%{membersPageLinkEnd}. Calitatea de membru trebuie să fie acordată în mod explicit fiecărui utilizator."
msgid "Only active projects show up in the search and on the dashboard."
msgstr "Numai proiectele active apar în căutări și în tabloul de bord."
@@ -27361,9 +27586,6 @@ msgstr "Este necesar numai dacă nu se utilizează acreditările instanței de r
msgid "Only use lowercase letters, numbers, and underscores."
msgstr "Folosiți numai litere minuscule, cifre și caractere de subliniere."
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-msgstr "Numai utilizatorii din intervalele de adrese IP specificate pot accesa acest grup, inclusiv toate subgrupurile, proiectele și repozitoriile Git."
-
msgid "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
msgstr "Numai utilizatorii verificați care au o adresă de e-mail în oricare dintre aceste domenii pot fi adăugați la grup. Sunt acceptate mai multe domenii."
@@ -27457,6 +27679,9 @@ msgstr "Mai multe informații"
msgid "OperationsDashboard|Operations Dashboard"
msgstr "Tabloul de bord al operațiunilor"
+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 "Tablourile de bord al Operațiunilor și al Mediilor au în comun aceeași listă de proiecte. Atunci când adăugați sau înlăturați un proiect din unul dintre ele, GitLab adaugă sau înlătură proiectul din celălalt. %{linkStart}Mai multe informații%{linkEnd}"
+
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "Tablou de bord de operațiuni oferă un rezumat al stării de sănătate operațională a fiecărui proiect, inclusiv statusul pipeline-urilor și alertelor."
@@ -27778,6 +28003,12 @@ msgstr "Creat de commit-ul %{link} pe ramura %{branch}"
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+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"
@@ -27787,6 +28018,9 @@ msgstr "Ștergeți versiunea pachetului"
msgid "PackageRegistry|Delete package"
msgstr "Ștergeți pachetul"
+msgid "PackageRegistry|Delete selected"
+msgstr "Ștergeți selectat"
+
msgid "PackageRegistry|Delete this package"
msgstr "Ștergeți acest pachet"
@@ -27796,6 +28030,9 @@ msgstr "Pachete duplicate"
msgid "PackageRegistry|Error publishing"
msgstr "Eroare de publicare"
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr "Exemple de active includ fișiere .pom și .jar"
+
msgid "PackageRegistry|Failed to load the package data"
msgstr "Nu s-a reușit încărcarea datelor pachetului"
@@ -27853,6 +28090,9 @@ msgstr "Aflați cum să vă %{noPackagesLinkStart}publicați și să partajați
msgid "PackageRegistry|License information located at %{link}"
msgstr "Informațiile despre licență se găsesc la %{link}"
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr "Gestionați spațiul de stocare utilizat de activele pachetului"
+
msgid "PackageRegistry|Manually Published"
msgstr "Publicat manual"
@@ -27871,9 +28111,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "Comanda NuGet"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "Numărul de active duplicate care trebuie păstrate"
+
msgid "PackageRegistry|Package Registry"
msgstr "Registrul de pachete"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr "Activele pachetului au fost șterse"
+
msgid "PackageRegistry|Package deleted successfully"
msgstr "Pachetul a fost șters cu succes"
@@ -27889,6 +28135,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 assets"
+msgstr "Ștergeți permanent activele"
+
msgid "PackageRegistry|Pip Command"
msgstr "Comanda Pip"
@@ -27946,6 +28195,9 @@ 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 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."
@@ -27997,18 +28249,30 @@ msgstr "Nu se pot obține informații despre versiunea pachetului."
msgid "PackageRegistry|Unable to load package"
msgstr "Nu se poate încărca pachetul"
+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 "Atunci când un pachet cu același nume și versiune este încărcat în registru, mai multe active sunt adăugate la pachet. Pentru a economisi spațiu de stocare, păstrați doar cele mai recente active."
+
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 1 asset. This operation is irreversible."
+msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
+msgstr[0] "Sunteți pe punctul de a șterge 1 activ. Această operațiune este ireversibilă."
+msgstr[1] "Sunteți pe cale să ștergeți %d active. Această operațiune este ireversibilă."
+msgstr[2] "Sunteți pe cale să ștergeți %d de active. Această operațiune este ireversibilă."
+
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
msgstr "Sunteți pe cale să ștergeți versiunea %{version} a %{name} Sunteți sigur?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "S-ar putea, de asemenea, să fie nevoie să configurați autentificarea cu ajutorul unui token auth. %{linkStart}Consultați documentația%{linkEnd} pentru a afla mai multe."
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr "Veți avea nevoie de un %{linkStart}token de acces personal%{linkEnd}."
+
msgid "PackageRegistry|npm"
msgstr "npm"
@@ -28264,6 +28528,9 @@ msgstr "Efectuați revizuiri de cod și îmbunătățiți colaborarea cu merge r
msgid "Perform common operations on GitLab project"
msgstr "Efectuați operații comune în proiectul GitLab"
+msgid "Performance insights"
+msgstr "Perspective despre performanță"
+
msgid "Performance optimization"
msgstr "Optimizarea performanțelor"
@@ -28369,6 +28636,18 @@ msgstr "Proiecte personale"
msgid "Personal projects limit:"
msgstr "Limita proiectelor personale:"
+msgid "PersonalProject|Learn to move a project to a group"
+msgstr "Învățați să mutați un proiect într-un grup"
+
+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 "Unele caracteristici GitLab, inclusiv posibilitatea de a trece la un plan plătit sau de a începe o perioadă de probă gratuită, sunt disponibile numai pentru grupuri și proiecte din cadrul grupurilor. %{projectName} este un proiect personal, deci nimic din toate acestea nu este disponibil. Vă recomandăm să vă mutați proiectul într-un grup pentru a debloca întregul potențial al GitLab."
+
+msgid "PersonalProject|We have some instructions to help you create a group and move your project into it."
+msgstr "Avem câteva instrucțiuni pentru a vă ajuta să creați un grup și să vă mutați proiectul în el."
+
+msgid "PersonalProject|Your project %{projectName} is not in a group"
+msgstr "Proiectul dvs. %{projectName} nu se află într-un grup"
+
msgid "Phabricator Server Import"
msgstr "Import de pe serverul Phabricator"
@@ -28525,6 +28804,9 @@ msgstr "💡 Sfat: Vizualizați și validați-vă pipeline-ul"
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
msgstr "🚀 Rulați primul dvs. pipeline"
+msgid "PipelineEditor|Configuration content has changed. Re-run validation for updated results."
+msgstr "Conținutul configurației s-a modificat. Reexecutați validarea pentru rezultate actualizate."
+
msgid "PipelineEditor|Current content in the Edit tab will be used for the simulation."
msgstr "Conținutul curent din fila Editare va fi utilizat pentru simulare."
@@ -28543,6 +28825,15 @@ msgstr "Comportamentul pipeline-ului va fi simulat, inclusiv %{codeStart}regulil
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 "Comportamentul pipeline-ului va fi simulat, inclusiv %{codeStart}regulile%{codeEnd} %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd} și %{codeStart}needs%{codeEnd} ale dependențelor jobului. %{linkStart}Aflați mai multe%{linkEnd}"
+msgid "PipelineEditor|Pipeline simulation completed with errors"
+msgstr "Simularea pipeline-ului s-a finalizat cu erori"
+
+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 "S-a simulat un eveniment %{codeStart}git push%{codeEnd} pentru o ramură implicită. Au fost evaluate %{codeStart}regulile%{codeEnd}, logica dependențelor de job %{codeStart}only%{codeEnd}, %{codeStart}except%{codeEnd} și %{codeStart}needs%{codeEnd}. %{linkStart}Aflați mai multe%{linkEnd}"
+
+msgid "PipelineEditor|Simulation completed successfully"
+msgstr "Simulare finalizată cu succes"
+
msgid "PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty."
msgstr "Configurația CI/CD este validată în mod continuu. Sunt afișate erori și avertismente atunci când fișierul de configurare CI/CD nu este gol."
@@ -28564,6 +28855,12 @@ msgstr "Validați pipeline-ul în condițiile selectate"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
msgstr "Validați pipeline-ul în condiții simulate"
+msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
+msgstr "Validarea conductelor... Poate dura până la un minut."
+
+msgid "PipelineEditor|Waiting for CI content to load..."
+msgstr "În așteptarea încărcării conținutului CI..."
+
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
msgstr "Personalizat (%{linkStart}Sintaxă Cron%{linkEnd})"
@@ -28585,6 +28882,9 @@ msgstr "Următoarea execuție"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Furnizați o scurtă descriere pentru acest pipeline"
@@ -28597,6 +28897,9 @@ msgstr "Țintă"
msgid "PipelineSchedules|Variables"
msgstr "Variabile"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr "Asumați-vă proprietatea de a edita"
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28843,6 +29146,9 @@ msgstr "Proprietar"
msgid "Pipelines|Pipeline Editor"
msgstr "Editor de pipeline"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "Sintaxa pipeline-ului este corectă."
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Cache-ul proiectului a fost resetat cu succes."
@@ -29011,9 +29317,18 @@ msgstr "Pipeline de merge request detașat"
msgid "Pipeline|Failed"
msgstr "Eșuat"
+msgid "Pipeline|Five slowest jobs"
+msgstr "Cinci dintre cele mai lente joburi"
+
msgid "Pipeline|In progress"
msgstr "ÃŽn curs"
+msgid "Pipeline|Last executed job"
+msgstr "Ultimul job executat"
+
+msgid "Pipeline|Longest queued job"
+msgstr "Cel mai lung job din coadă"
+
msgid "Pipeline|Manual"
msgstr "Manual"
@@ -29026,12 +29341,18 @@ msgstr "Joburile pipeline de merge train nu pot fi reîncercate"
msgid "Pipeline|Merged result pipeline"
msgstr "Pipeline de rezultate îmbinate"
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "Nu se pot afișa decât primele 100 de rezultate"
+
msgid "Pipeline|Passed"
msgstr "A trecut"
msgid "Pipeline|Pending"
msgstr "În așteptare"
+msgid "Pipeline|Performance insights"
+msgstr "Perspective despre performanță"
+
msgid "Pipeline|Pipeline"
msgstr "Pipeline"
@@ -29050,6 +29371,9 @@ msgstr "Căutarea de text brut nu este acceptată în prezent. Vă rugăm să ut
msgid "Pipeline|Run for branch name or tag"
msgstr "Executați pentru numele ramurii sau etichetă"
+msgid "Pipeline|Run merge request pipeline"
+msgstr "Rulați pipeline-ul de merge request"
+
msgid "Pipeline|Run pipeline"
msgstr "Executați pipeline-ul"
@@ -29086,6 +29410,12 @@ msgstr "Numele etichetei"
msgid "Pipeline|Test coverage"
msgstr "Coverage de testare"
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "Ultimul job executat este ultimul job care începe în pipeline."
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "Cel mai lung job din coadă este jobul care a petrecut cel mai mult timp în stare de așteptare, așteptând să fie preluat de un executor"
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr "Această modificare va reduce gradul general de coverage de teste dacă va fi îmbinată."
@@ -29101,6 +29431,9 @@ msgstr "Acest pipeline a rulat pe conținutul acestui merge request combinat cu
msgid "Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch."
msgstr "Acest pipeline a rulat pe conținutul ramurii sursă a acestui merge request, nu pe cel al ramurii țintă."
+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 "Pentru a rula un pipeline de merge request, joburile din fișierul de configurare CI/CD %{linkStart} trebuie să fie configurate%{linkEnd} pentru a rula în pipeline-urile de merge request."
+
msgid "Pipeline|Trigger author"
msgstr "Autorul declanșatorului"
@@ -29113,6 +29446,9 @@ msgstr "Variabile"
msgid "Pipeline|View commit"
msgstr "Vizualizați commit-ul"
+msgid "Pipeline|View dependency"
+msgstr "Vizualizați dependența"
+
msgid "Pipeline|View pipeline"
msgstr "Vizualizați pipeline-ul"
@@ -29212,6 +29548,9 @@ msgstr "Vă rugăm să vă verificați e-mailul %{email} pentru a vă confirma c
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 "Vă rugăm să vă verificați e-mailul (%{email}) pentru a confirma că sunteți proprietarul acestei adrese și pentru a debloca puterea CI/CD. Nu l-ați primit? %{resend_link}. Adresa de e-mail greșită? %{update_link}."
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr "Faceți clic pe linkul din e-mailul de confirmare înainte de a continua. Acesta a fost trimis la "
+
msgid "Please complete your profile with email address"
msgstr "Vă rugăm să completați profilul dvs. cu adresa de e-mail"
@@ -29314,6 +29653,9 @@ msgstr "Vă rugăm să furnizați atributele pentru actualizare"
msgid "Please reach out if you have any questions and we'll be happy to assist."
msgstr "Vă rugăm să ne contactați dacă aveți întrebări și vom fi bucuroși să vă ajutăm."
+msgid "Please review the %{linkStart}contribution guidelines%{linkEnd} for this project."
+msgstr "Consultați %{linkStart}ghidurile de contribuție%{linkEnd} pentru acest proiect."
+
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 "Vă rugăm să consultați politicile de escaladare actualizate pentru %{project_link} Se recomandă să luați legătura cu actualul respondent de gardă pentru a asigura continuitatea acoperirii de gardă."
@@ -29560,8 +29902,8 @@ msgstr "Anterior"
msgid "Prevent auto-stopping"
msgstr "Preveniți oprirea automată"
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr "Împiedicați editarea regulilor de aprobare în proiecte și merge request-uri."
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr "Preveniți modificarea regulilor de aprobare în proiecte și merge request-uri"
msgid "Prevent environment from auto-stopping"
msgstr "Împiedicați oprirea automată a mediului"
@@ -30179,7 +30521,7 @@ msgid "Project URL"
msgstr "URL-ul proiectului"
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 "Accesul la proiect trebuie să fie acordat în mod explicit fiecărui utilizator. Dacă acest proiect face parte dintr-un grup, accesul este acordat membrilor grupului."
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 "Crearea de tokenuri de acces la proiect este dezactivată în acest grup. Puteți în continuare să utilizați și să gestionați tokenurile existente. %{link_start}Aflați mai multe.%{link_end}"
@@ -30274,6 +30616,9 @@ msgstr "Slug de proiect"
msgid "Project uploads"
msgstr "Încărcările proiectului"
+msgid "Project visibility level is less restrictive than the group settings."
+msgstr "Nivelul de vizibilitate al proiectului este mai puțin restrictiv decât setările de grup."
+
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "Nivelul de vizibilitate al proiectului va fi modificat pentru a se potrivi cu regulile spațiului de nume atunci când se transferă într-un grup."
@@ -30283,6 +30628,12 @@ msgstr "Proiectul nu a fost găsit sau nu aveți permisiunea de a adăuga acest
msgid "Project: %{name}"
msgstr "Proiect: %{name}"
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr "Proiect:Ramuri: %{source_project_path}:%{source_branch} la %{target_project_path}:%{target_branch}"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr "Proiect:Ramuri: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Abonați-vă"
@@ -30361,6 +30712,9 @@ msgstr "Eșec"
msgid "ProjectQualitySummary|Get insight into the overall percentage of tests in your project that succeed, fail and are skipped."
msgstr "Obțineți informații despre procentajul global de teste din proiectul dvs. care reușesc, eșuează și sunt sărite."
+msgid "ProjectQualitySummary|Help us improve this page"
+msgstr "Ajutați-ne la îmbunătățirea acestei pagini"
+
msgid "ProjectQualitySummary|Latest pipeline results"
msgstr "Rezultatele celui mai recent pipeline"
@@ -30373,6 +30727,9 @@ msgstr "Aflați mai multe despre rapoartele de testare"
msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
msgstr "Măsoară cât de mult din codul dvs. este acoperit de teste."
+msgid "ProjectQualitySummary|Provide feedback"
+msgstr "Furnizați feedback"
+
msgid "ProjectQualitySummary|See full report"
msgstr "Consultați raportul complet"
@@ -30400,6 +30757,9 @@ msgstr "Rulări de testare"
msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
msgstr "Procentul de teste care reușesc, eșuează sau sunt sărite."
+msgid "ProjectQualitySummary|This page helps you understand the code testing trends for your project. Let us know how we can improve it!"
+msgstr "Pagina aceasta vă ajută la înțelegerea trendurilor în testarea codului din proiectul dumneavoastră. Faceți-ne cunoscut în ce mod îl putem îmbunătăți!"
+
msgid "ProjectSelect| or group"
msgstr "sau grup"
@@ -31588,18 +31948,36 @@ msgstr "implicit"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} va putea fi editat de dezvoltatori. Sunteți sigur?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+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"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr "Se permite implementarea în %{project} / %{environment}"
+
msgid "ProtectedEnvironment|Environment"
msgstr "Mediu"
+msgid "ProtectedEnvironment|Environments protected upstream"
+msgstr "Medii protejate în amonte"
+
+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 projected."
+msgstr "Acest proiect nu are niciun mediu protejat."
+
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
msgstr "Numai grupurile specificate pot executa implementări în medii protejate."
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
msgstr "Numai utilizatorii specificați pot executa desfășurări într-un mediu protejat."
+msgid "ProtectedEnvironment|Parent group"
+msgstr "Grupul părinte"
+
msgid "ProtectedEnvironment|Protect"
msgstr "Protejare"
@@ -31726,6 +32104,12 @@ msgstr "Pull request-urile din fork nu sunt acceptate"
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 "Puma rulează cu un număr de subiecte mai mare de 1 și serviciul Rugged este activat. Acest lucru poate scădea performanța în anumite medii. Consultați %{link_start}documentația%{link_end} noastră pentru detalii despre această problemă."
+msgid "PumbleIntegration|Send notifications about project events to Pumble."
+msgstr "Trimiteți notificări despre evenimentele proiectului la Pumble."
+
+msgid "PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}"
+msgstr "Trimiteți notificări despre evenimentele proiectului la Pumble. %{docs_link}"
+
msgid "Purchase more minutes"
msgstr "Cumpărați mai multe minute"
@@ -31996,12 +32380,6 @@ msgstr "Rebase fără pipeline"
msgid "Recaptcha verified?"
msgstr "Recaptcha este verificată?"
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr "Primiți un card cadou de 50 de dolari ca mulțumire pentru timpul dedicat."
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr "Primiți un %{strongOpen}card cadou de 50 de dolari%{strongClose} ca mulțumire pentru timpul dedicat."
-
msgid "Receive any notifications from GitLab."
msgstr "Primiți orice notificări de la GitLab."
@@ -32035,6 +32413,9 @@ msgstr "Utilizate recent"
msgid "Reconfigure"
msgstr "Reconfigurați"
+msgid "Recover password"
+msgstr "Recuperați parola"
+
msgid "Recovery Codes"
msgstr "Coduri de recuperare"
@@ -32206,9 +32587,6 @@ msgstr "Se referă la %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
msgstr "Feature Flags asociate"
-msgid "Related incidents or issues"
-msgstr "Incidente sau probleme conexe"
-
msgid "Related issues"
msgstr "Probleme asociate"
@@ -32224,6 +32602,9 @@ msgstr[0] "Lansare"
msgstr[1] "Lansări"
msgstr[2] "Lansări"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "Versiunea %{deletedRelease} a fost ștearsă cu succes."
+
msgid "Release assets"
msgstr "Resursele versiunii"
@@ -32296,6 +32677,9 @@ msgstr "Includeți mesajul din eticheta adnotată."
msgid "Release|Something went wrong while creating a new release."
msgstr "Ceva nu a mers bine în timpul creării unei noi versiuni."
+msgid "Release|Something went wrong while deleting the release."
+msgstr "Ceva nu a mers bine la ștergerea versiunii."
+
msgid "Release|Something went wrong while getting the release details."
msgstr "Ceva nu a funcționat la obținerea detaliilor despre versiune."
@@ -32359,12 +32743,6 @@ msgstr "Înlăturați legătura activului"
msgid "Remove assignee"
msgstr "Înlăturați responsabilul"
-msgid "Remove attention request"
-msgstr "Înlăturați cererea de atenție"
-
-msgid "Remove attention request(s)"
-msgstr "Înlăturați cererea / cererile de atenție"
-
msgid "Remove avatar"
msgstr "Înlăturați avatarul"
@@ -32506,12 +32884,6 @@ msgstr "S-au înlăturat toate etichetele."
msgid "Removed an issue from an epic."
msgstr "S-a înlăturat o problemă dintr-o epică."
-msgid "Removed attention from %{users_sentence}."
-msgstr "S-a înlăturat atenția de la %{users_sentence}."
-
-msgid "Removed attention request from @%{username}"
-msgstr "A fost eliminată solicitarea de atenție de la @%{username}"
-
msgid "Removed group can not be restored!"
msgstr "Grupul înlăturat nu poate fi restabilit!"
@@ -32560,9 +32932,6 @@ msgstr "Înlătură toate etichetele."
msgid "Removes an issue from an epic."
msgstr "Înlătură o problemă dintr-o epică."
-msgid "Removes attention from %{users_sentence}."
-msgstr "Înlătură atenția de la %{users_sentence}."
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Înlătură epica părinte %{epic_ref}."
@@ -32671,6 +33040,9 @@ msgstr "Răspundeți direct la acest e-mail sau %{view_it_on_gitlab}."
msgid "Reply…"
msgstr "Răspunde..."
+msgid "Report Finding not found"
+msgstr "Raportul de detectare nu a fost găsit"
+
msgid "Report abuse"
msgstr "Raportați un abuz"
@@ -32683,6 +33055,9 @@ msgstr "Raportul nu a putut fi pregătit."
msgid "Report for the scan has been removed from the database."
msgstr "Raportul pentru scanare a fost eliminat din baza de date."
+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 "Versiunea raportului nu este furnizată, tipul de raport %{report_type} acceptă versiunile: %{supported_schema_versions}. GitLab va încerca să valideze acest raport împotriva celor mai vechi versiuni acceptate ale acestui tip de raport, pentru a afișa toate erorile, dar nu va integra raportul"
+
msgid "Report your license usage data to GitLab"
msgstr "Raportați datele de utilizare a licenței dvs. către GitLab"
@@ -32750,10 +33125,10 @@ msgid "Reports|Classname"
msgstr "Numele clasei"
msgid "Reports|Copy failed test names to run locally"
-msgstr ""
+msgstr "Copiați numele testelor eșuate pentru a le rula local"
msgid "Reports|Copy failed tests"
-msgstr ""
+msgstr "Copiați testele eșuate"
msgid "Reports|Execution time"
msgstr "Timp de execuție"
@@ -32845,6 +33220,9 @@ msgstr "Vulnerabilitate"
msgid "Reports|Vulnerability Name"
msgstr "Numele vulnerabilității"
+msgid "Reports|metrics report"
+msgstr "raport de metrice"
+
msgid "Reports|no changed test results"
msgstr "nu s-au modificat rezultatele testelor"
@@ -33040,15 +33418,6 @@ msgstr "Solicitați acces"
msgid "Request a new one"
msgstr "Solicitați una nouă"
-msgid "Request attention from %{users_sentence}."
-msgstr "Solicitați atenție de la %{users_sentence}."
-
-msgid "Request attention from assignee or reviewer"
-msgstr "Solicitați atenție de la responsabil sau recenzent"
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr "Solicitați atenție de la responsabil(i) sau recenzent(i)"
-
msgid "Request data is too large"
msgstr "Datele solicitate sunt prea mari"
@@ -33073,24 +33442,12 @@ msgstr "Solicitat"
msgid "Requested %{time_ago}"
msgstr "Solicitat %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr "S-a solicitat atenție de la %{users_sentence}."
-
-msgid "Requested attention from @%{username}"
-msgstr "A solicitat atenție de la @%{username}"
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr "S-a solicitat atenția de la @%{username}. Propria dvs. solicitare de atenție a fost înlăturată."
-
msgid "Requested design version does not exist."
msgstr "Versiunea de design solicitată nu există."
msgid "Requested review"
msgstr "Revizuirea solicitată"
-msgid "Requested review. Your attention request was removed."
-msgstr "Revizuire solicitată. Solicitarea dvs. de atenție a fost înlăturată."
-
msgid "Requested states are invalid"
msgstr "Stările solicitate nu sunt valide"
@@ -33169,6 +33526,9 @@ msgstr "Retrimiteți"
msgid "Resend Request"
msgstr "Retrimiteți solicitarea"
+msgid "Resend confirmation e-mail"
+msgstr "Trimiteți din nou e-mailul de confirmare"
+
msgid "Resend confirmation email"
msgstr "Retrimiteți e-mailul de confirmare"
@@ -33185,7 +33545,7 @@ msgid "Reset"
msgstr "Resetați"
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "Resetați tokenul de acces pentru urmărirea erorilor"
msgid "Reset file"
msgstr "Resetare fișier"
@@ -33313,12 +33673,12 @@ msgstr "Recuperarea raportului de conformitate a eșuat. Reîmprospătați pagin
msgid "Retry"
msgstr "Reîncercați"
+msgid "Retry all failed or cancelled jobs"
+msgstr "Reîncercați toate joburile eșuate sau anulate"
+
msgid "Retry downstream pipeline"
msgstr "Reîncercare pipeline din aval"
-msgid "Retry failed jobs"
-msgstr "Reîncercați joburile eșuate"
-
msgid "Retry job"
msgstr "Reîncercați jobul"
@@ -33421,12 +33781,6 @@ msgstr "Copiați adresa de e-mail"
msgid "RightSidebar|Issue email"
msgstr "E-mail de problemă"
-msgid "RightSidebar|adding a"
-msgstr "la adăugarea"
-
-msgid "RightSidebar|deleting the"
-msgstr "la ștergerea"
-
msgid "Roadmap"
msgstr "Foaie parcurs"
@@ -33502,6 +33856,12 @@ msgstr "Executorii sunt procese care preiau și execută sarcini CI/CD pentru Gi
msgid "Runners page."
msgstr "Pagina executorilor."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] "%d executor selectat șters"
+msgstr[1] "%d executori selectați șterși"
+msgstr[2] "%d de executori selectați șterși"
+
msgid "Runners|%{percentage} spot."
msgstr "%{percentage} spot."
@@ -33559,6 +33919,9 @@ msgstr "Proiecte atribuite (%{projectCount})"
msgid "Runners|Associated with one or more projects"
msgstr "Asociat cu unul sau mai multe proiecte"
+msgid "Runners|Available"
+msgstr "Disponibil"
+
msgid "Runners|Available to all projects"
msgstr "Disponibil pentru toate proiectele"
@@ -33724,6 +34087,9 @@ msgstr "Executori online"
msgid "Runners|Online:"
msgstr "Online:"
+msgid "Runners|Outdated"
+msgstr "ÃŽnvechit"
+
msgid "Runners|Pause from accepting jobs"
msgstr "Întrerupeți acceptarea de joburi"
@@ -33748,6 +34114,9 @@ msgstr "Numele proprietății"
msgid "Runners|Protected"
msgstr "Protejat"
+msgid "Runners|Recommended"
+msgstr "Recomandat"
+
msgid "Runners|Register a group runner"
msgstr "Înregistrați un executor de grup"
@@ -33856,6 +34225,9 @@ msgstr "Afișați instrucțiunile de instalare și înregistrare a executorului"
msgid "Runners|Show runner installation instructions"
msgstr "Afișați instrucțiunile de instalare a executorului"
+msgid "Runners|Something went wrong while deleting. Please refresh the page to try again."
+msgstr "Ceva nu a mers bine în timpul ștergerii. Pentru a încerca din nou, vă rugăm să reîmprospătați pagina."
+
msgid "Runners|Something went wrong while fetching runner data."
msgstr "Ceva nu a mers bine în timpul preluării datelor executorilor."
@@ -33916,9 +34288,18 @@ msgstr "Pentru a instala un Executor în Kubernetes, urmați instrucțiunile des
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
msgstr "Pentru a instala un Executor într-un container, urmați instrucțiunile descrise în documentația GitLab"
+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|Up to date"
+msgstr "La zi"
+
msgid "Runners|Upgrade GitLab Runner to match the version of GitLab you're running. Both %{linkStart}major and minor versions%{linkEnd} should match."
msgstr "Actualizați GitLab Runner pentru a se potrivi cu versiunea lui GitLab pe care o utilizați. Amândouă %{linkStart}versiunile, majoră și minoră%{linkEnd}, ar trebui să corespundă."
+msgid "Runners|Upgrade Status"
+msgstr "Statusul actualizării"
+
msgid "Runners|Upgrade available"
msgstr "Upgrade disponibil"
@@ -33964,6 +34345,9 @@ msgstr "Ați folosit %{quotaUsed} din cele %{quotaLimit} de minute ale dvs. de p
msgid "Runners|active"
msgstr "activ"
+msgid "Runners|available"
+msgstr "disponibil"
+
msgid "Runners|group"
msgstr "grup"
@@ -33979,6 +34363,9 @@ msgstr "online"
msgid "Runners|paused"
msgstr "în pauză"
+msgid "Runners|recommended"
+msgstr "recomandat"
+
msgid "Runners|shared"
msgstr "partajat"
@@ -33992,7 +34379,10 @@ msgid "Runners|upgrade available"
msgstr "actualizare disponibilă"
msgid "Runners|upgrade recommended"
-msgstr "actualizare recomandată"
+msgstr "upgrade recomandat"
+
+msgid "Runner|Owner"
+msgstr "Proprietar"
msgid "Running"
msgstr "Rulează"
@@ -34036,6 +34426,9 @@ msgstr "Configurare SAST"
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr "Amprentele SSH"
+
msgid "SSH Key"
msgstr "Cheie SSH"
@@ -34045,6 +34438,9 @@ msgstr "Chei SSH"
msgid "SSH Keys Help"
msgstr "Ajutor pentru cheile 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 "Amprentele SSH verifică dacă clientul se conectează la gazda corectă. Verificați %{config_link_start}configurația curentă a instanței%{config_link_end}."
+
msgid "SSH host key fingerprints"
msgstr "Amprentele cheii SSH a gazdei"
@@ -34123,6 +34519,21 @@ msgstr "Se salvează"
msgid "Saving project."
msgstr "Se salvează proiectul."
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr "%{ifLabelStart}dacă%{ifLabelEnd} %{rules} pentru ramura/ramurile %{branches}"
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr "Se execută un pipeline"
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr "Programare"
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr "Elementul regulii de programare"
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr "Selectați ramurile"
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr "%{ifLabelStart}dacă%{ifLabelEnd} %{scanners} găsește mai mult de %{vulnerabilitiesAllowed} (de) vulnerabilitate/vulnerabilități %{severities} %{vulnerabilityStates} într-un merge request deschis care vizează %{branches}"
@@ -34453,6 +34864,12 @@ msgstr[0] "rezultat wiki"
msgstr[1] "rezultate wiki"
msgstr[2] "de rezultate wiki"
+msgid "SearchToken|Assignee"
+msgstr "Responsabil"
+
+msgid "SearchToken|Reviewer"
+msgstr "Recenzent"
+
msgid "Searching by both author and message is currently not supported."
msgstr "Căutarea atât după autor, cât și după mesaj nu este acceptată în prezent."
@@ -34513,6 +34930,9 @@ msgstr "Configurarea securității"
msgid "Security Dashboard"
msgstr "Tabloul de bord de securitate"
+msgid "Security Finding not found"
+msgstr "Detectarea de securitate nu a fost găsită"
+
msgid "Security dashboard"
msgstr "Tabloul de bord de securitate"
@@ -34757,7 +35177,7 @@ msgid "SecurityOrchestration|Description"
msgstr "Descriere"
msgid "SecurityOrchestration|Direct"
-msgstr ""
+msgstr "Direct"
msgid "SecurityOrchestration|Don't show the alert anymore"
msgstr "Nu mai afișați alerta"
@@ -34786,11 +35206,17 @@ msgstr "Impuneți securitatea pentru acest proiect. %{linkStart}Mai multe inform
msgid "SecurityOrchestration|Failed to load cluster agents."
msgstr "Încărcarea agenților de cluster a eșuat."
+msgid "SecurityOrchestration|Failed to load images."
+msgstr "Nu s-a reușit încărcarea imaginilor."
+
+msgid "SecurityOrchestration|Failed to load vulnerability scanners."
+msgstr "Nu s-au putut încărca scanerele de vulnerabilitate."
+
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 "Dacă un scaner găsește o vulnerabilitate critică nou detectată într-un merge request deschis care vizează ramura principală, atunci solicitați două aprobări din partea oricărui membru al securității aplicației."
msgid "SecurityOrchestration|Inherited"
-msgstr ""
+msgstr "Moștenit"
msgid "SecurityOrchestration|Inherited from %{namespace}"
msgstr "Moștenit din %{namespace}"
@@ -34951,6 +35377,9 @@ msgstr "Următoarele ramuri nu există în acest proiect de dezvoltare: %{branch
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr "A apărut o problemă în timpul creării noii politici de securitate"
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "Acest %{namespaceType} nu conține nicio politică de securitate."
+
msgid "SecurityOrchestration|This group"
msgstr "Acest grup"
@@ -34969,9 +35398,6 @@ msgstr "Această politică este moștenită din %{linkStart}spațiul de nume%{li
msgid "SecurityOrchestration|This project"
msgstr "Acest proiect"
-msgid "SecurityOrchestration|This project does not contain any security policies."
-msgstr "Acest proiect nu conține nicio politică de securitate."
-
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 "Această vizualizare afișează numai rezultatele scanării pentru agentul %{agent}. Puteți vizualiza rezultatele scanării pentru toți agenții în %{linkStart}fila Vulnerabilități operaționale din raportul de vulnerabilitate%{linkEnd}."
@@ -35128,6 +35554,9 @@ msgstr "Nu s-au putut obține informații despre raportul de securitate. Vă rug
msgid "SecurityReports|Hide dismissed"
msgstr "Ascundeți elementele respinse"
+msgid "SecurityReports|Image"
+msgstr "Imagine"
+
msgid "SecurityReports|Issue Created"
msgstr "Problemă creată"
@@ -35182,6 +35611,15 @@ msgstr "Oops, ceva nu pare să fie în regulă."
msgid "SecurityReports|Operational vulnerabilities"
msgstr "Vulnerabilități operaționale"
+msgid "SecurityReports|Parsing errors and warnings in pipeline"
+msgstr "Erori și avertismente de analiză în pipeline"
+
+msgid "SecurityReports|Parsing errors in pipeline"
+msgstr "Erori de analiză în pipeline"
+
+msgid "SecurityReports|Parsing warnings in pipeline"
+msgstr "Avertismente de analiză în pipeline"
+
msgid "SecurityReports|Project"
msgstr "Proiect"
@@ -35228,7 +35666,7 @@ msgid "SecurityReports|Show %{pageSize} items"
msgstr "Afișați %{pageSize} (de) articole"
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 "Uneori, un scaner nu poate determina severitatea unei descoperiri. Aceste constatări pot fi totuși o sursă potențială de risc. Vă rugăm să le examinați manual."
+msgstr "Uneori, un scaner nu poate determina severitatea unei descoperiri. Aceste detectări pot fi totuși o sursă potențială de risc. Vă rugăm să le examinați manual."
msgid "SecurityReports|Sorry, your filter produced no results"
msgstr "Ne pare rău, filtrul dvs. nu a produs rezultate"
@@ -35246,7 +35684,7 @@ msgid "SecurityReports|The Vulnerability Report shows results of successful scan
msgstr "Raportul de vulnerabilitate prezintă rezultatele scanărilor reușite pe ramura implicită a proiectului dvs., înregistrările de vulnerabilități adăugate manual și vulnerabilitățile găsite în urma scanării mediilor operaționale. %{linkStart}Aflați mai multe.%{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 "Următoarele rapoarte de securitate conțin una sau mai multe constatări de vulnerabilitate care nu au putut fi analizate și nu au fost înregistrate. Pentru a investiga un raport, descărcați artefactele din ieșirea jobului. Asigurați-vă că raportul de securitate este conform cu schema %{helpPageLinkStart}JSON relevantă%{helpPageLinkEnd}."
+msgstr "Următoarele rapoarte de securitate conțin una sau mai multe detectări de vulnerabilitate care nu au putut fi analizate și nu au fost înregistrate. Pentru a investiga un raport, descărcați artefactele din ieșirea jobului. Asigurați-vă că raportul de securitate este conform cu schema %{helpPageLinkStart}JSON relevantă%{helpPageLinkEnd}."
msgid "SecurityReports|The security report for this pipeline has %{helpPageLinkStart}expired%{helpPageLinkEnd}. Re-run the pipeline to generate a new security report."
msgstr "Raportul de securitate pentru acest pipeline a %{helpPageLinkStart}expirat%{helpPageLinkEnd}. Re-executați pipeline-ul pentru a genera un nou raport de securitate."
@@ -35536,9 +35974,6 @@ msgstr "Selectat pentru unele articole."
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 "Nivelurile selectate nu pot fi utilizate de utilizatorii care nu sunt administratori pentru grupuri, proiecte sau fragmente de cod. Dacă nivelul public este restricționat, profilurile utilizatorilor sunt vizibile numai pentru utilizatorii conectați."
-msgid "Selected projects"
-msgstr "Proiecte selectate"
-
msgid "Selected tag is already in use. Choose another option."
msgstr "Eticheta selectată este deja în uz. Alegeți o altă opțiune."
@@ -35722,9 +36157,6 @@ msgstr "Activați serviciul ping"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr "Activați ping-ul serviciului pentru a revizui analizele la nivel de instanță."
-msgid "Services"
-msgstr "Servicii"
-
msgid "Session ID"
msgstr "ID-ul sesiunii"
@@ -35740,9 +36172,6 @@ msgstr "Setați un șablon de descriere implicit pentru a fi utilizat pentru noi
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Setați o parolă în contul dvs. pentru a face pull sau push prin %{protocol}."
-msgid "Set access permissions for this token."
-msgstr "Setați permisiunile de acces pentru acest token."
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr "Setați orice limită de rată la %{code_open}0%{code_close} pentru a dezactiva limita."
@@ -35867,7 +36296,7 @@ msgid "Set up your project to automatically push and/or pull changes to/from ano
msgstr "Configurați-vă proiectul pentru push și/sau pull automat către/de la un alt repozitoriu. Ramurile, etichetele și commit-urile vor fi sincronizate automat."
msgid "Set visibility of project contents. Configure import sources and Git access protocols."
-msgstr ""
+msgstr "Setați vizibilitatea conținutului proiectului. Configurați sursele de import și protocoalele de acces Git."
msgid "Set weight"
msgstr "Setați greutatea"
@@ -36229,8 +36658,8 @@ msgstr "Se afișează cea mai recentă versiune"
msgid "Showing version #%{versionNumber}"
msgstr "Se afișează versiunea #%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr "Afișează problemele și %{labels_count} (de) etichete pentru grupul „%{group_name}†de la 1 noiembrie 2019 până la 31 decembrie 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgstr "Afișează problemele pentru grupul „%{group_name}†de la 1 noiembrie 2019 la 31 decembrie 2019"
msgid "Side-by-side"
msgstr "Alăturat"
@@ -36316,6 +36745,9 @@ msgstr "Pagina de autentificare și de Ajutor"
msgid "Sign-in count:"
msgstr "Număr de conectări:"
+msgid "Sign-in failed because %{error}."
+msgstr "Înregistrarea a eșuat deoarece %{error}."
+
msgid "Sign-in page"
msgstr "Pagina de conectare"
@@ -36325,6 +36757,9 @@ msgstr "Restricții de conectare"
msgid "Sign-in text"
msgstr "Text de conectare"
+msgid "Sign-in using %{provider} auth failed"
+msgstr "Autentificarea folosind autentificarea %{provider} a eșuat"
+
msgid "Sign-out page URL"
msgstr "URL-ul paginii de deconectare"
@@ -36559,9 +36994,6 @@ msgstr "Solid"
msgid "Solution"
msgstr "Soluție"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr "Unele acțiuni elimină cererile de atenție, cum ar fi aprobarea unui revizor sau îmbinarea unui merge request de către cineva."
-
msgid "Some changes are not shown"
msgstr "Unele modificări nu sunt afișate"
@@ -37678,9 +38110,6 @@ msgstr "Scade"
msgid "Succeeded"
msgstr "Reușit"
-msgid "Successful purchase image"
-msgstr "Imagine achiziționată cu succes"
-
msgid "Successfully activated"
msgstr "Activat cu succes"
@@ -37715,7 +38144,7 @@ msgid "Successfully synced %{synced_timeago}."
msgstr "S-a sincronizat cu succes %{synced_timeago}."
msgid "Successfully unbanned"
-msgstr "Anularea interzicerii reușită"
+msgstr "Eliminarea excluderii a avut succes"
msgid "Successfully unblocked"
msgstr "Deblocat cu succes"
@@ -38026,9 +38455,6 @@ msgstr "Suportul pentru certificate personalizate este dezactivat. Cereți admin
msgid "Support page URL"
msgstr "URL-ul paginii de asistență"
-msgid "Survey Response"
-msgstr "Răspuns la sondaj"
-
msgid "Surveys|Delighted"
msgstr "Încântat"
@@ -38131,6 +38557,9 @@ msgstr "Metrici de sistem (Kubernetes)"
msgid "System output"
msgstr "Ieșirea sistemului"
+msgid "System started"
+msgstr "Sistem pornit"
+
msgid "Table of Contents"
msgstr "Cuprins"
@@ -38203,6 +38632,9 @@ msgstr "Anulare"
msgid "TagsPage|Cancel, keep tag"
msgstr "Anulați, păstrați eticheta"
+msgid "TagsPage|Create release"
+msgstr "Creați o versiune"
+
msgid "TagsPage|Create tag"
msgstr "Creați eticheta"
@@ -38221,8 +38653,8 @@ msgstr "Ștergeți eticheta. Sunteți ABSOLUT SIGUR?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr "Ștergerea etichetei %{strongStart}%{tagName}%{strongEnd} nu poate fi anulată. Sunteți sigur?"
-msgid "TagsPage|Edit release notes"
-msgstr "Editați notele de lansare"
+msgid "TagsPage|Edit release"
+msgstr "Editarea versiunii"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Numele ramurii, eticheta sau SHA de commit existente"
@@ -38320,9 +38752,6 @@ msgstr "ID-ul sarcinii: %{elastic_task}"
msgid "Task list"
msgstr "Lista de sarcini"
-msgid "Task with ID: %{id} could not be found."
-msgstr "Sarcina cu ID-ul: %{id} nu a putut fi găsită."
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr "Creați/importați cod într-un proiect (repozitoriu)"
@@ -38678,7 +39107,7 @@ msgid "TestReports|Attachment"
msgstr "Atașament"
msgid "TestReports|Copy test name to rerun locally"
-msgstr ""
+msgstr "Copiați numele testului pentru a-l relua local"
msgid "TestReports|Job artifacts are expired"
msgstr "Artefactele de job sunt expirate"
@@ -38737,9 +39166,6 @@ msgstr "Stil de text"
msgid "Thank you for your business."
msgstr "Vă mulțumesc pentru afacerea dumneavoastră."
-msgid "Thank you for your feedback!"
-msgstr "Vă mulțumim pentru feedbackul dumneavoastră!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "Vă mulțumim pentru raportul dumneavoastră. Un administrator GitLab se va ocupa de acesta în scurt timp."
@@ -39031,9 +39457,6 @@ msgstr "Ultimul proprietar nu poate fi setat în așteptare"
msgid "The latest artifacts created by jobs in the most recent successful pipeline will be stored."
msgstr "Ultimele artefacte create de joburile din cel mai recent pipeline de succes vor fi stocate."
-msgid "The latest pipeline for this merge request did not complete successfully."
-msgstr "Cel mai recent pipeline pentru acest merge request nu s-a finalizat cu succes."
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr "Cel mai recent pipeline pentru acest merge request nu a reușit. Cele mai recente modificări sunt neverificate."
@@ -39193,6 +39616,9 @@ msgstr "Repozitoriul trebuie să fie accesibil prin %{code_open}http://%{code_cl
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 "Repozitoriul trebuie să fie accesibil prin %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} sau %{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 "Resursa pe care încercați să o accesați nu există sau nu aveți permisiunea de a efectua această acțiune."
+
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 "Același executor partajat execută cod din mai multe proiecte, numai dacă nu configurați scalarea automată cu %{link} setat la 1 (care este pe GitLab.com)."
@@ -39307,6 +39733,9 @@ msgstr "Nu există cerințe arhivate"
msgid "There are no archived test cases"
msgstr "Nu există cazuri de testare arhivate"
+msgid "There are no changed labels"
+msgstr "Nu există etichete modificate"
+
msgid "There are no changes"
msgstr "Nu există modificări"
@@ -39359,7 +39788,7 @@ msgid "There are no projects shared with this group yet"
msgstr "Nu există încă proiecte partajate cu acest grup"
msgid "There are no secure files yet."
-msgstr ""
+msgstr "Nu există încă fișiere securizate."
msgid "There are no topics to show."
msgstr "Nu există subiecte de afișat."
@@ -39379,6 +39808,9 @@ msgstr "Există mai multe limite de rată pentru a proteja sistemul."
msgid "There are several size limits in place."
msgstr "Există mai multe limite de mărime în vigoare."
+msgid "There are unsubmitted review comments."
+msgstr "Există comentarii de revizuire nedepuse."
+
msgid "There is already a repository with that name on disk"
msgstr "Există deja un repozitoriu cu acest nume pe disc"
@@ -39481,9 +39913,6 @@ msgstr "A existat o eroare la trimiterea e-mailului de confirmare"
msgid "There was a problem updating the keep latest artifacts setting."
msgstr "A existat o problemă la actualizarea setării de păstrare a celor mai recente artefacte."
-msgid "There was an error %{message} to-do item."
-msgstr "A apărut o eroare %{message} sarcinii de-făcut."
-
msgid "There was an error adding a To Do."
msgstr "S-a produs o eroare la adăugarea unui element De Făcut"
@@ -39562,9 +39991,6 @@ msgstr "A apărut o eroare la analizarea datelor pentru acest grafic."
msgid "There was an error removing the e-mail."
msgstr "A apărut o eroare la înlăturarea e-mailului."
-msgid "There was an error resetting group pipeline minutes."
-msgstr "A apărut o eroare la resetarea minutelor pipeline-ului grupului."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "A apărut o eroare la resetarea minutelor de pipeline ale utilizatorului."
@@ -39616,9 +40042,6 @@ msgstr "S-a produs o eroare în timpul preluării datelor de analiză a fluxului
msgid "There was an error while fetching value stream analytics duration data."
msgstr "S-a produs o eroare în timpul preluării datelor privind durata analizei fluxului de valori."
-msgid "There was an error while fetching value stream summary data."
-msgstr "S-a produs o eroare la preluarea datelor de sinteză a fluxului de valori."
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "A apărut o eroare cu reCAPTCHA. Vă rugăm să rezolvați din nou reCAPTCHA."
@@ -39799,6 +40222,9 @@ msgstr "Acest director"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "Acest domeniu nu este confirmat. Va trebui să verificați calitatea de proprietar înainte de activarea accesului."
+msgid "This email address does not look right, are you sure you typed it correctly?"
+msgstr "Această adresă de e-mail nu arată bine, sunteți sigur că ați introdus-o corect?"
+
msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_link}."
msgstr "Acest e-mail înlocuiește toate e-mailurile anterioare despre ștergerea programată pe care le-ați primit pentru %{project_link}."
@@ -40156,6 +40582,12 @@ msgstr "Acest proiect va fi șters la %{date}, deoarece grupul său părinte „
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
msgstr "Acest proiect va fi găzduit în grupul dvs. %{strong_open}%{namespace}%{strong_close}. Un proiect este locul unde vă stocați fișierele (repozitoriu), vă planificați activitatea (probleme), vă publicați documentația (wiki) și multe altele."
+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ă."
+
+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 "Acest raport utilizează o versiune de schemă MAJOR.MINOR acceptată, dar versiunea PATCH nu se potrivește cu nicio versiune de schemă comercializată. Se va încerca validarea împotriva versiunii %{find_latest_patch_version}"
+
msgid "This repository"
msgstr "Acest repozitoriu"
@@ -40468,6 +40900,9 @@ msgstr "Dezactivați afișarea actualizărilor recente"
msgid "Timeline|Turn recent updates view on"
msgstr "Activați vizualizarea actualizărilor recente"
+msgid "Timelog doesn't exist or you don't have permission to delete it"
+msgstr "Jurnalul de timp nu există sau nu aveți permisiunea de a-l șterge"
+
msgid "Timeout"
msgstr "Timeout"
@@ -40552,9 +40987,6 @@ msgstr "Pentru a adăuga un sufix personalizat, configurați o adresă de e-mail
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."
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr "Pentru a cere cuiva să examineze un merge request, selectați %{strongStart}Solicită atenție%{strongEnd}. Selectați din nou pentru a elimina solicitarea."
-
msgid "To complete registration, we need additional details from you."
msgstr "Pentru a finaliza înregistrarea, avem nevoie de detalii suplimentare de la dumneavoastră."
@@ -40630,8 +41062,8 @@ msgstr "Pentru a continua acest proiect, creați un nou merge request"
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr "Pentru a afla mai multe despre acest proiect, citiți %{link_to_wiki}"
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
-msgstr "Pentru a gestiona toți membrii asociați cu acest grup și cu subgrupurile și proiectele sale, vizitați %{link_start}pagina cotelor de utilizare%{link_end}."
+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 "Pentru a gestiona locurile pentru toți membrii asociați cu acest grup și subgrupurile și proiectele sale, vizitați %{link_start}pagina cotelor de utilizare%{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 "Pentru a muta sau a copia un întreg proiect GitLab de pe o altă instalație GitLab pe aceasta, navigați pe pagina de setări a proiectului original, generați un fișier de export și încărcați-l aici."
@@ -40864,6 +41296,9 @@ msgstr "S-au găsit prea mulți utilizatori. Acțiunile rapide sunt limitate la
msgid "TopNav|Go back"
msgstr "ÃŽnapoi"
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr "Îmbinarea subiectului %{source_topic} în subiectul %{target_topic} a reușit."
+
msgid "Topic %{topic_name} was successfully created."
msgstr "Subiectul %{topic_name} a fost creat cu succes."
@@ -41170,6 +41605,9 @@ msgstr "Încercați să schimbați sau să înlăturați filtrele."
msgid "Try grouping with different labels"
msgstr "Încercați să grupați cu etichete diferite"
+msgid "Try logging in using your username or email. If you have forgotten your password, try recovering it"
+msgstr "Încercați să vă conectați utilizând numele de utilizator sau e-mailul. Dacă ați uitat parola, încercați să o recuperați."
+
msgid "Try out GitLab Pipelines"
msgstr "Încercați pipeline-urile GitLab"
@@ -41254,6 +41692,9 @@ msgstr "Perioada de grație cu doi factori"
msgid "Type"
msgstr "Tipul"
+msgid "Type to search"
+msgstr "Introduceți textul de căutat"
+
msgid "U2F Devices (%{length})"
msgstr "Dispozitive U2F (%{length})"
@@ -41374,6 +41815,9 @@ msgstr "Nu se poate încărca diff-ul. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "Imposibil de încărcat widget-ul Merge-Request-ului. Încercați să reîncărcați pagina."
+msgid "Unable to parse JSON"
+msgstr "JSON nu poate fi analizat"
+
msgid "Unable to parse the vulnerability report's options."
msgstr "Nu se pot analiza opțiunile raportului de vulnerabilitate."
@@ -41437,6 +41881,9 @@ msgstr "Solicitări neautentificate"
msgid "Unauthenticated web rate limit period in seconds"
msgstr "Perioada limită a ratei pentru web-ul neautentificat în secunde"
+msgid "Unban"
+msgstr "Deblocați"
+
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr "Modificările care nu au fost comise vor fi pierdute dacă schimbați ramurile. Doriți să continuați?"
@@ -41482,9 +41929,6 @@ msgstr "Format necunoscut"
msgid "Unknown response text"
msgstr "Text de răspuns necunoscut"
-msgid "Unknown screen"
-msgstr "Ecran necunoscut"
-
msgid "Unknown user"
msgstr "Utilizator necunoscut"
@@ -41677,9 +42121,6 @@ msgstr "Data actualizării"
msgid "Updating"
msgstr "Actualizare"
-msgid "Updating the attention request for %{username} failed."
-msgstr "Actualizarea solicitării de atenție pentru %{username} a eșuat."
-
msgid "Updating…"
msgstr "Actualizare..."
@@ -41707,6 +42148,9 @@ msgstr "Încărcați un certificat pentru domeniul dvs cu toți intermediarii"
msgid "Upload a private key for your certificate"
msgstr "Încărcați o cheie privată pentru certificatul d-voastră"
+msgid "Upload could not be deleted."
+msgstr "Nu s-a putut șterge încărcarea."
+
msgid "Upload file"
msgstr "Încărcați fișierul"
@@ -41720,7 +42164,7 @@ msgid "Upload object map"
msgstr "Încărcați maparea obiectelor"
msgid "Uploaded date"
-msgstr ""
+msgstr "Data încărcării"
msgid "Uploading changes to terminal"
msgstr "Încărcarea modificărilor în terminal"
@@ -41731,9 +42175,6 @@ msgstr "Se încarcă..."
msgid "Upstream"
msgstr "ÃŽn amonte"
-msgid "Uptime"
-msgstr "Timp de funcționare"
-
msgid "Upvotes"
msgstr "Voturi pozitive"
@@ -41794,12 +42235,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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
-msgstr "Începând cu %{storage_enforcement_date}, se vor aplica limite de stocare pentru acest spațiu de nume. În prezent, utilizați %{used_storage} de spațiu de stocare pentru spațiul de nume. Vizualizați și gestionați utilizarea dvs. din %{strong_start}setările de %{namespace_type} &gt; Cote de utilizare%{strong_end}."
-
msgid "UsageQuota|Git repository."
msgstr "Repozitoriul Git."
@@ -41869,6 +42310,9 @@ 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."
@@ -41896,6 +42340,18 @@ msgstr "Tipul de stocare"
msgid "UsageQuota|Storage used"
msgstr "Stocarea utilizată"
+msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "
+msgstr "Grupul %{strong_start}%{context_name}%{strong_end} va fi afectat de acest lucru. "
+
+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}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}"
+msgstr "Spațiul de nume utilizează în prezent %{strong_start}%{used_storage}%{strong_end} de stocare a spațiului de nume. Proprietarii grupurilor pot vizualiza utilizarea spațiului de stocare al spațiului de nume și pot achiziționa mai mult accesând %{strong_start}Setări grup &gt; Cotele de utilizare%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 stocare a spațiului de nume. Vizualizați și gestionați consumul prin %{strong_start}Setări utilizator &gt; Cotele de consum%{strong_end}. %{docs_link_start}Aflați mai multe%{link_end} despre cum să vă reduceți spațiul de stocare."
+
msgid "UsageQuota|The table below shows current period usage"
msgstr "Tabelul de mai jos prezintă utilizarea din perioada curentă"
@@ -42166,6 +42622,12 @@ msgstr "Utilizați cardul inteligent pentru a vă autentifica prin serverul LDAP
msgid "Used"
msgstr "Folosit"
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "Folosit de %d pachet"
+msgstr[1] "Folosit de %d pachete"
+msgstr[2] "Folosit de %d de pachete"
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "Folosit de membri pentru a se conecta la grupul dvs. în GitLab"
@@ -42259,6 +42721,9 @@ msgstr "Utilizatorul a fost înlăturat cu succes din grup."
msgid "User was successfully removed from project."
msgstr "Utilizatorul a fost înlăturat cu succes din proiect."
+msgid "User was successfully unbanned."
+msgstr "Excluderea utilizatorului a fost ridicată."
+
msgid "User was successfully updated."
msgstr "Utilizatorul a fost actualizat cu succes."
@@ -42367,6 +42832,9 @@ msgstr "Activitate bot"
msgid "UserProfile|Contributed projects"
msgstr "Proiecte contribuite"
+msgid "UserProfile|Copy user ID"
+msgstr "Copiați ID-ul de utilizator"
+
msgid "UserProfile|Edit profile"
msgstr "Editare profil"
@@ -42448,6 +42916,9 @@ msgstr "Acest utilizator nu urmărește alți utilizatori."
msgid "UserProfile|Unconfirmed user"
msgstr "Utilizator neconfirmat"
+msgid "UserProfile|User ID: %{id}"
+msgstr "ID-ul de utilizator: %{id}"
+
msgid "UserProfile|View all"
msgstr "Vizualizați totul"
@@ -42613,12 +43084,6 @@ msgstr "Nu avem suficiente date pentru a afișa această etapă."
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr "%{stageCount}+ elemente"
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] "%{subjectFilterText} și %{selectedLabelsCount} etichetă"
-msgstr[1] "%{subjectFilterText} și %{selectedLabelsCount} etichete"
-msgstr[2] "%{subjectFilterText} și %{selectedLabelsCount} de etichete"
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr "%{value}luni"
@@ -42673,11 +43138,17 @@ msgstr "Numărul de noi probleme create."
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr "Procentul de implementări care provoacă un incident în producție."
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr "Afișează %{selectedFiltersDescription} pentru grupul „%{groupName}†și %{selectedProjectCount} (de) proiecte creat(e) între %{createdAfter} și %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr "Afișează %{selectedSubjectFilterText} și %{labelsCount} pentru grupul „%{groupName}†și %{projectsCount} de la %{createdAfter} la %{createdBefore}"
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr "Afișează %{selectedFiltersDescription} pentru grupul „%{groupName}†de la %{createdAfter} la %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr "Afișează %{selectedSubjectFilterText} și %{labelsCount} pentru grupul „%{groupName}†de la %{createdAfter} la %{createdBefore}"
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr "Afișează %{selectedSubjectFilterText} pentru grupul „%{groupName}†și %{projectsCount} de la %{createdAfter} la %{createdBefore}"
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr "Afișează %{selectedSubjectFilterText} pentru grupul „%{groupName}†de la %{createdAfter} la %{createdBefore}"
msgid "ValueStreamAnalytics|Tasks by type"
msgstr "Sarcini după tip"
@@ -42766,6 +43237,12 @@ msgstr "Verificați configurația"
msgid "Version"
msgstr "Versiune"
+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 "Versiunea %{report_version} a raportului de tip %{report_type} a fost depreciată, versiunile acceptate pentru acest tip de raport sunt: %{supported_schema_versions}. GitLab va încerca să analizeze și să integreze acest raport dacă este valid."
+
+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 "Versiunea %{report_version} a raportul de tip %{report_type} nu este acceptată, versiunile acceptate ale acestui tip de raport sunt: %{supported_schema_versions}. GitLab va încerca să valideze acest raport împotriva celor mai vechi versiuni acceptate ale acestui tip de raport, pentru a afișa toate erorile, dar nu va integra raportul"
+
msgid "Version %{versionNumber}"
msgstr "Versiunea %{versionNumber}"
@@ -43378,6 +43855,9 @@ msgstr "Avertisment: Sincronizarea LDAP înlătură accesul direct al membrilor.
msgid "Watch how"
msgstr "Observați cum"
+msgid "We also use email for avatar detection if no avatar is uploaded."
+msgstr "E-mailul este utilizat și pentru detectarea avatarului, dacă nu este încărcat niciun avatar."
+
msgid "We are currently unable to fetch data for the pipeline header."
msgstr "ÃŽn prezent, nu putem prelua date pentru antetul pipeline-ului."
@@ -43423,9 +43903,6 @@ msgstr "Vă invităm să %{featureLinkStart}solicitați o caracteristică%{featu
msgid "We recommend a work email address."
msgstr "Vă recomandăm o adresă de e-mail de serviciu."
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr "Vă recomandăm aplicațiile de autentificare mobilă bazate pe cloud, cum ar fi Authy, Duo Mobile și LastPass. Acestea pot restabili accesul în cazul în care vă pierdeți dispozitivul hardware."
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr "Vă recomandăm să lăsați toți analizatorii SAST activi"
@@ -43435,6 +43912,9 @@ msgstr "Vă recomandăm să cumpărați minute suplimentare pipeline pentru a ev
msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
msgstr "Vă recomandăm să cumpărați minute suplimentare pipeline pentru a relua serviciul normal."
+msgid "We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device."
+msgstr "Se recomandă utilizarea aplicațiilor de autentificare bazate pe cloud care pot restabili accesul în cazul în care vă pierdeți dispozitivul hardware."
+
msgid "We sent you an email with reset password instructions"
msgstr "V-am trimis un e-mail cu instrucțiuni de resetare a parolei"
@@ -43735,6 +44215,12 @@ msgstr "Ce sunt evenimentele de audit de instanță?"
msgid "What are project audit events?"
msgstr "Ce sunt evenimentele de audit de proiect?"
+msgid "What are some examples?"
+msgstr "Care sunt câteva exemple?"
+
+msgid "What does the setting affect?"
+msgstr "Ce anume influențează setarea?"
+
msgid "What does this command do?"
msgstr "Ce face această comandă?"
@@ -43795,6 +44281,12 @@ msgstr "Atunci când utilizați protocoalele %{code_open}http://%{code_close} sa
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 "Când vă transferați proiectul într-un grup, puteți să gestionați cu ușurință mai multe proiecte, să vizualizați cotele de utilizare a stocării, a minutelor de pipeline și a utilizatorilor și să începeți o perioadă de încercare sau să treceți la un nivel plătit."
+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] "La sfârșitul perioadei de probă, veți trece la nivelul gratuit, care are o limită de %{free_user_limit} seat. %{free_user_limit} seat va rămâne activ, iar membrii care nu ocupă un seat vor avea %{link_start}statutul Peste limită%{link_end} și vor pierde accesul la acest grup."
+msgstr[1] "La sfârșitul perioadei de probă, veți trece la nivelul gratuit, care are o limită de %{free_user_limit} seat-uri. %{free_user_limit} seat-uri vor rămâne active, iar membrii care nu ocupă un seat vor avea %{link_start}statutul Peste limită%{link_end} și vor pierde accesul la acest grup."
+msgstr[2] "La sfârșitul perioadei de probă, veți trece la nivelul gratuit, care are o limită de %{free_user_limit} de seat-uri. %{free_user_limit} de seat-uri vor rămâne active, iar membrii care nu ocupă un seat vor avea %{link_start}statutul Peste limită%{link_end} și vor pierde accesul la acest grup."
+
msgid "When:"
msgstr "Când:"
@@ -43831,6 +44323,12 @@ 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"
@@ -43957,12 +44455,6 @@ msgstr "Creați %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Creați pagina"
-msgid "WikiPage|Edit rich text"
-msgstr "Editați textul bogat"
-
-msgid "WikiPage|Edit source"
-msgstr "Editați sursa"
-
msgid "WikiPage|Format"
msgstr "Format"
@@ -44062,23 +44554,29 @@ msgstr "Lucrări în curs (deschise și neatribuite)"
msgid "Work in progress Limit"
msgstr "Limita de lucrări în curs"
-msgid "WorkItem|Add"
-msgstr "Adăugați"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "O sarcină vă oferă posibilitatea de a împărți munca în bucăți mai mici legate de o problemă. Sarcinile sunt primele elemente care utilizează noile noastre obiecte %{workItemsLink}. Alte tipuri de elemente de lucru vor fi disponibile în curând."
+
+msgid "WorkItem|Add a task"
+msgstr "Adăugați o sarcină"
-msgid "WorkItem|Add a child"
-msgstr "Adăugați un copil"
+msgid "WorkItem|Add a title"
+msgstr "Adăugați un titlu"
msgid "WorkItem|Add assignee"
-msgstr ""
+msgstr "Adăugare responsabil"
msgid "WorkItem|Add assignees"
-msgstr ""
+msgstr "Adăugare responsabili"
+
+msgid "WorkItem|Add task"
+msgstr "Adăugați sarcina"
msgid "WorkItem|Are you sure you want to cancel editing?"
msgstr "Sunteți sigur că doriți să anulați editarea?"
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
-msgstr "Sunteți sigur că doriți să ștergeți elementul de lucru? Această acțiune nu poate fi anulată."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "Sunteți sigur că doriți să ștergeți sarcina? Această acțiune nu poate fi anulată."
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -44092,6 +44590,9 @@ msgstr "Anulare"
msgid "WorkItem|Child items"
msgstr "Elemente copil"
+msgid "WorkItem|Child removed"
+msgstr "Copilul a fost înlăturat"
+
msgid "WorkItem|Closed"
msgstr "ÃŽnchis"
@@ -44104,24 +44605,39 @@ msgstr "Creați o sarcină"
msgid "WorkItem|Create work item"
msgstr "Creați elementul de lucru"
-msgid "WorkItem|Delete work item"
-msgstr "Ștergeți elementul de lucru"
+msgid "WorkItem|Delete task"
+msgstr "Ștergeți sarcina"
msgid "WorkItem|Expand child items"
msgstr "Extindeți elementele copil"
+msgid "WorkItem|Introducing tasks"
+msgstr "Introducerea sarcinilor"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "Aflați mai multe despre sarcini"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr "În prezent nu este atribuit niciun element copil. Utilizați elementele copil pentru a acorda prioritate sarcinilor pe care echipa dvs. trebuie să le completeze, pentru a vă îndeplini obiectivele!"
msgid "WorkItem|Open"
msgstr "Deschis"
+msgid "WorkItem|Remove"
+msgstr "Înlăturați"
+
msgid "WorkItem|Select type"
msgstr "Selectați tipul"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "Ceva nu a mers bine la crearea unei sarcini. Vă rugăm să încercați din nou"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr "Ceva nu a mers bine la crearea unui element de lucru. Vă rugăm să încercați din nou"
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "Ceva nu a mers bine la ștergerea sarcinii. Vă rugăm să încercați din nou."
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr "Ceva nu a mers bine la ștergerea elementului de lucru. Vă rugăm să încercați din nou."
@@ -44131,18 +44647,39 @@ msgstr "Ceva nu a mers bine la preluarea elementului de lucru. Vă rugăm să î
msgid "WorkItem|Something went wrong when fetching work item types. Please try again"
msgstr "Ceva nu a mers bine la preluarea tipurilor de elemente de lucru. Vă rugăm să încercați din nou"
+msgid "WorkItem|Something went wrong when trying to add a child. Please try again."
+msgstr "Ceva nu a mers bine atunci când s-a încercat adăugarea unui copil. Vă rugăm să încercați din nou."
+
+msgid "WorkItem|Something went wrong when trying to create a child. Please try again."
+msgstr "Ceva nu a mers bine atunci când ați încercat să creați un copil. Încercați din nou."
+
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|Task deleted"
+msgstr "Sarcină ștearsă"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr "Opriți confidențialitatea"
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr "Porniți confidențialitatea"
+
msgid "WorkItem|Type"
msgstr "Tipul"
+msgid "WorkItem|Undo"
+msgstr "Anulare"
+
msgid "WorkItem|Work Items"
msgstr "Elemente de lucru"
msgid "WorkItem|Work item deleted"
msgstr "Element de lucru șters"
+msgid "WorkItem|work items"
+msgstr "elemente de lucru"
+
msgid "Would you like to create a new branch?"
msgstr "Doriți să creați o nouă ramură?"
@@ -44425,8 +44962,11 @@ msgstr "Puteți începe prin a clona repozitoriul sau puteți începe să adăug
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 "Puteți grupa cazurile de testare utilizând etichete. Pentru a afla despre direcția viitoare a acestei funcții, vizitați %{linkStart}pagina direcției Managementul Calității%{linkEnd}."
-msgid "You can have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr "Puteți avea un maxim de %{free_limit} (de) membri unici în toate proiectele personale. Pentru a vizualiza și gestiona membrii, consultați pagina de membri pentru fiecare proiect din spațiul dvs. de nume. Vă recomandăm să vă %{move_link_start}mutați proiectele într-un grup%{move_link_end}, astfel încât să puteți gestiona cu ușurință utilizatorii și funcțiile."
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] "Puteți avea cel mult %{free_user_limit} membru unic în toate proiectele personale."
+msgstr[1] "Puteți avea maximum %{free_user_limit} membri unici în toate proiectele personale."
+msgstr[2] "Puteți avea maximum %{free_user_limit} de membri unici în toate proiectele personale."
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Puteți invita un nou membru la %{project_name} sau puteți invita un alt grup."
@@ -44434,9 +44974,6 @@ msgstr "Puteți invita un nou membru la %{project_name} sau puteți invita un al
msgid "You can invite a new member to %{project_name}."
msgstr "Puteți invita un nou membru la %{project_name}."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "Puteți invita un nou membru la %{strong_start}%{group_name}%{strong_end}."
-
msgid "You can invite another group to %{project_name}."
msgstr "Puteți invita un alt grup la %{project_name}."
@@ -44491,8 +45028,8 @@ msgstr "Vă puteți testa fișierul .gitlab-ci.yml în %{linkStart}CI Lint%{link
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
msgstr "Puteți vizualiza sursa sau %{linkStart}%{cloneIcon} clona repozitoriul%{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 this namespace can start a trial or upgrade to a paid tier."
-msgstr "Nu mai puteți adăuga membri, dar îi puteți gestiona pe cei existenți, de exemplu, prin înlăturarea membrilor inactivi și înlocuirea lor cu membri noi. Pentru a obține mai mulți membri, un proprietar al acestui namespace poate începe o perioadă de încercare sau poate face upgrade la un nivel plătit."
+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 "Nu puteți să mai adăugați membri, dar puteți să-i gestionați pe cei existenți, de exemplu, înlăturând membrii inactivi și înlocuindu-i cu alții noi. În vederea obținerii mai multor membri, un proprietar al grupului poate începe o perioadă de probă sau poate trece la un nivel plătit."
msgid "You cannot %{action} %{state} users."
msgstr "Nu puteți %{action} utilizatorii %{state}."
@@ -44503,15 +45040,9 @@ msgstr "Nu puteți accesa fișierul brut. Vă rugăm să așteptați un minut."
msgid "You cannot approve your own deployment."
msgstr "Nu puteți aproba propria implementare."
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr "Nu puteți modifica data de început după ce a început cadența. Vă rugăm să creați o nouă cadență."
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr "Nu puteți combina replace_ids cu add_ids sau remove_ids."
-msgid "You cannot edit this timeline event."
-msgstr "Nu puteți edita acest eveniment cronologic."
-
msgid "You cannot impersonate a blocked user"
msgstr "Nu puteți impersona un utilizator blocat"
@@ -44542,11 +45073,11 @@ msgstr "Nu puteÈ›i edita fiÈ™iere direct în acest proiect. Fork acest proiect È
msgid "You could not create a new trigger."
msgstr "Nu ați putut crea un nou declanșator."
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr "ÃŽn prezent, aveÈ›i peste %{free_limit} (de) membri în toate proiectele dvs. personale. ÃŽncepând cu 22 iunie 2022, cei mai recent activi %{free_limit} (de) membri vor rămâne activi, iar restul membrilor vor primi %{link_start}statutul „Peste limităâ€%{link_end} È™i își vor pierde accesul. Pentru a vizualiza È™i gestiona membrii, consultaÈ›i pagina membrilor pentru fiecare proiect din spaÈ›iul dvs. de nume. Vă recomandăm să vă %{move_link_start}mutaÈ›i proiectul într-un grup%{move_link_end} pentru a putea gestiona cu uÈ™urință utilizatorii È™i caracteristicile."
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr "Nu aveți niciun proiect Google Cloud. Vă rugăm să creați un proiect Google Cloud și apoi să reîncărcați această pagină."
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] "Aveți în prezent mai mult de %{free_user_limit} membru în toate proiectele personale. Începând cu 19 octombrie 2022, cel mai recent %{free_user_limit} membru activ va rămâne activ, iar ceilalți membri vor avea statutul %{link_start}Peste limită%{link_end} și-și vor pierde accesul."
+msgstr[1] "Aveți în prezent mai mult de %{free_user_limit} membri în toate proiectele personale. Începând cu 19 octombrie 2022, cei mai recent activi %{free_user_limit} membri vor rămâne activi, iar ceilalți membri vor avea statutul %{link_start}Peste limită%{link_end} și-și vor pierde accesul."
+msgstr[2] "Aveți în prezent mai mult de %{free_user_limit} de membri în toate proiectele personale. Începând cu 19 octombrie 2022, cei mai recent activi %{free_user_limit} membri vor rămâne activi, iar ceilalți membri vor avea statutul %{link_start}Peste limită%{link_end} și-și vor pierde accesul."
msgid "You do not have any subscriptions yet"
msgstr "Nu aveți încă niciun abonament"
@@ -44681,7 +45212,7 @@ msgid "You have insufficient permissions to remove this HTTP integration"
msgstr "Nu aveți permisiuni suficiente pentru a înlătura această integrare HTTP"
msgid "You have insufficient permissions to remove this Namespace Ban"
-msgstr ""
+msgstr "Nu aveți permisiuni suficiente pentru a înlătura interdicția acestui spațiu de nume"
msgid "You have insufficient permissions to set customer relations contacts for this issue"
msgstr "Aveți permisiuni insuficiente de a seta contacte pentru relațiile cu clienții pentru această problemă"
@@ -44881,6 +45412,9 @@ msgstr "Primiți acest e-mail pentru că ați fost menționat pe %{host}. %{mana
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 "Primiți acest e-mail pentru că ați fost menționat pe %{host}. %{unsubscribe_link_start}Dezabonați-vă%{unsubscribe_link_end} de la această discuție &middot; %{manage_notifications_link_start}Gestionați toate notificările%{manage_notifications_link_end} &middot; %{help_link_start}Ajutor%{help_link_end}"
+msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
+msgstr "Vizualizați membrii grupului %{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 "Ați activat deja autentificarea cu doi factori folosind autentificatoare cu o parolă unică. Pentru a înregistra un alt dispozitiv, trebuie mai întâi să dezactivați autentificarea cu doi factori."
@@ -44893,9 +45427,6 @@ msgstr "Ați respins %{user}"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr "%{doc_link_start}SpaÈ›iul dvs. de nume%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end}, are peste %{free_limit} de membri. ÃŽncepând cu 22 iunie 2022, acesta va fi limitat la %{free_limit}, iar restul membrilor vor primi %{link_start}statutul „Peste limităâ€%{link_end} È™i vor pierde accesul la spaÈ›iul de nume. PuteÈ›i accesa pagina „Cote de utilizare†pentru a gestiona care %{free_limit} de membri vor rămâne în spaÈ›iul dvs. de nume. Pentru a obÈ›ine mai mulÈ›i membri, un proprietar poate începe o perioadă de încercare sau poate face upgrade la un nivel plătit."
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr "Abonamentul dvs. %{group} va expira acum în %{days}."
@@ -44908,8 +45439,8 @@ msgstr "%{spammable_entity_type} dvs. a fost recunoscut ca spam È™i a fost înlÄ
msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
msgstr "%{spammable_entity_type} dvs. a fost recunoscut(ă) ca fiind spam. Vă rugăm să modificați conținutul sau să rezolvați reCAPTCHA pentru a continua."
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
-msgstr "Abonamentul dvs. %{strong}%{plan_name}%{strong_close} expiră pe %{strong}%{expires_on}%{strong_close}. După această dată, nu mai puteți crea probleme sau merge request-uri, sau folosi multe alte caracteristici."
+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 "Abonamentul %{strong}%{plan_name}%{strong_close} expiră la %{strong}%{expires_on}%{strong_close}. Dacă nu reînnoiți, pe abonamentul %{strong}%{downgrades_on}%{strong_close} veți pierde accesul la funcțiile plătite. După aceasta, problemele și merge request-urile nu vor mai putea fi create și multe funcții devin indisponibile."
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr "Abonamentul dvs. %{strong}%{plan_name}%{strong_close} pentru %{strong}%{namespace_name}%{strong_close} va expira pe %{strong}%{expires_on}%{strong_close}."
@@ -45082,6 +45613,18 @@ msgstr "Fișierul dvs. trebuie să conțină o coloană numită %{codeStart}titl
msgid "Your first project"
msgstr "Primul dvs. proiect"
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] "Grupul dvs. gratuit este acum limitat la %d membru"
+msgstr[1] "Grupul dvs. gratuit este acum limitat la %d membri"
+msgstr[2] "Grupul dvs. gratuit este acum limitat la %d de membri"
+
+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] "Grupul dvs., %{strong_start}%{namespace_name}%{strong_end} are mai mult de %{free_user_limit} membru. Începând cu 19 octombrie 2022, cel mai recent %{free_user_limit} membru activ va rămâne activ, iar restul membrilor vor avea statutul %{link_start}Peste limită%{link_end} și vor pierde accesul la grup. Pentru a gestiona care %{free_user_limit} membru va rămâne în grup, puteți accesa pagina Cotele de utilizare."
+msgstr[1] "Grupul dvs, %{strong_start}%{namespace_name}%{strong_end} are mai mult de %{free_user_limit} membri. Începând cu 19 octombrie 2022, cei mai recent %{free_user_limit} membri activi vor rămâne activi, iar ceilalți membri vor avea statutul %{link_start}Peste limită%{link_end} și vor pierde accesul la grup. Pentru a gestiona care dintre cei %{free_user_limit} membri vor rămâne în grup, puteți accesa pagina Cotele de utilizare."
+msgstr[2] "Grupul dvs., %{strong_start}%{namespace_name}%{strong_end} are mai mult de %{free_user_limit} de membri. Începând cu 19 octombrie 2022, cei mai recent activi %{free_user_limit} de membri vor rămâne activi, iar restul membrilor vor avea statutul %{link_start}Peste limită%{link_end} și vor pierde accesul la grup. Puteți accesa pagina Cotele de utilizare pentru a gestiona care dintre cei %{free_user_limit} de membri vor rămâne în grup."
+
msgid "Your groups"
msgstr "Grupurile dvs."
@@ -45178,9 +45721,6 @@ msgstr "Cerințele dvs. sunt importate. După terminare, veți primi un e-mail d
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr "Cerințele dvs. vor fi importate în fundal. După terminare, veți primi un e-mail de confirmare."
-msgid "Your response has been recorded."
-msgstr "Răspunsul dvs. a fost înregistrat."
-
msgid "Your search didn't match any commits."
msgstr "Căutarea dvs. nu a găsit niciun commit."
@@ -45205,17 +45745,14 @@ msgstr[0] "În abonamentul dvs. a rămas %{remaining_seat_count} din %{total_sea
msgstr[1] "În abonamentul dvs. a(u) rămas %{remaining_seat_count} din %{total_seat_count} seat-uri."
msgstr[2] "În abonamentul dvs. a(u) rămas %{remaining_seat_count} din %{total_seat_count} de seat-uri."
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] "Abonamentul dvs. va expira în %{remaining_days} zi."
-msgstr[1] "Abonamentul dvs. va expira în %{remaining_days} zile."
-msgstr[2] "Abonamentul dvs. va expira în %{remaining_days} de zile."
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "Abonamentul dvs. va expira la %{expires_on}"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
-msgstr ""
+msgstr "Actualizarea a eșuat. Puteți încărca doar un singur element de design atunci când îl adăugați la un design existent."
msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
-msgstr ""
+msgstr "Actualizarea a eșuat. Trebuie să încărcați un fișier cu același nume atunci când îl adăugați la un proiect existent."
msgid "Your username is %{username}."
msgstr "Numele dvs. de utilizator este %{username}."
@@ -45364,6 +45901,9 @@ msgstr "artefacte"
msgid "assign yourself"
msgstr "atribuiți-vă singur"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr "părintele asociat este confidențial și nu poate avea copii neconfidențiali."
+
msgid "at"
msgstr "la"
@@ -45445,6 +45985,9 @@ msgstr "nu poate include: %{invalid_storages}"
msgid "can't reference a branch that does not exist"
msgstr "nu poate face referire la o ramură care nu există"
+msgid "cannot assign a non-confidential work item to a confidential parent. Make the work item confidential and try again."
+msgstr "nu se poate atribui un element de lucru neconfidențial unui părinte confidențial. Faceți elementul de lucru confidențial și încercați din nou."
+
msgid "cannot be a date in the past"
msgstr "nu poate fi o dată în trecut"
@@ -45547,9 +46090,15 @@ msgstr "%{reportType}: Încărcarea a avut ca rezultat o eroare"
msgid "ciReport|%{sameNum} same"
msgstr "%{sameNum} la fel"
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
+msgstr "%{scanner} a detectat altă/alte %{boldStart}%{number}%{boldEnd} (de) nouă/noi potențială/potențiale %{vulnStr}"
+
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
msgstr "%{scanner} a detectat %{strong_start}%{number}%{strong_end} potențiale noi %{vulnStr}"
+msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
+msgstr "%{scanner} nu a detectat nicio %{boldStart}nouă%{boldEnd} vulnerabilitate potențială"
+
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
msgstr "%{scanner} nu a detectat %{strong_start}noi%{strong_end} %{vulnStr}"
@@ -45565,6 +46114,9 @@ msgstr "Fuzzing de API"
msgid "ciReport|All clusters"
msgstr "Toate clusterele"
+msgid "ciReport|All images"
+msgstr "Toate imaginile"
+
msgid "ciReport|All projects"
msgstr "Toate proiectele"
@@ -45838,6 +46390,9 @@ msgstr "se încarcă"
msgid "ciReport|is loading, errors when loading results"
msgstr "se încarcă, erori la încărcarea rezultatelor"
+msgid "ci_database"
+msgstr "ci_database"
+
msgid "closed"
msgstr "închis"
@@ -45865,6 +46420,9 @@ msgstr "comis"
msgid "compliance violation has already been recorded"
msgstr "încălcarea conformității a fost deja înregistrată"
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr "părintele confidențial nu poate fi utilizat în cazul în care există copii neconfidențiali."
+
msgid "contacts can only be added to root groups"
msgstr "contactele pot fi adăugate numai la grupurile rădăcină"
@@ -45904,9 +46462,6 @@ msgstr "creat(ă) de"
msgid "data"
msgstr "date"
-msgid "database"
-msgstr "baza de date"
-
msgid "date must not be after 9999-12-31"
msgstr "data nu trebuie să fie după 9999-12-31"
@@ -46003,6 +46558,9 @@ msgstr "%{slash_command} suprascrie timpul total estimat."
msgid "example.com"
msgstr "example.com"
+msgid "exceeds maximum length (100 usernames)"
+msgstr "depășește lungimea maximă (100 de nume de utilizatori)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr "depășește limita de %{max_value_length} caractere"
@@ -46087,9 +46645,6 @@ msgstr "tokenuri de acces de grup"
msgid "group members"
msgstr "membrii grupului"
-msgid "group's CI/CD settings."
-msgstr "setările CI/CD ale grupului."
-
msgid "groups"
msgstr "grupuri"
@@ -46141,6 +46696,9 @@ msgstr "https://serverul-tău-bitbucket"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr "%{language} (%{percent_translated}%% tradus)"
+msgid "if"
+msgstr "dacă"
+
msgid "image diff"
msgstr "diff imagine"
@@ -46318,6 +46876,9 @@ msgstr "încărcare"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "blocat(ă) de %{path_lock_user_name} la %{created_at}"
+msgid "main_database"
+msgstr "main_database"
+
msgid "manual"
msgstr "manual"
@@ -46363,12 +46924,6 @@ msgstr "%{commitCount} se va / vor adăuga la %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 commit de îmbinare"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr "Adaugă %{commitCount} și %{mergeCommitCount} la %{targetBranch}%{squashedCommits}."
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr "Adaugă %{commitCount} la %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr "Modificări îmbinate în %{targetBranch} cu %{mergeCommitSha}%{squashedCommits}."
@@ -46486,9 +47041,6 @@ msgstr "Creați o problemă pentru a rezolva toate subiectele"
msgid "mrWidget|Delete source branch"
msgstr "Ștergeți ramura sursă"
-msgid "mrWidget|Deletes the source branch"
-msgstr "Șterge ramura sursă"
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Statisticile de implementare nu sunt disponibile în prezent"
@@ -46498,9 +47050,6 @@ msgstr "Nu a închis"
msgid "mrWidget|Dismiss"
msgstr "Respingeți"
-msgid "mrWidget|Does not delete the source branch"
-msgstr "Nu șterge ramura sursă"
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Încărcarea statisticilor de implementare a eșuat"
@@ -46537,9 +47086,6 @@ msgstr[0] "Problemă menționată"
msgstr[1] "Probleme menționate"
msgstr[2] "Probleme menționate"
-msgid "mrWidget|Merge"
-msgstr "ÃŽmbinare"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr "Îmbinare blocată: toate aprobările necesare trebuie să fie acordate."
@@ -46573,9 +47119,6 @@ msgstr "Îmbinare indisponibilă: merge request-urile sunt numai în citire pe p
msgid "mrWidget|Merged by"
msgstr "ÃŽmbinat de"
-msgid "mrWidget|Merges changes into"
-msgstr "Îmbină modificările în"
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "Îmbinare în curs! Modificările sunt în curs de expediere..."
@@ -46660,21 +47203,9 @@ msgstr "Afișați detalii despre %{widget}"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr "Ramura %{type} %{codeStart}%{name}%{codeEnd} nu există."
-msgid "mrWidget|The changes were merged into"
-msgstr "Schimbările au fost îmbinate în"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Schimbările nu au fost îmbinate în"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Ramura sursă a fost ștearsă"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "Ramura sursă este cu %{link} ramurii țintă"
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Ramura sursă este în curs de ștergere"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Acest merge request nu a reușit să fie îmbinat automat"
@@ -46808,10 +47339,10 @@ msgid "on track"
msgstr "conform planului"
msgid "only %{parent_types} can be parent of Task."
-msgstr ""
+msgstr "numai %{parent_types} poate fi părintele Sarcinii."
msgid "only Task can be assigned as a child in hierarchy."
-msgstr ""
+msgstr "numai Sarcina poate fi atribuită ca un copil în ierarhie."
msgid "only available on top-level groups."
msgstr "disponibil(ă) numai pentru grupurile de nivel superior."
@@ -46847,10 +47378,10 @@ msgstr[1] "părinți"
msgstr[2] "de părinții"
msgid "parent already has maximum number of children."
-msgstr ""
+msgstr "părintele are deja numărul maxim de copii."
msgid "parent must be in the same project as child."
-msgstr ""
+msgstr "părintele trebuie să fie în același proiect ca și copilul."
msgid "password"
msgstr "parola"
@@ -46996,6 +47527,9 @@ msgstr "repozitorii"
msgid "repository:"
msgstr "repozitoriu:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr "nivelul de acces de bază al rolului nu corespunde nivelului de acces al calității de membru"
+
msgid "satisfied"
msgstr "satisfăcut"
@@ -47008,6 +47542,9 @@ msgstr "scan-execution-policy: politica nu s-a aplicat, fișierul %{policy_path}
msgid "security Reports|There was an error creating the merge request"
msgstr "A apărut o eroare la crearea merge request-ului"
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr "selective_code_owner_removals poate fi activat numai atunci când retain_approvals_on_push este activat"
+
msgid "severity|Blocker"
msgstr "Blocantă"
@@ -47119,14 +47656,14 @@ msgstr "stările terraform"
msgid "the correct format."
msgstr "formatul corect."
-msgid "the following epic(s)"
-msgstr "următoarea / următoarele epică(e)"
+msgid "the following epics"
+msgstr "următoarele epice"
-msgid "the following incident(s) or issue(s)"
-msgstr "următorul (următoarele) incident(e) sau problemă(e)"
+msgid "the following incidents or issues"
+msgstr "următoarele incidente sau probleme"
-msgid "the following issue(s)"
-msgstr "următoarea / următoarele problemă(e)"
+msgid "the following issues"
+msgstr "următoarele probleme"
msgid "the wiki"
msgstr "wiki"
@@ -47146,6 +47683,9 @@ msgstr "astăzi"
msgid "toggle collapse"
msgstr "comutare restrângere"
+msgid "total must be less than or equal to %{size}"
+msgstr "totalul trebuie să fie mai mic sau egal cu %{size}"
+
msgid "triggered"
msgstr "declanșat"
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index a85c992d7a2..9c4b2b468a7 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -610,6 +610,9 @@ msgstr "%{actionText} и переоткрыть %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} — недопуÑтимый диапазон IP-адреÑов"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} клонировал %{original_issue} в %{new_issue}."
@@ -664,12 +667,12 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} из %{count} задачи выполнено"
-msgstr[1] "%{completedCount} из %{count} задач выполнено"
-msgstr[2] "%{completedCount} из %{count} задач выполнено"
-msgstr[3] "%{completedCount} из %{count} задач выполнено"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "Завершено %{completedWeight} из %{totalWeight} приоритета"
@@ -859,6 +862,9 @@ msgstr "%{integrations_link_start}Интеграции%{link_end} позволÑ
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} будет удален! Вы уверены?"
+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 ""
@@ -910,6 +916,9 @@ msgstr "%{labelStart}Метод:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}ПроÑтранÑтво имён:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Сканер:%{labelEnd} %{scanner}"
@@ -922,15 +931,15 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Ðемодифицированный ответ:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупно"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -1046,6 +1055,18 @@ msgstr "%{openedEpics} открыто, %{closedEpics} закрыто"
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 ""
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1478,7 +1510,7 @@ msgid "+%{more_reviewers_count}"
msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
-msgstr ""
+msgstr "+%{more_reviewers_count} проверÑющих"
msgid "+%{tags} more"
msgstr "+ещё %{tags}"
@@ -1749,15 +1781,9 @@ msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "2FADevice|Registered On"
msgstr "ЗарегиÑтрированы"
-msgid "3 days"
-msgstr "3 днÑ"
-
msgid "3 hours"
msgstr "3 чаÑа"
-msgid "30 days"
-msgstr "30 дней"
-
msgid "30 minutes"
msgstr "30 минут"
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 дней"
-
msgid "8 hours"
msgstr "8 чаÑов"
@@ -2364,6 +2387,9 @@ msgstr "Добавить УÑÐ»Ð¾Ð²Ð¸Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ Полит
msgid "Add a bullet list"
msgstr "Добавить маркированный ÑпиÑок"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Добавить Ñворачиваемую Ñекцию"
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr "Добавить таблицу"
-msgid "Add a task list"
-msgstr "Добавить ÑпиÑок задач"
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr "Добавить правило утверждениÑ"
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Добавить широковещательное Ñообщение"
@@ -2481,6 +2501,9 @@ 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 "Добавить заголовок и подвал в Ñлектронные пиÑьма. ПожалуйÑта, обратите внимание, что наÑтройки цвета будут применены только в интерфейÑе приложениÑ"
@@ -4005,6 +4028,9 @@ msgstr "Ð’Ñе ветви"
msgid "All changes are committed"
msgstr "Ð’Ñе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð·Ð°Ñ„Ð¸ÐºÑированы"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "Ð’Ñе адреÑа Ñлектронной почты будут иÑпользоватьÑÑ Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ ваших коммитов."
@@ -4296,9 +4322,6 @@ msgstr "Произошла ошибка при получении предпро
msgid "An error occurred while fetching ancestors"
msgstr "Произошла ошибка при получении предков"
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr "Произошла ошибка при получении веток. Повторите поиÑк."
@@ -4344,6 +4367,9 @@ 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 "Произошла ошибка при получении тегов. Повторите поиÑк."
@@ -4431,9 +4457,6 @@ msgstr "Произошла ошибка при загрузке вкладки \
msgid "An error occurred while loading the Test Reports tab."
msgstr "Произошла ошибка при загрузке вкладки \"Отчеты по теÑтам\"."
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Произошла ошибка при загрузке формы токенов доÑтупа. ПожалуйÑта, повторите попытку."
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr "Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr "Утверждено"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Утверждающий"
@@ -5419,7 +5469,7 @@ msgid "Assigned %{assignee_users_sentence}."
msgstr "Ðазначены %{assignee_users_sentence}."
msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "%{reviewer_users_sentence} назначен(Ñ‹) в качеÑтве %{reviewer_text}."
msgid "Assigned Issues"
msgstr "Ðазначенные обÑуждениÑ"
@@ -5442,9 +5492,6 @@ msgstr "Ðазначить мне"
msgid "Assigned to you"
msgstr "Ðазначено вам"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "ОтветÑтвенный"
@@ -5468,7 +5515,7 @@ msgid "Assigns %{assignee_users_sentence}."
msgstr "Ðазначение %{assignee_users_sentence}."
msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "Ðазначает %{reviewer_users_sentence} в качеÑтве %{reviewer_text}."
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr ""
@@ -5488,8 +5535,8 @@ msgstr ""
msgid "At risk"
msgstr "Под угрозой"
-msgid "Attach a file"
-msgstr "Прикрепить файл"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr "Прикрепление файла - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] "Прикрепить %d файлов"
msgid "Attaching the file failed."
msgstr "Ðе удалоÑÑŒ прикрепить файл."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Ðудит Ñобытий"
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "Ðвг."
@@ -5843,8 +5911,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Разрешено автоматичеÑки"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "ÐвтоматичеÑки обновлÑÑ‚ÑŒ ветки и теги Ñтого проекта из иÑходного Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ ÐºÐ°Ð¶Ð´Ñ‹Ð¹ чаÑ."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Заметка"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr "Приглашение в группу"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 "УчаÑтники, приглашённые Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ группового приглашениÑ, не могут быть удалены. Ð’Ñ‹ можете либо удалить вÑÑŽ группу, либо попроÑить владельца приглашённой группы удалить учаÑтника."
@@ -6503,6 +6578,9 @@ msgstr "Приглашение в проект"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Удалить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %{username} из вашей подпиÑки"
+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 "Переключить подробноÑти о меÑтах"
@@ -6518,13 +6596,10 @@ msgstr ""
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{username} из вашей подпиÑки. ЕÑли вы продолжите, пользователь будет удалён из группы %{namespace} и вÑех её подгрупп и проектов. ДейÑтвие не может быть отменено."
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr "Ветка не загружена - %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Ветки"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Ðктивные"
@@ -7476,9 +7593,6 @@ msgstr "Ðевозможно найти HEAD-коммит Ñтой ветки"
msgid "Can't find variable: ZiteReader"
msgstr "Ðе удаётÑÑ Ð½Ð°Ð¹Ñ‚Ð¸ переменную: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr "Ðе удалоÑÑŒ загрузить Mermaid-модуль: %{err}"
-
msgid "Can't scan the code?"
msgstr "Ðе удаетÑÑ Ð¾Ñ‚Ñканировать QR-код?"
@@ -8171,9 +8285,6 @@ msgstr "Дочерней цели не ÑущеÑтвует."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -9428,7 +9554,7 @@ msgid "Code Quality"
msgstr "КачеÑтво кода"
msgid "Code Review"
-msgstr ""
+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 "Ðналитика Ð ÐµÑ†ÐµÐ½Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÑ‚ ÑпиÑок открытых запроÑов на ÑлиÑние, которые находÑÑ‚ÑÑ Ð½Ð° Ñтадии проверки кода. Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ проекта и/или фильтров отÑутÑтвуют рецензируемые запроÑÑ‹ на ÑлиÑние."
@@ -10511,9 +10637,6 @@ msgstr "Ð’Ñ‹ можете добавить образ в Ñтот рееÑÑ‚Ñ€ Ð
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr "Содержание"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr "Создать %{type}"
msgid "Create %{workspace} label"
msgstr "Создать метку %{workspace}"
-msgid "Create Google Cloud project"
-msgstr "Создать проект Google Cloud"
-
msgid "Create New Directory"
msgstr "Создать Ðовый каталог"
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr "Удалить файл"
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr "Удалить проект"
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr "Удалить Ñтроку"
@@ -12688,6 +12844,15 @@ msgstr ""
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "Ðе получилоÑÑŒ удалить репозиторий wiki. Попробуйте ещё раз или ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором."
+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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr "УдалÑет иÑходную ветку"
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr "Идет удаление"
@@ -12934,6 +13096,9 @@ msgstr[1] "РазвертываниÑ"
msgstr[2] "Развертываний"
msgstr[3] "РазвертываниÑ"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Ключи развёртываниÑ"
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Домен"
@@ -14413,9 +14575,6 @@ msgstr "ПуÑто. Выберите проÑтранÑтва имен Ð´Ð»Ñ Ð¸
msgid "Elastic|None. Select projects to index."
msgstr "ПуÑто. Выберите проекты Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑации."
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð°"
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñ€ÐµÐ½Ð´ÐµÑ€Ð¸Ð½Ð³Ð°: %{err}"
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr "Ошибка при удалении проекта. Проверьте журналы Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей об ошибке."
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ðе удалоÑÑŒ удалить раÑпиÑание Ñборочной линии"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ msgstr "Ðе удалоÑÑŒ Ñохранить наÑтройки (%{error_messa
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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr "Фев."
msgid "February"
msgstr "Февраль"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr "От ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð´Ð¾ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ñ€ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ в рабочей Ñреде"
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr "Ð’ процеÑÑе"
-msgid "Geo|In sync"
-msgstr "Синхронизировано"
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Ðе Ñинхронизировано"
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "ÐеизвеÑтное ÑоÑтоÑние"
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr "Коммит GitLab"
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 "Ваши Ñтраницы обÑлуживаютÑÑ Ð¿Ð¾Ð´:"
@@ -18292,16 +18475,13 @@ msgstr "Перейти к Ñвоим Ñниппетам"
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr "Содержание обзора группы"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ñ‹ была обновлена ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого DevOps"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr "РуководÑтво"
@@ -19243,7 +19426,7 @@ msgstr "HTTP Basic: доÑтуп запрещен\\nÐ’Ñ‹ должны иÑпол
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "ИÑториÑ"
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 "Чтобы назначить обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¼Ñƒ учаÑтнику команды, нужен проект Ð´Ð»Ñ Ñтих обÑуждений. %{linkStart}Создайте проект.%{linkEnd}"
-msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "Вы приглашаете группу в группу %{strongStart}%{name}%{strongEnd}."
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr "ИтерациÑ"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Ð˜Ñ‚ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð° на"
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "Прокрутить вниз"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Прокрутить вверх"
@@ -22972,8 +23161,8 @@ msgstr "Ключ"
msgid "Key (PEM)"
msgstr "Ключ (PEM)"
-msgid "Key: %{key}"
-msgstr "Ключ: %{key}"
+msgid "Key:"
+msgstr ""
msgid "Keyboard shortcuts"
msgstr "Ð¡Ð¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
@@ -23244,15 +23433,9 @@ msgstr "IP поÑледнего входа:"
msgid "Last sign-in at:"
msgstr "ПоÑледний вход:"
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr "ПоÑледнее уÑпешное обновление"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr "ПривÑзанные адреÑа Ñлектронной почты (%
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 "СÑылки"
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr "Ðужна помощь?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr "Ðет цели"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "Методы аутентификации не наÑтроены."
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ msgstr "OmniAuth"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr "По плану"
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 "ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ предоÑтавлÑет Ñводку оперативного ÑоÑтоÑÐ½Ð¸Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ проекта, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ ÑтатуÑÑ‹ Ñборочной линии и предупреждений."
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr "Удалить верÑию пакета"
msgid "PackageRegistry|Delete package"
msgstr "Удалить пакет"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr "Узнайте, как %{noPackagesLinkStart}публиковать и Ð
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr "Опубликовано вручную"
@@ -28068,9 +28316,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "Команда NuGet"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr "РееÑÑ‚Ñ€ пакетов"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Команда pip"
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 "Вам также может понадобитьÑÑ Ð½Ð°Ñтроить аутентификацию Ñ Ð¸Ñпользованием токена. %{linkStart}Смотрите документацию%{linkEnd}, чтобы узнать больше."
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
msgid "PackageRegistry|npm"
msgstr ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "ВыполнÑйте обычные дейÑÑ‚Ð²Ð¸Ñ Ð½Ð°Ð´ проектом GitLab"
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти"
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr "ПредоÑтавьте краткое опиÑание Ñтой Ñборочной линии"
@@ -28795,6 +29104,9 @@ msgstr "Цель"
msgid "PipelineSchedules|Variables"
msgstr "Переменные"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr "Редактор Ñборочных линий"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr "КÑш проекта уÑпешно очищен."
@@ -29209,9 +29524,18 @@ msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ Ð¾Ñ‚ÑоединившегоÑÑ Ð·Ð°Ð¿Ñ€Ð
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr "Ðазвание тега"
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr "Переменные"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "ПожалуйÑта, проверьте почту (%{email}), чтобы подтвердить, что вы владеете Ñтим адреÑом и открыть Ð´Ð»Ñ ÑÐµÐ±Ñ Ñилу CI/CD. Ðе получили пиÑьмо? %{resend_link}. Ðеверный Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ñ‡Ñ‚Ñ‹? %{update_link}."
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr "ПожалуйÑта, заполните Ð°Ð´Ñ€ÐµÑ Ñлектронной почты в Ñвоем профиле"
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr "Пред."
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ msgstr "URL проекта"
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 "При перемещении в группу уровень доÑтупа проекта будет изменен в ÑоответÑтвии Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°Ð¼Ð¸ Ñтой группы."
@@ -30481,6 +30835,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Проект: %{name}"
+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 "ПодпиÑатьÑÑ"
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 "или группа"
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} будет доÑтупно Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ°Ð¼Ð¸. Ð’Ñ‹ уверены?"
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 "Защитить"
@@ -31924,6 +32311,12 @@ 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 "ПриобреÑти больше минут"
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr "Коды воÑÑтановлениÑ"
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] "Релиза"
msgstr[2] "Релизов"
msgstr[3] "Релизов"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "Удалить ответÑтвенного"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Удалить аватар"
@@ -32706,12 +33093,6 @@ msgstr "Ð’Ñе метки удалены."
msgid "Removed an issue from an epic."
msgstr "ОбÑуждение удалено из цели."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr "УдалÑет вÑе метки."
msgid "Removes an issue from an epic."
msgstr "УдалÑет обÑуждение из цели."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "УдалÑет родительÑкую цель %{epic_ref}."
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "ПожаловатьÑÑ"
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Запрошено %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "Повторно отправить подтверждение по Ñлектронной почте"
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr "Повторить"
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33572,7 +33941,7 @@ msgid "Review changes"
msgstr ""
msgid "Review requests for you"
-msgstr "ЗапроÑÑ‹ рецензий Ð´Ð»Ñ Ð²Ð°Ñ"
+msgstr "С запроÑом провеÑти ревью"
msgid "Review the changes locally."
msgstr ""
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr "Удаление"
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr "Ð’Ñ‹ иÑпользовали %{quotaUsed} из %{quotaLimit} ваших
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "ВыполнÑетÑÑ"
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "Ключ SSH"
@@ -34261,6 +34664,9 @@ msgstr "Ключи SSH"
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 "Отпечатки ключа SSH хоÑта"
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] "Результата Wiki"
msgstr[2] "Результатов Wiki"
msgstr[3] "Результат Wiki"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr "Панель безопаÑноÑти"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Панель безопаÑноÑти"
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "Выбранные уровни не могут иÑпользоватьÑÑ Ð½Ðµ админиÑтраторами Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿, проектов или примеров кода. ЕÑли публичный уровень ограничен, профили пользователей видны только авторизованным пользователÑм."
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "УÑтановите пароль в Ñвоем аккаунте, чтобы отправлÑÑ‚ÑŒ или получать код через %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr "Показана поÑледнÑÑ Ð²ÐµÑ€ÑиÑ"
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr "КоличеÑтво входов:"
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr "ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð°"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "УÑпешно активировано"
@@ -38256,9 +38695,6 @@ msgstr "Поддержка пользовательÑких Ñертификат
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr "СиÑтемные метрики (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr "Отмена"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Создать тег"
@@ -38451,8 +38893,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Редактировать заметки к релизу"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Ð˜Ð¼Ñ ÑущеÑтвующей ветки, тега или SHA коммита"
@@ -38550,9 +38992,6 @@ msgstr "ID задачи: %{elastic_task}"
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "СпаÑибо за ваш отчет. ÐдминиÑтратор GitLab Ñкоро раÑÑмотрит его."
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr "Ðет архивных требований"
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑке уже еÑÑ‚ÑŒ репозиторий Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем"
@@ -39720,9 +40162,6 @@ msgstr "Произошла ошибка при отправке пиÑьма Ñ
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Произошла ошибка при удалении Ñлектронной почты."
-msgid "There was an error resetting group pipeline minutes."
-msgstr "Произошла ошибка при ÑброÑе минут Ñборочной линии группы."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "Произошла ошибка при ÑброÑе минут пользовательÑкой Ñборочной линии."
@@ -39855,9 +40291,6 @@ msgstr "Произошла ошибка при получении данных Ð
msgid "There was an error while fetching value stream analytics duration data."
msgstr "Произошла ошибка при получении аналитичеÑких данных о длительноÑти потока ценноÑти."
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Этот репозиторий"
@@ -40707,6 +41149,9 @@ 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 "Таймаут"
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Чтобы добавить запиÑÑŒ вручную, предоÑтавьте Ñледующую информацию в приложении на Ñвоем телефоне."
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr "Чтобы поддержать проект, Ñоздайте запрÐ
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr "Тип"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "УÑтройÑтва U2F (%{length})"
@@ -41615,6 +42066,9 @@ msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ отличиÑ. %{button_try_agai
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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr "ÐеизвеÑтный формат"
msgid "Unknown response text"
msgstr "ÐеизвеÑтный текÑÑ‚ ответа"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr "Загрузите закрытый ключ Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Ñертификата"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Загрузить файл"
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr "ГолоÑа \"за\""
@@ -42035,10 +42486,10 @@ msgstr "Текущий период иÑпользованиÑ"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr "ИÑпользуйте вашу Ñмарт-карту Ð´Ð»Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "Пользователь уÑпешно изменен."
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "Вклад в проекты"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "Изменить профиль"
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Показать вÑе"
@@ -42854,13 +43336,6 @@ msgstr "У Ð½Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr "%{stageCount}+ Ñлементов"
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr "Когда:"
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Ð’Ñ‹ можете приглаÑить нового учаÑтника в %{project_name} или приглаÑить другую группу."
@@ -44682,9 +45234,6 @@ msgstr "Ð’Ñ‹ можете приглаÑить нового учаÑтника Ð
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ msgstr "Ð’Ñ‹ можете протеÑтировать Ñвой файл .gitlab
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr "У Ð²Ð°Ñ Ð¿Ð¾ÐºÐ° нет подпиÑок"
@@ -45130,6 +45674,9 @@ 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 "Ð’Ñ‹ уже включили двухфакторную аутентификацию Ñ Ð¸Ñпользованием аутентификаторов Ñ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ñ‹Ð¼ паролем. Чтобы зарегиÑтрировать другое уÑтройÑтво, Ñначала необходимо отключить двухфакторную аутентификацию."
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr "Ваши группы"
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr "По вашему запроÑу не найдено ни одного коммита."
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr "назначить ÑебÑ"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Ð’Ñе проекты"
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr "закрыто"
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr "данные"
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr "учаÑтники группы"
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "группы"
@@ -46406,6 +46975,9 @@ msgstr "https://ваш-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ð°"
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr "ручной"
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коммит cлиÑниÑ"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Ðа данный момент ÑтатиÑтика Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупна"
@@ -46767,9 +47333,6 @@ msgstr "Ðе закрыт"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Ðе удалоÑÑŒ загрузить ÑтатиÑтику развёртываниÑ"
@@ -46807,9 +47370,6 @@ msgstr[1] "Упоминает обÑуждениÑ"
msgstr[2] "Упоминает обÑуждениÑ"
msgstr[3] "Упоминает обÑуждениÑ"
-msgid "mrWidget|Merge"
-msgstr "Слить"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ Ñлиты в"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ были Ñлиты в"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° удалÑетÑÑ"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Этот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние не может быть выполнен автоматичеÑки"
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr "репозиторий:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,14 +47945,14 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
-msgstr "Ñледующее(ие) обÑуждение(Ñ)"
+msgid "the following issues"
+msgstr ""
msgid "the wiki"
msgstr ""
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "Ñвернуть/развернуть"
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "запущено"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index ed815ec5ebd..7e227eee335 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:08\n"
msgid " %{start} to %{end}"
msgstr " %{start} සිට %{end}"
@@ -210,8 +210,8 @@ msgstr[1] ""
msgid "%d contribution"
msgid_plural "%d contributions"
-msgstr[0] "දà·à¶ºà¶šà¶­à·Šà·€ %d"
-msgstr[1] "දà·à¶ºà¶šà¶­à·Šà·€ %d"
+msgstr[0] "දà·à¶ºà¶šà¶­à·Šâ€à·€ %d"
+msgstr[1] "දà·à¶ºà¶šà¶­à·Šâ€à·€ %d"
msgid "%d day"
msgid_plural "%d days"
@@ -380,8 +380,8 @@ msgstr[1] "තත්පර %d"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "අදියර %d"
+msgstr[1] "අදියර %d"
msgid "%d star"
msgid_plural "%d stars"
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -716,13 +722,13 @@ msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr ""
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}බිඳවà·à¶§à·“මේ ලිපිනය:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
msgstr ""
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}බිඳ à·€à·à¶§à·“මේ තත්â€à·€à¶º:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
msgstr ""
@@ -742,29 +748,32 @@ msgstr "%{labelStart}ක්â€à¶»à¶¸à¶º:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
-msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
msgstr ""
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr "%{labelStart}සුපිරික්සනය:%{labelEnd} %{scanner}"
+
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
msgstr ""
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}තීව්â€à¶»à¶­à·à·€:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}මෙවලම:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}අසංà·à·à¶°à·’ත ප්â€à¶»à¶­à·’චà·à¶»à¶º:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
-msgstr ""
-
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
+msgstr "%{label_for_message} නොතිබේ"
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "පà·à¶º 1 කට %{lessThan} "
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}ලෙට්'ස් එන්ක්â€à¶»à·’ප්ට්%{lets_encrypt_link_end} යනු අඩවි සඳහ෠HTTPS (SSL/TLS) ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š කිරීමට සංඛ්â€à¶ºà·à¶‚ක සහතික නිකුත් කරන නොමිලේ, ස්වයංක්â€à¶»à·“ය සහ විවෘත සහතික අධිකà·à¶»à·’යකි (CA)."
@@ -782,7 +791,7 @@ msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent
msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more"
-msgstr ""
+msgstr "%{listToShow}, සහ තවත් %{awardsListLength}"
msgid "%{location} is missing required keys: %{keys}"
msgstr ""
@@ -791,13 +800,13 @@ msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
-msgstr ""
+msgstr "%{mergeLength}/%{usersLength} සංයුක්ත කළ à·„à·à¶šà·’ය"
msgid "%{message} showing first %{warnings_displayed}"
msgstr ""
msgid "%{message}. Your attention request was removed."
-msgstr ""
+msgstr "%{message}. ඔබගේ අවධà·à¶±à¶º ඉල්ලීම ඉවත් කෙරිණි."
msgid "%{milestone} (expired)"
msgstr "%{milestone} (ඉකුත්ය)"
@@ -812,7 +821,7 @@ msgid "%{model_name} not found"
msgstr "%{model_name} හමු නොවිණි"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+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 ""
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr "භà·à·€à·’තය %{percentageUsed}%%"
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1091,10 +1119,10 @@ msgid "%{total} remaining issue weight"
msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
-msgstr ""
+msgstr "අවවà·à¶¯ %{total} ක් හමු විය: පළමු %{warningsDisplayed} පෙන්වයි"
msgid "%{type} only supports %{name} name"
-msgstr ""
+msgstr "%{name} නමකට පමණක් %{type} සහà·à¶º දක්වයි"
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (සංයුක්ත කළ නොහà·à¶šà·’ය)"
@@ -1204,7 +1232,7 @@ msgid "(+%{count}&nbsp;rules)"
msgstr "(නීති&nbsp;+%{count})"
msgid "(Group Managed Account)"
-msgstr ""
+msgstr "(à·ƒà·à¶¸à·–හික කළමනà·à¶šà¶»à¶« ගිණුම)"
msgid "(No changes)"
msgstr "(වෙනස්කම් නà·à¶­)"
@@ -1222,7 +1250,7 @@ msgid "(expired)"
msgstr "(කල් ඉකුත්ය)"
msgid "(leave blank if you don't want to change it)"
-msgstr ""
+msgstr "(වෙනස් නොකළ යුතු නම් හිස්ව තබන්න)"
msgid "(max size 15 MB)"
msgstr "(උ. ප්â€à¶»à¶¸à·à¶«à¶º මෙ.බ. 15)"
@@ -1234,7 +1262,7 @@ msgid "(removed)"
msgstr "(ඉවතල෠ඇත)"
msgid "(revoked)"
-msgstr ""
+msgstr "(අහà·à·ƒà·’යි)"
msgid "(squashes %d commit)"
msgid_plural "(squashes %d commits)"
@@ -1245,7 +1273,7 @@ msgid "(this user)"
msgstr "(මෙම පරිà·à·“ලකයà·)"
msgid "(we need your current password to confirm your changes)"
-msgstr ""
+msgstr "(ඔබගේ වෙනස්කම් තහවුරුවට අපට වත්මන් මුරපදය අවà·à·Šâ€à¶ºà¶ºà·’)"
msgid "* All times are in UTC unless specified"
msgstr ""
@@ -1295,7 +1323,7 @@ msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status
msgstr ""
msgid "- Add or remove a user."
-msgstr ""
+msgstr "- පුද්ගලයෙක් එක් හ෠ඉවතලන්න."
msgid "- Available to run jobs."
msgstr ""
@@ -1476,10 +1504,10 @@ msgstr[0] "අවුරුදු 1 ක් තිබේ"
msgstr[1] "අවුරුදු %d ක් තිබේ"
msgid "1-9 contributions"
-msgstr "දà·à¶ºà¶šà¶­à·Šà·€ 1-9"
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€ 1-9"
msgid "10-19 contributions"
-msgstr "දà·à¶ºà¶šà¶­à·Šà·€ 10-19"
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€ 10-19"
msgid "1000+"
msgstr "1000+"
@@ -1488,10 +1516,10 @@ msgid "192.168.0.0/24 or 2001:0DB8:1234::/48"
msgstr "192.168.0.0/24 à·„à· 2001:0DB8:1234::/48"
msgid "1st contribution!"
-msgstr "පළමු දà·à¶ºà¶šà¶­à·Šà·€à¶º!"
+msgstr "පළමු දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º!"
msgid "20-29 contributions"
-msgstr "දà·à¶ºà¶šà¶­à·Šà·€ 20-29"
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€ 20-29"
msgid "2FA"
msgstr "2FA"
@@ -1499,44 +1527,35 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "දවස් 3"
-
msgid "3 hours"
msgstr "පà·à¶º 3"
-msgid "30 days"
-msgstr "දවස් 30"
-
msgid "30 minutes"
msgstr "විනà·à¶©à·’ 30"
msgid "30+ contributions"
-msgstr "දà·à¶ºà¶šà¶­à·Šà·€ 30+"
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€ 30+"
msgid "403|Please contact your GitLab administrator to get permission."
-msgstr ""
+msgstr "අවසර ලබ෠ගà·à¶±à·“මට ඔබගේ ගිට්ලà·à¶¶à·Š පරිපà·à¶½à¶š අමතන්න."
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "මෙම පිටුවට ප්â€à¶»à·€à·šà· වීමට ඔබට අවසර නà·à¶­."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "ලිපිනය නිවà·à¶»à¶¯à·’ බවත් පිටුව ගෙනගොස් නà·à¶­à·’ බවත් සහතික කර ගන්න."
msgid "404|Page Not Found"
msgstr "පිටුව හමු නොවිණි"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "මෙය අත්වà·à¶»à¶¯à·“මක් යà·à¶ºà·’ සිතන්නේ නම් ඔබගේ ගිට්ලà·à¶¶à·Š පරිපà·à¶½à¶š අමතන්න."
msgid "409|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "මෙය අත්වà·à¶»à¶¯à·“මක් යà·à¶ºà·’ සිතන්නේ නම් ඔබගේ ගිට්ලà·à¶¶à·Š පරිපà·à¶½à¶š අමතන්න."
msgid "409|There was a conflict with your request."
-msgstr ""
-
-msgid "7 days"
-msgstr "දවස් 7"
+msgstr "ඔබගේ ඉල්ලීම සමඟ à¶à¶§à·Šà¶§à¶±à¶ºà¶šà·Š ඇත."
msgid "8 hours"
msgstr "පà·à¶º 8"
@@ -1584,7 +1603,7 @@ msgid "A complete DevOps platform"
msgstr ""
msgid "A default branch cannot be chosen for an empty project."
-msgstr ""
+msgstr "හිස් ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් සඳහ෠පෙරනිමි à·à·à¶›à·à·€à¶šà·Š තේරීමට නොහà·à¶šà·’ය."
msgid "A deleted user"
msgstr "මකà·à¶¯à·à¶¸à·– පරිà·à·“ලකයෙකි"
@@ -1737,7 +1756,7 @@ msgid "APIFuzzing|Customize your project's API fuzzing configuration options and
msgstr ""
msgid "APIFuzzing|Enable authentication"
-msgstr ""
+msgstr "සත්â€à¶ºà·à¶´à¶±à¶º සබල කරන්න"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
msgstr ""
@@ -2106,7 +2125,7 @@ msgid "Add a GPG key"
msgstr "GPG යතුරක් යොදන්න"
msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š වෙත ආරක්â€à·‚ිතව ප්â€à¶»à·€à·šà·à¶º සඳහ෠ජීපීජී යතුරක් යොදන්න. %{help_link_start}තව දà·à¶±à¶œà¶±à·Šà¶±.%{help_link_end}"
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "වගුවක් එකතු කරන්න"
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr "සිරà·à·ƒà·’යක් එක්කරන්න…"
@@ -2178,13 +2197,10 @@ msgid "Add another link"
msgstr "තව සබà·à¶³à·’යක් යොදන්න"
msgid "Add approval rule"
-msgstr ""
+msgstr "අනුමත රීතියක් යොදන්න"
msgid "Add approvers"
-msgstr ""
-
-msgid "Add attention request"
-msgstr ""
+msgstr "අනුමතකරුවන් යොදන්න"
msgid "Add broadcast message"
msgstr "විකà·à·à¶± පණිවිඩයක් යොදන්න"
@@ -2223,7 +2239,7 @@ msgid "Add email address"
msgstr "වි-තà·à¶´à·‘ල එකතු කරන්න"
msgid "Add email participant(s)"
-msgstr ""
+msgstr "වි-තà·à¶´à·à¶½à·Š සහභà·à¶œà·“න් යොදන්න"
msgid "Add environment"
msgstr "පරිසරයක් යොදන්න"
@@ -2231,6 +2247,9 @@ 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 ""
@@ -2406,13 +2425,13 @@ msgid "Address"
msgstr "ලිපිනය"
msgid "Adds"
-msgstr ""
+msgstr "එක් කරයි"
msgid "Adds %{epic_ref} as child epic."
msgstr ""
msgid "Adds %{labels} %{label_text}."
-msgstr ""
+msgstr "%{labels} %{label_text} එක් කරයි."
msgid "Adds a Zoom meeting."
msgstr "සූම් රà·à·ƒà·Šà·€à·“මක් එක් කරයි"
@@ -2424,7 +2443,7 @@ msgid "Adds an issue to an epic."
msgstr ""
msgid "Adds email participant(s)."
-msgstr ""
+msgstr "වි-තà·à¶´à·à¶½à·Š සහභà·à¶œà·“න් එක් කරයි"
msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
msgstr ""
@@ -2721,10 +2740,10 @@ msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
msgstr ""
msgid "AdminSettings|Import sources"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» ආයà·à¶­à¶º"
msgid "AdminSettings|Inactive project deletion"
-msgstr ""
+msgstr "අක්â€à¶»à·’ය ව්â€à¶ºà·à¶´à·˜à¶­à·’ මකà·à¶¯à·à¶¸à·“ම"
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
msgstr ""
@@ -2739,7 +2758,7 @@ msgid "AdminSettings|Limit the number of namespaces and projects that can be ind
msgstr ""
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr ""
+msgstr "2FA සබල කර ඇති විට ගිට් මෙහෙයුම් සඳහ෠වà·à¶»à¶ºà¶šà¶§ උපරිම කà·à¶½à¶º."
msgid "AdminSettings|Maximum number of DAG dependencies that a job can have"
msgstr ""
@@ -2781,7 +2800,7 @@ msgid "AdminSettings|Preview payload"
msgstr ""
msgid "AdminSettings|Project export"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය නිර්යà·à¶­à¶º"
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr ""
@@ -2790,16 +2809,16 @@ msgid "AdminSettings|Registration Features include:"
msgstr ""
msgid "AdminSettings|Require users to prove ownership of custom domains"
-msgstr ""
+msgstr "අභිරුචි වසම්වල අයිතිය ඔප්පු කිරීමට පුද්ගලයින්ට සිදු වේ"
msgid "AdminSettings|Required pipeline configuration"
msgstr ""
msgid "AdminSettings|Requires %{linkStart}email notifications%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}වි-තà·à¶´à·à¶½à·Š දà·à¶±à·”ම්දීම්%{linkEnd} අවà·à·Šâ€à¶º වේ"
msgid "AdminSettings|Restrict group access by IP address. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "අ.ජ.කෙ. ලිපිනය මගින් සමූහයට ප්â€à¶»à·€à·šà·à¶º සීම෠කරන්න. %{link_start}තව දà·à¶±à¶œà¶±à·Šà¶±%{link_end}."
msgid "AdminSettings|Save %{name} limits"
msgstr ""
@@ -2808,7 +2827,7 @@ msgid "AdminSettings|Search with Elasticsearch enabled"
msgstr ""
msgid "AdminSettings|Select a CI/CD template"
-msgstr ""
+msgstr "CI/CD අච්චුවක් තà·à¶»à¶±à·Šà¶±"
msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
msgstr ""
@@ -2826,22 +2845,22 @@ msgid "AdminSettings|Service ping is disabled in your configuration file, and ca
msgstr ""
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr ""
+msgstr "2FA සබල විට ගිට් මෙහෙයුම් සඳහ෠වà·à¶»à¶ºà¶š කà·à¶½à·ƒà·“මà·à·€ (විනà·à¶©à·’)"
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 ""
+msgstr "එය අබල කිරීමට සීමà·à·€ 0 ට සකසන්න."
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 size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් සඳහ෠උපරිම ගිට්ලà·à¶¶à·Š පිටු ගණන සකසන්න (0 යනු අසීමිතයි). %{link_start}තව දà·à¶±à¶œà¶±à·Šà¶±.%{link_end}"
msgid "AdminSettings|Setting must be greater than 0."
-msgstr ""
+msgstr "à·ƒà·à¶šà·ƒà·”ම් 0 ට වඩ෠වà·à¶©à·’ විය යුතුය."
msgid "AdminSettings|Size and domain settings for Pages static sites."
msgstr ""
@@ -2883,7 +2902,7 @@ msgid "AdminSettings|You can enable Registration Features because Service Ping i
msgstr ""
msgid "AdminSettings|You can't delete projects before the warning email is sent."
-msgstr ""
+msgstr "අවවà·à¶¯ වි-තà·à¶´à·‘ල යà·à·€à·“මට පෙර ඔබට ව්â€à¶ºà·à¶´à·˜à¶­à·’ මà·à¶šà·“මට නොහà·à¶šà·’ය."
msgid "AdminStatistics|Active Users"
msgstr "සක්â€à¶»à·’ය පුද්ගලයින්"
@@ -2916,7 +2935,7 @@ msgid "AdminUsers|(Banned)"
msgstr ""
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(අවහිරයි)"
msgid "AdminUsers|(Deactivated)"
msgstr ""
@@ -3054,19 +3073,19 @@ msgid "AdminUsers|Deactivating a user has the following effects:"
msgstr ""
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr ""
+msgstr "පරිà·à·“ලක %{username} සහ දà·à¶ºà¶šà¶­à·Šà·€ මකන්නද?"
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr "පරිà·à·“ලක %{username} මකන්නද?"
msgid "AdminUsers|Delete user"
msgstr "පරිà·à·“ලකය෠මකන්න"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "පරිà·à·“ලක සහ දà·à¶ºà¶šà¶­à·Šâ€à·€ මකන්න"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "CSV ලෙස අවසර නිර්යà·à¶­à¶º (උපරිම පුද්ගලයින් 100,000)"
msgid "AdminUsers|External"
msgstr "බà·à·„ිර"
@@ -3096,7 +3115,7 @@ msgid "AdminUsers|It's you!"
msgstr "ඒ ඔබයි!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
-msgstr ""
+msgstr "%{link_start}තහනම් කළ පරිà·à·“ලකයින්%{link_end} ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±."
msgid "AdminUsers|Limits"
msgstr "සීමà·"
@@ -3105,7 +3124,7 @@ msgid "AdminUsers|Linkedin"
msgstr "ලින්ක්ඩින්"
msgid "AdminUsers|Locked"
-msgstr ""
+msgstr "අගුළු ල෠ඇත"
msgid "AdminUsers|Log in"
msgstr "ඇතුළු වන්න"
@@ -3366,7 +3385,7 @@ 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 "එය ඉකුත් වූ පසු, ඔබට සංයුක්ත අනුමà·à¶­à·’, කේත ගුණත්â€à·€à¶º, හ෠අනෙකුත් විà·à·šà·‚à·à¶‚ග භà·à·€à·’ත කළ නොහà·à¶šà·’ය."
msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
@@ -3492,7 +3511,7 @@ msgid "AlertManagement|Service"
msgstr "සේවà·à·€"
msgid "AlertManagement|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "AlertManagement|Start time"
msgstr "ආරම්භක වේලà·à·€"
@@ -3755,6 +3774,9 @@ msgstr "සියළු à·à·à¶›à·"
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3789,7 +3811,7 @@ msgid "All projects selected"
msgstr "සියළුම ව්â€à¶ºà·à¶´à·˜à¶­à·’ තà·à¶»à· ඇත"
msgid "All protected branches"
-msgstr ""
+msgstr "සියළුම ආරක්â€à·‚ිත à·à·à¶›à·"
msgid "All threads resolved!"
msgstr ""
@@ -3864,7 +3886,7 @@ msgid "Allow users to register any application to use GitLab as an OAuth provide
msgstr ""
msgid "Allowed"
-msgstr ""
+msgstr "ඉඩ දී ඇත"
msgid "Allowed characters: +, 0-9, -, and spaces."
msgstr ""
@@ -3885,7 +3907,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 "Opstrace අනුකලනයක් භà·à·€à·’තයෙන් දà·à·‚ නිරීක්ෂණයට ව්â€à¶ºà·à¶´à·˜à¶­à·’ වලට ඉඩදෙන්න."
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4269,7 +4288,7 @@ msgid "An error occurred while retrieving projects."
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගà·à¶±à·“මේදී දà·à·‚යකි."
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "ඔබගේ à·ƒà·à¶šà·ƒà·”ම් ලබ෠ගà·à¶±à·“මේදී දà·à·‚යක් ඇති විය. පිටුව නà·à·€à¶­ පූරණය කරන්න."
msgid "An error occurred while saving changes: %{error}"
msgstr "වෙනස්කම් සුරà·à¶šà·“මේදී දà·à·‚යකි: %{error}"
@@ -4280,7 +4299,7 @@ msgstr[0] "à·ƒà·à¶šà·ƒà·”ම සුරà·à¶šà·“මේදී දà·à·‚යක්
msgstr[1] "à·ƒà·à¶šà·ƒà·”ම් සුරà·à¶šà·“මේදී දà·à·‚යක් ඇති විය"
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "ඔබගේ à·ƒà·à¶šà·ƒà·”ම් සුරà·à¶šà·“මේදී දà·à·‚යක් ඇති විය. යළි සුරà·à¶šà·“මට බලන්න."
msgid "An error occurred while subscribing to notifications."
msgstr ""
@@ -4490,7 +4509,7 @@ msgid "Application settings saved successfully"
msgstr "යෙදුමේ à·ƒà·à¶šà·ƒà·”ම් à·ƒà·à¶»à·Šà¶®à¶šà·€ සුරà·à¶šà·’ණි"
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "යෙදුම් à·ƒà·à¶šà·ƒà·”ම් à·ƒà·à¶»à·Šà¶®à¶šà·€ සුරà·à¶šà·’ණි."
msgid "Application settings update failed"
msgstr "යෙදුමේ à·ƒà·à¶šà·ƒà·”ම් යà·à·€à¶­à·Šà¶šà·à¶½à¶ºà¶§ අසමත්!"
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 "වසම.ලංකà·"
@@ -4764,28 +4807,31 @@ msgstr "ඉලක්කගත à·à·à¶›à·à·€"
msgid "ApprovalRule|Try for free"
msgstr "නොමිලේ උත්සà·à·„යට"
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "අනුමතකරු"
@@ -5124,7 +5170,7 @@ msgid "Assign milestone"
msgstr ""
msgid "Assign myself"
-msgstr ""
+msgstr "මටම පවරන්න"
msgid "Assign reviewer"
msgstr "සමà·à¶½à·à¶ à¶š පà·à·€à¶»à·“ම"
@@ -5133,7 +5179,7 @@ msgid "Assign reviewer(s)"
msgstr "සමà·à¶½à·à¶ à¶šà¶ºà·’න් පà·à·€à¶»à·“ම"
msgid "Assign severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€ පවරන්න"
msgid "Assign some issues to this milestone."
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr "මට පවර෠ඇත"
msgid "Assigned to you"
msgstr "ඔබට පà·à·€à¶»à·–"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
-msgstr "ගොනුවක් අමුණන්න"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr "ගොනුව අමුණමින් - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] "ගොනු %d ක් අමුණමින්"
msgid "Attaching the file failed."
msgstr "ගොනුව ඇමිණීමට අසමත්!."
-msgid "Attention"
-msgstr "අවධà·à¶±à¶º"
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,11 +5359,14 @@ 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"
-msgstr ""
+msgstr "අභිරුචි HTTP à·à·Šâ€à¶»à·“ර්ෂ"
msgid "AuditStreams|Delete %{link}"
msgstr "%{link} මකන්න"
@@ -5331,18 +5377,33 @@ msgstr "ගමනà·à¶±à·Šà¶­ ඒ.à·ƒ.නි."
msgid "AuditStreams|Destinations receive all audit event data"
msgstr ""
-msgid "AuditStreams|Header"
+msgid "AuditStreams|Edit %{link}"
msgstr ""
+msgid "AuditStreams|Header"
+msgstr "à·à·Šâ€à¶»à·“ර්ෂය"
+
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
+msgstr "උපරිම HTTP à·à·Šâ€à¶»à·“ර්ෂ %{number} වෙත ළඟ෠වී ඇත."
+
+msgid "AuditStreams|Save external stream destination"
msgstr ""
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr "ප්â€à¶»à¶ à·à¶»"
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr "අගය"
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "නිකිණි"
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5590,31 +5654,31 @@ msgid "Available on-demand"
msgstr ""
msgid "Available shared runners:"
-msgstr ""
+msgstr "තිබෙන හවුල් ධà·à·€à¶š:"
msgid "Available specific runners"
msgstr ""
msgid "Avatar for %{assigneeName}"
-msgstr ""
+msgstr "%{assigneeName} සඳහ෠ප්â€à¶»à¶­à·’රූපය"
msgid "Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "ප්â€à¶»à¶­à·’රූපය ඉවත් කෙරේ. ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "Average per day: %{average}"
-msgstr ""
+msgstr "දිනකට à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶º: %{average}"
msgid "Awaiting user signup"
msgstr ""
msgid "Award added"
-msgstr ""
+msgstr "සම්මà·à¶±à¶º එක් කෙරිණි"
msgid "Award removed"
-msgstr ""
+msgstr "සම්මà·à¶±à¶º ඉවතලිණි"
msgid "AwardEmoji|No emojis found."
-msgstr ""
+msgstr "ඉමà·à¶¢à·’ හමු නොවිණි."
msgid "Back"
msgstr "ආපසු"
@@ -5629,7 +5693,7 @@ msgid "Background Jobs"
msgstr ""
msgid "Background Migrations"
-msgstr ""
+msgstr "පසුබිම් සංක්â€à¶»à¶¸à¶«"
msgid "Background color"
msgstr "පසුබිම් වර්ණය"
@@ -5674,7 +5738,7 @@ msgid "Badges|Badge saved."
msgstr "චිහ්නට සුරà·à¶šà·’ණි."
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "චිහ්නය මකන්නද?"
msgid "Badges|Deleting the badge failed, please try again."
msgstr ""
@@ -5686,7 +5750,7 @@ msgid "Badges|Example: %{exampleUrl}"
msgstr "නිදසුන: %{exampleUrl}"
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "සමූහයේ චිහ්නය"
msgid "Badges|Link"
msgstr "සබà·à¶³à·’ය"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5806,16 +5873,16 @@ msgid "BatchedJob|Finished at"
msgstr ""
msgid "BatchedJob|Max Value"
-msgstr ""
+msgstr "උපරිම අගය"
msgid "BatchedJob|Max value"
-msgstr ""
+msgstr "උපරිම අගය"
msgid "BatchedJob|Min Value"
-msgstr ""
+msgstr "අවම අගය"
msgid "BatchedJob|Min value"
-msgstr ""
+msgstr "අවම අගය"
msgid "BatchedJob|Next Status"
msgstr "ඊළඟ තත්â€à·€à¶º"
@@ -5950,7 +6017,7 @@ msgid "BillingPlans|If you would like to downgrade your plan please contact %{su
msgstr ""
msgid "BillingPlans|Includes free static websites"
-msgstr ""
+msgstr "නොමිලේ ස්ථිතික අඩවි ඇතුළත්ය"
msgid "BillingPlans|Learn more"
msgstr "තව දà·à¶±à¶œà¶±à·Šà¶±"
@@ -5959,7 +6026,7 @@ msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or st
msgstr ""
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
-msgstr ""
+msgstr "අපගේ %{pricing_page_link} වෙත පිවිසීමෙන් එක් එක් à·ƒà·à¶½à·ƒà·”ම ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±."
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 ""
@@ -5968,7 +6035,7 @@ msgid "BillingPlans|Loved and trusted by our customers"
msgstr ""
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "à·ƒà·à¶½à·ƒà·”ම කළමනà·à¶šà¶»à¶«à¶º"
msgid "BillingPlans|Not the group you're looking for? %{all_groups_link}."
msgstr ""
@@ -6001,7 +6068,7 @@ msgid "BillingPlans|Security risk mitigation"
msgstr ""
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "%{plan_name} සියළු විà·à·šà·‚à·à¶‚ග බලන්න"
msgid "BillingPlans|Self-managed reliability"
msgstr ""
@@ -6028,28 +6095,28 @@ msgid "BillingPlans|To manage the plan for this group, visit the billing section
msgstr ""
msgid "BillingPlans|Ultimate"
-msgstr ""
+msgstr "අත්â€à¶ºà¶±à·Šà¶­à¶º"
msgid "BillingPlans|Upgrade to Premium"
-msgstr ""
+msgstr "ආධික්â€à¶ºà¶ºà¶§ උත්à·à·Šâ€à¶»à·šà¶«à·’ය"
msgid "BillingPlans|Upgrade to Ultimate"
-msgstr ""
+msgstr "අත්â€à¶ºà¶±à·Šà¶­à¶ºà¶§ උත්à·à·Šâ€à¶»à·šà¶«à·’ය"
msgid "BillingPlans|Value stream management"
msgstr ""
msgid "BillingPlans|We're here to help."
-msgstr ""
+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 ""
+msgstr "ඔබ සතුව සමූහ නà·à¶­. %{create_group_link_start}සමූහයක් සෑදීමට%{create_group_link_end} සහ %{move_link_start}මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය එයට ගෙනයà·à¶¸à¶§%{move_link_end} අවà·à·Šâ€à¶º වනු ඇත."
msgid "BillingPlans|You'll have to %{move_link_start}move this project%{move_link_end} to one of your groups."
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය %{move_link_end}ඔබගේ සමූහ වලින් එකකට%{move_link_start} ගෙන යà·à¶¸à¶§ සිදුවේ."
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 ""
@@ -6061,7 +6128,7 @@ msgid "BillingPlans|Your current plan"
msgstr "ඔබගේ වත්මන් à·ƒà·à¶½à·ƒà·”ම"
msgid "BillingPlans|billed annually at %{price_per_year}"
-msgstr ""
+msgstr "à·€à·à¶»à·Šà·‚ිකව %{price_per_year} අය කෙරේ"
msgid "BillingPlans|for the remainder of your subscription"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6550,7 +6619,7 @@ msgid "Bold text"
msgstr "තද පෙළ"
msgid "Both SSH and HTTP(S)"
-msgstr ""
+msgstr "SSH සහ HTTP(S) දෙකම"
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr "à·à·à¶›à·à·€à·š නීති"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "à·à·à¶›à·"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7017,7 +7128,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 ""
@@ -7098,7 +7209,7 @@ msgid "CODEOWNERS rule violation"
msgstr ""
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "CPU"
msgstr "ම.à·ƒà·.ඒ."
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "කේතය සුපිරික්සීමට නොහà·à¶šà·’ද?"
@@ -7263,7 +7371,7 @@ msgid "Cancel your account"
msgstr "ගිණුම ඉවතලන්න"
msgid "Cancel, keep project"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය තබà·à¶œà¶±à·Šà¶±"
msgid "Canceled deployment to"
msgstr ""
@@ -7341,7 +7449,7 @@ msgid "Capacity threshold"
msgstr ""
msgid "Card holder name"
-msgstr ""
+msgstr "පත හිමියà·à¶œà·š නම"
msgid "Card number:"
msgstr "පතෙහි අංකය:"
@@ -7425,7 +7533,7 @@ msgid "Change status"
msgstr "තත්â€à·€à¶º සංà·à·à¶°à¶±à¶º"
msgid "Change subscription"
-msgstr "දà·à¶ºà¶šà¶­à·Šà·€à¶º සංà·à·à¶°à¶±à¶º"
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º සංà·à·à¶°à¶±à¶º"
msgid "Change template"
msgstr "අච්චුව සංà·à·à¶°à¶±à¶º"
@@ -7479,7 +7587,7 @@ msgid "ChangeTypeAction|Switch branch"
msgstr "à·à·à¶›à·à·€ මà·à¶»à·”à·€"
msgid "ChangeTypeAction|Switch project"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය මà·à¶»à·”à·€"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr ""
@@ -7488,7 +7596,7 @@ msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because
msgstr ""
msgid "Changed"
-msgstr ""
+msgstr "වෙනස් විය"
msgid "Changed assignee(s)."
msgstr ""
@@ -7512,19 +7620,19 @@ msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being
msgstr ""
msgid "Changes saved."
-msgstr ""
+msgstr "වෙනස්කම් සුරà·à¶šà·’ණි."
msgid "Changes suppressed. Click to show."
msgstr ""
msgid "Changes the title to \"%{title_param}\"."
-msgstr ""
+msgstr "මà·à¶­à·˜à¶šà·à·€ \"%{title_param}\" ලෙස වෙනස් කරයි."
msgid "Changes to the title have not been saved"
-msgstr ""
+msgstr "මà·à¶­à·˜à¶šà·à·€à·š වෙනස්කම් සුරà·à¶šà·“ නà·à¶­"
msgid "Changing any setting here requires an application restart"
-msgstr ""
+msgstr "මෙහි ඕනෑම à·ƒà·à¶šà·ƒà·”මක් වෙනස් කිරීමට යෙදුම යළි ඇරඹිය යුතුය"
msgid "Characters left"
msgstr "ඉතිරි අකුරු"
@@ -7646,13 +7754,13 @@ msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
msgstr ""
msgid "Checkout|%{name}'s CI minutes"
-msgstr ""
+msgstr "%{name}ගේ CI විනà·à¶©à·’"
msgid "Checkout|%{name}'s GitLab subscription"
-msgstr ""
+msgstr "%{name}ගේ ගිට්ලà·à¶¶à·Š දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "Checkout|%{name}'s storage subscription"
-msgstr ""
+msgstr "%{name}ගේ ආචයන දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "Checkout|%{quantity} CI minutes"
msgstr "CI විනà·à¶©à·’ %{quantity}"
@@ -7666,37 +7774,37 @@ msgstr[0] "ආචයන ඇසුරුම් %{quantity}"
msgstr[1] "ආචයන ඇසුරුම් %{quantity}"
msgid "Checkout|%{selectedPlanText} plan"
-msgstr ""
+msgstr "%{selectedPlanText} à·ƒà·à¶½à·ƒà·”ම"
msgid "Checkout|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
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 "නොදන්න෠දà·à·‚යක් සිදුවී ඇත. මෙම පිටුව නà·à·€à·”ම් කිරීමෙන් උත්සà·à·„ කරන්න."
msgid "Checkout|Billing address"
-msgstr ""
+msgstr "ලදුපත් ලිපිනය"
msgid "Checkout|CI minute pack"
-msgstr ""
+msgstr "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 ""
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "CI විනà·à¶©à·’"
msgid "Checkout|Calculating your subscription..."
-msgstr ""
+msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º ගණනය වෙමින්..."
msgid "Checkout|Checkout"
msgstr ""
@@ -7705,16 +7813,16 @@ msgid "Checkout|City"
msgstr "නගරය"
msgid "Checkout|Confirm purchase"
-msgstr ""
+msgstr "මිලදී ගà·à¶±à·“ම තහවුරුව"
msgid "Checkout|Confirming..."
msgstr "තහවුරු වෙමින්..."
msgid "Checkout|Continue to billing"
-msgstr ""
+msgstr "ලදුපතට දිගටම"
msgid "Checkout|Continue to payment"
-msgstr ""
+msgstr "ගෙවීමට ඉදිරියට"
msgid "Checkout|Country"
msgstr "රට"
@@ -7723,10 +7831,10 @@ msgid "Checkout|Create a new group"
msgstr "නව සමූහයක් à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "Checkout|Credit card form failed to load. Please try again."
-msgstr ""
+msgstr "ණය පතට ආකෘතිය පූරණයට අසමත් විය. යළි උත්සà·à·„ කරන්න."
msgid "Checkout|Credit card form failed to load: %{message}"
-msgstr ""
+msgstr "ණය පතට ආකෘතිය පූරණයට අසමත් විය: %{message}"
msgid "Checkout|Edit"
msgstr "සංස්කරණය"
@@ -7735,10 +7843,10 @@ msgid "Checkout|Enter a number greater than 0"
msgstr "0 ට වඩ෠වà·à¶©à·’ අංකයක් ඇතුල් කරන්න"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
-msgstr ""
+msgstr "ඉකුත්වීම %{expirationMonth}/%{expirationYear}"
msgid "Checkout|Failed to confirm your order! Please try again."
-msgstr ""
+msgstr "ඔබගේ ඇණවුම තහවුරුවට අසමත් විය! යළි උත්සà·à·„ කරන්න."
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -7912,7 +8017,7 @@ msgid "Choose a type..."
msgstr "වර්ගයක් තà·à¶»à¶±à·Šà¶±..."
msgid "Choose any color."
-msgstr ""
+msgstr "ඕනෑම පà·à¶§à¶šà·Š තà·à¶»à¶±à·Šà¶±."
msgid "Choose file…"
msgstr "ගොනුව තà·à¶»à¶±à·Šà¶±â€¦"
@@ -7942,7 +8047,7 @@ msgid "CiCdAnalytics|Date range: %{range}"
msgstr "දින පරà·à·ƒà¶º: %{range}"
msgid "CiStatusLabel|canceled"
-msgstr ""
+msgstr "අවලංගු කෙරිණි"
msgid "CiStatusLabel|created"
msgstr "සෑදිණි"
@@ -7957,7 +8062,7 @@ msgid "CiStatusLabel|manual action"
msgstr ""
msgid "CiStatusLabel|passed"
-msgstr ""
+msgstr "සමත් විය"
msgid "CiStatusLabel|passed with warnings"
msgstr ""
@@ -8106,7 +8211,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "Clear all repository checks"
-msgstr ""
+msgstr "සියළු කà·à·‚්ඨ පරීක්â€à·‚෠මකන්න"
msgid "Clear chart filters"
msgstr ""
@@ -8121,7 +8226,7 @@ msgid "Clear recent searches"
msgstr "මෑත සෙවුම් මකන්න"
msgid "Clear repository checks"
-msgstr ""
+msgstr "කà·à·‚්ඨ පරීක්â€à·‚෠මකන්න"
msgid "Clear search"
msgstr "සෙවුම මකන්න"
@@ -8148,13 +8253,13 @@ msgid "Clear weight"
msgstr ""
msgid "Cleared health status."
-msgstr ""
+msgstr "සෞඛ්â€à¶º තත්â€à·€à¶º මà·à¶šà·’ණි."
msgid "Cleared weight."
msgstr ""
msgid "Clears health status."
-msgstr ""
+msgstr "සෞඛ්â€à¶º තත්â€à·€à¶º මකයි."
msgid "Clears weight."
msgstr ""
@@ -8265,7 +8370,7 @@ msgid "Closed MRs"
msgstr ""
msgid "Closed date"
-msgstr ""
+msgstr "à·€à·à·ƒà·– දිනය"
msgid "Closed issues"
msgstr ""
@@ -8289,29 +8394,32 @@ msgid "CloudSeed|All"
msgstr "සියල්ල"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "පà·à·ƒà·Šà¶§à·Šà¶œà·Šâ€à¶»à·™à·ƒà·Š සඳහ෠AlloyDB"
msgid "CloudSeed|Available database services through which instances may be created"
msgstr ""
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "අවලංගු"
msgid "CloudSeed|Cloud Firestore"
msgstr ""
msgid "CloudSeed|Cloud SQL for MySQL"
-msgstr ""
+msgstr "MySQL සඳහ෠ක්ලවුඩ් SQL"
msgid "CloudSeed|Cloud SQL for Postgres"
-msgstr ""
+msgstr "පà·à·ƒà·Šà¶§à·Šà¶œà·Šâ€à¶»à·™à·ƒà·Š සඳහ෠ක්ලවුඩ් SQL"
msgid "CloudSeed|Cloud SQL for SQL Server"
-msgstr ""
+msgstr "SQL සේවà·à¶¯à·à¶ºà¶šà¶º සඳහ෠ක්ලවුඩ් SQL"
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr "දත්තසමුදà·à¶ºà·š අනුවà·à¶¯à¶º"
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr "සවිස්තරය"
@@ -8376,10 +8490,10 @@ msgid "CloudSeed|Learn more about pricing for %{cloudsqlPricingStart}Cloud SQL%{
msgstr ""
msgid "CloudSeed|Machine type"
-msgstr ""
+msgstr "යන්ත්â€à¶» වර්ගය"
msgid "CloudSeed|Memorystore for Redis"
-msgstr ""
+msgstr "රෙඩිස් සඳහ෠මෙමරිස්ටà·à¶»à·Š"
msgid "CloudSeed|No instances"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 "සේවà·"
@@ -8424,28 +8544,28 @@ msgid "ClusterAgents|%{linkStart}View the documentation%{linkEnd} for advanced i
msgstr ""
msgid "ClusterAgents|%{name} successfully deleted"
-msgstr ""
+msgstr "%{name} à·ƒà·à¶»à·Šà¶®à¶šà·€ මක෠ඇත"
msgid "ClusterAgents|%{name} successfully revoked"
-msgstr ""
+msgstr "%{name} à·ƒà·à¶»à·Šà¶®à¶šà·€ අහà·à·ƒà·’ කෙරිණි"
msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr ""
+msgstr "නියà·à¶­ %{total} / %{number}"
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
msgstr ""
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon} සම්බන්ධිතයි"
msgid "ClusterAgents|%{titleIcon}Not connected"
-msgstr ""
+msgstr "%{titleIcon} සම්බන්ධ නà·à¶­"
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} සෑදිණි"
msgid "ClusterAgents|%{tokenName} revoked"
-msgstr ""
+msgstr "%{tokenName} අහà·à·ƒà·’ කෙරිණි"
msgid "ClusterAgents|Access tokens"
msgstr ""
@@ -8454,7 +8574,7 @@ msgid "ClusterAgents|Add an agent configuration file to %{linkStart}this reposit
msgstr ""
msgid "ClusterAgents|Advanced installation methods"
-msgstr ""
+msgstr "à·€à·à¶©à·’දුර ස්ථà·à¶´à¶± ක්â€à¶»à¶¸"
msgid "ClusterAgents|Agent"
msgstr "නියà·à¶­à¶º"
@@ -8481,25 +8601,25 @@ msgid "ClusterAgents|Agent version mismatch and update"
msgstr ""
msgid "ClusterAgents|Agent version update required"
-msgstr ""
+msgstr "නියà·à¶­ අනුවà·à¶¯à¶º යà·à·€à¶­à·Šà¶šà·à¶½à¶º කළ යුතුය"
msgid "ClusterAgents|All"
msgstr "සියල්ල"
msgid "ClusterAgents|An error occurred while loading your agent"
-msgstr ""
+msgstr "ඔබගේ නියà·à¶­à¶º පූරණය කිරීමේදී දà·à·‚යක් ඇති විය"
msgid "ClusterAgents|An error occurred while loading your agents"
-msgstr ""
+msgstr "ඔබගේ නියà·à¶­ පූරණය කිරීමේදී දà·à·‚යක් ඇති විය"
msgid "ClusterAgents|An error occurred while retrieving agent activity. Reload the page to try again."
-msgstr ""
+msgstr "නියà·à¶­à¶ºà·š ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ගà·à¶±à·“මේදී දà·à·‚යක් ඇති විය. පිටුව නà·à·€à·”ම් කරන්න."
msgid "ClusterAgents|An unknown error occurred. Please try again."
-msgstr ""
+msgstr "නොදන්න෠දà·à·‚යක් සිදු විය. නà·à·€à¶­ උත්සà·à·„ කරන්න."
msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
-msgstr ""
+msgstr "ඔබට මෙම නියà·à¶­à¶º මà·à¶šà·“මට අවà·à·Šâ€à¶º ද? මෙය අප්â€à¶»à¶­à·’වර්ත්â€à¶ºà¶ºà·’."
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
msgstr ""
@@ -8556,16 +8676,16 @@ msgid "ClusterAgents|Created by %{name} %{time}"
msgstr ""
msgid "ClusterAgents|Date created"
-msgstr ""
+msgstr "සෑදූ දිනය"
msgid "ClusterAgents|Default configuration"
-msgstr ""
+msgstr "පෙරනිමි වින්â€à¶ºà·à·ƒà¶º"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "මකන්න"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "නියà·à¶­à¶º මකන්න"
msgid "ClusterAgents|Deprecated"
msgstr ""
@@ -8586,19 +8706,19 @@ msgid "ClusterAgents|From a terminal, connect to your cluster and run this comma
msgstr ""
msgid "ClusterAgents|GitLab agent"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š නියà·à¶­à¶º"
msgid "ClusterAgents|GitLab agent for Kubernetes"
-msgstr ""
+msgstr "කුබර්නෙට්ස් සඳහ෠ගිට්ලà·à¶¶à·Š නියà·à¶­à¶º"
msgid "ClusterAgents|Give feedback"
msgstr ""
msgid "ClusterAgents|How do I register an agent?"
-msgstr ""
+msgstr "මම නියà·à¶­à¶ºà¶šà·Š ලියà·à¶´à¶¯à·’ංචි කරන්නේ කෙසේද?"
msgid "ClusterAgents|How to update an agent?"
-msgstr ""
+msgstr "නියà·à¶­à¶ºà¶šà·Š යà·à·€à¶­à·Šà¶šà·à¶½ කරන්නේ කෙසේද?"
msgid "ClusterAgents|Install using Helm (recommended)"
msgstr ""
@@ -8616,10 +8736,10 @@ msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
msgid "ClusterAgents|Name"
-msgstr ""
+msgstr "නම"
msgid "ClusterAgents|Never"
-msgstr ""
+msgstr "කවදà·à·€à¶­à·Š"
msgid "ClusterAgents|Never connected"
msgstr ""
@@ -8630,13 +8750,13 @@ msgstr[0] ""
msgstr[1] ""
msgid "ClusterAgents|No agents"
-msgstr ""
+msgstr "නියà·à¶­ නà·à¶­"
msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr ""
msgid "ClusterAgents|Not connected"
-msgstr ""
+msgstr "සම්බන්ධ නà·à¶­"
msgid "ClusterAgents|Recommended"
msgstr "නිර්දේà·à·’ත"
@@ -8672,7 +8792,7 @@ msgid "ClusterAgents|Select an agent or enter a name to create new"
msgstr ""
msgid "ClusterAgents|Tell us what you think"
-msgstr ""
+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 ""
@@ -8780,7 +8900,7 @@ msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cl
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
-msgstr ""
+msgstr "ඇමසන් EKS"
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
msgstr ""
@@ -8798,7 +8918,7 @@ msgid "ClusterIntegration|Base domain"
msgstr ""
msgid "ClusterIntegration|CA Certificate"
-msgstr ""
+msgstr "CA සහතිකය"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -8840,13 +8960,13 @@ msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}clu
msgstr ""
msgid "ClusterIntegration|Connection Error"
-msgstr ""
+msgstr "සම්බන්ධතà·à·€à·š දà·à·‚යකි"
msgid "ClusterIntegration|Copy API URL"
-msgstr ""
+msgstr "යෙ.ක්â€à¶».මු. ඒ.à·ƒ.නි. පිටපතක්"
msgid "ClusterIntegration|Copy CA Certificate"
-msgstr ""
+msgstr "CA සහතිකයෙහි පිටපතක්"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -8858,13 +8978,13 @@ msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwis
msgstr ""
msgid "ClusterIntegration|Did you know?"
-msgstr ""
+msgstr "ඔබ දà·à¶± සිටියà·à¶¯?"
msgid "ClusterIntegration|Elastic Kubernetes Service"
msgstr ""
msgid "ClusterIntegration|Enable Prometheus integration"
-msgstr ""
+msgstr "ප්â€à¶»à·à¶¸à·’තියස් අනුකලනය සබල කරන්න"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr ""
@@ -8906,7 +9026,7 @@ msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
msgstr ""
msgid "ClusterIntegration|GitLab Integration"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š අනුකලනය"
msgid "ClusterIntegration|GitLab failed to authenticate."
msgstr ""
@@ -8918,7 +9038,7 @@ msgid "ClusterIntegration|GitLab-managed cluster"
msgstr ""
msgid "ClusterIntegration|Google GKE"
-msgstr ""
+msgstr "ගූගල් GKE"
msgid "ClusterIntegration|Google Kubernetes Engine"
msgstr ""
@@ -9011,7 +9131,7 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr ""
msgid "ClusterIntegration|Save changes"
-msgstr ""
+msgstr "වෙනස්කම් සුරකින්න"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -9119,7 +9239,7 @@ msgid "Clusters|An error occurred while loading clusters"
msgstr ""
msgid "Code"
-msgstr ""
+msgstr "කේතය"
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -9131,16 +9251,16 @@ msgid "Code Coverage|Couldn't fetch the code coverage data"
msgstr ""
msgid "Code Owner"
-msgstr ""
+msgstr "කේත හිමිකරු"
msgid "Code Owners"
-msgstr ""
+msgstr "කේත හිමිකරුවන්"
msgid "Code Quality"
-msgstr ""
+msgstr "කේත ගුණත්â€à·€à¶º"
msgid "Code Review"
-msgstr ""
+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 ""
@@ -9158,10 +9278,10 @@ msgid "Code owner approval is required"
msgstr ""
msgid "Code owners"
-msgstr ""
+msgstr "කේත හිමිකරුවන්"
msgid "Code review"
-msgstr ""
+msgstr "කේත සමà·à¶½à·à¶ à¶±à¶º"
msgid "Code snippet"
msgstr ""
@@ -9188,7 +9308,7 @@ msgid "Cohorts|Month %{month_index}"
msgstr ""
msgid "Cohorts|New users"
-msgstr ""
+msgstr "නව පුද්ගලයින්"
msgid "Cohorts|Registration month"
msgstr ""
@@ -9200,7 +9320,7 @@ msgid "Cohorts|User cohorts are shown for the last %{months_included} months. On
msgstr ""
msgid "Collapse"
-msgstr ""
+msgstr "හකුළන්න"
msgid "Collapse all threads"
msgstr ""
@@ -9218,13 +9338,13 @@ msgid "Collapse milestones"
msgstr ""
msgid "Collapse replies"
-msgstr ""
+msgstr "පිළිතුරු හකුළන්න"
msgid "Collapse settings section"
-msgstr ""
+msgstr "à·ƒà·à¶šà·ƒà·”ම් කොටස හකුළන්න"
msgid "Collapse sidebar"
-msgstr ""
+msgstr "පà·à¶­à·’ තීරුව හකුළන්න"
msgid "Collapses this file (only for you) until it’s changed again."
msgstr ""
@@ -9257,19 +9377,19 @@ msgid "Comma-separated list of email addresses."
msgstr ""
msgid "Command"
-msgstr ""
+msgstr "විධà·à¶±à¶º"
msgid "Command line instructions"
-msgstr ""
+msgstr "විධà·à¶± රේඛ෠උපදෙස්"
msgid "Commands applied"
-msgstr ""
+msgstr "විධà·à¶± යෙදිණි"
msgid "Commands did not apply"
-msgstr ""
+msgstr "විධà·à¶± නොයෙදිණි"
msgid "Comment"
-msgstr ""
+msgstr "අදහස"
msgid "Comment & resolve thread"
msgstr ""
@@ -9299,7 +9419,7 @@ msgid "Commenting on symbolic links that replace or are replaced by files is cur
msgstr ""
msgid "Comments"
-msgstr ""
+msgstr "අදහස්"
msgid "Commit"
msgid_plural "Commits"
@@ -9382,10 +9502,10 @@ msgid "Community forum"
msgstr "ප්â€à¶»à¶¢à· සංසදය"
msgid "Company"
-msgstr ""
+msgstr "සමà·à¶œà¶¸"
msgid "Company Name"
-msgstr ""
+msgstr "සමà·à¶œà¶¸à·š නම"
msgid "Compare"
msgstr "සසඳන්න"
@@ -9403,7 +9523,7 @@ msgid "Compare Revisions"
msgstr ""
msgid "Compare changes"
-msgstr ""
+msgstr "වෙනස්කම් සසඳන්න"
msgid "Compare changes with the last commit"
msgstr ""
@@ -9415,7 +9535,7 @@ msgid "Compare submodule commit revisions"
msgstr ""
msgid "Compare with previous version"
-msgstr ""
+msgstr "පෙර අනුවà·à¶¯à¶º සමඟ සසඳන්න"
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
msgstr ""
@@ -9424,13 +9544,13 @@ msgid "CompareBranches|There isn't anything to compare."
msgstr ""
msgid "CompareRevisions|Branches"
-msgstr ""
+msgstr "à·à·à¶›à·"
msgid "CompareRevisions|Compare"
-msgstr ""
+msgstr "සසඳන්න"
msgid "CompareRevisions|Create merge request"
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීමක් à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "CompareRevisions|Filter by Git revision"
msgstr ""
@@ -9463,13 +9583,13 @@ msgid "CompareRevisions|View open merge request"
msgstr ""
msgid "Complete"
-msgstr ""
+msgstr "සම්පූර්ණයි"
msgid "Complete verification to sign in."
-msgstr ""
+msgstr "පිවිසීමට තහවුරුව නිම කරන්න."
msgid "Completed"
-msgstr ""
+msgstr "සම්පූර්ණයි"
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
msgstr ""
@@ -9577,7 +9697,7 @@ msgid "ComplianceReport|No violations found"
msgstr ""
msgid "Component"
-msgstr ""
+msgstr "සංරචකය"
msgid "Confidence"
msgstr ""
@@ -9595,10 +9715,10 @@ msgid "Confidentiality"
msgstr ""
msgid "Configuration"
-msgstr ""
+msgstr "වින්â€à¶ºà·à·ƒà¶º"
msgid "Configuration help"
-msgstr ""
+msgstr "වින්â€à¶ºà·à·ƒà¶ºà¶§ උපකà·à¶»"
msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
msgstr ""
@@ -9628,19 +9748,19 @@ msgid "Configure Error Tracking"
msgstr ""
msgid "Configure GitLab"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š සකසන්න"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "වියමන අග්â€à¶»à¶º භà·à·€à·’තය ආරම්භයට ගිට්ලà·à¶¶à·Š ධà·à·€à¶š සකසන්න. %{helpStart}තව දà·à¶±à¶œà¶±à·Šà¶±.%{helpEnd}"
msgid "Configure Gitaly timeouts."
msgstr ""
msgid "Configure Integrations"
-msgstr ""
+msgstr "අනුකලන සකසන්න"
msgid "Configure Prometheus"
-msgstr ""
+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 ""
@@ -9673,7 +9793,7 @@ msgid "Configure advanced permissions, Large File Storage, two-factor authentica
msgstr ""
msgid "Configure existing installation"
-msgstr ""
+msgstr "පවතින ස්ථà·à¶´à¶±à¶º සකසන්න"
msgid "Configure pipeline"
msgstr ""
@@ -9682,19 +9802,19 @@ msgid "Configure pipelines to deploy web apps, backend services, APIs and static
msgstr ""
msgid "Configure region"
-msgstr ""
+msgstr "කලà·à¶´à¶º සකසන්න"
msgid "Configure region for environment"
-msgstr ""
+msgstr "පරිසරය සඳහ෠කලà·à¶´à¶º සකසන්න"
msgid "Configure regions"
-msgstr ""
+msgstr "කලà·à¶´ සකසන්න"
msgid "Configure repository mirroring."
msgstr ""
msgid "Configure repository storage."
-msgstr ""
+msgstr "කà·à·‚්ඨ ආචයනය සකසන්න."
msgid "Configure settings for Advanced Search with Elasticsearch."
msgstr ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10618,7 +10735,7 @@ msgid "Could not save project ID"
msgstr ""
msgid "Could not save prometheus manual configuration"
-msgstr ""
+msgstr "ප්â€à¶»à·™à·à·Šà¶¸à·’තියස් අතින් වින්â€à¶ºà·à·ƒà¶º සුරà·à¶šà·“මට නොහà·à¶šà·’ විය"
msgid "Could not update the LDAP settings"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11562,7 +11688,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 "සේව෠දත්ත ප්â€à¶»à¶­à·Šâ€à¶ºà¶»à·Šà¶´à¶«à¶ºà¶§ කà·à¶½à¶º ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත."
msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr "සේවà·à·€ ප්â€à¶»à¶­à·Šâ€à¶ºà¶»à·Šà¶´à¶«à¶ºà¶§ කà·à¶½à¶º"
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12314,7 +12458,7 @@ msgid "Delete image repository"
msgstr ""
msgid "Delete internal note"
-msgstr ""
+msgstr "අභ්â€à¶ºà¶±à·Šà¶­à¶» සටහන මකන්න"
msgid "Delete label"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "වසම"
@@ -13898,7 +14054,7 @@ msgid "Edit %{name}"
msgstr "%{name} සංස්කරණය"
msgid "Edit %{profileType} profile"
-msgstr ""
+msgstr "%{profileType} පà·à¶­à·’කඩ සංස්කරණය"
msgid "Edit Comment"
msgstr "අදහස සංස්කරණය"
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "වි-තà·à¶´à·‘ල"
@@ -14231,7 +14384,7 @@ msgid "Enable Auto DevOps"
msgstr ""
msgid "Enable GitLab Error Tracking"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š දà·à·‚ ලුහුබà·à¶³à·“ම සබල කරන්න"
msgid "Enable Gitpod"
msgstr "ගිට්පොඩ් සබල කරන්න"
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15502,7 +15655,7 @@ msgid "Expires"
msgstr ""
msgid "Expires %{preposition} %{expires_at}"
-msgstr ""
+msgstr "%{preposition} %{expires_at} ඉකුත් වේ"
msgid "Expires on"
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "නවම්"
msgid "February"
msgstr "නවම්"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17369,40 +17528,40 @@ msgid "Git version"
msgstr ""
msgid "GitAbuse|Excluded users"
-msgstr ""
+msgstr "බà·à·„à·à¶» කළ පුද්ගලයින්"
msgid "GitAbuse|Number of repositories"
-msgstr ""
+msgstr "කà·à·‚්ඨ ගණන"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "කà·à·‚්ඨ ගණන හිස් නොවිය යුතුය. 0 යනු සීම෠රහිතය."
msgid "GitAbuse|Number of repositories must be a number."
-msgstr ""
+msgstr "කà·à·‚්ඨ ගණන අංකයක් විය යුතුය."
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr ""
+msgstr "කà·à·‚්ඨ ගණන %{minNumRepos}-%{maxNumRepos} අතර විය යුතුය."
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "à·€à·à¶»à·Šà¶­à· කිරීමේ කà·à¶½ පරà·à·ƒà¶º (තත්.)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "à·€à·à¶»à·Šà¶­à· කිරීමේ කà·à¶½ පරà·à·ƒà¶º හිස් නොවිය යුතුය. 0 යනු සීම෠රහිතය."
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "à·€à·à¶»à·Šà¶­à· කිරීමේ කà·à¶½ පරà·à·ƒà¶º අංකයක් විය යුතුය."
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "à·€à·à¶»à·Šà¶­à· කිරීමේ කà·à¶½ පරà·à·ƒà¶º තත්. %{minTimePeriod}-%{maxTimePeriod} අතර විය යුතුය."
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr ""
+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 ""
+msgstr "ඔබට බà·à·„à·à¶» කළ පුද්ගලයින් %{maxExcludedUsers} කට වඩ෠දà·à¶šà·Šà·€à·’ය නොහà·à¶šà·’ය."
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
msgstr ""
@@ -17432,7 +17591,7 @@ msgid "GitLab Billing Team."
msgstr ""
msgid "GitLab Error Tracking"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š දà·à·‚ ලුහුබà·à¶³à·“ම"
msgid "GitLab Import"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr "ගිට්ලà·à¶¶à·Š KAS"
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17621,11 +17786,14 @@ msgid "GitLabPages|Unverified"
msgstr ""
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17777,7 +17948,7 @@ msgid "GlobalSearch|Type for new suggestions to appear below."
msgstr ""
msgid "GlobalSearch|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
-msgstr ""
+msgstr "සෙවීමක් ඇරඹීමට කෙටිමං යතුර %{kbdOpen}/%{kbdClose} භà·à·€à·’ත෠කරන්න"
msgid "GlobalSearch|What are you searching for?"
msgstr ""
@@ -17956,18 +18127,15 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
+msgid "Google Cloud Error - %{error}"
+msgstr ""
+
msgid "Google Cloud Project"
msgstr "ගූගල් ක්ලවුඩ් ව්â€à¶ºà·à¶´à·˜à¶­à·’ය"
msgid "Google Cloud authorizations required"
msgstr ""
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18068,7 +18236,7 @@ msgid "Group"
msgstr ""
msgid "Group \"%{group_name}\" was successfully updated."
-msgstr ""
+msgstr "\"%{group_name}\" සමූහය යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි."
msgid "Group %{group_name} couldn't be exported."
msgstr ""
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18236,7 +18401,7 @@ msgid "GroupActivityMetrics|Issues created"
msgstr ""
msgid "GroupActivityMetrics|Last 30 days"
-msgstr ""
+msgstr "පසුගිය දින 30"
msgid "GroupActivityMetrics|Members added"
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,11 +18721,14 @@ 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 ""
+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 ""
@@ -18568,14 +18736,8 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
-msgstr ""
-
-msgid "GroupSettings|Number of projects"
-msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගණන"
+msgstr "à·ƒà·à¶¸à·à¶¢à·’කයින්ට %{group} සමූහයෙන් හ෠එහි උපසමූහ වලින් පිටත සමූහ වලට ආරà·à¶°à¶±à· කළ නොහà·à¶šà·’ය"
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,11 +18757,8 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
-msgstr ""
+msgstr "%{group} à·„à·’ ඇති ව්â€à¶ºà·à¶´à·˜à¶­à·’ අන් සමූහ සමඟ බෙද෠ගත නොහà·à¶šà·’ය"
msgid "GroupSettings|Reporting"
msgstr "à·€à·à¶»à·Šà¶­à· කිරීම"
@@ -18622,15 +18781,9 @@ msgstr "මෙම සමූහයේ එක් එක් පිටු අඩවà
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19465,22 +19636,22 @@ msgid "IdentityVerification|Please enter a valid code"
msgstr ""
msgid "IdentityVerification|Resend code"
-msgstr ""
+msgstr "කේතය යළි යවන්න"
msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgstr "කේතය කල් ඉකුත්ය. නව කේතයක් යව෠යළි උත්සà·à·„ කරන්න."
msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgstr "කේතය à·€à·à¶»à¶¯à·’යි. යළි ඇතුල් කරන්න, හෝ නව කේතයක් යවන්න."
msgid "IdentityVerification|Verification code"
-msgstr ""
+msgstr "තහවුරු කේතය"
msgid "IdentityVerification|Verification successful"
-msgstr ""
+msgstr "තහවුරුව à·ƒà·à¶»à·Šà¶®à¶šà¶ºà·’"
msgid "IdentityVerification|Verify code"
-msgstr ""
+msgstr "තහවුරු කරන්න"
msgid "IdentityVerification|Verify your identity"
msgstr ""
@@ -19489,12 +19660,15 @@ msgid "IdentityVerification|You can always verify your account at a later time t
msgstr ""
msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+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 ""
+msgstr "ඔබගේ ගිණුම à·ƒà·à¶»à·Šà¶®à¶šà·€ තහවුරු කර ඇත. මොහොතකින් ඔබගේ ගිණුමට හරව෠යවනු ඇත, හෝ නà·à·€à·”ම් කිරීමට %{redirect_url_start}ඔබන්න%{redirect_url_end}."
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
+msgstr "තහවුරු කේතය විනà·à¶©à·’ %{expires_in_minutes} කින් ඉකුත් වේ."
+
+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."
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -20515,7 +20662,7 @@ msgid "IncidentManagement|Setting the status to Acknowledged or Resolved stops p
msgstr ""
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "IncidentManagement|Status"
msgstr ""
@@ -20665,10 +20812,10 @@ msgid "Incident|Timeline"
msgstr ""
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "කà·à¶½à¶»à·šà¶›à· පà·à¶¨à¶º"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "කà·à¶½à¶»à·šà¶›à· පà·à¶¨à¶º..."
msgid "Include author name in notification email body"
msgstr ""
@@ -20961,7 +21108,7 @@ msgid "Integrations|Connection details"
msgstr ""
msgid "Integrations|Connection failed. Check your integration settings."
-msgstr ""
+msgstr "සම්බන්ධතà·à·€à¶ºà¶§ අසමත් විය. ඔබගේ අනුකලන à·ƒà·à¶šà·ƒà·”ම් බලන්න."
msgid "Integrations|Connection successful."
msgstr ""
@@ -21054,7 +21201,7 @@ msgid "Integrations|No linked namespaces"
msgstr ""
msgid "Integrations|Notification settings"
-msgstr ""
+msgstr "දà·à¶±à·”ම්දීමේ à·ƒà·à¶šà·ƒà·”ම්"
msgid "Integrations|Projects using custom settings"
msgstr ""
@@ -21204,7 +21351,7 @@ msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid"
-msgstr ""
+msgstr "à·€à·à¶»à¶¯à·’ය"
msgid "Invalid Insights config file detected"
msgstr ""
@@ -21270,7 +21417,7 @@ msgid "Invalid repository path"
msgstr ""
msgid "Invalid rule"
-msgstr ""
+msgstr "à·€à·à¶»à¶¯à·’ රීතියකි"
msgid "Invalid server response"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22472,7 +22646,7 @@ msgid "Job|Manual"
msgstr ""
msgid "Job|No search results found"
-msgstr ""
+msgstr "සෙවුම් ප්â€à¶»à¶­à·’ඵල හමු නොවිණි"
msgid "Job|Passed"
msgstr ""
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22737,8 +22914,8 @@ msgstr ""
msgid "Label added: %{labels}"
msgid_plural "Labels added: %{labels}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "එක්කළ නම්පත: %{labels}"
+msgstr[1] "එක්කළ නම්පත්: %{labels}"
msgid "Label priority"
msgstr ""
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23046,7 +23217,7 @@ msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features
msgstr ""
msgid "LearnGitLab|Create a repository"
-msgstr ""
+msgstr "කà·à·‚්ඨයක් à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
msgstr ""
@@ -23097,7 +23268,7 @@ msgid "LearnGitLab|Save time by automating your integration and deployment tasks
msgstr ""
msgid "LearnGitLab|Scan dependencies for licenses"
-msgstr ""
+msgstr "බලපත්â€à¶» සඳහ෠පරà·à¶ºà¶­à·Šà¶­ සුපිරික්සන්න"
msgid "LearnGitLab|Scan dependencies for vulnerabilities"
msgstr ""
@@ -23109,7 +23280,7 @@ msgid "LearnGitLab|Set up CI/CD"
msgstr ""
msgid "LearnGitLab|Set up your first project's CI/CD"
-msgstr ""
+msgstr "ඔබගේ පළමු ව්â€à¶ºà·à¶´à·˜à¶­à·’යේ CI/CD පිහිටුවන්න"
msgid "LearnGitLab|Set up your workspace"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23874,7 +24087,7 @@ msgid "Marked this %{noun} as a draft."
msgstr ""
msgid "Marked this %{noun} as ready."
-msgstr ""
+msgstr "මෙම %{noun} සූදà·à¶±à¶¸à·Š ලෙස යොදන්න."
msgid "Marked this issue as a duplicate of %{duplicate_param}."
msgstr ""
@@ -23889,7 +24102,7 @@ msgid "Marks this %{noun} as a draft."
msgstr ""
msgid "Marks this %{noun} as ready."
-msgstr ""
+msgstr "මෙම %{noun} සූදà·à¶±à¶¸à·Š ලෙස යොදන්න."
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -24463,7 +24676,7 @@ msgid "Merge request events"
msgstr ""
msgid "Merge request locked."
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීම අගුළු ල෠ඇත."
msgid "Merge request not merged"
msgstr ""
@@ -24472,7 +24685,7 @@ msgid "Merge request reports"
msgstr ""
msgid "Merge request unlocked."
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීම අගුළු à·„à·à¶»à·’ණි."
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -24939,10 +25152,10 @@ msgid "Metrics|PromQL query is valid"
msgstr ""
msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
+msgstr "ප්â€à¶»à·à¶¸à·’තියස් විමසුම් ප්â€à¶»à¶½à·šà¶›à¶±à¶º"
msgid "Metrics|Refresh Prometheus data"
-msgstr ""
+msgstr "ප්â€à¶»à·à¶¸à·’තියස් දත්ත නà·à·€à·”ම් කිරීම"
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,11 +25684,11 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+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 ""
+msgstr "ප්â€à¶»à·à¶¸à·’තියස් අනුකලන කිහිපයකට සහය නොදක්වයි"
msgid "Multiple model types found: %{model_types}"
msgstr ""
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27111,7 +27329,7 @@ msgid "Only 1 appearances row can exist"
msgstr ""
msgid "Only HTTP(S)"
-msgstr ""
+msgstr "HTTP(S) පමණි"
msgid "Only Issue ID or merge request ID is required"
msgstr ""
@@ -27120,7 +27338,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 ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr "නුගෙට්"
msgid "PackageRegistry|NuGet Command"
msgstr "නුගෙට් විධà·à¶±à¶º"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Pip විධà·à¶±à¶º"
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28733,7 +29030,7 @@ msgid "Pipelines|Use template"
msgstr ""
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "වලංගුකරණය"
msgid "Pipelines|Validating GitLab CI configuration…"
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28973,7 +29300,7 @@ msgid "PlantUML URL"
msgstr ""
msgid "PlantUML diagram"
-msgstr ""
+msgstr "PlantUML රූප සටහන"
msgid "Play"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29114,6 +29444,9 @@ 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."
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29390,7 +29723,7 @@ msgid "Preview changes"
msgstr ""
msgid "Preview diagram"
-msgstr ""
+msgstr "රූප සටහන පෙරදසුන"
msgid "Preview payload"
msgstr ""
@@ -29612,7 +29945,7 @@ msgid "Profiles|Connect %{provider}"
msgstr ""
msgid "Profiles|Connect a service for sign-in."
-msgstr ""
+msgstr "පිවිසීමට සේවà·à·€à¶šà·Š සබඳින්න."
msgid "Profiles|Connected Accounts"
msgstr ""
@@ -29642,7 +29975,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 ""
@@ -29651,10 +29984,10 @@ 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 ""
@@ -29693,7 +30026,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 "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º (2FA) සබල කිරීමෙන් ගිණුමේ ආරක්â€à·‚à·à·€ තර කරන්න."
msgid "Profiles|Invalid password"
msgstr ""
@@ -29786,7 +30119,7 @@ msgid "Profiles|Set new profile picture"
msgstr ""
msgid "Profiles|Set your local time zone."
-msgstr ""
+msgstr "ස්ථà·à¶±à·“ය වේල෠කලà·à¶´à¶º සකසන්න."
msgid "Profiles|Some options are unavailable for LDAP accounts"
msgstr ""
@@ -29795,7 +30128,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 ""
@@ -29804,16 +30137,16 @@ msgid "Profiles|The maximum file size allowed is 200KB."
msgstr ""
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 ""
msgid "Profiles|This information will appear on your profile."
-msgstr ""
+msgstr "මෙම තොරතුරු ඔබගේ පà·à¶­à·’කඩෙහි දිස්වේ."
msgid "Profiles|Time settings"
msgstr ""
@@ -29822,7 +30155,7 @@ msgid "Profiles|Title"
msgstr ""
msgid "Profiles|Two-factor authentication"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
@@ -29858,7 +30191,7 @@ msgid "Profiles|What's your status?"
msgstr ""
msgid "Profiles|Who you represent or work for."
-msgstr ""
+msgstr "ඔබගේ නියà·à¶¢à¶±à¶º à·„à· à·€à·à¶© කරන්නේ කà·à¶§à¶¯."
msgid "Profiles|You can change your avatar here"
msgstr ""
@@ -29900,7 +30233,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 ""
+msgstr "%{provider_label} ගිණුම මත පදනම්ව ඔබගේ නම ස්වයංක්â€à¶»à·“යව සකස෠ඇත, එබà·à·€à·’න් ඔබ දන්න෠පුද්ගලයින්ට හඳුනà·à¶œà¶­ à·„à·à¶šà·’ය."
msgid "Profiles|Your status"
msgstr ""
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30104,7 +30446,7 @@ msgid "ProjectCreationLevel|No one"
msgstr ""
msgid "ProjectCreationLevel|Roles allowed to create projects"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ සෑදීමට ඉඩ දී ඇති භූමිකà·"
msgid "ProjectFileTree|Name"
msgstr ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -30218,7 +30569,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 ""
@@ -30971,7 +31322,7 @@ msgid "ProjectsNew|Want to organize several dependent projects under the same na
msgstr ""
msgid "PrometheusAlerts|exceeded"
-msgstr ""
+msgstr "ඉක්මවිණි"
msgid "PrometheusAlerts|is equal to"
msgstr ""
@@ -30980,7 +31331,7 @@ msgid "PrometheusAlerts|is less than"
msgstr ""
msgid "PrometheusService|%{exporters} with %{metrics} were found"
-msgstr ""
+msgstr "%{metrics} සමඟ %{exporters} හමු විය"
msgid "PrometheusService|Active"
msgstr ""
@@ -31013,13 +31364,13 @@ msgid "PrometheusService|Finding custom metrics..."
msgstr ""
msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
-msgstr ""
+msgstr "IAP_CLIENT_ID.apps.googleusercontent.com"
msgid "PrometheusService|Manage clusters"
msgstr ""
msgid "PrometheusService|Manual configuration"
-msgstr ""
+msgstr "අතින් වින්â€à¶ºà·à·ƒà¶º"
msgid "PrometheusService|Metrics"
msgstr ""
@@ -31031,7 +31382,7 @@ msgid "PrometheusService|Monitor application health with Prometheus metrics and
msgstr ""
msgid "PrometheusService|More information"
-msgstr ""
+msgstr "තව තොරතුරු"
msgid "PrometheusService|New metric"
msgstr ""
@@ -31055,7 +31406,7 @@ msgid "PrometheusService|The Prometheus API base URL."
msgstr ""
msgid "PrometheusService|The contents of the credentials.json file of your service account."
-msgstr ""
+msgstr "ඔබගේ සේව෠ගිණුමේ credentials.json ගොනුවේ අන්තර්ගතය."
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr ""
@@ -31070,7 +31421,7 @@ msgid "PrometheusService|You have a cluster with the Prometheus integration enab
msgstr ""
msgid "PrometheusService|https://prometheus.example.com/"
-msgstr ""
+msgstr "https://ප්â€à¶»à·à¶¸à·’තියස්.උදà·à·„රණය.ලංකà·/"
msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
msgstr ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] "නිකුතුව"
msgstr[1] "නිකුතු"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 "බලපත්â€à¶»à¶º භà·à·€à·’තය ගිට්ලà·à¶¶à·Š වෙත à·€à·à¶»à·Šà¶­à· කරන්න"
@@ -32611,7 +32977,7 @@ msgid "Reports|Scanner"
msgstr ""
msgid "Reports|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "Reports|System output"
msgstr ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr "උත්à·à·Šâ€à¶»à·šà¶«à·’ කිරීමක් තිබේ"
msgid "Runners|upgrade recommended"
msgstr "උත්à·à·Šâ€à¶»à·šà¶«à·’ කිරීම නිර්දේà·à·’තයි"
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33920,7 +34321,7 @@ msgid "ScanResultPolicy|scanners"
msgstr ""
msgid "ScanResultPolicy|severity levels"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à· මට්ටම්"
msgid "ScanResultPolicy|vulnerability states"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -34995,7 +35423,7 @@ msgid "SecurityReports|Set status"
msgstr ""
msgid "SecurityReports|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "SecurityReports|Show %{pageSize} items"
msgstr ""
@@ -35142,7 +35570,7 @@ msgid "Select a branch"
msgstr ""
msgid "Select a branch to compare"
-msgstr ""
+msgstr "à·ƒà·à·ƒà¶³à·“මට à·à·à¶›à·à·€à¶šà·Š තà·à¶»à¶±à·Šà¶±"
msgid "Select a color"
msgstr "පà·à¶§à¶šà·Š තà·à¶»à¶±à·Šà¶±"
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35559,7 +35978,7 @@ msgid "Set rate limits for searches performed by web or API requests."
msgstr ""
msgid "Set severity"
-msgstr ""
+msgstr "තිව්â€à¶»à¶­à·à·€ සකසන්න"
msgid "Set sign-in restrictions for all users."
msgstr ""
@@ -35703,7 +36122,7 @@ msgid "Sets the milestone to %{milestone_reference}."
msgstr ""
msgid "Sets the severity"
-msgstr ""
+msgstr "තිව්â€à¶»à¶­à·à·€ සකසයි"
msgid "Sets time estimate to %{time_estimate}."
msgstr ""
@@ -35732,19 +36151,19 @@ msgid "Setup"
msgstr ""
msgid "Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "Severity updated to %{severity}."
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€à¶º %{severity} ට යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි."
msgid "SeverityWidget|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€à¶º"
msgid "SeverityWidget|Severity: %{severity}"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€à¶º: %{severity}"
msgid "SeverityWidget|There was an error while updating severity."
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€à¶º යà·à·€à¶­à·Šà¶šà·à¶½ කිරීමේදී දà·à·‚යක් ඇති විය."
msgid "Share"
msgstr ""
@@ -35924,7 +36343,7 @@ msgid "ShowcaseSecurity|Dynamically examine your application for vulnerabilities
msgstr ""
msgid "ShowcaseSecurity|Enable SAST"
-msgstr ""
+msgstr "SAST සබල කරන්න"
msgid "ShowcaseSecurity|Enable Secret Detection"
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -36409,55 +36831,55 @@ 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 ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€ මක෠දà·à¶¸à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත. නà·à·€à¶­ බලන්න."
msgid "Something went wrong while deleting your note. Please try again."
-msgstr ""
+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 ""
+msgstr "ඔබගේ අදහස සංස්කරණයේ දී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත. නà·à·€à¶­ බලන්න."
msgid "Something went wrong while exporting requirements"
-msgstr ""
+msgstr "අවà·à·Šâ€à¶ºà¶­à· නිර්යà·à¶­à¶ºà·š දී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත"
msgid "Something went wrong while fetching branches"
-msgstr ""
+msgstr "à·à·à¶›à· ගෙන ඒමේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත"
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "අදහස් ලබ෠ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත. නà·à·€à¶­ බලන්න."
msgid "Something went wrong while fetching description changes. Please try again."
-msgstr ""
+msgstr "සවිස්තරයෙහි වෙනස්කම් ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත. නà·à·€à¶­ බලන්න."
msgid "Something went wrong while fetching details"
msgstr ""
msgid "Something went wrong while fetching group member contributions"
-msgstr ""
+msgstr "සමූහයේ à·ƒà·à¶¸à·à¶¢à·’ක දà·à¶ºà¶šà¶­à·Šà·€ ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත"
msgid "Something went wrong while fetching latest comments."
-msgstr ""
+msgstr "නවතම අදහස් ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත."
msgid "Something went wrong while fetching projects"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත"
msgid "Something went wrong while fetching projects."
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත."
msgid "Something went wrong while fetching related merge requests."
msgstr ""
msgid "Something went wrong while fetching requirements count."
-msgstr ""
+msgstr "අවà·à·Šâ€à¶ºà¶­à· ගණන ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත."
msgid "Something went wrong while fetching requirements list."
msgstr ""
msgid "Something went wrong while fetching source branches."
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à· ගà·à¶±à·“මේදී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත."
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr ""
@@ -36562,19 +36984,19 @@ msgid "Sort direction: Descending"
msgstr ""
msgid "SortOptions|Blocking"
-msgstr ""
+msgstr "අවහිරය"
msgid "SortOptions|Closed date"
-msgstr ""
+msgstr "à·€à·à·ƒà·– දිනය"
msgid "SortOptions|Closed earlier"
msgstr ""
msgid "SortOptions|Closed recently"
-msgstr ""
+msgstr "මෑතදී à·€à·à·ƒà·–"
msgid "SortOptions|Created date"
-msgstr ""
+msgstr "සෑදූ දිනය"
msgid "SortOptions|Due date"
msgstr ""
@@ -36586,16 +37008,16 @@ msgid "SortOptions|Due soon"
msgstr ""
msgid "SortOptions|Expired date"
-msgstr ""
+msgstr "ඉකුත් වූ දිනය"
msgid "SortOptions|Label priority"
msgstr ""
msgid "SortOptions|Largest group"
-msgstr ""
+msgstr "විà·à·à¶½à¶­à¶¸ සමූහය"
msgid "SortOptions|Largest repository"
-msgstr ""
+msgstr "විà·à·à¶½à¶­à¶¸ කà·à·‚්ඨය"
msgid "SortOptions|Last Contact"
msgstr ""
@@ -36610,16 +37032,16 @@ msgid "SortOptions|Less weight"
msgstr ""
msgid "SortOptions|Manual"
-msgstr ""
+msgstr "අතින්"
msgid "SortOptions|Merged date"
-msgstr ""
+msgstr "සංයුක්ත දිනය"
msgid "SortOptions|Merged earlier"
msgstr ""
msgid "SortOptions|Merged recently"
-msgstr ""
+msgstr "මෑතදී සංයුක්ත"
msgid "SortOptions|Milestone due date"
msgstr ""
@@ -36634,19 +37056,19 @@ msgid "SortOptions|More weight"
msgstr ""
msgid "SortOptions|Most popular"
-msgstr ""
+msgstr "වඩà·à¶­à·Š ප්â€à¶»à¶ à¶½à·’ත"
msgid "SortOptions|Most stars"
-msgstr ""
+msgstr "බොහ෠තරු"
msgid "SortOptions|Name"
-msgstr ""
+msgstr "නම"
msgid "SortOptions|Name, ascending"
-msgstr ""
+msgstr "නම, ආරà·à·„ණ"
msgid "SortOptions|Name, descending"
-msgstr ""
+msgstr "නම, අවරà·à·„ණ"
msgid "SortOptions|Oldest created"
msgstr ""
@@ -36667,22 +37089,22 @@ msgid "SortOptions|Popularity"
msgstr ""
msgid "SortOptions|Priority"
-msgstr ""
+msgstr "ප්â€à¶»à¶¸à·”ඛතà·à·€à¶º"
msgid "SortOptions|Project"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය"
msgid "SortOptions|Recent last activity"
-msgstr ""
+msgstr "මෑත අවසà·à¶± ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸"
msgid "SortOptions|Recent sign in"
-msgstr ""
+msgstr "මෑත ඇතුළු වීම"
msgid "SortOptions|Recently starred"
msgstr ""
msgid "SortOptions|Size"
-msgstr ""
+msgstr "ප්â€à¶»à¶¸à·à¶«à¶º"
msgid "SortOptions|Sort by:"
msgstr ""
@@ -36691,10 +37113,10 @@ msgid "SortOptions|Sort direction"
msgstr ""
msgid "SortOptions|Stars"
-msgstr ""
+msgstr "තරු"
msgid "SortOptions|Start date"
-msgstr ""
+msgstr "ආරම්භක දිනය"
msgid "SortOptions|Start later"
msgstr ""
@@ -36703,55 +37125,55 @@ msgid "SortOptions|Start soon"
msgstr ""
msgid "SortOptions|Title"
-msgstr ""
+msgstr "සිරà·à·ƒà·’ය"
msgid "SortOptions|Type"
-msgstr ""
+msgstr "වර්ගය"
msgid "SortOptions|Version"
-msgstr ""
+msgstr "අනුවà·à¶¯à¶º"
msgid "SortOptions|Weight"
msgstr ""
msgid "Source"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶»à¶º"
msgid "Source (branch or tag)"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶»à¶º (à·à·à¶›à·à·€/අනන්â€à¶ºà¶±à¶º)"
msgid "Source Branch"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€"
msgid "Source IP"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» අ.ජà·.කෙ."
msgid "Source branch"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€"
msgid "Source branch will be deleted."
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€ මක෠දà·à¶¸à·™à¶±à·” ඇත."
msgid "Source branch will not be deleted."
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€ මක෠නොදමනු ඇත."
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgid "Source code (%{fileExtension})"
-msgstr ""
+msgstr "ප්â€à¶»à¶·à·€ කේතය (%{fileExtension})"
msgid "Source is not available"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶»à¶º නොතිබේ"
msgid "Source project cannot be found."
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» ව්â€à¶ºà·à¶´à·˜à¶­à·’ය හමු නොවිණි."
msgid "SourceEditor|\"el\" parameter is required for createInstance()"
msgstr ""
msgid "SourceEditor|%{name} is not registered."
-msgstr ""
+msgstr "%{name} ලියà·à¶´à¶¯à·’ංචි කර නà·à¶­."
msgid "SourceEditor|Extension definition should be either a class or a function"
msgstr ""
@@ -36790,13 +37212,13 @@ msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourceg
msgstr ""
msgid "SourcegraphAdmin|Learn more."
-msgstr ""
+msgstr "තව දà·à¶±à¶œà¶±à·Šà¶±."
msgid "SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph."
msgstr ""
msgid "SourcegraphAdmin|Save changes"
-msgstr ""
+msgstr "වෙනස්කම් සුරකින්න"
msgid "SourcegraphAdmin|Sourcegraph URL"
msgstr ""
@@ -36805,28 +37227,28 @@ msgid "SourcegraphAdmin|https://sourcegraph.example.com"
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
-msgstr ""
+msgstr "මෙම විà·à·šà·‚à·à¶‚ගය පරීක්â€à·‚à·à¶­à·Šà¶¸à¶š වන අතර දà·à¶±à¶§ ඇතà·à¶¸à·Š ව්â€à¶ºà·à¶´à·˜à¶­à·’ සඳහ෠සීම෠වේ."
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
-msgstr ""
+msgstr "මෙම විà·à·šà·‚à·à¶‚ගය පරීක්â€à·‚à·à¶­à·Šà¶¸à¶š වන අතර ප්â€à¶»à·ƒà·’ද්ධ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සඳහ෠සීම෠වේ."
msgid "SourcegraphPreferences|This feature is experimental."
-msgstr ""
+msgstr "මෙම විà·à·šà·‚à·à¶‚ගය පරීක්â€à·‚à·à¶­à·Šà¶¸à¶šà¶ºà·’."
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "%{linkStart}Sourcegraph.com%{linkEnd} භà·à·€à·’ත෠කරයි."
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
msgstr ""
msgid "Spam Check"
-msgstr ""
+msgstr "අයà·à¶ à·’ත පරීක්â€à·‚à·à·€"
msgid "Spam Check API key"
-msgstr ""
+msgstr "අයà·à¶ à·’ත පරීක්â€à·‚෠යෙ.ක්â€à¶».මු. යතුර"
msgid "Spam Logs"
-msgstr ""
+msgstr "අයà·à¶ à·’ත සටහන්"
msgid "Spam and Anti-bot Protection"
msgstr ""
@@ -36835,7 +37257,7 @@ msgid "Spam log successfully submitted as ham."
msgstr ""
msgid "Specific runners"
-msgstr ""
+msgstr "නිà·à·Šà¶ à·’ත ධà·à·€à¶š"
msgid "Specified URL cannot be used: \"%{reason}\""
msgstr ""
@@ -36871,7 +37293,7 @@ msgid "Stage:"
msgstr ""
msgid "Standard"
-msgstr ""
+msgstr "සම්මත"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
@@ -36904,16 +37326,16 @@ msgid "Starrers"
msgstr ""
msgid "Stars"
-msgstr ""
+msgstr "තරු"
msgid "Start Date"
-msgstr ""
+msgstr "ආරම්භක දිනය"
msgid "Start Time"
-msgstr ""
+msgstr "ආරම්භක වේලà·à·€"
msgid "Start Web Terminal"
-msgstr ""
+msgstr "වියමන අග්â€à¶»à¶º අරඹන්න"
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
@@ -36922,13 +37344,13 @@ msgid "Start a Free Ultimate Trial"
msgstr ""
msgid "Start a new discussion…"
-msgstr ""
+msgstr "නව à·ƒà·à¶šà¶ à·Šà¶¡à·à·€à¶šà·Š අරඹන්න…"
msgid "Start a new merge request with these changes"
msgstr ""
msgid "Start a review"
-msgstr ""
+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 ""
@@ -36937,7 +37359,7 @@ msgid "Start cleanup"
msgstr ""
msgid "Start date"
-msgstr ""
+msgstr "ආරම්භක දිනය"
msgid "Start free trial"
msgstr ""
@@ -36958,7 +37380,7 @@ msgid "Start merge train..."
msgstr ""
msgid "Start search"
-msgstr ""
+msgstr "සෙවුම අරඹන්න"
msgid "Start thread"
msgstr ""
@@ -36982,7 +37404,7 @@ msgid "Started escalation for this incident."
msgstr ""
msgid "Starting..."
-msgstr ""
+msgstr "ඇරඹෙමින්..."
msgid "Starts"
msgstr ""
@@ -37006,16 +37428,16 @@ msgid "State your message to activate"
msgstr ""
msgid "State/Province"
-msgstr ""
+msgstr "ප්â€à¶»à·à¶±à·Šà¶­à¶º/පළà·à¶­"
msgid "State/Province/City"
-msgstr ""
+msgstr "ප්â€à¶»à·à¶±à·Šà¶­à¶º/පළà·à¶­/නගරය"
msgid "Static Application Security Testing (SAST)"
msgstr ""
msgid "Statistics"
-msgstr ""
+msgstr "සංඛ්â€à¶ºà·à¶½à·šà¶›à¶±"
msgid "Status"
msgstr "තත්â€à·€à¶º"
@@ -37024,10 +37446,10 @@ msgid "Status was retried."
msgstr ""
msgid "Status:"
-msgstr ""
+msgstr "තත්â€à·€à¶º:"
msgid "Status: %{title}"
-msgstr ""
+msgstr "තත්â€à·€à¶º: %{title}"
msgid "StatusCheck| %{failed} failed, and %{pending} pending"
msgstr ""
@@ -37039,13 +37461,13 @@ msgid "StatusCheck|%{pending} pending"
msgstr ""
msgid "StatusCheck|API to check"
-msgstr ""
+msgstr "පරීක්â€à·‚à·à·€à¶§ යෙ.ක්â€à¶».මු."
msgid "StatusCheck|Add status check"
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚à·à·€ එක්කරන්න"
msgid "StatusCheck|All passed"
-msgstr ""
+msgstr "සියල්ල සමත්!"
msgid "StatusCheck|An error occurred deleting the %{name} status check."
msgstr ""
@@ -37063,31 +37485,31 @@ msgid "StatusCheck|Examples: QA, Security."
msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
-msgstr ""
+msgstr "බà·à·„ිර යෙ.ක්â€à¶».මු. දà·à¶±à¶§à¶¸à¶­à·Š වෙනත් තත්â€à·€ පරීක්â€à·‚à·à·€à¶š භà·à·€à·’ත෠වේ."
msgid "StatusCheck|Failed to load status checks"
msgstr ""
msgid "StatusCheck|Failed to load status checks."
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚෠පූරණයට අසමත් විය."
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
msgstr ""
msgid "StatusCheck|No status checks are defined yet."
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚෠තවම නියම කර නà·à¶­."
msgid "StatusCheck|Remove status check"
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚à·à·€ ඉවත් කරන්න"
msgid "StatusCheck|Remove status check?"
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚à·à·€ ඉවත් කරනවà·à¶¯?"
msgid "StatusCheck|Service name"
-msgstr ""
+msgstr "සේවà·à·€à·š නම"
msgid "StatusCheck|Status checks"
-msgstr ""
+msgstr "තත්â€à·€à¶º පරීක්â€à·‚à·à·€"
msgid "StatusCheck|Status checks all passed"
msgstr ""
@@ -37096,10 +37518,10 @@ msgid "StatusCheck|Status checks are being fetched"
msgstr ""
msgid "StatusCheck|Status to check"
-msgstr ""
+msgstr "පරීක්â€à·‚à·à·€à¶§ තත්â€à·€à¶º"
msgid "StatusCheck|Target branch"
-msgstr ""
+msgstr "ඉලක්ක à·à·à¶›à·à·€"
msgid "StatusCheck|Update status check"
msgstr ""
@@ -37108,19 +37530,19 @@ msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
msgid "StatusCheck|status checks"
-msgstr ""
+msgstr "තත්â€à·€ පරීක්â€à·‚à·"
msgid "StatusPage|AWS %{docsLink}"
-msgstr ""
+msgstr "AWS %{docsLink}"
msgid "StatusPage|AWS Secret access key"
-msgstr ""
+msgstr "AWS රහස් ප්â€à¶»à·€à·šà· යතුර"
msgid "StatusPage|AWS access key ID"
-msgstr ""
+msgstr "AWS ප්â€à¶»à·€à·šà· යතුරෙහි à·„à·à¶³à·”."
msgid "StatusPage|AWS region"
-msgstr ""
+msgstr "AWS කලà·à¶´à¶º"
msgid "StatusPage|Active"
msgstr ""
@@ -37135,10 +37557,10 @@ msgid "StatusPage|S3 Bucket name"
msgstr ""
msgid "StatusPage|Status page"
-msgstr ""
+msgstr "තත්â€à·€ පිටුව"
msgid "StatusPage|Status page URL"
-msgstr ""
+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 ""
@@ -37156,43 +37578,43 @@ msgid "Step %{currentStep} of %{stepCount}"
msgstr ""
msgid "Step 1."
-msgstr ""
+msgstr "පියවර 1."
msgid "Step 2."
-msgstr ""
+msgstr "පියවර 2."
msgid "Step 3."
-msgstr ""
+msgstr "පියවර 3."
msgid "Step 4."
-msgstr ""
+msgstr "පියවර 4."
msgid "Stop Terminal"
-msgstr ""
+msgstr "අග්â€à¶»à¶º නවතන්න"
msgid "Stop impersonation"
msgstr ""
msgid "Stop this environment"
-msgstr ""
+msgstr "මෙම පරිසරය නවතන්න"
msgid "Stopped"
-msgstr ""
+msgstr "නà·à·€à¶­à·’ණි"
msgid "Stopping..."
-msgstr ""
+msgstr "නවතමින්..."
msgid "Storage"
-msgstr ""
+msgstr "ආචයනය"
msgid "Storage nodes for new repositories"
msgstr ""
msgid "Storage:"
-msgstr ""
+msgstr "ආචයනය:"
msgid "StorageSize|Unknown"
-msgstr ""
+msgstr "නොදනී"
msgid "Store your files, plan your work, collaborate on code, and more."
msgstr ""
@@ -37210,31 +37632,31 @@ msgid "Subdomains of the Pages root domain %{root_domain} are reserved and canno
msgstr ""
msgid "Subgroup information"
-msgstr ""
+msgstr "උප සමූහයේ තොරතුරු"
msgid "Subgroup milestone"
msgstr ""
msgid "Subgroup navigation"
-msgstr ""
+msgstr "උප සමූහය යà·à¶­à·Šâ€à¶»à¶«à¶º"
msgid "SubgroupCreationLevel|Roles allowed to create subgroups"
msgstr ""
msgid "SubgroupCreationlevel|Allowed to create subgroups"
-msgstr ""
+msgstr "උපසමූහ සෑදීමට ඉඩ ඇත"
msgid "SubgroupCreationlevel|Maintainers"
-msgstr ""
+msgstr "නඩත්තුකරුවන්"
msgid "SubgroupCreationlevel|Owners"
-msgstr ""
+msgstr "හිමිකරුවන්"
msgid "Subgroups"
-msgstr ""
+msgstr "උප සමූහ"
msgid "Subgroups and projects"
-msgstr ""
+msgstr "උපසමූහ හ෠ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "Subgroups can set up their own two-factor authentication rules"
msgstr ""
@@ -37243,61 +37665,61 @@ msgid "Subject Key Identifier:"
msgstr ""
msgid "Subkeys"
-msgstr ""
+msgstr "අනුයතුරු"
msgid "Submit"
-msgstr ""
+msgstr "යොමන්න"
msgid "Submit a review"
-msgstr ""
+msgstr "සමà·à¶½à·à¶ à¶±à¶ºà¶šà·Š යොමන්න"
msgid "Submit as ham"
msgstr ""
msgid "Submit as spam"
-msgstr ""
+msgstr "අයà·à¶ à·’ත ලෙස යොමන්න"
msgid "Submit feedback"
msgstr "ප්â€à¶»à¶­à·’පà·à·‚ණ යොමන්න"
msgid "Submit review"
-msgstr ""
+msgstr "සමà·à¶½à·à¶ à¶±à¶º යොමන්න"
msgid "Submit search"
-msgstr ""
+msgstr "සෙවුම යොමන්න"
msgid "Submit the current review."
-msgstr ""
+msgstr "වත්මන් සමà·à¶½à·à¶ à¶±à¶º යොමන්න."
msgid "Submitted as ham"
msgstr ""
msgid "Submitted the current review."
-msgstr ""
+msgstr "වත්මන් සමà·à¶½à·à¶ à¶±à¶º යොමු කෙරිණි."
msgid "Subscribe"
-msgstr ""
+msgstr "දà·à¶ºà¶š වන්න"
msgid "Subscribe at group level"
-msgstr ""
+msgstr "සමූහ මට්ටමින් දà·à¶ºà¶šà·€à¶±à·Šà¶±"
msgid "Subscribe at project level"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ මට්ටමින් දà·à¶ºà¶šà·€à¶±à·Šà¶±"
msgid "Subscribe to RSS feed"
-msgstr ""
+msgstr "RSS සංග්â€à¶»à·„යට දà·à¶ºà¶šà·€à¶±à·Šà¶±"
msgid "Subscribe to calendar"
-msgstr ""
+msgstr "දිනදසුනට දà·à¶ºà¶šà·€à¶±à·Šà¶±"
msgid "Subscribed"
-msgstr ""
+msgstr "දà·à¶ºà¶š විය"
msgid "Subscribed to this %{quick_action_target}."
msgstr ""
msgid "Subscribed to this project"
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’යට දà·à¶ºà¶š විය"
msgid "Subscribes to this %{quick_action_target}."
msgstr ""
@@ -37306,67 +37728,67 @@ msgid "Subscript"
msgstr "යටකුර"
msgid "Subscription"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "Subscription History"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šà·€ ඉතිහà·à·ƒà¶º"
msgid "Subscription deletion failed."
msgstr ""
msgid "Subscription service outage"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€ සේවà·à·€ ඇනහිටීම"
msgid "Subscription successfully applied to \"%{group_name}\""
msgstr ""
msgid "Subscription successfully created."
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ සෑදිණි."
msgid "Subscription successfully deleted."
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ මක෠ඇත."
msgid "SubscriptionBanner|Add new license"
-msgstr ""
+msgstr "නව බලපත්â€à¶»à¶º යොදන්න"
msgid "SubscriptionBanner|Export license usage file"
-msgstr ""
+msgstr "බලපත්â€à¶ºà¶» භà·à·€à·’ත ගොනුව බà·à¶œà¶±à·Šà¶±"
msgid "SubscriptionBanner|Upload new license"
msgstr "නව බලපත්â€à¶»à¶º යොදන්න"
msgid "SubscriptionTable|Add seats"
-msgstr ""
+msgstr "ආසන එක්කරන්න"
msgid "SubscriptionTable|An error occurred while loading the subscription details."
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šà·€ විස්තර පූරණය කිරීමේදී දà·à·‚යක් ඇති විය."
msgid "SubscriptionTable|Billing"
msgstr ""
msgid "SubscriptionTable|Free"
-msgstr ""
+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 ""
+msgstr "අවසන් à·€à·à¶»à·Šà¶«à·à·€"
msgid "SubscriptionTable|Loading subscriptions"
msgstr ""
msgid "SubscriptionTable|Manage"
-msgstr ""
+msgstr "කළමනà·à¶šà¶»à¶«à¶º"
msgid "SubscriptionTable|Max seats used"
msgstr ""
msgid "SubscriptionTable|Next invoice"
-msgstr ""
+msgstr "ඊළඟ à·€à·à¶»à·Šà¶«à·à·€"
msgid "SubscriptionTable|Refresh Seats"
-msgstr ""
+msgstr "ආසන නà·à·€à·”ම් කිරීම"
msgid "SubscriptionTable|Renew"
msgstr ""
@@ -37381,10 +37803,10 @@ msgid "SubscriptionTable|Seats owed"
msgstr ""
msgid "SubscriptionTable|See usage"
-msgstr ""
+msgstr "භà·à·€à·’තය බලන්න"
msgid "SubscriptionTable|Something went wrong trying to refresh seats"
-msgstr ""
+msgstr "ආසන නà·à·€à·”ම් කිරීමට උත්සà·à·„යේ දී යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත"
msgid "SubscriptionTable|Subscription end date"
msgstr ""
@@ -37414,22 +37836,22 @@ msgid "SubscriptionTable|Trial start date"
msgstr ""
msgid "SubscriptionTable|Usage"
-msgstr ""
+msgstr "භà·à·€à·’තය"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
msgstr ""
msgid "Subscriptions"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€"
msgid "Subscriptions|Chat with sales"
-msgstr ""
+msgstr "අලෙවිය සමඟ කත෠කරන්න"
msgid "Subscriptions|Close"
-msgstr ""
+msgstr "වසන්න"
msgid "Subscriptions|Not ready to buy yet?"
-msgstr ""
+msgstr "මිලදී ගà·à¶±à·“මට සූදà·à¶±à¶¸à·Š නà·à¶­à·’ද?"
msgid "Subscriptions|Start a free trial"
msgstr ""
@@ -37447,37 +37869,34 @@ msgid "Subtracts"
msgstr ""
msgid "Succeeded"
-msgstr ""
-
-msgid "Successful purchase image"
-msgstr ""
+msgstr "à·ƒà·à¶»à·Šà¶®à¶š විය"
msgid "Successfully activated"
-msgstr ""
+msgstr "ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š කෙරිණි"
msgid "Successfully approved"
-msgstr ""
+msgstr "අනුමත කෙරිණි"
msgid "Successfully banned"
-msgstr ""
+msgstr "තහනම් කෙරිණි"
msgid "Successfully blocked"
-msgstr ""
+msgstr "අවහිර කෙරිණි"
msgid "Successfully confirmed"
-msgstr ""
+msgstr "තහවුරු කෙරිණි"
msgid "Successfully deactivated"
msgstr ""
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "U2F උපà·à¶‚ගය à·ƒà·à¶»à·Šà¶®à¶šà·€ මà·à¶šà·’ණි."
msgid "Successfully deleted WebAuthn device."
msgstr ""
msgid "Successfully removed email."
-msgstr ""
+msgstr "වි-තà·à¶´à·‘ල ඉවත් කෙරිණි."
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
msgstr ""
@@ -37486,46 +37905,46 @@ msgid "Successfully synced %{synced_timeago}."
msgstr ""
msgid "Successfully unbanned"
-msgstr ""
+msgstr "තහනම ඉවත් කෙරිණි"
msgid "Successfully unblocked"
-msgstr ""
+msgstr "අනවහිර කෙරිණි"
msgid "Successfully unlocked"
-msgstr ""
+msgstr "අගුළු à·„à·à¶»à·’ණි"
msgid "Successfully updated %{last_updated_timeago}."
msgstr ""
msgid "Successfully updated the environment."
-msgstr ""
+msgstr "පරිසරය à·ƒà·à¶»à·Šà¶®à¶šà·€ යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි."
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
msgstr ""
msgid "Suggested change"
-msgstr ""
+msgstr "යà·à¶¢à·’ත වෙනස"
msgid "SuggestedColors|Aztec Gold"
msgstr ""
msgid "SuggestedColors|Blue"
-msgstr ""
+msgstr "නිල්"
msgid "SuggestedColors|Blue-gray"
-msgstr ""
+msgstr "නිල්-අළු"
msgid "SuggestedColors|Carrot orange"
-msgstr ""
+msgstr "කà·à¶»à¶§à·Š තà·à¶¹à·’ලි"
msgid "SuggestedColors|Champagne"
-msgstr ""
+msgstr "à·‚à·à¶¸à·Šà¶´à·šà¶±à·Š"
msgid "SuggestedColors|Charcoal grey"
-msgstr ""
+msgstr "අඟුරු අළු"
msgid "SuggestedColors|Crimson"
-msgstr ""
+msgstr "තද රතු"
msgid "SuggestedColors|Current addition color"
msgstr ""
@@ -37537,16 +37956,16 @@ msgid "SuggestedColors|Dark coral"
msgstr ""
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "තද කොළ"
msgid "SuggestedColors|Dark sea green"
-msgstr ""
+msgstr "තද සමුද්â€à¶» කොළ"
msgid "SuggestedColors|Dark violet"
-msgstr ""
+msgstr "අඳුරු ජම්බූල"
msgid "SuggestedColors|Deep violet"
-msgstr ""
+msgstr "තද ජම්බූල"
msgid "SuggestedColors|Default addition color"
msgstr ""
@@ -37555,13 +37974,13 @@ msgid "SuggestedColors|Default removal color"
msgstr ""
msgid "SuggestedColors|Gray"
-msgstr ""
+msgstr "අළු"
msgid "SuggestedColors|Green"
msgstr "කොළ"
msgid "SuggestedColors|Green screen"
-msgstr ""
+msgstr "කොළ තිරය"
msgid "SuggestedColors|Green-cyan"
msgstr ""
@@ -37573,43 +37992,43 @@ msgid "SuggestedColors|Magenta-pink"
msgstr ""
msgid "SuggestedColors|Medium sea green"
-msgstr ""
+msgstr "මධ්â€à¶ºà¶¸ සමුද්â€à¶» කොළ"
msgid "SuggestedColors|Orange"
-msgstr ""
+msgstr "තà·à¶¹à·’ලි"
msgid "SuggestedColors|Purple"
msgstr "දම්"
msgid "SuggestedColors|Red"
-msgstr ""
+msgstr "රතු"
msgid "SuggestedColors|Rose red"
-msgstr ""
+msgstr "රà·à·ƒ රතු"
msgid "SuggestedColors|Titanium yellow"
msgstr ""
msgid "Suggestion is not applicable as the suggestion was not found."
-msgstr ""
+msgstr "යà·à¶¢à¶±à·à·€ සොයà·à¶œà¶­ නොහà·à¶šà·’ බà·à·€à·’න් යà·à¶¢à¶±à·à·€ අදà·à·… නොවේ."
msgid "Suggestions are not applicable as one or more suggestions were not found."
-msgstr ""
+msgstr "යà·à¶¢à¶±à· එකක් හ෠කිහිපයක් හමු නොවූ බà·à·€à·’න් යà·à¶¢à¶±à· අදà·à·… නොවේ."
msgid "Suggestions are not applicable as their lines cannot overlap."
msgstr ""
msgid "Suggestions must all be on the same branch."
-msgstr ""
+msgstr "යà·à¶¢à¶±à· සියල්ලම එකම à·à·à¶›à·à·€à¶š තිබිය යුතුය."
msgid "Suggestions:"
-msgstr ""
+msgstr "යà·à¶¢à¶±à·:"
msgid "Suite"
msgstr ""
msgid "Summary"
-msgstr ""
+msgstr "à·ƒà·à¶»à·à¶‚à·à¶º"
msgid "Summary / note"
msgstr "à·ƒà·à¶»à·à¶‚à·à¶º / සටහන"
@@ -37630,7 +38049,7 @@ msgid "SuperSonics|An error occurred while adding your subscription."
msgstr ""
msgid "SuperSonics|Billable users"
-msgstr ""
+msgstr "අය කළ à·„à·à¶šà·’ පුද්ගලයින්"
msgid "SuperSonics|Buy subscription"
msgstr ""
@@ -37639,7 +38058,7 @@ msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
msgstr ""
msgid "SuperSonics|Cloud licensing"
-msgstr ""
+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 ""
@@ -37648,7 +38067,7 @@ msgid "SuperSonics|Enter activation code"
msgstr ""
msgid "SuperSonics|Export license usage file"
-msgstr ""
+msgstr "බලපත්â€à¶»à¶º භà·à·€à·’ත ගොනුව බà·à¶œà¶±à·Šà¶±"
msgid "SuperSonics|Free trial"
msgstr ""
@@ -37666,16 +38085,16 @@ msgid "SuperSonics|Licensed to"
msgstr ""
msgid "SuperSonics|Manage"
-msgstr ""
+msgstr "කළමනà·à¶šà¶»à¶«à¶º"
msgid "SuperSonics|Maximum users"
-msgstr ""
+msgstr "උපරිම පරිà·à·“ලකයින්"
msgid "SuperSonics|Offline license"
-msgstr ""
+msgstr "මà·à¶»à·Šà¶œà¶…පගත බලපත්â€à¶»à¶º"
msgid "SuperSonics|Online license"
-msgstr ""
+msgstr "මà·à¶»à·Šà¶œà¶œà¶­ බලපත්â€à¶»à¶º"
msgid "SuperSonics|Paste your activation code"
msgstr ""
@@ -37690,7 +38109,7 @@ msgid "SuperSonics|Start free trial"
msgstr ""
msgid "SuperSonics|Subscription details"
-msgstr ""
+msgstr "දà·à¶ºà¶šà¶­à·Šà·€ විස්තර"
msgid "SuperSonics|Subscription unavailable"
msgstr ""
@@ -37764,25 +38183,25 @@ msgid "SuperSonics|Your future dated license was successfully added"
msgstr ""
msgid "SuperSonics|Your subscription"
-msgstr ""
+msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "SuperSonics|Your subscription details will sync shortly."
-msgstr ""
+msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šà·€ විස්තර ඉක්මනින් සමමුහූර්ත වනු ඇත."
msgid "SuperSonics|Your subscription is expired."
-msgstr ""
+msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º කල් ඉකුත් වී ඇත."
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
-msgstr ""
+msgstr "ඔබගේ දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ සක්â€à¶»à·’ය කර ඇත. ඔබට පහත විස්තර බà·à¶½à·“මට à·„à·à¶šà·’ය."
msgid "SuperSonics|current subscription"
-msgstr ""
+msgstr "වත්මන් දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º"
msgid "SuperSonics|future subscriptions"
-msgstr ""
+msgstr "අනà·à¶œà¶­ දà·à¶ºà¶šà¶­à·Šà·€"
msgid "SuperSonics|past subscriptions"
-msgstr ""
+msgstr "පසුගිය දà·à¶ºà¶šà¶­à·Šà·€"
msgid "Superscript"
msgstr "උඩකුර"
@@ -37791,61 +38210,58 @@ msgid "Support"
msgstr "සහà·à¶º"
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+msgstr "අභිරුචි සහතික සඳහ෠සහය අබලයි. එය සබල කිරීමට ඔබගේ පද්ධතියේ පරිපà·à¶½à¶šà¶œà·™à¶±à·Š අසන්න."
msgid "Support page URL"
-msgstr ""
-
-msgid "Survey Response"
-msgstr ""
+msgstr "සහà·à¶º පිටුවේ ඒ.à·ƒ.නි."
msgid "Surveys|Delighted"
-msgstr ""
+msgstr "ප්â€à¶»à·“තියි"
msgid "Surveys|Happy"
-msgstr ""
+msgstr "සතුටුයි"
msgid "Surveys|Neutral"
-msgstr ""
+msgstr "මධ්â€à¶ºà·ƒà·Šà¶®"
msgid "Surveys|Sad"
-msgstr ""
+msgstr "දුකයි"
msgid "Surveys|Unhappy"
-msgstr ""
+msgstr "අසතුටුයි"
msgid "Switch Branches"
-msgstr ""
+msgstr "à·à·à¶›à· මà·à¶»à·”à·€"
msgid "Switch branch"
-msgstr ""
+msgstr "à·à·à¶›à·à·€ මà·à¶»à·”à·€"
msgid "Switch branch/tag"
-msgstr ""
+msgstr "à·à·à¶›à·à·€/අනන්â€à¶ºà¶±à¶º මà·à¶»à·”à·€"
msgid "Switch to GitLab Next"
msgstr "ගිට්ලà·à¶¶à·Š නෙක්â€à·ƒà·Šà¶§à·Š මà·à¶»à·”à·€"
msgid "Switch to the source to copy the file contents"
-msgstr ""
+msgstr "ගොනු අන්තර්ගතයෙහි පිටපතකට මූලà·à·à·Šâ€à¶»à¶º වෙත මà·à¶»à·”à·€"
msgid "Symbolic link"
msgstr ""
msgid "Sync LDAP"
-msgstr ""
+msgstr "LDAP සමමුහූර්තය"
msgid "Sync now"
-msgstr ""
+msgstr "සමමුහූර්ත කරන්න"
msgid "Synced"
-msgstr ""
+msgstr "සමමුහූර්තයි"
msgid "Synchronize LDAP"
-msgstr ""
+msgstr "LDAP සමමුහූර්තය"
msgid "Syncing…"
-msgstr ""
+msgstr "සමමුහූර්ත වෙමින් "
msgid "Syntax is correct."
msgstr ""
@@ -37854,16 +38270,16 @@ msgid "Syntax is incorrect."
msgstr ""
msgid "SynthaxHighlightingTheme|Dark"
-msgstr ""
+msgstr "අඳුරු"
msgid "SynthaxHighlightingTheme|Light"
-msgstr ""
+msgstr "දීප්ත"
msgid "SynthaxHighlightingTheme|Monokai"
msgstr "මොනොකà·à¶ºà·’"
msgid "SynthaxHighlightingTheme|None"
-msgstr ""
+msgstr "කිසිත් නà·à¶­"
msgid "SynthaxHighlightingTheme|Solarized Dark"
msgstr ""
@@ -37872,7 +38288,7 @@ msgid "SynthaxHighlightingTheme|Solarized Light"
msgstr ""
msgid "System"
-msgstr ""
+msgstr "පද්ධතිය"
msgid "System Hooks"
msgstr ""
@@ -37881,13 +38297,13 @@ msgid "System Hooks Help"
msgstr ""
msgid "System Info"
-msgstr ""
+msgstr "පද්ධතියේ තොරතුරු"
msgid "System default (%{default})"
-msgstr ""
+msgstr "පද්ධතියේ පෙරනිමි (%{default})"
msgid "System header and footer"
-msgstr ""
+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 ""
@@ -37899,13 +38315,16 @@ msgid "System metrics (Kubernetes)"
msgstr ""
msgid "System output"
+msgstr "පද්ධතියේ ප්â€à¶»à¶­à·’දà·à¶±à¶º"
+
+msgid "System started"
msgstr ""
msgid "Table of Contents"
-msgstr ""
+msgstr "පටුන"
msgid "Table of contents"
-msgstr ""
+msgstr "පටුන"
msgid "Tag"
msgstr "අනන්â€à¶ºà¶±à¶º"
@@ -37914,10 +38333,10 @@ msgid "Tag list:"
msgstr ""
msgid "Tag name"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶ºà·š නම"
msgid "Tag name is required."
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶ºà·š නම ඇවà·à·ƒà·’ය."
msgid "Tag push"
msgstr ""
@@ -37929,7 +38348,7 @@ msgid "Tag this commit."
msgstr ""
msgid "Tag:"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶º:"
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
msgstr ""
@@ -37953,7 +38372,7 @@ msgid "Tags this commit to %{tag_name}."
msgstr ""
msgid "Tags:"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±:"
msgid "TagsPage|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this tag."
msgstr ""
@@ -37962,52 +38381,55 @@ msgid "TagsPage|Browse commits"
msgstr ""
msgid "TagsPage|Browse files"
-msgstr ""
+msgstr "ගොනු පිරික්සන්න"
msgid "TagsPage|Can't find HEAD commit for this tag"
msgstr ""
msgid "TagsPage|Cancel"
-msgstr ""
+msgstr "අවලංගු"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
-msgid "TagsPage|Create tag"
+msgid "TagsPage|Create release"
msgstr ""
+msgid "TagsPage|Create tag"
+msgstr "අනන්â€à¶ºà¶±à¶º à·ƒà·à¶¯à¶±à·Šà¶±"
+
msgid "TagsPage|Delete protected tag"
-msgstr ""
+msgstr "රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶º මකන්න"
msgid "TagsPage|Delete protected tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶º මකන්න. ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "TagsPage|Delete tag"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶º මකන්න"
msgid "TagsPage|Delete tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶º මකන්න. ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "%{strongStart}%{tagName}%{strongEnd} අනන්â€à¶ºà¶±à¶º මක෠දà·à¶¸à·“ම අප්â€à¶»à¶­à·’වර්ත්â€à¶ºà¶ºà·’. ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr ""
msgid "TagsPage|Filter by tag name"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶±à¶º අනුව පෙරන්න"
msgid "TagsPage|New Tag"
-msgstr ""
+msgstr "නව අනන්â€à¶ºà¶±à¶º"
msgid "TagsPage|New tag"
-msgstr ""
+msgstr "නව අනන්â€à¶ºà¶±à¶º"
msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ නඩත්තුකරුවෙකුට හ෠හිමිකරුවෙකුට පමණක් රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶ºà¶šà·Š මක෠දà·à¶¸à·’ය à·„à·à¶šà·’ය"
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
msgstr ""
@@ -38016,85 +38438,82 @@ msgid "TagsPage|Optionally, create a public Release of your project, based on th
msgstr ""
msgid "TagsPage|Please type the following to confirm:"
-msgstr ""
+msgstr "තහවුරු කිරීමට පහත දෙය ලියන්න:"
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "නිකුතු සටහන්"
msgid "TagsPage|Repository has no tags yet."
-msgstr ""
+msgstr "කà·à·‚්ඨයෙහි තවම අනන්â€à¶ºà¶± නà·à¶­."
msgid "TagsPage|Sorry, your filter produced no results."
msgstr ""
msgid "TagsPage|Tags"
-msgstr ""
+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 ""
+msgstr "මෙම අනන්â€à¶ºà¶ºà·™à·„à·’ කිසිදු නිකුතු සටහනක් නà·à¶­."
msgid "TagsPage|Unable to load tags"
-msgstr ""
+msgstr "අනන්â€à¶ºà¶± පූරණය කිරීමට නොහà·à¶šà·’ය"
msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "ඔබගේ නිකුතු සටහන් ලියන්න හ෠ගොනු මෙතà·à¶±à¶§ අදින්න…"
msgid "TagsPage|Yes, delete protected tag"
-msgstr ""
+msgstr "ඔව්, රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶º මකන්න"
msgid "TagsPage|Yes, delete tag"
-msgstr ""
+msgstr "ඔව්, අනන්â€à¶ºà¶±à¶º මකන්න"
msgid "TagsPage|You're about to permanently delete the protected tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "ඔබ රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶º %{strongStart}%{tagName}%{strongEnd} සදහටම මà·à¶šà·“මට සූදà·à¶±à¶¸à·Š වේ."
msgid "TagsPage|You're about to permanently delete the tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "ඔබ රක්â€à·‚ිත අනන්â€à¶ºà¶±à¶º %{strongStart}%{tagName}%{strongEnd} සදහටම මà·à¶šà·“මට සූදà·à¶±à¶¸à·Š වේ."
msgid "TagsPage|protected"
-msgstr ""
+msgstr "රක්â€à·‚ිතයි"
msgid "Take a look at the documentation to discover all of GitLab’s capabilities."
msgstr ""
msgid "Target Branch"
-msgstr ""
+msgstr "ඉලක්කගත à·à·à¶›à·à·€"
msgid "Target Path"
-msgstr ""
+msgstr "ඉලක්කගත මà·à¶»à·Šà¶œà¶º"
msgid "Target branch"
-msgstr ""
+msgstr "ඉලක්කගත à·à·à¶›à·à·€"
msgid "Target branch or tag"
-msgstr ""
+msgstr "ඉලක්කගත à·à·à¶›à·à·€/අනන්â€à¶ºà¶±à¶º"
msgid "Target roles"
-msgstr ""
+msgstr "ඉලක්කගත භූමිකà·"
msgid "Target-Branch"
-msgstr ""
+msgstr "ඉලක්කගත-à·à·à¶›à·à·€"
msgid "Task"
-msgstr ""
+msgstr "කà·à¶»à·Šà¶º"
msgid "Task ID: %{elastic_task}"
-msgstr ""
+msgstr "කà·à¶»à·Šà¶º à·„à·à¶³à·”.: %{elastic_task}"
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’යකට (කà·à·‚්ඨය) කේත ආයà·à¶­/à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
msgstr ""
@@ -38103,10 +38522,10 @@ msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor
msgstr ""
msgid "Team"
-msgstr ""
+msgstr "කණ්ඩà·à¶ºà¶¸"
msgid "Team domain"
-msgstr ""
+msgstr "කණ්ඩà·à¶ºà¶¸à·š වසම"
msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
msgstr ""
@@ -38115,10 +38534,10 @@ msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repositor
msgstr ""
msgid "Telephone number"
-msgstr ""
+msgstr "දුරකථන අංකය"
msgid "Template"
-msgstr ""
+msgstr "අච්චුව"
msgid "Template to append to all Service Desk issues"
msgstr ""
@@ -38127,7 +38546,7 @@ msgid "TemplateRepository|Create common files more quickly, and standardize thei
msgstr ""
msgid "Templates"
-msgstr ""
+msgstr "අච්චු"
msgid "TemporaryStorageIncrease|can only be set once"
msgstr ""
@@ -38142,7 +38561,7 @@ msgid "TemporaryStorage|Increase storage temporarily"
msgstr ""
msgid "TemporaryStorage|Temporarily increase storage now?"
-msgstr ""
+msgstr "දà·à¶±à·Š ආචයනය තà·à·€à¶šà·à¶½à·’කව à·€à·à¶©à·’ කරන්නද?"
msgid "Terminal"
msgstr "අග්â€à¶»à¶º"
@@ -38175,7 +38594,7 @@ msgid "TerraformBanner|Using Terraform? Try the GitLab Managed Terraform State"
msgstr ""
msgid "Terraform|%{name} successfully removed"
-msgstr ""
+msgstr "%{name} à·ƒà·à¶»à·Šà¶®à¶šà·€ ඉවත් කෙරිණි"
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
@@ -38201,13 +38620,13 @@ msgid "Terraform|%{user} updated %{timeAgo}"
msgstr ""
msgid "Terraform|A Terraform report failed to generate."
-msgstr ""
+msgstr "ටෙරà·à·†à·à¶¸à·Š à·€à·à¶»à·Šà¶­à·à·€ උත්පà·à¶¯à¶±à¶ºà¶§ අසමත්!."
msgid "Terraform|A Terraform report was generated in your pipelines."
msgstr ""
msgid "Terraform|A report failed to generate."
-msgstr ""
+msgstr "à·€à·à¶»à·Šà¶­à·à·€à¶šà·Š උත්පà·à¶¯à¶±à¶ºà¶§ අසමත් විය."
msgid "Terraform|A report was generated in your pipelines."
msgstr ""
@@ -38258,10 +38677,10 @@ msgid "Terraform|Loading Terraform reports..."
msgstr ""
msgid "Terraform|Lock"
-msgstr ""
+msgstr "අගුල"
msgid "Terraform|Locked"
-msgstr ""
+msgstr "අගුළු ල෠ඇත"
msgid "Terraform|Locked by %{user} %{timeAgo}"
msgstr ""
@@ -38270,22 +38689,22 @@ msgid "Terraform|Locking state"
msgstr ""
msgid "Terraform|Name"
-msgstr ""
+msgstr "නම"
msgid "Terraform|Pipeline"
msgstr ""
msgid "Terraform|Remove"
-msgstr ""
+msgstr "ඉවතලන්න"
msgid "Terraform|Remove state file and versions"
-msgstr ""
+msgstr "තත්â€à·€ ගොනුව හ෠එහි අනුවà·à¶¯ ඉවත් කරන්න"
msgid "Terraform|Removed"
-msgstr ""
+msgstr "ඉවත් කෙරිණි"
msgid "Terraform|Removing"
-msgstr ""
+msgstr "ඉවත් වෙමින්"
msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
msgstr ""
@@ -38294,10 +38713,10 @@ msgid "Terraform|States"
msgstr ""
msgid "Terraform|Terraform init command"
-msgstr ""
+msgstr "ටෙරà·à·†à·à¶¸à·Š init විධà·à¶±à¶º"
msgid "Terraform|Terraform reports"
-msgstr ""
+msgstr "ටෙරà·à·†à·à¶¸à·Š à·€à·à¶»à·Šà¶­à·"
msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
@@ -38321,7 +38740,7 @@ msgid "Terraform|Unknown User"
msgstr "නොදන්න෠පරිà·à·“ලකයෙකි"
msgid "Terraform|Unlock"
-msgstr ""
+msgstr "අගුළු à·„à·à¶»à·“ම"
msgid "Terraform|Unlocking state"
msgstr ""
@@ -38330,10 +38749,10 @@ msgid "Terraform|You are about to remove the state file %{name}. This will perma
msgstr ""
msgid "Terraform|You have insufficient permissions to delete this state"
-msgstr ""
+msgstr "මෙම තත්â€à·€à¶º මක෠දà·à¶¸à·“මට ඔබට ප්â€à¶»à¶¸à·à¶«à·€à¶­à·Š අවසර නà·à¶­"
msgid "Terraform|Your project doesn't have any Terraform state files"
-msgstr ""
+msgstr "ඔබගේ ව්â€à¶ºà·à¶´à·˜à¶­à·’යට ටෙරà·à·†à·à¶¸à·Š තත්â€à·€ ගොනු කිසිවක් නà·à¶­"
msgid "Test"
msgstr ""
@@ -38427,19 +38846,19 @@ msgid "TestHooks|Ensure the wiki is enabled and has pages."
msgstr ""
msgid "TestReports|%{count} errors"
-msgstr ""
+msgstr "දà·à·‚ %{count}"
msgid "TestReports|%{count} failures"
-msgstr ""
+msgstr "අසමත් වීම් %{count}"
msgid "TestReports|%{count} tests"
-msgstr ""
+msgstr "අත්හද෠බà·à¶½à·“ම් %{count}"
msgid "TestReports|%{rate}%{sign} success rate"
msgstr ""
msgid "TestReports|Attachment"
-msgstr ""
+msgstr "ඇමුණුම"
msgid "TestReports|Copy test name to rerun locally"
msgstr ""
@@ -38463,7 +38882,7 @@ msgid "TestReports|Test reports require job artifacts but all artifacts are expi
msgstr ""
msgid "TestReports|Tests"
-msgstr ""
+msgstr "අත්හද෠බà·à¶½à·“ම්"
msgid "TestReports|There are no test cases to display."
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr "පෙළ à·à·›à¶½à·’ය"
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr "ඔබගේ ප්â€à¶»à¶­à·’පà·à·‚ණයට ස්තූතියි!"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "ඔබගේ à·€à·à¶»à·Šà¶­à·à·€à¶§ ස්තූතියි. ගිට්ලà·à¶¶à·Š පරිපà·à¶½à¶šà¶ºà·™à¶šà·” විසින් එය සොය෠බලනු ඇත."
@@ -38705,13 +39121,13 @@ 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 "පහත SSH යතුර පරිපà·à¶½à¶šà¶ºà·™à¶šà·” විසින් මක෠දà·à¶¸à·’ණි, %{username}."
msgid "The following items will NOT be exported:"
-msgstr ""
+msgstr "පහත අංග නිර්යà·à¶­ නොකෙරේ:"
msgid "The following items will be exported:"
-msgstr ""
+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."
@@ -38730,10 +39146,10 @@ msgid "The form contains the following warning:"
msgstr ""
msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
-msgstr ""
+msgstr "ගිට් සේවà·à¶¯à·à¶ºà¶šà¶º, ගිටලි, මේ මොහොතේ නà·à¶­. ඔබගේ පරිපà·à¶½à¶š අමතන්න."
msgid "The global settings require you to enable Two-Factor Authentication for your account."
-msgstr ""
+msgstr "ඔබගේ ගිණුම සඳහ෠ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º සබල කිරීමට ගà·à¶½à·“ය à·ƒà·à¶šà·ƒà·”ම් අවà·à·Šâ€à¶º වේ."
msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
@@ -38745,10 +39161,10 @@ msgid "The group and its projects can only be viewed by members."
msgstr ""
msgid "The group export can be downloaded from:"
-msgstr ""
+msgstr "සමූහයේ නිර්යà·à¶­ බà·à¶œà·à¶±à·“මට:"
msgid "The group has already been shared with this group"
-msgstr ""
+msgstr "සමූහය දà·à¶±à¶§à¶¸à¶­à·Š මෙම සමූහය සමඟ බෙදà·à¶œà·™à¶± ඇත"
msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38883,13 +39296,13 @@ msgid "The parent epic is confidential and can only contain confidential epics a
msgstr ""
msgid "The password for the Jenkins server."
-msgstr ""
+msgstr "ජෙන්කින්ස් සේවà·à¶¯à·à¶ºà¶šà¶º සඳහ෠මුරපදය."
msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
-msgstr ""
+msgstr "%{gitlab_url} à·„à·’ ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුම සඳහ෠මුරපදය à·ƒà·à¶»à·Šà¶®à¶šà·€ වෙනස් කර ඇත."
msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
-msgstr ""
+msgstr "%{link_to_gitlab} à·„à·’ ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුම සඳහ෠මුරපදය à·ƒà·à¶»à·Šà¶®à¶šà·€ වෙනස් කර ඇත."
msgid "The pipeline has been deleted"
msgstr ""
@@ -38898,16 +39311,16 @@ msgid "The pipelines schedule runs pipelines in the future, repeatedly, for spec
msgstr ""
msgid "The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "බà·à·„ිර පුද්ගලයින්ට à·„à·à¶» ඇතුළු වූ ඕනෑම අයෙකුට ව්â€à¶ºà·à¶´à·˜à¶­à·’යට ප්â€à¶»à·€à·šà· විය à·„à·à¶šà·’ය."
msgid "The project can be accessed without any authentication."
-msgstr ""
+msgstr "කිසිදු සත්â€à¶ºà·à¶´à¶±à¶ºà¶šà·’න් තොරව ව්â€à¶ºà·à¶´à·˜à¶­à·’යට ප්â€à¶»à·€à·šà· විය à·„à·à¶šà·’ය."
msgid "The project has already been added to your dashboard."
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය දà·à¶±à¶§à¶¸à¶­à·Š ඔබගේ උපකරණ පුවරුවට එක් කර ඇත."
msgid "The project is still being deleted. Please try again later."
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය තවමත් මà·à¶šà·™à¶¸à·’න් පවතී. පසුව බලන්න."
msgid "The project size exceeds the export limit."
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’යේ ප්â€à¶»à¶¸à·à¶«à¶º නිර්යà·à¶­ සීමà·à·€ ඉක්මවයි."
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr "වෙනස්කම් නà·à¶­"
@@ -39120,7 +39539,7 @@ msgid "There are no projects shared with this group yet"
msgstr "මෙම සමූහය සමග තවම බෙද෠ගත් ව්â€à¶ºà·à¶´à·˜à¶­à·’ නà·à¶­"
msgid "There are no secure files yet."
-msgstr ""
+msgstr "තවම ආරක්â€à·‚ිත ගොනු නà·à¶­."
msgid "There are no topics to show."
msgstr "පෙන්වීමට මà·à¶­à·˜à¶šà· නà·à¶­."
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "තà·à¶§à·’යේ එම නම සහිත කà·à·‚්ඨයක් දà·à¶±à¶§à¶¸à¶­à·Š ඇත"
@@ -39168,10 +39590,10 @@ msgid "There was a problem communicating with your device."
msgstr ""
msgid "There was a problem fetching CRM contacts."
-msgstr ""
+msgstr "CRM සබඳත෠ගà·à¶±à·“මේ ගà·à¶§à¶½à·”වකි."
msgid "There was a problem fetching CRM organizations."
-msgstr ""
+msgstr "CRM සංවිධà·à¶± ගà·à¶±à·“මේ ගà·à¶§à¶½à·”වකි."
msgid "There was a problem fetching branches."
msgstr "à·à·à¶›à· ගà·à¶±à·“මේ දී ගà·à¶§à¶½à·”වකි."
@@ -39242,9 +39664,6 @@ msgstr "තහවුරු කිරීමේ වි-තà·à¶´à·‘ල යà·à·€à·
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr "කළ යුතු දෙයක් එකතු කිරීමේදී දà·à·‚යකි."
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "වි-තà·à¶´à·‘ල ඉවත් කිරීමේදී දà·à·‚යකි."
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39336,7 +39752,7 @@ msgid "There was an error saving your changes."
msgstr "ඔබගේ වෙනස්කම් සුරà·à¶šà·“මේ දà·à·‚යකි."
msgid "There was an error subscribing to this label."
-msgstr ""
+msgstr "මෙම නම්පතට දà·à¶ºà¶š වීමේ දà·à·‚යක් ඇති විය."
msgid "There was an error syncing project %{name}"
msgstr "%{name} ව්â€à¶ºà·à¶´à·˜à¶­à·’ය සමමුහූර්ත වීමේ දà·à·‚යකි"
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39537,7 +39950,7 @@ msgid "This content could not be displayed because it is stored in LFS. You can
msgstr ""
msgid "This credential has expired"
-msgstr ""
+msgstr "මෙම අක්තපත්â€à¶»à¶º කල් ඉකුත්ය"
msgid "This deployment is not waiting for approvals."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39909,7 +40325,7 @@ msgid "This project path either does not exist or you do not have access."
msgstr ""
msgid "This project will be deleted on %{date}"
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය %{date} දී මකනු ඇත"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
msgstr ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "මෙම කà·à·‚්ඨය"
@@ -40083,7 +40505,7 @@ msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
msgstr ""
msgid "TimeTracking|An error occurred while removing the timelog."
-msgstr ""
+msgstr "වේල෠සටහන ඉවත් කිරීමේදී දà·à·‚යක් ඇති විය."
msgid "TimeTracking|Delete time spent"
msgstr ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40444,7 +40866,7 @@ msgid "To set up SAML authentication for your group through an identity provider
msgstr ""
msgid "To set up this integration:"
-msgstr ""
+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 ""
@@ -40623,6 +41045,9 @@ msgstr "බොහ෠පරිà·à·“ලකයින් හමු විය. ඉà
msgid "TopNav|Go back"
msgstr "ආපසු යන්න"
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40639,7 +41064,7 @@ msgid "Topic slug (name)"
msgstr ""
msgid "Topic title"
-msgstr ""
+msgstr "මà·à¶­à·˜à¶šà·à·€à·š සිරà·à·ƒà·’ය"
msgid "Topic was successfully updated."
msgstr "මà·à¶­à·˜à¶šà·à·€ à·ƒà·à¶»à·Šà¶®à¶šà·€ යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි."
@@ -40651,7 +41076,7 @@ msgid "Total"
msgstr "මුළු"
msgid "Total Contributions"
-msgstr "මුළු දà·à¶ºà¶šà¶­à·Šà·€"
+msgstr "මුළු දà·à¶ºà¶šà¶­à·Šâ€à·€"
msgid "Total Score"
msgstr "මුළු ලකුණු"
@@ -40702,52 +41127,52 @@ msgid "Training mode"
msgstr ""
msgid "Transfer"
-msgstr ""
+msgstr "මà·à¶»à·”à·€"
msgid "Transfer group to another parent group."
-msgstr ""
+msgstr "සමූහය වෙනත් මව් සමූහයකට මà·à¶»à·” කරන්න."
msgid "Transfer ownership"
-msgstr ""
+msgstr "අයිතිය පà·à·€à¶»à·“ම"
msgid "Transfer project"
-msgstr ""
+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 ""
+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 ""
+msgstr "දත්ත සමුදà·à¶º සහà·à¶º නොදක්වයි."
msgid "TransferGroup|Group contains contacts/organizations and you don't have enough permissions to move them to the new root group."
-msgstr ""
+msgstr "සමූහයේ සබඳතà·/සංවිධà·à¶± අඩංගු වන අතර ඔබට ඒව෠නව මූල සමූහයකට ගෙන යà·à¶¸à¶§ ප්â€à¶»à¶¸à·à¶«à·€à¶­à·Š අවසර නà·à¶­."
msgid "TransferGroup|Group contains projects with NPM packages."
-msgstr ""
+msgstr "NPM ඇසුරුම් සහිත ව්â€à¶ºà·à¶´à·˜à¶­à·’ සමූහයේ අඩංගු වේ."
msgid "TransferGroup|Group is already a root group."
-msgstr ""
+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 ""
+msgstr "මව් සමූහයේ දà·à¶±à¶§à¶¸à¶­à·Š උප සමූහයක් හ෠එම මà·à¶»à·Šà¶œà¶ºà¶¸ සහිත ව්â€à¶ºà·à¶´à·˜à¶­à·’යක් ඇත."
msgid "TransferGroup|Transfer failed: %{error_message}"
-msgstr ""
+msgstr "මà·à¶»à·” කිරීමට අසමත් විය: %{error_message}"
msgid "TransferGroup|You don't have enough permissions."
-msgstr ""
+msgstr "ඔබට ප්â€à¶»à¶¸à·à¶«à·€à¶­à·Š අවසර නà·à¶­."
msgid "TransferProject|Cannot move project"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය ගෙනයà·à¶¸à¶§ නොහà·à¶šà·’ය"
msgid "TransferProject|Please select a new namespace for your project."
msgstr ""
@@ -40768,7 +41193,7 @@ msgid "TransferProject|You don't have permission to transfer projects into that
msgstr ""
msgid "TransferProject|You don't have permission to transfer this project."
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය මà·à¶»à·” කිරීමට ඔබට අවසර නà·à¶­."
msgid "Tree view"
msgstr "à·à·à¶›à·“ය දà·à¶šà·Šà¶¸"
@@ -40786,7 +41211,7 @@ msgid "Trials|Create a new group to start your GitLab Ultimate trial."
msgstr ""
msgid "Trials|Day %{daysUsed}/%{duration}"
-msgstr ""
+msgstr "දවස් %{daysUsed}/%{duration}"
msgid "Trials|Go back to GitLab"
msgstr "ගිට්ලà·à¶¶à·Š වෙත ආපසු යන්න"
@@ -40927,6 +41352,9 @@ 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"
@@ -40972,40 +41400,40 @@ msgid "Twitter:"
msgstr "ට්විටර්:"
msgid "Two-Factor Authentication"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º"
msgid "Two-Factor Authentication code"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶± කේතය"
msgid "Two-factor Authentication"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º"
msgid "Two-factor Authentication Recovery codes"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶± ප්â€à¶»à¶­à·’à·ƒà·à¶°à¶± කේත"
msgid "Two-factor Authentication:"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º:"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º"
msgid "Two-factor authentication disabled"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º අබල කර ඇත"
msgid "Two-factor authentication grace period"
msgstr ""
msgid "Two-factor authentication has been disabled for this user"
-msgstr ""
+msgstr "මෙම පුද්ගලය෠සඳහ෠ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º අබල කර ඇත"
msgid "Two-factor authentication has been disabled for your GitLab account."
-msgstr ""
+msgstr "ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුම සඳහ෠ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º අබල කර ඇත."
msgid "Two-factor authentication has been disabled successfully!"
-msgstr ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º à·ƒà·à¶»à·Šà¶®à¶šà·€ අබල කර ඇත!"
msgid "Two-factor authentication is not enabled for this user"
-msgstr ""
+msgstr "මෙම පුද්ගලය෠සඳහ෠ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶±à¶º සබල කර නà·à¶­"
msgid "Two-factor grace period"
msgstr ""
@@ -41013,11 +41441,14 @@ msgstr ""
msgid "Type"
msgstr "වර්ගය"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "U2F උපà·à¶‚ග (%{length})"
msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
-msgstr ""
+msgstr "U2F ක්â€à¶»à·’ය෠කරන්නේ HTTPS-සබල වියමන අඩවි සමඟ පමණි. à·€à·à¶©à·’ විස්තර සඳහ෠පරිපà·à¶½à¶š අමතන්න."
msgid "URL"
msgstr "ඒ.ස.නි."
@@ -41044,10 +41475,10 @@ msgid "URL is triggered when repository is updated"
msgstr ""
msgid "URL must be percent-encoded if necessary."
-msgstr ""
+msgstr "අවà·à·Šâ€à¶º නම් ඒ.à·ƒ.නි. ප්â€à¶»à¶­à·’à·à¶­-ආකේතිත විය යුතුය."
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
-msgstr ""
+msgstr "ඒ.ස.නි. %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, හ෠%{codeStart}ftp://%{codeEnd} සමඟ ආරම්භ විය යුතුය"
msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
msgstr ""
@@ -41062,22 +41493,22 @@ msgid "URL or request ID"
msgstr "ඒ.à·ƒ.නි. / ඉල්ලීම් à·„à·à¶³à·”."
msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "පරිà·à·“ලක %{user_name} ඉවත් කරනු ලà·à¶¶à·š! ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "USER %{user} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "පරිà·à·“ලක %{user} ඉවත් කරනු ලà·à¶¶à·š! ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "USER WILL BE BLOCKED! Are you sure?"
-msgstr ""
+msgstr "පරිà·à·“ලකය෠අවහිර කරනු ඇත! ඔබට විà·à·Šà·€à·à·ƒà¶¯?"
msgid "UTC"
msgstr ""
msgid "Unable to apply suggestions to a deleted line."
-msgstr ""
+msgstr "මක෠දà·à¶¸à·– රේඛà·à·€à¶šà¶§ යà·à¶¢à¶±à· යෙදිය නොහà·à¶šà·’ය."
msgid "Unable to build Slack link."
-msgstr ""
+msgstr "ස්ලà·à¶šà·Š සබà·à¶³à·’ය තà·à¶±à·“මට නොහà·à¶šà·’ය."
msgid "Unable to collect CPU info"
msgstr "CPU තොරතුරු රà·à·ƒà·Š කළ නොහà·à¶šà·’ය"
@@ -41107,7 +41538,7 @@ msgid "Unable to fetch upstream and downstream pipelines."
msgstr ""
msgid "Unable to find Jira project to import data from."
-msgstr ""
+msgstr "දත්ත ආයà·à¶­à¶ºà¶§ ජිර෠ව්â€à¶ºà·à¶´à·˜à¶­à·’ය සොය෠ගà·à¶±à·“මට නොහà·à¶šà·’යි."
msgid "Unable to fully load the default commit message. You can still apply this suggestion and the commit message will be correct."
msgstr ""
@@ -41119,13 +41550,13 @@ msgid "Unable to load commits. Try again later."
msgstr ""
msgid "Unable to load file contents. Try again later."
-msgstr ""
+msgstr "ගොනුවේ අන්තර්ගතය පූරණය කළ නොහà·à¶šà·’ය. පසුව බලන්න."
msgid "Unable to load refs"
msgstr ""
msgid "Unable to load the diff"
-msgstr ""
+msgstr "වෙනස පූරණය කළ නොහà·à¶šà·’ය"
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41140,10 +41574,10 @@ msgid "Unable to save iteration. Please try again"
msgstr ""
msgid "Unable to save your changes. Please try again."
-msgstr ""
+msgstr "ඔබගේ වෙනස්කම් සුරà·à¶šà·“මට නොහà·à¶šà·’ය. යළි බලන්න."
msgid "Unable to save your preference"
-msgstr ""
+msgstr "ඔබගේ මනà·à¶´à¶º සුරà·à¶šà·“මට නොහà·à¶šà·’ය"
msgid "Unable to schedule a pipeline to run immediately"
msgstr ""
@@ -41152,7 +41586,7 @@ 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 ""
+msgstr "මà·à¶»à·Šà¶œà¶ºà¶šà·Š යà·à¶¢à¶±à· කළ නොහà·à¶šà·’ය. නà·à·€à·”ම් කර බලන්න."
msgid "Unable to update label prioritization at this time"
msgstr ""
@@ -41164,7 +41598,7 @@ msgid "Unable to update this issue at this time."
msgstr ""
msgid "Unable to verify the user"
-msgstr ""
+msgstr "පුද්ගලය෠තහවුරු කළ නොහà·à¶šà·’ය"
msgid "Unapprove a merge request"
msgstr ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr "නොදන්න෠ආකෘතියකි"
msgid "Unknown response text"
msgstr "නොදන්න෠ප්â€à¶»à¶­à·’චà·à¶» පෙළ"
-msgid "Unknown screen"
-msgstr "නොදන්න෠තිරය"
-
msgid "Unknown user"
msgstr "නොදන්න෠පරිà·à·“ලකයෙකි"
@@ -41263,7 +41697,7 @@ msgid "Unlock account"
msgstr "ගිණුම අගුළු හරින්න"
msgid "Unlock merge request"
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීම අගුළු à·„à·à¶»à·“ම"
msgid "Unlock more features with GitLab Ultimate"
msgstr ""
@@ -41362,19 +41796,19 @@ msgid "Update Now"
msgstr "දà·à¶±à·Š යà·à·€à¶­à·Šà¶šà·à¶½ කරන්න"
msgid "Update Scheduled…"
-msgstr ""
+msgstr "යà·à·€à¶­à·Šà¶šà·à¶½à¶º කල්තà·à¶¶à·’ණි…"
msgid "Update all"
msgstr "සියල්ල යà·à·€à¶­à·Šà¶šà·à¶½ කරන්න"
msgid "Update appearance settings"
-msgstr ""
+msgstr "පෙනුම à·ƒà·à¶šà·ƒà·”ම් යà·à·€à¶­à·Šà¶šà·à¶½à¶º"
msgid "Update approval rule"
msgstr ""
msgid "Update approvers"
-msgstr ""
+msgstr "අනුමතකරුවන් යà·à·€à¶­à·Šà¶šà·à¶½à¶º"
msgid "Update broadcast message"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr "යà·à·€à¶­à·Šà¶šà·à¶½ කළ දිනය"
msgid "Updating"
msgstr "යà·à·€à¶­à·Šà¶šà·à¶½ වෙමින්"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr "යà·à·€à¶­à·Šà¶šà·à¶½ වෙමින්…"
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "ගොනුව උඩුගත කරන්න"
@@ -41490,9 +41924,6 @@ msgstr "උඩුගත වෙමින්..."
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41509,7 +41940,7 @@ msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there ar
msgstr ""
msgid "UsageQuota|%{linkTitle} help link"
-msgstr ""
+msgstr "උදව් සබà·à¶³à·’ය %{linkTitle}"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr "පරà·à¶ºà¶­à·Šà¶­ ප්â€à¶»à¶­à·’යුක්තය"
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41572,13 +42003,13 @@ msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other ite
msgstr ""
msgid "UsageQuota|Increase storage temporarily"
-msgstr ""
+msgstr "තà·à·€à¶šà·à¶½à·’කව ආචයනය à·€à·à¶©à·’ කරන්න"
msgid "UsageQuota|LFS storage"
msgstr "LFS ආචයනය"
msgid "UsageQuota|Learn more about excess storage usage"
-msgstr ""
+msgstr "අතිරික්ත ආචයන භà·à·€à·’තය ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±"
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
@@ -41599,7 +42030,7 @@ msgid "UsageQuota|Packages"
msgstr "ඇසුරුම්"
msgid "UsageQuota|Pending Members"
-msgstr ""
+msgstr "පොරොත්තු à·ƒà·à¶¸à·à¶¢à·’කයින්"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -41608,16 +42039,16 @@ msgid "UsageQuota|Pipelines"
msgstr ""
msgid "UsageQuota|Purchase more storage"
-msgstr ""
+msgstr "තව ආචයන මිලදී ගන්න"
msgid "UsageQuota|Purchased storage"
msgstr "මිලදී ගත් ආචයනය"
msgid "UsageQuota|Purchased storage available"
-msgstr ""
+msgstr "මිලදී ගත් ආචයනය තිබේ"
msgid "UsageQuota|Purchased storage used"
-msgstr ""
+msgstr "මිලදී ගත් ආචයනය භà·à·€à·’ත෠කර ඇත"
msgid "UsageQuota|Recalculate repository usage"
msgstr ""
@@ -41626,6 +42057,9 @@ msgid "UsageQuota|Repository"
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."
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41701,7 +42147,7 @@ msgid "UsageQuota|Usage breakdown"
msgstr ""
msgid "UsageQuota|Usage by month"
-msgstr ""
+msgstr "මà·à·ƒà¶º අනුව භà·à·€à·’තය"
msgid "UsageQuota|Usage by project"
msgstr ""
@@ -41734,13 +42180,13 @@ msgid "UsageQuota|You have consumed all of your additional storage, please purch
msgstr ""
msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
-msgstr ""
+msgstr "%{projectsLockedText} à·„à·’ %{actualRepositorySizeLimit} නොමිලේ ආචයන සීමà·à·€à¶§ ඔබ ළඟ෠වී ඇත. ඒව෠අගුලු à·„à·à¶»à·“මට, අතිරේක ආචයනය මිලදී ගන්න."
msgid "UsageQuota|You used: %{usage} %{limit}"
-msgstr ""
+msgstr "ඔබගේ භà·à·€à·’තය: %{usage} %{limit}"
msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
-msgstr ""
+msgstr "ඔබ මිලදී ගත් ආචයනය අඩු වෙමින් පවතී. ව්â€à¶ºà·à¶´à·˜à¶­à·’ අගුලු à·€à·à¶§à·“ම à·€à·à·…à·à¶šà·Šà·€à·“මට, තවත් ආචයනය මිලදී ගන්න."
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
msgstr ""
@@ -41917,7 +42363,7 @@ msgid "Use webhook"
msgstr ""
msgid "Use your global notification setting"
-msgstr ""
+msgstr "ගà·à¶½à·“ය දà·à¶±à·”ම්දීම් à·ƒà·à¶šà·ƒà·”ම භà·à·€à·’ත෠කරන්න"
msgid "Use your smart card to authenticate with the LDAP server."
msgstr ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -41932,7 +42383,7 @@ msgid "Used by more than 100,000 organizations, GitLab is the most popular solut
msgstr ""
msgid "Used programming language"
-msgstr ""
+msgstr "භà·à·€à·’ත෠කළ ක්â€à¶»à¶¸à¶½à·šà¶›à¶± භà·à·‚à·à·€"
msgid "Used to help configure your identity provider"
msgstr ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,11 +42580,14 @@ 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 "දà·à¶ºà¶šà¶­à·Šà·€à¶ºà¶§ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොය෠ගà·à¶±à·“මට ප්â€à¶»à·ƒà·’ද්ධ සමූහ ගවේෂණය කරන්න."
+msgstr "දà·à¶ºà¶šà¶­à·Šâ€à·€à¶ºà¶§ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සොය෠ගà·à¶±à·“මට ප්â€à¶»à·ƒà·’ද්ධ සමූහ ගවේෂණය කරන්න."
msgid "UserProfile|Followers"
msgstr ""
@@ -42145,7 +42602,7 @@ 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 ""
+msgstr "ගà·à¶§à·…à·” සඳහ෠අදහස් දà·à¶šà·Šà·€à·“මෙන් හ෠සංයුක්ත ඉල්ලීම් යොමු කිරීමෙන් දà·à¶ºà¶šà¶­à·Šâ€à·€à¶º ඇරඹීමට සමූහයකට එක්වන්න à·„à· à·ƒà·à¶¯à¶±à·Šà¶±!"
msgid "UserProfile|Most Recent Activity"
msgstr "වඩà·à¶­à·Šà¶¸ මෑත ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸"
@@ -42160,10 +42617,10 @@ msgid "UserProfile|Personal projects"
msgstr "පෞද්ගලික ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "UserProfile|Pronounced as: %{pronunciation}"
-msgstr ""
+msgstr "උච්චà·à¶»à¶«à¶º: %{pronunciation}"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "අයුතු à·€à·à¶»à·Šà¶­à·à·€"
msgid "UserProfile|Retry"
msgstr "යළි උත්සà·à·„ය"
@@ -42175,13 +42632,13 @@ 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 ""
+msgstr "ප්â€à¶»à¶œà¶­à·’ය නිරීක්â€à·‚ණයට හ෠ඔබගේ ඇගයීම පෙන්වීමට ව්â€à¶ºà·à¶´à·˜à¶­à·’වලට තරු යොදන්න."
msgid "UserProfile|Starred projects"
msgstr "තරු යෙදූ ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "UserProfile|Subscribe"
-msgstr ""
+msgstr "දà·à¶ºà¶š වන්න"
msgid "UserProfile|This user doesn't have any followers."
msgstr ""
@@ -42196,7 +42653,7 @@ msgid "UserProfile|This user hasn't contributed to any projects"
msgstr "මෙම පරිà·à·“ලකය෠කිසිදු ව්â€à¶ºà·à¶´à·˜à¶­à·’යකට දà·à¶ºà¶š වී නà·à¶­"
msgid "UserProfile|This user hasn't starred any projects"
-msgstr ""
+msgstr "මෙම පුද්ගලය෠කිසිදු ව්â€à¶ºà·à¶´à·˜à¶­à·’යකට තරු යොද෠නà·à¶­"
msgid "UserProfile|This user is blocked"
msgstr "මෙම පරිà·à·“ලකය෠අවහිර කර ඇත"
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr "තහවුරු නොකළ පරිà·à·“ලක"
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "සියල්ල දකින්න"
@@ -42235,7 +42695,7 @@ msgid "UserProfile|at"
msgstr ""
msgid "UserProfile|made a private contribution"
-msgstr ""
+msgstr "පෞද්. දà·à¶ºà¶šà¶­à·Šâ€à·€à¶ºà¶šà·Š ලබ෠දී ඇත"
msgid "Username"
msgstr "පරිà·à·“ලක නà·à¶¸à¶º"
@@ -42265,10 +42725,10 @@ 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 "%{linkStart}ගිට්පොඩ්%{linkEnd} අනුකලනය සබල කර ඇති විට පුද්ගලයින්ට ගිට්ලà·à¶¶à·Š අතිරික්සු පටිත්තකින් සංවර්ධන පරිසරයක් දියත් කළ à·„à·à¶šà·’ය."
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 ""
@@ -42295,13 +42755,13 @@ msgid "Users to exclude from the rate limit"
msgstr "අනුපà·à¶­ සීමà·à·€à·™à¶±à·Š බà·à·„à·à¶» කිරීමට පරිà·à·“ලකයින්"
msgid "Users were successfully added."
-msgstr ""
+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 ""
+msgstr "%{name} + තවත් %{length}"
msgid "UsersSelect|Any User"
msgstr "ඕනෑම පරිà·à·“ලකයෙකු"
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42384,7 +42839,7 @@ msgid "ValueStreamAnalytics|%{value}d"
msgstr ""
msgid "ValueStreamAnalytics|%{value}h"
-msgstr ""
+msgstr "පà·à¶º%{value}"
msgid "ValueStreamAnalytics|%{value}m"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42510,25 +42971,31 @@ msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD
msgstr ""
msgid "Verified"
-msgstr ""
+msgstr "තහවුරුයි"
msgid "Verify SAML Configuration"
msgstr ""
msgid "Verify code"
-msgstr ""
+msgstr "කේතය තහවුරුව"
msgid "Verify configuration"
-msgstr ""
+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 "අනුවà·à¶¯à¶º %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
-msgstr ""
+msgstr "අනුවà·à¶¯à¶º %{versionNumber} (නවතම)"
msgid "VersionCheck|Up to date"
msgstr "යà·à·€à¶­à·Šà¶šà·à¶½à·“නයි"
@@ -42759,7 +43226,7 @@ msgid "Visual Studio Code (HTTPS)"
msgstr ""
msgid "Visual Studio Code (SSH)"
-msgstr ""
+msgstr "විෂුවල් ස්ටුඩිය෠කà·à¶©à·Š (SSH)"
msgid "Vulnerabilities"
msgstr ""
@@ -42789,7 +43256,7 @@ msgid "VulnerabilityChart|%{formattedStartDate} to today"
msgstr ""
msgid "VulnerabilityChart|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -42831,25 +43298,25 @@ msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
msgid "VulnerabilityManagement|Enter a name"
-msgstr ""
+msgstr "නමක් යොදන්න"
msgid "VulnerabilityManagement|Enter the CVE or CWE code"
-msgstr ""
+msgstr "CVE හ෠CWE කේතය යොදන්න"
msgid "VulnerabilityManagement|Enter the CVE or CWE identifier URL"
-msgstr ""
+msgstr "CVE හ෠CWE හඳුන්වනයේ ඒ.ස.නි. යොදන්න"
msgid "VulnerabilityManagement|Fetching linked Jira issues"
msgstr ""
msgid "VulnerabilityManagement|Identifier code and URL are required fields"
-msgstr ""
+msgstr "හඳුන්වන කේතය හ෠ඒ.à·ƒ.නි. අවà·à·Šâ€à¶º ක්â€à·‚ේත්â€à¶» වේ"
msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Name is a required field"
-msgstr ""
+msgstr "නම අවà·à·Šâ€à¶º ක්â€à·‚ේත්â€à¶»à¶ºà¶šà·’"
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -42861,25 +43328,25 @@ msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
msgid "VulnerabilityManagement|Requires assessment"
-msgstr ""
+msgstr "තක්සේරුවක් අවà·à·Šâ€à¶º වේ"
msgid "VulnerabilityManagement|Select a method"
-msgstr ""
+msgstr "ක්â€à¶»à¶¸à¶ºà¶šà·Š තà·à¶»à¶±à·Šà¶±"
msgid "VulnerabilityManagement|Select a severity level"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à· මට්ටමක් තà·à¶»à¶±à·Šà¶±"
msgid "VulnerabilityManagement|Select a status"
-msgstr ""
+msgstr "තත්â€à·€à¶ºà¶šà·Š තà·à¶»à¶±à·Šà¶±"
msgid "VulnerabilityManagement|Severity is a required field"
-msgstr ""
+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 ""
+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 ""
@@ -42891,19 +43358,19 @@ msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the
msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
-msgstr ""
+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 ""
+msgstr "යම් දෙයක් à·€à·à¶»à¶¯à·“ ඇත, පරිà·à·“ලකය෠ගà·à¶±à·“මට නොහà·à¶šà·’ විය."
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
msgid "VulnerabilityManagement|Status is a required field"
-msgstr ""
+msgstr "තත්â€à·€à¶º යනු අවà·à·Šâ€à¶º ක්â€à·‚ේත්â€à¶»à¶ºà¶šà·’"
msgid "VulnerabilityManagement|Submit vulnerability"
msgstr ""
@@ -42927,7 +43394,7 @@ msgid "VulnerabilityStatusTypes|All statuses"
msgstr "සියළු තත්ව"
msgid "VulnerabilityStatusTypes|Confirmed"
-msgstr ""
+msgstr "තහවුරුයි"
msgid "VulnerabilityStatusTypes|Dismissed"
msgstr "ඉවත ලූ"
@@ -42951,7 +43418,7 @@ msgid "Vulnerability|Actual received response is the one received when this faul
msgstr ""
msgid "Vulnerability|Add another identifier"
-msgstr ""
+msgstr "අන් හඳුන්වනයක් යොදන්න"
msgid "Vulnerability|Additional Info"
msgstr "අතිරේක තොරතුරු"
@@ -42969,19 +43436,19 @@ msgid "Vulnerability|Cluster"
msgstr ""
msgid "Vulnerability|Code Review"
-msgstr ""
+msgstr "කේත සමà·à¶½à·à¶ à¶±à¶º"
msgid "Vulnerability|Comments"
msgstr "අදහස්"
msgid "Vulnerability|Crash address"
-msgstr ""
+msgstr "බිඳවà·à¶§à·“මේ ලිපිනය"
msgid "Vulnerability|Crash state"
-msgstr ""
+msgstr "බිඳවà·à¶§à·“මේ තත්â€à·€à¶º"
msgid "Vulnerability|Crash type"
-msgstr ""
+msgstr "බිඳවà·à¶§à·“මේ වර්ගය"
msgid "Vulnerability|Description"
msgstr "සවිස්තරය"
@@ -42990,10 +43457,10 @@ msgid "Vulnerability|Details"
msgstr "විස්තර"
msgid "Vulnerability|Detected"
-msgstr ""
+msgstr "අනà·à·€à¶»à¶«à¶º විය"
msgid "Vulnerability|Detection method"
-msgstr ""
+msgstr "අනà·à·€à¶»à¶« ක්â€à¶»à¶¸à¶º"
msgid "Vulnerability|Download"
msgstr "බà·à¶œà¶±à·Šà¶±"
@@ -43014,19 +43481,19 @@ msgid "Vulnerability|File"
msgstr "ගොනුව"
msgid "Vulnerability|GitLab Security Report"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š ආරක්â€à·‚ණ à·€à·à¶»à·Šà¶­à·à·€"
msgid "Vulnerability|Identifier"
-msgstr ""
+msgstr "හඳුන්වනය"
msgid "Vulnerability|Identifier URL"
-msgstr ""
+msgstr "හඳුන්වනයේ ඒ.ස.නි."
msgid "Vulnerability|Identifier code"
-msgstr ""
+msgstr "හඳුන්වන කේතය"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "හඳුන්වන"
msgid "Vulnerability|Image"
msgstr ""
@@ -43050,7 +43517,7 @@ msgid "Vulnerability|Project"
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’ය"
msgid "Vulnerability|Remove identifier row"
-msgstr ""
+msgstr "හඳුන්වන පේළිය ඉවතලන්න "
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -43062,19 +43529,19 @@ msgid "Vulnerability|Request/Response"
msgstr "ඉල්ලීම/ප්â€à¶»à¶­à·’චà·à¶»à¶º"
msgid "Vulnerability|Scanner Provider"
-msgstr ""
+msgstr "සුපිරික්සන à·ƒà·à¶´à¶ºà·”ම්කරු"
msgid "Vulnerability|Security Audit"
-msgstr ""
+msgstr "ආරක්â€à·‚ණ විගණනය"
msgid "Vulnerability|Select a severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€à¶ºà¶šà·Š තà·à¶»à¶±à·Šà¶±"
msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
msgstr ""
msgid "Vulnerability|Severity"
-msgstr ""
+msgstr "තීව්â€à¶»à¶­à·à·€"
msgid "Vulnerability|Status"
msgstr "තත්â€à·€à¶º"
@@ -43095,7 +43562,7 @@ msgid "Vulnerability|Training not available for this vulnerability."
msgstr ""
msgid "Vulnerability|Unmodified Response"
-msgstr ""
+msgstr "අසංà·à·à¶°à·’ත ප්â€à¶»à¶­à·’චà·à¶»à¶º"
msgid "Vulnerability|View training"
msgstr ""
@@ -43107,16 +43574,16 @@ msgid "Wait for the file to load to copy its contents"
msgstr "ගොනුව එහි අන්තර්ගතය පිටපත් වීමට පූරණය වන තෙක් රà·à¶³à·™à¶±à·Šà¶±"
msgid "Waiting for approval"
-msgstr ""
+msgstr "අනුමà·à¶­à·’යට රà·à¶³à·™à¶¸à·’න්"
msgid "Waiting for merge (open and assigned)"
-msgstr ""
+msgstr "සංයුක්තයට රà·à¶³à·™à¶¸à·’න් (විවෘත හ෠පවර෠ඇත)"
msgid "Waiting for performance data"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access."
-msgstr ""
+msgstr "දත්ත බà·à¶½à·“මට අවà·à·Šâ€à¶ºà¶¯? ප්â€à¶»à·€à·šà·à¶º සඳහ෠පරිපà·à¶½à¶šà¶ºà·™à¶šà·”ගෙන් අසන්න."
msgid "Warning"
msgstr "අවවà·à¶¯à¶ºà¶ºà·’"
@@ -43131,6 +43598,9 @@ 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."
@@ -43155,7 +43625,7 @@ 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 "අපට ප්â€à¶»à·à¶¸à·’තියස් සේවà·à¶¯à·à¶ºà¶šà¶º වෙත ළඟ෠වීමට නොහà·à¶šà·’යි. සේවà·à¶¯à·à¶ºà¶šà¶º නොපවතී හ෠වින්â€à¶ºà·à·ƒ විස්තර යà·à·€à¶­à·Šà¶šà·à¶½ කළ යුතුය."
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 ""
@@ -43176,13 +43646,10 @@ msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %
msgstr ""
msgid "We recommend a work email address."
-msgstr ""
-
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
+msgstr "කà·à¶»à·Šà¶ºà·à¶½ වි-තà·à¶´à·‘ලක් නිර්දේ෠කෙරේ."
msgid "We recommend leaving all SAST analyzers enabled"
-msgstr ""
+msgstr "සියළුම SAST විà·à·Šà¶½à·šà·‚ක සබල කර තà·à¶¶à·“මට නිර්දේ෠කෙරේ"
msgid "We recommend that you buy additional Pipeline minutes to avoid any interruption of service."
msgstr ""
@@ -43190,20 +43657,23 @@ msgstr ""
msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
msgstr ""
-msgid "We sent you an email with reset password instructions"
+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 ""
+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 ""
+msgstr "ගිට්ලà·à¶¶à·Š සමඟ එක් වීමේ ආරà·à¶°à¶±à¶º ප්â€à¶»à¶­à·’ක්â€à·‚ේප කළ බව අපි %{inviter} වෙත දà·à¶±à·”ම් දෙන්නෙමු. ඔබට සිහිකà·à¶³à·€à·“ම් ලà·à¶¶à·“ම නවත්වනු ඇත."
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 ""
@@ -43218,16 +43688,16 @@ msgid "We're experiencing difficulties and this tab content is currently unavail
msgstr ""
msgid "We've detected some unusual activity"
-msgstr ""
+msgstr "අසà·à¶¸à·à¶±à·Šâ€à¶º ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š අනà·à·€à¶»à¶«à¶º විය"
msgid "We've detected unusual activity"
-msgstr ""
+msgstr "අසà·à¶¸à·à¶±à·Šâ€à¶º ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à¶šà·Š අනà·à·€à¶»à¶«à¶º විය"
msgid "We've found no vulnerabilities"
msgstr ""
msgid "Web IDE"
-msgstr ""
+msgstr "වියමන IDE"
msgid "Web Terminal"
msgstr "වියමන අග්â€à¶»à¶º"
@@ -43263,16 +43733,16 @@ msgid "WebIDE|You can’t edit files directly in this project. Go to your fork a
msgstr ""
msgid "WebIDE|You need permission to edit files directly in this project."
-msgstr ""
+msgstr "මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය තුළ සෘජුව ගොනු සංස්කරණයට ඔබට අවසරය අවà·à·Šâ€à¶º වේ."
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
-msgstr ""
+msgstr "වෙබෙක්ස් ටීම්ස් වෙත ව්â€à¶ºà·à¶´à·˜à¶­à·’යේ සිදුවීම් පිළිබඳ දà·à¶±à·”ම්දීම් යවන්න."
msgid "WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}"
-msgstr ""
+msgstr "වෙබෙක්ස් ටීම්ස් à·„à·’ සංවà·à¶¯à¶ºà¶šà¶§ ව්â€à¶ºà·à¶´à·˜à¶­à·’යේ සිදුවීම් පිළිබඳ දà·à¶±à·”ම්දීම් යවන්න. %{docs_link}"
msgid "WebexTeamsService|Webex Teams"
-msgstr ""
+msgstr "වෙබෙක්ස් ටීම්ස්"
msgid "Webhook"
msgstr ""
@@ -43311,7 +43781,7 @@ msgid "Webhooks|A feature flag is turned on or off."
msgstr ""
msgid "Webhooks|A group member is created, updated, or removed."
-msgstr ""
+msgstr "සමූහයේ à·ƒà·à¶¸à·à¶¢à·’කයෙක් à·ƒà·à¶¯à·, යà·à·€à¶­à·Šà¶šà·à¶½ කර හ෠ඉවත් කර ඇත."
msgid "Webhooks|A job's status changes."
msgstr ""
@@ -43362,13 +43832,13 @@ msgid "Webhooks|Deployment events"
msgstr ""
msgid "Webhooks|Enable SSL verification"
-msgstr ""
+msgstr "SSL තහවුරුව සබල කරන්න"
msgid "Webhooks|Failed to connect"
-msgstr ""
+msgstr "සබà·à¶³à·“මට අසමත්!"
msgid "Webhooks|Fails to connect"
-msgstr ""
+msgstr "සබà·à¶³à·“මට අසමත්!"
msgid "Webhooks|Feature flag events"
msgstr ""
@@ -43380,10 +43850,10 @@ msgid "Webhooks|Job events"
msgstr ""
msgid "Webhooks|Member events"
-msgstr ""
+msgstr "à·ƒà·à¶¸à·à¶¢à·’ක සිදුවීම්"
msgid "Webhooks|Merge request events"
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීම් සිදුවීම්"
msgid "Webhooks|Pipeline events"
msgstr ""
@@ -43398,7 +43868,7 @@ msgid "Webhooks|Releases events"
msgstr "නිකුතු සිදුවීම්"
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "SSL තහවුරුව"
msgid "Webhooks|Secret token"
msgstr ""
@@ -43490,6 +43960,12 @@ 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 "මෙම විධà·à¶±à¶º කරන්නේ කුමක්ද?"
@@ -43549,8 +44025,13 @@ 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 ""
+msgstr "කවදà·à¶¯:"
msgid "Which API requests are affected?"
msgstr ""
@@ -43559,16 +44040,16 @@ msgid "While it's rare to have no vulnerabilities, it can happen. In any event,
msgstr ""
msgid "Who can approve?"
-msgstr ""
+msgstr "අනුමත කළ à·„à·à¶šà·’ වන්නේ?"
msgid "Who can see this group?"
-msgstr ""
+msgstr "සමූහය දà·à¶šà·’ය à·„à·à¶šà·’ වන්නේ?"
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "මෙම සමූහය දà·à¶šà·’ය à·„à·à¶šà·’ වන්නේ?"
msgid "Who will be using GitLab?"
-msgstr ""
+msgstr "ගිට්ලà·à¶¶à·Š භà·à·€à·’ත෠කරන්නේ කවුද?"
msgid "Who will be using this GitLab subscription?"
msgstr ""
@@ -43577,7 +44058,7 @@ msgid "Who will be using this GitLab trial?"
msgstr ""
msgid "Who will be using this group?"
-msgstr ""
+msgstr "මෙම සමූහය භà·à·€à·’ත෠කරන්නේ කවුද?"
msgid "Why are you signing up? (optional)"
msgstr ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr "%{pageTitle} à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "WikiPage|Create page"
msgstr "පිටුව à·ƒà·à¶¯à¶±à·Šà¶±"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr "මූලà·à·à·Šâ€à¶»à¶º සංස්කරණය"
-
msgid "WikiPage|Format"
msgstr "ආකෘතිය"
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
-msgstr "එකතු"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
+msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr "අවලංගු"
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr "වස෠ඇත"
@@ -43852,29 +44342,44 @@ msgid "WorkItem|Collapse child items"
msgstr ""
msgid "WorkItem|Create task"
-msgstr ""
+msgstr "කà·à¶»à·Šà¶ºà¶ºà¶šà·Š à·ƒà·à¶¯à¶±à·Šà¶±"
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr "විවෘත"
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr "වර්ගය තà·à¶»à¶±à·Šà¶±"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,23 +44389,44 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr "වර්ගය"
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
-msgid "Would you like to create a new branch?"
+msgid "WorkItem|work items"
msgstr ""
+msgid "Would you like to create a new branch?"
+msgstr "ඔබ නව à·à·à¶›à·à·€à¶šà·Š සෑදීමට කà·à¶¸à¶­à·’ද?"
+
msgid "Would you like to try auto-generating a branch name?"
-msgstr ""
+msgstr "à·à·à¶›à·à·€à¶š නමක් ස්වයං උත්පà·à¶¯à¶±à¶ºà¶§ උත්සà·à·„ කිරීමට කà·à¶¸à¶­à·’ද?"
msgid "Write"
msgstr "ලියන්න"
@@ -43918,7 +44444,7 @@ msgid "Write a description…"
msgstr "සවිස්තරයක් ලියන්න…"
msgid "Write an internal note or drag your files here…"
-msgstr ""
+msgstr "අභ්â€à¶ºà¶±à·Šà¶­à¶» සටහනක් ලියන්න හ෠ගොනු මෙතà·à¶±à¶§ දමන්න…"
msgid "Write milestone description..."
msgstr ""
@@ -43930,7 +44456,7 @@ msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr ""
msgid "Xcode"
-msgstr ""
+msgstr "Xcode"
msgid "YYYY-MM-DD"
msgstr "YYY-MM-DD"
@@ -43995,7 +44521,7 @@ msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does
msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
-msgstr ""
+msgstr "ඔබ ප්â€à¶»à·à¶¸à·’තියස් සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ සම්බන්ධිතයි, දà·à¶±à¶§ පෙන්වීමට දත්ත නà·à¶­."
msgid "You are currently offline, or the GitLab instance is not reachable."
msgstr ""
@@ -44034,7 +44560,7 @@ msgid "You are not allowed to push into this branch. Create another branch or op
msgstr ""
msgid "You are not allowed to reject a user"
-msgstr ""
+msgstr "පුද්ගලයෙක් ප්â€à¶»à¶­à·’ක්â€à·‚ේප කිරීමට ඔබට අවසර නà·à¶­"
msgid "You are not allowed to unlink your primary login account"
msgstr ""
@@ -44067,7 +44593,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 ""
@@ -44112,10 +44638,10 @@ msgid "You can also use project access tokens with Git to authenticate over HTTP
msgstr ""
msgid "You can always change your URL later"
-msgstr ""
+msgstr "à·ƒà·à¶¸à·€à·’ට ඔබගේ ඒ.à·ƒ.නි. පසුව වෙනස් කළ à·„à·à¶šà·’ය"
msgid "You can always edit this later"
-msgstr ""
+msgstr "ඔබට මෙය පසුව සංà·à·à¶°à¶±à¶º කළ à·„à·à¶šà·’ය"
msgid "You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
msgstr ""
@@ -44127,22 +44653,22 @@ msgid "You can create a new %{link}."
msgstr "ඔබට නව %{link} සෑදීමට à·„à·à¶šà·’ය."
msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
-msgstr ""
+msgstr "පහත වි-තà·à¶´à·‘ලට වි-තà·à¶´à·‘ලක් යà·à·€à·“මෙන් ඔබට මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය තුළ නව %{name} සෑදීමට à·„à·à¶šà·’ය:"
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 ""
+msgstr "%{link} වෙත පිවිසීමෙන් නව SSH යතුරක් සෑදීමට à·„à·à¶šà·’ය"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
msgstr ""
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 "ඔබට නව එකක් සෑදීමට හ෠ඔබගේ %{ssh_key_link_start}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 "ඔබට නව එකක් සෑදීමට හ෠ඔබගේ SSH යතුරු à·ƒà·à¶šà·ƒà·”ම් %{ssh_key_link} තුළ පරීක්â€à·‚෠කළ à·„à·à¶šà·’ය."
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}."
msgstr ""
@@ -44154,7 +44680,7 @@ msgid "You can create new ones at your Personal Access Tokens settings %{pat_lin
msgstr ""
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+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 ""
@@ -44169,7 +44695,7 @@ 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 "ගිට්ලà·à¶¶à·Š දà·à¶ºà¶šà¶­à·Šâ€à·€ පිළිබඳ à·€à·à¶©à·’දුර තොරතුරු %{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 ""
@@ -44177,50 +44703,49 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
msgid "You can invite a new member to %{project_name}."
-msgstr ""
-
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
+msgstr "%{project_name} වෙත පුද්ගලයෙකුට ආරà·à¶°à¶±à· කළ à·„à·à¶šà·’ය."
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "%{project_name} වෙත අන් සමූහයකට ආරà·à¶°à¶±à· කළ à·„à·à¶šà·’ය."
msgid "You can move around the graph by using the arrow keys."
msgstr ""
msgid "You can notify the app / group or a project by sending them an email notification"
-msgstr ""
+msgstr "යෙදුමට / සමූහයට හ෠ව්â€à¶ºà·à¶´à·˜à¶­à·’යකට වි-තà·à¶´à·‘ලක් යà·à·€à·“මෙන් දà·à¶±à·”ම් දීමට à·„à·à¶šà·’ය"
msgid "You can now close this window."
msgstr "දà·à¶±à·Š ඔබට මෙම කවුළුව වස෠දà·à¶¸à·’ය à·„à·à¶šà·’ය."
msgid "You can now export your security dashboard to a CSV report."
-msgstr ""
+msgstr "දà·à¶±à·Š ඔබගේ ආරක්â€à·‚ණ උපකරණ පුවරුව CSV à·€à·à¶»à·Šà¶­à·à·€à¶šà¶§ නිර්යà·à¶­ කළ à·„à·à¶šà·’ය."
msgid "You can now submit a merge request to get this change into the original branch."
-msgstr ""
+msgstr "මෙම වෙනස මුල් à·à·à¶›à·à·€ වෙත ගà·à¶±à·“මට දà·à¶±à·Š සංයුක්ත ඉල්ලීමක් යොමු කළ à·„à·à¶šà·’ය."
msgid "You can now submit a merge request to get this change into the original project."
-msgstr ""
+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 ""
+msgstr "ඔබට එකවර සබඳත෠%{max_contacts} ක් එක් කළ à·„à·à¶šà·’ය"
msgid "You can only edit files when you are on a branch"
-msgstr ""
+msgstr "ඔබ à·à·à¶›à·à·€à¶š සිටින විට පමණක් ගොනු සංස්කරණය කළ à·„à·à¶šà·’ය"
msgid "You can only merge once the items above are resolved."
-msgstr ""
+msgstr "ඉහත අංග විසඳූ පසු පමණක් සංයුක්ත කළ à·„à·à¶šà·’ය."
msgid "You can only transfer the project to namespaces you manage."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44307,40 +44825,40 @@ msgid "You do not have permission to access dora metrics."
msgstr ""
msgid "You do not have permission to approve a member"
-msgstr ""
+msgstr "à·ƒà·à¶¸à·à¶¢à·’කයෙක් අනුමත කිරීමට ඔබට අවසර නà·à¶­"
msgid "You do not have permission to leave this %{namespaceType}."
-msgstr ""
+msgstr "මෙම %{namespaceType} à·„à·à¶» යà·à¶¸à¶§ ඔබට අවසර නà·à¶­."
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 ""
+msgstr "ඔබට වියමන අග්â€à¶»à¶º ධà·à·€à¶±à¶º කිරීමට අවසර නà·à¶­. ව්â€à¶ºà·à¶´à·˜à¶­à·’ පරිපà·à¶½à¶šà¶ºà·™à¶šà·” අමතන්න."
msgid "You do not have permission to set a member awaiting"
msgstr ""
msgid "You do not have permission to update the environment."
-msgstr ""
+msgstr "පරිසරය යà·à·€à¶­à·Šà¶šà·à¶½ කිරීම සඳහ෠ඔබට අවසර නà·à¶­."
msgid "You do not have permissions to run the import."
-msgstr ""
+msgstr "ඔබට ආයà·à¶­à¶º ධà·à·€à¶±à¶º කිරීමට අවසර නà·à¶­."
msgid "You don't have any U2F devices registered yet."
-msgstr ""
+msgstr "ඔබ සතුව ලියà·à¶´à¶¯à·’ංචි කළ U2F උපà·à¶‚ග නà·à¶­."
msgid "You don't have any WebAuthn devices registered yet."
msgstr ""
msgid "You don't have any active chat names."
-msgstr ""
+msgstr "ඔබ සතුව සක්â€à¶»à·’ය සංවà·à¶¯ නà·à¶¸ නà·à¶­."
msgid "You don't have any applications"
msgstr "ඔබ සතුව කිසිදු යෙදුමක් නà·à¶­"
msgid "You don't have any authorized applications"
-msgstr ""
+msgstr "ඔබ සතුව බලයලත් යෙදුම් කිසිවක් නà·à¶­"
msgid "You don't have any deployments right now."
msgstr ""
@@ -44355,16 +44873,16 @@ msgid "You don't have permission to review this deployment. Contact the project
msgstr ""
msgid "You don't have permissions to create this project"
-msgstr ""
+msgstr "ඔබට මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය සෑදීමට අවසර නà·à¶­"
msgid "You don't have sufficient permission to perform this action."
-msgstr ""
+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 ""
+msgstr "ඔබට මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€ වෙත ලිවීමේ ප්â€à¶»à·€à·šà·à¶º නà·à¶­."
msgid "You don’t have access to Productivity Analytics in this group"
msgstr ""
@@ -44399,7 +44917,7 @@ msgid "You have been unsubscribed from this thread."
msgstr ""
msgid "You have declined the invitation to join %{title} %{name}."
-msgstr ""
+msgstr "%{title} %{name} වෙත එක් වීමේ ආරà·à¶°à¶±à¶º ඔබ ප්â€à¶»à¶­à·’ක්â€à·‚ේප කර ඇත."
msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
msgstr ""
@@ -44411,7 +44929,7 @@ 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 ""
+msgstr "ඔබට මෙම ව්â€à¶ºà·à¶´à·˜à¶­à·’ය සඳහ෠HTTP අනුකලනයක් සෑදීමට ප්â€à¶»à¶¸à·à¶«à·€à¶­à·Š අවසර නà·à¶­"
msgid "You have insufficient permissions to create an on-call schedule for this project"
msgstr ""
@@ -44441,7 +44959,7 @@ msgid "You have insufficient permissions to update an on-call schedule for this
msgstr ""
msgid "You have insufficient permissions to update this HTTP integration"
-msgstr ""
+msgstr "ඔබට මෙම HTTP අනුකලනය යà·à·€à¶­à·Šà¶šà·à¶½ කිරීමට ප්â€à¶»à¶¸à·à¶«à·€à¶­à·Š අවසර නà·à¶­"
msgid "You have insufficient permissions to view shifts for this rotation"
msgstr ""
@@ -44456,7 +44974,7 @@ msgid "You have no permissions"
msgstr "ඔබට අවසර නà·à¶­"
msgid "You have not added any approvers. Start by adding users or groups."
-msgstr ""
+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 ""
@@ -44480,7 +44998,7 @@ msgid "You must be authenticated to access this path."
msgstr ""
msgid "You must be logged in to search across all of GitLab"
-msgstr ""
+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 ""
@@ -44489,10 +45007,10 @@ msgid "You must have maintainer access to force delete a lock"
msgstr ""
msgid "You must provide a valid current password"
-msgstr ""
+msgstr "ඔබ වලංගු වත්මන් මුරපදයක් à·ƒà·à¶´à¶ºà·’ය යුතුය"
msgid "You must provide your current password in order to change it."
-msgstr ""
+msgstr "එය වෙනස් කිරීමට ඔබගේ වත්මන් මුරපදය ලබ෠දිය යුතුය."
msgid "You must sign in to search for specific projects."
msgstr ""
@@ -44501,7 +45019,7 @@ msgid "You must sign in to search for specific terms."
msgstr ""
msgid "You must solve the CAPTCHA in order to submit"
-msgstr ""
+msgstr "යොමු කිරීමට ඔබ අභියà·à¶œà¶º විසඳිය යුතුය"
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -44513,7 +45031,7 @@ msgid "You need permission."
msgstr "ඔබට අවසරය ඇවà·à·ƒà·’ය."
msgid "You need to register a two-factor authentication app before you can set up a device."
-msgstr ""
+msgstr "උපà·à¶‚ගයක් පිහිටුවීමට පෙර ඔබ ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶± යෙදුමක් ලියà·à¶´à¶¯à·’ංචි කළ යුතුය."
msgid "You need to set terms to be enforced"
msgstr ""
@@ -44522,7 +45040,7 @@ 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 ""
+msgstr "ගිට්ලà·à¶¶à·Š ව්â€à¶ºà·à¶´à·˜à¶­à·’ නිර්යà·à¶­ සංරක්â€à·‚ිතයක් උඩුගත කළ යුතුය (අග .gz වන)."
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
msgstr ""
@@ -44534,16 +45052,16 @@ msgid "You tried to fork %{link_to_the_project} but it failed for the following
msgstr ""
msgid "You will be removed from existing projects/groups"
-msgstr ""
+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 ""
+msgstr "මෙම විà·à·šà·‚à·à¶‚ගය භà·à·€à·’තයට ඔබ මුලින්ම ජිර෠අනුකලනය පිහිටුවිය යුතුය."
msgid "You will lose all changes you've made to this file. This action cannot be undone."
-msgstr ""
+msgstr "ඔබ මෙම ගොනුවට සිදු කළ සියළුම වෙනස්කම් අහිමි වේ. මෙම ක්â€à¶»à·’යà·à¶¸à·à¶»à·Šà¶œà¶º අප්â€à¶»à¶­à·’වර්ත්â€à¶ºà¶ºà·’."
msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
msgstr ""
@@ -44552,7 +45070,7 @@ msgid "You will need to update your local repositories to point to the new locat
msgstr ""
msgid "You will not get any notifications via email"
-msgstr ""
+msgstr "ඔබට වි-තà·à¶´à·‘ලෙන් දà·à¶±à·”ම්දීම් නොලà·à¶¶à·™à·Š"
msgid "You will only receive notifications for the events you choose"
msgstr ""
@@ -44561,13 +45079,13 @@ msgid "You will only receive notifications for threads you have participated in"
msgstr ""
msgid "You will receive notifications for any activity"
-msgstr ""
+msgstr "ඕනෑම ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à¶šà·Š සඳහ෠දà·à¶±à·”ම්දීම් ලà·à¶¶à·™à¶±à·” ඇත"
msgid "You will receive notifications only for comments in which you were @mentioned"
-msgstr ""
+msgstr "ඔබව @සඳහන් කළ අදහස් සඳහ෠පමණක් දà·à¶±à·”ම්දීම් ලà·à¶¶à·™à¶±à·” ඇත"
msgid "You won't be able to create new projects because you have reached your project limit."
-msgstr ""
+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 ""
@@ -44576,7 +45094,7 @@ 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 ""
+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 ""
@@ -44600,19 +45118,19 @@ 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 ""
+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 ""
+msgstr "ඔබට මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à¶±à·Šà¶±à·š %{host} à·„à·’ ඔබගේ ගිණුම නිසà·à¶º. %{manage_label_subscriptions_link_start}නම්පත් දà·à¶ºà¶šà¶­à·Šâ€à·€ කළමනà·à¶šà¶»à¶«à¶º%{manage_label_subscriptions_link_end} &middot; %{help_link_start}උදව්%{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 "ඔබට මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à¶±à·Šà¶±à·š %{host} à·„à·’ ඔබගේ ගිණුම නිසà·à¶º. %{manage_notifications_link_start}සියළුම දà·à¶±à·”ම්දීම් කළමනà·à¶šà¶»à¶«à¶º%{manage_notifications_link_end} &middot; %{help_link_start}උදව්%{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 "%{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 ""
@@ -44624,14 +45142,17 @@ msgid "You're receiving this email because you have been assigned an item on %{h
msgstr ""
msgid "You're receiving this email because you have been mentioned on %{host}."
-msgstr ""
+msgstr "ඔබව %{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 "ඔබව %{host} à·„à·’ සඳහන් කර ඇති නිස෠ඔබට මෙම වි-තà·à¶´à·‘ල ලà·à¶¶à·™à·Š. %{manage_notifications_link_start}සියළු දà·à¶±à·”ම්දීම් කළමනà·à¶šà¶»à¶«à¶º%{manage_notifications_link_end} &middot; %{help_link_start}උදව්%{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 ""
+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 ""
@@ -44639,27 +45160,24 @@ msgid "You've reached your %{free_limit} member limit across all of your persona
msgstr ""
msgid "You've rejected %{user}"
-msgstr ""
+msgstr "ඔබ %{user} ප්â€à¶»à¶­à·’ක්â€à·‚ේප කර ඇත"
msgid "YouTube"
msgstr "යූටියුබ්"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
-msgstr ""
+msgstr "ඔබගේ %{group} à·ƒà·à¶¸à·à¶¢à·’කත්වය දà·à¶±à·Š %{days} කින් ඉකුත් වේ."
msgid "Your %{host} account was signed in to from a new location"
-msgstr ""
+msgstr "ඔබගේ %{host} ගිණුමට නව ස්ථà·à¶±à¶ºà¶šà·’න් ඇතුළු වී ඇත"
msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded."
-msgstr ""
+msgstr "ඔබගේ %{spammable_entity_type} අයà·à¶ à·’ත ලෙස හඳුන෠ගෙන ඉවත දම෠ඇත."
msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "ඔබගේ %{spammable_entity_type} අයà·à¶ à·’ත ලෙස හඳුන෠ගෙන ඇත. ඉදිරියට යà·à¶¸à¶§ අන්තර්ගතය වෙනස් කරන්න හ෠අභියà·à¶œà¶º විසඳන්න."
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44669,7 +45187,7 @@ msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more detail
msgstr ""
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
-msgstr ""
+msgstr "ඔබගේ CSV නිර්යà·à¶­à¶º ආරම්භ වී ඇත. නිම වූ විට එය %{email} වෙත එවනු ඇත."
msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
msgstr ""
@@ -44678,7 +45196,7 @@ msgid "Your CSV export of %{written_count} from project %{project_name} (%{proje
msgstr ""
msgid "Your CSV import for project"
-msgstr ""
+msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’යට ඔබගේ 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 ""
@@ -44687,10 +45205,10 @@ msgid "Your GPG keys (%{count})"
msgstr "ඔබගේ ජීපීජී යතුරු (%{count})"
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 "ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුමට අසà·à¶»à·Šà¶®à¶š ඇතුළු වීමේ තà·à¶­à·Š කිරීම් බොහොමයක් හේතුවෙන් අගුළු ල෠ඇත. ගිණුම %{duration} කින් ස්වයංක්â€à¶»à·“යව අගුළු à·„à·à¶»à·™à¶± තෙක් රà·à¶³à·“ සිටීමට à·„à·à¶šà·’ය, හ෠දà·à¶±à·Šà¶¸ අගුළු à·„à·à¶»à·“මට පහත සබà·à¶³à·’ය ඔබන්න."
msgid "Your GitLab account request has been approved!"
-msgstr ""
+msgstr "ඔබගේ ගිට්ලà·à¶¶à·Š ගිණුම සඳහ෠ඉල්ලීම අනුමතයි!"
msgid "Your GitLab group"
msgstr "ඔබගේ ගිට්ලà·à¶¶à·Š සමූහය"
@@ -44720,13 +45238,13 @@ msgid "Your SSH keys (%{count})"
msgstr "ඔබගේ SSH යතුරු (%{count})"
msgid "Your To-Do List"
-msgstr ""
+msgstr "ඔබගේ කළ-යුතු ලේඛනය"
msgid "Your U2F device did not send a valid JSON response."
-msgstr ""
+msgstr "ඔබගේ U2F උපà·à¶‚ගය වලංගු JSON ප්â€à¶»à¶­à·’චà·à¶»à¶ºà¶šà·Š එව෠නà·à¶­."
msgid "Your U2F device was registered!"
-msgstr ""
+msgstr "ඔබගේ U2F උපà·à¶‚ගය ලියà·à¶´à¶¯à·’ංචිව ඇත!"
msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
@@ -44738,10 +45256,10 @@ msgid "Your access request to the %{source_type} has been withdrawn."
msgstr ""
msgid "Your account has been deactivated"
-msgstr ""
+msgstr "ඔබගේ ගිණුම අක්â€à¶»à·’ය කර ඇත"
msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
-msgstr ""
+msgstr "ඔබගේ පරිපà·à¶½à¶š විසින් ඔබගේ ගිණුම අක්â€à¶»à·’ය කර ඇත. ගිණුම යළි සක්â€à¶»à·’ය කිරීමට නà·à·€à¶­ ඇතුළු වන්න."
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
@@ -44771,7 +45289,7 @@ 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 ""
+msgstr "අතිරික්සුව U2F සඳහ෠සහය නොදක්වයි. ගූගල් ක්â€à¶»à·à¶¸à·Š à·€à·à¶©à¶­à¶½à¶º භà·à·€à·’ත෠කරන්න (අනුවà·à¶¯à¶º 41 හ෠නව)."
msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
msgstr ""
@@ -44789,28 +45307,28 @@ msgid "Your changes have been successfully committed."
msgstr ""
msgid "Your comment could not be submitted because %{error}"
-msgstr ""
+msgstr "%{error} නිස෠ඔබගේ අදහස යොමු කළ නොහà·à¶šà·’ය"
msgid "Your comment could not be submitted! Please check your network connection and try again."
-msgstr ""
+msgstr "ඔබගේ අදහස යොමු කළ නොහà·à¶šà·’ විය! ජà·à¶½ සම්බන්ධතà·à·€à¶º පරීක්â€à·‚෠කර යළි බලන්න."
msgid "Your comment could not be updated! Please check your network connection and try again."
-msgstr ""
+msgstr "ඔබගේ අදහස යà·à·€à¶­à·Šà¶šà·à¶½ කළ නොහà·à¶šà·’ විය! ජà·à¶½ සම්බන්ධතà·à·€à¶º පරීක්â€à·‚෠කර යළි බලන්න."
msgid "Your comment will be discarded."
-msgstr ""
+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 ""
+msgstr "ද්වි-à·ƒà·à¶°à¶š සත්â€à¶ºà·à¶´à¶± යෙදුමක් ලියà·à¶´à¶¯à·’ංචියට ඔබගේ වත්මන් මුරපදය අවà·à·Šâ€à¶º වේ."
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
-msgstr ""
+msgstr "ඔබගේ උපකරණ පුවරුව පිටපත්ව ඇත. එය %{web_ide_link_start}මෙහි සංස්කරණය කළ à·„à·à¶šà·’ය%{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 "ඔබගේ උපකරණ පුවරුව යà·à·€à¶­à·Šà¶šà·à¶½à·€ ඇත. ඔබට එය %{web_ide_link_start}මෙහි සංස්කරණය කළ à·„à·à¶šà·’ය%{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 ""
@@ -44819,20 +45337,30 @@ msgid "Your deployment services will be broken, you will need to manually fix th
msgstr ""
msgid "Your device is not compatible with GitLab. Please try another device"
-msgstr ""
+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 ""
+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 "ඔබගේ ගොනුවේ %{codeStart}සිරà·à·ƒà·’ය%{codeEnd} නම් තීරුවක් අඩංගු විය යුතුය. %{codeStart}සවිස්තරය%{codeEnd} තීරුව විකල්පයකි. ගොනුවකට ඉඩ දෙන උපරිම ප්â€à¶»à¶¸à·à¶«à¶º මෙ.බ. 10 කි."
msgid "Your first project"
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 "ඔබගේ සමූහ"
@@ -44861,7 +45389,7 @@ msgid "Your license is valid from"
msgstr ""
msgid "Your membership in %{group} no longer expires."
-msgstr ""
+msgstr "%{group} à·„à·’ ඔබගේ à·ƒà·à¶¸à·à¶¢à·’කත්වය කල් ඉකුත් නොවේ."
msgid "Your message here"
msgstr "ඔබගේ පණිවිඩය මෙතà·à¶±"
@@ -44870,7 +45398,7 @@ msgid "Your name"
msgstr "ඔබගේ නම"
msgid "Your new %{accessTokenType}"
-msgstr ""
+msgstr "ඔබගේ නව %{accessTokenType}"
msgid "Your new %{accessTokenType} has been created."
msgstr ""
@@ -44894,7 +45422,7 @@ 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 ""
+msgstr "මූලික වි-තà·à¶´à·‘ල ප්â€à¶»à¶­à·’රූපය අනà·à·€à¶»à¶«à¶ºà¶§ භà·à·€à·’ත කෙරේ. එය ඔබගේ %{openingTag}පà·à¶­à·’කඩ à·ƒà·à¶šà·ƒà·”ම්%{closingTag} තුළ වෙනස් කළ à·„à·à¶šà·’ය."
msgid "Your profile"
msgstr "ඔබගේ පà·à¶­à·’කඩ"
@@ -44903,7 +45431,7 @@ msgid "Your project has limited quotas and features"
msgstr ""
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
-msgstr ""
+msgstr "ඔබගේ ව්â€à¶ºà·à¶´à·˜à¶­à·’ සීමà·à·€ %{limit} කි! එය à·€à·à¶©à·’ කිරීමට ඔබගේ පරිපà·à¶½à¶š අමතන්න"
msgid "Your project will be created at:"
msgstr "ඔබගේ ව්â€à¶ºà·à¶´à·˜à¶­à·’ය සෑදෙන්නේ:"
@@ -44915,22 +45443,19 @@ msgid "Your public email will be displayed on your public profile."
msgstr "ඔබගේ ප්â€à¶»à·ƒà·’ද්ධ වි-තà·à¶´à·‘ල ප්â€à¶»à·ƒà·’ද්ධ පà·à¶­à·’කඩෙහි දර්à·à¶±à¶º වනු ඇත."
msgid "Your request for access could not be processed: %{error_message}"
-msgstr ""
+msgstr "ප්â€à¶»à·€à·šà·à¶º සඳහ෠ඔබගේ ඉල්ලීම à·ƒà·à¶šà·ƒà·“මට නොහà·à¶šà·’ය: %{error_message}"
msgid "Your request for access has been queued for review."
-msgstr ""
+msgstr "ප්â€à¶»à·€à·šà·à¶º සඳහ෠ඔබගේ ඉල්ලීම සමà·à¶½à·à¶ à¶±à¶ºà¶§ පà·à¶½à·’ම්ගතයි."
msgid "Your request to join %{host} has been rejected."
-msgstr ""
+msgstr "%{host} වෙත එක්වීමේ ඔබගේ ඉල්ලීම ප්â€à¶»à¶­à·’ක්â€à·‚ේපිතයි."
msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
-msgstr ""
+msgstr "ඔබගේ අවà·à·Šâ€à¶ºà¶­à· ආයà·à¶­ වෙමින්. අවසන් වූ පසු, තහවුරු කිරීමේ වි-තà·à¶´à·‘ලක් ලà·à¶¶à·™à¶±à·” ඇත."
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
-msgstr ""
-
-msgid "Your response has been recorded."
-msgstr ""
+msgstr "ඔබගේ අවà·à·Šâ€à¶ºà¶­à· පසුබිමින් ආයà·à¶­ කෙරේ. අවසන් වූ පසු, තහවුරු කිරීමේ වි-තà·à¶´à·‘ලක් ලà·à¶¶à·™à¶±à·” ඇත."
msgid "Your search didn't match any commits."
msgstr ""
@@ -44939,7 +45464,7 @@ msgid "Your search didn't match any commits. Try a different query."
msgstr ""
msgid "Your search timed out"
-msgstr ""
+msgstr "ඔබගේ සෙවුම කල් ඉකුත්ය"
msgid "Your sign-in page is %{url}."
msgstr ""
@@ -44948,17 +45473,15 @@ msgid "Your snippets"
msgstr ""
msgid "Your subscription expired!"
-msgstr ""
+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 in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -44985,7 +45508,7 @@ 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 ""
+msgstr "ඔබ මෙම අනුකලනය සබල කිරීමට පෙර, ඔබ සෙන්ටà·à¶• වින්â€à¶ºà·à·ƒà¶œà¶­ කළ යුතුය. à·€à·à¶©à·’ විස්තර සඳහà·, %{link_start}සෙන්ටà·à¶• අනුකලන ප්â€à¶»à¶½à·šà¶›à¶±à¶º%{link_end} කියවන්න."
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -45042,7 +45565,7 @@ msgid "`work_items_hierarchy` feature flag disabled for this project"
msgstr ""
msgid "a deleted user"
-msgstr ""
+msgstr "මක෠දà·à¶¸à·– පුද්ගලයෙකි"
msgid "about 1 hour"
msgid_plural "about %d hours"
@@ -45056,7 +45579,7 @@ msgid "added"
msgstr "එකතු කෙරිණි"
msgid "added %{emails}"
-msgstr ""
+msgstr "%{emails} එක් කළà·"
msgid "added a Zoom call to this issue"
msgstr ""
@@ -45083,7 +45606,7 @@ msgid "already has a \"created\" issue link"
msgstr ""
msgid "already shared with this group"
-msgstr ""
+msgstr "දà·à¶±à¶§à¶¸à¶­à·Š මෙම සමූහය සමඟ බෙදà·à¶œà·™à¶± ඇත"
msgid "and"
msgstr "සහ"
@@ -45096,8 +45619,8 @@ msgstr ""
msgid "approval"
msgid_plural "approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "අනුමà·à¶­à·’ය"
+msgstr[1] "අනුමà·à¶­à·’"
msgid "archived"
msgstr "සංරක්â€à·‚ිතයි"
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45124,7 +45650,7 @@ msgid "at risk"
msgstr ""
msgid "attach a new file"
-msgstr ""
+msgstr "නව ගොනුවක් අමුණන්න"
msgid "authored"
msgstr ""
@@ -45162,13 +45688,13 @@ msgid "can not be changed for existing notes"
msgstr ""
msgid "can not be set for this resource"
-msgstr ""
+msgstr "මෙම සම්පතට à·ƒà·à¶šà·ƒà·“මට නොහà·à¶šà·’ය"
msgid "can not be set for this type of note"
-msgstr ""
+msgstr "මෙම වර්ගයේ සටහන් සඳහ෠සà·à¶šà·ƒà·“මට නොහà·à¶šà·’ය"
msgid "can only be changed by a group admin."
-msgstr ""
+msgstr "සමූහයේ පරිපà·à¶½à¶šà¶ºà·™à¶šà·”ට පමණක් වෙනස් කළ à·„à·à¶šà·’ය."
msgid "can only have one escalation policy"
msgstr ""
@@ -45183,7 +45709,7 @@ msgid "can't be solely blank"
msgstr ""
msgid "can't be the same as the source project"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» ව්â€à¶ºà·à¶´à·˜à¶­à·’යට සමà·à¶± විය නොහà·à¶šà·’ය"
msgid "can't include: %{invalid_storages}"
msgstr ""
@@ -45191,20 +45717,23 @@ msgstr ""
msgid "can't reference a branch that does not exist"
msgstr ""
-msgid "cannot be a date in the past"
+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 changed"
-msgstr ""
+msgstr "වෙනස් කළ නොහà·à¶šà·’ය"
msgid "cannot be changed if a personal project has container registry tags."
msgstr ""
msgid "cannot be changed if shared runners are enabled"
-msgstr ""
+msgstr "හවුල් ධà·à·€à¶š සබල කර ඇත්නම් වෙනස් කළ නොහà·à¶šà·’ය"
msgid "cannot be enabled"
-msgstr ""
+msgstr "සබල කළ නොහà·à¶šà·’ය"
msgid "cannot be enabled because parent group does not allow it"
msgstr ""
@@ -45213,10 +45742,10 @@ msgid "cannot be enabled because parent group has shared Runners disabled"
msgstr ""
msgid "cannot be enabled unless all domains have TLS certificates"
-msgstr ""
+msgstr "සියළුම වසම් වලට TLS සහතික නà·à¶­à·’ නම් සබල කළ නොහà·à¶šà·’ය"
msgid "cannot be enabled until a valid credit card is on file"
-msgstr ""
+msgstr "වලංගු ණය පතක් ගොනුවේ ඇති තෙක් සබල කළ නොහà·à¶šà·’ය"
msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
msgstr ""
@@ -45248,10 +45777,10 @@ msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_star
msgstr ""
msgid "ciReport|%{degradedNum} degraded"
-msgstr ""
+msgstr "%{degradedNum} පිරිහී ඇත"
msgid "ciReport|%{improvedNum} improved"
-msgstr ""
+msgstr "%{improvedNum} à·€à·à¶©à·’ දියුණුයි"
msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
msgstr ""
@@ -45263,43 +45792,49 @@ msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}DAST ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}පරà·à¶ºà¶­à·Šà¶­ සුපිරික්සීම ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}SAST ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}කේත ගුණත්â€à·€ à·€à·à¶»à·Šà¶­à· ගà·à¶± තව දà·à¶±à¶œà¶±à·Šà¶±%{linkEndTag}"
msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
-msgstr ""
+msgstr "තව %{remainingPackagesCount}"
msgid "ciReport|%{reportType} is loading"
msgstr "%{reportType} පූරණය වෙමින්"
msgid "ciReport|%{reportType}: Loading resulted in an error"
-msgstr ""
+msgstr "%{reportType}: පූරණය දà·à·‚යකට ලක් විය"
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
+msgstr "පූරණය දà·à·‚යකට ලක් විය"
msgid "ciReport|API Fuzzing"
msgstr ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "සියළු ව්â€à¶ºà·à¶´à·˜à¶­à·’"
@@ -45352,26 +45890,26 @@ msgid "ciReport|Cluster Image Scanning"
msgstr ""
msgid "ciReport|Code Quality"
-msgstr "කේත ගුණත්වය"
+msgstr "කේත ගුණත්â€à·€à¶º"
msgid "ciReport|Code Quality failed loading results"
-msgstr ""
+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] ""
+msgstr[0] "නව ගà·à¶§à·…ුවක් නිස෠කේත ගුණත්â€à·€à¶º පිරිහී ඇත"
+msgstr[1] "නව ගà·à¶§à·…à·” %d ක් නිස෠කේත ගුණත්â€à·€à¶º පිරිහී ඇත"
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] "විසඳූ ගà·à¶§à·…ුවක් නිස෠කේත ගුණත්â€à·€à¶º à·€à·à¶©à·’දියුණු විය"
+msgstr[1] "විසඳූ ගà·à¶§à·…à·” %d ක් නිස෠කේත ගුණත්â€à·€à¶º à·€à·à¶©à·’දියුණු විය"
msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
-msgstr ""
+msgstr "කේත ගුණත්â€à·€ සුපිරික්සීමට සංයුක්ත ප්â€à¶»à¶­à·’ඵලවල වෙනස්කම් %{issueCount} ක් අනà·à·€à¶»à¶«à¶º විය"
msgid "ciReport|Container Scanning"
msgstr ""
@@ -45434,7 +45972,7 @@ msgid "ciReport|Fixed:"
msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
-msgstr ""
+msgstr "%{issuesWithCount} හමුවිය"
msgid "ciReport|Full Report"
msgstr "පූර්ණ à·€à·à¶»à·Šà¶­à·à·€"
@@ -45446,7 +45984,7 @@ msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
msgid "ciReport|License Compliance"
-msgstr ""
+msgstr "බලපත්â€à¶» අනුකූලතà·à·€"
msgid "ciReport|License Compliance failed loading results"
msgstr ""
@@ -45475,7 +46013,7 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "%{reportName} à·€à·à¶»à·Šà¶­à·à·€ පූරණය වෙමින්"
msgid "ciReport|Loading Code Quality report"
-msgstr ""
+msgstr "කේත ගුණත්â€à·€ à·€à·à¶»à·Šà¶­à·à·€ පූරණය වෙමින්"
msgid "ciReport|Manage Licenses"
msgstr "බලපත්â€à¶» කළමනà·à¶šà¶»à¶«à¶º"
@@ -45484,25 +46022,25 @@ msgid "ciReport|Manage licenses"
msgstr "බලපත්â€à¶» කළමනà·à¶šà¶»à¶«à¶º"
msgid "ciReport|Manually Added"
-msgstr ""
+msgstr "අතින් එක් කෙරිණි"
msgid "ciReport|New"
msgstr "නව"
msgid "ciReport|No changes to Code Quality."
-msgstr "කේත ගුණත්වයට වෙනසක් නà·à¶­."
+msgstr "කේත ගුණත්â€à·€à¶ºà¶§ වෙනසක් නà·à¶­."
msgid "ciReport|No changes to code quality"
-msgstr "කේතයේ ගුණත්වයට වෙනසක් නà·à¶­"
+msgstr "කේතයේ ගුණත්â€à·€à¶ºà¶§ වෙනසක් නà·à¶­"
msgid "ciReport|No code quality issues found"
-msgstr ""
+msgstr "කේත ගුණත්â€à·€ ගà·à¶§à·…à·” හමු නොවිණි"
msgid "ciReport|RPS"
msgstr "RPS"
msgid "ciReport|Resolve with merge request"
-msgstr ""
+msgstr "සංයුක්ත ඉල්ලීම සමඟ විසඳන්න"
msgid "ciReport|SAST"
msgstr "SAST"
@@ -45517,16 +46055,16 @@ msgid "ciReport|Secret detection"
msgstr "රහස් අනà·à·€à¶»à¶«à¶º"
msgid "ciReport|Security reports failed loading results"
-msgstr ""
+msgstr "ආරක්â€à·‚ණ à·€à·à¶»à·Šà¶­à· ප්â€à¶»à¶­à·’ඵල පූරණයට අසමත් විය"
msgid "ciReport|Security scanning"
-msgstr ""
+msgstr "ආරක්â€à·‚ණ සුපිරික්සීම"
msgid "ciReport|Security scanning failed loading any results"
-msgstr ""
+msgstr "ආරක්â€à·‚ණ සුපිරික්සීම ප්â€à¶»à¶­à·’ඵල පූරණයට අසමත් විය"
msgid "ciReport|Security scanning is loading"
-msgstr ""
+msgstr "ආරක්â€à·‚ණ සුපිරික්සීම පූරණය වෙමින්"
msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr "පූරණය වෙමින්"
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr "වස෠ඇත"
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,11 +46188,8 @@ msgstr ""
msgid "data"
msgstr "දත්ත"
-msgid "database"
-msgstr "දත්තසමුදà·à¶º"
-
msgid "date must not be after 9999-12-31"
-msgstr ""
+msgstr "9999-12-31 ට පෙර දිනයක් විය යුතුය"
msgid "day"
msgid_plural "days"
@@ -45703,13 +46244,13 @@ msgid "element is not a hierarchy"
msgstr ""
msgid "eligible users"
-msgstr ""
+msgstr "සුදුසුකම් ලත් අය"
msgid "email '%{email}' is not a verified email."
msgstr ""
msgid "email address settings"
-msgstr ""
+msgstr "තà·à¶´à·à¶½à·Š ලිපින à·ƒà·à¶šà·ƒà·”ම්"
msgid "enabled"
msgstr "සබල කර ඇත"
@@ -45724,10 +46265,10 @@ msgid "entries cannot be larger than 255 characters"
msgstr ""
msgid "entries cannot be nil"
-msgstr ""
+msgstr "ඇතුළත් කිරීම් à·à·”න්â€à¶º විය නොහà·à¶š"
msgid "entries cannot contain HTML tags"
-msgstr ""
+msgstr "නිවේà·à·’තවල HTML අනන්â€à¶ºà¶± තොර විය යුතුය"
msgid "epic"
msgstr ""
@@ -45741,20 +46282,23 @@ 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 ""
+msgstr "බයිට %{bytes} ක සීමà·à·€ ඉක්මවයි"
msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
-msgstr ""
+msgstr "\"%{dirname}\" නà·à¶¸à·à·€à¶½à·’ය සඳහ෠බයිට %{bytes} ක සීමà·à·€ ඉක්මවයි"
msgid "expired on %{timebox_due_date}"
-msgstr ""
+msgstr "%{timebox_due_date} දී කල් ඉකුත් විය"
msgid "expires on %{timebox_due_date}"
-msgstr ""
+msgstr "%{timebox_due_date} දී කල් ඉකුත් විය"
msgid "failed"
msgstr "අසමත් විය"
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr "සමූහයේ à·ƒà·à¶¸à·à¶¢à·’කයින්"
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "සමූහ"
@@ -45833,7 +46374,7 @@ msgid "groups and projects"
msgstr "සමූහ හ෠ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "groups only"
-msgstr ""
+msgstr "සමූහ පමණි"
msgid "had %{count} failed job"
msgid_plural "had %{count} failed jobs"
@@ -45876,9 +46417,12 @@ msgstr "https://ඔබගේ-බිට්බකට්-සේවà·à¶¯à·à¶ºà¶šà¶
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
-msgid "image diff"
+msgid "if"
msgstr ""
+msgid "image diff"
+msgstr "රූපයේ වෙනස"
+
msgid "impersonation token"
msgstr ""
@@ -45915,7 +46459,7 @@ msgid "is already associated to a GitLab Issue. New issue will not be associated
msgstr ""
msgid "is an invalid IP address range"
-msgstr ""
+msgstr "වලංගු නොවන අ.ජà·.කෙ. ලිපින පරà·à·ƒà¶ºà¶šà·’"
msgid "is blocked by"
msgstr ""
@@ -45942,16 +46486,16 @@ msgid "is not allowed for sign-up. Please use your regular email address."
msgstr ""
msgid "is not allowed for this group."
-msgstr ""
+msgstr "මෙම සමූහය සඳහ෠ඉඩ නොදේ."
msgid "is not allowed for this project."
-msgstr ""
+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 ""
+msgstr "ඉඩ නොදේ. ඔබගේ à·ƒà·à¶¸à·à¶±à·Šâ€à¶º වි-තà·à¶´à·‘ල භà·à·€à·’ත෠කරන්න."
msgid "is not allowed. We do not currently support project-level iterations"
msgstr ""
@@ -45996,7 +46540,7 @@ msgid "issues on track"
msgstr ""
msgid "it is larger than %{limit}"
-msgstr ""
+msgstr "එය %{limit}ට වඩ෠විà·à·à¶½ වේ"
msgid "it is stored as a job artifact"
msgstr ""
@@ -46005,7 +46549,7 @@ msgid "it is stored externally"
msgstr "එය බà·à·„ිරව ගබඩ෠කර ඇත"
msgid "it is stored in LFS"
-msgstr ""
+msgstr "එය LFS හි ගබඩ෠කර ඇත"
msgid "it is too large"
msgstr "එය ඉත෠විà·à·à¶½à¶ºà·’"
@@ -46014,13 +46558,13 @@ msgid "jigsaw is not defined"
msgstr ""
msgid "kuromoji custom analyzer"
-msgstr ""
+msgstr "කුරුමà·à¶¢à·’ අභිරුචි විà·à·Šà¶½à·šà·‚කය"
msgid "last commit:"
msgstr ""
msgid "latest"
-msgstr ""
+msgstr "අවසà·à¶±"
msgid "latest deployment"
msgstr ""
@@ -46052,9 +46596,12 @@ msgstr "පූරණය â€â€à·€à·™à¶¸à·’න්"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
-msgid "manual"
+msgid "main_database"
msgstr ""
+msgid "manual"
+msgstr "අතින්"
+
msgid "math|Displaying this math block may cause performance issues on this page"
msgstr ""
@@ -46081,34 +46628,28 @@ msgid "missing"
msgstr ""
msgid "months"
-msgstr ""
+msgstr "මà·à·ƒ"
msgid "most recent deployment"
msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
-msgstr ""
+msgstr "%{targetBranch}%{squashedCommits} වෙත %{commitCount} සහ %{mergeCommitCount}එකතු වේ."
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr ""
+msgstr "%{targetBranch} වෙත %{commitCount} එකතු වේ."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
-msgstr ""
+msgstr "වෙනස්කම් %{targetBranch} වෙත %{mergeCommitSha}%{squashedCommits} සමඟ සංයුක්තයි."
msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
-msgstr ""
+msgstr "වෙනස්කම් %{targetBranch} වෙත සංයුක්ත කර නà·à¶­."
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
-msgstr ""
+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 ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr "මූලà·à·à·Šâ€à¶» à·à·à¶›à·à·€ මක෠දමයි"
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "සංයුක්ත"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46361,7 +46890,7 @@ msgid "mrWidget|Resolve conflicts"
msgstr ""
msgid "mrWidget|Resolve locally"
-msgstr ""
+msgstr "ස්ථà·à¶±à·“යව විසඳන්න"
msgid "mrWidget|Revert"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr "%{widget} විස්තර පෙන්වන්න"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "මෙම සංයුක්ත ඉල්ලීම ස්වයංක්â€à¶»à·“යව සංයුක්ත වීමට අසමත් විය"
@@ -46436,7 +46953,7 @@ msgid "must be a Debian package"
msgstr "ඩෙබියන් ඇසුරුමක් විය යුතුය"
msgid "must be a boolean value"
-msgstr ""
+msgstr "බූලියන් අගයක් විය යුතුය"
msgid "must be a root namespace"
msgstr ""
@@ -46475,16 +46992,16 @@ msgid "must match %{association}.project_id"
msgstr ""
msgid "my-awesome-group"
-msgstr ""
+msgstr "මà·à¶œà·š-සමූහය"
msgid "my-channel"
msgstr "මà·à¶œà·š-නà·à¶½à·’කà·à·€"
msgid "my-topic"
-msgstr ""
+msgstr "මà·à¶œà·š-මà·à¶­à·˜à¶šà·à·€"
msgid "need attention"
-msgstr ""
+msgstr "අවධà·à¶±à¶º අවà·à·Šâ€à¶ºà¶ºà·’"
msgid "needs to be between 10 minutes and 1 month"
msgstr ""
@@ -46564,10 +47081,10 @@ msgstr[0] ""
msgstr[1] ""
msgid "packages"
-msgstr ""
+msgstr "ඇසුරුම් "
msgid "pages"
-msgstr ""
+msgstr "පිටු"
msgid "parent"
msgid_plural "parents"
@@ -46602,7 +47119,7 @@ msgid "pipeline schedules documentation"
msgstr ""
msgid "pipelineEditorWalkthrough|Let's do this!"
-msgstr ""
+msgstr "අපි මෙය කරමු!"
msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
msgstr ""
@@ -46663,16 +47180,16 @@ msgid "projects"
msgstr "ව්â€à¶ºà·à¶´à·˜à¶­à·’"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "අභියà·à¶œà¶º"
msgid "reCAPTCHA helps prevent credential stuffing."
-msgstr ""
+msgstr "අභියà·à¶œà¶º අක්තපත්â€à¶» ස්වයං පිරවීම වළක්වයි."
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "අභියà·à¶œà¶ºà·™à·„à·’ පුද්ගලික යතුර"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "අභියà·à¶œà¶ºà·™à·„à·’ අඩවි යතුර"
msgid "recent activity"
msgstr "මෑත ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸"
@@ -46716,11 +47233,14 @@ msgid "reply should have same confidentiality as top-level note"
msgstr ""
msgid "repositories"
-msgstr ""
+msgstr "කà·à·‚්ඨ"
msgid "repository:"
msgstr "කà·à·‚්ඨය:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46740,16 +47263,16 @@ msgid "severity|Critical"
msgstr ""
msgid "severity|High"
-msgstr ""
+msgstr "ඉහළ"
msgid "severity|Info"
-msgstr ""
+msgstr "තොරතුරු"
msgid "severity|Low"
-msgstr ""
+msgstr "අඩු"
msgid "severity|Major"
-msgstr ""
+msgstr "ප්â€à¶»à¶°à·à¶±"
msgid "severity|Medium"
msgstr "මධ්â€à¶ºà¶¸"
@@ -46758,7 +47281,7 @@ msgid "severity|Minor"
msgstr ""
msgid "severity|None"
-msgstr ""
+msgstr "කිසිත් නà·à¶­"
msgid "severity|Unknown"
msgstr "නොදනී"
@@ -46776,10 +47299,10 @@ msgid "show %{count} more"
msgstr "තවත් %{count} පෙන්වන්න"
msgid "show fewer"
-msgstr ""
+msgstr "අවමව පෙන්වන්න"
msgid "show less"
-msgstr ""
+msgstr "අඩුවෙන් පෙන්වන්න"
msgid "sign in"
msgstr "ඇතුළු වන්න"
@@ -46791,7 +47314,7 @@ msgid "source"
msgstr "මූලà·à·à·Šâ€à¶»à¶º"
msgid "source diff"
-msgstr ""
+msgstr "මූලà·à·à·Šâ€à¶» වෙනස"
msgid "specified top is not part of the tree"
msgstr ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr "නිවà·à¶»à¶¯à·’ ආකෘතිය."
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 569a5457348..152b26a1b31 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -664,8 +667,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -859,6 +862,9 @@ 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 ""
@@ -910,6 +916,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -922,13 +931,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1046,6 +1055,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2481,6 +2501,9 @@ 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 ""
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 3011882bd5b..62d3c8f78fa 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -610,6 +610,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -664,8 +667,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -859,6 +862,9 @@ 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 ""
@@ -910,6 +916,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -922,13 +931,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -1046,6 +1055,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1749,15 +1781,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1785,9 +1811,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2364,6 +2387,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2403,9 +2429,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2433,9 +2456,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2481,6 +2501,9 @@ 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 ""
@@ -4005,6 +4028,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4296,9 +4322,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4344,6 +4367,9 @@ 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 ""
@@ -4431,9 +4457,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4842,13 +4865,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4875,6 +4910,18 @@ 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 ""
@@ -5030,28 +5077,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -5069,6 +5119,9 @@ 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 ""
@@ -5096,9 +5149,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5442,9 +5492,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5488,7 +5535,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 ""
@@ -5603,18 +5653,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5843,7 +5911,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -6032,6 +6100,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 ""
@@ -6476,17 +6550,18 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 ""
@@ -6503,6 +6578,9 @@ 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 ""
@@ -6518,13 +6596,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7476,9 +7593,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8171,9 +8285,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8598,6 +8709,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8616,6 +8730,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8673,12 +8793,18 @@ 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 ""
@@ -10511,9 +10637,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11405,6 +11525,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11811,6 +11937,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11826,6 +11955,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11871,6 +12003,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11907,9 +12042,21 @@ 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 ""
@@ -12607,6 +12754,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12688,6 +12844,15 @@ 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 ""
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12934,6 +13096,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13189,7 +13354,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -14002,9 +14167,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14413,9 +14575,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16219,22 +16378,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16252,6 +16408,9 @@ 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 ""
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16544,6 +16700,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16961,6 +17120,13 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17593,9 +17767,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17779,6 +17950,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17899,6 +18070,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17950,6 +18124,9 @@ 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 ""
@@ -17962,6 +18139,9 @@ 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 ""
@@ -17974,6 +18154,9 @@ 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 ""
@@ -18292,16 +18475,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18679,7 +18856,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -19084,6 +19249,9 @@ 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 ""
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19225,6 +19399,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19243,7 +19426,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19359,12 +19542,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ 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 ""
@@ -19868,6 +20054,9 @@ 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 ""
@@ -20153,6 +20342,9 @@ msgstr[3] ""
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 ""
@@ -20198,9 +20390,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20591,9 +20762,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22357,13 +22543,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22849,6 +23035,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22972,7 +23161,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23244,15 +23433,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23535,19 +23718,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23820,7 +24003,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23832,6 +24018,48 @@ 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 ""
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -25825,12 +26050,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,7 +26074,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -26042,9 +26261,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26316,6 +26532,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26773,6 +26986,9 @@ 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 ""
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,6 +28295,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -28068,9 +28316,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, 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[2] ""
+msgstr[3] ""
+
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 ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28567,6 +28843,18 @@ 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 ""
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28795,6 +29104,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -29041,6 +29353,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29284,6 +29617,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 ""
@@ -29311,6 +29653,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29410,6 +29755,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29512,6 +29860,9 @@ 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 ""
@@ -29758,7 +30109,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30472,6 +30823,9 @@ 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 ""
@@ -30481,6 +30835,12 @@ 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 ""
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 ""
@@ -30598,6 +30964,9 @@ 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 ""
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31924,6 +32311,12 @@ 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 ""
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32405,9 +32795,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32424,6 +32811,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32760,9 +33141,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32871,6 +33249,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33247,15 +33634,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33938,6 +34311,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,6 +34339,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -34195,6 +34589,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -34210,6 +34607,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34261,6 +34664,9 @@ 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 ""
@@ -34339,6 +34745,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35409,6 +35848,15 @@ 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 ""
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36458,7 +36897,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37907,9 +38349,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38256,9 +38695,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38433,6 +38872,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38451,7 +38893,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38550,9 +38992,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39546,6 +39982,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39720,9 +40162,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,6 +40831,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40707,6 +41149,9 @@ 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 ""
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41615,6 +42066,9 @@ 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 ""
@@ -41678,6 +42132,9 @@ 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 ""
@@ -41723,9 +42180,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41948,6 +42399,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -42035,10 +42486,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42137,6 +42591,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42407,6 +42873,13 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 ""
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 ""
@@ -43980,6 +44470,12 @@ 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 ""
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr ""
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44308,10 +44811,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44320,10 +44826,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44682,9 +45234,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -45130,6 +45674,9 @@ 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 ""
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,7 +45701,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr ""
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+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 ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46406,6 +46975,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46584,6 +47156,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46631,12 +47206,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46767,9 +47333,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46807,9 +47370,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46930,21 +47487,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -47271,6 +47816,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index a93f583a5aa..951df618961 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 2089442eec9..b88558fa656 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-07-14 17:12\n"
+"PO-Revision-Date: 2022-08-12 18:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -535,6 +535,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -586,8 +589,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -775,6 +778,9 @@ 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 ""
@@ -826,6 +832,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -838,13 +847,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -961,6 +970,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1042,6 +1063,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1081,9 +1114,6 @@ msgstr[2] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1624,15 +1654,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1660,9 +1684,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2239,6 +2260,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2278,9 +2302,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2308,9 +2329,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2356,6 +2374,9 @@ 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 ""
@@ -3880,6 +3901,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4171,9 +4195,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4219,6 +4240,9 @@ 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 ""
@@ -4306,9 +4330,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4714,13 +4735,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4747,6 +4780,18 @@ 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 ""
@@ -4897,28 +4942,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4936,6 +4984,9 @@ 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 ""
@@ -4963,9 +5014,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5308,9 +5356,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5353,7 +5398,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5368,12 +5413,6 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5434,6 +5473,12 @@ 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 ""
@@ -5452,6 +5497,9 @@ 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 ""
@@ -5467,18 +5515,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5491,6 +5554,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5707,7 +5773,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5896,6 +5962,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6247,6 +6316,9 @@ 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 ""
@@ -6340,17 +6412,17 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
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 ""
@@ -6367,6 +6439,9 @@ 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 ""
@@ -6382,13 +6457,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6724,9 +6796,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7336,9 +7450,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8029,9 +8140,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8455,6 +8563,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8473,6 +8584,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8530,12 +8647,18 @@ 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 ""
@@ -10363,9 +10486,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10804,9 +10924,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11257,6 +11374,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11644,6 +11764,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11662,6 +11785,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11677,6 +11803,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11722,6 +11851,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11758,9 +11890,21 @@ 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 ""
@@ -12457,6 +12601,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12481,6 +12628,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12538,6 +12691,15 @@ 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 ""
@@ -12562,9 +12724,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12778,6 +12937,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13033,7 +13195,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13840,9 +14002,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14251,9 +14410,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14575,9 +14731,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15076,6 +15229,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16054,22 +16210,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16087,6 +16240,9 @@ 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 ""
@@ -16132,9 +16288,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16378,6 +16531,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16795,6 +16951,12 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16819,11 +16981,17 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16882,6 +17050,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16933,6 +17104,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17107,9 +17281,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17167,9 +17338,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17425,9 +17593,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17611,6 +17776,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17635,9 +17803,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17731,6 +17896,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17782,6 +17950,9 @@ 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 ""
@@ -17794,6 +17965,9 @@ 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 ""
@@ -17806,6 +17980,9 @@ 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 ""
@@ -18124,16 +18301,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18355,9 +18529,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18511,7 +18682,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18676,7 +18847,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18724,6 +18895,9 @@ 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 ""
@@ -18736,15 +18910,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18763,9 +18931,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18790,15 +18955,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18916,6 +19075,9 @@ 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 ""
@@ -18934,6 +19096,9 @@ 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 ""
@@ -18979,6 +19144,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19057,6 +19225,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19075,7 +19252,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19189,12 +19366,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19417,6 +19588,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19486,6 +19660,9 @@ 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 ""
@@ -19669,6 +19846,9 @@ 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 ""
@@ -19696,6 +19876,9 @@ 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 ""
@@ -19978,6 +20161,9 @@ msgstr[2] ""
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 ""
@@ -20023,9 +20209,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20083,9 +20266,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20128,9 +20308,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20140,18 +20317,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20170,9 +20341,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20341,9 +20509,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20416,9 +20581,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20491,12 +20653,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20512,9 +20668,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21538,7 +21691,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21616,7 +21769,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21631,9 +21784,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22039,6 +22189,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22054,12 +22207,36 @@ 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 ""
@@ -22081,6 +22258,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22111,10 +22291,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22123,6 +22303,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22150,9 +22333,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22180,13 +22360,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22672,6 +22852,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22795,7 +22978,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23065,15 +23248,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23356,19 +23533,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23635,7 +23812,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23647,6 +23827,48 @@ 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 ""
@@ -23974,9 +24196,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24238,7 +24457,7 @@ 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_whitelist}."
+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"
@@ -25636,12 +25855,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25666,7 +25879,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25852,9 +26065,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26125,6 +26335,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26155,9 +26368,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26458,9 +26668,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26581,6 +26788,9 @@ 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 ""
@@ -26722,6 +26932,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26887,6 +27106,12 @@ 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] ""
+msgstr[2] ""
+
msgid "On track"
msgstr ""
@@ -27361,9 +27586,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27457,6 +27679,9 @@ 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 ""
@@ -27778,6 +28003,12 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27787,6 +28018,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27796,6 +28030,9 @@ 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 ""
@@ -27853,6 +28090,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27871,9 +28111,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27889,6 +28135,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27946,6 +28195,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27997,18 +28249,30 @@ 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}, this operation is irreversible, 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[2] ""
+
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 ""
@@ -28264,6 +28528,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28369,6 +28636,18 @@ 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 ""
@@ -28525,6 +28804,9 @@ 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 ""
@@ -28543,6 +28825,15 @@ 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 ""
@@ -28564,6 +28855,12 @@ 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 ""
@@ -28585,6 +28882,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28597,6 +28897,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28843,6 +29146,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29011,9 +29317,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29026,12 +29341,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29050,6 +29371,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29086,6 +29410,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29101,6 +29431,9 @@ 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 ""
@@ -29113,6 +29446,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29212,6 +29548,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29314,6 +29653,9 @@ 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 ""
@@ -29560,7 +29902,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30274,6 +30616,9 @@ 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 ""
@@ -30283,6 +30628,12 @@ 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 ""
@@ -30361,6 +30712,9 @@ 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 ""
@@ -30373,6 +30727,9 @@ 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 ""
@@ -30400,6 +30757,9 @@ 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 ""
@@ -31588,18 +31948,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31726,6 +32104,12 @@ 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 ""
@@ -31996,12 +32380,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32035,6 +32413,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32206,9 +32587,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32224,6 +32602,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32296,6 +32677,9 @@ 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 ""
@@ -32359,12 +32743,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32506,12 +32884,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32560,9 +32932,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32671,6 +33040,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32683,6 +33055,9 @@ 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 ""
@@ -32845,6 +33220,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33040,15 +33418,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33073,24 +33442,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33169,6 +33526,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33313,10 +33673,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33421,12 +33781,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33502,6 +33856,12 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33559,6 +33919,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33724,6 +34087,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33748,6 +34114,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33856,6 +34225,9 @@ 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 ""
@@ -33916,9 +34288,18 @@ 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|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 ""
@@ -33964,6 +34345,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33979,6 +34363,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33994,6 +34381,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34036,6 +34426,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34045,6 +34438,9 @@ 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 ""
@@ -34123,6 +34519,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34453,6 +34864,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34513,6 +34930,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34786,6 +35206,12 @@ 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 ""
@@ -34951,6 +35377,9 @@ 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 group"
msgstr ""
@@ -34969,9 +35398,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35128,6 +35554,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35182,6 +35611,15 @@ 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 ""
@@ -35536,9 +35974,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35722,9 +36157,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35740,9 +36172,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36229,7 +36658,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36316,6 +36745,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36325,6 +36757,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36559,9 +36994,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37678,9 +38110,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38026,9 +38455,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38131,6 +38557,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38203,6 +38632,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38221,7 +38653,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38320,9 +38752,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38737,9 +39166,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39031,9 +39457,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39193,6 +39616,9 @@ 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 ""
@@ -39307,6 +39733,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39379,6 +39808,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39481,9 +39913,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39562,9 +39991,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39616,9 +40042,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39799,6 +40222,9 @@ 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 ""
@@ -40156,6 +40582,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40468,6 +40900,9 @@ 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 ""
@@ -40552,9 +40987,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40630,7 +41062,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40864,6 +41296,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41170,6 +41605,9 @@ 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 ""
@@ -41254,6 +41692,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41374,6 +41815,9 @@ 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 ""
@@ -41437,6 +41881,9 @@ 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 ""
@@ -41482,9 +41929,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41677,9 +42121,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41707,6 +42148,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41731,9 +42175,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41794,10 +42235,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41869,6 +42310,9 @@ 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 ""
@@ -41896,6 +42340,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42166,6 +42622,12 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42259,6 +42721,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42367,6 +42832,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42448,6 +42916,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42613,12 +43084,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42673,10 +43138,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42766,6 +43237,12 @@ 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 ""
@@ -43378,6 +43855,9 @@ 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 ""
@@ -43423,9 +43903,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43435,6 +43912,9 @@ 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 ""
@@ -43735,6 +44215,12 @@ 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 ""
@@ -43795,6 +44281,12 @@ 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] ""
+msgstr[2] ""
+
msgid "When:"
msgstr ""
@@ -43831,6 +44323,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43957,12 +44455,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44062,10 +44554,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44074,10 +44569,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44092,6 +44590,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44104,24 +44605,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44131,18 +44647,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44425,8 +44962,11 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44434,9 +44974,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44491,7 +45028,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44503,15 +45040,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44542,11 +45073,11 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44881,6 +45412,9 @@ 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 ""
@@ -44893,9 +45427,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44908,7 +45439,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45082,6 +45613,18 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+
+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[2] ""
+
msgid "Your groups"
msgstr ""
@@ -45178,9 +45721,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45205,11 +45745,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+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 ""
@@ -45364,6 +45901,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45445,6 +45985,9 @@ 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 ""
@@ -45547,9 +46090,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45565,6 +46114,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45838,6 +46390,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45865,6 +46420,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45904,9 +46462,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46003,6 +46558,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46087,9 +46645,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46141,6 +46696,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46318,6 +46876,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46363,12 +46924,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46486,9 +47041,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46498,9 +47050,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46537,9 +47086,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46573,9 +47119,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46660,21 +47203,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46996,6 +47527,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47008,6 +47542,9 @@ msgstr ""
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 ""
@@ -47119,13 +47656,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47146,6 +47683,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 375c1e995f6..155ea63dbd4 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -535,6 +535,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -586,8 +589,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -775,6 +778,9 @@ 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 ""
@@ -826,6 +832,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -838,13 +847,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -961,6 +970,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -1042,6 +1063,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -1081,9 +1114,6 @@ msgstr[2] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1624,15 +1654,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1660,9 +1684,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2239,6 +2260,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2278,9 +2302,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2308,9 +2329,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2356,6 +2374,9 @@ 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 ""
@@ -3880,6 +3901,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4171,9 +4195,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4219,6 +4240,9 @@ 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 ""
@@ -4306,9 +4330,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4714,13 +4735,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4747,6 +4780,18 @@ 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 ""
@@ -4897,28 +4942,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4936,6 +4984,9 @@ 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 ""
@@ -4963,9 +5014,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5308,9 +5356,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5353,7 +5398,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5368,12 +5413,6 @@ msgstr[2] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5434,6 +5473,12 @@ 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 ""
@@ -5452,6 +5497,9 @@ 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 ""
@@ -5467,18 +5515,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5491,6 +5554,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5707,7 +5773,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5896,6 +5962,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6247,6 +6316,9 @@ 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 ""
@@ -6340,17 +6412,17 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
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 ""
@@ -6367,6 +6439,9 @@ 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 ""
@@ -6382,13 +6457,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6724,9 +6796,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7336,9 +7450,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -8029,9 +8140,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8455,6 +8563,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8473,6 +8584,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8530,12 +8647,18 @@ 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 ""
@@ -10363,9 +10486,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10804,9 +10924,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11257,6 +11374,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11644,6 +11764,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11662,6 +11785,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11677,6 +11803,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11722,6 +11851,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11758,9 +11890,21 @@ 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 ""
@@ -12457,6 +12601,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12481,6 +12628,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12538,6 +12691,15 @@ 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 ""
@@ -12562,9 +12724,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12778,6 +12937,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -13033,7 +13195,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13840,9 +14002,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14251,9 +14410,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14575,9 +14731,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -15076,6 +15229,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -16054,22 +16210,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -16087,6 +16240,9 @@ 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 ""
@@ -16132,9 +16288,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16378,6 +16531,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16795,6 +16951,12 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16819,11 +16981,17 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16882,6 +17050,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16933,6 +17104,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17107,9 +17281,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17167,9 +17338,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17425,9 +17593,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17611,6 +17776,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17635,9 +17803,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17731,6 +17896,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17782,6 +17950,9 @@ 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 ""
@@ -17794,6 +17965,9 @@ 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 ""
@@ -17806,6 +17980,9 @@ 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 ""
@@ -18124,16 +18301,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18355,9 +18529,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18511,7 +18682,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18676,7 +18847,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18724,6 +18895,9 @@ 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 ""
@@ -18736,15 +18910,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18763,9 +18931,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18790,15 +18955,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18916,6 +19075,9 @@ 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 ""
@@ -18934,6 +19096,9 @@ 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 ""
@@ -18979,6 +19144,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -19057,6 +19225,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -19075,7 +19252,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19189,12 +19366,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19417,6 +19588,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19486,6 +19660,9 @@ 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 ""
@@ -19669,6 +19846,9 @@ 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 ""
@@ -19696,6 +19876,9 @@ 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 ""
@@ -19978,6 +20161,9 @@ msgstr[2] ""
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 ""
@@ -20023,9 +20209,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20083,9 +20266,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20128,9 +20308,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -20140,18 +20317,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -20170,9 +20341,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20341,9 +20509,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20416,9 +20581,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20491,12 +20653,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20512,9 +20668,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21538,7 +21691,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21616,7 +21769,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21631,9 +21784,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22039,6 +22189,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -22054,12 +22207,36 @@ 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 ""
@@ -22081,6 +22258,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22111,10 +22291,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22123,6 +22303,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -22150,9 +22333,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22180,13 +22360,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22672,6 +22852,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22795,7 +22978,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -23065,15 +23248,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23356,19 +23533,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23635,7 +23812,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23647,6 +23827,48 @@ 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 ""
@@ -23974,9 +24196,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24238,7 +24457,7 @@ 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_whitelist}."
+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"
@@ -25636,12 +25855,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25666,7 +25879,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25852,9 +26065,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -26125,6 +26335,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -26155,9 +26368,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26458,9 +26668,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26581,6 +26788,9 @@ 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 ""
@@ -26722,6 +26932,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26887,6 +27106,12 @@ 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] ""
+msgstr[2] ""
+
msgid "On track"
msgstr ""
@@ -27361,9 +27586,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27457,6 +27679,9 @@ 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 ""
@@ -27778,6 +28003,12 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27787,6 +28018,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27796,6 +28030,9 @@ 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 ""
@@ -27853,6 +28090,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27871,9 +28111,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27889,6 +28135,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27946,6 +28195,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27997,18 +28249,30 @@ 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}, this operation is irreversible, 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[2] ""
+
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 ""
@@ -28264,6 +28528,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28369,6 +28636,18 @@ 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 ""
@@ -28525,6 +28804,9 @@ 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 ""
@@ -28543,6 +28825,15 @@ 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 ""
@@ -28564,6 +28855,12 @@ 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 ""
@@ -28585,6 +28882,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28597,6 +28897,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28843,6 +29146,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -29011,9 +29317,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -29026,12 +29341,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -29050,6 +29371,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -29086,6 +29410,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29101,6 +29431,9 @@ 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 ""
@@ -29113,6 +29446,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29212,6 +29548,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29314,6 +29653,9 @@ 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 ""
@@ -29560,7 +29902,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30274,6 +30616,9 @@ 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 ""
@@ -30283,6 +30628,12 @@ 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 ""
@@ -30361,6 +30712,9 @@ 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 ""
@@ -30373,6 +30727,9 @@ 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 ""
@@ -30400,6 +30757,9 @@ 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 ""
@@ -31588,18 +31948,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31726,6 +32104,12 @@ 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 ""
@@ -31996,12 +32380,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32035,6 +32413,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32206,9 +32587,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32224,6 +32602,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32296,6 +32677,9 @@ 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 ""
@@ -32359,12 +32743,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32506,12 +32884,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32560,9 +32932,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32671,6 +33040,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32683,6 +33055,9 @@ 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 ""
@@ -32845,6 +33220,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -33040,15 +33418,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33073,24 +33442,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33169,6 +33526,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33313,10 +33673,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33421,12 +33781,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33502,6 +33856,12 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33559,6 +33919,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33724,6 +34087,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33748,6 +34114,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33856,6 +34225,9 @@ 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 ""
@@ -33916,9 +34288,18 @@ 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|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 ""
@@ -33964,6 +34345,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33979,6 +34363,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33994,6 +34381,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -34036,6 +34426,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -34045,6 +34438,9 @@ 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 ""
@@ -34123,6 +34519,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34453,6 +34864,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34513,6 +34930,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34786,6 +35206,12 @@ 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 ""
@@ -34951,6 +35377,9 @@ 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 group"
msgstr ""
@@ -34969,9 +35398,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35128,6 +35554,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -35182,6 +35611,15 @@ 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 ""
@@ -35536,9 +35974,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35722,9 +36157,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35740,9 +36172,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36229,7 +36658,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36316,6 +36745,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36325,6 +36757,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36559,9 +36994,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37678,9 +38110,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -38026,9 +38455,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38131,6 +38557,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -38203,6 +38632,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -38221,7 +38653,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38320,9 +38752,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38737,9 +39166,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -39031,9 +39457,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39193,6 +39616,9 @@ 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 ""
@@ -39307,6 +39733,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39379,6 +39808,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39481,9 +39913,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39562,9 +39991,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39616,9 +40042,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39799,6 +40222,9 @@ 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 ""
@@ -40156,6 +40582,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40468,6 +40900,9 @@ 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 ""
@@ -40552,9 +40987,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40630,7 +41062,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40864,6 +41296,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41170,6 +41605,9 @@ 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 ""
@@ -41254,6 +41692,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41374,6 +41815,9 @@ 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 ""
@@ -41437,6 +41881,9 @@ 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 ""
@@ -41482,9 +41929,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41677,9 +42121,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41707,6 +42148,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41731,9 +42175,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41794,10 +42235,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41869,6 +42310,9 @@ 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 ""
@@ -41896,6 +42340,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42166,6 +42622,12 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -42259,6 +42721,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42367,6 +42832,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42448,6 +42916,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42613,12 +43084,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42673,10 +43138,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42766,6 +43237,12 @@ 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 ""
@@ -43378,6 +43855,9 @@ 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 ""
@@ -43423,9 +43903,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43435,6 +43912,9 @@ 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 ""
@@ -43735,6 +44215,12 @@ 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 ""
@@ -43795,6 +44281,12 @@ 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] ""
+msgstr[2] ""
+
msgid "When:"
msgstr ""
@@ -43831,6 +44323,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43957,12 +44455,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -44062,10 +44554,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr ""
+
+msgid "WorkItem|Add a task"
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -44074,10 +44569,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44092,6 +44590,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44104,24 +44605,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44131,18 +44647,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44425,8 +44962,11 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44434,9 +44974,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44491,7 +45028,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44503,15 +45040,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44542,11 +45073,11 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44881,6 +45412,9 @@ 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 ""
@@ -44893,9 +45427,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44908,7 +45439,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -45082,6 +45613,18 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+
+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[2] ""
+
msgid "Your groups"
msgstr ""
@@ -45178,9 +45721,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45205,11 +45745,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+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 ""
@@ -45364,6 +45901,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45445,6 +45985,9 @@ 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 ""
@@ -45547,9 +46090,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45565,6 +46114,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45838,6 +46390,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45865,6 +46420,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45904,9 +46462,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -46003,6 +46558,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46087,9 +46645,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -46141,6 +46696,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46318,6 +46876,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46363,12 +46924,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46486,9 +47041,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46498,9 +47050,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46537,9 +47086,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46573,9 +47119,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46660,21 +47203,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46996,6 +47527,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -47008,6 +47542,9 @@ msgstr ""
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 ""
@@ -47119,13 +47656,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47146,6 +47683,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 8820d7bffe2..55df14500e9 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} kommer att tas bort! Är du säker?"
+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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 dagar"
-
msgid "3 hours"
msgstr "3 timmar"
-msgid "30 days"
-msgstr "30 dagar"
-
msgid "30 minutes"
msgstr "30 minuter"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 dagar"
-
msgid "8 hours"
msgstr "8 timmar"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Lägg till en punktlista"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Lägg till en tabell"
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ msgstr ""
msgid "Add existing confidential %{issuableType}"
msgstr "Lägg till existerande konfidentiell %{issuableType}"
+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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Skapa ny katalog"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 9d1bc615c8e..d0a593a9951 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-07-14 17:13\n"
+"PO-Revision-Date: 2022-08-12 18:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index 646984380de..318300fa996 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/th_TH/gitlab.po b/locale/th_TH/gitlab.po
index 71614eb8017..34b8c1c5f65 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-07-14 17:07\n"
+"PO-Revision-Date: 2022-08-12 18:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ 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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28201,6 +28483,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 ""
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index c2f8827d4f4..428a636471d 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr "%{address} geçersiz bir IP adresi aralığıdır"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} kaldırılacak! Emin misiniz?"
+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 ""
@@ -742,6 +748,9 @@ msgstr "%{labelStart}Yöntem:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}İsim alanları:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Tarayıcı:%{labelEnd}%{scanner}"
@@ -754,15 +763,15 @@ msgstr "%{labelStart}Önem derecesi:%{labelEnd} %{severity}"
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 "%{label_for_message} kullanılamaz"
-msgid "%{learn_more_link}."
-msgstr ""
-
msgid "%{lessThan} 1 hour"
msgstr ""
@@ -876,6 +885,18 @@ msgstr "%{openedEpics} açık, %{closedEpics} kapalı"
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} açık, %{closedIssues} kapalı"
+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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 "%{size} %{unit}"
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr "2FA"
msgid "2FADevice|Registered On"
msgstr "Kayıtlı"
-msgid "3 days"
-msgstr "3 gün"
-
msgid "3 hours"
msgstr "3 saat"
-msgid "30 days"
-msgstr "30 gün"
-
msgid "30 minutes"
msgstr "30 dakika"
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr "7 gün"
-
msgid "8 hours"
msgstr "8 saat"
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr "Tablo ekle"
-msgid "Add a task list"
-msgstr "Görev listesi ekle"
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr "Onay kuralı ekle"
msgid "Add approvers"
msgstr "Onaylayan ekle"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Yayın mesajı ekle"
@@ -2231,6 +2247,9 @@ msgstr "Ortam ekle"
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 "E-postalar için üstbilgi ve altbilgi ekleyin. Renk ayarları sadece uygulama arabirimi içinde uygulanacak unutmayın"
@@ -3755,6 +3774,9 @@ msgstr "Bütün dallar"
msgid "All changes are committed"
msgstr "Tüm değişiklikler işlendi"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr "Tüm e-posta adresleri işlemlerinizi tanımlamak için kullanılacaktır."
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr "Hedef dal"
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr "Geçerli birleştirme talebi onaylandı."
msgid "Approved-By"
msgstr "Tarafından onaylandı:"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Onaylayıcı"
@@ -5174,9 +5220,6 @@ msgstr "Bana atanan"
msgid "Assigned to you"
msgstr "Size atanan"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Vekil"
@@ -5218,8 +5261,8 @@ msgstr ""
msgid "At risk"
msgstr "Riskli"
-msgid "Attach a file"
-msgstr "Bir dosya ekle"
+msgid "Attach a file or image"
+msgstr ""
msgid "Attaching File - %{progress}"
msgstr ""
@@ -5232,12 +5275,6 @@ msgstr[1] "%d dosya ekleniyor"
msgid "Attaching the file failed."
msgstr "Dosya ekleme başarısız oldu."
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Denetim Etkinlikleri"
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "AÄŸustos"
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Otomatik olarak çözüldü"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ 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|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr ""
+
+msgid "BranchRules|Allowed to merge"
+msgstr ""
+
+msgid "BranchRules|Allowed to push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Dallar"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "Etkin"
@@ -7196,9 +7307,6 @@ msgstr "Bu dal için HEAD işlemi bulunamadı"
msgid "Can't find variable: ZiteReader"
msgstr "Değişken bulunamıyor: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "Kodu tarayamıyor musun?"
@@ -7887,9 +7995,6 @@ msgstr "Alt epik mevcut deÄŸil."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "Yeni Dizin OluÅŸtur"
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr "Siliniyor"
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] "Dağıtım"
msgstr[1] "Dağıtımlar"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr "Dağıtım Anahtarları"
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "E-posta"
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "İş hattı zamanlaması kaldırılamadı"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr "Åžub"
msgid "February"
msgstr "Åžubat"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr "Bilinmeyen konum"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "%{timeAgo} güncellendi"
@@ -17443,6 +17602,9 @@ msgstr "GitLab Sorunu"
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ msgstr ""
msgid "GitLabPages|Verified"
msgstr "Doğrulandı"
+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 ""
@@ -17638,6 +17806,9 @@ 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 "Sayfalarınız şunun altında sunulmaktadır:"
@@ -17956,16 +18127,13 @@ msgstr "Parçacıklarınıza gidin"
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr "Gruba genel bakış içeriği"
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Grup için Otomatik DevOps iş hattı güncellendi"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ msgstr "Grup oluÅŸtur"
msgid "GroupsNew|Create new group"
msgstr "Yeni grup oluÅŸtur"
+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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "Dosya yükle"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "Geçmiş"
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ msgstr ""
msgid "Iterations"
msgstr "Yinelemeler"
+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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr "En alta kaydır"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "En üste kaydır"
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr "Son başarılı güncelleme"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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 "Lisans UyumluluÄŸu"
-msgid "License Compliance| Used by"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr "Bağlantılı e-postalar (%{email_count})"
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr "Çıkış yapın ve farklı bir hesapla oturum açın"
msgid "Need help?"
msgstr "Yardım ister misiniz?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr "Epik Yok"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 "Ön izlenecek bir şey yok."
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ msgstr "Sonraki çalışma"
msgid "PipelineSchedules|None"
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|Provide a short description for this pipeline"
msgstr "Bu iş hattı için kısa bir açıklama girin"
@@ -28399,6 +28690,9 @@ msgstr "Hedef"
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr "Önceki"
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ msgstr "Proje kullanıcı adı"
msgid "Project uploads"
msgstr "Proje yüklemeleri"
+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 ""
@@ -30085,6 +30421,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Proje: %{name}"
+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 "Abone ol"
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 " veya grup"
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} geliştiriciler için yazılabilir olacak. Emin misiniz?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr ""
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "Dağıtıma izin verildi"
+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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 "Daha fazla dakika satın al"
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Profil resmini kaldır"
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr "Epikten bir sorun kaldırıldı."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr "Epikten bir sorunu kaldırır."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "Üst epik %{epic_ref} kaldırır."
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "deÄŸiÅŸtirilmiÅŸ test sonucu yok"
@@ -32833,15 +33202,6 @@ msgstr "EriÅŸim Talebi"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "%{time_ago} istendi"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr "Yol haritası"
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr "Çalışıyor"
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ msgstr "SSH Anahtarları"
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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] "viki sonucu"
msgstr[1] "viki sonucu"
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34286,6 +34693,9 @@ msgstr "Güvenlik Yapılandırması"
msgid "Security Dashboard"
msgstr "Güvenlik Kontrol Panosu"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Güvenlik gösterge panosu"
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 "Proje"
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr "Oturum açma kısıtlamaları"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr "Destek sayfası URL'si"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr "Ä°ptal"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Etiket oluÅŸtur"
@@ -37991,8 +38413,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Sürüm notlarını düzenle"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Mevcut dal adını, etiketi veya SHA'yı taahhüt et"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr "Grup iş hattı dakikaları sıfırlanırken bir hata oluştu."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "Kullanıcı iş hattı dakikaları sıfırlanırken bir hata oluştu."
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ msgstr "Bu dizin"
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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 "Bu depo"
@@ -40229,6 +40651,9 @@ 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 "Zaman aşımı"
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr "Tür"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr "Bilinmeyen biçim"
msgid "Unknown response text"
msgstr "Bilinmeyen yanıt metni"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr "Güncelleniyor"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr "Sertifikanız için özel bir anahtar yükleyin"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "Dosya yükle"
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr "Mevcut dönem kullanımı"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "Kullanıcı projeden başarıyla kaldırıldı."
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr "Kullanıcı başarıyla güncelleştirildi."
@@ -42126,6 +42580,9 @@ msgstr "Bot etkinliÄŸi"
msgid "UserProfile|Contributed projects"
msgstr "Katıldığı projeler"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr "Profili düzenle"
@@ -42207,6 +42664,9 @@ msgstr "Bu kullanıcı diğer kullanıcıları takip etmiyor."
msgid "UserProfile|Unconfirmed user"
msgstr "Onaylanmamış kullanıcı"
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr "Tümünü görüntüle"
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
msgstr ""
msgid "ValueStreamAnalytics|Tasks by type"
@@ -42524,6 +42985,12 @@ msgstr ""
msgid "Version"
msgstr "Sürüm"
+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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr "Viki"
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 "Gruplarınız"
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr "kendinizi atayın"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr "Tüm projeler"
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr "https://sizin-bitbucket-sunucunuz"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr "resim deÄŸiÅŸikliÄŸi"
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "%{path_lock_user_name} tarafından kilitlendi %{created_at}"
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 iÅŸlemi birleÅŸtir"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Kaynak dalı sil"
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr "Kapatılmadı"
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr "BirleÅŸtir"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr "BirleÅŸtiren:"
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Kaynak dal silindi"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Kaynak dal siliniyor"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "daraltmayı aç/kapat"
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr "tetiklendi"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index d0d0905592b..80434d31f2d 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-07-14 18:54\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -376,10 +376,10 @@ msgstr[3] "%d задач уÑпішно імпортовані з міткою"
msgid "%d job"
msgid_plural "%d jobs"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d завданнÑ"
+msgstr[1] "%d завданнÑ"
+msgstr[2] "%d завдань"
+msgstr[3] "%d завдань"
msgid "%d layer"
msgid_plural "%d layers"
@@ -488,10 +488,10 @@ msgstr[3] ""
msgid "%d reply"
msgid_plural "%d replies"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d відповідь"
+msgstr[1] "%d відповіді"
+msgstr[2] "%d відповідей"
+msgstr[3] "%d відповідей"
msgid "%d second"
msgid_plural "%d seconds"
@@ -610,6 +610,9 @@ msgstr "%{actionText} і повторно відкрити %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address} - недійÑний діапазон IP-адреÑ"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} має бути між %{min} і %{max}"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link} клонув(-ла) %{original_issue} до %{new_issue}."
@@ -630,24 +633,24 @@ msgstr "%{board_target} не знайдено"
msgid "%{bold_start}%{count}%{bold_end} issue"
msgid_plural "%{bold_start}%{count}%{bold_end} issues"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} задача"
+msgstr[1] "%{bold_start}%{count}%{bold_end} задачі"
+msgstr[2] "%{bold_start}%{count}%{bold_end} задач"
+msgstr[3] "%{bold_start}%{count}%{bold_end} задач"
msgid "%{bold_start}%{count}%{bold_end} member"
msgid_plural "%{bold_start}%{count}%{bold_end} members"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} учаÑник"
+msgstr[1] "%{bold_start}%{count}%{bold_end} учаÑники"
+msgstr[2] "%{bold_start}%{count}%{bold_end} учаÑників"
+msgstr[3] "%{bold_start}%{count}%{bold_end} учаÑників"
msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} відкритий запит на злиттÑ"
+msgstr[1] "%{bold_start}%{count}%{bold_end} відкритих запитів на злиттÑ"
+msgstr[2] "%{bold_start}%{count}%{bold_end} відкритих запитів на злиттÑ"
+msgstr[3] "%{bold_start}%{count}%{bold_end} відкритих запитів на злиттÑ"
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr "%{code_open}ЗамаÑковано:%{code_close} Сховано в журналах завдань. Повинні відповідати вимогам до маÑкуваннÑ."
@@ -664,12 +667,12 @@ msgstr "%{commit_author_link} автор %{commit_authored_timeago} та %{commi
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} заповнена вага"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount} із %{count} Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¾"
-msgstr[1] "%{completedCount} з %{count} завдань завершено"
-msgstr[2] "%{completedCount} з %{count} завдань завершено"
-msgstr[3] "%{completedCount} з %{count} завдань завершено"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "%{completedWeight} з %{totalWeight} ваги виконано"
@@ -701,20 +704,20 @@ msgstr "%{count} Ñхвалень від %{name}"
msgid "%{count} contact"
msgid_plural "%{count} contacts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} контакт"
+msgstr[1] "%{count} контакти"
+msgstr[2] "%{count} контактів"
+msgstr[3] "%{count} контактів"
msgid "%{count} files touched"
msgstr "%{count} файлів змінено"
msgid "%{count} item"
msgid_plural "%{count} items"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%{count} елемент"
+msgstr[1] "%{count} елементи"
+msgstr[2] "%{count} елементів"
+msgstr[3] "%{count} елементів"
msgid "%{count} items per page"
msgstr "%{count} елементів на Ñторінці"
@@ -859,6 +862,9 @@ msgstr "%{integrations_link_start}Інтеграції%{link_end} дозволÑ
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} буде видалено! Ви впевнені?"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} не Ñ–Ñнує або у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу на Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð² журнал чаÑу."
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable}(-у) вже призначено"
@@ -893,7 +899,7 @@ msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}Стан збою:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
-msgstr ""
+msgstr "%{labelStart}Стан збою:%{labelEnd} %{crash_type}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}Дані:%{labelEnd} %{evidence}"
@@ -910,6 +916,9 @@ msgstr "%{labelStart}Метод:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}проÑÑ‚Ñ–Ñ€ імен:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}проєкт:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Сканер:%{labelEnd} %{scanner}"
@@ -922,15 +931,15 @@ msgstr "%{labelStart}Рівень:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}ІнÑтрумент:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}Ðезмінена відповідь:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупний"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}."
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 година"
@@ -1046,6 +1055,18 @@ msgstr "%{openedEpics} відкрито, %{closedEpics} закрито"
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 "%{over_limit_message} Щоб отримати більше учаÑників, влаÑник групи може почати пробну верÑÑ–ÑŽ або перейти на платний рівень."
+
+msgid "%{over_limit_message} To get more seats, %{link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed}%% викориÑтано"
@@ -1130,6 +1151,20 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} мітка"
+msgstr[1] "%{selectedLabelsCount} мітки"
+msgstr[2] "%{selectedLabelsCount} міток"
+msgstr[3] "%{selectedLabelsCount} міток"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} проєкт"
+msgstr[1] "%{selectedProjectsCount} проєкти"
+msgstr[2] "%{selectedProjectsCount} проєктів"
+msgstr[3] "%{selectedProjectsCount} проєктів"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -1170,9 +1205,6 @@ msgstr[3] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}ПопередженнÑ:%{strongClose} поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ SAML може Ñпричинити автоматичне Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑƒÑ‡Ð°Ñників із груп."
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr "%{strongStart}Порада:%{strongEnd}Ви також можете перевірÑти запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾, %{linkStart}ДізнатиÑÑŒ більше%{linkEnd}"
@@ -1432,10 +1464,10 @@ msgstr "(відкликано)"
msgid "(squashes %d commit)"
msgid_plural "(squashes %d commits)"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "(об'єднано %d коміт)"
+msgstr[1] "(об'єднано %d коміта)"
+msgstr[2] "(об'єднано %d комітів)"
+msgstr[3] "(об'єднано %d комітів)"
msgid "(this user)"
msgstr "(цей кориÑтувач)"
@@ -1749,15 +1781,9 @@ msgstr "двофакторна автентифікаціÑ"
msgid "2FADevice|Registered On"
msgstr "ЗареєÑтровано"
-msgid "3 days"
-msgstr "3 дні"
-
msgid "3 hours"
msgstr "3 години"
-msgid "30 days"
-msgstr "30 днів"
-
msgid "30 minutes"
msgstr "30 хвилин"
@@ -1785,9 +1811,6 @@ msgstr "Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтратоÑ
msgid "409|There was a conflict with your request."
msgstr "Виник конфлікт із вашим запитом."
-msgid "7 days"
-msgstr "7 днів"
-
msgid "8 hours"
msgstr "8 годин"
@@ -1822,7 +1845,7 @@ msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is
msgstr "Ðе можливо отримати SSL Ñертифікат Let's Encrypt до того Ñк ваш домен буде перевірено."
msgid "A Work Item can be a parent or a child, but not both."
-msgstr ""
+msgstr "Робочий елемент може бути батьківÑьким або дочірнім, але не обома."
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Базова Ñторінка та Serverless функціÑ, що викориÑтовує AWS Lambda, AWS API Gateway та GitLab Pages"
@@ -2233,7 +2256,7 @@ msgid "AccessibilityReport|The accessibility scanning found an error of the foll
msgstr "Перевірка доÑтупноÑÑ‚Ñ– виÑвила помилку такого типу: %{code}"
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "ДоÑтупно Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкого кориÑтувача, Ñкий увійшов у ÑиÑтему."
msgid "Accessible by anyone, regardless of authentication."
msgstr ""
@@ -2275,7 +2298,7 @@ msgid "AccountValidation|Verification is required to discourage and reduce the a
msgstr "Потрібна перевірка, щоб запобігти та зменшити Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. Якщо ви підтверджуєте за допомогою кредитної або дебетової картки, %{strong_start}GitLab не зніме ÑÑ‚ÑÐ³Ð½ÐµÐ½Ð½Ñ Ð· вашої картки, вона викориÑтовуватиметьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ.%{strong_end} %{learn_more_link}"
msgid "Acknowledge"
-msgstr "Визнати"
+msgstr "Підтвердити"
msgid "Action"
msgstr "ДіÑ"
@@ -2364,6 +2387,9 @@ msgstr "Додати угоду про умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ–
msgid "Add a bullet list"
msgstr "Додати ненумерований ÑпиÑок"
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr "Додати згорнуту Ñекцію"
@@ -2403,9 +2429,6 @@ msgstr "Додати ÑÑƒÑ„Ñ–ÐºÑ Ð´Ð¾ електронної адреÑи ÑлÑ
msgid "Add a table"
msgstr "Додати таблицю"
-msgid "Add a task list"
-msgstr "Додати ÑпиÑок завдань"
-
msgid "Add a title..."
msgstr "Додати назву..."
@@ -2433,9 +2456,6 @@ msgstr "Додати правило затвердженнÑ"
msgid "Add approvers"
msgstr "Додати затверджуючих оÑіб"
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr "Додати широкомовне повідомленнÑ"
@@ -2481,6 +2501,9 @@ msgstr "Додати Ñередовище"
msgid "Add existing confidential %{issuableType}"
msgstr "Додати Ñ–Ñнуючий конфіденційний %{issuableType}"
+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 "Додати заголовок Ñ– футер в електронні лиÑти. Будь лаÑка, зверніть увагу, що Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñƒ будуть викориÑтовуватиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ в інтерфейÑÑ– заÑтоÑунку"
@@ -2971,7 +2994,7 @@ msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
msgstr ""
msgid "AdminSettings|Import sources"
-msgstr ""
+msgstr "Імпорт джерел"
msgid "AdminSettings|Inactive project deletion"
msgstr ""
@@ -3031,7 +3054,7 @@ msgid "AdminSettings|Preview payload"
msgstr ""
msgid "AdminSettings|Project export"
-msgstr ""
+msgstr "ЕкÑпорт проєкту"
msgid "AdminSettings|Protect CI/CD variables by default"
msgstr "ЗахиÑтити змінні CI/CD за замовчуваннÑм"
@@ -3643,7 +3666,7 @@ msgid "Alert"
msgstr "ПопередженнÑ"
msgid "AlertManagement|Acknowledged"
-msgstr "Підтверджено"
+msgstr "Підтвердити"
msgid "AlertManagement|Activity feed"
msgstr "Канал активноÑÑ‚Ñ–"
@@ -4005,6 +4028,9 @@ msgstr "Ð’ÑÑ– гілки"
msgid "All changes are committed"
msgstr "Ð’ÑÑ– зміни закомічені"
+msgid "All eligible users"
+msgstr "УÑÑ– дозволені кориÑтувачі"
+
msgid "All email addresses will be used to identify your commits."
msgstr "Ð’ÑÑ– адреÑи електронної пошти будуть викориÑтовуватиÑÑ Ð´Ð»Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— ваших комітів."
@@ -4296,9 +4322,6 @@ msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑ
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr "Помилка при отриманні гілок."
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr "Помилка при отриманні гілок. Повторіть пошук."
@@ -4344,6 +4367,9 @@ 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 "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚ÐµÐ³Ñ–Ð² ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Повторіть пошук."
@@ -4431,9 +4457,6 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні необх
msgid "An error occurred while loading the Test Reports tab."
msgstr "Виникла помилка при завантаженні вкладки зі звітами про теÑтуваннÑ."
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ токенів доÑтупу. Повторіть Ñпробу."
-
msgid "An error occurred while loading the blob controls."
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð±Ñ–Ð½Ð°Ñ€Ð½Ð¸Ñ… даних."
@@ -4778,7 +4801,7 @@ msgid "ApplicationSettings|Any user that visits %{host} and creates an account m
msgstr ""
msgid "ApplicationSettings|Any user that visits %{host} can create an account."
-msgstr ""
+msgstr "Будь-Ñкий кориÑтувач, Ñкий відвідує %{host} може Ñтворити обліковий запиÑ."
msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
@@ -4794,7 +4817,7 @@ msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr "Затвердити кориÑтувачів у ÑтатуÑÑ– очікуваного затвердженнÑ?"
msgid "ApplicationSettings|Approve users who are pending approval?"
-msgstr ""
+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."
@@ -4842,26 +4865,38 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr "Див.%{linkStart}Правила політики щодо паролів%{linkEnd} GitLab."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
-msgstr ""
+msgstr "ÐадіÑлати лиÑта на пошту з підтвердженнÑм під Ñ‡Ð°Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Sign-up enabled"
msgstr "РеєÑтрацію увімкнено"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
-msgstr ""
+msgstr "ТекÑÑ‚, Ñкий відображаєтьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€ÐµÑ”Ñтрації кориÑтувача. Markdown увімкнено."
msgid "ApplicationSettings|This option is only available on GitLab.com"
-msgstr ""
+msgstr "Цей параметр доÑтупний лише на GitLab.com"
msgid "ApplicationSettings|Upload denylist file"
msgstr ""
@@ -4875,6 +4910,18 @@ 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 "domain.com"
@@ -5030,29 +5077,32 @@ 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 approval by author."
-msgstr "Заборонити ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼."
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
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 when commits are added to the source branch"
-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 "Вимагати пароль кориÑтувача Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
@@ -5069,6 +5119,9 @@ 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 "Цей параметр налаштовано в %{groupName} Ñ– може бути змінене в налаштуваннÑÑ… групи лише адмініÑтратором або влаÑником групи."
+msgid "ApprovalSettings|When a commit is added:"
+msgstr ""
+
msgid "Approvals are optional."
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ð¾Ð²'Ñзкові."
@@ -5096,9 +5149,6 @@ msgstr "Затверджено поточний запит на злиттÑ."
msgid "Approved-By"
msgstr "Затверджений"
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr "Затверджуюча оÑоба"
@@ -5392,7 +5442,7 @@ msgid "Assign milestone"
msgstr "Призначити етап"
msgid "Assign myself"
-msgstr ""
+msgstr "Призначити Ñебе"
msgid "Assign reviewer"
msgstr "Призначити оглÑдача"
@@ -5442,9 +5492,6 @@ msgstr "Призначено мені"
msgid "Assigned to you"
msgstr "Ðазначено вам"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "Виконавець"
@@ -5488,8 +5535,8 @@ msgstr ""
msgid "At risk"
msgstr "З ризиком"
-msgid "Attach a file"
-msgstr "Прикріпити файл"
+msgid "Attach a file or image"
+msgstr "Прикріпіть файл або зображеннÑ"
msgid "Attaching File - %{progress}"
msgstr "ÐŸÑ€Ð¸ÐºÑ€Ñ–Ð¿Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ - %{progress}"
@@ -5504,12 +5551,6 @@ msgstr[3] "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %d файлів"
msgid "Attaching the file failed."
msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¸ÐºÑ€Ñ–Ð¿Ð¸Ñ‚Ð¸ файл."
-msgid "Attention"
-msgstr "Увага"
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr "Події аудиту"
@@ -5570,6 +5611,12 @@ 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 ""
@@ -5588,6 +5635,9 @@ 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 "СкаÑувати редагуваннÑ"
@@ -5603,18 +5653,33 @@ msgstr "URL-адреÑа призначеннÑ"
msgid "AuditStreams|Destinations receive all audit event data"
msgstr ""
+msgid "AuditStreams|Edit %{link}"
+msgstr "Редагувати %{link}"
+
msgid "AuditStreams|Header"
msgstr "Заголовок"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
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 count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5627,6 +5692,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr "ЗначеннÑ"
+msgid "AuditStreams|Verification token"
+msgstr "Токен перевірки"
+
msgid "Aug"
msgstr "Ñерп."
@@ -5658,7 +5726,7 @@ msgid "Authenticated Git LFS requests"
msgstr "Ðвтентифіковані запити Git LFS"
msgid "Authenticated web rate limit period in seconds"
-msgstr ""
+msgstr "Період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти веб в Ñекундах з автентифікацією"
msgid "Authenticated web requests"
msgstr "Ðутентифіковані веб-запити"
@@ -5843,8 +5911,8 @@ msgstr ""
msgid "Automatically resolved"
msgstr "Вирішено автоматично"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "Ðвтоматично оноÑлювати гілки та теги цього проєкту із репозиторію upstream щогодини."
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr ""
msgid "Autosave|Note"
msgstr "Примітка"
@@ -5907,7 +5975,7 @@ msgid "Background color"
msgstr "Колір фону"
msgid "BackgroundMigrations|Background Migrations"
-msgstr ""
+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 ""
@@ -5916,7 +5984,7 @@ msgid "BackgroundMigrations|Batch size"
msgstr ""
msgid "BackgroundMigrations|Database"
-msgstr ""
+msgstr "База даних"
msgid "BackgroundMigrations|Failed jobs:"
msgstr ""
@@ -6032,6 +6100,9 @@ msgstr "ЗапуÑтити CI/CD конвеєри за допомогою Atlass
msgid "BambooService|The user with API access to the Bamboo server."
msgstr "КориÑтувач із API доÑтупом до Bambooo Ñервера."
+msgid "Banned"
+msgstr "Заблокований"
+
msgid "Banner message"
msgstr "Заголовок повідомленнÑ"
@@ -6042,7 +6113,7 @@ msgid "Batch size"
msgstr ""
msgid "Batched Job|Background Migrations"
-msgstr ""
+msgstr "Міграції у фоновому режимі"
msgid "Batched Job|Batched Job (Id: %{id})"
msgstr ""
@@ -6383,6 +6454,9 @@ 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 "Безкоштовний рівень та пробні групи можуть запрошувати макÑимум 20 учаÑників на день."
+
msgid "Billings|In a seat"
msgstr ""
@@ -6476,17 +6550,18 @@ msgstr "ПереглÑнути вÑÑ– плани"
msgid "Billing|Export list"
msgstr "ЕкÑпортувати ÑпиÑок"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr "З 22 Ñ‡ÐµÑ€Ð²Ð½Ñ 2022 року (GitLab 15.1) безкоштовні групи будуть обмежені до 5 учаÑників"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "З 19 Ð¶Ð¾Ð²Ñ‚Ð½Ñ 2022 року безкоштовні групи будуть обмежені до 5 учаÑників"
msgid "Billing|Group invite"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð² групу"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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[2] ""
+msgstr[3] ""
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 "УчаÑники, Ñкі були запрошені за допомогою Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ групи, не можуть бути видалені. Ви можете або видалити вÑÑŽ групу, або попроÑити влаÑника групи видалити учаÑника."
@@ -6503,6 +6578,9 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ проєкту"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "Видалити кориÑтувача %{username} з вашої підпиÑки"
+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 "Увімкнути/вимкнути подробиці міÑцÑ."
@@ -6518,13 +6596,10 @@ msgstr ""
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ кориÑтувача %{username} з вашої підпиÑки. Якщо ви продовжите, кориÑтувача буде видалено з групи %{namespace} та вÑÑ–Ñ… Ñ—Ñ— підгруп та проєктів. Цю дію не можна буде відмінити."
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6863,9 +6938,51 @@ msgstr "Гілку не завантажено: %{branchId}"
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+msgstr "ПідтримуютьÑÑ%{linkStart}шаблони%{linkEnd}, такі Ñк *-stable або production/*."
+
+msgid "BranchRules|Allow all users with push access to %{linkStart}force push%{linkEnd}."
+msgstr ""
+
+msgid "BranchRules|Allowed to merge"
+msgstr "Дозволено злиттÑ"
+
+msgid "BranchRules|Allowed to push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð³Ñ–Ð»Ð¾Ðº ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
+
+msgid "BranchRules|Branch"
+msgstr "Гілка"
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr "Створити шаблон: %{searchTerm}"
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "Гілки"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "Гілки: %{source_branch} до %{target_branch}"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "Гілки: %{source_branch} → %{target_branch}"
+
msgid "Branches|Active"
msgstr "Ðктивні"
@@ -7476,9 +7593,6 @@ msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
msgid "Can't find variable: ZiteReader"
msgstr "Ðеможливо знайти змінну: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr "Ðеможливо Ñканувати код?"
@@ -8171,9 +8285,6 @@ msgstr "Дочірній епік не Ñ–Ñнує."
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr "Дочірні елементи"
-
msgid "Chinese language support using"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¸Ñ‚Ð°Ð¹Ñької мови"
@@ -8581,10 +8692,10 @@ msgid "CloudSeed|Available database services through which instances may be crea
msgstr ""
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "СкаÑувати"
msgid "CloudSeed|Cloud Firestore"
-msgstr ""
+msgstr "Cloud Firestore"
msgid "CloudSeed|Cloud SQL for MySQL"
msgstr "Cloud SQL Ð´Ð»Ñ MySQL"
@@ -8598,11 +8709,14 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr "ÐалаштуваннÑ"
+
msgid "CloudSeed|Create cluster"
-msgstr ""
+msgstr "Створити клаÑтер"
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "Створити базу даних"
msgid "CloudSeed|Create instance"
msgstr ""
@@ -8616,8 +8730,14 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr "ВерÑÑ–Ñ Ð±Ð°Ð·Ð¸ даних"
+msgid "CloudSeed|Databases"
+msgstr "Бази даних"
+
+msgid "CloudSeed|Deployments"
+msgstr "РозгортаннÑ"
+
msgid "CloudSeed|Description"
-msgstr ""
+msgstr "ОпиÑ"
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
msgstr ""
@@ -8673,14 +8793,20 @@ 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 ""
+msgstr "СервіÑ"
+
+msgid "CloudSeed|Service Account"
+msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ñлужби"
msgid "CloudSeed|Services"
-msgstr ""
+msgstr "СервіÑи"
msgid "CloudSeed|There are no instances to display."
msgstr ""
@@ -8800,10 +8926,10 @@ msgid "ClusterAgents|Connect a Kubernetes cluster"
msgstr ""
msgid "ClusterAgents|Connect a cluster"
-msgstr ""
+msgstr "Підключити клаÑтер"
msgid "ClusterAgents|Connect a cluster (agent)"
-msgstr ""
+msgstr "Підключити клаÑтер (агент)"
msgid "ClusterAgents|Connect a cluster (certificate - deprecated)"
msgstr ""
@@ -9104,7 +9230,7 @@ msgid "ClusterIntegration|Choose which of your environments will use this cluste
msgstr "Виберіть, Ñке із ваших Ñередовищ буде викориÑтовувати цей клаÑтер."
msgid "ClusterIntegration|Civo Kubernetes"
-msgstr ""
+msgstr "Civo Kubernetes"
msgid "ClusterIntegration|Clear cluster cache"
msgstr "ОчиÑтити кеш клаÑтера"
@@ -10511,9 +10637,6 @@ msgstr "Ви можете додати образ до цього реєÑтру
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr "ЗміÑÑ‚"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10952,9 +11075,6 @@ msgstr "Створити %{type}"
msgid "Create %{workspace} label"
msgstr "Створити мітку %{workspace}"
-msgid "Create Google Cloud project"
-msgstr "Створити проєкт Google Cloud"
-
msgid "Create New Directory"
msgstr "Створити новий каталог"
@@ -11112,7 +11232,7 @@ msgid "Create new project"
msgstr "Створити новий проєкт"
msgid "Create new..."
-msgstr ""
+msgstr "Створити новий..."
msgid "Create one"
msgstr "Створити"
@@ -11405,6 +11525,9 @@ msgstr "Кредитна картка:"
msgid "Critical vulnerabilities present"
msgstr "ПриÑутні критичні вразливоÑÑ‚Ñ–"
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11793,6 +11916,9 @@ msgstr "Ð”Ð»Ñ Ð²Ñ–Ð·ÑƒÐ°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ— DAG потрібно щонайменшÐ
msgid "DAST Configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ DAST"
+msgid "DAST configuration not found"
+msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ DAST не знайдена"
+
msgid "DAST profile not found: %{name}"
msgstr "Профіль DAST не знайдено: %{name}"
@@ -11811,6 +11937,9 @@ msgstr "Ð’ Ñередньому (оÑтанні %{days}d)"
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr "Дата"
@@ -11826,6 +11955,9 @@ msgstr "ЧаÑтота розгортаннÑ"
msgid "DORA4Metrics|Lead time for changes"
msgstr "Ð§Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ð½"
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr "Ð’ Ñередньому (оÑтанні %{days}d)"
@@ -11871,6 +12003,9 @@ msgstr "Графік відображає Ñередній Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ об’
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr "DSN"
@@ -11907,9 +12042,21 @@ 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 ""
+msgid "DastConfig|Enabled"
+msgstr "Увімкнено"
+
msgid "DastConfig|Generate code snippet"
msgstr ""
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr "ОÑтаннє ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿ÑƒÑ‰ÐµÐ½Ð¾ %{runTimeAgo} в конвеєрі "
+
+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 "ПаÑивне ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñтежує вÑÑ– HTTP-Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (запити та відповіді), надіÑлані цільовому об’єкту. Ðктивне ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ñ‚Ð°ÐºÑƒÑ” цільовий об’єкт, щоб знайти потенційні вразливоÑÑ‚Ñ–."
@@ -12530,7 +12677,7 @@ msgid "Definition"
msgstr "ВизначеннÑ"
msgid "Delay 2FA enforcement (hours)"
-msgstr ""
+msgstr "Затримка заÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ 2FA (годин)"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
msgstr "Ви впевнені, що ви хочете запуÑтити %{jobName} відразу? Ð’ іншому випадку це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ виконано автоматично по завершенню таймера."
@@ -12607,6 +12754,9 @@ msgstr "Видалити ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
msgid "Delete file"
msgstr "Видалити файл"
+msgid "Delete identity"
+msgstr "Видалити ідентифікацію"
+
msgid "Delete image"
msgstr ""
@@ -12631,6 +12781,12 @@ msgstr "Видалити розклад конвеєра"
msgid "Delete project"
msgstr "Видалити проєкт"
+msgid "Delete release"
+msgstr "Видалити реліз"
+
+msgid "Delete release %{release}?"
+msgstr "Видалити реліз %{release}?"
+
msgid "Delete row"
msgstr "Видалити Ñ€Ñдок"
@@ -12688,6 +12844,15 @@ 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 "Ð”Ð»Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації дивітьÑÑ %{docsPathStart}Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ%{docsPathEnd}."
+
+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 "'%{name}' Потік значень видалено"
@@ -12712,9 +12877,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr "ВидалÑÑ” гілку-джерело"
-msgid "Deletes the source branch."
-msgstr "ВидалÑÑ” гілку-джерело."
-
msgid "Deleting"
msgstr "ВидаленнÑ"
@@ -12934,6 +13096,9 @@ msgstr[1] "РозгортаннÑ"
msgstr[2] "Розгортань"
msgstr[3] "Розгортань"
+msgid "Deploy Key"
+msgstr "Ключ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
+
msgid "Deploy Keys"
msgstr "Ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
@@ -13189,8 +13354,8 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
-msgstr ""
+msgid "DeploymentApproval|Approved %{time}"
+msgstr "Затверджено %{time}"
msgid "DeploymentApproval|Approved by you %{time}"
msgstr ""
@@ -13757,17 +13922,17 @@ msgstr "(базова)"
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] "%d додаваннÑ"
-msgstr[1] "%d додаваннÑ"
-msgstr[2] "%d додавань"
-msgstr[3] "%d додавань"
+msgstr[0] "%d доданий"
+msgstr[1] "%d додано"
+msgstr[2] "%d додано"
+msgstr[3] "%d додано"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] "%d видаленнÑ"
-msgstr[1] "%d видаленнÑ"
-msgstr[2] "%d видалень"
-msgstr[3] "%d видалень"
+msgstr[0] "%d видалено"
+msgstr[1] "%d видалено"
+msgstr[2] "%d видалено"
+msgstr[3] "%d видалено"
msgid "Diffs|Expand all lines"
msgstr ""
@@ -13940,7 +14105,7 @@ msgid "Dismiss trial promotion"
msgstr "Відхилити пробну верÑÑ–ÑŽ"
msgid "Dismissable"
-msgstr ""
+msgstr "Можна відхилити"
msgid "Dismissed"
msgstr "Відхилено"
@@ -14002,9 +14167,6 @@ msgstr "URL Ñторінки документації"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "Документів переіндекÑовано: %{processed_documents} (%{percentage}%%)"
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr "Домен"
@@ -14413,9 +14575,6 @@ msgstr "Ðемає. Виберіть проÑтори імен Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐº
msgid "Elastic|None. Select projects to index."
msgstr "Ðемає. Виберіть проєкти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ."
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr "Електронна пошта"
@@ -14603,13 +14762,13 @@ msgid "Enable and disable Service Desk. Some additional configuration might be r
msgstr ""
msgid "Enable authenticated API request rate limit"
-msgstr ""
+msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти API запитів з автентифікацією"
msgid "Enable authenticated Git LFS request rate limit"
msgstr "Увімкнути перевірене Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– запитів Git LFS"
msgid "Enable authenticated web request rate limit"
-msgstr ""
+msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти вебзапитів з автентифікацією"
msgid "Enable authentication"
msgstr "Увімкнути автентифікацію"
@@ -14699,10 +14858,10 @@ msgid "Enable two-factor authentication"
msgstr "Увімкнути двофакторну автентифікацію"
msgid "Enable unauthenticated API request rate limit"
-msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти запитів API без автентифікації"
+msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти API запитів без автентифікації"
msgid "Enable unauthenticated web request rate limit"
-msgstr ""
+msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти вебзапитів без автентифікації"
msgid "Enable user deactivation emails"
msgstr ""
@@ -14737,9 +14896,6 @@ msgstr "Увімкнути протоколи доÑтупу до Git"
msgid "Enabled OAuth authentication sources"
msgstr "Увімкнено джерела автентифікації OAuth"
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr "Ð§Ð°Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ"
@@ -15065,10 +15221,10 @@ msgid "Environments|Updated"
msgstr "Оновлено"
msgid "Environments|You don't have any environments."
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” жодного Ñередовища."
msgid "Environments|You don't have any stopped environments."
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” зупинених Ñередовищ."
msgid "Environments|by %{avatar}"
msgstr ""
@@ -15238,6 +15394,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr "Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ вразливоÑÑ‚Ñ–: %{errors}"
+
msgid "Error deleting project. Check logs for error details."
msgstr "Помилка при видаленні проєкту. Перевірте журнали Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð¸Ñ†ÑŒ про помилку."
@@ -15810,7 +15969,7 @@ msgid "Expiration date"
msgstr "Термін дії"
msgid "Expiration date (optional)"
-msgstr ""
+msgstr "Термін дії (необов'Ñзково)"
msgid "Expiration date:"
msgstr "Термін дії:"
@@ -16219,24 +16378,21 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Zoom-зуÑтріч"
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-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 request attention because no user was found."
-msgstr ""
-
msgid "Failed to retrieve page"
msgstr ""
@@ -16252,6 +16408,9 @@ msgstr "Ðе вдалÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ Ð½Ð°Ð»Ð°ÑˆÐ½ÑƒÐ²Ð°Ð½Ð½Ñ (%{error_mes
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 "Ðе вдалоÑÑ Ð²Ñтановити заплановану дату Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñ‚Ð¾Ð¼Ñƒ що формат дати Ñ” неправильним."
@@ -16297,9 +16456,6 @@ msgstr ""
msgid "Fast timeout"
msgstr "Швидкий тайм-аут"
-msgid "Fast-forward merge without a merge commit"
-msgstr "Fast-forward Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÐµÐ· окремого коміту злиттÑ"
-
msgid "Faster releases. Better code. Less pain."
msgstr "Швидші релізи. Кращий код. Менше болю."
@@ -16544,6 +16700,9 @@ msgstr "лют."
msgid "February"
msgstr "лютий"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16557,7 +16716,7 @@ msgid "File %{current} of %{total}"
msgstr "Файл %{current} з %{total}"
msgid "File Hooks"
-msgstr ""
+msgstr "Файлові Хуки"
msgid "File Hooks (%{count})"
msgstr "Файлові Хуки (%{count})"
@@ -16961,6 +17120,13 @@ msgstr "Фреймворк уÑпішно видалено"
msgid "Free Trial of GitLab.com Ultimate"
msgstr "Безкоштовна пробна верÑÑ–Ñ GitLab.com Ultimate"
+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] ""
+msgstr[3] ""
+
msgid "Freeze end"
msgstr ""
@@ -16985,11 +17151,19 @@ msgstr "З %{code_open}%{source_title}%{code_close} в"
msgid "From %{providerTitle}"
msgstr "З %{providerTitle}"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "From issue creation until deploy to production"
msgstr "З моменту ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– до Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
@@ -17048,6 +17222,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -17101,6 +17278,9 @@ msgstr "Синхронізовано з%{component}"
msgid "Geo|%{component} verified"
msgstr "%{component} підтверджено"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr "%{label} %{timeAgo}"
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -17275,9 +17455,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr "Ð’ процеÑÑ–"
-msgid "Geo|In sync"
-msgstr "Синхронізовано"
-
msgid "Geo|Internal URL"
msgstr ""
@@ -17335,9 +17512,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr "Ðе Ñинхронізовано"
-
msgid "Geo|Nothing found…"
msgstr "Ðічого не знайдено…"
@@ -17593,9 +17767,6 @@ msgstr "Ðездоровий"
msgid "Geo|Unknown"
msgstr "Ðевідомий"
-msgid "Geo|Unknown state"
-msgstr "Ðевідомий Ñтан"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "Оновлено %{timeAgo}"
@@ -17779,6 +17950,9 @@ msgstr "Задача GitLab"
msgid "GitLab KAS"
msgstr "GitLab KAS"
+msgid "GitLab Logo"
+msgstr "Логотип GitLab"
+
msgid "GitLab Pages"
msgstr "Gitlab Pages"
@@ -17803,9 +17977,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr "Запит на обліковий Ð·Ð°Ð¿Ð¸Ñ GitLab відхилено"
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ GitLab та Google Cloud незавершена. Можливо, ваша команда ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ GitLab зможе це владнати. Ви можете надіÑлати їм ці логи:"
-
msgid "GitLab commit"
msgstr "GitLab коміт"
@@ -17899,6 +18070,9 @@ msgstr "Може бути перевизначено Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ прÐ
msgid "GitLabPages|Certificate: %{subject}"
msgstr "Сертифікат: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "Перевірити ÑÑ‚Ð°Ñ‚ÑƒÑ ÐšÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°"
+
msgid "GitLabPages|Configure pages"
msgstr "Параметри Ñторінок"
@@ -17950,6 +18124,9 @@ msgstr "Зберегти зміни"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ %{domain}. Перевірте %{link_start}деталі домену%{link_end}, щоб повторити Ñпробу."
+msgid "GitLabPages|Start over"
+msgstr "Почати Ñпочатку"
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr "Підтримка доменів Ñ– Ñертифікатів вимкнена. ПопроÑÑ–Ñ‚ÑŒ адмініÑтратора вашої ÑиÑтеми ввімкнути його."
@@ -17962,6 +18139,9 @@ 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 "Якщо ввімкнено, уÑÑ– Ñпроби відвідати ваш вебÑайт через HTTP автоматично перенаправлÑÑŽÑ‚ÑŒÑÑ Ð½Ð° HTTPS за допомогою відповіді з кодом ÑтатуÑу 301. Потрібний дійÑний Ñертифікат Ð´Ð»Ñ Ð²ÑÑ–Ñ… доменів. %{docs_link_start}ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{link_end}"
@@ -17974,6 +18154,9 @@ msgstr "За допомогою GitLab Pages ви можете розміщувÐ
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 "Ваш Ñайт Ñторінок ще не налаштовано. ПереглÑньте документацію %{docs_link_start}GitLab Pages%{link_end} щоб дізнатиÑÑ, Ñк завантажити ваш Ñтатичний Ñайт Ñ– надати GitLab його обÑлуговуваннÑ. Ви також можете взÑти Ð½Ð°Ñ‚Ñ…Ð½ÐµÐ½Ð½Ñ Ð· %{samples_link_start}зразків проєктів 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 ""
+
msgid "GitLabPages|Your pages are served under:"
msgstr "Ваші Ñторінки показуютьÑÑ Ð½Ð°:"
@@ -18292,18 +18475,15 @@ msgstr "Перейти до ваших Ñніпетів"
msgid "Google Cloud"
msgstr "Google Cloud"
+msgid "Google Cloud Error - %{error}"
+msgstr "Помилка Google Cloud - %{error}"
+
msgid "Google Cloud Project"
msgstr "Проєкт Google Cloud"
msgid "Google Cloud authorizations required"
msgstr "Потрібно авторизуватиÑÑ Ð² Google Cloud"
-msgid "Google Cloud project misconfigured"
-msgstr "Ðеправильно налаштовано проєкт Google Cloud"
-
-msgid "Google Cloud project required"
-msgstr "Потрібен проєкт Google Cloud"
-
msgid "GoogleCloud|Cancel"
msgstr ""
@@ -18523,9 +18703,6 @@ msgstr ""
msgid "Group overview content"
msgstr "ВміÑÑ‚ оглÑдової Ñторінки групи"
-msgid "Group owners can register group runners in the %{link}"
-msgstr "ВлаÑники групи можуть реєÑтрувати групові runner'и в %{link}"
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr "ШлÑÑ… групи вже викориÑтовуєтьÑÑ. Ми пропонуємо доÑтупний."
@@ -18679,7 +18856,7 @@ msgstr "Ви впевнені, що хочете Ñкинути токен SCIM?
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18844,7 +19021,7 @@ msgstr "ЗаÑтоÑовуєтьÑÑ Ð´Ð¾ вÑÑ–Ñ… підгруп, Ñкщо не
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Конвеєр Auto DevOps оновлено Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18892,6 +19069,9 @@ 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 ""
@@ -18904,15 +19084,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18931,9 +19105,6 @@ msgstr "Заборонити форк за межами групи"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð¾Ñ€Ð¾Ð½Ð¸ форку не збережено"
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18958,15 +19129,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "Конвеєр Auto DevOps запуÑкаєтьÑÑ, Ñкщо не знайдено жодного альтернативного файлу конфігурації CI."
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 "Проєкти у цій підгрупі можна вибрати Ñк шаблони Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів, Ñтворених у цій групі. %{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{link_end}"
@@ -19084,6 +19249,9 @@ 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 "%{groupsLinkStart}Групи%{groupsLinkEnd} та %{subgroupsLinkStart}підгрупи%{subgroupsLinkEnd} дозволÑÑŽÑ‚ÑŒ керувати та Ñпівпрацювати між кількома проєктами. УчаÑники групи мають доÑтуп до вÑÑ–Ñ… Ñвоїх проєктів."
+
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 "%{linkStart}Групи%{linkEnd} дозволÑÑŽÑ‚ÑŒ вам керувати та Ñпівпрацювати з кількома проєктами. УчаÑники групи мають доÑтуп до вÑÑ–Ñ… Ñ—Ñ— проєктів."
@@ -19102,6 +19270,9 @@ 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 ""
@@ -19139,7 +19310,7 @@ msgid "GroupsNew|Provide credentials for another instance of GitLab to import yo
msgstr ""
msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
-msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð·Ð°Ñтаріла Ñ– замінена на %{docs_link_start}груповою міграцією%{docs_link_end}."
+msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð·Ð°Ñтаріла Ñ– замінена на %{docs_link_start}групову міграцію%{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 ""
@@ -19147,6 +19318,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr "Завантажити файл"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "Також ви можете %{linkStart}імпортувати Ñ–Ñнуючу групу%{linkEnd}."
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "напр. h8d3f016698e..."
@@ -19184,7 +19358,7 @@ msgid "Groups|Avatar will be removed. Are you sure?"
msgstr ""
msgid "Groups|Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "Зміна URL-адреÑи групи може мати небажані побічні ефекти."
msgid "Groups|Checking group URL availability..."
msgstr ""
@@ -19193,16 +19367,16 @@ msgid "Groups|Enter a descriptive name for your group."
msgstr ""
msgid "Groups|Group ID"
-msgstr ""
+msgstr "Ідентифікатор групи"
msgid "Groups|Group URL"
-msgstr ""
+msgstr "URL-адреÑа групи"
msgid "Groups|Group avatar"
msgstr "Ðватар групи"
msgid "Groups|Group description (optional)"
-msgstr ""
+msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸ (необов'Ñзково)"
msgid "Groups|Group name"
msgstr "Ðазва групи"
@@ -19225,6 +19399,15 @@ msgstr "Видалити аватар"
msgid "Groups|Save changes"
msgstr "Зберегти зміни"
+msgid "Groups|Subgroup URL"
+msgstr "URL підгрупи"
+
+msgid "Groups|Subgroup name"
+msgstr "Ðазва підгрупи"
+
+msgid "Groups|Subgroup slug"
+msgstr "ШлÑÑ… підгрупи"
+
msgid "Guideline"
msgstr "Керівництво"
@@ -19243,8 +19426,8 @@ msgstr "Базовий HTTP: відмовлено у доÑтупі\\nВи поÐ
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$HARBOR_PASSWORD’, ‘$HARBOR_URL’ and ‘$HARBOR_PROJECT’ will be created for CI/CD use."
-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|Base URL of the Harbor instance."
msgstr ""
@@ -19315,7 +19498,7 @@ msgid "HarborRegistry|Please try different search criteria"
msgstr ""
msgid "HarborRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "Опубліковано %{timeInfo}"
msgid "HarborRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
msgstr ""
@@ -19359,12 +19542,6 @@ msgstr "Хешовані шлÑхи Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr "Хешоване Ñховище більше не може бути відключено Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів"
-msgid "Have a quick chat with us about your experience."
-msgstr "Швидкий чат з нами про ваш доÑвід."
-
-msgid "Have more to say about GitLab?"
-msgstr "Вам Ñ” що розповіÑти про GitLab?"
-
msgid "Header logo"
msgstr "Логотип заголовка"
@@ -19589,6 +19766,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "ІÑторіÑ"
@@ -19658,6 +19838,9 @@ 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 ""
@@ -19841,6 +20024,9 @@ msgstr ""
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr ""
+msgid "Identity|Provider ID"
+msgstr "ID поÑтачальника"
+
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 "Якщо будь-Ñке проіндекÑоване поле перевищує це обмеженнÑ, воно обрізаєтьÑÑ Ð´Ð¾ цієї кількоÑÑ‚Ñ– Ñимволів. Решта вміÑту не індекÑуєтьÑÑ Ñ‚Ð° не підлÑгає пошуку. Це не ÑтоÑуєтьÑÑ Ñ–Ð½Ð´ÐµÐºÑÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ та вікі. Ð”Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ñ— кількоÑÑ‚Ñ– Ñимволів вÑтановіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ 0."
@@ -19868,6 +20054,9 @@ 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 "Якщо жоден із варіантів не працює, Ñпробуйте зв’ÑзатиÑÑ Ð· адмініÑтратором 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 "Якщо кількіÑÑ‚ÑŒ активних кориÑтувачів перевищує ліміт кориÑтувачів, то за наÑтупної звірки ліцензії з Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ знÑто плату за кількіÑÑ‚ÑŒ %{users_over_license_link}."
@@ -20153,6 +20342,9 @@ msgstr[3] "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ %d репозиторіїв"
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 "За цією URL-адреÑою немає дійÑного репозиторію Git. Якщо ваш репозиторій HTTP не Ñ” загальнодоÑтупним, перевірте Ñвої облікові дані."
@@ -20198,9 +20390,6 @@ msgstr "%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, Сан-Ф
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -20258,9 +20447,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -20303,9 +20489,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr "Чи знаєте ви, що команди, Ñкі викориÑтовують GitLab, набагато ефективніші?"
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr "Створити проєкт і репо"
@@ -20315,18 +20498,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr "Легко"
-
msgid "InProductMarketing|Epics"
msgstr "Епіки"
@@ -20345,9 +20522,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20516,9 +20690,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr "Вам потрібна альтернатива імпорту?"
-msgid "InProductMarketing|Neutral"
-msgstr "Ðейтральний"
-
msgid "InProductMarketing|No credit card required."
msgstr "Кредитна картка непотрібна."
@@ -20591,9 +20762,6 @@ msgstr "Ðе дивуйтеÑÑ Ñ– викориÑтовуйте GitLab, щоб Ð
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 "Оптимізуйте переглÑд коду, дізнавайтеÑÑ Ð· першого поглÑду, хто недоÑтупний, ÑпілкуйтеÑÑ Ð² коментарÑÑ… або електронною поштою та інтегруйтеÑÑ Ð·Ñ– Slack, щоб уÑÑ– були на одній Ñторінці."
-msgid "InProductMarketing|Take this 1-question survey!"
-msgstr "Візьміть учаÑÑ‚ÑŒ у цьому опитуванні з 1 запитаннÑ!"
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr "Зробіть перші кроки з GitLab"
@@ -20666,12 +20834,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr "ВикориÑтовуєтьÑÑ Ð¿Ð¾Ð½Ð°Ð´ 100 000 організаціÑми з уÑього Ñвіту:"
-msgid "InProductMarketing|Very difficult"
-msgstr "Дуже Ñкладний"
-
-msgid "InProductMarketing|Very easy"
-msgstr "Дуже проÑтий"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20687,9 +20849,6 @@ 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 "Ми дещо знаємо про ефективніÑÑ‚ÑŒ Ñ– хочемо цим поділитиÑÑ. ПідпишітьÑÑ Ð½Ð° безкоштовну пробну верÑÑ–ÑŽ GitLab Ultimate, Ñ– ваші команди кориÑтуватимутьÑÑ Ð½ÐµÑŽ з першого днÑ."
-msgid "InProductMarketing|We want your GitLab experience to be great"
-msgstr "Ми хочемо, щоб ви отримали гарний доÑвід від роботи з GitLab"
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr "Як виглÑдає чаÑова шкала нашого потоку значень від розробки продукту до його Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° ÑтвореннÑ?"
@@ -21424,7 +21583,7 @@ msgid "Integrations|Resetting this integration will clear the settings and deact
msgstr ""
msgid "Integrations|Restrict to branch (optional)"
-msgstr ""
+msgstr "Обмежити гілку (необов'Ñзково)"
msgid "Integrations|Return to GitLab for Jira"
msgstr ""
@@ -21556,7 +21715,7 @@ msgid "Introducing Your DevOps Reports"
msgstr "ПредÑтавлÑємо ваші DevOps звіти"
msgid "Invalid"
-msgstr ""
+msgstr "ÐедійÑний"
msgid "Invalid Insights config file detected"
msgstr "Знайдено недійÑний файл конфігурації ÑтатиÑтики (Insights)"
@@ -21622,7 +21781,7 @@ msgid "Invalid repository path"
msgstr "Ðеправильний шлÑÑ… до репозиторію"
msgid "Invalid rule"
-msgstr ""
+msgstr "ÐедійÑне правило"
msgid "Invalid server response"
msgstr "Ðеправильна відповідь від Ñервера"
@@ -21714,7 +21873,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21793,7 +21952,7 @@ 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 "Ð”Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб призначити задачі новому учаÑнику команди, вам потрібен проєкт Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ñ‡. %{linkStart}Створити проєкт, щоб почати.%{linkEnd}"
-msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21808,9 +21967,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -22216,6 +22372,9 @@ msgstr "ТекÑÑ‚ курÑивом"
msgid "Iteration"
msgstr "ІтераціÑ"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "Ітерацію змінено на"
@@ -22231,12 +22390,36 @@ 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 ""
@@ -22258,6 +22441,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "Створити ітерації автоматично за регулÑрним розкладом."
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -22288,10 +22474,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -22300,6 +22486,9 @@ 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 "Ітерації починаютьÑÑ Ð·Ð° розкладом по %{weekday}"
+
msgid "Iterations|Learn more about automatic scheduling"
msgstr ""
@@ -22327,9 +22516,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22343,7 +22529,7 @@ msgid "Iterations|Roll over issues"
msgstr ""
msgid "Iterations|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "Iterations|Select duration"
msgstr ""
@@ -22357,15 +22543,15 @@ 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|The start date of the first iteration determines when your cadence begins."
-msgstr ""
-
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr ""
@@ -22823,32 +23009,35 @@ msgid "Job|Keep"
msgstr "Залишити"
msgid "Job|Manual"
-msgstr ""
+msgstr "Вручну"
msgid "Job|No search results found"
msgstr "Ðічого не знайдено"
msgid "Job|Passed"
-msgstr ""
+msgstr "Виконано"
msgid "Job|Pending"
msgstr "В очікуванні"
msgid "Job|Preparing"
-msgstr ""
+msgstr "Підготовка"
msgid "Job|Retry"
msgstr "Повторити"
msgid "Job|Running"
-msgstr ""
+msgstr "ВиконуєтьÑÑ"
msgid "Job|Scheduled"
-msgstr ""
+msgstr "Заплановано"
msgid "Job|Scroll to bottom"
msgstr "Прокрутити вниз"
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr "Прокрутити вгору"
@@ -22862,7 +23051,7 @@ msgid "Job|Show complete raw"
msgstr "Показати повний неформатований"
msgid "Job|Skipped"
-msgstr ""
+msgstr "Пропущені"
msgid "Job|Status"
msgstr "СтатуÑ"
@@ -22898,13 +23087,13 @@ msgid "Job|We could not find this element"
msgstr "Ми не змогли знайти цей елемент"
msgid "Job|allowed to fail"
-msgstr ""
+msgstr "невдача дозволена"
msgid "Job|delayed"
-msgstr ""
+msgstr "відкладено"
msgid "Job|manual"
-msgstr ""
+msgstr "вручну"
msgid "Job|triggered"
msgstr ""
@@ -22972,8 +23161,8 @@ msgstr "Ключ"
msgid "Key (PEM)"
msgstr "Ключ (PEM)"
-msgid "Key: %{key}"
-msgstr "Ключ: %{key}"
+msgid "Key:"
+msgstr "Ключ:"
msgid "Keyboard shortcuts"
msgstr "Комбінації клавіш"
@@ -23244,15 +23433,9 @@ msgstr "IP оÑтаннього входу:"
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ ÑƒÑпішна ÑинхронізаціÑ"
-
msgid "Last successful update"
msgstr "ОÑтаннє уÑпішне оновленнÑ"
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr "ОÑтанній раз перевірено"
@@ -23535,20 +23718,20 @@ msgstr ""
msgid "Less Details"
msgstr ""
+msgid "Less restrictive visibility"
+msgstr ""
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encrypt не приймає Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти з example.com"
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 "Let's Encrypt Ñ” безкоштовним, автоматизованим та відкритим центром Ñертифікації (CA), Ñкий видає цифрові Ñертифікати Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— HTTPS (SSL/TLS) на вебÑайтах. ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Let's Encrypt перейшовши до %{docs_link_start}документації по GitLab Pages%{docs_link_end}."
-msgid "Let's talk!"
-msgstr "Давайте поговоримо!"
-
msgid "License Compliance"
msgstr "ВідповідніÑÑ‚ÑŒ ліцензіÑм"
-msgid "License Compliance| Used by"
-msgstr ""
+msgid "License Compliance| Used by %{dependencies}"
+msgstr "ВикориÑтовуєтьÑÑ %{dependencies}"
msgid "License compliance"
msgstr ""
@@ -23668,7 +23851,7 @@ msgid "LicenseCompliance|This license already exists in this project."
msgstr "Така Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð²Ð¶Ðµ Ñ–Ñнує в цьому проєкті."
msgid "LicenseCompliance|Uncategorized"
-msgstr ""
+msgstr "Без категорії"
msgid "LicenseCompliance|Update approvals"
msgstr ""
@@ -23683,7 +23866,7 @@ msgid "LicenseManagement|Denied"
msgstr "Відхилено"
msgid "LicenseManagement|Uncategorized"
-msgstr ""
+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 ""
@@ -23820,8 +24003,11 @@ msgstr "Пов’Ñзані адреÑи електронної пошти (%{em
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
-msgstr "Пов'Ñзані задачі"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
+msgstr "Пов'Ñзані елементи"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -23832,6 +24018,48 @@ msgstr "LinkedIn:"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr "Ще %{counterLabel} наÑтупних конвеєрів"
+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 "Помилка при Ñтворенні поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° реÑÑƒÑ€Ñ Ð´Ð»Ñ Ñ–Ð½Ñ†Ð¸Ð´ÐµÐ½Ñ‚Ñƒ: %{error}"
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr "Помилка Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð²'Ñзаного реÑурÑу Ð´Ð»Ñ Ñ–Ð½Ñ†Ð¸Ð´ÐµÐ½Ñ‚Ñƒ: %{error}"
+
+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 "ПоÑиланнÑ"
@@ -23941,7 +24169,7 @@ msgid "Lock the discussion"
msgstr "Заблокувати обговореннÑ"
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "Заблокувати цей %{issuableDisplayName}? Лише %{strongStart}учаÑники проєкту%{strongEnd} матимуть змогу коментувати."
msgid "Lock to current projects"
msgstr "Закріпити за поточними проєктами"
@@ -24159,9 +24387,6 @@ msgstr ""
msgid "Manual"
msgstr "Вручну"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ порÑдок задач"
@@ -24229,7 +24454,7 @@ msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
msgstr "Додати закреÑлений текÑÑ‚ (%{modifier_key}⇧X)"
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
-msgstr ""
+msgstr "ПідтримуєтьÑÑ %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -24322,7 +24547,7 @@ msgid "Max Value"
msgstr "МакÑимальне значеннÑ"
msgid "Max authenticated Git LFS requests per period per user"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ Git LFS запитів на період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– на кориÑтувача з автентифікацією"
msgid "Max file size is 200 KB."
msgstr "МакÑимальний розмір файлу 200 KB."
@@ -24382,10 +24607,10 @@ msgid "Maximum attachment size (MB)"
msgstr "МакÑимальний розмір Ð²ÐºÐ»Ð°Ð´ÐµÐ½Ð½Ñ (МБ)"
msgid "Maximum authenticated API requests per rate limit period per user"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ автентифікованих запитів API за період дії тарифного Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð° одного кориÑтувача"
msgid "Maximum authenticated web requests per rate limit period per user"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ вебзапитів на період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– на кориÑтувача з автентифікацією"
msgid "Maximum bulk request size (MiB)"
msgstr "МакÑимальний розмір маÑового запиту (MiB)"
@@ -24423,7 +24648,7 @@ 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_whitelist}."
+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"
@@ -24484,10 +24709,10 @@ msgid "Maximum number of requests per minute"
msgstr ""
msgid "Maximum number of requests per minute for an authenticated user"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ запитів на хвилину Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ¾Ð²Ð°Ð½Ð¾Ð³Ð¾ кориÑтувача"
msgid "Maximum number of requests per minute for an unauthenticated IP address"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ запитів на хвилину Ð´Ð»Ñ Ð½ÐµÐ°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ¾Ð²Ð°Ð½Ð¾Ñ— IP-адреÑи"
msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
msgstr "МакÑимальна кількіÑÑ‚ÑŒ запитів на хвилину Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ неформатованого шлÑху (за замовчуваннÑм 300). Ð’Ñтановіть 0, щоб вимкнути регулюваннÑ."
@@ -24562,10 +24787,10 @@ msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for
msgstr "МакÑимальний Ñ‡Ð°Ñ Ñƒ Ñекундах Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ веб-терміналу. 0 - необмежений."
msgid "Maximum unauthenticated API requests per rate limit period per IP"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ API запитів на період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– на IP без автентифікації"
msgid "Maximum unauthenticated web requests per rate limit period per IP"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ вебзапитів на період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– на IP без автентифікації"
msgid "May"
msgstr "травень"
@@ -25523,10 +25748,10 @@ msgid "MilestoneSidebar|Start date"
msgstr "Дата початку"
msgid "MilestoneSidebar|Toggle sidebar"
-msgstr ""
+msgstr "Увімкнути бічну панель"
msgid "MilestoneSidebar|Until"
-msgstr ""
+msgstr "До"
msgid "MilestoneSidebar|complete"
msgstr ""
@@ -25700,7 +25925,7 @@ msgid "Monday"
msgstr "Понеділок"
msgid "Monitor"
-msgstr "Монітор"
+msgstr "Моніторинг"
msgid "Monitor Settings"
msgstr ""
@@ -25825,12 +26050,6 @@ msgstr "Зупинити Ñередовище"
msgid "MrList|Assigned to %{name}"
msgstr "Призначено %{name}"
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25855,8 +26074,8 @@ msgstr "Багатопроєкт"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
-msgstr ""
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "ПідтримуєтьÑÑ ÐºÑ–Ð»ÑŒÐºÐ° діапазонів IP-адреÑ. Ðе впливає на доÑтуп до налаштувань групи."
msgid "Multiple Prometheus integrations are not supported"
msgstr ""
@@ -26042,9 +26261,6 @@ msgstr "Вийти Ñ– зайти під іншим обліковим запиÑ
msgid "Need help?"
msgstr "Потрібна допомога?"
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr "Потреби"
@@ -26316,6 +26532,9 @@ msgstr "Ðемає даних CSV Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "No Epic"
msgstr "Ðемає епіка"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "Ðемає проєктів Google Cloud - вам потрібен принаймні один проєкт Google Cloud"
+
msgid "No Matching Results"
msgstr "Ðемає відповідних результатів"
@@ -26346,9 +26565,6 @@ msgstr ""
msgid "No assignee"
msgstr "Ðемає виконавцÑ"
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr "Методи автентифікації не налаштовано."
@@ -26365,7 +26581,7 @@ msgid "No changes"
msgstr "Ðемає змін"
msgid "No changes between %{source} and %{target}"
-msgstr ""
+msgstr "Ðемає змін між %{source} та %{target}"
msgid "No child epics match applied filters"
msgstr ""
@@ -26428,7 +26644,7 @@ msgid "No file chosen."
msgstr "Файл не вибрано."
msgid "No file hooks found."
-msgstr ""
+msgstr "Файлові хуки не знайдено."
msgid "No file selected"
msgstr "Файл не вибраний"
@@ -26650,9 +26866,6 @@ msgstr ""
msgid "Normal text"
msgstr "Звичайний текÑÑ‚"
-msgid "Not Implemented"
-msgstr "Ðе реалізовано"
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26726,7 +26939,7 @@ msgid "NoteForm|Note"
msgstr "Примітка"
msgid "NoteToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd}, type %{keyboardStart}/%{keyboardEnd}."
-msgstr ""
+msgstr "ПідтримуєтьÑÑ %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. Ð”Ð»Ñ %{quickActionsDocsLinkStart}швидких дій%{quickActionsDocsLinkEnd}, введіть %{keyboardStart}/%{keyboardEnd}."
msgid "Notes"
msgstr "Ðотатки"
@@ -26773,6 +26986,9 @@ 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 "Ви бачите лише %{boldStart}іншу активніÑÑ‚ÑŒ%{boldEnd} в каналі. Ð”Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ, виберіть одну з наÑтупних опцій."
+msgid "Note|The created date provided is too far in the past."
+msgstr ""
+
msgid "Nothing to preview."
msgstr "Дані Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду відÑутні."
@@ -26918,6 +27134,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{commit_link} в %{mr_link}"
+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|%{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|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -27083,6 +27308,13 @@ msgstr "OmniAuth"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "On track"
msgstr ""
@@ -27523,7 +27755,7 @@ 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 ""
+msgstr "Дозволити будь-кому реєÑтрувати облікові запиÑи на інÑтанÑах GitLab, Ñкі ви маєте намір кориÑтуватиÑÑ Ð½Ð¸Ð¼Ð¸. Дозвіл будь-кому зареєÑтруватиÑÑ Ñ€Ð¾Ð±Ð¸Ñ‚ÑŒ GitLab інÑтанÑи більш вразливими."
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
@@ -27558,9 +27790,6 @@ msgstr "Ðеобхідний лише Ñкщо не викориÑтовують
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27654,6 +27883,9 @@ 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 "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми міÑтить інформацію про Ñтан кожного з проєктів разом зі Ñтаном його конвеєрів та попереджень."
@@ -27733,7 +27965,7 @@ msgid "OutboundRequests|Local IP addresses and domain names that hooks and servi
msgstr ""
msgid "OutboundRequests|Outbound requests"
-msgstr ""
+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 ""
@@ -27811,10 +28043,10 @@ msgid "Package Registry"
msgstr "РеєÑÑ‚Ñ€ пакетів"
msgid "Package Registry: authenticated API requests"
-msgstr ""
+msgstr "РеєÑÑ‚Ñ€ пакетів: API запити з автентифікацією"
msgid "Package Registry: unauthenticated API requests"
-msgstr ""
+msgstr "РеєÑÑ‚Ñ€ пакетів: API запити без автентифікації"
msgid "Package already exists"
msgstr "Пакет вже Ñ–Ñнує"
@@ -27829,7 +28061,7 @@ msgid "Package recipe already exists"
msgstr ""
msgid "Package registry rate limits"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÐºÑ–Ð»ÑŒÐºÐ¾ÑÑ‚Ñ– реєÑтру пакетів"
msgid "Package type"
msgstr "Тип пакету"
@@ -27892,7 +28124,7 @@ msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{auth
msgstr ""
msgid "PackageRegistry|Composer"
-msgstr ""
+msgstr "Composer"
msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
msgstr ""
@@ -27975,6 +28207,13 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27984,6 +28223,9 @@ msgstr "Видалити верÑÑ–ÑŽ пакету"
msgid "PackageRegistry|Delete package"
msgstr "Видалити пакет"
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr "Видалити цей пакет"
@@ -27993,6 +28235,9 @@ 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 ""
@@ -28050,9 +28295,12 @@ msgstr "ДізнайтеÑÑ Ñк %{noPackagesLinkStart}публікувати Ñ
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
-msgid "PackageRegistry|Manually Published"
+msgid "PackageRegistry|Manage storage used by package assets"
msgstr ""
+msgid "PackageRegistry|Manually Published"
+msgstr "Опубліковано вручну"
+
msgid "PackageRegistry|Maven"
msgstr "Maven"
@@ -28068,11 +28316,17 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "Команда NNGet"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "КількіÑÑ‚ÑŒ дублікатів, Ñкі потрібно зберегти"
+
msgid "PackageRegistry|Package Registry"
+msgstr "РеєÑÑ‚Ñ€ пакетів"
+
+msgid "PackageRegistry|Package assets deleted successfully"
msgstr ""
msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
+msgstr "Пакет уÑпішно видалено"
msgid "PackageRegistry|Package file deleted successfully"
msgstr ""
@@ -28087,6 +28341,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Команда pip"
@@ -28144,6 +28401,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -28195,18 +28455,31 @@ 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}, this operation is irreversible, are you sure?"
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{name}, Ñ– Ñ†Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ñ” незворотною. Ви впевнені?"
+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[2] ""
+msgstr[3] ""
+
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ верÑÑ–ÑŽ %{version} з %{name}. Ви впевнені?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "Можливо, вам також потрібно буде налаштувати автентифікацію за допомогою токена автентифікації. %{linkStart}ПереглÑньте документацію%{linkEnd}, щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ."
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr "Вам буде потрібно %{linkStart}перÑональний токен доÑтупу%{linkEnd}."
+
msgid "PackageRegistry|npm"
msgstr "npm"
@@ -28454,7 +28727,7 @@ msgid "Percentage"
msgstr "ВідÑоток"
msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
-msgstr ""
+msgstr "Виконуйте такі розширені операції, Ñк зміна шлÑху, перенеÑеннÑ, екÑпорт чи Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸."
msgid "Perform code reviews and enhance collaboration with merge requests."
msgstr ""
@@ -28462,6 +28735,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr "Виконати звичайні операції на проєкті GitLab"
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ–"
@@ -28550,7 +28826,7 @@ msgid "Permissions Help"
msgstr "Довідка щодо дозволів"
msgid "Permissions and group features"
-msgstr ""
+msgstr "Дозволи та функції групи"
msgid "Personal Access Token"
msgstr "Токену перÑонального доÑтупу"
@@ -28567,6 +28843,18 @@ 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 "Ваш проєкт %{projectName} не входить до групи"
+
msgid "Phabricator Server Import"
msgstr "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ñ‚Ñ‚Ñ Ñ–Ð· Ñерверу Phabricator"
@@ -28723,6 +29011,9 @@ 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 ""
@@ -28741,6 +29032,15 @@ 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 ""
@@ -28762,6 +29062,12 @@ 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 ""
@@ -28783,6 +29089,9 @@ 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|Provide a short description for this pipeline"
msgstr "Задайте короткий Ð¾Ð¿Ð¸Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ конвеєру"
@@ -28795,6 +29104,9 @@ msgstr "Ціль"
msgid "PipelineSchedules|Variables"
msgstr "Змінні"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr "Стати влаÑником Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ"
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28865,7 +29177,7 @@ msgid "PipelineWizardListWidget|remove step"
msgstr ""
msgid "PipelineWizard|Commit"
-msgstr ""
+msgstr "Коміт"
msgid "PipelineWizard|Commit Message"
msgstr ""
@@ -28910,7 +29222,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 ""
+msgstr "GitLab Runner — це заÑтоÑунок, Ñкий працює з GitLab CI/CD Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½ÑŒ у конвеєрі. Ð’Ñтановіть GitLab Runner та зареєÑтруйте влаÑні runner'и Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку з CI/CD."
msgid "Pipelines|API"
msgstr "API"
@@ -29041,6 +29353,9 @@ msgstr "ВлаÑник"
msgid "Pipelines|Pipeline Editor"
msgstr "Редактор Конвеєрів"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "СинтакÑÐ¸Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° правильний."
+
msgid "Pipelines|Project cache successfully reset."
msgstr "Кеш проєкту уÑпішно очищено."
@@ -29090,7 +29405,7 @@ msgid "Pipelines|This GitLab CI configuration is invalid:"
msgstr "Ð¦Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ GitLab CI недійÑна:"
msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
-msgstr ""
+msgstr "Ð¦Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ GitLab CI недійÑна. %{reason}."
msgid "Pipelines|This GitLab CI configuration is valid."
msgstr ""
@@ -29209,9 +29524,18 @@ msgstr "Відділений конвеєр запиту на злиттÑ"
msgid "Pipeline|Failed"
msgstr "Ðевдало"
+msgid "Pipeline|Five slowest jobs"
+msgstr "П'ÑÑ‚ÑŒ найповільніших завдань"
+
msgid "Pipeline|In progress"
msgstr "ВиконуєтьÑÑ"
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr "Вручну"
@@ -29224,12 +29548,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr "Конвеєр результату злиттÑ"
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr "Виконано"
msgid "Pipeline|Pending"
msgstr "Очікує"
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr "Конвеєр"
@@ -29248,6 +29578,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr "ЗапуÑтити конвеєр запиту на злиттÑ"
+
msgid "Pipeline|Run pipeline"
msgstr "ЗапуÑтити Конвеєр"
@@ -29284,6 +29617,12 @@ msgstr "Ім'Ñ Ñ‚ÐµÐ³Ñƒ"
msgid "Pipeline|Test coverage"
msgstr "ТеÑтове покриттÑ"
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -29299,6 +29638,9 @@ 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 "Ð”Ð»Ñ Ð·Ð°Ð¿ÑƒÑку конвеєра запиту на злиттÑ, Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð² файлі конфігурації CI/CD %{linkStart}повинні бути налаштовані%{linkEnd} Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку в конвеєрах запиту на злиттÑ."
+
msgid "Pipeline|Trigger author"
msgstr "Ðвтор тригера"
@@ -29311,6 +29653,9 @@ msgstr "Змінні"
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "ПереглÑнути конвеєр"
@@ -29351,7 +29696,7 @@ msgid "Plain diff"
msgstr "ПроÑте порівнÑннÑ"
msgid "Plain-text response to send to clients that hit a rate limit"
-msgstr ""
+msgstr "ПроÑта відповідь Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÐºÐ»Ñ–Ñ”Ð½Ñ‚Ñ–Ð², Ñкі доÑÑгли Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ–"
msgid "Plan"
msgstr "План"
@@ -29410,6 +29755,9 @@ 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 "Будь лаÑка, перевірте Ñвою поштову Ñкриньку (%{email}) Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð¾Ð³Ð¾, що ви нею володієте, щоб розкрити потенціал CI/CD. Ðе отримали? %{resend_link}. Ðеправильна адреÑа? %{update_link}."
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr "Будь лаÑка, доповніть Ñвій профіль адреÑою електронної пошти"
@@ -29512,6 +29860,9 @@ 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 "Будь лаÑка, переглÑньте правила %{linkStart}внеÑку%{linkEnd} Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту."
+
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 ""
@@ -29681,7 +30032,7 @@ msgid "Preferences|Enable integrated code intelligence on code views"
msgstr ""
msgid "Preferences|Failed to save preferences."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ налаштуваннÑ."
msgid "Preferences|For example: 30 minutes ago."
msgstr "Ðаприклад: 30 хвилин тому."
@@ -29693,7 +30044,7 @@ msgid "Preferences|Homepage content"
msgstr "ВміÑÑ‚ домашньої Ñторінки"
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
-msgstr ""
+msgstr "ЗаміÑÑ‚ÑŒ уÑÑ–Ñ… змінених файлів показувати лише по одному файлу за раз. Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð¼Ñ–Ð¶ файлами викориÑтовуйте файловий браузер."
msgid "Preferences|Integrations"
msgstr "Інтеграції"
@@ -29723,7 +30074,7 @@ msgid "Preferences|Sourcegraph"
msgstr "Sourcegraph"
msgid "Preferences|Surround text selection when typing quotes or brackets"
-msgstr ""
+msgstr "Охоплює виділений текÑÑ‚ під Ñ‡Ð°Ñ Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð»Ð°Ð¿Ð¾Ðº або дужок"
msgid "Preferences|Syntax highlighting theme"
msgstr "Тема Ð´Ð»Ñ Ð¿Ñ–Ð´Ñвітки ÑинтакÑиÑу"
@@ -29747,7 +30098,7 @@ 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}."
-msgstr ""
+msgstr "Коли ви вводите Ð¾Ð¿Ð¸Ñ Ð°Ð±Ð¾ поле коментарÑ, виділений текÑÑ‚ оточуєтьÑÑ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¸Ð¼ Ñимволом піÑÐ»Ñ Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ з таких Ñимволів: %{supported_characters}."
msgid "Preparing the report for the scan."
msgstr ""
@@ -29758,8 +30109,8 @@ msgstr "Ðазад"
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr "Заборонити редагувати правила ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ñƒ проєктах та запитах на злиттÑ"
msgid "Prevent environment from auto-stopping"
msgstr ""
@@ -30472,6 +30823,9 @@ 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 "Рівень видимоÑÑ‚Ñ– проєкту буде змінено відповідно до правил проÑтору імен під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð´Ð¾ групи."
@@ -30481,6 +30835,12 @@ msgstr ""
msgid "Project: %{name}"
msgstr "Проєкт %{name}"
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr "Проєкт: Гілки: %{source_project_path}:%{source_branch} - %{target_project_path}:%{target_branch}"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr "Проєкт: Гілки: %{source_project_path}:%{source_branch} - %{target_project_path}:%{target_branch}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПідпиÑатиÑÑ"
@@ -30559,6 +30919,9 @@ 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 ""
@@ -30571,6 +30934,9 @@ 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 "ПереглÑнути повний звіт"
@@ -30598,6 +30964,9 @@ 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 "або групу"
@@ -31786,18 +32155,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} буде доÑупне Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Ви впевнені?"
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 "ЗахиÑтити"
@@ -31907,7 +32294,7 @@ msgid "Publish to status page"
msgstr ""
msgid "Published"
-msgstr ""
+msgstr "Опубліковано"
msgid "Published on status page"
msgstr ""
@@ -31924,6 +32311,12 @@ 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 "Придбати більше хвилин"
@@ -32093,10 +32486,10 @@ msgid "Quickly and easily edit multiple files in your project."
msgstr "Швидко і легко редагувати декілька файлів у вашому проєкті."
msgid "Quota of CI/CD minutes"
-msgstr ""
+msgstr "Квота хвилин CI/CD"
msgid "Quota of CI/CD minutes:"
-msgstr ""
+msgstr "Квота хвилин CI/CD:"
msgid "README"
msgstr "ІнÑÑ‚Ñ€ÑƒÐºÑ†Ñ–Ñ (README)"
@@ -32194,12 +32587,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -32233,6 +32620,9 @@ msgstr ""
msgid "Reconfigure"
msgstr "Переналаштувати"
+msgid "Recover password"
+msgstr "Відновити пароль"
+
msgid "Recovery Codes"
msgstr "Коди відновленнÑ"
@@ -32405,9 +32795,6 @@ msgstr "ВідноÑитьÑÑ Ð´Ð¾ %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr "Пов'Ñзані інциденти або задачі"
-
msgid "Related issues"
msgstr "ПовʼÑзані задачі"
@@ -32424,6 +32811,9 @@ msgstr[1] "Релізи"
msgstr[2] "Релізів"
msgstr[3] "Релізів"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr "РеÑурÑи релізу"
@@ -32496,6 +32886,9 @@ 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 ""
@@ -32559,12 +32952,6 @@ msgstr "Видалити поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° реÑурÑ"
msgid "Remove assignee"
msgstr "Видалити виконавцÑ"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr "Видалити аватар"
@@ -32665,7 +33052,7 @@ msgid "Remove topic avatar"
msgstr ""
msgid "Remove user"
-msgstr ""
+msgstr "Видалити кориÑтувача"
msgid "Remove user & report"
msgstr ""
@@ -32706,12 +33093,6 @@ msgstr "Видалено вÑÑ– мітки."
msgid "Removed an issue from an epic."
msgstr "Видалено задачу із епіка."
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr "Видалену групу неможливо відновити!"
@@ -32760,9 +33141,6 @@ msgstr "ВидалÑÑ” вÑÑ– мітки."
msgid "Removes an issue from an epic."
msgstr "ВидалÑÑ” задачу із епіка."
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr "ВидалÑÑ” батьківÑький епік %{epic_ref}."
@@ -32871,6 +33249,9 @@ msgstr "ВідповіÑти на це електронне повідомлен
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr "Повідомити про порушеннÑ"
@@ -32883,6 +33264,9 @@ 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 ""
@@ -33050,6 +33434,9 @@ msgstr "ВразливіÑÑ‚ÑŒ"
msgid "Reports|Vulnerability Name"
msgstr "Ім'Ñ Ð²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¾ÑÑ‚Ñ–"
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr "результати теÑтів не змінилиÑÑ"
@@ -33247,15 +33634,6 @@ msgstr "Запит доÑтупу"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -33280,24 +33658,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Відправлено запит %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -33378,6 +33744,9 @@ msgstr ""
msgid "Resend Request"
msgstr "Повторно надіÑлати запит"
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr "Повторно відіÑлати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті"
@@ -33409,7 +33778,7 @@ msgid "Reset password"
msgstr ""
msgid "Reset registration token"
-msgstr ""
+msgstr "Скинути реєÑтраційний токен"
msgid "Reset template"
msgstr "Скинути шаблон"
@@ -33522,10 +33891,10 @@ msgstr ""
msgid "Retry"
msgstr "Спробувати знову"
-msgid "Retry downstream pipeline"
-msgstr ""
+msgid "Retry all failed or cancelled jobs"
+msgstr "Повторити вÑÑ– невдалі або ÑкаÑовані завданнÑ"
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33575,7 +33944,7 @@ msgid "Review requests for you"
msgstr "ПереглÑньте запити Ð´Ð»Ñ Ð²Ð°Ñ"
msgid "Review the changes locally."
-msgstr ""
+msgstr "ПереглÑньте зміни локально."
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr "ПереглÑте Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð²Ð°Ð¹Ð´ÐµÑ€Ñ–Ð² поÑлуг у вашому провайдері ідентифікації — в такому разі GitLab Ñ” \"провайдером поÑлуг\" або \"довірÑючою Ñтороною\"."
@@ -33632,12 +34001,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr "додаваннÑ"
-
-msgid "RightSidebar|deleting the"
-msgstr "видаленнÑ"
-
msgid "Roadmap"
msgstr "План-графік"
@@ -33713,6 +34076,13 @@ msgstr ""
msgid "Runners page."
msgstr "Сторінка Runner'ів."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33764,7 +34134,7 @@ msgid "Runners|Architecture"
msgstr "Ðрхітектура"
msgid "Runners|Assigned Group"
-msgstr ""
+msgstr "Призначена група"
msgid "Runners|Assigned Projects (%{projectCount})"
msgstr ""
@@ -33772,6 +34142,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr "ДоÑтупні"
+
msgid "Runners|Available to all projects"
msgstr "ДоÑтупно Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів"
@@ -33785,44 +34158,44 @@ msgid "Runners|Capacity of 1 enables warm HA through Auto Scaling group re-spawn
msgstr ""
msgid "Runners|Checkbox"
-msgstr ""
+msgstr "Прапорець"
msgid "Runners|Choose your preferred GitLab Runner"
msgstr ""
msgid "Runners|Clear selection"
-msgstr ""
+msgstr "ОчиÑтити вибір"
msgid "Runners|Command to register runner"
-msgstr ""
+msgstr "Команда Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації runner"
msgid "Runners|Configuration"
msgstr "КонфігураціÑ"
msgid "Runners|Copy instructions"
-msgstr ""
+msgstr "Скопіювати інÑтрукції"
msgid "Runners|Copy registration token"
msgstr "Скопіювати токен Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "Runners|Delete %d runner"
msgid_plural "Runners|Delete %d runners"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Видалити %d runner"
+msgstr[1] "Видалити %d runner`а"
+msgstr[2] "Видалити %d runner`ів"
+msgstr[3] "Видалити %d runner`ів"
msgid "Runners|Delete runner"
-msgstr ""
+msgstr "Видалити runner"
msgid "Runners|Delete runner %{name}?"
-msgstr ""
+msgstr "Видалити runner %{name}?"
msgid "Runners|Delete selected"
-msgstr ""
+msgstr "Видалити вибрані"
msgid "Runners|Deploy GitLab Runner in AWS"
-msgstr ""
+msgstr "Розгортати Runner GitLab в AWS"
msgid "Runners|Description"
msgstr "ОпиÑ"
@@ -33837,13 +34210,13 @@ msgid "Runners|Download and install binary"
msgstr "Завантажити та вÑтановити бінарний файл"
msgid "Runners|Download latest binary"
-msgstr ""
+msgstr "Завантажити оÑтанній бінарний файл"
msgid "Runners|Edit your search and try again"
msgstr "Відредагуйте ваш пошук Ñ– Ñпробуйте знову"
msgid "Runners|Enable stale runner cleanup"
-msgstr ""
+msgstr "Увімкнути Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ñтарілого runner"
msgid "Runners|Enable stale runner cleanup?"
msgstr ""
@@ -33879,7 +34252,7 @@ msgid "Runners|Last contact"
msgstr "ОÑтанній контакт"
msgid "Runners|Locked to this project"
-msgstr ""
+msgstr "Закріплено за цим проєктом"
msgid "Runners|Maintenance note"
msgstr ""
@@ -33906,7 +34279,7 @@ msgid "Runners|New group runners view"
msgstr ""
msgid "Runners|New registration token generated!"
-msgstr ""
+msgstr "Ðовий реєÑтраційний токен, Ñтворений!"
msgid "Runners|No results found"
msgstr "Ðе знайдено результатів"
@@ -33921,10 +34294,10 @@ msgid "Runners|Not accepting jobs"
msgstr ""
msgid "Runners|Offline"
-msgstr ""
+msgstr "Офлайн"
msgid "Runners|Offline runners"
-msgstr ""
+msgstr "Офлайн runner'и"
msgid "Runners|Offline:"
msgstr "Офлайн:"
@@ -33933,11 +34306,14 @@ msgid "Runners|Online"
msgstr "Онлайн"
msgid "Runners|Online runners"
-msgstr ""
+msgstr "Онлайн runner'и"
msgid "Runners|Online:"
msgstr "Онлайн:"
+msgid "Runners|Outdated"
+msgstr "ЗаÑтарілі"
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33963,8 +34339,11 @@ msgstr ""
msgid "Runners|Protected"
msgstr "Захищені"
+msgid "Runners|Recommended"
+msgstr "Рекомендовано"
+
msgid "Runners|Register a group runner"
-msgstr ""
+msgstr "ЗареєÑтрувати груповий runner"
msgid "Runners|Register a project runner"
msgstr ""
@@ -33973,16 +34352,16 @@ msgid "Runners|Register a runner"
msgstr ""
msgid "Runners|Register an instance runner"
-msgstr ""
+msgstr "ЗареєÑтрувати runner інÑтанÑа"
msgid "Runners|Registration token"
-msgstr ""
+msgstr "Токен Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "Runners|Registration token copied!"
-msgstr ""
+msgstr "РеєÑтраційний токен Ñкопійовано!"
msgid "Runners|Reset token"
-msgstr ""
+msgstr "Скинути токен"
msgid "Runners|Resume accepting jobs"
msgstr ""
@@ -33991,16 +34370,16 @@ msgid "Runners|Revision"
msgstr "ВерÑÑ–Ñ"
msgid "Runners|Runner"
-msgstr ""
+msgstr "Runner"
msgid "Runners|Runner #%{runner_id}"
-msgstr ""
+msgstr "Runner #%{runner_id}"
msgid "Runners|Runner %{name} was deleted"
-msgstr ""
+msgstr "Runner %{name} було видалено"
msgid "Runners|Runner assigned to project."
-msgstr ""
+msgstr "Runner призначено Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
msgid "Runners|Runner cannot be deleted, please contact your administrator"
msgstr ""
@@ -34045,7 +34424,7 @@ msgid "Runners|Runner registration"
msgstr ""
msgid "Runners|Runner statuses"
-msgstr ""
+msgstr "СтатуÑи Runner"
msgid "Runners|Runner unassigned from project."
msgstr ""
@@ -34071,6 +34450,9 @@ 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 ""
@@ -34078,13 +34460,13 @@ msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
msgid "Runners|Stale"
-msgstr ""
+msgstr "ЗаÑтарілі"
msgid "Runners|Stale runners"
-msgstr ""
+msgstr "ЗаÑтарілі runner'и"
msgid "Runners|Stale:"
-msgstr ""
+msgstr "ЗаÑтарілі:"
msgid "Runners|Status"
msgstr "СтатуÑ"
@@ -34132,9 +34514,18 @@ 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|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 ""
@@ -34180,6 +34571,9 @@ msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} Ñ
msgid "Runners|active"
msgstr "активні"
+msgid "Runners|available"
+msgstr "ДоÑтупні"
+
msgid "Runners|group"
msgstr "Група"
@@ -34193,16 +34587,19 @@ msgid "Runners|online"
msgstr "онлайн"
msgid "Runners|paused"
-msgstr ""
+msgstr "пауза"
+
+msgid "Runners|recommended"
+msgstr "рекомендовано"
msgid "Runners|shared"
-msgstr ""
+msgstr "Ñпільний"
msgid "Runners|specific"
msgstr ""
msgid "Runners|stale"
-msgstr ""
+msgstr "заÑтарілі"
msgid "Runners|upgrade available"
msgstr "доÑтупне оновленнÑ"
@@ -34210,6 +34607,9 @@ msgstr "доÑтупне оновленнÑ"
msgid "Runners|upgrade recommended"
msgstr "РекомендуєтьÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸"
+msgid "Runner|Owner"
+msgstr "ВлаÑник"
+
msgid "Running"
msgstr "ВиконуєтьÑÑ"
@@ -34252,6 +34652,9 @@ msgstr ""
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr "SSH ключ"
@@ -34261,6 +34664,9 @@ msgstr "Ключі SSH"
msgid "SSH Keys Help"
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 ""
+
msgid "SSH host key fingerprints"
msgstr "Відбитки SSH-ключа хоÑта"
@@ -34292,7 +34698,7 @@ msgid "SSL Verification:"
msgstr "Перевірка SSL:"
msgid "SSL verification"
-msgstr ""
+msgstr "Перевірка SSL"
msgid "Satisfied"
msgstr ""
@@ -34339,6 +34745,21 @@ msgstr "ЗбереженнÑ"
msgid "Saving project."
msgstr "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ."
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr "Конвеєр запущений"
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr "Виберіть гілки"
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34680,6 +35101,12 @@ msgstr[1] "результати у вікі"
msgstr[2] "результатів у вікі"
msgstr[3] "результатів у вікі"
+msgid "SearchToken|Assignee"
+msgstr "Виконавець"
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34740,6 +35167,9 @@ msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð‘ÐµÐ·Ð¿ÐµÐºÐ¸"
msgid "Security Dashboard"
msgstr "Панель безпеки"
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr "Панель безпеки"
@@ -35013,6 +35443,12 @@ 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 ""
@@ -35098,7 +35534,7 @@ msgid "SecurityOrchestration|Runs a %{action} scan"
msgstr ""
msgid "SecurityOrchestration|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "SecurityOrchestration|Scan Execution"
msgstr ""
@@ -35178,6 +35614,9 @@ 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 group"
msgstr ""
@@ -35196,9 +35635,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -35326,7 +35762,7 @@ msgid "SecurityReports|Download %{artifactName}"
msgstr ""
msgid "SecurityReports|Download results"
-msgstr ""
+msgstr "Завантажити результати"
msgid "SecurityReports|Download scanned URLs"
msgstr ""
@@ -35355,6 +35791,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr "Сховати відхилені"
+msgid "SecurityReports|Image"
+msgstr "Образ"
+
msgid "SecurityReports|Issue Created"
msgstr "Задача Ñтворена"
@@ -35409,6 +35848,15 @@ 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 "Проєкт"
@@ -35763,9 +36211,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "Вибрані рівні не можуть викориÑтовуватиÑÑ Ð½ÐµÐ°Ð´Ð¼Ñ–Ð½Ñ–Ñтраторами Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿, проєктів або Ñніпетів. Якщо публічний рівень обмежений, профілі кориÑтувачів відображаютьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð·Ð°Ñ€ÐµÑ”Ñтрованих кориÑтувачів."
-msgid "Selected projects"
-msgstr "Вибрані проєкти"
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35949,9 +36394,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr "СервіÑи"
-
msgid "Session ID"
msgstr ""
@@ -35967,9 +36409,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Ð’Ñтановіть пароль Ð´Ð»Ñ Ñвого облікового запиÑу, щоб мати можливіÑÑ‚ÑŒ відправлÑти та отримувати через %{protocol}."
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35989,7 +36428,7 @@ msgid "Set limit to 0 to allow any file size."
msgstr ""
msgid "Set limits for web and API requests."
-msgstr ""
+msgstr "Ð’Ñтановити Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²ÐµÐ± та API запитів."
msgid "Set milestone"
msgstr "Ð’Ñтановити етап"
@@ -36458,14 +36897,14 @@ msgstr "Показано оÑтанню верÑÑ–ÑŽ"
msgid "Showing version #%{versionNumber}"
msgstr "Показана верÑÑ–Ñ #%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+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 ""
+msgstr "%{name}: %{value}"
msgid "Sidebar|Assign health status"
msgstr ""
@@ -36545,6 +36984,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36554,6 +36996,9 @@ msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ"
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36788,9 +37233,6 @@ msgstr ""
msgid "Solution"
msgstr "РішеннÑ"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37272,10 +37714,10 @@ msgid "SourcegraphPreferences|This feature is experimental."
msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ” екÑпериментальною."
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "ВикориÑтовує %{linkStart}Sourcegraph.com%{linkEnd}."
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
-msgstr ""
+msgstr "ВикориÑтовує влаÑний %{linkStart}Ñервер Sourcegraph%{linkEnd}."
msgid "Spam Check"
msgstr "Перевірка Ñпаму"
@@ -37907,9 +38349,6 @@ msgstr "ВидалÑÑ”"
msgid "Succeeded"
msgstr "УÑпіх"
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr "УÑпішно активовано"
@@ -38256,9 +38695,6 @@ msgstr "Підтримку кориÑтувацьких Ñертифікатів
msgid "Support page URL"
msgstr "URL-адреÑа Ñторінки підтримки"
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -38361,6 +38797,9 @@ msgstr "СиÑтемні метрики (Kubernetes)"
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr "СиÑтема запущена"
+
msgid "Table of Contents"
msgstr "ЗміÑÑ‚"
@@ -38433,6 +38872,9 @@ msgstr "СкаÑувати"
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr "Створити тег"
@@ -38451,8 +38893,8 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
-msgstr "Редагувати Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ"
+msgid "TagsPage|Edit release"
+msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "Ім'Ñ Ñ–Ñнуючої гілки, тега або SHA коміта"
@@ -38527,7 +38969,7 @@ msgid "Target Branch"
msgstr "Цільова гілка"
msgid "Target Path"
-msgstr ""
+msgstr "Цільовий шлÑÑ…"
msgid "Target branch"
msgstr "Цільова гілка"
@@ -38550,9 +38992,6 @@ msgstr "Ідентифікатор завданнÑ: %{elastic_task}"
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38973,9 +39412,6 @@ msgstr "Стиль текÑту"
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "ДÑкуємо за ваш звіт. ÐдмініÑтратор GitLab розглÑне це Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°Ð¹Ð±Ð»Ð¸Ð¶Ñ‡Ð¸Ð¼ чаÑом."
@@ -39270,9 +39706,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -39319,7 +39752,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 ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ CI/CD хвилин Ð´Ð»Ñ Ñпільних runner'ів, Ñкі можна викориÑтовувати щоміÑÑцÑ. 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 ""
@@ -39432,6 +39865,9 @@ 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 ""
@@ -39508,7 +39944,7 @@ msgid "The vulnerability is no longer detected. Verify the vulnerability has bee
msgstr "ВразливіÑÑ‚ÑŒ більше не виÑвлÑєтьÑÑ. Перевірте, що цю вразливіÑÑ‚ÑŒ виправлено перед тим, Ñк змінювати ÑтатуÑ."
msgid "Theme"
-msgstr ""
+msgstr "Тема"
msgid "There are currently no events."
msgstr ""
@@ -39546,6 +39982,9 @@ msgstr "Ðемає жодних архівних вимог"
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr "Змінених міток немає"
+
msgid "There are no changes"
msgstr "Зміни відÑутні"
@@ -39601,7 +40040,7 @@ msgid "There are no secure files yet."
msgstr "Ðемає захищених файлів."
msgid "There are no topics to show."
-msgstr ""
+msgstr "Ðемає тем Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ."
msgid "There are no variables yet."
msgstr ""
@@ -39618,6 +40057,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑку вже Ñ–Ñнує репозиторій за таким ім’Ñм"
@@ -39720,9 +40162,6 @@ msgstr "Помилка при відÑиланні Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr "Помилка при додаванні нагадуваннÑ."
@@ -39801,9 +40240,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr "Помилка при видаленні адреÑи електронної пошти."
-msgid "There was an error resetting group pipeline minutes."
-msgstr "Помилка при Ñкиданні групових хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²."
-
msgid "There was an error resetting user pipeline minutes."
msgstr "Помилка при Ñкиданні хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² кориÑтувача."
@@ -39855,9 +40291,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° з reCAPTCHA. Будь лаÑка, пройдіть reCAPTCHA знову."
@@ -40038,6 +40471,9 @@ 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 ""
@@ -40395,11 +40831,17 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
+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 "Ðаразі цей репозиторій Ñ” порожнім. Ðовий конвеєр Auto DevOps буде Ñтворено піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк новий файл буде відправлено в ÑкуÑÑŒ гілку."
@@ -40498,7 +40940,7 @@ msgid "Time"
msgstr "ЧаÑ"
msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
-msgstr ""
+msgstr "Ð§Ð°Ñ (в годинах), впродовж Ñкого кориÑтувачам дозволено пропуÑкати примуÑове Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації."
msgid "Time based: Yes"
msgstr "Ðа оÑнові чаÑу: Так"
@@ -40707,6 +41149,9 @@ 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 "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ"
@@ -40793,9 +41238,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "Щоб додати Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ, надайте наÑтупні відомоÑÑ‚Ñ– заÑтоÑунку у вашому телефоні."
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40871,7 +41313,7 @@ msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·Ð²Ð¸Ñ‚ÐºÑƒ цього проєкту Ñтворіть ноÐ
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -41105,6 +41547,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -41361,7 +41806,7 @@ msgid "Trigger removed."
msgstr "Тригер видалено."
msgid "Trigger repository check"
-msgstr ""
+msgstr "ЗапуÑтити перевірку репозиторію"
msgid "Trigger this manual action"
msgstr "ЗапуÑтити цю ручну дію"
@@ -41388,7 +41833,7 @@ msgid "Trigger|invalid"
msgstr ""
msgid "Trusted"
-msgstr ""
+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 ""
@@ -41411,6 +41856,9 @@ 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 ""
@@ -41495,6 +41943,9 @@ msgstr ""
msgid "Type"
msgstr "Тип"
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr "U2F приÑтрої (%{length})"
@@ -41615,6 +42066,9 @@ msgstr "Ðеможливо завантажити порівнÑÐ½Ð½Ñ (diff). %
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 ""
@@ -41670,13 +42124,16 @@ msgid "Unassigned"
msgstr "Ðепризначено"
msgid "Unauthenticated API rate limit period in seconds"
-msgstr ""
+msgstr "Період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти API за Ñекунди без автентифікації"
msgid "Unauthenticated requests"
-msgstr ""
+msgstr "Запити без автентифікації"
msgid "Unauthenticated web rate limit period in seconds"
-msgstr ""
+msgstr "Період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти веб в Ñекундах без автентифікації"
+
+msgid "Unban"
+msgstr "Розблокувати"
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr ""
@@ -41723,9 +42180,6 @@ msgstr "Ðевідомий формат"
msgid "Unknown response text"
msgstr "Ðевідомий текÑÑ‚ відповіді"
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41918,9 +42372,6 @@ msgstr "Дата оновленнÑ"
msgid "Updating"
msgstr "ОновленнÑ"
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr "ОновленнÑ…"
@@ -41948,6 +42399,9 @@ msgstr "Завантажити Ñертифікат Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ доме
msgid "Upload a private key for your certificate"
msgstr "Завантажити приватний ключ Ð´Ð»Ñ Ñертифіката"
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "ÐадіÑлати файл"
@@ -41972,9 +42426,6 @@ msgstr ""
msgid "Upstream"
msgstr "Попередній"
-msgid "Uptime"
-msgstr "Ð§Ð°Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸"
-
msgid "Upvotes"
msgstr "Лайки"
@@ -42035,10 +42486,10 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð° поточний період"
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -42057,7 +42508,7 @@ msgid "UsageQuota|Increase storage temporarily"
msgstr ""
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "Сховище LFS"
msgid "UsageQuota|Learn more about excess storage usage"
msgstr ""
@@ -42110,6 +42561,9 @@ 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 ""
@@ -42132,11 +42586,23 @@ msgid "UsageQuota|Storage"
msgstr "Сховище"
msgid "UsageQuota|Storage type"
-msgstr ""
+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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -42171,7 +42637,7 @@ msgid "UsageQuota|Unlimited"
msgstr "Без обмежень"
msgid "UsageQuota|Uploads"
-msgstr ""
+msgstr "ЗавантаженнÑ"
msgid "UsageQuota|Usage"
msgstr "ВикориÑтаннÑ"
@@ -42407,6 +42873,13 @@ msgstr "ВикориÑтовуйте Ñмарт-карту Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "ВикориÑтовуєтьÑÑ %d пакетом"
+msgstr[1] "ВикориÑтовуєтьÑÑ %d пакетами"
+msgstr[2] "ВикориÑтовуєтьÑÑ %d пакетами"
+msgstr[3] "ВикориÑтовуєтьÑÑ %d пакетами"
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ВикориÑтовуєтьÑÑ ÑƒÑ‡Ð°Ñниками Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ у вашу групу в GitLab"
@@ -42500,6 +42973,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr "КориÑтувача уÑпішно видалено із проєкту."
+msgid "User was successfully unbanned."
+msgstr "КориÑтувач був уÑпішно розблокований."
+
msgid "User was successfully updated."
msgstr "КориÑтувача було уÑпішно оновлено."
@@ -42608,6 +43084,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "ВнеÑки в проєкти"
+msgid "UserProfile|Copy user ID"
+msgstr "Копіювати ID кориÑтувача"
+
msgid "UserProfile|Edit profile"
msgstr "Редагувати профіль"
@@ -42689,6 +43168,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr "ID кориÑтувача: %{id}"
+
msgid "UserProfile|View all"
msgstr "ПереглÑнути вÑе"
@@ -42854,13 +43336,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42915,10 +43390,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -43008,6 +43489,12 @@ 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 "ВерÑÑ–Ñ %{versionNumber}"
@@ -43015,7 +43502,7 @@ msgid "Version %{versionNumber} (latest)"
msgstr "ВерÑÑ–Ñ %{versionNumber} (оÑтаннÑ)"
msgid "VersionCheck|Up to date"
-msgstr ""
+msgstr "Ðайновіша верÑÑ–Ñ"
msgid "VersionCheck|Update ASAP"
msgstr "Оновити Ñкомога швидше"
@@ -43623,6 +44110,9 @@ 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 ""
@@ -43668,9 +44158,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43680,6 +44167,9 @@ 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 "Ми надіÑлали вам Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті з інÑтрукціÑми по відновленню паролю"
@@ -43888,7 +44378,7 @@ msgid "Webhooks|Releases events"
msgstr ""
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "Перевірка SSL"
msgid "Webhooks|Secret token"
msgstr ""
@@ -43980,6 +44470,12 @@ 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 "Що робить Ñ†Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°?"
@@ -44041,6 +44537,13 @@ 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] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "When:"
msgstr "Коли:"
@@ -44077,6 +44580,12 @@ msgstr ""
msgid "Wiki"
msgstr "Вікі"
+msgid "Wiki Page|Rich text"
+msgstr "Розширений текÑÑ‚"
+
+msgid "Wiki Page|Source"
+msgstr "Джерело"
+
msgid "Wiki page"
msgstr ""
@@ -44203,12 +44712,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr "Створити Ñторінку"
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr "Редагувати джерело"
-
msgid "WikiPage|Format"
msgstr "Формат"
@@ -44222,7 +44725,7 @@ msgid "WikiPage|Retry"
msgstr ""
msgid "WikiPage|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -44308,22 +44811,28 @@ msgstr "ВиконуєтьÑÑ Ñ€Ð¾Ð±Ð¾Ñ‚Ð° (відкрита та не приз
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
msgstr ""
+msgid "WorkItem|Add a title"
+msgstr "Додати заголовок"
+
msgid "WorkItem|Add assignee"
msgstr "Додати виконавцÑ"
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -44339,6 +44848,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr "Дочірній елемент видалено"
+
msgid "WorkItem|Closed"
msgstr ""
@@ -44351,24 +44863,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr "Видалити"
+
msgid "WorkItem|Select type"
msgstr "Вибрати тип"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -44378,18 +44905,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr "СкаÑувати"
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44673,8 +45221,12 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "Ви можете запроÑити нового учаÑника до %{project_name} або запроÑити іншу групу."
@@ -44682,9 +45234,6 @@ msgstr "Ви можете запроÑити нового учаÑника до
msgid "You can invite a new member to %{project_name}."
msgstr "Ви можете запроÑити нового учаÑника до %{project_name}."
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "Ви можете запроÑити нового учаÑника до %{strong_start}%{group_name}%{strong_end}."
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44739,7 +45288,7 @@ msgstr "Ви можете перевірити Ñвій .gitlab-ci.yml у %{link
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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44751,15 +45300,9 @@ msgstr "Ви не можете отримати доÑтуп до неформа
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr "Ви не можете імітувати заблокованого кориÑтувача"
@@ -44790,11 +45333,12 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "Ви не змогли Ñтворити новий тригер."
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "You do not have any subscriptions yet"
msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
@@ -45130,6 +45674,9 @@ 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 "Ви уже увімкнули двофакторну автентифікацію за допомогою автентифікаторів одноразових паролів. Ð”Ð»Ñ Ñ€ÐµÑ”Ñтрації іншого приÑтрою ви повинні Ñпочатку вимкнути двофакторну автентифікацію."
@@ -45142,9 +45689,6 @@ msgstr ""
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -45157,8 +45701,8 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
-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 "Ваша підпиÑка на %{strong}%{plan_name}%{strong_close} закінчуєтьÑÑ %{strong}%{expires_on}%{strong_close}. Якщо ви не поновите підпиÑку, ви втратите доÑтуп до платних функцій %{strong}%{downgrades_on}%{strong_close}. ПіÑÐ»Ñ Ñ†Ñ–Ñ”Ñ— дати ви не зможете Ñтворювати проблеми, об’єднувати запити чи викориÑтовувати багато інших функцій."
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr ""
@@ -45331,6 +45875,20 @@ msgstr ""
msgid "Your first project"
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] ""
+msgstr[2] ""
+msgstr[3] ""
+
+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[2] ""
+msgstr[3] ""
+
msgid "Your groups"
msgstr "Ваші групи"
@@ -45427,9 +45985,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -45455,12 +46010,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "Термін дії вашої підпиÑки закінчитьÑÑ %{expires_on}"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
msgstr ""
@@ -45617,6 +46168,9 @@ msgstr ""
msgid "assign yourself"
msgstr "призначити Ñамому Ñобі"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45699,6 +46253,9 @@ 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 ""
@@ -45802,9 +46359,15 @@ msgstr "%{reportType}: Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð·Ð²ÐµÐ»Ð¾ до помил
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45820,6 +46383,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr "УÑÑ– образи"
+
msgid "ciReport|All projects"
msgstr "Ð’ÑÑ– проєкти"
@@ -45993,7 +46559,7 @@ msgid "ciReport|Loading %{reportName} report"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð²Ñ–Ñ‚Ñƒ %{reportName}"
msgid "ciReport|Loading Code Quality report"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð²Ñ–Ñ‚Ñƒ про ÑкіÑÑ‚ÑŒ коду"
msgid "ciReport|Manage Licenses"
msgstr ""
@@ -46098,6 +46664,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr "ci_database"
+
msgid "closed"
msgstr "закрито"
@@ -46125,6 +46694,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -46164,9 +46736,6 @@ msgstr ""
msgid "data"
msgstr "дані"
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr "дата не повинна бути пізніше 9999-12-31"
@@ -46227,7 +46796,7 @@ msgid "element is not a hierarchy"
msgstr "елемент відÑутній в ієрархії"
msgid "eligible users"
-msgstr ""
+msgstr "відповідних кориÑтувачів"
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -46265,6 +46834,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr "перевищує макÑимальну довжину (100 кориÑтувачів)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -46351,9 +46923,6 @@ msgstr ""
msgid "group members"
msgstr "учаÑники групи"
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr "групи"
@@ -46406,6 +46975,9 @@ msgstr "https://your-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr "%{language} (%{percent_translated}%% перекладено)"
+msgid "if"
+msgstr "Ñкщо"
+
msgid "image diff"
msgstr "Ñ€Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
@@ -46584,6 +47156,9 @@ msgstr "завантаженнÑ"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
+msgid "main_database"
+msgstr "main_database"
+
msgid "manual"
msgstr "вручну"
@@ -46623,25 +47198,19 @@ msgid "most recent deployment"
msgstr "оÑтаннє розгортаннÑ"
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
-msgstr ""
+msgstr "%{commitCount} і %{mergeCommitCount} буде додано до %{targetBranch}%{squashedCommits}."
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr ""
+msgstr "%{commitCount} буде додано в %{targetBranch}."
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коміт-злиттÑ"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
-msgstr ""
+msgstr "Зміни злиті в %{targetBranch} з %{mergeCommitSha}%{squashedCommits}."
msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
-msgstr ""
+msgstr "Зміни не були злиті в %{targetBranch}."
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½Ðµ міÑтить змін."
@@ -46728,7 +47297,7 @@ msgid "mrWidget|Cancel auto-merge"
msgstr "СкаÑувати автоматичне злиттÑ"
msgid "mrWidget|Checking if merge request can be merged…"
-msgstr ""
+msgstr "Перевірка можливоÑÑ‚Ñ– Ð¾Ð±â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ…"
msgid "mrWidget|Cherry-pick"
msgstr "вибір (коміта)"
@@ -46755,9 +47324,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Видалити гілку-джерело"
-msgid "mrWidget|Deletes the source branch"
-msgstr "ВидалÑÑ” гілку джерела"
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "СтатиÑтика Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– недоÑтупна"
@@ -46767,9 +47333,6 @@ msgstr "Ðе закрив"
msgid "mrWidget|Dismiss"
msgstr "Відхилити"
-msgid "mrWidget|Does not delete the source branch"
-msgstr "Ðе можливо видалити гілку-джерело"
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑтатиÑтику розгортаннÑ"
@@ -46807,9 +47370,6 @@ msgstr[1] "Задачі зі згадками"
msgstr[2] "Задач зі згадками"
msgstr[3] "Задач зі згадками"
-msgid "mrWidget|Merge"
-msgstr "Об'єднати"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46843,9 +47403,6 @@ msgstr "ÐедоÑтупне: запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾Ñтупні л
msgid "mrWidget|Merged by"
msgstr "Злито"
-msgid "mrWidget|Merges changes into"
-msgstr "Об'єднує зміни в"
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "ЗлиттÑ! Зміни відправлÑÑŽÑ‚ÑŒÑÑ…"
@@ -46901,7 +47458,7 @@ msgid "mrWidget|Resolve conflicts"
msgstr "Вирішити конфлікти"
msgid "mrWidget|Resolve locally"
-msgstr ""
+msgstr "Вирішити локально"
msgid "mrWidget|Revert"
msgstr "Ðнулювати"
@@ -46930,20 +47487,8 @@ msgstr "Показати %{widget} подробиці"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr "Зміни були злиті в"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "Зміни не були злиті в"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "Гілку-джерело видалено"
-
msgid "mrWidget|The source branch is %{link} the target branch"
-msgstr ""
-
-msgid "mrWidget|The source branch is being deleted"
-msgstr "Гілка-джерело в процеÑÑ– видаленнÑ"
+msgstr "Гілка джерела %{link} цільової гілки"
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при автоматичному злитті цього запиту"
@@ -47271,6 +47816,9 @@ msgstr "репозиторії"
msgid "repository:"
msgstr "репозиторій:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr "задоволено"
@@ -47283,6 +47831,9 @@ msgstr ""
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 ""
@@ -47299,13 +47850,13 @@ msgid "severity|Low"
msgstr "Ðизький"
msgid "severity|Major"
-msgstr ""
+msgstr "ОÑновний"
msgid "severity|Medium"
msgstr "Середній"
msgid "severity|Minor"
-msgstr ""
+msgstr "Ðезначний"
msgid "severity|None"
msgstr "ВідÑутній"
@@ -47394,13 +47945,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
-msgstr ""
+msgid "the following epics"
+msgstr "наÑтупні епіки"
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -47421,6 +47972,9 @@ msgstr ""
msgid "toggle collapse"
msgstr "згорнути/розгорнути"
+msgid "total must be less than or equal to %{size}"
+msgstr "загальна Ñума повинна бути меншою або рівною %{size}"
+
msgid "triggered"
msgstr "запущено"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index e8244389c83..4af40d1d57c 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 029eb67552e..e829736ebd2 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-07-14 17:13\n"
+"PO-Revision-Date: 2022-08-12 18:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -460,6 +460,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -508,8 +511,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgstr[1] ""
@@ -691,6 +694,9 @@ 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 ""
@@ -742,6 +748,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -754,13 +763,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -876,6 +885,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -954,6 +975,16 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
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 ""
@@ -992,9 +1023,6 @@ msgstr[1] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1499,15 +1527,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1535,9 +1557,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -2114,6 +2133,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2153,9 +2175,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2183,9 +2202,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2231,6 +2247,9 @@ 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 ""
@@ -3755,6 +3774,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -4046,9 +4068,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -4094,6 +4113,9 @@ 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 ""
@@ -4181,9 +4203,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4586,13 +4605,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4619,6 +4650,18 @@ 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 ""
@@ -4764,28 +4807,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4803,6 +4849,9 @@ 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 ""
@@ -4830,9 +4879,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5174,9 +5220,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5218,7 +5261,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5232,12 +5275,6 @@ msgstr[1] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5298,6 +5335,12 @@ 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 ""
@@ -5316,6 +5359,9 @@ 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 ""
@@ -5331,18 +5377,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5355,6 +5416,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5571,7 +5635,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5760,6 +5824,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -6111,6 +6178,9 @@ 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 ""
@@ -6204,17 +6274,16 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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 ""
@@ -6231,6 +6300,9 @@ 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 ""
@@ -6246,13 +6318,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6585,9 +6654,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7196,9 +7307,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7887,9 +7995,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8312,6 +8417,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8330,6 +8438,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8387,12 +8501,18 @@ 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 ""
@@ -10215,9 +10335,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10656,9 +10773,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -11109,6 +11223,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11495,6 +11612,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11513,6 +11633,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11528,6 +11651,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11573,6 +11699,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11609,9 +11738,21 @@ 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 ""
@@ -12307,6 +12448,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12331,6 +12475,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12388,6 +12538,15 @@ 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 ""
@@ -12412,9 +12571,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12622,6 +12778,9 @@ msgid_plural "Deploys"
msgstr[0] ""
msgstr[1] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12877,7 +13036,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13678,9 +13837,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -14089,9 +14245,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14413,9 +14566,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14914,6 +15064,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15889,22 +16042,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15922,6 +16072,9 @@ 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 ""
@@ -15967,9 +16120,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16212,6 +16362,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16629,6 +16782,11 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16653,11 +16811,15 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
+msgstr[1] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
+msgstr[1] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16716,6 +16878,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16765,6 +16930,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16939,9 +17107,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16999,9 +17164,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17257,9 +17419,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17443,6 +17602,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17467,9 +17629,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17563,6 +17722,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17614,6 +17776,9 @@ 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 ""
@@ -17626,6 +17791,9 @@ 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 ""
@@ -17638,6 +17806,9 @@ 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 ""
@@ -17956,16 +18127,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
-msgstr ""
-
-msgid "Google Cloud authorizations required"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18187,9 +18355,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18343,7 +18508,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18508,7 +18673,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18556,6 +18721,9 @@ 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 ""
@@ -18568,15 +18736,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18595,9 +18757,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18622,15 +18781,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18748,6 +18901,9 @@ 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 ""
@@ -18766,6 +18922,9 @@ 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 ""
@@ -18811,6 +18970,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18889,6 +19051,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18907,7 +19078,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -19019,12 +19190,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19245,6 +19410,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19314,6 +19482,9 @@ 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 ""
@@ -19497,6 +19668,9 @@ 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 ""
@@ -19524,6 +19698,9 @@ 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 ""
@@ -19803,6 +19980,9 @@ 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 ""
@@ -19848,9 +20028,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19908,9 +20085,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19953,9 +20127,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19965,18 +20136,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19995,9 +20160,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -20166,9 +20328,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20241,9 +20400,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20316,12 +20472,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20337,9 +20487,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21362,7 +21509,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21439,7 +21586,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21454,9 +21601,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21862,6 +22006,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21877,12 +22024,36 @@ 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 ""
@@ -21904,6 +22075,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21934,10 +22108,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21946,6 +22120,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21973,9 +22150,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -22003,13 +22177,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22495,6 +22669,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22618,7 +22795,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22886,15 +23063,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -23177,19 +23348,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23450,7 +23621,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23462,6 +23636,48 @@ 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 ""
@@ -23789,9 +24005,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -24053,7 +24266,7 @@ 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_whitelist}."
+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"
@@ -25447,12 +25660,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25477,7 +25684,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25662,9 +25869,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25934,6 +26138,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25964,9 +26171,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26266,9 +26470,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26389,6 +26590,9 @@ 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 ""
@@ -26526,6 +26730,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26691,6 +26904,11 @@ 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 track"
msgstr ""
@@ -27164,9 +27382,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27260,6 +27475,9 @@ 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 ""
@@ -27581,6 +27799,11 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27590,6 +27813,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27599,6 +27825,9 @@ 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 ""
@@ -27656,6 +27885,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27674,9 +27906,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27691,6 +27929,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27748,6 +27989,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27799,18 +28043,29 @@ 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}, this operation is irreversible, 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 ""
@@ -28066,6 +28321,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -28171,6 +28429,18 @@ 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 ""
@@ -28327,6 +28597,9 @@ 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 ""
@@ -28345,6 +28618,15 @@ 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 ""
@@ -28366,6 +28648,12 @@ 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 ""
@@ -28387,6 +28675,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28399,6 +28690,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28645,6 +28939,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28813,9 +29110,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28828,12 +29134,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28852,6 +29164,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28888,6 +29203,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28903,6 +29224,9 @@ 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 ""
@@ -28915,6 +29239,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -29014,6 +29341,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -29116,6 +29446,9 @@ 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 ""
@@ -29362,7 +29695,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -30076,6 +30409,9 @@ 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 ""
@@ -30085,6 +30421,12 @@ 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 ""
@@ -30163,6 +30505,9 @@ 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 ""
@@ -30175,6 +30520,9 @@ 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 ""
@@ -30202,6 +30550,9 @@ 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 ""
@@ -31390,18 +31741,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31528,6 +31897,12 @@ 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 ""
@@ -31798,12 +32173,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31837,6 +32206,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -32007,9 +32379,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -32024,6 +32393,9 @@ msgid_plural "Releases"
msgstr[0] ""
msgstr[1] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -32096,6 +32468,9 @@ 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 ""
@@ -32159,12 +32534,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32306,12 +32675,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32360,9 +32723,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32471,6 +32831,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32483,6 +32846,9 @@ 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 ""
@@ -32640,6 +33006,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32833,15 +33202,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32866,24 +33226,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32960,6 +33308,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -33104,10 +33455,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -33210,12 +33561,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33291,6 +33636,11 @@ 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 ""
@@ -33346,6 +33696,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33510,6 +33863,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33533,6 +33889,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33641,6 +34000,9 @@ 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 ""
@@ -33700,9 +34062,18 @@ 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|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 ""
@@ -33748,6 +34119,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33763,6 +34137,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33778,6 +34155,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33820,6 +34200,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33829,6 +34212,9 @@ 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 ""
@@ -33907,6 +34293,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -34226,6 +34627,12 @@ 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 ""
@@ -34286,6 +34693,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34559,6 +34969,12 @@ 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 ""
@@ -34724,6 +35140,9 @@ 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 group"
msgstr ""
@@ -34742,9 +35161,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34901,6 +35317,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34955,6 +35374,15 @@ 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 ""
@@ -35309,9 +35737,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35495,9 +35920,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35513,9 +35935,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -36000,7 +36419,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -36087,6 +36506,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -36096,6 +36518,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36330,9 +36755,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37449,9 +37871,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37796,9 +38215,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37901,6 +38317,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37973,6 +38392,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37991,7 +38413,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -38090,9 +38512,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38501,9 +38920,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38792,9 +39208,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38954,6 +39367,9 @@ 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 ""
@@ -39068,6 +39484,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -39140,6 +39559,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39242,9 +39664,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39323,9 +39742,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39377,9 +39793,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39560,6 +39973,9 @@ 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 ""
@@ -39917,6 +40333,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -40229,6 +40651,9 @@ 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 ""
@@ -40311,9 +40736,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40389,7 +40811,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40623,6 +41045,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40929,6 +41354,9 @@ 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 ""
@@ -41013,6 +41441,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -41133,6 +41564,9 @@ 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 ""
@@ -41196,6 +41630,9 @@ 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 ""
@@ -41241,9 +41678,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41436,9 +41870,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41466,6 +41897,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41490,9 +41924,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41553,10 +41984,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41628,6 +42059,9 @@ 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 ""
@@ -41655,6 +42089,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41925,6 +42371,11 @@ 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 ""
@@ -42018,6 +42469,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -42126,6 +42580,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -42207,6 +42664,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42372,11 +42832,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42431,10 +42886,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42524,6 +42985,12 @@ 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 ""
@@ -43133,6 +43600,9 @@ 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 ""
@@ -43178,9 +43648,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -43190,6 +43657,9 @@ 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 ""
@@ -43490,6 +43960,12 @@ 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 ""
@@ -43549,6 +44025,11 @@ 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 ""
@@ -43585,6 +44066,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43711,12 +44198,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43816,10 +44297,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43828,10 +44312,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43845,6 +44332,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43857,24 +44347,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43884,18 +44389,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -44177,8 +44703,10 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
+msgstr[1] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -44186,9 +44714,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -44243,7 +44768,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44255,15 +44780,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44294,11 +44813,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
+msgstr[1] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44632,6 +45150,9 @@ 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 ""
@@ -44644,9 +45165,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44659,7 +45177,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44833,6 +45351,16 @@ msgstr ""
msgid "Your first project"
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 ""
@@ -44929,9 +45457,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44955,10 +45480,8 @@ msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_
msgstr[0] ""
msgstr[1] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-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 ""
@@ -45111,6 +45634,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -45191,6 +45717,9 @@ 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 ""
@@ -45292,9 +45821,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45310,6 +45845,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45578,6 +46116,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45605,6 +46146,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45644,9 +46188,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45741,6 +46282,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45823,9 +46367,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45876,6 +46417,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -46052,6 +46596,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -46095,12 +46642,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -46217,9 +46758,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -46229,9 +46767,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -46267,9 +46802,6 @@ msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
msgstr[1] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46303,9 +46835,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46390,21 +46919,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46721,6 +47238,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46733,6 +47253,9 @@ msgstr ""
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 ""
@@ -46844,13 +47367,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46871,6 +47394,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index c5806d85bc7..008d0e5b4af 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-07-14 17:05\n"
+"PO-Revision-Date: 2022-08-12 18:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ 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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr ""
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr ""
-
msgid "3 hours"
msgstr ""
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr ""
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr ""
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr ""
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr ""
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr ""
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
-
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr ""
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr ""
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr ""
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] ""
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr ""
msgid "February"
msgstr ""
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr ""
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr ""
@@ -28201,6 +28483,9 @@ msgstr ""
msgid "PipelineSchedules|Variables"
msgstr ""
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 ""
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr ""
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr ""
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr ""
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index d63df751052..f26612efe9b 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 18:02\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -385,6 +385,9 @@ msgstr "%{actionText} & é‡æ–°æ‰“å¼€ %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address}为无效的IP地å€èŒƒå›´"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} 必须介于 %{min} 和 %{max} 之间"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link}将%{original_issue}克隆到%{new_issue}。"
@@ -398,7 +401,7 @@ msgid "%{authorsName}'s thread"
msgstr "%{authorsName}的主题"
msgid "%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}"
-msgstr "已请求%{author}å°†%{source_branch}%{copy_button}åˆå¹¶åˆ°%{target_branch}%{created_at}"
+msgstr "%{author}请求将%{source_branch}%{copy_button}åˆå¹¶åˆ°%{target_branch} %{created_at}"
msgid "%{board_target} not found"
msgstr "找ä¸åˆ°%{board_target}"
@@ -430,9 +433,9 @@ msgstr "%{commit_author_link} 创作于 %{commit_authored_timeago} ,%{commit_c
msgid "%{completedCount} completed weight"
msgstr "%{completedCount}已完æˆæƒé‡"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount}/%{count} 任务已完æˆ"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] "%{completedCount}/%{count} 检查清å•é¡¹å·²å®Œæˆ"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "总æƒé‡%{totalWeight}中的%{completedWeight}已完æˆ"
@@ -607,6 +610,9 @@ msgstr "%{integrations_link_start}集æˆ%{link_end}使得将第三方应用程åº
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} 将被删除ï¼æ‚¨ç¡®å®šå—?"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} ä¸å­˜åœ¨æˆ–您无æƒå‘其添加时间日志。"
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable} 已分é…"
@@ -658,6 +664,9 @@ msgstr "%{labelStart}方法: %{labelEnd}%{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}命å空间: %{labelEnd}%{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}项目:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}扫æ工具:%{labelEnd} %{scanner}"
@@ -670,15 +679,15 @@ msgstr "%{labelStart}严é‡ç¨‹åº¦ :%{labelEnd}%{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}工具:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}未修改的å“应:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message}ä¸å¯ç”¨"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}。"
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1å°æ—¶"
@@ -791,6 +800,18 @@ msgstr "%{openedEpics}个开å¯ä¸­ï¼Œ %{closedEpics}个已关闭"
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 "%{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}。"
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} è¦æŸ¥çœ‹å’Œç®¡ç†æˆå‘˜ï¼Œè¯·æŸ¥çœ‹æ¯ä¸ªä¸ªäººé¡¹ç›®çš„æˆå‘˜é¡µé¢ã€‚我们建议您%{link_start}将项目移动到群组%{link_end},以便您å¯ä»¥è½»æ¾ç®¡ç†ç”¨æˆ·å’Œç›¸å…³åŠŸèƒ½ã€‚"
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} è¦æŸ¥çœ‹å’Œç®¡ç†æˆå‘˜ï¼Œè¯·æ£€æŸ¥å‘½å空间中æ¯ä¸ªé¡¹ç›®çš„æˆå‘˜é¡µé¢ã€‚我们建议您%{link_start}将项目移动到群组%{link_end},以便您å¯ä»¥è½»æ¾ç®¡ç†ç”¨æˆ·å’Œç›¸å…³åŠŸèƒ½ã€‚"
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed}%% 已被使用"
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] "%{securityScanner}无结果,因为自å¯ç”¨ä»¥æ¥å°šæœªè¿è¡Œæµæ°´çº¿ã€‚%{linkStart}è¿è¡Œæµæ°´çº¿%{linkEnd}"
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} 个标记"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} 个项目"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -903,9 +932,6 @@ 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 自动从群组中移除æˆå‘˜ã€‚"
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr "%{strongStart}需è¦æ‚¨çš„注æ„%{strongEnd} 指的是需è¦æ‚¨ä½œä¸ºæŒ‡æ´¾äººæˆ–审核者帮助处ç†çš„åˆå¹¶è¯·æ±‚。"
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr "%{strongStart}æ示:%{strongEnd} 您也å¯ä»¥åœ¨æœ¬åœ°æ£€å‡ºåˆå¹¶è¯·æ±‚。%{linkStart}了解更多。%{linkEnd}"
@@ -1374,15 +1400,9 @@ msgstr "åŒé‡è®¤è¯"
msgid "2FADevice|Registered On"
msgstr "注册于"
-msgid "3 days"
-msgstr "3天"
-
msgid "3 hours"
msgstr "3å°æ—¶"
-msgid "30 days"
-msgstr "30天"
-
msgid "30 minutes"
msgstr "30分钟"
@@ -1410,9 +1430,6 @@ msgstr "如果您认为这是信æ¯é”™è¯¯ï¼Œè¯·è”系您的管ç†å‘˜ã€‚"
msgid "409|There was a conflict with your request."
msgstr "您的请求中有冲çª"
-msgid "7 days"
-msgstr "7天"
-
msgid "8 hours"
msgstr "8å°æ—¶"
@@ -1738,7 +1755,7 @@ msgid "Access Git repositories or the API."
msgstr "访问 Git 仓库或 API。"
msgid "Access Token"
-msgstr ""
+msgstr "访问令牌"
msgid "Access Tokens"
msgstr "访问令牌"
@@ -1989,6 +2006,9 @@ msgstr "为此 GitLab 实例的用户添加æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–。"
msgid "Add a bullet list"
msgstr "添加一个符å·åˆ—表"
+msgid "Add a checklist"
+msgstr "添加检查清å•"
+
msgid "Add a collapsible section"
msgstr "添加å¯æŠ˜å éƒ¨åˆ†"
@@ -2028,9 +2048,6 @@ msgstr "为æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€æ·»åŠ åŽç¼€ã€‚ %{linkStart}了解更多ã€
msgid "Add a table"
msgstr "添加表格"
-msgid "Add a task list"
-msgstr "添加任务列表"
-
msgid "Add a title..."
msgstr "添加标题..."
@@ -2058,9 +2075,6 @@ msgstr "添加批准规则"
msgid "Add approvers"
msgstr "添加核准人"
-msgid "Add attention request"
-msgstr "添加关注请求"
-
msgid "Add broadcast message"
msgstr "添加广播消æ¯"
@@ -2106,6 +2120,9 @@ msgstr "添加环境"
msgid "Add existing confidential %{issuableType}"
msgstr "添加现有的ç§å¯†%{issuableType}"
+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 "添加页眉和页脚到电å­é‚®ä»¶ã€‚请注æ„,颜色设置仅适用于应用程åºç•Œé¢"
@@ -3630,6 +3647,9 @@ msgstr "所有分支"
msgid "All changes are committed"
msgstr "所有更改å‡å·²æ交"
+msgid "All eligible users"
+msgstr "所有符åˆæ¡ä»¶çš„用户"
+
msgid "All email addresses will be used to identify your commits."
msgstr "所有电å­é‚®ä»¶åœ°å€éƒ½å¯ç”¨äºŽæ ‡è¯†æ‚¨çš„æ交。"
@@ -3921,9 +3941,6 @@ msgstr "èŽ·å– Markdown 预览时出错"
msgid "An error occurred while fetching ancestors"
msgstr "获å–上级时å‘生错误"
-msgid "An error occurred while fetching branches."
-msgstr "获å–分支时å‘生错误。"
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr "获å–分支时å‘生错误,请é‡è¯•æœç´¢ã€‚"
@@ -3969,6 +3986,9 @@ 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 "获å–标签时å‘生错误,请é‡è¯•æœç´¢ã€‚"
@@ -4056,9 +4076,6 @@ msgstr "加载Needs选项å¡æ—¶å‡ºé”™ã€‚"
msgid "An error occurred while loading the Test Reports tab."
msgstr "加载测试报告选项å¡æ—¶å‘生错误。"
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr "加载访问令牌表å•æ—¶å‘生错误,请é‡è¯•ã€‚"
-
msgid "An error occurred while loading the blob controls."
msgstr "加载 blob 控件时出错。"
@@ -4458,14 +4475,26 @@ 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 "é™åˆ¶æ³¨å†Œä¸Žç»™å®šæ­£åˆ™è¡¨è¾¾å¼åŒ¹é…的电å­é‚®ä»¶åœ°å€ã€‚%{linkStart}支æŒçš„语法是什么?%{linkEnd}"
msgid "ApplicationSettings|Save changes"
msgstr "ä¿å­˜æ›´æ”¹"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr "请å‚阅GitLabçš„%{linkStart}密ç ç­–略指å—%{linkEnd}。"
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr "请å‚阅%{linkStart}密ç ç­–略指å—%{linkEnd}。"
msgid "ApplicationSettings|Send confirmation email on sign-up"
msgstr "注册时å‘é€ç¡®è®¤é‚®ä»¶"
@@ -4491,6 +4520,18 @@ 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 "当å¯ç”¨è¯¥è®¾ç½®åŽï¼Œè®¾ç½®æ–°çš„密ç æ—¶å¿…须包å«è‡³å°‘一个å°å†™å­—æ¯ï¼ˆa-z)。"
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
+msgstr "当å¯ç”¨è¯¥è®¾ç½®åŽï¼Œè®¾ç½®æ–°çš„密ç æ—¶å¿…须包å«è‡³å°‘一个数字(0-9)。"
+
+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 "当å¯ç”¨è¯¥è®¾ç½®åŽï¼Œè®¾ç½®æ–°çš„密ç æ—¶å¿…须包å«è‡³å°‘一个大写字æ¯ï¼ˆA-Z)。"
+
msgid "ApplicationSettings|domain.com"
msgstr "domain.com"
@@ -4631,29 +4672,32 @@ 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 approval by author."
-msgstr "ç¦æ­¢ä½œè€…审批。"
-
msgid "ApprovalSettings|Prevent approvals by users who add commits"
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 when commits are added to the source branch"
-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 "需è¦ç”¨æˆ·å¯†ç æ‰èƒ½æ‰¹å‡†"
@@ -4670,6 +4714,9 @@ 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 "此设置在 %{groupName} 中é…置,åªèƒ½ç”±ç®¡ç†å‘˜æˆ–群组所有者更改。"
+msgid "ApprovalSettings|When a commit is added:"
+msgstr "添加æ交时:"
+
msgid "Approvals are optional."
msgstr "核准为å¯é€‰ã€‚"
@@ -4697,9 +4744,6 @@ msgstr "批准了当å‰çš„åˆå¹¶è¯·æ±‚。"
msgid "Approved-By"
msgstr "已核准"
-msgid "Approved. Your attention request was removed."
-msgstr "已核准。您的关注请求已被删除。"
-
msgid "Approver"
msgstr "核准人"
@@ -4870,7 +4914,7 @@ 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 "您确定è¦é‡ç½®é”™è¯¯è·Ÿè¸ªè®¿é—®ä»¤ç‰Œå—?"
msgid "Are you sure you want to reset the health check token?"
msgstr "确定è¦é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥ä»¤ç‰Œå—?"
@@ -5040,9 +5084,6 @@ msgstr "已分派给我"
msgid "Assigned to you"
msgstr "分é…给您的"
-msgid "Assigned user(s). Your attention request was removed."
-msgstr "已指派用户。您的关注请求已被删除。"
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] "%dä½æŒ‡æ´¾äºº"
@@ -5083,8 +5124,8 @@ msgstr "您的个人访问令牌中至少有一个å³å°†è¿‡æœŸã€‚%{generate_new}
msgid "At risk"
msgstr "存在风险"
-msgid "Attach a file"
-msgstr "添加附件"
+msgid "Attach a file or image"
+msgstr "附加文件或图片"
msgid "Attaching File - %{progress}"
msgstr "附加文件中 - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] "添加%d个附件"
msgid "Attaching the file failed."
msgstr "添加附件失败。"
-msgid "Attention"
-msgstr "注æ„"
-
-msgid "Attention requested"
-msgstr "已请求关注"
-
msgid "Audit Events"
msgstr "审计事件"
@@ -5162,6 +5197,12 @@ msgstr "æ­¤å称的 header 已存在。"
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 "添加一个 HTTP 端点æ¥ç®¡ç†ç¬¬ä¸‰æ–¹ç³»ç»Ÿä¸­çš„审计日志。"
@@ -5180,6 +5221,9 @@ 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 "å–消编辑"
@@ -5195,18 +5239,33 @@ msgstr "目的地 URL"
msgid "AuditStreams|Destinations receive all audit event data"
msgstr "目的地接收所有审计事件数æ®"
+msgid "AuditStreams|Edit %{link}"
+msgstr "编辑 %{link}"
+
msgid "AuditStreams|Header"
msgstr "Header"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
msgstr "已达到最多 %{number} 个 HTTP headers。"
+msgid "AuditStreams|Save external stream destination"
+msgstr "添加外部事件æµç›®çš„地"
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr "为审计事件设置事件æµ"
+msgid "AuditStreams|Stream added successfully"
+msgstr "添加事件æµæˆåŠŸ"
+
msgid "AuditStreams|Stream count icon"
msgstr "事件æµè®¡æ•°"
+msgid "AuditStreams|Stream deleted successfully"
+msgstr "å·²æˆåŠŸåˆ é™¤äº‹ä»¶æµ"
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr "事件æµæ›´æ–°æˆåŠŸ"
+
msgid "AuditStreams|Streams"
msgstr "事件æµ"
@@ -5219,6 +5278,9 @@ msgstr "éžå¸¸é€‚åˆå°†æ‰€æœ‰æ•°æ®ä¿å­˜åœ¨ä¸€ä¸ªåœ°æ–¹ã€‚"
msgid "AuditStreams|Value"
msgstr "值"
+msgid "AuditStreams|Verification token"
+msgstr "验è¯ä»¤ç‰Œ"
+
msgid "Aug"
msgstr "8月"
@@ -5435,8 +5497,8 @@ msgstr "当æ¢å¤è­¦æŠ¥é€šçŸ¥è§£å†³è­¦æŠ¥æ—¶è‡ªåŠ¨å…³é—­ç›¸å…³äº‹ä»¶"
msgid "Automatically resolved"
msgstr "自动解决"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr "æ¯å°æ—¶è‡ªåŠ¨ä»Žä¸Šæ¸¸ä»“库更新此项目的分支和标记。"
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr "自动从上游仓库更新此项目的分支和标记。"
msgid "Autosave|Note"
msgstr "注æ„"
@@ -5624,6 +5686,9 @@ msgstr "使用Atlassian Bambooè¿è¡ŒCI/CDæµæ°´çº¿ã€‚您必须在Bamboo中设置
msgid "BambooService|The user with API access to the Bamboo server."
msgstr "对 Bamboo æœåŠ¡å™¨å…·æœ‰ API 访问æƒé™çš„用户。"
+msgid "Banned"
+msgstr "å·²å°ç¦"
+
msgid "Banner message"
msgstr "横幅消æ¯"
@@ -5975,6 +6040,9 @@ msgstr "延长试用期"
msgid "Billings|Free groups are limited to %{number} seats."
msgstr "å…费群组仅é™äºŽ %{number} 个席ä½ã€‚"
+msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
+msgstr "å…费版和试用群组æ¯å¤©æœ€å¤šå¯ä»¥é‚€è¯· 20 åæˆå‘˜ã€‚"
+
msgid "Billings|In a seat"
msgstr "å ç”¨å¸­ä½"
@@ -6068,17 +6136,15 @@ msgstr "æµè§ˆæ‰€æœ‰æ–¹æ¡ˆ"
msgid "Billing|Export list"
msgstr "导出列表"
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr "GitLab 上的å…费群组é™åˆ¶ %{maxNamespaceSeats} 个席ä½"
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr "从 2022 å¹´ 6 月 22 日(15.1)开始,å…费群组将é™åˆ¶ä¸º 5 åæˆå‘˜"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "从 2022 å¹´ 10 月 19 日起,å…费群组将é™åˆ¶æœ€å¤š5åæˆå‘˜åŠ å…¥"
msgid "Billing|Group invite"
msgstr "群组邀请"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-msgstr "如果群组æˆå‘˜è¶…过 %{maxNamespaceSeats} 人,åªæœ‰å æ®å¸­ä½çš„人å¯ä»¥è®¿é—®å‘½å空间。 为了确ä¿æ‰€æœ‰æˆå‘˜ (激活的æˆå‘˜å’Œ %{linkStart}超过é™åˆ¶%{linkEnd} çš„æˆå‘˜) 能够访问命å空间, 您å¯ä»¥å¼€å§‹è¯•ç”¨æˆ–å‡çº§åˆ°ä»˜è´¹ç‰ˆæœ¬ã€‚"
+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] "å…è´¹ç‰ˆä¸­çš„ç¾¤ç»„ä»…é™ %d 个席ä½"
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 "无法删除通过群组邀请而邀请的æˆå‘˜ã€‚您å¯ä»¥ç§»é™¤æ•´ä¸ªç¾¤ç»„,也å¯ä»¥è¦æ±‚å—邀群组的所有者移除æˆå‘˜ã€‚"
@@ -6095,6 +6161,9 @@ msgstr "项目邀请"
msgid "Billing|Remove user %{username} from your subscription"
msgstr "从您的订阅中删除用户 %{username}"
+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 "切æ¢å¸­ä½è¯¦æƒ…"
@@ -6110,14 +6179,11 @@ msgstr "查看待审批"
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
msgstr "您将è¦ä»Žè®¢é˜…中删除用户%{username}。如果继续,该用户将从 %{namespace} 群组åŠå…¶æ‰€æœ‰å­ç»„和项目中删除。此æ“作无法撤消。"
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr "您现在å¯ä»¥å¼€å§‹ç§»åŠ¨ %{namespaceName} 中的æˆå‘˜ã€‚当您关闭 %{strongStart}ä¸€ä¸ªå¸­ä½ %{strongEnd} 时,æˆå‘˜å°†å¤±åŽ»å¯¹ç¾¤ç»„çš„å­˜å–æƒé™ã€‚如果 2022 å¹´ 6 月 22 日之å‰å¯ç”¨äº†è¶…过 5 åæˆå‘˜çš„ %{strongStart}席ä½%{strongEnd},我们将选择 5 åæˆå‘˜ä¿æŒå­˜å–æƒé™ã€‚我们将首先计算具有拥有者和维护者角色的æˆå‘˜ï¼ŒæŽ¥ç€æ˜¯æœ€è¿‘活跃的æˆå‘˜ï¼Œç›´åˆ°è¾¾åˆ° 5 个æˆå‘˜ã€‚其余æˆå‘˜å°†å˜ä¸ºâ€œè¶…出é™åˆ¶â€çŠ¶æ€å¹¶å¤±åŽ»å¯¹è¯¥ç¾¤ç»„çš„å­˜å–æƒé™ã€‚"
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr "您的å…费群组现在é™åˆ¶ä¸º %{free_user_limit} åæˆå‘˜"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgstr "您现在å¯ä»¥å¼€å§‹ç§»åŠ¨ %{namespaceName} 中的æˆå‘˜ã€‚当您关闭 %{strongStart}ä¸€ä¸ªå¸­ä½ %{strongEnd} 时,æˆå‘˜å°†å¤±åŽ»å¯¹ç¾¤ç»„çš„å­˜å–æƒé™ã€‚如果 2022 å¹´10月 19 日之å‰å¯ç”¨äº†è¶…过 5 åæˆå‘˜çš„ %{strongStart}席ä½%{strongEnd},我们将选择 5 åæˆå‘˜ä¿æŒå­˜å–æƒé™ã€‚我们将首先ä¿ç•™å…·æœ‰æ‹¥æœ‰è€…和维护者角色的æˆå‘˜ï¼ŒæŽ¥ç€æ˜¯æœ€è¿‘活跃的æˆå‘˜ï¼Œç›´åˆ°è¾¾åˆ° 5 个æˆå‘˜ã€‚其余æˆå‘˜å°†å˜ä¸ºâ€œè¶…出é™åˆ¶â€çš„状æ€å¹¶å¤±åŽ»å¯¹ç¾¤ç»„的访问æƒé™ã€‚"
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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 "您的群组最近更改为使用å…费版。å…费群组é™åˆ¶ä¸º %{free_user_limit} åæˆå‘˜ï¼Œå…¶ä½™æˆå‘˜å°†èŽ·å¾—超é™çŠ¶æ€å¹¶æ— æ³•è®¿é—®è¯¥ç¾¤ç»„。您å¯ä»¥é€šè¿‡åˆ é™¤ä¸å†éœ€è¦è®¿é—®æƒé™çš„æˆå‘˜ï¼Œæˆ–将其切æ¢ä¸ºè¶…é™ï¼Œæ¥ä¸ºæ–°æˆå‘˜é‡Šæ”¾ç©ºé—´ã€‚è¦èŽ·å¾—æ— é™æ•°é‡çš„æˆå‘˜ï¼Œæ‚¨å¯ä»¥%{link_start}å‡çº§%{link_end}到付费版。"
+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 "您的群组最近更改为使用å…费版。%{over_limit_message}您å¯ä»¥é€šè¿‡åˆ é™¤ä¸å†éœ€è¦è®¿é—®æƒé™çš„æˆå‘˜ï¼Œæˆ–将其切æ¢ä¸ºè¶…é™çŠ¶æ€ï¼Œæ¥ä¸ºæ–°æˆå‘˜é‡Šæ”¾å¸­ä½ã€‚è¦èŽ·å¾—æ— é™æ•°é‡çš„会员,您å¯ä»¥%{link_start}å‡çº§%{link_end}到付费版。"
msgid "Bitbucket Server Import"
msgstr "BitbucketæœåŠ¡å™¨å¯¼å…¥"
@@ -6446,9 +6512,51 @@ msgstr "分支未载入 - %{branchId}"
msgid "Branch rules"
msgstr "分支规则"
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+msgstr "%{linkStart}支æŒé€šé…符%{linkEnd} ,例如 *-stable 或 production/*。"
+
+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 push"
+msgstr "å…许推é€"
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr "获å–分支时å‘生错误。"
+
+msgid "BranchRules|Branch"
+msgstr "分支"
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr "创建通é…符:%{searchTerm}"
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr "ä¿æŒç¨³å®šåˆ†æ”¯çš„安全并强制开å‘者使用åˆå¹¶è¯·æ±‚。%{linkStart}什么是å—ä¿æŠ¤çš„分支?%{linkEnd}"
+
+msgid "BranchRules|No matching results"
+msgstr "没有匹é…的结果"
+
+msgid "BranchRules|Protections"
+msgstr "ä¿æŠ¤"
+
+msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr "æ‹’ç»ä»£ç æŽ¨é€æ›´æ”¹ CODEOWNERS 文件中列出的文件。"
+
+msgid "BranchRules|Require approval from code owners."
+msgstr "需è¦ä»£ç æ‰€æœ‰è€…的核准。"
+
msgid "Branches"
msgstr "分支"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "分支:%{source_branch} 到 %{target_branch}"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "分支:%{source_branch} → %{target_branch}"
+
msgid "Branches|Active"
msgstr "活跃"
@@ -7056,9 +7164,6 @@ msgstr "无法找到此分支的 HEAD æ交"
msgid "Can't find variable: ZiteReader"
msgstr "找ä¸åˆ°å˜é‡: ZiteReader"
-msgid "Can't load mermaid module: %{err}"
-msgstr "无法加载mermaid模å—: %{err}"
-
msgid "Can't scan the code?"
msgstr "无法扫æ二维ç ï¼Ÿ"
@@ -7745,9 +7850,6 @@ msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
msgid "Child issues and epics"
msgstr "å­è®®é¢˜å’Œå²è¯—"
-msgid "Children"
-msgstr "å„¿ç«¥"
-
msgid "Chinese language support using"
msgstr "中文支æŒä½¿ç”¨"
@@ -8169,6 +8271,9 @@ msgstr "Cloud SQL for SQL Server"
msgid "CloudSeed|CloudSQL Instance"
msgstr "CloudSQL 实例"
+msgid "CloudSeed|Configuration"
+msgstr "é…ç½®"
+
msgid "CloudSeed|Create cluster"
msgstr "创建集群"
@@ -8187,6 +8292,12 @@ msgstr "与此项目相关的数æ®åº“实例"
msgid "CloudSeed|Database version"
msgstr "æ•°æ®åº“版本"
+msgid "CloudSeed|Databases"
+msgstr "æ•°æ®åº“"
+
+msgid "CloudSeed|Deployments"
+msgstr "部署"
+
msgid "CloudSeed|Description"
msgstr "æè¿°"
@@ -8244,12 +8355,18 @@ msgstr "无实例"
msgid "CloudSeed|Refs"
msgstr "Refs"
+msgid "CloudSeed|Regions"
+msgstr "地区"
+
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
msgstr "é¢å‘ Redis çš„å¯æ‰©å±•ã€å®‰å…¨ä¸”高å¯ç”¨çš„内存æœåŠ¡"
msgid "CloudSeed|Service"
msgstr "æœåŠ¡"
+msgid "CloudSeed|Service Account"
+msgstr "æœåŠ¡è´¦æˆ·"
+
msgid "CloudSeed|Services"
msgstr "æœåŠ¡"
@@ -9480,7 +9597,7 @@ msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if
msgstr "在`.gitlab-ci.yml`中é…ç½®ä¾èµ–扫æ,如果该文件ä¸å­˜åœ¨åˆ™åˆ›å»ºè¯¥æ–‡ä»¶"
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "é…置错误跟踪"
msgid "Configure GitLab"
msgstr "é…ç½® GitLab"
@@ -10067,9 +10184,6 @@ msgstr "您å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤å°†é•œåƒæ·»åŠ åˆ°å®¹å™¨é•œåƒåº“:"
msgid "Content parsed with %{link}."
msgstr "%{link}解æžçš„内容。"
-msgid "ContentEditor|Table of Contents"
-msgstr "目录列表"
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr "您必须æä¾›renderMarkdown 函数或自定义åºåˆ—化程åº"
@@ -10508,9 +10622,6 @@ msgstr "创建%{type}"
msgid "Create %{workspace} label"
msgstr "创建 %{workspace} 标记"
-msgid "Create Google Cloud project"
-msgstr "创建 Google Cloud 项目"
-
msgid "Create New Directory"
msgstr "创建新目录"
@@ -10961,6 +11072,9 @@ msgstr "信用å¡ï¼š"
msgid "Critical vulnerabilities present"
msgstr "存在严é‡æ¼æ´ž"
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr "è”系人"
@@ -11346,6 +11460,9 @@ msgstr "DAGå¯è§†åŒ–至少需è¦3个ä¾èµ–作业。"
msgid "DAST Configuration"
msgstr "DAST é…ç½®"
+msgid "DAST configuration not found"
+msgstr "未找到 DAST é…ç½®"
+
msgid "DAST profile not found: %{name}"
msgstr "未找到 DAST é…置文件:%{name}"
@@ -11364,6 +11481,9 @@ msgstr "å¹³å‡ï¼ˆæœ€è¿‘%{days}天)"
msgid "DORA4Metrics|Change failure rate"
msgstr "更改失败率"
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr "å˜æ›´å¤±è´¥çŽ‡ï¼ˆç™¾åˆ†æ¯”)"
+
msgid "DORA4Metrics|Date"
msgstr "日期"
@@ -11379,6 +11499,9 @@ msgstr "部署频率"
msgid "DORA4Metrics|Lead time for changes"
msgstr "å˜æ›´çš„å‰ç½®æ—¶é—´"
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr "å˜æ›´çš„å‰ç½®æ—¶é—´ï¼ˆä¸­ä½å¤©æ•°ï¼‰"
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr "中值(最近%{days}天)"
@@ -11424,6 +11547,9 @@ msgstr "该图表显示åˆå¹¶è¯·æ±‚被åˆå¹¶å’Œéƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒä¹‹é—´çš„中
msgid "DORA4Metrics|Time to restore service"
msgstr "æ¢å¤æœåŠ¡çš„时间"
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr "æ¢å¤æœåŠ¡çš„时间(中ä½å¤©æ•°ï¼‰"
+
msgid "DSN"
msgstr "DSN"
@@ -11460,9 +11586,21 @@ 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 "å¯ç”¨ DAST,在 CI/CD æµæ°´çº¿ä¸­è‡ªåŠ¨æµ‹è¯•åœ¨æ‚¨çš„项目中è¿è¡Œçš„应用程åºã€ç½‘站或 API 中的æ¼æ´žã€‚é…置更改必须应用于您的 .gitlab-ci.yml 文件æ‰èƒ½ç”Ÿæ•ˆã€‚有关所有é…置选项的详细信æ¯ï¼Œè¯·å‚阅 %{linkStart}DAST 文档%{linkEnd}。"
+msgid "DastConfig|Enabled"
+msgstr "å·²å¯ç”¨"
+
msgid "DastConfig|Generate code snippet"
msgstr "生æˆä»£ç ç‰‡æ®µ"
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr "最åŽä¸€æ¬¡æ‰«æ在æµæ°´çº¿ä¸­äºŽ %{runTimeAgo} 触å‘"
+
+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 "被动扫æ监控å‘é€åˆ°ç›®æ ‡çš„所有HTTP消æ¯(请求和å“应)。主动扫æ会对目标进行攻击以å‘现潜在æ¼æ´žã€‚"
@@ -12157,6 +12295,9 @@ msgstr "删除部署密钥"
msgid "Delete file"
msgstr "删除文件"
+msgid "Delete identity"
+msgstr "删除身份标识"
+
msgid "Delete image"
msgstr "删除镜åƒ"
@@ -12181,6 +12322,12 @@ msgstr "删除æµæ°´çº¿è®¡åˆ’"
msgid "Delete project"
msgstr "删除项目"
+msgid "Delete release"
+msgstr "删除å‘布"
+
+msgid "Delete release %{release}?"
+msgstr "删除å‘布 %{release}?"
+
msgid "Delete row"
msgstr "删除行"
@@ -12238,6 +12385,15 @@ msgstr "无法删除 Webhook。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
msgstr "删除wiki仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
+msgid "DeleteRelease|Are you sure you want to delete this release?"
+msgstr "您确定è¦åˆ é™¤æ­¤é¡¹å‘布å—?"
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr "欲了解更多信æ¯ï¼ŒæŸ¥çœ‹%{docsPathStart}删除å‘布%{docsPathEnd}。"
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr "您å³å°†åˆ é™¤å‘布 %{release} åŠå…¶ assets。Git 标签 %{tag} å°†ä¸ä¼šè¢«åˆ é™¤ã€‚"
+
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
msgstr "'%{name}' 价值æµå·²åˆ é™¤"
@@ -12262,9 +12418,6 @@ msgstr "æºåˆ†æ”¯å·²åˆ é™¤ã€‚"
msgid "Deletes the source branch"
msgstr "删除æºåˆ†æ”¯"
-msgid "Deletes the source branch."
-msgstr "删除æºåˆ†æ”¯ã€‚"
-
msgid "Deleting"
msgstr "删除中"
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
+msgid "Deploy Key"
+msgstr "部署密钥"
+
msgid "Deploy Keys"
msgstr "部署密钥"
@@ -12721,8 +12877,8 @@ msgstr "批准选项"
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr "批准或拒ç»éƒ¨ç½² #%{deploymentIid}"
-msgid "DeploymentApproval|Approved by %{user} %{time}"
-msgstr "由 %{user} 于 %{time} 批准"
+msgid "DeploymentApproval|Approved %{time}"
+msgstr "于 %{time} 批准"
msgid "DeploymentApproval|Approved by you %{time}"
msgstr "由您批准于 %{time}"
@@ -13516,9 +13672,6 @@ msgstr "文档页é¢URL"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr "文档é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
-msgid "Does not delete the source branch."
-msgstr "ä¸åˆ é™¤æºåˆ†æ”¯ã€‚"
-
msgid "Domain"
msgstr "域å"
@@ -13927,9 +14080,6 @@ msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„命å空间。"
msgid "Elastic|None. Select projects to index."
msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„项目。"
-msgid "Eligible users"
-msgstr "符åˆæ¡ä»¶çš„用户"
-
msgid "Email"
msgstr "电å­é‚®ä»¶"
@@ -14251,9 +14401,6 @@ msgstr "å¯ç”¨ Git 访问åè®®"
msgid "Enabled OAuth authentication sources"
msgstr "å¯ç”¨ OAuth 身份验è¯æº"
-msgid "Encountered an error while rendering: %{err}"
-msgstr "渲染时出现错误: %{err}"
-
msgid "End Time"
msgstr "结æŸæ—¶é—´"
@@ -14752,6 +14899,9 @@ msgstr "创建代ç ç‰‡æ®µ%{snippet_id}的代ç åº“时出错"
msgid "Error creating the snippet"
msgstr "创建代ç ç‰‡æ®µå‡ºé”™"
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr "创建æ¼æ´žå‘现结果时出错:%{errors}"
+
msgid "Error deleting project. Check logs for error details."
msgstr "删除项目时出错。请检查错误详细信æ¯ã€‚"
@@ -14933,7 +15083,7 @@ msgid "Error: Unable to find AWS role for current user"
msgstr "错误:找ä¸åˆ°å½“å‰ç”¨æˆ·çš„AWS角色"
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "访问令牌为 %{token_in_code_tag}"
msgid "ErrorTracking|Active"
msgstr "å¯ç”¨"
@@ -15724,24 +15874,21 @@ msgstr "无法删除Zoom会议"
msgid "Failed to remove a to-do item for the design."
msgstr "无法删除设计的待办事项。"
-msgid "Failed to remove attention because no user was found."
-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 request attention because no user was found."
-msgstr "由于找ä¸åˆ°ç”¨æˆ·ï¼Œæ— æ³•è¯·æ±‚关注。"
-
msgid "Failed to retrieve page"
msgstr "获å–页é¢å¤±è´¥"
@@ -15757,6 +15904,9 @@ msgstr "无法ä¿å­˜å好设置(%{error_message})。"
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 "由于日期格å¼æ— æ•ˆï¼Œè®¾ç½®åˆ°æœŸæ—¥æœŸå¤±è´¥ã€‚"
@@ -15802,9 +15952,6 @@ msgstr "误报"
msgid "Fast timeout"
msgstr "快速超时"
-msgid "Fast-forward merge without a merge commit"
-msgstr "æ— åˆå¹¶æ交的快进å¼åˆå¹¶"
-
msgid "Faster releases. Better code. Less pain."
msgstr "æ›´å¿«çš„å‘布。更好的代ç ã€‚更少的烦æ¼ã€‚"
@@ -16046,6 +16193,9 @@ msgstr "2月"
msgid "February"
msgstr "2月"
+msgid "Feedback issue"
+msgstr "å馈问题"
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr "获å–并检出这个åˆå¹¶è¯·æ±‚的功能分支:"
@@ -16463,6 +16613,10 @@ msgstr "框架删除æˆåŠŸ"
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr "冻结结æŸ"
@@ -16487,11 +16641,13 @@ msgstr "从%{code_open}%{source_title}%{code_close}到"
msgid "From %{providerTitle}"
msgstr "%{providerTitle}æºåœ°å€"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr "从 2022 å¹´ 6 月 22 日(GitLab 15.1)开始,å…费的个人命å空间和顶级群组将é™åˆ¶ä¸º %{free_limit} 个æˆå‘˜"
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] "自 2022 å¹´ 10 月 19 日起,å…费群组将é™åˆ¶ä¸º %d åæˆå‘˜"
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr "从 2022 å¹´ 6 月 22 日(15.1)开始,您的所有个人项目中最多å¯ä»¥æœ‰ %{free_limit} 个独特æˆå‘˜"
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] "从 2022 å¹´ 10 月 19 日起,您的所有个人项目中最多å¯ä»¥æœ‰ %d 个唯一æˆå‘˜"
msgid "From issue creation until deploy to production"
msgstr "从创建议题到部署至生产环境"
@@ -16550,6 +16706,9 @@ msgstr "为您需è¦è®¿é—®GitLab API的应用程åºç”Ÿæˆé¡¹ç›®è®¿é—®ä»¤ç‰Œã€‚"
msgid "Generate site and private keys at"
msgstr "生æˆç«™ç‚¹å’Œç§é’¥åœ¨"
+msgid "Generated with JSON data"
+msgstr "使用 JSON æ•°æ®ç”Ÿæˆ"
+
msgid "Generic"
msgstr "通用"
@@ -16597,6 +16756,9 @@ msgstr "%{component} å·²åŒæ­¥"
msgid "Geo|%{component} verified"
msgstr "%{component} 已验è¯"
+msgid "Geo|%{label} %{timeAgo}"
+msgstr "%{label} %{timeAgo}"
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label}ä¸èƒ½ä¸ºç©º"
@@ -16771,9 +16933,6 @@ msgstr "如需进行å˜æ›´ï¼Œå¿…须访问主站点。"
msgid "Geo|In progress"
msgstr "进行中"
-msgid "Geo|In sync"
-msgstr "å·²åŒæ­¥"
-
msgid "Geo|Internal URL"
msgstr "内部 URL"
@@ -16831,9 +16990,6 @@ msgstr "未找到Geo站点"
msgid "Geo|No available replication slots"
msgstr "没有å¯ç”¨çš„å¤åˆ¶æ§½"
-msgid "Geo|Not synced yet"
-msgstr "尚未åŒæ­¥"
-
msgid "Geo|Nothing found…"
msgstr "找ä¸åˆ°â€¦"
@@ -17089,9 +17245,6 @@ msgstr "éžå¥åº·"
msgid "Geo|Unknown"
msgstr "未知"
-msgid "Geo|Unknown state"
-msgstr "未知状æ€"
-
msgid "Geo|Updated %{timeAgo}"
msgstr "更新于%{timeAgo}"
@@ -17275,6 +17428,9 @@ msgstr "GitLab议题"
msgid "GitLab KAS"
msgstr "GitLab KAS"
+msgid "GitLab Logo"
+msgstr "GitLab Logo"
+
msgid "GitLab Pages"
msgstr "GitLab Pages"
@@ -17299,9 +17455,6 @@ msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
msgstr "GitLabå¸æˆ·è¯·æ±‚被拒ç»"
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr "GitLab å’Œ Google Cloud é…置似乎ä¸å®Œæ•´ã€‚è¿™å¯èƒ½éœ€è¦ç”±æ‚¨çš„ GitLab 管ç†å›¢é˜Ÿè§£å†³ï¼Œæ‚¨å¯ä»¥ä¸Žä»–们分享这些日志:"
-
msgid "GitLab commit"
msgstr "GitLabæ交"
@@ -17395,6 +17548,9 @@ msgstr "å¯ä»¥æŒ‰é¡¹ç›®è¦†ç›–。如果没有é™åˆ¶ï¼Œè¯·è¾“å…¥ 0。è¦ç»§æ‰¿è¯¥å
msgid "GitLabPages|Certificate: %{subject}"
msgstr "è¯ä¹¦: %{subject}"
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "检查æµæ°´çº¿çŠ¶æ€"
+
msgid "GitLabPages|Configure pages"
msgstr "é…置页é¢"
@@ -17446,6 +17602,9 @@ 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 "在获å–域å%{domain}çš„Let's Encryptè¯ä¹¦æ—¶å‡ºé”™ã€‚如需é‡è¯•ï¼Œè¯·è®¿é—®æ‚¨çš„%{link_start}域详细信æ¯%{link_end}。"
+msgid "GitLabPages|Start over"
+msgstr "从头开始"
+
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
msgstr "域åå’Œè¯ä¹¦æ”¯æŒå·²è¢«ç¦ç”¨ã€‚请系统管ç†å‘˜å¯ç”¨ã€‚"
@@ -17458,6 +17617,9 @@ msgstr "正在更新您的页é¢é…ç½®..."
msgid "GitLabPages|Verified"
msgstr "已验è¯"
+msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
+msgstr "正在等待 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 "å¯ç”¨åŽï¼Œæ‰€æœ‰é€šè¿‡HTTP的访问å°è¯•éƒ½ä¼šè‡ªåŠ¨é‡å®šå‘到HTTPS,使用状æ€ä»£ç 301。 需è¦å¯¹æ‰€æœ‰åŸŸå有效的è¯ä¹¦ã€‚%{docs_link_start}了解更多信æ¯ã€‚%{link_end}"
@@ -17470,6 +17632,9 @@ msgstr "使用 GitLab Pages,您å¯ä»¥ç›´æŽ¥ä»Žæ‚¨çš„ GitLab 仓库托管您的
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 "您的Pages站点尚未é…置。请å‚阅 %{docs_link_start}GitLab Pages 文档%{link_end} 以了解如何上传您的é™æ€ç«™ç‚¹å¹¶è®© GitLab 为其æä¾›æœåŠ¡ã€‚您还å¯ä»¥ä»Ž %{samples_link_start}示例 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 "您的项目已为 Pages é…置。现在我们必须等待æµæ°´çº¿ç¬¬ä¸€æ¬¡æˆåŠŸã€‚"
+
msgid "GitLabPages|Your pages are served under:"
msgstr "您的网页æœåŠ¡å¯é€šè¿‡ä»¥ä¸‹åœ°å€è®¿é—®:"
@@ -17612,7 +17777,7 @@ msgid "GlobalSearch|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a searc
msgstr "使用快æ·é”® %{kbdOpen}/%{kbdClose} 开始æœç´¢"
msgid "GlobalSearch|What are you searching for?"
-msgstr "您正在æœç´¢ä»€ä¹ˆï¼Ÿ"
+msgstr "您想è¦æœç´¢ä»€ä¹ˆï¼Ÿ"
msgid "GlobalSearch|all GitLab"
msgstr "全局æœç´¢"
@@ -17788,18 +17953,15 @@ msgstr "转到您的代ç ç‰‡æ®µ"
msgid "Google Cloud"
msgstr "Google Cloud"
+msgid "Google Cloud Error - %{error}"
+msgstr "Google Cloud 错误 - %{error}"
+
msgid "Google Cloud Project"
msgstr "Google Cloud 项目"
msgid "Google Cloud authorizations required"
msgstr "éœ€è¦ Google Cloud 授æƒ"
-msgid "Google Cloud project misconfigured"
-msgstr "Google Cloud 项目é…置错误"
-
-msgid "Google Cloud project required"
-msgstr "éœ€è¦ Google Cloud 项目"
-
msgid "GoogleCloud|Cancel"
msgstr "å–消"
@@ -18019,9 +18181,6 @@ msgstr "群组导航"
msgid "Group overview content"
msgstr "群组概述内容"
-msgid "Group owners can register group runners in the %{link}"
-msgstr "群组所有者å¯ä»¥åœ¨ %{link} 注册群组 Runner"
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr "群组路径已被å ç”¨ï¼Œæˆ‘们已ç»æŽ¨è了一个å¯ç”¨çš„。"
@@ -18175,8 +18334,8 @@ msgstr "您确定è¦é‡ç½® SCIM 令牌å—?在更新新令牌之å‰ï¼ŒSCIM é…ç
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr "在执行SSO之å‰ï¼Œå¯ç”¨SAML身份验è¯ã€‚"
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
-msgstr "在对 Git 活动强制执行仅 SSO 身份验è¯ä¹‹å‰ï¼Œä¸º Web 活动å¯ç”¨ä»… SSO 身份验è¯ã€‚"
+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 "è¯ä¹¦æŒ‡çº¹"
@@ -18340,8 +18499,8 @@ msgstr "应用到所有å­ç¾¤ç»„,除éžè¢«ç¾¤ç»„所有者覆盖。已添加到
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "已为群组更新 Auto DevOps æµæ°´çº¿"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
-msgstr "自动å°ç¦åœ¨ç‰¹å®šé—´éš”内下载超过指定数é‡çš„项目的用户。"
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
+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 "仅在顶级群组中å¯ç”¨ã€‚适用于所有å­ç»„。除éžæ‰‹åŠ¨åˆ é™¤ï¼Œå¦åˆ™ %{group} 以外的群组所共享的群组ä»ä¼šå…±äº«ã€‚"
@@ -18388,6 +18547,9 @@ msgstr "电å­é‚®ä»¶é€šçŸ¥å·²ç¦ç”¨"
msgid "GroupSettings|Export group"
msgstr "导出群组"
+msgid "GroupSettings|Git abuse rate limit"
+msgstr "Git 滥用率é™åˆ¶"
+
msgid "GroupSettings|Group members are not notified if the group is mentioned."
msgstr "如果群组被æåŠï¼Œä¸é€šçŸ¥ç¾¤ç»„æˆå‘˜ã€‚"
@@ -18400,15 +18562,9 @@ msgstr "如果未在群组或实例级别指定,则默认为 %{default_initial
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|Interval (seconds)"
-msgstr "间隔(秒)"
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr "æˆå‘˜ä¸èƒ½é‚€è¯· %{group} åŠå…¶å­ç»„之外的群组"
-msgid "GroupSettings|Number of projects"
-msgstr "项目数"
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr "组织和è”系人å¯ä»¥è¢«åˆ›å»ºå¹¶å…³è”到议题。"
@@ -18427,9 +18583,6 @@ msgstr "阻止派生到群组外。"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "阻止派生设置未ä¿å­˜"
-msgid "GroupSettings|Project download rate limit"
-msgstr "项目下载速率é™åˆ¶"
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr "%{group} 中的项目ä¸èƒ½ä¸Žå…¶ä»–群组共享"
@@ -18454,15 +18607,9 @@ msgstr "为该群组中æ¯ä¸ª Pages 站点中的所有内容设置大å°é™åˆ¶ã€
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr "设置群组中创建的新仓库的默认分支的åˆå§‹å称和ä¿æŠ¤ã€‚"
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr "设置为 0 以ç¦ç”¨é™åˆ¶ã€‚"
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr "如果找ä¸åˆ°æ›¿ä»£ CI é…置文件,则Auto DevOps æµæ°´çº¿å°†è¿è¡Œã€‚"
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-msgstr "用户在被å°ç¦ä¹‹å‰ï¼Œå¯ä»¥åœ¨æŒ‡å®šçš„间隔内下载的项目的最大数é‡ã€‚设置为 0 以ç¦ç”¨é™åˆ¶ã€‚"
-
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 "å¯ä»¥é€‰æ‹©è¯¥å­ç»„中的项目作为该组中创建的新项目的模æ¿ã€‚ %{link_start}了解更多。%{link_end}"
@@ -18580,6 +18727,9 @@ 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 "%{linkStart}群组%{linkEnd}å…许您在多个项目之间进行管ç†ä¸Žå作。群组的æˆå‘˜æ‹¥æœ‰è®¿é—®å…¶ä¸­æ‰€æœ‰é¡¹ç›®çš„æƒé™ã€‚"
@@ -18598,6 +18748,9 @@ 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 "在æºå®žä¾‹çš„ %{pat_link_start}用户设置%{pat_link_end} 中创建。出于 %{short_living_link_start}安全原因%{short_living_link_end},在创建令牌时使用较短的到期日期。"
@@ -18643,6 +18796,9 @@ msgstr "è¦å¯¼å…¥ç¾¤ç»„,请导航到 GitLab æºå®žä¾‹çš„群组设置, %{link
msgid "GroupsNew|Upload file"
msgstr "上传文件"
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "您还å¯ä»¥%{linkStart}导入现有群组%{linkEnd}。"
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr "例如h8d3f016698e..."
@@ -18721,6 +18877,15 @@ msgstr "删除头åƒ"
msgid "Groups|Save changes"
msgstr "ä¿å­˜æ›´æ”¹"
+msgid "Groups|Subgroup URL"
+msgstr "å­ç»„ URL"
+
+msgid "Groups|Subgroup name"
+msgstr "å­ç»„å称"
+
+msgid "Groups|Subgroup slug"
+msgstr "å­ç»„标识串"
+
msgid "Guideline"
msgstr "å‚考"
@@ -18739,8 +18904,8 @@ msgstr "HTTP Basic:访问被拒ç»\\n您必须使用具有'api'æƒé™çš„个人
msgid "Harbor Registry"
msgstr "Harbor é•œåƒåº“"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$HARBOR_PASSWORD’, ‘$HARBOR_URL’ and ‘$HARBOR_PROJECT’ will be created for CI/CD use."
-msgstr "å¯ç”¨ Harbor 集æˆåŽï¼Œå°†åˆ›å»ºå…¨å±€å˜é‡ “$HARBOR_USERNAMEâ€ã€â€œ$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。"
@@ -18849,12 +19014,6 @@ msgstr "哈希仓库存储路径"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr "新项目ä¸èƒ½å†ç¦ç”¨å“ˆå¸Œå­˜å‚¨"
-msgid "Have a quick chat with us about your experience."
-msgstr "与我们快速èŠèŠæ‚¨çš„体验。"
-
-msgid "Have more to say about GitLab?"
-msgstr "有更多关于GitLab的内容?"
-
msgid "Header logo"
msgstr "Header logo"
@@ -19073,6 +19232,9 @@ msgstr "原始警报:"
msgid "HighlightBar|Time to SLA:"
msgstr "è·SLA时间: "
+msgid "Historical release"
+msgstr "历å²å‘布"
+
msgid "History"
msgstr "历å²"
@@ -19142,6 +19304,9 @@ msgstr "如何使用 web 终端?"
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 "IP 计入 IP 地å€é™åˆ¶çš„秒数。"
@@ -19325,6 +19490,9 @@ msgstr "您的å¸æˆ·å·²æˆåŠŸéªŒè¯ã€‚ç¨åŽæ‚¨å°†è¢«é‡å®šå‘到您的å¸æˆ·æˆ–
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
msgstr "您的验è¯ç å°†åœ¨ %{expires_in_minutes} 分钟åŽè¿‡æœŸã€‚"
+msgid "Identity|Provider ID"
+msgstr "Provider ID"
+
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 "如果任何索引字段超过此é™åˆ¶ï¼Œåˆ™å°†å…¶æˆªæ–­ä¸ºæ­¤å­—符数。其余内容既ä¸ç¼–入索引也ä¸å¯æœç´¢ã€‚è¿™ä¸é€‚用于仓库和 wiki 索引。对于无é™å­—符,将此设置为 0。"
@@ -19352,6 +19520,9 @@ msgstr "如果å¯ç”¨ï¼Œåˆ™åªä¼šé•œåƒå—ä¿æŠ¤çš„分支。"
msgid "If no options are selected, only administrators can register runners."
msgstr "如果没有选定选项,åªæœ‰ç®¡ç†å‘˜å¯ä»¥æ³¨å†ŒRunner。"
+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 "如果活跃用户数é‡è¶…过了用户é™åˆ¶ï¼Œæ‚¨ä¸‹æ¬¡çš„许å¯è¯å¯¹è´¦æ—¶å°†ä¼šæ”¶å–%{users_over_license_link}个席ä½çš„费用。"
@@ -19628,6 +19799,9 @@ msgstr[0] "正在导入%d个仓库"
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 "在此 URL 上没有有效的 Git 仓库。如果您的 HTTP 仓库ä¸èƒ½å…¬å¼€è®¿é—®ï¼Œè¯·éªŒè¯æ‚¨çš„凭æ®ã€‚"
@@ -19673,9 +19847,6 @@ msgstr "%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Franc
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr "%{strong_start}多个批准角色%{strong_end} — 包括代ç æ‰€æœ‰è€…和所需的åˆå¹¶æ‰¹å‡†"
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr "%{strong_start}总体而言,开始使用 GitLab 的难易程度如何?%{strong_end}"
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr "*GitLab*,åè¯ï¼šé«˜æ•ˆå›¢é˜Ÿçš„åŒä¹‰è¯"
@@ -19733,9 +19904,6 @@ 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 "通过å¯ç”¨ä»£ç æ‰€æœ‰è€…和所需的åˆå¹¶æ‰¹å‡†ï¼Œåˆé€‚的人将审查åˆé€‚çš„ MR。这是åŒèµ¢çš„:更干净的代ç å’Œæ›´æœ‰æ•ˆçš„审查过程。"
-msgid "InProductMarketing|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr "å•å‡»ä¸‹é¢ä¸Žæ‚¨çš„答案相对应的数字 - 1 表示éžå¸¸å›°éš¾ï¼Œ5 表示éžå¸¸å®¹æ˜“。"
-
msgid "InProductMarketing|Code owners"
msgstr "代ç æ‰€æœ‰è€…"
@@ -19778,9 +19946,6 @@ msgstr "ä¾èµ–扫æ"
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr "您知é“使用 GitLab 的团队效率更高å—?"
-msgid "InProductMarketing|Difficult"
-msgstr "å›°éš¾"
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr "深入并创建一个项目和仓库"
@@ -19790,18 +19955,12 @@ msgstr "探索专业版和旗舰版"
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr "探索专业版和旗舰版。"
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr "简å•"
-
msgid "InProductMarketing|Epics"
msgstr "å²è¯—"
@@ -19820,9 +19979,6 @@ msgstr "探索 GitLab CI/CD 的力é‡"
msgid "InProductMarketing|Facebook"
msgstr "Facebook"
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr "æ¥è‡ªåƒæ‚¨è¿™æ ·çš„用户的å馈真正改善了我们的产å“,感谢您的帮助ï¼"
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr "感觉需è¦é€Ÿåº¦å—?"
@@ -19991,9 +20147,6 @@ msgstr "多个必需的核准人"
msgid "InProductMarketing|Need an alternative to importing?"
msgstr "需è¦æ›¿ä»£å¯¼å…¥çš„方法å—?"
-msgid "InProductMarketing|Neutral"
-msgstr "中性"
-
msgid "InProductMarketing|No credit card required."
msgstr "ä¸éœ€è¦ä¿¡ç”¨å¡ã€‚"
@@ -20066,9 +20219,6 @@ msgstr "åœæ­¢ç–‘惑,使用GitLab回答以下问题:"
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 "简化代ç å®¡æ ¸ï¼Œä¸€ç›®äº†ç„¶åœ°çŸ¥é“è°ä¸å¯ç”¨ï¼Œåœ¨è¯„论或电å­é‚®ä»¶ä¸­æ²Ÿé€šï¼Œå¹¶ä¸ŽSlackæ•´åˆï¼Œè®©æ¯ä¸ªäººéƒ½åœ¨åŒä¸€é¡µé¢ä¸Šã€‚"
-msgid "InProductMarketing|Take this 1-question survey!"
-msgstr "å‚加这个åªæœ‰ä¸€ä¸ªé—®é¢˜çš„调查ï¼"
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr "使用GitLab的第一步"
@@ -20141,12 +20291,6 @@ msgstr "使用我们的AWS cloudformation模æ¿ï¼Œåªéœ€ç‚¹å‡»å‡ ä¸‹ï¼Œå³å¯è®©
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr "å…¨çƒè¶…过10万个组织使用:"
-msgid "InProductMarketing|Very difficult"
-msgstr "éžå¸¸å›°éš¾"
-
-msgid "InProductMarketing|Very easy"
-msgstr "éžå¸¸å®¹æ˜“"
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr "在时间线上å¯è§†åŒ–您的å²è¯—和里程碑。"
@@ -20162,9 +20306,6 @@ msgstr "观看 iOS 构建实践。"
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 "我们知é“一些关于效率的事情,我们想分享给大家。注册GitLab Ultimateçš„å…费试用版,您的团队将从第一天开始使用它。"
-msgid "InProductMarketing|We want your GitLab experience to be great"
-msgstr "我们希望您的GitLab体验éžå¸¸å¥½"
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr "从产å“到开å‘,å†åˆ°å®¡æŸ¥å’Œç”Ÿäº§ï¼Œæˆ‘们的价值æµæ—¶é—´è¡¨æ˜¯ä»€ä¹ˆæ ·çš„?"
@@ -21186,8 +21327,8 @@ 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 this namespace can start a trial or upgrade to a paid tier."
-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 "%{linkStart}了解更多%{linkEnd}关于角色æƒé™çš„ä¿¡æ¯"
@@ -21262,8 +21403,8 @@ 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 "è¦å‘新团队æˆå‘˜åˆ†é…议题,您需è¦ä¸€ä¸ªè®®é¢˜æ‰€å±žçš„项目。 %{linkStart}从创建一个项目开始。%{linkEnd}"
-msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-msgstr "è¦èŽ·å¾—更多æˆå‘˜ï¼Œæ­¤å‘½å空间的所有者å¯ä»¥ %{trialLinkStart}开始试用%{trialLinkEnd} 或 %{upgradeLinkStart}å‡çº§%{upgradeLinkEnd} 到付费计划。"
+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|To make more space, you can remove members who no longer need access."
msgstr "为了创造更多空间,您å¯ä»¥ç§»é™¤ä¸å†éœ€è¦è®¿é—®çš„æˆå‘˜ã€‚"
@@ -21277,9 +21418,6 @@ msgstr "您ä¸èƒ½æ·»åŠ æ›´å¤šæˆå‘˜ï¼Œä½†æ‚¨å¯ä»¥åˆ é™¤ä¸å†éœ€è¦è®¿é—®çš„æˆ
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr "在 %{name},您åªæœ‰ %{count} 个更多的 %{members} 的空间"
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr "您的个人项目中仅有 %{count} 个更多的 %{members} 的空间"
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "您正在邀请一个群组加入 %{strongStart}%{name}%{strongEnd} 群组。"
@@ -21685,6 +21823,9 @@ msgstr "斜体文字"
msgid "Iteration"
msgstr "迭代"
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr "迭代更改为"
@@ -21700,12 +21841,36 @@ 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 "自动化起始日期必须在活动迭代 %{iteration_dates} 之åŽã€‚"
+
+msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
+msgstr "自动化起始日期必须在过去的迭代 %{iteration_dates} 之åŽã€‚"
+
+msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
+msgstr "自动化开始日期将追溯创建过去的迭代。%{start_date} 是最早å¯èƒ½çš„开始日期。"
+
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 "周期é…置无效。"
@@ -21727,6 +21892,9 @@ msgstr "创建周期"
msgid "Iterations|Create iteration"
msgstr "创建迭代"
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "在定期计划上自动创建迭代。"
+
msgid "Iterations|Delete cadence"
msgstr "删除周期"
@@ -21757,18 +21925,21 @@ msgstr "编辑迭代"
msgid "Iterations|Edit iteration cadence"
msgstr "编辑迭代周期"
+msgid "Iterations|Enable roll over"
+msgstr "å¯ç”¨è½®æ¢"
+
msgid "Iterations|Error loading iteration cadences."
msgstr "加载迭代周期时出错。"
-msgid "Iterations|First iteration start date"
-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|Learn more about automatic scheduling"
msgstr "了解更多关于自动计划的信æ¯"
@@ -21796,9 +21967,6 @@ msgstr "未找到迭代"
msgid "Iterations|No iterations in cadence."
msgstr "周期中没有迭代。"
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr "在周期开始åŽï¼Œä»»ä½•äººéƒ½æ— æ³•æ›´æ”¹æ­¤æ—¥æœŸã€‚"
-
msgid "Iterations|No open iterations."
msgstr "没有开放的迭代。"
@@ -21826,15 +21994,15 @@ 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|The start date of the first iteration determines when your cadence begins."
-msgstr "第一次迭代的开始日期决定了您的周期何时开始。"
-
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr "å¯ä»¥å°†æ­¤å‘¨æœŸè½¬æ¢ä¸ºä½¿ç”¨è‡ªåŠ¨è®¡åˆ’"
@@ -22318,6 +22486,9 @@ msgstr "已计划"
msgid "Job|Scroll to bottom"
msgstr "滚动到底部"
+msgid "Job|Scroll to next failure"
+msgstr "滚动到下一个失败"
+
msgid "Job|Scroll to top"
msgstr "滚动到顶部"
@@ -22441,8 +22612,8 @@ msgstr "é”®"
msgid "Key (PEM)"
msgstr "秘钥 (PEM)"
-msgid "Key: %{key}"
-msgstr "密钥: %{key}"
+msgid "Key:"
+msgstr "Key:"
msgid "Keyboard shortcuts"
msgstr "å¿«æ·é”®"
@@ -22707,15 +22878,9 @@ msgstr "最åŽç™»å½•IP:"
msgid "Last sign-in at:"
msgstr "最åŽç™»å½•äºŽï¼š"
-msgid "Last successful sync"
-msgstr "上次æˆåŠŸåŒæ­¥"
-
msgid "Last successful update"
msgstr "最近æˆåŠŸçš„æ›´æ–°"
-msgid "Last time checked"
-msgstr "上次检查时间"
-
msgid "Last time verified"
msgstr "最近一次验è¯"
@@ -22998,20 +23163,20 @@ msgstr "旧许å¯è¯"
msgid "Less Details"
msgstr "收起详情"
+msgid "Less restrictive visibility"
+msgstr "é™åˆ¶è¾ƒå°‘çš„å¯è§æ€§"
+
msgid "Let's Encrypt does not accept emails on example.com"
msgstr "Let's Encryptä¸æŽ¥å—example.com的电å­é‚®ä»¶"
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 "Let's Encrypt是一个å…è´¹ã€è‡ªåŠ¨åŒ–和开放的è¯ä¹¦æŽˆæƒ(CA)机构。它å¯ä»¥æ供网站å¯ç”¨HTTPS (SSL/TLS)所需的数字è¯ä¹¦ã€‚通过%{docs_link_start}GitLab Pages上的文档%{docs_link_end}æ¥äº†è§£Let's Encrypté…置的更多信æ¯ã€‚"
-msgid "Let's talk!"
-msgstr "让我们æ¥è°ˆè°ˆï¼"
-
msgid "License Compliance"
msgstr "许å¯è¯åˆè§„"
-msgid "License Compliance| Used by"
-msgstr "使用者"
+msgid "License Compliance| Used by %{dependencies}"
+msgstr "已被 %{dependencies} 使用"
msgid "License compliance"
msgstr "许å¯è¯åˆè§„"
@@ -23265,8 +23430,11 @@ msgstr "链接的电å­é‚®ä»¶ (%{email_count})"
msgid "Linked epics"
msgstr "å…³è”å²è¯—"
-msgid "Linked issues"
-msgstr "相关议题"
+msgid "Linked incidents or issues"
+msgstr "å…³è”的事件或议题"
+
+msgid "Linked items"
+msgstr "å…³è”项"
msgid "LinkedIn"
msgstr "领英(LinkedIn)"
@@ -23277,6 +23445,48 @@ msgstr "领英(LinkedIn):"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
msgstr "%{counterLabel}个更多下游æµæ°´çº¿"
+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 "创建事件资æºé“¾æŽ¥æ—¶å‡ºé”™ï¼š%{error}"
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr "删除事件资æºé“¾æŽ¥æ—¶å‡ºé”™ï¼š%{error}"
+
+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 "链接"
@@ -23604,9 +23814,6 @@ msgstr "Manifest文件导入"
msgid "Manual"
msgstr "手动"
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr "手动迭代周期被废弃。åªå…许自动迭代。"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "无法ä¿å­˜è®®é¢˜çš„顺åº"
@@ -23868,8 +24075,8 @@ msgstr "最大字段长度"
msgid "Maximum file size indexed (KiB)"
msgstr "索引的最大文件大å°(KiB)"
-msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}."
-msgstr "最大文件大å°ä¸º 1 MB。图片大å°å¿…须为 32 x 32 åƒç´ ã€‚å…许的图åƒæ ¼å¼ä¸º %{favicon_extension_whitelist}。"
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr "最大文件大å°ä¸º 1 MB。图片大å°å¿…须为 32 x 32 åƒç´ ã€‚å…许的图åƒæ ¼å¼ä¸º %{favicon_extension_allowlist}。"
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
msgstr "最大文件大å°ç‚ºä¸º 1MB。页é¢é’ˆå¯¹ 24 åƒç´ é«˜çš„ header logo 进行了优化"
@@ -25258,14 +25465,8 @@ msgstr "终止环境"
msgid "MrList|Assigned to %{name}"
msgstr "指派给 %{name}"
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr "请求指派人 %{name} 的关注"
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr "请求审核者 %{name} 的关注"
-
msgid "MrList|Review requested from %{name}"
-msgstr "审核æ¥è‡ª %{name} 的请求"
+msgstr "请求æ¥è‡ª %{name} 的审核"
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 "如果继续,您确认å“应将用于改进 GitLab å¹¶ç¬¦åˆ %{linkStart}GitLab éšç§æ”¿ç­–%{linkEnd}。"
@@ -25288,8 +25489,8 @@ msgstr "多项目"
msgid "Multiple HTTP integrations are not supported for this project"
msgstr "此项目ä¸æ”¯æŒå¤šä¸ªHTTP集æˆ"
-msgid "Multiple IP address ranges are supported."
-msgstr "支æŒå¤šä¸ªIP地å€èŒƒå›´ã€‚"
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "支æŒå¤šä¸ª IP 地å€èŒƒå›´ã€‚ä¸å½±å“对群组设置的访问。"
msgid "Multiple Prometheus integrations are not supported"
msgstr "ä¸æ”¯æŒå¤šä¸ªPrometheus集æˆ"
@@ -25472,9 +25673,6 @@ msgstr "退出并登录到其他账å·"
msgid "Need help?"
msgstr "如需帮助:"
-msgid "Need your attention"
-msgstr "需è¦æ‚¨çš„注æ„"
-
msgid "Needs"
msgstr "ä¾èµ–关系图"
@@ -25597,7 +25795,7 @@ msgid "New epic title"
msgstr "æ–°å²è¯—标题"
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„错误跟踪访问令牌ï¼"
msgid "New file"
msgstr "新建文件"
@@ -25743,6 +25941,9 @@ msgstr "没有è¦æ˜¾ç¤ºçš„ CSV æ•°æ®ã€‚"
msgid "No Epic"
msgstr "æ— å²è¯—"
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "没有 Google Cloud 项目 - 您至少需è¦ä¸€ä¸ª Google Cloud 项目"
+
msgid "No Matching Results"
msgstr "无匹é…结果"
@@ -25773,9 +25974,6 @@ msgstr "未找到产物"
msgid "No assignee"
msgstr "无指派人"
-msgid "No attention request"
-msgstr "没有关注请求"
-
msgid "No authentication methods configured."
msgstr "未é…置身份验è¯æ–¹æ³•ã€‚"
@@ -26074,9 +26272,6 @@ msgstr "没有任何群组里程碑与å‘布具有相åŒçš„项目"
msgid "Normal text"
msgstr "普通文本"
-msgid "Not Implemented"
-msgstr "尚未实现"
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr "并éžæ‰€æœ‰æµè§ˆå™¨éƒ½æ”¯æŒU2F设备。因此,我们需è¦æ‚¨é¦–先设置一个åŒé‡èº«ä»½éªŒè¯åº”用。这样å³ä½¿æ‚¨ä½¿ç”¨çš„æµè§ˆå™¨ä¸å—支æŒï¼Œæ‚¨ä¹Ÿå¯ä»¥ç™»å½•ã€‚"
@@ -26197,6 +26392,9 @@ 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 "您åªèƒ½åœ¨ä¿¡æ¯æµä¸­çœ‹åˆ°%{boldStart}其他活动%{boldEnd} 。è¦æ·»åŠ è¯„论,请切æ¢åˆ°ä»¥ä¸‹é€‰é¡¹ä¹‹ä¸€ã€‚"
+msgid "Note|The created date provided is too far in the past."
+msgstr "指定的创建日期太早。"
+
msgid "Nothing to preview."
msgstr "没有å¯é¢„览的内容。"
@@ -26330,6 +26528,15 @@ msgstr "%{author_link} 的议题 %{issue_reference_link} å³å°†åˆ°æœŸã€‚"
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr "%{mr_link} 中的 %{commit_link}"
+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|%{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|Assignee changed from %{fromNames} to %{toNames}"
msgstr "指派人从 %{fromNames} 更改为 %{toNames}"
@@ -26495,6 +26702,10 @@ msgstr "OmniAuth"
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] "在 %{end_date},您的试用期将结æŸï¼Œ%{namespace_name} 将被é™åˆ¶ä¸º %{free_user_limit} 个æˆå‘˜"
+
msgid "On track"
msgstr "进度正常"
@@ -26967,9 +27178,6 @@ msgstr "仅当ä¸ä½¿ç”¨è§’色实例凭æ®æ—¶æ‰éœ€è¦ã€‚"
msgid "Only use lowercase letters, numbers, and underscores."
msgstr "仅使用å°å†™å­—æ¯ã€æ•°å­—和下划线。"
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-msgstr "åªæœ‰æ¥è‡ªæŒ‡å®š IP 地å€èŒƒå›´çš„用户æ‰èƒ½è®¿é—®æ­¤ç¾¤ç»„,包括所有å­ç»„ã€é¡¹ç›®å’Œ Git 仓库。"
-
msgid "Only verified users with an email address in any of these domains can be added to the group. Multiple domains are supported."
msgstr "åªæœ‰å…·æœ‰è¿™äº›åŸŸå的电å­é‚®ä»¶åœ°å€çš„已验è¯ç”¨æˆ·æ‰èƒ½æ·»åŠ åˆ°ç¾¤ç»„。支æŒå¤šåŸŸå。"
@@ -27063,6 +27271,9 @@ 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 "è¿ç»´ä»ªè¡¨ç›˜å’ŒçŽ¯å¢ƒä»ªè¡¨ç›˜å…±äº«ç›¸åŒçš„项目列表。当您从一个仪表盘中添加或删除项目时,系统会从å¦ä¸€ä¸ªä»ªè¡¨ç›˜ä¸­æ·»åŠ æˆ–删除项目。%{linkStart}更多信æ¯%{linkEnd}"
+
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
msgstr "è¿ç»´ä»ªè¡¨æ¿æä¾›æ¯ä¸ªé¡¹ç›®çš„è¿è¡ŒçŠ¶å†µçš„摘è¦ï¼ŒåŒ…括æµæ°´çº¿å’Œè­¦æŠ¥çŠ¶æ€ã€‚"
@@ -27384,6 +27595,10 @@ msgstr "ç”±%{branch}分支上的%{link}æ交创建"
msgid "PackageRegistry|Debian"
msgstr "Debian"
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] "删除 %d 个 assets"
+
msgid "PackageRegistry|Delete Package File"
msgstr "删除软件包文件"
@@ -27393,6 +27608,9 @@ msgstr "删除软件包版本"
msgid "PackageRegistry|Delete package"
msgstr "删除软件包"
+msgid "PackageRegistry|Delete selected"
+msgstr "删除选中"
+
msgid "PackageRegistry|Delete this package"
msgstr "删除此软件包"
@@ -27402,6 +27620,9 @@ msgstr "é‡å¤çš„软件包"
msgid "PackageRegistry|Error publishing"
msgstr "å‘布错误"
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr "åŒ…å« .pom å’Œ .jar 文件的 assets 的示例"
+
msgid "PackageRegistry|Failed to load the package data"
msgstr "加载软件包数æ®å¤±è´¥"
@@ -27459,6 +27680,9 @@ msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软ä»
msgid "PackageRegistry|License information located at %{link}"
msgstr "许å¯è¯ä¿¡æ¯ä½äºŽ%{link}"
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr "管ç†è½¯ä»¶åŒ… assets 使用的存储"
+
msgid "PackageRegistry|Manually Published"
msgstr "手动å‘布"
@@ -27477,9 +27701,15 @@ msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
msgstr "NuGet命令"
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "è¦ä¿ç•™çš„é‡å¤ assets æ•°é‡"
+
msgid "PackageRegistry|Package Registry"
msgstr "软件包注册表"
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…"
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr "Pip命令"
@@ -27550,6 +27783,9 @@ msgstr "显示 PyPi 命令"
msgid "PackageRegistry|Show Yarn commands"
msgstr "显示 Yarn 命令"
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr "删除包文件时出错。"
@@ -27601,18 +27837,28 @@ 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 "您将è¦åˆ é™¤ %{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 1 asset. This operation is irreversible."
+msgid_plural "PackageRegistry|You are about to delete %d assets. This operation is irreversible."
+msgstr[0] ""
+
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
msgstr "å³å°†åˆ é™¤%{name}çš„%{version}版本。确定继续å—?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "您å¯èƒ½è¿˜éœ€è¦ä½¿ç”¨ä»¤ç‰Œè®¾ç½®èº«ä»½éªŒè¯ã€‚%{linkStart}请å‚阅文档%{linkEnd}以了解更多信æ¯ã€‚"
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr ""
+
msgid "PackageRegistry|npm"
msgstr "npm"
@@ -27752,16 +27998,16 @@ msgid "Passwords should be unique and not used for any other sites or services."
msgstr "密ç åº”唯一并未用于任何其他网站或æœåŠ¡ã€‚"
msgid "Password|requires at least one lowercase letter"
-msgstr "至少需è¦ä¸€ä¸ªå°å†™å­—æ¯"
+msgstr "需包å«è‡³å°‘一个å°å†™å­—æ¯"
msgid "Password|requires at least one number"
-msgstr "至少需è¦ä¸€ä¸ªæ•°å­—"
+msgstr "需包å«è‡³å°‘一个数字"
msgid "Password|requires at least one symbol character"
-msgstr "需è¦è‡³å°‘一个符å·å­—符"
+msgstr "需包å«è‡³å°‘一个符å·"
msgid "Password|requires at least one uppercase letter"
-msgstr "需è¦è‡³å°‘一个大写字æ¯"
+msgstr "需包å«è‡³å°‘一个大写字æ¯"
msgid "Past due"
msgstr "逾期"
@@ -27868,6 +28114,9 @@ msgstr "执行代ç å®¡æŸ¥å¹¶é€šè¿‡åˆå¹¶è¯·æ±‚增强å作。"
msgid "Perform common operations on GitLab project"
msgstr "在GitLab项目上执行常è§æ“作"
+msgid "Performance insights"
+msgstr "性能洞察"
+
msgid "Performance optimization"
msgstr "性能优化"
@@ -27973,6 +28222,18 @@ 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 "一些功能,包括å‡çº§åˆ°ä»˜è´¹ç‰ˆæˆ–开始å…费试用的能力,仅适用于群组和群组内的项目。%{projectName} 是个人项目,所以这些功能都ä¸å¯ç”¨ã€‚我们建议您将您的项目转移到一个群组中,释放æžç‹GitLab 的全部潜力。"
+
+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 "您的项目 %{projectName} ä¸åœ¨ç¾¤ç»„中"
+
msgid "Phabricator Server Import"
msgstr "PhabricatoræœåŠ¡å™¨å¯¼å…¥"
@@ -28129,6 +28390,9 @@ 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 "编辑选项å¡ä¸­çš„当å‰å†…容将用于模拟。"
@@ -28147,6 +28411,15 @@ msgstr "将模拟æµæ°´çº¿è¡Œä¸ºï¼ŒåŒ…括 %{codeStart}rules%{codeEnd}ã€%{codeSt
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 "将模拟æµæ°´çº¿è¡Œä¸ºï¼ŒåŒ…括 %{codeStart}rules%{codeEnd}ã€%{codeStart}only%{codeEnd}ã€%{codeStart}except%{codeEnd} å’Œ %{codeStart}needs%{codeEnd} 作业ä¾èµ–项。%{linkStart}了解更多%{linkEnd}"
+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 "模拟了一个默认分支的 %{codeStart}git 推é€%{codeEnd}事件。%{codeStart}Rules%{codeEnd}ã€%{codeStart}only%{codeEnd}ã€%{codeStart}except%{codeEnd} å’Œ %{codeStart}needs%{codeEnd} 作业ä¾èµ–逻辑已评估。%{linkStart}了解更多%{linkEnd}"
+
+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 "æŒç»­éªŒè¯ CI/CD é…置。当 CI/CD é…置文件ä¸ä¸ºç©ºæ—¶ï¼Œä¼šæ˜¾ç¤ºé”™è¯¯å’Œè­¦å‘Šã€‚"
@@ -28168,6 +28441,12 @@ 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 "等待 CI 内容加载..."
+
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
msgstr "自定义(%{linkStart}Cron 语法%{linkEnd})"
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr "为此æµæ°´çº¿æ供简短æè¿°"
@@ -28201,6 +28483,9 @@ msgstr "目标"
msgid "PipelineSchedules|Variables"
msgstr "å˜é‡"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr "å–得所有æƒä»¥è¿›è¡Œç¼–辑"
+
msgid "PipelineSource|API"
msgstr "API"
@@ -28447,6 +28732,9 @@ msgstr "所有者"
msgid "Pipelines|Pipeline Editor"
msgstr "æµæ°´çº¿ç¼–辑器"
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "æµæ°´çº¿è¯­æ³•æ˜¯æ­£ç¡®çš„。"
+
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
@@ -28615,9 +28903,18 @@ msgstr "游离的åˆå¹¶è¯·æ±‚æµæ°´çº¿"
msgid "Pipeline|Failed"
msgstr "失败"
+msgid "Pipeline|Five slowest jobs"
+msgstr "五个最慢的作业"
+
msgid "Pipeline|In progress"
msgstr "进行中"
+msgid "Pipeline|Last executed job"
+msgstr "上次执行的作业"
+
+msgid "Pipeline|Longest queued job"
+msgstr "排队最长的作业"
+
msgid "Pipeline|Manual"
msgstr "手动"
@@ -28630,12 +28927,18 @@ msgstr "åˆå¹¶é˜Ÿåˆ—æµæ°´çº¿ä½œä¸šæ— æ³•é‡è¯•"
msgid "Pipeline|Merged result pipeline"
msgstr "åˆå¹¶ç»“æžœæµæ°´çº¿"
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "åªèƒ½æ˜¾ç¤ºå‰ 100 个结果"
+
msgid "Pipeline|Passed"
msgstr "已通过"
msgid "Pipeline|Pending"
msgstr "等待中"
+msgid "Pipeline|Performance insights"
+msgstr "性能洞察"
+
msgid "Pipeline|Pipeline"
msgstr "æµæ°´çº¿"
@@ -28654,6 +28957,9 @@ msgstr "ç›®å‰ä¸æ”¯æŒåŽŸå§‹æ–‡æœ¬æœç´¢ã€‚请使用å¯ç”¨çš„æœç´¢ä»¤ç‰Œã€‚"
msgid "Pipeline|Run for branch name or tag"
msgstr "为分支å称或标签è¿è¡Œ"
+msgid "Pipeline|Run merge request pipeline"
+msgstr "è¿è¡Œåˆå¹¶è¯·æ±‚æµæ°´çº¿"
+
msgid "Pipeline|Run pipeline"
msgstr "è¿è¡Œæµæ°´çº¿"
@@ -28690,6 +28996,12 @@ msgstr "标签å称"
msgid "Pipeline|Test coverage"
msgstr "测试覆盖率"
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "最åŽæ‰§è¡Œçš„作业是在æµæ°´çº¿ä¸­å¯åŠ¨çš„最åŽä¸€ä¸ªä½œä¸šã€‚"
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "排队时间最长的作业是在 pending 状æ€ä¸­ç­‰å¾…时间最长的作业,等待被一个 Runner 选中"
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr "如果åˆå¹¶ï¼Œæ­¤æ›´æ”¹å°†é™ä½Žæ•´ä½“测试覆盖率。"
@@ -28705,6 +29017,9 @@ 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 "è¦è¿è¡Œåˆå¹¶è¯·æ±‚æµæ°´çº¿ï¼ŒCI/CD é…置文件中的作业%{linkStart}å¿…é¡»é…置为%{linkEnd}在åˆå¹¶è¯·æ±‚æµæ°´çº¿ä¸­è¿è¡Œã€‚"
+
msgid "Pipeline|Trigger author"
msgstr "触å‘者"
@@ -28717,6 +29032,9 @@ msgstr "å˜é‡"
msgid "Pipeline|View commit"
msgstr "查看æ交"
+msgid "Pipeline|View dependency"
+msgstr "查看ä¾èµ–"
+
msgid "Pipeline|View pipeline"
msgstr "查看æµæ°´çº¿"
@@ -28816,6 +29134,9 @@ 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 "请检查您的电å­é‚®ä»¶(%{email})以确认您拥有此电å­é‚®ç®±å¹¶è§£é”CI/CD的强大功能。还没收到邮件? %{resend_link}。或是电å­é‚®ä»¶åœ°å€é”™è¯¯ï¼Ÿ%{update_link}。"
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr "请在继续之å‰å•å‡»ç¡®è®¤ç”µå­é‚®ä»¶ä¸­çš„链接。它被å‘é€åˆ° "
+
msgid "Please complete your profile with email address"
msgstr "请在您的个人资料中填写电å­é‚®ä»¶åœ°å€"
@@ -28918,6 +29239,9 @@ 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 "请查看此项目的%{linkStart}贡献指å—%{linkEnd}。"
+
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 "请审核 %{project_link} çš„æ›´æ–°å‡çº§ç­–略。建议您è”系当å‰çš„ on-call å“åº”è€…ï¼Œä»¥ç¡®ä¿ on-call 覆盖的连续性。"
@@ -29164,7 +29488,7 @@ msgstr "上一页"
msgid "Prevent auto-stopping"
msgstr "防止自动åœæ­¢"
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr "ç¦æ­¢åœ¨é¡¹ç›®å’Œåˆå¹¶è¯·æ±‚中编辑批准规则。"
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 "当项目转移到群组åŽï¼Œå…¶å¯è§æ€§çº§åˆ«å°†æ›´æ”¹ä¸ºä¸Žå‘½å空间规则匹é…。"
@@ -29887,6 +30214,12 @@ msgstr "未找到项目或者您没有æƒé™å°†æ­¤é¡¹ç›®æ·»åŠ åˆ°å®‰å…¨ä»ªè¡¨ç›˜
msgid "Project: %{name}"
msgstr "项目: %{name}"
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr "项目:分支:%{source_project_path}:%{source_branch} 到 %{target_project_path}:%{target_branch}"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr "项目:分支:%{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "订阅"
@@ -29965,6 +30298,9 @@ 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 "最新æµæ°´çº¿ç»“æžœ"
@@ -29977,6 +30313,9 @@ 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 "查看完整报告"
@@ -30004,6 +30343,9 @@ 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 "或群组"
@@ -31192,18 +31534,36 @@ msgstr "默认"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr "%{environment_name} 将对开å‘人员å¯å†™ã€‚确定继续å—?"
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr "指定了以下部署级别的所有环境å‡å—父组ä¿æŠ¤ã€‚%{link_start}了解更多%{link_end}。"
+
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…许部署"
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr "å…许部署到 %{project}/%{environment}"
+
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 projected."
+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 "ä¿æŠ¤"
@@ -31330,6 +31690,12 @@ 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 "Pumaè¿è¡Œçš„线程数大于1,并且å¯ç”¨äº†RuggedæœåŠ¡ã€‚在æŸäº›çŽ¯å¢ƒä¸­ï¼Œè¿™å¯èƒ½ä¼šå¯¼è‡´æ€§èƒ½é™ä½Žã€‚有关此问题的详细信æ¯ï¼Œè¯·å‚è§æˆ‘们的%{link_start}文档%{link_end}。"
+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 "购买更多时间"
@@ -31600,12 +31966,6 @@ msgstr "没有æµæ°´çº¿çš„å˜åŸº"
msgid "Recaptcha verified?"
msgstr "é‡æ–°éªŒè¯ï¼Ÿ"
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr "收到一张 50 美元的礼å“å¡ä½œä¸ºå¯¹æ‚¨æ—¶é—´çš„感谢。"
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr "收到一张 %{strongOpen}美元 50 美元的礼å“å¡%{strongClose} 作为对您时间的感谢。"
-
msgid "Receive any notifications from GitLab."
msgstr "接收æ¥è‡ª GitLab 的任何通知。"
@@ -31639,6 +31999,9 @@ msgstr "最近使用"
msgid "Reconfigure"
msgstr "é‡æ–°é…ç½®"
+msgid "Recover password"
+msgstr "æ¢å¤å¯†ç "
+
msgid "Recovery Codes"
msgstr "æ¢å¤ç "
@@ -31808,9 +32171,6 @@ msgstr "å…³è”到 %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
msgstr "相关的功能标志"
-msgid "Related incidents or issues"
-msgstr "相关的事件或议题"
-
msgid "Related issues"
msgstr "相关议题"
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] "å‘è¡Œ"
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "å‘布 %{deletedRelease} å·²æˆåŠŸåˆ é™¤ã€‚"
+
msgid "Release assets"
msgstr "å‘布资æº"
@@ -31896,6 +32259,9 @@ 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 "获å–å‘布详情时出现问题。"
@@ -31959,12 +32325,6 @@ msgstr "删除资æºé“¾æŽ¥"
msgid "Remove assignee"
msgstr "删除指派人"
-msgid "Remove attention request"
-msgstr "删除关注请求"
-
-msgid "Remove attention request(s)"
-msgstr "删除关注请求"
-
msgid "Remove avatar"
msgstr "删除头åƒ"
@@ -32106,12 +32466,6 @@ msgstr "已删除所有标签。"
msgid "Removed an issue from an epic."
msgstr "从å²è¯—中移除了一个议题。"
-msgid "Removed attention from %{users_sentence}."
-msgstr "已从 %{users_sentence} 删除关注。"
-
-msgid "Removed attention request from @%{username}"
-msgstr "已从 @%{username} 移除关注请求"
-
msgid "Removed group can not be restored!"
msgstr "已删除的群组无法æ¢å¤ï¼"
@@ -32160,9 +32514,6 @@ msgstr "删除所有标记。"
msgid "Removes an issue from an epic."
msgstr "从å²è¯—中移除一个议题。"
-msgid "Removes attention from %{users_sentence}."
-msgstr "从 %{users_sentence} 删除关注。"
-
msgid "Removes parent epic %{epic_ref}."
msgstr "删除父å²è¯—%{epic_ref}。"
@@ -32271,6 +32622,9 @@ msgstr "直接回å¤æ­¤é‚®ä»¶æˆ– %{view_it_on_gitlab}。"
msgid "Reply…"
msgstr "回å¤â€¦"
+msgid "Report Finding not found"
+msgstr "未找到报告结果"
+
msgid "Report abuse"
msgstr "报告滥用"
@@ -32283,6 +32637,9 @@ 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 "报告您的许å¯è¯ä½¿ç”¨æ•°æ®"
@@ -32435,6 +32792,9 @@ msgstr "æ¼æ´ž"
msgid "Reports|Vulnerability Name"
msgstr "æ¼æ´žå称"
+msgid "Reports|metrics report"
+msgstr "指标报告"
+
msgid "Reports|no changed test results"
msgstr "未å‘生å˜åŒ–的测试结果"
@@ -32549,7 +32909,7 @@ msgid "Repository already read-only"
msgstr "存储库已ç»æ˜¯åªè¯»"
msgid "Repository by URL"
-msgstr "使用 URL 定ä½ä»“库"
+msgstr "仓库(URL)"
msgid "Repository check"
msgstr "仓库检查"
@@ -32626,15 +32986,6 @@ msgstr "申请æƒé™"
msgid "Request a new one"
msgstr "请求一个新的"
-msgid "Request attention from %{users_sentence}."
-msgstr "æ¥è‡ª %{users_sentence} 的请求关注"
-
-msgid "Request attention from assignee or reviewer"
-msgstr "æ¥è‡ªæŒ‡æ´¾äººæˆ–审核者的请求关注"
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr "æ¥è‡ªæŒ‡æ´¾äººæˆ–审核者的请求关注"
-
msgid "Request data is too large"
msgstr "请求数æ®è¿‡å¤§"
@@ -32659,24 +33010,12 @@ msgstr "已请求"
msgid "Requested %{time_ago}"
msgstr "请求的 %{time_ago}"
-msgid "Requested attention from %{users_sentence}."
-msgstr "已从 %{users_sentence} 请求关注。"
-
-msgid "Requested attention from @%{username}"
-msgstr "请求æ¥è‡ª @%{username} 的注æ„事项"
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr "已请求@%{username}的关注。您自己的关注请求已被删除。"
-
msgid "Requested design version does not exist."
msgstr "请求的设计版本ä¸å­˜åœ¨."
msgid "Requested review"
msgstr "请求审核"
-msgid "Requested review. Your attention request was removed."
-msgstr "已请求审核。您的关注请求已被删除。"
-
msgid "Requested states are invalid"
msgstr "请求的状æ€æ— æ•ˆ"
@@ -32751,6 +33090,9 @@ msgstr "é‡æ–°å‘é€"
msgid "Resend Request"
msgstr "é‡æ–°å‘é€è¯·æ±‚"
+msgid "Resend confirmation e-mail"
+msgstr "é‡æ–°å‘é€ç¡®è®¤é‚®ä»¶"
+
msgid "Resend confirmation email"
msgstr "é‡æ–°å‘é€ç¡®è®¤é‚®ä»¶"
@@ -32767,7 +33109,7 @@ msgid "Reset"
msgstr "é‡ç½®"
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "é‡ç½®é”™è¯¯è·Ÿè¸ªè®¿é—®ä»¤ç‰Œ"
msgid "Reset file"
msgstr "é‡ç½®æ–‡ä»¶"
@@ -32895,12 +33237,12 @@ msgstr "检索åˆè§„性报告失败。请刷新页é¢å¹¶é‡è¯•ã€‚"
msgid "Retry"
msgstr "é‡è¯•"
+msgid "Retry all failed or cancelled jobs"
+msgstr "é‡è¯•æ‰€æœ‰å¤±è´¥æˆ–å–消的作业"
+
msgid "Retry downstream pipeline"
msgstr "é‡è¯•ä¸‹æ¸¸æµæ°´çº¿"
-msgid "Retry failed jobs"
-msgstr "é‡è¯•å¤±è´¥çš„作业"
-
msgid "Retry job"
msgstr "é‡è¯•ä½œä¸š"
@@ -32999,12 +33341,6 @@ msgstr "å¤åˆ¶ç”µå­é‚®ä»¶åœ°å€"
msgid "RightSidebar|Issue email"
msgstr "邮件地å€"
-msgid "RightSidebar|adding a"
-msgstr "添加"
-
-msgid "RightSidebar|deleting the"
-msgstr "删除"
-
msgid "Roadmap"
msgstr "路线图"
@@ -33080,6 +33416,10 @@ msgstr "Runner用于接收和执行GitLab的CI/CD作业的进程。"
msgid "Runners page."
msgstr "Runner页é¢."
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr "%{percentage} 点。"
@@ -33133,6 +33473,9 @@ msgstr "分é…项目 (%{projectCount})"
msgid "Runners|Associated with one or more projects"
msgstr "与一个或多个项目关è”"
+msgid "Runners|Available"
+msgstr "å¯ç”¨"
+
msgid "Runners|Available to all projects"
msgstr "适用于所有项目"
@@ -33296,6 +33639,9 @@ msgstr "在线 Runners"
msgid "Runners|Online:"
msgstr "在线:"
+msgid "Runners|Outdated"
+msgstr "已过期"
+
msgid "Runners|Pause from accepting jobs"
msgstr "æš‚åœæŽ¥å—作业"
@@ -33318,6 +33664,9 @@ msgstr "属性å称"
msgid "Runners|Protected"
msgstr "å—ä¿æŠ¤"
+msgid "Runners|Recommended"
+msgstr "推è"
+
msgid "Runners|Register a group runner"
msgstr "注册一个群组runner"
@@ -33426,6 +33775,9 @@ msgstr "显示runner安装和注册说明"
msgid "Runners|Show runner installation instructions"
msgstr "显示 Runner 安装说明"
+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 "获å–Runneræ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -33484,9 +33836,18 @@ msgstr "è¦åœ¨ Kubernetes 中安装Runner,请éµå¾ª GitLab 文档中æè¿°çš„è
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
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|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 "å‡çº§ GitLab Runner 以匹é…您正在è¿è¡Œçš„ GitLab 版本。%{linkStart}大版本和å°ç‰ˆæœ¬%{linkEnd} 都应该匹é…。"
+msgid "Runners|Upgrade Status"
+msgstr "å‡çº§çŠ¶æ€"
+
msgid "Runners|Upgrade available"
msgstr "有å‡çº§å¯ç”¨"
@@ -33532,6 +33893,9 @@ msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶
msgid "Runners|active"
msgstr "å¯ç”¨"
+msgid "Runners|available"
+msgstr "å¯ç”¨"
+
msgid "Runners|group"
msgstr "群组"
@@ -33547,6 +33911,9 @@ msgstr "在线"
msgid "Runners|paused"
msgstr "已暂åœ"
+msgid "Runners|recommended"
+msgstr "推è"
+
msgid "Runners|shared"
msgstr "共享"
@@ -33562,6 +33929,9 @@ msgstr "å‡çº§å¯ç”¨"
msgid "Runners|upgrade recommended"
msgstr "推èå‡çº§"
+msgid "Runner|Owner"
+msgstr "所有者"
+
msgid "Running"
msgstr "è¿è¡Œä¸­"
@@ -33604,6 +33974,9 @@ msgstr "SASTé…ç½®"
msgid "SHA256"
msgstr "SHA256"
+msgid "SSH Fingerprints"
+msgstr "SSH 指纹"
+
msgid "SSH Key"
msgstr "SSH密钥"
@@ -33613,6 +33986,9 @@ msgstr "SSH密钥"
msgid "SSH Keys Help"
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 "SSH 指纹验è¯å®¢æˆ·ç«¯æ˜¯å¦è¿žæŽ¥åˆ°æ­£ç¡®çš„主机。检查%{config_link_start}当å‰å®žä¾‹é…ç½®%{config_link_end}。"
+
msgid "SSH host key fingerprints"
msgstr "SSH主机密钥指纹"
@@ -33691,6 +34067,21 @@ msgstr "ä¿å­˜ä¸­"
msgid "Saving project."
msgstr "正在ä¿å­˜é¡¹ç›®ã€‚"
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr "æµæ°´çº¿è¿è¡Œä¸­"
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr "计划"
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr "计划规则组件"
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr "选择分支"
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{scanners} 在针对 %{branches} 的开放åˆå¹¶è¯·æ±‚中å‘现超过 %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} çš„æ¼æ´ž"
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] "wiki结果"
+msgid "SearchToken|Assignee"
+msgstr "指派人"
+
+msgid "SearchToken|Reviewer"
+msgstr "审核者"
+
msgid "Searching by both author and message is currently not supported."
msgstr "ç›®å‰ä¸æ”¯æŒä½œè€…和消æ¯åŒæ—¶æœç´¢ã€‚"
@@ -34059,6 +34456,9 @@ msgstr "安全é…ç½®"
msgid "Security Dashboard"
msgstr "安全仪表盘"
+msgid "Security Finding not found"
+msgstr "未找到安全å‘现结果"
+
msgid "Security dashboard"
msgstr "安全仪表盘"
@@ -34332,6 +34732,12 @@ msgstr "强制此项目的安全性。 %{linkStart}更多信æ¯ã€‚%{linkEnd}"
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 "如果任何扫æ器在针对主分支的开放åˆå¹¶è¯·æ±‚中å‘现新检测的严é‡æ¼æ´žï¼Œç„¶åŽéœ€è¦ä»»ä½• App security æˆå‘˜çš„两次批准。"
@@ -34497,6 +34903,9 @@ msgstr "此开å‘项目中ä¸å­˜åœ¨ä»¥ä¸‹åˆ†æ”¯ï¼š%{branches}。在更新此策ç
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr "创建新的安全策略时出现问题"
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "æ­¤ %{namespaceType} ä¸åŒ…å«ä»»ä½•å®‰å…¨ç­–略。"
+
msgid "SecurityOrchestration|This group"
msgstr "此群组"
@@ -34515,9 +34924,6 @@ msgstr "此策略是从 %{linkStart}命å空间%{linkEnd} 继承的,必须在
msgid "SecurityOrchestration|This project"
msgstr "此项目"
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 "æ­¤è§†å›¾ä»…æ˜¾ç¤ºä»£ç† %{agent} 的扫æ结果。您å¯ä»¥åœ¨%{linkStart}æ¼æ´žæŠ¥å‘Šçš„è¿è¥æ¼æ´žé€‰é¡¹å¡ä¸­%{linkEnd}查看所有代ç†çš„扫æ结果。"
@@ -34674,6 +35080,9 @@ msgstr "无法获å–安全报告信æ¯ã€‚请é‡æ–°åŠ è½½é¡µé¢æˆ–ç¨åŽå†è¯•ã€‚
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
+msgid "SecurityReports|Image"
+msgstr "é•œåƒ"
+
msgid "SecurityReports|Issue Created"
msgstr "已创建议题"
@@ -34728,6 +35137,15 @@ 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 "项目"
@@ -35082,9 +35500,6 @@ msgstr "已选中一些项目。"
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "éžç®¡ç†å‘˜ç”¨æˆ·æ— æ³•ä¸ºç¾¤ç»„ã€é¡¹ç›®æˆ–代ç ç‰‡æ®µä½¿ç”¨æ‰€é€‰çº§åˆ«ã€‚如果公共级别å—到é™åˆ¶ï¼Œåˆ™ç”¨æˆ·é…置文件仅对登录用户å¯è§ã€‚"
-msgid "Selected projects"
-msgstr "选定项目"
-
msgid "Selected tag is already in use. Choose another option."
msgstr "所选标签已在使用中。选择å¦ä¸€ä¸ªé€‰é¡¹ã€‚"
@@ -35268,9 +35683,6 @@ msgstr "å¼€å¯æœåŠ¡ ping"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr "打开æœåŠ¡ping以查看实例级分æžã€‚"
-msgid "Services"
-msgstr "æœåŠ¡"
-
msgid "Session ID"
msgstr "ä¼šè¯ ID"
@@ -35286,9 +35698,6 @@ msgstr "设置用于新议题的默认æ述模æ¿ã€‚ %{link_start}什么是æè
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "为账å·åˆ›å»ºä¸€ä¸ªç”¨äºŽæŽ¨é€æˆ–拉å–çš„ %{protocol} 密ç ã€‚"
-msgid "Set access permissions for this token."
-msgstr "设置此令牌的访问æƒé™ã€‚"
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr "将任何速率é™åˆ¶è®¾ç½®ä¸º %{code_open}0%{code_close} 以ç¦ç”¨è¯¥é™åˆ¶ã€‚"
@@ -35771,8 +36180,8 @@ msgstr "显示最新版本"
msgid "Showing version #%{versionNumber}"
msgstr "显示版本#%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr "为群组 “%{group_name}†显示从 2019 年 11 月 1 日到 2019 年 12 月 31 日的议题和 %{labels_count} 个标记"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgstr "显示群组 “%{group_name}†从 2019 年 11 月 1 日到 2019 年 12 月 31 日的议题"
msgid "Side-by-side"
msgstr "并排"
@@ -35858,6 +36267,9 @@ msgstr "登录和帮助页é¢"
msgid "Sign-in count:"
msgstr "登录次数"
+msgid "Sign-in failed because %{error}."
+msgstr "登录失败,因为 %{error}。"
+
msgid "Sign-in page"
msgstr "登录页é¢"
@@ -35867,6 +36279,9 @@ msgstr "登录é™åˆ¶"
msgid "Sign-in text"
msgstr "登录文本"
+msgid "Sign-in using %{provider} auth failed"
+msgstr "使用 %{provider} 认è¯ç™»å½•å¤±è´¥"
+
msgid "Sign-out page URL"
msgstr "退出页é¢URL"
@@ -36101,9 +36516,6 @@ msgstr "实心"
msgid "Solution"
msgstr "解决方案"
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr "æŸäº›æ“作会移除关注请求,例如审核者批准或åˆå¹¶åˆå¹¶è¯·æ±‚的任何人。"
-
msgid "Some changes are not shown"
msgstr "一些å˜åŒ–未显示"
@@ -37220,9 +37632,6 @@ msgstr "å‡åŽ»"
msgid "Succeeded"
msgstr "å·²æˆåŠŸ"
-msgid "Successful purchase image"
-msgstr "æˆåŠŸè´­ä¹°å›¾ç‰‡"
-
msgid "Successfully activated"
msgstr "å·²æˆåŠŸæ¿€æ´»"
@@ -37566,9 +37975,6 @@ msgstr "对自定义è¯ä¹¦çš„支æŒå·²ç¦ç”¨ã€‚请è”系系统管ç†å‘˜æ¥å¯ç”¨
msgid "Support page URL"
msgstr "支æŒé¡µé¢ç½‘å€"
-msgid "Survey Response"
-msgstr "é—®å·è°ƒæŸ¥ç­”å¤"
-
msgid "Surveys|Delighted"
msgstr "高兴"
@@ -37671,6 +38077,9 @@ msgstr "系统指标(Kubernetes)"
msgid "System output"
msgstr "系统输出"
+msgid "System started"
+msgstr "系统已å¯åŠ¨"
+
msgid "Table of Contents"
msgstr "目录"
@@ -37743,6 +38152,9 @@ msgstr "å–消"
msgid "TagsPage|Cancel, keep tag"
msgstr "å–消,ä¿ç•™æ ‡ç­¾"
+msgid "TagsPage|Create release"
+msgstr "创建å‘布"
+
msgid "TagsPage|Create tag"
msgstr "创建标签"
@@ -37761,8 +38173,8 @@ msgstr "删除标签。您ç»å¯¹ç¡®å®šå—?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr "删除 %{strongStart}%{tagName}%{strongEnd} 标记无法撤消。您确定å—?"
-msgid "TagsPage|Edit release notes"
-msgstr "编辑å‘行说明"
+msgid "TagsPage|Edit release"
+msgstr "编辑å‘布"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
msgstr "已存在分支å称,标记或æ交SHA"
@@ -37860,9 +38272,6 @@ msgstr "任务ID: %{elastic_task}"
msgid "Task list"
msgstr "任务列表"
-msgid "Task with ID: %{id} could not be found."
-msgstr "无法找到 ID 为 %{id} 的任务。"
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr "创建/导入代ç åˆ°é¡¹ç›®ï¼ˆä»“库)"
@@ -38265,9 +38674,6 @@ msgstr "文本样å¼"
msgid "Thank you for your business."
msgstr "感谢您的购买。"
-msgid "Thank you for your feedback!"
-msgstr "感谢您的å馈ï¼"
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr "感谢您的报告。 GitLab管ç†å‘˜å°†å°½å¿«è¿›è¡Œè°ƒæŸ¥ã€‚"
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr "æ­¤åˆå¹¶è¯·æ±‚的最新æµæ°´çº¿æœªæˆåŠŸå®Œæˆã€‚"
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr "æ­¤åˆå¹¶è¯·æ±‚的最新æµæ°´çº¿æœªæˆåŠŸã€‚最新更改未ç»éªŒè¯ã€‚"
@@ -38715,6 +39118,9 @@ msgstr "仓库必须能够通过%{code_open}http://%{code_close},%{code_open}h
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 "仓库必须能够通过%{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close}或%{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 "您è¦è®¿é—®çš„资æºä¸å­˜åœ¨æˆ–您没有执行此æ“作的æƒé™ã€‚"
+
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 "åŒä¸€ä¸ªå…±äº«runnerå¯æ‰§è¡Œå¤šä¸ªé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨é…置了自动伸缩,将%{link}设置为1 (GitLab.com 上的设置)。"
@@ -38829,6 +39235,9 @@ msgstr "没有已归档的需求"
msgid "There are no archived test cases"
msgstr "没有存档的测试用例"
+msgid "There are no changed labels"
+msgstr "没有更改的标记"
+
msgid "There are no changes"
msgstr "没有å˜åŒ–"
@@ -38901,6 +39310,9 @@ msgstr "为了ä¿æŠ¤è¯¥ç³»ç»Ÿï¼Œå®žè¡Œäº†å‡ ç§é€ŸçŽ‡é™åˆ¶ã€‚"
msgid "There are several size limits in place."
msgstr "有几个大å°é™åˆ¶ã€‚"
+msgid "There are unsubmitted review comments."
+msgstr "有未æ交的审核评论。"
+
msgid "There is already a repository with that name on disk"
msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
@@ -39003,9 +39415,6 @@ msgstr "å‘é€ç¡®è®¤é‚®ä»¶æ—¶å‡ºçŽ°é—®é¢˜"
msgid "There was a problem updating the keep latest artifacts setting."
msgstr "æ›´æ–°ä¿æŒæœ€æ–°äº§ç‰©è®¾ç½®æ—¶å‡ºçŽ°é—®é¢˜ã€‚"
-msgid "There was an error %{message} to-do item."
-msgstr "待办事项å‘生错误%{message}"
-
msgid "There was an error adding a To Do."
msgstr "添加待办事项时出现错误"
@@ -39084,9 +39493,6 @@ msgstr "解æžæ­¤å›¾è¡¨çš„æ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "There was an error removing the e-mail."
msgstr "删除电å­é‚®ä»¶æ—¶å‡ºé”™ã€‚"
-msgid "There was an error resetting group pipeline minutes."
-msgstr "é‡ç½®ç¾¤ç»„æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
-
msgid "There was an error resetting user pipeline minutes."
msgstr "é‡ç½®ç”¨æˆ·æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
@@ -39138,9 +39544,6 @@ msgstr "获å–值æµåˆ†æžæ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "There was an error while fetching value stream analytics duration data."
msgstr "获å–价值æµåˆ†æžæŒç»­æ—¶é—´æ—¶å‡ºé”™ã€‚"
-msgid "There was an error while fetching value stream summary data."
-msgstr "获å–价值æµæ±‡æ€»æ•°æ®æ—¶å‡ºé”™ã€‚"
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA 验è¯é”™è¯¯ã€‚请å†æ¬¡éªŒè¯ reCAPTCHA。"
@@ -39321,6 +39724,9 @@ 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 "此电å­é‚®ä»¶å–代了以å‰ä»»ä½•æ‚¨å¯èƒ½å·²ç»æ”¶åˆ°çš„ %{project_link} 计划删除的电å­é‚®ä»¶ã€‚"
@@ -39678,6 +40084,12 @@ msgstr "此项目将于 %{date} 删除,因为它的父组 '%{parent_group_name
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
msgstr "该项目将存在于您的群组%{strong_open}%{namespace}%{strong_close}中。在项目中,您å¯ä»¥å­˜æ”¾æ–‡ä»¶(仓库),计划工作(议题),å‘布文档(Wiki)等等。"
+msgid "This release was created with a date in the past. Evidence collection at the moment of the release is unavailable."
+msgstr "æ­¤å‘布是使用过去的日期创建的,当时 Evidence 收集功能ä¸å¯ç”¨ã€‚"
+
+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 "当å‰ä»“库"
@@ -39990,6 +40402,9 @@ 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 "超时"
@@ -40070,9 +40485,6 @@ msgstr "è¦æ·»åŠ è‡ªå®šä¹‰åŽç¼€ï¼Œè¯·è®¾ç½®æœåŠ¡å°ç”µå­é‚®ä»¶åœ°å€ã€‚%{link
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr "如需手动添加æ¡ç›®ï¼Œè¯·åœ¨æ‰‹æœºåº”用中æ供以下信æ¯ã€‚"
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr "è¦è®©æŸäººæŸ¥çœ‹åˆå¹¶è¯·æ±‚,请选择 %{strongStart}请求关注%{strongEnd}。å†æ¬¡é€‰æ‹©ä»¥ç§»é™¤è¯·æ±‚。"
-
msgid "To complete registration, we need additional details from you."
msgstr "è¦å®Œæˆæ³¨å†Œï¼Œæˆ‘们需è¦æ‚¨æ供更多信æ¯ã€‚"
@@ -40148,8 +40560,8 @@ msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„进行,请创建一个新的åˆå¹¶è¯·æ±‚"
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr "è¦äº†è§£æ›´å¤šå…³äºŽæ­¤é¡¹ç›®çš„ä¿¡æ¯ï¼Œè¯·é˜…读 %{link_to_wiki}"
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
-msgstr "è¦ç®¡ç†ä¸Žæ­¤ç»„åŠå…¶å­ç»„和项目相关的所有æˆå‘˜ï¼Œè¯·è®¿é—® %{link_start}使用é…é¢é¡µé¢%{link_end}。"
+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 "è¦ç®¡ç†ä¸Žè¯¥ç¾¤ç»„åŠå…¶å­ç»„和项目关è”的所有æˆå‘˜çš„席ä½ï¼Œè¯·è®¿é—®%{link_start}使用é…é¢é¡µé¢%{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 "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°æ­¤æœåŠ¡å™¨ï¼Œè¯·è®¿é—®åŽŸé¡¹ç›®çš„设置页é¢ï¼Œç”Ÿæˆå¯¼å‡ºæ–‡ä»¶ï¼Œç„¶åŽåœ¨æ­¤å¤„上载。"
@@ -40305,7 +40717,7 @@ msgid "Toggle commit description"
msgstr "开关æ交æè¿°"
msgid "Toggle commit list"
-msgstr "开关æ交列表"
+msgstr "展开或éšè—æ交列表"
msgid "Toggle dropdown"
msgstr "切æ¢ä¸‹æ‹‰åˆ—表"
@@ -40382,6 +40794,9 @@ msgstr "找到了太多用户。快速æ“作仅é™äºŽæœ€å¤š %{max_count} 个用æ
msgid "TopNav|Go back"
msgstr "返回"
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr "主题 %{source_topic} å·²æˆåŠŸåˆå¹¶åˆ°ä¸»é¢˜ %{target_topic} 中。"
+
msgid "Topic %{topic_name} was successfully created."
msgstr "主题 %{topic_name} å·²æˆåŠŸåˆ›å»ºã€‚"
@@ -40688,6 +41103,9 @@ 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 "试用 GitLab æµæ°´çº¿"
@@ -40772,6 +41190,9 @@ msgstr "åŒå› ç´ å®½é™æœŸ"
msgid "Type"
msgstr "类型"
+msgid "Type to search"
+msgstr "输入è¦æœç´¢çš„内容"
+
msgid "U2F Devices (%{length})"
msgstr "U2F设备(%{length})"
@@ -40892,6 +41313,9 @@ msgstr "无法加载差异。 %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "无法加载åˆå¹¶è¯·æ±‚部件。请å°è¯•é‡æ–°åŠ è½½é¡µé¢ã€‚"
+msgid "Unable to parse JSON"
+msgstr "æ— æ³•è§£æž JSON"
+
msgid "Unable to parse the vulnerability report's options."
msgstr "无法解æžæ¼æ´žæŠ¥å‘Šçš„选项。"
@@ -40955,6 +41379,9 @@ msgstr "未认è¯çš„请求"
msgid "Unauthenticated web rate limit period in seconds"
msgstr "未ç»èº«ä»½éªŒè¯çš„ Web 速率é™åˆ¶æœŸï¼ˆä»¥ç§’为å•ä½ï¼‰"
+msgid "Unban"
+msgstr "解å°"
+
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
msgstr "如果您更改分支,未æ交的更改将丢失。您想è¦ç»§ç»­å—?"
@@ -41000,9 +41427,6 @@ msgstr "未知的格å¼"
msgid "Unknown response text"
msgstr "未知的å“应文本"
-msgid "Unknown screen"
-msgstr "未知å±å¹•"
-
msgid "Unknown user"
msgstr "未知用户"
@@ -41195,9 +41619,6 @@ msgstr "更新日期"
msgid "Updating"
msgstr "更新中"
-msgid "Updating the attention request for %{username} failed."
-msgstr "更新 %{username} 关注请求失败。"
-
msgid "Updating…"
msgstr "正在更新…"
@@ -41225,6 +41646,9 @@ msgstr "通过存储介质上传您的域åè¯ä¹¦"
msgid "Upload a private key for your certificate"
msgstr "为您的è¯ä¹¦ä¸Šä¼ ä¸€ä¸ªç§é’¥"
+msgid "Upload could not be deleted."
+msgstr "无法删除上传文件。"
+
msgid "Upload file"
msgstr "上传文件"
@@ -41249,9 +41673,6 @@ msgstr "正在上传..."
msgid "Upstream"
msgstr "上游"
-msgid "Uptime"
-msgstr "è¿è¡Œæ—¶é—´"
-
msgid "Upvotes"
msgstr "顶"
@@ -41312,12 +41733,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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
-msgstr "从 %{storage_enforcement_date},存储é™åˆ¶å°†åº”用于此命å空间。您当å‰æ­£åœ¨ä½¿ç”¨ %{used_storage} 个命å空间存储。从 %{strong_start}%{namespace_type} 设置 &gt; 使用é…é¢%{strong_end},查看和管ç†æ‚¨çš„使用情况。"
-
msgid "UsageQuota|Git repository."
msgstr "Git仓库。"
@@ -41387,6 +41808,9 @@ 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。"
@@ -41414,6 +41838,18 @@ msgstr "存储类型"
msgid "UsageQuota|Storage used"
msgstr "已使用存储"
+msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "
+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}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}"
+msgstr "命å空间当å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空间存储。群组所有者å¯ä»¥ä»Ž %{strong_start}群组设置 &gt; 使用é…é¢%{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}User settings &gt; Usage quotas%{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 "下表显示当å‰æ—¶é—´æ®µä½¿ç”¨æƒ…况"
@@ -41684,6 +42120,10 @@ msgstr "使用智能å¡å¯¹LDAPæœåŠ¡å™¨è¿›è¡Œèº«ä»½éªŒè¯ã€‚"
msgid "Used"
msgstr "已使用"
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "被 %d 个包使用"
+
msgid "Used by members to sign in to your group in GitLab"
msgstr "ä¾›æˆå‘˜ç™»å½•æ‚¨çš„GitLab群组"
@@ -41777,6 +42217,9 @@ msgstr "用户已æˆåŠŸä»Žç¾¤ç»„中删除。"
msgid "User was successfully removed from project."
msgstr "用户已æˆåŠŸä»Žé¡¹ç›®ä¸­åˆ é™¤ã€‚"
+msgid "User was successfully unbanned."
+msgstr "用户æˆåŠŸè§£å°ã€‚"
+
msgid "User was successfully updated."
msgstr "用户已æˆåŠŸæ›´æ–°ã€‚"
@@ -41885,6 +42328,9 @@ msgstr "Bot活动"
msgid "UserProfile|Contributed projects"
msgstr "å‚与贡献的项目"
+msgid "UserProfile|Copy user ID"
+msgstr "å¤åˆ¶ç”¨æˆ· ID"
+
msgid "UserProfile|Edit profile"
msgstr "编辑个人资料"
@@ -41966,6 +42412,9 @@ msgstr "此用户没有关注其他用户。"
msgid "UserProfile|Unconfirmed user"
msgstr "未确认的用户"
+msgid "UserProfile|User ID: %{id}"
+msgstr "用户 ID:%{id}"
+
msgid "UserProfile|View all"
msgstr "查看全部"
@@ -42131,10 +42580,6 @@ msgstr "我们没有足够的数æ®æ¥æ˜¾ç¤ºæ­¤é˜¶æ®µã€‚"
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr "%{stageCount}+ 项"
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] "%{subjectFilterText} 和 %{selectedLabelsCount} 标记"
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr "%{value}月"
@@ -42189,11 +42634,17 @@ msgstr "创建新议题的数é‡"
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr "导致生产事故的部署百分比。"
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr "显示群组 “%{groupName}†的 %{selectedFiltersDescription} 和从 %{createdAfter} 到 %{createdBefore} 的 %{selectedProjectCount} 个项目"
+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 "显示群组 “%{groupName}†的 %{selectedSubjectFilterText} 和从 %{createdAfter} 到 %{createdBefore} 的 %{projectsCount}。"
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr "为群组 “%{groupName}“ 显示从 %{createdAfter} 到 %{createdBefore} 的 %{selectedFiltersDescription}"
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr "为群组 “%{groupName}“ 显示 %{selectedSubjectFilterText},从 %{createdAfter} 到 %{createdBefore}。"
msgid "ValueStreamAnalytics|Tasks by type"
msgstr "按类型划分任务"
@@ -42282,6 +42733,12 @@ 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 "版本 %{versionNumber}"
@@ -42888,6 +43345,9 @@ msgstr "警告:åŒæ­¥ LDAP 会删除直接æˆå‘˜çš„访问æƒé™ã€‚"
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 "我们目å‰æ— æ³•èŽ·å–æ­¤æµæ°´çº¿æŠ¥å¤´çš„æ•°æ®ã€‚"
@@ -42933,9 +43393,6 @@ msgstr "我们邀请您加入 %{featureLinkStart}请求功能%{featureLinkEnd}ï¼
msgid "We recommend a work email address."
msgstr "我们推è工作电å­é‚®ä»¶åœ°å€ã€‚"
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr "我们推è基于云端的移动身份验è¯å™¨åº”用,例如Authyã€Duo Mobileå’ŒLastPas。如果您丢失了硬件设备,他们å¯ä»¥æ¢å¤è®¿é—®ã€‚"
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr "我们建议å¯ç”¨æ‰€æœ‰ SAST 分æžå™¨"
@@ -42945,6 +43402,9 @@ 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 "我们å‘é€äº†ä¸€å°å¸¦æœ‰é‡ç½®å¯†ç ä¿¡æ¯çš„电å­é‚®ä»¶"
@@ -43245,6 +43705,12 @@ 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 "这个命令有什么作用?"
@@ -43303,6 +43769,10 @@ msgstr "使用%{code_open}http://%{code_close}或%{code_open}https://%{code_clos
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] "当您的试用期结æŸæ—¶ï¼Œæ‚¨å°†è½¬åˆ°å…费版,席ä½é™åˆ¶ä¸º %{free_user_limit} 个。%{free_user_limit} 个席ä½å°†ä¿æŒæ´»åŠ¨çŠ¶æ€ï¼Œæœªå ç”¨å¸­ä½çš„æˆå‘˜å°†å¤„于%{link_start}超é™çŠ¶æ€%{link_end}并无法访问该群组。"
+
msgid "When:"
msgstr "当:"
@@ -43339,6 +43809,12 @@ msgstr "您为什么è¦æ³¨å†Œï¼Ÿï¼ˆå¯é€‰ï¼‰"
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr "富文本"
+
+msgid "Wiki Page|Source"
+msgstr "æ¥æº"
+
msgid "Wiki page"
msgstr "Wiki 页é¢"
@@ -43465,12 +43941,6 @@ msgstr "创建 %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "创建页é¢"
-msgid "WikiPage|Edit rich text"
-msgstr "编辑富文本"
-
-msgid "WikiPage|Edit source"
-msgstr "编辑æ¥æº"
-
msgid "WikiPage|Format"
msgstr "æ ¼å¼"
@@ -43570,11 +44040,14 @@ msgstr "正在进行中(开放和未分é…)"
msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
-msgid "WorkItem|Add"
-msgstr "添加"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "任务æ供了将您的工作分解æˆä¸Žè®®é¢˜ç›¸å…³çš„多个部分的能力。任务使用我们新的 %{workItemsLink} 对象。更多的工作项类型将很快到æ¥ã€‚"
-msgid "WorkItem|Add a child"
-msgstr "添加å­é¡¹"
+msgid "WorkItem|Add a task"
+msgstr "添加任务"
+
+msgid "WorkItem|Add a title"
+msgstr "添加标题"
msgid "WorkItem|Add assignee"
msgstr "添加指派人"
@@ -43582,11 +44055,14 @@ msgstr "添加指派人"
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
-msgstr "确定è¦åˆ é™¤å·¥ä½œé¡¹å—?此æ“作无法撤消。"
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "确定è¦åˆ é™¤æ­¤ä»»åŠ¡å—?此æ“作无法撤消。"
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
@@ -43598,6 +44074,9 @@ msgstr "å–消"
msgid "WorkItem|Child items"
msgstr "å­é¡¹"
+msgid "WorkItem|Child removed"
+msgstr "已删除å­é¡¹"
+
msgid "WorkItem|Closed"
msgstr "已关闭"
@@ -43610,24 +44089,39 @@ msgstr "创建任务"
msgid "WorkItem|Create work item"
msgstr "创建工作项"
-msgid "WorkItem|Delete work item"
-msgstr "删除工作项"
+msgid "WorkItem|Delete task"
+msgstr "删除任务"
msgid "WorkItem|Expand child items"
msgstr "展开å­é¡¹"
+msgid "WorkItem|Introducing tasks"
+msgstr "介ç»ä»»åŠ¡"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "了解任务"
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr "ç›®å‰æ²¡æœ‰æŒ‡æ´¾å­é¡¹ã€‚使用å­é¡¹æ¥æŽ’列您的团队应该完æˆçš„任务的优先级,实现您的目标ï¼"
msgid "WorkItem|Open"
msgstr "开放"
+msgid "WorkItem|Remove"
+msgstr "删除"
+
msgid "WorkItem|Select type"
msgstr "选择类型"
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "创建任务时出错。请é‡è¯•"
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr "创建工作项时出现错误,请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "删除任务时出错。请é‡è¯•ã€‚"
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr "删除工作项时出错。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr "更新工作项时出现错误,请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "WorkItem|Task deleted"
+msgstr "任务已删除"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr "类型"
+msgid "WorkItem|Undo"
+msgstr "撤消"
+
msgid "WorkItem|Work Items"
msgstr "工作事项"
msgid "WorkItem|Work item deleted"
msgstr "已删除工作项"
+msgid "WorkItem|work items"
+msgstr "工作项"
+
msgid "Would you like to create a new branch?"
msgstr "您è¦åˆ›å»ºä¸€ä¸ªæ–°åˆ†æ”¯å—?"
@@ -43929,8 +44444,9 @@ 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 "您å¯ä»¥ä½¿ç”¨æ ‡ç­¾å¯¹æµ‹è¯•ç”¨ä¾‹è¿›è¡Œåˆ†ç»„。è¦äº†è§£æ­¤åŠŸèƒ½çš„未æ¥å‘展方å‘,请访问 %{linkStart}è´¨é‡ç®¡ç†æ–¹å‘页%{linkEnd}。"
-msgid "You can have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr "在您的所有个人项目中,您最多å¯ä»¥æœ‰ %{free_limit} 个唯一æˆå‘˜ã€‚è¦æŸ¥çœ‹å’Œç®¡ç†æˆå‘˜ï¼Œè¯·æ£€æŸ¥å‘½å空间中æ¯ä¸ªé¡¹ç›®çš„æˆå‘˜é¡µé¢ã€‚我们建议您 %{move_link_start}将您的项目移动到群组%{move_link_end},以便您å¯ä»¥è½»æ¾ç®¡ç†ç”¨æˆ·å’ŒåŠŸèƒ½ã€‚"
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] "在您的所有个人项目中,您最多å¯ä»¥æœ‰ %{free_user_limit} 个æˆå‘˜ã€‚"
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。"
@@ -43938,9 +44454,6 @@ msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。
msgid "You can invite a new member to %{project_name}."
msgstr "您å¯ä»¥é‚€è¯·ä¸€ä¸ªæ–°æˆå‘˜åŠ å…¥%{project_name}。"
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr "您å¯ä»¥é‚€è¯·æ–°æˆå‘˜åŠ å…¥ %{strong_start}%{group_name}%{strong_end}。"
-
msgid "You can invite another group to %{project_name}."
msgstr "您å¯ä»¥é‚€è¯·å¦ä¸€ä¸ªç¾¤ç»„加入%{project_name}。"
@@ -43995,8 +44508,8 @@ msgstr "您也å¯ä»¥é€šè¿‡%{linkStart}Lint%{linkEnd}测试.gitlab-ci.yml."
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
msgstr "您å¯ä»¥æŸ¥çœ‹æºä»£ç æˆ–%{linkStart}%{cloneIcon}克隆仓库%{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 this namespace can start a trial or upgrade to a paid tier."
-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 "您ä¸èƒ½ %{action} %{state} 用户。"
@@ -44007,15 +44520,9 @@ msgstr "您ä¸èƒ½è®¿é—®åŽŸå§‹æ–‡ä»¶ã€‚请ç¨å€™ã€‚"
msgid "You cannot approve your own deployment."
msgstr "您ä¸èƒ½æ‰¹å‡†æ‚¨è‡ªå·±çš„部署。"
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr "在周期已ç»å¼€å§‹åŽï¼Œæ‚¨æ— æ³•è°ƒæ•´å¼€å§‹æ—¥æœŸã€‚请创建一个新周期。"
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr "您ä¸èƒ½å°† replace_ids 与 add_ids 或 remove_ids 结åˆä½¿ç”¨"
-msgid "You cannot edit this timeline event."
-msgstr "您无法编辑此时间线事件。"
-
msgid "You cannot impersonate a blocked user"
msgstr "您无法使用被ç¦ç”¨ç”¨æˆ·çš„身份"
@@ -44046,11 +44553,9 @@ msgstr "您ä¸èƒ½åœ¨è¿™ä¸ªé¡¹ç›®ä¸­ç›´æŽ¥ç¼–辑文件,请派生(Fork)这ä¸
msgid "You could not create a new trigger."
msgstr "您无法创建新的触å‘器。"
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr "您所有的个人项目中目å‰æœ‰è¶…过 %{free_limit} 个æˆå‘˜ã€‚自 2022 å¹´ 6 月22 日起,%{free_limit} 个最近活跃的æˆå‘˜å°†ç»§ç»­æ´»è·ƒï¼Œå…¶ä½™æˆå‘˜å°†èŽ·å¾—%{link_start}超过é™åˆ¶çš„状æ€%{link_end}并无法访问。è¦æŸ¥çœ‹å’Œç®¡ç†æˆå‘˜ï¼Œè¯·æ£€æŸ¥æ‚¨å‘½å空间中æ¯ä¸ªé¡¹ç›®çš„æˆå‘˜é¡µé¢ã€‚我们推è您 %{move_link_start}将您的项目移动到一个群组%{move_link_end} ,以便您å¯ä»¥è½»æ¾åœ°ç®¡ç†ç”¨æˆ·å’ŒåŠŸèƒ½ã€‚"
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr "您没有任何 Google Cloud 项目。请创建一个 Google Cloud 项目,然åŽé‡æ–°åŠ è½½æ­¤é¡µé¢ã€‚"
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr "您当å‰å°šæœªè®¢é˜…任何计划"
@@ -44383,6 +44888,9 @@ msgstr "您收到这å°ç”µå­é‚®ä»¶æ˜¯å› ä¸ºæ‚¨åœ¨ %{host} 上被æåŠã€‚%{mana
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 "您收到这å°ç”µå­é‚®ä»¶æ˜¯å› ä¸ºæ‚¨åœ¨ %{host} 上指派了一个事项。从此主题%{unsubscribe_link_start}å–消订阅%{unsubscribe_link_end} &middot; %{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}帮助%{help_link_end}"
+msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
+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 "您已ç»ä½¿ç”¨ä¸€æ¬¡å¯†ç éªŒè¯å™¨å¯ç”¨äº†åŒé‡è®¤è¯ã€‚如果您è¦æ³¨å†Œä¸åŒçš„设备,您必须先ç¦ç”¨åŒé‡è®¤è¯ã€‚"
@@ -44395,9 +44903,6 @@ msgstr "您拒ç»äº† %{user}"
msgid "YouTube"
msgstr "YouTube"
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr "您的 %{doc_link_start}命å空间%{doc_link_end},%{strong_start}%{namespace_name}%{strong_end} 有超过 %{free_limit} 个æˆå‘˜ã€‚从 2022 å¹´ 6 月 22 日起,将é™åˆ¶ä¸º %{free_limit} 个,其余æˆå‘˜å°†å¤„于 %{link_start} 超过é™åˆ¶%{link_end} 状æ€å¹¶å¤±åŽ»å¯¹å‘½å空间的访问æƒé™ã€‚您å¯ä»¥è½¬åˆ°ä½¿ç”¨é‡é…é¢é¡µé¢ï¼Œæ¥ç®¡ç†å°† %{free_limit} 个æˆå‘˜ä¿ç•™åœ¨æ‚¨çš„命å空间中。è¦èŽ·å¾—更多会员,所有者å¯ä»¥å¼€å§‹è¯•ç”¨æˆ–å‡çº§åˆ°ä»˜è´¹è®¡åˆ’。"
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr "您的%{group}æˆå‘˜èµ„格将在%{days}天内到期。"
@@ -44410,8 +44915,8 @@ msgstr "您的 %{spammable_entity_type} 涉åŠåžƒåœ¾ä¿¡æ¯ï¼Œå·²è¢«ä¸¢å¼ƒã€‚"
msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
msgstr "您的 %{spammable_entity_type} 已被识别为垃圾邮件。请更改内容或解决 reCAPTCHA æ¥ç»§ç»­ã€‚"
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
-msgstr "您的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。此åŽï¼Œæ‚¨å°†æ— æ³•åˆ›å»ºè®®é¢˜æˆ–åˆå¹¶è¯·æ±‚,åŒæ—¶ä¹Ÿæ— æ³•è®¿é—®å…¶ä»–众多功能。"
+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 "您的 %{strong}%{plan_name}%{strong_close} 订阅将于 %{strong}%{expires_on}%{strong_close} 到期。如果您ä¸ç»­è®¢ï¼Œæ‚¨å°†æ— æ³•åœ¨ %{strong}%{downgrades_on}%{strong_close} 访问您的付费功能。在该日期之åŽï¼Œæ‚¨å°†æ— æ³•åˆ›å»ºè®®é¢˜æˆ–åˆå¹¶è¯·æ±‚,或使用许多其他功能。"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
msgstr "您为%{strong}%{namespace_name}%{strong_close}的%{strong}%{plan_name}%{strong_close}订阅将于%{strong}%{expires_on}%{strong_close}到期。"
@@ -44584,6 +45089,14 @@ msgstr "您的文件必须包å«å为%{codeStart}title%{codeEnd}的列。%{code
msgid "Your first project"
msgstr "您的第一个项目"
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+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] "您的群组 %{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 "您的群组"
@@ -44680,9 +45193,6 @@ msgstr "您的需求正在导入。导入完æˆæ—¶æ‚¨å°†æ”¶åˆ°ä¸€å°ç¡®è®¤ç”µå­
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr "您的需求将在åŽå°å¯¼å…¥ã€‚完æˆåŽï¼Œæ‚¨å°†æ”¶åˆ°ä¸€å°ç¡®è®¤ç”µå­é‚®ä»¶ã€‚"
-msgid "Your response has been recorded."
-msgstr "ä½ çš„å馈已被记录。"
-
msgid "Your search didn't match any commits."
msgstr "您的æœç´¢æ²¡æœ‰åŒ¹é…任何æ交。"
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] "您的订阅共有 %{total_seat_count} 个席ä½ï¼Œè¿˜å‰©ä¸‹ %{remaining_seat_count} 个。"
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] "您的订阅将在 %{remaining_days} 天åŽåˆ°æœŸã€‚"
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "您的订阅将于 %{expires_on} 到期"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
msgstr "您的更新失败。通过拖放到现有设计的方å¼ï¼Œæ‚¨æ¯æ¬¡åªèƒ½ä¸Šä¼ ä¸€ä¸ªè®¾è®¡ã€‚"
@@ -44858,6 +45367,9 @@ msgstr "产物"
msgid "assign yourself"
msgstr "分é…给自己"
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr "å…³è”的父级是ç§å¯†çš„,ä¸èƒ½æœ‰éžç§å¯†çš„å­çº§ã€‚"
+
msgid "at"
msgstr "于"
@@ -44937,6 +45449,9 @@ msgstr "ä¸èƒ½åŒ…括: %{invalid_storages}"
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 "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
@@ -45037,9 +45552,15 @@ msgstr "%{reportType}:å‘生一个错误"
msgid "ciReport|%{sameNum} same"
msgstr "相åŒ%{sameNum}"
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
+msgstr "%{scanner} 检测到 %{boldStart}%{number} 个%{boldEnd}新的潜在%{vulnStr}"
+
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
msgstr "%{scanner} 检测到 %{strong_start}%{number} 个%{strong_end}新的潜在%{vulnStr}"
+msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
+msgstr "%{scanner} 未检测到%{boldStart}æ–°çš„%{boldEnd}潜在æ¼æ´ž"
+
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
msgstr "%{scanner} 没有检测到%{strong_start}新的%{strong_end} %{vulnStr}"
@@ -45055,6 +45576,9 @@ msgstr "API 模糊测试"
msgid "ciReport|All clusters"
msgstr "所有集群"
+msgid "ciReport|All images"
+msgstr "所有镜åƒ"
+
msgid "ciReport|All projects"
msgstr "所有项目"
@@ -45318,6 +45842,9 @@ msgstr "正在加载"
msgid "ciReport|is loading, errors when loading results"
msgstr "正在加载,加载结果时出错"
+msgid "ci_database"
+msgstr "ci_database"
+
msgid "closed"
msgstr "已关闭"
@@ -45345,6 +45872,9 @@ msgstr "å·²æ交"
msgid "compliance violation has already been recorded"
msgstr "è¿è§„行为已被记录"
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr "如果有éžç§å¯†å­çº§ï¼Œåˆ™ä¸èƒ½ä½¿ç”¨ç§å¯†çˆ¶çº§ã€‚"
+
msgid "contacts can only be added to root groups"
msgstr "è”系人åªèƒ½æ·»åŠ åˆ°æ ¹ç¾¤ç»„"
@@ -45384,9 +45914,6 @@ msgstr "创建人:"
msgid "data"
msgstr "æ•°æ®"
-msgid "database"
-msgstr "æ•°æ®åº“"
-
msgid "date must not be after 9999-12-31"
msgstr "日期ä¸èƒ½åœ¨9999-12-31之åŽ"
@@ -45479,6 +46006,9 @@ msgstr "%{slash_command} 覆盖总估计时间。"
msgid "example.com"
msgstr "example.com"
+msgid "exceeds maximum length (100 usernames)"
+msgstr "超过最大长度(100 个用户å)"
+
msgid "exceeds the %{max_value_length} character limit"
msgstr "超过 %{max_value_length} 个字符的é™åˆ¶"
@@ -45559,9 +46089,6 @@ msgstr "群组访问令牌"
msgid "group members"
msgstr "群组æˆå‘˜"
-msgid "group's CI/CD settings."
-msgstr "群组 CI/CD 设置。"
-
msgid "groups"
msgstr "群组"
@@ -45611,6 +46138,9 @@ msgstr "https://your-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr "%{language} (%{percent_translated}%% 已翻译)"
+msgid "if"
+msgstr "è‹¥"
+
msgid "image diff"
msgstr "图åƒå·®å¼‚"
@@ -45786,6 +46316,9 @@ msgstr "加载中"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "被 %{path_lock_user_name} 在 %{created_at} é”定"
+msgid "main_database"
+msgstr "main_database"
+
msgid "manual"
msgstr "手动"
@@ -45827,12 +46360,6 @@ msgstr "%{commitCount} 将被添加到 %{targetBranch}。"
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1个åˆå¹¶æ交"
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr "将 %{commitCount} 和 %{mergeCommitCount} 添加到 %{targetBranch}%{squashedCommits}。"
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr "将 %{commitCount} 添加到 %{targetBranch}。"
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr "å·²åˆå¹¶åˆ° %{targetBranch} çš„ %{mergeCommitSha}%{squashedCommits} çš„å˜æ›´ã€‚"
@@ -45948,9 +46475,6 @@ msgstr "创建议题æ¥è§£å†³æ‰€æœ‰ä¸»é¢˜"
msgid "mrWidget|Delete source branch"
msgstr "删除æºåˆ†æ”¯"
-msgid "mrWidget|Deletes the source branch"
-msgstr "删除æºåˆ†æ”¯"
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "部署统计信æ¯å½“å‰ä¸å¯ç”¨"
@@ -45960,9 +46484,6 @@ msgstr "未关闭"
msgid "mrWidget|Dismiss"
msgstr "关闭"
-msgid "mrWidget|Does not delete the source branch"
-msgstr "ä¸åˆ é™¤æºåˆ†æ”¯"
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr "无法加载部署统计信æ¯"
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] "æåŠè®®é¢˜"
-msgid "mrWidget|Merge"
-msgstr "åˆå¹¶"
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šå¿…须获得所有è¦æ±‚的批准。"
@@ -46033,9 +46551,6 @@ msgstr "åˆå¹¶ä¸å¯ç”¨ï¼šåˆå¹¶è¯·æ±‚在归档项目上是åªè¯»çš„。"
msgid "mrWidget|Merged by"
msgstr "åˆå¹¶è€…:"
-msgid "mrWidget|Merges changes into"
-msgstr "åˆå¹¶æ›´æ”¹åˆ°"
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "åˆå¹¶ä¸­ï¼æ­£åœ¨å‘é€æ›´æ”¹â€¦"
@@ -46120,21 +46635,9 @@ msgstr "显示 %{widget} 详情"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr "%{type} 分支 %{codeStart}%{name}%{codeEnd} ä¸å­˜åœ¨ã€‚"
-msgid "mrWidget|The changes were merged into"
-msgstr "更改已åˆå¹¶åˆ°"
-
-msgid "mrWidget|The changes were not merged into"
-msgstr "更改未åˆå¹¶åˆ°"
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr "æºåˆ†æ”¯å·²åˆ é™¤"
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "æºåˆ†æ”¯æ˜¯ %{link} 的目标分支"
-msgid "mrWidget|The source branch is being deleted"
-msgstr "æºåˆ†æ”¯æ­£åœ¨åˆ é™¤"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "该åˆå¹¶è¯·æ±‚未能自动åˆå¹¶"
@@ -46446,6 +46949,9 @@ msgstr "仓库"
msgid "repository:"
msgstr "仓库:"
+msgid "role's base access level does not match the access level of the membership"
+msgstr "基于角色的访问级别ä¸åŒ¹é…æˆå‘˜çš„访问级别"
+
msgid "satisfied"
msgstr "满足"
@@ -46458,6 +46964,9 @@ msgstr "扫æ执行策略:策略未应用,缺少 %{policy_path} 文件"
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 "åªæœ‰åœ¨å¯ç”¨äº† retain_approvals_on_push æ—¶æ‰èƒ½å¯ç”¨ selective_code_owner_removals"
+
msgid "severity|Blocker"
msgstr "阻塞"
@@ -46569,13 +47078,13 @@ msgstr "terraform 状æ€"
msgid "the correct format."
msgstr "正确的格å¼ã€‚"
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr "下列å²è¯—"
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr "下列事件或议题"
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr "下列议题"
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr "今天"
msgid "toggle collapse"
msgstr "切æ¢æŠ˜å "
+msgid "total must be less than or equal to %{size}"
+msgstr "总数必须å°äºŽæˆ–等于 %{size}"
+
msgid "triggered"
msgstr "已触å‘"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 2a97269afa5..c79e5a80e81 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-07-14 17:14\n"
+"PO-Revision-Date: 2022-08-12 18:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -385,6 +385,9 @@ msgstr ""
msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr ""
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr ""
@@ -430,8 +433,8 @@ msgstr ""
msgid "%{completedCount} completed weight"
msgstr ""
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
msgstr[0] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
@@ -607,6 +610,9 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "將會移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
+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 ""
@@ -658,6 +664,9 @@ msgstr ""
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr ""
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr ""
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
@@ -670,13 +679,13 @@ msgstr ""
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr ""
-msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
msgstr ""
-msgid "%{label_for_message} unavailable"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{learn_more_link}."
+msgid "%{label_for_message} unavailable"
msgstr ""
msgid "%{lessThan} 1 hour"
@@ -791,6 +800,18 @@ 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 "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr ""
+
msgid "%{percentageUsed}%% used"
msgstr ""
@@ -866,6 +887,14 @@ msgid "%{securityScanner} result is not available because a pipeline has not bee
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] ""
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] ""
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] ""
+
msgid "%{size} %{unit}"
msgstr ""
@@ -903,9 +932,6 @@ msgstr[0] ""
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr ""
-
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -1374,15 +1400,9 @@ msgstr "é›™é‡èªè­‰"
msgid "2FADevice|Registered On"
msgstr ""
-msgid "3 days"
-msgstr "3 天"
-
msgid "3 hours"
msgstr "3 å°æ™‚"
-msgid "30 days"
-msgstr ""
-
msgid "30 minutes"
msgstr "30 分é˜"
@@ -1410,9 +1430,6 @@ msgstr ""
msgid "409|There was a conflict with your request."
msgstr ""
-msgid "7 days"
-msgstr ""
-
msgid "8 hours"
msgstr "8 å°æ™‚"
@@ -1989,6 +2006,9 @@ msgstr ""
msgid "Add a bullet list"
msgstr ""
+msgid "Add a checklist"
+msgstr ""
+
msgid "Add a collapsible section"
msgstr ""
@@ -2028,9 +2048,6 @@ msgstr ""
msgid "Add a table"
msgstr "新增表格"
-msgid "Add a task list"
-msgstr ""
-
msgid "Add a title..."
msgstr ""
@@ -2058,9 +2075,6 @@ msgstr ""
msgid "Add approvers"
msgstr ""
-msgid "Add attention request"
-msgstr ""
-
msgid "Add broadcast message"
msgstr ""
@@ -2106,6 +2120,9 @@ 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 ""
@@ -3630,6 +3647,9 @@ msgstr ""
msgid "All changes are committed"
msgstr "所有改變都已經æ交"
+msgid "All eligible users"
+msgstr ""
+
msgid "All email addresses will be used to identify your commits."
msgstr ""
@@ -3921,9 +3941,6 @@ msgstr ""
msgid "An error occurred while fetching ancestors"
msgstr ""
-msgid "An error occurred while fetching branches."
-msgstr ""
-
msgid "An error occurred while fetching branches. Retry the search."
msgstr ""
@@ -3969,6 +3986,9 @@ 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 ""
@@ -4056,9 +4076,6 @@ msgstr ""
msgid "An error occurred while loading the Test Reports tab."
msgstr ""
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
-
msgid "An error occurred while loading the blob controls."
msgstr ""
@@ -4458,13 +4475,25 @@ 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 GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
msgstr ""
msgid "ApplicationSettings|Send confirmation email on sign-up"
@@ -4491,6 +4520,18 @@ 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 ""
@@ -4631,28 +4672,31 @@ msgstr ""
msgid "ApprovalRule|Try for free"
msgstr ""
-msgid "ApprovalSettings|Merge request approval settings have been updated."
+msgid "ApprovalSettings|Keep approvals"
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author"
+msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr ""
-msgid "ApprovalSettings|Prevent approval by author."
+msgid "ApprovalSettings|Prevent approval by author"
msgstr ""
msgid "ApprovalSettings|Prevent approvals by users who add commits"
msgstr ""
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
+msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
msgstr ""
-msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
+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 when commits are added to the source branch"
+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"
@@ -4670,6 +4714,9 @@ 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 ""
@@ -4697,9 +4744,6 @@ msgstr ""
msgid "Approved-By"
msgstr ""
-msgid "Approved. Your attention request was removed."
-msgstr ""
-
msgid "Approver"
msgstr ""
@@ -5040,9 +5084,6 @@ msgstr ""
msgid "Assigned to you"
msgstr ""
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
-
msgid "Assignee"
msgid_plural "%d Assignees"
msgstr[0] ""
@@ -5083,7 +5124,7 @@ msgstr ""
msgid "At risk"
msgstr ""
-msgid "Attach a file"
+msgid "Attach a file or image"
msgstr ""
msgid "Attaching File - %{progress}"
@@ -5096,12 +5137,6 @@ msgstr[0] ""
msgid "Attaching the file failed."
msgstr ""
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
-
msgid "Audit Events"
msgstr ""
@@ -5162,6 +5197,12 @@ 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 ""
@@ -5180,6 +5221,9 @@ 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 ""
@@ -5195,18 +5239,33 @@ 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|Save external stream destination"
+msgstr ""
+
msgid "AuditStreams|Setup streaming for audit events"
msgstr ""
+msgid "AuditStreams|Stream added successfully"
+msgstr ""
+
msgid "AuditStreams|Stream count icon"
msgstr ""
+msgid "AuditStreams|Stream deleted successfully"
+msgstr ""
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr ""
+
msgid "AuditStreams|Streams"
msgstr ""
@@ -5219,6 +5278,9 @@ msgstr ""
msgid "AuditStreams|Value"
msgstr ""
+msgid "AuditStreams|Verification token"
+msgstr ""
+
msgid "Aug"
msgstr "八月"
@@ -5435,7 +5497,7 @@ msgstr ""
msgid "Automatically resolved"
msgstr ""
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
msgid "Autosave|Note"
@@ -5624,6 +5686,9 @@ msgstr ""
msgid "BambooService|The user with API access to the Bamboo server."
msgstr ""
+msgid "Banned"
+msgstr ""
+
msgid "Banner message"
msgstr ""
@@ -5975,6 +6040,9 @@ 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 ""
@@ -6068,17 +6136,15 @@ msgstr ""
msgid "Billing|Export list"
msgstr ""
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
-
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
msgstr ""
msgid "Billing|Group invite"
msgstr ""
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] ""
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 ""
@@ -6095,6 +6161,9 @@ 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 ""
@@ -6110,13 +6179,10 @@ 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|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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."
+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"
@@ -6446,9 +6512,51 @@ msgstr ""
msgid "Branch rules"
msgstr ""
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+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 push"
+msgstr ""
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr ""
+
+msgid "BranchRules|Branch"
+msgstr ""
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr ""
+
+msgid "BranchRules|No matching results"
+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 "Branches"
msgstr "分支"
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr ""
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr ""
+
msgid "Branches|Active"
msgstr "æ´»èºçš„"
@@ -7056,9 +7164,6 @@ msgstr ""
msgid "Can't find variable: ZiteReader"
msgstr ""
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
-
msgid "Can't scan the code?"
msgstr ""
@@ -7745,9 +7850,6 @@ msgstr ""
msgid "Child issues and epics"
msgstr ""
-msgid "Children"
-msgstr ""
-
msgid "Chinese language support using"
msgstr ""
@@ -8169,6 +8271,9 @@ msgstr ""
msgid "CloudSeed|CloudSQL Instance"
msgstr ""
+msgid "CloudSeed|Configuration"
+msgstr ""
+
msgid "CloudSeed|Create cluster"
msgstr ""
@@ -8187,6 +8292,12 @@ msgstr ""
msgid "CloudSeed|Database version"
msgstr ""
+msgid "CloudSeed|Databases"
+msgstr ""
+
+msgid "CloudSeed|Deployments"
+msgstr ""
+
msgid "CloudSeed|Description"
msgstr ""
@@ -8244,12 +8355,18 @@ 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 ""
@@ -10067,9 +10184,6 @@ msgstr ""
msgid "Content parsed with %{link}."
msgstr ""
-msgid "ContentEditor|Table of Contents"
-msgstr ""
-
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -10508,9 +10622,6 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
-msgid "Create Google Cloud project"
-msgstr ""
-
msgid "Create New Directory"
msgstr "創建新目錄"
@@ -10961,6 +11072,9 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Active"
+msgstr ""
+
msgid "Crm|Contact"
msgstr ""
@@ -11346,6 +11460,9 @@ msgstr ""
msgid "DAST Configuration"
msgstr ""
+msgid "DAST configuration not found"
+msgstr ""
+
msgid "DAST profile not found: %{name}"
msgstr ""
@@ -11364,6 +11481,9 @@ msgstr ""
msgid "DORA4Metrics|Change failure rate"
msgstr ""
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr ""
+
msgid "DORA4Metrics|Date"
msgstr ""
@@ -11379,6 +11499,9 @@ msgstr ""
msgid "DORA4Metrics|Lead time for changes"
msgstr ""
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr ""
+
msgid "DORA4Metrics|Median (last %{days}d)"
msgstr ""
@@ -11424,6 +11547,9 @@ msgstr ""
msgid "DORA4Metrics|Time to restore service"
msgstr ""
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr ""
+
msgid "DSN"
msgstr ""
@@ -11460,9 +11586,21 @@ 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 ""
@@ -12157,6 +12295,9 @@ msgstr ""
msgid "Delete file"
msgstr ""
+msgid "Delete identity"
+msgstr ""
+
msgid "Delete image"
msgstr ""
@@ -12181,6 +12322,12 @@ msgstr ""
msgid "Delete project"
msgstr ""
+msgid "Delete release"
+msgstr ""
+
+msgid "Delete release %{release}?"
+msgstr ""
+
msgid "Delete row"
msgstr ""
@@ -12238,6 +12385,15 @@ 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 ""
@@ -12262,9 +12418,6 @@ msgstr ""
msgid "Deletes the source branch"
msgstr ""
-msgid "Deletes the source branch."
-msgstr ""
-
msgid "Deleting"
msgstr ""
@@ -12466,6 +12619,9 @@ msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
+msgid "Deploy Key"
+msgstr ""
+
msgid "Deploy Keys"
msgstr ""
@@ -12721,7 +12877,7 @@ msgstr ""
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
msgstr ""
-msgid "DeploymentApproval|Approved by %{user} %{time}"
+msgid "DeploymentApproval|Approved %{time}"
msgstr ""
msgid "DeploymentApproval|Approved by you %{time}"
@@ -13516,9 +13672,6 @@ msgstr ""
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
msgstr ""
-msgid "Does not delete the source branch."
-msgstr ""
-
msgid "Domain"
msgstr ""
@@ -13927,9 +14080,6 @@ msgstr ""
msgid "Elastic|None. Select projects to index."
msgstr ""
-msgid "Eligible users"
-msgstr ""
-
msgid "Email"
msgstr ""
@@ -14251,9 +14401,6 @@ msgstr ""
msgid "Enabled OAuth authentication sources"
msgstr ""
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
-
msgid "End Time"
msgstr ""
@@ -14752,6 +14899,9 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr ""
+
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -15724,22 +15874,19 @@ msgstr ""
msgid "Failed to remove a to-do item for the design."
msgstr ""
-msgid "Failed to remove attention because no user was found."
-msgstr ""
-
msgid "Failed to remove mirror."
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "無法刪除æµæ°´ç·šè¨ˆåŠƒ"
-msgid "Failed to remove user identity."
+msgid "Failed to remove timelog"
msgstr ""
-msgid "Failed to remove user key."
+msgid "Failed to remove user identity."
msgstr ""
-msgid "Failed to request attention because no user was found."
+msgid "Failed to remove user key."
msgstr ""
msgid "Failed to retrieve page"
@@ -15757,6 +15904,9 @@ 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 ""
@@ -15802,9 +15952,6 @@ msgstr ""
msgid "Fast timeout"
msgstr ""
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
-
msgid "Faster releases. Better code. Less pain."
msgstr ""
@@ -16046,6 +16193,9 @@ msgstr "二月"
msgid "February"
msgstr "二月"
+msgid "Feedback issue"
+msgstr ""
+
msgid "Fetch and check out this merge request's feature branch:"
msgstr ""
@@ -16463,6 +16613,10 @@ msgstr ""
msgid "Free Trial of GitLab.com Ultimate"
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 "Freeze end"
msgstr ""
@@ -16487,11 +16641,13 @@ msgstr ""
msgid "From %{providerTitle}"
msgstr ""
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] ""
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] ""
msgid "From issue creation until deploy to production"
msgstr "從創建議題到部署到生產環境"
@@ -16550,6 +16706,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated with JSON data"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -16597,6 +16756,9 @@ msgstr ""
msgid "Geo|%{component} verified"
msgstr ""
+msgid "Geo|%{label} %{timeAgo}"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -16771,9 +16933,6 @@ msgstr ""
msgid "Geo|In progress"
msgstr ""
-msgid "Geo|In sync"
-msgstr ""
-
msgid "Geo|Internal URL"
msgstr ""
@@ -16831,9 +16990,6 @@ msgstr ""
msgid "Geo|No available replication slots"
msgstr ""
-msgid "Geo|Not synced yet"
-msgstr ""
-
msgid "Geo|Nothing found…"
msgstr ""
@@ -17089,9 +17245,6 @@ msgstr ""
msgid "Geo|Unknown"
msgstr ""
-msgid "Geo|Unknown state"
-msgstr ""
-
msgid "Geo|Updated %{timeAgo}"
msgstr ""
@@ -17275,6 +17428,9 @@ msgstr ""
msgid "GitLab KAS"
msgstr ""
+msgid "GitLab Logo"
+msgstr ""
+
msgid "GitLab Pages"
msgstr ""
@@ -17299,9 +17455,6 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
-
msgid "GitLab commit"
msgstr ""
@@ -17395,6 +17548,9 @@ msgstr ""
msgid "GitLabPages|Certificate: %{subject}"
msgstr ""
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr ""
+
msgid "GitLabPages|Configure pages"
msgstr ""
@@ -17446,6 +17602,9 @@ 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 ""
@@ -17458,6 +17617,9 @@ 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 ""
@@ -17470,6 +17632,9 @@ 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 ""
@@ -17788,16 +17953,13 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud Project"
+msgid "Google Cloud Error - %{error}"
msgstr ""
-msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
+msgid "Google Cloud Project"
msgstr ""
-msgid "Google Cloud project required"
+msgid "Google Cloud authorizations required"
msgstr ""
msgid "GoogleCloud|Cancel"
@@ -18019,9 +18181,6 @@ msgstr ""
msgid "Group overview content"
msgstr ""
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
-
msgid "Group path is already taken. We've suggested one that is available."
msgstr ""
@@ -18175,7 +18334,7 @@ msgstr ""
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
+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"
@@ -18340,7 +18499,7 @@ msgstr ""
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr ""
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
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."
@@ -18388,6 +18547,9 @@ 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 ""
@@ -18400,15 +18562,9 @@ 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|Interval (seconds)"
-msgstr ""
-
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
msgstr ""
-msgid "GroupSettings|Number of projects"
-msgstr ""
-
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
msgstr ""
@@ -18427,9 +18583,6 @@ msgstr ""
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr ""
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
msgstr ""
@@ -18454,15 +18607,9 @@ msgstr ""
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
msgstr ""
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
-
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
msgstr ""
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-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 ""
@@ -18580,6 +18727,9 @@ 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 ""
@@ -18598,6 +18748,9 @@ 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 ""
@@ -18643,6 +18796,9 @@ msgstr ""
msgid "GroupsNew|Upload file"
msgstr ""
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr ""
+
msgid "GroupsNew|e.g. h8d3f016698e..."
msgstr ""
@@ -18721,6 +18877,15 @@ msgstr ""
msgid "Groups|Save changes"
msgstr ""
+msgid "Groups|Subgroup URL"
+msgstr ""
+
+msgid "Groups|Subgroup name"
+msgstr ""
+
+msgid "Groups|Subgroup slug"
+msgstr ""
+
msgid "Guideline"
msgstr ""
@@ -18739,7 +18904,7 @@ msgstr ""
msgid "Harbor Registry"
msgstr ""
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$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."
@@ -18849,12 +19014,6 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -19073,6 +19232,9 @@ msgstr ""
msgid "HighlightBar|Time to SLA:"
msgstr ""
+msgid "Historical release"
+msgstr ""
+
msgid "History"
msgstr "æ­·å²ç´€éŒ„"
@@ -19142,6 +19304,9 @@ 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 ""
@@ -19325,6 +19490,9 @@ 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 ""
@@ -19352,6 +19520,9 @@ 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 ""
@@ -19628,6 +19799,9 @@ msgstr[0] ""
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 ""
@@ -19673,9 +19847,6 @@ msgstr ""
msgid "InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals"
msgstr ""
-msgid "InProductMarketing|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
-
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
msgstr ""
@@ -19733,9 +19904,6 @@ 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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
-
msgid "InProductMarketing|Code owners"
msgstr ""
@@ -19778,9 +19946,6 @@ msgstr ""
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
msgstr ""
-msgid "InProductMarketing|Difficult"
-msgstr ""
-
msgid "InProductMarketing|Dig in and create a project and a repo"
msgstr ""
@@ -19790,18 +19955,12 @@ msgstr ""
msgid "InProductMarketing|Discover Premium & Ultimate."
msgstr ""
-msgid "InProductMarketing|Do you have a minute?"
-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|Easy"
-msgstr ""
-
msgid "InProductMarketing|Epics"
msgstr ""
@@ -19820,9 +19979,6 @@ msgstr ""
msgid "InProductMarketing|Facebook"
msgstr ""
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
-
msgid "InProductMarketing|Feel the need for speed?"
msgstr ""
@@ -19991,9 +20147,6 @@ msgstr ""
msgid "InProductMarketing|Need an alternative to importing?"
msgstr ""
-msgid "InProductMarketing|Neutral"
-msgstr ""
-
msgid "InProductMarketing|No credit card required."
msgstr ""
@@ -20066,9 +20219,6 @@ 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 this 1-question survey!"
-msgstr ""
-
msgid "InProductMarketing|Take your first steps with GitLab"
msgstr ""
@@ -20141,12 +20291,6 @@ msgstr ""
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
msgstr ""
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
-
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
msgstr ""
@@ -20162,9 +20306,6 @@ 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|We want your GitLab experience to be great"
-msgstr ""
-
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
msgstr ""
@@ -21186,7 +21327,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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"
@@ -21262,7 +21403,7 @@ 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 this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
+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|To make more space, you can remove members who no longer need access."
@@ -21277,9 +21418,6 @@ msgstr ""
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
msgstr ""
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -21685,6 +21823,9 @@ msgstr ""
msgid "Iteration"
msgstr ""
+msgid "Iteration cannot be created for cadence"
+msgstr ""
+
msgid "Iteration changed to"
msgstr ""
@@ -21700,12 +21841,36 @@ 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 ""
@@ -21727,6 +21892,9 @@ msgstr ""
msgid "Iterations|Create iteration"
msgstr ""
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr ""
+
msgid "Iterations|Delete cadence"
msgstr ""
@@ -21757,10 +21925,10 @@ msgstr ""
msgid "Iterations|Edit iteration cadence"
msgstr ""
-msgid "Iterations|Error loading iteration cadences."
+msgid "Iterations|Enable roll over"
msgstr ""
-msgid "Iterations|First iteration start date"
+msgid "Iterations|Error loading iteration cadences."
msgstr ""
msgid "Iterations|Iteration cadences"
@@ -21769,6 +21937,9 @@ 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|Learn more about automatic scheduling"
msgstr ""
@@ -21796,9 +21967,6 @@ msgstr ""
msgid "Iterations|No iterations in cadence."
msgstr ""
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
-
msgid "Iterations|No open iterations."
msgstr ""
@@ -21826,13 +21994,13 @@ msgstr ""
msgid "Iterations|Start date"
msgstr ""
-msgid "Iterations|The duration of each iteration (in weeks)."
+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 iteration has been deleted."
+msgid "Iterations|The duration of each iteration (in weeks)."
msgstr ""
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
+msgid "Iterations|The iteration has been deleted."
msgstr ""
msgid "Iterations|This cadence can be converted to use automated scheduling"
@@ -22318,6 +22486,9 @@ msgstr ""
msgid "Job|Scroll to bottom"
msgstr ""
+msgid "Job|Scroll to next failure"
+msgstr ""
+
msgid "Job|Scroll to top"
msgstr ""
@@ -22441,7 +22612,7 @@ msgstr ""
msgid "Key (PEM)"
msgstr ""
-msgid "Key: %{key}"
+msgid "Key:"
msgstr ""
msgid "Keyboard shortcuts"
@@ -22707,15 +22878,9 @@ msgstr ""
msgid "Last sign-in at:"
msgstr ""
-msgid "Last successful sync"
-msgstr ""
-
msgid "Last successful update"
msgstr ""
-msgid "Last time checked"
-msgstr ""
-
msgid "Last time verified"
msgstr ""
@@ -22998,19 +23163,19 @@ msgstr ""
msgid "Less Details"
msgstr ""
-msgid "Let's Encrypt does not accept emails on example.com"
+msgid "Less restrictive visibility"
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}."
+msgid "Let's Encrypt does not accept emails on example.com"
msgstr ""
-msgid "Let's talk!"
+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"
+msgid "License Compliance| Used by %{dependencies}"
msgstr ""
msgid "License compliance"
@@ -23265,7 +23430,10 @@ msgstr ""
msgid "Linked epics"
msgstr ""
-msgid "Linked issues"
+msgid "Linked incidents or issues"
+msgstr ""
+
+msgid "Linked items"
msgstr ""
msgid "LinkedIn"
@@ -23277,6 +23445,48 @@ 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 ""
@@ -23604,9 +23814,6 @@ msgstr ""
msgid "Manual"
msgstr ""
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -23868,7 +24075,7 @@ 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_whitelist}."
+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"
@@ -25258,12 +25465,6 @@ msgstr ""
msgid "MrList|Assigned to %{name}"
msgstr ""
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
-
msgid "MrList|Review requested from %{name}"
msgstr ""
@@ -25288,7 +25489,7 @@ msgstr ""
msgid "Multiple HTTP integrations are not supported for this project"
msgstr ""
-msgid "Multiple IP address ranges are supported."
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
msgstr ""
msgid "Multiple Prometheus integrations are not supported"
@@ -25472,9 +25673,6 @@ msgstr ""
msgid "Need help?"
msgstr ""
-msgid "Need your attention"
-msgstr ""
-
msgid "Needs"
msgstr ""
@@ -25743,6 +25941,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr ""
+
msgid "No Matching Results"
msgstr ""
@@ -25773,9 +25974,6 @@ msgstr ""
msgid "No assignee"
msgstr ""
-msgid "No attention request"
-msgstr ""
-
msgid "No authentication methods configured."
msgstr ""
@@ -26074,9 +26272,6 @@ msgstr ""
msgid "Normal text"
msgstr ""
-msgid "Not Implemented"
-msgstr ""
-
msgid "Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser."
msgstr ""
@@ -26197,6 +26392,9 @@ 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 ""
@@ -26330,6 +26528,15 @@ msgstr ""
msgid "Notify|%{commit_link} in %{mr_link}"
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|%{member_link} requested %{member_role} access to the %{target_source_link} %{target_type}."
+msgstr ""
+
msgid "Notify|Assignee changed from %{fromNames} to %{toNames}"
msgstr ""
@@ -26495,6 +26702,10 @@ 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] ""
+
msgid "On track"
msgstr ""
@@ -26967,9 +27178,6 @@ msgstr ""
msgid "Only use lowercase letters, numbers, and underscores."
msgstr ""
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-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 ""
@@ -27063,6 +27271,9 @@ 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 ""
@@ -27384,6 +27595,10 @@ msgstr ""
msgid "PackageRegistry|Debian"
msgstr ""
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] ""
+
msgid "PackageRegistry|Delete Package File"
msgstr ""
@@ -27393,6 +27608,9 @@ msgstr ""
msgid "PackageRegistry|Delete package"
msgstr ""
+msgid "PackageRegistry|Delete selected"
+msgstr ""
+
msgid "PackageRegistry|Delete this package"
msgstr ""
@@ -27402,6 +27620,9 @@ 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 ""
@@ -27459,6 +27680,9 @@ msgstr ""
msgid "PackageRegistry|License information located at %{link}"
msgstr ""
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr ""
+
msgid "PackageRegistry|Manually Published"
msgstr ""
@@ -27477,9 +27701,15 @@ msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr ""
+
msgid "PackageRegistry|Package Registry"
msgstr ""
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr ""
+
msgid "PackageRegistry|Package deleted successfully"
msgstr ""
@@ -27493,6 +27723,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 assets"
+msgstr ""
+
msgid "PackageRegistry|Pip Command"
msgstr ""
@@ -27550,6 +27783,9 @@ msgstr ""
msgid "PackageRegistry|Show Yarn commands"
msgstr ""
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr ""
+
msgid "PackageRegistry|Something went wrong while deleting the package file."
msgstr ""
@@ -27601,18 +27837,28 @@ 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}, this operation is irreversible, 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] ""
+
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 ""
@@ -27868,6 +28114,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
+msgid "Performance insights"
+msgstr ""
+
msgid "Performance optimization"
msgstr ""
@@ -27973,6 +28222,18 @@ 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 ""
@@ -28129,6 +28390,9 @@ 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 ""
@@ -28147,6 +28411,15 @@ 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 ""
@@ -28168,6 +28441,12 @@ 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 ""
@@ -28189,6 +28468,9 @@ 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|Provide a short description for this pipeline"
msgstr "為此æµæ°´ç·šæ供簡短æè¿°"
@@ -28201,6 +28483,9 @@ msgstr "目標"
msgid "PipelineSchedules|Variables"
msgstr "變é‡"
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr ""
+
msgid "PipelineSource|API"
msgstr ""
@@ -28447,6 +28732,9 @@ msgstr ""
msgid "Pipelines|Pipeline Editor"
msgstr ""
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr ""
+
msgid "Pipelines|Project cache successfully reset."
msgstr ""
@@ -28615,9 +28903,18 @@ msgstr ""
msgid "Pipeline|Failed"
msgstr ""
+msgid "Pipeline|Five slowest jobs"
+msgstr ""
+
msgid "Pipeline|In progress"
msgstr ""
+msgid "Pipeline|Last executed job"
+msgstr ""
+
+msgid "Pipeline|Longest queued job"
+msgstr ""
+
msgid "Pipeline|Manual"
msgstr ""
@@ -28630,12 +28927,18 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
+msgid "Pipeline|Only able to show first 100 results"
+msgstr ""
+
msgid "Pipeline|Passed"
msgstr ""
msgid "Pipeline|Pending"
msgstr ""
+msgid "Pipeline|Performance insights"
+msgstr ""
+
msgid "Pipeline|Pipeline"
msgstr ""
@@ -28654,6 +28957,9 @@ msgstr ""
msgid "Pipeline|Run for branch name or tag"
msgstr ""
+msgid "Pipeline|Run merge request pipeline"
+msgstr ""
+
msgid "Pipeline|Run pipeline"
msgstr ""
@@ -28690,6 +28996,12 @@ msgstr ""
msgid "Pipeline|Test coverage"
msgstr ""
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr ""
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr ""
+
msgid "Pipeline|This change will decrease the overall test coverage if merged."
msgstr ""
@@ -28705,6 +29017,9 @@ 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 ""
@@ -28717,6 +29032,9 @@ msgstr ""
msgid "Pipeline|View commit"
msgstr ""
+msgid "Pipeline|View dependency"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -28816,6 +29134,9 @@ 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 "
+msgstr ""
+
msgid "Please complete your profile with email address"
msgstr ""
@@ -28918,6 +29239,9 @@ 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 ""
@@ -29164,7 +29488,7 @@ msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
-msgid "Prevent editing approval rules in projects and merge requests."
+msgid "Prevent editing approval rules in projects and merge requests"
msgstr ""
msgid "Prevent environment from auto-stopping"
@@ -29878,6 +30202,9 @@ 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 ""
@@ -29887,6 +30214,12 @@ 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 "訂閱"
@@ -29965,6 +30298,9 @@ 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 ""
@@ -29977,6 +30313,9 @@ 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 ""
@@ -30004,6 +30343,9 @@ 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 ""
@@ -31192,18 +31534,36 @@ msgstr ""
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
+msgid "ProtectedEnvironment|All environments specivied 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 projected."
+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 ""
@@ -31330,6 +31690,12 @@ 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 ""
@@ -31600,12 +31966,6 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
-
msgid "Receive any notifications from GitLab."
msgstr ""
@@ -31639,6 +31999,9 @@ msgstr ""
msgid "Reconfigure"
msgstr ""
+msgid "Recover password"
+msgstr ""
+
msgid "Recovery Codes"
msgstr ""
@@ -31808,9 +32171,6 @@ msgstr ""
msgid "Related feature flags"
msgstr ""
-msgid "Related incidents or issues"
-msgstr ""
-
msgid "Related issues"
msgstr ""
@@ -31824,6 +32184,9 @@ msgid "Release"
msgid_plural "Releases"
msgstr[0] ""
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr ""
+
msgid "Release assets"
msgstr ""
@@ -31896,6 +32259,9 @@ 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 ""
@@ -31959,12 +32325,6 @@ msgstr ""
msgid "Remove assignee"
msgstr "移除指派人"
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
-
msgid "Remove avatar"
msgstr ""
@@ -32106,12 +32466,6 @@ msgstr ""
msgid "Removed an issue from an epic."
msgstr ""
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
-
msgid "Removed group can not be restored!"
msgstr ""
@@ -32160,9 +32514,6 @@ msgstr ""
msgid "Removes an issue from an epic."
msgstr ""
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
-
msgid "Removes parent epic %{epic_ref}."
msgstr ""
@@ -32271,6 +32622,9 @@ msgstr ""
msgid "Reply…"
msgstr ""
+msgid "Report Finding not found"
+msgstr ""
+
msgid "Report abuse"
msgstr ""
@@ -32283,6 +32637,9 @@ 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 ""
@@ -32435,6 +32792,9 @@ msgstr ""
msgid "Reports|Vulnerability Name"
msgstr ""
+msgid "Reports|metrics report"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -32626,15 +32986,6 @@ msgstr "申請權é™"
msgid "Request a new one"
msgstr ""
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
-
msgid "Request data is too large"
msgstr ""
@@ -32659,24 +33010,12 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
-
msgid "Requested design version does not exist."
msgstr ""
msgid "Requested review"
msgstr ""
-msgid "Requested review. Your attention request was removed."
-msgstr ""
-
msgid "Requested states are invalid"
msgstr ""
@@ -32751,6 +33090,9 @@ msgstr ""
msgid "Resend Request"
msgstr ""
+msgid "Resend confirmation e-mail"
+msgstr ""
+
msgid "Resend confirmation email"
msgstr ""
@@ -32895,10 +33237,10 @@ msgstr ""
msgid "Retry"
msgstr ""
-msgid "Retry downstream pipeline"
+msgid "Retry all failed or cancelled jobs"
msgstr ""
-msgid "Retry failed jobs"
+msgid "Retry downstream pipeline"
msgstr ""
msgid "Retry job"
@@ -32999,12 +33341,6 @@ msgstr ""
msgid "RightSidebar|Issue email"
msgstr ""
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
-
msgid "Roadmap"
msgstr ""
@@ -33080,6 +33416,10 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] ""
+
msgid "Runners|%{percentage} spot."
msgstr ""
@@ -33133,6 +33473,9 @@ msgstr ""
msgid "Runners|Associated with one or more projects"
msgstr ""
+msgid "Runners|Available"
+msgstr ""
+
msgid "Runners|Available to all projects"
msgstr ""
@@ -33296,6 +33639,9 @@ msgstr ""
msgid "Runners|Online:"
msgstr ""
+msgid "Runners|Outdated"
+msgstr ""
+
msgid "Runners|Pause from accepting jobs"
msgstr ""
@@ -33318,6 +33664,9 @@ msgstr ""
msgid "Runners|Protected"
msgstr ""
+msgid "Runners|Recommended"
+msgstr ""
+
msgid "Runners|Register a group runner"
msgstr ""
@@ -33426,6 +33775,9 @@ 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 ""
@@ -33484,9 +33836,18 @@ 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|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 ""
@@ -33532,6 +33893,9 @@ msgstr ""
msgid "Runners|active"
msgstr ""
+msgid "Runners|available"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -33547,6 +33911,9 @@ msgstr ""
msgid "Runners|paused"
msgstr ""
+msgid "Runners|recommended"
+msgstr ""
+
msgid "Runners|shared"
msgstr ""
@@ -33562,6 +33929,9 @@ msgstr ""
msgid "Runners|upgrade recommended"
msgstr ""
+msgid "Runner|Owner"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -33604,6 +33974,9 @@ msgstr ""
msgid "SHA256"
msgstr ""
+msgid "SSH Fingerprints"
+msgstr ""
+
msgid "SSH Key"
msgstr ""
@@ -33613,6 +33986,9 @@ 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 ""
@@ -33691,6 +34067,21 @@ msgstr ""
msgid "Saving project."
msgstr ""
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr ""
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr ""
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr ""
+
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
msgstr ""
@@ -33999,6 +34390,12 @@ msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
+msgid "SearchToken|Assignee"
+msgstr ""
+
+msgid "SearchToken|Reviewer"
+msgstr ""
+
msgid "Searching by both author and message is currently not supported."
msgstr ""
@@ -34059,6 +34456,9 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
+msgid "Security Finding not found"
+msgstr ""
+
msgid "Security dashboard"
msgstr ""
@@ -34332,6 +34732,12 @@ 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 ""
@@ -34497,6 +34903,9 @@ 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 group"
msgstr ""
@@ -34515,9 +34924,6 @@ msgstr ""
msgid "SecurityOrchestration|This project"
msgstr ""
-msgid "SecurityOrchestration|This project does not contain any security policies."
-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 ""
@@ -34674,6 +35080,9 @@ msgstr ""
msgid "SecurityReports|Hide dismissed"
msgstr ""
+msgid "SecurityReports|Image"
+msgstr ""
+
msgid "SecurityReports|Issue Created"
msgstr ""
@@ -34728,6 +35137,15 @@ 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 ""
@@ -35082,9 +35500,6 @@ msgstr ""
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr ""
-msgid "Selected projects"
-msgstr ""
-
msgid "Selected tag is already in use. Choose another option."
msgstr ""
@@ -35268,9 +35683,6 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
-msgid "Services"
-msgstr ""
-
msgid "Session ID"
msgstr ""
@@ -35286,9 +35698,6 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "為賬號添加壹個用於推é€æˆ–拉å–çš„ %{protocol} 密碼。"
-msgid "Set access permissions for this token."
-msgstr ""
-
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
msgstr ""
@@ -35771,7 +36180,7 @@ msgstr ""
msgid "Showing version #%{versionNumber}"
msgstr ""
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr ""
msgid "Side-by-side"
@@ -35858,6 +36267,9 @@ msgstr ""
msgid "Sign-in count:"
msgstr ""
+msgid "Sign-in failed because %{error}."
+msgstr ""
+
msgid "Sign-in page"
msgstr ""
@@ -35867,6 +36279,9 @@ msgstr ""
msgid "Sign-in text"
msgstr ""
+msgid "Sign-in using %{provider} auth failed"
+msgstr ""
+
msgid "Sign-out page URL"
msgstr ""
@@ -36101,9 +36516,6 @@ msgstr ""
msgid "Solution"
msgstr ""
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
-
msgid "Some changes are not shown"
msgstr ""
@@ -37220,9 +37632,6 @@ msgstr ""
msgid "Succeeded"
msgstr ""
-msgid "Successful purchase image"
-msgstr ""
-
msgid "Successfully activated"
msgstr ""
@@ -37566,9 +37975,6 @@ msgstr ""
msgid "Support page URL"
msgstr ""
-msgid "Survey Response"
-msgstr ""
-
msgid "Surveys|Delighted"
msgstr ""
@@ -37671,6 +38077,9 @@ msgstr ""
msgid "System output"
msgstr ""
+msgid "System started"
+msgstr ""
+
msgid "Table of Contents"
msgstr ""
@@ -37743,6 +38152,9 @@ msgstr ""
msgid "TagsPage|Cancel, keep tag"
msgstr ""
+msgid "TagsPage|Create release"
+msgstr ""
+
msgid "TagsPage|Create tag"
msgstr ""
@@ -37761,7 +38173,7 @@ msgstr ""
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
msgstr ""
-msgid "TagsPage|Edit release notes"
+msgid "TagsPage|Edit release"
msgstr ""
msgid "TagsPage|Existing branch name, tag, or commit SHA"
@@ -37860,9 +38272,6 @@ msgstr ""
msgid "Task list"
msgstr ""
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
-
msgid "TasksToBeDone|Create/import code into a project (repository)"
msgstr ""
@@ -38265,9 +38674,6 @@ msgstr ""
msgid "Thank you for your business."
msgstr ""
-msgid "Thank you for your feedback!"
-msgstr ""
-
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
msgstr ""
@@ -38553,9 +38959,6 @@ 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 complete successfully."
-msgstr ""
-
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
msgstr ""
@@ -38715,6 +39118,9 @@ 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 ""
@@ -38829,6 +39235,9 @@ msgstr ""
msgid "There are no archived test cases"
msgstr ""
+msgid "There are no changed labels"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -38901,6 +39310,9 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
+msgid "There are unsubmitted review comments."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -39003,9 +39415,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
-msgid "There was an error %{message} to-do item."
-msgstr ""
-
msgid "There was an error adding a To Do."
msgstr ""
@@ -39084,9 +39493,6 @@ msgstr ""
msgid "There was an error removing the e-mail."
msgstr ""
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
-
msgid "There was an error resetting user pipeline minutes."
msgstr ""
@@ -39138,9 +39544,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -39321,6 +39724,9 @@ 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 ""
@@ -39678,6 +40084,12 @@ msgstr ""
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
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 ""
@@ -39990,6 +40402,9 @@ 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 ""
@@ -40070,9 +40485,6 @@ msgstr ""
msgid "To add the entry manually, provide the following details to the application on your phone."
msgstr ""
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
-
msgid "To complete registration, we need additional details from you."
msgstr ""
@@ -40148,7 +40560,7 @@ msgstr ""
msgid "To learn more about this project, read %{link_to_wiki}"
msgstr ""
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
+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."
@@ -40382,6 +40794,9 @@ msgstr ""
msgid "TopNav|Go back"
msgstr ""
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr ""
+
msgid "Topic %{topic_name} was successfully created."
msgstr ""
@@ -40688,6 +41103,9 @@ 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 ""
@@ -40772,6 +41190,9 @@ msgstr ""
msgid "Type"
msgstr ""
+msgid "Type to search"
+msgstr ""
+
msgid "U2F Devices (%{length})"
msgstr ""
@@ -40892,6 +41313,9 @@ 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 ""
@@ -40955,6 +41379,9 @@ 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 ""
@@ -41000,9 +41427,6 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
-msgid "Unknown screen"
-msgstr ""
-
msgid "Unknown user"
msgstr ""
@@ -41195,9 +41619,6 @@ msgstr ""
msgid "Updating"
msgstr ""
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
-
msgid "Updating…"
msgstr ""
@@ -41225,6 +41646,9 @@ msgstr ""
msgid "Upload a private key for your certificate"
msgstr ""
+msgid "Upload could not be deleted."
+msgstr ""
+
msgid "Upload file"
msgstr "上傳文件"
@@ -41249,9 +41673,6 @@ msgstr ""
msgid "Upstream"
msgstr ""
-msgid "Uptime"
-msgstr ""
-
msgid "Upvotes"
msgstr ""
@@ -41312,10 +41733,10 @@ msgstr ""
msgid "UsageQuota|Dependency proxy"
msgstr ""
-msgid "UsageQuota|File attachments and smaller design graphics."
+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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
+msgid "UsageQuota|File attachments and smaller design graphics."
msgstr ""
msgid "UsageQuota|Git repository."
@@ -41387,6 +41808,9 @@ 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 ""
@@ -41414,6 +41838,18 @@ 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}Group settings &gt; Usage quotas%{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. View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{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 ""
@@ -41684,6 +42120,10 @@ msgstr ""
msgid "Used"
msgstr ""
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] ""
+
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
@@ -41777,6 +42217,9 @@ msgstr ""
msgid "User was successfully removed from project."
msgstr ""
+msgid "User was successfully unbanned."
+msgstr ""
+
msgid "User was successfully updated."
msgstr ""
@@ -41885,6 +42328,9 @@ msgstr ""
msgid "UserProfile|Contributed projects"
msgstr "è²¢ç»çš„專案"
+msgid "UserProfile|Copy user ID"
+msgstr ""
+
msgid "UserProfile|Edit profile"
msgstr ""
@@ -41966,6 +42412,9 @@ msgstr ""
msgid "UserProfile|Unconfirmed user"
msgstr ""
+msgid "UserProfile|User ID: %{id}"
+msgstr ""
+
msgid "UserProfile|View all"
msgstr ""
@@ -42131,10 +42580,6 @@ msgstr ""
msgid "ValueStreamAnalytics|%{stageCount}+ items"
msgstr ""
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
-
msgid "ValueStreamAnalytics|%{value}M"
msgstr ""
@@ -42189,10 +42634,16 @@ msgstr ""
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
msgstr ""
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
+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 %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+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"
@@ -42282,6 +42733,12 @@ 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 ""
@@ -42888,6 +43345,9 @@ 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 ""
@@ -42933,9 +43393,6 @@ msgstr ""
msgid "We recommend a work email address."
msgstr ""
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
-
msgid "We recommend leaving all SAST analyzers enabled"
msgstr ""
@@ -42945,6 +43402,9 @@ 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 ""
@@ -43245,6 +43705,12 @@ 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 ""
@@ -43303,6 +43769,10 @@ 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] ""
+
msgid "When:"
msgstr ""
@@ -43339,6 +43809,12 @@ msgstr ""
msgid "Wiki"
msgstr ""
+msgid "Wiki Page|Rich text"
+msgstr ""
+
+msgid "Wiki Page|Source"
+msgstr ""
+
msgid "Wiki page"
msgstr ""
@@ -43465,12 +43941,6 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
-
msgid "WikiPage|Format"
msgstr ""
@@ -43570,10 +44040,13 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
-msgid "WorkItem|Add"
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
msgstr ""
-msgid "WorkItem|Add a child"
+msgid "WorkItem|Add a task"
+msgstr ""
+
+msgid "WorkItem|Add a title"
msgstr ""
msgid "WorkItem|Add assignee"
@@ -43582,10 +44055,13 @@ msgstr ""
msgid "WorkItem|Add assignees"
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 work item? This action cannot be reversed."
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
msgstr ""
msgid "WorkItem|Assignee"
@@ -43598,6 +44074,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Child removed"
+msgstr ""
+
msgid "WorkItem|Closed"
msgstr ""
@@ -43610,24 +44089,39 @@ msgstr ""
msgid "WorkItem|Create work item"
msgstr ""
-msgid "WorkItem|Delete work item"
+msgid "WorkItem|Delete task"
msgstr ""
msgid "WorkItem|Expand child items"
msgstr ""
+msgid "WorkItem|Introducing tasks"
+msgstr ""
+
+msgid "WorkItem|Learn about tasks"
+msgstr ""
+
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
msgstr ""
msgid "WorkItem|Open"
msgstr ""
+msgid "WorkItem|Remove"
+msgstr ""
+
msgid "WorkItem|Select type"
msgstr ""
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr ""
+
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
msgstr ""
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr ""
+
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
msgstr ""
@@ -43637,18 +44131,39 @@ 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 work item. Please try again."
msgstr ""
+msgid "WorkItem|Task deleted"
+msgstr ""
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr ""
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr ""
+
msgid "WorkItem|Type"
msgstr ""
+msgid "WorkItem|Undo"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
msgid "WorkItem|Work item deleted"
msgstr ""
+msgid "WorkItem|work items"
+msgstr ""
+
msgid "Would you like to create a new branch?"
msgstr ""
@@ -43929,8 +44444,9 @@ 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 have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] ""
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -43938,9 +44454,6 @@ msgstr ""
msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
-
msgid "You can invite another group to %{project_name}."
msgstr ""
@@ -43995,7 +44508,7 @@ 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 this namespace can start a trial or upgrade to a paid tier."
+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."
@@ -44007,15 +44520,9 @@ msgstr ""
msgid "You cannot approve your own deployment."
msgstr ""
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
-
msgid "You cannot combine replace_ids with add_ids or remove_ids"
msgstr ""
-msgid "You cannot edit this timeline event."
-msgstr ""
-
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -44046,11 +44553,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] ""
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -44383,6 +44888,9 @@ 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 ""
@@ -44395,9 +44903,6 @@ msgstr ""
msgid "YouTube"
msgstr ""
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
-
msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
@@ -44410,7 +44915,7 @@ 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}. After that date, you cannot create issues or merge requests, or use many other features."
+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}."
@@ -44584,6 +45089,14 @@ msgstr ""
msgid "Your first project"
msgstr ""
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+msgstr[0] ""
+
+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] ""
+
msgid "Your groups"
msgstr ""
@@ -44680,9 +45193,6 @@ msgstr ""
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
msgstr ""
-msgid "Your response has been recorded."
-msgstr ""
-
msgid "Your search didn't match any commits."
msgstr ""
@@ -44705,9 +45215,8 @@ msgid "Your subscription has %{remaining_seat_count} out of %{total_seat_count}
msgid_plural "Your subscription has %{remaining_seat_count} out of %{total_seat_count} seats remaining."
msgstr[0] ""
-msgid "Your subscription will expire in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+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 ""
@@ -44858,6 +45367,9 @@ msgstr ""
msgid "assign yourself"
msgstr ""
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr ""
+
msgid "at"
msgstr ""
@@ -44937,6 +45449,9 @@ 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 ""
@@ -45037,9 +45552,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} 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 ""
@@ -45055,6 +45576,9 @@ msgstr ""
msgid "ciReport|All clusters"
msgstr ""
+msgid "ciReport|All images"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
@@ -45318,6 +45842,9 @@ msgstr ""
msgid "ciReport|is loading, errors when loading results"
msgstr ""
+msgid "ci_database"
+msgstr ""
+
msgid "closed"
msgstr ""
@@ -45345,6 +45872,9 @@ msgstr ""
msgid "compliance violation has already been recorded"
msgstr ""
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr ""
+
msgid "contacts can only be added to root groups"
msgstr ""
@@ -45384,9 +45914,6 @@ msgstr ""
msgid "data"
msgstr ""
-msgid "database"
-msgstr ""
-
msgid "date must not be after 9999-12-31"
msgstr ""
@@ -45479,6 +46006,9 @@ msgstr ""
msgid "example.com"
msgstr ""
+msgid "exceeds maximum length (100 usernames)"
+msgstr ""
+
msgid "exceeds the %{max_value_length} character limit"
msgstr ""
@@ -45559,9 +46089,6 @@ msgstr ""
msgid "group members"
msgstr ""
-msgid "group's CI/CD settings."
-msgstr ""
-
msgid "groups"
msgstr ""
@@ -45611,6 +46138,9 @@ msgstr ""
msgid "i18n|%{language} (%{percent_translated}%% translated)"
msgstr ""
+msgid "if"
+msgstr ""
+
msgid "image diff"
msgstr ""
@@ -45786,6 +46316,9 @@ msgstr ""
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
+msgid "main_database"
+msgstr ""
+
msgid "manual"
msgstr ""
@@ -45827,12 +46360,6 @@ msgstr ""
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
-
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
msgstr ""
@@ -45948,9 +46475,6 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
-
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -45960,9 +46484,6 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
-
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
@@ -45997,9 +46518,6 @@ msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
msgstr[0] ""
-msgid "mrWidget|Merge"
-msgstr ""
-
msgid "mrWidget|Merge blocked: all required approvals must be given."
msgstr ""
@@ -46033,9 +46551,6 @@ msgstr ""
msgid "mrWidget|Merged by"
msgstr ""
-msgid "mrWidget|Merges changes into"
-msgstr ""
-
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -46120,21 +46635,9 @@ msgstr ""
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
msgstr ""
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
-
msgid "mrWidget|The source branch is %{link} the target branch"
msgstr ""
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
@@ -46446,6 +46949,9 @@ msgstr ""
msgid "repository:"
msgstr ""
+msgid "role's base access level does not match the access level of the membership"
+msgstr ""
+
msgid "satisfied"
msgstr ""
@@ -46458,6 +46964,9 @@ msgstr ""
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 ""
@@ -46569,13 +47078,13 @@ msgstr ""
msgid "the correct format."
msgstr ""
-msgid "the following epic(s)"
+msgid "the following epics"
msgstr ""
-msgid "the following incident(s) or issue(s)"
+msgid "the following incidents or issues"
msgstr ""
-msgid "the following issue(s)"
+msgid "the following issues"
msgstr ""
msgid "the wiki"
@@ -46596,6 +47105,9 @@ msgstr ""
msgid "toggle collapse"
msgstr ""
+msgid "total must be less than or equal to %{size}"
+msgstr ""
+
msgid "triggered"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 98f774356e0..8b5ac668122 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-07-14 17:06\n"
+"PO-Revision-Date: 2022-08-12 19:01\n"
msgid " %{start} to %{end}"
msgstr " %{start} 到 %{end}"
@@ -47,7 +47,7 @@ msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr " 或 %{emphasisStart}ï¼åˆä½µè«‹æ±‚ID%{emphasisEnd}"
msgid " or %{emphasisStart}#id%{emphasisEnd}"
-msgstr ""
+msgstr " 或 %{emphasisStart} #id%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr " 或 %{emphasisStart} #å•é¡ŒID%{emphasisEnd}"
@@ -207,7 +207,7 @@ msgstr[0] "%d 次失敗"
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
+msgstr[0] "%d 個失敗的安全性作業"
msgid "%d file"
msgid_plural "%d files"
@@ -247,7 +247,7 @@ msgstr[0] "用標籤æˆåŠŸåŒ¯å…¥ %d 個議題"
msgid "%d job"
msgid_plural "%d jobs"
-msgstr[0] ""
+msgstr[0] "%d 個工作"
msgid "%d layer"
msgid_plural "%d layers"
@@ -311,7 +311,7 @@ msgstr[0] "剩餘 %d"
msgid "%d reply"
msgid_plural "%d replies"
-msgstr[0] ""
+msgstr[0] "%d 則回覆"
msgid "%d second"
msgid_plural "%d seconds"
@@ -319,7 +319,7 @@ msgstr[0] "%d秒"
msgid "%d stage"
msgid_plural "%d stages"
-msgstr[0] ""
+msgstr[0] "%d 個階段"
msgid "%d star"
msgid_plural "%d stars"
@@ -385,6 +385,9 @@ msgstr "%{actionText} & é‡æ–°é–‹å•Ÿ %{noteable}"
msgid "%{address} is an invalid IP address range"
msgstr "%{address}是無效的 IP ä½å€ç¯„åœ"
+msgid "%{attribute} must be between %{min} and %{max}"
+msgstr "%{attribute} 必須介於 %{min} 和 %{max}之間"
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
msgstr "%{author_link}將 %{original_issue}複製到 %{new_issue}。"
@@ -430,9 +433,9 @@ msgstr "ç”± %{commit_author_link} æ–¼ %{commit_authored_timeago} å»ºç«‹åŠ %{com
msgid "%{completedCount} completed weight"
msgstr "%{completedCount} 完æˆé‡æ¬Š"
-msgid "%{completedCount} of %{count} task completed"
-msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] "%{completedCount}/%{count} 的任務已完æˆ"
+msgid "%{completedCount} of %{count} checklist item completed"
+msgid_plural "%{completedCount} of %{count} checklist items completed"
+msgstr[0] "清單中的 %{completedCount}/%{count} 項目已完æˆ"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "完æˆçš„權é‡%{completedWeight}%{totalWeight}"
@@ -587,7 +590,7 @@ msgid "%{group_name} is approaching the limit of available seats"
msgstr "%{group_name} 接近å¯ç”¨å¸­ä½çš„é™åˆ¶"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
-msgstr "%{group_name} 使用群組管ç†å¸³æˆ¶ã€‚您需è¦å»ºç«‹ä¸€å€‹æ–°çš„ GitLab 帳戶,該帳戶將由 %{group_name} 群組管ç†ã€‚"
+msgstr "%{group_name} 使用群組管ç†å¸³è™Ÿã€‚您需è¦å»ºç«‹ä¸€å€‹æ–°çš„ GitLab 帳號,該帳號將由 %{group_name} 群組管ç†ã€‚"
msgid "%{group_name}&%{epic_iid} &middot; created %{epic_created} by %{author}"
msgstr "%{group_name}&%{epic_iid} &middot; %{epic_created} 由%{author}創建"
@@ -607,6 +610,9 @@ msgstr "%{integrations_link_start}æ•´åˆ%{link_end}能讓你將第三方應用ç¨
msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} 將被刪除ï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
+msgid "%{issuable_class_name} doesn't exist or you don't have permission to add timelog to it."
+msgstr "%{issuable_class_name} ä¸å­˜åœ¨ï¼Œæˆ–您沒有權é™å°‡æ™‚間日誌加入其中。"
+
msgid "%{issuable}(s) already assigned"
msgstr "%{issuable} 已分é…"
@@ -635,13 +641,13 @@ msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgstr "%{labelStart}崩潰地å€ï¼š%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{crash_state}"
-msgstr ""
+msgstr "%{labelStart}故障狀態:%{labelEnd} %{crash_state}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}崩潰狀態:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Crash Type:%{labelEnd} %{crash_type}"
-msgstr ""
+msgstr "%{labelStart}故障類型:%{labelEnd} %{crash_type}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}證據:%{labelEnd} %{evidence}"
@@ -658,6 +664,9 @@ msgstr "%{labelStart}方法:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
msgstr "%{labelStart}命å空間:%{labelEnd} %{namespace}"
+msgid "%{labelStart}Project:%{labelEnd} %{project}"
+msgstr "%{labelStart}專案:%{labelEnd} %{project}"
+
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}掃æ器:%{labelEnd} %{scanner}"
@@ -670,15 +679,15 @@ msgstr "%{labelStart}åš´é‡ç¨‹åº¦ï¼š%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgstr "%{labelStart}工具:%{labelEnd} %{reportType}"
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr "%{labelStart}網å€ï¼š%{labelEnd} %{url}"
+
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr "%{labelStart}未更改的回應:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} 無法使用"
-msgid "%{learn_more_link}."
-msgstr "%{learn_more_link}。"
-
msgid "%{lessThan} 1 hour"
msgstr "%{lessThan} 1 å°æ™‚"
@@ -791,6 +800,18 @@ msgstr "%{openedEpics} 個開放,%{closedEpics} 個關閉"
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 "%{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}以ç²å¾—更多席次。"
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each personal project. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} è¦æª¢è¦–和管ç†æˆå“¡ï¼Œè«‹æŸ¥çœ‹æ¯å€‹å€‹äººå°ˆæ¡ˆçš„æˆå“¡é é¢ã€‚我們建議您%{link_start}將您的專案移動到一個群組%{link_end},以便您å¯ä»¥è¼•é¬†ç®¡ç†ä½¿ç”¨è€…和功能。"
+
+msgid "%{over_limit_message} To view and manage members, check the members page for each project in your namespace. We recommend you %{link_start}move your projects to a group%{link_end} so you can easily manage users and features."
+msgstr "%{over_limit_message} è¦æª¢è¦–和管ç†æˆå“¡ï¼Œè«‹æª¢æŸ¥æ‚¨å‘½å空間中æ¯å€‹å°ˆæ¡ˆçš„æˆå“¡é é¢ã€‚我們建議您%{link_start}將您的專案移動到一個群組%{link_end},以便您å¯ä»¥è¼•é¬†ç®¡ç†ä½¿ç”¨è€…和功能。"
+
msgid "%{percentageUsed}%% used"
msgstr "%{percentageUsed}%% 已使用"
@@ -844,10 +865,10 @@ msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}att
msgstr "%{retryButtonStart}è«‹é‡è©¦%{retryButtonEnd}或%{newFileButtonStart}附加一個新的檔案%{newFileButtonEnd}。"
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 ""
+msgstr "%{rotation} 已與其餘åƒèˆ‡è€…é‡æ–°è¨ˆç®—。 %{rotation_link}的新設置。建議您è¯ç¹«ç•¶å‰çš„待命響應者,以確ä¿å¾…命覆蓋的連續性。"
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 ""
+msgstr "%{rotation} 已與其餘åƒèˆ‡è€…é‡æ–°è¨ˆç®—。 %{rotation}的新設置。建議您è¯ç¹«ç•¶å‰çš„待命響應者,以確ä¿å¾…命覆蓋的連續性。"
msgid "%{runner} created %{timeago}"
msgstr "%{runner} 建立 %{timeago}"
@@ -860,12 +881,20 @@ msgstr "%{seconds} 秒"
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
-msgstr[0] ""
+msgstr[0] "此專案未啟用%{securityScanner} 。 %{linkStart}更多信æ¯%{linkEnd}"
msgid "%{securityScanner} result is not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
msgstr[0] "%{securityScanner}並無çµæžœï¼Œå› ç‚ºè‡ªå•Ÿç”¨ä»¥ä¾†å°šæœªåŸ·è¡Œæµæ°´ç·šã€‚%{linkStart}執行æµæ°´ç·š%{linkEnd}"
+msgid "%{selectedLabelsCount} label"
+msgid_plural "%{selectedLabelsCount} labels"
+msgstr[0] "%{selectedLabelsCount} 個標籤"
+
+msgid "%{selectedProjectsCount} project"
+msgid_plural "%{selectedProjectsCount} projects"
+msgstr[0] "%{selectedProjectsCount} 個專案"
+
msgid "%{size} %{unit}"
msgstr "%{size} %{unit}"
@@ -901,10 +930,7 @@ 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 ""
-
-msgid "%{strongStart}Need your attention%{strongEnd} are the merge requests that need your help to move forward, as an assignee or reviewer."
-msgstr "%{strongStart}請注æ„%{strongEnd} ,因您為指派人或審閱者,此åˆä½µè«‹æ±‚需您的åŒæ„æ–¹å¯ç¹¼çºŒä¸‹ä¸€æ­¥"
+msgstr "%{strongOpen}警告:%{strongClose} SAML 群組連çµæœƒä½¿ GitLab 自動從群組中移除æˆå“¡ã€‚"
msgid "%{strongStart}Tip:%{strongEnd} You can also check out merge requests locally. %{linkStart}Learn more.%{linkEnd}"
msgstr "%{strongStart}æ示:%{strongEnd} 您也å¯ä»¥åœ¨æœ¬åœ°ç«¯æŸ¥çœ‹åˆä½µè«‹æ±‚。%{linkStart}了解更多%{linkEnd}"
@@ -923,7 +949,7 @@ msgstr[0] "å…±%{strong_start}%{count}æ¢æ ¸å‡†è¦å‰‡%{strong_end}需è¦å…·æ¬Šé™
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[0] "需%{strong_start}%{count}ä½æœ‰æ¬Šé™ä½¿ç”¨è€…%{strong_end}核准æ‰å¯åˆä½µã€‚"
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."
@@ -933,7 +959,7 @@ msgid "%{strong_start}%{human_size}%{strong_end} Project Storage"
msgstr "%{strong_start}%{human_size}%{strong_end} 專案儲存"
msgid "%{strong_start}%{project_name}%{strong_end} is a personal project, so you can’t upgrade to a paid plan or start a free trial to lift these limits. We recommend %{move_to_group_link}moving this project to a group%{end_link} to unlock these options. You can %{manage_members_link}manage the members of this project%{end_link}, but don’t forget that all unique members in your personal namespace %{strong_start}%{namespace_name}%{strong_end} count towards total seats in use."
-msgstr ""
+msgstr "%{strong_start}%{project_name}%{strong_end} 是個人專案,因此您無法å‡ç´šåˆ°ä»˜è²»è¨ˆåŠƒæˆ–開始å…費試用來解除這些é™åˆ¶ã€‚我們建議 %{move_to_group_link}將此專案移至群組%{end_link} 以解鎖這些é¸é …。您å¯ä»¥ %{manage_members_link}管ç†æ­¤å°ˆæ¡ˆçš„æˆå“¡%{end_link},但ä¸è¦å¿˜è¨˜æ‚¨å€‹äººå‘½å空間 %{strong_start}%{namespace_name}%{strong_end} 內的所有唯一æˆå“¡éƒ½æœƒè¨ˆå…¥ä½¿ç”¨çš„總席次。"
msgid "%{strong_start}%{release_count}%{strong_end} Release"
msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
@@ -971,7 +997,7 @@ msgid "%{timebox_type} must have a start and due date"
msgstr "%{timebox_type} 必須有開始日期和截止日期"
msgid "%{time} UTC"
-msgstr ""
+msgstr "%{time} UTC"
msgid "%{title} %{operator} %{threshold}"
msgstr "%{title} %{operator} %{threshold}"
@@ -1007,7 +1033,7 @@ msgid "%{userName}'s avatar"
msgstr "%{userName} 的大頭貼"
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) 從 %{rotation} in %{schedule} in %{project}刪除。 "
msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project_link}: "
msgstr "%{user_name} (%{user_username}) 已從 %{project_link}çš„å‡ç´šç­–略中刪除 "
@@ -1022,7 +1048,7 @@ 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 ""
+msgstr "%{username} 在您的 %{host} GitLab 實例上請求了一個使用者帳號:"
msgid "%{username}'s avatar"
msgstr "%{username} 的大頭貼"
@@ -1031,7 +1057,7 @@ msgid "%{user} created a merge request: %{mr_link}"
msgstr "%{user} 建立了åˆä½µè«‹æ±‚: %{mr_link}"
msgid "%{user} created an epic: %{epic_link}"
-msgstr ""
+msgstr "%{user} 建立了å²è©©ï¼š %{epic_link}"
msgid "%{user} created an issue: %{issue_link}"
msgstr "%{user} 建立了一個議題: %{issue_link}"
@@ -1055,37 +1081,37 @@ msgid "%{widget} options"
msgstr "%{widget} é¸é …"
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
-msgstr ""
+msgstr "%{wildcards_link_start}è¬ç”¨å­—å…ƒ%{wildcards_link_end} ä¾‹å¦‚æ”¯æ´ %{code_tag_start}v*%{code_tag_end} 或 %{code_tag_start}*-release%{code_tag_end}。"
msgid "'%{data}' at %{location} does not match format: %{format}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' ä¸ç¬¦åˆæ ¼å¼ï¼š%{format}"
msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' ä¸ç¬¦åˆæ¨¡å¼ï¼š%{pattern}"
msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' 無效: error_type=%{type}"
msgid "'%{data}' at %{location} is not of type: %{type}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' ä¸å±¬æ–¼ï¼š %{type}"
msgid "'%{data}' at %{location} is not one of: %{enum}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' ä¸æ˜¯ä»»ä½•ä¸€ç¨®ï¼š %{enum}"
msgid "'%{data}' at %{location} is not: %{const}"
-msgstr ""
+msgstr "%{location}上的 '%{data}' ä¸æ˜¯ï¼š%{const}"
msgid "'%{level}' is not a valid visibility level"
msgstr "「%{level}ã€ä¸æ˜¯æœ‰æ•ˆçš„å¯è¦‹æ€§ç´šåˆ¥"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "'%{name}' 價值æµå·²å‰µå»º"
msgid "'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "'%{name}' 價值æµå·²åˆªé™¤"
msgid "'%{name}' Value Stream saved"
-msgstr ""
+msgstr "'%{name}' 價值æµå·²å„²å­˜"
msgid "'%{source}' is not a import source"
msgstr "「%{source}ã€ä¸æ˜¯ä¸€å€‹åŒ¯å…¥ä¾†æº"
@@ -1101,10 +1127,10 @@ msgid "(%{mrCount} merged)"
msgstr "(%{mrCount} å·²åˆä½µ)"
msgid "(%{value}) has already been taken"
-msgstr ""
+msgstr "(%{value}) 已經被使用"
msgid "(+%{count}&nbsp;rules)"
-msgstr ""
+msgstr "(+%{count}&nbsp;æ¢è¦å‰‡)"
msgid "(Group Managed Account)"
msgstr "(由群組管ç†çš„帳號)"
@@ -1113,7 +1139,7 @@ msgid "(No changes)"
msgstr "(無變更)"
msgid "(UTC %{offset}) %{timezone}"
-msgstr ""
+msgstr "(UTC %{offset}) %{timezone}"
msgid "(check progress)"
msgstr "(檢查進度)"
@@ -1131,13 +1157,13 @@ msgid "(max size 15 MB)"
msgstr "(最大15 MB)"
msgid "(optional)"
-msgstr ""
+msgstr "(é¸é …)"
msgid "(removed)"
msgstr "(已刪除)"
msgid "(revoked)"
-msgstr ""
+msgstr "(已撤回)"
msgid "(squashes %d commit)"
msgid_plural "(squashes %d commits)"
@@ -1147,13 +1173,13 @@ msgid "(this user)"
msgstr "(此使用者)"
msgid "(we need your current password to confirm your changes)"
-msgstr ""
+msgstr "(我們需è¦æ‚¨ç•¶å‰å¯†ç¢¼ä¾†ç¢ºèªæ‚¨çš„資料更改)"
msgid "* All times are in UTC unless specified"
-msgstr ""
+msgstr "* 除éžå¦æœ‰èªªæ˜Žï¼Œå¦å‰‡æ‰€æœ‰æ™‚é–“å‡ä»¥ UTC 為準"
msgid "*Required"
-msgstr ""
+msgstr "*å¿…å¡«"
msgid "+ %{amount} more"
msgstr "+ 其餘 %{amount} 項"
@@ -1169,37 +1195,37 @@ msgstr "+ 其餘 %{numberOfHiddenAssignees} 項"
msgid "+%d more"
msgid_plural "+%d more"
-msgstr[0] ""
+msgstr[0] "+%d 更多"
msgid "+%{more_assignees_count}"
-msgstr ""
+msgstr "+%{more_assignees_count}"
msgid "+%{more_assignees_count} more assignees"
-msgstr ""
+msgstr "+%{more_assignees_count} å指派人"
msgid "+%{more_reviewers_count}"
-msgstr ""
+msgstr "+%{more_reviewers_count}"
msgid "+%{more_reviewers_count} more reviewers"
-msgstr ""
+msgstr "+%{more_reviewers_count} å審閱者"
msgid "+%{tags} more"
-msgstr ""
+msgstr "+%{tags} 個"
msgid ", "
-msgstr ""
+msgstr ", "
msgid ", or "
msgstr "ã€æˆ– "
msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status})"
-msgstr ""
+msgstr "- %{policy_name} (在 %{elapsed_time} 分é˜å¾Œç™¼å‡ºé€šçŸ¥, 除éžç‹€æ…‹ç‚º %{status})"
msgid "- Add or remove a user."
msgstr "- 增加或移除使用者"
msgid "- Available to run jobs."
-msgstr ""
+msgstr "å¯ç”¨æ–¼åŸ·è¡Œä»»å‹™ã€‚"
msgid "- Create or close an issue."
msgstr "- 新建或關閉議題"
@@ -1234,10 +1260,10 @@ msgid "- View the last_activity_at attribute for %{project_name} using the Proje
msgstr "- 使用專案 API %{projects_api_link} 查看 %{project_name} 的 last_activity_at 屬性。"
msgid "- of - issues closed"
-msgstr ""
+msgstr "-/- 議題已關閉"
msgid "- of - weight completed"
-msgstr ""
+msgstr "完æˆäº† - / - 權é‡"
msgid "- show less"
msgstr "- 顯示較少內容"
@@ -1256,7 +1282,7 @@ msgstr "0 ä½å…ƒçµ„"
msgid "1 Code quality finding"
msgid_plural "%d Code quality findings"
-msgstr[0] ""
+msgstr[0] "%d 個程å¼ç¢¼å“質注æ„點"
msgid "1 Day"
msgid_plural "%d Days"
@@ -1374,15 +1400,9 @@ msgstr "兩步驟驗證"
msgid "2FADevice|Registered On"
msgstr "註冊於"
-msgid "3 days"
-msgstr "3天"
-
msgid "3 hours"
msgstr "3å°æ™‚"
-msgid "30 days"
-msgstr "30 天"
-
msgid "30 minutes"
msgstr "30分é˜"
@@ -1410,9 +1430,6 @@ msgstr "如果您èªç‚ºé€™æ˜¯ä¸€å€‹éŒ¯èª¤ï¼Œè«‹è¯ç¹«æ‚¨çš„ GitLab 管ç†å“¡ã€‚"
msgid "409|There was a conflict with your request."
msgstr "與您的請求有è¡çªã€‚"
-msgid "7 days"
-msgstr "7 天"
-
msgid "8 hours"
msgstr "8å°æ™‚"
@@ -1429,7 +1446,7 @@ msgid "A CI/CD pipeline must run and be successful before merge."
msgstr "åˆä½µå‰ï¼ŒCI/CD æµç¨‹å¿…須先執行æˆåŠŸã€‚"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
-msgstr "GitBook 網站使用 Netlify 來å–代 Gitlab çš„ CI/CD,但ä»ä¿±å‚™å®Œæ•´çš„ GitLab 其他優秀功能"
+msgstr "GitBook 網站使用 Netlify 來å–代 GitLab çš„ CI/CD,但ä»ä¿±å‚™å®Œæ•´çš„ GitLab 其他優秀功能"
msgid "A Gitpod configured Webapplication in Spring and Java"
msgstr "Gitpod é€éŽ Spring 與 Java é…ç½® Web 應用程å¼"
@@ -1447,13 +1464,13 @@ msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is
msgstr "在網域驗證之å‰ï¼Œæˆ‘們無法å–å¾— Encrype SSL 憑證。"
msgid "A Work Item can be a parent or a child, but not both."
-msgstr ""
+msgstr "工作項å¯ä»¥æ˜¯çˆ¶é …或å­é …,但ä¸èƒ½åŒæ™‚是兩者。"
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "使用 AWS Lambdaã€AWS API é–˜é“åŠ GitLab Pages 的基本é é¢å’Œç„¡ä¼ºæœå™¨åŠŸèƒ½"
msgid "A basic template for developing Linux programs using Kotlin Native"
-msgstr ""
+msgstr "一個使用 Kotlin Native 為開發 Linux 程å¼çš„基本範本"
msgid "A complete DevOps platform"
msgstr "一個完整的 DevOps å¹³å°"
@@ -1486,10 +1503,10 @@ msgid "A group represents your organization in GitLab. Groups allow you to manag
msgstr "群組代表您在GitLab中的組織。群組使您å¯ä»¥ç®¡ç†æ•¸å€‹ä½¿ç”¨è€…並跨多個專案進行å”åŒåˆä½œã€‚"
msgid "A job artifact is an archive of files and directories saved by a job when it finishes."
-msgstr ""
+msgstr "作業產出物是作業完æˆå¾Œæ‰€ä¿å­˜çš„檔案與目錄的歸檔。"
msgid "A limit of %{ci_project_subscriptions_limit} subscriptions to or from a project applies."
-msgstr ""
+msgstr "專案é©ç”¨çš„訂閱或被訂閱數é‡ä¸Šé™ç‚º %{ci_project_subscriptions_limit}。"
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 "被組織所採用的管ç†ã€æ“作或技術控制 (å³ä¿éšœæŽªæ–½æˆ–å°ç­–) åŒæ™‚å¯ç‚ºè³‡è¨Šç³»çµ±æ供相等或類似的ä¿è­·ã€‚"
@@ -1513,13 +1530,13 @@ msgid "A new impersonation token has been created."
msgstr "已建立新的身份模擬權æ–。"
msgid "A new personal access token has been created"
-msgstr ""
+msgstr "已建立一個新的個人存å–權æ–"
msgid "A new personal access token, named %{token_name}, has been created."
-msgstr ""
+msgstr "已建立一個新的個人存å–權æ–,命å為%{token_name}。"
msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
+msgstr "éžç§äººå²è©©ä¸å¯è¢«æŒ‡æ´¾åˆ°ç§äººçˆ¶å²è©©"
msgid "A page with that title already exists"
msgstr "該標題é é¢å·²å­˜åœ¨"
@@ -1528,7 +1545,7 @@ msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but stil
msgstr "ç´” HTML 網站使用 NetLify æ¥å–代 Gitlab çš„ CI/CD,但ä»ä¿±å‚™å®Œæ•´çš„ GitLab 其他優秀功能"
msgid "A platform value can be web, mob or app."
-msgstr ""
+msgstr "å¹³å°å¯ä»¥æ˜¯ webã€mob 或 app."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr "使用 Salesforce Developer 工具開發 Salesforce App 的專案樣æ¿"
@@ -1537,154 +1554,154 @@ msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js
msgstr "使用 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 ""
+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 "專案的存放庫å稱定義其 URL(用於é€éŽç€è¦½å™¨è¨ªå•è©²å°ˆæ¡ˆï¼‰åŠå…¶åœ¨å®‰è£ GitLab 的文件ç£ç¢Ÿä¸Šçš„ä½ç½®ã€‚ %{link_start}了解更多。%{link_end}"
msgid "A quarterly reconciliation is due on %{date}"
-msgstr ""
+msgstr "該季度的帳目核å°è³‡æ–™å°‡æ–¼ %{date}截止"
msgid "A ready-to-go template for use with Android apps"
-msgstr ""
+msgstr "é©ç”¨æ–¼ Android 應用程å¼çš„樣æ¿æº–備就緒"
msgid "A ready-to-go template for use with iOS Swift apps"
-msgstr ""
+msgstr "é©ç”¨æ–¼ iOS Swift 應用程å¼çš„樣æ¿æº–備就緒"
msgid "A rebase is already in progress."
-msgstr ""
+msgstr "é‡è¨‚基底作業已在進行中。"
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
-msgstr ""
+msgstr "你的帳號已被從下列的IP登入: %{ip}"
msgid "A title is required"
-msgstr ""
+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 ""
+msgstr "需è¦å‹•ä½œ: ç²å– GitLab Pages 網域 '%{domain}' çš„ Let's Encrypt 加密證書時出了點å•é¡Œ"
msgid "API"
-msgstr ""
+msgstr "API"
msgid "API Fuzzing"
-msgstr ""
+msgstr "API 模糊測試"
msgid "API Fuzzing Configuration"
-msgstr ""
+msgstr "API 模糊測試é…ç½®"
msgid "API Help"
-msgstr ""
+msgstr "API 說明"
msgid "API Token"
msgstr "API 權æ–"
msgid "API key"
-msgstr ""
+msgstr "API 金鑰"
msgid "API?"
-msgstr ""
+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 ""
+msgstr "API模糊測試é…ç½®"
msgid "APIFuzzing|Base URL of API testing target. For example, http://www.example.com."
-msgstr ""
+msgstr "API測試目標的基本網å€ã€‚例如,http://www.example.com。"
msgid "APIFuzzing|Choose a method"
-msgstr ""
+msgstr "é¸æ“‡ä¸€ç¨®æ–¹æ³•"
msgid "APIFuzzing|Choose a profile"
-msgstr ""
+msgstr "é¸æ“‡å€‹äººè³‡æ–™"
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "é…ç½®HTTP基本身份驗證值。支æŒå…¶ä»–身份驗證方法。 %{linkStart}了解更多%{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 ""
+msgstr "自訂專案的 API 模糊測試設定é¸é …,複製程å¼ç¢¼ç‰‡æ®µåˆ°æ‚¨çš„ .gitlab-ci.yml 檔案,並套用變更。注æ„,這個工具ä¸æœƒè‡ªå‹•æ›´æ–°æ‚¨çš„ .gitlab-ci.yml 檔案。有關進階設定é¸é …的詳情,請åƒé–± %{docsLinkStart}API 模糊測試文件%{docsLinkEnd}。"
msgid "APIFuzzing|Enable authentication"
-msgstr ""
+msgstr "啟用身份驗證"
msgid "APIFuzzing|Enter the name of the CI variable containing the password. For example, $VARIABLE_WITH_PASSWORD."
-msgstr ""
+msgstr "輸入包å«å¯†ç¢¼çš„ CI 變數å稱。例如 $VARIABLE_WITH_PASSWORD。"
msgid "APIFuzzing|Enter the name of the CI variable containing the username. For example, $VARIABLE_WITH_USERNAME."
-msgstr ""
+msgstr "輸入包å«ä½¿ç”¨è€…å稱的 CI 變數å稱。例如 $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 "è¦æ¸¬è©¦çš„ API 的文件路徑或 URL。例如,文件夾/example_fuzz.har。 HAR 文件å¯èƒ½åŒ…å«æ•æ„Ÿä¿¡æ¯ï¼Œä¾‹å¦‚身份驗證令牌(權æ–)ã€API 密鑰和會話 cookie。我們建議您在將 HAR 文件添加到儲存庫之å‰æŸ¥çœ‹å®ƒå€‘的內容。"
msgid "APIFuzzing|File path or URL to OpenAPI specification. For example, folder/openapi.json or http://www.example.com/openapi.json."
-msgstr ""
+msgstr "OpenAPI è¦ç¯„的文件路徑或 URL。例如,文件夾/openapi.json 或 http://www.example.com/openapi.json。"
msgid "APIFuzzing|File path or URL to requests to be tested. For example, folder/example.postman_collection.json."
-msgstr ""
+msgstr "è¦æ¸¬è©¦çš„請求的文件路徑或網å€ã€‚例如,folder/example.postman_collection.json。"
msgid "APIFuzzing|Generate code snippet"
-msgstr ""
+msgstr "產生程å¼ç¢¼ç‰‡æ®µ"
msgid "APIFuzzing|Make sure your credentials are secured"
-msgstr ""
+msgstr "確ä¿æ‚¨çš„憑據安全"
msgid "APIFuzzing|Password for basic authentication"
-msgstr ""
+msgstr "用於基本身份驗證的密碼"
msgid "APIFuzzing|Predefined profiles"
-msgstr ""
+msgstr "é è¨­çš„設定文件"
msgid "APIFuzzing|Scan mode"
-msgstr ""
+msgstr "掃æ模å¼"
msgid "APIFuzzing|Scan profile"
-msgstr ""
+msgstr "掃æé…置文件"
msgid "APIFuzzing|Show code snippet for the profile"
-msgstr ""
+msgstr "顯示é…置文件的程å¼ç¢¼ç‰‡æ®µ"
msgid "APIFuzzing|Target URL"
msgstr "目標URL"
msgid "APIFuzzing|There are three ways to perform scans."
-msgstr ""
+msgstr "å¯ä»¥é€šéŽä¸‰ç¨®æ–¹å¼åŸ·è¡ŒæŽƒæ。"
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
msgstr "Tip:在階段以下的任何ä½ç½®æ’入以下變é‡ï¼Œä¸¦åŒ…括"
msgid "APIFuzzing|Tip: Insert this part below all include"
-msgstr ""
+msgstr "Tip:在以下所有內容下é¢æ’入此部分"
msgid "APIFuzzing|Tip: Insert this part below all stages"
-msgstr ""
+msgstr "Tip:在所有階段下æ’入此部分"
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 "為了防止安全洩æ¼ï¼Œå¿…須將身份驗證信æ¯æ·»åŠ ç‚º %{ciVariablesLinkStart}CI 變é‡%{ciVariablesLinkEnd}。具有維護者訪å•æ¬Šé™çš„使用者å¯ä»¥åœ¨ %{ciSettingsLinkStart}設置%{ciSettingsLinkEnd} å€åŸŸä¸­ç®¡ç† CI 變é‡ã€‚我們檢測到您ä¸æ˜¯ç¶­è­·è€…。æ交您的更改並將它們分é…給維護人員以在åˆä½µä¹‹å‰æ›´æ–°æ†‘據。"
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 "為了防止安全洩æ¼ï¼Œå¿…須將身份驗證信æ¯æ·»åŠ ç‚º %{ciVariablesLinkStart}CI 變é‡%{ciVariablesLinkEnd}。作為具有維護者訪å•æ¬Šé™çš„使用者,您å¯ä»¥åœ¨ %{ciSettingsLinkStart}設置%{ciSettingsLinkEnd} å€åŸŸä¸­ç®¡ç† CI 變é‡ã€‚"
msgid "APIFuzzing|Username for basic authentication"
-msgstr ""
+msgstr "用於基本身份驗證的使用者å"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
-msgstr ""
+msgstr "您å¯èƒ½éœ€è¦ç¶­è­·äººå“¡çš„幫助來ä¿è­·æ‚¨çš„憑證。"
msgid "APIFuzzing|folder/example.postman_collection.json"
-msgstr ""
+msgstr "folder/example.postman_collection.json"
msgid "APIFuzzing|folder/example_fuzz.har"
-msgstr ""
+msgstr "folder/example_fuzz.har"
msgid "APIFuzzing|folder/openapi.json"
-msgstr ""
+msgstr "folder/openapi.json"
msgid "AWS Access Key"
msgstr "AWS å­˜å–金鑰"
@@ -1693,13 +1710,13 @@ msgid "AWS Secret Access Key"
msgstr "AWS 密碼存å–金鑰"
msgid "AWS access key ID (Optional)"
-msgstr ""
+msgstr "AWS å­˜å–金鑰 ID(å¯é¸ï¼‰"
msgid "AWS secret access key (Optional)"
-msgstr ""
+msgstr "AWS ç§å¯†å­˜å–金鑰(å¯é¸ï¼‰"
msgid "AWS service error: %{error}"
-msgstr ""
+msgstr "AWSæœå‹™éŒ¯èª¤ï¼š %{error}"
msgid "Abort"
msgstr "中止"
@@ -1714,7 +1731,7 @@ msgid "About this feature"
msgstr "關於此功能"
msgid "About your company"
-msgstr ""
+msgstr "關於貴公å¸"
msgid "Abuse Reports"
msgstr "濫用報告"
@@ -1723,7 +1740,7 @@ msgid "Abuse reports"
msgstr "濫用報告"
msgid "Abuse reports notification email"
-msgstr ""
+msgstr "濫用報告通知電å­éƒµä»¶"
msgid "Accept invitation"
msgstr "接å—邀請"
@@ -1732,13 +1749,13 @@ msgid "Accept terms"
msgstr "接å—æœå‹™æ¢æ¬¾"
msgid "Acceptable for use in this project"
-msgstr ""
+msgstr "å¯æŽ¥å—於專案中使用"
msgid "Access Git repositories or the API."
-msgstr ""
+msgstr "å­˜å– Git 版本庫或 API。"
msgid "Access Token"
-msgstr ""
+msgstr "å­˜å–權æ–"
msgid "Access Tokens"
msgstr "å­˜å–憑證"
@@ -1747,25 +1764,25 @@ msgid "Access denied for your LDAP account."
msgstr "您的 LDAP 帳號被拒絕存å–。"
msgid "Access denied: %{error}"
-msgstr ""
+msgstr "拒絕存å–:%{error}"
msgid "Access expires"
-msgstr ""
+msgstr "å­˜å–權é™å·²åˆ°æœŸ"
msgid "Access forbidden. Check your access level."
msgstr "ç¦æ­¢å­˜å–。請檢查您的存å–權é™ã€‚"
msgid "Access granted"
-msgstr ""
+msgstr "已授權存å–"
msgid "Access requests"
-msgstr ""
+msgstr "授權請求"
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…許存å–「%{classification_label}ã€"
msgid "AccessDropdown|Deploy Keys"
-msgstr ""
+msgstr "部署密鑰"
msgid "AccessDropdown|Groups"
msgstr "群組"
@@ -1789,13 +1806,13 @@ msgid "AccessTokens|Are you sure? Any issue email addresses currently in use wil
msgstr "你確定嗎?目å‰æ­£åœ¨ä½¿ç”¨çš„所有議題電å­éƒµä»¶ä½å€éƒ½å°‡åœæ­¢é‹ä½œã€‚"
msgid "AccessTokens|Copy feed token"
-msgstr ""
+msgstr "訪å•ä»¤ç‰Œ(權æ–)|複製æè¦ä»¤ç‰Œ(權æ–)"
msgid "AccessTokens|Copy incoming email token"
-msgstr ""
+msgstr "複製傳入的電å­éƒµä»¶å­˜å–權æ–"
msgid "AccessTokens|Copy static object token"
-msgstr ""
+msgstr "複製éœæ…‹ç‰©ä»¶æ¬Šæ–"
msgid "AccessTokens|Created"
msgstr "已建立"
@@ -1810,13 +1827,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 "ä¿æŒè©²ä»¤ç‰Œ(權æ–)的機密。任何æ“有它的人都å¯ä»¥åƒæ‚¨ä¸€æ¨£å­˜å–儲存庫的éœæ…‹ç‰©ä»¶ã€‚ 如果發生這種情æ³ï¼Œè«‹ %{linkStart} é‡ç½®æ­¤ä»¤ç‰Œ(權æ–) %{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 "ä¿æŒè©²ä»¤ç‰Œ(權æ–)的機密。任何æ“有它的人都å¯ä»¥åƒæ‚¨ä¸€æ¨£å»ºç«‹è­°é¡Œã€‚如果發生這種情æ³ï¼Œè«‹ %{linkStart} é‡ç½®æ­¤ä»¤ç‰Œ(權æ–) %{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 "ä¿å¯†æ­¤æ¬Šæ–,å¦å‰‡ä»–人å¯ä»¥æ“有您查閱活動ã€ç™¼å¸ƒ RSS 關注或日曆關注的權é™ï¼Œå¦‚該情æ³ç™¼ç”Ÿï¼Œ %{linkStart}é‡ç½®æ­¤æ¬Šæ–%{linkEnd}。"
msgid "AccessTokens|Personal Access Tokens"
msgstr "個人存å–權æ–"
@@ -1825,7 +1842,7 @@ msgid "AccessTokens|Static object token"
msgstr "éœæ…‹ç‰©ä»¶æ¬Šæ–"
msgid "AccessTokens|The last time a token was used"
-msgstr ""
+msgstr "上次使用權æ–的時間"
msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
msgstr "當您啟用兩步驟èªè­‰ (2FA) 時,它們將是唯一能接å—的密碼。"
@@ -1837,52 +1854,52 @@ msgid "AccessTokens|You can generate a personal access token for each applicatio
msgstr "您å¯ä»¥ç‚ºæ¯å€‹éœ€è¦å­˜å– GitLab API 的應用程å¼ç”Ÿæˆå€‹äººå­˜å–權æ–。"
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 "當您的 RSS 閱讀器加載個性化 RSS 訂閱æºæˆ–日曆應用程åºåŠ è¼‰å€‹æ€§åŒ–日曆時,您的訂閱æºæ¬Šæ–å°æ‚¨é€²è¡Œèº«ä»½é©—證。它在這些關注 URL 中å¯è¦‹ã€‚"
msgid "AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses."
-msgstr ""
+msgstr "您的傳入電å­éƒµä»¶ä»¤ç‰Œ(權æ–)在您通éŽé›»å­éƒµä»¶å‰µå»ºæ–°å•é¡Œæ™‚å°æ‚¨é€²è¡Œèº«ä»½é©—證,並且包å«åœ¨æ‚¨çš„個人項目特定電å­éƒµä»¶åœ°å€ä¸­ã€‚"
msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
-msgstr ""
+msgstr "當儲存庫éœæ…‹å°è±¡ï¼ˆä¾‹å¦‚檔案或 blob)從外部儲存æ供時,您的éœæ…‹å°è±¡æ¬Šæ–會å°æ‚¨é€²è¡Œèº«ä»½é©—證。"
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "AccessibilityReport|Message: %{message}"
-msgstr ""
+msgstr "消æ¯ï¼š %{message}"
msgid "AccessibilityReport|New"
-msgstr ""
+msgstr "最新"
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
-msgstr ""
+msgstr "輔助功能掃æ發ç¾ä»¥ä¸‹é¡žåž‹çš„錯誤: %{code}"
msgid "Accessible by any user who is logged in."
-msgstr ""
+msgstr "任何登入的使用者皆å¯å­˜å–。"
msgid "Accessible by anyone, regardless of authentication."
-msgstr ""
+msgstr "任何人皆å¯å­˜å–,無論是å¦ç™»å…¥ã€‚"
msgid "Account"
-msgstr "帳戶"
+msgstr "帳號"
msgid "Account ID"
-msgstr "帳戶 ID"
+msgstr "帳號 ID"
msgid "Account and limit"
-msgstr "帳戶和é™åˆ¶"
+msgstr "帳號和é™åˆ¶"
msgid "Account:"
-msgstr ""
+msgstr "帳號:"
msgid "Account: %{account}"
-msgstr "帳戶:%{account}"
+msgstr "帳號:%{account}"
msgid "AccountValidation|Fix your pipelines by validating your account"
-msgstr ""
+msgstr "通éŽé©—證您的帳號來修復您的æµæ°´ç·š"
msgid "AccountValidation|I'll bring my own runners"
-msgstr ""
+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時數,您需è¦ä½¿ç”¨é©—è­‰é¸é …中的其中一項來驗證您的帳號。 如果您ä¸é¡˜æ供驗證,您å¯ä»¥é€éŽè‡ªå·±çš„執行器æ¥é‹è¡Œæµæ°´ç·šä¸¦ç‚ºæ‚¨çš„專案ç¦ç”¨å…±äº«åŸ·è¡Œå™¨ã€‚"
@@ -1900,28 +1917,28 @@ msgid "AccountValidation|Verification is required to discourage and reduce the a
msgstr "驗證是為了阻止並減少 GitLab 基礎設施上的濫用。如果您使用信用å¡æˆ–金èžå¡é€²è¡Œé©—證,%{strong_start}GitLab å°‡ä¸æœƒæ”¶å–費用或儲存您的å¡ç‰‡è³‡è¨Šï¼Œåƒ…使用於驗證上,%{strong_end} %{learn_more_link}"
msgid "Acknowledge"
-msgstr ""
+msgstr "確èª"
msgid "Action"
-msgstr ""
+msgstr "動作"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "接收警示時è¦åŸ·è¡Œçš„動作。%{docsLink}"
msgid "Actions"
-msgstr ""
+msgstr "動作"
msgid "Activate Service Desk"
msgstr "啟用æœå‹™å°"
msgid "Activated on"
-msgstr ""
+msgstr "啟用於"
msgid "Active"
msgstr "使用中"
msgid "Active %{accessTokenTypePlural} (%{totalAccessTokens})"
-msgstr ""
+msgstr "使用中 %{accessTokenTypePlural} (%{totalAccessTokens})"
msgid "Active %{type} (%{token_length})"
msgstr "使用中 %{type}(%{token_length})"
@@ -1930,22 +1947,22 @@ msgid "Active Sessions"
msgstr "使用中的工作階段"
msgid "Active chat names (%{count})"
-msgstr ""
+msgstr "æ´»èºçš„èŠå¤©ä½¿ç”¨è€…å (%{count})"
msgid "Activity"
msgstr "å‹•æ…‹"
msgid "Activity|An error occurred while retrieving activity. Reload the page to try again."
-msgstr ""
+msgstr "å–得動態時發生錯誤。請é‡æ–°è¼‰å…¥é é¢å†è©¦ä¸€æ¬¡ã€‚"
msgid "Add"
msgstr "加入"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "增加\"%{value}\""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
-msgstr ""
+msgstr "新增%{linkStart}資產%{linkEnd}至您的發佈中。GitLab 會自動加入唯讀資產,如原始碼åŠç™¼ä½ˆè­‰æ“šã€‚"
msgid "Add CHANGELOG"
msgstr "加入變更記錄"
@@ -1960,10 +1977,10 @@ msgid "Add LICENSE"
msgstr "加入授權æ¢æ¬¾"
msgid "Add License"
-msgstr ""
+msgstr "新增授權æ¢æ¬¾"
msgid "Add New Site"
-msgstr ""
+msgstr "新增新的網站"
msgid "Add README"
msgstr "加入說明檔案"
@@ -1972,37 +1989,40 @@ msgid "Add Zoom meeting"
msgstr "加入 Zoom 會議"
msgid "Add a %{type}"
-msgstr ""
+msgstr "新增一個 %{type}"
msgid "Add a GCP region"
-msgstr ""
+msgstr "新增 GCP å€åŸŸ"
msgid "Add a GPG key"
msgstr "加入 GPG 金鑰"
msgid "Add a GPG key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
-msgstr ""
+msgstr "新增 GPG é‡‘é‘°ä»¥å®‰å…¨è¨ªå• GitLab。 %{help_link_start}了解更多。%{help_link_end}"
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
-msgstr ""
+msgstr "為此 GitLab 實體的使用者加入æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–。"
msgid "Add a bullet list"
msgstr "加入項目清單"
+msgid "Add a checklist"
+msgstr "增加清單"
+
msgid "Add a collapsible section"
-msgstr ""
+msgstr "加入å¯ç¸®åˆå€å¡Šã€‚"
msgid "Add a comment to this line"
-msgstr ""
+msgstr "在此行新增評論"
msgid "Add a comment to this line or drag for multiple lines"
-msgstr ""
+msgstr "在此行新增評論或拖放多行"
msgid "Add a confidential internal note to this %{noteableDisplayName}."
-msgstr ""
+msgstr "å‘æ­¤ %{noteableDisplayName} 添加機密內部註釋。"
msgid "Add a custom message with details about the instance's shared runners. The message is visible in group and project CI/CD settings, in the Runners section. Markdown is supported."
-msgstr ""
+msgstr "加入自訂訊æ¯ï¼Œè¨Šæ¯åŒ…å«å¯¦é«”的共享執行器細節。該訊æ¯æœƒåœ¨ç¾¤çµ„和專案的 CI / CD çµ„æ…‹åŸ·è¡Œå™¨ä¸­é¡¯ç¤ºã€‚æ”¯æŒ Markdown æ ¼å¼ã€‚"
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "加入一般留言至 %{noteableDisplayName}。"
@@ -2011,43 +2031,40 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "在 wiki 中加入首é ï¼Œå…¶ä¸­åŒ…å«æœ‰é—œå°ˆæ¡ˆçš„資訊,GitLab 將在這裡顯示該首é ï¼Œè€Œä¸æ˜¯æ­¤è¨Šæ¯ã€‚"
msgid "Add a new issue"
-msgstr ""
+msgstr "建立議題"
msgid "Add a numbered list"
msgstr "加入編號列表"
msgid "Add a related epic"
-msgstr ""
+msgstr "新增相關å²è©©"
msgid "Add a related issue"
msgstr "增加一個相關議題"
msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "為æœå‹™å°é›»å­éƒµä»¶åœ°å€æ·»åŠ å¾Œç¶´ã€‚ %{linkStart}了解詳情。%{linkEnd}"
msgid "Add a table"
msgstr "加入表格"
-msgid "Add a task list"
-msgstr "加入作業列表"
-
msgid "Add a title..."
-msgstr ""
+msgstr "新增標題..."
msgid "Add a to do"
-msgstr ""
+msgstr "新增待辦事項"
msgid "Add an SSH key"
msgstr "加入 SSH 金鑰"
msgid "Add an SSH key for secure access to GitLab. %{help_link_start}Learn more.%{help_link_end}"
-msgstr ""
+msgstr "新增 SSH é‡‘é‘°ä»¥å®‰å…¨è¨ªå• GitLab。 %{help_link_start}了解更多。%{help_link_end}"
msgid "Add an existing issue"
-msgstr ""
+msgstr "新增到ç¾æœ‰çš„è­°é¡Œ"
msgid "Add an impersonation token"
-msgstr ""
+msgstr "身份模擬令牌(權æ–)"
msgid "Add another link"
msgstr "加入其他éˆæŽ¥"
@@ -2056,13 +2073,10 @@ msgid "Add approval rule"
msgstr "加入核准è¦å‰‡"
msgid "Add approvers"
-msgstr ""
-
-msgid "Add attention request"
-msgstr ""
+msgstr "新增核准者"
msgid "Add broadcast message"
-msgstr ""
+msgstr "添加廣播消æ¯"
msgid "Add child epic to an epic"
msgstr "加入å­å²è©©åˆ°å²è©©"
@@ -2071,10 +2085,10 @@ msgid "Add comment now"
msgstr "ç«‹å³åŠ å…¥ç•™è¨€"
msgid "Add comment to design"
-msgstr ""
+msgstr "新增設計的評論"
msgid "Add comment..."
-msgstr ""
+msgstr "新增留言..."
msgid "Add commit messages as comments to Asana tasks. %{docs_link}"
msgstr "增加æ交訊æ¯ä½œç‚º Asana 任務的留言。%{docs_link}"
@@ -2086,13 +2100,13 @@ msgid "Add customer relation contact(s)."
msgstr "新增客戶關係è¯çµ¡äººã€‚"
msgid "Add customer relation contacts"
-msgstr ""
+msgstr "新增客戶關係è¯çµ¡äºº"
msgid "Add deploy freeze"
-msgstr ""
+msgstr "新增部署å‡çµ"
msgid "Add deploy keys to grant read/write access to this repository. %{link_start}What are deploy keys?%{link_end}"
-msgstr ""
+msgstr "增加部署金鑰授予這個版本庫 讀ï¼å¯« å­˜å–權。%{link_start}什麼是部署金鑰?%{link_end}"
msgid "Add email address"
msgstr "加入電å­éƒµä»¶åœ°å€"
@@ -2104,7 +2118,10 @@ msgid "Add environment"
msgstr "增加環境"
msgid "Add existing confidential %{issuableType}"
-msgstr ""
+msgstr "建立新的機密%{issuableType}"
+
+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 "加入é é¦–å’Œé å°¾åˆ°é›»å­éƒµä»¶ã€‚請注æ„,é¡è‰²è¨­å®šåªæœƒå¥—用於應用程å¼ä»‹é¢"
@@ -2113,10 +2130,10 @@ msgid "Add image comment"
msgstr "加入圖片留言"
msgid "Add internal note"
-msgstr ""
+msgstr "加入內部說明"
msgid "Add key"
-msgstr ""
+msgstr "新增金鑰"
msgid "Add label(s)"
msgstr "加入標籤"
@@ -2131,25 +2148,25 @@ msgid "Add new directory"
msgstr "新增目錄"
msgid "Add or remove a user."
-msgstr ""
+msgstr "新增或移除使用者。"
msgid "Add or remove previously merged commits"
-msgstr ""
+msgstr "新增或移除先å‰åˆä½µçš„æ交"
msgid "Add or subtract spent time"
msgstr "增加或減少耗時"
msgid "Add people"
-msgstr ""
+msgstr "新增人員"
msgid "Add previously merged commits"
-msgstr ""
+msgstr "新增先å‰åˆä½µçš„æ交"
msgid "Add project"
-msgstr ""
+msgstr "新增專案"
msgid "Add projects"
-msgstr ""
+msgstr "新增專案"
msgid "Add reaction"
msgstr "加入回應"
@@ -2158,16 +2175,16 @@ msgid "Add request manually"
msgstr "手動加入請求"
msgid "Add suggestion to batch"
-msgstr ""
+msgstr "批次添加建議"
msgid "Add system hook"
msgstr "加入系統掛鉤"
msgid "Add text to the sign-in page. Markdown enabled."
-msgstr ""
+msgstr "加入文字到登入é é¢ã€‚Markdown 已啟用。"
msgid "Add to board"
-msgstr ""
+msgstr "新增到看æ¿"
msgid "Add to epic"
msgstr "加到å²è©©"
@@ -2188,7 +2205,7 @@ msgid "Add topics to projects to help users find them."
msgstr "加入主題到專案以幫助使用者尋找。"
msgid "Add trigger"
-msgstr ""
+msgstr "新增觸發器"
msgid "Add user(s) to the group:"
msgstr "å‘群組加入使用者:"
@@ -2197,7 +2214,7 @@ msgid "Add users to group"
msgstr "å‘群組加入使用者"
msgid "Add variable"
-msgstr ""
+msgstr "新增/變數"
msgid "Add vulnerability finding"
msgstr "新增發ç¾çš„æ¼æ´ž"
@@ -2206,10 +2223,10 @@ msgid "Add webhook"
msgstr "加入 Webhook"
msgid "Add your team members and others to GitLab."
-msgstr ""
+msgstr "將您的團隊æˆå“¡å’Œå…¶ä»–人加入到 GitLab。"
msgid "Add/remove"
-msgstr ""
+msgstr "新增/移除"
msgid "AddContextCommits|Add previously merged commits"
msgstr "加入先å‰å·²åˆä½µçš„æ交紀錄"
@@ -2227,7 +2244,7 @@ msgid "AddMember|Invites cannot be blank"
msgstr "邀請ä¸å¯ç‚ºç©º"
msgid "AddMember|No invite source provided."
-msgstr ""
+msgstr "未æ供邀請來æºã€‚"
msgid "AddMember|No users specified."
msgstr "未指定使用者。"
@@ -2245,13 +2262,13 @@ msgid "Added %{label_references} %{label_text}."
msgstr "已加入 %{label_references} %{label_text}。"
msgid "Added a to do."
-msgstr ""
+msgstr "已添加一個代辦事項。"
msgid "Added an issue to an epic."
msgstr "å·²å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
msgid "Added for this merge request"
-msgstr ""
+msgstr "添加此åˆä½µè«‹æ±‚"
msgid "Added in this version"
msgstr "此版本新增"
@@ -2263,22 +2280,22 @@ msgid "Additional minutes"
msgstr "é¡å¤–分é˜"
msgid "Additional minutes:"
-msgstr ""
+msgstr "é¡å¤–的分é˜æ•¸ï¼š"
msgid "Additional text"
msgstr "附加文字"
msgid "Additional text for the sign-in and Help page."
-msgstr ""
+msgstr "登入åŠèªªæ˜Žé é¢çš„é¡å¤–文字。"
msgid "Additional text to show on the Help page"
-msgstr ""
+msgstr "在說明é é¢é¡¯ç¤ºçš„é¡å¤–文字"
msgid "Additional text to show on the sign-in page"
-msgstr ""
+msgstr "在登入é é¢é¡¯ç¤ºçš„é¡å¤–文字"
msgid "Address"
-msgstr ""
+msgstr "地å€"
msgid "Adds"
msgstr "加入"
@@ -2290,46 +2307,46 @@ msgid "Adds %{labels} %{label_text}."
msgstr "加入 %{labels}%{label_text}。"
msgid "Adds a Zoom meeting."
-msgstr ""
+msgstr "加入 Zoom 會議."
msgid "Adds a to do."
-msgstr ""
+msgstr "新增待辦事項。"
msgid "Adds an issue to an epic."
msgstr "å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
msgid "Adds email participant(s)."
-msgstr ""
+msgstr "新增電å­éƒµä»¶åƒèˆ‡è€…。"
msgid "Adds this %{issuable_type} as related to the %{issuable_type} it was created from"
-msgstr ""
+msgstr "將 %{issuable_type} 新增為與創建它的 %{issuable_type} 相關"
msgid "Adjust how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "調整 GitLab UI 輪詢的更新頻率。"
msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
msgstr "在上方調整您的篩é¸/æœå°‹æ¢ä»¶ã€‚如果您èªç‚ºé€™å¯èƒ½æ˜¯ä¸€å€‹éŒ¯èª¤ï¼Œè«‹åƒè€ƒ %{linkStart}Geo故障排除%{linkEnd} 文件以了解更多資訊。"
msgid "Admin"
-msgstr ""
+msgstr "管ç†å“¡"
msgid "Admin Area"
msgstr "管ç†ä¸­å¿ƒ"
msgid "Admin Mode"
-msgstr ""
+msgstr "管ç†å“¡æ¨¡å¼"
msgid "Admin Note"
-msgstr ""
+msgstr "管ç†å“¡å‚™è¨»"
msgid "Admin Notifications"
-msgstr ""
+msgstr "管ç†å“¡é€šçŸ¥"
msgid "Admin Overview"
msgstr "管ç†æ¦‚覽"
msgid "Admin Section"
-msgstr ""
+msgstr "管ç†éƒ¨åˆ†"
msgid "Admin mode already enabled"
msgstr "管ç†å“¡æ¨¡å¼å·²å•Ÿç”¨"
@@ -2341,97 +2358,97 @@ msgid "Admin mode enabled"
msgstr "管ç†å“¡æ¨¡å¼å·²å•Ÿç”¨"
msgid "Admin navigation"
-msgstr ""
+msgstr "管ç†å“¡å°Žèˆª"
msgid "Admin notes"
msgstr "管ç†å“¡å‚™è¨»"
msgid "AdminArea|%{billable_users_link_start}Learn more%{billable_users_link_end} about what defines a billable user"
-msgstr ""
+msgstr "%{billable_users_link_start}了解更多%{billable_users_link_end}有關計費使用者的定義"
msgid "AdminArea|Active users"
-msgstr ""
+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 ""
+msgstr "所有在此實例中建立的使用者,包括%{billable_users_link_start}計費使用者%{billable_users_link_end}以外的使用者。"
msgid "AdminArea|Billable users"
-msgstr ""
+msgstr "計費使用者"
msgid "AdminArea|Blocked users"
-msgstr ""
+msgstr "å°éŽ–使用者"
msgid "AdminArea|Bots"
-msgstr ""
+msgstr "機器人"
msgid "AdminArea|Components"
-msgstr ""
+msgstr "組件"
msgid "AdminArea|Developer"
-msgstr ""
+msgstr "開發人員"
msgid "AdminArea|Features"
-msgstr ""
+msgstr "功能"
msgid "AdminArea|Get security updates from GitLab and stay up to date"
msgstr "從 GitLab å–得安全更新並ä¿æŒæœ€æ–°ç‹€æ…‹"
msgid "AdminArea|Groups"
-msgstr ""
+msgstr "群組"
msgid "AdminArea|Guest"
msgstr "訪客"
msgid "AdminArea|Included Free in license"
-msgstr ""
+msgstr "包å«å…費授權"
msgid "AdminArea|Instance OAuth applications"
-msgstr ""
+msgstr "驗證應用程å¼å¯¦é«”"
msgid "AdminArea|Latest groups"
-msgstr ""
+msgstr "最新群組"
msgid "AdminArea|Latest projects"
-msgstr ""
+msgstr "最新專案"
msgid "AdminArea|Latest users"
-msgstr ""
+msgstr "最新使用者"
msgid "AdminArea|Maintainer"
-msgstr ""
+msgstr "維護者"
msgid "AdminArea|Manage applications for your instance that can use GitLab as an %{docs_link_start}OAuth provider%{docs_link_end}."
-msgstr ""
+msgstr "管ç†æ‚¨çš„應用系統使用 GitLab 為 %{docs_link_start}OAuth æ供者%{docs_link_end}."
msgid "AdminArea|Minimal access"
-msgstr ""
+msgstr "最å°å­˜å–權é™"
msgid "AdminArea|New group"
-msgstr ""
+msgstr "新的群組"
msgid "AdminArea|New project"
-msgstr ""
+msgstr "新的專案"
msgid "AdminArea|New user"
-msgstr ""
+msgstr "新使用者"
msgid "AdminArea|No applications found"
-msgstr ""
+msgstr "未找到應用程å¼"
msgid "AdminArea|Owner"
-msgstr ""
+msgstr "所有者"
msgid "AdminArea|Projects"
-msgstr ""
+msgstr "專案"
msgid "AdminArea|Reporter"
-msgstr ""
+msgstr "報告者"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "登記 GitLab 安全通訊以å–得安全更新通知。"
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "登記 GitLab 通訊"
msgid "AdminArea|Stop all jobs"
msgstr "åœæ­¢æ‰€æœ‰ä½œæ¥­"
@@ -2446,46 +2463,46 @@ msgid "AdminArea|Stopping jobs failed"
msgstr "åœæ­¢ä½œæ¥­å¤±æ•—"
msgid "AdminArea|Total users"
-msgstr ""
+msgstr "總使用者"
msgid "AdminArea|Users"
-msgstr ""
+msgstr "使用者"
msgid "AdminArea|Users statistics"
-msgstr ""
+msgstr "使用者統計"
msgid "AdminArea|Users with highest role"
-msgstr ""
+msgstr "用户有最高的權é™"
msgid "AdminArea|Users without a Group and Project"
-msgstr ""
+msgstr "沒有群組和專案的使用者"
msgid "AdminArea|View latest groups"
-msgstr ""
+msgstr "查看最新群組"
msgid "AdminArea|View latest projects"
-msgstr ""
+msgstr "查看最新專案"
msgid "AdminArea|View latest users"
-msgstr ""
+msgstr "查看最新使用者"
msgid "AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running."
-msgstr ""
+msgstr "您打算åœæ­¢æ‰€æœ‰ä»»å‹™ã€‚這將會åœæ­¢æ‰€æœ‰æ­£åœ¨åŸ·è¡Œä¸­çš„任務。"
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "載入統計資料時發生錯誤。請å†è©¦ä¸€æ¬¡"
msgid "AdminLabels|Define your default set of project labels"
-msgstr ""
+msgstr "定義您專案標籤的é è¨­è¨­å®š"
msgid "AdminLabels|Labels created here will be automatically added to new projects."
-msgstr ""
+msgstr "這裡創建的標籤將自動新增到新專案中。"
msgid "AdminLabels|They can be used to categorize issues and merge requests."
-msgstr ""
+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 ""
+msgstr "您å³å°‡æ°¸ä¹…刪除專案 %{projectName}ã€å…¶ç‰ˆæœ¬åº«ä»¥åŠæ‰€æœ‰ç›¸é—œè³‡æºï¼ŒåŒ…括議題和åˆä½µè«‹æ±‚。確èªä¸¦æŒ‰ %{strong_start}刪除專案%{strong_end}後,將無法撤消或æ¢å¾©ã€‚"
msgid "AdminProjects|Delete"
msgstr "刪除"
@@ -2494,271 +2511,271 @@ msgid "AdminProjects|Delete Project %{projectName}?"
msgstr "刪除專案 %{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}警告:%{strongEnd} 環境變數 %{environment_variable} ä¸å­˜åœ¨æˆ–未指å‘有效目錄。 %{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 "å³å°‡ä½¿ç”¨æ­¤é›»éƒµåœ°å€ç‚ºè©² GitLab 實體é…ç½® Let's Encrypt 帳號。您將會收到證書å³å°‡éŽæœŸçš„郵件。%{link_start}了解更多。%{link_end}"
msgid "AdminSettings|Affects all new and existing groups."
-msgstr ""
+msgstr "影響所有新的和ç¾æœ‰çš„群組項目"
msgid "AdminSettings|All new projects can use the instance's shared runners by default."
-msgstr ""
+msgstr "é è¨­æ‰€æœ‰æ–°å°ˆæ¡ˆéƒ½å¯ä»¥ä½¿ç”¨å¯¦ä¾‹çš„共享執行器。"
msgid "AdminSettings|Auto DevOps domain"
msgstr "Auto DevOps 網域"
msgid "AdminSettings|Automatically ban users who download more than a specified number of repositories in a given time."
-msgstr ""
+msgstr "自動å°éŽ–在時間內下載超éŽæŒ‡å®šæ•¸é‡å­˜å„²åº«çš„用戶。"
msgid "AdminSettings|CI/CD limits"
-msgstr ""
+msgstr "CI/CD é™åˆ¶"
msgid "AdminSettings|Configure Let's Encrypt"
-msgstr ""
+msgstr "é…ç½® Let's Encrypt"
msgid "AdminSettings|Configure when inactive projects should be automatically deleted. %{linkStart}What are inactive projects?%{linkEnd}"
-msgstr ""
+msgstr "設定何時應自動刪除ä¸æ´»èºçš„專案。 %{linkStart}什麼是ä¸æ´»èºå°ˆæ¡ˆï¼Ÿ%{linkEnd}"
msgid "AdminSettings|Delete inactive projects"
-msgstr ""
+msgstr "刪除ä¸æ´»èºå°ˆæ¡ˆ"
msgid "AdminSettings|Delete inactive projects that exceed"
-msgstr ""
+msgstr "刪除超出時é™çš„ä¸æ´»èºå°ˆæ¡ˆã€‚"
msgid "AdminSettings|Delete project after"
-msgstr ""
+msgstr "之後刪除專案"
msgid "AdminSettings|Disable Elasticsearch until indexing completes."
-msgstr ""
+msgstr "åœç”¨ Elasticsearch 一直到索引建立完æˆã€‚"
msgid "AdminSettings|Disable feed token"
-msgstr ""
+msgstr "åœç”¨å‹•æ…‹æ¬Šæ–"
msgid "AdminSettings|Disable public access to Pages sites"
-msgstr ""
+msgstr "åœç”¨å…¬é–‹å­˜å–é é¢ç¶²é "
msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
-msgstr ""
+msgstr "在沒有æµæ°´ç·šå°ˆæ¡ˆçš„åˆä½µè«‹æ±‚上顯示橫幅,以啟動加入 .gitlab-ci.yml 檔案的步驟。"
msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "網域驗證是公共 GitLab 網站的基本安全措施。在啟用網域å‰ï¼Œä½¿ç”¨è€…需è¦è­‰æ˜Žæ“有網域的所有權。%{link_start}了解更多%{link_end}"
msgid "AdminSettings|Elasticsearch indexing"
-msgstr ""
+msgstr "正在建立 Elasticsearch 索引"
msgid "AdminSettings|Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "來自於 GitlLab çš„é›»å­éƒµä»¶ - 從管ç†å€åŸŸå‘使用者所發é€çš„é›»å­éƒµä»¶ã€‚ %{link_start}了解更多%{link_end}."
msgid "AdminSettings|Enable Registration Features"
-msgstr ""
+msgstr "啟用註冊功能"
msgid "AdminSettings|Enable Service Ping"
-msgstr ""
+msgstr "啟用 Service Ping"
msgid "AdminSettings|Enable a Prometheus endpoint that exposes health and performance statistics. The Health Check menu item appears in the Monitoring section of the Admin Area. Restart required. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "啟用公開é‹è¡Œç‹€æ³å’Œæ€§èƒ½çµ±è¨ˆä¿¡æ¯çš„ Prometheus 端點。å¥åº·æª¢æŸ¥é¸å–®é …出ç¾åœ¨ç®¡ç†å€åŸŸçš„監控部分。需è¦é‡æ–°å•Ÿå‹•ã€‚ %{link_start}了解更多。%{link_end}"
msgid "AdminSettings|Enable kuromoji custom analyzer: Indexing"
-msgstr ""
+msgstr "啟用 kuromoji 自訂分æžå™¨: 索引建立中"
msgid "AdminSettings|Enable kuromoji custom analyzer: Search"
-msgstr ""
+msgstr "啟用 kuromoji 自訂分æžå™¨: 查詢"
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "啟用æµæ°´ç·šå»ºè­°æ©«å¹…"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "啟用新專案的共享執行器"
msgid "AdminSettings|Enable smartcn custom analyzer: Indexing"
-msgstr ""
+msgstr "啟用 smartcn 自訂分æžå™¨: 索引建立中"
msgid "AdminSettings|Enable smartcn custom analyzer: Search"
-msgstr ""
+msgstr "啟用 smartcn 自訂分æžå™¨: 查詢"
msgid "AdminSettings|Enabled"
-msgstr ""
+msgstr "已啟用"
msgid "AdminSettings|Feed token"
-msgstr ""
+msgstr "動態權æ–"
msgid "AdminSettings|Git abuse rate limit"
-msgstr ""
+msgstr "Git 濫用率é™åˆ¶"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
-msgstr ""
+msgstr "我已閱讀並åŒæ„ Let's Encrypt çš„%{link_start}æœå‹™æ¢æ¬¾%{link_end}(PDF)。"
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
-msgstr ""
+msgstr "如果沒有在群組或實例級別指定,則é è¨­ç‚º %{default_initial_branch_name}。這ä¸æœƒå½±éŸ¿ç¾æœ‰çš„檔案庫。"
msgid "AdminSettings|If there isn't any existing index, GitLab creates one."
-msgstr ""
+msgstr "如果沒有任何ç¾æœ‰ç´¢å¼•ï¼ŒGitLab 會建立一個。"
msgid "AdminSettings|Import sources"
-msgstr ""
+msgstr "匯入來æº"
msgid "AdminSettings|Inactive project deletion"
-msgstr ""
+msgstr "ä¸æ´»èºå°ˆæ¡ˆç§»é™¤"
msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines"
-msgstr ""
+msgstr "ä¿ç•™æœ€æ–°ä¸”æˆåŠŸçš„æµæ°´ç·šä¸­æ‰€æœ‰ä»»å‹™çš„最新產物"
msgid "AdminSettings|Let's Encrypt email"
-msgstr ""
+msgstr "Let's Encrypt é›»å­éƒµä»¶"
msgid "AdminSettings|Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "在全域ã€ç¾¤çµ„ã€å°ˆæ¡ˆå±¤ç´šé™åˆ¶å°ˆæ¡ˆçš„大å°ã€‚%{link_start}了解更多%{link_end}."
msgid "AdminSettings|Limit the number of namespaces and projects that can be indexed."
-msgstr ""
+msgstr "é™åˆ¶å¯ä»¥è¢«ç´¢å¼•çš„命å空間和專案的數é‡ã€‚"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
-msgstr ""
+msgstr "兩步驟驗證啟用時,Git æ“作的最長工作階段時間。"
msgid "AdminSettings|Maximum number of DAG dependencies that a job can have"
-msgstr ""
+msgstr " 作業å¯æŒæœ‰çš„ DAG ä¾è³´æœ€å¤§æ•¸"
msgid "AdminSettings|Maximum number of active pipelines per project"
-msgstr ""
+msgstr "æ¯å€‹å°ˆæ¡ˆçš„最大活動æµæ°´ç·šæ•¸é‡"
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
-msgstr ""
+msgstr "在一個æµæ°´ç·šä¸­çš„最大作業數"
msgid "AdminSettings|Maximum number of pipeline schedules"
-msgstr ""
+msgstr "æµæ°´ç·šæŽ’程的最大數é‡"
msgid "AdminSettings|Maximum number of pipeline subscriptions to and from a project"
-msgstr ""
+msgstr "專案å¯è¨‚閱的最大æµæ°´ç·šæ•¸"
msgid "AdminSettings|Maximum number of runners registered per group"
-msgstr ""
+msgstr "æ¯çµ„註冊的執行器的最大數é‡"
msgid "AdminSettings|Maximum number of runners registered per project"
-msgstr ""
+msgstr "æ¯å€‹å°ˆæ¡ˆè¨»å†Šçš„執行器的最大數é‡"
msgid "AdminSettings|Minimum size must be at least 0."
-msgstr ""
+msgstr "最å°å°ºå¯¸å¿…須至少為 0。"
msgid "AdminSettings|New CI/CD variables in projects and groups default to protected."
-msgstr ""
+msgstr "專案和群組的新 CI / CD 變數é è¨­ç‚ºå—ä¿è­·ã€‚"
msgid "AdminSettings|No required pipeline"
msgstr "沒有強制性的æµæ°´ç·š"
msgid "AdminSettings|Only enable search after installing the plugin, enabling indexing, and recreating the index."
-msgstr ""
+msgstr "åªæœ‰åœ¨å®‰è£æ’件ã€å•Ÿç”¨ä¸”é‡å»ºç´¢å¼•å¾Œæ–¹å¯é–‹å•ŸæŸ¥è©¢ã€‚"
msgid "AdminSettings|Pause Elasticsearch indexing"
-msgstr ""
+msgstr "æš«åœ Elasticsearch 索引建立"
msgid "AdminSettings|Preview payload"
-msgstr ""
+msgstr "負載é è¦½"
msgid "AdminSettings|Project export"
-msgstr ""
+msgstr "匯出專案"
msgid "AdminSettings|Protect CI/CD variables by default"
-msgstr ""
+msgstr "é è¨­ä¿è­· CI / CD 變數"
msgid "AdminSettings|Registration Features include:"
-msgstr ""
+msgstr "註冊功能包括:"
msgid "AdminSettings|Require users to prove ownership of custom domains"
-msgstr ""
+msgstr "è¦æ±‚使用者證明æ“有自訂網域的所有權"
msgid "AdminSettings|Required pipeline configuration"
msgstr "強制æµæ°´ç·šè¨­å®š"
msgid "AdminSettings|Requires %{linkStart}email notifications%{linkEnd}"
-msgstr ""
+msgstr "éœ€è¦ %{linkStart}é›»å­éƒµä»¶é€šçŸ¥%{linkEnd}"
msgid "AdminSettings|Restrict group access by IP address. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "é€éŽ IP 地å€é™åˆ¶ç¾¤çµ„訪å•ã€‚ %{link_start}了解更多%{link_end}。"
msgid "AdminSettings|Save %{name} limits"
-msgstr ""
+msgstr "儲存 %{name} é™åˆ¶"
msgid "AdminSettings|Search with Elasticsearch enabled"
-msgstr ""
+msgstr "啟用 Elasticsearch 進行æœå°‹"
msgid "AdminSettings|Select a CI/CD template"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ CI/CD 範本"
msgid "AdminSettings|Select a group to use as the source for instance-level project templates."
-msgstr ""
+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 ""
+msgstr "é¸æ“‡åœç”¨å…¬é–‹å­˜å–é é¢ç¶²ç«™ï¼Œè¡¨ç¤ºç”¨æˆ¶éœ€è¦ç™»å…¥æ‰èƒ½å­˜å–您實例的é é¢ç¶²ç«™ã€‚%{link_start}了解更多。%{link_end}"
msgid "AdminSettings|Send email to maintainers after project is inactive for"
-msgstr ""
+msgstr "在專案處於éžæ´»èºç‹€æ…‹å¾Œå‘維護人員發é€é›»å­éƒµä»¶"
msgid "AdminSettings|Send warning email"
-msgstr ""
+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 ""
+msgstr "Service ping 在您的組態文件中被ç¦ç”¨ï¼Œä¸¦ä¸”無法通éŽæ­¤è¡¨å–®å•Ÿç”¨ã€‚ 有關詳細信æ¯ï¼Œè«‹åƒé–± %{link_start}åœç”¨ Service ping%{link_end} 的文檔。"
msgid "AdminSettings|Session duration for Git operations when 2FA is enabled (minutes)"
-msgstr ""
+msgstr "兩步驟驗證啟用時 Git æ“作的工作階段æŒçºŒæ™‚間(分é˜ï¼‰"
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 "å°‡ CI / CD 模æ¿è¨­å®šç‚ºå¯¦ä¾‹ä¸­æ‰€æœ‰å°ˆæ¡ˆçš„å¿…è¦æµæ°´ç·šé…置。當執行æµæ°´ç·šæ™‚,專案的 CI / CD é…置會與必è¦æµæ°´ç·šé…ç½®åˆä½µã€‚%{link_start}甚麼是必è¦æµæ°´ç·šé…置?%{link_end}"
msgid "AdminSettings|Set limit to 0 to disable it."
-msgstr ""
+msgstr "å°‡é™åˆ¶è¨­å®šç‚º 0 以åœç”¨å®ƒã€‚"
msgid "AdminSettings|Set the initial name and protections for the default branch of new repositories created in the instance."
-msgstr ""
+msgstr "為實例中創建的新存儲庫的默èªåˆ†æ”¯è¨­ç½®åˆå§‹å稱和ä¿è­·ã€‚"
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "設定æ¯å€‹å°ˆæ¡ˆçš„ GitLab 網é çš„最大容é‡ï¼ˆ0 表示無é™åˆ¶ï¼‰ã€‚%{link_start}了解更多。%{link_end}"
msgid "AdminSettings|Setting must be greater than 0."
-msgstr ""
+msgstr "設定值必須大於 0。"
msgid "AdminSettings|Size and domain settings for Pages static sites."
-msgstr ""
+msgstr "é é¢éœæ…‹ç¶²ç«™çš„容é‡åŠç¶²åŸŸè¨­å®šã€‚"
msgid "AdminSettings|The default domain to use for Auto Review Apps and Auto Deploy stages in all projects."
-msgstr ""
+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 "æ¯å€‹å°ˆæ¡ˆæœ€æ–°æˆåŠŸçš„æµæ°´ç·šï¼Œå…¶æ‰€æœ‰ä»»å‹™çš„最新產物已被儲存,並且ä¸æœƒéŽæœŸã€‚"
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 "å¯é¸æ“‡æ­¤ç¾¤çµ„的專案作為實例中新建立專案的模æ¿ã€‚%{link_start}了解更多。%{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 "å¿…è¦æµæ°´ç·šé…置的範本å¯ä»¥æ˜¯ GitLab æ供的範本之一,或者是新增到實例範本檔案庫的自訂範本。%{link_start}如何建立實例範本檔案庫?%{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 "進階查詢å‡ç´šç‚ºå¾…處ç†ç‹€æ…‹ç›´åˆ°æš«åœå»ºç«‹ç´¢å¼•ã€‚ 建立索引必須ä¿æŒæš«åœï¼Œç›´åˆ° GitLab 完æˆå‡ç´šã€‚"
msgid "AdminSettings|To enable Registration Features, first enable Service Ping."
-msgstr ""
+msgstr "è¦å•Ÿç”¨è¨»å†ŠåŠŸèƒ½ï¼Œéœ€å…ˆå•Ÿç”¨ Service Ping。"
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 "為了幫助改善 GitLab åŠå…¶ä½¿ç”¨è€…體驗,GitLab 會定期收集使用訊æ¯ã€‚ %{link_start} 哪些信æ¯èˆ‡ GitLab Inc. 分享? %{link_end}"
msgid "AdminSettings|Total number of jobs in currently active pipelines"
-msgstr ""
+msgstr "ç›®å‰æ´»å‹•ä¸­çš„æµæ°´ç®¡ç·šä½œæ¥­ç¸½æ•¸"
msgid "AdminSettings|Use AWS hosted Elasticsearch with IAM credentials"
-msgstr ""
+msgstr "使用 AWS 託管具有 IAM 憑證的 Elasticsearch"
msgid "AdminSettings|When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
-msgstr ""
+msgstr "æš«åœæ™‚,Gitlab ä»ç„¶æœƒè¿½è¹¤è®Šæ›´ã€‚這有助於 å¢é›†/索引 çš„å‡ç´šã€‚"
msgid "AdminSettings|When to delete inactive projects"
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥å•Ÿç”¨è¨»å†ŠåŠŸèƒ½ï¼Œå› ç‚º Service Ping 已啟用。è¦ç¹¼çºŒä½¿ç”¨è¨»å†ŠåŠŸèƒ½ï¼Œæ‚¨å¿…é ˆå‘GitLab註冊新的雲æœå‹™è¨±å¯æ¬Šã€‚"
msgid "AdminSettings|You can't delete projects before the warning email is sent."
-msgstr ""
+msgstr "在發é€è­¦å‘Šé›»å­éƒµä»¶ä¹‹å‰ï¼Œæ‚¨ç„¡æ³•åˆªé™¤å°ˆæ¡ˆã€‚"
msgid "AdminStatistics|Active Users"
msgstr "æ´»èºä½¿ç”¨è€…"
@@ -2770,7 +2787,7 @@ msgid "AdminStatistics|Issues"
msgstr "議題"
msgid "AdminStatistics|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "AdminStatistics|Milestones"
msgstr "里程碑"
@@ -2785,25 +2802,25 @@ msgid "AdminStatistics|Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "AdminUsers|(Admin)"
-msgstr ""
+msgstr "管ç†å“¡"
msgid "AdminUsers|(Banned)"
-msgstr ""
+msgstr "(å·²å°éŽ–)"
msgid "AdminUsers|(Blocked)"
-msgstr ""
+msgstr "(å·²å°éŽ–)"
msgid "AdminUsers|(Deactivated)"
-msgstr ""
+msgstr "(已åœç”¨ï¼‰"
msgid "AdminUsers|(Internal)"
-msgstr ""
+msgstr "(内部)"
msgid "AdminUsers|(Locked)"
-msgstr ""
+msgstr "(已鎖定)"
msgid "AdminUsers|(Pending approval)"
-msgstr ""
+msgstr "(正在等待批准)"
msgid "AdminUsers|2FA Disabled"
msgstr "未啟用兩步驟驗證"
@@ -2812,73 +2829,73 @@ 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 "使用者å¯ä»¥é€šéŽè¼¸å…¥ä¿¡ç”¨å¡/借記å¡ä¾†é©—證自己,或者管ç†å“¡å¯ä»¥æ‰‹å‹•é©—證使用者。經éŽé©—證的使用者å¯ä»¥åœ¨å…±äº«åŸ·è¡Œå™¨ä¸Šä½¿ç”¨å…費的 CI 分é˜æ•¸ã€‚"
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "權é™"
msgid "AdminUsers|Access Git repositories"
-msgstr ""
+msgstr "å­˜å– Git 版本庫"
msgid "AdminUsers|Access level"
-msgstr ""
+msgstr "å­˜å–等級"
msgid "AdminUsers|Access the API"
-msgstr ""
+msgstr "訪å•API"
msgid "AdminUsers|Activate"
-msgstr ""
+msgstr "啟用"
msgid "AdminUsers|Activate user %{username}?"
-msgstr ""
+msgstr "啟用使用者 %{username}?"
msgid "AdminUsers|Active"
msgstr "æ´»èº"
msgid "AdminUsers|Adjust the user cap setting on your instance"
-msgstr ""
+msgstr "在您的實例上調整使用者上é™è¨­ç½®"
msgid "AdminUsers|Admin"
msgstr "管ç†å“¡"
msgid "AdminUsers|Administrator"
-msgstr ""
+msgstr "系統管ç†å“¡"
msgid "AdminUsers|Admins"
msgstr "管ç†å“¡"
msgid "AdminUsers|Approve"
-msgstr ""
+msgstr "批准"
msgid "AdminUsers|Approve user %{username}?"
-msgstr ""
+msgstr "核准使用者 %{username}?"
msgid "AdminUsers|Approved users can:"
-msgstr ""
+msgstr "核准使用者å¯ä»¥ï¼š"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "審核員"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr "審核員有權唯讀存å–所有群組ã€å°ˆæ¡ˆåŠä½¿ç”¨è€…。"
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "é è¨­æ¨™è¨˜æˆå…§éƒ¨ä½¿ç”¨è€…"
msgid "AdminUsers|Avatar"
-msgstr ""
+msgstr "é ­åƒ"
msgid "AdminUsers|Ban user"
-msgstr ""
+msgstr "å°éŽ–使用者"
msgid "AdminUsers|Ban user %{username}?"
-msgstr ""
+msgstr "å°éŽ–使用者 %{username}?"
msgid "AdminUsers|Banned"
-msgstr ""
+msgstr "å·²å°éŽ–"
msgid "AdminUsers|Be added to groups and projects"
-msgstr ""
+msgstr "增加到群組和專案"
msgid "AdminUsers|Block"
msgstr "å°éŽ–"
@@ -2896,31 +2913,31 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "å°éŽ–使用者具有以下效果:"
msgid "AdminUsers|Can create group"
-msgstr ""
+msgstr "å¯ä»¥å»ºç«‹ç¾¤çµ„"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "無法登入或存å–實例資訊"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "無法解除å°éŽ– LDAP å°éŽ–的使用者"
msgid "AdminUsers|Cohorts"
-msgstr ""
+msgstr "åŒé¡žç¾¤çµ„"
msgid "AdminUsers|Confirm user"
-msgstr ""
+msgstr "確èªä½¿ç”¨è€…"
msgid "AdminUsers|Confirm user %{username}?"
-msgstr ""
+msgstr "確èªä½¿ç”¨è€… %{username}?"
msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
-msgstr ""
+msgstr "無法加載使用者群組計數。請刷新é é¢é‡è©¦ã€‚"
msgid "AdminUsers|Deactivate"
msgstr "å‡çµ"
msgid "AdminUsers|Deactivate user %{username}?"
-msgstr ""
+msgstr "åœç”¨çš„使用者 %{username}?"
msgid "AdminUsers|Deactivated"
msgstr "å·²å‡çµ"
@@ -2941,52 +2958,52 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "刪除使用者åŠç›¸é—œè²¢ç»"
msgid "AdminUsers|Export permissions as CSV (max 100,000 users)"
-msgstr ""
+msgstr "以 CSV æ ¼å¼åŒ¯å‡ºæ¬Šé™ (最多 100,000 個使用者)"
msgid "AdminUsers|External"
msgstr "外部"
msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
-msgstr ""
+msgstr "除éžæ˜Žç¢ºæŽˆäºˆå­˜å–權é™ï¼Œå¦å‰‡å¤–部使用者無法查看內部或ç§äººå°ˆæ¡ˆã€‚å¦å¤–,外部使用者無法建立專案ã€ç¾¤çµ„åŠå€‹äººç¨‹å¼ç¢¼ç‰‡æ®µã€‚"
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "更多詳細信æ¯ï¼Œè«‹åƒé–± %{link_start}使用者帳號刪除文檔。%{link_end}"
msgid "AdminUsers|Here are some helpful links to help you manage your instance:"
-msgstr ""
+msgstr "以下是一些有用的éˆæŽ¥ï¼Œå¯å¹«åŠ©æ‚¨ç®¡ç†å¯¦ä¾‹ï¼š"
msgid "AdminUsers|If you have any questions about this process please consult our %{doc_link} or %{support_link}."
-msgstr ""
+msgstr "如果å°æ­¤éŽç¨‹æœ‰ä»»ä½•ç–‘å•ï¼Œè«‹è«®è©¢æˆ‘們的 %{doc_link} 或 %{support_link}。"
msgid "AdminUsers|Important information about usage on your GitLab instance"
-msgstr ""
+msgstr "有關您GitLab實例使用情æ³çš„é‡è¦ä¿¡æ¯"
msgid "AdminUsers|Is using seat"
-msgstr ""
+msgstr "管ç†ä½¿ç”¨è€…正在使用"
msgid "AdminUsers|Issues authored by this user are hidden from other users."
-msgstr ""
+msgstr "此使用者所著的議題已å‘其他使用者隱è—。"
msgid "AdminUsers|It's you!"
msgstr "這就是你ï¼"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
-msgstr ""
+msgstr "了解更多有關%{link_start}被å°éŽ–使用者。%{link_end}"
msgid "AdminUsers|Limits"
-msgstr ""
+msgstr "é™åˆ¶"
msgid "AdminUsers|Linkedin"
-msgstr ""
+msgstr "Linkedin"
msgid "AdminUsers|Locked"
-msgstr ""
+msgstr "AdminUsers | 已鎖定"
msgid "AdminUsers|Log in"
-msgstr ""
+msgstr "登入"
msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
-msgstr ""
+msgstr "管ç†ï¼ˆæŽ¥å—/拒絕)掛起的使用者註冊"
msgid "AdminUsers|New user"
msgstr "新增使用者"
@@ -2998,7 +3015,7 @@ msgid "AdminUsers|Owned groups will be left"
msgstr "將會ä¿ç•™æ“有的群組"
msgid "AdminUsers|Pending approval"
-msgstr ""
+msgstr "待批准"
msgid "AdminUsers|Personal projects will be left"
msgstr "將會ä¿ç•™å€‹äººå°ˆæ¡ˆ"
@@ -3007,31 +3024,31 @@ msgid "AdminUsers|Personal projects, group and user history will be left intact"
msgstr "個人專案ã€ç¾¤çµ„和使用者歷å²è¨˜éŒ„將維æŒä¸è®Š"
msgid "AdminUsers|Quota of CI/CD minutes"
-msgstr ""
+msgstr "CI/CD 分é˜é…é¡"
msgid "AdminUsers|Reactivating a user will:"
msgstr "å–消å‡çµä½¿ç”¨è€…將會:"
msgid "AdminUsers|Regular"
-msgstr ""
+msgstr "一般"
msgid "AdminUsers|Regular users have access to their groups and projects."
-msgstr ""
+msgstr "普通使用者有權存å–他們的群組和專案。"
msgid "AdminUsers|Reject"
-msgstr ""
+msgstr "拒絕"
msgid "AdminUsers|Reject user %{username}?"
-msgstr ""
+msgstr "é§å›žä½¿ç”¨è€… %{username}?"
msgid "AdminUsers|Rejected users:"
-msgstr ""
+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 "還原使用者存å–帳戶的權é™ï¼ŒåŒ…括網é ã€Git å’Œ API。"
+msgstr "還原使用者存å–帳號的權é™ï¼ŒåŒ…括網é ã€Git å’Œ API。"
msgid "AdminUsers|Search by name, email or username"
msgstr "ä¾åå­—ã€é›»å­éƒµä»¶æˆ–使用者å稱æœå°‹"
@@ -3043,22 +3060,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 "一個群組æ¯å€‹æœˆå¯ä»¥ä½¿ç”¨å…±äº«åŸ·è¡Œå™¨ä¸Šçš„ CI/CD 最大分é˜æ•¸ã€‚設置為 0 表示沒有é™åˆ¶ã€‚設置為空則繼承 %{minutes} 的全域設置"
msgid "AdminUsers|The user can't access git repositories."
-msgstr ""
+msgstr "ä½¿ç”¨è€…ç„¡æ³•å­˜å– git 版本庫。"
msgid "AdminUsers|The user can't log in."
-msgstr ""
+msgstr "使用者無法登入。"
msgid "AdminUsers|The user has unlimited access to all groups, projects, users, and features."
-msgstr ""
+msgstr "管ç†ä½¿ç”¨è€…|使用者å¯ä»¥ç„¡é™åˆ¶åœ°è¨ªå•æ‰€æœ‰ç¾¤çµ„ã€å°ˆæ¡ˆã€äººå“¡å’ŒåŠŸèƒ½ã€‚"
msgid "AdminUsers|The user will be logged out"
msgstr "此使用者將會登出"
@@ -3082,22 +3099,22 @@ msgid "AdminUsers|To confirm, type %{username}"
msgstr "請輸入 %{username} 來確èª"
msgid "AdminUsers|Unban user"
-msgstr ""
+msgstr "å–消å°éŽ–"
msgid "AdminUsers|Unban user %{username}?"
-msgstr ""
+msgstr "是å¦è§£é™¤ %{username} çš„å°éŽ–?"
msgid "AdminUsers|Unblock"
-msgstr ""
+msgstr "å–消阻止"
msgid "AdminUsers|Unblock user %{username}?"
-msgstr ""
+msgstr "å–消阻止使用者 %{username}?"
msgid "AdminUsers|Unlock user %{username}?"
-msgstr ""
+msgstr "是å¦è§£é™¤ %{username} çš„å°éŽ–?"
msgid "AdminUsers|User administration"
-msgstr ""
+msgstr "使用者管ç†"
msgid "AdminUsers|User will not be able to access git repositories"
msgstr "ä½¿ç”¨è€…å°‡ç„¡æ³•å­˜å– git 版本庫"
@@ -3106,133 +3123,133 @@ msgid "AdminUsers|User will not be able to login"
msgstr "使用者將無法登入"
msgid "AdminUsers|Users"
-msgstr ""
+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 ""
+msgstr "使用者ä»ç„¶å¯ä»¥è¢«é‚€è«‹åˆ°æ‚¨çš„實例,和/或根據您的設定å…許使用者自行加入。直至您 %{approve_link},他們將無法存å–您的實例,也ä¸è¨ˆå…¥æ‚¨çš„訂閱席ä½ã€‚"
msgid "AdminUsers|Validate user account"
-msgstr ""
+msgstr "驗證使用者帳號"
msgid "AdminUsers|View pending member requests"
-msgstr ""
+msgstr "查看待處ç†çš„æˆå“¡è«‹æ±‚"
msgid "AdminUsers|Website URL"
-msgstr ""
+msgstr "網站 URL"
msgid "AdminUsers|What can I do?"
-msgstr ""
+msgstr "我å¯ä»¥åšç”šéº¼ï¼Ÿ"
msgid "AdminUsers|What does this mean?"
-msgstr ""
+msgstr "這是甚麼æ„æ€ï¼Ÿ"
msgid "AdminUsers|When banned:"
-msgstr ""
+msgstr "被å°éŽ–時:"
msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
-msgstr ""
+msgstr "使用者é‡æ–°ç™»å…¥å¾Œï¼Œå…¶å¸³è™Ÿå°‡å–消å‡çµæˆå®Œå…¨æ´»èºçš„帳號"
msgid "AdminUsers|Will be deleted"
-msgstr ""
+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 ""
+msgstr "您å³å°‡æ°¸ä¹…刪除使用者 %{username}。與他相關的議題ã€åˆä½µè«‹æ±‚åŠç¾¤çµ„將被轉移到系統下的「幽éˆä½¿ç”¨è€…ã€ã€‚為é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strongStart}å°éŽ–使用者%{strongEnd}功能。一旦您%{strongStart}刪除使用者%{strongEnd},就無法撤銷或æ¢å¾©ã€‚"
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 "您å³å°‡æ°¸ä¹…刪除使用者 %{username}。這會刪除與他相關的所有議題ã€åˆä½µè«‹æ±‚åŠç¾¤çµ„。為é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strongStart}å°éŽ–使用者%{strongEnd}功能。一旦您%{strongStart}刪除使用者%{strongEnd},就無法撤銷或æ¢å¾©ã€‚"
msgid "AdminUsers|You can always block their account again if needed."
-msgstr ""
+msgstr "如有需è¦ï¼Œä½ å¯ä»¥éš¨æ™‚å†æ¬¡å°éŽ–他們的帳號。"
msgid "AdminUsers|You can always deactivate their account again if needed."
-msgstr ""
+msgstr "如有需è¦ï¼Œä½ å¯ä»¥éš¨æ™‚å†æ¬¡åœç”¨ä»–們的帳號。"
msgid "AdminUsers|You can always re-activate their account, their data will remain intact."
-msgstr ""
+msgstr "ä½ å¯ä»¥éš¨æ™‚é‡æ–°å•Ÿç”¨ä»–們的帳號,他們的資料將會ä¿æŒä¸è®Šã€‚"
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
-msgstr ""
+msgstr "ä½ å¯ä»¥éš¨æ™‚解å°ä»–們的帳號,他們的資料將會維æŒä¸è®Šã€‚"
msgid "AdminUsers|You can ban their account in the future if necessary."
-msgstr ""
+msgstr "如有必è¦ï¼Œä½ å¯ä»¥åœ¨å°‡ä¾†å°éŽ–他們的帳號。"
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
-msgstr ""
+msgstr "ä½ å¯ä»¥åœ¨æ—¥å¾Œè§£é™¤å°éŽ–他們的帳號。他們的資料將維æŒä¸è®Šã€‚"
msgid "AdminUsers|You cannot remove your own administrator access."
-msgstr ""
+msgstr "您ä¸èƒ½åˆªé™¤æ‚¨è‡ªå·±çš„管ç†å“¡è¨ªå•æ¬Šé™ã€‚"
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
-msgstr ""
+msgstr "您必須轉讓所有權或刪除此使用者æ“有的群組,æ‰å¯ä»¥åˆªé™¤ä»–的帳號。"
msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
-msgstr ""
+msgstr "您的 GitLab 實例已é”到實例管ç†å“¡è¨­ç½®çš„最大å…è¨±æ•¸é‡ %{user_doc_link}。"
msgid "AdminUsers|approve them"
-msgstr ""
+msgstr "核准"
msgid "AdminUsers|contact our support team"
-msgstr ""
+msgstr "è¯ç¹«æˆ‘們的維護團隊"
msgid "AdminUsers|docs"
-msgstr ""
+msgstr "文件"
msgid "AdminUsers|user cap"
-msgstr ""
+msgstr "使用者上é™"
msgid "Administration"
-msgstr ""
+msgstr "管ç†ç•Œé¢"
msgid "Administrators"
-msgstr ""
+msgstr "系統管ç†å“¡"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
-msgstr ""
+msgstr "其他使用者必須經éŽç³»çµ±ç®¡ç†å“¡çš„審核和批准。詳細了解 %{help_link_start}使用上é™%{help_link_end}。"
msgid "Admin|Admin notes"
-msgstr ""
+msgstr "管ç†å‚™è¨»"
msgid "Admin|Learn more about quarterly reconciliation"
-msgstr ""
+msgstr "了解更多關於季度帳目的資訊"
msgid "Admin|Note"
-msgstr ""
+msgstr "備註"
msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
-msgstr ""
+msgstr "æ¯å­£çš„帳目核å°å°‡æ–¼ %{qrtlyDate}進行"
msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
-msgstr ""
+msgstr "您的命å空間中的最大席ä½æ•¸è¶…éŽäº†æ‚¨è¨‚閱中的席ä½æ•¸ã€‚將於 %{qrtlyDate}進行æ¯å­£åº¦ä¸€æ¬¡çš„å°è³¬ï¼Œä¸¦è‡ªå‹•æŒ‰æ¯”例å‘您收å–超é¡è²»ç”¨ã€‚您無需採å–任何行動。如果您有儲存信用å¡è³‡è¨Šï¼Œå°‡é€²è¡Œè‡ªå‹•æ‰£æ¬¾ã€‚å¦å‰‡æ‚¨å°‡æ”¶åˆ°ä»˜æ¬¾å¸³å–®ã€‚有關付款æµç¨‹åŸ·è¡Œæ™‚間的相關信æ¯ï¼Œè«‹æª¢è¦–文件。"
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 "您的實例中的最大使用者數超éŽäº†æ‚¨çš„許å¯è­‰ä¸­çš„使用者數。將於 %{qrtlyDate}進行æ¯å­£åº¦ä¸€æ¬¡çš„å°è³¬ï¼Œä¸¦è‡ªå‹•æŒ‰æ¯”例å‘您收å–超é¡è²»ç”¨ã€‚您無需採å–任何行動。如果您有儲存信用å¡è³‡è¨Šï¼Œå°‡é€²è¡Œè‡ªå‹•æ‰£æ¬¾ã€‚å¦å‰‡æ‚¨å°‡æ”¶åˆ°ä»˜æ¬¾å¸³å–®ã€‚有關付款æµç¨‹åŸ·è¡Œæ™‚間的相關信æ¯ï¼Œè«‹æª¢è¦–文件。"
msgid "Admin|View pending user approvals"
-msgstr ""
+msgstr "檢視待核准的使用者"
msgid "Admin|Your instance has reached its user cap"
-msgstr ""
+msgstr "您的實例已é”到其使用者上é™"
msgid "Advanced"
msgstr "進階"
msgid "Advanced Search"
-msgstr ""
+msgstr "進階æœå°‹"
msgid "Advanced Settings"
-msgstr ""
+msgstr "進階設定"
msgid "Advanced export options"
-msgstr ""
+msgstr "進階匯出é¸é …"
msgid "AdvancedSearch|Elasticsearch version not compatible"
-msgstr ""
+msgstr "Elasticsearch 版本ä¸ç›¸å®¹"
msgid "AdvancedSearch|Reindex required"
-msgstr ""
+msgstr "需è¦é‡æ–°å»ºç«‹ç´¢å¼•"
msgid "After a successful password update you will be redirected to login screen."
msgstr "密碼更新æˆåŠŸå¾Œï¼Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘至登入é é¢ã€‚"
@@ -3241,370 +3258,370 @@ 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 "éŽæœŸå¾Œï¼Œæ‚¨å°‡ç„¡æ³•æ‰¹å‡†åˆä½µè«‹æ±‚ã€æª¢è¦–代碼å“質或許多其他功能。"
msgid "After it expires, you can't use merge approvals, epics, or many other features."
-msgstr ""
+msgstr "éŽæœŸå¾Œï¼Œæ‚¨å°‡ç„¡æ³•æ‰¹å‡†åˆä½µè«‹æ±‚ã€å²è©©æˆ–許多其他功能。"
msgid "After it expires, you can't use merge approvals, epics, or many security features."
-msgstr ""
+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 "匯出完æˆå¾Œï¼Œå¾žé€šçŸ¥é›»å­éƒµä»¶æˆ–æ­¤é é¢ä¸‹è¼‰æ•¸æ“šæ–‡ä»¶ã€‚然後,您å¯ä»¥å¾žå¦ä¸€å€‹ GitLab 實例的 %{strong_text_start}建立新群組%{strong_text_end} é é¢åŒ¯å…¥æ•¸æ“šæ–‡ä»¶ã€‚"
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
-msgstr ""
+msgstr "在閱讀這些貢ç»æŒ‡å—後,您將準備好"
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
-msgstr ""
+msgstr "Akismet API 金鑰"
msgid "Akismet helps prevent the creation of spam issues in public projects."
-msgstr ""
+msgstr "Akismet 有助於防止在公開專案中產生垃圾議題。"
msgid "Alert"
-msgstr ""
+msgstr "警告"
msgid "AlertManagement|Acknowledged"
-msgstr ""
+msgstr "已確èª"
msgid "AlertManagement|Activity feed"
-msgstr ""
+msgstr "活動訂閱"
msgid "AlertManagement|Alert"
-msgstr ""
+msgstr "警報"
msgid "AlertManagement|Alert assignee(s): %{assignees}"
-msgstr ""
+msgstr "警示處ç†è€…: %{assignees}"
msgid "AlertManagement|Alert detail"
-msgstr ""
+msgstr "警報詳細資訊"
msgid "AlertManagement|Alert details"
-msgstr ""
+msgstr "警報詳細資訊"
msgid "AlertManagement|Alert status: %{status}"
-msgstr ""
+msgstr "警報狀態: %{status}"
msgid "AlertManagement|Alerts"
-msgstr ""
+msgstr "警報"
msgid "AlertManagement|All alerts"
-msgstr ""
+msgstr "所有警報"
msgid "AlertManagement|Assign status"
-msgstr ""
+msgstr "分é…狀態"
msgid "AlertManagement|Assignees"
-msgstr ""
+msgstr "分é…"
msgid "AlertManagement|Authorize external service"
-msgstr ""
+msgstr "授權外部æœå‹™"
msgid "AlertManagement|Create incident"
-msgstr ""
+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 ""
+msgstr "直接在GitLab中顯示來自所有監視工具的警報。簡化å°è­¦å ±çš„調查以åŠè­¦å ±å°äº‹ä»¶çš„å‡ç´šã€‚"
msgid "AlertManagement|Edit"
-msgstr ""
+msgstr "編輯"
msgid "AlertManagement|Environment"
-msgstr ""
+msgstr "環境"
msgid "AlertManagement|Events"
-msgstr ""
+msgstr "事件"
msgid "AlertManagement|Incident"
-msgstr ""
+msgstr "事件"
msgid "AlertManagement|Key"
-msgstr ""
+msgstr "éµ"
msgid "AlertManagement|Metrics"
-msgstr ""
+msgstr "指標"
msgid "AlertManagement|Metrics weren't available in the alerts payload."
-msgstr ""
+msgstr "相關指標無法在警示資訊中å–å¾—"
msgid "AlertManagement|More information"
-msgstr ""
+msgstr "更多資訊"
msgid "AlertManagement|No alert data to display."
-msgstr ""
+msgstr "無警報數據å¯é¡¯ç¤ºã€‚"
msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
-msgstr ""
+msgstr "警示管ç†|沒有å¯é¡¯ç¤ºçš„警報。有關將警報添加到列表的更多信æ¯ï¼Œè«‹åƒé–± %{linkStart}啟用警示管ç†%{linkEnd}。"
msgid "AlertManagement|No alerts to display."
-msgstr ""
+msgstr "無警報å¯é¡¯ç¤ºã€‚"
msgid "AlertManagement|None"
-msgstr ""
+msgstr "ç„¡"
msgid "AlertManagement|Open"
-msgstr ""
+msgstr "打開"
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "AlertManagement|Reported %{when}"
-msgstr ""
+msgstr "報告 %{when}"
msgid "AlertManagement|Reported %{when} by %{tool}"
-msgstr ""
+msgstr "報告 %{when} é€šéŽ %{tool}"
msgid "AlertManagement|Resolved"
-msgstr ""
+msgstr "解決"
msgid "AlertManagement|Runbook"
-msgstr ""
+msgstr "使用教學"
msgid "AlertManagement|Service"
-msgstr ""
+msgstr "æœå‹™"
msgid "AlertManagement|Severity"
-msgstr ""
+msgstr "åš´é‡æ€§"
msgid "AlertManagement|Start time"
-msgstr ""
+msgstr "開始時間"
msgid "AlertManagement|Status"
-msgstr ""
+msgstr "狀態"
msgid "AlertManagement|Surface alerts in GitLab"
-msgstr ""
+msgstr "GitLab中的表é¢è­¦å ±"
msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
-msgstr ""
+msgstr "顯示警報時出ç¾éŒ¯èª¤ã€‚è«‹é‡æ–°æ•´ç†é é¢ï¼Œç„¶å¾Œé‡è©¦ã€‚"
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
-msgstr ""
+msgstr "顯示警報時出錯。確èªçµ‚端點(endpoint)çš„é…置詳細資訊,以確ä¿å‡ºç¾è­¦å ±ã€‚"
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
-msgstr ""
+msgstr "在更新處ç†äººå“¡åˆ—表時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€é。"
msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
-msgstr ""
+msgstr "在更新警示的處ç†äººå“¡æ™‚出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€é。"
msgid "AlertManagement|There was an error while updating the status of the alert."
-msgstr ""
+msgstr "在更新警示狀態時出ç¾éŒ¯èª¤ã€‚"
msgid "AlertManagement|There was an error while updating the to-do item of the alert."
-msgstr ""
+msgstr "在更新警示待辦清單時發生錯誤。"
msgid "AlertManagement|This assignee cannot be assigned to this alert."
-msgstr ""
+msgstr "無法指派此人為這個警示的處ç†äººå“¡"
msgid "AlertManagement|Tool"
-msgstr ""
+msgstr "工具"
msgid "AlertManagement|Triggered"
-msgstr ""
+msgstr "已觸發"
msgid "AlertManagement|Value"
-msgstr ""
+msgstr "值"
msgid "AlertManagement|View incident"
-msgstr ""
+msgstr "查看å•é¡Œ"
msgid "AlertMappingBuilder|Define fallback"
-msgstr ""
+msgstr "定義回退"
msgid "AlertMappingBuilder|GitLab alert key"
-msgstr ""
+msgstr "GitLab 警示金鑰"
msgid "AlertMappingBuilder|Make selection"
-msgstr ""
+msgstr "è«‹é¸æ“‡"
msgid "AlertMappingBuilder|Payload alert key"
-msgstr ""
+msgstr "è£è¼‰è­¦ç¤ºé‡‘é‘°"
msgid "AlertMappingBuilder|Select key"
-msgstr ""
+msgstr "é¸å–金鑰"
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
-msgstr ""
+msgstr "標題是 GitLab 中警示的必填字段。如果您指定的有效è£è¼‰å­—段ä¸å¯ç”¨ï¼Œè«‹æŒ‡å®šæˆ‘們應該使用哪個字段。 "
msgid "AlertSettings|A webhook URL and authorization key is generated for the integration. After you save the integration, both are visible under the “View credentials†tab."
-msgstr ""
+msgstr "為整åˆç”¢ç”Ÿä¸€å€‹ webhook URL 和授權金鑰。ä¿å­˜æ•´åˆå¾Œï¼Œå…©è€…都在“查看憑據â€é¸é …å¡ä¸‹å¯è¦‹ã€‚"
msgid "AlertSettings|Add new integration"
-msgstr ""
+msgstr "新增新的整åˆ"
msgid "AlertSettings|Alert settings"
-msgstr ""
+msgstr "警報設置"
msgid "AlertSettings|Authorization key"
-msgstr ""
+msgstr "授權金鑰"
msgid "AlertSettings|Configure details"
-msgstr ""
+msgstr "é…置詳細信æ¯"
msgid "AlertSettings|Current integrations"
-msgstr ""
+msgstr "ç›®å‰çš„æ•´åˆ"
msgid "AlertSettings|Customize alert payload mapping (optional)"
-msgstr ""
+msgstr "自訂警示è£è¼‰å°æ‡‰ (å¯é¸)"
msgid "AlertSettings|Delete integration"
-msgstr ""
+msgstr "刪除整åˆ"
msgid "AlertSettings|Edit integration"
-msgstr ""
+msgstr "編輯整åˆ"
msgid "AlertSettings|Edit payload"
-msgstr ""
+msgstr "編輯è£è¼‰"
msgid "AlertSettings|Enable integration"
-msgstr ""
+msgstr "啟用整åˆ"
msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
-msgstr ""
+msgstr "輸入來自您é¸æ“‡çš„監視工具的示例è£è¼‰ã€‚這支æŒå‘ GitLab 端點發é€è­¦å ±ã€‚"
msgid "AlertSettings|Enter integration name"
-msgstr ""
+msgstr "輸入整åˆå稱"
msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
-msgstr ""
+msgstr "警示設定|GitLab çš„å…費版本僅é™æ–¼æ¯ç¨®é¡žåž‹ä¸€å€‹æ•´åˆã€‚è¦æ·»åŠ æ›´å¤šï¼Œ %{linkStart}å‡ç´šæ‚¨çš„訂閱%{linkEnd}。"
msgid "AlertSettings|GitLab has created a URL and authorization key for your integration. You can use them to set up a webhook and authorize your endpoint to send alerts to GitLab."
-msgstr ""
+msgstr "GitLab 已為您的整åˆå‰µå»ºäº† URL 和授權密鑰。您å¯ä»¥ä½¿ç”¨å®ƒå€‘來設置 webhook ä¸¦æŽˆæ¬Šæ‚¨çš„ç«¯é»žå‘ GitLab 發é€è­¦ç¤ºã€‚"
msgid "AlertSettings|HTTP Endpoint"
-msgstr ""
+msgstr "警報設置|HTTP 端點"
msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
-msgstr ""
+msgstr "如果您編輯è£è¼‰ï¼Œå‰‡å¿…é ˆå†æ¬¡é‡æ–°å°æ‡‰æ¬„ä½ã€‚"
msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
-msgstr ""
+msgstr "如果您é‡è¨­äº†æ­¤å°ˆæ¡ˆçš„授權金鑰,你必須在æ¯å€‹å·²å•Ÿç”¨çš„警示來æºä¸­æ›´æ–°è©²é‡‘鑰。"
msgid "AlertSettings|Integration successfully saved"
-msgstr ""
+msgstr "æˆåŠŸå„²å­˜æ•´åˆ"
msgid "AlertSettings|Name integration"
-msgstr ""
+msgstr "å稱整åˆ"
msgid "AlertSettings|Parse payload fields"
-msgstr ""
+msgstr "解æžè£è¼‰æ¬„ä½"
msgid "AlertSettings|Proceed with editing"
-msgstr ""
+msgstr "繼續編輯"
msgid "AlertSettings|Prometheus"
-msgstr ""
+msgstr "Prometheus"
msgid "AlertSettings|Prometheus API base URL"
-msgstr ""
+msgstr "Prometheus API 基本 URL"
msgid "AlertSettings|Reset Key"
-msgstr ""
+msgstr "é‡ç½®é‡‘é‘°"
msgid "AlertSettings|Reset the mapping"
-msgstr ""
+msgstr "é‡è¨­å°æ‡‰"
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
-msgstr ""
+msgstr "已解æžè£è¼‰æ¨£æœ¬ã€‚您ç¾åœ¨å¯ä»¥å°æ‡‰æ¬„ä½ã€‚"
msgid "AlertSettings|Save & create test alert"
-msgstr ""
+msgstr "儲存並建立測試警示"
msgid "AlertSettings|Save integration"
-msgstr ""
+msgstr "儲存整åˆ"
msgid "AlertSettings|Save integration & send"
-msgstr ""
+msgstr "儲存整åˆä¸¦ç™¼é€"
msgid "AlertSettings|Select integration type"
-msgstr ""
+msgstr "é¸æ“‡æ•´åˆé¡žåž‹"
msgid "AlertSettings|Send test alert"
-msgstr ""
+msgstr "發é€æ¸¬è©¦è­¦ç¤º"
msgid "AlertSettings|Send without saving"
-msgstr ""
+msgstr "發é€ä½†ä¸å„²å­˜"
msgid "AlertSettings|The form has unsaved changes"
-msgstr ""
+msgstr "表格有尚未儲存的變更"
msgid "AlertSettings|The form has unsaved changes. How would you like to proceed?"
-msgstr ""
+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 ""
+msgstr "如è¦å»ºç«‹è‡ªè¨‚å°æ‡‰ï¼Œè«‹æ–¼æ‚¨çš„監視工具中輸入 JSON æ ¼å¼çš„è£è¼‰ç¯„例。點é¸ã€Œè§£æžè£è¼‰æ¬„ä½ã€æŒ‰éˆ•ä»¥ç¹¼çºŒã€‚"
msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
-msgstr ""
+msgstr " URL ä¸å¯ç•™ç©ºï¼Œå¿…須以 http: 或 https 開頭。"
msgid "AlertSettings|Use the URL and authorization key below to configure how Prometheus sends alerts to GitLab. Review the %{linkStart}GitLab documentation%{linkEnd} to learn how to configure your endpoint."
-msgstr ""
+msgstr "使用以下的 URL 和授權金鑰來設定 Prometheus 發é€è­¦ç¤ºåˆ° GitLab çš„æ–¹å¼ã€‚查看 %{linkStart}GitLab 文件%{linkEnd}學習如何設定您的端點。"
msgid "AlertSettings|Use the URL and authorization key below to configure how an external service sends alerts to GitLab. %{linkStart}How do I configure the endpoint?%{linkEnd}"
-msgstr ""
+msgstr "使用下é¢çš„ URL 和授權金鑰來é…置外部æœå‹™ç™¼é€è­¦ç¤ºåˆ° GitLab çš„æ–¹å¼ã€‚%{linkStart}我如何é…置端點?%{linkEnd}"
msgid "AlertSettings|View URL and authorization key"
-msgstr ""
+msgstr "查看 URL 和授權金鑰"
msgid "AlertSettings|View credentials"
-msgstr ""
+msgstr "查看憑證"
msgid "AlertSettings|Webhook URL"
-msgstr ""
+msgstr "Webhook網å€"
msgid "AlertSettings|You can map default GitLab alert fields to your payload keys in the dropdowns below."
-msgstr ""
+msgstr "您å¯ä»¥å¾žä¸‹æ–¹çš„下拉é¸å–®ä¸­ï¼Œå°‡é è¨­çš„ GitLab 警示欄ä½å°æ‡‰åˆ°æ‚¨çš„è£è¼‰é‡‘鑰。"
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
-msgstr ""
+msgstr "{ \"events\": [{ \"application\": \"應用程å¼å稱\" }] }"
msgid "Alerts"
msgstr "警示"
msgid "AlertsIntegrations|Alerts will be created through this integration"
-msgstr ""
+msgstr "å°‡é€éŽæ­¤æ•´åˆå»ºç«‹è­¦ç¤º"
msgid "AlertsIntegrations|Alerts will not be created through this integration"
-msgstr ""
+msgstr "å°‡ä¸æœƒé€éŽæ­¤æ•´åˆå»ºç«‹è­¦ç¤º"
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
-msgstr ""
+msgstr "如果您刪除了 %{integrationName} æ•´åˆï¼Œå‰‡ä¸å†å¾žæ­¤ç«¯é»žç™¼é€è­¦ç¤ºã€‚此動作無法撤銷。"
msgid "AlertsIntegrations|Integration Name"
-msgstr ""
+msgstr "æ•´åˆå稱"
msgid "AlertsIntegrations|Integration payload is invalid."
-msgstr ""
+msgstr "æ•´åˆè£è¼‰ç„¡æ•ˆã€‚"
msgid "AlertsIntegrations|No integrations have been added yet."
-msgstr ""
+msgstr "尚未加入整åˆã€‚"
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
-msgstr ""
+msgstr "無法更新目å‰æ•´åˆã€‚è«‹é‡è©¦ã€‚"
msgid "AlertsIntegrations|The integration could not be added. Please try again."
-msgstr ""
+msgstr "無法新增此整åˆã€‚è«‹é‡è©¦ã€‚"
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
-msgstr ""
+msgstr "無法刪除此整åˆã€‚è«‹é‡è©¦ã€‚"
msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
-msgstr ""
+msgstr "此整åˆç›®å‰ä¸¦æœªå•Ÿç”¨ã€‚啟用此整åˆä¾†ç™¼é€è­¦ç¤ºæ¸¬è©¦ã€‚"
msgid "AlertsIntegrations|The integration is deleted."
-msgstr ""
+msgstr "已刪除此整åˆã€‚"
msgid "AlertsIntegrations|The integration is saved."
-msgstr ""
+msgstr "已儲存此整åˆã€‚"
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
-msgstr ""
+msgstr "無法é‡è¨­æ•´åˆæ†‘證。請é‡è©¦ã€‚"
msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
-msgstr ""
+msgstr "測試警示ç¾åœ¨æ‡‰è©²é¡¯ç¤ºåœ¨æ‚¨çš„警示列表中。"
msgid "Algorithm"
msgstr "演算法"
@@ -3613,13 +3630,13 @@ msgid "All"
msgstr "全部"
msgid "All %{replicableType} are being scheduled for %{action}"
-msgstr ""
+msgstr "全部 %{replicableType} 計劃為 %{action}"
msgid "All (default)"
-msgstr ""
+msgstr "全部 (é è¨­)"
msgid "All GitLab"
-msgstr ""
+msgstr "所有 GitLab"
msgid "All Members"
msgstr "所有æˆå“¡"
@@ -3630,17 +3647,20 @@ 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 ""
+msgstr "所有環境"
msgid "All groups and projects"
msgstr "所有群組和專案"
msgid "All issues"
-msgstr ""
+msgstr "所有議題"
msgid "All issues for this milestone are closed."
msgstr "此里程碑的所有議題å‡å·²é—œé–‰ã€‚"
@@ -3655,112 +3675,112 @@ msgid "All merge request dependencies have been merged"
msgstr "所有åˆä½µè«‹æ±‚ä¾è³´é—œä¿‚å‡å·²åˆä½µ"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
-msgstr ""
+msgstr "所有路徑都相å°æ–¼ GitLab URL。ä¸åŒ…括%{relative_url_link_start}ç›¸å° URL%{relative_url_link_end}。"
msgid "All projects"
msgstr "所有專案"
msgid "All projects selected"
-msgstr ""
+msgstr "所有已é¸å–的專案"
msgid "All protected branches"
-msgstr ""
+msgstr "所有å—ä¿è­·çš„分支"
msgid "All threads resolved!"
-msgstr ""
+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 ""
+msgstr "所有使用者必須接å—æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–æ‰èƒ½å­˜å– GitLab"
msgid "All users must have a name."
msgstr "所有的使用者都必須具有å稱。"
msgid "All users with matching cards"
-msgstr ""
+msgstr "所有æ“有匹é…å¡çš„使用者"
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…許「%{group_name}ã€ä»¥æ‚¨çš„身份登入"
msgid "Allow access to members of the following group"
-msgstr ""
+msgstr "å…許以下群組的æˆå“¡å­˜å–"
msgid "Allow access to the following IP addresses"
-msgstr ""
+msgstr "å…許下列IPä½å€å­˜å–"
msgid "Allow commits from members who can merge to the target branch. %{link_start}About this feature.%{link_end}"
-msgstr ""
+msgstr "å…許具有åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯æ¬Šé™çš„æˆå“¡æ交,%{link_start}關於該功能。%{link_end}"
msgid "Allow group owners to manage LDAP-related settings"
msgstr "å…è¨±ç¾¤çµ„æ‰€æœ‰è€…ç®¡ç† LDAP 相關的設定"
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "å…許éžç®¡ç†å“¡å­˜å–效能資訊欄"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "僅å…許é¸å–之用於 Git å­˜å–的通訊å”定。"
msgid "Allow owners to manage default branch protection per group."
-msgstr ""
+msgstr "å…許æ“有者管ç†æ¯å€‹çµ„別的é è¨­åˆ†æ”¯ä¿è­·ã€‚"
msgid "Allow owners to manually add users outside of LDAP"
-msgstr ""
+msgstr "å…許所有者手動添加LDAP之外的使用者"
msgid "Allow password authentication for Git over HTTP(S)"
-msgstr ""
+msgstr "å…è¨±é€šéŽ HTTP(S) å° Git 進行密碼驗證"
msgid "Allow password authentication for the web interface"
-msgstr ""
+msgstr "å…許通éŽç¶²é ç•Œé¢çš„密碼驗證"
msgid "Allow project maintainers to configure repository mirroring"
-msgstr ""
+msgstr "å…許維護者é…置版本庫"
msgid "Allow projects and subgroups to override the group setting"
-msgstr ""
+msgstr "å…許專案和å­ç¾¤çµ„覆寫群組設置"
msgid "Allow projects within this group to use Git LFS"
msgstr "å…許該群組內的專案使用 Git LFS"
msgid "Allow public access to pipelines and job details, including output logs and artifacts."
-msgstr ""
+msgstr "å…許公開存å–æµæ°´ç·šå’Œä½œæ¥­è©³ç´°è³‡è¨Šï¼ŒåŒ…å«è¼¸å‡ºè¨˜éŒ„和產物."
msgid "Allow this key to push to this repository"
-msgstr ""
+msgstr "å…許此金鑰推é€åˆ°æ­¤ç‰ˆæœ¬åº«"
msgid "Allow use of licensed EE features"
-msgstr ""
+msgstr "å…許使用許å¯çš„ EE 功能"
msgid "Allow users to dismiss the broadcast message"
-msgstr ""
+msgstr "å…許使用者忽略廣播訊æ¯"
msgid "Allow users to register any application to use GitLab as an OAuth provider"
msgstr "å…許使用者註冊任何應用程å¼ï¼Œä½¿ç”¨ GitLab 作為 OAuth æ供者"
msgid "Allowed"
-msgstr ""
+msgstr "å·²å…許"
msgid "Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "å…許的字符:+ã€0-9ã€- 和空格。"
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "åªå…許頂層群組使用電å­éƒµä»¶ç¶²åŸŸé™åˆ¶"
msgid "Allowed to create:"
-msgstr ""
+msgstr "å…許創建:"
msgid "Allowed to delete projects"
-msgstr ""
+msgstr "å…許刪除專案"
msgid "Allowed to fail"
msgstr "å…許失敗"
msgid "Allows projects or subgroups in this group to override the global setting."
-msgstr ""
+msgstr "å…許該群組中的專案或å­ç¾¤çµ„覆寫全局設置。"
msgid "Allows projects to track errors using an Opstrace integration."
-msgstr ""
+msgstr "å…許專案使用 Opstrace æ•´åˆä¾†è¿½è¸ªéŒ¯èª¤ã€‚"
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "讓你能加入åŠç®¡ç† Kubernetes å¢é›†ã€‚"
@@ -3769,13 +3789,13 @@ msgid "Almost there"
msgstr "å³å°‡å®Œæˆ"
msgid "Almost there..."
-msgstr ""
+msgstr "å³å°‡å®Œæˆ..."
msgid "Already blocked"
-msgstr ""
+msgstr "已被鎖定"
msgid "Already have login and password?"
-msgstr ""
+msgstr "已經有登入帳號和密碼?"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "也稱為「簽發者ã€æˆ–「信任憑證者信任識別碼ã€"
@@ -3784,16 +3804,16 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "也稱為「信任憑證者æœå‹™ç¶²å€ã€æˆ–「回覆網å€ã€"
msgid "Also remove direct user membership from subgroups and projects"
-msgstr ""
+msgstr "一併從å­ç¾¤çµ„和專案中刪除使用者æˆå“¡è³‡æ ¼"
msgid "Also unassign this user from related issues and merge requests"
-msgstr ""
+msgstr "åŒæ™‚從相關議題和åˆä½µè«‹æ±‚中å–消指派此使用者"
msgid "Alternate support URL for Help page and Help dropdown."
-msgstr ""
+msgstr "說明é é¢å’Œèªªæ˜Žä¸‹æ‹‰é¸å–®çš„備用支æ´ç¶²å€."
msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
-msgstr ""
+msgstr "或者,您å¯ä»¥å°‡æ‚¨çš„帳號轉æ›ç‚º %{group_name} 群組的託管帳號。"
msgid "Amazon EKS"
msgstr "Amazon EKS"
@@ -3802,31 +3822,31 @@ msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
msgstr "Amazon EKS æ•´åˆè®“您能從 GitLab ç®¡ç† EKS å¢é›†ã€‚"
msgid "Amazon Web Services Logo"
-msgstr ""
+msgstr "Amazon 網路æœå‹™æ¨™èªŒ"
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
-msgstr ""
+msgstr "具有相åŒæŒ‡ç´‹çš„ %{link_start}警示%{link_end} 已開啟。è¦æ›´æ”¹æ­¤è­¦ç¤ºçš„狀態,請解決此éˆæŽ¥çš„警示。"
msgid "An Administrator has set the maximum expiration date to %{maxDate}. %{helpLinkStart}Learn more%{helpLinkEnd}."
-msgstr ""
+msgstr "管ç†å“¡å·²å°‡æœ€çµ‚的到期日期設置為 %{maxDate}。 %{helpLinkStart}了解更多%{helpLinkEnd}。"
msgid "An Enterprise User GitLab account has been created for you by your organization:"
-msgstr ""
+msgstr "您的組織已為您創建了一個ä¼æ¥­ä½¿ç”¨è€… GitLab 帳號:"
msgid "An administrator changed the password for your GitLab account on %{link_to}."
-msgstr ""
+msgstr "管ç†å“¡åœ¨ %{link_to}上更改了您 GitLab 帳號的密碼。"
msgid "An alert has been resolved in %{project_path}."
-msgstr ""
+msgstr "警示已於 %{project_path}中解決。"
msgid "An alert has been triggered in %{project_path}."
-msgstr ""
+msgstr "警示已在 %{project_path}中觸發。"
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr "æ‡‰ç”¨ç¨‹å¼ %{link_to_client} 請求存å–您的 GitLab 帳戶。"
+msgstr "æ‡‰ç”¨ç¨‹å¼ %{link_to_client} 請求存å–您的 GitLab 帳號。"
msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
-msgstr ""
+msgstr "管ç†é¢æ¿å‰›æ‰ç™¼é€äº†ä¸€å°é›»å­éƒµä»¶é€šçŸ¥ã€‚請等待 %{wait_time_in_words} ,然後å†å˜—試發é€å¦ä¸€æ¢è¨Šæ¯ã€‚"
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空 GitLab 使用者欄ä½å°‡åœ¨æ‰€æœ‰è­°é¡ŒåŠç•™è¨€çš„æ述中加入 FogBugz 使用者的全å(例如「由 John Smithã€ï¼‰ã€‚其還會與專案建立者關è¯å’Œï¼æˆ–分é…這些議題或留言。"
@@ -3835,7 +3855,7 @@ msgid "An error has occurred"
msgstr "發生錯誤"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
-msgstr ""
+msgstr "報告錯誤,測試çµæžœéŒ¯èª¤åœ°æŒ‡ç¤ºç³»çµ±ä¸­å­˜åœ¨æ¼æ´žï¼Œè€Œæ¼æ´žä¸å­˜åœ¨ã€‚"
msgid "An error occurred adding a draft to the thread."
msgstr "å‘話題加入è‰ç¨¿æ™‚發生錯誤。"
@@ -3856,37 +3876,37 @@ msgid "An error occurred fetching the dropdown data."
msgstr "抓å–下拉資料時發生錯誤。"
msgid "An error occurred fetching the project authors."
-msgstr ""
+msgstr "ç²å–項目作者時發生錯誤。"
msgid "An error occurred fetching the public deploy keys. Please try again."
-msgstr ""
+msgstr "ç²å–公共部署金鑰時出錯。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 時發生錯誤"
msgid "An error occurred when loading the user verification challenge. Refresh to try again."
-msgstr ""
+msgstr "加載使用者驗證質詢時發生錯誤。請é‡æ–°æ•´ç†é é¢ï¼Œå†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred when updating the title"
-msgstr ""
+msgstr "更新標題時發生錯誤"
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
-msgstr ""
+msgstr "確èªé€šçŸ¥æ™‚發生錯誤,請é‡æ–°æ•´ç†ä¸¦å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred while adding approvers"
-msgstr ""
+msgstr "新增核准者時發生錯誤"
msgid "An error occurred while adding formatted title for epic"
-msgstr ""
+msgstr "為å²è©©(epic)添加格å¼åŒ–標題時發生錯誤"
msgid "An error occurred while authorizing your role"
-msgstr ""
+msgstr "授權您的角色時發生錯誤"
msgid "An error occurred while checking group path. Please refresh and try again."
-msgstr ""
+msgstr "檢查群組路徑時發生錯誤,請é‡æ–°æ•´ç†ä¸¦å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred while decoding the file."
-msgstr ""
+msgstr "譯解檔案時發生錯誤。"
msgid "An error occurred while deleting the approvers group"
msgstr "刪除核准者群組時發生錯誤"
@@ -3910,34 +3930,31 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "忽略功能çªé¡¯æ™‚發生錯誤。請é‡æ–°æ•´ç†é é¢ä¸¦å†æ¬¡å˜—試。"
msgid "An error occurred while drawing job relationship links."
-msgstr ""
+msgstr "繪製作業關係éˆæŽ¥æ™‚發生錯誤。"
msgid "An error occurred while enabling Service Desk."
msgstr "啟用æœå‹™å°æ™‚發生錯誤。"
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "ç²å– Markdown é è¦½æ™‚發生錯誤"
msgid "An error occurred while fetching ancestors"
-msgstr ""
-
-msgid "An error occurred while fetching branches."
-msgstr ""
+msgstr "ç²å–上級(ancestors)時發生錯誤"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "ç²å–分支時發生錯誤,請é‡æ–°æœç´¢ã€‚"
msgid "An error occurred while fetching codequality mr diff reports."
-msgstr ""
+msgstr "ç²å–代碼質é‡åˆä½µè«‹æ±‚差異報告時發生錯誤。"
msgid "An error occurred while fetching commit data."
-msgstr ""
+msgstr "ç²å–æ交數據時發生錯誤。"
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "ç²å–æ交時發生錯誤,請é‡æ–°æœç´¢ã€‚"
msgid "An error occurred while fetching coverage reports."
-msgstr ""
+msgstr "在載入涵蓋報告時發生錯誤,請é‡è©¦"
msgid "An error occurred while fetching environments."
msgstr "抓å–環境時發生錯誤。"
@@ -3955,10 +3972,10 @@ msgid "An error occurred while fetching label colors."
msgstr "抓å–標籤é¡è‰²æ™‚發生錯誤。"
msgid "An error occurred while fetching participants"
-msgstr ""
+msgstr "ç²å–åƒèˆ‡è€…時發生錯誤"
msgid "An error occurred while fetching participants."
-msgstr ""
+msgstr "ç²å–åƒèˆ‡è€…時發生錯誤。"
msgid "An error occurred while fetching pending comments"
msgstr "抓å–待處ç†ç•™è¨€æ™‚發生錯誤"
@@ -3967,19 +3984,22 @@ msgid "An error occurred while fetching projects autocomplete."
msgstr "抓å–專案自動完æˆæ™‚發生錯誤。"
msgid "An error occurred while fetching reference"
-msgstr ""
+msgstr "ç²å–åƒè€ƒæ™‚發生錯誤"
+
+msgid "An error occurred while fetching reviewers."
+msgstr "æ“·å–檢閱者時發生錯誤。"
msgid "An error occurred while fetching tags. Retry the search."
-msgstr ""
+msgstr "在載入標籤時發生錯誤,請é‡è©¦"
msgid "An error occurred while fetching terraform reports."
-msgstr ""
+msgstr "ç²å–é …ç›®(terraform)報告時發生錯誤。"
msgid "An error occurred while fetching the job log."
msgstr "抓å–作業日誌時發生錯誤。"
msgid "An error occurred while fetching the job logs."
-msgstr ""
+msgstr "æ“·å–作業記錄時發生錯誤。"
msgid "An error occurred while fetching the job."
msgstr "抓å–作業時發生錯誤。"
@@ -3991,7 +4011,7 @@ msgid "An error occurred while fetching the latest pipeline."
msgstr "抓å–最後一個æµæ°´ç·šæ™‚發生錯誤。"
msgid "An error occurred while fetching the pipelines jobs."
-msgstr ""
+msgstr "ç²å–æµæ°´ç·šä½œæ¥­æ™‚發生錯誤。"
msgid "An error occurred while fetching the releases. Please try again."
msgstr "抓å–發行版本時發生錯誤。請é‡è©¦ã€‚"
@@ -4003,7 +4023,7 @@ msgid "An error occurred while getting files for - %{branchId}"
msgstr "å–å¾— %{branchId} 的檔案時發生錯誤"
msgid "An error occurred while getting issue counts"
-msgstr ""
+msgstr "ç²å–議題數é‡æ™‚發生錯誤"
msgid "An error occurred while getting projects"
msgstr "å–得專案時發生錯誤"
@@ -4012,7 +4032,7 @@ msgid "An error occurred while initializing path locks"
msgstr "åˆå§‹åŒ–路徑鎖時發生錯誤"
msgid "An error occurred while loading a section of this page."
-msgstr ""
+msgstr "加載此é é¢çš„æŸéƒ¨åˆ†æ™‚發生錯誤。"
msgid "An error occurred while loading all the files."
msgstr "載入所有檔案時發生錯誤。"
@@ -4021,7 +4041,7 @@ msgid "An error occurred while loading chart data"
msgstr "載入圖表資料時發生錯誤"
msgid "An error occurred while loading code owners."
-msgstr ""
+msgstr "加載代碼所有者時發生錯誤。"
msgid "An error occurred while loading commit signatures"
msgstr "載入æ交簽å時發生錯誤"
@@ -4042,25 +4062,22 @@ msgid "An error occurred while loading issues"
msgstr "載入議題時發生錯誤"
msgid "An error occurred while loading merge requests."
-msgstr ""
+msgstr "載入åˆä½µè«‹æ±‚時發生錯誤。"
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "載入專案時發生錯誤。"
msgid "An error occurred while loading the Jobs tab."
-msgstr ""
+msgstr "加載作業é¸é …é æ™‚發生錯誤。"
msgid "An error occurred while loading the Needs tab."
-msgstr ""
+msgstr "加載“需求â€é¸é …é æ™‚發生錯誤。"
msgid "An error occurred while loading the Test Reports tab."
-msgstr ""
-
-msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
+msgstr "加載“測試報告â€é¸é …é æ™‚發生錯誤。"
msgid "An error occurred while loading the blob controls."
-msgstr ""
+msgstr "加載 blob 控制軟體套件時發生錯誤。"
msgid "An error occurred while loading the data. Please try again."
msgstr "載入資料時發生錯誤。請é‡è©¦ã€‚"
@@ -4075,10 +4092,10 @@ msgid "An error occurred while loading the file."
msgstr "載入檔案時發生錯誤。"
msgid "An error occurred while loading the file. Please try again later."
-msgstr ""
+msgstr "加載文件時發生錯誤,請ç¨å¾Œå†è©¦ã€‚"
msgid "An error occurred while loading the file. Please try again."
-msgstr ""
+msgstr "加載文件時發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred while loading the merge request changes."
msgstr "載入åˆä½µè«‹æ±‚的變更內容時發生錯誤。"
@@ -4090,10 +4107,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 "加載通知設定時發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "An error occurred while loading the pipeline."
-msgstr ""
+msgstr "載入æµæ°´ç·šæ™‚發生錯誤。"
msgid "An error occurred while loading the pipelines jobs."
msgstr "載入æµæ°´ç·šä½œæ¥­æ™‚發生錯誤。"
@@ -4108,13 +4125,13 @@ msgid "An error occurred while parsing recent searches"
msgstr "解æžæœ€è¿‘æœå°‹æ™‚發生錯誤"
msgid "An error occurred while parsing the file."
-msgstr ""
+msgstr "讀å–檔案時發生錯誤"
msgid "An error occurred while pasting text in the editor. Please try again."
-msgstr ""
+msgstr "在編輯器中貼上文字時發生錯誤。請é‡è©¦ã€‚"
msgid "An error occurred while performing this action."
-msgstr ""
+msgstr "執行該æ“作時發生錯誤"
msgid "An error occurred while removing epics."
msgstr "移除å²è©©æ™‚發生錯誤。"
@@ -4126,7 +4143,7 @@ msgid "An error occurred while rendering preview broadcast message"
msgstr "繪製廣播訊æ¯æ™‚發生錯誤"
msgid "An error occurred while rendering the editor"
-msgstr ""
+msgstr "顯示編輯器時發生錯誤"
msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè­°é¡Œæ™‚發生錯誤。"
@@ -4138,23 +4155,23 @@ msgid "An error occurred while retrieving diff"
msgstr "å–得差異時發生錯誤"
msgid "An error occurred while retrieving diff files"
-msgstr ""
+msgstr "讀å–變更紀錄時發生錯誤"
msgid "An error occurred while retrieving projects."
-msgstr ""
+msgstr "讀å–專案時發生錯誤"
msgid "An error occurred while retrieving your settings. Reload the page to try again."
-msgstr ""
+msgstr "讀å–您的設定時發生錯誤。é‡æ–°è¼‰å…¥é é¢ç™¼ç”ŸéŒ¯èª¤é‡è©¦ã€‚"
msgid "An error occurred while saving changes: %{error}"
-msgstr ""
+msgstr "儲存變更:%{error}時發生錯誤"
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
-msgstr[0] ""
+msgstr[0] "儲存設定時發生錯誤"
msgid "An error occurred while saving your settings. Try saving them again."
-msgstr ""
+msgstr "儲存您的設定時發生錯誤。試著å†æ¬¡å„²å­˜æ‚¨çš„設定。"
msgid "An error occurred while subscribing to notifications."
msgstr "訂閱通知時發生錯誤。"
@@ -4163,16 +4180,16 @@ msgid "An error occurred while triggering the job."
msgstr "觸發作業時發生錯誤。"
msgid "An error occurred while trying to follow this user, please try again."
-msgstr ""
+msgstr "嘗試跟隨此使用者時發生錯誤,請é‡è©¦ã€‚"
msgid "An error occurred while trying to generate the report. Please try again later."
-msgstr ""
+msgstr "試圖製作報告時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
msgid "An error occurred while trying to run a new pipeline for this merge request."
-msgstr ""
+msgstr "嘗試執行此åˆä½µè«‹æ±‚çš„æ–°æµæ°´ç·šæ™‚發生錯誤。"
msgid "An error occurred while trying to unfollow this user, please try again."
-msgstr ""
+msgstr "嘗試å–消關注此使用者發生錯誤,請é‡è©¦ã€‚"
msgid "An error occurred while unsubscribing to notifications."
msgstr "å–消訂閱通知時發生錯誤。"
@@ -4181,25 +4198,25 @@ msgid "An error occurred while updating approvers"
msgstr "更新核准者時發生錯誤"
msgid "An error occurred while updating assignees."
-msgstr ""
+msgstr "更新被指派人時發生錯誤。"
msgid "An error occurred while updating configuration."
-msgstr ""
+msgstr "æ›´æ–°é…置時發生錯誤。"
msgid "An error occurred while updating labels."
-msgstr ""
+msgstr "更新標籤時發生錯誤。"
msgid "An error occurred while updating the comment"
msgstr "更新留言時發生錯誤"
msgid "An error occurred while updating the configuration."
-msgstr ""
+msgstr "æ›´æ–°é…置時發生錯誤。"
msgid "An error occurred while updating the notification settings. Please try again."
-msgstr ""
+msgstr "更新通知設定時發生錯誤。請é‡è©¦ã€‚"
msgid "An error occurred while uploading the file. Please try again."
-msgstr ""
+msgstr "上傳檔案時發生錯誤。請é‡è©¦ã€‚"
msgid "An error occurred while validating group path"
msgstr "驗證群組路徑時發生錯誤"
@@ -4208,37 +4225,37 @@ msgid "An error occurred while validating username"
msgstr "驗證使用者å稱時發生錯誤"
msgid "An error occurred. Please sign in again."
-msgstr ""
+msgstr "發生錯誤,請é‡æ–°ç™»å…¥ã€‚"
msgid "An error occurred. Please try again."
msgstr "發生了錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "An example project for managing Kubernetes clusters integrated with GitLab"
-msgstr ""
+msgstr "ç®¡ç† Kubernetes å¢é›†èˆ‡ 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 "一個範例專案,展示了為您自己的組織設置 GitLab 的最佳實åšï¼ŒåŒ…括範例議題ã€åˆä½µè«‹æ±‚和里程碑"
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
-msgstr ""
+msgstr "å°‡ Jsonnet çµåˆ GitLab å‹•æ…‹å­æµæ°´ç®¡ç·šçš„範例"
msgid "An incident has been resolved in %{project_path}."
-msgstr ""
+msgstr "事件已於 %{project_path} 中解決。"
msgid "An incident has been triggered in %{project_path}."
-msgstr ""
+msgstr "事件已於 %{project_path} 中觸發。"
msgid "An integer value is required for seconds"
-msgstr ""
+msgstr "秒數必須為整數"
msgid "An issue already exists"
-msgstr ""
+msgstr "該議題已存在"
msgid "An unauthenticated user"
-msgstr ""
+msgstr "未經驗證的使用者"
msgid "An unexpected error occurred"
-msgstr ""
+msgstr "發生æ„外的錯誤"
msgid "An unexpected error occurred while checking the project environment."
msgstr "檢查專案環境時發生æ„外錯誤。"
@@ -4250,7 +4267,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 "加載程å¼ç¢¼è³ªé‡å·®ç•°æ¯”較時,發生æ„外錯誤。"
msgid "An unexpected error occurred while starting the Web Terminal."
msgstr "啟動網é çµ‚端機時發生æ„外錯誤。"
@@ -4259,422 +4276,452 @@ msgid "An unexpected error occurred while stopping the Web Terminal."
msgstr "åœæ­¢ç¶²é çµ‚端機時發生æ„外錯誤。"
msgid "An unknown error occurred while loading this graph."
-msgstr ""
+msgstr "載入圖片時發生錯誤"
msgid "An unknown error occurred."
-msgstr ""
+msgstr "發生未知的錯誤"
msgid "Analytics"
msgstr "分æž"
msgid "Analyze your dependencies for known vulnerabilities."
-msgstr ""
+msgstr "分æžå·²çŸ¥æ¼æ´žçš„ä¾è³´é—œä¿‚"
msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
-msgstr ""
+msgstr "將您的基礎設施作為已知æ¼æ´žçš„代碼é…置文件進行分æžã€‚"
msgid "Analyze your source code and git history for secrets."
-msgstr ""
+msgstr "分æžæ‚¨çš„程å¼ç¢¼å’Œ git æ­·å²ã€‚"
msgid "Analyze your source code for known vulnerabilities."
-msgstr ""
+msgstr "分æžæ‚¨ç¨‹å¼ç¢¼ä¸­çš„已知æ¼æ´ž"
msgid "Analyzing file…"
-msgstr ""
+msgstr "正在分æžæ–‡ä»¶â€¦"
msgid "Ancestors"
-msgstr ""
+msgstr "祖先"
msgid "And this registration token:"
-msgstr ""
+msgstr "以åŠè©²è¨»å†Šæ†‘證:"
msgid "Anonymous"
-msgstr ""
+msgstr "匿å"
msgid "Another action is currently in progress"
-msgstr ""
+msgstr "ç›®å‰æ­£åœ¨åŸ·è¡Œå¦ä¸€é …作業"
msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
-msgstr ""
+msgstr "å¦ä¸€å€‹è­°é¡Œè¿½è¹¤å™¨å·²ç¶“在使用中。一次åªèƒ½å•Ÿç”¨ä¸€å€‹è­°é¡Œè¿½è¹¤æœå‹™"
msgid "Another third-party wiki is already in use. Only one third-party wiki integration can be active at a time"
-msgstr ""
+msgstr "å¦ä¸€å€‹ç¬¬ä¸‰æ–¹ Wiki 已經在使用,åŒä¸€æ™‚é–“åªèƒ½å•Ÿç”¨ä¸€å€‹ç¬¬ä¸‰æ–¹ Wiki。"
msgid "Anti-spam verification"
-msgstr ""
+msgstr "å垃圾郵件驗證"
msgid "Any"
msgstr "任何"
msgid "Any %{header}"
-msgstr ""
+msgstr "任何 %{header}"
msgid "Any Author"
-msgstr ""
+msgstr "任何作者"
msgid "Any Milestone"
-msgstr ""
+msgstr "任何里程碑"
msgid "Any encrypted tokens"
-msgstr ""
+msgstr "任何加密的令牌(權æ–)"
msgid "Any label"
-msgstr ""
+msgstr "任何標籤"
msgid "Any member with at least Developer permissions on the project."
-msgstr ""
+msgstr "任何至少具有開發者權é™çš„專案æˆå“¡ã€‚"
msgid "Any milestone"
-msgstr ""
+msgstr "任何里程碑"
msgid "Any namespace"
-msgstr ""
+msgstr "任何命å空間"
msgid "Anyone can register for an account."
-msgstr ""
+msgstr "任何人都å¯ä»¥è¨»å†Šä¸€å€‹å¸³è™Ÿã€‚"
msgid "App ID"
-msgstr ""
+msgstr "應用程å¼ID"
msgid "Appearance"
-msgstr ""
+msgstr "外觀"
msgid "Appearance was successfully created."
-msgstr ""
+msgstr "å·²æˆåŠŸå»ºç«‹å¤–觀。"
msgid "Appearance was successfully updated."
-msgstr ""
+msgstr "外觀更新æˆåŠŸã€‚"
msgid "Append the comment with %{shrug}"
-msgstr ""
+msgstr "添加 %{shrug} 到留言"
msgid "Append the comment with %{tableflip}"
-msgstr ""
+msgstr "添加 %{tableflip} 到留言"
msgid "Application"
-msgstr ""
+msgstr "應用程å¼"
msgid "Application ID"
msgstr "æ‡‰ç”¨ç¨‹å¼ ID"
msgid "Application limits saved successfully"
-msgstr ""
+msgstr "應用程å¼é™åˆ¶å„²å­˜æˆåŠŸ"
msgid "Application settings saved successfully"
-msgstr ""
+msgstr "應用程å¼è¨­å®šå„²å­˜æˆåŠŸ"
msgid "Application settings saved successfully."
-msgstr ""
+msgstr "應用程å¼è¨­å®šå·²å„²å­˜æˆåŠŸã€‚"
msgid "Application settings update failed"
-msgstr ""
+msgstr "應用程å¼è¨­å®šæ›´æ–°å¤±æ•—"
msgid "Application uninstalled but failed to destroy: %{error_message}"
-msgstr ""
+msgstr "應用程å¼å·²ç§»é™¤ä½†æœªèƒ½éŠ·æ¯€: %{error_message}"
msgid "Application was successfully destroyed."
-msgstr ""
+msgstr "應用程å¼å·²æˆåŠŸéŠ·æ¯€ã€‚"
msgid "Application was successfully updated."
-msgstr ""
+msgstr "應用程å¼å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Application: %{name}"
-msgstr ""
+msgstr "應用程å¼ï¼š%{name}"
msgid "ApplicationSettings|A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
-msgstr ""
+msgstr "指標儀表æ¿é¸å–®ä½æ–¼ç®¡ç†å€çš„監管部份。"
msgid "ApplicationSettings|Add a link to Grafana"
-msgstr ""
+msgstr "在 Grafana 加入連çµ"
msgid "ApplicationSettings|After sign-up text"
-msgstr ""
+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 "實例é”到使用者上é™å¾Œï¼Œä»»ä½•å¢žåŠ æˆ–請求訪å•çš„使用者都必須得到管ç†å“¡çš„批准。空白表示無é™åˆ¶ã€‚"
msgid "ApplicationSettings|Allowed domains for sign-ups"
-msgstr ""
+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 ""
+msgstr "ä»»ä½•è¨ªå• %{host} 並建立帳號的使用者都必須得到管ç†å“¡çš„明確核准æ‰èƒ½ç™»éŒ„。僅在啟用註冊後æ‰æœ‰æ•ˆã€‚"
msgid "ApplicationSettings|Any user that visits %{host} can create an account."
-msgstr ""
+msgstr "ä»»ä½•è¨ªå• %{host} 的使用者都å¯ä»¥å»ºç«‹ä¸€å€‹å¸³è™Ÿã€‚"
msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
-msgstr[0] ""
+msgstr[0] "核准 %d 使用者"
msgid "ApplicationSettings|Approve users"
-msgstr ""
+msgstr "核准使用者"
msgid "ApplicationSettings|Approve users in the pending approval status?"
-msgstr ""
+msgstr "核准等待批准狀態的使用者?"
msgid "ApplicationSettings|Approve users who are pending approval?"
-msgstr ""
+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[0] "進行此變更,您將自動核准 %d ä½å¾…核准的使用者。"
msgid "ApplicationSettings|By making this change, you will automatically approve all users who are pending approval."
-msgstr ""
+msgstr "進行此變更,您將自動核准所有待核准的使用者。"
msgid "ApplicationSettings|Denied domains for sign-ups"
-msgstr ""
+msgstr "拒絕註冊的網域"
msgid "ApplicationSettings|Denylist file"
-msgstr ""
+msgstr "拒絕å單文件"
msgid "ApplicationSettings|Domain denylist"
-msgstr ""
+msgstr "å°éŽ–網域清單"
msgid "ApplicationSettings|Email restrictions"
-msgstr ""
+msgstr "é›»å­éƒµä»¶å°éŽ–清單"
msgid "ApplicationSettings|Email restrictions for sign-ups"
-msgstr ""
+msgstr "ç¦æ­¢ä»¥ä¸‹é›»å­éƒµä»¶è¨»å†Š"
msgid "ApplicationSettings|Enable Slack application"
-msgstr ""
+msgstr "啟用 Slack 應用程å¼"
msgid "ApplicationSettings|Enable domain denylist for sign-ups"
-msgstr ""
+msgstr "為註冊啟用網域å°éŽ–åå–®"
msgid "ApplicationSettings|Enable email restrictions for sign-ups"
-msgstr ""
+msgstr "註冊時啟用電å­éƒµä»¶å°éŽ–清單"
msgid "ApplicationSettings|Enter denylist manually"
-msgstr ""
+msgstr "手動輸入拒絕清單"
msgid "ApplicationSettings|Minimum password length (number of characters)"
-msgstr ""
+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 ""
+msgstr "åªæœ‰é›»å­éƒµä»¶åœ°å€ç¬¦åˆé€™äº›ç¶²åŸŸè¨­ç½®çš„使用者æ‰èƒ½è¨»å†Šã€‚ å…許使用通用é…置符號,å°å¤šå€‹é…置使用分行。 例如:domain.com, *.domain.com"
msgid "ApplicationSettings|Require admin approval for new sign-ups"
-msgstr ""
+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 ""
+msgstr "é™åˆ¶è¨»å†Šçš„é›»å­éƒµä»¶åœ°å€éœ€è¦åŒ¹é…çš„æ­£è¦è¡¨é”å¼ã€‚%{linkStart}何謂支æŒçš„語法%{linkEnd}。"
msgid "ApplicationSettings|Save changes"
-msgstr ""
+msgstr "ä¿å­˜æ›´æ”¹"
-msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}."
-msgstr ""
+msgid "ApplicationSettings|See %{linkStart}password policy guidelines%{linkEnd}."
+msgstr "è«‹åƒé–±%{linkStart}密碼政策指å—%{linkEnd}。"
msgid "ApplicationSettings|Send confirmation email on sign-up"
-msgstr ""
+msgstr "註冊時發é€ç¢ºèªé›»å­éƒµä»¶"
msgid "ApplicationSettings|Sign-up enabled"
-msgstr ""
+msgstr "已啟用註冊"
msgid "ApplicationSettings|Text shown after a user signs up. Markdown enabled."
-msgstr ""
+msgstr "使用者註冊後顯示的文字內容。å¯ä»¥ä½¿ç”¨ Markdown。"
msgid "ApplicationSettings|This option is only available on GitLab.com"
-msgstr ""
+msgstr "該é¸é …僅å¯ä½¿ç”¨æ–¼ GitLab.com"
msgid "ApplicationSettings|Upload denylist file"
-msgstr ""
+msgstr "上傳拒絕å單文件"
msgid "ApplicationSettings|User cap"
-msgstr ""
+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 ""
+msgstr "é›»å­éƒµä»¶åœ°å€ç¬¦åˆé€™äº›ç¶²åŸŸè¨­ç½®çš„使用者ä¸èƒ½è¨»å†Šã€‚ å…許使用通用é…置符號,å°å¤šå€‹é…置使用分行。 例如:domain.com, *.domain.com"
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 "é›»å­éƒµä»¶åœ°å€ç¬¦åˆé€™äº›ç¶²åŸŸè¨­ç½®çš„使用者ä¸èƒ½è¨»å†Šã€‚ å…許使用通用é…置符號,å°å¤šå€‹é…置使用分行或逗號分隔。 例如:domain.com, *.domain.com"
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one lowercase letter (a-z)."
+msgstr "啟用後,新密碼必須至少包å«ä¸€å€‹å°å¯«å­—æ¯ (a-z)。"
+
+msgid "ApplicationSettings|When enabled, new passwords must contain at least one number (0-9)."
+msgstr "啟用後,新密碼必須至少包å«ä¸€å€‹æ•¸å­— (0-9)。"
+
+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 "啟用後,新密碼必須至少包å«ä¸€å€‹å¤§å¯«å­—æ¯ (A-Z)。"
msgid "ApplicationSettings|domain.com"
-msgstr ""
+msgstr "domain.com"
msgid "Applications"
-msgstr ""
+msgstr "應用程å¼"
msgid "Applied"
-msgstr ""
+msgstr "已套用"
msgid "Apply"
-msgstr ""
+msgstr "套用"
msgid "Apply %d suggestion"
msgid_plural "Apply %d suggestions"
-msgstr[0] ""
+msgstr[0] "套用 %d 個建議"
msgid "Apply a label"
-msgstr ""
+msgstr "套用標籤"
msgid "Apply a template"
-msgstr ""
+msgstr "套用範本"
msgid "Apply suggestion"
-msgstr ""
+msgstr "套用建議"
msgid "Apply template"
-msgstr ""
+msgstr "套用範本"
msgid "Apply this approval rule to all branches or a specific protected branch."
-msgstr ""
+msgstr "將此批准è¦å‰‡æ‡‰ç”¨æ–¼æ‰€æœ‰åˆ†æ”¯æˆ–特定å—ä¿è­·çš„分支。"
msgid "Applying"
-msgstr ""
+msgstr "套用中"
msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
-msgstr ""
+msgstr "使用範本將å–代目å‰çš„è­°é¡Œæ述。您所åšçš„任何變更都將éºå¤±ã€‚"
msgid "Applying command"
-msgstr ""
+msgstr "正在執行指令"
msgid "Applying command to %{commandDescription}"
-msgstr ""
+msgstr "正在執行指令以 %{commandDescription}"
msgid "Applying multiple commands"
-msgstr ""
+msgstr "正在執行多個指令"
msgid "Applying suggestion..."
-msgstr ""
+msgstr "正在套用建議..."
msgid "Applying suggestions..."
-msgstr ""
+msgstr "正在套用建議..."
msgid "Approval rules"
-msgstr ""
+msgstr "核准è¦å‰‡"
msgid "Approval rules reset to project defaults"
-msgstr ""
+msgstr "回復審核æ¢ä»¶åˆ°é è¨­å€¼"
msgid "Approval settings"
-msgstr ""
+msgstr "核准設定"
msgid "ApprovalRuleRemove|%d member"
msgid_plural "ApprovalRuleRemove|%d members"
-msgstr[0] ""
+msgstr[0] "%d æˆå“¡"
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[0] "核准è¦å‰‡åˆªé™¤|æ‚¨å°‡åˆªé™¤åŒ…å« %{strongStart}%{count} 個æˆå“¡%{strongEnd}çš„ %{name} 核准人群組。這些æˆå“¡çš„批准ä¸æœƒè¢«æ’¤éŠ·ã€‚"
msgid "ApprovalRuleSummary|%d member"
msgid_plural "ApprovalRuleSummary|%d members"
-msgstr[0] ""
+msgstr[0] "%d æˆå“¡"
msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
-msgstr[0] ""
+msgstr[0] "%{membersCount} éœ€è¦ %{count} 個核准"
msgid "ApprovalRule|A merge request author collaborating with a merge request approver"
-msgstr ""
+msgstr "與åˆä½µè«‹æ±‚核准人åˆä½œçš„åˆä½µè«‹æ±‚作者"
msgid "ApprovalRule|Add approvers"
-msgstr ""
+msgstr "新增核准人"
msgid "ApprovalRule|Approval rules"
-msgstr ""
+msgstr "核准è¦å‰‡"
msgid "ApprovalRule|Approvals required"
-msgstr ""
+msgstr "需è¦æ ¸å‡†"
msgid "ApprovalRule|Approver Type"
-msgstr ""
+msgstr "核准人類型"
msgid "ApprovalRule|Approvers"
-msgstr ""
+msgstr "核准者"
msgid "ApprovalRule|Confirmed"
-msgstr ""
+msgstr "已核准"
msgid "ApprovalRule|Dismissed"
-msgstr ""
+msgstr "å·²é§å›ž"
msgid "ApprovalRule|Examples: QA, Security."
-msgstr ""
+msgstr "範例:QA,安全。"
msgid "ApprovalRule|Improve your organization's code review with required approvals."
-msgstr ""
+msgstr "通éŽåŸ·è¡Œå¿…è¦çš„核准以改進組織的代碼審查"
msgid "ApprovalRule|Increase quality and maintain standards."
-msgstr ""
+msgstr "æ高å“質並維æŒæº–則"
msgid "ApprovalRule|Learn more about merge request approval rules."
-msgstr ""
+msgstr "了解更多有關åˆä½µè«‹æ±‚的核准è¦å‰‡ã€‚"
msgid "ApprovalRule|Name"
-msgstr ""
+msgstr "å稱"
msgid "ApprovalRule|Newly detected"
-msgstr ""
+msgstr "新檢測到"
msgid "ApprovalRule|Previously detected"
-msgstr ""
+msgstr "之å‰æª¢æ¸¬åˆ°"
msgid "ApprovalRule|Reduce your time to merge."
-msgstr ""
+msgstr "減少åˆä½µæ™‚é–“"
msgid "ApprovalRule|Resolved"
-msgstr ""
+msgstr "已解決"
msgid "ApprovalRule|Rule name"
-msgstr ""
+msgstr "è¦å‰‡å稱"
msgid "ApprovalRule|Select eligible approvers by expertise or files changed."
-msgstr ""
+msgstr "按專業領域或被更改的文件,é¸æ“‡ç¬¦åˆæ¢ä»¶çš„核准人"
msgid "ApprovalRule|Target branch"
-msgstr ""
+msgstr "目標分支"
msgid "ApprovalRule|Try for free"
-msgstr ""
+msgstr "å…費試用"
+
+msgid "ApprovalSettings|Keep approvals"
+msgstr "ä¿æŒæ ¸å‡†"
msgid "ApprovalSettings|Merge request approval settings have been updated."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚核准設定已更新"
msgid "ApprovalSettings|Prevent approval by author"
-msgstr ""
-
-msgid "ApprovalSettings|Prevent approval by author."
-msgstr ""
+msgstr "阻止作者核准"
msgid "ApprovalSettings|Prevent approvals by users who add commits"
-msgstr ""
-
-msgid "ApprovalSettings|Prevent approvals by users who add commits."
-msgstr ""
+msgstr "é é˜²æ–°å¢žæ交的使用者核准"
msgid "ApprovalSettings|Prevent editing approval rules in merge requests"
-msgstr ""
+msgstr "防止在åˆä½µè«‹æ±‚中編輯核准è¦å‰‡"
+
+msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests"
+msgstr "防止在專案與åˆä½µè«‹æ±‚中編輯核准è¦å‰‡"
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgstr "防止在專案與åˆä½µè«‹æ±‚中編輯核准è¦å‰‡"
-msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch"
-msgstr ""
+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 ""
+msgstr "需è¦ä½¿ç”¨è€…密碼æ‰èƒ½æ ¸å‡†"
msgid "ApprovalSettings|There was an error loading merge request approval settings."
-msgstr ""
+msgstr "加載åˆä½µè«‹æ±‚核准設定時發生錯誤。"
msgid "ApprovalSettings|There was an error updating merge request approval settings."
-msgstr ""
+msgstr "æ›´æ–°åˆä½µè«‹æ±‚核准設定時發生錯誤。"
msgid "ApprovalSettings|This setting is configured at the instance level and can only be changed by an administrator."
-msgstr ""
+msgstr "此設定在實例級別已é…置且åªèƒ½ç”±ç®¡ç†å“¡æ›´æ”¹ã€‚"
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed in the group settings by an administrator or group owner."
-msgstr ""
+msgstr "此設定é…置為 %{groupName} ,åªèƒ½ç”±ç®¡ç†å“¡æˆ–群組æ“有者在群組設定中變更。"
+
+msgid "ApprovalSettings|When a commit is added:"
+msgstr "增加æ交時:"
msgid "Approvals are optional."
-msgstr ""
+msgstr "核准是å¯é¸çš„。"
msgid "Approvals|Section: %section"
-msgstr ""
+msgstr "部份: %section"
msgid "Approve"
msgstr "核准"
@@ -4686,28 +4733,25 @@ msgid "Approve the current merge request."
msgstr "核准目å‰åˆä½µè«‹æ±‚。"
msgid "Approved"
-msgstr ""
+msgstr "已核准"
msgid "Approved MRs"
-msgstr ""
+msgstr "已核准的 MRs"
msgid "Approved the current merge request."
msgstr "核准了目å‰çš„åˆä½µè«‹æ±‚。"
msgid "Approved-By"
-msgstr ""
-
-msgid "Approved. Your attention request was removed."
-msgstr ""
+msgstr "批准者"
msgid "Approver"
msgstr "核准人"
msgid "Approvers"
-msgstr ""
+msgstr "批准"
msgid "Approvers from private group(s) not shown"
-msgstr ""
+msgstr "未顯示來自ç§äººç¾¤çµ„的核准者"
msgid "Apr"
msgstr "4月"
@@ -4716,10 +4760,10 @@ msgid "April"
msgstr "4月"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "作業系統中找ä¸åˆ°æ­¤æž¶æ§‹"
msgid "Archive"
-msgstr ""
+msgstr "å°å­˜"
msgid "Archive jobs"
msgstr "歸檔作業"
@@ -4728,16 +4772,16 @@ msgid "Archive project"
msgstr "歸檔專案"
msgid "Archive test case"
-msgstr ""
+msgstr "歸檔測試案例"
msgid "Archived"
-msgstr ""
+msgstr "å·²å°å­˜"
msgid "Archived (%{movedToStart}moved%{movedToEnd})"
-msgstr ""
+msgstr "已歸檔(%{movedToStart} 已移動 %{movedToEnd})"
msgid "Archived in this version"
-msgstr ""
+msgstr "此版本已歸檔"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已歸檔專案ï¼ç‰ˆæœ¬åº«å’Œå…¶ä»–專案資æºå‡ç‚ºå”¯è®€"
@@ -4746,86 +4790,86 @@ 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 ""
+msgstr "您「éžå¸¸ç¢ºå®šã€è¦ç§»é™¤æ­¤ç¾¤çµ„嗎?"
msgid "Are you absolutely sure?"
-msgstr ""
+msgstr "è«‹å•æ‚¨éžå¸¸ç¢ºå®šå—Žï¼Ÿ"
msgid "Are you sure that you want to archive this project?"
msgstr "確定è¦æ­¸æª”此專案嗎?"
msgid "Are you sure that you want to destroy %{application}"
-msgstr ""
+msgstr "您確定è¦éŠ·æ¯€ %{application} 嗎?"
msgid "Are you sure that you want to unarchive this project?"
msgstr "確定è¦å–消歸檔此專案嗎?"
msgid "Are you sure you want to %{action} %{name}?"
-msgstr ""
+msgstr "您確定è¦%{action}%{name}?"
msgid "Are you sure you want to approve %{user}?"
-msgstr ""
+msgstr "您確定è¦æ ¸å‡†%{user}?"
msgid "Are you sure you want to attempt to merge?"
-msgstr ""
+msgstr "您確定è¦å˜—試åˆä½µï¼Ÿ"
msgid "Are you sure you want to cancel editing this %{commentType}?"
-msgstr ""
+msgstr "您確定è¦å–消編輯此 %{commentType} 嗎?"
msgid "Are you sure you want to close this blocked issue?"
-msgstr ""
+msgstr "您確定è¦é—œé–‰é€™å€‹è¢«å°é˜»çš„å•é¡Œå—Žï¼Ÿ"
msgid "Are you sure you want to delete %{name}?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤ %{name}嗎?"
msgid "Are you sure you want to delete these artifacts?"
msgstr "確定è¦åˆªé™¤é€™äº›ç”¢ç‰©å—Žï¼Ÿ"
msgid "Are you sure you want to delete this %{commentType}?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤ %{commentType} 嗎?"
msgid "Are you sure you want to delete this SSH key?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤é€™å€‹ SSH 金鑰?"
msgid "Are you sure you want to delete this comment?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤é€™å€‹ç•™è¨€ï¼Ÿ"
msgid "Are you sure you want to delete this deploy key?"
-msgstr ""
+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 ""
+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 ""
+msgstr "您確定刪除這個æµæ°´ç·šå—Žï¼Ÿé€™éº¼åšæœƒå°‡æ‰€æœ‰æµæ°´ç·šå¿«å–設æˆéŽæœŸï¼Œä¸¦åˆªé™¤æ‰€æœ‰ç›¸é—œç‰©ä»¶ï¼Œä¾‹å¦‚組建ã€æ—¥èªŒã€ç”¢ç‰©åŠè§¸ç™¼å™¨ã€‚這個動作ä¸èƒ½å¾©åŽŸã€‚"
msgid "Are you sure you want to deploy this environment?"
-msgstr ""
+msgstr "您確定è¦éƒ¨ç½²æ­¤ç’°å¢ƒå—Žï¼Ÿ"
msgid "Are you sure you want to discard this comment?"
-msgstr ""
+msgstr "您確定è¦æ¨æ£„此評論嗎?"
msgid "Are you sure you want to discard your changes?"
-msgstr ""
+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[0] "您確定è¦åŒ¯å…¥%d 檔案庫嗎?"
msgid "Are you sure you want to lock %{path}?"
-msgstr ""
+msgstr "您確定è¦éŽ–ä½ %{path}?"
msgid "Are you sure you want to lock this directory?"
-msgstr ""
+msgstr "您確定è¦éŽ–ä½é€™å€‹ç›®éŒ„?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "確定è¦æ”¾æ£„未儲存的變更嗎?"
@@ -4837,5319 +4881,5389 @@ msgid "Are you sure you want to merge immediately?"
msgstr "您確定è¦ç«‹å³åˆä½µå—Žï¼Ÿ"
msgid "Are you sure you want to re-deploy this environment?"
-msgstr ""
+msgstr "您確定è¦é‡æ–°éƒ¨ç½²æ­¤ç’°å¢ƒå—Žï¼Ÿ"
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "您確定è¦é‡æ–°ç´¢å¼•å—Žï¼Ÿ"
msgid "Are you sure you want to remove %{email}?"
-msgstr ""
+msgstr "您確定è¦ç§»é™¤%{email}嗎?"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "您確定è¦ç§»é™¤ %{group_name} 嗎?"
msgid "Are you sure you want to remove %{topic_name}?"
-msgstr ""
+msgstr "您確定è¦ç§»é™¤%{topic_name}嗎?"
msgid "Are you sure you want to remove the attachment?"
msgstr "您確定è¦ç§»é™¤æ­¤é™„件嗎?"
msgid "Are you sure you want to remove the license?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤è¨±å¯è­‰å—Žï¼Ÿ"
msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
-msgstr ""
+msgstr "您確定è¦ç§»é™¤é€™å€‹éƒ¨ç½²é‡‘鑰嗎?如果有任何æ±è¥¿ä»åœ¨ä½¿ç”¨æ­¤é‡‘鑰,它將åœæ­¢é‹ä½œã€‚"
msgid "Are you sure you want to remove this identity?"
msgstr "您確定è¦ç§»é™¤é€™å€‹èº«ä»½è­˜åˆ¥å—Žï¼Ÿ"
msgid "Are you sure you want to remove this list?"
-msgstr ""
+msgstr "您確定è¦ç§»é™¤é€™å€‹æ¸…單嗎?"
msgid "Are you sure you want to remove this nickname?"
-msgstr ""
+msgstr "您確定è¦ç§»é™¤é€™å€‹æš±ç¨±å—Žï¼Ÿ"
msgid "Are you sure you want to reset the error tracking access token?"
-msgstr ""
+msgstr "您確定è¦é‡ç½®éŒ¯èª¤è¿½è¹¤å­˜å–權æ–嗎?"
msgid "Are you sure you want to reset the health check token?"
-msgstr ""
+msgstr "確定è¦é‡è¨­åŸ·è¡Œç‹€æ³æª¢æŸ¥æ¬Šæ–嗎?"
msgid "Are you sure you want to reset the registration token?"
-msgstr ""
+msgstr "您確定è¦é‡è¨­è¨»å†Šæ†‘證嗎?"
msgid "Are you sure you want to retry this migration?"
-msgstr ""
+msgstr "您確定è¦é‡è©¦é€™å€‹ç§»è½‰å—Žï¼Ÿ"
msgid "Are you sure you want to revoke this %{accessTokenType}? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦æ’¤æ¶ˆæ­¤ %{accessTokenType} 嗎?此æ“作無法復原。"
msgid "Are you sure you want to revoke this %{type}? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦æ’¤éŠ·æ­¤ %{type}嗎?此動作無法復原。"
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦æ’¤å›žæ­¤å€‹äººå­˜å–憑證 (access token)嗎?此動作無法復原。"
msgid "Are you sure you want to revoke this project access token? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦æ’¤å›žæ­¤å°ˆæ¡ˆå­˜å–憑證 (access token)嗎?此動作無法復原。"
msgid "Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "是å¦ç¢ºå®šçµ‚止目å‰ç’°å¢ƒï¼Ÿ"
msgid "Are you sure you want to unlock %{path_lock_path}?"
-msgstr ""
+msgstr "您確定è¦è§£éŽ– %{path_lock_path} 嗎?"
msgid "Are you sure you want to unlock %{path}?"
-msgstr ""
+msgstr "您確定è¦è§£éŽ– %{path} 嗎?"
msgid "Are you sure you want to unlock this directory?"
-msgstr ""
+msgstr "您確定è¦è§£éŽ–此目錄?"
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
-msgstr ""
+msgstr "您確定è¦å–消訂閱 %{type}:%{link_to_noteable_text}嗎?"
msgid "Are you sure?"
-msgstr ""
+msgstr "確定嗎?"
msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
-msgstr ""
+msgstr "您確定è¦å¾©åŽŸå—Žï¼Ÿæ‰€æœ‰ä½¿ç”¨è©²GPG金鑰簽åçš„æ交都會被變為未經驗證。"
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
-msgstr ""
+msgstr "您確èªè¦åˆªé™¤GPG金鑰嗎?刪除此GPG金鑰ä¸æœƒå½±éŸ¿å·²ç¶“ç°½åçš„æ交。"
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
-msgstr ""
+msgstr "你確定嗎?該設備將從 GitLab 註銷,並且所有記ä½æˆ‘的憑證都將被撤銷。"
msgid "Arrange charts"
-msgstr ""
+msgstr "排列圖表"
msgid "Artifact"
-msgstr ""
+msgstr "產物"
msgid "Artifact could not be deleted."
-msgstr ""
+msgstr "無法刪除產物。"
msgid "Artifact was successfully deleted."
-msgstr ""
+msgstr "產物已æˆåŠŸåˆªé™¤ã€‚"
msgid "Artifacts"
-msgstr ""
+msgstr "æˆå“"
msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
-msgstr ""
+msgstr "隨著我們繼續為 SAST å»ºç«‹æ›´å¤šåŠŸèƒ½ï¼Œæˆ‘å€‘å¸Œæœ›æ‚¨å° %{linkStart} 本期 %{linkEnd} 中的 SAST é…置功能æä¾›å饋。"
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
-msgstr ""
+msgstr "%{user} 推é€åˆ° %{project_name} 的分支%{branch} ( %{commit_url} ): "
msgid "AsanaService|Add commit messages as comments to Asana tasks."
-msgstr ""
+msgstr "新增æ交訊æ¯ä½œç‚º Asana 任務的留言。"
msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
-msgstr ""
+msgstr "è¦è‡ªå‹•æª¢æŸ¥çš„以逗號分隔的分支列表。留空以包括所有分支。"
msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
-msgstr ""
+msgstr "使用者個人存å–憑證。使用者必須æ“有存å–任務的權é™ã€‚將會以使用者的身分進行所有留言。"
msgid "Ascending"
-msgstr ""
+msgstr "å‡åºæŽ’列"
msgid "Ask again later"
-msgstr ""
+msgstr "ç¨å¾Œå†å•"
msgid "Ask someone with write access to resolve it."
-msgstr ""
+msgstr "請具有寫入存å–權é™çš„人解決它。"
msgid "Ask your group owner to set up a group runner."
-msgstr ""
+msgstr "請您的群組æ“有者設定一個群組執行器"
msgid "Assertion consumer service URL"
-msgstr ""
+msgstr "斷言消費者æœå‹™ URL"
msgid "Assets"
-msgstr ""
+msgstr "資æº"
msgid "Assets:"
-msgstr ""
+msgstr "資æº:"
msgid "Assign"
-msgstr ""
+msgstr "指派"
msgid "Assign Iteration"
-msgstr ""
+msgstr "指派迭代"
msgid "Assign To"
-msgstr ""
+msgstr "分é…到"
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "分é…自訂é¡è‰²ï¼Œå¦‚FF0000"
msgid "Assign labels"
-msgstr ""
+msgstr "指派標記"
msgid "Assign milestone"
-msgstr ""
+msgstr "分é…里程碑"
msgid "Assign myself"
-msgstr ""
+msgstr "指派給自己"
msgid "Assign reviewer"
-msgstr ""
+msgstr "指派審核者"
msgid "Assign reviewer(s)"
-msgstr ""
+msgstr "指派審核者"
msgid "Assign severity"
-msgstr ""
+msgstr "指派嚴é‡åº¦"
msgid "Assign some issues to this milestone."
-msgstr ""
+msgstr "為此里程碑分é…一些議題。"
msgid "Assign to"
-msgstr ""
+msgstr "分é…到"
msgid "Assign to commenting user"
-msgstr ""
+msgstr "指派給留言使用者"
msgid "Assign to me"
-msgstr ""
+msgstr "指派給我"
msgid "Assigned %{assignee_users_sentence}."
-msgstr ""
+msgstr "已指派%{assignee_users_sentence}。"
msgid "Assigned %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "已將%{reviewer_users_sentence}指派為%{reviewer_text}。"
msgid "Assigned Issues"
-msgstr ""
+msgstr "已指派議題"
msgid "Assigned merge requests"
-msgstr ""
+msgstr "指派åˆä½µè«‹æ±‚"
msgid "Assigned projects"
-msgstr ""
+msgstr "已指派專案"
msgid "Assigned to %{assigneeName}"
-msgstr ""
+msgstr "已指派給%{assigneeName}"
msgid "Assigned to %{assignee_name}"
-msgstr ""
+msgstr "已指派給 %{assignee_name}"
msgid "Assigned to me"
-msgstr ""
+msgstr "已指派給我"
msgid "Assigned to you"
-msgstr ""
-
-msgid "Assigned user(s). Your attention request was removed."
-msgstr ""
+msgstr "已指派給您"
msgid "Assignee"
msgid_plural "%d Assignees"
-msgstr[0] ""
+msgstr[0] "%dä½è¢«æŒ‡æ´¾äºº"
msgid "Assignee has no permissions"
-msgstr ""
+msgstr "被指派人沒有權é™"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "被指派人åå–®ä¸æ”¯æ´æ‚¨ç›®å‰çš„授權"
msgid "Assignee(s)"
-msgstr ""
+msgstr "å—指派者(s)"
msgid "Assignees"
-msgstr ""
+msgstr "å—指派者(s)"
msgid "Assigns %{assignee_users_sentence}."
-msgstr ""
+msgstr "指派 %{assignee_users_sentence}。"
msgid "Assigns %{reviewer_users_sentence} as %{reviewer_text}."
-msgstr ""
+msgstr "將 %{reviewer_users_sentence} 指派為 %{reviewer_text}。"
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹ç¨‹å¼ç¢¼æ‰€æœ‰è€…核准,以便變更符åˆç›¸æ‡‰çš„ CODEEWNER è¦å‰‡çš„文件。"
msgid "At least one field of %{one_of_required_fields} must be present"
-msgstr ""
+msgstr "%{one_of_required_fields} 中至少è¦æœ‰ä¸€å€‹æ¬„ä½å­˜åœ¨"
msgid "At least one of group_id or project_id must be specified"
-msgstr ""
+msgstr "必須指定至少一個group_id或 project_id"
msgid "At least one of your Personal Access Tokens is expired. %{generate_new}"
-msgstr ""
+msgstr "您的個人存å–令牌(權æ–)中至少有一個已éŽæœŸã€‚ %{generate_new}"
msgid "At least one of your Personal Access Tokens will expire soon. %{generate_new}"
-msgstr ""
+msgstr "您的個人存å–令牌(權æ–)中至少有一個å³å°‡éŽæœŸã€‚ %{generate_new}"
msgid "At risk"
-msgstr ""
+msgstr "存在風險"
-msgid "Attach a file"
-msgstr ""
+msgid "Attach a file or image"
+msgstr "附上檔案或影åƒ"
msgid "Attaching File - %{progress}"
-msgstr ""
+msgstr "附加文件 - %{progress}"
msgid "Attaching a file"
msgid_plural "Attaching %d files"
-msgstr[0] ""
+msgstr[0] "加入%d個附件"
msgid "Attaching the file failed."
-msgstr ""
-
-msgid "Attention"
-msgstr ""
-
-msgid "Attention requested"
-msgstr ""
+msgstr "加入附件失敗。"
msgid "Audit Events"
-msgstr ""
+msgstr "審計事件"
msgid "Audit events"
-msgstr ""
+msgstr "審計事件"
msgid "AuditLogs|(removed)"
-msgstr ""
+msgstr "(已移除)"
msgid "AuditLogs|Action"
-msgstr ""
+msgstr "æ“作"
msgid "AuditLogs|Author"
-msgstr ""
+msgstr "作者"
msgid "AuditLogs|Date"
-msgstr ""
+msgstr "日期"
msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
-msgstr ""
+msgstr "未找到%{type}。請嘗試æœç´¢å…¶ä»–çš„%{type}。"
msgid "AuditLogs|Failed to find %{type}. Please try again."
-msgstr ""
+msgstr "未找到%{type},請å†è©¦ä¸€æ¬¡ã€‚"
msgid "AuditLogs|Group Events"
-msgstr ""
+msgstr "群組事件"
msgid "AuditLogs|IP Address"
-msgstr ""
+msgstr "IP地å€"
msgid "AuditLogs|Log"
-msgstr ""
+msgstr "紀錄"
msgid "AuditLogs|Member Events"
-msgstr ""
+msgstr "æˆå“¡äº‹ä»¶"
msgid "AuditLogs|No matching %{type} found."
-msgstr ""
+msgstr "沒有符åˆçš„%{type}。"
msgid "AuditLogs|Object"
-msgstr ""
+msgstr "å°è±¡"
msgid "AuditLogs|Project Events"
-msgstr ""
+msgstr "項目事件"
msgid "AuditLogs|Target"
-msgstr ""
+msgstr "目標"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "當月"
msgid "AuditLogs|User Events"
-msgstr ""
+msgstr "使用者事件"
msgid "AuditStreams|A header with this name already exists."
-msgstr ""
+msgstr "已存在åŒå稱的標頭。"
msgid "AuditStreams|Active"
-msgstr ""
+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 ""
+msgstr "新增一個 HTTP 端點來管ç†ç¬¬ä¸‰æ–¹ç³»çµ±ä¸­çš„紀錄。"
msgid "AuditStreams|Add external stream destination"
-msgstr ""
+msgstr "新增外部事件æµç¨‹ç›®çš„地"
msgid "AuditStreams|Add stream"
-msgstr ""
+msgstr "新增事件æµç¨‹"
msgid "AuditStreams|An error occurred when creating external audit event stream destination. Please try it again."
-msgstr ""
+msgstr "創建外部審計事件æµç¨‹ç›®çš„地時發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "AuditStreams|An error occurred when deleting external audit event stream destination. Please try it again."
-msgstr ""
+msgstr "刪除外部審計事件æµç¨‹ç›®çš„地時發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
msgid "AuditStreams|An error occurred when fetching external audit event streams. Please try it again"
-msgstr ""
+msgstr "ç²å–外部審計事件æµç¨‹æ™‚發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
+
+msgid "AuditStreams|An error occurred when updating external audit event stream destination. Please try it again."
+msgstr "更新外部審計事件æµç›®æ¨™æ™‚發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "AuditStreams|Cancel editing"
-msgstr ""
+msgstr "å–消編輯"
msgid "AuditStreams|Custom HTTP headers"
-msgstr ""
+msgstr "自定義 HTTP 標題"
msgid "AuditStreams|Delete %{link}"
-msgstr ""
+msgstr "刪除 %{link}"
msgid "AuditStreams|Destination URL"
-msgstr ""
+msgstr "目的地 URL"
msgid "AuditStreams|Destinations receive all audit event data"
-msgstr ""
+msgstr "目的地接收所有審計事件數據"
+
+msgid "AuditStreams|Edit %{link}"
+msgstr "編輯 %{link}"
msgid "AuditStreams|Header"
-msgstr ""
+msgstr "標題"
msgid "AuditStreams|Maximum of %{number} HTTP headers has been reached."
-msgstr ""
+msgstr "å·²é”到最大 %{number} 個 HTTP 標題。"
+
+msgid "AuditStreams|Save external stream destination"
+msgstr "儲存外部æµç›®çš„地"
msgid "AuditStreams|Setup streaming for audit events"
-msgstr ""
+msgstr "為審計事件設置事件æµç¨‹"
+
+msgid "AuditStreams|Stream added successfully"
+msgstr "å·²æˆåŠŸåŠ å…¥æµ"
msgid "AuditStreams|Stream count icon"
-msgstr ""
+msgstr "æµç¨‹è¨ˆæ•¸åœ–標"
+
+msgid "AuditStreams|Stream deleted successfully"
+msgstr "å·²æˆåŠŸåˆªé™¤æµ"
+
+msgid "AuditStreams|Stream updated successfully"
+msgstr "å·²æˆåŠŸæ›´æ–°æµ"
msgid "AuditStreams|Streams"
-msgstr ""
+msgstr "æµç¨‹"
msgid "AuditStreams|This could include sensitive information. Make sure you trust the destination endpoint."
-msgstr ""
+msgstr "這å¯èƒ½åŒ…括æ•æ„Ÿä¿¡æ¯ï¼Œè«‹ç¢ºèªæ‚¨ä¿¡ä»»è©²ç›®çš„地端點。"
msgid "AuditStreams|This is great for keeping everything one place."
-msgstr ""
+msgstr "這éžå¸¸é©åˆå°‡æ‰€æœ‰å…§å®¹ä¿å­˜åœ¨ä¸€å€‹åœ°æ–¹ã€‚"
msgid "AuditStreams|Value"
-msgstr ""
+msgstr "價值"
+
+msgid "AuditStreams|Verification token"
+msgstr "驗證權æ–"
msgid "Aug"
msgstr "8月"
msgid "August"
-msgstr ""
+msgstr "8 月"
msgid "Authenticate"
-msgstr ""
+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 ""
+msgstr "無需é¡å¤–é…ç½®å³å¯é©—證使用者 SSH 密鑰。 GitLab 的性能å¯ä»¥é€šéŽä½¿ç”¨ GitLab 數據庫來æ高。%{link_start}如何使用 GitLab 數據庫設置身份驗證? %{link_end}"
msgid "Authenticate with GitHub"
-msgstr ""
+msgstr "使用GitHub身份驗證"
msgid "Authenticated API rate limit period in seconds"
-msgstr ""
+msgstr "已身份驗證的 API 速率é™åˆ¶æœŸé™ï¼ˆä»¥ç§’為單ä½ï¼‰"
msgid "Authenticated API requests"
-msgstr ""
+msgstr "經éŽèº«ä»½é©—證的 API 請求"
msgid "Authenticated Git LFS rate limit period in seconds"
-msgstr ""
+msgstr "èªè­‰çš„ Git LFS 速率é™åˆ¶æ™‚間(以秒為單ä½ï¼‰"
msgid "Authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "èªè­‰çš„ Git LFS 請求速率é™åˆ¶"
msgid "Authenticated Git LFS requests"
-msgstr ""
+msgstr "經éŽèº«ä»½é©—證的 Git LFS 請求"
msgid "Authenticated web rate limit period in seconds"
-msgstr ""
+msgstr "經éŽèº«ä»½é©—證的 Web 速率é™åˆ¶æœŸï¼ˆä»¥ç§’為單ä½ï¼‰"
msgid "Authenticated web requests"
-msgstr ""
+msgstr "經éŽèº«ä»½é©—證的 Web 請求"
msgid "Authentication"
-msgstr ""
+msgstr "èªè­‰"
msgid "Authentication Failure"
-msgstr ""
+msgstr "èªè­‰å¤±æ•—"
msgid "Authentication Log"
-msgstr ""
+msgstr "èªè­‰æ—¥èªŒ"
msgid "Authentication error: enable 2FA in your profile settings to continue using GitLab: %{mfa_help_page}"
-msgstr ""
+msgstr "Authentication error: 在您的個人資料設置中啟用 2FA 以繼續使用 GitLab:%{mfa_help_page}"
msgid "Authentication failed: %{error_message}"
-msgstr ""
+msgstr "身份驗證失敗: %{error_message}"
msgid "Authentication log"
-msgstr ""
+msgstr "èªè­‰æ—¥èªŒ"
msgid "Authentication method"
-msgstr ""
+msgstr "驗證方å¼"
msgid "Authentication method updated"
-msgstr ""
+msgstr "身份驗證方法已更新"
msgid "Authentication via U2F device failed."
-msgstr ""
+msgstr "é€éŽU2Fè£ç½®é€²è¡Œèº«ä»½é©—證失敗。"
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "é€šéŽ WebAuthn 設備的身份驗證失敗。"
msgid "Author"
-msgstr ""
+msgstr "作者"
msgid "Author: %{author_name}"
-msgstr ""
+msgstr "作者:%{author_name}"
msgid "Authored %{timeago}"
-msgstr ""
+msgstr "編寫於%{timeago}"
msgid "Authored %{timeago} by %{author}"
-msgstr ""
+msgstr "%{author}編寫於%{timeago}"
msgid "Authorization code:"
-msgstr ""
+msgstr "授權碼:"
msgid "Authorization required"
-msgstr ""
+msgstr "需è¦æŽˆæ¬Š"
msgid "Authorization token duration (minutes)"
-msgstr ""
+msgstr "授權令牌(權æ–)期é™åˆ†é˜ï¼‰"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "在應用程å¼ä¸­è¼¸å…¥æ‚¨çš„使用者å稱和密碼å³å®ŒæˆæŽˆæ¬Šã€‚"
msgid "Authorize"
-msgstr ""
+msgstr "授權"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "授權 %{link_to_client} 使用您的帳號?"
msgid "Authorize %{user} to use your account?"
-msgstr ""
+msgstr "授權 %{user} 使用您的帳號?"
msgid "Authorized %{new_chat_name}"
-msgstr ""
+msgstr "已授權給 %{new_chat_name}"
msgid "Authorized At"
-msgstr ""
+msgstr "授權於"
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "å·²æŽˆæ¬Šæ‡‰ç”¨ç¨‹å¼ (%{size})"
msgid "AuthorizedApplication|Are you sure you want to revoke this application?"
-msgstr ""
+msgstr "èªè­‰æ‡‰ç”¨ç¨‹å¼|您確定è¦æ’¤éŠ·æ­¤ç”³è«‹å—Žï¼Ÿ"
msgid "AuthorizedApplication|Revoke application"
-msgstr ""
+msgstr "èªè­‰æ‡‰ç”¨ç¨‹å¼|撤銷申請"
msgid "Authors: %{authors}"
-msgstr ""
+msgstr "作者人數:%{authors}"
msgid "Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "Auto DevOps enabled"
-msgstr ""
+msgstr "啟用Auto DevOps"
msgid "Auto stop successfully canceled."
-msgstr ""
+msgstr "自動åœæ­¢å·²æˆåŠŸå–消。"
msgid "Auto-cancel redundant pipelines"
-msgstr ""
+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 ""
+msgstr "自動 DevOps|根據您的æŒçºŒé›†æˆå’Œäº¤ä»˜é…置,%{auto_devops_start}自動建構ã€æ¸¬è©¦å’Œéƒ¨ç½²%{auto_devops_end}您的應用程å¼ã€‚%{quickstart_start}我該如何開始?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "AutoDevOps|Auto DevOps documentation"
-msgstr ""
+msgstr "DevOps 自動化文件"
msgid "AutoDevOps|Dismiss Auto DevOps box"
-msgstr ""
+msgstr "自動 DevOps|關閉 Auto DevOps å°è©±æ¡†"
msgid "AutoDevOps|Enable in settings"
-msgstr ""
+msgstr "在設定中啟用"
msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
-msgstr ""
+msgstr "將根據é å®šç¾©çš„ CI/CD é…置自動組建ã€æ¸¬è©¦å’Œéƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ã€‚"
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
-msgstr ""
+msgstr "æƒ³äº†è§£æ›´å¤šè«‹å­˜å– %{link_to_documentation}"
msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found."
-msgstr ""
+msgstr "自動 DevOps|Auto DevOpsæµæ°´ç·šå·²å•Ÿç”¨ï¼Œå¦‚果未找到替代 CI é…置文件,將使用該æµæ°´ç·šã€‚"
msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "自動 DevOps 警示|啟用安全測試工具 %{linkStart}Auto DevOps%{linkEnd}"
msgid "AutoRemediation| 1 Merge Request"
-msgstr ""
+msgstr "1個åˆä½µè«‹æ±‚"
msgid "AutoRemediation|%{mrsCount} ready for review"
-msgstr ""
+msgstr "%{mrsCount}å·²å¯å¯©æ ¸"
msgid "AutoRemediation|Auto-fix"
-msgstr ""
+msgstr "自動修復"
msgid "AutoRemediation|Auto-fix solutions"
-msgstr ""
+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 ""
+msgstr "如果您使用ä¾è³´å’Œ/或容器掃æ並啟用動修復,自動修復將自動創建åˆä½µè«‹æ±‚,並修復æ¼æ´žã€‚"
msgid "AutoRemediation|Introducing GitLab auto-fix"
-msgstr ""
+msgstr "GitLab自動修復功能簡介"
msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
-msgstr ""
+msgstr "觸發嚴é‡è­¦å ±æ™‚啟動自動回退。如果無法自動回退到最後一次æˆåŠŸçš„部署,ä»ç„¶å¯ä»¥æ‰‹å‹•é€²è¡Œã€‚"
msgid "AutoRollback|Automatically roll back to the last successful deployment when a critical problem is detected."
-msgstr ""
+msgstr "檢測到嚴é‡å•é¡Œæ™‚,自動回退到最近一次的æˆåŠŸéƒ¨ç½²ã€‚"
msgid "AutoRollback|Enable automatic rollbacks"
-msgstr ""
+msgstr "啟用自動回退(rollbacks)"
msgid "Autocomplete"
-msgstr ""
+msgstr "自動補全"
msgid "Autocomplete description"
-msgstr ""
+msgstr "自動補全æè¿°"
msgid "Autocomplete hint"
-msgstr ""
+msgstr "自動補全æ示"
msgid "Autocomplete usage hint"
-msgstr ""
+msgstr "自動補全使用æ示"
msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
-msgstr ""
+msgstr "使用%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}自動管ç†æ†‘è­‰"
msgid "Automatic certificate management using Let's Encrypt"
-msgstr ""
+msgstr "使用Let's Encrypt自動管ç†æ†‘è­‰"
msgid "Automatic deployment rollbacks"
-msgstr ""
+msgstr "自動部署回退"
msgid "Automatic event tracking provides a traceable history for audits."
-msgstr ""
+msgstr "自動跟蹤事件為審計æ供了一個å¯è¿½è¹¤çš„æ­·å²ç´€éŒ„。"
msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
-msgstr ""
+msgstr "當æ¢å¾©è­¦å ±é€šçŸ¥è§£æ±ºè­¦å ±æ™‚自動關閉相關事件"
msgid "Automatically resolved"
-msgstr ""
+msgstr "自動解決"
-msgid "Automatically update this project's branches and tags from the upstream repository every hour."
-msgstr ""
+msgid "Automatically update this project's branches and tags from the upstream repository."
+msgstr "從上游版本庫自動更新該專案的分支和標籤。"
msgid "Autosave|Note"
-msgstr ""
+msgstr "注æ„"
msgid "Available"
-msgstr ""
+msgstr "å¯ç”¨çš„"
msgid "Available ID"
-msgstr ""
+msgstr "å¯ä½¿ç”¨çš„ ID"
msgid "Available group runners: %{runners}"
-msgstr ""
+msgstr "å¯ä½¿ç”¨çš„群組執行器:%{runners}"
msgid "Available on-demand"
-msgstr ""
+msgstr "按需æä¾›"
msgid "Available shared runners:"
-msgstr ""
+msgstr "å¯å…±ç”¨çš„執行器:"
msgid "Available specific runners"
-msgstr ""
+msgstr "å¯æŒ‡å®šçš„執行器(Runners)"
msgid "Avatar for %{assigneeName}"
-msgstr ""
+msgstr "%{assigneeName} é ­åƒ"
msgid "Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "å³å°‡ç§»é™¤é ­åƒã€‚確定繼續嗎?"
msgid "Average per day: %{average}"
-msgstr ""
+msgstr "å¹³å‡æ¯å¤©: %{average}"
msgid "Awaiting user signup"
-msgstr ""
+msgstr "等待使用者註冊"
msgid "Award added"
-msgstr ""
+msgstr "已添加çŽå‹µ"
msgid "Award removed"
-msgstr ""
+msgstr "已移除çŽå‹µ"
msgid "AwardEmoji|No emojis found."
-msgstr ""
+msgstr "AwardEmoji|未找到表情符號。"
msgid "Back"
-msgstr ""
+msgstr "返回"
msgid "Back to page %{number}"
-msgstr ""
+msgstr "返回第 %{number} é "
msgid "Background Color"
-msgstr ""
+msgstr "背景é¡è‰²"
msgid "Background Jobs"
-msgstr ""
+msgstr "後å°ä½œæ¥­"
msgid "Background Migrations"
-msgstr ""
+msgstr "後å°é·ç§»"
msgid "Background color"
-msgstr ""
+msgstr "背景é¡è‰²"
msgid "BackgroundMigrations|Background Migrations"
-msgstr ""
+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 ""
+msgstr "當é·ç§»è¶…éŽæŒ‡å°Žæ–¹é‡ä¸­çš„時間é™åˆ¶æ™‚,後å°é·ç§»ç”¨æ–¼åŸ·è¡Œæ•¸æ“šé·ç§»ã€‚ %{linkStart}了解更多%{linkEnd}"
msgid "BackgroundMigrations|Batch size"
-msgstr ""
+msgstr "批次大å°"
msgid "BackgroundMigrations|Database"
-msgstr ""
+msgstr "資料庫"
msgid "BackgroundMigrations|Failed jobs:"
-msgstr ""
+msgstr "失敗的工作:"
msgid "BackgroundMigrations|Finished at"
-msgstr ""
+msgstr "完æˆæ–¼"
msgid "BackgroundMigrations|Started at"
-msgstr ""
+msgstr "開始於"
msgid "Badges"
-msgstr ""
+msgstr "徽章"
msgid "Badges|Add badge"
-msgstr ""
+msgstr "加入徽章"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "加入徽章失敗,請檢查輸入的網å€ä¸¦é‡è©¦ã€‚"
msgid "Badges|Badge image URL"
-msgstr ""
+msgstr "徽章圖片網å€"
msgid "Badges|Badge image preview"
-msgstr ""
+msgstr "徽章圖片é è¦½"
msgid "Badges|Badge saved."
-msgstr ""
+msgstr "徽章已儲存。"
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "刪除徽章嗎?"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "刪除徽章失敗,請é‡è©¦ã€‚"
msgid "Badges|Enter a valid URL"
-msgstr ""
+msgstr "輸入有效的網å€"
msgid "Badges|Example: %{exampleUrl}"
-msgstr ""
+msgstr "範例: %{exampleUrl}"
msgid "Badges|Group Badge"
msgstr "群組徽章"
msgid "Badges|Link"
-msgstr ""
+msgstr "連çµ"
msgid "Badges|Name"
-msgstr ""
+msgstr "å稱"
msgid "Badges|New badge added."
-msgstr ""
+msgstr "徽章|已加入新徽章。"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "無徽章圖片"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "無圖片å¯é è¦½"
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "項目徽章"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "é‡æ–°è¼‰å…¥å¾½ç« åœ–片"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "儲存徽章失敗,請檢查輸入的網å€ä¸¦é‡è©¦ã€‚"
msgid "Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}"
-msgstr ""
+msgstr "徽章|支æŒ%{docsLinkStart}變é‡%{docsLinkEnd}:%{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "徽章已刪除。"
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "ç›®å‰ç¾¤çµ„無徽章"
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "ç›®å‰é …目無徽章"
msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
-msgstr ""
+msgstr "徽章|您將刪除此徽章。已刪除的徽章 %{strongStart}將無法æ¢å¾©%{strongEnd}。"
msgid "Badges|Your badges"
-msgstr ""
+msgstr "您的徽章"
msgid "BambooService|Atlassian Bamboo"
-msgstr ""
+msgstr "Atlassian Bamboo"
msgid "BambooService|Bamboo URL"
-msgstr ""
+msgstr "Bamboo URL"
msgid "BambooService|Bamboo build plan key."
-msgstr ""
+msgstr "Bamboo 構建計劃密鑰。"
msgid "BambooService|Bamboo service root URL."
-msgstr ""
+msgstr "Bamboo æœå‹™æ ¹ URL。"
msgid "BambooService|Enter new build key"
-msgstr ""
+msgstr "輸入新的構建密鑰"
msgid "BambooService|Leave blank to use your current build key."
-msgstr ""
+msgstr "留空以使用您當å‰çš„構建密鑰。"
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
-msgstr ""
+msgstr "BambooService | 使用 Atlassian Bamboo é‹è¡Œ CI/CD æµæ°´ç·šã€‚"
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 "BambooService|使用 Atlassian Bamboo é‹è¡Œ CI/CD æµæ°´ç·šã€‚您必須在 Bamboo 中設置自動修訂標籤和儲存庫觸發器。 %{docs_link}"
msgid "BambooService|The user with API access to the Bamboo server."
-msgstr ""
+msgstr "BambooService|å° Bamboo æœå‹™å™¨å…·æœ‰ API 訪å•æ¬Šé™çš„使用者。"
+
+msgid "Banned"
+msgstr "å·²å°éŽ–"
msgid "Banner message"
-msgstr ""
+msgstr "橫幅訊æ¯"
msgid "Based on"
-msgstr ""
+msgstr "基於"
msgid "Batch size"
-msgstr ""
+msgstr "批次大å°"
msgid "Batched Job|Background Migrations"
-msgstr ""
+msgstr "後å°é·ç§»"
msgid "Batched Job|Batched Job (Id: %{id})"
-msgstr ""
+msgstr "批次作業 (Id: %{id})"
msgid "BatchedJob|Attempts"
-msgstr ""
+msgstr "嘗試"
msgid "BatchedJob|Batch size"
-msgstr ""
+msgstr "批次大å°"
msgid "BatchedJob|Batched Jobs"
-msgstr ""
+msgstr "批次作業"
msgid "BatchedJob|Created At"
-msgstr ""
+msgstr "建立於"
msgid "BatchedJob|Created at"
-msgstr ""
+msgstr "建立於"
msgid "BatchedJob|Exception Class"
-msgstr ""
+msgstr "異常類別"
msgid "BatchedJob|Exception Message"
-msgstr ""
+msgstr "異常訊æ¯"
msgid "BatchedJob|Exception class"
-msgstr ""
+msgstr "異常類別"
msgid "BatchedJob|Exception message"
-msgstr ""
+msgstr "異常訊æ¯"
msgid "BatchedJob|Finished at"
-msgstr ""
+msgstr "完æˆæ–¼"
msgid "BatchedJob|Max Value"
-msgstr ""
+msgstr "最大值"
msgid "BatchedJob|Max value"
-msgstr ""
+msgstr "最大值"
msgid "BatchedJob|Min Value"
-msgstr ""
+msgstr "最å°å€¼"
msgid "BatchedJob|Min value"
-msgstr ""
+msgstr "最å°å€¼"
msgid "BatchedJob|Next Status"
-msgstr ""
+msgstr "下一個狀態"
msgid "BatchedJob|Next status"
-msgstr ""
+msgstr "下一個狀態"
msgid "BatchedJob|Pause ms"
-msgstr ""
+msgstr "æš«åœæ¯«ç§’"
msgid "BatchedJob|Pause time (ms)"
-msgstr ""
+msgstr "æš«åœæ™‚é–“(毫秒)"
msgid "BatchedJob|Previous Status"
-msgstr ""
+msgstr "å‰ä¸€å€‹ç‹€æ…‹"
msgid "BatchedJob|Previous status"
-msgstr ""
+msgstr "å‰ä¸€å€‹ç‹€æ…‹"
msgid "BatchedJob|Started at"
-msgstr ""
+msgstr "開始於"
msgid "BatchedJob|Transition logs:"
-msgstr ""
+msgstr "éŽæ¸¡æ—¥èªŒï¼š"
msgid "Be careful. Changing the project's namespace can have unintended side effects."
-msgstr ""
+msgstr "請注æ„,變更項目的命å空間å¯èƒ½æœƒç”¢ç”Ÿéžé æœŸçš„副作用。"
msgid "Be careful. Renaming a project's repository can have unintended side effects."
-msgstr ""
+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 "在啟用此集æˆä¹‹å‰ï¼Œè«‹åœ¨ Google Chat 中為您希望從該項目接收通知的房間創建一個 webhook。 %{docs_link}"
msgid "Before inserting code, be sure to read the comment that separated each code group."
-msgstr ""
+msgstr "在æ’入代碼之å‰ï¼Œè«‹å‹™å¿…閱讀分隔æ¯å€‹ä»£ç¢¼ç¾¤çµ„的註解。"
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
-msgstr ""
+msgstr "在åˆä½µä¹‹å‰ï¼Œå¿…須在標題或æ述中éˆæŽ¥ Jira è­°é¡Œ"
msgid "Begin with the selected commit"
-msgstr ""
+msgstr "從é¸å®šçš„æ交開始"
msgid "Below are the fingerprints for the current instance SSH host keys."
-msgstr ""
+msgstr "下é¢æ˜¯ç›®å‰å¯¦é«”SSH主機金鑰的指紋。"
msgid "Below are the settings for %{link_to_gitlab_pages}."
-msgstr ""
+msgstr "以下是 %{link_to_gitlab_pages}的設置。"
msgid "Below you will find all the groups that are public."
-msgstr ""
+msgstr "您將在下é¢æ‰¾åˆ°æ‰€æœ‰å…¬é–‹çš„群組。"
msgid "Bi-weekly code coverage"
-msgstr ""
+msgstr "雙周代碼覆蓋率"
msgid "Billable Users"
-msgstr ""
+msgstr "計費使用者"
msgid "Billing"
-msgstr ""
+msgstr "計費"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}"
-msgstr ""
+msgstr "%{group_name} ç›®å‰æ­£åœ¨ä½¿ç”¨ %{plan_name}"
msgid "BillingPlans|10,000 CI/CD minutes per month"
-msgstr ""
+msgstr "æ¯æœˆ 10,000 CI/CD 分é˜"
msgid "BillingPlans|10GB transfer per month"
-msgstr ""
+msgstr "æ¯æœˆ 10GB 傳輸"
msgid "BillingPlans|400 CI/CD minutes per month"
-msgstr ""
+msgstr "æ¯æœˆ 400 CI/CD 分é˜"
msgid "BillingPlans|5 users per namespace"
-msgstr ""
+msgstr "æ¯å€‹å‘½å空間 5 個使用者"
msgid "BillingPlans|50,000 CI/CD minutes per month"
-msgstr ""
+msgstr "æ¯æœˆ 50,000 CI/CD 分é˜"
msgid "BillingPlans|5GB storage"
-msgstr ""
+msgstr "5GB 存儲空間"
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
-msgstr ""
+msgstr "計費計畫|%{user_name},您正在使用%{plan_name}計畫。"
msgid "BillingPlans|Advanced CI/CD"
-msgstr ""
+msgstr "進階 CI/CD"
msgid "BillingPlans|All plans have unlimited (private) repositories."
-msgstr ""
+msgstr "所有計劃都有無é™åˆ¶çš„(ç§æœ‰ï¼‰å­˜å„²åº«ã€‚"
msgid "BillingPlans|All the features from Free"
-msgstr ""
+msgstr "所有å…費的功能"
msgid "BillingPlans|All the features from Premium"
-msgstr ""
+msgstr "Premium 的全部功能"
msgid "BillingPlans|Billed annually at %{price_per_year} USD"
-msgstr ""
+msgstr "æ¯å¹´æŒ‰ %{price_per_year} 美元計費"
msgid "BillingPlans|Check out all groups"
-msgstr ""
+msgstr "查看所有群組"
msgid "BillingPlans|Compliance"
-msgstr ""
+msgstr "åˆè¦"
msgid "BillingPlans|Congratulations, your free trial is activated."
-msgstr ""
+msgstr "計費計畫|æ­å–œï¼Œæ‚¨çš„å…費試用計畫已啟用。"
msgid "BillingPlans|End of availability for the Bronze Plan"
-msgstr ""
+msgstr "計費計畫|銅級方案已çµæŸ"
msgid "BillingPlans|Enhance team productivity and collaboration"
-msgstr ""
+msgstr "æ高團隊生產力與å”åŒåˆä½œ"
msgid "BillingPlans|Enterprise agile planning"
-msgstr ""
+msgstr "ä¼æ¥­æ•æ·è¦åŠƒ"
msgid "BillingPlans|Faster code reviews"
-msgstr ""
+msgstr "更快的程å¼ç¢¼å¯©æŸ¥"
msgid "BillingPlans|Free forever features for individual users"
-msgstr ""
+msgstr "個人使用者永久å…費功能"
msgid "BillingPlans|Free guest users"
-msgstr ""
+msgstr "å…費的來賓使用者"
msgid "BillingPlans|Free upgrade!"
-msgstr ""
+msgstr "計費計劃|å…è²»å‡ç´š"
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
-msgstr ""
+msgstr "如果您想è¦é™ç´šæ‚¨çš„訂閱計劃,請è¯çµ¡%{support_link_start}客戶支æ´%{support_link_end}。"
msgid "BillingPlans|Includes free static websites"
-msgstr ""
+msgstr "包括å…費的éœæ…‹ç¶²ç«™"
msgid "BillingPlans|Learn more"
-msgstr ""
+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}了解有關æ¯å€‹è¨ˆåŠƒçš„更多信æ¯ï¼Œæˆ–開始 GitLab.com Ultimate çš„ 30 天å…費試用。"
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
-msgstr ""
+msgstr "é€éŽé–±è®€æˆ‘們的 %{pricing_page_link} 了解有關æ¯å€‹è¨ˆåŠƒçš„更多訊æ¯ã€‚"
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 "計費計劃|想為您的團隊購買或管ç†è¨‚閱?導航到您的 %{groups_link} 並轉到 %{strong_open}設置 &gt; 計費。%{strong_close}"
msgid "BillingPlans|Loved and trusted by our customers"
-msgstr ""
+msgstr "å—客戶喜愛和信賴"
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "管ç†è¨ˆåŠƒ"
msgid "BillingPlans|Not the group you're looking for? %{all_groups_link}."
-msgstr ""
+msgstr "ä¸æ˜¯æ‚¨è¦æ‰¾çš„群組? %{all_groups_link}。"
msgid "BillingPlans|Open Source - MIT License"
-msgstr ""
+msgstr "開放æºç¢¼ - MIT 授權許å¯"
msgid "BillingPlans|Organization wide security, compliance and planning"
-msgstr ""
+msgstr "組織範åœå…§çš„安全性ã€åˆè¦æ€§å’Œè¦åŠƒ"
msgid "BillingPlans|Portfolio management"
-msgstr ""
+msgstr "投資組åˆç®¡ç†"
msgid "BillingPlans|Premium"
-msgstr ""
+msgstr "高級"
msgid "BillingPlans|Pricing page"
-msgstr ""
+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 ""
+msgstr "推薦"
msgid "BillingPlans|Release controls"
-msgstr ""
+msgstr "發布控制"
msgid "BillingPlans|Security risk mitigation"
-msgstr ""
+msgstr "安全風險緩解"
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "查看 %{plan_name} 計劃中的功能"
msgid "BillingPlans|Self-managed reliability"
-msgstr ""
+msgstr "自管ç†çš„å¯é æ€§"
msgid "BillingPlans|Spans the DevOps lifecycle"
-msgstr ""
+msgstr "跨越 DevOps 生命週期"
msgid "BillingPlans|Start a free Ultimate trial"
-msgstr ""
+msgstr "開始å…è²» Ultimate 試用"
msgid "BillingPlans|Still have questions?"
-msgstr ""
+msgstr "還有å•é¡Œå—Žï¼Ÿ"
msgid "BillingPlans|Support"
-msgstr ""
+msgstr "支æ´"
msgid "BillingPlans|Talk to an expert today."
-msgstr ""
+msgstr "今天與專案交談。"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+msgstr "使用與其父項目一致的計劃"
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "å­˜å–%{parent_billing_page_link}的計費部分以管ç†è©²é …目的訂閱計劃。"
msgid "BillingPlans|Ultimate"
-msgstr ""
+msgstr "旗艦級"
msgid "BillingPlans|Upgrade to Premium"
-msgstr ""
+msgstr "æå‡åˆ°é«˜ç´š"
msgid "BillingPlans|Upgrade to Ultimate"
-msgstr ""
+msgstr "æå‡åˆ°æ——艦級"
msgid "BillingPlans|Value stream management"
-msgstr ""
+msgstr "價值æµç®¡ç†"
msgid "BillingPlans|We're here to help."
-msgstr ""
+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 ""
+msgstr "雖然 GitLab 將終止使用銅級方案,但您ä»ç„¶å¯ä»¥åœ¨ %{eoa_bronze_plan_end_date} 之å‰å†çºŒè¨‚一次銅級訂閱。我們還æä¾›é™æ™‚å…è²»å‡ç´šåˆ°æˆ‘們的專業方案(最多 25 個使用者)ï¼åœ¨æˆ‘們的 %{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 ""
+msgstr "您還沒加入任何群組。您必須%{create_group_link_start}建立群組%{create_group_link_end}並且%{move_link_start}移動此專案到那裡%{move_link_end}。"
msgid "BillingPlans|You'll have to %{move_link_start}move this project%{move_link_end} to one of your groups."
-msgstr ""
+msgstr "您必須%{move_link_start}移動這個專案%{move_link_end}到您其中一個群組。"
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
-msgstr ""
+msgstr "計費計劃|您的 GitLab.com %{plan} 試用版將在 %{strong_open} %{expiration_date}%{strong_close}之後éŽæœŸã€‚您å¯ä»¥é€šéŽä»¥ä¸‹å‡ç´šä¿ç•™å° %{plan} 項功能的訪å•æ¬Šé™ã€‚"
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
-msgstr ""
+msgstr "您的GitLab.com試用已於%{expiration_date}到期。您å¯ä»¥é€éŽä»¥ä¸‹å‡ç´šéš¨æ™‚復原å°åŠŸèƒ½çš„å­˜å–。"
msgid "BillingPlans|Your current plan"
-msgstr ""
+msgstr "您當å‰çš„計劃"
msgid "BillingPlans|billed annually at %{price_per_year}"
-msgstr ""
+msgstr "æ¯å¹´æ”¯ä»˜%{price_per_year}"
msgid "BillingPlans|for the remainder of your subscription"
-msgstr ""
+msgstr "為您的剩餘訂閱時間"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "常見å•é¡Œ"
msgid "BillingPlans|group"
-msgstr ""
+msgstr "群組"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "æ¯æœˆ"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "æ¯ä½¿ç”¨è€…"
msgid "BillingPlans|per user/month"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…/月"
msgid "BillingPlan|Upgrade"
-msgstr ""
+msgstr "å‡ç´š"
msgid "BillingPlan|Upgrade for free"
-msgstr ""
+msgstr "å…è²»å‡ç´š"
msgid "Billings|%{planName} plan"
-msgstr ""
+msgstr "%{planName} 計劃"
msgid "Billings|An error occurred while extending your trial."
-msgstr ""
+msgstr "延長試用期時發生錯誤。"
msgid "Billings|An error occurred while reactivating your trial."
-msgstr ""
+msgstr "é‡æ–°å•Ÿç”¨æ‚¨çš„試用版時發生錯誤。"
msgid "Billings|By extending your trial, you will receive an additional 30 days of %{planName}. Your trial can be only extended once."
-msgstr ""
+msgstr "通éŽå»¶é•·è©¦ç”¨æœŸï¼Œæ‚¨å°‡é¡å¤–ç²å¾— 30 天 %{planName}。您的試用期åªèƒ½å»¶é•·ä¸€æ¬¡ã€‚"
msgid "Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once."
-msgstr ""
+msgstr "通éŽé‡æ–°å•Ÿç”¨æ‚¨çš„試用版,您將ç²å¾—é¡å¤–çš„ 30 天 %{planName}。您的試用版åªèƒ½é‡æ–°å•Ÿç”¨ä¸€æ¬¡ã€‚"
msgid "Billings|Error validating card details"
-msgstr ""
+msgstr "é©—è­‰å¡ç‰‡è©³ç´°è³‡è¨ŠéŒ¯èª¤"
msgid "Billings|Extend trial"
-msgstr ""
+msgstr "延長試用期"
msgid "Billings|Free groups are limited to %{number} seats."
-msgstr ""
+msgstr "å…è²»ç¾¤çµ„åƒ…é™ %{number} 個席次"
+
+msgid "Billings|Free tier and trial groups can invite a maximum of 20 members per day."
+msgstr "å…費版或試用版的群組æ¯å¤©æœ€å¤šåªèƒ½é‚€è«‹ 20 åæˆå“¡ã€‚"
msgid "Billings|In a seat"
-msgstr ""
+msgstr "一個席次"
msgid "Billings|Reactivate trial"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿè©¦ç”¨"
msgid "Billings|Seats in use / Seats available"
-msgstr ""
+msgstr "使用中席次 / å¯ç”¨å¸­æ¬¡"
msgid "Billings|Seats in use / Seats in subscription"
-msgstr ""
+msgstr "使用中席次 / 訂閱席次"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr ""
+msgstr "在有效的信用å¡å­˜æª”之å‰ï¼Œç„¡æ³•å•Ÿç”¨å…±ç”¨åŸ·è¡Œå™¨ã€‚"
msgid "Billings|The last owner cannot be removed from a seat."
-msgstr ""
+msgstr "ä¸èƒ½ç§»é™¤å¸­æ¬¡ä¸Šçš„最後一ä½æ“有者"
msgid "Billings|To make this member active, you must first remove an existing active member, or toggle them to over limit."
-msgstr ""
+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 ""
+msgstr "è¦åœ¨å…±äº«çš„執行器(runners)上使用å…è²» CI/CD 分é˜ï¼Œæ‚¨éœ€è¦ä½¿ç”¨ä¿¡ç”¨å¡é©—證您的帳號。如果您ä¸æƒ³æ供,您å¯ä»¥é€šéŽç‚ºæ‚¨çš„項目帶來自己的 runner 並ç¦ç”¨ shared runners 來é‹è¡Œæµæ°´ç·šã€‚é€™æ˜¯é˜»æ­¢å’Œæ¸›å°‘å° 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 ""
+msgstr "è¦åœ¨å…±äº«åŸ·è¡Œå™¨(runner)上使用å…費的 CI/CD 分é˜ï¼Œæ‚¨éœ€è¦ä½¿ç”¨ä¿¡ç”¨å¡é©—證您的帳號。 這樣åšçš„目的是為了阻止和減少 GitLab 基礎設施的濫用。 %{strongStart}GitLab ä¸æœƒå°æ‚¨çš„å¡è™Ÿæ‰£è²»ï¼Œå®ƒåƒ…用於驗證。%{strongEnd}"
msgid "Billings|User validation required"
-msgstr ""
+msgstr "需è¦ä½¿ç”¨è€…é©—è­‰"
msgid "Billings|Validate account"
-msgstr ""
+msgstr "驗證帳號"
msgid "Billings|Validate user account"
-msgstr ""
+msgstr "驗證使用者帳號"
msgid "Billings|You can't change the seat status of a user who was invited via a group or project."
-msgstr ""
+msgstr "您無法更改通éŽç¾¤çµ„或專案邀請的使用者席次狀態。"
msgid "Billings|You can't remove yourself from a seat, but you can leave the group."
-msgstr ""
+msgstr "您無法將自己從座次上移除,但您å¯ä»¥é›¢é–‹ç¾¤çµ„。"
msgid "Billings|You'll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥åˆ©ç”¨å…±äº«åŸ·è¡Œå™¨çš„å…è²» CI/CD 分é˜æ•¸ã€‚"
msgid "Billings|Your account has been validated"
-msgstr ""
+msgstr "您的帳號已經驗證"
msgid "Billing|%{user} was successfully approved"
-msgstr ""
+msgstr "%{user} å·²æˆåŠŸç²å¾—批准"
msgid "Billing|Add seats"
-msgstr ""
+msgstr "增加度次"
msgid "Billing|An email address is only visible for users with public emails."
-msgstr ""
+msgstr "åªæœ‰æ“有公開電å­ä¿¡ç®±çš„用戶å¯ä»¥çœ‹è¦‹é›»å­éƒµä»¶åœ°å€ã€‚"
msgid "Billing|An error occurred while approving %{user}"
-msgstr ""
+msgstr "核准 %{user} 時發生錯誤"
msgid "Billing|An error occurred while getting a billable member details."
-msgstr ""
+msgstr "å–得計費會員詳細資訊時發生錯誤"
msgid "Billing|An error occurred while loading GitLab subscription details."
-msgstr ""
+msgstr "載入 GitLab 訂閱詳細資訊時發生錯誤。"
msgid "Billing|An error occurred while loading billable members list."
-msgstr ""
+msgstr "載入計費æˆå“¡åˆ—表時發生錯誤。"
msgid "Billing|An error occurred while loading pending members list"
-msgstr ""
+msgstr "加載待定æˆå“¡æ¸…單時發生錯誤"
msgid "Billing|An error occurred while removing a billable member."
-msgstr ""
+msgstr "移除計費會員時發生錯誤。"
msgid "Billing|Awaiting member signup"
-msgstr ""
+msgstr "等待會員註冊"
msgid "Billing|Cannot remove user"
-msgstr ""
+msgstr "無法移除使用者"
msgid "Billing|Direct memberships"
-msgstr ""
+msgstr "直接會員"
msgid "Billing|Enter at least three characters to search."
-msgstr ""
+msgstr "請輸入最少 3 個字元來æœå°‹ã€‚"
msgid "Billing|Explore all plans"
-msgstr ""
+msgstr "查看所有計劃"
msgid "Billing|Export list"
-msgstr ""
-
-msgid "Billing|Free groups on GitLab are limited to %{maxNamespaceSeats} seats"
-msgstr ""
+msgstr "匯出清單"
-msgid "Billing|From June 22, 2022 (GitLab 15.1), free groups will be limited to 5 members"
-msgstr ""
+msgid "Billing|From October 19, 2022, free groups will be limited to 5 members"
+msgstr "從 2022 å¹´ 10 月 19 日起,å…費群組將é™åˆ¶ç‚º 5 åæˆå“¡"
msgid "Billing|Group invite"
-msgstr ""
+msgstr "群組邀請"
-msgid "Billing|If the group has over %{maxNamespaceSeats} members, only those occupying a seat can access the namespace. To ensure all members (active and %{linkStart}over limit%{linkEnd}) can access the namespace, you can start a trial or upgrade to a paid tier."
-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] "å…費版中的群組åªèƒ½æœ‰ %d 個æˆå“¡ã€‚"
msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
-msgstr ""
+msgstr "無法移除通éŽç¾¤çµ„邀請的被邀請æˆå“¡ã€‚您å¯ä»¥ç§»é™¤æ•´å€‹ç¾¤çµ„,也å¯ä»¥è¦æ±‚å—邀群組的所有者移除æˆå“¡ã€‚"
msgid "Billing|No users to display."
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„使用者。"
msgid "Billing|Private"
-msgstr ""
+msgstr "ç§äººçš„"
msgid "Billing|Project invite"
-msgstr ""
+msgstr "專案邀請"
msgid "Billing|Remove user %{username} from your subscription"
-msgstr ""
+msgstr "從您的訂閱中移除使用者 %{username}"
+
+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 ""
+msgstr "切æ›åº§ä½ï¼ˆtoggle seat)詳細資訊"
msgid "Billing|Type %{username} to confirm"
-msgstr ""
+msgstr "輸入 %{username} 以確èª"
msgid "Billing|User was successfully removed"
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤ä½¿ç”¨è€…"
msgid "Billing|View pending approvals"
-msgstr ""
+msgstr "檢視等待中的核准"
msgid "Billing|You are about to remove user %{username} from your subscription. If you continue, the user will be removed from the %{namespace} group and all its subgroups and projects. This action can't be undone."
-msgstr ""
+msgstr "您將è¦å¾žè¨‚閱中移除使用者%{username}。如果繼續,該使用者將從 %{namespace} 群組åŠå…¶æ‰€æœ‰å­çµ„和項目中刪除。此æ“作無法撤消。"
-msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
-msgstr ""
-
-msgid "Billing|Your free group is now limited to %{free_user_limit} members"
-msgstr ""
+msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after October 19, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
+msgstr "您ç¾åœ¨å¯ä»¥é–‹å§‹ç§»å‹• %{namespaceName} 中的æˆå“¡äº†ï¼Œç•¶æ‚¨é—œé–‰ %{strongStart}席次%{strongEnd} 後,æˆå“¡å°‡ç„¡æ³•å­˜å–該群組。如果在 2022 å¹´ 10 月 19 æ—¥ä¹‹å¾Œå•Ÿç”¨äº†è¶…éŽ 5 åæˆå“¡çš„ %{strongStart}席次%{strongEnd},我們將é¸æ“‡ 5 åæˆå“¡ç¶­æŒå­˜å–權é™ã€‚我們將首先計算具有æ“者和維護者角色的æˆå“¡ï¼Œç„¶å¾Œæ˜¯æœ€è¿‘較為活èºçš„æˆå“¡ï¼Œç›´åˆ°æˆ‘們é”到 5 個æˆå“¡ï¼Œå…¶é¤˜æˆå“¡å°‡è®Šç‚ºâ€œè¶…出é™åˆ¶â€ç‹€æ…‹ä¸¦å¤±åŽ»å°è©²ç¾¤çµ„çš„å­˜å–權é™ã€‚"
-msgid "Billing|Your group recently changed to use the Free plan. 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. 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 "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 "您的群組最近更改為使用å…費計劃。 %{over_limit_message} 您å¯ä»¥é€šéŽåˆªé™¤ä¸å†éœ€è¦è¨ªå•æ¬Šé™çš„æˆå“¡æˆ–將其切æ›ç‚ºè¶…é™ä¾†ç‚ºæ–°æˆå“¡é‡‹æ”¾ç©ºé–“。è¦ç²å¾—ç„¡é™æ•¸é‡çš„會員,您å¯ä»¥ %{link_start}å‡ç´š%{link_end} 到付費等級。"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Bitbucket伺æœå™¨åŒ¯å…¥"
msgid "Bitbucket Server import"
-msgstr ""
+msgstr "Bitbucket 伺æœå™¨åŒ¯å…¥"
msgid "Bitbucket import"
-msgstr ""
+msgstr "從 Bitbucket 匯入"
msgid "Blame"
-msgstr ""
+msgstr "咎責"
msgid "BlobViewer|View on %{environmentName}"
-msgstr ""
+msgstr "BlobViewer|在 %{environmentName}上檢視"
msgid "Block user"
-msgstr ""
+msgstr "å°éŽ–使用者"
msgid "Blocked"
msgstr "å·²å°éŽ–"
msgid "Blocked by %d issue"
msgid_plural "Blocked by %d issues"
-msgstr[0] ""
+msgstr[0] "被 %d 個議題å°éŽ–"
msgid "Blocked issue"
-msgstr ""
+msgstr "被å°éŽ–çš„è­°é¡Œ"
msgid "Blocking"
-msgstr ""
+msgstr "å°éŽ–中"
msgid "Blocking issues"
-msgstr ""
+msgstr "å°éŽ–中議題"
msgid "Blocks"
-msgstr ""
+msgstr "å€å¡Š"
msgid "Blog"
-msgstr ""
+msgstr "部è½æ ¼"
msgid "Board scope affects which epics are displayed for anyone who visits this board"
-msgstr ""
+msgstr "看æ¿ç¯„åœæœƒå½±éŸ¿ä»»ä½•å­˜å–此看æ¿çš„人å¯ä»¥çœ‹åˆ°å“ªäº›å²è©©é¡¯ç¤º"
msgid "Board scope affects which issues are displayed for anyone who visits this board"
-msgstr ""
+msgstr "看æ¿ç¯„åœæœƒå½±éŸ¿å­˜å–此看æ¿çš„人å¯ä»¥é¡¯ç¤ºå“ªäº›è­°é¡Œ"
msgid "BoardNewEpic|Groups"
-msgstr ""
+msgstr "BoardNewEpic|群組"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "BoardNewEpic|加載群組"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "BoardNewEpic|沒有符åˆçš„çµæžœ"
msgid "BoardNewEpic|Search groups"
-msgstr ""
+msgstr "BoardNewEpic|æœå°‹ç¾¤çµ„"
msgid "BoardNewEpic|Select a group"
-msgstr ""
+msgstr "BoardNewEpic|é¸æ“‡ä¸€å€‹ç¾¤çµ„"
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "沒有符åˆçš„çµæžœ"
msgid "BoardNewIssue|Projects"
msgstr "專案"
msgid "BoardNewIssue|Search projects"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "BoardNewIssue|Select a project"
-msgstr ""
+msgstr "é¸å–一個專案"
msgid "BoardScope|%{iterationTitle} iteration in %{iterationCadence}"
-msgstr ""
+msgstr "在 %{iterationCadence} 進行 %{iterationTitle} 迭代"
msgid "BoardScope|An error occurred while getting iterations. Please try again."
-msgstr ""
+msgstr "ç²å–迭代時發生錯誤。請é‡è©¦ã€‚"
msgid "BoardScope|An error occurred while getting milestones, please try again."
-msgstr ""
+msgstr "ç²å–里程碑時發生錯誤,請é‡è©¦ã€‚"
msgid "BoardScope|An error occurred while searching for labels, please try again."
-msgstr ""
+msgstr "æœå°‹æ¨™ç±¤æ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "BoardScope|An error occurred while searching for users, please try again."
-msgstr ""
+msgstr "æœå°‹ä½¿ç”¨è€…時發生錯誤,請é‡è©¦ã€‚"
msgid "BoardScope|Any Milestone"
-msgstr ""
+msgstr "任何里程碑"
msgid "BoardScope|Any assignee"
-msgstr ""
+msgstr "任何指派人"
msgid "BoardScope|Any iteration"
-msgstr ""
+msgstr "任何迭代"
msgid "BoardScope|Any label"
-msgstr ""
+msgstr "任何標籤"
msgid "BoardScope|Assignee"
-msgstr ""
+msgstr "指派人"
msgid "BoardScope|Choose labels"
-msgstr ""
+msgstr "é¸æ“‡æ¨™ç±¤"
msgid "BoardScope|Current iteration"
-msgstr ""
+msgstr "ç›®å‰è¿­ä»£"
msgid "BoardScope|Don't filter milestone"
-msgstr ""
+msgstr "ä¸éŽæ¿¾é‡Œç¨‹ç¢‘"
msgid "BoardScope|Edit"
-msgstr ""
+msgstr "編輯"
msgid "BoardScope|Iteration"
-msgstr ""
+msgstr "迭代"
msgid "BoardScope|Labels"
-msgstr ""
+msgstr "標籤"
msgid "BoardScope|Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "BoardScope|No iteration"
-msgstr ""
+msgstr "沒有迭代"
msgid "BoardScope|No milestone"
-msgstr ""
+msgstr "沒有里程碑"
msgid "BoardScope|Search iterations"
-msgstr ""
+msgstr "æœå°‹è¿­ä»£"
msgid "BoardScope|Search milestones"
-msgstr ""
+msgstr "æœå°‹é‡Œç¨‹ç¢‘"
msgid "BoardScope|Select assignee"
-msgstr ""
+msgstr "é¸å–指派人"
msgid "BoardScope|Select iteration"
-msgstr ""
+msgstr "é¸å–迭代"
msgid "BoardScope|Select labels"
-msgstr ""
+msgstr "é¸å–標籤"
msgid "BoardScope|Select milestone"
-msgstr ""
+msgstr "é¸å–里程碑"
msgid "BoardScope|Select weight"
-msgstr ""
+msgstr "é¸å–權é‡"
msgid "BoardScope|Started"
-msgstr ""
+msgstr "開始"
msgid "BoardScope|Upcoming"
-msgstr ""
+msgstr "å³å°‡æŽ¨å‡º"
msgid "BoardScope|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Boards"
-msgstr ""
+msgstr "看æ¿"
msgid "Boards and board lists"
-msgstr ""
+msgstr "看æ¿å’Œçœ‹æ¿æ¸…å–®"
msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
msgid_plural "Boards|+ %{displayedIssuablesCount} more %{issuableType}s"
-msgstr[0] ""
+msgstr[0] "+ %{displayedIssuablesCount} 更多 %{issuableType}"
msgid "Boards|An error occurred while creating the epic. Please try again."
-msgstr ""
+msgstr "建立epic時發生錯誤,請é‡è©¦ã€‚"
msgid "Boards|An error occurred while creating the issue. Please try again."
-msgstr ""
+msgstr "建立議題時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while creating the list. Please try again."
-msgstr ""
+msgstr "建立清單時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while fetching child groups. Please try again."
-msgstr ""
+msgstr "抓å–å­ç¾¤çµ„時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while fetching group projects. Please try again."
-msgstr ""
+msgstr "抓å–群組專案時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
+msgstr "抓å–議題時發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Boards|An error occurred while fetching labels. Please reload the page."
-msgstr ""
+msgstr "抓å–標籤時發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
-msgstr ""
+msgstr "抓å–看æ¿å²è©© (epic) 時發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "抓å–看æ¿è­°é¡Œæ™‚發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
-msgstr ""
+msgstr "抓å–看æ¿æ¸…單時發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
-msgstr ""
+msgstr "抓å–çœ‹æ¿ swimlanes 時發生錯誤。請é‡æ–°åŠ è¼‰é é¢ã€‚"
msgid "Boards|An error occurred while fetching the board. Please reload the page."
-msgstr ""
+msgstr "抓å–看æ¿æ™‚發生錯誤。請é‡æ–°åŠ è¼‰é é¢ã€‚"
msgid "Boards|An error occurred while generating lists. Please reload the page."
-msgstr ""
+msgstr "產生清單時發生錯誤。請é‡æ–°åŠ è¼‰é é¢ã€‚"
msgid "Boards|An error occurred while moving the epic. Please try again."
-msgstr ""
+msgstr "移動 epic 時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while moving the issue. Please try again."
-msgstr ""
+msgstr "移動å•é¡Œ (issue)時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while removing the list. Please try again."
-msgstr ""
+msgstr "移動清單時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|An error occurred while updating the board list. Please try again."
-msgstr ""
+msgstr "更新看æ¿æ¸…單時發生錯誤。請é‡è©¦ã€‚"
msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
-msgstr[0] ""
+msgstr[0] "被 %{blockedByCount} %{issuableType}ç¦ç”¨"
msgid "Boards|Collapse"
-msgstr ""
+msgstr "收起"
msgid "Boards|Edit board"
-msgstr ""
+msgstr "編輯看æ¿"
msgid "Boards|Expand"
-msgstr ""
+msgstr "展開"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
-msgstr ""
+msgstr "無法抓å–ç¦ç”¨çš„ %{issuableType}"
msgid "Boards|New board"
-msgstr ""
+msgstr "新建看æ¿"
msgid "Boards|New epic"
-msgstr ""
+msgstr "新建å²è©©"
msgid "Boards|Retrieving blocking %{issuableType}s"
-msgstr ""
+msgstr "正在å–回å°éŽ–中的%{issuableType}"
msgid "Boards|View all blocking %{issuableType}s"
-msgstr ""
+msgstr "查看所有å°éŽ–中的 %{issuableType}"
msgid "Boards|View scope"
-msgstr ""
+msgstr "查看範åœ"
msgid "Board|An error occurred while fetching the board, please try again."
-msgstr ""
+msgstr "讀å–看æ¿æ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "Board|Are you sure you want to delete this board?"
-msgstr ""
+msgstr "確定è¦åˆªé™¤æ­¤çœ‹æ¿å—Žï¼Ÿ"
msgid "Board|Board scope"
-msgstr ""
+msgstr "看æ¿ç¯„åœ"
msgid "Board|Create board"
-msgstr ""
+msgstr "建立看æ¿"
msgid "Board|Create new board"
-msgstr ""
+msgstr "建立新看æ¿"
msgid "Board|Delete board"
-msgstr ""
+msgstr "刪除看æ¿"
msgid "Board|Edit board"
-msgstr ""
+msgstr "編輯看æ¿"
msgid "Board|Enter board name"
-msgstr ""
+msgstr "輸入看æ¿å稱"
msgid "Board|Failed to delete board. Please try again."
-msgstr ""
+msgstr "刪除看æ¿å¤±æ•—,請é‡è©¦ã€‚"
msgid "Board|Load more epics"
-msgstr ""
+msgstr "加載更多å²è©©"
msgid "Board|Load more issues"
-msgstr ""
+msgstr "載入更多議題"
msgid "Board|Loading epics"
-msgstr ""
+msgstr "正在加載å²è©©"
msgid "Bold text"
-msgstr ""
+msgstr "粗體字"
msgid "Both SSH and HTTP(S)"
-msgstr ""
+msgstr "SSH 和 HTTP(S)"
msgid "Both project and dashboard_path are required"
-msgstr ""
+msgstr "專案和儀表æ¿è·¯å¾‘都是必需的"
msgid "Branch"
-msgstr ""
+msgstr "分支"
msgid "Branch %{branchName} was not found in this project's repository."
-msgstr ""
+msgstr "未在此項目的版本庫中找到 %{branchName} 分支。"
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr ""
+msgstr "已創建分支 %{branch_name}。如需設置自動部署,請é¸æ“‡åˆé©çš„ GitLab CI Yaml範本並æ交更改。%{link_to_autodeploy_doc}"
msgid "Branch already exists"
-msgstr ""
+msgstr "分支已經存在"
msgid "Branch changed"
-msgstr ""
+msgstr "分支已變更"
msgid "Branch has been updated since the merge was requested."
-msgstr ""
+msgstr "自請求åˆä½µä»¥ä¾†ï¼Œåˆ†æ”¯å·²æ›´æ–°ã€‚"
msgid "Branch is already taken"
-msgstr ""
+msgstr "分支已被採用"
msgid "Branch name"
msgstr "分支å稱"
msgid "Branch not loaded - %{branchId}"
-msgstr ""
+msgstr "分支未被載入 - %{branchId}"
msgid "Branch rules"
-msgstr ""
+msgstr "分支è¦å‰‡"
+
+msgid "BranchRules|%{linkStart}Wildcards%{linkEnd} such as *-stable or production/* are supported."
+msgstr "%{linkStart}è¬ç”¨å­—å…ƒ%{linkEnd} å¯æ”¯æ´å½¢å¦‚ *-stable or production/* 。"
+
+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 push"
+msgstr "å…許推é€"
+
+msgid "BranchRules|An error occurred while fetching branches."
+msgstr "æ“·å–分支時發生錯誤。"
+
+msgid "BranchRules|Branch"
+msgstr "分支"
+
+msgid "BranchRules|Create wildcard: %{searchTerm}"
+msgstr "建立è¬ç”¨å­—元:%{searchTerm}"
+
+msgid "BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}"
+msgstr "維æŒç©©å®šåˆ†æ”¯çš„安全並強制開發者使用åˆä½µè«‹æ±‚。%{linkStart}什麼是å—ä¿è­·çš„分支?%{linkEnd}"
+
+msgid "BranchRules|No matching results"
+msgstr "無符åˆçš„çµæžœ"
+
+msgid "BranchRules|Protections"
+msgstr "ä¿è­·"
+
+msgid "BranchRules|Reject code pushes that change files listed in the CODEOWNERS file."
+msgstr "拒絕程å¼ç¢¼æŽ¨é€è®Šæ›´åˆ—æ–¼ CODEOWNERS 檔案中的檔案。"
+
+msgid "BranchRules|Require approval from code owners."
+msgstr "需è¦ç¨‹å¼ç¢¼æ“有者的批准。"
msgid "Branches"
-msgstr ""
+msgstr "分支"
+
+msgid "Branches: %{source_branch} to %{target_branch}"
+msgstr "分支:%{source_branch} 到 %{target_branch}"
+
+msgid "Branches: %{source_branch} → %{target_branch}"
+msgstr "分支:%{source_branch} → %{target_branch}"
msgid "Branches|Active"
-msgstr ""
+msgstr "æ´»èº"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "æ´»èºåˆ†æ”¯"
msgid "Branches|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this branch."
-msgstr ""
+msgstr "在您確èªä¸¦é¸æ“‡ %{strongStart}%{buttonText},%{strongEnd} 後,您將無法復原此分支。"
msgid "Branches|All"
-msgstr ""
+msgstr "全部"
msgid "Branches|Cancel, keep branch"
-msgstr ""
+msgstr "分支|å–消,ä¿ç•™åˆ†æ”¯"
msgid "Branches|Can’t find HEAD commit for this branch"
-msgstr ""
+msgstr "分支|找ä¸åˆ°è©²åˆ†æ”¯çš„ HEAD æ交"
msgid "Branches|Compare"
-msgstr ""
+msgstr "比較"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr ""
+msgstr "刪除所有已åˆä½µåˆ° %{default_branch} 的分支。"
msgid "Branches|Delete branch"
-msgstr ""
+msgstr "刪除分支"
msgid "Branches|Delete branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "分支|刪除分支,您確定繼續嗎?"
msgid "Branches|Delete merged branches"
-msgstr ""
+msgstr "刪除已åˆä½µçš„分支"
msgid "Branches|Delete protected branch"
-msgstr ""
+msgstr "刪除å—ä¿è­·çš„分支"
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "分支|刪除å—ä¿è­·çš„分支,您確定繼續嗎?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "分支|刪除 %{strongStart}%{branchName}%{strongEnd} 分支æ“作無法撤銷。您確定繼續嗎?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
-msgstr ""
+msgstr "刪除已åˆä½µçš„分支後將無法回復,您確定繼續嗎?"
msgid "Branches|Filter by branch name"
-msgstr ""
+msgstr "僅篩é¸åˆ†æ”¯å稱"
msgid "Branches|Merged into %{default_branch}"
-msgstr ""
+msgstr "å·²åˆä½µè‡³ %{default_branch}"
msgid "Branches|New branch"
-msgstr ""
+msgstr "新建分支"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„分支"
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr ""
+msgstr "åªæœ‰é …目維護者或所有者æ‰èƒ½åˆªé™¤å—ä¿è­·çš„分支"
msgid "Branches|Overview"
-msgstr ""
+msgstr "概覽"
msgid "Branches|Please type the following to confirm:"
-msgstr ""
+msgstr "分支|請輸入以下內容進行確èªï¼š"
msgid "Branches|Show active branches"
-msgstr ""
+msgstr "查看活èºåˆ†æ”¯"
msgid "Branches|Show all branches"
-msgstr ""
+msgstr "查看所有分支"
msgid "Branches|Show more active branches"
-msgstr ""
+msgstr "查看更多活èºåˆ†æ”¯"
msgid "Branches|Show more stale branches"
-msgstr ""
+msgstr "查看更多éžæ´»èºåˆ†æ”¯"
msgid "Branches|Show overview of the branches"
-msgstr ""
+msgstr "查看分支概覽"
msgid "Branches|Show stale branches"
-msgstr ""
+msgstr "查看éžæ´»èºåˆ†æ”¯"
msgid "Branches|Stale"
-msgstr ""
+msgstr "éžæ´»èº"
msgid "Branches|Stale branches"
-msgstr ""
+msgstr "éžæ´»èºåˆ†æ”¯"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr ""
+msgstr "分支無法自動æ交,因為與上游分支è¡çªã€‚"
msgid "Branches|The default branch cannot be deleted"
-msgstr ""
+msgstr "無法刪除é è¨­åˆ†æ”¯"
msgid "Branches|This branch hasn't been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
+msgstr "此分支尚未åˆä½µåˆ° %{defaultBranchName}。為é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®åœ¨åˆªé™¤ä¹‹å‰åˆä½µæ­¤åˆ†æ”¯ã€‚"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
-msgstr ""
+msgstr "è¦æ”¾æ£„本機變更並覆蓋上游版本的分支,請在此處將其刪除,然後é¸æ“‡ä¸Šé¢çš„「立å³æ›´æ–°ã€ã€‚"
msgid "Branches|Unable to load branches"
-msgstr ""
+msgstr "無法載入分支"
msgid "Branches|Yes, delete branch"
-msgstr ""
+msgstr "分支|是的,刪除分支"
msgid "Branches|Yes, delete protected branch"
-msgstr ""
+msgstr "是的,刪除å—ä¿è­·çš„分支"
msgid "Branches|You're about to permanently delete the branch %{branchName}."
-msgstr ""
+msgstr "您將永久刪除 %{branchName} 分支。"
msgid "Branches|You're about to permanently delete the protected branch %{branchName}."
-msgstr ""
+msgstr "您將永久刪除å—ä¿è­·çš„ %{branchName} 分支 。"
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "與上游存在差異"
msgid "Branches|merged"
-msgstr ""
+msgstr "å·²åˆä½µ"
msgid "Branches|protected"
-msgstr ""
+msgstr "å—ä¿è­·"
msgid "Breadcrumbs"
-msgstr ""
+msgstr "é é¢è·¯å¾‘"
msgid "Broadcast Message was successfully created."
-msgstr ""
+msgstr "廣播訊æ¯å·²æˆåŠŸå»ºç«‹ã€‚"
msgid "Broadcast Message was successfully updated."
-msgstr ""
+msgstr "廣播訊æ¯å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Broadcast Messages"
-msgstr ""
+msgstr "廣播訊æ¯"
msgid "Browse Directory"
-msgstr ""
+msgstr "ç€è¦½ç›®éŒ„"
msgid "Browse File"
-msgstr ""
+msgstr "ç€è¦½æ–‡ä»¶"
msgid "Browse Files"
-msgstr ""
+msgstr "ç€è¦½æ–‡ä»¶"
msgid "Browse artifacts"
-msgstr ""
+msgstr "ç€è¦½ç”¢ç‰©"
msgid "Browse files"
-msgstr ""
+msgstr "ç€è¦½æ–‡ä»¶"
msgid "Browse templates"
-msgstr ""
+msgstr "ç€è¦½ç¯„本"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
-msgstr ""
+msgstr "抓å–產物時發生錯誤"
msgid "BuildArtifacts|Loading artifacts"
-msgstr ""
+msgstr "正在載入產物"
msgid "Built-in"
-msgstr ""
+msgstr "內建"
msgid "Bulk request concurrency"
-msgstr ""
+msgstr "並發批é‡è«‹æ±‚"
msgid "Bulk update"
-msgstr ""
+msgstr "批次更新"
msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
-msgstr ""
+msgstr "%{host} 正在é‹è¡ŒéŽæœŸçš„ GitLab 版本(v%{version})"
msgid "BulkImport|%{feature} (require v%{version})"
-msgstr ""
+msgstr "%{feature}ï¼ˆéœ€è¦ v%{version})"
msgid "BulkImport|Destination"
-msgstr ""
+msgstr "BulkImport|目的地"
msgid "BulkImport|Destination group"
-msgstr ""
+msgstr "BulkImport|目標群組"
msgid "BulkImport|Existing groups"
-msgstr ""
+msgstr "BulkImport|ç¾æœ‰ç¾¤çµ„"
msgid "BulkImport|Filter by source group"
-msgstr ""
+msgstr "BulkImport|ä¾ç¾¤çµ„來æºç¯©é¸"
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 "以下資料將ä¸æœƒè¢«é·ç§»ï¼š%{bullets} 如果您在é·ç§»ä¸­éœ€è¦æ­¤è³‡æ–™ï¼Œè«‹è¯ç¹« %{host} 系統管ç†å“¡å‡ç´š GitLab"
msgid "BulkImport|From source group"
-msgstr ""
+msgstr "BulkImport|來自於æºç¾¤çµ„"
msgid "BulkImport|Group import history"
-msgstr ""
+msgstr "BulkImport|群組匯入歷å²"
msgid "BulkImport|History"
-msgstr ""
+msgstr "BulkImport|æ­·å²"
msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source group. Change the destination and try again."
-msgstr ""
+msgstr "BulkImport|匯入失敗:目的地ä¸èƒ½æ˜¯ä¾†æºç¾¤çµ„çš„å­ç¾¤çµ„。請變更目的地,並é‡è©¦ã€‚"
msgid "BulkImport|Import groups from GitLab"
-msgstr ""
+msgstr "BulkImport|從 GitLab 匯入群組"
msgid "BulkImport|Import is finished. Pick another name for re-import"
-msgstr ""
+msgstr "BulkImport|匯入已完æˆã€‚é¸æ“‡å¦ä¸€å€‹å稱以é‡æ–°åŒ¯å…¥"
msgid "BulkImport|Import selected"
-msgstr ""
+msgstr "BulkImport|å·²é¸å–匯入"
msgid "BulkImport|Importing the group failed."
-msgstr ""
+msgstr "匯入群組失敗。"
msgid "BulkImport|Last imported to %{link}"
-msgstr ""
+msgstr "上次匯入到 %{link}"
msgid "BulkImport|Name already exists."
-msgstr ""
+msgstr "å稱已存在。"
msgid "BulkImport|Name already used as a target for another group."
-msgstr ""
+msgstr "å稱已被其他群組所使用。"
msgid "BulkImport|No additional information provided."
-msgstr ""
+msgstr "未æ供其它信æ¯ã€‚"
msgid "BulkImport|No groups found"
-msgstr ""
+msgstr "未發ç¾ç¾¤çµ„"
msgid "BulkImport|No history is available"
-msgstr ""
+msgstr "沒有歷å²è¨˜éŒ„"
msgid "BulkImport|No parent"
-msgstr ""
+msgstr "沒有父級"
msgid "BulkImport|Only groups that you have the %{role} role for are listed as groups you can import."
-msgstr ""
+msgstr "åªæœ‰æ‚¨æ“有 %{role} 角色的群組æ‰æœƒè¢«åˆ—為您å¯ä»¥å°Žå…¥çš„群組。"
msgid "BulkImport|Project import history"
-msgstr ""
+msgstr "專案匯入歷å²"
msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
-msgstr ""
+msgstr "é‡æ–°åŒ¯å…¥æœƒå‰µå»ºä¸€å€‹æ–°ç¾¤çµ„。它ä¸èˆ‡ç¾æœ‰ç¾¤çµ„åŒæ­¥ã€‚"
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
-msgstr ""
+msgstr "顯示 %{start}-%{end} / %{total}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own from %{link}"
-msgstr ""
+msgstr "顯示您從 %{link} 所æ“有 %{total} çš„ %{start}-%{end}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} that you own matching filter \"%{filter}\" from %{link}"
-msgstr ""
+msgstr "從 %{link} 顯示符åˆæ‚¨æ‰€æ“æœ‰ç¯©é¸ \"%{filter}\" çš„ %{start}-%{end} / %{total}"
msgid "BulkImport|Source"
-msgstr ""
+msgstr "來æº"
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "來æºç¾¤çµ„"
msgid "BulkImport|Template / File-based import / GitLab Migration"
-msgstr ""
+msgstr "模版 / 基於文件匯入 / GitLab é·ç§»"
msgid "BulkImport|To new group"
-msgstr ""
+msgstr "到新群組"
msgid "BulkImport|Update of import statuses with realtime changes failed"
-msgstr ""
+msgstr "更新實時變動的匯入狀態失敗"
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "您匯入的群組將出ç¾åœ¨é€™è£¡ã€‚"
msgid "BulkImport|Your imported projects will appear here."
-msgstr ""
+msgstr "您匯入的專案將出ç¾åœ¨é€™è£¡ã€‚"
msgid "BulkImport|expected an associated Group but has an associated Project"
-msgstr ""
+msgstr "需關è¯åˆ°ä¸€å€‹ç¾¤çµ„,但目å‰æœ‰ä¸€å€‹é—œè¯çš„專案"
msgid "BulkImport|expected an associated Project but has an associated Group"
-msgstr ""
+msgstr "批次匯入|é æœŸç‚ºé—œè¯çš„專案,但目å‰ç‚ºé—œè¯çš„群組"
msgid "BulkImport|must be a group"
-msgstr ""
+msgstr "批次匯入|必須是一個群組"
msgid "Bullet list"
-msgstr ""
+msgstr "項目符號清單"
msgid "Burndown chart"
-msgstr ""
+msgstr "燃盡圖"
msgid "BurndownChartLabel|Remaining"
-msgstr ""
+msgstr "其餘"
msgid "Burnup chart"
-msgstr ""
+msgstr "燃起圖"
msgid "Burnup chart could not be generated due to too many events"
-msgstr ""
+msgstr "由於事件éŽå¤šï¼Œç„¡æ³•ç”¢ç”Ÿç‡ƒèµ·åœ–"
msgid "Business"
-msgstr ""
+msgstr "商業"
msgid "Business metrics (Custom)"
-msgstr ""
+msgstr "業務指標(自訂)"
msgid "Busy"
-msgstr ""
+msgstr "忙碌"
msgid "Buy CI Minutes"
-msgstr ""
+msgstr "購買 CI 時數"
msgid "Buy Storage"
-msgstr ""
+msgstr "購買儲存空間"
msgid "Buy more Pipeline minutes"
-msgstr ""
+msgstr "購買更多æµæ°´ç·šåˆ†é˜æ•¸"
msgid "By %{user_name}"
-msgstr ""
+msgstr "ç”± %{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 "通éŽä½¿ç”¨èˆ‡ä¼æ¥­é›»å­éƒµä»¶åœ°å€ç¶å®šçš„帳號進行身份驗證,å¯ä»¥å¾—知該帳號是ä¼æ¥­ä½¿ç”¨è€…。 "
msgid "By default, all projects and groups will use the global notifications setting."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œæ‰€æœ‰é …目和群組將使用全域通知設定。"
msgid "By month"
-msgstr ""
+msgstr "按月"
msgid "By quarter"
-msgstr ""
+msgstr "按季度"
msgid "By week"
-msgstr ""
+msgstr "按週"
msgid "ByAuthor|by"
msgstr "作者:"
msgid "CHANGELOG"
-msgstr ""
+msgstr "更新日誌"
msgid "CI Lint"
-msgstr ""
+msgstr "CI Lint"
msgid "CI configuration validated, including all configuration added with the %{codeStart}include%{codeEnd} keyword. %{link}"
-msgstr ""
+msgstr "已驗證 CI 組態,包括所有使用 %{codeStart}include%{codeEnd} é—œéµå­—新增的組態。 %{link}"
msgid "CI settings"
-msgstr ""
+msgstr "CI 設定"
msgid "CI variables"
-msgstr ""
+msgstr "CI 變數"
msgid "CI/CD"
-msgstr ""
+msgstr "CI/CD"
msgid "CI/CD Analytics"
-msgstr ""
+msgstr "CI / CD分æž"
msgid "CI/CD Settings"
-msgstr ""
+msgstr "CI/CD 設定"
msgid "CI/CD configuration"
-msgstr ""
+msgstr "CI/CD é…ç½®"
msgid "CI/CD configuration file"
-msgstr ""
+msgstr "CI/CD 設定檔"
msgid "CI/CD limits"
-msgstr ""
+msgstr "CI/CD é™åˆ¶"
msgid "CI/CD minutes"
-msgstr ""
+msgstr "CI/CD 分é˜æ•¸"
msgid "CI/CD|No projects have been added to the scope"
-msgstr ""
+msgstr "CI/CD|範åœå…§æœªæ–°å¢žä»»ä½•å°ˆæ¡ˆ"
msgid "CICDAnalytics|%{percent}%{percentSymbol}"
-msgstr ""
+msgstr "%{percent}%{percentSymbol}"
msgid "CICDAnalytics|All time"
-msgstr ""
+msgstr "所有時間"
msgid "CICDAnalytics|Change failure rate"
-msgstr ""
+msgstr "變更失敗率"
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "部署頻率"
msgid "CICDAnalytics|Lead time"
-msgstr ""
+msgstr "å‰ç½®æ™‚é–“"
msgid "CICDAnalytics|No shared runner minute usage data available"
-msgstr ""
+msgstr "沒有å¯ç”¨çš„共享執行器分é˜ä½¿ç”¨è³‡æ–™"
msgid "CICDAnalytics|Projects with releases"
-msgstr ""
+msgstr "發布的專案"
msgid "CICDAnalytics|Release"
msgid_plural "CICDAnalytics|Releases"
-msgstr[0] ""
+msgstr[0] "發布"
msgid "CICDAnalytics|Release statistics"
-msgstr ""
+msgstr "發布統計"
msgid "CICDAnalytics|Releases"
-msgstr ""
+msgstr "發布"
msgid "CICDAnalytics|Shared Runners Usage"
-msgstr ""
+msgstr "CICDAnalytics|共享執行器使用情æ³"
msgid "CICDAnalytics|Shared runner duration is the total runtime of all jobs that ran on shared runners"
-msgstr ""
+msgstr "共享執行器æŒçºŒæ™‚間是所有作業在共享執行器上的總é‹è¡Œæ™‚é–“"
msgid "CICDAnalytics|Shared runner pipeline minute duration by month"
-msgstr ""
+msgstr "CICDAnalytics|共享執行器æµæ°´ç·šåˆ†é˜æŒçºŒæœŸé–“(按月)"
msgid "CICDAnalytics|Shared runner usage"
-msgstr ""
+msgstr "CICDAnalytics|共享執行器使用情æ³"
msgid "CICDAnalytics|Shared runner usage is the total runtime of all jobs that ran on shared runners"
-msgstr ""
+msgstr "共享執行器的使用é‡æ˜¯åœ¨å…±äº«çš„執行器上é‹è¡Œçš„所有作業的總é‹è¡Œæ™‚é–“"
msgid "CICDAnalytics|Something went wrong while fetching release statistics"
-msgstr ""
+msgstr "抓å–發布統計信æ¯æ™‚出ç¾éŒ¯èª¤"
msgid "CICDAnalytics|Time to restore service"
-msgstr ""
+msgstr "æœå‹™æ¢å¾©æ™‚é–“"
msgid "CICDAnalytics|What is shared runner duration?"
-msgstr ""
+msgstr "什麼是共享執行器æŒçºŒæ™‚間?"
msgid "CICDAnalytics|What is shared runner usage?"
-msgstr ""
+msgstr "CICDAnalytics|共享的執行器使用情æ³ï¼Ÿ"
msgid "CICD|Add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} for your deployment strategy to work."
-msgstr ""
+msgstr "è«‹å°‡%{base_domain_link_start}基礎域å%{link_end}添加到%{kubernetes_cluster_link_start}Kuberneteså¢é›†%{link_end},æ‰èƒ½ä½¿æ‚¨çš„部署策略正常工作。"
msgid "CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable."
-msgstr ""
+msgstr "添加具有域åçš„%{kubernetes_cluster_link_start}Kuberneteså¢é›†æ•´åˆ%{link_end},或創建一個變é‡å為AUTO_DEVOPS_PLATFORM_TARGETçš„CI變é‡ã€‚"
msgid "CICD|Add an existing project to the scope"
-msgstr ""
+msgstr "CICD|å°‡ç¾æœ‰å°ˆæ¡ˆå¢žåŠ åˆ°ç¯„åœ"
msgid "CICD|Auto DevOps"
-msgstr ""
+msgstr "Auto DevOps"
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr ""
+msgstr "自動部署到é ç™¼å¸ƒç’°å¢ƒï¼Œæ‰‹å‹•éƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Continuous deployment to production"
-msgstr ""
+msgstr "æŒçºŒéƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Continuous deployment to production using timed incremental rollout"
-msgstr ""
+msgstr "使用已定時的增é‡éƒ¨ç½²é€²è¡ŒæŒçºŒéƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒ"
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "é è¨­ç‚ºAuto DevOpsæµæ°´ç·š"
msgid "CICD|Default to Auto DevOps pipeline for all projects"
-msgstr ""
+msgstr "所有項目é è¨­ä½¿ç”¨Auto DevOpsæµæ°´ç·š"
msgid "CICD|Deployment strategy"
-msgstr ""
+msgstr "部署策略"
msgid "CICD|Jobs"
-msgstr ""
+msgstr "作業"
msgid "CICD|Limit"
-msgstr ""
+msgstr "é™åˆ¶"
msgid "CICD|Limit CI_JOB_TOKEN access"
-msgstr ""
+msgstr "é™åˆ¶ CI_JOB_TOKEN 訪å•"
msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
-msgstr ""
+msgstr "é¸æ“‡å¯ä»¥é€šéŽ API 訪å•çš„專案來驗證此項目的 CI_JOB_TOKEN CI/CD 變é‡ã€‚"
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file. %{link_start}What is Auto DevOps?%{link_end}"
-msgstr ""
+msgstr "Auto DevOps æµæ°´ç·šé è¨­åœ¨æ²’有 CI/CD é…置文件的所有專案中é‹è¡Œã€‚%{link_start}什麼是 Auto DevOps?%{link_end}"
msgid "CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
+msgstr "在未找到備用 CI é…置文件時,將使用Auto DevOpsæµæ°´ç·šã€‚"
msgid "CICD|There are several CI/CD limits in place."
-msgstr ""
+msgstr "有幾個 CI/CD é™åˆ¶ã€‚"
msgid "CICD|Unprotected branches will not have access to the cache from protected branches."
-msgstr ""
+msgstr "未å—ä¿è­·çš„分支將無法存å–å—ä¿è­·åˆ†æ”¯çš„ç·©å­˜"
msgid "CICD|Use separate caches for protected branches"
-msgstr ""
+msgstr "為å—ä¿è­·çš„分支使用ç¨ç«‹çš„ç·©å­˜"
msgid "CICD|group enabled"
-msgstr ""
+msgstr "群組已啟用"
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "已啟用的實體"
msgid "CLOSED"
-msgstr ""
+msgstr "已關閉"
msgid "CLOSED (MOVED)"
-msgstr ""
+msgstr "已關閉(已移走)"
msgid "CODEOWNERS rule violation"
-msgstr ""
+msgstr "é•åCODEOWNERSè¦å‰‡"
msgid "CONTRIBUTING"
-msgstr ""
+msgstr "è²¢ç»è¨Šæ¯"
msgid "CPU"
msgstr "CPU"
msgid "CSV is being generated and will be emailed to you upon completion."
-msgstr ""
+msgstr "æ­£åœ¨ç”Ÿæˆ CSV,完æˆå¾Œå°‡é€šéŽé›»å­éƒµä»¶ç™¼é€çµ¦æ‚¨ã€‚"
msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project will help your users stay secure and informed."
-msgstr ""
+msgstr "作為維護者,為您專案中的æ¼æ´žç”³è«‹CVE,將有助於您的使用者ä¿æŒå®‰å…¨å’ŒçŸ¥æƒ…。"
msgid "CVE|CVE ID Request"
-msgstr ""
+msgstr "CVE ID 申請"
msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
-msgstr ""
+msgstr "Common Vulnerability Enumeration(CVE)標識符用於跟蹤特定版本代碼中的ä¸åŒæ¼æ´žã€‚"
msgid "CVE|Create CVE ID Request"
-msgstr ""
+msgstr "創建CVE ID申請"
msgid "CVE|Enable CVE ID requests in the issue sidebar"
-msgstr ""
+msgstr "在議題å´é‚Šæ¬„中啟用CVE ID申請"
msgid "CVE|Request CVE ID"
-msgstr ""
+msgstr "申請 CVE ID"
msgid "CVE|Why Request a CVE ID?"
-msgstr ""
+msgstr "為什麼è¦ç”³è«‹ä¸€å€‹ CVE ID?"
msgid "Cadence is not automated"
-msgstr ""
+msgstr "Cadence ä¸æ˜¯è‡ªå‹•åŒ–çš„"
msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
+msgstr "計算é‡æ–°ç´¢å¼•æœŸé–“的切片數。 乘數應用於æ¯å€‹ç´¢å¼•çš„分片數。 詳細了解 %{slice_multiplier_link_start}slice 乘數é…ç½®%{slice_multiplier_link_end}。"
msgid "Callback URL"
-msgstr ""
+msgstr "回調 URL"
msgid "Campfire room ID (optional)"
-msgstr ""
+msgstr "Campfire room ID(å¯é¸ï¼‰"
msgid "Campfire subdomain (optional)"
-msgstr ""
+msgstr "Campfire å­åŸŸï¼ˆå¯é¸ï¼‰"
msgid "Campfire token"
-msgstr ""
+msgstr "Campfire 令牌"
msgid "CampfireService|API authentication token from Campfire."
-msgstr ""
+msgstr "來自 Campfire 的 API 身份驗證令牌。"
msgid "CampfireService|From the end of the room URL."
-msgstr ""
+msgstr "從 room URL 的末尾開始。"
msgid "CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}"
-msgstr ""
+msgstr "å‘ Campfire èŠå¤©å®¤ç™¼é€æœ‰é—œæŽ¨é€äº‹ä»¶çš„通知。 %{docs_link}"
msgid "CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain."
-msgstr ""
+msgstr "%{code_open}.campfirenow.com%{code_close} å­åŸŸå。"
msgid "Can be manually deployed to"
-msgstr ""
+msgstr "å¯ä»¥æ‰‹å‹•éƒ¨ç½²åˆ°"
msgid "Can be overridden in each project."
-msgstr ""
+msgstr "å¯ä»¥åœ¨æ¯å€‹å°ˆæ¡ˆä¸­è¦†è“‹ã€‚"
msgid "Can create groups:"
-msgstr ""
+msgstr "å¯ä»¥å‰µå»ºç¾¤çµ„:"
msgid "Can not delete primary training"
-msgstr ""
+msgstr "ä¸èƒ½åˆªé™¤åˆç´šåŸ¹è¨“"
msgid "Can't apply as the source branch was deleted."
-msgstr ""
+msgstr "由於來æºåˆ†æ”¯å·²åˆªé™¤ï¼Œå› æ­¤ç„¡æ³•å¥—用。"
msgid "Can't apply as these lines were changed in a more recent version."
-msgstr ""
+msgstr "由於這幾行在較新版本中已被更改,故無法套用。"
msgid "Can't apply as this line was changed in a more recent version."
-msgstr ""
+msgstr "該行已在較新版本中被更改,故無法套用。"
msgid "Can't apply this suggestion."
-msgstr ""
+msgstr "無法套用此建議。"
msgid "Can't be empty"
-msgstr ""
+msgstr "ä¸èƒ½ç‚ºç©º"
msgid "Can't create snippet: %{err}"
-msgstr ""
+msgstr "無法建立程å¼ç¢¼ç‰‡æ®µï¼š %{err}"
msgid "Can't fetch content for the blob: %{err}"
-msgstr ""
+msgstr "無法ç²å–Blob的內容: %{err}"
msgid "Can't find HEAD commit for this branch"
-msgstr ""
+msgstr "無法找到此分支的 HEAD æ交"
msgid "Can't find variable: ZiteReader"
-msgstr ""
-
-msgid "Can't load mermaid module: %{err}"
-msgstr ""
+msgstr "找ä¸åˆ°è®Šæ•¸: ZiteReader"
msgid "Can't scan the code?"
-msgstr ""
+msgstr "無法掃æ二維碼?"
msgid "Can't update snippet: %{err}"
-msgstr ""
+msgstr "無法更新程å¼ç¢¼ç‰‡æ®µï¼š %{err}"
msgid "Canary"
-msgstr ""
+msgstr "Canary"
msgid "Canary Ingress does not exist in the environment."
-msgstr ""
+msgstr "該環境中ä¸å­˜åœ¨Canary Ingress。"
msgid "Canary weight must be specified and valid range (0..100)."
-msgstr ""
+msgstr "必須指定Canary權é‡ï¼Œæœ‰æ•ˆç¯„åœï¼ˆ0..100)。"
msgid "CanaryIngress|%{boldStart}Canary:%{boldEnd} %{canary}"
-msgstr ""
+msgstr "%{boldStart}Canary:%{boldEnd} %{canary}"
msgid "CanaryIngress|%{boldStart}Stable:%{boldEnd} %{stable}"
-msgstr ""
+msgstr "%{boldStart}Stable:%{boldEnd} %{stable}"
msgid "CanaryIngress|Canary"
-msgstr ""
+msgstr "Canary"
msgid "CanaryIngress|Change ratio"
-msgstr ""
+msgstr "變更比例"
msgid "CanaryIngress|Change the ratio of canary deployments?"
-msgstr ""
+msgstr "更改canary部署比例?"
msgid "CanaryIngress|Doing so will set a deployment change in progress. This temporarily blocks any further configuration until the deployment is finished."
-msgstr ""
+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 "與穩定部署相比,您將 %{environment} çš„canaryæ供比例更改為:"
msgid "Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Cancel and close"
-msgstr ""
+msgstr "å–消並關閉"
msgid "Cancel downstream pipeline"
-msgstr ""
+msgstr "å–消下游æµæ°´ç·š"
msgid "Cancel editing"
-msgstr ""
+msgstr "å–消編輯"
msgid "Cancel index deletion"
-msgstr ""
+msgstr "å–消刪除索引æ“作"
msgid "Cancel running"
-msgstr ""
+msgstr "å–消執行"
msgid "Cancel this job"
-msgstr ""
+msgstr "å–消此作業"
msgid "Cancel your account"
-msgstr ""
+msgstr "å–消你的帳號"
msgid "Cancel, keep project"
-msgstr ""
+msgstr "å–消,ä¿ç•™å°ˆæ¡ˆ"
msgid "Canceled deployment to"
-msgstr ""
+msgstr "å·²å–消佈署至"
msgid "Cancelled"
-msgstr ""
+msgstr "å·²å–消"
msgid "Cancelling Preview"
-msgstr ""
+msgstr "å–消é è¦½"
msgid "Cannot assign a confidential epic to a non-confidential issue. Make the issue confidential and try again"
-msgstr ""
+msgstr "無法將機密å²è©©åˆ†é…給éžæ©Ÿå¯†è­°é¡Œã€‚請將此議題設置機密並é‡è©¦"
msgid "Cannot assign an issue that does not belong under the same group (or descendant) as the epic."
-msgstr ""
+msgstr "無法分é…與å²è©©ä¸å±¬æ–¼åŒä¸€ç¾¤çµ„(或後代)的議題"
msgid "Cannot be merged automatically"
-msgstr ""
+msgstr "無法自動åˆä½µ"
msgid "Cannot create the abuse report. The reported user was invalid. Please try again or contact support."
-msgstr ""
+msgstr "無法建立濫用報告。報告的使用者無效。請é‡è©¦æˆ–è¯ç¹«æ”¯æ´äººå“¡ã€‚"
msgid "Cannot create the abuse report. The user has been deleted."
-msgstr ""
+msgstr "無法建立濫用報告。使用者已被刪除。"
msgid "Cannot create the abuse report. This user has been blocked."
-msgstr ""
+msgstr "無法建立濫用報告。此使用者已被åœç”¨ã€‚"
msgid "Cannot delete %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "ä¸èƒ½åˆªé™¤å®‰å…¨ç­–略中引用的 %{profile_name}"
msgid "Cannot have multiple Jira imports running at the same time"
-msgstr ""
+msgstr "ä¸èƒ½åŒæ™‚é‹è¡Œå¤šå€‹Jira匯入"
msgid "Cannot have multiple unresolved alerts"
-msgstr ""
+msgstr "ä¸èƒ½æœ‰å¤šå€‹æœªè§£æ±ºçš„警示"
msgid "Cannot import because issues are not available in this project."
-msgstr ""
+msgstr "無法匯入,因為議題在此專案中ä¸å¯ç”¨ã€‚"
msgid "Cannot make the epic confidential if it contains non-confidential child epics"
-msgstr ""
+msgstr "如果å²è©©åŒ…å«éžç§å¯†å­å²è©©ï¼Œå‰‡ç„¡æ³•å°‡è©²å²è©©è¨­ç½®ç‚ºç§å¯†ã€‚"
msgid "Cannot make the epic confidential if it contains non-confidential issues"
-msgstr ""
+msgstr "如果å²è©©åŒ…å«éžç§å¯†è­°é¡Œï¼Œå‰‡ç„¡æ³•å°‡è©²å²è©©è¨­ç½®ç‚ºç§å¯†ã€‚"
msgid "Cannot merge"
-msgstr ""
+msgstr "無法åˆä½µ"
msgid "Cannot modify %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "無法修改安全策略中引用的 %{profile_name}"
msgid "Cannot modify managed Kubernetes cluster"
-msgstr ""
+msgstr "無法修改托管的 Kubernetes å¢é›†"
msgid "Cannot modify provider during creation"
-msgstr ""
+msgstr "創建期間無法修改æ供者"
msgid "Cannot promote issue because it does not belong to a group."
-msgstr ""
+msgstr "ä¸èƒ½å‡ç´šå•é¡Œï¼Œå› ç‚ºå®ƒä¸å±¬æ–¼ä¸€å€‹ç¾¤çµ„。"
msgid "Cannot promote issue due to insufficient permissions."
-msgstr ""
+msgstr "由於權é™ä¸è¶³ï¼Œç„¡æ³•å‡ç´šè­°é¡Œã€‚"
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
-msgstr ""
+msgstr "無法通éŽå…§éƒ¨ID引用群組%{timebox_type}ï¼"
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
-msgstr ""
+msgstr "無法顯示é è¦½ã€‚如需é è¦½ï¼Œè‰åœ–文件必須具有Sketch 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
msgid "Cannot skip two factor authentication setup"
-msgstr ""
+msgstr "無法跳éŽå…©æ­¥é©Ÿé©—證設定"
msgid "Capacity threshold"
-msgstr ""
+msgstr "容é‡é–¾å€¼"
msgid "Card holder name"
-msgstr ""
+msgstr "æŒå¡äººå§“å"
msgid "Card number:"
-msgstr ""
+msgstr "å¡è™Ÿï¼š"
msgid "CascadingSettings|Enforce deletion protection for all subgroups"
-msgstr ""
+msgstr "å°æ‰€æœ‰å­ç¾¤çµ„實施刪除ä¿è­·"
msgid "CascadingSettings|Enforce for all subgroups"
-msgstr ""
+msgstr "強制所有å­ç¾¤çµ„"
msgid "CascadingSettings|Setting enforced"
-msgstr ""
+msgstr "強制設置"
msgid "CascadingSettings|Subgroups cannot change this setting."
-msgstr ""
+msgstr "å­ç¾¤çµ„無法更改此設置。"
msgid "CascadingSettings|This setting has been enforced by an instance admin."
-msgstr ""
+msgstr "此設置已由實例管ç†å“¡å¼·åˆ¶åŸ·è¡Œã€‚"
msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
-msgstr ""
+msgstr "此設置已由%{link}的所有者強制執行。"
msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
-msgstr ""
+msgstr "無法更改,因為它被父級鎖定"
msgid "CascadingSettings|cannot be nil when locking the attribute"
-msgstr ""
+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 ""
+msgstr "此使用者內容將被移動到系統級「幽éˆä½¿ç”¨è€…ã€ï¼Œä»¥ä¿ç•™ä¾›æœªä¾†éœ€è¦æ™‚使用。 欲瞭解更多信æ¯ï¼Œè«‹åƒé–±%{link_start}用戶帳號刪除文檔%{link_end}。"
msgid "Certificate"
msgstr "憑證"
msgid "Certificate (PEM)"
-msgstr ""
+msgstr "憑證(PEM)"
msgid "Certificate Issuer"
-msgstr ""
+msgstr "憑證頒發機構"
msgid "Certificate Subject"
-msgstr ""
+msgstr "憑證主題"
msgid "Change Failure Rate"
-msgstr ""
+msgstr "變更失敗率"
msgid "Change assignee"
-msgstr ""
+msgstr "變更指派人"
msgid "Change assignee(s)"
-msgstr ""
+msgstr "變更指派人"
msgid "Change assignee(s)."
-msgstr ""
+msgstr "變更指派人。"
msgid "Change branches"
-msgstr ""
+msgstr "變更分支"
msgid "Change label"
-msgstr ""
+msgstr "變更標籤"
msgid "Change made by"
-msgstr ""
+msgstr "變更者"
msgid "Change milestone"
-msgstr ""
+msgstr "變更里程碑"
msgid "Change path"
-msgstr ""
+msgstr "變更路徑"
msgid "Change reviewer(s)"
-msgstr ""
+msgstr "變更審者"
msgid "Change reviewer(s)."
-msgstr ""
+msgstr "變更審閱者"
msgid "Change role"
-msgstr ""
+msgstr "變更角色"
msgid "Change status"
-msgstr ""
+msgstr "變更狀態"
msgid "Change subscription"
-msgstr ""
+msgstr "變更訂閱"
msgid "Change template"
-msgstr ""
+msgstr "變更模æ¿"
msgid "Change title"
-msgstr ""
+msgstr "變更標題"
msgid "Change your password"
-msgstr ""
+msgstr "變更您的密碼"
msgid "Change your password or recover your current one"
-msgstr ""
+msgstr "變更您的密碼或復原目å‰å¯†ç¢¼"
msgid "ChangeReviewer|Reviewer changed from %{old} to %{new}"
-msgstr ""
+msgstr "審閱者已從%{old}更改為%{new}"
msgid "ChangeReviewer|Reviewer changed to %{new}"
-msgstr ""
+msgstr "審閱者已更改為%{new}"
msgid "ChangeReviewer|Unassigned"
-msgstr ""
+msgstr "未指派"
msgid "ChangeTypeAction|Cherry-pick"
-msgstr ""
+msgstr "Cherry-pick"
msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab å°‡åœ¨ä½ çš„åˆ†å‰ (fork) 中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
msgid "ChangeTypeAction|Pick into branch"
-msgstr ""
+msgstr "é¸æ“‡åˆ†æ”¯"
msgid "ChangeTypeAction|Pick into project"
-msgstr ""
+msgstr "é¸æ“‡å°ˆæ¡ˆ"
msgid "ChangeTypeAction|Revert"
-msgstr ""
+msgstr "還原"
msgid "ChangeTypeAction|Revert in branch"
-msgstr ""
+msgstr "還原分支"
msgid "ChangeTypeAction|Search branches"
-msgstr ""
+msgstr "æœå°‹åˆ†æ”¯"
msgid "ChangeTypeAction|Search projects"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
-msgstr ""
+msgstr "由此變更建立一個新的%{newMergeRequest}"
msgid "ChangeTypeAction|Switch branch"
-msgstr ""
+msgstr "切æ›åˆ†æ”¯"
msgid "ChangeTypeAction|Switch project"
-msgstr ""
+msgstr "切æ›å°ˆæ¡ˆ"
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
-msgstr ""
+msgstr "這將建立一個新的æ交, 來還原ç¾æœ‰çš„變更。"
msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已開啟,變更將被æ交到%{branchName}。"
msgid "Changed"
-msgstr ""
+msgstr "已更改"
msgid "Changed assignee(s)."
-msgstr ""
+msgstr "已變更的指派人"
msgid "Changed merge method to %{merge_method}"
-msgstr ""
+msgstr "已變更åˆä½µæ–¹æ³•ç‚º %{merge_method}"
msgid "Changed reviewer(s)."
-msgstr ""
+msgstr "已變更審閱者。"
msgid "Changed squash option to %{squash_option}"
-msgstr ""
+msgstr "已變更壓縮é¸é …為 %{squash_option}"
msgid "Changed the title to \"%{title_param}\"."
-msgstr ""
+msgstr "已將標題變更為「%{title_param}ã€ã€‚"
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 ""
+msgstr "差異顯示方å¼ä¾%{b_open}來æº%{b_close}版本åˆä½µåˆ°%{b_open}目標%{b_close}版本的形å¼ã€‚"
msgid "Changes saved."
-msgstr ""
+msgstr "更改已儲存"
msgid "Changes suppressed. Click to show."
-msgstr ""
+msgstr "部分顯示。點此顯示全部。"
msgid "Changes the title to \"%{title_param}\"."
-msgstr ""
+msgstr "將標題變更為「%{title_param}ã€ã€‚"
msgid "Changes to the title have not been saved"
-msgstr ""
+msgstr "標題變更尚未儲存"
msgid "Changing any setting here requires an application restart"
-msgstr ""
+msgstr "更改此處的任何設定都需è¦é‡æ–°å•Ÿå‹•æ‡‰ç”¨ç¨‹å¼"
msgid "Characters left"
-msgstr ""
+msgstr "剩餘字元"
msgid "Characters over limit"
-msgstr ""
+msgstr "字數超éŽé™åˆ¶"
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
-msgstr ""
+msgstr "無法顯示圖表,因為資料請求已超時。%{documentationLink}"
msgid "Chat"
msgstr "å³æ™‚通訊"
msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
-msgstr ""
+msgstr "%{project_link}:ç”±%{user_combined_name}%{humanized_status}觸發的%{ref_type}%{ref_link}æµæ°´ç·š%{pipeline_link}耗時%{duration}"
msgid "ChatMessage|Branch"
-msgstr ""
+msgstr "分支"
msgid "ChatMessage|Commit"
-msgstr ""
+msgstr "æ交"
msgid "ChatMessage|Failed job"
-msgstr ""
+msgstr "失敗的作業"
msgid "ChatMessage|Failed stage"
-msgstr ""
+msgstr "失敗的階段"
msgid "ChatMessage|Invalid CI config YAML file"
-msgstr ""
+msgstr "無效的CIé…ç½®YAML文件"
msgid "ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}"
-msgstr ""
+msgstr "æµæ°´ç·š#%{pipeline_id}%{humanized_status}耗時%{duration}"
msgid "ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}"
-msgstr ""
+msgstr "ç”±%{user_combined_name}%{humanized_status}觸發的%{ref_type}%{ref_link}æµæ°´ç·š%{pipeline_link}"
msgid "ChatMessage|Tag"
-msgstr ""
+msgstr "標籤"
msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
-msgstr ""
+msgstr "以åŠ[其餘%{count}é …](%{pipeline_failed_jobs_url})"
msgid "ChatMessage|has failed"
-msgstr ""
+msgstr "已失敗"
msgid "ChatMessage|has passed"
-msgstr ""
+msgstr "å·²éŽéŽ"
msgid "ChatMessage|has passed with warnings"
-msgstr ""
+msgstr "å·²éŽéŽä½†æœ‰è­¦å‘Š"
msgid "ChatMessage|in %{duration}"
-msgstr ""
+msgstr "在%{duration}後"
msgid "ChatMessage|in %{project_link}"
-msgstr ""
+msgstr "在%{project_link}中"
msgid "Check again"
-msgstr ""
+msgstr "å†æ¬¡æª¢æŸ¥"
msgid "Check feature availability on namespace plan"
-msgstr ""
+msgstr "檢查命å空間方案的功能å¯ç”¨æ€§"
msgid "Check out branch"
-msgstr ""
+msgstr "簽出分支"
msgid "Check out, review, and merge locally"
-msgstr ""
+msgstr "在本地簽出 (checkout)ã€å¯©é–±å’Œåˆå¹¶"
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 "檢查 %{code_open}elasticsearch.log%{code_close} 文件,debug é·ç§»åœæ­¢çš„原因並在é‡è©¦é·ç§»ä¹‹å‰é€²è¡Œä»»ä½•æ›´æ”¹ï¼Œä¿®å¾©å¤±æ•—原因後,é¸æ“‡ %{strong_open}é‡è©¦é·ç§»%{strong_close},é·ç§»è¨ˆåŠƒåœ¨èƒŒæ™¯é‡è©¦ã€‚"
msgid "Check the current instance configuration "
-msgstr ""
+msgstr "檢查目å‰å¯¦é«”é…ç½® "
msgid "Check with your administrator."
-msgstr ""
+msgstr "請跟您的管ç†å“¡ç¢ºèªã€‚"
msgid "Check your Docker images for known vulnerabilities."
-msgstr ""
+msgstr "檢查您的Docker 映åƒæª”是å¦å­˜åœ¨å·²çŸ¥æ¼æ´žã€‚"
msgid "Check your Kubernetes cluster images for known vulnerabilities."
-msgstr ""
+msgstr "檢查您的Kuberneteså¢é›†æ˜ åƒæª”是å¦å­˜åœ¨å·²çŸ¥æ¼æ´žã€‚"
msgid "Checking %{text} availability…"
-msgstr ""
+msgstr "正在檢查%{text}çš„å¯ç”¨æ€§..."
msgid "Checking approval status"
-msgstr ""
+msgstr "檢查核准狀態"
msgid "Checking branch availability..."
-msgstr ""
+msgstr "正在檢查分支的å¯ç”¨æ€§..."
msgid "Checking group path availability..."
-msgstr ""
+msgstr "正在檢查群組路徑是å¦å¯ç”¨..."
msgid "Checking username availability..."
-msgstr ""
+msgstr "檢查使用者å稱是å¦å¯ç”¨..."
msgid "Checkout"
-msgstr ""
+msgstr "çµå¸³"
msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
-msgstr ""
+msgstr "æ¯10 GB儲存空間æ¯å¹´ %{selectedPlanPrice} 美元"
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
-msgstr ""
+msgstr "æ¯åŒ… 1,000 分é˜ï¼Œ$%{selectedPlanPrice} 美元"
msgid "Checkout|$%{selectedPlanPrice} per user per year"
-msgstr ""
+msgstr "æ¯ä½ä½¿ç”¨è€…æ¯å¹´éœ€è¦ $%{selectedPlanPrice} 美元"
msgid "Checkout|%d CI minute pack"
msgid_plural "Checkout|%d CI minute packs"
-msgstr[0] ""
+msgstr[0] "%d 個 CI 分é˜åŒ…"
msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
-msgstr ""
+msgstr "以%{lastFourDigits}çµå°¾çš„%{cardType} "
msgid "Checkout|%{name}'s CI minutes"
-msgstr ""
+msgstr "%{name}çš„ CI 分é˜"
msgid "Checkout|%{name}'s GitLab subscription"
-msgstr ""
+msgstr "%{name} 的 GitLab 訂閱"
msgid "Checkout|%{name}'s storage subscription"
-msgstr ""
+msgstr "%{name}訂閱的儲存空間"
msgid "Checkout|%{quantity} CI minutes"
-msgstr ""
+msgstr "%{quantity} CI 分é˜"
msgid "Checkout|%{quantity} GB of storage"
-msgstr ""
+msgstr "%{quantity} GB 的儲存空間"
msgid "Checkout|%{quantity} storage pack"
msgid_plural "Checkout|%{quantity} storage packs"
-msgstr[0] ""
+msgstr[0] "%{quantity} 個儲存空間包"
msgid "Checkout|%{selectedPlanText} plan"
-msgstr ""
+msgstr "%{selectedPlanText} 計劃"
msgid "Checkout|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
-msgstr ""
+msgstr "(å¯èƒ½æœƒåœ¨%{linkStart}購買時收費%{linkEnd})"
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 "發生未知錯誤,請é‡æ–°æ•´ç†æ­¤é é¢å†è©¦ã€‚"
msgid "Checkout|Billing address"
-msgstr ""
+msgstr "帳單地å€"
msgid "Checkout|CI minute pack"
-msgstr ""
+msgstr "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 "CI 分é˜åŒ…僅在您使用完訂閱的æ¯æœˆé…é¡å¾Œä½¿ç”¨ã€‚é¡å¤–的分é˜æ•¸å°‡é€æœˆæ»¾å‹•ï¼Œæœ‰æ•ˆæœŸç‚ºä¸€å¹´ã€‚"
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "CI 分é˜"
msgid "Checkout|Calculating your subscription..."
-msgstr ""
+msgstr "正在計算您的訂閱..."
msgid "Checkout|Checkout"
-msgstr ""
+msgstr " çµå¸³"
msgid "Checkout|City"
-msgstr ""
+msgstr "城市"
msgid "Checkout|Confirm purchase"
-msgstr ""
+msgstr "確èªè³¼è²·"
msgid "Checkout|Confirming..."
-msgstr ""
+msgstr "正在確èª..."
msgid "Checkout|Continue to billing"
-msgstr ""
+msgstr "繼續計費"
msgid "Checkout|Continue to payment"
-msgstr ""
+msgstr "繼續付款"
msgid "Checkout|Country"
-msgstr ""
+msgstr "國家"
msgid "Checkout|Create a new group"
-msgstr ""
+msgstr "建立新群組"
msgid "Checkout|Credit card form failed to load. Please try again."
-msgstr ""
+msgstr "信用å¡è¡¨å–®è¼‰å…¥å¤±æ•—,請é‡è©¦ã€‚"
msgid "Checkout|Credit card form failed to load: %{message}"
-msgstr ""
+msgstr "信用å¡è¡¨å–®è¼‰å…¥å¤±æ•—:%{message}"
msgid "Checkout|Edit"
-msgstr ""
+msgstr "編輯"
msgid "Checkout|Enter a number greater than 0"
-msgstr ""
+msgstr "請輸入一個大於0的數字"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
-msgstr ""
+msgstr "有效期至 %{expirationMonth}/%{expirationYear}"
msgid "Checkout|Failed to confirm your order! Please try again."
-msgstr ""
+msgstr "您的訂單確èªå¤±æ•—ï¼è«‹é‡è©¦ã€‚"
msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
-msgstr ""
+msgstr "無法確èªæ‚¨çš„訂單: %{message}。請é‡è©¦ã€‚"
msgid "Checkout|Failed to load countries. Please try again."
-msgstr ""
+msgstr "加載國家失敗。請é‡è©¦ã€‚"
msgid "Checkout|Failed to load states. Please try again."
-msgstr ""
+msgstr "加載州失敗。請é‡è©¦ã€‚"
msgid "Checkout|Failed to load the payment form. Please try again."
-msgstr ""
+msgstr "加載付款表格失敗。請é‡è©¦ã€‚"
msgid "Checkout|Failed to register credit card. Please try again."
-msgstr ""
+msgstr "信用å¡è¨»å†Šå¤±æ•—。請é‡è©¦ã€‚"
msgid "Checkout|GB"
-msgstr ""
+msgstr "GB"
msgid "Checkout|GitLab group"
-msgstr ""
+msgstr "GitLab 群組"
msgid "Checkout|GitLab plan"
-msgstr ""
+msgstr "GitLab 方案"
msgid "Checkout|Group"
-msgstr ""
+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 ""
+msgstr "使用 GitLab çš„å…¬å¸æˆ–組織å稱"
msgid "Checkout|Name: %{errors}"
-msgstr ""
+msgstr "å稱:%{errors}"
msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
-msgstr ""
+msgstr "需è¦æ›´å¤šä½¿ç”¨è€…嗎?請為您的 %{company} 購買 GitLab。"
msgid "Checkout|Number of users"
-msgstr ""
+msgstr "使用者數"
msgid "Checkout|Payment method"
-msgstr ""
+msgstr "付款方å¼"
msgid "Checkout|Please select a country"
-msgstr ""
+msgstr "è«‹é¸æ“‡åœ‹å®¶"
msgid "Checkout|Please select a state"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹å·ž"
msgid "Checkout|Purchase details"
-msgstr ""
+msgstr "購買詳情"
msgid "Checkout|Select"
-msgstr ""
+msgstr "é¸æ“‡"
msgid "Checkout|State"
-msgstr ""
+msgstr "å·ž"
msgid "Checkout|Storage packs"
-msgstr ""
+msgstr "儲存空間 (包)"
msgid "Checkout|Street address"
-msgstr ""
+msgstr "è¡—é“地å€"
msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
-msgstr ""
+msgstr "æ交信用å¡è¡¨æ ¼å¤±æ•—,錯誤碼 %{errorCode}: %{errorMessage}"
msgid "Checkout|Subscription details"
-msgstr ""
+msgstr "訂閱詳細資訊"
msgid "Checkout|Subtotal"
-msgstr ""
+msgstr "å°è¨ˆ"
msgid "Checkout|Success: subscription"
-msgstr ""
+msgstr "æˆåŠŸ: 訂閱"
msgid "Checkout|Tax"
-msgstr ""
+msgstr "稅é¡"
msgid "Checkout|Total"
-msgstr ""
+msgstr "總計"
msgid "Checkout|Total minutes: %{quantity}"
-msgstr ""
+msgstr "總分é˜æ•¸ï¼š %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "總儲存空間: %{quantity} GB"
msgid "Checkout|Users"
-msgstr ""
+msgstr "使用者"
msgid "Checkout|You'll create your new group after checkout"
-msgstr ""
+msgstr "çµå¸³å¾Œæ‚¨å°‡å»ºç«‹æ–°çš„群組"
msgid "Checkout|Your organization"
-msgstr ""
+msgstr "您的組織"
msgid "Checkout|Your storage subscription has the same term as your main subscription, and the price is prorated accordingly."
-msgstr ""
+msgstr "您訂閱的儲存空間與您主è¦è¨‚閱具有相åŒçš„期é™ï¼Œä¸¦ä¸”價格會相應地按比例分é…。"
msgid "Checkout|Your subscription will be applied to this group"
-msgstr ""
+msgstr "您的訂閱將應用於該群組"
msgid "Checkout|Zip code"
-msgstr ""
+msgstr "郵éžå€è™Ÿ"
msgid "Checkout|a storage subscription"
-msgstr ""
+msgstr "訂閱儲存空間"
msgid "Checkout|company or team"
-msgstr ""
+msgstr "å…¬å¸æˆ–團隊"
msgid "Checkout|minutes"
-msgstr ""
+msgstr "分é˜"
msgid "Checkout|x %{quantity} %{units} per pack"
-msgstr ""
+msgstr "x %{quantity} %{units} æ¯åŒ…"
msgid "Checkout|x %{quantity} %{units} per pack ="
-msgstr ""
+msgstr "x %{quantity} %{units} æ¯åŒ… ="
msgid "Cherry-pick this commit"
-msgstr ""
+msgstr "Cherry-pick 該æ交"
msgid "Cherry-pick this merge request"
-msgstr ""
+msgstr "Cherry-pick 該åˆä½µè«‹æ±‚"
msgid "Child"
-msgstr ""
+msgstr "å­ç´š"
msgid "Child epic"
-msgstr ""
+msgstr "å­å²è©©"
msgid "Child epic does not exist."
-msgstr ""
+msgstr "å­å²è©©ä¸å­˜åœ¨ã€‚"
msgid "Child epic doesn't exist."
-msgstr ""
+msgstr "å­å²è©©ä¸å­˜åœ¨ã€‚"
msgid "Child issues and epics"
-msgstr ""
-
-msgid "Children"
-msgstr ""
+msgstr "å­è­°é¡Œèˆ‡å²è©©"
msgid "Chinese language support using"
-msgstr ""
+msgstr "支æŒä½¿ç”¨ä¸­æ–‡"
msgid "Choose File..."
-msgstr ""
+msgstr "é¸æ“‡æ–‡ä»¶..."
msgid "Choose a file"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æ–‡ä»¶"
msgid "Choose a group"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç¾¤çµ„"
msgid "Choose a template"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç¯„本"
msgid "Choose a template..."
-msgstr ""
+msgstr "é¸æ“‡æ¨¡æ¿â€¦"
msgid "Choose a type..."
-msgstr ""
+msgstr "é¸æ“‡é¡žåž‹..."
msgid "Choose any color."
-msgstr ""
+msgstr "é¸æ“‡ä»»ä½•é¡è‰²ã€‚"
msgid "Choose file…"
-msgstr ""
+msgstr "é¸æ“‡æ–‡ä»¶â€¦"
msgid "Choose the preferred Runner and populate the AWS CFT."
-msgstr ""
+msgstr "é¸æ“‡é¦–é¸åŸ·è¡Œå™¨ä¸¦å¡«æ–¼ AWS CFT。"
msgid "Choose the top-level group for your repository imports."
-msgstr ""
+msgstr "é¸æ“‡ç‰ˆæœ¬åº«åŒ¯å…¥çš„頂級群組。"
msgid "Choose visibility level, enable/disable project features and their permissions, disable email notifications, and show default award emoji."
-msgstr ""
+msgstr "é¸æ“‡å¯è¦‹æ€§ç´šåˆ¥ï¼Œå•Ÿç”¨/ç¦ç”¨é …目功能åŠå…¶æ¬Šé™ï¼Œç¦ç”¨é›»å­éƒµä»¶é€šçŸ¥ï¼Œä¸¦é¡¯ç¤ºé è¨­è®šè³žè¡¨æƒ…符號。"
msgid "Choose what content you want to see on a group’s overview page."
-msgstr ""
+msgstr "é¸æ“‡æ‚¨è¦åœ¨ç¾¤çµ„概覽é é¢ä¸Šçœ‹åˆ°çš„內容。"
msgid "Choose which Git strategy to use when fetching the project."
-msgstr ""
+msgstr "é¸æ“‡æŠ“å–專案時è¦ä½¿ç”¨çš„ Git 策略。"
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
-msgstr ""
+msgstr "è«‹é¸æ“‡è¦é€£æŽ¥ä¸¦åŸ·è¡Œ CI/CD æµæ°´ç·šçš„程å¼ç¢¼ç‰ˆæœ¬åº«ã€‚"
msgid "Choose your framework"
-msgstr ""
+msgstr "é¸æ“‡æ‚¨çš„框架"
msgid "CiCdAnalytics|Date range: %{range}"
-msgstr ""
+msgstr "日期範åœï¼š%{range}"
msgid "CiStatusLabel|canceled"
-msgstr ""
+msgstr "å·²å–消"
msgid "CiStatusLabel|created"
-msgstr ""
+msgstr "已建立"
msgid "CiStatusLabel|delayed"
-msgstr ""
+msgstr "已延é²"
msgid "CiStatusLabel|failed"
-msgstr ""
+msgstr "已失敗"
msgid "CiStatusLabel|manual action"
-msgstr ""
+msgstr "手動æ“作"
msgid "CiStatusLabel|passed"
-msgstr ""
+msgstr "已通éŽ"
msgid "CiStatusLabel|passed with warnings"
-msgstr ""
+msgstr "已通éŽä½†æœ‰è­¦å‘Š"
msgid "CiStatusLabel|pending"
-msgstr ""
+msgstr "等待中"
msgid "CiStatusLabel|preparing"
-msgstr ""
+msgstr "準備"
msgid "CiStatusLabel|skipped"
-msgstr ""
+msgstr "已跳éŽ"
msgid "CiStatusLabel|waiting for delayed job"
-msgstr ""
+msgstr "等待已延é²çš„作業"
msgid "CiStatusLabel|waiting for manual action"
-msgstr ""
+msgstr "等待手動æ“作"
msgid "CiStatusLabel|waiting for resource"
-msgstr ""
+msgstr "等待資æº"
msgid "CiStatusText|blocked"
-msgstr ""
+msgstr "已阻塞"
msgid "CiStatusText|canceled"
-msgstr ""
+msgstr "å·²å–消"
msgid "CiStatusText|created"
-msgstr ""
+msgstr "已建立"
msgid "CiStatusText|delayed"
-msgstr ""
+msgstr "已延é²"
msgid "CiStatusText|failed"
-msgstr ""
+msgstr "已失敗"
msgid "CiStatusText|manual"
-msgstr ""
+msgstr "手動æ“作"
msgid "CiStatusText|passed"
-msgstr ""
+msgstr "已通éŽ"
msgid "CiStatusText|pending"
-msgstr ""
+msgstr "等待中"
msgid "CiStatusText|preparing"
-msgstr ""
+msgstr "準備"
msgid "CiStatusText|skipped"
-msgstr ""
+msgstr "已跳éŽ"
msgid "CiStatusText|waiting"
-msgstr ""
+msgstr "等待"
msgid "CiStatus|running"
-msgstr ""
+msgstr "執行中"
msgid "CiVariables|Cannot use Masked Variable with current value"
-msgstr ""
+msgstr "ç›®å‰æ•¸å€¼ç„¡æ³•ä½¿ç”¨è®Šæ•¸é®ç½©"
msgid "CiVariables|Environments"
-msgstr ""
+msgstr "Ci變數|環境"
msgid "CiVariables|Input variable key"
-msgstr ""
+msgstr "Ci變數|輸入變數的å稱"
msgid "CiVariables|Input variable value"
-msgstr ""
+msgstr "Ci變數|輸入變數的值"
msgid "CiVariables|Key"
-msgstr ""
+msgstr "Ci變數|éµ"
msgid "CiVariables|Masked"
-msgstr ""
+msgstr "Ci變數|é®ç½©"
msgid "CiVariables|Protected"
-msgstr ""
+msgstr "Ci變數|å—ä¿è­·"
msgid "CiVariables|Remove variable"
-msgstr ""
+msgstr "Ci變數|移除變數"
msgid "CiVariables|Remove variable row"
-msgstr ""
+msgstr "Ci變數|移除變數行"
msgid "CiVariables|Scope"
-msgstr ""
+msgstr "Ci變數|範åœ"
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 ""
+msgstr "Ci變數|指定è¦åœ¨æ­¤åŸ·è¡Œä¸­ä½¿ç”¨çš„變數值。%{linkStart}CI/CD設定%{linkEnd}中指定的值將用作é è¨­å€¼"
msgid "CiVariables|State"
-msgstr ""
+msgstr "Ci變數|狀態"
msgid "CiVariables|Type"
-msgstr ""
+msgstr "Ci變數|類型"
msgid "CiVariables|Value"
-msgstr ""
+msgstr "Ci變數|值"
msgid "CiVariables|Variables"
-msgstr ""
+msgstr "Ci變數|變數"
msgid "CiVariable|* (All environments)"
-msgstr ""
+msgstr "Ci變數|* (所有環境)"
msgid "CiVariable|All environments"
-msgstr ""
+msgstr "Ci變數|所有環境"
msgid "CiVariable|Create wildcard"
-msgstr ""
+msgstr "Ci變數|建立è¬ç”¨å­—å…ƒ"
msgid "CiVariable|New environment"
-msgstr ""
+msgstr "Ci變數|建立新環境"
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "Ci變數|æœå°‹ç’°å¢ƒ"
msgid "Classification Label (optional)"
-msgstr ""
+msgstr "分類標籤(å¯é¸)"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
-msgstr ""
+msgstr "ä¸å¯ç”¨: %{reason}"
msgid "Clean up after running %{link_start}git filter-repo%{link_end} on the repository."
-msgstr ""
+msgstr "在儲存庫上é‹è¡Œ %{link_start}git filter-repo%{link_end} 後進行清ç†ã€‚"
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 "清ç†ç­–略由背景worker執行。此設置定義了å¯ä»¥åŒæ™‚é‹è¡Œçš„最大worker數。將其設置為 0 以刪除所有worker,並且ä¸åŸ·è¡Œæ¸…ç†ç­–略。"
msgid "Cleanup policy maximum number of tags to be deleted"
-msgstr ""
+msgstr "清ç†ç­–ç•¥è¦åˆªé™¤çš„最大標籤數"
msgid "Cleanup policy maximum processing time (seconds)"
-msgstr ""
+msgstr "清ç†ç­–略最大處ç†æ™‚é–“(秒)"
msgid "Cleanup policy maximum workers running concurrently"
-msgstr ""
+msgstr "清ç†ç­–略最大åŒæ™‚é‹è¡Œçš„worker數é‡"
msgid "Clear"
-msgstr ""
+msgstr "清除"
msgid "Clear %{count} image from cache?"
msgid_plural "Clear %{count} images from cache?"
-msgstr[0] ""
+msgstr[0] "從快å–緩存中清除%{count}個映åƒæª”?"
msgid "Clear all repository checks"
-msgstr ""
+msgstr "清除所有版本庫檢查"
msgid "Clear chart filters"
-msgstr ""
+msgstr "清除圖表éŽæ¿¾å™¨"
msgid "Clear due date"
-msgstr ""
+msgstr "清除截止日"
msgid "Clear health status"
-msgstr ""
+msgstr "清除å¥åº·ç‹€æ…‹"
msgid "Clear recent searches"
-msgstr ""
+msgstr "清除最近的æœå°‹"
msgid "Clear repository checks"
-msgstr ""
+msgstr "清除版本庫檢查"
msgid "Clear search"
msgstr "清除æœå°‹"
msgid "Clear search input"
-msgstr ""
+msgstr "清除æœå°‹è¼¸å…¥"
msgid "Clear start date"
-msgstr ""
+msgstr "清除起始日"
msgid "Clear templates search input"
-msgstr ""
+msgstr "清除範本æœå°‹è¼¸å…¥"
msgid "Clear this checkbox to use a personal access token instead."
-msgstr ""
+msgstr "清除此勾é¸æ¡†ä»¥æ”¹ç”¨å€‹äººå­˜å–憑證 (access token)。"
msgid "Clear this checkbox to use a personal access token or LDAP password instead."
-msgstr ""
+msgstr "清除此勾é¸æ¡†ï¼Œä½¿ç”¨å€‹äººè¨ªå•ä»¤ç‰Œ(權æ–)或 LDAP 密碼代替。"
msgid "Clear this checkbox to use an external authentication provider instead."
-msgstr ""
+msgstr "清除此勾é¸æ¡†ï¼Œä½¿ç”¨å¤–部身份驗證代替。"
msgid "Clear weight"
-msgstr ""
+msgstr "清除權é‡"
msgid "Cleared health status."
-msgstr ""
+msgstr "å¥åº·ç‹€æ…‹å·²æ¸…除。"
msgid "Cleared weight."
-msgstr ""
+msgstr "å·²é‡è¨­çš„權é‡"
msgid "Clears health status."
-msgstr ""
+msgstr "清除å¥åº·ç‹€æ…‹ã€‚"
msgid "Clears weight."
-msgstr ""
+msgstr "清除權é‡"
msgid "Click %{link_start}here%{link_end} to view the request."
-msgstr ""
+msgstr "點擊%{link_start}此處%{link_end}檢視請求。"
msgid "Click %{link_to} to view the request."
-msgstr ""
+msgstr "點擊%{link_to}檢視請求。"
msgid "Click the link below to confirm your email address (%{email})"
-msgstr ""
+msgstr "點擊下方連çµä»¥é©—證您的信箱 %{email}"
msgid "Click the link below to confirm your email address."
-msgstr ""
+msgstr "點擊下方連çµä»¥é©—證您的信箱。"
msgid "Click to expand it."
-msgstr ""
+msgstr "點擊以展開。"
msgid "Click to expand text"
-msgstr ""
+msgstr "點擊展開文字"
msgid "Click to hide"
-msgstr ""
+msgstr "點擊以隱è—"
msgid "Click to reveal"
-msgstr ""
+msgstr "點擊以顯示"
msgid "Client request timeout"
-msgstr ""
+msgstr "客戶端請求超時"
msgid "Clients"
-msgstr ""
+msgstr "客戶端"
msgid "Clientside DSN"
-msgstr ""
+msgstr "客戶端 DSN"
msgid "Clone"
-msgstr ""
+msgstr "複製"
msgid "Clone repository"
-msgstr ""
+msgstr "複製版本庫"
msgid "Clone this issue"
-msgstr ""
+msgstr "複製該議題"
msgid "Clone with %{http_label}"
-msgstr ""
+msgstr "使用 %{http_label} 複製"
msgid "Clone with %{protocol}"
-msgstr ""
+msgstr "使用 %{protocol} 克隆"
msgid "Clone with KRB5"
-msgstr ""
+msgstr "以 KRB5 複製"
msgid "Clone with SSH"
-msgstr ""
+msgstr "以 SSH 複製"
msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
-msgstr ""
+msgstr "CloneIssue|由於權é™ä¸è¶³ï¼Œç„¡æ³•è¤‡è£½ç‰ˆæœ¬åº«è­°é¡Œ (issue)ï¼"
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
-msgstr ""
+msgstr "CloneIssue|無法將議題(issue)複製到目標專案,因為正在等待刪除。"
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
-msgstr ""
+msgstr "CloneIssue|無法複製“%{issue_type}â€é¡žåž‹çš„議題。"
msgid "Cloned this issue to %{path_to_project}."
-msgstr ""
+msgstr "將此議題(issue)複製到%{path_to_project}。"
msgid "Clones this issue, without comments, to %{project}."
-msgstr ""
+msgstr "將此議題(issue)複製到 %{project},ä¸å«è©•è«–/留言。"
msgid "Close"
-msgstr ""
+msgstr "關閉"
msgid "Close %{issueType}"
-msgstr ""
+msgstr "關閉%{issueType}"
msgid "Close %{noteable}"
-msgstr ""
+msgstr "關閉%{noteable}"
msgid "Close %{tabname}"
-msgstr ""
+msgstr "關閉%{tabname}"
msgid "Close design"
-msgstr ""
+msgstr "關閉設計"
msgid "Close epic"
-msgstr ""
+msgstr "關閉å²è©©"
msgid "Close milestone"
-msgstr ""
+msgstr "關閉里程碑"
msgid "Close sidebar"
-msgstr ""
+msgstr "關閉å´é‚Šæ¬„"
msgid "Close this %{quick_action_target}"
-msgstr ""
+msgstr "關閉此%{quick_action_target}"
msgid "Closed"
-msgstr ""
+msgstr "已關閉"
msgid "Closed %{epicTimeagoDate}"
-msgstr ""
+msgstr "已關閉 %{epicTimeagoDate}"
msgid "Closed MRs"
-msgstr ""
+msgstr "已關閉的åˆä½µè«‹æ±‚"
msgid "Closed date"
-msgstr ""
+msgstr "關閉日期"
msgid "Closed issues"
-msgstr ""
+msgstr "已關閉的議題"
msgid "Closed this %{quick_action_target}."
-msgstr ""
+msgstr "已關閉此%{quick_action_target}."
msgid "Closed: %{closed}"
-msgstr ""
+msgstr "已關閉: %{closed}"
msgid "Closes this %{quick_action_target}."
-msgstr ""
+msgstr "關閉此%{quick_action_target}."
msgid "Cloud Run"
-msgstr ""
+msgstr "雲端執行"
msgid "Cloud Storage"
-msgstr ""
+msgstr "雲端儲存"
msgid "CloudSeed|All"
-msgstr ""
+msgstr "全部"
msgid "CloudSeed|AlloyDB for Postgres"
-msgstr ""
+msgstr "AlloyDB for Postgres"
msgid "CloudSeed|Available database services through which instances may be created"
-msgstr ""
+msgstr "通éŽå‰µå»ºå¯¦ä¾‹ä¾†æä¾›å¯ç”¨çš„資料庫æœå‹™"
msgid "CloudSeed|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "CloudSeed|Cloud Firestore"
-msgstr ""
+msgstr "Cloud Firestore"
msgid "CloudSeed|Cloud SQL for MySQL"
-msgstr ""
+msgstr "Cloud SQL for MySQL"
msgid "CloudSeed|Cloud SQL for Postgres"
-msgstr ""
+msgstr "Cloud SQL for Postgres"
msgid "CloudSeed|Cloud SQL for SQL Server"
-msgstr ""
+msgstr "é©ç”¨æ–¼ SQL Server çš„ Cloud SQL"
msgid "CloudSeed|CloudSQL Instance"
-msgstr ""
+msgstr "CloudSQL 實例"
+
+msgid "CloudSeed|Configuration"
+msgstr "é…ç½®"
msgid "CloudSeed|Create cluster"
-msgstr ""
+msgstr "建立å¢é›†"
msgid "CloudSeed|Create database"
-msgstr ""
+msgstr "建立資料庫"
msgid "CloudSeed|Create instance"
-msgstr ""
+msgstr "建立實例"
msgid "CloudSeed|Database instance is generated within the selected Google Cloud project"
-msgstr ""
+msgstr "資料庫實例已在é¸å®šçš„ Google Cloud 專案中建立完æˆ"
msgid "CloudSeed|Database instances associated with this project"
-msgstr ""
+msgstr "與該專案關è¯çš„資料庫實例"
msgid "CloudSeed|Database version"
-msgstr ""
+msgstr "資料庫版本"
+
+msgid "CloudSeed|Databases"
+msgstr "資料庫"
+
+msgid "CloudSeed|Deployments"
+msgstr "部署"
msgid "CloudSeed|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "CloudSeed|Determines memory and virtual cores available to your instance"
-msgstr ""
+msgstr "CloudSeed|確定您實例的å¯ç”¨å…§å­˜èˆ‡è™›æ“¬æ ¸å¿ƒ"
msgid "CloudSeed|Enhance security by storing database variables in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "將資料庫變數儲存在 secret 管ç†ä¸­ä¾†å¢žå¼·å®‰å…¨æ€§ - 瞭解更多關於 %{docLinkStart}使用 GitLab 進行 secret 管ç†%{docLinkEnd}"
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 Project"
-msgstr ""
+msgstr "Google Cloud 專案"
msgid "CloudSeed|Google Cloud project"
-msgstr ""
+msgstr "Google Cloud 專案"
msgid "CloudSeed|I accept Google Cloud pricing and responsibilities involved with managing database instances"
-msgstr ""
+msgstr "我接å—與管ç†è³‡æ–™åº«å¯¦ä¾‹æœ‰é—œçš„ Google Cloud 定價和責任"
msgid "CloudSeed|Instances"
-msgstr ""
+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 ""
+msgstr "無實例"
msgid "CloudSeed|Refs"
-msgstr ""
+msgstr "Refs"
+
+msgid "CloudSeed|Regions"
+msgstr "å€åŸŸ"
msgid "CloudSeed|Scalable, secure, and highly available in-memory service for Redis"
-msgstr ""
+msgstr "é©ç”¨æ–¼ Redis çš„å¯æ“´å±•ã€å®‰å…¨ä¸”高å¯ç”¨çš„記憶體存å–æœå‹™"
msgid "CloudSeed|Service"
-msgstr ""
+msgstr "æœå‹™"
+
+msgid "CloudSeed|Service Account"
+msgstr "æœå‹™å¸³è™Ÿ"
msgid "CloudSeed|Services"
-msgstr ""
+msgstr "æœå‹™"
msgid "CloudSeed|There are no instances to display."
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„實例。"
msgid "CloudSeed|Version"
-msgstr ""
+msgstr "版本"
msgid "Cluster"
-msgstr ""
+msgstr "å¢é›†"
msgid "Cluster Health"
-msgstr ""
+msgstr "å¢é›†å¥åº·"
msgid "Cluster cache cleared."
-msgstr ""
+msgstr "å¢é›†å¿«å–已清除。"
msgid "Cluster is required for Stages::ClusterEndpointInserter"
-msgstr ""
+msgstr "Stages::ClusterEndpointInserter需è¦å¢é›†"
msgid "Cluster level"
-msgstr ""
+msgstr "å¢é›†ç´šåˆ¥"
msgid "Cluster type must be specified for Stages::ClusterEndpointInserter"
-msgstr ""
+msgstr "必須為 Stages::ClusterEndpointInserter 指定å¢é›†é¡žåž‹"
msgid "ClusterAgents|%{linkStart}View the documentation%{linkEnd} for advanced installation. Ensure you have your access token available."
-msgstr ""
+msgstr "%{linkStart}查看高級安è£æ–‡æª”%{linkEnd} 。請確ä¿æ‚¨æœ‰å¯ç”¨çš„訪å•ä»¤ç‰Œã€‚"
msgid "ClusterAgents|%{name} successfully deleted"
-msgstr ""
+msgstr "%{name} å·²æˆåŠŸåˆªé™¤"
msgid "ClusterAgents|%{name} successfully revoked"
-msgstr ""
+msgstr "%{name} å·²æˆåŠŸæ’¤éŠ·"
msgid "ClusterAgents|%{number} of %{total} agents"
-msgstr ""
+msgstr "å…± %{total} 個代ç†ä¸­çš„ %{number} 個"
msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
-msgstr ""
+msgstr "%{total}個å¢é›†ä¸­çš„%{number}個通éŽå¢é›†è­‰æ›¸é€£æŽ¥"
msgid "ClusterAgents|%{titleIcon}Connected"
-msgstr ""
+msgstr "%{titleIcon}已連接"
msgid "ClusterAgents|%{titleIcon}Not connected"
-msgstr ""
+msgstr "%{titleIcon}未連接"
msgid "ClusterAgents|%{tokenName} created"
-msgstr ""
+msgstr "%{tokenName} 已創建"
msgid "ClusterAgents|%{tokenName} revoked"
-msgstr ""
+msgstr "%{tokenName} 已撤銷"
msgid "ClusterAgents|Access tokens"
-msgstr ""
+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 ""
+msgstr "添加代ç†é…置文件到 %{linkStart}此版本庫%{linkEnd} 並é¸æ“‡å®ƒï¼Œæˆ–創建一個新的é…置文件在 GitLab 註冊:"
msgid "ClusterAgents|Advanced installation methods"
-msgstr ""
+msgstr "ClusterAgents|進階安è£æ–¹æ³•"
msgid "ClusterAgents|Agent"
-msgstr ""
+msgstr "ClusterAgents|代ç†"
msgid "ClusterAgents|Agent %{strongStart}connected%{strongEnd}"
-msgstr ""
+msgstr "ClusterAgents|ä»£ç† %{strongStart}已連線%{strongEnd}"
msgid "ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}"
-msgstr ""
+msgstr "ClusterAgents|ä»£ç† %{strongStart}已中斷連線%{strongEnd}"
msgid "ClusterAgents|Agent access token:"
-msgstr ""
+msgstr "ClusterAgents|代ç†å­˜å–令牌(權æ–):"
msgid "ClusterAgents|Agent might not be connected to GitLab"
-msgstr ""
+msgstr "ClusterAgents|代ç†å¯èƒ½æœªé€£ç·šåˆ° GitLab"
msgid "ClusterAgents|Agent never connected to GitLab"
-msgstr ""
+msgstr "ClusterAgents|代ç†å¾žæœªé€£ç·šåˆ° GitLab"
msgid "ClusterAgents|Agent version mismatch"
-msgstr ""
+msgstr "ClusterAgents|代ç†ç‰ˆæœ¬ä¸åŒ¹é…"
msgid "ClusterAgents|Agent version mismatch and update"
-msgstr ""
+msgstr "ClusterAgents|代ç†ç‰ˆæœ¬ä¸åŒ¹é…和更新"
msgid "ClusterAgents|Agent version update required"
-msgstr ""
+msgstr "ClusterAgents|需è¦æ›´æ–°ä»£ç†ç‰ˆæœ¬"
msgid "ClusterAgents|All"
-msgstr ""
+msgstr "ClusterAgents|全部"
msgid "ClusterAgents|An error occurred while loading your agent"
-msgstr ""
+msgstr "ClusterAgents|載入代ç†æ™‚發生錯誤"
msgid "ClusterAgents|An error occurred while loading your agents"
-msgstr ""
+msgstr "ClusterAgents|載入代ç†æ™‚發生錯誤"
msgid "ClusterAgents|An error occurred while retrieving agent activity. Reload the page to try again."
-msgstr ""
+msgstr "å–得代ç†æ´»å‹•æ™‚發生錯誤,é‡æ–°è¼‰å…¥é é¢é‡è©¦ã€‚"
msgid "ClusterAgents|An unknown error occurred. Please try again."
-msgstr ""
+msgstr "ClusterAgents|發生未知錯誤。請é‡è©¦ã€‚"
msgid "ClusterAgents|Are you sure you want to delete this agent? You cannot undo this."
-msgstr ""
+msgstr "ClusterAgents|您確定è¦åˆªé™¤æ­¤ä»£ç†å—Žï¼Ÿæ‚¨ç„¡æ³•æ’¤æ¶ˆæ­¤æ“作。"
msgid "ClusterAgents|Are you sure you want to revoke this token? You cannot undo this action."
-msgstr ""
+msgstr "ClusterAgents|您確定è¦æ’¤éŠ·è©²ä»¤ç‰Œ(權æ–)å—Ž? 該動作無法回復。"
msgid "ClusterAgents|Certificate"
-msgstr ""
+msgstr "ClusterAgents|憑證"
msgid "ClusterAgents|Configuration"
-msgstr ""
+msgstr "ClusterAgents|組態"
msgid "ClusterAgents|Connect a Kubernetes cluster"
-msgstr ""
+msgstr "ClusterAgents|連線 Kubernetes å¢é›†"
msgid "ClusterAgents|Connect a cluster"
-msgstr ""
+msgstr "ClusterAgents|連線å¢é›†"
msgid "ClusterAgents|Connect a cluster (agent)"
-msgstr ""
+msgstr "ClusterAgents|連線å¢é›†ï¼ˆä»£ç†ï¼‰"
msgid "ClusterAgents|Connect a cluster (certificate - deprecated)"
-msgstr ""
+msgstr "ClusterAgents|連線å¢é›†ï¼ˆæ†‘è­‰ - 已棄用)"
msgid "ClusterAgents|Connect a cluster (deprecated)"
-msgstr ""
+msgstr "ClusterAgents|連線å¢é›†ï¼ˆå·²æ£„用)"
msgid "ClusterAgents|Connected"
-msgstr ""
+msgstr "ClusterAgents|已連線"
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "ClusterAgents|連線狀態"
msgid "ClusterAgents|Copy command"
-msgstr ""
+msgstr "ClusterAgents|複製命令"
msgid "ClusterAgents|Copy token"
-msgstr ""
+msgstr "ClusterAgents|複製令牌(權æ–)"
msgid "ClusterAgents|Create a cluster"
-msgstr ""
+msgstr "ClusterAgents|建立å¢é›†"
msgid "ClusterAgents|Create agent access token"
-msgstr ""
+msgstr "ClusterAgents|建立代ç†å­˜å–令牌(權æ–) (access token):"
msgid "ClusterAgents|Create agent: %{searchTerm}"
-msgstr ""
+msgstr "ClusterAgents|建立代ç†ï¼š %{searchTerm}"
msgid "ClusterAgents|Create token"
-msgstr ""
+msgstr "ClusterAgents|建立令牌(權æ–)"
msgid "ClusterAgents|Created by"
-msgstr ""
+msgstr "ClusterAgents|建立者"
msgid "ClusterAgents|Created by %{name} %{time}"
-msgstr ""
+msgstr "ClusterAgents|建立者 %{name} %{time}"
msgid "ClusterAgents|Date created"
-msgstr ""
+msgstr "ClusterAgents|建立日期"
msgid "ClusterAgents|Default configuration"
-msgstr ""
+msgstr "ClusterAgents|é è¨­é…ç½®"
msgid "ClusterAgents|Delete"
-msgstr ""
+msgstr "刪除"
msgid "ClusterAgents|Delete agent"
-msgstr ""
+msgstr "刪除代ç†"
msgid "ClusterAgents|Deprecated"
-msgstr ""
+msgstr "已棄用"
msgid "ClusterAgents|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "ClusterAgents|Event occurred"
-msgstr ""
+msgstr "已發生的事件"
msgid "ClusterAgents|Failed to create a token"
-msgstr ""
+msgstr "ClusterAgents|建立令牌(權æ–)失敗"
msgid "ClusterAgents|Failed to register an agent"
-msgstr ""
+msgstr "ClusterAgents|註冊代ç†å¤±æ•—"
msgid "ClusterAgents|From a terminal, connect to your cluster and run this command. The token is included in the command."
-msgstr ""
+msgstr "從終端連接到您的å¢é›†ä¸¦é‹è¡Œæ­¤å‘½ä»¤ï¼Œä»¤ç‰Œ(權æ–)包å«åœ¨å‘½ä»¤ä¸­ã€‚"
msgid "ClusterAgents|GitLab agent"
-msgstr ""
+msgstr "GitLab 代ç†"
msgid "ClusterAgents|GitLab agent for Kubernetes"
-msgstr ""
+msgstr "é©ç”¨æ–¼ Kubernetes çš„ GitLab 代ç†"
msgid "ClusterAgents|Give feedback"
-msgstr ""
+msgstr "ClusterAgents|æä¾›å饋"
msgid "ClusterAgents|How do I register an agent?"
-msgstr ""
+msgstr "ClusterAgents|如何註冊代ç†ï¼Ÿ"
msgid "ClusterAgents|How to update an agent?"
-msgstr ""
+msgstr "ClusterAgents|如何更新代ç†ï¼Ÿ"
msgid "ClusterAgents|Install using Helm (recommended)"
-msgstr ""
+msgstr "使用 Helm (建議) 進行安è£"
msgid "ClusterAgents|Last connected %{timeAgo}."
-msgstr ""
+msgstr "上次已在 %{timeAgo} 連接。"
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "最後一次è¯ç¹«"
msgid "ClusterAgents|Learn how to troubleshoot"
-msgstr ""
+msgstr "ClusterAgents|了解如何進行除錯"
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "ClusterAgents|確èªæ‚¨ä½¿ç”¨çš„是有效的令牌(權æ–)。"
msgid "ClusterAgents|Name"
-msgstr ""
+msgstr "ClusterAgents|å稱"
msgid "ClusterAgents|Never"
-msgstr ""
+msgstr "ClusterAgents|從ä¸"
msgid "ClusterAgents|Never connected"
-msgstr ""
+msgstr "ClusterAgents|從未連線"
msgid "ClusterAgents|No activity occurred in the past day"
msgid_plural "ClusterAgents|No activity occurred in the past %d days"
-msgstr[0] ""
+msgstr[0] "ClusterAgents|éŽåŽ»%d天內未發生任何活動"
msgid "ClusterAgents|No agents"
-msgstr ""
+msgstr "ClusterAgents|無代ç†äºº"
msgid "ClusterAgents|No clusters connected through cluster certificates"
-msgstr ""
+msgstr "沒有通éŽå¢é›†è­‰æ›¸é€£æŽ¥çš„å¢é›†"
msgid "ClusterAgents|Not connected"
-msgstr ""
+msgstr "ClusterAgents|未連線"
msgid "ClusterAgents|Recommended"
-msgstr ""
+msgstr "ClusterAgents|建議"
msgid "ClusterAgents|Register"
-msgstr ""
+msgstr "ClusterAgents|註冊"
msgid "ClusterAgents|Registering agent"
-msgstr ""
+msgstr "ClusterAgents|註冊代ç†äºº"
msgid "ClusterAgents|Requires a Maintainer or greater role to delete agents"
-msgstr ""
+msgstr "ClusterAgents|需è¦ç¶­è­·è€…或更高層的人æ‰èƒ½åˆªé™¤ä»£ç†äºº"
msgid "ClusterAgents|Requires a Maintainer or greater role to perform these actions"
-msgstr ""
+msgstr "ClusterAgents|需è¦ç¶­è­·è€…或更高層的人æ‰èƒ½åŸ·è¡Œé€™äº›æ“作"
msgid "ClusterAgents|Requires a Maintainer or greater role to perform this action"
-msgstr ""
+msgstr "ClusterAgents|需è¦ç¶­è­·è€…或更高權é™è§’色的人æ‰èƒ½åŸ·è¡Œè©²å‹•ä½œ"
msgid "ClusterAgents|Revoke access token?"
-msgstr ""
+msgstr "ClusterAgents|撤銷存å–令牌(權æ–)?"
msgid "ClusterAgents|Revoke token"
-msgstr ""
+msgstr "ClusterAgents|撤銷令牌(權æ–)"
msgid "ClusterAgents|Security"
-msgstr ""
+msgstr "ClusterAgents|安全性"
msgid "ClusterAgents|See agent activity updates, like tokens created or revoked and clusters connected or not connected."
-msgstr ""
+msgstr "查看代ç†æ´»å‹•æ›´æ–°ï¼Œä¾‹å¦‚創建或撤銷的令牌(權æ–),以åŠé€£æŽ¥æˆ–未連接的å¢é›†ã€‚"
msgid "ClusterAgents|Select an agent or enter a name to create new"
-msgstr ""
+msgstr "ClusterAgents|é¸æ“‡ä¸€å€‹ä»£ç†äººæˆ–輸入一個å稱來建立新的"
msgid "ClusterAgents|Tell us what you think"
-msgstr ""
+msgstr "ClusterAgents|告訴我們您的想法"
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 "當將 Kubernetes å¢é›†é€£æŽ¥åˆ° GitLab 時,GitLab 代ç†æ供更高級別的安全性。 %{linkStart}瞭解有關 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 "該代ç†å¾ˆé•·æ™‚間沒有連接,å¯èƒ½å­˜åœ¨é€£æŽ¥å•é¡Œã€‚最後一次è¯ç¹«æ˜¯ %{timeAgo}。"
msgid "ClusterAgents|The agent uses the token to connect with GitLab."
-msgstr ""
+msgstr "代ç†ä½¿ç”¨ä»¤ç‰Œé€£æŽ¥åˆ° 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 "該代ç†ç‰ˆæœ¬åœ¨å¢é›†çš„ pod 中彼此ä¸åŒ¹é…。 當剛剛部署了新的代ç†ç‰ˆæœ¬ï¼Œè€Œ Kubernetes 正在關閉舊的 Pod 時,å¯èƒ½æœƒç™¼ç”Ÿé€™ç¨®æƒ…æ³ã€‚"
msgid "ClusterAgents|This agent has no tokens"
-msgstr ""
+msgstr "ClusterAgents|此代ç†äººæ²’有令牌(權æ–)"
msgid "ClusterAgents|To delete the agent, type %{name} to confirm:"
-msgstr ""
+msgstr "ClusterAgents|è¦åˆªé™¤ä»£ç†äººï¼Œè«‹éµå…¥ %{name} 進行確èªï¼š"
msgid "ClusterAgents|To revoke the token, type %{name} to confirm:"
-msgstr ""
+msgstr "è¦æ’¤å›žæ†‘證,請輸入 %{name} 進行確èªï¼š"
msgid "ClusterAgents|Token created by %{userName}"
-msgstr ""
+msgstr "ClusterAgents|ç”± %{userName}建立的令牌(權æ–)"
msgid "ClusterAgents|Token revoked by %{userName}"
-msgstr ""
+msgstr "ClusterAgents|令牌(權æ–)被 %{userName} 撤回"
msgid "ClusterAgents|Unknown user"
-msgstr ""
+msgstr "ClusterAgents|未知使用者"
msgid "ClusterAgents|View all %{number} agents"
-msgstr ""
+msgstr "ClusterAgent|檢視全部 %{number} 個代ç†äºº"
msgid "ClusterAgents|View all %{number} clusters"
-msgstr ""
+msgstr "ClusterAgents|檢視全部 %{number} 個å¢é›†"
msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
-msgstr ""
+msgstr "ClusterAgents|我們很想了解更多關於您使用 GitLab 代ç†çš„體驗。"
msgid "ClusterAgents|What is agent activity?"
-msgstr ""
+msgstr "ClusterAgents|什麼是 GitLab 代ç†æ´»å‹•ï¼Ÿ"
msgid "ClusterAgents|What is default configuration?"
-msgstr ""
+msgstr "ClusterAgents|什麼是é è¨­é…置?"
msgid "ClusterAgents|You cannot see this token again after you close this window."
-msgstr ""
+msgstr "ClusterAgents|關閉此視窗後,您將無法å†æ¬¡çœ‹åˆ°æ­¤ä»¤ç‰Œ(權æ–)。"
msgid "ClusterAgents|You will need to create a token to connect to your agent"
-msgstr ""
+msgstr "ClusterAgents|您需è¦å»ºç«‹ä¸€å€‹ä»¤ç‰Œ(權æ–)來連接您的代ç†"
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 "ClusterAgents|您的代ç†ç‰ˆæœ¬èˆ‡æ‚¨çš„ GitLab 版本 (v%{version}) ä¸åŒæ­¥ï¼Œé€™å¯èƒ½æœƒå°Žè‡´ç›¸å®¹æ€§å•é¡Œã€‚å°‡å¢é›†ä¸Šå®‰è£çš„代ç†æ›´æ–°åˆ°æœ€æ–°ç‰ˆæœ¬ã€‚"
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 "您的實例沒有設置 %{linkStart}GitLab 代ç†æœå‹™å™¨ (KAS)%{linkEnd} 。è¦æ±‚ GitLab 管ç†å“¡å®‰è£å®ƒã€‚"
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
-msgstr ""
+msgstr "ClusterAgent|使用者權é™ä¸è¶³ï¼Œç„¡æ³•ç‚ºæ­¤å°ˆæ¡ˆå»ºç«‹ä»¤ç‰Œ(權æ–)"
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
-msgstr ""
+msgstr "ClusterAgent|您的權é™ä¸è¶³ï¼Œç„¡æ³•ç‚ºæ­¤å°ˆæ¡ˆå»ºç«‹å¢é›†ä»£ç†"
msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
-msgstr ""
+msgstr "您的權é™ä¸è¶³ï¼Œç„¡æ³•ç‚ºæ­¤é …目刪除å¢é›†ä»£ç†"
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
-msgstr ""
+msgstr "å¢é›†ç®¡ç†é …ç›®å¯ä»¥ä½¿ç”¨Kubernetes%{code_open}cluster-admin%{code_close}權é™ä¾†é‹è¡Œéƒ¨ç½²ä½œæ¥­ã€‚"
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
-msgstr ""
+msgstr "在%{code}kube-system%{end_code}具有%{code}cluster-admin%{end_code}權é™çš„æœå‹™ä»¤ç‰Œ(權æ–)"
msgid "ClusterIntegration|API URL"
-msgstr ""
+msgstr "API地å€"
msgid "ClusterIntegration|API URL should be a valid http/https url."
-msgstr ""
+msgstr "API URL應該是有效的 http/https URL。"
msgid "ClusterIntegration|Add Kubernetes cluster"
-msgstr ""
+msgstr "加入 Kubernetes å¢é›†"
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 ""
+msgstr "å°‡Kuberneteså¢é›†åŠ å…¥åˆ°ç¾¤çµ„後,群組中的所有項目都將共享該å¢é›†ã€‚您å¯ä»¥åœ¨åŒä¸€å¢é›†ä¸Šä½¿ç”¨è©•å¯©æ‡‰ç”¨ç¨‹å¼ã€éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ä»¥åŠåŸ·è¡Œå¢é›†ä¸­æ‰€æœ‰é …目的æµæ°´ç·šã€‚"
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 ""
+msgstr "加入Kuberneteså¢é›†å°‡è‡ªå‹•åœ¨æ‰€æœ‰é …目中共享å¢é›†ã€‚此整åˆå¯ç”¨æ–¼å¯©é–±ã€éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ï¼Œä»¥åŠä½¿ç”¨åŒä¸€å¢é›†åŸ·è¡Œæ‰€æœ‰é …目的æµæ°´ç·šã€‚"
msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
-msgstr ""
+msgstr "加入整åˆåˆ°ç¾¤çµ„後,å¯ä»¥åœ¨ç¾¤çµ„中的所有項目中共享å¢é›†ã€‚"
msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
-msgstr ""
+msgstr "加入整åˆå¾Œï¼Œå¯ä»¥åœ¨æ‰€æœ‰é …目中共享å¢é›†ã€‚"
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
-msgstr ""
+msgstr "Kuberneteså¢é›†é›†æˆçš„進階é¸é …"
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
-msgstr ""
+msgstr "å…許GitLab管ç†æ­¤å¢é›†çš„命å空間和æœå‹™è³¬æˆ¶ã€‚"
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
-msgstr ""
+msgstr "å…許 GitLab 查詢特定é…置的å¢é›†å…§å»º Prometheus,以ç²å–指標。"
msgid "ClusterIntegration|Amazon EKS"
-msgstr ""
+msgstr "Amazon EKS"
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
-msgstr ""
+msgstr "嘗試連接到 Kubernetes 時發生未知錯誤。"
msgid "ClusterIntegration|Any project namespaces"
-msgstr ""
+msgstr "任何項目命å空間"
msgid "ClusterIntegration|Apply for credit"
-msgstr ""
+msgstr "申請é¡åº¦"
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "身份驗證錯誤"
msgid "ClusterIntegration|Base domain"
-msgstr ""
+msgstr "基礎域"
msgid "ClusterIntegration|CA Certificate"
-msgstr ""
+msgstr "CA憑證"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
-msgstr ""
+msgstr "憑證授權包(PEMæ ¼å¼)"
msgid "ClusterIntegration|Check your CA certificate"
-msgstr ""
+msgstr "檢查您的CA憑證"
msgid "ClusterIntegration|Check your cluster status"
-msgstr ""
+msgstr "檢查您的å¢é›†ç‹€æ…‹"
msgid "ClusterIntegration|Check your token"
-msgstr ""
+msgstr "檢查您的令牌(權æ–)"
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
-msgstr ""
+msgstr "è«‹é¸æ“‡ä½¿ç”¨æ­¤Kuberneteså¢é›†çš„環境。"
msgid "ClusterIntegration|Civo Kubernetes"
-msgstr ""
+msgstr "Civo Kubernetes"
msgid "ClusterIntegration|Clear cluster cache"
-msgstr ""
+msgstr "清除å¢é›†å¿«å–"
msgid "ClusterIntegration|Clear the local cache of namespace and service accounts."
-msgstr ""
+msgstr "清除命å空間和æœå‹™è³¬æˆ¶çš„本地緩存。"
msgid "ClusterIntegration|Cluster management project"
-msgstr ""
+msgstr "å¢é›†ç®¡ç†é …ç›®"
msgid "ClusterIntegration|Cluster name is required."
-msgstr ""
+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 ""
+msgstr "層級中最低且匹é…環境範åœçš„å¢é›†å°‡æœƒè¢«ä½¿ç”¨ã€‚例如,專案å¢é›†å°‡å„ªå…ˆæ–¼ç¾¤çµ„å¢é›†ã€‚%{linkStart}更多信æ¯%{linkEnd}"
msgid "ClusterIntegration|Connect a Kubernetes cluster"
-msgstr ""
+msgstr "連接 Kubernetes å¢é›†"
msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
-msgstr ""
+msgstr "é€šéŽ %{linkStart}集群證書%{linkEnd} 將您的å¢é›†é€£æŽ¥åˆ° GitLab 。"
msgid "ClusterIntegration|Connection Error"
-msgstr ""
+msgstr "連接錯誤"
msgid "ClusterIntegration|Copy API URL"
-msgstr ""
+msgstr "複製API地å€"
msgid "ClusterIntegration|Copy CA Certificate"
-msgstr ""
+msgstr "複製CA憑證"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
-msgstr ""
+msgstr "複製Kuberneteså¢é›†å稱"
msgid "ClusterIntegration|Create a Kubernetes cluster"
-msgstr ""
+msgstr "建立一個 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 "å°‡æ¯å€‹ç’°å¢ƒéƒ¨ç½²åˆ°è‡ªå·±çš„命å空間。å¦å‰‡ï¼Œä¸€å€‹å°ˆæ¡ˆä¸­çš„環境共享專案範åœçš„命å空間。 請注æ„,任何能夠觸發部署命å空間的人都å¯ä»¥é–±è®€å‘½å空間的秘密。 如果被修改,ç¾æœ‰ç’°å¢ƒå°‡ä½¿ç”¨ç•¶å‰çš„命å空間,直到å¢é›†ç·©å­˜è¢«æ¸…除。"
msgid "ClusterIntegration|Did you know?"
-msgstr ""
+msgstr "你是å¦çž­è§£ï¼Ÿ"
msgid "ClusterIntegration|Elastic Kubernetes Service"
-msgstr ""
+msgstr "Elastic Kubernetes Service(EKS)"
msgid "ClusterIntegration|Enable Prometheus integration"
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|啟用 Prometheus æ•´åˆ"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
-msgstr ""
+msgstr "啟用或åœç”¨GitLab與Kuberneteså¢é›†çš„連接。"
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
-msgstr ""
+msgstr "如果使用基於角色的存å–控制(RBAC),請啟用此設定。"
msgid "ClusterIntegration|Enter details about your cluster. %{linkStart}How do I use a certificate to connect to my cluster?%{linkEnd}"
-msgstr ""
+msgstr "輸入有關您的å¢é›†çš„詳細信æ¯ã€‚%{linkStart}如何使用憑證連接到我的å¢é›†ï¼Ÿ%{linkEnd}"
msgid "ClusterIntegration|Enter new Service Token"
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|輸入新的æœå‹™æ†‘è­‰"
msgid "ClusterIntegration|Enter your Kubernetes cluster certificate details"
-msgstr ""
+msgstr "群集整åˆ|輸入您的 Kubernetes å¢é›†æ†‘證細節"
msgid "ClusterIntegration|Environment scope"
-msgstr ""
+msgstr "環境範åœ"
msgid "ClusterIntegration|Environment scope is required."
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|需è¦ç’°å¢ƒç¯„åœã€‚"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
-msgstr ""
+msgstr "æ¯å€‹æ–°çš„ Google é›²å¹³å° (GCP) å¸³è™Ÿä½¿ç”¨æ­¤é€£çµ %{sign_up_link} å¯ä»¥æ”¶åˆ°åƒ¹å€¼300美元的å…è²»é¡åº¦ã€‚é€éŽèˆ‡Google çš„åˆä½œï¼ŒGitLabå¯ä»¥ç‚ºæ–°è¨»å†Šçš„å’Œç¾æœ‰çš„ GCP 帳號æä¾›é¡å¤– 200 美元的é¡åº¦ï¼Œä»¥æ–¹ä¾¿å¯¦ç¾ GitLab å’Œ Google Kubernetes引擎的整åˆã€‚"
msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
-msgstr ""
+msgstr "無法é…ç½®EKSæ供程å¼ï¼š%{message}"
msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
-msgstr ""
+msgstr "é…ç½®GoogleKubernetes引擎(GKE)å¢é›†å¤±æ•—: %{message}"
msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
-msgstr ""
+msgstr "抓å–CloudFormation stack失敗:%{message}"
msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
-msgstr ""
+msgstr "請求Google雲平å°å¤±æ•—: %{message}"
msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
-msgstr ""
+msgstr "執行 Kubeclient 失敗: %{message}"
msgid "ClusterIntegration|GitLab Integration"
-msgstr ""
+msgstr "GitLabæ•´åˆ"
msgid "ClusterIntegration|GitLab failed to authenticate."
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|GitLab 身份驗證失敗。"
msgid "ClusterIntegration|GitLab failed to connect to the cluster."
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|GitLab 無法連線到å¢é›†ã€‚"
msgid "ClusterIntegration|GitLab-managed cluster"
-msgstr ""
+msgstr "GitLab管ç†çš„å¢é›†"
msgid "ClusterIntegration|Google GKE"
-msgstr ""
+msgstr "Google GKE"
msgid "ClusterIntegration|Google Kubernetes Engine"
-msgstr ""
+msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Group cluster"
-msgstr ""
+msgstr "群組級å¢é›†"
msgid "ClusterIntegration|HTTP Error"
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|http 錯誤"
msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
-msgstr ""
+msgstr "如果您ä¸æƒ³åˆªé™¤æ‰€æœ‰ç›¸é—œçš„GitLab資æºï¼Œæ‚¨å¯ä»¥åªåˆªé™¤æ•´åˆã€‚"
msgid "ClusterIntegration|In order to view the health of your cluster, you must first enable Prometheus in the Integrations tab."
-msgstr ""
+msgstr "為了查看å¢é›†çš„é‹è¡Œç‹€æ³ï¼Œæ‚¨å¿…須首先在「整åˆã€é¸é …å¡ä¸­å•Ÿç”¨ Prometheus。"
msgid "ClusterIntegration|Instance cluster"
-msgstr ""
+msgstr "實體å¢é›†"
msgid "ClusterIntegration|Integration disabled"
-msgstr ""
+msgstr "å·²ç¦ç”¨æ•´åˆ"
msgid "ClusterIntegration|Integration enabled"
-msgstr ""
+msgstr "å¢é›†æ•´åˆ|已啟用整åˆ"
msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
-msgstr ""
+msgstr "æ•´åˆå…許您使用安è£åœ¨å¢é›†ä¸­çš„應用程åºä½œç‚º GitLab 工作æµç¨‹çš„一部分。"
msgid "ClusterIntegration|Kubernetes cluster is being created..."
-msgstr ""
+msgstr "正在建立Kuberneteså¢é›†..."
msgid "ClusterIntegration|Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes å¢é›†å稱"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
-msgstr ""
+msgstr "å·²æˆåŠŸå»ºç«‹Kuberneteså¢é›†ã€‚"
msgid "ClusterIntegration|Learn more about Kubernetes."
-msgstr ""
+msgstr "瞭解更多關於 Kubernetes 的訊æ¯ã€‚"
msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
-msgstr ""
+msgstr "了解更多的群組級Kuberneteså¢é›†è¨Šæ¯"
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
-msgstr ""
+msgstr "了解有關實體級Kuberneteså¢é›†æ›´å¤šè¨Šæ¯"
msgid "ClusterIntegration|Make sure your API endpoint is correct"
-msgstr ""
+msgstr "請確ä¿æ‚¨çš„API端點正確"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
-msgstr ""
+msgstr "é€éŽå­˜å–%{provider_link}管ç†Kuberneteså¢é›†"
msgid "ClusterIntegration|Namespace per environment"
-msgstr ""
+msgstr "按環境分é…命å空間"
msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
-msgstr ""
+msgstr "節點計算使用Kubernetes Metrics API。請確ä¿æ‚¨çš„å¢é›†å·²å®‰è£æŒ‡æ¨™ã€‚"
msgid "ClusterIntegration|Project cluster"
-msgstr ""
+msgstr "項目級å¢é›†"
msgid "ClusterIntegration|Project namespace (optional, unique)"
-msgstr ""
+msgstr "項目命å空間(å¯é¸ï¼Œå”¯ä¸€)"
msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
-msgstr ""
+msgstr "項目命å空間å‰ç¶´(å¯é¸ï¼Œå”¯ä¸€)"
msgid "ClusterIntegration|Provider details"
-msgstr ""
+msgstr "å¢é›†è©³æƒ…"
msgid "ClusterIntegration|RBAC-enabled cluster"
-msgstr ""
+msgstr "啟用RBACçš„å¢é›†"
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
-msgstr ""
+msgstr "刪除Kuberneteså¢é›†æ•´åˆ"
msgid "ClusterIntegration|Remove integration"
-msgstr ""
+msgstr "移除整åˆ"
msgid "ClusterIntegration|Remove integration and resources"
-msgstr ""
+msgstr "移除整åˆå’Œè³‡æº"
msgid "ClusterIntegration|Remove integration and resources?"
-msgstr ""
+msgstr "移除整åˆå’Œè³‡æºå—Žï¼Ÿ"
msgid "ClusterIntegration|Remove integration?"
-msgstr ""
+msgstr "移除整åˆå—Ž?"
msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "從目å‰é …目中移除此Kuberneteså¢é›†çš„é…置。該æ“作並ä¸æœƒåˆªé™¤å¯¦éš›Kuberneteså¢é›†ã€‚"
msgid "ClusterIntegration|Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
-msgstr ""
+msgstr "查看並編輯Kuberneteså¢é›†çš„詳細訊æ¯"
msgid "ClusterIntegration|Service Token"
-msgstr ""
+msgstr "æœå‹™ä»¤ç‰Œ(權æ–)"
msgid "ClusterIntegration|Service token is required."
-msgstr ""
+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 ""
+msgstr "設定å稱空間的å‰ç¶´ã€‚如未設定,則é è¨­ç‚ºå°ˆæ¡ˆè·¯å¾‘。如進行了修改,則ç¾æœ‰ç’°å¢ƒä»å°‡ä½¿ç”¨å…¶ç›®å‰çš„å稱空間,直到清除å¢é›†å¿«å–。"
msgid "ClusterIntegration|Something went wrong on our end."
-msgstr ""
+msgstr "發生了內部錯誤"
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
-msgstr ""
+msgstr "建立Kuberneteså¢é›†æ™‚發生錯誤"
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
-msgstr ""
+msgstr "指定網域將å…許您使用%{linkStart}Auto DevOps%{linkEnd}中的自動評審應用和自動部署階段。網域å應包å«èˆ‡ç¶²åŸŸåŒ¹é…的通é…符DNS。"
msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
-msgstr ""
+msgstr "用於å°å¢é›†é€²è¡Œèº«ä»½é©—證的 Kubernetes 憑證。"
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
-msgstr ""
+msgstr "ç”¨æ–¼å­˜å– Kubernetes API çš„ URL。"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support."
-msgstr ""
+msgstr "基於證書的 Kubernetes æ•´åˆå·²è¢«æ£„用,將於 2022 å¹´ 11 月關閉。請 %{linkStart}é·ç§»åˆ° GitLab 代ç†çš„ Kubernetes%{linkEnd} 或è¯ç¹« GitLab 支æ´æœå‹™ã€‚"
msgid "ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}."
-msgstr ""
+msgstr "基於證書的 Kubernetes æ•´åˆå·²è¢«æ£„用,將於 2022 å¹´ 11 月關閉。請 %{linkStart}é·ç§»åˆ° GitLab 代ç†çš„ Kubernetes%{linkEnd}。"
msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
-msgstr ""
+msgstr "採用憑證將å¢é›†é€£æŽ¥åˆ° GitLab 的方法將於 14.5 版本%{linkStart}棄用%{linkEnd}。"
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, and Web terminals."
-msgstr ""
+msgstr "與您專案關è¯çš„命å空間,將用於部署看æ¿å’Œ Web 終端。"
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
-msgstr ""
+msgstr "å¢é›†èº«ä»½é©—證時出ç¾å•é¡Œã€‚請確ä¿æ‚¨çš„CA憑證和權æ–有效。"
msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
-msgstr ""
+msgstr "連接到您的å¢é›†æ™‚發生HTTP錯誤。"
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 "如整åˆå·²å¤±åŽ»åŒæ­¥ï¼Œå‰‡æ­¤æ“作為必須。快å–緩存將在所需å稱空間和æœå‹™å¸³è™Ÿçš„下一個CI作業期間é‡æ–°ç”Ÿæˆã€‚"
msgid "ClusterIntegration|This is necessary to clear existing environment-namespace associations from clusters previously managed by GitLab."
-msgstr ""
+msgstr "必需清除之å‰ç”± GitLab 所管ç†çš„å¢é›†èˆ‡ç’°å¢ƒå‘½å空間的關è¯ã€‚"
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
-msgstr ""
+msgstr "æ­¤é¸é …å…許您在啟用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 "此程åºå·²è¢« %{issue_link_start}棄用%{issue_link_end}。 請改用 %{docs_link_start}GitLab ä»£ç† Kubernetes%{docs_link_end}。"
msgid "ClusterIntegration|This will permanently delete the following resources:"
-msgstr ""
+msgstr "æ­¤æ“作將永久刪除以下資æºï¼š"
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
-msgstr ""
+msgstr "è¦åˆªé™¤æ•´åˆå’Œè³‡æºï¼Œè«‹è¼¸å…¥%{clusterName}以確èªï¼š"
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
-msgstr ""
+msgstr "è¦åˆªé™¤æ•´åˆï¼Œè«‹è¼¸å…¥%{clusterName}以確èªï¼š"
msgid "ClusterIntegration|Troubleshooting tips:"
-msgstr ""
+msgstr "故障排除æ示:"
msgid "ClusterIntegration|Unable to Authenticate"
-msgstr ""
+msgstr "無法驗證"
msgid "ClusterIntegration|Unable to Connect"
-msgstr ""
+msgstr "無法連接"
msgid "ClusterIntegration|Unknown Error"
-msgstr ""
+msgstr "未知錯誤"
msgid "ClusterIntegration|Use GitLab to deploy to your cluster, run jobs, use review apps, and more."
-msgstr ""
+msgstr "使用 GitLab 部署到您的å¢é›†ï¼ŒåŸ·è¡Œä½œæ¥­ï¼Œä½¿ç”¨ review apps 等等。"
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 "使用 %{linkStart}GitLab 代ç†%{linkEnd} 將您的 Kubernetes å¢é›†å®‰å…¨åœ°é€£æŽ¥åˆ° GitLab。您å¯ä»¥éƒ¨ç½²æ‚¨çš„應用程åºã€é‹è¡Œæ‚¨çš„æµæ°´ç·šã€ä½¿ç”¨ Review Apps 等等。"
msgid "ClusterIntegration|Using AutoDevOps with multiple clusters? %{help_link_start}Read this first.%{help_link_end}"
-msgstr ""
+msgstr "在多個å¢é›†ä¸­ä½¿ç”¨ AutoDevOps? %{help_link_start}請先閱讀此內容。%{help_link_end}"
msgid "ClusterIntegration|Where do you want to create a cluster?"
-msgstr ""
+msgstr "您想è¦åœ¨å“ªè£¡å‰µå»ºå¢é›†ï¼Ÿ"
msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
-msgstr ""
+msgstr "您å³å°‡åˆªé™¤å¢é›†æ•´åˆå’Œèˆ‡æ­¤å¢é›†ä¸­GitLab建立的所有資æºã€‚"
msgid "ClusterIntegration|You are about to remove your cluster integration."
-msgstr ""
+msgstr "å³å°‡åˆªé™¤å¢é›†æ•´åˆã€‚"
msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
-msgstr ""
+msgstr "您的 API 無法存å–。請確ä¿æ‚¨çš„ API URL 正確。"
msgid "ClusterIntegration|sign up"
-msgstr ""
+msgstr "註冊"
msgid "Clusters|An error occurred while loading clusters"
-msgstr ""
+msgstr "載入å¢é›†æ™‚發生錯誤"
msgid "Code"
-msgstr ""
+msgstr "程å¼ç¢¼"
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
-msgstr ""
+msgstr "程å¼ç¢¼è¦†è“‹çŽ‡ï¼š%{coveragePercentage}%{percentSymbol}"
msgid "Code Coverage| Empty code coverage data"
-msgstr ""
+msgstr "程å¼ç¢¼è¦†è“‹çŽ‡è³‡æ–™ç‚ºç©ºçš„"
msgid "Code Coverage|Couldn't fetch the code coverage data"
-msgstr ""
+msgstr "無法å–得程å¼ç¢¼è¦†è“‹çŽ‡è³‡æ–™"
msgid "Code Owner"
-msgstr ""
+msgstr "程å¼ç¢¼æ“有者"
msgid "Code Owners"
msgstr "程å¼ç¢¼æ‰€æœ‰è€…"
msgid "Code Quality"
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡"
msgid "Code Review"
-msgstr ""
+msgstr "程å¼ç¢¼å¯©æŸ¥"
msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
-msgstr ""
+msgstr "程å¼ç¢¼å¯©æŸ¥åˆ†æžé¡¯ç¤ºäº†ä¸€å€‹è™•æ–¼é–‹å•Ÿåˆä½µè«‹æ±‚階段的程å¼ç¢¼å¯©æŸ¥åˆ—表。 當å‰æ²’有此專案和/或篩é¸å™¨çš„åˆä½µè«‹æ±‚。"
msgid "Code block"
-msgstr ""
+msgstr "程å¼ç¢¼å€å¡Š"
msgid "Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub"
-msgstr ""
+msgstr "專案創建期間å¯ä»¥å•Ÿç”¨å¾žä¾†æºåŒ¯å…¥ç¨‹å¼ç¢¼ï¼Œå¿…須為 GitHub é…ç½® OmniAuth。"
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
-msgstr ""
+msgstr "程å¼ç¢¼è¦†è“‹çŽ‡çµ±è¨ˆ %{ref} %{start_date} - %{end_date}"
msgid "Code owner approval is required"
-msgstr ""
+msgstr "程å¼ç¢¼æ“有者的核准是必須的"
msgid "Code owners"
-msgstr ""
+msgstr "程å¼ç¢¼æ“有者"
msgid "Code review"
-msgstr ""
+msgstr "程å¼ç¢¼å¯©æŸ¥"
msgid "Code snippet"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
-msgstr ""
+msgstr "已複製程å¼ç¢¼ç‰‡æ®µã€‚將其æ’å…¥YAML檔案中的正確ä½ç½®ã€‚"
msgid "CodeIntelligence|This is the definition"
-msgstr ""
+msgstr "此處為定義"
msgid "CodeNavigation|No references found"
-msgstr ""
+msgstr "未找到åƒè€ƒå…§å®¹"
msgid "CodeOwner|Pattern"
-msgstr ""
+msgstr "模å¼"
msgid "CodeQuality|New code quality degradations on this line"
-msgstr ""
+msgstr "此行新程å¼ç¢¼çš„質é‡ä¸‹é™"
msgid "Cohorts|Inactive users"
-msgstr ""
+msgstr "未啟用的使用者"
msgid "Cohorts|Month %{month_index}"
-msgstr ""
+msgstr "月 %{month_index}"
msgid "Cohorts|New users"
-msgstr ""
+msgstr "新使用者"
msgid "Cohorts|Registration month"
-msgstr ""
+msgstr "註冊月份"
msgid "Cohorts|Returning users"
-msgstr ""
+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 ""
+msgstr "使用者世代表顯示éŽåŽ»%{months_included}個月內的狀æ³ã€‚åªæœ‰æ´»å‹•çš„使用者被計入「新使用者ã€æ¬„ï¼›éžæ´»å‹•ä½¿ç”¨è€…會被單ç¨çµ±è¨ˆã€‚"
msgid "Collapse"
-msgstr ""
+msgstr "收疊"
msgid "Collapse all threads"
-msgstr ""
+msgstr "收疊所有主題"
msgid "Collapse approvers"
-msgstr ""
+msgstr "收疊核准者"
msgid "Collapse issues"
-msgstr ""
+msgstr "收疊議題"
msgid "Collapse jobs"
-msgstr ""
+msgstr "收疊作業"
msgid "Collapse milestones"
-msgstr ""
+msgstr "收疊里程碑"
msgid "Collapse replies"
-msgstr ""
+msgstr "收疊回復"
msgid "Collapse settings section"
-msgstr ""
+msgstr "收疊設定部份"
msgid "Collapse sidebar"
-msgstr ""
+msgstr "收疊å´é‚Šæ¬„"
msgid "Collapses this file (only for you) until it’s changed again."
-msgstr ""
+msgstr "收疊此文件(僅é©ç”¨æ–¼æ‚¨ï¼‰ï¼Œç›´åˆ°å®ƒå†æ¬¡è®Šæ›´ã€‚"
msgid "Collector hostname"
-msgstr ""
+msgstr "Collector主機å稱"
msgid "Color"
-msgstr ""
+msgstr "é¡è‰²"
msgid "ColorWidget|An error occurred while updating color."
-msgstr ""
+msgstr "æ›´æ–°é¡è‰²æ™‚發生錯誤。"
msgid "ColorWidget|Assign epic color"
-msgstr ""
+msgstr "設定å²è©©é¡è‰²"
msgid "ColorWidget|Color"
-msgstr ""
+msgstr "é¡è‰²"
msgid "ColorWidget|Error fetching epic color."
-msgstr ""
+msgstr "讀å–å²è©©é¡è‰²æ™‚發生錯誤"
msgid "Colorize messages"
-msgstr ""
+msgstr "為消æ¯è‘—色"
msgid "ComboSearch is not defined"
-msgstr ""
+msgstr "ComboSearch未定義"
msgid "Comma-separated list of email addresses."
-msgstr ""
+msgstr "逗號分隔的電å­éƒµä»¶åœ°å€åˆ—表。"
msgid "Command"
-msgstr ""
+msgstr "指令"
msgid "Command line instructions"
-msgstr ""
+msgstr "命令列指引"
msgid "Commands applied"
-msgstr ""
+msgstr "指令已執行"
msgid "Commands did not apply"
-msgstr ""
+msgstr "指令未使用"
msgid "Comment"
msgstr "è©•è«–"
msgid "Comment & resolve thread"
-msgstr ""
+msgstr "留言並確èª"
msgid "Comment & unresolve thread"
-msgstr ""
+msgstr "留言但未確èª"
msgid "Comment '%{label}' position"
-msgstr ""
+msgstr "留言%{label}'çš„ä½ç½®"
msgid "Comment form position"
-msgstr ""
+msgstr "留言框ä½ç½®"
msgid "Comment is being updated"
-msgstr ""
+msgstr "留言正在更新"
msgid "Comment on lines %{startLine} to %{endLine}"
-msgstr ""
+msgstr "å°%{startLine}到%{endLine}行的留言"
msgid "Comment/Reply (quoting selected text)"
-msgstr ""
+msgstr "留言/回復 (引用é¸å®šçš„文字)"
msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
-msgstr ""
+msgstr "當å‰ä¸æ”¯æŒç•™è¨€æ›¿æ›æˆ–被符號éˆæŽ¥æ›¿æ›çš„文件。"
msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
-msgstr ""
+msgstr "當å‰ä¸æ”¯æŒå°æ›¿æ›æˆ–被文件替æ›çš„符號éˆæŽ¥é€²è¡Œç•™è¨€ã€‚"
msgid "Comments"
-msgstr ""
+msgstr "留言"
msgid "Commit"
msgid_plural "Commits"
-msgstr[0] ""
+msgstr[0] "æ交"
msgid "Commit %{commit_id}"
-msgstr ""
+msgstr "æ交 %{commit_id}"
msgid "Commit (when editing commit message)"
-msgstr ""
+msgstr "æ交(編輯æ交消æ¯æ™‚)"
msgid "Commit Message"
-msgstr ""
+msgstr "æ交訊æ¯"
msgid "Commit SHA"
-msgstr ""
+msgstr "æ交的 SHA"
msgid "Commit changes"
-msgstr ""
+msgstr "æ交更改"
msgid "Commit deleted"
-msgstr ""
+msgstr "æ交已刪除"
msgid "Commit message"
-msgstr ""
+msgstr "æ交訊æ¯"
msgid "Commit message (optional)"
-msgstr ""
+msgstr "æ交訊æ¯ï¼ˆé¸å¡«ï¼‰"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
-msgstr ""
+msgstr "æ交統計 %{ref} %{start_time} - %{end_time}"
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "æ交到 %{branchName} 分支"
msgid "CommitBoxTitle|Commit"
-msgstr ""
+msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
-msgstr ""
+msgstr "加入 %{file_name}"
msgid "CommitWidget|authored"
-msgstr ""
+msgstr "撰寫"
msgid "Commits"
-msgstr ""
+msgstr "æ交"
msgid "Commits feed"
-msgstr ""
+msgstr "æ交動態"
msgid "Commits per day hour (UTC)"
-msgstr ""
+msgstr "一天中æ¯å°æ™‚(UTC)æ交數"
msgid "Commits per day of month"
-msgstr ""
+msgstr "一個月中æ¯å¤©çš„æ交數"
msgid "Commits per weekday"
-msgstr ""
+msgstr "一週中æ¯æ—¥æ交數"
msgid "Commits to"
-msgstr ""
+msgstr "æ交到"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
-msgstr ""
+msgstr "您é¸æ“‡çš„æ交顯示在此處。請至第一個é ç°½é¸æ“‡æ交以添加到此åˆä½µè«‹æ±‚。"
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr ""
+msgstr "å–å¾—åˆä½µè«‹æ±‚資料時發生錯誤"
msgid "Commits|History"
-msgstr ""
+msgstr "æ­·å²"
msgid "Commits|No related merge requests found"
-msgstr ""
+msgstr "無相關åˆä½µè«‹æ±‚"
msgid "Committed by"
-msgstr ""
+msgstr "æ交者:"
msgid "Community forum"
-msgstr ""
+msgstr "社å€è«–壇"
msgid "Company"
-msgstr ""
+msgstr "å…¬å¸"
msgid "Company Name"
-msgstr ""
+msgstr "å…¬å¸å稱"
msgid "Compare"
-msgstr ""
+msgstr "比較"
msgid "Compare %{oldCommitId}...%{newCommitId}"
-msgstr ""
+msgstr "比較 %{oldCommitId}...%{newCommitId}"
msgid "Compare Git revisions"
-msgstr ""
+msgstr "比較Gitæ交版本"
msgid "Compare GitLab editions"
-msgstr ""
+msgstr "比較GitLab版本"
msgid "Compare Revisions"
-msgstr ""
+msgstr "比較版本"
msgid "Compare changes"
-msgstr ""
+msgstr "比較變更"
msgid "Compare changes with the last commit"
-msgstr ""
+msgstr "與上個æ交比較變更內容"
msgid "Compare changes with the merge request target branch"
-msgstr ""
+msgstr "與åˆä½µè«‹æ±‚的目標分支比較變更內容"
msgid "Compare submodule commit revisions"
-msgstr ""
+msgstr "比較å­æ¨¡çµ„çš„æ交修訂"
msgid "Compare with previous version"
-msgstr ""
+msgstr "與之å‰çš„版本比較"
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
-msgstr ""
+msgstr "%{source_branch} å’Œ %{target_branch} 是相åŒçš„"
msgid "CompareBranches|There isn't anything to compare."
-msgstr ""
+msgstr "沒有å¯ä»¥æ¯”較的。"
msgid "CompareRevisions|Branches"
-msgstr ""
+msgstr "比較修訂|分支"
msgid "CompareRevisions|Compare"
-msgstr ""
+msgstr "比較修訂|比較"
msgid "CompareRevisions|Create merge request"
-msgstr ""
+msgstr "比較修訂|建立åˆä½µè«‹æ±‚"
msgid "CompareRevisions|Filter by Git revision"
-msgstr ""
+msgstr "比較修訂|ä¾ç…§ Git 版本進行篩é¸"
msgid "CompareRevisions|Select Git revision"
-msgstr ""
+msgstr "比較修訂|é¸æ“‡ Git 版本"
msgid "CompareRevisions|Select branch/tag"
-msgstr ""
+msgstr "比較修訂|é¸æ“‡åˆ†æ”¯/標籤"
msgid "CompareRevisions|Select target project"
-msgstr ""
+msgstr "比較修訂|é¸æ“‡ç›®æ¨™å°ˆæ¡ˆ"
msgid "CompareRevisions|Swap revisions"
-msgstr ""
+msgstr "比較修訂|交æ›ç‰ˆæœ¬"
msgid "CompareRevisions|Tags"
-msgstr ""
+msgstr "比較修訂|標籤"
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
-msgstr ""
+msgstr "比較修訂|載入分支/標籤列表時發生錯誤。請é‡è©¦ã€‚"
msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
-msgstr ""
+msgstr "比較修訂|æœå°‹åˆ†æ”¯/標籤列表時發生錯誤。請é‡è©¦ã€‚"
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
-msgstr ""
+msgstr "比較修訂|更新分支/標籤列表時發生錯誤。請é‡è©¦ã€‚"
msgid "CompareRevisions|View open merge request"
-msgstr ""
+msgstr "比較修訂|檢視開啟的åˆä½µè«‹æ±‚"
msgid "Complete"
-msgstr ""
+msgstr "完æˆ"
msgid "Complete verification to sign in."
-msgstr ""
+msgstr "完æˆé©—證方å¯ç™»éŒ„。"
msgid "Completed"
-msgstr ""
+msgstr "已完æˆ"
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
-msgstr ""
+msgstr "在 %{duration_seconds} 秒內完æˆï¼ˆ%{relative_time})"
msgid "Compliance framework"
-msgstr ""
+msgstr "åˆè¦æ¡†æž¶"
msgid "Compliance report"
-msgstr ""
+msgstr "åˆè¦å ±å‘Š"
msgid "ComplianceFrameworks|Add framework"
-msgstr ""
+msgstr "添加框架"
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "背景é¡è‰²"
msgid "ComplianceFrameworks|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤åˆè¦æ¡†æž¶"
msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
-msgstr ""
+msgstr "åˆè¦æµæ°´ç·šçµ„態設定(å¯é¸ï¼‰"
msgid "ComplianceFrameworks|Configuration not found"
-msgstr ""
+msgstr "找ä¸åˆ°çµ„態設定"
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
-msgstr ""
+msgstr "刪除%{framework}åˆè¦æ¡†æž¶"
msgid "ComplianceFrameworks|Delete framework"
-msgstr ""
+msgstr "刪除框架"
msgid "ComplianceFrameworks|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "ComplianceFrameworks|Description is required"
-msgstr ""
+msgstr "å¿…è¦çš„æè¿°"
msgid "ComplianceFrameworks|Edit framework"
-msgstr ""
+msgstr "編輯框架"
msgid "ComplianceFrameworks|Error deleting the compliance framework. Please try again"
-msgstr ""
+msgstr "刪除åˆè¦æ¡†æž¶æ™‚出錯,請é‡è©¦"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page"
-msgstr ""
+msgstr "å–å¾—åˆè¦æ¡†æž¶è³‡æ–™éŒ¯èª¤ï¼Œè«‹é‡æ–°è¼‰å…¥é é¢"
msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please refresh the page or try a different framework"
-msgstr ""
+msgstr "å–å¾—åˆè¦æ¡†æž¶è³‡æ–™éŒ¯èª¤ï¼Œè«‹é‡æ–°è¼‰å…¥é é¢æˆ–嘗試其它的框架"
msgid "ComplianceFrameworks|Frameworks that have been added will appear here."
-msgstr ""
+msgstr "已添加的框架將出ç¾åœ¨æ­¤è™•ã€‚"
msgid "ComplianceFrameworks|Invalid format"
-msgstr ""
+msgstr "無效格å¼"
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "å稱"
msgid "ComplianceFrameworks|Name is required"
-msgstr ""
+msgstr "å稱是必è¦çš„"
msgid "ComplianceFrameworks|No compliance frameworks are set up yet"
-msgstr ""
+msgstr "尚未設置åˆè¦æ¡†æž¶"
msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "所需格å¼ï¼š %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}。 %{linkStart}瞭解更多。%{linkEnd}"
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
-msgstr ""
+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 ""
+msgstr "您å³å°‡å¾žæ‰€æœ‰ç•¶å‰æ‡‰ç”¨çš„專案中永久刪除åˆè¦æ¡†æž¶ %{framework} ,這å¯èƒ½æœƒåˆªé™¤å…¶å®ƒåŠŸèƒ½ã€‚æ­¤æ“作無法撤消。"
msgid "ComplianceFramework|Add a framework to %{linkStart}%{groupName}%{linkEnd} and it will appear here."
-msgstr ""
+msgstr "添加一個框架到 %{linkStart}%{groupName}%{linkEnd} 並將出ç¾åœ¨é€™è£¡ã€‚"
msgid "ComplianceFramework|Add framework in %{groupName}"
-msgstr ""
+msgstr "在 %{groupName} 中添加框架"
msgid "ComplianceFramework|After a framework is added to %{linkStart}%{groupName}%{linkEnd}, it will appear here."
-msgstr ""
+msgstr "框架被添加到 %{linkStart}%{groupName}%{linkEnd} 之後,將會出ç¾åœ¨æ­¤è™•ã€‚"
msgid "ComplianceFramework|Edit compliance framework"
-msgstr ""
+msgstr "編輯åˆè¦æ¡†æž¶"
msgid "ComplianceFramework|New compliance framework"
-msgstr ""
+msgstr "新建åˆè¦æ¡†æž¶"
msgid "ComplianceFramework|No compliance frameworks are set up yet"
-msgstr ""
+msgstr "尚未建立åˆè¦æ¡†æž¶"
msgid "ComplianceReport|Approved by author"
-msgstr ""
+msgstr "由作者批准"
msgid "ComplianceReport|Approved by committer"
-msgstr ""
+msgstr "ç”±æ交者批准"
msgid "ComplianceReport|Less than 2 approvers"
-msgstr ""
+msgstr "少於 2 個核准人"
msgid "ComplianceReport|No violations found"
-msgstr ""
+msgstr "未發ç¾é•è¦è¡Œç‚º"
msgid "Component"
-msgstr ""
+msgstr "元件"
msgid "Confidence"
-msgstr ""
+msgstr "å¯ä¿¡åº¦"
msgid "Confidential"
-msgstr ""
+msgstr "機密"
msgid "Confidential issue"
-msgstr ""
+msgstr "機密議題"
msgid "Confidential note"
-msgstr ""
+msgstr "機密備註"
msgid "Confidentiality"
-msgstr ""
+msgstr "機密性"
msgid "Configuration"
-msgstr ""
+msgstr "組態"
msgid "Configuration help"
-msgstr ""
+msgstr "組態å”助說明"
msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
-msgstr ""
+msgstr "設定 %{italic_start}What's new%{italic_end} 內容。"
msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "設定 %{link} 跟蹤事件,%{link_start}瞭解更多信æ¯ã€‚%{link_end}"
msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and %{housekeeping_link_start}housekeeping%{link_end} on repositories."
-msgstr ""
+msgstr "在版本庫上設定 %{repository_checks_link_start}版本庫檢查%{link_end} 和 %{housekeeping_link_start}例行維護%{link_end}。"
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
-msgstr ""
+msgstr "設定 CAPTCHAã€IP 地å€é™åˆ¶å’Œå…¶ä»–å垃圾郵件措施。"
msgid "Configure 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 "在 `.gitlab-ci.yml` ä½¿ç”¨å— GitLab 管ç†çš„模æ¿è¨­å®šå®¹å™¨æŽƒæ功能,您å¯ä»¥[添加覆蓋變é‡](https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings)來自定義容器掃æ設置。"
msgid "Configure Container Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "在 `.gitlab-ci.yml` 中設定容器掃æ,如果該文件ä¸å­˜åœ¨å‰‡å‰µå»ºè©²æ–‡ä»¶"
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
-msgstr ""
+msgstr "ä½¿ç”¨å— GitLab 管ç†çš„模æ¿åœ¨ `.gitlab-ci.yml` 中設定ä¾è³´æŽƒæ,您å¯ä»¥[添加變é‡è¦†è“‹](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) 來自定義ä¾è³´é …掃æ設置。"
msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "在`.gitlab-ci.yml`中設å—定ä¾è³´æŽƒæ,如果該文件ä¸å­˜åœ¨å‰‡å‰µå»ºè©²æ–‡ä»¶"
msgid "Configure Error Tracking"
-msgstr ""
+msgstr "設定錯誤追蹤"
msgid "Configure GitLab"
-msgstr ""
+msgstr "GitLab 設定"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "設定 GitLab Runner 以開始使用Web終端。%{helpStart}了解更多。%{helpEnd}"
msgid "Configure Gitaly timeouts."
-msgstr ""
+msgstr "設定 Gitaly 逾時時間。"
msgid "Configure Integrations"
-msgstr ""
+msgstr "æ•´åˆè¨­å®š"
msgid "Configure Prometheus"
-msgstr ""
+msgstr "設定 Promethes"
msgid "Configure SAST IaC in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST IaC settings."
-msgstr ""
+msgstr "使用 GitLab 所管ç†çš„範本在「.gitlab-ci.ymlã€ä¸­é…ç½® SAST IaC。您å¯ä»¥[添加變é‡è¦†å¯«](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) 來自定義 SAST IaC 設置。"
msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "在 `.gitlab-ci.yml` 中é…ç½® SAST IaC,如果該文件ä¸å­˜åœ¨å‰‡å‰µå»ºè©²æ–‡ä»¶"
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 "使用 GitLab 所管ç†çš„範本在 `.gitlab-ci.yml` 中é…ç½® SAST。您å¯ä»¥[添加變é‡è¦†å¯«](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) 來自定義 SAST 設置。"
msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "在 `.gitlab-ci.yml` 中é…ç½® SAST,如果該文件ä¸å­˜åœ¨å‰‡å‰µå»ºæ­¤æ–‡ä»¶"
msgid "Configure Secret Detection in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) to customize Secret Detection settings."
-msgstr ""
+msgstr "使用 GitLab 所管ç†çš„範本在 `.gitlab-ci.yml` 中é…置金鑰檢測。您å¯ä»¥[添加變é‡è¦†è“‹](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) 來自定義密鑰檢測設置。"
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "在 `.gitlab-ci.yml` 中é…ç½® Secret Detection,如果該文件ä¸å­˜åœ¨å‰‡å‰µå»ºæ­¤æ–‡ä»¶"
msgid "Configure Sentry integration for error tracking"
-msgstr ""
+msgstr "設定 Sentry æ•´åˆä»¥é€²è¡ŒéŒ¯èª¤è¿½è¹¤"
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr ""
+msgstr "在%{codeStart}.gitlab%{codeEnd}目錄中é…ç½®%{codeStart}gitlab-webide.yml%{codeEnd}文件以開始使用Web終端。 %{helpStart}瞭解更多。%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings."
-msgstr ""
+msgstr "é…置進階權é™ã€å¤§åž‹æ–‡ä»¶å­˜å„²ã€é›™å› å­èªè­‰å’ŒCI/CD設定。"
msgid "Configure advanced permissions, Large File Storage, two-factor authentication, and customer relations settings."
-msgstr ""
+msgstr "設定進階權é™ã€å¤§æ–‡ä»¶å­˜å„²ã€é›™å› å­èªè­‰å’Œå®¢æˆ¶é—œä¿‚設定。"
msgid "Configure existing installation"
-msgstr ""
+msgstr "設定ç¾æœ‰å®‰è£"
msgid "Configure pipeline"
-msgstr ""
+msgstr "æµæ°´ç·šè¨­å®š"
msgid "Configure pipelines to deploy web apps, backend services, APIs and static resources to Google Cloud"
-msgstr ""
+msgstr "設定æµæ°´ç·šä»¥å°‡ç¶²è·¯æ‡‰ç”¨ç¨‹å¼ã€å¾Œç«¯æœå‹™ã€API å’Œéœæ…‹è³‡æºéƒ¨ç½²åˆ° Google Cloud"
msgid "Configure region"
-msgstr ""
+msgstr "å€åŸŸè¨­å®š"
msgid "Configure region for environment"
-msgstr ""
+msgstr "為環境設定å€åŸŸ"
msgid "Configure regions"
-msgstr ""
+msgstr "å€åŸŸ(s)設定"
msgid "Configure repository mirroring."
-msgstr ""
+msgstr "版本庫映åƒè¨­å®šã€‚"
msgid "Configure repository storage."
-msgstr ""
+msgstr "版本庫儲存空間設定。"
msgid "Configure settings for Advanced Search with Elasticsearch."
-msgstr ""
+msgstr "使用 Elasticsearch é…置進階æœå°‹çš„設定。"
msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "為 Files API 請求é…置特定é™åˆ¶ä»¥å–代一般用戶和 IP 速率é™åˆ¶ã€‚"
msgid "Configure specific limits for Git LFS requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "為å–代一般使用者和 IP 速率é™åˆ¶çš„ Git LFS 請求設定特定é™åˆ¶ã€‚"
msgid "Configure specific limits for deprecated API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "為已廢棄的 API 請求é…置特定é™åˆ¶ä»¥å–代一般用戶和 IP 速率é™åˆ¶ã€‚"
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "%{link} æ•´åˆè¨­å®šã€‚"
msgid "Configure the default first day of the week and time tracking units."
-msgstr ""
+msgstr "設定é è¨­çš„æ¯é€±ç¬¬ä¸€å¤©å’Œæ™‚間追蹤單ä½ã€‚"
msgid "Configure the way a user creates a new account."
-msgstr ""
+msgstr "é…置使用者建立新帳號的方å¼ã€‚"
msgid "Configure via Merge Request"
-msgstr ""
+msgstr "經由åˆä½µè«‹æ±‚設定"
msgid "Configure which lists are shown for anyone who visits this board"
-msgstr ""
+msgstr "為訪å•æ­¤çœ‹ç‰ˆçš„人設定顯示哪些列表"
msgid "Configure with a merge request"
-msgstr ""
+msgstr "使用åˆä½µè«‹æ±‚進行設定"
msgid "Configure your environments to be deployed to specific geographical regions"
-msgstr ""
+msgstr "設定您è¦éƒ¨ç½²åˆ°ç‰¹å®šåœ°ç†å€åŸŸçš„環境"
msgid "Confirm"
-msgstr ""
+msgstr "確èª"
msgid "Confirm approval"
-msgstr ""
+msgstr "確èªæ‰¹å‡†"
msgid "Confirm destroy application"
-msgstr ""
+msgstr "確èªéŠ·æ¯€ç”³è«‹"
msgid "Confirm new password"
-msgstr ""
+msgstr "確èªæ–°å¯†ç¢¼"
msgid "Confirm user"
-msgstr ""
+msgstr "確èªä½¿ç”¨è€…"
msgid "Confirm your account"
-msgstr ""
+msgstr "確èªæ‚¨çš„帳號"
msgid "Confirm your email address"
-msgstr ""
+msgstr "確èªæ‚¨çš„é›»å­éƒµä»¶åœ°å€"
msgid "Confirmation email sent to %{email}"
-msgstr ""
+msgstr "確èªé›»å­éƒµä»¶ç™¼é€åˆ°%{email}"
msgid "Confirmation required"
-msgstr ""
+msgstr "需è¦ç¢ºèª"
msgid "Confirmed at:"
-msgstr ""
+msgstr "確èªæ–¼"
msgid "Confirmed:"
-msgstr ""
+msgstr "已確èªï¼š"
msgid "Conflict: This file was added both in the source and target branches, but with different contents."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案已添加到來æºå’Œç›®æ¨™åˆ†æ”¯ä¸­ï¼Œä½†å…§å®¹ä¸åŒã€‚"
msgid "Conflict: This file was modified in both the source and target branches."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºå’Œç›®æ¨™åˆ†æ”¯ä¸­å‡å·²ä¿®æ”¹ã€‚"
msgid "Conflict: This file was modified in the source branch, but removed in the target branch."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºåˆ†æ”¯ä¸­å·²è¢«ä¿®æ”¹ï¼Œä½†åœ¨ç›®æ¨™åˆ†æ”¯ä¸­è¢«ç§»é™¤ã€‚"
msgid "Conflict: This file was removed in the source branch, but modified in the target branch."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºåˆ†æ”¯ä¸­å·²è¢«ç§»é™¤ï¼Œä½†åœ¨ç›®æ¨™åˆ†æ”¯ä¸­è¢«ä¿®æ”¹ã€‚"
msgid "Conflict: This file was removed in the source branch, but renamed in the target branch."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºåˆ†æ”¯ä¸­å·²è¢«ç§»é™¤ï¼Œä½†åœ¨ç›®æ¨™åˆ†æ”¯ä¸­è¢«é‡æ–°å‘½å。"
msgid "Conflict: This file was renamed differently in the source and target branches."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºå’Œç›®æ¨™åˆ†æ”¯ä¸­é‡æ–°å‘½åçš„å稱ä¸åŒã€‚"
msgid "Conflict: This file was renamed in the source branch, but removed in the target branch."
-msgstr ""
+msgstr "è¡çªï¼šè©²æª”案在來æºåˆ†æ”¯ä¸­å·²è¢«é‡æ–°å‘½å,但在目標分支中被移除。"
msgid "Confluence"
-msgstr ""
+msgstr "Confluence"
msgid "Confluence Cloud Workspace URL"
-msgstr ""
+msgstr "Confluence é›²å·¥ä½œå€ URL"
msgid "ConfluenceService|Confluence Workspace"
-msgstr ""
+msgstr "Confluence工作å€"
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
-msgstr ""
+msgstr "從å´é‚Šæ¬„éˆæŽ¥åˆ° Confluence 工作å€ã€‚"
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the \"Wiki\" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL."
-msgstr ""
+msgstr "從å´é‚Šæ¬„éˆæŽ¥åˆ° Confluence 工作å€ã€‚啟用此整åˆæœƒå°‡ã€ŒWikiã€å´é‚Šæ¬„éˆæŽ¥æ›¿æ›ç‚º Confluence 工作å€çš„éˆæŽ¥ã€‚ GitLab wiki ä»ç„¶åœ¨åŽŸå§‹ URL 上å¯ç”¨ã€‚"
msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
-msgstr ""
+msgstr "您的 GitLab wiki 在 %{wiki_link} ä»ç„¶å¯ç”¨ã€‚è¦é‡æ–°å•Ÿç”¨ GitLab wiki çš„éˆæŽ¥ï¼Œè«‹ç¦ç”¨æ­¤æ•´åˆã€‚"
msgid "Congratulations, your free trial is activated."
-msgstr ""
+msgstr "æ­å–œï¼Œæ‚¨çš„å…費試用已啟用。"
msgid "Connect"
-msgstr ""
+msgstr "連接"
msgid "Connect a Kubernetes Cluster"
-msgstr ""
+msgstr "連接 Kubernetes å¢é›†"
msgid "Connect a cluster"
-msgstr ""
+msgstr "連接å¢é›†"
msgid "Connect all repositories"
-msgstr ""
+msgstr "連線所有版本庫"
msgid "Connect repositories from GitHub"
-msgstr ""
+msgstr "從 Github 中匯入程å¼ç¢¼ç‰ˆæœ¬åº«"
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 ""
+msgstr "連接外部版本庫後,新æ交將會啟動CI/CDæµæ°´ç·šã€‚僅啟用CI/CD功能的Gitlab項目將會被建立。"
msgid "Connected"
-msgstr ""
+msgstr "已連接"
msgid "Connecting"
-msgstr ""
+msgstr "正在連線"
msgid "Connecting to terminal sync service"
-msgstr ""
+msgstr "連接到終端åŒæ­¥æœå‹™"
msgid "Connecting..."
-msgstr ""
+msgstr "正在連線..."
msgid "Connection failed"
-msgstr ""
+msgstr "連線失敗"
msgid "Connection failure"
-msgstr ""
+msgstr "連線失敗"
msgid "Connection timed out"
-msgstr ""
+msgstr "連線逾時"
msgid "Consistency guarantee method"
-msgstr ""
+msgstr "一致性ä¿éšœæ–¹æ³•"
msgid "Contact support"
-msgstr ""
+msgstr "è¯ç¹«æ”¯æ´"
msgid "Contacts"
-msgstr ""
+msgstr "è¯çµ¡äºº"
msgid "Container Registry"
-msgstr ""
+msgstr "容器映åƒåº«"
msgid "Container Scanning"
-msgstr ""
+msgstr "容器掃æ"
msgid "Container must be a project or a group."
-msgstr ""
+msgstr "容器必須是一個專案或一個群組。"
msgid "Container registry images"
-msgstr ""
+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 ""
+msgstr "æ­¤ GitLab 實體未啟用容器映åƒåº«ã€‚為了讓自動 DevOps 能é‹ä½œï¼Œè«‹è©¢å•ç®¡ç†å“¡å•Ÿç”¨ã€‚"
msgid "Container repositories"
-msgstr ""
+msgstr "容器映åƒåº«"
msgid "Container repository"
-msgstr ""
+msgstr "容器映åƒåº«"
msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
-msgstr ""
+msgstr "請訪å•%{linkStart}管ç†è¨­ç½®%{linkEnd}以啟用此功能。"
msgid "ContainerRegistry|%{count} Image repository"
msgid_plural "ContainerRegistry|%{count} Image repositories"
-msgstr[0] ""
+msgstr[0] "%{count}個映åƒå€‰åº«"
msgid "ContainerRegistry|%{count} Tag"
msgid_plural "ContainerRegistry|%{count} Tags"
-msgstr[0] ""
+msgstr[0] "%{count}個標籤"
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
-msgstr ""
+msgstr "%{strongStart}ç¦ç”¨%{strongEnd} - 標籤將ä¸æœƒè¢«è‡ªå‹•åˆªé™¤ã€‚"
msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
-msgstr ""
+msgstr "%{strongStart}啟用%{strongEnd} - 符åˆæ­¤é é¢ä¸Šè¦å‰‡çš„標籤將自動安排刪除。"
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
-msgstr ""
+msgstr "%{title}å·²æˆåŠŸå®‰æŽ’刪除"
msgid "ContainerRegistry|-- tags"
-msgstr ""
+msgstr "-- 標籤"
msgid "ContainerRegistry|Build an image"
-msgstr ""
+msgstr "構建映åƒ"
msgid "ContainerRegistry|CLI Commands"
-msgstr ""
+msgstr "CLI命令"
msgid "ContainerRegistry|Clean up image tags"
-msgstr ""
+msgstr "清ç†æ˜ åƒæª”標籤"
msgid "ContainerRegistry|Cleanup disabled"
-msgstr ""
+msgstr "清ç†å·²ç¦ç”¨æ¸…ç†"
msgid "ContainerRegistry|Cleanup in progress"
-msgstr ""
+msgstr "ContainerRegistry|正在進行清ç†"
msgid "ContainerRegistry|Cleanup incomplete"
-msgstr ""
+msgstr "ContainerRegistry|尚未完æˆæ¸…ç†"
msgid "ContainerRegistry|Cleanup is currently removing tags"
-msgstr ""
+msgstr "正在清ç†åˆªé™¤ä¸­çš„標籤"
msgid "ContainerRegistry|Cleanup is disabled for this project"
-msgstr ""
+msgstr "該專案已ç¦ç”¨æ¸…ç†"
msgid "ContainerRegistry|Cleanup is ongoing"
-msgstr ""
+msgstr "ContainerRegistry|正在清ç†ä¸­"
msgid "ContainerRegistry|Cleanup pending"
-msgstr ""
+msgstr "ContainerRegistry|等待清ç†ä¸­"
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
-msgstr ""
+msgstr "ContainerRegistry|標籤的清ç†æ”¿ç­–å·²åœç”¨"
msgid "ContainerRegistry|Cleanup policy successfully saved."
-msgstr ""
+msgstr "ContainerRegistry|清ç†ç­–略已æˆåŠŸå„²å­˜ã€‚"
msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
-msgstr ""
+msgstr "ContainerRegistry|已執行清ç†ï¼Œä½†æŸäº›æ¨™ç±¤æœªè¢«ç§»é™¤"
msgid "ContainerRegistry|Cleanup will run %{time}"
-msgstr ""
+msgstr "ContainerRegistry|å³å°‡åŸ·è¡Œæ¸…ç† %{time}"
msgid "ContainerRegistry|Cleanup will run soon"
-msgstr ""
+msgstr "ContainerRegistry|å³å°‡åŸ·è¡Œæ¸…ç†"
msgid "ContainerRegistry|Configuration digest: %{digest}"
-msgstr ""
+msgstr "ContainerRegistry|é…置摘è¦ï¼š %{digest}"
msgid "ContainerRegistry|Container Registry"
-msgstr ""
+msgstr "容器映åƒåº«"
msgid "ContainerRegistry|Copy build command"
-msgstr ""
+msgstr "複製構建指令"
msgid "ContainerRegistry|Copy image path"
-msgstr ""
+msgstr "複製映åƒæª”路徑"
msgid "ContainerRegistry|Copy login command"
-msgstr ""
+msgstr "複製登入指令"
msgid "ContainerRegistry|Copy push command"
-msgstr ""
+msgstr "複製推é€æŒ‡ä»¤"
msgid "ContainerRegistry|Delete image repository?"
-msgstr ""
+msgstr "ContainerRegistry|刪除映åƒæª”版本庫?"
msgid "ContainerRegistry|Delete selected tags"
-msgstr ""
+msgstr "ContainerRegistry|刪除é¸å–的標籤"
msgid "ContainerRegistry|Delete tag"
-msgstr ""
+msgstr "ContainerRegistry|刪除標籤"
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 "ContainerRegistry|刪除映åƒæª”版本庫會刪除裡é¢æ‰€æœ‰çš„映åƒæª”和標籤。此æ“作無法復原。請輸入以下內容進行確èªï¼š%{code}"
msgid "ContainerRegistry|Digest: %{imageId}"
-msgstr ""
+msgstr "ContainerRegistry|摘è¦ï¼š%{imageId}"
msgid "ContainerRegistry|Docker connection error"
-msgstr ""
+msgstr "Docker連接錯誤"
msgid "ContainerRegistry|Enable expiration policy"
-msgstr ""
+msgstr "ContainerRegistry|啟用逾期策略"
msgid "ContainerRegistry|Expiration policy is disabled."
-msgstr ""
+msgstr "å·²åœç”¨é€¾æœŸç­–略。"
msgid "ContainerRegistry|Expiration policy will run in %{time}"
-msgstr ""
+msgstr "ContainerRegistry|逾期策略將在 %{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 ""
+msgstr "如果您尚未登入,您需è¦ä½¿ç”¨æ‚¨çš„GitLab使用者å稱和密碼來進行身份èªè­‰ã€‚如果您啟用 %{twofaDocLinkStart}é›™é‡èº«ä»½é©—è­‰%{twofaDocLinkEnd} ,請使用%{personalAccessTokensDocLinkStart}個人存å–令牌(權æ–)%{personalAccessTokensDocLinkEnd}而ä¸æ˜¯å¯†ç¢¼ã€‚"
msgid "ContainerRegistry|Image repository deletion failed"
-msgstr ""
+msgstr "ContainerRegistry|映åƒæª”版本庫刪除失敗"
msgid "ContainerRegistry|Image repository not found"
-msgstr ""
+msgstr "ContainerRegistry|未找到映åƒæª”版本庫"
msgid "ContainerRegistry|Image repository temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}"
-msgstr ""
+msgstr "暫時無法將映åƒå­˜å„²åº«æ¨™è¨˜ç‚ºåˆªé™¤ã€‚ 請在幾分é˜å¾Œå†è©¦ä¸€æ¬¡ã€‚ %{docLinkStart}更多詳情%{docLinkEnd}"
msgid "ContainerRegistry|Image repository will be deleted"
-msgstr ""
+msgstr "ContainerRegistry|映åƒæª”版本庫將被刪除"
msgid "ContainerRegistry|Image repository with no name located at the project URL."
-msgstr ""
+msgstr "ContainerRegistry|在專案的 URL 中沒有å稱的映åƒæª”版本庫。"
msgid "ContainerRegistry|Image tags"
-msgstr ""
+msgstr "ContainerRegistry|映åƒæª”標籤"
msgid "ContainerRegistry|Invalid tag: missing manifest digest"
-msgstr ""
+msgstr "ContainerRegistry|無效標籤:缺少摘è¦æ¸…å–®"
msgid "ContainerRegistry|Keep tags matching:"
-msgstr ""
+msgstr "ContainerRegistry|ä¿ç•™æ¨™ç±¤åŒ¹é…:"
msgid "ContainerRegistry|Keep the most recent:"
-msgstr ""
+msgstr "ContainerRegistry|ä¿ç•™æœ€è¿‘的:"
msgid "ContainerRegistry|Keep these tags"
-msgstr ""
+msgstr "ContainerRegistry|ä¿ç•™é€™äº›æ¨™ç±¤"
msgid "ContainerRegistry|Last updated %{time}"
-msgstr ""
+msgstr "ContainerRegistry|上次更新時間 %{time}"
msgid "ContainerRegistry|Login"
-msgstr ""
+msgstr "ContainerRegistry|登入"
msgid "ContainerRegistry|Manifest digest: %{digest}"
-msgstr ""
+msgstr "ContainerRegistry|摘è¦æ¸…單:%{digest}"
msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
-msgstr ""
+msgstr "ContainerRegistry|缺少權é™æˆ–權é™ä¸è¶³ï¼Œå·²åœç”¨åˆªé™¤æŒ‰éˆ•"
msgid "ContainerRegistry|Next cleanup scheduled to run on:"
-msgstr ""
+msgstr "ContainerRegistry|下一次清ç†æŽ’程é‹è¡Œæ–¼ï¼š"
msgid "ContainerRegistry|Not yet scheduled"
-msgstr ""
+msgstr "ContainerRegistry|尚未安排"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
+msgstr "ContainerRegistry|注æ„:任何策略更新都會導致排程é‹è¡Œæ—¥æœŸå’Œæ™‚間發生變化"
msgid "ContainerRegistry|Partial cleanup complete"
-msgstr ""
+msgstr "部分清ç†å®Œæˆ"
msgid "ContainerRegistry|Please try different search criteria"
-msgstr ""
+msgstr "ContainerRegistry|請嘗試ä¸åŒçš„æœå°‹æ¢ä»¶"
msgid "ContainerRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "ContainerRegistry|已發布於 %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "ContainerRegistry|已於 %{date} %{time} 發布到 %{repositoryPath} 映åƒæª”版本庫"
msgid "ContainerRegistry|Push an image"
-msgstr ""
+msgstr "ContainerRegistry|推é€æ˜ åƒæª”"
msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
-msgstr ""
+msgstr "ContainerRegistry|請記得é‹è¡Œ %{docLinkStart}垃圾回收%{docLinkEnd}以從儲存空間中移除éŽæœŸçš„資料。"
msgid "ContainerRegistry|Remove repository"
-msgstr ""
+msgstr "移除映åƒåº«"
msgid "ContainerRegistry|Remove tag"
msgid_plural "ContainerRegistry|Remove tags"
-msgstr[0] ""
+msgstr[0] "移除標籤"
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "ContainerRegistry|移除匹é…標籤:"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "ContainerRegistry|移除早於以下時間的的標籤:"
msgid "ContainerRegistry|Remove these tags"
-msgstr ""
+msgstr "ContainerRegistry|移除這些標籤"
msgid "ContainerRegistry|Run cleanup:"
-msgstr ""
+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 "通éŽè‡ªå‹•å¾žå®¹å™¨è¨»å†Šåº«ä¸­åˆªé™¤ä¸¦ä¿ç•™æ‚¨æƒ³è¦çš„標籤來節çœå„²å­˜ç©ºé–“。%{linkStart}清ç†å·¥ä½œå¦‚何進行?%{linkEnd}"
msgid "ContainerRegistry|Set up cleanup"
-msgstr ""
+msgstr "設置清ç†"
msgid "ContainerRegistry|Show full path"
-msgstr ""
+msgstr "顯示完整路徑"
msgid "ContainerRegistry|Some tags were not deleted"
-msgstr ""
+msgstr "部分標籤未被刪除"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
-msgstr ""
+msgstr "å–得清ç†æ”¿ç­–時發生錯誤。"
msgid "ContainerRegistry|Something went wrong while fetching the image details."
-msgstr ""
+msgstr "å–å¾—é¡åƒè©³ç´°ä¿¡æ¯æ™‚發生錯誤。"
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
-msgstr ""
+msgstr "å–得倉庫列表時發生錯誤。"
msgid "ContainerRegistry|Something went wrong while fetching the tags list."
-msgstr ""
+msgstr "å–得標籤列表時發生錯誤。"
msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
-msgstr ""
+msgstr "將標籤標記為待刪除時發生錯誤。"
msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
-msgstr ""
+msgstr "將標籤標記為待刪除時發生錯誤。"
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
-msgstr ""
+msgstr "安排刪除%{title}時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
-msgstr ""
+msgstr "安排刪除映åƒæ™‚發生錯誤。"
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
-msgstr ""
+msgstr "更新清ç†ç­–略時發生錯誤。"
msgid "ContainerRegistry|Sorry, your filter produced no results."
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæ²’有符åˆç¯©é¸å™¨çš„任何çµæžœ."
msgid "ContainerRegistry|Tag successfully marked for deletion."
-msgstr ""
+msgstr "標籤已æˆåŠŸè¢«æ¨™è¨˜ç‚ºå¾…刪除。"
msgid "ContainerRegistry|Tags successfully marked for deletion."
-msgstr ""
+msgstr "標籤已æˆåŠŸè¢«æ¨™è¨˜ç‚ºå¾…刪除。"
msgid "ContainerRegistry|Tags temporarily cannot be marked for deletion. Please try again in a few minutes. %{docLinkStart}More details%{docLinkEnd}."
-msgstr ""
+msgstr "標籤暫時ä¸èƒ½è¢«æ¨™è¨˜ç‚ºåˆªé™¤ã€‚請幾分é˜å¾Œå†è©¦ã€‚%{docLinkStart}更多詳情%{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 "符åˆé€™äº›è¦å‰‡çš„標籤會被%{strongStart}ä¿ç•™%{strongEnd},å³ä½¿å®ƒå€‘與下é¢çš„刪除è¦å‰‡ç›¸åŒ¹é…。 %{secondStrongStart}最新的%{secondStrongEnd}標籤總是會被ä¿ç•™ã€‚"
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
+msgstr "符åˆé€™äº›è¦å‰‡çš„標籤將被%{strongStart}移除%{strongEnd},除éžä»¥ä¸Šä»»ä¸€è¦å‰‡è¦æ±‚ä¿ç•™å®ƒå€‘。"
msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "符åˆæ­¤æ­£å‰‡è¡¨é”å¼çš„å稱的標籤將會被ä¿ç•™ã€‚ %{linkStart}查看正則表é”å¼ç¤ºä¾‹%{linkEnd}"
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "符åˆæ­¤æ­£å‰‡è¡¨é”å¼çš„å稱的標籤將會被移除。 %{linkStart}查看正則表é”å¼ç¤ºä¾‹%{linkEnd}"
msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "清ç†ç­–略在刪除所有標籤之å‰é€¾æ™‚。 管ç†å“¡å¯ä»¥%{adminLinkStart}ç«‹å³åŸ·è¡Œæ‰‹å‹•æ¸…ç†%{adminLinkEnd}或者等待清ç†ç­–略下次自動é‹è¡Œã€‚%{docLinkStart}更多信æ¯%{docLinkEnd}"
msgid "ContainerRegistry|The cleanup will continue within %{time}. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "清ç†å·¥ä½œå°‡åœ¨ %{time} å…§æŒçºŒã€‚ %{linkStart}了解更多%{linkEnd}"
msgid "ContainerRegistry|The filter returned no results"
-msgstr ""
+msgstr "éŽæ¿¾å™¨æ²’有返回çµæžœ"
msgid "ContainerRegistry|The image repository could not be found."
-msgstr ""
+msgstr "找ä¸åˆ°æ˜ åƒå€‰åº«ã€‚"
msgid "ContainerRegistry|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
-msgstr ""
+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 "請求的映åƒå€‰åº«ä¸å­˜åœ¨æˆ–已被刪除。如果您èªç‚ºé€™æ˜¯ä¸€å€‹éŒ¯èª¤ï¼Œè«‹å˜—試é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr ""
+msgstr "該輸入值應å°æ–¼256個字元"
msgid "ContainerRegistry|There are no container images available in this group"
-msgstr ""
+msgstr "ç›®å‰ç¾¤çµ„沒有容器映åƒã€‚"
msgid "ContainerRegistry|There are no container images stored for this project"
-msgstr ""
+msgstr "ç›®å‰å°ˆæ¡ˆæ²’有容器映åƒã€‚"
msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
-msgstr ""
+msgstr "刪除此映åƒå€‰åº«æ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "ContainerRegistry|This image has no active tags"
-msgstr ""
+msgstr "此映åƒæ²’有有效的標籤"
msgid "ContainerRegistry|This image repository has failed to be deleted"
-msgstr ""
+msgstr "刪除該映åƒå€‰åº«å¤±æ•—"
msgid "ContainerRegistry|This image repository is scheduled for deletion"
-msgstr ""
+msgstr "已安排刪除該映åƒå€‰åº«"
msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "該映åƒå€‰åº«å°‡è¢«åˆªé™¤ã€‚ %{linkStart}瞭解更多。%{linkEnd}"
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
-msgstr ""
+msgstr "未啟用該專案的標籤清ç†ç­–略。"
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
-msgstr ""
+msgstr "è¦æ“´å¤§æœç´¢ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–刪除上é¢çš„éŽæ¿¾å™¨ã€‚"
msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr ""
+msgstr "連接到容器映åƒåº«å‡ºéŒ¯ã€‚請嘗試é‡æ–°è¼‰å…¥é é¢ã€‚如果此錯誤ä»ç„¶å­˜åœ¨ï¼Œè«‹æŸ¥çœ‹ %{docLinkStart}故障排除文件%{docLinkEnd}。"
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
-msgstr ""
+msgstr "在容器映åƒåº«ä¸­ï¼Œæ¯å€‹é …目都有自己的空間來儲存容器映åƒã€‚%{docLinkStart}更多訊æ¯%{docLinkEnd}"
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 ""
+msgstr "使用容器映åƒåº«ï¼Œæ¯å€‹é …目都å¯ä»¥æœ‰è‡ªå·±çš„空間來儲存其Docker映åƒã€‚å‘此群組中的項目推é€è‡³å°‘一個Docker映åƒå¾Œï¼Œæ˜ åƒå°‡æœƒåœ¨æ­¤è™•é¡¯ç¤ºã€‚%{docLinkStart}更多訊æ¯%{docLinkEnd}"
msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
-msgstr ""
+msgstr "å³å°‡ç§»é™¤%{item}個標籤,確定繼續嗎?"
msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
-msgstr ""
+msgstr "å³å°‡ç§»é™¤%{item},確定繼續嗎?"
msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
-msgstr ""
+msgstr "您將è¦ç§»é™¤å€‰åº«%{title},確èªå¾Œï¼Œæ­¤å€‰åº«å°‡è¢«æ°¸ä¹…刪除。"
msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
-msgstr ""
+msgstr "您å¯ä»¥é€éŽä»¥ä¸‹æŒ‡ä»¤å°‡æ˜ åƒåŠ å…¥åˆ°å®¹å™¨æ˜ åƒåº«ï¼š"
msgid "Content parsed with %{link}."
-msgstr ""
-
-msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "%{link}解æžçš„內容。"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
-msgstr ""
+msgstr "您必須æä¾› renderMarkdown 函數或自定義åºåˆ—化程åº"
msgid "Contents of .gitlab-ci.yml"
-msgstr ""
+msgstr ".gitlab-ci.yml的內容"
msgid "ContextCommits|Failed to create context commits. Please try again."
-msgstr ""
+msgstr "創建相關æ交失敗。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ContextCommits|Failed to create/remove context commits. Please try again."
-msgstr ""
+msgstr "創建/刪除相關æ交失敗。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ContextCommits|Failed to delete context commits. Please try again."
-msgstr ""
+msgstr "刪除相關æ交失敗。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "Continue"
-msgstr ""
+msgstr "繼續"
msgid "Continue editing"
-msgstr ""
+msgstr "繼續編輯"
msgid "Continue to the next step"
-msgstr ""
+msgstr "繼續下一步"
msgid "Continuous Integration and Deployment"
-msgstr ""
+msgstr "æŒçºŒæ•´åˆå’Œéƒ¨ç½²"
msgid "Contribute to GitLab"
-msgstr ""
+msgstr "è²¢ç»çµ¦ GitLab"
msgid "Contribution"
-msgstr ""
+msgstr "è²¢ç»"
msgid "Contribution Analytics"
-msgstr ""
+msgstr "è²¢ç»åº¦åˆ†æž"
msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
-msgstr ""
+msgstr "建立%{created_count}個,關閉%{closed_count}個。"
msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
-msgstr ""
+msgstr "已建立%{created_count}個,已åˆä½µ%{merged_count}個,已關閉%{closed_count}個。"
msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
-msgstr ""
+msgstr "%{pushes}次推é€ï¼Œè¶…éŽäº†%{people}個貢ç»è€…çš„%{commits}次æ交。"
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
-msgstr ""
+msgstr "從 %{start_date} 開始å°è­°é¡Œã€åˆä½µè«‹æ±‚åŠæŽ¨é€äº‹ä»¶çš„è²¢ç»çµ±è¨ˆ"
msgid "ContributionAnalytics|Issues"
-msgstr ""
+msgstr "議題"
msgid "ContributionAnalytics|Last 3 months"
-msgstr ""
+msgstr "最近 3 個月"
msgid "ContributionAnalytics|Last month"
-msgstr ""
+msgstr "最近 1 個月"
msgid "ContributionAnalytics|Last week"
-msgstr ""
+msgstr "最近 1 週"
msgid "ContributionAnalytics|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "ContributionAnalytics|No issues for the selected time period."
-msgstr ""
+msgstr "é¸å–的時間範åœæ²’有議題。"
msgid "ContributionAnalytics|No merge requests for the selected time period."
-msgstr ""
+msgstr "é¸å–的時間範åœæ²’有åˆä½µè«‹æ±‚。"
msgid "ContributionAnalytics|No pushes for the selected time period."
-msgstr ""
+msgstr "é¸å–的時間範åœæ²’有推é€ã€‚"
msgid "Contributions for %{calendar_date}"
-msgstr ""
+msgstr "%{calendar_date}çš„è²¢ç»"
msgid "Contributions per group member"
-msgstr ""
+msgstr "群組æˆå“¡è²¢ç»è©³æƒ…"
msgid "Contributor"
-msgstr ""
+msgstr "è²¢ç»è€…"
msgid "Contributors"
msgstr "è²¢ç»è€…"
@@ -10158,4371 +10272,4404 @@ msgid "Control emails linked to your account"
msgstr "控制與您帳號關è¯çš„é›»å­éƒµä»¶"
msgid "Control how the GitLab Package Registry functions."
-msgstr ""
+msgstr "控制 GitLab 軟體套件倉庫如何é‹ä½œã€‚"
msgid "Control whether to display customer experience improvement content and third-party offers in GitLab."
-msgstr ""
+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 ""
+msgstr "控制使用此專案的 CI_JOB_TOKEN CI/CD 變é‡é€²è¡Œèº«ä»½é©—證的 API 請求å¯ä»¥è¨ªå•å“ªäº›å°ˆæ¡ˆã€‚ç¦ç”¨æ­¤åŠŸèƒ½å­˜åœ¨å®‰å…¨é¢¨éšªï¼Œå› ç‚ºæœªç¶“授權的專案å¯èƒ½æœƒå˜—試存å–活動令牌(權æ–)ä¸¦è¨ªå• API。"
msgid "Cookie domain"
-msgstr ""
+msgstr "Cookie域"
msgid "Copied"
-msgstr ""
+msgstr "已複製"
msgid "Copied labels and milestone from %{source_issuable_reference}."
-msgstr ""
+msgstr "已從%{source_issuable_reference}複製標記和里程碑。"
msgid "Copy"
-msgstr ""
+msgstr "複製"
msgid "Copy %{accessTokenType}"
-msgstr ""
+msgstr "複製 %{accessTokenType}"
msgid "Copy %{http_label} clone URL"
-msgstr ""
+msgstr "複製 %{http_label} 仿製(clone) URL"
msgid "Copy %{name}"
-msgstr ""
+msgstr "複製 %{name}"
msgid "Copy %{protocol} clone URL"
-msgstr ""
+msgstr "複製 %{protocol} 仿製(clone) URL"
msgid "Copy %{type}"
-msgstr ""
+msgstr "複製 %{type}"
msgid "Copy ID"
-msgstr ""
+msgstr "複製ID"
msgid "Copy KRB5 clone URL"
-msgstr ""
+msgstr "複製KRB5仿製U(clone)URL"
msgid "Copy SSH clone URL"
-msgstr ""
+msgstr "複製SSH仿製(clone)URL"
msgid "Copy SSH public key"
-msgstr ""
+msgstr "複製SSH公鑰"
msgid "Copy URL"
-msgstr ""
+msgstr "複製連çµ"
msgid "Copy audio URL"
-msgstr ""
+msgstr "複製音頻URL"
msgid "Copy branch name"
-msgstr ""
+msgstr "複製分支å稱"
msgid "Copy code"
-msgstr ""
+msgstr "複製代碼"
msgid "Copy codes"
-msgstr ""
+msgstr "複製代碼"
msgid "Copy command"
-msgstr ""
+msgstr "複製指令"
msgid "Copy commands"
-msgstr ""
+msgstr "複製指令"
msgid "Copy commit SHA"
-msgstr ""
+msgstr "複製æ交SHA"
msgid "Copy environment"
-msgstr ""
+msgstr "複製環境"
msgid "Copy evidence SHA"
-msgstr ""
+msgstr "複製 SHA 證明"
msgid "Copy failed. Please manually copy the value."
-msgstr ""
+msgstr "複製失敗。請手動複製該值。"
msgid "Copy file contents"
-msgstr ""
+msgstr "複製文件內容"
msgid "Copy file path"
-msgstr ""
+msgstr "複製文件路徑"
msgid "Copy image URL"
-msgstr ""
+msgstr "複製映åƒæª”URL"
msgid "Copy issue URL to clipboard"
-msgstr ""
+msgstr "將議題(issue)URL複製到剪貼簿"
msgid "Copy key"
-msgstr ""
+msgstr "複製金鑰"
msgid "Copy labels and milestone from %{source_issuable_reference}."
-msgstr ""
+msgstr "從 %{source_issuable_reference} 複製標記和里程碑。"
msgid "Copy labels and milestone from other issue or merge request in this project"
-msgstr ""
+msgstr "從目å‰å°ˆæ¡ˆä¸­å…¶ä»–議題或åˆä½µè«‹æ±‚複製標記和里程碑"
msgid "Copy link"
msgstr "複製連çµ"
msgid "Copy link URL"
-msgstr ""
+msgstr "複製éˆçµ URL"
msgid "Copy link to chart"
-msgstr ""
+msgstr "å°‡éˆçµè¤‡è£½åˆ°åœ–表"
msgid "Copy reference"
-msgstr ""
+msgstr "複製åƒç…§å¼•ç”¨"
msgid "Copy secret"
-msgstr ""
+msgstr "複製密碼"
msgid "Copy source branch name"
-msgstr ""
+msgstr "複製來æºåˆ†æ”¯å稱"
msgid "Copy the code below to implement tracking in your application:"
-msgstr ""
+msgstr "複製以下程å¼ç¢¼ä»¥åœ¨æ‚¨çš„應用程å¼ä¸­åŸ·è¡Œè¿½è¹¤ï¼š"
msgid "Copy this registration token."
-msgstr ""
+msgstr "複製此註冊憑證。"
msgid "Copy to clipboard"
-msgstr ""
+msgstr "複製到剪貼簿"
msgid "Copy token"
-msgstr ""
+msgstr "複製權æ–"
msgid "Copy trigger token"
-msgstr ""
+msgstr "複製觸發權æ–"
msgid "Copy value"
-msgstr ""
+msgstr "複製數值"
msgid "Copy video URL"
-msgstr ""
+msgstr "複製影åƒURL"
msgid "Corpus Management"
-msgstr ""
+msgstr "語詞庫管ç†"
msgid "Corpus Management|Are you sure you want to delete the corpus?"
-msgstr ""
+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 ""
+msgstr "模糊測試使用語詞庫來æ高覆蓋率。語詞庫文件å¯ä»¥æ‰‹å‹•å‰µå»ºæˆ–自動生æˆã€‚%{linkStart}瞭解更多%{linkEnd}"
msgid "CorpusManagement|Actions"
-msgstr ""
+msgstr "動作"
msgid "CorpusManagement|Corpus file"
-msgstr ""
+msgstr "語詞庫檔案"
msgid "CorpusManagement|Corpus files are used in coverage-guided fuzz testing as seed inputs to improve testing."
-msgstr ""
+msgstr "語詞庫檔案用於覆蓋率引導的模糊測試,作為種å­è¼¸å…¥ä¾†æ”¹é€²æ¸¬è©¦ã€‚"
msgid "CorpusManagement|Corpus files must be in *.zip format. Maximum 5 GB"
-msgstr ""
+msgstr "語詞庫檔案必須以 *.zip æ ¼å¼ä¸Šå‚³ï¼ˆæœ€å¤§ 5 GB)"
msgid "CorpusManagement|Corpus name"
-msgstr ""
+msgstr "語詞庫å稱"
msgid "CorpusManagement|Currently, there are no uploaded or generated corpuses."
-msgstr ""
+msgstr "ç›®å‰æ²’有已上傳或自動生æˆçš„語詞庫。"
msgid "CorpusManagement|File too large, Maximum 5 GB"
-msgstr ""
+msgstr "檔案éŽå¤§ï¼ˆæœ€å¤§ 5GB)"
msgid "CorpusManagement|Filename can contain only lowercase letters (a-z), uppercase letter (A-Z), numbers (0-9), dots (.), hyphens (-), or underscores (_)."
-msgstr ""
+msgstr "檔案å稱åªèƒ½åŒ…å«å¤§å¯«ï¼ˆA-Z)和å°å¯«ï¼ˆa-z)英文字æ¯ã€æ•¸å­—(0-9)ã€é»žè™Ÿï¼ˆ.)ã€æ©«æ§“(-)或下劃線(_)。"
msgid "CorpusManagement|Fuzz testing corpus management"
-msgstr ""
+msgstr "模糊測試語詞庫管ç†"
msgid "CorpusManagement|Last updated"
-msgstr ""
+msgstr "語詞庫管ç†|最後更新"
msgid "CorpusManagement|Last used"
-msgstr ""
+msgstr "語詞庫管ç†|上次使用"
msgid "CorpusManagement|Latest Job:"
-msgstr ""
+msgstr "語詞庫管ç†|最新作業:"
msgid "CorpusManagement|Manage your fuzz testing corpus files"
-msgstr ""
+msgstr "管ç†æ‚¨çš„模糊測試語詞庫文件"
msgid "CorpusManagement|New corpus"
-msgstr ""
+msgstr "新建語詞庫"
msgid "CorpusManagement|New upload"
-msgstr ""
+msgstr "語詞庫管ç†|新上傳"
msgid "CorpusManagement|Not Set"
-msgstr ""
+msgstr "語詞庫管ç†|未設定"
msgid "CorpusManagement|Target"
-msgstr ""
+msgstr "語詞庫管ç†|目標"
msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
-msgstr ""
+msgstr "語詞庫管ç†|è¦ä½¿ç”¨æ­¤èªžè©žåº«ï¼Œè«‹ç·¨è¼¯ç›¸æ‡‰çš„ YAML 檔案"
msgid "CorpusManagement|Total Size: %{totalSize}"
-msgstr ""
+msgstr "語詞庫管ç†|總大å°ï¼š %{totalSize}"
msgid "Could not add admins as members"
-msgstr ""
+msgstr "無法將管ç†å“¡åŠ å…¥ç‚ºæˆå“¡"
msgid "Could not apply %{name} command."
-msgstr ""
+msgstr "無法套用 %{name} 命令。"
msgid "Could not apply %{name} command. %{message}."
-msgstr ""
+msgstr "無法套用 %{name} 命令。 %{message}。"
msgid "Could not authorize chat nickname. Try again!"
-msgstr ""
+msgstr "無法授權èŠå¤©æš±ç¨±ã€‚å†è©¦ä¸€æ¬¡ï¼"
msgid "Could not change HEAD: branch '%{branch}' does not exist"
-msgstr ""
+msgstr "無法變更HEAD:分支「%{branch}ã€ä¸å­˜åœ¨"
msgid "Could not commit. An unexpected error occurred."
-msgstr ""
+msgstr "無法æ交。發生一個éžé æœŸçš„錯誤。"
msgid "Could not connect to FogBugz, check your URL"
-msgstr ""
+msgstr "無法連接到 FogBugz,請檢查您的 URL"
msgid "Could not connect to Sentry. Refresh the page to try again."
-msgstr ""
+msgstr "無法連線到 Sentry。é‡æ–°æ•´ç†é é¢ï¼Œå†è©¦ä¸€æ¬¡ã€‚"
msgid "Could not connect to Web IDE file mirror service."
-msgstr ""
+msgstr "無法連接到Web IDE的文件é¡åƒæœå‹™ã€‚"
msgid "Could not create Wiki Repository at this time. Please try again later."
-msgstr ""
+msgstr "ç›®å‰ç„¡æ³•å»ºç«‹ Wiki 版本庫。請ç¨å¾Œå†è©¦ã€‚"
msgid "Could not create environment"
-msgstr ""
+msgstr "無法建立環境"
msgid "Could not create group"
-msgstr ""
+msgstr "無法建立群組"
msgid "Could not create issue"
-msgstr ""
+msgstr "無法建立議題"
msgid "Could not create project"
-msgstr ""
+msgstr "無法建立專案"
msgid "Could not create wiki page"
-msgstr ""
+msgstr "無法建立 wiki é é¢"
msgid "Could not delete chat nickname %{chat_name}."
-msgstr ""
+msgstr "無法刪除èŠå¤©æš±ç¨± %{chat_name}。"
msgid "Could not delete wiki page"
-msgstr ""
+msgstr "無法刪除 wiki é é¢"
msgid "Could not draw the lines for job relationships"
-msgstr ""
+msgstr "無法為作業繪製關è¯ç·š"
msgid "Could not fetch policy because existing policy YAML is invalid"
-msgstr ""
+msgstr "無法å–得政策,因為ç¾æœ‰æ”¿ç­– YAML 無效"
msgid "Could not fetch training providers. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法å–得培訓æ供者。請é‡æ–°è¼‰å…¥æ­¤é ï¼Œæˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "Could not find design."
-msgstr ""
+msgstr "找ä¸åˆ°è¨­è¨ˆã€‚"
msgid "Could not find iteration"
-msgstr ""
+msgstr "無法找到迭代"
msgid "Could not get the data properly"
-msgstr ""
+msgstr "無法å–得資料屬性"
msgid "Could not load the user chart. Please refresh the page to try again."
-msgstr ""
+msgstr "無法載入使用者圖表。請é‡æ–°æ•´ç†é é¢ï¼Œå†è©¦ä¸€æ¬¡ã€‚"
msgid "Could not load usage counts. Please refresh the page to try again."
-msgstr ""
+msgstr "無法載入使用計數,請é‡æ–°è¼‰å…¥é é¢é‡è©¦ã€‚"
msgid "Could not remove %{user} from %{group}. Cannot remove last group owner."
-msgstr ""
+msgstr "無法從 %{group} 中移除 %{user} ,無法移除最後一個群組的æ“有者。"
msgid "Could not remove %{user} from %{group}. User is not a group member."
-msgstr ""
+msgstr "無法從%{group}中移除%{user},使用者ä¸æ˜¯ç¾¤çµ„æˆå“¡ã€‚"
msgid "Could not remove the trigger."
-msgstr ""
+msgstr "無法刪除觸發器。"
msgid "Could not restore the group"
-msgstr ""
+msgstr "無法還原群組"
msgid "Could not revoke access token %{access_token_name}."
-msgstr ""
+msgstr "無法撤消訪å•ä»¤ç‰Œ(權æ–) %{access_token_name}。"
msgid "Could not revoke impersonation token %{token_name}."
-msgstr ""
+msgstr "無法復原身份模擬令牌(權æ–) %{token_name}。"
msgid "Could not revoke personal access token %{personal_access_token_name}."
-msgstr ""
+msgstr "無法復原個人存å–令牌(權æ–) %{personal_access_token_name}。"
msgid "Could not save configuration. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法ä¿å­˜çµ„態,請é‡æ–°è¼‰å…¥æ­¤é ï¼Œæˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "Could not save group ID"
-msgstr ""
+msgstr "無法儲存群組 ID"
msgid "Could not save project ID"
-msgstr ""
+msgstr "無法儲存專案ID"
msgid "Could not save prometheus manual configuration"
-msgstr ""
+msgstr "無法儲存prometheus手動設定"
msgid "Could not update the LDAP settings"
-msgstr ""
+msgstr "無法更新LDAP設定"
msgid "Could not update wiki page"
-msgstr ""
+msgstr "無法更新 wiki é é¢"
msgid "Could not upload your designs as one or more files uploaded are not supported."
-msgstr ""
+msgstr "無法上傳您的設計,一個或數個已上傳的檔案ä¸è¢«æ”¯æ´ã€‚"
msgid "Couldn't assign policy to project or group"
-msgstr ""
+msgstr "無法將策略分é…給專案或群組"
msgid "Country"
-msgstr ""
+msgstr "國家"
msgid "Coverage"
-msgstr ""
+msgstr "覆蓋率"
msgid "Coverage Fuzzing"
-msgstr ""
+msgstr "覆蓋率模糊測試"
msgid "Create"
-msgstr ""
+msgstr "建立"
msgid "Create %{environment}"
-msgstr ""
+msgstr "建立 %{environment}"
msgid "Create %{humanized_resource_name}"
-msgstr ""
+msgstr "建立 %{humanized_resource_name}"
msgid "Create %{type}"
-msgstr ""
+msgstr "建立 %{type}"
msgid "Create %{workspace} label"
-msgstr ""
-
-msgid "Create Google Cloud project"
-msgstr ""
+msgstr "建立 %{workspace} 標籤"
msgid "Create New Directory"
-msgstr ""
+msgstr "建立新目錄"
msgid "Create New Domain"
-msgstr ""
+msgstr "建立新å€åŸŸ"
msgid "Create a GitLab account first, and then connect it to your %{label} account."
-msgstr ""
+msgstr "請先建立一個GitLab帳號,然後將其連接到您的 %{label} 帳號。"
msgid "Create a Kubernetes cluster"
-msgstr ""
+msgstr "建立 Kubernetes å¢é›†"
msgid "Create a Mattermost team for this group"
-msgstr ""
+msgstr "為這個群組建立一個Mattermost團隊"
msgid "Create a cluster"
-msgstr ""
+msgstr "建立å¢é›†"
msgid "Create a group"
-msgstr ""
+msgstr "建立群組"
msgid "Create a merge request"
-msgstr ""
+msgstr "建立一個åˆä½µç”³è«‹"
msgid "Create a new %{codeStart}.gitlab-ci.yml%{codeEnd} file at the root of the repository to get started."
-msgstr ""
+msgstr "在版本庫的根目錄創建一個新的 %{codeStart}.gitlab-ci.yml%{codeEnd} 文件以開始æ“作。"
msgid "Create a new branch"
-msgstr ""
+msgstr "建立一個新分支"
msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
-msgstr ""
+msgstr "ç›®å‰å°šç„¡æ–‡ä»¶ï¼Œè«‹å…ˆå»ºç«‹ä¸€å€‹æ–°æ–‡ä»¶ï¼Œç„¶å¾Œæ‚¨å°‡èƒ½å¤ æ交您的變更。"
msgid "Create a new issue"
-msgstr ""
+msgstr "建立新議題"
msgid "Create a new project"
-msgstr ""
+msgstr "建立一個新專案"
msgid "Create a new repository"
-msgstr ""
+msgstr "建立一個新版本庫"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
-msgstr ""
+msgstr "在帳號上建立個人存å–令牌(權æ–),並以此 %{protocol} 來 pull 或 push。"
msgid "Create a project"
-msgstr ""
+msgstr "建立一個專案"
msgid "Create an account using:"
-msgstr ""
+msgstr "使用以下方å¼å»ºç«‹å¸³è™Ÿï¼š"
msgid "Create an incident. Incidents are created for each alert triggered."
-msgstr ""
+msgstr "建立一個事件(incident),æ¯å€‹è§¸ç™¼çš„警報都會被建立一個事件(Incidents)。"
msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "請建立並æ供您GitHub%{link_start}的個人訪å•ä»¤ç‰Œ(權æ–)%{link_end},您需è¦é¸æ“‡%{code_open}repo%{code_close}範åœï¼Œé€™æ¨£æˆ‘們æ‰å¯ä»¥å‘您顯示å¯å°Žå…¥çš„公共和ç§æœ‰ç‰ˆæœ¬åº«çš„列表。"
msgid "Create branch"
-msgstr ""
+msgstr "建立分支"
msgid "Create commit"
-msgstr ""
+msgstr "建立æ交"
msgid "Create commit..."
-msgstr ""
+msgstr "建立æ交..."
msgid "Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "更快的建立共åŒæ–‡ä»¶ä¸¦ä½¿å…¶æ ¼å¼æ¨™æº–化。"
msgid "Create confidential merge request"
-msgstr ""
+msgstr "建立機密åˆä½µè«‹æ±‚"
msgid "Create confidential merge request and branch"
-msgstr ""
+msgstr "建立機密åˆä½µè«‹æ±‚åŠåˆ†æ”¯"
msgid "Create custom type"
-msgstr ""
+msgstr "建立自定義型別"
msgid "Create directory"
-msgstr ""
+msgstr "建立目錄"
msgid "Create empty repository"
-msgstr ""
+msgstr "建立空的版本庫"
msgid "Create epic"
-msgstr ""
+msgstr "建立å²è©©"
msgid "Create file"
-msgstr ""
+msgstr "建立文件"
msgid "Create from"
-msgstr ""
+msgstr "建立從"
msgid "Create group"
-msgstr ""
+msgstr "建立群組"
msgid "Create group label"
msgstr "建立群組標籤"
msgid "Create issue"
-msgstr ""
+msgstr "建立議題"
msgid "Create issue to resolve all threads"
-msgstr ""
+msgstr "建立議題(issue)來解決所有主題"
msgid "Create iteration"
-msgstr ""
+msgstr "建立迭代"
msgid "Create label"
-msgstr ""
+msgstr "建立標記"
msgid "Create list"
-msgstr ""
+msgstr "建立清單"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr ""
+msgstr "從標記建立列表,å«æœ‰è©²æ¨™è¨˜çš„議題將出ç¾åœ¨ç›¸æ‡‰çš„列中。"
msgid "Create merge request"
-msgstr ""
+msgstr "建立åˆä½µè¦æ±‚"
msgid "Create merge request and branch"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚åŠåˆ†æ”¯"
msgid "Create milestone"
-msgstr ""
+msgstr "建立里程碑"
msgid "Create new"
-msgstr ""
+msgstr "建立新的"
msgid "Create new %{name} by email"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶å»ºç«‹æ–°çš„ %{name}"
msgid "Create new Value Stream"
-msgstr ""
+msgstr "創建新的價值æµ"
msgid "Create new branch"
-msgstr ""
+msgstr "建立新分支"
msgid "Create new confidential %{issuableType}"
-msgstr ""
+msgstr "建立新的機密%{issuableType}"
msgid "Create new directory"
-msgstr ""
+msgstr "建立新目錄"
msgid "Create new file"
-msgstr ""
+msgstr "建立新檔案"
msgid "Create new file or directory"
-msgstr ""
+msgstr "建立新文件或目錄"
msgid "Create new label"
-msgstr ""
+msgstr "建立新標記"
msgid "Create new project"
-msgstr ""
+msgstr "建立新專案"
msgid "Create new..."
-msgstr ""
+msgstr "建立新…"
msgid "Create one"
-msgstr ""
+msgstr "建立一個"
msgid "Create or close an issue."
-msgstr ""
+msgstr "建立或關閉議題。"
msgid "Create or import your first project"
-msgstr ""
+msgstr "建立或匯入您的第一個專案"
msgid "Create project"
-msgstr ""
+msgstr "建立專案"
msgid "Create project label"
-msgstr ""
+msgstr "建立專案標記"
msgid "Create release"
-msgstr ""
+msgstr "建立版本發布"
msgid "Create requirement"
-msgstr ""
+msgstr "建立需求"
msgid "Create service account"
-msgstr ""
+msgstr "建立æœå‹™å¸³è™Ÿ"
msgid "Create snippet"
-msgstr ""
+msgstr "創建程å¼ç¢¼ç‰‡æ®µ"
msgid "Create tag %{tagName}"
-msgstr ""
+msgstr "建立標籤%{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "建立主題"
msgid "Create user"
-msgstr ""
+msgstr "建立使用者"
msgid "Create wildcard: %{searchTerm}"
-msgstr ""
+msgstr "建立è¬ç”¨å­—元:%{searchTerm}"
msgid "Create your first page"
-msgstr ""
+msgstr "建立您的第一個é é¢"
msgid "Create your group"
-msgstr ""
+msgstr "建立您的群組"
msgid "Create, update, or delete a merge request."
-msgstr ""
+msgstr "建立ã€æ›´æ–°æˆ–刪除åˆä½µè«‹æ±‚。"
msgid "Create/import your first project"
-msgstr ""
+msgstr "建立/匯入您的第一個專案"
msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
-msgstr ""
+msgstr "您無權在此群組中建立å­ç¾¤çµ„。"
msgid "CreateGroup|You don’t have permission to create groups."
-msgstr ""
+msgstr "您無權建立群組。"
msgid "CreateTag|Tag"
-msgstr ""
+msgstr "標籤"
msgid "CreateValueStreamForm|%{name} (default)"
-msgstr ""
+msgstr "CreateValueStreamForm|%{name}(é è¨­å€¼ï¼‰"
msgid "CreateValueStreamForm|'%{name}' Value Stream created"
-msgstr ""
+msgstr "CreateValueStreamForm|%{name} 價值æµå·²å»ºç«‹"
msgid "CreateValueStreamForm|'%{name}' Value Stream saved"
-msgstr ""
+msgstr "CreateValueStreamForm|%{name} 價值æµå·²å„²å­˜"
msgid "CreateValueStreamForm|Add another stage"
-msgstr ""
+msgstr "CreateValueStreamForm|新增å¦ä¸€å€‹éšŽæ®µ"
msgid "CreateValueStreamForm|Add stage"
-msgstr ""
+msgstr "CreateValueStreamForm|新增階段"
msgid "CreateValueStreamForm|All default stages are currently visible"
-msgstr ""
+msgstr "CreateValueStreamForm|所有é è¨­éšŽæ®µç›®å‰éƒ½çœ‹å¾—見"
msgid "CreateValueStreamForm|Code stage start"
-msgstr ""
+msgstr "CreateValueStreamForm|程å¼ç¢¼éšŽæ®µé–‹å§‹"
msgid "CreateValueStreamForm|Create from default template"
-msgstr ""
+msgstr "CreateValueStreamForm|從é è¨­ç¯„本建立"
msgid "CreateValueStreamForm|Create from no template"
-msgstr ""
+msgstr "CreateValueStreamForm|從無範本建立"
msgid "CreateValueStreamForm|Create new Value Stream"
-msgstr ""
+msgstr "CreateValueStreamForm|建立新的價值æµ"
msgid "CreateValueStreamForm|Create value stream"
-msgstr ""
+msgstr "CreateValueStreamForm|建立價值æµ"
msgid "CreateValueStreamForm|Default stages"
-msgstr ""
+msgstr "CreateValueStreamForm|é è¨­éšŽæ®µ"
msgid "CreateValueStreamForm|Default stages can only be hidden or re-ordered"
-msgstr ""
+msgstr "é è¨­éšŽæ®µåªèƒ½éš±è—或é‡æ–°æŽ’åº"
msgid "CreateValueStreamForm|Edit value stream"
-msgstr ""
+msgstr "編輯價值æµ"
msgid "CreateValueStreamForm|Editing stage"
-msgstr ""
+msgstr "編輯階段"
msgid "CreateValueStreamForm|End event"
-msgstr ""
+msgstr "çµæŸäº‹ä»¶"
msgid "CreateValueStreamForm|End event label"
-msgstr ""
+msgstr "çµæŸäº‹ä»¶æ¨™è¨˜"
msgid "CreateValueStreamForm|End event: "
-msgstr ""
+msgstr "çµæŸäº‹ä»¶ï¼š "
msgid "CreateValueStreamForm|Enter stage name"
-msgstr ""
+msgstr "輸入階段å稱"
msgid "CreateValueStreamForm|Enter value stream name"
-msgstr ""
+msgstr "輸入價值æµå稱"
msgid "CreateValueStreamForm|Issue stage end"
-msgstr ""
+msgstr "è­°é¡Œ(issue)階段çµæŸ"
msgid "CreateValueStreamForm|Maximum length %{maxLength} characters"
-msgstr ""
+msgstr "最大長度 %{maxLength} 個字元"
msgid "CreateValueStreamForm|Name is required"
-msgstr ""
+msgstr "å稱為必填"
msgid "CreateValueStreamForm|New stage"
-msgstr ""
+msgstr "新階段"
msgid "CreateValueStreamForm|Plan stage start"
-msgstr ""
+msgstr "計畫階段開始"
msgid "CreateValueStreamForm|Please select a start event first"
-msgstr ""
+msgstr "è«‹å…ˆé¸æ“‡ä¸€å€‹å•Ÿå§‹äº‹ä»¶"
msgid "CreateValueStreamForm|Please select an end event"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹çµæŸäº‹ä»¶"
msgid "CreateValueStreamForm|Recover hidden stage"
-msgstr ""
+msgstr "æ¢å¾©éš±è—階段"
msgid "CreateValueStreamForm|Restore defaults"
-msgstr ""
+msgstr "還原é è¨­å€¼"
msgid "CreateValueStreamForm|Restore stage"
-msgstr ""
+msgstr "還原階段"
msgid "CreateValueStreamForm|Save value stream"
-msgstr ""
+msgstr "儲存價值æµ"
msgid "CreateValueStreamForm|Select end event"
-msgstr ""
+msgstr "é¸æ“‡çµæŸäº‹ä»¶"
msgid "CreateValueStreamForm|Select start event"
-msgstr ""
+msgstr "é¸æ“‡é–‹å§‹äº‹ä»¶"
msgid "CreateValueStreamForm|Stage %{index}"
-msgstr ""
+msgstr "階段 %{index}"
msgid "CreateValueStreamForm|Stage name already exists"
-msgstr ""
+msgstr "階段å稱已經存在"
msgid "CreateValueStreamForm|Stage name is required"
-msgstr ""
+msgstr "階段å稱為必填"
msgid "CreateValueStreamForm|Start event"
-msgstr ""
+msgstr "開始事件"
msgid "CreateValueStreamForm|Start event changed, please select a valid end event"
-msgstr ""
+msgstr "開始事件發生變更,請é¸æ“‡ä¸€å€‹æœ‰æ•ˆçš„çµæŸäº‹ä»¶"
msgid "CreateValueStreamForm|Start event label"
-msgstr ""
+msgstr "開始事件標記"
msgid "CreateValueStreamForm|Start event: "
-msgstr ""
+msgstr "開始事件: "
msgid "CreateValueStreamForm|Update stage"
-msgstr ""
+msgstr "更新階段"
msgid "CreateValueStreamForm|Value Stream name"
-msgstr ""
+msgstr "價值æµå稱"
msgid "Created"
-msgstr ""
+msgstr "建立時間"
msgid "Created %{epicTimeagoDate}"
-msgstr ""
+msgstr "已建立於 %{epicTimeagoDate}"
msgid "Created %{timestamp}"
-msgstr ""
+msgstr "已建立於%{timestamp}"
msgid "Created At"
-msgstr ""
+msgstr "已建立於"
msgid "Created On"
-msgstr ""
+msgstr "已建立於"
msgid "Created a branch and a merge request to resolve this issue."
-msgstr ""
+msgstr "已建立了一個分支和一個åˆä½µè«‹æ±‚來解決此議題。"
msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr ""
+msgstr "已建立分支「%{branch_name}ã€èˆ‡åˆä½µè«‹æ±‚來解決此議題。"
msgid "Created by %{job}"
-msgstr ""
+msgstr "由%{job}建立"
msgid "Created by me"
-msgstr ""
+msgstr "由我建立"
msgid "Created by:"
-msgstr ""
+msgstr "建立者:"
msgid "Created compliance violations if any were found"
-msgstr ""
+msgstr "如果發ç¾ä»»ä½•é•è¦è¡Œç‚ºï¼Œå‰‡è©²å‰µå»ºä¸ç¬¦è¦ç¯„"
msgid "Created date"
-msgstr ""
+msgstr "建立日期"
msgid "Created issue %{issueLink}"
-msgstr ""
+msgstr "建立議題 %{issueLink}"
msgid "Created issue %{issueLink} at %{projectLink}"
-msgstr ""
+msgstr "在 %{projectLink} 中建立議題 %{issueLink}"
msgid "Created merge request %{mergeRequestLink}"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚ %{mergeRequestLink}"
msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
-msgstr ""
+msgstr "在 %{projectLink} 中建立åˆä½µè«‹æ±‚ %{mergeRequestLink}"
msgid "Created on"
-msgstr ""
+msgstr "建立於"
msgid "Created on %{created_at}"
-msgstr ""
+msgstr "建立於%{created_at}"
msgid "Created on:"
-msgstr ""
+msgstr "建立於:"
msgid "Creates a branch and a merge request to resolve this issue."
-msgstr ""
+msgstr "建立分支和åˆä½µè«‹æ±‚來解決這個議題。"
msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr ""
+msgstr "建立分支「%{branch_name}ã€å’Œåˆä½µè«‹æ±‚以解決此議題。"
msgid "Creating"
-msgstr ""
+msgstr "建立"
msgid "Creating epic"
-msgstr ""
+msgstr "建立å²è©©ä¸­"
msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
-msgstr ""
+msgstr "正在使用Prometheus伺æœå™¨ä¸­çš„資料建立圖表。如果這需è¦å¾ˆé•·æ™‚間,請確ä¿è³‡æ–™å¯ç”¨ã€‚"
msgid "Creation date"
-msgstr ""
+msgstr "建立日期"
msgid "Creator"
-msgstr ""
+msgstr "建立者"
msgid "Credentials"
-msgstr ""
+msgstr "憑證"
msgid "CredentialsInventory|GPG Keys"
-msgstr ""
+msgstr "GPG金鑰"
msgid "CredentialsInventory|No credentials found"
-msgstr ""
+msgstr "找ä¸åˆ°æ†‘è­‰"
msgid "CredentialsInventory|Personal Access Tokens"
-msgstr ""
+msgstr "個人存å–令牌(權æ–)"
msgid "CredentialsInventory|Project Access Tokens"
-msgstr ""
+msgstr "專案存å–令牌(權æ–)"
msgid "CredentialsInventory|SSH Keys"
-msgstr ""
+msgstr "SSH 金鑰"
msgid "Credit card required to be on file in order to create a pipeline"
-msgstr ""
+msgstr "信用å¡éœ€è¦å­˜æª”æ‰èƒ½å»ºç«‹æµæ°´ç·š"
msgid "Credit card:"
-msgstr ""
+msgstr "信用å¡ï¼š"
msgid "Critical vulnerabilities present"
-msgstr ""
+msgstr "存在嚴é‡æ¼æ´ž"
+
+msgid "Crm|Active"
+msgstr "活動"
msgid "Crm|Contact"
-msgstr ""
+msgstr "è¯çµ¡"
msgid "Crm|Contact has been added."
-msgstr ""
+msgstr "已添加è¯çµ¡äººã€‚"
msgid "Crm|Contact has been updated."
-msgstr ""
+msgstr "已更新è¯çµ¡äººã€‚"
msgid "Crm|Customer relations contacts"
-msgstr ""
+msgstr "客戶關係è¯çµ¡äºº"
msgid "Crm|Customer relations organizations"
-msgstr ""
+msgstr "客戶關係組織"
msgid "Crm|Default rate"
-msgstr ""
+msgstr "é è¨­é€ŸçŽ‡"
msgid "Crm|Edit contact"
-msgstr ""
+msgstr "編輯è¯çµ¡äºº"
msgid "Crm|Edit organization"
-msgstr ""
+msgstr "編輯組織"
msgid "Crm|New contact"
-msgstr ""
+msgstr "新建è¯çµ¡äºº"
msgid "Crm|New organization"
-msgstr ""
+msgstr "新建組織"
msgid "Crm|No contacts found"
-msgstr ""
+msgstr "找ä¸åˆ°è¯çµ¡äºº"
msgid "Crm|No organization"
-msgstr ""
+msgstr "沒有組織"
msgid "Crm|No organizations found"
-msgstr ""
+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 ""
+msgstr "Cron 時å€"
msgid "Cron time zone"
-msgstr ""
+msgstr "Cron 時å€"
msgid "Crowd"
-msgstr ""
+msgstr "Crowd"
msgid "CsvParser|Failed to render the CSV file for the following reasons:"
-msgstr ""
+msgstr "ç”±æ–¼ä»¥ä¸‹åŽŸå› æœªèƒ½å‘ˆç¾ CSV 文件:"
msgid "CsvParser|Quoted field unterminated"
-msgstr ""
+msgstr "帶引號的字段未終止"
msgid "CsvParser|Too few fields"
-msgstr ""
+msgstr "字段太少"
msgid "CsvParser|Too many fields"
-msgstr ""
+msgstr "字段太多"
msgid "CsvParser|Trailing quote on quoted field is malformed"
-msgstr ""
+msgstr "帶引號字段的尾隨引號格å¼ä¸æ­£ç¢º"
msgid "CsvParser|Unable to auto-detect delimiter; defaulted to \",\""
-msgstr ""
+msgstr "無法自動檢測分隔符;é è¨­ç‚º\",\""
msgid "Current"
-msgstr ""
+msgstr "ç›®å‰"
msgid "Current Branch"
-msgstr ""
+msgstr "ç›®å‰åˆ†æ”¯"
msgid "Current Project"
msgstr "ç›®å‰å°ˆæ¡ˆ"
msgid "Current forks will keep their visibility level."
-msgstr ""
+msgstr "當å‰å»¶ä¼¸çš„分å‰(fork)將維æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
msgid "Current node must be the primary node or you will be locking yourself out"
-msgstr ""
+msgstr "當å‰ç¯€é»žå¿…須是主節點,å¦å‰‡æ‚¨å°‡æœƒéŽ–定自己。"
msgid "Current password"
-msgstr ""
+msgstr "ç›®å‰å¯†ç¢¼"
msgid "Current sign-in IP:"
-msgstr ""
+msgstr "ç›®å‰ç™»éŒ„IP:"
msgid "Current sign-in at:"
-msgstr ""
+msgstr "ç›®å‰ç™»éŒ„於:"
msgid "Current sign-in ip"
-msgstr ""
+msgstr "ç›®å‰ç™»éŒ„ IP"
msgid "Current vulnerabilities count"
-msgstr ""
+msgstr "ç›®å‰æ¼æ´žæ•¸é‡"
msgid "CurrentUser|Buy Pipeline minutes"
-msgstr ""
+msgstr "購買æµæ°´ç·šåˆ†é˜"
msgid "CurrentUser|Edit profile"
-msgstr ""
+msgstr "編輯個人資料"
msgid "CurrentUser|One of your groups is running out"
-msgstr ""
+msgstr "您的一個群組å³å°‡ç”¨å®Œ"
msgid "CurrentUser|Preferences"
-msgstr ""
+msgstr "å好設定"
msgid "CurrentUser|Start an Ultimate trial"
-msgstr ""
+msgstr "開始試用旗艦版"
msgid "Currently unable to fetch data for this pipeline."
-msgstr ""
+msgstr "ç›®å‰ç„¡æ³•å–得該æµæ°´ç·šè³‡æ–™"
msgid "Custom (%{language})"
-msgstr ""
+msgstr "自訂 (%{language})"
msgid "Custom Attributes"
-msgstr ""
+msgstr "自訂屬性"
msgid "Custom Git clone URL for HTTP(S)"
-msgstr ""
+msgstr "自訂HTTP(S)å”è­°çš„ Git clone URL"
msgid "Custom analyzers: language support"
-msgstr ""
+msgstr "自訂分æžå™¨ï¼šæ”¯æ´èªžç³»"
msgid "Custom hostname (for private commit emails)"
-msgstr ""
+msgstr "自訂主機å稱(用於ç§æœ‰æ交電å­éƒµä»¶ï¼‰"
msgid "Custom metrics"
-msgstr ""
+msgstr "自訂指標"
msgid "Custom notification events"
-msgstr ""
+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 ""
+msgstr "自訂通知級別與åƒèˆ‡ç´šåˆ¥ç›¸åŒã€‚使用自定義通知級別,您還將收到é¸å®šäº‹ä»¶çš„通知。è¦çž­è§£æ›´å¤šä¿¡æ¯ï¼Œè«‹æŸ¥çœ‹ %{notificationLinkStart}通知電å­éƒµä»¶%{notificationLinkEnd}。"
msgid "Custom project templates"
-msgstr ""
+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 ""
+msgstr "尚未為您所屬的群組設定自訂項目範本。請在群組的設定é é¢å•Ÿç”¨å®ƒã€‚è¦è¨­å®šè‡ªè¨‚項目範本,請è¯çµ¡ç¾¤çµ„的所有者或維護者。"
msgid "Custom range"
-msgstr ""
+msgstr "自訂範åœ"
msgid "Custom range (UTC)"
-msgstr ""
+msgstr "è‡ªè¨‚ç¯„åœ (UTC)"
msgid "Customer experience improvement and third-party offers"
-msgstr ""
+msgstr "客戶體驗改善和第三方優惠"
msgid "Customer relations"
-msgstr ""
+msgstr "客戶關係"
msgid "Customer relations contacts"
-msgstr ""
+msgstr "客戶關係è¯çµ¡äºº"
msgid "Customer relations organizations"
-msgstr ""
+msgstr "客戶關係組織"
msgid "Customize CI/CD settings, including Auto DevOps, shared runners, and job artifacts."
-msgstr ""
+msgstr "自訂 CI/CD 設定,包括 Auto DevOpsã€å…±äº«åŸ·è¡Œå™¨å’Œä½œæ¥­ç”¢ç‰©ï¼ˆ job artifacts )。"
msgid "Customize colors"
-msgstr ""
+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 ""
+msgstr "自訂如何將FogBugzé›»å­éƒµä»¶åœ°å€å’Œä½¿ç”¨è€…å稱匯入GitLab。下一步將é¸æ“‡è¦åŒ¯å…¥çš„項目。"
msgid "Customize icon"
-msgstr ""
+msgstr "自訂圖示"
msgid "Customize language and region related settings."
-msgstr ""
+msgstr "自訂語言和å€åŸŸç›¸é—œè¨­å®šã€‚"
msgid "Customize name"
-msgstr ""
+msgstr "自訂å稱"
msgid "Customize your pipeline configuration."
-msgstr ""
+msgstr "自訂您的æµæ°´ç·šé…置。"
msgid "Cycle Time"
-msgstr ""
+msgstr "週期時間"
msgid "CycleAnalyticsEvent|%{label_reference} label was added to the issue"
-msgstr ""
+msgstr "%{label_reference} 標記已添加到議題(issue)中"
msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge request"
-msgstr ""
+msgstr "%{label_reference} 標記已添加到åˆä½µè«‹æ±‚中"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
-msgstr ""
+msgstr "%{label_reference} 標記已從議題(issue)中移除"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
-msgstr ""
+msgstr "%{label_reference} 標記已從åˆä½µè«‹æ±‚中移除"
msgid "CycleAnalyticsEvent|Issue closed"
-msgstr ""
+msgstr "議題已關閉"
msgid "CycleAnalyticsEvent|Issue created"
-msgstr ""
+msgstr "議題已建立"
msgid "CycleAnalyticsEvent|Issue first added to a board"
-msgstr ""
+msgstr "議題首次加入到看æ¿"
msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
-msgstr ""
+msgstr "議題首次與里程碑相關è¯"
msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
-msgstr ""
+msgstr "議題首次加入到里程碑或看æ¿"
msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
-msgstr ""
+msgstr "議題首次在æ交中æåŠ"
msgid "CycleAnalyticsEvent|Issue label was added"
-msgstr ""
+msgstr "已加入議題標記"
msgid "CycleAnalyticsEvent|Issue label was removed"
-msgstr ""
+msgstr "議題標記已刪除"
msgid "CycleAnalyticsEvent|Issue last edited"
-msgstr ""
+msgstr "議題最後編輯"
msgid "CycleAnalyticsEvent|Merge request closed"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已關閉"
msgid "CycleAnalyticsEvent|Merge request created"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已建立"
msgid "CycleAnalyticsEvent|Merge request first commit time"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚首次æ交時間"
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚首次部署到正å¼ç’°å¢ƒ"
msgid "CycleAnalyticsEvent|Merge request label was added"
-msgstr ""
+msgstr "已新增åˆä½µè«‹æ±‚標記"
msgid "CycleAnalyticsEvent|Merge request label was removed"
-msgstr ""
+msgstr "已移除åˆä½µè«‹æ±‚標記"
msgid "CycleAnalyticsEvent|Merge request last build finish time"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚上次構建完æˆæ™‚é–“"
msgid "CycleAnalyticsEvent|Merge request last build start time"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚上次構建開始時間"
msgid "CycleAnalyticsEvent|Merge request last edited"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚最後編輯"
msgid "CycleAnalyticsEvent|Merge request merged"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚å·²åˆä½µ"
msgid "CycleAnalyticsStage|Code"
-msgstr ""
+msgstr "編碼"
msgid "CycleAnalyticsStage|Issue"
-msgstr ""
+msgstr "議題"
msgid "CycleAnalyticsStage|Plan"
-msgstr ""
+msgstr "計劃"
msgid "CycleAnalyticsStage|Review"
-msgstr ""
+msgstr "評審"
msgid "CycleAnalyticsStage|Staging"
-msgstr ""
+msgstr "é ç™¼ä½ˆ"
msgid "CycleAnalyticsStage|Test"
-msgstr ""
+msgstr "測試"
msgid "CycleAnalyticsStage|Total"
-msgstr ""
+msgstr "總計"
msgid "CycleAnalyticsStage|is not available for the selected group"
-msgstr ""
+msgstr "ä¸é©ç”¨æ–¼æ‰€é¸ç¾¤çµ„"
msgid "CycleAnalyticsStage|should be under a group"
-msgstr ""
+msgstr "應歸屬於一個群組"
msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
-msgstr ""
+msgstr "å·²é¸å– %{selectedLabelsCount} 個(最多 %{maxLabels})"
msgid "CycleAnalytics|'%{name}' is collecting the data. This can take a few minutes."
-msgstr ""
+msgstr "'%{name}'正在收集資料,這å¯èƒ½éœ€è¦å¹¾åˆ†é˜ã€‚"
msgid "CycleAnalytics|Average time to completion"
-msgstr ""
+msgstr "å¹³å‡å®Œæˆæ™‚é–“"
msgid "CycleAnalytics|Change Failure Rate"
-msgstr ""
+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 ""
+msgstr "建立自定義價值æµï¼ŒæŸ¥çœ‹æœ‰é—œç‰¹å®šæ–¼æ‚¨é–‹ç™¼æµç¨‹çš„階段指標。使用您的價值æµä¾†å¯è¦–化您的 DevSecOps 生命週期,確定您的團隊的速度,並識別低效的æµç¨‹ã€‚"
msgid "CycleAnalytics|Create a custom value stream…"
-msgstr ""
+msgstr "建立自訂價值æµâ€¦"
msgid "CycleAnalytics|Custom value streams to measure your DevSecOps lifecycle"
-msgstr ""
+msgstr "自定義價值æµä¾†è¡¡é‡æ‚¨çš„ DevSecOps 生命週期"
msgid "CycleAnalytics|Data is collecting and loading."
-msgstr ""
+msgstr "正在收集與載入資料"
msgid "CycleAnalytics|Date"
-msgstr ""
+msgstr "日期"
msgid "CycleAnalytics|Display chart filters"
-msgstr ""
+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 ""
+msgstr "如果您最近å‡ç´šåˆ° GitLab 高級版,則收集和顯示數據最多å¯èƒ½éœ€è¦ 30 分é˜ã€‚"
msgid "CycleAnalytics|Lead Time for Changes"
-msgstr ""
+msgstr "變更的å‰ç½®æ™‚é–“"
msgid "CycleAnalytics|Number of tasks"
-msgstr ""
+msgstr "作業數"
msgid "CycleAnalytics|Only %{maxLabels} labels can be selected at this time"
-msgstr ""
+msgstr "此時åªèƒ½é¸å– %{maxLabels} 個標記"
msgid "CycleAnalytics|Project selected"
msgid_plural "CycleAnalytics|%d projects selected"
-msgstr[0] ""
+msgstr[0] "å·²é¸å– %d 個專案"
msgid "CycleAnalytics|Select labels"
-msgstr ""
+msgstr "é¸å–標記"
msgid "CycleAnalytics|Show"
-msgstr ""
+msgstr "顯示"
msgid "CycleAnalytics|Stage time: %{title}"
-msgstr ""
+msgstr "階段時間:%{title}"
msgid "CycleAnalytics|Tasks by type"
-msgstr ""
+msgstr "作業,ä¾é¡žåž‹"
msgid "CycleAnalytics|The average time items spent in this stage. Data limited to items completed within this date range."
-msgstr ""
+msgstr "此階段花費的平å‡æ™‚間,該資料僅é™æ–¼åœ¨æ­¤æ—¥æœŸç¯„åœå…§å®Œæˆçš„項目。"
msgid "CycleAnalytics|The given date range is larger than 180 days"
-msgstr ""
+msgstr "給定的日期範åœå¤§æ–¼180天"
msgid "CycleAnalytics|The total time items spent across each value stream stage. Data limited to items completed within this date range."
-msgstr ""
+msgstr "項目在æ¯å€‹åƒ¹å€¼æµéšŽæ®µèŠ±è²»çš„總時間,該資料僅é™æ–¼åœ¨æ­¤æ—¥æœŸç¯„åœå…§å®Œæˆçš„項目。"
msgid "CycleAnalytics|There is no data for 'Stage time' available. Adjust the current filters."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„'階段時間'資料,請調整當å‰éŽæ¿¾å™¨ã€‚"
msgid "CycleAnalytics|There is no data for 'Total time' available. Adjust the current filters."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„'總時間'資料,請調整當å‰éŽæ¿¾å™¨ã€‚"
msgid "CycleAnalytics|Time to Restore Service"
-msgstr ""
+msgstr "是時候æ¢å¾©æœå‹™äº†"
msgid "CycleAnalytics|Total time"
-msgstr ""
+msgstr "總時間"
msgid "CycleAnalytics|group dropdown filter"
-msgstr ""
+msgstr "群組下拉é¸å–®éŽæ¿¾å™¨"
msgid "CycleAnalytics|not allowed for the given start event"
-msgstr ""
+msgstr "ä¸é©ç”¨æ–¼çµ¦å®šçš„開始事件"
msgid "CycleAnalytics|project dropdown filter"
-msgstr ""
+msgstr "項目下拉é¸å–®éŽæ¿¾å™¨"
msgid "DAG visualization requires at least 3 dependent jobs."
-msgstr ""
+msgstr "DAGå¯è¦–化至少需è¦3個相關作業。"
msgid "DAST Configuration"
-msgstr ""
+msgstr "DAST é…ç½®"
+
+msgid "DAST configuration not found"
+msgstr "未找到 DAST 組態"
msgid "DAST profile not found: %{name}"
-msgstr ""
+msgstr "未找到 DAST 設定檔:%{name}"
msgid "DAST profiles"
-msgstr ""
+msgstr "DAST 設定檔"
msgid "DNS"
msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "DORA4Metrics|Average (last %{days}d)"
-msgstr ""
+msgstr "å¹³å‡ï¼ˆæœ€è¿‘%{days}天)"
msgid "DORA4Metrics|Change failure rate"
-msgstr ""
+msgstr "變更失敗率"
+
+msgid "DORA4Metrics|Change failure rate (percentage)"
+msgstr "變更失敗率(%%)"
msgid "DORA4Metrics|Date"
-msgstr ""
+msgstr "日期"
msgid "DORA4Metrics|Days for an open incident"
-msgstr ""
+msgstr "事故開啟的天數"
msgid "DORA4Metrics|Days from merge to deploy"
-msgstr ""
+msgstr "從åˆä½µåˆ°éƒ¨ç½²çš„天數"
msgid "DORA4Metrics|Deployment frequency"
-msgstr ""
+msgstr "部署頻率"
msgid "DORA4Metrics|Lead time for changes"
-msgstr ""
+msgstr "變更的å‰ç½®æ™‚é–“"
+
+msgid "DORA4Metrics|Lead time for changes (median days)"
+msgstr "變更å‰ç½®æ™‚間(中ä½å¤©æ•¸ï¼‰"
msgid "DORA4Metrics|Median (last %{days}d)"
-msgstr ""
+msgstr "中值(最近%{days}天)"
msgid "DORA4Metrics|Median time (last %{days}d)"
-msgstr ""
+msgstr "中ä½æ•¸æ™‚é–“ (最近 %{days} 天)"
msgid "DORA4Metrics|Median time an incident was open in a production environment over the given time period."
-msgstr ""
+msgstr "在給定時間內,於正å¼ç’°å¢ƒä¸­æ‰€é–‹å•Ÿçš„事故中ä½æ•¸æ™‚間。"
msgid "DORA4Metrics|No incidents during this period"
-msgstr ""
+msgstr "該期間無事故"
msgid "DORA4Metrics|No merge requests were deployed during this period"
-msgstr ""
+msgstr "在此期間未部署任何åˆä½µè«‹æ±‚"
msgid "DORA4Metrics|Number of deployments"
-msgstr ""
+msgstr "部署數é‡"
msgid "DORA4Metrics|Number of incidents divided by the number of deployments to a production environment in the given time period."
-msgstr ""
+msgstr "在給定時間段內,事故數除以生產環境的部署數。"
msgid "DORA4Metrics|Percentage of failed deployments"
-msgstr ""
+msgstr "部署失敗的百分比"
msgid "DORA4Metrics|Something went wrong while getting change failure rate data."
-msgstr ""
+msgstr "讀å–變更失敗率資料時出ç¾éŒ¯èª¤ã€‚"
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
-msgstr ""
+msgstr "å–部署頻率資料時出ç¾å•é¡Œã€‚"
msgid "DORA4Metrics|Something went wrong while getting lead time data."
-msgstr ""
+msgstr "å–å¾—å‰ç½®æ™‚間資料時發生錯誤。"
msgid "DORA4Metrics|Something went wrong while getting time to restore service data."
-msgstr ""
+msgstr "在æ¢å¾©æœå‹™è³‡æ–™æœŸé–“出ç¾éŒ¯èª¤ã€‚"
msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
-msgstr ""
+msgstr "該圖表根據 %{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 "該圖表根據 %{linkStart}deployment_tier%{linkEnd} 值顯示åˆä½µè«‹æ±‚與部署到生產環境之間的中間時間。"
msgid "DORA4Metrics|Time to restore service"
-msgstr ""
+msgstr "æœå‹™æ¢å¾©æ™‚é–“"
+
+msgid "DORA4Metrics|Time to restore service (median days)"
+msgstr "æœå‹™æ¢å¾©æ™‚間(中ä½å¤©æ•¸ï¼‰"
msgid "DSN"
-msgstr ""
+msgstr "DSN"
msgid "Dashboard"
-msgstr ""
+msgstr "儀表æ¿"
msgid "Dashboard uid not found"
-msgstr ""
+msgstr "找ä¸åˆ°å„€è¡¨ç›¤uid"
msgid "DashboardProjects|All"
-msgstr ""
+msgstr "所有"
msgid "DashboardProjects|Personal"
-msgstr ""
+msgstr "個人"
msgid "DashboardProjects|Trending"
-msgstr ""
+msgstr "熱門"
msgid "Dashboard|%{firstProject} and %{secondProject}"
-msgstr ""
+msgstr "%{firstProject} 和 %{secondProject}"
msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
-msgstr ""
+msgstr "%{firstProject}ã€%{rest} å’Œ %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Premium plan."
-msgstr ""
+msgstr "無法加入 %{invalidProjects}。 該儀表æ¿å¯ç”¨æ–¼å…¬å…±é …目和具有高級方案群組中的ç§äººå°ˆæ¡ˆã€‚"
msgid "DastConfig|Customize DAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{docsLinkStart}GitLab DAST documentation%{docsLinkEnd}."
-msgstr ""
+msgstr "自訂 DAST 設定以滿足您的è¦æ±‚。 此處所åšçš„組態變更會覆寫 GitLab æ供的組態,並且ä¸åŒ…括在更新中。 有關更進階組態é¸é …的詳細資料,請åƒé–± %{docsLinkStart}GitLab DAST 文件%{docsLinkEnd}。"
msgid "DastConfig|DAST CI/CD configuration"
-msgstr ""
+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 "已啟用"
msgid "DastConfig|Generate code snippet"
-msgstr ""
+msgstr "產生程å¼ç¢¼ç‰‡æ®µ"
+
+msgid "DastConfig|Last scan triggered %{runTimeAgo} in pipeline "
+msgstr "在æµæ°´ç·šä¸­ï¼Œ%{runTimeAgo} å‰è§¸ç™¼äº†ä¸Šæ¬¡çš„掃æ"
+
+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 ""
+msgstr "被動掃æ監控發é€åˆ°ç›®æ¨™çš„所有 HTTP 消æ¯ï¼ˆè«‹æ±‚和回應),主動掃æ則攻擊目標以發ç¾æ½›åœ¨æ¼æ´žã€‚"
msgid "DastProfiles|AJAX spider"
-msgstr ""
+msgstr "AJAX 爬蟲"
msgid "DastProfiles|API"
-msgstr ""
+msgstr "API"
msgid "DastProfiles|API endpoint URL"
-msgstr ""
+msgstr "API 端點 URL"
msgid "DastProfiles|Active"
-msgstr ""
+msgstr "啟用"
msgid "DastProfiles|Additional request headers (optional)"
-msgstr ""
+msgstr "é¡å¤–的請求標頭(å¯é¸ï¼‰"
msgid "DastProfiles|Are you sure you want to delete this profile?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤è¨­å®šæª”嗎?"
msgid "DastProfiles|Attacks the target to find potential vulnerabilities. Active scans are potentially harmful to the site being scanned."
-msgstr ""
+msgstr "攻擊目標來發ç¾æ½›åœ¨æ¼æ´žã€‚啟動掃æå¯èƒ½å°è¢«æŽƒæ的站點有害。"
msgid "DastProfiles|Authentication"
-msgstr ""
+msgstr "èªè­‰"
msgid "DastProfiles|Authentication URL"
-msgstr ""
+msgstr "èªè­‰ URL"
msgid "DastProfiles|Branch missing"
-msgstr ""
+msgstr "缺少分支"
msgid "DastProfiles|Change scanner profile"
-msgstr ""
+msgstr "變更掃æ器設定檔"
msgid "DastProfiles|Change site profile"
-msgstr ""
+msgstr "變更站點設定檔"
msgid "DastProfiles|Choose a scan method"
-msgstr ""
+msgstr "é¸æ“‡ä¸€ç¨®æŽƒæ方法"
msgid "DastProfiles|Could not create the scanner profile. Please try again."
-msgstr ""
+msgstr "無法建立掃æ器設定檔。請é‡è©¦ã€‚"
msgid "DastProfiles|Could not create the site profile. Please try again."
-msgstr ""
+msgstr "無法建立站點設定檔。請é‡è©¦ã€‚"
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法刪除掃æ器設定檔。請é‡æ–°æ•´ç†é é¢ï¼Œæˆ–ç¨å¾Œé‡è©¦ã€‚"
msgid "DastProfiles|Could not delete scanner profiles:"
-msgstr ""
+msgstr "無法刪除掃æ器設定檔:"
msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法刪除站點設定檔。請é‡æ–°æ•´ç†é é¢ï¼Œæˆ–ç¨å¾Œé‡è©¦ã€‚"
msgid "DastProfiles|Could not delete site profiles:"
-msgstr ""
+msgstr "無法刪除站點設定檔:"
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法ç²å–掃æ器設定檔。請é‡æ–°æ•´ç†é é¢ï¼Œæˆ–ç¨å¾Œé‡è©¦ã€‚"
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法ç²å–站點設定檔。請é‡æ–°æ•´ç†é é¢ï¼Œæˆ–ç¨å¾Œé‡è©¦ã€‚"
msgid "DastProfiles|Could not update the scanner profile. Please try again."
-msgstr ""
+msgstr "無法更新掃æ器設定檔。請é‡è©¦ã€‚"
msgid "DastProfiles|Could not update the site profile. Please try again."
-msgstr ""
+msgstr "無法更新站點設定檔。請é‡è©¦ã€‚"
msgid "DastProfiles|DAST profile library"
-msgstr ""
+msgstr "DAST 個人文件庫"
msgid "DastProfiles|Debug messages"
-msgstr ""
+msgstr "除錯訊æ¯"
msgid "DastProfiles|Delete profile"
-msgstr ""
+msgstr "刪除設定檔"
msgid "DastProfiles|Do you want to discard this scanner profile?"
-msgstr ""
+msgstr "是å¦è¦æ¨æ£„此掃æ器設定檔?"
msgid "DastProfiles|Do you want to discard this site profile?"
-msgstr ""
+msgstr "是å¦è¦æ¨æ£„此站點設定檔?"
msgid "DastProfiles|Do you want to discard your changes?"
-msgstr ""
+msgstr "是å¦è¦æ¨æ£„您的變更?"
msgid "DastProfiles|Edit profile"
-msgstr ""
+msgstr "編輯個人資料"
msgid "DastProfiles|Edit scanner profile"
-msgstr ""
+msgstr "編輯掃æ工具設定檔"
msgid "DastProfiles|Edit site profile"
-msgstr ""
+msgstr "編輯站點設定檔"
msgid "DastProfiles|Enable Authentication"
-msgstr ""
+msgstr "啟用èªè­‰"
msgid "DastProfiles|Enter URLs in a comma-separated list."
-msgstr ""
+msgstr "在用逗號分隔的清單中輸入 URL。"
msgid "DastProfiles|Enter headers in a comma-separated list."
-msgstr ""
+msgstr "在用逗號分隔的清單中輸入標題。"
msgid "DastProfiles|Error Details"
-msgstr ""
+msgstr "錯誤詳情"
msgid "DastProfiles|Excluded URLs"
-msgstr ""
+msgstr "排除的 URL"
msgid "DastProfiles|Excluded URLs (optional)"
-msgstr ""
+msgstr "排除的 URL(å¯é¸ï¼‰"
msgid "DastProfiles|Excluded paths"
-msgstr ""
+msgstr "排除的路徑"
msgid "DastProfiles|Excluded paths (optional)"
-msgstr ""
+msgstr "排除的路徑(å¯é¸ï¼‰"
msgid "DastProfiles|Hide debug messages"
-msgstr ""
+msgstr "éš±è—除錯訊æ¯"
msgid "DastProfiles|Include debug messages in the DAST console output."
-msgstr ""
+msgstr "在 DAST 控制å°è¼¸å‡ºä¸­åŒ…å«é™¤éŒ¯è¨Šæ¯ã€‚"
msgid "DastProfiles|Manage %{profileType} profiles"
-msgstr ""
+msgstr "ç®¡ç† %{profileType} 個人設定"
msgid "DastProfiles|Manage profiles"
-msgstr ""
+msgstr "管ç†å€‹äººè³‡æ–™"
msgid "DastProfiles|Manage site profiles"
-msgstr ""
+msgstr "管ç†ç«™é»žè¨­å®šæª”"
msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
-msgstr ""
+msgstr "最å°å€¼ = 0(未啟用超時),最大值 = 2880 分é˜"
msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
-msgstr ""
+msgstr "最å°å€¼ = 1 秒,最大值 = 3600 秒"
msgid "DastProfiles|Monitors all HTTP requests sent to the target to find potential vulnerabilities."
-msgstr ""
+msgstr "監控發é€åˆ°ç›®æ¨™çš„所有 HTTP 請求以發ç¾æ½›åœ¨æ¼æ´žã€‚"
msgid "DastProfiles|New scanner profile"
-msgstr ""
+msgstr "新掃æ器設定檔"
msgid "DastProfiles|New site profile"
-msgstr ""
+msgstr "新站點設定檔"
msgid "DastProfiles|No scanner profile selected"
-msgstr ""
+msgstr "未é¸å–掃æ器設定檔"
msgid "DastProfiles|No scanner profiles created yet"
-msgstr ""
+msgstr "尚未建立掃æ器設定檔"
msgid "DastProfiles|No site profile selected"
-msgstr ""
+msgstr "未é¸å–站點設定檔"
msgid "DastProfiles|No site profiles created yet"
-msgstr ""
+msgstr "尚未建立站點設定檔"
msgid "DastProfiles|Not Validated"
-msgstr ""
+msgstr "未驗證"
msgid "DastProfiles|Passive"
-msgstr ""
+msgstr "被動的"
msgid "DastProfiles|Password"
-msgstr ""
+msgstr "密碼"
msgid "DastProfiles|Password form field"
-msgstr ""
+msgstr "密碼表單欄ä½"
msgid "DastProfiles|Profile is being used by this on-demand scan"
-msgstr ""
+msgstr "é…置已被用於該按需掃æ"
msgid "DastProfiles|Profile name"
-msgstr ""
+msgstr "個人資料å稱"
msgid "DastProfiles|Request header names and values. Headers are added to every request made by DAST."
-msgstr ""
+msgstr "需è¦æ¨™é ­å稱和數值。標頭會添加到 DAST 發出的æ¯å€‹è«‹æ±‚中。"
msgid "DastProfiles|Request headers"
-msgstr ""
+msgstr "請求標頭"
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
-msgstr ""
+msgstr "除了傳統的爬蟲之外,å¯ä»¥é‹è¡ŒAJAX爬蟲來é歷目標站點。"
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
-msgstr ""
+msgstr "將目標站點和掃æ設置的常用設定ä¿å­˜ç‚ºé…置。使用這些é…置進行需求掃æ。"
msgid "DastProfiles|Save profile"
-msgstr ""
+msgstr "儲存個人資料"
msgid "DastProfiles|Scan method"
-msgstr ""
+msgstr "掃æ方法"
msgid "DastProfiles|Scan mode"
-msgstr ""
+msgstr "掃æ模å¼"
msgid "DastProfiles|Scanner Profile"
-msgstr ""
+msgstr "掃æ器設定檔"
msgid "DastProfiles|Scanner Profiles"
-msgstr ""
+msgstr "掃æ器設定檔"
msgid "DastProfiles|Scanner name"
-msgstr ""
+msgstr "掃æ器å稱"
msgid "DastProfiles|Scanner profiles define the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "掃æé…置文件定義了安全掃æ的組態細節。 %{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|Select a scanner profile to run a DAST scan"
-msgstr ""
+msgstr "é¸æ“‡æŽƒæé…置文件以執行 DAST 掃æ"
msgid "DastProfiles|Select a site profile to run a DAST scan"
-msgstr ""
+msgstr "é¸æ“‡ç«™é»žé…置文件以執行 DAST 掃æ"
msgid "DastProfiles|Select branch"
-msgstr ""
+msgstr "é¸æ“‡åˆ†æ”¯"
msgid "DastProfiles|Select scanner profile"
-msgstr ""
+msgstr "é¸æ“‡æŽƒæé…ç½®"
msgid "DastProfiles|Select site profile"
-msgstr ""
+msgstr "é¸æ“‡ç«™é»žé…ç½®"
msgid "DastProfiles|Show debug messages"
-msgstr ""
+msgstr "顯示除錯訊æ¯"
msgid "DastProfiles|Site Profile"
-msgstr ""
+msgstr "站點設定檔"
msgid "DastProfiles|Site Profiles"
-msgstr ""
+msgstr "站點設定檔"
msgid "DastProfiles|Site name"
-msgstr ""
+msgstr "站點å稱"
msgid "DastProfiles|Site profiles define the attributes and configuration details of your deployed application, website, or API. %{linkStart}Learn more%{linkEnd}."
-msgstr ""
+msgstr "站點é…置定義了已部署的應用程åºã€ç¶²ç«™æˆ– API 的屬性和組態詳細資訊。 %{linkStart}了解更多%{linkEnd}。"
msgid "DastProfiles|Site type"
-msgstr ""
+msgstr "站點類型"
msgid "DastProfiles|Spider timeout"
-msgstr ""
+msgstr "爬蟲超時"
msgid "DastProfiles|Submit button"
-msgstr ""
+msgstr "æ交按鈕"
msgid "DastProfiles|Submit button (optional)"
-msgstr ""
+msgstr "æ交按鈕 (å¯é¸)"
msgid "DastProfiles|Target URL"
-msgstr ""
+msgstr "目標URL"
msgid "DastProfiles|Target timeout"
-msgstr ""
+msgstr "目標超時"
msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
-msgstr ""
+msgstr "爬蟲é歷站點所å…許的最大分é˜æ•¸ã€‚"
msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
-msgstr ""
+msgstr "被測站點回應請求所å…許的最大秒數。"
msgid "DastProfiles|This profile is currently being used in a policy."
-msgstr ""
+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 ""
+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 ""
+msgstr "此站點é…置文件正由當å‰ç­–略使用中,è¦é€²è¡Œç·¨è¼¯ï¼Œæ‚¨å¿…須將其從已啟用策略中移除。"
msgid "DastProfiles|Turn on AJAX spider"
-msgstr ""
+msgstr "啟用AJAX爬蟲"
msgid "DastProfiles|URL"
-msgstr ""
+msgstr "URL"
msgid "DastProfiles|URLs to skip during the authenticated scan."
-msgstr ""
+msgstr "在驗證掃æéŽç¨‹ä¸­è·³éŽçš„ URL。"
msgid "DastProfiles|Username"
-msgstr ""
+msgstr "使用者å稱"
msgid "DastProfiles|Username form field"
-msgstr ""
+msgstr "使用者å稱表單欄ä½"
msgid "DastProfiles|Validated"
-msgstr ""
+msgstr "已驗證"
msgid "DastProfiles|Validation status"
-msgstr ""
+msgstr "驗證狀態"
msgid "DastProfiles|Website"
-msgstr ""
+msgstr "網站"
msgid "DastProfiles|What does each method do?"
-msgstr ""
+msgstr "æ¯ç¨®æ–¹æ³•çš„作用是什麼?"
msgid "DastProfiles|You can either choose a passive scan or validate the target site from the site profile management page. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
-msgstr ""
+msgstr "您å¯ä»¥é¸æ“‡è¢«å‹•æŽƒæ或從站點é…置文件管ç†é é¢é©—證目標站點。 %{docsLinkStart}瞭解有關站點驗證的更多信æ¯ã€‚%{docsLinkEnd}"
msgid "DastProfiles|You cannot run an active scan against an unvalidated site."
-msgstr ""
+msgstr "ä¸èƒ½å°æœªç¶“驗證的站點é‹è¡Œä¸»å‹•æŽƒæ。"
msgid "DastProfiles|folder/dast_example.har or https://example.com/dast_example.har"
-msgstr ""
+msgstr "folder/dast_example.har 或 https://example.com/dast_example.har"
msgid "DastProfiles|folder/example.postman_collection.json or https://example.com/"
-msgstr ""
+msgstr "folder/example.postman_collection.json 或 https://example.com/"
msgid "DastProfiles|folder/openapi.json or https://example.com/openapi.json"
-msgstr ""
+msgstr "folder/openapi.json 或 https://example.com/openapi.json"
msgid "DastSiteValidation|Copy HTTP header to clipboard"
-msgstr ""
+msgstr "複製HTTP標頭到剪貼簿"
msgid "DastSiteValidation|Copy Meta tag to clipboard"
-msgstr ""
+msgstr "複製 Meta 標籤到剪貼簿"
msgid "DastSiteValidation|Could not create validation token. Please try again."
-msgstr ""
+msgstr "無法建立驗證令牌。請é‡è©¦ã€‚"
msgid "DastSiteValidation|Could not revoke validation. Please try again."
-msgstr ""
+msgstr "無法撤銷驗證,請é‡è©¦ã€‚"
msgid "DastSiteValidation|Download validation text file"
-msgstr ""
+msgstr "下載驗證文字檔"
msgid "DastSiteValidation|Header validation"
-msgstr ""
+msgstr "標頭驗證"
msgid "DastSiteValidation|Meta tag validation"
-msgstr ""
+msgstr "Meta 標籤驗證"
msgid "DastSiteValidation|Not validated"
-msgstr ""
+msgstr "尚未驗證"
msgid "DastSiteValidation|Retry validation"
-msgstr ""
+msgstr "é‡è©¦é©—è­‰"
msgid "DastSiteValidation|Revoke validation"
-msgstr ""
+msgstr "撤銷驗證"
msgid "DastSiteValidation|Step 1 - Choose site validation method."
-msgstr ""
+msgstr "步驟1 - é¸æ“‡ç«™é»žé©—證方法。"
msgid "DastSiteValidation|Step 2 - Add the following HTTP header to your site."
-msgstr ""
+msgstr "步驟2 - 將以下HTTP標頭加到您的網站。"
msgid "DastSiteValidation|Step 2 - Add the following meta tag to your site."
-msgstr ""
+msgstr "步驟2 - 將以下元標籤加到您的網站。"
msgid "DastSiteValidation|Step 2 - Download the following text file, then upload it to the target site."
-msgstr ""
+msgstr "步驟2 - 下載以下文字檔,然後將其上傳到目標站點。"
msgid "DastSiteValidation|Step 3 - Confirm header location."
-msgstr ""
+msgstr "步驟3 - 確èªæ¨™é ­ä½ç½®ã€‚"
msgid "DastSiteValidation|Step 3 - Confirm meta tag location."
-msgstr ""
+msgstr "步驟3 - ç¢ºèª meta 標籤ä½ç½®ã€‚"
msgid "DastSiteValidation|Step 3 - Confirm text file location."
-msgstr ""
+msgstr "步驟3 - 確èªæ–‡å­—檔ä½ç½®ã€‚"
msgid "DastSiteValidation|Text file validation"
-msgstr ""
+msgstr "文字檔驗證"
msgid "DastSiteValidation|The validation has failed. Please try again."
-msgstr ""
+msgstr "驗證失敗。請é‡è©¦ã€‚"
msgid "DastSiteValidation|The validation is in progress. Please wait..."
-msgstr ""
+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[0] "這將影響 %d å€‹å…¶ä»–ä»¥ç›¸åŒ 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 "è¦é‹è¡Œä¸»å‹•æŽƒæ,請驗證您的站點。 站點é…置文件驗證é™ä½Žäº†é‡å°éŒ¯èª¤ç¶²ç«™é‹è¡Œä¸»å‹•æŽƒæ的風險。 共享相åŒåŸºæœ¬ URL 的所有站點é…置文件共享相åŒçš„驗證狀態。"
msgid "DastSiteValidation|Validate"
-msgstr ""
+msgstr "é©—è­‰"
msgid "DastSiteValidation|Validate site"
-msgstr ""
+msgstr "驗證站點"
msgid "DastSiteValidation|Validated"
-msgstr ""
+msgstr "已驗證"
msgid "DastSiteValidation|Validating..."
-msgstr ""
+msgstr "驗證中..."
msgid "DastSiteValidation|Validation failed"
-msgstr ""
+msgstr "驗證失敗"
msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
-msgstr ""
+msgstr "%{url} 的驗證失敗。 %{retryButtonStart}é‡è©¦é©—è­‰%{retryButtonEnd}。"
msgid "DastSiteValidation|Validation succeeded. Both active and passive scans can be run against the target site."
-msgstr ""
+msgstr "é©—è­‰æˆåŠŸã€‚å¯ä»¥é‡å°ç›®æ¨™ç«™é»žåŸ·è¡Œä¸»å‹•å’Œè¢«å‹•æŽƒæ。"
msgid "DastSiteValidation|You will not be able to run active scans against %{url}."
-msgstr ""
+msgstr "您將無法å°%{url}é‹è¡Œä¸»å‹•æŽƒæ。"
msgid "Data is still calculating..."
-msgstr ""
+msgstr "資料ä»åœ¨è¨ˆç®—中……"
msgid "Data refresh"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†è³‡æ–™"
msgid "Data type"
-msgstr ""
+msgstr "資料類型"
msgid "Database update failed"
-msgstr ""
+msgstr "數據庫更新失敗"
msgid "DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog."
-msgstr ""
+msgstr "%{linkOpen}API 金鑰%{linkClose} 用於 Datadog 的身份驗證。"
msgid "DatadogIntegration|(Advanced) The full URL for your Datadog site."
-msgstr ""
+msgstr "(進階)您 Datadog 的完整URL"
msgid "DatadogIntegration|API URL"
-msgstr ""
+msgstr "API 網å€ï¼ˆURL)"
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 "Datadog 中的自定義標籤。 以 %{codeOpen}key:value%{codeClose} æ ¼å¼æ¯è¡Œè¼¸å…¥ä¸€å€‹æ¨™ç±¤ã€‚ %{linkOpen}如何使用標籤?%{linkClose}"
msgid "DatadogIntegration|Environment"
-msgstr ""
+msgstr "環境"
msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}"
-msgstr ""
+msgstr "å°æ–¼è‡ªç®¡ç†çš„部署,為發é€åˆ° Datadog 的所有數據設置 %{codeOpen}env%{codeClose} 標籤。 %{linkOpen}如何使用標籤?%{linkClose}"
msgid "DatadogIntegration|How do I set up this integration?"
-msgstr ""
+msgstr "我應如何設置此整åˆï¼Ÿ"
msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues. %{docs_link}"
-msgstr ""
+msgstr "å°‡ CI/CD æµæ°´ç·šè¨Šæ¯ç™¼é€åˆ° Datadog 以監控作業失敗並解決性能å•é¡Œã€‚ %{docs_link}"
msgid "DatadogIntegration|Service"
-msgstr ""
+msgstr "æœå‹™"
msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments."
-msgstr ""
+msgstr "在 Datadog 中標記來自此 GitLab 實例的所有資料。 在管ç†å¤šå€‹è‡ªç®¡ç†éƒ¨ç½²æ™‚很有用。"
msgid "DatadogIntegration|Tags"
-msgstr ""
+msgstr "標籤"
msgid "DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}."
-msgstr ""
+msgstr "將資料發é€åˆ° Datadog 站點。 è¦å°‡è³‡æ–™ç™¼é€åˆ° EU 站點,請使用 %{codeOpen}datadoghq.eu%{codeClose}。"
msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
-msgstr ""
+msgstr "使用 Datadog 追蹤您的 GitLab æµæ°´ç·šã€‚"
msgid "DatadogIntegration|have an invalid format"
-msgstr ""
+msgstr "無效的格å¼"
msgid "Datasource name not found"
-msgstr ""
+msgstr "找ä¸åˆ°è³‡æ–™ä¾†æºçš„å稱"
msgid "Date"
-msgstr ""
+msgstr "日期"
msgid "Date merged"
-msgstr ""
+msgstr "åˆä½µæ—¥æœŸ"
msgid "Date range"
-msgstr ""
+msgstr "日期範åœ"
msgid "Date range limited to %{number} days"
-msgstr ""
+msgstr "日期範åœçš„é™åˆ¶ç‚º %{number} 天"
msgid "Date range must be shorter than %{max_range} days."
-msgstr ""
+msgstr "日期範åœå¿…é ˆå°æ–¼ %{max_range} 天。"
msgid "Day of month"
-msgstr ""
+msgstr "月份中的第幾天"
msgid "DayTitle|F"
-msgstr ""
+msgstr "五"
msgid "DayTitle|M"
-msgstr ""
+msgstr "一"
msgid "DayTitle|S"
-msgstr ""
+msgstr "æ—¥"
msgid "DayTitle|W"
-msgstr ""
+msgstr "三"
msgid "Days"
-msgstr ""
+msgstr "天"
msgid "Days to merge"
-msgstr ""
+msgstr "åˆä½µæ‰€éœ€å¤©æ•¸"
msgid "Deactivate dormant users after 90 days of inactivity"
-msgstr ""
+msgstr "åœç”¨é–’ç½® 90 天後的休眠使用者"
msgid "Dear Administrator,"
-msgstr ""
+msgstr "親愛的管ç†å“¡ï¼Œ"
msgid "Debian package already exists in Distribution"
-msgstr ""
+msgstr "Debian 軟體套件已經存在於發行版中"
msgid "Debug"
-msgstr ""
+msgstr "除錯"
msgid "Dec"
msgstr "12月"
msgid "December"
-msgstr ""
+msgstr "12月"
msgid "Decline"
-msgstr ""
+msgstr "拒絕"
msgid "Decline and sign out"
-msgstr ""
+msgstr "拒絕並退出"
msgid "Decompressed archive size validation failed."
-msgstr ""
+msgstr "解壓縮檔案大å°é©—證失敗。"
msgid "Decrease"
-msgstr ""
+msgstr "減少"
msgid "Default CI/CD configuration file"
-msgstr ""
+msgstr "é è¨­ CI/CD 組態設定檔"
msgid "Default artifacts expiration"
-msgstr ""
+msgstr "é è¨­ç”¢ç‰©éŽæœŸæ™‚é–“"
msgid "Default branch"
-msgstr ""
+msgstr "é è¨­åˆ†æ”¯"
msgid "Default branch and protected branches"
-msgstr ""
+msgstr "é è¨­åˆ†æ”¯å’Œå—ä¿è­·çš„分支"
msgid "Default description template for issues"
-msgstr ""
+msgstr "議題的é è¨­æ述範本"
msgid "Default description template for merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚çš„é è¨­æ述範本"
msgid "Default first day of the week"
-msgstr ""
+msgstr "æ¯é€±çš„é è¨­èµ·å§‹æ—¥"
msgid "Default first day of the week in calendars and date pickers."
-msgstr ""
+msgstr "在日期é¸æ“‡å™¨ä¸­é¡¯ç¤ºæ¯é€±é è¨­çš„起始日。"
msgid "Default projects limit"
-msgstr ""
+msgstr "é è¨­å°ˆæ¡ˆé™åˆ¶"
msgid "Default timeout"
-msgstr ""
+msgstr "é è¨­çš„逾時"
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "é è¨­ï¼šå°‡ FogBugz 帳號 ID 映射為全å"
msgid "DefaultBranchLabel|default"
-msgstr ""
+msgstr "é è¨­å€¼"
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
-msgstr ""
+msgstr "開發者和維護者都å¯ä»¥æŽ¨é€æ–°çš„æ交,但ä¸èƒ½å¼·åˆ¶æŽ¨é€ã€‚"
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
-msgstr ""
+msgstr "開發者和維護者都å¯ä»¥æŽ¨é€æ–°çš„æ交ã€å¼·åˆ¶æŽ¨é€ï¼Œæˆ–刪除分支。"
msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
-msgstr ""
+msgstr "開發者ä¸èƒ½æŽ¨é€æ–°çš„æ交,但å…許接å—åˆä½µè«‹æ±‚到分支,維護者å¯ä»¥æŽ¨é€åˆ°åˆ†æ”¯ã€‚"
msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
-msgstr ""
+msgstr "開發人員無法推é€æ–°æ交,但維護者å¯ä»¥ã€‚沒有人å¯ä»¥å¼·è¡ŒæŽ¨é€ã€‚"
msgid "DefaultBranchProtection|Fully protected"
-msgstr ""
+msgstr "完全ä¿è­·"
msgid "DefaultBranchProtection|Not protected"
-msgstr ""
+msgstr "ä¸å—ä¿è­·"
msgid "DefaultBranchProtection|Partially protected"
-msgstr ""
+msgstr "部分å—ä¿è­·"
msgid "DefaultBranchProtection|Protected against pushes"
-msgstr ""
+msgstr "防止推é€"
msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
-msgstr ""
+msgstr "使用%{cronSyntaxStart}cron語法%{cronSyntaxEnd}定義自定義部署å‡çµæ¨¡å¼"
msgid "Define a custom pattern with cron syntax"
-msgstr ""
+msgstr "使用 Cron 語法定義自訂模å¼"
msgid "Define custom rules for what constitutes spam, independent of Akismet"
-msgstr ""
+msgstr "é‡å°Akismet定義構æˆåžƒåœ¾éƒµä»¶çš„自訂è¦å‰‡"
msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
-msgstr ""
+msgstr "在%{code_open}.githab-ci.yml%{code_close}的部署階段中定義環境來追蹤部署。"
msgid "Define how approval rules are applied to merge requests."
-msgstr ""
+msgstr "定義如何將核准è¦å‰‡å¥—用於åˆä½µè«‹æ±‚。"
msgid "Define rules for who can push, merge, and the required approvals for each branch."
-msgstr ""
+msgstr "定義誰å¯ä»¥æŽ¨é€ã€åˆä½µä»¥åŠæ¯å€‹åˆ†æ”¯æ‰€éœ€çš„核准è¦å‰‡ã€‚"
msgid "Definition"
-msgstr ""
+msgstr "定義"
msgid "Delay 2FA enforcement (hours)"
-msgstr ""
+msgstr "延é²åŸ·è¡Œé›™å› å­é©—證(å°æ™‚)"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
-msgstr ""
+msgstr "確定è¦ç«‹å³åŸ·è¡Œ%{jobName}嗎? å¦å‰‡è©²ä½œæ¥­å°‡åœ¨è¨ˆæ™‚器完æˆå¾Œè‡ªå‹•åŸ·è¡Œã€‚"
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
-msgstr ""
+msgstr "您確定è¦ç«‹å³åŸ·è¡Œ%{job_name}嗎? 該作業將在計時çµæŸå¾Œè‡ªå‹•åŸ·è¡Œã€‚"
msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes."
-msgstr ""
+msgstr "您確定è¦ç«‹å³åŸ·è¡Œ%{job_name}嗎? 該作業將在計時çµæŸå¾Œè‡ªå‹•åŸ·è¡Œã€‚"
msgid "DelayedJobs|Run the delayed job now?"
-msgstr ""
+msgstr "ç¾åœ¨åŸ·è¡Œå·²å»¶é²çš„作業嗎?"
msgid "DelayedJobs|Start now"
-msgstr ""
+msgstr "ç«‹å³é–‹å§‹"
msgid "DelayedJobs|Unschedule"
-msgstr ""
+msgstr "å–消計劃"
msgid "DelayedJobs|delayed"
-msgstr ""
+msgstr "已延時"
msgid "Delete"
-msgstr ""
+msgstr "刪除"
msgid "Delete %{issuableType}"
-msgstr ""
+msgstr "刪除 %{issuableType}"
msgid "Delete %{name}"
-msgstr ""
+msgstr "刪除%{name}"
msgid "Delete Comment"
-msgstr ""
+msgstr "刪除留言"
msgid "Delete File"
-msgstr ""
+msgstr "刪除檔案"
msgid "Delete Key"
-msgstr ""
+msgstr "刪除金鑰"
msgid "Delete Selected"
-msgstr ""
+msgstr "刪除é¸æ“‡çš„"
msgid "Delete Value Stream"
-msgstr ""
+msgstr "刪除價值æµ"
msgid "Delete account"
-msgstr ""
+msgstr "刪除帳號"
msgid "Delete artifacts"
-msgstr ""
+msgstr "刪除產物"
msgid "Delete audio"
-msgstr ""
+msgstr "刪除音頻"
msgid "Delete badge"
-msgstr ""
+msgstr "刪除徽章"
msgid "Delete code block"
-msgstr ""
+msgstr "刪除程å¼ç¢¼å€å¡Š"
msgid "Delete column"
-msgstr ""
+msgstr "刪除列"
msgid "Delete comment"
-msgstr ""
+msgstr "刪除留言"
msgid "Delete corpus"
-msgstr ""
+msgstr "刪除語料庫"
msgid "Delete deploy key"
-msgstr ""
+msgstr "刪除部署金鑰"
msgid "Delete file"
-msgstr ""
+msgstr "刪除檔案"
+
+msgid "Delete identity"
+msgstr "刪除身份"
msgid "Delete image"
-msgstr ""
+msgstr "刪除映åƒæª”"
msgid "Delete image repository"
-msgstr ""
+msgstr "刪除映åƒæª”版本庫"
msgid "Delete internal note"
-msgstr ""
+msgstr "刪除內部註釋"
msgid "Delete label"
-msgstr ""
+msgstr "刪除標籤"
msgid "Delete label: %{labelName}"
-msgstr ""
+msgstr "刪除標記:%{labelName}"
msgid "Delete pipeline"
-msgstr ""
+msgstr "刪除æµæ°´ç·š"
msgid "Delete pipeline schedule"
-msgstr ""
+msgstr "刪除æµæ°´ç·š (pipeline) 排程"
msgid "Delete project"
-msgstr ""
+msgstr "刪除專案"
+
+msgid "Delete release"
+msgstr "刪除版本發佈"
+
+msgid "Delete release %{release}?"
+msgstr "刪除 %{release} 版本發佈?"
msgid "Delete row"
-msgstr ""
+msgstr "刪除行"
msgid "Delete self monitoring project"
-msgstr ""
+msgstr "刪除自我監控專案"
msgid "Delete snippet"
-msgstr ""
+msgstr "刪除程å¼ç¢¼ç‰‡æ®µ"
msgid "Delete snippet?"
-msgstr ""
+msgstr "刪除程å¼ç¢¼ç‰‡æ®µå—Žï¼Ÿ"
msgid "Delete source branch"
-msgstr ""
+msgstr "刪除æºåˆ†æ”¯"
msgid "Delete subscription"
-msgstr ""
+msgstr "刪除訂閱"
msgid "Delete table"
-msgstr ""
+msgstr "刪除表"
msgid "Delete this attachment"
-msgstr ""
+msgstr "刪除該附件"
msgid "Delete this epic and all descendants?"
-msgstr ""
+msgstr "刪除此å²è©©å’Œæ‰€æœ‰ä¸‹ç´šï¼Ÿ"
msgid "Delete this project"
-msgstr ""
+msgstr "刪除此專案"
msgid "Delete user list"
-msgstr ""
+msgstr "刪除使用者列表"
msgid "Delete variable"
-msgstr ""
+msgstr "刪除變數"
msgid "Delete video"
-msgstr ""
+msgstr "刪除影åƒ"
msgid "DeleteProject|Failed to remove events. Please try again or contact administrator."
-msgstr ""
+msgstr "移除事件失敗。請é‡è©¦æˆ–è¯ç¹«ç®¡ç†å“¡ã€‚"
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
-msgstr ""
+msgstr "刪除項目版本庫失敗。請é‡è©¦æˆ–è¯çµ¡ç®¡ç†å“¡ã€‚"
msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
-msgstr ""
+msgstr "移除專案程å¼ç¢¼ç‰‡æ®µå¤±æ•—。請é‡è©¦æˆ–è¯ç¹«ç®¡ç†å“¡ã€‚"
msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
-msgstr ""
+msgstr "刪除項目容器é¡åƒåº«ä¸­çš„æŸäº›æ¨™ç±¤å¤±æ•—。請é‡è©¦æˆ–è¯çµ¡ç®¡ç†å“¡ã€‚"
msgid "DeleteProject|Failed to remove webhooks. Please try again or contact administrator."
-msgstr ""
+msgstr "移除 Webhooks 失敗。請é‡è©¦æˆ–è¯ç¹«ç®¡ç†å“¡ã€‚"
msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
-msgstr ""
+msgstr "刪除wiki版本庫失敗。請é‡è©¦æˆ–è¯çµ¡ç®¡ç†å“¡ã€‚"
+
+msgid "DeleteRelease|Are you sure you want to delete this release?"
+msgstr "您確定è¦åˆªé™¤æ­¤ç‰ˆæœ¬ç™¼ä½ˆå—Žï¼Ÿ"
+
+msgid "DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}."
+msgstr "有關更多詳細信æ¯ï¼Œè«‹åƒé–± %{docsPathStart}刪除版本發佈%{docsPathEnd}。"
+
+msgid "DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted."
+msgstr "您å³å°‡åˆªé™¤ %{release} 版本發佈åŠå…¶è³‡ç”¢ã€‚ Git 標籤 %{tag} ä¸æœƒè¢«åˆªé™¤ã€‚"
msgid "DeleteValueStream|'%{name}' Value Stream deleted"
-msgstr ""
+msgstr "「%{name}〠價值æµå·²åˆªé™¤"
msgid "DeleteValueStream|Are you sure you want to delete the \"%{name}\" Value Stream?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤ “%{name}†價值æµå—Žï¼Ÿ"
msgid "DeleteValueStream|Delete %{name}"
-msgstr ""
+msgstr "刪除 %{name}"
msgid "Deleted"
-msgstr ""
+msgstr "已刪除"
msgid "Deleted chat nickname: %{chat_name}!"
-msgstr ""
+msgstr "已刪除èŠå¤©çš„暱稱: %{chat_name}!"
msgid "Deleted projects cannot be restored!"
-msgstr ""
+msgstr "已刪除的專案無法復原ï¼"
msgid "Deleted the source branch."
-msgstr ""
+msgstr "已刪除來æºåˆ†æ”¯"
msgid "Deletes the source branch"
-msgstr ""
-
-msgid "Deletes the source branch."
-msgstr ""
+msgstr "已刪除來æºåˆ†æ”¯"
msgid "Deleting"
-msgstr ""
+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 "刪除專案會使其呈ç¾å”¯è®€ç‹€æ…‹ï¼Œä¸”到 %{date} 時專案將被永久刪除。您「éžå¸¸ã€ç¢ºå®šå—Žï¼Ÿ"
msgid "Deleting the project will delete its repository and all related resources, including issues and merge requests."
-msgstr ""
+msgstr "刪除專案將刪除其版本庫和所有相關資æºï¼ŒåŒ…括議題 (issue) å’Œåˆä½µè«‹æ±‚。"
msgid "Deletion pending. This project will be deleted on %{date}. Repository and other project resources are read-only."
-msgstr ""
+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 "ä¿ç•™å·²åˆªé™¤çš„專案1天"
msgid "DeletionSettings|None, delete immediately"
-msgstr ""
+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 ""
+msgstr "已拒絕"
msgid "Denied authorization of chat nickname %{user_name}."
-msgstr ""
+msgstr "已拒絕èŠå¤©æš±ç¨± %{user_name} 的授權。"
msgid "Deny"
-msgstr ""
+msgstr "拒絕"
msgid "Deny access request"
-msgstr ""
+msgstr "拒絕存å–請求"
msgid "Dependencies"
-msgstr ""
+msgstr "ä¾è³´é …"
msgid "Dependencies help page link"
-msgstr ""
+msgstr "ä¾è³´é …幫助é é¢é€£çµ"
msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
-msgstr[0] ""
+msgstr[0] "%d個其它æ¼æ´žæœªé¡¯ç¤º"
msgid "Dependencies|%d more"
msgid_plural "Dependencies|%d more"
-msgstr[0] ""
+msgstr[0] "å† %d 個"
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
-msgstr[0] ""
+msgstr[0] "åµæ¸¬åˆ° %d 個æ¼æ´ž"
msgid "Dependencies|%{remainingLicensesCount} more"
-msgstr ""
+msgstr "其餘%{remainingLicensesCount}項"
msgid "Dependencies|(top level)"
-msgstr ""
+msgstr "(頂級)"
msgid "Dependencies|All"
-msgstr ""
+msgstr "所有"
msgid "Dependencies|Component"
-msgstr ""
+msgstr "元件"
msgid "Dependencies|Component name"
-msgstr ""
+msgstr "元件å稱"
msgid "Dependencies|Dependency path"
-msgstr ""
+msgstr "ä¾è³´è·¯å¾‘"
msgid "Dependencies|Export as JSON"
-msgstr ""
+msgstr "匯出為JSON"
msgid "Dependencies|Job failed to generate the dependency list"
-msgstr ""
+msgstr "作業無法生æˆä¾è³´é …列表"
msgid "Dependencies|Learn more about dependency paths"
-msgstr ""
+msgstr "了解更多關於ä¾è³´è·¯å¾‘"
msgid "Dependencies|License"
-msgstr ""
+msgstr "授權æ¢æ¬¾"
msgid "Dependencies|Location"
-msgstr ""
+msgstr "ä½ç½®"
msgid "Dependencies|Location and dependency path"
-msgstr ""
+msgstr "ä½ç½®å’Œä¾è³´è·¯å¾‘"
msgid "Dependencies|Packager"
-msgstr ""
+msgstr "å°è£å·¥å…·"
msgid "Dependencies|Software Bill of Materials (SBOM) based on the %{linkStart}latest successful%{linkEnd} scan"
-msgstr ""
+msgstr "基於%{linkStart}最新æˆåŠŸ%{linkEnd}掃æ的軟體物料清單 (SBOM)"
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 ""
+msgstr "%{codeStartTag}dependency_scanning%{codeEndTag} 作業失敗,無法生æˆåˆ—表。請確ä¿ä½œæ¥­æ­£å¸¸åŸ·è¡Œä¸¦é‡å•Ÿæµæ°´ç·šã€‚"
msgid "Dependencies|The component dependency path is based on the lock file. There may be several paths. In these cases, the longest path is displayed."
-msgstr ""
+msgstr "元件ä¾è³´è·¯å¾‘基於鎖定文件,å¯èƒ½æœ‰å¤šå€‹è·¯å¾‘。在這些情æ³ä¸‹ï¼Œå°‡é¡¯ç¤ºçš„最長的路徑。"
msgid "Dependencies|There may be multiple paths"
-msgstr ""
+msgstr "å¯èƒ½æœ‰å¤šå€‹è·¯å¾‘"
msgid "Dependencies|Toggle vulnerability list"
-msgstr ""
+msgstr "切æ›æ¼æ´žæ¸…å–®"
msgid "Dependencies|Unsupported file(s) detected"
-msgstr ""
+msgstr "檢測到ä¸æ”¯æ´çš„文件"
msgid "Dependencies|Vulnerable components"
-msgstr ""
+msgstr "有æ¼æ´žçš„元件"
msgid "Dependency List"
-msgstr ""
+msgstr "ä¾è³´é …列表"
msgid "Dependency List has no entries"
-msgstr ""
+msgstr "ä¾è³´é …列表沒有æ¢ç›®"
msgid "Dependency Proxy"
-msgstr ""
+msgstr "ä¾è³´é …代ç†"
msgid "Dependency Scanning"
-msgstr ""
+msgstr "ä¾è³´é …掃æ"
msgid "Dependency list"
-msgstr ""
+msgstr "ä¾è³´é …列表"
msgid "DependencyProxy|All items in the cache are scheduled for removal."
-msgstr ""
+msgstr "所有快å–緩存中的項目將被列入刪除排程"
msgid "DependencyProxy|Cached %{time}"
-msgstr ""
+msgstr "ä¾è³´ä»£ç†|å·²å¿«å– %{time}"
msgid "DependencyProxy|Clear cache"
-msgstr ""
+msgstr "清楚快å–"
msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
-msgstr ""
+msgstr "自動清除快å–çš„ä¾è³´ä»£ç†"
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
-msgstr ""
+msgstr "åŒ…å« %{count} 個映åƒå¡Šï¼ˆ%{size})"
msgid "DependencyProxy|Copy prefix"
-msgstr ""
+msgstr "複製å‰ç¶´"
msgid "DependencyProxy|Dependency Proxy"
-msgstr ""
+msgstr "ä¾è³´é …代ç†"
msgid "DependencyProxy|Dependency Proxy image prefix"
-msgstr ""
+msgstr "ä¾è³´é …代ç†æ˜ åƒæª”å‰ç¶´"
msgid "DependencyProxy|Enable Dependency Proxy"
-msgstr ""
+msgstr "啟用ä¾è³´é …代ç†"
msgid "DependencyProxy|Enable the Dependency Proxy and settings for clearing the cache."
-msgstr ""
+msgstr "啟用ä¾è³´ä»£ç†å’Œè¨­å®šæ¸…除快å–。"
msgid "DependencyProxy|Image list"
-msgstr ""
+msgstr "映åƒæª”清單"
msgid "DependencyProxy|Scheduled for deletion"
-msgstr ""
+msgstr "é å®šåˆªé™¤"
msgid "DependencyProxy|There are no images in the cache"
-msgstr ""
+msgstr "å¿«å–中沒有映åƒæª”"
msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
-msgstr ""
+msgstr "欲查看映åƒæª”å‰ç¶´å’Œå¿«å–中的內容,請å‰å¾€ %{linkStart} ä¾è³´æ€§ä»£ç†ä¼ºæœå™¨ %{linkEnd}"
msgid "DependencyProxy|When enabled, images older than 90 days will be removed from the cache."
-msgstr ""
+msgstr "å•Ÿç”¨å¾Œï¼Œè¶…éŽ 90 天的映åƒæª”將從快å–中移除。"
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
-msgstr[0] ""
+msgstr[0] "ä¾è³´æ–¼%d 個正在åˆä½µçš„åˆä½µè«‹æ±‚"
msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
-msgstr[0] ""
+msgstr[0] "ä¾è³´æ–¼%{strongStart}%{closedCount}已關閉的%{strongEnd}åˆä½µè«‹æ±‚。"
msgid "Deploy"
msgid_plural "Deploys"
-msgstr[0] ""
+msgstr[0] "部署"
+
+msgid "Deploy Key"
+msgstr "部署金鑰"
msgid "Deploy Keys"
-msgstr ""
+msgstr "部署金鑰"
msgid "Deploy Token"
-msgstr ""
+msgstr "部署令牌(權æ–)"
msgid "Deploy container based web apps on Google managed clusters"
-msgstr ""
+msgstr "在 Google 託管的å¢é›†ä¸Šéƒ¨ç½²åŸºæ–¼å®¹å™¨çš„網路應用"
msgid "Deploy freezes"
-msgstr ""
+msgstr "å‡çµéƒ¨ç½²"
msgid "Deploy key was successfully updated."
-msgstr ""
+msgstr "部署金鑰已æˆåŠŸæ›´æ–°ã€‚"
msgid "Deploy keys"
-msgstr ""
+msgstr "部署金鑰"
msgid "Deploy keys grant read/write access to all repositories in your instance"
-msgstr ""
+msgstr "部署金鑰授予å°å¯¦ä¾‹ä¸­æ‰€æœ‰æª”案庫的讀/寫存å–權é™"
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
-msgstr ""
+msgstr "未找到部署進度。è¦æŸ¥çœ‹pod,請確ä¿æ‚¨çš„環境符åˆ%{linkStart}部署看æ¿æ¢ä»¶%{linkEnd}。"
msgid "Deploy static assets and resources to Google managed CDN"
-msgstr ""
+msgstr "å°‡éœæ…‹è³‡ç”¢å’Œè³‡æºéƒ¨ç½²åˆ° Google 管ç†çš„ CDN"
msgid "Deploy to..."
-msgstr ""
+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 ""
+msgstr "è¦æŸ¥çœ‹æ‚¨çš„環境的部署進度,請確ä¿æ‚¨æ­£åœ¨éƒ¨ç½²åˆ° %{codeStart}$KUBE_NAMESPACE%{codeEnd} 並使用 %{codeStart}app.gitlab.com/app=$CI_PROJECT_PATH_SLUG%{codeEnd} å’Œ %{codeStart}app.gitlab.com/env=$CI_ENVIRONMENT_SLUG%{codeEnd} 進行註釋。"
msgid "DeployBoard|Kubernetes Pods"
-msgstr ""
+msgstr "Kubernetes Pods"
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 "加入å‡çµæœŸé–“以防止在給定環境的一段時間內æ„外發布。您必須根據此處加入的å‡çµéƒ¨ç½²æ›´æ–°%{filename}的部署作業。%{freeze_period_link_start}瞭解更多。%{freeze_period_link_end}"
msgid "DeployFreeze|Add deploy freeze"
-msgstr ""
+msgstr "加入å‡çµéƒ¨ç½²"
msgid "DeployFreeze|Delete"
-msgstr ""
+msgstr "刪除"
msgid "DeployFreeze|Delete deploy freeze?"
-msgstr ""
+msgstr "刪除å‡çµéƒ¨ç½²?"
msgid "DeployFreeze|Delete freeze period"
-msgstr ""
+msgstr "刪除å‡çµæœŸ"
msgid "DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?"
-msgstr ""
+msgstr "將刪除在 %{timezone} 從 %{start} 到 %{end} çš„å‡çµéƒ¨ç½²ï¼Œä½ ç¢ºå®šå—Žï¼Ÿ"
msgid "DeployFreeze|Edit"
-msgstr ""
+msgstr "編輯"
msgid "DeployFreeze|Freeze end"
-msgstr ""
+msgstr "å‡çµçµæŸ"
msgid "DeployFreeze|Freeze start"
-msgstr ""
+msgstr "å‡çµé–‹å§‹"
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}"
-msgstr ""
+msgstr "此專案ä¸å­˜åœ¨å‡çµéƒ¨ç½²ã€‚è¦åŠ å…¥ä¸€å€‹ï¼Œè«‹é¸æ“‡ %{strongStart}加入å‡çµéƒ¨ç½²%{strongEnd}"
msgid "DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
-msgstr ""
+msgstr "使用 %{cron_syntax_link_start}cron 語法%{cron_syntax_link_end} 指定å‡çµéƒ¨ç½²ã€‚"
msgid "DeployFreeze|Time zone"
-msgstr ""
+msgstr "時å€"
msgid "DeployKeys|+%{count} others"
-msgstr ""
+msgstr "+%{count} 其他"
msgid "DeployKeys|Current project"
-msgstr ""
+msgstr "ç›®å‰å°ˆæ¡ˆ"
msgid "DeployKeys|Deploy key"
-msgstr ""
+msgstr "部署金鑰"
msgid "DeployKeys|Enabled deploy keys"
-msgstr ""
+msgstr "已啟用的部署金鑰"
msgid "DeployKeys|Error enabling deploy key"
-msgstr ""
+msgstr "啟用部署金鑰發生錯誤"
msgid "DeployKeys|Error getting deploy keys"
-msgstr ""
+msgstr "å–得部署金鑰發生錯誤"
msgid "DeployKeys|Error removing deploy key"
-msgstr ""
+msgstr "移除部署金鑰時發生錯誤"
msgid "DeployKeys|Expand %{count} other projects"
-msgstr ""
+msgstr "展開 %{count} 個其他項目"
msgid "DeployKeys|Grant write permissions to this key"
-msgstr ""
+msgstr "授予此金鑰的寫入權é™"
msgid "DeployKeys|Loading deploy keys"
-msgstr ""
+msgstr "載入部署金鑰"
msgid "DeployKeys|No deploy keys found. Create one with the form above."
-msgstr ""
+msgstr "沒有找到部署金鑰。請使用上é¢çš„表單建立部署金鑰。"
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr ""
+msgstr "ç§æœ‰å­˜å–的部署金鑰"
msgid "DeployKeys|Project usage"
-msgstr ""
+msgstr "專案使用情æ³"
msgid "DeployKeys|Publicly accessible deploy keys"
-msgstr ""
+msgstr "公開存å–的部署金鑰"
msgid "DeployKeys|Read access only"
-msgstr ""
+msgstr "唯讀權é™"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
-msgstr ""
+msgstr "啟用部署令牌(權æ–)(%{active_tokens})"
msgid "DeployTokens|Allows read and write access to the package registry."
-msgstr ""
+msgstr "å…許å°è»Ÿé«”套件包註冊庫進行讀寫訪å•ã€‚"
msgid "DeployTokens|Allows read-only access to registry images."
-msgstr ""
+msgstr "å…許以唯讀權é™è®€å–倉庫中的映åƒã€‚"
msgid "DeployTokens|Allows read-only access to the package registry."
-msgstr ""
+msgstr "å…許å°è»Ÿé«”套件包註冊進行唯讀訪å•ã€‚"
msgid "DeployTokens|Allows read-only access to the repository."
-msgstr ""
+msgstr "å…許以唯讀權é™è®€å–該版本庫。"
msgid "DeployTokens|Allows write access to registry images."
-msgstr ""
+msgstr "å…許寫入該映åƒè¨»å†Šåº«ã€‚"
msgid "DeployTokens|Copy deploy token"
-msgstr ""
+msgstr "複製部署令牌(權æ–)"
msgid "DeployTokens|Copy username"
-msgstr ""
+msgstr "複製使用者å稱"
msgid "DeployTokens|Create a new deploy token for all projects in this group. %{link_start}What are deploy tokens?%{link_end}"
-msgstr ""
+msgstr "為該組中的所有專案建立一個新的部署令牌(權æ–)。 %{link_start}什麼是部署令牌(權æ–)?%{link_end}"
msgid "DeployTokens|Create deploy token"
-msgstr ""
+msgstr "建立部署令牌"
msgid "DeployTokens|Created"
-msgstr ""
+msgstr "建立時間"
msgid "DeployTokens|Deploy tokens"
-msgstr ""
+msgstr "部署令牌|部署令牌(權æ–)"
msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
-msgstr ""
+msgstr "部署令牌|部署令牌(權æ–)å…許存å–軟體套件ã€æ‚¨çš„版本庫和註冊庫映åƒæª”。"
msgid "DeployTokens|Enter a unique name for your deploy token."
-msgstr ""
+msgstr "部署令牌|為您的部署令牌(權æ–)輸入一個唯一的å稱。"
msgid "DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}."
-msgstr ""
+msgstr "為您的令牌輸入使用者å稱。é è¨­ç‚º %{code_start}gitlab+deploy-token-{n}%{code_end}。"
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
-msgstr ""
+msgstr "輸入令牌的到期日期。é è¨­ç‚ºæ°¸ä¸éŽæœŸã€‚"
msgid "DeployTokens|Expires"
-msgstr ""
+msgstr "éŽæœŸ"
msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
-msgstr ""
+msgstr "部署令牌|群組部署令牌å…許存å–群組內的軟體套件ã€ç‰ˆæœ¬åº«å’Œè¨»å†Šåº«æ˜ åƒæª”。"
msgid "DeployTokens|Name"
-msgstr ""
+msgstr "å稱"
msgid "DeployTokens|New deploy token"
-msgstr ""
+msgstr "部署令牌|新建部署令牌"
msgid "DeployTokens|Revoke"
-msgstr ""
+msgstr "撤銷"
msgid "DeployTokens|Revoke %{name}"
-msgstr ""
+msgstr "撤銷 %{name}"
msgid "DeployTokens|Scopes"
-msgstr ""
+msgstr "有效範åœ"
msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
-msgstr ""
+msgstr "部署令牌|此 %{entity_type} 沒有啟用的部署令牌。"
msgid "DeployTokens|This action cannot be undone."
-msgstr ""
+msgstr "該動作作無法復原。"
msgid "DeployTokens|This username supports access. %{link_start}What kind of access?%{link_end}"
-msgstr ""
+msgstr "該使用者å稱支æ´è¨ªå•æ¬Šé™ã€‚ %{link_start}什麼類型的訪å•æ¬Šé™ï¼Ÿ%{link_end}"
msgid "DeployTokens|Use this token as a password. Save it. This password can %{i_start}not%{i_end} be recovered."
-msgstr ""
+msgstr "使用此令牌作為密碼。此密碼 %{i_start}ä¸èƒ½%{i_end} 被回復。"
msgid "DeployTokens|Username"
-msgstr ""
+msgstr "使用者å稱"
msgid "DeployTokens|Your new Deploy Token username"
-msgstr ""
+msgstr "部署令牌|您的新部署令牌使用者å稱"
msgid "DeployTokens|Your new group deploy token has been created."
-msgstr ""
+msgstr "部署令牌|您的新群組佈署令牌已經建立。"
msgid "DeployTokens|Your new project deploy token has been created."
-msgstr ""
+msgstr "新項目部署令牌(權æ–)已建立。"
msgid "Deployed"
-msgstr ""
+msgstr "已部署"
msgid "Deployed to"
-msgstr ""
+msgstr "已部署到"
msgid "Deployed-after"
-msgstr ""
+msgstr "部署後"
msgid "Deployed-before"
-msgstr ""
+msgstr "部署å‰"
msgid "Deploying to"
-msgstr ""
+msgstr "正在部署到"
msgid "Deploying to AWS is easy with GitLab"
-msgstr ""
+msgstr "使用 GitLab 輕鬆部署到 AWS"
msgid "Deployment"
-msgstr ""
+msgstr "部署"
msgid "Deployment Frequency"
-msgstr ""
+msgstr "部署頻率"
msgid "Deployment Target|%{linkStart}How to provision or deploy to Kubernetes clusters from GitLab?%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}如何從 GitLab 設定或部署到 Kubernetes å¢é›†ï¼Ÿ%{linkEnd}"
msgid "Deployment Target|Project deployment target (optional)"
-msgstr ""
+msgstr "專案部署目標(å¯é¸ï¼‰"
msgid "Deployment Target|Select the deployment target"
-msgstr ""
+msgstr "é¸å–部署目標"
msgid "Deployment frequency"
-msgstr ""
+msgstr "部署頻率"
msgid "DeploymentApproval| Current approvals: %{current}"
-msgstr ""
+msgstr "ç›®å‰æ ¸å‡†ï¼š%{current}"
msgid "DeploymentApproval|Approval options"
-msgstr ""
+msgstr "核准é¸é …"
msgid "DeploymentApproval|Approve or reject deployment #%{deploymentIid}"
-msgstr ""
+msgstr "核准或拒絕部署 #%{deploymentIid}"
-msgid "DeploymentApproval|Approved by %{user} %{time}"
-msgstr ""
+msgid "DeploymentApproval|Approved %{time}"
+msgstr "您已在 %{time} 核准"
msgid "DeploymentApproval|Approved by you %{time}"
-msgstr ""
+msgstr "您已在 %{time} 核准"
msgid "DeploymentApproval|Approving will run the manual job from deployment #%{deploymentIid}. Rejecting will fail the manual job."
-msgstr ""
+msgstr "核准將從部署#%{deploymentIid}執行手動作業,拒絕將使手動作業失敗。"
msgid "DeploymentApproval|Deployment tier: %{tier}"
-msgstr ""
+msgstr "部署層: %{tier}"
msgid "DeploymentApproval|Environment: %{environment}"
-msgstr ""
+msgstr "環境: %{environment}"
msgid "DeploymentApproval|Manual job: %{jobName}"
-msgstr ""
+msgstr "手動作業: %{jobName}"
msgid "DeploymentTarget|GitLab Pages"
-msgstr ""
+msgstr "GitLab Pages"
msgid "DeploymentTarget|Heroku"
-msgstr ""
+msgstr "Heroku"
msgid "DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)"
-msgstr ""
+msgstr "基礎設施æ供商(Terraformã€Cloudformation 等)"
msgid "DeploymentTarget|Kubernetes (GKE, EKS, OpenShift, and so on)"
-msgstr ""
+msgstr "Kubernetes ( GKEã€EKSã€OpenShift ç­‰)"
msgid "DeploymentTarget|Managed container runtime (Fargate, Cloud Run, DigitalOcean App)"
-msgstr ""
+msgstr "管ç†å®¹å™¨é‹è¡Œæ™‚é–“ (Fargateã€Cloud Runã€DigitalOcean 應用程å¼)"
msgid "DeploymentTarget|Mobile app store"
-msgstr ""
+msgstr "行動應用程å¼å•†åº—"
msgid "DeploymentTarget|No deployment planned"
-msgstr ""
+msgstr "未計劃部署"
msgid "DeploymentTarget|Other hosting service"
-msgstr ""
+msgstr "其他主機æœå‹™"
msgid "DeploymentTarget|Registry (package or container)"
-msgstr ""
+msgstr "登錄表(軟體套件或容器)"
msgid "DeploymentTarget|Self-managed container runtime (Podman, Docker Swarm, Docker Compose)"
-msgstr ""
+msgstr "自我管ç†çš„容器é‹è¡Œæ™‚間(Podmanã€Docker Swarmã€Docker Compose)"
msgid "DeploymentTarget|Serverless backend (Lambda, Cloud functions)"
-msgstr ""
+msgstr "ç„¡æœå‹™å™¨å¾Œç«¯ï¼ˆLambdaã€é›²å‡½æ•¸ï¼‰"
msgid "DeploymentTarget|Virtual machine (for example, EC2)"
-msgstr ""
+msgstr "虛擬主機(例如 EC2)"
msgid "Deployments"
-msgstr ""
+msgstr "部署"
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
-msgstr[0] ""
+msgstr[0] "%{deployments} 環境å—到影響。"
msgid "Deployment|API"
-msgstr ""
+msgstr "API"
msgid "Deployment|Cancelled"
-msgstr ""
+msgstr "å·²å–消"
msgid "Deployment|Created"
-msgstr ""
+msgstr "已建立"
msgid "Deployment|Deployment ID"
-msgstr ""
+msgstr "部署 ID"
msgid "Deployment|Failed"
-msgstr ""
+msgstr "失敗"
msgid "Deployment|Latest Deployed"
-msgstr ""
+msgstr "最新部署"
msgid "Deployment|Needs Approval"
-msgstr ""
+msgstr "需è¦æ ¸å‡†"
msgid "Deployment|Running"
-msgstr ""
+msgstr "執行中"
msgid "Deployment|Skipped"
-msgstr ""
+msgstr "已略éŽ"
msgid "Deployment|Success"
-msgstr ""
+msgstr "æˆåŠŸ"
msgid "Deployment|This deployment was created using the API"
-msgstr ""
+msgstr "此部署使用API建立"
msgid "Deployment|Triggerer"
-msgstr ""
+msgstr "觸發器"
msgid "Deployment|Waiting"
-msgstr ""
+msgstr "等待中"
msgid "Deployment|blocked"
-msgstr ""
+msgstr "å·²å°éŽ–"
msgid "Deployment|canceled"
-msgstr ""
+msgstr "å·²å–消"
msgid "Deployment|created"
-msgstr ""
+msgstr "已建立"
msgid "Deployment|failed"
-msgstr ""
+msgstr "已失敗"
msgid "Deployment|running"
-msgstr ""
+msgstr "執行中"
msgid "Deployment|skipped"
-msgstr ""
+msgstr "部署|已略éŽ"
msgid "Deployment|success"
-msgstr ""
+msgstr "æˆåŠŸ"
msgid "Deprecated API rate limits"
-msgstr ""
+msgstr "已棄用的 API 速率é™åˆ¶"
msgid "Deprecations|Feature deprecation and removal"
-msgstr ""
+msgstr "棄用和移除功能"
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
-msgstr ""
+msgstr "關於å¯èƒ½æ›¿æ›çš„訊æ¯ï¼Œ%{epicStart}瞭解更多關於 Opstrace %{epicEnd}。"
msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
-msgstr ""
+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 ""
+msgstr "GitLab 14.7 中已棄用了日誌和跟踪功能,並計劃在 GitLab 15.0 中刪除 %{link_end} %{removal_link_start}。"
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
-msgstr ""
+msgstr "指標功能在 GitLab 14.7 中已棄用。"
msgid "Deprioritize label"
-msgstr ""
+msgstr "å–消優先標記"
msgid "Descending"
-msgstr ""
+msgstr "é™åº"
msgid "Describe the goal of the changes and what reviewers should be aware of."
-msgstr ""
+msgstr "æ述變更的目的以åŠè©•å¯©äººå“¡æ‡‰æ³¨æ„的事項。"
msgid "Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Description (alt text)"
-msgstr ""
+msgstr "æè¿° (替代文字)"
msgid "Description (optional)"
-msgstr ""
+msgstr "æ述(å¯é¸ï¼‰"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
-msgstr ""
+msgstr "使用%{link_start}GitLab風格Markdown%{link_end}解æžçš„æè¿°"
msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}."
-msgstr ""
+msgstr "使用 %{link_start}GitLab Flavored Markdown%{link_end} 解æžçš„æ述。"
msgid "Description:"
-msgstr ""
+msgstr "æè¿°:"
msgid "Descriptive label"
-msgstr ""
+msgstr "æ述性標記"
msgid "Design Management files and data"
-msgstr ""
+msgstr "設計管ç†æ–‡ä»¶å’Œè³‡æ–™"
msgid "Design repositories"
-msgstr ""
+msgstr "設計版本庫"
msgid "Design repository"
-msgstr ""
+msgstr "設計版本庫"
msgid "DesignManagement|%{current_design} of %{designs_count}"
-msgstr ""
+msgstr "%{current_design}/%{designs_count}"
msgid "DesignManagement|%{filename} did not change."
msgid_plural "DesignManagement|The designs you tried uploading did not change."
-msgstr[0] ""
+msgstr[0] "您嘗試上傳的設計沒有改變。"
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
-msgstr ""
+msgstr "加入具有相åŒæª”案å的設計會å–代為新版本的文件。"
msgid "DesignManagement|Archive design"
-msgstr ""
+msgstr "設計管ç†|歸檔設計"
msgid "DesignManagement|Archive designs"
-msgstr ""
+msgstr "歸檔設計"
msgid "DesignManagement|Archive selected"
-msgstr ""
+msgstr "å·²é¸æ“‡æª”案"
msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
-msgstr ""
+msgstr "已存檔的設計ä»å¯åœ¨ä¹‹å‰ç‰ˆæœ¬çš„設計集中使用。"
msgid "DesignManagement|Are you sure you want to archive the selected designs?"
-msgstr ""
+msgstr "您確定è¦æ­¸æª”所é¸çš„設計嗎?"
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
-msgstr ""
+msgstr "您確定è¦å–消å°æ­¤ç•™è¨€è©•è«–的更改嗎?"
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "您確定è¦å–消建立此留言評論嗎?"
msgid "DesignManagement|Cancel changes"
-msgstr ""
+msgstr "å–消變更"
msgid "DesignManagement|Cancel comment confirmation"
-msgstr ""
+msgstr "確èªå–消留言評論"
msgid "DesignManagement|Cancel comment update confirmation"
-msgstr ""
+msgstr "確èªå–消留言更新"
msgid "DesignManagement|Click the image where you'd like to start a new discussion"
-msgstr ""
+msgstr "單擊您è¦é–‹å§‹æ–°è¨Žè«–的圖åƒ"
msgid "DesignManagement|Comment"
-msgstr ""
+msgstr "留言(評論)"
msgid "DesignManagement|Could not add a new comment. Please try again."
-msgstr ""
+msgstr "無法新增新留言。請é‡è©¦ã€‚"
msgid "DesignManagement|Could not create new discussion. Please try again."
-msgstr ""
+msgstr "無法建立新討論。請é‡è©¦ã€‚"
msgid "DesignManagement|Could not update discussion. Please try again."
-msgstr ""
+msgstr "無法更新討論。請é‡è©¦ã€‚"
msgid "DesignManagement|Could not update note. Please try again."
-msgstr ""
+msgstr "無法更新註釋。請é‡è©¦ã€‚"
msgid "DesignManagement|Deselect all"
-msgstr ""
+msgstr "å–消全部é¸æ“‡"
msgid "DesignManagement|Designs"
-msgstr ""
+msgstr "設計"
msgid "DesignManagement|Discard comment"
-msgstr ""
+msgstr "æ¨æ£„留言"
msgid "DesignManagement|Download design"
-msgstr ""
+msgstr "下載設計"
msgid "DesignManagement|Error uploading a new design. Please try again."
-msgstr ""
+msgstr "上傳新設計時發生錯誤。請é‡è©¦ã€‚"
msgid "DesignManagement|Go back to designs"
-msgstr ""
+msgstr "返回到設計"
msgid "DesignManagement|Go to next design"
-msgstr ""
+msgstr "å‰å¾€ä¸‹ä¸€å€‹è¨­è¨ˆ"
msgid "DesignManagement|Go to previous design"
-msgstr ""
+msgstr "å‰å¾€ä¸Šä¸€å€‹è¨­è¨ˆ"
msgid "DesignManagement|Keep changes"
-msgstr ""
+msgstr "ä¿ç•™æ›´æ”¹"
msgid "DesignManagement|Keep comment"
-msgstr ""
+msgstr "ä¿ç•™ç•™è¨€"
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
-msgstr ""
+msgstr "請求的設計版本ä¸å­˜åœ¨ï¼Œé¡¯ç¤ºæœ€æ–°ç‰ˆæœ¬"
msgid "DesignManagement|Resolve thread"
-msgstr ""
+msgstr "處ç†çš„主題"
msgid "DesignManagement|Resolved Comments"
-msgstr ""
+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 ""
+msgstr "您嘗試上傳的一些設計沒有更改: %{skippedFiles} 和 %{moreCount}。"
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
-msgstr ""
+msgstr "您嘗試上傳的æŸäº›è¨­è¨ˆæ²’有更改:%{skippedFiles}。"
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
-msgstr ""
+msgstr "å…許上傳的設計最大數é‡ç‚º %{upload_limit}。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "DesignManagement|There was an error moving your designs. Please upload your designs below."
-msgstr ""
+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 ""
+msgstr "è¦ä¸Šå‚³è¨­è¨ˆï¼Œæ‚¨éœ€è¦å•Ÿç”¨ LFS 並讓管ç†å“¡å•Ÿç”¨å“ˆå¸Œå„²å­˜ã€‚ %{requirements_link_start}更多訊æ¯%{requirements_link_end}"
msgid "DesignManagement|Unresolve thread"
-msgstr ""
+msgstr "將主題置為未處ç†"
msgid "DesignManagement|Upload designs"
-msgstr ""
+msgstr "上傳設計"
msgid "DesignManagement|Upload skipped. %{reason}"
-msgstr ""
+msgstr "已跳éŽä¸Šå‚³ã€‚%{reason}"
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
-msgstr ""
+msgstr "您的設計正在複製éŽç¨‹ä¸­â€¦ 請刷新以ç²å¾—更新。"
msgid "Designs"
-msgstr ""
+msgstr "設計"
msgid "Destroy"
-msgstr ""
+msgstr "刪除"
msgid "Detail"
-msgstr ""
+msgstr "詳情"
msgid "Details"
-msgstr ""
+msgstr "詳情"
msgid "Details (default)"
-msgstr ""
+msgstr "詳細訊æ¯(é è¨­)"
msgid "Details block"
-msgstr ""
+msgstr "細節å€å¡Š"
msgid "Detect host keys"
-msgstr ""
+msgstr "檢測主機金鑰"
msgid "DevOps Adoption"
-msgstr ""
+msgstr "DevOps Adoption"
msgid "DevOps Reports"
-msgstr ""
+msgstr "DevOps 報告"
msgid "DevOps adoption"
-msgstr ""
+msgstr "DevOps adoption"
msgid "Devices (optional)"
-msgstr ""
+msgstr "設備(å¯é¸ï¼‰"
msgid "DevopsAdoption|%{adoptedCount}/%{featuresCount} %{title} features adopted"
-msgstr ""
+msgstr "%{adoptedCount}/%{featuresCount} %{title} 功能已採用"
msgid "DevopsAdoption|Add a group to get started"
-msgstr ""
+msgstr "加入一個群組以開始使用"
msgid "DevopsAdoption|Add or remove groups"
-msgstr ""
+msgstr "加入或刪除群組"
msgid "DevopsAdoption|Add or remove subgroups"
-msgstr ""
+msgstr "加入或刪除å­ç¾¤çµ„"
msgid "DevopsAdoption|Adopted"
-msgstr ""
+msgstr "已採用"
msgid "DevopsAdoption|Adoption by group"
-msgstr ""
+msgstr "按群組採用"
msgid "DevopsAdoption|Adoption by subgroup"
-msgstr ""
+msgstr "按å­ç¾¤çµ„採用"
msgid "DevopsAdoption|Adoption over time"
-msgstr ""
+msgstr "隨時間推移採用"
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
-msgstr ""
+msgstr "移除群組時發生錯誤。請é‡è©¦ã€‚"
msgid "DevopsAdoption|Approvals"
-msgstr ""
+msgstr "核准"
msgid "DevopsAdoption|Are you sure that you would like to remove %{name} from the table?"
-msgstr ""
+msgstr "您確定è¦å¾žè¡¨æ ¼ä¸­ç§»é™¤ %{name} 嗎?"
msgid "DevopsAdoption|At least one approval on a merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚至少ç²å¾—一項核准"
msgid "DevopsAdoption|At least one deploy"
-msgstr ""
+msgstr "至少一個部署"
msgid "DevopsAdoption|At least one issue created"
-msgstr ""
+msgstr "至少建立一個議題 (issue)"
msgid "DevopsAdoption|At least one merge request created"
-msgstr ""
+msgstr "至少建立一個åˆä½µè«‹æ±‚"
msgid "DevopsAdoption|At least one pipeline successfully run"
-msgstr ""
+msgstr "至少一個æˆåŠŸåŸ·è¡Œçš„æµæ°´ç·š"
msgid "DevopsAdoption|Code owners"
-msgstr ""
+msgstr "程å¼ç¢¼æ“有者"
msgid "DevopsAdoption|Code owners enabled for at least one project"
-msgstr ""
+msgstr "為至少一個專案啟用程å¼ç¢¼æ“有者"
msgid "DevopsAdoption|Confirm remove Group"
-msgstr ""
+msgstr "確èªç§»é™¤ç¾¤çµ„"
msgid "DevopsAdoption|DAST"
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ€§æ¸¬è©¦ (DAST)"
msgid "DevopsAdoption|DAST enabled for at least one project"
-msgstr ""
+msgstr "為至少一個專案啟用動態應用程å¼å®‰å…¨æ€§æ¸¬è©¦ (DAST)"
msgid "DevopsAdoption|Dependency Scanning"
-msgstr ""
+msgstr "ä¾è³´é …掃æ中"
msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
-msgstr ""
+msgstr "為至少一個專案啟用ä¾è³´æŽƒæ"
msgid "DevopsAdoption|Deploys"
-msgstr ""
+msgstr "部署"
msgid "DevopsAdoption|Dev"
-msgstr ""
+msgstr "開發"
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
-msgstr ""
+msgstr "DevOps Adoption 追蹤您最喜歡群組關éµåŠŸèƒ½çš„使用情æ³ï¼Œå°‡ç¾¤çµ„加入到表中以開始。"
msgid "DevopsAdoption|Edit groups"
-msgstr ""
+msgstr "編輯群組"
msgid "DevopsAdoption|Edit subgroups"
-msgstr ""
+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 ""
+msgstr "功能採用基於上一個日曆月的使用情æ³ï¼Œè³‡æ–™åœ¨æ¯å€‹æœˆåˆæ›´æ–°ï¼Œæœ€å¾Œæ›´æ–°ï¼š %{timestamp}。"
msgid "DevopsAdoption|Fuzz Testing"
-msgstr ""
+msgstr "模糊測試"
msgid "DevopsAdoption|Fuzz Testing enabled for at least one project"
-msgstr ""
+msgstr "至少為一個專案啟用了模糊測試"
msgid "DevopsAdoption|Issues"
-msgstr ""
+msgstr "議題"
msgid "DevopsAdoption|MRs"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "DevopsAdoption|No results…"
-msgstr ""
+msgstr "沒有çµæžœâ€¦"
msgid "DevopsAdoption|No tracked features"
-msgstr ""
+msgstr "沒有跟蹤的功能"
msgid "DevopsAdoption|Not adopted"
-msgstr ""
+msgstr "DevopsAdoption|未採用"
msgid "DevopsAdoption|Ops"
-msgstr ""
+msgstr "維é‹"
msgid "DevopsAdoption|Overall adoption"
-msgstr ""
+msgstr "å…¨é¢æŽ¡ç”¨"
msgid "DevopsAdoption|Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "DevopsAdoption|Remove Group"
-msgstr ""
+msgstr "刪除群組"
msgid "DevopsAdoption|Remove Group from the table."
-msgstr ""
+msgstr "從表中刪除群組。"
msgid "DevopsAdoption|Runner configured for project/group"
-msgstr ""
+msgstr "為專案/群組é…置的Runner"
msgid "DevopsAdoption|Runners"
-msgstr ""
+msgstr "Runners"
msgid "DevopsAdoption|SAST"
-msgstr ""
+msgstr "SAST"
msgid "DevopsAdoption|SAST enabled for at least one project"
-msgstr ""
+msgstr "至少為一個專案啟用了 SAST"
msgid "DevopsAdoption|Sec"
-msgstr ""
+msgstr "安全"
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
-msgstr ""
+msgstr "DevopsAdoption|啟用目å‰ç¾¤çµ„時發生錯誤。請é‡æ–°æ•´ç†é é¢ã€‚"
msgid "DevopsAdoption|There was an error fetching Group adoption data. Please refresh the page."
-msgstr ""
+msgstr "å–得群組採用資料時發生錯誤,請é‡æ–°æ•´ç†é é¢ã€‚"
msgid "DevopsAdoption|There was an error fetching Groups. Please refresh the page."
-msgstr ""
+msgstr "å–得群組時發生錯誤,請é‡æ–°æ•´ç†é é¢ã€‚"
msgid "DevopsAdoption|This group has no subgroups"
-msgstr ""
+msgstr "此群組沒有å­ç¾¤çµ„"
msgid "DevopsAdoption|Total number of features adopted"
-msgstr ""
+msgstr "已採ç´çš„特性總數"
msgid "DevopsAdoption|You cannot remove the group you are currently in."
-msgstr ""
+msgstr "您ä¸èƒ½åˆªé™¤æ‚¨ç•¶å‰æ‰€åœ¨çš„群組。"
msgid "DevopsReport|DevOps Score"
-msgstr ""
+msgstr "DevOps分數"
msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
-msgstr ""
+msgstr "DevOps 評分指標基於éŽåŽ» 30 天的使用情æ³ï¼Œæœ€å¾Œæ›´æ–°ï¼š%{timestamp}。"
msgid "DevopsReport|High"
-msgstr ""
+msgstr "高"
msgid "DevopsReport|Leader usage"
-msgstr ""
+msgstr "領導者使用情æ³"
msgid "DevopsReport|Low"
-msgstr ""
+msgstr "低"
msgid "DevopsReport|Moderate"
-msgstr ""
+msgstr "中"
msgid "DevopsReport|Overview"
-msgstr ""
+msgstr "概觀"
msgid "DevopsReport|Score"
-msgstr ""
+msgstr "分數"
msgid "DevopsReport|Your score"
-msgstr ""
+msgstr "您的分數"
msgid "DevopsReport|Your usage"
-msgstr ""
+msgstr "您的使用情æ³"
msgid "Diagram (%{language})"
-msgstr ""
+msgstr "圖表 (%{language})"
msgid "Did not delete the source branch."
-msgstr ""
+msgstr "未刪除來æºåˆ†æ”¯"
msgid "Didn't receive a confirmation email?"
-msgstr ""
+msgstr "沒有收到確èªéƒµä»¶ï¼Ÿ"
msgid "Didn't receive confirmation instructions?"
-msgstr ""
+msgstr "沒有收到確èªèªªæ˜Žï¼Ÿ"
msgid "Didn't receive unlock instructions?"
-msgstr ""
+msgstr "沒有收到解鎖說明?"
msgid "Diff files surpassing this limit will be presented as 'too large' and won't be expandable."
-msgstr ""
+msgstr "超éŽæ­¤é™åˆ¶çš„差異文件將顯示為「太大ã€ä¸¦ä¸”無法擴展。"
msgid "Diff limits"
-msgstr ""
+msgstr "差異é™åˆ¶"
msgid "Diff notes"
-msgstr ""
+msgstr "差界說明"
msgid "Difference between start date and now"
-msgstr ""
+msgstr "開始日期和ç¾åœ¨ä¹‹é–“的差異"
msgid "DiffsCompareBaseBranch|(HEAD)"
-msgstr ""
+msgstr "(HEAD)"
msgid "DiffsCompareBaseBranch|(base)"
-msgstr ""
+msgstr "(æº)"
msgid "Diffs|%d addition"
msgid_plural "Diffs|%d additions"
-msgstr[0] ""
+msgstr[0] "%d 個加入"
msgid "Diffs|%d deletion"
msgid_plural "Diffs|%d deletions"
-msgstr[0] ""
+msgstr[0] "%d 個刪除"
msgid "Diffs|Expand all lines"
-msgstr ""
+msgstr "展開所有行"
msgid "Diffs|Next 20 lines"
-msgstr ""
+msgstr "下20行"
msgid "Diffs|No file name available"
-msgstr ""
+msgstr "ç„¡å¯ç”¨çš„檔案å"
msgid "Diffs|Previous 20 lines"
-msgstr ""
+msgstr "å‰20è¡Œ"
msgid "Diffs|Show %{unfoldCount} lines"
-msgstr ""
+msgstr "顯示%{unfoldCount}行"
msgid "Diffs|Show all unchanged lines"
-msgstr ""
+msgstr "顯示所有未更改的行"
msgid "Diffs|Showing %{dropdownStart}%{count} changed file%{dropdownEnd}"
msgid_plural "Diffs|Showing %{dropdownStart}%{count} changed files%{dropdownEnd}"
-msgstr[0] ""
+msgstr[0] "顯示 %{dropdownStart}%{count} 個更改的檔案%{dropdownEnd}"
msgid "Diffs|Something went wrong while fetching diff lines."
-msgstr ""
+msgstr "å–得差異行時發生錯誤。"
msgid "Diffs|with %{additions} and %{deletions}"
-msgstr ""
+msgstr "有 %{additions} 和 %{deletions}"
msgid "Direct member"
-msgstr ""
+msgstr "直接æˆå“¡"
msgid "Direct members"
-msgstr ""
+msgstr "直接æˆå“¡"
msgid "Direct non-authenticated users to this page."
-msgstr ""
+msgstr "å°‡éžèªè­‰ä½¿ç”¨è€…直接導å‘æ­¤é é¢ã€‚"
msgid "Direct users to this page after they sign out."
-msgstr ""
+msgstr "登入後,將使用者導å‘æ­¤é é¢ã€‚"
msgid "Direction"
-msgstr ""
+msgstr "æ–¹å‘"
msgid "Directory name"
-msgstr ""
+msgstr "目錄å稱"
msgid "Disable"
-msgstr ""
+msgstr "åœç”¨"
msgid "Disable Two-factor Authentication"
-msgstr ""
+msgstr "ç¦ç”¨é›™é‡èªè­‰"
msgid "Disable What's new"
-msgstr ""
+msgstr "åœç”¨æœ€è¿‘æ›´æ–°"
msgid "Disable for this project"
-msgstr ""
+msgstr "在此專案中åœç”¨"
msgid "Disable group runners"
-msgstr ""
+msgstr "åœç”¨ç¾¤çµ„執行器"
msgid "Disable two-factor authentication"
-msgstr ""
+msgstr "åœç”¨é›™å› å­èªè­‰"
msgid "Disabled"
msgstr "å·²åœç”¨"
msgid "Disabled by %{parent} owner"
-msgstr ""
+msgstr "已被 %{parent} æ“有者åœç”¨"
msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
-msgstr ""
+msgstr "å·²åœç”¨æ˜ åƒåªèƒ½ç”±å¯¦é«”æ“有者啟用。建議刪除此項。"
msgid "Discard"
-msgstr ""
+msgstr "æ¨æ£„"
msgid "Discard all changes"
-msgstr ""
+msgstr "放棄所有變更"
msgid "Discard all changes?"
-msgstr ""
+msgstr "æ¨æ£„所有變更?"
msgid "Discard changes"
-msgstr ""
+msgstr "放棄變更"
msgid "Discard changes to %{path}?"
-msgstr ""
+msgstr "æ”¾æ£„å° %{path} 的變更嗎?"
msgid "Discard draft"
-msgstr ""
+msgstr "å–消"
msgid "DiscordService|Discord Notifications"
-msgstr ""
+msgstr "Discord 通知"
msgid "DiscordService|Send notifications about project events to a Discord channel."
-msgstr ""
+msgstr "å‘ Discord é »é“發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。"
msgid "Discover"
-msgstr ""
+msgstr "Discover"
msgid "Discover GitLab Geo"
-msgstr ""
+msgstr "探索GitLab Geo"
msgid "Discover projects, groups and snippets. Share your projects with others"
-msgstr ""
+msgstr "ç€è¦½å°ˆæ¡ˆï¼Œç¾¤çµ„和程å¼ç¢¼ç‰‡æ®µã€‚與他人分享您的專案"
msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
-msgstr ""
+msgstr "Discover|檢查您的應用程å¼æ˜¯å¦å­˜åœ¨å¯èƒ½å°Žè‡´æœªç¶“授權的存å–ã€è³‡æ–™æ´©éœ²å’Œæ‹’絕æœå‹™çš„安全æ¼æ´žã€‚"
msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
-msgstr ""
+msgstr "å°æ–¼å·²ç¶“發布到生產環境中的程å¼ç¢¼ï¼Œæˆ‘們的儀表æ¿ç‚ºæ‚¨æ供了一種簡單的方å¼ä¾†å®šè¨‚已發ç¾å•é¡Œçš„優先處ç†å±¤ç´šï¼Œ 從而增強您的團隊能力,實ç¾å¿«é€Ÿå’Œå®‰å…¨åœ°ç™¼å¸ƒã€‚"
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å°‡å°æ‚¨çš„應用程å¼ç¨‹å¼ç¢¼åŸ·è¡Œéœæ…‹å’Œå‹•æ…‹æ¸¬è©¦ï¼ŒæŸ¥æ‰¾å·²çŸ¥ç¼ºé™·ï¼›ä¸¦åœ¨åˆä½µè«‹æ±‚中報告這些缺陷,以便您å¯ä»¥åœ¨åˆä½µä¹‹å‰ä¿®å¾©å®ƒå€‘。"
msgid "Discover|Security capabilities, integrated into your development lifecycle"
-msgstr ""
+msgstr "安全能力,整åˆåˆ°æ‚¨çš„開發生命週期中"
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
-msgstr ""
+msgstr "查看 %{linkStart}旗艦版方案%{linkEnd} 的其它功能"
msgid "Discover|Start a free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "Discover|Upgrade now"
-msgstr ""
+msgstr "ç«‹å³å‡ç´š"
msgid "Discuss a specific suggestion or question internally that needs to be resolved."
-msgstr ""
+msgstr "在內部討論需è¦è§£æ±ºçš„具體建議或å•é¡Œã€‚"
msgid "Discuss a specific suggestion or question internally."
-msgstr ""
+msgstr "在內部討論具體的建議或å•é¡Œã€‚"
msgid "Discuss a specific suggestion or question that needs to be resolved."
-msgstr ""
+msgstr "討論需è¦è§£æ±ºçš„具體建議或å•é¡Œã€‚"
msgid "Discuss a specific suggestion or question."
-msgstr ""
+msgstr "討論具體的建議或å•é¡Œã€‚"
msgid "Discussion to reply to cannot be found"
-msgstr ""
+msgstr "無法找到è¦å¾©åŽŸçš„討論"
msgid "Disk Usage"
-msgstr ""
+msgstr "ç£ç¢Ÿä½¿ç”¨æƒ…æ³"
msgid "Dismiss"
-msgstr ""
+msgstr "忽略"
msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
-msgstr[0] ""
+msgstr[0] "忽略%d個é¸å®šçš„æ¼æ´žï¼Œå°‡å®ƒå€‘歸類為"
msgid "Dismiss Alert"
-msgstr ""
+msgstr "忽略警報"
msgid "Dismiss merge request promotion"
-msgstr ""
+msgstr "關閉åˆä½µè«‹æ±‚推薦"
msgid "Dismiss selected"
-msgstr ""
+msgstr "忽略é¸å–專案"
msgid "Dismiss trial promotion"
-msgstr ""
+msgstr "關閉試用推薦"
msgid "Dismissable"
-msgstr ""
+msgstr "å¯å¿½ç•¥"
msgid "Dismissed"
-msgstr ""
+msgstr "已忽略"
msgid "Dismissed at %{projectLink}"
-msgstr ""
+msgstr "在%{projectLink}中忽略"
msgid "Dismissed on pipeline %{pipelineLink}"
-msgstr ""
+msgstr "在æµæ°´ç·š%{pipelineLink}上忽略"
msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
-msgstr ""
+msgstr "在%{projectLink} 中的æµæ°´ç·š %{pipelineLink}上忽略"
msgid "Display"
-msgstr ""
+msgstr "顯示"
msgid "Display alerts from all configured monitoring tools."
-msgstr ""
+msgstr "顯示來自所有設定監控工具的警報。"
msgid "Display milestones"
-msgstr ""
+msgstr "顯示里程碑"
msgid "Display name"
-msgstr ""
+msgstr "顯示å稱"
msgid "Display progress of child issues"
-msgstr ""
+msgstr "顯示å­è­°é¡Œçš„進度"
msgid "Display rendered file"
-msgstr ""
+msgstr "顯示渲染後文件"
msgid "Display source"
-msgstr ""
+msgstr "顯示來æº"
msgid "Display time tracking in issues in total hours only. %{link_start}What is time tracking?%{link_end}"
-msgstr ""
+msgstr "僅顯示å•é¡Œä¸­çš„總å°æ™‚數追踪時間。 %{link_start}什麼是時間追踪?%{link_end}"
msgid "Do not display content for customer experience improvement and offers from third parties"
-msgstr ""
+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 "ä¸è¦å¼·è¡ŒæŽ¨å‹•å·²åˆ†æ­§çš„ref。建立映åƒå¾Œï¼Œåªèƒ½ä½¿ç”¨ API 修改此設置。 %{mirroring_docs_link_start}瞭解有關此é¸é …%{link_closing_tag} å’Œ %{mirroring_api_docs_link_start}API 的更多訊æ¯ã€‚%{link_closing_tag}"
msgid "Do you want to remove this deploy key?"
-msgstr ""
+msgstr "您是å¦è¦ç§»é™¤æ­¤éƒ¨ç½²é‡‘鑰?"
msgid "Dockerfile"
-msgstr ""
+msgstr "Dockerfile"
msgid "Documentation"
-msgstr ""
+msgstr "文件"
msgid "Documentation for popular identity providers"
-msgstr ""
+msgstr "常見的身份驗證æ供商的相關文件"
msgid "Documentation pages URL"
-msgstr ""
+msgstr "文件é é¢ URL"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
-msgstr ""
-
-msgid "Does not delete the source branch."
-msgstr ""
+msgstr "文件é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
msgid "Domain"
-msgstr ""
+msgstr "網域"
msgid "Domain Name"
-msgstr ""
+msgstr "網域å稱"
msgid "Don't have a group?"
-msgstr ""
+msgstr "沒有群組?"
msgid "Don't have an account yet?"
-msgstr ""
+msgstr "還沒有帳號?"
msgid "Don't include description in commit message"
-msgstr ""
+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 ""
+msgstr "ä¸è¦æŠŠGPG金鑰中的ç§é‘°éƒ¨åˆ†è²¼éŽä¾†ï¼Œè«‹åªè²¼ä¸Šå…¬é‘°éƒ¨åˆ†ï¼Œå…¶é–‹é ­ç‚º '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
msgid "Don't send service data"
-msgstr ""
+msgstr "請勿發é€æœå‹™è³‡æ–™"
msgid "Don't show again"
-msgstr ""
+msgstr "ä¸å†é¡¯ç¤º"
msgid "Done"
-msgstr ""
+msgstr "完æˆ"
msgid "Dormant users"
-msgstr ""
+msgstr "休眠使用者"
msgid "Download"
-msgstr ""
+msgstr "下載"
msgid "Download %{format}"
-msgstr ""
+msgstr "下載%{format}"
msgid "Download %{format}:"
-msgstr ""
+msgstr "下載%{format}:"
msgid "Download (%{fileSizeReadable})"
-msgstr ""
+msgstr "下載(%{fileSizeReadable})"
msgid "Download (%{size})"
-msgstr ""
+msgstr "下載(%{size})"
msgid "Download CSV"
-msgstr ""
+msgstr "下載CSV"
msgid "Download PDF"
-msgstr ""
+msgstr "下載 PDF"
msgid "Download artifacts"
-msgstr ""
+msgstr "下載產物"
msgid "Download codes"
-msgstr ""
+msgstr "下載程å¼ç¢¼"
msgid "Download evidence JSON"
-msgstr ""
+msgstr "下載JSON憑證"
msgid "Download export"
-msgstr ""
+msgstr "下載匯出"
msgid "Download image"
-msgstr ""
+msgstr "下載圖片"
msgid "Download payload"
-msgstr ""
+msgstr "下載è£è¼‰"
msgid "Download raw data (.csv)"
-msgstr ""
+msgstr "下載原始資料 (.csv)"
msgid "Download source code"
-msgstr ""
+msgstr "下載原始碼"
msgid "Download this directory"
-msgstr ""
+msgstr "下載此目錄"
msgid "DownloadCommit|Email Patches"
-msgstr ""
+msgstr "é›»å­éƒµä»¶è£œä¸"
msgid "DownloadCommit|Plain Diff"
-msgstr ""
+msgstr "差異文件"
msgid "DownloadSource|Download"
-msgstr ""
+msgstr "下載"
msgid "Downstream"
-msgstr ""
+msgstr "下游"
msgid "Downvotes"
-msgstr ""
+msgstr "踩"
msgid "Draft"
-msgstr ""
+msgstr "è‰ç¨¿"
msgid "Draft: %{filename}"
-msgstr ""
+msgstr "è‰ç¨¿ï¼š%{filename}"
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
+msgstr "將您的設計拖到此處或 %{linkStart} 點擊上傳 %{linkEnd}。"
msgid "Drop or %{linkStart}upload%{linkEnd} file to attach"
-msgstr ""
+msgstr "拖放或 %{linkStart}上傳%{linkEnd} 文件以附加文件"
msgid "Drop or %{linkStart}upload%{linkEnd} files to attach"
-msgstr ""
+msgstr "拖放或%{linkStart}上傳%{linkEnd}文件以附加"
msgid "Drop your designs to start your upload."
-msgstr ""
+msgstr "拖放您的設計以啟動上傳。"
msgid "Drop your files to start your upload."
-msgstr ""
+msgstr "拖放您的文件以啟動上傳。"
msgid "DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}."
-msgstr ""
+msgstr "å–得所é¸%{issuableType}çš„%{issuableAttribute}時發生錯誤。"
msgid "DropdownWidget|Assign %{issuableAttribute}"
-msgstr ""
+msgstr "分派 %{issuableAttribute}"
msgid "DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again."
-msgstr ""
+msgstr "無法為此%{issuableType}å–å¾—%{issuableAttribute},請é‡è©¦ã€‚"
msgid "DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again."
-msgstr ""
+msgstr "在%{issuableType}設置%{issuableAttribute}失敗,請é‡è©¦ã€‚"
msgid "DropdownWidget|No %{issuableAttribute}"
-msgstr ""
+msgstr "ç„¡ %{issuableAttribute}"
msgid "DropdownWidget|No %{issuableAttribute} found"
-msgstr ""
+msgstr "未找到 %{issuableAttribute}"
msgid "DropdownWidget|No open %{issuableAttribute} found"
-msgstr ""
+msgstr "找ä¸åˆ°é–‹æ”¾çš„ %{issuableAttribute}"
msgid "Due Date"
-msgstr ""
+msgstr "截止日期"
msgid "Due date"
-msgstr ""
+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 ""
+msgstr "由於ä¸æ´»èºï¼Œ%{project_link}專案計劃於%{b_open}%{deletion_date}%{b_close}刪除。è¦å–消%{project_link}的刪除計劃,請å°å…¶åŸ·è¡Œä¸€äº›æ´»å‹•ã€‚例如:"
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 "由於ä¸æ´»èºï¼Œ%{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 ""
+msgstr "由於ä¸æ´»èºï¼Œæ­¤å°ˆæ¡ˆè¨ˆåŠƒæ–¼%{deletion_date}刪除。%{link_start}為什麼è¦å®‰æŽ’這個?%{link_end}"
msgid "Duplicate page: %{error_message}"
-msgstr ""
+msgstr "é‡è¤‡çš„é é¢: %{error_message}"
msgid "Duration"
-msgstr ""
+msgstr "時長"
msgid "Duration (min)"
-msgstr ""
+msgstr "時長 (分「"
msgid "Duration|%s days"
-msgstr ""
+msgstr "%s 天"
msgid "Duration|%s hours"
-msgstr ""
+msgstr "%s å°æ™‚"
msgid "Duration|%s minutes"
-msgstr ""
+msgstr "%s 分é˜"
msgid "Duration|%s months"
-msgstr ""
+msgstr "%s 個月"
msgid "Duration|%s seconds"
-msgstr ""
+msgstr "%s 秒"
msgid "Duration|%s weeks"
-msgstr ""
+msgstr "%s 週"
msgid "Duration|%s years"
-msgstr ""
+msgstr "%s å¹´"
msgid "Duration|1 day"
-msgstr ""
+msgstr "1 天"
msgid "Duration|1 hour"
-msgstr ""
+msgstr "1 å°æ™‚"
msgid "Duration|1 minute"
-msgstr ""
+msgstr "1 分é˜"
msgid "Duration|1 month"
-msgstr ""
+msgstr "1 個月"
msgid "Duration|1 week"
-msgstr ""
+msgstr "1 周"
msgid "Duration|1 year"
-msgstr ""
+msgstr "1 å¹´"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
-msgstr ""
+msgstr "在此éŽç¨‹ä¸­ï¼Œæˆ‘們會è¦æ±‚您æ供來自 GitLab çš„ URL 。請使用下é¢çš„網å€ã€‚"
msgid "Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ€§æ¸¬è©¦(DAST)"
msgid "E-mail:"
-msgstr ""
+msgstr "é›»å­éƒµä»¶ï¼š"
msgid "Each project can also have an issue tracker and a wiki."
-msgstr ""
+msgstr "æ¯å€‹å°ˆæ¡ˆé‚„å¯ä»¥æœ‰ä¸€å€‹è­°é¡Œè¿½è¹¤å™¨å’Œä¸€å€‹ wiki。"
msgid "Edit"
msgstr "編輯"
msgid "Edit %{name}"
-msgstr ""
+msgstr "編輯%{name}"
msgid "Edit %{profileType} profile"
-msgstr ""
+msgstr "編輯 %{profileType} 個人資料"
msgid "Edit Comment"
-msgstr ""
+msgstr "編輯留言"
msgid "Edit Deploy Key"
-msgstr ""
+msgstr "編輯部署金鑰"
msgid "Edit Geo Site"
-msgstr ""
+msgstr "編輯 Geo 站點"
msgid "Edit Group Hook"
-msgstr ""
+msgstr "編輯群組掛鉤"
msgid "Edit Identity"
-msgstr ""
+msgstr "編輯身份"
msgid "Edit Label"
-msgstr ""
+msgstr "編輯標籤"
msgid "Edit Milestone"
-msgstr ""
+msgstr "編輯里程碑"
msgid "Edit Password"
-msgstr ""
+msgstr "編輯密碼"
msgid "Edit Pipeline Schedule"
-msgstr ""
+msgstr "編輯æµæ°´ç·šè¨ˆåŠƒ"
msgid "Edit Release"
-msgstr ""
+msgstr "編輯發佈"
msgid "Edit Requirement"
-msgstr ""
+msgstr "編輯需求"
msgid "Edit Slack integration"
-msgstr ""
+msgstr "編輯Slackæ•´åˆ"
msgid "Edit Snippet"
-msgstr ""
+msgstr "編輯程å¼ç¢¼ç‰‡æ®µ"
msgid "Edit System Hook"
-msgstr ""
+msgstr "編輯系統掛鉤"
msgid "Edit application"
-msgstr ""
+msgstr "編輯應用"
msgid "Edit audio description"
-msgstr ""
+msgstr "編輯音頻æè¿°"
msgid "Edit comment"
-msgstr ""
+msgstr "編輯留言"
msgid "Edit commit message"
-msgstr ""
+msgstr "編輯æ交訊æ¯"
msgid "Edit deploy freeze"
-msgstr ""
+msgstr "編輯å‡çµéƒ¨ç½²"
msgid "Edit deploy key"
-msgstr ""
+msgstr "編輯部署金鑰"
msgid "Edit description"
-msgstr ""
+msgstr "編輯æ述訊æ¯"
msgid "Edit environment"
-msgstr ""
+msgstr "編輯環境"
msgid "Edit epics"
-msgstr ""
+msgstr "編輯å²è©©"
msgid "Edit files in the editor and commit changes here"
-msgstr ""
+msgstr "在編輯器中編輯文件,並在這裡​​æ交變更內容"
msgid "Edit fork in Web IDE"
-msgstr ""
+msgstr "在Web IDE中編輯延生的分支(fork)"
msgid "Edit group application"
-msgstr ""
+msgstr "編輯群組應用程å¼"
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "編輯群組:%{group_name}"
msgid "Edit identity for %{user_name}"
-msgstr ""
+msgstr "編輯 %{user_name} 的身份訊æ¯"
msgid "Edit image description"
-msgstr ""
+msgstr "編輯映åƒæè¿°"
msgid "Edit in pipeline editor"
-msgstr ""
+msgstr "在æµæ°´ç·šç·¨è¼¯å™¨ä¸­ç·¨è¼¯"
msgid "Edit in single-file editor"
-msgstr ""
+msgstr "在單文件編輯器中編輯"
msgid "Edit inline"
-msgstr ""
+msgstr "å…§è¯ç·¨è¼¯"
msgid "Edit issues"
-msgstr ""
+msgstr "編輯議題"
msgid "Edit link"
-msgstr ""
+msgstr "編輯連çµ"
msgid "Edit merge requests"
-msgstr ""
+msgstr "編輯åˆä½µè«‹æ±‚"
msgid "Edit public deploy key"
-msgstr ""
+msgstr "編輯公共部署金鑰"
msgid "Edit sidebar"
-msgstr ""
+msgstr "編輯å´é‚Šæ¬„"
msgid "Edit table"
-msgstr ""
+msgstr "編輯表"
msgid "Edit this file only."
-msgstr ""
+msgstr "僅編輯此檔案。"
msgid "Edit this release"
-msgstr ""
+msgstr "編輯此發佈"
msgid "Edit title and description"
-msgstr ""
+msgstr "編輯標題和æè¿°"
msgid "Edit topic: %{topic_name}"
-msgstr ""
+msgstr "編輯主題:%{topic_name}"
msgid "Edit user: %{user_name}"
-msgstr ""
+msgstr "編輯使用者:%{user_name}"
msgid "Edit video description"
-msgstr ""
+msgstr "編輯視頻æè¿°"
msgid "Edit wiki page"
-msgstr ""
+msgstr "編輯Wikié é¢"
msgid "Edit your most recent comment in a thread (from an empty textarea)"
-msgstr ""
+msgstr "編輯你在最近話題中的留言(從空白文字å€)"
msgid "Edit, lint, and visualize your pipeline."
-msgstr ""
+msgstr "編輯ã€æ•´ç†å’Œå¯è¦–化您的æµæ°´ç·šã€‚"
msgid "Edited"
-msgstr ""
+msgstr "已編輯"
msgid "Edited %{timeago}"
-msgstr ""
+msgstr "編輯於%{timeago}"
msgid "Editing"
-msgstr ""
+msgstr "編輯中"
msgid "Elapsed time"
-msgstr ""
+msgstr "已經éŽæ™‚é–“"
msgid "Elasticsearch AWS IAM credentials"
-msgstr ""
+msgstr "Elasticsearch AWS IAM 憑證"
msgid "Elasticsearch HTTP client timeout value in seconds."
-msgstr ""
+msgstr "Elasticsearch HTTP 客戶端超時數值(以秒為單ä½ï¼‰ã€‚"
msgid "Elasticsearch indexing restrictions"
-msgstr ""
+msgstr "Elasticsearch 索引é™åˆ¶"
msgid "Elasticsearch indexing started"
-msgstr ""
+msgstr "Elasticsearch 索引已啟動"
msgid "Elasticsearch migration halted"
-msgstr ""
+msgstr "Elasticsearch å·²åœæ­¢é·ç§»"
msgid "Elasticsearch reindexing is already in progress"
-msgstr ""
+msgstr "Elasticsearch é‡å»ºç´¢å¼•æ­£åœ¨é€²è¡Œä¸­"
msgid "Elasticsearch reindexing triggered"
-msgstr ""
+msgstr "Elasticsearch 已觸發é‡å»ºç´¢å¼•"
msgid "Elasticsearch reindexing was not started: %{errors}"
-msgstr ""
+msgstr "Elasticsearch é‡å»ºç´¢å¼•å°šæœªé–‹å§‹ï¼š%{errors}"
msgid "Elasticsearch zero-downtime reindexing"
-msgstr ""
+msgstr "Elasticsearch ä¸åœæ©Ÿé‡å»ºç´¢å¼•ä¸­"
msgid "Elasticsearch's region."
-msgstr ""
+msgstr "Elasticsearch çš„å€åŸŸã€‚"
msgid "Elastic|None. Select namespaces to index."
-msgstr ""
+msgstr "無。請é¸æ“‡è¦å»ºç«‹ç´¢å¼•çš„命å空間。"
msgid "Elastic|None. Select projects to index."
-msgstr ""
-
-msgid "Eligible users"
-msgstr ""
+msgstr "無。請é¸æ“‡è¦å»ºç«‹ç´¢å¼•çš„專案。"
msgid "Email"
-msgstr ""
+msgstr "é›»å­éƒµä»¶"
msgid "Email %{number}"
-msgstr ""
+msgstr "é›»å­éƒµä»¶%{number}"
msgid "Email Notification"
-msgstr ""
+msgstr "é›»å­éƒµä»¶é€šçŸ¥"
msgid "Email a new %{name} to this project"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶å‘該專案發é€ä¸€å€‹æ–°çš„ %{name}"
msgid "Email address suffix"
-msgstr ""
+msgstr "é›»å­éƒµä»¶åœ°å€å¾Œç¶´"
msgid "Email address to use for Support Desk"
-msgstr ""
+msgstr "用於技術支æ´çš„é›»å­éƒµä»¶åœ°å€"
msgid "Email could not be sent"
-msgstr ""
+msgstr "無法發é€é›»å­éƒµä»¶"
msgid "Email display name"
-msgstr ""
+msgstr "é›»å­éƒµä»¶é¡¯ç¤ºå稱"
msgid "Email not verified. Please verify your email in Salesforce."
-msgstr ""
+msgstr "é›»å­éƒµä»¶æœªé©—證。請在Salesforce中驗證您的電å­éƒµä»¶ã€‚"
msgid "Email notification for unknown sign-ins"
-msgstr ""
+msgstr "未知登錄的電å­éƒµä»¶é€šçŸ¥"
msgid "Email patch"
-msgstr ""
+msgstr "é›»å­éƒµä»¶è£œä¸"
msgid "Email patches"
-msgstr ""
+msgstr "é›»å­éƒµä»¶è£œä¸"
msgid "Email sent"
-msgstr ""
+msgstr "é›»å­éƒµä»¶å·²å‚³é€"
msgid "Email the pipeline status to a list of recipients."
-msgstr ""
+msgstr "å°‡æµæ°´ç·šç‹€æ…‹é€éŽé›»å­éƒµä»¶ç™¼é€çµ¦æ¸…單上的收件人。"
msgid "Email updates (optional)"
-msgstr ""
+msgstr "發é€é›»å­éƒµä»¶æ›´æ–°ï¼ˆå¯é¸ï¼‰"
msgid "Email:"
-msgstr ""
+msgstr "é›»å­éƒµä»¶ï¼š"
msgid "Email: %{email}"
-msgstr ""
+msgstr "é›»å­éƒµä»¶ï¼š%{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 ""
+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 "您復原的主題ä¸å†å­˜åœ¨ï¼Œå¯èƒ½å·²è¢«åˆªé™¤ã€‚如果您èªç‚ºé€™æ˜¯éŒ¯èª¤çš„,請è¯çµ¡ç³»çµ±ç®¡ç†å“¡ã€‚"
msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
-msgstr ""
+msgstr "我們無法弄清楚電å­éƒµä»¶çš„用途。請é€éŽWEBé é¢å»ºç«‹æ‚¨çš„議題或留言。"
msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
-msgstr ""
+msgstr "我們無法弄清楚電å­éƒµä»¶çš„回覆內容。請é€éŽWEBé é¢å»ºç«‹æ‚¨çš„留言。"
msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
-msgstr ""
+msgstr "我們無法確定使用者å°æ‡‰çš„é›»å­éƒµä»¶ã€‚è«‹é€éŽWEBé é¢å»ºç«‹æ‚¨çš„留言。"
msgid "EmailError|We couldn't find the project. Please check if there's any typo."
-msgstr ""
+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 "é›»å­éƒµä»¶éŒ¯èª¤|我們無法處ç†æ‚¨çš„é›»å­éƒµä»¶ï¼Œå› ç‚ºå®ƒå¤ªå¤§äº†ã€‚請通éŽç¶²é ç•Œé¢å»ºç«‹æ‚¨çš„è­°é¡Œ (issue) 或留言。"
msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "ä¸å…許您執行此æ“作。如果您èªç‚ºé€™æ˜¯éŒ¯èª¤çš„,請è¯çµ¡ç³»çµ±ç®¡ç†å“¡ã€‚"
msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
-msgstr ""
+msgstr "您的帳號已被åœç”¨ã€‚如果您èªç‚ºé€™æ˜¯éŒ¯èª¤çš„,請è¯çµ¡ç³»çµ±ç®¡ç†å“¡ã€‚"
msgid "EmailParticipantsWarning|%{emails} will be notified of your comment."
-msgstr ""
+msgstr "%{emails} 將收到您的留言通知。"
msgid "EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment."
-msgstr ""
+msgstr "%{emails}, %{andMore} 將收到您的留言通知。"
msgid "EmailParticipantsWarning|and %{moreCount} more"
-msgstr ""
+msgstr "é›»å­éƒµä»¶åƒèˆ‡è€…警告|還有 %{moreCount} 個"
msgid "Emails"
msgstr "é›»å­éƒµä»¶"
msgid "Emails sent from Service Desk have this name."
-msgstr ""
+msgstr "從æœå‹™å°ç™¼é€çš„é›»å­éƒµä»¶å…·æœ‰æ­¤å稱。"
msgid "Emails sent to %{email} are also supported."
-msgstr ""
+msgstr "也支æ´ç™¼é€åˆ° %{email} çš„é›»å­éƒµä»¶ã€‚"
msgid "EmailsOnPushService|Disable code diffs"
-msgstr ""
+msgstr "åœç”¨ç¨‹å¼ç¢¼å·®ç•°"
msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
-msgstr ""
+msgstr "ä¸åœ¨é€šçŸ¥ä¸­åŒ…å«å¯èƒ½æ•æ„Ÿçš„程å¼ç¢¼å·®ç•°ã€‚"
msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
-msgstr ""
+msgstr "å°‡æ¯å€‹æŽ¨é€çš„æ交和差異é€éŽé›»å­éƒµä»¶ç™¼é€åˆ°æ”¶ä»¶äººåˆ—表。"
msgid "EmailsOnPushService|Emails on push"
-msgstr ""
+msgstr "推é€æ™‚發é€é›»å­éƒµä»¶"
msgid "EmailsOnPushService|Emails separated by whitespace."
-msgstr ""
+msgstr "EmailsOnPushService|以空格分隔的電å­éƒµä»¶ã€‚"
msgid "EmailsOnPushService|Send from committer"
-msgstr ""
+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 "如果這個網域å稱是 GitLab 域å的一部分(例如%{domains}),則從æ交者電å­éƒµä»¶åœ°å€ç™¼é€é€šçŸ¥ 。"
msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
-msgstr ""
+msgstr "tanuki@example.com gitlab@example.com"
msgid "Embed"
-msgstr ""
+msgstr "嵌入"
msgid "Empty file"
-msgstr ""
+msgstr "空文件"
msgid "Enable"
-msgstr ""
+msgstr "啟用"
msgid "Enable Akismet"
-msgstr ""
+msgstr "啟用 Akismet"
msgid "Enable Amazon EKS integration"
-msgstr ""
+msgstr "啟用 Amazon EKS æ•´åˆ"
msgid "Enable Auto DevOps"
-msgstr ""
+msgstr "啟用 Auto DevOps"
msgid "Enable GitLab Error Tracking"
-msgstr ""
+msgstr "啟用 GitLab 錯誤追踪"
msgid "Enable Gitpod"
-msgstr ""
+msgstr "啟用 Gitpod"
msgid "Enable Gitpod?"
-msgstr ""
+msgstr "è¦å•Ÿç”¨ Gitpod 嗎?"
msgid "Enable Invisible Captcha during sign up"
-msgstr ""
+msgstr "在註冊期間啟用 Invisible Captcha"
msgid "Enable Kroki"
-msgstr ""
+msgstr "啟用 Kroki"
msgid "Enable Mailgun event receiver"
-msgstr ""
+msgstr "啟用 Mailgun 事件接收器"
msgid "Enable PlantUML"
-msgstr ""
+msgstr "啟用PlantUML"
msgid "Enable SSL verification"
-msgstr ""
+msgstr "啟用 SSL 驗證"
msgid "Enable Sentry error tracking"
-msgstr ""
+msgstr "啟用 Sentry 錯誤追蹤"
msgid "Enable Snowplow tracking"
-msgstr ""
+msgstr "啟用 Snowplow 追蹤"
msgid "Enable Spam Check via external API endpoint"
-msgstr ""
+msgstr "通éŽå¤–部 API 端點啟用垃圾郵件檢查"
msgid "Enable What's new: All tiers"
-msgstr ""
+msgstr "啟用新增功能:所有層級"
msgid "Enable What's new: Current tier only"
-msgstr ""
+msgstr "啟用新功能:僅當å‰ç´šåˆ¥"
msgid "Enable access to the performance bar for non-administrators in a given group."
-msgstr ""
+msgstr "å…許該群組中的éžç®¡ç†å“¡è¨ªå•æ€§èƒ½æ¬„。"
msgid "Enable admin mode"
-msgstr ""
+msgstr "啟用管ç†æ¨¡å¼"
msgid "Enable and disable Service Desk. Some additional configuration might be required. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "啟用和ç¦ç”¨æœå‹™å°ã€‚å¯èƒ½éœ€è¦ä¸€äº›é¡å¤–çš„é…置。 %{link_start}瞭解更多%{link_end}。"
msgid "Enable authenticated API request rate limit"
-msgstr ""
+msgstr "啟用已身份驗證的 API 請求速率é™åˆ¶"
msgid "Enable authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "啟用經éŽèº«ä»½é©—證的 Git LFS 請求速率é™åˆ¶"
msgid "Enable authenticated web request rate limit"
-msgstr ""
+msgstr "啟用經éŽèº«ä»½é©—證的 Web 請求速率é™åˆ¶"
msgid "Enable authentication"
-msgstr ""
+msgstr "啟用身份驗證"
msgid "Enable automatic repository housekeeping"
-msgstr ""
+msgstr "啟用自動例行維護版本庫"
msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
-msgstr ""
+msgstr "為建立於早於GitLab 12.7版本的專案啟用容器éŽæœŸå’Œä¿ç•™ç­–略。"
msgid "Enable container expiration caching."
-msgstr ""
+msgstr "啟用容器éŽæœŸç·©å­˜ã€‚"
msgid "Enable email notification"
-msgstr ""
+msgstr "啟用電å­éƒµä»¶é€šçŸ¥"
msgid "Enable error tracking"
-msgstr ""
+msgstr "啟用錯誤跟蹤"
msgid "Enable feature to choose access level"
-msgstr ""
+msgstr "啟用功能以é¸æ“‡å­˜å–級別"
msgid "Enable for this project"
-msgstr ""
+msgstr "在此專案中啟用"
msgid "Enable group runners"
-msgstr ""
+msgstr "啟用群組執行器"
msgid "Enable header and footer in emails"
-msgstr ""
+msgstr "在電å­éƒµä»¶ä¸­å•Ÿç”¨é é¦–å’Œé å°¾"
msgid "Enable health and performance metrics endpoint"
-msgstr ""
+msgstr "啟用é‹è¡Œç‹€æ³å’Œæ€§èƒ½æŒ‡æ¨™ç«¯é»ž"
msgid "Enable in-product marketing emails"
-msgstr ""
+msgstr "接收產å“營銷電å­éƒµä»¶"
msgid "Enable incident management inbound alert limit"
-msgstr ""
+msgstr "啟用事件管ç†è­¦å ±é™åˆ¶"
msgid "Enable integration"
-msgstr ""
+msgstr "啟用整åˆ"
msgid "Enable logs collection"
-msgstr ""
+msgstr "啟用日誌收集"
msgid "Enable maintenance mode"
-msgstr ""
+msgstr "啟用維護模å¼"
msgid "Enable multipart emails"
-msgstr ""
+msgstr "啟用 multipart 郵件"
msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
-msgstr ""
+msgstr "僅å°å¯å®‰å…¨å­˜å„²å®¢æˆ¶ç«¯æ©Ÿå¯†çš„å—信任後端æœå‹™å™¨å°ˆç”¨çš„機密應用程å¼å•Ÿç”¨ã€‚ ä¸è¦ç‚ºåŽŸç”Ÿç§»å‹•ã€å–®é æˆ–其他 JavaScript 應用程å¼å•Ÿç”¨ï¼Œå› ç‚ºå®ƒå€‘無法為客戶端ä¿å¯†ã€‚"
msgid "Enable or disable version check and Service Ping."
-msgstr ""
+msgstr "啟用或ç¦ç”¨ç‰ˆæœ¬æª¢æŸ¥å’ŒService Ping。"
msgid "Enable rate limiting for POST requests to the specified paths"
-msgstr ""
+msgstr "為指定路徑的 POST 請求啟用速率é™åˆ¶"
msgid "Enable reCAPTCHA"
-msgstr ""
+msgstr "啟用 reCAPTCHA"
msgid "Enable reCAPTCHA for login."
-msgstr ""
+msgstr "啟用 reCAPTCHA 進行登入。"
msgid "Enable repository checks"
-msgstr ""
+msgstr "啟用版本庫檢查"
msgid "Enable security training"
-msgstr ""
+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 ""
+msgstr "啟用安全培訓,幫助您的開發者們學習如何修復æ¼æ´žã€‚開發者å¯ä»¥é€šéŽæ‚¨é¸æ“‡çš„培訓供應商,é¸æ“‡èˆ‡æª¢æ¸¬åˆ°çš„æ¼æ´žç›¸é—œçš„安全培訓。"
msgid "Enable shared runners for all projects and subgroups in this group."
-msgstr ""
+msgstr "為該群組中的所有專案和å­ç¾¤çµ„啟用共享執行器。"
msgid "Enable shared runners for this group"
-msgstr ""
+msgstr "為該群組啟用共享執行器"
msgid "Enable shared runners for this project"
-msgstr ""
+msgstr "為此專案啟用共享執行器"
msgid "Enable two-factor authentication"
-msgstr ""
+msgstr "啟用兩步驟驗證"
msgid "Enable unauthenticated API request rate limit"
-msgstr ""
+msgstr "啟用未經身份驗證的 API 請求速率é™åˆ¶"
msgid "Enable unauthenticated web request rate limit"
-msgstr ""
+msgstr "啟用未經身份驗證的 Web 請求速率é™åˆ¶"
msgid "Enable user deactivation emails"
-msgstr ""
+msgstr "啟用使用者åœç”¨é›»å­éƒµä»¶"
msgid "Enable version check"
-msgstr ""
+msgstr "啟用版本檢查"
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}步驟 1%{stepEnd}: 確ä¿æ‚¨å·²è¨­ç½®Kubernetes並為您的%{linkStart}å¢é›†%{linkEnd}æ供了基本域。"
msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
-msgstr ""
+msgstr "%{stepStart}步驟 2%{stepEnd}: 複製以下腳本:"
msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
-msgstr ""
+msgstr "%{stepStart}步驟 3%{stepEnd}: 將其加入到專案的%{linkStart}gitlab-ci.yml%{linkEnd}文件。"
msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
-msgstr ""
+msgstr "%{stepStart}步驟 4(å¯é¸ï¼‰%{stepEnd}。%{linkStart}根據設定說明啟用å¯è¦–化評審%{linkEnd}。"
msgid "EnableReviewApp|Close"
-msgstr ""
+msgstr "關閉"
msgid "EnableReviewApp|Copy snippet text"
-msgstr ""
+msgstr "複製代碼片段"
msgid "Enabled"
-msgstr ""
+msgstr "已啟用"
msgid "Enabled Git access protocols"
-msgstr ""
+msgstr "啟用 Git å­˜å–å”è­°"
msgid "Enabled OAuth authentication sources"
-msgstr ""
-
-msgid "Encountered an error while rendering: %{err}"
-msgstr ""
+msgstr "啟用 OAuth 身份驗證æº"
msgid "End Time"
-msgstr ""
+msgstr "çµæŸæ™‚é–“"
msgid "Ends"
-msgstr ""
+msgstr "çµæŸ"
msgid "Ends at (UTC)"
-msgstr ""
+msgstr "çµæŸæ–¼(UTC)"
msgid "Ends on"
-msgstr ""
+msgstr "çµæŸæ–¼"
msgid "Ends: %{endsAt}"
-msgstr ""
+msgstr "çµæŸæ–¼ï¼š%{endsAt}"
msgid "Enforce two-factor authentication"
-msgstr ""
+msgstr "強制執行雙因å­èªè­‰"
msgid "Enforce two-factor authentication for all user sign-ins."
-msgstr ""
+msgstr "å°æ‰€æœ‰ä½¿ç”¨è€…登入強制執行雙因å­èªè­‰ã€‚"
msgid "Enhance security by storing service account keys in secret managers - learn more about %{docLinkStart}secret management with GitLab%{docLinkEnd}"
-msgstr ""
+msgstr "通éŽå°‡æœå‹™å¸³è™Ÿé‡‘鑰存儲在 secret 管ç†å™¨ä¸­ä¾†å¢žå¼·å®‰å…¨æ€§ - 瞭解更多關於 %{docLinkStart}使用 GitLab%{docLinkEnd} 進行 secret 管ç†çš„訊æ¯"
msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
-msgstr ""
+msgstr "確ä¿å¾žGitLabæœå‹™å™¨åˆ°Prometheusæœå‹™å™¨çš„連接"
msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd} of your CI pipeline to track deployments to your cluster."
-msgstr ""
+msgstr "如需追蹤到å¢é›†çš„部署,請確ä¿æ‚¨çš„%{linkStart}環境包å«æ–¼CIæµæ°´ç·šçš„部署階段%{linkEnd}。"
msgid "Enter %{weights_link_start}weights%{weights_link_end} for storages for new repositories. Configured storages appear below."
-msgstr ""
+msgstr "為新倉庫的儲存輸入 %{weights_link_start}權é‡%{weights_link_end}。é…置的儲存如下所示。"
msgid "Enter 2FA for Admin Mode"
-msgstr ""
+msgstr "輸入管ç†å“¡æ¨¡å¼çš„雙因為驗證碼"
msgid "Enter Admin Mode"
-msgstr ""
+msgstr "進入管ç†å“¡æ¨¡å¼"
msgid "Enter a number"
-msgstr ""
+msgstr "輸入數字"
msgid "Enter an integer number between 0 and 100"
-msgstr ""
+msgstr "輸入介於 0 到 100 之間的整數"
msgid "Enter any color or choose one of the suggested colors below."
-msgstr ""
+msgstr "輸入任何é¡è‰²æˆ–在下方建議的é¡è‰²ä¸­é¸æ“‡ä¸€å€‹ã€‚"
msgid "Enter any color."
-msgstr ""
+msgstr "輸入任何é¡è‰²ã€‚"
msgid "Enter at least three characters to search"
-msgstr ""
+msgstr "請至少輸入三個字元æ‰å¯æœå°‹"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "輸入您的Bitbucket伺æœå™¨URL和個人存å–令牌(權æ–)"
msgid "Enter in your Phabricator Server URL and personal access token below"
-msgstr ""
+msgstr "在下é¢è¼¸å…¥æ‚¨çš„ Phabricator Server URL 和個人存å–令牌(權æ–)"
msgid "Enter license key"
-msgstr ""
+msgstr "請輸入授權金鑰"
msgid "Enter merge request URLs"
-msgstr ""
+msgstr "輸入åˆä½µè«‹æ±‚網å€"
msgid "Enter new AWS Secret Access Key"
-msgstr ""
+msgstr "輸入新的AWS Secret Access金鑰"
msgid "Enter number of issues"
-msgstr ""
+msgstr "請輸入議題(issues)的號碼"
msgid "Enter one or more user ID separated by commas"
-msgstr ""
+msgstr "輸入一個或多個使用者ID,請以逗號隔開"
msgid "Enter the %{name} description"
-msgstr ""
+msgstr "輸入 %{name} æè¿°"
msgid "Enter the %{name} title"
-msgstr ""
+msgstr "輸入 %{name} 標題"
msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
-msgstr ""
+msgstr "在您的移動設備上輸入來自雙因å­æ‡‰ç”¨ç¨‹åºçš„代碼。 如果您丟失了設備,您å¯ä»¥è¼¸å…¥å…¶ä¸­ä¸€å€‹æ¢å¾©ä»£ç¢¼ã€‚"
msgid "Enter the following to confirm:"
-msgstr ""
+msgstr "輸入以下內容進行確èªï¼š"
msgid "Enter the name of your application, and we'll return a unique %{type}."
-msgstr ""
+msgstr "輸入您的應用程å¼çš„å稱,我們將回傳一個唯一的 %{type}。"
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
-msgstr ""
+msgstr "輸入秒數或其他人類å¯è®€çš„輸入,例如\"1 å°æ™‚\"。此逾時優先於為專案所設定的較低逾時。"
msgid "Enter the password for password-protected Elasticsearch servers."
-msgstr ""
+msgstr "輸入å—密碼ä¿è­·çš„ Elasticsearch 伺æœå™¨çš„密碼。"
msgid "Enter the username for password-protected Elasticsearch servers."
-msgstr ""
+msgstr "輸入å—密碼ä¿è­·çš„ Elasticsearch 伺æœå™¨çš„使用者å稱。"
msgid "Enter your Packagist server. Defaults to https://packagist.org."
-msgstr ""
+msgstr "輸入您的 Packagist 伺æœå™¨ã€‚é è¨­ç‚º https://packagist.org。"
msgid "Enter your Packagist token."
-msgstr ""
+msgstr "輸入您的 Packagist 令牌(權æ–)。"
msgid "Enter your Packagist username."
-msgstr ""
+msgstr "輸入您的 Packagist 使用者å稱。"
msgid "Enter your password to approve"
-msgstr ""
+msgstr "輸入核准密碼"
msgid "Enterprise"
-msgstr ""
+msgstr "ä¼æ¥­"
msgid "Environment"
-msgstr ""
+msgstr "環境"
msgid "Environment is required for Stages::MetricEndpointInserter"
-msgstr ""
+msgstr "Stages::MetricEndpointInserter 需è¦ç’°å¢ƒ"
msgid "Environment is required for Stages::VariableEndpointInserter"
-msgstr ""
+msgstr "Stages::VariableEndpointInserter 需è¦ç’°å¢ƒ"
msgid "Environment scope"
-msgstr ""
+msgstr "環境範åœ"
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œç’°å¢ƒè®Šé‡ç”±ç®¡ç†å“¡é…置為 %{link_start}ä¿è­·%{link_end}"
msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default."
-msgstr ""
+msgstr "æ­¤GitLab實例上的環境變é‡è¢«é è¨­é…置為%{link_start}å—ä¿è­·%{link_end}."
msgid "Environment:"
-msgstr ""
+msgstr "環境:"
msgid "EnvironmentDashboard|API"
-msgstr ""
+msgstr "API"
msgid "EnvironmentDashboard|Created through the Deployment API"
-msgstr ""
+msgstr "å·²é€éŽéƒ¨ç½²API建立"
msgid "EnvironmentDashboard|You are looking at the last updated environment"
-msgstr ""
+msgstr "您正在查看最後更新的環境"
msgid "Environments"
-msgstr ""
+msgstr "環境"
msgid "Environments Dashboard"
-msgstr ""
+msgstr "環境儀表æ¿"
msgid "Environments allow you to track deployments of your application. %{linkStart}More information%{linkEnd}."
-msgstr ""
+msgstr "環境å…許您追蹤應用程å¼çš„部署。%{linkStart} 瞭解更多 %{linkEnd}。"
msgid "Environments in %{name}"
-msgstr ""
+msgstr "%{name}中的環境"
msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
-msgstr ""
+msgstr "%{severity} ‧ %{title} %{text}。 %{linkStart}查看詳細訊æ¯%{linkEnd} · %{startedAt} "
msgid "EnvironmentsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "將專案加入到儀表æ¿"
msgid "EnvironmentsDashboard|Add projects"
-msgstr ""
+msgstr "加入專案"
msgid "EnvironmentsDashboard|Environments Dashboard"
-msgstr ""
+msgstr "環境儀表æ¿"
msgid "EnvironmentsDashboard|Job: %{job}"
-msgstr ""
+msgstr "作業:%{job}"
msgid "EnvironmentsDashboard|More actions"
-msgstr ""
+msgstr "更多æ“作"
msgid "EnvironmentsDashboard|Remove"
-msgstr ""
+msgstr "移除"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
-msgstr ""
+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 "此儀表æ¿é¡¯ç¤ºæ¯å€‹å°ˆæ¡ˆçš„ 3 個環境,並éˆæŽ¥åˆ°æ“作儀表æ¿ï¼Œç•¶æ‚¨å¾žä¸€å€‹å„€è¡¨æ¿åŠ å…¥æˆ–移除專案時,GitLab 會從å¦ä¸€å€‹å„€è¡¨æ¿åŠ å…¥æˆ–移除專案。 %{linkStart}更多訊æ¯%{linkEnd}"
msgid "Environments|An error occurred while canceling the auto stop, please try again"
-msgstr ""
+msgstr "å–消自動åœæ­¢æ™‚發生錯誤,請é‡è©¦"
msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
-msgstr ""
+msgstr "刪除環境時發生錯誤。檢查環境是å¦çµ‚止;如果沒有,請終止後é‡è©¦ã€‚"
msgid "Environments|An error occurred while fetching the environments."
-msgstr ""
+msgstr "å–得環境時發生錯誤。"
msgid "Environments|An error occurred while making the request."
-msgstr ""
+msgstr "發é€è«‹æ±‚時發生錯誤。"
msgid "Environments|An error occurred while re-deploying the environment, please try again"
-msgstr ""
+msgstr "é‡æ–°éƒ¨ç½²ç’°å¢ƒæ™‚發生錯誤,請é‡è©¦"
msgid "Environments|An error occurred while rolling back the environment, please try again"
-msgstr ""
+msgstr "還原環境時發生錯誤,請é‡è©¦"
msgid "Environments|An error occurred while stopping the environment, please try again"
-msgstr ""
+msgstr "終止環境時發生錯誤,請ç¨å¾Œé‡è©¦"
msgid "Environments|Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "是å¦ç¢ºå®šçµ‚止當å‰ç’°å¢ƒï¼Ÿ"
msgid "Environments|Auto stop"
-msgstr ""
+msgstr "環境|自動åœæ­¢"
msgid "Environments|Auto stops %{autoStopAt}"
-msgstr ""
+msgstr "環境|自動åœæ­¢ %{autoStopAt}"
msgid "Environments|Commit"
-msgstr ""
+msgstr "æ交"
msgid "Environments|Delete"
-msgstr ""
+msgstr "環境|刪除"
msgid "Environments|Delete '%{environmentName}'?"
-msgstr ""
+msgstr "環境|刪除 「%{environmentName}ã€ï¼Ÿ"
msgid "Environments|Delete environment"
-msgstr ""
+msgstr "環境|刪除環境"
msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
-msgstr ""
+msgstr "刪除'%{environmentName}'的環境無法撤消,您確定è¦åˆªé™¤å®ƒå—Žï¼Ÿ"
msgid "Environments|Deploy to..."
-msgstr ""
+msgstr "部署到..."
msgid "Environments|Deployment"
-msgstr ""
+msgstr "部署"
msgid "Environments|Deployment %{status}"
-msgstr ""
+msgstr "部署%{status}"
msgid "Environments|Enable review app"
-msgstr ""
+msgstr "啟用審核應用"
msgid "Environments|Environment"
-msgstr ""
+msgstr "環境"
msgid "Environments|Environments"
-msgstr ""
+msgstr "環境"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "環境是指部署程å¼ç¢¼çš„ä½ç½®ï¼Œä¾‹å¦‚é ç™¼å¸ƒæˆ–產å“。"
msgid "Environments|How do I create an environment?"
-msgstr ""
+msgstr "如何建立環境?"
msgid "Environments|Job"
-msgstr ""
+msgstr "作業"
msgid "Environments|Learn about environments"
-msgstr ""
+msgstr "了解環境"
msgid "Environments|Learn more about stopping environments"
-msgstr ""
+msgstr "了解更多關於如何終止環境的訊æ¯"
msgid "Environments|New environment"
-msgstr ""
+msgstr "建立環境"
msgid "Environments|No deployed environments"
-msgstr ""
+msgstr "沒有已部署的環境"
msgid "Environments|No deployments yet"
-msgstr ""
+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}影響已經存在的部署。"
@@ -14531,43 +14678,43 @@ msgid "Environments|Open"
msgstr "é–‹å•Ÿ"
msgid "Environments|Open live environment"
-msgstr ""
+msgstr "打開執行中的環境"
msgid "Environments|Re-deploy environment"
-msgstr ""
+msgstr "é‡æ–°éƒ¨ç½²ç’°å¢ƒ"
msgid "Environments|Re-deploy environment %{name}?"
-msgstr ""
+msgstr "é‡æ–°éƒ¨ç½²ç’°å¢ƒ %{name}?"
msgid "Environments|Re-deploy to environment"
-msgstr ""
+msgstr "é‡æ–°éƒ¨ç½²è‡³ç’°å¢ƒ"
msgid "Environments|Rollback environment"
-msgstr ""
+msgstr "還原環境"
msgid "Environments|Rollback environment %{name}?"
-msgstr ""
+msgstr "還原 %{name} 環境?"
msgid "Environments|Show all"
-msgstr ""
+msgstr "顯示全部"
msgid "Environments|Stop"
-msgstr ""
+msgstr "終止"
msgid "Environments|Stop environment"
-msgstr ""
+msgstr "終止環境"
msgid "Environments|Stopping %{environmentName}"
-msgstr ""
+msgstr "環境|正在åœæ­¢ %{environmentName}"
msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
msgstr "尚無此環境的部署。 %{linkStart} 了解更多關於設定部署。%{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 "這動作將在該環境 %{docsStart} é‡è©¦æœ€æ–°éƒ¨ç½² %{docsEnd} çš„ %{commitId} æ交。您確定è¦ç¹¼çºŒå—Žï¼Ÿ"
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 "這動作將 %{docsStart}該環境回退%{docsEnd}到先å‰æˆåŠŸéƒ¨ç½²çš„ %{commitId} æ交。您確定è¦ç¹¼çºŒå—Žï¼Ÿ"
msgid "Environments|Upcoming"
msgstr "å³å°‡åˆ°ä¾†"
@@ -14579,241 +14726,244 @@ msgid "Environments|Updated"
msgstr "已更新"
msgid "Environments|You don't have any environments."
-msgstr ""
+msgstr "您沒有任何環境。"
msgid "Environments|You don't have any stopped environments."
-msgstr ""
+msgstr "您沒有任何已åœæ­¢çš„環境。"
msgid "Environments|by %{avatar}"
-msgstr ""
+msgstr "ç”± %{avatar} æä¾›"
msgid "Environments|protected"
-msgstr ""
+msgstr "å—ä¿è­·çš„"
msgid "Environment|Auto stop %{time}"
-msgstr ""
+msgstr "自動åœæ­¢ %{time}"
msgid "Environment|Deployment tier"
-msgstr ""
+msgstr "部署層級"
msgid "Epic"
-msgstr ""
+msgstr "å²è©©"
msgid "Epic Boards"
-msgstr ""
+msgstr "å²è©©çœ‹æ¿"
msgid "Epic cannot be found."
-msgstr ""
+msgstr "找ä¸åˆ°å²è©©ã€‚"
msgid "Epic details"
-msgstr ""
+msgstr "å²è©©è©³æƒ…"
msgid "Epic events"
-msgstr ""
+msgstr "å²è©©äº‹ä»¶"
msgid "Epic not found for given params"
-msgstr ""
+msgstr "未找到給定åƒæ•¸çš„å²è©©"
msgid "Epics"
-msgstr ""
+msgstr "å²è©©"
msgid "Epics Roadmap"
-msgstr ""
+msgstr "å²è©©è·¯ç·šåœ–"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr ""
+msgstr "有效利用å²è©©ï¼Œæ‚¨çš„產å“線管ç†æœƒè®Šå¾—更輕鬆高效"
msgid "Epics, issues, and merge requests"
-msgstr ""
+msgstr "å²è©©ã€è­°é¡Œå’Œåˆä½µè«‹æ±‚"
msgid "Epics|%{startDate} – %{dueDate}"
-msgstr ""
+msgstr "%{startDate} – %{dueDate}"
msgid "Epics|%{startDate} – No due date"
-msgstr ""
+msgstr "%{startDate} – 無截止日期"
msgid "Epics|Add a new epic"
-msgstr ""
+msgstr "加入一個新的å²è©©ã€‚"
msgid "Epics|Add an existing epic"
-msgstr ""
+msgstr "加入一個ç¾æœ‰çš„å²è©©ã€‚"
msgid "Epics|An error occurred while saving the %{epicDateType} date"
-msgstr ""
+msgstr "ä¿å­˜ %{epicDateType} 日期時發生錯誤"
msgid "Epics|An error occurred while updating labels."
-msgstr ""
+msgstr "更新標記時出錯。"
msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
-msgstr ""
+msgstr "確定è¦å¾ž%{bStart}%{parentEpicTitle}%{bEnd}刪除%{bStart}%{targetIssueTitle}%{bEnd}å—Ž?"
msgid "Epics|Assign Epic"
-msgstr ""
+msgstr "指派å²è©©"
msgid "Epics|Leave empty to inherit from milestone dates"
-msgstr ""
+msgstr "留空以繼承里程碑日期"
msgid "Epics|No start date – %{dueDate}"
-msgstr ""
+msgstr "無開始日期 — %{dueDate}"
msgid "Epics|Remove epic"
-msgstr ""
+msgstr "刪除å²è©©"
msgid "Epics|Remove issue"
-msgstr ""
+msgstr "刪除議題"
msgid "Epics|Search epics"
-msgstr ""
+msgstr "æœå°‹å²è©©"
msgid "Epics|Select epic"
-msgstr ""
+msgstr "é¸æ“‡å²è©©"
msgid "Epics|Show more"
-msgstr ""
+msgstr "顯示更多"
msgid "Epics|Something went wrong while assigning issue to epic."
-msgstr ""
+msgstr "分é…議題到å²è©©æ™‚發生錯誤。"
msgid "Epics|Something went wrong while creating child epics."
-msgstr ""
+msgstr "建立å­å²è©©æ™‚發生錯誤。"
msgid "Epics|Something went wrong while creating issue."
-msgstr ""
+msgstr "建立議題時發生錯誤。"
msgid "Epics|Something went wrong while fetching child epics."
-msgstr ""
+msgstr "å–å¾—å­å²è©©æ™‚發生錯誤。"
msgid "Epics|Something went wrong while fetching epics list."
-msgstr ""
+msgstr "å–å¾—å²è©©åˆ—表時發生錯誤。"
msgid "Epics|Something went wrong while fetching group epics."
-msgstr ""
+msgstr "å–得群組å²è©©æ™‚發生錯誤。"
msgid "Epics|Something went wrong while moving item."
-msgstr ""
+msgstr "移動專案時出了錯。"
msgid "Epics|Something went wrong while ordering item."
-msgstr ""
+msgstr "排åºæ™‚發生錯誤。"
msgid "Epics|Something went wrong while removing issue from epic."
-msgstr ""
+msgstr "從å²è©©ä¸­åˆªé™¤è­°é¡Œæ™‚發生錯誤。"
msgid "Epics|Something went wrong while updating epics."
-msgstr ""
+msgstr "æ›´æ–°å²è©©æ™‚發生錯誤。"
msgid "Epics|The color for the epic when it's visualized, such as on roadmap timeline bars."
-msgstr ""
+msgstr "å²è©©åœ¨å¯è¦–覺化時的é¡è‰²ï¼Œä¾‹å¦‚在路線圖的時間軸線上。"
msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
-msgstr ""
+msgstr "這個å²è©©å’Œä»»ä½•åŒ…å«å­å²è©©çš„訊æ¯å‡ç‚ºç§å¯†ï¼Œåªèƒ½å°æ“有至少報告者訪å•æ¬Šé™çš„團隊æˆå“¡å¯è¦‹ã€‚"
msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
-msgstr ""
+msgstr "該æ“作也會從%{bStart}%{parentEpicTitle}%{bEnd}中移除%{bStart}%{targetEpicTitle}%{bEnd}的所有級別å­å²è©©ã€‚確定繼續嗎?"
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
-msgstr ""
+msgstr "如需根據里程碑來安排å²è©©çš„ %{epicDateType} 日期,請為å²è©©ä¸­çš„任一議題指定帶有 %{epicDateType} 日期的里程碑。"
msgid "Epics|Unable to save epic. Please try again"
-msgstr ""
+msgstr "無法ä¿å­˜å²è©©ã€‚è«‹é‡è©¦"
msgid "Epics|due"
-msgstr ""
+msgstr "到期"
msgid "Epics|start"
-msgstr ""
+msgstr "開始"
msgid "Erased"
-msgstr ""
+msgstr "已刪除"
msgid "Error"
-msgstr ""
+msgstr "錯誤"
msgid "Error Details"
-msgstr ""
+msgstr "錯誤詳情"
msgid "Error Tracking"
-msgstr ""
+msgstr "錯誤跟蹤"
msgid "Error creating epic"
-msgstr ""
+msgstr "建立 å²è©© 時發生錯誤"
msgid "Error creating label."
-msgstr ""
+msgstr "建立標記時發生錯誤。"
msgid "Error creating new directory. Please try again."
-msgstr ""
+msgstr "建立新目錄時發生錯誤。請é‡è©¦ã€‚"
msgid "Error creating new iteration"
-msgstr ""
+msgstr "建立新迭代時發生錯誤"
msgid "Error creating repository for snippet with id %{snippet_id}"
-msgstr ""
+msgstr "以id %{snippet_id} 建立程å¼ç¢¼ç‰‡æ®µåº«æ™‚發生錯誤"
msgid "Error creating the snippet"
-msgstr ""
+msgstr "建立程å¼ç¢¼ç‰‡æ™‚段發生錯誤"
+
+msgid "Error creating vulnerability finding: %{errors}"
+msgstr "建立æ¼æ´žæœå°‹æ™‚發生錯誤:%{errors}"
msgid "Error deleting project. Check logs for error details."
-msgstr ""
+msgstr "刪除專案時發生錯誤。請檢視日誌以å–得錯誤詳細資訊。"
msgid "Error fetching burnup chart data"
-msgstr ""
+msgstr "æå–燃起圖資料時發生錯誤"
msgid "Error fetching diverging counts for branches. Please try again."
-msgstr ""
+msgstr "å–得分支分å‰æ•¸ç›®æ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "Error fetching forked projects. Please try again."
-msgstr ""
+msgstr "讀å–已分å‰(forked)的專案時發生錯誤。請é‡è©¦ã€‚"
msgid "Error fetching labels."
-msgstr ""
+msgstr "å–得標記時發生錯誤。"
msgid "Error fetching network graph."
-msgstr ""
+msgstr "å–得網路圖時發生錯誤。"
msgid "Error fetching payload data."
-msgstr ""
+msgstr "å–得有效資料時發生錯誤。"
msgid "Error fetching refs"
-msgstr ""
+msgstr "å–å¾—refs時發生錯誤。"
msgid "Error fetching the dependency list. Please check your network connection and try again."
-msgstr ""
+msgstr "å–å¾—ä¾è³´åˆ—表時發生錯誤。請檢查您的網路連接,然後é‡è©¦ã€‚"
msgid "Error loading branch data. Please try again."
-msgstr ""
+msgstr "載入分支資料失敗,請é‡è©¦ã€‚"
msgid "Error loading branches."
-msgstr ""
+msgstr "載入分支時發生錯誤。"
msgid "Error loading burndown chart data"
-msgstr ""
+msgstr "載入燃盡圖資料時發生錯誤"
msgid "Error loading countries data."
-msgstr ""
+msgstr "載入國家/地å€è³‡æ–™æ™‚發生錯誤。"
msgid "Error loading file viewer."
-msgstr ""
+msgstr "載入文件查看器時發生錯誤。"
msgid "Error loading issues"
-msgstr ""
+msgstr "載入議題時發生錯誤"
msgid "Error loading iterations"
-msgstr ""
+msgstr "載入迭代時發生錯誤"
msgid "Error loading last commit."
-msgstr ""
+msgstr "載入最後一次æ交失敗。"
msgid "Error loading markdown preview"
-msgstr ""
+msgstr "載入Markdowné è¦½æ™‚發生錯誤"
msgid "Error loading merge requests."
-msgstr ""
+msgstr "載入åˆä½µè«‹æ±‚時發生錯誤。"
msgid "Error loading milestone tab"
-msgstr ""
+msgstr "載入里程碑é¢æ¿æ™‚發生錯誤"
msgid "Error loading project data. Please try again."
-msgstr ""
+msgstr "載入專案資料失敗,請é‡è©¦ã€‚"
msgid "Error loading template types."
msgstr "載入範本類型時發生錯誤。"
@@ -14822,3343 +14972,3352 @@ msgid "Error loading template."
msgstr "載入範本時發生錯誤。"
msgid "Error loading viewer"
-msgstr ""
+msgstr "載入查看器時發生錯誤"
msgid "Error occurred when fetching sidebar data"
-msgstr ""
+msgstr "å–å¾—å´é‚Šæ¬„資料時發生錯誤"
msgid "Error occurred when saving assignees"
-msgstr ""
+msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ™‚出ç¾éŒ¯èª¤ã€‚"
msgid "Error occurred when saving reviewers"
-msgstr ""
+msgstr "ä¿å­˜å¯©æ ¸è€…時發生錯誤"
msgid "Error occurred while updating the %{issuableType} status"
-msgstr ""
+msgstr "更新 %{issuableType} 狀態時發生錯誤"
msgid "Error occurred while updating the issue status"
-msgstr ""
+msgstr "更新議題狀態時發生錯誤"
msgid "Error occurred. A blocked user cannot be deactivated"
-msgstr ""
+msgstr "發生錯誤。無法åœç”¨è¢«å°éŽ–的使用者"
msgid "Error occurred. A blocked user must be unblocked to be activated"
-msgstr ""
+msgstr "發生錯誤。已å°éŽ–的使用者必須解除å°éŽ–後æ‰èƒ½è¢«å•Ÿå‹•"
msgid "Error occurred. User was not banned"
-msgstr ""
+msgstr "發生錯誤,使用者未被ç¦æ­¢"
msgid "Error occurred. User was not blocked"
-msgstr ""
+msgstr "發生了錯誤。使用者未被å°éŽ–"
msgid "Error occurred. User was not confirmed"
-msgstr ""
+msgstr "發生了錯誤。使用者尚未被確èª"
msgid "Error occurred. User was not unbanned"
-msgstr ""
+msgstr "發生錯誤。使用者未被解除ç¦æ­¢"
msgid "Error occurred. User was not unblocked"
-msgstr ""
+msgstr "發生了錯誤。使用者未解除å°éŽ–"
msgid "Error occurred. User was not unlocked"
-msgstr ""
+msgstr "發生了錯誤。使用者未解除鎖定"
msgid "Error parsing CSV file. Please make sure it has"
-msgstr ""
+msgstr "è§£æž CSV 檔案時出錯。請確ä¿å®ƒæœ‰"
msgid "Error rendering Markdown preview"
-msgstr ""
+msgstr "查看 Markdown é è¦½æ™‚生錯誤"
msgid "Error saving label update."
-msgstr ""
+msgstr "儲存標記更新時發生錯誤。"
msgid "Error setting up editor. Please try again."
-msgstr ""
+msgstr "設定編輯器時發生錯誤。請é‡è©¦ã€‚"
msgid "Error tracking"
-msgstr ""
+msgstr "錯誤追蹤"
msgid "Error updating %{issuableType}"
-msgstr ""
+msgstr "更新 %{issuableType} 時發生錯誤"
msgid "Error updating status for all to-do items."
-msgstr ""
+msgstr "更新所有待辦事項狀態時發生錯誤。"
msgid "Error updating status of to-do item."
-msgstr ""
+msgstr "更新待辦事項狀態時發生錯誤。"
msgid "Error updating the snippet"
-msgstr ""
+msgstr "更新片段時出錯"
msgid "Error uploading file"
-msgstr ""
+msgstr "上傳文件時發生錯誤"
msgid "Error uploading file. Please try again."
-msgstr ""
+msgstr "上傳檔案時出錯。請é‡è©¦ã€‚"
msgid "Error uploading file: %{stripped}"
-msgstr ""
+msgstr "上傳文件時發生錯誤: %{stripped}"
msgid "Error while loading the merge request. Please try again."
-msgstr ""
+msgstr "載入åˆä½µè«‹æ±‚時出錯。請é‡è©¦ã€‚"
msgid "Error while migrating %{upload_id}: %{error_message}"
-msgstr ""
+msgstr "é·ç§» %{upload_id} 時發生錯誤 : %{error_message}"
msgid "Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Akismet 錯誤。請檢查日誌以å–得更多訊æ¯ã€‚"
msgid "Error: %{error_message}"
-msgstr ""
+msgstr "錯誤:%{error_message}"
msgid "Error: %{error}"
-msgstr ""
+msgstr "錯誤:%{error}"
msgid "Error: Couldn't load some or all of the changes."
-msgstr ""
+msgstr "錯誤:無法載入部分或全部變更。"
msgid "Error: No AWS credentials were supplied"
-msgstr ""
+msgstr "錯誤:未æä¾› AWS 憑證"
msgid "Error: No AWS provision role found for user"
-msgstr ""
+msgstr "錯誤:未找到使用者的 AWS é ç½®è§’色"
msgid "Error: Unable to create deploy freeze"
-msgstr ""
+msgstr "錯誤:無法建立å‡çµéƒ¨ç½²"
msgid "Error: Unable to delete deploy freeze"
-msgstr ""
+msgstr "錯誤:無法刪除å‡çµéƒ¨ç½²"
msgid "Error: Unable to find AWS role for current user"
-msgstr ""
+msgstr "錯誤:無法找到目å‰ä½¿ç”¨è€…çš„ AWS 角色"
msgid "ErrorTracking|Access token is %{token_in_code_tag}"
-msgstr ""
+msgstr "å­˜å–權æ–為 %{token_in_code_tag}"
msgid "ErrorTracking|Active"
-msgstr ""
+msgstr "啟用"
msgid "ErrorTracking|After adding your Auth Token, select the Connect button to load projects."
-msgstr ""
+msgstr "加入您的身份驗證令牌(Auth Token)後,é¸å–連線(Connect)按鈕以載入專案。"
msgid "ErrorTracking|Auth Token"
-msgstr ""
+msgstr "驗證令牌(權æ–)"
msgid "ErrorTracking|Click Connect to reestablish the connection to Sentry and activate the dropdown."
-msgstr ""
+msgstr "點擊連線以é‡æ–°å»ºç«‹èˆ‡ Sentry 的連線並啟用下拉é¸å–®ã€‚"
msgid "ErrorTracking|Connection failed. Check Auth Token and try again."
-msgstr ""
+msgstr "連線失敗。檢查身份驗證令牌(Auth Token)並é‡è©¦ã€‚"
msgid "ErrorTracking|Enable error tracking"
-msgstr ""
+msgstr "啟用錯誤追蹤"
msgid "ErrorTracking|Error tracking backend"
-msgstr ""
+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 "å¦‚æžœæ‚¨è‡ªç®¡ç† Sentry,請輸入您的 Sentry 實例完整網å€ã€‚如果您使用的是 Sentry 的託管解決方案,請輸入 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 ""
+msgstr "æ•´åˆéŒ¯èª¤è¿½è¹¤ %{epicLinkStart}é è¨­é—œé–‰%{epicLinkEnd}並且ä¸å†å°æ­¤å°ˆæ¡ˆç”Ÿæ•ˆã€‚為了é‡æ–°å•Ÿç”¨ç§æœ‰åŒ–部署實例的錯誤跟蹤,您å¯ä»¥%{flagLinkStart}打開功能標誌%{flagLinkEnd} 用於整åˆéŒ¯èª¤è¿½è¹¤ï¼Œ 或者在您的專案設置é é¢ä¸Šæ供一個 %{settingsLinkStart}Sentry API URL和身份驗證令牌%{settingsLinkEnd} 。然而,錯誤追蹤尚未準備就緒在使用者正å¼ç’°å¢ƒï¼Œç„¡æ³•åœ¨ GitLab.com 上啟用。"
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 ""
+msgstr "æ•´åˆéŒ¯èª¤è¿½è¹¤ %{epicLinkStart}é è¨­é—œé–‰%{epicLinkEnd} 並且ä¸å†å°æ­¤å°ˆæ¡ˆç”Ÿæ•ˆã€‚為了é‡æ–°å•Ÿç”¨ç§æœ‰åŒ–部署實例的錯誤追蹤,您å¯ä»¥%{flagLinkStart}打開功能標誌%{flagLinkEnd} 用於集æˆéŒ¯èª¤è·Ÿè¹¤ï¼Œ 或者在下é¢æ供一個 Sentry API URL和身份驗證令牌 。然而,錯誤跟蹤尚未準備就緒在使用者正å¼ç’°å¢ƒï¼Œç„¡æ³•åœ¨ GitLab.com 上啟用。"
msgid "ErrorTracking|No projects available"
-msgstr ""
+msgstr "ç„¡å¯ç”¨çš„é …ç›®"
msgid "ErrorTracking|Select project"
-msgstr ""
+msgstr "é¸æ“‡é …ç›®"
msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
-msgstr ""
+msgstr "è¦å•Ÿç”¨é¸æ“‡çš„專案,請輸入有效的身份驗證令牌。"
msgid "ErrorTracking|View project settings"
-msgstr ""
+msgstr "查看專案設置"
msgid "Errors"
-msgstr ""
+msgstr "錯誤"
msgid "Errors found on line %{line_number}: %{error_lines}. Please check if these lines have a requirement title."
-msgstr ""
+msgstr "在第%{line_number}行中發ç¾éŒ¯èª¤: %{error_lines}。請檢查這些行是å¦åŒ…å«æ‰€éœ€çš„標題。"
msgid "Escalate this incident"
-msgstr ""
+msgstr "å‡ç´šæ­¤äº‹ä»¶"
msgid "Escalation Policies"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–"
msgid "Escalation policies"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–"
msgid "Escalation policies may not have more than %{rule_count} rules"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–çš„è¦å‰‡ä¸å¾—è¶…éŽ %{rule_count} 個"
msgid "Escalation policies must have at least one rule"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–必須至少有一æ¢è¦å‰‡"
msgid "Escalation policy"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–"
msgid "Escalation policy:"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–:"
msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
-msgstr ""
+msgstr "%{clockIcon}如果警報在%{minutes}分é˜å…§ä¸æ˜¯%{alertStatus}"
msgid "EscalationPolicies|%{notificationIcon} THEN %{doAction} %{forScheduleOrUser}"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–|%{notificationIcon} 然後 %{doAction} %{forScheduleOrUser}"
msgid "EscalationPolicies|+ Add an additional rule"
-msgstr ""
+msgstr "EscalationPolicies|+ 增加附加è¦å‰‡"
msgid "EscalationPolicies|A schedule is required for adding an escalation policy."
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–|增加å‡ç´šæ”¿ç­–需è¦æŽ’程。"
msgid "EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first."
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–|增加å‡ç´šæ”¿ç­–需è¦æŽ’程。請先建立一個待命排程。"
msgid "EscalationPolicies|A user is required for adding an escalation policy."
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–|增加å‡ç´šæ”¿ç­–需有使用者。"
msgid "EscalationPolicies|Add an escalation policy"
-msgstr ""
+msgstr "加入å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Add escalation policy"
-msgstr ""
+msgstr "加入å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Add policy"
-msgstr ""
+msgstr "加入政策"
msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦åˆªé™¤\"%{escalationPolicy}\"å‡ç´šæ”¿ç­–嗎?該動作無法回復。"
msgid "EscalationPolicies|Create an escalation policy in GitLab"
-msgstr ""
+msgstr "在 GitLab 中建立å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Delete escalation policy"
-msgstr ""
+msgstr "刪除å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Edit escalation policy"
-msgstr ""
+msgstr "編輯å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Email on-call user in schedule"
-msgstr ""
+msgstr "æŒ‰è¨ˆåŠƒå‘ on-call 使用者發é€é›»å­éƒµä»¶"
msgid "EscalationPolicies|Email user"
-msgstr ""
+msgstr "é›»å­éƒµä»¶ä½¿ç”¨è€…"
msgid "EscalationPolicies|Escalation policies"
-msgstr ""
+msgstr "å‡ç´šæ”¿ç­–"
msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
-msgstr ""
+msgstr "專案 %{project} çš„å‡ç´šæ”¿ç­– %{obstacle}"
msgid "EscalationPolicies|Escalation rules"
-msgstr ""
+msgstr "å‡ç´šè¦å‰‡"
msgid "EscalationPolicies|Failed to load oncall-schedules"
-msgstr ""
+msgstr "載入 on-call 計劃失敗"
msgid "EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes"
-msgstr ""
+msgstr "如果警報在%{minutes}分é˜å…§ä¸æ˜¯%{alertStatus}"
msgid "EscalationPolicies|Maximum of 10 rules has been reached."
-msgstr ""
+msgstr "å·²é”到最多10æ¢è¦å‰‡ã€‚"
msgid "EscalationPolicies|Minutes must be between 0 and 1440."
-msgstr ""
+msgstr "分é˜æ•¸å¿…須在 0 到 1440 之間。"
msgid "EscalationPolicies|Remove escalation rule"
-msgstr ""
+msgstr "移除å‡ç´šè¦å‰‡"
msgid "EscalationPolicies|Search for user"
-msgstr ""
+msgstr "æœå°‹ä½¿ç”¨è€…"
msgid "EscalationPolicies|Select schedule"
-msgstr ""
+msgstr "é¸æ“‡æŽ’程"
msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
-msgstr ""
+msgstr "設置å‡ç´šæ”¿ç­–以定義在第一個被呼å«çš„使用者ä¸å›žæ‡‰çš„事件中,誰應被呼å«ä»¥åŠä½•æ™‚呼å«ã€‚"
msgid "EscalationPolicies|THEN %{doAction} %{scheduleOrUser}"
-msgstr ""
+msgstr "然後%{doAction}%{scheduleOrUser}"
msgid "EscalationPolicies|The escalation policy could not be deleted. Please try again."
-msgstr ""
+msgstr "無法刪除å‡ç´šæ”¿ç­–,請é‡è©¦ã€‚"
msgid "EscalationPolicies|The escalation policy could not be updated. Please try again"
-msgstr ""
+msgstr "無法更新å‡ç´šæ”¿ç­–,請é‡è©¦ã€‚"
msgid "EscalationPolicies|This policy has no escalation rules."
-msgstr ""
+msgstr "該政策沒有å‡ç´šè¦å‰‡ã€‚"
msgid "EscalationPolicies|mins"
-msgstr ""
+msgstr "最å°å€¼"
msgid "Estimate"
-msgstr ""
+msgstr "é ä¼°"
msgid "Estimated"
-msgstr ""
+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 ""
+msgstr "å³ä½¿æ‚¨é”到了訂閱的席ä½æ•¸é‡ï¼Œæ‚¨ä¹Ÿå¯ä»¥ç¹¼çºŒå¢žåŠ ä½¿ç”¨è€…,GitLab 會與您收å–超é¡è²»ç”¨ã€‚"
msgid "EventFilterBy|Filter by all"
-msgstr ""
+msgstr "全部"
msgid "EventFilterBy|Filter by comments"
-msgstr ""
+msgstr "åªé¡¯ç¤ºç•™è¨€äº‹ä»¶"
msgid "EventFilterBy|Filter by designs"
-msgstr ""
+msgstr "ä¾è¨­è¨ˆç¯©é¸"
msgid "EventFilterBy|Filter by epic events"
-msgstr ""
+msgstr "ä¾å²è©©äº‹ä»¶ç¯©é¸"
msgid "EventFilterBy|Filter by issue events"
-msgstr ""
+msgstr "åªé¡¯ç¤ºè­°é¡Œäº‹ä»¶"
msgid "EventFilterBy|Filter by merge events"
-msgstr ""
+msgstr "åªé¡¯ç¤ºåˆä½µäº‹ä»¶"
msgid "EventFilterBy|Filter by push events"
-msgstr ""
+msgstr "åªé¡¯ç¤ºæŽ¨é€äº‹ä»¶"
msgid "EventFilterBy|Filter by team"
-msgstr ""
+msgstr "åªé¡¯ç¤ºåœ˜éšŠäº‹ä»¶"
msgid "EventFilterBy|Filter by wiki"
-msgstr ""
+msgstr "ä¾Wiki篩é¸"
msgid "Events"
-msgstr ""
+msgstr "事件"
msgid "Events API"
-msgstr ""
+msgstr "事件 API"
msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
-msgstr ""
+msgstr "所有 %{action} 嘗試都已失敗: %{job_error_message}。請é‡è©¦ã€‚"
msgid "Every 3 months"
-msgstr ""
+msgstr "æ¯ 3 個月"
msgid "Every 3 months on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯ä¸‰å€‹æœˆåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every 6 months"
-msgstr ""
+msgstr "æ¯ 6 個月"
msgid "Every 6 months on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯ 6 個月在 %{day} 在 %{time} %{timezone}"
msgid "Every day"
-msgstr ""
+msgstr "æ¯å¤©"
msgid "Every day (at %{time})"
-msgstr ""
+msgstr "æ¯å¤©(%{time})"
msgid "Every day at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯å¤©åœ¨ %{time} %{timezone}"
msgid "Every month"
-msgstr ""
+msgstr "æ¯æœˆ"
msgid "Every month (Day %{day} at %{time})"
-msgstr ""
+msgstr "æ¯æœˆ(%{day}日的%{time})"
msgid "Every month on the %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯æœˆåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every three months"
-msgstr ""
+msgstr "æ¯ä¸‰å€‹æœˆ"
msgid "Every two weeks"
-msgstr ""
+msgstr "æ¯å…©å‘¨"
msgid "Every week"
msgid_plural "Every %d weeks"
-msgstr[0] ""
+msgstr[0] "æ¯%d周"
msgid "Every week (%{weekday} at %{time})"
-msgstr ""
+msgstr "æ¯é€±(%{weekday}çš„%{time})"
msgid "Every week on %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯å€‹æ˜ŸæœŸåœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Every year"
-msgstr ""
+msgstr "æ¯å¹´"
msgid "Every year on %{day} at %{time} %{timezone}"
-msgstr ""
+msgstr "æ¯å¹´åœ¨ %{day} çš„ %{time} %{timezone}"
msgid "Everyone With Access"
-msgstr ""
+msgstr "具有訪å•æ¬Šé™çš„任何人"
msgid "Everyone can access the wiki."
-msgstr ""
+msgstr "æ¯å€‹äººéƒ½å¯ä»¥å­˜å–維基。"
msgid "Everyone can contribute"
-msgstr ""
+msgstr "人人皆å¯è²¢ç»"
msgid "Everything on your to-do list is marked as done."
-msgstr ""
+msgstr "您的待辦事項列表中的所有內容都標記為已完æˆã€‚"
msgid "Everything you need to create a GitLab Pages site using Gatsby"
-msgstr ""
+msgstr "使用Gatsby建立GitLab Pages網站所需的所有訊æ¯"
msgid "Everything you need to create a GitLab Pages site using GitBook"
-msgstr ""
+msgstr "使用GitBook建立GitLab Pages站點所需的所有訊æ¯"
msgid "Everything you need to create a GitLab Pages site using Hexo"
-msgstr ""
+msgstr "使用Hexo建立GitLab Pages站點所需的所有訊æ¯"
msgid "Everything you need to create a GitLab Pages site using Hugo"
-msgstr ""
+msgstr "使用Hugo建立GitLab Pages站點所需的所有訊æ¯"
msgid "Everything you need to create a GitLab Pages site using Jekyll"
-msgstr ""
+msgstr "使用Jekyll建立GitLab Pages站點所需的所有訊æ¯"
msgid "Everything you need to create a GitLab Pages site using Middleman"
-msgstr ""
+msgstr "使用 Middleman 建立 GitLab Pages 站點所需的一切"
msgid "Everything you need to create a GitLab Pages site using Pelican"
-msgstr ""
+msgstr "使用 Pelican 建立 GitLab Pages 站點所需的一切"
msgid "Everything you need to create a GitLab Pages site using plain HTML"
-msgstr ""
+msgstr "使用純HTML建立GitLab Pages網站所需的所有訊æ¯"
msgid "Evidence collection"
-msgstr ""
+msgstr "憑證集"
msgid "Exactly one of %{attributes} is required"
-msgstr ""
+msgstr "其中的一個%{attributes}是必需的"
msgid "Example: @sub\\.company\\.com$"
-msgstr ""
+msgstr "範例: @sub\\.company\\.com$"
msgid "Examples"
-msgstr ""
+msgstr "範例"
msgid "Except policy:"
-msgstr ""
+msgstr "除外政策:"
msgid "Exceptions"
-msgstr ""
+msgstr "例外"
msgid "Excluding merge commits. Limited to %{limit} commits."
-msgstr ""
+msgstr "ä¸åŒ…括åˆä½µæ交。僅é™%{limit}次æ交。"
msgid "Excluding merge commits. Limited to 6,000 commits."
-msgstr ""
+msgstr "ä¸åŒ…括åˆä½µæ交。僅é™6,000次æ交。"
msgid "Execution time"
-msgstr ""
+msgstr "執行時間"
msgid "Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "ç¾æœ‰åˆ†æ”¯å稱ã€æ¨™ç±¤æˆ–æ交 SHA"
msgid "Existing projects may be moved into a group"
-msgstr ""
+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 ""
+msgstr "ç¾æœ‰å°ˆæ¡ˆèƒ½å¤ ä½¿ç”¨éŽæœŸç­–略。如果正在使用外部容器註冊庫(Container Registry),請é¿å…啟用此功能,因為如果一個專案中存在多個映åƒï¼Œå‰‡æœƒæœ‰æ€§èƒ½é¢¨éšªã€‚"
msgid "Existing sign in methods may be removed"
-msgstr ""
+msgstr "ç¾æœ‰çš„登入方法å¯èƒ½æœƒè¢«ç§»é™¤"
msgid "Exit."
-msgstr ""
+msgstr "離開。"
msgid "Expand"
-msgstr ""
+msgstr "展開"
msgid "Expand all"
-msgstr ""
+msgstr "展開全部"
msgid "Expand all files"
-msgstr ""
+msgstr "展開所有檔案"
msgid "Expand all threads"
-msgstr ""
+msgstr "展開所有話題"
msgid "Expand approvers"
-msgstr ""
+msgstr "展開核准者"
msgid "Expand file"
-msgstr ""
+msgstr "展開檔案"
msgid "Expand issues"
-msgstr ""
+msgstr "展開議題"
msgid "Expand jobs"
-msgstr ""
+msgstr "展開作業"
msgid "Expand milestones"
-msgstr ""
+msgstr "展開里程碑"
msgid "Expand panel"
-msgstr ""
+msgstr "展開é¢æ¿"
msgid "Expand settings section"
-msgstr ""
+msgstr "展開設定部份"
msgid "Expand sidebar"
-msgstr ""
+msgstr "展開å´é‚Šæ¬„"
msgid "Expected documents: %{expected_documents}"
-msgstr ""
+msgstr "需è¦çš„文件: %{expected_documents}"
msgid "ExperimentSubject|Must have exactly one of User, Namespace, or Project."
-msgstr ""
+msgstr "必須有一個使用者ã€å‘½å空間或專案。"
msgid "Expiration"
-msgstr ""
+msgstr "到期"
msgid "Expiration date"
-msgstr ""
+msgstr "到期時間"
msgid "Expiration date (optional)"
-msgstr ""
+msgstr "截止日期(å¯é¸ï¼‰"
msgid "Expiration date:"
-msgstr ""
+msgstr "截止日期:"
msgid "Expired"
-msgstr ""
+msgstr "å·²éŽæœŸ"
msgid "Expired %{expiredOn}"
-msgstr ""
+msgstr "已在 %{expiredOn} éŽæœŸ"
msgid "Expired:"
-msgstr ""
+msgstr "å·²éŽæœŸ:"
msgid "Expires"
-msgstr ""
+msgstr "到期"
msgid "Expires %{preposition} %{expires_at}"
-msgstr ""
+msgstr "éŽæœŸ %{preposition} %{expires_at}"
msgid "Expires on"
-msgstr ""
+msgstr "有效期至"
msgid "Expires:"
-msgstr ""
+msgstr "到期:"
msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
-msgstr ""
+msgstr "請解釋此å•é¡Œã€‚如é©ç”¨ï¼Œå¯æ供相關議題或留言的連çµã€‚"
msgid "Explore"
-msgstr ""
+msgstr "探索"
msgid "Explore GitLab"
-msgstr ""
+msgstr "ç€è¦½GitLab"
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 ""
+msgstr "ç€è¦½ç¨‹å¼ç¢¼ç‰‡æ®µ"
msgid "Explore topics"
-msgstr ""
+msgstr "ç€è¦½ä¸»é¡Œ"
msgid "Export"
-msgstr ""
+msgstr "匯出"
msgid "Export %{requirementsCount} requirements?"
-msgstr ""
+msgstr "匯出 %{requirementsCount} 需求?"
msgid "Export as CSV"
-msgstr ""
+msgstr "匯出為 CSV"
msgid "Export commit custody report"
-msgstr ""
+msgstr "匯出æ交監管報告"
msgid "Export group"
-msgstr ""
+msgstr "匯出群組"
msgid "Export issues"
-msgstr ""
+msgstr "匯出議題"
msgid "Export merge requests"
-msgstr ""
+msgstr "匯出åˆä½µè«‹æ±‚"
msgid "Export project"
-msgstr ""
+msgstr "匯出專案"
msgid "Export requirements"
-msgstr ""
+msgstr "匯出需求"
msgid "Export this group with all related data."
-msgstr ""
+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 ""
+msgstr "匯出該專案åŠå…¶æ‰€æœ‰ç›¸é—œè³‡æ–™ï¼Œä»¥ä¾¿å°‡å…¶ç§»å‹•åˆ°æ–°çš„ GitLab 實例。導出的文件準備就緒後,您å¯ä»¥å¾žæ­¤é é¢æˆ–從您將收到的電å­éƒµä»¶é€šçŸ¥ä¸­çš„下載éˆæŽ¥ä¸‹è¼‰å®ƒã€‚然後,您å¯ä»¥åœ¨å»ºç«‹æ–°å°ˆæ¡ˆæ™‚將其導入。 %{link_start}瞭解更多。%{link_end}"
msgid "Export variable to pipelines running on protected branches and tags only."
-msgstr ""
+msgstr "僅匯出變é‡åˆ°å—ä¿è­·åˆ†æ”¯å’Œæ¨™ç±¤ä¸Šé‹è¡Œçš„æµæ°´ç·šã€‚"
msgid "Exported requirements"
-msgstr ""
+msgstr "匯出è¦æ±‚"
msgid "External URL"
-msgstr ""
+msgstr "外部URL"
msgid "External User:"
-msgstr ""
+msgstr "外部使用者:"
msgid "External authorization denied access to this project"
-msgstr ""
+msgstr "外部授權拒絕存å–此專案"
msgid "External storage URL"
-msgstr ""
+msgstr "外部儲存網å€"
msgid "External storage authentication token"
-msgstr ""
+msgstr "外部儲存驗證令牌(權æ–)"
msgid "External storage for repository static objects"
-msgstr ""
+msgstr "版本庫éœæ…‹ç‰©ä»¶çš„外部儲存"
msgid "ExternalAuthorizationService|Classification label"
-msgstr ""
+msgstr "分類標記"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
-msgstr ""
+msgstr "未設定分類標記的時候,將使用é è¨­çš„分類標記`%{default_label}`。"
msgid "ExternalAuthorization|Access to projects is validated on an external service using their classification label."
-msgstr ""
+msgstr "專案的存å–權通éŽå¤–部æœå‹™ä½¿ç”¨å…¶åˆ†é¡žæ¨™è¨˜é€²è¡Œé©—證。"
msgid "ExternalAuthorization|Certificate used to authenticate with the external authorization service. If blank, the server certificate is validated when accessing over HTTPS."
-msgstr ""
+msgstr "用於通éŽå¤–部授權æœå‹™é€²è¡Œèº«ä»½é©—è­‰çš„è­‰æ›¸ã€‚å¦‚æžœç‚ºç©ºï¼Œå‰‡åœ¨é€šéŽ HTTPS å­˜å–時驗證æœå‹™å™¨è­‰æ›¸ã€‚"
msgid "ExternalAuthorization|Classification label to use when requesting authorization if no specific label is defined on the project."
-msgstr ""
+msgstr "如果專案上未定義特定標記,在請求授權時將使用分類標記。"
msgid "ExternalAuthorization|Client authorization certificate"
-msgstr ""
+msgstr "客戶端授權證書"
msgid "ExternalAuthorization|Client authorization key"
-msgstr ""
+msgstr "客戶端授權金鑰"
msgid "ExternalAuthorization|Client authorization key password (optional)"
-msgstr ""
+msgstr "客戶端授權金鑰密碼(é¸é …)"
msgid "ExternalAuthorization|Default classification label"
-msgstr ""
+msgstr "é è¨­åˆ†é¡žæ¨™è¨˜"
msgid "ExternalAuthorization|Enable classification control using an external service"
-msgstr ""
+msgstr "使用外部æœå‹™å•Ÿç”¨åˆ†é¡žæŽ§åˆ¶"
msgid "ExternalAuthorization|External authorization"
-msgstr ""
+msgstr "外部授權"
msgid "ExternalAuthorization|External authorization request timeout (seconds)"
-msgstr ""
+msgstr "外部授權請求逾時(秒)"
msgid "ExternalAuthorization|External classification policy authorization."
-msgstr ""
+msgstr "外部分類政策授權。"
msgid "ExternalAuthorization|Passphrase required to decrypt the private key. Encrypted when stored."
-msgstr ""
+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 ""
+msgstr "GitLab 等待來自外部æœå‹™çš„回應的期間。如果沒有回應,則拒絕存å–。等待時間é è¨­å€¼ï¼š0.5 秒。"
msgid "ExternalAuthorization|Private key of client authentication certificate. Encrypted when stored."
-msgstr ""
+msgstr "客戶端èªè­‰æ†‘證的ç§é‘°ï¼Œå„²å­˜æ™‚加密。"
msgid "ExternalAuthorization|Service URL"
-msgstr ""
+msgstr "æœå‹™ URL"
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。如果 URL 為空,則跨專案功能å¯ç”¨ä¸¦ä¸”ä»å¯ä»¥ç‚ºå°ˆæ¡ˆæŒ‡å®šåˆ†é¡žæ¨™è¨˜ã€‚"
msgid "ExternalIssueIntegration|Another issue tracker is already in use"
-msgstr ""
+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 ""
+msgstr "此處å¯èƒ½ä¸æœƒé¡¯ç¤ºæ‰€æœ‰è³‡æ–™ï¼Œè¦æŸ¥çœ‹æ›´å¤šè©³ç´°è¨Šæ¯æˆ–å°æ­¤è­°é¡Œé€²è¡Œæ›´æ”¹ï¼Œè«‹è½‰åˆ° %{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 "åªèƒ½å­˜åœ¨ä¸€å€‹æœ‰æ•ˆçš„議題追蹤器整åˆã€‚è«‹å…ˆç¦ç”¨ç•¶å‰æœ‰æ•ˆçš„追蹤器,然後é‡è©¦ã€‚"
msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
-msgstr ""
+msgstr "此議題已與 %{trackerName} åŒæ­¥"
msgid "ExternalWikiService|Enter the URL to the external wiki."
-msgstr ""
+msgstr "輸入外部 wiki 的 URL 。"
msgid "ExternalWikiService|External wiki"
-msgstr ""
+msgstr "外部Wiki"
msgid "ExternalWikiService|External wiki URL"
-msgstr ""
+msgstr "外部Wiki URL"
msgid "ExternalWikiService|Link to an external wiki from the sidebar."
-msgstr ""
+msgstr "從å´é‚Šæ¬„éˆæŽ¥åˆ°å¤–部 wiki。"
msgid "ExternalWikiService|https://example.com/xxx/wiki/..."
-msgstr ""
+msgstr "https://example.com/xxx/wiki/..."
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
-msgstr ""
+msgstr "已失敗"
msgid "Failed Jobs"
-msgstr ""
+msgstr "失敗的作業"
msgid "Failed job"
msgid_plural "Failed jobs"
-msgstr[0] ""
+msgstr[0] "失敗的作業"
msgid "Failed on"
-msgstr ""
+msgstr "失敗於"
msgid "Failed to add a Zoom meeting"
-msgstr ""
+msgstr "無法加入Zoom會議"
msgid "Failed to apply commands."
-msgstr ""
+msgstr "應用指令失敗。"
msgid "Failed to archive a design. Please try again."
msgid_plural "Failed to archive designs. Please try again."
-msgstr[0] ""
+msgstr[0] "歸檔設計失敗。請é‡è©¦ã€‚"
msgid "Failed to assign a reviewer because no user was specified."
-msgstr ""
+msgstr "由於沒有指定使用者,無法分é…審核者。"
msgid "Failed to assign a user because no user was found."
-msgstr ""
+msgstr "由於未找到使用者,因此無法指派使用者。"
msgid "Failed to cancel auto stop because failed to update the environment."
-msgstr ""
+msgstr "由於更新環境失敗,å–消自動終止失敗。"
msgid "Failed to cancel auto stop because the environment is not set as auto stop."
-msgstr ""
+msgstr "å–消自動åœæ­¢å¤±æ•—,因為環境沒有設定為自動終止。"
msgid "Failed to cancel auto stop because you do not have permission to update the environment."
-msgstr ""
+msgstr "å–消自動終止失敗,因為您沒有更新環境的權é™ã€‚"
msgid "Failed to change the owner"
-msgstr ""
+msgstr "無法變更所有者"
msgid "Failed to check related branches."
-msgstr ""
+msgstr "無法檢查相關分支。"
msgid "Failed to clone this issue because target project doesn't exist."
-msgstr ""
+msgstr "無法仿製(clone)此議題,因為目標專案ä¸å­˜åœ¨ã€‚"
msgid "Failed to clone this issue: wrong parameters."
-msgstr ""
+msgstr "無法仿製(clone)此議題:åƒæ•¸éŒ¯èª¤ã€‚"
msgid "Failed to create a branch for this issue. Please try again."
-msgstr ""
+msgstr "無法為此å•é¡Œå»ºç«‹åˆ†æ”¯ã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Failed to create a to-do item for the design."
-msgstr ""
+msgstr "無法為該設計建立待辦事項。"
msgid "Failed to create framework"
-msgstr ""
+msgstr "建立框架失敗"
msgid "Failed to create import label for jira import."
-msgstr ""
+msgstr "建立從 jira 匯入的匯入標記失敗。"
msgid "Failed to create new access token: %{token_response_message}"
-msgstr ""
+msgstr "建立新訪å•ä»¤ç‰Œå¤±æ•—:%{token_response_message}"
msgid "Failed to create repository"
-msgstr ""
+msgstr "建立版本庫失敗"
msgid "Failed to create resources"
-msgstr ""
+msgstr "建立資æºå¤±æ•—"
msgid "Failed to create wiki"
-msgstr ""
+msgstr "建立Wiki失敗"
msgid "Failed to deploy to"
-msgstr ""
+msgstr "無法部署到"
msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
-msgstr ""
+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 ""
+msgstr "找ä¸åˆ°ç”¨æ–¼Jira匯入的匯入標記。"
msgid "Failed to find users for %{missing}"
-msgstr ""
+msgstr "找ä¸åˆ°ä½¿ç”¨è€… %{missing}"
msgid "Failed to generate export, please try again later."
-msgstr ""
+msgstr "生æˆåŒ¯å‡ºå¤±æ•—,請ç¨å¾Œå†è©¦ã€‚"
msgid "Failed to generate report, please try again after sometime"
-msgstr ""
+msgstr "生æˆå ±å‘Šå¤±æ•—,請ç¨å¾Œå†è©¦"
msgid "Failed to get ref."
-msgstr ""
+msgstr "å–å¾—ref失敗。"
msgid "Failed to install."
-msgstr ""
+msgstr "安è£å¤±æ•—。"
msgid "Failed to load"
-msgstr ""
+msgstr "載入失敗"
msgid "Failed to load Roadmap"
-msgstr ""
+msgstr "無法載入路線圖"
msgid "Failed to load assignees."
-msgstr ""
+msgstr "載入指派人失敗。"
msgid "Failed to load assignees. Please try again."
-msgstr ""
+msgstr "載入指派人失敗。請é‡è©¦ã€‚"
msgid "Failed to load authors. Please try again."
-msgstr ""
+msgstr "載入作者失敗。請é‡è©¦ã€‚"
msgid "Failed to load branches. Please try again."
-msgstr ""
+msgstr "載入分支失敗。請é‡è©¦ã€‚"
msgid "Failed to load deploy keys."
-msgstr ""
+msgstr "載入部署金鑰失敗。"
msgid "Failed to load emoji list."
-msgstr ""
+msgstr "無法載入表情列表。"
msgid "Failed to load error details from Sentry."
-msgstr ""
+msgstr "無法從Sentry載入錯誤詳細訊æ¯ã€‚"
msgid "Failed to load errors from Sentry."
-msgstr ""
+msgstr "無法從 Sentry 載入錯誤訊æ¯ã€‚"
msgid "Failed to load group activity metrics. Please try again."
-msgstr ""
+msgstr "載入群組活動度é‡æŒ‡æ¨™å¤±æ•—。請é‡è©¦ã€‚"
msgid "Failed to load groups, users and deploy keys."
-msgstr ""
+msgstr "無法載入群組,使用者和部署金鑰。"
msgid "Failed to load groups."
-msgstr ""
+msgstr "載入群組失敗"
msgid "Failed to load iteration cadences."
-msgstr ""
+msgstr "無法終止載入迭代"
msgid "Failed to load iterations."
-msgstr ""
+msgstr "無法載入迭代"
msgid "Failed to load labels. Please try again."
-msgstr ""
+msgstr "載入標記失敗。請é‡è©¦ã€‚"
msgid "Failed to load milestones."
-msgstr ""
+msgstr "載入里程碑失敗。"
msgid "Failed to load milestones. Please try again."
-msgstr ""
+msgstr "載入里程碑失敗。請é‡è©¦ã€‚"
msgid "Failed to load projects"
-msgstr ""
+msgstr "載入專案失敗"
msgid "Failed to load related branches"
-msgstr ""
+msgstr "載入相關分支失敗"
msgid "Failed to load stacktrace."
-msgstr ""
+msgstr "載入堆疊追蹤失敗。"
msgid "Failed to make repository read-only. %{reason}"
-msgstr ""
+msgstr "無法將版本庫設為唯讀。 %{reason}"
msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
-msgstr ""
+msgstr "無法將此議題標記為é‡è¤‡ï¼Œå› ç‚ºæœªæ‰¾åˆ°å¼•ç”¨çš„議題。"
msgid "Failed to move this issue because label was not found."
-msgstr ""
+msgstr "無法移動此議題,因為相關標記ä¸å­˜åœ¨ã€‚"
msgid "Failed to move this issue because only a single label can be provided."
-msgstr ""
+msgstr "無法移動此議題,因為åªèƒ½åªå¯æ供一個標記。"
msgid "Failed to move this issue because target project doesn't exist."
-msgstr ""
+msgstr "無法移動此議題,因為目標專案ä¸å­˜åœ¨ã€‚"
msgid "Failed to promote issue to incident"
-msgstr ""
+msgstr "æå‡è­°é¡Œåˆ°äº‹ä»¶å¤±æ•—"
msgid "Failed to promote label due to internal error. Please contact administrators."
-msgstr ""
+msgstr "由於內部錯誤而無法å‡ç´šæ¨™è¨˜ã€‚è«‹è¯çµ¡ç®¡ç†å“¡ã€‚"
msgid "Failed to protect the branch"
-msgstr ""
+msgstr "ä¿è­·åˆ†æ”¯å¤±æ•—"
msgid "Failed to protect the environment"
-msgstr ""
+msgstr "ä¿è­·ç’°å¢ƒå¤±æ•—"
msgid "Failed to publish issue on status page."
-msgstr ""
+msgstr "在狀態é ä¸Šç™¼å¸ƒè­°é¡Œå¤±æ•—。"
msgid "Failed to remove a Zoom meeting"
-msgstr ""
+msgstr "無法刪除Zoom會議"
msgid "Failed to remove a to-do item for the design."
-msgstr ""
-
-msgid "Failed to remove attention because no user was found."
-msgstr ""
+msgstr "無法移除設計的待辦事項。"
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "移除é¡åƒå¤±æ•—。"
msgid "Failed to remove the pipeline schedule"
-msgstr ""
+msgstr "無法刪除æµæ°´ç·šè¨ˆåŠƒ"
+
+msgid "Failed to remove timelog"
+msgstr "無法移除時間日誌"
msgid "Failed to remove user identity."
-msgstr ""
+msgstr "無法刪除使用者標識。"
msgid "Failed to remove user key."
-msgstr ""
-
-msgid "Failed to request attention because no user was found."
-msgstr ""
+msgstr "無法刪除使用者金鑰。"
msgid "Failed to retrieve page"
-msgstr ""
+msgstr "å–å¾—é é¢å¤±æ•—"
msgid "Failed to save merge conflicts resolutions. Please try again!"
-msgstr ""
+msgstr "儲存åˆä½µè¡çªè§£æ±ºè¾¦æ³•å¤±æ•—。請é‡è©¦ï¼"
msgid "Failed to save new settings"
-msgstr ""
+msgstr "無法儲存新設定"
msgid "Failed to save preferences (%{error_message})."
-msgstr ""
+msgstr "無法儲存å好設定 (%{error_message})。"
msgid "Failed to save preferences."
-msgstr ""
+msgstr "無法儲存å好設定。"
+
+msgid "Failed to save timelog"
+msgstr "無法儲存時間日誌"
msgid "Failed to set due date because the date format is invalid."
-msgstr ""
+msgstr "由於日期格å¼ç„¡æ•ˆï¼Œè¨­å®šåˆ°æœŸæ—¥æœŸå¤±æ•—。"
msgid "Failed to set iteration on this issue. Please try again."
-msgstr ""
+msgstr "無法在此議題上設定迭代。請é‡è©¦ã€‚"
msgid "Failed to signing using smartcard authentication"
-msgstr ""
+msgstr "無法使用智慧å¡èº«ä»½é©—證進行登入"
msgid "Failed to toggle the to-do status for the design."
-msgstr ""
+msgstr "無法切æ›è¨­è¨ˆçš„待辦事項狀態。"
msgid "Failed to update branch!"
-msgstr ""
+msgstr "更新分支失敗ï¼"
msgid "Failed to update environment!"
-msgstr ""
+msgstr "更新環境失敗ï¼"
msgid "Failed to update framework"
-msgstr ""
+msgstr "更新架構失敗"
msgid "Failed to update issue status"
-msgstr ""
+msgstr "無法更新議題狀態"
msgid "Failed to update the Canary Ingress."
-msgstr ""
+msgstr "無法更新 Canary Ingress。"
msgid "Failed to update."
-msgstr ""
+msgstr "更新失敗。"
msgid "Failed to upgrade."
-msgstr ""
+msgstr "å‡ç´šå¤±æ•—。"
msgid "Failed to upload object map file"
-msgstr ""
+msgstr "上傳物件映射文件失敗"
msgid "Failure"
-msgstr ""
+msgstr "失敗"
msgid "False positive"
-msgstr ""
+msgstr "誤報"
msgid "Fast timeout"
-msgstr ""
-
-msgid "Fast-forward merge without a merge commit"
-msgstr ""
+msgstr "快速逾時"
msgid "Faster releases. Better code. Less pain."
-msgstr ""
+msgstr "更快的發布,更好的程å¼ç¢¼ï¼Œæ›´å°‘的痛苦。"
msgid "Favicon"
-msgstr ""
+msgstr "圖標"
msgid "Favicon was successfully removed."
-msgstr ""
+msgstr "網站圖示已被æˆåŠŸåˆªé™¤ã€‚"
msgid "Favicon will be removed. Are you sure?"
-msgstr ""
+msgstr "圖標將被移除。您確定嗎?"
msgid "Feature Flags"
-msgstr ""
+msgstr "功能標誌"
msgid "Feature deprecation"
-msgstr ""
+msgstr "功能æè¿°"
msgid "Feature flag status"
-msgstr ""
+msgstr "功能標誌狀態"
msgid "Feature flag was not removed."
-msgstr ""
+msgstr "功能標誌未被移除。"
msgid "Feature flag was successfully removed."
-msgstr ""
+msgstr "功能標誌已æˆåŠŸç§»é™¤ã€‚"
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
-msgstr[0] ""
+msgstr[0] "%d個使用者"
msgid "FeatureFlags|%{percent} by available ID"
-msgstr ""
+msgstr "ä¾å¯ç”¨ID%{percent}"
msgid "FeatureFlags|%{percent} by session ID"
-msgstr ""
+msgstr "ä¾æœƒè©±ID%{percent}"
msgid "FeatureFlags|%{percent} by user ID"
-msgstr ""
+msgstr "ä¾ä½¿ç”¨è€…ID%{percent}"
msgid "FeatureFlags|%{percent} randomly"
-msgstr ""
+msgstr "隨機%{percent}"
msgid "FeatureFlags|* (All Environments)"
-msgstr ""
+msgstr "*(所有環境)"
msgid "FeatureFlags|API URL"
-msgstr ""
+msgstr "API URL"
msgid "FeatureFlags|Active"
-msgstr ""
+msgstr "已啟用"
msgid "FeatureFlags|Add strategy"
-msgstr ""
+msgstr "加入策略"
msgid "FeatureFlags|All Environments"
-msgstr ""
+msgstr "所有環境"
msgid "FeatureFlags|All Users"
-msgstr ""
+msgstr "所有使用者"
msgid "FeatureFlags|All users"
-msgstr ""
+msgstr "所有使用者"
msgid "FeatureFlags|Configure"
-msgstr ""
+msgstr "é…ç½®"
msgid "FeatureFlags|Configure feature flags"
-msgstr ""
+msgstr "é…置功能標誌"
msgid "FeatureFlags|Consider using the more flexible \"Percent rollout\" strategy instead."
-msgstr ""
+msgstr "請考慮使用更éˆæ´»çš„\"Percent rollout\"策略。"
msgid "FeatureFlags|Create feature flag"
-msgstr ""
+msgstr "建立功能標誌"
msgid "FeatureFlags|Delete %{name}?"
-msgstr ""
+msgstr "刪除 %{name}?"
msgid "FeatureFlags|Delete feature flag"
-msgstr ""
+msgstr "刪除功能標誌"
msgid "FeatureFlags|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "FeatureFlags|Edit Feature Flag"
-msgstr ""
+msgstr "編輯功能標誌"
msgid "FeatureFlags|Edit User List"
-msgstr ""
+msgstr "編輯使用者列表"
msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
-msgstr ""
+msgstr "通éŽè¨­ç½®åŠŸèƒ½æ¨™èªŒç­–略,為特定使用者和環境啟用功能。"
msgid "FeatureFlags|Environment Specs"
-msgstr ""
+msgstr "環境è¦æ ¼"
msgid "FeatureFlags|Feature Flag"
-msgstr ""
+msgstr "功能標誌"
msgid "FeatureFlags|Feature Flag User List Details"
-msgstr ""
+msgstr "功能標誌使用者列表詳細訊æ¯"
msgid "FeatureFlags|Feature Flag User Lists"
-msgstr ""
+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 ""
+msgstr "功能標誌是é€éŽå»ºç«‹ä¸€çµ„è¦å‰‡ä¾†å®šç¾©ç›®æ¨™ç’°å¢ƒç‹€æ…‹çš„構建行為。é è¨­çš„è¦å‰‡%{codeStart} *%{codeEnd}用於%{boldStart}所有環境%{boldEnd},您å¯ä»¥é€éŽä¸‹é¢çš„環境è¦ç¯„加入任æ„數é‡çš„è¦å‰‡ã€‚您å¯ä»¥åˆ‡æ›æ¯å€‹è¦å‰‡çš„行為以設定它們%{boldStart}啟用%{boldEnd}或%{boldStart}åœç”¨%{boldEnd}。"
msgid "FeatureFlags|Feature Flag has no strategies"
-msgstr ""
+msgstr "功能標誌無策略"
msgid "FeatureFlags|Feature Flags"
-msgstr ""
+msgstr "功能標誌"
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
-msgstr ""
+msgstr "功能標誌 %{name} 將被刪除。您確定嗎?"
msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
-msgstr ""
+msgstr "功能標誌å…許é€éŽå‹•æ…‹åˆ‡æ›æŸäº›åŠŸèƒ½ä½¿æ‡‰ç”¨å‘ˆç¾ä¸åŒç‰¹æ€§ã€‚"
msgid "FeatureFlags|Feature flags limit reached (%{featureFlagsLimit}). Delete one or more feature flags before adding new ones."
-msgstr ""
+msgstr "功能標誌已é”到上é™(%{featureFlagsLimit})。在加入新功能標誌之å‰åˆªé™¤ä¸€å€‹æˆ–多個ç¾æœ‰çš„功能標誌。"
msgid "FeatureFlags|Get started with feature flags"
-msgstr ""
+msgstr "功能標誌入門"
msgid "FeatureFlags|ID"
-msgstr ""
+msgstr "ID"
msgid "FeatureFlags|Inactive"
-msgstr ""
+msgstr "未啟用"
msgid "FeatureFlags|Inactive flag for %{scope}"
-msgstr ""
+msgstr "%{scope} çš„éžæ´»å‹•æ¨™èªŒ"
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 "安è£%{docsLinkAnchoredStart}兼容的客戶端文庫%{docsLinkAnchoredEnd} ,並在設定中指定API URLã€æ‡‰ç”¨ç¨‹å¼å稱和實例ID。%{docsLinkStart}更多訊æ¯%{docsLinkEnd}"
msgid "FeatureFlags|Instance ID"
-msgstr ""
+msgstr "實體ID"
msgid "FeatureFlags|List details"
-msgstr ""
+msgstr "列表詳細訊æ¯"
msgid "FeatureFlags|Loading feature flags"
-msgstr ""
+msgstr "載入功能標誌"
msgid "FeatureFlags|More information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "FeatureFlags|Name"
-msgstr ""
+msgstr "å稱"
msgid "FeatureFlags|New"
-msgstr ""
+msgstr "新建"
msgid "FeatureFlags|New Feature Flag"
-msgstr ""
+msgstr "新建功能標誌"
msgid "FeatureFlags|New User List"
-msgstr ""
+msgstr "新建使用者列表"
msgid "FeatureFlags|New feature flag"
-msgstr ""
+msgstr "新建功能標誌"
msgid "FeatureFlags|No user list selected"
-msgstr ""
+msgstr "未é¸æ“‡ä½¿ç”¨è€…列表"
msgid "FeatureFlags|Percent of users"
-msgstr ""
+msgstr "使用者百分比"
msgid "FeatureFlags|Percent rollout"
-msgstr ""
+msgstr "Percent rollout"
msgid "FeatureFlags|Percent rollout must be an integer number between 0 and 100"
-msgstr ""
+msgstr "Percent rollout必須是0-100之間的整數"
msgid "FeatureFlags|Remove"
-msgstr ""
+msgstr "移除"
msgid "FeatureFlags|Search code references"
-msgstr ""
+msgstr "æœå°‹ä»£ç¢¼å¼•ç”¨"
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
-msgstr ""
+msgstr "設置Unleash客戶端應用å稱為應用程å¼é‹è¡Œçš„環境å稱。 此值將用於匹é…環境範åœã€‚查看 %{linkStart}客戶端é…置示例%{linkEnd}。"
msgid "FeatureFlags|Status"
-msgstr ""
+msgstr "狀態"
msgid "FeatureFlags|Strategies"
-msgstr ""
+msgstr "ç­–ç•¥"
msgid "FeatureFlags|There was an error fetching the feature flags."
-msgstr ""
+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 "為了防止誤æ“作,我們需è¦æ‚¨å†æ¬¡ç¢ºèªã€‚請輸入%{projectName}繼續或關閉此å°è©±æ¡†ä»¥å–消。"
msgid "FeatureFlags|Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "è«‹ç¨å¾Œé‡è©¦æˆ–è¯ç¹«æ”¯æ´åœ˜éšŠã€‚"
msgid "FeatureFlags|User IDs"
-msgstr ""
+msgstr "使用者ID"
msgid "FeatureFlags|User List"
-msgstr ""
+msgstr "使用者列表"
msgid "FeatureFlags|User Lists"
-msgstr ""
+msgstr "使用者列表"
msgid "FeatureFlags|View user lists"
-msgstr ""
+msgstr "查看使用者列表"
msgid "FeatureFlag|Percentage"
-msgstr ""
+msgstr "功能標籤|百分比"
msgid "FeatureFlag|Select a user list"
-msgstr ""
+msgstr "功能標籤|é¸æ“‡ä¸€å€‹ä½¿ç”¨è€…清單"
msgid "FeatureFlag|Select the environment scope for this feature flag"
-msgstr ""
+msgstr "功能標籤|é¸æ“‡æ­¤åŠŸèƒ½æ¨™ç±¤çš„環境範åœ"
msgid "FeatureFlag|There are no configured user lists"
-msgstr ""
+msgstr "功能標籤|沒有é…置的使用者清單"
msgid "FeatureFlag|Type"
-msgstr ""
+msgstr "功能標籤|類型"
msgid "FeatureFlag|User IDs"
-msgstr ""
+msgstr "功能標籤|使用者 ID"
msgid "FeatureFlag|User List"
-msgstr ""
+msgstr "功能標籤|使用者清單"
msgid "Feb"
msgstr "2月"
msgid "February"
-msgstr ""
+msgstr "2月"
+
+msgid "Feedback issue"
+msgstr "å•é¡Œå›žé¥‹"
msgid "Fetch and check out this merge request's feature branch:"
-msgstr ""
+msgstr "å–得並簽出此åˆä½µè«‹æ±‚的功能分支:"
msgid "Fetching incoming email"
-msgstr ""
+msgstr "å–得接收郵件地å€"
msgid "File"
-msgstr ""
+msgstr "文件"
msgid "File %{current} of %{total}"
-msgstr ""
+msgstr "文件%{current},總計%{total}"
msgid "File Hooks"
-msgstr ""
+msgstr "文件掛鉤"
msgid "File Hooks (%{count})"
-msgstr ""
+msgstr "文件掛鉤 (%{count})"
msgid "File Tree"
-msgstr ""
+msgstr "文件樹"
msgid "File added"
-msgstr ""
+msgstr "文件已加入"
msgid "File browser"
-msgstr ""
+msgstr "文件ç€è¦½"
msgid "File deleted"
-msgstr ""
+msgstr "文件已刪除"
msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
-msgstr ""
+msgstr "文件掛鉤類似系統掛鉤,但會以檔案執行,而éžå‚³é€è³‡æ–™åˆ°ç¶²å€ã€‚"
msgid "File mode changed from %{a_mode} to %{b_mode}"
-msgstr ""
+msgstr "文件模å¼å¾ž %{a_mode} 變更為 %{b_mode}"
msgid "File moved"
-msgstr ""
+msgstr "文件已移動"
msgid "File name"
-msgstr ""
+msgstr "文件å稱"
msgid "File renamed with no changes."
-msgstr ""
+msgstr "文件已é‡å‘½å,但無更改。"
msgid "File suppressed by a .gitattributes entry or the file's encoding is unsupported."
-msgstr ""
+msgstr "文件被 .gitattributes æ¢ç›®ä»°åˆ¶æˆ–文件的編碼ä¸å—支æŒã€‚"
msgid "File templates"
msgstr "檔案範本"
msgid "File too large. Secure Files must be less than %{limit} MB."
-msgstr ""
+msgstr "檔案éŽå¤§ã€‚安全檔案必須å°æ–¼ %{limit} MB"
msgid "File upload error."
-msgstr ""
+msgstr "文件上傳錯誤。"
msgid "Filename"
-msgstr ""
+msgstr "檔å"
msgid "Files"
-msgstr ""
+msgstr "文件"
msgid "Files API Rate Limits"
-msgstr ""
+msgstr "文件 API 速率é™åˆ¶"
msgid "Files breadcrumb"
-msgstr ""
+msgstr "文件導航"
msgid "Files with large changes are collapsed by default."
-msgstr ""
+msgstr "具有較大更改的文件é è¨­æƒ…æ³ä¸‹æ˜¯æŠ˜ç–Šçš„。"
msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
-msgstr ""
+msgstr "æ交引用%{ref}路徑%{path}中的文件,目錄和å­æ¨¡çµ„"
msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
-msgstr ""
+msgstr "填寫以下字段,開啟%{strong_open}å°æ­¤ç¾¤çµ„啟用SAML身份驗證%{strong_close},然後點擊%{strong_open}ä¿å­˜æ›´æ”¹%{strong_close}"
msgid "Filter"
-msgstr ""
+msgstr "éŽæ¿¾å™¨"
msgid "Filter by"
-msgstr ""
+msgstr "éŽæ¿¾æ¢ä»¶ï¼š"
msgid "Filter by %{page_context_word} that are currently open."
-msgstr ""
+msgstr "éŽæ¿¾ç•¶å‰é–‹æ”¾çš„ %{page_context_word}"
msgid "Filter by Git revision"
-msgstr ""
+msgstr "ä¾Git版本éŽæ¿¾"
msgid "Filter by issues that are currently closed."
-msgstr ""
+msgstr "ä¾ç•¶å‰é—œé–‰çš„è­°é¡ŒéŽæ¿¾ã€‚"
msgid "Filter by issues that are currently opened."
-msgstr ""
+msgstr "ä¾ç•¶å‰é–‹å•Ÿçš„è­°é¡ŒéŽæ¿¾ã€‚"
msgid "Filter by label"
-msgstr ""
+msgstr "ä¾æ¨™è¨˜éŽæ¿¾"
msgid "Filter by merge requests that are currently closed and unmerged."
-msgstr ""
+msgstr "ä¾ç•¶å‰å·²é—œé–‰å’Œæœªåˆä½µçš„åˆä½µè«‹æ±‚éŽæ¿¾ã€‚"
msgid "Filter by merge requests that are currently merged."
-msgstr ""
+msgstr "ä¾ç•¶å‰å·²åˆä½µçš„åˆä½µè«‹æ±‚éŽæ¿¾ã€‚"
msgid "Filter by milestone"
-msgstr ""
+msgstr "ä¾é‡Œç¨‹ç¢‘éŽæ¿¾"
msgid "Filter by milestone name"
-msgstr ""
+msgstr "ä¾é‡Œç¨‹ç¢‘å稱éŽæ¿¾"
msgid "Filter by name"
-msgstr ""
+msgstr "ä¾å稱éŽæ¿¾"
msgid "Filter by test cases that are currently archived."
-msgstr ""
+msgstr "ä¾ç•¶å‰å·²æ­¸æª”的測試用例éŽæ¿¾ã€‚"
msgid "Filter by test cases that are currently open."
-msgstr ""
+msgstr "ä¾ç•¶å‰é–‹æ”¾çš„測試用例進行éŽæ¿¾ã€‚"
msgid "Filter by user"
-msgstr ""
+msgstr "ä¾ä½¿ç”¨è€…éŽæ¿¾"
msgid "Filter parameters are not valid. Make sure that the end date is after the start date."
-msgstr ""
+msgstr "éŽæ¿¾åƒæ•¸ç„¡æ•ˆã€‚確ä¿çµæŸæ—¥æœŸæ™šæ–¼é–‹å§‹æ—¥æœŸã€‚"
msgid "Filter pipelines"
-msgstr ""
+msgstr "éŽæ¿¾æµæ°´ç·š"
msgid "Filter results"
-msgstr ""
+msgstr "éŽæ¿¾çµæžœ"
msgid "Filter results by group"
-msgstr ""
+msgstr "ä¾ç¾¤çµ„éŽæ¿¾çµæžœ"
msgid "Filter results by project"
-msgstr ""
+msgstr "ä¾å°ˆæ¡ˆéŽæ¿¾çµæžœ"
msgid "Filter results..."
-msgstr ""
+msgstr "éŽæ¿¾çµæžœ..."
msgid "Filter users"
-msgstr ""
+msgstr "éŽæ¿¾ä½¿ç”¨è€…"
msgid "Filter..."
-msgstr ""
+msgstr "éŽæ¿¾..."
msgid "Find File"
-msgstr ""
+msgstr "尋找檔案"
msgid "Find bugs in your code with API fuzzing."
-msgstr ""
+msgstr "使用 API fuzzing 找到您程å¼ç¢¼ä¸­çš„錯誤。"
msgid "Find bugs in your code with coverage-guided fuzzing."
-msgstr ""
+msgstr "使用覆蓋率引導的模糊測試查找程å¼ç¢¼ä¸­çš„錯誤。"
msgid "Find by path"
-msgstr ""
+msgstr "ä¾è·¯å¾‘尋找"
msgid "Find file"
-msgstr ""
+msgstr "尋找文件"
msgid "Fingerprint (MD5)"
-msgstr ""
+msgstr "數ä½æŒ‡ç´‹ (MD5)"
msgid "Fingerprint (SHA256)"
-msgstr ""
+msgstr "數ä½æŒ‡ç´‹ (SHA256)"
msgid "Fingerprints"
-msgstr ""
+msgstr "指紋"
msgid "Finish editing this message first!"
-msgstr ""
+msgstr "先完æˆæ­¤æ¶ˆæ¯çš„編輯ï¼"
msgid "Finish review"
-msgstr ""
+msgstr "完æˆå¯©é–±"
msgid "Finish setting up your dedicated account for %{group_name}."
-msgstr ""
+msgstr "完æˆæ‚¨çš„%{group_name}專用帳號設置。"
msgid "Finished"
-msgstr ""
+msgstr "已完æˆ"
msgid "First Name"
-msgstr ""
+msgstr "åå­—"
msgid "First Seen"
-msgstr ""
+msgstr "首次出ç¾"
msgid "First day of the week"
-msgstr ""
+msgstr "æ¯é€±çš„起始日"
msgid "First name"
-msgstr ""
+msgstr "åå­—"
msgid "First seen"
-msgstr ""
+msgstr "首次出ç¾"
msgid "Fixed"
-msgstr ""
+msgstr "固定"
msgid "Fixed burndown chart"
-msgstr ""
+msgstr "固定燃盡圖"
msgid "Fixed:"
-msgstr ""
+msgstr "固定:"
msgid "Flags"
-msgstr ""
+msgstr "旗幟"
msgid "FloC|Configure whether you want to participate in FloC."
-msgstr ""
+msgstr "FloC|設定您是å¦æƒ³åƒèˆ‡ FloC。"
msgid "FloC|Enable FloC (Federated Learning of Cohorts)"
-msgstr ""
+msgstr "啟用 FloC(Federated Learning of Cohorts)"
msgid "FloC|Federated Learning of Cohorts"
-msgstr ""
+msgstr "FloC(Federated Learning of Cohorts)"
msgid "FlowdockService|Enter your Flowdock token."
-msgstr ""
+msgstr "輸入您的 Flowdock 令牌(權æ–)"
msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows."
-msgstr ""
+msgstr "從 GitLab 發é€äº‹ä»¶é€šçŸ¥åˆ° Flowdock æµã€‚"
msgid "FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}"
-msgstr ""
+msgstr "從 GitLab å‘ Flowdock æµç™¼é€äº‹ä»¶é€šçŸ¥ã€‚ %{docs_link}"
msgid "Focus filter bar"
-msgstr ""
+msgstr "èšç„¦éŽæ¿¾åˆ—"
msgid "FogBugz Email"
-msgstr ""
+msgstr "FogBugzé›»å­éƒµä»¶"
msgid "FogBugz Import"
-msgstr ""
+msgstr "FogBugz匯入"
msgid "FogBugz Password"
-msgstr ""
+msgstr "FogBugz密碼"
msgid "FogBugz URL"
-msgstr ""
+msgstr "FogBugz網å€"
msgid "FogBugz import"
-msgstr ""
+msgstr "FogBugz匯入"
msgid "Fogbugz|Fogbugz import failed due to an error: %{error}"
-msgstr ""
+msgstr "Fogbugz 因錯誤而導入失敗:%{error}"
msgid "Fogbugz|Project %{repo} could not be found"
-msgstr ""
+msgstr "找ä¸åˆ° %{repo} 專案"
msgid "Folder/%{name}"
-msgstr ""
+msgstr "資料夾/%{name}"
msgid "Follow"
-msgstr ""
+msgstr "關注"
msgid "Followed Users' Activity"
-msgstr ""
+msgstr "關注使用者的動態"
msgid "Followed users"
-msgstr ""
+msgstr "關注的使用者"
msgid "Font Color"
-msgstr ""
+msgstr "å­—é«”é¡è‰²"
msgid "Footer message"
-msgstr ""
+msgstr "é å°¾æ¶ˆæ¯"
msgid "For a faster browsing experience, some files are collapsed by default."
-msgstr ""
+msgstr "為了ç²å¾—æ›´å¿«çš„ç€è¦½é«”驗,é è¨­æœƒæŠ˜ç–ŠæŸäº›æª”案。"
msgid "For additional information, review your %{link_to} or contact your group owner."
-msgstr ""
+msgstr "有關其他訊æ¯ï¼Œè«‹æŸ¥çœ‹æ‚¨çš„ %{link_to} 或è¯ç¹«æ‚¨çš„群組所有者。"
msgid "For additional information, review your group membership: %{link_to} or contact your group owner."
-msgstr ""
+msgstr "有關其他訊æ¯ï¼Œè«‹æŸ¥çœ‹æ‚¨çš„群組æˆå“¡èº«ä»½ï¼š %{link_to} 或è¯ç¹«æ‚¨çš„群組所有者。"
msgid "For each job, clone the repository."
-msgstr ""
+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 ""
+msgstr "é‡å°æ¯å€‹ä½œæ¥­ï¼Œé‡è¤‡ä½¿ç”¨å°ˆæ¡ˆå·¥ä½œç©ºé–“。如果工作空間ä¸å­˜åœ¨ï¼Œè«‹ä½¿ç”¨ %{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 "例如,使用令牌的應用程å¼æˆ–令牌的用途。ä¸è¦æ供令牌å稱的æ•æ„Ÿè¨Šæ¯ï¼Œå› ç‚ºå®ƒå°‡å°æ‰€æœ‰ %{resource_type} æˆå“¡å¯è¦‹ã€‚"
msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
+msgstr "å°æ–¼å¤§æ–¼æ­¤é™åˆ¶çš„檔案,僅索引檔案å稱。檔案內容沒有索引也ä¸å¯æœå°‹ã€‚"
msgid "For general work"
-msgstr ""
+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 "è‹¥è¦å€‹äººä½¿ç”¨ï¼Œè«‹åœ¨æ‚¨çš„個人電å­éƒµä»¶åœ°å€ä¸‹å»ºç«‹ä¸€å€‹å–®ç¨çš„帳號,ä¸è¦ç¶å®šåˆ°ä¼æ¥­é›»å­éƒµä»¶åŸŸæˆ–群組。"
msgid "For investigating IT service disruptions or outages"
-msgstr ""
+msgstr "用於調查 IT æœå‹™ä¸­æ–·æˆ–åœæ©Ÿ"
msgid "For more info, read the documentation."
-msgstr ""
+msgstr "有關詳細訊æ¯ï¼Œè«‹é–±è®€æ–‡ä»¶ã€‚"
msgid "For more information on how the number of active users is calculated, see the %{self_managed_subscriptions_doc_link} documentation."
-msgstr ""
+msgstr "有關如何計算活èºä½¿ç”¨è€…數的更多訊æ¯ï¼Œè«‹åƒè¦‹æ–‡ä»¶ %{self_managed_subscriptions_doc_link}。"
msgid "For more information, go to the "
-msgstr ""
+msgstr "如需了解詳細訊æ¯ï¼Œè«‹åƒé–±"
msgid "For more information, see the File Hooks documentation."
-msgstr ""
+msgstr "欲知更多資訊,請檢視檔案掛鉤文件。"
msgid "Forgot your password?"
-msgstr ""
+msgstr "忘記密碼?"
msgid "Fork"
-msgstr ""
+msgstr "分å‰"
msgid "Fork Error!"
-msgstr ""
+msgstr "分å‰éŒ¯èª¤ï¼"
msgid "Fork project"
-msgstr ""
+msgstr "分å‰å°ˆæ¡ˆ"
msgid "Fork project?"
-msgstr ""
+msgstr "分å‰å°ˆæ¡ˆ?"
msgid "ForkProject|A fork is a copy of a project."
-msgstr ""
+msgstr "åˆ†å‰ (fork) 是複製專案。"
msgid "ForkProject|An error occurred while forking the project. Please try again."
-msgstr ""
+msgstr "åˆ†å‰ (fork) 專案時發生錯誤。請é‡è©¦ã€‚"
msgid "ForkProject|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "ForkProject|Create a group"
-msgstr ""
+msgstr "建立群組"
msgid "ForkProject|Fork project"
-msgstr ""
+msgstr "åˆ†å‰ (fork) 專案"
msgid "ForkProject|Forking a repository allows you to make changes without affecting the original project."
-msgstr ""
+msgstr "åˆ†å‰ (fork) 版本庫å…許您在ä¸å½±éŸ¿åŽŸå§‹å°ˆæ¡ˆçš„情æ³ä¸‹é€²è¡Œè®Šæ›´ã€‚"
msgid "ForkProject|Internal"
-msgstr ""
+msgstr "內部"
msgid "ForkProject|Please select a namespace"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹å‘½å空間"
msgid "ForkProject|Please select a visibility level"
-msgstr ""
+msgstr "è«‹é¸æ“‡å¯è¦‹æ€§ç­‰ç´š"
msgid "ForkProject|Private"
-msgstr ""
+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 ""
+msgstr "專案訪å•æ¬Šé™å¿…須明確授予æ¯å€‹ä½¿ç”¨è€…,如果此專案屬於æŸå€‹ç¾¤çµ„,則將授予該群組æˆå“¡è¨ªå•æ¬Šé™ã€‚"
msgid "ForkProject|Public"
-msgstr ""
+msgstr "公開"
msgid "ForkProject|Select a namespace"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å‘½å空間"
msgid "ForkProject|The project can be accessed by any logged in user."
-msgstr ""
+msgstr "任何登入的使用者都å¯ä»¥å­˜å–該專案。"
msgid "ForkProject|The project can be accessed without any authentication."
-msgstr ""
+msgstr "該專案無需任何驗證å³å¯å­˜å–。"
msgid "ForkProject|Visibility level"
-msgstr ""
+msgstr "å¯è¦‹æ€§ç­‰ç´š"
msgid "ForkProject|Want to organize several dependent projects under the same namespace?"
-msgstr ""
+msgstr "想在åŒä¸€å€‹å‘½å空間下組織多個ä¾è³´å°ˆæ¡ˆï¼Ÿ"
msgid "ForkSuggestion|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "ForkSuggestion|Fork"
-msgstr ""
+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 ""
+msgstr "您ä¸èƒ½åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç›´æŽ¥ %{edit_start}編輯%{edit_end} 文件,請分å‰å‡ºï¼ˆFork)這個專案並æ交åˆä½µè«‹æ±‚。"
msgid "ForkedFromProjectPath|Forked from"
-msgstr ""
+msgstr "分å‰è‡ª"
msgid "ForkedFromProjectPath|Forked from an inaccessible project"
-msgstr ""
+msgstr "從無法存å–的專案分å‰"
msgid "Forking in progress"
-msgstr ""
+msgstr "分å‰è™•ç†ä¸­"
msgid "Forks"
-msgstr ""
+msgstr "分å‰"
msgid "Format: %{dateFormat}"
-msgstr ""
+msgstr "æ ¼å¼ï¼š%{dateFormat}"
msgid "Forward %{package_type} package requests to the %{registry_type} Registry if the packages are not found in the GitLab Package Registry"
-msgstr ""
+msgstr "如果在 GitLab 軟體套件註冊庫中找ä¸åˆ°è»Ÿé«”套件,則將 %{package_type} 軟體套件請求轉發到 %{registry_type} 註冊庫"
msgid "Found errors in your %{gitlab_ci_yml}:"
-msgstr ""
+msgstr "在您的 %{gitlab_ci_yml} 中找到錯誤:"
msgid "Found errors in your .gitlab-ci.yml:"
-msgstr ""
+msgstr "在.gitlab-ci.yml中發ç¾éŒ¯èª¤ï¼š"
msgid "Framework successfully deleted"
-msgstr ""
+msgstr "框架刪除æˆåŠŸ"
msgid "Free Trial of GitLab.com Ultimate"
-msgstr ""
+msgstr "å…費試用 GitLab.com Ultimate"
+
+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 "Freeze end"
-msgstr ""
+msgstr "çµæŸå‡çµ"
msgid "Freeze start"
-msgstr ""
+msgstr "開始å‡çµ"
msgid "Frequency"
-msgstr ""
+msgstr "頻率"
msgid "Frequently searched"
-msgstr ""
+msgstr "經常æœå°‹çš„"
msgid "Friday"
-msgstr ""
+msgstr "星期五"
msgid "From"
-msgstr ""
+msgstr "來自"
msgid "From %{code_open}%{source_title}%{code_close} into"
-msgstr ""
+msgstr "從%{code_open}%{source_title}%{code_close}到"
msgid "From %{providerTitle}"
-msgstr ""
+msgstr "%{providerTitle}來æºåœ°å€"
-msgid "From June 22, 2022 (GitLab 15.1), free personal namespaces and top-level groups will be limited to %{free_limit} members"
-msgstr ""
+msgid "From October 19, 2022, free groups will be limited to %d member"
+msgid_plural "From October 19, 2022, free groups will be limited to %d members"
+msgstr[0] "從 2022 å¹´ 10 月 19 日起,å…費群組將é™åˆ¶ç‚º %d åæˆå“¡"
-msgid "From June 22, 2022 (GitLab 15.1), you can have a maximum of %{free_limit} unique members across all of your personal projects"
-msgstr ""
+msgid "From October 19, 2022, you can have a maximum of %d unique member across all of your personal projects"
+msgid_plural "From October 19, 2022, you can have a maximum of %d unique members across all of your personal projects"
+msgstr[0] "從 2022 å¹´ 10 月 19 日起,您個人所有專案中最多å¯ä»¥æ“有 %d ä½å”¯ä¸€æˆå“¡"
msgid "From issue creation until deploy to production"
-msgstr ""
+msgstr "從建立議題到部署至正å¼ç’°å¢ƒ"
msgid "From merge request merge until deploy to production"
-msgstr ""
+msgstr "從åˆä½µè«‹æ±‚被åˆä½µå¾Œåˆ°éƒ¨ç½²è‡³æ­£å¼ç’°å¢ƒ"
msgid "Full"
-msgstr ""
+msgstr "全部"
msgid "Full log"
-msgstr ""
+msgstr "完整日誌"
msgid "Full name"
-msgstr ""
+msgstr "å…¨å"
msgid "GCP region configured"
-msgstr ""
+msgstr "å·²é…ç½® GCP å€åŸŸ"
msgid "GPG Key ID:"
-msgstr ""
+msgstr "GPG金鑰ID:"
msgid "GPG Keys"
-msgstr ""
+msgstr "GPG 金鑰"
msgid "GPG keys allow you to verify signed commits."
-msgstr ""
+msgstr "GPG金鑰å…許您å°ç°½åçš„æ交進行驗證。"
msgid "GPG signature (loading...)"
-msgstr ""
+msgstr "GPGç°½å(載入中...)"
msgid "General"
-msgstr ""
+msgstr "通用"
msgid "General Settings"
msgstr "一般設定"
msgid "General pipelines"
-msgstr ""
+msgstr "æµæ°´ç·šé€šç”¨è¨­å®š"
msgid "General settings"
-msgstr ""
+msgstr "一般設定"
msgid "Generate a default set of labels"
-msgstr ""
+msgstr "生æˆä¸€çµ„é è¨­çš„標記"
msgid "Generate group access tokens scoped to this group for your applications that need access to the GitLab API."
-msgstr ""
+msgstr "為需è¦å­˜å– GitLab API 的應用程å¼ç”Ÿæˆæ­¤ç¾¤çµ„範åœå…§çš„群組存å–令牌。"
msgid "Generate new export"
-msgstr ""
+msgstr "生æˆæ–°çš„匯出"
msgid "Generate project access tokens scoped to this project for your applications that need access to the GitLab API."
-msgstr ""
+msgstr "為您需è¦å­˜å–GitLab API的應用程å¼ç”Ÿæˆå°ˆæ¡ˆå­˜å–令牌。"
msgid "Generate site and private keys at"
-msgstr ""
+msgstr "生æˆç«™é»žå’Œç§é‘°åœ¨"
+
+msgid "Generated with JSON data"
+msgstr "使用JSON 資料生æˆ"
msgid "Generic"
-msgstr ""
+msgstr "通用"
msgid "Generic package file size in bytes"
-msgstr ""
+msgstr "通用文件包大å°ï¼ˆå­—節)"
msgid "GenericReport|After"
-msgstr ""
+msgstr "之後"
msgid "GenericReport|Before"
-msgstr ""
+msgstr "之å‰"
msgid "GenericReport|Diff"
-msgstr ""
+msgstr "差異"
msgid "Geo"
msgstr "Geo"
msgid "Geo Replication"
-msgstr ""
+msgstr "Geo複製"
msgid "Geo Settings"
-msgstr ""
+msgstr "Geo設置"
msgid "Geo Sites"
-msgstr ""
+msgstr "Geo 站點"
msgid "Geo sites"
-msgstr ""
+msgstr "Geo站點"
msgid "Geo|%d group selected"
msgid_plural "%d groups selected"
-msgstr[0] ""
+msgstr[0] "%d 個群組已é¸æ“‡"
msgid "Geo|%d shard selected"
msgid_plural "%d shards selected"
-msgstr[0] ""
+msgstr[0] "å·²é¸æ“‡ %d 碎片"
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}ä¸é©ç”¨%{boldEnd}:Geo 尚未驗證此元件。請åƒé–± %{linkStart}我們計劃支æ´çš„資料類型%{linkEnd}。"
msgid "Geo|%{component} synced"
-msgstr ""
+msgstr "%{component} å·²åŒæ­¥"
msgid "Geo|%{component} verified"
-msgstr ""
+msgstr "%{component} 已驗證"
+
+msgid "Geo|%{label} %{timeAgo}"
+msgstr "%{label} %{timeAgo}"
msgid "Geo|%{label} can't be blank"
-msgstr ""
+msgstr "%{label}ä¸èƒ½ç‚ºç©º"
msgid "Geo|%{label} should be between 1-999"
-msgstr ""
+msgstr "%{label}應該在1-999之間"
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} 計劃強制é‡æ–°ä¸‹è¼‰"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} 已計劃é‡æ–°åŒæ­¥"
msgid "Geo|%{name} is scheduled for re-verify"
-msgstr ""
+msgstr "%{name}已計劃é‡æ–°é©—è­‰"
msgid "Geo|%{timeAgoStr} (%{pendingEvents} events)"
-msgstr ""
+msgstr "%{timeAgoStr} (%{pendingEvents} 事件)"
msgid "Geo|%{title} checksum progress"
-msgstr ""
+msgstr "%{title} 校驗進度"
msgid "Geo|Add New Site"
-msgstr ""
+msgstr "新增站點"
msgid "Geo|Add site"
-msgstr ""
+msgstr "加入站點"
msgid "Geo|Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
-msgstr ""
+msgstr "請您調整上é¢çš„éŽæ¿¾å™¨/æœå°‹æ¢ä»¶ã€‚如果您èªç‚ºæ­¤è™•æœ‰èª¤ï¼Œè«‹åƒé–± %{linkStart}Geo Troubleshow%{linkEnd} 文件以å–得更多訊æ¯ã€‚"
msgid "Geo|All"
-msgstr ""
+msgstr "全部"
msgid "Geo|All %{replicable_name}"
-msgstr ""
+msgstr "全部 %{replicable_name}"
msgid "Geo|All projects"
-msgstr ""
+msgstr "所有專案"
msgid "Geo|All projects are being scheduled for resync"
-msgstr ""
+msgstr "所有專案都已安排é‡æ–°åŒæ­¥"
msgid "Geo|All projects are being scheduled for reverify"
-msgstr ""
+msgstr "Geo|所有專案都已安排é‡æ–°é©—è­‰"
msgid "Geo|Allow this secondary site to replicate content on Object Storage"
-msgstr ""
+msgstr "å…許此輔助站點複製物件儲存的內容"
msgid "Geo|Allowed Geo IP"
-msgstr ""
+msgstr "å…許的 Geo IP"
msgid "Geo|Allowed Geo IP can't be blank"
-msgstr ""
+msgstr "å…許的 Geo IP ä¸èƒ½ç‚ºç©ºç™½"
msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
-msgstr ""
+msgstr "å…許的 Geo IP 應介於 1 到 255 個字元之間"
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
-msgstr ""
+msgstr "å…許的 Geo IP 應包å«æœ‰æ•ˆçš„ IP 地å€"
msgid "Geo|Checksummed"
-msgstr ""
+msgstr "已校驗"
msgid "Geo|Choose specific groups or storage shards"
-msgstr ""
+msgstr "é¸æ“‡ç‰¹å®šç¾¤çµ„或儲存分片"
msgid "Geo|Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
-msgstr ""
+msgstr "逗號分隔,例如 '1.1.1.1, 2.2.2.0/24'"
msgid "Geo|Configure various settings for your %{siteType} site. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "為您的 %{siteType} 站點設定å„種組態。 %{linkStart}了解更多%{linkEnd}"
msgid "Geo|Connection timeout"
-msgstr ""
+msgstr "連線逾時"
msgid "Geo|Connection timeout can't be blank"
-msgstr ""
+msgstr "連線逾時ä¸èƒ½ç©ºç™½"
msgid "Geo|Connection timeout must be a number"
-msgstr ""
+msgstr "連線逾時必須為數字"
msgid "Geo|Connection timeout should be between 1-120"
-msgstr ""
+msgstr "連線逾時應介於 1 到 120 之間"
msgid "Geo|Consult Geo troubleshooting information"
-msgstr ""
+msgstr "諮詢 Geo 故障排除資訊"
msgid "Geo|Container repositories synchronization concurrency limit"
-msgstr ""
+msgstr "容器庫åŒæ­¥ä¸¦è¡Œé™åˆ¶"
msgid "Geo|Could not remove tracking entry for an existing project."
-msgstr ""
+msgstr "無法移除ç¾æœ‰å°ˆæ¡ˆçš„追蹤æ¢ç›®ã€‚"
msgid "Geo|Data replication lag"
-msgstr ""
+msgstr "資料複製延é²"
msgid "Geo|Data type"
-msgstr ""
+msgstr "資料類型"
msgid "Geo|Disabled"
-msgstr ""
+msgstr "å·²åœç”¨"
msgid "Geo|Discover GitLab Geo"
-msgstr ""
+msgstr "探索 GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
-msgstr ""
+msgstr "ä¸ç¬¦åˆä¸»è¦å„²å­˜ç©ºé–“設定"
msgid "Geo|Edit %{nodeType} site"
-msgstr ""
+msgstr "編輯 %{nodeType} 站點"
msgid "Geo|Edit Geo Site"
-msgstr ""
+msgstr "編輯 Geo 站點"
msgid "Geo|Edit your search and try again."
-msgstr ""
+msgstr "編輯您的查詢並且é‡è©¦"
msgid "Geo|Errors:"
-msgstr ""
+msgstr "錯誤:"
msgid "Geo|Failed"
-msgstr ""
+msgstr "失敗"
msgid "Geo|File synchronization concurrency limit"
-msgstr ""
+msgstr "文件åŒæ­¥ä¸¦è¡Œé™åˆ¶"
msgid "Geo|Filter Geo sites"
-msgstr ""
+msgstr "éŽæ¿¾ Geo 站點"
msgid "Geo|Filter by name"
-msgstr ""
+msgstr "ä¾å稱éŽæ¿¾"
msgid "Geo|Filter by status"
-msgstr ""
+msgstr "ä¾ç‹€æ…‹éŽæ¿¾"
msgid "Geo|Full details"
-msgstr ""
+msgstr "完整的細節"
msgid "Geo|Geo Settings"
-msgstr ""
+msgstr "Geo 設定"
msgid "Geo|Geo Status"
-msgstr ""
+msgstr "Geo狀態"
msgid "Geo|Geo allows you to choose specific groups or storage shards to replicate."
-msgstr ""
+msgstr "Geo å…許您é¸æ“‡è¦å¾©è£½çš„特定群組或儲存分片。"
msgid "Geo|Geo can replicate objects stored in Object Storage (AWS S3, or other compatible object storage)."
-msgstr ""
+msgstr "Geo å¯ä»¥å¾©è£½å„²å­˜åœ¨ç‰©ä»¶å„²å­˜ï¼ˆAWS S3 或其他兼容的物件儲存)中的å°è±¡ã€‚"
msgid "Geo|Geo sites"
-msgstr ""
+msgstr "Geo 站點"
msgid "Geo|Geo sites are paused using a command run on the site"
-msgstr ""
+msgstr "使用在站點上é‹è¡Œçš„命令來暫åœGeo站點"
msgid "Geo|Go to the primary site"
-msgstr ""
+msgstr "Geo|å‰å¾€ä¸»è¦ç«™é»ž"
msgid "Geo|Groups to synchronize"
-msgstr ""
+msgstr "群組åŒæ­¥"
msgid "Geo|Healthy"
-msgstr ""
+msgstr "å¥åº·"
msgid "Geo|If enabled, GitLab will handle Object Storage replication using Geo."
-msgstr ""
+msgstr "如果啟用,GitLab將使用GEO處ç†ç‰©ä»¶å„²å­˜è¤‡è£½ã€‚"
msgid "Geo|If you want to make changes, you must visit the primary site."
-msgstr ""
+msgstr "如果您è¦é€²è¡Œè®Šæ›´ï¼Œå‰‡å¿…é ˆå‰å¾€ä¸»è¦ç«™é»žã€‚"
msgid "Geo|In progress"
-msgstr ""
-
-msgid "Geo|In sync"
-msgstr ""
+msgstr "進行中"
msgid "Geo|Internal URL"
-msgstr ""
+msgstr "內部 URL"
msgid "Geo|Internal URL (optional)"
-msgstr ""
+msgstr "內部的 URL (å¯é¸)"
msgid "Geo|Last event ID from primary"
-msgstr ""
+msgstr "來自主畫é¢çš„最後一個事件 ID"
msgid "Geo|Last event ID processed by cursor"
-msgstr ""
+msgstr "由游標處ç†çš„最後一個事件 ID"
msgid "Geo|Last repository check run"
-msgstr ""
+msgstr "上次版本庫的執行檢查"
msgid "Geo|Last successful sync"
-msgstr ""
+msgstr "最近一次æˆåŠŸçš„åŒæ­¥"
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "最近一次嘗試åŒæ­¥"
msgid "Geo|Last time verified"
-msgstr ""
+msgstr "最近一次驗證"
msgid "Geo|Learn more about Geo"
-msgstr ""
+msgstr "了解更多關於 Geo"
msgid "Geo|Learn more about Geo site statuses"
-msgstr ""
+msgstr "了解更多關於 Geo 站點狀態"
msgid "Geo|Limit the number of concurrent operations this secondary site can run in the background."
-msgstr ""
+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 ""
+msgstr "GitLab Geo å¯ä»¥å»ºç«‹ GitLab 實例的唯讀映åƒ, 使得從é ç«¯ä»¿è£½(clone)和拉å–大型程å¼ç¢¼å€‰åº«çš„時間大大縮短,從而æ高團隊æˆå“¡çš„工作效率。"
msgid "Geo|Minimum interval in days"
-msgstr ""
+msgstr "最å°é–“隔天數"
msgid "Geo|Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
-msgstr ""
+msgstr "必須與 %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd} 中的 %{codeStart}external_url%{codeEnd} 匹é…。"
msgid "Geo|Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
-msgstr ""
+msgstr "å¿…é ˆç¬¦åˆ %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd} 中的 %{codeStart}geo_node_name%{codeEnd}。"
msgid "Geo|Never"
-msgstr ""
+msgstr "從ä¸"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "下一次åŒæ­¥å®‰æŽ’在"
msgid "Geo|No Geo site found"
-msgstr ""
+msgstr "未發ç¾Geo站點"
msgid "Geo|No available replication slots"
-msgstr ""
-
-msgid "Geo|Not synced yet"
-msgstr ""
+msgstr "沒有å¯ç”¨çš„複製槽"
msgid "Geo|Nothing found…"
-msgstr ""
+msgstr "什麼都沒找到…"
msgid "Geo|Nothing to checksum"
-msgstr ""
+msgstr "沒有è¦æ ¸å°çš„內容"
msgid "Geo|Nothing to synchronize"
-msgstr ""
+msgstr "沒有è¦åŒæ­¥çš„內容"
msgid "Geo|Nothing to verify"
-msgstr ""
+msgstr "沒有è¦é©—證的內容"
msgid "Geo|Object Storage replication"
-msgstr ""
+msgstr "物件儲存複製"
msgid "Geo|Offline"
-msgstr ""
+msgstr "離線"
msgid "Geo|Pending synchronization"
-msgstr ""
+msgstr "å¾…åŒæ­¥"
msgid "Geo|Pending verification"
-msgstr ""
+msgstr "å¾…é©—è­‰"
msgid "Geo|Primary"
-msgstr ""
+msgstr "主è¦çš„"
msgid "Geo|Primary site"
-msgstr ""
+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 ""
+msgstr "專案(ID: %{project_id})å·²ä¸å†å­˜åœ¨æ–¼ä¸»ç¯€é»žã€‚ç›®å‰é …ç›®å¯ä»¥è¢«å®‰å…¨çš„移除,因為這並ä¸æœƒç§»é™¤ä»»ä½•ç£ç¢Ÿä¸Šçš„有用資料。"
msgid "Geo|Projects in certain groups"
-msgstr ""
+msgstr "指定群組中的專案"
msgid "Geo|Projects in certain storage shards"
-msgstr ""
+msgstr "特定儲存片中的專案"
msgid "Geo|Queued"
-msgstr ""
+msgstr "佇列中"
msgid "Geo|Re-verification interval"
-msgstr ""
+msgstr "é‡æ–°é©—證間隔"
msgid "Geo|Redownload"
-msgstr ""
+msgstr "é‡æ–°ä¸‹è¼‰"
msgid "Geo|Remove"
-msgstr ""
+msgstr "移除"
msgid "Geo|Remove %{nodeType} site"
-msgstr ""
+msgstr "移除 %{nodeType} 站點"
msgid "Geo|Remove entry"
-msgstr ""
+msgstr "移除æ¢ç›®"
msgid "Geo|Remove site"
-msgstr ""
+msgstr "移除站點"
msgid "Geo|Remove tracking database entry"
-msgstr ""
+msgstr "移除追蹤資料庫æ¢ç›®"
msgid "Geo|Removing a Geo site stops the synchronization to and from that site. Are you sure?"
-msgstr ""
+msgstr "移除 Geo 站點會åœæ­¢èˆ‡è©²ç«™é»žçš„åŒæ­¥ã€‚您確定嗎?"
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums"
-msgstr ""
+msgstr "通éŽæ¬¡è¦ç«™é»žä½¿ç”¨æª¢æŸ¥ç¢¼(checksums)來驗證複製的資料"
msgid "Geo|Replicated data is verified with the secondary site(s) using checksums."
-msgstr ""
+msgstr "複製的資料由使用檢查碼(checksums)的次è¦ç«™é»žé©—證。"
msgid "Geo|Replication Details"
-msgstr ""
+msgstr "複製詳情"
msgid "Geo|Replication slot WAL"
-msgstr ""
+msgstr "複製槽WAL"
msgid "Geo|Replication slots"
-msgstr ""
+msgstr "複製槽"
msgid "Geo|Replication status"
-msgstr ""
+msgstr "複製狀態"
msgid "Geo|Replication summary"
-msgstr ""
+msgstr "複製摘è¦"
msgid "Geo|Repository synchronization concurrency limit"
-msgstr ""
+msgstr "儲存庫åŒæ­¥ä¸¦è¡Œé™åˆ¶"
msgid "Geo|Resync"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥"
msgid "Geo|Resync all"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥æ‰€æœ‰"
msgid "Geo|Resync all %{projects_count} projects"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥å…¨éƒ¨ %{projects_count} 個專案"
msgid "Geo|Resync all %{total}%{replicableType}"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥æ‰€æœ‰ %{total}%{replicableType}"
msgid "Geo|Resync project"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥å°ˆæ¡ˆ"
msgid "Geo|Retry count"
-msgstr ""
+msgstr "é‡è©¦è¨ˆæ•¸"
msgid "Geo|Reverify"
-msgstr ""
+msgstr "é‡æ–°æ ¡é©—"
msgid "Geo|Reverify all"
-msgstr ""
+msgstr "é‡æ–°æ ¡é©—所有"
msgid "Geo|Reverify all %{projects_count} projects"
-msgstr ""
+msgstr "é‡æ–°é©—證全部 %{projects_count} 個專案"
msgid "Geo|Reverify project"
-msgstr ""
+msgstr "é‡æ–°é©—證專案"
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary site."
-msgstr ""
+msgstr "查看複製狀態並與主è¦ç«™é»žé‡æ–°åŒæ­¥å’Œé‡æ–°é©—證專案。"
msgid "Geo|Secondary"
-msgstr ""
+msgstr "次è¦"
msgid "Geo|Secondary site"
-msgstr ""
+msgstr "次è¦ç«™é»ž"
msgid "Geo|Select groups to replicate"
-msgstr ""
+msgstr "é¸æ“‡è¦è¤‡è£½çš„群組"
msgid "Geo|Select shards to replicate"
-msgstr ""
+msgstr "é¸æ“‡è¦è¤‡è£½çš„碎片"
msgid "Geo|Selective (%{syncLabel})"
-msgstr ""
+msgstr "é¸æ“‡æ€§ (%{syncLabel})"
msgid "Geo|Selective synchronization"
-msgstr ""
+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 ""
+msgstr "以秒為單ä½è¨­ç½®é€¾æ™‚以將輔助站點狀態發é€åˆ°ä¸»ç«™é»žå’Œè¼”助站點å…許的 IP。"
msgid "Geo|Set verification limit and frequency."
-msgstr ""
+msgstr "設定驗證é™åˆ¶å’Œé »çŽ‡ã€‚"
msgid "Geo|Set what should be replicated by this secondary site."
-msgstr ""
+msgstr "設定該輔助站點應該複製的內容。"
msgid "Geo|Shards to synchronize"
-msgstr ""
+msgstr "åŒæ­¥åˆ†ç‰‡"
msgid "Geo|Show more"
-msgstr ""
+msgstr "顯示更多"
msgid "Geo|Site name can't be blank"
-msgstr ""
+msgstr "站點å稱ä¸å¯ç‚ºç©º"
msgid "Geo|Site name should be between 1 and 255 characters"
-msgstr ""
+msgstr "站點å稱應介於1~255個字元間"
msgid "Geo|Site's status was updated %{timeAgo}."
-msgstr ""
+msgstr "站點狀態更新於%{timeAgo}。"
msgid "Geo|Status"
-msgstr ""
+msgstr "狀態"
msgid "Geo|Storage config"
-msgstr ""
+msgstr "儲存é…ç½®"
msgid "Geo|Synced"
-msgstr ""
+msgstr "åŒæ­¥"
msgid "Geo|Synchronization"
-msgstr ""
+msgstr "åŒæ­¥"
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "åŒæ­¥å¤±æ•— - %{error}"
msgid "Geo|Synchronization settings"
-msgstr ""
+msgstr "åŒæ­¥è¨­å®š"
msgid "Geo|Synchronization status"
-msgstr ""
+msgstr "åŒæ­¥ç‹€æ…‹"
msgid "Geo|The URL of the primary site that is used internally by the secondary sites."
-msgstr ""
+msgstr "次級站點內部使用的主è¦ç«™é»žçš„URL。"
msgid "Geo|The URL of the secondary site that is used internally by the primary site."
-msgstr ""
+msgstr "主站點內部使用的輔助站點的URL。"
msgid "Geo|The database is currently %{db_lag} behind the primary site."
-msgstr ""
+msgstr "資料庫當å‰ä½æ–¼ä¸»ç«™é»žå¾Œé¢ %{db_lag}。"
msgid "Geo|The site is currently %{minutes_behind} behind the primary site."
-msgstr ""
+msgstr "站點當å‰ä½æ–¼ä¸»ç«™é»žå¾Œé¢ %{minutes_behind}。"
msgid "Geo|There are no %{replicable_type} to show"
-msgstr ""
+msgstr "沒有%{replicable_type}å¯é¡¯ç¤º"
msgid "Geo|There was an error deleting the Geo Site"
-msgstr ""
+msgstr "刪除Geo站點時發生錯誤"
msgid "Geo|There was an error fetching the Geo Settings"
-msgstr ""
+msgstr "讀å–Geo站點設定時發生錯誤"
msgid "Geo|There was an error fetching the Geo Sites"
-msgstr ""
+msgstr "讀å–Geo站點時發生錯誤"
msgid "Geo|There was an error fetching the Sites's Groups"
-msgstr ""
+msgstr "讀å–站點群組時發生錯誤"
msgid "Geo|There was an error saving this Geo Site"
-msgstr ""
+msgstr "儲存該Geo站點時發生錯誤"
msgid "Geo|There was an error updating the Geo Settings"
-msgstr ""
+msgstr "更新Geo設定時發生錯誤"
msgid "Geo|This will resync all %{replicableType}. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "å°‡è¦é‡æ–°åŒæ­¥æ‰€æœ‰%{replicableType}。å¯èƒ½éœ€è¦ä¸€äº›æ™‚間完æˆã€‚確定繼續嗎?"
msgid "Geo|This will resync all projects. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "å°‡è¦é‡æ–°åŒæ­¥æ‰€æœ‰å°ˆæ¡ˆã€‚å¯èƒ½éœ€è¦ä¸€äº›æ™‚間完æˆã€‚確定繼續嗎?"
msgid "Geo|This will reverify all projects. It may take some time to complete. Are you sure you want to continue?"
-msgstr ""
+msgstr "å°‡è¦é‡æ–°æ ¡é©—所有專案。å¯èƒ½éœ€è¦ä¸€äº›æ™‚間完æˆã€‚確定è¦ç¹¼çºŒå—Žï¼Ÿ"
msgid "Geo|Time in seconds"
-msgstr ""
+msgstr "以秒為單ä½çš„時間"
msgid "Geo|Tracking database entry will be removed. Are you sure?"
-msgstr ""
+msgstr "追蹤資料庫æ¢ç›®å°‡è¢«åˆªé™¤ã€‚確定繼續嗎?"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤å°ˆæ¡ˆ (%{project_id}) 的追蹤項。"
msgid "Geo|Tuning settings"
-msgstr ""
+msgstr "調整設定"
msgid "Geo|URL can't be blank"
-msgstr ""
+msgstr "URLä¸å¯ç‚ºç©º"
msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
-msgstr ""
+msgstr "URL必須有效的 url (ex: https://gitlab.com)"
msgid "Geo|Undefined"
-msgstr ""
+msgstr "未定義"
msgid "Geo|Unhealthy"
-msgstr ""
+msgstr "ä¸å¥åº·"
msgid "Geo|Unknown"
-msgstr ""
-
-msgid "Geo|Unknown state"
-msgstr ""
+msgstr "未知"
msgid "Geo|Updated %{timeAgo}"
-msgstr ""
+msgstr "æ›´æ–°æ–¼%{timeAgo}"
msgid "Geo|Verification"
-msgstr ""
+msgstr "é©—è­‰"
msgid "Geo|Verification concurrency limit"
-msgstr ""
+msgstr "驗證並行é™åˆ¶"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "驗證失敗 - %{error}"
msgid "Geo|Verification information"
-msgstr ""
+msgstr "驗證訊æ¯"
msgid "Geo|Verification status"
-msgstr ""
+msgstr "驗證狀態"
msgid "Geo|Verified"
-msgstr ""
+msgstr "已驗證"
msgid "Geo|Waiting for scheduler"
-msgstr ""
+msgstr "等待調度"
msgid "Geo|With GitLab Geo, you can install a special read-only and replicated instance anywhere."
-msgstr ""
+msgstr "使用Gitlab Geo,您å¯ä»¥åœ¨ä»»ä½•åœ°æ–¹å®‰è£ä¸€å€‹ç‰¹æ®Šçš„讀å–和復制實例。"
msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo site."
-msgstr ""
+msgstr "當å‰è™•æ–¼ä¸€å€‹æ¬¡è¦çš„,%{b_open}唯讀的%{b_close}Geo站點。"
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 "您å¯ä»¥åœ¨æ­¤é é¢ä¸Šé€²è¡Œæœ‰é™çš„更改或執行有é™çš„æ“作。"
msgid "Geo|misconfigured"
-msgstr ""
+msgstr "é…置錯誤"
msgid "Geo|primary"
-msgstr ""
+msgstr "主è¦ç¯€é»ž"
msgid "Geo|secondary"
-msgstr ""
+msgstr "次è¦ç¯€é»ž"
msgid "Get a free instance review"
-msgstr ""
+msgstr "ç²å¾—å…費的實體評估"
msgid "Get a free trial"
-msgstr ""
+msgstr "ç²å¾—å…費試用"
msgid "Get a support subscription"
-msgstr ""
+msgstr "å–得支æ´è¨‚é–±"
msgid "Get started"
-msgstr ""
+msgstr "開始使用"
msgid "Get started with GitLab"
-msgstr ""
+msgstr "開始使用 GitLab"
msgid "Get started with error tracking"
-msgstr ""
+msgstr "開始使用錯誤跟蹤"
msgid "Get started with performance monitoring"
-msgstr ""
+msgstr "開始進行效能監控"
msgid "Get started!"
-msgstr ""
+msgstr "開始å§ï¼"
msgid "Getting started with releases"
-msgstr ""
+msgstr "開始使用發佈"
msgid "Git"
-msgstr ""
+msgstr "Git"
msgid "Git GC period"
-msgstr ""
+msgstr "Git GC 週期"
msgid "Git LFS Rate Limits"
-msgstr ""
+msgstr "Git LFS 速率é™åˆ¶"
msgid "Git LFS is not enabled on this GitLab server, contact your admin."
-msgstr ""
+msgstr "æ­¤ GitLab 伺æœå™¨ä¸Šæœªå•Ÿç”¨ Git LFS,請è¯çµ¡ç®¡ç†å“¡ã€‚"
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 "如果%{docs_link_start}為專案啟用%{docs_link_end}了LFS,則Git LFSå°åƒå°‡æœƒåŒæ­¥ã€‚ 推é€æ˜ åƒ%{strong_open}無法%{strong_close}通éŽSSHåŒæ­¥LFSå°è±¡ã€‚"
msgid "Git LFS status:"
-msgstr ""
+msgstr "Git LFS 狀態:"
msgid "Git global setup"
-msgstr ""
+msgstr "Git 全域設定"
msgid "Git repository URL"
-msgstr ""
+msgstr "Git版本庫URL"
msgid "Git revision"
-msgstr ""
+msgstr "Gitæ交版本"
msgid "Git shallow clone"
-msgstr ""
+msgstr "Git 淺仿製(clone)"
msgid "Git strategy"
-msgstr ""
+msgstr "Git ç­–ç•¥"
msgid "Git transfer in progress"
-msgstr ""
+msgstr "正在進行 Git 傳輸"
msgid "Git version"
-msgstr ""
+msgstr "Git 版本"
msgid "GitAbuse|Excluded users"
-msgstr ""
+msgstr "已排除的使用者"
msgid "GitAbuse|Number of repositories"
-msgstr ""
+msgstr "版本庫數é‡"
msgid "GitAbuse|Number of repositories can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "版本庫ä¸èƒ½ç‚ºç©ºï¼Œè¨­å®šç‚º0表示沒有é™åˆ¶ã€‚"
msgid "GitAbuse|Number of repositories must be a number."
-msgstr ""
+msgstr "版本庫必須為數字。"
msgid "GitAbuse|Number of repositories should be between %{minNumRepos}-%{maxNumRepos}."
-msgstr ""
+msgstr "版本庫數é‡æ‡‰ä»‹æ–¼ %{minNumRepos}-%{maxNumRepos}之間。"
msgid "GitAbuse|Reporting time period (seconds)"
-msgstr ""
+msgstr "報告時間å€é–“(秒)"
msgid "GitAbuse|Reporting time period can't be blank. Set to 0 for no limit."
-msgstr ""
+msgstr "報告時間å€é–“ä¸èƒ½ç‚ºç©ºï¼Œè¨­å®šç‚º 0 表示沒有é™åˆ¶ã€‚"
msgid "GitAbuse|Reporting time period must be a number."
-msgstr ""
+msgstr "報告時間å€é–“必須為數字。"
msgid "GitAbuse|Reporting time period should be between %{minTimePeriod}-%{maxTimePeriod} seconds."
-msgstr ""
+msgstr "報告時間å€é–“應介於 %{minTimePeriod}-%{maxTimePeriod} 秒之間。"
msgid "GitAbuse|The maximum number of unique repositories a user can download in the specified time period before they're banned."
-msgstr ""
+msgstr "使用者在被å°éŽ–之å‰æ–¼æŒ‡å®šæ™‚é–“å€é–“å…§å¯ä»¥ä¸‹è¼‰çš„單一版本庫最大數é‡ã€‚"
msgid "GitAbuse|Users who are excluded from the Git abuse rate limit."
-msgstr ""
+msgstr "被排除在 Git 濫用率é™åˆ¶ä¹‹å¤–的使用者。"
msgid "GitAbuse|You cannot specify more than %{maxExcludedUsers} excluded users."
-msgstr ""
+msgstr "您ä¸èƒ½æŒ‡å®šè¶…éŽ %{maxExcludedUsers} 個排除的使用者。"
msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
-msgstr ""
+msgstr "已超出 GitHub API 速率é™åˆ¶ã€‚%{reset_time} 後é‡è©¦"
msgid "GitHub import"
-msgstr ""
+msgstr "GitHub匯入"
msgid "GitHubImporter|*Merged by: %{author} at %{timestamp}*"
-msgstr ""
+msgstr "GitHubImporter|*åˆä½µè€…: %{author} æ–¼ %{timestamp}*"
msgid "GitLab"
-msgstr ""
+msgstr "GitLab"
msgid "GitLab (self-managed)"
-msgstr ""
+msgstr "GitLab(自管ç†ï¼‰"
msgid "GitLab / Unsubscribe"
-msgstr ""
+msgstr "GitLab / å–消訂閱"
msgid "GitLab API"
-msgstr ""
+msgstr "GitLab API"
msgid "GitLab Account Request"
-msgstr ""
+msgstr "請求建立GitLab帳號"
msgid "GitLab Billing Team."
-msgstr ""
+msgstr "GitLab 計費團隊"
msgid "GitLab Error Tracking"
-msgstr ""
+msgstr "GitLab 錯誤追踪"
msgid "GitLab Import"
-msgstr ""
+msgstr "GitLab匯入"
msgid "GitLab Issue"
-msgstr ""
+msgstr "GitLab議題"
msgid "GitLab KAS"
-msgstr ""
+msgstr "GitLab KAS"
+
+msgid "GitLab Logo"
+msgstr "GitLab 標誌"
msgid "GitLab Pages"
-msgstr ""
+msgstr "GitLab Pages"
msgid "GitLab Shell"
-msgstr ""
+msgstr "GitLab Shell"
msgid "GitLab Support Bot"
-msgstr ""
+msgstr "GitLab支æ´æ©Ÿå™¨äºº"
msgid "GitLab Team Member"
-msgstr ""
+msgstr "GitLab團隊æˆå“¡"
msgid "GitLab Ultimate trial"
-msgstr ""
+msgstr "GitLab 旗艦版試用"
msgid "GitLab User"
-msgstr ""
+msgstr "GitLab使用者"
msgid "GitLab Workhorse"
-msgstr ""
+msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
-msgstr ""
-
-msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
-msgstr ""
+msgstr "GitLab帳號請求被拒絕"
msgid "GitLab commit"
-msgstr ""
+msgstr "GitLab æ交"
msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
-msgstr ""
+msgstr "GitLab 事件觸發 webhook。使用 webhook 請求的詳細訊æ¯ä¾†å¹«åŠ©è§£æ±ºå•é¡Œã€‚%{link_start}如何排除故障?%{link_end}"
msgid "GitLab export"
-msgstr ""
+msgstr "GitLab 匯出"
msgid "GitLab for Jira Cloud"
-msgstr ""
+msgstr "é©ç”¨æ–¼ Jira Cloud çš„ GitLab"
msgid "GitLab group: %{source_link}"
-msgstr ""
+msgstr "GitLab 群組:%{source_link}"
msgid "GitLab informs you if a new version is available. %{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "如果有新版本å¯ç”¨ï¼ŒGitLab 會通知您。 %{link_start}GitLab Inc. 收集哪些信æ¯ï¼Ÿ%{link_end}"
msgid "GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way Development, Security, and Ops teams collaborate"
-msgstr ""
+msgstr "GitLab是一個完整的DevOpså¹³å°ï¼Œä½œç‚ºå–®å€‹æ‡‰ç”¨ç¨‹å¼å‘ˆç¾ï¼Œå¾žæ ¹æœ¬ä¸Šæ”¹è®Šäº†é–‹ç™¼ï¼Œå®‰å…¨å’Œé‹ç¶­åœ˜éšŠçš„å”作方å¼"
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 ""
+msgstr "GitLab是一個完整的DevOpså¹³å°ï¼Œä½œç‚ºå–®å€‹æ‡‰ç”¨ç¨‹å¼å‘ˆç¾ï¼Œå¾žæ ¹æœ¬ä¸Šæ”¹è®Šäº†%{br_tag}開發,安全和é‹ç¶­åœ˜éšŠçš„å”作方å¼"
msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
-msgstr ""
+msgstr "GitLab是æœå‹™æ–¼æ•´å€‹è»Ÿä»¶é–‹ç™¼ç”Ÿå‘½é€±æœŸçš„單一應用程å¼ã€‚從專案è¦åŠƒå’Œæºç¢¼ç®¡ç†åˆ°CI/CDã€ç›£æŽ§å’Œå®‰å…¨ã€‚"
msgid "GitLab is 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 "GitLab å¯ä»¥å…費使用。大型團隊的許多功能是我們 %{link_start}付費產å“%{link_end} 的一部分。您å¯ä»¥å…費試用 Ultimate,無需任何義務或付款細節。"
msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
-msgstr ""
+msgstr "GitLab正在為該域å–å¾—Let's Encrypt SSL證書。這個éŽç¨‹å¯èƒ½éœ€è¦ä¸€äº›æ™‚間。請ç¨å¾Œå†è©¦ã€‚"
msgid "GitLab is open source software to collaborate on code."
-msgstr ""
+msgstr "GitLab 是用於程å¼ç¢¼å”作的開æºè»Ÿä»¶ã€‚"
msgid "GitLab is undergoing maintenance"
-msgstr ""
+msgstr "GitLab 正在進行維護"
msgid "GitLab logo"
-msgstr ""
+msgstr "GitLab 標識"
msgid "GitLab metadata URL"
-msgstr ""
+msgstr "GitLab 中繼資料 URL"
msgid "GitLab project export"
-msgstr ""
+msgstr "GitLab 專案匯出"
msgid "GitLab single sign-on URL"
-msgstr ""
+msgstr "GitLab 單一登入 URL"
msgid "GitLab username"
-msgstr ""
+msgstr "GitLab 使用者å稱"
msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs"
-msgstr ""
+msgstr "GitLab 使用 %{linkStart}Sidekiq%{linkEnd} 處ç†èƒŒæ™¯ä½œæ¥­"
msgid "GitLab version"
-msgstr ""
+msgstr "GitLab版本"
msgid "GitLab will create a branch in your fork and start a merge request."
-msgstr ""
+msgstr "GitLab å°‡åœ¨ä½ çš„åˆ†å‰ (fork) 中建立一個分支並啟動一個åˆä½µè«‹æ±‚。"
msgid "GitLab.com"
-msgstr ""
+msgstr "GitLab.com"
msgid "GitLab.com (SaaS)"
-msgstr ""
+msgstr "GitLab.com (SaaS)"
msgid "GitLab.com import"
-msgstr ""
+msgstr "從GitLab.com匯入"
msgid "GitLabPagesDomains|Retry"
-msgstr ""
+msgstr "GitLabPagesDomains|é‡è©¦"
msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
-msgstr ""
+msgstr "%{domain}尚未驗證。請存å–%{link_start}域詳細訊æ¯%{link_end}了解如何驗證所有權。"
msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
-msgstr ""
+msgstr "æ­¤Pages網站已啟用存å–控制;åªæœ‰ç¶“éŽæŽˆæ¬Šçš„使用者æ‰èƒ½å­˜å–它。如果è¦å…¬é–‹æ‚¨çš„網站,請轉到你的專案的%{strong_start}設置 &gt; å¸¸è¦ &gt; å¯è¦‹æ€§%{strong_end}並在Pages部分é¸æ“‡%{strong_start}所有人%{strong_end}。請查閱%{link_start}文件%{link_end}以å–得更多訊æ¯ã€‚"
msgid "GitLabPages|Access pages"
-msgstr ""
+msgstr "å­˜å–é é¢"
msgid "GitLabPages|Are you sure?"
-msgstr ""
+msgstr "確定繼續嗎?"
msgid "GitLabPages|Can be overridden per project. For no limit, enter 0. To inherit the value, leave empty."
-msgstr ""
+msgstr "å¯ä»¥è¢«å°ˆæ¡ˆè¦†è“‹ã€‚輸入0,表示沒é™åˆ¶ã€‚è¦ç¹¼æ‰¿è©²å€¼ï¼Œè«‹ç•™ç©ºã€‚"
msgid "GitLabPages|Certificate: %{subject}"
-msgstr ""
+msgstr "憑證: %{subject}"
+
+msgid "GitLabPages|Check the Pipeline Status"
+msgstr "檢查æµæ°´ç·šç‹€æ…‹"
msgid "GitLabPages|Configure pages"
-msgstr ""
+msgstr "設定Pages"
msgid "GitLabPages|Domains"
-msgstr ""
+msgstr "網域"
msgid "GitLabPages|Edit"
-msgstr ""
+msgstr "編輯"
msgid "GitLabPages|Expired"
-msgstr ""
+msgstr "å·²éŽæœŸ"
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
-msgstr ""
+msgstr "強制HTTPS (需è¦æœ‰æ•ˆçš„憑證)"
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 "GitLab Pages在此專案中ç¦ç”¨ã€‚您å¯ä»¥åœ¨æ‚¨çš„專案的%{strong_start}設置 &gt; å¸¸è¦ &gt; å¯è¦‹æ€§%{strong_end}é é¢å•Ÿç”¨ã€‚"
msgid "GitLabPages|Maximum size (MB)"
-msgstr ""
+msgstr "æœ€å¤§å¤§å° (MB)"
msgid "GitLabPages|New Domain"
-msgstr ""
+msgstr "新網域"
msgid "GitLabPages|Only project maintainers can remove pages"
-msgstr ""
+msgstr "åªæœ‰é …目維護者å¯ä»¥åˆªé™¤é é¢"
msgid "GitLabPages|Pages"
-msgstr ""
+msgstr "é é¢"
msgid "GitLabPages|Remove"
-msgstr ""
+msgstr "刪除"
msgid "GitLabPages|Remove certificate"
-msgstr ""
+msgstr "移除憑證"
msgid "GitLabPages|Remove domain"
-msgstr ""
+msgstr "移除網域"
msgid "GitLabPages|Remove pages"
-msgstr ""
+msgstr "刪除é é¢"
msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
-msgstr ""
+msgstr "刪除é é¢å¾Œå¤–部將無法存å–。"
msgid "GitLabPages|Save changes"
-msgstr ""
+msgstr "GitLabPages|儲存變更"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
-msgstr ""
+msgstr "在å–得網域å%{domain}çš„Let's Encrypt憑證時發生錯誤。如需é‡è©¦ï¼Œè«‹å­˜å–您的%{link_start}網域詳細訊æ¯%{link_end}。"
+
+msgid "GitLabPages|Start over"
+msgstr "é‡æ–°é–‹å§‹"
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+msgstr "GitLabPages|å°ç¶²åŸŸå’Œæ†‘證的支æ´å·²åœç”¨ã€‚è«‹è¯çµ¡æ‚¨çš„系統管ç†å“¡ä¾†å•Ÿç”¨å®ƒã€‚"
msgid "GitLabPages|Unverified"
-msgstr ""
+msgstr "未驗證"
msgid "GitLabPages|Updating your Pages configuration..."
-msgstr ""
+msgstr "正在更新您的é é¢é…ç½®..."
msgid "GitLabPages|Verified"
-msgstr ""
+msgstr "已驗證"
+
+msgid "GitLabPages|Waiting for the Pages Pipeline to complete..."
+msgstr "正在等待 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 "啟用後,所有通éŽHTTPçš„å­˜å–嘗試都會自動é‡å®šå‘到HTTPS,使用狀態代碼301。 需è¦å°æ‰€æœ‰åŸŸå有效的證書。%{docs_link_start}瞭解更多訊æ¯ã€‚%{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 "當在 GitLab 實例 (%{pages_host})的一般域å下使用 Pages 時,您ä¸èƒ½ä½¿ç”¨ HTTPS 與å­åŸŸçš„å­åŸŸå。 如果您的命å空間或群組å稱包å«ä¸€å€‹é»žï¼Œè©²å稱無效。這是一個 HTTP On TLS å”è­°çš„é™åˆ¶ã€‚ 如果您ä¸å°‡ HTTP é‡å®šå‘到 HTTPS ,HTTP é é¢å¯ä»¥æ­£å¸¸å·¥ä½œã€‚ %{docs_link_start}瞭解更多訊æ¯ã€‚%{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 "使用 GitLab Pages,您å¯ä»¥ç›´æŽ¥å¾žæ‚¨çš„ GitLab 倉庫託管您的éœæ…‹ç¶²ç«™ã€‚%{docs_link_start}瞭解更多。%{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 "您的Pages站點尚未é…置。請åƒé–± %{docs_link_start}GitLab Pages 文件%{link_end} 以瞭解如何上傳您的éœæ…‹ç«™é»žä¸¦è®“ GitLab 為其æä¾›æœå‹™ã€‚您還å¯ä»¥å¾ž %{samples_link_start}示例 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 "您的專案已é‡å° Pages 進行了設定,ç¾åœ¨æˆ‘們必須等待æµæ°´ç·šç¬¬ä¸€æ¬¡æˆåŠŸã€‚"
msgid "GitLabPages|Your pages are served under:"
-msgstr ""
+msgstr "您的網é æœå‹™å¯é€éŽä»¥ä¸‹åœ°å€å­˜å–:"
msgid "Gitaly Servers"
-msgstr ""
+msgstr "Gitaly伺æœå™¨"
msgid "Gitaly relative path:"
-msgstr ""
+msgstr "Gitaly 相å°è·¯å¾‘:"
msgid "Gitaly storage name:"
-msgstr ""
+msgstr "Gitaly 存儲å稱:"
msgid "Gitaly timeouts"
-msgstr ""
+msgstr "Gitaly 逾時"
msgid "Gitaly|Address"
-msgstr ""
+msgstr "地å€"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "Gitea 主機地å€"
msgid "Gitea Import"
-msgstr ""
+msgstr "從Gitea匯入"
msgid "GithubImporter|PR mergers"
-msgstr ""
+msgstr "PR åˆä½µ"
msgid "GithubImporter|PR reviews"
-msgstr ""
+msgstr "PR 審查"
msgid "GithubImporter|Pull requests"
-msgstr ""
+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 "建立一個具有%{status_html}å­˜å–權é™çš„%{token_link_start}個人存å–令牌%{token_link_end},並將其粘貼到此處。"
msgid "GithubIntegration|Enable static status check names"
-msgstr ""
+msgstr "啟用éœæ…‹ç‹€æ…‹æª¢æŸ¥å稱"
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
-msgstr ""
+msgstr "å–å¾—æ交和拉å–請求的狀態。"
msgid "GithubIntegration|Repository URL"
-msgstr ""
+msgstr "版本庫URL"
msgid "GithubIntegration|Select this if you want GitHub to mark status checks as \"Required\". %{learn_more_link_start}Learn more%{learn_more_link_end}."
-msgstr ""
+msgstr "如果您希望 GitHub 將狀態檢查標記為「必需ã€ï¼Œè«‹é¸æ“‡æ­¤é …。%{learn_more_link_start}瞭解更多%{learn_more_link_end}。"
msgid "GithubIntegration|Static status check names (optional)"
-msgstr ""
+msgstr "éœæ…‹ç‹€æ…‹æª¢æŸ¥å稱(å¯é¸ï¼‰"
msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
+msgstr "這需è¦å°‡æ‚¨çš„ GitHub 倉庫映åƒåˆ°æ­¤å°ˆæ¡ˆã€‚ %{docs_link}"
msgid "Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Gitpod|Enable Gitpod integration"
-msgstr ""
+msgstr "啟用Gitpodæ•´åˆ"
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "Gitpod網å€"
msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
-msgstr ""
+msgstr "é…ç½®ç‚ºè®€å– GitLab 專案的 Gitpod 實例的 URL,例如 https://gitpod.example.com。"
msgid "Gitpod|To use Gitpod you must first enable the feature in the integrations section of your %{linkStart}user preferences%{linkEnd}."
-msgstr ""
+msgstr "è¦ä½¿ç”¨ Gitpod,您必須首先在您的%{linkStart}使用者å好設置%{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 "è¦ä½¿ç”¨æ•´åˆï¼Œæ¯å€‹ä½¿ç”¨è€…還必須在其 GitLab 賬號上啟用 Gitpod。 %{link_start}如何啟用它?%{link_end} "
msgid "Gitpod|https://gitpod.example.com"
-msgstr ""
+msgstr "https://gitpod.example.com"
msgid "Given access %{time_ago}"
-msgstr ""
+msgstr "%{time_ago}授權存å–"
msgid "Given epic is already related to this epic."
-msgstr ""
+msgstr "給定å²è©©å·²ç¶“與此å²è©©é—œè¯ã€‚"
msgid "Global Search is disabled for this scope"
-msgstr ""
+msgstr "此範åœçš„全域æœå°‹å·²ç¦ç”¨"
msgid "Global Shortcuts"
-msgstr ""
+msgstr "全域快æ·éµ"
msgid "Global notification settings"
-msgstr ""
+msgstr "全域通知設定"
msgid "GlobalSearch| %{search} %{description} %{scope}"
-msgstr ""
+msgstr "%{search} %{description} %{scope}"
msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
-msgstr ""
+msgstr "æä¾› %{count} 個é è¨­çµæžœï¼Œä½¿ç”¨ä¸Šä¸‹ç®­é ­éµå°Žèˆªæœå°‹çµæžœåˆ—表。"
msgid "GlobalSearch|Groups"
-msgstr ""
+msgstr "群組"
msgid "GlobalSearch|Issues I've created"
-msgstr ""
+msgstr "我建立的議題"
msgid "GlobalSearch|Issues assigned to me"
-msgstr ""
+msgstr "已分派給我的議題"
msgid "GlobalSearch|Merge requests I've created"
-msgstr ""
+msgstr "我建立的åˆä½µè«‹æ±‚"
msgid "GlobalSearch|Merge requests assigned to me"
-msgstr ""
+msgstr "已分派給我的åˆä½µè«‹æ±‚"
msgid "GlobalSearch|Merge requests that I'm a reviewer"
-msgstr ""
+msgstr "我作為審核者的åˆä½µè«‹æ±‚"
msgid "GlobalSearch|Projects"
-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 ""
+msgstr "çµæžœå·²æ›´æ–°ï¼Œ %{count} 個çµæžœå¯ç”¨ï¼Œä½¿ç”¨ä¸Šä¸‹ç®­é ­éµç€è¦½æœå°‹çµæžœåˆ—表,或使用 ENTER éµæ交。"
msgid "GlobalSearch|Search GitLab"
-msgstr ""
+msgstr "æœå°‹ GitLab"
msgid "GlobalSearch|Search for projects, issues, etc."
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆã€è­°é¡Œç­‰ã€‚"
msgid "GlobalSearch|Search results are loading"
-msgstr ""
+msgstr "æœå°‹çµæžœæ­£åœ¨è¼‰å…¥ä¸­"
msgid "GlobalSearch|There was an error fetching search autocomplete suggestions."
-msgstr ""
+msgstr "å–å¾—æœå°‹è‡ªå‹•å®Œæˆå»ºè­°æ™‚發生錯誤。"
msgid "GlobalSearch|Type and press the enter key to submit search."
-msgstr ""
+msgstr "輸入並按回車éµæ交æœå°‹ã€‚"
msgid "GlobalSearch|Type for new suggestions to appear below."
-msgstr ""
+msgstr "新建議在下é¢é¡¯ç¤ºã€‚"
msgid "GlobalSearch|Use the shortcut key %{kbdOpen}/%{kbdClose} to start a search"
-msgstr ""
+msgstr "使用快æ·éµ %{kbdOpen}/%{kbdClose} 開始æœå°‹"
msgid "GlobalSearch|What are you searching for?"
-msgstr ""
+msgstr "您正在æœå°‹ä»€éº¼ï¼Ÿ"
msgid "GlobalSearch|all GitLab"
-msgstr ""
+msgstr "整個 GitLab"
msgid "GlobalSearch|group"
-msgstr ""
+msgstr "群組"
msgid "GlobalSearch|in %{scope}"
-msgstr ""
+msgstr "在 %{scope}"
msgid "GlobalSearch|project"
-msgstr ""
+msgstr "專案"
msgid "Globally-allowed IP ranges"
-msgstr ""
+msgstr "å…¨çƒå…許的 IP 範åœ"
msgid "Go Back"
-msgstr ""
+msgstr "返回"
msgid "Go Micro is a framework for micro service development"
-msgstr ""
+msgstr "Go Micro是一個微æœå‹™é–‹ç™¼çš„框架"
msgid "Go back"
-msgstr ""
+msgstr "返回"
msgid "Go back (while searching for files)"
-msgstr ""
+msgstr "後退(在æœå°‹æ–‡ä»¶æ™‚)"
msgid "Go back to configuration"
-msgstr ""
+msgstr "返回組態"
msgid "Go full screen"
-msgstr ""
+msgstr "全螢幕模å¼"
msgid "Go to %{source_name}"
-msgstr ""
+msgstr "å‰å¾€ %{source_name}"
msgid "Go to commits"
-msgstr ""
+msgstr "å‰å¾€æ交"
msgid "Go to definition"
-msgstr ""
+msgstr "å‰å¾€å®šç¾©"
msgid "Go to environments"
-msgstr ""
+msgstr "å‰å¾€ç’°å¢ƒ"
msgid "Go to environments page to approve or reject"
-msgstr ""
+msgstr "å‰å¾€ç’°å¢ƒé é¢ä»¥æ ¸å‡†æˆ–é§å›ž"
msgid "Go to epic"
-msgstr ""
+msgstr "å‰å¾€å²è©©ï¼ˆepic)"
msgid "Go to file"
-msgstr ""
+msgstr "å‰å¾€æ–‡ä»¶"
msgid "Go to file permalink (while viewing a file)"
-msgstr ""
+msgstr "å‰å¾€æ–‡ä»¶æ°¸ä¹…é€£çµ (åŒæ™‚查看文件)"
msgid "Go to files"
-msgstr ""
+msgstr "å‰å¾€æ–‡ä»¶"
msgid "Go to find file"
-msgstr ""
+msgstr "å‰å¾€å°‹æ‰¾æ–‡ä»¶"
msgid "Go to issue boards"
-msgstr ""
+msgstr "å‰å¾€è­°é¡Œçœ‹æ¿"
msgid "Go to issues"
-msgstr ""
+msgstr "å‰å¾€è­°é¡Œ"
msgid "Go to jobs"
-msgstr ""
+msgstr "å‰å¾€ä½œæ¥­"
msgid "Go to kubernetes"
-msgstr ""
+msgstr "å‰å¾€ kubernete"
msgid "Go to merge requests"
-msgstr ""
+msgstr "å‰å¾€åˆä½µè«‹æ±‚"
msgid "Go to metrics"
-msgstr ""
+msgstr "å‰å¾€æŒ‡æ¨™"
msgid "Go to next page"
-msgstr ""
+msgstr "å‰å¾€ä¸‹ä¸€é "
msgid "Go to next unresolved thread"
-msgstr ""
+msgstr "å‰å¾€ä¸‹ä¸€å€‹æœªè§£æ±ºçš„線程"
msgid "Go to page %{page}"
-msgstr ""
+msgstr "å‰å¾€é é¢ %{page}"
msgid "Go to parent"
-msgstr ""
+msgstr "å‰å¾€ä¸Šä¸€ç´š"
msgid "Go to parent directory"
-msgstr ""
+msgstr "å‰å¾€ä¸Šå±¤ç›®éŒ„"
msgid "Go to previous page"
-msgstr ""
+msgstr "å‰å¾€å‰ä¸€é "
msgid "Go to previous unresolved thread"
-msgstr ""
+msgstr "å‰å¾€ä¸Šä¸€å€‹æœªè§£æ±ºçš„線程"
msgid "Go to primary site"
-msgstr ""
+msgstr "å‰å¾€ä¸»è¦ç«™é»ž"
msgid "Go to project"
-msgstr ""
+msgstr "è·³å‰å¾€é …ç›®"
msgid "Go to releases"
-msgstr ""
+msgstr "å‰å¾€ç™¼ä½ˆ"
msgid "Go to repository charts"
-msgstr ""
+msgstr "å‰å¾€ç‰ˆæœ¬åº«åœ–表"
msgid "Go to repository graph"
-msgstr ""
+msgstr "å‰å¾€ç‰ˆæœ¬åº«åœ–表"
msgid "Go to snippets"
-msgstr ""
+msgstr "å‰å¾€ç¨‹å¼ç¢¼ç‰‡æ®µ"
msgid "Go to the %{b_open}Activity%{b_close} page for %{project_link}."
-msgstr ""
+msgstr "å‰å¾€ %{project_link} çš„ %{b_open}å‹•æ…‹%{b_close} é é¢ã€‚"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Allowed domains for sign-ups'."
-msgstr ""
+msgstr "å‰å¾€'管ç†ä¸­å¿ƒ &gt; 註冊é™åˆ¶',然後é¸å–'å…許註冊的網域'。"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check 'Email restrictions for sign-ups'."
-msgstr ""
+msgstr "å‰å¾€'管ç†ä¸­å¿ƒ &gt; 註冊é™åˆ¶',然後é¸å–'ç¦æ­¢ä»¥ä¸‹éƒµç®±è¨»å†Š'。"
msgid "Go to the 'Admin area &gt; Sign-up restrictions', and check the 'Domain denylist'."
-msgstr ""
+msgstr "å‰å¾€'管ç†ä¸­å¿ƒ &gt; 註冊é™åˆ¶',然後é¸å–'網域黑åå–®'。"
msgid "Go to the activity feed"
-msgstr ""
+msgstr "å‰å¾€å‹•æ…‹æº"
msgid "Go to the group’s 'Settings &gt; General' page, and check 'Restrict membership by email domain'."
-msgstr ""
+msgstr "å‰å¾€ç¾¤çµ„çš„'設置 &gt; 通用'é é¢ï¼Œç„¶å¾Œé¸å–「通éŽé›»å­éƒµä»¶åŸŸé™è£½æˆå“¡è³‡æ ¼ã€ã€‚"
msgid "Go to the milestone list"
-msgstr ""
+msgstr "å‰å¾€é‡Œç¨‹ç¢‘列表"
msgid "Go to the project's activity feed"
-msgstr ""
+msgstr "å‰å¾€é …目的動態æº"
msgid "Go to the project's overview page"
-msgstr ""
+msgstr "å‰å¾€é …目的概述é é¢"
msgid "Go to wiki"
-msgstr ""
+msgstr "å‰å¾€wiki"
msgid "Go to your To-Do list"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„待辦事項列表"
msgid "Go to your fork"
-msgstr ""
+msgstr "è·³å‰å¾€ä½ çš„分å‰é …ç›®"
msgid "Go to your groups"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„群組"
msgid "Go to your issues"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„è­°é¡Œ"
msgid "Go to your merge requests"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„åˆä½µè«‹æ±‚"
msgid "Go to your projects"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„é …ç›®"
msgid "Go to your snippets"
-msgstr ""
+msgstr "å‰å¾€æ‚¨çš„程å¼ç¢¼ç‰‡æ®µ"
msgid "Google Cloud"
-msgstr ""
+msgstr "Google 雲"
+
+msgid "Google Cloud Error - %{error}"
+msgstr "Google Cloud 錯誤 - %{error}"
msgid "Google Cloud Project"
-msgstr ""
+msgstr "Google 雲專案"
msgid "Google Cloud authorizations required"
-msgstr ""
-
-msgid "Google Cloud project misconfigured"
-msgstr ""
-
-msgid "Google Cloud project required"
-msgstr ""
+msgstr "éœ€è¦ Google 雲èªè­‰"
msgid "GoogleCloud|Cancel"
-msgstr ""
+msgstr "GoogleCloud|å–消"
msgid "GoogleCloud|Configured region is linked to the selected branch or tag"
-msgstr ""
+msgstr "å·²é…置的å€åŸŸå·²éˆæŽ¥åˆ°æ‰€é¸åˆ†æ”¯æˆ–標籤"
msgid "GoogleCloud|Create service account"
-msgstr ""
+msgstr "GoogleCloud|建立æœå‹™å¸³è™Ÿ"
msgid "GoogleCloud|Generated service account is linked to the selected branch or tag"
-msgstr ""
+msgstr "已生æˆçš„æœå‹™å¸³è™Ÿå·²éˆæŽ¥åˆ°æ‰€é¸åˆ†æ”¯æˆ–標籤"
msgid "GoogleCloud|Google Cloud project"
-msgstr ""
+msgstr "GoogleCloud|Google 雲專案"
msgid "GoogleCloud|Google OAuth2 token revocation request failed"
-msgstr ""
+msgstr "Google OAuth2 令牌撤銷請求失敗"
msgid "GoogleCloud|Google OAuth2 token revocation requested"
-msgstr ""
+msgstr "已請求 Google OAuth2 令牌撤消"
msgid "GoogleCloud|I understand the responsibilities involved with managing service account keys"
-msgstr ""
+msgstr "我瞭解管ç†æœå‹™å¸³è™Ÿé‡‘鑰所涉åŠçš„è·è²¬"
msgid "GoogleCloud|New service account is generated for the selected Google Cloud project"
-msgstr ""
+msgstr "為é¸å®šçš„ Google Cloud 專案生æˆæ–°çš„æœå‹™å¸³è™Ÿ"
msgid "GoogleCloud|Refs"
-msgstr ""
+msgstr "Refs"
msgid "GoogleCloud|Revoke authorizations"
-msgstr ""
+msgstr "撤銷授權"
msgid "GoogleCloud|Revoke authorizations granted to GitLab. This does not invalidate service accounts."
-msgstr ""
+msgstr "撤銷授予 GitLab 的授權,ä¸æœƒä½¿æœå‹™å¸³è™Ÿå¤±æ•ˆã€‚"
msgid "Got it"
-msgstr ""
+msgstr "知é“了"
msgid "Got it!"
-msgstr ""
+msgstr "了解ï¼"
msgid "Grafana URL"
-msgstr ""
+msgstr "Grafana網å€"
msgid "Grafana response contains invalid json"
-msgstr ""
+msgstr "Grafana回應包å«ç„¡æ•ˆçš„json"
msgid "GrafanaIntegration|API token"
-msgstr ""
+msgstr "API令牌"
msgid "GrafanaIntegration|Active"
-msgstr ""
+msgstr "啟用"
msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
-msgstr ""
+msgstr "輸入 %{docLinkStart}Grafana API 令牌%{docLinkEnd}。"
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
-msgstr ""
+msgstr "輸入Grafana實體的基礎URL。"
msgid "GrafanaIntegration|Grafana URL"
-msgstr ""
+msgstr "Grafana URL"
msgid "GrafanaIntegration|Grafana authentication"
-msgstr ""
+msgstr "Grafana身份驗證"
msgid "GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown."
-msgstr ""
+msgstr "設定 Grafana 身份驗證以在 GitLab Flavored Markdown 中嵌入 Grafana é¢æ¿ã€‚"
msgid "Grant access"
-msgstr ""
+msgstr "å…許存å–"
msgid "Grant write permissions to this key"
-msgstr ""
+msgstr "授予此金鑰的寫入權é™"
msgid "Graph"
-msgstr ""
+msgstr "分支圖"
msgid "GraphViewType|Job dependencies"
-msgstr ""
+msgstr "GraphViewType|作業ä¾è³´"
msgid "GraphViewType|Show dependencies"
-msgstr ""
+msgstr "GraphViewType|顯示ä¾è³´é …"
msgid "GraphViewType|Stage"
-msgstr ""
+msgstr "GraphViewType|階段"
msgid "Graphs"
-msgstr ""
+msgstr "圖表"
msgid "Gravatar"
-msgstr ""
+msgstr "Gravatar"
msgid "Gravatar enabled"
-msgstr ""
+msgstr "啟用 Gravatar"
msgid "Group"
-msgstr ""
+msgstr "群組"
msgid "Group \"%{group_name}\" was successfully updated."
-msgstr ""
+msgstr "群組 \"%{group_name}\" å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Group %{group_name} couldn't be exported."
-msgstr ""
+msgstr "無法匯出群組 %{group_name}。"
msgid "Group %{group_name} was exported successfully."
-msgstr ""
+msgstr "æˆåŠŸåŒ¯å‡ºç¾¤çµ„ %{group_name}。"
msgid "Group %{group_name} was scheduled for deletion."
-msgstr ""
+msgstr "群組%{group_name}已安排刪除。"
msgid "Group %{group_name} was successfully created."
-msgstr ""
+msgstr "群組 %{group_name} å·²æˆåŠŸå»ºç«‹ã€‚"
msgid "Group Access Tokens"
-msgstr ""
+msgstr "群組存å–令牌(權æ–)"
msgid "Group Git LFS status:"
-msgstr ""
+msgstr "群組Git LFS狀態:"
msgid "Group Hooks"
-msgstr ""
+msgstr "群組掛鉤"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
-msgstr ""
+msgstr "群組æ“有者在啟用群組管ç†å¸³è™Ÿå‰ï¼Œå¿…須先以 SAML 登入"
msgid "Group SAML must be enabled to test"
-msgstr ""
+msgstr "必須啟用群組SAMLæ‰èƒ½é€²è¡Œæ¸¬è©¦"
msgid "Group URL"
-msgstr ""
+msgstr "群組URL"
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 "在此群組中已ç¦æ­¢å»ºç«‹ç¾¤çµ„å­˜å–憑證 (access token)。您ä»ç„¶å¯ä»¥ä½¿ç”¨å’Œç®¡ç†ç¾æœ‰æ†‘證。 %{link_start}了解更多。%{link_end}"
msgid "Group application: %{name}"
-msgstr ""
+msgstr "群組應用程å¼ï¼š%{name}"
msgid "Group applications"
-msgstr ""
+msgstr "群組應用程å¼"
msgid "Group audit events"
-msgstr ""
+msgstr "群組審計事件"
msgid "Group avatar"
-msgstr ""
+msgstr "群組大頭貼"
msgid "Group by"
-msgstr ""
+msgstr "根據...分組"
msgid "Group description (optional)"
-msgstr ""
+msgstr "群組æ述(å¯é¸ï¼‰"
msgid "Group export could not be started."
-msgstr ""
+msgstr "群組匯出無法啟動。"
msgid "Group export download requests"
-msgstr ""
+msgstr "群組匯出下載請求"
msgid "Group export error"
-msgstr ""
+msgstr "群組匯出發生錯誤"
msgid "Group export link has expired. Please generate a new export from your group settings."
-msgstr ""
+msgstr "群組匯出éˆæŽ¥å·²éŽæœŸã€‚請從群組設定生æˆæ–°çš„匯出。"
msgid "Group export requests"
-msgstr ""
+msgstr "群組匯出請求"
msgid "Group export started. A download link will be sent by email and made available on this page."
-msgstr ""
+msgstr "群組匯出已經開始。下載éˆæŽ¥å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€ä¸¦åœ¨æ­¤é é¢ä¸Šæ供。"
msgid "Group has been already marked for deletion"
-msgstr ""
+msgstr "群組已標記為將被刪除"
msgid "Group has not been marked for deletion"
-msgstr ""
+msgstr "群組未標記為將被刪除"
msgid "Group import could not be scheduled"
-msgstr ""
+msgstr "無法安排群組匯入"
msgid "Group import requests"
-msgstr ""
+msgstr "群組匯入請求"
msgid "Group info:"
-msgstr ""
+msgstr "群組訊æ¯"
msgid "Group information"
-msgstr ""
+msgstr "群組資訊"
msgid "Group is required when cluster_type is :group"
-msgstr ""
+msgstr "cluster_type為:group時群組為必需"
msgid "Group jobs by"
-msgstr ""
+msgstr "群組作業ä¾"
msgid "Group members"
-msgstr ""
+msgstr "群組æˆå“¡"
msgid "Group membership expiration date changed"
-msgstr ""
+msgstr "群組æˆå“¡è³‡æ ¼åˆ°æœŸæ—¥æœŸå·²æ›´æ”¹"
msgid "Group membership expiration date removed"
-msgstr ""
+msgstr "群組æˆå“¡è³‡æ ¼åˆ°æœŸæ—¥æœŸå·²ç§»é™¤"
msgid "Group milestone"
-msgstr ""
+msgstr "群組里程碑"
msgid "Group name"
-msgstr ""
+msgstr "群組å稱"
msgid "Group name (your organization)"
-msgstr ""
+msgstr "群組å稱(您的組織)"
msgid "Group navigation"
-msgstr ""
+msgstr "群組導航"
msgid "Group overview content"
-msgstr ""
-
-msgid "Group owners can register group runners in the %{link}"
-msgstr ""
+msgstr "群組概述內容"
msgid "Group path is already taken. We've suggested one that is available."
-msgstr ""
+msgstr "群組路徑已被佔用,我們已經推薦了一個å¯ç”¨çš„。"
msgid "Group path is available."
-msgstr ""
+msgstr "群組路徑å¯ç”¨ã€‚"
msgid "Group pipeline minutes were successfully reset."
-msgstr ""
+msgstr "群組æµæ°´ç·šåˆ†é˜æ•¸å·²æˆåŠŸé‡è¨­ã€‚"
msgid "Group project URLs are prefixed with the group namespace"
-msgstr ""
+msgstr "群組專案的URL以群組命å空間為å‰ç¶´"
msgid "Group requires separate account"
-msgstr ""
+msgstr "群組需è¦å–®ç¨å¸³è™Ÿ"
msgid "Group runners"
-msgstr ""
+msgstr "群組執行器"
msgid "Group runners can be managed with the %{link}."
-msgstr ""
+msgstr "å¯ä»¥ä½¿ç”¨ %{link}管ç†ç¾¤çµ„執行器。"
msgid "Group variables (inherited)"
-msgstr ""
+msgstr "群組變數 (繼承)"
msgid "Group was exported"
-msgstr ""
+msgstr "群組已匯出"
msgid "Group was successfully updated."
-msgstr ""
+msgstr "群組已æˆåŠŸæ›´æ–°ã€‚"
msgid "Group wikis"
-msgstr ""
+msgstr "群組 Wiki"
msgid "Group-level wiki is disabled."
-msgstr ""
+msgstr "å·²ç¦ç”¨ç¾¤ç»„ wiki。"
msgid "Group: %{group_name}"
-msgstr ""
+msgstr "群組:%{group_name}"
msgid "Group: %{name}"
-msgstr ""
+msgstr "群組:%{name}"
msgid "GroupActivityMetrics|Issues created"
-msgstr ""
+msgstr "議題已建立"
msgid "GroupActivityMetrics|Last 30 days"
-msgstr ""
+msgstr "éŽåŽ» 30 天"
msgid "GroupActivityMetrics|Members added"
-msgstr ""
+msgstr "加入新æˆå“¡æ•¸"
msgid "GroupActivityMetrics|Merge Requests created"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已建立"
msgid "GroupActivityMetrics|Recent activity"
-msgstr ""
+msgstr "最近活動"
msgid "GroupImport|Failed to import group."
-msgstr ""
+msgstr "匯入群組失敗"
msgid "GroupImport|Group '%{group_name}' is being imported."
-msgstr ""
+msgstr "正在匯入群組'%{group_name}'。"
msgid "GroupImport|Group could not be imported: %{errors}"
-msgstr ""
+msgstr "無法匯入群組: %{errors}"
msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
-msgstr ""
+msgstr "匯入群組中,請ç¨å€™ã€‚å¯åœ¨ä»»æ„時刻é‡æ–°æ•´ç†ä»¥å–得當å‰ç‹€æ…‹ã€‚"
msgid "GroupImport|The group was successfully imported."
-msgstr ""
+msgstr "群組已æˆåŠŸåŒ¯å…¥ã€‚"
msgid "GroupImport|Unable to process group import file"
-msgstr ""
+msgstr "無法處ç†ç¾¤çµ„匯入文件"
msgid "GroupPage|Copy group ID"
-msgstr ""
+msgstr "複製群組 ID"
msgid "GroupPage|Group ID: %{group_id}"
-msgstr ""
+msgstr "群組 ID: %{group_id}"
msgid "GroupRoadmap|%{dateWord} – No end date"
-msgstr ""
+msgstr "%{dateWord} - ç„¡çµæŸæ—¥æœŸ"
msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
-msgstr ""
+msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|Loading epics"
-msgstr ""
+msgstr "正在載入å²è©©"
msgid "GroupRoadmap|No start and end date"
-msgstr ""
+msgstr "無開始和çµæŸæ—¥æœŸ"
msgid "GroupRoadmap|No start date – %{dateWord}"
-msgstr ""
+msgstr "無開始日期 - %{dateWord}"
msgid "GroupRoadmap|Something went wrong while fetching epics"
msgstr "è®€å– å²è©© 時發生錯誤"
msgid "GroupRoadmap|Something went wrong while fetching milestones"
-msgstr ""
+msgstr "å–得里程碑時出ç¾éŒ¯èª¤"
msgid "GroupRoadmap|Sorry, no epics matched your search"
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæœªæœå°‹åˆ°ä»»ä½•ç¬¦åˆæ¢ä»¶çš„å²è©©"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
-msgstr "開發è—圖顯示了å²è©© 沿著時間軸的進展情æ³"
+msgstr "開發è—圖顯示了å²è©©æ²¿è‘—時間軸的進展情æ³"
msgid "GroupRoadmap|This quarter"
-msgstr ""
+msgstr "本季度"
msgid "GroupRoadmap|This year"
-msgstr ""
+msgstr "今年"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
-msgstr ""
+msgstr "è¦ä½¿æ‚¨çš„å²è©©å‡ºç¾åœ¨è·¯ç·šåœ–中,請為其加入開始日期或截止日期。"
msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
-msgstr ""
+msgstr "è¦æŸ¥çœ‹é–‹ç™¼è—圖,請至少為一個%{linkStart}å­å²è©©%{linkEnd}加入開始或截止日期。"
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 ""
+msgstr "è¦æŸ¥çœ‹é–‹ç™¼è—圖,請在此群組或其å­ç¾¤çµ„中的一個 å²è©© 中加入開始日期或截止日期;從 %{startDate} 到 %{endDate}。"
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹è®Šæ›´æˆ–移除éŽæ¿¾å™¨ï¼Œå¾ž %{startDate} 到 %{endDate}。"
msgid "GroupRoadmap|Within 3 years"
msgstr "3 年之內"
msgid "GroupSAML|\"persistent\" recommended"
-msgstr ""
+msgstr "推薦的\"æŒä¹…化\""
msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
-msgstr ""
+msgstr "%{strongOpen}警告%{strongClose} - 啟用 %{linkStart}SSO 實施%{linkEnd} 以é™ä½Žå®‰å…¨é¢¨éšªã€‚"
msgid "GroupSAML|Active SAML Group Links (%{count})"
-msgstr ""
+msgstr "啟用的SAML群組éˆæŽ¥(%{count})"
msgid "GroupSAML|An error occurred generating your SCIM token. Please try again."
msgstr "ç”Ÿæˆ SCIM 憑證時發生錯誤。請é‡è©¦ã€‚"
@@ -18170,16 +18329,16 @@ msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr "您確定è¦ç§»é™¤ SAML 群組連çµï¼Ÿ"
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 "您確定è¦é‡è¨­ SCIM 權æ–嗎?在更新新權æ–之å‰ï¼ŒSCIM 佈建將åœæ­¢é‹ä½œã€‚"
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr "在執行 SSO 之å‰ï¼Œå•Ÿç”¨ SAML èªè­‰ã€‚"
-msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity, enable SSO-only authentication for web activity."
-msgstr ""
+msgid "GroupSAML|Before enforcing SSO-only authentication for Git activity of all users, enable SSO-only authentication for web activity."
+msgstr "在å°æ‰€æœ‰ä½¿ç”¨è€…çš„ Git 活動強制 SSO-only 身份驗證之å‰ï¼Œè«‹ç‚º Web 活動啟用 SSO-only 身份驗證。"
msgid "GroupSAML|Certificate fingerprint"
-msgstr ""
+msgstr "憑證指紋"
msgid "GroupSAML|Configuration"
msgstr "設定"
@@ -18188,22 +18347,22 @@ msgid "GroupSAML|Copy SAML Response XML"
msgstr "複製SAML回應XML"
msgid "GroupSAML|Could not create SAML group link: %{errors}."
-msgstr ""
+msgstr "無法建立SAML群組éˆæŽ¥ï¼š%{errors}"
msgid "GroupSAML|Default membership role"
-msgstr ""
+msgstr "é è¨­æˆå“¡è§’色"
msgid "GroupSAML|Enable SAML authentication for this group"
-msgstr ""
+msgstr "為此群組啟用 SAML 身份èªè­‰"
msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
-msgstr ""
+msgstr "å°è©²çµ„çš„ Git å’Œä¾è³´ä»£ç†æ´»å‹•å¼·åˆ¶åŸ·è¡Œ SSO-only 身份驗證"
msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
-msgstr ""
+msgstr "å°è©²ç¾¤çµ„çš„ Web 活動強制執行 SSO-only 身份驗證"
msgid "GroupSAML|Enforce users to have dedicated group-managed accounts for this group"
-msgstr ""
+msgstr "強制使用者為此群組æ“有專用的群組管ç†å¸³è™Ÿ"
msgid "GroupSAML|Generate a SCIM token"
msgstr "ç”Ÿæˆ SCIM 權æ–"
@@ -18212,40 +18371,40 @@ msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Id
msgstr "ç”Ÿæˆ SCIM 權æ–以設定系統進行跨域身份管ç†ã€‚"
msgid "GroupSAML|Identifier"
-msgstr ""
+msgstr "識別碼"
msgid "GroupSAML|Identity provider single sign-on URL"
-msgstr ""
+msgstr "身份驗證æ供商單點登入URL"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
-msgstr ""
+msgstr "請妥善儲存此權æ–-您將無法å†æ¬¡å­˜å–它的內容。"
msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "é€éŽSAML管ç†ç¾¤çµ„æˆå“¡ï¼Œé€²ä¸€æ­¥æ高安全性。"
msgid "GroupSAML|Members"
-msgstr ""
+msgstr "æˆå“¡"
msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "群組æˆå“¡åœ¨ç™»å…¥æ‚¨çš„群組時會跳å‰å¾€æ­¤è™•ã€‚請從您的身份èªè­‰æ供商處ç²å¾—該訊æ¯ã€‚它å¯èƒ½å«åšã€ŒSSOæœå‹™ä½ç½®ï¼ˆSSO Service Location)ã€ï¼Œã€ŒSAML權æ–頒發點(SAML Token Issuance Endpoint)ã€æˆ–「SAML 2.0/W-Federation URLã€ã€‚"
msgid "GroupSAML|NameID"
-msgstr ""
+msgstr "NameID"
msgid "GroupSAML|NameID Format"
-msgstr ""
+msgstr "NameIDæ ¼å¼"
msgid "GroupSAML|New SAML group link saved."
-msgstr ""
+msgstr "æ–°çš„SAML群組éˆæŽ¥å·²ä¿å­˜"
msgid "GroupSAML|No active SAML group links"
-msgstr ""
+msgstr "沒有啟用的SAML群組éˆæŽ¥"
msgid "GroupSAML|Prohibit outer forks for this group"
-msgstr ""
+msgstr "ç¦æ­¢å¾žæ­¤ç¾¤çµ„å‘外分å‰(fork)。"
msgid "GroupSAML|Reset SCIM token"
-msgstr ""
+msgstr "GroupSAML|é‡è¨­ SCIM 令牌(權æ–)"
msgid "GroupSAML|Role to assign members of this SAML group."
msgstr "指派此 SAML 群組æˆå“¡çš„角色。"
@@ -18254,22 +18413,22 @@ msgid "GroupSAML|SAML Group Links"
msgstr "SAML 群組連çµ"
msgid "GroupSAML|SAML Group Name"
-msgstr ""
+msgstr "SAML群組å稱"
msgid "GroupSAML|SAML Group Name: %{saml_group_name}"
-msgstr ""
+msgstr "SAML群組å稱: %{saml_group_name}"
msgid "GroupSAML|SAML Response Output"
-msgstr ""
+msgstr "SAML回應輸出"
msgid "GroupSAML|SAML Response XML"
-msgstr ""
+msgstr "SAML回應XML"
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "SAML 單點登入"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "SAML 單點登入設定"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr "SAML 群組連çµå·²æˆåŠŸç§»é™¤ã€‚"
@@ -18281,34 +18440,34 @@ msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get thi
msgstr "SAML權æ–ç°½å憑證的SHA1指紋。請從身份驗證æ供商處抓å–(也å¯ä»¥è¢«ç¨±ç‚ºã€Œæ‹‡æŒ‡ç´‹ã€ï¼‰ã€‚"
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 "GroupSAML|SCIM 令牌(權æ–)ç¾å·²éš±è—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œ(權æ–)çš„å€¼ï¼Œæ‚¨éœ€è¦ %{linkStart}é‡ç½®å®ƒ%{linkEnd}。"
msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
-msgstr ""
+msgstr "將由 SAML 身份æ供商發é€çš„群組å稱,å€åˆ†å¤§å°å¯«ã€‚"
msgid "GroupSAML|This will be set as the access level of users added to the group."
-msgstr ""
+msgstr "GroupSAML|這將被設定為加入到群組的使用者的存å–級別。"
msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
-msgstr ""
+msgstr "GroupSAML|為了能夠啟用群組管ç†å¸³è™Ÿï¼Œæ‚¨é¦–先需è¦å¼·åˆ¶å•Ÿç”¨ SSO。"
msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
-msgstr ""
+msgstr "GroupSAML|為了能夠ç¦æ­¢å¤–部分å‰ï¼Œæ‚¨é¦–先需è¦å¼·åˆ¶åŸ·è¡Œå°ˆç”¨çš„群組管ç†å¸³è™Ÿã€‚"
msgid "GroupSAML|Use SAML group links to manage group membership using SAML."
-msgstr ""
+msgstr "GroupSAML|使用 SAML 群組éˆæŽ¥ä¾†ç®¡ç†ä½¿ç”¨ SAML 的群組æˆå“¡è³‡æ ¼ã€‚"
msgid "GroupSAML|Valid SAML Response"
-msgstr ""
+msgstr "有效的SAML回應"
msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
-msgstr ""
+msgstr "在ç¦æ­¢å¤–部分å‰æ¨™èªŒå•Ÿç”¨å¾Œï¼Œç¾¤çµ„æˆå“¡å°‡åªèƒ½åœ¨æ‚¨çš„群組內分å‰å°ˆæ¡ˆã€‚"
msgid "GroupSAML|as %{access_level}"
-msgstr ""
+msgstr "以%{access_level}身份"
msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" to identify user and allow sign in"
-msgstr ""
+msgstr "必須匹é…儲存的「%{extern_uid}ã€çš„ NameID 以識別使用者並å…許登入"
msgid "GroupSAML|recommend persistent ID instead of email"
msgstr "建議使用永久性 ID ,ä¸è¦ä½¿ç”¨é›»å­éƒµä»¶"
@@ -18317,160 +18476,148 @@ msgid "GroupSaml|Copy SCIM API endpoint URL"
msgstr "複製 SCIM API 端點 URL"
msgid "GroupSaml|Copy SCIM token"
-msgstr ""
+msgstr "GroupSaml|複製 SCIM 令牌(權æ–)"
msgid "GroupSaml|SCIM API endpoint URL"
msgstr "SCIM API 端點 URL"
msgid "GroupSaml|Your SCIM token"
-msgstr ""
+msgstr "GroupSaml|您的 SCIM 令牌(權æ–)"
msgid "GroupSelect|No matching results"
-msgstr ""
+msgstr "沒有符åˆçš„çµæžœ"
msgid "GroupSelect|Search groups"
-msgstr ""
+msgstr "查詢群組"
msgid "GroupSelect|Select a group"
-msgstr ""
+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 ""
+msgstr "已為群組更新 Auto DevOps æµæ°´ç·š"
-msgid "GroupSettings|Automatically ban users who download more than the specified number of projects within the specified interval."
-msgstr ""
+msgid "GroupSettings|Automatically ban users who download more than a specified number of repositories in a given time."
+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 "GroupSettings|僅在頂級群組上å¯ç”¨ã€‚é©ç”¨æ–¼æ‰€æœ‰å­ç¾¤çµ„。除éžæ‰‹å‹•ç§»é™¤ï¼Œå¦å‰‡å·²èˆ‡ %{group} 以外的群組共享的群組ä»æœƒå…±äº«ã€‚"
msgid "GroupSettings|Badges"
-msgstr ""
+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 ""
+msgstr "注æ„,更改群組的父級å¯èƒ½æœƒç”¢ç”Ÿæ„想ä¸åˆ°çš„副作用。%{learn_more_link_start}瞭解更多。%{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 "無法更新路徑。因為此群組下的專案包å«äº†å®¹å™¨æ˜ åƒåº«çš„Docker映åƒã€‚請先從您的專案中移除映åƒå¾Œé‡è©¦ã€‚"
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "變更群組URL"
msgid "GroupSettings|Changing a group's URL can have unintended side effects."
-msgstr ""
+msgstr "更改群組 URL å¯èƒ½æœƒç”¢ç”Ÿæ„外的副作用。"
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 "é¸æ“‡ä¸€å€‹ç¾¤çµ„路徑,ä¸èƒ½ä»¥ç ´æŠ˜è™Ÿé–‹é ­æˆ–以å¥è™Ÿçµå°¾ï¼Œå¯ä»¥åŒ…å«å­—æ¯æ•¸å­—字符和下劃線。"
msgid "GroupSettings|Compliance frameworks"
-msgstr ""
+msgstr "åˆè¦æ¡†æž¶"
msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "設定åˆè¦æ¡†æž¶ä»¥æ供給此群組中的專案。 %{linkStart}瞭解更多訊æ¯ã€‚%{linkEnd}"
msgid "GroupSettings|Custom project templates"
msgstr "自訂專案範本"
msgid "GroupSettings|Customer relations is enabled"
-msgstr ""
+msgstr "客戶關係已啟用"
msgid "GroupSettings|Customize this group's badges."
-msgstr ""
+msgstr "自訂此該組的徽章。"
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
-msgstr ""
+msgstr "é è¨­ç‚ºæ­¤ç¾¤çµ„中所有專案的 Auto DevOps æµæ°´ç·š"
msgid "GroupSettings|Email notifications are disabled"
-msgstr ""
+msgstr "é›»å­éƒµä»¶é€šçŸ¥å·²ç¦ç”¨"
msgid "GroupSettings|Export group"
-msgstr ""
+msgstr "匯出群組"
+
+msgid "GroupSettings|Git abuse rate limit"
+msgstr "Git 濫用率é™åˆ¶"
msgid "GroupSettings|Group members are not notified if the group is mentioned."
-msgstr ""
+msgstr "防止在æåŠç¾¤çµ„時通知群組æˆå“¡ã€‚"
msgid "GroupSettings|Group mentions are disabled"
-msgstr ""
+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 ""
+msgstr "如果未在群組或實例級別指定,則é è¨­ç‚º %{default_initial_branch_name}。ä¸å½±éŸ¿ç¾æœ‰ç‰ˆæœ¬åº«ã€‚"
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|Interval (seconds)"
-msgstr ""
+msgstr "如果父群組的å¯è¦‹æ€§ä½Žæ–¼è©²ç¾¤çµ„的當å‰å¯è¦‹æ€§ï¼Œå‰‡å­ç¾¤çµ„和專案的å¯è¦‹æ€§ç´šåˆ¥å°‡æ›´æ”¹ä»¥ç¬¦åˆæ–°çˆ¶çµ„çš„å¯è¦‹æ€§ã€‚"
msgid "GroupSettings|Members cannot invite groups outside of %{group} and its subgroups"
-msgstr ""
-
-msgid "GroupSettings|Number of projects"
-msgstr ""
+msgstr "æˆå“¡ä¸èƒ½é‚€è«‹ %{group} 以外的群組åŠå…¶å­ç¾¤çµ„"
msgid "GroupSettings|Organizations and contacts can be created and associated with issues."
-msgstr ""
+msgstr "組織和è¯çµ¡äººå¯ä»¥è¢«å»ºç«‹ä¸¦é—œè¯åˆ°è­°é¡Œã€‚"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
-msgstr ""
+msgstr "覆蓋群組ã€å­ç¾¤çµ„和專案所有æˆå“¡çš„使用者通知å好設定。"
msgid "GroupSettings|Pipeline settings was updated for the group"
-msgstr ""
+msgstr "群組æµæ°´ç·šè¨­å®šå·²æ›´æ–°"
msgid "GroupSettings|Please choose a group URL with no special characters or spaces."
-msgstr ""
+msgstr "GroupSettings|è«‹é¸æ“‡ä¸€å€‹æ²’有特殊字元或空格的群組 URL。"
msgid "GroupSettings|Prevent forking outside of the group"
-msgstr ""
+msgstr "GroupSettings|防止在群組外分å‰"
msgid "GroupSettings|Prevent forking setting was not saved"
msgstr "防止分å‰è¨­å®šæœªå„²å­˜"
-msgid "GroupSettings|Project download rate limit"
-msgstr ""
-
msgid "GroupSettings|Projects in %{group} cannot be shared with other groups"
-msgstr ""
+msgstr "%{group} 內的專案無法與其他群組共享"
msgid "GroupSettings|Reporting"
-msgstr ""
+msgstr "報告"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å­ç¾¤çµ„用作該群組的自訂專案範本來æºã€‚"
msgid "GroupSettings|Select parent group"
msgstr "é¸æ“‡ä¸Šå±¤ç¾¤çµ„"
msgid "GroupSettings|Select the project containing the %{code_start}.gitlab/insights.yml%{code_end} file"
-msgstr ""
+msgstr "é¸æ“‡åŒ…å« %{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 "é¸æ“‡åŒ…å«æ‚¨çš„自定義 Insights 文件的專案。 %{help_link_start}什麼是 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 "為該群組中æ¯å€‹ Pages 站點的所有內容設置大å°é™åˆ¶ã€‚%{link_start}了解更多%{link_end}"
msgid "GroupSettings|Set the initial name and protections for the default branch of new repositories created in the group."
-msgstr ""
-
-msgid "GroupSettings|Set to 0 to disable limiting."
-msgstr ""
+msgstr "GroupSettings|為群組中建立的新檔案庫的é è¨­åˆ†æ”¯è¨­å®šåˆå§‹å稱和ä¿è­·ã€‚"
msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found."
-msgstr ""
-
-msgid "GroupSettings|The maximum number of unique projects a user can download within the specified interval before they're banned. Set to 0 to disable limiting."
-msgstr ""
+msgstr "GroupSettings|如果未找到替代 CI 設定檔案,執行 Auto DevOps æµæ°´ç·šã€‚"
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 "å¯ä»¥é¸æ“‡è©²å­ç¾¤çµ„中的專案作為該組中建立的新專案的模æ¿ã€‚ %{link_start}瞭解更多。%{link_end}"
msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
-msgstr ""
+msgstr "æ›´æ–° Auto DevOps æµæ°´ç·šæ™‚出ç¾å•é¡Œï¼š %{error_messages}。"
msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
-msgstr ""
+msgstr "æ›´æ–°æµæ°´ç·šè¨­å®šæ™‚出ç¾å•é¡Œ: %{error_messages}。"
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "此設定已經應用於 %{ancestor_group},並已覆蓋此å­ç¾¤çµ„的設定。"
@@ -18479,701 +18626,719 @@ msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share proj
msgstr "此設定已應用於 %{ancestor_group}。若è¦èˆ‡å…¶å®ƒç¾¤çµ„共享此群組中的的專案,請è¯çµ¡æ‰€æœ‰è€…覆蓋此設定或者 %{remove_ancestor_share_with_group_lock}。"
msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr ""
+msgstr "此設定已應用於 %{ancestor_group}。您å¯ä»¥è¦†è“‹æ­¤è¨­å®šæˆ– %{remove_ancestor_share_with_group_lock}。"
msgid "GroupSettings|Transfer group"
-msgstr ""
+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 "使用者å¯ä»¥åœ¨è©²ç¾¤çµ„中建立 %{link_start_project}專案存å–權æ–%{link_end} å’Œ %{link_start_group}群組存å–權æ–%{link_end}。"
msgid "GroupSettings|What are badges?"
-msgstr ""
+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 ""
+msgstr "當活èºä½¿ç”¨è€…數é‡è¶…éŽé€™å€‹æ•¸å­—時,é¡å¤–的使用者必須由 %{user_cap_docs_link_start}所有者%{user_cap_docs_link_end}核准,如果您ä¸æƒ³å¼·åˆ¶åŸ·è¡Œæ ¸å‡†ï¼Œè«‹ç•™ç©ºã€‚"
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 "當活èºä½¿ç”¨è€…數超éŽé€™å€‹æ•¸æ™‚,é¡å¤–的使用者必須是 %{user_cap_docs_link_start}由所有者%{user_cap_docs_link_end}核准。如果您ä¸æƒ³å¼·åˆ¶åŸ·è¡Œå¯©æ‰¹ï¼Œè«‹ç•™ç©ºã€‚增加使用者上é™ä¸æœƒè‡ªå‹•æ ¸å‡†å¾…定使用者。"
msgid "GroupSettings|You can only transfer the group to a group you manage."
-msgstr ""
+msgstr "您åªèƒ½å°‡ç›®å‰ç¾¤çµ„轉移到您管ç†ä¸‹çš„群組。"
msgid "GroupSettings|You will need to update your local repositories to point to the new location."
-msgstr ""
+msgstr "您需è¦æ›´æ–°æœ¬æ©Ÿç‰ˆæœ¬åº«ä»¥æŒ‡å‘æ–°ä½ç½®ã€‚"
msgid "GroupSettings|cannot be changed by you"
-msgstr ""
+msgstr "GroupSettings|您ä¸èƒ½è®Šæ›´"
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
-msgstr ""
+msgstr "無法åœç”¨çˆ¶çµ„çš„\"共享群組鎖\",åªæœ‰çˆ¶ç¾¤çµ„的所有者æ‰å¯ä»¥æ“作"
msgid "GroupSettings|cannot change when group contains projects with NPM packages"
-msgstr ""
+msgstr "當群組中的專案包å«æœ‰NPM包時,無法變更"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
-msgstr ""
+msgstr "從 %{ancestor_group_name} 中移除共享群組鎖"
msgid "Groups"
-msgstr ""
+msgstr "群組"
msgid "Groups (%{count})"
-msgstr ""
+msgstr "群組(%{count})"
msgid "Groups and projects"
-msgstr ""
+msgstr "群組和專案"
msgid "Groups are a great way to organize projects and people."
-msgstr ""
+msgstr "群組是組織專案和人員的好方法。"
msgid "Groups are the best way to manage projects and members."
-msgstr ""
+msgstr "群組是管ç†å°ˆæ¡ˆå’Œæˆå“¡çš„最佳方å¼ã€‚"
msgid "GroupsDropdown|Frequently visited"
-msgstr ""
+msgstr "經常存å–的群組"
msgid "GroupsDropdown|Groups you visit often will appear here"
-msgstr ""
+msgstr "您經常存å–的群組將出ç¾åœ¨é€™è£¡"
msgid "GroupsDropdown|Loading groups"
-msgstr ""
+msgstr "載入群組中"
msgid "GroupsDropdown|Search your groups"
-msgstr ""
+msgstr "æœå°‹æ‚¨çš„群組"
msgid "GroupsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "發生了內部錯誤."
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæœªæœå°‹åˆ°ä»»ä½•ç¬¦åˆçš„群組"
msgid "GroupsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "此功能需è¦ç€è¦½å™¨æœ¬æ©Ÿå„²å­˜æ”¯æ´"
msgid "GroupsEmptyState|A group is a collection of several projects."
-msgstr ""
+msgstr "群組是幾個專案的集åˆã€‚"
msgid "GroupsEmptyState|Create new project"
-msgstr ""
+msgstr "新建專案"
msgid "GroupsEmptyState|Create new subgroup"
-msgstr ""
+msgstr "新建å­ç¾¤çµ„"
msgid "GroupsEmptyState|Groups are the best way to manage multiple projects and members."
-msgstr ""
+msgstr "群組是管ç†å°ˆæ¡ˆå’Œæˆå“¡çš„最好方å¼ã€‚"
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
-msgstr ""
+msgstr "如果您在一個群組下組織專案,它的工作方å¼å°±åƒä¸€å€‹æ–‡ä»¶å¤¾ã€‚"
msgid "GroupsEmptyState|No groups found"
-msgstr ""
+msgstr "找ä¸åˆ°ç¾¤çµ„"
msgid "GroupsEmptyState|No subgroups or projects."
-msgstr ""
+msgstr "沒有å­ç¾¤çµ„或專案"
msgid "GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab."
-msgstr ""
+msgstr "專案是您儲存您的程å¼ç¢¼ã€å­˜å–è­°é¡Œã€wiki 和其它GitLab 功能的地方。"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
-msgstr ""
+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 "您沒有在該群組中建立å­ç¾¤çµ„或專案所需è¦çš„權é™ã€‚è«‹è¯çµ¡è©²ç¾¤çµ„çš„æ“有者來建立新的å­ç¾¤çµ„或專案。"
+
+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 "%{groupsLinkStart}群組%{groupsLinkEnd} å’Œ %{subgroupsLinkStart}å­ç¾¤çµ„%{subgroupsLinkEnd} å…許您跨多個專案進行管ç†å’Œå”作。群組的æˆå“¡å¯ä»¥å­˜å–群組的所有專案。"
msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "%{linkStart}群組%{linkEnd}å…許您在多個專案之間進行管ç†èˆ‡å”作。群組的æˆå“¡æ“有存å–其中所有專案的權é™ã€‚"
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "GroupsNew|將相關專案組åˆåœ¨ä¸€èµ·ä¸¦æŽˆäºˆæˆå“¡ä¸€æ¬¡å­˜å–多個專案的權é™ã€‚"
msgid "GroupsNew|Connect instance"
-msgstr ""
+msgstr "GroupsNew|連接實例"
msgid "GroupsNew|Contact an administrator to enable options for importing your group."
-msgstr ""
+msgstr "GroupsNew|è¯ç¹«ç®¡ç†å“¡ä»¥å•Ÿç”¨åŒ¯å…¥ç¾¤çµ„çš„é¸é …。"
msgid "GroupsNew|Create group"
-msgstr ""
+msgstr "建立群組"
msgid "GroupsNew|Create new group"
-msgstr ""
+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 ""
+msgstr "在 GitLab 實例的 %{pat_link_start}user settings%{pat_link_end} 中建立。 出於%{short_living_link_start}安全原因%{short_living_link_end},在建立令牌時使用較短的到期日期。"
msgid "GroupsNew|GitLab source URL"
-msgstr ""
+msgstr "GroupsNew|GitLab ä¾†æº URL"
msgid "GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}."
-msgstr ""
+msgstr "通éŽå»ºç«‹ %{linkStart}å­ç¾¤çµ„%{linkEnd} 也å¯ä»¥åµŒå¥—群組。"
msgid "GroupsNew|Import a group and related data from another GitLab instance."
-msgstr ""
+msgstr "從å¦ä¸€å€‹ GitLab 實例導入群組和相關資料。"
msgid "GroupsNew|Import group"
-msgstr ""
+msgstr "匯入群組"
msgid "GroupsNew|Import groups from another instance of GitLab"
-msgstr ""
+msgstr "從å¦ä¸€å€‹GitLab實例匯入群組"
msgid "GroupsNew|No import options available"
-msgstr ""
+msgstr "GroupsNew|沒有å¯ç”¨çš„匯入é¸é …"
msgid "GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}."
-msgstr ""
+msgstr "並éžæ‰€æœ‰ç›¸é—œç‰©ä»¶éƒ½å·²é·ç§»ã€‚%{docs_link_start}更多訊æ¯%{docs_link_end}。"
msgid "GroupsNew|Personal access token"
-msgstr ""
+msgstr "GroupsNew|個人存å–令牌(權æ–)(access token)"
msgid "GroupsNew|Please fill in GitLab source URL."
-msgstr ""
+msgstr "GroupsNew|請填寫 GitLab 來æºç¶²å€ã€‚"
msgid "GroupsNew|Please fill in your personal access token."
-msgstr ""
+msgstr "GroupsNew|請填寫您的個人存å–令牌(權æ–)(access token)。"
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
-msgstr ""
+msgstr "為å¦ä¸€å€‹ GitLab 實例æ供憑據以直接匯入您的群組。"
msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}."
-msgstr ""
+msgstr "此功能已棄用並由%{docs_link_start}群組é·ç§»%{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 "è¦åŒ¯å…¥ç¾¤çµ„,請å‰å¾€ GitLab 來æºå¯¦ä¾‹çš„群組設定, %{link_start}生æˆåŒ¯å‡ºæ–‡ä»¶%{link_end},然後在此處上傳。"
msgid "GroupsNew|Upload file"
-msgstr ""
+msgstr "上傳文件"
+
+msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
+msgstr "您還å¯ä»¥%{linkStart}匯入一個ç¾å­˜ç¾¤çµ„%{linkEnd}。"
msgid "GroupsNew|e.g. h8d3f016698e..."
-msgstr ""
+msgstr "例如h8d3f016698e..."
msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
-msgstr ""
+msgstr "您確定è¦é€€å‡ºç¾¤çµ„「%{fullName}ã€å—Žï¼Ÿ"
msgid "GroupsTree|Delete"
-msgstr ""
+msgstr "GroupsTree|刪除"
msgid "GroupsTree|Edit"
-msgstr ""
+msgstr "GroupsTree|編輯"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
-msgstr ""
+msgstr "無法退出群組。請確ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„群組所有者。"
msgid "GroupsTree|Leave group"
-msgstr ""
+msgstr "GroupsTree|離開群組"
msgid "GroupsTree|Loading groups"
-msgstr ""
+msgstr "載入群組中"
msgid "GroupsTree|No groups matched your search"
-msgstr ""
+msgstr "沒有æœå°‹åˆ°ä»»ä½•ç¬¦åˆçš„群組"
msgid "GroupsTree|No groups or projects matched your search"
-msgstr ""
+msgstr "沒有任何群組或項目符åˆæ‚¨çš„æœå°‹"
msgid "GroupsTree|Options"
-msgstr ""
+msgstr "GroupsTree|é¸é …"
msgid "GroupsTree|Search by name"
-msgstr ""
+msgstr "按å稱æœå°‹"
msgid "Groups|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "é ­åƒå°‡è¢«ç§»é™¤ã€‚您確定嗎?"
msgid "Groups|Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "變更群組 URL å¯èƒ½æœƒç”¢ç”Ÿéžé æœŸçš„影響。"
msgid "Groups|Checking group URL availability..."
-msgstr ""
+msgstr "正在檢查群組 URL å¯ç”¨æ€§..."
msgid "Groups|Enter a descriptive name for your group."
-msgstr ""
+msgstr "為您的群組輸入一個æ述性的å稱。"
msgid "Groups|Group ID"
-msgstr ""
+msgstr "群組 ID"
msgid "Groups|Group URL"
-msgstr ""
+msgstr "群組 URL"
msgid "Groups|Group avatar"
-msgstr ""
+msgstr "群組頭åƒ"
msgid "Groups|Group description (optional)"
-msgstr ""
+msgstr "群組æ述(å¯é¸ï¼‰"
msgid "Groups|Group name"
-msgstr ""
+msgstr "群組å稱"
msgid "Groups|Group path is available."
-msgstr ""
+msgstr "群組路徑å¯ç”¨ã€‚"
msgid "Groups|Group path is unavailable. Path has been replaced with a suggested available path."
-msgstr ""
+msgstr "群組路徑ä¸å¯ç”¨ã€‚路徑已替æ›ç‚ºå»ºè­°çš„å¯ç”¨è·¯å¾‘。"
msgid "Groups|Learn more"
-msgstr ""
+msgstr "瞭解更多"
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
-msgstr ""
+msgstr "必須以字æ¯ã€æ•¸å­—ã€è¡¨æƒ…符號或下劃線開頭,也å¯ä»¥åŒ…å«å¥é»žã€ç ´æŠ˜è™Ÿã€ç©ºæ ¼å’Œæ‹¬è™Ÿã€‚"
msgid "Groups|Remove avatar"
-msgstr ""
+msgstr "移除頭åƒ"
msgid "Groups|Save changes"
-msgstr ""
+msgstr "ä¿å­˜æ›´æ”¹"
+
+msgid "Groups|Subgroup URL"
+msgstr "å­ç¾¤çµ„ URL"
+
+msgid "Groups|Subgroup name"
+msgstr "å­ç¾¤çµ„å稱"
+
+msgid "Groups|Subgroup slug"
+msgstr "å­ç¾¤çµ„ Slug"
msgid "Guideline"
-msgstr ""
+msgstr "åƒè€ƒ"
msgid "HAR (HTTP Archive)"
-msgstr ""
+msgstr "HAR(HTTP 存檔)"
msgid "HAR file path or URL"
-msgstr ""
+msgstr "HAR 文件路徑或 URL"
msgid "HTTP Archive (HAR)"
-msgstr ""
+msgstr "HTTP 存檔 (HAR)"
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
-msgstr ""
+msgstr "HTTP Basic:存å–被拒絕\\n您必須使用具有'api'權é™çš„個人存å–令牌(權æ–)。\\n您å¯ä»¥åœ¨ %{profile_personal_access_tokens_url}中生æˆä¸€å€‹"
msgid "Harbor Registry"
-msgstr ""
+msgstr "Harbor 映åƒåº«"
-msgid "HarborIntegration|After the Harbor integration is activated, global variables ‘$HARBOR_USERNAME’, ‘$HARBOR_PASSWORD’, ‘$HARBOR_URL’ and ‘$HARBOR_PROJECT’ will be created for CI/CD use."
-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 æ•´åˆå¾Œï¼Œå°‡ç‚º CI/CD 的使用建立全局變é‡â€œ$HARBOR_USERNAMEâ€ã€â€œ$HARBOR_HOSTâ€ã€â€œ$HARBOR_OCIâ€ã€â€œ$HARBOR_PASSWORDâ€ã€â€œ$HARBOR_URLâ€å’Œâ€œ$HARBOR_PROJECTâ€ã€‚"
msgid "HarborIntegration|Base URL of the Harbor instance."
-msgstr ""
+msgstr "Harbor 實例的基本 URL。"
msgid "HarborIntegration|Enter new Harbor password"
-msgstr ""
+msgstr "輸入新的 Harbor 密碼"
msgid "HarborIntegration|Harbor URL"
-msgstr ""
+msgstr "Harbor URL"
msgid "HarborIntegration|Harbor password"
-msgstr ""
+msgstr "Harbor 密碼"
msgid "HarborIntegration|Harbor project name"
-msgstr ""
+msgstr "Harbor 專案å稱"
msgid "HarborIntegration|Harbor username"
-msgstr ""
+msgstr "Harbor 使用者å"
msgid "HarborIntegration|Leave blank to use your current password."
-msgstr ""
+msgstr "留空表示使用您當å‰çš„密碼。"
msgid "HarborIntegration|Password for your Harbor username."
-msgstr ""
+msgstr "您的 Harbor 使用者å的密碼。"
msgid "HarborIntegration|The name of the project in Harbor."
-msgstr ""
+msgstr "Harbor 中的專案å稱。"
msgid "HarborIntegration|Use Harbor as this project's container registry."
-msgstr ""
+msgstr "使用 Harbor 作為該專案的容器映åƒåº«ã€‚"
msgid "HarborRegistry|%{count} Image repository"
msgid_plural "HarborRegistry|%{count} Image repositories"
-msgstr[0] ""
+msgstr[0] "%{count} 個映åƒå€‰åº«"
msgid "HarborRegistry|%{count} Tag"
msgid_plural "HarborRegistry|%{count} Tags"
-msgstr[0] ""
+msgstr[0] "%{count} 個標籤"
msgid "HarborRegistry|Configuration digest: %{digest}"
-msgstr ""
+msgstr "é…置摘è¦: %{digest}"
msgid "HarborRegistry|Digest: %{imageId}"
-msgstr ""
+msgstr "摘è¦: %{imageId}"
msgid "HarborRegistry|Harbor Registry"
-msgstr ""
+msgstr "Harbor Registry"
msgid "HarborRegistry|Harbor connection error"
-msgstr ""
+msgstr "Harbor 連接錯誤"
msgid "HarborRegistry|Invalid tag: missing manifest digest"
-msgstr ""
+msgstr "無效標籤:缺少 manifest 摘è¦"
msgid "HarborRegistry|Last updated %{time}"
-msgstr ""
+msgstr "最近更新於%{time}"
msgid "HarborRegistry|Manifest digest: %{digest}"
-msgstr ""
+msgstr "Manifest 摘è¦: %{digest}"
msgid "HarborRegistry|Please try different search criteria"
-msgstr ""
+msgstr "請嘗試ä¸åŒçš„æœå°‹æ¢ä»¶"
msgid "HarborRegistry|Published %{timeInfo}"
-msgstr ""
+msgstr "發布於%{timeInfo}"
msgid "HarborRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "æ–¼%{date}%{time}發布到%{repositoryPath}映åƒå€‰åº«ã€‚"
msgid "HarborRegistry|Root image"
-msgstr ""
+msgstr "HarborRegistry|根映åƒæª”"
msgid "HarborRegistry|Sorry, your filter produced no results."
-msgstr ""
+msgstr "HarborRegistry|抱歉,您的éŽæ¿¾å™¨æ²’有產生任何çµæžœã€‚"
msgid "HarborRegistry|The filter returned no results"
-msgstr ""
+msgstr "HarborRegistry|éŽæ¿¾å™¨æœªè¿”回任何çµæžœ"
msgid "HarborRegistry|The image repository could not be found."
-msgstr ""
+msgstr "HarborRegistry|找ä¸åˆ°æ˜ åƒæª”版本庫。"
msgid "HarborRegistry|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 ""
+msgstr "與此映åƒç›¸é—œçš„最後一個標籤最近已被刪除。空映åƒå’Œæ‰€æœ‰ç›¸é—œè³‡æ–™å°‡ä½œç‚ºå¸¸è¦åžƒåœ¾æ”¶é›†éŽç¨‹çš„一部分自動清除。如有任何疑å•ï¼Œè«‹èˆ‡ç®¡ç†å“¡è¯ç¹«ã€‚"
msgid "HarborRegistry|The requested image repository does not exist or has been deleted. If you think this is an error, try refreshing the page."
-msgstr ""
+msgstr "請求的映åƒå€‰åº«ä¸å­˜åœ¨æˆ–已被刪除。如果您èªç‚ºé€™æ˜¯ä¸€å€‹éŒ¯èª¤ï¼Œè«‹å˜—試é‡æ–°æ•´ç†é é¢ã€‚"
msgid "HarborRegistry|This image has no active tags"
-msgstr ""
+msgstr "此映åƒæª”沒有有效標籤"
msgid "HarborRegistry|To widen your search, change or remove the filters above."
-msgstr ""
+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 ""
+msgstr "連接到 Harbor Registry 發生錯誤。請嘗試é‡æ–°æ•´ç†é é¢ã€‚如果此錯誤ä»ç„¶å­˜åœ¨ï¼Œè«‹æŸ¥çœ‹ %{docLinkStart}故障排查文件%{docLinkEnd}。"
msgid "HarborRegistry|With the Harbor Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "使用 Harbor Registry,æ¯å€‹å°ˆæ¡ˆéƒ½æœ‰è‡ªå·±çš„空間來儲存容器映åƒã€‚%{docLinkStart}更多訊æ¯%{docLinkEnd}"
msgid "Hashed Storage must be enabled to use Geo"
-msgstr ""
+msgstr "啟用哈希儲存後æ‰èƒ½ä½¿ç”¨ Geo"
msgid "Hashed repository storage paths"
-msgstr ""
+msgstr "雜湊版本庫儲存路徑"
msgid "Hashed storage can't be disabled anymore for new projects"
-msgstr ""
-
-msgid "Have a quick chat with us about your experience."
-msgstr ""
-
-msgid "Have more to say about GitLab?"
-msgstr ""
+msgstr "新專案ä¸èƒ½å†ç¦ç”¨å“ˆå¸Œå„²å­˜"
msgid "Header logo"
-msgstr ""
+msgstr "Header logo"
msgid "Header logo was successfully removed."
-msgstr ""
+msgstr "標題徽標已æˆåŠŸåˆªé™¤ã€‚"
msgid "Header logo will be removed. Are you sure?"
-msgstr ""
+msgstr "Header logo將被刪除。您確定嗎?"
msgid "Header message"
-msgstr ""
+msgstr "標頭消æ¯"
msgid "HeaderAction|incident"
-msgstr ""
+msgstr "事件"
msgid "HeaderAction|issue"
-msgstr ""
+msgstr "議題"
msgid "Headers"
-msgstr ""
+msgstr "標頭"
msgid "Heading 1"
-msgstr ""
+msgstr "標題 1"
msgid "Heading 2"
-msgstr ""
+msgstr "標題 2"
msgid "Heading 3"
-msgstr ""
+msgstr "標題 3"
msgid "Heading 4"
-msgstr ""
+msgstr "標題 4"
msgid "Health"
-msgstr ""
+msgstr "å¥åº·"
msgid "Health Check"
-msgstr ""
+msgstr "執行狀æ³æª¢æŸ¥"
msgid "Health information can be retrieved from the following endpoints. More information is available"
-msgstr ""
+msgstr "執行狀æ³è¨Šæ¯å¯ä»¥å¾žä»¥ä¸‹API路徑抓å–。如需了解更多資訊,請查看"
msgid "Health status"
-msgstr ""
+msgstr "å¥åº·ç‹€æ…‹"
msgid "Health status cannot be edited because this issue is closed"
-msgstr ""
+msgstr "無法編輯å¥åº·ç‹€æ…‹ï¼Œå› ç‚ºæ­¤è­°é¡Œå·²é—œé–‰"
msgid "HealthCheck|Access token is"
-msgstr ""
+msgstr "å­˜å–權æ–為"
msgid "HealthCheck|Healthy"
-msgstr ""
+msgstr "å¥åº·"
msgid "HealthCheck|No Health Problems Detected"
-msgstr ""
+msgstr "未檢測到執行狀æ³å•é¡Œ"
msgid "HealthCheck|Unhealthy"
-msgstr ""
+msgstr "éžå¥åº·"
msgid "Hello %{name},"
-msgstr ""
+msgstr "哈囉 %{name}:"
msgid "Hello, %{name}!"
-msgstr ""
+msgstr "哈囉,%{name}ï¼"
msgid "Hello, %{username}!"
-msgstr ""
+msgstr "哈囉,%{username}ï¼"
msgid "HelloMessage|%{handshake_emoji} Contribute to GitLab: %{contribute_link}"
-msgstr ""
+msgstr "%{handshake_emoji} å‘ GitLab è²¢ç»ç¨‹å¼ç¢¼ï¼š%{contribute_link}"
msgid "HelloMessage|%{magnifier_emoji} Create a new GitLab issue: %{new_issue_link}"
-msgstr ""
+msgstr "%{magnifier_emoji} 建立一個新的議題:%{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} 我們喜歡您的好奇心ï¼é€šéŽåŠ å…¥åœ˜éšŠä¾†å¹«åŠ©æˆ‘們改進:%{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 "æ­¤é é¢éœ€è¦ä¿®å¾©æˆ–改進嗎?打開一個議題或貢ç»ä¸€å€‹åˆä½µè«‹æ±‚,æ¯å€‹äººéƒ½å¯ä»¥åšå‡ºè²¢ç»ï¼"
msgid "HelloMessage|Welcome to GitLab!"
-msgstr ""
+msgstr "歡迎使用 GitLabï¼"
msgid "Help"
-msgstr ""
+msgstr "幫助"
msgid "Help translate GitLab into your language"
-msgstr ""
+msgstr "幫助將 GitLab 翻譯æˆæ‚¨çš„語言"
msgid "Helps prevent bots from brute-force attacks."
-msgstr ""
+msgstr "å”助防止機器人暴力攻擊。"
msgid "Helps prevent bots from creating accounts."
-msgstr ""
+msgstr "å”助防止機器人程å¼å»ºç«‹å¸³è™Ÿã€‚"
msgid "Helps prevent bots from creating accounts. %{link_start}How do I configure it?%{link_end}"
-msgstr ""
+msgstr "å”助防止機器人建立帳號。 %{link_start}如何é…置?%{link_end}"
msgid "Helps prevent bots from creating issues."
-msgstr ""
+msgstr "å”助防止機器人建立議題。"
msgid "Helps prevent malicious users hide their activity."
-msgstr ""
+msgstr "å”助防止惡æ„使用者隱è—他們的活動。"
msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
-msgstr ""
+msgstr "å”助減少請求é‡ï¼ˆä¾‹å¦‚來自爬蟲或濫用機器人的請求)"
msgid "Helps reduce request volume for protected paths."
-msgstr ""
+msgstr "å”助減少å—ä¿è­·è·¯å¾‘的請求é‡ã€‚"
msgid "Hi %{username}!"
-msgstr ""
+msgstr "%{username},您好!"
msgid "Hi %{username},"
-msgstr ""
+msgstr "å—¨ %{username},"
msgid "Hidden"
-msgstr ""
+msgstr "éš±è—"
msgid "Hide"
-msgstr ""
+msgstr "éš±è—"
msgid "Hide Live Preview"
-msgstr ""
+msgstr "éš±è—å³æ™‚é è¦½"
msgid "Hide archived projects"
-msgstr ""
+msgstr "éš±è—已歸檔的項目"
msgid "Hide chart"
msgid_plural "Hide charts"
-msgstr[0] ""
+msgstr[0] "éš±è—圖表"
msgid "Hide comments on this file"
-msgstr ""
+msgstr "éš±è—在此檔案的留言"
msgid "Hide details"
-msgstr ""
+msgstr "éš±è—詳細資料"
msgid "Hide file browser"
-msgstr ""
+msgstr "éš±è—文件ç€è¦½å™¨"
msgid "Hide group projects"
-msgstr ""
+msgstr "éš±è—群組項目"
msgid "Hide host keys manual input"
-msgstr ""
+msgstr "éš±è—主機金鑰手動輸入"
msgid "Hide list"
-msgstr ""
+msgstr "éš±è—清單"
msgid "Hide marketing-related entries from the Help page"
-msgstr ""
+msgstr "在幫助é é¢éš±è—與市場營銷相關的æ¢ç›®"
msgid "Hide payload"
-msgstr ""
+msgstr "éš±è—上傳資料"
msgid "Hide shared projects"
-msgstr ""
+msgstr "éš±è—共享項目"
msgid "Hide thread"
-msgstr ""
+msgstr "éš±è—話題"
msgid "Hide tooltips or popovers"
-msgstr ""
+msgstr "éš±è—工具æ示或彈出窗å£"
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] ""
+msgstr[0] "éš±è—值"
msgid "Hide values"
-msgstr ""
+msgstr "éš±è—值"
msgid "Hierarchy|Current structure"
-msgstr ""
+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 ""
+msgstr "通éŽå°‡å¿…è¦çš„工作分解為層次çµæ§‹ï¼Œæ›´æœ‰æ•ˆåœ°äº¤ä»˜åƒ¹å€¼ã€‚這種çµæ§‹æœ‰åŠ©æ–¼åœ˜éšŠçž­è§£ç¯„åœã€å„ªå…ˆç´šä»¥åŠå·¥ä½œå¦‚何é€æ­¥å¯¦ç¾æ›´å¤§çš„目標。"
msgid "Hierarchy|Help us improve work items in GitLab!"
-msgstr ""
+msgstr "å”助我們改進 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 "是å¦æœ‰æ‚¨å¸Œæœ›åœ¨ GitLab 中存å–的框架或工作項類型?給我們您的å饋並幫助我們建立å°æ‚¨æœ‰åƒ¹å€¼çš„體驗。"
msgid "Hierarchy|Planning hierarchy"
-msgstr ""
+msgstr "è¦åŠƒå±¤æ¬¡çµæ§‹"
msgid "Hierarchy|Take the work items survey"
-msgstr ""
+msgstr "åƒåŠ å·¥ä½œäº‹é …調查"
msgid "Hierarchy|These items are unavailable in the current structure."
-msgstr ""
+msgstr "這些事項在當å‰çµæ§‹ä¸­ä¸å¯ç”¨ã€‚"
msgid "Hierarchy|Unavailable structure"
-msgstr ""
+msgstr "ä¸å¯ç”¨çš„çµæ§‹"
msgid "Hierarchy|You can start using these items now."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é–‹å§‹ä½¿ç”¨é€™äº›äº‹é …。"
msgid "High or unknown vulnerabilities present"
-msgstr ""
+msgstr "存在高å±éšªæˆ–未知æ¼æ´ž"
msgid "Highest role:"
-msgstr ""
+msgstr "最上層角色:"
msgid "HighlightBar|Alert events:"
-msgstr ""
+msgstr "警報事件:"
msgid "HighlightBar|Alert start time:"
-msgstr ""
+msgstr "警報開始時間:"
msgid "HighlightBar|Original alert:"
-msgstr ""
+msgstr "原始警報:"
msgid "HighlightBar|Time to SLA:"
-msgstr ""
+msgstr "è·SLA時間: "
+
+msgid "Historical release"
+msgstr "æ­·å²ç™¼ä½ˆç‰ˆæœ¬"
msgid "History"
-msgstr ""
+msgstr "æ­·å²è¨˜éŒ„"
msgid "History of authentications"
-msgstr ""
+msgstr "身份驗證的歷å²"
msgid "Holder name:"
-msgstr ""
+msgstr "æŒå¡äººå§“å"
msgid "Home page URL"
-msgstr ""
+msgstr "首é URL"
msgid "Homepage"
-msgstr ""
+msgstr "主é "
msgid "Hook execution failed. Ensure the group has a project with commits."
-msgstr ""
+msgstr "Hook 執行失敗。確ä¿ç¾¤çµ„有一個包å«æ交的專案。"
msgid "Hook was successfully updated."
-msgstr ""
+msgstr "掛鉤已æˆåŠŸæ›´æ–°ã€‚"
msgid "Horizontal rule"
-msgstr ""
+msgstr "æ°´å¹³è¦å‰‡"
msgid "Hostname"
-msgstr ""
+msgstr "主機å"
msgid "Hostname used in private commit emails. %{learn_more}"
-msgstr ""
+msgstr "ç§äººæ交電å­éƒµä»¶ä¸­ä½¿ç”¨çš„主機å。 %{learn_more}"
msgid "Hour (UTC)"
-msgstr ""
+msgstr "å°æ™‚(UTC)"
msgid "Housekeeping"
-msgstr ""
+msgstr "例行維護"
msgid "Housekeeping successfully started"
-msgstr ""
+msgstr "已開始維護"
msgid "How do I configure Akismet?"
-msgstr ""
+msgstr "如何é…ç½® Akismet ?"
msgid "How do I configure runners?"
-msgstr ""
+msgstr "如何é…置執行器?"
msgid "How do I configure this integration?"
-msgstr ""
+msgstr "如何設定此整åˆï¼Ÿ"
msgid "How do I generate it?"
-msgstr ""
+msgstr "我如何生æˆå®ƒï¼Ÿ"
msgid "How do I mirror repositories?"
-msgstr ""
+msgstr "如何é¡åƒç‰ˆæœ¬åº«ï¼Ÿ"
msgid "How do I rename an environment?"
-msgstr ""
+msgstr "如何é‡å‘½å環境?"
msgid "How do I set up a Google Chat webhook?"
-msgstr ""
+msgstr "如何設定 Google Chat webhook?"
msgid "How do I set up this service?"
-msgstr ""
+msgstr "如何設定此æœå‹™ï¼Ÿ"
msgid "How do I use a web terminal?"
-msgstr ""
+msgstr "如何使用 web 終端?"
msgid "How do I use file templates?"
-msgstr ""
+msgstr "如何使用文件範本?"
+
+msgid "How does pull mirroring work?"
+msgstr "Pull mirroring 是如何é‹ä½œçš„?"
msgid "How many seconds an IP counts toward the IP address limit."
-msgstr ""
+msgstr "IP 計入 IP 地å€é™åˆ¶çš„秒數。"
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 "作業é™è£½å™¨å¦‚何處ç†è¶…出以下指定閾值的作業。 'track'模å¼åªè¨˜éŒ„作業。'compress'模å¼å£“縮作業並在壓縮大å°è¶…éŽé™åˆ¶æ™‚引發異常。"
msgid "I accept the %{terms_link}"
-msgstr ""
+msgstr "æˆ‘æŽ¥å— %{terms_link}"
msgid "I forgot my password"
-msgstr ""
+msgstr "我忘記了密碼"
msgid "I want to explore GitLab to see if it’s worth switching to"
-msgstr ""
+msgstr "我想探索 GitLab,看看是å¦å€¼å¾—切æ›åˆ°é€™è£¡"
msgid "I want to learn the basics of Git"
-msgstr ""
+msgstr "我想學習Git基礎知識"
msgid "I want to move my repository to GitLab from somewhere else"
-msgstr ""
+msgstr "我想把我的版本庫從其它地方移動到GitLab"
msgid "I want to store my code"
-msgstr ""
+msgstr "我想儲存我的程å¼ç¢¼ç¢¼"
msgid "I want to use GitLab CI with my existing repository"
-msgstr ""
+msgstr "我想在我的ç¾æœ‰ç‰ˆæœ¬åº«ä¸Šä½¿ç”¨GitLab CI"
msgid "I'd like to receive updates about GitLab via email"
-msgstr ""
+msgstr "我希望通éŽé›»å­éƒµä»¶æŽ¥æ”¶GitLabçš„æ›´æ–°"
msgid "I'm signing up for GitLab because:"
-msgstr ""
+msgstr "我註冊GitLab是因為:"
msgid "ID"
msgstr "ID"
@@ -19182,3222 +19347,3228 @@ msgid "ID:"
msgstr "ID:"
msgid "IDE"
-msgstr ""
+msgstr "æ•´åˆé–‹ç™¼ç’°å¢ƒ"
msgid "IDE|Back"
-msgstr ""
+msgstr "返回"
msgid "IDE|Commit"
-msgstr ""
+msgstr "æ交"
msgid "IDE|Commit to %{branchName} branch"
-msgstr ""
+msgstr "æ交到%{branchName}分支"
msgid "IDE|Edit"
-msgstr ""
+msgstr "編輯"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "開始時é è¦½"
msgid "IDE|Go to project"
-msgstr ""
+msgstr "å‰å¾€å°ˆæ¡ˆ"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "å³æ™‚é è¦½"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "使用Web IDE客戶端計算來é è¦½æ‚¨çš„web應用。"
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†é è¦½"
msgid "IDE|Review"
-msgstr ""
+msgstr "檢閱"
msgid "IDE|Start a new merge request"
-msgstr ""
+msgstr "開始一個新的åˆä½µè«‹æ±‚"
msgid "IDE|Successful commit"
-msgstr ""
+msgstr "æˆåŠŸæ交"
msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
-msgstr ""
+msgstr "æ­¤é¸é …被ç¦ç”¨ï¼Œå› ç‚ºæ‚¨ä¸å…許在此專案中建立åˆä½µè«‹æ±‚。"
msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
-msgstr ""
+msgstr "æ­¤é¸é …被ç¦ç”¨ï¼Œå› ç‚ºæ‚¨æ²’有當å‰åˆ†æ”¯çš„寫入權é™ã€‚"
msgid "INFO: Your SSH key has expired. Please generate a new key."
-msgstr ""
+msgstr "訊æ¯ï¼šæ‚¨çš„SSH金鑰已éŽæœŸã€‚請生æˆä¸€å€‹æ–°é‡‘鑰。"
msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
-msgstr ""
+msgstr "訊æ¯ï¼šæ‚¨çš„SSH金鑰å³å°‡éŽæœŸã€‚請生æˆä¸€å€‹æ–°é‡‘鑰。"
msgid "IP Address"
-msgstr ""
+msgstr "IP地å€"
msgid "IP address expiration time"
-msgstr ""
+msgstr "IP地å€åˆ°æœŸæ™‚é–“"
msgid "IP address restrictions"
-msgstr ""
+msgstr "IP 地å€é™åˆ¶"
msgid "IP addresses per user"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…çš„ IP 地å€"
msgid "IP subnet restriction only allowed for top-level groups"
-msgstr ""
+msgstr "åªå…許在最頂層群組設定IPå­ç¶²é™åˆ¶"
msgid "Id"
-msgstr ""
+msgstr "Id"
msgid "Identifier"
-msgstr ""
+msgstr "身份標識"
msgid "Identifiers"
-msgstr ""
+msgstr "識別碼"
msgid "Identities"
-msgstr ""
+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 ""
+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 "在您建立群組之å‰ï¼Œæˆ‘們需è¦æ‚¨ä½¿ç”¨æœ‰æ•ˆçš„付款方å¼é©—證您的身份。在此步驟中ä¸æœƒå‘您收費。如果我們需è¦å‘您收費,我們會通知您。"
msgid "IdentityVerification|Before you sign in, we need to verify your identity. Enter the following code on the sign-in page."
-msgstr ""
+msgstr "在您登入之å‰ï¼Œæˆ‘們需è¦é©—證您的身份,請在登入é é¢è¼¸å…¥ä»¥ä¸‹é©—證碼。"
msgid "IdentityVerification|Create a project"
-msgstr ""
+msgstr "建立專案"
msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}"
-msgstr ""
+msgstr "為了增加安全性,您需è¦é©—證您的身份。我們已發é€é©—證碼到 %{email}"
msgid "IdentityVerification|Help us protect your account"
-msgstr ""
+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 ""
+msgstr "如果您最近沒有åšè©¦ç™»å…¥ GitLab,我們建議 %{password_link_start}更改您的密碼%{link_end} 並且 %{two_fa_link_start} 設定雙因å­èªè­‰ %{link_end} 以確ä¿æ‚¨çš„帳號安全。您的驗證碼將在 %{expires_in_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 "如果您最近沒有åšè©¦ç™»å…¥ GitLab,我們建議更改您的密碼 (%{password_link}) 並且設定雙因å­èªè­‰ (%{two_fa_link}) 以確ä¿æ‚¨çš„帳號安全。"
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 "如果您無法存å–與該帳號關è¯çš„é›»å­éƒµä»¶æˆ–驗證碼有å•é¡Œï¼Œ %{link_start}這裡是您å¯ä»¥æŽ¡å–的其他一些步驟。%{link_end}"
msgid "IdentityVerification|Maximum login attempts exceeded. Wait %{interval} and try again."
-msgstr ""
+msgstr "已超éŽæœ€å¤§ç™»å…¥å˜—試次數。等待 %{interval} 後å†é‡è©¦ã€‚"
msgid "IdentityVerification|Please enter a valid code"
-msgstr ""
+msgstr "請輸入有效的驗證碼"
msgid "IdentityVerification|Resend code"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€é©—證碼"
msgid "IdentityVerification|The code has expired. Resend a new code and try again."
-msgstr ""
+msgstr "驗證碼已éŽæœŸï¼Œé‡æ–°ç™¼é€æ–°é©—證碼並é‡è©¦ã€‚"
msgid "IdentityVerification|The code is incorrect. Enter it again, or resend a new code."
-msgstr ""
+msgstr "驗證碼ä¸æ­£ç¢ºï¼Œå†æ¬¡è¼¸å…¥æˆ–é‡æ–°ç™¼é€æ–°é©—證碼。"
msgid "IdentityVerification|Verification code"
-msgstr ""
+msgstr "驗證碼"
msgid "IdentityVerification|Verification successful"
-msgstr ""
+msgstr "é©—è­‰æˆåŠŸ"
msgid "IdentityVerification|Verify code"
-msgstr ""
+msgstr "æ ¸å°é©—證碼"
msgid "IdentityVerification|Verify your identity"
-msgstr ""
+msgstr "驗證您的身份"
msgid "IdentityVerification|You can always verify your account at a later time to create a group."
-msgstr ""
+msgstr "您å¯ä»¥ç¨å¾Œéš¨æ™‚驗證您的帳號,來建立一個群組。"
msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or resend a new code and try again."
-msgstr ""
+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 ""
+msgstr "您的帳號已æˆåŠŸé©—證,ç¨å¾Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘至您的帳號或%{redirect_url_start}點擊此處%{redirect_url_end} 刷新。"
msgid "IdentityVerification|Your verification code expires after %{expires_in_minutes} minutes."
-msgstr ""
+msgstr "您的驗證碼將在 %{expires_in_minutes} 分é˜å¾ŒéŽæœŸã€‚"
+
+msgid "Identity|Provider ID"
+msgstr "æ供者 ID"
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 "如果任何索引字段超éŽæ­¤é™åˆ¶ï¼Œå‰‡å°‡å…¶æˆªæ–·ç‚ºæ­¤å­—符數。其餘內容既ä¸ç·¨å…¥ç´¢å¼•ä¹Ÿä¸å¯æœå°‹ã€‚這ä¸é©ç”¨æ–¼å€‰åº«å’Œ wiki 索引。å°æ–¼ç„¡é™å­—符,將此設定為 0。"
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
-msgstr ""
+msgstr "如果為空,é è¨­ç‚º %{code_open}ç¨å¾Œé‡è©¦%{code_close}。"
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 ""
+msgstr "如果為空,則將å…許壽命設定為 %{instance_level_policy_in_words},如實例管ç†å“¡æ‰€å®šç¾©ã€‚設定後,該群組中的使用者ç¾æœ‰ä»¤ç‰Œå¯èƒ½æœƒè¢«æ’¤éŠ·ã€‚"
msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
-msgstr ""
+msgstr "如é¸å–,則群組所有者å¯ä»¥ç®¡ç†LDAP群組連çµå’Œ LDAPæˆå“¡è¦†è“‹"
msgid "If checked, new group memberships and permissions can only be added via LDAP synchronization"
-msgstr ""
+msgstr "é¸å–後將則åªèƒ½é€éŽLDAPåŒæ­¥åŠ å…¥æ–°çš„組æˆå“¡èº«ä»½å’Œæ¬Šé™"
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 ""
+msgstr "如果åœç”¨ï¼Œåˆ†å‰çš„本地分支將ä¸æœƒè‡ªå‹•æ›´æ–°å…¶é ç¨‹åˆ†æ”¯çš„æ交,以防止本地資料丟失。 如果é è¨­åˆ†æ”¯ (%{default_branch}) 已經發散並且無法更新,則é¡åƒå°‡å¤±æ•—。 其他分歧的分支被默默地忽略。 %{link_start}了解更多。%{link_end}"
msgid "If disabled, only administrators can configure repository mirroring."
-msgstr ""
+msgstr "如果åœç”¨ï¼Œå‰‡åªæœ‰ç®¡ç†å“¡å¯ä»¥è¨­å®šå€‰åº«æ˜ åƒã€‚"
msgid "If enabled, only protected branches will be mirrored."
-msgstr ""
+msgstr "如果啟用,則åªæœƒæ˜ åƒå—ä¿è­·çš„分支。"
msgid "If no options are selected, only administrators can register runners."
-msgstr ""
+msgstr "如果未é¸å–任何é¸é …,則åªæœ‰ç®¡ç†å“¡å¯ä»¥è¨»å†ŠåŸ·è¡Œå™¨ã€‚"
+
+msgid "If none of the options work, try contacting a GitLab administrator."
+msgstr "如果這些é¸é …都ä¸èµ·ä½œç”¨ï¼Œè«‹å˜—試è¯çµ¡ 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 "若啟用的使用者數é‡è¶…éŽé™åˆ¶ï¼Œæ‚¨å°‡æœƒåœ¨ä¸‹æ¬¡çºŒç´„æ™‚è¢«æ”¶å– %{users_over_license_link} 人的費用"
msgid "If this email was added in error, you can remove it here:"
-msgstr ""
+msgstr "如果此電å­éƒµä»¶è¢«éŒ¯èª¤åŠ å…¥ï¼Œæ‚¨å¯ä»¥åœ¨é€™è£¡ç§»é™¤ï¼š"
msgid "If this email was added in error, you can remove it here: %{profile_emails_url}"
-msgstr ""
+msgstr "如果此電å­éƒµä»¶è¢«éŒ¯èª¤åŠ å…¥ï¼Œæ‚¨å¯ä»¥åœ¨é€™è£¡ç§»é™¤å®ƒï¼š %{profile_emails_url}"
msgid "If this is a mistake, you can %{link_start}unban them%{link_end}."
-msgstr ""
+msgstr "如果這是一個錯誤,您å¯ä»¥ %{link_start}解ç¦ä»–們%{link_end}。"
msgid "If this is a mistake, you can unban them: %{url}."
-msgstr ""
+msgstr "如果這是一個錯誤,你å¯ä»¥è§£ç¦ä»–們:%{url}。"
msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
-msgstr ""
+msgstr "如果這是一個錯誤,你å¯ä»¥%{leave_link_start}退出%{source_type}%{link_end}。"
msgid "If this was a mistake you can leave the %{source_type}."
-msgstr ""
+msgstr "如果這是一個錯誤,你å¯ä»¥é€€å‡º%{source_type}。"
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
-msgstr ""
+msgstr "如使用 GitHub,GitHub çš„æ交 (commits) å’Œæå–è¦æ±‚ (pull request) é é¢å°‡é¡¯ç¤ºæµæ°´ç·šç‹€æ…‹ã€‚%{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 "如果將%{codeStart}needs%{codeEnd}加到æµæ°´ç·šçš„作業裡é¢ï¼Œæ‚¨å°‡å¯ä»¥åœ¨%{linkStart}有å‘無環圖 (DAG)%{linkEnd}é é¢çœ‹åˆ°ä½œæ¥­ä¹‹é–“çš„%{codeStart}needs%{codeEnd}關係。"
msgid "If you are added to a project, it will be displayed here."
-msgstr ""
+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 ""
+msgstr "如果您沒有發起這些登入嘗試,請è¯ç¹«æ‚¨çš„管ç†å“¡æˆ–在您的帳號上啟用雙é‡èº«ä»½é©—證(2FA)。"
msgid "If you did not initiate this change, please contact your administrator immediately."
-msgstr ""
+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 ""
+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 ""
+msgstr "如果您從版本庫檢查中得到大é‡èª¤å ±ï¼Œæ‚¨å¯ä»¥å¾žè³‡æ–™åº«ä¸­æ¸…除所有版本庫檢查訊æ¯ã€‚"
msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
-msgstr ""
+msgstr "如果您éºå¤±äº†å¾©åŽŸç¢¼ï¼Œæ‚¨å¯ä»¥ç”Ÿæˆæ–°çš„復原碼,所有以å‰çš„復原碼將失效。"
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
-msgstr ""
+msgstr "如果您最近從上述IP地å€ç™»å…¥éŽï¼Œå‰‡å¯ä»¥å¿½ç•¥æ­¤é›»å­éƒµä»¶ã€‚"
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
-msgstr ""
+msgstr "如果您想è¦é‡æ–°å•Ÿç”¨é›™å› å­èº«ä»½é©—證,請訪å•%{two_factor_link}"
msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
-msgstr ""
+msgstr "如果您想è¦é‡æ–°å•Ÿç”¨é›™å› å­èº«ä»½é©—證,請訪å•%{settings_link_to}é é¢ã€‚"
msgid "If you want to remove this email address, visit %{profile_link}"
-msgstr ""
+msgstr "如果您想刪除此電å­éƒµä»¶åœ°å€ï¼Œè«‹è¨ªå• %{profile_link}"
msgid "If you want to remove this email address, visit the %{settings_link_to} page."
-msgstr ""
+msgstr "如果您想刪除此電å­éƒµä»¶åœ°å€ï¼Œè«‹è¨ªå• %{settings_link_to} é é¢ã€‚"
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 "如果您已購買或續訂訂閱並æ“有啟動碼,請在下方輸入啟動碼以開始啟動éŽç¨‹ã€‚"
msgid "If your HTTP repository is not publicly accessible, add your credentials."
-msgstr ""
+msgstr "如果您的HTTP版本庫無法公開存å–,需在地å€ä¸­åŠ å…¥æ†‘據。"
msgid "Ignore"
-msgstr ""
+msgstr "忽略"
msgid "Ignored"
-msgstr ""
+msgstr "已忽略"
msgid "Image URL"
-msgstr ""
+msgstr "圖片網å€"
msgid "ImageDiffViewer|2-up"
-msgstr ""
+msgstr "並列(2-up)"
msgid "ImageDiffViewer|Onion skin"
-msgstr ""
+msgstr "分幀(Onion skin)"
msgid "ImageDiffViewer|Swipe"
-msgstr ""
+msgstr "滑動"
msgid "ImageViewerDimensions|H"
-msgstr ""
+msgstr "高"
msgid "ImageViewerDimensions|W"
-msgstr ""
+msgstr "寬"
msgid "Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior."
-msgstr ""
+msgstr "尺寸ä¸æ­£ç¢ºçš„圖åƒä¸æœƒè‡ªå‹•èª¿æ•´å¤§å°ï¼Œä¸¦ä¸”å¯èƒ½æœƒå°Žè‡´æ„外行為。"
msgid "Impersonate"
-msgstr ""
+msgstr "模擬"
msgid "Impersonation Tokens"
-msgstr ""
+msgstr "身份模擬令牌"
msgid "Impersonation has been disabled"
-msgstr ""
+msgstr "身份模擬已被ç¦ç”¨"
msgid "Import"
-msgstr ""
+msgstr "匯入"
msgid "Import %d compatible repository"
msgid_plural "Import %d compatible repositories"
-msgstr[0] ""
+msgstr[0] "匯入%d個兼容的倉庫"
msgid "Import %d repository"
msgid_plural "Import %d repositories"
-msgstr[0] ""
+msgstr[0] "匯入%d個倉庫"
msgid "Import CSV"
-msgstr ""
+msgstr "匯入CSV"
msgid "Import Projects from Gitea"
-msgstr ""
+msgstr "從Gitea匯入專案"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "匯入一個從GitLab匯出的項目"
msgid "Import and export rate limits"
-msgstr ""
+msgstr "匯入/匯出速率é™åˆ¶"
msgid "Import failed due to a GitHub error: %{original} (HTTP %{code})"
-msgstr ""
+msgstr "由於 GitHub 錯誤,匯入失敗: %{original}(HTTP %{code})"
msgid "Import from"
-msgstr ""
+msgstr "匯入自"
msgid "Import from Jira"
-msgstr ""
+msgstr "從Jira匯入"
msgid "Import group"
-msgstr ""
+msgstr "匯入群組"
msgid "Import group from file"
-msgstr ""
+msgstr "從文件匯入群組"
msgid "Import groups"
-msgstr ""
+msgstr "匯入群組"
msgid "Import history"
-msgstr ""
+msgstr "匯入歷å²"
msgid "Import in progress"
-msgstr ""
+msgstr "正在匯入"
msgid "Import in progress. Refresh page to see newly added issues."
-msgstr ""
+msgstr "匯入進行中。é‡æ–°æ•´ç†é é¢ä»¥æŸ¥çœ‹æ–°åŠ å…¥çš„議題。"
msgid "Import issues"
-msgstr ""
+msgstr "匯入議題"
msgid "Import multiple repositories by uploading a manifest file."
-msgstr ""
+msgstr "é€éŽä¸Šå‚³manifest文件匯入多個版本庫"
msgid "Import project"
-msgstr ""
+msgstr "匯入項目"
msgid "Import project from"
-msgstr ""
+msgstr "匯入專案自"
msgid "Import projects from Bitbucket"
-msgstr ""
+msgstr "從Bitbucket匯入項目"
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "從Bitbucket匯入項目"
msgid "Import projects from FogBugz"
-msgstr ""
+msgstr "從FogBugz匯入項目"
msgid "Import projects from GitLab.com"
-msgstr ""
+msgstr "從GitLab.com匯入項目"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "從Bitbucket匯入版本庫"
msgid "Import repositories from GitHub"
-msgstr ""
+msgstr "從 GitHub 匯入版本庫"
msgid "Import repository"
-msgstr ""
+msgstr "匯入版本庫"
msgid "Import requirements"
-msgstr ""
+msgstr "匯入需求"
msgid "Import started by: %{importInitiator}"
-msgstr ""
+msgstr "匯入已由%{importInitiator}啟動"
msgid "Import tasks"
-msgstr ""
+msgstr "匯入作業"
msgid "Import tasks from Phabricator into issues"
-msgstr ""
+msgstr "從Pharbricator匯入作業到議題"
msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
-msgstr ""
+msgstr "åŒ¯å…¥è¶…æ™‚ã€‚è€—æ™‚å·²è¶…éŽ %{import_jobs_expiration} 秒"
msgid "ImportAProjectModal|Import from a project"
-msgstr ""
+msgstr "從一個專案匯入"
msgid "ImportAProjectModal|Import members from another project"
-msgstr ""
+msgstr "從å¦ä¸€å€‹å°ˆæ¡ˆåŒ¯å…¥æˆå“¡"
msgid "ImportAProjectModal|Import project members"
-msgstr ""
+msgstr "匯入專案æˆå“¡"
msgid "ImportAProjectModal|Only project members (not group members) are imported, and they get the same permissions as the project you import from."
-msgstr ""
+msgstr "僅匯入專案æˆå“¡ï¼ˆè€Œéžç¾¤çµ„æˆå“¡ï¼‰ï¼Œä¸¦ä¸”他們ç²å¾—與您從中匯入的專案相åŒçš„權é™ã€‚"
msgid "ImportAProjectModal|Successfully imported"
-msgstr ""
+msgstr "匯入æˆåŠŸ"
msgid "ImportAProjectModal|Unable to import project members"
-msgstr ""
+msgstr "無法匯入專案æˆå“¡"
msgid "ImportAProjectModal|You're importing members to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "您正在邀請æˆå“¡åŠ å…¥ %{strongStart}%{name}%{strongEnd} 群組。"
msgid "ImportButtons|Connect repositories from"
-msgstr ""
+msgstr "用以下方å¼é€£æŽ¥å„²å­˜åº«"
msgid "ImportProjects|%{provider} rate limit exceeded. Try again later"
-msgstr ""
+msgstr "超éŽ%{provider}的速率é™åˆ¶ã€‚è«‹ç¨å¾Œå†è©¦"
msgid "ImportProjects|Blocked import URL: %{message}"
-msgstr ""
+msgstr "ç¦æ­¢çš„匯入URL: %{message}"
msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
-msgstr ""
+msgstr "將版本庫 %{project_safe_import_url} 匯入到 %{project_full_path} 時發生錯誤:%{message}"
msgid "ImportProjects|Import repositories"
-msgstr ""
+msgstr "匯入倉庫"
msgid "ImportProjects|Importing the project failed"
-msgstr ""
+msgstr "匯入專案失敗"
msgid "ImportProjects|Importing the project failed: %{reason}"
-msgstr ""
+msgstr "匯入專案失敗: %{reason}"
msgid "ImportProjects|Requesting namespaces failed"
-msgstr ""
+msgstr "請求命å空間失敗"
msgid "ImportProjects|Requesting your %{provider} repositories failed"
-msgstr ""
+msgstr "å–得您的%{provider}版本庫失敗"
msgid "ImportProjects|Select the repositories you want to import"
-msgstr ""
+msgstr "é¸æ“‡æ‚¨æƒ³è¦åŒ¯å…¥çš„版本庫"
msgid "ImportProjects|The remote data could not be imported."
-msgstr ""
+msgstr "無法匯入é ç«¯è³‡æ–™ã€‚"
msgid "ImportProjects|The repository could not be created."
-msgstr ""
+msgstr "無法建立版本庫。"
msgid "ImportProjects|Update of imported projects with realtime changes failed"
-msgstr ""
+msgstr "匯入項目å³æ™‚更新失敗"
msgid "Imported requirements"
-msgstr ""
+msgstr "匯入的需求"
msgid "Importing %d repository"
msgid_plural "Importing %d repositories"
-msgstr[0] ""
+msgstr[0] "正在匯入%d個版本庫"
msgid "Importing..."
-msgstr ""
+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 ""
+msgstr "在此 URL 上沒有有效的 Git 倉庫。如果您的 HTTP 倉庫ä¸èƒ½å…¬é–‹å­˜å–,請驗證您的憑據。"
msgid "Improve customer support with Service Desk"
-msgstr ""
+msgstr "通éŽæœå‹™å°æ”¹å–„客戶支æ´"
msgid "In a seat"
-msgstr ""
+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 ""
+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 ""
+msgstr "在æ¯å€‹ç¯„例中,將 %{code_start}TOKEN%{code_end} 替æ›ç‚ºæ‚¨ç”Ÿæˆçš„觸發令牌,並將 %{code_start}REF_NAME%{code_end} 替æ›ç‚ºåˆ†æ”¯æˆ–標籤å稱。"
msgid "In progress"
-msgstr ""
+msgstr "進行中"
msgid "In the background, we're attempting to connect you again."
-msgstr ""
+msgstr "我們正在後å°å˜—試å†æ¬¡é€£æŽ¥æ‚¨ã€‚"
msgid "In this page you will find information about the settings that are used in your current instance."
-msgstr ""
+msgstr "在此é é¢ä¸­ï¼Œæ‚¨å°‡æ‰¾åˆ°æœ‰é—œç•¶å‰å¯¦ä¾‹ä¸­ä½¿ç”¨çš„設定的訊æ¯ã€‚"
msgid "In use"
-msgstr ""
+msgstr "使用中"
msgid "InProductMarketing|%{organization_name} logo"
-msgstr ""
+msgstr "%{organization_name} 標誌"
msgid "InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection"
-msgstr ""
+msgstr "%{strong_start}進階應用程å¼å®‰å…¨%{strong_end} — 包括 SASTã€DAST 掃æã€FUZZ 測試ã€ä¾è³´æ€§æŽƒæã€è¨±å¯è­‰åˆè¦æ€§ã€ç§˜å¯†æª¢æ¸¬"
msgid "InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels"
-msgstr ""
+msgstr "%{strong_start}å…¬å¸ç¯„åœå…§çš„組åˆç®¡ç†%{strong_end} — 包括多層級å²è©©ã€ç¯„åœæ¨™ç±¤"
msgid "InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream"
-msgstr ""
+msgstr "%{strong_start}執行級別的見解%{strong_end} — 包括生產力報告ã€ä»»å‹™é¡žåž‹ã€å®Œæˆå¤©æ•¸ã€åƒ¹å€¼æµ"
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|%{strong_start}Overall, how difficult or easy was it to get started with GitLab?%{strong_end}"
-msgstr ""
+msgstr "%{strong_start}多個核准角色%{strong_end} — 包括代碼所有者和所需的åˆä½µæ ¸å‡†"
msgid "InProductMarketing|*GitLab*, noun: a synonym for efficient teams"
-msgstr ""
+msgstr "*GitLab*,å詞:高效團隊的åŒç¾©è©ž"
msgid "InProductMarketing|...and you can get a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "...您å¯ä»¥ç²å¾—旗艦版的å…費試用"
msgid "InProductMarketing|3 ways to dive into GitLab CI/CD"
-msgstr ""
+msgstr "深入瞭解 GitLab CI/CD 的 3 種方法"
msgid "InProductMarketing|A single application eliminates complex integrations, data chokepoints, and toolchain maintenance, resulting in greater productivity and lower cost."
-msgstr ""
+msgstr "單一應用程å¼æ¶ˆé™¤äº†è¤‡é›œçš„æ•´åˆã€è³‡æ–™é›œå‹™å’Œå·¥å…·éˆç¶­è­·ï¼Œä½¿å¾—生產力æ高和æˆæœ¬é™ä½Žã€‚"
msgid "InProductMarketing|Access advanced features, build more efficiently, strengthen security and compliance."
-msgstr ""
+msgstr "å­˜å–進階功能,更有效地構建,加強安全和åˆè¦ã€‚"
msgid "InProductMarketing|Access advanced features."
-msgstr ""
+msgstr "å­˜å–進階功能。"
msgid "InProductMarketing|Actually, GitLab makes the team work (better)"
-msgstr ""
+msgstr "實際上,GitLab 使團隊能夠工作更好"
msgid "InProductMarketing|And finally %{deploy_link} a Python application."
-msgstr ""
+msgstr "最後 %{deploy_link} 一個 Python 應用程å¼ã€‚"
msgid "InProductMarketing|And many more..."
-msgstr ""
+msgstr "還有更多..."
msgid "InProductMarketing|Are your runners ready?"
-msgstr ""
+msgstr "InProductMarketing|您的執行器就緒了嗎?"
msgid "InProductMarketing|Automated security scans directly within GitLab"
-msgstr ""
+msgstr "直接在 GitLab 中自動進行安全掃æ"
msgid "InProductMarketing|Be a DevOps hero"
-msgstr ""
+msgstr "æˆç‚ºDevOps英雄"
msgid "InProductMarketing|Beef up your security"
-msgstr ""
+msgstr "增強您的安全性"
msgid "InProductMarketing|Better code in less time"
-msgstr ""
+msgstr "用更少的時間編寫更好的程å¼ç¢¼"
msgid "InProductMarketing|Blog"
-msgstr ""
+msgstr "部è½æ ¼"
msgid "InProductMarketing|Break down silos to coordinate seamlessly across development, operations, and security with a consistent experience across the development lifecycle."
-msgstr ""
+msgstr "打破孤島,在開發ã€é‹ç‡Ÿå’Œå®‰å…¨ä¹‹é–“無縫å”調,在整個開發生命週期中æ供一致的體驗。"
msgid "InProductMarketing|Building for iOS? We've got you covered."
-msgstr ""
+msgstr "為 iOS 構建? 我們為您æä¾›ä¿éšœ"
msgid "InProductMarketing|Burn up/down charts"
-msgstr ""
+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|Click on the number below that corresponds with your answer — 1 being very difficult, 5 being very easy."
-msgstr ""
+msgstr "通éŽå•Ÿç”¨ä»£ç¢¼æ‰€æœ‰è€…和所需的åˆä½µæ ¸å‡†ï¼Œåˆé©çš„人將審查åˆé©çš„ MR。這是雙è´çš„:更乾淨的代碼和更有效的審查éŽç¨‹ã€‚"
msgid "InProductMarketing|Code owners"
-msgstr ""
+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 ""
+msgstr "程å¼æ‰€æœ‰è€…和所需的åˆä½µæ ¸å‡†æ˜¯ GitLab 付費版的一部分。您å¯ä»¥é–‹å§‹å…費試用 GitLab 旗艦版 30 天,並在 5 分é˜å…§å•Ÿç”¨é€™äº›åŠŸèƒ½ï¼Œç„¡éœ€ä¿¡ç”¨å¡ã€‚"
msgid "InProductMarketing|Code review analytics"
-msgstr ""
+msgstr "程å¼å¯©æ ¸åˆ†æž"
msgid "InProductMarketing|Collaboration across stages in GitLab"
-msgstr ""
+msgstr "GitLab 中跨階段的å”åŒåˆä½œ"
msgid "InProductMarketing|Collaboration made easy"
-msgstr ""
+msgstr "讓å”åŒåˆä½œè®Šå¾—ç°¡å–®"
msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
-msgstr ""
+msgstr "InProductMarketing|åªéœ€é»žæ“Šå¹¾ä¸‹å³å¯å»ºç«‹è‡ªè¨‚ CI 執行器"
msgid "InProductMarketing|Create a custom runner"
-msgstr ""
+msgstr "InProductMarketing|建立自訂執行器"
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
-msgstr ""
+msgstr "5分é˜å…§åœ¨ GitLab 中建立一個專案"
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 ""
+msgstr "通éŽåœ¨è­°é¡Œã€åˆä½µè«‹æ±‚å’Œå²è©©ä¸Šä½¿ç”¨ç¯„åœæ¨™ç±¤ï¼Œå»ºç«‹å®šç¾©æ˜Žç¢ºçš„工作æµã€‚無法將相åŒç¯„åœçš„標籤一起使用,從而防止è¡çªã€‚"
msgid "InProductMarketing|Create your first project!"
-msgstr ""
+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 ""
+msgstr "定義誰æ“有特定文件或目錄,所以當åˆä½µè«‹æ±‚å°é€™äº›æ–‡ä»¶é€²è¡Œæ›´æ”¹æ™‚,建議確定正確的審核者。"
msgid "InProductMarketing|Deliver Better Products Faster"
-msgstr ""
+msgstr "更快地交付更好的產å“"
msgid "InProductMarketing|Dependency scanning"
-msgstr ""
+msgstr "ä¾è³´æŽƒæ"
msgid "InProductMarketing|Did you know teams that use GitLab are far more efficient?"
-msgstr ""
-
-msgid "InProductMarketing|Difficult"
-msgstr ""
+msgstr "您知é“使用 GitLab 的團隊效率更高嗎?"
msgid "InProductMarketing|Dig in and create a project and a repo"
-msgstr ""
+msgstr "深入並建立一個專案和版本庫"
msgid "InProductMarketing|Discover Premium & Ultimate"
-msgstr ""
+msgstr "探索專業版和旗艦版"
msgid "InProductMarketing|Discover Premium & Ultimate."
-msgstr ""
-
-msgid "InProductMarketing|Do you have a minute?"
-msgstr ""
+msgstr "探索專業版和旗艦版。"
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
-msgstr ""
+msgstr "您有一ä½é©åˆæ­¤ä»»å‹™çš„團隊æˆå“¡å—Žï¼Ÿ"
msgid "InProductMarketing|Dynamic application security testing"
-msgstr ""
-
-msgid "InProductMarketing|Easy"
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ¸¬è©¦"
msgid "InProductMarketing|Epics"
-msgstr ""
+msgstr "å²è©©"
msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
-msgstr ""
+msgstr "通éŽå…費的 GitLab 試用擴展您的 DevOps 之旅"
msgid "InProductMarketing|Explore GitLab CI/CD"
-msgstr ""
+msgstr "探索GitLab CI/CD"
msgid "InProductMarketing|Explore the options"
-msgstr ""
+msgstr "探索é¸é …"
msgid "InProductMarketing|Explore the power of GitLab CI/CD"
-msgstr ""
+msgstr "探索 GitLab CI/CD 的力é‡"
msgid "InProductMarketing|Facebook"
-msgstr ""
-
-msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
-msgstr ""
+msgstr "Facebook"
msgid "InProductMarketing|Feel the need for speed?"
-msgstr ""
+msgstr "感覺需è¦é€Ÿåº¦å—Žï¼Ÿ"
msgid "InProductMarketing|Find and fix bottlenecks in your code review process by understanding how long open merge requests have been in review."
-msgstr ""
+msgstr "了解開放的åˆä½µè«‹æ±‚已被審核多長時間,查找和解決您的代碼審查éŽç¨‹ä¸­çš„瓶頸。"
msgid "InProductMarketing|Find out how your teams are really doing"
-msgstr ""
+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 "瞭解您的外部庫是å¦å®‰å…¨ã€‚é‹è¡Œä¾è³´æŽƒæ作業,檢查您外部庫中的已知æ¼æ´žã€‚"
msgid "InProductMarketing|Follow our steps"
-msgstr ""
+msgstr "跟隨我們的步驟"
msgid "InProductMarketing|Free 30-day trial"
-msgstr ""
+msgstr "30 天å…費試用"
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 "用我們的%{quick_start_link}快速開始使用 CI/CD。從一個å¯ç”¨çš„é‹è¡Œå™¨é–‹å§‹ï¼Œç„¶å¾Œå»ºç«‹ä¸€å€‹ CI .yml 文件——這真的很容易。"
msgid "InProductMarketing|Get our import guides"
-msgstr ""
+msgstr "å–得匯入指å—"
msgid "InProductMarketing|Get set up to build for iOS"
-msgstr ""
+msgstr "為iOS構建進行設置"
msgid "InProductMarketing|Get started today"
-msgstr ""
+msgstr "ç«‹å³é–‹å§‹"
msgid "InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required."
-msgstr ""
+msgstr "ç«‹å³é–‹å§‹ç‚ºæœŸ 30 天的 GitLab 旗艦版 試用,無需信用å¡ã€‚"
msgid "InProductMarketing|Get started with GitLab CI/CD"
-msgstr ""
+msgstr "開始使用 GitLab CI/CD"
msgid "InProductMarketing|Get to know GitLab CI/CD"
-msgstr ""
+msgstr "瞭解GitLab CI/CD"
msgid "InProductMarketing|Get your team set up on GitLab"
-msgstr ""
+msgstr "在 GitLab 上建立您的團隊"
msgid "InProductMarketing|Git basics"
-msgstr ""
+msgstr "Git 基礎知識"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
-msgstr ""
+msgstr "GitHub ä¼æ¥­å°ˆæ¡ˆåˆ° 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 èˆ‡åŸºç¤Žè¨­æ–½ç„¡é—œï¼ˆæ”¯æ´ GCPã€AWSã€Azureã€OpenShiftã€VMWareã€On Premã€Bare Metal 等),無論環境如何,都å¯æ供一致的工作æµç¨‹é«”驗。"
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 æä¾›éœæ…‹æ‡‰ç”¨ç¨‹å¼å®‰å…¨æ¸¬è©¦ï¼ˆSAST)ã€å‹•æ…‹æ‡‰ç”¨ç¨‹å¼å®‰å…¨æ¸¬è©¦ï¼ˆDAST)ã€å®¹å™¨æŽƒæå’Œä¾è³´æŽƒæ以幫助您æ供安全的應用程å¼ä»¥åŠéµå®ˆè¨±å¯å”議。"
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 "GitLab çš„ CI/CD 使軟件開發更容易。ä¸ç›¸ä¿¡æˆ‘們?您å¯ä»¥é€šéŽä»¥ä¸‹ä¸‰ç¨®æ–¹å¼é€²è¡Œå¿«é€Ÿï¼ˆä¸”令人滿æ„)的測試驅動:"
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 "專業版是為了使您ã€æ‚¨çš„團隊和您的應用程å¼æ›´æœ‰æ•ˆçŽ‡å’Œæ›´å®‰å…¨è€Œè¨­è¨ˆï¼Œä¸¦ä¸”包括但ä¸é™æ–¼ï¼š"
msgid "InProductMarketing|Give us one minute..."
-msgstr ""
+msgstr "給我們一分é˜..."
msgid "InProductMarketing|Go farther with GitLab"
-msgstr ""
+msgstr "用 GitLab èµ°å¾—æ›´é "
msgid "InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day"
-msgstr ""
+msgstr "Goldman Sachs 從æ¯å…©é€±ä¸€æ¬¡æ§‹å»ºåˆ°æ¯å¤©æ•¸åƒæ¬¡æ§‹å»º"
msgid "InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}."
-msgstr ""
+msgstr "è¦åŒ¯å…¥ä¸åŒçš„實例嗎?這是我們的 %{import_link}。"
msgid "InProductMarketing|Here's what you need to know"
-msgstr ""
+msgstr "這是你需è¦çŸ¥é“çš„"
msgid "InProductMarketing|How (and why) mirroring makes sense"
-msgstr ""
+msgstr "如何(以åŠç‚ºä»€éº¼ï¼‰è®“é¡åƒè®Šçš„有æ„義"
msgid "InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?"
-msgstr ""
+msgstr "關閉功能請求ã€bugã€æŠ€è¡“債務ã€å®‰å…¨æ€§ç­‰é¡žåž‹çš„è­°é¡Œ/MR 需è¦å¤šé•·æ™‚間?"
msgid "InProductMarketing|How many days does it take our team to complete various tasks?"
-msgstr ""
+msgstr "我們的團隊完æˆå„種任務需è¦å¤šå°‘天?"
msgid "InProductMarketing|How to build and test faster"
-msgstr ""
+msgstr "如何更快地構建和測試"
msgid "InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}."
-msgstr ""
+msgstr "如果您ä¸æƒ³ç›´æŽ¥æŽ¥æ”¶æˆ‘們的營銷電å­éƒµä»¶ï¼Œå‰‡ %{marketing_preference_link}."
msgid "InProductMarketing|If you no longer wish to receive marketing emails from us,"
-msgstr ""
+msgstr "如果您ä¸å†å¸Œæœ›æ”¶åˆ°æˆ‘們的營銷電å­éƒµä»¶ï¼Œ"
msgid "InProductMarketing|Import your project and code from GitHub, Bitbucket and others"
-msgstr ""
+msgstr "從 GitHubã€Bitbucket 等匯入您的專案和代碼"
msgid "InProductMarketing|Improve app security with a 30-day trial"
-msgstr ""
+msgstr "é€šéŽ 30 天試用æ高應用安全性"
msgid "InProductMarketing|Improve code quality and streamline reviews"
-msgstr ""
+msgstr "æ高程å¼ç¢¼è³ªé‡ä¸¦ç°¡åŒ–審查"
msgid "InProductMarketing|Increase Operational Efficiencies"
-msgstr ""
+msgstr "æ高é‹ç‡Ÿæ•ˆçŽ‡"
msgid "InProductMarketing|Invite them to help out."
-msgstr ""
+msgstr "邀請他們æ供幫助。"
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
-msgstr ""
+msgstr "邀請您的åŒäº‹ä¸¦é–‹å§‹æ›´å¿«åœ°ç™¼å¸ƒç¨‹å¼ç¢¼ã€‚"
msgid "InProductMarketing|Invite your colleagues to join in less than one minute"
-msgstr ""
+msgstr "ä¸åˆ°ä¸€åˆ†é˜é‚€è«‹æ‚¨çš„åŒäº‹åŠ å…¥"
msgid "InProductMarketing|Invite your colleagues today"
-msgstr ""
+msgstr "ç«‹å³é‚€è«‹æ‚¨çš„åŒäº‹"
msgid "InProductMarketing|Invite your team in less than 60 seconds"
-msgstr ""
+msgstr "60 秒內邀請您的團隊"
msgid "InProductMarketing|Invite your team now"
-msgstr ""
+msgstr "ç«‹å³é‚€è«‹æ‚¨çš„團隊"
msgid "InProductMarketing|Invite your team today to build better code (and processes) together"
-msgstr ""
+msgstr "ç«‹å³é‚€è«‹æ‚¨çš„團隊一起構建更好的代碼(和æµç¨‹ï¼‰"
msgid "InProductMarketing|It's all in the stats"
-msgstr ""
+msgstr "一切盡在統計中"
msgid "InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD."
-msgstr ""
+msgstr "為了利用 GitLab çš„ CI/CD,也å¯ä»¥ç°¡å–®åœ°è¨­å®šç‚º %{external_repo_link}"
msgid "InProductMarketing|Keep your code quality high by defining who should approve merge requests and how many approvals are required."
-msgstr ""
+msgstr "通éŽå®šç¾©èª°æ‡‰è©²æ ¸å‡†åˆä½µè«‹æ±‚以åŠéœ€è¦å¤šå°‘核准來ä¿æŒæ‚¨çš„代碼質é‡ã€‚"
msgid "InProductMarketing|Launch GitLab CI/CD in 20 minutes or less"
-msgstr ""
+msgstr "在 20 分é˜æˆ–更短的時間內啟動 GitLab CI/CD"
msgid "InProductMarketing|Learn how to build for iOS"
-msgstr ""
+msgstr "學習如何為iOS構建"
msgid "InProductMarketing|Lower cost of development"
-msgstr ""
+msgstr "é™ä½Žé–‹ç™¼æˆæœ¬"
msgid "InProductMarketing|Make it easier to collaborate on high-level ideas by grouping related issues in an epic."
-msgstr ""
+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 "進行轉æ›ï¼Ÿå°‡å°ˆæ¡ˆåŒ¯å…¥ GitLab 比您想åƒçš„è¦å®¹æ˜“,移動 %{github_link},或者匯入一些æ±è¥¿ %{bitbucket_link}。"
msgid "InProductMarketing|Master the art of importing!"
-msgstr ""
+msgstr "掌æ¡åŒ¯å…¥çš„è—è¡“ï¼"
msgid "InProductMarketing|Merge request approval rule"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚核准è¦å‰‡"
msgid "InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}"
-msgstr ""
+msgstr "繼續輕鬆建立 Pages 網站 %{ci_template_link}"
msgid "InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"
-msgstr ""
+msgstr "多個所有者,混亂的工作æµï¼Ÿæˆ‘們已為您æä¾›ä¿éšœ"
msgid "InProductMarketing|Multiple required approvers"
-msgstr ""
+msgstr "多個必需的核准人"
msgid "InProductMarketing|Need an alternative to importing?"
-msgstr ""
-
-msgid "InProductMarketing|Neutral"
-msgstr ""
+msgstr "需è¦æ›¿ä»£åŒ¯å…¥çš„方法嗎?"
msgid "InProductMarketing|No credit card required."
-msgstr ""
+msgstr "ä¸éœ€è¦ä¿¡ç”¨å¡ã€‚"
msgid "InProductMarketing|Our tool brings all the things together"
-msgstr ""
+msgstr "我們的工具將所有æ±è¥¿æ•´åˆåœ¨ä¸€èµ·"
msgid "InProductMarketing|Protect your web application by using DAST to examine for vulnerabilities in deployed environments."
-msgstr ""
+msgstr "通éŽä½¿ç”¨ DAST 檢查部署環境中的æ¼æ´žï¼Œä¿è­·æ‚¨çš„ web 應用程å¼ã€‚"
msgid "InProductMarketing|Rapid development, simplified"
-msgstr ""
+msgstr "快速開發,簡化"
msgid "InProductMarketing|Reduce Security & Compliance Risk"
-msgstr ""
+msgstr "é™ä½Žå®‰å…¨èˆ‡åˆè¦é¢¨éšª"
msgid "InProductMarketing|Require multiple approvers on a merge request, so you know it's in good shape before it's merged."
-msgstr ""
+msgstr "在åˆä½µè«‹æ±‚時需è¦å¤šå€‹å¯©æ‰¹ï¼Œæ‰€ä»¥æ‚¨å¯ä»¥çŸ¥é“它處於良好狀態,然後æ‰èƒ½åˆä½µã€‚"
msgid "InProductMarketing|Roadmaps"
-msgstr ""
+msgstr "路線圖"
msgid "InProductMarketing|Scoped labels"
-msgstr ""
+msgstr "範åœæ¨™è¨˜"
msgid "InProductMarketing|Security that's integrated into your development lifecycle"
-msgstr ""
+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 "有時您還沒有準備好完全éŽæ¸¡åˆ°æ–°å·¥å…·ã€‚如果您還沒有準備好完全æ交, %{mirroring_link} 為您æ供了一種與當å‰å·¥å…·ä¸¦è¡Œè©¦ç”¨ GitLab 的安全方法。"
msgid "InProductMarketing|Speed. Efficiency. Trust."
-msgstr ""
+msgstr "快速,高效,值得信任。"
msgid "InProductMarketing|Spin up an autoscaling runner in GitLab"
-msgstr ""
+msgstr "InProductMarketing|在 GitLab 中啟動自動縮放執行器"
msgid "InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required."
-msgstr ""
+msgstr "ç«‹å³åœ¨ä¸åˆ°ä¸€åˆ†é˜çš„時間內開始 GitLab Ultimate 試用,無需信用å¡ã€‚"
msgid "InProductMarketing|Start a Self-Managed trial"
-msgstr ""
+msgstr "開始試用"
msgid "InProductMarketing|Start a free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "InProductMarketing|Start a free trial of GitLab Ultimate – no credit card required"
-msgstr ""
+msgstr "開始å…費試用旗艦版 - 無需信用å¡"
msgid "InProductMarketing|Start a trial"
-msgstr ""
+msgstr "開始試用"
msgid "InProductMarketing|Start by %{performance_link}"
-msgstr ""
+msgstr "從%{performance_link}開始"
msgid "InProductMarketing|Start by importing your projects"
-msgstr ""
+msgstr "從匯入您的專案開始"
msgid "InProductMarketing|Start with a GitLab Ultimate free trial"
-msgstr ""
+msgstr "開始å…費試用 GitLab Ultimate"
msgid "InProductMarketing|Start your trial now!"
-msgstr ""
+msgstr "ç¾åœ¨å°±é–‹å§‹è©¦ç”¨ï¼"
msgid "InProductMarketing|Start your trial today to experience single application success and discover all the features of GitLab Ultimate for free!"
-msgstr ""
+msgstr "å³åˆ»é–‹å§‹è©¦ç”¨ï¼Œé«”驗單個應用的æˆåŠŸï¼Œä¸¦å…費發ç¾GitLab Ultimate的所有功能。"
msgid "InProductMarketing|Stop wondering and use GitLab to answer questions like:"
-msgstr ""
+msgstr "åœæ­¢ç–‘惑,使用GitLab回答以下å•é¡Œï¼š"
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 this 1-question survey!"
-msgstr ""
+msgstr "簡化代碼審核,一目瞭然地知é“誰ä¸å¯ç”¨ï¼Œåœ¨è©•è«–或電å­éƒµä»¶ä¸­æºé€šï¼Œä¸¦èˆ‡Slackæ•´åˆï¼Œè®“æ¯å€‹äººéƒ½åœ¨åŒä¸€é é¢ä¸Šã€‚"
msgid "InProductMarketing|Take your first steps with GitLab"
-msgstr ""
+msgstr "使用GitLab的第一步"
msgid "InProductMarketing|Take your source code management to the next level"
-msgstr ""
+msgstr "讓您的æºä»£ç¢¼ç®¡ç†æ›´ä¸Šä¸€å±¤æ¨“"
msgid "InProductMarketing|Team members collaborating"
-msgstr ""
+msgstr "團隊æˆå“¡åˆä½œ"
msgid "InProductMarketing|Team up in GitLab for greater efficiency"
-msgstr ""
+msgstr "在 GitLab 中組隊以æ高效率"
msgid "InProductMarketing|Team work makes the dream work"
-msgstr ""
+msgstr "團隊åˆä½œæˆå°±å¤¢æƒ³"
msgid "InProductMarketing|Test, create, deploy"
-msgstr ""
+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 "這就是開始使用 GitLab 所需的全部內容,但是如果您ä¸ç†Ÿæ‚‰ Git,請查看我們的 %{basics_link} 以å–得有用的入門æ示和技巧。"
msgid "InProductMarketing|This is email %{current_series} of %{total_series} in the %{track} series."
-msgstr ""
+msgstr "這是 %{track} 系列中的第 %{current_series} å°é›»å­éƒµä»¶ï¼Œå…± %{total_series} å°"
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 "這是 %{track} 系列中的第 %{current_series} å°é›»å­éƒµä»¶ï¼Œå…± %{total_series} å°ã€‚è¦ç¦ç”¨æœ¬åœ° GitLab 實例發é€çš„通知電å­éƒµä»¶ï¼Œè«‹è¯ç¹«æ‚¨çš„管ç†å“¡æˆ– %{unsubscribe_link}。"
msgid "InProductMarketing|Ticketmaster decreased their CI build time by 15X"
-msgstr ""
+msgstr "Ticketmaster å°‡ CI 構建時間縮短了 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 ""
+msgstr "厭倦了與ä¸åŒçš„工具éˆã€è¨Šæ¯å­¤å³¶å’Œä½Žæ•ˆæµç¨‹çš„æ鬥? GitLab çš„ CI/CD 建立在 DevOps å¹³å°ä¸Šï¼Œå…·æœ‰æºä»£ç¢¼ç®¡ç†ã€è¦åŠƒã€ç›£æŽ§ç­‰åŠŸèƒ½ã€‚åƒé–± %{ci_link}。"
msgid "InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}."
-msgstr ""
+msgstr "é¸æ“‡é€€å‡ºOnboarding郵件,%{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 "è¦çž­è§£ä¸¦å……分利用GitLab,請從頭開始,從%{project_link}開始。在GitLab中,版本庫是專案的一部分,所以在您建立了您的專案之後,您å¯ä»¥ç¹¼çºŒåŸ·è¡Œ%{repo_link}。"
msgid "InProductMarketing|Track completed issues in a chart, so you can see how a milestone is progressing at a glance."
-msgstr ""
+msgstr "通éŽåœ¨åœ–表中追蹤已完æˆçš„議題,一目瞭然地觀望里程碑的進展。"
msgid "InProductMarketing|Try GitLab Ultimate for free"
-msgstr ""
+msgstr "å…費試用 GitLab 旗艦版"
msgid "InProductMarketing|Try it out"
-msgstr ""
+msgstr "嘗試一下"
msgid "InProductMarketing|Try it yourself"
-msgstr ""
+msgstr "親自嘗試一下"
msgid "InProductMarketing|Turn coworkers into collaborators"
-msgstr ""
+msgstr "å°‡åŒäº‹è®Šæˆåˆä½œè€…"
msgid "InProductMarketing|Twitter"
-msgstr ""
+msgstr "Twitter"
msgid "InProductMarketing|Understand repository mirroring"
-msgstr ""
+msgstr "瞭解版本庫é¡åƒ"
msgid "InProductMarketing|Understand your project options"
-msgstr ""
+msgstr "瞭解您的專案é¸é …"
msgid "InProductMarketing|Use GitLab CI/CD"
-msgstr ""
+msgstr "使用 GitLab CI/CD"
msgid "InProductMarketing|Use our AWS cloudformation template to spin up your runners in just a few clicks!"
-msgstr ""
+msgstr "InProductMarketing|使用我們的 AWS cloudformation 範本,åªéœ€é»žæ“Šå¹¾ä¸‹å³å¯å•Ÿå‹•æ‚¨çš„執行器ï¼"
msgid "InProductMarketing|Used by more than 100,000 organizations from around the globe:"
-msgstr ""
-
-msgid "InProductMarketing|Very difficult"
-msgstr ""
-
-msgid "InProductMarketing|Very easy"
-msgstr ""
+msgstr "å…¨çƒè¶…éŽ10è¬å€‹çµ„織使用:"
msgid "InProductMarketing|Visualize your epics and milestones in a timeline."
-msgstr ""
+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 "想è¦å•Ÿå‹•ä¸¦é‹è¡Œæ‚¨çš„ iOS 應用程åºï¼ŒåŒ…括一直發布到 TestFlight? 按照我們的指å—設置 GitLab å’Œ fastlane 以將 iOS 應用程å¼ç™¼å¸ƒåˆ° App Store。"
msgid "InProductMarketing|Want to host GitLab on your servers?"
-msgstr ""
+msgstr "想在您的æœå‹™å™¨ä¸Šè¨—管 GitLab?"
msgid "InProductMarketing|Watch iOS building in action."
-msgstr ""
+msgstr "觀看é‹è¡Œä¸­çš„ iOS 構建。"
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|We want your GitLab experience to be great"
-msgstr ""
+msgstr "我們知é“一些關於效率的事情,我們想分享給大家。註冊GitLab Ultimateçš„å…費試用版,您的團隊將從第一天開始使用它。"
msgid "InProductMarketing|What does our value stream timeline look like from product to development to review and production?"
-msgstr ""
+msgstr "從產å“到開發,å†åˆ°å¯©æŸ¥å’Œç”Ÿç”¢ï¼Œæˆ‘們的價值æµæ™‚間表是什麼樣的?"
msgid "InProductMarketing|When your team is on GitLab these answers are a click away."
-msgstr ""
+msgstr "當您的團隊在 GitLab 上時,åªéœ€å–®æ“Šä¸€ä¸‹å³å¯ç²å¾—這些答案。"
msgid "InProductMarketing|Working in GitLab = more efficient"
-msgstr ""
+msgstr "在 GitLab 中工作 = 更高效"
msgid "InProductMarketing|YouTube"
-msgstr ""
+msgstr "YouTube"
msgid "InProductMarketing|Your software, deployed your way"
-msgstr ""
+msgstr "ä¾æ‚¨çš„想法,部署您的軟件"
msgid "InProductMarketing|Your teams can be more efficient"
-msgstr ""
+msgstr "您的團隊å¯ä»¥æ›´å…·æ•ˆçŽ‡"
msgid "InProductMarketing|comprehensive guide"
-msgstr ""
+msgstr "綜åˆå°Žå¼•"
msgid "InProductMarketing|connect an external repository"
-msgstr ""
+msgstr "連接外部版本庫"
msgid "InProductMarketing|create a project"
-msgstr ""
+msgstr "建立一個專案"
msgid "InProductMarketing|from Bitbucket"
-msgstr ""
+msgstr "從 Bitbucket"
msgid "InProductMarketing|go to about.gitlab.com"
-msgstr ""
+msgstr "å‰å¾€about.gitlab.cn"
msgid "InProductMarketing|how easy it is to get started"
-msgstr ""
+msgstr "如何輕鬆地開始"
msgid "InProductMarketing|quick start guide"
-msgstr ""
+msgstr "快速開始指引"
msgid "InProductMarketing|repository mirroring"
-msgstr ""
+msgstr "版本庫é¡åƒ"
msgid "InProductMarketing|set up a repo"
-msgstr ""
+msgstr "設定 repo"
msgid "InProductMarketing|test and deploy"
-msgstr ""
+msgstr "測試和部署"
msgid "InProductMarketing|testing browser performance"
-msgstr ""
+msgstr "測試ç€è¦½å™¨æ€§èƒ½ã€‚"
msgid "InProductMarketing|unsubscribe"
-msgstr ""
+msgstr "å–消訂閱"
msgid "InProductMarketing|update your preferences"
-msgstr ""
+msgstr "更新您的å好設定"
msgid "InProductMarketing|using a CI/CD template"
-msgstr ""
+msgstr "使用 CI/CD 範本"
msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
-msgstr ""
+msgstr "您å¯ä»¥éš¨æ™‚%{unsubscribe_link}。"
msgid "Inactive"
-msgstr ""
+msgstr "未啟用"
msgid "Incident"
-msgstr ""
+msgstr "事件"
msgid "Incident Management Limits"
-msgstr ""
+msgstr "事件管ç†é™åˆ¶"
msgid "Incident details"
-msgstr ""
+msgstr "事件詳情"
msgid "Incident template (optional)."
-msgstr ""
+msgstr "事件範本(å¯é¸ï¼‰ã€‚"
msgid "IncidentManagement|%{hours} hours, %{minutes} minutes remaining"
-msgstr ""
+msgstr "剩餘%{hours}å°æ™‚%{minutes} 分é˜"
msgid "IncidentManagement|%{minutes} minutes remaining"
-msgstr ""
+msgstr "剩餘%{minutes}分é˜"
msgid "IncidentManagement|Achieved SLA"
-msgstr ""
+msgstr "å·²å¯¦ç¾ SLA"
msgid "IncidentManagement|Acknowledged"
-msgstr ""
+msgstr "已確èª"
msgid "IncidentManagement|All"
-msgstr ""
+msgstr "全部"
msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
-msgstr ""
+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 ""
+msgstr "æå‡åˆ°äº‹ä»¶çš„所有警報都自動顯示在列表中,您也å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„按鈕建立一個新事件。"
msgid "IncidentManagement|An error occurred while fetching the incident status. Please reload the page."
-msgstr ""
+msgstr "å–得事件狀態時發生錯誤。請é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "IncidentManagement|An error occurred while updating the incident status. Please reload the page and try again."
-msgstr ""
+msgstr "更新事件狀態時發生錯誤。請é‡æ–°æ•´ç†é é¢ï¼Œç„¶å¾Œå†è©¦ä¸€æ¬¡ã€‚"
msgid "IncidentManagement|Assign paging status"
-msgstr ""
+msgstr "分é…分é ç‹€æ…‹"
msgid "IncidentManagement|Assignees"
-msgstr ""
+msgstr "指派人"
msgid "IncidentManagement|Closed"
-msgstr ""
+msgstr "已關閉"
msgid "IncidentManagement|Create incident"
-msgstr ""
+msgstr "建立事件"
msgid "IncidentManagement|Critical - S1"
-msgstr ""
+msgstr "åš´é‡ - S1"
msgid "IncidentManagement|Date created"
-msgstr ""
+msgstr "建立日期"
msgid "IncidentManagement|Display your incidents in a dedicated view"
-msgstr ""
+msgstr "在專用視圖中顯示您的事件"
msgid "IncidentManagement|High - S2"
-msgstr ""
+msgstr "高 - S2"
msgid "IncidentManagement|Incident"
-msgstr ""
+msgstr "事件"
msgid "IncidentManagement|Incidents"
-msgstr ""
+msgstr "事件"
msgid "IncidentManagement|Learn more about incident statuses"
-msgstr ""
+msgstr "了解有關事件狀態的更多信æ¯"
msgid "IncidentManagement|Low - S4"
-msgstr ""
+msgstr "低 - S4"
msgid "IncidentManagement|Medium - S3"
-msgstr ""
+msgstr "中 - S3"
msgid "IncidentManagement|Missed SLA"
-msgstr ""
+msgstr "已錯éŽçš„SLA"
msgid "IncidentManagement|No incidents to display."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„事件。"
msgid "IncidentManagement|None"
-msgstr ""
+msgstr "ç„¡"
msgid "IncidentManagement|Open"
-msgstr ""
+msgstr "打開"
msgid "IncidentManagement|Page your team with escalation policies"
-msgstr ""
+msgstr "通知您的團隊使用å‡ç´šç­–ç•¥"
msgid "IncidentManagement|Paged"
-msgstr ""
+msgstr "已通知"
msgid "IncidentManagement|Published"
-msgstr ""
+msgstr "已發布"
msgid "IncidentManagement|Published to status page"
-msgstr ""
+msgstr "發布到狀態é "
msgid "IncidentManagement|Resolved"
-msgstr ""
+msgstr "已解決"
msgid "IncidentManagement|Setting the status to Acknowledged or Resolved stops paging when escalation policies are selected for the incident."
-msgstr ""
+msgstr "當為事件é¸æ“‡å‡ç´šç­–略時,設定狀態為已確èªæˆ–已解決時åœæ­¢é€šçŸ¥ã€‚"
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "åš´é‡æ€§"
msgid "IncidentManagement|Status"
-msgstr ""
+msgstr "狀態"
msgid "IncidentManagement|There are no closed incidents"
-msgstr ""
+msgstr "沒有已關閉的事件"
msgid "IncidentManagement|There was an error displaying the incidents."
-msgstr ""
+msgstr "顯示事件時發生錯誤。"
msgid "IncidentManagement|Time to SLA"
-msgstr ""
+msgstr "è·SLA時間"
msgid "IncidentManagement|Triggered"
-msgstr ""
+msgstr "已觸發"
msgid "IncidentManagement|Unassigned"
-msgstr ""
+msgstr "å–消指派"
msgid "IncidentManagement|Unknown"
-msgstr ""
+msgstr "未知"
msgid "IncidentManagement|Unpublished"
-msgstr ""
+msgstr "未發布"
msgid "IncidentManagement|Use escalation policies to automatically page your team when incidents are created."
-msgstr ""
+msgstr "事件建立時,使用å‡ç´šç­–略自動為您的團隊建立é é¢ã€‚"
msgid "IncidentSettings|Activate \"time to SLA\" countdown timer"
-msgstr ""
+msgstr "啟動 \"SLA時間 \"倒數計時器。"
msgid "IncidentSettings|Fine-tune incident settings and set up integrations with external tools to help better manage incidents."
-msgstr ""
+msgstr "微調事件設定並設定與外部工具的整åˆï¼Œä»¥å¹«åŠ©æ›´å¥½åœ°ç®¡ç†äº‹ä»¶ã€‚"
msgid "IncidentSettings|Grafana integration"
-msgstr ""
+msgstr "Grafanaæ•´åˆ"
msgid "IncidentSettings|Incident settings"
-msgstr ""
+msgstr "事件設定"
msgid "IncidentSettings|Incidents"
-msgstr ""
+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 ""
+msgstr "在事件議題中引入倒計時,以便更好地追蹤æœå‹™ç´šåˆ¥å”議(SLA)。計時器在建立事件時自動啟動,並設定解決事件的時間é™åˆ¶ã€‚激活時,所有新事件都會顯示SLA倒計時時間。"
msgid "IncidentSettings|PagerDuty integration"
-msgstr ""
+msgstr "PagerDutyæ•´åˆ"
msgid "IncidentSettings|Time limit"
-msgstr ""
+msgstr "時間é™åˆ¶"
msgid "IncidentSettings|Time limit must be a multiple of 15 minutes."
-msgstr ""
+msgstr "時間é™åˆ¶å¿…須是15分é˜çš„å€æ•¸ã€‚"
msgid "IncidentSettings|Time limit must be a valid number."
-msgstr ""
+msgstr "時間é™åˆ¶å¿…須是有效的數字。"
msgid "IncidentSettings|Time limit must be greater than 0."
-msgstr ""
+msgstr "時間é™åˆ¶å¿…須大於 0。"
msgid "IncidentSettings|When activated, this applies to all new incidents in the project."
-msgstr ""
+msgstr "當啟用後,這é©ç”¨æ–¼å°ˆæ¡ˆä¸­çš„所有新事件。"
msgid "IncidentSettings|hours"
-msgstr ""
+msgstr "å°æ™‚"
msgid "IncidentSettings|minutes"
-msgstr ""
+msgstr "分é˜"
msgid "Incidents"
-msgstr ""
+msgstr "事故"
msgid "Incidents|Add image details"
-msgstr ""
+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 "加入文本或éˆæŽ¥ä¾†å±•ç¤ºæ‚¨çš„映åƒã€‚如果您沒有加入,文件å將會顯示。"
msgid "Incidents|Drop or %{linkStart}upload%{linkEnd} a metric screenshot to attach it to the incident"
-msgstr ""
+msgstr "放置或%{linkStart}上傳%{linkEnd}指標截圖,將其附加到事件中。"
msgid "Incidents|Must start with http or https"
-msgstr ""
+msgstr "必須以http或https開頭"
msgid "Incident|Add new timeline event"
-msgstr ""
+msgstr "加入時間線事件"
msgid "Incident|Alert details"
-msgstr ""
+msgstr "警報詳情"
msgid "Incident|Are you sure you want to delete this event?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤é€™å€‹äº‹ä»¶ï¼Ÿ"
msgid "Incident|Are you sure you wish to delete this image?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤æ˜ åƒå—Žï¼Ÿ"
msgid "Incident|Delete event"
-msgstr ""
+msgstr "刪除事件"
msgid "Incident|Delete image"
-msgstr ""
+msgstr "刪除映åƒ"
msgid "Incident|Deleting %{filename}"
-msgstr ""
+msgstr "刪除%{filename}"
msgid "Incident|Edit image text or link"
-msgstr ""
+msgstr "編輯映åƒæ–‡æœ¬æˆ–éˆæŽ¥"
msgid "Incident|Editing %{filename}"
-msgstr ""
+msgstr "正在編輯 %{filename}"
msgid "Incident|Error creating incident timeline event: %{error}"
-msgstr ""
+msgstr "建立事故時間線事件發生錯誤:%{error}"
msgid "Incident|Error deleting incident timeline event: %{error}"
-msgstr ""
+msgstr "刪除事故時間線事件發生錯誤:%{error}"
msgid "Incident|Metrics"
-msgstr ""
+msgstr "指標"
msgid "Incident|No timeline items have been added yet."
-msgstr ""
+msgstr "尚未加入任何時間線事項。"
msgid "Incident|Save and add another event"
-msgstr ""
+msgstr "儲存並新增其他事件"
msgid "Incident|Something went wrong while creating the incident timeline event."
-msgstr ""
+msgstr "建立事故時間線事件時發生錯誤。"
msgid "Incident|Something went wrong while deleting the incident timeline event."
-msgstr ""
+msgstr "刪除事故時間線事件時發生錯誤。"
msgid "Incident|Something went wrong while fetching incident timeline events."
-msgstr ""
+msgstr "æå–事故時間線事件時發生錯誤。"
msgid "Incident|Summary"
-msgstr ""
+msgstr "摘è¦"
msgid "Incident|There was an issue loading alert data. Please try again."
-msgstr ""
+msgstr "載入警報資料時出ç¾å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Incident|There was an issue loading incident data. Please try again."
-msgstr ""
+msgstr "載入事件資料時出ç¾å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Incident|Timeline"
-msgstr ""
+msgstr "時間線"
msgid "Incident|Timeline text"
-msgstr ""
+msgstr "時間線文字"
msgid "Incident|Timeline text..."
-msgstr ""
+msgstr "時間線文字..."
msgid "Include author name in notification email body"
-msgstr ""
+msgstr "在通知電å­éƒµä»¶æ­£æ–‡ä¸­åŒ…å«ä½œè€…姓å"
msgid "Include description in commit message"
-msgstr ""
+msgstr "在æ交消æ¯ä¸­åŒ…å«æè¿°"
msgid "Include new features from all tiers."
-msgstr ""
+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 ""
+msgstr "在郵件正文中包括議題ã€åˆä½µè«‹æ±‚或評論的作者å稱。é è¨­æƒ…æ³ä¸‹ï¼ŒGitLab會覆蓋電å­éƒµä»¶ç™¼ä»¶äººçš„å字。有些電å­éƒµä»¶æœå‹™å™¨ä¸æ”¯æ´é€™å€‹é¸é …。"
msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
-msgstr ""
+msgstr "如果需è¦ï¼Œè«‹åœ¨URL中包å«ä½¿ç”¨è€…å:%{code_open}https://username@gitlab.company.com/group/project.git%{code_close}。"
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
-msgstr ""
+msgstr "åŒ…å« LFS 物件。它å¯ä»¥æŒ‰ç¾¤çµ„或項目覆蓋。0 表示無é™åˆ¶ã€‚"
msgid "Includes an MVC structure to help you get started"
-msgstr ""
+msgstr "åŒ…å« MVC çµæ§‹ä»¥å¹«åŠ©æ‚¨å…¥é–€"
msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started"
-msgstr ""
+msgstr "包括 MVC çµæ§‹ã€Gemfileã€Rakefile 以åŠè¨±å¤šå…¶ä»–çµæ§‹ï¼Œä»¥å¹«åŠ©æ‚¨å…¥é–€"
msgid "Includes an MVC structure, mvnw and pom.xml to help you get started"
-msgstr ""
+msgstr "åŒ…å« MVC çµæ§‹ã€mvnw å’Œ pom.xml 以幫助您入門"
msgid "Incoming email"
-msgstr ""
+msgstr "傳入電å­éƒµä»¶"
msgid "Incoming!"
-msgstr ""
+msgstr "傳入ï¼"
msgid "Incompatible options set!"
-msgstr ""
+msgstr "設定了ä¸ç›¸å®¹çš„é¸é …ï¼"
msgid "Incompatible project"
-msgstr ""
+msgstr "ä¸ç›¸å®¹çš„專案"
msgid "Incomplete"
-msgstr ""
+msgstr "未完æˆ"
msgid "Increase"
-msgstr ""
+msgstr "增加"
msgid "Index"
-msgstr ""
+msgstr "索引"
msgid "Index all projects"
-msgstr ""
+msgstr "索引所有專案"
msgid "Index deletion is canceled"
-msgstr ""
+msgstr "索引刪除已å–消"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "指示此runner是å¦å¯ä»¥é¸æ“‡ç„¡æ¨™è¨˜çš„作業"
msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
-msgstr ""
+msgstr "通知使用者沒有上傳 SSH 金鑰,如果沒有 SSH 金鑰,將無法é€éŽ SSH 推é€ã€‚"
msgid "Infrastructure"
-msgstr ""
+msgstr "基礎設施"
msgid "Infrastructure Registry"
-msgstr ""
+msgstr "基礎設施註冊庫"
msgid "Infrastructure as Code (IaC) Scanning"
-msgstr ""
+msgstr "基礎設施å³ç¨‹å¼ç¢¼ (IaC) 掃æ"
msgid "InfrastructureRegistry|Copy Terraform Command"
-msgstr ""
+msgstr "複製 Terraform 指令"
msgid "InfrastructureRegistry|Copy Terraform Setup Command"
-msgstr ""
+msgstr "複製 Terraform 設定指令"
msgid "InfrastructureRegistry|Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
-msgstr ""
+msgstr "複製並貼上到您的 Terraform 設定中,æ’入變數,然後執行 Terraform init:"
msgid "InfrastructureRegistry|For more information on the Terraform registry, %{linkStart}see our documentation%{linkEnd}."
-msgstr ""
+msgstr "有關Terraform註冊庫的訊æ¯ï¼Œ%{linkStart}åƒè¦‹æˆ‘們的文件%{linkEnd}。"
msgid "InfrastructureRegistry|Infrastructure Registry"
-msgstr ""
+msgstr "基礎設施註冊庫"
msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "發布和共享您的模組。 %{docLinkStart}更多訊æ¯%{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 "Terraform 模組是使用 Terraform 打包和é‡ç”¨è³‡æºé…置的主è¦æ–¹å¼ã€‚瞭解有關如何在 GitLab 中 %{noPackagesLinkStart}建立 Terraform 模塊%{noPackagesLinkEnd}。"
msgid "InfrastructureRegistry|To authorize access to the Terraform registry:"
-msgstr ""
+msgstr "è¦æŽˆæ¬Šå­˜å–Terraform庫:"
msgid "InfrastructureRegistry|You have no Terraform modules in your project"
-msgstr ""
+msgstr "您的專案中沒有 Terraform 模組"
msgid "Inherited"
-msgstr ""
+msgstr "已繼承"
msgid "Inherited:"
-msgstr ""
+msgstr "繼承:"
msgid "Initial default branch name"
-msgstr ""
+msgstr "åˆå§‹é è¨­åˆ†æ”¯å稱"
msgid "Initial default branch protection"
-msgstr ""
+msgstr "åˆå§‹é è¨­åˆ†æ”¯ä¿è­·"
msgid "Inline"
-msgstr ""
+msgstr "å…§è¯"
msgid "Inline math"
-msgstr ""
+msgstr "å…§è¯æ•¸å­¸"
msgid "Input host keys manually"
-msgstr ""
+msgstr "手動輸入主機金鑰"
msgid "Input the remote repository URL"
-msgstr ""
+msgstr "輸入é ç«¯ç‰ˆæœ¬åº«URL"
msgid "Insert"
-msgstr ""
+msgstr "æ’å…¥"
msgid "Insert a %{rows}x%{cols} table."
-msgstr ""
+msgstr "æ’å…¥ %{rows}x%{cols} 的表格。"
msgid "Insert a quote"
-msgstr ""
+msgstr "æ’入引用"
msgid "Insert code"
-msgstr ""
+msgstr "æ’入程å¼ç¢¼"
msgid "Insert column after"
-msgstr ""
+msgstr "å‘後æ’入列"
msgid "Insert column before"
-msgstr ""
+msgstr "å‘å‰æ’入列"
msgid "Insert image"
-msgstr ""
+msgstr "æ’入圖片"
msgid "Insert link"
-msgstr ""
+msgstr "æ’å…¥éˆæŽ¥"
msgid "Insert row after"
-msgstr ""
+msgstr "下方æ’入行"
msgid "Insert row before"
-msgstr ""
+msgstr "上方æ’入行"
msgid "Insert suggestion"
-msgstr ""
+msgstr "æ’入建議"
msgid "Insights"
-msgstr ""
+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 "有些æ¢ç›®ä¸å¯è¦‹ï¼Œç”±æ–¼å·²åœ¨insights.yml文件中éŽæ¿¾æŽ‰(見projects.onlyé…置以瞭解更多訊æ¯)。"
msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
-msgstr ""
+msgstr "此專案已在insights.yml文件中éŽæ¿¾æŽ‰(見projects.onlyé…置以瞭解更多訊æ¯)。"
msgid "Install GitLab Runner and ensure it's running."
-msgstr ""
+msgstr "å®‰è£ GitLab 執行器並確ä¿å®ƒæ­£åœ¨é‹è¡Œã€‚"
msgid "Install on clusters"
-msgstr ""
+msgstr "在å¢é›†ä¸Šå®‰è£"
msgid "Installation"
-msgstr ""
+msgstr "安è£"
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
+msgstr[0] "實體"
msgid "Instance Configuration"
-msgstr ""
+msgstr "實體設定"
msgid "Instance access request"
-msgstr ""
+msgstr "實體存å–請求"
msgid "Instance access request approved"
-msgstr ""
+msgstr "實體存å–請求已核准"
msgid "Instance access request rejected"
-msgstr ""
+msgstr "實體存å–請求被拒絕"
msgid "Instance administrators group already exists"
-msgstr ""
+msgstr "實體管ç†å“¡çµ„已存在"
msgid "Instance audit events"
-msgstr ""
+msgstr "實體審計事件"
msgid "Instance overview"
-msgstr ""
+msgstr "實體概覽"
msgid "Insufficient permissions"
-msgstr ""
+msgstr "權é™ä¸è¶³"
msgid "Insufficient permissions for dast_configuration keyword"
-msgstr ""
+msgstr "dast_configuration é—œéµå­—權é™ä¸è¶³"
msgid "Integration"
-msgstr ""
+msgstr "æ•´åˆ"
msgid "Integration Settings"
-msgstr ""
+msgstr "æ•´åˆè¨­å®š"
msgid "IntegrationEvents|A comment is added on a confidential issue"
-msgstr ""
+msgstr "å°æ©Ÿå¯†è­°é¡Œæ–°å¢žç•™è¨€"
msgid "IntegrationEvents|A comment is added on an issue"
-msgstr ""
+msgstr "å°è­°é¡Œå¢žåŠ ç•™è¨€"
msgid "IntegrationEvents|A confidential issue is created, updated, or closed"
-msgstr ""
+msgstr "建立ã€æ›´æ–°æˆ–關閉機密議題"
msgid "IntegrationEvents|A merge request is created, updated, or merged"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已建立ã€æ›´æ–°æˆ–åˆä½µ"
msgid "IntegrationEvents|A pipeline status changes"
-msgstr ""
+msgstr "æµæ°´ç·šç‹€æ…‹è®Šæ›´"
msgid "IntegrationEvents|A push is made to the repository"
-msgstr ""
+msgstr "推é€åˆ°ç‰ˆæœ¬åº«"
msgid "IntegrationEvents|A tag is pushed to the repository"
-msgstr ""
+msgstr "標籤已推é€åˆ°ç‰ˆæœ¬åº«"
msgid "IntegrationEvents|A wiki page is created or updated"
-msgstr ""
+msgstr "wiki é é¢å·²å»ºç«‹æˆ–æ›´æ–° "
msgid "IntegrationEvents|An issue is created, updated, or closed"
-msgstr ""
+msgstr "議題已建立ã€æ›´æ–°æˆ–關閉"
msgid "Integrations"
-msgstr ""
+msgstr "æ•´åˆ"
msgid "Integrations|%{integrationTitle}: active"
-msgstr ""
+msgstr "%{integrationTitle}:啟用"
msgid "Integrations|%{integration} settings saved and active."
-msgstr ""
+msgstr "%{integration}設定已ä¿å­˜ä¸¦å•Ÿç”¨ã€‚"
msgid "Integrations|%{integration} settings saved, but not active."
-msgstr ""
+msgstr "%{integration}設定已ä¿å­˜ä½†æœªå•Ÿç”¨ã€‚"
msgid "Integrations|Active integrations"
-msgstr ""
+msgstr "啟用整åˆ"
msgid "Integrations|Add an integration"
-msgstr ""
+msgstr "加入整åˆ"
msgid "Integrations|Add namespace"
-msgstr ""
+msgstr "加入命å空間"
msgid "Integrations|All details"
-msgstr ""
+msgstr "所有詳細訊æ¯"
msgid "Integrations|All projects inheriting these settings will also be reset."
-msgstr ""
+msgstr "繼承這些設定的所有專案也將被é‡ç½®ã€‚"
msgid "Integrations|An error occurred while loading projects using custom settings."
-msgstr ""
+msgstr "使用自訂設定載入專案時發生錯誤。"
msgid "Integrations|An event will be triggered when one of the following items happen."
-msgstr ""
+msgstr "當下列情æ³ç™¼ç”Ÿæ™‚,將會觸發該事件。"
msgid "Integrations|Branches for which notifications are to be sent"
-msgstr ""
+msgstr "è¦ç™¼é€é€šçŸ¥çš„分支"
msgid "Integrations|Clear if using a self-signed certificate."
-msgstr ""
+msgstr "如果使用自簽å憑證,請清除"
msgid "Integrations|Comment detail:"
-msgstr ""
+msgstr "留言詳情:"
msgid "Integrations|Comment settings:"
-msgstr ""
+msgstr "留言設定:"
msgid "Integrations|Configure the scope of notifications."
-msgstr ""
+msgstr "設定通知的範åœã€‚"
msgid "Integrations|Connection details"
-msgstr ""
+msgstr "連接情æ³"
msgid "Integrations|Connection failed. Check your integration settings."
-msgstr ""
+msgstr "連接失敗。請檢查您的整åˆè¨­å®šã€‚"
msgid "Integrations|Connection successful."
-msgstr ""
+msgstr "連接æˆåŠŸã€‚"
msgid "Integrations|Create new issue in Jira"
-msgstr ""
+msgstr "在Jira中建立新議題"
msgid "Integrations|Create new issue in ZenTao"
-msgstr ""
+msgstr "在禪é“中建立新議題"
msgid "Integrations|Default settings are inherited from the group level."
-msgstr ""
+msgstr "é è¨­è¨­å®šç¹¼æ‰¿è‡ªç¾¤çµ„級別。"
msgid "Integrations|Default settings are inherited from the instance level."
-msgstr ""
+msgstr "é è¨­è¨­å®šç¹¼æ‰¿è‡ªå¯¦é«”級別。"
msgid "Integrations|Edit project alias"
-msgstr ""
+msgstr "編輯專案別å"
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
-msgstr ""
+msgstr "在 Slack 工作å€ä¸­å•Ÿç”¨ GitLab.com 斜槓命令。"
msgid "Integrations|Enable SSL verification"
-msgstr ""
+msgstr "啟用 SSL 驗證"
msgid "Integrations|Enable comments"
-msgstr ""
+msgstr "啟用留言評論"
msgid "Integrations|Enter your alias"
-msgstr ""
+msgstr "輸入您的別å"
msgid "Integrations|Failed to link namespace. Please try again."
-msgstr ""
+msgstr "無法éˆæŽ¥å‘½å空間,請é‡è©¦ã€‚"
msgid "Integrations|Failed to load namespaces. Please try again."
-msgstr ""
+msgstr "載入命å空間失敗,請é‡è©¦ã€‚"
msgid "Integrations|Failed to load subscriptions."
-msgstr ""
+msgstr "無法載入訂閱。"
msgid "Integrations|Failed to sign in to GitLab."
-msgstr ""
+msgstr "無法登入 GitLab。"
msgid "Integrations|Failed to unlink namespace. Please try again."
-msgstr ""
+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 ""
+msgstr "GitLab 管ç†å“¡å¯ä»¥è¨­å®šæ‰€æœ‰ç¾¤çµ„和專案é è¨­ç¹¼æ‰¿å’Œä½¿ç”¨çš„æ•´åˆï¼Œ 這些整åˆæ‡‰ç”¨æ–¼æ‰€æœ‰å°šæœªä½¿ç”¨è‡ªè¨‚設定的組和專案, 如果需è¦è¨­å®šï¼Œæ‚¨å¯ä»¥è¦†è“‹ä¸€å€‹çµ„或專案的自訂設定。 瞭解更多關於 %{integrations_link_start}實例級整åˆç®¡ç†%{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 "GitLab 管ç†å“¡å¯ä»¥è¨­å®šä¸€å€‹ç¾¤çµ„中所有專案é è¨­ç¹¼æ‰¿å’Œä½¿ç”¨çš„æ•´åˆï¼Œé€™äº›æ•´åˆæ‡‰ç”¨æ–¼æ‰€æœ‰å°šæœªä½¿ç”¨è‡ªè¨‚設定的專案, 如果專案需è¦è¨­å®šï¼Œæ‚¨å¯ä»¥è¦†è“‹è‡ªè¨‚設定。 瞭解更多關於 %{integrations_link_start}群組級整åˆç®¡ç†%{link_end}。"
msgid "Integrations|Group-level integration management"
-msgstr ""
+msgstr "群組層級整åˆç®¡ç†"
msgid "Integrations|Includes Standard, plus the entire commit message, commit hash, and issue IDs"
-msgstr ""
+msgstr "包括標準,以åŠæ•´å€‹æ交消æ¯ã€æ交哈希和議題 ID"
msgid "Integrations|Includes commit title and branch."
-msgstr ""
+msgstr "包括æ交標題和分支。"
msgid "Integrations|Instance-level integration management"
-msgstr ""
+msgstr "實體層級整åˆç®¡ç†"
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
-msgstr ""
+msgstr "當議題在Jira中設定的專案中建立後,Jira中建立的議題會顯示於此。"
msgid "Integrations|Keep your PHP dependencies updated on Packagist."
-msgstr ""
+msgstr "在 Packagist 上更新您的 PHP ä¾è³´é …。"
msgid "Integrations|Known limitations"
-msgstr ""
+msgstr "已知é™åˆ¶"
msgid "Integrations|Link namespaces"
-msgstr ""
+msgstr "éˆæŽ¥å‘½å空間"
msgid "Integrations|Linked namespaces"
-msgstr ""
+msgstr "é—œè¯çš„命å空間"
msgid "Integrations|Namespace successfully linked"
-msgstr ""
+msgstr "命å空間éˆæŽ¥æˆåŠŸ"
msgid "Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance."
-msgstr ""
+msgstr "命å空間是您éˆæŽ¥åˆ°æ­¤ Jira 實例的 GitLab 群組和å­ç¾¤çµ„。"
msgid "Integrations|No available namespaces."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„命å空間。"
msgid "Integrations|No linked namespaces"
-msgstr ""
+msgstr "沒有éˆæŽ¥çš„命å空間"
msgid "Integrations|Notification settings"
-msgstr ""
+msgstr "通知設定"
msgid "Integrations|Projects using custom settings"
-msgstr ""
+msgstr "使用自訂設定的專案"
msgid "Integrations|Projects using custom settings will not be affected."
-msgstr ""
+msgstr "使用自訂設定的專案ä¸æœƒå—到影響。"
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
-msgstr ""
+msgstr "除éžå°ˆæ¡ˆæ‰€æœ‰è€…é¸æ“‡ä½¿ç”¨çˆ¶ç´šé è¨­å€¼ï¼Œä½¿ç”¨è‡ªè¨‚設定的專案ä¸æœƒå—到影響。"
msgid "Integrations|Reset integration?"
-msgstr ""
+msgstr "é‡ç½®æ•´åˆå—Žï¼Ÿ"
msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration."
-msgstr ""
+msgstr "é‡ç½®æ­¤æ•´åˆå°‡æ¸…除設定並åœç”¨æ­¤æ•´åˆã€‚"
msgid "Integrations|Restrict to branch (optional)"
-msgstr ""
+msgstr "分支é™å®š (å¯é¸)"
msgid "Integrations|Return to GitLab for Jira"
-msgstr ""
+msgstr "返回 GitLab å–å¾— Jira"
msgid "Integrations|SSL verification"
-msgstr ""
+msgstr "SSL é©—è­‰"
msgid "Integrations|Save settings?"
-msgstr ""
+msgstr "ä¿å­˜è¨­å®šå—Žï¼Ÿ"
msgid "Integrations|Saving will update the default settings for all projects that are not using custom settings."
-msgstr ""
+msgstr "ä¿å­˜å°‡æ›´æ–°æ‰€æœ‰ä¸ä½¿ç”¨è‡ªè¨‚設定的專案的é è¨­è¨­å®šã€‚"
msgid "Integrations|Search Jira issues"
-msgstr ""
+msgstr "æœå°‹Jiraè­°é¡Œ"
msgid "Integrations|Search ZenTao issues"
-msgstr ""
+msgstr "æœå°‹ZenTaoè­°é¡Œ"
msgid "Integrations|Send notifications about project events to Unify Circuit."
-msgstr ""
+msgstr "將有關專案事件的通知發é€åˆ° Unify Circuit。"
msgid "Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}"
-msgstr ""
+msgstr "將有關專案事件的通知發é€åˆ° Unify Circuit å°è©±ã€‚ %{docs_link}"
msgid "Integrations|Sign in to GitLab"
-msgstr ""
+msgstr "登入到 GitLab"
msgid "Integrations|Sign in to add namespaces"
-msgstr ""
+msgstr "登入以加入命å空間"
msgid "Integrations|Standard"
-msgstr ""
+msgstr "標準"
msgid "Integrations|There are no projects using custom settings"
-msgstr ""
+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 ""
+msgstr "此整åˆåƒ…é©ç”¨æ–¼ SaaS。加入命å空間僅é©ç”¨æ–¼å…許跨站點 cookie çš„ç€è¦½å™¨ã€‚ %{linkStart}瞭解更多%{linkEnd}。"
msgid "Integrations|This integration, and inheriting projects were reset."
-msgstr ""
+msgstr "此整åˆå’Œç¹¼æ‰¿å°ˆæ¡ˆå·²è¢«é‡ç½®ã€‚"
msgid "Integrations|To keep this project going, create a new issue."
-msgstr ""
+msgstr "為了ä¿æŒé€™å€‹å°ˆæ¡ˆçš„推進,請建立一個新的議題."
msgid "Integrations|Trigger"
-msgstr ""
+msgstr "觸發器"
msgid "Integrations|Use custom settings"
-msgstr ""
+msgstr "使用自訂設定"
msgid "Integrations|Use default settings"
-msgstr ""
+msgstr "使用é è¨­è¨­å®š"
msgid "Integrations|You can close this window."
-msgstr ""
+msgstr "您å¯ä»¥é—œé–‰æ­¤çª—å£ã€‚"
msgid "Integrations|You can use this alias in your Slack commands"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ Slack 命令中使用此別å"
msgid "Integrations|You haven't activated any integrations yet."
-msgstr ""
+msgstr "您尚未激活任何整åˆã€‚"
msgid "Integrations|You must have owner or maintainer permissions to link namespaces."
-msgstr ""
+msgstr "您必須æ“有所有者或維護者權é™æ‰èƒ½éˆæŽ¥å‘½å空間。"
msgid "Integrations|You must use a %{linkStart}supported browser%{linkEnd} to use the GitLab for Jira app."
-msgstr ""
+msgstr "您必須使用 %{linkStart}支æ´çš„ç€è¦½å™¨%{linkEnd} æ‰èƒ½ä½¿ç”¨ GitLab for Jira 應用程å¼ã€‚"
msgid "Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "您ç¾åœ¨æ‡‰è©²åœ¨ Jira Cloud 議題中看到動態。%{linkStart}瞭解更多%{linkEnd}"
msgid "Integrations|You've activated every integration 🎉"
-msgstr ""
+msgstr "您已啟用了æ¯ä¸€å€‹æ•´åˆ"
msgid "Integrations|Your browser is not supported"
-msgstr ""
+msgstr "ä¸æ”¯æ´æ‚¨çš„ç€è¦½å™¨"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
-msgstr ""
+msgstr "當您在ZenTao中建立專案的議題時,禪é“議題會顯示在此處。"
msgid "Integrations|can't exceed %{recipients_limit}"
-msgstr ""
+msgstr "ä¸èƒ½è¶…éŽ %{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 "交互模å¼"
msgid "Interested parties can even contribute by pushing commits if they want to."
-msgstr ""
+msgstr "使用者å¯ä»¥é€šéŽæŽ¨é€æ交來å°å°ˆæ¡ˆä½œå‡ºè²¢ç»ã€‚"
msgid "Internal"
-msgstr ""
+msgstr "內部"
msgid "Internal - The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
+msgstr "除外部使用者外,任何登入使用者å‡å¯æŸ¥çœ‹è©²ç¾¤çµ„和任何內部專案。"
msgid "Internal - The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "除外部使用者外,任何登入使用者å‡å¯å­˜å–該專案。"
msgid "Internal error occurred while delivering this webhook."
-msgstr ""
+msgstr "傳é€æ­¤ webhook 時發生內部錯誤。"
msgid "Internal note"
-msgstr ""
+msgstr "內部說明"
msgid "Internal users"
-msgstr ""
+msgstr "內部使用者"
msgid "Internal users cannot be deactivated"
-msgstr ""
+msgstr "ä¸èƒ½åœç”¨å…§éƒ¨ä½¿ç”¨è€…"
msgid "Interval"
-msgstr ""
+msgstr "é–“éš”"
msgid "Interval Pattern"
-msgstr ""
+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 ""
+msgstr "從 13.1 版本起,您需è¦å…ˆ%{recreate_link_start}é‡å»ºç´¢å¼•%{link_end}æ‰èƒ½åŸ·è¡Œ%{reindexing_link_start}ä¸åœæ©Ÿé‡ç´¢å¼•%{link_end}å’Œ%{migrations_link_start}高級æœå°‹é·ç§»%{link_end}。"
msgid "Introducing Your DevOps Reports"
-msgstr ""
+msgstr "介紹您的 DevOps 報告"
msgid "Invalid"
-msgstr ""
+msgstr "無效的"
msgid "Invalid Insights config file detected"
-msgstr ""
+msgstr "檢測到無效的 Insights 設定檔案"
msgid "Invalid OS"
-msgstr ""
+msgstr "無效的作業系統"
msgid "Invalid URL"
-msgstr ""
+msgstr "無效的網å€"
msgid "Invalid URL: %{url}"
-msgstr ""
+msgstr "無效 URL:%{url}"
msgid "Invalid date"
-msgstr ""
+msgstr "無效日期"
msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
-msgstr ""
+msgstr "日期格å¼ç„¡æ•ˆã€‚請使用UTCæ ¼å¼ YYYY-MM-DD"
msgid "Invalid date range"
-msgstr ""
+msgstr "無效的日期範åœ"
msgid "Invalid feature"
-msgstr ""
+msgstr "無效的功能"
msgid "Invalid field"
-msgstr ""
+msgstr "無效字段。"
msgid "Invalid file format with specified file type"
-msgstr ""
+msgstr "指定文件類型的文件格å¼ç„¡æ•ˆ"
msgid "Invalid file."
-msgstr ""
+msgstr "無效的文件。"
msgid "Invalid format selected"
-msgstr ""
+msgstr "é¸å–çš„æ ¼å¼ç„¡æ•ˆ"
msgid "Invalid hash"
-msgstr ""
+msgstr "無效雜湊"
msgid "Invalid import params"
-msgstr ""
+msgstr "匯入åƒæ•¸ç„¡æ•ˆ"
msgid "Invalid input, please avoid emojis"
-msgstr ""
+msgstr "輸入無效,請é¿å…使用表情符號"
msgid "Invalid login or password"
-msgstr ""
+msgstr "登入å或密碼無效"
msgid "Invalid period"
-msgstr ""
+msgstr "無效的週期"
msgid "Invalid pin code."
-msgstr ""
+msgstr "無效的 pin 碼。"
msgid "Invalid policy type"
-msgstr ""
+msgstr "無效的策略類型"
msgid "Invalid repository bundle for snippet with id %{snippet_id}"
-msgstr ""
+msgstr "é‡å°ä»£ç¢¼ç‰‡æ®µ%{snippet_id}的無效倉庫包"
msgid "Invalid repository path"
-msgstr ""
+msgstr "無效的倉庫路徑"
msgid "Invalid rule"
-msgstr ""
+msgstr "無效的è¦å‰‡"
msgid "Invalid server response"
-msgstr ""
+msgstr "無效的æœå‹™å™¨éŸ¿æ‡‰"
msgid "Invalid status"
-msgstr ""
+msgstr "無效的狀態"
msgid "Invalid two-factor code."
-msgstr ""
+msgstr "無效的雙é‡èªè­‰ç¢¼ã€‚"
msgid "Invalid yaml"
-msgstr ""
+msgstr "無效的yaml"
msgid "Investigate vulnerability: %{title}"
-msgstr ""
+msgstr "調查æ¼æ´ž: %{title}"
msgid "Invisible Captcha"
-msgstr ""
+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 ""
+msgstr "隱形驗證碼有助於防止建立垃圾郵件帳號。它在帳號註冊表單中加入了一個蜜ç½å­—段和時間æ•æ„Ÿçš„表單æ交。"
msgid "Invitation"
-msgstr ""
+msgstr "邀請"
msgid "Invitation declined"
-msgstr ""
+msgstr "邀請已被拒絕。"
msgid "Invite \"%{email}\" by email"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶é‚€è«‹ã€Œ%{email}ã€"
msgid "Invite \"%{trimmed}\" by email"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶é‚€è«‹ã€Œ%{trimmed}ã€"
msgid "Invite Members"
-msgstr ""
+msgstr "邀請æˆå“¡"
msgid "Invite a group"
-msgstr ""
+msgstr "邀請群組"
msgid "Invite members"
-msgstr ""
+msgstr "邀請æˆå“¡"
msgid "InviteEmail|%{inviter} invited you to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "%{inviter}邀請您作為%{role}加入%{project_or_group_name}%{project_or_group}"
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 ""
+msgstr "%{inviter}邀請您作為%{role}加入%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}%{br_tag}"
msgid "InviteEmail|%{project_or_group} details"
-msgstr ""
+msgstr "%{project_or_group} 詳情"
msgid "InviteEmail|Groups assemble related projects together and grant members access to several projects at once."
-msgstr ""
+msgstr "群組彙集相關專案並åŒæ™‚授予æˆå“¡å°è‹¥å¹²å°ˆæ¡ˆçš„å­˜å–權é™ã€‚"
msgid "InviteEmail|Join now"
-msgstr ""
+msgstr "ç«‹å³åŠ å…¥"
msgid "InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}"
-msgstr ""
+msgstr "加入您的 GitLab åœ˜éšŠï¼ %{inviter} 邀請您加入 %{project_or_group_name}"
msgid "InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}"
-msgstr ""
+msgstr "加入您的 GitLab 團隊ï¼æ‚¨è¢«é‚€è«‹åŠ å…¥ %{project_or_group_name}"
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 "專案用於託管和å”作程å¼ç¢¼ï¼Œè¿½è¹¤è­°é¡Œï¼Œä»¥åŠä½¿ç”¨å…§ç½®çš„GitLab CI/CDæŒçºŒæ§‹å»ºã€æ¸¬è©¦å’Œéƒ¨ç½²æ‚¨çš„應用程å¼ã€‚"
msgid "InviteEmail|What's it about?"
-msgstr ""
+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 ""
+msgstr "您被邀請以%{role}身份加入%{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group}%{br_tag}"
msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{project_or_group} as a %{role}"
-msgstr ""
+msgstr "您被邀請以%{role}身份加入%{project_or_group_name}%{project_or_group}"
msgid "InviteEmail|You were assigned the following tasks:"
-msgstr ""
+msgstr "您被指派了以下任務:"
msgid "InviteEmail|and has assigned you the following tasks:"
-msgstr ""
+msgstr "並為您指派了以下任務:"
msgid "InviteMembersBanner|Collaborate with your team"
-msgstr ""
+msgstr "與您的團隊å”åŒåˆä½œ"
msgid "InviteMembersBanner|Invite your colleagues"
-msgstr ""
+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 ""
+msgstr "ç›®å‰æ‚¨é‚„沒有邀請任何人加入這個群組。 您å¯ä»¥é‚€è«‹æ‚¨çš„åŒäº‹åˆ°ç¾¤çµ„,以方便討論å•é¡Œï¼Œåœ¨åˆä½µè«‹æ±‚中進行å”作,以åŠåˆ†äº«æ‚¨çš„知識。"
-msgid "InviteMembersModal| To get more members and access to additional paid features, an owner of this namespace can start a trial or upgrade to a paid tier."
-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 ""
+msgstr "%{linkStart}瞭解更多%{linkEnd}關於角色權é™çš„訊æ¯"
msgid "InviteMembersModal|Access expiration date (optional)"
-msgstr ""
+msgstr "å­˜å–到期日期(å¯é¸)"
msgid "InviteMembersModal|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "InviteMembersModal|Choose a project for the issues"
-msgstr ""
+msgstr "é¸æ“‡è­°é¡Œçš„專案"
msgid "InviteMembersModal|Close invite team members"
-msgstr ""
+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 ""
+msgstr "為您的新團隊æˆå“¡å»ºç«‹è­°é¡Œ (å¯é¸)"
msgid "InviteMembersModal|Explore paid plans"
-msgstr ""
+msgstr "ç€ç ä»˜è²»è¨ˆåŠƒ"
msgid "InviteMembersModal|GitLab is better with colleagues!"
-msgstr ""
+msgstr "GitLab 與åŒäº‹å…±è™•æ›´ä½³ï¼"
msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
-msgstr ""
+msgstr "邀請一兩個åŒäº‹åŠ å…¥ä½ ï¼Œæ€Žéº¼æ¨£ï¼Ÿ"
msgid "InviteMembersModal|Invite"
-msgstr ""
+msgstr "邀請"
msgid "InviteMembersModal|Invite a group"
-msgstr ""
+msgstr "邀請群組"
msgid "InviteMembersModal|Invite members"
-msgstr ""
+msgstr "邀請æˆå“¡"
msgid "InviteMembersModal|Manage members"
-msgstr ""
+msgstr "管ç†æˆå“¡"
msgid "InviteMembersModal|Members were successfully added"
-msgstr ""
+msgstr "æˆå“¡å·²æˆåŠŸåŠ å…¥"
msgid "InviteMembersModal|Review the invite errors and try again:"
-msgstr ""
+msgstr "查看邀請錯誤並é‡è©¦ï¼š"
msgid "InviteMembersModal|Search for a group to invite"
-msgstr ""
+msgstr "æœå°‹è¦é‚€è«‹çš„群組"
msgid "InviteMembersModal|Select a group to invite"
-msgstr ""
+msgstr "é¸æ“‡è¦é‚€è«‹çš„群組"
msgid "InviteMembersModal|Select a role"
-msgstr ""
+msgstr "é¸æ“‡è§’色"
msgid "InviteMembersModal|Select members or type email addresses"
-msgstr ""
+msgstr "é¸æ“‡æˆå“¡æˆ–輸入電å­éƒµä»¶åœ°å€"
msgid "InviteMembersModal|Something went wrong"
-msgstr ""
+msgstr "出ç¾éŒ¯èª¤"
msgid "InviteMembersModal|The following member couldn't be invited"
msgid_plural "InviteMembersModal|The following %d members couldn't be invited"
-msgstr[0] ""
+msgstr[0] "下列 %d 個æˆå“¡ç„¡æ³•è¢«é‚€è«‹"
msgid "InviteMembersModal|This feature is disabled until this group has space for more members."
-msgstr ""
+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 ""
+msgstr "è¦å‘新團隊æˆå“¡åˆ†é…議題,您需è¦ä¸€å€‹è­°é¡Œæ‰€å±¬çš„專案。 %{linkStart}從建立一個專案開始。%{linkEnd}"
-msgid "InviteMembersModal|To get more members an owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier."
-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 "è¦å–得更多æˆå“¡ï¼Œç¾¤çµ„çš„æ“有者å¯ä»¥ %{trialLinkStart}開始試用%{trialLinkEnd} 或 %{upgradeLinkStart}å‡ç´š%{upgradeLinkEnd} 到付費等級。"
msgid "InviteMembersModal|To make more space, you can remove members who no longer need access."
-msgstr ""
+msgstr "è¦ç²å¾—更多空間,您å¯ä»¥ç§»é™¤ä¸å†éœ€è¦å­˜å–權é™çš„æˆå“¡ã€‚"
msgid "InviteMembersModal|Username or email address"
-msgstr ""
+msgstr "使用者å稱或郵箱地å€"
msgid "InviteMembersModal|You cannot add more members, but you can remove members who no longer need access."
-msgstr ""
+msgstr "您無法增加更多æˆå“¡ï¼Œä½†å¯ä»¥ç§»é™¤ä¸å†éœ€è¦å­˜å–權é™çš„æˆå“¡ã€‚"
msgid "InviteMembersModal|You only have space for %{count} more %{members} in %{name}"
-msgstr ""
-
-msgid "InviteMembersModal|You only have space for %{count} more %{members} in your personal projects"
-msgstr ""
+msgstr "在 %{name},您åªæœ‰ %{count} 個更多的 %{members} 的空間"
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "您正在邀請一個群組加入 %{strongStart}%{name}%{strongEnd} 群組。"
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "您正在邀請一個å°çµ„加入 %{strongStart}%{name}%{strongEnd} 專案。"
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} group."
-msgstr ""
+msgstr "您正在邀請æˆå“¡åŠ å…¥ %{strongStart}%{name}%{strongEnd} 群組。"
msgid "InviteMembersModal|You're inviting members to the %{strongStart}%{name}%{strongEnd} project."
-msgstr ""
+msgstr "您正在邀請æˆå“¡åŠ å…¥ %{strongStart}%{name}%{strongEnd} 專案。"
msgid "InviteMembersModal|You've reached your %{count} %{members} limit for %{name}"
-msgstr ""
+msgstr "您已é”到 %{name} çš„ %{count} 個 %{members} é™åˆ¶"
msgid "InviteMembersModal|You've reached your %{count} %{members} limit for your personal projects"
-msgstr ""
+msgstr "您的個人專案已é”到 %{count} %{members} 個é™åˆ¶"
msgid "InviteMembers|Invite a group"
-msgstr ""
+msgstr "邀請群組"
msgid "InviteMembers|Invite team members"
-msgstr ""
+msgstr "邀請團隊æˆå“¡"
msgid "InviteMember|Add members to this project and start collaborating with your team."
-msgstr ""
+msgstr "加入æˆå“¡åˆ°æ­¤å°ˆæ¡ˆä¸¦é–‹å§‹èˆ‡æ‚¨çš„團隊åˆä½œã€‚"
msgid "InviteMember|Invite Members (optional)"
-msgstr ""
+msgstr "邀請æˆå“¡ï¼ˆå¯é¸ï¼‰"
msgid "InviteMember|Invite another member"
-msgstr ""
+msgstr "邀請其他æˆå“¡"
msgid "InviteMember|Invite members"
-msgstr ""
+msgstr "邀請æˆå“¡"
msgid "InviteMember|Invite your team"
-msgstr ""
+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 "邀請使用者將被加入到開發者級別權é™ä¸­ã€‚%{linkStart}查看文件%{linkEnd}以瞭解如何更改此權é™ã€‚"
msgid "InviteReminderEmail|%{inviter} is still waiting for you to join GitLab"
-msgstr ""
+msgstr "%{inviter} 還在等待您加入GitLab"
msgid "InviteReminderEmail|%{inviter} is waiting for you to join GitLab"
-msgstr ""
+msgstr "%{inviter} 還在等待您加入GitLab"
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} 邀請您加入 %{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group} 作為 %{role}."
msgid "InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"
-msgstr ""
+msgstr "來自 %{inviter} å° GitLab 的邀請正在等待中"
msgid "InviteReminderEmail|Accept invitation"
-msgstr ""
+msgstr "接å—邀請"
msgid "InviteReminderEmail|Accept invitation: %{invite_url}"
-msgstr ""
+msgstr "接å—邀請: %{invite_url}"
msgid "InviteReminderEmail|Decline invitation"
-msgstr ""
+msgstr "拒絕邀請"
msgid "InviteReminderEmail|Decline invitation: %{decline_url}"
-msgstr ""
+msgstr "拒絕邀請: %{decline_url}"
msgid "InviteReminderEmail|Hey there %{wave_emoji}"
-msgstr ""
+msgstr "您好 %{wave_emoji}"
msgid "InviteReminderEmail|Hey there!"
-msgstr ""
+msgstr "您好ï¼"
msgid "InviteReminderEmail|In case you missed it..."
-msgstr ""
+msgstr "è¬ä¸€æ‚¨éŒ¯éŽäº†..."
msgid "InviteReminderEmail|Invitation pending"
-msgstr ""
+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 ""
+msgstr "è·é›¢ %{inviter} 邀請您加入 %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} 作為 %{role}已經%{invitation_age} 天。請å•æ‚¨æ‰“算怎麼處置?"
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 "溫馨æ醒:%{inviter} 邀請您加入 %{strong_start}%{project_or_group_name}%{strong_end}%{project_or_group} 作為 %{role}."
msgid "Invited"
-msgstr ""
+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 "å—邀群組å…許的電å­éƒµä»¶åŸŸå¿…須包å«æ ¹ç¾¤çµ„å…許電å­éƒµä»¶åŸŸçš„å­é›†ã€‚請至群組的“設定 &gt; 一般†é é¢ä¸¦é¸å–“通éŽé›»å­éƒµä»¶åŸŸé™è£½æˆå“¡è³‡æ ¼â€ã€‚"
msgid "IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}"
-msgstr ""
+msgstr "用空格分隔的頻é“和使用者。 %{recipients_docs_link}"
msgid "IrkerService|Default IRC URI (optional)"
-msgstr ""
+msgstr "é è¨­ IRC URI (å¯é¸)"
msgid "IrkerService|How to enter channels or users?"
-msgstr ""
+msgstr "如何輸入頻é“或使用者?"
msgid "IrkerService|Recipients"
-msgstr ""
+msgstr "收件人"
msgid "IrkerService|Send update messages to an irker server."
-msgstr ""
+msgstr "å‘ 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 "å‘ irker æœå‹™å™¨ç™¼é€æ›´æ–°æ¶ˆæ¯ã€‚在使用它之å‰ï¼Œæ‚¨éœ€è¦è¨­å®š irker 守護進程。 %{docs_link}"
msgid "IrkerService|Server host (optional)"
-msgstr ""
+msgstr "æœå‹™å™¨ä¸»æ©Ÿï¼ˆå¯é¸ï¼‰"
msgid "IrkerService|Server port (optional)"
-msgstr ""
+msgstr "æœå‹™å™¨ç«¯å£(å¯é¸)"
msgid "IrkerService|URI to add before each recipient."
-msgstr ""
+msgstr "è¦åœ¨æ¯å€‹æ”¶ä»¶äººä¹‹å‰åŠ å…¥çš„ URI。"
msgid "IrkerService|irker (IRC gateway)"
-msgstr ""
+msgstr "irker (IRC網關)"
msgid "IrkerService|irker daemon hostname (defaults to localhost)."
-msgstr ""
+msgstr "irker 守護進程主機å(é è¨­ç‚º localhost)。"
msgid "IrkerService|irker daemon port (defaults to 6659)."
-msgstr ""
+msgstr "irker 守護進程端å£ï¼ˆé è¨­ç‚º 6659)。"
msgid "Is blocked by"
-msgstr ""
+msgstr "已被å°éŽ–"
msgid "Is using license seat:"
-msgstr ""
+msgstr "正在使用授權æ¢æ¬¾ï¼š"
msgid "Is using seat"
-msgstr ""
+msgstr "正在使用許å¯å¸­æ¬¡"
msgid "IssuableStatus|Closed"
-msgstr ""
+msgstr "已關閉"
msgid "IssuableStatus|Closed (%{link})"
-msgstr ""
+msgstr "關閉(%{link})"
msgid "IssuableStatus|duplicated"
-msgstr ""
+msgstr "é‡è¤‡"
msgid "IssuableStatus|moved"
-msgstr ""
+msgstr "已移動"
msgid "IssuableStatus|promoted"
-msgstr ""
+msgstr "å·²å‡ç´š"
msgid "Issue"
-msgstr ""
+msgstr "議題"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
-msgstr ""
+msgstr "è­°é¡Œ%{issue_reference}已被加入到å²è©©%{epic_reference}。"
msgid "Issue Analytics"
-msgstr ""
+msgstr "議題分æž"
msgid "Issue Boards"
-msgstr ""
+msgstr "議題看æ¿"
msgid "Issue Type"
-msgstr ""
+msgstr "議題類型"
msgid "Issue already promoted to epic."
-msgstr ""
+msgstr "議題已å‡ç´šç‚ºå²è©©ã€‚"
msgid "Issue cannot be found."
-msgstr ""
+msgstr "議題無法找到"
msgid "Issue created from vulnerability %{vulnerability_link}"
-msgstr ""
+msgstr "從æ¼æ´ž %{vulnerability_link}建立的議題"
msgid "Issue creation requests"
-msgstr ""
+msgstr "議題建立請求"
msgid "Issue details"
-msgstr ""
+msgstr "議題詳情"
msgid "Issue events"
-msgstr ""
+msgstr "議題事件"
msgid "Issue first deployed to production"
-msgstr ""
+msgstr "議題首次部署到正å¼ç’°å¢ƒ"
msgid "Issue has been promoted to incident"
-msgstr ""
+msgstr "議題已å‡ç´šç‚ºäº‹ä»¶"
msgid "Issue label"
-msgstr ""
+msgstr "議題標記"
msgid "Issue or merge request ID is required"
-msgstr ""
+msgstr "需è¦è­°é¡Œæˆ–åˆä½µè«‹æ±‚ ID"
msgid "Issue published on status page."
-msgstr ""
+msgstr "議題發布在狀態é é¢ä¸Šã€‚"
msgid "Issue types"
-msgstr ""
+msgstr "議題類型"
msgid "Issue update failed"
-msgstr ""
+msgstr "議題更新失敗"
msgid "Issue was closed by %{name} %{reason}"
-msgstr ""
+msgstr "%{reason},議題由 %{name} 關閉。"
msgid "Issue weight"
-msgstr ""
+msgstr "議題權é‡"
msgid "IssueAnalytics|Age"
-msgstr ""
+msgstr "年齡"
msgid "IssueAnalytics|Assignees"
-msgstr ""
+msgstr "指派人"
msgid "IssueAnalytics|Created by"
-msgstr ""
+msgstr "建立者"
msgid "IssueAnalytics|Due date"
-msgstr ""
+msgstr "截止日期"
msgid "IssueAnalytics|Failed to load issues. Please try again."
-msgstr ""
+msgstr "載入議題失敗。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "IssueAnalytics|Issue"
-msgstr ""
+msgstr "議題"
msgid "IssueAnalytics|Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "IssueAnalytics|Status"
-msgstr ""
+msgstr "狀態"
msgid "IssueAnalytics|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "IssueBoards|Board"
-msgstr ""
+msgstr "看æ¿"
msgid "IssueBoards|Boards"
-msgstr ""
+msgstr "看æ¿"
msgid "IssueBoards|Create new board"
-msgstr ""
+msgstr "建立新看æ¿"
msgid "IssueBoards|Delete board"
-msgstr ""
+msgstr "刪除看æ¿"
msgid "IssueBoards|No matching boards found"
-msgstr ""
+msgstr "未找到符åˆçš„看æ¿"
msgid "IssueBoards|Some of your boards are hidden, add a license to see them again."
-msgstr ""
+msgstr "您的一些看æ¿è¢«éš±è—,請加入許å¯è­‰å¾Œå†æ¬¡æŸ¥çœ‹ã€‚"
msgid "IssueBoards|Switch board"
-msgstr ""
+msgstr "切æ›çœ‹æ¿"
msgid "IssueList|created %{timeAgoString} by %{user}"
-msgstr ""
+msgstr "由 %{user} 建立於 %{timeAgoString}"
msgid "IssueTracker|Custom issue tracker"
-msgstr ""
+msgstr "自訂議題追蹤器"
msgid "IssueTracker|Issue URL"
-msgstr ""
+msgstr "議題 URL"
msgid "IssueTracker|New issue URL"
-msgstr ""
+msgstr "新建議題URL"
msgid "IssueTracker|The URL to create an issue in the external issue tracker."
-msgstr ""
+msgstr "在外部議題追蹤器中建立議題的 URL。"
msgid "IssueTracker|The URL to the project in the external issue tracker."
-msgstr ""
+msgstr "外部議題追蹤器中專案的 URL。"
msgid "IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}."
-msgstr ""
+msgstr "在外部議題追蹤器中查看議題的 URLã€‚å¿…é ˆåŒ…å« %{colon_id}。"
msgid "IssueTracker|Use Bugzilla as this project's issue tracker."
-msgstr ""
+msgstr "使用 Bugzilla 作為該專案的議題追蹤器。"
msgid "IssueTracker|Use Bugzilla as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "使用 Bugzilla 作為該專案的議題追蹤器。 %{docs_link}"
msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker."
-msgstr ""
+msgstr "使用 IBM Engineering Workflow Management 作為該專案的議題追蹤器。"
msgid "IssueTracker|Use IBM Engineering Workflow Management as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "使用 IBM Engineering Workflow Management 作為該專案的議題追蹤器。 %{docs_link}"
msgid "IssueTracker|Use Redmine as the issue tracker. %{docs_link}"
-msgstr ""
+msgstr "使用 Redmine 作為議題追蹤器。 %{docs_link}"
msgid "IssueTracker|Use Redmine as this project's issue tracker."
-msgstr ""
+msgstr "使用 Redmine 作為該專案的議題追蹤器。"
msgid "IssueTracker|Use YouTrack as this project's issue tracker."
-msgstr ""
+msgstr "使用 YouTrack 作為該專案的議題追蹤器。"
msgid "IssueTracker|Use YouTrack as this project's issue tracker. %{docs_link}"
-msgstr ""
+msgstr "使用 YouTrack 作為該專案的å•é¡Œè¿½è¹¤å™¨ã€‚ %{docs_link}"
msgid "IssueTracker|Use a custom issue tracker as this project's issue tracker."
-msgstr ""
+msgstr "使用自訂議題追蹤器作為該專案的議題追蹤器。"
msgid "IssueTracker|Use a custom issue tracker that is not in the integration list. %{docs_link}"
-msgstr ""
+msgstr "使用ä¸åœ¨æ•´åˆåˆ—表中的自訂議題追蹤器。 %{docs_link}"
msgid "Issues"
-msgstr ""
+msgstr "議題"
msgid "Issues Rate Limits"
-msgstr ""
+msgstr "議題比率é™åˆ¶"
msgid "Issues and merge requests"
-msgstr ""
+msgstr "議題與åˆä½µè«‹æ±‚"
msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
-msgstr ""
+msgstr "正在é‡æ–°æ¬Šè¡¡è­°é¡Œï¼Œå› æ­¤æ‰‹å‹•é‡æ–°æŽ’åºå·²è¢«åœç”¨ã€‚"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr ""
+msgstr "è­°é¡Œå¯ä»¥æ˜¯ç¼ºé™·ã€ä»»å‹™æˆ–者想法,便於使用者討論它。此外,議題是å¯æœå°‹å’ŒéŽæ¿¾çš„。"
msgid "Issues closed"
-msgstr ""
+msgstr "關閉議題"
msgid "Issues exist in projects, so to create an issue, first create a project."
-msgstr ""
+msgstr "議題存在專案中,因此,è¦å»ºç«‹è­°é¡Œï¼Œé ˆå…ˆå»ºç«‹ä¸€å€‹å°ˆæ¡ˆã€‚"
msgid "Issues must match this scope to appear in this list."
-msgstr ""
+msgstr "議題必須與此範åœç›¸ç¬¦æ‰èƒ½å‡ºç¾åœ¨æ­¤åˆ—表中。"
msgid "Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities"
-msgstr ""
+msgstr "議題留言,åˆä½µè«‹æ±‚的差異和留言,標記,里程碑,程å¼ç¢¼ç‰‡æ®µå’Œå…¶ä»–項目實體"
msgid "Issues with label %{label}"
-msgstr ""
+msgstr "帶標記 %{label} 的議題"
msgid "Issues with no epic assigned"
-msgstr ""
+msgstr "未分é…å²è©©çš„è­°é¡Œ"
msgid "Issues, merge requests, pushes, and comments."
-msgstr ""
+msgstr "議題,åˆä½µè«‹æ±‚,推é€åŠç•™è¨€ã€‚"
msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
-msgstr ""
+msgstr "在您為專案建立議題後,我們就會開始追蹤並顯示它們的指標"
msgid "IssuesAnalytics|Avg/Month:"
-msgstr ""
+msgstr "月å‡ï¼š"
msgid "IssuesAnalytics|Issues created"
-msgstr ""
+msgstr "議題已建立"
msgid "IssuesAnalytics|Issues created per month"
-msgstr ""
+msgstr "æ¯æœˆå»ºç«‹çš„è­°é¡Œ"
msgid "IssuesAnalytics|Last 12 months"
-msgstr ""
+msgstr "最近12個月"
msgid "IssuesAnalytics|Sorry, your filter produced no results"
-msgstr ""
+msgstr "抱歉,無符åˆéŽæ¿¾å™¨çš„çµæžœ"
msgid "IssuesAnalytics|There are no issues for the projects in your group"
-msgstr ""
+msgstr "群組中的專案無任何議題"
msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
-msgstr ""
+msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹è®Šæ›´æˆ–刪除上é¢çš„éŽæ¿¾æ¢ä»¶"
msgid "IssuesAnalytics|Total:"
-msgstr ""
+msgstr "總計:"
msgid "Issue|Title"
-msgstr ""
+msgstr "標題"
msgid "It is not possible to %{action} files that are stored in LFS using the web interface"
-msgstr ""
+msgstr "無法使用 Web ç•Œé¢ %{action} 儲存在 LFS 中的文件"
msgid "It looks like you have some draft commits in this branch."
-msgstr ""
+msgstr "看起來你在這個分支上有一些è‰ç¨¿æ交。"
msgid "It looks like you're attempting to activate your subscription. Use %{a_start}the Subscription page%{a_end} instead."
-msgstr ""
+msgstr "您似乎正在嘗試啟用您的訂閱。請使用 %{a_start}訂閱é é¢%{a_end} 代替。"
msgid "It may be several days before you see feature usage data."
-msgstr ""
+msgstr "您å¯èƒ½è¦éŽå¹¾å¤©æ‰èƒ½çœ‹åˆ°åŠŸèƒ½ä½¿ç”¨æƒ…æ³è³‡æ–™ã€‚"
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
-msgstr ""
+msgstr "它必須有標題行和至少有兩列:第一欄是議題標題,第二欄是議題æ述。自動檢測分隔符。"
msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
-msgstr ""
+msgstr "ä¾è³´é …掃æ作業é‹è¡ŒæˆåŠŸï¼Œä½†æ‚¨çš„專案中沒有檢測到ä¾è³´é …。"
msgid "It seems that there is currently no available data for code coverage"
-msgstr ""
+msgstr "ç›®å‰ä¼¼ä¹Žç„¡å¯ç”¨è³‡æ–™ä¾†é€²è¡Œç¨‹å¼ç¢¼è¦†è“‹çŽ‡è¨ˆç®—"
msgid "It's you"
-msgstr ""
+msgstr "你自己"
msgid "Italic text"
-msgstr ""
+msgstr "斜體文字"
msgid "Iteration"
-msgstr ""
+msgstr "迭代"
+
+msgid "Iteration cannot be created for cadence"
+msgstr "無法為週期建立迭代"
msgid "Iteration changed to"
-msgstr ""
+msgstr "迭代已更改為"
msgid "Iteration lists not available with your current license"
-msgstr ""
+msgstr "當å‰è¨±å¯è­‰ä¸­ç„¡æ³•ä½¿ç”¨è¿­ä»£åˆ—表"
msgid "Iteration removed"
-msgstr ""
+msgstr "迭代已刪除"
msgid "Iteration updated"
-msgstr ""
+msgstr "迭代已更新"
msgid "Iterations"
-msgstr ""
+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 "自動啟動日期必須是在活動迭代 %{iteration_dates} 之後。"
+
+msgid "IterationsCadence|The automation start date must come after the past iteration %{iteration_dates}."
+msgstr "自動開始日期必須在éŽåŽ»çš„迭代 %{iteration_dates} 之後。"
+
+msgid "IterationsCadence|The automation start date would retroactively create a past iteration. %{start_date} is the earliest possible start date."
+msgstr "自動開始日期將追溯éŽåŽ»å»ºç«‹çš„迭代,%{start_date} 是最早的開始日期。"
msgid "Iterations|Add iteration"
-msgstr ""
+msgstr "加入迭代"
msgid "Iterations|All"
-msgstr ""
+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 ""
+msgstr "週期設定無效。"
msgid "Iterations|Cadence name"
-msgstr ""
+msgstr "週期å稱"
msgid "Iterations|Can be converted"
-msgstr ""
+msgstr "å¯ä»¥è½‰æ›"
msgid "Iterations|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Iterations|Couldn't find iteration cadence"
-msgstr ""
+msgstr "找ä¸åˆ°è¿­ä»£é€±æœŸ"
msgid "Iterations|Create cadence"
-msgstr ""
+msgstr "建立週期"
msgid "Iterations|Create iteration"
-msgstr ""
+msgstr "建立迭代"
+
+msgid "Iterations|Create iterations automatically on a regular schedule."
+msgstr "定期自動建立迭代。"
msgid "Iterations|Delete cadence"
-msgstr ""
+msgstr "刪除週期"
msgid "Iterations|Delete iteration cadence?"
-msgstr ""
+msgstr "刪除迭代週期?"
msgid "Iterations|Delete iteration?"
-msgstr ""
+msgstr "刪除迭代?"
msgid "Iterations|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Iterations|Done"
-msgstr ""
+msgstr "已完æˆ"
msgid "Iterations|Due date"
-msgstr ""
+msgstr "截止日期"
msgid "Iterations|Duration"
-msgstr ""
+msgstr "為期"
msgid "Iterations|Edit cadence"
-msgstr ""
+msgstr "編輯週期"
msgid "Iterations|Edit iteration"
-msgstr ""
+msgstr "編輯迭代"
msgid "Iterations|Edit iteration cadence"
-msgstr ""
+msgstr "編輯迭代週期"
-msgid "Iterations|Error loading iteration cadences."
-msgstr ""
+msgid "Iterations|Enable roll over"
+msgstr "啟用 roll over"
-msgid "Iterations|First iteration start date"
-msgstr ""
+msgid "Iterations|Error loading iteration cadences."
+msgstr "載入迭代週期時發生錯誤。"
msgid "Iterations|Iteration cadences"
-msgstr ""
+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 ""
+msgstr "迭代是在一段時間內追蹤議題的一種方法,使å°çµ„也能夠追蹤速度和波動指標。"
+
+msgid "Iterations|Iterations are scheduled to start on %{weekday}s."
+msgstr "迭代排程從 %{weekday} 開始。"
msgid "Iterations|Learn more about automatic scheduling"
-msgstr ""
+msgstr "瞭解更多關於自動計劃的訊æ¯"
msgid "Iterations|Manual management of iterations will be deprecated in GitLab 15.6. Convert your manual cadence to use automated scheduling when you are ready."
-msgstr ""
+msgstr "GitLab 15.6 將棄用手動迭代管ç†ã€‚準備好後,將您的手動週期轉æ›ç‚ºä½¿ç”¨è‡ªå‹•èª¿åº¦ã€‚"
msgid "Iterations|Move incomplete issues to the next iteration."
-msgstr ""
+msgstr "將未完æˆçš„議題移至下一次迭代。"
msgid "Iterations|New iteration"
-msgstr ""
+msgstr "新建迭代"
msgid "Iterations|New iteration cadence"
-msgstr ""
+msgstr "新建迭代週期"
msgid "Iterations|No closed iterations."
-msgstr ""
+msgstr "沒有已關閉的迭代。"
msgid "Iterations|No iteration cadences to show."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„迭代週期。"
msgid "Iterations|No iterations found"
-msgstr ""
+msgstr "未找到迭代"
msgid "Iterations|No iterations in cadence."
-msgstr ""
-
-msgid "Iterations|No one can change this date after the cadence has begun."
-msgstr ""
+msgstr "週期中沒有迭代。"
msgid "Iterations|No open iterations."
-msgstr ""
+msgstr "沒有開放的迭代。"
msgid "Iterations|Number of upcoming iterations that should be scheduled at a time."
-msgstr ""
+msgstr "一次性的安排å³å°‡åˆ°ä¾†çš„迭代次數。"
msgid "Iterations|Open"
-msgstr ""
+msgstr "開放"
msgid "Iterations|Roll over issues"
-msgstr ""
+msgstr "滾動議題"
msgid "Iterations|Save changes"
-msgstr ""
+msgstr "ä¿å­˜ä¿®æ”¹"
msgid "Iterations|Select duration"
-msgstr ""
+msgstr "é¸æ“‡æŒçºŒæ™‚é–“"
msgid "Iterations|Select number"
-msgstr ""
+msgstr "é¸æ“‡æ•¸é‡"
msgid "Iterations|Select start date"
-msgstr ""
+msgstr "é¸æ“‡é–‹å§‹æ—¥æœŸ"
msgid "Iterations|Start date"
-msgstr ""
+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 ""
+msgstr "æ¯æ¬¡è¿­ä»£çš„æŒçºŒæ™‚間(以周為單ä½ï¼‰ã€‚"
msgid "Iterations|The iteration has been deleted."
-msgstr ""
-
-msgid "Iterations|The start date of the first iteration determines when your cadence begins."
-msgstr ""
+msgstr "迭代已被刪除。"
msgid "Iterations|This cadence can be converted to use automated scheduling"
-msgstr ""
+msgstr "å¯ä»¥å°‡æ­¤é€±æœŸè½‰æ›ç‚ºä½¿ç”¨è‡ªå‹•èª¿åº¦"
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
-msgstr ""
+msgstr "這將刪除週期以åŠå…¶ä¸­çš„所有迭代。"
msgid "Iterations|This will remove the iteration from any issues that are assigned to it."
-msgstr ""
+msgstr "這將從分é…給它的任何議題中刪除迭代。"
msgid "Iterations|Title"
-msgstr ""
+msgstr "標題"
msgid "Iterations|To convert this cadence to automatic scheduling, add a duration and number of upcoming iterations. The upgrade is irreversible."
-msgstr ""
+msgstr "è¦å°‡æ­¤é€±æœŸè½‰æ›ç‚ºè‡ªå‹•èª¿åº¦ï¼Œè«‹å¢žåŠ æŒçºŒæ™‚é–“å’Œå³å°‡é€²è¡Œçš„迭代次數。該æ昇是ä¸å¯é€†çš„。"
msgid "Iterations|Unable to find iteration cadence."
-msgstr ""
+msgstr "無法找到迭代週期。"
msgid "Iterations|Unable to find iteration."
-msgstr ""
+msgstr "無法找到迭代。"
msgid "Iterations|Unable to save cadence. Please try again."
-msgstr ""
+msgstr "無法ä¿å­˜é€±æœŸï¼Œè«‹é‡è©¦ã€‚"
msgid "Iterations|Upcoming iterations"
-msgstr ""
+msgstr "å³å°‡åˆ°ä¾†çš„迭代"
msgid "Iterations|Your manual cadence can be converted to use automated scheduling"
-msgstr ""
+msgstr "您的手動週期å¯ä»¥è½‰æ›ç‚ºä½¿ç”¨è‡ªå‹•èª¿åº¦"
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
-msgstr ""
+msgstr "日期ä¸èƒ½èˆ‡è©²ç¾¤çµ„內的其它ç¾æœ‰è¿­ä»£é‡ç–Š"
msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence"
-msgstr ""
+msgstr "日期ä¸èƒ½èˆ‡æ­¤è¿­ä»£é€±æœŸå…§çš„其他ç¾æœ‰è¿­ä»£é‡ç–Š"
msgid "Iteration|cannot be more than 500 years in the future"
-msgstr ""
+msgstr "ä¸èƒ½è¶…éŽæœªä¾†çš„500å¹´"
msgid "Jan"
msgstr "1月"
msgid "January"
-msgstr ""
+msgstr "1月"
msgid "Japanese language support using"
-msgstr ""
+msgstr "支æ´ä½¿ç”¨æ—¥èªž"
msgid "Jira display name"
-msgstr ""
+msgstr "Jira顯示å稱"
msgid "Jira import is already running."
-msgstr ""
+msgstr "Jira匯入已在é‹è¡Œã€‚"
msgid "Jira integration not configured."
-msgstr ""
+msgstr "未設定Jiraæ•´åˆã€‚"
msgid "Jira project key is not configured."
-msgstr ""
+msgstr "未設定 Jira 專案金鑰。"
msgid "Jira project: %{importProject}"
-msgstr ""
+msgstr "Jira專案: %{importProject}"
msgid "Jira service not configured."
-msgstr ""
+msgstr "未設定Jiraæœå‹™ã€‚"
msgid "Jira user"
-msgstr ""
+msgstr "Jira使用者"
msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
-msgstr ""
+msgstr "已從設定的Jira實例中匯入了Jira使用者。å¯ä»¥é€šéŽå¾žã€Œ GitLab使用者åã€åˆ—的下拉列表中é¸æ“‡ä¸€å€‹GitLab使用者來映射它們。當表單出ç¾æ™‚,下拉èœå–®é è¨­ç‚ºåŸ·è¡ŒåŒ¯å…¥çš„使用者。"
msgid "Jira-GitLab user mapping template"
-msgstr ""
+msgstr "Jira-GitLab使用者å°æ‡‰ç¯„本"
msgid "JiraConnect|Cannot find namespace. Make sure you have sufficient permissions."
-msgstr ""
+msgstr "找ä¸åˆ°å‘½å空間,請確èªæ‚¨æœ‰è¶³å¤ çš„權é™ã€‚"
msgid "JiraConnect|Configure your Jira Connect Application ID."
-msgstr ""
+msgstr "設定您的 Jira Connect æ‡‰ç”¨ç¨‹åº ID。"
msgid "JiraConnect|Could not fetch user information from Jira. Check the permissions in Jira and try again."
-msgstr ""
+msgstr "無法從 Jira å–得使用者資訊,請檢查 Jira 中的權é™ä¸¦é‡è©¦ã€‚"
msgid "JiraConnect|Create branch for Jira issue %{jiraIssue}"
-msgstr ""
+msgstr "為Jira議題%{jiraIssue}建立分支"
msgid "JiraConnect|Failed to create branch."
-msgstr ""
+msgstr "建立分支失敗。"
msgid "JiraConnect|Failed to create branch. Please try again."
-msgstr ""
+msgstr "建立分支失敗。請é‡è©¦ã€‚"
msgid "JiraConnect|GitLab for Jira App"
-msgstr ""
+msgstr "é©ç”¨æ–¼ Jira 應用程åºçš„ GitLab"
msgid "JiraConnect|Jira Connect Application ID"
-msgstr ""
+msgstr "Jira Connect æ‡‰ç”¨ç¨‹åº ID"
msgid "JiraConnect|New branch was successfully created."
-msgstr ""
+msgstr "æˆåŠŸå»ºç«‹æ–°åˆ†æ”¯ã€‚"
msgid "JiraConnect|The Jira user is not a site administrator. Check the permissions in Jira and try again."
-msgstr ""
+msgstr "Jira 使用者éžç«™é»žç®¡ç†å“¡ï¼Œè«‹æª¢æŸ¥ Jira 中的權é™ä¸¦é‡è©¦ã€‚"
msgid "JiraConnect|You can now close this window and return to Jira."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é—œé–‰æ­¤çª—å£ä¸¦è¿”回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 "您無權為此專案建立分支。é¸æ“‡å…¶ä»–專案或è¯ç¹«å°ˆæ¡ˆæ‰€æœ‰è€…以å–å¾—å­˜å–權é™ã€‚ %{linkStart}瞭解更多。%{linkEnd}"
msgid "JiraRequest|A connection error occurred while connecting to Jira. Try your request again."
-msgstr ""
+msgstr "連接到 Jira 時發生連接錯誤。請您å†æ¬¡å˜—試請求。"
msgid "JiraRequest|A timeout error occurred while connecting to Jira. Try your request again."
-msgstr ""
+msgstr "連接到 Jira 時發生超時錯誤。請您å†æ¬¡å˜—試請求。"
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
-msgstr ""
+msgstr "連接到 Jira 時發生 SSL 錯誤: %{message}。å†æ¬¡å˜—試您的請求。"
msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
-msgstr ""
+msgstr "從 Jira 請求資料時發生錯誤。檢查您的%{docs_link_start} Jira æ•´åˆé…ç½®%{docs_link_end}並é‡è©¦ã€‚"
msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
-msgstr ""
+msgstr "從 Jira 請求資料時發生錯誤:%{messages}。檢查您的%{docs_link_start} Jira æ•´åˆè¨­å®š%{docs_link_end}並é‡è©¦ã€‚"
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
-msgstr ""
+msgstr "用於連接到 Jira çš„ Jira API URL 無效。檢查您的 Jira æ•´åˆ API URL,然後é‡è©¦ã€‚"
msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
-msgstr ""
+msgstr "å­˜å–Jira的憑證ä¸å…許存å–資料。%{docs_link_start}檢查您的Jiraæ•´åˆæ†‘è­‰%{docs_link_end},然後é‡è©¦ã€‚"
msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
-msgstr ""
+msgstr "å­˜å– Jira 的憑證無效。檢查您的 %{docs_link_start}Jira æ•´åˆæ†‘è­‰%{docs_link_end} 並é‡è©¦ã€‚"
msgid "JiraService| on branch %{branch_link}"
-msgstr ""
+msgstr "於分支%{branch_link}"
msgid "JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab."
-msgstr ""
+msgstr "%{jiraDocsLinkStart}啟用Jiraæ•´åˆ%{jiraDocsLinkEnd} ,在GitLab中查看您的Jira議題。"
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}啟用Jiraæ•´åˆ%{jira_docs_link_end}以在GitLab中查看您的Jira議題。"
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
-msgstr ""
+msgstr "%{user_link}在%{project_link}%{branch}中的%{entity_link}中æåŠæ­¤è­°é¡Œ: {quote}%{entity_message}{quote}"
msgid "JiraService|An error occurred while fetching issue list"
-msgstr ""
+msgstr "å–得議題列表時發生錯誤"
msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "自動將 Jira å•é¡Œè½‰æ›ç‚ºã€Œå®Œæˆã€é¡žåˆ¥ã€‚ %{linkStart}瞭解更多%{linkEnd}"
msgid "JiraService|Base URL of the Jira instance."
-msgstr ""
+msgstr "Jira 實例的基礎 URL。"
msgid "JiraService|Change GitLab version"
-msgstr ""
+msgstr "變更 GitLab 版本"
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
-msgstr ""
+msgstr "定義è¦å¾žæ¼æ´žå»ºç«‹çš„ Jira 議題的類型。"
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 "在啟用 GitLab 議題的åŒæ™‚顯示 Jira è­°é¡Œå¯èƒ½æœƒä»¤äººå›°æƒ‘。 如果ä¸ä½¿ç”¨ GitLab 議題,請考慮 %{gitlab_issues_link_start}åœç”¨ GitLab è­°é¡Œ%{link_end}。"
msgid "JiraService|Enable Jira issue creation from vulnerabilities"
-msgstr ""
+msgstr "啟用從æ¼æ´žå»ºç«‹ Jira è­°é¡Œ"
msgid "JiraService|Enable Jira issues"
-msgstr ""
+msgstr "啟用Jira議題"
msgid "JiraService|Enable Jira transitions"
-msgstr ""
+msgstr "啟用 Jira 轉æ›"
msgid "JiraService|Enter new password or API token"
-msgstr ""
+msgstr "輸入新密碼或 API 令牌"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
-msgstr ""
+msgstr "%{noteable_model_name} 事件已åœç”¨ã€‚"
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
-msgstr ""
+msgstr "無法載入 Jira 議題。在 Jira 中查看議題,或é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "JiraService|Fetch issue types for this Jira project"
-msgstr ""
+msgstr "å–å¾—æ­¤ Jira 專案的議題類型"
msgid "JiraService|For example, 12, 24"
-msgstr ""
+msgstr "例如12ã€24"
msgid "JiraService|For example, AB"
-msgstr ""
+msgstr "例如:AB"
msgid "JiraService|For example: https://gitlab.example.com"
-msgstr ""
+msgstr "例如:https://gitlab.example.com"
msgid "JiraService|GitLab for Jira Configuration"
-msgstr ""
+msgstr "用於 Jira é…置的 GitLab"
msgid "JiraService|GitLab instance URL"
-msgstr ""
+msgstr "GitLab 實例 URL"
msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
-msgstr ""
+msgstr "ID 必須是å¯ä»¥ç”¨ , 或 ; 分割的數字列表"
msgid "JiraService|If different from Web URL."
-msgstr ""
+msgstr "如果與 Web URL ä¸åŒã€‚"
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
-msgstr ""
+msgstr "由該專案中的æ¼æ´žå»ºç«‹çš„å•é¡Œå°‡æ˜¯ Jira å•é¡Œï¼Œå³ä½¿å•Ÿç”¨äº† GitLab å•é¡Œã€‚"
msgid "JiraService|Jira API URL"
-msgstr ""
+msgstr "Jira API URL"
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
-msgstr ""
+msgstr "Jira 評論是在æ交中引用議題時建立的。"
msgid "JiraService|Jira comments are created when an issue is referenced in a merge request."
-msgstr ""
+msgstr "Jira 評論是在åˆä½µè«‹æ±‚中引用議題時建立的。"
msgid "JiraService|Jira issues"
-msgstr ""
+msgstr "Jira議題"
msgid "JiraService|Jira project key"
-msgstr ""
+msgstr "Jira 專案金鑰"
msgid "JiraService|Leave blank to use your current password or API token."
-msgstr ""
+msgstr "留空以使用您當å‰çš„密碼或 API 令牌。"
msgid "JiraService|Move to Done"
-msgstr ""
+msgstr "移動到完æˆ"
msgid "JiraService|Open Jira"
-msgstr ""
+msgstr "打開Jira"
msgid "JiraService|Password or API token"
-msgstr ""
+msgstr "密碼或 API 令牌"
msgid "JiraService|Project key changed, refresh list"
-msgstr ""
+msgstr "專案金鑰已更改,é‡æ–°æ•´ç†åˆ—表"
msgid "JiraService|Project key is required to generate issue types"
-msgstr ""
+msgstr "需è¦å°ˆæ¡ˆé‡‘鑰以生æˆè­°é¡Œé¡žåž‹"
msgid "JiraService|Select issue type"
-msgstr ""
+msgstr "é¸æ“‡å•é¡Œé¡žåž‹"
msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
-msgstr ""
+msgstr "ä½¿ç”¨è½‰æ› ID 設定自訂最終狀態。 %{linkStart}çž­è§£è½‰æ› ID%{linkEnd}"
msgid "JiraService|Sign in to GitLab to link namespaces."
-msgstr ""
+msgstr "登入 GitLab 以連接命å空間。"
msgid "JiraService|Sign in to GitLab.com to get started."
-msgstr ""
+msgstr "登入並開始使用。"
msgid "JiraService|This feature requires a Premium plan."
-msgstr ""
+msgstr "此功能需è¦é«˜ç´šæ–¹æ¡ˆã€‚"
msgid "JiraService|Transition Jira issues to their final state:"
-msgstr ""
+msgstr "å°‡ Jira 議題轉æ›ç‚ºæœ€çµ‚狀態:"
msgid "JiraService|Use Jira as this project's issue tracker."
-msgstr ""
+msgstr "使用 Jira 作為此專案的議題追蹤器。"
msgid "JiraService|Use a password for server version and an API token for cloud version."
-msgstr ""
+msgstr "æœå‹™å™¨ç‰ˆæœ¬ä½¿ç”¨å¯†ç¢¼ï¼Œé›²ç‰ˆæœ¬ä½¿ç”¨ API 令牌。"
msgid "JiraService|Use a username for server version and an email for cloud version."
-msgstr ""
+msgstr "æœå‹™å™¨ç‰ˆæœ¬ä½¿ç”¨ä½¿ç”¨è€…å稱,雲版本使用電å­éƒµä»¶ã€‚"
msgid "JiraService|Use custom transitions"
-msgstr ""
+msgstr "使用自訂轉æ›"
msgid "JiraService|Username or Email"
-msgstr ""
+msgstr "使用者å稱或電å­éƒµä»¶"
msgid "JiraService|Using Jira for issue tracking?"
-msgstr ""
+msgstr "使用 Jira 追蹤å•é¡Œï¼Ÿ"
msgid "JiraService|Warning: All GitLab users with access to this GitLab project can view all issues from the Jira project you select."
-msgstr ""
+msgstr "警告:有權存å–æ­¤ GitLab 專案的所有 GitLab 用戶都å¯ä»¥æŸ¥çœ‹æ‚¨é¸æ“‡çš„ Jira 專案中的所有議題。"
msgid "JiraService|Web URL"
-msgstr ""
+msgstr "Web URL"
msgid "JiraService|Welcome to GitLab for Jira"
-msgstr ""
+msgstr "歡迎來到 Jira 的 GitLab"
msgid "JiraService|What version of GitLab are you using?"
-msgstr ""
+msgstr "你使用的是什麼版本的 GitLab?"
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 "在æ交或åˆä½µè«‹æ±‚中æåŠ Jira 議題時,將建立é ç¨‹éˆæŽ¥å’Œè©•è«–(如果啟用)。"
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 "在ä¸é›¢é–‹ GitLab 的情æ³ä¸‹è™•ç† Jira 議題。加入一個 Jira èœå–®ï¼Œå­˜å–您的 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 "在ä¸é›¢é–‹ GitLab 的情æ³ä¸‹è™•ç† Jira 議題。加入 Jira èœå–®ï¼Œå­˜å– Jira 議題的唯讀列表。%{jira_issues_link_start}瞭解更多。%{link_end}"
msgid "JiraService|You can now close this window and%{br}return to the GitLab for Jira application."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é—œé–‰æ­¤çª—å£ä¸¦%{br}返回到 GitLab for Jira 應用程å¼ã€‚"
msgid "JiraService|You must configure Jira before enabling this integration. %{jira_doc_link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "您必須在啟用此整åˆä¹‹å‰è¨­å®š Jira。%{jira_doc_link_start}瞭解更多。%{link_end}"
msgid "Job"
msgstr "作業"
msgid "Job %{jobName}"
-msgstr ""
+msgstr "作業 %{jobName}"
msgid "Job Failed #%{build_id}"
-msgstr ""
+msgstr "作業 #%{build_id} 已失敗 "
msgid "Job has been erased"
-msgstr ""
+msgstr "作業已被刪除"
msgid "Job has been successfully erased!"
-msgstr ""
+msgstr "作業已æˆåŠŸåˆªé™¤!"
msgid "Job has wrong arguments format."
-msgstr ""
+msgstr "作業的åƒæ•¸æ ¼å¼éŒ¯èª¤ã€‚"
msgid "Job is missing the `model_type` argument."
-msgstr ""
+msgstr "作業缺少 `model_type` åƒæ•¸ã€‚"
msgid "Job is stuck. Check runners."
-msgstr ""
+msgstr "作業已阻塞。請檢查Runner。"
msgid "Job logs and artifacts"
-msgstr ""
+msgstr "作業日誌和產物"
msgid "Job to create self-monitoring project is in progress"
-msgstr ""
+msgstr "建立自我監控專案的作業正在執行"
msgid "Job to delete self-monitoring project is in progress"
-msgstr ""
+msgstr "刪除自我監控專案的作業正在執行"
msgid "Job was retried"
-msgstr ""
+msgstr "作業已é‡è©¦"
msgid "Jobs"
-msgstr ""
+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 ""
+msgstr "如果作業é‹è¡Œæ™‚間超éŽé€¾æ™‚時間,則作業將失敗。é è¨­æƒ…æ³ä¸‹ï¼Œè¼¸å…¥å€¼ä»¥ç§’為單ä½ã€‚也接å—å¯è®€çš„輸入,例如 %{code_open}1 å°æ™‚%{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 "早於設定時間的作業被視為已éŽæœŸä¸¦å·²å­˜æª”。無法å†é‡è©¦å­˜æª”的作業。留空以從ä¸è‡ªå‹•å­˜æª”作業。é è¨­å–®ä½æ˜¯å¤©ï¼Œä½†æ‚¨å¯ä»¥ä½¿ç”¨å…¶ä»–å–®ä½ï¼Œä¾‹å¦‚ %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}。最å°å€¼ç‚º 1 天。"
msgid "Jobs|All"
-msgstr ""
+msgstr "全部"
msgid "Jobs|An error occurred while loading the Failed Jobs tab."
-msgstr ""
+msgstr "載入失敗的作業é æ™‚發生錯誤。"
msgid "Jobs|Are you sure you want to proceed?"
-msgstr ""
+msgstr "確定è¦ç¹¼çºŒå—Ž?"
msgid "Jobs|Are you sure you want to retry this job?"
-msgstr ""
+msgstr "您確定è¦é‡è©¦æ­¤ä½œæ¥­å—Žï¼Ÿ"
msgid "Jobs|Create CI/CD configuration file"
-msgstr ""
+msgstr "建立CI/CDé…置文件"
msgid "Jobs|Filter jobs"
-msgstr ""
+msgstr "éŽæ¿¾ä½œæ¥­"
msgid "Jobs|Finished"
-msgstr ""
+msgstr "已完æˆ"
msgid "Jobs|Job is stuck. Check runners."
-msgstr ""
+msgstr "作業已阻塞。請檢查執行器(Runner)。"
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 "作業(Job)是GitLab CI/CDæµæ°´ç·šçš„基本組æˆéƒ¨åˆ†ã€‚æ¯å€‹ä½œæ¥­éƒ½æœ‰ä¸€å€‹ç‰¹å®šçš„任務,例如測試程å¼ç¢¼ã€‚ è‹¥è¦åœ¨CI/CDæµæ°´ç·šä¸­è¨­å®šJob,請在您的專案中加入一個CI/CD組態設定文件。"
msgid "Jobs|No jobs to show"
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„作業"
msgid "Jobs|Raw text search is not currently supported for the jobs filtered search feature. Please use the available search tokens."
-msgstr ""
+msgstr "å°ä»»å‹™éŽæ¿¾å¾Œçš„æœå°‹åŠŸèƒ½ï¼Œç•¶å‰ä¸æ”¯æ´æœå°‹åŽŸå§‹æ–‡æœ¬ã€‚請使用å¯ç”¨çš„æœå°‹ä»¤ç‰Œã€‚"
msgid "Jobs|Status"
-msgstr ""
+msgstr "狀態"
msgid "Jobs|There was a problem fetching the failed jobs."
-msgstr ""
+msgstr "讀å–失敗的作業時出ç¾å•é¡Œã€‚"
msgid "Jobs|Use jobs to automate your tasks"
-msgstr ""
+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 ""
+msgstr "ä½ å³å°‡é‡è©¦ä¸€å€‹ä½œæ¥­ï¼Œæ­¤ä½œæ¥­å› è©¦åœ–部署舊的程å¼ç¢¼è€Œå¤±æ•—。 é‡è©¦æ­¤ä»»å‹™å¯èƒ½å°Žè‡´ç”¨èˆŠç‰ˆæœ¬ä¾†æºç¨‹å¼ç¢¼è¦†è“‹ç’°å¢ƒã€‚"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id}"
-msgstr ""
+msgstr "%{boldStart}æµæ°´ç·š%{boldEnd} %{id}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source}"
-msgstr ""
+msgstr "å°æ–¼å…·æœ‰ %{source} çš„ %{mrId} çš„ %{boldStart}æµæ°´ç·š%{boldEnd} %{id}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{mrId} with %{source} into %{target}"
-msgstr ""
+msgstr "å°æ–¼å¾ž %{source} 到 %{target} çš„ %{mrId} çš„ %{boldStart}æµæ°´ç·š%{boldEnd} %{id}"
msgid "Job|%{boldStart}Pipeline%{boldEnd} %{id} for %{ref}"
-msgstr ""
+msgstr "å°æ–¼ %{ref} çš„ %{boldStart}æµæ°´ç·š%{boldEnd} %{id}"
msgid "Job|%{searchLength} results found for %{searchTerm}"
-msgstr ""
+msgstr "ä¾æ“š %{searchTerm} 找到 %{searchLength} 個çµæžœ"
msgid "Job|Are you sure you want to erase this job log and artifacts?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤ä½œæ¥­æ—¥èªŒå’Œç”¢ç‰©å—Žï¼Ÿ"
msgid "Job|Browse"
-msgstr ""
+msgstr "ç€è¦½"
msgid "Job|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Job|Canceled"
-msgstr ""
+msgstr "å·²å–消"
msgid "Job|Complete Raw"
-msgstr ""
+msgstr "完整原始日誌"
msgid "Job|Created"
-msgstr ""
+msgstr "已建立"
msgid "Job|Download"
-msgstr ""
+msgstr "下載"
msgid "Job|Erase job log and artifacts"
-msgstr ""
+msgstr "擦除作業日誌和產物"
msgid "Job|Failed"
-msgstr ""
+msgstr "失敗"
msgid "Job|Finished at"
-msgstr ""
+msgstr "完æˆæ–¼"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "作業產物"
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "作業已被刪除"
msgid "Job|Job has been erased by %{userLink}"
-msgstr ""
+msgstr "作業已被 %{userLink} 刪除"
msgid "Job|Job log search"
-msgstr ""
+msgstr "工作日誌æœå°‹"
msgid "Job|Keep"
-msgstr ""
+msgstr "ä¿æŒ"
msgid "Job|Manual"
-msgstr ""
+msgstr "手動"
msgid "Job|No search results found"
-msgstr ""
+msgstr "沒有æœå°‹çµæžœ"
msgid "Job|Passed"
-msgstr ""
+msgstr "已通éŽ"
msgid "Job|Pending"
-msgstr ""
+msgstr "等待中"
msgid "Job|Preparing"
-msgstr ""
+msgstr "正在準備"
msgid "Job|Retry"
-msgstr ""
+msgstr "é‡è©¦"
msgid "Job|Running"
-msgstr ""
+msgstr "執行中"
msgid "Job|Scheduled"
-msgstr ""
+msgstr "已計劃"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "滾動到底部"
+
+msgid "Job|Scroll to next failure"
+msgstr "滾動到下一個失敗"
msgid "Job|Scroll to top"
-msgstr ""
+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 ""
+msgstr "在您的作業日誌輸出中æœå°‹å­å­—符串,目å‰åƒ…支æ´å¯è¦‹çš„作業日誌輸出æœå°‹ï¼Œä¸æ”¯æ´å› å¤§å°è€Œè¢«æˆªæ–·çš„任何日誌輸出。"
msgid "Job|Search job log"
-msgstr ""
+msgstr "æœå°‹å·¥ä½œæ—¥èªŒ"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "顯示完整æº"
msgid "Job|Skipped"
-msgstr ""
+msgstr "已跳éŽ"
msgid "Job|Status"
-msgstr ""
+msgstr "狀態"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "作業產物已被刪除"
msgid "Job|The artifacts will be removed"
-msgstr ""
+msgstr "產物將被刪除"
msgid "Job|There was a problem retrying the failed job."
-msgstr ""
+msgstr "é‡è©¦å¤±æ•—的作業時出ç¾å•é¡Œã€‚"
msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
-msgstr ""
+msgstr "這些產物為當å‰æœ€æ–°ã€‚在更新的產物å¯ç”¨ä¹‹å‰ï¼Œé€™äº›ç”¢ç‰©å°‡ä¸æœƒè¢«åˆªé™¤(å³ä½¿å·²éŽæœŸ)。"
msgid "Job|This job failed because the necessary resources were not successfully created."
-msgstr ""
+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 "由於以下å•é¡Œä¹‹ä¸€ï¼Œæ­¤ä½œæ¥­è¢«å¡ä½ã€‚沒有線上啟用的執行器,沒有該%{linkStart}å—ä¿è­·åˆ†æ”¯%{linkEnd}的執行器,或者沒有符åˆæ‰€æœ‰ä½œæ¥­æ¨™ç±¤çš„執行器:"
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "此作業已阻塞,因為該項目沒有分é…任何å¯ç”¨Runner。"
msgid "Job|This job is stuck because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "作業|此作業被å¡ä½äº†ï¼Œå› ç‚ºæ‚¨æ²’有任何啟用的執行器å¯ä»¥é‹è¡Œæ­¤ä½œæ¥­ã€‚"
msgid "Job|Waiting for resource"
-msgstr ""
+msgstr "等待資æº"
msgid "Job|We could not find this element"
-msgstr ""
+msgstr "找ä¸åˆ°è©²å…ƒä»¶"
msgid "Job|allowed to fail"
-msgstr ""
+msgstr "å…許失敗"
msgid "Job|delayed"
-msgstr ""
+msgstr "延é²"
msgid "Job|manual"
-msgstr ""
+msgstr "手動"
msgid "Job|triggered"
-msgstr ""
+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 ""
+msgstr "加入Zoom會議"
msgid "Join a project"
-msgstr ""
+msgstr "加入專案"
msgid "Join your team on GitLab and contribute to an existing project"
-msgstr ""
+msgstr "加入您的 GitLab 團隊,並為ç¾æœ‰å°ˆæ¡ˆåšå‡ºè²¢ç»"
msgid "Joined %{time_ago}"
-msgstr ""
+msgstr "加入於%{time_ago}"
msgid "Joined %{user_created_time}"
-msgstr ""
+msgstr "加入於%{user_created_time}"
msgid "Joined projects (%{projects_count})"
-msgstr ""
+msgstr "已加入的專案 (%{projects_count})"
msgid "Jul"
msgstr "7月"
@@ -22412,1053 +22583,1092 @@ msgid "June"
msgstr "6月"
msgid "Just me"
-msgstr ""
+msgstr "åªæœ‰æˆ‘"
msgid "K8s pod health"
-msgstr ""
+msgstr "K8s pod å¥åº·"
msgid "KEY"
-msgstr ""
+msgstr "金鑰"
msgid "Keep"
-msgstr ""
+msgstr "ä¿æŒ"
msgid "Keep artifacts from most recent successful jobs"
-msgstr ""
+msgstr "ä¿ç•™æœ€è¿‘æˆåŠŸä½œæ¥­çš„產物"
msgid "Keep divergent refs"
-msgstr ""
+msgstr "ä¿ç•™åˆ†å‰çš„refs"
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 "ä¿æŒæ‰€æœ‰ SAST 分æžå™¨å·²å•Ÿç”¨ï¼Œä»¥ç¢ºä¿å°ˆæ¡ˆåœ¨ä»¥å¾ŒåŠ å…¥æ–°èªžè¨€æ™‚ä¸æœƒéŽæ™‚。確定應用哪些分æžå™¨æ˜¯ä¸€å€‹æ¶ˆè€—最少資æºä¸¦ç‚ºæµæ°´ç·šå¢žåŠ æœ€å°‘時間的éŽç¨‹ã€‚啟用所有 SAST 分æžå™¨å¯ç¢ºä¿æœ€å¤§è¦†è“‹ç¯„åœã€‚"
msgid "Kerberos access denied"
-msgstr ""
+msgstr "Kerberoså­˜å–被拒絕"
msgid "Key"
msgstr "金鑰"
msgid "Key (PEM)"
-msgstr ""
+msgstr "金鑰 (PEM)"
-msgid "Key: %{key}"
-msgstr ""
+msgid "Key:"
+msgstr "金鑰:"
msgid "Keyboard shortcuts"
-msgstr ""
+msgstr "å¿«æ·éµ"
msgid "KeyboardKey|Alt"
-msgstr ""
+msgstr "Alt"
msgid "KeyboardKey|Ctrl"
-msgstr ""
+msgstr "Ctrl"
msgid "KeyboardKey|Ctrl+"
-msgstr ""
+msgstr "Ctrl +"
msgid "KeyboardKey|Enter"
-msgstr ""
+msgstr "Enter"
msgid "KeyboardKey|Esc"
-msgstr ""
+msgstr "Esc"
msgid "KeyboardKey|Shift"
-msgstr ""
+msgstr "Shift"
msgid "KeyboardShortcuts|No shortcuts matched your search"
-msgstr ""
+msgstr "沒有與您的æœå°‹åŒ¹é…çš„å¿«æ·éµ"
msgid "KeyboardShortcuts|Search keyboard shortcuts"
-msgstr ""
+msgstr "æœå°‹éµç›¤å¿«æ·éµ"
msgid "Keys"
-msgstr ""
+msgstr "éµ"
msgid "Ki"
-msgstr ""
+msgstr "Ki"
msgid "Kroki"
-msgstr ""
+msgstr "Kroki"
msgid "Kubernetes"
-msgstr ""
+msgstr "Kubernetes"
msgid "Kubernetes Cluster"
-msgstr ""
+msgstr "Kuberneteså¢é›†"
msgid "Kubernetes Clusters"
-msgstr ""
+msgstr "Kuberneteså¢é›†"
msgid "Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes å¢é›†"
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
-msgstr ""
+msgstr "Kuberneteså¢é›†å»ºç«‹æ™‚間超éŽè¶…時; %{timeout}"
msgid "Kubernetes cluster integration and resources are being removed."
-msgstr ""
+msgstr "Kuberneteså¢é›†æ•´åˆå’Œè³‡æºæ­£åœ¨è¢«åˆªé™¤ã€‚"
msgid "Kubernetes cluster integration was successfully removed."
-msgstr ""
+msgstr "Kuberneteså¢é›†æ•´åˆå·²æˆåŠŸåˆªé™¤ã€‚"
msgid "Kubernetes cluster was successfully updated."
-msgstr ""
+msgstr "Kuberneteså¢é›†å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Kubernetes clusters"
-msgstr ""
+msgstr "Kubernetes å¢é›†"
msgid "Kubernetes deployment not found"
-msgstr ""
+msgstr "找ä¸åˆ°Kubernetes部署"
msgid "Kubernetes error: %{error_code}"
-msgstr ""
+msgstr "Kubinentes 錯誤: %{error_code}"
msgid "LDAP"
-msgstr ""
+msgstr "LDAP"
msgid "LDAP Synchronization"
-msgstr ""
+msgstr "LDAPåŒæ­¥"
msgid "LDAP group settings"
-msgstr ""
+msgstr "LDAP組設定"
msgid "LDAP settings"
-msgstr ""
+msgstr "LDAP 設定"
msgid "LDAP settings updated"
-msgstr ""
+msgstr "LDAP設定已更新"
msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
-msgstr ""
+msgstr "LDAPåŒæ­¥æ­£åœ¨é€²è¡Œä¸­ã€‚æ­¤éŽç¨‹å¯èƒ½éœ€è¦å¹¾åˆ†é˜ã€‚è«‹é‡æ–°æ•´ç†é é¢ä»¥æŸ¥çœ‹æ›´æ”¹ã€‚"
msgid "LDAP synchronizations"
-msgstr ""
+msgstr "LDAPåŒæ­¥"
msgid "LDAP uid:"
-msgstr ""
+msgstr "LDAP uid:"
msgid "LFS"
msgstr "LFS"
msgid "LFS objects"
-msgstr ""
+msgstr "LFS å°åƒ"
msgid "LFSStatus|Disabled"
-msgstr ""
+msgstr "åœç”¨"
msgid "LFSStatus|Enabled"
-msgstr ""
+msgstr "啟用"
msgid "LICENSE"
-msgstr ""
+msgstr "授權æ¢æ¬¾"
msgid "Label"
-msgstr ""
+msgstr "標記"
msgid "Label actions dropdown"
-msgstr ""
+msgstr "標記æ“作下拉é¸å–®"
msgid "Label added: %{labels}"
msgid_plural "Labels added: %{labels}"
-msgstr[0] ""
+msgstr[0] "增加的標籤: %{labels}"
msgid "Label priority"
-msgstr ""
+msgstr "標記優先級"
msgid "Label was created"
-msgstr ""
+msgstr "標記已建立"
msgid "Label was removed"
-msgstr ""
+msgstr "標記已刪除"
msgid "Label was successfully updated."
-msgstr ""
+msgstr "標記已更新。"
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
-msgstr ""
+msgstr "%{firstLabelName} +%{remainingLabelCount} 更多"
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
-msgstr ""
+msgstr "%{labelsString}和 %{remainingLabelCount} 更多"
msgid "LabelSelect|Labels"
-msgstr ""
+msgstr "標記"
msgid "Labels"
-msgstr ""
+msgstr "標記"
msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
-msgstr ""
+msgstr "標記å¯ä»¥æ‡‰ç”¨æ–¼ %{features}。群組標記å¯ç”¨æ–¼ç¾¤çµ„中的所有專案。"
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "標記å¯ç”¨æ–¼å°è­°é¡Œå’Œåˆä½µè«‹æ±‚進行分類。"
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "標記å¯ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚。"
msgid "Labels with no issues in this iteration:"
-msgstr ""
+msgstr "此迭代中沒有議題的標記:"
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
-msgstr ""
+msgstr "%{spanStart}將標記%{spanEnd}%{labelTitle}%{spanStart}å‡ç´šç‚ºç¾¤çµ„標記?%{spanEnd}"
msgid "Labels|Promote Label"
-msgstr ""
+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 ""
+msgstr "å‡ç´š%{labelTitle}將使其å¯ç”¨æ–¼%{groupName}內的所有專案。ç¾æœ‰çš„åŒå專案標記將被åˆä½µã€‚ç¾æœ‰çš„åŒå群組標記也將被åˆä½µã€‚該æ“作ä¸å¯æ’¤éŠ·ã€‚"
msgid "Language"
-msgstr ""
+msgstr "語言"
msgid "Language type"
-msgstr ""
+msgstr "語言類型"
msgid "Large File Storage"
-msgstr ""
+msgstr "大型檔案儲存 (LFS)"
msgid "Last %d day"
msgid_plural "Last %d days"
-msgstr[0] ""
+msgstr[0] "最近 %d 天"
msgid "Last %{days} days"
-msgstr ""
+msgstr "最近%{days}天"
msgid "Last 2 weeks"
-msgstr ""
+msgstr "最近2週"
msgid "Last 30 days"
-msgstr ""
+msgstr "最近 30 天"
msgid "Last 60 days"
-msgstr ""
+msgstr "最近 60 天"
msgid "Last 90 days"
-msgstr ""
+msgstr "最近 90 天"
msgid "Last Accessed On"
-msgstr ""
+msgstr "最後存å–æ–¼"
msgid "Last Activity"
-msgstr ""
+msgstr "最近活動"
msgid "Last Name"
-msgstr ""
+msgstr "姓"
msgid "Last Pipeline"
-msgstr ""
+msgstr "最新æµæ°´ç·š"
msgid "Last Seen"
-msgstr ""
+msgstr "最後出ç¾"
msgid "Last Sync"
-msgstr ""
+msgstr "最近åŒæ­¥"
msgid "Last Used"
-msgstr ""
+msgstr "最近使用"
msgid "Last accessed on"
-msgstr ""
+msgstr "最後存å–時間"
msgid "Last activity"
-msgstr ""
+msgstr "上次活動"
msgid "Last commit"
-msgstr ""
+msgstr "最後æ交"
msgid "Last contact"
-msgstr ""
+msgstr "最後è¯çµ¡"
msgid "Last edited %{date}"
-msgstr ""
+msgstr "最後修改於%{date}"
msgid "Last edited by %{link_start}%{avatar} %{name}%{link_end}"
-msgstr ""
+msgstr "最後一次由 %{link_start}%{avatar} %{name}%{link_end} 編輯"
msgid "Last event"
-msgstr ""
+msgstr "最近一次事件"
msgid "Last item before this page loaded in your browser:"
-msgstr ""
+msgstr "在此é é¢è¼‰å…¥ä¹‹å‰çš„最後一個專案:"
msgid "Last modified"
-msgstr ""
+msgstr "最近修改"
msgid "Last month"
-msgstr ""
+msgstr "上個月"
msgid "Last name"
-msgstr ""
+msgstr "姓"
msgid "Last reply by"
-msgstr ""
+msgstr "最後回復來自於"
msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
-msgstr ""
+msgstr "最後一次版本庫檢查(%{last_check_timestamp})失敗。請查看'repocheck.log'文件以å–得錯誤消æ¯ã€‚"
msgid "Last seen"
-msgstr ""
+msgstr "最後出ç¾"
msgid "Last sign-in"
-msgstr ""
+msgstr "上次登入"
msgid "Last sign-in IP:"
-msgstr ""
+msgstr "上次登入IP:"
msgid "Last sign-in at:"
-msgstr ""
-
-msgid "Last successful sync"
-msgstr ""
+msgstr "上次登入於:"
msgid "Last successful update"
-msgstr ""
-
-msgid "Last time checked"
-msgstr ""
+msgstr "最近æˆåŠŸçš„æ›´æ–°"
msgid "Last time verified"
-msgstr ""
+msgstr "最近一次驗證"
msgid "Last update"
-msgstr ""
+msgstr "最後更新"
msgid "Last update attempt"
-msgstr ""
+msgstr "上次更新嘗試"
msgid "Last updated"
-msgstr ""
+msgstr "最近更新"
msgid "Last updated %{time} ago"
-msgstr ""
+msgstr "最後更新於 %{time} å‰"
msgid "Last used"
-msgstr ""
+msgstr "最後使用"
msgid "Last used %{last_used_at} ago"
-msgstr ""
+msgstr "最後使用 %{last_used_at} 之å‰"
msgid "Last used on:"
-msgstr ""
+msgstr "上次使用於:"
msgid "Last week"
-msgstr ""
+msgstr "上星期"
msgid "Last year"
-msgstr ""
+msgstr "去年"
msgid "LastCommit|authored"
-msgstr ""
+msgstr "編輯於"
msgid "LastPushEvent|You pushed to"
-msgstr ""
+msgstr "您推é€äº†"
msgid "LastPushEvent|at"
-msgstr ""
+msgstr "æ–¼"
msgid "Latest changes"
-msgstr ""
+msgstr "最新變更"
msgid "Latest pipeline for the most recent commit on this branch"
-msgstr ""
+msgstr "此分支上最近æ交的最新æµæ°´ç·š"
msgid "Launch a ready-to-code development environment for your project."
-msgstr ""
+msgstr "為您的專案啟動一個ç¾æˆçš„程å¼ç¢¼é–‹ç™¼ç’°å¢ƒã€‚"
msgid "Layout|Fixed"
-msgstr ""
+msgstr "固定"
msgid "Layout|Fluid"
-msgstr ""
+msgstr "æµå‹•"
msgid "Lead Time"
-msgstr ""
+msgstr "å‰ç½®æ™‚é–“"
msgid "Lead Time for Changes"
-msgstr ""
+msgstr "變更å‰ç½®æ™‚é–“"
msgid "Lead time"
-msgstr ""
+msgstr "å‰ç½®æ™‚é–“"
msgid "Learn GitLab"
-msgstr ""
+msgstr "學習GitLab"
msgid "Learn GitLab - Ultimate trial"
-msgstr ""
+msgstr "學習 GitLab - 旗艦版試用"
msgid "Learn More"
-msgstr ""
+msgstr "瞭解更多"
msgid "Learn More."
-msgstr ""
+msgstr "瞭解更多。"
msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
-msgstr ""
+msgstr "了解如何 %{link_start}è²¢ç»åˆ°å…§å»ºçš„範本%{link_end}"
msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
-msgstr ""
+msgstr "了解GitLab如何 %{no_packages_link_start}發布和共享您的包%{no_packages_link_end}。"
msgid "Learn more"
-msgstr ""
+msgstr "進一步了解"
msgid "Learn more about %{username}"
-msgstr ""
+msgstr "進一步了解%{username}"
msgid "Learn more about Auto DevOps"
-msgstr ""
+msgstr "了解更多關於Auto DevOps"
msgid "Learn more about GitLab"
-msgstr ""
+msgstr "進一步了解 GitLab"
msgid "Learn more about Needs relationships"
-msgstr ""
+msgstr "了解更多關於Needs關係的資訊"
msgid "Learn more about Web Terminal"
-msgstr ""
+msgstr "了解更多關於 Web 終端"
msgid "Learn more about X.509 signed commits"
-msgstr ""
+msgstr "了解更多關於X.509ç°½åæ交"
msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
-msgstr ""
+msgstr "é€éŽ%{docs_link_start}GitLab Pages上的文件%{docs_link_end}了解更多關於å‘專案加入憑證的資訊。"
msgid "Learn more about custom project templates"
-msgstr ""
+msgstr "了解更多關於自訂專案範本"
msgid "Learn more about deploying to AWS"
-msgstr ""
+msgstr "了解更多有關部署到AWS的資訊"
msgid "Learn more about deploying to a cluster"
-msgstr ""
+msgstr "了解有關部署到å¢é›†çš„詳細資訊"
msgid "Learn more about group-level project templates"
-msgstr ""
+msgstr "了解更多關於群組級專案範本"
msgid "Learn more about groups."
-msgstr ""
+msgstr "了解關於群組的更多資訊。"
msgid "Learn more about max seats used"
-msgstr ""
+msgstr "了解更多關於最大席ä½æ•¸çš„資訊"
msgid "Learn more about seats owed"
-msgstr ""
+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 "在 %{configuration_link_start}進階æœå°‹è¨­å®š%{configuration_link_end} 中了解更多關於切片和副本的訊æ¯ï¼Œç›´åˆ°æ‚¨ %{recreated_link_start}é‡æ–°å»ºç«‹%{recreated_link_end} 索引,æ‰èƒ½é€²è¡Œæ›´æ”¹ã€‚"
msgid "Learn more about signing commits"
-msgstr ""
+msgstr "了解更多有關簽åæ交的詳細訊æ¯"
msgid "Learn more in the"
-msgstr ""
+msgstr "了解更多"
msgid "Learn more."
-msgstr ""
+msgstr "了解更多。"
msgid "LearnGitLab|%{percentage}%{percentSymbol} completed"
-msgstr ""
+msgstr "%{percentage}%{percentSymbol} 已完æˆ"
msgid "LearnGitLab|Add code owners"
-msgstr ""
+msgstr "加入程å¼ç¢¼æ‰€æœ‰è€…"
msgid "LearnGitLab|Analyze your application for vulnerabilities with DAST"
-msgstr ""
+msgstr "使用 DAST 分æžæ‚¨çš„應用程å¼æ¼æ´ž"
msgid "LearnGitLab|Complete these tasks first so you can enjoy GitLab's features to their fullest:"
-msgstr ""
+msgstr "首先完æˆé€™äº›ä»»å‹™ï¼Œä»¥ä¾¿æ‚¨å¯ä»¥å……åˆ†äº«å— GitLab 的功能:"
msgid "LearnGitLab|Create a repository"
-msgstr ""
+msgstr "建立一個版本庫"
msgid "LearnGitLab|Create a workflow for your new workspace, and learn how GitLab features work together:"
-msgstr ""
+msgstr "為您的新工作å€å»ºç«‹å·¥ä½œæµï¼Œä¸¦äº†è§£ GitLab 功能如何å”åŒå·¥ä½œï¼š"
msgid "LearnGitLab|Create an issue"
-msgstr ""
+msgstr "建立議題"
msgid "LearnGitLab|Create or import your first repository into your new project."
-msgstr ""
+msgstr "建立或匯入您的第一個版本庫到您的新專案中。"
msgid "LearnGitLab|Create/import issues (tickets) to collaborate on ideas and plan work."
-msgstr ""
+msgstr "建立/匯入議題(工單)以å”åŒå‰µæ„和工作計劃。"
msgid "LearnGitLab|Deploy"
-msgstr ""
+msgstr "部署"
msgid "LearnGitLab|Enable require merge approvals"
-msgstr ""
+msgstr "啟用需è¦åˆä½µæ ¸å‡†"
msgid "LearnGitLab|GitLab works best as a team. Invite your colleague to enjoy all features."
-msgstr ""
+msgstr "GitLab 團隊工作上佳。邀請您的åŒäº‹äº«å—所有功能。"
msgid "LearnGitLab|Invite your colleagues"
-msgstr ""
+msgstr "邀請你的åŒäº‹"
msgid "LearnGitLab|Learn GitLab"
-msgstr ""
+msgstr "學習 GitLab"
msgid "LearnGitLab|Plan and execute"
-msgstr ""
+msgstr "計劃和執行"
msgid "LearnGitLab|Prevent unexpected changes to important assets by assigning ownership of files and paths."
-msgstr ""
+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 ""
+msgstr "準備好開始使用 GitLab 了嗎?按照以下步驟設定您的工作å€ã€è¨ˆåŠƒå’Œæ交更改以åŠéƒ¨ç½²æ‚¨çš„專案。"
msgid "LearnGitLab|Review and edit proposed changes to source code."
-msgstr ""
+msgstr "審核和編輯å°ä¾†æºç¨‹å¼ç¢¼çš„æ議更改。"
msgid "LearnGitLab|Route code reviews to the right reviewers, every time."
-msgstr ""
+msgstr "æ¯æ¬¡éƒ½å°‡ç¨‹å¼ç¢¼è©•å¯©å‚³éžçµ¦åˆé©çš„審核者。"
msgid "LearnGitLab|Run a Security scan using CI/CD"
-msgstr ""
+msgstr "使用 CI/CD é‹è¡Œå®‰å…¨æŽƒæ"
msgid "LearnGitLab|Save time by automating your integration and deployment tasks."
-msgstr ""
+msgstr "通éŽè‡ªå‹•åŒ–您的整åˆå’Œéƒ¨ç½²ä»»å‹™ä¾†ç¯€çœæ™‚間。"
msgid "LearnGitLab|Scan dependencies for licenses"
-msgstr ""
+msgstr "掃æ許å¯è­‰ä¾è³´é …"
msgid "LearnGitLab|Scan dependencies for vulnerabilities"
-msgstr ""
+msgstr "掃ææ¼æ´žä¾è³´é …"
msgid "LearnGitLab|Scan your code to uncover vulnerabilities before deploying."
-msgstr ""
+msgstr "在部署之å‰æŽƒæ您的程å¼ç¢¼ä»¥ç™¼ç¾æ¼æ´žã€‚"
msgid "LearnGitLab|Set up CI/CD"
-msgstr ""
+msgstr "設定 CI/CD"
msgid "LearnGitLab|Set up your first project's CI/CD"
-msgstr ""
+msgstr "設定您第一個專案的CI/CD"
msgid "LearnGitLab|Set up your workspace"
-msgstr ""
+msgstr "設定您的工作å€"
msgid "LearnGitLab|Start a free trial of GitLab Ultimate"
-msgstr ""
+msgstr "開始å…費試用 GitLab 旗艦版"
msgid "LearnGitLab|Submit a merge request (MR)"
-msgstr ""
+msgstr "æ交åˆä½µè«‹æ±‚ (MR)"
msgid "LearnGitLab|Try GitLab Ultimate for free"
-msgstr ""
+msgstr "å…費試用旗艦版"
msgid "LearnGitLab|Try all GitLab features for 30 days, no credit card required."
-msgstr ""
+msgstr "試用所有 GitLab 功能 30 天,無需信用å¡ã€‚"
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
-msgstr ""
+msgstr "使用您的新 GitLab 工作æµç¨‹éƒ¨ç½²æ‚¨çš„應用程å¼ã€ç›£æŽ§å…¶é‹è¡Œç‹€æ³ä¸¦ç¢ºä¿å…¶å®‰å…¨ï¼š"
msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
-msgstr ""
+msgstr "您的團隊正在æˆé•·ï¼æ‚¨å·²æˆåŠŸåœ°é‚€è«‹äº†æ–°çš„團隊æˆå“¡åˆ° %{projectName} 專案。"
msgid "LearnGitlab|- Included in trial"
-msgstr ""
+msgstr "- 包å«åœ¨è©¦ç”¨å…§"
msgid "LearnGitlab|Contact your administrator to start a free Ultimate trial."
-msgstr ""
+msgstr "è«‹è¯ç¹«æ‚¨çš„管ç†å“¡ä»¥é–‹å§‹å…費的 Ultimate 試用。"
msgid "LearnGitlab|Creating your onboarding experience..."
-msgstr ""
+msgstr "正在建立您的入門體驗..."
msgid "LearnGitlab|Ok, let's go"
-msgstr ""
+msgstr "好的,讓我們繼續"
msgid "LearnGitlab|View administrator list"
-msgstr ""
+msgstr "查看管ç†è€…列表"
msgid "Leave"
-msgstr ""
+msgstr "退出"
msgid "Leave Admin Mode"
-msgstr ""
+msgstr "退出管ç†å“¡æ¨¡å¼"
msgid "Leave edit mode? All unsaved changes will be lost."
-msgstr ""
+msgstr "退出編輯模å¼ï¼Ÿæ‰€æœ‰æœªå„²å­˜çš„變更都將éºå¤±ã€‚"
msgid "Leave group"
-msgstr ""
+msgstr "退出群組"
msgid "Leave project"
-msgstr ""
+msgstr "退出專案"
msgid "Leave zen mode"
-msgstr ""
+msgstr "離開禪模å¼"
msgid "Leaving this setting enabled is recommended."
-msgstr ""
+msgstr "建議啟用此設定。"
msgid "Legacy burndown chart"
-msgstr ""
+msgstr "éºç•™çš„燃盡圖"
msgid "Legacy license"
-msgstr ""
+msgstr "éºç•™çš„授權æ¢æ¬¾"
msgid "Less Details"
-msgstr ""
+msgstr "較少的詳情"
+
+msgid "Less restrictive visibility"
+msgstr "é™åˆ¶è¼ƒå°‘çš„å¯è¦‹æ€§"
msgid "Let's Encrypt does not accept emails on example.com"
-msgstr ""
+msgstr "Let's Encryptä¸æŽ¥å—example.comçš„é›»å­éƒµä»¶"
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 "Let's talk!"
-msgstr ""
+msgstr "Let's Encrypt是一個å…è²»ã€è‡ªå‹•åŒ–和開放的憑證授權(CA)機構。它å¯ä»¥æ供網站啟用HTTPS (SSL/TLS)所需的數字憑證。é€éŽ%{docs_link_start}GitLab Pages上的文件%{docs_link_end}來了解Let's Encrypté…置的更多訊æ¯ã€‚"
msgid "License Compliance"
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆè¦"
-msgid "License Compliance| Used by"
-msgstr ""
+msgid "License Compliance| Used by %{dependencies}"
+msgstr "被 %{dependencies} 使用"
msgid "License compliance"
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆè¦"
msgid "License key"
-msgstr ""
+msgstr "授權金鑰"
msgid "License overview"
-msgstr ""
+msgstr "授權æ¢æ¬¾æ¦‚覽"
msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
-msgstr ""
+msgstr "%{docLinkStart}授權核准%{docLinkEnd}有效"
msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
-msgstr ""
+msgstr "%{docLinkStart}授權核准%{docLinkEnd}無效"
msgid "LicenseCompliance|Acceptable for use in this project"
-msgstr ""
+msgstr "å¯æŽ¥å—用於此專案"
msgid "LicenseCompliance|Acceptable license to be used in the project"
-msgstr ""
+msgstr "專案中å¯æŽ¥å—的授權"
msgid "LicenseCompliance|Add license and related policy"
-msgstr ""
+msgstr "加入授權æ¢æ¬¾å’Œç›¸é—œæ”¿ç­–"
msgid "LicenseCompliance|Add license policy"
-msgstr ""
+msgstr "加入授權æ¢æ¬¾ç­–ç•¥"
msgid "LicenseCompliance|Allow"
-msgstr ""
+msgstr "å…許"
msgid "LicenseCompliance|Allowed"
-msgstr ""
+msgstr "å·²å…許"
msgid "LicenseCompliance|Denied"
-msgstr ""
+msgstr "已拒絕"
msgid "LicenseCompliance|Deny"
-msgstr ""
+msgstr "拒絕"
msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
-msgstr ""
+msgstr "如檢測到則ä¸å…許åˆä½µè«‹æ±‚並指示開發人員移除"
msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
-msgstr ""
+msgstr "了解更多有關%{linkStart}授權核准%{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"
-msgstr[0] ""
+msgstr[0] "授權åˆè¦æ€§åƒ…檢測到æºåˆ†æ”¯çš„ %d 個授權和政策é•è¦"
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
-msgstr[0] ""
+msgstr[0] "授權åˆè¦æª¢æŸ¥åªåœ¨æºåˆ†æ”¯ä¸Šæª¢æ¸¬åˆ°%d個授權åŠæ”¿ç­–é•è¦ã€‚需è¦æ ¸å‡†ã€‚"
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[0] "授權åˆè¦æ€§åƒ…檢測到æºåˆ†æ”¯æª¢æ¸¬åˆ°%d個授權"
msgid "LicenseCompliance|License Compliance detected %d new license"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
-msgstr[0] ""
+msgstr[0] "授權åˆè¦æ€§åƒ…檢測到%d個新的授權"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
-msgstr[0] ""
+msgstr[0] "授權åˆè¦æ€§åƒ…檢測到%d個新的授權åŠæ”¿ç­–é•è¦ã€‚"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
-msgstr[0] ""
+msgstr[0] "授權åˆè¦æ€§åƒ…檢測到%d個新的授權åŠæ”¿ç­–é•è¦ã€‚需è¦æ ¸å‡†ã€‚"
msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆè¦åƒ…在æºåˆ†æ”¯æœªæª¢æ¸¬åˆ°æŽˆæ¬Šæ¢æ¬¾"
msgid "LicenseCompliance|License Compliance detected no new licenses"
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆè¦æœªæª¢æ¸¬åˆ°æ–°æŽˆæ¬Šæ¢æ¬¾"
msgid "LicenseCompliance|License name"
-msgstr ""
+msgstr "授權æ¢æ¬¾å稱"
msgid "LicenseCompliance|No policy matches this license"
-msgstr ""
+msgstr "沒有符åˆæ­¤æŽˆæ¬Šæ¢æ¬¾çš„政策"
msgid "LicenseCompliance|Out-of-compliance with the project's policies and should be removed"
-msgstr ""
+msgstr "超出éµå®ˆå°ˆæ¡ˆæ”¿ç­–的權é™ï¼Œæ‡‰è¢«ç§»é™¤"
msgid "LicenseCompliance|Remove license"
-msgstr ""
+msgstr "移除授權æ¢æ¬¾"
msgid "LicenseCompliance|Remove license?"
-msgstr ""
+msgstr "移除授權æ¢æ¬¾å—Žï¼Ÿ"
msgid "LicenseCompliance|There are currently no policies in this project."
-msgstr ""
+msgstr "此專案目å‰æ²’有政策。"
msgid "LicenseCompliance|There are currently no policies that match in this project."
-msgstr ""
+msgstr "此專案目å‰æ²’有符åˆçš„政策。"
msgid "LicenseCompliance|This license already exists in this project."
-msgstr ""
+msgstr "此授權æ¢æ¬¾å·²ç¶“存在於該專案中。"
msgid "LicenseCompliance|Uncategorized"
-msgstr ""
+msgstr "未分類"
msgid "LicenseCompliance|Update approvals"
-msgstr ""
+msgstr "更新核准"
msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "您å³å°‡å¾žç›®å‰å°ˆæ¡ˆä¸­ç§»é™¤æŽˆæ¬Šæ¢æ¬¾%{name}。"
msgid "LicenseManagement|Allowed"
-msgstr ""
+msgstr "å·²å…許"
msgid "LicenseManagement|Denied"
-msgstr ""
+msgstr "已拒絕"
msgid "LicenseManagement|Uncategorized"
-msgstr ""
+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 ""
+msgstr "如果專案命å空間的計劃包å«è©²åŠŸèƒ½ï¼Œæˆ–者該專案是公開的,則å¯ä»¥ä½¿ç”¨æŽˆæ¬Šçš„功能。"
msgid "Licensed Features"
-msgstr ""
+msgstr "需è¦æŽˆæ¬Šçš„功能"
msgid "Licensed to:"
-msgstr ""
+msgstr "授權給:"
msgid "Licenses"
-msgstr ""
+msgstr "授權æ¢æ¬¾"
msgid "Licenses|%{remainingComponentsCount} more"
-msgstr ""
+msgstr "其餘%{remainingComponentsCount}項"
msgid "Licenses|Acceptable license to be used in the project"
-msgstr ""
+msgstr "專案中å¯æŽ¥å—的授權æ¢æ¬¾"
msgid "Licenses|Component"
-msgstr ""
+msgstr "元件"
msgid "Licenses|Components"
-msgstr ""
+msgstr "元件"
msgid "Licenses|Detected in Project"
-msgstr ""
+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 "根據 %{linkStart}latest successful%{linkEnd} 掃æ,顯示在專案中檢測到的ä¸ç¬¦åˆå°ˆæ¡ˆæ”¿ç­–的授權æ¢æ¬¾"
msgid "Licenses|Drag your license file here or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
+msgstr "將您的授權æ¢æ¬¾æ–‡ä»¶æ‹–動到此處,或 %{linkStart}點擊上傳%{linkEnd}"
msgid "Licenses|Drop your license file to start the upload."
-msgstr ""
+msgstr "拖放您的授權æ¢æ¬¾æ–‡ä»¶ï¼Œé–‹å§‹ä¸Šå‚³ã€‚"
msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
-msgstr ""
+msgstr "讀å–授權æ¢æ¬¾åˆ—表時發生錯誤。請檢查您的網路連接並é‡è©¦ã€‚"
msgid "Licenses|Error: You are trying to upload something other than a file"
-msgstr ""
+msgstr "錯誤: 您正在嘗試上傳文件以外的內容"
msgid "Licenses|License Compliance"
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆè¦æ€§"
msgid "Licenses|Name"
-msgstr ""
+msgstr "å稱"
msgid "Licenses|Policies"
-msgstr ""
+msgstr "政策"
msgid "Licenses|Policy"
-msgstr ""
+msgstr "政策"
msgid "Licenses|Policy violation: denied"
-msgstr ""
+msgstr "é•å政策:已拒絕"
msgid "Licenses|Specified policies in this project"
-msgstr ""
+msgstr "本專案中的指定政策"
msgid "Licenses|The file could not be uploaded."
-msgstr ""
+msgstr "此文件無法上傳。"
msgid "Licenses|The license list details information about the licenses used within your project."
-msgstr ""
+msgstr "授權æ¢æ¬¾åˆ—表詳細說明您專案中使用的授權æ¢æ¬¾è¨Šæ¯ã€‚"
msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
-msgstr ""
+msgstr "ä¸å¯æŽ¥å—的授權æ¢æ¬¾ï¼Œå¦‚果檢測到,它將ä¸å…許åˆä½µè«‹æ±‚,直到它被移除"
msgid "Licenses|View license details for your project"
-msgstr ""
+msgstr "查看您專案的授權æ¢æ¬¾è©³ç´°è¨Šæ¯"
msgid "Limit display of time tracking units to hours."
-msgstr ""
+msgstr "é™åˆ¶æ™‚間追蹤單ä½é¡¯ç¤ºåˆ°å°æ™‚。"
msgid "Limit sign in from multiple IP addresses"
-msgstr ""
+msgstr "é™åˆ¶å¾žå¤šå€‹IP地å€ç™»å…¥"
msgid "Limit the number of inbound incident management alerts that can be sent to a project."
-msgstr ""
+msgstr "é™åˆ¶å¯ä»¥ç™¼é€åˆ°å°ˆæ¡ˆçš„入站事件管ç†è­¦å ±æ•¸é‡ã€‚"
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
-msgstr ""
+msgstr "é™åˆ¶ä½¿ç”¨è€…æ¯åˆ†é˜å¯ä»¥é€šéŽ Web å’Œ 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 "é™åˆ¶æ¯åˆ†é˜çš„æµæ°´ç·šå»ºç«‹è«‹æ±‚數。此é™åˆ¶åŒ…æ‹¬é€šéŽ UIã€API 和後å°è™•ç†å»ºç«‹çš„æµæ°´ç·šã€‚"
msgid "Limit the size of Sidekiq jobs stored in Redis."
-msgstr ""
+msgstr "é™åˆ¶å„²å­˜åœ¨Redis中的Sidekiq作業的大å°ã€‚"
msgid "Limiting mode"
-msgstr ""
+msgstr "é™åˆ¶æ¨¡å¼"
msgid "Line changes"
-msgstr ""
+msgstr "變更的行"
msgid "Link"
-msgstr ""
+msgstr "連çµ"
msgid "Link (optional)"
-msgstr ""
+msgstr "連çµï¼ˆå¯é¸ï¼‰"
msgid "Link Sentry to GitLab to discover and view the errors your application generates."
-msgstr ""
+msgstr "å°‡ Sentry 連çµåˆ° GitLab 以發ç¾å’ŒæŸ¥çœ‹æ‚¨çš„應用程å¼ç”Ÿæˆçš„錯誤。"
msgid "Link URL"
-msgstr ""
+msgstr "é€£çµ URL"
msgid "Link an external wiki from the project's sidebar. %{docs_link}"
-msgstr ""
+msgstr "從專案的å´é‚Šæ¬„連çµå¤–部 wiki。 %{docs_link}"
msgid "Link copied"
-msgstr ""
+msgstr "連çµå·²è¤‡è£½"
msgid "Link text"
-msgstr ""
+msgstr "連çµæ–‡å­—"
msgid "Link title"
-msgstr ""
+msgstr "連çµæ¨™é¡Œ"
msgid "Link title is required"
-msgstr ""
+msgstr "連接標題為必填項"
msgid "Link to go to GitLab pipeline documentation"
-msgstr ""
+msgstr "連çµä»¥å‰å¾€GitLaæµæ°´ç·šæ–‡ä»¶"
msgid "Link to your Grafana instance."
-msgstr ""
+msgstr "連çµåˆ°æ‚¨çš„ Grafana 實例。"
msgid "Linked emails (%{email_count})"
-msgstr ""
+msgstr "已連çµçš„é›»å­éƒµä»¶ (%{email_count})"
msgid "Linked epics"
-msgstr ""
+msgstr "已連çµå²è©©"
-msgid "Linked issues"
-msgstr ""
+msgid "Linked incidents or issues"
+msgstr "é—œè¯çš„事故或議題"
+
+msgid "Linked items"
+msgstr "連çµçš„é …ç›®"
msgid "LinkedIn"
-msgstr ""
+msgstr "領英(LinkedIn)"
msgid "LinkedIn:"
-msgstr ""
+msgstr "LinkedIn:"
msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
-msgstr ""
+msgstr "%{counterLabel}個更多下游æµæ°´ç·š"
+
+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 "為事件建立資æºé€£çµæ™‚發生錯誤:%{error}"
+
+msgid "LinkedResources|Error deleting the linked resource for the incident: %{error}"
+msgstr "刪除事故的éˆçµè³‡æºæ™‚發生錯誤:%{error}"
+
+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 ""
+msgstr "連çµ"
msgid "List"
-msgstr ""
+msgstr "列表"
msgid "List Your Gitea Repositories"
-msgstr ""
+msgstr "列出Gitea版本庫"
msgid "List available repositories"
-msgstr ""
+msgstr "列出å¯ç”¨ç‰ˆæœ¬åº«"
msgid "List of all merge commits"
-msgstr ""
+msgstr "所有åˆä½µæ交列表"
msgid "List of suitable GCP locations"
-msgstr ""
+msgstr "åˆé©çš„ GCP ä½ç½®åˆ—表"
msgid "List of users who are allowed to exceed the rate limit. Example: username1, username2"
-msgstr ""
+msgstr "å…許超éŽé€ŸçŽ‡é™åˆ¶çš„使用者列表。例如:使用者 1ã€ä½¿ç”¨è€… 2"
msgid "List options"
-msgstr ""
+msgstr "列表é¸é …"
msgid "List settings"
-msgstr ""
+msgstr "列表設定"
msgid "List the merge requests that must be merged before this one."
-msgstr ""
+msgstr "列出在此之å‰å¿…é ˆåˆä½µçš„åˆä½µè«‹æ±‚。"
msgid "List the visible events for %{project_link} using the %{events_api_link}."
-msgstr ""
+msgstr "使用%{events_api_link}列出%{project_link}çš„å¯è¦‹äº‹ä»¶ã€‚"
msgid "List view"
-msgstr ""
+msgstr "列表檢視"
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "列出您的 Bitbucket 庫"
msgid "Live preview"
-msgstr ""
+msgstr "å³æ™‚é è¦½"
msgid "Load more"
-msgstr ""
+msgstr "載入更多"
msgid "Load more users"
-msgstr ""
+msgstr "加載更多使用者"
msgid "Loading"
-msgstr ""
+msgstr "載入中"
msgid "Loading %{name}"
-msgstr ""
+msgstr "正在載入 %{name}"
msgid "Loading contribution stats for group members"
-msgstr ""
+msgstr "載入群組æˆå“¡çš„è²¢ç»çµ±è¨ˆè¨Šæ¯"
msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
-msgstr ""
+msgstr "載入æ交引用%{ref}路徑%{path}中的文件,目錄和å­æ¨¡çµ„"
msgid "Loading more"
-msgstr ""
+msgstr "載入更多"
msgid "Loading snippet"
-msgstr ""
+msgstr "正在載入程å¼ç¢¼ç‰‡æ®µ"
msgid "Loading the GitLab IDE..."
-msgstr ""
+msgstr "載入GitLab IDE..."
msgid "Loading, please wait."
-msgstr ""
+msgstr "載入中,請ç¨å¾…"
msgid "Loading..."
-msgstr ""
+msgstr "正在載入..."
msgid "Loading…"
-msgstr ""
+msgstr "正在載入..."
msgid "Localization"
-msgstr ""
+msgstr "在地化"
msgid "Location"
-msgstr ""
+msgstr "ä½ç½®"
msgid "Location:"
-msgstr ""
+msgstr "ä½ç½®ï¼š"
msgid "Lock"
msgstr "鎖定"
msgid "Lock %{issuableDisplayName}"
-msgstr ""
+msgstr "鎖定 %{issuableDisplayName}"
msgid "Lock File?"
-msgstr ""
+msgstr "鎖定文件?"
msgid "Lock memberships to LDAP synchronization"
-msgstr ""
+msgstr "鎖定æˆå“¡èº«ä»½åˆ°LDAPåŒæ­¥"
msgid "Lock merge request"
-msgstr ""
+msgstr "鎖定åˆä½µè«‹æ±‚"
msgid "Lock not found"
-msgstr ""
+msgstr "未找到鎖"
msgid "Lock the discussion"
-msgstr ""
+msgstr "鎖定討論"
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "鎖定%{issuableDisplayName}嗎?鎖定後將åªæœ‰%{strongStart}專案æˆå“¡%{strongEnd}å¯ä»¥ç™¼è¡¨ç•™è¨€è©•è«–。"
msgid "Lock to current projects"
-msgstr ""
+msgstr "鎖定到當å‰å°ˆæ¡ˆ"
msgid "Locked"
-msgstr ""
+msgstr "已鎖定"
msgid "Locked Files"
-msgstr ""
+msgstr "已鎖定文件"
msgid "Locked by %{fileLockUserName}"
-msgstr ""
+msgstr "被%{fileLockUserName}鎖定"
msgid "Locked the discussion."
-msgstr ""
+msgstr "鎖定討論."
msgid "Locks give the ability to lock specific file or folder."
-msgstr ""
+msgstr "加鎖å¯ä»¥éŽ–定特定的文件或資料夾。"
msgid "Locks the discussion."
-msgstr ""
+msgstr "鎖定討論."
msgid "LoggedOutMarketingHeader|About GitLab"
-msgstr ""
+msgstr "關於 GitLab"
msgid "LoggedOutMarketingHeader|Explore GitLab"
-msgstr ""
+msgstr "ç€è¦½ GitLab"
msgid "LoggedOutMarketingHeader|Get started"
-msgstr ""
+msgstr "開始使用"
msgid "LoggedOutMarketingHeader|GitLab Learn"
-msgstr ""
+msgstr "GitLab 學習"
msgid "LoggedOutMarketingHeader|GitLab docs"
-msgstr ""
+msgstr "GitLab 文件"
msgid "LoggedOutMarketingHeader|GitLab: the DevOps platform"
-msgstr ""
+msgstr "GitLab:DevOps å¹³å°"
msgid "LoggedOutMarketingHeader|How GitLab compares"
-msgstr ""
+msgstr "與åŒé¡žç”¢å“相比"
msgid "LoggedOutMarketingHeader|Install GitLab"
-msgstr ""
+msgstr "å®‰è£ GitLab"
msgid "LoggedOutMarketingHeader|Pricing"
-msgstr ""
+msgstr "定價"
msgid "LoggedOutMarketingHeader|Talk to an expert"
-msgstr ""
+msgstr "與專家交談"
msgid "Login"
-msgstr ""
+msgstr "登入"
msgid "Login with smartcard"
-msgstr ""
+msgstr "使用智慧å¡ç™»å…¥"
msgid "Logo was successfully removed."
-msgstr ""
+msgstr "Logo å·²æˆåŠŸç§»é™¤ã€‚"
msgid "Logo will be removed. Are you sure?"
-msgstr ""
+msgstr "Logo 將被刪除,您確定嗎?"
msgid "Logs"
-msgstr ""
+msgstr "日誌"
msgid "Looks like you've reached your %{free_limit} member limit for %{strong_start}%{namespace_name}%{strong_end}"
-msgstr ""
+msgstr "您似乎已é”到 %{strong_start}%{namespace_name}%{strong_end} çš„ %{free_limit} æˆå“¡é™åˆ¶"
msgid "Low vulnerabilities present"
-msgstr ""
+msgstr "存在低風險æ¼æ´ž"
msgid "MB"
msgstr "MB"
@@ -23467,1523 +23677,1520 @@ msgid "MD5"
msgstr "MD5"
msgid "MERGED"
-msgstr ""
+msgstr "å·²åˆä½µ"
msgid "MR widget|Back to the merge request"
-msgstr ""
+msgstr "返回åˆä½µè«‹æ±‚"
msgid "MR widget|See your pipeline in action"
-msgstr ""
+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 ""
+msgstr "請查閱我們的%{beginnerLinkStart}æŒçºŒæ•´åˆæ–°æ‰‹å°Žå¼•%{beginnerLinkEnd}å’Œ%{exampleLinkStart}GitLab CI/CD實例%{exampleLinkEnd}來了解更多訊æ¯ã€‚"
msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
-msgstr ""
+msgstr "æµæ°´ç·šå°‡åœ¨æ¯æ¬¡æ交時測試您的程å¼ç¢¼ã€‚%{codeQualityLinkStart}程å¼ç¢¼è³ªé‡å ±å‘Š%{codeQualityLinkEnd}將出ç¾åœ¨æ‚¨çš„åˆä½µè«‹æ±‚中,å°æ‚¨æ½›åœ¨çš„程å¼ç¢¼è³ªé‡ä¸‹é™ç™¼å‡ºè­¦å‘Šã€‚"
msgid "MRApprovals|Approvals"
-msgstr ""
+msgstr "核准"
msgid "MRApprovals|Approved by"
-msgstr ""
+msgstr "核准者為"
msgid "MRApprovals|Approvers"
-msgstr ""
+msgstr "核准者"
msgid "MRApprovals|Commented by"
-msgstr ""
+msgstr "留言評論者為"
msgid "MRDiffFile|Changes are too large to be shown."
-msgstr ""
+msgstr "更改太大而無法顯示。"
msgid "MRDiffFile|View file @ %{commitSha}"
-msgstr ""
+msgstr "查看文件@ %{commitSha}"
msgid "MRDiff|Show changes only"
-msgstr ""
+msgstr "åªæŸ¥çœ‹è®Šæ›´å…§å®¹"
msgid "MRDiff|Show full file"
-msgstr ""
+msgstr "顯示全部文件"
msgid "Made this issue confidential."
-msgstr ""
+msgstr "將此議題設定為ç§å¯†."
msgid "Mailgun"
-msgstr ""
+msgstr "Mailgun"
msgid "Mailgun HTTP webhook signing key"
-msgstr ""
+msgstr "Mailgun HTTP webhook ç°½å金鑰"
msgid "Mailgun events"
-msgstr ""
+msgstr "Mailgun事件"
msgid "Maintenance mode"
-msgstr ""
+msgstr "維護模å¼"
msgid "Make adjustments to how your GitLab instance is set up."
-msgstr ""
+msgstr "調整您 GitLab 實例的設定方å¼ã€‚"
msgid "Make and review changes in the browser with the Web IDE"
-msgstr ""
+msgstr "使用Web IDE在ç€è¦½å™¨ä¸­å»ºç«‹å’ŒæŸ¥çœ‹æ›´æ”¹"
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 ""
+msgstr "GitLab Geoå¯ä»¥å»ºç«‹GitLab實體的唯讀é¡åƒ, 使得從é ç«¯è¤‡è£½å’Œæ‹‰å–大型程å¼ç¢¼ç‰ˆæœ¬åº«çš„時間大大縮短,從而æ高團隊æˆå“¡çš„工作效率。"
msgid "Make issue confidential"
-msgstr ""
+msgstr "將議題設定為機密。"
msgid "Make sure you have the correct permissions to link your project."
-msgstr ""
+msgstr "確ä¿æ‚¨å…·æœ‰éˆæŽ¥å°ˆæ¡ˆçš„正確權é™ã€‚"
msgid "Make sure you save it - you won't be able to access it again."
-msgstr ""
+msgstr "請確ä¿å¦¥å–„儲存它 - 您無法å†æ¬¡å­˜å–它的內容。"
msgid "Makes this issue confidential."
-msgstr ""
+msgstr "將此議題設定為機密."
msgid "Manage %{workspace} labels"
-msgstr ""
+msgstr "ç®¡ç† %{workspace} 標記"
msgid "Manage Web IDE features."
-msgstr ""
+msgstr "ç®¡ç† Web IDE 功能。"
msgid "Manage access"
-msgstr ""
+msgstr "管ç†æ¬Šé™"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
-msgstr ""
+msgstr "管ç†å¯ä»¥å°‡ GitLab 用作 OAuth æ供程å¼çš„應用程å¼ï¼Œä»¥åŠæ‚¨å·²æŽˆæ¬Šä½¿ç”¨æ‚¨çš„帳號的應用程å¼ã€‚"
msgid "Manage applications that use GitLab as an OAuth provider."
-msgstr ""
+msgstr "管ç†ä½¿ç”¨ GitLab 作為 OAuth æ供程å¼çš„應用程å¼ã€‚"
msgid "Manage applications that you've authorized to use your account."
-msgstr ""
+msgstr "管ç†æ‚¨æŽˆæ¬Šä½¿ç”¨å¸³è™Ÿçš„應用程å¼ã€‚"
msgid "Manage git repositories with fine-grained access controls that keep your code secure."
-msgstr ""
+msgstr "使用精細的存å–控制來管ç†git版本庫,確ä¿æ‚¨çš„程å¼ç¢¼å®‰å…¨ã€‚"
msgid "Manage group labels"
-msgstr ""
+msgstr "管ç†ç¾¤çµ„標記"
msgid "Manage labels"
-msgstr ""
+msgstr "管ç†æ¨™è¨˜"
msgid "Manage members"
-msgstr ""
+msgstr "管ç†æˆå“¡"
msgid "Manage milestones"
-msgstr ""
+msgstr "管ç†é‡Œç¨‹ç¢‘"
msgid "Manage project labels"
-msgstr ""
+msgstr "管ç†é …目標記"
msgid "Manage projects."
-msgstr ""
+msgstr "管ç†å°ˆæ¡ˆã€‚"
msgid "Manage two-factor authentication"
-msgstr ""
+msgstr "管ç†é›™å› å­é©—è­‰"
msgid "Manage your license"
-msgstr ""
+msgstr "管ç†æ‚¨çš„授權許å¯"
msgid "Manage your project's triggers"
-msgstr ""
+msgstr "管ç†æ‚¨çš„專案觸發器"
msgid "Managed Account"
-msgstr ""
+msgstr "託管帳號"
msgid "Manifest"
-msgstr ""
+msgstr "Manifest"
msgid "Manifest file import"
-msgstr ""
+msgstr "Manifest文件匯入"
msgid "Manifest import"
-msgstr ""
+msgstr "Manifest文件匯入"
msgid "Manual"
-msgstr ""
-
-msgid "Manual iteration cadences are deprecated. Only automatic iteration cadences are allowed."
-msgstr ""
+msgstr "手動"
msgid "ManualOrdering|Couldn't save the order of the issues"
-msgstr ""
+msgstr "無法儲存議題的順åº"
msgid "Manually link this issue by adding it to the linked issue section of the %{linkStart}originating vulnerability%{linkEnd}."
-msgstr ""
+msgstr "è¦æ‰‹å‹•é€£çµæ­¤è­°é¡Œï¼Œå°‡å…¶åŠ å…¥åˆ°%{linkStart}原始æ¼æ´ž%{linkEnd}的連çµè­°é¡Œéƒ¨åˆ†ã€‚"
msgid "Map a FogBugz account ID to a GitLab user"
-msgstr ""
+msgstr "å°‡ FogBugz 帳號 ID å°æ‡‰ç‚º GitLab 使用者"
msgid "Mar"
msgstr "3月"
msgid "March"
-msgstr ""
+msgstr "3月"
msgid "Mark as done"
-msgstr ""
+msgstr "標記為已完æˆ"
msgid "Mark as draft"
-msgstr ""
+msgstr "標記為è‰ç¨¿"
msgid "Mark as ready"
-msgstr ""
+msgstr "標記為就緒"
msgid "Mark this issue as a duplicate of another issue"
-msgstr ""
+msgstr "將此議題標記為å¦ä¸€å€‹è­°é¡Œçš„é‡è¤‡"
msgid "Mark this issue as related to another issue"
-msgstr ""
+msgstr "將此議題標記為與å¦ä¸€å€‹è­°é¡Œçš„相關"
msgid "Mark to do as done"
-msgstr ""
+msgstr "將待辦事項標記為已完æˆã€‚"
msgid "Markdown Help"
-msgstr ""
+msgstr "Markdown 幫助"
msgid "Markdown enabled."
-msgstr ""
+msgstr "Markdown已啟用。"
msgid "Markdown supported."
-msgstr ""
+msgstr "æ”¯æ´ Markdown。"
msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
-msgstr ""
+msgstr "加入éˆæŽ¥(%{modifierKey}K)"
msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
-msgstr ""
+msgstr "加入éˆæŽ¥(%{modifier_key}K)"
msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
-msgstr ""
+msgstr "加入粗體文本(%{modifierKey}B)"
msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
-msgstr ""
+msgstr "加入粗體文本(%{modifier_key}B)"
msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
-msgstr ""
+msgstr "加入斜體文本(%{modifierKey}I)"
msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
-msgstr ""
+msgstr "加入斜體文本(%{modifier_key}I)"
msgid "MarkdownEditor|Add strikethrough text (%{modifierKey}⇧X)"
-msgstr ""
+msgstr "加入刪除線文本 (%{modifierKey}⇧X)"
msgid "MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)"
-msgstr ""
+msgstr "加入帶刪除線的文本 (%{modifier_key}⇧X)"
msgid "MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
-msgstr ""
+msgstr "支æ´%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}"
msgid "Marked For Deletion At - %{deletion_time}"
-msgstr ""
+msgstr "標記刪除於 - %{deletion_time}"
msgid "Marked as draft. Can only be merged when marked as ready."
-msgstr ""
+msgstr "標記為è‰ç¨¿ã€‚åªæœ‰åœ¨æ¨™è¨˜ç‚ºå°±ç·’後æ‰èƒ½åˆä½µã€‚"
msgid "Marked as ready. Merging is now allowed."
-msgstr ""
+msgstr "標記為已準備好。ç¾åœ¨å…許åˆä½µã€‚"
msgid "Marked this %{noun} as a draft."
-msgstr ""
+msgstr "已標記此%{noun}為è‰ç¨¿ã€‚"
msgid "Marked this %{noun} as ready."
-msgstr ""
+msgstr "已將 %{noun} 標記為準備就緒。"
msgid "Marked this issue as a duplicate of %{duplicate_param}."
-msgstr ""
+msgstr "標記這個議題為%{duplicate_param}çš„é‡è¤‡é …。"
msgid "Marked this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "將此議題標記為%{issue_ref}的相關議題。"
msgid "Marked to do as done."
-msgstr ""
+msgstr "將待辦事項標記為已完æˆã€‚"
msgid "Marks this %{noun} as a draft."
-msgstr ""
+msgstr "將標記此%{noun}為è‰ç¨¿ã€‚"
msgid "Marks this %{noun} as ready."
-msgstr ""
+msgstr "標記該 %{noun} 為準備就緒。"
msgid "Marks this issue as a duplicate of %{duplicate_reference}."
-msgstr ""
+msgstr "將此議題標記為 %{duplicate_reference} çš„é‡è¤‡ã€‚"
msgid "Marks this issue as related to %{issue_ref}."
-msgstr ""
+msgstr "將此議題標記為%{issue_ref}的相關議題。"
msgid "Marks to do as done."
-msgstr ""
+msgstr "將待辦事項標記為已完æˆã€‚"
msgid "Mask variable"
-msgstr ""
+msgstr "éš±è—變數"
msgid "Match not found; try refining your search query."
-msgstr ""
+msgstr "未找到符åˆï¼›è«‹å˜—試變更查詢æ¢ä»¶ã€‚"
msgid "Mattermost"
-msgstr ""
+msgstr "Mattermost"
msgid "Mattermost URL:"
-msgstr ""
+msgstr "Mattermost URL:"
msgid "Mattermost notifications"
-msgstr ""
+msgstr "Mattermost 通知"
msgid "MattermostService|Add to Mattermost"
-msgstr ""
+msgstr "加入到Mattermost"
msgid "MattermostService|After you configure the integration, view your new Mattermost commands by entering"
-msgstr ""
+msgstr "設定整åˆå¾Œï¼Œé€šéŽè¼¸å…¥æŸ¥çœ‹æ–°çš„ Mattermost 指令"
msgid "MattermostService|Command trigger word"
-msgstr ""
+msgstr "指令觸發詞"
msgid "MattermostService|Fill in the word that works best for your team."
-msgstr ""
+msgstr "填入最é©åˆä½ çš„團隊的文字。"
msgid "MattermostService|Request URL"
-msgstr ""
+msgstr "請求網å€"
msgid "MattermostService|Request method"
-msgstr ""
+msgstr "請求方法"
msgid "MattermostService|Response icon"
-msgstr ""
+msgstr "響應圖示"
msgid "MattermostService|Response username"
-msgstr ""
+msgstr "響應使用者å稱"
msgid "MattermostService|Suggestions:"
-msgstr ""
+msgstr "建議:"
msgid "MattermostService|Use this service to perform common tasks in your project by entering slash commands in Mattermost."
-msgstr ""
+msgstr "通éŽåœ¨ Mattermost 中輸入斜槓指令,使用此æœå‹™åŸ·è¡Œå°ˆæ¡ˆä¸­çš„常見任務。"
msgid "Max 100,000 events"
-msgstr ""
+msgstr "最多100,000個事件"
msgid "Max Value"
-msgstr ""
+msgstr "最大值"
msgid "Max authenticated Git LFS requests per period per user"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…在æ¯å€‹æ™‚期的最大身份驗證 Git LFS 請求"
msgid "Max file size is 200 KB."
-msgstr ""
+msgstr "檔案大å°ä¸Šé™ç‚º200 KB。"
msgid "Max role"
-msgstr ""
+msgstr "最大角色"
msgid "Max seats used"
-msgstr ""
+msgstr "使用的最大席次"
msgid "Max session time"
-msgstr ""
+msgstr "最大會話時間"
msgid "Maximum 20 characters"
-msgstr ""
+msgstr "最多 20 個字元"
msgid "Maximum Conan package file size in bytes"
-msgstr ""
+msgstr "最大Conan文件包大å°ï¼ˆå­—節)"
msgid "Maximum Helm chart file size in bytes"
-msgstr ""
+msgstr "最大 Helm chart 文件大å°ï¼ˆä»¥å­—節為單ä½ï¼‰"
msgid "Maximum Maven package file size in bytes"
-msgstr ""
+msgstr "最大Maven文件包大å°ï¼ˆå­—節)"
msgid "Maximum NuGet package file size in bytes"
-msgstr ""
+msgstr "最大NuGet文件包大å°ï¼ˆå­—節)"
msgid "Maximum PyPI package file size in bytes"
-msgstr ""
+msgstr "最大PyPI文件包大å°ï¼ˆå­—節)"
msgid "Maximum Terraform Module package file size in bytes"
-msgstr ""
+msgstr "最大 Terraform 模組包文件大å°ï¼ˆä»¥å­—節為單ä½ï¼‰"
msgid "Maximum Users"
-msgstr ""
+msgstr "最大使用者數"
msgid "Maximum allowable lifetime for access token (days)"
-msgstr ""
+msgstr "å­˜å–令牌(權æ–)的最大å…許壽命(天)"
msgid "Maximum allowable lifetime for personal access token (days)"
-msgstr ""
+msgstr "個人存å–令牌(權æ–)的最長有效期(天)"
msgid "Maximum allowed lifetime for SSH keys (in days)"
-msgstr ""
+msgstr "SSH 金鑰的最長å…許生命週期(以天為單ä½ï¼‰"
msgid "Maximum artifacts size"
-msgstr ""
+msgstr "最大工件大å°"
msgid "Maximum artifacts size (MB)"
-msgstr ""
+msgstr "最大產物大å°ï¼ˆMB)"
msgid "Maximum attachment size"
-msgstr ""
+msgstr "最大附件大å°"
msgid "Maximum attachment size (MB)"
-msgstr ""
+msgstr "æœ€å¤§é™„ä»¶å¤§å° (MB)"
msgid "Maximum authenticated API requests per rate limit period per user"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…æ¯å€‹é€ŸçŽ‡é™åˆ¶æœŸçš„最大已驗證 API 請求數"
msgid "Maximum authenticated web requests per rate limit period per user"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…æ¯å€‹é€ŸçŽ‡é™åˆ¶æœŸé–“的最大已驗證 Web 請求數"
msgid "Maximum bulk request size (MiB)"
-msgstr ""
+msgstr "最大批次請求大å°(MiB)"
msgid "Maximum capacity"
-msgstr ""
+msgstr "最大容é‡"
msgid "Maximum character limit - %{limit}"
-msgstr ""
+msgstr "最大字元數é™åˆ¶ - %{limit}"
msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
-msgstr ""
+msgstr "æ¯å€‹ç´¢å¼•æ“作的Elasticsearch批次請求的最大並行性。"
msgid "Maximum delay (Minutes)"
-msgstr ""
+msgstr "æœ€å¤§å»¶é² (分é˜)"
msgid "Maximum diff patch size"
-msgstr ""
+msgstr "最大差異補ä¸å¤§å°"
msgid "Maximum diff patch size (Bytes)"
-msgstr ""
+msgstr "最大差異補ä¸å¤§å°ï¼ˆå­—節)"
msgid "Maximum duration of a session."
-msgstr ""
+msgstr "會話的最大有效期é™ã€‚"
msgid "Maximum export size"
-msgstr ""
+msgstr "最大匯出大å°"
msgid "Maximum export size (MB)"
-msgstr ""
+msgstr "æœ€å¤§åŒ¯å‡ºå¤§å° (MB)"
msgid "Maximum field length"
-msgstr ""
+msgstr "最大字段長度"
msgid "Maximum file size indexed (KiB)"
-msgstr ""
+msgstr "索引的最大文件大å°(KiB)"
-msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}."
-msgstr ""
+msgid "Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_allowlist}."
+msgstr "最大文件大å°ç‚º 1 MB,圖片尺寸必須為 32 x 32 åƒç´ ï¼Œå…許的圖åƒæ ¼å¼æ˜¯ %{favicon_extension_allowlist}。"
msgid "Maximum file size is 1MB. Pages are optimized for a 24px tall header logo"
-msgstr ""
+msgstr "最大文件大å°ç‚º 1MB。 é é¢é‡å° 24 åƒç´ çš„標題 logo 進行了優化"
msgid "Maximum file size is 1MB. Pages are optimized for a 640x360 px logo."
-msgstr ""
+msgstr "最大文件大å°ç‚º 1MB,é é¢é‡å° 640x360 åƒç´ çš„logo進行了優化。"
msgid "Maximum files in a diff"
-msgstr ""
+msgstr "差異中的最大文件數"
msgid "Maximum group export download requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§ç¾¤çµ„匯出下載請求"
msgid "Maximum group export requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§ç¾¤çµ„匯出請求"
msgid "Maximum group import requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§ç¾¤çµ„匯入請求"
msgid "Maximum import size"
-msgstr ""
+msgstr "最大匯入大å°"
msgid "Maximum import size (MB)"
-msgstr ""
+msgstr "æœ€å¤§åŒ¯å…¥å¤§å° (MB)"
msgid "Maximum job artifact size"
-msgstr ""
+msgstr "最大作業產物大å°"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "最大作業超時"
msgid "Maximum job timeout has a value which could not be accepted"
-msgstr ""
+msgstr "作業最大超時設定無效"
msgid "Maximum lines in a diff"
-msgstr ""
+msgstr "差異中的最大行數"
msgid "Maximum npm package file size in bytes"
-msgstr ""
+msgstr "最大 npm 軟體套件檔案大å°ï¼ˆä»¥å­—節為單ä½ï¼‰"
msgid "Maximum number of %{name} (%{count}) exceeded"
-msgstr ""
+msgstr "超éŽ%{name}的最大數é‡(%{count})"
msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
-msgstr ""
+msgstr "單次推é€ä¸­è§¸ç™¼ webhook å’Œæœå‹™çš„最大更改數(分支或標籤)(é è¨­ç‚º 3)。"
msgid "Maximum number of comments exceeded"
-msgstr ""
+msgstr "超出最大留言數"
msgid "Maximum number of mirrors that can be synchronizing at the same time."
-msgstr ""
+msgstr "å¯ä»¥åŒæ™‚åŒæ­¥çš„最大é¡åƒæ•¸ã€‚"
msgid "Maximum number of projects."
-msgstr ""
+msgstr "最大專案數é‡ã€‚"
msgid "Maximum number of requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§è«‹æ±‚數"
msgid "Maximum number of requests per minute for an authenticated user"
-msgstr ""
+msgstr "經éŽèº«ä»½é©—證的使用者æ¯åˆ†é˜çš„最大請求數"
msgid "Maximum number of requests per minute for an unauthenticated IP address"
-msgstr ""
+msgstr "未經身份驗證的 IP 地å€æ¯åˆ†é˜çš„最大請求數"
msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
-msgstr ""
+msgstr "æ¯å€‹åŽŸå§‹è·¯å¾‘æ¯åˆ†é˜çš„最大請求數(é è¨­ç‚º 300)。設定為 0 以ç¦ç”¨ç¯€æµã€‚"
msgid "Maximum number of unique IP addresses per user."
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…的最大唯一 IP 地å€æ•¸ã€‚"
msgid "Maximum of 255 characters"
-msgstr ""
+msgstr "最多 255 個字元"
msgid "Maximum page reached"
-msgstr ""
+msgstr "å·²é”到最大é é¢"
msgid "Maximum page size"
-msgstr ""
+msgstr "最大é é¢å¤§å°"
msgid "Maximum project export download requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§å°ˆæ¡ˆåŒ¯å‡ºä¸‹è¼‰è«‹æ±‚"
msgid "Maximum project export requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§å°ˆæ¡ˆåŒ¯å‡ºè«‹æ±‚"
msgid "Maximum project import requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§å°ˆæ¡ˆåŒ¯å…¥è«‹æ±‚"
msgid "Maximum push size"
-msgstr ""
+msgstr "最大推é€å¤§å°"
msgid "Maximum push size (MB)"
-msgstr ""
+msgstr "最大推é€å¤§å° (MB)"
msgid "Maximum requests per 10 minutes per user"
-msgstr ""
+msgstr "æ¯å€‹ä½¿ç”¨è€…10分é˜å…§çš„最大請求數"
msgid "Maximum requests per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜æœ€å¤§è«‹æ±‚數"
msgid "Maximum running slices"
-msgstr ""
+msgstr "最大é‹è¡Œåˆ‡ç‰‡"
msgid "Maximum size limit for a single commit."
-msgstr ""
+msgstr "單次æ交的最大大å°é™åˆ¶ã€‚"
msgid "Maximum size limit for each repository."
-msgstr ""
+msgstr "æ¯å€‹ç‰ˆæœ¬åº«çš„最大大å°é™åˆ¶ã€‚"
msgid "Maximum size of Elasticsearch bulk indexing requests."
-msgstr ""
+msgstr "Elasticsearch批次索引請求的最大大å°ã€‚"
msgid "Maximum size of export files."
-msgstr ""
+msgstr "匯出文件的最大大å°ã€‚"
msgid "Maximum size of import files."
-msgstr ""
+msgstr "匯入文件的最大大å°ã€‚"
msgid "Maximum size of individual attachments in comments."
-msgstr ""
+msgstr "留言中單個附件的最大大å°ã€‚"
msgid "Maximum size of pages (MB)"
-msgstr ""
+msgstr "最大é é¢å¤§å°ï¼ˆMB)"
msgid "Maximum snippet size"
-msgstr ""
+msgstr "最大代碼片段大å°"
msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
-msgstr ""
+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 "å…許使用者跳éŽé›™å› å­èº«ä»½é©—證的最長時間(以å°æ™‚為單ä½ï¼‰ã€‚設定為 0(零)以在下次登入時強制執行。"
msgid "Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited."
-msgstr ""
+msgstr "Web 終端 websocket 連接的最長時間,以秒為單ä½ï¼Œ0 表示無é™åˆ¶ã€‚"
msgid "Maximum unauthenticated API requests per rate limit period per IP"
-msgstr ""
+msgstr "æ¯å€‹ IP æ¯å€‹é€ŸçŽ‡é™åˆ¶æœŸé–“的最大未經身份驗證的 API 請求數"
msgid "Maximum unauthenticated web requests per rate limit period per IP"
-msgstr ""
+msgstr "æ¯å€‹ IP æ¯å€‹é€ŸçŽ‡é™åˆ¶æœŸé–“的最大未經身份驗證的 Web 請求"
msgid "May"
msgstr "5月"
msgid "Mean time to merge"
-msgstr ""
+msgstr "å¹³å‡åˆä½µæ™‚é–“"
msgid "Measured in bytes of code. Excludes generated and vendored code."
-msgstr ""
+msgstr "ä¾ç¨‹å¼ç¢¼çš„ä½å…ƒçµ„數測é‡ã€‚排除已產生的åŠä¾›æ‡‰å•†çš„程å¼ç¢¼ã€‚"
msgid "Medium timeout"
-msgstr ""
+msgstr "中等逾時"
msgid "Medium vulnerabilities present"
-msgstr ""
+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 ""
+msgstr "%{member_name}邀請您使用GitLab"
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
-msgstr ""
+msgstr "邀請加入 %{project_or_group} %{project_or_group_name}"
msgid "Members"
-msgstr ""
+msgstr "æˆå“¡"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
-msgstr ""
+msgstr "æˆå“¡å¯ç”±å°ˆæ¡ˆçš„%{i_open}維護者%{i_close} 或 %{i_open}所有者%{i_close}加入"
msgid "Members listed as CODEOWNERS of affected files."
-msgstr ""
+msgstr "列為å—影響文件的CODEOWNERSçš„æˆå“¡ã€‚"
msgid "Members of %{group} can also merge into this branch: %{branch}"
-msgstr ""
+msgstr "%{group}çš„æˆå“¡ä¹Ÿå¯ä»¥åˆä½µåˆ°æ­¤åˆ†æ”¯: %{branch}"
msgid "Members of %{group} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "%{group}çš„æˆå“¡ä¹Ÿå¯ä»¥æŽ¨é€åˆ°æ­¤åˆ†æ”¯: %{branch}"
msgid "Members of a group may only view projects they have permission to access"
-msgstr ""
+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[0] "如果您繼續, %{groupName} 群組將有 %{quantity} 個席次在使用中,並會收å–超é¡è²»ç”¨ã€‚"
msgid "MembersOverage|You are about to incur additional charges"
-msgstr ""
+msgstr "您å³å°‡ç”¢ç”Ÿé¡å¤–費用"
msgid "MembersOverage|Your subscription includes %d seat."
msgid_plural "MembersOverage|Your subscription includes %d seats."
-msgstr[0] ""
+msgstr[0] "您的訂閱包括 %d 個席次。"
msgid "Membership"
-msgstr ""
+msgstr "æˆå“¡è³‡æ ¼"
msgid "Members|%{time} by %{user}"
-msgstr ""
+msgstr "æ–¼%{time}ç”±%{user}"
msgid "Members|%{userName} is currently an LDAP user. Editing their permissions will override the settings from the LDAP group sync."
-msgstr ""
+msgstr "%{userName}當å‰æ˜¯LDAP使用者。編輯其權é™å°‡è¦†è“‹LDAP群組åŒæ­¥ä¸­çš„設定。"
msgid "Members|2FA"
-msgstr ""
+msgstr "2FA"
msgid "Members|An error occurred while trying to enable LDAP override, please try again."
-msgstr ""
+msgstr "嘗試啟用LDAP覆蓋時發生錯誤,請é‡è©¦ã€‚"
msgid "Members|An error occurred while trying to revert to LDAP group sync settings, please try again."
-msgstr ""
+msgstr "嘗試æ¢å¾©LDAP組åŒæ­¥è¨­å®šæ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "Members|An error occurred while updating the member's expiration date, please try again."
-msgstr ""
+msgstr "æ›´æ–°æˆå“¡åˆ°æœŸæ—¥æœŸæ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "Members|An error occurred while updating the member's role, please try again."
-msgstr ""
+msgstr "æ›´æ–°æˆå“¡è§’色時發生錯誤,請é‡è©¦ã€‚"
msgid "Members|Are you sure you want to deny %{usersName}'s request to join \"%{source}\""
-msgstr ""
+msgstr "您確定è¦æ‹’絕%{usersName}加入\"%{source}\"的請求嗎?"
msgid "Members|Are you sure you want to leave \"%{source}\"?"
-msgstr ""
+msgstr "您確定è¦é›¢é–‹\"%{source}\"嗎?"
msgid "Members|Are you sure you want to remove \"%{groupName}\"?"
-msgstr ""
+msgstr "您確定è¦ç§»é™¤\"%{groupName}\"嗎?"
msgid "Members|Are you sure you want to remove %{usersName} from \"%{source}\"?"
-msgstr ""
+msgstr "您確定è¦å¾žã€Œ%{source}ã€ä¸­ç§»é™¤%{usersName}嗎?"
msgid "Members|Are you sure you want to remove this orphaned member from \"%{source}\"?"
-msgstr ""
+msgstr "您確定è¦å¾žã€Œ%{source}ã€ä¸­ç§»é™¤é€™å€‹å­¤ç«‹çš„æˆå“¡å—Žï¼Ÿ"
msgid "Members|Are you sure you want to revoke the invitation for %{inviteEmail} to join \"%{source}\""
-msgstr ""
+msgstr "您確定è¦æ’¤éŠ· %{inviteEmail} 加入\"%{source}\"的邀請嗎"
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
-msgstr ""
+msgstr "你確定想è¦æ’¤å›žä½ å°%{source}å­˜å–請求嗎"
msgid "Members|Direct"
-msgstr ""
+msgstr "直接"
msgid "Members|Disabled"
-msgstr ""
+msgstr "å·²åœç”¨"
msgid "Members|Edit permissions"
-msgstr ""
+msgstr "編輯權é™"
msgid "Members|Enabled"
-msgstr ""
+msgstr "啟用"
msgid "Members|Expiration date removed successfully."
-msgstr ""
+msgstr "æˆåŠŸç§»é™¤éŽæœŸæ—¥æœŸã€‚"
msgid "Members|Expiration date updated successfully."
-msgstr ""
+msgstr "æˆåŠŸæ›´æ–°éŽæœŸæ—¥æœŸã€‚"
msgid "Members|Filter groups"
-msgstr ""
+msgstr "éŽæ¿¾ç¾¤çµ„"
msgid "Members|Filter members"
-msgstr ""
+msgstr "éŽæ¿¾æˆå“¡"
msgid "Members|Inherited"
-msgstr ""
+msgstr "繼承"
msgid "Members|LDAP override enabled."
-msgstr ""
+msgstr "LDAP覆蓋已啟用。"
msgid "Members|Leave \"%{source}\""
-msgstr ""
+msgstr "離開\"%{source}\""
msgid "Members|Membership"
-msgstr ""
+msgstr "æˆå“¡"
msgid "Members|Remove \"%{groupName}\""
-msgstr ""
+msgstr "移除\"%{groupName}\""
msgid "Members|Remove group"
-msgstr ""
+msgstr "移除群組"
msgid "Members|Revert to LDAP group sync settings"
-msgstr ""
+msgstr "æ¢å¾©åˆ°LDAP群組åŒæ­¥è¨­å®š"
msgid "Members|Reverted to LDAP group sync settings."
-msgstr ""
+msgstr "å·²æ¢å¾©åˆ°LDAP群組åŒæ­¥è¨­å®š."
msgid "Members|Role updated successfully."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°è§’色。"
msgid "Members|Search groups"
-msgstr ""
+msgstr "æœå°‹ç¾¤çµ„"
msgid "Members|Search invited"
-msgstr ""
+msgstr "查詢已邀請"
msgid "Member|Deny access"
-msgstr ""
+msgstr "拒絕存å–"
msgid "Member|Revoke invite"
-msgstr ""
+msgstr "撤銷邀請"
msgid "Memory Usage"
-msgstr ""
+msgstr "記憶體使用情æ³"
msgid "Menu"
-msgstr ""
+msgstr "é¸å–®"
msgid "Merge"
-msgstr ""
+msgstr "åˆä½µ"
msgid "Merge Conflicts"
-msgstr ""
+msgstr "åˆä½µè¡çª"
msgid "Merge Request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Request Analytics"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚分æž"
msgid "Merge Requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge Requests created"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚"
msgid "Merge Requests in Review"
-msgstr ""
+msgstr "審閱中的åˆä½µè«‹æ±‚"
msgid "Merge Requests merged"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚å·²åˆä½µ"
msgid "Merge automatically (%{strategy})"
-msgstr ""
+msgstr "自動åˆä½µ(%{strategy})"
msgid "Merge blocked: all merge request dependencies must be merged."
-msgstr ""
+msgstr "åˆä½µç¦æ­¢ï¼šå¿…é ˆåˆä½µæ‰€æœ‰åˆä½µè«‹æ±‚ä¾è³´é …。"
msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
-msgstr ""
+msgstr "åˆä½µè¢«ç¦æ­¢ï¼šåˆä½µè«‹æ±‚必須標記為就緒。它ä»ç„¶è¢«æ¨™è¨˜ç‚ºè‰ç¨¿ã€‚"
msgid "Merge blocked: new changes were just added."
-msgstr ""
+msgstr "åˆä½µè¢«ç¦æ­¢ï¼šå‰›å‰›åŠ å…¥äº†æ–°çš„更改。"
msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
-msgstr ""
+msgstr "åˆä½µå·²ç¦æ­¢ï¼šæµæ°´ç·šå¿…é ˆæˆåŠŸã€‚正在等待手動作業繼續。"
msgid "Merge blocked: the source branch must be rebased onto the target branch."
-msgstr ""
+msgstr "åˆä½µç¦æ­¢ï¼šä¾†æºåˆ†æ”¯å¿…須變基(rebase)到目標分支。"
msgid "Merge commit SHA"
-msgstr ""
+msgstr "åˆä½µæ交SHA"
msgid "Merge commit message"
-msgstr ""
+msgstr "åˆä½µæ交消æ¯"
msgid "Merge details"
-msgstr ""
+msgstr "åˆä½µè©³æƒ…"
msgid "Merge events"
-msgstr ""
+msgstr "åˆä½µäº‹ä»¶"
msgid "Merge immediately"
-msgstr ""
+msgstr "ç«‹å³åˆä½µ"
msgid "Merge in progress"
-msgstr ""
+msgstr "正在åˆä½µ"
msgid "Merge locally"
-msgstr ""
+msgstr "本地åˆä½µ"
msgid "Merge options"
-msgstr ""
+msgstr "åˆä½µé¸é …"
msgid "Merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚%{mr_link}已被%{mr_author}審核"
msgid "Merge request actions"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚動作"
msgid "Merge request analytics"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚分æž"
msgid "Merge request approvals"
-msgstr ""
+msgstr "批准åˆä½µè«‹æ±‚"
msgid "Merge request commits"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚æ交"
msgid "Merge request dependencies"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚ä¾è³´"
msgid "Merge request events"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚事件"
msgid "Merge request locked."
-msgstr ""
+msgstr "åˆä½µè¦æ±‚已鎖定。"
msgid "Merge request not merged"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚未åˆä½µ"
msgid "Merge request reports"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚報告"
msgid "Merge request unlocked."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已解鎖。"
msgid "Merge request was scheduled to merge after pipeline succeeds"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已安排在æµæ°´ç·šæˆåŠŸå¾Œåˆä½µ"
msgid "Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚用於æ出å°å°ˆæ¡ˆçš„變更並與他人進行討論"
msgid "Merge the feature branch into the target branch and fix any conflicts. %{linkStart}How do I fix them?%{linkEnd}"
-msgstr ""
+msgstr "將功能分支åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯ä¸¦ä¿®å¾©ä»»ä½•è¡çªã€‚ %{linkStart}我該如何修復它們?%{linkEnd}"
msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
-msgstr ""
+msgstr "åˆä½µä¸å¯ç”¨ï¼šåˆä½µè«‹æ±‚åœ¨æ¬¡è¦ Geo 節點中是唯讀的。"
msgid "Merge unverified changes"
-msgstr ""
+msgstr "åˆä½µæœªç¶“驗證的更改"
msgid "Merge unverified changes?"
-msgstr ""
+msgstr "åˆä½µæœªç¶“驗證的更改?"
msgid "Merge when pipeline succeeds"
-msgstr ""
+msgstr "當æµæ°´ç·šæˆåŠŸæ™‚åˆä½µ"
msgid "Merge..."
-msgstr ""
+msgstr "åˆä½µ"
msgid "MergeConflict|Commit to source branch"
-msgstr ""
+msgstr "æ交到æºåˆ†æ”¯"
msgid "MergeConflict|Committing..."
-msgstr ""
+msgstr "æ交..."
msgid "MergeConflict|HEAD//our changes"
-msgstr ""
+msgstr "HEAD //我們的變更"
msgid "MergeConflict|Use ours"
-msgstr ""
+msgstr "使用我們的"
msgid "MergeConflict|Use theirs"
-msgstr ""
+msgstr "使用他們的"
msgid "MergeConflict|conflict"
-msgstr ""
+msgstr "è¡çª"
msgid "MergeConflict|conflicts"
-msgstr ""
+msgstr "è¡çª"
msgid "MergeConflict|origin//their changes"
-msgstr ""
+msgstr "來æº//他們的變更"
msgid "MergeRequestAnalytics|Assignees"
-msgstr ""
+msgstr "指派人"
msgid "MergeRequestAnalytics|Date Merged"
-msgstr ""
+msgstr "åˆä½µæ—¥æœŸ"
msgid "MergeRequestAnalytics|Line changes"
-msgstr ""
+msgstr "更改行數"
msgid "MergeRequestAnalytics|Merge Request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "MergeRequestAnalytics|Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "MergeRequestAnalytics|Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "MergeRequestAnalytics|Time to merge"
-msgstr ""
+msgstr "åˆä½µæ™‚é–“"
msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
-msgstr ""
+msgstr "定義核准è¦å‰‡å’Œè¨­å®šï¼Œä»¥ç¢ºä¿æ–°åˆä½µè«‹æ±‚çš„ %{link_start}è·è²¬åˆ†é›¢%{link_end}。"
msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
-msgstr ""
+msgstr "å°æ‰€æœ‰å°ˆæ¡ˆå¼·åˆ¶åŸ·è¡Œ %{link_start}è·è²¬åˆ†é›¢%{link_end}。"
msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
-msgstr ""
+msgstr "å°æ‰€æœ‰å°ˆæ¡ˆå¼·åˆ¶åŸ·è¡Œ %{separationLinkStart}è·è²¬åˆ†é›¢%{separationLinkEnd}。%{learnLinkStart}了解更多。%{learnLinkEnd}"
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
-msgstr ""
+msgstr "å°%{selectStart}開始於%{selectEnd}到%{end}行發表評論"
msgid "MergeRequestDiffs|Select comment starting line"
-msgstr ""
+msgstr "é¸æ“‡è©•è«–起始行"
msgid "MergeRequests|An error occurred while saving the draft comment."
-msgstr ""
+msgstr "儲存留言è‰ç¨¿æ™‚發生錯誤。"
msgid "MergeRequests|Create issue to resolve thread"
-msgstr ""
+msgstr "建立議題以解決主題"
msgid "MergeRequests|Saving the comment failed"
-msgstr ""
+msgstr "儲存留言失敗"
msgid "MergeRequests|Squashing failed: Squash the commits locally, resolve any conflicts, then push the branch."
-msgstr ""
+msgstr "壓縮失敗:壓縮本地æ交,解決任何存在的è¡çªï¼Œç„¶å¾ŒæŽ¨é€åˆ†æ”¯ã€‚"
msgid "MergeRequests|Squashing not allowed: This project doesn't allow you to squash commits when merging."
-msgstr ""
+msgstr "ä¸å…許壓縮:此專案ä¸å…許您在åˆä½µæ™‚壓縮æ交。"
msgid "MergeRequests|Thread stays resolved"
-msgstr ""
+msgstr "話題ä¿æŒå·²è§£æ±ºç‹€æ…‹"
msgid "MergeRequests|Thread stays unresolved"
-msgstr ""
+msgstr "話題ä¿æŒæœªè§£æ±ºç‹€æ…‹"
msgid "MergeRequests|Thread will be resolved"
-msgstr ""
+msgstr "話題將置為解決狀態"
msgid "MergeRequests|Thread will be unresolved"
-msgstr ""
+msgstr "話題將置為未解決狀態"
msgid "MergeRequests|View file @ %{commitId}"
-msgstr ""
+msgstr "查看文件 @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr ""
+msgstr "查看已å–代文件 @ %{commitId}"
msgid "MergeRequests|commented on commit %{commitLink}"
-msgstr ""
+msgstr "討論%{commitLink}æ交"
msgid "MergeRequests|started a thread"
-msgstr ""
+msgstr "開啟新話題"
msgid "MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}"
-msgstr ""
+msgstr "開啟有關%{linkStart}舊版本差異%{linkEnd}的話題"
msgid "MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}"
-msgstr ""
+msgstr "開啟有關%{linkStart}差異%{linkEnd}的話題"
msgid "MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitDisplay}%{linkEnd}"
-msgstr ""
+msgstr "開啟有關%{linkStart}%{commitDisplay}%{linkEnd}中較舊的變更的話題"
msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
-msgstr ""
+msgstr "開啟有關æ交%{linkStart}%{commitDisplay}%{linkEnd}的話題"
msgid "MergeRequest|Approved by @%{username}"
-msgstr ""
+msgstr "由 @%{username} 核准"
msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
-msgstr ""
+msgstr "由於內部錯誤,無法顯示此åˆä½µè«‹æ±‚。請è¯ç¹«æ‚¨çš„管ç†å“¡ã€‚"
msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
-msgstr ""
+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 ""
+msgstr "無法顯示此åˆä½µè«‹æ±‚,因為æºåˆ†æ”¯ %{branch_badge} 缺少專案 %{path_badge}。關閉此åˆä½µè«‹æ±‚或更新æºåˆ†æ”¯ã€‚"
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 "無法顯示此åˆä½µè«‹æ±‚,因為專案 %{branch_badge} 中缺少目標分支 %{path_badge}。關閉此åˆä½µè«‹æ±‚或更新目標分支。"
msgid "MergeRequest|Compare %{target} and %{source}"
-msgstr ""
+msgstr "比較%{target}和%{source}"
msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
-msgstr ""
+msgstr "關閉建議彈窗時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "MergeRequest|Error loading full diff. Please try again."
-msgstr ""
+msgstr "載入完整差異時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "MergeRequest|No files found"
-msgstr ""
+msgstr "未找到任何文件"
msgid "MergeRequest|Search (e.g. *.vue) (%{modifier_key}P)"
-msgstr ""
+msgstr "æœå°‹ï¼ˆä¾‹å¦‚ *.vue)(%{modifier_key}P)"
msgid "Merged"
-msgstr ""
+msgstr "å·²åˆä½µ"
msgid "Merged MRs"
-msgstr ""
+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 ""
+msgstr "å·²åˆä½µåˆ†æ”¯æ­£åœ¨è¢«åˆªé™¤ã€‚該æ“作å¯èƒ½éœ€è¦ä¸€äº›æ™‚間,具體å–決於分支的數é‡ã€‚è«‹é‡æ–°æ•´ç†é é¢ä»¥æŸ¥çœ‹æ›´æ–°ã€‚"
msgid "Merged by"
-msgstr ""
+msgstr "åˆä½µè€…"
msgid "Merged this merge request."
-msgstr ""
+msgstr "å·²åˆä½µæ­¤åˆä½µè«‹æ±‚。"
msgid "Merged: %{merged}"
-msgstr ""
+msgstr "å·²åˆä½µ: %{merged}"
msgid "Merges this merge request immediately."
-msgstr ""
+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 ""
+msgstr "ä¸å»ºè­°ç«‹å³åˆä½µï¼Œå› ç‚ºå®ƒå¯èƒ½å°ç¾æœ‰åˆä½µåˆ—車產生ä¸åˆ©å½±éŸ¿ã€‚請查閱%{docsLinkStart}文件%{docsLinkEnd}以了解更多訊æ¯ã€‚"
msgid "Mermaid diagram"
-msgstr ""
+msgstr "Mermaid 圖表"
msgid "Message"
-msgstr ""
+msgstr "消æ¯"
msgid "Messages"
-msgstr ""
+msgstr "消æ¯"
msgid "Method"
-msgstr ""
+msgstr "方法"
msgid "Method call threshold (ms)"
-msgstr ""
+msgstr "方法調用閾值(毫秒)"
msgid "Metric was successfully added."
-msgstr ""
+msgstr "指標已æˆåŠŸåŠ å…¥ã€‚"
msgid "Metric was successfully updated."
-msgstr ""
+msgstr "指標已æˆåŠŸæ›´æ–°ã€‚"
msgid "Metric:"
-msgstr ""
+msgstr "指標:"
msgid "MetricChart|Please select a metric"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹æŒ‡æ¨™"
msgid "MetricChart|Selected"
-msgstr ""
+msgstr "é¸å–çš„"
msgid "MetricChart|There is no data available. Please change your selection."
-msgstr ""
+msgstr "沒有å¯ç”¨è³‡æ–™ã€‚請更改é¸æ“‡ã€‚"
msgid "MetricChart|There is too much data to calculate. Please change your selection."
-msgstr ""
+msgstr "資料太多無法計算。請更改您的é¸æ“‡ã€‚"
msgid "MetricImages|There was an issue deleting the image."
-msgstr ""
+msgstr "刪除圖åƒæ™‚出ç¾å•é¡Œã€‚"
msgid "MetricImages|There was an issue loading metric images."
-msgstr ""
+msgstr "載入指標圖åƒæ™‚出ç¾å•é¡Œã€‚"
msgid "MetricImages|There was an issue updating your image."
-msgstr ""
+msgstr "更新圖åƒæ™‚出ç¾å•é¡Œã€‚"
msgid "MetricImages|There was an issue uploading your image."
-msgstr ""
+msgstr "上傳圖åƒæ™‚出ç¾å•é¡Œã€‚"
msgid "Metrics"
-msgstr ""
+msgstr "指標"
msgid "Metrics - Grafana"
-msgstr ""
+msgstr "指標 - Grafana"
msgid "Metrics - Prometheus"
-msgstr ""
+msgstr "指標 - Prometheus"
msgid "Metrics Dashboard"
-msgstr ""
+msgstr "指標儀表æ¿"
msgid "Metrics Dashboard YAML definition"
-msgstr ""
+msgstr "指標儀表æ¿YAML定義"
msgid "Metrics Dashboard YAML definition is invalid:"
-msgstr ""
+msgstr "指標儀表æ¿YAML定義無效:"
msgid "Metrics Dashboard YAML definition is valid."
-msgstr ""
+msgstr "指標儀表æ¿YAML定義有效。"
msgid "Metrics and profiling"
-msgstr ""
+msgstr "指標與分æž"
msgid "Metrics:"
-msgstr ""
+msgstr "指標:"
msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
+msgstr "註解ä¸èƒ½åŒæ™‚屬於一個集群和一個環境"
msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
-msgstr ""
+msgstr "註解未被刪除"
msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
-msgstr ""
+msgstr "註解必須屬於一個集群或一個環境"
msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "找ä¸åˆ°è«‹æ±‚路徑的儀表æ¿"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
-msgstr ""
+msgstr "您沒有權é™ç‚ºæ‰€é¸å¢é›†å»ºç«‹è¨»è§£"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
-msgstr ""
+msgstr "您沒有權é™ç‚ºæ‰€é¸ç’°å¢ƒå»ºç«‹è¨»è§£"
msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
-msgstr ""
+msgstr "您沒有權é™åˆªé™¤æ­¤è¨»è§£"
msgid "MetricsDashboardAnnotation|can't be before starting_at time"
-msgstr ""
+msgstr "ä¸èƒ½åœ¨ starting_at 時間之å‰"
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
-msgstr ""
+msgstr "å‘指標儀表æ¿åŠ å…¥ä¸€å€‹æŒ‰éˆ•ï¼Œç›´æŽ¥é€£çµåˆ°æ‚¨ç¾æœ‰å¤–部的儀表æ¿ã€‚"
msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
-msgstr ""
+msgstr "é¸æ“‡æ˜¯ä»¥UTC還是使用者本地時å€é¡¯ç¤ºå„€è¡¨æ¿æŒ‡æ¨™ã€‚"
msgid "MetricsSettings|Dashboard timezone"
-msgstr ""
+msgstr "儀表æ¿æ™‚å€"
msgid "MetricsSettings|External dashboard URL"
-msgstr ""
+msgstr "外部儀表æ¿URL"
msgid "MetricsSettings|Manage metrics dashboard settings."
-msgstr ""
+msgstr "管ç†æŒ‡æ¨™å„€è¡¨æ¿è¨­å®š"
msgid "MetricsSettings|Metrics"
-msgstr ""
+msgstr "指標"
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
-msgstr ""
+msgstr "UTC(世界標準時間)"
msgid "MetricsSettings|User's local timezone"
-msgstr ""
+msgstr "使用者本地時å€"
msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "找ä¸åˆ°è¦æ±‚路徑的儀表æ¿"
msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
-msgstr ""
+msgstr "您無權å‘此儀表æ¿åŠ å…¥æ˜Ÿè™Ÿ"
msgid "Metrics|1. Define and preview panel"
-msgstr ""
+msgstr "1. 定義和é è¦½é¢æ¿"
msgid "Metrics|2. Paste panel YAML into dashboard"
-msgstr ""
+msgstr "2. å°‡é¢æ¿YAML貼上到儀表æ¿"
msgid "Metrics|Add metric"
-msgstr ""
+msgstr "加入指標"
msgid "Metrics|Add panel"
-msgstr ""
+msgstr "加入é¢æ¿"
msgid "Metrics|Avg"
-msgstr ""
+msgstr "å¹³å‡"
msgid "Metrics|Back to dashboard"
-msgstr ""
+msgstr "返回到儀表æ¿"
msgid "Metrics|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
-msgstr ""
+msgstr "查看有關部署到環境的CI/CD文件"
msgid "Metrics|Collapse panel"
-msgstr ""
+msgstr "收起é¢æ¿"
msgid "Metrics|Collapse panel (Esc)"
-msgstr ""
+msgstr "收起é¢æ¿(Esc)"
msgid "Metrics|Copy YAML"
-msgstr ""
+msgstr "複製YAML"
msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
-msgstr ""
+msgstr "複製並貼上é¢æ¿YAML到您的儀表æ¿YAML文件。"
msgid "Metrics|Create custom dashboard %{fileName}"
-msgstr ""
+msgstr "å»ºç«‹è‡ªè¨‚å„€è¡¨æ¿ %{fileName}"
msgid "Metrics|Create metric"
-msgstr ""
+msgstr "建立指標"
msgid "Metrics|Create new dashboard"
-msgstr ""
+msgstr "建立新儀表æ¿"
msgid "Metrics|Create your dashboard configuration file"
-msgstr ""
+msgstr "建立儀表æ¿é…置文件"
msgid "Metrics|Current"
-msgstr ""
+msgstr "當å‰"
msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "儀表æ¿æ–‡ä»¶å¯ä»¥åœ¨æ­¤å°ˆæ¡ˆçš„根目錄下%{codeStart}.gitlab/dashboards%{codeEnd}中找到。"
msgid "Metrics|Define panel YAML below to preview panel."
-msgstr ""
+msgstr "在下é¢å®šç¾©é¢æ¿YAML以é è¦½é¢æ¿ã€‚"
msgid "Metrics|Delete metric"
-msgstr ""
+msgstr "刪除指標"
msgid "Metrics|Delete metric?"
-msgstr ""
+msgstr "刪除指標?"
msgid "Metrics|Duplicate"
-msgstr ""
+msgstr "複製"
msgid "Metrics|Duplicate current dashboard"
-msgstr ""
+msgstr "複製當å‰å„€è¡¨æ¿"
msgid "Metrics|Duplicate dashboard"
-msgstr ""
+msgstr "複製儀表æ¿"
msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
-msgstr ""
+msgstr "複製此儀表æ¿ä»¥åŠ å…¥é¢æ¿æˆ–編輯儀表æ¿YAML。"
msgid "Metrics|Duplicating..."
-msgstr ""
+msgstr "正在複製..."
msgid "Metrics|Edit dashboard YAML"
-msgstr ""
+msgstr "編輯儀表æ¿YAML"
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
-msgstr[0] ""
+msgstr[0] "編輯指標"
msgid "Metrics|Expand panel"
-msgstr ""
+msgstr "展開é¢æ¿"
msgid "Metrics|For grouping similar metrics"
-msgstr ""
+msgstr "用於分組類似指標"
msgid "Metrics|Invalid time range, please verify."
-msgstr ""
+msgstr "無效的時間範åœï¼Œè«‹é©—證。"
msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
-msgstr ""
+msgstr "Y軸是標籤(通常是單ä½)。X軸總是代表時間。"
msgid "Metrics|Legend label (optional)"
-msgstr ""
+msgstr "圖例標籤(å¯é¸ï¼‰"
msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
-msgstr ""
+msgstr "連çµåŒ…å«ç„¡æ•ˆçš„時間視窗 (time window),請驗證連çµä»¥æª¢è¦–請求的時間範åœã€‚"
msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
-msgstr ""
+msgstr "連çµåŒ…å«ç„¡æ•ˆçš„圖表訊æ¯ï¼Œè«‹é©—證連çµä»¥æŸ¥çœ‹å±•é–‹å¾Œçš„é¢æ¿ã€‚"
msgid "Metrics|Manage chart links"
-msgstr ""
+msgstr "管ç†åœ–表連çµ"
msgid "Metrics|Max"
-msgstr ""
+msgstr "最大值"
msgid "Metrics|Metrics Settings"
-msgstr ""
+msgstr "指標設定"
msgid "Metrics|Min"
-msgstr ""
+msgstr "最å°å€¼"
msgid "Metrics|More actions"
-msgstr ""
+msgstr "更多動作"
msgid "Metrics|Must be a valid PromQL query."
-msgstr ""
+msgstr "必須是有效的 PromQL 查詢。"
msgid "Metrics|New metric"
-msgstr ""
+msgstr "建立指標"
msgid "Metrics|Open repository"
-msgstr ""
+msgstr "開啟版本庫"
msgid "Metrics|Panel YAML"
-msgstr ""
+msgstr "é¢æ¿YAML"
msgid "Metrics|Panel YAML copied"
-msgstr ""
+msgstr "é¢æ¿YAML已複製"
msgid "Metrics|Preview panel"
-msgstr ""
+msgstr "é è¦½é¢æ¿"
msgid "Metrics|PromQL query is valid"
-msgstr ""
+msgstr "PromotQL 查詢有效"
msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
+msgstr "Prometheus查詢文件"
msgid "Metrics|Refresh Prometheus data"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†Prometheus資料"
msgid "Metrics|Refresh dashboard"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†å„€è¡¨æ¿"
msgid "Metrics|Select a value"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å€¼"
msgid "Metrics|Set refresh rate"
-msgstr ""
+msgstr "設定刷新率"
msgid "Metrics|Star dashboard"
-msgstr ""
+msgstr "星號儀表æ¿"
msgid "Metrics|There was an error creating the dashboard."
-msgstr ""
+msgstr "建立儀表æ¿æ™‚發生錯誤。"
msgid "Metrics|There was an error creating the dashboard. %{error}"
-msgstr ""
+msgstr "建立儀表æ¿æ™‚發生錯誤。 %{error}"
msgid "Metrics|There was an error fetching annotations. Please try again."
-msgstr ""
+msgstr "å–得註解時發生錯誤。請é‡è©¦ã€‚"
msgid "Metrics|There was an error fetching the environments data, please try again"
-msgstr ""
+msgstr "å–得環境資料時發生錯誤,請é‡è©¦"
msgid "Metrics|There was an error getting annotations information."
-msgstr ""
+msgstr "å–得註解資訊時發生錯誤。"
msgid "Metrics|There was an error getting dashboard validation warnings information."
-msgstr ""
+msgstr "å–得儀表æ¿é©—證警告資訊時發生錯誤。"
msgid "Metrics|There was an error getting deployment information."
-msgstr ""
+msgstr "å–得部署訊æ¯æ™‚發生錯誤。"
msgid "Metrics|There was an error getting environments information."
-msgstr ""
+msgstr "å–得環境訊æ¯æ™‚發生錯誤。"
msgid "Metrics|There was an error getting options for variable \"%{name}\"."
-msgstr ""
+msgstr "å–得變數\"%{name}\"çš„é¸é …時發生錯誤。"
msgid "Metrics|There was an error trying to validate your query"
-msgstr ""
+msgstr "嘗試驗證您的查詢時發生錯誤"
msgid "Metrics|There was an error while retrieving metrics"
-msgstr ""
+msgstr "檢索度é‡æ¨™æº–時出錯"
msgid "Metrics|There was an error while retrieving metrics. %{message}"
-msgstr ""
+msgstr "讀å–指標時發生錯誤。%{message}"
msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "è¦å»ºç«‹æ–°çš„儀表æ¿ï¼Œè«‹å°‡æ–°çš„YAML文件加入到該專案的根目錄下%{codeStart}.gitlab /dashboards%{codeEnd}中。"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
-msgstr ""
+msgstr "來自Prometheus終端節點的æ„外部署資料響應"
msgid "Metrics|Unit label"
-msgstr ""
+msgstr "å–®ä½æ¨™ç±¤"
msgid "Metrics|Unstar dashboard"
-msgstr ""
+msgstr "å–消儀表æ¿æ˜Ÿè™Ÿ"
msgid "Metrics|Used as a title for the chart"
-msgstr ""
+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 ""
+msgstr "用於查詢返回單個系列時。如果返回多個系列,相應的圖例標籤將從返回資料中é¸å–。"
msgid "Metrics|Validating query"
-msgstr ""
+msgstr "正在驗證查詢"
msgid "Metrics|Values"
-msgstr ""
+msgstr "值"
msgid "Metrics|View documentation"
-msgstr ""
+msgstr "查看文件"
msgid "Metrics|Y-axis label"
-msgstr ""
+msgstr "Y軸標記"
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 ""
+msgstr "您能夠儲存儀表æ¿çš„副本到版本庫以供自訂。請é¸æ“‡æª”案å稱åŠåˆ†æ”¯ä»¥å„²å­˜ã€‚"
msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
-msgstr ""
+msgstr "您å³å°‡æ°¸ä¹…刪除此指標且無法復原。"
msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
-msgstr ""
+msgstr "您的儀表æ¿æ¦‚è¦ç„¡æ•ˆã€‚編輯儀表æ¿ä»¥ä¿®æ­£YAML概è¦ã€‚"
msgid "Metrics|e.g. HTTP requests"
-msgstr ""
+msgstr "例如:HTTP 請求"
msgid "Metrics|e.g. Requests/second"
-msgstr ""
+msgstr "例如:請求/秒"
msgid "Metrics|e.g. Throughput"
-msgstr ""
+msgstr "例如:åžåé‡"
msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
+msgstr "例如:速率(http_requests_total[5m])"
msgid "Metrics|e.g. req/sec"
-msgstr ""
+msgstr "例如:req / sec"
msgid "Mi"
-msgstr ""
+msgstr "Mi"
msgid "Migrated %{success_count}/%{total_count} files."
-msgstr ""
+msgstr "å·²é·ç§» %{success_count}/%{total_count} 文件。"
msgid "Migration"
-msgstr ""
+msgstr "é·ç§»(å‡ç´š)"
msgid "Migration has been scheduled to be retried"
-msgstr ""
+msgstr "已計劃é‡è©¦é·ç§»"
msgid "Migration successful."
-msgstr ""
+msgstr "é·ç§»æˆåŠŸã€‚"
msgid "Milestone"
msgid_plural "Milestones"
-msgstr[0] ""
+msgstr[0] "里程碑"
msgid "Milestone due date"
-msgstr ""
+msgstr "里程碑截止日期"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "ç›®å‰æŽˆæ¬Šæ¢æ¬¾ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "MilestoneCombobox|An error occurred while searching for milestones"
-msgstr ""
+msgstr "æœå°‹é‡Œç¨‹ç¢‘時發生錯誤"
msgid "MilestoneCombobox|Group milestones"
-msgstr ""
+msgstr "群組里程碑"
msgid "MilestoneCombobox|Milestone"
-msgstr ""
+msgstr "里程碑"
msgid "MilestoneCombobox|No matching results"
-msgstr ""
+msgstr "沒有相符的çµæžœ"
msgid "MilestoneCombobox|No milestone"
-msgstr ""
+msgstr "無里程碑"
msgid "MilestoneCombobox|Project milestones"
-msgstr ""
+msgstr "專案里程碑"
msgid "MilestoneCombobox|Search Milestones"
-msgstr ""
+msgstr "æœå°‹é‡Œç¨‹ç¢‘"
msgid "MilestoneCombobox|Select milestone"
-msgstr ""
+msgstr "é¸æ“‡é‡Œç¨‹ç¢‘"
msgid "MilestoneSidebar|Closed:"
-msgstr ""
+msgstr "關閉:"
msgid "MilestoneSidebar|Copy reference"
-msgstr ""
+msgstr "複製åƒç…§"
msgid "MilestoneSidebar|Due date"
-msgstr ""
+msgstr "截止日期"
msgid "MilestoneSidebar|Edit"
-msgstr ""
+msgstr "編輯"
msgid "MilestoneSidebar|From"
-msgstr ""
+msgstr "從"
msgid "MilestoneSidebar|Issues"
-msgstr ""
+msgstr "議題"
msgid "MilestoneSidebar|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "MilestoneSidebar|Merged:"
-msgstr ""
+msgstr "åˆä½µï¼š"
msgid "MilestoneSidebar|New Issue"
-msgstr ""
+msgstr "新建議題"
msgid "MilestoneSidebar|New issue"
-msgstr ""
+msgstr "新建議題"
msgid "MilestoneSidebar|No due date"
-msgstr ""
+msgstr "無截止日期"
msgid "MilestoneSidebar|No start date"
-msgstr ""
+msgstr "無開始日期"
msgid "MilestoneSidebar|None"
-msgstr ""
+msgstr "ç„¡"
msgid "MilestoneSidebar|Open:"
-msgstr ""
+msgstr "開啟:"
msgid "MilestoneSidebar|Reference:"
-msgstr ""
+msgstr "åƒç…§é€£çµï¼š"
msgid "MilestoneSidebar|Start date"
-msgstr ""
+msgstr "起始日期"
msgid "MilestoneSidebar|Toggle sidebar"
-msgstr ""
+msgstr "切æ›å´é‚Šæ¬„"
msgid "MilestoneSidebar|Until"
-msgstr ""
+msgstr "直到"
msgid "MilestoneSidebar|complete"
-msgstr ""
+msgstr "完æˆ"
msgid "Milestones"
-msgstr ""
+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 ""
+msgstr "您å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle} 並將其從 %{issuesWithCount} å’Œ %{mergeRequestsWithCount} 刪除。刪除後,無法撤消或æ¢å¾©ã€‚"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
+msgstr "您å³å°‡æ°¸ä¹…刪除里程碑 %{milestoneTitle}。此里程碑當å‰æœªç”¨æ–¼ä»»ä½•è­°é¡Œæˆ–åˆä½µè«‹æ±‚。"
msgid "Milestones|Close Milestone"
-msgstr ""
+msgstr "關閉里程碑"
msgid "Milestones|Completed Issues (closed)"
-msgstr ""
+msgstr "已完æˆçš„è­°é¡Œ(已關閉)"
msgid "Milestones|Create a milestone to better track your issues and merge requests. %{learn_more_link}"
-msgstr ""
+msgstr "建立一個里程碑來更好地追蹤您的議題和åˆä½µè«‹æ±‚。%{learn_more_link}"
msgid "Milestones|Delete milestone"
-msgstr ""
+msgstr "刪除里程碑"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
msgstr "刪除里程碑 %{milestoneTitle} ?"
@@ -24992,21743 +25199,22048 @@ msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
msgstr "刪除里程碑 %{milestoneTitle} 時發生錯誤"
msgid "Milestones|Group Milestone"
-msgstr ""
+msgstr "群組里程碑"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
msgstr "找ä¸åˆ°é‡Œç¨‹ç¢‘ %{milestoneTitle}"
msgid "Milestones|Ongoing Issues (open and assigned)"
-msgstr ""
+msgstr "處ç†ä¸­çš„è­°é¡Œ(開啟且已指派)"
msgid "Milestones|Organize issues and merge requests into a cohesive group, and set optional start and due dates. %{learn_more_link}"
-msgstr ""
+msgstr "將議題與åˆä½µè«‹æ±‚組織到一個有å‡èšåŠ›çš„群組中,並設定å¯é¸çš„起始日期和截止日期。%{learn_more_link}"
msgid "Milestones|Project Milestone"
-msgstr ""
+msgstr "專案里程碑"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
msgstr "å°‡ %{milestoneTitle} å‡ç´šç‚ºç¾¤çµ„里程碑?"
msgid "Milestones|Promote Milestone"
-msgstr ""
+msgstr "å‡ç´šé‡Œç¨‹ç¢‘"
msgid "Milestones|Promote to Group Milestone"
-msgstr ""
+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 ""
+msgstr "å‡ç´š%{milestoneTitle}後,該里程碑將å¯ç”¨æ–¼%{groupName}群組內的所有專案。如果ç¾æœ‰å°ˆæ¡ˆé‡Œç¨‹ç¢‘具有相åŒæ¨™é¡Œï¼Œé€™äº›é …目里程碑被åˆä½µå…¥ç¾¤çµ„里程碑。"
msgid "Milestones|Reopen Milestone"
-msgstr ""
+msgstr "é‡å•Ÿé‡Œç¨‹ç¢‘"
msgid "Milestones|There are no closed milestones"
-msgstr ""
+msgstr "沒有已關閉的里程碑"
msgid "Milestones|There are no open milestones"
-msgstr ""
+msgstr "沒有開放的里程碑"
msgid "Milestones|This action cannot be reversed."
-msgstr ""
+msgstr "該æ“作無法復原。"
msgid "Milestones|Unstarted Issues (open and unassigned)"
-msgstr ""
+msgstr "未開始的議題(開啟且尚未指派)"
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
-msgstr ""
+msgstr "使用里程碑在固定時間內追蹤議題和åˆä½µè«‹æ±‚"
msgid "Min Value"
-msgstr ""
+msgstr "最å°å€¼"
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
-msgstr ""
+msgstr "在我們é å…ˆå®‰æŽ’更多映åƒä¹‹å‰å¯ç”¨çš„最å°å®¹é‡ã€‚"
msgid "Minutes"
-msgstr ""
+msgstr "分é˜"
msgid "Mirror direction"
-msgstr ""
+msgstr "é¡åƒæ–¹å‘"
msgid "Mirror only protected branches"
-msgstr ""
+msgstr "僅é¡åƒå—ä¿è­·çš„分支"
msgid "Mirror repository"
-msgstr ""
+msgstr "é¡åƒç‰ˆæœ¬åº«"
msgid "Mirror settings are only available to GitLab administrators."
-msgstr ""
+msgstr "é¡åƒè¨­å®šåƒ…GitLab管ç†å“¡å¯ç”¨ã€‚"
msgid "Mirror user"
-msgstr ""
+msgstr "é¡åƒä½¿ç”¨è€…"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "é¡åƒçš„版本庫"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "é¡åƒç‰ˆæœ¬åº«"
msgid "Mirroring settings were successfully updated."
-msgstr ""
+msgstr "é¡åƒè¨­å®šå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Mirroring settings were successfully updated. The project is being updated."
-msgstr ""
+msgstr "é¡åƒè¨­å®šå·²æˆåŠŸæ›´æ–°ã€‚正在更新該專案。"
msgid "Mirroring was successfully disabled."
-msgstr ""
+msgstr "é¡åƒå·²æˆåŠŸåœç”¨ã€‚"
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
-msgstr ""
+msgstr "åªæœ‰åœ¨æ‰€é¸ç¾¤çµ„或使用者的計劃中包å«é¡åƒåŠŸèƒ½æ™‚,æ‰èƒ½ä½¿ç”¨ã€‚"
msgid "Miscellaneous"
-msgstr ""
+msgstr "雜項"
msgid "Missing"
-msgstr ""
+msgstr "éºå¤±"
msgid "Missing OAuth configuration for GitHub."
-msgstr ""
+msgstr "缺少GitHubçš„OAuthé…置。"
msgid "Missing OS"
-msgstr ""
+msgstr "缺少æ“作系統"
msgid "Missing arch"
-msgstr ""
+msgstr "缺少架構"
msgid "Missing commit signatures endpoint!"
-msgstr ""
+msgstr "缺少æ交簽å節點ï¼"
msgid "MissingSSHKeyWarningLink|Add SSH key"
-msgstr ""
+msgstr "加入SSH金鑰"
msgid "MissingSSHKeyWarningLink|Don't show again"
-msgstr ""
+msgstr "ä¸å†é¡¯ç¤º"
msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
-msgstr ""
+msgstr "在您個人資料中加入SSH金鑰之å‰ï¼Œæ‚¨ç„¡æ³•é€šéŽSSH來拉å–或推é€ç‰ˆæœ¬åº«ã€‚"
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 "在您個人資料中加入SSH金鑰之å‰ï¼Œæ‚¨å°‡ä¸èƒ½é€šéŽSSH來拉å–或推é€ç‰ˆæœ¬åº«ã€‚"
msgid "ModalButton|Add projects"
-msgstr ""
+msgstr "加入專案"
msgid "Modal|Close"
-msgstr ""
+msgstr "關閉"
msgid "Modified"
-msgstr ""
+msgstr "已修改"
msgid "Modified in this version"
-msgstr ""
+msgstr "此版本修改"
msgid "Modify commit message"
-msgstr ""
+msgstr "修改æ交訊æ¯"
msgid "Modify commit messages"
-msgstr ""
+msgstr "修改æ交消æ¯"
msgid "Modify merge commit"
-msgstr ""
+msgstr "修改åˆä½µæ交"
msgid "Monday"
-msgstr ""
+msgstr "星期一"
msgid "Monitor"
-msgstr ""
+msgstr "監控"
msgid "Monitor Settings"
-msgstr ""
+msgstr "監控設定"
msgid "Monitor the health and performance of GitLab with Prometheus."
-msgstr ""
+msgstr "用Prometheus監控 GitLab çš„å¥åº·å’Œæ€§èƒ½ã€‚"
msgid "Monitor your errors by integrating with Sentry."
-msgstr ""
+msgstr "通éŽèˆ‡Sentryæ•´åˆä¾†ç›£æŽ§æ‚¨çš„錯誤。"
msgid "Monitoring"
-msgstr ""
+msgstr "監控"
msgid "Month"
-msgstr ""
+msgstr "月"
msgid "Months"
-msgstr ""
+msgstr "月"
msgid "More Details"
-msgstr ""
+msgstr "更多詳情"
msgid "More Information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "More actions"
-msgstr ""
+msgstr "更多æ“作"
msgid "More details"
-msgstr ""
+msgstr "更多詳細訊æ¯"
msgid "More info"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "More information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "More information and share feedback"
-msgstr ""
+msgstr "更多訊æ¯å’Œå…±äº«å›žé¥‹"
msgid "More information is available|here"
-msgstr ""
+msgstr "這裡"
msgid "More information."
-msgstr ""
+msgstr "更多訊æ¯ã€‚"
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
-msgstr ""
+msgstr "è¶…å‰ %{number_commits_distance} 個æ交與 %{default_branch} ä¸åŒ"
msgid "More topics"
-msgstr ""
+msgstr "更多主題"
msgid "Most common"
-msgstr ""
+msgstr "最常見的"
msgid "Most relevant"
-msgstr ""
+msgstr "相關度最高"
msgid "Most stars"
-msgstr ""
+msgstr "最多星號"
msgid "Mount point %{mounted_as} not found in %{model_class}."
-msgstr ""
+msgstr "%{model_class} 中未找到掛載點 %{mounted_as}。"
msgid "Move"
msgstr "移動"
msgid "Move down"
-msgstr ""
+msgstr "下移"
msgid "Move issue"
-msgstr ""
+msgstr "移動議題"
msgid "Move issue from one column of the board to another"
-msgstr ""
+msgstr "將議題從看æ¿çš„一列移到å¦ä¸€åˆ—"
msgid "Move selection down"
-msgstr ""
+msgstr "下移所é¸çš„專案"
msgid "Move selection up"
-msgstr ""
+msgstr "上移所é¸çš„專案"
msgid "Move test case"
-msgstr ""
+msgstr "移動測試案例"
msgid "Move this issue to another project."
-msgstr ""
+msgstr "將此議題移至å¦ä¸€å€‹é …目。"
msgid "Move up"
-msgstr ""
+msgstr "上移"
msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
-msgstr ""
+msgstr "由於權é™ä¸è¶³è€Œç„¡æ³•ç§»å‹•è­°é¡Œ!"
msgid "MoveIssue|Cannot move issue to project it originates from!"
-msgstr ""
+msgstr "無法將議題移動到來æºå°ˆæ¡ˆä¸­!"
msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
-msgstr ""
+msgstr "無法移動「%{issue_type}ã€é¡žåž‹çš„議題。"
msgid "Moved issue to %{label} column in the board."
-msgstr ""
+msgstr "將議題移動到看æ¿ä¸­çš„%{label}列。"
msgid "Moved this issue to %{path_to_project}."
-msgstr ""
+msgstr "將此議題移動到%{path_to_project}。"
msgid "Moves issue to %{label} column in the board."
-msgstr ""
+msgstr "將議題移至看æ¿çš„ %{label} 列中。"
msgid "Moves this issue to %{path_to_project}."
-msgstr ""
+msgstr "將此議題移動到 %{path_to_project}。"
msgid "MrDeploymentActions|Deploy"
-msgstr ""
+msgstr "部署"
msgid "MrDeploymentActions|Re-deploy"
-msgstr ""
+msgstr "é‡æ–°éƒ¨ç½²"
msgid "MrDeploymentActions|Stop environment"
-msgstr ""
+msgstr "åœæ­¢ç’°å¢ƒ"
msgid "MrList|Assigned to %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from assignee %{name}"
-msgstr ""
-
-msgid "MrList|Attention requested from reviewer %{name}"
-msgstr ""
+msgstr "指派給 %{name}"
msgid "MrList|Review requested from %{name}"
-msgstr ""
+msgstr "審核來自 %{name} 的請求"
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 "如若繼續,您確èªè©²å›žæ‡‰å°‡ç”¨æ–¼æ”¹é€² GitLab ä¸¦ä¸”ç¬¦åˆ %{linkStart}GitLab éš±ç§æ”¿ç­–%{linkEnd}。"
msgid "MrSurvey|How satisfied are you with %{strongStart}speed/performance%{strongEnd} of merge requests?"
-msgstr ""
+msgstr "您å°åˆä½µè«‹æ±‚çš„ %{strongStart}速度/性能%{strongEnd} 滿æ„程度為何?"
msgid "MrSurvey|Merge request experience survey"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚經驗調查"
msgid "MrSurvey|Overall, how satisfied are you with merge requests?"
-msgstr ""
+msgstr "總體而言,您å°åˆä½µè«‹æ±‚的滿æ„度為何?"
msgid "MrSurvey|Thank you for your feedback!"
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨çš„回饋ï¼"
msgid "Multi-project"
-msgstr ""
+msgstr "多專案"
msgid "Multiple HTTP integrations are not supported for this project"
-msgstr ""
+msgstr "此專案ä¸æ”¯æ´å¤šå€‹HTTPæ•´åˆ"
-msgid "Multiple IP address ranges are supported."
-msgstr ""
+msgid "Multiple IP address ranges are supported. Does not affect access to the group's settings."
+msgstr "支æ´å¤šå€‹ IP 地å€ç¯„åœã€‚ä¸æœƒå½±éŸ¿å°ç¾¤çµ„設定的存å–。"
msgid "Multiple Prometheus integrations are not supported"
-msgstr ""
+msgstr "ä¸æ”¯æ´å¤šå€‹Prometheusæ•´åˆ"
msgid "Multiple model types found: %{model_types}"
-msgstr ""
+msgstr "找到多個模型類型: %{model_types}"
msgid "Multiple uploaders found: %{uploader_types}"
-msgstr ""
+msgstr "找到多個上傳器: %{uploader_types}"
msgid "Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1."
-msgstr ""
+msgstr "應用於輪詢間隔的乘數。支æ´å進制值。é è¨­ç‚º 1。"
msgid "My awesome group"
-msgstr ""
+msgstr "我最棒的團隊"
msgid "My company or team"
-msgstr ""
+msgstr "我的公å¸æˆ–團隊"
msgid "My topic"
-msgstr ""
+msgstr "我的主題"
msgid "My-Reaction"
-msgstr ""
+msgstr "我的å應"
msgid "NEW"
-msgstr ""
+msgstr "新建"
msgid "Name"
-msgstr ""
+msgstr "å稱"
msgid "Name can't be blank"
-msgstr ""
+msgstr "å稱ä¸èƒ½ç‚ºç©º"
msgid "Name has already been taken"
-msgstr ""
+msgstr "å稱已被使用"
msgid "Name is already taken."
-msgstr ""
+msgstr "å稱已被佔用。"
msgid "Name new label"
-msgstr ""
+msgstr "命å新標記"
msgid "Name:"
-msgstr ""
+msgstr "å稱:"
msgid "Namespace"
-msgstr ""
+msgstr "命å空間"
msgid "Namespace ID:"
-msgstr ""
+msgstr "命å空間ID:"
msgid "Namespace:"
-msgstr ""
+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[0] "%{namespace_name}包å«%{locked_project_count}個鎖定的專案"
msgid "NamespaceStorageSize|%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr ""
+msgstr "%{namespace_name}ç›®å‰ç‚ºå”¯è®€ç‹€æ…‹ã€‚您ä¸èƒ½ï¼š%{base_message}"
msgid "NamespaceStorageSize|If you reach 100%% storage capacity, you will not be able to: %{base_message}"
-msgstr ""
+msgstr "如果您已使用100%%儲存容é‡ï¼Œæ‚¨å°‡ç„¡æ³•: %{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 "請購買更多的儲存空間以解鎖超éŽå…è²»%{free_size_limit}é™åˆ¶çš„專案。您ä¸èƒ½ %{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 "您已經用盡所有更多的儲存空間,請購買更多空間以解鎖超éŽå…è²»%{free_size_limit}é™åˆ¶çš„專案。您ä¸èƒ½ %{base_message}"
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
-msgstr ""
+msgstr "您已使用了%{namespace_name}儲存空間的%{usage_in_percent}(總計%{storage_limit},已使用%{used_storage})"
msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
-msgstr ""
+msgstr "您已經é”到了一個或多個專案的 %{free_size_limit} çš„å…費儲存é™åˆ¶ã€‚"
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
-msgstr ""
+msgstr "推é€åˆ°æ‚¨çš„版本庫,建立æµæ°´ç·šï¼Œå»ºç«‹è­°é¡Œæˆ–加入留言評論。如需減少儲存空間使用,請刪除未使用的版本庫,產物,wiki,議題和æµæ°´ç·šã€‚"
msgid "NamespaceStorage|%{name_with_link} namespace has approximately %{percent} (%{size}) namespace storage space remaining."
-msgstr ""
+msgstr "%{name_with_link} 命å空間剩餘大約 %{percent} (%{size}) 命å空間的存儲空間。"
msgid "NamespaceStorage|%{name_with_link} namespace has exceeded its namespace storage limit."
-msgstr ""
+msgstr "%{name_with_link} 命å空間已超出其命å空間儲存é™åˆ¶ã€‚"
msgid "NamespaceStorage|%{name}(%{url}) namespace has approximately %{percent} (%{size}) namespace storage space remaining."
-msgstr ""
+msgstr "%{name}(%{url})å稱空間剩餘大約 %{percent} (%{size}) 命å空間的儲存空間。"
msgid "NamespaceStorage|%{name}(%{url}) namespace has exceeded its namespace storage limit."
-msgstr ""
+msgstr "%{name}(%{url}) 命å空間已超出其命å空間儲存é™åˆ¶ã€‚"
msgid "NamespaceStorage|Action required: Approximately %{percentage_of_available_storage}%% of namespace storage remains for %{namespace_name}"
-msgstr ""
+msgstr "需è¦æŽ¡å–的措施:大約 %{percentage_of_available_storage}%% 的命å空間儲存留給 %{namespace_name}"
msgid "NamespaceStorage|Action required: Storage has been exceeded for %{namespace_name}"
-msgstr ""
+msgstr "需è¦æŽ¡å–的措施:已超出 %{namespace_name} 的儲存空間"
msgid "NamespaceStorage|Buy more storage"
-msgstr ""
+msgstr "購買更多儲存"
msgid "NamespaceStorage|We recommend that you buy additional storage to ensure your service is not interrupted."
-msgstr ""
+msgstr "我們建議您購買é¡å¤–儲存,確ä¿æ‚¨çš„æœå‹™ä¸ä¸­æ–·ã€‚"
msgid "NamespaceStorage|We recommend that you buy additional storage to resume normal service."
-msgstr ""
+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 ""
+msgstr "需è¦å¯©æ ¸çš„使用者必須由群組所有者審核。了解更多關於%{user_caps_link_start}使用者上é™%{link_end}å’Œ%{users_pending_approval_link_start}使用者等待核准%{link_end}的訊æ¯ã€‚"
msgid "NamespaceUserCap|View pending approvals"
-msgstr ""
+msgstr "查看等待處ç†çš„審核"
msgid "NamespaceUserCap|Your group has reached its billable member limit"
-msgstr ""
+msgstr "您的群組已é”到å¯è¨ˆè²»æˆå“¡ä¸Šé™"
msgid "Namespaces"
-msgstr ""
+msgstr "命å空間"
msgid "Namespaces to index"
-msgstr ""
+msgstr "è¦ç´¢å¼•çš„命å空間"
msgid "Naming, topics, avatar"
-msgstr ""
+msgstr "命å,主題,頭åƒ"
msgid "Naming, visibility"
-msgstr ""
+msgstr "å稱與å¯è¦‹æ€§"
msgid "Navigate to the project to close the milestone."
-msgstr ""
+msgstr "å‰å¾€è©²å°ˆæ¡ˆä»¥é—œé–‰é‡Œç¨‹ç¢‘。"
msgid "Navigation bar"
-msgstr ""
+msgstr "導覽欄"
msgid "NavigationTheme|Blue"
-msgstr ""
+msgstr "è—色"
msgid "NavigationTheme|Dark Mode (alpha)"
-msgstr ""
+msgstr "深色模å¼ï¼ˆalpha)"
msgid "NavigationTheme|Gray"
-msgstr ""
+msgstr "ç°è‰²"
msgid "NavigationTheme|Green"
-msgstr ""
+msgstr "綠色"
msgid "NavigationTheme|Indigo"
-msgstr ""
+msgstr "é›è—"
msgid "NavigationTheme|Light Blue"
-msgstr ""
+msgstr "æ·ºè—"
msgid "NavigationTheme|Light Gray"
-msgstr ""
+msgstr "æ·ºç°è‰²"
msgid "NavigationTheme|Light Green"
-msgstr ""
+msgstr "淺綠"
msgid "NavigationTheme|Light Indigo"
-msgstr ""
+msgstr "æ·ºé›è—"
msgid "NavigationTheme|Light Red"
-msgstr ""
+msgstr "淺紅"
msgid "NavigationTheme|Red"
-msgstr ""
+msgstr "紅色"
msgid "Nav|Help"
-msgstr ""
+msgstr "幫助"
msgid "Nav|Home"
-msgstr ""
+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 ""
-
-msgid "Need your attention"
-msgstr ""
+msgstr "需è¦å¹«åŠ©å—Žï¼Ÿ"
msgid "Needs"
-msgstr ""
+msgstr "需è¦"
msgid "Needs attention"
-msgstr ""
+msgstr "需è¦é—œæ³¨"
msgid "Network"
-msgstr ""
+msgstr "網路"
msgid "Network:"
-msgstr ""
+msgstr "網路:"
msgid "Never"
-msgstr ""
+msgstr "從ä¸"
msgid "New"
msgstr "新增"
msgid "New %{type} in %{project}"
-msgstr ""
+msgstr "在 %{project} 中新建 %{type}"
msgid "New Application"
-msgstr ""
+msgstr "新增應用"
msgid "New Branch"
-msgstr ""
+msgstr "新增分支"
msgid "New Deploy Key"
-msgstr ""
+msgstr "新增部署金鑰"
msgid "New Environment"
-msgstr ""
+msgstr "新建環境"
msgid "New Epic"
-msgstr ""
+msgstr "新增å²è©©"
msgid "New File"
-msgstr ""
+msgstr "新增文件"
msgid "New Group"
-msgstr ""
+msgstr "建立群組"
msgid "New Group Name"
-msgstr ""
+msgstr "新增群組å稱"
msgid "New Identity"
-msgstr ""
+msgstr "新增身份標識"
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] ""
+msgstr[0] "新增議題"
msgid "New Jira import"
-msgstr ""
+msgstr "新增Jira匯入"
msgid "New Label"
-msgstr ""
+msgstr "新標籤"
msgid "New Milestone"
-msgstr ""
+msgstr "新增里程碑"
msgid "New Pages Domain"
-msgstr ""
+msgstr "新增Pages網域"
msgid "New Password"
-msgstr ""
+msgstr "新增密碼"
msgid "New Pipeline Schedule"
-msgstr ""
+msgstr "新增æµæ°´ç·šè¨ˆåŠƒ"
msgid "New Project"
-msgstr ""
+msgstr "新增專案"
msgid "New Requirement"
-msgstr ""
+msgstr "新增需求"
msgid "New Snippet"
-msgstr ""
+msgstr "新增程å¼ç¢¼ç‰‡æ®µ"
msgid "New Test Case"
-msgstr ""
+msgstr "新增測試案例"
msgid "New User"
-msgstr ""
+msgstr "新增使用者"
msgid "New application"
-msgstr ""
+msgstr "新增應用"
msgid "New branch"
-msgstr ""
+msgstr "新增分支"
msgid "New branch unavailable"
-msgstr ""
+msgstr "新增的分支ä¸å¯ç”¨"
msgid "New confidential epic title "
-msgstr ""
+msgstr "新增機密å²è©©æ¨™é¡Œ "
msgid "New confidential issue title"
-msgstr ""
+msgstr "新增機密議題標題"
msgid "New deploy key"
-msgstr ""
+msgstr "新增部署金鑰"
msgid "New directory"
-msgstr ""
+msgstr "建立目錄"
msgid "New discussion"
-msgstr ""
+msgstr "新增討論"
msgid "New email address added"
-msgstr ""
+msgstr "已加入新電å­éƒµä»¶åœ°å€"
msgid "New environment"
-msgstr ""
+msgstr "新增環境"
msgid "New epic"
-msgstr ""
+msgstr "建立å²è©©"
msgid "New epic title"
-msgstr ""
+msgstr "新增å²è©©æ¨™é¡Œ"
msgid "New error tracking access token has been generated!"
-msgstr ""
+msgstr "已產生新的錯誤追踪存å–權æ–ï¼"
msgid "New file"
-msgstr ""
+msgstr "新增文件"
msgid "New group"
-msgstr ""
+msgstr "建立群組"
msgid "New health check access token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„執行狀æ³æª¢æŸ¥å­˜å–令牌(權æ–)ï¼"
msgid "New identity"
-msgstr ""
+msgstr "新建身份標識"
msgid "New issue"
-msgstr ""
+msgstr "新建議題"
msgid "New issue in %{project}"
-msgstr ""
+msgstr "在 %{project} 中新建議題"
msgid "New issue title"
-msgstr ""
+msgstr "新議題標題"
msgid "New iteration created"
-msgstr ""
+msgstr "已建立新的迭代"
msgid "New label"
-msgstr ""
+msgstr "新增標記"
msgid "New list"
-msgstr ""
+msgstr "新增列表"
msgid "New merge request"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚"
msgid "New milestone"
-msgstr ""
+msgstr "新增里程碑"
msgid "New name"
-msgstr ""
+msgstr "新增å稱"
msgid "New password"
-msgstr ""
+msgstr "新增密碼"
msgid "New pipelines cause older pending or running pipelines on the same branch to be cancelled."
-msgstr ""
+msgstr "æ–°æµæ°´ç·šæœƒå°Žè‡´åŒä¸€åˆ†æ”¯ä¸Šè¼ƒèˆŠçš„待處ç†æˆ–正在é‹è¡Œçš„æµæ°´ç·šè¢«å–消。"
msgid "New project"
-msgstr ""
+msgstr "新建專案"
msgid "New project page"
-msgstr ""
+msgstr "新建專案é é¢"
msgid "New project pages"
-msgstr ""
+msgstr "新建專案é é¢"
msgid "New project/repository"
-msgstr ""
+msgstr "新建專案/版本庫"
msgid "New public deploy key"
-msgstr ""
+msgstr "新建公共部署金鑰"
msgid "New related %{issueType}"
-msgstr ""
+msgstr "新建關è¯çš„ %{issueType}"
msgid "New release"
-msgstr ""
+msgstr "新建發布"
msgid "New requirement"
-msgstr ""
+msgstr "新建需求"
msgid "New response for issue #%{issue_iid}:"
-msgstr ""
+msgstr "議題#%{issue_iid}的新回復:"
msgid "New runners registration token has been generated!"
-msgstr ""
+msgstr "已生æˆæ–°çš„執行器(Runner)註冊令牌(權æ–)ï¼"
msgid "New schedule"
-msgstr ""
+msgstr "新建計劃"
msgid "New snippet"
-msgstr ""
+msgstr "新建程å¼ç¢¼ç‰‡æ®µ"
msgid "New subgroup"
-msgstr ""
+msgstr "新建å­ç¾¤çµ„"
msgid "New tag"
-msgstr ""
+msgstr "新建標籤"
msgid "New test case"
-msgstr ""
+msgstr "新增測試案例"
msgid "New topic"
-msgstr ""
+msgstr "新增主題"
msgid "New users set to external"
-msgstr ""
+msgstr "新使用者設定為外部"
msgid "New! Suggest changes directly"
-msgstr ""
+msgstr "新特性ï¼ç›´æŽ¥å»ºè­°è®Šæ›´å…§å®¹"
msgid "Newest first"
-msgstr ""
+msgstr "最新在å‰"
msgid "Newly-registered users are external by default"
-msgstr ""
+msgstr "新註冊的使用者é è¨­æ˜¯å¤–部使用者"
msgid "Next"
-msgstr ""
+msgstr "下一個"
msgid "Next commit"
-msgstr ""
+msgstr "下一次æ交"
msgid "Next design"
-msgstr ""
+msgstr "下一個設計"
msgid "Next file in diff"
-msgstr ""
+msgstr "下一個有差異的文件"
msgid "Next scan"
-msgstr ""
+msgstr "下一次掃æ"
msgid "Next unresolved discussion"
-msgstr ""
+msgstr "下一個未解決的討論"
msgid "Next update"
-msgstr ""
+msgstr "下次更新"
msgid "Nickname"
-msgstr ""
+msgstr "暱稱"
msgid "No"
msgstr "å¦"
msgid "No %{header} for this request."
-msgstr ""
+msgstr "此請求沒有%{header}。"
msgid "No %{providerTitle} repositories found"
-msgstr ""
+msgstr "找ä¸åˆ°%{providerTitle}的版本庫"
msgid "No CSV data to display."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„ CSV 資料。"
msgid "No Epic"
-msgstr ""
+msgstr "ç„¡å²è©©"
+
+msgid "No Google Cloud projects - You need at least one Google Cloud project"
+msgstr "沒有 Google Cloud 專案 - 您至少需è¦ä¸€å€‹ Google Cloud 專案"
msgid "No Matching Results"
-msgstr ""
+msgstr "無相符的çµæžœ"
msgid "No Milestone"
-msgstr ""
+msgstr "沒有里程碑"
msgid "No Scopes"
-msgstr ""
+msgstr "無範åœ"
msgid "No Work Item Link found"
-msgstr ""
+msgstr "未找到工作項éŠçµ"
msgid "No active admin user found"
-msgstr ""
+msgstr "沒有找到活動的管ç†å“¡ä½¿ç”¨è€…"
msgid "No activities found"
-msgstr ""
+msgstr "沒有發ç¾ä»»ä½•æ´»å‹•"
msgid "No application_settings found"
-msgstr ""
+msgstr "未找到應用程å¼è¨­å®š"
msgid "No approvers"
-msgstr ""
+msgstr "沒有核准人"
msgid "No artifacts found"
-msgstr ""
+msgstr "未找到產物"
msgid "No assignee"
-msgstr ""
-
-msgid "No attention request"
-msgstr ""
+msgstr "無指派人"
msgid "No authentication methods configured."
-msgstr ""
+msgstr "未é…置身份驗證方法。"
msgid "No available branches"
-msgstr ""
+msgstr "沒有å¯ç”¨çš„分支"
msgid "No branches found"
-msgstr ""
+msgstr "未發ç¾åˆ†æ”¯"
msgid "No change to this %{noun}'s draft status."
-msgstr ""
+msgstr "未變更該 %{noun} çš„è‰ç¨¿ç‹€æ…‹ã€‚"
msgid "No changes"
-msgstr ""
+msgstr "無變更內容"
msgid "No changes between %{source} and %{target}"
-msgstr ""
+msgstr "%{source}和%{target} 之間沒有變更內容"
msgid "No child epics match applied filters"
-msgstr ""
+msgstr "沒有符åˆç•¶å‰éŽæ¿¾å™¨çš„å­å²è©©"
msgid "No commenters"
-msgstr ""
+msgstr "沒有留言評論者"
msgid "No commits present here"
-msgstr ""
+msgstr "此處無æ交"
msgid "No committers"
-msgstr ""
+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 ""
+msgstr "無法連接到Gitaly伺æœå™¨ï¼Œè«‹æª¢æŸ¥ç›¸é—œæ—¥èªŒï¼"
msgid "No contributions"
-msgstr ""
+msgstr "ç„¡è²¢ç»"
msgid "No contributions were found"
-msgstr ""
+msgstr "未找到任何貢ç»è€…"
msgid "No credit card data for matching"
-msgstr ""
+msgstr "沒有相符的信用å¡è³‡æ–™"
msgid "No credit card required."
-msgstr ""
+msgstr "無需信用å¡ã€‚"
msgid "No data found"
-msgstr ""
+msgstr "未找到資料"
msgid "No data to display"
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„資料"
msgid "No deployments detected. Use environments to control your software's continuous deployment. %{linkStart}Learn more about deployment jobs.%{linkEnd}"
-msgstr ""
+msgstr "未檢測到部署。使用環境來控制軟體的æŒçºŒéƒ¨ç½²ã€‚ %{linkStart}了解有關部署作業的更多訊æ¯ã€‚%{linkEnd}"
msgid "No deployments found"
-msgstr ""
+msgstr "沒有找到部署"
msgid "No due date"
-msgstr ""
+msgstr "無截止日期"
msgid "No email participants were added. Either none were provided, or they already exist."
-msgstr ""
+msgstr "沒有加入電å­éƒµä»¶åƒèˆ‡è€…。沒有æ供或它們已經存在。"
msgid "No endpoint provided"
-msgstr ""
+msgstr "未æ供端點"
msgid "No errors to display."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„錯誤."
msgid "No estimate or time spent"
-msgstr ""
+msgstr "ç„¡é è¨ˆæˆ–已用時間"
msgid "No file chosen."
-msgstr ""
+msgstr "未é¸å®šä»»ä½•æ–‡ä»¶ã€‚"
msgid "No file hooks found."
-msgstr ""
+msgstr "找ä¸åˆ°æª”案掛鉤。"
msgid "No file selected"
-msgstr ""
+msgstr "未é¸æ“‡ä»»ä½•æ–‡ä»¶"
msgid "No files"
-msgstr ""
+msgstr "沒有文件"
msgid "No files found."
-msgstr ""
+msgstr "未找到文件。"
msgid "No forks are available to you."
-msgstr ""
+msgstr "沒有您å¯ç”¨çš„分å‰ã€‚"
msgid "No group provided"
-msgstr ""
+msgstr "沒有æ供群組"
msgid "No grouping"
-msgstr ""
+msgstr "無分組"
msgid "No issues found"
-msgstr ""
+msgstr "未發ç¾è­°é¡Œ"
msgid "No iteration"
-msgstr ""
+msgstr "無迭代"
msgid "No iterations to show"
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºè¿­ä»£"
msgid "No job log"
-msgstr ""
+msgstr "沒有作業日誌"
msgid "No jobs to show"
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„作業"
msgid "No label"
-msgstr ""
+msgstr "無標記"
msgid "No labels with such name or description"
-msgstr ""
+msgstr "沒有具有此類å稱或æ述的標記"
msgid "No license. All rights reserved"
-msgstr ""
+msgstr "未設定授權æ¢æ¬¾ã€‚版權所有。"
msgid "No matches found"
-msgstr ""
+msgstr "沒有找到符åˆé …"
msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} ID."
-msgstr ""
+msgstr "未找到相符åˆçš„ %{issuable},請確定您加入的是一個有效的 %{issuable} ID。"
msgid "No matching %{issuable} found. Make sure that you are adding a valid %{issuable} URL."
-msgstr ""
+msgstr "æœªæ‰¾åˆ°ç›¸ç¬¦åˆ %{issuable} 的地å€ã€‚請確ä¿æ‚¨æ­£åœ¨åŠ å…¥ä¸€å€‹æœ‰æ•ˆçš„ %{issuable} URL。"
msgid "No matching labels"
-msgstr ""
+msgstr "沒有符åˆçš„標記"
msgid "No matching results"
-msgstr ""
+msgstr "沒有符åˆçš„çµæžœ"
msgid "No matching results for \"%{query}\""
-msgstr ""
+msgstr "沒有與\"%{query}\"符åˆçš„çµæžœ"
msgid "No matching results..."
-msgstr ""
+msgstr "無符åˆçš„çµæžœ..."
msgid "No members found"
-msgstr ""
+msgstr "未找到æˆå“¡"
msgid "No memberships found"
-msgstr ""
+msgstr "未找到æˆå“¡"
msgid "No merge requests found"
-msgstr ""
+msgstr "找ä¸åˆ°åˆä½µè«‹æ±‚"
msgid "No messages were logged"
-msgstr ""
+msgstr "未記錄任何消æ¯"
msgid "No milestone"
-msgstr ""
+msgstr "無里程碑"
msgid "No namespace"
-msgstr ""
+msgstr "沒有命å空間"
msgid "No other labels with such name or description"
-msgstr ""
+msgstr "沒有其他具有此類å稱或æ述的標記"
msgid "No panels matching properties %{opts}"
-msgstr ""
+msgstr "沒有與屬性相符的é¢æ¿%{opts}"
msgid "No parent group"
-msgstr ""
+msgstr "父群組ä¸å­˜åœ¨"
msgid "No plan"
-msgstr ""
+msgstr "沒有計劃"
msgid "No policy matches this license"
-msgstr ""
+msgstr "沒有符åˆæ­¤æŽˆæ¬Šçš„政策"
msgid "No preview for this file type"
-msgstr ""
+msgstr "無法é è¦½æ­¤é¡žåž‹æ–‡ä»¶"
msgid "No prioritized labels with such name or description"
-msgstr ""
+msgstr "沒有此å稱或æ述的優先標記"
msgid "No project subscribes to the pipelines in this project."
-msgstr ""
+msgstr "沒有專案訂閱此專案中的æµæ°´ç·šã€‚"
msgid "No projects available."
-msgstr ""
+msgstr "沒有å¯ç”¨å°ˆæ¡ˆ"
msgid "No projects found"
-msgstr ""
+msgstr "未找到專案"
msgid "No public deploy keys"
-msgstr ""
+msgstr "沒有公共部署金鑰"
msgid "No public groups"
-msgstr ""
+msgstr "無公開群組"
msgid "No ref selected"
-msgstr ""
+msgstr "未é¸æ“‡ref"
msgid "No regions configured"
-msgstr ""
+msgstr "未é…ç½®å€åŸŸ"
msgid "No related merge requests found."
-msgstr ""
+msgstr "未找到相關的åˆä½µè«‹æ±‚。"
msgid "No repository"
-msgstr ""
+msgstr "無版本庫"
msgid "No results"
-msgstr ""
+msgstr "沒有çµæžœ"
msgid "No runner executable"
-msgstr ""
+msgstr "沒有執行器å¯åŸ·è¡Œæ–‡ä»¶"
msgid "No schedules"
-msgstr ""
+msgstr "無計劃"
msgid "No service accounts"
-msgstr ""
+msgstr "沒有æœå‹™å¸³è™Ÿ"
msgid "No severity matches the provided parameter"
-msgstr ""
+msgstr "沒有與æ供的åƒæ•¸ç›¸ç¬¦åˆçš„åš´é‡ç¨‹åº¦"
msgid "No source selected"
-msgstr ""
+msgstr "未é¸æ“‡ä¾†æº"
msgid "No stack trace for this error"
-msgstr ""
+msgstr "沒有此錯誤的堆棧追蹤"
msgid "No starrers matched your search"
-msgstr ""
+msgstr "沒有符åˆæ‚¨æœå°‹æ¢ä»¶çš„收è—使用者"
msgid "No start date"
-msgstr ""
+msgstr "沒有開始日期"
msgid "No suggestions found"
-msgstr ""
+msgstr "未找到任何建議"
msgid "No tag selected"
-msgstr ""
+msgstr "未é¸å–標籤"
msgid "No template"
-msgstr ""
+msgstr "沒有範本"
msgid "No template selected"
-msgstr ""
+msgstr "未é¸æ“‡ç¯„本"
msgid "No test coverage"
-msgstr ""
+msgstr "無測試覆蓋率"
msgid "No triggers exist yet. Use the form above to create one."
-msgstr ""
+msgstr "尚無觸發器。使用上é¢çš„表單建立一個。"
msgid "No user provided"
-msgstr ""
+msgstr "未æ供使用者"
msgid "No vulnerabilities present"
-msgstr ""
+msgstr "ç„¡æ¼æ´ž"
msgid "No webhook events"
-msgstr ""
+msgstr "沒有 webhook 事件"
msgid "No webhooks enabled. Select trigger events above."
-msgstr ""
+msgstr "未啟用 webhook。é¸æ“‡ä¸Šé¢çš„觸發事件。"
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[0] "ä¸ç”¨æ“”心,您ç¾åœ¨ä»ç„¶å¯ä»¥ä½¿ç”¨æ‰€æœ‰ %{strong}%{plan_name}%{strong_close} 功能。您有 %{remaining_days} 天來續訂您的訂閱。"
msgid "No. of commits"
-msgstr ""
+msgstr "æ交次數"
msgid "Nobody has starred this repository yet"
-msgstr ""
+msgstr "ç›®å‰ç„¡ä½¿ç”¨è€…收è—此版本庫"
msgid "Node was successfully created."
-msgstr ""
+msgstr "節點已æˆåŠŸå»ºç«‹ã€‚"
msgid "Node was successfully updated."
-msgstr ""
+msgstr "節點已æˆåŠŸæ›´æ–°ã€‚"
msgid "Nodes"
-msgstr ""
+msgstr "節點"
msgid "Non-admin users are restricted to read-only access, in both GitLab UI and API."
-msgstr ""
+msgstr "在 UI å’Œ API 中,éžç®¡ç†å“¡ä½¿ç”¨è€…僅é™å”¯è®€å­˜å–。"
msgid "None"
msgstr "ç„¡"
msgid "None of the group milestones have the same project as the release"
-msgstr ""
+msgstr "沒有任何群組里程碑與發布具有相åŒçš„專案"
msgid "Normal text"
-msgstr ""
-
-msgid "Not Implemented"
-msgstr ""
+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 ""
+msgstr "並éžæ‰€æœ‰ç€è¦½å™¨éƒ½æ”¯æ´ U2F è£ç½®ï¼Œå› æ­¤æˆ‘們è¦æ±‚您設定雙因å­é©—證程å¼ã€‚這樣å³ä½¿æ‚¨ä½¿ç”¨ä¸æ”¯æ´çš„ç€è¦½å™¨ä¹Ÿå¯ä»¥ç™»å…¥ã€‚"
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 "並éžæ‰€æœ‰ç€è¦½å™¨éƒ½æ”¯æ´ WebAuthn,因此我們è¦æ±‚您設定雙因å­é©—證程å¼ã€‚這樣å³ä½¿æ‚¨ä½¿ç”¨ä¸æ”¯æ´çš„ç€è¦½å™¨ä¹Ÿå¯ä»¥ç™»å…¥ã€‚"
msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
-msgstr ""
+msgstr "尚未處ç†æ‰€æœ‰è³‡æ–™ï¼Œå› æ­¤æ‰€é¸æ™‚間範åœå…§åœ–表的ä¸ä¸€å®šå®Œå…¨æº–確。"
msgid "Not applicable."
-msgstr ""
+msgstr "ä¸é©ç”¨"
msgid "Not available"
-msgstr ""
+msgstr "資料ä¸è¶³"
msgid "Not available for private projects"
-msgstr ""
+msgstr "å°ç§æœ‰é …ç›®ä¸å¯ç”¨"
msgid "Not available for protected branches"
-msgstr ""
+msgstr "å°å—ä¿è­·çš„分支ä¸å¯ç”¨"
msgid "Not confidential"
-msgstr ""
+msgstr "éžç§å¯†"
msgid "Not found"
-msgstr ""
+msgstr "未找到"
msgid "Not found."
-msgstr ""
+msgstr "未找到。"
msgid "Not permitted to destroy framework"
-msgstr ""
+msgstr "沒有權é™åˆªé™¤æ¡†æž¶"
msgid "Not ready yet. Try again later."
-msgstr ""
+msgstr "還沒有準備好。請ç¨å¾Œå†è©¦ã€‚"
msgid "Not started"
-msgstr ""
+msgstr "未開始"
msgid "Not supported"
-msgstr ""
+msgstr "ä¸æ”¯æ´"
msgid "Note"
-msgstr ""
+msgstr "備註"
msgid "Note creation requests"
-msgstr ""
+msgstr "備註建立請求"
msgid "Note parameters are invalid: %{errors}"
-msgstr ""
+msgstr "說明åƒæ•¸ç„¡æ•ˆ: %{errors}"
msgid "Note that pushing to GitLab requires write access to this repository."
-msgstr ""
+msgstr "請注æ„,推é€åˆ°GitLab需è¦å°æ­¤ç‰ˆæœ¬åº«æœ‰å¯«å…¥æ¬Šé™ã€‚"
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 ""
+msgstr "æ示:作為GitLab管ç†å“¡ï¼Œå¯ä»¥é…ç½® %{github_integration_link},這將å…許é€éŽGitHub登入並å…許連接Github程å¼ç¢¼ç‰ˆæœ¬åº«è€Œä¸éœ€è¦å€‹äººå­˜å–令牌(權æ–)。"
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 ""
+msgstr "æ示:作為GitLab管ç†å“¡ï¼Œå¯ä»¥é…ç½® %{github_integration_link},這將å…許é€éŽGitHub登入並å…許匯入Github程å¼ç¢¼ç‰ˆæœ¬åº«è€Œä¸éœ€è¦å€‹äººå­˜å–令牌(權æ–)。"
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 ""
+msgstr "æ示:如GitLab管ç†å“¡é…ç½® %{github_integration_link},將å…許é€éŽGitHub登入並å…許連接Github程å¼ç¢¼ç‰ˆæœ¬åº«è€Œä¸éœ€è¦å€‹äººå­˜å–令牌(權æ–)。"
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 ""
+msgstr "æ示:如GitLab管ç†å“¡é…ç½® %{github_integration_link},將å…許é€éŽGitHub登入並å…許匯入Github程å¼ç¢¼ç‰ˆæœ¬åº«è€Œä¸éœ€è¦å€‹äººå­˜å–令牌(權æ–)。"
msgid "Note: current forks will keep their visibility level."
-msgstr ""
+msgstr "注æ„:當å‰çš„分å‰ï¼ˆfork)將ä¿æŒå…¶å¯è¦‹ç­‰ç´šã€‚"
msgid "NoteForm|Note"
-msgstr ""
+msgstr "備註"
msgid "NoteToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}. For %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd}, type %{keyboardStart}/%{keyboardEnd}."
-msgstr ""
+msgstr "æ”¯æ´ %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}。é‡å° %{quickActionsDocsLinkStart}快速æ“作%{quickActionsDocsLinkEnd},輸入 %{keyboardStart}/%{keyboardEnd}。"
msgid "Notes"
-msgstr ""
+msgstr "備註"
msgid "Notes rate limit"
-msgstr ""
+msgstr "備註 速率é™åˆ¶"
msgid "Notes|Are you sure you want to cancel creating this %{commentType}?"
-msgstr ""
+msgstr "您確定è¦å–消建立此 %{commentType} 嗎?"
msgid "Notes|Are you sure you want to cancel creating this comment?"
-msgstr ""
+msgstr "確定è¦å–消此留言嗎?"
msgid "Notes|Collapse replies"
-msgstr ""
+msgstr "收起復原"
msgid "Notes|Expand replies"
-msgstr ""
+msgstr "展開回復"
msgid "Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher"
-msgstr ""
+msgstr "內部註釋僅å°ä½œè€…ã€å—指派人和具有報告者或更高角色的æˆå“¡å¯è¦‹"
msgid "Notes|Last reply by %{name}"
-msgstr ""
+msgstr "由 %{name} 最後回復"
msgid "Notes|Make this an internal note"
-msgstr ""
+msgstr "將此作為內部註釋"
msgid "Notes|Show all activity"
-msgstr ""
+msgstr "顯示所有活動"
msgid "Notes|Show comments only"
-msgstr ""
+msgstr "僅顯示留言"
msgid "Notes|Show history only"
-msgstr ""
+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 ""
+msgstr "自您開始編輯以來,此留言已變更,請查看 %{open_link}æ›´æ–°éŽçš„留言%{close_link} 以確ä¿è¨Šæ¯ä¸æœƒéºå¤±"
msgid "Notes|This internal note will always remain confidential"
-msgstr ""
+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 "您åªèƒ½åœ¨è¨Šæ¯æµä¸­çœ‹åˆ°%{boldStart}其他活動%{boldEnd} 。è¦åŠ å…¥ç•™è¨€ï¼Œè«‹åˆ‡æ›åˆ°ä»¥ä¸‹é¸é …之一。"
+
+msgid "Note|The created date provided is too far in the past."
+msgstr "指定的建立日期太舊。"
msgid "Nothing to preview."
-msgstr ""
+msgstr "沒有å¯é è¦½çš„內容。"
msgid "Notification events"
-msgstr ""
+msgstr "通知事件"
msgid "Notification setting - %{notification_title}"
-msgstr ""
+msgstr "通知設定 - %{notification_title}"
msgid "Notification settings saved"
-msgstr ""
+msgstr "通知設定已儲存"
msgid "NotificationEmail|Assignee"
msgid_plural "NotificationEmail|Assignees"
-msgstr[0] ""
+msgstr[0] "指派人"
msgid "NotificationEmail|Assignee: %{users}"
msgid_plural "NotificationEmail|Assignees: %{users}"
-msgstr[0] ""
+msgstr[0] "指派人:%{users}"
msgid "NotificationEmail|Reviewer"
msgid_plural "NotificationEmail|Reviewers"
-msgstr[0] ""
+msgstr[0] "審核者"
msgid "NotificationEmail|Reviewer: %{users}"
msgid_plural "NotificationEmail|Reviewers: %{users}"
-msgstr[0] ""
+msgstr[0] "審核者: %{users}"
msgid "NotificationEvent|Change reviewer merge request"
-msgstr ""
+msgstr "更改審核者åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Close issue"
-msgstr ""
+msgstr "關閉議題"
msgid "NotificationEvent|Close merge request"
-msgstr ""
+msgstr "關閉åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Failed pipeline"
-msgstr ""
+msgstr "æµæ°´ç·šå¤±æ•—"
msgid "NotificationEvent|Fixed pipeline"
-msgstr ""
+msgstr "已修復的æµæ°´ç·š"
msgid "NotificationEvent|Issue due"
-msgstr ""
+msgstr "到期議題"
msgid "NotificationEvent|Merge merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚被åˆä½µ"
msgid "NotificationEvent|Merge when pipeline succeeds"
-msgstr ""
+msgstr "æµæ°´ç·šæˆåŠŸæ™‚åˆä½µ"
msgid "NotificationEvent|Moved project"
-msgstr ""
+msgstr "移動專案"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "æ–°å²è©©"
msgid "NotificationEvent|New issue"
-msgstr ""
+msgstr "新建議題"
msgid "NotificationEvent|New merge request"
-msgstr ""
+msgstr "新建åˆä½µè«‹æ±‚"
msgid "NotificationEvent|New note"
-msgstr ""
+msgstr "新建通知"
msgid "NotificationEvent|New release"
-msgstr ""
+msgstr "新發佈"
msgid "NotificationEvent|Push to merge request"
-msgstr ""
+msgstr "推é€åˆ°åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Reassign issue"
-msgstr ""
+msgstr "é‡æ–°æŒ‡æ´¾è­°é¡Œ"
msgid "NotificationEvent|Reassign merge request"
-msgstr ""
+msgstr "é‡æ–°æŒ‡æ´¾åˆä½µè«‹æ±‚"
msgid "NotificationEvent|Reopen issue"
-msgstr ""
+msgstr "é‡å•Ÿè­°é¡Œ"
msgid "NotificationEvent|Reopen merge request"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿåˆä½µè«‹æ±‚"
msgid "NotificationEvent|Successful pipeline"
-msgstr ""
+msgstr "æµæ°´ç·šæˆåŠŸå®Œæˆ"
msgid "NotificationLevel|Custom"
-msgstr ""
+msgstr "自訂"
msgid "NotificationLevel|Disabled"
-msgstr ""
+msgstr "åœç”¨"
msgid "NotificationLevel|Global"
-msgstr ""
+msgstr "全域"
msgid "NotificationLevel|On mention"
-msgstr ""
+msgstr "æåŠ"
msgid "NotificationLevel|Participate"
-msgstr ""
+msgstr "åƒèˆ‡"
msgid "NotificationLevel|Watch"
-msgstr ""
+msgstr "關注"
msgid "Notifications"
-msgstr ""
+msgstr "通知"
msgid "Notifications have been disabled by the project or group owner"
-msgstr ""
+msgstr "專案或群組所有者åœç”¨äº†é€šçŸ¥"
msgid "Notifications off"
-msgstr ""
+msgstr "åœç”¨é€šçŸ¥"
msgid "Notifications on"
-msgstr ""
+msgstr "啟用通知"
msgid "Notifications turned off."
-msgstr ""
+msgstr "已關閉通知功能"
msgid "Notifications turned on."
-msgstr ""
+msgstr "已開啟通知功能"
msgid "Notify users by email when sign-in location is not recognized."
-msgstr ""
+msgstr "無法識別登入ä½ç½®æ™‚通éŽé›»å­éƒµä»¶é€šçŸ¥ä½¿ç”¨è€…。"
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
-msgstr ""
+msgstr "%{author_link} çš„è­°é¡Œ %{issue_reference_link} å³å°‡åˆ°æœŸã€‚"
msgid "Notify|%{commit_link} in %{mr_link}"
-msgstr ""
+msgstr "%{commit_link} 在 %{mr_link}"
+
+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|%{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|Assignee changed from %{fromNames} to %{toNames}"
-msgstr ""
+msgstr "被指派人從 %{fromNames} 更改為 %{toNames}"
msgid "Notify|Assignee changed to %{toNames}"
-msgstr ""
+msgstr "被指派人更改為 %{toNames}"
msgid "Notify|Author: %{author_name}"
-msgstr ""
+msgstr "作者: %{author_name}"
msgid "Notify|Auto DevOps pipeline was disabled for %{project}"
-msgstr ""
+msgstr "%{project} 的自動 DevOps æµæ°´ç·šå·²ç¦ç”¨"
msgid "Notify|CI/CD project settings"
-msgstr ""
+msgstr "CI/CD 專案設定"
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 Pages 一起使用,請將其從您的 GitLab 專案中移除並刪除任何相關的 DNS 記錄。"
msgid "Notify|Issue was %{issue_status} by %{updated_by}"
-msgstr ""
+msgstr "å•é¡Œæ˜¯ %{updated_by} çš„ %{issue_status}"
msgid "Notify|Issue was moved to another project."
-msgstr ""
+msgstr "議題已移至其他專案"
msgid "Notify|Learn more about Auto DevOps"
-msgstr ""
+msgstr "學習更多關於 Auto DevOps 的相關訊æ¯"
msgid "Notify|Merge request %{merge_request} can no longer be merged due to conflict."
-msgstr ""
+msgstr "由於è¡çªï¼Œç„¡æ³•å†åˆä½µåˆä½µè«‹æ±‚ %{merge_request}。"
msgid "Notify|Merge request %{merge_request} was %{mr_status}"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚ %{merge_request} 為 %{mr_status}"
msgid "Notify|Merge request %{merge_request} was %{mr_status} by %{updated_by}"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚ %{merge_request} 為 %{mr_status},由 %{updated_by} æ›´æ–°"
msgid "Notify|Merge request %{merge_request} was merged"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚ %{merge_request} å·²åˆä½µ"
msgid "Notify|Merge request %{mr_link} was closed by %{closed_by}"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚ %{mr_link} 已被 %{closed_by} 關閉"
msgid "Notify|Merge request URL: %{merge_request_url}"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚URL: %{merge_request_url}"
msgid "Notify|Milestone changed to %{milestone}"
-msgstr ""
+msgstr "里程碑已更改為 %{milestone}"
msgid "Notify|New issue: %{project_issue_url}"
-msgstr ""
+msgstr "新議題: %{project_issue_url}"
msgid "Notify|Pipeline %{pipeline_link} triggered by"
-msgstr ""
+msgstr "æµæ°´ç·š %{pipeline_link} 的觸發者為"
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 ""
+msgstr "æµæ°´ç·š %{pipeline_link} çš„ Auto DevOps æµæ°´ç·šå¤±æ•—,且在 %{project_link} 中被ç¦ç”¨ã€‚為了在您的專案中使用 Auto DevOps æµæ°´ç·šï¼Œè«‹æŸ¥çœ‹ %{supported_langs_link},調整您的專案,並在您的 %{settings_link} 內開啟Auto DevOps æµæ°´ç·šã€‚"
msgid "Notify|This issue is due on: %{issue_due_date}"
-msgstr ""
+msgstr "該議題到期日: %{issue_due_date}"
msgid "Notify|Unless you verify your domain by %{time_start}%{time}%{time_end} it will be removed from your GitLab project."
-msgstr ""
+msgstr "除éžæ‚¨é€šéŽ %{time_start}%{time}%{time_end} 驗證您的網域,å¦å‰‡å®ƒå°‡å¾žæ‚¨çš„ GitLab 專案中移除。"
msgid "Notify|You don't have access to the project."
-msgstr ""
+msgstr "您沒有存å–該專案的權é™"
msgid "Notify|Your request to join the %{target_to_join} %{target_type} has been %{denied_tag}."
-msgstr ""
+msgstr "您加入 %{target_to_join} %{target_type} 的請求已被 %{denied_tag}。"
msgid "Notify|currently supported languages"
-msgstr ""
+msgstr "當å‰æ”¯æ´çš„語系"
msgid "Notify|successfully completed %{jobs} in %{stages}."
-msgstr ""
+msgstr "在 %{stages} 中æˆåŠŸå®Œæˆäº† %{jobs}。"
msgid "Nov"
msgstr "11月"
msgid "November"
-msgstr ""
+msgstr "11月"
msgid "Now, personalize your GitLab experience"
-msgstr ""
+msgstr "ç¾åœ¨ï¼Œå€‹æ€§åŒ–您的 GitLab 體驗"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
-msgstr ""
+msgstr "Nuget元資料必須至少設定license_url,project_url或icon_url"
msgid "Number of Elasticsearch shards and replicas per index:"
-msgstr ""
+msgstr "æ¯å€‹ç´¢å¼•çš„ Elasticsearch 碎片和副本數:"
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
-msgstr ""
+msgstr "%{code_start}git gc%{code_end} 之後的 Git 推é€æ¬¡æ•¸ã€‚"
msgid "Number of Git pushes after which a full %{code_start}git repack%{code_end} is run."
-msgstr ""
+msgstr "完整 %{code_start}git repack%{code_end} 後的 Git 推é€æ¬¡æ•¸ã€‚"
msgid "Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run."
-msgstr ""
+msgstr "å¢žé‡ %{code_start}git repack%{code_end} 後的 Git 推é€æ¬¡æ•¸ã€‚"
msgid "Number of LOCs per commit"
-msgstr ""
+msgstr "æ¯æ¬¡æ交的程å¼ç¢¼è¡Œæ•¸"
msgid "Number of commits"
-msgstr ""
+msgstr "æ交次數"
msgid "Number of commits per MR"
-msgstr ""
+msgstr "æ¯å€‹MR包å«çš„æ交數é‡"
msgid "Number of employees"
-msgstr ""
+msgstr "員工人數"
msgid "Number of events"
-msgstr ""
+msgstr "事件數é‡"
msgid "Number of events for this project: %{total_count}."
-msgstr ""
+msgstr "此專案的事件數é‡: %{total_count}。"
msgid "Number of files touched"
-msgstr ""
+msgstr "改動的文件數"
msgid "Number of replicas"
-msgstr ""
+msgstr "副本數"
msgid "Number of shards"
-msgstr ""
+msgstr "碎片數é‡"
msgid "OK"
msgstr "確定"
msgid "Object does not exist on the server or you don't have permissions to access it"
-msgstr ""
+msgstr "物件在伺æœå™¨ä¸Šä¸å­˜åœ¨, 或者您沒有存å–它的權é™"
msgid "Oct"
msgstr "10月"
msgid "October"
-msgstr ""
+msgstr "10月"
msgid "OfSearchInADropdown|Filter"
-msgstr ""
+msgstr "éŽæ¿¾"
msgid "Off"
-msgstr ""
+msgstr "關閉"
msgid "Offline"
-msgstr ""
+msgstr "離線"
msgid "Oh no!"
-msgstr ""
+msgstr "哦ä¸ï¼"
msgid "Ok, let's go"
-msgstr ""
+msgstr "好的,我們開始å§"
msgid "Okay"
-msgstr ""
+msgstr "確定"
msgid "Oldest first"
-msgstr ""
+msgstr "最早的優先"
msgid "OmniAuth"
-msgstr ""
+msgstr "OmniAuth"
msgid "On"
-msgstr ""
+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] "在您的試用版於 %{end_date} çµæŸæ™‚,%{namespace_name} å°‡é™åˆ¶ç‚º %{free_user_limit} åæˆå“¡ã€‚"
msgid "On track"
-msgstr ""
+msgstr "如期進行"
msgid "On-call Schedules"
-msgstr ""
+msgstr "排程待命中"
msgid "On-call schedules"
-msgstr ""
+msgstr "排程待命中"
msgid "On-demand scans run outside of the DevOps cycle and find vulnerabilities in your projects"
-msgstr ""
+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 ""
+msgstr "1 天"
msgid "OnCallSchedules|2 weeks"
-msgstr ""
+msgstr "2 周"
msgid "OnCallSchedules|Add a rotation"
-msgstr ""
+msgstr "加入輪æ›"
msgid "OnCallSchedules|Add a schedule"
-msgstr ""
+msgstr "加入排程"
msgid "OnCallSchedules|Add an additional schedule to your project"
-msgstr ""
+msgstr "為您的專案加入é¡å¤–的排程"
msgid "OnCallSchedules|Add rotation"
-msgstr ""
+msgstr "加入輪æ›"
msgid "OnCallSchedules|Add schedule"
-msgstr ""
+msgstr "加入排程"
msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteRotation}\" rotation? This action cannot be undone."
-msgstr ""
+msgstr "確定è¦åˆªé™¤\"%{deleteRotation}\"輪æ›å—Žï¼Ÿæ­¤æ“作無法回復。"
msgid "OnCallSchedules|Are you sure you want to delete the \"%{deleteSchedule}\" schedule? This action cannot be undone."
-msgstr ""
+msgstr "確定è¦åˆªé™¤\"%{deleteSchedule}\"排程嗎?此æ“作無法回復。"
msgid "OnCallSchedules|Collapse schedule"
-msgstr ""
+msgstr "收疊排程"
msgid "OnCallSchedules|Create on-call schedules in GitLab"
-msgstr ""
+msgstr "在GitLab中建立 on-call 排程"
msgid "OnCallSchedules|Currently no rotation."
-msgstr ""
+msgstr "ç›®å‰æ²’有輪æ›ã€‚"
msgid "OnCallSchedules|Delete rotation"
-msgstr ""
+msgstr "刪除輪æ›"
msgid "OnCallSchedules|Delete schedule"
-msgstr ""
+msgstr "刪除排程"
msgid "OnCallSchedules|Edit rotation"
-msgstr ""
+msgstr "編輯輪æ›"
msgid "OnCallSchedules|Edit schedule"
-msgstr ""
+msgstr "編輯排程"
msgid "OnCallSchedules|Enable end date"
-msgstr ""
+msgstr "啟用çµæŸæ—¥æœŸ"
msgid "OnCallSchedules|Expand schedule"
-msgstr ""
+msgstr "展開排程"
msgid "OnCallSchedules|Failed to add rotation"
-msgstr ""
+msgstr "加入輪æ›å¤±æ•—"
msgid "OnCallSchedules|Failed to add schedule"
-msgstr ""
+msgstr "加入排程失敗"
msgid "OnCallSchedules|Failed to edit schedule"
-msgstr ""
+msgstr "編輯排程失敗"
msgid "OnCallSchedules|For this rotation, on-call will be:"
-msgstr ""
+msgstr "å°æ–¼é€™å€‹è¼ªæ›ï¼Œon-call 將是:"
msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
-msgstr ""
+msgstr "專案 %{project} 中的 on-call 排程 %{obstacle}"
msgid "OnCallSchedules|On-call schedules"
-msgstr ""
+msgstr "On-call 排程"
msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view."
-msgstr ""
+msgstr "請注æ„,æ¯é€±è¦–圖目å‰ä¸æ”¯æ´è¼ªç­æ™‚間少於四å°æ™‚的輪æ›ã€‚"
msgid "OnCallSchedules|Removing this user may put their on-call team at risk of missing a notification."
-msgstr ""
+msgstr "刪除此使用者å¯èƒ½æœƒä½¿ä»–們的待命團隊é¢è‡¨éŒ¯éŽé€šçŸ¥çš„風險。"
msgid "OnCallSchedules|Removing yourself may put your on-call team at risk of missing a notification."
-msgstr ""
+msgstr "移除您自己å¯èƒ½æœƒä½¿æ‚¨çš„待命團隊é¢è‡¨éŒ¯éŽé€šçŸ¥çš„風險。"
msgid "OnCallSchedules|Restrict to time intervals"
-msgstr ""
+msgstr "é™åˆ¶æ™‚é–“é–“éš”"
msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
-msgstr ""
+msgstr "輪æ›çµæŸæ—¥æœŸ/時間必須晚於開始日期/時間"
msgid "OnCallSchedules|Rotation length"
-msgstr ""
+msgstr "輪æ›é•·åº¦"
msgid "OnCallSchedules|Rotation name cannot be empty"
-msgstr ""
+msgstr "輪æ›å稱ä¸èƒ½ç‚ºç©º"
msgid "OnCallSchedules|Rotation participants cannot be empty"
-msgstr ""
+msgstr "輪æ›åƒèˆ‡è€…ä¸èƒ½ç‚ºç©º"
msgid "OnCallSchedules|Rotation start date cannot be empty"
-msgstr ""
+msgstr "輪æ›é–‹å§‹æ—¥æœŸä¸èƒ½ç‚ºç©º"
msgid "OnCallSchedules|Rotations"
-msgstr ""
+msgstr "輪æ›"
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
-msgstr ""
+msgstr "將警報直接分é…給特定的團隊æˆå“¡"
msgid "OnCallSchedules|Select participant"
-msgstr ""
+msgstr "é¸æ“‡åƒèˆ‡è€…"
msgid "OnCallSchedules|Select timezone"
-msgstr ""
+msgstr "é¸æ“‡æ™‚å€"
msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
-msgstr ""
+msgstr "設定所有åƒèˆ‡è€…çš„é è¨­æ™‚å€"
msgid "OnCallSchedules|Successfully created a new rotation"
-msgstr ""
+msgstr "æˆåŠŸå»ºç«‹æ–°è¼ªæ›"
msgid "OnCallSchedules|Successfully edited your rotation"
-msgstr ""
+msgstr "å·²æˆåŠŸç·¨è¼¯æ‚¨çš„輪æ›"
msgid "OnCallSchedules|The rotation could not be deleted. Please try again."
-msgstr ""
+msgstr "無法刪除輪æ›ã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "OnCallSchedules|The rotation could not be updated. Please try again."
-msgstr ""
+msgstr "無法更新輪æ›ã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "OnCallSchedules|The schedule could not be deleted. Please try again."
-msgstr ""
+msgstr "無法刪除排程,請é‡è©¦ã€‚"
msgid "OnCallSchedules|The schedule could not be updated. Please try again."
-msgstr ""
+msgstr "無法更新排程,請é‡è©¦ã€‚"
msgid "OnCallSchedules|Try adding a rotation"
-msgstr ""
+msgstr "嘗試加入輪æ›"
msgid "OnCallSchedules|User %{name} is currently part of:"
-msgstr ""
+msgstr "使用者 %{name} 當å‰å±¬æ–¼ï¼š"
msgid "OnCallSchedules|View next timeframe"
-msgstr ""
+msgstr "查看下一個時間表"
msgid "OnCallSchedules|View previous timeframe"
-msgstr ""
+msgstr "查看上一個時間表"
msgid "OnCallSchedules|You are currently a part of:"
-msgstr ""
+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 ""
+msgstr "您的日程已æˆåŠŸå»ºç«‹ã€‚è¦å°‡å–®å€‹ä½¿ç”¨è€…加入到此排程,請使用加入輪æ›æŒ‰éˆ•ã€‚è¦ç‚ºæ­¤æŽ’程啟用通知,您還必須建立 %{linkStart}å‡ç´šç­–ç•¥%{linkEnd}。"
msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "%{learnMoreLinkStart}了解有關按需掃æ的更多訊æ¯%{learnMoreLinkEnd}。"
msgid "OnDemandScans|%{profileType} profile library"
-msgstr ""
+msgstr "%{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 "加入排程以在指定的日期和時間或定期é‹è¡Œæ­¤æŽƒæ,排程的掃æ會自動ä¿å­˜åˆ°æŽƒæ庫中。"
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 ""
+msgstr "通éŽå¾žå¤–å‘內檢查已部署 Web 應用程å¼çš„版本來分æžå·²çŸ¥æ¼æ´žã€‚DAST 的工作原ç†æ˜¯åœ¨æ‡‰ç”¨ç¨‹å¼é‹è¡Œæ™‚模擬å°æ‡‰ç”¨ç¨‹å¼çš„外部攻擊。"
msgid "OnDemandScans|Are you sure you want to delete this scan?"
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤æŽƒæ嗎?"
msgid "OnDemandScans|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "OnDemandScans|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法刪除ä¿å­˜çš„掃æ。請é‡æ–°æ•´ç†é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法å–å¾— on-demand 掃æ。請é‡æ–°æ•´ç†é é¢ï¼Œæˆ–ç¨å¾Œé‡è©¦ã€‚"
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法å–得掃æ工具設定。請é‡æ–°æ•´ç†é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法å–得站點設定。請é‡æ–°æ•´ç†é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "OnDemandScans|Could not run the scan. Please try again."
-msgstr ""
+msgstr "無法執行掃æ。請é‡è©¦ã€‚"
msgid "OnDemandScans|Create new scanner profile"
-msgstr ""
+msgstr "建立新的掃æ工具設定"
msgid "OnDemandScans|Create new site profile"
-msgstr ""
+msgstr "建立新的站點設定"
msgid "OnDemandScans|DAST configuration"
-msgstr ""
+msgstr "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 "DAST 掃æ您的項目正在é‹è¡Œçš„應用程行ã€ç¶²ç«™æˆ– API 中的æ¼æ´žã€‚ 有關所有設定é¸é …的詳細信æ¯ï¼Œè«‹åƒé–± %{linkStart}GitLab DAST 文件%{linkEnd}。"
msgid "OnDemandScans|Define the fundamental configuration options for your on-demand scan."
-msgstr ""
+msgstr "為您的 on-demand 掃æ定義基本設定é¸é …。"
msgid "OnDemandScans|Delete profile"
-msgstr ""
+msgstr "刪除設定"
msgid "OnDemandScans|Description (optional)"
-msgstr ""
+msgstr "æè¿° (å¯é¸)"
msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ¸¬è©¦ (DAST)"
msgid "OnDemandScans|Edit %{profileType} profile"
-msgstr ""
+msgstr "編輯 %{profileType} é…置資料"
msgid "OnDemandScans|Edit on-demand DAST scan"
-msgstr ""
+msgstr "編輯 on-demand DAST 掃æ"
msgid "OnDemandScans|Edit on-demand scan"
-msgstr ""
+msgstr "編輯 on-demand 掃æ"
msgid "OnDemandScans|Edit profile"
-msgstr ""
+msgstr "編輯設定"
msgid "OnDemandScans|Enable scan schedule"
-msgstr ""
+msgstr "啟用掃æ排程"
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
-msgstr ""
+msgstr "例如:測試SQL注入的登入é é¢"
msgid "OnDemandScans|Manage scanner profiles"
-msgstr ""
+msgstr "管ç†æŽƒæ工具設定"
msgid "OnDemandScans|Manage site profiles"
-msgstr ""
+msgstr "管ç†ç«™é»žè¨­å®š"
msgid "OnDemandScans|My daily scan"
-msgstr ""
+msgstr "我的æ¯æ—¥æŽƒæ"
msgid "OnDemandScans|New %{profileType} profile"
-msgstr ""
+msgstr "æ–° %{profileType} é…ç½®"
msgid "OnDemandScans|New on-demand DAST scan"
-msgstr ""
+msgstr "新建 on-demand DAST 掃æ"
msgid "OnDemandScans|New on-demand scan"
-msgstr ""
+msgstr "新建 on-demand 掃æ"
msgid "OnDemandScans|New profile"
-msgstr ""
+msgstr "æ–°é…ç½®"
msgid "OnDemandScans|New scan"
-msgstr ""
+msgstr "新增掃æ"
msgid "OnDemandScans|No %{profileType} profiles found for DAST"
-msgstr ""
+msgstr "未找到 DAST çš„ %{profileType} é…置文件"
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
-msgstr ""
+msgstr "å°šç„¡é…置文件。如需建立新掃æ,需è¦è‡³å°‘有一個完整的掃æ工具設定。"
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
-msgstr ""
+msgstr "尚無設定。如需建立新掃æ,需è¦è‡³å°‘有一個完整的站點設定。"
msgid "OnDemandScans|On-demand Scans"
-msgstr ""
+msgstr "On-demand 掃æ"
msgid "OnDemandScans|On-demand scans"
-msgstr ""
+msgstr "On-demand 掃æ"
msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "On-demand 掃æ在DevOps週期之外é‹è¡Œï¼Œä¸¦åœ¨æ‚¨çš„專案中發ç¾æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}。"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
-msgstr ""
+msgstr "On-demand 掃æ在DevOps週期之外é‹è¡Œï¼Œä¸¦åœ¨æ‚¨çš„專案中發ç¾æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}"
msgid "OnDemandScans|Repeats"
-msgstr ""
+msgstr "é‡è¤‡"
msgid "OnDemandScans|Run scan"
-msgstr ""
+msgstr "執行掃æ"
msgid "OnDemandScans|Save and run scan"
-msgstr ""
+msgstr "ä¿å­˜ä¸¦åŸ·è¡ŒæŽƒæ"
msgid "OnDemandScans|Save scan"
-msgstr ""
+msgstr "ä¿å­˜æŽƒæ"
msgid "OnDemandScans|Scan configuration"
-msgstr ""
+msgstr "掃æ組態"
msgid "OnDemandScans|Scan library"
-msgstr ""
+msgstr "掃æ庫"
msgid "OnDemandScans|Scan name"
-msgstr ""
+msgstr "掃æå稱"
msgid "OnDemandScans|Scan results will be associated with the selected branch."
-msgstr ""
+msgstr "掃æçµæžœèˆ‡æ‚¨æ‰€é¸å–的分支相關"
msgid "OnDemandScans|Scan schedule"
-msgstr ""
+msgstr "掃æ排程"
msgid "OnDemandScans|Scan type"
-msgstr ""
+msgstr "掃æé¡žåž‹"
msgid "OnDemandScans|Scanner profile"
-msgstr ""
+msgstr "掃æ工具設定"
msgid "OnDemandScans|Select one of the existing profiles"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç¾æœ‰çš„設定"
msgid "OnDemandScans|Site profile"
-msgstr ""
+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 ""
+msgstr "首先建立一個新的é…置文件。é…置文件å¯ä»¥è¼•é¬†ä¿å­˜å’Œé‡å¾©ä½¿ç”¨ GitLab 安全工具的組態詳細信æ¯ã€‚"
msgid "OnDemandScans|Start time"
-msgstr ""
+msgstr "開始時間"
msgid "OnDemandScans|Target"
-msgstr ""
+msgstr "目標"
msgid "OnDemandScans|The scan could not be canceled."
-msgstr ""
+msgstr "無法å–消掃æ。"
msgid "OnDemandScans|The scan could not be retried."
-msgstr ""
+msgstr "無法é‡è©¦æŽƒæ。"
msgid "OnDemandScans|There are no finished scans."
-msgstr ""
+msgstr "沒有已完æˆçš„掃æ。"
msgid "OnDemandScans|There are no running scans."
-msgstr ""
+msgstr "沒有執行中的掃æ。"
msgid "OnDemandScans|There are no saved scans."
-msgstr ""
+msgstr "沒有已ä¿å­˜çš„掃æ。"
msgid "OnDemandScans|There are no scheduled scans."
-msgstr ""
+msgstr "沒有排程中的掃æ。"
msgid "OnDemandScans|Timezone"
-msgstr ""
+msgstr "時å€"
msgid "OnDemandScans|Use existing scanner profile"
-msgstr ""
+msgstr "使用ç¾æœ‰çš„站點設定"
msgid "OnDemandScans|Use existing site profile"
-msgstr ""
+msgstr "使用ç¾æœ‰çš„站點設定"
msgid "OnDemandScans|View results"
-msgstr ""
+msgstr "查看çµæžœ"
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
-msgstr ""
+msgstr "您必須在專案中建立倉庫æ‰èƒ½é‹è¡ŒæŒ‰éœ€æŽƒæ。"
msgid "OnDemandScans|at"
-msgstr ""
+msgstr "在"
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
-msgstr ""
+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 ""
+msgstr "移除後將無法æ¢å¾©åˆ†å‰(fork)關係。此專案將無法å†å‘來æºå°ˆæ¡ˆæˆ–其他分å‰ç™¼é€æˆ–接收åˆä½µè«‹æ±‚。"
msgid "Once you confirm and press \"Reduce project visibility\":"
-msgstr ""
+msgstr "一旦您確èªä¸¦æŒ‰ä¸‹\"é™ä½Žå°ˆæ¡ˆå¯è¦‹æ€§\":"
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
+msgstr[0] "其餘%d項"
msgid "One or more arguments are invalid: %{args}."
-msgstr ""
+msgstr "一個或多個åƒæ•¸ç„¡æ•ˆï¼š %{args}。"
msgid "One or more contacts were successfully added."
-msgstr ""
+msgstr "å·²æˆåŠŸåŠ å…¥ä¸€ä½æˆ–多ä½è¯çµ¡äººã€‚"
msgid "One or more contacts were successfully removed."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤ä¸€ä½æˆ–多ä½è¯çµ¡äººã€‚"
msgid "One or more groups that you don't have access to."
-msgstr ""
+msgstr "您沒有存å–的一個或多個群組的權é™ã€‚"
msgid "One or more of you personal access tokens were revoked"
-msgstr ""
+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 "您的一個或多個 %{provider} 專案無法直接匯入 GitLab,因為它們使用 Subversion 或 Mercurial 進行版本控制,而ä¸æ˜¯ Git。"
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 ""
+msgstr "有一個或多個ä¾è³´é …文件ä¸è¢«æ”¯æ´ï¼Œä¸¦ä¸”ä¾è³´é …列表å¯èƒ½ä¸å®Œæ•´ã€‚以下是支æ´çš„文件類型列表。"
msgid "One or more of your personal access tokens has expired."
-msgstr ""
+msgstr "您的一個或多個個人存å–令牌已éŽæœŸã€‚"
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less:"
-msgstr ""
+msgstr "您的一個或多個個人存å–令牌將在 %{days_to_expire} 天或更短的時間內到期:"
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 ""
+msgstr "åªæœ‰åœ¨å°ˆæ¥­ç‰ˆåŠä»¥ä¸Šæ–¹æ¡ˆä¸­ï¼Œã€Œå ±å‘Šè€…ã€åŠä»¥ä¸Šè§’色æ‰èƒ½çœ‹åˆ°åƒ¹å€¼æµåˆ†æžã€‚"
msgid "Only 1 appearances row can exist"
-msgstr ""
+msgstr "åªèƒ½å­˜åœ¨ä¸€å€‹å¤–觀"
msgid "Only HTTP(S)"
-msgstr ""
+msgstr "僅 HTTP(S)"
msgid "Only Issue ID or merge request ID is required"
-msgstr ""
+msgstr "僅需è¦è­°é¡Œ ID 或åˆä½µè«‹æ±‚ ID"
msgid "Only Project Members"
-msgstr ""
+msgstr "僅專案æˆå“¡"
msgid "Only SSH"
-msgstr ""
+msgstr "僅 SSH"
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
-msgstr ""
+msgstr "僅 %{membersPageLinkStart} 專案æˆå“¡ %{membersPageLinkEnd} å¯ä»¥å­˜å–。æˆå“¡è³‡æ ¼å¿…須明確授予æ¯å€‹ä½¿ç”¨è€…。"
msgid "Only active projects show up in the search and on the dashboard."
-msgstr ""
+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 ""
+msgstr "å…許任何人在您打算被任何人使用的 GitLab 實例上註冊帳號。å…許任何人註冊會使 GitLab 實例更容易å—到攻擊。"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
-msgstr ""
+msgstr "僅在啟用é ç¨‹å„²å­˜æ™‚有效。設定為 0 表示沒有大å°é™åˆ¶ã€‚"
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 ""
+msgstr "僅包括您當å‰è¨‚閱級別的新功能。"
msgid "Only members of this group can access the wiki."
-msgstr ""
+msgstr "åªæœ‰è©²çµ„群的æˆå“¡æ‰èƒ½å­˜å– wiki。"
msgid "Only policy:"
-msgstr ""
+msgstr "僅政策:"
msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
-msgstr ""
+msgstr "åªæœ‰åœ¨æ‚¨ä¿¡ä»» %{idp_url} 時æ‰èƒ½ç¹¼çºŒæŽ§åˆ¶GitLab帳號登入。"
msgid "Only project members can comment."
-msgstr ""
+msgstr "åªæœ‰å°ˆæ¡ˆæˆå“¡å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "Only projects created under a Ultimate license are available in Security Dashboards."
-msgstr ""
+msgstr "åªæœ‰åœ¨æ——艦版授權下建立的專案æ‰èƒ½åœ¨å®‰å…¨å„€è¡¨æ¿ä¸­ä½¿ç”¨ã€‚"
msgid "Only reCAPTCHA v2 is supported:"
-msgstr ""
+msgstr "僅支æ´reCAPTCHA v2:"
msgid "Only required if not using role instance credentials."
-msgstr ""
+msgstr "僅當ä¸ä½¿ç”¨è§’色實例憑證時æ‰éœ€è¦ã€‚"
msgid "Only use lowercase letters, numbers, and underscores."
-msgstr ""
-
-msgid "Only users from the specified IP address ranges can reach this group, including all subgroups, projects, and Git repositories."
-msgstr ""
+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 ""
+msgstr "åªæœ‰åœ¨å°ˆæ¥­ç‰ˆåŠä»¥ä¸Šæ–¹æ¡ˆä¸­ï¼Œã€Œå ±å‘Šè€…ã€åŠä»¥ä¸Šè§’色æ‰èƒ½çœ‹åˆ°ç”Ÿç”¢åŠ›åˆ†æžã€‚"
msgid "Oops, are you sure?"
-msgstr ""
+msgstr "您確定嗎?"
msgid "Open"
-msgstr ""
+msgstr "打開"
msgid "Open Selection"
-msgstr ""
+msgstr "開啟所é¸é …"
msgid "Open errors"
-msgstr ""
+msgstr "開啟錯誤"
msgid "Open in Gitpod"
-msgstr ""
+msgstr "在 Gitpod 中打開"
msgid "Open in Web IDE"
-msgstr ""
+msgstr "在 Web IDE 中打開"
msgid "Open in file view"
-msgstr ""
+msgstr "在文件視窗中打開"
msgid "Open in your IDE"
-msgstr ""
+msgstr "在您的IDE中打開"
msgid "Open new window"
-msgstr ""
+msgstr "開啟新視窗"
msgid "Open raw"
-msgstr ""
+msgstr "開啟原始檔"
msgid "Open sidebar"
-msgstr ""
+msgstr "打開å´é‚Šæ¬„"
msgid "Open: %{open}"
-msgstr ""
+msgstr "é–‹å•Ÿ: %{open}"
msgid "OpenAPI"
-msgstr ""
+msgstr "OpenAPI"
msgid "OpenAPI Specification file path or URL"
-msgstr ""
+msgstr "OpenAPI è¦ç¯„文件路徑或 URL"
msgid "Opened"
-msgstr ""
+msgstr "已開啟"
msgid "Opened MRs"
-msgstr ""
+msgstr "é–‹å•Ÿçš„åˆä½µè«‹æ±‚"
msgid "Opened issues"
-msgstr ""
+msgstr "開啟的議題"
msgid "OpenedNDaysAgo|Created"
-msgstr ""
+msgstr "已建立"
msgid "Opens in a new window"
-msgstr ""
+msgstr "開啟一個新視窗"
msgid "Opens new window"
-msgstr ""
+msgstr "開啟新視窗"
msgid "Operation failed. Check pod logs for %{pod_name} for more details."
-msgstr ""
+msgstr "æ“作失敗。請檢查 Pod 日誌 %{pod_name} 了解更多資訊。"
msgid "Operation not allowed"
-msgstr ""
+msgstr "ä¸å…許該æ“作"
msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
-msgstr ""
+msgstr "æ“作逾時。請檢查 Pod 日誌 %{pod_name} 了解更多資訊。"
msgid "Operations"
-msgstr ""
+msgstr "維é‹"
msgid "Operations Dashboard"
-msgstr ""
+msgstr "動作儀表æ¿"
msgid "OperationsDashboard|Add a project to the dashboard"
-msgstr ""
+msgstr "將專案加入到儀表æ¿"
msgid "OperationsDashboard|Add projects"
-msgstr ""
+msgstr "加入專案"
msgid "OperationsDashboard|More information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "OperationsDashboard|Operations Dashboard"
-msgstr ""
+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 "æ“作和環境儀表æ¿å…±äº«ç›¸åŒçš„專案列表。當您從一個專案中增加或刪除專案時,GitLab 會從å¦ä¸€å€‹å°ˆæ¡ˆä¸­å¢žåŠ æˆ–刪除專案。 %{linkStart}更多資訊%{linkEnd}"
msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
-msgstr ""
+msgstr "維é‹å„€è¡¨æ¿æä¾›æ¯å€‹å°ˆæ¡ˆçš„執行狀æ³çš„摘è¦ï¼ŒåŒ…括æµæ°´ç·šå’Œè­¦å ±ç‹€æ…‹ã€‚"
msgid "Opstrace endpoint for Error Tracking integration"
-msgstr ""
+msgstr "用於錯誤追踪整åˆçš„ Opstrace 端點"
msgid "Optimize your workflow with CI/CD Pipelines"
-msgstr ""
+msgstr "使用 CI/CD æµæ°´ç·šå„ªåŒ–您的工作æµç¨‹"
msgid "Optional"
-msgstr ""
+msgstr "å¯é¸"
msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
-msgstr ""
+msgstr "å¯é¸åƒæ•¸ã€Œvariablesã€å¿…須是雜湊。例如:variables[key1]=value1"
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
-msgstr ""
+msgstr "或者,您å¯ä»¥è‡ªè¨‚如何將 %{link_to_customize} FogBugz çš„é›»å­éƒµä»¶åœ°å€å’Œä½¿ç”¨è€…å稱匯入到GitLab。"
msgid "Options"
-msgstr ""
+msgstr "é¸é …"
msgid "Or you can choose one of the suggested colors below"
-msgstr ""
+msgstr "或者您å¯ä»¥é¸æ“‡ä¸‹é¢å»ºè­°çš„é¡è‰²ä¹‹ä¸€"
msgid "Ordered list"
-msgstr ""
+msgstr "項目清單"
msgid "Organizations"
-msgstr ""
+msgstr "組織"
msgid "Orphaned member"
-msgstr ""
+msgstr "孤兒æˆå“¡"
msgid "Other Labels"
-msgstr ""
+msgstr "其他標記"
msgid "Other available runners"
-msgstr ""
+msgstr "其他å¯ç”¨çš„執行器(runners)"
msgid "Other information"
-msgstr ""
+msgstr "其他訊æ¯"
msgid "Other merge requests block this MR"
-msgstr ""
+msgstr "其他åˆä½µè«‹æ±‚阻止了該MR"
msgid "Other versions"
-msgstr ""
+msgstr "其他版本"
msgid "Other visibility settings have been disabled by the administrator."
-msgstr ""
+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 ""
+msgstr "我們的團隊已收到通知,請é‡è©¦ã€‚"
msgid "Out-of-compliance with this project's policies and should be removed"
-msgstr ""
+msgstr "ä¸ç¬¦åˆè©²å°ˆæ¡ˆæ”¿ç­–,應予以移除"
msgid "OutboundRequests|Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "å…許來自掛鉤(hooks)å’Œæœå‹™å°æœ¬åœ°ç¶²è·¯çš„請求。"
msgid "OutboundRequests|Allow requests to the local network from system hooks"
-msgstr ""
+msgstr "å…許系統掛鉤(hooks)å‘本地網路發é€è«‹æ±‚"
msgid "OutboundRequests|Allow requests to the local network from web hooks and services"
-msgstr ""
+msgstr "å…許來自 web hooks å’Œæœå‹™å°æœ¬åœ°ç¶²è·¯çš„請求"
msgid "OutboundRequests|Enforce DNS rebinding attack protection"
-msgstr ""
+msgstr "強制執行 DNS é‡æ–°ç¶å®šæ”»æ“Šä¿è­·"
msgid "OutboundRequests|Local IP addresses and domain names that hooks and services may access"
-msgstr ""
+msgstr "掛鉤和æœå‹™å¯ä»¥å­˜å–的本地IP地å€å’Œç¶²åŸŸã€‚"
msgid "OutboundRequests|Outbound requests"
-msgstr ""
+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 ""
+msgstr "å³ä½¿ä¸å…許本地請求,系統 hook å’Œ Webhook 也å¯ä»¥å­˜å–å°é€™äº›ç¶²åŸŸå’Œ IP 地å€çš„è«‹æ±‚ã€‚æ”¯æ´ 1:0:0:0:0:0:0:0/124 å’Œ 127.0.0.0/28 ç­‰ IP 範åœã€‚ä¸æ”¯æ´åŸŸå通é…符。è¦åˆ†éš”æ¢ç›®ï¼Œè«‹ä½¿ç”¨é€—號ã€åˆ†è™Ÿæˆ–æ›è¡Œç¬¦ã€‚å…許列表最多å¯åŒ…å« 1000 個æ¢ç›®ã€‚網域å必須是 IDNA 編碼的。"
msgid "OutboundRequests|Resolve IP addresses once and uses them to submit requests."
-msgstr ""
+msgstr "解æžIP地å€ä¸¦ä½¿ç”¨å®ƒå€‘æ交請求。"
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
-msgstr ""
+msgstr "GitLabå¯èƒ½ç„¡æ³•æ­£å¸¸å·¥ä½œï¼Œå› ç‚ºæ‚¨æ­£åœ¨ä½¿ç”¨éŽæ™‚çš„ç€è¦½å™¨ã€‚"
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
-msgstr ""
+msgstr "請安è£ä¸€å€‹%{browser_link_start}支æ´çš„網é ç€è¦½å™¨%{browser_link_end}以å–得更好的體驗。"
msgid "Overridden"
-msgstr ""
+msgstr "覆蓋"
msgid "Overview"
-msgstr ""
+msgstr "概覽"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "覆蓋分å‰åˆ†æ”¯"
msgid "Owned by %{image_tag}"
-msgstr ""
+msgstr "ç”±%{image_tag}æ“有"
msgid "Owned by anyone"
-msgstr ""
+msgstr "æ“有者為任何人"
msgid "Owned by me"
-msgstr ""
+msgstr "æ“有者為我"
msgid "Owned by:"
-msgstr ""
+msgstr "æ“有者:"
msgid "Owner"
-msgstr ""
+msgstr "所有者"
msgid "Owners and administrators"
-msgstr ""
+msgstr "所有者和系統管ç†å“¡"
msgid "Owners can modify this selection."
-msgstr ""
+msgstr "所有者å¯ä»¥ä¿®æ”¹æ­¤é¸æ“‡ã€‚"
msgid "PQL|An error occurred while sending hand raise lead."
-msgstr ""
+msgstr "發é€éƒµä»¶æ™‚發生錯誤。"
msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
-msgstr ""
+msgstr "通éŽæ供我的è¯ç¹«è¨Šæ¯ï¼Œæˆ‘åŒæ„ GitLab å¯ä»¥é€šéŽé›»å­éƒµä»¶è¯ç¹«æˆ‘有關它的產å“ã€æœå‹™å’Œäº‹ä»¶ã€‚ 您å¯ä»¥é€šéŽé›»å­éƒµä»¶æˆ–å­˜å–我們的通訊首é¸é …中心隨時å–消訂閱。"
msgid "PQL|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "PQL|Contact our Sales team"
-msgstr ""
+msgstr "è¯çµ¡æˆ‘們的銷售團隊"
msgid "PQL|Contact sales"
-msgstr ""
+msgstr "è¯çµ¡éŠ·å”®"
msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
-msgstr ""
+msgstr "您好 %{userName}。在與我們的銷售團隊è¯çµ¡ä¹‹å‰ï¼Œæˆ‘們希望您驗證並完æˆä¸‹é¢çš„訊æ¯ã€‚"
msgid "PQL|Message for the Sales team (optional)"
-msgstr ""
+msgstr "給銷售團隊的消æ¯ï¼ˆå¯é¸ï¼‰"
msgid "PQL|Please select a city or state"
-msgstr ""
+msgstr "è«‹é¸æ“‡åŸŽå¸‚或州"
msgid "PQL|Submit information"
-msgstr ""
+msgstr "æ交訊æ¯"
msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨çš„è¯çµ¡ï¼æˆ‘們的銷售團隊將很快與您è¯çµ¡ã€‚"
msgid "Package Registry"
-msgstr ""
+msgstr "軟體套件(Package)庫"
msgid "Package Registry: authenticated API requests"
-msgstr ""
+msgstr "軟體套件(Package)庫:經éŽèº«ä»½é©—證的 API 請求"
msgid "Package Registry: unauthenticated API requests"
-msgstr ""
+msgstr "軟體套件(Package)庫:未經身份驗證的 API 請求"
msgid "Package already exists"
-msgstr ""
+msgstr "軟體套件(Package)已存在"
msgid "Package deleted successfully"
-msgstr ""
+msgstr "軟體套件(Package)å·²æˆåŠŸåˆªé™¤"
msgid "Package file size limits"
-msgstr ""
+msgstr "軟體套件(Package)檔案大å°é™åˆ¶"
msgid "Package recipe already exists"
-msgstr ""
+msgstr "軟體套件(Package)已存在"
msgid "Package registry rate limits"
-msgstr ""
+msgstr "軟體套件(Package)庫速率é™åˆ¶"
msgid "Package type"
-msgstr ""
+msgstr "軟體套件(Package)類型"
msgid "Package type must be Conan"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是Conan"
msgid "Package type must be Debian"
-msgstr ""
+msgstr "軟體套件(Package)類型必須為Debian"
msgid "Package type must be Helm"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是Helm"
msgid "Package type must be Maven"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是Maven"
msgid "Package type must be NPM"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是 NPM"
msgid "Package type must be NuGet"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是Nuget"
msgid "Package type must be PyPi"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是PyPi"
msgid "Package type must be RubyGems"
-msgstr ""
+msgstr "軟體套件(Package)類型必須是 RubyGems"
msgid "PackageRegistry|%{name} version %{version} was first created %{datetime}"
-msgstr ""
+msgstr "%{name}的版本%{version}最åˆå»ºç«‹æ–¼%{datetime}"
msgid "PackageRegistry|Add Conan Remote"
-msgstr ""
+msgstr "新增 Conan é ç«¯ä¾†æº"
msgid "PackageRegistry|Add Gradle Groovy DSL repository command"
-msgstr ""
+msgstr "加入 Gradle Groovy DSL 版本庫指令"
msgid "PackageRegistry|Add Gradle Kotlin DSL repository command"
-msgstr ""
+msgstr "加入 Gradle Kotlin DSL 版本庫指令"
msgid "PackageRegistry|Add NuGet Source"
-msgstr ""
+msgstr "加入Nuget來æº"
msgid "PackageRegistry|Add composer registry"
-msgstr ""
+msgstr "加入composer註冊表"
msgid "PackageRegistry|Additional metadata"
-msgstr ""
+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 ""
+msgstr "應用分組: %{group}"
msgid "PackageRegistry|App name: %{name}"
-msgstr ""
+msgstr "應用å稱: %{name}"
msgid "PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}"
-msgstr ""
+msgstr "ç”±%{author}在%{datetime}觸發的æµæ°´ç·š%{link}所構建"
msgid "PackageRegistry|Composer"
-msgstr ""
+msgstr "Composer"
msgid "PackageRegistry|Composer.json with license: %{license} and version: %{version}"
-msgstr ""
+msgstr "Composer.json 授權許å¯ï¼š%{license} 和版本:%{version}"
msgid "PackageRegistry|Conan"
-msgstr ""
+msgstr "Conan"
msgid "PackageRegistry|Conan Command"
-msgstr ""
+msgstr "Conan 指令"
msgid "PackageRegistry|Copy .pypirc content"
-msgstr ""
+msgstr "複製 .pypirc 內容"
msgid "PackageRegistry|Copy Conan Command"
-msgstr ""
+msgstr "複製 Conan 命令"
msgid "PackageRegistry|Copy Conan Setup Command"
-msgstr ""
+msgstr "複製 Conan 安è£å‘½ä»¤"
msgid "PackageRegistry|Copy Gradle Groovy DSL install command"
-msgstr ""
+msgstr "複製Gradle Groovy DSL安è£æŒ‡ä»¤"
msgid "PackageRegistry|Copy Gradle Kotlin DSL install command"
-msgstr ""
+msgstr "複製Gradle Kotlin DSL安è£æŒ‡ä»¤"
msgid "PackageRegistry|Copy Maven XML"
-msgstr ""
+msgstr "複製Maven XML"
msgid "PackageRegistry|Copy Maven command"
-msgstr ""
+msgstr "複製Maven指令"
msgid "PackageRegistry|Copy Maven registry XML"
-msgstr ""
+msgstr "複製Maven註冊表XML"
msgid "PackageRegistry|Copy NuGet Command"
-msgstr ""
+msgstr "複製Nuget指令"
msgid "PackageRegistry|Copy NuGet Setup Command"
-msgstr ""
+msgstr "複製Nuget設定指令"
msgid "PackageRegistry|Copy Pip command"
-msgstr ""
+msgstr "複製Pip指令"
msgid "PackageRegistry|Copy SHA"
-msgstr ""
+msgstr "複製SHA"
msgid "PackageRegistry|Copy add Gradle Groovy DSL repository command"
-msgstr ""
+msgstr "複製加入 Gradle Groovy DSL 版本庫指令"
msgid "PackageRegistry|Copy add Gradle Kotlin DSL repository command"
-msgstr ""
+msgstr "複製加入 Gradle Kotlin DSL 版本庫指令"
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
-msgstr ""
+msgstr "將其複製並貼到您的%{codeStart}pom.xml%{codeEnd}文件的%{codeStart}dependencies%{codeEnd}塊中。"
msgid "PackageRegistry|Copy npm command"
-msgstr ""
+msgstr "複製npm指令"
msgid "PackageRegistry|Copy npm setup command"
-msgstr ""
+msgstr "複製npm設定指令"
msgid "PackageRegistry|Copy registry include"
-msgstr ""
+msgstr "複製註冊表包å«"
msgid "PackageRegistry|Copy require package include"
-msgstr ""
+msgstr "複製所需的軟體套件(package)並包å«"
msgid "PackageRegistry|Copy target SHA"
-msgstr ""
+msgstr "複製目標 SHA"
msgid "PackageRegistry|Copy yarn command"
-msgstr ""
+msgstr "複製yarn指令"
msgid "PackageRegistry|Copy yarn setup command"
-msgstr ""
+msgstr "複製yarn設定指令"
msgid "PackageRegistry|Created by commit %{link} on branch %{branch}"
-msgstr ""
+msgstr "ç”±%{branch}分支上的%{link}æ交建立"
msgid "PackageRegistry|Debian"
-msgstr ""
+msgstr "Debian"
+
+msgid "PackageRegistry|Delete 1 asset"
+msgid_plural "PackageRegistry|Delete %d assets"
+msgstr[0] "刪除 %d 項資產"
msgid "PackageRegistry|Delete Package File"
-msgstr ""
+msgstr "刪除軟體套件檔案"
msgid "PackageRegistry|Delete Package Version"
-msgstr ""
+msgstr "刪除軟體套件版本"
msgid "PackageRegistry|Delete package"
-msgstr ""
+msgstr "刪除軟體套件"
+
+msgid "PackageRegistry|Delete selected"
+msgstr "刪除é¸å–"
msgid "PackageRegistry|Delete this package"
-msgstr ""
+msgstr "刪除該軟體套件"
msgid "PackageRegistry|Duplicate packages"
-msgstr ""
+msgstr "é‡è¤‡çš„套件"
msgid "PackageRegistry|Error publishing"
-msgstr ""
+msgstr "錯誤發布"
+
+msgid "PackageRegistry|Examples of assets include .pom & .jar files"
+msgstr "è³‡ç”¢çš„ç¯„ä¾‹åŒ…å« .pom å’Œ .jar 文件"
msgid "PackageRegistry|Failed to load the package data"
-msgstr ""
+msgstr "載入軟體套件資料失敗"
msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
-msgstr ""
+msgstr "關於Composer註冊表的更多訊æ¯ï¼Œ%{linkStart}請見文件。%{linkEnd}"
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "如需 Conan 註冊表的更多資訊,請%{linkStart}查閱文件%{linkEnd}。"
msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "有關Maven的註冊表的詳細訊æ¯ï¼Œ%{linkStart}è«‹åƒé–±æ–‡ä»¶%{linkEnd}。"
msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "關於Nuget註冊表的更多訊æ¯ï¼Œ%{linkStart}請見文件%{linkEnd}。"
msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
-msgstr ""
+msgstr "關於PyPi註冊表的更多訊æ¯ï¼Œ%{linkStart}請見文件%{linkEnd}。"
msgid "PackageRegistry|Generic"
-msgstr ""
+msgstr "通用"
msgid "PackageRegistry|Gradle Groovy DSL"
-msgstr ""
+msgstr "Gradle Groovy DSL"
msgid "PackageRegistry|Gradle Groovy DSL install command"
-msgstr ""
+msgstr "Gradle Groovy DSL安è£æŒ‡ä»¤"
msgid "PackageRegistry|Gradle Kotlin DSL"
-msgstr ""
+msgstr "Gradle Kotlin DSL"
msgid "PackageRegistry|Gradle Kotlin DSL install command"
-msgstr ""
+msgstr "Gradle Kotlin DSL安è£æŒ‡ä»¤"
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 "如果尚未é…置,需è¦å°‡ä»¥ä¸‹å…§å®¹åŠ å…¥åˆ°%{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 "如果尚未é…置,需è¦å°‡ä»¥ä¸‹å…§å®¹åŠ å…¥åˆ°%{codeStart}pom.xml%{codeEnd}文件中。"
msgid "PackageRegistry|Install package version"
-msgstr ""
+msgstr "安è£è»Ÿé«”套件版本"
msgid "PackageRegistry|Instance-level"
-msgstr ""
+msgstr "實例級別"
msgid "PackageRegistry|Invalid Package: failed metadata extraction"
-msgstr ""
+msgstr "無效的軟體套件:元資料æå–失敗"
msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
-msgstr ""
+msgstr "了解如何使用GitLab%{noPackagesLinkStart}發布和共享您的軟體套件%{noPackagesLinkEnd}。"
msgid "PackageRegistry|License information located at %{link}"
-msgstr ""
+msgstr "授權許å¯è¨Šæ¯ä½æ–¼%{link}"
+
+msgid "PackageRegistry|Manage storage used by package assets"
+msgstr "管ç†å¥—件資產中使用的儲存"
msgid "PackageRegistry|Manually Published"
-msgstr ""
+msgstr "手動發布"
msgid "PackageRegistry|Maven"
-msgstr ""
+msgstr "Maven"
msgid "PackageRegistry|Maven Command"
-msgstr ""
+msgstr "Maven指令"
msgid "PackageRegistry|Maven XML"
-msgstr ""
+msgstr "Maven XML"
msgid "PackageRegistry|NuGet"
-msgstr ""
+msgstr "NuGet"
msgid "PackageRegistry|NuGet Command"
-msgstr ""
+msgstr "NuGet指令"
+
+msgid "PackageRegistry|Number of duplicate assets to keep"
+msgstr "è¦ä¿ç•™çš„é‡è¤‡è³‡ç”¢æ•¸é‡"
msgid "PackageRegistry|Package Registry"
-msgstr ""
+msgstr "軟體套件註冊表"
+
+msgid "PackageRegistry|Package assets deleted successfully"
+msgstr "å·²æˆåŠŸåˆªé™¤è»Ÿé«”套件資產"
msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
+msgstr "æˆåŠŸåˆªé™¤è»Ÿé«”套件"
msgid "PackageRegistry|Package file deleted successfully"
-msgstr ""
+msgstr "æˆåŠŸåˆªé™¤è»Ÿé«”套件檔"
msgid "PackageRegistry|Package has %{updatesCount} archived update"
msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
-msgstr[0] ""
+msgstr[0] "軟體套件有 %{updatesCount} 個存檔更新"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
-msgstr ""
+msgstr "軟體套件由分支%{branch}上的%{link}æ交所更新,由æµæ°´ç·š%{pipeline}構建並於%{datetime}發布到庫"
+
+msgid "PackageRegistry|Permanently delete assets"
+msgstr "永久刪除資產"
msgid "PackageRegistry|Pip Command"
-msgstr ""
+msgstr "Pip指令"
msgid "PackageRegistry|Project-level"
-msgstr ""
+msgstr "專案級別"
msgid "PackageRegistry|Publish packages if their name or version matches this regex."
-msgstr ""
+msgstr "如果軟體套件å稱或版本符åˆæ­¤æ­£å‰‡è¡¨é”å¼ï¼Œå‰‡ç™¼å¸ƒè»Ÿé«”套件。"
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
-msgstr ""
+msgstr "於%{datetime}發布到%{project}軟體套件註冊表"
msgid "PackageRegistry|PyPI"
-msgstr ""
+msgstr "PyPI"
msgid "PackageRegistry|Recipe: %{recipe}"
-msgstr ""
+msgstr "構æˆ: %{recipe}"
msgid "PackageRegistry|Registry setup"
-msgstr ""
+msgstr "倉庫設定"
msgid "PackageRegistry|Reject packages with the same name and version"
-msgstr ""
+msgstr "拒絕具有相åŒå稱與版本的套件"
msgid "PackageRegistry|Remove package"
-msgstr ""
+msgstr "刪除軟體套件"
msgid "PackageRegistry|Required Python: %{pythonVersion}"
-msgstr ""
+msgstr "éœ€è¦ Python: %{pythonVersion}"
msgid "PackageRegistry|RubyGems"
-msgstr ""
+msgstr "RubyGems"
msgid "PackageRegistry|Settings for Generic packages"
-msgstr ""
+msgstr "通用軟體套件設定"
msgid "PackageRegistry|Settings for Maven packages"
-msgstr ""
+msgstr "Maven 軟體套件的設定"
msgid "PackageRegistry|Show Composer commands"
-msgstr ""
+msgstr "顯示 Composer 指令"
msgid "PackageRegistry|Show Conan commands"
-msgstr ""
+msgstr "顯示Conan指令"
msgid "PackageRegistry|Show NPM commands"
-msgstr ""
+msgstr "顯示 NPM 指令"
msgid "PackageRegistry|Show Nuget commands"
-msgstr ""
+msgstr "顯示 Nuget 指令"
msgid "PackageRegistry|Show PyPi commands"
-msgstr ""
+msgstr "顯示 PyPi 指令"
msgid "PackageRegistry|Show Yarn commands"
-msgstr ""
+msgstr "顯示 Yarn 指令"
+
+msgid "PackageRegistry|Something went wrong while deleting the package assets."
+msgstr "刪除軟體套件資產時發生錯誤。"
msgid "PackageRegistry|Something went wrong while deleting the package file."
-msgstr ""
+msgstr "刪除軟體套件檔時發生錯誤。"
msgid "PackageRegistry|Something went wrong while deleting the package."
-msgstr ""
+msgstr "刪除軟體套件時發生錯誤。"
msgid "PackageRegistry|Something went wrong while fetching the package history."
-msgstr ""
+msgstr "讀å–軟體套件歷å²è¨˜éŒ„時出ç¾å•é¡Œã€‚"
msgid "PackageRegistry|Something went wrong while fetching the package metadata."
-msgstr ""
+msgstr "讀å–軟體套件資料時發生錯誤。"
msgid "PackageRegistry|Sorry, your filter produced no results"
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæ²’有符åˆéŽæ¿¾å™¨çš„任何çµæžœ"
msgid "PackageRegistry|Source project located at %{link}"
-msgstr ""
+msgstr "來æºå°ˆæ¡ˆä½æ–¼%{link}"
msgid "PackageRegistry|Target SHA: %{sha}"
-msgstr ""
+msgstr "目標 SHA:%{sha}"
msgid "PackageRegistry|There are no other versions of this package."
-msgstr ""
+msgstr "此軟體套件沒有其他版本。"
msgid "PackageRegistry|There are no packages yet"
-msgstr ""
+msgstr "ç›®å‰ç„¡è»Ÿé«”套件"
msgid "PackageRegistry|There was a problem fetching the details for this package."
-msgstr ""
+msgstr "å–得此軟體套件的詳細訊æ¯æ™‚出ç¾å•é¡Œã€‚"
msgid "PackageRegistry|There was a timeout and the package was not published. Delete this package and try again."
-msgstr ""
+msgstr "有一個逾時的軟體套件沒有發布。 刪除此軟體套件,然後é‡è©¦ã€‚"
msgid "PackageRegistry|There was an error publishing a %{packageName} package"
-msgstr ""
+msgstr "發布%{packageName}套件錯誤"
msgid "PackageRegistry|This NuGet package has no dependencies."
-msgstr ""
+msgstr "這個Nuget套件沒有ä¾è³´å°ˆæ¡ˆã€‚"
msgid "PackageRegistry|To widen your search, change or remove the filters above."
-msgstr ""
+msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–刪除上é¢çš„éŽæ¿¾å™¨ã€‚"
msgid "PackageRegistry|Type"
-msgstr ""
+msgstr "é¡žåž‹"
msgid "PackageRegistry|Unable to fetch package version information."
-msgstr ""
+msgstr "無法å–得軟體套件版本訊æ¯ã€‚"
msgid "PackageRegistry|Unable to load package"
-msgstr ""
+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 ""
+msgstr "您將è¦åˆªé™¤ %{filename}。這是一種破壞性æ“作,å¯èƒ½æœƒä½¿æ‚¨çš„軟體套件無法使用。您確定嗎?"
msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
-msgstr ""
+msgstr "您將è¦åˆªé™¤%{name},此æ“作ä¸å¯é€†ï¼Œç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
+
+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] "您å³å°‡åˆªé™¤ %d 項資產,該æ“作是ä¸å¯é€†çš„。"
msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
-msgstr ""
+msgstr "å³å°‡åˆªé™¤%{name}çš„%{version}版本。確定繼續嗎?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
-msgstr ""
+msgstr "您å¯èƒ½é‚„需è¦ä½¿ç”¨ä»¤ç‰Œè¨­å®šèº«ä»½é©—證。%{linkStart}è«‹åƒé–±æ–‡ä»¶%{linkEnd}以了解更多訊æ¯ã€‚"
+
+msgid "PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}."
+msgstr "您將需è¦ä¸€å€‹%{linkStart} 個人存å–æ¬Šæ– %{linkEnd}。"
msgid "PackageRegistry|npm"
-msgstr ""
+msgstr "npm"
msgid "PackageRegistry|published by %{author}"
-msgstr ""
+msgstr "由%{author}發布"
msgid "Packages & Registries"
-msgstr ""
+msgstr "軟體套件與映åƒåº«"
msgid "Page not found"
-msgstr ""
+msgstr "找ä¸åˆ°é é¢"
msgid "PagerDutySettings|Active"
-msgstr ""
+msgstr "啟用"
msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
-msgstr ""
+msgstr "通éŽ%{linkStart}在 PagerDuty 中設定 webhook%{linkEnd},為æ¯å€‹ PagerDuty 事件建立 GitLab 事件"
msgid "PagerDutySettings|Failed to update Webhook URL"
-msgstr ""
+msgstr "æ›´æ–°Webhook網å€å¤±æ•—"
msgid "PagerDutySettings|Reset webhook URL"
-msgstr ""
+msgstr "é‡ç½®webhook網å€"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
-msgstr ""
+msgstr "é‡ç½®æ­¤å°ˆæ¡ˆçš„webhook網å€å°‡éœ€è¦åœ¨PagerDuty中更新此整åˆè¨­å®šã€‚"
msgid "PagerDutySettings|Webhook URL"
-msgstr ""
+msgstr "Webhook網å€"
msgid "PagerDutySettings|Webhook URL update was successful"
-msgstr ""
+msgstr "Webhook網å€æ›´æ–°æˆåŠŸ"
msgid "Pages"
-msgstr ""
+msgstr "Pages"
msgid "Pages Domain"
-msgstr ""
+msgstr "Pages網域"
msgid "Pagination|First"
-msgstr ""
+msgstr "首é "
msgid "Pagination|Go to first page"
-msgstr ""
+msgstr "å‰å¾€ç¬¬ä¸€é "
msgid "Pagination|Go to last page"
-msgstr ""
+msgstr "å‰å¾€æœ€å¾Œä¸€é "
msgid "Pagination|Go to next page"
-msgstr ""
+msgstr "å‰å¾€ä¸‹ä¸€é "
msgid "Pagination|Go to previous page"
-msgstr ""
+msgstr "å‰å¾€ä¸Šä¸€é "
msgid "Pagination|Last"
-msgstr ""
+msgstr "å°¾é "
msgid "Pagination|Last »"
-msgstr ""
+msgstr "æœ€æœ«é  Â»"
msgid "Pagination|Next"
-msgstr ""
+msgstr "下一é "
msgid "Pagination|Prev"
-msgstr ""
+msgstr "上一é "
msgid "Pagination|« First"
-msgstr ""
+msgstr "« 第一é "
msgid "Parameter"
-msgstr ""
+msgstr "åƒæ•¸"
msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
-msgstr ""
+msgstr "\"job_id\" åƒæ•¸çš„長度ä¸èƒ½è¶…éŽ %{job_id_max_size}"
msgid "Parent"
-msgstr ""
+msgstr "上層"
msgid "Parent epic doesn't exist."
-msgstr ""
+msgstr "父å²è©©ä¸å­˜åœ¨ã€‚"
msgid "Parent epic is not present."
-msgstr ""
+msgstr "父å²è©©ä¸å­˜åœ¨ã€‚"
msgid "Parsing error for param :embed_json. %{message}"
-msgstr ""
+msgstr "åƒæ•¸:embed_json解æžéŒ¯èª¤ã€‚%{message}"
msgid "Part of merge request changes"
-msgstr ""
+msgstr "包å«æ–¼åˆä½µè«‹æ±‚變更中"
msgid "Partial import"
-msgstr ""
+msgstr "部份匯入"
msgid "Participants"
-msgstr ""
+msgstr "åƒèˆ‡è€…"
msgid "Pass job variables"
-msgstr ""
+msgstr "傳éžä½œæ¥­è®Šæ•¸"
msgid "Passed"
-msgstr ""
+msgstr "已通éŽ"
msgid "Passed on"
-msgstr ""
+msgstr "已通éŽæ–¼"
msgid "Password"
-msgstr ""
+msgstr "密碼"
msgid "Password (optional)"
-msgstr ""
+msgstr "密碼 (å¯é¸)"
msgid "Password authentication is unavailable."
-msgstr ""
+msgstr "密碼驗證ä¸å¯ç”¨ã€‚"
msgid "Password confirmation"
-msgstr ""
+msgstr "密碼確èª"
msgid "Password successfully changed"
-msgstr ""
+msgstr "密碼修改æˆåŠŸ"
msgid "Password was successfully updated. Please sign in again."
-msgstr ""
+msgstr "密碼更新æˆåŠŸã€‚è«‹é‡æ–°ç™»å…¥ã€‚"
msgid "PasswordPrompt|Confirm password"
-msgstr ""
+msgstr "確èªå¯†ç¢¼"
msgid "PasswordPrompt|Confirm password to continue"
-msgstr ""
+msgstr "確èªå¯†ç¢¼ä»¥ç¹¼çºŒ"
msgid "PasswordPrompt|Password is required"
-msgstr ""
+msgstr "密碼為必è¦"
msgid "PasswordPrompt|Please enter your password to confirm"
-msgstr ""
+msgstr "請輸入您的密碼以確èª"
msgid "Passwords should be unique and not used for any other sites or services."
-msgstr ""
+msgstr "密碼應唯一,並且未用於任何其他網站或æœå‹™ã€‚"
msgid "Password|requires at least one lowercase letter"
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹å°å¯«å­—æ¯"
msgid "Password|requires at least one number"
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹æ•¸å­—"
msgid "Password|requires at least one symbol character"
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹ç¬¦è™Ÿå­—å…ƒ"
msgid "Password|requires at least one uppercase letter"
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹å¤§å¯«å­—æ¯"
msgid "Past due"
-msgstr ""
+msgstr "逾期"
msgid "Paste a public key here."
-msgstr ""
+msgstr "在此處貼上公鑰。"
msgid "Paste a public key here. %{link_start}How do I generate it?%{link_end}"
-msgstr ""
+msgstr "在這裡貼上一個公鑰。%{link_start}我如何生æˆå®ƒï¼Ÿ%{link_end}"
msgid "Paste confidential epic link"
-msgstr ""
+msgstr "貼上機密å²è©©é€£çµ"
msgid "Paste confidential issue link"
-msgstr ""
+msgstr "貼上機密議題連çµ"
msgid "Paste epic link"
-msgstr ""
+msgstr "貼上å²è©©é€£çµ"
msgid "Paste issue link"
-msgstr ""
+msgstr "貼上議題連çµ"
msgid "Paste link"
-msgstr ""
+msgstr "貼上連çµ"
msgid "Paste project path (i.e. gitlab-org/gitlab)"
-msgstr ""
+msgstr "貼上專案路徑(å³gitlab-org/gitlab)"
msgid "Paste this DSN into your Sentry SDK"
-msgstr ""
+msgstr "將此DSN貼上到您的Sentry SDK"
msgid "Patch to apply"
-msgstr ""
+msgstr "è¦æ‡‰ç”¨çš„補ä¸"
msgid "Path"
-msgstr ""
+msgstr "路徑"
msgid "Path:"
-msgstr ""
+msgstr "路徑:"
msgid "Paths can contain wildcards, like */welcome"
-msgstr ""
+msgstr "路徑å¯ä»¥åŒ…å«è¬ç”¨å­—元,如*/welcome"
msgid "Paths to protect with rate limiting"
-msgstr ""
+msgstr "使用速率é™åˆ¶ä¿è­·çš„路徑"
msgid "Pause"
-msgstr ""
+msgstr "æš«åœ"
msgid "Pause indexing and upgrade Elasticsearch to a supported version."
-msgstr ""
+msgstr "æš«åœç´¢å¼•ä¸¦å°‡ Elasticsearch å‡ç´šåˆ°å—支æ´çš„版本。"
msgid "Pause time (ms)"
-msgstr ""
+msgstr "æš«åœæ™‚é–“ (ms)"
msgid "Paused"
-msgstr ""
+msgstr "已暫åœ"
msgid "Paused runners don't accept new jobs"
-msgstr ""
+msgstr "æš«åœçš„執行器(runners)ä¸æŽ¥å—新作業"
msgid "Peer review by"
-msgstr ""
+msgstr "åŒè¡Œè©•å¯©"
msgid "Pending"
-msgstr ""
+msgstr "等待中"
msgid "Pending Deletion"
-msgstr ""
+msgstr "等待刪除"
msgid "Pending comments"
-msgstr ""
+msgstr "待處ç†çš„留言"
msgid "Pending deletion"
-msgstr ""
+msgstr "等待刪除"
msgid "Pending owner action"
-msgstr ""
+msgstr "等待æ“有者動作"
msgid "Pending sync…"
-msgstr ""
+msgstr "等待åŒæ­¥â€¦"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
+msgstr "權é™ä¸è¶³çš„使用者將無法收到通知,也無法留言。"
msgid "People without permission will never get a notification."
-msgstr ""
+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 ""
+msgstr "rollout 百分比必須是0-100之間的整數"
msgid "Percentage"
-msgstr ""
+msgstr "百分比"
msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
-msgstr ""
+msgstr "執行進階é¸é …,如改變路徑ã€è½‰ç§»ã€åŒ¯å‡ºæˆ–移除群組。"
msgid "Perform code reviews and enhance collaboration with merge requests."
-msgstr ""
+msgstr "執行程å¼ç¢¼å¯©æŸ¥ä¸¦é€šéŽåˆä½µè«‹æ±‚增強å”作。"
msgid "Perform common operations on GitLab project"
-msgstr ""
+msgstr "在GitLab專案上執行常見æ“作"
+
+msgid "Performance insights"
+msgstr "性能洞察"
msgid "Performance optimization"
-msgstr ""
+msgstr "性能優化"
msgid "PerformanceBar|Backend"
-msgstr ""
+msgstr "後å°"
msgid "PerformanceBar|Bullet notifications"
-msgstr ""
+msgstr "å­å½ˆé€šçŸ¥"
msgid "PerformanceBar|DOM Content Loaded"
-msgstr ""
+msgstr "DOM 內容已載入"
msgid "PerformanceBar|Download"
-msgstr ""
+msgstr "下載"
msgid "PerformanceBar|Elasticsearch calls"
-msgstr ""
+msgstr "Elasticsearch調用"
msgid "PerformanceBar|External Http calls"
-msgstr ""
+msgstr "外部 Http 調用"
msgid "PerformanceBar|First Contentful Paint"
-msgstr ""
+msgstr "首次內容繪製"
msgid "PerformanceBar|Flamegraph with mode:"
-msgstr ""
+msgstr "ç«ç„°åœ–模å¼ï¼š"
msgid "PerformanceBar|Frontend resources"
-msgstr ""
+msgstr "å‰ç«¯è³‡æº"
msgid "PerformanceBar|Gitaly calls"
-msgstr ""
+msgstr "Gitaly調用"
msgid "PerformanceBar|Memory"
-msgstr ""
+msgstr "記憶體"
msgid "PerformanceBar|Memory report"
-msgstr ""
+msgstr "記憶體報告"
msgid "PerformanceBar|Redis calls"
-msgstr ""
+msgstr "Redis調用"
msgid "PerformanceBar|Rugged calls"
-msgstr ""
+msgstr "Rugged調用"
msgid "PerformanceBar|SQL queries"
-msgstr ""
+msgstr "SQL查詢"
msgid "PerformanceBar|Sort by duration"
-msgstr ""
+msgstr "ä¾æŒçºŒæ™‚間排åº"
msgid "PerformanceBar|Sort chronologically"
-msgstr ""
+msgstr "ä¾æ™‚間排åº"
msgid "PerformanceBar|Stats"
-msgstr ""
+msgstr "統計"
msgid "PerformanceBar|Total duration"
-msgstr ""
+msgstr "總æŒçºŒæ™‚é–“"
msgid "PerformanceBar|Trace"
-msgstr ""
+msgstr "追蹤"
msgid "PerformanceBar|cpu"
-msgstr ""
+msgstr "cpu"
msgid "PerformanceBar|object"
-msgstr ""
+msgstr "物件"
msgid "PerformanceBar|wall"
-msgstr ""
+msgstr "牆"
msgid "Period in seconds"
-msgstr ""
+msgstr "週期(秒)"
msgid "Permalink"
-msgstr ""
+msgstr "永久連çµ"
msgid "Permanently remove group"
-msgstr ""
+msgstr "永久刪除群組"
msgid "Permissions"
-msgstr ""
+msgstr "權é™"
msgid "Permissions Help"
-msgstr ""
+msgstr "權é™å¹«åŠ©"
msgid "Permissions and group features"
-msgstr ""
+msgstr "權é™å’Œç¾¤çµ„功能"
msgid "Personal Access Token"
-msgstr ""
+msgstr "個人存å–憑證"
msgid "Personal Access Token prefix"
-msgstr ""
+msgstr "個人存å–令牌å‰ç¶´"
msgid "Personal project creation is not allowed. Please contact your administrator with questions"
-msgstr ""
+msgstr "ä¸å…許建立個人專案。如有疑å•ï¼Œè«‹è¯çµ¡æ‚¨çš„管ç†å“¡"
msgid "Personal projects"
-msgstr ""
+msgstr "個人專案"
msgid "Personal projects limit:"
-msgstr ""
+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 "æŸäº› GitLab 功能——包括å‡ç´šè‡³ä»˜è²»å°ˆæ¡ˆå’Œé–‹å§‹å…費試用——åªèƒ½åœ¨ç¾¤çµ„ã€å’Œç¾¤çµ„中的專案使用。%{projectName} 是個人專案,因此ä¸é©ç”¨é€™äº›åŠŸèƒ½ã€‚我們建議您將專案移入群組,以釋放 GitLab 的完整潛力。"
+
+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 "您的 %{projectName} 專案ä¸åœ¨ç¾¤çµ„中"
msgid "Phabricator Server Import"
-msgstr ""
+msgstr "Phabricator伺æœå™¨åŒ¯å…¥"
msgid "Phabricator Server URL"
-msgstr ""
+msgstr "Pharibator伺æœå™¨URL"
msgid "Phabricator Tasks"
-msgstr ""
+msgstr "Phabricator任務"
msgid "Phone"
-msgstr ""
+msgstr "電話"
msgid "Pick a name"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å稱"
msgid "Pin code"
-msgstr ""
+msgstr "Pin碼"
msgid "Pipeline"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "Pipeline %{label}"
-msgstr ""
+msgstr "æµæ°´ç·š%{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
-msgstr ""
+msgstr "「%{dataTitle}ã€çš„æµæ°´ç·š%{label}"
msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
-msgstr ""
+msgstr "您確定è¦å°‡æ–‡ä»¶é‡ç½®ç‚ºä¸Šæ¬¡æ交的版本嗎?"
msgid "Pipeline ID"
-msgstr ""
+msgstr "æµæ°´ç·šID"
msgid "Pipeline IID"
-msgstr ""
+msgstr "æµæ°´ç·šIID"
msgid "Pipeline Schedule"
-msgstr ""
+msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Pipeline Schedules"
-msgstr ""
+msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Pipeline URL"
-msgstr ""
+msgstr "æµæ°´ç·š URL"
msgid "Pipeline creation rate limits"
-msgstr ""
+msgstr "æµæ°´ç·šå»ºç«‹é€ŸçŽ‡é™åˆ¶"
msgid "Pipeline durations for the last 30 commits"
-msgstr ""
+msgstr "最近 30 次æ交的æµæ°´ç·šæŒçºŒæ™‚é–“"
msgid "Pipeline ran in fork of project"
-msgstr ""
+msgstr "æµæ°´ç·šåœ¨åˆ†å‰çš„專案中執行"
msgid "Pipeline status emails"
-msgstr ""
+msgstr "æµæ°´ç·šç‹€æ…‹é›»å­éƒµä»¶"
msgid "Pipeline subscriptions"
-msgstr ""
+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 "當訂閱專案 %{default_branch_docs} 上的新標籤æˆåŠŸå®Œæˆæµæ°´ç·šæ™‚,æµæ°´ç·šè¨‚閱會在此專案的é è¨­åˆ†æ”¯ä¸Šè§¸ç™¼ä¸€å€‹æ–°æµæ°´ç·šã€‚"
msgid "Pipeline triggers"
-msgstr ""
+msgstr "æµæ°´ç·šè§¸ç™¼å™¨"
msgid "Pipeline: %{status}"
-msgstr ""
+msgstr "æµæ°´ç·š: %{status}"
msgid "PipelineCharts|An error has occurred when retrieving the analytics data"
-msgstr ""
+msgstr "å–回分æžè³‡æ–™æ™‚發生錯誤"
msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
-msgstr ""
+msgstr "å–回æµæ°´ç·šè³‡æ–™æ™‚發生錯誤"
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
-msgstr ""
+msgstr "處ç†CI/CD分æžæ™‚發生未知錯誤。"
msgid "PipelineCharts|CI/CD Analytics"
-msgstr ""
+msgstr "CI/CD 分æž"
msgid "PipelineCharts|Failed:"
-msgstr ""
+msgstr "失敗:"
msgid "PipelineCharts|Overall statistics"
-msgstr ""
+msgstr "總體統計資料"
msgid "PipelineCharts|Success ratio:"
-msgstr ""
+msgstr "æˆåŠŸçŽ‡ï¼š"
msgid "PipelineCharts|Successful:"
-msgstr ""
+msgstr "æˆåŠŸï¼š"
msgid "PipelineCharts|There was an error parsing the data for the charts."
-msgstr ""
+msgstr "解æžåœ–表資料時發生錯誤。"
msgid "PipelineCharts|Total:"
-msgstr ""
+msgstr "總計:"
msgid "PipelineEditorFileTree|Configuration files added with the include keyword"
-msgstr ""
+msgstr "設定文件已加入 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 ""
+msgstr "當您使用 include é—œéµå­—加入專案中的æµæ°´ç·šè¨­å®šæ–‡ä»¶æ™‚,這些文件將在此處列出。"
msgid "PipelineEditorTutorial|Browse %{linkStart}CI/CD examples and templates%{linkEnd}"
-msgstr ""
+msgstr "ç€è¦½ %{linkStart}CI/CD 示例和範本%{linkEnd}"
msgid "PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically."
-msgstr ""
+msgstr "將檔案æ交到您的版本庫。然後æµæ°´ç·šæœƒè‡ªå‹•é‹è¡Œã€‚"
msgid "PipelineEditorTutorial|Get started with GitLab CI/CD"
-msgstr ""
+msgstr "開始使用 GitLab CI/CD"
msgid "PipelineEditorTutorial|GitLab CI/CD can automatically build, test, and deploy your application."
-msgstr ""
+msgstr "GitLab CI/CD å¯ä»¥è‡ªå‹•æ§‹å»ºã€æ¸¬è©¦å’Œéƒ¨ç½²æ‚¨çš„應用程å¼ã€‚"
msgid "PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}"
-msgstr ""
+msgstr "如果您使用的是自管ç†çš„ GitLab 實例,請%{linkStart}確ä¿æ‚¨çš„實例具有å¯ç”¨çš„執行器(Runner)。%{linkEnd}"
msgid "PipelineEditorTutorial|Learn more about %{linkStart}GitLab CI/CD concepts%{linkEnd}"
-msgstr ""
+msgstr "了解更多關於%{linkStart}GitLab CI/CD 概念%{linkEnd}的訊æ¯"
msgid "PipelineEditorTutorial|Make your pipeline more efficient with the %{linkStart}Needs keyword%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Needs é—œéµå­—%{linkEnd}讓您的æµæ°´ç·šæ›´é«˜æ•ˆ"
msgid "PipelineEditorTutorial|Resources to help with your CI/CD configuration:"
-msgstr ""
+msgstr "幫助您進行 CI/CD 設定的資æºï¼š"
msgid "PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run."
-msgstr ""
+msgstr "é¸æ“‡æµæ°´ç·š ID 以查看有關第一次æµæ°´ç·šé‹è¡Œçš„完整詳細訊æ¯ã€‚"
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 "æµæ°´ç·šçš„階段和作業在 %{codeStart}.gitlab-ci.yml%{codeEnd} 文件中定義,您å¯ä»¥ä½¿ç”¨æµæ°´ç·šç·¨è¼¯å™¨ç·¨è¼¯ã€å¯è¦–化和驗證此文件中的語法。"
msgid "PipelineEditorTutorial|The pipeline status is at the top of the page."
-msgstr ""
+msgstr "æµæ°´ç·šç‹€æ…‹åœ¨é é¢é ‚部。"
msgid "PipelineEditorTutorial|This template creates a simple test pipeline. To use it:"
-msgstr ""
+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 ""
+msgstr "使用æµæ°´ç·šç·¨è¼¯å™¨ä¸­çš„ Visualize å’Œ Lint 標籤來å¯è¦–化您的æµæ°´ç·šä¸¦æª¢æŸ¥ä»»ä½•éŒ¯èª¤æˆ–警告,然後å†é€²è¡Œæ›´æ”¹ã€‚"
msgid "PipelineEditorTutorial|View %{linkStart}.gitlab-ci.yml syntax reference%{linkEnd}"
-msgstr ""
+msgstr "查看 %{linkStart}.gitlab-ci.yml 語法åƒè€ƒ%{linkEnd}"
msgid "PipelineEditorTutorial|âš™ï¸ Pipeline configuration reference"
-msgstr ""
+msgstr "âš™ï¸ æµæ°´ç·šè¨­å®šåƒè€ƒ"
msgid "PipelineEditorTutorial|💡 Tip: Visualize and validate your pipeline"
-msgstr ""
+msgstr "💡 æ示: 視覺化與驗證您的æµæ°´ç·š"
msgid "PipelineEditorTutorial|🚀 Run your first pipeline"
-msgstr ""
+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 ""
+msgstr "當å‰ç·¨è¼¯é ç°½çš„內容將被用於模擬。"
msgid "PipelineEditor|Git push event to the default branch"
-msgstr ""
+msgstr "Git 推é€äº‹ä»¶åˆ°é è¨­åˆ†æ”¯"
msgid "PipelineEditor|Other pipeline sources are not available yet."
-msgstr ""
+msgstr "其他來æºæµæ°´ç·šä»ä¸å¯ç”¨ã€‚"
msgid "PipelineEditor|Pipeline Source"
-msgstr ""
+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 "æµæ°´ç·šè¡Œç‚ºå°‡è¢«æ‘¸æ“¬æ–¼åŒ…括 %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} å’Œ %{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 "æµæ°´ç·šè¡Œç‚ºå°‡è¢«æ¨¡æ“¬æ–¼åŒ…括 %{codeStart}rules%{codeEnd} %{codeStart}only%{codeEnd} %{codeStart}except%{codeEnd} å’Œ %{codeStart}needs%{codeEnd} 作業ä¾è³´é …。 %{linkStart}了解更多%{linkEnd}"
+
+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 "模擬默èªåˆ†æ”¯çš„ %{codeStart}git push%{codeEnd} 事件,已評估 %{codeStart}Rules%{codeEnd}ã€%{codeStart}only%{codeEnd}ã€%{codeStart}except%{codeEnd} å’Œ %{codeStart}needs%{codeEnd} 作業ä¾è³´é‚輯。 %{linkStart}了解更多%{linkEnd}"
+
+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 ""
+msgstr "æŒçºŒé©—è­‰ CI/CD 設定。當 CI/CD 設定文件ä¸ç‚ºç©ºæ™‚,會顯示錯誤和警告。"
msgid "PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax."
-msgstr ""
+msgstr "當 CI/CD 設定文件具有有效語法時,將顯示åˆä½µçš„ YAML 視圖。"
msgid "PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax."
-msgstr ""
+msgstr "當 CI/CD 設定文件具有有效語法時顯示視覺化æµæ°´ç·šã€‚"
msgid "PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax."
-msgstr ""
+msgstr "當 CI/CD 設定文件使用有效語法填寫時,此é ç±¤å°‡å¯ç”¨ã€‚"
msgid "PipelineEditor|Validate pipeline"
-msgstr ""
+msgstr "é©—è­‰æµæ°´ç·š"
msgid "PipelineEditor|Validate pipeline under selected conditions"
-msgstr ""
+msgstr "在é¸å®šæ¢ä»¶ä¸‹é©—è­‰æµæ°´ç·š"
msgid "PipelineEditor|Validate pipeline under simulated conditions"
-msgstr ""
+msgstr "在模擬æ¢ä»¶ä¸‹é©—è­‰æµæ°´ç·š"
+
+msgid "PipelineEditor|Validating pipeline... It can take up to a minute."
+msgstr "正在驗證æµæ°´ç·š...å¯èƒ½éœ€è¦ä¸€åˆ†é˜ã€‚"
+
+msgid "PipelineEditor|Waiting for CI content to load..."
+msgstr "等待載入 CI 內容..."
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
-msgstr ""
+msgstr "自訂(%{linkStart}Cron 語法%{linkEnd})"
msgid "PipelineSchedules|Activated"
-msgstr ""
+msgstr "是å¦å•Ÿç”¨"
msgid "PipelineSchedules|Active"
-msgstr ""
+msgstr "已啟用"
msgid "PipelineSchedules|All"
-msgstr ""
+msgstr "所有"
msgid "PipelineSchedules|Inactive"
-msgstr ""
+msgstr "未啟用"
msgid "PipelineSchedules|Next Run"
-msgstr ""
+msgstr "下次執行時間"
msgid "PipelineSchedules|None"
-msgstr ""
+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|Provide a short description for this pipeline"
-msgstr ""
+msgstr "為此æµæ°´ç·šæ供簡短æè¿°"
msgid "PipelineSchedules|Take ownership"
-msgstr ""
+msgstr "å–得所有權"
msgid "PipelineSchedules|Target"
-msgstr ""
+msgstr "目標"
msgid "PipelineSchedules|Variables"
-msgstr ""
+msgstr "變數"
+
+msgid "PipelineSchedule|Take ownership to edit"
+msgstr "å–得所有權進行編輯"
msgid "PipelineSource|API"
-msgstr ""
+msgstr "API"
msgid "PipelineSource|Chat"
-msgstr ""
+msgstr "Chat"
msgid "PipelineSource|External"
-msgstr ""
+msgstr "外部"
msgid "PipelineSource|External Pull Request"
-msgstr ""
+msgstr "外部æå–è¦æ±‚"
msgid "PipelineSource|Merge Request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "PipelineSource|On-Demand DAST Scan"
-msgstr ""
+msgstr "On-Demand DAST 掃æ"
msgid "PipelineSource|On-Demand DAST Validation"
-msgstr ""
+msgstr "On-Demand DAST é©—è­‰"
msgid "PipelineSource|Parent Pipeline"
-msgstr ""
+msgstr "上級æµæ°´ç·š"
msgid "PipelineSource|Pipeline"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "PipelineSource|Push"
-msgstr ""
+msgstr "推é€"
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "排程"
msgid "PipelineSource|Trigger"
-msgstr ""
+msgstr "觸發器"
msgid "PipelineSource|Web"
-msgstr ""
+msgstr "Web"
msgid "PipelineSource|Web IDE"
-msgstr ""
+msgstr "Web IDE"
msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
-msgstr ""
+msgstr "æµæ°´ç·šï¼š%{ciStatus}"
msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
-msgstr ""
+msgstr "æµæ°´ç·šï¼š%{ci_status}"
msgid "PipelineWizardDefaultCommitMessage|Add %{filename}"
-msgstr ""
+msgstr "加入 %{filename}"
msgid "PipelineWizardDefaultCommitMessage|Update %{filename}"
-msgstr ""
+msgstr "æ›´æ–° %{filename}"
msgid "PipelineWizardInputValidation|At least one entry is required"
-msgstr ""
+msgstr "至少需è¦ä¸€å€‹æ¢ç›®"
msgid "PipelineWizardInputValidation|This field is required"
-msgstr ""
+msgstr "此欄ä½æ˜¯å¿…需的"
msgid "PipelineWizardInputValidation|This value is not valid"
-msgstr ""
+msgstr "此值無效"
msgid "PipelineWizardListWidget|add another step"
-msgstr ""
+msgstr "加入å¦ä¸€å€‹æ­¥é©Ÿ"
msgid "PipelineWizardListWidget|remove step"
-msgstr ""
+msgstr "移除步驟"
msgid "PipelineWizard|Commit"
-msgstr ""
+msgstr "æ交"
msgid "PipelineWizard|Commit Message"
-msgstr ""
+msgstr "æ交消æ¯"
msgid "PipelineWizard|Commit changes to your file"
-msgstr ""
+msgstr "æ交您å°æª”案的更改"
msgid "PipelineWizard|Commit file to Branch"
-msgstr ""
+msgstr "æ交檔案到分支"
msgid "PipelineWizard|Commit your new file"
-msgstr ""
+msgstr "æ交您的新檔案"
msgid "PipelineWizard|The file has been committed."
-msgstr ""
+msgstr "檔案已æ交。"
msgid "PipelineWizard|There was a problem committing the changes."
-msgstr ""
+msgstr "æ交更改時發生å•é¡Œã€‚"
msgid "PipelineWizard|There was a problem while checking whether your file already exists in the specified branch."
-msgstr ""
+msgstr "檢查您的檔案是å¦å·²å­˜åœ¨æ–¼æŒ‡å®šåˆ†æ”¯æ™‚出ç¾å•é¡Œã€‚"
msgid "PipelineWizard|There was an unexpected error trying to set up the template. The error has been logged."
-msgstr ""
+msgstr "嘗試設定範本時發生æ„外錯誤。錯誤已被記錄。"
msgid "Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "Pipelines charts"
-msgstr ""
+msgstr "æµæ°´ç·šçµ±è¨ˆåœ–"
msgid "Pipelines settings for '%{project_name}' were successfully updated."
-msgstr ""
+msgstr "「%{project_name}ã€çš„æµæ°´ç·šè¨­å®šå·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Pipelines|\"Hello world\" with GitLab CI"
-msgstr ""
+msgstr "使用 GitLab CI å¯¦ç¾ \"Hello world\""
msgid "Pipelines|1. Set up a runner"
-msgstr ""
+msgstr "1.設定執行器"
msgid "Pipelines|2. Configure deployment pipeline"
-msgstr ""
+msgstr "2.設定部署æµæ°´ç·š"
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 ""
+msgstr "æµæ°´ç·š|GitLab 執行器是一個與 GitLab CI/CD 一起在æµæ°´ç·šä¸­é‹è¡Œä½œæ¥­çš„應用程å¼ã€‚å®‰è£ GitLab 執行器並註冊您自己的執行器來開始使用 CI/CD。"
msgid "Pipelines|API"
-msgstr ""
+msgstr "API"
msgid "Pipelines|Are you sure you want to run this pipeline?"
-msgstr ""
+msgstr "您確定è¦åŸ·è¡Œé€™æ¢æµæ°´ç·šå—Žï¼Ÿ"
msgid "Pipelines|Auto DevOps"
-msgstr ""
+msgstr "自動化 DevOps"
msgid "Pipelines|Based on your project, we recommend this template:"
-msgstr ""
+msgstr "根據您的專案,我們推薦此範本:"
msgid "Pipelines|Build with confidence"
-msgstr ""
+msgstr "自信地構建"
msgid "Pipelines|Building for iOS?"
-msgstr ""
+msgstr "為 iOS 構建?"
msgid "Pipelines|By revoking a trigger you will break any processes making use of it. Are you sure?"
-msgstr ""
+msgstr "通éŽæ’¤éŠ·è§¸ç™¼å™¨å°‡æœƒå½±éŸ¿ä»»ä½•æ­£åœ¨èª¿ç”¨å®ƒçš„程åºï¼Œæ‚¨ç¢ºå®šå—Žï¼Ÿ"
msgid "Pipelines|CI lint"
-msgstr ""
+msgstr "CI lint"
msgid "Pipelines|Child pipeline (%{link_start}parent%{link_end})"
-msgstr ""
+msgstr "å­æµæ°´ç·šï¼ˆ%{link_start}父æµæ°´ç·š%{link_end})"
msgid "Pipelines|Clear runner caches"
-msgstr ""
+msgstr "清除Runner緩存"
msgid "Pipelines|Configuration validation currently not available."
-msgstr ""
+msgstr "設定驗證目å‰ä¸å¯ç”¨ã€‚"
msgid "Pipelines|Configure pipeline"
-msgstr ""
+msgstr "é…ç½®æµæ°´ç·š"
msgid "Pipelines|Continuous integration and deployment template to test and deploy your %{name} project."
-msgstr ""
+msgstr "æŒçºŒæ•´åˆå’Œéƒ¨ç½²ç¯„本用於測試和部署您的 %{name} 專案。"
msgid "Pipelines|Copy trigger token"
-msgstr ""
+msgstr "複製觸發令牌"
msgid "Pipelines|Could not load artifacts."
-msgstr ""
+msgstr "無法載入產物。"
msgid "Pipelines|Could not load merged YAML content"
-msgstr ""
+msgstr "無法載入åˆä½µçš„ YAML 內容"
msgid "Pipelines|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Pipelines|Don't need a guide? Jump in right away with a template."
-msgstr ""
+msgstr "ä¸éœ€è¦å°Žå¼•ï¼Ÿç«‹å³ä½¿ç”¨ç¯„本。"
msgid "Pipelines|Edit"
-msgstr ""
+msgstr "編輯"
msgid "Pipelines|Editor"
-msgstr ""
+msgstr "編輯器"
msgid "Pipelines|Follow these instructions to install GitLab Runner on macOS."
-msgstr ""
+msgstr "ä¾ç…§é€™äº›èªªæ˜Žåœ¨ macOS ä¸Šå®‰è£ GitLab Runner。"
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 ""
+msgstr "通éŽè¨­å®šä¸€å€‹åŸ·è¡Œ \"Hello world\" 腳本的簡單æµæ°´ç·šä¾†ç†Ÿæ‚‰ GitLab CI 語法,查看它如何é‹è¡Œï¼ŒæŽ¢ç´¢ CI/CD 的工作方å¼ã€‚"
msgid "Pipelines|Get started with GitLab CI/CD"
-msgstr ""
+msgstr "開始使用 GitLab CI/CD"
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å¯ä»¥è‡ªå‹•æ§‹å»ºï¼Œæ¸¬è©¦å’Œéƒ¨ç½²æ‚¨çš„代碼。讓GitLab處ç†è²»æ™‚的任務,您就有花更多的時間進行創造性的工作。"
msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline."
-msgstr ""
+msgstr "GitLab Runner 是一個與 GitLab CI/CD 一起使用在æµæ°´ç·šä¸­åŸ·è¡Œä½œæ¥­çš„應用程åºã€‚"
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 ""
+msgstr "GitLab Runner 是一個與 GitLab CI/CD åˆä½œåœ¨æµæ°´ç·šä¸­é‹è¡Œä½œæ¥­çš„應用程å¼ã€‚ç¾åœ¨æœ‰å•Ÿç”¨çš„ runner å¯ä»¥é‹è¡Œæ‚¨çš„作業。您å¯ä»¥%{settingsLinkStart}設定您的 runner%{settingsLinkEnd} 或%{docsLinkStart}了解更多關於 runner 的訊æ¯%{docsLinkEnd}。"
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
-msgstr ""
+msgstr "如果您ä¸ç¢ºå®šï¼Œè«‹å°ˆæ¡ˆç¶­è­·è€…為您審核。"
msgid "Pipelines|Install GitLab Runner"
-msgstr ""
+msgstr "å®‰è£ GitLab Runner"
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
-msgstr ""
+msgstr "建議在使用父專案的CI資æºåŸ·è¡Œæ­¤æµæ°´ç·šä¹‹å‰ï¼Œå°ç¨‹å¼ç¢¼é€²è¡Œè©³ç›¡çš„審核。"
msgid "Pipelines|Last Used"
-msgstr ""
+msgstr "最近使用"
msgid "Pipelines|Learn the basics of pipelines and .yml files"
-msgstr ""
+msgstr "學習æµæ°´ç·šå’Œ .yml 文件的基礎知識"
msgid "Pipelines|Let's get that runner set up! %{emojiStart}tada%{emojiEnd}"
-msgstr ""
+msgstr "è®“æˆ‘å€‘è¨­å®šåŸ·è¡Œå™¨ï¼ %{emojiStart}tada%{emojiEnd}"
msgid "Pipelines|Lint"
-msgstr ""
+msgstr "Lint"
msgid "Pipelines|Loading Pipelines"
-msgstr ""
+msgstr "載入æµæ°´ç·š"
msgid "Pipelines|Loading pipelines"
-msgstr ""
+msgstr "正在載入æµæ°´ç·š"
msgid "Pipelines|Merged YAML is view only"
-msgstr ""
+msgstr "åˆä½µå¾Œçš„ YAML 僅供ç€è¦½"
msgid "Pipelines|More Information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "Pipelines|Need more information to set up your runner? %{linkStart}Check out our documentation%{linkEnd}."
-msgstr ""
+msgstr "需è¦æ›´å¤šä¿¡æ¯ä¾†è¨­å®šæ‚¨çš„執行器? %{linkStart}查看我們的文檔%{linkEnd}。"
msgid "Pipelines|No runners detected"
-msgstr ""
+msgstr "æµæ°´ç·š|未檢測到執行器"
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
-msgstr ""
+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 ""
+msgstr "ä¸æ˜¯ç‚º iOS 構建或ä¸æ˜¯æ‚¨æ­£åœ¨å°‹æ‰¾çš„æ±è¥¿ï¼Ÿ %{linkStart}看看還有什麼%{linkEnd} GitLab CI/CD æ供的。"
msgid "Pipelines|Owner"
-msgstr ""
+msgstr "所有者"
msgid "Pipelines|Pipeline Editor"
-msgstr ""
+msgstr "æµæ°´ç·šç·¨è¼¯å™¨"
+
+msgid "Pipelines|Pipeline syntax is correct."
+msgstr "æµæ°´ç·šèªžæ³•æ­£ç¢ºã€‚"
msgid "Pipelines|Project cache successfully reset."
-msgstr ""
+msgstr "專案快å–é‡è¨­æˆåŠŸã€‚"
msgid "Pipelines|Ready to set up CI/CD for your project?"
-msgstr ""
+msgstr "準備好為您的專案設定 CI/CD 嗎?"
msgid "Pipelines|Revoke trigger"
-msgstr ""
+msgstr "撤銷觸發器"
msgid "Pipelines|Runners are available to run your jobs now"
-msgstr ""
+msgstr "æµæ°´ç·š|執行器ç¾åœ¨å¯ä»¥åŸ·è¡Œæ‚¨çš„作業"
msgid "Pipelines|Set up a runner"
-msgstr ""
+msgstr "設定執行器"
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr ""
+msgstr "清ç†runnerå¿«å–時發生錯誤。"
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 "%{namespace_name} 命å空間還有 %{percentage}%% 或更少的共享Runneræµæ°´ç·šå‰©é¤˜åˆ†é˜æ•¸ã€‚它用完後,其專案中的新作業或æµæ°´ç·šå°‡ä¸æœƒé‹è¡Œã€‚"
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 "%{namespace_name} 命å空間已超出其æµæ°´ç·šåˆ†é˜é…é¡ã€‚購買é¡å¤–çš„æµæ°´ç·šåˆ†é˜æ•¸ï¼Œå¦å‰‡å…¶å°ˆæ¡ˆä¸­å°‡ä¸æœƒåŸ·è¡Œæ–°çš„作業或æµæ°´ç·šã€‚"
msgid "Pipelines|The CI configuration was not loaded, please try again."
-msgstr ""
+msgstr "CI設定未載入,請é‡è©¦ã€‚"
msgid "Pipelines|The GitLab CI configuration could not be updated."
-msgstr ""
+msgstr "GitLab CI設定無法更新。"
msgid "Pipelines|There are currently no finished pipelines."
-msgstr ""
+msgstr "ç›®å‰æ²’有已完æˆçš„æµæ°´ç·šã€‚"
msgid "Pipelines|There are currently no pipelines."
-msgstr ""
+msgstr "當å‰ç„¡æµæ°´ç·šã€‚"
msgid "Pipelines|There was a problem with loading the pipeline data."
-msgstr ""
+msgstr "載入æµæ°´ç·šè³‡æ–™æ™‚出ç¾å•é¡Œã€‚"
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "å–å¾—æµæ°´ç·šæ™‚發生錯誤。請ç¨å¾Œé‡è©¦æˆ–è¯çµ¡æ”¯æ´åœ˜éšŠã€‚"
msgid "Pipelines|This GitLab CI configuration is invalid."
-msgstr ""
+msgstr "此GitLab CI設定無效。"
msgid "Pipelines|This GitLab CI configuration is invalid:"
-msgstr ""
+msgstr "此GitLab CI設定無效:"
msgid "Pipelines|This GitLab CI configuration is invalid: %{reason}."
-msgstr ""
+msgstr "此GitLab CI設定無效:%{reason}。"
msgid "Pipelines|This GitLab CI configuration is valid."
-msgstr ""
+msgstr "此GitLab CI設定有效。"
msgid "Pipelines|This is a child pipeline within the parent pipeline"
-msgstr ""
+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 "æ­¤æµæ°´ç·šåœ¨æ­¤åˆä½µè«‹æ±‚的內容上執行,並çµåˆæ‰€æœ‰å…¶å®ƒæŽ’隊等待åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯çš„åˆä½µè«‹æ±‚的內容。"
msgid "Pipelines|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+msgstr "æ­¤æµæ°´ç·šåœ¨æ­¤åˆä½µè«‹æ±‚çš„æºåˆ†æ”¯çš„內容上執行,而ä¸æ˜¯ç›®æ¨™åˆ†æ”¯ã€‚"
msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
-msgstr ""
+msgstr "æ­¤æµæ°´ç·šå°‡åŸ·è¡Œæºè‡ªåˆ†å‰çš„專案åˆä½µè«‹æ±‚程å¼ç¢¼ã€‚ 這æ„味著該程å¼ç¢¼å¯èƒ½å­˜åœ¨å®‰å…¨å•é¡Œï¼Œå¦‚暴露CI變數。"
msgid "Pipelines|This project is not currently set up to run pipelines."
-msgstr ""
+msgstr "此專案目å‰æœªè¨­å®šåŸ·è¡Œæµæ°´ç·šã€‚"
msgid "Pipelines|Token"
-msgstr ""
+msgstr "令牌(權æ–)"
msgid "Pipelines|Trigger user has insufficient permissions to project"
-msgstr ""
+msgstr "觸發使用者沒有足夠的專案權é™"
msgid "Pipelines|Try test template"
-msgstr ""
+msgstr "嘗試測試範本"
msgid "Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works."
-msgstr ""
+msgstr "使用 %{codeStart}.gitlab-ci.yml%{codeEnd} 範本文件來探索CI/CD 如何工作。"
msgid "Pipelines|Use a template based on your project's language or framework to get started with GitLab CI/CD."
-msgstr ""
+msgstr "使用基於您的專案語言或框架的範本來開始使用 GitLab CI/CD。"
msgid "Pipelines|Use template"
-msgstr ""
+msgstr "使用範本"
msgid "Pipelines|Validate"
-msgstr ""
+msgstr "é©—è­‰"
msgid "Pipelines|Validating GitLab CI configuration…"
-msgstr ""
+msgstr "驗證GitLab CI設定中…"
msgid "Pipelines|View merged YAML"
-msgstr ""
+msgstr "查看åˆä½µçš„ YAML"
msgid "Pipelines|Visualize"
-msgstr ""
+msgstr "視覺化"
msgid "Pipelines|We'll guide you through a simple pipeline set-up."
-msgstr ""
+msgstr "我們將指導您完æˆä¸€å€‹ç°¡å–®çš„æµæ°´ç·šè¨­å®šã€‚"
msgid "Pipelines|We'll walk you through how to deploy to iOS in two easy steps."
-msgstr ""
+msgstr "我們將通éŽå…©å€‹ç°¡å–®çš„步驟å‘您介紹如何部署到 iOS。"
msgid "Pipelines|You have runners available to run your job now. No need to do anything else."
-msgstr ""
+msgstr "您ç¾åœ¨æœ‰åŸ·è¡Œå™¨å¯ä»¥åŸ·è¡Œæ‚¨çš„工作。無需åšä»»ä½•å…¶ä»–事情。"
msgid "Pipelines|Your changes have been successfully committed. Now redirecting to the new merge request page."
-msgstr ""
+msgstr "您的更改已æˆåŠŸæ交,ç¾åœ¨é‡å®šå‘到新的åˆä½µè«‹æ±‚é é¢ã€‚"
msgid "Pipelines|error"
-msgstr ""
+msgstr "錯誤"
msgid "Pipelines|invalid"
-msgstr ""
+msgstr "無效"
msgid "Pipelines|latest"
-msgstr ""
+msgstr "最新"
msgid "Pipelines|merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Pipelines|merge train"
-msgstr ""
+msgstr "åˆä½µéšŠåˆ—"
msgid "Pipelines|stuck"
-msgstr ""
+msgstr "阻塞"
msgid "Pipelines|yaml invalid"
-msgstr ""
+msgstr "Yaml 無效"
msgid "Pipeline|Actions"
-msgstr ""
+msgstr "動作"
msgid "Pipeline|Branch name"
-msgstr ""
+msgstr "分支å稱"
msgid "Pipeline|Branches or tags could not be loaded."
-msgstr ""
+msgstr "無法載入分支或標籤。"
msgid "Pipeline|Canceled"
-msgstr ""
+msgstr "å·²å–消"
msgid "Pipeline|Checking pipeline status"
-msgstr ""
+msgstr "檢查æµæ°´ç·šç‹€æ…‹"
msgid "Pipeline|Checking pipeline status."
-msgstr ""
+msgstr "檢查æµæ°´ç·šç‹€æ…‹ã€‚"
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
-msgstr ""
+msgstr "無法å–å¾—æµæ°´ç·šç‹€æ…‹ã€‚有關故障排除步驟,請åƒé–±%{linkStart}文件%{linkEnd}。"
msgid "Pipeline|Created"
-msgstr ""
+msgstr "已建立"
msgid "Pipeline|Creating pipeline."
-msgstr ""
+msgstr "正在建立æµæ°´ç·šã€‚"
msgid "Pipeline|Date"
-msgstr ""
+msgstr "日期"
msgid "Pipeline|Detached merge request pipeline"
-msgstr ""
+msgstr "游離的åˆä½µè«‹æ±‚æµæ°´ç·š"
msgid "Pipeline|Failed"
-msgstr ""
+msgstr "失敗"
+
+msgid "Pipeline|Five slowest jobs"
+msgstr "五個最慢的作業"
msgid "Pipeline|In progress"
-msgstr ""
+msgstr "進行中"
+
+msgid "Pipeline|Last executed job"
+msgstr "最後執行的作業"
+
+msgid "Pipeline|Longest queued job"
+msgstr "排隊時間最長的作業"
msgid "Pipeline|Manual"
-msgstr ""
+msgstr "手動"
msgid "Pipeline|Merge train pipeline"
-msgstr ""
+msgstr "åˆä½µä½‡åˆ—æµæ°´ç·š"
msgid "Pipeline|Merge train pipeline jobs can not be retried"
-msgstr ""
+msgstr "åˆä½µä½‡åˆ—æµæ°´ç·šä½œæ¥­ç„¡æ³•é‡è©¦"
msgid "Pipeline|Merged result pipeline"
-msgstr ""
+msgstr "åˆä½µçµæžœæµæ°´ç·š"
+
+msgid "Pipeline|Only able to show first 100 results"
+msgstr "åªèƒ½é¡¯ç¤ºå‰ 100 個çµæžœ"
msgid "Pipeline|Passed"
-msgstr ""
+msgstr "已通éŽ"
msgid "Pipeline|Pending"
-msgstr ""
+msgstr "等待中"
+
+msgid "Pipeline|Performance insights"
+msgstr "效能檢視"
msgid "Pipeline|Pipeline"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "Pipeline|Pipeline %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
-msgstr ""
+msgstr "æµæ°´ç·š %{idStart}#%{idEnd} %{statusStart}%{statusEnd} for %{commitStart}%{commitEnd}"
msgid "Pipeline|Pipeline cannot be run."
-msgstr ""
+msgstr "æµæ°´ç·šç„¡æ³•åŸ·è¡Œã€‚"
msgid "Pipeline|Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
-msgstr ""
+msgstr "ç›®å‰ä¸æ”¯æ´åŽŸå§‹æ–‡æœ¬æœå°‹ã€‚請使用å¯ç”¨çš„查尋令牌。"
msgid "Pipeline|Run for branch name or tag"
-msgstr ""
+msgstr "以分支å稱或標籤執行"
+
+msgid "Pipeline|Run merge request pipeline"
+msgstr "執行åˆä½µè«‹æ±‚æµæ°´ç·š"
msgid "Pipeline|Run pipeline"
-msgstr ""
+msgstr "執行æµæ°´ç·š"
msgid "Pipeline|Running"
-msgstr ""
+msgstr "執行中"
msgid "Pipeline|Skipped"
-msgstr ""
+msgstr "已跳éŽ"
msgid "Pipeline|Source"
-msgstr ""
+msgstr "來æº"
msgid "Pipeline|Source|Security Policy"
-msgstr ""
+msgstr "安全政策"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
-msgstr ""
+msgstr "指定è¦åœ¨æ­¤æ¬¡åŸ·è¡Œä¸­ä½¿ç”¨çš„變數值。%{linkStart}CI/CD設定%{linkEnd}中指定的值將用作é è¨­å€¼."
msgid "Pipeline|Stages"
-msgstr ""
+msgstr "階段"
msgid "Pipeline|Status"
-msgstr ""
+msgstr "狀態"
msgid "Pipeline|Stop pipeline"
-msgstr ""
+msgstr "åœæ­¢æµæ°´ç·š"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
-msgstr ""
+msgstr "åœæ­¢æµæ°´ç·šï¼ƒ%{pipelineId}嗎?"
msgid "Pipeline|Tag name"
-msgstr ""
+msgstr "標籤å稱"
msgid "Pipeline|Test coverage"
-msgstr ""
+msgstr "測試覆蓋率"
+
+msgid "Pipeline|The last executed job is the last job to start in the pipeline."
+msgstr "最後執行的作業是在æµæ°´ç·šä¸­æœ€å¾Œé–‹å§‹çš„作業。"
+
+msgid "Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner"
+msgstr "排隊時間最長的作業是指在待處ç†ç‹€æ…‹ä¸­èŠ±è²»æœ€é•·æ™‚間,等待被執行器æ€é¸çš„作業"
msgid "Pipeline|This change will decrease the overall test coverage if merged."
-msgstr ""
+msgstr "如果åˆä½µï¼Œæ­¤æ›´æ”¹å°‡é™ä½Žæ•´é«”測試覆蓋率。"
msgid "Pipeline|This change will increase the overall test coverage if merged."
-msgstr ""
+msgstr "如果åˆä½µï¼Œæ­¤æ›´æ”¹å°‡å¢žåŠ æ•´é«”測試覆蓋率。"
msgid "Pipeline|This change will not change the overall test coverage if merged."
-msgstr ""
+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 "æ­¤æµæ°´ç·šåœ¨æ­¤åˆä½µè«‹æ±‚的內容上執行,並çµåˆæ‰€æœ‰å…¶å®ƒæŽ’隊等待åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯çš„åˆä½µè«‹æ±‚的內容。"
msgid "Pipeline|This pipeline ran on the contents of this merge request's source branch, not the target branch."
-msgstr ""
+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 "è¦åŸ·è¡Œåˆä½µè«‹æ±‚æµæ°´ç·šï¼Œå¿…須將 CI/CD 作業中的設定文件 %{linkStart} 設定為%{linkEnd} 在åˆä½µè«‹æ±‚æµæ°´ç·šä¸­åŸ·è¡Œã€‚"
msgid "Pipeline|Trigger author"
-msgstr ""
+msgstr "觸發者"
msgid "Pipeline|Triggerer"
-msgstr ""
+msgstr "觸發者"
msgid "Pipeline|Variables"
-msgstr ""
+msgstr "變數"
msgid "Pipeline|View commit"
-msgstr ""
+msgstr "查看æ交"
+
+msgid "Pipeline|View dependency"
+msgstr "檢視ä¾è³´"
msgid "Pipeline|View pipeline"
-msgstr ""
+msgstr "查看æµæ°´ç·š"
msgid "Pipeline|We are currently unable to fetch pipeline data"
-msgstr ""
+msgstr "我們目å‰ç„¡æ³•å–å¾—æµæ°´ç·šè³‡æ–™"
msgid "Pipeline|You’re about to stop pipeline #%{pipelineId}."
-msgstr ""
+msgstr "您å³å°‡è¦åœæ­¢æµæ°´ç·š #%{pipelineId}。"
msgid "Pipeline|for"
-msgstr ""
+msgstr "使用æ交"
msgid "Pipeline|merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "Pipeline|merge train"
-msgstr ""
+msgstr "åˆä½µä½‡åˆ—"
msgid "Pipeline|on"
-msgstr ""
+msgstr "æ–¼"
msgid "Pipeline|with stage"
-msgstr ""
+msgstr ",包å«éšŽæ®µ"
msgid "Pipeline|with stages"
-msgstr ""
+msgstr ",包å«éšŽæ®µ"
msgid "PivotalTrackerService|Add commit messages as comments to Pivotal Tracker stories."
-msgstr ""
+msgstr "å°‡æ交訊æ¯ä½œç‚ºç•™è¨€åŠ å…¥åˆ° Pivotal Tracker 故事。"
msgid "PivotalTrackerService|Comma-separated list of branches to automatically inspect. Leave blank to include all branches."
-msgstr ""
+msgstr "è¦è‡ªå‹•æª¢æŸ¥ä»¥é€—號分隔的分支列表。留空以包括所有分支。"
msgid "PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user."
-msgstr ""
+msgstr "Pivotal Tracker API 令牌。使用者必須有權存å–故事。所有留言都歸於該使用者。"
msgid "Plain diff"
-msgstr ""
+msgstr "文字差異"
msgid "Plain-text response to send to clients that hit a rate limit"
-msgstr ""
+msgstr "å‘é”到速率é™åˆ¶çš„客戶發é€çš„純文本回應。"
msgid "Plan"
-msgstr ""
+msgstr "計劃"
msgid "Plan:"
-msgstr ""
+msgstr "計劃:"
msgid "Planning hierarchy"
-msgstr ""
+msgstr "è¦åŠƒçµæ§‹"
msgid "PlantUML"
-msgstr ""
+msgstr "PlantUML"
msgid "PlantUML URL"
-msgstr ""
+msgstr "PlantUML URL"
msgid "PlantUML diagram"
-msgstr ""
+msgstr "PlantUML 圖"
msgid "Play"
msgstr "執行"
msgid "Play all manual"
-msgstr ""
+msgstr "執行所有手動作業"
msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
-msgstr ""
+msgstr "想è¦ç•™è¨€è«‹ %{link_to_register} 或 %{link_to_sign_in}"
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 ""
+msgstr "請接å—æœå‹™æ¢æ¬¾ä»¥ç¹¼çºŒã€‚"
msgid "Please add a comment in the text area above"
-msgstr ""
+msgstr "請在上é¢æ–‡å­—框加入留言"
msgid "Please check the configuration file for this chart"
-msgstr ""
+msgstr "請檢查此圖表的設定檔案"
msgid "Please check the configuration file to ensure that a collection of charts has been declared."
-msgstr ""
+msgstr "請檢查設定文件以確ä¿å·²è²æ˜Žäº†ä¸€çµ„圖表。"
msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
-msgstr ""
+msgstr "請檢查設定文件以確ä¿å®ƒå¯ç”¨ä¸”YAML有效"
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 ""
+msgstr "請檢查您的電å­éƒµä»¶(%{email})以確èªæ‚¨æ“有此電å­ä¿¡ç®±ä¸¦è§£éŽ–CI/CD的強大功能。還沒收到郵件? %{resend_link}。或是電å­éƒµä»¶åœ°å€éŒ¯èª¤ï¼Ÿ%{update_link}。"
+
+msgid "Please click the link in the confirmation email before continuing. It was sent to "
+msgstr "繼續å‰ï¼Œè«‹é»žé¸ç¢ºèªä¿¡ä¸­çš„連çµã€‚信件已傳é€è‡³ "
msgid "Please complete your profile with email address"
-msgstr ""
+msgstr "請在您的個人資料中填寫電å­éƒµä»¶åœ°å€"
msgid "Please confirm your email address"
-msgstr ""
+msgstr "請確èªæ‚¨çš„é›»å­éƒµä»¶åœ°å€"
msgid "Please contact an admin to register runners."
-msgstr ""
+msgstr "è«‹è¯çµ¡ç®¡ç†å“¡ä»¥è¨»å†ŠåŸ·è¡Œå™¨ã€‚"
msgid "Please contact your GitLab administrator if you think this is an error."
-msgstr ""
+msgstr "如果您èªç‚ºé€™æ˜¯ä¸€å€‹éŒ¯èª¤ï¼Œè«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ã€‚"
msgid "Please contact your administrator with any questions."
-msgstr ""
+msgstr "如有任何å•é¡Œï¼Œè«‹è¯çµ¡æ‚¨çš„管ç†å“¡ã€‚"
msgid "Please contact your administrator."
-msgstr ""
+msgstr "è«‹è¯çµ¡æ‚¨çš„管ç†å“¡ã€‚"
msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
-msgstr ""
+msgstr "請將他們%{linkStart}轉æ›ç‚ºGit%{linkEnd},然後å†æ¬¡åŸ·è¡Œ%{linkToImportFlow}。"
msgid "Please copy, download, or print your recovery codes before proceeding."
-msgstr ""
+msgstr "請複製ã€ä¸‹è¼‰æˆ–列å°æ‚¨çš„æ¢å¾©ç¢¼å¾Œå†ç¹¼çºŒã€‚"
msgid "Please create a password for your new account."
-msgstr ""
+msgstr "請為您的新帳號建立密碼。"
msgid "Please create a username with only alphanumeric characters."
-msgstr ""
+msgstr "請建立僅包å«å­—æ¯å’Œæ•¸å­—的使用者å稱。"
msgid "Please create an index before enabling indexing"
-msgstr ""
+msgstr "啟用索引å‰è«‹å…ˆå»ºç«‹ç´¢å¼•"
msgid "Please delete your current license if you want to downgrade to the free plan."
-msgstr ""
+msgstr "如果您想é™ç´šåˆ°æ¨™æº–版,請刪除您當å‰çš„授權許å¯ã€‚"
msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
-msgstr ""
+msgstr "請啟用並é·ç§»åˆ°æ•£åˆ—儲存以é¿å…安全å•é¡Œä¸¦ç¢ºä¿è³‡æ–™å®Œæ•´æ€§ã€‚%{migrate_link}"
msgid "Please enter a non-negative number"
-msgstr ""
+msgstr "請輸入一個éžè² æ•¸"
msgid "Please enter a number greater than %{number} (from the project settings)"
-msgstr ""
+msgstr "請輸入大於%{number}(來自專案設定)的數字"
msgid "Please enter a valid URL format, ex: http://www.example.com/home"
-msgstr ""
+msgstr "請輸入一個有效的URLæ ¼å¼ï¼Œä¾‹å¦‚:http://www.example.com/home"
msgid "Please enter a valid hex (#RRGGBB or #RGB) color value"
-msgstr ""
+msgstr "請輸入一個有效的å六進制(#RRGGBB或#RGB)é¡è‰²å€¼"
msgid "Please enter a valid number"
-msgstr ""
+msgstr "請輸入有效的數字"
msgid "Please enter a valid time interval"
-msgstr ""
+msgstr "請輸入有效的時間間隔"
msgid "Please enter your current password."
-msgstr ""
+msgstr "請輸入您的當å‰å¯†ç¢¼ã€‚"
msgid "Please fill in a descriptive name for your group."
-msgstr ""
+msgstr "請為您的群組填寫æ述性å稱。"
msgid "Please fill in a name for your topic."
-msgstr ""
+msgstr "請填寫您主題的å稱。"
msgid "Please fill in a title for your topic."
-msgstr ""
+msgstr "請填寫您主題的標題。"
msgid "Please fill out this field."
-msgstr ""
+msgstr "請填寫此欄ä½ã€‚"
msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
-msgstr ""
+msgstr "請按照%{link_start}Let's Encrypt故障排除指å—%{link_end}來é‡æ–°å–得加密證書。"
msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
-msgstr ""
+msgstr "請按照Let's Encrypt故障排除指å—來é‡æ–°å–å¾—Let's Encrypt證書: %{docs_url}"
msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
-msgstr ""
+msgstr "請將所有ç¾æœ‰å°ˆæ¡ˆé·ç§»åˆ°æ•£åˆ—儲存,以é¿å…安全å•é¡Œä¸¦ç¢ºä¿è³‡æ–™å®Œæ•´æ€§ã€‚ %{migrate_link}"
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
-msgstr ""
+msgstr "請注æ„,GitLabä¸æ供此應用程å¼ï¼Œæ‚¨æ‡‰è©²åœ¨å…許存å–之å‰é©—證其真實性。"
msgid "Please provide a name"
-msgstr ""
+msgstr "è«‹æä¾›å稱"
msgid "Please provide a name."
-msgstr ""
+msgstr "è«‹æ供一個å稱。"
msgid "Please provide a valid URL."
-msgstr ""
+msgstr "è«‹æ供有效的URL。"
msgid "Please provide a valid email address."
-msgstr ""
+msgstr "è«‹æ供有效的電å­éƒµä»¶åœ°å€ã€‚"
msgid "Please provide attributes to update"
-msgstr ""
+msgstr "è«‹æä¾›è¦æ›´æ–°çš„屬性"
msgid "Please reach out if you have any questions and we'll be happy to assist."
-msgstr ""
+msgstr "若有任何å•é¡Œè«‹è¯çµ¡æˆ‘們,我們將竭誠為您æœå‹™ã€‚"
+
+msgid "Please review the %{linkStart}contribution guidelines%{linkEnd} for this project."
+msgstr "請審閱此專案的%{linkStart}è²¢ç»æŒ‡å—%{linkEnd}。"
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 ""
+msgstr "請審核 %{project_link} çš„æ›´æ–°å‡ç´šæ”¿ç­–。建議您è¯çµ¡ç•¶å‰çš„ on-call å›žæ‡‰è€…ï¼Œä»¥ç¢ºä¿ on-call 覆蓋的連續性。"
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 ""
+msgstr "請審核 %{project} çš„æ›´æ–°å‡ç´šæ”¿ç­–。建議您è¯çµ¡ç•¶å‰çš„ on-call å›žæ‡‰è€…ï¼Œä»¥ç¢ºä¿ on-call 覆蓋的連續性。"
msgid "Please select"
-msgstr ""
+msgstr "è«‹é¸æ“‡"
msgid "Please select a Jira project"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹Jira專案"
msgid "Please select a country"
-msgstr ""
+msgstr "è«‹é¸æ“‡åœ‹å®¶/地å€"
msgid "Please select a file"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹æ–‡ä»¶"
msgid "Please select a group"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹ç¾¤çµ„"
msgid "Please select a valid target branch"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹æœ‰æ•ˆçš„目標分支"
msgid "Please select a valid target branch."
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹æœ‰æ•ˆçš„目標分支。"
msgid "Please select and add a member"
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸¦åŠ å…¥ä¸€å€‹æˆå“¡"
msgid "Please select at least one filter to see results"
-msgstr ""
+msgstr "請至少é¸æ“‡ä¸€å€‹éŽæ¿¾å™¨ä¾†æŸ¥çœ‹çµæžœ"
msgid "Please select what should be included in each exported requirement."
-msgstr ""
+msgstr "è«‹é¸æ“‡æ¯å€‹åŒ¯å‡ºéœ€æ±‚中應包å«çš„內容。"
msgid "Please select..."
-msgstr ""
+msgstr "è«‹é¸æ“‡..."
msgid "Please set a new password before proceeding."
-msgstr ""
+msgstr "請設定新密碼以繼續下一步。"
msgid "Please solve the captcha"
-msgstr ""
+msgstr "請處ç†é©—證碼"
msgid "Please try again"
-msgstr ""
+msgstr "è«‹å†è©¦ä¸€æ¬¡"
msgid "Please try and refresh the page. If the problem persists please contact support."
-msgstr ""
+msgstr "請嘗試é‡æ–°æ•´ç†é é¢ã€‚如果å•é¡Œä»ç„¶å­˜åœ¨ï¼Œè«‹è¯çµ¡æ”¯æ´äººå“¡ã€‚"
msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
-msgstr ""
+msgstr "請輸入%{phrase_code}以繼續或關閉此å°è©±æ¡†ä»¥å–消。"
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
-msgstr ""
+msgstr "請使用此表單å‘管ç†å“¡å ±å‘Šå»ºç«‹åžƒåœ¾è­°é¡Œã€ç•™è¨€æˆ–行為ä¸ç•¶çš„使用者。"
msgid "Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "è«‹ç¨ç­‰ç‰‡åˆ»ï¼Œæ­¤é é¢åœ¨å°±ç·’時會自動é‡æ–°æ•´ç†ã€‚"
msgid "Please wait while we connect to your repository. Refresh at will."
-msgstr ""
+msgstr "連接程å¼ç¢¼ç‰ˆæœ¬åº«ä¸­ï¼Œè«‹ç¨å€™ã€‚å¯åœ¨ä»»æ„時刻é‡æ–°æ•´ç†ä»¥è®€å–ç›®å‰ç‹€æ…‹ã€‚"
msgid "Please wait while we import the repository for you. Refresh at will."
-msgstr ""
+msgstr "匯入程å¼ç¢¼ç‰ˆæœ¬åº«ä¸­ï¼Œè«‹ç¨å€™ã€‚å¯åœ¨ä»»æ„時刻é‡æ–°æ•´ç†ä»¥è®€å–ç›®å‰ç‹€æ…‹ã€‚"
msgid "Pods in use"
-msgstr ""
+msgstr "正在使用的Pod"
msgid "Point to any links you like: documentation, built binaries, or other related materials. These can be internal or external links from your GitLab instance. Each URL and link title must be unique."
-msgstr ""
+msgstr "指å‘您喜歡的任何連çµï¼šæ–‡ä»¶ã€æ§‹å»ºçš„二進制文件或其他相關æ料。這些å¯ä»¥æ˜¯ä¾†è‡ª GitLab 實例的內部或外部連çµã€‚æ¯å€‹ URL 和連çµæ¨™é¡Œå¿…須是唯一的。"
msgid "Policies"
-msgstr ""
+msgstr "政策"
msgid "Policy '%{escalation_policy_name}' does not exist."
-msgstr ""
+msgstr "政策「%{escalation_policy_name}ã€ä¸å­˜åœ¨ã€‚"
msgid "Policy management project does not have any policies in %{policy_path}"
-msgstr ""
+msgstr "政策管ç†å°ˆæ¡ˆåœ¨ %{policy_path} 中沒有任何政策"
msgid "Policy project doesn't exist"
-msgstr ""
+msgstr "政策專案ä¸å­˜åœ¨"
msgid "PolicyRuleMultiSelect|%{firstLabel} +%{numberOfAdditionalLabels} more"
-msgstr ""
+msgstr "%{firstLabel} +%{numberOfAdditionalLabels} 更多"
msgid "PolicyRuleMultiSelect|All %{itemTypeName}"
-msgstr ""
+msgstr "所有 %{itemTypeName}"
msgid "PolicyRuleMultiSelect|Select %{itemTypeName}"
-msgstr ""
+msgstr "é¸æ“‡ %{itemTypeName}"
msgid "PolicyRuleMultiSelect|Select all"
-msgstr ""
+msgstr "é¸æ“‡æ‰€æœ‰"
msgid "Polling interval multiplier"
-msgstr ""
+msgstr "輪詢間隔å€æ•¸"
msgid "Popularity"
-msgstr ""
+msgstr "è²æœ›"
msgid "Port"
-msgstr ""
+msgstr "埠號"
msgid "Postman collection"
-msgstr ""
+msgstr "Postman 集åˆ"
msgid "Postman collection file path or URL"
-msgstr ""
+msgstr "Postman 集åˆæ–‡ä»¶è·¯å¾‘或 URL"
msgid "Potentially unwanted character detected: Unicode BiDi Control"
-msgstr ""
+msgstr "檢測到å¯èƒ½ä¸éœ€è¦çš„字符:Unicode BiDi Control"
msgid "Pre-defined push rules"
-msgstr ""
+msgstr "é å…ˆå®šç¾©çš„推é€è¦å‰‡"
msgid "Preferences"
msgstr "å好設定"
msgid "Preferences saved."
-msgstr ""
+msgstr "å好設定已儲存。"
msgid "Preferences|Behavior"
-msgstr ""
+msgstr "個人化"
msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
-msgstr ""
+msgstr "為應用程å¼é¸æ“‡å›ºå®šæ–¹å¼(最大值1280px)或æµå‹•æ–¹å¼(%{percentage})佈局。"
msgid "Preferences|Choose what content you want to see on a project’s overview page."
-msgstr ""
+msgstr "é¸æ“‡å°ˆæ¡ˆæ¦‚覽é é¢ä¸­æ‚¨æƒ³çœ‹åˆ°çš„內容。"
msgid "Preferences|Choose what content you want to see on your homepage."
-msgstr ""
+msgstr "é¸æ“‡æ‚¨æƒ³è¦åœ¨é¦–é ä¸Šçœ‹åˆ°çš„內容。"
msgid "Preferences|Color for added lines"
-msgstr ""
+msgstr "為已加入行著色"
msgid "Preferences|Color for removed lines"
-msgstr ""
+msgstr "為已移除行著色"
msgid "Preferences|Color theme"
-msgstr ""
+msgstr "佈景主題å好設定"
msgid "Preferences|Configure how dates and times display for you."
-msgstr ""
+msgstr "設定日期和時間的顯示方å¼ã€‚"
msgid "Preferences|Customize integrations with third party services."
-msgstr ""
+msgstr "自訂與第三方æœå‹™çš„æ•´åˆã€‚"
msgid "Preferences|Customize the color of GitLab."
-msgstr ""
+msgstr "自定義 GitLab çš„é¡è‰²ã€‚"
msgid "Preferences|Customize the colors of removed and added lines in diffs."
-msgstr ""
+msgstr "自定義差異中的刪除和加入行的é¡è‰²ã€‚"
msgid "Preferences|Diff colors"
-msgstr ""
+msgstr "差異的é¡è‰²"
msgid "Preferences|Display time in 24-hour format"
-msgstr ""
+msgstr "以24å°æ™‚æ ¼å¼é¡¯ç¤ºæ™‚é–“"
msgid "Preferences|Enable Gitpod integration"
-msgstr ""
+msgstr "啟用Gitpodæ•´åˆ"
msgid "Preferences|Enable integrated code intelligence on code views"
-msgstr ""
+msgstr "啟用程å¼ç¢¼è¦–圖的整åˆç¨‹å¼ç¢¼æ™ºèƒ½åŠŸèƒ½"
msgid "Preferences|Failed to save preferences."
-msgstr ""
+msgstr "無法ä¿å­˜å好設定"
msgid "Preferences|For example: 30 minutes ago."
-msgstr ""
+msgstr "例如:30分é˜å‰"
msgid "Preferences|Gitpod"
-msgstr ""
+msgstr "Gitpod"
msgid "Preferences|Homepage content"
-msgstr ""
+msgstr "首é å…§å®¹"
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
-msgstr ""
+msgstr "一次僅顯示一個文件,而ä¸æ˜¯æ‰€æœ‰æ›´æ”¹çš„文件。è¦åœ¨æ–‡ä»¶ä¹‹é–“切æ›ï¼Œè«‹ä½¿ç”¨æ–‡ä»¶ç€è¦½å™¨ã€‚"
msgid "Preferences|Integrations"
-msgstr ""
+msgstr "æ•´åˆ"
msgid "Preferences|Layout width"
-msgstr ""
+msgstr "佈局寬度"
msgid "Preferences|Must be a number between %{min} and %{max}"
-msgstr ""
+msgstr "必須為%{min}到%{max}之間的數字"
msgid "Preferences|Preview"
-msgstr ""
+msgstr "é è¦½"
msgid "Preferences|Project overview content"
-msgstr ""
+msgstr "專案概覽內容"
msgid "Preferences|Render whitespace characters in the Web IDE"
-msgstr ""
+msgstr "åœ¨ç¶²é  IDE 繪製空白字元"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
-msgstr ""
+msgstr "在åˆä½µè«‹æ±‚的變更標籤上一次åªé¡¯ç¤ºä¸€å€‹æ–‡ä»¶"
msgid "Preferences|Show whitespace changes in diffs"
-msgstr ""
+msgstr "顯示差異中的空白變化"
msgid "Preferences|Sourcegraph"
-msgstr ""
+msgstr "來æºåœ–"
msgid "Preferences|Surround text selection when typing quotes or brackets"
-msgstr ""
+msgstr "輸入引號或方括號時的環繞文字é¸æ“‡"
msgid "Preferences|Syntax highlighting theme"
-msgstr ""
+msgstr "語法醒目標示主題"
msgid "Preferences|Tab width"
-msgstr ""
+msgstr "Tab 寬度"
msgid "Preferences|This feature is experimental and translations are not yet complete."
-msgstr ""
+msgstr "此功能是實驗性的,翻譯尚未完æˆã€‚"
msgid "Preferences|This setting allows you to customize the appearance of the syntax."
-msgstr ""
+msgstr "此設定å…許您自訂基於語法的外觀。"
msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
-msgstr ""
+msgstr "此設定å…許您自訂系統佈局和é è¨­æª¢è¦–的呈ç¾ã€‚"
msgid "Preferences|Time preferences"
-msgstr ""
+msgstr "時å€è¨­å®š"
msgid "Preferences|Use relative times"
-msgstr ""
+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 ""
+msgstr "當您在æ述或留言框中輸入時,在輸入以下字元之一後,é¸å®šçš„文本將被相應的字元包åœï¼š%{supported_characters}。"
msgid "Preparing the report for the scan."
-msgstr ""
+msgstr "準備掃æ報告。"
msgid "Prev"
-msgstr ""
+msgstr "上一é "
msgid "Prevent auto-stopping"
-msgstr ""
+msgstr "ç¦æ­¢è‡ªå‹•åœæ­¢"
-msgid "Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgid "Prevent editing approval rules in projects and merge requests"
+msgstr "防止在專案與åˆä½µè«‹æ±‚中編輯核准è¦å‰‡"
msgid "Prevent environment from auto-stopping"
-msgstr ""
+msgstr "ç¦æ­¢ç’°å¢ƒè‡ªå‹•åœæ­¢"
msgid "Prevent project forking outside current group"
-msgstr ""
+msgstr "ç¦æ­¢å°ˆæ¡ˆåˆ†å‰(fork)到當å‰ç¾¤çµ„以外"
msgid "Prevent users from changing their profile name"
-msgstr ""
+msgstr "ç¦æ­¢ä½¿ç”¨è€…變更個人檔案å稱"
msgid "Prevent users from performing write operations while GitLab maintenance is in progress."
-msgstr ""
+msgstr "ç¦æ­¢ä½¿ç”¨è€…在維護期間執行寫入æ“作。"
msgid "Preview"
-msgstr ""
+msgstr "é è¦½"
msgid "Preview JavaScript projects in the Web IDE with CodeSandbox Live Preview. %{link_start}Learn more.%{link_end} "
-msgstr ""
+msgstr "使用 CodeSandbox Live Preview 在 Web IDE 中é è¦½ã€‚%{link_start}了解更多訊æ¯ã€‚%{link_end} "
msgid "Preview Markdown"
-msgstr ""
+msgstr "Markdowné è¦½"
msgid "Preview changes"
-msgstr ""
+msgstr "é è¦½è®Šæ›´"
msgid "Preview diagram"
-msgstr ""
+msgstr "é è¦½åœ–"
msgid "Preview payload"
-msgstr ""
+msgstr "é è¦½ä¸Šå‚³è³‡æ–™"
msgid "Previous Artifacts"
-msgstr ""
+msgstr "å‰ä¸€å€‹ç”¢ç‰©"
msgid "Previous commit"
-msgstr ""
+msgstr "上一次æ交"
msgid "Previous design"
-msgstr ""
+msgstr "上一個設計"
msgid "Previous file in diff"
-msgstr ""
+msgstr "差異中的上一個文件"
msgid "Previous unresolved discussion"
-msgstr ""
+msgstr "上一次未解決的討論"
msgid "Primary Action"
-msgstr ""
+msgstr "主è¦æ“作"
msgid "Print codes"
-msgstr ""
+msgstr "列å°ç¨‹å¼ç¢¼"
msgid "Prioritize"
-msgstr ""
+msgstr "優先"
msgid "Prioritize label"
-msgstr ""
+msgstr "優先標記"
msgid "Prioritized Labels"
-msgstr ""
+msgstr "優先標記"
msgid "Prioritized label"
-msgstr ""
+msgstr "優先標記"
msgid "Priority"
-msgstr ""
+msgstr "優先級"
msgid "Private"
-msgstr ""
+msgstr "ç§æœ‰"
msgid "Private - Guest users are not allowed to view detailed release information like title and source code."
-msgstr ""
+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 ""
+msgstr "ç§æœ‰ - 專案存å–必須明確授予æ¯å€‹ä½¿ç”¨è€…。如果此專案是在一個群組中,群組æˆå“¡å°‡æœƒç²å¾—å­˜å–權é™ã€‚"
msgid "Private - The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "ç§äºº - 群組åŠå…¶å°ˆæ¡ˆåªèƒ½ç”±æˆå“¡æŸ¥çœ‹ã€‚"
msgid "Private group(s)"
-msgstr ""
+msgstr "ç§æœ‰ç¾¤çµ„"
msgid "Private profile"
-msgstr ""
+msgstr "éžå…¬é–‹è³‡æ–™"
msgid "Private projects Minutes cost factor"
-msgstr ""
+msgstr "ç§æœ‰å°ˆæ¡ˆåˆ†é˜æˆæœ¬ä¿‚數"
msgid "Private projects can be created in your personal namespace with:"
-msgstr ""
+msgstr "ç§æœ‰å°ˆæ¡ˆå¯ä»¥åœ¨å€‹äººå稱空間中建立:"
msgid "Problem with %{name} command: %{message}."
-msgstr ""
+msgstr "%{name} 指令發生錯誤: %{message}。"
msgid "Proceed"
-msgstr ""
+msgstr "繼續"
msgid "Product Analytics"
-msgstr ""
+msgstr "產å“分æž"
msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
-msgstr ""
+msgstr "此類型的圖表目å‰æ²’有資料。如果您尚未設定產å“分æžå·¥å…·ï¼Œè«‹æŸ¥çœ‹è¨­å®šæ¨™ç±¤ã€‚"
msgid "Productivity"
-msgstr ""
+msgstr "生產率"
msgid "Productivity Analytics"
-msgstr ""
+msgstr "生產率分æž"
msgid "Productivity analytics can help identify the problems that are delaying your team"
-msgstr ""
+msgstr "生產率分æžæœ‰åŠ©æ–¼æ‰¾å‡ºé€ æˆåœ˜éšŠæ‹–延的å•é¡Œ"
msgid "ProductivityAanalytics|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
-msgstr ""
+msgstr "æ—©æ–¼å…許的最早日期"
msgid "ProductivityAnalytics|Ascending"
-msgstr ""
+msgstr "å‡åº"
msgid "ProductivityAnalytics|Days"
-msgstr ""
+msgstr "天"
msgid "ProductivityAnalytics|Days to merge"
-msgstr ""
+msgstr "完æˆåˆä½µæ‰€éœ€å¤©æ•¸"
msgid "ProductivityAnalytics|Descending"
-msgstr ""
+msgstr "é™åº"
msgid "ProductivityAnalytics|Hours"
-msgstr ""
+msgstr "å°æ™‚"
msgid "ProductivityAnalytics|List"
-msgstr ""
+msgstr "列表"
msgid "ProductivityAnalytics|Merge Requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "ProductivityAnalytics|Merge date"
-msgstr ""
+msgstr "åˆä½µæ—¥æœŸ"
msgid "ProductivityAnalytics|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "ProductivityAnalytics|Time to merge"
-msgstr ""
+msgstr "åˆä½µæ™‚é–“"
msgid "ProductivityAnalytics|Trendline"
-msgstr ""
+msgstr "趨勢"
msgid "ProductivityAnalytics|is earlier than the given merged at after date"
-msgstr ""
+msgstr "æ—©æ–¼åˆä½µå¾Œæ—¥æœŸ"
msgid "Profile"
-msgstr ""
+msgstr "個人檔案"
msgid "Profile Settings"
-msgstr ""
+msgstr "個人資料設定"
msgid "Profile failed to delete"
-msgstr ""
+msgstr "刪除個人資料失敗"
msgid "Profile image guideline"
-msgstr ""
+msgstr "個人資料圖片導引"
msgid "Profile page:"
-msgstr ""
+msgstr "個人資料é ï¼š"
msgid "Profile parameter missing"
-msgstr ""
+msgstr "設定文件åƒæ•¸ä¸Ÿå¤±"
msgid "ProfileSession|on"
-msgstr ""
+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 ""
+msgstr "您å³å°‡æ°¸ä¹…刪除 %{yourAccount},以åŠèˆ‡æ‚¨çš„帳號關è¯çš„所有議題,åˆä½µè«‹æ±‚å’Œç¾¤çµ„ã€‚ä¸€æ—¦ç¢ºèª %{deleteAccount},此æ“作便無法撤銷和æ¢å¾©ã€‚"
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 ""
+msgstr "您將變更使用者å稱 %{currentUsernameBold} 為 %{newUsernameBold}。設定檔案和專案將é‡å®šä½åˆ° %{newUsername} 命å空間,但是一旦 %{currentUsername} 命å空間被å¦ä¸€å€‹ä½¿ç”¨è€…或組註冊,此é‡å®šå‘å°‡éŽæœŸã€‚請儘快更新您的é ç«¯Git版本庫。"
msgid "Profiles|%{provider} Active"
-msgstr ""
+msgstr "%{provider}有效"
msgid "Profiles|@username"
-msgstr ""
+msgstr "@使用者å稱"
msgid "Profiles|Account could not be deleted. GitLab was unable to verify your identity."
-msgstr ""
+msgstr "帳號無法刪除,GitLab 無法驗證您的身份。"
msgid "Profiles|Account scheduled for removal."
-msgstr ""
+msgstr "帳號已安排刪除。"
msgid "Profiles|Active"
-msgstr ""
+msgstr "活動"
msgid "Profiles|Add key"
-msgstr ""
+msgstr "加入金鑰"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "在狀態中加入表情符號"
msgid "Profiles|An error occurred while updating your username, please try again."
-msgstr ""
+msgstr "更新您的使用者å稱時發生錯誤,請é‡è©¦ã€‚"
msgid "Profiles|An indicator appears next to your name and avatar."
-msgstr ""
+msgstr "在您的å字和頭åƒæ—邊顯示標識。"
msgid "Profiles|Avatar cropper"
-msgstr ""
+msgstr "é ­åƒè£å‰ª"
msgid "Profiles|Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "å³å°‡åˆªé™¤é ­åƒã€‚確定繼續嗎?"
msgid "Profiles|Begins with %{ssh_key_algorithms}."
-msgstr ""
+msgstr "以 %{ssh_key_algorithms} 開頭。"
msgid "Profiles|Bio"
-msgstr ""
+msgstr "自我介紹"
msgid "Profiles|Busy"
-msgstr ""
+msgstr "忙碌中"
msgid "Profiles|Change username"
-msgstr ""
+msgstr "變更使用者å稱"
msgid "Profiles|Changing your username can have unintended side effects."
-msgstr ""
+msgstr "變更您的使用者å稱å¯èƒ½æœƒç”¢ç”Ÿæ„想ä¸åˆ°çš„副作用。"
msgid "Profiles|Choose file..."
-msgstr ""
+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 ""
+msgstr "城市,國家"
msgid "Profiles|Clear status"
-msgstr ""
+msgstr "清除狀態"
msgid "Profiles|Commit email"
-msgstr ""
+msgstr "æ交郵件"
msgid "Profiles|Connect %{provider}"
-msgstr ""
+msgstr "連接%{provider}"
msgid "Profiles|Connect a service for sign-in."
-msgstr ""
+msgstr "連接第三方登入æœå‹™ã€‚"
msgid "Profiles|Connected Accounts"
-msgstr ""
+msgstr "已連線帳號"
msgid "Profiles|Current path: %{path}"
-msgstr ""
+msgstr "ç›®å‰è·¯å¾‘: %{path}"
msgid "Profiles|Current status"
-msgstr ""
+msgstr "ç›®å‰ç‹€æ…‹"
msgid "Profiles|Default notification email"
-msgstr ""
+msgstr "é è¨­é€šçŸ¥éƒµä»¶"
msgid "Profiles|Delete account"
-msgstr ""
+msgstr "刪除帳號"
msgid "Profiles|Deleting an account has the following effects:"
-msgstr ""
+msgstr "刪除帳號具有以下效果:"
msgid "Profiles|Disconnect"
-msgstr ""
+msgstr "æ–·é–‹"
msgid "Profiles|Disconnect %{provider}"
-msgstr ""
+msgstr "與%{provider}斷開連接"
msgid "Profiles|Do not show on profile"
-msgstr ""
+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 ""
+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 ""
+msgstr "輸入您的密碼以確èªé›»å­éƒµä»¶æ›´æ”¹"
msgid "Profiles|Enter your pronouns to let people know how to refer to you."
-msgstr ""
+msgstr "輸入您的代稱,讓人們知é“如何稱呼您."
msgid "Profiles|Example: MacBook key"
-msgstr ""
+msgstr "例如:MacBook Key"
msgid "Profiles|Expiration date"
-msgstr ""
+msgstr "到期日期"
msgid "Profiles|Expired:"
-msgstr ""
+msgstr "å·²éŽæœŸï¼š"
msgid "Profiles|Expires:"
-msgstr ""
+msgstr "éŽæœŸï¼š"
msgid "Profiles|Feed token was successfully reset"
-msgstr ""
+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 ""
+msgstr "GitLab ç„¡æ³•è‡ªå‹•é©—è­‰æ‚¨çš„èº«ä»½ã€‚ç‚ºäº†å®‰å…¨èµ·è¦‹ï¼Œæ‚¨å¿…é ˆé€šéŽ %{openingTag}é‡ç½®æ‚¨çš„密碼%{closingTag} 進行密碼設定來刪除您的帳號。"
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 "如果設定密碼後,刪除帳號的é¸é …ä»ç„¶ä¸å¯ç”¨ï¼Œè«‹%{link_start}æ交請求%{link_end}來開始帳號刪除程åºã€‚"
msgid "Profiles|Include private contributions on my profile"
-msgstr ""
+msgstr "在個人資料中包å«éžå…¬é–‹è²¢ç»"
msgid "Profiles|Incoming email token was successfully reset"
-msgstr ""
+msgstr "接收郵件令牌(權æ–)å·²é‡è¨­"
msgid "Profiles|Increase your account's security by enabling two-factor authentication (2FA)."
-msgstr ""
+msgstr "啟用雙因å­é©—è­‰ (2FA),æ高帳號安全性"
msgid "Profiles|Invalid password"
-msgstr ""
+msgstr "密碼無效"
msgid "Profiles|Invalid username"
-msgstr ""
+msgstr "使用者å稱無效"
msgid "Profiles|Job title"
-msgstr ""
+msgstr "è·ä½"
msgid "Profiles|Key"
-msgstr ""
+msgstr "金鑰"
msgid "Profiles|Key becomes invalid on this date."
-msgstr ""
+msgstr "金鑰在此日期無效。"
msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
-msgstr ""
+msgstr "金鑰在此日期無效,SSH 金鑰的最大有效期為 %{max_ssh_key_lifetime} 天"
msgid "Profiles|Key titles are publicly visible."
-msgstr ""
+msgstr "金鑰標題是公開å¯è¦‹çš„。"
msgid "Profiles|Last used:"
-msgstr ""
+msgstr "最近使用:"
msgid "Profiles|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "Profiles|Location"
-msgstr ""
+msgstr "ä½ç½®"
msgid "Profiles|Made a private contribution"
-msgstr ""
+msgstr "作出了ç§æœ‰è²¢ç»"
msgid "Profiles|Main settings"
-msgstr ""
+msgstr "主è¦è¨­å®š"
msgid "Profiles|Manage two-factor authentication"
-msgstr ""
+msgstr "管ç†å…©æ­¥é©Ÿé©—è­‰"
msgid "Profiles|No file chosen."
-msgstr ""
+msgstr "未é¸æ“‡æ–‡ä»¶ã€‚"
msgid "Profiles|Notification email"
-msgstr ""
+msgstr "通知郵件"
msgid "Profiles|Organization"
-msgstr ""
+msgstr "組織"
msgid "Profiles|Path"
-msgstr ""
+msgstr "路徑"
msgid "Profiles|Position and size your new avatar"
-msgstr ""
+msgstr "您新頭åƒçš„ä½ç½®å’Œå¤§å°"
msgid "Profiles|Primary email"
-msgstr ""
+msgstr "主郵件"
msgid "Profiles|Private contributions"
-msgstr ""
+msgstr "éžå…¬é–‹è²¢ç»"
msgid "Profiles|Profile was successfully updated"
-msgstr ""
+msgstr "個人資料已æˆåŠŸæ›´æ–°"
msgid "Profiles|Pronouns"
-msgstr ""
+msgstr "稱呼"
msgid "Profiles|Pronunciation"
-msgstr ""
+msgstr "讀音"
msgid "Profiles|Public avatar"
-msgstr ""
+msgstr "公開頭åƒ"
msgid "Profiles|Public email"
-msgstr ""
+msgstr "公開郵件"
msgid "Profiles|Publicly visible private SSH keys can compromise your system."
-msgstr ""
+msgstr "公開å¯è¦‹çš„ç§æœ‰SSH金鑰å¯èƒ½æœƒæ害您的系統。"
msgid "Profiles|Remove avatar"
-msgstr ""
+msgstr "刪除頭åƒ"
msgid "Profiles|Select a service to sign in with."
-msgstr ""
+msgstr "é¸æ“‡è¦ç™»å…¥çš„æœå‹™ã€‚"
msgid "Profiles|Service sign-in"
-msgstr ""
+msgstr "第三方登入"
msgid "Profiles|Set new profile picture"
-msgstr ""
+msgstr "設定新個人資料圖片"
msgid "Profiles|Set your local time zone."
-msgstr ""
+msgstr "設定您的時å€."
msgid "Profiles|Some options are unavailable for LDAP accounts"
-msgstr ""
+msgstr "æŸäº›é¸é …å°æ–¼ LDAP 帳號ä¸å¯ç”¨"
msgid "Profiles|Static object token was successfully reset"
-msgstr ""
+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 ""
+msgstr "管ç†å“¡é™åˆ¶äº†æ‚¨æ›´æ–°å稱的權利。"
msgid "Profiles|The maximum file size allowed is 200KB."
-msgstr ""
+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 ""
+msgstr "此表情符號和消æ¯æœƒé¡¯ç¤ºåœ¨æ‚¨çš„個人資料和界é¢ä¸­ã€‚"
msgid "Profiles|This information will appear on your profile."
-msgstr ""
+msgstr "這個訊æ¯å°‡æœƒé¡¯ç¤ºåœ¨æ‚¨çš„個人資料中。"
msgid "Profiles|Time settings"
-msgstr ""
+msgstr "時間設定"
msgid "Profiles|Title"
-msgstr ""
+msgstr "標題"
msgid "Profiles|Two-factor authentication"
-msgstr ""
+msgstr "雙因å­é©—è­‰"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
-msgstr ""
+msgstr "輸入您的 %{confirmationValue} 以確èªï¼š"
msgid "Profiles|Update profile settings"
-msgstr ""
+msgstr "更新個人資料設定"
msgid "Profiles|Update username"
-msgstr ""
+msgstr "更新使用者å稱"
msgid "Profiles|Upload new avatar"
-msgstr ""
+msgstr "上傳新頭åƒ"
msgid "Profiles|Use a private email - %{email}"
-msgstr ""
+msgstr "使用ç§äººé›»å­éƒµä»¶ - %{email}"
msgid "Profiles|User ID"
-msgstr ""
+msgstr "使用者ID"
msgid "Profiles|Username change failed - %{message}"
-msgstr ""
+msgstr "使用者å稱變更失敗 - %{message}"
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 ""
+msgstr "姓å中使用表情符號雖然有趣,但請å‰å¾€ç‹€æ…‹è¨Šæ¯è£¡ä½¿ç”¨å®ƒ"
msgid "Profiles|Website url"
-msgstr ""
+msgstr "網站 URL"
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 ""
+msgstr "å¯ä»¥åœ¨é€™è£¡ä¿®æ”¹æ‚¨çš„é ­åƒ"
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨é€™è£¡ä¿®æ”¹é ­åƒæˆ–刪除當å‰é ­åƒä¸¦æ¢å¾©ç‚º %{gravatar_link}"
msgid "Profiles|You can upload your avatar here"
-msgstr ""
+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 ""
+msgstr "您無權刪除此使用者。"
msgid "Profiles|You must accept the Terms of Service in order to perform this action."
-msgstr ""
+msgstr "您必須接å—æœå‹™æ¢æ¬¾æ‰èƒ½åŸ·è¡Œæ­¤æ“作。"
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
-msgstr ""
+msgstr "您必須轉移所有權或刪除這些群組,然後æ‰èƒ½åˆªé™¤æ‚¨çš„帳號。"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
-msgstr ""
+msgstr "您必須轉移所有權或刪除這些群組,然後æ‰èƒ½åˆªé™¤æ‚¨çš„帳號。"
msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
-msgstr ""
+msgstr "您的LinkedInå稱,åƒè¦‹linkedin.com/in/profilename"
msgid "Profiles|Your account is currently an owner in these groups:"
-msgstr ""
+msgstr "您的帳號目å‰æ˜¯é€™äº›ç¾¤çµ„的所有者:"
msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "您的電å­éƒµä»¶åœ°å€æ˜¯æ ¹æ“šæ‚¨çš„ %{provider_label} 帳號自動設定的"
msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
-msgstr ""
+msgstr "您的ä½ç½®æ˜¯åŸºæ–¼æ‚¨çš„ %{provider_label} 帳號自動設定的。"
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
-msgstr ""
+msgstr "您的姓å是根據您的 %{provider_label} 帳號自動設定的,以便大家èªè­˜æ‚¨"
msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
-msgstr ""
+msgstr "您的姓å是根據您的 %{provider_label} 帳號自動設定的,以便大家èªè­˜æ‚¨."
msgid "Profiles|Your status"
-msgstr ""
+msgstr "您目å‰çš„狀態?"
msgid "Profiles|https://website.com"
-msgstr ""
+msgstr "https://website.com"
msgid "Profiles|username"
-msgstr ""
+msgstr "使用者å稱"
msgid "Profiles|your account"
-msgstr ""
+msgstr "您的帳號"
msgid "Profile|%{job_title} at %{organization}"
-msgstr ""
+msgstr "%{organization}çš„%{job_title}"
msgid "Profiling - Performance bar"
-msgstr ""
+msgstr "åˆ†æž - 效能欄"
msgid "Programming languages used in this repository"
-msgstr ""
+msgstr "ç›®å‰ç¨‹å¼ç¢¼ç‰ˆæœ¬åº«ä¸­ä½¿ç”¨çš„程å¼èªžè¨€"
msgid "Progress"
-msgstr ""
+msgstr "進度"
msgid "Progress tracking"
-msgstr ""
+msgstr "進度追蹤"
msgid "Project"
-msgstr ""
+msgstr "專案"
msgid "Project \"%{name}\" is no longer available. Select another project to continue."
-msgstr ""
+msgstr "專案「%{name}ã€ä¸å†å¯ç”¨ã€‚é¸æ“‡å¦ä¸€å€‹å°ˆæ¡ˆä»¥ç¹¼çºŒã€‚"
msgid "Project %{project_repo} could not be found"
-msgstr ""
+msgstr "無法找到專案 %{project_repo}"
msgid "Project & Group can not be assigned at the same time"
-msgstr ""
+msgstr "專案和群組ä¸èƒ½åŒæ™‚分é…"
msgid "Project '%{project_name}' is being imported."
-msgstr ""
+msgstr "正在匯入專案 \"%{project_name}\"。"
msgid "Project '%{project_name}' is in the process of being deleted."
-msgstr ""
+msgstr "專案 「%{project_name}〠正在被刪除。"
msgid "Project '%{project_name}' is restored."
-msgstr ""
+msgstr "專案'%{project_name}'å·²æ¢å¾©ã€‚"
msgid "Project '%{project_name}' queued for deletion."
-msgstr ""
+msgstr "專案 '%{project_name}' 已進入刪除佇列。"
msgid "Project '%{project_name}' was successfully created."
-msgstr ""
+msgstr "專案 '%{project_name}' 已建立æˆåŠŸã€‚"
msgid "Project '%{project_name}' was successfully updated."
-msgstr ""
+msgstr "專案 '%{project_name}' 已更新完æˆã€‚"
msgid "Project '%{project_name}' will be deleted on %{date}"
-msgstr ""
+msgstr "專案%{project_name}將於%{date}被刪除"
msgid "Project Access Tokens"
-msgstr ""
+msgstr "專案存å–令牌"
msgid "Project Badges"
-msgstr ""
+msgstr "專案徽章"
msgid "Project Files"
-msgstr ""
+msgstr "專案文件"
msgid "Project ID"
-msgstr ""
+msgstr "專案ID"
msgid "Project Templates"
-msgstr ""
+msgstr "專案範本"
msgid "Project URL"
-msgstr ""
+msgstr "專案 URL"
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 "專案存å–必須明確授予æ¯å€‹ä½¿ç”¨è€…。 如果此專案是在一個群組中,群組æˆå“¡å°‡æœƒç²å¾—å­˜å–權é™ã€‚"
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 "專案存å–令牌建立在此群組中被ç¦ç”¨ã€‚您ä»ç„¶å¯ä»¥ä½¿ç”¨å’Œç®¡ç†ç¾æœ‰ä»¤ç‰Œã€‚ %{link_start}了解更多訊æ¯ã€‚%{link_end}"
msgid "Project already deleted"
-msgstr ""
+msgstr "專案已被刪除"
msgid "Project and wiki repositories"
-msgstr ""
+msgstr "專案和wiki倉庫"
msgid "Project audit events"
-msgstr ""
+msgstr "專案審計事件"
msgid "Project avatar"
-msgstr ""
+msgstr "專案頭åƒ"
msgid "Project cannot be shared with the group it is in or one of its ancestors."
-msgstr ""
+msgstr "專案ä¸èƒ½åˆ†äº«çµ¦ç•¶å‰æ‰€åœ¨çš„群組或其任一級父群組。"
msgid "Project configuration, excluding integrations"
-msgstr ""
+msgstr "專案設定,ä¸åŒ…括整åˆ"
msgid "Project description (optional)"
-msgstr ""
+msgstr "專案æè¿° (å¯é¸)"
msgid "Project does not exist or you don't have permission to perform this action"
-msgstr ""
+msgstr "專案ä¸å­˜åœ¨æˆ–您沒有權é™åŸ·è¡Œæ­¤æ“作"
msgid "Project does not have a policy configuration"
-msgstr ""
+msgstr "專案沒有政策設定"
msgid "Project export could not be deleted."
-msgstr ""
+msgstr "無法刪除專案匯出。"
msgid "Project export download requests"
-msgstr ""
+msgstr "專案匯出下載請求"
msgid "Project export has been deleted."
-msgstr ""
+msgstr "專案匯出已被刪除。"
msgid "Project export link has expired. Please generate a new export from your project settings."
-msgstr ""
+msgstr "專案匯出連çµå·²éŽæœŸã€‚請從專案設定中é‡æ–°ç”Ÿæˆå°ˆæ¡ˆåŒ¯å‡ºã€‚"
msgid "Project export requests"
-msgstr ""
+msgstr "專案匯出請求"
msgid "Project export started. A download link will be sent by email and made available on this page."
-msgstr ""
+msgstr "專案匯出已經開始。下載連çµå°‡é€šéŽé›»å­éƒµä»¶ç™¼é€ä¸¦åœ¨æ­¤é é¢ä¸Šæ供。"
msgid "Project has too many %{label_for_message} to search"
-msgstr ""
+msgstr "專案有太多個 %{label_for_message} è¦æœå°‹"
msgid "Project import requests"
-msgstr ""
+msgstr "專案匯入請求"
msgid "Project info:"
-msgstr ""
+msgstr "專案訊æ¯ï¼š"
msgid "Project information"
-msgstr ""
+msgstr "專案訊æ¯"
msgid "Project is required when cluster_type is :project"
-msgstr ""
+msgstr "cluster_type為 :project 時專案為必需"
msgid "Project members"
-msgstr ""
+msgstr "專案æˆå“¡"
msgid "Project milestone"
-msgstr ""
+msgstr "專案里程碑"
msgid "Project name"
-msgstr ""
+msgstr "專案å稱"
msgid "Project navigation"
-msgstr ""
+msgstr "專案導覽"
msgid "Project order will not be saved as local storage is not available."
-msgstr ""
+msgstr "由於本機儲存ä¸å¯ç”¨ï¼Œå› æ­¤ä¸æœƒå„²å­˜å°ˆæ¡ˆé †åºã€‚"
msgid "Project path"
-msgstr ""
+msgstr "專案路徑"
msgid "Project security status"
-msgstr ""
+msgstr "專案安全狀態"
msgid "Project security status help page"
-msgstr ""
+msgstr "專案安全狀態幫助é é¢"
msgid "Project slug"
-msgstr ""
+msgstr "專案標識"
msgid "Project uploads"
-msgstr ""
+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 ""
+msgstr "當專案轉移到群組後,其å¯è¦‹ç´šåˆ¥å°‡è®Šæ›´ç‚ºèˆ‡å‘½å空間è¦å‰‡ç›¸ç¬¦åˆã€‚"
msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "未找到專案或者您沒有權é™å°‡æ­¤å°ˆæ¡ˆåŠ å…¥åˆ°å®‰å…¨å„€è¡¨æ¿ã€‚"
msgid "Project: %{name}"
-msgstr ""
+msgstr "專案: %{name}"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}"
+msgstr "專案:分支:%{source_project_path}:%{source_branch} 到 %{target_project_path}:%{target_branch}"
+
+msgid "Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
+msgstr "專案:分支:%{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}"
msgid "ProjectActivityRSS|Subscribe"
-msgstr ""
+msgstr "訂閱"
msgid "ProjectCreationLevel|Allowed to create projects"
-msgstr ""
+msgstr "å…許建立專案"
msgid "ProjectCreationLevel|Default project creation protection"
-msgstr ""
+msgstr "é è¨­çš„群組專案建立ä¿è­·"
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr ""
+msgstr "開發人員 + 維護人員"
msgid "ProjectCreationLevel|Maintainers"
-msgstr ""
+msgstr "維護人員"
msgid "ProjectCreationLevel|No one"
-msgstr ""
+msgstr "ç¦æ­¢"
msgid "ProjectCreationLevel|Roles allowed to create projects"
-msgstr ""
+msgstr "å…許建立專案的角色"
msgid "ProjectFileTree|Name"
-msgstr ""
+msgstr "å稱"
msgid "ProjectFileTree|Show more"
-msgstr ""
+msgstr "顯示更多"
msgid "ProjectLastActivity|Never"
-msgstr ""
+msgstr "從未"
msgid "ProjectOverview|Fork"
-msgstr ""
+msgstr "分å‰"
msgid "ProjectOverview|Forks"
-msgstr ""
+msgstr "分å‰"
msgid "ProjectOverview|Go to your fork"
-msgstr ""
+msgstr "å‰å¾€æ‚¨å¾—分å‰"
msgid "ProjectOverview|Star"
-msgstr ""
+msgstr "星號(收è—)"
msgid "ProjectOverview|Starrer"
-msgstr ""
+msgstr "星號(收è—)者"
msgid "ProjectOverview|Starrers"
-msgstr ""
+msgstr "星號(收è—)者"
msgid "ProjectOverview|Unstar"
-msgstr ""
+msgstr "å–消星號(收è—)"
msgid "ProjectOverview|You don't have permission to fork this project"
-msgstr ""
+msgstr "您沒有權é™åˆ†å‰æ­¤å°ˆæ¡ˆ"
msgid "ProjectOverview|You have reached your project limit"
-msgstr ""
+msgstr "您已é”到專案數é‡é™åˆ¶"
msgid "ProjectOverview|You must sign in to star a project"
-msgstr ""
+msgstr "登入後æ‰èƒ½æ˜Ÿè™Ÿ(收è—)專案"
msgid "ProjectPage|Copy project ID"
-msgstr ""
+msgstr "複製專案ID"
msgid "ProjectPage|Project ID: %{project_id}"
-msgstr ""
+msgstr "專案ID: %{project_id}"
msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
-msgstr ""
+msgstr "嘗試å–得專案質é‡çµ±è¨ˆè¨Šæ¯æ™‚發生錯誤"
msgid "ProjectQualitySummary|Coverage"
-msgstr ""
+msgstr "覆蓋率"
msgid "ProjectQualitySummary|Failure"
-msgstr ""
+msgstr "失敗"
msgid "ProjectQualitySummary|Get insight into the overall percentage of tests in your project that succeed, fail and are skipped."
-msgstr ""
+msgstr "深入了解專案中,æˆåŠŸã€å¤±æ•—和被跳éŽçš„測試總體百分比。"
+
+msgid "ProjectQualitySummary|Help us improve this page"
+msgstr "å”助我們改進此é é¢"
msgid "ProjectQualitySummary|Latest pipeline results"
-msgstr ""
+msgstr "最新æµæ°´ç·šçµæžœ"
msgid "ProjectQualitySummary|Learn more about test coverage"
-msgstr ""
+msgstr "了解有關測試覆蓋率的更多訊æ¯"
msgid "ProjectQualitySummary|Learn more about test reports"
-msgstr ""
+msgstr "了解有關測試報告的更多訊æ¯"
msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
-msgstr ""
+msgstr "è¡¡é‡æ¸¬è©¦è¦†è“‹äº†å¤šå°‘代碼。。"
+
+msgid "ProjectQualitySummary|Provide feedback"
+msgstr "æ供回饋æ„見"
msgid "ProjectQualitySummary|See full report"
-msgstr ""
+msgstr "查看完整報告"
msgid "ProjectQualitySummary|See project Code Coverage Statistics"
-msgstr ""
+msgstr "查看專案程å¼ç¢¼è¦†è“‹çŽ‡çµ±è¨ˆ"
msgid "ProjectQualitySummary|Set up test runs"
-msgstr ""
+msgstr "設定測試執行"
msgid "ProjectQualitySummary|Set up test runs (opens in a new tab)"
-msgstr ""
+msgstr "設定測試執行(在新標籤中打開)"
msgid "ProjectQualitySummary|Skipped"
-msgstr ""
+msgstr "è·³éŽ"
msgid "ProjectQualitySummary|Success"
-msgstr ""
+msgstr "æˆåŠŸ"
msgid "ProjectQualitySummary|Test coverage"
-msgstr ""
+msgstr "測試覆蓋率"
msgid "ProjectQualitySummary|Test runs"
-msgstr ""
+msgstr "測試執行"
msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
-msgstr ""
+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 ""
+msgstr "或群組"
msgid "ProjectSelect|No matching results"
-msgstr ""
+msgstr "沒有符åˆçš„çµæžœ"
msgid "ProjectSelect|Search for project"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "ProjectSelect|Search projects"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "ProjectSelect|Select a project"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å°ˆæ¡ˆ"
msgid "ProjectSelect|Something went wrong while fetching projects"
-msgstr ""
+msgstr "讀å–專案時發生錯誤。"
msgid "ProjectSelect|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "å–得專案時發生錯誤。請é‡è©¦ã€‚"
msgid "ProjectService|Drone server URL"
-msgstr ""
+msgstr "Drone 伺æœå™¨URL"
msgid "ProjectService|Enter new API key"
-msgstr ""
+msgstr "輸入新的 API 金鑰"
msgid "ProjectService|Enter new password"
-msgstr ""
+msgstr "輸入新密碼"
msgid "ProjectService|Enter new password."
-msgstr ""
+msgstr "輸入新密碼。"
msgid "ProjectService|Enter new token"
-msgstr ""
+msgstr "輸入新令牌"
msgid "ProjectService|Jenkins server URL"
-msgstr ""
+msgstr "Jenkins 伺æœå™¨ URL"
msgid "ProjectService|Leave blank to use your current API key"
-msgstr ""
+msgstr "留空時,使用您當å‰çš„ API 金鑰"
msgid "ProjectService|Leave blank to use your current API key."
-msgstr ""
+msgstr "留空以使用您當å‰çš„ API 金鑰。"
msgid "ProjectService|Leave blank to use your current password"
-msgstr ""
+msgstr "留空時,使用您當å‰çš„密碼"
msgid "ProjectService|Leave blank to use your current password."
-msgstr ""
+msgstr "留空時,使用您當å‰çš„密碼。"
msgid "ProjectService|Leave blank to use your current token."
-msgstr ""
+msgstr "留空以使用您當å‰çš„令牌。"
msgid "ProjectService|Mock service URL"
-msgstr ""
+msgstr "模擬æœå‹™URL"
msgid "ProjectService|Must have permission to trigger a manual build in TeamCity."
-msgstr ""
+msgstr "必須具有在 TeamCity 中觸發手動構建的權é™ã€‚"
msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
-msgstr ""
+msgstr "在GitLab專案上執行常見æ“作: %{project_name}"
msgid "ProjectService|Run CI/CD pipelines with Buildkite."
-msgstr ""
+msgstr "使用 Buildkite 執行 CI/CD æµæ°´ç·šã€‚"
msgid "ProjectService|Run CI/CD pipelines with Drone."
-msgstr ""
+msgstr "使用 Drone 執行 CI/CD æµæ°´ç·šã€‚"
msgid "ProjectService|Run CI/CD pipelines with JetBrains TeamCity."
-msgstr ""
+msgstr "使用 JetBrains TeamCity 執行 CI/CD æµæ°´ç·šã€‚"
msgid "ProjectService|TeamCity server URL"
-msgstr ""
+msgstr "TeamCity 伺æœå™¨ URL"
msgid "ProjectService|The build configuration ID of the TeamCity project."
-msgstr ""
+msgstr "TeamCity 專案的構建設定 ID。"
msgid "ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository."
-msgstr ""
+msgstr "使用 GitLab 版本庫建立 Buildkite æµæ°´ç·šå¾Œç²å¾—的令牌。"
msgid "ProjectService|To configure this integration, you should:"
-msgstr ""
+msgstr "è¦è¨­å®šæ­¤æ•´åˆï¼Œæ‚¨æ‡‰è©²ï¼š"
msgid "ProjectService|Token for the Drone project."
-msgstr ""
+msgstr "Drone 專案的令牌。"
msgid "ProjectService|Trigger event for new comments on confidential issues."
-msgstr ""
+msgstr "é‡å°æ©Ÿå¯†å•é¡Œçš„新留言觸發事件。"
msgid "ProjectService|Trigger event for new comments."
-msgstr ""
+msgstr "新留言的觸發事件。"
msgid "ProjectService|Trigger event for new tags pushed to the repository."
-msgstr ""
+msgstr "推é€åˆ°ç‰ˆæœ¬åº«çš„新標籤觸發事件。"
msgid "ProjectService|Trigger event for pushes to the repository."
-msgstr ""
+msgstr "推é€åˆ°ç‰ˆæœ¬åº«çš„觸發事件。"
msgid "ProjectService|Trigger event when a commit is created or updated."
-msgstr ""
+msgstr "在建立或更新æ交時觸發事件。"
msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
-msgstr ""
+msgstr "在建立ã€æ›´æ–°æˆ–關閉機密議題時觸發事件。"
msgid "ProjectService|Trigger event when a deployment starts or finishes."
-msgstr ""
+msgstr "在部署開始或完æˆæ™‚觸發事件。"
msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
-msgstr ""
+msgstr "在建立ã€æ›´æ–°æˆ–åˆä½µåˆä½µè«‹æ±‚時觸發事件。"
msgid "ProjectService|Trigger event when a new, unique alert is recorded."
-msgstr ""
+msgstr "在記錄新的ã€å”¯ä¸€çš„警報時觸發事件。"
msgid "ProjectService|Trigger event when a new, unique vulnerability is recorded. (Note: This feature requires an Ultimate plan.)"
-msgstr ""
+msgstr "在記錄新的唯一æ¼æ´žæ™‚觸發事件。(注æ„:此功能需è¦æ——艦版方案。)"
msgid "ProjectService|Trigger event when a pipeline status changes."
-msgstr ""
+msgstr "æµæ°´ç·šç‹€æ…‹æ›´æ”¹æ™‚觸發事件。"
msgid "ProjectService|Trigger event when a wiki page is created or updated."
-msgstr ""
+msgstr "在建立或更新 wiki é é¢æ™‚觸發事件。"
msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
-msgstr ""
+msgstr "在建立ã€æ›´æ–°æˆ–關閉議題時觸發事件。"
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
-msgstr ""
+msgstr "%{link_start}什麼是æ述範本?%{link_end}"
msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
-msgstr ""
+msgstr "%{link_start}我å¯ä»¥ä½¿ç”¨å“ªäº›è®Šæ•¸ï¼Ÿ%{link_end}"
msgid "ProjectSettings|Additional options"
-msgstr ""
+msgstr "附加é¸é …"
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
-msgstr ""
+msgstr "影響åˆä½µå®Œæˆçš„æ–¹å¼å’Œæ™‚間的其他設定。"
msgid "ProjectSettings|All threads must be resolved"
-msgstr ""
+msgstr "必須解決所有線程"
msgid "ProjectSettings|Allow"
-msgstr ""
+msgstr "å…許"
msgid "ProjectSettings|Always show thumbs-up and thumbs-down award emoji buttons on issues, merge requests, and snippets."
-msgstr ""
+msgstr "始終在議題ã€åˆä½µè«‹æ±‚和程å¼ç¢¼ç‰‡æ®µä¸Šé¡¯ç¤ºè®šåŒå’Œä¸è®šåŒè¡¨æƒ…符號按鈕。"
msgid "ProjectSettings|Analytics"
-msgstr ""
+msgstr "分æž"
msgid "ProjectSettings|Automatically resolve merge request diff threads when they become outdated"
-msgstr ""
+msgstr "當它們變得éŽæ™‚時自動處ç†åˆä½µè«‹æ±‚差異線程"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "徽章"
msgid "ProjectSettings|Build, test, and deploy your changes."
-msgstr ""
+msgstr "構建ã€æ¸¬è©¦å’Œéƒ¨ç½²æ‚¨çš„更改。"
msgid "ProjectSettings|Checkbox is visible and selected by default."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œå¾©é¸æ¡†æ˜¯å¯è¦‹å’Œé¸å–的。"
msgid "ProjectSettings|Checkbox is visible and unselected by default."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œå¾©é¸æ¡†æ˜¯å¯è¦‹å’Œæœªé¸å–的。"
msgid "ProjectSettings|Choose the method, options, checks, and squash options for merge requests. You can also set up merge request templates for different actions."
-msgstr ""
+msgstr "為åˆä½µè«‹æ±‚é¸æ“‡æ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮。您還å¯ä»¥ç‚ºä¸åŒçš„æ“作設定åˆä½µè«‹æ±‚模æ¿ã€‚"
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
-msgstr ""
+msgstr "è«‹é¸æ“‡æ‚¨çš„åˆä½µæ–¹æ³•ã€åˆä½µé¸é …ã€åˆä½µæª¢æŸ¥ä»¥åŠåˆä½µå»ºè­°ã€‚"
msgid "ProjectSettings|Choose your merge method, options, checks, and squash options."
-msgstr ""
+msgstr "é¸æ“‡æ‚¨çš„åˆä½µæ–¹æ³•ã€é¸é …ã€æª¢æŸ¥å’Œå£“縮é¸é …。"
msgid "ProjectSettings|Configure your project resources and monitor their health."
-msgstr ""
+msgstr "設定您的專案資æºä¸¦ç›£æŽ§å®ƒå€‘的執行狀æ³ã€‚"
msgid "ProjectSettings|Contact an admin to change this setting."
-msgstr ""
+msgstr "è¯çµ¡ç®¡ç†å“¡è®Šæ›´æ­¤è¨­å®šã€‚"
msgid "ProjectSettings|Container registry"
-msgstr ""
+msgstr "容器映åƒåº«"
msgid "ProjectSettings|Customize this project's badges."
-msgstr ""
+msgstr "自訂此專案的徽章。"
msgid "ProjectSettings|Determine what happens to the commit history when you merge a merge request."
-msgstr ""
+msgstr "確定åˆä½µåˆä½µè«‹æ±‚時,æ交歷å²æœƒè¨˜éŒ„發生了什麼。"
msgid "ProjectSettings|Disable email notifications"
-msgstr ""
+msgstr "åœç”¨é›»å­éƒµä»¶é€šçŸ¥"
msgid "ProjectSettings|Do not allow"
-msgstr ""
+msgstr "ä¸å…許"
msgid "ProjectSettings|Enable \"Delete source branch\" option by default"
-msgstr ""
+msgstr "é è¨­å•Ÿç”¨ã€Œåˆªé™¤ä¾†æºåˆ†æ”¯ã€é¸é …"
msgid "ProjectSettings|Enable merge trains"
-msgstr ""
+msgstr "啟用åˆä½µä½‡åˆ—"
msgid "ProjectSettings|Enable merged results pipelines"
-msgstr ""
+msgstr "啟用åˆä½µçµæžœæµæ°´ç·š"
msgid "ProjectSettings|Encourage"
-msgstr ""
+msgstr "激勵"
msgid "ProjectSettings|Every merge creates a merge commit."
-msgstr ""
+msgstr "æ¯æ¬¡åˆä½µéƒ½æœƒå»ºç«‹ä¸€å€‹åˆä½µæ交。"
msgid "ProjectSettings|Every project can have its own space to store its Docker images"
-msgstr ""
+msgstr "æ¯å€‹å°ˆæ¡ˆéƒ½å¯ä»¥æœ‰è‡ªå·±çš„空間來儲存其Docker映åƒ"
msgid "ProjectSettings|Every project can have its own space to store its packages."
-msgstr ""
+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 ""
+msgstr "æ¯å€‹å°ˆæ¡ˆéƒ½å¯ä»¥æœ‰è‡ªå·±çš„空間來儲存它的軟體套件。注æ„:當一個專案是公開時,軟體套件庫總是å¯è¦‹çš„。"
msgid "ProjectSettings|Everyone"
-msgstr ""
+msgstr "所有人"
msgid "ProjectSettings|Existing merge requests and protected branches are not affected."
-msgstr ""
+msgstr "ç¾æœ‰åˆä½µè«‹æ±‚å’Œå—ä¿è­·åˆ†æ”¯ä¸å—影響。"
msgid "ProjectSettings|Failed to protect the tag"
-msgstr ""
+msgstr "ä¿è­·æ¨™ç±¤å¤±æ•—"
msgid "ProjectSettings|Failed to update tag!"
-msgstr ""
+msgstr "更新標籤失敗ï¼"
msgid "ProjectSettings|Fast-forward merge"
-msgstr ""
+msgstr "快進å¼(Fast-forward)åˆä½µ"
msgid "ProjectSettings|Fast-forward merges only."
-msgstr ""
+msgstr "僅快進å¼ï¼ˆFast-forward)åˆä½µã€‚"
msgid "ProjectSettings|Flexible tool to collaboratively develop ideas and plan work in this project."
-msgstr ""
+msgstr "用於在此專案中å”作開發想法和計劃工作的éˆæ´»å·¥å…·ã€‚"
msgid "ProjectSettings|Forks"
-msgstr ""
+msgstr "分å‰"
msgid "ProjectSettings|Git Large File Storage (LFS)"
-msgstr ""
+msgstr "Git大文件儲存 (LFS)"
msgid "ProjectSettings|Global"
-msgstr ""
+msgstr "全域"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
-msgstr ""
+msgstr "çªå‡ºé¡¯ç¤ºéš±è—çš„ unicode 字元的用法。這些å°å¾žå³åˆ°å·¦çš„語言無害,但也å¯ç”¨æ–¼æ½›åœ¨çš„æ¼æ´žåˆ©ç”¨ã€‚"
msgid "ProjectSettings|Housekeeping, export, archive, change path, transfer, and delete."
-msgstr ""
+msgstr "例行維護ã€åŒ¯å‡ºã€æ­¸æª”ã€æ›´æ”¹è·¯å¾‘ã€å‚³è¼¸å’Œåˆªé™¤ã€‚"
msgid "ProjectSettings|How do they differ?"
-msgstr ""
+msgstr "它們有何ä¸åŒï¼Ÿ"
msgid "ProjectSettings|If merge trains are enabled, merging is only possible if the branch can be rebased without conflicts."
-msgstr ""
+msgstr "如果啟用了åˆä½µä½‡åˆ—,則åªæœ‰åœ¨å¯ä»¥é‡æ–°è¨­å®šåˆ†æ”¯è€Œä¸ç™¼ç”Ÿè¡çªçš„情æ³ä¸‹æ‰èƒ½é€²è¡Œåˆä½µã€‚"
msgid "ProjectSettings|Internal"
-msgstr ""
+msgstr "內部"
msgid "ProjectSettings|Introduces the risk of merging changes that do not pass the pipeline."
-msgstr ""
+msgstr "未通éŽåˆä½µçš„已變更æµæ°´ç·šå¯èƒ½æœƒå°Žè‡³é¢¨éšªã€‚"
msgid "ProjectSettings|Issues"
-msgstr ""
+msgstr "議題"
msgid "ProjectSettings|LFS objects from this repository are available to forks. %{linkStart}How do I remove them?%{linkEnd}"
-msgstr ""
+msgstr "此倉庫中的 LFS å°è±¡å¯ä¾›åˆ†å‰ã€‚ %{linkStart}我如何移除它們?%{linkEnd}"
msgid "ProjectSettings|Leave empty to use default template."
-msgstr ""
+msgstr "留空使用é è¨­ç¯„本。"
msgid "ProjectSettings|Manage who can see the project in the public access directory."
-msgstr ""
+msgstr "管ç†èª°å¯ä»¥åœ¨å…¬å…±å­˜å–目錄中看到這個專案。"
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
-msgstr ""
+msgstr "管ç†å¤§åž‹æ–‡ä»¶ï¼Œä¾‹å¦‚音頻ã€è¦–頻和圖形文件。"
msgid "ProjectSettings|Maximum %{maxLength} characters."
-msgstr ""
+msgstr "最多 %{maxLength} 個字符。"
msgid "ProjectSettings|Merge checks"
-msgstr ""
+msgstr "åˆä½µæª¢æŸ¥"
msgid "ProjectSettings|Merge commit"
-msgstr ""
+msgstr "åˆä½µæ交"
msgid "ProjectSettings|Merge commit message template"
-msgstr ""
+msgstr "åˆä½µæ交消æ¯ç¯„本"
msgid "ProjectSettings|Merge commit with semi-linear history"
-msgstr ""
+msgstr "åˆä½µæ交與åŠç·šæ€§æ­·å²è¨˜éŒ„"
msgid "ProjectSettings|Merge method"
-msgstr ""
+msgstr "åˆä½µæ–¹æ³•"
msgid "ProjectSettings|Merge options"
-msgstr ""
+msgstr "åˆä½µé¸é …"
msgid "ProjectSettings|Merge requests"
-msgstr ""
+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 ""
+msgstr "已核准的åˆä½µè«‹æ±‚已排入佇列,æµæ°´ç·šåœ¨åˆä½µå‰é©—證來æºå’Œç›®æ¨™åˆ†æ”¯çš„åˆä½µçµæžœã€‚ %{link_start}什麼是åˆä½µä½‡åˆ—?%{link_end}"
msgid "ProjectSettings|Merge requests can't be merged if the latest pipeline did not succeed or is still running."
-msgstr ""
+msgstr "如果最新æµæ°´ç·šæœªæˆåŠŸæˆ–ä»åœ¨åŸ·è¡Œï¼Œå‰‡ç„¡æ³•åˆä½µåˆä½µè«‹æ±‚。"
msgid "ProjectSettings|Merge suggestions"
-msgstr ""
+msgstr "åˆä½µå»ºè­°"
msgid "ProjectSettings|Merging is only allowed when the source branch is up-to-date with its target."
-msgstr ""
+msgstr "åªæœ‰ç•¶ä¾†æºåˆ†æ”¯èˆ‡å…¶ç›®æ¨™æ˜¯æœ€æ–°çš„時候,æ‰å…許åˆä½µã€‚"
msgid "ProjectSettings|No merge commits are created."
-msgstr ""
+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 ""
+msgstr "注æ„:當專案是公共的並且容器映åƒåº«è¨­å®šç‚ºã€Œ%{access_level_description}ã€æ™‚,容器映åƒåº«å§‹çµ‚å¯è¦‹"
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
-msgstr ""
+msgstr "åªæœ‰å·²ç°½ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ç‰ˆæœ¬åº«ã€‚"
msgid "ProjectSettings|Operations"
-msgstr ""
+msgstr "維é‹"
msgid "ProjectSettings|Override user notification preferences for all project members."
-msgstr ""
+msgstr "覆蓋所有專案æˆå“¡çš„使用者通知å好é¸é …。"
msgid "ProjectSettings|Package registry"
-msgstr ""
+msgstr "軟體套件註冊表"
msgid "ProjectSettings|Packages"
-msgstr ""
+msgstr "軟體套件"
msgid "ProjectSettings|Pages"
-msgstr ""
+msgstr "Pages"
msgid "ProjectSettings|Pages for project documentation."
-msgstr ""
+msgstr "專案Pages的文件。"
msgid "ProjectSettings|Pipelines must succeed"
-msgstr ""
+msgstr "æµæ°´ç·šå¿…é ˆæˆåŠŸ"
msgid "ProjectSettings|Prevents direct linking to potentially sensitive media files"
-msgstr ""
+msgstr "防止直接éˆæŽ¥åˆ°å¯èƒ½æ•æ„Ÿçš„媒體檔案"
msgid "ProjectSettings|Private"
-msgstr ""
+msgstr "ç§æœ‰çš„"
msgid "ProjectSettings|Project visibility"
-msgstr ""
+msgstr "專案å¯è¦‹æ€§"
msgid "ProjectSettings|Public"
-msgstr ""
+msgstr "公開的"
msgid "ProjectSettings|Repository"
-msgstr ""
+msgstr "版本庫"
msgid "ProjectSettings|Require"
-msgstr ""
+msgstr "å¿…é ˆ"
msgid "ProjectSettings|Require an associated issue from Jira"
-msgstr ""
+msgstr "需è¦ä¾†è‡ª Jira 的相關議題"
msgid "ProjectSettings|Require authentication to view media files"
-msgstr ""
+msgstr "需è¦èº«ä»½é©—è­‰æ‰èƒ½æŸ¥çœ‹åª’體檔案"
msgid "ProjectSettings|Requirements"
-msgstr ""
+msgstr "需求"
msgid "ProjectSettings|Requirements management system."
-msgstr ""
+msgstr "需求管ç†ç³»çµ±ã€‚"
msgid "ProjectSettings|Search for topic"
-msgstr ""
+msgstr "æœå°‹ä¸»é¡Œ"
msgid "ProjectSettings|Security & Compliance"
-msgstr ""
+msgstr "安全與åˆè¦"
msgid "ProjectSettings|Security & Compliance for this project"
-msgstr ""
+msgstr "此專案的安全與åˆè¦"
msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
-msgstr ""
+msgstr "在åˆä½µè«‹æ±‚中設定此é¸é …çš„é è¨­è¡Œç‚ºã€‚å°æ­¤çš„更改也é©ç”¨æ–¼ç¾æœ‰çš„åˆä½µè«‹æ±‚。"
msgid "ProjectSettings|Share code with others outside the project."
-msgstr ""
+msgstr "與專案外的其它人共享程å¼ç¢¼ã€‚"
msgid "ProjectSettings|Show default award emojis"
-msgstr ""
+msgstr "顯示é è¨­çš„çŽå‹µè¡¨æƒ…符號"
msgid "ProjectSettings|Show link to create or view a merge request when pushing from the command line"
-msgstr ""
+msgstr "從指令行推é€æ™‚顯示用於建立或查看åˆä½µè«‹æ±‚的連çµ"
msgid "ProjectSettings|Skipped pipelines are considered successful"
-msgstr ""
+msgstr "被跳éŽçš„æµæ°´ç·šè¦–為æˆåŠŸ"
msgid "ProjectSettings|Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "ProjectSettings|Squash commit message template"
-msgstr ""
+msgstr "壓縮æ交訊æ¯æ¨¡æ¿"
msgid "ProjectSettings|Squash commits when merging"
-msgstr ""
+msgstr "åˆä½µæ™‚壓縮æ交"
msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
-msgstr ""
+msgstr "總是執行壓縮。複é¸æ¡†æ˜¯å¯è¦‹çš„並處於é¸å–狀態,使用者無法更改它。"
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
-msgstr ""
+msgstr "æ°¸é ä¸æœƒåŸ·è¡Œå£“縮,且該複é¸æ¡†æ˜¯éš±è—的。"
msgid "ProjectSettings|Submit changes to be merged upstream."
-msgstr ""
+msgstr "æ交è¦åˆä½µåˆ°ä¸Šæ¸¸çš„更改。"
msgid "ProjectSettings|Target project"
-msgstr ""
+msgstr "目標專案"
msgid "ProjectSettings|The commit message used when applying merge request suggestions."
-msgstr ""
+msgstr "套用åˆä½µè«‹æ±‚建議時使用的æ交消æ¯ã€‚"
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
-msgstr ""
+msgstr "åˆä½µæ™‚使用的æ交訊æ¯ï¼Œå¦‚æžœåˆä½µæ–¹æ³•å»ºç«‹äº†åˆä½µæ交。"
msgid "ProjectSettings|The commit message used when squashing commits."
-msgstr ""
+msgstr "壓縮æ交時使用的æ交訊æ¯ã€‚"
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
-msgstr ""
+msgstr "在此分å‰å°ˆæ¡ˆä¸­å»ºç«‹çš„åˆä½µè«‹æ±‚çš„é è¨­ç›®æ¨™å°ˆæ¡ˆã€‚"
msgid "ProjectSettings|The default template will be applied on save."
-msgstr ""
+msgstr "ä¿å­˜æ™‚將套用é è¨­ç¯„本。"
msgid "ProjectSettings|These checks must pass before merge requests can be merged."
-msgstr ""
+msgstr "必須通éŽé€™äº›æª¢æŸ¥æ‰èƒ½åˆä½µåˆä½µè«‹æ±‚。"
msgid "ProjectSettings|This project"
-msgstr ""
+msgstr "該專案"
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
-msgstr ""
+msgstr "此設定已套用於伺æœå™¨ç´šåˆ¥ï¼Œå¯ç”±ç®¡ç†å“¡ä¿®æ”¹ã€‚"
msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
-msgstr ""
+msgstr "此設定套用於伺æœå™¨ç´šåˆ¥ï¼Œä½†å·²è¢«è©²å°ˆæ¡ˆè¦†å¯«ã€‚"
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
-msgstr ""
+msgstr "此設定將套用於所有專案,除éžè¢«ç®¡ç†å“¡è¦†è“‹ã€‚"
msgid "ProjectSettings|Transfer project"
-msgstr ""
+msgstr "轉移專案"
msgid "ProjectSettings|Upstream project"
-msgstr ""
+msgstr "上游專案"
msgid "ProjectSettings|Used for every new merge request."
-msgstr ""
+msgstr "用於æ¯å€‹æ–°çš„åˆä½µè«‹æ±‚。"
msgid "ProjectSettings|Users can copy the repository to a new project."
-msgstr ""
+msgstr "使用者å¯ä»¥å°‡ç‰ˆæœ¬åº«è¤‡è£½åˆ°æ–°å°ˆæ¡ˆã€‚"
msgid "ProjectSettings|Users can only push commits to this repository if the committer email is one of their own verified emails."
-msgstr ""
+msgstr "如果æ交者電å­éƒµä»¶æ˜¯ä»–們自己經éŽé©—證的電å­éƒµä»¶ä¹‹ä¸€ï¼Œä½¿ç”¨è€…åªèƒ½å°‡æ交推é€åˆ°æ­¤å­˜å„²åº«ã€‚"
msgid "ProjectSettings|Users can request access"
-msgstr ""
+msgstr "使用者å¯ä»¥è«‹æ±‚å­˜å–"
msgid "ProjectSettings|View and edit files in this project."
-msgstr ""
+msgstr "查看和編輯此專案中的文件。"
msgid "ProjectSettings|View and edit files in this project. Non-project members have only read access."
-msgstr ""
+msgstr "查看和編輯此專案中的文件。éžå°ˆæ¡ˆæˆå“¡åªæœ‰è®€å–權é™ã€‚"
msgid "ProjectSettings|View project analytics."
-msgstr ""
+msgstr "查看專案分æžã€‚"
msgid "ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project."
-msgstr ""
+msgstr "此分å‰çš„å¯è¦‹æ€§é¸é …å—來æºå°ˆæ¡ˆç•¶å‰å¯è¦‹æ€§çš„é™åˆ¶ã€‚"
msgid "ProjectSettings|Visualize the project's performance metrics."
-msgstr ""
+msgstr "視覺化專案的性能指標。"
msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
-msgstr ""
+msgstr "關於潛在的ä¸éœ€è¦çš„字元警告"
msgid "ProjectSettings|What are badges?"
-msgstr ""
+msgstr "什麼是徽章?"
msgid "ProjectSettings|What are merge trains?"
-msgstr ""
+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 ""
+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 ""
+msgstr "當åŠç·šæ€§åˆä½µä¸å¯èƒ½æ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸº(rebase)。"
msgid "ProjectSettings|When there is a merge conflict, the user is given the option to rebase."
-msgstr ""
+msgstr "當出ç¾åˆä½µè¡çªæ™‚,使用者å¯ä»¥é¸æ“‡è®ŠåŸºï¼ˆrebase)。"
msgid "ProjectSettings|Wiki"
-msgstr ""
+msgstr "Wiki"
msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab."
-msgstr ""
+msgstr "使用GitLab Pages,您å¯ä»¥åœ¨GitLab上託管éœæ…‹ç¶²ç«™ã€‚"
msgid "ProjectTemplates|.NET Core"
-msgstr ""
+msgstr ".NET Core"
msgid "ProjectTemplates|Android"
-msgstr ""
+msgstr "Android"
msgid "ProjectTemplates|GitLab Cluster Management"
-msgstr ""
+msgstr "GitLabå¢é›†ç®¡ç†"
msgid "ProjectTemplates|Gitpod/Spring Petclinic"
-msgstr ""
+msgstr "Gitpod/Spring Petclinic"
msgid "ProjectTemplates|Go Micro"
-msgstr ""
+msgstr "Go Micro"
msgid "ProjectTemplates|HIPAA Audit Protocol"
-msgstr ""
+msgstr "HIPAA審計å”è­°"
msgid "ProjectTemplates|Jsonnet for Dynamic Child Pipelines"
-msgstr ""
+msgstr "用於動態å­æµæ°´ç·šçš„ Jsonnet"
msgid "ProjectTemplates|Kotlin Native for Linux"
-msgstr ""
+msgstr "Linuxçš„Kotlin Native"
msgid "ProjectTemplates|Netlify/GitBook"
-msgstr ""
+msgstr "Netlify/GitBook"
msgid "ProjectTemplates|Netlify/Hexo"
-msgstr ""
+msgstr "Nettify/Hexo"
msgid "ProjectTemplates|Netlify/Hugo"
-msgstr ""
+msgstr "Netrify/Hugo"
msgid "ProjectTemplates|Netlify/Jekyll"
-msgstr ""
+msgstr "Nettlity/Jekyll"
msgid "ProjectTemplates|Netlify/Plain HTML"
-msgstr ""
+msgstr "Netrify/Plain HTML"
msgid "ProjectTemplates|NodeJS Express"
-msgstr ""
+msgstr "NodeJS Express"
msgid "ProjectTemplates|Pages/Gatsby"
-msgstr ""
+msgstr "Pages/Gatsby"
msgid "ProjectTemplates|Pages/GitBook"
-msgstr ""
+msgstr "Pages/GitBook"
msgid "ProjectTemplates|Pages/Hexo"
-msgstr ""
+msgstr "Pages/hexo"
msgid "ProjectTemplates|Pages/Hugo"
-msgstr ""
+msgstr "Pages/Hugo"
msgid "ProjectTemplates|Pages/Jekyll"
-msgstr ""
+msgstr "Pages/Jekyll"
msgid "ProjectTemplates|Pages/Middleman"
-msgstr ""
+msgstr "Pages/Middleman"
msgid "ProjectTemplates|Pages/Pelican"
-msgstr ""
+msgstr "Pages/Pelican"
msgid "ProjectTemplates|Pages/Plain HTML"
-msgstr ""
+msgstr "Pages/Plain HTML"
msgid "ProjectTemplates|Ruby on Rails"
-msgstr ""
+msgstr "Ruby on Rails"
msgid "ProjectTemplates|SalesforceDX"
-msgstr ""
+msgstr "SalesforceDX"
msgid "ProjectTemplates|Sample GitLab Project"
-msgstr ""
+msgstr "GitLab示例專案"
msgid "ProjectTemplates|Serverless Framework/JS"
-msgstr ""
+msgstr "Serverless Framework/JS"
msgid "ProjectTemplates|Spring"
-msgstr ""
+msgstr "Spring"
msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
-msgstr ""
+msgstr "Tencent Serverless 框架/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
-msgstr ""
+msgstr "iOS (Swift)"
msgid "ProjectView|Activity"
-msgstr ""
+msgstr "å‹•æ…‹"
msgid "ProjectView|Files and Readme (default)"
-msgstr ""
+msgstr "文件和 Readme(é è¨­ï¼‰"
msgid "ProjectView|Readme"
-msgstr ""
+msgstr "Readme"
msgid "Projects"
-msgstr ""
+msgstr "專案"
msgid "Projects (%{count})"
-msgstr ""
+msgstr "專案 (%{count})"
msgid "Projects API"
-msgstr ""
+msgstr "專案 API"
msgid "Projects Successfully Retrieved"
-msgstr ""
+msgstr "專案æˆåŠŸè®€å–"
msgid "Projects are graded based on the highest severity vulnerability present"
-msgstr ""
+msgstr "專案ä¾æ‰€åŒ…å«æœ€é«˜å±éšªç¨‹åº¦å®‰å…¨æ¼æ´žåˆ†ç´šã€‚"
msgid "Projects are organized into groups"
-msgstr ""
+msgstr "專案被組織æˆç¾¤çµ„"
msgid "Projects are where you store your code, access issues, wiki and other features of GitLab."
-msgstr ""
+msgstr "專案是您儲存您的程å¼ç¢¼ã€å­˜å–è­°é¡Œã€wiki 和其它功能的地方。"
msgid "Projects contributed to"
-msgstr ""
+msgstr "è²¢ç»çš„專案"
msgid "Projects help you organize your work. They contain your file repository, issues, merge requests, and so much more."
-msgstr ""
+msgstr "專案å¯å¹«åŠ©æ‚¨çµ„織工作。它們包å«æ‚¨çš„文件倉庫ã€è­°é¡Œã€åˆä½µè«‹æ±‚等等。"
msgid "Projects in this group can use Git LFS"
-msgstr ""
+msgstr "該群組內專案å¯ä»¥ä½¿ç”¨ Git LFS"
msgid "Projects shared with %{group_name}"
-msgstr ""
+msgstr "與 %{group_name} 共享的專案"
msgid "Projects that can be accessed"
-msgstr ""
+msgstr "å¯ä»¥å­˜å–的專案"
msgid "Projects to index"
-msgstr ""
+msgstr "è¦ç´¢å¼•çš„專案"
msgid "Projects with critical vulnerabilities"
-msgstr ""
+msgstr "具有嚴é‡æ¼æ´žçš„專案"
msgid "Projects with high or unknown vulnerabilities"
-msgstr ""
+msgstr "具有高å±æˆ–未知æ¼æ´žçš„專案"
msgid "Projects with low vulnerabilities"
-msgstr ""
+msgstr "具有低風險æ¼æ´žçš„專案"
msgid "Projects with medium vulnerabilities"
-msgstr ""
+msgstr "具有中風險æ¼æ´žçš„專案"
msgid "Projects with no vulnerabilities and security scanning enabled"
-msgstr ""
+msgstr "未啟用æ¼æ´žå’Œå®‰å…¨æŽƒæ的專案"
msgid "Projects with this topic"
-msgstr ""
+msgstr "與此主題相關的專案"
msgid "Projects with write access"
-msgstr ""
+msgstr "具有寫入權é™çš„專案"
msgid "ProjectsDropdown|Frequently visited"
-msgstr ""
+msgstr "經常存å–"
msgid "ProjectsDropdown|Loading projects"
-msgstr ""
+msgstr "載入專案中"
msgid "ProjectsDropdown|Projects you visit often will appear here"
-msgstr ""
+msgstr "您經常存å–的專案將出ç¾åœ¨é€™è£¡"
msgid "ProjectsDropdown|Search your projects"
-msgstr ""
+msgstr "æœå°‹æ‚¨çš„專案"
msgid "ProjectsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "發生內部錯誤。"
msgid "ProjectsDropdown|Sorry, no projects matched your search"
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæœªæœå°‹åˆ°ç¬¦åˆæ¢ä»¶çš„專案"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+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 "å…許您立å³è¤‡è£½é€™å€‹å°ˆæ¡ˆçš„版本庫。如果您計劃推é€ä¸€å€‹ç¾æœ‰çš„版本庫,請跳éŽé€™å€‹æ­¥é©Ÿã€‚"
msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "分æžæºç¨‹å¼ç¢¼æŸ¥æ‰¾å·²çŸ¥å®‰å…¨æ¼æ´ž."
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
-msgstr ""
+msgstr "將外部版本庫連接到GitLab CI/CD"
msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
-msgstr ""
+msgstr "è¯çµ¡ç®¡ç†å“¡å•Ÿç”¨åŒ¯å…¥å°ˆæ¡ˆçš„é¸é …。"
msgid "ProjectsNew|Create"
-msgstr ""
+msgstr "建立"
msgid "ProjectsNew|Create a blank project to store your files, plan your work, and collaborate on code, among other things."
-msgstr ""
+msgstr "建立一個空白專案來存放您的文件,è¦åŠƒæ‚¨çš„工作,並在程å¼ç¢¼ç­‰æ–¹é¢é€²è¡Œå”åŒåˆä½œã€‚"
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
-msgstr ""
+msgstr "建立一個é å…ˆå…·å‚™äº†å¿…è¦æ–‡ä»¶çš„專案,以幫助您快速入門。"
msgid "ProjectsNew|Create blank project"
-msgstr ""
+msgstr "建立空白專案"
msgid "ProjectsNew|Create from template"
-msgstr ""
+msgstr "從範本建立"
msgid "ProjectsNew|Create new project"
-msgstr ""
+msgstr "建立新專案"
msgid "ProjectsNew|Description format"
-msgstr ""
+msgstr "æè¿°æ ¼å¼"
msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "啟用éœæ…‹æ‡‰ç”¨å®‰å…¨æ¸¬è©¦ (SAST)"
msgid "ProjectsNew|Import"
-msgstr ""
+msgstr "匯入"
msgid "ProjectsNew|Import project"
-msgstr ""
+msgstr "匯入專案"
msgid "ProjectsNew|Include a Getting Started README"
-msgstr ""
+msgstr "包å«ä¸€å€‹README文件"
msgid "ProjectsNew|Initialize repository with a README"
-msgstr ""
+msgstr "使用自述文件åˆå§‹åŒ–版本庫"
msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
-msgstr ""
+msgstr "從外部來æºï¼ˆå¦‚ GitHubã€Bitbucket 或 GitLab 的其他實例)é·ç§»è³‡æ–™ã€‚"
msgid "ProjectsNew|No import options available"
-msgstr ""
+msgstr "沒有å¯ç”¨çš„匯入é¸é …"
msgid "ProjectsNew|Pick a group or namespace"
-msgstr ""
+msgstr "é¸æ“‡ç¾¤çµ„或命å空間"
msgid "ProjectsNew|Pick a group or namespace where you want to create this project."
-msgstr ""
+msgstr "é¸æ“‡è¦åœ¨å…¶ä¸­å»ºç«‹æ­¤å°ˆæ¡ˆçš„群組或命å空間。"
msgid "ProjectsNew|Project Configuration"
-msgstr ""
+msgstr "專案設定"
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
-msgstr ""
+msgstr "專案æè¿°%{tag_start}(å¯é¸)%{tag_end}"
msgid "ProjectsNew|Recommended if you're new to GitLab"
-msgstr ""
+msgstr "如果您是 GitLab 新手,建議使用"
msgid "ProjectsNew|Run CI/CD for external repository"
-msgstr ""
+msgstr "為外部版本庫執行CI/CD"
msgid "ProjectsNew|Visibility Level"
-msgstr ""
+msgstr "å¯è¦‹æ€§ç´šåˆ¥"
msgid "ProjectsNew|Want to organize several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
-msgstr ""
+msgstr "想在åŒä¸€å€‹å‘½å空間下組織多個ä¾è³´å°ˆæ¡ˆï¼Ÿ %{link_start}建立一個群組。%{link_end}"
msgid "PrometheusAlerts|exceeded"
-msgstr ""
+msgstr "超出"
msgid "PrometheusAlerts|is equal to"
-msgstr ""
+msgstr "等於"
msgid "PrometheusAlerts|is less than"
-msgstr ""
+msgstr "å°æ–¼"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
-msgstr ""
+msgstr "找到%{exporters} åŠ %{metrics}"
msgid "PrometheusService|Active"
-msgstr ""
+msgstr "啟用"
msgid "PrometheusService|Auto configuration settings are used unless you override their values here."
-msgstr ""
+msgstr "自動設定將被使用,除éžæ‚¨åœ¨é€™è£¡è¦†å¯«ä»–們的值。"
msgid "PrometheusService|Common metrics"
-msgstr ""
+msgstr "通用指標"
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
-msgstr ""
+msgstr "通用指標會根據套用的匯出工具指標庫自動監控。"
msgid "PrometheusService|Configure GitLab to query a Prometheus installed in one of your clusters."
-msgstr ""
+msgstr "設定 GitLab 以查詢安è£åœ¨æ‚¨çš„å¢é›†ä¸­çš„ Prometheus。"
msgid "PrometheusService|Custom metrics"
-msgstr ""
+msgstr "自訂指標"
msgid "PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope \"*\" OR a manually configured Prometheus to be available."
-msgstr ""
+msgstr "自訂指標è¦æ±‚Prometheus安è£åœ¨å…·æœ‰ç’°å¢ƒç¯„åœã€Œ*ã€çš„群集上,或者手動設定的Prometheuså¯ç”¨ã€‚"
msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
-msgstr ""
+msgstr "使用上é¢ä»»ä¸€é¸é …以啟用 Prometheus 來定義自訂度é‡æ¨™æº–,"
msgid "PrometheusService|Finding and configuring metrics..."
-msgstr ""
+msgstr "查找和設定指標..."
msgid "PrometheusService|Finding custom metrics..."
-msgstr ""
+msgstr "查找自訂指標..."
msgid "PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com"
-msgstr ""
+msgstr "IAP_CLIENT_ID.apps.googleusercontent.com"
msgid "PrometheusService|Manage clusters"
-msgstr ""
+msgstr "管ç†å¢é›†"
msgid "PrometheusService|Manual configuration"
-msgstr ""
+msgstr "手動é…ç½®"
msgid "PrometheusService|Metrics"
-msgstr ""
+msgstr "指標"
msgid "PrometheusService|Missing environment variable"
-msgstr ""
+msgstr "無環境變數"
msgid "PrometheusService|Monitor application health with Prometheus metrics and dashboards"
-msgstr ""
+msgstr "使用 Prometheus 指標和儀表æ¿ç›£æŽ§æ‡‰ç”¨ç¨‹å¼åŸ·è¡Œç‹€æ³"
msgid "PrometheusService|More information"
-msgstr ""
+msgstr "更多的訊æ¯"
msgid "PrometheusService|New metric"
-msgstr ""
+msgstr "新建指標"
msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
-msgstr ""
+msgstr "未找到%{docsUrlStart}通用指標%{docsUrlEnd}"
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
-msgstr ""
+msgstr "尚未建立自訂指標。使用上é¢çš„按鈕建立一個"
msgid "PrometheusService|Prometheus cluster integration"
-msgstr ""
+msgstr "Prometheuså¢é›†æ•´åˆ"
msgid "PrometheusService|Select this checkbox to override the auto configuration settings with your own settings."
-msgstr ""
+msgstr "é¸ä¸­æ­¤å¾©é¸æ¡†å¯ä½¿ç”¨æ‚¨è‡ªå·±çš„設定覆蓋自動設定。"
msgid "PrometheusService|The ID of the IAP-secured resource."
-msgstr ""
+msgstr "IAP 安全資æºçš„ ID。"
msgid "PrometheusService|The Prometheus API base URL."
-msgstr ""
+msgstr "Prometheus API 基本 URL。"
msgid "PrometheusService|The contents of the credentials.json file of your service account."
-msgstr ""
+msgstr "您æœå‹™å¸³è™Ÿçš„credentials.json文件的內容。"
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
-msgstr ""
+msgstr "在首次部署到環境之後, 這些指標æ‰æœƒè¢«ç›£æŽ§"
msgid "PrometheusService|To use a Prometheus installed on a cluster, deactivate the manual configuration."
-msgstr ""
+msgstr "è¦ä½¿ç”¨å®‰è£åœ¨å¢é›†ä¸Šçš„ Prometheus,請åœç”¨æ‰‹å‹•è¨­å®šã€‚"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
-msgstr ""
+msgstr "等待首次部署到環境以查找常用指標"
msgid "PrometheusService|You have a cluster with the Prometheus integration enabled."
-msgstr ""
+msgstr "您有一個啟用了 Prometheus æ•´åˆçš„å¢é›†ã€‚"
msgid "PrometheusService|https://prometheus.example.com/"
-msgstr ""
+msgstr "https://prometheus.example.com/"
msgid "PrometheusService|{ \"type\": \"service_account\", \"project_id\": ... }"
-msgstr ""
+msgstr "{ \"type\": \"service_account\", \"project_id\": ... }"
msgid "Promote"
-msgstr ""
+msgstr "æå‡"
msgid "Promote issue to an epic"
-msgstr ""
+msgstr "將議題æå‡ç‚ºå²è©©"
msgid "Promote issue to incident"
-msgstr ""
+msgstr "將議題æå‡ç‚ºäº‹ä»¶"
msgid "Promote to epic"
-msgstr ""
+msgstr "æå‡åˆ°å²è©©"
msgid "Promote to group label"
-msgstr ""
+msgstr "å‡ç´šåˆ°ç¾¤çµ„標記"
msgid "PromoteMilestone|Only project milestones can be promoted."
-msgstr ""
+msgstr "åªèƒ½å‡ç´šå°ˆæ¡ˆé‡Œç¨‹ç¢‘。"
msgid "PromoteMilestone|Project does not belong to a group."
-msgstr ""
+msgstr "專案ä¸å±¬æ–¼ä»»ä½•ä¸€å€‹ç¾¤çµ„。"
msgid "PromoteMilestone|Promotion failed - %{message}"
-msgstr ""
+msgstr "å‡ç´šå¤±æ•— - %{message}"
msgid "Promoted issue to an epic."
-msgstr ""
+msgstr "將議題å‡ç´šç‚ºå²è©©."
msgid "Promotes issue to incident"
-msgstr ""
+msgstr "將議題æå‡ç‚ºäº‹ä»¶"
msgid "Promotion is not supported."
-msgstr ""
+msgstr "ä¸æ”¯æ´æå‡ã€‚"
msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
-msgstr ""
+msgstr "加入 %{link_start} æ述範本 %{link_end} 以幫助您的貢ç»è€…有效地交æµï¼"
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "加入群組 Webhooks å’Œ GitLab ä¼æ¥­ç‰ˆã€‚"
msgid "Promotions|Better Protected Branches"
-msgstr ""
+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 "燃盡圖是里程碑完æˆé€²åº¦çš„視覺呈ç¾ã€‚通éŽç‡ƒç›¡åœ–,您å¯ä»¥é¦¬ä¸Šç›´è§€äº†è§£å°æ‡‰çš„里程碑的完æˆé€²åº¦ã€‚沒有燃盡圖的話,您需è¦è‡ªå·±å¾žé‡Œç¨‹ç¢‘æœé›†è³‡æ–™ä¾†è£½ä½œè¡¨é”åŒæ¨£å«ç¾©çš„進度圖。"
msgid "Promotions|Buy EE"
-msgstr ""
+msgstr "購買ä¼æ¥­ç‰ˆ"
msgid "Promotions|Buy GitLab Enterprise Edition"
-msgstr ""
+msgstr "購買GitLabä¼æ¥­ç‰ˆ"
msgid "Promotions|Configure Service Desk"
-msgstr ""
+msgstr "æœå‹™å°è¨­å®š"
msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
-msgstr ""
+msgstr "è«‹è¯çµ¡%{namespace_name}群組的所有者來å‡ç´šè¨ˆåŠƒã€‚"
msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
-msgstr ""
+msgstr "è¯çµ¡æ‰€æœ‰è€…%{link_start}%{owner_name}%{link_end}以å‡ç´šè¨ˆåŠƒã€‚"
msgid "Promotions|Contact your Administrator to upgrade your license."
-msgstr ""
+msgstr "請與管ç†å“¡è¯çµ¡ä»¥å‡ç´šæŽˆæ¬Šè¨±å¯ã€‚"
msgid "Promotions|Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr ""
+msgstr "æ述範本å…許您為專案的議題和åˆä½µè«‹æ±‚æ述文字定義特定上下文的範本。"
msgid "Promotions|Dismiss Service Desk promotion"
-msgstr ""
+msgstr "關閉æœå‹™å°æ示"
msgid "Promotions|Dismiss burndown charts promotion"
-msgstr ""
+msgstr "關閉燃盡圖æ示"
msgid "Promotions|Dismiss repository features promotion"
-msgstr ""
+msgstr "關閉版本庫功能促銷"
msgid "Promotions|Don't show me this again"
-msgstr ""
+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 ""
+msgstr "Epic 讓您å¯ä»¥é€šéŽè¿½è¹¤è·¨å°ˆæ¡ˆå’Œé‡Œç¨‹ç¢‘共享主題的å•é¡Œçµ„,更有效地管ç†å°ˆæ¡ˆçµ„åˆã€‚"
msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用GitLabä¼æ¥­ç‰ˆä¸­è­°é¡Œæ¬Šé‡å¸¶ä¾†çš„增強議題管ç†åŠŸèƒ½ã€‚"
msgid "Promotions|Improve merge requests and customer support with GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用GitLabä¼æ¥­ç‰ˆæ”¹é€²åˆä½µè«‹æ±‚和客戶支æ´ã€‚"
msgid "Promotions|Improve milestones with Burndown Charts."
-msgstr ""
+msgstr "通éŽç‡ƒç›¡åœ–增強里程碑。"
msgid "Promotions|Improve repositories with GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用GitLabä¼æ¥­ç‰ˆæå‡ç‰ˆæœ¬åº«ã€‚"
msgid "Promotions|Improve search with Advanced Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "使用進階æœå°‹å’ŒGitLabä¼æ¥­ç‰ˆæå‡æœå°‹èƒ½åŠ›ã€‚"
msgid "Promotions|Keep track of events in your project"
-msgstr ""
+msgstr "追蹤專案中的事件"
msgid "Promotions|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "Promotions|Merge request approvals"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚核准"
msgid "Promotions|Not now, thanks!"
-msgstr ""
+msgstr "暫時ä¸ç”¨ï¼Œè¬è¬ï¼"
msgid "Promotions|Push Rules"
-msgstr ""
+msgstr "推é€è¦å‰‡"
msgid "Promotions|Push Rules are defined per project so you can have different rules applied to different projects depends on your needs."
-msgstr ""
+msgstr "推é€è¦å‰‡æ˜¯ä¾æ¯å€‹å°ˆæ¡ˆå®šç¾©çš„,因此您å¯ä»¥æ ¹æ“šæ‚¨çš„需è¦ï¼Œå°ä¸åŒçš„專案é©ç”¨ä¸åŒçš„è¦å‰‡ã€‚"
msgid "Promotions|Repository Mirroring"
-msgstr ""
+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 ""
+msgstr "版本庫é¡åƒæ˜¯ä¸€ç¨®å¾žå¤–部來æºé¡åƒç‰ˆæœ¬åº«çš„方法。它å¯ç”¨æ–¼é¡åƒç‰ˆæœ¬åº«ä¸­çš„所有分支ã€æ¨™ç±¤å’Œæ交。"
msgid "Promotions|See the other features in the %{subscription_link_start}Premium plan%{subscription_link_end}"
-msgstr ""
+msgstr "查看 %{subscription_link_start}專業版%{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 "設定必è¦çš„核准數é‡ä¸¦å®šç¾©å°ˆæ¡ˆä¸­æ¯å€‹åˆä½µè«‹æ±‚所需的核准者列表。"
msgid "Promotions|Start GitLab Ultimate trial"
-msgstr ""
+msgstr "啟動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 "進階æœå°‹æ˜¯ä¸€é …功能強大的æœå°‹æœå‹™ï¼Œå¯ä»¥ç¯€çœæ‚¨çš„時間。您ç¾åœ¨å¯ä»¥åœ¨å…¶å®ƒåœ˜éšŠä¸­æœå°‹å¯ä»¥å¹«åŠ©æ‚¨è‡ªå·±çš„專案的程å¼ç¢¼ï¼Œè€Œä¸æ˜¯å»ºç«‹é‡è¤‡çš„程å¼ç¢¼å’Œæµªè²»æ™‚間。"
msgid "Promotions|This feature is locked."
-msgstr ""
+msgstr "此功能已鎖定"
msgid "Promotions|Try it for free"
-msgstr ""
+msgstr "å…費試用"
msgid "Promotions|Upgrade plan"
-msgstr ""
+msgstr "å‡ç´šè¨‚閱計劃"
msgid "Promotions|Upgrade your plan to activate Advanced Search."
-msgstr ""
+msgstr "å‡ç´šæ‚¨çš„方案以啟用進階æœå°‹ã€‚"
msgid "Promotions|Upgrade your plan to activate Audit Events."
-msgstr ""
+msgstr "å‡ç´šæ‚¨çš„方案以啟用審計事件。"
msgid "Promotions|Upgrade your plan to activate Group Webhooks."
-msgstr ""
+msgstr "å‡ç´šæ‚¨çš„方案以啟用群組Webhooks。"
msgid "Promotions|Upgrade your plan to improve merge requests."
-msgstr ""
+msgstr "å‡ç´šæ‚¨çš„方案以æå‡åˆä½µè«‹æ±‚功能。"
msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
-msgstr ""
+msgstr "å‡ç´šæ‚¨çš„訂閱計劃,以使用燃盡圖來增強里程碑。"
msgid "Promotions|Upgrade your plan to improve repositories."
-msgstr ""
+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 ""
+msgstr "Webhooks å…許您在例如推é€æ–°ç¨‹å¼ç¢¼æˆ–建立新議題時觸發 URL。您å¯ä»¥è¨­å®š webhook 來監è½ç‰¹å®šäº‹ä»¶ï¼Œä¾‹å¦‚推é€ã€è­°é¡Œæˆ–åˆä½µè«‹æ±‚。群組 webhook 將應用於群組中的所有專案,å…許您在整個群組中標準化 webhook 功能。"
msgid "Promotions|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Promotions|Weighting your issue"
-msgstr ""
+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 ""
+msgstr "當議題數目很多時,很難得到一個整體情æ³ã€‚ 通éŽçµ¦è­°é¡ŒåŠ å…¥æ¬Šé‡ï¼Œå¯ä»¥æ›´å¥½åœ°äº†è§£å·¥ä½œé‡ã€ æˆæœ¬ã€æ‰€éœ€æ™‚間或æ¯å€‹è­°é¡Œçš„價值,從而更好地進行管ç†ã€‚"
msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽé¸æ“‡è§’色(維護者ã€é–‹ç™¼è€…)以åŠæŸäº›ä½¿ç”¨è€…來é™åˆ¶å°å—ä¿è­·åˆ†æ”¯çš„å­˜å–。"
msgid "Promotions|description templates"
-msgstr ""
+msgstr "æ述範本"
msgid "Promotions|to help your contributors communicate effectively!"
-msgstr ""
+msgstr "幫助您的貢ç»è€…有效æºé€šï¼"
msgid "Prompt users to upload SSH keys"
-msgstr ""
+msgstr "æ示使用者上傳SSH金鑰"
msgid "Protect"
-msgstr ""
+msgstr "ä¿è­·"
msgid "Protect a tag"
-msgstr ""
+msgstr "ä¿è­·æ¨™ç±¤"
msgid "Protect variable"
-msgstr ""
+msgstr "ä¿è­·è®Šæ•¸"
msgid "Protected"
-msgstr ""
+msgstr "å—ä¿è­·"
msgid "Protected Branch"
-msgstr ""
+msgstr "å—ä¿è­·çš„分支"
msgid "Protected Branches"
-msgstr ""
+msgstr "å—ä¿è­·çš„分支"
msgid "Protected Environment"
-msgstr ""
+msgstr "å—ä¿è­·çš„環境"
msgid "Protected Paths: requests"
-msgstr ""
+msgstr "å—ä¿è­·çš„路徑: 請求"
msgid "Protected Tag"
-msgstr ""
+msgstr "å—ä¿è­·çš„標籤"
msgid "Protected Tags"
-msgstr ""
+msgstr "å—ä¿è­·çš„標籤"
msgid "Protected branches"
-msgstr ""
+msgstr "å—ä¿è­·çš„分支"
msgid "Protected environments"
-msgstr ""
+msgstr "å—ä¿è­·çš„環境"
msgid "Protected paths"
-msgstr ""
+msgstr "å—ä¿è­·çš„路徑"
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
-msgstr ""
+msgstr "æ”¯æ´ %{wildcards_link_start}è¬å…ƒå­—å…ƒ%{wildcards_link_end},例如 %{code_tag_start}*-stable%{code_tag_end} 或 %{code_tag_start}production/*%{code_tag_end}。"
msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
-msgstr ""
+msgstr "å…許所有具有推é€å­˜å–權é™çš„使用者%{tag_start}強制推é€%{tag_end}。"
msgid "ProtectedBranch|Allow all users with push access to force push."
-msgstr ""
+msgstr "å…許所有具有推é€å­˜å–權é™çš„使用者強制推é€ã€‚"
msgid "ProtectedBranch|Allowed to force push"
-msgstr ""
+msgstr "å…許強制推é€"
msgid "ProtectedBranch|Allowed to force push:"
-msgstr ""
+msgstr "å…許強制推é€ï¼š"
msgid "ProtectedBranch|Allowed to merge"
-msgstr ""
+msgstr "å…許åˆä½µ"
msgid "ProtectedBranch|Allowed to merge:"
-msgstr ""
+msgstr "å…許åˆä½µï¼š"
msgid "ProtectedBranch|Allowed to push"
-msgstr ""
+msgstr "å…許推é€"
msgid "ProtectedBranch|Allowed to push:"
-msgstr ""
+msgstr "å…許推é€ï¼š"
msgid "ProtectedBranch|Branch"
-msgstr ""
+msgstr "分支"
msgid "ProtectedBranch|Branch will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "分支å°é–‹ç™¼äººå“¡æ˜¯å¯å¯«å…¥çš„,您確定嗎?"
msgid "ProtectedBranch|Branch:"
-msgstr ""
+msgstr "分支:"
msgid "ProtectedBranch|By default, protected branches restrict who can modify the branch."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œå—ä¿è­·åˆ†æ”¯é™åˆ¶èª°å¯ä»¥ä¿®æ”¹åˆ†æ”¯ã€‚"
msgid "ProtectedBranch|Code owner approval"
-msgstr ""
+msgstr "程å¼ç¢¼æ‰€æœ‰è€…核准"
msgid "ProtectedBranch|Does not apply to users allowed to push. Optional sections are not enforced."
-msgstr ""
+msgstr "ä¸é©ç”¨æ–¼å…許推é€çš„使用者。ä¸å¼·åˆ¶åŸ·è¡Œå¯é¸éƒ¨åˆ†ã€‚"
msgid "ProtectedBranch|Keep stable branches secure and force developers to use merge requests."
-msgstr ""
+msgstr "ä¿æŒç©©å®šçš„分支安全並強制開發人員使用åˆä½µè«‹æ±‚。"
msgid "ProtectedBranch|Learn more."
-msgstr ""
+msgstr "了解更多。"
msgid "ProtectedBranch|Protect"
-msgstr ""
+msgstr "ä¿è­·"
msgid "ProtectedBranch|Protect a branch"
-msgstr ""
+msgstr "ä¿è­·åˆ†æ”¯"
msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
-msgstr ""
+msgstr "å—ä¿è­·åˆ†æ”¯ (%{protected_branches_count})"
msgid "ProtectedBranch|Protected branches"
-msgstr ""
+msgstr "å—ä¿è­·åˆ†æ”¯"
msgid "ProtectedBranch|Reject code pushes that change files listed in the CODEOWNERS file."
-msgstr ""
+msgstr "拒絕程å¼ç¢¼æŽ¨é€æ›´æ”¹ CODEOWNERS 文件中列出的文件。"
msgid "ProtectedBranch|Require approval from code owners:"
-msgstr ""
+msgstr "需è¦ç¨‹å¼ç¢¼æ‰€æœ‰è€…的核准:"
msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
-msgstr ""
+msgstr "ç›®å‰æ²’有å—ä¿è­·çš„分支,請使用上述表單來ä¿è­·åˆ†æ”¯ã€‚"
msgid "ProtectedBranch|Toggle allowed to force push"
-msgstr ""
+msgstr "切æ›å…許強制推é€"
msgid "ProtectedBranch|Toggle code owner approval"
-msgstr ""
+msgstr "切æ›ç¨‹å¼ç¢¼æ‰€æœ‰è€…的核准"
msgid "ProtectedBranch|Unprotect"
-msgstr ""
+msgstr "å–消ä¿è­·"
msgid "ProtectedBranch|Unprotect branch"
-msgstr ""
+msgstr "å–消ä¿è­·åˆ†æ”¯"
msgid "ProtectedBranch|What are protected branches?"
-msgstr ""
+msgstr "什麼是å—ä¿è­·çš„分支?"
msgid "ProtectedBranch|default"
-msgstr ""
+msgstr "é è¨­"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} å°‡å°é–‹ç™¼äººå“¡å¯å¯«å…¥ï¼Œç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
+
+msgid "ProtectedEnvironment|All environments specivied with the deployment tiers below are protected by a parent group. %{link_start}Learn More%{link_end}."
+msgstr "使用以下部署層級指定的所有環境å‡å—父群組ä¿è­·ã€‚ %{link_start}了解更多%{link_end}。"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "å…許部署"
+
+msgid "ProtectedEnvironment|Allowed to deploy to %{project} / %{environment}"
+msgstr "å…許部署到 %{project} / %{environment}"
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+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 projected."
+msgstr "該專案中沒有å—ä¿è­·çš„環境。"
msgid "ProtectedEnvironment|Only specified groups can execute deployments in protected environments."
-msgstr ""
+msgstr "åªæœ‰æŒ‡å®šçš„使用者æ‰èƒ½åœ¨å—ä¿è­·çš„環境中執行部署。"
msgid "ProtectedEnvironment|Only specified users can execute deployments in a protected environment."
-msgstr ""
+msgstr "åªæœ‰æŒ‡å®šçš„使用者æ‰èƒ½åœ¨å—ä¿è­·çš„環境中執行部署。"
+
+msgid "ProtectedEnvironment|Parent group"
+msgstr "父群組"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "ä¿è­·"
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "ä¿è­·éƒ¨ç½²ç’°å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "å—ä¿è­·çš„環境 (%{protected_environments_count})"
msgid "ProtectedEnvironment|Required approvals"
-msgstr ""
+msgstr "需è¦æ ¸å‡†"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç’°å¢ƒ"
msgid "ProtectedEnvironment|Select groups"
-msgstr ""
+msgstr "é¸æ“‡ç¾¤çµ„"
msgid "ProtectedEnvironment|Select users"
-msgstr ""
+msgstr "é¸æ“‡ä½¿ç”¨è€…"
msgid "ProtectedEnvironment|There are currently no protected environments. Protect an environment with this form."
-msgstr ""
+msgstr "當å‰æ²’有å—ä¿è­·çš„環境。使用該方å¼ä¿è­·ç’°å¢ƒã€‚"
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "å–消ä¿è­·"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "您的環境無法å—到ä¿è­·"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "您的環境已å—到ä¿è­·ã€‚"
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "您的環境沒有å—到ä¿è­·"
msgid "ProtectedTags|Unprotect tag"
-msgstr ""
+msgstr "å–消ä¿è­·æ¨™ç±¤"
msgid "ProtectedTags|default"
-msgstr ""
+msgstr "é è¨­"
msgid "ProtectedTag|By default, protected tags restrict who can modify the tag."
-msgstr ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œå—ä¿è­·çš„標籤é™åˆ¶èª°å¯ä»¥ä¿®æ”¹æ¨™ç±¤ã€‚"
msgid "ProtectedTag|Learn more."
-msgstr ""
+msgstr "了解更多。"
msgid "ProtectedTag|Limit access to creating and updating tags."
-msgstr ""
+msgstr "é™åˆ¶å»ºç«‹å’Œæ›´æ–°æ¨™ç±¤çš„å­˜å–。"
msgid "ProtectedTag|Protected tags"
-msgstr ""
+msgstr "å—ä¿è­·çš„標籤"
msgid "ProtectedTag|What are protected tags?"
-msgstr ""
+msgstr "什麼是å—ä¿è­·çš„標籤?"
msgid "ProtectedTag|default"
-msgstr ""
+msgstr "é è¨­"
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
-msgstr ""
+msgstr "æ示:%{linkStart}Auto DevOps%{linkEnd} 使用 Kubernetes å¢é›†ä¾†éƒ¨ç½²æ‚¨çš„程å¼ç¢¼ï¼"
msgid "Provide Feedback"
-msgstr ""
+msgstr "æ供回饋æ„見"
msgid "Provide a number our sales team can use to call you."
-msgstr ""
+msgstr "æ供一個我們銷售團隊å¯ä»¥çµ¦æ‚¨æ‰“電話的號碼。"
msgid "Provider"
-msgstr ""
+msgstr "æ供者"
msgid "Provision instructions"
-msgstr ""
+msgstr "æ供說明"
msgid "Provisioned by:"
-msgstr ""
+msgstr "æ供者:"
msgid "Proxy support for this API is not available currently"
-msgstr ""
+msgstr "æ­¤APIç›®å‰ä¸æ”¯æ´ä½¿ç”¨ä»£ç†"
msgid "Public"
-msgstr ""
+msgstr "公開"
msgid "Public - The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "公開 - 群組和任何公開專案å¯ä»¥é–‹æ”¾æŸ¥çœ‹ï¼Œç„¡éœ€èº«ä»½é©—證。"
msgid "Public - The project can be accessed without any authentication."
-msgstr ""
+msgstr "公開 - 無需任何身份驗證å³å¯å­˜å–該專案。"
msgid "Public Access Help"
-msgstr ""
+msgstr "公開存å–å”助"
msgid "Public deploy keys"
-msgstr ""
+msgstr "公共部署金鑰"
msgid "Public pipelines"
-msgstr ""
+msgstr "公開æµæ°´ç·š"
msgid "Public projects Minutes cost factor"
-msgstr ""
+msgstr "公開專案分é˜æˆæœ¬ä¿‚數"
msgid "Public projects are an easy way to allow everyone to have read-only access."
-msgstr ""
+msgstr "公開專案是使æ¯å€‹äººéƒ½èƒ½å¤ å”¯è®€å­˜å–的一種簡單方å¼ã€‚"
msgid "Publish to status page"
-msgstr ""
+msgstr "發布到狀態é "
msgid "Published"
-msgstr ""
+msgstr "已發布"
msgid "Published on status page"
-msgstr ""
+msgstr "已發布到狀態é "
msgid "Publishes this issue to the associated status page."
-msgstr ""
+msgstr "將此議題發布到相關的狀態é é¢ã€‚"
msgid "Pull"
-msgstr ""
+msgstr "æå–"
msgid "Pull requests from fork are not supported"
-msgstr ""
+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 ""
+msgstr "Puma 執行的線程數大於1,並且啟用了 Rugged æœå‹™ã€‚在æŸäº›ç’°å¢ƒä¸­ï¼Œé€™å¯èƒ½æœƒå°Žè‡´æ€§èƒ½é™ä½Žã€‚有關此å•é¡Œçš„詳細訊æ¯ï¼Œè«‹åƒè¦‹æˆ‘們的%{link_start}文件%{link_end}。"
+
+msgid "PumbleIntegration|Send notifications about project events to Pumble."
+msgstr "å‘ Pumble 發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。"
+
+msgid "PumbleIntegration|Send notifications about project events to Pumble. %{docs_link}"
+msgstr "å‘ Pumble 發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。 %{docs_link}"
msgid "Purchase more minutes"
-msgstr ""
+msgstr "購買更多時間"
msgid "Purchase more storage"
-msgstr ""
+msgstr "購買更多儲存"
msgid "PurchaseStep|An error occurred in the purchase step. If the problem persists please contact support at https://support.gitlab.com."
-msgstr ""
+msgstr "購買步驟發生錯誤。如果å•é¡Œä»ç„¶å­˜åœ¨ï¼Œè«‹è¯çµ¡æ”¯æ´äººå“¡ã€‚"
msgid "Push"
-msgstr ""
+msgstr "推é€"
msgid "Push Rule updated successfully."
-msgstr ""
+msgstr "推é€è¦å‰‡å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Push Rules"
-msgstr ""
+msgstr "推é€è¦å‰‡"
msgid "Push Rules updated successfully."
-msgstr ""
+msgstr "推é€è¦å‰‡å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Push an existing Git repository"
-msgstr ""
+msgstr "推é€ç¾æœ‰çš„ Git 版本庫"
msgid "Push an existing folder"
-msgstr ""
+msgstr "推é€ç¾æœ‰è³‡æ–™å¤¾"
msgid "Push code to the repository."
-msgstr ""
+msgstr "推é€ç¨‹å¼ç¢¼é€²ç‰ˆæœ¬åº«ã€‚"
msgid "Push commits to the source branch or add previously merged commits to review them."
-msgstr ""
+msgstr "推é€æ交到來æºåˆ†æ”¯æˆ–加入先å‰åˆä½µçš„æ交以進行審核。"
msgid "Push events"
-msgstr ""
+msgstr "推é€äº‹ä»¶"
msgid "Push project from command line"
-msgstr ""
+msgstr "從命令列推é€å°ˆæ¡ˆ"
msgid "Push rules"
-msgstr ""
+msgstr "推é€è¦å‰‡"
msgid "Push the target branch up to GitLab."
-msgstr ""
+msgstr "將目標分支推é€åˆ° GitLab。"
msgid "Push to create a project"
-msgstr ""
+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 ""
+msgstr "所有分支å稱必須與此 %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}符åˆã€‚如果為空,則å…許任何分支å稱。"
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 "所有æ交作者的電å­éƒµä»¶å¿…須與此 %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}符åˆã€‚如果為空,則å…許任何電å­éƒµä»¶ã€‚"
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 "所有æ交訊æ¯å¿…須符åˆé€™å€‹ %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}。如果為空,則æ交消æ¯ä¸éœ€è¦ç¬¦åˆä»»ä½•è¡¨é”å¼ã€‚"
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 ""
+msgstr "所有æ交的文件å都ä¸èƒ½ç¬¦åˆé€™å€‹ %{wiki_syntax_link_start}正則表é”å¼%{wiki_syntax_link_end}。如果為空,則å…許使用任何文件å。"
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 ""
+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 ""
+msgstr "ä¸å…許使用者使用 %{code_block_start}git push%{code_block_end}時刪除Git標籤。"
msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}"
-msgstr ""
+msgstr "拒絕任何å¯èƒ½åŒ…å« secret 的文件。 %{secret_files_link_start}哪些 secret 文件會被拒絕?%{secret_files_link_end}"
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 "拒絕等於或大於此大å°çš„文件。如果設定為 0,則å…許任何大å°çš„文件。此è¦å‰‡ä¸é©ç”¨æ–¼ Git LFS 追蹤的文件。"
msgid "PushRules|Restrict commits to existing GitLab users."
-msgstr ""
+msgstr "é™åˆ¶å°ç¾æœ‰ GitLab 使用者的æ交。"
msgid "PushRules|Restrict push operations for this project."
-msgstr ""
+msgstr "é™åˆ¶æ­¤å°ˆæ¡ˆçš„推é€æ“作。"
msgid "PushRules|Save push rules"
-msgstr ""
+msgstr "ä¿å­˜æŽ¨é€è¦å‰‡"
msgid "PushRules|Select push rules"
-msgstr ""
+msgstr "é¸æ“‡æŽ¨é€è¦å‰‡"
msgid "PushRules|Users can still delete tags through the GitLab UI."
-msgstr ""
+msgstr "使用者ä»ç„¶å¯ä»¥é€šéŽUI刪除標籤。"
msgid "PushRule|Push rules"
-msgstr ""
+msgstr "推é€è¦å‰‡"
msgid "PushRule|Reject unverified users"
-msgstr ""
+msgstr "拒絕未經驗證的使用者"
msgid "Pushed"
-msgstr ""
+msgstr "已推é€"
msgid "Pushes"
-msgstr ""
+msgstr "推é€"
msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
-msgstr ""
+msgstr "%{user_name} 已刪除分支「%{ref}ã€ã€‚"
msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
-msgstr ""
+msgstr "%{user_name} 推é€åˆ†æ”¯ \"%{ref}\"。"
msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
-msgstr ""
+msgstr "%{user_name} 已推é€æ–°åˆ†æ”¯ \"%{ref}\"。"
msgid "PushoverService|Enter new user key"
-msgstr ""
+msgstr "輸入新的使用者金鑰"
msgid "PushoverService|Enter your application key."
-msgstr ""
+msgstr "輸入您的應用程å¼é‡‘鑰。"
msgid "PushoverService|Enter your user key."
-msgstr ""
+msgstr "輸入您的使用者金鑰。"
msgid "PushoverService|Get real-time notifications on your device."
-msgstr ""
+msgstr "在您的設備上å–得實時通知。"
msgid "PushoverService|High priority"
-msgstr ""
+msgstr "高優先級"
msgid "PushoverService|Leave blank for all active devices."
-msgstr ""
+msgstr "留空為所有啟用設備."
msgid "PushoverService|Leave blank to use your current user key."
-msgstr ""
+msgstr "留空以使用您當å‰çš„使用者金鑰。"
msgid "PushoverService|Low priority"
-msgstr ""
+msgstr "低優先級"
msgid "PushoverService|Lowest priority"
-msgstr ""
+msgstr "最低優先級"
msgid "PushoverService|Normal priority"
-msgstr ""
+msgstr "正常優先級"
msgid "PushoverService|See project %{project_full_name}"
-msgstr ""
+msgstr "åƒè¦‹å°ˆæ¡ˆ %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
-msgstr ""
+msgstr "總æ交次數:%{total_commits_count}"
msgid "QualitySummary|Project quality"
-msgstr ""
+msgstr "專案質é‡"
msgid "Query"
-msgstr ""
+msgstr "查詢"
msgid "Query cannot be processed"
-msgstr ""
+msgstr "無法處ç†æŸ¥è©¢"
msgid "Queued"
-msgstr ""
+msgstr "已佇列"
msgid "Quick actions can be used in description and comment boxes."
-msgstr ""
+msgstr "å¯ä»¥åœ¨æ述和留言框中使用快速æ“作。"
msgid "Quick help"
-msgstr ""
+msgstr "快速幫助"
msgid "Quick range"
-msgstr ""
+msgstr "å¿«æ·ç¯„åœ"
msgid "Quickly and easily edit multiple files in your project."
-msgstr ""
+msgstr "快速輕鬆地編輯您專案中的多個文件。"
msgid "Quota of CI/CD minutes"
-msgstr ""
+msgstr "CI/CD 分é˜æ•¸é…é¡"
msgid "Quota of CI/CD minutes:"
-msgstr ""
+msgstr "CI/CD 分é˜æ•¸é…é¡ï¼š"
msgid "README"
-msgstr ""
+msgstr "README"
msgid "Rails"
-msgstr ""
+msgstr "Rails"
msgid "Rake Tasks Help"
-msgstr ""
+msgstr "Rake任務幫助"
msgid "Random"
-msgstr ""
+msgstr "隨機"
msgid "Rate Limits"
-msgstr ""
+msgstr "速率é™åˆ¶"
msgid "Rate limit"
-msgstr ""
+msgstr "速率é™åˆ¶"
msgid "Rate limit access to specified paths."
-msgstr ""
+msgstr "é™åˆ¶å­˜å–指定路徑的速度。"
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
-msgstr ""
+msgstr "速率é™åˆ¶æœ‰åŠ©æ–¼æ¸›å°‘請求é‡ï¼ˆä¾‹å¦‚來自爬蟲或濫用機器人的請求)。"
msgid "Raw blob request rate limit per minute"
-msgstr ""
+msgstr "æ¯åˆ†é˜åŽŸå§‹Blob請求速率é™åˆ¶"
msgid "Raw blob requests"
-msgstr ""
+msgstr "原始 blob 請求"
msgid "Re-authentication period expired or never requested. Please try again"
-msgstr ""
+msgstr "é‡æ–°èªè­‰æœŸå·²éŽæœŸæˆ–從未請求éŽã€‚è«‹å†è©¦ä¸€é"
msgid "Re-authentication required"
-msgstr ""
+msgstr "需è¦é‡æ–°èªè­‰"
msgid "Re-import"
-msgstr ""
+msgstr "é‡æ–°åŒ¯å…¥"
msgid "Re-request review"
-msgstr ""
+msgstr "é‡æ–°è«‹æ±‚審核"
msgid "Read documentation"
-msgstr ""
+msgstr "閱讀文件"
msgid "Read more"
-msgstr ""
+msgstr "進一步了解"
msgid "Read more about GitLab at %{link_to_promo}."
-msgstr ""
+msgstr "在%{link_to_promo}上閱讀更多關於 GitLab 的訊æ¯ã€‚"
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
+msgstr "æ–¼%{help_link_open}此處%{help_link_close}了解有關專案權é™çš„更多訊æ¯"
msgid "Read more about related epics"
-msgstr ""
+msgstr "閱讀更多關於相關å²è©©çš„訊æ¯"
msgid "Read more about related issues"
-msgstr ""
+msgstr "了解更多關於相關議題的訊æ¯"
msgid "Read their documentation."
-msgstr ""
+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 ""
+msgstr "準備好開始使用 GitLab 了嗎?按照以下步驟設定您的工作å€ã€è¨ˆåŠƒå’Œæ交更改以åŠéƒ¨ç½²æ‚¨çš„專案。"
msgid "Ready to merge by members who can write to the target branch."
-msgstr ""
+msgstr "準備由å¯ä»¥å¯«å…¥ç›®æ¨™åˆ†æ”¯çš„æˆå“¡åˆä½µã€‚"
msgid "Ready to merge!"
-msgstr ""
+msgstr "準備åˆä½µï¼"
msgid "Reauthenticating with SAML provider."
-msgstr ""
+msgstr "正在與 SAML æ供商é‡æ–°é©—證。"
msgid "Rebase"
-msgstr ""
+msgstr "變基"
msgid "Rebase completed"
-msgstr ""
+msgstr "變基完æˆ"
msgid "Rebase in progress"
-msgstr ""
+msgstr "Rebase正在進行中"
msgid "Rebase source branch"
-msgstr ""
+msgstr "Rebase來æºåˆ†æ”¯"
msgid "Rebase source branch on the target branch."
-msgstr ""
+msgstr "在目標分支上Rebase來æºåˆ†æ”¯ã€‚"
msgid "Rebase without pipeline"
-msgstr ""
+msgstr "沒有æµæ°´ç·šçš„變基"
msgid "Recaptcha verified?"
-msgstr ""
-
-msgid "Receive a $50 gift card as a thank you for your time."
-msgstr ""
-
-msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
-msgstr ""
+msgstr "é‡æ–°é©—證?"
msgid "Receive any notifications from GitLab."
-msgstr ""
+msgstr "接收來自 GitLab 的任何通知。"
msgid "Receive notification of abuse reports by email."
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶æŽ¥æ”¶æ¿«ç”¨å ±å‘Šé€šçŸ¥ã€‚"
msgid "Receive notifications about your own activity"
-msgstr ""
+msgstr "接收關於您自己活動的通知"
msgid "Receive product marketing emails"
-msgstr ""
+msgstr "接收產å“營銷電å­éƒµä»¶"
msgid "Recent"
-msgstr ""
+msgstr "最近"
msgid "Recent Project Activity"
-msgstr ""
+msgstr "最近的專案動態"
msgid "Recent Searches Service is unavailable"
-msgstr ""
+msgstr "最近æœå°‹æœå‹™ä¸å¯ç”¨"
msgid "Recent events"
-msgstr ""
+msgstr "最近事件"
msgid "Recent searches"
-msgstr ""
+msgstr "最近的æœå°‹"
msgid "Recently used"
-msgstr ""
+msgstr "最近使用"
msgid "Reconfigure"
-msgstr ""
+msgstr "é‡æ–°è¨­å®š"
+
+msgid "Recover password"
+msgstr "æ¢å¾©å¯†ç¢¼"
msgid "Recovery Codes"
-msgstr ""
+msgstr "æ¢å¾©ç¢¼"
msgid "Redirect to SAML provider to test configuration"
-msgstr ""
+msgstr "å‰å¾€SAML供應商以測試設定"
msgid "Redirecting"
-msgstr ""
+msgstr "é‡å®šå‘中"
msgid "Redis"
-msgstr ""
+msgstr "Redis"
msgid "Reduce incident management alert volume (for example, if too many issues are being created)."
-msgstr ""
+msgstr "減少事件管ç†è­¦å ±é‡ï¼ˆä¾‹å¦‚,如果建立的議題éŽå¤šï¼‰ã€‚"
msgid "Reduce project visibility"
-msgstr ""
+msgstr "é™ä½Žå°ˆæ¡ˆå¯è¦‹æ€§"
msgid "Reduce risk and triage fewer vulnerabilities with security training"
-msgstr ""
+msgstr "通éŽå®‰å…¨åŸ¹è¨“é™ä½Žé¢¨éšªä¸¦æ¸›å°‘æ¼æ´žé¡žåž‹"
msgid "Reduce this project’s visibility?"
-msgstr ""
+msgstr "é™ä½Žæ­¤å°ˆæ¡ˆå¯åº¦å—Žï¼Ÿ"
msgid "Reference"
-msgstr ""
+msgstr "åƒè€ƒ"
msgid "References"
-msgstr ""
+msgstr "引用"
msgid "Refine your search criteria (select a %{strong_open}group%{strong_close} and %{strong_open}project%{strong_close} when possible)"
-msgstr ""
+msgstr "優化您的æœå°‹æ¢ä»¶ï¼ˆç›¡å¯èƒ½é¸æ“‡ %{strong_open}群組%{strong_close} å’Œ %{strong_open}專案%{strong_close}"
msgid "Refresh the page and try again."
-msgstr ""
+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[0] "%d 秒後é‡æ–°æ•´ç†ä»¥é¡¯ç¤ºæ›´æ–°ç‹€æ…‹..."
msgid "Regenerate export"
-msgstr ""
+msgstr "é‡æ–°åŒ¯å‡º"
msgid "Regenerate instance ID"
-msgstr ""
+msgstr "é‡æ–°ç”Ÿæˆå¯¦é«”ID"
msgid "Regenerate recovery codes"
-msgstr ""
+msgstr "é‡æ–°ç”Ÿæˆæ¢å¾©ç¢¼"
msgid "Regenerating the instance ID can break integration depending on the client you are using."
-msgstr ""
+msgstr "é‡æ–°ç”Ÿæˆå¯¦é«” ID,å¯èƒ½æœƒæ‚¨ä½¿ç”¨çš„部分客戶端的整åˆå¤±æ•ˆã€‚"
msgid "Regex pattern"
-msgstr ""
+msgstr "æ­£è¦è¡¨ç¤ºå¼"
msgid "Region"
-msgstr ""
+msgstr "å€åŸŸ"
msgid "Regions"
-msgstr ""
+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 ""
+msgstr "註冊通用雙因å­èªè­‰è¨­å‚™(U2F)"
msgid "Register WebAuthn Device"
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥è¨»å†Šç„¡ä¸Šé™å€‹çš„執行器。您å¯ä»¥åœ¨å–®ç¨çš„伺æœå™¨å’Œæ‚¨çš„本地設備上,將執行器註冊為單ç¨çš„使用者。執行器å¯ä»¥æ˜¯ï¼š"
msgid "Register device"
-msgstr ""
+msgstr "註冊設備"
msgid "Register now"
-msgstr ""
+msgstr "ç«‹å³è¨»å†Š"
msgid "Register the runner with this URL:"
-msgstr ""
+msgstr "使用此 URL 註冊執行器:"
msgid "Register with two-factor app"
-msgstr ""
+msgstr "使用雙因å­èªè­‰æ‡‰ç”¨ç¨‹å¼è¨»å†Š"
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
-msgstr ""
+msgstr "啟用æœå‹™ Ping 並註冊此功能。"
msgid "RegistrationFeatures|Read more about the %{link_start}Registration Features Program%{link_end}."
-msgstr ""
+msgstr "閱讀有關%{link_start}註冊功能計劃%{link_end}的更多訊æ¯ã€‚"
msgid "RegistrationFeatures|Registration Features Program"
-msgstr ""
+msgstr "註冊功能程åº"
msgid "RegistrationFeatures|Want to %{feature_title} for free?"
-msgstr ""
+msgstr "想è¦å…費使用 %{feature_title} 嗎?"
msgid "RegistrationFeatures|send emails to users"
-msgstr ""
+msgstr "å‘使用者發é€é›»å­éƒµä»¶"
msgid "RegistrationFeatures|use this feature"
-msgstr ""
+msgstr "使用此功能"
msgid "RegistrationVerification|Are you sure you want to skip this step?"
-msgstr ""
+msgstr "您確定è¦è·³éŽé€™ä¸€æ­¥å—Žï¼Ÿ"
msgid "RegistrationVerification|Enable free CI/CD minutes"
-msgstr ""
+msgstr "啟用å…è²» CI/CD 分é˜"
msgid "RegistrationVerification|GitLab will not charge your card, it will only be used for validation."
-msgstr ""
+msgstr "GitLab ä¸æœƒå¾žæ‚¨çš„å¡ä¸­æ‰£æ¬¾ï¼Œå®ƒåªæœƒç”¨æ–¼é©—證。"
msgid "RegistrationVerification|Pipelines using shared GitLab runners will fail until you validate your account."
-msgstr ""
+msgstr "請先驗證您的帳號,å¦å‰‡ç„¡æ³•ä½¿ç”¨å…±äº« GitLab 執行器的æµæ°´ç·šã€‚"
msgid "RegistrationVerification|Skip this for now"
-msgstr ""
+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 ""
+msgstr "為了防止 GitLab 垃圾郵件和濫用,我們è¦æ±‚您使用有效的付款方å¼ï¼ˆä¾‹å¦‚借記å¡æˆ–信用å¡ï¼‰é©—證您的身份。在此之å‰ï¼Œæ‚¨ç„¡æ³•ä½¿ç”¨å…費的 CI/CD 分é˜ä¾†æ§‹å»ºæ‚¨çš„應用程å¼ã€‚"
msgid "RegistrationVerification|Validate account"
-msgstr ""
+msgstr "驗證帳號"
msgid "RegistrationVerification|Verify your identity"
-msgstr ""
+msgstr "驗證您的身份"
msgid "RegistrationVerification|Yes, I'd like to skip"
-msgstr ""
+msgstr "是的,我想跳éŽ"
msgid "RegistrationVerification|You can alway verify your account at a later time."
-msgstr ""
+msgstr "您å¯ä»¥ç¨å¾Œé©—證您的帳號。"
msgid "Registration|Checkout"
-msgstr ""
+msgstr "支付"
msgid "Registration|Your GitLab group"
-msgstr ""
+msgstr "您的GitLab群組"
msgid "Registration|Your first project"
-msgstr ""
+msgstr "您的第一個專案"
msgid "Registration|Your profile"
-msgstr ""
+msgstr "您的個人資料"
msgid "Registry setup"
-msgstr ""
+msgstr "註冊表設定"
msgid "Reindexing Status: %{status} (Slice multiplier: %{multiplier}, Maximum running slices: %{max_slices})"
-msgstr ""
+msgstr "é‡æ–°ç´¢å¼•ç‹€æ…‹ï¼š %{status} (切片乘數: %{multiplier},最大執行切片: %{max_slices})"
msgid "Reject"
-msgstr ""
+msgstr "拒絕"
msgid "Rejected (closed)"
-msgstr ""
+msgstr "已拒絕(關閉)"
msgid "Relate to %{issuable_type} %{add_related_issue_link}"
-msgstr ""
+msgstr "é—œè¯åˆ° %{issuable_type} %{add_related_issue_link}"
msgid "Related feature flags"
-msgstr ""
-
-msgid "Related incidents or issues"
-msgstr ""
+msgstr "相關的功能標誌"
msgid "Related issues"
-msgstr ""
+msgstr "相關議題"
msgid "Related merge requests"
-msgstr ""
+msgstr "相關åˆä½µè«‹æ±‚"
msgid "Relates to"
-msgstr ""
+msgstr "與下述相關"
msgid "Release"
msgid_plural "Releases"
-msgstr[0] ""
+msgstr[0] "發行"
+
+msgid "Release %{deletedRelease} has been successfully deleted."
+msgstr "發佈版本 %{deletedRelease} å·²æˆåŠŸåˆªé™¤ã€‚"
msgid "Release assets"
-msgstr ""
+msgstr "發布資產"
msgid "Release assets documentation"
-msgstr ""
+msgstr "發布資產文件"
msgid "Release date"
-msgstr ""
+msgstr "發布日期"
msgid "Release does not have the same project as the milestone"
-msgstr ""
+msgstr "發布與里程碑沒有相åŒçš„專案"
msgid "Release notes"
-msgstr ""
+msgstr "發佈說明"
msgid "Release notes:"
-msgstr ""
+msgstr "發佈說明:"
msgid "Release title"
-msgstr ""
+msgstr "發佈標題"
msgid "Release with tag \"%{tag}\" was not found"
-msgstr ""
+msgstr "找ä¸åˆ°å¸¶æ¨™ç±¤ç‚ºã€Œ%{tag}ã€çš„版本"
msgid "ReleaseAssetLinkType|Image"
-msgstr ""
+msgstr "映åƒ"
msgid "ReleaseAssetLinkType|Images"
-msgstr ""
+msgstr "映åƒ"
msgid "ReleaseAssetLinkType|Other"
-msgstr ""
+msgstr "其他"
msgid "ReleaseAssetLinkType|Package"
-msgstr ""
+msgstr "軟體套件"
msgid "ReleaseAssetLinkType|Packages"
-msgstr ""
+msgstr "軟體套件"
msgid "ReleaseAssetLinkType|Runbook"
-msgstr ""
+msgstr "Runbook"
msgid "ReleaseAssetLinkType|Runbooks"
-msgstr ""
+msgstr "Runbook"
msgid "Released date"
-msgstr ""
+msgstr "發布日期"
msgid "Releases"
-msgstr ""
+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 ""
+msgstr "發布基於Git標籤,並標記專案開發歷å²ä¸­çš„特定點。它們å¯ä»¥åŒ…å«æœ‰é—œæ›´æ”¹é¡žåž‹çš„訊æ¯ï¼Œé‚„å¯ä»¥æ供二進制文件,例如軟體的編譯版本。"
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 "發布基於 Git 標籤,我們推薦使用語義版本控制的標籤,例如 %{codeStart}v1.0.0%{codeEnd}〠%{codeStart}v2.1.0-pre%{codeEnd}。"
msgid "Releases documentation"
-msgstr ""
+msgstr "發布文件"
msgid "Releases|New Release"
-msgstr ""
+msgstr "新發布"
msgid "Releases|Tag message"
-msgstr ""
+msgstr "標籤訊æ¯"
msgid "Release|Include message from the annotated tag."
-msgstr ""
+msgstr "帶註釋的標籤å«æœ‰è¨Šæ¯ã€‚"
msgid "Release|Something went wrong while creating a new release."
-msgstr ""
+msgstr "建立新發布時發生錯誤。"
+
+msgid "Release|Something went wrong while deleting the release."
+msgstr "刪除發佈版本時發生錯誤。"
msgid "Release|Something went wrong while getting the release details."
-msgstr ""
+msgstr "å–得發布詳情時出ç¾å•é¡Œã€‚"
msgid "Release|Something went wrong while saving the release details."
-msgstr ""
+msgstr "ä¿å­˜ç™¼å¸ƒè©³ç´°è¨Šæ¯æ™‚發生錯誤。"
msgid "Release|Unable to fetch the tag notes."
-msgstr ""
+msgstr "無法å–得標籤註釋。"
msgid "Release|You can edit the content later by editing the release. %{linkStart}How do I edit a release?%{linkEnd}"
-msgstr ""
+msgstr "您å¯ä»¥ç¨å¾Œé€šéŽç·¨è¼¯ç™¼å¸ƒä¾†ç·¨è¼¯å…§å®¹ã€‚ %{linkStart}我如何編輯發布?%{linkEnd}"
msgid "Reload page"
-msgstr ""
+msgstr "é‡æ–°è¼‰å…¥é é¢"
msgid "Remediations"
-msgstr ""
+msgstr "修復措施"
msgid "Remember me"
-msgstr ""
+msgstr "記ä½å¸³è™Ÿ"
msgid "Remind later"
-msgstr ""
+msgstr "ç¨å¾Œæ醒"
msgid "Remote object has no absolute path."
-msgstr ""
+msgstr "é ç«¯ç‰©ä»¶æ²’有絕å°è·¯å¾‘。"
msgid "Remove"
-msgstr ""
+msgstr "移除"
msgid "Remove %{displayReference}"
-msgstr ""
+msgstr "移除%{displayReference}"
msgid "Remove Zoom meeting"
-msgstr ""
+msgstr "移除Zoom會議"
msgid "Remove Zoom meeting."
-msgstr ""
+msgstr "移除Zoom會議"
msgid "Remove access"
-msgstr ""
+msgstr "移除存å–權é™"
msgid "Remove all or specific assignee(s)"
-msgstr ""
+msgstr "移除所有或特定指派人"
msgid "Remove all or specific label(s)"
-msgstr ""
+msgstr "移除全部或特定標記"
msgid "Remove all or specific reviewer(s)"
-msgstr ""
+msgstr "移除全部或特定的審核者"
msgid "Remove approvers"
-msgstr ""
+msgstr "程除核准者"
msgid "Remove approvers?"
-msgstr ""
+msgstr "移除核准者?"
msgid "Remove asset link"
-msgstr ""
+msgstr "移除資產連çµ"
msgid "Remove assignee"
-msgstr ""
-
-msgid "Remove attention request"
-msgstr ""
-
-msgid "Remove attention request(s)"
-msgstr ""
+msgstr "移除指派人"
msgid "Remove avatar"
-msgstr ""
+msgstr "移除頭åƒ"
msgid "Remove card"
-msgstr ""
+msgstr "刪除å¡ç‰‡"
msgid "Remove child epic from an epic"
-msgstr ""
+msgstr "從å²è©©ä¸­åˆªé™¤å­å²è©©"
msgid "Remove customer relation contact(s)."
-msgstr ""
+msgstr "移除客戶關係è¯çµ¡äºº(s)。"
msgid "Remove customer relation contacts"
-msgstr ""
+msgstr "移除客戶關係è¯çµ¡äºº"
msgid "Remove deploy key"
-msgstr ""
+msgstr "移除部署金鑰"
msgid "Remove description history"
-msgstr ""
+msgstr "移除æè¿°æ­·å²"
msgid "Remove due date"
-msgstr ""
+msgstr "移除截止日期"
msgid "Remove favicon"
-msgstr ""
+msgstr "移除圖標"
msgid "Remove file"
-msgstr ""
+msgstr "移除文件"
msgid "Remove fork relationship"
-msgstr ""
+msgstr "移除分å‰é—œä¿‚"
msgid "Remove from batch"
-msgstr ""
+msgstr "從批次中移除"
msgid "Remove from epic"
-msgstr ""
+msgstr "從å²è©©ä¸­ç§»é™¤"
msgid "Remove group"
-msgstr ""
+msgstr "移除群組"
msgid "Remove header logo"
-msgstr ""
+msgstr "移除標題標誌(logo)"
msgid "Remove iteration"
-msgstr ""
+msgstr "移除迭代"
msgid "Remove license"
-msgstr ""
+msgstr "移除授權許å¯"
msgid "Remove limit"
-msgstr ""
+msgstr "移除é™åˆ¶"
msgid "Remove link"
-msgstr ""
+msgstr "移除連çµ"
msgid "Remove list"
-msgstr ""
+msgstr "移除列表"
msgid "Remove log"
-msgstr ""
+msgstr "移除日誌"
msgid "Remove logo"
-msgstr ""
+msgstr "移除logo"
msgid "Remove member"
-msgstr ""
+msgstr "移除æˆå“¡"
msgid "Remove milestone"
-msgstr ""
+msgstr "移除里程碑"
msgid "Remove parent epic from an epic"
-msgstr ""
+msgstr "從å²è©©ä¸­ç§»é™¤çˆ¶å²è©©"
msgid "Remove priority"
-msgstr ""
+msgstr "移除優先級別"
msgid "Remove report"
-msgstr ""
+msgstr "移除報告"
msgid "Remove reviewer"
-msgstr ""
+msgstr "移除審核者"
msgid "Remove runner"
-msgstr ""
+msgstr "移除執行器"
msgid "Remove secondary email"
-msgstr ""
+msgstr "移除次è¦é›»å­éƒµä»¶"
msgid "Remove spent time"
-msgstr ""
+msgstr "移除消耗時間"
msgid "Remove time estimate"
-msgstr ""
+msgstr "移除時間估計"
msgid "Remove topic avatar"
-msgstr ""
+msgstr "移除主題頭åƒ"
msgid "Remove user"
-msgstr ""
+msgstr "移除使用者"
msgid "Remove user & report"
-msgstr ""
+msgstr "移除使用者和報告"
msgid "Remove user from group"
-msgstr ""
+msgstr "從群組中移除使用者"
msgid "Remove user from project"
-msgstr ""
+msgstr "從專案中移除使用者"
msgid "Remove..."
-msgstr ""
+msgstr "移除..."
msgid "Removed"
-msgstr ""
+msgstr "已移除"
msgid "Removed %{assignee_text} %{assignee_references}."
-msgstr ""
+msgstr "已移除%{assignee_text}%{assignee_references}。"
msgid "Removed %{epic_ref} from child epics."
-msgstr ""
+msgstr "已從å­å²è©©ä¸­ç§»é™¤%{epic_ref}。"
msgid "Removed %{iteration_reference} iteration."
-msgstr ""
+msgstr "移除了迭代%{iteration_reference}。"
msgid "Removed %{label_references} %{label_text}."
-msgstr ""
+msgstr "已移除%{label_references}%{label_text}。"
msgid "Removed %{milestone_reference} milestone."
-msgstr ""
+msgstr "已移除里程碑%{milestone_reference} 。"
msgid "Removed %{reviewer_text} %{reviewer_references}."
-msgstr ""
+msgstr "已移除 %{reviewer_text} %{reviewer_references}。"
msgid "Removed all labels."
-msgstr ""
+msgstr "已移除所有標籤。"
msgid "Removed an issue from an epic."
-msgstr ""
-
-msgid "Removed attention from %{users_sentence}."
-msgstr ""
-
-msgid "Removed attention request from @%{username}"
-msgstr ""
+msgstr "從å²è©©ä¸­ç§»é™¤äº†ä¸€å€‹è­°é¡Œã€‚"
msgid "Removed group can not be restored!"
-msgstr ""
+msgstr "已移除的群組無法復原ï¼"
msgid "Removed parent epic %{epic_ref}."
-msgstr ""
+msgstr "已移除父å²è©©%{epic_ref}。"
msgid "Removed spent time."
-msgstr ""
+msgstr "已移除消耗時間."
msgid "Removed the due date."
-msgstr ""
+msgstr "已移除截止日期."
msgid "Removed time estimate."
-msgstr ""
+msgstr "已移除時間估計。"
msgid "Removed upload with id %{id}"
-msgstr ""
+msgstr "已移除id為 %{id} 的上傳"
msgid "RemovedProjects|No projects pending deletion found"
-msgstr ""
+msgstr "找ä¸åˆ°ç­‰å¾…刪除的專案"
msgid "RemovedProjects|Projects that are pending deletion that you have access to are listed here."
-msgstr ""
+msgstr "此處列出了您有權存å–的待刪除專案。"
msgid "Removes %{assignee_text} %{assignee_references}."
-msgstr ""
+msgstr "移除%{assignee_text} %{assignee_references}。"
msgid "Removes %{epic_ref} from child epics."
-msgstr ""
+msgstr "從å­å²è©©ä¸­ç§»é™¤%{epic_ref}。"
msgid "Removes %{iteration_reference} iteration."
-msgstr ""
+msgstr "移除迭代%{iteration_reference}。"
msgid "Removes %{label_references} %{label_text}."
-msgstr ""
+msgstr "移除%{label_references}%{label_text}."
msgid "Removes %{milestone_reference} milestone."
-msgstr ""
+msgstr "移除里程碑%{milestone_reference}。"
msgid "Removes %{reviewer_text} %{reviewer_references}."
-msgstr ""
+msgstr "移除 %{reviewer_text} %{reviewer_references}。"
msgid "Removes all labels."
-msgstr ""
+msgstr "移除所有標記。"
msgid "Removes an issue from an epic."
-msgstr ""
-
-msgid "Removes attention from %{users_sentence}."
-msgstr ""
+msgstr "從å²è©©ä¸­ç§»é™¤ä¸€å€‹è­°é¡Œã€‚"
msgid "Removes parent epic %{epic_ref}."
-msgstr ""
+msgstr "移除父å²è©©%{epic_ref}。"
msgid "Removes spent time."
-msgstr ""
+msgstr "移除消耗時間."
msgid "Removes the due date."
-msgstr ""
+msgstr "移除截止日期."
msgid "Removes time estimate."
-msgstr ""
+msgstr "移除時間估計。"
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
-msgstr ""
+msgstr "移除該群組會åŒæ™‚移除所有å­å°ˆæ¡ˆï¼ŒåŒ…括已歸檔專案åŠå…¶ç›¸é—œè³‡æºã€‚"
msgid "Rename file"
-msgstr ""
+msgstr "é‡æ–°å‘½å文件"
msgid "Rename folder"
-msgstr ""
+msgstr "é‡æ–°å‘½å資料夾"
msgid "Rename/Move"
-msgstr ""
+msgstr "é‡å‘½å/移動"
msgid "Render diagrams in your documents using PlantUML."
-msgstr ""
+msgstr "使用 PlantUML 在您的文件中渲染圖表。"
msgid "Renew subscription"
-msgstr ""
+msgstr "續訂"
msgid "Renews"
-msgstr ""
+msgstr "æ›´æ–°"
msgid "Reopen"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ"
msgid "Reopen %{issueType}"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ%{issueType}"
msgid "Reopen %{noteable}"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ %{noteable}"
msgid "Reopen epic"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿå²è©©"
msgid "Reopen milestone"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿé‡Œç¨‹ç¢‘"
msgid "Reopen test case"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿæ¸¬è©¦æ¡ˆä¾‹"
msgid "Reopen this %{quick_action_target}"
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ%{quick_action_target}"
msgid "Reopened this %{quick_action_target}."
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ%{quick_action_target}。"
msgid "Reopens this %{quick_action_target}."
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿ%{quick_action_target}。"
msgid "Replace"
-msgstr ""
+msgstr "å–代"
msgid "Replace %{name}"
-msgstr ""
+msgstr "å–代 %{name}"
msgid "Replace all label(s)"
-msgstr ""
+msgstr "å–代所有標記"
msgid "Replace audio"
-msgstr ""
+msgstr "å–代音頻"
msgid "Replace file"
-msgstr ""
+msgstr "å–代文件"
msgid "Replace image"
-msgstr ""
+msgstr "å–代影åƒ"
msgid "Replace video"
-msgstr ""
+msgstr "å–代視頻"
msgid "Replaced all labels with %{label_references} %{label_text}."
-msgstr ""
+msgstr "已將所有標記å–代為%{label_references}%{label_text}。"
msgid "Replaces the clone URL root."
-msgstr ""
+msgstr "å–代仿製(clone)URL根地å€ã€‚"
msgid "Replication"
-msgstr ""
+msgstr "複製"
msgid "Reply"
-msgstr ""
+msgstr "回複"
msgid "Reply by email"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶å›žå¾©"
msgid "Reply internally"
-msgstr ""
+msgstr "內部回復"
msgid "Reply to comment"
-msgstr ""
+msgstr "回復留言"
msgid "Reply to this email directly or %{view_it_on_gitlab}."
-msgstr ""
+msgstr "直接回復此郵件或 %{view_it_on_gitlab}。"
msgid "Reply…"
-msgstr ""
+msgstr "回復…"
+
+msgid "Report Finding not found"
+msgstr "未發ç¾æœå°‹å ±å‘Š"
msgid "Report abuse"
-msgstr ""
+msgstr "報告濫用"
msgid "Report abuse to admin"
-msgstr ""
+msgstr "å‘管ç†å“¡å ±å‘Šæ¿«ç”¨è¡Œç‚º"
msgid "Report couldn't be prepared."
-msgstr ""
+msgstr "無法準備報告。"
msgid "Report for the scan has been removed from the database."
-msgstr ""
+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 "未æ供報告版本,%{report_type} 報告類型支æ´ç‰ˆæœ¬ï¼š%{supported_schema_versions}。 GitLab 將嘗試根據此報告類型的最早支æ´ç‰ˆæœ¬é©—證此報告並顯示所有錯誤,但ä¸ç²å–報告"
msgid "Report your license usage data to GitLab"
-msgstr ""
+msgstr "å‘ GitLab 匯報您的許å¯è­‰ä½¿ç”¨è³‡æ–™"
msgid "Reported %{timeAgo} by %{reportedBy}"
-msgstr ""
+msgstr "由%{reportedBy}報告於%{timeAgo}"
msgid "Reported by"
-msgstr ""
+msgstr "報告人"
msgid "Reported by %{reporter}"
-msgstr ""
+msgstr "由%{reporter}報告"
msgid "Reporting"
-msgstr ""
+msgstr "報告"
msgid "Reports|%{combinedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{combinedString}åŠ%{resolvedString}"
msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
-msgstr ""
+msgstr "在éŽåŽ»çš„14天中,%{failed}個測試中有%{recentlyFailed}個失敗了一次以上"
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[0] "在éŽåŽ»çš„14天中,%{failed}個測試中有%{recentlyFailed}個失敗了一次以上"
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[0] "無障礙性掃æ檢測到%d個僅存在於來æºåˆ†æ”¯çš„å•é¡Œ"
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[0] "無障礙性掃æ檢測到 %{strong_start}%{number}%{strong_end} 個僅é‡å°ä¾†æºåˆ†æ”¯çš„å•é¡Œ"
msgid "Reports|Accessibility scanning detected no issues for the source branch only"
-msgstr ""
+msgstr "無障礙性掃æ沒有檢測到僅存在於來æºåˆ†æ”¯çš„å•é¡Œ"
msgid "Reports|Accessibility scanning failed loading results"
-msgstr ""
+msgstr "無障礙性掃æ載入çµæžœå¤±æ•—"
msgid "Reports|Accessibility scanning results are being parsed"
-msgstr ""
+msgstr "正在解æžç„¡éšœç¤™æ€§æŽƒæçµæžœ"
msgid "Reports|Actions"
-msgstr ""
+msgstr "æ“作"
msgid "Reports|Activity"
-msgstr ""
+msgstr "å‹•æ…‹"
msgid "Reports|An error occurred while loading %{name} results"
-msgstr ""
+msgstr "載入%{name}çµæžœæ™‚發生錯誤"
msgid "Reports|An error occurred while loading report"
-msgstr ""
+msgstr "載入報告時發生錯誤"
msgid "Reports|Base report parsing error:"
-msgstr ""
+msgstr "基礎報告分æžéŒ¯èª¤ï¼š"
msgid "Reports|Classname"
-msgstr ""
+msgstr "é¡žå"
msgid "Reports|Copy failed test names to run locally"
-msgstr ""
+msgstr "複製失敗的測試å稱在本地執行"
msgid "Reports|Copy failed tests"
-msgstr ""
+msgstr "複製失敗的測試"
msgid "Reports|Execution time"
-msgstr ""
+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[0] "éŽåŽ»14天中在%{baseBranch}上,失敗了%{count} 次"
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[0] "éŽåŽ»14天中在%{base_branch}上,失敗了%{count} 次"
msgid "Reports|Failure"
-msgstr ""
+msgstr "失敗"
msgid "Reports|Filename"
-msgstr ""
+msgstr "文件å"
msgid "Reports|Fixed"
-msgstr ""
+msgstr "固定的"
msgid "Reports|Full report"
-msgstr ""
+msgstr "完整報告"
msgid "Reports|Head report parsing error:"
-msgstr ""
+msgstr "HEAD 報告解æžéŒ¯èª¤ï¼š"
msgid "Reports|Identifier"
-msgstr ""
+msgstr "標識符"
msgid "Reports|Metrics report scanning detected no new changes"
-msgstr ""
+msgstr "指標報告掃æ未檢測到新變更"
msgid "Reports|Metrics reports are loading"
-msgstr ""
+msgstr "正在載入指標報告"
msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
-msgstr ""
+msgstr "指標報告有%{numberOfChanges} %{pointsString}變化"
msgid "Reports|Metrics reports did not change"
-msgstr ""
+msgstr "指標報告無變化"
msgid "Reports|Metrics reports failed loading results"
-msgstr ""
+msgstr "指標報告載入çµæžœå¤±æ•—"
msgid "Reports|Metrics reports failed to load results"
-msgstr ""
+msgstr "指標報告未能載入çµæžœ"
msgid "Reports|Metrics reports: %{strong_start}%{numberOfChanges}%{strong_end} %{changes}"
-msgstr ""
+msgstr "指標報告:%{strong_start}%{numberOfChanges}%{strong_end} 個 %{changes}"
msgid "Reports|New"
-msgstr ""
+msgstr "新增"
msgid "Reports|Scanner"
-msgstr ""
+msgstr "掃æ工具"
msgid "Reports|Severity"
-msgstr ""
+msgstr "åš´é‡ç´šåˆ¥"
msgid "Reports|System output"
-msgstr ""
+msgstr "系統輸出"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "測試總çµå ±å‘Š"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "測試摘è¦åœ¨è¼‰å…¥çµæžœæ™‚出錯"
msgid "Reports|Test summary failed to load results"
-msgstr ""
+msgstr "測試摘è¦è¼‰å…¥çµæžœå¤±æ•—"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "測試摘è¦å ±å‘Šè§£æžä¸­"
msgid "Reports|Test summary results are loading"
-msgstr ""
+msgstr "測試摘è¦çµæžœæ­£åœ¨è¼‰å…¥"
msgid "Reports|Tool"
-msgstr ""
+msgstr "工具"
msgid "Reports|Vulnerability"
-msgstr ""
+msgstr "æ¼æ´ž"
msgid "Reports|Vulnerability Name"
-msgstr ""
+msgstr "æ¼æ´žå稱"
+
+msgid "Reports|metrics report"
+msgstr "指標報告"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "未發生變化的測試çµæžœ"
msgid "Repositories"
-msgstr ""
+msgstr "版本庫"
msgid "Repositories Analytics"
-msgstr ""
+msgstr "版本庫分æž"
msgid "RepositoriesAnalytics|Analyze repositories for projects in %{groupName}. Data doesn't include projects in subgroups. %{learnMoreLink}."
-msgstr ""
+msgstr "åˆ†æž %{groupName} 中專案的版本庫。資料ä¸åŒ…括å­ç¾¤çµ„中的專案。 %{learnMoreLink}。"
msgid "RepositoriesAnalytics|Average Coverage by Job"
-msgstr ""
+msgstr "作業的平å‡è¦†è“‹çŽ‡"
msgid "RepositoriesAnalytics|Average coverage"
-msgstr ""
+msgstr "å¹³å‡è¦†è“‹çŽ‡"
msgid "RepositoriesAnalytics|Average test coverage"
-msgstr ""
+msgstr "å¹³å‡æ¸¬è©¦è¦†è“‹çŽ‡"
msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
-msgstr ""
+msgstr "程å¼ç¢¼è¦†è“‹ç¯„åœ: %{averageCoverage}"
msgid "RepositoriesAnalytics|Coverage"
-msgstr ""
+msgstr "覆蓋率"
msgid "RepositoriesAnalytics|Coverage Jobs"
-msgstr ""
+msgstr "覆蓋率作業"
msgid "RepositoriesAnalytics|Download historic test coverage data"
-msgstr ""
+msgstr "下載歷å²æ¸¬è©¦è¦†è“‹çŽ‡è³‡æ–™"
msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
-msgstr ""
+msgstr "下載歷å²æ¸¬è©¦è¦†è“‹çŽ‡è³‡æ–™(.csv)"
msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
-msgstr ""
+msgstr "下載測試覆蓋率資料 (.csv)"
msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
-msgstr ""
+msgstr "æ­·å²æ¸¬è©¦è¦†è“‹çŽ‡è³‡æ–™åŽŸå§‹æ ¼å¼(.csv)已就緒,å¯ä¾›é€²ä¸€æ­¥åˆ†æžã€‚"
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[0] "在最後一天,%{metricValue} 作業有程å¼ç¢¼è¦†è“‹çŽ‡ã€‚"
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[0] "在最後一天,%{groupName} 中的 %{metricValue} 專案啟用了程å¼ç¢¼è¦†è“‹çŽ‡ã€‚"
msgid "RepositoriesAnalytics|In the last day, on average, %{metricValue} of all jobs are covered."
-msgstr ""
+msgstr "在最後一天,全部作業的 %{metricValue} 被平å‡è¦†è“‹ã€‚"
msgid "RepositoriesAnalytics|Jobs with Coverage"
-msgstr ""
+msgstr "覆蓋範åœå…§çš„作業"
msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
-msgstr ""
+msgstr "覆蓋範åœçš„作業: %{coverageCount}"
msgid "RepositoriesAnalytics|Last 30 days"
-msgstr ""
+msgstr "éŽåŽ» 30 天"
msgid "RepositoriesAnalytics|Last Update"
-msgstr ""
+msgstr "最新更新"
msgid "RepositoriesAnalytics|Last updated %{timeAgo}"
-msgstr ""
+msgstr "最後更新 %{timeAgo}"
msgid "RepositoriesAnalytics|Latest test coverage results"
-msgstr ""
+msgstr "最新測試覆蓋率çµæžœ"
msgid "RepositoriesAnalytics|Latest test coverage results for all projects in %{groupName} (excluding projects in subgroups)."
-msgstr ""
+msgstr "%{groupName} 中所有專案的最新測試覆蓋率çµæžœï¼ˆä¸åŒ…括å­ç¾¤çµ„中的專案)。"
msgid "RepositoriesAnalytics|No test coverage to display"
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„測試覆蓋率"
msgid "RepositoriesAnalytics|Please select a project or multiple projects to display their most recent test coverage data."
-msgstr ""
+msgstr "è«‹é¸æ“‡ä¸€å€‹å°ˆæ¡ˆæˆ–多個專案來顯示最近的測試覆蓋率資料。"
msgid "RepositoriesAnalytics|Please select projects to display."
-msgstr ""
+msgstr "è«‹é¸æ“‡è¦é¡¯ç¤ºçš„專案。"
msgid "RepositoriesAnalytics|Projects with Coverage"
-msgstr ""
+msgstr "覆蓋範åœå…§çš„專案"
msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
-msgstr ""
+msgstr "覆蓋範åœçš„專案: %{projectCount}"
msgid "RepositoriesAnalytics|Repositories Analytics"
-msgstr ""
+msgstr "版本庫分æž"
msgid "RepositoriesAnalytics|Test Code Coverage"
-msgstr ""
+msgstr "測試程å¼ç¢¼è¦†è“‹çŽ‡"
msgid "RepositoriesAnalytics|There was an error fetching the projects."
-msgstr ""
+msgstr "å–得專案時發生錯誤。"
msgid "Repository"
-msgstr ""
+msgstr "版本庫"
msgid "Repository Analytics"
-msgstr ""
+msgstr "版本庫分æž"
msgid "Repository Graph"
-msgstr ""
+msgstr "版本庫圖"
msgid "Repository Settings"
-msgstr ""
+msgstr "版本庫設定"
msgid "Repository already read-only"
-msgstr ""
+msgstr "版本庫已經是唯讀"
msgid "Repository by URL"
-msgstr ""
+msgstr "URL版本庫"
msgid "Repository check"
-msgstr ""
+msgstr "版本庫檢查"
msgid "Repository check was triggered."
-msgstr ""
+msgstr "已觸發版本庫檢查。"
msgid "Repository checks"
-msgstr ""
+msgstr "版本庫檢查"
msgid "Repository cleanup"
-msgstr ""
+msgstr "版本庫清ç†"
msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
-msgstr ""
+msgstr "版本庫清ç†å·²ç¶“開始。一旦清ç†å®Œæˆï¼Œæ‚¨å°‡æ”¶åˆ°ä¸€å°é›»å­éƒµä»¶ã€‚"
msgid "Repository clone URL"
-msgstr ""
+msgstr "版本庫仿製(clone)地å€"
msgid "Repository files count over the limit"
-msgstr ""
+msgstr "版本庫文件數超éŽé™åˆ¶"
msgid "Repository has an invalid default branch name."
-msgstr ""
+msgstr "版本庫有一個無效的é è¨­åˆ†æ”¯å稱。"
msgid "Repository has more than one branch."
-msgstr ""
+msgstr "版本庫有多個分支。"
msgid "Repository has no locks."
-msgstr ""
+msgstr "ç›®å‰ç‰ˆæœ¬åº«ç„¡åŠ éŽ–文件。"
msgid "Repository has tags."
-msgstr ""
+msgstr "版本庫有標籤。"
msgid "Repository maintenance"
-msgstr ""
+msgstr "版本庫維護"
msgid "Repository mirroring"
-msgstr ""
+msgstr "版本庫é¡åƒ"
msgid "Repository mirroring configuration"
-msgstr ""
+msgstr "版本庫é¡åƒè¨­å®š"
msgid "Repository must contain at least 1 file."
-msgstr ""
+msgstr "版本庫必須包å«è‡³å°‘1個文件。"
msgid "Repository size is above the limit."
-msgstr ""
+msgstr "版本庫大å°è¶…éŽé™åˆ¶ã€‚"
msgid "Repository size limit (MB)"
-msgstr ""
+msgstr "版本庫大å°é™åˆ¶ï¼ˆMB)"
msgid "Repository storage"
-msgstr ""
+msgstr "版本庫儲存"
msgid "Repository update events"
-msgstr ""
+msgstr "版本庫更新事件"
msgid "Repository usage recalculation started"
-msgstr ""
+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 ""
+msgstr "版本庫: %{counter_repositories} / Wikis: %{counter_wikis} / 構建產物: %{counter_build_artifacts} / æµæ°´ç·šç”¢ç‰©ï¼š%{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / 程å¼ç¢¼ç‰‡æ®µ: %{counter_snippets} / 軟體套件: %{counter_packages} / 上傳文件: %{counter_uploads}"
msgid "RepositorySettingsAccessLevel|Select"
-msgstr ""
+msgstr "é¸æ“‡"
msgid "Request"
-msgstr ""
+msgstr "請求"
msgid "Request Access"
-msgstr ""
+msgstr "申請權é™"
msgid "Request a new one"
-msgstr ""
-
-msgid "Request attention from %{users_sentence}."
-msgstr ""
-
-msgid "Request attention from assignee or reviewer"
-msgstr ""
-
-msgid "Request attention from assignee(s) or reviewer(s)"
-msgstr ""
+msgstr "請求一個新的"
msgid "Request data is too large"
-msgstr ""
+msgstr "請求的資料é‡å¤ªå¤§"
msgid "Request details"
-msgstr ""
+msgstr "請求詳情"
msgid "Request parameter %{param} is missing."
-msgstr ""
+msgstr "缺少請求åƒæ•¸ %{param}。"
msgid "Request review from"
-msgstr ""
+msgstr "請求審核來自"
msgid "Request time"
-msgstr ""
+msgstr "請求時間"
msgid "Request to link SAML account must be authorized"
-msgstr ""
+msgstr "連çµSAML帳號的請求必須經éŽæŽˆæ¬Š"
msgid "Requested"
-msgstr ""
+msgstr "已請求"
msgid "Requested %{time_ago}"
-msgstr ""
-
-msgid "Requested attention from %{users_sentence}."
-msgstr ""
-
-msgid "Requested attention from @%{username}"
-msgstr ""
-
-msgid "Requested attention from @%{username}. Your own attention request was removed."
-msgstr ""
+msgstr "請求的 %{time_ago}"
msgid "Requested design version does not exist."
-msgstr ""
+msgstr "請求的設計版本ä¸å­˜åœ¨."
msgid "Requested review"
-msgstr ""
-
-msgid "Requested review. Your attention request was removed."
-msgstr ""
+msgstr "請求審核"
msgid "Requested states are invalid"
-msgstr ""
+msgstr "請求的狀態無效"
msgid "Requests"
-msgstr ""
+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 ""
+msgstr "%{code_start}%{help_text_url}%{code_end} é é¢çš„請求é‡å®šå‘到 URL。目的地必須滿足æŸäº›è¦æ±‚。 %{docs_link_start}了解更多。%{docs_link_end}"
msgid "Requests per period"
-msgstr ""
+msgstr "æ¯å€‹é€±æœŸçš„請求"
msgid "Require additional authentication for administrative tasks."
-msgstr ""
+msgstr "需è¦å°ç®¡ç†ä»»å‹™é€²è¡Œé¡å¤–的身份驗證。"
msgid "Required approvals (%{approvals_given} given)"
-msgstr ""
+msgstr "å¿…è¦çš„核准(%{approvals_given}已完æˆ)"
msgid "Required approvals (%{approvals_given} given, you've approved)"
-msgstr ""
+msgstr "å¿…è¦çš„核准(%{approvals_given}完æˆï¼Œæ‚¨å·²æ ¸å‡†)"
msgid "Required in this project."
-msgstr ""
+msgstr "在此專案為必須。"
msgid "Required only if you are not using role instance credentials."
-msgstr ""
+msgstr "僅當您沒有使用角色實例憑據時æ‰éœ€è¦ã€‚"
msgid "Requirement"
-msgstr ""
+msgstr "需求"
msgid "Requirement %{reference} has been added"
-msgstr ""
+msgstr "需求%{reference}已加入"
msgid "Requirement %{reference} has been archived"
-msgstr ""
+msgstr "需求%{reference}已存檔"
msgid "Requirement %{reference} has been reopened"
-msgstr ""
+msgstr "需求%{reference}å·²é‡æ–°æ‰“é–‹"
msgid "Requirement %{reference} has been updated"
-msgstr ""
+msgstr "需求%{reference}已更新"
msgid "Requirement title cannot have more than %{limit} characters."
-msgstr ""
+msgstr "需求標題ä¸èƒ½è¶…éŽ%{limit}個字元。"
msgid "Requirements"
-msgstr ""
+msgstr "需求"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
-msgstr ""
+msgstr "需求å¯ä»¥åŸºæ–¼ä½¿ç”¨è€…ã€åˆ©ç›Šç›¸é—œè€…ã€ç³»çµ±ã€è»Ÿä»¶æˆ–您èªç‚ºé‡è¦çš„其他任何æ±è¥¿ã€‚"
msgid "Requires %d approval from eligible users."
msgid_plural "Requires %d approvals from eligible users."
-msgstr[0] ""
+msgstr[0] "需è¦%d個符åˆæ¢ä»¶çš„使用者的核准。"
msgid "Requires %{count} approval from %{names}."
msgid_plural "Requires %{count} approvals from %{names}."
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %{count} 個來自 %{names} 的核准。"
msgid "Requires values to meet regular expression requirements."
-msgstr ""
+msgstr "需è¦å€¼ç¬¦åˆæ­£å‰‡è¡¨é”å¼ã€‚"
msgid "Requires you to deploy or set up cloud-hosted Sentry."
-msgstr ""
+msgstr "需è¦æ‚¨éƒ¨ç½²æˆ–設定雲托管的 Sentry。"
msgid "Requires your primary GitLab email address."
-msgstr ""
+msgstr "需è¦æ‚¨çš„主GitLabé›»å­éƒµä»¶åœ°å€ã€‚"
msgid "Resend"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€"
msgid "Resend Request"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€è«‹æ±‚"
+
+msgid "Resend confirmation e-mail"
+msgstr "é‡æ–°å‚³é€é©—證信"
msgid "Resend confirmation email"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€ç¢ºèªéƒµä»¶"
msgid "Resend invite"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€é‚€è«‹"
msgid "Resend it"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€"
msgid "Resend unlock instructions"
-msgstr ""
+msgstr "é‡æ–°ç™¼é€è§£éŽ–說明"
msgid "Reset"
-msgstr ""
+msgstr "é‡è¨­"
msgid "Reset error tracking access token"
-msgstr ""
+msgstr "é‡è¨­éŒ¯èª¤è¿½è¸ªå­˜å–權æ–"
msgid "Reset file"
-msgstr ""
+msgstr "é‡è¨­æ–‡ä»¶"
msgid "Reset filters"
-msgstr ""
+msgstr "é‡è¨­éŽæ¿¾å™¨"
msgid "Reset health check access token"
-msgstr ""
+msgstr "é‡è¨­åŸ·è¡Œç‹€æ³æª¢æŸ¥å­˜å–權æ–"
msgid "Reset password"
-msgstr ""
+msgstr "é‡è¨­å¯†ç¢¼"
msgid "Reset registration token"
-msgstr ""
+msgstr "é‡è¨­è¨»å†Šä»¤ç‰Œ(權æ–)"
msgid "Reset template"
-msgstr ""
+msgstr "é‡è¨­ç¯„本"
msgid "Reset to project defaults"
-msgstr ""
+msgstr "é‡è¨­ç‚ºå°ˆæ¡ˆé è¨­å€¼"
msgid "Resolve"
-msgstr ""
+msgstr "解決"
msgid "Resolve conflicts"
-msgstr ""
+msgstr "解決è¡çª"
msgid "Resolve conflicts on source branch"
-msgstr ""
+msgstr "在來æºåˆ†æ”¯ä¸Šè§£æ±ºè¡çª"
msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
-msgstr ""
+msgstr "解決這些è¡çªæˆ–請具有版本庫寫入權é™çš„使用者在本地進行åˆä½µã€‚"
msgid "Resolve thread"
-msgstr ""
+msgstr "解決主題"
msgid "Resolved"
-msgstr ""
+msgstr "已解決"
msgid "Resolved 1 discussion."
-msgstr ""
+msgstr "已解決 1 個討論。"
msgid "Resolved all discussions."
-msgstr ""
+msgstr "已解決所有討論。"
msgid "Resolved by"
-msgstr ""
+msgstr "處ç†è€…"
msgid "Resolved by %{name}"
-msgstr ""
+msgstr "已由%{name}解決"
msgid "Response"
-msgstr ""
+msgstr "響應"
msgid "Response didn't include `service_desk_address`"
-msgstr ""
+msgstr "響應ä¸åŒ…括`service_desk_address`"
msgid "Response metrics (AWS ELB)"
-msgstr ""
+msgstr "響應指標(AWS ELB)"
msgid "Response metrics (Custom)"
-msgstr ""
+msgstr "響應指標(自訂)"
msgid "Response metrics (HA Proxy)"
-msgstr ""
+msgstr "響應指標(HA Proxy)"
msgid "Response metrics (NGINX Ingress VTS)"
-msgstr ""
+msgstr "響應指標(NGINX Ingress VTS)"
msgid "Response metrics (NGINX Ingress)"
-msgstr ""
+msgstr "響應指標(NGINX Ingress)"
msgid "Response metrics (NGINX)"
-msgstr ""
+msgstr "響應指標(NGINX)"
msgid "Response text"
-msgstr ""
+msgstr "響應文本"
msgid "Restart GitLab to apply changes."
-msgstr ""
+msgstr "é‡å•Ÿ GitLab 以套用更改。"
msgid "Restart Terminal"
-msgstr ""
+msgstr "é‡å•Ÿçµ‚端"
msgid "Restore"
-msgstr ""
+msgstr "復原"
msgid "Restore group"
-msgstr ""
+msgstr "復原群組"
msgid "Restore project"
-msgstr ""
+msgstr "復原專案"
msgid "Restoring projects"
-msgstr ""
+msgstr "專案復原中"
msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
-msgstr ""
+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 ""
+msgstr "復原該專案將防止專案在此日期被移除,並復原使用者å°å…¶é€²è¡Œè®Šæ›´çš„能力。"
msgid "Restrict access by IP address"
-msgstr ""
+msgstr "以 IP ä½å€ä¾†é™åˆ¶å­˜å–"
msgid "Restrict membership by email domain"
-msgstr ""
+msgstr "通éŽé›»å­éƒµä»¶åŸŸé™è£½æˆå“¡è³‡æ ¼"
msgid "Restrict projects for this runner"
-msgstr ""
+msgstr "é™åˆ¶ç”¨æ–¼é€™å€‹åŸ·è¡Œå™¨çš„專案"
msgid "Restricted shift times are not available for hourly shifts"
-msgstr ""
+msgstr "é™åˆ¶è¼ªç­æ™‚é–“ä¸é©ç”¨æ–¼æ¯å°æ™‚輪ç­"
msgid "Resume"
-msgstr ""
+msgstr "æ¢å¾©"
msgid "Resync"
-msgstr ""
+msgstr "é‡æ–°åŒæ­¥"
msgid "Retrieving the compliance report failed. Refresh the page and try again."
-msgstr ""
+msgstr "檢索åˆè¦æ€§å ±å‘Šå¤±æ•—。請é‡æ–°æ•´ç†é é¢ä¸¦é‡è©¦ã€‚"
msgid "Retry"
-msgstr ""
+msgstr "é‡è©¦"
-msgid "Retry downstream pipeline"
-msgstr ""
+msgid "Retry all failed or cancelled jobs"
+msgstr "é‡è©¦æ‰€æœ‰å¤±æ•—或å–消的作業"
-msgid "Retry failed jobs"
-msgstr ""
+msgid "Retry downstream pipeline"
+msgstr "é‡è©¦ä¸‹æ¸¸æµæ°´ç·š"
msgid "Retry job"
-msgstr ""
+msgstr "é‡è©¦ä½œæ¥­"
msgid "Retry migration"
-msgstr ""
+msgstr "é‡è©¦é·ç§»"
msgid "Retry this job"
-msgstr ""
+msgstr "é‡è©¦ç•¶å‰ä½œæ¥­"
msgid "Retry this job in order to create the necessary resources."
-msgstr ""
+msgstr "é‡è©¦æ­¤ä½œæ¥­ä»¥å»ºç«‹å¿…è¦çš„資æºã€‚"
msgid "Retry verification"
-msgstr ""
+msgstr "é‡è©¦é©—è­‰"
msgid "Reveal value"
msgid_plural "Reveal values"
-msgstr[0] ""
+msgstr[0] "顯示值"
msgid "Reveal values"
-msgstr ""
+msgstr "顯示值"
msgid "Revert this commit"
-msgstr ""
+msgstr "還原此æ交"
msgid "Revert this merge request"
-msgstr ""
+msgstr "還原此åˆä½µè«‹æ±‚"
msgid "Review"
-msgstr ""
+msgstr "檢閱"
msgid "Review App|View app"
-msgstr ""
+msgstr "檢視 App"
msgid "Review App|View latest app"
-msgstr ""
+msgstr "檢視最新版 App"
msgid "Review changes"
-msgstr ""
+msgstr "檢視更動"
msgid "Review requests for you"
-msgstr ""
+msgstr "您的審核請求"
msgid "Review the changes locally."
-msgstr ""
+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 ""
+msgstr "查看在您的身份驗證æ供商中設定æœå‹™æ供商的æµç¨‹ - 在這裡,GitLab是「æœå‹™æ供商ã€æˆ–「ä¾è³´æ–¹ã€ã€‚"
msgid "Review the target project before submitting to avoid exposing %{source} changes."
-msgstr ""
+msgstr "在æ交å‰å¯©æŸ¥ç›®æ¨™å°ˆæ¡ˆï¼Œä»¥é¿å…暴露 %{source} 的更改。"
msgid "Review time"
-msgstr ""
+msgstr "檢視時間"
msgid "Review time is defined as the time it takes from first comment until merged."
-msgstr ""
+msgstr "檢視時間的定義是自第一次留言到åˆä½µæ‰€èŠ±çš„時間。"
msgid "ReviewApp|Enable Review App"
-msgstr ""
+msgstr "啟用審閱應用程å¼"
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] ""
+msgstr[0] "%dä½å¯©é–±è€…"
msgid "Reviewer(s)"
-msgstr ""
+msgstr "審閱者"
msgid "Reviewers"
-msgstr ""
+msgstr "審閱者"
msgid "Reviewing"
-msgstr ""
+msgstr "審閱中"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "審閱(åˆä½µè«‹æ±‚ !%{mergeRequestId})"
msgid "Revoke"
-msgstr ""
+msgstr "撤銷"
msgid "Revoked"
-msgstr ""
+msgstr "已撤銷"
msgid "Revoked access token %{access_token_name}!"
-msgstr ""
+msgstr "已撤銷存å–令牌 %{access_token_name}ï¼"
msgid "Revoked impersonation token %{token_name}!"
-msgstr ""
+msgstr "已撤銷身份模擬令牌 %{token_name}ï¼"
msgid "Revoked personal access token %{personal_access_token_name}!"
-msgstr ""
+msgstr "已撤銷個人存å–令牌 %{personal_access_token_name}ï¼"
msgid "RightSidebar|Copy email address"
-msgstr ""
+msgstr "複製電å­éƒµä»¶åœ°å€"
msgid "RightSidebar|Issue email"
-msgstr ""
-
-msgid "RightSidebar|adding a"
-msgstr ""
-
-msgid "RightSidebar|deleting the"
-msgstr ""
+msgstr "郵件地å€"
msgid "Roadmap"
-msgstr ""
+msgstr "路線圖"
msgid "Roadmap settings"
-msgstr ""
+msgstr "路線圖設定"
msgid "Roadmap view"
-msgstr ""
+msgstr "路線視圖"
msgid "Role"
-msgstr ""
+msgstr "角色"
msgid "Rollback"
-msgstr ""
+msgstr "還原"
msgid "Ruby"
-msgstr ""
+msgstr "Ruby"
msgid "Rule name is already taken."
-msgstr ""
+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 ""
+msgstr "定義此群組中專案所接å—çš„git推é€è¦å‰‡ã€‚此群組中所有新建立的專案都將使用這些設定。"
msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
-msgstr ""
+msgstr "定義專案所接å—çš„git推é€è¦å‰‡ã€‚所有新建立的專案都將使用這些設定。"
msgid "Run %{code_start}git fsck%{code_end} periodically in all project and wiki repositories to look for silent disk corruption issues."
-msgstr ""
+msgstr "在所有專案和 wiki 儲存庫中定期執行 %{code_start}git fsck%{code_end}"
msgid "Run CI/CD pipelines for external repositories"
-msgstr ""
+msgstr "使用外部版本庫的CI/CDæµæ°´ç·š"
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 "當您推é€åˆ°ç‰ˆæœ¬åº«æ™‚,或者當一個åˆä½µè«‹æ±‚被建立ã€æ›´æ–°æˆ–åˆä½µæ™‚,使用 Jenkins 執行CI/CD æµæ°´ç·šã€‚ %{docs_link}"
msgid "Run CI/CD pipelines with Jenkins."
-msgstr ""
+msgstr "使用 Jenkins 執行 CI/CD æµæ°´ç·šã€‚"
msgid "Run housekeeping"
-msgstr ""
+msgstr "執行例行維護"
msgid "Run manual or delayed jobs"
-msgstr ""
+msgstr "執行手動或延é²çš„作業"
msgid "Run tests against your code live using the Web Terminal"
-msgstr ""
+msgstr "使用Web終端å°æ‚¨çš„程å¼ç¢¼é€²è¡Œå¯¦æ™‚測試"
msgid "Run untagged jobs"
-msgstr ""
+msgstr "執行未標記的作業"
msgid "Runner"
-msgstr ""
+msgstr "執行器(runner)"
msgid "Runner API"
-msgstr ""
+msgstr "執行器 API"
msgid "Runner tokens"
-msgstr ""
+msgstr "執行器令牌(權æ–)"
msgid "Runner was not updated."
-msgstr ""
+msgstr "Runner未更新。"
msgid "Runner was successfully updated."
-msgstr ""
+msgstr "Runner å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "Runners"
-msgstr ""
+msgstr "執行器(Runners)"
msgid "Runners are processes that pick up and execute CI/CD jobs for GitLab."
-msgstr ""
+msgstr "執行器是å”助 GitLab 挑é¸å’ŒåŸ·è¡Œ CI/CD 作業的程åºã€‚"
msgid "Runners page."
-msgstr ""
+msgstr "執行器(Runners)é é¢."
+
+msgid "Runners|%d selected runner deleted"
+msgid_plural "Runners|%d selected runners deleted"
+msgstr[0] "已刪除 %d 個é¸å®šçš„執行器"
msgid "Runners|%{percentage} spot."
-msgstr ""
+msgstr "%{percentage}點。"
msgid "Runners|%{strongStart}%{count}%{strongEnd} runner selected"
msgid_plural "Runners|%{strongStart}%{count}%{strongEnd} runners selected"
-msgstr[0] ""
+msgstr[0] "%{strongStart}%{count}%{strongEnd} 個執行器(runner)å·²é¸æ“‡"
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[0] "%{strongStart}%{count}%{strongEnd} 個執行器(runner)將被永久刪除,ä¸å†é©ç”¨æ–¼å°ˆæ¡ˆæˆ–群組。您確定è¦ç¹¼çºŒå—Žï¼Ÿ"
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 ""
+msgstr "1的容é‡å¯ä»¥é€šéŽè‡ªå‹•ç¸®æ”¾ç¾¤çµ„é‡æ–°ç”¢ç”Ÿ warm HA。容é‡ç‚º 2,啟用 hot HA,因為å³ä½¿ç¯€é»žä¸Ÿå¤±ï¼Œè©²æœå‹™ä¹Ÿå¯ç”¨ã€‚容é‡ç‚º 3 個或更多,啟用 hot HA 和手動擴展執行器(runner)佇列。"
msgid "Runners|A new version is available"
-msgstr ""
+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 ""
+msgstr "定期後å°ä»»å‹™æœƒåˆªé™¤è¶…éŽ %{elapsedTime} 未è¯ç¹« GitLab 的執行器。 %{linkStart}我å¯ä»¥æŸ¥çœ‹åˆªé™¤äº†å¤šå°‘執行器嗎?%{linkEnd}"
msgid "Runners|Active"
-msgstr ""
+msgstr "啟用"
msgid "Runners|Add notes, like who owns the runner or what it should be used for."
-msgstr ""
+msgstr "增加註釋,例如執行器的æ“有者或執行器的用途。"
msgid "Runners|All"
-msgstr ""
+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 ""
+msgstr "è¶…éŽ %{elapsedTime} 未è¯ç¹« GitLab 的所有群組執行器將被永久刪除。此任務在後å°å®šæœŸåŸ·è¡Œã€‚"
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
-msgstr ""
+msgstr "Amazon Linux 2 Docker HA 具有手動縮放和å¯é¸çš„排程。 %{percentage} spot。"
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. Non-spot."
-msgstr ""
+msgstr "Amazon Linux 2 Docker HA 具有手動縮放和å¯é¸çš„排程。Non-spot。"
msgid "Runners|An error has occurred fetching instructions"
-msgstr ""
+msgstr "å–得指令時發生錯誤"
msgid "Runners|Architecture"
-msgstr ""
+msgstr "架構"
msgid "Runners|Assigned Group"
-msgstr ""
+msgstr "指派的群組"
msgid "Runners|Assigned Projects (%{projectCount})"
-msgstr ""
+msgstr "指派的專案(%{projectCount})"
msgid "Runners|Associated with one or more projects"
-msgstr ""
+msgstr "與一個或多個專案有關è¯"
+
+msgid "Runners|Available"
+msgstr "å¯ç”¨æ€§"
msgid "Runners|Available to all projects"
-msgstr ""
+msgstr "é©ç”¨æ–¼æ‰€æœ‰å°ˆæ¡ˆ"
msgid "Runners|Available to all projects and subgroups in the group"
-msgstr ""
+msgstr "é©ç”¨æ–¼ç¾¤çµ„中的所有專案和å­å°ˆæ¡ˆ"
msgid "Runners|Can run untagged jobs"
-msgstr ""
+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 ""
+msgstr "容é‡ç‚º 1,通éŽè‡ªå‹•æ“´å±•çµ„é‡æ–°ç”Ÿæˆå•Ÿç”¨ warm HA。容é‡ç‚º 2,啟用 hot HA,因為å³ä½¿ç¯€é»žä¸Ÿå¤±ï¼Œè©²æœå‹™ä¹Ÿå¯ç”¨ã€‚容é‡ç‚º 3 個或更多,啟用 warm HA 和手動擴展執行器(runner)佇列。"
msgid "Runners|Checkbox"
-msgstr ""
+msgstr "複é¸æ¡†"
msgid "Runners|Choose your preferred GitLab Runner"
-msgstr ""
+msgstr "é¸æ“‡æ‚¨å–œæ­¡çš„GitLab執行器"
msgid "Runners|Clear selection"
-msgstr ""
+msgstr "清除é¸æ“‡"
msgid "Runners|Command to register runner"
-msgstr ""
+msgstr "註冊執行器的指令"
msgid "Runners|Configuration"
-msgstr ""
+msgstr "設定"
msgid "Runners|Copy instructions"
-msgstr ""
+msgstr "複製說明"
msgid "Runners|Copy registration token"
-msgstr ""
+msgstr "複製註冊令牌(權æ–)"
msgid "Runners|Delete %d runner"
msgid_plural "Runners|Delete %d runners"
-msgstr[0] ""
+msgstr[0] "刪除 %d 個 執行器(runner)"
msgid "Runners|Delete runner"
-msgstr ""
+msgstr "刪除執行器"
msgid "Runners|Delete runner %{name}?"
-msgstr ""
+msgstr "刪除%{name}執行器?"
msgid "Runners|Delete selected"
-msgstr ""
+msgstr "刪除已é¸å–"
msgid "Runners|Deploy GitLab Runner in AWS"
-msgstr ""
+msgstr "在AWS中部署GitLab執行器(Runner)"
msgid "Runners|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "Runners|Details"
-msgstr ""
+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 ""
+msgstr "沒有看到您è¦æŸ¥æ‰¾çš„內容?%{linkStart}here%{linkEnd} 查看完整的é¸é …列表,包括完全å¯è‡ªå®šç¾©çš„é¸é …。"
msgid "Runners|Download and install binary"
-msgstr ""
+msgstr "下載並安è£äºŒé€²ä½æª”案"
msgid "Runners|Download latest binary"
-msgstr ""
+msgstr "下載最新的二進ä½æª”案"
msgid "Runners|Edit your search and try again"
-msgstr ""
+msgstr "編輯您的查詢並且é‡è©¦"
msgid "Runners|Enable stale runner cleanup"
-msgstr ""
+msgstr "啟用éŽæ™‚的執行器清ç†"
msgid "Runners|Enable stale runner cleanup?"
-msgstr ""
+msgstr "啟用éŽæ™‚的執行器清ç†?"
msgid "Runners|Enter the number of seconds. This timeout takes precedence over lower timeouts set for the project."
-msgstr ""
+msgstr "輸入秒數。此逾時優先於為專案設定的較低逾時。"
msgid "Runners|Executor"
-msgstr ""
+msgstr "執行者"
msgid "Runners|Get started with runners"
-msgstr ""
+msgstr "執行器入門"
msgid "Runners|Group"
-msgstr ""
+msgstr "群組"
msgid "Runners|How do we upgrade GitLab runner?"
-msgstr ""
+msgstr "如何å‡ç´š GitLab 執行器?"
msgid "Runners|IP Address"
-msgstr ""
+msgstr "IP ä½å€"
msgid "Runners|Install a runner"
-msgstr ""
+msgstr "安è£åŸ·è¡Œå™¨"
msgid "Runners|Instance"
-msgstr ""
+msgstr "實例"
msgid "Runners|Jobs"
-msgstr ""
+msgstr "作業"
msgid "Runners|Last contact"
-msgstr ""
+msgstr "最後一次è¯çµ¡"
msgid "Runners|Locked to this project"
-msgstr ""
+msgstr "已鎖定此專案"
msgid "Runners|Maintenance note"
-msgstr ""
+msgstr "維護說明"
msgid "Runners|Maximum job timeout"
-msgstr ""
+msgstr "作業逾時最大值"
msgid "Runners|Members of the %{type} can register runners"
-msgstr ""
+msgstr "%{type}的會員å¯ä»¥è¨»å†ŠåŸ·è¡Œå™¨"
msgid "Runners|Multi-project runners cannot be deleted"
-msgstr ""
+msgstr "無法刪除多專案執行器"
msgid "Runners|Name"
-msgstr ""
+msgstr "å稱"
msgid "Runners|Never contacted"
-msgstr ""
+msgstr "從未連接éŽ"
msgid "Runners|Never contacted:"
-msgstr ""
+msgstr "從未連接éŽ:"
msgid "Runners|New group runners view"
-msgstr ""
+msgstr "新的群組執行器視圖"
msgid "Runners|New registration token generated!"
-msgstr ""
+msgstr "已產生新的註冊令牌(權æ–)ï¼"
msgid "Runners|No results found"
-msgstr ""
+msgstr "未找到çµæžœ"
msgid "Runners|No spot. Default choice for Windows Shell executor."
-msgstr ""
+msgstr "未發ç¾ã€‚Windows Shell executor çš„é è¨­é¸æ“‡ã€‚"
msgid "Runners|No spot. This is the default choice for Linux Docker executor."
-msgstr ""
+msgstr "沒有發ç¾ã€‚這是 Linux Docker 執行器的é è¨­é¸æ“‡ã€‚"
msgid "Runners|Not accepting jobs"
-msgstr ""
+msgstr "ä¸æŽ¥å—作業"
msgid "Runners|Offline"
-msgstr ""
+msgstr "離線"
msgid "Runners|Offline runners"
-msgstr ""
+msgstr "離線執行器"
msgid "Runners|Offline:"
-msgstr ""
+msgstr "離線:"
msgid "Runners|Online"
-msgstr ""
+msgstr "在線"
msgid "Runners|Online runners"
-msgstr ""
+msgstr "在線執行器"
msgid "Runners|Online:"
-msgstr ""
+msgstr "在線:"
+
+msgid "Runners|Outdated"
+msgstr "å·²éŽæ™‚"
msgid "Runners|Pause from accepting jobs"
-msgstr ""
+msgstr "æš«åœæŽ¥å—作業"
msgid "Runners|Paused"
-msgstr ""
+msgstr "已暫åœ"
msgid "Runners|Permanently delete %d runner"
msgid_plural "Runners|Permanently delete %d runners"
-msgstr[0] ""
+msgstr[0] "永久刪除 %d 個 runner"
msgid "Runners|Platform"
-msgstr ""
+msgstr "å¹³å°"
msgid "Runners|Project"
-msgstr ""
+msgstr "專案"
msgid "Runners|Property Name"
-msgstr ""
+msgstr "屬性å稱"
msgid "Runners|Protected"
-msgstr ""
+msgstr "å—ä¿è­·"
+
+msgid "Runners|Recommended"
+msgstr "推薦"
msgid "Runners|Register a group runner"
-msgstr ""
+msgstr "註冊一個群組執行器(runner)"
msgid "Runners|Register a project runner"
-msgstr ""
+msgstr "註冊專案執行器(runner)"
msgid "Runners|Register a runner"
-msgstr ""
+msgstr "註冊執行器(runner)"
msgid "Runners|Register an instance runner"
-msgstr ""
+msgstr "註冊一個實例執行器(runner)"
msgid "Runners|Registration token"
-msgstr ""
+msgstr "註冊令牌(權æ–)"
msgid "Runners|Registration token copied!"
-msgstr ""
+msgstr "已複製註冊令牌ï¼"
msgid "Runners|Reset token"
-msgstr ""
+msgstr "é‡è¨­ä»¤ç‰Œ(權æ–)"
msgid "Runners|Resume accepting jobs"
-msgstr ""
+msgstr "æ¢å¾©æŽ¥å—作業"
msgid "Runners|Revision"
-msgstr ""
+msgstr "修訂版本"
msgid "Runners|Runner"
-msgstr ""
+msgstr "執行器(Runner)"
msgid "Runners|Runner #%{runner_id}"
-msgstr ""
+msgstr "執行器 #%{runner_id}"
msgid "Runners|Runner %{name} was deleted"
-msgstr ""
+msgstr "%{name} 執行器已刪除"
msgid "Runners|Runner assigned to project."
-msgstr ""
+msgstr "指派給專案的執行器。"
msgid "Runners|Runner cannot be deleted, please contact your administrator"
-msgstr ""
+msgstr "執行器(Runner)無法刪除,請è¯çµ¡æ‚¨çš„管ç†å“¡ã€‚"
msgid "Runners|Runner has contacted GitLab within the last %{elapsedTime}"
-msgstr ""
+msgstr "在最近 %{elapsedTime} 內,執行器(Runner)é€£æŽ¥éŽ GitLab"
msgid "Runners|Runner has never contacted GitLab (when you register a runner, use %{codeStart}gitlab-runner run%{codeEnd} to bring it online)"
-msgstr ""
+msgstr "執行器(Runner)從未連接éŽGitLab(註冊執行器(Runner)時使用 %{codeStart}gitlab-runner run%{codeEnd} 將其上線)"
msgid "Runners|Runner has never contacted this instance"
-msgstr ""
+msgstr "執行器(Runner)從未連接到此實例"
msgid "Runners|Runner has not contacted GitLab in more than %{elapsedTime}"
-msgstr ""
+msgstr "è¶…éŽ %{elapsedTime} 的時間,執行器(Runner)æœªé€£æŽ¥éŽ GitLab"
msgid "Runners|Runner is locked and available for currently assigned projects only. Only administrators can change the assigned projects."
-msgstr ""
+msgstr "執行器(Runner)已被鎖定,僅供當å‰æŒ‡æ´¾çš„專案使用。åªæœ‰ç®¡ç†å“¡å¯ä»¥æ›´æ”¹æŒ‡æ´¾çš„專案。"
msgid "Runners|Runner is offline; last contact was %{runner_contact} ago"
-msgstr ""
+msgstr "執行器(Runner)處於離線狀態;最後連接是在%{runner_contact}å‰"
msgid "Runners|Runner is offline; last contact was %{timeAgo}"
-msgstr ""
+msgstr "執行器(Runner)處於離線狀態,最後連接是在%{timeAgo}"
msgid "Runners|Runner is online; last contact was %{runner_contact} ago"
-msgstr ""
+msgstr "執行器(Runner)處於上線狀態,最後連接是在%{runner_contact}å‰"
msgid "Runners|Runner is online; last contact was %{timeAgo}"
-msgstr ""
+msgstr "執行器處於上線狀態,上次è¯ç¹«æ˜¯ %{timeAgo} å¹´å‰"
msgid "Runners|Runner is stale; it has never contacted this instance"
-msgstr ""
+msgstr "執行器(Runner)是éŽæœŸçš„;它從未連接éŽé€™å€‹å¯¦ä¾‹"
msgid "Runners|Runner is stale; last contact was %{runner_contact} ago"
-msgstr ""
+msgstr "執行器(Runner)是éŽæœŸçš„;最後一次連接是在 %{runner_contact} å‰"
msgid "Runners|Runner is stale; last contact was %{timeAgo}"
-msgstr ""
+msgstr "執行器(Runner)是éŽæœŸçš„;最後一次連接是在 %{timeAgo}"
msgid "Runners|Runner registration"
-msgstr ""
+msgstr "執行器(Runner)註冊"
msgid "Runners|Runner statuses"
-msgstr ""
+msgstr "執行器(Runner)狀態"
msgid "Runners|Runner unassigned from project."
-msgstr ""
+msgstr "å–消指派到專案的執行器(Runner)。"
msgid "Runners|Runners"
-msgstr ""
+msgstr "執行器(Runners)"
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 "執行器是é‹è¡Œ CI/CD 作業的代ç†ã€‚按照%{linkStart}安è£å’Œè¨»å†Šèªªæ˜Ž%{linkEnd}來設定執行器。"
msgid "Runners|Runs untagged jobs"
-msgstr ""
+msgstr "執行未被標籤的作業"
msgid "Runners|Select projects to assign to this runner"
-msgstr ""
+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 ""
+msgstr "執行器|在此處é¸æ“‡æ‚¨çš„首è¦é¸é …。在下一步中,您å¯ä»¥åœ¨ AWS CloudFormation 控制å°ä¸­ç‚ºæ‚¨çš„執行器(runner)é¸æ“‡å®¹é‡ã€‚"
msgid "Runners|Show runner installation and registration instructions"
-msgstr ""
+msgstr "顯示執行器(runner)安è£å’Œè¨»å†Šèªªæ˜Ž"
msgid "Runners|Show runner installation instructions"
-msgstr ""
+msgstr "顯示執行器(runner)安è£èªªæ˜Ž"
+
+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 ""
+msgstr "å–得執行器(runner)資料時出ç¾å•é¡Œã€‚"
msgid "Runners|Something went wrong while fetching the tags suggestions"
-msgstr ""
+msgstr "å–得標籤建議時出ç¾å•é¡Œ"
msgid "Runners|Stale"
-msgstr ""
+msgstr "éŽæœŸ"
msgid "Runners|Stale runners"
-msgstr ""
+msgstr "éŽæœŸçš„執行器(runners)"
msgid "Runners|Stale:"
-msgstr ""
+msgstr "éŽæœŸï¼š"
msgid "Runners|Status"
-msgstr ""
+msgstr "狀態"
msgid "Runners|Stop the runner from accepting new jobs."
-msgstr ""
+msgstr "åœæ­¢åŸ·è¡Œå™¨(runner)接å—新的作業。"
msgid "Runners|Tags"
-msgstr ""
+msgstr "標籤"
msgid "Runners|Take me there!"
-msgstr ""
+msgstr "帶我到那裡ï¼"
msgid "Runners|The new view gives you more space and better visibility into your fleet of runners."
-msgstr ""
+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 ""
+msgstr "執行器(runner)將被永久刪除,ä¸èƒ½å¤ å†ç”¨æ–¼å¯¦ä¾‹ä¸­çš„專案或群組。您確定è¦ç¹¼çºŒå—Žï¼Ÿ"
msgid "Runners|This group currently has 1 stale runner."
msgid_plural "Runners|This group currently has %d stale runners."
-msgstr[0] ""
+msgstr[0] "該群組目å‰æœ‰ %d 個éŽæ™‚的執行器。"
msgid "Runners|This group currently has no stale runners."
-msgstr ""
+msgstr "該群組目å‰æ²’有éŽæ™‚的執行器。"
msgid "Runners|This runner has not run any jobs."
-msgstr ""
+msgstr "此執行器(runner)沒有執行任何作業。"
msgid "Runners|This runner is associated with specific projects."
-msgstr ""
+msgstr "該執行器(runner)與特定專案相關è¯ã€‚"
msgid "Runners|This runner is available to all projects and subgroups in a group."
-msgstr ""
+msgstr "這個執行器(runner)å¯ç”¨æ–¼ç¾¤çµ„中的所有專案和å­å°ˆæ¡ˆ."
msgid "Runners|This runner is outdated, an upgrade is recommended"
-msgstr ""
+msgstr "該執行器已éŽæœŸï¼Œå»ºè­°é€²è¡Œå‡ç´š"
msgid "Runners|To install Runner in Kubernetes follow the instructions described in the GitLab documentation."
-msgstr ""
+msgstr "è¦åœ¨ Kubernetes 中安è£åŸ·è¡Œå™¨åŸ·è¡Œå™¨(runner),請按照 GitLab 的說明文件進行æ“作。"
msgid "Runners|To install Runner in a container follow the instructions described in the GitLab documentation"
-msgstr ""
+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|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 Runner 以符åˆæ‚¨æ­£åœ¨é‹è¡Œçš„ GitLab 版本。 %{linkStart} 主è¦å’Œæ¬¡è¦ç‰ˆæœ¬%{linkEnd} 二者應該相符åˆã€‚"
+
+msgid "Runners|Upgrade Status"
+msgstr "å‡ç´šç‹€æ…‹"
msgid "Runners|Upgrade available"
-msgstr ""
+msgstr "å¯ç”¨å‡ç´š"
msgid "Runners|Upgrade recommended"
-msgstr ""
+msgstr "建議å‡ç´š"
msgid "Runners|Use Group runners when you want all projects in a group to have access to a set of runners."
-msgstr ""
+msgstr "如果您希望群組中的所有專案都å¯ä»¥å­˜å–一組執行器(runner),請使用群組執行器。"
msgid "Runners|Use the runner for jobs without tags, in addition to tagged jobs."
-msgstr ""
+msgstr "除了帶標籤的作業外,還å¯ä»¥å°‡åŸ·è¡Œå™¨(runner)用於沒有標籤的作業。"
msgid "Runners|Use the runner for the currently assigned projects only. Only administrators can change the assigned projects."
-msgstr ""
+msgstr "僅將執行器(runner)用於當å‰æŒ‡æ´¾çš„專案。åªæœ‰ç®¡ç†å“¡å¯ä»¥æ›´æ”¹æŒ‡æ´¾çš„專案。"
msgid "Runners|Use the runner on pipelines for protected branches only."
-msgstr ""
+msgstr "僅在å—ä¿è­·åˆ†æ”¯çš„æµæ°´ç·šä¸Šä½¿ç”¨åŸ·è¡Œå™¨(runner)。"
msgid "Runners|Value"
-msgstr ""
+msgstr "值"
msgid "Runners|Version"
-msgstr ""
+msgstr "版本"
msgid "Runners|View installation instructions"
-msgstr ""
+msgstr "檢視安è£èªªæ˜Ž"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
-msgstr ""
+msgstr "Windows 2019 Shell,具有手動縮放和å¯é¸æŽ’程的功能。 %{percentage} 點。"
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. Non-spot."
-msgstr ""
+msgstr "具有手動縮放和å¯é¸æŽ’程功能的 Windows 2019 Shell。Non-spot。"
msgid "Runners|Yes, start deleting stale runners"
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥è¨­å®šä¸€å€‹ç‰¹å®šçš„執行器(runner)供多個專案使用,但您ä¸èƒ½å°‡å…¶è¨­ç‚ºå…±äº«åŸ·è¡Œå™¨ã€‚"
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
-msgstr ""
+msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´ç·šæ™‚é–“é…é¡é™åˆ¶ï¼ˆ%{quotaLimit} )。"
msgid "Runners|active"
-msgstr ""
+msgstr "啟用"
+
+msgid "Runners|available"
+msgstr "å¯ç”¨çš„"
msgid "Runners|group"
-msgstr ""
+msgstr "群組"
msgid "Runners|never contacted"
-msgstr ""
+msgstr "從未連接éŽ"
msgid "Runners|offline"
-msgstr ""
+msgstr "離線"
msgid "Runners|online"
-msgstr ""
+msgstr "在線"
msgid "Runners|paused"
-msgstr ""
+msgstr "æš«åœ"
+
+msgid "Runners|recommended"
+msgstr "推薦的"
msgid "Runners|shared"
-msgstr ""
+msgstr "共用"
msgid "Runners|specific"
-msgstr ""
+msgstr "特定"
msgid "Runners|stale"
-msgstr ""
+msgstr "éŽæœŸ"
msgid "Runners|upgrade available"
-msgstr ""
+msgstr "å¯ç”¨å‡ç´š"
msgid "Runners|upgrade recommended"
-msgstr ""
+msgstr "建議å‡ç´š"
+
+msgid "Runner|Owner"
+msgstr "所有者"
msgid "Running"
-msgstr ""
+msgstr "執行中"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
-msgstr ""
+msgstr "在目å‰ç‰ˆæœ¬åº«ä¸­åŸ·è¡Œä¸€äº›ä¾‹è¡Œç¶­è­·ä½œæ¥­ï¼Œä¾‹å¦‚壓縮文件修訂和刪除無法存å–的物件。"
msgid "SAML"
-msgstr ""
+msgstr "SAML"
msgid "SAML SSO"
-msgstr ""
+msgstr "SAML SSO(單點登入)"
msgid "SAML SSO for %{group_name}"
-msgstr ""
+msgstr "群組%{group_name} 的 SAML SSO"
msgid "SAML discovery tokens"
-msgstr ""
+msgstr "SAML探索令牌(權æ–)"
msgid "SAML for %{group_name}"
-msgstr ""
+msgstr "%{group_name} çš„ SAML"
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}\" å…許您使用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 "è¦å­˜å–“%{group_name}â€ï¼Œæ‚¨å¿…須使用單點登入帳號通éŽå¤–部登入é é¢ç™»å…¥ã€‚"
msgid "SAML|Your organization's SSO has been connected to your GitLab account"
-msgstr ""
+msgstr "您組織的 SSO 已連接到您的 GitLab 帳號"
msgid "SAST Configuration"
-msgstr ""
+msgstr "SAST設定"
msgid "SHA256"
-msgstr ""
+msgstr "SHA256"
+
+msgid "SSH Fingerprints"
+msgstr "SSH 指紋"
msgid "SSH Key"
-msgstr ""
+msgstr "SSH金鑰"
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 "SSH 指紋驗證客戶端是å¦é€£çµåˆ°æ­£ç¢ºçš„主機。檢查 %{config_link_start}ç›®å‰å¯¦ä¾‹çš„設定 %{config_link_end}"
msgid "SSH host key fingerprints"
-msgstr ""
+msgstr "SSH主機金鑰指紋"
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 ""
+msgstr "SSH主機金鑰在此系統上ä¸å¯ç”¨ã€‚請使用%{ssh_keyscan}指令或與您的GitLab管ç†å“¡è¯çµ¡ä»¥å–得更多訊æ¯ã€‚"
msgid "SSH key"
-msgstr ""
+msgstr "SSH金鑰"
msgid "SSH keys"
-msgstr ""
+msgstr "SSH 金鑰"
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
-msgstr ""
+msgstr "SSH金鑰用於在您的電腦和GitLab建立安全連接。"
msgid "SSH keys with the following fingerprints are scheduled to expire soon. Expired SSH keys can not be used:"
-msgstr ""
+msgstr "具有以下指紋的 SSH 金鑰計劃很快到期。éŽæœŸçš„ SSH 金鑰ä¸èƒ½ä½¿ç”¨ï¼š"
msgid "SSH keys with the following fingerprints have expired and can no longer be used:"
-msgstr ""
+msgstr "具有以下指紋的 SSH 金鑰已éŽæœŸï¼Œç„¡æ³•å†ä½¿ç”¨ï¼š"
msgid "SSH public key"
-msgstr ""
+msgstr "SSH公鑰"
msgid "SSL Verification:"
-msgstr ""
+msgstr "SSL驗證:"
msgid "SSL verification"
-msgstr ""
+msgstr "SSL é©—è­‰"
msgid "Satisfied"
-msgstr ""
+msgstr "滿æ„"
msgid "Saturday"
-msgstr ""
+msgstr "星期六"
msgid "Save"
-msgstr ""
+msgstr "儲存"
msgid "Save %{name} size limits"
-msgstr ""
+msgstr "儲存%{name}大å°é™åˆ¶"
msgid "Save Changes"
-msgstr ""
+msgstr "儲存變更"
msgid "Save application"
-msgstr ""
+msgstr "儲存應用"
msgid "Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "Save changes before testing"
-msgstr ""
+msgstr "測試å‰å„²å­˜è®Šæ›´"
msgid "Save comment"
-msgstr ""
+msgstr "儲存留言"
msgid "Save deploy freeze"
-msgstr ""
+msgstr "儲存å‡çµéƒ¨ç½²"
msgid "Save internal note"
-msgstr ""
+msgstr "ä¿å­˜å…§éƒ¨è¨»é‡‹"
msgid "Save password"
-msgstr ""
+msgstr "儲存密碼"
msgid "Save pipeline schedule"
-msgstr ""
+msgstr "儲存æµæ°´ç·šè¨ˆåŠƒ"
msgid "Saving"
-msgstr ""
+msgstr "儲存中"
msgid "Saving project."
-msgstr ""
+msgstr "正在儲存專案。"
+
+msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
+msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{rules} 用於 %{branches} 分支"
+
+msgid "ScanExecutionPolicy|A pipeline is run"
+msgstr "æµæ°´ç·šåŸ·è¡Œä¸­"
+
+msgid "ScanExecutionPolicy|Schedule"
+msgstr "排程"
+
+msgid "ScanExecutionPolicy|Schedule rule component"
+msgstr "排程è¦å‰‡å…ƒä»¶"
+
+msgid "ScanExecutionPolicy|Select branches"
+msgstr "é¸æ“‡åˆ†æ”¯"
msgid "ScanResultPolicy|%{ifLabelStart}if%{ifLabelEnd} %{scanners} find(s) more than %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} vulnerabilities in an open merge request targeting %{branches}"
-msgstr ""
+msgstr "%{ifLabelStart}如果%{ifLabelEnd} %{scanners} 在é‡å° %{branches} 的開放åˆä½µè«‹æ±‚中發ç¾è¶…éŽ %{vulnerabilitiesAllowed} %{severities} %{vulnerabilityStates} çš„æ¼æ´ž"
msgid "ScanResultPolicy|%{thenLabelStart}Then%{thenLabelEnd} Require approval from %{approvalsRequired} of the following approvers:"
-msgstr ""
+msgstr "%{thenLabelStart}然後%{thenLabelEnd} 需è¦ä»¥ä¸‹ %{approvalsRequired} 個核准人的核准:"
msgid "ScanResultPolicy|add an approver"
-msgstr ""
+msgstr "加入核准者"
msgid "ScanResultPolicy|scanners"
-msgstr ""
+msgstr "掃æ器"
msgid "ScanResultPolicy|severity levels"
-msgstr ""
+msgstr "åš´é‡ç¨‹åº¦"
msgid "ScanResultPolicy|vulnerability states"
-msgstr ""
+msgstr "æ¼æ´žç‹€æ…‹"
msgid "Scanner"
-msgstr ""
+msgstr "掃æ工具"
msgid "Scanner profile failed to delete"
-msgstr ""
+msgstr "掃æ工具設定文件刪除失敗"
msgid "Scanner profile not found for given parameters"
-msgstr ""
+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 ""
+msgstr "已計劃刪除於 - %{permanent_deletion_time}"
msgid "Scheduled a rebase of branch %{branch}."
-msgstr ""
+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 ""
+msgstr "已計劃的æµæ°´ç·šæ¯æ¬¡åŸ·è¡Œæ™‚é–“ä¸èƒ½è¶…éŽæ¯%{limit} 分é˜ä¸€æ¬¡ã€‚ 一個設定更頻ç¹åŸ·è¡Œçš„æµæ°´ç·šåƒ…è‡ªä¸Šæ¬¡åŸ·è¡Œå¾ŒéŽ %{limit} 分é˜æ‰å†å•Ÿå‹•ã€‚"
msgid "Scheduled to merge this merge request (%{strategy})."
-msgstr ""
+msgstr "已計劃åˆä½µæ­¤åˆä½µè«‹æ±‚ (%{strategy})。"
msgid "Schedules"
-msgstr ""
+msgstr "計劃"
msgid "Schedules to merge this merge request (%{strategy})."
-msgstr ""
+msgstr "計劃åˆä½µæ­¤åˆä½µè«‹æ±‚ (%{strategy})。"
msgid "Scheduling Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·šè¨ˆåŠƒ"
msgid "Scope"
-msgstr ""
+msgstr "範åœ"
msgid "Scope board to current iteration"
-msgstr ""
+msgstr "範åœçœ‹æ¿åˆ°ç•¶å‰è¿­ä»£"
msgid "Scopes"
-msgstr ""
+msgstr "範åœ"
msgid "Scopes (select at least one)"
-msgstr ""
+msgstr "範åœï¼ˆè‡³å°‘é¸æ“‡ä¸€é …)"
msgid "Scopes can't be blank"
-msgstr ""
+msgstr "範åœä¸èƒ½ç‚ºç©º"
msgid "Scopes: %{scope_list}"
-msgstr ""
+msgstr "範åœï¼š%{scope_list}"
msgid "Scroll down"
-msgstr ""
+msgstr "å‘下滾動"
msgid "Scroll left"
-msgstr ""
+msgstr "å‘左滾動"
msgid "Scroll right"
-msgstr ""
+msgstr "å‘å³æ»¾å‹•"
msgid "Scroll to bottom"
-msgstr ""
+msgstr "滾動到底部"
msgid "Scroll to top"
-msgstr ""
+msgstr "滾動到頂部"
msgid "Scroll up"
-msgstr ""
+msgstr "å‘上滾動"
msgid "Search"
msgstr "æœå°‹"
msgid "Search GitLab"
-msgstr ""
+msgstr "æœå°‹ GitLab"
msgid "Search a group"
-msgstr ""
+msgstr "æœå°‹ç¾¤çµ„"
msgid "Search an environment spec"
-msgstr ""
+msgstr "æœå°‹ç’°å¢ƒè¦ç¯„"
msgid "Search assignees"
-msgstr ""
+msgstr "æœå°‹æŒ‡æ´¾äºº"
msgid "Search authors"
-msgstr ""
+msgstr "æœå°‹ä½œè€…"
msgid "Search branches"
-msgstr ""
+msgstr "æœå°‹åˆ†æ”¯"
msgid "Search branches and tags"
-msgstr ""
+msgstr "æœå°‹åˆ†æ”¯å’Œæ¨™ç±¤"
msgid "Search branches, tags, and commits"
-msgstr ""
+msgstr "æœå°‹åˆ†æ”¯ï¼Œæ¨™ç±¤å’Œæ交"
msgid "Search by Git revision"
-msgstr ""
+msgstr "使用Git版本æœå°‹"
msgid "Search by author"
-msgstr ""
+msgstr "按作者æœå°‹"
msgid "Search by commit title or SHA"
-msgstr ""
+msgstr "通éŽæ交標題或SHAæœå°‹"
msgid "Search by message"
-msgstr ""
+msgstr "按消æ¯æœå°‹"
msgid "Search by name"
-msgstr ""
+msgstr "按å稱æœå°‹"
msgid "Search files"
-msgstr ""
+msgstr "æœå°‹æ–‡ä»¶"
msgid "Search for Namespace"
-msgstr ""
+msgstr "æœå°‹å‘½å空間"
msgid "Search for a LDAP group"
-msgstr ""
+msgstr "æœå°‹LDAP組"
msgid "Search for a group"
-msgstr ""
+msgstr "æœå°‹ç¾¤çµ„"
msgid "Search for a user"
-msgstr ""
+msgstr "æœå°‹ä½¿ç”¨è€…"
msgid "Search for an emoji"
-msgstr ""
+msgstr "æœå°‹ emoji"
msgid "Search for projects, issues, etc."
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆã€è­°é¡Œç­‰ç­‰â€¦"
msgid "Search for this text"
-msgstr ""
+msgstr "æœå°‹æ­¤æ–‡å­—"
msgid "Search forks"
-msgstr ""
+msgstr "æœå°‹åˆ†å‰"
msgid "Search groups"
-msgstr ""
+msgstr "æœå°‹ç¾¤çµ„"
msgid "Search iterations"
-msgstr ""
+msgstr "æœå°‹è¿­ä»£"
msgid "Search labels"
-msgstr ""
+msgstr "æœå°‹æ¨™è¨˜"
msgid "Search merge requests"
-msgstr ""
+msgstr "æœå°‹åˆä½µè«‹æ±‚"
msgid "Search milestones"
msgstr "æœå°‹é‡Œç¨‹ç¢‘"
msgid "Search or create tag"
-msgstr ""
+msgstr "æœå°‹æˆ–建立標籤"
msgid "Search or filter results..."
-msgstr ""
+msgstr "æœå°‹æˆ–éŽæ¿¾çµæžœ......"
msgid "Search or filter results…"
-msgstr ""
+msgstr "æœå°‹æˆ–éŽæ¿¾çµæžœâ€¦"
msgid "Search page"
-msgstr ""
+msgstr "æœå°‹é é¢"
msgid "Search project"
msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search projects"
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "Search projects..."
-msgstr ""
+msgstr "æœå°‹å°ˆæ¡ˆ..."
msgid "Search rate limits"
-msgstr ""
+msgstr "æœå°‹é€ŸçŽ‡é™åˆ¶"
msgid "Search refs"
-msgstr ""
+msgstr "æœå°‹refs"
msgid "Search requirements"
-msgstr ""
+msgstr "æœå°‹éœ€æ±‚"
msgid "Search settings"
-msgstr ""
+msgstr "æœå°‹è¨­å®š"
msgid "Search users"
-msgstr ""
+msgstr "æœå°‹ä½¿ç”¨è€…"
msgid "Search users or groups"
-msgstr ""
+msgstr "æœå°‹ä½¿ç”¨è€…或群組"
msgid "Search your project dependencies for their licenses and apply policies."
-msgstr ""
+msgstr "在您的專案ä¾è³´é …中æœå°‹å…¶æŽˆæ¬Šè¨±å¯ä¸¦ä¸”套用政策。"
msgid "Search your projects"
-msgstr ""
+msgstr "æœå°‹æ‚¨çš„專案"
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "在整個 GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "我建立的議題"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "分é…給我的議題"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "我建立的åˆä½µè«‹æ±‚"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "分é…給我的åˆä½µè«‹æ±‚"
msgid "SearchAutocomplete|Merge requests that I'm a reviewer"
-msgstr ""
+msgstr "審核者是我的åˆä½µè«‹æ±‚"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "在整個 GitLab"
msgid "SearchAutocomplete|in group %{groupName}"
-msgstr ""
+msgstr "在群組%{groupName}中"
msgid "SearchAutocomplete|in project %{projectName}"
-msgstr ""
+msgstr "在專案%{projectName}中"
msgid "SearchCodeResults|of %{link_to_project}"
-msgstr ""
+msgstr "於%{link_to_project}專案中"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "顯示包å«%{term_element}中%{count}é …çš„%{scope}"
msgid "SearchResults|Showing %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "在個人和專案程å¼ç¢¼ç‰‡æ®µä¸­é¡¯ç¤ºæœå°‹%{term_element}çµæžœçš„%{count}é …%{scope}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element}"
-msgstr ""
+msgstr "顯示%{term_element}的 %{from} - %{to}/ %{count} %{scope}"
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for %{term_element} in your personal and project snippets"
-msgstr ""
+msgstr "在個人和專案程å¼ç¢¼ç‰‡æ®µä¸­é¡¯ç¤ºæœå°‹%{term_element}çµæžœçš„%{count}é …%{scope}裡的第%{from}é … - 第%{to}é …"
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
-msgstr[0] ""
+msgstr[0] "程å¼ç¢¼çµæžœ"
msgid "SearchResults|comment"
msgid_plural "SearchResults|comments"
-msgstr[0] ""
+msgstr[0] "留言"
msgid "SearchResults|commit"
msgid_plural "SearchResults|commits"
-msgstr[0] ""
+msgstr[0] "æ交"
msgid "SearchResults|epic"
msgid_plural "SearchResults|epics"
-msgstr[0] ""
+msgstr[0] "å²è©©"
msgid "SearchResults|issue"
msgid_plural "SearchResults|issues"
-msgstr[0] ""
+msgstr[0] "議題"
msgid "SearchResults|merge request"
msgid_plural "SearchResults|merge requests"
-msgstr[0] ""
+msgstr[0] "åˆä½µè«‹æ±‚"
msgid "SearchResults|milestone"
msgid_plural "SearchResults|milestones"
-msgstr[0] ""
+msgstr[0] "里程碑"
msgid "SearchResults|project"
msgid_plural "SearchResults|projects"
-msgstr[0] ""
+msgstr[0] "專案"
msgid "SearchResults|snippet"
msgid_plural "SearchResults|snippets"
-msgstr[0] ""
+msgstr[0] "程å¼ç¢¼ç‰‡æ®µ"
msgid "SearchResults|user"
msgid_plural "SearchResults|users"
-msgstr[0] ""
+msgstr[0] "使用者"
msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
-msgstr[0] ""
+msgstr[0] "wikiçµæžœ"
+
+msgid "SearchToken|Assignee"
+msgstr "被指派者"
+
+msgid "SearchToken|Reviewer"
+msgstr "審閱者"
msgid "Searching by both author and message is currently not supported."
-msgstr ""
+msgstr "ç›®å‰ä¸æ”¯æ´ä½œè€…和消æ¯åŒæ™‚æœå°‹ã€‚"
msgid "Seats"
-msgstr ""
+msgstr "席次"
msgid "Seats owed"
-msgstr ""
+msgstr "所欠席次"
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
-msgstr ""
+msgstr "席次使用情æ³è³‡æ–™ï¼Œæˆªè‡³ %{last_enqueue_time} (æ¯å¤©æ›´æ–°ï¼‰"
msgid "Seats usage data is updated every day at 12:00pm UTC"
-msgstr ""
+msgstr "席次使用資料更新於æ¯æ—¥12:00pm UTC"
msgid "Secondary email:"
-msgstr ""
+msgstr "次è¦éƒµç®±ï¼š"
msgid "Seconds"
-msgstr ""
+msgstr "秒"
msgid "Secret"
-msgstr ""
+msgstr "ä¿å¯†"
msgid "Secret Detection"
-msgstr ""
+msgstr "ä¿å¯†æª¢æ¸¬"
msgid "Secret token"
-msgstr ""
+msgstr "ä¿å¯†ä»¤ç‰Œ"
msgid "Secure Code Warrior"
-msgstr ""
+msgstr "安全代碼"
msgid "Secure Files"
-msgstr ""
+msgstr "安全文件"
msgid "Secure token that identifies an external storage request."
-msgstr ""
+msgstr "識別外部儲存請求的安全令牌。"
msgid "SecureFiles|Delete %{name}?"
-msgstr ""
+msgstr "刪除 %{name}?"
msgid "SecureFiles|Delete secure file"
-msgstr ""
+msgstr "刪除安全文件"
msgid "SecureFiles|Secure File %{name} will be permanently deleted. Are you sure?"
-msgstr ""
+msgstr "安全文件 %{name} 將被永久刪除。您確定嗎?"
msgid "Security"
-msgstr ""
+msgstr "安全"
msgid "Security & Compliance"
-msgstr ""
+msgstr "安全與åˆè¦"
msgid "Security Configuration"
-msgstr ""
+msgstr "安全設定"
msgid "Security Dashboard"
-msgstr ""
+msgstr "安全儀表æ¿"
+
+msgid "Security Finding not found"
+msgstr "未發ç¾å®‰å…¨æŸ¥å°‹"
msgid "Security dashboard"
-msgstr ""
+msgstr "安全儀表æ¿"
msgid "Security navigation"
-msgstr ""
+msgstr "安全導覽"
msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
-msgstr ""
+msgstr "安全報告已éŽæ™‚。請使用目標分支(%{targetBranchName})中的最新更改來更新您的分支。"
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
-msgstr ""
+msgstr "安全報告已éŽæ™‚。請在目標分支(%{targetBranchName})上執行%{newPipelineLinkStart}æ–°çš„æµæ°´ç·š%{newPipelineLinkEnd}"
msgid "SecurityApprovals|A merge request approval is required when test coverage declines."
-msgstr ""
+msgstr "當測試覆蓋率下é™æ™‚需è¦åˆä½µè«‹æ±‚核准。"
msgid "SecurityApprovals|A merge request approval is required when the license compliance report contains a denied license."
-msgstr ""
+msgstr "當授權許å¯åˆè¦æ€§å ±å‘ŠåŒ…å«åˆ—å…¥ç¦æ­¢å單的授權許å¯æ™‚,åˆä½µè«‹æ±‚核准為必需。"
msgid "SecurityApprovals|Coverage-Check"
-msgstr ""
+msgstr "覆蓋率檢查"
msgid "SecurityApprovals|Learn more about Coverage-Check"
-msgstr ""
+msgstr "了解更多關於覆蓋率檢查的訊æ¯"
msgid "SecurityApprovals|Learn more about License-Check"
-msgstr ""
+msgstr "了解更多關於授權許å¯æª¢æŸ¥çš„訊æ¯"
msgid "SecurityApprovals|License-Check"
-msgstr ""
+msgstr "授權許å¯æª¢æŸ¥"
msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "需è¦å°è¢«æ‹’絕的授權許å¯é€²è¡Œæ ¸å‡†ã€‚%{linkStart}了解更多。%{linkEnd}"
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "測試覆蓋率é™ä½Žï¼Œéœ€æ ¸å‡†ã€‚%{linkStart}了解更多。%{linkEnd}"
msgid "SecurityConfiguration|%{featureName} merge request creation mutation failed"
-msgstr ""
+msgstr "%{featureName} åˆä½µè«‹æ±‚建立變異失敗"
msgid "SecurityConfiguration|%{scanType} configuration code snippet"
-msgstr ""
+msgstr "%{scanType} 設定程å¼ç¢¼ç‰‡æ®µ"
msgid "SecurityConfiguration|An error occurred while creating the merge request."
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚時發生錯誤。"
msgid "SecurityConfiguration|Available with Ultimate"
-msgstr ""
+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 ""
+msgstr "é è¨­æƒ…æ³ä¸‹ï¼Œæ‰€æœ‰åˆ†æžå™¨éƒ½è¢«å¥—用來覆蓋您專案的所有語言,並且åªåœ¨åˆä½µè«‹æ±‚中檢測到該語言時æ‰åŸ·è¡Œã€‚"
msgid "SecurityConfiguration|Compliance"
-msgstr ""
+msgstr "åˆè¦æ€§"
msgid "SecurityConfiguration|Configuration guide"
-msgstr ""
+msgstr "設定指引"
msgid "SecurityConfiguration|Configuration history"
-msgstr ""
+msgstr "設定歷å²"
msgid "SecurityConfiguration|Configure %{feature}"
-msgstr ""
+msgstr "設定 %{feature}"
msgid "SecurityConfiguration|Configure with a merge request"
-msgstr ""
+msgstr "使用åˆä½µè«‹æ±‚設定"
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
-msgstr ""
+msgstr "複製程å¼ç¢¼ä¸¦æ‰“é–‹ .gitlab-ci.yml 文件"
msgid "SecurityConfiguration|Copy code only"
-msgstr ""
+msgstr "僅複製程å¼ç¢¼"
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
-msgstr ""
+msgstr "無法å–得設定資料。請é‡æ–°æ•´ç†é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "SecurityConfiguration|Create merge request"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚"
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
-msgstr ""
+msgstr "自訂常見的SAST設定以滿足您的需求。此處所åšçš„設定更改會覆蓋GitLabæ供的設定,並且ä¸æœƒåŒ…å«åœ¨æ›´æ–°ä¸­ã€‚有關更多進階設定é¸é …的詳細訊æ¯ï¼Œè«‹åƒè¦‹%{linkStart}GitLab SAST文件%{linkEnd}。"
msgid "SecurityConfiguration|Enable %{feature}"
-msgstr ""
+msgstr "啟用 %{feature}"
msgid "SecurityConfiguration|Enable Auto DevOps"
-msgstr ""
+msgstr "啟用自動化 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 ""
+msgstr "啟用安全培訓,幫助您的開發人員學習如何修復æ¼æ´žã€‚開發者å¯ä»¥æŸ¥çœ‹é¸å®šçš„教育æ供者æ供的與發ç¾çš„脆弱性相關的安全培訓。"
msgid "SecurityConfiguration|Enabled"
-msgstr ""
+msgstr "已啟用"
msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups"
-msgstr ""
+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 ""
+msgstr "使用應用程å¼å®‰å…¨åŠŸèƒ½ç«‹å³é–‹å§‹é¢¨éšªåˆ†æžå’Œè£œæ•‘。從 SAST å’Œ Secret 檢測開始,é©ç”¨æ–¼æ‰€æœ‰è¨ˆåŠƒã€‚å‡ç´šåˆ° Ultimate 以ç²å¾—所有功能,包括:"
msgid "SecurityConfiguration|Learn more about vulnerability training"
-msgstr ""
+msgstr "了解更多關於æ¼æ´žåŸ¹è¨“的訊æ¯"
msgid "SecurityConfiguration|Manage corpus"
-msgstr ""
+msgstr "管ç†èªžè©žåº«"
msgid "SecurityConfiguration|Manage corpus files used as seed inputs with coverage-guided fuzzing."
-msgstr ""
+msgstr "管ç†åœ¨è¦†è“‹æ¨¡ç³Šæ¸¬è©¦ä¸­ç”¨ä½œè¼¸å…¥ç¨®å­çš„語詞庫文件。"
msgid "SecurityConfiguration|Manage profiles"
-msgstr ""
+msgstr "管ç†è¨­å®šæ–‡ä»¶"
msgid "SecurityConfiguration|Manage profiles for use by DAST scans."
-msgstr ""
+msgstr "管ç†ä¾› DAST 掃æ使用的設定文件。"
msgid "SecurityConfiguration|More scan types, including Container Scanning, DAST, Dependency Scanning, Fuzzing, and Licence Compliance"
-msgstr ""
+msgstr "更多掃æ類型,包括容器掃æ,DAST,ä¾è³´æŽƒæ,模糊和授權許å¯åˆè¦ã€‚"
msgid "SecurityConfiguration|Not enabled"
-msgstr ""
+msgstr "未啟用"
msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
-msgstr ""
+msgstr "一旦您啟用了é è¨­åˆ†æ”¯æŽƒæ,隨後建立的任何功能分支將包å«æŽƒæ。"
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Auto DevOps%{linkEnd}快速啟用所有æŒçºŒæ¸¬è©¦å’Œåˆè¦æ€§å·¥å…·"
msgid "SecurityConfiguration|Runtime security metrics for application environments"
-msgstr ""
+msgstr "應用程å¼ç’°å¢ƒçš„執行時安全指標"
msgid "SecurityConfiguration|SAST Analyzers"
-msgstr ""
+msgstr "SAST分æžå·¥å…·"
msgid "SecurityConfiguration|SAST Configuration"
-msgstr ""
+msgstr "SAST設定"
msgid "SecurityConfiguration|Secure your project"
-msgstr ""
+msgstr "ä¿è­·æ‚¨çš„專案"
msgid "SecurityConfiguration|Security testing"
-msgstr ""
+msgstr "安全測試"
msgid "SecurityConfiguration|Security training"
-msgstr ""
+msgstr "安全培訓"
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
-msgstr ""
+msgstr "工具的狀態僅é©ç”¨æ–¼é è¨­åˆ†æ”¯ï¼Œä¸¦åŸºæ–¼ %{linkStart}最新æµæ°´ç·š%{linkEnd}。"
msgid "SecurityConfiguration|Upgrade or start a free trial"
-msgstr ""
+msgstr "å‡ç´šæˆ–開始å…費試用"
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
-msgstr ""
+msgstr "使用自訂設定。您ä¸æœƒæ”¶åˆ°æ­¤è®Šæ•¸çš„自動更新。 %{anchorStart}還原到é è¨­%{anchorEnd}"
msgid "SecurityConfiguration|Vulnerability Management"
-msgstr ""
+msgstr "æ¼æ´žç®¡ç†"
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚中的æ¼æ´žè©³ç´°è¨Šæ¯å’Œçµ±è¨ˆ"
msgid "SecurityOrchestration| and "
-msgstr ""
+msgstr "和"
msgid "SecurityOrchestration| or "
-msgstr ""
+msgstr "或 "
msgid "SecurityOrchestration|%{branches} %{plural}"
-msgstr ""
+msgstr "%{branches} %{plural}"
msgid "SecurityOrchestration|%{branches} and %{lastBranch} %{plural}"
-msgstr ""
+msgstr "%{branches} 和 %{lastBranch} %{plural}"
msgid "SecurityOrchestration|%{scanners}"
-msgstr ""
+msgstr "%{scanners}"
msgid "SecurityOrchestration|%{scanners} %{severities} in an open merge request targeting %{branches}."
-msgstr ""
+msgstr "é‡å° %{branches} 的開放åˆä½µè«‹æ±‚中的 %{scanners} %{severities}。"
msgid "SecurityOrchestration|+%{count} more"
-msgstr ""
+msgstr "+%{count} 更多"
msgid "SecurityOrchestration|, and %{count} more"
-msgstr ""
+msgstr ",還有 %{count} 個"
msgid "SecurityOrchestration|.yaml mode"
-msgstr ""
+msgstr ".yaml 模å¼"
msgid "SecurityOrchestration|.yaml preview"
-msgstr ""
+msgstr ".yaml é è¦½"
msgid "SecurityOrchestration|Actions"
-msgstr ""
+msgstr "行動"
msgid "SecurityOrchestration|Add rule"
-msgstr ""
+msgstr "加入è¦å‰‡"
msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again."
-msgstr ""
+msgstr "解除警報後,該訊æ¯å°‡ä¸å†é¡¯ç¤ºã€‚"
msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects and sub-groups in this group."
-msgstr ""
+msgstr "啟用群組級別政策後,該政策自動應用於該群組中的所有專案和å­ç¾¤çµ„。"
msgid "SecurityOrchestration|All policies"
-msgstr ""
+msgstr "所有政策"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
-msgstr ""
+msgstr "指派您的安全政策專案時發生錯誤"
msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
-msgstr ""
+msgstr "å–消指派您的安全政策專案時發生錯誤"
msgid "SecurityOrchestration|An error occurred while fetching the scan result policies."
-msgstr ""
+msgstr "讀å–掃æçµæžœæ”¿ç­–時發生錯誤"
msgid "SecurityOrchestration|Any scanner finds"
-msgstr ""
+msgstr "任何掃æ器發ç¾"
msgid "SecurityOrchestration|Are you sure you want to delete this policy? This action cannot be undone."
-msgstr ""
+msgstr "您確定è¦åˆªé™¤æ­¤æ”¿ç­–嗎? æ­¤æ“作無法撤消。"
msgid "SecurityOrchestration|Choose a project"
-msgstr ""
+msgstr "é¸æ“‡å°ˆæ¡ˆ"
msgid "SecurityOrchestration|Create more robust vulnerability rules and apply them to all your projects."
-msgstr ""
+msgstr "建立更å¥å…¨çš„æ¼æ´žè¦å‰‡ä¸¦å°‡å…¶å¥—用於您的所有專案。"
msgid "SecurityOrchestration|Create policy"
-msgstr ""
+msgstr "建立政策"
msgid "SecurityOrchestration|Create security policy"
-msgstr ""
+msgstr "建立安全政策"
msgid "SecurityOrchestration|Define this policy's location, conditions and actions."
-msgstr ""
+msgstr "定義該政策的ä½ç½®ã€æ¢ä»¶å’Œå‹•ä½œã€‚"
msgid "SecurityOrchestration|Delete policy"
-msgstr ""
+msgstr "刪除政策"
msgid "SecurityOrchestration|Delete policy: %{policy}"
-msgstr ""
+msgstr "刪除政策: %{policy}"
msgid "SecurityOrchestration|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "SecurityOrchestration|Direct"
-msgstr ""
+msgstr "直接"
msgid "SecurityOrchestration|Don't show the alert anymore"
-msgstr ""
+msgstr "ä¸å†é¡¯ç¤ºè­¦å ±"
msgid "SecurityOrchestration|Edit policy"
-msgstr ""
+msgstr "編輯政策"
msgid "SecurityOrchestration|Edit policy project"
-msgstr ""
+msgstr "編輯政策專案"
msgid "SecurityOrchestration|Edit scan execution policy"
-msgstr ""
+msgstr "編輯掃æ執行政策"
msgid "SecurityOrchestration|Edit scan result policy"
-msgstr ""
+msgstr "編輯掃æçµæžœæ”¿ç­–"
msgid "SecurityOrchestration|Empty policy name"
-msgstr ""
+msgstr "空政策å稱"
msgid "SecurityOrchestration|Enabled"
-msgstr ""
+msgstr "已啟用"
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
-msgstr ""
+msgstr "強制執行此專案的安全性。 %{linkStart}更多訊æ¯ã€‚%{linkEnd}"
msgid "SecurityOrchestration|Failed to load cluster agents."
-msgstr ""
+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 ""
+msgstr "如果任何掃æ器在é‡å°ä¸»åˆ†æ”¯çš„開放åˆä½µè«‹æ±‚中發ç¾æ–°æª¢æ¸¬çš„åš´é‡æ¼æ´žï¼Œå‰‡éœ€è¦å–得應用程å¼å®‰å…¨çš„任何æˆå“¡çš„兩次核准。"
msgid "SecurityOrchestration|Inherited"
-msgstr ""
+msgstr "繼承"
msgid "SecurityOrchestration|Inherited from %{namespace}"
-msgstr ""
+msgstr "繼承自 %{namespace}"
msgid "SecurityOrchestration|Invalid policy type"
-msgstr ""
+msgstr "無效的政策類型"
msgid "SecurityOrchestration|Latest scan run against %{agent}"
-msgstr ""
+msgstr "é‡å° %{agent} 執行的最新掃æ"
msgid "SecurityOrchestration|New policy"
-msgstr ""
+msgstr "新政策"
msgid "SecurityOrchestration|New scan execution policy"
-msgstr ""
+msgstr "新建掃æ執行政策"
msgid "SecurityOrchestration|New scan result policy"
-msgstr ""
+msgstr "新建掃æçµæžœæ”¿ç­–"
msgid "SecurityOrchestration|No actions defined - policy will not run."
-msgstr ""
+msgstr "未定義任何æ“作 - 政略ä¸æœƒåŸ·è¡Œã€‚"
msgid "SecurityOrchestration|No description"
-msgstr ""
+msgstr "ç„¡æè¿°"
msgid "SecurityOrchestration|No rules defined - policy will not run."
-msgstr ""
+msgstr "未定義è¦å‰‡ - 政策無法執行。"
msgid "SecurityOrchestration|Not enabled"
-msgstr ""
+msgstr "尚未啟用"
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
-msgstr ""
+msgstr "åªæœ‰æ‰€æœ‰è€…å¯ä»¥æ›´æ–°å®‰å…¨æ”¿ç­–專案"
msgid "SecurityOrchestration|Policies"
-msgstr ""
+msgstr "政策"
msgid "SecurityOrchestration|Policy Type"
-msgstr ""
+msgstr "政策類型"
msgid "SecurityOrchestration|Policy cannot be enabled for non-existing branches (%{branches})"
-msgstr ""
+msgstr "無法為ä¸å­˜åœ¨çš„分支啟用政略 (%{branches})"
msgid "SecurityOrchestration|Policy cannot be enabled without branch information"
-msgstr ""
+msgstr "沒有分支訊æ¯å°±ç„¡æ³•å•Ÿç”¨æ”¿ç•¥"
msgid "SecurityOrchestration|Policy definition"
-msgstr ""
+msgstr "政策定義"
msgid "SecurityOrchestration|Policy editor"
-msgstr ""
+msgstr "政策編輯器"
msgid "SecurityOrchestration|Policy status"
-msgstr ""
+msgstr "政策狀態"
msgid "SecurityOrchestration|Policy type"
-msgstr ""
+msgstr "政策類型"
msgid "SecurityOrchestration|Require %{approvals} %{plural} from %{approvers} if any of the following occur:"
-msgstr ""
+msgstr "如果發生以下任何情æ³ï¼Œå‰‡éœ€è¦ä¾†è‡ª %{approvers} çš„ %{approvals} %{plural}:"
msgid "SecurityOrchestration|Rule mode"
-msgstr ""
+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 ""
+msgstr "此政策無法使用è¦å‰‡æ¨¡å¼ï¼Œåœ¨æŸäº›æƒ…æ³ä¸‹ï¼Œæˆ‘們無法將 YAML 文件解æžå›žè¦å‰‡ç·¨è¼¯å™¨ã€‚"
msgid "SecurityOrchestration|Rules"
-msgstr ""
+msgstr "è¦å‰‡"
msgid "SecurityOrchestration|Run a DAST scan with Scan Profile A and Site Profile A when a pipeline run against the main branch."
-msgstr ""
+msgstr "當æµæ°´ç·šåŸ·è¡Œåœ¨ä¸»åˆ†æ”¯æ™‚,使用掃æ設定文件 A 和站點設定文件 A 執行 DAST 掃æ。"
msgid "SecurityOrchestration|Runs %{actions} and %{lastAction} scans"
-msgstr ""
+msgstr "執行 %{actions} å’Œ %{lastAction} 掃æ"
msgid "SecurityOrchestration|Runs a %{action} scan"
-msgstr ""
+msgstr "執行 %{action} 掃æ"
msgid "SecurityOrchestration|Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "SecurityOrchestration|Scan Execution"
-msgstr ""
+msgstr "掃æ執行"
msgid "SecurityOrchestration|Scan Result"
-msgstr ""
+msgstr "掃æçµæžœ"
msgid "SecurityOrchestration|Scan execution"
-msgstr ""
+msgstr "掃æ執行"
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
-msgstr ""
+msgstr "掃æ執行政策åªèƒ½ç”±å°ˆæ¡ˆæ‰€æœ‰è€…建立。"
msgid "SecurityOrchestration|Scan execution policy"
-msgstr ""
+msgstr "掃æ執行政策"
msgid "SecurityOrchestration|Scan result"
-msgstr ""
+msgstr "掃æçµæžœ"
msgid "SecurityOrchestration|Scan result policies can only be created by project owners."
-msgstr ""
+msgstr "掃æçµæžœæ”¿ç­–åªèƒ½ç”±å°ˆæ¡ˆæ‰€æœ‰è€…建立。"
msgid "SecurityOrchestration|Scan result policy"
-msgstr ""
+msgstr "掃æçµæžœæ”¿ç­–"
msgid "SecurityOrchestration|Scan to be performed %{cadence}"
-msgstr ""
+msgstr "è¦åŸ·è¡Œçš„掃æ %{cadence}"
msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
-msgstr ""
+msgstr "掃æ %{cadence} 在 %{branches} 上執行"
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
-msgstr ""
+msgstr "在%{branches}上掃ææ¯å€‹æµæ°´ç·š"
msgid "SecurityOrchestration|Security Approvals"
-msgstr ""
+msgstr "安全èªè­‰"
msgid "SecurityOrchestration|Security policy project was linked successfully"
-msgstr ""
+msgstr "安全政策專案已æˆåŠŸé€£æŽ¥"
msgid "SecurityOrchestration|Security policy project was unlinked successfully"
-msgstr ""
+msgstr "安全政策專案已æˆåŠŸå–消關è¯"
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å°ˆæ¡ˆä¾†å„²å­˜æ‚¨çš„安全政策。 %{linkStart}更多訊æ¯ã€‚%{linkEnd}"
msgid "SecurityOrchestration|Select policy"
-msgstr ""
+msgstr "é¸æ“‡æ”¿ç­–"
msgid "SecurityOrchestration|Select security project"
-msgstr ""
+msgstr "é¸æ“‡å®‰å…¨å°ˆæ¡ˆ"
msgid "SecurityOrchestration|Something went wrong, unable to fetch policies"
-msgstr ""
+msgstr "出了點å•é¡Œï¼Œç„¡æ³•å–得政策"
msgid "SecurityOrchestration|Sorry, your filter produced no results."
-msgstr ""
+msgstr "抱歉,您的éŽæ¿¾å™¨æ²’有產生任何çµæžœã€‚"
msgid "SecurityOrchestration|Source"
-msgstr ""
+msgstr "來æº"
msgid "SecurityOrchestration|Status"
-msgstr ""
+msgstr "狀態"
msgid "SecurityOrchestration|Step 1: Choose a policy type"
-msgstr ""
+msgstr "步驟 1:é¸æ“‡æ”¿ç­–é¡žåž‹"
msgid "SecurityOrchestration|Step 2: Policy details"
-msgstr ""
+msgstr "步驟 2:政策詳情"
msgid "SecurityOrchestration|Summary"
-msgstr ""
+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 ""
+msgstr "此開發專案中ä¸å­˜åœ¨ä»¥ä¸‹åˆ†æ”¯ï¼š%{branches}。 在更新此政策之å‰ï¼Œè«‹æª¢æŸ¥æ‰€æœ‰åˆ†æ”¯ä»¥ç¢ºä¿è©²å€¼æº–確無誤。"
msgid "SecurityOrchestration|There was a problem creating the new security policy"
-msgstr ""
+msgstr "建立新的安全政策時出ç¾å•é¡Œ"
+
+msgid "SecurityOrchestration|This %{namespaceType} does not contain any security policies."
+msgstr "該 %{namespaceType} ä¸åŒ…å«ä»»ä½•å®‰å…¨æ”¿ç­–。"
msgid "SecurityOrchestration|This group"
-msgstr ""
+msgstr "該群組"
msgid "SecurityOrchestration|This is a group-level policy"
-msgstr ""
+msgstr "這是群組層級的政策"
msgid "SecurityOrchestration|This is a project-level policy"
-msgstr ""
+msgstr "這是一個專案級別的政策"
msgid "SecurityOrchestration|This policy is inherited from %{namespace}"
-msgstr ""
+msgstr "該政策繼承自 %{namespace}"
msgid "SecurityOrchestration|This policy is inherited from the %{linkStart}namespace%{linkEnd} and must be edited there"
-msgstr ""
+msgstr "該政策繼承自 %{linkStart}namespace%{linkEnd},必須在此處進行編輯"
msgid "SecurityOrchestration|This project"
-msgstr ""
-
-msgid "SecurityOrchestration|This project does not contain any security policies."
-msgstr ""
+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 ""
+msgstr "æ­¤è¦–åœ–åƒ…é¡¯ç¤ºä»£ç† %{agent} 的掃æçµæžœã€‚您å¯ä»¥åœ¨%{linkStart}æ¼æ´žå ±å‘Šçš„é‹ç‡Ÿæ¼æ´žé¸é …中%{linkEnd}查看所有代ç†çš„掃æçµæžœã€‚"
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
-msgstr ""
+msgstr "è¦æ“´å¤§æ‚¨çš„æœå°‹ç¯„åœï¼Œè«‹åœ¨ä¸Šé¢æ›´æ”¹éŽæ¿¾è¦å‰‡æˆ–é¸æ“‡ä¸åŒçš„安全政策專案。"
msgid "SecurityOrchestration|Unlink project"
-msgstr ""
+msgstr "å–消專案關è¯"
msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
-msgstr ""
+msgstr "å–消連çµå®‰å…¨å°ˆæ¡ˆæœƒç§»é™¤åœ¨é€£çµçš„安全專案中儲存的所有政策。ä¿å­˜ä»¥ç¢ºèªæ­¤æ“作。"
msgid "SecurityOrchestration|Update scan policies"
-msgstr ""
+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ã€Secret 檢測ã€å®¹å™¨æŽƒæ。"
msgid "SecurityOrchestration|Use a scan result policy to create rules that ensure security issues are checked before merging a merge request."
-msgstr ""
+msgstr "使用掃æçµæžœæ”¿ç­–建立è¦å‰‡ï¼Œç¢ºä¿åœ¨åˆä½µåˆä½µè«‹æ±‚之å‰æª¢æŸ¥å®‰å…¨å•é¡Œã€‚"
msgid "SecurityOrchestration|View policy project"
-msgstr ""
+msgstr "查看政策專案"
msgid "SecurityOrchestration|You don't have any security policies yet"
-msgstr ""
+msgstr "您還沒有任何安全政策"
msgid "SecurityOrchestration|a"
-msgstr ""
+msgstr "一個"
msgid "SecurityOrchestration|all branches"
-msgstr ""
+msgstr "所有分支"
msgid "SecurityOrchestration|an"
-msgstr ""
+msgstr "一個"
msgid "SecurityOrchestration|branch"
-msgstr ""
+msgstr "分支"
msgid "SecurityOrchestration|branches"
-msgstr ""
+msgstr "分支"
msgid "SecurityOrchestration|scanner finds"
-msgstr ""
+msgstr "掃æ器發ç¾"
msgid "SecurityOrchestration|scanners find"
-msgstr ""
+msgstr "掃æ器發ç¾"
msgid "SecurityOrchestration|the %{branches}"
-msgstr ""
+msgstr "%{branches}"
msgid "SecurityOrchestration|vulnerabilities"
-msgstr ""
+msgstr "æ¼æ´ž"
msgid "SecurityOrchestration|vulnerability"
-msgstr ""
+msgstr "æ¼æ´ž"
msgid "SecurityReports|%{count} Selected"
-msgstr ""
+msgstr "å·²é¸å– %{count}"
msgid "SecurityReports|%{count}+ projects"
-msgstr ""
+msgstr "%{count}+ 專案"
msgid "SecurityReports|%{firstProject} and %{secondProject}"
-msgstr ""
+msgstr "%{firstProject}和%{secondProject}"
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
-msgstr ""
+msgstr "%{firstProject},%{secondProject},åŠ%{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 "加入或刪除安全å€å…§çš„專案。 此列表中專案的掃æçµæžœå°‡é¡¯ç¤ºåœ¨å®‰å…¨å„€è¡¨æ¿å’Œæ¼æ´žå ±å‘Šä¸­ã€‚"
msgid "SecurityReports|Add projects"
-msgstr ""
+msgstr "加入專案"
msgid "SecurityReports|All activity"
-msgstr ""
+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 ""
+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 ""
+msgstr "在 GitLab,我們專注於迭代和回饋。這就是為什麼我們è¦è¯çµ¡åƒæ‚¨é€™æ¨£çš„客戶來幫助指導我們今年在æ¼æ´žç®¡ç†æ–¹é¢çš„工作。我們有很多令人興奮的想法,請您å”助我們進行ä¸è¶…éŽ 10 åˆ†é˜ %{boldStart}%{boldEnd} 來評估我們的一些潛在功能。"
msgid "SecurityReports|Change status"
-msgstr ""
+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 ""
+msgstr "解æžä»¥ä¸‹å®‰å…¨å ±å‘Šæ™‚檢查產生的訊æ¯ï¼Œå› ç‚ºå®ƒå€‘å¯èƒ½æœƒé˜»æ­¢ GitLab å–å¾—çµæžœã€‚確ä¿å®‰å…¨å ±å‘Šç¬¦åˆæ”¯æ´çš„ %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}。"
msgid "SecurityReports|Cluster"
-msgstr ""
+msgstr "å¢é›†"
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
-msgstr ""
+msgstr "留言已加入到'%{vulnerabilityName}'"
msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "留言已從'%{vulnerabilityName}' 刪除"
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
-msgstr ""
+msgstr "在'%{vulnerabilityName}' 上的留言已編輯"
msgid "SecurityReports|Configure security testing"
-msgstr ""
+msgstr "設定安全測試"
msgid "SecurityReports|Create Jira issue"
-msgstr ""
+msgstr "建立 Jira 議題"
msgid "SecurityReports|Create issue"
-msgstr ""
+msgstr "建立議題"
msgid "SecurityReports|Development vulnerabilities"
-msgstr ""
+msgstr "開發æ¼æ´ž"
msgid "SecurityReports|Dismiss vulnerability"
-msgstr ""
+msgstr "忽略æ¼æ´ž"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
-msgstr ""
+msgstr "已忽略的'%{vulnerabilityName}'"
msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
-msgstr ""
+msgstr "已忽略'%{vulnerabilityName}'。請關閉隱è—忽略開關以查看。"
msgid "SecurityReports|Download %{artifactName}"
-msgstr ""
+msgstr "下載 %{artifactName}"
msgid "SecurityReports|Download results"
-msgstr ""
+msgstr "下載çµæžœ"
msgid "SecurityReports|Download scanned URLs"
-msgstr ""
+msgstr "下載掃æçš„ URL"
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 "您無權查看此儀表æ¿æˆ–尚未設定儀表æ¿ã€‚è«‹å‘管ç†å“¡æŸ¥è©¢æ‚¨çš„權é™è¨­å®šï¼Œæˆ–檢查儀表æ¿è¨­å®šä¸¦ç¹¼çºŒã€‚"
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 "請確ä¿æ­¤å°ˆæ¡ˆå•Ÿç”¨%{trackingStart}議題追蹤%{trackingEnd}並且您有%{permissionsStart}權é™å»ºç«‹æ–°è­°é¡Œ%{permissionsEnd}。"
msgid "SecurityReports|Error fetching the vulnerabilities over time. Please check your network connection and try again."
-msgstr ""
+msgstr "隨著時間的推移讀å–æ¼æ´žæ™‚出錯。請檢查您的網絡連接,然後é‡è©¦ã€‚"
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
-msgstr ""
+msgstr "å–å¾—æ¼æ´žæ•¸é‡æ™‚發生錯誤。請檢查您的網路連接,然後é‡è©¦ã€‚"
msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
-msgstr ""
+msgstr "å–å¾—æ¼æ´žåˆ—表時發生錯誤。請檢查您的網路連接,然後é‡è©¦ã€‚"
msgid "SecurityReports|Error parsing security reports"
-msgstr ""
+msgstr "解æžå®‰å…¨å ±å‘Šæ™‚發生錯誤"
msgid "SecurityReports|Failed to get security report information. Please reload the page or try again later."
-msgstr ""
+msgstr "無法å–得安全報告訊æ¯ã€‚è«‹é‡æ–°è¼‰å…¥é é¢æˆ–ç¨å¾Œå†è©¦ã€‚"
msgid "SecurityReports|Hide dismissed"
-msgstr ""
+msgstr "éš±è—已忽略項"
+
+msgid "SecurityReports|Image"
+msgstr "圖åƒ"
msgid "SecurityReports|Issue Created"
-msgstr ""
+msgstr "已建立議題"
msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
-msgstr ""
+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 ""
+msgstr "管ç†å’Œè¿½è¹¤æ‚¨ç¾¤çµ„內專案中發ç¾çš„æ¼æ´žã€‚設定安全測試時,此處顯示專案中的æ¼æ´žã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
-msgstr ""
+msgstr "管ç†å’Œè¿½è¹¤æ‚¨çš„專案中發ç¾çš„æ¼æ´žã€‚設定安全測試時,此處會顯示æ¼æ´žã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
-msgstr ""
+msgstr "管ç†å’Œè¿½è¹¤åœ¨æ‚¨é¸æ“‡çš„專案中發ç¾çš„æ¼æ´žã€‚此處顯示了設定了安全測試的é¸å®šå°ˆæ¡ˆçš„æ¼æ´žã€‚"
msgid "SecurityReports|Maximum selected projects limit reached"
-msgstr ""
+msgstr "å·²é”到最大é¸å®šå°ˆæ¡ˆé™åˆ¶"
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
-msgstr ""
+msgstr "監控您所有專案中的æ¼æ´ž"
msgid "SecurityReports|Monitor vulnerabilities in your group"
-msgstr ""
+msgstr "監控您的群組中的æ¼æ´ž"
msgid "SecurityReports|Monitor vulnerabilities in your project"
-msgstr ""
+msgstr "監控您的專案中的æ¼æ´ž"
msgid "SecurityReports|Monitored projects"
-msgstr ""
+msgstr "監控的專案"
msgid "SecurityReports|More info"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "SecurityReports|No activity"
-msgstr ""
+msgstr "無活動"
msgid "SecurityReports|No longer detected"
-msgstr ""
+msgstr "ä¸å†æª¢æ¸¬"
msgid "SecurityReports|No vulnerabilities found"
-msgstr ""
+msgstr "未發ç¾æ¼æ´ž"
msgid "SecurityReports|No vulnerabilities found for this pipeline"
-msgstr ""
+msgstr "æ­¤æµæ°´ç·šä¸­æœªç™¼ç¾æ¼æ´ž"
msgid "SecurityReports|Oops, something doesn't seem right."
-msgstr ""
+msgstr "看起來ä¸æ­£ç¢ºã€‚"
msgid "SecurityReports|Operational vulnerabilities"
-msgstr ""
+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 ""
+msgstr "專案"
msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
-msgstr ""
+msgstr "未找到專案或者您沒有權é™å°‡æ­¤å°ˆæ¡ˆåŠ å…¥åˆ°å®‰å…¨å„€è¡¨æ¿ã€‚"
msgid "SecurityReports|Projects added"
-msgstr ""
+msgstr "專案已加入"
msgid "SecurityReports|Remove project from dashboard"
-msgstr ""
+msgstr "從儀表æ¿åˆªé™¤å°ˆæ¡ˆ"
msgid "SecurityReports|Report has expired"
-msgstr ""
+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 ""
+msgstr "çµæžœé¡¯ç¤ºåˆä½µè«‹æ±‚引入的æ¼æ´žï¼Œä»¥åŠå°ˆæ¡ˆé è¨­åˆ†æ”¯ä¸­æœ€æ–°æˆåŠŸæµæ°´ç·šä¸­çš„ç¾æœ‰æ¼æ´žã€‚"
msgid "SecurityReports|Scan details"
-msgstr ""
+msgstr "掃æ詳情"
msgid "SecurityReports|Security Dashboard"
-msgstr ""
+msgstr "安全儀表æ¿"
msgid "SecurityReports|Security reports can only be accessed by authorized users."
-msgstr ""
+msgstr "安全報告åªèƒ½ç”±æŽˆæ¬Šçš„使用者存å–。"
msgid "SecurityReports|Security reports help page link"
-msgstr ""
+msgstr "安全報告幫助é é¢é€£çµ"
msgid "SecurityReports|Security scans have run"
-msgstr ""
+msgstr "安全掃æ已執行"
msgid "SecurityReports|Select a project to add by using the project search field above."
-msgstr ""
+msgstr "請使用上é¢çš„專案æœå°‹å­—段來é¸æ“‡è¦åŠ å…¥çš„專案。"
msgid "SecurityReports|Set status"
-msgstr ""
+msgstr "設定狀態"
msgid "SecurityReports|Severity"
-msgstr ""
+msgstr "åš´é‡ç¨‹åº¦"
msgid "SecurityReports|Show %{pageSize} items"
-msgstr ""
+msgstr "顯示 %{pageSize} 項"
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 "有時掃æ工具無法確定調查çµæžœçš„åš´é‡æ€§ï¼Œé€™äº›çµæžœå¯èƒ½ä»ç„¶æ˜¯æ½›åœ¨çš„風險來æºï¼Œè«‹æ‰‹å‹•æŸ¥çœ‹"
msgid "SecurityReports|Sorry, your filter produced no results"
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæ²’有符åˆéŽæ¿¾å™¨çš„任何çµæžœ"
msgid "SecurityReports|Status"
-msgstr ""
+msgstr "狀態"
msgid "SecurityReports|Submit vulnerability"
-msgstr ""
+msgstr "æ交æ¼æ´ž"
msgid "SecurityReports|Take survey"
-msgstr ""
+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 ""
+msgstr "æ¼æ´žå ±å‘Šé¡¯ç¤ºå°å°ˆæ¡ˆé è¨­åˆ†æ”¯çš„æˆåŠŸæŽƒæçµæžœã€æ‰‹å‹•æ·»åŠ çš„æ¼æ´žè¨˜éŒ„以åŠå¾žæŽƒææ“作環境中發ç¾çš„æ¼æ´žã€‚ %{linkStart}了解更多。%{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 "安全報告包å«ä¸€å€‹æˆ–多個無法解æžä¸”未記錄的æ¼æ´žç™¼ç¾ã€‚查看報告,請下載該作業項的產出物,確ä¿å»ºç«‹çš„安全報告都符åˆç›¸é—œçš„ %{helpPageLinkStart}JSON 綱è¦%{helpPageLinkEnd}。"
msgid "SecurityReports|The security report for this pipeline has %{helpPageLinkStart}expired%{helpPageLinkEnd}. Re-run the pipeline to generate a new security report."
-msgstr ""
+msgstr "æ­¤æµæ°´ç·šçš„安全報告 %{helpPageLinkStart}å·²éŽæœŸ%{helpPageLinkEnd}。é‡æ–°åŸ·è¡Œæµæ°´ç·šä¾†ç”¢ç”Ÿæ–°çš„安全報告。"
msgid "SecurityReports|There was an error adding the comment."
-msgstr ""
+msgstr "加入留言時發生錯誤。"
msgid "SecurityReports|There was an error creating the issue."
-msgstr ""
+msgstr "建立議題時發生錯誤。"
msgid "SecurityReports|There was an error creating the merge request."
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚時發生錯誤。"
msgid "SecurityReports|There was an error deleting the comment."
-msgstr ""
+msgstr "刪除留言時發生錯誤。"
msgid "SecurityReports|There was an error dismissing the vulnerabilities."
-msgstr ""
+msgstr "忽略æ¼æ´žæ™‚發生錯誤。"
msgid "SecurityReports|There was an error dismissing the vulnerability."
-msgstr ""
+msgstr "忽略æ¼æ´žæ™‚發生錯誤。"
msgid "SecurityReports|There was an error reverting the dismissal."
-msgstr ""
+msgstr "å–消忽略時發生錯誤。"
msgid "SecurityReports|There was an error reverting this dismissal."
-msgstr ""
+msgstr "å–消忽略時發生錯誤。"
msgid "SecurityReports|There was an error while generating the report."
-msgstr ""
+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 ""
+msgstr "這些æ¼æ´žæ˜¯åœ¨å¤–部來æºä¸­æª¢æ¸¬åˆ°çš„,它們ä¸ä¸€å®šèˆ‡æ‚¨çš„專案相關è¯ã€‚例如,執行中的容器ã€URL 等。"
msgid "SecurityReports|To widen your search, change or remove filters above"
-msgstr ""
+msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–刪除上é¢çš„éŽæ¿¾å™¨ã€‚"
msgid "SecurityReports|Tool"
-msgstr ""
+msgstr "工具"
msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
-msgstr ""
+msgstr "無法加入%{invalidProjectsMessage}: %{errorMessage}"
msgid "SecurityReports|Undo dismiss"
-msgstr ""
+msgstr "å–消忽略"
msgid "SecurityReports|Upgrade to interact, track and shift left with vulnerability management features in the UI."
-msgstr ""
+msgstr "å‡ç´šä»¥ä¾¿åœ¨UI中使用æ¼æ´žç®¡ç†åŠŸèƒ½é€²è¡Œäº’å‹•ã€è¿½è¹¤å’Œç§»å‹•ã€‚"
msgid "SecurityReports|Upgrade to manage vulnerabilities"
-msgstr ""
+msgstr "å‡ç´šä»¥ç®¡ç†æ¼æ´ž"
msgid "SecurityReports|Vulnerability Management feature survey"
-msgstr ""
+msgstr "æ¼æ´žç®¡ç†åŠŸèƒ½èª¿æŸ¥"
msgid "SecurityReports|Vulnerability Report"
-msgstr ""
+msgstr "æ¼æ´žå ±å‘Š"
msgid "SecurityReports|Warning parsing security reports"
-msgstr ""
+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 ""
+msgstr "雖然您的æµæ°´ç·šä¸­æ²’有æ¼æ´žï¼Œé€™ç¨®ç¾è±¡å¾ˆç½•è¦‹ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。無論如何,建議您仔細檢查設定以確ä¿å„€è¡¨æ¿çš„設定正確。"
msgid "SecurityReports|With issues"
-msgstr ""
+msgstr "有議題"
msgid "SecurityReports|You do not have sufficient permissions to access this report"
-msgstr ""
+msgstr "您沒有足夠的權é™å­˜å–此報告"
msgid "SecurityReports|You must sign in as an authorized user to see this report"
-msgstr ""
+msgstr "您必須以授權使用者身份登入æ‰èƒ½æŸ¥çœ‹æ­¤å ±å‘Š"
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
-msgstr ""
+msgstr "您的回饋å°æˆ‘們很é‡è¦ï¼æˆ‘們將在一周內å†æ¬¡è©¢å•ã€‚"
msgid "SecurityReports|scanned resources"
-msgstr ""
+msgstr "掃æ資æº"
msgid "SecurityTraining|Primary Training"
-msgstr ""
+msgstr "åˆç´šåŸ¹è¨“"
msgid "SecurityTraining|Training from this partner takes precedence when more than one training partner is enabled."
-msgstr ""
+msgstr "當多個培訓åˆä½œå¤¥ä¼´å•Ÿç”¨æ™‚,來自此åˆä½œå¤¥ä¼´çš„培訓將優先進行。"
msgid "See example DevOps Score page in our documentation."
-msgstr ""
+msgstr "è«‹åƒé–±æˆ‘們文件中的範例 DevOps 得分é é¢ã€‚"
msgid "See metrics"
-msgstr ""
+msgstr "查看指標"
msgid "See our website for help"
-msgstr ""
+msgstr "查看我們的網站以å–得幫助"
msgid "See the affected projects in the GitLab admin panel"
-msgstr ""
+msgstr "查看 GitLab 管ç†é¢æ¿ä¸­çš„å—影響專案"
msgid "See vulnerability %{vulnerability_link} for any Remediation details."
-msgstr ""
+msgstr "有關任何修復的詳細訊æ¯ï¼Œè«‹åƒè¦‹æ¼æ´ž%{vulnerability_link}。"
msgid "See vulnerability %{vulnerability_link} for any Solution details."
-msgstr ""
+msgstr "有關任何解決方案的詳細訊æ¯ï¼Œè«‹åƒè¦‹æ¼æ´ž %{vulnerability_link}。"
msgid "Select"
-msgstr ""
+msgstr "é¸æ“‡"
msgid "Select Archive Format"
-msgstr ""
+msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select Git revision"
-msgstr ""
+msgstr "é¸æ“‡Git版本"
msgid "Select Page"
-msgstr ""
+msgstr "é¸æ“‡é é¢"
msgid "Select Profile"
-msgstr ""
+msgstr "é¸æ“‡å€‹äººè³‡æ–™"
msgid "Select a branch"
-msgstr ""
+msgstr "é¸æ“‡åˆ†æ”¯"
msgid "Select a branch to compare"
-msgstr ""
+msgstr "é¸æ“‡è¦æ¯”較的分支"
msgid "Select a color"
-msgstr ""
+msgstr "é¸æ“‡é¡è‰²ï¼š"
msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
-msgstr ""
+msgstr "é¸æ“‡é©ç”¨æ–¼è©²å°ˆæ¡ˆçš„åˆè¦æ¡†æž¶ã€‚ %{linkStart}這些是如何加入的?%{linkEnd}"
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
-msgstr ""
+msgstr "請先從左å´é‚Šæ¬„é¸æ“‡ä¸€å€‹æ–‡ä»¶é–‹å§‹ç·¨è¼¯ï¼Œç„¶å¾Œå°±å¯ä»¥æ交您的變更了。"
msgid "Select a label"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æ¨™è¨˜"
msgid "Select a milestone"
-msgstr ""
+msgstr "é¸æ“‡é‡Œç¨‹ç¢‘"
msgid "Select a new namespace"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æ–°çš„命å空間"
msgid "Select a project"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹å°ˆæ¡ˆ"
msgid "Select a reason"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹åŽŸå› "
msgid "Select a repository containing templates for common files."
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹åŒ…å«å¸¸è¦‹æ–‡ä»¶ç¯„本的版本庫。"
msgid "Select a role"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹è§’色"
msgid "Select a template repository"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç¯„本版本庫"
msgid "Select a template type"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹ç¯„本類型"
msgid "Select a time zone"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æ™‚å€"
msgid "Select a timezone"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æ™‚å€"
msgid "Select all"
-msgstr ""
+msgstr "é¸æ“‡å…¨éƒ¨"
msgid "Select an assignee"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹æŒ‡æ´¾äºº"
msgid "Select an iteration"
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹è¿­ä»£"
msgid "Select assignee"
-msgstr ""
+msgstr "é¸æ“‡æŒ‡æ´¾äºº"
msgid "Select assignee(s)"
-msgstr ""
+msgstr "é¸æ“‡æŒ‡æ´¾äºº(s)"
msgid "Select branch"
-msgstr ""
+msgstr "é¸æ“‡åˆ†æ”¯"
msgid "Select branches"
-msgstr ""
+msgstr "é¸æ“‡åˆ†æ”¯(s)"
msgid "Select due date"
-msgstr ""
+msgstr "設定截止日期"
msgid "Select epic"
-msgstr ""
+msgstr "é¸æ“‡å²è©©"
msgid "Select group"
-msgstr ""
+msgstr "é¸æ“‡ç¾¤çµ„"
msgid "Select group or project"
-msgstr ""
+msgstr "é¸æ“‡ç¾¤çµ„或專案"
msgid "Select health status"
-msgstr ""
+msgstr "é¸æ“‡å¥åº·ç‹€æ…‹"
msgid "Select iteration"
-msgstr ""
+msgstr "é¸æ“‡è¿­ä»£"
msgid "Select label"
-msgstr ""
+msgstr "é¸æ“‡æ¨™è¨˜"
msgid "Select labels"
-msgstr ""
+msgstr "é¸æ“‡æ¨™è¨˜(s)"
msgid "Select merge moment"
-msgstr ""
+msgstr "é¸æ“‡åˆä½µæ™‚é–“"
msgid "Select milestone"
-msgstr ""
+msgstr "é¸æ“‡é‡Œç¨‹ç¢‘"
msgid "Select private project"
-msgstr ""
+msgstr "é¸æ“‡ç§æœ‰å°ˆæ¡ˆ"
msgid "Select project"
-msgstr ""
+msgstr "é¸æ“‡å°ˆæ¡ˆ"
msgid "Select project to create %{type}"
-msgstr ""
+msgstr "é¸æ“‡è¦å»ºç«‹ %{type} 的專案"
msgid "Select project to create issue"
-msgstr ""
+msgstr "é¸æ“‡è¦å»ºç«‹è­°é¡Œçš„專案"
msgid "Select projects"
-msgstr ""
+msgstr "é¸æ“‡å°ˆæ¡ˆ(s)"
msgid "Select reviewer(s)"
-msgstr ""
+msgstr "é¸æ“‡å¯©æ ¸è€…(s)"
msgid "Select source"
-msgstr ""
+msgstr "é¸æ“‡ä¾†æº"
msgid "Select source branch"
-msgstr ""
+msgstr "é¸æ“‡ä¾†æºåˆ†æ”¯"
msgid "Select source project"
-msgstr ""
+msgstr "é¸æ“‡ä¾†æºå°ˆæ¡ˆ"
msgid "Select start date"
-msgstr ""
+msgstr "é¸æ“‡é–‹å§‹æ—¥æœŸ"
msgid "Select status"
-msgstr ""
+msgstr "é¸æ“‡ç‹€æ…‹"
msgid "Select strategy activation method"
-msgstr ""
+msgstr "é¸æ“‡ç­–略啟用方å¼"
msgid "Select subgroup"
-msgstr ""
+msgstr "é¸æ“‡å­ç¾¤çµ„"
msgid "Select subscription"
-msgstr ""
+msgstr "é¸æ“‡è¨‚é–±"
msgid "Select target branch"
-msgstr ""
+msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
msgid "Select target branch or tag"
-msgstr ""
+msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯æˆ–標籤"
msgid "Select target project"
-msgstr ""
+msgstr "é¸æ“‡ç›®æ¨™å°ˆæ¡ˆ"
msgid "Select timezone"
-msgstr ""
+msgstr "é¸æ“‡æ™‚å€"
msgid "Select type"
-msgstr ""
+msgstr "é¸æ“‡é¡žåž‹"
msgid "Selected"
-msgstr ""
+msgstr "å·²é¸æ“‡"
msgid "Selected commits"
-msgstr ""
+msgstr "å·²é¸å®šçš„æ交"
msgid "Selected for all items."
-msgstr ""
+msgstr "å·²é¸å–全部項目。"
msgid "Selected for some items."
-msgstr ""
+msgstr "å·²é¸å–了一些項目。"
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
-msgstr ""
-
-msgid "Selected projects"
-msgstr ""
+msgstr "éžç®¡ç†å“¡ä½¿ç”¨è€…無法為群組ã€å°ˆæ¡ˆæˆ–程å¼ç¢¼ç‰‡æ®µä½¿ç”¨æ‰€é¸ç´šåˆ¥ã€‚如果公開級別å—到é™åˆ¶ï¼Œå‰‡ä½¿ç”¨è€…設定檔案僅å°ç™»å…¥ä½¿ç”¨è€…å¯è¦‹ã€‚"
msgid "Selected tag is already in use. Choose another option."
-msgstr ""
+msgstr "所é¸æ¨™ç±¤å·²åœ¨ä½¿ç”¨ä¸­ã€‚é¸æ“‡å¦ä¸€å€‹é¸é …。"
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "é¸æ“‡GitLab使用者將在議題和留言的æ述中加入指å‘該GitLab使用者的連çµ(例如「由%{link_open}@johnsmith%{link_close}ã€)。它還將這些å•é¡Œå’Œè©•è«–與所é¸ä½¿ç”¨è€…é—œè¯å’Œ/或分派。"
msgid "Self monitoring"
-msgstr ""
+msgstr "自監控"
msgid "Self monitoring project does not exist"
-msgstr ""
+msgstr "沒有自監控專案"
msgid "Self-monitoring project does not exist. Please check logs for any error messages"
-msgstr ""
+msgstr "沒有自監控專案。請檢查記錄檔是å¦æœ‰éŒ¯èª¤è¨Šæ¯"
msgid "Self-monitoring project has been successfully deleted"
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤è‡ªç›£æŽ§å°ˆæ¡ˆ"
msgid "Self-monitoring project was not deleted. Please check logs for any error messages"
-msgstr ""
+msgstr "未刪除自監控專案。請檢查記錄檔是å¦æœ‰éŒ¯èª¤è¨Šæ¯"
msgid "SelfMonitoring|Activate or deactivate instance self monitoring."
-msgstr ""
+msgstr "啟用或åœç”¨å¯¦ä¾‹è‡ªç›£æ¸¬ã€‚"
msgid "SelfMonitoring|Activate self monitoring to create a project to use to monitor the health of your instance."
-msgstr ""
+msgstr "啟用自監控以建立用於監控實例執行狀æ³çš„專案。"
msgid "SelfMonitoring|Deactivate self monitoring?"
-msgstr ""
+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 ""
+msgstr "åœç”¨è‡ªç›£æŽ§å°‡åˆªé™¤è‡ªç›£æŽ§å°ˆæ¡ˆã€‚您確定è¦åœç”¨è‡ªç›£æŽ§ä¸¦åˆªé™¤å°ˆæ¡ˆå—Žï¼Ÿ"
msgid "SelfMonitoring|Self monitoring"
-msgstr ""
+msgstr "自監控"
msgid "SelfMonitoring|Self monitoring is active. Use the %{projectLinkStart}self monitoring project%{projectLinkEnd} to monitor the health of your instance."
-msgstr ""
+msgstr "自監控已啟用。使用 %{projectLinkStart}自監控專案%{projectLinkEnd} 來監控您的實例執行狀æ³ã€‚"
msgid "SelfMonitoring|Self monitoring project successfully created."
-msgstr ""
+msgstr "æˆåŠŸå»ºç«‹äº†è‡ªç›£æ¸¬å°ˆæ¡ˆã€‚"
msgid "SelfMonitoring|Self monitoring project successfully deleted."
-msgstr ""
+msgstr "æˆåŠŸåˆªé™¤äº†è‡ªç›£æ¸¬å°ˆæ¡ˆã€‚"
msgid "Send"
-msgstr ""
+msgstr "發é€"
msgid "Send a single email notification to Owners and Maintainers for new alerts."
-msgstr ""
+msgstr "å‘所有者和維護者發é€ä¸€å°é›»å­éƒµä»¶é€šçŸ¥ä»¥å–得新警報。"
msgid "Send confirmation email"
-msgstr ""
+msgstr "發é€ç¢ºèªéƒµä»¶"
msgid "Send email"
-msgstr ""
+msgstr "發é€é›»å­éƒµä»¶"
msgid "Send email in multipart format (HTML and plain text). Uncheck to send email messages in plain text only."
-msgstr ""
+msgstr "以 multipart æ ¼å¼ï¼ˆHTML 和純文字)發é€é›»å­éƒµä»¶ã€‚å–消勾é¸åƒ…以純文字形å¼ç™¼é€é›»å­éƒµä»¶ã€‚"
msgid "Send email notification"
-msgstr ""
+msgstr "發é€é›»å­éƒµä»¶é€šçŸ¥"
msgid "Send emails to help guide new users through the onboarding process."
-msgstr ""
+msgstr "發é€é›»å­éƒµä»¶ä»¥å¹«åŠ©æŒ‡å°Žæ–°ä½¿ç”¨è€…完æˆæ–°äººæµç¨‹ã€‚"
msgid "Send emails to users upon account deactivation."
-msgstr ""
+msgstr "帳號åœç”¨å¾Œå‘使用者發é€é›»å­éƒµä»¶ã€‚"
msgid "Send message"
-msgstr ""
+msgstr "發é€è¨Šæ¯"
msgid "Send notifications about project events to Mattermost channels."
-msgstr ""
+msgstr "å‘ Mattermost é »é“發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。"
msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
-msgstr ""
+msgstr "å‘ Mattermost é »é“發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。 %{docs_link}"
msgid "Send notifications about project events to a Discord channel. %{docs_link}"
-msgstr ""
+msgstr "å‘ Discord é »é“發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。 %{docs_link}"
msgid "Send report"
-msgstr ""
+msgstr "發é€å ±å‘Š"
msgid "Send service data"
-msgstr ""
+msgstr "發é€æœå‹™è³‡æ–™"
msgid "Sentry"
-msgstr ""
+msgstr "Sentry(哨兵)"
msgid "Sentry API URL"
-msgstr ""
+msgstr "Sentry API URL"
msgid "Sentry event"
-msgstr ""
+msgstr "Sentry(哨兵) 事件"
msgid "Sep"
msgstr "9月"
msgid "September"
-msgstr ""
+msgstr "9月"
msgid "SeriesFinalConjunction|and"
-msgstr ""
+msgstr "與"
msgid "Serve repository static objects (for example, archives and blobs) from external storage."
-msgstr ""
+msgstr "從外部儲存æ供版本庫éœæ…‹ç‰©ä»¶ï¼ˆä¾‹å¦‚,檔案和 blob)。"
msgid "Server (optional)"
-msgstr ""
+msgstr "伺æœå™¨ï¼ˆå¯é¸ï¼‰"
msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
-msgstr ""
+msgstr "伺æœå™¨åƒ…支æ´æ‰¹æ¬¡è™•ç†API,請將您的Git LFS用戶端更新到1.0.1åŠæ›´é«˜ç‰ˆæœ¬ã€‚"
msgid "Server version"
-msgstr ""
+msgstr "伺æœå™¨ç‰ˆæœ¬"
msgid "Service"
-msgstr ""
+msgstr "æœå‹™"
msgid "Service Account"
-msgstr ""
+msgstr "æœå‹™å¸³è™Ÿ"
msgid "Service Account Key"
-msgstr ""
+msgstr "æœå‹™å¸³è™Ÿé‡‘é‘°"
msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
-msgstr ""
+msgstr "æœå‹™å¸³è™Ÿé‡‘鑰授權 GitLab 部署您的 Google Cloud 專案"
msgid "Service Desk"
-msgstr ""
+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 ""
+msgstr "æœå‹™è‡º(Service Desk)å…許人們在沒有自己的使用者帳號的情æ³ä¸‹åœ¨æ‚¨çš„ GitLab 實例中建立議題。它為最終使用者在專案中建立議題æ供了唯一的電å­éƒµä»¶åœ°å€ã€‚ å¯ä»¥é€šéŽ GitLab ç•Œé¢æˆ–é›»å­éƒµä»¶ç™¼é€å›žå¾©ã€‚ 最終使用者åªèƒ½é€šéŽé›»å­éƒµä»¶æŸ¥çœ‹è­°é¡Œã€‚"
msgid "Service Ping payload not found in the application cache"
-msgstr ""
+msgstr "在應用程å¼å¿«å–中找ä¸åˆ° Service Ping 的有效è£è¼‰"
msgid "Service account generated successfully"
-msgstr ""
+msgstr "æœå‹™å¸³è™Ÿç”¢ç”ŸæˆåŠŸ"
msgid "Service accounts"
-msgstr ""
+msgstr "æœå‹™å¸³è™Ÿ"
msgid "Service usage data"
-msgstr ""
+msgstr "æœå‹™ä½¿ç”¨è³‡æ–™"
msgid "ServiceDesk|Enable Service Desk"
-msgstr ""
+msgstr "啟用æœå‹™å°"
msgid "ServiceDesk|For help setting up the Service Desk for your instance, please contact an administrator."
-msgstr ""
+msgstr "有關為您的實例設定æœå‹™å°çš„幫助,請è¯çµ¡ç®¡ç†å“¡ã€‚"
msgid "ServiceDesk|Issues created from Service Desk emails will appear here. Each comment becomes part of the email conversation."
-msgstr ""
+msgstr "從æœå‹™å°é›»å­éƒµä»¶å»ºç«‹çš„議題將顯示在此處,æ¯æ¢ç•™è¨€éƒ½æˆç‚ºé›»å­éƒµä»¶å°è©±çš„一部分。"
msgid "ServiceDesk|Service Desk is not enabled"
-msgstr ""
+msgstr "æœå‹™å°æœªå•Ÿç”¨"
msgid "ServiceDesk|Service Desk is not supported"
-msgstr ""
+msgstr "ä¸æ”¯æ´Service Desk"
msgid "ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email."
-msgstr ""
+msgstr "è¦åœ¨æ­¤å¯¦ä¾‹ä¸Šå•Ÿç”¨æœå‹™å°ï¼Œå¯¦ä¾‹ç®¡ç†å“¡å¿…須首先設定接收電å­éƒµä»¶åœ°å€ã€‚"
msgid "ServiceDesk|Use Service Desk to connect with your users and offer customer support through email right inside GitLab"
-msgstr ""
+msgstr "使用 Service Desk 與您的使用者è¯çµ¡ä¸¦åœ¨ GitLab 內通éŽé›»å­éƒµä»¶æ供客戶支æ´"
msgid "ServiceDesk|Your users can send emails to this address:"
-msgstr ""
+msgstr "您的使用者å¯ä»¥å‘以下地å€ç™¼é€é›»å­éƒµä»¶ï¼š"
msgid "ServicePing|Service ping is off"
-msgstr ""
+msgstr "Service Ping 已關閉"
msgid "ServicePing|To view instance-level analytics, ask an admin to turn on %{docLinkStart}service ping%{docLinkEnd}."
-msgstr ""
+msgstr "è¦æŸ¥çœ‹å¯¦ä¾‹ç´šåˆ†æžï¼Œè«‹è®“管ç†å“¡æ‰“é–‹%{docLinkStart}Service Ping%{docLinkEnd}。"
msgid "ServicePing|Turn on service ping"
-msgstr ""
+msgstr "é–‹å•Ÿ Service Ping"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
-msgstr ""
-
-msgid "Services"
-msgstr ""
+msgstr "打開 Service Ping 以查看實例級分æžã€‚"
msgid "Session ID"
-msgstr ""
+msgstr "會話 ID"
msgid "Session duration (minutes)"
-msgstr ""
+msgstr "會話(session)æŒçºŒæ™‚é–“(分é˜)"
msgid "Set %{epic_ref} as the parent epic."
-msgstr ""
+msgstr "å°‡%{epic_ref}設定為父å²è©©ã€‚"
msgid "Set a default description template to be used for new issues. %{link_start}What are description templates?%{link_end}"
-msgstr ""
+msgstr "設定用於新議題的é è¨­æ述範本。 %{link_start}什麼是æ述範本?%{link_end}"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-
-msgid "Set access permissions for this token."
-msgstr ""
+msgstr "為帳號建立一個用於推é€æˆ–拉å–çš„ %{protocol} 密碼。"
msgid "Set any rate limit to %{code_open}0%{code_close} to disable the limit."
-msgstr ""
+msgstr "將任何速率é™åˆ¶è¨­å®šç‚º %{code_open}0%{code_close} 以ç¦ç”¨è©²é™åˆ¶ã€‚"
msgid "Set due date"
-msgstr ""
+msgstr "設定截止日期"
msgid "Set health status"
-msgstr ""
+msgstr "設定å¥åº·ç‹€æ…‹"
msgid "Set health status to %{health_status}."
-msgstr ""
+msgstr "å°‡å¥åº·ç‹€æ…‹è¨­å®šç‚º %{health_status}。"
msgid "Set iteration"
-msgstr ""
+msgstr "設定迭代"
msgid "Set limit to 0 to allow any file size."
-msgstr ""
+msgstr "設定é™åˆ¶ç‚º 0 以å…許任何文件大å°ã€‚"
msgid "Set limits for web and API requests."
-msgstr ""
+msgstr "為 Web å’Œ API 請求設定é™åˆ¶ã€‚"
msgid "Set milestone"
-msgstr ""
+msgstr "設定里程碑"
msgid "Set new password"
-msgstr ""
+msgstr "設定新密碼"
msgid "Set parent epic to an epic"
-msgstr ""
+msgstr "為å²è©©è¨­å®šä¸Šç´šå²è©©"
msgid "Set per-user rate limits for imports and exports of projects and groups."
-msgstr ""
+msgstr "為專案和群組的匯入和匯出設定æ¯å€‹ä½¿ç”¨è€…的速率é™åˆ¶ã€‚"
msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
-msgstr ""
+msgstr "設定專案和最大空間é™åˆ¶ã€æœƒè©±æŒçºŒæ™‚é–“ã€ä½¿ç”¨è€…é¸é …,並檢查命å空間計劃的功能å¯ç”¨æ€§ã€‚"
msgid "Set rate limits for package registry API requests that supersede the general user and IP rate limits."
-msgstr ""
+msgstr "為 Packages registry API 請求設定速率é™åˆ¶ä»¥å–代一般使用者和 IP 速率é™åˆ¶ã€‚"
msgid "Set rate limits for searches performed by web or API requests."
-msgstr ""
+msgstr "設定 web 或 API 請求æœå°‹çš„速率é™åˆ¶ã€‚"
msgid "Set severity"
-msgstr ""
+msgstr "設定嚴é‡æ€§"
msgid "Set sign-in restrictions for all users."
-msgstr ""
+msgstr "為所有使用者設定登入é™åˆ¶ã€‚"
msgid "Set size limits for displaying diffs in the browser."
-msgstr ""
+msgstr "設定在ç€è¦½å™¨ä¸­é¡¯ç¤ºå·®ç•°çš„大å°é™åˆ¶ã€‚"
msgid "Set target branch"
-msgstr ""
+msgstr "設定目標分支"
msgid "Set target branch to %{branch_name}."
-msgstr ""
+msgstr "設定目標分支為%{branch_name}。"
msgid "Set the Ready status"
-msgstr ""
+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 "設定此專案的é è¨­åˆ†æ”¯ã€‚除éžæ‚¨æŒ‡å®šä¸åŒçš„分支,å¦å‰‡æ‰€æœ‰åˆä½µè«‹æ±‚å’Œæ交都是é‡å°æ­¤åˆ†æ”¯é€²è¡Œçš„。"
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 "為所有專案中的作業產物設定é è¨­åˆ°æœŸæ™‚間。é è¨­æƒ…æ³ä¸‹è¨­å®šç‚º %{code_open}0%{code_close} 表示永ä¸éŽæœŸã€‚如果沒有寫入單ä½ï¼Œå‰‡é è¨­ç‚ºç§’。例如,以下都是等價的: %{code_open}3600%{code_close}〠%{code_open}60 minutes%{code_close}或 %{code_open}one hour%{code_close}。"
msgid "Set the due date to %{due_date}."
-msgstr ""
+msgstr "設定到期日期為%{due_date}。"
msgid "Set the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "將迭代設定為%{iteration_reference}。"
msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-msgstr ""
+msgstr "設定 Elasticsearch é‡å»ºæœŸé–“å…許åŒæ™‚執行的碎片的最大數é‡ã€‚了解更多關於 %{max_slices_running_link_start}最大執行碎片設定%{max_slices_link_end}。"
msgid "Set the maximum session time for a web terminal."
-msgstr ""
+msgstr "設定 Web 終端的最長會話時間。"
msgid "Set the milestone to %{milestone_reference}."
-msgstr ""
+msgstr "將里程碑設定為%{milestone_reference}。"
msgid "Set the per-user rate limit for getting a user by ID via the API."
-msgstr ""
+msgstr "為æ¯å€‹é€éŽAPI以IDå–得的使用者設定æ¯å€‹ä½¿ç”¨è€…速率é™åˆ¶ã€‚"
msgid "Set the per-user rate limit for notes created by web or API requests."
-msgstr ""
+msgstr "為由 Web 或 API 請求建立的 notes 設定æ¯å€‹ä½¿ç”¨è€…的速率é™åˆ¶ã€‚"
msgid "Set this number to 0 to disable the limit."
-msgstr ""
+msgstr "將此數字設定為 0 來ç¦ç”¨é™åˆ¶ã€‚"
msgid "Set time estimate"
-msgstr ""
+msgstr "設定é ä¼°æ™‚é–“"
msgid "Set time estimate to %{time_estimate}."
-msgstr ""
+msgstr "將時間估計設定為%{time_estimate}。"
msgid "Set to 0 for no size limit."
-msgstr ""
+msgstr "設定為 0 表示沒有大å°é™åˆ¶ã€‚"
msgid "Set up CI/CD"
-msgstr ""
+msgstr "é…ç½® CI/CD"
msgid "Set up Jira Integration"
-msgstr ""
+msgstr "設定Jiraæ•´åˆ"
msgid "Set up a %{type} runner for a project"
-msgstr ""
+msgstr "為專案設定一個%{type}執行器(runner)"
msgid "Set up a hardware device as a second factor to sign in."
-msgstr ""
+msgstr "設定一個硬體設備作為登入的第二個因å­ã€‚"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
-msgstr ""
+msgstr "根據%{docsLinkStart}文件%{icon}%{docsLinkEnd}設定斷言/屬性/è²æ˜Žï¼ˆemail,first_name,last_name)和NameID"
msgid "Set up new device"
-msgstr ""
+msgstr "設定新設備"
msgid "Set up new password"
-msgstr ""
+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 ""
+msgstr "設定專案以自動推é€å’Œ/或從å¦ä¸€å€‹ç‰ˆæœ¬åº«ä¸­æå–變更。分支,標籤和æ交將自動åŒæ­¥ã€‚"
msgid "Set visibility of project contents. Configure import sources and Git access protocols."
-msgstr ""
+msgstr "設定專案內容的å¯è¦‹æ€§ï¼Œé…置匯入來æºå’Œ Git å­˜å–å”議。"
msgid "Set weight"
-msgstr ""
+msgstr "設定權é‡"
msgid "Set weight to %{weight}."
-msgstr ""
+msgstr "將權é‡è¨­å®šç‚º%{weight}。"
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "在您的å字和頭åƒæ—邊顯示標識。"
msgid "SetStatusModal|Busy"
-msgstr ""
+msgstr "忙碌"
msgid "SetStatusModal|Clear status"
-msgstr ""
+msgstr "清除狀態"
msgid "SetStatusModal|Clear status after"
-msgstr ""
+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 ""
+msgstr "設定狀態"
msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
-msgstr ""
+msgstr "å°ä¸èµ·ï¼Œæˆ‘們無法設定您的狀態。請ç¨å¾Œå†è©¦ã€‚"
msgid "SetStatusModal|Status updated"
-msgstr ""
+msgstr "狀態已更新"
msgid "SetStatusModal|What's your status?"
-msgstr ""
+msgstr "您的狀態為?"
msgid "SetStatusModal|Your status resets on %{date}."
-msgstr ""
+msgstr "您的狀態在 %{date} 時é‡è¨­ã€‚"
msgid "Sets %{epic_ref} as parent epic."
-msgstr ""
+msgstr "å°‡%{epic_ref}設定為父å²è©©ã€‚"
msgid "Sets health status to %{health_status}."
-msgstr ""
+msgstr "å°‡å¥åº·ç‹€æ…‹è¨­å®šç‚º %{health_status}。"
msgid "Sets target branch to %{branch_name}."
-msgstr ""
+msgstr "設定目標分支為%{branch_name}。"
msgid "Sets the due date to %{due_date}."
-msgstr ""
+msgstr "將截止日期設定為 %{due_date}。"
msgid "Sets the iteration to %{iteration_reference}."
-msgstr ""
+msgstr "迭代設定為%{iteration_reference}。"
msgid "Sets the milestone to %{milestone_reference}."
-msgstr ""
+msgstr "將里程碑設定為 %{milestone_reference}。"
msgid "Sets the severity"
-msgstr ""
+msgstr "設定嚴é‡ç¨‹åº¦"
msgid "Sets time estimate to %{time_estimate}."
-msgstr ""
+msgstr "將時間估計設定為 %{time_estimate}。"
msgid "Sets weight to %{weight}."
-msgstr ""
+msgstr "將權é‡è¨­å®šç‚º %{weight}。"
msgid "Setting"
-msgstr ""
+msgstr "設定"
msgid "Setting enforced"
-msgstr ""
+msgstr "強制設定"
msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
-msgstr[0] ""
+msgstr[0] "設定已æˆåŠŸä¿å­˜"
msgid "Settings"
-msgstr ""
+msgstr "設定"
msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
-msgstr ""
+msgstr "無法載入åˆä½µè«‹æ±‚é¸é …設定。嘗試é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "Setup"
-msgstr ""
+msgstr "設定"
msgid "Severity"
-msgstr ""
+msgstr "åš´é‡ç¨‹åº¦"
msgid "Severity updated to %{severity}."
-msgstr ""
+msgstr "åš´é‡ç¨‹åº¦å·²æ›´æ–°ç‚º%{severity}。"
msgid "SeverityWidget|Severity"
-msgstr ""
+msgstr "åš´é‡æ€§"
msgid "SeverityWidget|Severity: %{severity}"
-msgstr ""
+msgstr "åš´é‡æ€§: %{severity}"
msgid "SeverityWidget|There was an error while updating severity."
-msgstr ""
+msgstr "æ›´æ–°åš´é‡æ€§æ™‚發生錯誤。"
msgid "Share"
-msgstr ""
+msgstr "分享"
msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "分享%{strong_open}GitLab單一登入網å€%{strong_close}給群組æˆå“¡ï¼Œä»¥ä¾¿ä»–們å¯ä»¥é€šéŽæ‚¨çš„身份æ供商登入您的群組"
msgid "Shared Runners"
-msgstr ""
+msgstr "共用執行器(Runners)"
msgid "Shared projects"
-msgstr ""
+msgstr "共用專案"
msgid "Shared runners"
-msgstr ""
+msgstr "共用執行器(runners)"
msgid "Shared runners are disabled for the parent group"
-msgstr ""
+msgstr "上層群組無法使用共用執行器"
msgid "Shared runners are disabled on group level"
-msgstr ""
+msgstr "共用執行器在群組級別已åœç”¨"
msgid "Shared runners details"
-msgstr ""
+msgstr "共用執行器詳細資訊"
msgid "Shared runners enabled cannot be enabled until a valid credit card is on file"
-msgstr ""
+msgstr "在有效的信用å¡å­˜æª”之å‰ï¼Œç„¡æ³•å•Ÿç”¨å·²å•Ÿç”¨çš„共用執行器"
msgid "Shared runners help link"
-msgstr ""
+msgstr "共用執行器(runner)幫助連çµ"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
-msgstr ""
+msgstr "é€éŽé‡è¨­æ­¤å‘½å空間的æµæ°´ç·šåˆ†é˜æ•¸ï¼Œç›®å‰ä½¿ç”¨çš„分é˜æ•¸å°‡è¢«æ­¸é›¶ã€‚"
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
-msgstr ""
+msgstr "é‡è¨­æµæ°´ç·šåˆ†é˜æ•¸"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
-msgstr ""
+msgstr "é‡è¨­å·²ç”¨æµæ°´ç·šåˆ†é˜æ•¸"
msgid "Shimo|Go to Shimo Workspace"
-msgstr ""
+msgstr "å‰å¾€ Shimo 工作å€"
msgid "Shimo|Link to a Shimo Workspace from the sidebar."
-msgstr ""
+msgstr "從å´é‚Šæ¬„連çµåˆ° Shimo 工作å€ã€‚"
msgid "Shimo|Shimo"
-msgstr ""
+msgstr "Shimo"
msgid "Shimo|Shimo Workspace"
-msgstr ""
+msgstr "Shimo工作å€"
msgid "Shimo|Shimo Workspace URL"
-msgstr ""
+msgstr "Shimoå·¥ä½œå€ URL"
msgid "Shimo|Shimo Workspace integration is enabled"
-msgstr ""
+msgstr "Shimo工作å€æ•´åˆå·²å•Ÿç”¨"
msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
-msgstr ""
+msgstr "您已啟用Shimo工作å€æ•´åˆã€‚您å¯ä»¥ç›´æŽ¥åœ¨Shimo查看您的wiki。"
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 ""
+msgstr "如果您éºå¤±æ‰‹æ©Ÿæˆ–一次性存å–密碼,æ¯å€‹æ¢å¾©ç¢¼éƒ½å¯ä»¥ä½¿ç”¨ä¸€æ¬¡ï¼Œä»¥é‡æ–°ç²å¾—您的帳號存å–權é™ã€‚請將它們ä¿å­˜åœ¨å®‰å…¨çš„地方,å¦å‰‡æ‚¨%{boldStart}å°‡%{boldEnd}無法存å–您的帳號。"
msgid "Show Pipeline ID"
-msgstr ""
+msgstr "顯示æµæ°´ç·šID"
msgid "Show Pipeline IID"
-msgstr ""
+msgstr "顯示æµæ°´ç·šIID"
msgid "Show all %{issuable_type}."
-msgstr ""
+msgstr "顯示所有 %{issuable_type}。"
msgid "Show all activity"
-msgstr ""
+msgstr "顯示所有活動"
msgid "Show all breadcrumbs"
-msgstr ""
+msgstr "顯示所有麵包屑導覽"
msgid "Show all epics"
-msgstr ""
+msgstr "顯示所有å²è©©"
msgid "Show all issues."
-msgstr ""
+msgstr "顯示所有議題。"
msgid "Show all milestones"
-msgstr ""
+msgstr "顯示所有里程碑"
msgid "Show all test cases."
-msgstr ""
+msgstr "顯示所有測試案例。"
msgid "Show archived projects"
-msgstr ""
+msgstr "顯示已歸檔的專案"
msgid "Show archived projects only"
-msgstr ""
+msgstr "僅顯示已歸檔專案"
msgid "Show closed epics"
-msgstr ""
+msgstr "顯示已關閉的å²è©©"
msgid "Show command"
-msgstr ""
+msgstr "顯示相關指令"
msgid "Show comments"
-msgstr ""
+msgstr "顯示留言"
msgid "Show comments on this file"
-msgstr ""
+msgstr "顯示å°æ­¤æ–‡ä»¶çš„留言"
msgid "Show comments only"
-msgstr ""
+msgstr "僅顯示留言"
msgid "Show complete raw log"
-msgstr ""
+msgstr "顯示完整的原始日誌"
msgid "Show details"
-msgstr ""
+msgstr "顯示詳情"
msgid "Show file browser"
-msgstr ""
+msgstr "顯示文件ç€è¦½å™¨"
msgid "Show file contents"
-msgstr ""
+msgstr "顯示文件內容"
msgid "Show group milestones"
-msgstr ""
+msgstr "顯示群組里程碑"
msgid "Show labels"
-msgstr ""
+msgstr "顯示標記"
msgid "Show latest version"
-msgstr ""
+msgstr "顯示最新版本"
msgid "Show list"
-msgstr ""
+msgstr "顯示列表"
msgid "Show one file at a time"
-msgstr ""
+msgstr "一次顯示一個文件"
msgid "Show open epics"
-msgstr ""
+msgstr "顯示開放中的å²è©©"
msgid "Show project milestones"
-msgstr ""
+msgstr "顯示專案里程碑"
msgid "Show sub-group milestones"
-msgstr ""
+msgstr "顯示å­ç¾¤çµ„里程碑"
msgid "Show the Closed list"
-msgstr ""
+msgstr "顯示已關閉列表"
msgid "Show the Open list"
-msgstr ""
+msgstr "顯示已打開列表"
msgid "Show thread"
-msgstr ""
+msgstr "顯示主題"
msgid "Show whitespace changes"
-msgstr ""
+msgstr "顯示空白變更內容"
msgid "ShowcaseSecurity|Access a dedicated area for vulnerability management. This includes a security dashboard, vulnerability report, and settings."
-msgstr ""
+msgstr "å­˜å–專用的æ¼æ´žç®¡ç†å€åŸŸï¼Œé€™åŒ…括安全儀表æ¿ã€æ¼æ´žå ±å‘Šå’Œè¨­ç½®ã€‚"
msgid "ShowcaseSecurity|Audit your Docker-based app. Scan for known vulnerabilities in the Docker images where your code is shipped."
-msgstr ""
+msgstr "審核您基於 Docker 的應用程å¼ï¼ŒæŽƒæ您程å¼ç¢¼æ‰€éƒ¨å»ºçš„ Docker 映åƒæª”內已知æ¼æ´žã€‚"
msgid "ShowcaseSecurity|Container scanning"
-msgstr ""
+msgstr "容器掃æ"
msgid "ShowcaseSecurity|Dependency scanning"
-msgstr ""
+msgstr "ä¾è³´æŽƒæ"
msgid "ShowcaseSecurity|Dynamic Application Security Testing (DAST)"
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ¸¬è©¦ (DAST)"
msgid "ShowcaseSecurity|Dynamically examine your application for vulnerabilities in deployed environments."
-msgstr ""
+msgstr "在已部署環境中動態檢查您的應用程å¼æ¼æ´žã€‚"
msgid "ShowcaseSecurity|Enable SAST"
-msgstr ""
+msgstr "啟用 SAST"
msgid "ShowcaseSecurity|Enable Secret Detection"
-msgstr ""
+msgstr "啟用 Secret 檢測"
msgid "ShowcaseSecurity|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "啟用éœæ…‹æ‡‰ç”¨å®‰å…¨æ¸¬è©¦ (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 "瞭解您的外部程å¼åº«æ˜¯å¦å®‰å…¨ã€‚é‹è¡Œä¾è³´æŽƒæ作業,檢查您外部程å¼åº«ä¸­çš„已知æ¼æ´žã€‚"
msgid "ShowcaseSecurity|Identify vulnerabilities in your code now"
-msgstr ""
+msgstr "ç«‹å³è­˜åˆ¥ç¨‹å¼ç¢¼ä¸­çš„æ¼æ´ž"
msgid "ShowcaseSecurity|Scan your code to detect unintentionally committed secrets, like keys, passwords, and API tokens."
-msgstr ""
+msgstr "掃æ您的程å¼ç¢¼ä»¥æª¢æ¸¬ç„¡æ„é–“æ交的æ•æ„Ÿä¿¡æ¯ï¼Œä¾‹å¦‚密鑰ã€å¯†ç¢¼å’Œ API 權æ–。"
msgid "ShowcaseSecurity|Scan your source code using GitLab CI/CD and uncover vulnerabilities before deploying."
-msgstr ""
+msgstr "使用 GitLab CI/CD 掃æ您的程å¼ç¢¼ä¸¦åœ¨éƒ¨ç½²ä¹‹å‰æ­éœ²æ¼æ´žã€‚"
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 "開始å…è²» 30 天的 Ultimate 試用或å‡ç´šæ‚¨çš„實例以存å–組織範åœçš„安全性和åˆè¦æ€§åŠŸèƒ½ï¼ŒæŸ¥çœ‹ Ultimate 計劃的其他功能。"
msgid "ShowcaseSecurity|Start a free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "ShowcaseSecurity|Take your security to the next level"
-msgstr ""
+msgstr "讓您的資安更上一層樓"
msgid "ShowcaseSecurity|Upgrade now"
-msgstr ""
+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 ""
+msgstr "使用 GitLab CI/CD 分æžæ‚¨ç¨‹å¼ç¢¼ä¸­çš„已知æ¼æ´žï¼Œæ¯”較來æºåˆ†æ”¯å’Œç›®æ¨™åˆ†æ”¯ä¹‹é–“發ç¾çš„æ¼æ´žã€‚"
msgid "ShowcaseSecurity|Vulnerability management"
-msgstr ""
+msgstr "æ¼æ´žç®¡ç†"
msgid "Showing %{conflict}"
-msgstr ""
+msgstr "正在顯示 %{conflict}"
msgid "Showing %{count} of %{total} projects"
-msgstr ""
+msgstr "顯示%{count}個專案,共計%{total} 個"
msgid "Showing %{count} project"
msgid_plural "Showing %{count} projects"
-msgstr[0] ""
+msgstr[0] "顯示%{count}個專案"
msgid "Showing %{limit} of %{total_count} issues. "
-msgstr ""
+msgstr "顯示%{total_count}個議題中的%{limit}項. "
msgid "Showing %{pageSize} of %{total} %{issuableType}"
-msgstr ""
+msgstr "顯示 %{pageSize} / %{total} %{issuableType}"
msgid "Showing all epics"
-msgstr ""
+msgstr "顯示所有å²è©©"
msgid "Showing all issues"
-msgstr ""
+msgstr "顯示所有議題"
msgid "Showing data for workflow items created in this date range. Date range limited to %{maxDateRange} days."
-msgstr ""
+msgstr "顯示在此日期範åœå…§å»ºç«‹çš„工作æµäº‹é …的資料。日期範åœæœ€å¤š %{maxDateRange} 天。"
msgid "Showing graphs based on events of the last %{timerange} days."
-msgstr ""
+msgstr "顯示基於最近%{timerange}天的事件的圖表。"
msgid "Showing last %{size} of log -"
-msgstr ""
+msgstr "顯示日誌的最後%{size} -"
msgid "Showing latest version"
-msgstr ""
+msgstr "顯示最新版本"
msgid "Showing version #%{versionNumber}"
-msgstr ""
+msgstr "顯示版本#%{versionNumber}"
-msgid "Shows issues and %{labels_count} labels for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
-msgstr ""
+msgid "Shows issues for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
+msgstr "顯示 2019 å¹´ 11 月 1 日至 2019 å¹´ 12 月 31 日“%{group_name}â€ç¾¤çµ„çš„è­°é¡Œ"
msgid "Side-by-side"
-msgstr ""
+msgstr "並排"
msgid "Sidebar|%{name}: %{value}"
-msgstr ""
+msgstr "%{name}: %{value}"
msgid "Sidebar|Assign health status"
-msgstr ""
+msgstr "指定å¥åº·ç‹€æ…‹"
msgid "Sidebar|Health status"
-msgstr ""
+msgstr "å¥åº·ç‹€æ…‹"
msgid "Sidebar|No status"
-msgstr ""
+msgstr "無狀態"
msgid "Sidebar|None"
-msgstr ""
+msgstr "ç„¡"
msgid "Sidekiq job compression threshold (bytes)"
-msgstr ""
+msgstr "Sidekiq 作業壓縮閾值(字節)"
msgid "Sidekiq job size limit (bytes)"
-msgstr ""
+msgstr "Sidekiq 作業大å°é™åˆ¶ (字節)"
msgid "Sidekiq job size limits"
-msgstr ""
+msgstr "Sidekiq 作業大å°é™åˆ¶"
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 ""
+msgstr "以具有符åˆé›»å­éƒµä»¶åœ°å€çš„使用者身份登入,將電å­éƒµä»¶åŠ å…¥åˆ°æ­¤å¸³è™Ÿï¼Œæˆ–使用符åˆçš„é›»å­éƒµä»¶è¨»å†Šæ–°å¸³è™Ÿã€‚"
msgid "Sign in preview"
-msgstr ""
+msgstr "登入é è¦½"
msgid "Sign in to \"%{group_name}\""
-msgstr ""
+msgstr "登入到 \"%{group_name}\""
msgid "Sign in to GitLab"
-msgstr ""
+msgstr "登入到GitLab"
msgid "Sign in using smart card"
-msgstr ""
+msgstr "使用智慧å¡ç™»å…¥"
msgid "Sign in via 2FA code"
-msgstr ""
+msgstr "é€éŽ2FA程å¼ç¢¼ç™»å…¥"
msgid "Sign in with"
-msgstr ""
+msgstr "登入方å¼"
msgid "Sign in with Single Sign-On"
-msgstr ""
+msgstr "使用單一登入(SSO)進行登入"
msgid "Sign in with smart card"
-msgstr ""
+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 "å›  %{error} 而造æˆç™»å…¥å¤±æ•—。"
msgid "Sign-in page"
-msgstr ""
+msgstr "登入é é¢"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "登入é™åˆ¶"
msgid "Sign-in text"
-msgstr ""
+msgstr "登入文字"
+
+msgid "Sign-in using %{provider} auth failed"
+msgstr "使用 %{provider} 驗證登入失敗"
msgid "Sign-out page URL"
-msgstr ""
+msgstr "退出é é¢URL"
msgid "Sign-up restrictions"
-msgstr ""
+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 ""
+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},我åŒæ„æˆ‘å·²é–±è®€ä¸¦æŽ¥å— GitLab %{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 ""
+msgstr "已登入"
msgid "Signed in to GitLab"
-msgstr ""
+msgstr "已登入到 GitLab"
msgid "Signed in to GitLab as %{user_link}"
-msgstr ""
+msgstr "以%{user_link}身份登入到 GitLab"
msgid "Signed in with %{authentication} authentication"
-msgstr ""
+msgstr "使用%{authentication}進行身份驗證"
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 ""
+msgstr "沒有é å…ˆå­˜åœ¨çš„GitLab帳號的情æ³ä¸‹ç„¡æ³•ä½¿ç”¨æ‚¨çš„%{label}帳號登入。"
msgid "Similar issues"
-msgstr ""
+msgstr "相似議題"
msgid "Simulate a pipeline created for the default branch"
-msgstr ""
+msgstr "模擬為é è¨­åˆ†æ”¯å»ºç«‹çš„æµæ°´ç·š"
msgid "Site profile failed to delete"
-msgstr ""
+msgstr "網站設定文件刪除失敗"
msgid "Site profile not found for given parameters"
-msgstr ""
+msgstr "找ä¸åˆ°çµ¦å®šåƒæ•¸çš„站點設定文件"
msgid "Sites"
-msgstr ""
+msgstr "站點"
msgid "Size"
-msgstr ""
+msgstr "大å°"
msgid "Size Limits"
-msgstr ""
+msgstr "大å°é™åˆ¶"
msgid "Size limit per repository (MB)"
-msgstr ""
+msgstr "æ¯å€‹ç‰ˆæœ¬åº«çš„大å°é™åˆ¶ (MB)"
msgid "Skip outdated deployment jobs"
-msgstr ""
+msgstr "è·³éŽå·²éŽæ™‚的部署作業"
msgid "Skipped"
-msgstr ""
+msgstr "已跳éŽ"
msgid "Skipped deployment to"
-msgstr ""
+msgstr "è·³éŽéƒ¨ç½²åˆ°"
msgid "Skype:"
-msgstr ""
+msgstr "Skype:"
msgid "Slack application"
-msgstr ""
+msgstr "Slack應用"
msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
-msgstr ""
+msgstr "Slackæ•´åˆå…許您é€éŽèŠå¤©è¦–窗中的shash指令與GitLab互動。"
msgid "Slack logo"
-msgstr ""
+msgstr "Slack logo"
msgid "SlackIntegration|Are you sure you want to remove this project from the Slack application?"
-msgstr ""
+msgstr "您確定è¦å¾ž Slack 應用程å¼ä¸­åˆªé™¤æ­¤å°ˆæ¡ˆå—Žï¼Ÿ"
msgid "SlackIntegration|Client ID"
-msgstr ""
+msgstr "客戶端 ID"
msgid "SlackIntegration|Client secret"
-msgstr ""
+msgstr "客戶端密鑰"
msgid "SlackIntegration|GitLab for Slack"
-msgstr ""
+msgstr "GitLab for Slack"
msgid "SlackIntegration|GitLab for Slack was successfully installed."
-msgstr ""
+msgstr "GitLab for Slack å·²æˆåŠŸå®‰è£ã€‚"
msgid "SlackIntegration|Install Slack app"
-msgstr ""
+msgstr "å®‰è£ Slack 應用程å¼"
msgid "SlackIntegration|Project alias"
-msgstr ""
+msgstr "專案別å"
msgid "SlackIntegration|Reinstall Slack app"
-msgstr ""
+msgstr "é‡æ–°å®‰è£ Slack 應用程å¼"
msgid "SlackIntegration|Remove project"
-msgstr ""
+msgstr "移除專案"
msgid "SlackIntegration|See the list of available commands in Slack after setting up this integration by entering"
-msgstr ""
+msgstr "通éŽè¼¸å…¥è¨­å®šæ­¤æ•´åˆå¾Œï¼ŒæŸ¥çœ‹ Slack 中å¯ç”¨çš„命令列表"
msgid "SlackIntegration|Select a GitLab project to link with your Slack workspace."
-msgstr ""
+msgstr "é¸æ“‡ä¸€å€‹è¦é€£æŽ¥åˆ°æ‚¨ Slack 工作å€çš„專案。"
msgid "SlackIntegration|Sends notifications about project events to Slack channels."
-msgstr ""
+msgstr "å‘ Slack é »é“發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。"
msgid "SlackIntegration|Signing secret"
-msgstr ""
+msgstr "簽署密鑰"
msgid "SlackIntegration|Team name"
-msgstr ""
+msgstr "團隊å稱"
msgid "SlackIntegration|This integration allows users to perform common operations on this project by entering slash commands in Slack."
-msgstr ""
+msgstr "該整åˆå…許使用者通éŽåœ¨ Slack 中輸入斜æ å‘½ä»¤ä¾†å°è©²å°ˆæ¡ˆåŸ·è¡Œå¸¸è¦‹æ“作。"
msgid "SlackIntegration|Verification token"
-msgstr ""
+msgstr "驗證令牌(權æ–)"
msgid "SlackIntegration|You can now close this window and go to your Slack workspace."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é—œé–‰æ­¤çª—å£ä¸¦è½‰åˆ°æ‚¨çš„ Slack 工作å€ã€‚"
msgid "SlackIntegration|You may need to reinstall the Slack application when we %{linkStart}make updates or change permissions%{linkEnd}."
-msgstr ""
+msgstr "當我們%{linkStart}進行更新或更改權é™%{linkEnd}時,您å¯èƒ½éœ€è¦é‡æ–°å®‰è£ Slack 應用程å¼ã€‚"
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}在您的Slack團隊中使用此訊æ¯åŠ å…¥ä¸€å€‹æ–œæ§“指令%{slash_command_link_end}:"
msgid "SlackService|2. Paste the token from Slack in the %{strong_open}Token%{strong_close} field below."
-msgstr ""
+msgstr "2. 在下é¢çš„ %{strong_open}令牌%{strong_close} 字段貼上來自Slack的令牌。"
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. é¸æ“‡ %{strong_open}å•Ÿå‹•%{strong_close} 復é¸æ¡†ï¼Œé¸æ“‡ %{strong_open}ä¿å­˜æ›´æ”¹%{strong_close},然後開始使用Slack的斜槓指令ï¼"
msgid "SlackService|After setup, get a list of available Slack slash commands by entering"
-msgstr ""
+msgstr "設定後,通éŽè¼¸å…¥å–å¾—å¯ç”¨Slack斜槓指令的列表"
msgid "SlackService|Fill in the word that works best for your team."
-msgstr ""
+msgstr "填寫最é©åˆæ‚¨çš„團隊的文字。"
msgid "SlackService|Perform common operations in this project by entering slash commands in Slack."
-msgstr ""
+msgstr "通éŽåœ¨Slack中輸入斜槓指令來執行這個專案中的常用æ“作。"
msgid "Slice multiplier"
-msgstr ""
+msgstr "切片乖數"
msgid "Smartcard"
-msgstr ""
+msgstr "智慧å¡"
msgid "Smartcard authentication failed: client certificate header is missing."
-msgstr ""
+msgstr "智慧å¡èº«ä»½é©—證失敗:缺少客戶端憑證標頭(header)。"
msgid "Snippet"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "Snippets with non-text files can only be edited via Git."
-msgstr ""
+msgstr "具有éžæ–‡å­—文件的程å¼ç¢¼ç‰‡æ®µåªèƒ½é€šéŽGit編輯。"
msgid "SnippetsEmptyState|Code snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "SnippetsEmptyState|Documentation"
-msgstr ""
+msgstr "文件"
msgid "SnippetsEmptyState|New snippet"
-msgstr ""
+msgstr "新建程å¼ç¢¼ç‰‡æ®µ"
msgid "SnippetsEmptyState|No snippets found"
-msgstr ""
+msgstr "當å‰ç„¡ç¨‹å¼ç¢¼ç‰‡æ®µ"
msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
-msgstr ""
+msgstr "儲存〠分享和嵌入å°æ®µç¨‹å¼ç¢¼å’Œæ–‡å­—。"
msgid "SnippetsEmptyState|There are no snippets to show."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„程å¼ç¢¼ç‰‡æ®µã€‚"
msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} å·²æˆåŠŸæ交給 Akismet。"
msgid "Snippets|Add another file %{num}/%{total}"
-msgstr ""
+msgstr "加入å¦ä¸€å€‹æ–‡ä»¶%{num}/%{total}"
msgid "Snippets|Delete file"
-msgstr ""
+msgstr "刪除文件"
msgid "Snippets|Description (optional)"
-msgstr ""
+msgstr "æè¿° (å¯é¸)"
msgid "Snippets|Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Akismet 發生錯誤。請檢查日誌å–得更多訊æ¯ã€‚"
msgid "Snippets|Files"
-msgstr ""
+msgstr "文件"
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
-msgstr ""
+msgstr "給文件命å以啟用程å¼ç¢¼é«˜äº®ï¼Œä¾‹å¦‚Ruby文件 example.rb"
msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
-msgstr ""
+msgstr "å¯é¸åŠ å…¥æ述您的程å¼ç¢¼ç‰‡æ®µåšä»€éº¼æˆ–如何使用它…"
msgid "Snippets|Snippets can't contain empty files. Ensure all files have content, or delete them."
-msgstr ""
+msgstr "片段ä¸èƒ½åŒ…å«ç©ºæ–‡ä»¶ã€‚確ä¿æ‰€æœ‰æ–‡ä»¶éƒ½æœ‰å…§å®¹ï¼Œæˆ–者刪除它們。"
msgid "Snowplow"
-msgstr ""
+msgstr "Snowplow"
msgid "Solid"
-msgstr ""
+msgstr "實心"
msgid "Solution"
-msgstr ""
-
-msgid "Some actions remove attention requests, like a reviewer approving or anyone merging the merge request."
-msgstr ""
+msgstr "解決方案"
msgid "Some changes are not shown"
-msgstr ""
+msgstr "一些變更未顯示"
msgid "Some child epics may be hidden due to applied filters"
-msgstr ""
+msgstr "æŸäº›å­å²è©©å¯èƒ½ç”±æ–¼å¥—用éŽæ¿¾å™¨è€Œè¢«éš±è—"
msgid "Some common domains are not allowed. %{learn_more_link}."
-msgstr ""
+msgstr "æŸäº›å¸¸è¦‹ç¶²åŸŸä¸è¢«å…許。%{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 "有人在您編輯文件的åŒæ™‚編輯了該文件。請檢查 %{link_start}文件 %{icon}%{link_end} 並確ä¿æ‚¨çš„更改ä¸æœƒç„¡æ„中刪除他們的更改。"
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 ""
+msgstr "其他使用者åŒæ™‚編輯了這個議題。請檢查%{linkStart}è­°é¡Œ%{linkEnd}並確ä¿æ‚¨çš„變更ä¸æœƒç„¡æ„中移除他們的變更。"
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 ""
+msgstr "有人與您åŒæ™‚編輯了%{issueType} 。æ述已被更新,您需è¦é‡æ–°ä¿®æ”¹ã€‚"
msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
-msgstr ""
+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 "有人在您編輯的åŒæ™‚編輯了這個測試案例。æ述已更新,您需è¦å†æ¬¡é€²è¡Œæ›´æ”¹ã€‚"
msgid "Someone, hopefully you, has requested to reset the password for your GitLab account on %{link_to_gitlab}."
-msgstr ""
+msgstr "有人(希望是您)è¦æ±‚在 %{link_to_gitlab} 上é‡è¨­æ‚¨çš„ GitLab 帳號的密碼。"
msgid "Something went wrong"
-msgstr ""
+msgstr "發生錯誤了"
msgid "Something went wrong on our end"
-msgstr ""
+msgstr "發生錯誤了,抱歉。"
msgid "Something went wrong on our end."
-msgstr ""
+msgstr "發生錯誤了,抱歉。"
msgid "Something went wrong on our end. Please try again!"
-msgstr ""
+msgstr "伺æœå™¨ç«¯ç™¼ç”ŸéŒ¯èª¤ï¼Œè«‹é‡è©¦ã€‚"
msgid "Something went wrong on our end. Please try again."
-msgstr ""
+msgstr "伺æœå™¨ç«¯ç™¼ç”ŸéŒ¯èª¤ã€‚è«‹å†è©¦ã€‚"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "試圖改變 %{issuableDisplayName} 的鎖定狀態時發生錯誤了"
msgid "Something went wrong trying to load issue contacts."
-msgstr ""
+msgstr "嘗試載入議題è¯çµ¡äººæ™‚發生錯誤。"
msgid "Something went wrong when reordering designs. Please try again"
-msgstr ""
+msgstr "é‡æ–°æŽ’åºè¨­è¨ˆæ™‚出了點å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡"
msgid "Something went wrong while adding your award. Please try again."
-msgstr ""
+msgstr "加入讚賞時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong while applying the batch of suggestions. Please try again."
-msgstr ""
+msgstr "套用批次建議時出了點å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong while applying the suggestion. Please try again."
-msgstr ""
+msgstr "套用åŒæ„時出了點å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong while archiving a requirement."
-msgstr ""
+msgstr "歸檔需求時出了錯。"
msgid "Something went wrong while closing the epic. Please try again later."
-msgstr ""
+msgstr "關閉å²è©©æ™‚出了錯。請ç¨å¾Œå†è©¦ã€‚"
msgid "Something went wrong while closing the merge request. Please try again later."
-msgstr ""
+msgstr "關閉åˆä½µè«‹æ±‚時發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "Something went wrong while creating a requirement."
-msgstr ""
+msgstr "建立需求時出了錯。"
msgid "Something went wrong while deleting description changes. Please try again."
-msgstr ""
+msgstr "刪除æ述變更時發生錯誤了,請ç¨å¾Œé‡è©¦ã€‚"
msgid "Something went wrong while deleting the source branch. Please try again."
-msgstr ""
+msgstr "刪除來æºåˆ†æ”¯æ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "Something went wrong while deleting your note. Please try again."
-msgstr ""
+msgstr "刪除備註時發生錯誤。請é‡è©¦ã€‚"
msgid "Something went wrong while deploying this environment. Please try again."
-msgstr ""
+msgstr "部署此環境時發生錯誤。請é‡è©¦ã€‚"
msgid "Something went wrong while editing your comment. Please try again."
-msgstr ""
+msgstr "編輯留言時發生錯誤。請é‡è©¦ã€‚"
msgid "Something went wrong while exporting requirements"
-msgstr ""
+msgstr "匯出需求時出ç¾å•é¡Œ"
msgid "Something went wrong while fetching branches"
-msgstr ""
+msgstr "å–得分支時出了錯。"
msgid "Something went wrong while fetching comments. Please try again."
-msgstr ""
+msgstr "å–得留言時發生錯誤。請ç¨å¾Œé‡è©¦ã€‚"
msgid "Something went wrong while fetching description changes. Please try again."
-msgstr ""
+msgstr "å–å¾—æ述變更時發生錯誤了,請ç¨å¾Œé‡è©¦ã€‚"
msgid "Something went wrong while fetching details"
-msgstr ""
+msgstr "å–得詳細訊æ¯æ™‚發生錯誤"
msgid "Something went wrong while fetching group member contributions"
-msgstr ""
+msgstr "å–得群組æˆå“¡è²¢ç»æ™‚發生錯誤"
msgid "Something went wrong while fetching latest comments."
-msgstr ""
+msgstr "å–得最新留言時發生錯誤。"
msgid "Something went wrong while fetching projects"
-msgstr ""
+msgstr "å–得專案時發生錯誤。"
msgid "Something went wrong while fetching projects."
-msgstr ""
+msgstr "å–得專案時出了錯。"
msgid "Something went wrong while fetching related merge requests."
-msgstr ""
+msgstr "å–得相關的åˆä½µè«‹æ±‚時發生錯誤了。"
msgid "Something went wrong while fetching requirements count."
-msgstr ""
+msgstr "å–得需求數é‡æ™‚出了錯。"
msgid "Something went wrong while fetching requirements list."
-msgstr ""
+msgstr "å–得需求列表時出了錯。"
msgid "Something went wrong while fetching source branches."
-msgstr ""
+msgstr "å–得來æºåˆ†æ”¯æ™‚發生錯誤。"
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
-msgstr ""
+msgstr "å–å¾—æ­¤åˆä½µè«‹æ±‚的環境時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
msgid "Something went wrong while fetching the packages list."
-msgstr ""
+msgstr "å–得軟體套件列表時發生錯誤。"
msgid "Something went wrong while initializing the OpenAPI viewer"
-msgstr ""
+msgstr "åˆå§‹åŒ–OpenAPI查看器時發生錯誤"
msgid "Something went wrong while obtaining the Let's Encrypt certificate."
-msgstr ""
+msgstr "å–å¾—Let's Encrypt憑證時發生錯誤。"
msgid "Something went wrong while promoting the issue to an epic. Please try again."
-msgstr ""
+msgstr "將議題å‡ç´šåˆ°å²è©©æ™‚發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "Something went wrong while reopening a requirement."
-msgstr ""
+msgstr "é‡æ–°æ‰“開需求時發生錯誤。"
msgid "Something went wrong while reopening the epic. Please try again later."
-msgstr ""
+msgstr "é‡æ–°æ‰“é–‹å²è©©æ™‚發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "Something went wrong while reopening the merge request. Please try again later."
-msgstr ""
+msgstr "é‡æ–°é–‹å•Ÿåˆä½µè«‹æ±‚時發生錯誤。請ç¨å¾Œå†è©¦."
msgid "Something went wrong while resolving this discussion. Please try again."
-msgstr ""
+msgstr "解決當å‰è¨Žè«–時發生錯誤,請é‡è©¦ã€‚"
msgid "Something went wrong while setting %{issuableType} %{dateType} date."
-msgstr ""
+msgstr "設定%{issuableType} %{dateType}日期時發生錯誤。"
msgid "Something went wrong while setting %{issuableType} confidentiality."
-msgstr ""
+msgstr "設定%{issuableType}的機密性時發生錯誤。"
msgid "Something went wrong while setting %{issuableType} health status."
-msgstr ""
+msgstr "設定 %{issuableType} å¥åº·ç‹€æ…‹æ™‚發生錯誤。"
msgid "Something went wrong while setting %{issuableType} notifications."
-msgstr ""
+msgstr "設定%{issuableType}的通知時發生錯誤。"
msgid "Something went wrong while setting %{issuableType} to-do item."
-msgstr ""
+msgstr "設定%{issuableType}的待辦事項時發生錯誤。"
msgid "Something went wrong while setting %{issuableType} weight."
-msgstr ""
+msgstr "設定 %{issuableType} 權é‡æ™‚出了錯。"
msgid "Something went wrong while stopping this environment. Please try again."
-msgstr ""
+msgstr "åœæ­¢ç’°å¢ƒæ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "Something went wrong while updating a requirement."
-msgstr ""
+msgstr "更新需求時發生錯誤。"
msgid "Something went wrong while updating assignees"
-msgstr ""
+msgstr "更新指派人時發生錯誤"
msgid "Something went wrong while updating your list settings"
-msgstr ""
+msgstr "更新您的列表設定時發生錯誤"
msgid "Something went wrong with your automatic subscription renewal."
-msgstr ""
+msgstr "自動更新訂閱時發生錯誤。"
msgid "Something went wrong, unable to add %{project} to dashboard"
-msgstr ""
+msgstr "å°‡%{project} 加入到儀表æ¿æ™‚發生錯誤"
msgid "Something went wrong, unable to delete project"
-msgstr ""
+msgstr "發生錯誤,無法刪除專案"
msgid "Something went wrong, unable to get projects"
-msgstr ""
+msgstr "發生錯誤,無法抓å–é …ç›®"
msgid "Something went wrong, unable to search projects"
-msgstr ""
+msgstr "發生錯誤,無法æœå°‹å°ˆæ¡ˆ"
msgid "Something went wrong. Please try again later"
-msgstr ""
+msgstr "發生錯誤,請ç¨å¾Œå†è©¦ã€‚"
msgid "Something went wrong. Please try again."
-msgstr ""
+msgstr "出ç¾éŒ¯èª¤ã€‚è«‹é‡è©¦ã€‚"
msgid "Something went wrong. Try again later."
-msgstr ""
+msgstr "出ç¾éŒ¯èª¤ã€‚è«‹ç¨å¾Œå†è©¦ã€‚"
msgid "Sorry, no projects matched your search"
-msgstr ""
+msgstr "抱歉,未æœå°‹åˆ°ä»»ä½•ç¬¦åˆæ¢ä»¶çš„專案"
msgid "Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further."
-msgstr ""
+msgstr "抱歉,您已經超éŽäº†æœ€å¤§å¯ç€è¦½çš„é é¢æ•¸ã€‚請使用API來進一步å–得資料。"
msgid "Sorry, your filter produced no results"
-msgstr ""
+msgstr "抱歉,沒有符åˆæ‚¨çš„éŽæ¿¾çµæžœ"
msgid "Sort by"
-msgstr ""
+msgstr "排åº"
msgid "Sort direction"
-msgstr ""
+msgstr "排åºæ–¹å‘"
msgid "Sort direction: Ascending"
-msgstr ""
+msgstr "排åºæ–¹å‘:å‡åº"
msgid "Sort direction: Descending"
-msgstr ""
+msgstr "排åºæ–¹å‘:é™åº"
msgid "SortOptions|Blocking"
-msgstr ""
+msgstr "阻塞議題數"
msgid "SortOptions|Closed date"
-msgstr ""
+msgstr "關閉日期"
msgid "SortOptions|Closed earlier"
-msgstr ""
+msgstr "更早關閉"
msgid "SortOptions|Closed recently"
-msgstr ""
+msgstr "最近關閉"
msgid "SortOptions|Created date"
-msgstr ""
+msgstr "建立日期"
msgid "SortOptions|Due date"
-msgstr ""
+msgstr "截止日期"
msgid "SortOptions|Due later"
-msgstr ""
+msgstr "ç¨å¾Œåˆ°æœŸ"
msgid "SortOptions|Due soon"
-msgstr ""
+msgstr "å³å°‡åˆ°æœŸ"
msgid "SortOptions|Expired date"
-msgstr ""
+msgstr "到期日期"
msgid "SortOptions|Label priority"
-msgstr ""
+msgstr "標記優先級"
msgid "SortOptions|Largest group"
-msgstr ""
+msgstr "最大群組"
msgid "SortOptions|Largest repository"
-msgstr ""
+msgstr "最大版本庫"
msgid "SortOptions|Last Contact"
-msgstr ""
+msgstr "最後è¯çµ¡"
msgid "SortOptions|Last created"
-msgstr ""
+msgstr "最近建立時間"
msgid "SortOptions|Least popular"
-msgstr ""
+msgstr "最ä¸å—æ­¡è¿Ž"
msgid "SortOptions|Less weight"
-msgstr ""
+msgstr "é™ä½Žæ¬Šé‡"
msgid "SortOptions|Manual"
-msgstr ""
+msgstr "手動"
msgid "SortOptions|Merged date"
-msgstr ""
+msgstr "åˆä½µæ—¥æœŸ"
msgid "SortOptions|Merged earlier"
-msgstr ""
+msgstr "較早åˆä½µ"
msgid "SortOptions|Merged recently"
-msgstr ""
+msgstr "最近åˆä½µ"
msgid "SortOptions|Milestone due date"
-msgstr ""
+msgstr "里程碑截止日期"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "ç¨å¾Œåˆ°æœŸçš„里程碑"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "å³å°‡åˆ°æœŸçš„里程碑"
msgid "SortOptions|More weight"
-msgstr ""
+msgstr "增加權é‡"
msgid "SortOptions|Most popular"
-msgstr ""
+msgstr "最å—æ­¡è¿Ž"
msgid "SortOptions|Most stars"
-msgstr ""
+msgstr "最多星號"
msgid "SortOptions|Name"
-msgstr ""
+msgstr "å稱"
msgid "SortOptions|Name, ascending"
-msgstr ""
+msgstr "å稱,å‡åºæŽ’列"
msgid "SortOptions|Name, descending"
-msgstr ""
+msgstr "å稱,é™åºæŽ’列"
msgid "SortOptions|Oldest created"
-msgstr ""
+msgstr "最早建立"
msgid "SortOptions|Oldest last activity"
-msgstr ""
+msgstr "最新的活動"
msgid "SortOptions|Oldest sign in"
-msgstr ""
+msgstr "最早的登入"
msgid "SortOptions|Oldest starred"
-msgstr ""
+msgstr "最早收è—(星號)"
msgid "SortOptions|Oldest updated"
-msgstr ""
+msgstr "最早更新"
msgid "SortOptions|Popularity"
-msgstr ""
+msgstr "人氣"
msgid "SortOptions|Priority"
-msgstr ""
+msgstr "優先"
msgid "SortOptions|Project"
-msgstr ""
+msgstr "專案"
msgid "SortOptions|Recent last activity"
-msgstr ""
+msgstr "最近一次活動"
msgid "SortOptions|Recent sign in"
-msgstr ""
+msgstr "最近登入"
msgid "SortOptions|Recently starred"
-msgstr ""
+msgstr "最近收è—(星號)"
msgid "SortOptions|Size"
-msgstr ""
+msgstr "大å°"
msgid "SortOptions|Sort by:"
-msgstr ""
+msgstr "排åºæ–¹å¼ï¼š"
msgid "SortOptions|Sort direction"
-msgstr ""
+msgstr "排åºæ–¹å‘"
msgid "SortOptions|Stars"
-msgstr ""
+msgstr "星號"
msgid "SortOptions|Start date"
-msgstr ""
+msgstr "開始日期"
msgid "SortOptions|Start later"
-msgstr ""
+msgstr "ç¨å¾Œé–‹å§‹"
msgid "SortOptions|Start soon"
-msgstr ""
+msgstr "ç¾åœ¨é–‹å§‹"
msgid "SortOptions|Title"
-msgstr ""
+msgstr "標題"
msgid "SortOptions|Type"
-msgstr ""
+msgstr "é¡žåž‹"
msgid "SortOptions|Version"
-msgstr ""
+msgstr "版本"
msgid "SortOptions|Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Source"
-msgstr ""
+msgstr "來æº"
msgid "Source (branch or tag)"
-msgstr ""
+msgstr "來æº(分支或標籤)"
msgid "Source Branch"
-msgstr ""
+msgstr "來æºåˆ†æ”¯"
msgid "Source IP"
-msgstr ""
+msgstr "來æºIP"
msgid "Source branch"
-msgstr ""
+msgstr "來æºåˆ†æ”¯"
msgid "Source branch will be deleted."
-msgstr ""
+msgstr "來æºåˆ†å°‡è¢«åˆªé™¤"
msgid "Source branch will not be deleted."
-msgstr ""
+msgstr "來æºåˆ†æ”¯å°‡ä¸è¢«åˆªé™¤"
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
-msgstr ""
+msgstr "來æºåˆ†æ”¯: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgid "Source code (%{fileExtension})"
-msgstr ""
+msgstr "來æºç¨‹å¼ç¢¼(%{fileExtension})"
msgid "Source is not available"
-msgstr ""
+msgstr "來æºä¸å¯ç”¨"
msgid "Source project cannot be found."
-msgstr ""
+msgstr "找ä¸åˆ°ä¾†æºå°ˆæ¡ˆã€‚"
msgid "SourceEditor|\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "createInstance() éœ€è¦ \"el\" åƒæ•¸"
msgid "SourceEditor|%{name} is not registered."
-msgstr ""
+msgstr "%{name} 未註冊。"
msgid "SourceEditor|Extension definition should be either a class or a function"
-msgstr ""
+msgstr "擴展定義應該是一個類或一個函數"
msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
-msgstr ""
+msgstr "擴展定義應該是類別ã€å‡½æ•¸æˆ–定義數組。"
msgid "SourceEditor|Extensions Store is required to check for an extension."
-msgstr ""
+msgstr "擴展儲存需è¦æª¢æŸ¥æ“´å±•ã€‚"
msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
-msgstr ""
+msgstr "\"%{prop}()\"方法å稱è¡çªã€‚"
msgid "SourceEditor|No extension for unuse has been specified."
-msgstr ""
+msgstr "未指定未使用的擴展å。"
msgid "SourceEditor|Source Editor instance is required to set up an extension."
-msgstr ""
+msgstr "需è¦ä¾†æºç·¨è¼¯å™¨(Source Editor)實例來設定擴展。"
msgid "SourceEditor|`definition` property is expected on the extension."
-msgstr ""
+msgstr "`definition` 屬性應該在擴展上。"
msgid "Sourcegraph"
-msgstr ""
+msgstr "æºåœ–(Sourcegraph)"
msgid "SourcegraphAdmin|Block on private and internal projects"
-msgstr ""
+msgstr "å°éŽ–ç§æœ‰å’Œå…§éƒ¨å°ˆæ¡ˆ"
msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
-msgstr ""
+msgstr "設定å¯è®€å–GitLab專案的Sourcegraph實體網å€ã€‚"
msgid "SourcegraphAdmin|Enable Sourcegraph"
-msgstr ""
+msgstr "啟用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 "在您的GitLab實體的程å¼ç¢¼æª¢è¦–å’Œåˆä½µè«‹æ±‚上啟用由%{link_start}Sourcegraph%{link_end}æ供的程å¼ç¢¼æ™ºèƒ½ã€‚"
msgid "SourcegraphAdmin|Learn more."
-msgstr ""
+msgstr "了解更多。"
msgid "SourcegraphAdmin|Only public projects have code intelligence enabled and communicate with Sourcegraph."
-msgstr ""
+msgstr "åªæœ‰å…¬é–‹å°ˆæ¡ˆå•Ÿç”¨äº†ç¨‹å¼ç¢¼æ™ºèƒ½ä¸¦èˆ‡ Sourcegraph 進行通信。"
msgid "SourcegraphAdmin|Save changes"
-msgstr ""
+msgstr "儲存變更"
msgid "SourcegraphAdmin|Sourcegraph URL"
-msgstr ""
+msgstr "Sourcegraph網å€"
msgid "SourcegraphAdmin|https://sourcegraph.example.com"
-msgstr ""
+msgstr "https://sourcegraph.example.com"
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
-msgstr ""
+msgstr "此功能是實驗性的,目å‰åƒ…é™æ–¼æŸäº›å°ˆæ¡ˆã€‚"
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
-msgstr ""
+msgstr "此功能是實驗性的,僅é™æ–¼å…¬é–‹å°ˆæ¡ˆã€‚"
msgid "SourcegraphPreferences|This feature is experimental."
-msgstr ""
+msgstr "此功能是實驗性的。"
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
-msgstr ""
+msgstr "使用%{linkStart}Sourcegraph.com%{linkEnd}。"
msgid "SourcegraphPreferences|Uses a custom %{linkStart}Sourcegraph instance%{linkEnd}."
-msgstr ""
+msgstr "使用自訂的%{linkStart}Sourcegraph實例%{linkEnd}。"
msgid "Spam Check"
-msgstr ""
+msgstr "垃圾郵件檢查"
msgid "Spam Check API key"
-msgstr ""
+msgstr "垃圾郵件檢查 API 金鑰"
msgid "Spam Logs"
-msgstr ""
+msgstr "垃圾訊æ¯æ—¥èªŒ"
msgid "Spam and Anti-bot Protection"
-msgstr ""
+msgstr "垃圾訊æ¯åŠé˜²æ©Ÿå™¨äººä¿è­·"
msgid "Spam log successfully submitted as ham."
-msgstr ""
+msgstr "垃圾訊æ¯æ—¥èªŒå·²æˆåŠŸæ”¹ç‚ºæœ‰æ•ˆè¨Šæ¯æ交。"
msgid "Specific runners"
-msgstr ""
+msgstr "指定執行器(runner)"
msgid "Specified URL cannot be used: \"%{reason}\""
-msgstr ""
+msgstr "無法使用指定的URL:「%{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 "指定始終å…許入站æµé‡çš„ IP 範åœï¼Œç”¨æ–¼ç¾¤çµ„ç´š IP é™åˆ¶ã€‚應在此處列出 Runner å’Œ Pages 守護程åºå…§éƒ¨ IP,以便它們å¯ä»¥å­˜å–專案工件。"
msgid "Specify an email address regex pattern to identify default internal users."
-msgstr ""
+msgstr "指定電å­éƒµä»¶åœ°å€æ­£å‰‡è¡¨é”å¼æ¨¡å¼ä»¥æ¨™è­˜é è¨­å…§éƒ¨ä½¿ç”¨è€…。"
msgid "Speed up your pipelines with Needs relationships"
-msgstr ""
+msgstr "通éŽNeeds關係加速您的æµæ°´ç·š"
msgid "Spent at"
-msgstr ""
+msgstr "花費在"
msgid "Squash commit message"
-msgstr ""
+msgstr "壓縮æ交訊æ¯"
msgid "Squash commits"
-msgstr "åˆä½µæ交"
+msgstr "壓縮æ交"
msgid "Stack trace"
-msgstr ""
+msgstr "堆疊追蹤"
msgid "Stacktrace snippet"
-msgstr ""
+msgstr "堆疊追蹤程å¼ç¢¼ç‰‡æ®µ"
msgid "Stage"
-msgstr ""
+msgstr "æš«å­˜"
msgid "Stage:"
-msgstr ""
+msgstr "æš«å­˜:"
msgid "Standard"
-msgstr ""
+msgstr "標準"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
-msgstr ""
+msgstr "把一個標記加上星號,å¯å°‡å…¶è®Šç‚ºå„ªå…ˆæ¨™è¨˜ã€‚é€éŽæ‹–放來調整優先標記的順åºï¼Œå¯ä»¥æ”¹è®Šä»–們的相å°å„ªå…ˆåº¦ã€‚"
msgid "Star labels to start sorting by priority"
-msgstr ""
+msgstr "標記星號以優先排åº"
msgid "Star toggle failed. Try again later."
-msgstr ""
+msgstr "星號切æ›é–‹é—œã€‚è«‹ç¨å¾Œå†è©¦ã€‚"
msgid "StarProject|Star"
-msgstr ""
+msgstr "收è—(星號)"
msgid "Starred Projects"
-msgstr ""
+msgstr "收è—(星號)專案"
msgid "Starred Projects' Activity"
-msgstr ""
+msgstr "收è—(星號)專案的動態"
msgid "Starred projects"
-msgstr ""
+msgstr "星號專案"
msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
-msgstr ""
+msgstr "å­˜å–æŸä¸€å°ˆæ¡ˆé é¢ä¸¦é»žæ“Šæ˜Ÿå½¢åœ–標後å¯ä»¥åœ¨æ­¤é é¢ä¸Šæ‰¾åˆ°è©²å°ˆæ¡ˆã€‚"
msgid "StarredProjectsEmptyState|You don't have starred projects yet."
-msgstr ""
+msgstr "您還沒有已加收è—(星號)的專案。"
msgid "Starrers"
-msgstr ""
+msgstr "收è—(星號)使用者"
msgid "Stars"
-msgstr ""
+msgstr "星號"
msgid "Start Date"
-msgstr ""
+msgstr "開始日期"
msgid "Start Time"
-msgstr ""
+msgstr "開始時間"
msgid "Start Web Terminal"
-msgstr ""
+msgstr "啟動Web終端"
msgid "Start a %{new_merge_request} with these changes"
-msgstr ""
+msgstr "由此變更 %{new_merge_request}"
msgid "Start a Free Ultimate Trial"
-msgstr ""
+msgstr "開始å…費試用旗艦版"
msgid "Start a new discussion…"
-msgstr ""
+msgstr "開始一個新的討論..."
msgid "Start a new merge request with these changes"
-msgstr ""
+msgstr "使用這些變更開始新的åˆä½µè«‹æ±‚"
msgid "Start a review"
-msgstr ""
+msgstr "啟動審閱"
msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
-msgstr ""
+msgstr "首先é¸æ“‡ä¸€å€‹ç¾¤çµ„以開始ç€è¦½è©²ç¾¤çµ„中的åˆä½µè«‹æ±‚。然後您å¯ä»¥æŒ‰å°ˆæ¡ˆã€æ¨™è¨˜ã€é‡Œç¨‹ç¢‘和作者進行éŽæ¿¾ã€‚"
msgid "Start cleanup"
-msgstr ""
+msgstr "開始清ç†"
msgid "Start date"
-msgstr ""
+msgstr "開始日期"
msgid "Start free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "Start inputting changes and we will generate a YAML-file for you to add to your repository"
-msgstr ""
+msgstr "開始輸入更改,我們將產生一個 YAML 文件供您加入到您的版本庫"
msgid "Start internal thread"
-msgstr ""
+msgstr "開始內部線程"
msgid "Start merge train"
-msgstr ""
+msgstr "å•Ÿå‹•åˆä½µä½‡åˆ—"
msgid "Start merge train when pipeline succeeds"
-msgstr ""
+msgstr "æµæ°´ç·šæˆåŠŸæ™‚å•Ÿå‹•åˆä½µä½‡åˆ—"
msgid "Start merge train..."
-msgstr ""
+msgstr "å•Ÿå‹•åˆä½µä½‡åˆ—..."
msgid "Start search"
-msgstr ""
+msgstr "開始æœå°‹"
msgid "Start thread"
-msgstr ""
+msgstr "開啟主題"
msgid "Start your Free Ultimate Trial"
-msgstr ""
+msgstr "開始您的å…費試用"
msgid "Start your free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "Started"
-msgstr ""
+msgstr "已啟動"
msgid "Started %{startsIn}"
-msgstr ""
+msgstr "已開始 %{startsIn}"
msgid "Started asynchronous removal of all repository check states."
-msgstr ""
+msgstr "已開始所有版本庫檢查狀態的éžåŒæ­¥åˆªé™¤ã€‚"
msgid "Started escalation for this incident."
-msgstr ""
+msgstr "已開始å‡ç´šæ­¤äº‹ä»¶(incident)。"
msgid "Starting..."
-msgstr ""
+msgstr "正在啟動..."
msgid "Starts"
-msgstr ""
+msgstr "開始"
msgid "Starts %{startsIn}"
-msgstr ""
+msgstr "開始 %{startsIn}"
msgid "Starts at (UTC)"
-msgstr ""
+msgstr "開始於(UTC)"
msgid "Starts escalations for this incident"
-msgstr ""
+msgstr "開始å‡ç´šæ­¤äº‹ä»¶(incident)"
msgid "Starts on"
-msgstr ""
+msgstr "開始於"
msgid "Starts: %{startsAt}"
-msgstr ""
+msgstr "開始於: %{startsAt}"
msgid "State your message to activate"
-msgstr ""
+msgstr "輸入訊æ¯ä»¥å•Ÿç”¨"
msgid "State/Province"
-msgstr ""
+msgstr "å·ž/çœ"
msgid "State/Province/City"
-msgstr ""
+msgstr "å·ž/çœ/市"
msgid "Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "éœæ…‹æ‡‰ç”¨ç¨‹å¼å®‰å…¨æ¸¬è©¦(SAST)"
msgid "Statistics"
-msgstr ""
+msgstr "統計"
msgid "Status"
-msgstr ""
+msgstr "狀態"
msgid "Status was retried."
-msgstr ""
+msgstr "狀態已é‡è©¦ã€‚"
msgid "Status:"
-msgstr ""
+msgstr "狀態:"
msgid "Status: %{title}"
-msgstr ""
+msgstr "狀態: %{title}"
msgid "StatusCheck| %{failed} failed, and %{pending} pending"
-msgstr ""
+msgstr "%{failed} 個失敗, %{pending} 個待處ç†"
msgid "StatusCheck|%{failed} failed"
-msgstr ""
+msgstr "%{failed} 個失敗"
msgid "StatusCheck|%{pending} pending"
-msgstr ""
+msgstr "%{pending} 等待中"
msgid "StatusCheck|API to check"
-msgstr ""
+msgstr "API檢查"
msgid "StatusCheck|Add status check"
-msgstr ""
+msgstr "加入狀態檢查"
msgid "StatusCheck|All passed"
-msgstr ""
+msgstr "全部通éŽ"
msgid "StatusCheck|An error occurred deleting the %{name} status check."
-msgstr ""
+msgstr "刪除 %{name} 狀態檢查時發生錯誤。"
msgid "StatusCheck|An error occurred fetching the status checks."
-msgstr ""
+msgstr "å–得狀態檢查時發生錯誤。"
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
-msgstr ""
+msgstr "將此狀態檢查套用於所有分支或特定的å—ä¿è­·åˆ†æ”¯ã€‚"
msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
-msgstr ""
+msgstr "在åˆä½µè«‹æ±‚中檢查狀態回應,失敗ä¸æœƒé˜»æ­¢åˆä½µã€‚ %{link_start}了解更多%{link_end}"
msgid "StatusCheck|Examples: QA, Security."
-msgstr ""
+msgstr "示例:QAã€å®‰å…¨ã€‚"
msgid "StatusCheck|External API is already in use by another status check."
-msgstr ""
+msgstr "外部 API 已被å¦ä¸€å€‹ç‹€æ…‹æª¢æŸ¥ä½¿ç”¨ã€‚"
msgid "StatusCheck|Failed to load status checks"
-msgstr ""
+msgstr "載入狀態檢查失敗"
msgid "StatusCheck|Failed to load status checks."
-msgstr ""
+msgstr "無法載入狀態檢查。"
msgid "StatusCheck|Invoke an external API as part of the pipeline process."
-msgstr ""
+msgstr "調用外部 API 作為æµæ°´ç·šéŽç¨‹çš„一部分。"
msgid "StatusCheck|No status checks are defined yet."
-msgstr ""
+msgstr "尚未定義狀態檢查。"
msgid "StatusCheck|Remove status check"
-msgstr ""
+msgstr "移除狀態檢查"
msgid "StatusCheck|Remove status check?"
-msgstr ""
+msgstr "移除狀態檢查?"
msgid "StatusCheck|Service name"
-msgstr ""
+msgstr "æœå‹™å稱"
msgid "StatusCheck|Status checks"
-msgstr ""
+msgstr "狀態檢查"
msgid "StatusCheck|Status checks all passed"
-msgstr ""
+msgstr "狀態檢查全部通éŽ"
msgid "StatusCheck|Status checks are being fetched"
-msgstr ""
+msgstr "正在å–得狀態檢查"
msgid "StatusCheck|Status to check"
-msgstr ""
+msgstr "è¦æª¢æŸ¥çš„狀態"
msgid "StatusCheck|Target branch"
-msgstr ""
+msgstr "目標分支"
msgid "StatusCheck|Update status check"
-msgstr ""
+msgstr "更新狀態檢查"
msgid "StatusCheck|You are about to remove the %{name} status check."
-msgstr ""
+msgstr "您將è¦åˆªé™¤ %{name} 狀態檢查。"
msgid "StatusCheck|status checks"
-msgstr ""
+msgstr "狀態檢查"
msgid "StatusPage|AWS %{docsLink}"
-msgstr ""
+msgstr "AWS %{docsLink}"
msgid "StatusPage|AWS Secret access key"
-msgstr ""
+msgstr "AWS機密存å–金鑰"
msgid "StatusPage|AWS access key ID"
-msgstr ""
+msgstr "AWSå­˜å–金鑰ID"
msgid "StatusPage|AWS region"
-msgstr ""
+msgstr "AWSå€åŸŸ"
msgid "StatusPage|Active"
-msgstr ""
+msgstr "啟用"
msgid "StatusPage|Bucket %{docsLink}"
-msgstr ""
+msgstr "儲存桶%{docsLink}"
msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
-msgstr ""
+msgstr "設定文件儲存設定,將此專案中的議題連çµåˆ°å¤–部狀態é é¢ã€‚"
msgid "StatusPage|S3 Bucket name"
-msgstr ""
+msgstr "S3儲存桶å稱"
msgid "StatusPage|Status page"
-msgstr ""
+msgstr "狀態é "
msgid "StatusPage|Status page URL"
-msgstr ""
+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 ""
+msgstr "è¦åœ¨å¤–部狀態é é¢ç™¼å¸ƒäº‹ä»¶ï¼ŒGitLab需è¦Amazon S3 帳號中儲存一個JSON文件,存放在您的外部狀態é é¢æœå‹™å¯ä»¥å­˜å–çš„ä½ç½®ã€‚ 請確ä¿åŒæ™‚設定%{docsLink}"
msgid "StatusPage|configuration documentation"
-msgstr ""
+msgstr "設定文件"
msgid "StatusPage|your status page frontend."
-msgstr ""
+msgstr "您的狀態é é¢å‰ç«¯"
msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
-msgstr ""
+msgstr "通éŽè¨­å®šPrometheus來監控您的部署,了解環境的效能和å¥åº·åº¦çš„最新狀態。"
msgid "Step %{currentStep} of %{stepCount}"
-msgstr ""
+msgstr "第 %{currentStep} 步,共 %{stepCount} 步"
msgid "Step 1."
-msgstr ""
+msgstr "步驟 1 ."
msgid "Step 2."
-msgstr ""
+msgstr "步驟 2."
msgid "Step 3."
-msgstr ""
+msgstr "步驟 3."
msgid "Step 4."
-msgstr ""
+msgstr "步驟 4."
msgid "Stop Terminal"
-msgstr ""
+msgstr "åœæ­¢çµ‚端"
msgid "Stop impersonation"
-msgstr ""
+msgstr "åœæ­¢èº«ä»½æ¨¡æ“¬"
msgid "Stop this environment"
-msgstr ""
+msgstr "åœæ­¢ç›®å‰ç’°å¢ƒ"
msgid "Stopped"
-msgstr ""
+msgstr "å·²åœæ­¢"
msgid "Stopping..."
-msgstr ""
+msgstr "正在åœæ­¢â€¦â€¦"
msgid "Storage"
-msgstr ""
+msgstr "儲存"
msgid "Storage nodes for new repositories"
-msgstr ""
+msgstr "新版本庫的儲存節點"
msgid "Storage:"
-msgstr ""
+msgstr "儲存:"
msgid "StorageSize|Unknown"
-msgstr ""
+msgstr "未知"
msgid "Store your files, plan your work, collaborate on code, and more."
-msgstr ""
+msgstr "儲存您的文件ã€è¦åŠƒæ‚¨çš„工作ã€ç¨‹å¼ç¢¼å”作等等。"
msgid "Strikethrough"
-msgstr ""
+msgstr "刪除線"
msgid "Strikethrough text"
-msgstr ""
+msgstr "刪除線文字"
msgid "Sub-batch size"
-msgstr ""
+msgstr "å­æ‰¹æ¬¡å¤§å°"
msgid "Subdomains of the Pages root domain %{root_domain} are reserved and cannot be used as custom Pages domains."
-msgstr ""
+msgstr "Pages 根網域 %{root_domain} çš„å­ç¶²åŸŸæ˜¯ä¿ç•™çš„,ä¸èƒ½ç”¨ä½œè‡ªå®šç¾©çš„ Pages 網域。"
msgid "Subgroup information"
-msgstr ""
+msgstr "å­ç¾¤çµ„訊æ¯"
msgid "Subgroup milestone"
-msgstr ""
+msgstr "å­ç¾¤çµ„里程碑"
msgid "Subgroup navigation"
-msgstr ""
+msgstr "å­ç¾¤çµ„導覽"
msgid "SubgroupCreationLevel|Roles allowed to create subgroups"
-msgstr ""
+msgstr "å…許建立å­ç¾¤çµ„的角色"
msgid "SubgroupCreationlevel|Allowed to create subgroups"
-msgstr ""
+msgstr "å…許建立å­ç¾¤çµ„"
msgid "SubgroupCreationlevel|Maintainers"
-msgstr ""
+msgstr "維護者"
msgid "SubgroupCreationlevel|Owners"
-msgstr ""
+msgstr "æ“有者"
msgid "Subgroups"
-msgstr ""
+msgstr "å­ç¾¤çµ„"
msgid "Subgroups and projects"
-msgstr ""
+msgstr "å­ç¾¤çµ„和專案"
msgid "Subgroups can set up their own two-factor authentication rules"
-msgstr ""
+msgstr "å­ç¾¤çµ„å¯ä»¥è¨­ç½®è‡ªå·±çš„雙因å­é©—è­‰è¦å‰‡"
msgid "Subject Key Identifier:"
-msgstr ""
+msgstr "主題金鑰標識符:"
msgid "Subkeys"
-msgstr ""
+msgstr "å­é‡‘é‘°"
msgid "Submit"
-msgstr ""
+msgstr "éžäº¤"
msgid "Submit a review"
-msgstr ""
+msgstr "éžäº¤å¯©é–±"
msgid "Submit as ham"
-msgstr ""
+msgstr "以ham身份éžäº¤"
msgid "Submit as spam"
-msgstr ""
+msgstr "舉報垃圾訊æ¯"
msgid "Submit feedback"
-msgstr ""
+msgstr "éžäº¤å›žé¥‹"
msgid "Submit review"
-msgstr ""
+msgstr "éžäº¤å¯©é–±"
msgid "Submit search"
-msgstr ""
+msgstr "éžäº¤æœå°‹"
msgid "Submit the current review."
-msgstr ""
+msgstr "éžäº¤ç›®å‰å¯©é–±ã€‚"
msgid "Submitted as ham"
-msgstr ""
+msgstr "以ham身份éžäº¤"
msgid "Submitted the current review."
-msgstr ""
+msgstr "å·²éžäº¤ç•¶å‰è©•å¯©ã€‚"
msgid "Subscribe"
-msgstr ""
+msgstr "訂閱"
msgid "Subscribe at group level"
-msgstr ""
+msgstr "在群組級別訂閱"
msgid "Subscribe at project level"
-msgstr ""
+msgstr "在專案級別訂閱"
msgid "Subscribe to RSS feed"
-msgstr ""
+msgstr "訂閱 RSS "
msgid "Subscribe to calendar"
-msgstr ""
+msgstr "訂閱日曆"
msgid "Subscribed"
-msgstr ""
+msgstr "已訂閱"
msgid "Subscribed to this %{quick_action_target}."
-msgstr ""
+msgstr "已訂閱 %{quick_action_target}。"
msgid "Subscribed to this project"
-msgstr ""
+msgstr "已訂閱此專案"
msgid "Subscribes to this %{quick_action_target}."
-msgstr ""
+msgstr "訂閱%{quick_action_target}。"
msgid "Subscript"
-msgstr ""
+msgstr "下標"
msgid "Subscription"
-msgstr ""
+msgstr "訂閱"
msgid "Subscription History"
-msgstr ""
+msgstr "訂閱歷å²"
msgid "Subscription deletion failed."
-msgstr ""
+msgstr "訂閱刪除失敗。"
msgid "Subscription service outage"
-msgstr ""
+msgstr "訂閱æœå‹™ä¸­æ–·"
msgid "Subscription successfully applied to \"%{group_name}\""
-msgstr ""
+msgstr "訂閱æˆåŠŸæ‡‰ç”¨æ–¼ã€Œ%{group_name}ã€"
msgid "Subscription successfully created."
-msgstr ""
+msgstr "訂閱已æˆåŠŸå»ºç«‹ã€‚"
msgid "Subscription successfully deleted."
-msgstr ""
+msgstr "訂閱已æˆåŠŸåˆªé™¤ã€‚"
msgid "SubscriptionBanner|Add new license"
-msgstr ""
+msgstr "加入新的授權許å¯"
msgid "SubscriptionBanner|Export license usage file"
-msgstr ""
+msgstr "匯出授權許å¯ä½¿ç”¨æ–‡ä»¶"
msgid "SubscriptionBanner|Upload new license"
-msgstr ""
+msgstr "上傳新授權"
msgid "SubscriptionTable|Add seats"
-msgstr ""
+msgstr "加入席次"
msgid "SubscriptionTable|An error occurred while loading the subscription details."
-msgstr ""
+msgstr "載入訂閱訊æ¯æ™‚發生錯誤。"
msgid "SubscriptionTable|Billing"
-msgstr ""
+msgstr "帳單"
msgid "SubscriptionTable|Free"
-msgstr ""
+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 ""
+msgstr "GitLab å…許您繼續使用您的訂閱,å³ä½¿æ‚¨å·²è¶…éŽæ‚¨è³¼è²·çš„最大使用者數é‡ã€‚您必須在續訂時支付這些訂閱。"
msgid "SubscriptionTable|Last invoice"
-msgstr ""
+msgstr "最後一個發票"
msgid "SubscriptionTable|Loading subscriptions"
-msgstr ""
+msgstr "載入訂閱"
msgid "SubscriptionTable|Manage"
-msgstr ""
+msgstr "管ç†"
msgid "SubscriptionTable|Max seats used"
-msgstr ""
+msgstr "已使用的最大使用者數é‡"
msgid "SubscriptionTable|Next invoice"
-msgstr ""
+msgstr "下一張發票"
msgid "SubscriptionTable|Refresh Seats"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†å¸­æ¬¡"
msgid "SubscriptionTable|Renew"
-msgstr ""
+msgstr "續訂"
msgid "SubscriptionTable|Seats currently in use"
-msgstr ""
+msgstr "ç›®å‰æ­£åœ¨ä½¿ç”¨çš„使用者數é‡"
msgid "SubscriptionTable|Seats in subscription"
-msgstr ""
+msgstr "訂閱中的使用者數é‡"
msgid "SubscriptionTable|Seats owed"
-msgstr ""
+msgstr "欠款使用者數é‡"
msgid "SubscriptionTable|See usage"
-msgstr ""
+msgstr "查看使用情æ³"
msgid "SubscriptionTable|Something went wrong trying to refresh seats"
-msgstr ""
+msgstr "嘗試é‡æ–°æ•´ç†å¸­æ¬¡æ™‚發生錯誤"
msgid "SubscriptionTable|Subscription end date"
-msgstr ""
+msgstr "訂閱çµæŸæ—¥æœŸ"
msgid "SubscriptionTable|Subscription start date"
-msgstr ""
+msgstr "訂閱開始日期"
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
-msgstr ""
+msgstr "這是 GitLab.com 團隊關於您的欠款最近一次與您è¯çµ¡çš„時間。"
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
-msgstr ""
+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 ""
+msgstr "這是 GitLab.com 團隊關於您的欠款下一次與您è¯çµ¡çš„時間。"
msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
-msgstr ""
+msgstr "這是您更新到付費方案時需è¦è³¼è²·çš„最大使用者數é‡ã€‚"
msgid "SubscriptionTable|Trial"
-msgstr ""
+msgstr "試用"
msgid "SubscriptionTable|Trial end date"
-msgstr ""
+msgstr "試用çµæŸæ—¥æœŸ"
msgid "SubscriptionTable|Trial start date"
-msgstr ""
+msgstr "試用開始日期"
msgid "SubscriptionTable|Usage"
-msgstr ""
+msgstr "使用情æ³"
msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
-msgstr ""
+msgstr "使用次數將在æ¯å¤©ä¸­åˆ12:00進行更新。"
msgid "Subscriptions"
-msgstr ""
+msgstr "訂閱"
msgid "Subscriptions|Chat with sales"
-msgstr ""
+msgstr "與銷售交談"
msgid "Subscriptions|Close"
-msgstr ""
+msgstr "關閉"
msgid "Subscriptions|Not ready to buy yet?"
-msgstr ""
+msgstr "尚未準備好購買?"
msgid "Subscriptions|Start a free trial"
-msgstr ""
+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 ""
+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 ""
+msgstr "æ‚¨å° %{strong}%{namespace_name}%{strong_close} 的訂閱已éŽæœŸï¼Œæ‚¨ç¾åœ¨åœ¨ %{pricing_link_start}標準版%{pricing_link_end}了。別擔心,您的資料是安全的。請è¯çµ¡æˆ‘們的支æ´åœ˜éšŠï¼ˆ%{support_email})。他們將樂æ„幫助您更新訂閱。"
msgid "Subtracted"
-msgstr ""
+msgstr "已減去"
msgid "Subtracts"
-msgstr ""
+msgstr "減去"
msgid "Succeeded"
-msgstr ""
-
-msgid "Successful purchase image"
-msgstr ""
+msgstr "å·²æˆåŠŸ"
msgid "Successfully activated"
-msgstr ""
+msgstr "å·²æˆåŠŸå•Ÿå‹•"
msgid "Successfully approved"
-msgstr ""
+msgstr "å·²æˆåŠŸæ ¸å‡†"
msgid "Successfully banned"
-msgstr ""
+msgstr "å·²æˆåŠŸç¦æ­¢"
msgid "Successfully blocked"
-msgstr ""
+msgstr "å·²æˆåŠŸå°éŽ–"
msgid "Successfully confirmed"
-msgstr ""
+msgstr "å·²æˆåŠŸç¢ºèª"
msgid "Successfully deactivated"
-msgstr ""
+msgstr "å·²æˆåŠŸå‡çµ"
msgid "Successfully deleted U2F device."
-msgstr ""
+msgstr "æˆåŠŸåˆªé™¤ U2F 設備。"
msgid "Successfully deleted WebAuthn device."
-msgstr ""
+msgstr "å·²æˆåŠŸåˆªé™¤WebAuthn設備。"
msgid "Successfully removed email."
-msgstr ""
+msgstr "æˆåŠŸåˆªé™¤é›»å­éƒµä»¶ã€‚"
msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
-msgstr ""
+msgstr "æµæ°´ç·šå·²å®‰æŽ’執行。請查看 %{pipelines_link_start}æµæ°´ç·šé é¢%{pipelines_link_end}ä»¥äº†è§£è©³ç´°è¨Šæ¯ ã€‚"
msgid "Successfully synced %{synced_timeago}."
-msgstr ""
+msgstr "å·²æˆåŠŸåŒæ­¥æ–¼%{synced_timeago}。"
msgid "Successfully unbanned"
-msgstr ""
+msgstr "å·²æˆåŠŸè§£ç¦"
msgid "Successfully unblocked"
-msgstr ""
+msgstr "å·²æˆåŠŸè§£é™¤å°éŽ–"
msgid "Successfully unlocked"
-msgstr ""
+msgstr "å·²æˆåŠŸè§£é™¤éŽ–定"
msgid "Successfully updated %{last_updated_timeago}."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°æ–¼%{last_updated_timeago}."
msgid "Successfully updated the environment."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°ç’°å¢ƒã€‚"
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
-msgstr ""
+msgstr "å¯ä»¥ä¸€éµç«‹åˆ»å¥—用的建議程å¼ç¢¼è®Šæ›´åŠŸèƒ½ã€‚試試看ï¼"
msgid "Suggested change"
-msgstr ""
+msgstr "變更建議"
msgid "SuggestedColors|Aztec Gold"
-msgstr ""
+msgstr "阿茲特克金色"
msgid "SuggestedColors|Blue"
-msgstr ""
+msgstr "è—色"
msgid "SuggestedColors|Blue-gray"
-msgstr ""
+msgstr "è—ç°è‰²"
msgid "SuggestedColors|Carrot orange"
-msgstr ""
+msgstr "胡蘿蔔橙色"
msgid "SuggestedColors|Champagne"
-msgstr ""
+msgstr "香檳色"
msgid "SuggestedColors|Charcoal grey"
-msgstr ""
+msgstr "ç‚­ç°è‰²"
msgid "SuggestedColors|Crimson"
-msgstr ""
+msgstr "深紅色"
msgid "SuggestedColors|Current addition color"
-msgstr ""
+msgstr "當å‰åŠ å…¥çš„é¡è‰²"
msgid "SuggestedColors|Current removal color"
-msgstr ""
+msgstr "當å‰ç§»é™¤çš„é¡è‰²"
msgid "SuggestedColors|Dark coral"
-msgstr ""
+msgstr "æš—çŠç‘šè‰²"
msgid "SuggestedColors|Dark green"
-msgstr ""
+msgstr "深綠色"
msgid "SuggestedColors|Dark sea green"
-msgstr ""
+msgstr "深海綠"
msgid "SuggestedColors|Dark violet"
-msgstr ""
+msgstr "暗紫色"
msgid "SuggestedColors|Deep violet"
-msgstr ""
+msgstr "深紫色"
msgid "SuggestedColors|Default addition color"
-msgstr ""
+msgstr "é è¨­åŠ å…¥çš„é¡è‰²"
msgid "SuggestedColors|Default removal color"
-msgstr ""
+msgstr "é è¨­ç§»é™¤çš„é¡è‰²"
msgid "SuggestedColors|Gray"
-msgstr ""
+msgstr "ç°è‰²"
msgid "SuggestedColors|Green"
-msgstr ""
+msgstr "綠色"
msgid "SuggestedColors|Green screen"
-msgstr ""
+msgstr "綠å±"
msgid "SuggestedColors|Green-cyan"
-msgstr ""
+msgstr "綠é’色"
msgid "SuggestedColors|Lavendar"
-msgstr ""
+msgstr "è–°è¡£è‰ç´«"
msgid "SuggestedColors|Magenta-pink"
-msgstr ""
+msgstr "å“紅色-粉色"
msgid "SuggestedColors|Medium sea green"
-msgstr ""
+msgstr "中海綠"
msgid "SuggestedColors|Orange"
-msgstr ""
+msgstr "橙色"
msgid "SuggestedColors|Purple"
-msgstr ""
+msgstr "紫色"
msgid "SuggestedColors|Red"
-msgstr ""
+msgstr "紅色"
msgid "SuggestedColors|Rose red"
-msgstr ""
+msgstr "玫瑰紅色"
msgid "SuggestedColors|Titanium yellow"
-msgstr ""
+msgstr "鈦黃色"
msgid "Suggestion is not applicable as the suggestion was not found."
-msgstr ""
+msgstr "建議ä¸é©ç”¨ï¼Œå› ç‚ºç„¡æ³•æ‰¾åˆ°å»ºè­°ã€‚"
msgid "Suggestions are not applicable as one or more suggestions were not found."
-msgstr ""
+msgstr "建議ä¸é©ç”¨ï¼Œå› ç‚ºç„¡æ³•æ‰¾åˆ°ä¸€å€‹æˆ–多個建議。"
msgid "Suggestions are not applicable as their lines cannot overlap."
-msgstr ""
+msgstr "建議ä¸é©ç”¨ï¼Œå› ç‚ºå®ƒå€‘çš„ç·š(lines)ä¸èƒ½é‡ç–Šã€‚"
msgid "Suggestions must all be on the same branch."
-msgstr ""
+msgstr "建議必須都在åŒä¸€å€‹åˆ†æ”¯ä¸Šã€‚"
msgid "Suggestions:"
-msgstr ""
+msgstr "建議:"
msgid "Suite"
-msgstr ""
+msgstr "測試集"
msgid "Summary"
-msgstr ""
+msgstr "概è¦"
msgid "Summary / note"
-msgstr ""
+msgstr "摘è¦/註釋"
msgid "Summary comment (optional)"
-msgstr ""
+msgstr "摘è¦è©•è«–(å¯é¸ï¼‰"
msgid "Sunday"
-msgstr ""
+msgstr "星期日"
msgid "SuperSonics|Activate subscription"
-msgstr ""
+msgstr "啟用訂閱"
msgid "SuperSonics|Activation code"
-msgstr ""
+msgstr "啟用碼"
msgid "SuperSonics|An error occurred while adding your subscription."
-msgstr ""
+msgstr "增加訂閱時發生錯誤"
msgid "SuperSonics|Billable users"
-msgstr ""
+msgstr "å¯è¨ˆè²»çš„使用者"
msgid "SuperSonics|Buy subscription"
-msgstr ""
+msgstr "購買訂閱"
msgid "SuperSonics|Cannot activate instance due to a connectivity issue."
-msgstr ""
+msgstr "由於連線å•é¡Œï¼Œç„¡æ³•å•Ÿç”¨å¯¦ä¾‹ã€‚"
msgid "SuperSonics|Cloud licensing"
-msgstr ""
+msgstr "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 "Cloud 授權許å¯ç¾å·²æŽ¨å‡ºã€‚這是啟用實例和管ç†è¨‚閱的更簡單方法。閱讀 %{blogPostLinkStart}部è½æ ¼æ–‡ç« %{blogPostLinkEnd}中的更多相關訊æ¯ã€‚啟用碼在 %{portalLinkStart}客戶入å£ç¶²%{portalLinkEnd}中å¯ç”¨ã€‚"
msgid "SuperSonics|Enter activation code"
-msgstr ""
+msgstr "輸入啟用碼"
msgid "SuperSonics|Export license usage file"
-msgstr ""
+msgstr "匯出授權許å¯ä½¿ç”¨æ–‡ä»¶"
msgid "SuperSonics|Free trial"
-msgstr ""
+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 ""
+msgstr "我åŒæ„æˆ‘å° GitLab 軟體的使用必須éµå®ˆä½æ–¼ %{linkStart}æœå‹™æ¢æ¬¾%{linkEnd} 的訂閱å”議, 除éžèˆ‡GitLabå¦æœ‰æ›¸é¢å”議。"
msgid "SuperSonics|Learn how to %{linkStart}activate your subscription%{linkEnd}."
-msgstr ""
+msgstr "了解如何 %{linkStart}啟用您的訂閱%{linkEnd}。"
msgid "SuperSonics|Learn more about %{activationLinkStart}activating your subscription%{activationLinkEnd}. If you need further assistance, %{supportLinkStart}contact GitLab Support%{supportLinkEnd}."
-msgstr ""
+msgstr "詳細了解 %{activationLinkStart}啟用您的訂閱%{activationLinkEnd}。 如果您需è¦é€²ä¸€æ­¥çš„幫助,%{supportLinkStart}è¯çµ¡ GitLab 支æ´%{supportLinkEnd}。"
msgid "SuperSonics|Licensed to"
-msgstr ""
+msgstr "授權許å¯æ–¼"
msgid "SuperSonics|Manage"
-msgstr ""
+msgstr "管ç†"
msgid "SuperSonics|Maximum users"
-msgstr ""
+msgstr "最大使用者數"
msgid "SuperSonics|Offline license"
-msgstr ""
+msgstr "離線授權許å¯"
msgid "SuperSonics|Online license"
-msgstr ""
+msgstr "在線授權許å¯"
msgid "SuperSonics|Paste your activation code"
-msgstr ""
+msgstr "貼上您的啟用碼"
msgid "SuperSonics|Please agree to the Subscription Agreement"
-msgstr ""
+msgstr "è«‹åŒæ„訂閱å”è­°"
msgid "SuperSonics|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
-msgstr ""
+msgstr "準備好開始了嗎? GitLab 方案éžå¸¸é©åˆæ“´å±•çµ„織和多團隊使用。"
msgid "SuperSonics|Start free trial"
-msgstr ""
+msgstr "開始å…費試用"
msgid "SuperSonics|Subscription details"
-msgstr ""
+msgstr "訂閱詳情"
msgid "SuperSonics|Subscription unavailable"
-msgstr ""
+msgstr "訂閱ä¸å¯ç”¨"
msgid "SuperSonics|Sync subscription details"
-msgstr ""
+msgstr "åŒæ­¥è¨‚閱詳情"
msgid "SuperSonics|Sync subscription request."
-msgstr ""
+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 ""
+msgstr "啟用碼無效。請確ä¿å¾žå®¢æˆ¶ç«¯å…¥å£ç¶²æˆ–確èªé›»å­éƒµä»¶ä¸­æº–確複製。 了解更多關於 %{linkStart}啟用您的訂閱%{linkEnd}。"
msgid "SuperSonics|The activation code should be a 24-character alphanumeric string"
-msgstr ""
+msgstr "啟用碼應該是一個24個字元的字æ¯æ•¸å­—字元串"
msgid "SuperSonics|There is a connectivity issue."
-msgstr ""
+msgstr "存在連接å•é¡Œã€‚"
msgid "SuperSonics|This is the highest peak of users on your installation since the license started."
-msgstr ""
+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 ""
+msgstr "這是 %{billableUsersLinkStart}計費使用者%{billableUsersLinkEnd}的數é‡ï¼Œä¹Ÿæ˜¯æ‚¨çºŒè¨‚授權許å¯æ™‚需è¦è³¼è²·çš„最å°æ•¸é‡ã€‚"
msgid "SuperSonics|To activate your subscription, your instance needs to connect to GitLab. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "è¦å•Ÿç”¨æ‚¨çš„訂閱,您的實例需è¦é€£æŽ¥åˆ° GitLab。 %{learnMoreLinkStart}了解更多信æ¯%{learnMoreLinkEnd}。"
msgid "SuperSonics|User in subscription"
msgid_plural "SuperSonics|Users in subscription"
-msgstr[0] ""
+msgstr[0] "訂閱使用者"
msgid "SuperSonics|Users in subscription"
-msgstr ""
+msgstr "訂閱數內的使用者"
msgid "SuperSonics|Users over subscription"
-msgstr ""
+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 ""
+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 ""
+msgstr "您å¯ä»¥%{purchaseSubscriptionLinkStart}購買新訂閱%{purchaseSubscriptionLinkEnd},然後é‡è©¦ã€‚如果您需è¦é€²ä¸€æ­¥çš„幫助,請 %{supportLinkStart}è¯ç¹« 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 "您無法å†å°‡è¨‚閱詳細訊æ¯èˆ‡ GitLab åŒæ­¥ã€‚ %{connectivityHelpLinkStart}通éŽå°å•Ÿç”¨ç¢¼é€²è¡Œæ•…障排除%{connectivityHelpLinkEnd},å–得有關最常見連接å•é¡Œçš„幫助。"
msgid "SuperSonics|You can start a free trial of GitLab Ultimate without any obligation or payment details."
-msgstr ""
+msgstr "您å¯ä»¥é–‹å§‹å…費試用 GitLab 旗艦版,無需任何承諾或付款訊æ¯ã€‚"
msgid "SuperSonics|You do not have an active subscription"
-msgstr ""
+msgstr "您沒有有效訂閱"
msgid "SuperSonics|You have a future dated license"
-msgstr ""
+msgstr "您有一個未到期的授權許å¯"
msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details."
-msgstr ""
+msgstr "您已經加入了啟用於 %{date} 的授權許å¯ã€‚詳情請查看下é¢çš„訂閱歷å²è¡¨ã€‚"
msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details."
-msgstr ""
+msgstr "您已æˆåŠŸåŠ å…¥åœ¨ %{date} 啟用的授權許å¯ã€‚有關更多詳細訊æ¯ï¼Œè«‹åƒé–±ä¸‹é¢çš„訂閱歷å²è¡¨ã€‚"
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 "根據您的å”è­°æ¢æ¬¾ï¼Œæ‚¨å°‡æŒ‰å­£åº¦æˆ–æ¯å¹´ç‚º %{trueUpLinkStart} 超éŽæŽˆæ¬Šè¨±å¯çš„使用者%{trueUpLinkEnd}付費。"
msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again."
-msgstr ""
+msgstr "您的 %{subscriptionEntryName} 暫時無法顯示。請é‡æ–°æ•´ç†æ­¤é é¢ã€‚"
msgid "SuperSonics|Your future dated license was successfully added"
-msgstr ""
+msgstr "您的未到期授權許å¯å·²æˆåŠŸåŠ å…¥"
msgid "SuperSonics|Your subscription"
-msgstr ""
+msgstr "您的訂閱"
msgid "SuperSonics|Your subscription details will sync shortly."
-msgstr ""
+msgstr "您的訂閱訊æ¯å°‡å¾ˆå¿«åŒæ­¥"
msgid "SuperSonics|Your subscription is expired."
-msgstr ""
+msgstr "您的訂閱已到期"
msgid "SuperSonics|Your subscription was successfully activated. You can see the details below."
-msgstr ""
+msgstr "您的訂閱已æˆåŠŸå•Ÿç”¨ã€‚您å¯ä»¥åœ¨ä¸‹é¢æŸ¥çœ‹è©³ç´°è¨Šæ¯ã€‚"
msgid "SuperSonics|current subscription"
-msgstr ""
+msgstr "當å‰è¨‚é–±"
msgid "SuperSonics|future subscriptions"
-msgstr ""
+msgstr "未來的訂閱"
msgid "SuperSonics|past subscriptions"
-msgstr ""
+msgstr "以å‰çš„訂閱"
msgid "Superscript"
-msgstr ""
+msgstr "上標"
msgid "Support"
-msgstr ""
+msgstr "支æ´"
msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+msgstr "å°è‡ªè¨‚憑證的支æ´å·²åœç”¨ã€‚è«‹è¯çµ¡ç³»çµ±ç®¡ç†å“¡ä¾†å•Ÿç”¨å®ƒã€‚"
msgid "Support page URL"
-msgstr ""
-
-msgid "Survey Response"
-msgstr ""
+msgstr "支æ´é é¢ç¶²å€"
msgid "Surveys|Delighted"
-msgstr ""
+msgstr "愉悅"
msgid "Surveys|Happy"
-msgstr ""
+msgstr "快樂"
msgid "Surveys|Neutral"
-msgstr ""
+msgstr "一般"
msgid "Surveys|Sad"
-msgstr ""
+msgstr "傷心"
msgid "Surveys|Unhappy"
-msgstr ""
+msgstr "ä¸å¿«æ¨‚"
msgid "Switch Branches"
-msgstr ""
+msgstr "切æ›åˆ†æ”¯"
msgid "Switch branch"
-msgstr ""
+msgstr "切æ›åˆ†æ”¯"
msgid "Switch branch/tag"
-msgstr ""
+msgstr "切æ›åˆ†æ”¯/標籤"
msgid "Switch to GitLab Next"
-msgstr ""
+msgstr "切æ›åˆ°GitLab é è¦½ç‰ˆ"
msgid "Switch to the source to copy the file contents"
-msgstr ""
+msgstr "切æ›åˆ°ä¾†æºä»¥è¤‡è£½æ–‡ä»¶å…§å®¹"
msgid "Symbolic link"
-msgstr ""
+msgstr "符號連çµ"
msgid "Sync LDAP"
-msgstr ""
+msgstr "åŒæ­¥ LDAP"
msgid "Sync now"
-msgstr ""
+msgstr "ç«‹å³åŒæ­¥"
msgid "Synced"
-msgstr ""
+msgstr "å·²åŒæ­¥"
msgid "Synchronize LDAP"
-msgstr ""
+msgstr "åŒæ­¥ LDAP"
msgid "Syncing…"
-msgstr ""
+msgstr "åŒæ­¥ä¸­..."
msgid "Syntax is correct."
-msgstr ""
+msgstr "語法正確。"
msgid "Syntax is incorrect."
-msgstr ""
+msgstr "語法ä¸æ­£ç¢ºã€‚"
msgid "SynthaxHighlightingTheme|Dark"
-msgstr ""
+msgstr "深色"
msgid "SynthaxHighlightingTheme|Light"
-msgstr ""
+msgstr "淺色"
msgid "SynthaxHighlightingTheme|Monokai"
-msgstr ""
+msgstr "Monokai"
msgid "SynthaxHighlightingTheme|None"
-msgstr ""
+msgstr "ç„¡"
msgid "SynthaxHighlightingTheme|Solarized Dark"
-msgstr ""
+msgstr "Solarized Dark"
msgid "SynthaxHighlightingTheme|Solarized Light"
-msgstr ""
+msgstr "Solarized Light"
msgid "System"
-msgstr ""
+msgstr "系統"
msgid "System Hooks"
-msgstr ""
+msgstr "系統鉤å­(Hooks) "
msgid "System Hooks Help"
-msgstr ""
+msgstr "系統鉤å­(Hooks)幫助"
msgid "System Info"
-msgstr ""
+msgstr "系統訊æ¯"
msgid "System default (%{default})"
-msgstr ""
+msgstr "系統é è¨­å€¼ï¼ˆ%{default})"
msgid "System header and footer"
-msgstr ""
+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 "系統鉤å­(hooks)是在一系列事件上觸發的,例如建立專案或加入 SSH 金鑰。您還å¯ä»¥å•Ÿç”¨é¡å¤–的觸發器,例如推é€äº‹ä»¶ã€‚"
msgid "System metrics (Custom)"
-msgstr ""
+msgstr "系統指標(自訂)"
msgid "System metrics (Kubernetes)"
-msgstr ""
+msgstr "系統指標(Kubernetes)"
msgid "System output"
-msgstr ""
+msgstr "系統輸出"
+
+msgid "System started"
+msgstr "系統已啟動"
msgid "Table of Contents"
-msgstr ""
+msgstr "目錄"
msgid "Table of contents"
-msgstr ""
+msgstr "目錄"
msgid "Tag"
msgstr "標籤"
msgid "Tag list:"
-msgstr ""
+msgstr "標籤列表:"
msgid "Tag name"
-msgstr ""
+msgstr "標籤å稱"
msgid "Tag name is required."
-msgstr ""
+msgstr "標籤å稱為必è¦ã€‚"
msgid "Tag push"
-msgstr ""
+msgstr "標籤推é€"
msgid "Tag push events"
-msgstr ""
+msgstr "標籤推é€äº‹ä»¶"
msgid "Tag this commit."
-msgstr ""
+msgstr "為此æ交上標籤。"
msgid "Tag:"
-msgstr ""
+msgstr "標籤:"
msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
-msgstr ""
+msgstr "使用「%{message}ã€ç‚ºæ­¤æ交設定%{tag_name} 標籤。"
msgid "Tagged this commit to %{tag_name}."
-msgstr ""
+msgstr "將此æ交標記為%{tag_name}。"
msgid "Tags"
msgstr "標籤"
msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
-msgstr ""
+msgstr "標籤刪除直到逾時為止。任何剩餘標籤都將包括在下次執行政策中。è¦è§£é™¤æ™‚é–“é™åˆ¶ï¼Œè«‹è¨­å®šç‚º0。"
msgid "Tags feed"
-msgstr ""
+msgstr "標籤動態"
msgid "Tags this commit to %{tag_name} with \"%{message}\"."
-msgstr ""
+msgstr "使用「%{message}ã€å°‡æ­¤æ交設定%{tag_name}標籤。"
msgid "Tags this commit to %{tag_name}."
-msgstr ""
+msgstr "將此æ交設定%{tag_name}標籤。"
msgid "Tags:"
-msgstr ""
+msgstr "標籤:"
msgid "TagsPage|After you confirm and select %{strongStart}%{buttonText},%{strongEnd} you cannot recover this tag."
-msgstr ""
+msgstr "在您確èªä¸¦é¸æ“‡ %{strongStart}%{buttonText},%{strongEnd}後,您將無法æ¢å¾©æ­¤æ¨™ç±¤ã€‚"
msgid "TagsPage|Browse commits"
-msgstr ""
+msgstr "ç€è¦½æ交"
msgid "TagsPage|Browse files"
-msgstr ""
+msgstr "ç€è¦½æ–‡ä»¶"
msgid "TagsPage|Can't find HEAD commit for this tag"
-msgstr ""
+msgstr "無法找到此標籤的HEADæ交"
msgid "TagsPage|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "TagsPage|Cancel, keep tag"
-msgstr ""
+msgstr "å–消,ä¿ç•™æ¨™ç±¤"
+
+msgid "TagsPage|Create release"
+msgstr "建立發布版本"
msgid "TagsPage|Create tag"
-msgstr ""
+msgstr "建立標籤"
msgid "TagsPage|Delete protected tag"
-msgstr ""
+msgstr "刪除å—ä¿è­·æ¨™ç±¤"
msgid "TagsPage|Delete protected tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "刪除å—ä¿è­·çš„標籤,您å分確定嗎?"
msgid "TagsPage|Delete tag"
-msgstr ""
+msgstr "刪除標籤"
msgid "TagsPage|Delete tag. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "刪除標籤,您å分確定嗎?"
msgid "TagsPage|Deleting the %{strongStart}%{tagName}%{strongEnd} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "刪除 %{strongStart}%{tagName}%{strongEnd} 標籤無法撤消,您確定嗎?"
-msgid "TagsPage|Edit release notes"
-msgstr ""
+msgid "TagsPage|Edit release"
+msgstr "編輯發布版本"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "已存在分支å稱,標記或æ交SHA"
msgid "TagsPage|Filter by tag name"
-msgstr ""
+msgstr "根據標籤å稱éŽæ¿¾"
msgid "TagsPage|New Tag"
-msgstr ""
+msgstr "建立標籤"
msgid "TagsPage|New tag"
-msgstr ""
+msgstr "建立標籤"
msgid "TagsPage|Only a project maintainer or owner can delete a protected tag"
-msgstr ""
+msgstr "åªæœ‰å°ˆæ¡ˆç¶­è­·è€…或æ“有者æ‰èƒ½åˆªé™¤å—ä¿è­·çš„標籤"
msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
-msgstr ""
+msgstr "也å¯ä»¥åŠ å…¥æ¶ˆæ¯åˆ°æ¨™ç±¤ã€‚ä¿ç•™ç©ºç™½å‰‡å»ºç«‹ %{link_start}輕é‡æ¨™ç±¤%{link_end}。"
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 "或者,根據此標籤建立專案的公開版本。 發行說明顯示在 %{releases_page_link_start}Releases%{link_end} é é¢ä¸Šã€‚ %{docs_link_start}更多訊æ¯%{link_end}"
msgid "TagsPage|Please type the following to confirm:"
-msgstr ""
+msgstr "請輸入以下內容進行確èªï¼š"
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "發行說明"
msgid "TagsPage|Repository has no tags yet."
-msgstr ""
+msgstr "版本庫還沒有標籤。"
msgid "TagsPage|Sorry, your filter produced no results."
-msgstr ""
+msgstr "抱歉,您的éŽæ¿¾å™¨æ²’有產生任何çµæžœã€‚"
msgid "TagsPage|Tags"
-msgstr ""
+msgstr "標籤"
msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
-msgstr ""
+msgstr "標籤å¯ä»¥å°‡æ­·å²ä¸­çš„特定點標示為é‡è¦çš„"
msgid "TagsPage|This tag has no release notes."
-msgstr ""
+msgstr "此標籤無發行說明。"
msgid "TagsPage|Unable to load tags"
-msgstr ""
+msgstr "無法載入標籤"
msgid "TagsPage|Use git tag command to add a new one:"
-msgstr ""
+msgstr "使用git tag指令加入一個:"
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "編寫發行說明(Release Notes)或將文件拖動到此處..."
msgid "TagsPage|Yes, delete protected tag"
-msgstr ""
+msgstr "是的,刪除å—ä¿è­·çš„標籤"
msgid "TagsPage|Yes, delete tag"
-msgstr ""
+msgstr "是的,刪除標籤"
msgid "TagsPage|You're about to permanently delete the protected tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "您å³å°‡æ°¸ä¹…刪除å—ä¿è­·çš„標籤 %{strongStart}%{tagName}。%{strongEnd}"
msgid "TagsPage|You're about to permanently delete the tag %{strongStart}%{tagName}.%{strongEnd}"
-msgstr ""
+msgstr "您å³å°‡æ°¸ä¹…刪除標籤 %{strongStart}%{tagName}。%{strongEnd}"
msgid "TagsPage|protected"
-msgstr ""
+msgstr "å·²ä¿è­·"
msgid "Take a look at the documentation to discover all of GitLab’s capabilities."
-msgstr ""
+msgstr "查看文件以了解 GitLab 的所有功能。"
msgid "Target Branch"
-msgstr ""
+msgstr "目標分支"
msgid "Target Path"
-msgstr ""
+msgstr "目標路徑"
msgid "Target branch"
-msgstr ""
+msgstr "目標分支"
msgid "Target branch or tag"
-msgstr ""
+msgstr "目標分支或標籤"
msgid "Target roles"
-msgstr ""
+msgstr "目標角色"
msgid "Target-Branch"
-msgstr ""
+msgstr "目標分支"
msgid "Task"
-msgstr ""
+msgstr "任務"
msgid "Task ID: %{elastic_task}"
-msgstr ""
+msgstr "任務ID: %{elastic_task}"
msgid "Task list"
-msgstr ""
-
-msgid "Task with ID: %{id} could not be found."
-msgstr ""
+msgstr "工作清單"
msgid "TasksToBeDone|Create/import code into a project (repository)"
-msgstr ""
+msgstr "建立/匯入程å¼ç¢¼åˆ°å°ˆæ¡ˆï¼ˆç‰ˆæœ¬åº«ï¼‰"
msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
-msgstr ""
+msgstr "建立/匯入 議題(工單)以就想法和è¦åŠƒå·¥ä½œé€²è¡Œå”åŒåˆä½œ"
msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
-msgstr ""
+msgstr "設定 CI/CD æµæ°´ç·šä¾†æ§‹å»ºã€æ¸¬è©¦ã€éƒ¨ç½²å’Œç›£æŽ§ç¨‹å¼ç¢¼"
msgid "Team"
msgstr "團隊"
msgid "Team domain"
-msgstr ""
+msgstr "團隊網域"
msgid "TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated"
-msgstr ""
+msgstr "在建立或更新åˆä½µè«‹æ±‚後觸發 TeamCity CI"
msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete"
-msgstr ""
+msgstr "æ¯æ¬¡æŽ¨é€åˆ°ç‰ˆæœ¬åº«å¾Œè§¸ç™¼ TeamCity CI,分支刪除除外"
msgid "Telephone number"
-msgstr ""
+msgstr "電話號碼"
msgid "Template"
-msgstr ""
+msgstr "模æ¿"
msgid "Template to append to all Service Desk issues"
-msgstr ""
+msgstr "附加到所有æœå‹™å°è­°é¡Œçš„範本"
msgid "TemplateRepository|Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "更快地建立通åŒæ–‡ä»¶ä¸¦ä½¿å…¶æ ¼å¼æ¨™æº–化。"
msgid "Templates"
-msgstr ""
+msgstr "模æ¿"
msgid "TemporaryStorageIncrease|can only be set once"
-msgstr ""
+msgstr "åªèƒ½è¨­å®šä¸€æ¬¡"
msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
-msgstr ""
+msgstr "åªèƒ½è¨­å®šç‚ºå¤§æ–¼%{percentage}%%使用é‡"
msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
-msgstr ""
+msgstr "GitLabå…許您申請%{strongStart}å…費的一次性儲存增加%{strongEnd}。 您在30天內將å¯ä½¿ç”¨ç„¡é™çš„儲存空間。這將使您有時間減少您的儲存使用é‡ã€‚ 30天後,您的原始儲存é™åˆ¶%{limit}將生效。如果您的儲存使用已é”容é‡ä¸Šé™ï¼Œæ‚¨çš„帳號將變為唯讀。如需繼續使用 GitLab ,您必須購買更多的儲存或減少儲存使用é‡ã€‚"
msgid "TemporaryStorage|Increase storage temporarily"
-msgstr ""
+msgstr "臨時增加儲存"
msgid "TemporaryStorage|Temporarily increase storage now?"
-msgstr ""
+msgstr "ç¾åœ¨è‡¨æ™‚增加儲存嗎?"
msgid "Terminal"
-msgstr ""
+msgstr "終端"
msgid "Terminal for environment"
-msgstr ""
+msgstr "環境終端"
msgid "Terminal sync service is running"
-msgstr ""
+msgstr "終端åŒæ­¥æœå‹™æ­£åœ¨åŸ·è¡Œ"
msgid "Terms of Service Agreement and Privacy Policy"
-msgstr ""
+msgstr "æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–"
msgid "Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–"
msgid "Terms of service"
-msgstr ""
+msgstr "æœå‹™æ¢æ¬¾"
msgid "Terraform"
-msgstr ""
+msgstr "Terraform"
msgid "TerraformBanner|Learn more about GitLab's Backend State"
-msgstr ""
+msgstr "了解有關 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 "GitLab 管ç†çš„ Terraform state 後端å¯ä»¥è¼•é¬†å®‰å…¨åœ°å„²å­˜æ‚¨çš„ Terraform state,並使您無需設定é¡å¤–çš„é ç¨‹è³‡æºã€‚它的功能包括:版本控制ã€å‚³è¼¸å’Œéœæ­¢ç‹€æ…‹æ–‡ä»¶çš„加密ã€éŽ–定和é ç¨‹ Terraform 計劃/應用執行。"
msgid "TerraformBanner|Using Terraform? Try the GitLab Managed Terraform State"
-msgstr ""
+msgstr "使用 Terraform?嘗試 GitLab 託管 Terraform State"
msgid "Terraform|%{name} successfully removed"
-msgstr ""
+msgstr "%{name} å·²æˆåŠŸç§»é™¤"
msgid "Terraform|%{number} Terraform report failed to generate"
msgid_plural "Terraform|%{number} Terraform reports failed to generate"
-msgstr[0] ""
+msgstr[0] "%{number}個Terraform報告產生失敗"
msgid "Terraform|%{number} Terraform report was generated in your pipelines"
msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
-msgstr[0] ""
+msgstr[0] "您的æµæ°´ç·šç”¢ç”Ÿäº†%{number}個Terraform報告"
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[0] "%{strong_start}%{number}%{strong_end} 個 Terraform 報告產生失敗"
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[0] "您的æµæ°´ç·šç”¢ç”Ÿäº† %{strong_start}%{number}%{strong_end} 個 Terraform 報告"
msgid "Terraform|%{user} updated %{timeAgo}"
-msgstr ""
+msgstr "%{user}æ›´æ–°æ–¼%{timeAgo}"
msgid "Terraform|A Terraform report failed to generate."
-msgstr ""
+msgstr "Terraform 報告產生失敗。"
msgid "Terraform|A Terraform report was generated in your pipelines."
-msgstr ""
+msgstr "在您的æµæ°´ç·šä¸­ç”¢ç”Ÿäº†ä¸€å€‹ Terraform 報告。"
msgid "Terraform|A report failed to generate."
-msgstr ""
+msgstr "無法產生報告。"
msgid "Terraform|A report was generated in your pipelines."
-msgstr ""
+msgstr "在您的æµæ°´ç·šä¸­ç”¢ç”Ÿäº†ä¸€ä»½å ±å‘Šã€‚"
msgid "Terraform|Actions"
-msgstr ""
+msgstr "動作"
msgid "Terraform|An error occurred while changing the state file"
-msgstr ""
+msgstr "更改狀態文件時發生錯誤"
msgid "Terraform|An error occurred while loading your Terraform States"
-msgstr ""
+msgstr "載入您的Terraform狀態時發生錯誤"
msgid "Terraform|Are you sure you want to remove the Terraform State %{name}?"
-msgstr ""
+msgstr "確定è¦ç§»é™¤Terraform狀態%{name}嗎?"
msgid "Terraform|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Terraform|Cannot remove a locked state"
-msgstr ""
+msgstr "無法移除鎖定狀態"
msgid "Terraform|Copy Terraform init command"
-msgstr ""
+msgstr "複製 Terraform init 指令"
msgid "Terraform|Deletion in progress"
-msgstr ""
+msgstr "正在刪除"
msgid "Terraform|Details"
-msgstr ""
+msgstr "詳細訊æ¯"
msgid "Terraform|Download JSON"
-msgstr ""
+msgstr "下載JSON"
msgid "Terraform|Failed to load Terraform reports"
-msgstr ""
+msgstr "載入 Terraform 報告失敗"
msgid "Terraform|Generating the report caused an error."
-msgstr ""
+msgstr "產生報告時發生錯誤。"
msgid "Terraform|How to use GitLab-managed Terraform state?"
-msgstr ""
+msgstr "å¦‚ä½•ä½¿ç”¨å— GitLab 管ç†çš„ Terraform 狀態?"
msgid "Terraform|Job status"
-msgstr ""
+msgstr "作業狀態"
msgid "Terraform|Loading Terraform reports..."
-msgstr ""
+msgstr "正在載入 Terraform 報告..."
msgid "Terraform|Lock"
-msgstr ""
+msgstr "鎖定"
msgid "Terraform|Locked"
-msgstr ""
+msgstr "已鎖定"
msgid "Terraform|Locked by %{user} %{timeAgo}"
-msgstr ""
+msgstr "由%{user}於%{timeAgo}鎖定"
msgid "Terraform|Locking state"
-msgstr ""
+msgstr "鎖定狀態"
msgid "Terraform|Name"
-msgstr ""
+msgstr "å稱"
msgid "Terraform|Pipeline"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "Terraform|Remove"
-msgstr ""
+msgstr "移除"
msgid "Terraform|Remove state file and versions"
-msgstr ""
+msgstr "移除狀態文件和版本"
msgid "Terraform|Removed"
-msgstr ""
+msgstr "已移除"
msgid "Terraform|Removing"
-msgstr ""
+msgstr "正在移除"
msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
-msgstr ""
+msgstr "報告的資æºè®Šæ›´: 加入%{addNum}é …, 更改%{changeNum}é …, 刪除%{deleteNum}é …"
msgid "Terraform|States"
-msgstr ""
+msgstr "狀態"
msgid "Terraform|Terraform init command"
-msgstr ""
+msgstr "Terraform init 指令"
msgid "Terraform|Terraform reports"
-msgstr ""
+msgstr "Terraform 報告"
msgid "Terraform|The job %{name} failed to generate a report."
-msgstr ""
+msgstr "作業 %{name} 產生報告失敗。"
msgid "Terraform|The job %{name} generated a report."
-msgstr ""
+msgstr "作業 %{name} 產生了一個報告。"
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} failed to generate a report."
-msgstr ""
+msgstr "作業 %{strong_start}%{name}%{strong_end} 產生報告失敗。"
msgid "Terraform|The job %{strong_start}%{name}%{strong_end} generated a report."
-msgstr ""
+msgstr "作業 %{strong_start}%{name}%{strong_end} 產生了一份報告。"
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 "è¦å¾žæœ¬åœ°ä¸»æ©Ÿå­˜å–æ­¤ terraform state,請在指令行中執行以下指令。第一行需è¦å…·æœ‰ API 讀寫存å–權é™çš„個人存å–令牌。 %{linkStart}如何建立個人存å–令牌?%{linkEnd}."
msgid "Terraform|To remove the State file and its versions, type %{name} to confirm:"
-msgstr ""
+msgstr "è¦ç§»é™¤ç‹€æ…‹æ–‡ä»¶åŠå…¶ç‰ˆæœ¬ï¼Œè«‹è¼¸å…¥%{name}確èªï¼š"
msgid "Terraform|Unknown User"
-msgstr ""
+msgstr "未知使用者"
msgid "Terraform|Unlock"
-msgstr ""
+msgstr "解鎖"
msgid "Terraform|Unlocking state"
-msgstr ""
+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 "您將è¦ç§»é™¤ç‹€æ…‹(state)文件 %{name}。這將永久刪除所有狀態版本和歷å²è¨˜éŒ„。之å‰è¨­å®šçš„基礎架構將ä¿æŒä¸è®Šï¼Œä¸¦ä¸”åªæœƒç§»é™¤åŒ…å«æ‰€æœ‰ç‰ˆæœ¬çš„狀態文件。此æ“作無法撤消。"
msgid "Terraform|You have insufficient permissions to delete this state"
-msgstr ""
+msgstr "您的權é™ä¸è¶³ï¼Œç„¡æ³•åˆªé™¤æ­¤ç‹€æ…‹"
msgid "Terraform|Your project doesn't have any Terraform state files"
-msgstr ""
+msgstr "您的專案沒有任何 Terraform 狀態文件"
msgid "Test"
-msgstr ""
+msgstr "測試"
msgid "Test Cases"
-msgstr ""
+msgstr "測試案例"
msgid "Test case"
-msgstr ""
+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[0] "該æµæ°´ç·šçš„測試覆蓋率值是通éŽå¹³å‡ %d 個作業的çµæžœè¦†è“‹çŽ‡å€¼ä¾†è¨ˆç®—的。"
msgid "Test coverage: %d hit"
msgid_plural "Test coverage: %d hits"
-msgstr[0] ""
+msgstr[0] "測試覆蓋率: %d次命中"
msgid "Test settings"
-msgstr ""
+msgstr "測試設定"
msgid "TestCases|Move test case"
-msgstr ""
+msgstr "移動測試案例"
msgid "TestCases|Moving test case"
-msgstr ""
+msgstr "移動中的測試案例"
msgid "TestCases|New Test Case"
-msgstr ""
+msgstr "新增測試案例"
msgid "TestCases|New test case"
-msgstr ""
+msgstr "新建測試案例"
msgid "TestCases|Search test cases"
-msgstr ""
+msgstr "æœå°‹æ¸¬è©¦æ¡ˆä¾‹"
msgid "TestCases|Something went wrong while adding test case to a to-do item."
-msgstr ""
+msgstr "å‘待辦事項加入測試案例時發生錯誤。"
msgid "TestCases|Something went wrong while creating a test case."
-msgstr ""
+msgstr "建立新測試案例時出ç¾éŒ¯èª¤."
msgid "TestCases|Something went wrong while fetching test case."
-msgstr ""
+msgstr "å–得測試案例時發生錯誤。"
msgid "TestCases|Something went wrong while fetching test cases list."
-msgstr ""
+msgstr "å–得測試案例列表時發生錯誤。"
msgid "TestCases|Something went wrong while marking test case to-do item as done."
-msgstr ""
+msgstr "將測試案例待辦事項標示為完æˆæ™‚發生錯誤。"
msgid "TestCases|Something went wrong while moving test case."
-msgstr ""
+msgstr "移動測試案例時發生錯誤。"
msgid "TestCases|Something went wrong while updating the test case labels."
-msgstr ""
+msgstr "更新測試案例列表標記時發生錯誤。"
msgid "TestCases|Something went wrong while updating the test case."
-msgstr ""
+msgstr "更新測試案例列表時發生錯誤。"
msgid "TestCases|Submit test case"
-msgstr ""
+msgstr "éžäº¤æ¸¬è©¦æ¡ˆä¾‹"
msgid "TestHooks|Ensure one of your projects has merge requests."
-msgstr ""
+msgstr "確ä¿æ‚¨çš„任一專案中有åˆä½µè«‹æ±‚。"
msgid "TestHooks|Ensure the project has CI jobs."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆå…·æœ‰CI作業。"
msgid "TestHooks|Ensure the project has CI pipelines."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆå…·æœ‰CIæµæ°´ç·šã€‚"
msgid "TestHooks|Ensure the project has deployments."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆå·²ç¶“部署。"
msgid "TestHooks|Ensure the project has issues."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆæœ‰è­°é¡Œã€‚"
msgid "TestHooks|Ensure the project has merge requests."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆæœ‰åˆä½µè«‹æ±‚。"
msgid "TestHooks|Ensure the project has notes."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆæœ‰è¨»é‡‹ã€‚"
msgid "TestHooks|Ensure the project has releases."
-msgstr ""
+msgstr "確ä¿å°ˆæ¡ˆåŒ…å«ç™¼å¸ƒã€‚"
msgid "TestHooks|Ensure the wiki is enabled and has pages."
-msgstr ""
+msgstr "確ä¿wiki已啟用並具有é é¢ã€‚"
msgid "TestReports|%{count} errors"
-msgstr ""
+msgstr "%{count}個錯誤"
msgid "TestReports|%{count} failures"
-msgstr ""
+msgstr "%{count}個失敗"
msgid "TestReports|%{count} tests"
-msgstr ""
+msgstr "%{count}項測試"
msgid "TestReports|%{rate}%{sign} success rate"
-msgstr ""
+msgstr "%{rate}%{sign}æˆåŠŸçŽ‡"
msgid "TestReports|Attachment"
-msgstr ""
+msgstr "附件"
msgid "TestReports|Copy test name to rerun locally"
-msgstr ""
+msgstr "複製測試å稱至本地é‡æ–°åŸ·è¡Œ"
msgid "TestReports|Job artifacts are expired"
-msgstr ""
+msgstr "作業工件已éŽæœŸ"
msgid "TestReports|Jobs"
-msgstr ""
+msgstr "作業"
msgid "TestReports|Learn how to upload pipeline test reports"
-msgstr ""
+msgstr "學習如何上傳æµæ°´ç·šæ¸¬è©¦å ±å‘Š"
msgid "TestReports|Learn more about pipeline test reports"
-msgstr ""
+msgstr "了解有關æµæ°´ç·šæ¸¬è©¦å ±å‘Šçš„更多訊æ¯"
msgid "TestReports|No test cases were found in the test report."
-msgstr ""
+msgstr "在測試報告中沒有找到測試案例。"
msgid "TestReports|Test reports require job artifacts but all artifacts are expired. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "測試報告需è¦ä½œæ¥­å·¥ä»¶ï¼Œä½†æ‰€æœ‰å·¥ä»¶éƒ½å·²éŽæœŸã€‚ %{linkStart}了解更多%{linkEnd}"
msgid "TestReports|Tests"
-msgstr ""
+msgstr "測試"
msgid "TestReports|There are no test cases to display."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„測試案例。"
msgid "TestReports|There are no test reports for this pipeline"
-msgstr ""
+msgstr "æ­¤æµæ°´ç·šæ²’有測試報告"
msgid "TestReports|There are no test suites to show."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„測試集。"
msgid "TestReports|There are no tests to display"
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„測試"
msgid "TestReports|There was an error fetching the summary."
-msgstr ""
+msgstr "å–得總çµæ™‚發生錯誤。"
msgid "TestReports|There was an error fetching the test suite."
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥å°‡ä½œæ¥­è¨­å®šç‚ºä½¿ç”¨å–®å…ƒæ¸¬è©¦å ±å‘Šï¼ŒGitLab 會在此處和相關åˆä½µè«‹æ±‚中顯示報告。"
msgid "Tests"
-msgstr ""
+msgstr "測試"
msgid "Text (optional)"
-msgstr ""
+msgstr "文字(å¯é¸ï¼‰"
msgid "Text added to the body of all email messages. %{character_limit} character limit"
-msgstr ""
+msgstr "加入到所有電å­éƒµä»¶æ­£æ–‡çš„文字。 %{character_limit} å­—å…ƒé™åˆ¶"
msgid "Text style"
-msgstr ""
+msgstr "文字樣å¼"
msgid "Thank you for your business."
-msgstr ""
-
-msgid "Thank you for your feedback!"
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨çš„購買。"
msgid "Thank you for your report. A GitLab administrator will look into it shortly."
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨çš„報告。GitLab管ç†å“¡å°‡å„˜å¿«é€²è¡Œèª¿æŸ¥ã€‚"
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨çš„請求å”助ï¼æˆ‘們正é€éŽç¥¨è™Ÿ #%{issue_iid} 追蹤您的請求,並將盡快回復您。"
msgid "Thanks for signing up to GitLab!"
-msgstr ""
+msgstr "æ„Ÿè¬æ‚¨è¨»å†Š GitLabï¼"
msgid "Thanks for your purchase!"
-msgstr ""
+msgstr "æ„Ÿè¬è³¼è²·ï¼"
msgid "That's OK, I don't want to renew"
-msgstr ""
+msgstr "好的,我ä¸æƒ³çºŒè¨‚"
msgid "That's it, well done!"
-msgstr ""
+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 ""
+msgstr "%{link_start}校準模å¼%{link_end}å…許有é¡å¤–使用者,這些é¡å¤–使用者在更新訂閱時將會產生追溯費用。"
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 "%{plan_name} 已無法購買。欲了解更多關於這將如何影響您的訊æ¯ï¼Œè«‹æŸ¥çœ‹æˆ‘們的 %{faq_link_start}常見å•é¡Œ%{faq_link_end}。"
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
-msgstr[0] ""
+msgstr[0] "%{type} 包å«ä»¥ä¸‹éŒ¯èª¤ï¼š"
msgid "The API key used by GitLab for accessing the Spam Check service endpoint."
-msgstr ""
+msgstr "用於存å–垃圾郵件檢查æœå‹™ç«¯é»žçš„ API 金鑰."
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
-msgstr ""
+msgstr "CSV匯出將在背景建立。完æˆå¾Œï¼Œå®ƒå°‡ä»¥é™„件形å¼ç™¼é€åˆ°%{email}。"
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
-msgstr ""
+msgstr "GitLab 訂閱æœå‹™ (customers.gitlab.com) ç›®å‰æ­£åœ¨ä¸­æ–·ã€‚您å¯ä»¥é€šéŽ %{linkStart}status.gitlab.com%{linkEnd}監控狀態並å–得更新。"
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
-msgstr ""
+msgstr "Jira使用者%{jiraDisplayName}將被映射到的GitLab使用者"
msgid "The ID of the application."
-msgstr ""
+msgstr "應用程å¼ID。"
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
-msgstr ""
+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 ""
+msgstr "議題追蹤用於管ç†éœ€æ±‚改進或者解決的å•é¡Œã€‚請註冊或登入後為當å‰å°ˆæ¡ˆå»ºç«‹è­°é¡Œã€‚"
msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
-msgstr ""
+msgstr "Prometheus伺æœå™¨ä»¥ã€ŒéŒ¯èª¤è«‹æ±‚ã€å›žæ‡‰ã€‚請檢查您的查詢是å¦æ­£ç¢ºï¼Œä¸¦ä¸”支æ´ç•¶å‰çš„Prometheus版本。%{documentationLink}"
msgid "The Snowplow cookie domain."
-msgstr ""
+msgstr "Snowplow cookie 網域。"
msgid "The URL of the Jenkins server."
-msgstr ""
+msgstr "Jenkins 伺æœå™¨çš„ URL。"
msgid "The URL should start with http:// or https://"
-msgstr ""
+msgstr "URL 應該以 http:// 或 https:// 開頭"
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
-msgstr ""
+msgstr "連接到 Elasticsearch çš„ URL。å°æ–¼å¢é›†ï¼Œè«‹åŠ å…¥ç”¨é€—號分隔的 URL。"
msgid "The `/merge` quick action requires the SHA of the head of the branch."
-msgstr ""
+msgstr "`/merge` 快速æ“作需è¦åˆ†æ”¯é ­éƒ¨çš„ SHA。"
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 ""
+msgstr "應用程å¼å¯ç”¨æ–¼å®¢æˆ¶ç«¯é‡‘é‘°å¯ä»¥ä¿æŒä¿å¯†çš„地方。原生移動應用和單é æ‡‰ç”¨è¢«è¦–為為éžä¿å¯†ã€‚"
msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
-msgstr ""
+msgstr "相關的議題#%{issueId}已關閉,因為該錯誤已經解決。"
msgid "The branch for this project has no active pipeline configuration."
-msgstr ""
+msgstr "此專案的分支沒有啟用的æµæ°´ç·šè¨­å®šã€‚"
msgid "The branch or tag does not exist"
-msgstr ""
+msgstr "分支或標籤ä¸å­˜åœ¨"
msgid "The broadcast message displays only to users in projects and groups who have these roles."
-msgstr ""
+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 ""
+msgstr "字元高光顯示幫助您將主題行ä¿æŒç‚º %{titleLength} 字元並將正文包è£ç‚º %{bodyLength} 以便它們在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 "您正在編輯的留言已被其他使用者更改。您想ä¿ç•™æ‚¨çš„更改並覆蓋新的æ述還是放棄您的更改?"
msgid "The commit does not exist"
-msgstr ""
+msgstr "該æ交ä¸å­˜åœ¨"
msgid "The comparison view may be inaccurate due to merge conflicts."
-msgstr ""
+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 ""
+msgstr "完整的 DevOps å¹³å°ï¼Œä¸€ç¨®å…·æœ‰ç„¡é™å¯èƒ½æ€§çš„應用程å¼ã€‚組織ä¾é  GitLab çš„æºç¢¼ç®¡ç†ã€CI/CDã€å®‰å…¨æ€§ç­‰ä¾†å¿«é€Ÿäº¤ä»˜è»Ÿé«”。"
msgid "The compliance report shows the merge request violations merged in protected environments."
-msgstr ""
+msgstr "åˆè¦æ€§å ±å‘Šé¡¯ç¤ºåœ¨å—ä¿è­·ç’°å¢ƒä¸­åˆä½µçš„åˆä½µè«‹æ±‚é•è¦ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "該連接將在 %{timeout} 後逾時。如版本庫匯入耗時超éŽè©²æ™‚間,請使用仿製(clone)/推é€(push)組åˆã€‚"
msgid "The contact does not belong to the issue group's root ancestor"
-msgstr ""
+msgstr "è¯çµ¡äººä¸å±¬æ–¼è­°é¡Œç¾¤çµ„的根組"
msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
-msgstr ""
+msgstr "內容編輯器å¯èƒ½æœƒæ›´æ”¹æ–‡ä»¶çš„ Markdown æ ¼å¼æ¨£å¼ï¼Œé€™å¯èƒ½èˆ‡æ‚¨åŽŸä¾†çš„ Markdown 樣å¼ä¸ç¬¦åˆã€‚"
msgid "The content for this wiki page failed to load. To fix this error, reload the page."
-msgstr ""
+msgstr "æ­¤ wiki é é¢çš„內容無法載入。è¦ä¿®å¾©æ­¤éŒ¯èª¤ï¼Œè«‹é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "The content for this wiki page failed to render."
-msgstr ""
+msgstr "æ­¤wikié é¢çš„內容無法渲染。"
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
-msgstr ""
+msgstr "æ­¤é é¢çš„內容未以UTF-8編碼。編輯åªèƒ½é€šéŽGit版本庫進行。"
msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
-msgstr ""
+msgstr "該群組,其å­ç¾¤çµ„和專案的內容將於%{deletion_adjourned_period}天後在%{date}永久移除。在此之後,您的資料將無法æ¢å¾©ã€‚"
msgid "The current epic"
-msgstr ""
+msgstr "當å‰å²è©©"
msgid "The current incident"
-msgstr ""
+msgstr "ç›®å‰äº‹ä»¶"
msgid "The current issue"
-msgstr ""
+msgstr "ç›®å‰è­°é¡Œ"
msgid "The current user is not authorized to access the job log."
-msgstr ""
+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 ""
+msgstr "æ­¤æµæ°´ç·šä¸­çš„資料太舊,無法呈ç¾ç‚ºåœ–形。請檢查作業é¸é …é ä»¥å­˜å–æ­·å²è³‡æ–™ã€‚"
msgid "The data source is connected, but there is no data to display. %{documentationLink}"
-msgstr ""
+msgstr "資料æºå·²é€£æŽ¥ï¼Œä½†æ²’有å¯é¡¯ç¤ºçš„資料。%{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 "發布版本準備就緒的日期,具有未來日期的版本被標記為 %{linkStart}å³å°‡ç™¼å¸ƒçš„版本%{linkEnd}。"
msgid "The default CI/CD configuration file and path for new projects."
-msgstr ""
+msgstr "新專案的é è¨­ CI/CD 設定文件和路徑。"
msgid "The default branch for this project has been changed. Please update your bookmarks."
-msgstr ""
+msgstr "此專案的é è¨­åˆ†æ”¯å·²æ›´æ”¹ï¼Œè«‹æ›´æ–°æ‚¨çš„書籤。"
msgid "The dependency list details information about the components used within your project."
-msgstr ""
+msgstr "ä¾è³´é …列表詳細說明了專案中使用元件的訊æ¯ã€‚"
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "將此作業部署至 %{environmentLink} 未æˆåŠŸã€‚"
msgid "The directory has been successfully created."
-msgstr ""
+msgstr "目錄已æˆåŠŸå»ºç«‹ã€‚"
msgid "The domain you entered is misformatted."
-msgstr ""
+msgstr "您輸入的網域格å¼éŒ¯èª¤ã€‚"
msgid "The domain you entered is not allowed."
-msgstr ""
+msgstr "您輸入的網域ä¸è¢«å…許。"
msgid "The download link will expire in 24 hours."
-msgstr ""
+msgstr "下載連çµå°‡æ–¼24å°æ™‚後éŽæœŸã€‚"
msgid "The environment tiers must be from %{environment_tiers}."
-msgstr ""
+msgstr "環境級別必須是%{environment_tiers}之一。"
msgid "The errors we encountered were:"
-msgstr ""
+msgstr "我們é‡åˆ°çš„錯誤是:"
msgid "The file containing the export is not available yet; it may still be transferring. Please try again later."
-msgstr ""
+msgstr "包å«åŒ¯å‡ºçš„文件尚ä¸å¯ç”¨ï¼›å®ƒå¯èƒ½ä»åœ¨è½‰ç§»ã€‚è«‹ç¨å¾Œå†è©¦ã€‚"
msgid "The file could not be displayed because it is empty or larger than the maximum file size indexed (%{size})."
-msgstr ""
+msgstr "è©²æ–‡ä»¶ç„¡æ³•é¡¯ç¤ºï¼Œå› ç‚ºå®ƒç‚ºç©ºæˆ–å¤§æ–¼å·²ç´¢å¼•çš„æœ€å¤§æ–‡ä»¶å¤§å° (%{size})。"
msgid "The file has been successfully created."
-msgstr ""
+msgstr "文件已æˆåŠŸå»ºç«‹ã€‚"
msgid "The file has been successfully deleted."
-msgstr ""
+msgstr "文件已æˆåŠŸåˆªé™¤ã€‚"
msgid "The file name should have a .yml extension"
-msgstr ""
+msgstr "文件å稱的副檔å必須是 .yml。"
msgid "The finding is not a vulnerability because it is part of a test or is test data."
-msgstr ""
+msgstr "該發ç¾ä¸æ˜¯æ¼æ´žï¼Œå› ç‚ºå®ƒæ˜¯æ¸¬è©¦çš„一部分或測試資料。"
msgid "The following %{user} can also merge into this branch: %{branch}"
-msgstr ""
+msgstr "以下%{user}也å¯ä»¥åˆä½µåˆ°è©²åˆ†æ”¯ä¸­: %{branch}"
msgid "The following %{user} can also push to this branch: %{branch}"
-msgstr ""
+msgstr "以下%{user}也å¯ä»¥æŽ¨é€åˆ°è©²åˆ†æ”¯ä¸­: %{branch}"
msgid "The following Personal Access Token was revoked by an administrator, %{username}."
-msgstr ""
+msgstr "管ç†å“¡ %{username} 撤消了以下個人存å–令牌。"
msgid "The following SSH key was deleted by an administrator, %{username}."
-msgstr ""
+msgstr "以下SSH金鑰已由管ç†å“¡ %{username} 刪除。"
msgid "The following items will NOT be exported:"
-msgstr ""
+msgstr "以下項目將ä¸æœƒè¢«åŒ¯å‡ºï¼š"
msgid "The following items will be exported:"
-msgstr ""
+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[0] "因為設置了使個人訪å•ä»¤ç‰ŒéŽæœŸçš„新政策,以下個人存å–令牌已被撤銷:%{token_names}。"
msgid "The fork relationship has been removed."
-msgstr ""
+msgstr "分å‰é—œä¿‚已被移除。"
msgid "The form contains the following error:"
msgid_plural "The form contains the following errors:"
-msgstr[0] ""
+msgstr[0] "該表單包å«ä»¥ä¸‹éŒ¯èª¤ï¼š"
msgid "The form contains the following warning:"
-msgstr ""
+msgstr "該表單包å«ä»¥ä¸‹è­¦å‘Šï¼š"
msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
-msgstr ""
+msgstr "git 伺æœå™¨ Gitaly ç›®å‰ä¸å¯ç”¨ã€‚è«‹è¯çµ¡æ‚¨çš„管ç†å“¡ã€‚"
msgid "The global settings require you to enable Two-Factor Authentication for your account."
-msgstr ""
+msgstr "系統設定è¦æ±‚您為帳號啟用雙因å­é©—證。"
msgid "The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
+msgstr "除外部使用者外,任何登入使用者å‡å¯æŸ¥çœ‹è©²ç¾¤çµ„和任何內部專案。"
msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "群組和任何公開專案å¯ä»¥åœ¨æ²’有任何身份驗證的情æ³ä¸‹æŸ¥çœ‹ã€‚"
msgid "The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "群組åŠå…¶å°ˆæ¡ˆåªèƒ½ç”±æˆå“¡æŸ¥çœ‹ã€‚"
msgid "The group export can be downloaded from:"
-msgstr ""
+msgstr "群組的匯出å¯ä»¥å¾žä»¥ä¸‹ä½ç½®ä¸‹è¼‰ï¼š"
msgid "The group has already been shared with this group"
-msgstr ""
+msgstr "該群組已與此群組共享"
msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
-msgstr ""
+msgstr "%{group_links} 的群組設定è¦æ±‚您為帳號啟用雙因å­é©—證。您也å¯ä»¥ %{leave_group_links}。"
msgid "The group_project_ids parameter is only allowed for a group"
-msgstr ""
+msgstr "group_project_ids åƒæ•¸åªå…許用於一個群組"
msgid "The hostname of your PlantUML server."
-msgstr ""
+msgstr "您的 PlantUML 伺æœå™¨çš„主機å。"
msgid "The hostname of your Snowplow collector."
-msgstr ""
+msgstr "您的 Snowplow 收集器的主機å。"
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "該匯入éŽç¨‹å°‡åœ¨ %{timeout} 後逾時。å°æ–¼éœ€è¦é•·æ–¼è©²æ™‚é–“æ‰èƒ½åŒ¯å…¥çš„版本庫,請使用仿製(clone)/推é€(push)組åˆã€‚"
msgid "The interval must be one of %{intervals}."
-msgstr ""
+msgstr "間隔必須是 %{intervals}。"
msgid "The invitation can not be found with the provided invite token."
-msgstr ""
+msgstr "這å°é‚€è«‹ç„¡æ•ˆï¼Œç„¡æ³•ä½¿ç”¨æ供的邀請令牌(權æ–)。"
msgid "The invitation could not be accepted."
-msgstr ""
+msgstr "無法接å—邀請。"
msgid "The invitation could not be declined."
-msgstr ""
+msgstr "無法拒絕邀請"
msgid "The invitation has already been accepted."
-msgstr ""
+msgstr "邀請已被接å—。"
msgid "The invitation was successfully resent."
-msgstr ""
+msgstr "邀請已é‡æ–°ç™¼é€ã€‚"
msgid "The issue was successfully promoted to an epic. Redirecting to epic..."
-msgstr ""
+msgstr "該å•é¡Œè¢«æˆåŠŸæå‡ç‚ºå²è©©ã€‚é‡å°Žå‘到å²è©©..."
msgid "The last owner cannot be set to awaiting"
-msgstr ""
+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 complete successfully."
-msgstr ""
+msgstr "將儲存由最近æˆåŠŸæµæ°´ç·šä½œæ¥­æ‰€å»ºç«‹çš„最新產物。"
msgid "The latest pipeline for this merge request did not succeed. The latest changes are unverified."
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚的最新æµæ°´ç·šæœªæˆåŠŸã€‚最新更改未經驗證。"
msgid "The latest pipeline for this merge request has failed."
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚的最新æµæ°´ç·šå·²å¤±æ•—。"
msgid "The license key is invalid."
-msgstr ""
+msgstr "授權許å¯é‡‘鑰無效。"
msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
-msgstr ""
+msgstr "授權許å¯é‡‘鑰無效。請確ä¿å®ƒèˆ‡æ‚¨å¾žGitLab Inc.收到的一致。"
msgid "The license was removed. GitLab has fallen back on the previous license."
-msgstr ""
+msgstr "授權許å¯å·²è¢«ç§»é™¤ã€‚GitLab已經回退到å‰ä¸€å€‹æŽˆæ¬Šè¨±å¯ã€‚"
msgid "The license was removed. GitLab now no longer has a valid license."
-msgstr ""
+msgstr "授權許å¯å·²è¢«ç§»é™¤ã€‚GitLabç›®å‰ç„¡æœ‰æ•ˆçš„授權許å¯ã€‚"
msgid "The license was successfully uploaded and is now active. You can see the details below."
-msgstr ""
+msgstr "授權許å¯å·²æˆåŠŸä¸Šå‚³ä¸¦å·²å•Ÿå‹•ã€‚詳細訊æ¯å¦‚下。"
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
-msgstr ""
+msgstr "授權已æˆåŠŸä¸Šå‚³ï¼Œå°‡æ–¼ %{starts_at} 啟用。詳細訊æ¯å¦‚下。"
msgid "The license you uploaded is invalid. If the issue persists, contact support at %{link}."
-msgstr ""
+msgstr "您上傳的授權許å¯ç„¡æ•ˆã€‚如果å•é¡Œä»ç„¶å­˜åœ¨ï¼Œè«‹é€šéŽ %{link} è¯çµ¡æ”¯æ´äººå“¡ã€‚"
msgid "The list creation wizard is already open"
-msgstr ""
+msgstr "列表建立精éˆå·²æ‰“é–‹"
msgid "The maximum amount of time users have to set up two-factor authentication before it's enforced."
-msgstr ""
+msgstr "使用者在強制執行之å‰å¿…須設定雙因å­é©—證的最長時間。"
msgid "The maximum file size allowed is %{size}."
-msgstr ""
+msgstr "å…許的最大檔案大å°ç‚º %{size}。"
msgid "The maximum file size for job artifacts."
-msgstr ""
+msgstr "作業產物的最大文件大å°ã€‚"
msgid "The maximum file size in megabytes for individual job artifacts."
-msgstr ""
+msgstr "個別作業產物的最大文件大å°ï¼Œä»¥ megabytes(MB)計算。"
msgid "The maximum file size is %{size}."
-msgstr ""
+msgstr "最大文件大å°ç‚º %{size}。"
msgid "The maximum number of CI/CD minutes on shared runners that a group can use each month. 0 for unlimited."
-msgstr ""
+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 ""
+msgstr "單個worker接å—清ç†çš„最大標籤數。如果標籤數é‡è¶…éŽæ­¤é™åˆ¶ï¼Œå‰‡è¦åˆªé™¤çš„標籤列表將被截斷為該數é‡ã€‚è¦å–消此é™åˆ¶ï¼Œè«‹å°‡å…¶è¨­å®šç‚º 0。"
msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
-msgstr ""
+msgstr "GitLab無法解決此åˆä½µè«‹æ±‚çš„åˆä½µè¡çªã€‚請嘗試在本機解決它們。"
msgid "The merge conflicts for this merge request have already been resolved."
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚çš„åˆä½µè¡çªå·²è§£æ±ºã€‚"
msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚çš„åˆä½µè¡çªå·²å¾—到解決。請返回åˆä½µè«‹æ±‚。"
msgid "The metric must be one of %{metrics}."
-msgstr ""
+msgstr "指標必須是 %{metrics} 之一。"
msgid "The name \"%{name}\" is already taken in this directory."
-msgstr ""
+msgstr "此資料夾中已經有åŒå的「%{name}ã€ã€‚"
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 "CI/CD 設定文件的å稱。相å°æ–¼æ ¹ç›®éŒ„的路徑是å¯é¸çš„(例如 %{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 "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 ""
+msgstr "仿製(clone)版本庫時è¦å¾ž GitLab å–得的更改數é‡ï¼Œè¼ƒä½Žçš„值å¯ä»¥åŠ é€Ÿæµæ°´ç·šåŸ·è¡Œã€‚ 設定為 %{code_open}0%{code_close} 或空白以å–å¾—æ¯å€‹ä½œæ¥­çš„所有分支和標籤"
msgid "The number of merge requests merged by month."
-msgstr ""
+msgstr "æ¯æœˆåˆä½µçš„åˆä½µè«‹æ±‚數"
msgid "The number of times an upload record could not find its file"
-msgstr ""
+msgstr "上載記錄無法找到相應文件的次數"
msgid "The page could not be displayed because it timed out."
-msgstr ""
+msgstr "é é¢å·²é€¾æ™‚,無法顯示。"
msgid "The parent epic is confidential and can only contain confidential epics and issues"
-msgstr ""
+msgstr "父å²è©©æ˜¯æ©Ÿå¯†çš„,åªèƒ½åŒ…å«æ©Ÿå¯†å²è©©å’Œè­°é¡Œ"
msgid "The password for the Jenkins server."
-msgstr ""
+msgstr "Jenkins 伺æœå™¨çš„密碼。"
msgid "The password for your GitLab account on %{gitlab_url} has successfully been changed."
-msgstr ""
+msgstr "您在 %{gitlab_url} çš„ GitLab 帳號密碼已æˆåŠŸæ›´æ”¹ã€‚"
msgid "The password for your GitLab account on %{link_to_gitlab} has successfully been changed."
-msgstr ""
+msgstr "您在 %{link_to_gitlab} çš„ GitLab 帳號密碼已æˆåŠŸæ›´æ”¹ã€‚"
msgid "The pipeline has been deleted"
-msgstr ""
+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 ""
+msgstr "æµæ°´ç·šæŽ’程會在特定分支或標籤上自動定期執行æµæ°´ç·šã€‚這些排程的æµæ°´ç·šå°‡å¾žé—œè¯çš„使用者繼承有é™çš„專案存å–權é™ã€‚"
msgid "The project can be accessed by any logged in user except external users."
-msgstr ""
+msgstr "除外部使用者外,任何登入的使用者å‡å¯å­˜å–該專案。"
msgid "The project can be accessed without any authentication."
-msgstr ""
+msgstr "該專案å…許任何人存å–。"
msgid "The project has already been added to your dashboard."
-msgstr ""
+msgstr "此專案已被加入到您的儀表æ¿ã€‚"
msgid "The project is still being deleted. Please try again later."
-msgstr ""
+msgstr "該專案ä»åœ¨åˆªé™¤ä¸­ã€‚è«‹ç¨å¾Œå†è©¦ã€‚"
msgid "The project size exceeds the export limit."
-msgstr ""
+msgstr "專案大å°è¶…éŽåŒ¯å‡ºé™åˆ¶ã€‚"
msgid "The project was successfully forked."
-msgstr ""
+msgstr "該專案æˆåŠŸåˆ†å‰ã€‚"
msgid "The project was successfully imported."
-msgstr ""
+msgstr "該專案已æˆåŠŸåŒ¯å…¥ã€‚"
msgid "The related CI build failed."
-msgstr ""
+msgstr "相關的 CI 建置失敗。"
msgid "The remote mirror URL is invalid."
-msgstr ""
+msgstr "é ç¨‹é¡åƒ URL 無效。"
msgid "The remote mirror took to long to complete."
-msgstr ""
+msgstr "é ç¨‹é¡åƒéœ€è¦å¾ˆé•·æ™‚é–“æ‰èƒ½å®Œæˆã€‚"
msgid "The remote repository is being updated..."
-msgstr ""
+msgstr "é ç¨‹ç‰ˆæœ¬åº«æ­£åœ¨æ›´æ–°......"
msgid "The report artifact provided by the CI build couldn't be parsed."
-msgstr ""
+msgstr "ç„¡æ³•è§£æž CI 建置æ供的報告產物。"
msgid "The report has been successfully prepared."
-msgstr ""
+msgstr "報告已æˆåŠŸå‚™å¦¥ã€‚"
msgid "The repository can be committed to, and issues, comments and other entities can be created."
-msgstr ""
+msgstr "å¯ä»¥æ交版本庫,並建立議題,留言和其他實體。"
msgid "The repository for this project does not exist."
-msgstr ""
+msgstr "此專案的版本庫ä¸å­˜åœ¨ã€‚"
msgid "The repository for this project is empty"
-msgstr ""
+msgstr "該專案版本庫目å‰ç‚ºç©º"
msgid "The repository is being updated..."
-msgstr ""
+msgstr "版本庫正在更新......"
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "版本庫必須能夠通éŽ%{code_open}http://%{code_close},%{code_open}https://%{code_close}或%{code_open}git://%{code_close}來存å–。"
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "版本庫必須能夠通éŽ%{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close}或%{code_open}git://%{code_close}來存å–。"
+
+msgid "The 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 ""
+msgstr "åŒä¸€å€‹å…±ç”¨åŸ·è¡Œå™¨åŸ·è¡Œä¾†è‡ªå¤šå€‹å°ˆæ¡ˆçš„程å¼ç¢¼ï¼Œé™¤éžæ‚¨å°‡è‡ªå‹•ç¸®æ”¾è¨­å®šç‚º %{link} 設定為 1(在 GitLab.com 上)。"
msgid "The scan has been created."
-msgstr ""
+msgstr "掃瞄已建立。"
msgid "The snippet can be accessed without any authentication."
-msgstr ""
+msgstr "無需任何身份驗證å³å¯å­˜å–該程å¼ç¢¼ç‰‡æ®µã€‚"
msgid "The snippet is visible only to me."
-msgstr ""
+msgstr "該程å¼ç¢¼ç‰‡æ®µåƒ…å°æˆ‘å¯è¦‹ã€‚"
msgid "The snippet is visible only to project members."
-msgstr ""
+msgstr "該程å¼ç¢¼ç‰‡æ®µåƒ…å°å°ˆæ¡ˆæˆå“¡å¯è¦‹ã€‚"
msgid "The snippet is visible to any logged in user except external users."
-msgstr ""
+msgstr "該程å¼ç¢¼ç‰‡æ®µå°é™¤å¤–部使用者外的所有登入使用者å¯è¦‹ã€‚"
msgid "The source project of this merge request has been removed."
-msgstr ""
+msgstr "æ­¤åˆä½µè«‹æ±‚的來æºå°ˆæ¡ˆå·²è¢«ç§»é™¤ã€‚"
msgid "The specified tab is invalid, please select another"
-msgstr ""
+msgstr "指定é ç±¤ç„¡æ•ˆï¼Œè«‹é¸æ“‡å¦ä¸€å€‹"
msgid "The start date must be ealier than the end date."
-msgstr ""
+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 ""
+msgstr "該主題將用作新議題的標題,訊æ¯å°‡ä½œç‚ºèªªæ˜Žã€‚ æ”¯æ´ %{quickActionsLinkStart}快速æ“作%{quickActionsLinkEnd} 並使用支æ´çš„ %{markdownLinkStart}Markdown%{markdownLinkEnd} 風格。"
msgid "The tag name can't be changed for an existing release."
-msgstr ""
+msgstr "å°æ–¼ç¾æœ‰ç™¼å¸ƒï¼Œä¸èƒ½æ›´æ”¹æ¨™ç±¤å稱。"
msgid "The time period in seconds that the maximum requests per project limit applies to."
-msgstr ""
+msgstr "æ¯å€‹å°ˆæ¡ˆæœ€å¤§è«‹æ±‚所é©ç”¨çš„時間間隔(秒)。"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "æ›´æ–°æ“作將在 %{number_of_minutes} 分é˜å¾Œé€¾æ™‚。å°æ–¼å¤§åž‹ç‰ˆæœ¬åº«ï¼Œè«‹ä½¿ç”¨ clone/push 組åˆã€‚"
msgid "The uploaded file was invalid. Supported file extensions are %{extensions}."
-msgstr ""
+msgstr "上傳的文件無效。支æ´çš„文件擴展å為%{extensions}。"
msgid "The user is being deleted."
-msgstr ""
+msgstr "使用者正在被刪除。"
msgid "The user map has been saved. Continue by selecting the projects you want to import."
-msgstr ""
+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 ""
+msgstr "使用者å°æ‡‰æ˜¯åƒèˆ‡å°ˆæ¡ˆçš„ FogBugz 使用者的電å­éƒµä»¶åœ°å€å’Œä½¿ç”¨è€…å稱將被匯入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€éŽä»¥ä¸‹è¡¨æ ¼ä¾†ä¿®æ”¹å°æ‡‰é—œä¿‚。"
msgid "The user you are trying to approve is not pending approval"
-msgstr ""
+msgstr "您嘗試核准的使用者ä¸æ˜¯å¾…核准的使用者"
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
-msgstr ""
+msgstr "您正在嘗試å‡çµçš„使用者在éŽåŽ»%{minimum_inactive_days}天一直處於活動狀態,因此無法å‡çµã€‚"
msgid "The username for the Jenkins server."
-msgstr ""
+msgstr "Jenkins 伺æœå™¨çš„使用者å稱。"
msgid "The value of the provided variable exceeds the %{count} character limit"
-msgstr ""
+msgstr "æ供的變數值超éŽäº†%{count}å­—å…ƒé™åˆ¶"
msgid "The vulnerability is known, and has not been remediated or mitigated, but is considered to be an acceptable business risk."
-msgstr ""
+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 ""
+msgstr "該æ¼æ´žæ˜¯å·²çŸ¥çš„,並且尚未修復或緩解,但被èªç‚ºå­˜åœ¨æ–¼ä¸æœƒæ›´æ–°çš„應用程å¼éƒ¨åˆ†ä¸­ã€‚"
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
-msgstr ""
+msgstr "æ¼æ´žå·²ä¸å†è¢«æª¢æ¸¬åˆ°ã€‚請於更改其狀態å‰ç¢ºä¿æ¼æ´žå·²ä¿®å¾©æˆ–移除。"
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
-msgstr ""
+msgstr "æ¼æ´žå·²ä¸å†è¢«æª¢æ¸¬åˆ°ã€‚請於更改其狀態å‰ç¢ºä¿æ¼æ´žå·²ä¿®è£œã€‚"
msgid "Theme"
-msgstr ""
+msgstr "主題"
msgid "There are currently no events."
-msgstr ""
+msgstr "當å‰æ²’有事件。"
msgid "There are merge conflicts"
-msgstr ""
+msgstr "存在åˆä½µè¡çª"
msgid "There are no %{replicableTypeName} to show"
-msgstr ""
+msgstr "沒有å¯é¡¯ç¤ºçš„%{replicableTypeName}"
msgid "There are no GPG keys associated with this account."
-msgstr ""
+msgstr "沒有與此帳號關è¯çš„GPG金鑰。"
msgid "There are no GPG keys with access to your account."
-msgstr ""
+msgstr "沒有å¯å­˜å–您帳號的GPG金鑰。"
msgid "There are no SSH keys associated with this account."
-msgstr ""
+msgstr "沒有與此帳號關è¯çš„SSH金鑰。"
msgid "There are no SSH keys with access to your account."
-msgstr ""
+msgstr "沒有å¯å­˜å–您帳號的SSH金鑰。"
msgid "There are no Spam Logs"
-msgstr ""
+msgstr "沒有垃圾郵件日誌"
msgid "There are no abuse reports!"
-msgstr ""
+msgstr "沒有濫用報告ï¼"
msgid "There are no archived projects yet"
-msgstr ""
+msgstr "當å‰å°šç„¡å·²æ­¸æª”的專案"
msgid "There are no archived requirements"
-msgstr ""
+msgstr "沒有已歸檔的需求"
msgid "There are no archived test cases"
-msgstr ""
+msgstr "沒有已歸檔的測試案例"
+
+msgid "There are no changed labels"
+msgstr "沒有更改標籤"
msgid "There are no changes"
-msgstr ""
+msgstr "沒有變化"
msgid "There are no charts configured for this page"
-msgstr ""
+msgstr "沒有為此é é¢è¨­å®šåœ–表"
msgid "There are no closed epics"
-msgstr ""
+msgstr "沒有已關閉的å²è©©"
msgid "There are no closed issues"
-msgstr ""
+msgstr "沒有已關閉的議題"
msgid "There are no closed merge requests"
-msgstr ""
+msgstr "沒有已關閉的åˆä½µè«‹æ±‚"
msgid "There are no commits yet."
-msgstr ""
+msgstr "ç›®å‰é‚„沒有æ交。"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
-msgstr ""
+msgstr "沒有為此 GitLab 實體設定自訂專案範本。它們是從 GitLab 的管ç†å€åŸŸå•Ÿç”¨çš„。請與您的 GitLab 實體管ç†å“¡è¯çµ¡ä»¥è¨­å®šè‡ªè¨‚專案範本。"
msgid "There are no issues to show"
-msgstr ""
+msgstr "ç›®å‰ç„¡è­°é¡Œ"
msgid "There are no issues with the selected labels"
-msgstr ""
+msgstr "所é¸æ¨™è¨˜æ²’有議題"
msgid "There are no matching files"
-msgstr ""
+msgstr "沒有符åˆçš„文件"
msgid "There are no open epics"
-msgstr ""
+msgstr "沒有開啟中的å²è©©"
msgid "There are no open issues"
-msgstr ""
+msgstr "沒有未關閉的議題"
msgid "There are no open merge requests"
-msgstr ""
+msgstr "沒有未關閉的åˆä½µè«‹æ±‚"
msgid "There are no open requirements"
-msgstr ""
+msgstr "沒有開啟的需求"
msgid "There are no open test cases"
-msgstr ""
+msgstr "沒有開啟的測試案例"
msgid "There are no packages yet"
-msgstr ""
+msgstr "還沒有軟體套件"
msgid "There are no projects shared with this group yet"
-msgstr ""
+msgstr "ç›®å‰å°šç„¡åˆ†äº«çµ¦è©²ç¾¤çµ„的專案"
msgid "There are no secure files yet."
-msgstr ""
+msgstr "還沒有安全文件。"
msgid "There are no topics to show."
-msgstr ""
+msgstr "沒有è¦é¡¯ç¤ºçš„主題。"
msgid "There are no variables yet."
-msgstr ""
+msgstr "還沒有變數。"
msgid "There are running deployments on the environment. Please retry later."
-msgstr ""
+msgstr "環境上有正在執行的部署。請ç¨å¾Œé‡è©¦ã€‚"
msgid "There are several file size limits in place for the Package Registry."
-msgstr ""
+msgstr "軟體套件庫有幾個文件大å°é™åˆ¶ã€‚"
msgid "There are several rate limits in place to protect the system."
-msgstr ""
+msgstr "為了ä¿è­·è©²ç³»çµ±ï¼Œå¯¦è¡Œäº†å¹¾ç¨®é€ŸçŽ‡é™åˆ¶ã€‚"
msgid "There are several size limits in place."
-msgstr ""
+msgstr "有幾個大å°é™åˆ¶ã€‚"
+
+msgid "There are unsubmitted review comments."
+msgstr "有未æ交的審閱留言。"
msgid "There is already a repository with that name on disk"
-msgstr ""
+msgstr "ç£ç¢Ÿä¸Šå·²å­˜åœ¨å…·æœ‰è©²å稱的版本庫"
msgid "There is already a to-do item for this design."
-msgstr ""
+msgstr "這個設計已經有一個待辦事項。"
msgid "There is no chart data available."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„圖表資料。"
msgid "There is no data available."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„資料。"
msgid "There is no data available. Please change your selection."
-msgstr ""
+msgstr "沒有å¯ç”¨è³‡æ–™ã€‚請變更é¸æ“‡ã€‚"
msgid "There is no seat left to activate the member"
-msgstr ""
+msgstr "已無啟用會員的席次"
msgid "There is no table data available."
-msgstr ""
+msgstr "沒有å¯ç”¨çš„表資料。"
msgid "There is too much data to calculate. Please change your selection."
-msgstr ""
+msgstr "資料太多無法計算。請更改您的é¸æ“‡ã€‚"
msgid "There was a problem communicating with your device."
-msgstr ""
+msgstr "與您的設備通信時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching CRM contacts."
-msgstr ""
+msgstr "è®€å– CRM è¯çµ¡äººæ™‚發生錯誤。"
msgid "There was a problem fetching CRM organizations."
-msgstr ""
+msgstr "è®€å– CRM 組織時發生錯誤。"
msgid "There was a problem fetching branches."
-msgstr ""
+msgstr "å–得分支時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching emojis."
-msgstr ""
+msgstr "å–得表情符號時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching epics."
-msgstr ""
+msgstr "å–å¾—å²è©©æ™‚出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching groups."
-msgstr ""
+msgstr "å–得群組時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching iterations."
-msgstr ""
+msgstr "å–得迭代時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching labels."
-msgstr ""
+msgstr "å–得標記時發生錯誤。"
msgid "There was a problem fetching linked pipelines."
-msgstr ""
+msgstr "å–得連çµçš„æµæ°´ç·šæ™‚出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching milestones."
-msgstr ""
+msgstr "å–得里程碑時發生錯誤。"
msgid "There was a problem fetching project branches."
-msgstr ""
+msgstr "å–得專案分支時發生錯誤。"
msgid "There was a problem fetching project tags."
-msgstr ""
+msgstr "å–得專案標籤時發生錯誤。"
msgid "There was a problem fetching project users."
-msgstr ""
+msgstr "å–得專案使用者時發生錯誤。"
msgid "There was a problem fetching recent groups."
-msgstr ""
+msgstr "å–得最近的群組時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching recent projects."
-msgstr ""
+msgstr "å–得最近的專案時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching releases."
-msgstr ""
+msgstr "å–得版本時發生錯誤。"
msgid "There was a problem fetching the job token scope value"
-msgstr ""
+msgstr "å–得作業令牌範åœå€¼æ™‚出ç¾å•é¡Œ"
msgid "There was a problem fetching the keep latest artifacts setting."
-msgstr ""
+msgstr "å–å¾—ä¿ç•™æœ€æ–°çš„產出物設定時出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching the latest pipeline status."
-msgstr ""
+msgstr "å–得最新æµæ°´ç·šç‹€æ…‹æ™‚出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching the pipeline stages."
-msgstr ""
+msgstr "å–å¾—æµæ°´ç·šéšŽæ®µæ™‚出ç¾å•é¡Œã€‚"
msgid "There was a problem fetching the projects"
-msgstr ""
+msgstr "å–得專案時出ç¾å•é¡Œ"
msgid "There was a problem fetching users."
-msgstr ""
+msgstr "å–得使用者時出ç¾å•é¡Œã€‚"
msgid "There was a problem handling the pipeline data."
-msgstr ""
+msgstr "å–å¾—æµæ°´ç·šè³‡æ–™æ™‚出ç¾å•é¡Œã€‚"
msgid "There was a problem sending the confirmation email"
-msgstr ""
+msgstr "發é€ç¢ºèªéƒµä»¶æ™‚出ç¾å•é¡Œ"
msgid "There was a problem updating the keep latest artifacts setting."
-msgstr ""
-
-msgid "There was an error %{message} to-do item."
-msgstr ""
+msgstr "æ›´æ–°ä¿ç•™æœ€æ–°ç”¢å‡ºç‰©è¨­å®šæ™‚出ç¾å•é¡Œã€‚"
msgid "There was an error adding a To Do."
-msgstr ""
+msgstr "加入待辦事項時出ç¾éŒ¯èª¤"
msgid "There was an error creating the dashboard, branch name is invalid."
-msgstr ""
+msgstr "建立儀表æ¿æ™‚發生錯誤:分支å稱無效。"
msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
-msgstr ""
+msgstr "建立儀表æ¿æ™‚發生錯誤:已經有åŒå的分支:%{branch}。"
msgid "There was an error creating the issue"
-msgstr ""
+msgstr "建立議題時發生錯誤"
msgid "There was an error deleting the To Do."
-msgstr ""
+msgstr "刪除待辦事項時出ç¾éŒ¯èª¤"
msgid "There was an error fetching configuration for charts"
-msgstr ""
+msgstr "å–得圖表的設定時發生錯誤"
msgid "There was an error fetching data for the selected stage"
-msgstr ""
+msgstr "å–å¾—å·²é¸å®šçš„階段資料時發生錯誤"
msgid "There was an error fetching data for the tasks by type chart"
-msgstr ""
+msgstr "ä¾é¡žåž‹åœ–表å–得作業資料時發生錯誤"
msgid "There was an error fetching label data for the selected group"
-msgstr ""
+msgstr "å–å¾—é¸å–的群組標記資料時發生錯誤"
msgid "There was an error fetching median data for stages"
-msgstr ""
+msgstr "å–得階段的中ä½æ•¸è³‡æ–™æ™‚發生錯誤"
msgid "There was an error fetching projects"
-msgstr ""
+msgstr "å–得專案時發生錯誤"
msgid "There was an error fetching stage total counts"
-msgstr ""
+msgstr "å–得階段總計數時發生錯誤"
msgid "There was an error fetching the %{replicableType}"
-msgstr ""
+msgstr "å–å¾—%{replicableType}時發生錯誤"
msgid "There was an error fetching the deploy freezes."
-msgstr ""
+msgstr "å–å¾—å‡çµéƒ¨ç½²æ™‚發生錯誤。"
msgid "There was an error fetching the environments information."
-msgstr ""
+msgstr "å–得環境訊æ¯æ™‚發生錯誤。"
msgid "There was an error fetching the jobs for your project."
-msgstr ""
+msgstr "為您的專案å–得作業時發生錯誤。"
msgid "There was an error fetching the top labels for the selected group"
-msgstr ""
+msgstr "å–å¾—é¸ä¸­ç¾¤çµ„的頂級標記時發生錯誤"
msgid "There was an error fetching the variables."
-msgstr ""
+msgstr "å–得變數時發生錯誤。"
msgid "There was an error fetching value stream analytics stages."
-msgstr ""
+msgstr "å–得價值æµåˆ†æžéšŽæ®µæ™‚發生錯誤。"
msgid "There was an error gathering the chart data"
-msgstr ""
+msgstr "收集圖表資料時發生錯誤"
msgid "There was an error getting the epic participants."
-msgstr ""
+msgstr "å–å¾—å²è©©åƒèˆ‡è€…時發生錯誤。"
msgid "There was an error importing the Jira project."
-msgstr ""
+msgstr "匯入Jira專案時發生錯誤。"
msgid "There was an error loading related feature flags"
-msgstr ""
+msgstr "載入相關功能標誌時發生錯誤"
msgid "There was an error loading users activity calendar."
-msgstr ""
+msgstr "載入使用者活動日曆時發生錯誤。"
msgid "There was an error parsing the data for this graph."
-msgstr ""
+msgstr "解æžæ­¤åœ–表的資料時發生錯誤。"
msgid "There was an error removing the e-mail."
-msgstr ""
-
-msgid "There was an error resetting group pipeline minutes."
-msgstr ""
+msgstr "刪除電å­éƒµä»¶æ™‚發生錯誤。"
msgid "There was an error resetting user pipeline minutes."
-msgstr ""
+msgstr "é‡è¨­ä½¿ç”¨è€…æµæ°´ç·šåˆ†é˜æ•¸æ™‚發生錯誤。"
msgid "There was an error retrieving the Jira users."
-msgstr ""
+msgstr "å–å¾—Jira使用者時發生錯誤。"
msgid "There was an error saving your changes."
-msgstr ""
+msgstr "ä¿å­˜è®Šæ›´æ™‚發生錯誤。"
msgid "There was an error subscribing to this label."
-msgstr ""
+msgstr "訂閱此標記時發生錯誤。"
msgid "There was an error syncing project %{name}"
-msgstr ""
+msgstr "åŒæ­¥å°ˆæ¡ˆ%{name}時發生錯誤"
msgid "There was an error syncing the %{replicableType}"
-msgstr ""
+msgstr "åŒæ­¥%{replicableType}時發生錯誤"
msgid "There was an error trying to validate your query"
-msgstr ""
+msgstr "嘗試驗證您的查詢時發生錯誤"
msgid "There was an error updating the Maintenance Mode Settings"
-msgstr ""
+msgstr "更新維護模å¼è¨­å®šæ™‚發生錯誤"
msgid "There was an error updating the dashboard, branch name is invalid."
-msgstr ""
+msgstr "更新儀表æ¿æ™‚發生錯誤,分支å稱無效。"
msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
-msgstr ""
+msgstr "更新儀表æ¿æ™‚發生錯誤,å為%{branch}的分支已存在。"
msgid "There was an error when reseting email token."
-msgstr ""
+msgstr "é‡è¨­é›»å­éƒµä»¶ä»¤ç‰Œ(權æ–)時發生錯誤。"
msgid "There was an error when subscribing to this label."
-msgstr ""
+msgstr "訂閱此標記時發生錯誤。"
msgid "There was an error when unsubscribing from this label."
-msgstr ""
+msgstr "å–消訂閱此標記時發生錯誤。"
msgid "There was an error while fetching the chart data. Please refresh the page to try again."
-msgstr ""
+msgstr "å–得圖表資料時發生錯誤。請é‡æ–°æ•´ç†é é¢ä»¥é‡è©¦ã€‚"
msgid "There was an error while fetching the table data. Please refresh the page to try again."
-msgstr ""
+msgstr "å–得表格資料時發生錯誤。請é‡æ–°æ•´ç†é é¢ä»¥é‡è©¦ã€‚"
msgid "There was an error while fetching value stream analytics data."
-msgstr ""
+msgstr "å–得價值æµåˆ†æžè³‡æ–™æ™‚發生錯誤。"
msgid "There was an error while fetching value stream analytics duration data."
-msgstr ""
-
-msgid "There was an error while fetching value stream summary data."
-msgstr ""
+msgstr "å–得價值æµåˆ†æžæŒçºŒæ™‚間時發生錯誤。"
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
-msgstr ""
+msgstr "reCAPTCHA 驗證錯誤。請å†æ¬¡é©—è­‰ reCAPTCHA。"
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 "這些日期會影響您的å²è©©åœ¨è·¯ç·šåœ–中的顯示方å¼ã€‚設定一個固定日期或從分é…給此å²è©©ä¸­è­°é¡Œçš„里程碑繼承的日期。"
msgid "These examples show how to trigger this project's pipeline for a branch or tag."
-msgstr ""
+msgstr "這些範例顯示了如何為分支或標記觸發此專案的æµæ°´ç·šã€‚"
msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
-msgstr ""
+msgstr "這些ç¾æœ‰çš„議題具有類似的標題。在那裡留言å¯èƒ½æ›´å¥½ï¼Œè€Œä¸æ˜¯å»ºç«‹å¦ä¸€å€‹é¡žä¼¼çš„å•é¡Œã€‚"
msgid "These runners are shared across projects in this group."
-msgstr ""
+msgstr "這些執行器(runners)在該群組中的專案之間共用。"
msgid "These runners are shared across this GitLab instance."
-msgstr ""
+msgstr "這些執行器(runners)在此 GitLab 實例中共用。"
msgid "These runners are specific to this project."
-msgstr ""
+msgstr "以下這些執行器(runners)為該專案特定。"
msgid "These variables are inherited from the parent group."
-msgstr ""
+msgstr "這些變數是從上層群組繼承的。"
msgid "These will be sent to %{email} in an attachment once finished."
-msgstr ""
+msgstr "在附件完æˆå¾Œå°‡ç™¼é€è‡³ %{email}。"
msgid "Things to be aware of before transferring:"
-msgstr ""
+msgstr "轉移å‰éœ€è¦æ³¨æ„的事項:"
msgid "Third Party Advisory Link"
-msgstr ""
+msgstr "第三方建議連çµ"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
-msgstr ""
+msgstr "æ­¤%{issuableDisplayName}被鎖定。åªæœ‰å°ˆæ¡ˆæˆå“¡å¯ä»¥ç•™è¨€ã€‚"
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
-msgstr ""
+msgstr "æ­¤%{issuable}已被鎖定。åªæœ‰%{strong_open}專案æˆå“¡%{strong_close}æ‰å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{confidentialLinkEnd} and %{lockedLinkStart}locked%{lockedLinkEnd}."
-msgstr ""
+msgstr "此 %{noteableTypeText} 是%{confidentialLinkStart}機密的%{confidentialLinkEnd}且%{lockedLinkStart}已鎖定%{lockedLinkEnd}。"
msgid "This %{noteableTypeText} is locked."
-msgstr ""
+msgstr "此%{noteableTypeText}已鎖定。"
msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "因為 %{reason}無法顯示 %{viewer} 。您å¯ä»¥æ”¹ç‚º %{options}。"
msgid "This Cron pattern is invalid"
-msgstr ""
+msgstr "æ­¤Cronæ ¼å¼ç„¡æ•ˆ"
msgid "This GitLab instance does not provide any shared runners yet. Instance administrators can register shared runners in the admin area."
-msgstr ""
+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 ""
+msgstr "該GitLab實例的授權許å¯ç‚º%{insufficient_license}級別。Geo 僅é©ç”¨æ–¼è‡³å°‘æ“有高級授權許å¯çš„使用者。"
msgid "This PDF is too large to display. Please download to view."
-msgstr ""
+msgstr "此 PDF 太大而無法顯示。請下載查看。"
msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
-msgstr ""
+msgstr "此專案目å‰å·²æ­¸æª”並唯讀。如果您想è¦æ¢å¾©æ‹‰å–é¡åƒï¼Œè«‹å…ˆå–消歸檔。"
msgid "This URL already exists."
-msgstr ""
+msgstr "此 URL 已存在"
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
-msgstr ""
+msgstr "æ­¤æ“作å¯èƒ½å°Žè‡´è³‡æ–™éºå¤±ã€‚為防止æ„外,我們會è¦æ±‚您確èªæ‚¨çš„æ“作。"
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
-msgstr ""
+msgstr "æ­¤æ“作無法撤消,它將永久刪除%{key}SSH金鑰"
msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} and everything this project contains. %{strongOpen}There is no going back.%{strongClose}"
-msgstr ""
+msgstr "æ­¤æ“作會刪除 %{codeOpen}%{project_path_with_namespace}%{codeClose} 和此專案包å«çš„所有內容。 %{strongOpen}無法撤消。%{strongClose}"
msgid "This action deletes %{codeOpen}%{project_path_with_namespace}%{codeClose} on %{date} and everything this project contains."
-msgstr ""
+msgstr "æ­¤æ“作會刪除在 %{date} 建立的 %{codeOpen}%{project_path_with_namespace}%{codeClose} 以åŠè©²å°ˆæ¡ˆåŒ…å«çš„所有內容。"
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 "æ­¤æ“作會刪除在 %{date} 建立的 %{codeOpen}%{project_path_with_namespace}%{codeClose} 以åŠè©²å°ˆæ¡ˆåŒ…å«çš„所有內容。%{strongOpen}æ­¤æ“作ä¸å¯æ¢å¾©ã€‚%{strongClose}"
msgid "This action will %{strongOpen}permanently remove%{strongClose} %{codeOpen}%{group}%{codeClose} %{strongOpen}immediately%{strongClose}."
-msgstr ""
+msgstr "æ­¤æ“作將%{strongOpen}ç«‹å³%{strongClose}%{strongOpen}永久移除%{strongClose} %{codeOpen}%{group}%{codeClose}。"
msgid "This also resolves all related threads"
-msgstr ""
+msgstr "這也會åŒæ™‚解決所有相關主題"
msgid "This also resolves this thread"
-msgstr ""
+msgstr "這也會åŒæ™‚解決此主題"
msgid "This application was created by %{user_link}."
-msgstr ""
+msgstr "此應用程å¼ç”±%{user_link}建立。"
msgid "This application was created for group %{group_link}."
-msgstr ""
+msgstr "此應用程å¼æ˜¯ç‚º%{group_link}群組建立的。"
msgid "This application will be able to:"
-msgstr ""
+msgstr "此應用程å¼å°‡å¯ä»¥ï¼š"
msgid "This archive has been requested too many times. Try again later."
-msgstr ""
+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 ""
+msgstr "此附件已被截斷,以é¿å…超éŽæœ€å¤§å…è¨±çš„é™„ä»¶å¤§å° %{size_limit}。 其中包括%{count} 個%{issuables} 中的%{written_count}個。考慮縮å°é¸æ“‡çš„ %{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 "此附件已被截斷,以é¿å…超éŽæœ€å¤§å…è¨±çš„é™„ä»¶å¤§å° %{size_limit}。 其中包括了 %{issues_count} 個議題中的 %{written_count} 個,考慮縮å°åŒ¯å‡ºçš„é¸æ“‡ç¯„åœã€‚"
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 "此附件已被截斷,以é¿å…超éŽæœ€å¤§å…è¨±çš„é™„ä»¶å¤§å° %{size_limit}。 其中包括%{merge_requests_count} 個åˆä½µè«‹æ±‚中的%{written_count}個。考慮縮å°åˆä½µè«‹æ±‚çš„é¸æ“‡ç¯„åœã€‚"
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 "此附件已被截斷,以é¿å…超éŽæœ€å¤§å…è¨±çš„é™„ä»¶å¤§å° %{size_limit}。 其中包括了 %{requirements_count} é …è¦æ±‚中的 %{written_count} 項;考慮縮å°åŒ¯å‡ºçš„é¸æ“‡ç¯„åœã€‚"
msgid "This block is self-referential"
-msgstr ""
+msgstr "該å€å¡Šç‚ºè‡ªæˆ‘引用"
msgid "This board's scope is reduced"
-msgstr ""
+msgstr "此看æ¿ç¯„åœç¸®å°äº†"
msgid "This chart could not be displayed"
-msgstr ""
+msgstr "無法顯示此圖表"
msgid "This clears repository check states for all projects in the database and cannot be undone. Are you sure?"
-msgstr ""
+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 ""
+msgstr "此程å¼ç¢¼æ®µåŒ…å«å映在設定表單中的所有內容。將其複製並貼上到 %{linkStart}.gitlab-ci.yml%{linkEnd} 文件中並ä¿å­˜æ‚¨çš„更改。之後的 %{scanType} 掃瞄將使用這些設定。"
msgid "This comment changed after you started editing it. Review the %{startTag}updated comment%{endTag} to ensure information is not lost."
-msgstr ""
+msgstr "此留言在您開始編輯後發生了變化。查看 %{startTag}更新留言%{endTag} 以確ä¿è¨Šæ¯ä¸æœƒä¸Ÿå¤±ã€‚"
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 ""
+msgstr "æ­¤æ交是åˆä½µè«‹æ±‚ %{link_to_merge_request} 的一部分。此處建立的留言將在該åˆä½µè«‹æ±‚的上下文中建立。"
msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
-msgstr ""
+msgstr "æ­¤æ交使用 %{strong_open}多個%{strong_close} ç°½å進行簽署。"
msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
-msgstr ""
+msgstr "æ­¤æ交使用%{strong_open}已驗證的%{strong_close}ç°½å進行簽署,並且已驗證æ交者的電å­éƒµä»¶å±¬æ–¼åŒä¸€ä½¿ç”¨è€…。"
msgid "This commit was signed with a different user's verified signature."
-msgstr ""
+msgstr "æ­¤æ交使用其他使用者的已驗證簽å進行簽å。"
msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
-msgstr ""
+msgstr "æ­¤æ交已使用經éŽé©—證的簽å進行簽署,但%{strong_open}尚未驗證%{strong_close}æ交者電å­éƒµä»¶å±¬æ–¼åŒä¸€ä½¿ç”¨è€…。"
msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
-msgstr ""
+msgstr "æ­¤æ交使用%{strong_open}未經驗證的%{strong_close}ç°½å進行簽署。"
msgid "This content could not be displayed because %{reason}. You can %{options} instead."
-msgstr ""
+msgstr "由於%{reason},無法顯示此內容。您å¯ä»¥%{options}代替。"
msgid "This content could not be displayed because it is stored in LFS. You can %{linkStart}download it%{linkEnd} instead."
-msgstr ""
+msgstr "此內容無法顯示,因為它儲存在 LFS 中。您å¯ä»¥ %{linkStart}下載它%{linkEnd} 來代替。"
msgid "This credential has expired"
-msgstr ""
+msgstr "此憑證已éŽæœŸ"
msgid "This deployment is not waiting for approvals."
-msgstr ""
+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 ""
+msgstr "此部署作業ä¸æœƒè‡ªå‹•åŸ·è¡Œï¼Œå¿…須手動啟動,但您無權存å–此作業的å—ä¿è­·ç’°å¢ƒã€‚該作業åªèƒ½ç”±å…許部署到環境的專案æˆå“¡å•Ÿå‹•ã€‚"
msgid "This device has already been registered with us."
-msgstr ""
+msgstr "此設備已註冊。"
msgid "This device has not been registered with us."
-msgstr ""
+msgstr "此設備未註冊。"
msgid "This diff is collapsed."
-msgstr ""
+msgstr "此差異已摺疊。"
msgid "This directory"
-msgstr ""
+msgstr "該目錄"
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
-msgstr ""
+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 ""
+msgstr "該電å­éƒµä»¶å°‡å–代您之å‰å¯èƒ½æ”¶åˆ°é—œæ–¼ %{project_link} 計劃刪除的任何電å­éƒµä»¶ã€‚"
msgid "This email supersedes any previous emails about scheduled deletion you may have received for %{project_name}."
-msgstr ""
+msgstr "該電å­éƒµä»¶å°‡å–代您之å‰å¯èƒ½æ”¶åˆ°é—œæ–¼ %{project_name} 計劃刪除的任何電å­éƒµä»¶ã€‚"
msgid "This endpoint has been requested too many times. Try again later."
-msgstr ""
+msgstr "此端點請求次數éŽå¤šã€‚è«‹ç¨å¾Œå†è©¦ã€‚"
msgid "This environment has no deployments yet."
-msgstr ""
+msgstr "此環境還沒有部署。"
msgid "This environment is being deployed"
-msgstr ""
+msgstr "正在部署到此環境"
msgid "This environment is being re-deployed"
-msgstr ""
+msgstr "正在é‡æ–°éƒ¨ç½²åˆ°æ­¤ç’°å¢ƒ"
msgid "This environment is not protected."
-msgstr ""
+msgstr "此環境ä¸å—ä¿è­·ã€‚"
msgid "This environment's canary ingress has been updated recently. Please retry later."
-msgstr ""
+msgstr "此環境的Canary Ingress最近有更新。請ç¨å¾Œå†è©¦ã€‚"
msgid "This epic already has the maximum number of child epics."
-msgstr ""
+msgstr "æ­¤å²è©©çš„å­å²è©©æ•¸ç›®å·²é”最大值。"
msgid "This epic does not exist or you don't have sufficient permission."
-msgstr ""
+msgstr "æ­¤å²è©©ä¸å­˜åœ¨æˆ–者您沒有足夠的權é™ã€‚"
msgid "This epic would exceed maximum number of related epics."
-msgstr ""
+msgstr "æ­¤å²è©©å°‡è¶…éŽç›¸é—œå²è©©çš„最大數é‡ã€‚"
msgid "This feature requires local storage to be enabled"
-msgstr ""
+msgstr "此功能需è¦å•Ÿç”¨æœ¬åœ°å„²å­˜"
msgid "This field is required"
-msgstr ""
+msgstr "此欄ä½ç‚ºå¿…å¡«"
msgid "This field is required."
-msgstr ""
+msgstr "該欄ä½æ˜¯å¿…填。"
msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
-msgstr ""
+msgstr "此文件已被修改以æ高å¯è®€æ€§ï¼Œä¸èƒ½æŽ¥å—建議,請直接編輯。"
msgid "This form is disabled in preview"
-msgstr ""
+msgstr "此表單在é è¦½ä¸­è¢«ç¦ç”¨"
msgid "This group"
-msgstr ""
+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 ""
+msgstr "該群組åŠå…¶å­ç¾¤çµ„和專案將在 %{deletion_adjourned_period} 天內處於「待刪除ã€ç‹€æ…‹ï¼Œç„¶å¾Œåœ¨ %{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 "此群組ä¸èƒ½è¢«åˆªé™¤ï¼Œå› ç‚ºå®ƒå·²é€£çµåˆ°ä¸€å€‹è¨‚閱,è¦åˆªé™¤æ­¤ç¾¤çµ„, %{linkStart}將訂閱%{linkEnd} 連çµåˆ°å¦ä¸€å€‹ç¾¤çµ„。"
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 "無法轉移此群組,它已連çµåˆ°ä¸€å€‹è¨‚閱。è¦è½‰ç§»æ­¤ç¾¤çµ„,請將%{linkStart}此訂閱%{linkEnd}連çµåˆ°å…¶ä»–群組。"
msgid "This group cannot be invited to a project inside a group with enforced SSO"
-msgstr ""
+msgstr "此群組ä¸èƒ½è¢«é‚€è«‹åˆ°å¼·åˆ¶SSO的群組中"
msgid "This group does not have any group runners yet."
-msgstr ""
+msgstr "這個群組尚未æ“有任何群組執行器(runners)。"
msgid "This group has been scheduled for permanent removal on %{date}"
-msgstr ""
+msgstr "此群組已安排在%{date}永久移除"
msgid "This group has no active access tokens."
-msgstr ""
+msgstr "此群組沒有有效的存å–令牌。"
msgid "This group is linked to a subscription"
-msgstr ""
+msgstr "此群組已連çµåˆ°è¨‚é–±"
msgid "This group is not permitted to create compliance violations"
-msgstr ""
+msgstr "ä¸å…許此群組建立é•è¦è¡Œç‚º"
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
-msgstr ""
+msgstr "此群組ã€å…¶å­ç¾¤çµ„和專案已安排在%{date}移除。"
msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
-msgstr ""
+msgstr "此群組ã€å…¶å­ç¾¤çµ„åŠå°ˆæ¡ˆå°‡æ–¼%{date}被移除,因為其父群組「%{parent_group_name}ã€å·²è¢«è¨ˆåŠƒç§»é™¤ã€‚"
msgid "This incident is already escalated with '%{escalation_policy_name}'."
-msgstr ""
+msgstr "此事件已å‡ç´šç‚ºã€Œ%{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 ""
+msgstr "請注æ„,此邀請已經發é€åˆ° %{mail_to_invite_email},但您以 %{link_to_current_user} 身份使用電å­éƒµä»¶ %{mail_to_current_user}登入。"
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 ""
+msgstr "此使用者為「幽éˆä½¿ç”¨è€…ã€ï¼Œç”¨æ–¼æŒæœ‰è¢«åˆªé™¤ä½¿ç”¨è€…的所有議題。該使用者無法被刪除。"
msgid "This is a Jira user."
-msgstr ""
+msgstr "這是一個 Jira 使用者。"
msgid "This is a confidential %{noteableTypeText}."
-msgstr ""
+msgstr "這是一個機密%{noteableTypeText}。"
msgid "This is a delayed job to run in %{remainingTime}"
-msgstr ""
+msgstr "這是一個將在%{remainingTime}後執行的延é²ä½œæ¥­ã€‚"
msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
-msgstr ""
+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 "這是專為您產生的ç§äººé›»å­éƒµä»¶åœ°å€ %{helpIcon} 任何æ“有它的人都å¯ä»¥åƒæ‚¨ä¸€æ¨£å»ºç«‹å•é¡Œæˆ–åˆä½µè«‹æ±‚。如果發生這種情æ³ï¼Œ %{resetLinkStart}é‡è¨­é€™å€‹ä»¤ç‰Œ%{resetLinkEnd}。"
msgid "This is a security log of authentication events involving your account."
-msgstr ""
+msgstr "這是涉åŠæ‚¨å¸³è™Ÿçš„身份驗證事件的安全日誌。"
msgid "This is a self-managed instance of GitLab."
-msgstr ""
+msgstr "這是GitLab的自管ç†å¯¦ä¾‹ã€‚"
msgid "This is an experimental feature developed by GitLab Incubation Engineering."
-msgstr ""
+msgstr "這是 GitLab Incubation Engineering 開發的一項實驗性功能。"
msgid "This is the highest peak of users on your installation since the license started."
-msgstr ""
+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 ""
+msgstr "此數目為您伺æœå™¨ç•¶å‰%{billable_users_link_start}收費使用者%{link_end}的數é‡ï¼Œ 也是更新授權許å¯æ™‚需è¦è³¼è²·çš„最低數é‡ã€‚"
msgid "This is your current session"
-msgstr ""
+msgstr "這是您目å‰çš„工作階段"
msgid "This issue cannot be assigned to a confidential epic because it is public."
-msgstr ""
+msgstr "此議題ä¸èƒ½åˆ†é…給機密å²è©©ï¼Œå› ç‚ºå®ƒæ˜¯å…¬é–‹çš„。"
msgid "This issue cannot be made public because it belongs to a confidential epic."
-msgstr ""
+msgstr "此議題ä¸èƒ½å…¬é–‹ï¼Œå› ç‚ºå®ƒå±¬æ–¼æ©Ÿå¯†å²è©©ã€‚"
msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
-msgstr ""
+msgstr "此議題是機密的,åªèƒ½é¡¯ç¤ºçµ¦æ“有至少「報告人ã€å­˜å–權é™çš„團隊æˆå“¡ã€‚"
msgid "This issue is currently blocked by the following issues:"
-msgstr ""
+msgstr "此議題目å‰è¢«ä»¥ä¸‹è­°é¡Œå°é˜»ï¼š"
msgid "This issue is hidden because its author has been banned"
-msgstr ""
+msgstr "此議題已隱è—,因為其作者已被ç¦æ­¢"
msgid "This issue is in a child epic of the filtered epic"
-msgstr ""
+msgstr "此議題在éŽæ¿¾å²è©©çš„å­å²è©©ä¸­"
msgid "This job could not start because it could not retrieve the needed artifacts%{punctuation}%{invalid_dependencies}"
-msgstr ""
+msgstr "此作業無法啟動,因為它無法檢索所需的工件%{punctuation}%{invalid_dependencies}"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
-msgstr ""
+msgstr "ç›®å‰ä½œæ¥­éœ€åœ¨ä¸Šç´šä½œæ¥­æˆåŠŸå¾Œæ‰å¯è¢«å•Ÿå‹•ã€‚"
msgid "This job deploys to the protected environment \"%{environment}\" which requires approvals."
-msgstr ""
+msgstr "該作業部署到å—ä¿è­·çš„環境\"%{environment}\",需è¦æ ¸å‡†ã€‚"
msgid "This job does not have a trace."
-msgstr ""
+msgstr "該作業無輸出日誌。"
msgid "This job does not run automatically and must be started manually, but you do not have access to it."
-msgstr ""
+msgstr "該作業ä¸æœƒè‡ªå‹•åŸ·è¡Œï¼Œå¿…須手動啟動,但您無權存å–它。"
msgid "This job has been canceled"
-msgstr ""
+msgstr "該作業已å–消"
msgid "This job has been skipped"
-msgstr ""
+msgstr "該作業已被跳éŽ"
msgid "This job has not been triggered yet"
-msgstr ""
+msgstr "該業還未被觸發"
msgid "This job has not started yet"
-msgstr ""
+msgstr "該業尚未開始"
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "該作業是在å¢é›†%{clusterNameOrLink}命å空間%{kubernetesNamespace}上到%{environmentLink}çš„éŽæœŸéƒ¨ç½²ã€‚"
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
-msgstr ""
+msgstr "該作業是在å¢é›†%{clusterNameOrLink}命å空間%{kubernetesNamespace}上到%{environmentLink}çš„éŽæœŸéƒ¨ç½²ã€‚查看%{deploymentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
-msgstr ""
+msgstr "該作業是在å¢é›†%{clusterNameOrLink}上到%{environmentLink}çš„éŽæœŸéƒ¨ç½²ã€‚"
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}."
-msgstr ""
+msgstr "該作業是在å¢é›†%{clusterNameOrLink}上到%{environmentLink}çš„éŽæœŸéƒ¨ç½²ã€‚查看%{deploymentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "此項作業已éŽæ™‚,無法部署到 %{environmentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}."
-msgstr ""
+msgstr "該作業是到%{environmentLink}çš„éŽæœŸéƒ¨ç½²ã€‚查看%{deploymentLink}。"
msgid "This job is archived. Only the complete pipeline can be retried."
-msgstr ""
+msgstr "這個作業已歸檔。åªèƒ½é‡è©¦æ•´å€‹æµæ°´ç·šã€‚"
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "該作業正在建立å¢é›†%{clusterNameOrLink}命å空間%{kubernetesNamespace}上到%{environmentLink}的部署。"
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "該作業正在建立å¢é›†%{clusterNameOrLink}命å空間%{kubernetesNamespace}上到%{environmentLink}的部署。該部署將覆蓋%{deploymentLink}。"
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
-msgstr ""
+msgstr "該作業正在建立å¢é›†%{clusterNameOrLink}上到%{environmentLink}的部署。"
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "該作業正在å¢é›†%{clusterNameOrLink}上建立到%{environmentLink}的部署。該部署將覆蓋%{deploymentLink}。"
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "該作業正在建立部署到%{environmentLink}。"
msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
-msgstr ""
+msgstr "該作業正在建立部署到%{environmentLink}並將覆蓋%{deploymentLink} 。"
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
-msgstr ""
+msgstr "該作業在å¢é›†%{clusterNameOrLink}命å空間%{kubernetesNamespace}上部署到%{environmentLink}。"
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
-msgstr ""
+msgstr "該作業被部署到%{clusterNameOrLink}å¢é›†ä¸Šçš„%{environmentLink}。"
msgid "This job is deployed to %{environmentLink}."
-msgstr ""
+msgstr "該作業已部署到%{environmentLink}。"
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr ""
+msgstr "該作業處於待處ç†ç‹€æ…‹ï¼Œæ­£åœ¨ç­‰å¾…被執行者挑é¸"
msgid "This job is performing tasks that must complete before it can start"
-msgstr ""
+msgstr "該作業正在處ç†ä½œæ¥­å•Ÿå‹•å‰å¿…須完æˆçš„作業"
msgid "This job is preparing to start"
-msgstr ""
+msgstr "該作業正準備開始"
msgid "This job is waiting for resource: "
-msgstr ""
+msgstr "該作業正在等待資æºï¼š "
msgid "This job requires a manual action"
-msgstr ""
+msgstr "該作業需手動æ“作"
msgid "This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes."
-msgstr ""
+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 ""
+msgstr "該作業將在計時器完æˆå¾Œè‡ªå‹•åŸ·è¡Œã€‚它們通常用於生產環境的增é‡éƒ¨ç½²ã€‚未計劃時,它會轉æ›ç‚ºæ‰‹å‹•æ“作。"
msgid "This license has already expired."
-msgstr ""
+msgstr "該授權許å¯å·²éŽæœŸã€‚"
msgid "This link points to external content"
-msgstr ""
+msgstr "該連çµæŒ‡å‘外部內容"
msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
-msgstr ""
+msgstr "該æ“作å¯èƒ½æœƒæ´©æ¼æ©Ÿå¯†è¨Šæ¯ï¼Œå› ç‚ºé¸å®šçš„分å‰ä½æ–¼å¦ä¸€å€‹å字空間中,å¯èƒ½åŒ…å«å…¶ä»–æˆå“¡ã€‚"
msgid "This means you can not push code until you create an empty repository or import existing one."
-msgstr ""
+msgstr "在建立一個空的版本庫或匯入ç¾æœ‰ç‰ˆæœ¬åº«ä¹‹å‰ï¼Œå°‡ç„¡æ³•æŽ¨é€ç¨‹å¼ç¢¼ã€‚"
msgid "This merge request branch is protected from force push."
-msgstr ""
+msgstr "這個åˆä½µè«‹æ±‚分支ä¸æœƒè¢«å¼·åˆ¶æŽ¨é€ã€‚"
msgid "This merge request cannot be rebased while there are conflicts."
-msgstr ""
+msgstr "存在è¡çªæ™‚,此åˆä½µè«‹æ±‚無法 rebase。"
msgid "This merge request does not have accessibility reports"
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚沒有無障礙性掃瞄報告"
msgid "This merge request does not have codequality reports"
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚沒有程å¼ç¢¼è³ªé‡å ±å‘Š"
msgid "This merge request is closed. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚已關閉。è¦æ‡‰ç”¨æ­¤å»ºè­°ï¼Œè«‹ç›´æŽ¥ç·¨è¼¯æ­¤æ–‡ä»¶ã€‚"
msgid "This merge request is from a private project to a public project."
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚是從ç§æœ‰å°ˆæ¡ˆåˆ°å…¬é–‹å°ˆæ¡ˆã€‚"
msgid "This merge request is from a private project to an internal project."
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚是從ç§æœ‰å°ˆæ¡ˆåˆ°å…§éƒ¨å°ˆæ¡ˆã€‚"
msgid "This merge request is from an internal project to a public project."
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚是從內部專案到公開專案。"
msgid "This merge request is locked."
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚已鎖定。"
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚å·²åˆä½µã€‚è¦æ‡‰ç”¨æ­¤å»ºè­°ï¼Œè«‹ç›´æŽ¥ç·¨è¼¯æ­¤æ–‡ä»¶ã€‚"
msgid "This namespace has already been taken! Please choose another one."
-msgstr ""
+msgstr "該命å空間已被使用ï¼è«‹é¸æ“‡å…¶ä»–命å空間。"
msgid "This only applies to repository indexing operations."
-msgstr ""
+msgstr "這僅é©ç”¨æ–¼ç‰ˆæœ¬åº«ç´¢å¼•æ“作。"
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
-msgstr ""
+msgstr "該é é¢ä¸å¯ç”¨ï¼Œæ‚¨ç„¡æ¬Šè·¨å°ˆæ¡ˆé–±è®€ç›¸é—œè¨Šæ¯ã€‚"
msgid "This page sends a payload. Go back to the events page to see a newly created event."
-msgstr ""
+msgstr "該é é¢ç™¼é€äº†ä¸€å€‹æœ‰æ•ˆè³‡æ–™ã€‚返回事件é é¢æŸ¥çœ‹æ–°å»ºç«‹çš„事件。"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
-msgstr ""
+msgstr "該æµæ°´ç·šä½¿ç”¨äº†åŒ…å«%{b_open}Auto DevOps%{b_close}çš„é å…ˆå®šç¾©çš„CI/CD設定。"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
-msgstr ""
+msgstr "該æµæ°´ç·šä½¿ç”¨äº† %{strongStart}Auto DevOps%{strongEnd}é å…ˆå®šç¾©ä¸¦å·²å•Ÿç”¨çš„CI/CD設定。"
msgid "This pipeline was triggered by a schedule."
-msgstr ""
+msgstr "該æµæ°´ç·šæ˜¯ç”±æŽ’程觸發的."
msgid "This process deletes the project repository and all related resources."
-msgstr ""
+msgstr "該æµç¨‹å°‡åˆªé™¤å°ˆæ¡ˆç‰ˆæœ¬åº«å’Œæ‰€æœ‰ç›¸é—œè³‡æºã€‚"
msgid "This project"
-msgstr ""
+msgstr "ç›®å‰å°ˆæ¡ˆ"
msgid "This project can be restored until %{date}."
-msgstr ""
+msgstr "該專案å¯ä»¥åœ¨ %{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 "該專案ä¸èƒ½ç‚º%{visibilityLevel} ,因為 %{openShowLink}%{name}%{closeShowLink} çš„å¯è¦‹æ€§ç‚º %{visibility}。è¦ä½¿é€™å€‹å°ˆæ¡ˆç‚º%{visibilityLevel},您必須首先%{openEditLink}更改父群組的å¯è¦‹æ€§%{closeEditLink}。"
msgid "This project does not belong to a group and cannot make use of group runners."
-msgstr ""
+msgstr "該專案ä¸å±¬æ–¼ä»»ä½•ç¾¤çµ„,因此ä¸èƒ½ä½¿ç”¨ç¾¤çµ„執行器(runners)。"
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 "該專案未啟用%{service_desk_link_start}æœå‹™å°%{service_desk_link_end}。因此建立議題的使用者將ä¸å†æ”¶åˆ°é—œæ–¼è­°é¡Œæ›´æ–°çš„é›»å­éƒµä»¶é€šçŸ¥ã€‚"
msgid "This project does not have a wiki homepage yet"
-msgstr ""
+msgstr "該專案尚無wiki首é "
msgid "This project has no active access tokens."
-msgstr ""
+msgstr "該專案沒有有效的存å–令牌。"
msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
-msgstr ""
+msgstr "該專案 %{strongStart}ä¸æ˜¯%{strongEnd} 一個分å‰å°ˆæ¡ˆï¼Œä¸¦å…·æœ‰ä»¥ä¸‹å…§å®¹ï¼š"
msgid "This project is %{strongStart}NOT%{strongEnd} a fork. This process deletes the project repository and all related resources."
-msgstr ""
+msgstr "該專案 %{strongStart}ä¸æ˜¯%{strongEnd} 一個分å‰å°ˆæ¡ˆï¼Œæ­¤æµç¨‹å°‡åˆªé™¤å°ˆæ¡ˆç‰ˆæœ¬åº«å’Œæ‰€æœ‰ç›¸é—œçš„資æºã€‚"
msgid "This project is archived and cannot be commented on."
-msgstr ""
+msgstr "該專案已歸檔,無法加入留言。"
msgid "This project is licensed under the %{strong_start}%{license_name}%{strong_end}."
-msgstr ""
+msgstr "該專案在 %{strong_start}%{license_name}%{strong_end}下å–得授權許å¯ã€‚"
msgid "This project is not subscribed to any project pipelines."
-msgstr ""
+msgstr "該專案未訂閱任何專案æµæ°´ç·šã€‚"
msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
-msgstr ""
+msgstr "該專案使用%{strong_start}%{manager_name}%{strong_end}管ç†å…¶ä¾è³´é—œä¿‚"
msgid "This project path either does not exist or you do not have access."
-msgstr ""
+msgstr "該專案路徑ä¸å­˜åœ¨æˆ–您沒有存å–權é™ã€‚"
msgid "This project will be deleted on %{date}"
-msgstr ""
+msgstr "該專案將於 %{date} 刪除"
msgid "This project will be deleted on %{date} since its parent group '%{parent_group_name}' has been scheduled for deletion."
-msgstr ""
+msgstr "該專案將於 %{date} 刪除,因為它的父群組 '%{parent_group_name}' 已排入刪除排程。"
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you store your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
-msgstr ""
+msgstr "該專案將存在於您的群組 %{strong_open}%{namespace}%{strong_close} 中。專案是您儲存文件(版本庫)ã€å·¥ä½œè¨ˆåŠƒï¼ˆè­°é¡Œï¼‰ã€ç™¼å¸ƒæ–‡æª”(wiki)等等的地方。"
+
+msgid "This 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 "此報告使用å—支æ´çš„ MAJOR.MINOR 架構版本,但 PATCH 版本與供應商的架構版本ä¸åŒ¹é…,將嘗試é‡å° %{find_latest_patch_version} 版本進行驗證"
msgid "This repository"
-msgstr ""
+msgstr "ç›®å‰ç‰ˆæœ¬åº«"
msgid "This repository has never been checked."
-msgstr ""
+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 ""
+msgstr "此版本庫目å‰ç‚ºç©ºã€‚將新文件推é€åˆ°åˆ†æ”¯å¾Œï¼Œå°‡å»ºç«‹æ–°çš„Auto DevOpsæµæ°´ç·šã€‚"
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 "此版本庫上次檢查於%{last_check_timestamp}。檢查%{strong_start}未通éŽ%{strong_end}。請查看'repocheck.log'文件å–得發生錯誤訊æ¯ã€‚"
msgid "This repository was last checked %{last_check_timestamp}. The check passed."
-msgstr ""
+msgstr "此版本庫上次檢查於%{last_check_timestamp}。檢查通éŽã€‚"
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "此執行器(runner)僅在å—ä¿è­·åˆ†æ”¯ä¸Šè§¸ç™¼çš„æµæ°´ç·šä¸ŠåŸ·è¡Œ"
msgid "This setting can be overridden in each project."
-msgstr ""
+msgstr "ç›®å‰è¨­å®šå¯åœ¨æ¯å€‹å°ˆæ¡ˆä¸­é€²è¡Œè®Šæ›´è¦†è“‹ã€‚"
msgid "This setting has been configured at the instance level and cannot be overridden per group"
-msgstr ""
+msgstr "該設定已在實例級別é…置,且ä¸èƒ½æŒ‰ç¾¤çµ„覆蓋"
msgid "This setting is allowed for forked projects only"
-msgstr ""
+msgstr "此設定僅é©ç”¨æ–¼åˆ†å‰å°ˆæ¡ˆ"
msgid "This subscription is for"
-msgstr ""
+msgstr "此訂閱é©ç”¨æ–¼"
msgid "This suggestion already matches its content."
-msgstr ""
+msgstr "此建議已經與它的內容相åŒã€‚"
msgid "This title already exists."
-msgstr ""
+msgstr "此標題已存在。"
msgid "This user cannot be unlocked manually from GitLab"
-msgstr ""
+msgstr "無法從GitLab手動解鎖此使用者"
msgid "This user has an unconfirmed email address (%{email}). You may force a confirmation."
-msgstr ""
+msgstr "此使用者有一個未經確èªçš„é›»å­éƒµä»¶åœ°å€ (%{email})。您å¯ä»¥å¼·åˆ¶ç¢ºèªã€‚"
msgid "This user has an unconfirmed email address. You may force a confirmation."
-msgstr ""
+msgstr "此使用者有一個未經確èªçš„é›»å­éƒµä»¶åœ°å€ã€‚您å¯ä»¥å¼·åˆ¶ç¢ºèªã€‚"
msgid "This user has no active %{accessTokenTypePlural}."
-msgstr ""
+msgstr "此用戶沒有啟動的 %{accessTokenTypePlural}。"
msgid "This user has no active %{type}."
-msgstr ""
+msgstr "此使用者沒有有效的%{type}。"
msgid "This user has no identities"
-msgstr ""
+msgstr "該使用者無身份標識"
msgid "This user has no personal projects."
-msgstr ""
+msgstr "該使用者沒有個人專案。"
msgid "This user has previously committed to the %{name} project."
-msgstr ""
+msgstr "該使用者曾經æ交到%{name}專案。"
msgid "This user has the %{access} role in the %{name} project."
-msgstr ""
+msgstr "該使用者在%{name}專案中的角色為%{access}。"
msgid "This user is the author of this %{noteable}."
-msgstr ""
+msgstr "該使用者是%{noteable}的作者。"
msgid "This variable can not be masked."
-msgstr ""
+msgstr "此變數無法被隱è—。"
msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
+msgstr "這會使您註冊的應用程å¼å’Œ U2F / WebAuthn 設備無效。"
msgid "This will invalidate your registered applications and U2F devices."
-msgstr ""
+msgstr "這將使您的註冊應用程å¼å’Œ U2F 設備無效。"
msgid "This will remove the fork relationship between this project and %{fork_source}."
-msgstr ""
+msgstr "這將移除該專案和%{fork_source}之間的分å‰é—œä¿‚。"
msgid "This will remove the fork relationship between this project and other projects in the fork network."
-msgstr ""
+msgstr "這將移除此專案與分å‰ç¶²è·¯ä¸­å…¶ä»–專案之間的分å‰é—œä¿‚。"
msgid "Thread to reply to cannot be found"
-msgstr ""
+msgstr "找ä¸åˆ°è¦å›žå¾©çš„主題"
msgid "Threshold in bytes at which to compress Sidekiq job arguments."
-msgstr ""
+msgstr "壓縮 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 "拒絕 Sidekiq 作業的閾值(以ä½å…ƒçµ„為單ä½ï¼‰ã€‚如果您ä¸æƒ³é™åˆ¶ Sidekiq 作業,請將其設定為 0。"
msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
-msgstr ""
+msgstr "單次推é€ä¸­æ›´æ”¹ï¼ˆåˆ†æ”¯æˆ–標籤)的閾值數é‡ï¼Œé«˜æ–¼è©²é–¾å€¼æœƒå»ºç«‹æ‰¹æ¬¡æŽ¨é€äº‹ä»¶ï¼ˆé è¨­å€¼ç‚º 3)。"
msgid "Throughput"
-msgstr ""
+msgstr "åžåé‡"
msgid "Thursday"
-msgstr ""
+msgstr "星期四"
msgid "Time"
-msgstr ""
+msgstr "時間"
msgid "Time (in hours) that users are allowed to skip forced configuration of two-factor authentication."
-msgstr ""
+msgstr "å…許使用者跳éŽå¼·åˆ¶è¨­å®šé›™å› å­èªè­‰çš„時間(以å°æ™‚為單ä½ï¼‰"
msgid "Time based: Yes"
-msgstr ""
+msgstr "基於時間:是"
msgid "Time before an issue gets scheduled"
-msgstr ""
+msgstr "議題被列入日程表的時間"
msgid "Time before an issue starts implementation"
-msgstr ""
+msgstr "開始進行編碼å‰çš„時間"
msgid "Time between merge request creation and merge/close"
-msgstr ""
+msgstr "從建立åˆä½µè«‹æ±‚到被åˆä½µæˆ–關閉的時間"
msgid "Time estimate"
-msgstr ""
+msgstr "é ä¼°æ™‚é–“"
msgid "Time from first comment to last commit"
-msgstr ""
+msgstr "第一次留言到最後一次æ交的時間"
msgid "Time from first commit until first comment"
-msgstr ""
+msgstr "第一次æ交至第一個留言的時間"
msgid "Time from last commit to merge"
-msgstr ""
+msgstr "最後一次æ交到åˆä½µçš„時間"
msgid "Time of import: %{importTime}"
-msgstr ""
+msgstr "匯入時間: %{importTime}"
msgid "Time remaining"
-msgstr ""
+msgstr "剩餘時間:"
msgid "Time spent"
-msgstr ""
+msgstr "花費的時間"
msgid "Time to Restore Service"
-msgstr ""
+msgstr "是時候æ¢å¾©æœå‹™äº†"
msgid "Time to merge"
-msgstr ""
+msgstr "åˆä½µæ™‚é–“"
msgid "Time to subtract exceeds the total time spent"
-msgstr ""
+msgstr "è¦æ¸›åŽ»çš„時間超éŽç¸½è€—時"
msgid "Time tracking"
-msgstr ""
+msgstr "工時統計"
msgid "Time tracking report"
-msgstr ""
+msgstr "時間追蹤報告"
msgid "Time until first merge request"
-msgstr ""
+msgstr "è·é›¢ç¬¬ä¸€æ¬¡åˆä½µè«‹æ±‚的時間"
msgid "Time zone"
-msgstr ""
+msgstr "時å€"
msgid "TimeTrackingEstimated|Est"
-msgstr ""
+msgstr "é ä¼°"
msgid "TimeTracking|%{spentStart}Spent: %{spentEnd}"
-msgstr ""
+msgstr "%{spentStart}花費:%{spentEnd}"
msgid "TimeTracking|An error occurred while removing the timelog."
-msgstr ""
+msgstr "移除時間日誌時發生錯誤。"
msgid "TimeTracking|Delete time spent"
-msgstr ""
+msgstr "刪除時間花費"
msgid "TimeTracking|Estimated:"
-msgstr ""
+msgstr "é ä¼°:"
msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
-msgstr ""
+msgstr "逾時%{timeRemainingHumanReadable}"
msgid "TimeTracking|Spent"
-msgstr ""
+msgstr "耗時:"
msgid "TimeTracking|Time remaining: %{timeRemainingHumanReadable}"
-msgstr ""
+msgstr "剩餘時間: %{timeRemainingHumanReadable}"
msgid "Timeago|%s days ago"
-msgstr ""
+msgstr "%s天å‰"
msgid "Timeago|%s days remaining"
-msgstr ""
+msgstr "剩餘%s天"
msgid "Timeago|%s hours ago"
msgstr "%s å°æ™‚å‰"
msgid "Timeago|%s hours remaining"
-msgstr ""
+msgstr "剩餘%så°æ™‚"
msgid "Timeago|%s minutes ago"
-msgstr ""
+msgstr "%s分é˜å‰"
msgid "Timeago|%s minutes remaining"
-msgstr ""
+msgstr "剩餘%s分é˜"
msgid "Timeago|%s months ago"
-msgstr ""
+msgstr "%s個月å‰"
msgid "Timeago|%s months remaining"
-msgstr ""
+msgstr "剩餘%s月"
msgid "Timeago|%s seconds remaining"
-msgstr ""
+msgstr "剩餘%s秒"
msgid "Timeago|%s weeks ago"
-msgstr ""
+msgstr "%s星期å‰"
msgid "Timeago|%s weeks remaining"
-msgstr ""
+msgstr "剩餘%s星期"
msgid "Timeago|%s years ago"
-msgstr ""
+msgstr "%så¹´å‰"
msgid "Timeago|%s years remaining"
-msgstr ""
+msgstr "剩餘%s年"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "1天å‰"
msgid "Timeago|1 day remaining"
-msgstr ""
+msgstr "剩餘1天"
msgid "Timeago|1 hour ago"
-msgstr ""
+msgstr "1å°æ™‚å‰"
msgid "Timeago|1 hour remaining"
-msgstr ""
+msgstr "剩餘1å°æ™‚"
msgid "Timeago|1 minute ago"
-msgstr ""
+msgstr "1分é˜å‰"
msgid "Timeago|1 minute remaining"
-msgstr ""
+msgstr "剩餘1分é˜"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "1個月å‰"
msgid "Timeago|1 month remaining"
-msgstr ""
+msgstr "剩餘1個月"
msgid "Timeago|1 week ago"
-msgstr ""
+msgstr "1星期å‰"
msgid "Timeago|1 week remaining"
-msgstr ""
+msgstr "剩餘1星期"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "1å¹´å‰"
msgid "Timeago|1 year remaining"
-msgstr ""
+msgstr "剩餘1年"
msgid "Timeago|Past due"
-msgstr ""
+msgstr "逾期"
msgid "Timeago|in %s days"
-msgstr ""
+msgstr " %s天後"
msgid "Timeago|in %s hours"
-msgstr ""
+msgstr "%så°æ™‚後"
msgid "Timeago|in %s minutes"
-msgstr ""
+msgstr "%s分é˜å¾Œ"
msgid "Timeago|in %s months"
-msgstr ""
+msgstr " %s個月後"
msgid "Timeago|in %s seconds"
-msgstr ""
+msgstr "%s秒後"
msgid "Timeago|in %s weeks"
-msgstr ""
+msgstr "%s星期後"
msgid "Timeago|in %s years"
-msgstr ""
+msgstr "%s年後"
msgid "Timeago|in 1 day"
-msgstr ""
+msgstr "1天後"
msgid "Timeago|in 1 hour"
-msgstr ""
+msgstr "1å°æ™‚後"
msgid "Timeago|in 1 minute"
-msgstr ""
+msgstr "1分é˜å¾Œ"
msgid "Timeago|in 1 month"
-msgstr ""
+msgstr "1月後"
msgid "Timeago|in 1 week"
-msgstr ""
+msgstr "1星期後"
msgid "Timeago|in 1 year"
-msgstr ""
+msgstr "1年後"
msgid "Timeago|just now"
-msgstr ""
+msgstr "ç¾åœ¨"
msgid "Timeago|right now"
-msgstr ""
+msgstr "ç«‹å³"
msgid "Timeline|Turn recent updates view off"
-msgstr ""
+msgstr "關閉最近更新視圖"
msgid "Timeline|Turn recent updates view on"
-msgstr ""
+msgstr "開啟最近更新視圖"
+
+msgid "Timelog doesn't exist or you don't have permission to delete it"
+msgstr "時間日誌ä¸å­˜åœ¨ï¼Œæˆ–您沒有刪除時間日誌的權é™"
msgid "Timeout"
-msgstr ""
+msgstr "逾時"
msgid "Timeout connecting to the Google API. Please try again."
-msgstr ""
+msgstr "連接Google API逾時。請é‡è©¦ã€‚"
msgid "Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout."
-msgstr ""
+msgstr "中等速度的 Gitaly æ“作逾時(以秒為單ä½ï¼‰ã€‚æ供一個介於é è¨­é€¾æ™‚和快速逾時之間的值。"
msgid "Timeout for most Gitaly operations (in seconds)."
-msgstr ""
+msgstr "大多數 Gitaly æ“作逾時(以秒為單ä½ï¼‰ã€‚"
msgid "Timeout for the fastest Gitaly operations (in seconds)."
-msgstr ""
+msgstr "最快的 Gitaly æ“作逾時(以秒為單ä½ï¼‰ã€‚"
msgid "Timezone"
-msgstr ""
+msgstr "時å€"
msgid "Time|hr"
msgid_plural "Time|hrs"
-msgstr[0] ""
+msgstr[0] "å°æ™‚"
msgid "Time|min"
msgid_plural "Time|mins"
-msgstr[0] ""
+msgstr[0] "分é˜"
msgid "Time|s"
-msgstr ""
+msgstr "秒"
msgid "Tip: Hover over a job to see the jobs it depends on to run."
-msgstr ""
+msgstr "æ示:將游標懸åœåœ¨ä½œæ¥­ä¸Šå¯æŸ¥çœ‹å…¶åŸ·è¡Œæ‰€ä¾è³´çš„作業。"
msgid "Tip: add a %{linkStart}CODEOWNERS%{linkEnd} to automatically add approvers based on file paths and file types."
-msgstr ""
+msgstr "æ示:加入 %{linkStart}CODEOWNERS%{linkEnd} 以根據文件路徑和文件類型自動加入核准者。"
msgid "Title"
-msgstr ""
+msgstr "標題"
msgid "Title (required)"
-msgstr ""
+msgstr "標題 (å¿…è¦)"
msgid "Title:"
-msgstr ""
+msgstr "標題:"
msgid "Titles and Descriptions"
-msgstr ""
+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 ""
+msgstr "è¦%{link_to_help}到您的網域,請將上述金鑰加入到DNS設定中的TXT記錄。"
msgid "To Do"
-msgstr ""
+msgstr "待處ç†"
msgid "To GitLab"
-msgstr ""
+msgstr "GitLab目標路徑"
msgid "To accept this invitation, create an account or sign in."
-msgstr ""
+msgstr "è¦æŽ¥å—此邀請,請建立一個帳號或登入。"
msgid "To accept this invitation, sign in or create an account."
-msgstr ""
+msgstr "è¦æŽ¥å—此邀請,請登入或建立一個帳號。"
msgid "To accept this invitation, sign in."
-msgstr ""
+msgstr "è¦æŽ¥å—此邀請,請登入。"
msgid "To access this domain create a new DNS record"
-msgstr ""
+msgstr "è¦å­˜å–此網域,請建立新的DNS記錄"
msgid "To activate your trial, we need additional details from you."
-msgstr ""
+msgstr "è¦å•Ÿç”¨æ‚¨çš„試用版,我們需è¦æ‚¨æ供更多詳細信æ¯ã€‚"
msgid "To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "è¦åŠ å…¥è‡ªè¨‚後綴,請設定æœå‹™å°é›»å­éƒµä»¶åœ°å€ã€‚ %{linkStart}了解更多。%{linkEnd}"
msgid "To add the entry manually, provide the following details to the application on your phone."
-msgstr ""
-
-msgid "To ask someone to look at a merge request, select %{strongStart}Request attention%{strongEnd}. Select again to remove the request."
-msgstr ""
+msgstr "如需手動加入æ¢ç›®ï¼Œè«‹åœ¨æ‰‹æ©Ÿæ‡‰ç”¨ä¸­æ供以下訊æ¯ã€‚"
msgid "To complete registration, we need additional details from you."
-msgstr ""
+msgstr "è¦å®Œæˆè¨»å†Šï¼Œæˆ‘們需è¦æ‚¨æ供更多詳細信æ¯ã€‚"
msgid "To confirm, type %{phrase_code}"
-msgstr ""
+msgstr "è¦ç¢ºèªï¼Œè«‹è¼¸å…¥ %{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 "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link} 連接GitHub版本庫。當建立個人存å–令牌時,需è¦é¸æ“‡%{code_open}repo%{code_close}範åœï¼Œä»¥é¡¯ç¤ºå¯ä¾›é€£æŽ¥çš„公開和ç§æœ‰çš„版本庫列表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
-msgstr ""
+msgstr "è¦é€£æŽ¥GitHub版本庫,首先需è¦æŽˆæ¬ŠGitLabå­˜å–您的GitHub版本庫列表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "è¦é€£æŽ¥GitHub版本庫,首先需è¦æŽˆæ¬ŠGitLabå­˜å–列表中的GitHub版本庫:"
msgid "To connect an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "如è¦é€£æŽ¥SVN版本庫,請查看 %{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 "è¦ç¹¼çºŒä½¿ç”¨ GitLab ä¼æ¥­ç‰ˆï¼Œè«‹ä¸Šå‚³ %{codeOpen}.gitlab-license%{codeClose} 文件或輸入您從 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 "è¦ç¹¼çºŒï¼Œæ‚¨éœ€è¦é¸æ“‡æˆ‘們發é€çš„確èªé›»å­éƒµä»¶ä¸­çš„連çµä»¥é©—證您的電å­éƒµä»¶åœ°å€ã€‚如果您沒有收到我們的電å­éƒµä»¶ï¼Œè«‹é¸æ“‡ %{strongStart}é‡æ–°ç™¼é€ç¢ºèªé›»å­éƒµä»¶ã€‚%{strongEnd}"
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "è¦å®šç¾©å…§éƒ¨ä½¿ç”¨è€…,請首先啟用設定為外部的新使用者"
msgid "To enable Registration Features, first enable Service Ping."
-msgstr ""
+msgstr "è¦å•Ÿç”¨è¨»å†ŠåŠŸèƒ½ï¼Œè«‹å…ˆå•Ÿç”¨ Service Ping。"
msgid "To ensure %{project_link} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
-msgstr ""
+msgstr "ç‚ºç¢ºä¿ %{project_link} 未計劃的刪除,請檢查 GitLab 是å¦å·²è¨˜éŒ„活動。例如:"
msgid "To ensure %{project_name} is unscheduled for deletion, check that activity has been logged by GitLab. For example:"
-msgstr ""
+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 ""
+msgstr "為ä¿è­‰å€‹äººå…§å®¹ä¸éºå¤±ï¼Œæœ¬å¸³è™Ÿåƒ…用於與 %{group_name}相關的事項。"
msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
-msgstr ""
+msgstr "è¦åœ¨ä»»ä½•é€™äº›ç‰ˆæœ¬ä¸­æŸ¥æ‰¾æ­¤å°ˆæ¡ˆç‰ˆæœ¬åº«çš„狀態,請檢查 %{link_start}標籤%{link_end}。"
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
-msgstr ""
+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 ""
+msgstr "首先請在下é¢è¼¸å…¥æ‚¨çš„FogBugz URL和登入訊æ¯ã€‚下一步,您將å¯ä»¥æ˜ å°„使用者並é¸æ“‡è¦åŒ¯å…¥çš„專案。"
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 ""
+msgstr "首先,請您輸入您的 Gitea 伺æœå™¨åœ°å€å’Œä¸€å€‹ %{link_to_personal_token}。"
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 ""
+msgstr "為了幫助改進GitLab,我們會定期%{docs_link}。您å¯ä»¥éš¨æ™‚通éŽ%{settings_link}更改設定。"
msgid "To import an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "è¦åŒ¯å…¥SVN版本庫,請查看 %{svn_link}。"
msgid "To keep this project going, create a new issue"
-msgstr ""
+msgstr "為了ä¿æŒé€™å€‹å°ˆæ¡ˆçš„進行,請建立一個新的議題"
msgid "To keep this project going, create a new merge request"
-msgstr ""
+msgstr "為了ä¿æŒé€™å€‹å°ˆæ¡ˆçš„進行,請建立一個新的åˆä½µè«‹æ±‚"
msgid "To learn more about this project, read %{link_to_wiki}"
-msgstr ""
+msgstr "è¦äº†è§£æ›´å¤šé—œæ–¼æ­¤å°ˆæ¡ˆçš„訊æ¯ï¼Œè«‹é–±è®€ %{link_to_wiki}"
-msgid "To manage all members associated with this group and its subgroups and projects, visit the %{link_start}usage quotas page%{link_end}."
-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 "è¦ç®¡ç†èˆ‡è©²ç¾¤çµ„åŠå…¶å­ç¾¤çµ„和專案相關è¯çš„所有æˆå“¡å¸­æ¬¡ï¼Œè«‹è¨ªå•%{link_start}使用é…é¡é é¢%{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 ""
+msgstr "如需將整個GitLab專案從å¦ä¸€å€‹GitLab伺æœå™¨ç§»å‹•æˆ–複製到此伺æœå™¨ï¼Œè«‹å­˜å–原專案的設定é é¢ï¼Œç”¢ç”ŸåŒ¯å‡ºæ–‡ä»¶ï¼Œç„¶å¾Œåœ¨æ­¤è™•ä¸Šè¼‰ã€‚"
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
-msgstr ""
+msgstr "如需外部版本庫僅使用CI/CD功能時,請é¸æ“‡%{strong_open}使用外部版本庫執行CI/CD%{strong_close}。"
msgid "To pass variables to the triggered pipeline, add %{code_start}variables[VARIABLE]=VALUE%{code_end} to the API request."
-msgstr ""
+msgstr "è‹¥è¦å°‡è®Šæ•¸å‚³éžåˆ°å·²è§¸ç™¼çš„æµæ°´ç·šï¼Œè«‹åœ¨ API 請求中加入 %{code_start}variables[VARIABLE]=VALUE%{code_end}。"
msgid "To personalize your GitLab experience, we'd like to know a bit more about you"
-msgstr ""
+msgstr "為了個性化您的GitLab體驗,我們想了解更多關於您的訊æ¯"
msgid "To preserve performance only %{strongStart}%{visible} of %{total}%{strongEnd} files are displayed."
-msgstr ""
+msgstr "為了ä¿æŒæ€§èƒ½ï¼Œåªé¡¯ç¤º %{strongStart}%{visible}/%{total}%{strongEnd} 個文件。"
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
-msgstr ""
+msgstr "為了ä¿è­‰æ€§èƒ½ï¼Œåƒ…顯示文件中的總計%{strong_open}%{real_size}中的%{display_size}%{strong_close}。"
msgid "To protect this issue's confidentiality, %{linkStart}fork this project%{linkEnd} and set the fork's visibility to private."
-msgstr ""
+msgstr "為了ä¿è­·æ­¤è­°é¡Œçš„機密性, %{linkStart}分å‰è©²å°ˆæ¡ˆ%{linkEnd}並將å¯è¦‹æ€§è¨­å®šç‚ºç§æœ‰å°ˆæ¡ˆã€‚"
msgid "To protect this issue's confidentiality, a private fork of this project was selected."
-msgstr ""
+msgstr "為了ä¿è­‰æ­¤è­°é¡Œçš„機密性,é¸æ“‡äº†è©²å°ˆæ¡ˆçš„ç§æœ‰åˆ†å‰ã€‚"
msgid "To reactivate your account, %{gitlab_link_start}sign in to GitLab.%{link_end}"
-msgstr ""
+msgstr "è¦é‡æ–°å•Ÿç”¨æ‚¨çš„帳號, %{gitlab_link_start}登入到 GitLab。%{link_end}"
msgid "To reactivate your account, sign in to GitLab at %{gitlab_url}."
-msgstr ""
+msgstr "è¦é‡æ–°å•Ÿç”¨æ‚¨çš„帳號,請在 %{gitlab_url}登入 GitLab。"
msgid "To resolve this, try to:"
-msgstr ""
+msgstr "è¦è§£æ±ºæ­¤å•é¡Œï¼Œè«‹å˜—試:"
msgid "To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings."
-msgstr ""
+msgstr "è¦ä½¿ç”¨ JetBrains TeamCity 執行 CI/CD æµæ°´ç·šï¼Œè«‹åœ¨ TeamCity 專案版本控制設定中輸入 GitLab 專案詳細訊æ¯ã€‚"
msgid "To see all the user's personal access tokens you must impersonate them first."
-msgstr ""
+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 ""
+msgstr "è¦æŸ¥çœ‹æ­¤å°ˆæ¡ˆçš„æ“作詳情, %{linkStart}將群組方案å‡ç´šåˆ°å°ˆæ¥­ç‰ˆ%{linkEnd}。您也å¯ä»¥å¾žå„€è¡¨æ¿ä¸­ç§»é™¤è©²å°ˆæ¡ˆã€‚"
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 ""
+msgstr "è¦æŸ¥çœ‹è©²å°ˆæ¡ˆçš„維é‹è©³ç´°è¨Šæ¯ï¼Œè«‹èˆ‡%{groupName}群組的所有者è¯çµ¡ä»¥å‡ç´šè¨‚閱計劃。或者您也å¯ä»¥å¾žå„€è¡¨æ¿ä¸Šç§»é™¤æ­¤å°ˆæ¡ˆã€‚"
msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
-msgstr ""
+msgstr "è¦æŸ¥çœ‹æ›´æ”¹çš„內容或建立åˆä½µè«‹æ±‚,請é¸æ“‡åˆ†æ”¯æˆ–標籤(如 %{branch}),或輸入æ交(如 %{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 ""
+msgstr "é€éŽAzure,Okta,Onelogin,Ping Identity或自訂SAML 2.0等身份驗證程å¼ç‚ºæ‚¨çš„群組設定SAML身份驗證:"
msgid "To set up this integration:"
-msgstr ""
+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 ""
+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 "è¦é–‹å§‹ä½¿ç”¨ä¼æ¥­ç‰ˆï¼Œè«‹ä¸Šå‚³ %{codeOpen}.gitlab-license%{codeClose} 文件或輸入您從 GitLab Inc. 收到的授權許å¯é‡‘é‘°"
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
-msgstr ""
+msgstr "è‹¥è¦å–消訂閱此議題,請將以下連çµè²¼ä¸Šåˆ°æ‚¨çš„ç€è¦½å™¨ï¼š"
msgid "To update Snippets with multiple files, you must use the `files` parameter"
-msgstr ""
+msgstr "è¦ä½¿ç”¨å¤šå€‹æ–‡ä»¶æ›´æ–°ç¨‹å¼ç¢¼ç‰‡æ®µï¼Œæ‚¨å¿…須使用 `files` åƒæ•¸"
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
-msgstr ""
+msgstr "è¦ä½¿ç”¨å…¶å®ƒæ ¼å¼ï¼Œæ‚¨å¿…須啟動所需的 %{container_link_start}é…套容器(companion containers)%{container_link_end}。"
msgid "To use the system's default, set this value to 0."
-msgstr ""
+msgstr "è¦ä½¿ç”¨ç³»çµ±é è¨­å€¼ï¼Œè«‹å°‡æ­¤å€¼è¨­å®šç‚º 0。"
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
-msgstr ""
+msgstr "如需查看所有%{scannedResourcesCount}已掃瞄網å€ï¼Œ%{linkStart}請下載CSV文件%{linkEnd}"
msgid "To view usage, refresh this page in a few minutes."
-msgstr ""
+msgstr "è¦æŸ¥çœ‹ä½¿ç”¨æƒ…æ³ï¼Œè«‹åœ¨å¹¾åˆ†é˜å¾Œåˆ·æ–°æ­¤é é¢ã€‚"
msgid "To widen your search, change or remove filters above"
-msgstr ""
+msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–移除上é¢çš„éŽæ¿¾å™¨"
msgid "To widen your search, change or remove filters above."
-msgstr ""
+msgstr "è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹æ›´æ”¹æˆ–移除上é¢çš„éŽæ¿¾å™¨ã€‚"
msgid "To-Do"
-msgstr ""
+msgstr "待辦"
msgid "To-Do List"
-msgstr ""
+msgstr "待辦事項列表"
msgid "To-do item successfully marked as done."
-msgstr ""
+msgstr "待辦事項已æˆåŠŸæ¨™ç¤ºç‚ºå·²å®Œæˆã€‚"
msgid "Today"
-msgstr ""
+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 ""
+msgstr "您正在尋找è¦åšçš„事情嗎? 查看 %{strongStart}%{openIssuesLinkStart}é–‹å•Ÿçš„è­°é¡Œ%{openIssuesLinkEnd}%{strongEnd},貢ç»çµ¦ %{strongStart}%{mergeRequestLinkStart}åˆä½µè«‹æ±‚%{mergeRequestLinkEnd}%{mergeRequestLinkEnd}%{strongEnd},或在留言中æåŠæŸäººï¼Œè‡ªå‹•æŒ‡æ´¾æ–°çš„待辦事項。"
msgid "Todos|Filter by author"
-msgstr ""
+msgstr "ä¾ä½œè€…éŽæ¿¾"
msgid "Todos|Filter by group"
-msgstr ""
+msgstr "ä¾ç¾¤çµ„éŽæ¿¾"
msgid "Todos|Filter by project"
-msgstr ""
+msgstr "ä¾å°ˆæ¡ˆéŽæ¿¾"
msgid "Todos|It's how you always know what to work on next."
-msgstr ""
+msgstr "這是您總是知é“下一步è¦åšä»€éº¼çš„æ–¹å¼ã€‚"
msgid "Todos|Mark all as done"
-msgstr ""
+msgstr "標示為全部完æˆ"
msgid "Todos|Nothing is on your to-do list. Nice work!"
-msgstr ""
+msgstr "您的待辦事項列表中沒有任何事項。"
msgid "Todos|Undo mark all as done"
-msgstr ""
+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 ""
+msgstr "當一個議題或åˆä½µè«‹æ±‚指派給您,或者當您收到留言中的 %{strongStart}@mention%{strongEnd} 時,會自動觸發您待辦事項列表中的一個新事項。"
msgid "Todos|You're all done!"
-msgstr ""
+msgstr "已經全部完æˆäº†ï¼"
msgid "Todos|Your To-Do List shows what to work on next"
-msgstr ""
+msgstr "您的待辦事項列表顯示下一步è¦åšä»€éº¼"
msgid "Toggle GitLab Next"
-msgstr ""
+msgstr "切æ›GitLabé è¦½ç‰ˆ"
msgid "Toggle Markdown preview"
-msgstr ""
+msgstr "切æ›Markdowné è¦½"
msgid "Toggle Sidebar"
-msgstr ""
+msgstr "切æ›å´é‚Šæ¬„"
msgid "Toggle backtrace"
-msgstr ""
+msgstr "切æ›å‘¼å«å †ç–Šå›žæº¯(backtrace)"
msgid "Toggle collapse"
-msgstr ""
+msgstr "切æ›æ‘ºç–Š"
msgid "Toggle comments for this file"
-msgstr ""
+msgstr "切æ›æ­¤æ–‡ä»¶çš„留言"
msgid "Toggle commit description"
-msgstr ""
+msgstr "é–‹é—œæ交æè¿°"
msgid "Toggle commit list"
-msgstr ""
+msgstr "é–‹é—œæ交列表"
msgid "Toggle dropdown"
-msgstr ""
+msgstr "切æ›ä¸‹æ‹‰åˆ—表"
msgid "Toggle emoji award"
-msgstr ""
+msgstr "切æ›è¡¨æƒ…符號讚賞"
msgid "Toggle focus mode"
-msgstr ""
+msgstr "切æ›å°ˆæ³¨æ¨¡å¼"
msgid "Toggle keyboard shortcuts help dialog"
-msgstr ""
+msgstr "切æ›éµç›¤å¿«æ·éµå¹«åŠ©å°è©±æ¡†"
msgid "Toggle navigation"
-msgstr ""
+msgstr "切æ›å°Žè¦½"
msgid "Toggle project select"
-msgstr ""
+msgstr "切æ›å°ˆæ¡ˆé¸æ“‡"
msgid "Toggle shortcuts"
-msgstr ""
+msgstr "切æ›å¿«æ·éµ"
msgid "Toggle sidebar"
-msgstr ""
+msgstr "切æ›å´é‚Šæ¬„"
msgid "Toggle the Draft status"
-msgstr ""
+msgstr "切æ›è‰ç¨¿ç‹€æ…‹"
msgid "Toggle the Performance Bar"
-msgstr ""
+msgstr "切æ›æ•ˆèƒ½æ¬„"
msgid "Toggled :%{name}: emoji award."
-msgstr ""
+msgstr "åˆ‡æ› :%{name}: 表情符號讚賞。"
msgid "Toggles :%{name}: emoji award."
-msgstr ""
+msgstr "åˆ‡æ› :%{name}: 表情符號讚賞。"
msgid "Token"
-msgstr ""
+msgstr "令牌(權æ–)"
msgid "Token Access"
-msgstr ""
+msgstr "å­˜å–令牌(權æ–)"
msgid "Token name"
-msgstr ""
+msgstr "令牌å稱"
msgid "Token valid until revoked"
-msgstr ""
+msgstr "令牌在撤銷å‰æœ‰æ•ˆ"
msgid "Tokens|Scopes set the permission levels granted to the token."
-msgstr ""
+msgstr "設定授予令牌的權é™ç´šåˆ¥ç¯„åœã€‚"
msgid "Tokens|Select scopes"
-msgstr ""
+msgstr "é¸æ“‡ç¯„åœ"
msgid "Tomorrow"
-msgstr ""
+msgstr "明日"
msgid "Too many changes to show."
-msgstr ""
+msgstr "è¦é¡¯ç¤ºçš„變更太多。"
msgid "Too many namespaces enabled. Manage them through the console or the API."
-msgstr ""
+msgstr "啟用了太多的命å空間,通éŽæŽ§åˆ¶å°æˆ–API管ç†å®ƒå€‘。"
msgid "Too many projects enabled. Manage them through the console or the API."
-msgstr ""
+msgstr "啟用了太多的專案,通éŽæŽ§åˆ¶å°æˆ– API 管ç†å®ƒå€‘。"
msgid "Too many references. Quick actions are limited to at most %{max_count} user references"
-msgstr ""
+msgstr "åƒè€ƒè³‡æ–™å¤ªå¤šã€‚快速æ“作僅é™æ–¼æœ€å¤š %{max_count} 個使用者引用"
msgid "Too many users found. Quick actions are limited to at most %{max_count} users"
-msgstr ""
+msgstr "發ç¾å¤ªå¤šä½¿ç”¨è€…。快速æ“作僅é™æ–¼æœ€å¤š %{max_count} 個使用者"
msgid "TopNav|Go back"
-msgstr ""
+msgstr "返回"
+
+msgid "Topic %{source_topic} was successfully merged into topic %{target_topic}."
+msgstr "主題 %{source_topic} å·²æˆåŠŸåˆä½µè‡³ä¸»é¡Œ %{target_topic}。"
msgid "Topic %{topic_name} was successfully created."
-msgstr ""
+msgstr "主題 %{topic_name} å·²æˆåŠŸå»ºç«‹ã€‚"
msgid "Topic %{topic_name} was successfully removed."
-msgstr ""
+msgstr "主題 %{topic_name} å·²æˆåŠŸç§»é™¤ã€‚"
msgid "Topic avatar"
-msgstr ""
+msgstr "主題頭åƒ"
msgid "Topic avatar for %{name} will be removed. This cannot be undone."
-msgstr ""
+msgstr "%{name} 的主題頭åƒå°‡è¢«ç§»é™¤ã€‚æ­¤æ“作無法撤消。"
msgid "Topic slug (name)"
-msgstr ""
+msgstr "主題固定éˆçµ(slug)"
msgid "Topic title"
-msgstr ""
+msgstr "主題標題"
msgid "Topic was successfully updated."
-msgstr ""
+msgstr "主題已æˆåŠŸæ›´æ–°ã€‚"
msgid "Topics"
-msgstr ""
+msgstr "主題"
msgid "Total"
-msgstr ""
+msgstr "全部"
msgid "Total Contributions"
-msgstr ""
+msgstr "è²¢ç»ç¸½è¨ˆ"
msgid "Total Score"
-msgstr ""
+msgstr "總分"
msgid "Total artifacts size: %{total_size}"
-msgstr ""
+msgstr "所有產物大å°ï¼š %{total_size}"
msgid "Total cores (CPUs)"
-msgstr ""
+msgstr "總核心數目 (CPUs)"
msgid "Total memory (GB)"
-msgstr ""
+msgstr "總記憶體 (GB)"
msgid "Total test time for all commits/merges"
-msgstr ""
+msgstr "所有æ交/åˆä½µçš„總測試時間"
msgid "Total users"
-msgstr ""
+msgstr "使用者總數"
msgid "Total weight"
-msgstr ""
+msgstr "總權é‡"
msgid "Total: %{total}"
-msgstr ""
+msgstr "總計:%{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 ""
+msgstr "在ä¸åŒå°ˆæ¡ˆå’Œé‡Œç¨‹ç¢‘中追蹤具有åŒä¸€ä¸»é¡Œçš„議題組"
msgid "Track important events in your GitLab instance."
-msgstr ""
+msgstr "追蹤您的 GitLab 實例中的é‡è¦äº‹ä»¶ã€‚"
msgid "Track important events in your group."
-msgstr ""
+msgstr "追蹤您的群組中的é‡è¦äº‹ä»¶ã€‚"
msgid "Track important events in your project."
-msgstr ""
+msgstr "追蹤您的專案中的é‡è¦äº‹ä»¶ã€‚"
msgid "Track time with quick actions"
-msgstr ""
+msgstr "使用快æ·æ“作來追蹤時間"
msgid "Training mode"
-msgstr ""
+msgstr "訓練模å¼"
msgid "Transfer"
-msgstr ""
+msgstr "轉移"
msgid "Transfer group to another parent group."
-msgstr ""
+msgstr "將群組轉移到å¦ä¸€å€‹çˆ¶ç¾¤çµ„。"
msgid "Transfer ownership"
-msgstr ""
+msgstr "轉移所有權"
msgid "Transfer project"
-msgstr ""
+msgstr "轉移專案"
msgid "Transfer your project into another namespace. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "將您的專案轉移到å¦ä¸€å€‹å‘½å空間。 %{link_start}了解更多。%{link_end}"
msgid "TransferGroup|Cannot transfer group to one of its subgroup."
-msgstr ""
+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 ""
+msgstr "無法更新路徑。因為此群組下的專案包å«äº†å®¹å™¨æ˜ åƒåº«çš„Docker映åƒã€‚請先從您的專案中移除映åƒå¾Œé‡è©¦ã€‚"
msgid "TransferGroup|Database is not supported."
-msgstr ""
+msgstr "ä¸æ”¯æ´çš„資料庫。"
msgid "TransferGroup|Group contains contacts/organizations and you don't have enough permissions to move them to the new root group."
-msgstr ""
+msgstr "群組包å«è¯çµ¡äºº/組織,您沒有足夠的權é™å°‡å®ƒå€‘移動到新的根群組。"
msgid "TransferGroup|Group contains projects with NPM packages."
-msgstr ""
+msgstr "群組包å«å¸¶æœ‰NPM軟體套件的專案。"
msgid "TransferGroup|Group is already a root group."
-msgstr ""
+msgstr "群組已經是一個根群組。"
msgid "TransferGroup|Group is already associated to the parent group."
-msgstr ""
+msgstr "群組已與父群組關è¯ã€‚"
msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
-msgstr ""
+msgstr "父群組已經有一個具有相åŒè·¯å¾‘çš„å­ç¾¤çµ„或專案。"
msgid "TransferGroup|Transfer failed: %{error_message}"
-msgstr ""
+msgstr "轉移失敗: %{error_message}"
msgid "TransferGroup|You don't have enough permissions."
-msgstr ""
+msgstr "您沒有足夠的權é™ã€‚"
msgid "TransferProject|Cannot move project"
-msgstr ""
+msgstr "無法移動專案"
msgid "TransferProject|Please select a new namespace for your project."
-msgstr ""
+msgstr "請為專案é¸æ“‡æ–°å‘½å空間。"
msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
-msgstr ""
+msgstr "項目無法轉移,因為標籤存在於其容器映åƒåº«ä¸­"
msgid "TransferProject|Project is already in this namespace."
-msgstr ""
+msgstr "專案已經存在該命å空間中。"
msgid "TransferProject|Project with same name or path in target namespace already exists"
-msgstr ""
+msgstr "目標命å空間中已存在具有相åŒå稱或路徑的專案"
msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
-msgstr ""
+msgstr "如果專案具有NPM軟體套件,則無法更新根命å空間"
msgid "TransferProject|You don't have permission to transfer projects into that namespace."
-msgstr ""
+msgstr "您沒有權é™å°‡å°ˆæ¡ˆå‚³è¼¸åˆ°è©²å‘½å空間中。"
msgid "TransferProject|You don't have permission to transfer this project."
-msgstr ""
+msgstr "您沒有權é™å‚³è¼¸æ­¤å°ˆæ¡ˆã€‚"
msgid "Tree view"
-msgstr ""
+msgstr "樹狀圖"
msgid "Trending"
-msgstr ""
+msgstr "趨勢"
msgid "Trials|%{planName} Trial"
-msgstr ""
+msgstr "%{planName} 試用"
msgid "Trials|Compare all plans"
-msgstr ""
+msgstr "比較所有方案"
msgid "Trials|Create a new group to start your GitLab Ultimate trial."
-msgstr ""
+msgstr "建立一個新群組以開始您的旗艦版試用。"
msgid "Trials|Day %{daysUsed}/%{duration}"
-msgstr ""
+msgstr "第 %{daysUsed}/%{duration} 天"
msgid "Trials|Go back to GitLab"
-msgstr ""
+msgstr "返回GitLab"
msgid "Trials|Hey there"
-msgstr ""
+msgstr "您好ï¼"
msgid "Trials|Skip Trial"
-msgstr ""
+msgstr "è·³éŽè©¦ç”¨"
msgid "Trials|Upgrade %{groupName} to %{planName}"
-msgstr ""
+msgstr "å‡ç´š %{groupName} 到 %{planName}"
msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start an Ultimate trial'"
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽé¸æ“‡æ‚¨çš„é ­åƒä¸¦é¸æ“‡ã€Œé–‹å§‹è©¦ç”¨æ——艦版ã€ä¾†æ¢å¾©æ­¤ç¨‹åºã€‚"
msgid "Trials|You can apply your trial to a new group or an existing group."
-msgstr ""
+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 ""
+msgstr "您ç¾åœ¨ç„¡æ³•ç²å¾—å…費試用,但您å¯ä»¥éš¨æ™‚通éŽé¸æ“‡æ‚¨çš„é ­åƒä¸¦é¸æ“‡ã€Œé–‹å§‹æ——艦版試用ã€ä¾†æ¢å¾©æ­¤ç¨‹åºã€‚"
msgid "Trials|Your trial ends on %{boldStart}%{trialEndDate}%{boldEnd}. We hope you’re enjoying the features of GitLab %{planName}. To keep those features after your trial ends, you’ll need to buy a subscription. (You can also choose GitLab Premium if it meets your needs.)"
-msgstr ""
+msgstr "您的試用版在 %{boldStart}%{trialEndDate}%{boldEnd}çµæŸï¼Œæˆ‘們希望您能享å—GitLab %{planName}的功能,為了在試用çµæŸå¾Œä¿ç•™é€™äº›åŠŸèƒ½ï¼Œæ‚¨éœ€è¦è³¼è²·è¨‚閱。(如果您滿足您的需è¦ï¼Œæ‚¨ä¹Ÿå¯ä»¥é¸æ“‡å°ˆæ¥­ç‰ˆã€‚)"
msgid "Trial|Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "å…許的字元:+ã€0-9ã€- 和空格。"
msgid "Trial|Company name"
-msgstr ""
+msgstr "å…¬å¸å稱"
msgid "Trial|Continue"
-msgstr ""
+msgstr "繼續"
msgid "Trial|Continue using the basic features of GitLab for free."
-msgstr ""
+msgstr "繼續å…費使用基本功能。"
msgid "Trial|Country"
-msgstr ""
+msgstr "國家"
msgid "Trial|Dismiss"
-msgstr ""
+msgstr "撤回"
msgid "Trial|GitLab Ultimate trial (optional)"
-msgstr ""
+msgstr "GitLab Ultimate 試用版(å¯é¸ï¼‰"
msgid "Trial|Number of employees"
-msgstr ""
+msgstr "員工人數"
msgid "Trial|Please select a country"
-msgstr ""
+msgstr "è«‹é¸æ“‡åœ‹å®¶"
msgid "Trial|Telephone number"
-msgstr ""
+msgstr "電話號碼"
msgid "Trial|Upgrade to Ultimate to keep using GitLab with advanced features."
-msgstr ""
+msgstr "å‡ç´šç‚ºæ——艦版以ä¿æŒä½¿ç”¨ GitLab 進階功能。"
msgid "Trial|We will activate your trial on your group after you complete this step. After 30 days, you can:"
-msgstr ""
+msgstr "在您完æˆæ­¤æ­¥é©Ÿå¾Œï¼Œæˆ‘們將在您的群組中啟用您的試用。 30 天後,您å¯ä»¥ï¼š"
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 "您的 GitLab Ultimate 試用期為 30 天,但您å¯ä»¥æ°¸ä¹…ä¿ç•™å…費的 GitLab 帳號。我們åªéœ€è¦ä¸€äº›é¡å¤–的訊æ¯ä¾†å•Ÿç”¨æ‚¨çš„試用版。"
msgid "Trigger"
-msgstr ""
+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 "通éŽç”¢ç”Ÿè§¸ç™¼ä»¤ç‰Œä¸¦å°‡å…¶èˆ‡ API 調用一起使用,為分支或標籤觸發æµæ°´ç·šã€‚令牌模擬使用者的專案存å–和權é™ã€‚"
msgid "Trigger cluster reindexing"
-msgstr ""
+msgstr "觸發å¢é›†é‡å»ºç´¢å¼•"
msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
-msgstr ""
+msgstr "觸發å¢é›†é‡å»ºç´¢å¼•ã€‚僅使用 13.0 或更高版本建立的索引。"
msgid "Trigger job"
-msgstr ""
+msgstr "觸發作業"
msgid "Trigger manual job"
-msgstr ""
+msgstr "觸發手動作業"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+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 ""
+msgstr "在上游版本庫中更新分支或標籤時觸發æµæ°´ç·šã€‚根據上游版本庫的活動,這å¯èƒ½æœƒå¤§å¤§å¢žåŠ  CI 執行器的負載。 僅當您知é“他們å¯ä»¥è™•ç†è² è¼‰æ™‚æ‰å•Ÿç”¨æ­¤åŠŸèƒ½ã€‚ %{strong_start}CI 將使用上é¢æŒ‡æ´¾çš„憑證é‹è¡Œã€‚%{strong_end} %{link_start}了解更多信æ¯ã€‚%{link_end}"
msgid "Trigger removed."
-msgstr ""
+msgstr "已移除觸發。"
msgid "Trigger repository check"
-msgstr ""
+msgstr "觸發版本庫檢查"
msgid "Trigger this manual action"
-msgstr ""
+msgstr "觸發此手動æ“作"
msgid "Trigger token:"
-msgstr ""
+msgstr "觸發令牌(權æ–):"
msgid "Trigger variables:"
-msgstr ""
+msgstr "觸發變數:"
msgid "Trigger was created successfully."
-msgstr ""
+msgstr "觸發器已æˆåŠŸå»ºç«‹ã€‚"
msgid "Trigger was successfully updated."
-msgstr ""
+msgstr "觸發器已æˆåŠŸæ›´æ–°ã€‚"
msgid "Triggerer"
-msgstr ""
+msgstr "觸發者"
msgid "Trigger|Trigger user has insufficient permissions to project"
-msgstr ""
+msgstr "觸發使用者沒有足夠的專案權é™"
msgid "Trigger|invalid"
-msgstr ""
+msgstr "無效"
msgid "Trusted"
-msgstr ""
+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 ""
+msgstr "å—信任的應用程å¼åœ¨ GitLab OAuth æµç¨‹ä¸Šè‡ªå‹•å–得授權。 為了使用者的安全,強烈建議å—信任的應用程å¼å°‡æ©Ÿå¯†è¨­å®šè¨­ç‚º true。"
msgid "Try again"
-msgstr ""
+msgstr "è«‹é‡è©¦"
msgid "Try again?"
-msgstr ""
+msgstr "é‡è©¦ï¼Ÿ"
msgid "Try all GitLab features for free for 30 days. No credit card required."
-msgstr ""
+msgstr "å…費試用 GitLab 的所有功能 30 天。無需信用å¡ã€‚"
msgid "Try all GitLab has to offer for 30 days."
-msgstr ""
+msgstr "30天內體驗GitLab的所有功能。"
msgid "Try changing or removing filters."
-msgstr ""
+msgstr "請嘗試更改或移除éŽæ¿¾å™¨ã€‚"
msgid "Try grouping with different labels"
-msgstr ""
+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 ""
+msgstr "試用 GitLab æµæ°´ç·š"
msgid "Try the troubleshooting steps here."
-msgstr ""
+msgstr "嘗試此處的故障排除步驟。"
msgid "Try to fork again"
-msgstr ""
+msgstr "嘗試å†æ¬¡åˆ†å‰"
msgid "Try to keep the first line under 52 characters and the others under 72."
-msgstr ""
+msgstr "請將第一行ä¿æŒåœ¨52個字元以內,其他行ä¿æŒåœ¨72個字元以內。"
msgid "Try using a different search term to find the file you are looking for."
-msgstr ""
+msgstr "嘗試使用ä¸åŒçš„æœå°‹è©žå°‹æ‰¾ä½ æƒ³è¦çš„文件。"
msgid "Trying to communicate with your device. Plug it in (if needed) and press the button on the device now."
-msgstr ""
+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 ""
+msgstr "嘗試與您的設備通信。請將其æ’入並立å³æŒ‰ä¸‹è¨­å‚™ä¸Šçš„按鈕。"
msgid "Tuesday"
-msgstr ""
+msgstr "星期二"
msgid "Turn off"
-msgstr ""
+msgstr "關閉"
msgid "Turn off notifications"
-msgstr ""
+msgstr "關閉通知"
msgid "Turn on"
-msgstr ""
+msgstr "é–‹å•Ÿ"
msgid "Turn on notifications"
-msgstr ""
+msgstr "開啟通知"
msgid "Twitter"
-msgstr ""
+msgstr "Twitter"
msgid "Twitter:"
-msgstr ""
+msgstr "Twitter:"
msgid "Two-Factor Authentication"
-msgstr ""
+msgstr "雙因å­èªè­‰"
msgid "Two-Factor Authentication code"
-msgstr ""
+msgstr "雙因å­èªè­‰é©—證碼"
msgid "Two-factor Authentication"
-msgstr ""
+msgstr "雙因å­èªè­‰"
msgid "Two-factor Authentication Recovery codes"
-msgstr ""
+msgstr "雙因å­èªè­‰æ¢å¾©ç¢¼"
msgid "Two-factor Authentication:"
-msgstr ""
+msgstr "雙因å­èªè­‰ï¼š"
msgid "Two-factor authentication"
-msgstr ""
+msgstr "雙因å­èªè­‰"
msgid "Two-factor authentication disabled"
-msgstr ""
+msgstr "雙因å­èªè­‰å·²åœç”¨"
msgid "Two-factor authentication grace period"
-msgstr ""
+msgstr "雙因å­é©—證寬é™æœŸ"
msgid "Two-factor authentication has been disabled for this user"
-msgstr ""
+msgstr "此使用者已åœç”¨é›™å› å­èªè­‰"
msgid "Two-factor authentication has been disabled for your GitLab account."
-msgstr ""
+msgstr "您的帳號已ç¦ç”¨é›™å› å­èªè­‰"
msgid "Two-factor authentication has been disabled successfully!"
-msgstr ""
+msgstr "雙因å­èªè­‰å·²è¢«æˆåŠŸåœç”¨ï¼"
msgid "Two-factor authentication is not enabled for this user"
-msgstr ""
+msgstr "此使用者未啟用雙因å­èªè­‰"
msgid "Two-factor grace period"
-msgstr ""
+msgstr "雙因å­å¯¬é™æœŸ"
msgid "Type"
-msgstr ""
+msgstr "é¡žåž‹"
+
+msgid "Type to search"
+msgstr "輸入查詢"
msgid "U2F Devices (%{length})"
-msgstr ""
+msgstr "U2F設備(%{length})"
msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
-msgstr ""
+msgstr "U2Fåªæ”¯æ´åœ¨HTTPS的網站。請è¯çµ¡ç®¡ç†å“¡ç²å¾—更多訊æ¯"
msgid "URL"
msgstr "URL"
msgid "URL cannot be blank"
-msgstr ""
+msgstr "URLä¸èƒ½ç‚ºç©º"
msgid "URL is invalid"
-msgstr ""
+msgstr "URL無效"
msgid "URL is required"
-msgstr ""
+msgstr "URL為必需"
msgid "URL is triggered for each branch updated to the repository"
-msgstr ""
+msgstr "為æ¯å€‹æ›´æ–°åˆ°ç‰ˆæœ¬åº«çš„分支觸發 URL"
msgid "URL is triggered when a merge request is created, updated, or merged"
-msgstr ""
+msgstr "建立ã€æ›´æ–°æˆ–åˆä½µåˆä½µè«‹æ±‚時觸發 URL"
msgid "URL is triggered when a new tag is pushed to the repository"
-msgstr ""
+msgstr "將新標籤推é€åˆ°ç‰ˆæœ¬åº«æ™‚會觸發 URL"
msgid "URL is triggered when repository is updated"
-msgstr ""
+msgstr "更新版本庫時觸發 URL"
msgid "URL must be percent-encoded if necessary."
-msgstr ""
+msgstr "如有必è¦ï¼ŒURL 必須經éŽç™¾åˆ†æ¯”編碼。"
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
-msgstr ""
+msgstr "URL必須以%{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}或%{codeStart}ftp://%{codeEnd}開始"
msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
-msgstr ""
+msgstr "è¦å¾žæŒ‡æ¨™å„€è¡¨æ¿é¸å–®é€£çµåˆ° Grafana 實例的 URL。"
msgid "URL of the external Spam Check endpoint"
-msgstr ""
+msgstr "外部垃圾訊æ¯æª¢æŸ¥ç«¯é»žURL"
msgid "URL of the external storage to serve the repository static objects."
-msgstr ""
+msgstr "用於為版本庫éœæ…‹ç‰©ä»¶æä¾›æœå‹™çš„外部儲存的 URL。"
msgid "URL or request ID"
-msgstr ""
+msgstr "URL或請求ID"
msgid "USER %{user_name} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "使用者 %{user_name} 將被刪除ï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
msgid "USER %{user} WILL BE REMOVED! Are you sure?"
-msgstr ""
+msgstr "使用者 %{user} 將被刪除ï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
msgid "USER WILL BE BLOCKED! Are you sure?"
-msgstr ""
+msgstr "使用者將被ç¦ç”¨ï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
msgid "UTC"
-msgstr ""
+msgstr "國際標準時間"
msgid "Unable to apply suggestions to a deleted line."
-msgstr ""
+msgstr "無法將建議應用於已刪除的行。"
msgid "Unable to build Slack link."
-msgstr ""
+msgstr "無法建立Slack連çµã€‚"
msgid "Unable to collect CPU info"
-msgstr ""
+msgstr "無法收集CPU訊æ¯"
msgid "Unable to collect memory info"
-msgstr ""
+msgstr "無法收集記憶體訊æ¯"
msgid "Unable to connect to Prometheus server"
-msgstr ""
+msgstr "無法連接到Prometheus伺æœå™¨"
msgid "Unable to connect to server: %{error}"
-msgstr ""
+msgstr "無法連線到伺æœå™¨: %{error}"
msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
-msgstr ""
+msgstr "無法連線到Jira伺æœå™¨ã€‚請檢查您的Jiraæ•´åˆè¨­å®šã€‚"
msgid "Unable to create link to vulnerability"
-msgstr ""
+msgstr "無法建立到æ¼æ´žçš„連çµ"
msgid "Unable to fetch branch list for this project."
-msgstr ""
+msgstr "無法å–得此專案的分支列表。"
msgid "Unable to fetch branches list, please close the form and try again"
-msgstr ""
+msgstr "無法å–得分支列表,請關閉表單並é‡è©¦"
msgid "Unable to fetch upstream and downstream pipelines."
-msgstr ""
+msgstr "無法å–得上游和下游æµæ°´ç·šã€‚"
msgid "Unable to find Jira project to import data from."
-msgstr ""
+msgstr "無法找到è¦åŒ¯å…¥è³‡æ–™çš„Jira專案。"
msgid "Unable to fully load the default commit message. You can still apply this suggestion and the commit message will be correct."
-msgstr ""
+msgstr "無法完全載入é è¨­æ交訊æ¯ã€‚ 您ä»ç„¶å¯ä»¥å¥—用此建議,並且æ交訊æ¯å°‡æ˜¯æ­£ç¢ºçš„。"
msgid "Unable to generate new instance ID"
-msgstr ""
+msgstr "無法生æˆæ–°çš„實體 ID"
msgid "Unable to load commits. Try again later."
-msgstr ""
+msgstr "無法載入æ交。請ç¨å¾Œå†è©¦ã€‚"
msgid "Unable to load file contents. Try again later."
-msgstr ""
+msgstr "無法載入文件內容。ç¨å¾Œå†è©¦ã€‚"
msgid "Unable to load refs"
-msgstr ""
+msgstr "無法載入 refs"
msgid "Unable to load the diff"
-msgstr ""
+msgstr "無法載入差異"
msgid "Unable to load the diff. %{button_try_again}"
-msgstr ""
+msgstr "無法載入差異。%{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
-msgstr ""
+msgstr "無法載入åˆä½µè«‹æ±‚部件。請嘗試é‡æ–°è¼‰å…¥é é¢ã€‚"
+
+msgid "Unable to parse JSON"
+msgstr "ç„¡æ³•è§£æž JSON"
msgid "Unable to parse the vulnerability report's options."
-msgstr ""
+msgstr "無法解æžæ¼æ´žå ±å‘Šçš„é¸é …。"
msgid "Unable to save iteration. Please try again"
-msgstr ""
+msgstr "無法ä¿å­˜è¿­ä»£ã€‚è«‹é‡è©¦"
msgid "Unable to save your changes. Please try again."
-msgstr ""
+msgstr "無法儲存您的變更。請é‡è©¦ã€‚"
msgid "Unable to save your preference"
-msgstr ""
+msgstr "無法ä¿å­˜æ‚¨çš„å好設定"
msgid "Unable to schedule a pipeline to run immediately"
-msgstr ""
+msgstr "無法安排立å³åŸ·è¡Œæµæ°´ç·š"
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
-msgstr ""
+msgstr "由於\"%{reason}\"的原因,您暫時ä¸èƒ½é€²å…¥è¨­å®šäº†SAML 的群組"
msgid "Unable to suggest a path. Please refresh and try again."
-msgstr ""
+msgstr "無法建議路徑。請é‡æ–°æ•´ç†ä¸¦é‡è©¦ã€‚"
msgid "Unable to update label prioritization at this time"
-msgstr ""
+msgstr "ç›®å‰ç„¡æ³•æ›´æ–°æ¨™è¨˜å„ªå…ˆåº¦"
msgid "Unable to update this epic at this time."
-msgstr ""
+msgstr "ç›®å‰ç„¡æ³•æ›´æ–°è©²å²è©©ã€‚"
msgid "Unable to update this issue at this time."
-msgstr ""
+msgstr "ç›®å‰ç„¡æ³•æ›´æ–°è©²è­°é¡Œã€‚"
msgid "Unable to verify the user"
-msgstr ""
+msgstr "無法驗證使用者"
msgid "Unapprove a merge request"
-msgstr ""
+msgstr "å–消核准åˆä½µè«‹æ±‚"
msgid "Unapprove the current merge request."
-msgstr ""
+msgstr "å–消核准當å‰åˆä½µè«‹æ±‚。"
msgid "Unapproved the current merge request."
-msgstr ""
+msgstr "å·²å–消核准當å‰åˆä½µè«‹æ±‚。"
msgid "Unarchive project"
-msgstr ""
+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 "解除歸檔專案將æ¢å¾©å…¶æˆå“¡èƒ½å¤ å°å…¶é€²è¡Œæ›´æ”¹ï¼Œå¯ä»¥æ交版本庫,並且å¯ä»¥å»ºç«‹è­°é¡Œã€ç•™è¨€å’Œå…¶ä»–實體。 %{strong_start}一旦解除,該專案就會顯示在æœå°‹å’Œå„€è¡¨æ¿ä¸Šã€‚%{strong_end} %{link_start}了解更多。%{link_end}"
msgid "Unassign from commenting user"
-msgstr ""
+msgstr "從留言使用者解除指派"
msgid "Unassigned"
-msgstr ""
+msgstr "未指派"
msgid "Unauthenticated API rate limit period in seconds"
-msgstr ""
+msgstr "未經身份驗證的 API 速率é™åˆ¶æ™‚間(以秒為單ä½ï¼‰"
msgid "Unauthenticated requests"
-msgstr ""
+msgstr "未èªè­‰çš„請求"
msgid "Unauthenticated web rate limit period in seconds"
-msgstr ""
+msgstr "未經身份驗證的 Web 速率é™åˆ¶æ™‚間(以秒為單ä½ï¼‰"
+
+msgid "Unban"
+msgstr "解除å°éŽ–"
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
-msgstr ""
+msgstr "如果您更改分支,未æ交的更改將éºå¤±ã€‚您想è¦ç¹¼çºŒå—Žï¼Ÿ"
msgid "Undo"
-msgstr ""
+msgstr "復原"
msgid "Undo Ignore"
-msgstr ""
+msgstr "復原忽略"
msgid "Undo ignore"
-msgstr ""
+msgstr "復原忽略"
msgid "Unexpected error"
-msgstr ""
+msgstr "未é æœŸçš„錯誤"
msgid "Unfollow"
-msgstr ""
+msgstr "å–消關注"
msgid "Unfortunately, your email message to GitLab could not be processed."
-msgstr ""
+msgstr "很éºæ†¾ï¼Œæ‚¨ç™¼é€çµ¦GitLabçš„é›»å­éƒµä»¶ç„¡æ³•è™•ç†ã€‚"
msgid "Unhappy?"
-msgstr ""
+msgstr "ä¸æ»¿æ„?"
msgid "Units|ms"
-msgstr ""
+msgstr "毫秒"
msgid "Units|s"
-msgstr ""
+msgstr "秒"
msgid "Unknown"
-msgstr ""
+msgstr "未知的"
msgid "Unknown Error"
-msgstr ""
+msgstr "未知錯誤"
msgid "Unknown encryption strategy: %{encrypted_strategy}!"
-msgstr ""
+msgstr "未知的加密策略: %{encrypted_strategy}!"
msgid "Unknown format"
-msgstr ""
+msgstr "未知的格å¼"
msgid "Unknown response text"
-msgstr ""
-
-msgid "Unknown screen"
-msgstr ""
+msgstr "未知的回應文字"
msgid "Unknown user"
-msgstr ""
+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 ""
+msgstr "除éžèˆ‡GitLabå¦æœ‰æ›¸é¢å”議,å¦å‰‡é»žæ“Šã€Œä¸Šå‚³è¨±å¯ã€å³è¡¨ç¤ºæ‚¨åŒæ„使用GitLab軟體應éµå®ˆ %{eula_link_start}æœå‹™æ¢æ¬¾%{eula_link_end}。"
msgid "Unlimited"
-msgstr ""
+msgstr "ç„¡é™"
msgid "Unlink"
-msgstr ""
+msgstr "å–消關è¯"
msgid "Unlock"
-msgstr ""
+msgstr "解鎖"
msgid "Unlock account"
-msgstr ""
+msgstr "解鎖帳號"
msgid "Unlock merge request"
-msgstr ""
+msgstr "解鎖åˆä½µè«‹æ±‚"
msgid "Unlock more features with GitLab Ultimate"
-msgstr ""
+msgstr "使用旗艦版解鎖更多功能"
msgid "Unlock the discussion"
-msgstr ""
+msgstr "解鎖的討論"
msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
-msgstr ""
+msgstr "解鎖此%{issuableDisplayName}嗎?%{strongStart}所有人%{strongEnd}都將å¯ä»¥ç™¼è¡¨ç•™è¨€ã€‚"
msgid "Unlocked"
-msgstr ""
+msgstr "未鎖定"
msgid "Unlocked the discussion."
-msgstr ""
+msgstr "解鎖討論。"
msgid "Unlocks the discussion."
-msgstr ""
+msgstr "解鎖討論。"
msgid "Unreachable"
-msgstr ""
+msgstr "無法存å–"
msgid "Unrecognized approval status."
-msgstr ""
+msgstr "未識別的核准狀態。"
msgid "Unrecognized cluster type"
-msgstr ""
+msgstr "無法識別的å¢é›†é¡žåž‹"
msgid "Unresolve"
-msgstr ""
+msgstr "未解決"
msgid "Unresolve thread"
-msgstr ""
+msgstr "將主題設為未解決"
msgid "Unresolved"
-msgstr ""
+msgstr "未解決的"
msgid "Unschedule job"
-msgstr ""
+msgstr "å–消作業排程"
msgid "Unstar"
-msgstr ""
+msgstr "å–消收è—(星號)"
msgid "Unstarted"
-msgstr ""
+msgstr "未啟動"
msgid "Unsubscribe"
-msgstr ""
+msgstr "å–消訂閱"
msgid "Unsubscribe at group level"
-msgstr ""
+msgstr "在群組級別å–消訂閱"
msgid "Unsubscribe at project level"
-msgstr ""
+msgstr "在專案級別å–消訂閱"
msgid "Unsubscribe from %{type}"
-msgstr ""
+msgstr "å–消訂閱 %{type}"
msgid "Unsubscribed from this %{quick_action_target}."
-msgstr ""
+msgstr "å–消訂閱%{quick_action_target}."
msgid "Unsubscribes from this %{quick_action_target}."
-msgstr ""
+msgstr "å–消訂閱%{quick_action_target}."
msgid "Unsupported sort value."
-msgstr ""
+msgstr "ä¸æ”¯æ´çš„排åºå€¼ã€‚"
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
-msgstr ""
+msgstr "傳入了ä¸æ”¯æ´çš„待辦事項類型。支æ´çš„待辦事項類型為: %{todo_types}"
msgid "Unused"
-msgstr ""
+msgstr "未使用"
msgid "Unused, previous indices: %{index_names} will be deleted after %{time} automatically."
-msgstr ""
+msgstr "未被使用的先å‰ç´¢å¼•ï¼š %{index_names} 將在 %{time} 後自動刪除。"
msgid "Unverified"
-msgstr ""
+msgstr "未驗證"
msgid "Up to date"
-msgstr ""
+msgstr "最新"
msgid "Upcoming"
-msgstr ""
+msgstr "å³å°‡é–‹å§‹"
msgid "Upcoming Release"
-msgstr ""
+msgstr "å³å°‡ç™¼å¸ƒ"
msgid "Update"
-msgstr ""
+msgstr "æ›´æ–°"
msgid "Update %{sourcePath} file"
-msgstr ""
+msgstr "更新%{sourcePath}文件"
msgid "Update Now"
-msgstr ""
+msgstr "ç«‹å³æ›´æ–°"
msgid "Update Scheduled…"
-msgstr ""
+msgstr "更新排程…"
msgid "Update all"
-msgstr ""
+msgstr "全部更新"
msgid "Update appearance settings"
-msgstr ""
+msgstr "更新外觀設定"
msgid "Update approval rule"
-msgstr ""
+msgstr "更新核准è¦å‰‡"
msgid "Update approvers"
-msgstr ""
+msgstr "更新核准人"
msgid "Update broadcast message"
-msgstr ""
+msgstr "更新廣播訊æ¯"
msgid "Update failed"
-msgstr ""
+msgstr "更新失敗"
msgid "Update it"
-msgstr ""
+msgstr "æ›´æ–°"
msgid "Update milestone"
-msgstr ""
+msgstr "更新里程碑"
msgid "Update now"
-msgstr ""
+msgstr "ç«‹å³æ›´æ–°"
msgid "Update username"
-msgstr ""
+msgstr "更新使用者å稱"
msgid "Update variable"
-msgstr ""
+msgstr "更新變數"
msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
-msgstr ""
+msgstr "請更新您的書籤 URLs, 因為éŽæ¿¾/排åºçš„分支 URL 已變更。"
msgid "Update your group name, description, avatar, and visibility."
-msgstr ""
+msgstr "更新您的群組å稱ã€èªªæ˜Žã€é ­åƒä»¥åŠå¯è¦‹æ€§ã€‚"
msgid "Update your project name, topics, description, and avatar."
-msgstr ""
+msgstr "更新您的專案å稱ã€ä¸»é¡Œã€æ述和頭åƒã€‚"
msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
-msgstr ""
+msgstr "因為專案容器映åƒåº«å·²æœ‰æ¨™ç±¤ï¼Œç„¡æ³•æ›´æ–°ç•¶å‰å°ˆæ¡ˆï¼"
msgid "UpdateProject|Could not set the default branch"
-msgstr ""
+msgstr "無法設定é è¨­åˆ†æ”¯"
msgid "UpdateProject|New visibility level not allowed!"
-msgstr ""
+msgstr "ä¸å…許新的å¯è¦‹æ€§ç´šåˆ¥ï¼"
msgid "UpdateProject|Project could not be updated!"
-msgstr ""
+msgstr "專案無法更新ï¼"
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
-msgstr ""
+msgstr "從%{old}到%{new}的%{type}版本庫檢查碼驗證失敗"
msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
-msgstr ""
+msgstr "等待%{type}版本庫推é€é€¾æ™‚"
msgid "Updated"
-msgstr ""
+msgstr "已更新於"
msgid "Updated %{updated_at} by %{updated_by}"
-msgstr ""
+msgstr "ç”±%{updated_by}æ›´æ–°æ–¼%{updated_at}"
msgid "Updated date"
-msgstr ""
+msgstr "更新日期"
msgid "Updating"
-msgstr ""
-
-msgid "Updating the attention request for %{username} failed."
-msgstr ""
+msgstr "更新中"
msgid "Updating…"
-msgstr ""
+msgstr "正在更新…"
msgid "Upgrade offers available!"
-msgstr ""
+msgstr "æä¾›å‡ç´šå„ªæƒ ï¼"
msgid "Upload"
-msgstr ""
+msgstr "上傳"
msgid "Upload %{file_name} file"
-msgstr ""
+msgstr "上傳 %{file_name} 文件"
msgid "Upload CSV file"
-msgstr ""
+msgstr "上傳CSV文件"
msgid "Upload File"
-msgstr ""
+msgstr "上傳文件"
msgid "Upload New File"
-msgstr ""
+msgstr "上傳新文件"
msgid "Upload a certificate for your domain with all intermediates"
-msgstr ""
+msgstr "é€éŽå„²å­˜ä»‹è³ªä¸Šå‚³æ‚¨çš„網域憑證"
msgid "Upload a private key for your certificate"
-msgstr ""
+msgstr "為您的憑證上傳一個ç§é‘°"
+
+msgid "Upload could not be deleted."
+msgstr "無法刪除上傳。"
msgid "Upload file"
-msgstr ""
+msgstr "上傳文件"
msgid "Upload image"
-msgstr ""
+msgstr "上傳圖片"
msgid "Upload new file"
-msgstr ""
+msgstr "上傳新文件"
msgid "Upload object map"
-msgstr ""
+msgstr "上傳物件圖"
msgid "Uploaded date"
-msgstr ""
+msgstr "上傳日期"
msgid "Uploading changes to terminal"
-msgstr ""
+msgstr "正在將變更內容上傳到終端"
msgid "Uploading..."
-msgstr ""
+msgstr "上傳中..."
msgid "Upstream"
-msgstr ""
-
-msgid "Uptime"
-msgstr ""
+msgstr "上游"
msgid "Upvotes"
-msgstr ""
+msgstr "讚æˆ"
msgid "Usage Trends"
-msgstr ""
+msgstr "使用趨勢"
msgid "Usage statistics"
-msgstr ""
+msgstr "使用情æ³çµ±è¨ˆ"
msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
-msgstr ""
+msgstr "%{help_link_start}共用執行器(Runner)%{help_link_end}å·²åœç”¨ï¼Œæ‰€ä»¥æµæ°´ç·šä½¿ç”¨æ²’有設定é™åˆ¶"
msgid "UsageQuota|%{linkStart}Shared runners%{linkEnd} are disabled, so there are no limits set on pipeline usage"
-msgstr ""
+msgstr "%{linkStart}共享執行器%{linkEnd}被åœç”¨ï¼Œå› æ­¤å°æµæ°´ç·šçš„使用沒有設置é™åˆ¶"
msgid "UsageQuota|%{linkTitle} help link"
-msgstr ""
+msgstr "%{linkTitle} 幫助連çµ"
msgid "UsageQuota|%{percentageLeft} of purchased storage is available"
-msgstr ""
+msgstr "%{percentageLeft} 購買的儲存空間å¯ç”¨"
msgid "UsageQuota|Artifacts"
-msgstr ""
+msgstr "產物"
msgid "UsageQuota|Artifacts is a sum of build and pipeline artifacts."
-msgstr ""
+msgstr "產物是構建和æµæ°´ç·šç”¢å‡ºç‰©çš„總和。"
msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
-msgstr ""
+msgstr "音頻樣本ã€è¦–é »ã€è³‡æ–™é›†å’Œåœ–形。"
msgid "UsageQuota|Buy additional minutes"
-msgstr ""
+msgstr "購買é¡å¤–分é˜æ•¸"
msgid "UsageQuota|Buy storage"
-msgstr ""
+msgstr "購買儲存"
msgid "UsageQuota|CI minutes usage by month"
-msgstr ""
+msgstr "CI 分é˜ä½¿ç”¨é‡ï¼ˆæŒ‰æœˆï¼‰"
msgid "UsageQuota|CI minutes usage by project"
-msgstr ""
+msgstr "CI 分é˜ä½¿ç”¨é‡ï¼ˆæŒ‰å°ˆæ¡ˆï¼‰"
msgid "UsageQuota|CI/CD minutes usage"
-msgstr ""
+msgstr "CI/CD 使用分é˜æ•¸"
msgid "UsageQuota|CI/CD minutes usage since %{timeElapsed}"
-msgstr ""
+msgstr "從 %{timeElapsed} 以來的 CI 分é˜ä½¿ç”¨é‡"
msgid "UsageQuota|Code packages and container images."
-msgstr ""
+msgstr "程å¼ç¢¼å¥—件和容器映åƒã€‚"
msgid "UsageQuota|Container Registry"
-msgstr ""
+msgstr "容器註冊表"
msgid "UsageQuota|Current period usage"
-msgstr ""
+msgstr "當å‰é€±æœŸä½¿ç”¨é‡"
msgid "UsageQuota|Dependency proxy"
-msgstr ""
+msgstr "ä¾è³´ä»£ç†"
-msgid "UsageQuota|File attachments and smaller design graphics."
-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|From %{storage_enforcement_date} storage limits will apply to this namespace. You are currently using %{used_storage} of namespace storage. View and manage your usage from %{strong_start}%{namespace_type} settings &gt; Usage quotas%{strong_end}."
-msgstr ""
+msgid "UsageQuota|File attachments and smaller design graphics."
+msgstr "文件附件和較å°çš„設計圖表。"
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Git版本庫。"
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images."
-msgstr ""
+msgstr "Gitlab æ•´åˆçš„ Docker 容器註冊表,用於儲存 Docker 映åƒæª”。"
msgid "UsageQuota|Gitlab-integrated Docker Container Registry for storing Docker Images. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Gitlab æ•´åˆçš„ Docker 容器註冊表,用於儲存 Docker 映åƒæª”。 %{linkStart}更多信æ¯%{linkEnd}"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
-msgstr ""
+msgstr "包括產物ã€ç‰ˆæœ¬åº«ã€wikiã€ä¸Šå‚³æ–‡ä»¶å’Œå…¶å®ƒäº‹é …。"
msgid "UsageQuota|Increase storage temporarily"
-msgstr ""
+msgstr "臨時增加儲存"
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "LFS儲存"
msgid "UsageQuota|Learn more about excess storage usage"
-msgstr ""
+msgstr "了解有關超é¡å„²å­˜ä½¿ç”¨é‡çš„更多訊æ¯"
msgid "UsageQuota|Learn more about usage quotas"
-msgstr ""
+msgstr "了解有關使用é…é¡çš„更多訊æ¯"
msgid "UsageQuota|Learn more about usage quotas."
-msgstr ""
+msgstr "詳細了解使用é…é¡ã€‚"
msgid "UsageQuota|Local proxy used for frequently-accessed upstream Docker images. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "用於經常存å–的上游 Docker 映åƒçš„本地代ç†ã€‚ %{linkStart}更多信æ¯%{linkEnd}"
msgid "UsageQuota|Namespace storage used"
-msgstr ""
+msgstr "已使用的命å空間儲存"
msgid "UsageQuota|No CI minutes usage data available."
-msgstr ""
+msgstr "ç„¡å¯ç”¨çš„ CI 分é˜ä½¿ç”¨è³‡æ–™ã€‚"
msgid "UsageQuota|Packages"
-msgstr ""
+msgstr "軟體套件"
msgid "UsageQuota|Pending Members"
-msgstr ""
+msgstr "待定æˆå“¡"
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
-msgstr ""
+msgstr "用 CI/CD 建立的æµæ°´ç·šç”¢ç‰©å’Œä½œæ¥­ç”¢ç‰©ã€‚"
msgid "UsageQuota|Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "UsageQuota|Purchase more storage"
-msgstr ""
+msgstr "購買更多儲存空間"
msgid "UsageQuota|Purchased storage"
-msgstr ""
+msgstr "已購買的儲存空間"
msgid "UsageQuota|Purchased storage available"
-msgstr ""
+msgstr "購買的儲存空間å¯ç”¨"
msgid "UsageQuota|Purchased storage used"
-msgstr ""
+msgstr "已使用的購買儲存"
msgid "UsageQuota|Recalculate repository usage"
-msgstr ""
+msgstr "é‡æ–°è¨ˆç®—版本庫使用情æ³"
msgid "UsageQuota|Repository"
-msgstr ""
+msgstr "版本庫"
msgid "UsageQuota|Seats"
-msgstr ""
+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 ""
+msgstr "共用程å¼ç¢¼å’Œæ–‡å­—"
msgid "UsageQuota|Shared runner duration"
-msgstr ""
+msgstr "共享執行器æŒçºŒæ™‚é–“"
msgid "UsageQuota|Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "UsageQuota|Something went wrong while fetching pipeline statistics"
-msgstr ""
+msgstr "讀å–æµæ°´ç·šçµ±è¨ˆä¿¡æ¯æ™‚出ç¾å•é¡Œ"
msgid "UsageQuota|Something went wrong while fetching project storage statistics"
-msgstr ""
+msgstr "å–得專案儲存統計時出ç¾éŒ¯èª¤"
msgid "UsageQuota|Something went wrong while loading usage details"
-msgstr ""
+msgstr "讀å–詳細的使用資料時發生錯誤"
msgid "UsageQuota|Storage"
-msgstr ""
+msgstr "儲存媒體"
msgid "UsageQuota|Storage type"
-msgstr ""
+msgstr "儲存類型"
msgid "UsageQuota|Storage used"
-msgstr ""
+msgstr "已使用的儲存"
+
+msgid "UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "
+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}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}"
+msgstr "命å空間目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空間儲存,群組所有者å¯ä»¥å¾ž %{strong_start}群組設定 &gt; 使用é…é¡%{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}User settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more%{link_end} about how to reduce your storage."
+msgstr "命å空間目å‰æ­£åœ¨ä½¿ç”¨ %{strong_start}%{used_storage}%{strong_end} 的命å空間儲存。從 %{strong_start}使用者設定 &gt; 使用é¡åº¦%{strong_end}檢視和管ç†æ‚¨çš„使用情æ³ã€‚ %{docs_link_start}詳細了解%{link_end}如何減少您的儲存空間。"
msgid "UsageQuota|The table below shows current period usage"
-msgstr ""
+msgstr "下表顯示了目å‰å€é–“的使用情æ³"
msgid "UsageQuota|The table below shows usage since %{timeElapsed}"
-msgstr ""
+msgstr "下表顯示了自 %{timeElapsed} 以來的使用情æ³"
msgid "UsageQuota|This is the total amount of storage used across your projects within this namespace."
-msgstr ""
+msgstr "這是此命å空間中所有專案使用的儲存空間總和。"
msgid "UsageQuota|This is the total amount of storage used by projects above the free %{actualRepositorySizeLimit} storage limit."
-msgstr ""
+msgstr "這是超出專案å…è²»%{actualRepositorySizeLimit}儲存é™åˆ¶çš„儲存空間。"
msgid "UsageQuota|This namespace contains locked projects"
-msgstr ""
+msgstr "此命å空間包å«å·²éŽ–定的專案"
msgid "UsageQuota|This namespace has no projects which use shared runners"
-msgstr ""
+msgstr "此命å空間沒有使用共用執行器(runners)的專案"
msgid "UsageQuota|This namespace has no projects which used shared runners in the current period"
-msgstr ""
+msgstr "此命å空間目å‰æ²’有使用共享執行器的專案"
msgid "UsageQuota|This table omits projects that used 0 CI/CD minutes or 0 shared runners duration"
-msgstr ""
+msgstr "此表çœç•¥äº†ä½¿ç”¨ 0 CI/CD 分é˜æˆ– 0 共享執行器æŒçºŒæ™‚間的專案"
msgid "UsageQuota|Total excess storage used"
-msgstr ""
+msgstr "已使用超é‡å„²å­˜ç©ºé–“總計"
msgid "UsageQuota|Total namespace storage used"
-msgstr ""
+msgstr "已使用命å空間儲存總計"
msgid "UsageQuota|Unlimited"
-msgstr ""
+msgstr "ç„¡é™"
msgid "UsageQuota|Uploads"
-msgstr ""
+msgstr "上傳"
msgid "UsageQuota|Usage"
-msgstr ""
+msgstr "使用é‡"
msgid "UsageQuota|Usage Quotas"
-msgstr ""
+msgstr "使用é‡é…é¡"
msgid "UsageQuota|Usage breakdown"
-msgstr ""
+msgstr "使用明細"
msgid "UsageQuota|Usage by month"
-msgstr ""
+msgstr "月使用é‡"
msgid "UsageQuota|Usage by project"
-msgstr ""
+msgstr "專案使用é‡"
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
-msgstr ""
+msgstr "%{strong_start}%{group_name}%{strong_end}群組中的專案使用群組資æºç‹€æ³"
msgid "UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project"
-msgstr ""
+msgstr "%{strong_start}%{project_name}%{strong_end} 專案中專案資æºä½¿ç”¨æƒ…æ³"
msgid "UsageQuota|Usage of resources across your projects"
-msgstr ""
+msgstr "您的專案中資æºä½¿ç”¨æƒ…æ³"
msgid "UsageQuota|Usage quotas help link"
-msgstr ""
+msgstr "使用é…é¡å¹«åŠ©é€£çµ"
msgid "UsageQuota|Usage since %{usageSince}"
-msgstr ""
+msgstr "自 %{usageSince} 以來的使用情æ³"
msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit."
-msgstr ""
+msgstr "當您購買更多的儲存空間時,我們會自動解鎖é”到%{actualRepositorySizeLimit}é™åˆ¶æ™‚被鎖定的專案。"
msgid "UsageQuota|Wiki"
-msgstr ""
+msgstr "Wiki"
msgid "UsageQuota|Wiki content."
-msgstr ""
+msgstr "Wiki 內容。"
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
-msgstr ""
+msgstr "您已經用盡所有更多的儲存空間,請購買更多空間以解鎖超éŽå…è²»%{actualRepositorySizeLimit}é™åˆ¶çš„專案。"
msgid "UsageQuota|You have reached the free storage limit of %{actualRepositorySizeLimit} on %{projectsLockedText}. To unlock them, please purchase additional storage."
-msgstr ""
+msgstr "您已經在%{projectsLockedText}é”到儲存空間é™åˆ¶%{actualRepositorySizeLimit}。如需解鎖,請購買更多儲存空間。"
msgid "UsageQuota|You used: %{usage} %{limit}"
-msgstr ""
+msgstr "您已使用: %{usage} %{limit}"
msgid "UsageQuota|Your purchased storage is running low. To avoid locked projects, please purchase more storage."
-msgstr ""
+msgstr "您購買的儲存空間已ä¸è¶³ã€‚為了é¿å…專案被鎖定,請購買更多儲存空間。"
msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
-msgstr ""
+msgstr "超éŽæ‚¨å‘½å空間儲存的%{formattedLimit}"
msgid "UsageTrends|Could not load the issues and merge requests chart. Please refresh the page to try again."
-msgstr ""
+msgstr "無法載入議題和åˆä½µè«‹æ±‚圖表,請é‡æ–°æ•´ç†é é¢é‡è©¦ã€‚"
msgid "UsageTrends|Could not load the pipelines chart. Please refresh the page to try again."
-msgstr ""
+msgstr "無法載入æµæ°´ç·šåœ–表,請é‡æ–°æ•´ç†é é¢é‡è©¦ã€‚"
msgid "UsageTrends|Could not load the projects and groups chart. Please refresh the page to try again."
-msgstr ""
+msgstr "無法載入專案和群組圖表,請é‡æ–°æ•´ç†é é¢é‡è©¦ã€‚"
msgid "UsageTrends|Groups"
-msgstr ""
+msgstr "群組"
msgid "UsageTrends|Issues"
-msgstr ""
+msgstr "議題"
msgid "UsageTrends|Issues & merge requests"
-msgstr ""
+msgstr "議題與åˆä½µè«‹æ±‚"
msgid "UsageTrends|Items"
-msgstr ""
+msgstr "事項"
msgid "UsageTrends|Merge requests"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "UsageTrends|Month"
-msgstr ""
+msgstr "月"
msgid "UsageTrends|No data available."
-msgstr ""
+msgstr "ç„¡å¯ç”¨è³‡æ–™ã€‚"
msgid "UsageTrends|Pipelines"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "UsageTrends|Pipelines canceled"
-msgstr ""
+msgstr "æµæ°´ç·šå·²å–消"
msgid "UsageTrends|Pipelines failed"
-msgstr ""
+msgstr "æµæ°´ç·šå¤±æ•—"
msgid "UsageTrends|Pipelines skipped"
-msgstr ""
+msgstr "æµæ°´ç·šå·²è·³éŽ"
msgid "UsageTrends|Pipelines succeeded"
-msgstr ""
+msgstr "æµæ°´ç·šæˆåŠŸ"
msgid "UsageTrends|Pipelines total"
-msgstr ""
+msgstr "æµæ°´ç·šç¸½æ•¸"
msgid "UsageTrends|Projects"
-msgstr ""
+msgstr "專案"
msgid "UsageTrends|There was an error fetching the cancelled pipelines. Please try again."
-msgstr ""
+msgstr "å–å¾—å·²å–消的æµæ°´ç·šæ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the failed pipelines. Please try again."
-msgstr ""
+msgstr "å–得失敗的æµæ°´ç·šæ™‚發生錯誤。請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the groups. Please try again."
-msgstr ""
+msgstr "å–得群組時發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the issues. Please try again."
-msgstr ""
+msgstr "å–得議題時發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the merge requests. Please try again."
-msgstr ""
+msgstr "å–å¾—åˆä½µè«‹æ±‚時發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the projects. Please try again."
-msgstr ""
+msgstr "å–得專案時發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the skipped pipelines. Please try again."
-msgstr ""
+msgstr "å–å¾—è·³éŽçš„æµæ°´ç·šæ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the successful pipelines. Please try again."
-msgstr ""
+msgstr "å–å¾—æˆåŠŸçš„æµæ°´ç·šæ™‚發生錯誤,請é‡è©¦ã€‚"
msgid "UsageTrends|There was an error fetching the total pipelines. Please try again."
-msgstr ""
+msgstr "å–å¾—æµæ°´ç·šç¸½æ•¸æ™‚發生錯誤,請å†è©¦ã€‚"
msgid "UsageTrends|Total groups"
-msgstr ""
+msgstr "群組總數"
msgid "UsageTrends|Total projects"
-msgstr ""
+msgstr "專案總數"
msgid "UsageTrends|Total projects & groups"
-msgstr ""
+msgstr "專案和群組總數"
msgid "UsageTrends|Users"
-msgstr ""
+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 ""
+msgstr "使用 %{code_start}::%{code_end} 建立 %{link_start}有範åœçš„標籤集%{link_end} (例如 %{code_start}priority::1%{code_end})"
msgid "Use .gitlab-ci.yml"
-msgstr ""
+msgstr "使用 .gitlab-ci.yml"
msgid "Use GitLab Runner in AWS"
-msgstr ""
+msgstr "在AWS中使用GitLab執行器"
msgid "Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates."
-msgstr ""
+msgstr "使用安全文件來儲存您æµæ°´ç·šä½¿ç”¨çš„æ–‡ä»¶ï¼Œä¾‹å¦‚å®‰å“ keystores 或 Apple provising profile 和簽å證書。"
msgid "Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
-msgstr ""
+msgstr "在您的移動設備或電腦上使用一次性密碼驗證器來啟用雙因å­é©—è­‰ (2FA)。"
msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab Runner in AWS."
-msgstr ""
+msgstr "使用 AWS CloudFormation 範本 (CFT) 在 AWS 中安è£å’Œè¨­å®š GitLab 執行器。"
msgid "Use authorized_keys file to authenticate SSH keys"
-msgstr ""
+msgstr "使用 authorized_keys 文件來驗證 SSH 金鑰"
msgid "Use banners and notifications to notify your users about scheduled maintenance, recent upgrades, and more."
-msgstr ""
+msgstr "使用橫幅和通告,通知您的使用者有關定期維護ã€æœ€è¿‘å‡ç´šç­‰è¨Šæ¯ã€‚"
msgid "Use cURL"
-msgstr ""
+msgstr "使用 cURL"
msgid "Use custom color #FF0000"
-msgstr ""
+msgstr "使用自訂é¡è‰² #FF0000"
msgid "Use double quotes for multiple keywords, such as %{code_open}\"your search\"%{code_close}"
-msgstr ""
+msgstr "å°å¤šå€‹é—œéµå­—使用雙引號,例如 %{code_open}\"您的æœå°‹\"%{code_close}"
msgid "Use hashed storage"
-msgstr ""
+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 "å°æ–°å»ºç«‹å’Œé‡æ–°å‘½å的儲存庫使用散列儲存路徑。 自 13.0 起固定啟用。 %{link_start}了解更多。%{link_end}"
msgid "Use issue count"
-msgstr ""
+msgstr "使用議題計數"
msgid "Use issue weight"
-msgstr ""
+msgstr "使用議題權é‡"
msgid "Use one line per URI"
-msgstr ""
+msgstr "æ¯å€‹URIå ä¸€è¡Œ"
msgid "Use primary email (%{email})"
-msgstr ""
+msgstr "使用主電å­éƒµä»¶(%{email})"
msgid "Use shortcuts"
-msgstr ""
+msgstr "使用快æ·éµ"
msgid "Use slash commands."
-msgstr ""
+msgstr "使用斜線指令。"
msgid "Use template"
-msgstr ""
+msgstr "使用模æ¿"
msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
-msgstr ""
+msgstr "使用上é¢çš„ %{strongStart}測試%{strongEnd} é¸é …建立事件。"
msgid "Use the link below to confirm your email address (%{email})"
-msgstr ""
+msgstr "使用以下連çµç¢ºèªæ‚¨çš„é›»å­éƒµä»¶åœ°å€ (%{email})"
msgid "Use the link below to confirm your email address."
-msgstr ""
+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 ""
+msgstr "使用公共雲實例 URL (%{kroki_public_url}) 或 %{install_link_start}åœ¨æ‚¨è‡ªå·±çš„åŸºç¤Žæž¶æ§‹ä¸Šå®‰è£ Kroki%{install_link_end} 並使用您自己的實例 URL。"
msgid "Use the search bar on the top of this page"
-msgstr ""
+msgstr "使用本é é ‚部的æœå°‹æ¬„"
msgid "Use this token to validate received payloads."
-msgstr ""
+msgstr "使用此令牌來驗證收到的有效資料。"
msgid "Use webhook"
-msgstr ""
+msgstr "使用 webhook"
msgid "Use your global notification setting"
-msgstr ""
+msgstr "使用全域通知設定"
msgid "Use your smart card to authenticate with the LDAP server."
-msgstr ""
+msgstr "使用智慧å¡å°LDAP伺æœå™¨é€²è¡Œèº«ä»½é©—證。"
msgid "Used"
-msgstr ""
+msgstr "已使用"
+
+msgid "Used by %d package"
+msgid_plural "Used by %d packages"
+msgstr[0] "被 %d 個套件使用"
msgid "Used by members to sign in to your group in GitLab"
-msgstr ""
+msgstr "用於æˆå“¡ç™»å…¥æ‚¨çš„GitLab群組"
msgid "Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises."
-msgstr ""
+msgstr "æˆ‘å€‘è¢«è¶…éŽ 100,000 個組織使用,是管ç†æœ¬åœ° git 版本庫的最å—歡迎的解決方案。"
msgid "Used programming language"
-msgstr ""
+msgstr "使用的程å¼èªžè¨€"
msgid "Used to help configure your identity provider"
-msgstr ""
+msgstr "用於幫助設定您的身份æ供者"
msgid "User"
-msgstr ""
+msgstr "使用者"
msgid "User %{current_user_username} has started impersonating %{username}"
-msgstr ""
+msgstr "使用者 %{current_user_username} 已開始使用%{username}的身份"
msgid "User %{username} was successfully removed."
-msgstr ""
+msgstr "使用者 %{username} å·²æˆåŠŸåˆªé™¤ã€‚"
msgid "User %{user} was removed from %{group}."
-msgstr ""
+msgstr "使用者 %{user} 已從 %{group} 移除。"
msgid "User ID"
-msgstr ""
+msgstr "使用者ID"
msgid "User OAuth applications"
-msgstr ""
+msgstr "使用者的 OAuth 應用程å¼"
msgid "User Settings"
-msgstr ""
+msgstr "使用者設定"
msgid "User and IP rate limits"
-msgstr ""
+msgstr "使用者和 IP 速率é™åˆ¶"
msgid "User cap"
-msgstr ""
+msgstr "使用者上é™"
msgid "User cap cannot be enabled. The group or one of its subgroups or projects is shared externally."
-msgstr ""
+msgstr "無法啟用使用者上é™ã€‚該群組或其å­ç¾¤çµ„或專案之一在外部共用。"
msgid "User created at"
-msgstr ""
+msgstr "使用者建立於"
msgid "User does not have a pending request"
-msgstr ""
+msgstr "使用者沒有待處ç†è«‹æ±‚"
msgid "User identity was successfully created."
-msgstr ""
+msgstr "å·²æˆåŠŸå»ºç«‹ä½¿ç”¨è€…身份。"
msgid "User identity was successfully removed."
-msgstr ""
+msgstr "å·²æˆåŠŸç§»é™¤ä½¿ç”¨è€…身份。"
msgid "User identity was successfully updated."
-msgstr ""
+msgstr "å·²æˆåŠŸæ›´æ–°ä½¿ç”¨è€…身份。"
msgid "User is not allowed to resolve thread"
-msgstr ""
+msgstr "使用者ä¸è¢«å…許解決主題"
msgid "User key"
-msgstr ""
+msgstr "使用者金鑰"
msgid "User key was successfully removed."
-msgstr ""
+msgstr "使用者金鑰已æˆåŠŸç§»é™¤ã€‚"
msgid "User list %{name} will be removed. Are you sure?"
-msgstr ""
+msgstr "使用者列表%{name}將被移除,確定繼續嗎?"
msgid "User map"
-msgstr ""
+msgstr "使用者映射"
msgid "User pipeline minutes were successfully reset."
-msgstr ""
+msgstr "使用者æµæ°´ç·šåˆ†é˜æ•¸å·²æˆåŠŸé‡è¨­ã€‚"
msgid "User restrictions"
-msgstr ""
+msgstr "使用者é™åˆ¶"
msgid "User settings"
-msgstr ""
+msgstr "使用者設定"
msgid "User was successfully created."
-msgstr ""
+msgstr "使用者已æˆåŠŸå»ºç«‹ã€‚"
msgid "User was successfully removed from group and any subgroups and projects."
-msgstr ""
+msgstr "å·²æˆåŠŸå¾žç¾¤çµ„ã€å­ç¾¤çµ„和專案中移除該使用者。"
msgid "User was successfully removed from group."
-msgstr ""
+msgstr "使用者已æˆåŠŸå¾žç¾¤çµ„中移除。"
msgid "User was successfully removed from project."
-msgstr ""
+msgstr "使用者已æˆåŠŸå¾žå°ˆæ¡ˆä¸­ç§»é™¤ã€‚"
+
+msgid "User was successfully unbanned."
+msgstr "æˆåŠŸè§£é™¤å°éŽ–使用者。"
msgid "User was successfully updated."
-msgstr ""
+msgstr "使用者已æˆåŠŸæ›´æ–°ã€‚"
msgid "User-based escalation rules must have a user with access to the project"
-msgstr ""
+msgstr "基於使用者的å‡ç´šè¦å‰‡å¿…須有一個使用者å¯ä»¥å­˜å–專案"
msgid "UserAvailability|%{author} %{spanStart}(Busy)%{spanEnd}"
-msgstr ""
+msgstr "%{author} %{spanStart}(忙碌)%{spanEnd}"
msgid "UserAvailability|%{author} (Busy)"
-msgstr ""
+msgstr "%{author} (忙碌)"
msgid "UserAvailability|(Busy)"
-msgstr ""
+msgstr "(忙碌)"
msgid "UserLists|Add"
-msgstr ""
+msgstr "加入"
msgid "UserLists|Add Users"
-msgstr ""
+msgstr "加入使用者"
msgid "UserLists|Add users"
-msgstr ""
+msgstr "加入使用者"
msgid "UserLists|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "UserLists|Create"
-msgstr ""
+msgstr "建立"
msgid "UserLists|Define a set of users to be used within feature flag strategies"
-msgstr ""
+msgstr "定義在功能標誌策略中使用的一組使用者"
msgid "UserLists|Edit"
-msgstr ""
+msgstr "編輯"
msgid "UserLists|Edit %{name}"
-msgstr ""
+msgstr "編輯%{name}"
msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
-msgstr ""
+msgstr "輸入一個逗號分隔的使用者ID列表。這些ID應該是設定使用功能標誌的系統的使用者,而ä¸æ˜¯GitLab ID"
msgid "UserLists|Feature flag user list"
-msgstr ""
+msgstr "功能標誌使用者列表"
msgid "UserLists|Get started with user lists"
-msgstr ""
+msgstr "開始使用使用者列表"
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
-msgstr ""
+msgstr "列表å…許您定義一組用於功能標誌的使用者。 %{linkStart}閱讀更多關於功能標誌列表的訊æ¯ã€‚%{linkEnd}"
msgid "UserLists|Loading user lists"
-msgstr ""
+msgstr "載入使用者列表"
msgid "UserLists|Name"
-msgstr ""
+msgstr "å稱"
msgid "UserLists|New list"
-msgstr ""
+msgstr "新建列表"
msgid "UserLists|New user list"
-msgstr ""
+msgstr "新建使用者列表"
msgid "UserLists|Save"
-msgstr ""
+msgstr "ä¿å­˜"
msgid "UserLists|There are no users"
-msgstr ""
+msgstr "沒有使用者"
msgid "UserLists|There was an error fetching the user lists."
-msgstr ""
+msgstr "å–得使用者列表時發生錯誤。"
msgid "UserLists|User ID"
-msgstr ""
+msgstr "使用者ID"
msgid "UserLists|User IDs"
-msgstr ""
+msgstr "使用者ID"
msgid "UserLists|User Lists"
-msgstr ""
+msgstr "使用者列表"
msgid "UserLists|User lists allow you to define a set of users to use with Feature Flags."
-msgstr ""
+msgstr "使用者列表å…許您定義一組與功能標誌一起使用的使用者。"
msgid "UserList|Delete %{name}?"
-msgstr ""
+msgstr "刪除%{name}嗎?"
msgid "UserList|created %{timeago}"
-msgstr ""
+msgstr "建立於%{timeago}"
msgid "UserProfile|(Busy)"
-msgstr ""
+msgstr "(忙碌)"
msgid "UserProfile|Activity"
-msgstr ""
+msgstr "活動"
msgid "UserProfile|Already reported for abuse"
-msgstr ""
+msgstr "已報告濫用"
msgid "UserProfile|Blocked user"
-msgstr ""
+msgstr "å·²ç¦ç”¨ä½¿ç”¨è€…"
msgid "UserProfile|Bot activity"
-msgstr ""
+msgstr "Bot活動"
msgid "UserProfile|Contributed projects"
-msgstr ""
+msgstr "åƒèˆ‡è²¢ç»çš„專案"
+
+msgid "UserProfile|Copy user ID"
+msgstr "複製使用者ID"
msgid "UserProfile|Edit profile"
-msgstr ""
+msgstr "編輯個人資料"
msgid "UserProfile|Explore public groups to find projects to contribute to."
-msgstr ""
+msgstr "ç€è¦½å…¬é–‹ç¾¤çµ„以尋找è¦è²¢ç»çš„專案。"
msgid "UserProfile|Followers"
-msgstr ""
+msgstr "關注者"
msgid "UserProfile|Following"
-msgstr ""
+msgstr "正在關注的人"
msgid "UserProfile|Groups"
-msgstr ""
+msgstr "群組"
msgid "UserProfile|Groups are the best way to manage projects and members."
-msgstr ""
+msgstr "群組是管ç†å°ˆæ¡ˆå’Œæˆå“¡çš„最佳方å¼ã€‚"
msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
-msgstr ""
+msgstr "加入或建立一個群組,通éŽç•™è¨€è­°é¡Œæˆ–æ交åˆä½µè«‹æ±‚來開始貢ç»ï¼"
msgid "UserProfile|Most Recent Activity"
-msgstr ""
+msgstr "最新活動"
msgid "UserProfile|No snippets found."
-msgstr ""
+msgstr "未找到程å¼ç¢¼ç‰‡æ®µ"
msgid "UserProfile|Overview"
-msgstr ""
+msgstr "概覽"
msgid "UserProfile|Personal projects"
-msgstr ""
+msgstr "個人專案"
msgid "UserProfile|Pronounced as: %{pronunciation}"
-msgstr ""
+msgstr "讀作: %{pronunciation}"
msgid "UserProfile|Report abuse"
-msgstr ""
+msgstr "舉報濫用行為"
msgid "UserProfile|Retry"
-msgstr ""
+msgstr "é‡è©¦"
msgid "UserProfile|Snippets"
-msgstr ""
+msgstr "程å¼ç¢¼ç‰‡æ®µ"
msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
-msgstr ""
+msgstr "GitLab 中的程å¼ç¢¼ç‰‡æ®µå¯ä»¥æ˜¯ç§æœ‰çš„ã€å…§éƒ¨æˆ–公開。"
msgid "UserProfile|Star projects to track their progress and show your appreciation."
-msgstr ""
+msgstr "給專案加星號以追蹤其進度並表é”您的讚賞。"
msgid "UserProfile|Starred projects"
-msgstr ""
+msgstr "收è—(星號)專案"
msgid "UserProfile|Subscribe"
-msgstr ""
+msgstr "關注"
msgid "UserProfile|This user doesn't have any followers."
-msgstr ""
+msgstr "這個使用者沒有任何關注者。"
msgid "UserProfile|This user doesn't have any personal projects"
-msgstr ""
+msgstr "使用者沒有任何個人專案"
msgid "UserProfile|This user has a private profile"
-msgstr ""
+msgstr "此使用者具有éžå…¬é–‹å€‹äººè³‡æ–™è¨­å®š"
msgid "UserProfile|This user hasn't contributed to any projects"
-msgstr ""
+msgstr "此使用者未å°ä»»ä½•å°ˆæ¡ˆåšå‡ºè²¢ç»"
msgid "UserProfile|This user hasn't starred any projects"
-msgstr ""
+msgstr "此使用者沒有收è—(星號)任何專案"
msgid "UserProfile|This user is blocked"
-msgstr ""
+msgstr "該使用者已被ç¦ç”¨"
msgid "UserProfile|This user isn't following other users."
-msgstr ""
+msgstr "此使用者沒有關注其他使用者。"
msgid "UserProfile|Unconfirmed user"
-msgstr ""
+msgstr "未確èªçš„使用者"
+
+msgid "UserProfile|User ID: %{id}"
+msgstr "使用者 ID:%{id}"
msgid "UserProfile|View all"
-msgstr ""
+msgstr "查看全部"
msgid "UserProfile|View user in admin area"
-msgstr ""
+msgstr "在管ç†å€åŸŸä¸­æŸ¥çœ‹ä½¿ç”¨è€…"
msgid "UserProfile|You are not following other users."
-msgstr ""
+msgstr "您沒有關注其他使用者。"
msgid "UserProfile|You can create a group for several dependent projects."
-msgstr ""
+msgstr "您å¯ä»¥ç‚ºå¤šå€‹ä¾è³´å°ˆæ¡ˆå»ºç«‹ä¸€å€‹ç¾¤çµ„。"
msgid "UserProfile|You do not have any followers."
-msgstr ""
+msgstr "您沒有任何關注者。"
msgid "UserProfile|You haven't created any personal projects."
-msgstr ""
+msgstr "您還沒有建立任何個人專案"
msgid "UserProfile|You haven't created any snippets."
-msgstr ""
+msgstr "您還沒有建立任何程å¼ç¢¼ç‰‡æ®µ"
msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
-msgstr ""
+msgstr "您的專案å¯ä»¥æ ¹æ“šæ‚¨çš„é¸æ“‡å…¬é–‹ã€å…§éƒ¨æˆ–ç§ä¸‹æ供。"
msgid "UserProfile|at"
-msgstr ""
+msgstr "æ–¼"
msgid "UserProfile|made a private contribution"
-msgstr ""
+msgstr "作出了個人貢ç»"
msgid "Username"
-msgstr ""
+msgstr "使用者å稱"
msgid "Username (optional)"
-msgstr ""
+msgstr "使用者å稱 (å¯é¸)"
msgid "Username is already taken."
-msgstr ""
+msgstr "使用者å稱已被使用。"
msgid "Username is available."
-msgstr ""
+msgstr "使用者å稱å¯ç”¨ã€‚"
msgid "Username or email"
-msgstr ""
+msgstr "使用者å稱或信箱"
msgid "Username:"
-msgstr ""
+msgstr "使用者å稱"
msgid "Username: %{username}"
-msgstr ""
+msgstr "使用者å稱: %{username}"
msgid "Users"
-msgstr ""
+msgstr "使用者"
msgid "Users API rate limit"
-msgstr ""
+msgstr "使用者 API 速率é™åˆ¶"
msgid "Users can launch a development environment from a GitLab browser tab when the %{linkStart}Gitpod%{linkEnd} integration is enabled."
-msgstr ""
+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 ""
+msgstr "使用者å¯ä»¥ä½¿ç”¨ Kroki 在 AsciiDocã€Markdownã€reStructuredText å’Œ Textile 文件中渲染圖表。"
msgid "Users can request access (if visibility is public or internal)"
-msgstr ""
+msgstr "使用者å¯ä»¥è«‹æ±‚å­˜å–(如果å¯è¦‹æ€§æ˜¯å…¬é–‹çš„或內部的)"
msgid "Users cannot be added to projects in this group"
-msgstr ""
+msgstr "無法將使用者加到此群組中的專案"
msgid "Users in License"
-msgstr ""
+msgstr "授權許å¯ä¸­çš„使用者數"
msgid "Users or groups set as approvers in the project's or merge request's settings."
-msgstr ""
+msgstr "在專案或åˆä½µè«‹æ±‚的設定中設為審批人的使用者或群組。"
msgid "Users over License"
-msgstr ""
+msgstr "超出授權許å¯çš„使用者數"
msgid "Users requesting access to"
-msgstr ""
+msgstr "請求存å–的使用者"
msgid "Users to exclude from the rate limit"
-msgstr ""
+msgstr "從速率é™åˆ¶ä¸­æŽ’除的使用者"
msgid "Users were successfully added."
-msgstr ""
+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 ""
+msgstr "具有訪客角色或ä¸å±¬æ–¼å°ˆæ¡ˆæˆ–群組的使用者將ä¸ä½”用您授權許å¯ä¸­çš„座次。"
msgid "UsersSelect|%{name} + %{length} more"
-msgstr ""
+msgstr "%{name} + 其餘%{length}ä½"
msgid "UsersSelect|Any User"
-msgstr ""
+msgstr "任何使用者"
msgid "UsersSelect|Assignee"
-msgstr ""
+msgstr "指派人"
msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
-msgstr ""
+msgstr "沒有指派人 - %{openingTag}分é…給自己%{closingTag}"
msgid "UsersSelect|Unassigned"
-msgstr ""
+msgstr "未分é…"
msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr ""
+msgstr "使用 GitLab 作為 Sentry 的輕é‡ç´šæ›¿ä»£å“。"
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
-msgstr ""
+msgstr "使用 %{code_start}::%{code_end} 表示 %{link_start}範åœæ¨™ç±¤é›†%{link_end}"
msgid "Using required encryption strategy when encrypted field is missing!"
-msgstr ""
+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 "使用%{codeStart}needs%{codeEnd}é—œéµå­—讓作業項比其所在階段更早執行。åªè¦å®ƒå€‘çš„%{codeStart}needs%{codeEnd}關係得到滿足,作業將盡快執行,從而實ç¾æµæ°´ç·šåŠ é€Ÿã€‚"
msgid "Valid From"
-msgstr ""
+msgstr "有效期自"
msgid "Validate"
-msgstr ""
+msgstr "é©—è­‰"
msgid "Validate your GitLab CI configuration"
-msgstr ""
+msgstr "驗證您的GitLab CI設定"
msgid "Validate your GitLab CI configuration file"
-msgstr ""
+msgstr "驗證您的GitLab CI設定文件"
msgid "Validated at"
-msgstr ""
+msgstr "驗證於"
msgid "Validated at:"
-msgstr ""
+msgstr "驗證於:"
msgid "Validated:"
-msgstr ""
+msgstr "已驗證:"
msgid "Validations failed."
-msgstr ""
+msgstr "驗證失敗。"
msgid "Value"
-msgstr ""
+msgstr "值"
msgid "Value Stream Analytics"
-msgstr ""
+msgstr "價值æµåˆ†æž"
msgid "Value Stream Analytics can help you determine your team’s velocity"
-msgstr ""
+msgstr "價值æµåˆ†æžå¯ä»¥å¹«åŠ©æ‚¨äº†è§£åœ˜éšŠçš„效率"
msgid "Value might contain a variable reference"
-msgstr ""
+msgstr "值å¯èƒ½åŒ…å«è®Šæ•¸å¼•ç”¨"
msgid "Value stream"
-msgstr ""
+msgstr "價值æµ"
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
-msgstr ""
+msgstr "我們沒有足夠的資料來顯示此階段。"
msgid "ValueStreamAnalytics|%{stageCount}+ items"
-msgstr ""
-
-msgid "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} label"
-msgid_plural "ValueStreamAnalytics|%{subjectFilterText} and %{selectedLabelsCount} labels"
-msgstr[0] ""
+msgstr "%{stageCount}+ é …"
msgid "ValueStreamAnalytics|%{value}M"
-msgstr ""
+msgstr "%{value}月"
msgid "ValueStreamAnalytics|%{value}d"
-msgstr ""
+msgstr "%{value}天"
msgid "ValueStreamAnalytics|%{value}h"
-msgstr ""
+msgstr "%{value}å°æ™‚"
msgid "ValueStreamAnalytics|%{value}m"
-msgstr ""
+msgstr "%{value}分é˜"
msgid "ValueStreamAnalytics|%{value}w"
-msgstr ""
+msgstr "%{value}周"
msgid "ValueStreamAnalytics|&lt;1m"
-msgstr ""
+msgstr "&lt;1m"
msgid "ValueStreamAnalytics|Average number of deployments to production per day."
-msgstr ""
+msgstr "æ¯å¤©éƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒçš„å¹³å‡æ•¸ã€‚"
msgid "ValueStreamAnalytics|DORA metrics"
-msgstr ""
+msgstr "DORA 指標"
msgid "ValueStreamAnalytics|Dashboard"
-msgstr ""
+msgstr "儀表æ¿"
msgid "ValueStreamAnalytics|Go to docs"
-msgstr ""
+msgstr "å‰å¾€æ–‡ä»¶"
msgid "ValueStreamAnalytics|Key metrics"
-msgstr ""
+msgstr "é—œéµæŒ‡æ¨™"
msgid "ValueStreamAnalytics|Median time an incident was open on a production environment in the given time period."
-msgstr ""
+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 ""
+msgstr "å°æ–¼åœ¨çµ¦å®šæ™‚間內部署的所有管ç†è¨Šæ¯ç³»çµ±ï¼Œå¾žåˆä½µè«‹æ±‚åˆä½µåˆ°éƒ¨ç½²åˆ°æ­£å¼ç’°å¢ƒä¹‹é–“的時間中ä½æ•¸ã€‚"
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
-msgstr ""
+msgstr "從議題建立到關閉的時間中ä½æ•¸ã€‚"
msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
-msgstr ""
+msgstr "從一個關è¯è­°é¡Œçš„åˆä½µè«‹æ±‚最早æ交到該議題çµæŸçš„時間中ä½æ•¸ã€‚"
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
-msgstr ""
+msgstr "推é€åˆ°é è¨­åˆ†æ”¯çš„æ交數é‡"
msgid "ValueStreamAnalytics|Number of new issues created."
-msgstr ""
+msgstr "建立新議題的數é‡"
msgid "ValueStreamAnalytics|Percentage of deployments that cause an incident in production."
-msgstr ""
+msgstr "在正å¼ç’°å¢ƒä¸­å°Žè‡´éƒ¨ç½²äº‹æ•…的百分比。"
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr "顯示從 %{createdAfter} 到 %{createdBefore} “%{groupName}â€ç¾¤çµ„å’Œ %{projectsCount} çš„ %{selectedSubjectFilterText} 與 %{labelsCount}"
-msgid "ValueStreamAnalytics|Shows %{selectedFiltersDescription} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} and %{labelsCount} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr "顯示從 %{createdAfter} 到 %{createdBefore} “%{groupName}†群組的 %{selectedSubjectFilterText} 和 %{labelsCount}"
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' and %{projectsCount} from %{createdAfter} to %{createdBefore}"
+msgstr "顯示從 %{createdAfter} 到 %{createdBefore} '%{groupName}' 群組 的 %{selectedSubjectFilterText} 和 %{projectsCount} "
+
+msgid "ValueStreamAnalytics|Shows %{selectedSubjectFilterText} for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
+msgstr "顯示從 %{createdAfter} 到 %{createdBefore} 群組“%{groupName}â€çš„ %{selectedSubjectFilterText}"
msgid "ValueStreamAnalytics|Tasks by type"
-msgstr ""
+msgstr "按類型劃分的任務"
msgid "ValueStreamAnalytics|There was an error while fetching value stream analytics %{requestTypeName} data."
-msgstr ""
+msgstr "å–得價值æµåˆ†æž %{requestTypeName} 資料時出ç¾éŒ¯èª¤ã€‚"
msgid "ValueStreamAnalytics|Total number of deploys to production."
-msgstr ""
+msgstr "æ­£å¼ç’°å¢ƒéƒ¨ç½²çš„總數。"
msgid "ValueStreamAnalytics|Value stream"
-msgstr ""
+msgstr "價值æµ"
msgid "ValueStreamEvent|Items in stage"
-msgstr ""
+msgstr "階段中的事項"
msgid "ValueStreamEvent|Stage time (median)"
-msgstr ""
+msgstr "階段時間(中ä½æ•¸ï¼‰"
msgid "ValueStreamEvent|Start"
-msgstr ""
+msgstr "開始"
msgid "ValueStreamEvent|Stop"
-msgstr ""
+msgstr "åœæ­¢"
msgid "ValueStream|The Default Value Stream cannot be deleted"
-msgstr ""
+msgstr "é è¨­åƒ¹å€¼æµä¸å¯åˆªé™¤"
msgid "Values that contain the %{codeStart}$%{codeEnd} character can be considered a variable reference and expanded. %{docsLinkStart}Learn more.%{docsLinkEnd}"
-msgstr ""
+msgstr "åŒ…å« %{codeStart}$%{codeEnd} 字元的值å¯ä»¥è¢«è¦–為變數引用並進行擴展。%{docsLinkStart}了解更多。%{docsLinkEnd}"
msgid "Variable"
-msgstr ""
+msgstr "變數"
msgid "Variable will be masked in job logs."
-msgstr ""
+msgstr "變數值將在作業日誌中被隱è—。"
msgid "Variables"
-msgstr ""
+msgstr "變數"
msgid "Variables can be:"
-msgstr ""
+msgstr "變數å¯ä»¥æ˜¯ï¼š"
msgid "Variables store information, like passwords and secret keys, that you can use in job scripts."
-msgstr ""
+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 ""
+msgstr "變數儲存訊æ¯ï¼Œå¦‚密碼和金鑰,您å¯ä»¥åœ¨ä½œæ¥­è…³æœ¬ä¸­ä½¿ç”¨ã€‚實例上的所有專案都å¯ä»¥ä½¿ç”¨é€™äº›è®Šæ•¸ã€‚"
msgid "Various container registry settings."
-msgstr ""
+msgstr "容器映åƒåº«ç›¸é—œè¨­å®šã€‚"
msgid "Various email settings."
-msgstr ""
+msgstr "é›»å­éƒµä»¶ç›¸é—œè¨­å®š"
msgid "Various settings that affect GitLab performance."
-msgstr ""
+msgstr "影響GitLab效能相關設定。"
msgid "Verification status"
-msgstr ""
+msgstr "驗證狀態"
msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity."
-msgstr ""
+msgstr "æµæ°´ç·šå¤±æ•—?為了防止 GitLab 垃圾郵件和濫用,我們è¦æ±‚您使用有效的付款方å¼é©—證您的身份。"
msgid "VerificationReminder|Until then, shared runners will be unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
-msgstr ""
+msgstr "VerificationReminder|在此之å‰ï¼Œå…±ç”¨åŸ·è¡Œå™¨å°‡ä¸å¯ä½¿ç”¨ã€‚ %{validateLinkStart}驗證您的帳號%{validateLinkEnd} 或 %{docsLinkStart}使用您自己的執行器%{docsLinkEnd}。"
msgid "VerificationReminder|Your account has been validated"
-msgstr ""
+msgstr "您的帳號已通éŽé©—證。"
msgid "VerificationReminder|You’ll now be able to take advantage of free CI/CD minutes on shared runners."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥åœ¨å…±äº«åŸ·è¡Œå™¨åˆ©ç”¨å…費的 CI/CD 時數。"
msgid "Verified"
-msgstr ""
+msgstr "已驗證"
msgid "Verify SAML Configuration"
-msgstr ""
+msgstr "驗證SAML設定"
msgid "Verify code"
-msgstr ""
+msgstr "驗證碼"
msgid "Verify configuration"
-msgstr ""
+msgstr "驗證設定"
msgid "Version"
-msgstr ""
+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 "%{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 "%{report_type} 報告類型的 %{report_version} 版本已ä¸è¢«æ”¯æ´ ,此報告類型支æ´çš„版本是:%{supported_schema_versions}。 GitLab 將嘗試根據此報告類型的最早支æ´ç‰ˆæœ¬é©—證此報告並顯示所有錯誤,但ä¸æœƒç²å–報告"
msgid "Version %{versionNumber}"
-msgstr ""
+msgstr "版本 %{versionNumber}"
msgid "Version %{versionNumber} (latest)"
-msgstr ""
+msgstr "版本 %{versionNumber} (最新)"
msgid "VersionCheck|Up to date"
-msgstr ""
+msgstr "最新"
msgid "VersionCheck|Update ASAP"
-msgstr ""
+msgstr "盡快更新"
msgid "VersionCheck|Update available"
-msgstr ""
+msgstr "å¯ç”¨æ›´æ–°"
msgid "VersionCheck|Your GitLab Version"
-msgstr ""
+msgstr "您的 GitLab 版本"
msgid "View Stage: %{title}"
-msgstr ""
+msgstr "查看階段期: %{title}"
msgid "View alert details at"
-msgstr ""
+msgstr "查看警報詳細訊æ¯æ–¼"
msgid "View alert details."
-msgstr ""
+msgstr "查看警報詳細訊æ¯ã€‚"
msgid "View all environments."
-msgstr ""
+msgstr "查看所有環境。"
msgid "View all issues"
-msgstr ""
+msgstr "查看所有議題"
msgid "View all personal projects"
-msgstr ""
+msgstr "查看所有個人的專案"
msgid "View blame"
-msgstr ""
+msgstr "查看責任歸屬(blame)"
msgid "View blame prior to this change"
-msgstr ""
+msgstr "在該變更之å‰æª¢è¦–責任歸屬(blame)"
msgid "View chart"
msgid_plural "View charts"
-msgstr[0] ""
+msgstr[0] "查看圖表"
msgid "View dependency details for your project"
-msgstr ""
+msgstr "查看您專案的ä¾è³´è©³ç´°è¨Šæ¯"
msgid "View deployment"
-msgstr ""
+msgstr "查看部署"
msgid "View details"
-msgstr ""
+msgstr "查看詳細訊æ¯"
msgid "View details: %{details_url}"
-msgstr ""
+msgstr "查看詳細訊æ¯: %{details_url}"
msgid "View documentation"
-msgstr ""
+msgstr "查看文件"
msgid "View eligible approvers"
-msgstr ""
+msgstr "查看具備相關資格的核准者"
msgid "View epics list"
-msgstr ""
+msgstr "查看å²è©©åˆ—表"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
-msgstr[0] ""
+msgstr[0] "查看%d項展示產物"
msgid "View file @ "
-msgstr ""
+msgstr "ç€è¦½æ–‡ä»¶ @ "
msgid "View file @ %{commitSha}"
-msgstr ""
+msgstr "查看文件@%{commitSha}"
msgid "View full dashboard"
-msgstr ""
+msgstr "查看完整儀表æ¿"
msgid "View full log"
-msgstr ""
+msgstr "查看完整日誌"
msgid "View group in admin area"
-msgstr ""
+msgstr "在管ç†å€æŸ¥çœ‹ç¾¤çµ„"
msgid "View group labels"
-msgstr ""
+msgstr "查看群組標記"
msgid "View group pipeline usage quota"
-msgstr ""
+msgstr "查看群組æµæ°´ç·šç”¨é‡é…é¡"
msgid "View incident details at"
-msgstr ""
+msgstr "查看事件詳細訊æ¯æ–¼"
msgid "View incident details."
-msgstr ""
+msgstr "查看事件詳情。"
msgid "View incident issues."
-msgstr ""
+msgstr "查看事件議題。"
msgid "View issue"
-msgstr ""
+msgstr "查看議題"
msgid "View issues"
-msgstr ""
+msgstr "查看議題"
msgid "View it on GitLab"
-msgstr ""
+msgstr "使用GitLab查看"
msgid "View job"
-msgstr ""
+msgstr "查看作業"
msgid "View job log"
-msgstr ""
+msgstr "查看作業日誌"
msgid "View jobs"
-msgstr ""
+msgstr "查看作業"
msgid "View labels"
-msgstr ""
+msgstr "查看標記"
msgid "View log"
-msgstr ""
+msgstr "查看日誌"
msgid "View logs"
-msgstr ""
+msgstr "查看日誌"
msgid "View milestones"
-msgstr ""
+msgstr "查看里程碑"
msgid "View on %{url}"
-msgstr ""
+msgstr "在 %{url} 上查看"
msgid "View open merge request"
-msgstr ""
+msgstr "查看待處ç†çš„åˆä½µè«‹æ±‚"
msgid "View page @ "
-msgstr ""
+msgstr "查看é é¢ @ "
msgid "View performance dashboard."
-msgstr ""
+msgstr "查看性能儀表æ¿ã€‚"
msgid "View project"
-msgstr ""
+msgstr "檢視專案"
msgid "View project in admin area"
-msgstr ""
+msgstr "在管ç†å€æŸ¥çœ‹å°ˆæ¡ˆ"
msgid "View project labels"
-msgstr ""
+msgstr "查看專案標記"
msgid "View public GPG key"
msgid_plural "View public GPG keys"
-msgstr[0] ""
+msgstr[0] "查看公開 GPG 金鑰"
msgid "View replaced file @ "
-msgstr ""
+msgstr "查看å–代文件 @ "
msgid "View seat usage"
-msgstr ""
+msgstr "查看席次使用情æ³"
msgid "View supported languages and frameworks"
-msgstr ""
+msgstr "查看支æ´çš„語言和框架"
msgid "View the %{code_open}last_activity_at%{code_close} attribute for %{project_link} using the %{projects_api_link}."
-msgstr ""
+msgstr "使用 %{projects_api_link} 查看 %{project_link} 的 %{code_open}last_activity_at%{code_close} 屬性。"
msgid "View the documentation"
-msgstr ""
+msgstr "查看文件"
msgid "View the latest successful deployment to this environment"
-msgstr ""
+msgstr "檢視此環境中最新一次的æˆåŠŸéƒ¨ç½²"
msgid "View the performance dashboard at"
-msgstr ""
+msgstr "查看性能儀表æ¿æ–¼"
msgid "View usage details"
-msgstr ""
+msgstr "查看使用詳情"
msgid "View users statistics"
-msgstr ""
+msgstr "查看使用者統計"
msgid "Viewed"
-msgstr ""
+msgstr "已查看"
msgid "Viewing commit"
-msgstr ""
+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 "使用統一的 URL 無法從主站查看專案和設計資料,直接存å–次è¦ç«™é»žã€‚%{geo_help_url}"
msgid "Violation"
-msgstr ""
+msgstr "é•è¦"
msgid "Visibility"
-msgstr ""
+msgstr "å¯è¦‹æ€§"
msgid "Visibility and access controls"
-msgstr ""
+msgstr "å¯è¦‹æ€§èˆ‡å­˜å–控制"
msgid "Visibility level"
-msgstr ""
+msgstr "å¯è¦‹æ€§ç´šåˆ¥"
msgid "Visibility level:"
-msgstr ""
+msgstr "å¯è¦‹æ€§ç´šåˆ¥:"
msgid "Visibility settings have been disabled by the administrator."
-msgstr ""
+msgstr "å¯è¦‹æ€§è¨­å®šå·²è¢«ç®¡ç†å“¡åœç”¨ã€‚"
msgid "Visibility, project features, permissions"
-msgstr ""
+msgstr "å¯è¦‹æ€§ï¼Œå°ˆæ¡ˆåŠŸèƒ½ï¼Œæ¬Šé™"
msgid "Visibility:"
-msgstr ""
+msgstr "å¯è¦‹æ€§ï¼š"
msgid "VisibilityLevel|Internal"
-msgstr ""
+msgstr "內部"
msgid "VisibilityLevel|Private"
-msgstr ""
+msgstr "ç§æœ‰"
msgid "VisibilityLevel|Public"
-msgstr ""
+msgstr "公開"
msgid "VisibilityLevel|Unknown"
-msgstr ""
+msgstr "未知"
msgid "Visual Studio Code (HTTPS)"
-msgstr ""
+msgstr "Visual Studio Code (HTTPS)"
msgid "Visual Studio Code (SSH)"
-msgstr ""
+msgstr "Visual Studio Code (SSH)"
msgid "Vulnerabilities"
-msgstr ""
+msgstr "æ¼æ´ž"
msgid "Vulnerabilities over time"
-msgstr ""
+msgstr "æ¼æ´žè¶¨å‹¢åœ–"
msgid "Vulnerability"
-msgstr ""
+msgstr "æ¼æ´ž"
msgid "Vulnerability Report"
-msgstr ""
+msgstr "æ¼æ´žå ±å‘Š"
msgid "Vulnerability remediated. Review before resolving."
-msgstr ""
+msgstr "æ¼æ´žå·²ä¿®è£œã€‚設為解決之å‰è«‹å…ˆé€²è¡Œå¯©æ ¸ã€‚"
msgid "Vulnerability report"
-msgstr ""
+msgstr "æ¼æ´žå ±å‘Š"
msgid "Vulnerability resolved in %{branch}"
-msgstr ""
+msgstr "æ¼æ´žå·²åœ¨%{branch}分支上解決"
msgid "Vulnerability resolved in the default branch"
-msgstr ""
+msgstr "æ¼æ´žå·²åœ¨é è¨­åˆ†æ”¯ä¸Šè§£æ±º"
msgid "VulnerabilityChart|%{formattedStartDate} to today"
-msgstr ""
+msgstr "%{formattedStartDate}到今天"
msgid "VulnerabilityChart|Severity"
-msgstr ""
+msgstr "åš´é‡ç´šåˆ¥"
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "ç”±%{user}%{statusStart}確èª%{statusEnd}æ–¼%{timeago}"
msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
+msgstr "ç”±æµæ°´ç·š%{pipelineLink}æ–¼%{timeago}%{statusStart}檢測出%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "由%{user}於%{timeago}%{statusStart}忽略%{statusEnd}"
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
-msgstr ""
+msgstr "由%{user}於%{timeago}%{statusStart}解決%{statusEnd}"
msgid "VulnerabilityManagement|(optional) Include the solution to the vulnerability if available."
-msgstr ""
+msgstr "(å¯é¸ï¼‰åŒ…括æ¼æ´žçš„解決方案(如果有)。"
msgid "VulnerabilityManagement|A removed or remediated vulnerability"
-msgstr ""
+msgstr "已刪除或已修正的æ¼æ´ž"
msgid "VulnerabilityManagement|A true-positive and will fix"
-msgstr ""
+msgstr "真實æ¼æ´žä¸¦å°‡ä¿®å¾©"
msgid "VulnerabilityManagement|A verified true-positive vulnerability"
-msgstr ""
+msgstr "經證實的真實æ¼æ´ž"
msgid "VulnerabilityManagement|Add vulnerability finding"
-msgstr ""
+msgstr "加入æ¼æ´žç™¼ç¾"
msgid "VulnerabilityManagement|An unverified non-confirmed finding"
-msgstr ""
+msgstr "未證實的未確èªç™¼ç¾"
msgid "VulnerabilityManagement|Change status"
-msgstr ""
+msgstr "更改狀態"
msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
-msgstr ""
+msgstr "無法處ç†%{issueReference}: %{errorMessage}。"
msgid "VulnerabilityManagement|Create Jira issue"
-msgstr ""
+msgstr "建立 Jira 議題"
msgid "VulnerabilityManagement|Enter a name"
-msgstr ""
+msgstr "輸入å稱"
msgid "VulnerabilityManagement|Enter the CVE or CWE code"
-msgstr ""
+msgstr "輸入 CVE 或 CWE 編號"
msgid "VulnerabilityManagement|Enter the CVE or CWE identifier URL"
-msgstr ""
+msgstr "輸入 CVE 或 CWE 標識符 URL"
msgid "VulnerabilityManagement|Fetching linked Jira issues"
-msgstr ""
+msgstr "å–å¾—é—œè¯çš„ Jira è­°é¡Œ"
msgid "VulnerabilityManagement|Identifier code and URL are required fields"
-msgstr ""
+msgstr "識別碼和 URL 是必填字段"
msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
-msgstr ""
+msgstr "在æ¼æ´žå ±å‘Šä¸­æ‰‹å‹•åŠ å…¥æ¼æ´žé …。"
msgid "VulnerabilityManagement|Name is a required field"
-msgstr ""
+msgstr "å稱為必填"
msgid "VulnerabilityManagement|Needs triage"
-msgstr ""
+msgstr "需è¦åˆ†é¡ž"
msgid "VulnerabilityManagement|Read more about related issues"
-msgstr ""
+msgstr "閱讀更多相關議題"
msgid "VulnerabilityManagement|Related Jira issues"
-msgstr ""
+msgstr "相關 Jira å•é¡Œ"
msgid "VulnerabilityManagement|Requires assessment"
-msgstr ""
+msgstr "需è¦è©•ä¼°"
msgid "VulnerabilityManagement|Select a method"
-msgstr ""
+msgstr "é¸æ“‡æ–¹æ³•"
msgid "VulnerabilityManagement|Select a severity level"
-msgstr ""
+msgstr "é¸æ“‡åš´é‡æ€§ç´šåˆ¥"
msgid "VulnerabilityManagement|Select a status"
-msgstr ""
+msgstr "é¸æ“‡ç‹€æ…‹"
msgid "VulnerabilityManagement|Severity is a required field"
-msgstr ""
+msgstr "åš´é‡æ€§ç´šåˆ¥ç‚ºå¿…å¡«"
msgid "VulnerabilityManagement|Something went wrong while creating vulnerability"
-msgstr ""
+msgstr "建立æ¼æ´žè¨Šæ¯æ™‚發生錯誤。"
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
-msgstr ""
+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 ""
+msgstr "嘗試å–得相關的 Jira 議題時發生錯誤。請檢查 %{linkStart}Jira æ•´åˆè¨­å®š%{linkEnd} 並é‡è©¦ã€‚"
msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
-msgstr ""
+msgstr "試圖é‡æ–°æ•´ç†æ¼æ´žæ™‚發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
-msgstr ""
+msgstr "試圖å–å¾—æ¼æ´žæ­·å²æ™‚發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
-msgstr ""
+msgstr "試圖ä¿å­˜ç•™è¨€æ™‚發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
-msgstr ""
+msgstr "嘗試å–消與議題的連çµæ™‚發生錯誤。請ç¨å¾Œå†è©¦ã€‚"
msgid "VulnerabilityManagement|Something went wrong, could not get user."
-msgstr ""
+msgstr "發生錯誤,無法讀å–使用者。"
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
-msgstr ""
+msgstr "發生錯誤,無法更新æ¼æ´žç‹€æ…‹ã€‚"
msgid "VulnerabilityManagement|Status is a required field"
-msgstr ""
+msgstr "狀態為必填"
msgid "VulnerabilityManagement|Submit vulnerability"
-msgstr ""
+msgstr "æ交æ¼æ´žè¨Šæ¯"
msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
-msgstr ""
+msgstr "總çµã€è©³ç´°èªªæ˜Žã€é‡ç¾æ­¥é©Ÿç­‰"
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
-msgstr ""
+msgstr "已驗證為修復或緩解"
msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
-msgstr ""
+msgstr "æ¼æ´žå稱或類型。例如:跨站腳本"
msgid "VulnerabilityManagement|Will not fix or a false-positive"
-msgstr ""
+msgstr "å°‡ä¸ä¿®å¾©æˆ–為誤報"
msgid "VulnerabilityManagement|invalid issue link or ID"
-msgstr ""
+msgstr "無效的議題連çµæˆ–ID"
msgid "VulnerabilityStatusTypes|All statuses"
-msgstr ""
+msgstr "所有狀態"
msgid "VulnerabilityStatusTypes|Confirmed"
-msgstr ""
+msgstr "已確èª"
msgid "VulnerabilityStatusTypes|Dismissed"
-msgstr ""
+msgstr "已忽略"
msgid "VulnerabilityStatusTypes|Needs triage"
-msgstr ""
+msgstr "需è¦åˆ†é¡ž"
msgid "VulnerabilityStatusTypes|Resolved"
-msgstr ""
+msgstr "已解決"
msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
-msgstr ""
+msgstr "%{scannerName} (版本 %{scannerVersion})"
msgid "Vulnerability|Activity"
-msgstr ""
+msgstr "å‹•æ…‹"
msgid "Vulnerability|Actual Response"
-msgstr ""
+msgstr "實際回應"
msgid "Vulnerability|Actual received response is the one received when this fault was detected"
-msgstr ""
+msgstr "實際收到的回應是檢測到此缺陷時收到的回應"
msgid "Vulnerability|Add another identifier"
-msgstr ""
+msgstr "加入å¦ä¸€å€‹æ¨™è­˜ç¬¦"
msgid "Vulnerability|Additional Info"
-msgstr ""
+msgstr "其它訊æ¯"
msgid "Vulnerability|Bug Bounty"
-msgstr ""
+msgstr "æ¼æ´žè³žé‡‘(Bug Bounty)"
msgid "Vulnerability|CVSS v3"
-msgstr ""
+msgstr "CVSS v3"
msgid "Vulnerability|Class"
-msgstr ""
+msgstr "é¡žåž‹"
msgid "Vulnerability|Cluster"
-msgstr ""
+msgstr "å¢é›†"
msgid "Vulnerability|Code Review"
-msgstr ""
+msgstr "程å¼ç¢¼å¯©é–±"
msgid "Vulnerability|Comments"
-msgstr ""
+msgstr "註釋"
msgid "Vulnerability|Crash address"
-msgstr ""
+msgstr "當機(Crash)地å€"
msgid "Vulnerability|Crash state"
-msgstr ""
+msgstr "當機(Crash)狀態"
msgid "Vulnerability|Crash type"
-msgstr ""
+msgstr "當機(Crash)類型"
msgid "Vulnerability|Description"
-msgstr ""
+msgstr "說明"
msgid "Vulnerability|Details"
-msgstr ""
+msgstr "詳情"
msgid "Vulnerability|Detected"
-msgstr ""
+msgstr "檢測到"
msgid "Vulnerability|Detection method"
-msgstr ""
+msgstr "檢測方法"
msgid "Vulnerability|Download"
-msgstr ""
+msgstr "下載"
msgid "Vulnerability|Enter the associated CVE or CWE entries for this vulnerability."
-msgstr ""
+msgstr "輸入此æ¼æ´žçš„é—œè¯ CVE 或 CWE æ¢ç›®ã€‚"
msgid "Vulnerability|Evidence"
-msgstr ""
+msgstr "證據"
msgid "Vulnerability|External Security Report"
-msgstr ""
+msgstr "外部安全報告"
msgid "Vulnerability|False positive detected"
-msgstr ""
+msgstr "檢測到誤報"
msgid "Vulnerability|File"
-msgstr ""
+msgstr "文件"
msgid "Vulnerability|GitLab Security Report"
-msgstr ""
+msgstr "GitLab 安全報告"
msgid "Vulnerability|Identifier"
-msgstr ""
+msgstr "標識"
msgid "Vulnerability|Identifier URL"
-msgstr ""
+msgstr "標識 URL"
msgid "Vulnerability|Identifier code"
-msgstr ""
+msgstr "識別碼"
msgid "Vulnerability|Identifiers"
-msgstr ""
+msgstr "標識"
msgid "Vulnerability|Image"
-msgstr ""
+msgstr "映åƒ"
msgid "Vulnerability|Information related to how the vulnerability was discovered and its impact on the system."
-msgstr ""
+msgstr "與如何發ç¾æ¼æ´žåŠå…¶å°ç³»çµ±çš„影響有關的ira æ¯ã€‚"
msgid "Vulnerability|Learn more about this vulnerability and the best way to resolve it."
-msgstr ""
+msgstr "詳細了解此æ¼æ´žä»¥åŠè§£æ±ºæ­¤æ¼æ´žçš„最佳方法。"
msgid "Vulnerability|Links"
-msgstr ""
+msgstr "連çµ"
msgid "Vulnerability|Method"
-msgstr ""
+msgstr "方法"
msgid "Vulnerability|Namespace"
-msgstr ""
+msgstr "命å空間"
msgid "Vulnerability|Project"
-msgstr ""
+msgstr "專案"
msgid "Vulnerability|Remove identifier row"
-msgstr ""
+msgstr "移除標識符行"
msgid "Vulnerability|Reproduction Assets"
-msgstr ""
+msgstr "é‡è£½è³‡ç”¢"
msgid "Vulnerability|Request"
-msgstr ""
+msgstr "請求"
msgid "Vulnerability|Request/Response"
-msgstr ""
+msgstr "請求/回應"
msgid "Vulnerability|Scanner Provider"
-msgstr ""
+msgstr "掃瞄工具æ供者"
msgid "Vulnerability|Security Audit"
-msgstr ""
+msgstr "安全審計"
msgid "Vulnerability|Select a severity"
-msgstr ""
+msgstr "é¸æ“‡åš´é‡ç¨‹åº¦"
msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
-msgstr ""
+msgstr "根據您å¯ä»¥ç²å¾—的訊æ¯è¨­å®šæ¼æ´žç™¼ç¾çš„狀態。"
msgid "Vulnerability|Severity"
-msgstr ""
+msgstr "åš´é‡ç´šåˆ¥"
msgid "Vulnerability|Status"
-msgstr ""
+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 ""
+msgstr "掃瞄器確定此æ¼æ´žç‚ºèª¤å ±ã€‚在更改其狀態之å‰é©—證評估。 %{linkStart}了解有關誤報檢測的更多訊æ¯ã€‚%{linkEnd}"
msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
-msgstr ""
+msgstr "未修改的回應是未å°è«‹æ±‚進行任何更改的原始回應"
msgid "Vulnerability|Tool"
-msgstr ""
+msgstr "工具"
msgid "Vulnerability|Training"
-msgstr ""
+msgstr "培訓"
msgid "Vulnerability|Training not available for this vulnerability."
-msgstr ""
+msgstr "沒有é‡å°æ­¤æ¼æ´žçš„培訓。"
msgid "Vulnerability|Unmodified Response"
-msgstr ""
+msgstr "未修改的回應"
msgid "Vulnerability|View training"
-msgstr ""
+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 ""
+msgstr "警告:此程å¼ç¢¼ç‰‡æ®µåŒ…å«å¯èƒ½ç”¨æ–¼æŽ©è“‹æƒ¡æ„行為的隱è—文件,仿製(clone)和執行其中的程å¼ç¢¼éœ€è¦è¬¹æ…Žã€‚"
msgid "Wait for the file to load to copy its contents"
-msgstr ""
+msgstr "等待文件載入以複製其內容"
msgid "Waiting for approval"
-msgstr ""
+msgstr "等待核准"
msgid "Waiting for merge (open and assigned)"
-msgstr ""
+msgstr "等待åˆä½µ(開啟和已指派)"
msgid "Waiting for performance data"
-msgstr ""
+msgstr "等待效能資料"
msgid "Want to see the data? Please ask an administrator for access."
-msgstr ""
+msgstr "權é™ä¸è¶³ã€‚如需查看相關資料,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
msgid "Warning"
-msgstr ""
+msgstr "警告"
msgid "Warning:"
-msgstr ""
+msgstr "警告:"
msgid "Warning: Displaying this diagram might cause performance issues on this page."
-msgstr ""
+msgstr "警告:顯示此圖表å¯èƒ½æœƒå¼•èµ·é é¢çš„性能å•é¡Œã€‚"
msgid "Warning: Synchronizing LDAP removes direct members' access."
-msgstr ""
+msgstr "警告:åŒæ­¥ LDAP 會移除直接æˆå“¡çš„å­˜å–權é™ã€‚"
msgid "Watch how"
-msgstr ""
+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 ""
+msgstr "我們目å‰ç„¡æ³•å–å¾—æ­¤æµæ°´ç·šæ¨™é ­(header)的資料。"
msgid "We are currently unable to fetch data for this graph."
-msgstr ""
+msgstr "我們目å‰ç„¡æ³•å–得此圖表的資料。"
msgid "We could not determine the path to remove the epic"
-msgstr ""
+msgstr "我們無法確定移除å²è©©çš„路徑"
msgid "We could not determine the path to remove the issue"
-msgstr ""
+msgstr "我們無法確定移除議題的路徑"
msgid "We couldn't find any %{scope} matching %{term}"
-msgstr ""
+msgstr "找ä¸åˆ°ä»»ä½•ç¬¦åˆ%{term}çš„%{scope}"
msgid "We couldn't find any %{scope} matching %{term} in group %{group}"
-msgstr ""
+msgstr "我們在群組%{group}中找ä¸åˆ°èˆ‡%{scope}相符åˆçš„%{term}"
msgid "We couldn't find any %{scope} matching %{term} in project %{project}"
-msgstr ""
+msgstr "我們在專案%{project}中找ä¸åˆ°èˆ‡%{scope}相符åˆçš„%{term}"
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
-msgstr ""
+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 ""
+msgstr "我們建立了一個沙盒專案,將幫助您學習 GitLab 的基礎知識。您將通éŽè­°é¡Œé¢æ¿ä¸­çš„è­°é¡Œç²å¾—指導。您å¯ä»¥æŒ‰ç…§è‡ªå·±çš„節å¥é€šè®€é€™äº›è­°é¡Œã€‚"
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "我們在%{humanized_resource_name}檢測到潛在濫用行為。請輸入此reCAPTCHA驗證碼並繼續。"
msgid "We don't have enough data to show this stage."
-msgstr ""
+msgstr "該階段的資料ä¸è¶³ï¼Œç„¡æ³•é¡¯ç¤ºã€‚"
msgid "We have found the following errors:"
-msgstr ""
+msgstr "我們發ç¾ä»¥ä¸‹éŒ¯èª¤ï¼š"
msgid "We heard back from your device. You have been authenticated."
-msgstr ""
+msgstr "我們收到了您設備的回應。您已通éŽèº«ä»½é©—證。"
msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
-msgstr ""
+msgstr "我們邀請您加入 %{featureLinkStart}請求功能%{featureLinkEnd}, %{bugLinkStart}報告錯誤%{bugLinkEnd} 或 %{feedbackLinkStart}分享回饋%{feedbackLinkEnd}"
msgid "We recommend a work email address."
-msgstr ""
-
-msgid "We recommend cloud-based mobile authenticator apps such as Authy, Duo Mobile, and LastPass. They can restore access if you lose your hardware device."
-msgstr ""
+msgstr "我們推薦一個工作電å­éƒµä»¶åœ°å€ã€‚"
msgid "We recommend leaving all SAST analyzers enabled"
-msgstr ""
+msgstr "我們建議啟用所有 SAST 分æžå™¨"
msgid "We recommend that you buy additional Pipeline minutes to avoid any interruption of service."
-msgstr ""
+msgstr "我們建議您購買更多的æµæ°´ç·šæ™‚間,以é¿å…任何æœå‹™ä¸­æ–·ã€‚"
msgid "We recommend that you buy additional Pipeline minutes to resume normal service."
-msgstr ""
+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 ""
+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 "我們嘗試於%{expires_on}自動將%{strong}%{namespace_name}%{strong_close}上您的訂閱進行續訂,但是出ç¾äº†å•é¡Œã€‚因此您的訂閱已é™ç´šç‚ºå…費計劃。您的資料是ä»ç„¶æ˜¯å®‰å…¨çš„。我們建議您檢查付款方å¼ä¸¦èˆ‡æˆ‘們的支æ´åœ˜éšŠè¯çµ¡(%{support_link})。他們將很會å”助您完æˆçºŒè¨‚。"
msgid "We want to be sure it is you, please confirm you are not a robot."
-msgstr ""
+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 ""
+msgstr "æˆ‘å€‘æƒ³è®“æ‚¨çŸ¥é“ %{username} 已被 %{scope} å°éŽ–,因為他們在 %{within_minutes} 分é˜å…§ä¸‹è¼‰äº†è¶…éŽ %{max_project_downloads} 個專案版本庫。"
msgid "We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders."
-msgstr ""
+msgstr "我們會通知 %{inviter} 您拒絕了他們加入 GitLab 的邀請。您將ä¸æœƒå†æŽ¥æ”¶æ醒。"
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 "您的 GitLab Enterprise Edition %{plan_name} 已經接近使用者上é™ï¼Œç›®å‰æ‚¨æœ‰ %{active_user_count} 個啟用的使用者,已接近é™åˆ¶çš„ %{maximum_user_count} 人。"
msgid "We'll continuously validate your pipeline configuration. The validation results will appear here."
-msgstr ""
+msgstr "我們將ä¸æ–·é©—證您的æµæ°´ç·šè¨­å®šã€‚é©—è­‰çµæžœå°‡é¡¯ç¤ºåœ¨æ­¤è™•ã€‚"
msgid "We'll use this to help surface the right features and information to you."
-msgstr ""
+msgstr "我們將使用它來幫助å‘您展示正確的功能和訊æ¯ã€‚"
msgid "We're experiencing difficulties and this tab content is currently unavailable."
-msgstr ""
+msgstr "我們é‡åˆ°äº†å›°é›£ï¼Œæ­¤æ¨™ç±¤é å…§å®¹ç›®å‰ä¸å¯ç”¨ã€‚"
msgid "We've detected some unusual activity"
-msgstr ""
+msgstr "我們檢測到一些異常活動"
msgid "We've detected unusual activity"
-msgstr ""
+msgstr "我們檢測到異常活動"
msgid "We've found no vulnerabilities"
-msgstr ""
+msgstr "未發ç¾å®‰å…¨æ¼æ´ž"
msgid "Web IDE"
-msgstr ""
+msgstr "Web IDE"
msgid "Web Terminal"
-msgstr ""
+msgstr "Web終端"
msgid "Web terminal"
-msgstr ""
+msgstr "Web終端"
msgid "WebAuthn Devices (%{length})"
-msgstr ""
+msgstr "WebAuthn設備 (%{length})"
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
-msgstr ""
+msgstr "WebAuthnåªæ”¯æ´å•Ÿç”¨äº†HTTPS的網站。您å¯ä»¥è¯çµ¡ç®¡ç†å“¡ç²å¾—更多訊æ¯"
msgid "WebIDE|Fork project"
-msgstr ""
+msgstr "分å‰å°ˆæ¡ˆ"
msgid "WebIDE|Go to fork"
-msgstr ""
+msgstr "å‰å¾€åˆ†å‰"
msgid "WebIDE|Merge request"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚"
msgid "WebIDE|This project does not accept unsigned commits."
-msgstr ""
+msgstr "此專案ä¸æŽ¥å—未簽åçš„æ交。"
msgid "WebIDE|This project does not accept unsigned commits. You can’t commit changes through the Web IDE."
-msgstr ""
+msgstr "此專案ä¸æŽ¥å—未簽åçš„æäº¤ï¼Œæ‚¨ç„¡æ³•é€šéŽ Web IDE æ交更改。"
msgid "WebIDE|You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+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 ""
+msgstr "ä¸èƒ½ç›´æŽ¥åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç·¨è¼¯æ–‡ä»¶ï¼Œå‰å¾€æ‚¨çš„分å‰(fork)並æ交包å«æ›´æ”¹çš„åˆä½µè«‹æ±‚。"
msgid "WebIDE|You need permission to edit files directly in this project."
-msgstr ""
+msgstr "您需è¦æ¬Šé™æ‰èƒ½ç›´æŽ¥åœ¨æ­¤å°ˆæ¡ˆä¸­ç·¨è¼¯æ–‡ä»¶ã€‚"
msgid "WebexTeamsService|Send notifications about project events to Webex Teams."
-msgstr ""
+msgstr "å‘ Webex Teams 發é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。"
msgid "WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}"
-msgstr ""
+msgstr "å‘ Webex Teams å°è©±ç™¼é€æœ‰é—œå°ˆæ¡ˆäº‹ä»¶çš„通知。 %{docs_link}"
msgid "WebexTeamsService|Webex Teams"
-msgstr ""
+msgstr "Webex 團隊"
msgid "Webhook"
-msgstr ""
+msgstr "Webhook"
msgid "Webhook Logs"
-msgstr ""
+msgstr "Webhook日誌"
msgid "Webhook Settings"
-msgstr ""
+msgstr "Webhook設定"
msgid "Webhook events will be displayed here."
-msgstr ""
+msgstr "Webhook事件將在這裡顯示。"
msgid "Webhook:"
-msgstr ""
+msgstr "Webhook:"
msgid "Webhooks"
-msgstr ""
+msgstr "Webhooks"
msgid "Webhooks Help"
-msgstr ""
+msgstr "Webhooks幫助"
msgid "Webhooks|A comment is added to a confidential issue."
-msgstr ""
+msgstr "一æ¢ç•™è¨€è¢«åŠ å…¥åˆ°æ©Ÿå¯†è­°é¡Œã€‚"
msgid "Webhooks|A comment is added to an issue or merge request."
-msgstr ""
+msgstr "一æ¢ç•™è¨€è¢«åŠ å…¥è­°é¡Œæˆ–åˆä½µè«‹æ±‚。"
msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
-msgstr ""
+msgstr "已建立ã€æ›´æ–°ã€é—œé–‰æˆ–é‡æ–°é–‹å•Ÿæ©Ÿå¯†è­°é¡Œã€‚"
msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
-msgstr ""
+msgstr "部署開始ã€å®Œæˆã€å¤±æ•—或被å–消。"
msgid "Webhooks|A feature flag is turned on or off."
-msgstr ""
+msgstr "一個功能標誌已打開或關閉。"
msgid "Webhooks|A group member is created, updated, or removed."
-msgstr ""
+msgstr "已建立ã€æ›´æ–°æˆ–移除群組æˆå“¡ã€‚"
msgid "Webhooks|A job's status changes."
-msgstr ""
+msgstr "作業的狀態發生變化。"
msgid "Webhooks|A merge request is created, updated, or merged."
-msgstr ""
+msgstr "建立ã€æ›´æ–°æˆ–åˆä½µåˆä½µè«‹æ±‚。"
msgid "Webhooks|A new tag is pushed to the repository."
-msgstr ""
+msgstr "新標籤被推é€åˆ°ç‰ˆæœ¬åº«ã€‚"
msgid "Webhooks|A pipeline's status changes."
-msgstr ""
+msgstr "æµæ°´ç·šçš„狀態變更。"
msgid "Webhooks|A release is created or updated."
-msgstr ""
+msgstr "已建立或更新發布。"
msgid "Webhooks|A subgroup is created or removed."
-msgstr ""
+msgstr "已建立或移除å­ç¾¤çµ„。"
msgid "Webhooks|A wiki page is created or updated."
-msgstr ""
+msgstr "已建立或更新 wiki é é¢ã€‚"
msgid "Webhooks|An issue is created, updated, closed, or reopened."
-msgstr ""
+msgstr "已建立ã€æ›´æ–°ã€é—œé–‰æˆ–é‡æ–°é–‹å•Ÿè­°é¡Œã€‚"
msgid "Webhooks|Are you sure you want to delete this group hook?"
-msgstr ""
+msgstr "您確實需è¦åˆªé™¤é€™å€‹ç¾¤çµ„ hook 嗎?"
msgid "Webhooks|Are you sure you want to delete this project hook?"
-msgstr ""
+msgstr "您確實需è¦åˆªé™¤é€™å€‹å°ˆæ¡ˆ hook 嗎?"
msgid "Webhooks|Are you sure you want to delete this webhook?"
-msgstr ""
+msgstr "您確實需è¦åˆªé™¤é€™å€‹ webhook 嗎?"
msgid "Webhooks|Comments"
-msgstr ""
+msgstr "留言"
msgid "Webhooks|Confidential comments"
-msgstr ""
+msgstr "機密留言"
msgid "Webhooks|Confidential issues events"
-msgstr ""
+msgstr "機密議題事件"
msgid "Webhooks|Delete webhook"
-msgstr ""
+msgstr "刪除 webhook"
msgid "Webhooks|Deployment events"
-msgstr ""
+msgstr "部署事件"
msgid "Webhooks|Enable SSL verification"
-msgstr ""
+msgstr "啟用SSL驗證"
msgid "Webhooks|Failed to connect"
-msgstr ""
+msgstr "連接失敗"
msgid "Webhooks|Fails to connect"
-msgstr ""
+msgstr "連接失敗"
msgid "Webhooks|Feature flag events"
-msgstr ""
+msgstr "功能標誌事件"
msgid "Webhooks|Issues events"
-msgstr ""
+msgstr "議題事件"
msgid "Webhooks|Job events"
-msgstr ""
+msgstr "作業事件"
msgid "Webhooks|Member events"
-msgstr ""
+msgstr "æˆå“¡äº‹ä»¶"
msgid "Webhooks|Merge request events"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚事件"
msgid "Webhooks|Pipeline events"
-msgstr ""
+msgstr "æµæ°´ç·šäº‹ä»¶"
msgid "Webhooks|Push events"
-msgstr ""
+msgstr "推é€äº‹ä»¶"
msgid "Webhooks|Push to the repository."
-msgstr ""
+msgstr "推é€åˆ°ç‰ˆæœ¬åº«ã€‚"
msgid "Webhooks|Releases events"
-msgstr ""
+msgstr "發布事件"
msgid "Webhooks|SSL verification"
-msgstr ""
+msgstr "SSLé©—è­‰"
msgid "Webhooks|Secret token"
-msgstr ""
+msgstr "Secret 令牌"
msgid "Webhooks|Subgroup events"
-msgstr ""
+msgstr "å­ç¾¤çµ„事件"
msgid "Webhooks|Tag push events"
-msgstr ""
+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 ""
+msgstr "Webhook %{help_link_start}連接失敗%{help_link_end},將在 %{retry_time} å…§é‡è©¦ã€‚è‹¥è¦é‡æ–°å•Ÿç”¨ï¼Œè«‹æª¢æŸ¥ %{strong_start}最近事件%{strong_end} å–得錯誤詳情,然後在下方測試您的設定。"
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 "Webhook 連接失敗,已åœç”¨ã€‚è¦é‡æ–°å•Ÿç”¨å®ƒï¼Œè«‹æª¢æŸ¥ %{strong_start}最近的事件%{strong_end} 以å–得錯誤詳細訊æ¯ï¼Œç„¶å¾Œåœ¨ä¸‹æ–¹æ¸¬è©¦æ‚¨çš„設定。"
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 "Webhook æ¯åˆ†é˜å·²è¢«è§¸ç™¼è¶…éŽ %{limit} 次,ç¾åœ¨å·²è¢«åœç”¨ã€‚è‹¥è¦é‡æ–°å•Ÿç”¨æ­¤ Webhook,請修復在 %{strong_start}最近事件%{strong_end} 中顯示的å•é¡Œï¼Œç„¶å¾Œé‡æ–°æ¸¬è©¦æ‚¨çš„設定。如果您需è¦å¹«åŠ©é‡æ–°å•Ÿç”¨æ‚¨çš„ Webhook,%{support_link_start}è«‹è¯çµ¡æŠ€è¡“支æ´%{support_link_end}。"
msgid "Webhooks|Trigger"
-msgstr ""
+msgstr "觸發器"
msgid "Webhooks|URL"
-msgstr ""
+msgstr "網å€"
msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
-msgstr ""
+msgstr "如果 URL 包å«ä¸€å€‹æˆ–多個特殊字元,則必須進行百分號編碼。"
msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
-msgstr ""
+msgstr "用於驗證接收到的有效資訊。與 %{code_start}X-Gitlab-Token HTTP%{code_end} 標頭中的請求一起發é€ã€‚"
msgid "Webhooks|Webhook failed to connect"
-msgstr ""
+msgstr "Webhook 連接失敗"
msgid "Webhooks|Webhook fails to connect"
-msgstr ""
+msgstr "Webhook 連接失敗"
msgid "Webhooks|Webhook was automatically disabled"
-msgstr ""
+msgstr "Webhook 被自動åœç”¨"
msgid "Webhooks|Wiki page events"
-msgstr ""
+msgstr "Wikié é¢äº‹ä»¶"
msgid "Website"
-msgstr ""
+msgstr "網站"
msgid "Website:"
-msgstr ""
+msgstr "網站:"
msgid "Wednesday"
-msgstr ""
+msgstr "星期三"
msgid "Weekday"
-msgstr ""
+msgstr "工作日"
msgid "Weeks"
-msgstr ""
+msgstr "星期"
msgid "Weight"
-msgstr ""
+msgstr "權é‡"
msgid "Weight %{weight}"
-msgstr ""
+msgstr "æ¬Šé‡ %{weight}"
msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
-msgstr ""
+msgstr "歡迎回來ï¼æ‚¨çš„帳號之å‰å› ç‚ºæ²’有活動而被å‡çµï¼Œä½†ç›®å‰å·²è¢«é‡æ–°å•Ÿå‹•ã€‚"
msgid "Welcome to GitLab"
-msgstr ""
+msgstr "歡迎來到GitLab"
msgid "Welcome to GitLab, %{first_name}!"
-msgstr ""
+msgstr "歡迎來到GitLab, %{first_name}ï¼"
msgid "Welcome to GitLab,%{br_tag}%{name}!"
-msgstr ""
+msgstr "歡迎使用 GitLab,%{br_tag}%{name}ï¼"
msgid "Welcome, %{name}!"
-msgstr ""
+msgstr "歡迎, %{name}ï¼"
msgid "What are CI/CD minutes?"
-msgstr ""
+msgstr "什麼是 CI/CD 時數?"
msgid "What are group audit events?"
-msgstr ""
+msgstr "什麼是群組審查事件?"
msgid "What are instance audit events?"
-msgstr ""
+msgstr "什麼是實例審查事件?"
msgid "What are project audit events?"
-msgstr ""
+msgstr "什麼是專案審查事件?"
+
+msgid "What are some examples?"
+msgstr "有哪些範例?"
+
+msgid "What does the setting affect?"
+msgstr "設定有什麼影響?"
msgid "What does this command do?"
-msgstr ""
+msgstr "這個指令有什麼作用?"
msgid "What is Markdown?"
-msgstr ""
+msgstr "什麼是 Markdown?"
msgid "What is listed here?"
-msgstr ""
+msgstr "這裡列出了什麼?"
msgid "What is repository mirroring?"
-msgstr ""
+msgstr "什麼是版本庫é¡åƒï¼Ÿ"
msgid "What is squashing?"
-msgstr ""
+msgstr "什麼是壓縮(squashing)?"
msgid "What templates can I create?"
-msgstr ""
+msgstr "我å¯ä»¥å»ºç«‹ä»€éº¼æ¨£çš„範本?"
msgid "What will you use this group for?"
-msgstr ""
+msgstr "您會用這個群組åšä»€éº¼ï¼Ÿ"
msgid "What would you like to do?"
-msgstr ""
+msgstr "您想è¦åšä»€éº¼ï¼Ÿ"
msgid "What's new"
-msgstr ""
+msgstr "新的功能"
msgid "When a deployment job is successful, skip older deployment jobs that are still pending."
-msgstr ""
+msgstr "部署作業æˆåŠŸæ™‚,跳éŽå°šæœªå®Œæˆçš„舊部署任務。"
msgid "When a runner is locked, it cannot be assigned to other projects"
-msgstr ""
+msgstr "當Runner被鎖定時,ä¸èƒ½å°‡å…¶åˆ†é…給其他專案"
msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
-msgstr ""
+msgstr "如果啟用,則ä¸å†æŽ¥å—ç„¡éŽæœŸæ—¥æœŸæˆ–無效éŽæœŸæ—¥æœŸçš„ SSH 金鑰。留空為無é™åˆ¶ã€‚"
msgid "When enabled, cleanup polices execute faster but put more load on Redis."
-msgstr ""
+msgstr "啟用後,清ç†æ”¿ç­–執行速度更快,但會給 Redis 帶來更多負載。"
msgid "When enabled, existing access tokens may be revoked. Leave blank for no limit."
-msgstr ""
+msgstr "啟用後,ç¾æœ‰çš„å­˜å–令牌å¯èƒ½æœƒè¢«æ’¤éŠ·ã€‚ 留空表示沒有é™åˆ¶ã€‚"
msgid "When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces."
-msgstr ""
+msgstr "啟用後,Datadog 會收集作業日誌並與æµæ°´ç·šåŸ·è¡Œè¿½è¹¤ä¸€èµ·é¡¯ç¤ºã€‚"
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
-msgstr ""
+msgstr "當é è¨­åˆ†æ”¯ä¸­çš„åˆä½µè«‹æ±‚å’Œæ交關閉時,它們引用的任何議題也會關閉。"
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
-msgstr[0] ""
+msgstr[0] "當åˆä½µè«‹æ±‚被接å—時"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
+msgstr "使用%{code_open}http://%{code_close}或%{code_open}https://%{code_close}å”議時,請æ供版本庫的實際地å€ã€‚ä¸æ”¯æ´HTTPé‡å®šå‘。"
msgid "When 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 ""
+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} 並無法訪å•è©²çµ„。"
msgid "When:"
-msgstr ""
+msgstr "當:"
msgid "Which API requests are affected?"
-msgstr ""
+msgstr "哪些API請求å—到影響?"
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 "雖然沒有發ç¾æ¼æ´žï¼Œé€™ç¨®ç¾è±¡å¾ˆç½•è¦‹ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。無論如何,建議您仔細檢查設定以確ä¿å„€è¡¨æ¿çš„設定正確。"
msgid "Who can approve?"
-msgstr ""
+msgstr "誰å¯ä»¥æ ¸å‡†ï¼Ÿ"
msgid "Who can see this group?"
-msgstr ""
+msgstr "哪些人å¯ä»¥çœ‹åˆ°é€™å€‹ç¾¤çµ„?"
msgid "Who will be able to see this group?"
-msgstr ""
+msgstr "哪些人å¯ä»¥çœ‹åˆ°é€™å€‹ç¾¤çµ„?"
msgid "Who will be using GitLab?"
-msgstr ""
+msgstr "誰將使用GitLab?"
msgid "Who will be using this GitLab subscription?"
-msgstr ""
+msgstr "誰將使用此GitLab訂閱?"
msgid "Who will be using this GitLab trial?"
-msgstr ""
+msgstr "誰將使用此GitLab試用?"
msgid "Who will be using this group?"
-msgstr ""
+msgstr "誰將使用這個群組?"
msgid "Why are you signing up? (optional)"
-msgstr ""
+msgstr "您為什麼註冊?(å¯é¸ï¼‰"
msgid "Wiki"
msgstr "Wiki"
+msgid "Wiki Page|Rich text"
+msgstr "è±å¯Œæ–‡å­—æ ¼å¼"
+
+msgid "Wiki Page|Source"
+msgstr "來æº"
+
msgid "Wiki page"
-msgstr ""
+msgstr "Wiki é é¢"
msgid "Wiki page was successfully created."
-msgstr ""
+msgstr "Wikié é¢å·²æˆåŠŸå»ºç«‹ã€‚"
msgid "Wiki page was successfully deleted."
-msgstr ""
+msgstr "Wikié é¢å·²æˆåŠŸåˆªé™¤ã€‚"
msgid "Wiki page was successfully updated."
-msgstr ""
+msgstr "Wikié é¢å·²æˆåŠŸæ›´æ–°ã€‚"
msgid "WikiClone|Clone your wiki"
-msgstr ""
+msgstr "仿製(clone)您的 wiki"
msgid "WikiClone|Git Access"
-msgstr ""
+msgstr "Git å­˜å–"
msgid "WikiClone|Install Gollum"
-msgstr ""
+msgstr "å®‰è£ Gollum"
msgid "WikiClone|Start Gollum and edit locally"
-msgstr ""
+msgstr "啟動 Gollum 並在本機編輯"
msgid "WikiEdit|There is already a page with the same title in that path."
-msgstr ""
+msgstr "在該路徑中已經有一個具有相åŒæ¨™é¡Œçš„é é¢ã€‚"
msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
-msgstr ""
+msgstr "Wiki 改進建議"
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 ""
+msgstr "åªæœ‰è©²ç¾¤çµ„çš„æˆå“¡æ‰å¯ä»¥åŠ å…¥Wikié é¢ï¼Œå¦‚果您有任何關於群組Wiki的改進建議,請通éŽ%{issues_link}æ交議題。"
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 ""
+msgstr "åªæœ‰è©²å°ˆæ¡ˆçš„æˆå“¡æ‰å¯ä»¥åŠ å…¥ Wiki é é¢ï¼Œå¦‚果您有任何關於專案 Wiki çš„æ”¹é€²å»ºè­°ï¼Œè«‹é€šéŽ %{issues_link} æ交議題。"
msgid "WikiEmptyIssueMessage|issue tracker"
-msgstr ""
+msgstr "議題追蹤"
msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
-msgstr ""
+msgstr "已經有Confluence Wiki?å¯ä»¥ç›´æŽ¥ä½¿ç”¨ã€‚"
msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
-msgstr ""
+msgstr "您å¯ä»¥ä½¿ç”¨Wikiæ述您的群組訊æ¯ï¼Œä¾‹å¦‚:建立該群組的原因ã€ç¾¤çµ„的原則或者群組的使用說明等等。"
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 ""
+msgstr "您å¯ä»¥ä½¿ç”¨ Wiki 來儲存專案的詳細訊æ¯ï¼Œä¾‹å¦‚:建立該專案的原因, 專案的原ç†åŠå°ˆæ¡ˆçš„使用說明等等。"
msgid "WikiEmpty|Confluence is enabled"
-msgstr ""
+msgstr "Confluence 已啟用"
msgid "WikiEmpty|Create your first page"
-msgstr ""
+msgstr "建立您的第一個é é¢"
msgid "WikiEmpty|Enable the Confluence Wiki integration"
-msgstr ""
+msgstr "啟用Confluence Wikiæ•´åˆ"
msgid "WikiEmpty|Go to Confluence"
-msgstr ""
+msgstr "å‰å¾€Confluence"
msgid "WikiEmpty|Suggest wiki improvement"
-msgstr ""
+msgstr "Wiki 改進建議"
msgid "WikiEmpty|The wiki lets you write documentation for your group"
-msgstr ""
+msgstr "您å¯ä»¥ä½¿ç”¨Wiki為您的群組編寫文件"
msgid "WikiEmpty|The wiki lets you write documentation for your project"
-msgstr ""
+msgstr "您å¯ä»¥ä½¿ç”¨ Wiki 為您的專案編寫文件"
msgid "WikiEmpty|This group has no wiki pages"
-msgstr ""
+msgstr "該群組沒有任何Wikié é¢"
msgid "WikiEmpty|This project has no wiki pages"
-msgstr ""
+msgstr "該專案無任何 Wiki é é¢"
msgid "WikiEmpty|You must be a group member in order to add wiki pages."
-msgstr ""
+msgstr "åªæœ‰ç¾¤çµ„æˆå“¡æ‰å¯ä»¥åŠ å…¥Wikié é¢ã€‚"
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
-msgstr ""
+msgstr "åªæœ‰å°ˆæ¡ˆæˆå“¡æ‰å¯ä»¥åŠ å…¥ Wiki é é¢ã€‚"
msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
-msgstr ""
+msgstr "您已啟用Confluence Workspaceæ•´åˆã€‚您的Wikiå°‡å¯ç›´æŽ¥åœ¨Confluence中查看。我們正在努力將Confluence更無縫地整åˆåˆ°GitLab中。如果您想了解最新訊æ¯ï¼Œè«‹é—œæ³¨æˆ‘們的%{wiki_confluence_epic_link_start}Confluenceå²è©©%{wiki_confluence_epic_link_end}。"
msgid "WikiHistoricalPage|This is an old version of this page."
-msgstr ""
+msgstr "這是此é é¢çš„éŽæœŸç‰ˆæœ¬ã€‚"
msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
-msgstr ""
+msgstr "您å¯ä»¥æŸ¥çœ‹ %{most_recent_link} 或ç€è¦½ %{history_link}。"
msgid "WikiHistoricalPage|history"
-msgstr ""
+msgstr "æ­·å²"
msgid "WikiHistoricalPage|most recent version"
-msgstr ""
+msgstr "最新版本"
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
-msgstr ""
+msgstr "確定è¦åˆªé™¤æ­¤é é¢å—Žï¼Ÿ"
msgid "WikiPageConfirmDelete|Delete page"
-msgstr ""
+msgstr "刪除é é¢"
msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
-msgstr ""
+msgstr "刪除é é¢%{pageTitle}?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{wikiLinkStart}the page%{wikiLinkEnd} and make sure your changes will not unintentionally remove theirs."
-msgstr ""
+msgstr "有人在您編輯é é¢çš„åŒæ™‚編輯了é é¢ã€‚請查看%{wikiLinkStart}é é¢%{wikiLinkEnd}並確ä¿æ‚¨çš„更改ä¸æœƒç„¡æ„中刪除它們的更改。"
msgid "WikiPage|An error occurred while trying to render the content editor. Please try again later."
-msgstr ""
+msgstr "嘗試顯示內容編輯器時發生錯誤,請ç¨å¾Œå†è©¦ã€‚"
msgid "WikiPage|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "WikiPage|Commit message"
-msgstr ""
+msgstr "æ交訊æ¯"
msgid "WikiPage|Content"
-msgstr ""
+msgstr "內容"
msgid "WikiPage|Create %{pageTitle}"
-msgstr ""
+msgstr "建立 %{pageTitle}"
msgid "WikiPage|Create page"
-msgstr ""
-
-msgid "WikiPage|Edit rich text"
-msgstr ""
-
-msgid "WikiPage|Edit source"
-msgstr ""
+msgstr "建立é é¢"
msgid "WikiPage|Format"
-msgstr ""
+msgstr "æ ¼å¼"
msgid "WikiPage|Learn more."
-msgstr ""
+msgstr "了解更多。"
msgid "WikiPage|Page title"
-msgstr ""
+msgstr "é é¢æ¨™é¡Œ"
msgid "WikiPage|Retry"
-msgstr ""
+msgstr "é‡è©¦"
msgid "WikiPage|Save changes"
-msgstr ""
+msgstr "ä¿å­˜æ›´æ”¹"
msgid "WikiPage|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr ""
+msgstr "æ示:您å¯ä»¥é€šéŽåœ¨æ¨™é¡Œé–‹é ­åŠ å…¥è·¯å¾‘來移動此é é¢ã€‚"
msgid "WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr ""
+msgstr "æ示:您å¯ä»¥ç‚ºæ–°æ–‡ä»¶æŒ‡å®šå®Œæ•´è·¯å¾‘。我們將自動建立任何缺失的目錄。"
msgid "WikiPage|Title"
-msgstr ""
+msgstr "標題"
msgid "WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}."
-msgstr ""
+msgstr "è¦é€£çµåˆ°ï¼ˆæ–°ï¼‰é é¢ï¼Œåªéœ€è¼¸å…¥ %{linkExample}。更多示例請查看 %{linkStart}文件%{linkEnd}。"
msgid "WikiPage|Update %{pageTitle}"
-msgstr ""
+msgstr "æ›´æ–° %{pageTitle}"
msgid "WikiPage|Write your content or drag files here…"
-msgstr ""
+msgstr "在這裡編寫您的內容或將文件拖動到此處..."
msgid "Wikis"
-msgstr ""
+msgstr "Wiki"
msgid "Wiki|Create New Page"
-msgstr ""
+msgstr "建立新é é¢"
msgid "Wiki|Created date"
-msgstr ""
+msgstr "建立日期"
msgid "Wiki|Edit Page"
-msgstr ""
+msgstr "修改é é¢"
msgid "Wiki|New page"
-msgstr ""
+msgstr "æ–°é é¢"
msgid "Wiki|Page history"
-msgstr ""
+msgstr "é é¢æ­·å²"
msgid "Wiki|Page version"
-msgstr ""
+msgstr "é é¢ç‰ˆæœ¬"
msgid "Wiki|Pages"
-msgstr ""
+msgstr "é é¢"
msgid "Wiki|The sidebar failed to load. You can reload the page to try again."
-msgstr ""
+msgstr "å´é‚Šæ¬„載入失敗。您å¯ä»¥é‡æ–°è¼‰å…¥é é¢å†è©¦ä¸€æ¬¡ã€‚"
msgid "Wiki|Title"
-msgstr ""
+msgstr "標題"
msgid "Wiki|View All Pages"
-msgstr ""
+msgstr "查看所有é é¢"
msgid "Wiki|Wiki Pages"
-msgstr ""
+msgstr "Wiki é é¢"
msgid "Will be created"
-msgstr ""
+msgstr "將被建立"
msgid "Will be mapped to"
-msgstr ""
+msgstr "將被映射到"
msgid "Will deploy to"
-msgstr ""
+msgstr "將部署到"
msgid "Wireframe"
-msgstr ""
+msgstr "線框稿"
msgid "With requirements, you can set criteria to check your products against."
-msgstr ""
+msgstr "根據è¦æ±‚,您å¯ä»¥è¨­å®šæ¨™æº–來檢查您的產å“。"
msgid "With test cases, you can define conditions for your project to meet in determining quality"
-msgstr ""
+msgstr "使用測試案例,您å¯ä»¥å®šç¾©å°ˆæ¡ˆçš„æ¢ä»¶ä»¥æ±ºå®šè³ªé‡"
msgid "Withdraw Access Request"
-msgstr ""
+msgstr "å–消權é™ç”³è«‹"
msgid "Won't fix / Accept risk"
-msgstr ""
+msgstr "ä¸ä¿®å¾©/接å—風險"
msgid "Work in progress (open and unassigned)"
-msgstr ""
+msgstr "正在進行中(開啟且未指派)"
msgid "Work in progress Limit"
-msgstr ""
+msgstr "「進行中(Work in progress, WIP)ã€çš„é™åˆ¶"
-msgid "WorkItem|Add"
-msgstr ""
+msgid "WorkItem|A task provides the ability to break down your work into smaller pieces tied to an issue. Tasks are the first items using our new %{workItemsLink} objects. Additional work item types will be coming soon."
+msgstr "任務æ供了將您的工作分解為å°å¡Šèˆ‡è­°é¡Œç›¸é—œçš„能力,任務是使用我們新的 %{workItemsLink} å°è±¡çš„第一個項目,其他更多的工作項類型將陸續推出。"
-msgid "WorkItem|Add a child"
-msgstr ""
+msgid "WorkItem|Add a task"
+msgstr "增加任務"
+
+msgid "WorkItem|Add a title"
+msgstr "增加標題"
msgid "WorkItem|Add assignee"
-msgstr ""
+msgstr "增加指派者"
msgid "WorkItem|Add assignees"
-msgstr ""
+msgstr "增加指派者"
+
+msgid "WorkItem|Add task"
+msgstr "增加任務"
msgid "WorkItem|Are you sure you want to cancel editing?"
-msgstr ""
+msgstr "您確定è¦å–消編輯嗎?"
-msgid "WorkItem|Are you sure you want to delete the work item? This action cannot be reversed."
-msgstr ""
+msgid "WorkItem|Are you sure you want to delete the task? This action cannot be reversed."
+msgstr "您確定è¦åˆªé™¤è©²ä»»å‹™å—Žï¼Ÿæ­¤æ“作無法回復。"
msgid "WorkItem|Assignee"
msgid_plural "WorkItem|Assignees"
-msgstr[0] ""
+msgstr[0] "指派者"
msgid "WorkItem|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "WorkItem|Child items"
-msgstr ""
+msgstr "å­é …"
+
+msgid "WorkItem|Child removed"
+msgstr "已移除å­é …"
msgid "WorkItem|Closed"
-msgstr ""
+msgstr "已關閉"
msgid "WorkItem|Collapse child items"
-msgstr ""
+msgstr "收摺å­é …"
msgid "WorkItem|Create task"
-msgstr ""
+msgstr "建立任務"
msgid "WorkItem|Create work item"
-msgstr ""
+msgstr "建立工作項"
-msgid "WorkItem|Delete work item"
-msgstr ""
+msgid "WorkItem|Delete task"
+msgstr "刪除任務"
msgid "WorkItem|Expand child items"
-msgstr ""
+msgstr "擴展å­é …"
+
+msgid "WorkItem|Introducing tasks"
+msgstr "任務介紹"
+
+msgid "WorkItem|Learn about tasks"
+msgstr "了解任務"
msgid "WorkItem|No child items are currently assigned. Use child items to prioritize tasks that your team should complete in order to accomplish your goals!"
-msgstr ""
+msgstr "ç›®å‰æœªåˆ†é…å­é …。使用å­é …目來確定您的團隊應該完æˆçš„任務優先級,以實ç¾æ‚¨çš„目標ï¼"
msgid "WorkItem|Open"
-msgstr ""
+msgstr "é–‹å•Ÿ"
+
+msgid "WorkItem|Remove"
+msgstr "移除"
msgid "WorkItem|Select type"
-msgstr ""
+msgstr "é¸æ“‡é¡žåž‹"
+
+msgid "WorkItem|Something went wrong when creating a task. Please try again"
+msgstr "建立任務時發生å•é¡Œï¼Œè«‹é‡è©¦"
msgid "WorkItem|Something went wrong when creating a work item. Please try again"
-msgstr ""
+msgstr "建立工作項時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚"
+
+msgid "WorkItem|Something went wrong when deleting the task. Please try again."
+msgstr "刪除任務時發生錯誤,請é‡è©¦ã€‚"
msgid "WorkItem|Something went wrong when deleting the work item. Please try again."
-msgstr ""
+msgstr "刪除作項時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong when fetching the work item. Please try again."
-msgstr ""
+msgstr "å–得工作項時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚"
msgid "WorkItem|Something went wrong when fetching work item types. Please try again"
-msgstr ""
+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 work item. Please try again."
-msgstr ""
+msgstr "更新工作項時出ç¾éŒ¯èª¤ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚"
+
+msgid "WorkItem|Task deleted"
+msgstr "任務已移除"
+
+msgid "WorkItem|Turn off confidentiality"
+msgstr "關閉機密性"
+
+msgid "WorkItem|Turn on confidentiality"
+msgstr "開啟機密性"
msgid "WorkItem|Type"
-msgstr ""
+msgstr "é¡žåž‹"
+
+msgid "WorkItem|Undo"
+msgstr "復原"
msgid "WorkItem|Work Items"
-msgstr ""
+msgstr "工作事項"
msgid "WorkItem|Work item deleted"
-msgstr ""
+msgstr "已刪除的工作項"
+
+msgid "WorkItem|work items"
+msgstr "工作項"
msgid "Would you like to create a new branch?"
-msgstr ""
+msgstr "您è¦å»ºç«‹ä¸€å€‹æ–°åˆ†æ”¯å—Žï¼Ÿ"
msgid "Would you like to try auto-generating a branch name?"
-msgstr ""
+msgstr "您想嘗試自動產生分支å稱嗎?"
msgid "Write"
-msgstr ""
+msgstr "編輯"
msgid "Write a comment or drag your files here…"
-msgstr ""
+msgstr "在此發表留言或拖動您的文件到這裡…"
msgid "Write a comment…"
-msgstr ""
+msgstr "發表留言..."
msgid "Write a description or drag your files here…"
-msgstr ""
+msgstr "撰寫æ述或將您的文件拖到此處…"
msgid "Write a description…"
-msgstr ""
+msgstr "撰寫æè¿°..."
msgid "Write an internal note or drag your files here…"
-msgstr ""
+msgstr "寫一個內部註釋或將您的文件拖到這裡..."
msgid "Write milestone description..."
-msgstr ""
+msgstr "寫入里程碑æè¿°..."
msgid "Write your release notes or drag your files here…"
-msgstr ""
+msgstr "撰寫發行說明(Release Notes) 或將文件拖動到此處..."
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
-msgstr ""
+msgstr "æ供了錯誤的外部UID。請正確設定Auth0。"
msgid "Xcode"
-msgstr ""
+msgstr "Xcode"
msgid "YYYY-MM-DD"
-msgstr ""
+msgstr "YYYY-MM-DD"
msgid "Yes"
msgstr "是"
msgid "Yes or No"
-msgstr ""
+msgstr "是或å¦"
msgid "Yes, add it"
-msgstr ""
+msgstr "是的,加入它"
msgid "Yes, close issue"
-msgstr ""
+msgstr "是的,關閉議題"
msgid "Yes, delete project"
-msgstr ""
+msgstr "是的,刪除專案"
msgid "Yesterday"
-msgstr ""
+msgstr "昨天"
msgid "You"
msgstr "您"
msgid "You already have pending todo for this alert"
-msgstr ""
+msgstr "您已有é‡å°æ­¤è­¦å ±çš„待處ç†å¾…辦事項"
msgid "You are about to add %{usersTag} people to the discussion. They will all receive a notification."
-msgstr ""
+msgstr "å³å°‡æŠŠ%{usersTag}相關人員加入到討論中。他們都會收到通知。"
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[0] "您å³å°‡å¾žå¿«å–中清除 %{count} 個圖åƒã€‚ 確èªå¾Œï¼Œæµæ°´ç·šä¸‹æ¬¡é‹è¡Œæ™‚必須從 Docker Hub 拉å–映åƒæˆ–標籤。你確定嗎?"
msgid "You are about to delete this forked project containing:"
-msgstr ""
+msgstr "您將è¦åˆªé™¤æ­¤åˆ†å‰å°ˆæ¡ˆï¼Œå…¶ä¸­åŒ…å«ï¼š"
msgid "You are about to delete this project containing:"
-msgstr ""
+msgstr "您將è¦åˆªé™¤æ­¤å°ˆæ¡ˆï¼Œå…¶ä¸­åŒ…å«ï¼š"
msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
-msgstr ""
+msgstr "您å³å°‡æŠŠå¸³è™ŸæŽ§åˆ¶æ¬Šè½‰ç§»åˆ°%{group_name}群組。此æ“作ä¸å¯æ’¤æ¶ˆï¼Œè½‰ç§»å®Œæˆå¾Œï¼Œæ‚¨å°‡ç„¡æ³•å­˜å–%{group_name}以外的任何群組和專案。"
msgid "You are already a member of this %{member_source}."
-msgstr ""
+msgstr "您已經是%{member_source}çš„æˆå“¡ã€‚"
msgid "You are already impersonating another user"
-msgstr ""
+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 ""
+msgstr "您是管ç†å“¡ï¼Œé€™æ„味著賦予%{client_name}權é™å°‡å…許他們作為管ç†å“¡ä¾†å°GitLab進行æ“作。請謹慎行事。"
msgid "You are attempting to delete a file that has been previously updated."
-msgstr ""
+msgstr "您正在嘗試刪除先å‰å·²æ›´æ–°çš„文件。"
msgid "You are attempting to update a file that has changed since you started editing it."
-msgstr ""
+msgstr "您正在嘗試更新的文件自您開始編輯以來已經發生變更。"
msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
-msgstr ""
+msgstr "如果超éŽæ­¤æ•¸å­—,將為您計費。%{qsrOverageLinkStart}計費如何é‹ä½œï¼Ÿ%{qsrOverageLinkEnd}"
msgid "You are connected to the Prometheus server, but there is currently no data to display."
-msgstr ""
+msgstr "您已連接到Prometheus伺æœå™¨ï¼Œä½†ç›®å‰æ²’有資料å¯é¡¯ç¤ºã€‚"
msgid "You are currently offline, or the GitLab instance is not reachable."
-msgstr ""
+msgstr "您當å‰è™•æ–¼é›¢ç·šç‹€æ…‹ï¼Œæˆ–者 GitLab 實例無法訪å•ã€‚"
msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "å³å°‡è¦åˆªé™¤%{project_full_name}。已刪除的專案無法æ¢å¾©ï¼ç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
msgid "You are going to remove %{group_name}. This will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "您將刪除 %{group_name}。這也將刪除其所有å­ç¾¤çµ„和專案。刪除的群組無法æ¢å¾©ï¼æ‚¨ç¢ºå®šå—Žï¼Ÿ"
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "å³å°‡ç§»é™¤èˆ‡ä¾†æºå°ˆæ¡ˆ%{project_full_name}的分å‰é—œä¿‚。確定繼續嗎?"
msgid "You are going to transfer %{group_name} to another namespace. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "您正在將 %{group_name} 轉移到å¦ä¸€å€‹å‘½å空間,您確定嗎?"
msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "您正在將 %{project_full_name} 轉移到å¦ä¸€å€‹å稱空間。您完全確定嗎?"
msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
-msgstr ""
+msgstr "å³å°‡é—œé–‰æ©Ÿå¯†æ€§ã€‚這將使得%{strongStart}所有使用者%{strongEnd}都å¯ä»¥æŸ¥çœ‹ä¸¦ä¸”留言於該%{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 "您將開啟機密功能。åªæœ‰æ“有 %{strongStart} %{permissions} %{strongEnd}權é™ä»¥ä¸Šçš„ %{context} 個æˆå“¡å¯ä»¥æŸ¥çœ‹æˆ–收到有關此%{issuableType}的通知。"
msgid "You are not allowed to %{action} a user"
-msgstr ""
+msgstr "您無權%{action}一å使用者"
msgid "You are not allowed to approve a user"
-msgstr ""
+msgstr "您無權核准使用者"
msgid "You are not allowed to log in using password"
-msgstr ""
+msgstr "您ä¸èƒ½ä½¿ç”¨å¯†ç¢¼ç™»å…¥"
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
-msgstr ""
+msgstr "您無權推é€åˆ°æ­¤åˆ†æ”¯ã€‚請建立一個新的分支或開啟åˆä½µè«‹æ±‚。"
msgid "You are not allowed to reject a user"
-msgstr ""
+msgstr "您無權拒絕使用者"
msgid "You are not allowed to unlink your primary login account"
-msgstr ""
+msgstr "您ä¸èƒ½å–消與主登入帳號的關è¯"
msgid "You are not authorized to delete this site profile"
-msgstr ""
+msgstr "您無權刪除此站點設定文件"
msgid "You are not authorized to perform this action"
-msgstr ""
+msgstr "您無權執行此æ“作"
msgid "You are not authorized to run this manual job"
-msgstr ""
+msgstr "您無權執行此手動作業"
msgid "You are not authorized to update this profile"
-msgstr ""
+msgstr "您無權更新此設定文件"
msgid "You are not authorized to update this scanner profile"
-msgstr ""
+msgstr "您無權更新此掃瞄工具設定文件"
msgid "You are not authorized to upload metric images"
-msgstr ""
+msgstr "您無權上傳指標映åƒ"
msgid "You are now impersonating %{username}"
-msgstr ""
+msgstr "您正在使用%{username}的身份"
msgid "You are on a read-only GitLab instance."
-msgstr ""
+msgstr "ç›®å‰æ­£åœ¨å­˜å–唯讀 GitLab 實體。"
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
-msgstr ""
+msgstr "您收到此消æ¯æ˜¯å› ç‚ºæ‚¨æ˜¯ %{url} çš„GitLab管ç†å“¡ã€‚"
msgid "You are signed in to GitLab as:"
-msgstr ""
+msgstr "您以該身份æ›å…¥GitLab:"
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
-msgstr ""
+msgstr "您正在嘗試上傳éžåœ–片文件。請上傳.pngã€.jpgã€.jpegã€.gifã€.bmpã€.tiff或.ico。"
msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
-msgstr ""
+msgstr "您正在使用PostgreSQL %{pg_version_current},但此版本的GitLab需è¦PostgreSQL %{pg_version_minimum}。請將您的環境å‡ç´šåˆ°æ”¯æ´çš„ PostgreSQL版本,詳情請見%{pg_requirements_url}。"
msgid "You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
-msgstr ""
+msgstr "您å¯ä»¥%{gitlabLinkStart}在 GitLab 上解決è¡çª%{gitlabLinkEnd} 或 %{resolveLocallyStart}本機解決%{resolveLocallyEnd}。"
msgid "You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}."
-msgstr ""
+msgstr "您å¯ä»¥ %{resolveLocallyStart}在本機解決它%{resolveLocallyEnd}。"
msgid "You can adjust rules on auto-banning %{link_start}here%{link_end}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ %{link_start}此處%{link_end}調整自動ç¦æ­¢è¦å‰‡ã€‚"
msgid "You can adjust rules on auto-banning here: %{url}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ­¤è™•èª¿æ•´è‡ªå‹•ç¦æ­¢è¦å‰‡ï¼š%{url}。"
msgid "You can also create a project from the command line."
-msgstr ""
+msgstr "您也å¯ä»¥é€éŽå‘½ä»¤åˆ—來建立新專案。"
msgid "You can also press Ctrl-Enter"
-msgstr ""
+msgstr "您也å¯ä»¥æŒ‰ Ctrl-Enter"
msgid "You can also press ⌘-Enter"
-msgstr ""
+msgstr "您也å¯ä»¥æŒ‰ ⌘-Enter"
msgid "You can also star a label to make it a priority label."
-msgstr ""
+msgstr "å¯ä»¥é€éŽç‚ºæ¨™è¨˜è¨­å®šæ”¶è—(星號)來æ高其優先度。"
msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ %{lint_link_start}CI Lint%{lint_link_end} 中測試 %{gitlab_ci_yml}"
msgid "You can also upload existing files from your computer using the instructions below."
-msgstr ""
+msgstr "您還å¯ä»¥æŒ‰ç…§ä»¥ä¸‹èªªæ˜Žå¾žé›»è…¦ä¸­ä¸Šå‚³ç¾æœ‰æ–‡ä»¶ã€‚"
msgid "You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "您還å¯ä»¥åœ¨ Git 中使用群組存å–ä»¤ç‰Œé€šéŽ HTTP(S) 進行身份驗證。%{link_start}了解更多。%{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 "您還å¯ä»¥å°‡å°ˆæ¡ˆå­˜å–令牌與 Git çµåˆä½¿ç”¨ä»¥é€šéŽ HTTP(S) 進行身份驗證。 %{link_start}了解更多。%{link_end}"
msgid "You can always change your URL later"
-msgstr ""
+msgstr "您å¯ä»¥ç¨å¾Œæ›´æ”¹æ‚¨çš„ URL"
msgid "You can always edit this later"
-msgstr ""
+msgstr "您也å¯ä»¥ç¨å¾Œç·¨è¼¯æ­¤é¸é …。"
msgid "You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ %{pat_link_start}個人存å–令牌%{pat_link_end} 中查看它。"
msgid "You can check it in your in your personal access tokens settings %{pat_link}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„個人存å–令牌設定 %{pat_link} 中查看它。"
msgid "You can create a new %{link}."
-msgstr ""
+msgstr "您å¯ä»¥å»ºç«‹ä¸€å€‹æ–°çš„%{link}。"
msgid "You can create a new %{name} inside this project by sending an email to the following email address:"
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽå‘以下電å­éƒµä»¶åœ°å€ç™¼é€é›»å­éƒµä»¶ä¾†åœ¨æ­¤å°ˆæ¡ˆä¸­å»ºç«‹ä¸€å€‹æ–°çš„ %{name}"
msgid "You can create a new Personal Access Token by visiting %{link}"
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽå­˜å–%{link}建立一個新的個人存å–令牌"
msgid "You can create a new SSH key by visiting %{link}"
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽå­˜å–%{link}建立一個新的SSH金鑰"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„ %{pat_link_start}個人存å–令牌%{pat_link_end} 設定中建立一個新的或檢查它們。"
msgid "You can create a new one or check them in your %{ssh_key_link_start}SSH keys%{ssh_key_link_end} settings."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„ %{ssh_key_link_start}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 "您å¯ä»¥åœ¨æ‚¨çš„ SSH 金鑰設定 %{ssh_key_link} 中建立一個新的金鑰或檢查它們。"
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨æ‚¨çš„個人存å–令牌設定%{pat_link}中建立一個新的令牌或檢查它們。"
msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨%{pat_link_start}個人存å–令牌(權æ–)%{pat_link_end}設定中建立新的令牌(權æ–)"
msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨å€‹äººå­˜å–令牌(權æ–)設定%{pat_link}中建立新的存å–令牌(權æ–)。"
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥å•Ÿç”¨è¨»å†ŠåŠŸèƒ½ï¼Œå› ç‚º Service Ping 已啟用。è¦åœ¨æœªä¾†ç¹¼çºŒä½¿ç”¨è¨»å†ŠåŠŸèƒ½ï¼Œæ‚¨é‚„需è¦é€šéŽæ–°çš„雲授權許å¯æœå‹™å‘ GitLab 註冊。"
msgid "You can enable group access token creation in %{link_start}group settings%{link_end}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨%{link_start}群組設定%{link_end}中啟用群組存å–令牌建立。"
msgid "You can enable project access token creation in %{link_start}group settings%{link_end}."
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ %{link_start}群組設定%{link_end} 中啟用專案存å–令牌建立。"
msgid "You can filter by 'days to merge' by clicking on the columns in the chart."
-msgstr ""
+msgstr "您å¯ä»¥é€éŽå–®æ“Šåœ–表中的列來按「åˆä½µå¤©æ•¸ã€é€²è¡ŒéŽæ¿¾ã€‚"
msgid "You can find more information about GitLab subscriptions in %{subscriptions_doc_link}."
-msgstr ""
+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 ""
+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 ""
+msgstr "您å¯ä»¥ä½¿ç”¨æ¨™ç±¤å°æ¸¬è©¦æ¡ˆä¾‹é€²è¡Œåˆ†çµ„。è¦äº†è§£æ­¤åŠŸèƒ½çš„未來發展方å‘ï¼Œè«‹å­˜å– %{linkStart}質é‡ç®¡ç†æ–¹å‘é %{linkEnd}。"
-msgid "You can have a maximum of %{free_limit} unique members across all of your personal projects. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your projects to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
+msgid "You can have a maximum of %{free_user_limit} unique member across all of your personal projects."
+msgid_plural "You can have a maximum of %{free_user_limit} unique members across all of your personal projects."
+msgstr[0] "在您的個人所有專案中,您最多å¯ä»¥æ“有 %{free_user_limit} ä½å”¯ä¸€æˆå“¡ã€‚"
msgid "You can invite a new member to %{project_name} or invite another group."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è«‹æ–°æˆå“¡æˆ–å¦ä¸€å€‹ç¾¤çµ„加入%{project_name} 。"
msgid "You can invite a new member to %{project_name}."
-msgstr ""
-
-msgid "You can invite a new member to %{strong_start}%{group_name}%{strong_end}."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è«‹æ–°æˆå“¡åŠ å…¥%{project_name}。"
msgid "You can invite another group to %{project_name}."
-msgstr ""
+msgstr "您å¯ä»¥é‚€è«‹å¦ä¸€å€‹ç¾¤çµ„加入%{project_name}。"
msgid "You can move around the graph by using the arrow keys."
-msgstr ""
+msgstr "å¯ä»¥ä½¿ç”¨æ–¹å‘éµç§»å‹•åœ–形。"
msgid "You can notify the app / group or a project by sending them an email notification"
-msgstr ""
+msgstr "您å¯ä»¥é€šéŽé›»å­éƒµä»¶ä¾†é€šçŸ¥æ‡‰ç”¨ç¨‹å¼/群組或專案"
msgid "You can now close this window."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é—œé–‰æ­¤çª—å£ã€‚"
msgid "You can now export your security dashboard to a CSV report."
-msgstr ""
+msgstr "ç¾åœ¨æ‚¨å¯ä»¥åŒ¯å‡ºå®‰å…¨å„€è¡¨æ¿åˆ° CSV 報告。"
msgid "You can now submit a merge request to get this change into the original branch."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥æ交åˆä½µè«‹æ±‚以將此更改發é€åˆ°ä¾†æºåˆ†æ”¯ã€‚"
msgid "You can now submit a merge request to get this change into the original project."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥æ交åˆä½µè«‹æ±‚以將此更改加入到來æºå°ˆæ¡ˆä¸­ã€‚"
msgid "You can only %{action} files when you are on a branch"
-msgstr ""
+msgstr "當處於分支時,您åªèƒ½ %{action} 文件"
msgid "You can only add up to %{max_contacts} contacts at one time"
-msgstr ""
+msgstr "您一次最多åªèƒ½åŠ å…¥ %{max_contacts} 個è¯çµ¡äºº"
msgid "You can only edit files when you are on a branch"
-msgstr ""
+msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šç·¨è¼¯æ–‡ä»¶"
msgid "You can only merge once the items above are resolved."
-msgstr ""
+msgstr "解決以上å•é¡Œå¾Œï¼Œæ‚¨æ‰èƒ½åˆä½µã€‚"
msgid "You can only transfer the project to namespaces you manage."
-msgstr ""
+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 ""
+msgstr "您å¯ä»¥ä½¿ç”¨äº’動模å¼ï¼Œé€šéŽé¸æ“‡ %{use_ours} 或 %{use_theirs} 按鈕來解決åˆä½µè¡çªã€‚也å¯ä»¥é€šéŽç›´æŽ¥ç·¨è¼¯æ–‡ä»¶ä¾†è§£æ±ºåˆä½µè¡çªã€‚然後將這些更改æ交到 %{branch_name}"
msgid "You can see your chat accounts."
-msgstr ""
+msgstr "您å¯ä»¥æŸ¥çœ‹æ‚¨çš„èŠå¤©å¸³è™Ÿã€‚"
msgid "You can set up jobs to only use runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "您å¯ä»¥å°‡ä½œæ¥­è¨­å®šç‚ºåƒ…使用具有特定標籤的執行器(runners)。請使用逗號分隔ä¸åŒçš„標籤。"
msgid "You can specify notification level per group or per project."
-msgstr ""
+msgstr "您å¯ä»¥æŒ‡å®šæ¯å€‹ç¾¤çµ„或æ¯å€‹å°ˆæ¡ˆçš„通知級別。"
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
-msgstr ""
+msgstr "您也å¯ä»¥é€šéŽ%{linkStart}Lint%{linkEnd}測試.gitlab-ci.yml."
msgid "You can view the source or %{linkStart}%{cloneIcon} clone the repository%{linkEnd}"
-msgstr ""
+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 this namespace can start a trial or upgrade to a paid tier."
-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 ""
+msgstr "您ä¸èƒ½ %{action} %{state} 使用者。"
msgid "You cannot access the raw file. Please wait a minute."
-msgstr ""
+msgstr "您ä¸èƒ½å­˜å–原始文件。請ç¨å€™ã€‚"
msgid "You cannot approve your own deployment."
-msgstr ""
-
-msgid "You cannot change the start date after the cadence has started. Please create a new cadence."
-msgstr ""
+msgstr "您ä¸èƒ½æ ¸å‡†æ‚¨è‡ªå·±çš„部署。"
msgid "You cannot combine replace_ids with add_ids or remove_ids"
-msgstr ""
-
-msgid "You cannot edit this timeline event."
-msgstr ""
+msgstr "您ä¸èƒ½å°‡ replace_ids 與 add_ids 或 remove_ids çµåˆä½¿ç”¨"
msgid "You cannot impersonate a blocked user"
-msgstr ""
+msgstr "您無法使用被åœç”¨çš„使用者"
msgid "You cannot impersonate a user who cannot log in"
-msgstr ""
+msgstr "您無法摸擬使用無法登入的使用者"
msgid "You cannot impersonate an internal user"
-msgstr ""
+msgstr "您無法摸擬使用內部的使用者"
msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
-msgstr ""
+msgstr "您目å‰ç„¡æ³•åŸ·è¡Œæ­¤æµæ°´ç·šè¨ˆåŠƒã€‚è«‹ç¨å€™ã€‚"
msgid "You cannot rename an environment after it's created."
-msgstr ""
+msgstr "環境建立後ä¸èƒ½é‡æ–°å‘½å。"
msgid "You cannot set yourself to awaiting"
-msgstr ""
+msgstr "您ä¸èƒ½å°‡è‡ªå·²è¨­ç‚ºç­‰å¾…"
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
-msgstr ""
+msgstr "您ä¸èƒ½å¯«å…¥å”¯è®€çš„æ¬¡è¦ GitLab Geo 實體。請改用%{link_to_primary_node}。"
msgid "You cannot write to this read-only GitLab instance."
-msgstr ""
+msgstr "您ä¸èƒ½å¯«å…¥é€™å€‹å”¯è®€çš„ GitLab 實體。"
msgid "You can’t edit files directly in this project. Fork this project and submit a merge request with your changes."
-msgstr ""
+msgstr "您ä¸èƒ½åœ¨é€™å€‹å°ˆæ¡ˆä¸­ç›´æŽ¥ç·¨è¼¯æ–‡ä»¶ï¼Œè«‹åˆ†å‰ï¼ˆFork)這個專案並æ交包å«æ‚¨çš„更改的åˆä½µè«‹æ±‚。"
msgid "You could not create a new trigger."
-msgstr ""
+msgstr "您無法建立新的觸發器。"
-msgid "You currently have more than %{free_limit} members across all your personal projects. From June 22, 2022, the %{free_limit} most recently active members will remain active, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access. To view and manage members, check the members page for each project in your namespace. We recommend you %{move_link_start}move your project to a group%{move_link_end} so you can easily manage users and features."
-msgstr ""
-
-msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
-msgstr ""
+msgid "You currently have more than %{free_user_limit} member across all your personal projects. 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."
+msgid_plural "You currently have more than %{free_user_limit} members across all your personal projects. 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."
+msgstr[0] "您目å‰åœ¨å€‹äººæ‰€æœ‰å°ˆæ¡ˆä¸­æ“æœ‰è¶…éŽ %{free_user_limit} ä½æˆå“¡ã€‚從 2022 å¹´ 10 月 19 日起,%{free_user_limit} 最近活èºçš„æˆå“¡å°‡ä¿æŒæ´»èºç‹€æ…‹ï¼Œå…¶é¤˜æˆå“¡å°‡è™•æ–¼ %{link_start}超é™ç‹€æ…‹%{link_end} 並失去存å–權é™ã€‚"
msgid "You do not have any subscriptions yet"
-msgstr ""
+msgstr "您目å‰å°šæœªæœ‰ä»»ä½•è¨‚é–±"
msgid "You do not have permission to access dora metrics."
-msgstr ""
+msgstr "æ‚¨ç„¡æ¬Šå­˜å– dora 指標。"
msgid "You do not have permission to approve a member"
-msgstr ""
+msgstr "您沒有權é™æ ¸å‡†æˆå“¡"
msgid "You do not have permission to leave this %{namespaceType}."
-msgstr ""
+msgstr "您沒有權é™é€€å‡º%{namespaceType}。"
msgid "You do not have permission to run a pipeline on this branch."
-msgstr ""
+msgstr "您沒有權é™åœ¨æ­¤åˆ†æ”¯ä¸ŠåŸ·è¡Œæµæ°´ç·šã€‚"
msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
-msgstr ""
+msgstr "您無權執行Web終端。請è¯çµ¡å°ˆæ¡ˆç®¡ç†å“¡ã€‚"
msgid "You do not have permission to set a member awaiting"
-msgstr ""
+msgstr "您無權設置æˆå“¡ç­‰å¾…"
msgid "You do not have permission to update the environment."
-msgstr ""
+msgstr "您沒有更新此環境的權é™ã€‚"
msgid "You do not have permissions to run the import."
-msgstr ""
+msgstr "您沒有權é™åŸ·è¡ŒåŒ¯å…¥ã€‚"
msgid "You don't have any U2F devices registered yet."
-msgstr ""
+msgstr "您還沒有註冊任何U2F設備。"
msgid "You don't have any WebAuthn devices registered yet."
-msgstr ""
+msgstr "您尚未註冊任何WebAuthn設備。"
msgid "You don't have any active chat names."
-msgstr ""
+msgstr "您沒有任何啟用的èŠå¤©å稱。"
msgid "You don't have any applications"
-msgstr ""
+msgstr "您沒有任何應用程å¼"
msgid "You don't have any authorized applications"
-msgstr ""
+msgstr "您沒有任何授權的應用"
msgid "You don't have any deployments right now."
-msgstr ""
+msgstr "您ç¾åœ¨æ²’有任何部署。"
msgid "You don't have any open merge requests"
-msgstr ""
+msgstr "您沒有任何開啟的åˆä½µè«‹æ±‚"
msgid "You don't have any recent searches"
-msgstr ""
+msgstr "您沒有任何近期的æœå°‹"
msgid "You don't have permission to review this deployment. Contact the project or group owner for help."
-msgstr ""
+msgstr "您無權查看此部署。è¯çµ¡å°ˆæ¡ˆæˆ–群組所有者尋求幫助。"
msgid "You don't have permissions to create this project"
-msgstr ""
+msgstr "您無權建立此專案"
msgid "You don't have sufficient permission to perform this action."
-msgstr ""
+msgstr "您沒有足夠的權é™ä¾†åŸ·è¡Œæ­¤æ“作。"
msgid "You don't have the %{role} role for any groups in this instance."
-msgstr ""
+msgstr "您沒有此實例中任何群組的 %{role} 角色。"
msgid "You don't have write access to the source branch."
-msgstr ""
+msgstr "您沒有å°ä¾†æºåˆ†æ”¯çš„寫入權é™ã€‚"
msgid "You don’t have access to Productivity Analytics in this group"
-msgstr ""
+msgstr "您沒有存å–此群組效率分æžçš„權é™"
msgid "You don’t have access to Value Stream Analytics for this group"
-msgstr ""
+msgstr "您沒有存å–此群組價值æµåˆ†æžçš„權é™"
msgid "You have %{pendingMembersCount} pending member that needs approval."
msgid_plural "You have %{pendingMembersCount} pending members that need approval."
-msgstr[0] ""
+msgstr[0] "您有 %{pendingMembersCount} 個待處ç†æˆå“¡éœ€è¦æ ¸å‡†ã€‚"
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
-msgstr ""
+msgstr "您已被授予 %{access_level} å­˜å– %{source_link} %{source_type} 的權é™ã€‚"
msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
-msgstr ""
+msgstr "您已被授予 %{access_level} å­˜å– %{source_name} %{source_type} 的權é™ã€‚"
msgid "You have been granted %{member_human_access} access to group %{name}."
-msgstr ""
+msgstr "您已被授予了%{name}群組的%{member_human_access}權é™ã€‚"
msgid "You have been granted %{member_human_access} access to project %{name}."
-msgstr ""
+msgstr "您已被授予了%{name}專案的%{member_human_access}權é™ã€‚"
msgid "You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}"
-msgstr ""
+msgstr "您已被 %{link_to_inviter} 邀請加入 %{source_name} %{strong_open}%{link_to_source}%{strong_close} 作為 %{role}"
msgid "You have been redirected to the only result; see the %{a_start}search results%{a_end} instead."
-msgstr ""
+msgstr "您已被é‡å°Žå‘到唯一的çµæžœï¼›æ”¹ç‚ºæŸ¥çœ‹ %{a_start}æœå°‹çµæžœ%{a_end}。"
msgid "You have been unsubscribed from this thread."
-msgstr ""
+msgstr "您已å–消訂閱該主題。"
msgid "You have declined the invitation to join %{title} %{name}."
-msgstr ""
+msgstr "您已拒絕加入 %{title} %{name}的邀請。"
msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
-msgstr ""
+msgstr "您已從該專案匯入%{numberOfPreviousImports} 次。æ¯æ¬¡åŒ¯å…¥éƒ½æœƒç”¢ç”Ÿé‡è¤‡çš„議題。"
msgid "You have insufficient permissions to configure escalation policies for this project"
-msgstr ""
+msgstr "您沒有足夠的權é™ç‚ºæ­¤å°ˆæ¡ˆè¨­å®šå‡ç´šæ”¿ç­–"
msgid "You have insufficient permissions to create a Todo for this alert"
-msgstr ""
+msgstr "您沒有足夠的權é™ç‚ºé€™å€‹è­¦å‘Šå»ºç«‹å¾…辦事項"
msgid "You have insufficient permissions to create an HTTP integration for this project"
-msgstr ""
+msgstr "您沒有足夠的權é™ç‚ºæ­¤å°ˆæ¡ˆå»ºç«‹HTTPæ•´åˆ"
msgid "You have insufficient permissions to create an on-call schedule for this project"
-msgstr ""
+msgstr "您沒有足夠的權é™ä¾†å»ºç«‹æ­¤å°ˆæ¡ˆçš„待命(on-call)計劃"
msgid "You have insufficient permissions to manage resource links for this incident"
-msgstr ""
+msgstr "您沒有足夠的權é™ç®¡ç†æ­¤äº‹æ•…的資æºéˆçµ"
msgid "You have insufficient permissions to manage timeline events for this incident"
-msgstr ""
+msgstr "您沒有足夠的權é™ç®¡ç†æ­¤äº‹æ•…的時間線事件"
msgid "You have insufficient permissions to remove an on-call rotation from this project"
-msgstr ""
+msgstr "您的權é™ä¸è¶³ï¼Œç„¡æ³•å¾žæ­¤å°ˆæ¡ˆä¸­ç§»é™¤on-call輪æ›"
msgid "You have insufficient permissions to remove an on-call schedule from this project"
-msgstr ""
+msgstr "您沒有足夠的權é™å¾žæ­¤å°ˆæ¡ˆä¸­ç§»é™¤ on-call 計劃"
msgid "You have insufficient permissions to remove this HTTP integration"
-msgstr ""
+msgstr "您沒有足夠的權é™ç§»é™¤æ­¤HTTPæ•´åˆ"
msgid "You have insufficient permissions to remove this Namespace Ban"
-msgstr ""
+msgstr "您的權é™ä¸è¶³ä»¥ç§»é™¤æ­¤å‘½å空間的ç¦ä»¤"
msgid "You have insufficient permissions to set customer relations contacts for this issue"
-msgstr ""
+msgstr "您沒有足夠的權é™ç‚ºæ­¤è­°é¡Œè¨­å®šå®¢æˆ¶é—œä¿‚è¯çµ¡äºº"
msgid "You have insufficient permissions to update an on-call schedule for this project"
-msgstr ""
+msgstr "您沒有足夠的權é™ä¾†æ›´æ–°æ­¤å°ˆæ¡ˆçš„on-call計劃"
msgid "You have insufficient permissions to update this HTTP integration"
-msgstr ""
+msgstr "您沒有足夠的權é™ä¾†æ›´æ–°æ­¤HTTPæ•´åˆ"
msgid "You have insufficient permissions to view shifts for this rotation"
-msgstr ""
+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 ""
+msgstr "您的使用者啟用數超éŽäº†æ‚¨æŽˆæ¬Šè¨±å¯æ‰€å…許的數é‡ã€‚在 %{date} 之å‰å¿…須調整您的訂閱。è¦å®Œæˆæ­¤éŽç¨‹ï¼Œè«‹åŒ¯å‡ºæ‚¨çš„授權許å¯ä½¿ç”¨æ–‡ä»¶ä¸¦å°‡å…¶é€šéŽé›»å­éƒµä»¶ç™¼é€è‡³ %{renewal_service_email}。新的授權許å¯å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€åˆ° %{customers_dot} 註冊的電å­éƒµä»¶åœ°å€ã€‚您å¯ä»¥å°‡æ­¤æŽˆæ¬Šè¨±å¯åŠ å…¥åˆ°æ‚¨çš„實例。"
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 "您的使用者啟用數超éŽäº†æ‚¨çš„授權許å¯æ‰€å…許的數é‡ï¼Œå¿…須調整您的訂閱。è¦å®Œæˆæ­¤éŽç¨‹ï¼Œè«‹åŒ¯å‡ºæ‚¨çš„授權許å¯ä½¿ç”¨æ–‡ä»¶ä¸¦å°‡å…¶é€šéŽé›»å­éƒµä»¶ç™¼é€è‡³ %{renewal_service_email}。新的授權許å¯å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€åˆ° %{customers_dot} 註冊的電å­éƒµä»¶åœ°å€ã€‚您å¯ä»¥å°‡æ­¤æŽˆæ¬Šè¨±å¯åŠ å…¥åˆ°æ‚¨çš„實例。"
msgid "You have no permissions"
-msgstr ""
+msgstr "您沒有權é™"
msgid "You have not added any approvers. Start by adding users or groups."
-msgstr ""
+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 "您已經為您的帳號設定了雙因å­(2FA)é©—è­‰ï¼ å¦‚æžœæ‚¨ç„¡æ³•å­˜å–您的 2FA 設備,您å¯ä»¥ä½¿ç”¨æ¢å¾©ç¢¼å­˜å–您的帳號。或者,如果您上傳一個 SSH 金鑰,您å¯ä»¥ä½¿ç”¨ %{anchorOpen}使用該金鑰產生é¡å¤–çš„æ¢å¾©ç¢¼%{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 ""
+msgstr "您已æˆåŠŸè³¼è²· %{product}。您將通éŽé›»å­éƒµä»¶æ”¶åˆ°æ”¶æ“šã€‚您的購買å¯èƒ½éœ€è¦ä¸€åˆ†é˜æ‰èƒ½åŒæ­¥ï¼Œå¦‚果您還沒有看到,請é‡æ–°æ•´ç†é é¢ã€‚"
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
-msgstr ""
+msgstr "您已æˆåŠŸè³¼è²· %{seats} ä½ä½¿ç”¨è€…çš„ %{plan} 訂閱計劃。收據將通éŽé›»å­éƒµä»¶ç™¼é€çµ¦æ‚¨ã€‚"
msgid "You have unsaved changes"
-msgstr ""
+msgstr "您有未儲存的變更"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
-msgstr ""
+msgstr "您已經從「%{membershipable_human_name}〠%{source_type}退出。"
msgid "You may close the milestone now."
-msgstr ""
+msgstr "您ç¾åœ¨å¯ä»¥é—œé–‰é€™å€‹é‡Œç¨‹ç¢‘。"
msgid "You must be authenticated to access this path."
-msgstr ""
+msgstr "您必須經éŽé©—è­‰æ‰èƒ½å­˜å–此路徑。"
msgid "You must be logged in to search across all of GitLab"
-msgstr ""
+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 ""
+msgstr "啟用除錯追蹤時,您必須在關è¯å°ˆæ¡ˆä¸­æ“有開發人員或更高權é™æ‰èƒ½æŸ¥çœ‹ä½œæ¥­æ—¥èªŒã€‚è¦åœç”¨é™¤éŒ¯è¿½è¹¤ï¼Œè«‹åœ¨æµæ°´ç·šè¨­å®šæˆ– CI/CD 設定中將「CI_DEBUG_TRACEã€è®Šæ•¸è¨­å®šç‚ºã€Œfalseã€ã€‚如果您需è¦æŸ¥çœ‹æ­¤ä½œæ¥­æ—¥èªŒï¼Œå°ˆæ¡ˆç¶­è­·è€…必須將您加入到具有開發人員權é™æˆ–更高權é™çš„專案中。"
msgid "You must have maintainer access to force delete a lock"
-msgstr ""
+msgstr "å¿…é ˆæ“有維護者權é™æ‰èƒ½å¼·åˆ¶åˆªé™¤éŽ–定"
msgid "You must provide a valid current password"
-msgstr ""
+msgstr "您必須æ供一個有效的目å‰å¯†ç¢¼"
msgid "You must provide your current password in order to change it."
-msgstr ""
+msgstr "您必須æ供目å‰å¯†ç¢¼æ‰èƒ½é€²è¡Œè®Šæ›´ã€‚"
msgid "You must sign in to search for specific projects."
-msgstr ""
+msgstr "您必須登入æ‰èƒ½æœå°‹ç‰¹å®šå°ˆæ¡ˆã€‚"
msgid "You must sign in to search for specific terms."
-msgstr ""
+msgstr "您必須登入æ‰èƒ½æœå°‹ç‰¹å®šäº‹é …。"
msgid "You must solve the CAPTCHA in order to submit"
-msgstr ""
+msgstr "您必須解答驗證碼æ‰èƒ½éžäº¤"
msgid "You need a different license to enable FileLocks feature"
-msgstr ""
+msgstr "需è¦ä½¿ç”¨èˆ‡ç›®å‰ä¸åŒçš„授權許å¯(license)æ‰èƒ½å•Ÿç”¨æ–‡ä»¶éŽ–(FileLocks)功能"
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
-msgstr ""
+msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ½ç¹¼çºŒã€‚è«‹å­˜å–https://git-lfs.github.com"
msgid "You need permission."
-msgstr ""
+msgstr "您需è¦ç›¸é—œçš„權é™ã€‚"
msgid "You need to register a two-factor authentication app before you can set up a device."
-msgstr ""
+msgstr "您需è¦å…ˆè¨»å†Šä¸€å€‹é›™å› å­é©—證應用程å¼ï¼Œç„¶å¾Œæ‰èƒ½è¨­å®šè¨­å‚™ã€‚"
msgid "You need to set terms to be enforced"
-msgstr ""
+msgstr "您需è¦å°‡æ¢æ¬¾è¨­ç‚ºå¼·åˆ¶"
msgid "You need to specify both an Access Token and a Host URL."
-msgstr ""
+msgstr "您需è¦åŒæ™‚指定存å–令牌(權æ–)和主機URL。"
msgid "You need to upload a GitLab project export archive (ending in .gz)."
-msgstr ""
+msgstr "您需è¦ä¸Šå‚³GitLab專案匯出文件(以.gzçµå°¾)."
msgid "You need to verify your primary email first before enabling Two-Factor Authentication."
-msgstr ""
+msgstr "您需è¦å…ˆé©—證您的主è¦é›»å­éƒµä»¶ï¼Œç„¶å¾Œæ‰èƒ½å•Ÿç”¨é›™å› å­é©—證。"
msgid "You successfully declined the invitation"
-msgstr ""
+msgstr "您已æˆåŠŸæ‹’絕邀請"
msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
-msgstr ""
+msgstr "您已嘗試分å‰(fort) %{link_to_the_project} 但由於以下原因導致失敗:"
msgid "You will be removed from existing projects/groups"
-msgstr ""
+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 ""
+msgstr "您將æˆç‚ºå‹•æ…‹ä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如建立新分支或者推é€æ–°æ交到ç¾æœ‰åˆ†æ”¯ã€‚"
msgid "You will first need to set up Jira Integration to use this feature."
-msgstr ""
+msgstr "您首先需è¦è¨­å®šJiraæ•´åˆæ‰èƒ½ä½¿ç”¨æ­¤åŠŸèƒ½ã€‚"
msgid "You will lose all changes you've made to this file. This action cannot be undone."
-msgstr ""
+msgstr "您將éºå¤±å°æ­¤æ–‡ä»¶æ‰€åšçš„所有變更。此æ“作無法復原。"
msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
-msgstr ""
+msgstr "您將失去在此專案中所有未æ交的更改,此æ“作無法復原。"
msgid "You will need to update your local repositories to point to the new location."
-msgstr ""
+msgstr "您需è¦æ›´æ–°æœ¬æ©Ÿç‰ˆæœ¬åº«ä»¥æŒ‡å‘æ–°ä½ç½®ã€‚"
msgid "You will not get any notifications via email"
-msgstr ""
+msgstr "ä¸æœƒæ”¶åˆ°ä»»ä½•éƒµä»¶é€šçŸ¥"
msgid "You will only receive notifications for the events you choose"
-msgstr ""
+msgstr "åªæŽ¥æ”¶é¸æ“‡çš„事件通知"
msgid "You will only receive notifications for threads you have participated in"
-msgstr ""
+msgstr "åªæŽ¥æ”¶åƒèˆ‡çš„主題通知"
msgid "You will receive notifications for any activity"
-msgstr ""
+msgstr "接收所有活動的通知"
msgid "You will receive notifications only for comments in which you were @mentioned"
-msgstr ""
+msgstr "åªæŽ¥æ”¶ç•™è¨€ä¸­æåŠ(@)您的通知"
msgid "You won't be able to create new projects because you have reached your project limit."
-msgstr ""
+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 ""
+msgstr "根據å”è­°æ¢æ¬¾ï¼Œæ‚¨å°‡éœ€è¦æŒ‰å­£åº¦æˆ–年度支付%{true_up_link_start}超出授權許å¯ä½¿ç”¨è€…%{link_end}的費用。"
msgid "You'll be signed out from your current account automatically."
-msgstr ""
+msgstr "您將自動從目å‰å¸³è™Ÿé€€å‡ºã€‚"
msgid "You'll need to use different branch names to get a valid comparison."
-msgstr ""
+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 ""
+msgstr "您將è¦é™ä½Ž%{strong_start}%{group_name}%{strong_end}中%{strong_start}%{project_name}%{strong_end}專案的å¯è¦‹æ€§ã€‚"
msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
-msgstr ""
+msgstr "您將è¦é™ä½Žå°ˆæ¡ˆ %{strong_start}%{project_name}%{strong_end}çš„å¯è¦‹æ€§ã€‚"
msgid "You're at the first commit"
-msgstr ""
+msgstr "您的第一個æ交"
msgid "You're at the last commit"
-msgstr ""
+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 ""
+msgstr "您無權直接%{tag_start}編輯%{tag_end}這個專案的文件。請分å‰é€™å€‹å°ˆæ¡ˆï¼Œä¸¦åœ¨åˆ†å‰ä¸­é€²è¡Œè®Šæ›´ï¼Œç„¶å¾Œæ交åˆä½µè«‹æ±‚。"
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 ""
+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 ""
+msgstr "您ä¸èƒ½ç›´æŽ¥å°æ­¤å°ˆæ¡ˆé€²è¡Œè®Šæ›´ã€‚此專案的分å‰å°ˆæ¡ˆæ­£åœ¨å»ºç«‹ï¼Œæ‚¨å¯ä»¥åœ¨åˆ†å‰å°ˆæ¡ˆä¸­é€²è¡Œæ›´æ”¹ï¼Œä»¥ä¾¿æ交åˆä½µè«‹æ±‚。"
msgid "You're receiving this email because of your account on %{host}."
-msgstr ""
+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 ""
+msgstr "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨åœ¨ %{host} 上的帳號, %{manage_label_subscriptions_link_start}管ç†æ¨™ç±¤è¨‚é–±%{manage_label_subscriptions_link_end} · %{help_link_start}幫助%{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 "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨åœ¨ %{host} 上的帳號。 %{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{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 ""
+msgstr "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨åœ¨ %{host} 上的帳號,從該主題 &middot; %{unsubscribe_link_start}退訂%{unsubscribe_link_end} · %{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{help_link_end}"
msgid "You're receiving this email because of your activity on %{host}."
-msgstr ""
+msgstr "您在%{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 ""
+msgstr "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨åœ¨ %{host} 上的活動,從該主題 &middot; %{unsubscribe_link_start}å–消訂閱%{unsubscribe_link_end} %{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{help_link_end}"
msgid "You're receiving this email because you have been assigned an item on %{host}."
-msgstr ""
+msgstr "您收到此電å­éƒµä»¶æ˜¯å› ç‚º%{host}上有æŸå€‹å°ˆæ¡ˆæŒ‡æ´¾çµ¦æ‚¨ã€‚"
msgid "You're receiving this email because you have been 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 ""
+msgstr "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚ºæ‚¨åœ¨ %{host} 上分é…了一個項目,從該主題 &middot; %{unsubscribe_link_start}退訂%{unsubscribe_link_end} ,%{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{help_link_end}"
msgid "You're receiving this email because you have been mentioned on %{host}."
-msgstr ""
+msgstr "您收到此電å­éƒµä»¶æ˜¯å› ç‚º%{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 "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚º %{host} 上æ到了您,%{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{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 "您收到這å°é›»å­éƒµä»¶æ˜¯å› ç‚º %{host} 上曾æ到了您,從此主題 %{unsubscribe_link_start}退訂%{unsubscribe_link_end} &middot; %{manage_notifications_link_start}管ç†æ‰€æœ‰é€šçŸ¥%{manage_notifications_link_end} &middot; %{help_link_start}幫助%{help_link_end}"
+
+msgid "You're viewing members of %{strong_start}%{group_name}%{strong_end}."
+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 ""
+msgstr "您已經使用一次密碼驗證器來啟用了雙因å­èªè­‰ã€‚如果您è¦è¨»å†Šä¸åŒçš„設備,您必須先åœç”¨é›™å› å­èªè­‰ã€‚"
msgid "You've reached your %{free_limit} member limit across all of your personal projects"
-msgstr ""
+msgstr "您已é”到所有個人專案的 %{free_limit} æˆå“¡é™åˆ¶"
msgid "You've rejected %{user}"
-msgstr ""
+msgstr "您拒絕了 %{user}"
msgid "YouTube"
-msgstr ""
-
-msgid "Your %{doc_link_start}namespace%{doc_link_end}, %{strong_start}%{namespace_name}%{strong_end} has more than %{free_limit} members. From June 22, 2022, it will be limited to %{free_limit}, and the remaining members will get a %{link_start}status of Over limit%{link_end} and lose access to the namespace. You can go to the Usage Quotas page to manage which %{free_limit} members will remain in your namespace. To get more members, an owner can start a trial or upgrade to a paid tier."
-msgstr ""
+msgstr "YouTube"
msgid "Your %{group} membership will now expire in %{days}."
-msgstr ""
+msgstr "您的%{group}æˆå“¡è³‡æ ¼å°‡åœ¨%{days}天內到期。"
msgid "Your %{host} account was signed in to from a new location"
-msgstr ""
+msgstr "您在%{host}上的帳號已從一個新的ä½ç½®ç™»å…¥"
msgid "Your %{spammable_entity_type} has been recognized as spam and has been discarded."
-msgstr ""
+msgstr "您的 %{spammable_entity_type} 已被識別為垃圾郵件並已被丟棄。"
msgid "Your %{spammable_entity_type} has been recognized as spam. Please, change the content or solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "您的 %{spammable_entity_type} 已被識別為垃圾郵件。請更改內容或解答 reCAPTCHA 來繼續。"
-msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
-msgstr ""
+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 "您的 %{strong}%{plan_name}%{strong_close} 訂閱將於 %{strong}%{expires_on}%{strong_close} 到期,如果您ä¸çºŒè¨‚,您將無法存å–您在 %{strong}%{downgrades_on}%{strong_close} 的付費功能。在該日期之後,您將無法建立議題或åˆä½µè«‹æ±‚,以åŠä½¿ç”¨è¨±å¤šå…¶ä»–功能。"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
-msgstr ""
+msgstr "您為%{strong}%{namespace_name}%{strong_close}的%{strong}%{plan_name}%{strong_close}訂閱將於%{strong}%{expires_on}%{strong_close}到期。"
msgid "Your CI/CD configuration syntax is invalid. View Lint tab for more details."
-msgstr ""
+msgstr "您的 CI/CD 設定語法無效。查看 Lint é ç±¤ä»¥å–得更多詳細訊æ¯ã€‚"
msgid "Your CSV export has started. It will be emailed to %{email} when complete."
-msgstr ""
+msgstr "CSV匯出已經開始。完æˆå¾Œå°‡ç™¼é€é›»å­éƒµä»¶è‡³%{email}。"
msgid "Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment."
-msgstr ""
+msgstr "您從專案%{project_link}匯出包å«%{count}çš„CSV文件已作為附件加入到此電å­éƒµä»¶ä¸­ã€‚"
msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
-msgstr ""
+msgstr "您從專案%{project_name}(%{project_url})匯出包å«%{written_count}çš„CSV文件已作為附件加入到此電å­éƒµä»¶ä¸­ã€‚"
msgid "Your CSV import for project"
-msgstr ""
+msgstr "您的專案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 ""
+msgstr "您的 DevOps 報告從功能角度概述了您如何使用 GitLab。使用它們來查看您與其他組織的比較情æ³ï¼Œä»¥åŠæ‚¨çš„團隊之間的比較情æ³ã€‚"
msgid "Your GPG keys (%{count})"
-msgstr ""
+msgstr "您的GPG金鑰 (%{count})"
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 "由於大é‡ä¸æˆåŠŸçš„嘗試登入,您的 GitLab 帳號已被鎖定。您的帳號將在 %{duration} 自動解鎖,或者您å¯ä»¥å–®æ“Šä¸‹é¢çš„連çµç«‹å³è§£éŽ–。"
msgid "Your GitLab account request has been approved!"
-msgstr ""
+msgstr "您的GitLab帳號建立請求已被核准ï¼"
msgid "Your GitLab group"
-msgstr ""
+msgstr "您的GitLab群組"
msgid "Your Groups"
-msgstr ""
+msgstr "您的群組"
msgid "Your Personal Access Token was revoked"
-msgstr ""
+msgstr "您的個人存å–令牌已被åŠéŠ·ã€‚"
msgid "Your Projects (default)"
-msgstr ""
+msgstr "您的專案 (é è¨­å€¼)"
msgid "Your Projects' Activity"
-msgstr ""
+msgstr "您的專案動態"
msgid "Your SSH key has expired"
-msgstr ""
+msgstr "您的SSH金鑰已éŽæœŸ"
msgid "Your SSH key is expiring soon."
-msgstr ""
+msgstr "您的SSH金鑰å³å°‡åˆ°æœŸã€‚"
msgid "Your SSH key was deleted"
-msgstr ""
+msgstr "您的SSH金鑰已刪除"
msgid "Your SSH keys (%{count})"
-msgstr ""
+msgstr "您的SSH金鑰(%{count})"
msgid "Your To-Do List"
-msgstr ""
+msgstr "您的待辦事項列表"
msgid "Your U2F device did not send a valid JSON response."
-msgstr ""
+msgstr "您的 U2F 設備沒有發é€æœ‰æ•ˆçš„ JSON 響應。"
msgid "Your U2F device was registered!"
-msgstr ""
+msgstr "您的 U2F 設備已註冊ï¼"
msgid "Your WebAuthn device did not send a valid JSON response."
-msgstr ""
+msgstr "您的WebAuthn設備未發é€æœ‰æ•ˆçš„JSON回應。"
msgid "Your WebAuthn device was registered!"
-msgstr ""
+msgstr "您的WebAuthn設備已註冊ï¼"
msgid "Your access request to the %{source_type} has been withdrawn."
-msgstr ""
+msgstr "æ‚¨å° %{source_type} å­˜å–請求已被撤消。"
msgid "Your account has been deactivated"
-msgstr ""
+msgstr "您的帳號已被åœç”¨"
msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
-msgstr ""
+msgstr "您的帳號已被管ç†å“¡å‡çµã€‚è«‹é‡æ–°ç™»å…¥ä»¥é‡æ–°å•Ÿç”¨æ‚¨çš„帳號。"
msgid "Your account has been deactivated. You will not be able to: "
-msgstr ""
+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 ""
+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 ""
+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 ""
+msgstr "您的帳號已被鎖定。"
msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
-msgstr ""
+msgstr "您帳號使用群組「%{group_name}ã€çš„專用憑證,並且åªèƒ½é€éŽSSO進行更新。"
msgid "Your action succeeded."
-msgstr ""
+msgstr "您的æ“作æˆåŠŸã€‚"
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "您的應用程å¼(%{size})"
msgid "Your authorized applications"
-msgstr ""
+msgstr "您已授權的應用"
msgid "Your browser does not support iFrames"
-msgstr ""
+msgstr "您的ç€è¦½å™¨ä¸æ”¯æ´ iFrame"
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
-msgstr ""
+msgstr "您的ç€è¦½å™¨ä¸æ”¯æ´U2F。請使用Google Chromeæ¡Œé¢ç‰ˆï¼ˆ41或更高版本)。"
msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
-msgstr ""
+msgstr "您的ç€è¦½å™¨ä¸æ”¯æ´WebAuthn。請使用支æ´çš„ç€è¦½å™¨ï¼Œå¦‚Chrome(67+)或Firefox(60+)。"
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已開啟,å¯ä»¥æ交變更到%{branch_name}。"
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
-msgstr ""
+msgstr "變更已æ交。æ交 %{commitId} %{commitStats}"
msgid "Your changes have been saved"
-msgstr ""
+msgstr "您的變更已儲存"
msgid "Your changes have been successfully committed."
-msgstr ""
+msgstr "您的變更已æˆåŠŸæ交。"
msgid "Your comment could not be submitted because %{error}"
-msgstr ""
+msgstr "由於%{error}因此無法æ交您的留言"
msgid "Your comment could not be submitted! Please check your network connection and try again."
-msgstr ""
+msgstr "您的留言無法æ交ï¼è«‹æª¢æŸ¥æ‚¨çš„網路連接,然後é‡è©¦ã€‚"
msgid "Your comment could not be updated! Please check your network connection and try again."
-msgstr ""
+msgstr "您的留言無法更新ï¼è«‹æª¢æŸ¥æ‚¨çš„網路連接,然後é‡è©¦ã€‚"
msgid "Your comment will be discarded."
-msgstr ""
+msgstr "您的留言將被丟棄。"
msgid "Your commit email is used for web based operations, such as edits and merges."
-msgstr ""
+msgstr "您的æ交電å­éƒµä»¶ç”¨æ–¼åŸºæ–¼ web çš„æ“作,例如編輯和åˆä½µã€‚"
msgid "Your current password is required to register a two-factor authenticator app."
-msgstr ""
+msgstr "需è¦æ‚¨ç•¶å‰çš„密碼來註冊雙因å­é©—證程å¼ã€‚"
msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
-msgstr ""
+msgstr "已複製您的儀表æ¿ã€‚您å¯ä»¥%{web_ide_link_start}在此編輯%{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 "您的儀表æ¿å·²æ›´æ–°ã€‚您å¯ä»¥%{web_ide_link_start}在這裡進行編輯%{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 "如果沒有設定 %{openingTag}é‡å°ç‰¹å®šç¾¤çµ„çš„é›»å­éƒµä»¶åœ°å€%{closingTag},您的é è¨­é€šçŸ¥é›»å­éƒµä»¶å°‡ç”¨æ–¼å¸³è™Ÿé€šçŸ¥ã€‚"
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
-msgstr ""
+msgstr "您的部署æœå‹™å°‡å¤±æ•ˆï¼Œéœ€è¦åœ¨é‡æ–°å‘½å後手動修復æœå‹™ã€‚"
msgid "Your device is not compatible with GitLab. Please try another device"
-msgstr ""
+msgstr "您的設備與GitLabä¸ç›¸å®¹ã€‚請嘗試其他設備"
msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
-msgstr ""
+msgstr "您的設備需è¦è¨­å®šã€‚將其æ’入(如果需è¦ï¼‰ï¼Œç„¶å¾Œå–®æ“Šå·¦å´çš„按鈕。"
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
-msgstr ""
+msgstr "您的設備已æˆåŠŸè¨­å®šï¼è«‹çµ¦å®ƒå‘½å並將其註冊到GitLab伺æœå™¨ã€‚"
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 "您的文件必須包å«å為%{codeStart}title%{codeEnd}的列。%{codeStart}description%{codeEnd}列為å¯é¸çš„。å…許的最大文件大å°ç‚º10 MB。"
msgid "Your first project"
-msgstr ""
+msgstr "您的第一個專案"
+
+msgid "Your free group is now limited to %d member"
+msgid_plural "Your free group is now limited to %d members"
+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] "您的群組 %{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 ""
+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 ""
+msgstr "您的實例中包å«%{remaining_user_count}個使用者,而您的訂閱中包å«%{total_user_count}個使用者。您å¯ä»¥åŠ å…¥è¶…éŽæŽˆæ¬Šè¨±å¯ä¸­åŒ…å«çš„使用者數,我們將在您的下一份賬單中包括超é¡è²»ç”¨ã€‚"
msgid "Your instance has exceeded your subscription's licensed user count."
-msgstr ""
+msgstr "您的實例已超出您訂閱的授權許å¯ä½¿ç”¨è€…數é‡ã€‚"
msgid "Your instance is approaching its licensed user count"
-msgstr ""
+msgstr "您的實例å³å°‡é”到授權許å¯ä½¿ç”¨è€…數"
msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
-msgstr ""
+msgstr "您的議題正在匯入。完æˆå¾Œï¼Œæ‚¨å°‡æ”¶åˆ°ä¸€å°ç¢ºèªé›»å­éƒµä»¶ã€‚"
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
-msgstr ""
+msgstr "您的議題將在背景匯入。完æˆå¾Œï¼Œæ‚¨å°‡æ”¶åˆ°ä¸€å°ç¢ºèªé›»å­éƒµä»¶ã€‚"
msgid "Your license does not support on-call rotations"
-msgstr ""
+msgstr "您的授權許å¯ä¸æ”¯æ´ on-call 輪æ›"
msgid "Your license does not support on-call schedules"
-msgstr ""
+msgstr "您的授權許å¯ä¸æ”¯æ´å¾… on-cal 排程"
msgid "Your license is valid from"
-msgstr ""
+msgstr "您的授權許å¯æœ‰æ•ˆæœŸè‡ª"
msgid "Your membership in %{group} no longer expires."
-msgstr ""
+msgstr "您在 %{group} 中的æˆå“¡è³‡æ ¼ä¸å†éŽæœŸã€‚"
msgid "Your message here"
-msgstr ""
+msgstr "您的消æ¯é¡¯ç¤ºæ–¼æ­¤"
msgid "Your name"
-msgstr ""
+msgstr "您的åå­—"
msgid "Your new %{accessTokenType}"
-msgstr ""
+msgstr "您的新 %{accessTokenType}"
msgid "Your new %{accessTokenType} has been created."
-msgstr ""
+msgstr "您的新 %{accessTokenType} 已建立。"
msgid "Your new %{type}"
-msgstr ""
+msgstr "您的新%{type}"
msgid "Your new access token has been created."
-msgstr ""
+msgstr "您的新存å–令牌已建立。"
msgid "Your new comment"
-msgstr ""
+msgstr "您的新留言"
msgid "Your password reset token has expired."
-msgstr ""
+msgstr "您的密碼é‡è¨­ä»¤ç‰Œå·²éŽæœŸã€‚"
msgid "Your personal access token has expired"
-msgstr ""
+msgstr "您的個人存å–令牌已éŽæœŸ"
msgid "Your personal access tokens will expire in %{days_to_expire} days or less"
-msgstr ""
+msgstr "您的個人存å–令牌將在 %{days_to_expire} 天或更短的時間內到期"
msgid "Your primary email is used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}."
-msgstr ""
+msgstr "您的主è¦é›»å­éƒµä»¶ç”¨æ–¼é ­åƒæª¢æ¸¬ã€‚您å¯ä»¥åœ¨æ‚¨çš„ %{openingTag}個人資料設定%{closingTag}更改它。"
msgid "Your profile"
-msgstr ""
+msgstr "個人資料"
msgid "Your project has limited quotas and features"
-msgstr ""
+msgstr "您專案的é…é¡èˆ‡åŠŸèƒ½æ˜¯æœ‰é™åˆ¶çš„"
msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
-msgstr ""
+msgstr "您的專案é™åˆ¶ç‚º %{limit} 個專案ï¼è«‹èˆ‡æ‚¨çš„管ç†å“¡è¯çµ¡ä»¥å¢žåŠ å®ƒ"
msgid "Your project will be created at:"
-msgstr ""
+msgstr "您的專案將建立於:"
msgid "Your projects"
-msgstr ""
+msgstr "您的專案"
msgid "Your public email will be displayed on your public profile."
-msgstr ""
+msgstr "您的公開電å­éƒµä»¶å°‡é¡¯ç¤ºåœ¨æ‚¨çš„公開個人資料中。"
msgid "Your request for access could not be processed: %{error_message}"
-msgstr ""
+msgstr "無法處ç†æ‚¨çš„請求:%{error_message}"
msgid "Your request for access has been queued for review."
-msgstr ""
+msgstr "您的存å–請求已進入審核佇列。"
msgid "Your request to join %{host} has been rejected."
-msgstr ""
+msgstr "您在%{host}上註冊帳號的請求已被拒絕。"
msgid "Your requirements are being imported. Once finished, you'll receive a confirmation email."
-msgstr ""
+msgstr "您的需求正在匯入。匯入完æˆæ™‚您將收到一å°ç¢ºèªé›»å­éƒµä»¶ã€‚"
msgid "Your requirements will be imported in the background. After it's finished, you'll get a confirmation email."
-msgstr ""
-
-msgid "Your response has been recorded."
-msgstr ""
+msgstr "您的需求將在背景匯入。完æˆå¾Œï¼Œæ‚¨å°‡æ”¶åˆ°ä¸€å°ç¢ºèªé›»å­éƒµä»¶ã€‚"
msgid "Your search didn't match any commits."
-msgstr ""
+msgstr "您的æœå°‹æ²’有符åˆä»»ä½•æ交。"
msgid "Your search didn't match any commits. Try a different query."
-msgstr ""
+msgstr "您的æœå°‹ä¸¦æœªç¬¦åˆä»»ä½•æ交。請嘗試其他查詢。"
msgid "Your search timed out"
-msgstr ""
+msgstr "您的æœå°‹å·²é€¾æ™‚"
msgid "Your sign-in page is %{url}."
-msgstr ""
+msgstr "您的登入é é¢ç‚º%{url}。"
msgid "Your snippets"
-msgstr ""
+msgstr "您的程å¼ç¢¼ç‰‡æ®µ"
msgid "Your subscription expired!"
-msgstr ""
+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 in %{remaining_days} day."
-msgid_plural "Your subscription will expire in %{remaining_days} days."
-msgstr[0] ""
+msgid "Your subscription will expire on %{expires_on}"
+msgstr "您的訂閱將於 %{expires_on} 到期"
msgid "Your update failed. You can only upload one design when dropping onto an existing design."
-msgstr ""
+msgstr "您的更新失败,é€éŽæ‹–放到ç¾æœ‰è¨­è¨ˆçš„æ–¹å¼ï¼Œæ‚¨æ¯æ¬¡åªèƒ½ä¸Šå‚³ä¸€å€‹è¨­è¨ˆã€‚"
msgid "Your update failed. You must upload a file with the same file name when dropping onto an existing design."
-msgstr ""
+msgstr "您的更新失敗,拖放到ç¾æœ‰è¨­è¨ˆæ™‚,您必須上傳具有相åŒæª”å的文件。"
msgid "Your username is %{username}."
-msgstr ""
+msgstr "您的使用者å是%{username}。"
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
-msgstr ""
+msgstr "無法載入禪é“(ZenTao)議題。在禪é“(ZenTao)中查看議題,或é‡æ–°è¼‰å…¥é é¢ã€‚"
msgid "ZenTaoIntegration|This is a ZenTao user."
-msgstr ""
+msgstr "這是一個禪é“(ZenTao)使用者。"
msgid "ZenTaoIntegration|ZenTao user"
-msgstr ""
+msgstr "禪é“(ZenTao)使用者"
msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
-msgstr ""
+msgstr "從禪é“(ZenTao)æœå‹™è«‹æ±‚資料時發生錯誤。"
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
-msgstr ""
+msgstr "禪é“(ZenTao)實例的基礎 URL。"
msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
-msgstr ""
+msgstr "在您啟用此整åˆä¹‹å‰ï¼Œæ‚¨å¿…須設定禪é“(ZenTao)ã€‚æ¬²äº†è§£æ›´å¤šè©³æƒ…ï¼Œè«‹å­˜å– %{link_start}Zentao æ•´åˆæ–‡ä»¶%{link_end}。"
msgid "ZentaoIntegration|Enter new ZenTao API token"
-msgstr ""
+msgstr "輸入新的禪é“(ZenTao) API 令牌"
msgid "ZentaoIntegration|If different from Web URL."
-msgstr ""
+msgstr "如果與 Web URL ä¸åŒã€‚"
msgid "ZentaoIntegration|Open ZenTao"
-msgstr ""
+msgstr "打開禪é“(ZenTao)"
msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
-msgstr ""
+msgstr "使用禪é“(ZenTao)作為此專案的議題追蹤器。"
msgid "ZentaoIntegration|ZenTao"
-msgstr ""
+msgstr "禪é“(ZenTao)"
msgid "ZentaoIntegration|ZenTao API URL (optional)"
-msgstr ""
+msgstr "禪é“(ZenTao) API URL(å¯é¸ï¼‰"
msgid "ZentaoIntegration|ZenTao API token"
-msgstr ""
+msgstr "禪é“(ZenTao) API 令牌"
msgid "ZentaoIntegration|ZenTao Product ID"
-msgstr ""
+msgstr "禪é“(ZenTao)ç”¢å“ ID"
msgid "ZentaoIntegration|ZenTao Web URL"
-msgstr ""
+msgstr "禪é“(ZenTao) Web URL"
msgid "ZentaoIntegration|ZenTao issues"
-msgstr ""
+msgstr "禪é“(ZenTao)è­°é¡Œ"
msgid "Zoom meeting added"
-msgstr ""
+msgstr "已加入Zoom會議"
msgid "Zoom meeting removed"
-msgstr ""
+msgstr "已移除Zoom會議"
msgid "[No reason]"
-msgstr ""
+msgstr "[無原因]"
msgid "[REDACTED]"
-msgstr ""
+msgstr "[REDACTED]"
msgid "[Redacted]"
-msgstr ""
+msgstr "[Redacted]"
msgid "`end_time` should not exceed one month after `start_time`"
-msgstr ""
+msgstr "`end_time` ä¸æ‡‰è¶…éŽ `start_time` 後的一個月"
msgid "`start_time` should precede `end_time`"
-msgstr ""
+msgstr "`start_time` 應該在 `end_time` 之å‰"
msgid "`work_items_hierarchy` feature flag disabled for this project"
-msgstr ""
+msgstr "該專案ç¦ç”¨äº†â€œwork_items_hierarchyâ€çš„功能標誌"
msgid "a deleted user"
-msgstr ""
+msgstr "已刪除的使用者"
msgid "about 1 hour"
msgid_plural "about %d hours"
-msgstr[0] ""
+msgstr[0] "ç´„%då°æ™‚"
msgid "access:"
-msgstr ""
+msgstr "å­˜å–:"
msgid "added"
-msgstr ""
+msgstr "已加入"
msgid "added %{emails}"
-msgstr ""
+msgstr "加入了 %{emails}"
msgid "added a Zoom call to this issue"
-msgstr ""
+msgstr "加入Zoom通話到此議題"
msgid "ago"
msgstr "å‰"
msgid "alert"
-msgstr ""
+msgstr "警告"
msgid "allowed to fail"
-msgstr ""
+msgstr "å…許失敗"
msgid "already banned from namespace"
-msgstr ""
+msgstr "已被命å空間å°éŽ–"
msgid "already being used for another group or project %{timebox_name}."
-msgstr ""
+msgstr "已用於å¦ä¸€ç¾¤ç§Ÿæˆ–專案%{timebox_name}。"
msgid "already being used for another iteration within this cadence."
-msgstr ""
+msgstr "已用於此週期中的å¦ä¸€æ¬¡è¿­ä»£ã€‚"
msgid "already has a \"created\" issue link"
-msgstr ""
+msgstr "已經有\"已建立\"的議題連çµ"
msgid "already shared with this group"
-msgstr ""
+msgstr "已與該群組分享"
msgid "and"
-msgstr ""
+msgstr "和"
msgid "any-approver for the merge request already exists"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚的任一核准人(any-approver)已存在"
msgid "any-approver for the project already exists"
-msgstr ""
+msgstr "專案的任一核准人(any-approver)已存在"
msgid "approval"
msgid_plural "approvals"
-msgstr[0] ""
+msgstr[0] "核准"
msgid "archived"
-msgstr ""
+msgstr "已歸檔"
msgid "archived:"
-msgstr ""
+msgstr "歸檔"
msgid "artifacts"
-msgstr ""
+msgstr "產物"
msgid "assign yourself"
-msgstr ""
+msgstr "指派給自己"
+
+msgid "associated parent is confidential and can not have non-confidential children."
+msgstr "é—œè¯çš„上層是機密的,因此ä¸èƒ½å»ºç«‹éžæ©Ÿå¯†å­é …目。"
msgid "at"
-msgstr ""
+msgstr "æ–¼"
msgid "at least the Reporter role"
-msgstr ""
+msgstr "至少是報告者角色"
msgid "at least the Reporter role, the author, and assignees"
-msgstr ""
+msgstr "至少是報告者角色ã€ä½œè€…和指派者"
msgid "at risk"
-msgstr ""
+msgstr "存在風險"
msgid "attach a new file"
-msgstr ""
+msgstr "加入新附件"
msgid "authored"
-msgstr ""
+msgstr "編寫於"
msgid "banned user already exists"
-msgstr ""
+msgstr "ç¦æ­¢ä½¿ç”¨è€…已存在"
msgid "blocks"
-msgstr ""
+msgstr "å€å¡Š"
msgid "branch"
msgid_plural "branches"
-msgstr[0] ""
+msgstr[0] "分支"
msgid "branch name"
-msgstr ""
+msgstr "分支å稱"
msgid "builds"
-msgstr ""
+msgstr "建構"
msgid "by"
msgstr "來自"
msgid "cURL:"
-msgstr ""
+msgstr "cURL:"
msgid "can contain only letters of the Base64 alphabet (RFC4648) with the addition of '@', ':' and '.'"
-msgstr ""
+msgstr "åªèƒ½åŒ…å«Base64å­—æ¯è¡¨(RFC4648)中的字æ¯ï¼Œä»¥åŠã€Œ@ã€ã€ã€Œ:ã€å’Œã€Œ.ã€ã€‚"
msgid "can contain only lowercase letters, digits, and '_'."
-msgstr ""
+msgstr "åªèƒ½åŒ…å«å°å¯«å­—æ¯ã€æ•¸å­—和「_ã€ã€‚"
msgid "can not be changed for existing notes"
-msgstr ""
+msgstr "無法更改ç¾æœ‰è¨»é‡‹"
msgid "can not be set for this resource"
-msgstr ""
+msgstr "無法設定該資æº"
msgid "can not be set for this type of note"
-msgstr ""
+msgstr "無法設定該類型的註釋"
msgid "can only be changed by a group admin."
-msgstr ""
+msgstr "åªèƒ½ç”±ç¾¤çµ„管ç†å“¡æ›´æ”¹ã€‚"
msgid "can only have one escalation policy"
-msgstr ""
+msgstr "åªèƒ½æœ‰ä¸€å€‹å‡ç´šæ”¿ç­–"
msgid "can't be enabled when delayed group deletion is disabled"
-msgstr ""
+msgstr "如果延é²ç¾¤çµ„刪除被ç¦ç”¨ï¼Œå‰‡ç„¡æ³•å•Ÿç”¨"
msgid "can't be nil"
-msgstr ""
+msgstr "ä¸èƒ½ç‚º nil"
msgid "can't be solely blank"
-msgstr ""
+msgstr "ä¸èƒ½å®Œå…¨ç‚ºç©ºç™½"
msgid "can't be the same as the source project"
-msgstr ""
+msgstr "ä¸èƒ½å’Œä¾†æºå°ˆæ¡ˆç›¸åŒ"
msgid "can't include: %{invalid_storages}"
-msgstr ""
+msgstr "ä¸èƒ½åŒ…括: %{invalid_storages}"
msgid "can't reference a branch that does not exist"
-msgstr ""
+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 ""
+msgstr "ä¸èƒ½æ˜¯éŽåŽ»çš„日期"
msgid "cannot be changed"
-msgstr ""
+msgstr "無法被更改"
msgid "cannot be changed if a personal project has container registry tags."
-msgstr ""
+msgstr "如果個人專案具有容器映åƒåº«æ¨™ç±¤ï¼Œå‰‡ç„¡æ³•æ›´æ”¹ã€‚"
msgid "cannot be changed if shared runners are enabled"
-msgstr ""
+msgstr "如果啟用共用執行器(runners),則無法更改"
msgid "cannot be enabled"
-msgstr ""
+msgstr "無法啟用"
msgid "cannot be enabled because parent group does not allow it"
-msgstr ""
+msgstr "無法啟用,因為父群組ä¸å…許"
msgid "cannot be enabled because parent group has shared Runners disabled"
-msgstr ""
+msgstr "無法啟用,因為上層群組已åœç”¨å…±ç”¨åŸ·è¡Œå™¨"
msgid "cannot be enabled unless all domains have TLS certificates"
-msgstr ""
+msgstr "除éžæ‰€æœ‰åŸŸéƒ½å…·æœ‰TLS憑證,å¦å‰‡ç„¡æ³•å•Ÿç”¨"
msgid "cannot be enabled until a valid credit card is on file"
-msgstr ""
+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 ""
+msgstr "ä¸èƒ½ç”¨æ–¼ä½¿ç”¨è€…命å空間"
msgid "cannot block others"
-msgstr ""
+msgstr "無法阻止其他"
msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
-msgstr ""
+msgstr "ä¸èƒ½åŒ…å«HTML/XML標籤,包括尖括號(&lt;,&gt;)之間的任何文字。"
msgid "cannot include leading slash or directory traversal."
-msgstr ""
+msgstr "ä¸èƒ½ä»¥æ–œç·šé–‹é ­æˆ–ç€è¦½ç‰ˆæœ¬åº«ä»¥å¤–目錄。"
msgid "cannot itself be blocked"
-msgstr ""
+msgstr "本身ä¸èƒ½è¢«é˜»æ­¢"
msgid "cannot merge"
-msgstr ""
+msgstr "無法åˆä½µ"
msgid "change"
msgid_plural "changes"
-msgstr[0] ""
+msgstr[0] "變更"
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} é™ä½Ž%{danger_end}ã€%{same_start}%{sameNum} 相åŒ%{same_end} å’Œ %{success_start}%{improvedNum} 改善%{success_end}"
msgid "ciReport|%{degradedNum} degraded"
-msgstr ""
+msgstr "å·²é™ä½Ž%{degradedNum}"
msgid "ciReport|%{improvedNum} improved"
-msgstr ""
+msgstr "已改進%{improvedNum}"
msgid "ciReport|%{linkStartTag}Learn more about API Fuzzing%{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解有關 API 模糊測試的更多訊æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多有關容器安全掃æçš„è¨Šæ¯ %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解有關Coverage Fuzzing的更多訊æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多有關DAST %{linkEndTag}的訊æ¯"
msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多有關ä¾è³´é …掃æçš„è¨Šæ¯ %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多有關SAST %{linkEndTag}的訊æ¯"
msgid "ciReport|%{linkStartTag}Learn more about Secret Detection %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解更多關於密碼檢測的訊æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解有關程å¼ç¢¼è³ªé‡å ±å‘Šçš„更多訊æ¯%{linkEndTag}"
msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
-msgstr ""
+msgstr "%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} æ–¼ %{path}"
msgid "ciReport|%{remainingPackagesCount} more"
-msgstr ""
+msgstr "還有%{remainingPackagesCount} 個"
msgid "ciReport|%{reportType} is loading"
-msgstr ""
+msgstr "%{reportType} 載入中"
msgid "ciReport|%{reportType}: Loading resulted in an error"
-msgstr ""
+msgstr "%{reportType}:發生一個錯誤"
msgid "ciReport|%{sameNum} same"
-msgstr ""
+msgstr "相åŒ%{sameNum}"
+
+msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
+msgstr "%{scanner} 檢測到 %{boldStart}%{number}%{boldEnd} 個新的潛在 %{vulnStr}"
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
-msgstr ""
+msgstr "%{scanner} 檢測到 %{strong_start} %{number} %{strong_end} 個新的潛在 %{vulnStr}"
+
+msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
+msgstr "%{scanner} 未檢測到 %{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 ""
+msgstr ": 載入導致錯誤"
msgid "ciReport|API Fuzzing"
-msgstr ""
+msgstr "API模糊測試"
msgid "ciReport|API fuzzing"
-msgstr ""
+msgstr "API模糊測試"
msgid "ciReport|All clusters"
-msgstr ""
+msgstr "所有å¢é›†"
+
+msgid "ciReport|All images"
+msgstr "所有圖åƒ"
msgid "ciReport|All projects"
-msgstr ""
+msgstr "所有專案"
msgid "ciReport|All severities"
-msgstr ""
+msgstr "全部嚴é‡ç´šåˆ¥"
msgid "ciReport|All tools"
-msgstr ""
+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 ""
+msgstr "通éŽç”±å¤–å‘內檢查 Web 應用程å¼çš„已部署版本來分æžå·²çŸ¥æ¼æ´žã€‚DAST 的工作原ç†æ˜¯åœ¨æ‡‰ç”¨ç¨‹å¼é‹è¡Œæ™‚模擬å°æ‡‰ç”¨ç¨‹å¼çš„外部攻擊。"
msgid "ciReport|Automatically apply the patch in a new branch"
-msgstr ""
+msgstr "在新分支中自動套用更新"
msgid "ciReport|Base pipeline codequality artifact not found"
-msgstr ""
+msgstr "找ä¸åˆ°åŸºæº–æµæ°´ç·šç¨‹å¼ç¢¼è³ªé‡ç”¢ç‰©"
msgid "ciReport|Browser Performance"
-msgstr ""
+msgstr "ç€è¦½å™¨æ€§èƒ½"
msgid "ciReport|Browser performance test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžç€è¦½å™¨æ€§èƒ½æ¸¬è©¦æŒ‡æ¨™çµæžœ"
msgid "ciReport|Browser performance test metrics: "
-msgstr ""
+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[0] "ç€è¦½å™¨æ€§èƒ½æ¸¬è©¦æŒ‡æ¨™ï¼š%{strong_start}%{changesFound}%{strong_end} 個更改"
msgid "ciReport|Browser performance test metrics: No changes"
-msgstr ""
+msgstr "ç€è¦½å™¨æ€§èƒ½æ¸¬è©¦æŒ‡æ¨™ï¼šç„¡è®ŠåŒ–"
msgid "ciReport|Checks"
-msgstr ""
+msgstr "檢查"
msgid "ciReport|Cluster Image Scanning"
-msgstr ""
+msgstr "å¢é›†æ˜ åƒæŽƒæ"
msgid "ciReport|Code Quality"
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡(Code Quality)"
msgid "ciReport|Code Quality failed loading results"
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡(Code Quality)載入çµæžœå¤±æ•—"
msgid "ciReport|Code Quality test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžç¨‹å¼ç¢¼è³ªé‡(Code Quality)測試指標çµæžœ"
msgid "ciReport|Code quality degraded due to 1 new issue"
msgid_plural "ciReport|Code quality degraded due to %d new issues"
-msgstr[0] ""
+msgstr[0] "由於 %d 個新議題導致程å¼ç¢¼è³ªé‡ä¸‹é™"
msgid "ciReport|Code quality improved due to 1 resolved issue"
msgid_plural "ciReport|Code quality improved due to %d resolved issues"
-msgstr[0] ""
+msgstr[0] "由於 %d 個已解決的議題æ昇了程å¼ç¢¼è³ªé‡"
msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡(Code Quality)掃æ在åˆä½µçµæžœä¸­æª¢æ¸¬åˆ° %{issueCount} 個更改"
msgid "ciReport|Container Scanning"
-msgstr ""
+msgstr "容器掃æ"
msgid "ciReport|Container scanning"
-msgstr ""
+msgstr "容器掃æ"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
-msgstr ""
+msgstr "容器掃æå¯ä»¥æª¢æ¸¬Docker映åƒæª”中已知的安全æ¼æ´žã€‚"
msgid "ciReport|Could not dismiss vulnerability because the associated pipeline no longer exists. Refresh the page and try again."
-msgstr ""
+msgstr "無法解除æ¼æ´žï¼Œå› ç‚ºé—œè¯çš„æµæ°´ç·šä¸å†å­˜åœ¨ã€‚é‡æ–°æ•´ç†é é¢ä¸¦é‡è©¦ã€‚"
msgid "ciReport|Coverage Fuzzing"
-msgstr ""
+msgstr "覆蓋率模糊測試(Coverage Fuzzing)"
msgid "ciReport|Coverage fuzzing"
-msgstr ""
+msgstr "覆蓋率模糊測試(Coverage Fuzzing)"
msgid "ciReport|Create Jira issue"
-msgstr ""
+msgstr "建立 Jira 議題"
msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
-msgstr ""
+msgstr "建立一個åˆä½µè«‹æ±‚來執行這個解決方案,或者下載並手動應用補ä¸ã€‚"
msgid "ciReport|Create issue"
-msgstr ""
+msgstr "建立議題"
msgid "ciReport|DAST"
-msgstr ""
+msgstr "DAST"
msgid "ciReport|Dependency Scanning"
-msgstr ""
+msgstr "ä¾è³´æŽƒæ"
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "ä¾è³´é …掃æå¯ä»¥æª¢æ¸¬åŽŸå§‹ç¢¼ä¾è³´é …中已知的æ¼æ´žã€‚"
msgid "ciReport|Dependency scanning"
-msgstr ""
+msgstr "ä¾è³´é …掃æ"
msgid "ciReport|Download patch to resolve"
-msgstr ""
+msgstr "下載補ä¸ä»¥è§£æ±º"
msgid "ciReport|Download the patch to apply it manually"
-msgstr ""
+msgstr "下載補ä¸ä»¥æ‰‹å‹•æ‡‰ç”¨"
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
-msgstr ""
+msgstr "動態應用程å¼å®‰å…¨æ¸¬è©¦ï¼ˆDAST)å¯æª¢æ¸¬Web應用程å¼ä¸­çš„已知æ¼æ´žã€‚"
msgid "ciReport|Failed to load %{reportName} report"
-msgstr ""
+msgstr "無法載入 %{reportName} 報告"
msgid "ciReport|Failed to load Code Quality report"
-msgstr ""
+msgstr "載入程å¼ç¢¼è³ªé‡å ±å‘Šå¤±æ•—"
msgid "ciReport|Fixed"
-msgstr ""
+msgstr "已修復"
msgid "ciReport|Fixed:"
-msgstr ""
+msgstr "已修復:"
msgid "ciReport|Found %{issuesWithCount}"
-msgstr ""
+msgstr "找到%{issuesWithCount}"
msgid "ciReport|Full Report"
-msgstr ""
+msgstr "完整報告"
msgid "ciReport|IaC Scanning"
-msgstr ""
+msgstr "IaC 掃æ"
msgid "ciReport|Investigate this vulnerability by creating an issue"
-msgstr ""
+msgstr "é€éŽå»ºç«‹è­°é¡Œä¾†èª¿æŸ¥æ­¤æ¼æ´ž"
msgid "ciReport|License Compliance"
-msgstr ""
+msgstr "授權許å¯åˆè¦"
msgid "ciReport|License Compliance failed loading results"
-msgstr ""
+msgstr "授權許å¯åˆè¦è¼‰å…¥çµæžœå¤±æ•—"
msgid "ciReport|License Compliance test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžæŽˆæ¬Šè¨±å¯åˆè¦æ€§æ¸¬è©¦æŒ‡æ¨™çµæžœ"
msgid "ciReport|Load Performance"
-msgstr ""
+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[0] "負載性能測試指標檢測到 %{strong_start}%{changesFound}%{strong_end} 個更改"
msgid "ciReport|Load performance test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžæ€§èƒ½æ¸¬è©¦æŒ‡æ¨™çµæžœ"
msgid "ciReport|Load performance test metrics: "
-msgstr ""
+msgstr "負載性能測試指標:"
msgid "ciReport|Load performance test metrics: No changes"
-msgstr ""
+msgstr "負載性能測試指標:無變化"
msgid "ciReport|Loading %{reportName} report"
-msgstr ""
+msgstr "載入%{reportName} 報告"
msgid "ciReport|Loading Code Quality report"
-msgstr ""
+msgstr "載入程å¼ç¢¼è³ªé‡å ±å‘Š"
msgid "ciReport|Manage Licenses"
-msgstr ""
+msgstr "管ç†æŽˆæ¬Šè¨±å¯"
msgid "ciReport|Manage licenses"
-msgstr ""
+msgstr "管ç†æŽˆæ¬Šè¨±å¯"
msgid "ciReport|Manually Added"
-msgstr ""
+msgstr "已手動加入"
msgid "ciReport|New"
-msgstr ""
+msgstr "新增"
msgid "ciReport|No changes to Code Quality."
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡(Code Quality)無變化。"
msgid "ciReport|No changes to code quality"
-msgstr ""
+msgstr "程å¼ç¢¼è³ªé‡(Code Quality)無變化"
msgid "ciReport|No code quality issues found"
-msgstr ""
+msgstr "未發ç¾ç¨‹å¼ç¢¼è³ªé‡(Code Quality)å•é¡Œ"
msgid "ciReport|RPS"
-msgstr ""
+msgstr "RPS"
msgid "ciReport|Resolve with merge request"
-msgstr ""
+msgstr "é€éŽåˆä½µè«‹æ±‚解決"
msgid "ciReport|SAST"
-msgstr ""
+msgstr "SAST"
msgid "ciReport|Secret Detection"
-msgstr ""
+msgstr "Secret 檢測"
msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
-msgstr ""
+msgstr "Secret 檢測在æºç¨‹å¼ç¢¼ä¸­æª¢æ¸¬ Secrets 和憑據æ¼æ´žã€‚"
msgid "ciReport|Secret detection"
-msgstr ""
+msgstr "Secret 檢測"
msgid "ciReport|Security reports failed loading results"
-msgstr ""
+msgstr "安全報告載入çµæžœå¤±æ•—"
msgid "ciReport|Security scanning"
-msgstr ""
+msgstr "安全掃æ"
msgid "ciReport|Security scanning failed loading any results"
-msgstr ""
+msgstr "安全掃æ無法載入任何çµæžœ"
msgid "ciReport|Security scanning is loading"
-msgstr ""
+msgstr "正在載入安全掃æ"
msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
-msgstr ""
+msgstr "顯示 %{fetchedItems} 項,共 %{totalItems}項"
msgid "ciReport|Solution"
-msgstr ""
+msgstr "解決方案"
msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
-msgstr ""
+msgstr "éœæ…‹æ‡‰ç”¨ç¨‹å¼å®‰å…¨æ¸¬è©¦ï¼ˆSAST)å¯ä»¥æª¢æ¸¬åŽŸå§‹ç¢¼ä¸­å·²çŸ¥çš„æ¼æ´žã€‚"
msgid "ciReport|TTFB P90"
-msgstr ""
+msgstr "TTFB P90"
msgid "ciReport|TTFB P95"
-msgstr ""
+msgstr "TTFB P95"
msgid "ciReport|There was an error creating the issue. Please try again."
-msgstr ""
+msgstr "建立議題時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ciReport|There was an error creating the merge request. Please try again."
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
-msgstr ""
+msgstr "忽略此æ¼æ´žæ™‚發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ciReport|There was an error fetching the codequality report."
-msgstr ""
+msgstr "å–得程å¼ç¢¼è³ªé‡å ±å‘Šæ™‚發生錯誤。"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
-msgstr ""
+msgstr "å–消忽略æ“作時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
msgid "ciReport|This report contains all Code Quality issues in the source branch."
-msgstr ""
+msgstr "此報表包å«ä¾†æºåˆ†æ”¯ä¸­æ‰€æœ‰ç¨‹å¼ç¢¼è³ªé‡å•é¡Œã€‚"
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
+msgstr[0] "已用於 %{packagesString} 和 %{lastPackage}"
msgid "ciReport|View full report"
-msgstr ""
+msgstr "查看完整報告"
msgid "ciReport|in"
-msgstr ""
+msgstr "在"
msgid "ciReport|is loading"
-msgstr ""
+msgstr "正在載入"
msgid "ciReport|is loading, errors when loading results"
-msgstr ""
+msgstr "正在載入,載入çµæžœæ™‚發生錯誤"
+
+msgid "ci_database"
+msgstr "CI 資料庫"
msgid "closed"
-msgstr ""
+msgstr "已關閉"
msgid "closed %{timeago}"
-msgstr ""
+msgstr "於 %{timeago} 關閉"
msgid "closed issue"
-msgstr ""
+msgstr "已關閉議題"
msgid "collect usage information"
-msgstr ""
+msgstr "收集使用訊æ¯"
msgid "comment"
-msgstr ""
+msgstr "留言"
msgid "commented on %{link_to_project}"
-msgstr ""
+msgstr "留言 %{link_to_project}"
msgid "commit %{commit_id}"
-msgstr ""
+msgstr "æ交 %{commit_id}"
msgid "committed"
-msgstr ""
+msgstr "å·²æ交"
msgid "compliance violation has already been recorded"
-msgstr ""
+msgstr "é•è¦è¡Œç‚ºå·²è¢«è¨˜éŒ„"
+
+msgid "confidential parent can not be used if there are non-confidential children."
+msgstr "如果上層有éžæ©Ÿå¯†å­é …目,則ä¸èƒ½è¨­ç‚ºæ©Ÿå¯†ã€‚"
msgid "contacts can only be added to root groups"
-msgstr ""
+msgstr "è¯çµ¡äººåªèƒ½åŠ å…¥åˆ°æ ¹ç¾¤çµ„"
msgid "container registry images"
-msgstr ""
+msgstr "容器庫映åƒ"
msgid "contains URLs that exceed the 1024 character limit (%{urls})"
-msgstr ""
+msgstr "包å«è¶…éŽ 1024 個字元é™åˆ¶çš„ URL (%{urls})"
msgid "contains invalid URLs (%{urls})"
-msgstr ""
+msgstr "包å«ç„¡æ•ˆ URL (%{urls})"
msgid "contribute to this project."
-msgstr ""
+msgstr "為此專案åšå‡ºè²¢ç»ã€‚"
msgid "could not read private key, is the passphrase correct?"
-msgstr ""
+msgstr "無法讀å–ç§é‘°ï¼Œå¯†ç¢¼å£ä»¤æ˜¯å¦æ­£ç¢ºï¼Ÿ"
msgid "created"
-msgstr ""
+msgstr "已建立"
msgid "created %{issuable_created} by %{author}"
-msgstr ""
+msgstr "%{issuable_created}由%{author}建立"
msgid "created %{timeAgoString} by %{email} via %{user}"
-msgstr ""
+msgstr "ç”± %{user} é€šéŽ %{email} 建立於 %{timeAgoString}"
msgid "created %{timeAgo}"
-msgstr ""
+msgstr "建立於%{timeAgo}"
msgid "created %{timeAgo} by %{author}"
-msgstr ""
+msgstr "由 %{author} 建立於 %{timeAgo}"
msgid "created by"
-msgstr ""
+msgstr "建立人:"
msgid "data"
-msgstr ""
-
-msgid "database"
-msgstr ""
+msgstr "資料"
msgid "date must not be after 9999-12-31"
-msgstr ""
+msgstr "日期ä¸èƒ½åœ¨9999-12-31之後"
msgid "day"
msgid_plural "days"
msgstr[0] "天"
msgid "days"
-msgstr ""
+msgstr "天(s) "
msgid "default branch"
-msgstr ""
+msgstr "é è¨­åˆ†æ”¯"
msgid "deleted"
-msgstr ""
+msgstr "已刪除"
msgid "denied"
-msgstr ""
+msgstr "已拒絕"
msgid "deploy"
-msgstr ""
+msgstr "部署"
msgid "design"
-msgstr ""
+msgstr "設計"
msgid "disabled"
-msgstr ""
+msgstr "å·²åœç”¨"
msgid "does not exist"
-msgstr ""
+msgstr "ä¸å­˜åœ¨"
msgid "does not have a supported extension. Only %{extension_list} are supported"
-msgstr ""
+msgstr "沒有支æ´çš„副檔å。åªæ”¯æ´ %{extension_list} 副檔å"
msgid "does not match dast_site.project"
-msgstr ""
+msgstr "與 dast_site.project ä¸ç¬¦åˆ"
msgid "does not match dast_site_validation.project"
-msgstr ""
+msgstr "與 dast_site_validation.project ä¸ç¬¦åˆ"
msgid "download it"
-msgstr ""
+msgstr "下載"
msgid "draft"
msgid_plural "drafts"
-msgstr[0] ""
+msgstr[0] "è‰ç¨¿"
msgid "e.g. %{token}"
-msgstr ""
+msgstr "例如,%{token}"
msgid "element is not a hierarchy"
-msgstr ""
+msgstr "此元素並éžç¾¤çµ„層級"
msgid "eligible users"
-msgstr ""
+msgstr "符åˆæ¢ä»¶çš„使用者"
msgid "email '%{email}' is not a verified email."
-msgstr ""
+msgstr "é›»å­éƒµä»¶'%{email}'還未被驗證。"
msgid "email address settings"
-msgstr ""
+msgstr "é›»å­éƒµä»¶åœ°å€è¨­å®š"
msgid "enabled"
-msgstr ""
+msgstr "已啟用"
msgid "encrypted: needs to be a :required, :optional or :migrating!"
-msgstr ""
+msgstr "加密:必須是 :required,:optional 或 :migrating!"
msgid "ending with a reserved file extension is not allowed."
-msgstr ""
+msgstr "ä¸å…許以ä¿ç•™çš„文件副檔åçµå°¾ã€‚"
msgid "entries cannot be larger than 255 characters"
-msgstr ""
+msgstr "輸入ä¸èƒ½è¶…éŽ255個字元"
msgid "entries cannot be nil"
-msgstr ""
+msgstr "輸入ä¸èƒ½ç‚ºç©º"
msgid "entries cannot contain HTML tags"
-msgstr ""
+msgstr "輸入ä¸èƒ½åŒ…å«HTML標籤"
msgid "epic"
-msgstr ""
+msgstr "å²è©©"
msgid "error"
-msgstr ""
+msgstr "錯誤"
msgid "estimateCommand|%{slash_command} overwrites the total estimated time."
-msgstr ""
+msgstr "%{slash_command} 覆寫總估計時間。"
msgid "example.com"
-msgstr ""
+msgstr "example.com"
+
+msgid "exceeds maximum length (100 usernames)"
+msgstr "超éŽæœ€å¤§é•·åº¦ï¼ˆ100 個使用者å)"
msgid "exceeds the %{max_value_length} character limit"
-msgstr ""
+msgstr "è¶…éŽ %{max_value_length} 個字元的é™åˆ¶"
msgid "exceeds the limit of %{bytes} bytes"
-msgstr ""
+msgstr "超éŽ%{bytes}ä½å…ƒçµ„çš„é™åˆ¶"
msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
-msgstr ""
+msgstr "目錄å\"%{dirname}\"超éŽ%{bytes}字節的é™åˆ¶"
msgid "expired on %{timebox_due_date}"
-msgstr ""
+msgstr "已於%{timebox_due_date}éŽæœŸ"
msgid "expires on %{timebox_due_date}"
-msgstr ""
+msgstr "æ–¼%{timebox_due_date}éŽæœŸ"
msgid "failed"
-msgstr ""
+msgstr "已失敗"
msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
-msgstr ""
+msgstr "無法忽略關è¯çš„發ç¾(id=%{finding_id}): %{message}"
msgid "failed to dismiss finding: %{message}"
-msgstr ""
+msgstr "忽略發ç¾å¤±æ•—:%{message}"
msgid "failed to revert associated finding(id=%{finding_id}) to detected"
-msgstr ""
+msgstr "無法將關è¯çš„發ç¾(id=%{finding_id})回復為檢測到"
msgid "file"
msgid_plural "files"
-msgstr[0] ""
+msgstr[0] "文件"
msgid "finding is not found or is already attached to a vulnerability"
-msgstr ""
+msgstr "çµæžœç„¡æ³•æ‰¾åˆ°æˆ–已與æ¼æ´žé—œè¯ã€‚"
msgid "following"
-msgstr ""
+msgstr "已關注"
msgid "for"
-msgstr ""
+msgstr "å°æ–¼"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
-msgstr ""
+msgstr "使用%{link_to_merge_request}於%{link_to_merge_request_source_branch}"
msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
-msgstr ""
+msgstr "使用%{link_to_merge_request}ç”±%{link_to_merge_request_source_branch}åˆä½µåˆ°%{link_to_merge_request_target_branch}"
msgid "for %{link_to_pipeline_ref}"
-msgstr ""
+msgstr "æ–¼%{link_to_pipeline_ref}"
msgid "for %{ref}"
-msgstr ""
+msgstr "æ–¼%{ref}"
msgid "for this project"
-msgstr ""
+msgstr "å°æ–¼é€™å€‹å°ˆæ¡ˆ"
msgid "fork"
-msgstr ""
+msgstr "分å‰"
msgid "from"
-msgstr ""
+msgstr "來自"
msgid "from %d job"
msgid_plural "from %d jobs"
-msgstr[0] ""
+msgstr[0] "來自%d個作業"
msgid "frontmatter"
-msgstr ""
+msgstr "å‰æ²¿(frontmatter)"
msgid "group"
-msgstr ""
+msgstr "群組"
msgid "group access token"
-msgstr ""
+msgstr "群組存å–憑證"
msgid "group access tokens"
-msgstr ""
+msgstr "群組存å–憑證"
msgid "group members"
-msgstr ""
-
-msgid "group's CI/CD settings."
-msgstr ""
+msgstr "群組æˆå“¡"
msgid "groups"
-msgstr ""
+msgstr "群組"
msgid "groups and projects"
-msgstr ""
+msgstr "群組和專案"
msgid "groups only"
-msgstr ""
+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 ""
+msgstr "已經與其他æ¼æ´žæœ‰é—œè¯"
msgid "has already been taken"
-msgstr ""
+msgstr "已被使用"
msgid "has already been taken as Codename"
-msgstr ""
+msgstr "已經被作為暱稱代號"
msgid "has already been taken as Suite"
-msgstr ""
+msgstr "已被視為套件"
msgid "has been completed."
-msgstr ""
+msgstr "已完æˆã€‚"
msgid "has too deep level of nesting"
-msgstr ""
+msgstr "有太深的巢狀級別"
msgid "help"
-msgstr ""
+msgstr "幫助"
msgid "http:"
-msgstr ""
+msgstr "http:"
msgid "http://www.example.com"
-msgstr ""
+msgstr "http://www.example.com"
msgid "https://bamboo.example.com"
-msgstr ""
+msgstr "https://bambo.example.com"
msgid "https://your-bitbucket-server"
-msgstr ""
+msgstr "https://your-bitbucket-server"
msgid "i18n|%{language} (%{percent_translated}%% translated)"
-msgstr ""
+msgstr "%{language} (%{percent_translated}%% 已翻譯)"
+
+msgid "if"
+msgstr "如果"
msgid "image diff"
-msgstr ""
+msgstr "圖åƒå·®ç•°"
msgid "impersonation token"
-msgstr ""
+msgstr "身份模擬令牌"
msgid "impersonation tokens"
-msgstr ""
+msgstr "身份模擬令牌"
msgid "import flow"
-msgstr ""
+msgstr "匯入æµç¨‹"
msgid "in"
-msgstr ""
+msgstr "æ–¼"
msgid "in group %{link_to_group}"
-msgstr ""
+msgstr "在 %{link_to_group} 群組"
msgid "in project %{link_to_project}"
-msgstr ""
+msgstr "在 %{link_to_project} 專案"
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
+msgstr[0] "實體已完æˆ"
msgid "internal note"
-msgstr ""
+msgstr "內部說明"
msgid "invalid milestone state `%{state}`"
-msgstr ""
+msgstr "無效的里程碑狀態 `%{state}`"
msgid "is"
-msgstr ""
+msgstr "是"
msgid "is already associated to a GitLab Issue. New issue will not be associated."
-msgstr ""
+msgstr "已經與一個GitLab議題關è¯ã€‚新的議題將ä¸æœƒè¢«é—œè¯ã€‚"
msgid "is an invalid IP address range"
-msgstr ""
+msgstr "是無效的 IP ä½å€ç¯„åœ"
msgid "is blocked by"
-msgstr ""
+msgstr "已經由下述人員å°éŽ–"
msgid "is forbidden by a top-level group"
-msgstr ""
+msgstr "被最上層群組ç¦æ­¢"
msgid "is invalid because there is downstream lock"
-msgstr ""
+msgstr "因下游鎖定而無效"
msgid "is invalid because there is upstream lock"
-msgstr ""
+msgstr "因上游鎖定而無效"
msgid "is not"
-msgstr ""
+msgstr "ä¸æ˜¯"
msgid "is not a descendant of the Group owning the template"
-msgstr ""
+msgstr "ä¸æ˜¯æ“有範本的群組å­æˆå“¡"
msgid "is not a valid X509 certificate."
-msgstr ""
+msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509憑證。"
msgid "is not allowed for sign-up. Please use your regular email address."
-msgstr ""
+msgstr "ä¸å…許註冊。請使用您的常è¦é›»å­éƒµä»¶åœ°å€ã€‚"
msgid "is not allowed for this group."
-msgstr ""
+msgstr "在此群組中ä¸è¢«å…許。"
msgid "is not allowed for this project."
-msgstr ""
+msgstr "在此專案中ä¸è¢«å…許。"
msgid "is not allowed since the group is not top-level group."
-msgstr ""
+msgstr "ä¸è¢«å…許,因為該群組ä¸æ˜¯æœ€ä¸Šå±¤ç¾¤çµ„。"
msgid "is not allowed. Please use your regular email address."
-msgstr ""
+msgstr "ä¸è¢«å…許。請使用您的常è¦é›»å­éƒµä»¶åœ°å€ã€‚"
msgid "is not allowed. We do not currently support project-level iterations"
-msgstr ""
+msgstr "ä¸è¢«å…許。我們目å‰ä¸æ”¯æ´å°ˆæ¡ˆç´šè¿­ä»£"
msgid "is not in the group enforcing Group Managed Account"
-msgstr ""
+msgstr "ä¸åœ¨å¼·åˆ¶åŸ·è¡Œç¾¤çµ„託管帳號的群組中"
msgid "is not in the member group"
-msgstr ""
+msgstr "ä¸åœ¨æˆå“¡ç¾¤çµ„中"
msgid "is not the member project"
-msgstr ""
+msgstr "ä¸åœ¨æˆå“¡å°ˆæ¡ˆ"
msgid "is not valid. The iteration group has to match the iteration cadence group."
-msgstr ""
+msgstr "無效。迭代群組必須與迭代週期群組符åˆã€‚"
msgid "is read-only"
-msgstr ""
+msgstr "是唯讀"
msgid "is too long (%{current_value}). The maximum size is %{max_size}."
-msgstr ""
+msgstr "太長(%{current_value})。最大值為%{max_size}。"
msgid "is too long (maximum is %{count} characters)"
-msgstr ""
+msgstr "éŽé•·ï¼ˆæœ€é•·ç‚º %{count} 個字元)"
msgid "is too long (maximum is 100 entries)"
-msgstr ""
+msgstr "太長(最多100個æ¢ç›®ï¼‰"
msgid "is too long (maximum is 1000 entries)"
-msgstr ""
+msgstr "太長(最多1000個æ¢ç›®ï¼‰"
msgid "issue"
-msgstr ""
+msgstr "議題"
msgid "issues at risk"
-msgstr ""
+msgstr "存在風險的議題"
msgid "issues need attention"
msgstr "需è¦é—œæ³¨çš„è­°é¡Œ"
msgid "issues on track"
-msgstr ""
+msgstr "如期進行的議題"
msgid "it is larger than %{limit}"
-msgstr ""
+msgstr "大於%{limit}"
msgid "it is stored as a job artifact"
-msgstr ""
+msgstr "它是作為作業產物儲存的"
msgid "it is stored externally"
-msgstr ""
+msgstr "它是外部儲存的"
msgid "it is stored in LFS"
-msgstr ""
+msgstr "它儲存在LFS中"
msgid "it is too large"
-msgstr ""
+msgstr "它太大了"
msgid "jigsaw is not defined"
-msgstr ""
+msgstr "jigsaw 未定義"
msgid "kuromoji custom analyzer"
-msgstr ""
+msgstr "kuromoji 自訂分æžå™¨"
msgid "last commit:"
-msgstr ""
+msgstr "最後æ交:"
msgid "latest"
-msgstr ""
+msgstr "最新"
msgid "latest deployment"
-msgstr ""
+msgstr "最新部署"
msgid "latest version"
-msgstr ""
+msgstr "最新版本"
msgid "leave %{group_name}"
-msgstr ""
+msgstr "退出%{group_name}"
msgid "less than a minute"
-msgstr ""
+msgstr "ä¸åˆ°ä¸€åˆ†é˜"
msgid "level: %{level}"
-msgstr ""
+msgstr "等級: %{level}"
msgid "lfs objects"
-msgstr ""
+msgstr "LFS å°åƒ"
msgid "limit of %{project_limit} reached"
-msgstr ""
+msgstr "å·²é”到%{project_limit}çš„é™åˆ¶"
msgid "load it anyway"
-msgstr ""
+msgstr "ä»ç„¶è¼‰å…¥"
msgid "loading"
-msgstr ""
+msgstr "載入中"
msgid "locked by %{path_lock_user_name} %{created_at}"
-msgstr ""
+msgstr "被 %{path_lock_user_name} 在 %{created_at} 鎖定"
+
+msgid "main_database"
+msgstr "主資料庫"
msgid "manual"
-msgstr ""
+msgstr "手動"
msgid "math|Displaying this math block may cause performance issues on this page"
-msgstr ""
+msgstr "顯示此公å¼å€å¡Šå¯èƒ½æœƒå°Žè‡´æ­¤é é¢å‡ºç¾æ€§èƒ½å•é¡Œ"
msgid "math|There was an error rendering this math block"
-msgstr ""
+msgstr "繪製此數學表é”å¼æ™‚發生錯誤"
msgid "member"
msgid_plural "members"
-msgstr[0] ""
+msgstr[0] "æˆå“¡"
msgid "merge request"
msgid_plural "merge requests"
-msgstr[0] ""
+msgstr[0] "åˆä½µè«‹æ±‚"
msgid "mergedCommitsAdded|(commits were squashed)"
-msgstr ""
+msgstr "(æ交被壓縮)"
msgid "metric_id must be unique across a project"
-msgstr ""
+msgstr "metric_id必須是整個專案唯一的"
msgid "missing"
-msgstr ""
+msgstr "éºå¤±"
msgid "months"
-msgstr ""
+msgstr "月"
msgid "most recent deployment"
-msgstr ""
+msgstr "最近的部署"
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
-msgstr ""
+msgstr "%{commitCount} 和 %{mergeCommitCount} 將被加入到 %{targetBranch}%{squashedCommits}。"
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr ""
+msgstr "%{commitCount} 將被加入到 %{targetBranch}。"
msgid "mrWidgetCommitsAdded|1 merge commit"
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
-msgstr ""
-
-msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
-msgstr ""
+msgstr "1個åˆä½µæ交"
msgid "mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}."
-msgstr ""
+msgstr "變更以 %{mergeCommitSha}%{squashedCommits} åˆä½µåˆ° %{targetBranch}。"
msgid "mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}."
-msgstr ""
+msgstr "變更未åˆä½µåˆ° %{targetBranch}。"
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
-msgstr ""
+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 ""
+msgstr "使用åˆä½µè«‹æ±‚å‘您的專案æ出更改建議並與您的團隊討論。è¦é€²è¡Œæ›´æ”¹ï¼Œè«‹æŽ¨é€æ交或編輯此åˆä½µè«‹æ±‚以使用ä¸åŒçš„分支。使用 %{linkStart}CI/CD%{linkEnd},在åˆä½µä¹‹å‰è‡ªå‹•æ¸¬è©¦æ‚¨çš„更改。"
msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
-msgstr ""
+msgstr "%{boldHeaderStart}此處沒有æµæ°´ç·šã€‚%{boldHeaderEnd}"
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "mrWidget|%{linkStart}ç¾åœ¨è¨­å®š%{linkEnd} 來分æžæ‚¨çš„原始碼中已知的安全æ¼æ´žã€‚"
msgid "mrWidget|%{mergeError}."
-msgstr ""
+msgstr "%{mergeError}。"
msgid "mrWidget|%{mergeError}. Try again."
-msgstr ""
+msgstr "%{mergeError},å†è©¦ä¸€æ¬¡ã€‚"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 佔用 %{emphasisStart} ä¸‹é™ %{emphasisEnd},從 %{memoryFrom}MB 到 %{memoryTo}MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 佔用 %{emphasisStart} ä¸Šå‡ %{emphasisEnd},從 %{memoryFrom}MB 到 %{memoryTo}MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 記憶體 %{metricsLinkEnd} 佔用 %{emphasisStart} 無變化 %{emphasisEnd}, ä¿æŒåœ¨ %{memoryFrom}MB"
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
-msgstr ""
+msgstr "åˆä½µä½‡åˆ—是等待åˆä½µåˆ°ç›®æ¨™åˆ†æ”¯çš„åˆä½µè«‹æ±‚列表。æ¯å€‹åˆä½µè«‹æ±‚中的變動與先å‰åˆä½µè«‹æ±‚中的變動相çµåˆï¼Œç„¶å¾Œåœ¨åˆä½µå‰é€²è¡Œæ¸¬è©¦ã€‚"
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
-msgstr ""
+msgstr "æ–°åˆä½µä½‡åˆ—已經啟動,此åˆä½µè«‹æ±‚ä½æ–¼åˆä½µä½‡åˆ—中的第一ä½ã€‚"
msgid "mrWidget|Added to the merge train by %{merge_author}"
-msgstr ""
+msgstr "ç”± %{merge_author} 加入到åˆä½µä½‡åˆ—"
msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
-msgstr ""
+msgstr "已加入到åˆä½µä½‡åˆ—。當å‰æœ‰%{mergeTrainPosition}個åˆä½µè«‹æ±‚等待åˆä½µ"
msgid "mrWidget|An error occurred while removing your approval."
-msgstr ""
+msgstr "移除您的核准時發生錯誤。"
msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
-msgstr ""
+msgstr "檢索此åˆä½µè«‹æ±‚的核准資料時發生錯誤。"
msgid "mrWidget|An error occurred while submitting your approval."
-msgstr ""
+msgstr "éžäº¤æ‚¨çš„核準時發生錯誤。"
msgid "mrWidget|Approval is optional"
-msgstr ""
+msgstr "核准為å¯é¸"
msgid "mrWidget|Approval password is invalid."
-msgstr ""
+msgstr "核准密碼無效"
msgid "mrWidget|Approval rule %{rules} is invalid. GitLab has approved this rule automatically to unblock the merge request. %{link}"
-msgstr ""
+msgstr "審核è¦å‰‡ %{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 ""
+msgstr "核准"
msgid "mrWidget|Approve additionally"
-msgstr ""
+msgstr "é¡å¤–核准"
msgid "mrWidget|Approved by"
-msgstr ""
+msgstr "核准人:"
msgid "mrWidget|Approved by you"
-msgstr ""
+msgstr "由您核准"
msgid "mrWidget|Approved by you and others"
-msgstr ""
+msgstr "由您或其他人核准"
msgid "mrWidget|Assign yourself to these issues"
-msgstr ""
+msgstr "將這些議題指派給自己"
msgid "mrWidget|Assign yourself to this issue"
-msgstr ""
+msgstr "將這個議題指派給自己"
msgid "mrWidget|Cancel auto-merge"
-msgstr ""
+msgstr "å–消自動åˆä½µ"
msgid "mrWidget|Checking if merge request can be merged…"
-msgstr ""
+msgstr "正在檢查åˆä½µè«‹æ±‚是å¦å¯ä»¥åˆä½µâ€¦"
msgid "mrWidget|Cherry-pick"
-msgstr ""
+msgstr "æ€é¸(Cherry-pick)"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr ""
+msgstr "通éŽæ–°çš„åˆä½µè«‹æ±‚中æ€é¸(Cherry-pick)æ­¤åˆä½µè«‹æ±‚"
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "已關閉"
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "關閉:"
msgid "mrWidget|Closes issue"
msgid_plural "mrWidget|Closes issues"
-msgstr[0] ""
+msgstr[0] "關閉議題"
msgid "mrWidget|Create issue to resolve all threads"
-msgstr ""
+msgstr "建立議題來解決所有主題"
msgid "mrWidget|Delete source branch"
-msgstr ""
-
-msgid "mrWidget|Deletes the source branch"
-msgstr ""
+msgstr "刪除來æºåˆ†æ”¯"
msgid "mrWidget|Deployment statistics are not available currently"
-msgstr ""
+msgstr "部署統計訊æ¯ç•¶å‰ä¸å¯ç”¨"
msgid "mrWidget|Did not close"
-msgstr ""
+msgstr "未關閉"
msgid "mrWidget|Dismiss"
-msgstr ""
-
-msgid "mrWidget|Does not delete the source branch"
-msgstr ""
+msgstr "解除"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr ""
+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 ""
+msgstr "GitLab %{linkStart}CI/CD å¯ä»¥è‡ªå‹•æ§‹å»ºã€æ¸¬è©¦å’Œéƒ¨ç½²æ‚¨çš„應用程å¼ã€‚%{linkEnd} åªéœ€å¹¾åˆ†é˜å³å¯ä¸Šæ‰‹ï¼Œæˆ‘們å¯ä»¥å¹«åŠ©æ‚¨å»ºç«‹æµæ°´ç·šè¨­å®šæ–‡ä»¶ã€‚"
msgid "mrWidget|Hide %{widget} details"
-msgstr ""
+msgstr "éš±è— %{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 "如果本地版本庫中存在 %{type} 分支,å¯ä»¥ä½¿ç”¨æŒ‡ä»¤è¡Œæ‰‹å‹•åˆä½µé€™å€‹åˆä½µè«‹æ±‚。"
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 "如果最後一個æµæ°´ç·šåŸ·è¡Œåœ¨åˆ†å‰å°ˆæ¡ˆä¸­ï¼Œå®ƒå¯èƒ½ä¸æº–確。åˆä½µå‰ï¼Œæˆ‘們建議在這個專案中執行一æ¢æµæ°´ç·šã€‚"
msgid "mrWidget|Jump to first unresolved thread"
-msgstr ""
+msgstr "å‰å¾€åˆ°ç¬¬ä¸€å€‹æœªè§£æ±ºçš„主題"
msgid "mrWidget|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "載入部署統計訊æ¯ä¸­"
msgid "mrWidget|Mark as ready"
-msgstr ""
+msgstr "標示為已就緒"
msgid "mrWidget|Members who can merge are allowed to add commits."
-msgstr ""
+msgstr "å…許å¯ä»¥åˆä½µçš„æˆå“¡åŠ å…¥æ交。"
msgid "mrWidget|Mentions issue"
msgid_plural "mrWidget|Mentions issues"
-msgstr[0] ""
-
-msgid "mrWidget|Merge"
-msgstr ""
+msgstr[0] "æåŠçš„è­°é¡Œ"
msgid "mrWidget|Merge blocked: all required approvals must be given."
-msgstr ""
+msgstr "åˆä½µè¢«é˜»æ­¢ï¼šå¿…é ˆæ供所有必è¦çš„核准。"
msgid "mrWidget|Merge blocked: all threads must be resolved."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:必須解決所有主題。"
msgid "mrWidget|Merge blocked: denied licenses must be removed."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:必須移除被拒絕的授權許å¯ã€‚"
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:快進åˆä½µæ˜¯ä¸å¯èƒ½çš„。è¦åˆä½µé€™å€‹è«‹æ±‚,首先在本地變基(rebase)。"
msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:必須解決åˆä½µè¡çªã€‚"
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:æµæ°´ç·šå¿…é ˆæˆåŠŸã€‚等待手動完æˆæ“作。"
msgid "mrWidget|Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
-msgstr ""
+msgstr "åˆä½µå·²å—阻:æµæ°´ç·šå¿…é ˆæˆåŠŸã€‚推é€ä¸€å€‹ä¿®å¾©å¤±æ•—çš„æ交,或者%{linkStart}了解其它解決方案。%{linkEnd}"
msgid "mrWidget|Merge blocked: you can only merge after the above items are resolved."
-msgstr ""
+msgstr "åˆä½µå·²å—阻:解決上述å•é¡Œå¾Œæ‰èƒ½åˆä½µã€‚"
msgid "mrWidget|Merge failed."
-msgstr ""
+msgstr "åˆä½µå¤±æ•—。"
msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
-msgstr ""
+msgstr "åˆä½µä¸å¯ç”¨ï¼šåˆä½µè«‹æ±‚在歸檔專案上是唯讀的。"
msgid "mrWidget|Merged by"
-msgstr ""
-
-msgid "mrWidget|Merges changes into"
-msgstr ""
+msgstr "åˆä½µè€…:"
msgid "mrWidget|Merging! Changes are being shipped…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼æ­£åœ¨é€å‡ºè®Šæ›´â€¦"
msgid "mrWidget|Merging! Changes will land soon…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼å³å°‡å®Œæˆâ€¦"
msgid "mrWidget|Merging! Drum roll, please…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼è«‹ç¨å¾Œâ€¦"
msgid "mrWidget|Merging! Everything's good…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼ä¸€åˆ‡éƒ½å¾ˆå¥½â€¦"
msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼å³å°‡å®Œæˆ 5… 4… 3…"
msgid "mrWidget|Merging! Take a deep breath and relax…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼è«‹ç¨å€™â€¦"
msgid "mrWidget|Merging! The changes are leaving the station…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼è«‹ç¨å€™â€¦"
msgid "mrWidget|Merging! This is going to be great…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼è«‹ç¨å¾Œâ€¦"
msgid "mrWidget|Merging! We're almost there…"
-msgstr ""
+msgstr "åˆä½µä¸­ï¼å³å°‡å®Œæˆäº†â€¦"
msgid "mrWidget|More information"
-msgstr ""
+msgstr "更多訊æ¯"
msgid "mrWidget|No users match the rule's criteria."
-msgstr ""
+msgstr "沒有使用者符åˆè©²è¦å‰‡çš„標準。"
msgid "mrWidget|Please restore it or use a different %{type} branch."
-msgstr ""
+msgstr "請還原它或使用ä¸åŒçš„ %{type} 分支。"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "å·²å¯è‡ªå‹•åˆä½µã€‚請具有版本庫寫入權é™çš„使用者來åˆä½µæ­¤è«‹æ±‚"
msgid "mrWidget|Refresh"
-msgstr ""
+msgstr "é‡æ–°æ•´ç†"
msgid "mrWidget|Refresh now"
-msgstr ""
+msgstr "ç«‹å³é‡æ–°æ•´ç†"
msgid "mrWidget|Refreshing now"
-msgstr ""
+msgstr "ç«‹å³é‡æ–°æ•´ç†"
msgid "mrWidget|Remove from merge train"
-msgstr ""
+msgstr "從åˆä½µä½‡åˆ—中移除"
msgid "mrWidget|Resolve conflicts"
-msgstr ""
+msgstr "解決è¡çª"
msgid "mrWidget|Resolve locally"
-msgstr ""
+msgstr "本地解決"
msgid "mrWidget|Revert"
-msgstr ""
+msgstr "還原"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr ""
+msgstr "é€éŽæ–°çš„åˆä½µè«‹æ±‚中還原此åˆä½µè«‹æ±‚"
msgid "mrWidget|Revoke approval"
-msgstr ""
+msgstr "撤銷核准"
msgid "mrWidget|SAST and Secret Detection is not enabled."
-msgstr ""
+msgstr "SAST和Secret檢測未啟用。"
msgid "mrWidget|Set by %{merge_author} to be added to the merge train when the pipeline succeeds"
-msgstr ""
+msgstr "ç”±%{merge_author}設定為在æµæ°´ç·šæˆåŠŸæ™‚加入到åˆä½µä½‡åˆ—中"
msgid "mrWidget|Set by %{merge_author} to be merged automatically when the pipeline succeeds"
-msgstr ""
+msgstr "ç”±%{merge_author}設定為æµæ°´ç·šæˆåŠŸæ™‚自動åˆä½µ"
msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline succeeds"
-msgstr ""
+msgstr "ç”±%{merge_author}設定為在æµæ°´ç·šæˆåŠŸæ™‚å•Ÿå‹•åˆä½µä½‡åˆ—"
msgid "mrWidget|Show %{widget} details"
-msgstr ""
+msgstr "顯示 %{widget} 詳情"
msgid "mrWidget|The %{type} branch %{codeStart}%{name}%{codeEnd} does not exist."
-msgstr ""
-
-msgid "mrWidget|The changes were merged into"
-msgstr ""
-
-msgid "mrWidget|The changes were not merged into"
-msgstr ""
-
-msgid "mrWidget|The source branch has been deleted"
-msgstr ""
+msgstr "%{type} 分支 %{codeStart}%{name}%{codeEnd} ä¸å­˜åœ¨ã€‚"
msgid "mrWidget|The source branch is %{link} the target branch"
-msgstr ""
-
-msgid "mrWidget|The source branch is being deleted"
-msgstr ""
+msgstr "來æºåˆ†æ”¯æ˜¯ %{link} 的目標分支"
msgid "mrWidget|This merge request failed to be merged automatically"
-msgstr ""
+msgstr "該åˆä½µè«‹æ±‚未能自動åˆä½µ"
msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
-msgstr ""
+msgstr "è¦æ ¸å‡†æ­¤åˆä½µè«‹æ±‚,請輸入您的密碼。此專案需è¦æ‰€æœ‰æ ¸å‡†æ‰èƒ½èªè­‰ã€‚"
msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯å£“縮與åˆä½µæ交訊æ¯çš„範本。%{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯åˆä½µæ交訊æ¯çš„範本。 %{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "è¦æ›´æ”¹æ­¤é è¨­è¨Šæ¯ï¼Œè«‹ç·¨è¼¯å£“縮æ交訊æ¯çš„範本。 %{linkStart}了解更多訊æ¯ã€‚%{linkEnd}"
msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
-msgstr ""
+msgstr "è¦åˆä½µï¼Œå¿…須在標題或æ述中æ到Jira議題的key。"
msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
-msgstr ""
+msgstr "å¯ä»¥å¯«å…¥ä¾†æºæˆ–目標分支的使用者å¯ä»¥è§£æ±ºè¡çªã€‚"
msgid "mrWidget|What is a merge train?"
-msgstr ""
+msgstr "什麼是åˆä½µä½‡åˆ—?"
msgid "mrWidget|Your password"
-msgstr ""
+msgstr "您的密碼"
msgid "must be a Debian package"
-msgstr ""
+msgstr "必須是 Debian 軟體套件"
msgid "must be a boolean value"
-msgstr ""
+msgstr "必須是布林值"
msgid "must be a root namespace"
-msgstr ""
+msgstr "必須是根命å空間"
msgid "must be a valid IPv4 or IPv6 address"
-msgstr ""
+msgstr "必須是有效的IPv4或IPv6地å€"
msgid "must be a valid json schema"
-msgstr ""
+msgstr "必須是有效的 json schema"
msgid "must be after start"
-msgstr ""
+msgstr "必須在開始之後"
msgid "must be an email you have verified"
-msgstr ""
+msgstr "必須是您已驗證的電å­éƒµä»¶"
msgid "must be greater than start date"
-msgstr ""
+msgstr "必須大於開始日期"
msgid "must be inside the fork network"
-msgstr ""
+msgstr "必須在分å‰ï¼ˆfork)網路內"
msgid "must be less than the limit of %{tag_limit} tags"
-msgstr ""
+msgstr "å¿…é ˆå°æ–¼ %{tag_limit} 個標籤的數é‡é™åˆ¶"
msgid "must be set for a project namespace"
-msgstr ""
+msgstr "必須為專案命å空間設定"
msgid "must be unique by status and elapsed time within a policy"
-msgstr ""
+msgstr "必須在政策中的狀態和經éŽæ™‚間上是唯一的"
msgid "must have a repository"
-msgstr ""
+msgstr "必須有一個版本庫"
msgid "must match %{association}.project_id"
-msgstr ""
+msgstr "å¿…é ˆç¬¦åˆ %{association}.project_id"
msgid "my-awesome-group"
-msgstr ""
+msgstr "我的群組"
msgid "my-channel"
-msgstr ""
+msgstr "我的頻é“"
msgid "my-topic"
-msgstr ""
+msgstr "我的主題"
msgid "need attention"
-msgstr ""
+msgstr "需è¦é—œæ³¨"
msgid "needs to be between 10 minutes and 1 month"
-msgstr ""
+msgstr "需è¦åœ¨10分é˜è‡³1個月之間"
msgid "never"
-msgstr ""
+msgstr "從ä¸"
msgid "never expires"
-msgstr ""
+msgstr "æ°¸ä¸éŽæœŸ"
msgid "new merge request"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚"
msgid "no expiration"
-msgstr ""
+msgstr "ç„¡éŽæœŸ"
msgid "no name set"
-msgstr ""
+msgstr "未設定å稱"
msgid "no one can merge"
-msgstr ""
+msgstr "沒有人å¯ä»¥åˆä½µ"
msgid "no scopes selected"
-msgstr ""
+msgstr "未é¸æ“‡ç¯„åœ"
msgid "none"
-msgstr ""
+msgstr "ç„¡"
msgid "not authorized to create member"
-msgstr ""
+msgstr "未被授權建立æˆå“¡"
msgid "not authorized to update member"
-msgstr ""
+msgstr "未被授權建立æˆå“¡"
msgid "not found"
-msgstr ""
+msgstr "未找到"
msgid "nounSeries|%{firstItem} and %{lastItem}"
-msgstr ""
+msgstr "%{firstItem} 和 %{lastItem}"
msgid "nounSeries|%{item}"
-msgstr ""
+msgstr "%{item}"
msgid "nounSeries|%{item}, %{nextItem}"
-msgstr ""
+msgstr "%{item}, %{nextItem}"
msgid "nounSeries|%{item}, and %{lastItem}"
-msgstr ""
+msgstr "%{item},和 %{lastItem}"
msgid "on track"
-msgstr ""
+msgstr "如期進行"
msgid "only %{parent_types} can be parent of Task."
-msgstr ""
+msgstr "åªæœ‰ %{parent_types} å¯ä»¥æ˜¯ Task 的父級。"
msgid "only Task can be assigned as a child in hierarchy."
-msgstr ""
+msgstr "åªæœ‰ä»»å‹™å¯ä»¥è¢«åˆ†é…為層次çµæ§‹ä¸­çš„å­é …。"
msgid "only available on top-level groups."
-msgstr ""
+msgstr "åªèƒ½åœ¨æœ€ä¸Šå±¤ç¾¤çµ„中使用。"
msgid "open issue"
-msgstr ""
+msgstr "開啟議題"
msgid "or"
-msgstr ""
+msgstr "或"
msgid "organizations can only be added to root groups"
-msgstr ""
+msgstr "組織åªèƒ½è¢«åŠ å…¥åˆ°æ ¹(root)群組"
msgid "other card matches"
-msgstr ""
+msgstr "其他符åˆçš„å¡ç‰‡"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
+msgstr[0] "於總計%d個測試中"
msgid "packages"
-msgstr ""
+msgstr "軟體套件"
msgid "pages"
-msgstr ""
+msgstr "Pages"
msgid "parent"
msgid_plural "parents"
-msgstr[0] ""
+msgstr[0] "父級"
msgid "parent already has maximum number of children."
-msgstr ""
+msgstr "父級已經有最大數é‡çš„å­ç´šã€‚"
msgid "parent must be in the same project as child."
-msgstr ""
+msgstr "父級必須與å­ç´šåœ¨åŒä¸€å€‹å°ˆæ¡ˆä¸­ã€‚"
msgid "password"
-msgstr ""
+msgstr "密碼"
msgid "pending comment"
-msgstr ""
+msgstr "待處ç†çš„留言"
msgid "pending deletion"
-msgstr ""
+msgstr "待刪除"
msgid "personal access token"
-msgstr ""
+msgstr "個人存å–令牌(權æ–)"
msgid "personal access tokens"
-msgstr ""
+msgstr "個人存å–憑證"
msgid "pipeline"
-msgstr ""
+msgstr "æµæ°´ç·š"
msgid "pipeline schedules documentation"
-msgstr ""
+msgstr "æµæ°´ç·šè¨ˆåŠƒæ–‡ä»¶"
msgid "pipelineEditorWalkthrough|Let's do this!"
-msgstr ""
+msgstr "讓我們這樣åšï¼"
msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
-msgstr ""
+msgstr "了解 GitLab æµæ°´ç·šçš„工作原ç†"
msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
-msgstr ""
+msgstr "這個 %{codeStart}.gitlab-ci.yml%{codeEnd} 文件建立了一個簡單的測試æµæ°´ç·šã€‚"
msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
-msgstr ""
+msgstr "使用é é¢åº•éƒ¨çš„ %{boldStart}æ交修改%{boldEnd} 按鈕來執行æµæ°´ç·šã€‚"
msgid "pipelineEditorWalkthrough|You can use the file tree to view your pipeline configuration files. %{linkStart}Learn more%{linkEnd}"
-msgstr ""
+msgstr "您å¯ä»¥ä½¿ç”¨æ–‡ä»¶æ¨¹ä¾†æŸ¥çœ‹æ‚¨çš„æµæ°´ç·šçµ„態文件。 %{linkStart}了解更多%{linkEnd}"
msgid "point"
msgid_plural "points"
-msgstr[0] ""
+msgstr[0] "點"
msgid "previously merged commits"
-msgstr ""
+msgstr "å…ˆå‰åˆä½µçš„æ交"
msgid "private"
-msgstr ""
+msgstr "ç§æœ‰"
msgid "private key does not match certificate."
-msgstr ""
+msgstr "ç§é‘°èˆ‡æ†‘è­‰ä¸ç¬¦åˆã€‚"
msgid "processing"
-msgstr ""
+msgstr "處ç†ä¸­"
msgid "project"
msgid_plural "projects"
-msgstr[0] ""
+msgstr[0] "專案"
msgid "project access token"
-msgstr ""
+msgstr "專案存å–令牌(權æ–)"
msgid "project access tokens"
-msgstr ""
+msgstr "專案存å–憑證"
msgid "project bots cannot be added to other groups / projects"
-msgstr ""
+msgstr "專案機器人ä¸èƒ½åŠ å…¥åˆ°å…¶ä»–群組/專案"
msgid "project is read-only"
-msgstr ""
+msgstr "專案為唯讀"
msgid "project members"
-msgstr ""
+msgstr "專案æˆå“¡"
msgid "project name"
-msgstr ""
+msgstr "專案å稱"
msgid "project namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "專案命å空間ä¸èƒ½æ˜¯å¦ä¸€å€‹å‘½å空間的父級"
msgid "projects"
-msgstr ""
+msgstr "專案(s)"
msgid "reCAPTCHA"
-msgstr ""
+msgstr "reCAPTCHA"
msgid "reCAPTCHA helps prevent credential stuffing."
-msgstr ""
+msgstr "reCAPTCHA有助於防止憑證填充。"
msgid "reCAPTCHA private key"
-msgstr ""
+msgstr "reCAPTCHA ç§é‘°"
msgid "reCAPTCHA site key"
-msgstr ""
+msgstr "reCAPTCHA 公鑰"
msgid "recent activity"
-msgstr ""
+msgstr "最近活動"
msgid "register"
-msgstr ""
+msgstr "註冊"
msgid "relates to"
-msgstr ""
+msgstr "涉åŠåˆ°"
msgid "remaining"
-msgstr ""
+msgstr "剩餘"
msgid "remove"
-msgstr ""
+msgstr "移除"
msgid "remove due date"
-msgstr ""
+msgstr "移除截止日期"
msgid "remove start date"
-msgstr ""
+msgstr "移除開始日期"
msgid "remove weight"
-msgstr ""
+msgstr "移除權é‡"
msgid "removed"
-msgstr ""
+msgstr "已移除"
msgid "removed a Zoom call from this issue"
-msgstr ""
+msgstr "從目å‰è­°é¡Œä¸­ç§»é™¤Zoom通話"
msgid "rendered diff"
-msgstr ""
+msgstr "繪製差異"
msgid "reply"
msgid_plural "replies"
-msgstr[0] ""
+msgstr[0] "æ¢å›žå¾©"
msgid "reply should have same confidentiality as top-level note"
-msgstr ""
+msgstr "回復應與最上層註釋具有相åŒçš„機密性"
msgid "repositories"
-msgstr ""
+msgstr "版本庫"
msgid "repository:"
-msgstr ""
+msgstr "版本庫:"
+
+msgid "role's base access level does not match the access level of the membership"
+msgstr "基於角色的存å–等級ä¸åŒ¹é…æˆå“¡çš„å­˜å–等級"
msgid "satisfied"
-msgstr ""
+msgstr "滿足"
msgid "scan-execution-policy: policy not applied, %{policy_path} file is invalid"
-msgstr ""
+msgstr "掃æ執行政策:政策未套用, %{policy_path} 文件無效"
msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing"
-msgstr ""
+msgstr "掃æ執行政策:政策未套用,缺少 %{policy_path} 文件"
msgid "security Reports|There was an error creating the merge request"
-msgstr ""
+msgstr "建立åˆä½µè«‹æ±‚時發生錯誤"
+
+msgid "selective_code_owner_removals can only be enabled when retain_approvals_on_push is enabled"
+msgstr "åªæœ‰åœ¨å•Ÿç”¨äº† retain_approvals_on_push 時æ‰èƒ½å•Ÿç”¨ selective_code_owner_removals"
msgid "severity|Blocker"
-msgstr ""
+msgstr "攔截器"
msgid "severity|Critical"
-msgstr ""
+msgstr "åš´é‡"
msgid "severity|High"
-msgstr ""
+msgstr "高"
msgid "severity|Info"
-msgstr ""
+msgstr "訊æ¯"
msgid "severity|Low"
-msgstr ""
+msgstr "低"
msgid "severity|Major"
-msgstr ""
+msgstr "主è¦"
msgid "severity|Medium"
-msgstr ""
+msgstr "中"
msgid "severity|Minor"
-msgstr ""
+msgstr "次è¦"
msgid "severity|None"
-msgstr ""
+msgstr "ç„¡"
msgid "severity|Unknown"
-msgstr ""
+msgstr "未知"
msgid "should be an array of %{object_name} objects"
-msgstr ""
+msgstr "應該是%{object_name}物件的陣列"
msgid "should be an array of existing usernames. %{invalid} does not exist"
-msgstr ""
+msgstr "應為ç¾å­˜ä½¿ç”¨è€…å稱的陣列, %{invalid} ä¸å­˜åœ¨"
msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
-msgstr ""
+msgstr "應該從高於或等於從%{group_name} 群組繼承的æˆå“¡èº«ä»½%{access}"
msgid "show %{count} more"
-msgstr ""
+msgstr "å†é¡¯ç¤º%{count}é …"
msgid "show fewer"
-msgstr ""
+msgstr "顯示較少"
msgid "show less"
-msgstr ""
+msgstr "顯示較少"
msgid "sign in"
-msgstr ""
+msgstr "登入"
msgid "smartcn custom analyzer"
-msgstr ""
+msgstr "smartcn自訂分æžå™¨"
msgid "source"
-msgstr ""
+msgstr "來æº"
msgid "source diff"
-msgstr ""
+msgstr "來æºå·®ç•°"
msgid "specified top is not part of the tree"
-msgstr ""
+msgstr "指定的最上層ä¸å±¬æ–¼è©²æ¨¹ç‹€çš„一部份"
msgid "spendCommand|%{slash_command} adds or subtracts time already spent."
-msgstr ""
+msgstr "%{slash_command} 增加或減少已經花費的時間。"
msgid "ssh:"
-msgstr ""
+msgstr "ssh:"
msgid "started a discussion on %{design_link}"
-msgstr ""
+msgstr "開始討論%{design_link}"
msgid "started on %{timebox_start_date}"
-msgstr ""
+msgstr "開始於%{timebox_start_date}"
msgid "starts on %{timebox_start_date}"
-msgstr ""
+msgstr "開始於%{timebox_start_date}"
msgid "structure is too large"
-msgstr ""
+msgstr "çµæ§‹éŽå¤§"
msgid "stuck"
-msgstr ""
+msgstr "阻塞"
msgid "success"
-msgstr ""
+msgstr "æˆåŠŸ"
msgid "suggestPipeline|1/2: Choose a template"
-msgstr ""
+msgstr "1/2:é¸æ“‡ç¯„本"
msgid "suggestPipeline|2/2: Commit your changes"
-msgstr ""
+msgstr "2/2:æ交更改"
msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
-msgstr ""
+msgstr "é¸æ“‡%{boldStart}Code Quality%{boldEnd}來加入一個測試程å¼ç¢¼è³ªé‡çš„æµæ°´ç·šã€‚"
msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
-msgstr ""
+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 ""
+msgstr "我們正在加入GitLab CI設定文件,以將æµæ°´ç·šåŠ å…¥åˆ°å°ˆæ¡ˆä¸­ã€‚您也å¯ä»¥æ‰‹å‹•å»ºç«‹ï¼Œä½†æˆ‘們建議您從一個立å³å¯ç”¨çš„GitLab範本開始。"
msgid "tag name"
-msgstr ""
+msgstr "標籤å稱"
msgid "terraform states"
-msgstr ""
+msgstr "terraform 狀態"
msgid "the correct format."
-msgstr ""
+msgstr "正確的格å¼ã€‚"
-msgid "the following epic(s)"
-msgstr ""
+msgid "the following epics"
+msgstr "下列å²è©©"
-msgid "the following incident(s) or issue(s)"
-msgstr ""
+msgid "the following incidents or issues"
+msgstr "如下事件或議題"
-msgid "the following issue(s)"
-msgstr ""
+msgid "the following issues"
+msgstr "下列議題"
msgid "the wiki"
-msgstr ""
+msgstr "wiki"
msgid "then"
-msgstr ""
+msgstr "然後"
msgid "this document"
-msgstr ""
+msgstr "此文件"
msgid "time summary"
-msgstr ""
+msgstr "時間總計"
msgid "today"
-msgstr ""
+msgstr "今天"
msgid "toggle collapse"
-msgstr ""
+msgstr "切æ›æ‘ºç–Š"
+
+msgid "total must be less than or equal to %{size}"
+msgstr "總值必須å°æ–¼æˆ–等於 %{size}"
msgid "triggered"
-msgstr ""
+msgstr "已觸發"
msgid "two-factor authentication settings"
-msgstr ""
+msgstr "雙因å­èªè­‰è¨­å®š"
msgid "type must be Debian"
-msgstr ""
+msgstr "類型必須是 Debian"
msgid "type parameter is missing and is required"
-msgstr ""
+msgstr "缺少類型åƒæ•¸ä¸¦ä¸”是必需的"
msgid "unicode domains should use IDNA encoding"
-msgstr ""
+msgstr "Unicode 網域應使用 IDNA 編碼"
msgid "updated"
-msgstr ""
+msgstr "已更新"
msgid "updated %{timeAgo}"
-msgstr ""
+msgstr "æ›´æ–°æ–¼%{timeAgo}"
msgid "updated %{time_ago}"
-msgstr ""
+msgstr "æ›´æ–°æ–¼%{time_ago}"
msgid "uploads"
-msgstr ""
+msgstr "上傳"
msgid "user avatar"
-msgstr ""
+msgstr "使用者頭åƒ"
msgid "user namespace cannot be the parent of another namespace"
-msgstr ""
+msgstr "使用者命å空間ä¸èƒ½æ˜¯å¦ä¸€å€‹å‘½å空間的父級"
msgid "username"
-msgstr ""
+msgstr "使用者å稱"
msgid "v%{version} published %{timeAgo}"
-msgstr ""
+msgstr "v%{version} 發布於%{timeAgo}"
msgid "value for '%{storage}' must be an integer"
-msgstr ""
+msgstr "'%{storage}'的值必須是整數"
msgid "value for '%{storage}' must be between 0 and 100"
-msgstr ""
+msgstr "'%{storage}'的值必須在 0 到 100 之間"
msgid "verify ownership"
-msgstr ""
+msgstr "驗證所有權"
msgid "version %{versionIndex}"
-msgstr ""
+msgstr "版本 %{versionIndex}"
msgid "via %{closed_via}"
-msgstr ""
+msgstr "é€éŽ%{closed_via}"
msgid "via merge request %{link}"
-msgstr ""
+msgstr "é€éŽåˆä½µè«‹æ±‚%{link}"
msgid "view it on GitLab"
-msgstr ""
+msgstr "在GitLab中查看"
msgid "view the blob"
-msgstr ""
+msgstr "查看blob"
msgid "view the source"
-msgstr ""
+msgstr "查看來æºç¨‹å¼ç¢¼"
msgid "visibility"
-msgstr ""
+msgstr "å¯è¦‹æ€§"
msgid "vulnerability"
msgid_plural "vulnerabilities"
-msgstr[0] ""
+msgstr[0] "æ¼æ´ž"
msgid "vulnerability|Add a comment"
-msgstr ""
+msgstr "加入留言"
msgid "vulnerability|Add a comment or reason for dismissal"
-msgstr ""
+msgstr "加入留言或忽略的原因"
msgid "vulnerability|Add comment"
-msgstr ""
+msgstr "加入留言"
msgid "vulnerability|Add comment & dismiss"
-msgstr ""
+msgstr "加入留言並忽略"
msgid "vulnerability|Add comment and dismiss"
-msgstr ""
+msgstr "加入留言並忽略"
msgid "vulnerability|Dismiss vulnerability"
-msgstr ""
+msgstr "忽略æ¼æ´ž"
msgid "vulnerability|Save comment"
-msgstr ""
+msgstr "儲存留言"
msgid "vulnerability|Undo dismiss"
-msgstr ""
+msgstr "撤銷忽略"
msgid "vulnerability|dismissed"
-msgstr ""
+msgstr "已忽略"
msgid "was scheduled to merge after pipeline succeeds by"
-msgstr ""
+msgstr "åˆä½µè«‹æ±‚已安排在æµæ°´ç·šæˆåŠŸå¾Œåˆä½µã€‚åˆä½µäºº: "
msgid "wiki page"
-msgstr ""
+msgstr "wikié é¢"
msgid "with %{additions} additions, %{deletions} deletions."
-msgstr ""
+msgstr "共 %{additions} 行新增,%{deletions} 行刪除。"
msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
-msgstr ""
+msgstr "å°‡éŽæœŸæ™‚間從 %{old_expiry} 變更到 %{new_expiry}"
msgid "with expiry remaining unchanged at %{old_expiry}"
-msgstr ""
+msgstr "å°‡éŽæœŸæ™‚間維æŒåœ¨ %{old_expiry} ä¸è®Š"
msgid "yaml invalid"
-msgstr ""
+msgstr "yaml 無效"
msgid "your GitLab instance"
-msgstr ""
+msgstr "您的 GitLab 實例"
msgid "your group (%{group_name})"
-msgstr ""
+msgstr "您的群組(%{group_name})"
msgid "your settings"
-msgstr ""
+msgstr "你的設定"
msgid "{group}"
-msgstr ""
+msgstr "{group}"
msgid "{project}"
-msgstr ""
+msgstr "{project}"
msgid "✔"
-msgstr ""
+msgstr "✔"
diff --git a/package.json b/package.json
index 2924ef910d3..ecd30dd2560 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,6 @@
"jest:ci": "jest --config jest.config.js --ci --coverage --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
"jest:ci:minimal": "jest --config jest.config.js --ci --coverage --findRelatedTests $(cat tmp/changed_files.txt) --passWithNoTests --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
"jest:integration": "jest --config jest.config.integration.js",
- "jsdoc": "jsdoc -c config/jsdocs.config.js",
"lint:eslint": "node scripts/frontend/eslint.js",
"lint:eslint:fix": "node scripts/frontend/eslint.js --fix",
"lint:eslint:all": "node scripts/frontend/eslint.js .",
@@ -46,51 +45,51 @@
"webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js"
},
"dependencies": {
+ "@_ueberdosis/prosemirror-tables": "^1.1.3",
"@apollo/client": "^3.5.10",
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "2.28.0",
- "@gitlab/ui": "42.22.0",
+ "@gitlab/svgs": "3.1.0",
+ "@gitlab/ui": "43.6.0",
"@gitlab/visual-review-tools": "1.7.3",
"@rails/actioncable": "6.1.4-7",
"@rails/ujs": "6.1.4-7",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
- "@tiptap/core": "^2.0.0-beta.176",
- "@tiptap/extension-blockquote": "^2.0.0-beta.26",
- "@tiptap/extension-bold": "^2.0.0-beta.26",
- "@tiptap/extension-bullet-list": "^2.0.0-beta.26",
- "@tiptap/extension-code": "^2.0.0-beta.26",
- "@tiptap/extension-code-block-lowlight": "2.0.0-beta.68",
- "@tiptap/extension-document": "^2.0.0-beta.15",
- "@tiptap/extension-dropcursor": "^2.0.0-beta.25",
- "@tiptap/extension-gapcursor": "^2.0.0-beta.34",
- "@tiptap/extension-hard-break": "^2.0.0-beta.30",
- "@tiptap/extension-heading": "^2.0.0-beta.26",
- "@tiptap/extension-history": "^2.0.0-beta.21",
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.31",
- "@tiptap/extension-image": "^2.0.0-beta.27",
- "@tiptap/extension-italic": "^2.0.0-beta.26",
- "@tiptap/extension-link": "^2.0.0-beta.38",
- "@tiptap/extension-list-item": "^2.0.0-beta.20",
- "@tiptap/extension-ordered-list": "^2.0.0-beta.27",
- "@tiptap/extension-paragraph": "^2.0.0-beta.23",
- "@tiptap/extension-strike": "^2.0.0-beta.27",
- "@tiptap/extension-subscript": "^2.0.0-beta.10",
- "@tiptap/extension-superscript": "^2.0.0-beta.10",
- "@tiptap/extension-table": "^2.0.0-beta.49",
- "@tiptap/extension-table-cell": "^2.0.0-beta.20",
- "@tiptap/extension-table-header": "^2.0.0-beta.22",
- "@tiptap/extension-table-row": "^2.0.0-beta.19",
- "@tiptap/extension-task-item": "^2.0.0-beta.32",
- "@tiptap/extension-task-list": "^2.0.0-beta.26",
- "@tiptap/extension-text": "^2.0.0-beta.15",
- "@tiptap/vue-2": "^2.0.0-beta.79",
+ "@tiptap/core": "^2.0.0-beta.182",
+ "@tiptap/extension-blockquote": "^2.0.0-beta.29",
+ "@tiptap/extension-bold": "^2.0.0-beta.28",
+ "@tiptap/extension-bullet-list": "^2.0.0-beta.29",
+ "@tiptap/extension-code": "^2.0.0-beta.28",
+ "@tiptap/extension-code-block-lowlight": "2.0.0-beta.73",
+ "@tiptap/extension-document": "^2.0.0-beta.17",
+ "@tiptap/extension-dropcursor": "^2.0.0-beta.28",
+ "@tiptap/extension-gapcursor": "^2.0.0-beta.38",
+ "@tiptap/extension-hard-break": "^2.0.0-beta.33",
+ "@tiptap/extension-heading": "^2.0.0-beta.29",
+ "@tiptap/extension-history": "^2.0.0-beta.25",
+ "@tiptap/extension-horizontal-rule": "^2.0.0-beta.36",
+ "@tiptap/extension-image": "^2.0.0-beta.30",
+ "@tiptap/extension-italic": "^2.0.0-beta.28",
+ "@tiptap/extension-link": "^2.0.0-beta.43",
+ "@tiptap/extension-list-item": "^2.0.0-beta.23",
+ "@tiptap/extension-ordered-list": "^2.0.0-beta.30",
+ "@tiptap/extension-paragraph": "^2.0.0-beta.26",
+ "@tiptap/extension-strike": "^2.0.0-beta.29",
+ "@tiptap/extension-subscript": "^2.0.0-beta.13",
+ "@tiptap/extension-superscript": "^2.0.0-beta.13",
+ "@tiptap/extension-table": "^2.0.0-beta.54",
+ "@tiptap/extension-table-cell": "^2.0.0-beta.23",
+ "@tiptap/extension-table-header": "^2.0.0-beta.25",
+ "@tiptap/extension-table-row": "^2.0.0-beta.22",
+ "@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/vue-2": "^2.0.0-beta.84",
"apollo-upload-client": "15.0.0",
"autosize": "^5.0.1",
- "aws-sdk": "^2.637.0",
"axios": "^0.24.0",
"babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4",
@@ -98,11 +97,10 @@
"cache-loader": "^4.1.0",
"canvas-confetti": "^1.4.0",
"clipboard": "^2.0.8",
- "codemirror": "^5.48.4",
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.23.5",
+ "core-js": "^3.24.1",
"cron-validator": "^1.1.1",
"cronstrue": "^1.122.0",
"cropper": "^2.3.0",
@@ -113,7 +111,7 @@
"dateformat": "^5.0.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "dompurify": "^2.3.9",
+ "dompurify": "^2.3.10",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^10.0.0",
@@ -123,7 +121,7 @@
"graphql": "^15.7.2",
"graphql-tag": "^2.11.0",
"highlight.js": "^11.5.1",
- "immer": "^7.0.7",
+ "immer": "^9.0.15",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
"jquery": "^3.6.0",
@@ -135,14 +133,15 @@
"katex": "^0.13.2",
"lodash": "^4.17.20",
"lowlight": "^2.6.1",
- "marked": "^0.3.12",
+ "marked": "^4.0.18",
"mathjax": "3",
- "mermaid": "^9.1.1",
+ "mdurl": "^1.0.1",
+ "mermaid": "^9.1.3",
"micromatch": "^4.0.5",
"minimatch": "^3.0.4",
- "monaco-editor": "^0.25.2",
- "monaco-editor-webpack-plugin": "^4.0.0",
- "monaco-yaml": "^2.5.1",
+ "monaco-editor": "^0.30.1",
+ "monaco-editor-webpack-plugin": "^6.0.0",
+ "monaco-yaml": "3.0.0",
"mousetrap": "1.6.5",
"papaparse": "^5.3.1",
"patch-package": "^6.4.7",
@@ -152,14 +151,14 @@
"portal-vue": "^2.1.7",
"postcss": "8.4.14",
"prismjs": "^1.21.0",
- "prosemirror-markdown": "1.8.0",
- "prosemirror-model": "^1.16.1",
- "prosemirror-state": "^1.3.4",
- "prosemirror-tables": "^1.1.1",
- "prosemirror-view": "^1.23.13",
+ "prosemirror-markdown": "1.9.1",
+ "prosemirror-model": "^1.18.1",
+ "prosemirror-state": "^1.4.1",
+ "prosemirror-view": "^1.26.1",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"rehype-raw": "^6.1.1",
+ "remark-frontmatter": "^4.0.1",
"remark-gfm": "^3.0.1",
"remark-parse": "^10.0.1",
"remark-rehype": "^10.1.0",
@@ -199,23 +198,22 @@
"yaml": "^2.0.0-10"
},
"devDependencies": {
- "@gitlab/eslint-plugin": "13.1.0",
+ "@gitlab/eslint-plugin": "16.0.0",
"@gitlab/stylelint-config": "4.1.0",
- "@graphql-eslint/eslint-plugin": "3.10.6",
+ "@graphql-eslint/eslint-plugin": "3.10.7",
"@testing-library/dom": "^7.16.2",
- "@types/jest": "^26.0.24",
+ "@types/jest": "^27.5.1",
"@vue/test-utils": "1.3.0",
- "acorn": "^6.3.0",
+ "@vue/vue2-jest": "^27.0.0",
"ajv": "^8.10.0",
"ajv-formats": "^2.1.1",
"axios-mock-adapter": "^1.15.0",
- "babel-jest": "^26.5.2",
+ "babel-jest": "^27.5.1",
"chalk": "^2.4.1",
"cheerio": "^1.0.0-rc.9",
"commander": "^2.20.3",
"custom-jquery-matchers": "^2.1.0",
- "docdash": "^1.0.2",
- "eslint": "7.32.0",
+ "eslint": "8.22.0",
"eslint-import-resolver-jest": "3.0.2",
"eslint-import-resolver-webpack": "0.13.2",
"eslint-plugin-no-jquery": "2.7.0",
@@ -225,35 +223,32 @@
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-report": "^3.0.0",
"istanbul-reports": "^3.0.0",
- "jest": "^26.5.2",
+ "jest": "^27.5.1",
"jest-canvas-mock": "^2.1.2",
- "jest-diff": "^27.4.6",
- "jest-environment-jsdom": "^26.5.2",
+ "jest-diff": "^27.5.1",
+ "jest-environment-jsdom": "^27.5.1",
+ "jest-jasmine2": "^27.5.1",
"jest-junit": "^12.0.0",
"jest-raw-loader": "^1.0.1",
"jest-transform-graphql": "^2.1.0",
- "jest-util": "^26.5.2",
- "jsdoc": "^3.5.5",
- "jsdoc-vue": "^1.0.0",
+ "jest-util": "^27.5.1",
"markdownlint-cli": "0.31.0",
- "md5": "^2.2.1",
"miragejs": "^0.1.40",
"mock-apollo-client": "1.2.0",
- "nodemon": "^2.0.4",
+ "nodemon": "^2.0.19",
"prettier": "2.2.1",
- "prosemirror-schema-basic": "^1.1.2",
- "prosemirror-schema-list": "^1.1.6",
- "prosemirror-test-builder": "^1.0.6",
+ "prosemirror-schema-basic": "^1.2.0",
+ "prosemirror-schema-list": "^1.2.0",
+ "prosemirror-test-builder": "^1.1.0",
"purgecss": "^4.0.3",
"purgecss-from-html": "^4.0.3",
"sass": "^1.49.9",
"stylelint": "^14.9.1",
"timezone-mock": "^1.0.8",
- "vue-jest": "4.0.1",
- "webpack-dev-server": "4.9.3",
+ "webpack-dev-server": "4.10.0",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
- "yarn-deduplicate": "^5.0.0"
+ "yarn-deduplicate": "^5.0.2"
},
"blockedDependencies": {
"bootstrap-vue": "https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#bootstrapvue"
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 9611b3653eb..341732ab56f 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,5 +1,5 @@
ARG DOCKER_VERSION=20.10.14
-ARG CHROME_VERSION=101
+ARG CHROME_VERSION=103
ARG QA_BUILD_TARGET=qa
FROM registry.gitlab.com/gitlab-org/gitlab-build-images/debian-bullseye-ruby-2.7:bundler-2.3-git-2.33-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-383-kubectl-1.23 AS qa
diff --git a/qa/Gemfile b/qa/Gemfile
index d8d00400563..7c46d35bb48 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -29,12 +29,16 @@ gem 'influxdb-client', '~> 1.17'
gem 'terminal-table', '~> 3.0.0', require: false
gem 'slack-notifier', '~> 2.4', require: false
gem 'fog-google', '~> 1.17', require: false
+gem "warning", "~> 1.3"
gem 'confiner', '~> 0.3'
gem 'chemlab', '~> 0.9'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
+# dependencies for jenkins client
+gem 'nokogiri', '~> 1.12'
+
gem 'deprecation_toolkit', '~> 1.5.1', require: false
group :development do
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 71484c30c9a..ff382788c5a 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -148,8 +148,8 @@ GEM
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.9.0)
google-apis-core (>= 0.4, < 2.a)
- google-cloud-env (1.5.0)
- faraday (>= 0.17.3, < 2.0)
+ google-cloud-env (1.6.0)
+ faraday (>= 0.17.3, < 3.0)
googleauth (1.1.0)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
@@ -198,12 +198,12 @@ GEM
multi_xml (0.6.0)
multipart-post (2.1.1)
netrc (0.11.0)
- nokogiri (1.13.6)
+ nokogiri (1.13.8)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
- octokit (4.21.0)
- faraday (>= 0.9)
- sawyer (~> 0.8.0, >= 0.5.3)
+ octokit (4.25.1)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
oj (3.13.11)
os (1.1.4)
parallel (1.19.2)
@@ -270,9 +270,9 @@ GEM
rake (>= 0.8.1)
ruby2_keywords (0.0.4)
rubyzip (2.3.2)
- sawyer (0.8.2)
+ sawyer (0.9.2)
addressable (>= 2.3.5)
- faraday (> 0.8, < 2.0)
+ faraday (>= 0.17.3, < 3)
selenium-webdriver (4.0.3)
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
@@ -307,6 +307,7 @@ GEM
procto (~> 0.0.2)
uuid (2.3.9)
macaddr (~> 1.0)
+ warning (1.3.0)
watir (6.19.1)
regexp_parser (>= 1.2, < 3)
selenium-webdriver (>= 3.142.7)
@@ -337,6 +338,7 @@ DEPENDENCIES
gitlab-qa (~> 7)
influxdb-client (~> 1.17)
knapsack (~> 4.0)
+ nokogiri (~> 1.12)
octokit (~> 4.21)
parallel (~> 1.19)
parallel_tests (~> 2.29)
@@ -354,6 +356,7 @@ DEPENDENCIES
slack-notifier (~> 2.4)
terminal-table (~> 3.0.0)
timecop (~> 0.9.1)
+ warning (~> 1.3)
webdrivers (~> 5.0)
zeitwerk (~> 2.4)
diff --git a/qa/Rakefile b/qa/Rakefile
index e4d38d8294f..d3e39d8ed1e 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-# rubocop:disable Rails/RakeEnvironment
require_relative "qa"
@@ -86,4 +85,8 @@ namespace :test_resources do
QA::Tools::TestResourcesHandler.new.download(args[:ci_project_name])
end
end
-# rubocop:enable Rails/RakeEnvironment
+
+desc "Deletes user's projects"
+task :delete_user_projects, [:delete_before, :dry_run] do |t, args|
+ QA::Tools::DeleteUserProjects.new(args).run
+end
diff --git a/qa/qa.rb b/qa/qa.rb
index 7d2f363143b..dd6462cfe27 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -17,8 +17,6 @@ require 'active_support/core_ext/hash'
require 'active_support/core_ext/object/blank'
require 'rainbow/refinement'
-require_relative 'qa/support/fips'
-
module QA
root = "#{__dir__}/qa"
@@ -67,7 +65,8 @@ module QA
"registry_tls" => "RegistryTLS",
"jetbrains" => "JetBrains",
"vscode" => "VSCode",
- "registry_with_cdn" => "RegistryWithCDN"
+ "registry_with_cdn" => "RegistryWithCDN",
+ "fips" => "FIPS"
)
# Configure knapsack at the very begining of the setup
@@ -77,3 +76,10 @@ module QA
loader.setup
end
+
+# Custom warning processing
+Warning.process do |warning|
+ QA::Runtime::Logger.warn(warning.strip)
+end
+
+Warning.ignore(/already initialized constant Chemlab::Vendor|previous definition of Vendor was here/)
diff --git a/qa/qa/ce/strategy.rb b/qa/qa/ce/strategy.rb
index bf08f887c7d..981b60d1920 100644
--- a/qa/qa/ce/strategy.rb
+++ b/qa/qa/ce/strategy.rb
@@ -6,6 +6,16 @@ module QA
extend self
def perform_before_hooks
+ if QA::Runtime::Env.admin_personal_access_token.present?
+ QA::Resource::PersonalAccessTokenCache.set_token_for_username(QA::Runtime::User.admin_username,
+ QA::Runtime::Env.admin_personal_access_token)
+ end
+
+ if QA::Runtime::Env.personal_access_token.present? && QA::Runtime::Env.user_username.present?
+ QA::Resource::PersonalAccessTokenCache.set_token_for_username(QA::Runtime::Env.user_username,
+ QA::Runtime::Env.personal_access_token)
+ end
+
# The login page could take some time to load the first time it is visited.
# We visit the login page and wait for it to properly load only once before the tests.
QA::Runtime::Logger.info("Performing sanity check for environment!")
diff --git a/qa/qa/flow/purchase.rb b/qa/qa/flow/purchase.rb
index 5558e177685..e0efa8a8178 100644
--- a/qa/qa/flow/purchase.rb
+++ b/qa/qa/flow/purchase.rb
@@ -108,3 +108,5 @@ module QA
end
end
end
+
+QA::Flow::Purchase.prepend_mod_with('Flow::Purchase', namespace: QA)
diff --git a/qa/qa/page/admin/overview/users/components/impersonation_tokens.rb b/qa/qa/page/admin/overview/users/components/impersonation_tokens.rb
new file mode 100644
index 00000000000..0d0c92ce29d
--- /dev/null
+++ b/qa/qa/page/admin/overview/users/components/impersonation_tokens.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Overview
+ module Users
+ module Components
+ class ImpersonationTokens < Page::Base
+ include Page::Component::AccessTokens
+ include Page::Component::ConfirmModal
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/overview/users/show.rb b/qa/qa/page/admin/overview/users/show.rb
index be73f3d80bf..2fde3ac2c6d 100644
--- a/qa/qa/page/admin/overview/users/show.rb
+++ b/qa/qa/page/admin/overview/users/show.rb
@@ -8,6 +8,7 @@ module QA
class Show < QA::Page::Base
view 'app/views/admin/users/_head.html.haml' do
element :impersonate_user_link
+ element :impersonation_tokens_tab
end
view 'app/views/admin/users/show.html.haml' do
@@ -32,6 +33,11 @@ module QA
click_element(:user_actions_dropdown_toggle, username: user.username)
end
+ def go_to_impersonation_tokens(&block)
+ navigate_to_tab(:impersonation_tokens_tab)
+ Users::Components::ImpersonationTokens.perform(&block)
+ end
+
def click_impersonate_user
click_element(:impersonate_user_link)
end
@@ -50,6 +56,20 @@ module QA
click_element :approve_user_button
click_element :approve_user_confirm_button
end
+
+ private
+
+ def navigate_to_tab(element_name)
+ wait_until(reload: false) do
+ click_element element_name unless on_impersontation_tokens_tab?
+
+ on_impersontation_tokens_tab?(wait: 10)
+ end
+ end
+
+ def on_impersontation_tokens_tab?(wait: 1)
+ has_css?(".active", text: 'Impersonation Tokens', wait: wait)
+ end
end
end
end
diff --git a/qa/qa/page/alert/auto_devops_alert.rb b/qa/qa/page/alert/auto_devops_alert.rb
index 8f66c805b77..26801c4996c 100644
--- a/qa/qa/page/alert/auto_devops_alert.rb
+++ b/qa/qa/page/alert/auto_devops_alert.rb
@@ -5,7 +5,7 @@ module QA
module Alert
class AutoDevopsAlert < Page::Base
view 'app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml' do
- element :auto_devops_banner
+ element :auto_devops_banner_content
end
end
end
diff --git a/qa/qa/page/component/access_tokens.rb b/qa/qa/page/component/access_tokens.rb
index f143e5b9e1f..36c0f8c2f00 100644
--- a/qa/qa/page/component/access_tokens.rb
+++ b/qa/qa/page/component/access_tokens.rb
@@ -23,6 +23,10 @@ module QA
element :create_token_button
end
+ base.view 'app/views/shared/access_tokens/_table.html.haml' do
+ element :revoke_button
+ end
+
base.view 'app/views/shared/tokens/_scopes_form.html.haml' do
element :api_label, '#{scope}_label' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
end
@@ -54,7 +58,11 @@ module QA
def fill_expiry_date(date)
date = date.to_s if date.is_a?(Date)
- Date.strptime(date, '%Y-%m-%d') rescue ArgumentError raise "Expiry date must be in YYYY-MM-DD format"
+ begin
+ Date.strptime(date, '%Y-%m-%d')
+ rescue ArgumentError
+ raise "Expiry date must be in YYYY-MM-DD format"
+ end
fill_element(:expiry_date_field, date)
end
diff --git a/qa/qa/page/component/ci_badge_link.rb b/qa/qa/page/component/ci_badge_link.rb
index 4c053f1d6a9..2ba198621fc 100644
--- a/qa/qa/page/component/ci_badge_link.rb
+++ b/qa/qa/page/component/ci_badge_link.rb
@@ -40,8 +40,6 @@ module QA
find_element(:status_badge).text
end
- private
-
def completed?(timeout: 60)
wait_until(reload: false, sleep_interval: 3.0, max_duration: timeout) do
COMPLETED_STATUSES.include?(status_badge)
diff --git a/qa/qa/page/component/confirm_modal.rb b/qa/qa/page/component/confirm_modal.rb
index 76200490f66..4d1cf30c392 100644
--- a/qa/qa/page/component/confirm_modal.rb
+++ b/qa/qa/page/component/confirm_modal.rb
@@ -12,21 +12,26 @@ module QA
base.view 'app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue' do
element :confirm_ok_button
end
+
+ base.view 'app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue' do
+ element :confirm_danger_modal_button
+ element :confirm_danger_field
+ end
end
def fill_confirmation_text(text)
- fill_element(:confirm_input, text)
+ fill_element(:confirm_danger_field, text)
end
def wait_for_confirm_button_enabled
wait_until(reload: false) do
- !find_element(:confirm_button).disabled?
+ !find_element(:confirm_danger_modal_button).disabled?
end
end
def confirm_transfer
wait_for_confirm_button_enabled
- click_element(:confirm_button)
+ click_element(:confirm_danger_modal_button)
end
def click_confirmation_ok_button
diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb
index f82bb81a3fc..ff61c91f0f6 100644
--- a/qa/qa/page/component/groups_filter.rb
+++ b/qa/qa/page/component/groups_filter.rb
@@ -10,7 +10,7 @@ module QA
super
base.view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter
+ element :groups_filter_field
end
base.view 'app/assets/javascripts/groups/components/groups.vue' do
@@ -22,7 +22,7 @@ module QA
def has_filtered_group?(name)
# Filter and submit to reload the page and only retrieve the filtered results
- find_element(:groups_filter).set(name).send_keys(:return)
+ find_element(:groups_filter_field).set(name).send_keys(:return)
# Since we submitted after filtering, the presence of
# groups_list_tree_container means we have the complete filtered list
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 4131731111f..68da89dc81d 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -35,7 +35,7 @@ module QA
end
base.view 'app/views/shared/issuable/_sidebar.html.haml' do
- element :assignee_block
+ element :assignee_block_container
element :milestone_block
end
@@ -127,7 +127,7 @@ module QA
private
def wait_assignees_block_finish_loading
- within_element(:assignee_block) do
+ within_element(:assignee_block_container) do
wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
finished_loading_block?
yield
diff --git a/qa/qa/page/component/namespace_select.rb b/qa/qa/page/component/namespace_select.rb
index 924e1af876c..4dbcb39ced6 100644
--- a/qa/qa/page/component/namespace_select.rb
+++ b/qa/qa/page/component/namespace_select.rb
@@ -13,6 +13,7 @@ module QA
element :namespaces_list
element :namespaces_list_groups
element :namespaces_list_item
+ element :namespaces_list_search
end
end
@@ -20,6 +21,10 @@ module QA
click_element :namespaces_list
within_element(:namespaces_list) do
+ find_element(:namespaces_list_search).fill_in(with: item)
+
+ wait_for_requests
+
find_element(:namespaces_list_item, text: item).click
end
end
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index 74b6c6b2d5e..22b9a4c8b0d 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -48,7 +48,9 @@ module QA
end
def use_new_editor
- click_element(:editing_mode_button, mode: 'Edit rich text')
+ within_element(:editing_mode_button) do
+ find('label', text: 'Rich text').click
+ end
wait_until(reload: false) do
has_element?(:content_editor_container)
diff --git a/qa/qa/page/dashboard/groups.rb b/qa/qa/page/dashboard/groups.rb
index 52853376f17..644d19d6bcb 100644
--- a/qa/qa/page/dashboard/groups.rb
+++ b/qa/qa/page/dashboard/groups.rb
@@ -6,13 +6,8 @@ module QA
class Groups < Page::Base
include Page::Component::GroupsFilter
- view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter, 'search_field_tag :filter' # rubocop:disable QA/ElementWithPattern
- element :groups_filter_placeholder, 'Search by name' # rubocop:disable QA/ElementWithPattern
- end
-
view 'app/views/dashboard/_groups_head.html.haml' do
- element :new_group_button, 'link_to _("New group")' # rubocop:disable QA/ElementWithPattern
+ element :new_group_button
end
def has_group?(name)
@@ -26,7 +21,7 @@ module QA
end
def click_new_group
- click_on 'New group'
+ click_element(:new_group_button)
end
end
end
diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb
index a0b42598962..10529ed69e1 100644
--- a/qa/qa/page/dashboard/projects.rb
+++ b/qa/qa/page/dashboard/projects.rb
@@ -5,7 +5,7 @@ module QA
module Dashboard
class Projects < Page::Base
view 'app/views/shared/projects/_search_form.html.haml' do
- element :project_filter_form, required: true
+ element :project_filter_form_container, required: true
end
view 'app/views/shared/projects/_project.html.haml' do
@@ -24,7 +24,7 @@ module QA
end
def filter_by_name(name)
- within_element(:project_filter_form) do
+ within_element(:project_filter_form_container) do
fill_in :name, with: name
end
end
@@ -44,7 +44,7 @@ module QA
end
def clear_project_filter
- fill_element(:project_filter_form, "")
+ fill_element(:project_filter_form_container, "")
end
end
end
diff --git a/qa/qa/page/file/edit.rb b/qa/qa/page/file/edit.rb
index 3a4a1837b1c..d2b8c8260fd 100644
--- a/qa/qa/page/file/edit.rb
+++ b/qa/qa/page/file/edit.rb
@@ -7,6 +7,30 @@ module QA
include Shared::CommitMessage
include Shared::CommitButton
include Shared::Editor
+
+ view 'app/assets/javascripts/editor/components/source_editor_toolbar_button.vue' do
+ element :editor_toolbar_button
+ end
+
+ view 'app/views/projects/blob/_editor.html.haml' do
+ element :source_editor_preview_container
+ end
+
+ def has_markdown_preview?(component, content)
+ within_element(:source_editor_preview_container) do
+ has_css?(component, exact_text: content)
+ end
+ end
+
+ def wait_for_markdown_preview(component, content)
+ return if has_markdown_preview?(component, content)
+
+ raise ElementNotFound, %("Couldn't find #{component} element with content '#{content}')
+ end
+
+ def click_editor_toolbar
+ click_element(:editor_toolbar_button)
+ end
end
end
end
diff --git a/qa/qa/page/file/shared/editor.rb b/qa/qa/page/file/shared/editor.rb
index ce4465d2a5c..dab02c1e34f 100644
--- a/qa/qa/page/file/shared/editor.rb
+++ b/qa/qa/page/file/shared/editor.rb
@@ -20,7 +20,11 @@ module QA
end
def remove_content
- text_area.send_keys([:command, 'a'], :backspace)
+ if page.driver.browser.capabilities.platform.include? "mac"
+ text_area.send_keys([:command, 'a'], :backspace)
+ else
+ text_area.send_keys([:control, 'a'], :backspace)
+ end
end
private
diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb
index 09a9af7aaf7..1f17b470ada 100644
--- a/qa/qa/page/group/new.rb
+++ b/qa/qa/page/group/new.rb
@@ -12,7 +12,7 @@ module QA
end
view 'app/views/groups/_new_group_fields.html.haml' do
- element :create_group_button, "submit _('Create group')" # rubocop:disable QA/ElementWithPattern
+ element :create_group_button
end
view 'app/views/groups/_import_group_from_another_instance_panel.html.haml' do
@@ -34,6 +34,10 @@ module QA
click_button 'Create group'
end
+ def create_subgroup
+ click_button 'Create subgroup'
+ end
+
def set_gitlab_url(url)
fill_element(:import_gitlab_url, url)
end
diff --git a/qa/qa/page/issuable/new.rb b/qa/qa/page/issuable/new.rb
index 0c95f722080..f3e6a84ef54 100644
--- a/qa/qa/page/issuable/new.rb
+++ b/qa/qa/page/issuable/new.rb
@@ -5,11 +5,7 @@ module QA
module Issuable
class New < Page::Base
view 'app/views/shared/issuable/form/_title.html.haml' do
- element :issuable_form_title
- end
-
- view 'app/views/shared/issuable/form/_metadata.html.haml' do
- element :issuable_milestone_dropdown
+ element :issuable_form_title_field
end
view 'app/views/shared/form_elements/_description.html.haml' do
@@ -17,11 +13,12 @@ module QA
end
view 'app/views/shared/issuable/_milestone_dropdown.html.haml' do
- element :issuable_dropdown_menu_milestone
+ element :issuable_milestone_dropdown
+ element :issuable_milestone_dropdown_content
end
view 'app/views/shared/issuable/_label_dropdown.html.haml' do
- element :issuable_label
+ element :issuable_label_dropdown
end
view 'app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml' do
@@ -33,7 +30,7 @@ module QA
end
def fill_title(title)
- fill_element :issuable_form_title, title
+ fill_element :issuable_form_title_field, title
end
def fill_description(description)
@@ -42,7 +39,7 @@ module QA
def choose_milestone(milestone)
click_element :issuable_milestone_dropdown
- within_element(:issuable_dropdown_menu_milestone) do
+ within_element(:issuable_milestone_dropdown_content) do
click_on milestone.title
end
end
@@ -55,11 +52,11 @@ module QA
end
def select_label(label)
- click_element :issuable_label
+ click_element :issuable_label_dropdown
click_link label.title
- click_element :issuable_label # So that the dropdown goes away(click away action)
+ click_element :issuable_label_dropdown # So that the dropdown goes away(click away action)
end
def assign_to_me
diff --git a/qa/qa/page/label/index.rb b/qa/qa/page/label/index.rb
index e73d40b37ac..e19bc0838c9 100644
--- a/qa/qa/page/label/index.rb
+++ b/qa/qa/page/label/index.rb
@@ -7,26 +7,26 @@ module QA
include Component::LazyLoader
view 'app/views/shared/labels/_nav.html.haml' do
- element :label_create_new
+ element :create_new_label_button
end
view 'app/views/shared/empty_states/_labels.html.haml' do
- element :label_svg
+ element :label_svg_content
end
view 'app/views/shared/empty_states/_priority_labels.html.haml' do
- element :label_svg
+ element :label_svg_content
end
def click_new_label_button
# The 'labels.svg' takes a fraction of a second to load after which the "New label" button shifts up a bit
# This can cause webdriver to miss the hit so we wait for the svg to load (implicitly with has_element?)
# before clicking the button.
- within_element(:label_svg) do
+ within_element(:label_svg_content) do
has_element?(:js_lazy_loaded)
end
- click_element :label_create_new
+ click_element :create_new_label_button
end
end
end
diff --git a/qa/qa/page/label/new.rb b/qa/qa/page/label/new.rb
index a40179489c1..12427443280 100644
--- a/qa/qa/page/label/new.rb
+++ b/qa/qa/page/label/new.rb
@@ -5,9 +5,9 @@ module QA
module Label
class New < Page::Base
view 'app/views/shared/labels/_form.html.haml' do
- element :label_title
- element :label_description
- element :label_color
+ element :label_title_field
+ element :label_description_field
+ element :label_color_field
element :label_create_button
end
@@ -16,15 +16,15 @@ module QA
end
def fill_title(title)
- fill_element :label_title, title
+ fill_element :label_title_field, title
end
def fill_description(description)
- fill_element :label_description, description
+ fill_element :label_description_field, description
end
def fill_color(color)
- fill_element :label_color, color
+ fill_element :label_color_field, color
end
end
end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index f3ee627c41e..d7ca8223862 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -183,8 +183,7 @@ module QA
switch_to_sign_in_tab if has_sign_in_tab?
switch_to_standard_tab if has_standard_tab?
- fill_element :login_field, user.username
- fill_element :password_field, user.password
+ fill_in_credential(user)
if Runtime::Env.running_on_dot_com?
click_accept_all_cookies if has_accept_all_cookies_button?
@@ -211,6 +210,11 @@ module QA
Page::Main::Menu.validate_elements_present! unless skip_page_validation
end
+ def fill_in_credential(user)
+ fill_element :login_field, user.username
+ fill_element :password_field, user.password
+ end
+
# Handle request for password change
# Happens on clean GDK installations when seeded root admin password is expired
#
@@ -236,3 +240,5 @@ module QA
end
end
end
+
+QA::Page::Main::Login.prepend_mod_with('Page::Main::Login', namespace: QA)
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 27c12a4e21f..9fc0cf0ccf8 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -11,6 +11,7 @@ module QA
element :review_preview_dropdown
end
+ # Remove once :mr_review_submit_comment ff is enabled by default
view 'app/assets/javascripts/batch_comments/components/publish_button.vue' do
element :submit_review_button
end
@@ -19,8 +20,9 @@ module QA
element :review_bar_content
end
- view 'app/assets/javascripts/batch_comments/components/draft_note.vue' do
- element :draft_note_content
+ view 'app/assets/javascripts/batch_comments/components/submit_dropdown.vue' do
+ element :submit_review_dropdown
+ element :submit_review_button
end
view 'app/assets/javascripts/diffs/components/compare_dropdown_layout.vue' do
@@ -71,7 +73,6 @@ module QA
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
element :cherry_pick_button
- element :merged_status_content
element :revert_button
end
@@ -134,6 +135,11 @@ module QA
element :cancel_auto_merge_button
end
+ view 'app/views/shared/_broadcast_message.html.haml' do
+ element :broadcast_notification_container
+ element :close_button
+ end
+
def start_review
click_element(:start_review_button)
@@ -151,16 +157,34 @@ module QA
end
def submit_pending_reviews
- has_element?(:submit_review_button)
+ # On test environments we have a broadcast message that can cover the buttons
+
+ if has_element?(:broadcast_notification_container, wait: 5)
+ within_element(:broadcast_notification_container) do
+ click_element(:close_button)
+ end
+ end
+
within_element(:review_bar_content) do
click_element(:review_preview_dropdown)
end
- within_element(:draft_note_content) do
+
+ # Remove if statement once :mr_review_submit_comment ff is enabled by default
+
+ if has_element?(:submit_review_dropdown, wait: 5)
+ click_element(:submit_review_dropdown)
click_element(:submit_review_button)
+ else
+ within_element(:review_bar_content) do
+ click_element(:submit_review_button)
+ end
end
- # After clicking the button, wait for it to disappear
+
+ # After clicking the button, wait for the review bar to disappear
# before moving on to the next part of the test
- has_no_element?(:submit_review_button)
+ wait_until(reload: false) do
+ has_no_element?(:review_bar_content)
+ end
end
def add_comment_to_diff(text)
diff --git a/qa/qa/page/profile/ssh_keys.rb b/qa/qa/page/profile/ssh_keys.rb
index 8da484003f4..db71062cec6 100644
--- a/qa/qa/page/profile/ssh_keys.rb
+++ b/qa/qa/page/profile/ssh_keys.rb
@@ -31,7 +31,11 @@ module QA
def fill_expiry_date(date)
date = date.strftime('%m/%d/%Y') if date.is_a?(Date)
- Date.strptime(date, '%m/%d/%Y') rescue ArgumentError raise "Expiry date must be in mm/dd/yyyy format"
+ begin
+ Date.strptime(date, '%m/%d/%Y')
+ rescue ArgumentError
+ raise "Expiry date must be in mm/dd/yyyy format"
+ end
fill_element(:key_expiry_date_field, date)
end
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 7864e664429..bb4fb84f2d2 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -81,9 +81,9 @@ module QA
# Disable experiment for SAST at project creation https://gitlab.com/gitlab-org/gitlab/-/issues/333196
def disable_initialize_with_sast
- return unless has_element?(:initialize_with_sast_checkbox)
+ return unless has_element?(:initialize_with_sast_checkbox, visible: false)
- uncheck_element(:initialize_with_sast_checkbox)
+ uncheck_element(:initialize_with_sast_checkbox, true)
end
def click_github_link
@@ -95,7 +95,7 @@ module QA
end
def disable_initialize_with_readme
- uncheck_element(:initialize_with_readme_checkbox)
+ uncheck_element(:initialize_with_readme_checkbox, true)
end
end
end
diff --git a/qa/qa/page/project/pipeline_editor/show.rb b/qa/qa/page/project/pipeline_editor/show.rb
index 78f16a8a65c..70c0c5abb52 100644
--- a/qa/qa/page/project/pipeline_editor/show.rb
+++ b/qa/qa/page/project/pipeline_editor/show.rb
@@ -54,7 +54,12 @@ module QA
element :file_tree_popover
end
+ view 'app/assets/javascripts/pipeline_editor/components/validate/ci_validate.vue' do
+ element :simulate_pipeline_button
+ end
+
def initialize
+ wait_for_requests(skip_finished_loading_check: true)
dismiss_file_tree_popover if has_element?(:file_tree_popover)
super
@@ -89,7 +94,7 @@ module QA
end
def submit_changes
- Support::Waiter.wait_until { !find_element(:commit_changes_button).disabled? }
+ wait_until(reload: false) { !find_element(:commit_changes_button).disabled? }
click_element(:commit_changes_button)
wait_for_requests
@@ -115,14 +120,14 @@ module QA
go_to_tab('Visualize')
end
- def go_to_lint_tab
- go_to_tab('Lint')
- end
-
def go_to_view_merged_yaml_tab
go_to_tab('View merged YAML')
end
+ def go_to_validate_tab
+ go_to_tab('Validate')
+ end
+
def has_source_editor?
has_element?(:source_editor_container)
end
@@ -141,6 +146,12 @@ module QA
end
end
+ def tab_alert_title
+ within_element(:file_editor_container) do
+ find('.gl-alert-title').text
+ end
+ end
+
def has_new_mr_checkbox?
has_element?(:new_mr_checkbox, visible: true)
end
@@ -153,6 +164,10 @@ module QA
check_element(:new_mr_checkbox, true)
end
+ def simulate_pipeline
+ click_element(:simulate_pipeline_button)
+ end
+
private
def go_to_tab(name)
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index fd9cc8a13e7..9d8ed132ffd 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -8,6 +8,10 @@ module QA
include QA::Page::Component::ConfirmModal
include Component::NamespaceSelect
+ view 'app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue' do
+ element :confirm_danger_button
+ end
+
view 'app/views/projects/edit.html.haml' do
element :project_path_field
element :change_path_button
@@ -47,7 +51,7 @@ module QA
# https://gitlab.com/gitlab-org/gitlab/-/issues/218965
select_namespace(namespace.gsub(%r{([^\s])/([^\s])}, '\1 / \2'))
- click_element(:transfer_button)
+ click_element(:confirm_danger_button)
fill_confirmation_text(project_name)
confirm_transfer
end
diff --git a/qa/qa/page/project/settings/integrations.rb b/qa/qa/page/project/settings/integrations.rb
index 0d5515aacdf..58b3badbb22 100644
--- a/qa/qa/page/project/settings/integrations.rb
+++ b/qa/qa/page/project/settings/integrations.rb
@@ -6,6 +6,7 @@ module QA
module Settings
class Integrations < QA::Page::Base
view 'app/assets/javascripts/integrations/index/components/integrations_table.vue' do
+ element :jenkins_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :prometheus_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :jira_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
element :pipelines_email_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
@@ -22,10 +23,12 @@ module QA
def click_jira_link
click_element :jira_link
end
+
+ def click_jenkins_ci_link
+ click_element :jenkins_link
+ end
end
end
end
end
end
-
-QA::Page::Project::Settings::Integrations.prepend_mod_with('Page::Project::Settings::Integrations', namespace: QA)
diff --git a/qa/qa/page/project/settings/pages.rb b/qa/qa/page/project/settings/pages.rb
new file mode 100644
index 00000000000..1417f7ec1b5
--- /dev/null
+++ b/qa/qa/page/project/settings/pages.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class Pages < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/views/projects/pages/_access.html.haml' do
+ element :access_page_container
+ end
+
+ def go_to_access_page
+ within_element(:access_page_container) do
+ find('a').click
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+QA::Page::Project::Settings::Pages.prepend_mod_with("Page::Project::Settings::Pages", namespace: QA)
diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb
index 308cf6366a7..35fc87f717c 100644
--- a/qa/qa/page/project/settings/protected_branches.rb
+++ b/qa/qa/page/project/settings/protected_branches.rb
@@ -17,10 +17,6 @@ module QA
element :allowed_to_merge_dropdown
end
- view 'app/views/shared/projects/protected_branches/_update_protected_branch.html.haml' do
- element :allowed_to_merge
- end
-
view 'app/views/projects/protected_branches/shared/_branches_list.html.haml' do
element :protected_branches_list
end
diff --git a/qa/qa/page/project/settings/services/jenkins.rb b/qa/qa/page/project/settings/services/jenkins.rb
index 8e092371491..39403995ce8 100644
--- a/qa/qa/page/project/settings/services/jenkins.rb
+++ b/qa/qa/page/project/settings/services/jenkins.rb
@@ -17,11 +17,11 @@ module QA
element :save_changes_button
end
- def setup_service_with(jenkins_url:, project_name:)
+ def setup_service_with(jenkins_url:, project_name:, username:, password:)
set_jenkins_url(jenkins_url)
set_project_name(project_name)
- set_username('admin')
- set_password('password')
+ set_username(username)
+ set_password(password)
click_save_changes_button
end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 022e08215be..e048afee8b3 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -67,8 +67,8 @@ module QA
end
view 'app/views/shared/_ref_switcher.html.haml' do
- element :branches_select
element :branches_dropdown
+ element :branches_dropdown_content
end
view 'app/views/projects/blob/viewers/_loading.html.haml' do
@@ -176,9 +176,9 @@ module QA
end
def switch_to_branch(branch_name)
- find_element(:branches_select).click
+ find_element(:branches_dropdown).click
- within_element(:branches_dropdown) do
+ within_element(:branches_dropdown_content) do
click_on branch_name
end
end
diff --git a/qa/qa/page/project/sub_menus/settings.rb b/qa/qa/page/project/sub_menus/settings.rb
index f35d27e658d..53a5eaf60c5 100644
--- a/qa/qa/page/project/sub_menus/settings.rb
+++ b/qa/qa/page/project/sub_menus/settings.rb
@@ -69,6 +69,14 @@ module QA
end
end
+ def go_to_pages_settings
+ hover_settings do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Pages')
+ end
+ end
+ end
+
private
def hover_settings
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index bc6c839bfe2..e572569e496 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -24,11 +24,11 @@ module QA
end
view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do
- element :file_list
+ element :file_list_container
end
view 'app/assets/javascripts/ide/components/file_templates/bar.vue' do
- element :file_templates_bar
+ element :file_templates_container
element :file_template_dropdown
end
@@ -110,7 +110,7 @@ module QA
end
def has_file?(file_name)
- within_element(:file_list) do
+ within_element(:file_list_container) do
has_element?(:file_name_content, file_name: file_name)
end
end
@@ -173,7 +173,7 @@ module QA
has_no_element?(:new_file_modal)
wait_until(reload: false) do
- within_element(:file_templates_bar) do
+ within_element(:file_templates_container) do
click_element :file_template_dropdown
fill_element :dropdown_filter_input, template
@@ -291,12 +291,12 @@ module QA
click_element(:fork_project_button)
# wait for the fork to be created
wait_until(reload: true) do
- has_element?(:file_list)
+ has_element?(:file_list_container)
end
end
def upload_file(file_path)
- within_element(:file_list) do
+ within_element(:file_list_container) do
find_element(:file_upload_field, visible: false).send_keys(file_path)
end
end
diff --git a/qa/qa/page/view.rb b/qa/qa/page/view.rb
index fa17b8fe302..6a6396b8ed4 100644
--- a/qa/qa/page/view.rb
+++ b/qa/qa/page/view.rb
@@ -37,7 +37,7 @@ module QA
def self.evaluate(&block)
Page::View::DSL.new.tap do |evaluator|
- evaluator.instance_exec(&block) if block_given?
+ evaluator.instance_exec(&block) if block
end
end
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index 667dbc03fc3..d1cfdfbc16c 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -74,6 +74,13 @@ module QA
response.code == HTTP_STATUS_OK
end
+ # Parameters included in the query URL
+ #
+ # @return [Hash]
+ def query_parameters
+ @query_parameters ||= {}
+ end
+
private
def resource_web_url(resource)
@@ -87,7 +94,8 @@ module QA
end
def api_get_from(get_path)
- request = Runtime::API::Request.new(api_client, get_path)
+ path = "#{get_path}#{query_parameters_to_string}"
+ request = Runtime::API::Request.new(api_client, path)
response = get(request.url)
if response.code == HTTP_STATUS_SERVER_ERROR
@@ -101,6 +109,15 @@ module QA
response
end
+ # Query parameters formatted as `?key1=value1&key2=value2...`
+ #
+ # @return [String]
+ def query_parameters_to_string
+ query_parameters.each_with_object([]) do |(k, v), arr|
+ arr << "#{k}=#{v}"
+ end.join('&').prepend('?').chomp('?') # prepend `?` unless the string is blank
+ end
+
def api_post
process_api_response(api_post_to(api_post_path, api_post_body))
end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index c3da9d47de5..60f6cbdfc51 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -38,10 +38,8 @@ module QA
group_show.go_to_new_subgroup
Page::Group::New.perform do |group_new|
- group_new.click_create_group
group_new.set_path(path)
- group_new.set_visibility('Public')
- group_new.create
+ group_new.create_subgroup
end
# Ensure that the group was actually created
@@ -63,6 +61,13 @@ module QA
"/groups/#{CGI.escape(determine_full_path)}"
end
+ # Parameters included in the query URL
+ #
+ # @return [Hash]
+ def query_parameters
+ super.merge({ with_projects: false })
+ end
+
def api_post_body
{
parent_id: sandbox.id,
diff --git a/qa/qa/resource/group_ci_variable.rb b/qa/qa/resource/group_ci_variable.rb
new file mode 100644
index 00000000000..f78d11b6c11
--- /dev/null
+++ b/qa/qa/resource/group_ci_variable.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class GroupCiVariable < Base
+ attr_accessor :key, :value, :masked, :protected
+
+ attribute :group do
+ QA::Resource::Group.fabricate_via_api!
+ end
+
+ def initialize
+ @masked = false
+ @protected = false
+ end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def api_get_path
+ "/groups/#{group.id}/variables/#{key}"
+ end
+
+ def api_post_path
+ "/groups/#{group.id}/variables"
+ end
+
+ def api_post_body
+ {
+ key: key,
+ value: value,
+ masked: masked,
+ protected: protected
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/impersonation_token.rb b/qa/qa/resource/impersonation_token.rb
new file mode 100644
index 00000000000..3bd356b5e9b
--- /dev/null
+++ b/qa/qa/resource/impersonation_token.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ImpersonationToken < Base
+ attr_writer :name
+
+ attribute :id
+ attribute :user
+ attribute :token
+ attribute :expires_at
+
+ def api_get_path
+ "/users/#{user.id}/impersonation_tokens/#{id}"
+ rescue NoValueError
+ token = parse_body(api_get_from("/users/#{user.id}/impersonation_tokens")).find { |t| t[:name] == name }
+
+ raise ResourceNotFoundError unless token
+
+ @id = token[:id]
+ retry
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def name
+ @name ||= "api-impersonation-access-token-#{Faker::Alphanumeric.alphanumeric(number: 8)}"
+ end
+
+ def api_post_body
+ {
+ name: name,
+ scopes: ["api"],
+ expires_at: expires_at.to_s
+ }
+ end
+
+ def api_delete_path
+ "/users/#{user.id}/impersonation_tokens/#{id}"
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def revoke_via_browser_ui!
+ Flow::Login.sign_in_unless_signed_in(user: Runtime::User.admin)
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_users_overview)
+ Page::Admin::Overview::Users::Index.perform do |index|
+ index.search_user(user.username)
+ index.click_user(user.name)
+ end
+
+ Page::Admin::Overview::Users::Show.perform do |show|
+ show.go_to_impersonation_tokens do |impersonation_tokens|
+ impersonation_tokens.revoke_first_token_with_name(name)
+ end
+ end
+ yield if block_given?
+ end
+
+ # Expire in 2 days just in case the token is created just before midnight
+ def expires_at
+ @expires_at || Time.now.utc.to_date + 2
+ end
+
+ def fabricate!
+ Flow::Login.sign_in_unless_signed_in(user: Runtime::User.admin)
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_users_overview)
+ Page::Admin::Overview::Users::Index.perform do |index|
+ index.search_user(user.username)
+ index.click_user(user.name)
+ end
+
+ Page::Admin::Overview::Users::Show.perform do |show|
+ show.go_to_impersonation_tokens do |impersonation_tokens|
+ impersonation_tokens.fill_token_name(name)
+ impersonation_tokens.check_api
+ impersonation_tokens.fill_expiry_date(expires_at)
+ impersonation_tokens.click_create_token_button
+ self.token = impersonation_tokens.created_access_token
+ end
+ end
+
+ reload!
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/integrations/project.rb b/qa/qa/resource/integrations/project.rb
new file mode 100644
index 00000000000..11e59408e22
--- /dev/null
+++ b/qa/qa/resource/integrations/project.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Integrations
+ module Project
+ def find_integration(slug)
+ fetch_integrations.find do |integration|
+ integration[:slug] == slug
+ end
+ end
+
+ def fetch_integrations
+ parse_body api_get_from(api_get_integrations)
+ end
+
+ private
+
+ def api_get_integrations
+ "#{api_get_path}/integrations"
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/personal_access_token.rb b/qa/qa/resource/personal_access_token.rb
index a12c210ea0e..ad0f183c603 100644
--- a/qa/qa/resource/personal_access_token.rb
+++ b/qa/qa/resource/personal_access_token.rb
@@ -17,20 +17,17 @@ module QA
# If Runtime::Env.admin_personal_access_token is provided, fabricate via the API,
# else, fabricate via the browser.
def fabricate_via_api!
- QA::Resource::PersonalAccessTokenCache.get_token_for_username(user.username).tap do |cached_token|
- @token = cached_token if cached_token
- end
- return if @token
+ return if find_and_set_value
resource = if Runtime::Env.admin_personal_access_token && !@user.nil?
self.api_client = Runtime::API::Client.as_admin
-
super
else
fabricate!
end
- QA::Resource::PersonalAccessTokenCache.set_token_for_username(user.username, token) if @user
+ self.token = api_response[:token] unless api_response.nil?
+ cache_token
resource
end
@@ -60,7 +57,17 @@ module QA
# this particular resource does not expose a web_url property
end
+ def find_and_set_value
+ @token ||= QA::Resource::PersonalAccessTokenCache.get_token_for_username(user.username)
+ end
+
+ def cache_token
+ QA::Resource::PersonalAccessTokenCache.set_token_for_username(user.username, self.token) if @user && self.token
+ end
+
def fabricate!
+ return if find_and_set_value
+
Flow::Login.sign_in_unless_signed_in(user: user)
Page::Main::Menu.perform(&:click_edit_profile_link)
@@ -74,6 +81,10 @@ module QA
token_page.click_create_token_button
self.token = Page::Profile::PersonalAccessTokens.perform(&:created_access_token)
+
+ cache_token
+
+ self.token
end
end
end
diff --git a/qa/qa/resource/personal_access_token_cache.rb b/qa/qa/resource/personal_access_token_cache.rb
index 3e9dc3fd7df..0874618201a 100644
--- a/qa/qa/resource/personal_access_token_cache.rb
+++ b/qa/qa/resource/personal_access_token_cache.rb
@@ -6,7 +6,17 @@ module QA
@personal_access_tokens = {}
def self.get_token_for_username(username)
- @personal_access_tokens[username]
+ token = @personal_access_tokens[username]
+
+ log_message = if token
+ %Q[Retrieved cached token for username: #{username}, last six chars of token:#{token[-6..]}]
+ else
+ %Q[No cached token found for username: #{username}]
+ end
+
+ QA::Runtime::Logger.info(log_message)
+
+ token
end
def self.set_token_for_username(username, token)
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 825041cbead..13c6f285259 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -4,6 +4,7 @@ module QA
module Resource
class Project < Base
include Events::Project
+ include Integrations::Project
include Members
include Visibility
@@ -20,13 +21,13 @@ module QA
:name,
:path,
:add_name_uuid,
- :description,
:runners_token,
:visibility,
:template_name,
:import,
:import_status,
- :import_error
+ :import_error,
+ :description
attribute :group do
Group.fabricate! do |group|
@@ -107,7 +108,7 @@ module QA
end
new_page.choose_name(@name)
- new_page.add_description(@description)
+ new_page.add_description(@description) if @description
new_page.set_visibility(@visibility)
new_page.disable_initialize_with_sast
new_page.disable_initialize_with_readme unless @initialize_with_readme
@@ -294,6 +295,21 @@ module QA
)
end
+ def change_path(new_path)
+ response = put(request_url(api_put_path), path: new_path)
+
+ unless response.code == HTTP_STATUS_OK
+ raise(
+ ResourceUpdateFailedError,
+ "Failed to update the project path to '#{new_path}'. Request returned (#{response.code}): `#{response}`."
+ )
+ end
+
+ # We need to manually set the path_with_namespace as reload! relies on it being correct and avoid 404s
+ result = parse_body(response)
+ @path_with_namespace = result[:path_with_namespace]
+ end
+
def default_branch
reload!.api_response[:default_branch] || Runtime::Env.default_branch
end
@@ -458,10 +474,12 @@ module QA
response = post(request_url(api_housekeeping_path), nil)
- unless response.code == HTTP_STATUS_CREATED
- raise ResourceQueryError,
- "Could not perform housekeeping. Request returned (#{response.code}): `#{response.body}`."
- end
+ return if response.code == HTTP_STATUS_CREATED
+
+ raise(
+ ResourceQueryError,
+ "Could not perform housekeeping. Request returned (#{response.code}): `#{response.body}`."
+ )
end
# Gets project statistics.
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 8e7527bccd4..12ecce1ce9a 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -57,6 +57,13 @@ module QA
"/groups/#{path}"
end
+ # Parameters included in the query URL
+ #
+ # @return [Hash]
+ def query_parameters
+ super.merge({ with_projects: false })
+ end
+
def api_post_body
{
path: path,
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index f7aca2571c9..1fd097d0acf 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -291,6 +291,14 @@ module QA
ENV['JIRA_HOSTNAME']
end
+ def jenkins_admin_username
+ ENV.fetch('QA_JENKINS_USER', 'administrator')
+ end
+
+ def jenkins_admin_password
+ ENV.fetch('QA_JENKINS_PASS', 'password')
+ end
+
# this is set by the integrations job
# which will allow bidirectional communication
# between the app and the specs container
@@ -484,6 +492,10 @@ module QA
ENV.fetch('MAX_CAPYBARA_WAIT_TIME', 10).to_i
end
+ def use_public_ip_api?
+ enabled?(ENV['QA_USE_PUBLIC_IP_API'], default: false)
+ end
+
private
def remote_grid_credentials
diff --git a/qa/qa/runtime/ip_address.rb b/qa/qa/runtime/ip_address.rb
index 657dc789cff..fcb6db750bb 100644
--- a/qa/qa/runtime/ip_address.rb
+++ b/qa/qa/runtime/ip_address.rb
@@ -13,7 +13,10 @@ module QA
def fetch_current_ip_address
# When running on CI against a live environment such as staging.gitlab.com,
# we use the public facing IP address
- ip_address = if Env.running_in_ci? && !URI.parse(Scenario.gitlab_address).host.include?('.test')
+ non_test_host = !URI.parse(Scenario.gitlab_address).host.include?('.test')
+ has_no_public_ip = Env.running_in_ci? || Env.use_public_ip_api?
+
+ ip_address = if has_no_public_ip && non_test_host
response = get(PUBLIC_IP_ADDRESS_API)
raise HostUnreachableError, "#{PUBLIC_IP_ADDRESS_API} is unreachable" unless response.code == Support::API::HTTP_STATUS_OK
diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb
index 0af42470a7c..e4eeca2000f 100644
--- a/qa/qa/runtime/user.rb
+++ b/qa/qa/runtime/user.rb
@@ -55,3 +55,5 @@ module QA
end
end
end
+
+QA::Runtime::User.extend_mod_with('Runtime::User', namespace: QA)
diff --git a/qa/qa/scenario/test/integration/metrics.rb b/qa/qa/scenario/test/integration/metrics.rb
new file mode 100644
index 00000000000..c1297038a0f
--- /dev/null
+++ b/qa/qa/scenario/test/integration/metrics.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class Metrics < Test::Instance::All
+ tags :metrics
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/sanity/selectors.rb b/qa/qa/scenario/test/sanity/selectors.rb
index 8b355c5faf6..688fede1b2e 100644
--- a/qa/qa/scenario/test/sanity/selectors.rb
+++ b/qa/qa/scenario/test/sanity/selectors.rb
@@ -19,7 +19,7 @@ module QA
validators.flat_map(&:errors).tap do |errors|
break if errors.none?
- warn <<~EOS
+ warn <<~WARN
GitLab QA sanity selectors validation test detected problems
with your merge request!
@@ -42,15 +42,14 @@ module QA
contribute, please open an issue in GitLab QA issue tracker.
Please see errors described below.
-
- EOS
+ WARN
warn errors
end
validators.each(&:validate!)
- puts 'Views / selectors validation passed!'
+ QA::Runtime::Logger.info('Views / selectors validation passed!')
end
end
end
diff --git a/qa/qa/service/docker_run/gitlab_runner.rb b/qa/qa/service/docker_run/gitlab_runner.rb
index 1584b577af1..45ab4ceff99 100644
--- a/qa/qa/service/docker_run/gitlab_runner.rb
+++ b/qa/qa/service/docker_run/gitlab_runner.rb
@@ -36,13 +36,14 @@ module QA
end
def register!
- shell <<~CMD.tr("\n", ' ')
+ cmd = <<~CMD.tr("\n", ' ')
docker run -d --rm --network #{runner_network} --name #{@name}
#{'-v /var/run/docker.sock:/var/run/docker.sock' if @executor == :docker}
--privileged
#{@image} #{add_gitlab_tls_cert if @address.include? 'https'}
&& docker exec --detach #{@name} sh -c "#{register_command}"
CMD
+ shell(cmd, mask_secrets: [@token])
wait_until_running_and_configured
diff --git a/qa/qa/service/docker_run/jenkins.rb b/qa/qa/service/docker_run/jenkins.rb
index 808fab80c63..88b69210382 100644
--- a/qa/qa/service/docker_run/jenkins.rb
+++ b/qa/qa/service/docker_run/jenkins.rb
@@ -4,11 +4,27 @@ module QA
module Service
module DockerRun
class Jenkins < Base
+ include Mixins::ThirdPartyDocker
+
+ attr_reader :port
+
def initialize
- @image = 'registry.gitlab.com/gitlab-org/gitlab-qa/jenkins-gitlab:version1'
+ @image = "#{third_party_repository}/jenkins:latest"
@name = 'jenkins-server'
@port = '8080'
- super()
+ super
+ end
+
+ def network
+ @network || 'test'
+ end
+
+ def username
+ Runtime::Env.jenkins_admin_username
+ end
+
+ def password
+ Runtime::Env.jenkins_admin_password
end
def host_address
@@ -16,30 +32,37 @@ module QA
end
def host_name
- if !QA::Runtime::Env.running_in_ci? && !runner_network.equal?('airgapped')
- 'localhost'
- end
+ return 'localhost' unless QA::Runtime::Env.running_in_ci?
super
end
def register!
+ authenticate_third_party
+
command = <<~CMD.tr("\n", ' ')
docker run -d --rm
--network #{network}
--hostname #{host_name}
--name #{@name}
- --env JENKINS_HOME=jenkins_home
+ --env JENKINS_USER=#{username}
+ --env JENKINS_PASS=#{password}
--publish #{@port}:8080
--publish 50000:50000
#{@image}
CMD
- if !QA::Runtime::Env.running_in_ci? && !runner_network.equal?('airgapped')
- command.gsub!("--network #{network} ", '')
- end
+ shell(command, mask_secrets: [password])
- shell command
+ wait_for_running
+ end
+
+ private
+
+ def wait_for_running
+ Support::Waiter.wait_until(max_duration: 10, reload_page: false, raise_on_failure: false) do
+ running?
+ end
end
end
end
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 8563c3656a8..c332e7a6198 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -30,7 +30,7 @@ module QA
wait_until_shell_command_matches(dataloss_command, /Outdated repositories/)
end
- def replicated?(project_id)
+ def replicated?(project_id, project_name_prefix = 'gitaly_cluster')
Support::Retrier.retry_until(raise_on_failure: false) do
replicas = wait_until_shell_command(%(docker exec #{@gitlab} bash -c 'gitlab-rake "gitlab:praefect:replicas[#{project_id}]"')) do |line|
QA::Runtime::Logger.debug(line.chomp)
@@ -40,7 +40,7 @@ module QA
# ----------------------------------------------------------------------------------------------------------------------------------------------------------------
# gitaly_cluster-3aff1f2bd14e6c98 | 23c4422629234d62b62adacafd0a33a8364e8619 | 23c4422629234d62b62adacafd0a33a8364e8619 | 23c4422629234d62b62adacafd0a33a8364e8619
#
- break line if line.start_with?('gitaly_cluster')
+ break line if line.start_with?(project_name_prefix)
break nil if line.include?('Something went wrong when getting replicas')
end
next false unless replicas
@@ -101,7 +101,7 @@ module QA
wait_until_shell_command_matches(
"docker inspect -f {{.State.Running}} #{name}",
/true/,
- sleep_interval: 3,
+ sleep_interval: 1,
max_duration: 180,
retry_on_exception: true
)
@@ -425,7 +425,7 @@ module QA
end
def value_for_node(data, node)
- data.find(-> {{ value: 0 }}) { |item| item[:node] == node }[:value]
+ data.find(-> { { value: 0 } }) { |item| item[:node] == node }[:value]
end
def wait_for_replication(project_id)
diff --git a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
index 79509bdbe01..df34bf32421 100644
--- a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
@@ -65,10 +65,8 @@ module QA
end
def verify_repository_import
- expect(imported_project.api_response).to include(
- description: 'Project for github import test',
- import_error: nil
- )
+ 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
diff --git a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
index c47afbd23f0..de460a39ccf 100644
--- a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
@@ -8,9 +8,14 @@ module QA
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 }
@@ -83,14 +88,14 @@ module QA
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|
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body # use base html url as key
+ hash[c.html_url.gsub(/\#\S+/, "")] << c.body&.gsub(gh_link_pattern, dummy_url) # use base html url as key
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|
- hash[c.html_url.gsub(/\#\S+/, "")] << c.body # use base html url as key
+ hash[c.html_url.gsub(/\#\S+/, "")] << c.body&.gsub(gh_link_pattern, dummy_url) # use base html url as key
end
end
@@ -135,7 +140,7 @@ module QA
target: {
name: "GitLab",
project_name: imported_project.path_with_namespace,
- address: QA::Runtime::Scenario.gitlab_address,
+ address: gitlab_address,
data: {
branches: gl_branches.length,
commits: gl_commits.length,
@@ -381,15 +386,16 @@ module QA
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]) || '',
- comments: resource
- .comments(auto_paginate: true, attempts: 2)
- # remove system notes
- .reject { |c| c[:system] || c[:body].match?(/^(\*\*Review:\*\*)|(\*Merged by:).*/) }
- .map { |c| sanitize_comment(c[:body]) }
+ events: events(comments),
+ comments: non_event_comments(comments)
}]
end.to_h
end
@@ -412,24 +418,54 @@ module QA
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]) || '',
- comments: resource
- .comments(auto_paginate: true, attempts: 2)
- .map { |c| sanitize_comment(c[:body]) }
+ events: events(comments),
+ comments: non_event_comments(comments)
}]
end.to_h
end
end
- # Remove added prefixes and legacy diff format from comments
+ # 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")
+ 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
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 fc221c963b1..874626e01f1 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' do
+ describe 'rate limits', :reliable 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_inherited_access_spec.rb b/qa/qa/specs/features/api/1_manage/user_inherited_access_spec.rb
index faef321c89d..444d86f63d3 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
@@ -36,6 +36,7 @@ module QA
it(
'is allowed to push code to sub-group project via the CLI',
+ :reliable,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363345'
) do
expect do
@@ -52,6 +53,7 @@ module QA
it(
'is allowed to create a file in sub-group project via the API',
+ :reliable,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363348'
) do
expect do
@@ -68,6 +70,7 @@ module QA
it(
'is allowed to commit to sub-group project via the API',
+ :reliable,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363349'
) do
expect do
@@ -116,6 +119,7 @@ module QA
it(
'is not allowed to push code to parent group project via the CLI',
+ :reliable,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363344'
) do
expect do
@@ -148,6 +152,7 @@ module QA
it(
'is not allowed to commit to parent group project via the API',
+ :reliable,
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/363342'
) do
expect do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
index cd1b7730fa9..5ee6dfdb8d8 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
@@ -67,6 +67,28 @@ module QA
it_behaves_like 'repository storage move'
end
+
+ # Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
+ # scenario with other tests that aren't considered orchestrated.
+ # It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
+ context 'when moving from Gitaly Cluster to Gitaly', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/369204' do
+ let(:source_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
+ let(:destination_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'repo-storage-move'
+ project.initialize_with_readme = true
+ project.repository_storage = source_storage[:name]
+ project.api_client = Runtime::API::Client.as_admin
+ end
+ end
+
+ before do
+ praefect_manager.gitlab = 'gitlab-gitaly-cluster'
+ end
+
+ it_behaves_like 'repository storage move'
+ end
end
end
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index 150378016e1..2b96c35415e 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -20,11 +20,6 @@ module QA
praefect_manager.wait_for_replication(project.id)
end
- after do
- # Leave the cluster in a suitable state for subsequent tests
- praefect_manager.start_all_nodes
- end
-
it 'reads from each node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347833' do
pre_read_data = praefect_manager.query_read_distribution
@@ -42,14 +37,12 @@ module QA
context 'when a node is unhealthy' do
before do
- praefect_manager.start_all_nodes
praefect_manager.stop_secondary_node
- praefect_manager.wait_for_secondary_node_health_check_failure
end
after do
# Leave the cluster in a suitable state for subsequent tests
- praefect_manager.start_all_nodes
+ praefect_manager.start_secondary_node
end
it 'does not read from the unhealthy node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347834' do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
index b6296b5a263..a53614960cd 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
@@ -3,10 +3,7 @@
require 'parallel'
module QA
- RSpec.describe 'Create', quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/361382',
- type: :investigating
- } do
+ RSpec.describe 'Create' do
context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env do
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
@@ -35,6 +32,9 @@ module QA
# to `in_progress`, and create a job lock for each one.
queue_size_target = 10
+ # During normal operations we avoid create a replication event
+ # https://gitlab.com/groups/gitlab-org/-/epics/7741
+ praefect_manager.stop_secondary_node
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
@@ -46,11 +46,12 @@ module QA
end
repository.push_all_branches
end
+ praefect_manager.start_secondary_node
- count = 0
- while count < 1
+ Support::Retrier.retry_until(max_duration: 60) do
count = praefect_manager.replication_queue_lock_count
QA::Runtime::Logger.debug("Lock count: #{count}")
+ count >= 1
end
praefect_manager.stop_praefect
@@ -58,12 +59,12 @@ module QA
praefect_manager.start_praefect
- # Create a new project, push to it, and check that replication occurs
- project_push = Resource::Repository::ProjectPush.fabricate! do |push|
- push.project_name = "gitaly_cluster"
+ # Create a new project, and check that replication occurs
+ new_project = Resource::Project.fabricate! do |project|
+ project.initialize_with_readme = true
end
- expect(praefect_manager.replicated?(project_push.project.id)).to be true
+ expect(praefect_manager.replicated?(new_project.id, new_project.name)).to be true
end
end
end
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
index e27f37abedf..47be7e0620b 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
@@ -15,7 +15,6 @@ module QA
end
after do
- praefect_manager.start_all_nodes
praefect_manager.remove_repo_from_disk(repo1["relative_path"])
praefect_manager.remove_repo_from_disk(repo2["relative_path"])
praefect_manager.remove_repository_from_praefect_database(repo1["relative_path"])
diff --git a/qa/qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb b/qa/qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb
new file mode 100644
index 00000000000..98612d84b21
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.initialize_with_readme = true
+ end
+ end
+
+ context 'when creating a tag for a ref' do
+ context 'when it triggers a prereceive hook configured with a custom error' do
+ before do
+ # The configuration test prereceive hook must match a specific naming pattern
+ # In this test we create a project with a different name and then change the path.
+ # Otherwise we wouldn't be able create any commits to be tagged due to the hook.
+ project.change_path("project-reject-prereceive-#{SecureRandom.hex(8)}")
+ end
+
+ it 'returns a custom server hook error',
+ :skip_live_env,
+ except: { job: 'review-qa-*' },
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/369053' do
+ expect { project.create_repository_tag('v1.2.3') }.to raise_error
+ .with_message(
+ /rejecting prereceive hook for projects with GL_PROJECT_PATH matching pattern reject-prereceive/
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/5_package/container_registry_spec.rb b/qa/qa/specs/features/api/5_package/container_registry_spec.rb
index 79384e374d7..8412c0b2872 100644
--- a/qa/qa/specs/features/api/5_package/container_registry_spec.rb
+++ b/qa/qa/specs/features/api/5_package/container_registry_spec.rb
@@ -3,7 +3,7 @@
require 'airborne'
module QA
- RSpec.describe 'Package', only: { subdomain: %i[staging pre] } do
+ RSpec.describe 'Package', :reliable, only: { subdomain: %i[staging staging-canary pre] } do
include Support::API
include Support::Helpers::MaskToken
@@ -41,7 +41,7 @@ module QA
stages:
- build
- test
-
+
build:
image: docker:19.03.12
stage: build
@@ -60,7 +60,7 @@ module QA
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
- docker pull $IMAGE_TAG
-
+
test:
image: dwdraju/alpine-curl-jq:latest
stage: test
@@ -72,7 +72,7 @@ module QA
- 'status_code=$(curl --request DELETE --head --output /dev/null --write-out "%{http_code}\n" --header "PRIVATE-TOKEN: #{masked_token}" "https://${CI_SERVER_HOST}/api/v4/projects/#{project.id}/registry/repositories/$id/tags/master")'
- if [ $status_code -ne 200 ]; then exit 1; fi;
- 'status_code=$(curl --head --output /dev/null --write-out "%{http_code}\n" --header "PRIVATE-TOKEN: #{masked_token}" "https://${CI_SERVER_HOST}/api/v4/projects/#{project.id}/registry/repositories/$id/tags/master")'
- - if [ $status_code -ne 404 ]; then exit 1; fi;
+ - if [ $status_code -ne 404 ]; then exit 1; fi;
YAML
end
diff --git a/qa/qa/specs/features/api/8_monitor/metrics_spec.rb b/qa/qa/specs/features/api/8_monitor/metrics_spec.rb
new file mode 100644
index 00000000000..1235b996958
--- /dev/null
+++ b/qa/qa/specs/features/api/8_monitor/metrics_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'GitLab Metrics', :aggregate_failures, :orchestrated, :metrics do
+ let(:web_uri) { URI.parse(Runtime::Scenario.gitlab_address) }
+ let(:endpoint) do
+ "#{web_uri.scheme}://#{web_uri.host}:#{port}#{path}"
+ end
+
+ let(:response) { RestClient.get(endpoint) }
+
+ describe 'Web metrics' do
+ describe 'via Rails controller endpoint' do
+ let(:port) { web_uri.port }
+ let(:path) { '/-/metrics' }
+
+ it 'returns 200 OK and serves metrics',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/362911' do
+ # This does not currently work because it requires a special auth token to
+ # make an internal endpoint request. But we should probably test this, too.
+ skip
+ end
+ end
+
+ describe 'via dedicated server' do
+ let(:port) { '8083' }
+ let(:path) { '/metrics' }
+
+ it 'returns 200 OK and serves metrics',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/362912' do
+ expect(response.code).to be(200)
+ expect(response.body).to match(/^puma_/)
+ end
+ end
+ end
+
+ describe 'Sidekiq metrics' do
+ describe 'via dedicated server' do
+ let(:port) { '8082' }
+ let(:path) { '/metrics' }
+
+ it 'returns 200 OK and serves metrics',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/362913' do
+ expect(response.code).to be(200)
+ expect(response.body).to match(/^sidekiq_/)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb
new file mode 100644
index 00000000000..867c54102ae
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_analytics/performance_bar_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Analytics' do
+ describe 'Performance bar display', :requires_admin, :skip_live_env do
+ context 'when logged in as an admin user' do
+ # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
+ let(:minimum_metrics_count) { 3 }
+
+ before do
+ Flow::Login.sign_in_as_admin
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+
+ Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
+ setting.expand_performance_bar do |page|
+ page.enable_performance_bar
+ page.save_settings
+ end
+ end
+ end
+
+ it(
+ 'shows results for the original request and AJAX requests',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348030'
+ ) do
+ # Issue pages always make AJAX requests
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
+ issue.title = 'Performance bar test'
+ end
+
+ Page::Layout::PerformanceBar.perform do |bar_component|
+ expect(bar_component).to have_performance_bar
+ expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
+ expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb b/qa/qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb
new file mode 100644
index 00000000000..7826aca3601
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_analytics/service_ping_default_enabled_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Analytics' do
+ describe 'Service ping default enabled' do
+ context 'when using default enabled from gitlab.yml config', :requires_admin, except: { job: 'review-qa-*' } do
+ before do
+ Flow::Login.sign_in_as_admin
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+ end
+
+ it(
+ 'has service ping toggle enabled',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348335'
+ ) do
+ Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
+ setting.expand_usage_statistics do |page|
+ expect(page).not_to have_disabled_usage_data_checkbox
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb b/qa/qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb
new file mode 100644
index 00000000000..8b30d6a7ad7
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_analytics/service_ping_disabled_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Analytics' do
+ describe 'Service ping disabled', :orchestrated, :service_ping_disabled, :requires_admin do
+ context 'when disabled from gitlab.yml config' do
+ before do
+ Flow::Login.sign_in_as_admin
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+ end
+
+ it(
+ 'has service ping toggle is disabled',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348340'
+ ) do
+ Page::Admin::Settings::MetricsAndProfiling.perform do |settings|
+ settings.expand_usage_statistics do |usage_statistics|
+ expect(usage_statistics).to have_disabled_usage_data_checkbox
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_product_intelligence/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/14_product_intelligence/performance_bar_spec.rb
deleted file mode 100644
index 10076a329bc..00000000000
--- a/qa/qa/specs/features/browser_ui/14_product_intelligence/performance_bar_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Product Intelligence' do
- describe 'Performance bar display', :requires_admin, :skip_live_env do
- context 'when logged in as an admin user' do
- # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
- let(:minimum_metrics_count) { 3 }
-
- before do
- Flow::Login.sign_in_as_admin
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
-
- Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
- setting.expand_performance_bar do |page|
- page.enable_performance_bar
- page.save_settings
- end
- end
- end
-
- it(
- 'shows results for the original request and AJAX requests',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348030'
- ) do
- # Issue pages always make AJAX requests
- Resource::Issue.fabricate_via_browser_ui! do |issue|
- issue.title = 'Performance bar test'
- end
-
- Page::Layout::PerformanceBar.perform do |bar_component|
- expect(bar_component).to have_performance_bar
- expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
- expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_default_enabled_spec.rb b/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_default_enabled_spec.rb
deleted file mode 100644
index cc2888063ca..00000000000
--- a/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_default_enabled_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Product Intelligence' do
- describe 'Service ping default enabled' do
- context 'when using default enabled from gitlab.yml config', :requires_admin, except: { job: 'review-qa-*' } do
- before do
- Flow::Login.sign_in_as_admin
-
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
- end
-
- it(
- 'has service ping toggle enabled',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348335'
- ) do
- Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
- setting.expand_usage_statistics do |page|
- expect(page).not_to have_disabled_usage_data_checkbox
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_disabled_spec.rb b/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_disabled_spec.rb
deleted file mode 100644
index f762adf52a1..00000000000
--- a/qa/qa/specs/features/browser_ui/14_product_intelligence/service_ping_disabled_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Product Intelligence' do
- describe 'Service ping disabled', :orchestrated, :service_ping_disabled, :requires_admin do
- context 'when disabled from gitlab.yml config' do
- before do
- Flow::Login.sign_in_as_admin
-
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
- end
-
- it(
- 'has service ping toggle is disabled',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348340'
- ) do
- Page::Admin::Settings::MetricsAndProfiling.perform do |settings|
- settings.expand_usage_statistics do |usage_statistics|
- expect(usage_statistics).to have_disabled_usage_data_checkbox
- end
- end
- end
- end
- end
- end
-end
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 db02d1e8390..2c331584cf7 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
@@ -9,7 +9,7 @@ module QA
end
end
- let(:target_group) do
+ let!(:target_group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "target-group-for-transfer_#{SecureRandom.hex(8)}"
end
@@ -19,48 +19,39 @@ module QA
Resource::Project.fabricate_via_api! do |project|
project.group = source_group
project.name = 'transfer-project'
- project.initialize_with_readme = true
end
end
- let(:edited_readme_content) { 'Here is the edited content.' }
+ let(:readme_content) { 'Here is the edited content.' }
before do
- Flow::Login.sign_in
-
- project.visit!
-
- Page::Project::Show.perform do |project|
- project.click_file('README.md')
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.add_files([
+ { file_path: 'README.md', content: readme_content }
+ ])
end
- Page::File::Show.perform(&:click_edit)
+ Flow::Login.sign_in
- Page::File::Edit.perform do |file|
- file.remove_content
- file.add_content(edited_readme_content)
- file.commit_changes
- end
+ project.visit!
end
it 'user transfers a project between groups',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347878' do
- # Retry is needed here as the target group is not avaliable for transfer right away.
- QA::Support::Retrier.retry_on_exception(reload_page: page) do
- Page::File::Show.perform(&:go_to_general_settings)
+ Page::File::Show.perform(&:go_to_general_settings)
- Page::Project::Settings::Main.perform(&:expand_advanced_settings)
+ Page::Project::Settings::Main.perform(&:expand_advanced_settings)
- Page::Project::Settings::Advanced.perform do |advanced|
- advanced.transfer_project!(project.name, target_group.full_path)
- end
+ Page::Project::Settings::Advanced.perform do |advanced|
+ advanced.transfer_project!(project.name, target_group.full_path)
end
Page::Project::Settings::Main.perform(&:click_project)
Page::Project::Show.perform do |project|
expect(project).to have_breadcrumb(target_group.path)
- expect(project).to have_readme_content(edited_readme_content)
+ expect(project).to have_readme_content(readme_content)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
index f85c07001e2..6c69e4c59d9 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Manage', :requires_admin, :skip_live_env do
+ context 'Manage', :reliable, :requires_admin, :skip_live_env do
describe '2FA' do
let!(:user) { Resource::User.fabricate_via_api! }
let!(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) }
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
index 2c7656e20f1..1d30b915594 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Manage', only: { subdomain: :staging }, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344213', type: :stale } do
+ RSpec.describe 'Manage', only: { subdomain: %i[staging staging-canary] }, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344213', type: :stale } do
describe 'basic user' do
it 'remains logged in when redirected from canary to non-canary node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347626' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
index 85ab466078a..8cc772ed022 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.shared_examples 'registration and login' do
- it 'allows the user to registers and login' do
+ it 'allows the user to register and login' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Resource::User.fabricate_via_browser_ui!
@@ -39,7 +39,7 @@ module QA
end
end
- describe 'standard', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347867' do
+ describe 'standard', :reliable, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347867' do
context 'when admin approval is not required' do
before(:all) do
set_require_admin_approval_after_user_signup_via_api(false)
@@ -69,7 +69,7 @@ module QA
Support::Waiter.wait_until(retry_on_exception: true, sleep_interval: 3) { !user.exists? }
end
- it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
+ it 'allows recreating with same credentials', :reliable, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy
Flow::Login.sign_in(as: user, skip_page_validation: true)
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 3921595204c..f624f2fb44f 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
@@ -42,10 +42,6 @@ module QA
expect(project.asset_exists?(expected_badge_image_url)).to be_truthy
end
end
-
- after do
- project&.remove_via_api!
- end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index 0063ce2613a..d07fff80b19 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
@@ -10,7 +10,6 @@ module QA
expect(project_page).to have_content(
/Project \S?#{project_name}\S+ was successfully created/
)
- expect(project_page).to have_content('create awesome project test')
expect(project_page).to have_content('The repository for this project is empty')
end
end
@@ -26,7 +25,7 @@ module QA
let(:project) do
Resource::Project.fabricate_via_browser_ui! do |project|
project.name = project_name
- project.description = 'create awesome project test'
+ project.description = nil
end
end
@@ -38,17 +37,13 @@ module QA
let(:project) do
Resource::Project.fabricate_via_browser_ui! do |project|
project.name = project_name
- project.description = 'create awesome project test'
project.personal_namespace = Runtime::User.username
+ project.description = nil
end
end
it_behaves_like 'successful project creation'
end
-
- after do
- project.remove_via_api!
- end
end
end
end
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 8201e2772aa..dbfb114dc82 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' do
+ describe 'Invite group', :reliable 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 2f148c4051c..29e590976d2 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' do
+ describe 'Project owner permissions', :reliable 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/protected_tags_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb
deleted file mode 100644
index f6448fea2d4..00000000000
--- a/qa/qa/specs/features/browser_ui/1_manage/project/protected_tags_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Manage' do
- describe 'Repository tags', :reliable do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'project-for-tags'
- project.initialize_with_readme = true
- end
- end
-
- let(:developer_user) do
- Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
- end
-
- let(:maintainer_user) do
- Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2)
- end
-
- let(:tag_name) { 'v0.0.1' }
- let(:tag_message) { 'Version 0.0.1' }
- let(:tag_release_notes) { 'Release It!' }
-
- shared_examples 'successful tag creation' do |user, testcase|
- it "can be created by #{user}", testcase: testcase do
- Flow::Login.sign_in(as: send(user))
-
- create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
-
- 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
- end
-
- shared_examples 'unsuccessful tag creation' do |user, testcase|
- it "cannot be created by an unauthorized #{user}", testcase: testcase do
- Flow::Login.sign_in(as: send(user))
-
- create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
-
- Page::Project::Tag::New.perform do |new_tag|
- expect(new_tag).to have_content('You are not allowed to create this tag as it is protected.')
- expect(new_tag).to have_element(:create_tag_button)
- end
- end
- end
-
- context 'when not protected' do
- before do
- add_members_to_project(project)
- end
-
- it_behaves_like 'successful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347930'
- it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347929'
- end
-
- context 'when protected' do
- before do
- add_members_to_project(project)
-
- Flow::Login.sign_in
-
- protect_tag_for_project(project, 'v*', 'Maintainers')
-
- Page::Main::Menu.perform(&:sign_out)
- end
-
- it_behaves_like 'unsuccessful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347927'
- it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347928'
- end
-
- def create_tag_for_project(project, name, message, release_notes)
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_repository_tags)
- Page::Project::Tag::Index.perform(&:click_new_tag_button)
-
- 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
-
- def protect_tag_for_project(project, tag, role)
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_repository_settings)
-
- Page::Project::Settings::Repository.perform do |setting|
- setting.expand_protected_tags do |protected_tags|
- protected_tags.set_tag(tag)
- protected_tags.choose_access_level_role(role)
-
- protected_tags.click_protect_tag_button
- end
- end
- end
-
- def add_members_to_project(project)
- @developer_user = developer_user
- @maintainer_user = maintainer_user
-
- project.add_member(@developer_user, Resource::Members::AccessLevel::DEVELOPER)
- project.add_member(@maintainer_user, Resource::Members::AccessLevel::MAINTAINER)
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/impersonation_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/impersonation_token_spec.rb
new file mode 100644
index 00000000000..5bcea1ff094
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/impersonation_token_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Manage' do
+ describe 'Impersonation tokens', :requires_admin do
+ let(:admin_api_client) { Runtime::API::Client.as_admin }
+
+ let!(:user) do
+ Resource::User.fabricate_via_api! do |usr|
+ usr.api_client = admin_api_client
+ usr.hard_delete_on_api_removal = true
+ end
+ end
+
+ it(
+ 'can be created and revoked via the UI',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368888'
+ ) do
+ impersonation_token = QA::Resource::ImpersonationToken.fabricate_via_browser_ui! do |impersonation_token|
+ impersonation_token.api_client = admin_api_client
+ impersonation_token.user = user
+ end
+
+ expect(impersonation_token.token).not_to be_nil
+
+ impersonation_token.revoke_via_browser_ui!
+
+ expect(page).to have_text("Revoked impersonation token #{impersonation_token.name}!")
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb
new file mode 100644
index 00000000000..66208921f0e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/design_management/add_design_content_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan', quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
+ type: :test_environment,
+ only: { job: 'review-qa-*' }
+ } do
+ describe 'Design Management' do
+ let(:issue) { Resource::Issue.fabricate_via_api! }
+ let(:design_filename) { 'banana_sample.gif' }
+ let(:design) { File.absolute_path(File.join('qa', 'fixtures', 'designs', design_filename)) }
+ let(:annotation) { "This design is great!" }
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'user adds a design and annotates it',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347822' do
+ issue.visit!
+
+ Page::Project::Issue::Show.perform do |issue|
+ issue.add_design(design)
+ issue.click_design(design_filename)
+ issue.add_annotation(annotation)
+
+ expect(issue).to have_annotation(annotation)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb
new file mode 100644
index 00000000000..8cbc6d7209c
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/design_management/archive_design_content_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan', quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
+ type: :test_environment,
+ only: { job: 'review-qa-*' }
+ } do
+ describe 'Design Management' do
+ let(:first_design) { Resource::Design.fabricate! }
+
+ let(:second_design) do
+ Resource::Design.fabricate! do |design|
+ design.issue = first_design.issue
+ design.filename = 'values.png'
+ end
+ end
+
+ let(:third_design) do
+ Resource::Design.fabricate_via_browser_ui! do |design|
+ design.issue = second_design.issue
+ design.filename = 'testfile.png'
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347713' do
+ third_design.issue.visit!
+
+ Page::Project::Issue::Show.perform do |issue|
+ issue.select_design(third_design.filename)
+
+ issue.archive_selected_designs
+
+ expect(issue).not_to have_design(third_design.filename)
+ expect(issue).to have_design(first_design.filename)
+ expect(issue).to have_design(second_design.filename)
+ end
+
+ Page::Project::Issue::Show.perform do |issue|
+ issue.select_design(second_design.filename)
+ issue.select_design(first_design.filename)
+
+ issue.archive_selected_designs
+
+ expect(issue).not_to have_design(first_design.filename)
+ expect(issue).not_to have_design(second_design.filename)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb
new file mode 100644
index 00000000000..8f4902026d2
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/design_management/modify_design_content_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan', quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
+ type: :test_environment,
+ only: { job: 'review-qa-*' }
+ } do
+ describe 'Design Management' do
+ let(:design) do
+ Resource::Design.fabricate_via_browser_ui! do |design|
+ design.filename = 'testfile.png'
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it(
+ 'user adds a design and modifies it',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347712'
+ ) do
+ design.issue.visit!
+
+ Page::Project::Issue::Show.perform do |issue|
+ expect(issue).to have_created_icon
+ end
+
+ Page::Project::Issue::Show.perform do |issue|
+ issue.update_design(design.filename)
+ expect(issue).to have_modified_icon
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index b8f1824126d..ed271533f87 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -1,11 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe(
- 'Plan',
- :smoke,
- quarantine: { issue: 'https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7099', type: :investigating, only: { subdomain: 'pre' } }
- ) do
+ RSpec.describe 'Plan', :smoke do
describe 'Issue creation' do
let(:project) { Resource::Project.fabricate_via_api! }
let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } }
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 36b7378ee2a..206e6b8a456 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
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Plan', :reliable do
describe 'Custom issue templates' do
- let(:template_name) { 'custom_issue_template'}
+ let(:template_name) { 'custom_issue_template' }
let(:template_content) { 'This is a custom issue template test' }
let(:template_project) do
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
deleted file mode 100644
index 71415c4bb57..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
- type: :test_environment,
- only: { job: 'review-qa-*' }
- } do
- context 'Design Management' do
- let(:issue) { Resource::Issue.fabricate_via_api! }
- let(:design_filename) { 'banana_sample.gif' }
- let(:design) { File.absolute_path(File.join('qa', 'fixtures', 'designs', design_filename)) }
- let(:annotation) { "This design is great!" }
-
- before do
- Flow::Login.sign_in
- end
-
- it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347822' do
- issue.visit!
-
- Page::Project::Issue::Show.perform do |issue|
- issue.add_design(design)
- issue.click_design(design_filename)
- issue.add_annotation(annotation)
-
- expect(issue).to have_annotation(annotation)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb
deleted file mode 100644
index 9b969f563a2..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
- type: :test_environment,
- only: { job: 'review-qa-*' }
- } do
- context 'Design Management' do
- let(:first_design) { Resource::Design.fabricate! }
-
- let(:second_design) do
- Resource::Design.fabricate! do |design|
- design.issue = first_design.issue
- design.filename = 'values.png'
- end
- end
-
- let(:third_design) do
- Resource::Design.fabricate_via_browser_ui! do |design|
- design.issue = second_design.issue
- design.filename = 'testfile.png'
- end
- end
-
- before do
- Flow::Login.sign_in
- end
-
- it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347713' do
- third_design.issue.visit!
-
- Page::Project::Issue::Show.perform do |issue|
- issue.select_design(third_design.filename)
-
- issue.archive_selected_designs
-
- expect(issue).not_to have_design(third_design.filename)
- expect(issue).to have_design(first_design.filename)
- expect(issue).to have_design(second_design.filename)
- end
-
- Page::Project::Issue::Show.perform do |issue|
- issue.select_design(second_design.filename)
- issue.select_design(first_design.filename)
-
- issue.archive_selected_designs
-
- expect(issue).not_to have_design(first_design.filename)
- expect(issue).not_to have_design(second_design.filename)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
deleted file mode 100644
index 6a0c51245ad..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/modify_design_content_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create', quarantine: {
- issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/366839',
- type: :test_environment,
- only: { job: 'review-qa-*' }
- } do
- context 'Design Management' do
- let(:design) do
- Resource::Design.fabricate_via_browser_ui! do |design|
- design.filename = 'testfile.png'
- end
- end
-
- before do
- Flow::Login.sign_in
- end
-
- it(
- 'user adds a design and modifies it',
- testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347712'
- ) do
- design.issue.visit!
-
- Page::Project::Issue::Show.perform do |issue|
- expect(issue).to have_created_icon
- end
-
- Page::Project::Issue::Show.perform do |issue|
- issue.update_design(design.filename)
- expect(issue).to have_modified_icon
- end
- 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
index ea531d84634..4bfd253c992 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
@@ -1,8 +1,23 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :requires_admin, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/195179', type: :flaky } do
+ 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
@@ -13,97 +28,82 @@ module QA
end
end
- before do
- jenkins_server = run_jenkins_server
+ let(:access_token) do
+ Runtime::Env.personal_access_token ||= fabricate_access_token
+ end
- Vendor::Jenkins::Page::Base.host = jenkins_server.host_address
+ before do
+ toggle_local_requests(true)
+ jenkins_server.register!
- Runtime::Env.personal_access_token ||= fabricate_personal_access_token
+ Support::Waiter.wait_until(max_duration: 30, reload_page: false, retry_on_exception: true) do
+ jenkins_client.ready?
+ end
- allow_requests_to_local_networks
+ configure_gitlab_jenkins
+ end
- setup_jenkins
+ 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
- login_to_gitlab
+ setup_project_integration
- setup_project_integration_with_jenkins
+ 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'
- expect(page).to have_text("Jenkins settings saved and active.")
+ job = create_jenkins_job
- QA::Support::Retrier.retry_on_exception do
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.new_branch = false
- push.file_name = "file_#{SecureRandom.hex(4)}.txt"
- end
-
- Vendor::Jenkins::Page::LastJobConsole.perform do |job_console|
- job_console.job_name = project_name
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.new_branch = false
+ push.file_name = "file_#{SecureRandom.hex(4)}.txt"
+ end
- job_console.visit!
+ Support::Waiter.wait_until(max_duration: 60, raise_on_failure: false, reload_page: false) do
+ job.status == :success
+ end
- Support::Waiter.wait_until(sleep_interval: 2, reload_page: page) do
- job_console.has_successful_build? && job_console.no_failed_status_update?
- end
- end
+ expect(job.status).to eql(:success), "Build failed or is not found: #{job.log}"
- project.visit!
+ project.visit!
- Flow::Pipeline.visit_latest_pipeline
+ Flow::Pipeline.visit_latest_pipeline
- Page::Project::Pipeline::Show.perform do |show|
- expect(show).to have_build('jenkins', status: :success, wait: 15)
- end
+ Page::Project::Pipeline::Show.perform do |show|
+ expect(show).to have_build('jenkins', status: :success, wait: 15)
end
end
- after do
- remove_jenkins_server
- end
+ private
- def setup_jenkins
- Vendor::Jenkins::Page::Login.perform do |login_page|
- login_page.visit!
- login_page.login
- end
-
- token_description = "token-#{SecureRandom.hex(8)}"
-
- Vendor::Jenkins::Page::NewCredentials.perform do |new_credentials|
- new_credentials.visit_and_set_gitlab_api_token(Runtime::Env.personal_access_token, token_description)
- end
-
- Vendor::Jenkins::Page::Configure.perform do |configure|
- configure.visit_and_setup_gitlab_connection(patch_host_name(Runtime::Scenario.gitlab_address, 'gitlab'), token_description) do
- configure.click_test_connection
- expect(configure).to have_success
- end
- end
+ def setup_project_integration
+ login_to_gitlab
- Vendor::Jenkins::Page::NewJob.perform do |new_job|
- new_job.visit_and_create_new_job_with_name(project_name)
- end
+ project.visit!
- Vendor::Jenkins::Page::ConfigureJob.perform do |configure_job|
- configure_job.job_name = project_name
- configure_job.configure(scm_url: patch_host_name(project.repository_http_location.git_uri, 'gitlab'))
- end
- end
+ Page::Project::Menu.perform(&:click_project)
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ Page::Project::Settings::Integrations.perform(&:click_jenkins_ci_link)
- def run_jenkins_server
- Service::DockerRun::Jenkins.new.tap do |runner|
- runner.pull
- runner.register!
+ 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 remove_jenkins_server
- Service::DockerRun::Jenkins.new.remove!
+ def login_to_gitlab
+ Flow::Login.sign_in
end
- def fabricate_personal_access_token
+ def fabricate_access_token
login_to_gitlab
token = Resource::PersonalAccessToken.fabricate!.token
@@ -111,8 +111,23 @@ module QA
token
end
- def login_to_gitlab
- Flow::Login.sign_in
+ 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)
@@ -122,32 +137,8 @@ module QA
host_name.gsub('localhost', ip_address)
end
- def setup_project_integration_with_jenkins
- 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(Vendor::Jenkins::Page::Base.host, 'jenkins-server'),
- project_name: project_name)
- end
- end
-
- def allow_requests_to_local_networks
- Page::Main::Menu.perform(&:sign_out_if_signed_in)
- Flow::Login.sign_in_as_admin
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_network_settings)
-
- Page::Admin::Settings::Network.perform do |network|
- network.expand_outbound_requests do |outbound_requests|
- outbound_requests.allow_requests_to_local_network_from_services
- end
- end
-
- Page::Main::Menu.perform(&:sign_out)
+ def toggle_local_requests(on)
+ Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: on)
end
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 3373f4f4233..6ce4217f8ac 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
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create', :reliable do
describe 'Merge request custom templates' do
- let(:template_name) { 'custom_merge_request_template'}
+ let(:template_name) { 'custom_merge_request_template' }
let(:template_content) { 'This is a custom merge request template test' }
let(:template_project) do
Resource::Project.fabricate_via_api! do |project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
index d73fb57a581..aa637ac4d55 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb
@@ -52,7 +52,12 @@ module QA
merge_request.click_commits_tab
- expect(merge_request).to have_content(commit_message)
+ # Commit does not always display immediately and may require a page refresh
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/368735
+ # TODO: Remove page refresh logic once issue is resolved.
+ Support::Retrier.retry_on_exception(max_attempts: 2, reload_page: merge_request) do
+ expect(merge_request).to have_content(commit_message)
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/3_create/pages/pages_pipeline_spec.rb
new file mode 100644
index 00000000000..191c4a096e7
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/pages/pages_pipeline_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Release', :runner do
+ # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906
+ describe 'Pages' do
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'jekyll-pages-project'
+ project.template_name = :jekyll
+ end
+ end
+
+ let(:pipeline) do
+ Resource::Pipeline.fabricate_via_api! do |pipeline|
+ pipeline.project = project
+ pipeline.variables =
+ { key: :CI_PAGES_DOMAIN, value: 'nip.io', variable_type: :env_var },
+ { key: :CI_PAGES_URL, value: 'http://127.0.0.1.nip.io', variable_type: :env_var }
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+
+ Resource::Runner.fabricate_via_api! do |runner|
+ runner.project = project
+ runner.executor = :docker
+ end
+
+ pipeline.visit!
+ end
+
+ it('runs a Pages-specific pipeline',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669') do
+ Page::Project::Pipeline::Show.perform do |show|
+ expect(show).to have_job(:pages)
+ show.click_job(:pages)
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to have_passed(timeout: 300)
+ 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
index 8074e1fa992..3db8128bc6d 100644
--- 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
@@ -28,16 +28,16 @@ module QA
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'}
+ 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'}
+ let(:license_file_name) { 'GFDL-1.2-only' }
+ let(:rendered_license_name) { 'Other' }
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
new file mode 100644
index 00000000000..fb87ca864f4
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protected_tags_spec.rb
@@ -0,0 +1,112 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Repository tags', :reliable do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-for-tags'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:developer_user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+ end
+
+ let(:maintainer_user) do
+ Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2)
+ end
+
+ let(:tag_name) { 'v0.0.1' }
+ let(:tag_message) { 'Version 0.0.1' }
+ let(:tag_release_notes) { 'Release It!' }
+
+ shared_examples 'successful tag creation' do |user, testcase|
+ it "can be created by #{user}", testcase: testcase do
+ Flow::Login.sign_in(as: send(user))
+
+ create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
+
+ 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
+ end
+
+ shared_examples 'unsuccessful tag creation' do |user, testcase|
+ it "cannot be created by an unauthorized #{user}", testcase: testcase do
+ Flow::Login.sign_in(as: send(user))
+
+ create_tag_for_project(project, tag_name, tag_message, tag_release_notes)
+
+ Page::Project::Tag::New.perform do |new_tag|
+ expect(new_tag).to have_content('You are not allowed to create this tag as it is protected.')
+ expect(new_tag).to have_element(:create_tag_button)
+ end
+ end
+ end
+
+ context 'when not protected' do
+ before do
+ add_members_to_project(project)
+ end
+
+ it_behaves_like 'successful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347930'
+ it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347929'
+ end
+
+ context 'when protected' do
+ before do
+ add_members_to_project(project)
+
+ Flow::Login.sign_in
+
+ protect_tag_for_project(project, 'v*', 'Maintainers')
+
+ Page::Main::Menu.perform(&:sign_out)
+ end
+
+ it_behaves_like 'unsuccessful tag creation', :developer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347927'
+ it_behaves_like 'successful tag creation', :maintainer_user, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347928'
+ end
+
+ def create_tag_for_project(project, name, message, release_notes)
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_repository_tags)
+ Page::Project::Tag::Index.perform(&:click_new_tag_button)
+
+ 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
+
+ def protect_tag_for_project(project, tag, role)
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_repository_settings)
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_protected_tags do |protected_tags|
+ protected_tags.set_tag(tag)
+ protected_tags.choose_access_level_role(role)
+
+ protected_tags.click_protect_tag_button
+ end
+ end
+ end
+
+ def add_members_to_project(project)
+ project.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
+ project.add_member(maintainer_user, Resource::Members::AccessLevel::MAINTAINER)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
index f374ecff3f2..55df1615f5c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
@@ -3,7 +3,8 @@
module QA
RSpec.describe 'Create' do
describe 'SSH keys support', :smoke do
- key_title = "key for ssh tests #{Time.now.to_f}"
+ let(:key_title) { "key for ssh tests #{Time.now.to_f}" }
+
key = nil
before do
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index b4519327a62..620e6870b26 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :smoke, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/326624', type: :investigating } do
+ RSpec.describe 'Create', :smoke do
describe 'Personal snippet creation' do
let(:snippet) do
Resource::Snippet.fabricate_via_browser_ui! do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb b/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb
new file mode 100644
index 00000000000..f95f624d59a
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/source_editor/source_editor_toolbar_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+# tagged transient due to feature-flag caching flakiness. Remove tag along with feature flag removal.
+module QA
+ RSpec.describe 'Create', feature_flag: { name: 'source_editor_toolbar', scope: :global } do
+ describe 'Source editor toolbar preview' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'empty-project-with-md'
+ project.initialize_with_readme = true
+ end
+ end
+
+ let(:edited_readme_content) { 'Here is the edited content.' }
+
+ before do
+ Runtime::Feature.enable(:source_editor_toolbar)
+ Flow::Login.sign_in
+ end
+
+ after do
+ Runtime::Feature.disable(:source_editor_toolbar)
+ end
+
+ it 'can preview markdown side-by-side while editing',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/367749' do
+ project.visit!
+ Page::Project::Show.perform do |project|
+ project.click_file('README.md')
+ end
+
+ Page::File::Show.perform(&:click_edit)
+
+ # wait_until required due to feature_caching. Remove along with feature flag removal.
+ Page::File::Edit.perform do |file|
+ Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page,
+ retry_on_exception: true) do
+ expect(file).to have_element(:editor_toolbar_button)
+ end
+ file.remove_content
+ file.click_editor_toolbar
+ file.add_content('# ' + edited_readme_content)
+ file.wait_for_markdown_preview('h1', edited_readme_content)
+ file.commit_changes
+ end
+
+ Page::File::Show.perform do |file|
+ aggregate_failures 'file details' do
+ expect(file).to have_notice('Your changes have been successfully committed.')
+ expect(file).to have_file_content(edited_readme_content)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb
deleted file mode 100644
index 02ee94381b2..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_lint_spec.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Verify' do
- # TODO: Remove this test when feature flag is removed
- # Flag rollout issue https://gitlab.com/gitlab-org/gitlab/-/issues/364257
- describe 'Pipeline editor', :reliable, feature_flag: {
- name: :simulate_pipeline,
- scope: :global
- } do
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'pipeline-editor-project'
- end
- end
-
- let!(:commit) do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- stages:
- - stage1
- - stage2
-
- job1:
- stage: stage1
- script: echo 'Done.'
-
- job2:
- stage: stage2
- script: echo 'Done.'
- YAML
- }
- ]
- )
- end
- end
-
- before do
- Runtime::Feature.disable(:simulate_pipeline) if Runtime::Feature.enabled?(:simulate_pipeline)
-
- Flow::Login.sign_in
- project.visit!
- Page::Project::Menu.perform(&:go_to_pipeline_editor)
- end
-
- after do
- project&.remove_via_api!
- end
-
- context 'when CI has valid syntax' do
- it 'shows valid validations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349128' do
- Page::Project::PipelineEditor::Show.perform do |show|
- aggregate_failures do
- expect(show.ci_syntax_validate_message).to have_content('Pipeline syntax is correct')
-
- show.go_to_visualize_tab
- { stage1: 'job1', stage2: 'job2' }.each_pair do |stage, job|
- expect(show).to have_stage(stage), "Pipeline graph does not have stage #{stage}."
- expect(show).to have_job(job), "Pipeline graph does not have job #{job}."
- end
-
- show.go_to_lint_tab
- expect(show.tab_alert_message).to have_content('Syntax is correct')
-
- show.go_to_view_merged_yaml_tab
- expect(show).to have_source_editor
- end
- end
- end
- end
-
- context 'when CI has invalid syntax' do
- it 'shows invalid validations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349129' do
- invalid_msg = 'syntax is invalid'
-
- Page::Project::PipelineEditor::Show.perform do |show|
- show.write_to_editor(SecureRandom.hex(10))
-
- aggregate_failures do
- show.go_to_visualize_tab
- expect(show.tab_alert_message).to have_content(invalid_msg)
-
- show.go_to_lint_tab
- expect(show.tab_alert_message).to have_content('Syntax is incorrect')
-
- show.go_to_view_merged_yaml_tab
- expect(show.tab_alert_message).to have_content(invalid_msg)
-
- expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid')
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb
new file mode 100644
index 00000000000..bef15b46fcd
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_tabs_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Verify' do
+ describe 'Pipeline editor', :reliable do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pipeline-editor-project'
+ end
+ end
+
+ let!(:commit) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ stages:
+ - stage1
+ - stage2
+
+ job1:
+ stage: stage1
+ script: echo 'Done.'
+
+ job2:
+ stage: stage2
+ script: echo 'Done.'
+ YAML
+ }
+ ]
+ )
+ end
+ end
+
+ before do
+ # Make sure a pipeline is created before visiting pipeline editor page.
+ # Otherwise, test might timeout before the page finishing fetching pipeline status.
+ Support::Waiter.wait_until { project.pipelines.present? }
+
+ Flow::Login.sign_in
+ project.visit!
+ Page::Project::Menu.perform(&:go_to_pipeline_editor)
+ end
+
+ context 'when CI has valid syntax' do
+ it(
+ 'shows valid validations',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368332'
+ ) do
+ Page::Project::PipelineEditor::Show.perform do |show|
+ aggregate_failures do
+ expect(show.ci_syntax_validate_message).to have_content('Pipeline syntax is correct')
+
+ show.go_to_visualize_tab
+ { stage1: 'job1', stage2: 'job2' }.each_pair do |stage, job|
+ expect(show).to have_stage(stage), "Pipeline graph does not have stage #{stage}."
+ expect(show).to have_job(job), "Pipeline graph does not have job #{job}."
+ end
+
+ show.go_to_validate_tab
+ show.simulate_pipeline
+ expect(show.tab_alert_title).to have_content('Simulation completed successfully')
+
+ show.go_to_view_merged_yaml_tab
+ expect(show).to have_source_editor
+ end
+ end
+ end
+ end
+
+ context 'when CI has invalid syntax' do
+ it(
+ 'shows invalid validations',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368333'
+ ) do
+ invalid_msg = 'syntax is invalid'
+
+ Page::Project::PipelineEditor::Show.perform do |show|
+ show.write_to_editor(SecureRandom.hex(10))
+
+ aggregate_failures do
+ show.go_to_visualize_tab
+ expect(show.tab_alert_message).to have_content(invalid_msg)
+
+ show.go_to_validate_tab
+ show.simulate_pipeline
+ expect(show.tab_alert_title).to have_content('Pipeline simulation completed with errors')
+
+ show.go_to_view_merged_yaml_tab
+ expect(show.tab_alert_message).to have_content(invalid_msg)
+
+ expect(show.ci_syntax_validate_message).to have_content('CI configuration is invalid')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb
new file mode 100644
index 00000000000..412498476f0
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_with_image_pull_policy_spec.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+
+module QA
+ # TODO: remove feature flag upon rollout completion
+ # FF rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/363186
+ RSpec.describe 'Verify', :runner, feature_flag: {
+ name: 'ci_docker_image_pull_policy',
+ scope: :global
+ } do
+ describe 'Pipeline with image:pull_policy' do
+ let(:runner_name) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
+ let(:job_name) { "test-job-#{pull_policies.join('-')}" }
+
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'pipeline-with-image-pull-policy'
+ end
+ end
+
+ let!(:runner) do
+ Resource::Runner.fabricate! do |runner|
+ runner.project = project
+ runner.name = runner_name
+ runner.tags = [runner_name]
+ runner.executor = :docker
+ end
+ end
+
+ before do
+ Runtime::Feature.enable(:ci_docker_image_pull_policy)
+ # Give the feature some time to switch
+ sleep(30)
+
+ update_runner_policy(allowed_policies)
+ add_ci_file
+ Flow::Login.sign_in
+ project.visit!
+ Flow::Pipeline.visit_latest_pipeline
+ end
+
+ after do
+ Runtime::Feature.disable(:ci_docker_image_pull_policy)
+
+ runner.remove_via_api!
+ end
+
+ context 'when policy is allowed' do
+ let(:allowed_policies) { %w[if-not-present always never] }
+
+ where do
+ {
+ 'with [always] policy' => {
+ pull_policies: %w[always],
+ pull_image: true,
+ message: 'Pulling docker image ruby:2.6',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/367154'
+ },
+ 'with [always if-not-present] policies' => {
+ pull_policies: %w[always if-not-present],
+ pull_image: true,
+ message: 'Pulling docker image ruby:2.6',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368857'
+ },
+ 'with [if-not-present] policy' => {
+ pull_policies: %w[if-not-present],
+ pull_image: true,
+ message: 'Using locally found image version due to "if-not-present" pull policy',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368858'
+ },
+ 'with [never] policy' => {
+ pull_policies: %w[never],
+ pull_image: false,
+ message: 'Pulling docker image',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368859'
+ }
+ }
+ end
+
+ with_them do
+ it 'applies pull policy in job correctly', testcase: params[:testcase] do
+ visit_job
+
+ if pull_image
+ expect(job_log).to have_content(message),
+ "Expected to find #{message} in #{job_log}, but didn't."
+ else
+ expect(job_log).not_to have_content(message),
+ "Found #{message} in #{job_log}, but didn't expect to."
+ end
+ end
+ end
+ end
+
+ context 'when policy is not allowed' do
+ let(:allowed_policies) { %w[never] }
+ let(:pull_policies) { %w[always] }
+
+ let(:message) do
+ 'ERROR: Preparation failed: the configured PullPolicies ([always])'\
+ ' are not allowed by AllowedPullPolicies ([never])'
+ end
+
+ it(
+ 'fails job with policy not allowed message',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/368853'
+ ) do
+ visit_job
+
+ expect(job_log).to have_content(message),
+ "Expected to find #{message} in #{job_log}, but didn't."
+ end
+ end
+
+ private
+
+ def update_runner_policy(allowed_policies)
+ Runtime::Logger.info('Updating runner config to allow pull policies...')
+
+ # Copy config.toml file from docker to local
+ # Update local file with allowed_pull_policies config
+ # Copy file with new content back to docker
+ tempdir = Tempfile.new('config.toml')
+ QA::Service::Shellout.shell("docker cp #{runner_name}:/etc/gitlab-runner/config.toml #{tempdir.path}")
+
+ File.open(tempdir.path, 'a') do |f|
+ f << %Q[ allowed_pull_policies = #{allowed_policies}\n]
+ end
+
+ QA::Service::Shellout.shell("docker cp #{tempdir.path} #{runner_name}:/etc/gitlab-runner/config.toml")
+
+ tempdir.close!
+
+ # Give runner some time to pick up new configuration
+ sleep(30)
+ end
+
+ def add_ci_file
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ default:
+ image: ruby:2.6
+ tags: [#{runner_name}]
+
+ #{job_name}:
+ script: echo "Using pull policies #{pull_policies}"
+ image:
+ name: ruby:2.6
+ pull_policy: #{pull_policies}
+ YAML
+ }
+ ]
+ )
+ end
+ end
+
+ def visit_job
+ Page::Project::Pipeline::Show.perform do |show|
+ Support::Waiter.wait_until { show.completed? }
+
+ show.click_job(job_name)
+ end
+ end
+
+ def job_log
+ Page::Project::Job::Show.perform(&:output)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
index 6918c087a4e..5a29b44e8b3 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Package' do
- describe 'Container Registry', :reliable, only: { subdomain: %i[staging pre] } do
+ describe 'Container Registry', only: { subdomain: %i[staging staging-canary pre] } do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-with-registry'
@@ -37,7 +37,7 @@ module QA
do
docker info && break
sleep 1s
- done
+ done
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
index d9d75a8ae7a..ad820977747 100644
--- a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
@@ -4,6 +4,7 @@ module QA
RSpec.describe 'Package', :orchestrated, :registry, only: { pipeline: :main } do
describe 'Dependency Proxy' do
using RSpec::Parameterized::TableSyntax
+ include Support::Helpers::MaskToken
let(:project) do
Resource::Project.fabricate_via_api! do |project|
@@ -21,6 +22,19 @@ module QA
end
end
+ let(:group_deploy_token) do
+ Resource::GroupDeployToken.fabricate_via_api! do |deploy_token|
+ deploy_token.name = 'dp-group-deploy-token'
+ deploy_token.group = project.group
+ deploy_token.scopes = %w[
+ read_registry
+ write_registry
+ ]
+ end
+ end
+
+ let(:personal_access_token) { Runtime::Env.personal_access_token }
+
let(:uri) { URI.parse(Runtime::Scenario.gitlab_address) }
let(:gitlab_host_with_port) { "#{uri.host}:#{uri.port}" }
let(:dependency_proxy_url) { "#{gitlab_host_with_port}/#{project.group.full_path}/dependency_proxy/containers" }
@@ -43,12 +57,92 @@ module QA
runner.remove_via_api!
end
- where(:case_name, :docker_client_version, :testcase) do
- 'using docker:19.03.12' | 'docker:19.03.12' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347605'
- 'using docker:20.10' | 'docker:20.10' | 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347604'
+ where do
+ {
+ 'using docker:18.09.9 and a personal access token' => {
+ docker_client_version: 'docker:18.09.9',
+ authentication_token_type: :personal_access_token,
+ token_name: 'Personal Access Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370195'
+ },
+ 'using docker:18.09.9 and a group deploy token' => {
+ docker_client_version: 'docker:18.09.9',
+ authentication_token_type: :group_deploy_token,
+ token_name: 'Deploy Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370196'
+ },
+ 'using docker:18.09.9 and a ci job token' => {
+ docker_client_version: 'docker:18.09.9',
+ authentication_token_type: :ci_job_token,
+ token_name: 'Job Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370198'
+ },
+ 'using docker:19.03.12 and a personal access token' => {
+ docker_client_version: 'docker:19.03.12',
+ authentication_token_type: :personal_access_token,
+ token_name: 'Personal Access Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370189'
+ },
+ 'using docker:19.03.12 and a group deploy token' => {
+ docker_client_version: 'docker:19.03.12',
+ authentication_token_type: :group_deploy_token,
+ token_name: 'Deploy Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370190'
+ },
+ 'using docker:19.03.12 and a ci job token' => {
+ docker_client_version: 'docker:19.03.12',
+ authentication_token_type: :ci_job_token,
+ token_name: 'Job Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370191'
+ },
+ 'using docker:20.10 and a personal access token' => {
+ docker_client_version: 'docker:20.10',
+ authentication_token_type: :personal_access_token,
+ token_name: 'Personal Access Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370192'
+ },
+ 'using docker:20.10 and a group deploy token' => {
+ docker_client_version: 'docker:20.10',
+ authentication_token_type: :group_deploy_token,
+ token_name: 'Deploy Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370193'
+ },
+ 'using docker:20.10 and a ci job token' => {
+ docker_client_version: 'docker:20.10',
+ authentication_token_type: :ci_job_token,
+ token_name: 'Job Token',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/370194'
+ }
+ }
end
with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ use_ci_variable(name: 'PERSONAL_ACCESS_TOKEN', value: personal_access_token, project: project)
+ when :group_deploy_token
+ use_group_ci_variable(
+ name: "GROUP_DEPLOY_TOKEN_#{group_deploy_token.id}",
+ value: group_deploy_token.token,
+ group: project.group
+ )
+ when :ci_job_token
+ '$CI_JOB_TOKEN'
+ end
+ end
+
+ let(:auth_user) do
+ case authentication_token_type
+ when :personal_access_token
+ "$CI_REGISTRY_USER"
+ when :group_deploy_token
+ "\"#{group_deploy_token.username}\""
+ when :ci_job_token
+ 'gitlab-ci-token'
+ end
+ end
+
it "pulls an image using the dependency proxy", testcase: params[:testcase] do
Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
@@ -65,8 +159,7 @@ module QA
command: ["--insecure-registry=gitlab.test:80"]
before_script:
- apk add curl jq grep
- - echo $CI_DEPENDENCY_PROXY_SERVER
- - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" gitlab.test:80
+ - docker login -u #{auth_user} -p #{auth_token} gitlab.test:80
script:
- docker pull #{dependency_proxy_url}/#{image_sha}
- TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
deleted file mode 100644
index d1d2340e5f1..00000000000
--- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Release', :runner do
- # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906
- describe 'Pages' do
- let!(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'jekyll-pages-project'
- project.template_name = :jekyll
- end
- end
-
- let(:pipeline) do
- Resource::Pipeline.fabricate_via_api! do |pipeline|
- pipeline.project = project
- pipeline.variables =
- { key: :CI_PAGES_DOMAIN, value: 'nip.io', variable_type: :env_var },
- { key: :CI_PAGES_URL, value: 'http://127.0.0.1.nip.io', variable_type: :env_var }
- end
- end
-
- before do
- Flow::Login.sign_in
-
- Resource::Runner.fabricate_via_api! do |runner|
- runner.project = project
- runner.executor = :docker
- end
-
- pipeline.visit!
- end
-
- it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do
- Page::Project::Pipeline::Show.perform do |show|
- expect(show).to have_job(:pages)
- show.click_job(:pages)
- end
-
- Page::Project::Job::Show.perform do |show|
- expect(show).to have_passed(timeout: 300)
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
index 980c6da2576..608dd7e089f 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Configure' do
- describe 'AutoDevOps Templates', only: { subdomain: :staging } do
+ describe 'AutoDevOps Templates', only: { subdomain: %i[staging staging-canary] } do
using RSpec::Parameterized::TableSyntax
# specify jobs to be disabled in the pipeline.
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index dca6f961047..f1a2eb71390 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Configure',
- only: { subdomain: :staging },
+ only: { subdomain: %i[staging staging-canary] },
quarantine: {
issue: 'https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1198',
type: :waiting_on
diff --git a/qa/qa/specs/features/sanity/feature_flags_spec.rb b/qa/qa/specs/features/sanity/feature_flags_spec.rb
index f771978802e..acb9528fe6a 100644
--- a/qa/qa/specs/features/sanity/feature_flags_spec.rb
+++ b/qa/qa/specs/features/sanity/feature_flags_spec.rb
@@ -26,7 +26,7 @@ module QA
end
let(:flag) { Pathname.new(file.path).basename('.yml').to_s }
- let(:root) { '..'}
+ let(:root) { '..' }
before do
definition = <<~YAML
@@ -78,7 +78,7 @@ module QA
end
context 'with an EE feature flag' do
- let(:root) { '../ee'}
+ let(:root) { '../ee' }
include_examples 'gets flag value'
end
diff --git a/qa/qa/support/helpers/mask_token.rb b/qa/qa/support/helpers/mask_token.rb
index 1f8161f7173..0c0af524c97 100644
--- a/qa/qa/support/helpers/mask_token.rb
+++ b/qa/qa/support/helpers/mask_token.rb
@@ -13,6 +13,16 @@ module QA
end
"$#{name}"
end
+
+ def use_group_ci_variable(name:, value:, group:)
+ Resource::GroupCiVariable.fabricate_via_api! do |ci_variable|
+ ci_variable.group = group
+ ci_variable.key = name
+ ci_variable.value = value
+ ci_variable.protected = true
+ end
+ "$#{name}"
+ end
end
end
end
diff --git a/qa/qa/support/knapsack_report.rb b/qa/qa/support/knapsack_report.rb
index 8114e838ede..659b8f10e0a 100644
--- a/qa/qa/support/knapsack_report.rb
+++ b/qa/qa/support/knapsack_report.rb
@@ -98,7 +98,7 @@ module QA
#
# @return [void]
def setup_logger!
- Knapsack.logger = QA::Runtime::Logger.logger
+ Knapsack.logger = logger
end
# Set knapsack environment variables
@@ -112,9 +112,9 @@ module QA
# Logger instance
#
- # @return [Logger]
+ # @return [ActiveSupport::Logger]
def logger
- @logger ||= Knapsack.logger
+ QA::Runtime::Logger.logger
end
# GCS client
diff --git a/qa/qa/support/loglinking.rb b/qa/qa/support/loglinking.rb
index caf381912d3..ceddd35da17 100644
--- a/qa/qa/support/loglinking.rb
+++ b/qa/qa/support/loglinking.rb
@@ -8,18 +8,18 @@ module QA
PRODUCTION_ADDRESS = 'https://gitlab.com'
PRE_PROD_ADDRESS = 'https://pre.gitlab.com'
SENTRY_ENVIRONMENTS = {
- staging: 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg',
+ staging: 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg',
staging_canary: 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg-cny',
- staging_ref: 'https://sentry.gitlab.net/gitlab/staging-ref/?environment=gstg-ref',
- pre: 'https://sentry.gitlab.net/gitlab/pregitlabcom/?environment=pre',
- canary: 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd',
- production: 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd-cny'
+ staging_ref: 'https://sentry.gitlab.net/gitlab/staging-ref/?environment=gstg-ref',
+ pre: 'https://sentry.gitlab.net/gitlab/pregitlabcom/?environment=pre',
+ canary: 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd',
+ production: 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd-cny'
}.freeze
KIBANA_ENVIRONMENTS = {
- staging: 'https://nonprod-log.gitlab.net/',
+ staging: 'https://nonprod-log.gitlab.net/',
staging_canary: 'https://nonprod-log.gitlab.net/',
- canary: 'https://log.gprd.gitlab.net/',
- production: 'https://log.gprd.gitlab.net/'
+ canary: 'https://log.gprd.gitlab.net/',
+ production: 'https://log.gprd.gitlab.net/'
}.freeze
def self.failure_metadata(correlation_id)
diff --git a/qa/qa/support/parallel_pipeline_jobs.rb b/qa/qa/support/parallel_pipeline_jobs.rb
new file mode 100644
index 00000000000..a551bf9978b
--- /dev/null
+++ b/qa/qa/support/parallel_pipeline_jobs.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ # Helper utility to fetch parallel job names in a given pipelines stage
+ #
+ class ParallelPipelineJobs
+ include API
+
+ PARALLEL_JOB_NAME_PATTERN = %r{^\S+ \d+/\d+$}.freeze
+
+ def initialize(stage_name:, project_id:, pipeline_id:, access_token:)
+ @stage_name = stage_name
+ @access_token = access_token
+ @project_id = project_id || raise("project_id must be provided")
+ @pipeline_id = pipeline_id || raise("pipeline_id must be provided")
+ end
+
+ # Fetch parallel job names in given stage
+ #
+ # Default to arguments available on CI
+ #
+ # @param [String] stage_name
+ # @param [Integer] project_id
+ # @param [Integer] pipeline_id
+ # @param [String] access_token
+ # @return [Array]
+ def self.fetch(
+ stage_name:,
+ access_token:,
+ project_id: ENV["CI_PROJECT_ID"],
+ pipeline_id: ENV["CI_PIPELINE_ID"]
+ )
+ new(
+ stage_name: stage_name,
+ project_id: project_id,
+ pipeline_id: pipeline_id,
+ access_token: access_token
+ ).parallel_jobs
+ end
+
+ # Parallel job list
+ #
+ # @return [Array<String>]
+ def parallel_jobs
+ api_get("projects/#{project_id}/pipelines/#{pipeline_id}/jobs?per_page=100")
+ .select { |job| job[:stage] == stage_name && job[:name].match?(PARALLEL_JOB_NAME_PATTERN) }
+ .map { |job| job[:name].gsub(%r{ \d+/\d+}, "") }
+ .uniq
+ end
+
+ private
+
+ attr_reader :stage_name, :access_token, :project_id, :pipeline_id
+
+ # Api get request
+ #
+ # @param [String] path
+ # @param [Hash] payload
+ # @return [Hash, Array]
+ def api_get(path)
+ response = get("#{api_url}/#{path}", { headers: { "PRIVATE-TOKEN" => access_token } })
+ raise "Failed to fetch pipeline jobs: '#{response.body}'" unless response.code == API::HTTP_STATUS_OK
+
+ parse_body(response)
+ end
+
+ # Gitlab api url
+ #
+ # @return [String]
+ def api_url
+ @api_url ||= ENV['CI_API_V4_URL'] || "https://gitlab.com/api/v4"
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/delete_projects.rb b/qa/qa/tools/delete_projects.rb
index 96ea5f8de7e..da46606f286 100644
--- a/qa/qa/tools/delete_projects.rb
+++ b/qa/qa/tools/delete_projects.rb
@@ -9,6 +9,7 @@ module QA
module Tools
class DeleteProjects
include Support::API
+ include Lib::Project
def initialize
raise ArgumentError, "Please provide GITLAB_ADDRESS environment variable" unless ENV['GITLAB_ADDRESS']
@@ -30,25 +31,12 @@ module QA
project_ids = fetch_project_ids(group_id, total_project_pages)
$stdout.puts "Number of projects to be deleted: #{project_ids.length}"
- delete_projects(project_ids) unless project_ids.empty?
+ delete_projects(project_ids, @api_client) unless project_ids.empty?
$stdout.puts "\nDone"
end
private
- def delete_projects(project_ids)
- $stdout.puts "Deleting #{project_ids.length} projects..."
- project_ids.each do |project_id|
- request_url = Runtime::API::Request.new(@api_client, "/projects/#{project_id}").url
- path = parse_body(get(request_url))[:path_with_namespace]
- $stdout.puts "\nDeleting project #{path}..."
-
- delete_response = delete(request_url)
- dot_or_f = delete_response.code.between?(200, 300) ? "\e[32m.\e[0m" : "\e[31mF - #{delete_response}\e[0m"
- print dot_or_f
- end
- end
-
def fetch_group_id
group_name = ENV['TOP_LEVEL_GROUP_NAME'] || "gitlab-qa-sandbox-group-#{Time.now.wday + 1}"
group_search_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_name}").url
diff --git a/qa/qa/tools/delete_user_projects.rb b/qa/qa/tools/delete_user_projects.rb
new file mode 100644
index 00000000000..9c031e352b4
--- /dev/null
+++ b/qa/qa/tools/delete_user_projects.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# This script deletes all projects owned by a given USER_ID in their personal namespace
+# Required environment variables: USER_ID, GITLAB_QA_ACCESS_TOKEN and GITLAB_ADDRESS
+# Run `rake delete_user_projects`
+
+module QA
+ module Tools
+ class DeleteUserProjects
+ include Support::API
+ include Lib::Project
+
+ def initialize(delete_before: (Date.today - 1).to_s, dry_run: false)
+ unless ENV['GITLAB_ADDRESS']
+ raise ArgumentError, "Please provide GITLAB_ADDRESS environment variable"
+ end
+
+ unless ENV['GITLAB_QA_ACCESS_TOKEN']
+ raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN environment variable"
+ end
+
+ unless ENV['USER_ID']
+ raise ArgumentError, "Please provide USER_ID environment variable"
+ end
+
+ @delete_before = Date.parse(delete_before)
+ @dry_run = dry_run
+ @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'],
+ personal_access_token: ENV['GITLAB_QA_ACCESS_TOKEN'])
+ end
+
+ def run
+ $stdout.puts 'Running...'
+
+ projects_head_response = head Runtime::API::Request.new(@api_client, "/users/#{ENV['USER_ID']}/projects",
+ per_page: "100").url
+ total_project_pages = projects_head_response.headers[:x_total_pages]
+
+ $stdout.puts "Total project pages: #{total_project_pages}"
+
+ project_ids = fetch_project_ids(total_project_pages)
+
+ delete_projects(project_ids, @api_client, @dry_run) unless project_ids.empty?
+ $stdout.puts "\nDone"
+ end
+
+ private
+
+ def fetch_project_ids(total_project_pages)
+ projects_ids = []
+
+ total_project_pages.to_i.times do |page_no|
+ projects_response = get Runtime::API::Request.new(@api_client, "/users/#{ENV['USER_ID']}/projects",
+ page: (page_no + 1).to_s, per_page: "100").url
+ projects_ids.concat(JSON.parse(projects_response.body)
+ .select { |project| Date.parse(project["created_at"]) < @delete_before }
+ .map { |project| project["id"] })
+ end
+
+ projects_ids.uniq
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/lib/project.rb b/qa/qa/tools/lib/project.rb
new file mode 100644
index 00000000000..52e5e5c63a4
--- /dev/null
+++ b/qa/qa/tools/lib/project.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module QA
+ module Tools
+ module Lib
+ module Project
+ def delete_projects(project_ids, api_client, dry_run = false)
+ if dry_run
+ $stdout.puts "Following #{project_ids.length} projects would be deleted:"
+ else
+ $stdout.puts "Deleting #{project_ids.length} projects..."
+ end
+
+ project_ids.each do |project_id|
+ request_url = Runtime::API::Request.new(api_client, "/projects/#{project_id}").url
+ parsed_body = parse_body(get(request_url))
+ path = parsed_body[:path_with_namespace]
+ created_at = parsed_body[:created_at]
+
+ if dry_run
+ $stdout.puts "#{path} - created at: #{created_at}"
+ else
+ $stdout.puts "\nDeleting project #{path} - created at: #{created_at}"
+ delete_response = delete(request_url)
+ dot_or_f = delete_response.code.between?(200, 300) ? "\e[32m.\e[0m" : "\e[31mF - #{delete_response}\e[0m"
+ print dot_or_f
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/jenkins/README.md b/qa/qa/vendor/jenkins/README.md
new file mode 100644
index 00000000000..98304bd7cb8
--- /dev/null
+++ b/qa/qa/vendor/jenkins/README.md
@@ -0,0 +1,61 @@
+## jenkins_client
+
+For use with [this jenkins docker image](https://gitlab.com/gitlab-org/quality/third-party-docker-images/jenkins)
+
+### usage
+
+instantiate client
+
+```ruby
+client = Jenkins::Client.new(
+ '127.0.0.1',
+ user: ENV['JENKINS_ADMIN_USER'],
+ password: ENV['JENKINS_ADMIN_PASS'],
+)
+```
+
+configure gitlab plugin and create a job
+
+```ruby
+connection_name = 'gitlab-connection'
+
+client.configure_gitlab_plugin(
+ ENV['GITLAB_URL'],
+ connection_name: connection_name,
+ access_token: ENV['GITLAB_ACCESS_TOKEN'],
+ read_timeout: 20,
+ connection_timeout: 10
+)
+
+job = client.create_job 'Job Name' do |job|
+ job.gitlab_connection = connection_name
+ job.description = 'Job Description'
+ job.repo_url = 'https://location-of-project.git'
+ job.shell_command = 'sleep 20'
+end
+```
+
+view info about the job
+
+```ruby
+while job.running?
+ puts "Number of active builds: #{job.active_runs}"
+end
+
+puts "Last build status #{job.status}"
+puts "Last build log #{job.log}"
+```
+
+### developer notes
+
+This client makes extensive use of the [/script api](https://docs.cloudbees.com/docs/cloudbees-ci-kb/latest/client-and-managed-masters/execute-groovy-with-a-rest-call).
+
+Groovy is a dynamic language hosted on the Java platform. Please refer to https://learnxinyminutes.com/docs/groovy/ for basic syntax.
+
+The scripts may reference the code api of jenkins and the gitlab jenkins plugin. Here are some articles and source files to reference when debugging.
+
+* [Setting Jenkins Credentials](https://nickcharlton.net/posts/setting-jenkins-credentials-with-groovy.html)
+* [GitLabConnectionConfig](https://github.com/jenkinsci/gitlab-plugin/blob/master/src/main/java/com/dabsquared/gitlabjenkins/connection/GitLabConnectionConfig.java) and [GitLabConnection](https://github.com/jenkinsci/gitlab-plugin/blob/master/src/main/java/com/dabsquared/gitlabjenkins/connection/GitLabConnection.java)
+* [Jenkins.instance.getProjects](https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/model/Jenkins.java#L1878)
+* [Job.getBuilds](https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Job.java#L734)
+* [Run.getResult](https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Run.java#L491)
diff --git a/qa/qa/vendor/jenkins/client.rb b/qa/qa/vendor/jenkins/client.rb
new file mode 100644
index 00000000000..d7666255010
--- /dev/null
+++ b/qa/qa/vendor/jenkins/client.rb
@@ -0,0 +1,298 @@
+# frozen_string_literal: true
+
+require 'base64'
+require 'cgi'
+require 'fileutils'
+require 'json'
+require 'nokogiri'
+require 'rest-client'
+require 'securerandom'
+
+require_relative './helpers'
+require_relative './job'
+
+module QA
+ module Vendor
+ module Jenkins
+ NetworkError = Class.new(StandardError)
+ NotParseableError = Class.new(StandardError)
+ class Client
+ include Helpers
+
+ attr_accessor :cookies
+
+ DEFAULT_SERVER_PORT = 8080
+
+ # @param host [String] the ip or hostname of the jenkins server
+ # @param user [String] the Jenkins admin user
+ # @param password [String] the Jenkins admin password
+ # @param port [Integer] the port that Jenkins is serving on
+ def initialize(host, user:, password:, port: nil)
+ @host = host
+ @user = user
+ @password = password
+ @port = port
+ @cookies = {}
+ end
+
+ def ready?
+ !!try_parse(RestClient.get(crumb_path, auth_headers).body)
+ end
+
+ # Creates a new job in Jenkins
+ #
+ # @param name [String] the name of the job
+ # @yieldparam job [Jenkins::Job] the job to be configured
+ # @return [Jenkins::Job] the created job in Jenkins
+ def create_job(name)
+ job = Job.new(name, self)
+ yield job if block_given?
+ job.create
+ job
+ end
+
+ # Is a given job running?
+ #
+ # @param name [String] the name of the job
+ # @return [Boolean] is the job running?
+ def job_running?(name)
+ res = execute <<~GROOVY
+ project = Jenkins.instance.getProjects().find{p -> p.getName().equals('#{name}')}
+ build = project.getBuilds().find{b -> b.getExecutor()}
+ return build ? build.getExecutor().isActive() : false
+ GROOVY
+ JSON.parse parse_result(res)
+ end
+
+ # Number of builds currently executing for a given job
+ #
+ # @param name [String] the name of the job
+ # @return [Integer] the number of builds currently running
+ def number_of_jobs_running(name)
+ res = execute <<~GROOVY
+ project = Jenkins.instance.getProjects().find{p -> p.getName().equals('#{name}')}
+ builds = project.getBuilds().findAll{b -> b.getExecutor()}
+ return builds.size
+ GROOVY
+ JSON.parse parse_result(res)&.to_i
+ end
+
+ # Latest build status for a job
+ #
+ # @param name [String] the name of the job
+ # @return [Symbol] the latest build status eg, (:success, :failure, etc)
+ def last_build_status(name)
+ res = execute <<~GROOVY
+ project = Jenkins.instance.getProjects().find{p -> p.getName().equals('#{name}')}
+ build = project.getBuilds()[-1]
+ return build.getResult()
+ GROOVY
+ parse_result(res)&.downcase&.to_sym
+ end
+
+ # Latest build id for a job
+ # Can be used to reference in other queries
+ #
+ # @param job_name [String] the name of the job
+ # @return [Integer] the latest build id
+ def last_build_id(job_name)
+ res = execute <<~GROOVY
+ project = Jenkins.instance.getProjects().find{p -> p.getName().equals('#{job_name}')}
+ build = project.getBuilds()[-1]
+ return build.getId()
+ GROOVY
+ parse_result(res)&.to_i
+ end
+
+ # Latest build log for a job
+ #
+ # @param job_name [String] the name of the job
+ # @param start [Integer] the log offset to return
+ # @return [String] the latest Jenkins log/output for this job
+ def last_build_log(job_name, start = 0)
+ get(
+ path: "/job/#{job_name}/#{last_build_id(job_name)}/logText/progressiveText",
+ params: { start: start }
+ ).body
+ end
+
+ # Triggers a build for a given job
+ #
+ # @param name [String] the name of the job to trigger a build for
+ # @param [Hash] params the query parameters as a hash for the build endpoint
+ def build(name, params: {})
+ post(params, path: "/job/#{name}/build")
+ end
+
+ # Executes a Groovy script against the Jenkins instance
+ #
+ # @param script [String] the Groovy script to execute
+ def execute(script)
+ post("script=#{script}", path: '/scriptText')
+ end
+
+ # Sends XML to a given Jenkins endpoint
+ # This might be useful for filling in gaps in this lib
+ #
+ # @param xml [String] the xml to post
+ # @param params [Hash] the query parameters as a hash
+ # @param path [String] the path to post to ex: /job/<name>/build
+ # @return [Typhoeus::Response]
+ def post_xml(xml, params: {}, path: '')
+ post(xml, params: params, path: path, headers: { 'Content-Type' => 'text/xml' })
+ end
+
+ # Posts data to Jenkins
+ # This might be useful for filling in gaps in this lib
+ #
+ # @param data [String | Hash] the xml to post
+ # @param params [Hash] the query parameters as a hash
+ # @param path [String] the path to post to ex: /job/<name>/build
+ # @param headers [Hash] additional headers to send
+ # @return [Typhoeus::Response]
+ def post(data, params: {}, path: '', headers: {})
+ get_crumb
+ RestClient.post(
+ "#{api_path}#{path}?#{params_to_s(params)}",
+ data,
+ headers.merge(full_headers)
+ )
+ end
+
+ # Gets from a Jenkins endpoint
+ # This might be useful for filling in gaps in this lib
+ #
+ # @param path [String] the path to get from ex: /job/<name>/builds/<build_id>/logText/progressiveText
+ # @param params [Hash] the query parameters as a hash
+ # @return [Typhoeus::Response]
+ def get(path: '', params: {})
+ get_crumb
+ RestClient.get(
+ "#{api_path}#{path}?#{params_to_s(params)}",
+ full_headers
+ )
+ end
+
+ # configures the Jenkins GitLab plugin
+ #
+ # @param url [String] the url for the GitLab instance
+ # @param access_token [String] an access token for the GitLab instance
+ # @param secret_id [String] an secret id used for the Jenkins GitLab credentials
+ # @param hargs [Hash] extra keyword arguments to provide
+ # @option hargs [String] :connection_name the name to use for the gitlab connection
+ # @option hargs [Integer] :read_timeout the read timeout for GitLab Jenkins
+ # @option hargs [Integer] :connection_timeout the connection timeout for GitLab Jenkins
+ # @option hargs [Boolean] :ignore_ssl_errors whether GitLab Jenkins should ignore SSL errors
+ # @return [String] the execute response from Jenkins
+ def configure_gitlab_plugin(url, access_token:, secret_id: SecureRandom.hex(4), **hargs)
+ configure_secret(access_token, secret_id)
+ configure_gitlab(url, secret_id, **hargs)
+ end
+
+ private
+
+ def parse_result(res)
+ check_network_error(res)
+
+ res.body.scan(/Result: (.*)/)&.dig(0, 0)
+ end
+
+ def configure_gitlab(
+ url,
+ secret_id,
+ connection_name: 'default',
+ read_timeout: 10,
+ connection_timeout: 10,
+ ignore_ssl_errors: true
+ )
+ res = execute <<~GROOVY
+ import com.dabsquared.gitlabjenkins.connection.*;
+ conn = new GitLabConnection(
+ "#{connection_name}",
+ "#{url}",
+ "#{secret_id}",
+ #{ignore_ssl_errors},
+ #{connection_timeout},
+ #{read_timeout}
+ );
+
+ config = GitLabConnectionConfig.get();
+ config.setConnections([conn]);
+ GROOVY
+ res.body
+ end
+
+ def configure_secret(access_token, credential_id)
+ execute <<~GROOVY
+ import jenkins.model.Jenkins;
+ import com.cloudbees.plugins.credentials.domains.Domain;
+ import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
+ import com.cloudbees.plugins.credentials.CredentialsScope;
+ import hudson.util.Secret;
+
+ instance = Jenkins.instance;
+ domain = Domain.global();
+ store = instance.getExtensionList("com.cloudbees.plugins.credentials.SystemCredentialsProvider")[0].getStore();
+
+ secretText = new StringCredentialsImpl(
+ CredentialsScope.GLOBAL,
+ "#{credential_id}",
+ "GitLab API Token",
+ Secret.fromString("#{access_token}")
+ );
+
+ store.addCredentials(domain, secretText);
+ GROOVY
+ end
+
+ def get_crumb
+ return if @crumb
+
+ response = RestClient.get(crumb_path, auth_headers)
+ response_body = handle_json_response(response)
+ @crumb = response_body['crumb']
+ end
+
+ def params_to_s(params)
+ params.each_with_object([]) do |(k, v), memo|
+ memo << "#{k}=#{v}"
+ end.join('&')
+ end
+
+ def full_headers
+ crumb_headers
+ .merge(auth_headers)
+ .merge(cookie_headers)
+ end
+
+ def crumb_headers
+ { 'Jenkins-Crumb' => @crumb }
+ end
+
+ def auth_headers
+ { 'Authorization' => "Basic #{userpwd}" }
+ end
+
+ def cookie_headers
+ { cookies: @cookies }
+ end
+
+ def userpwd
+ Base64.encode64("#{@user}:#{@password}")
+ end
+
+ def api_path
+ "http://#{@host}:#{port}"
+ end
+
+ def crumb_path
+ "#{api_path}/crumbIssuer/api/json"
+ end
+
+ def port
+ @port || DEFAULT_SERVER_PORT
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/jenkins/helpers.rb b/qa/qa/vendor/jenkins/helpers.rb
new file mode 100644
index 00000000000..38175d5687a
--- /dev/null
+++ b/qa/qa/vendor/jenkins/helpers.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Jenkins
+ module Helpers
+ private
+
+ def try_parse(string)
+ JSON.parse(string)
+ rescue StandardError => _e
+ nil
+ end
+
+ def check_network_error(response)
+ raise NetworkError, "#{response.code} - #{response.body}" if response.code >= 400
+ end
+
+ def handle_json_response(response)
+ check_network_error(response)
+ set_cookies(response)
+
+ unless (data = try_parse(response.body))
+ raise NotParseableError, "Code: #{response.code}\nBody: #{response.body}"
+ end
+
+ data
+ end
+
+ def set_cookies(response)
+ self.cookies = response.cookies
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/jenkins/job.rb b/qa/qa/vendor/jenkins/job.rb
new file mode 100644
index 00000000000..46048960fae
--- /dev/null
+++ b/qa/qa/vendor/jenkins/job.rb
@@ -0,0 +1,166 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module Jenkins
+ class Job
+ include Helpers
+
+ REQUIRED_BUILD_FIELDS = %i[name description shell_command].freeze
+
+ attr_accessor(
+ :name,
+ :description,
+ :keep_deps,
+ :can_roam,
+ :disabled,
+ :repo_url,
+ :gitlab_connection,
+ :shell_command
+ )
+
+ # Prefer Jenkins::Client#jobs and Jenkins::Client.create_job over this constructor
+ #
+ # @param name [String] the name of the job
+ # @param client [Jenkins::Client] the jenkins client
+ def initialize(name, client)
+ @name = name
+ @client = client
+ end
+
+ # Saves the Job in Jenkins
+ def create
+ validate_required_fields!
+
+ response = @client.post_xml(build, path: '/createItem', params: { name: name })
+
+ check_network_error(response)
+ response.body
+ end
+
+ # Triggers a build for the job
+ def run
+ @client.build(@name)
+ end
+
+ # Returns the jobs last build status
+ def status
+ @client.last_build_status(@name)
+ end
+
+ # Returns the jobs last log
+ #
+ # @param start [Integer] the log offset to query
+ def log(start: 0)
+ @client.last_build_log(@name, start)
+ end
+
+ # Returns whether the job is running
+ #
+ # @return [Boolean]
+ def running?
+ @client.job_running?(@name)
+ end
+
+ # Returns the count of active builds
+ #
+ # @return [Integer]
+ def active_runs
+ @client.number_of_jobs_running(@name)
+ end
+
+ private
+
+ def validate_required_fields!
+ error = REQUIRED_BUILD_FIELDS.each_with_object("") do |field, memo|
+ memo << "#{field} is required\n" unless send(field)
+ end
+ raise ArgumentError, error unless error.empty?
+ end
+
+ def build
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
+ xml.project do
+ xml.actions
+ xml.description description
+ xml.keepDependencies false
+ xml.properties do |props|
+ build_gitlab_connection(props)
+ end
+ xml.canRoam true
+ xml.disabled false
+ xml.blockBuildWhenDownstreamBuilding false
+ xml.blockBuildWhenUpstreamBuilding false
+ xml.triggers do |triggers|
+ build_gitlab_triggers(triggers)
+ end
+ xml.concurrentBuild false
+ xml.builders do
+ xml.send('hudson.tasks.Shell') do
+ xml.command shell_command
+ xml.configuredLocalRules
+ end
+ end
+ xml.publishers do |publishers|
+ build_gitlab_publishers(publishers)
+ end
+ xml.buildWrappers
+ build_scm(xml)
+ end
+ end
+ builder.to_xml
+ end
+
+ def build_scm(xml)
+ if repo_url
+ xml.scm(class: 'hudson.plugins.git.GitSCM') do
+ xml.userRemoteConfigs do
+ xml.send('hudson.plugins.git.UserRemoteConfig') do
+ xml.url repo_url
+ end
+ end
+ xml.branches do
+ xml.send('hudson.plugins.git.BranchSpec') do
+ xml.name
+ end
+ end
+ xml.configVersion 2
+ xml.doGenerateSubmoduleConfiguration false
+ xml.gitTool 'Default'
+ end
+ end
+ end
+
+ def build_gitlab_connection(xml)
+ if gitlab_connection
+ xml.send('com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty') do
+ xml.gitLabConnection gitlab_connection
+ end
+ end
+ end
+
+ def build_gitlab_triggers(xml)
+ if gitlab_connection
+ xml.send('com.dabsquared.gitlabjenkins.GitLabPushTrigger') do
+ xml.spec
+ xml.triggerOnPush true
+ xml.triggerOnMergeRequest true
+ xml.includeBranchesSpec 'main,master'
+ xml.branchFilterType 'NameBasedFilter'
+ xml.ciSkip true
+ end
+ end
+ end
+
+ def build_gitlab_publishers(xml)
+ if gitlab_connection
+ xml.send('com.dabsquared.gitlabjenkins.publisher.GitLabCommitStatusPublisher') do
+ xml.name 'jenkins'
+ xml.markUnstableAsSuccess false
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/jenkins/page/base.rb b/qa/qa/vendor/jenkins/page/base.rb
deleted file mode 100644
index 8dfbe7570f8..00000000000
--- a/qa/qa/vendor/jenkins/page/base.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class Base
- include Capybara::DSL
- include Scenario::Actable
-
- attr_reader :path
-
- class << self
- attr_accessor :host
- end
-
- def visit!
- page.visit URI.join(Base.host, path).to_s
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/configure.rb b/qa/qa/vendor/jenkins/page/configure.rb
deleted file mode 100644
index da59060152d..00000000000
--- a/qa/qa/vendor/jenkins/page/configure.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class Configure < Page::Base
- def initialize
- @path = 'configure'
- end
-
- def visit_and_setup_gitlab_connection(gitlab_host, token_description)
- visit!
- fill_in '_.name', with: 'GitLab'
- find('.setting-name', text: "Gitlab host URL").find(:xpath, "..").find('input').set gitlab_host
-
- dropdown_element = find('.setting-name', text: "Credentials").find(:xpath, "..").find('select')
-
- QA::Support::Retrier.retry_until(raise_on_failure: true) do
- dropdown_element.select "GitLab API token (#{token_description})"
- dropdown_element.value != ''
- end
-
- yield if block_given?
-
- click_save
- end
-
- def click_test_connection
- click_on 'Test Connection'
- end
-
- def has_success?
- has_css?('div.ok', text: "Success")
- end
-
- private
-
- def click_save
- click_on 'Save'
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/configure_job.rb b/qa/qa/vendor/jenkins/page/configure_job.rb
deleted file mode 100644
index 65719795720..00000000000
--- a/qa/qa/vendor/jenkins/page/configure_job.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class ConfigureJob < Page::Base
- attr_accessor :job_name
-
- def path
- "/job/#{@job_name}/configure"
- end
-
- def configure(scm_url:)
- set_git_source_code_management_url(scm_url)
- set_git_branches_to_build("*/#{Runtime::Env.default_branch}")
- click_build_when_change_is_pushed_to_gitlab
- set_publish_status_to_gitlab
-
- Support::Retrier.retry_until(sleep_interval: 0.5) do
- click_save
- wait_for_configuration_to_save
- end
- end
-
- private
-
- def set_git_source_code_management_url(repository_url)
- select_git_source_code_management
- set_repository_url(repository_url)
- end
-
- def set_git_branches_to_build(branches)
- find('.setting-name', text: "Branch Specifier (blank for 'any')").find(:xpath, "..").find('input').set branches
- end
-
- def click_build_when_change_is_pushed_to_gitlab
- find('label', text: 'Build when a change is pushed to GitLab').find(:xpath, "..").find('input').click
- end
-
- def set_publish_status_to_gitlab
- click_add_post_build_action
- select_publish_build_status_to_gitlab
- end
-
- def click_save
- click_on 'Save'
- end
-
- def select_git_source_code_management
- find('#radio-block-1').click
- end
-
- def set_repository_url(repository_url)
- find('.setting-name', text: "Repository URL").find(:xpath, "..").find('input').set repository_url
- end
-
- def click_add_post_build_action
- click_on "Add post-build action"
- end
-
- def select_publish_build_status_to_gitlab
- click_link "Publish build status to GitLab"
- end
-
- def wait_for_configuration_to_save
- QA::Support::Waiter.wait_until(max_duration: 10, raise_on_failure: false) do
- !page.current_url.include?(path)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/last_job_console.rb b/qa/qa/vendor/jenkins/page/last_job_console.rb
deleted file mode 100644
index 9fcbb8ab956..00000000000
--- a/qa/qa/vendor/jenkins/page/last_job_console.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class LastJobConsole < Page::Base
- attr_accessor :job_name
-
- CONSOLE_OUTPUT_SELECTOR = '.console-output'
-
- def path
- "/job/#{@job_name}/lastBuild/console"
- end
-
- def has_successful_build?
- # Retry on errors such as:
- # Selenium::WebDriver::Error::JavascriptError:
- # javascript error: this.each is not a function
- Support::Retrier.retry_on_exception(reload_page: page, sleep_interval: 1) do
- has_console_output? && console_output.include?('Finished: SUCCESS')
- end
- end
-
- def no_failed_status_update?
- !console_output.include?('Failed to update Gitlab commit status')
- end
-
- private
-
- def has_console_output?
- page.has_selector?(CONSOLE_OUTPUT_SELECTOR, wait: 1)
- end
-
- def console_output
- page.find(CONSOLE_OUTPUT_SELECTOR).text
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/login.rb b/qa/qa/vendor/jenkins/page/login.rb
deleted file mode 100644
index b18c02b5a44..00000000000
--- a/qa/qa/vendor/jenkins/page/login.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class Login < Page::Base
- def initialize
- @path = 'login'
- end
-
- def visit!
- super
-
- QA::Support::Retrier.retry_until(sleep_interval: 3, reload_page: page, max_attempts: 20, raise_on_failure: true) do
- page.has_text? 'Welcome to Jenkins!'
- end
- end
-
- def login
- fill_in 'j_username', with: 'admin'
- fill_in 'j_password', with: 'password'
- click_on 'Sign in'
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/new_credentials.rb b/qa/qa/vendor/jenkins/page/new_credentials.rb
deleted file mode 100644
index b0d13973090..00000000000
--- a/qa/qa/vendor/jenkins/page/new_credentials.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class NewCredentials < Page::Base
- def initialize
- @path = 'credentials/store/system/domain/_/newCredentials'
- end
-
- def visit_and_set_gitlab_api_token(api_token, description)
- visit!
- wait_for_page_to_load
- select_gitlab_api_token
- set_api_token(api_token)
- set_description(description)
- click_ok
- end
-
- private
-
- def select_gitlab_api_token
- find('.setting-name', text: "Kind").find(:xpath, "..").find('select').select "GitLab API token"
- end
-
- def set_api_token(api_token)
- fill_in '_.apiToken', with: api_token
- end
-
- def set_description(description)
- fill_in '_.description', with: description
- end
-
- def click_ok
- click_on 'OK'
- end
-
- def wait_for_page_to_load
- QA::Support::Waiter.wait_until(sleep_interval: 1.0) do
- page.has_css?('.setting-name', text: "Description")
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/vendor/jenkins/page/new_job.rb b/qa/qa/vendor/jenkins/page/new_job.rb
deleted file mode 100644
index 11fa4ca8a53..00000000000
--- a/qa/qa/vendor/jenkins/page/new_job.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'capybara/dsl'
-
-module QA
- module Vendor
- module Jenkins
- module Page
- class NewJob < Page::Base
- def initialize
- @path = 'newJob'
- end
-
- def visit_and_create_new_job_with_name(new_job_name)
- visit!
- set_new_job_name(new_job_name)
- click_free_style_project
- click_ok
- end
-
- private
-
- def set_new_job_name(new_job_name)
- fill_in 'name', with: new_job_name
- end
-
- def click_free_style_project
- find('.hudson_model_FreeStyleProject').click
- end
-
- def click_ok
- click_on 'OK'
- end
- end
- end
- end
- end
-end
diff --git a/qa/spec/scenario/test/sanity/selectors_spec.rb b/qa/spec/scenario/test/sanity/selectors_spec.rb
index 2a68dd23219..ecc8e0e0f2c 100644
--- a/qa/spec/scenario/test/sanity/selectors_spec.rb
+++ b/qa/spec/scenario/test/sanity/selectors_spec.rb
@@ -5,20 +5,26 @@ RSpec.describe QA::Scenario::Test::Sanity::Selectors do
before do
stub_const('QA::Page::Validator', validator)
+
+ allow(QA::Runtime::Logger).to receive(:warn)
+ allow(QA::Runtime::Logger).to receive(:info)
end
context 'when there are errors detected' do
+ let(:error) { 'some error' }
+
before do
- allow(validator).to receive(:errors).and_return(['some error'])
+ allow(validator).to receive(:errors).and_return([error])
end
- it 'outputs information about errors' do
- expect { described_class.perform }
- .to output(/some error/).to_stderr
+ it 'outputs information about errors', :aggregate_failures do
+ described_class.perform
+
+ expect(QA::Runtime::Logger).to have_received(:warn)
+ .with(/GitLab QA sanity selectors validation test detected problems/)
- expect { described_class.perform }
- .to output(/electors validation test detected problems/)
- .to_stderr
+ expect(QA::Runtime::Logger).to have_received(:warn)
+ .with(/#{error}/)
end
end
diff --git a/qa/spec/service/docker_run/gitlab_runner_spec.rb b/qa/spec/service/docker_run/gitlab_runner_spec.rb
index d9f201cf67e..dd4aaf8f0a1 100644
--- a/qa/spec/service/docker_run/gitlab_runner_spec.rb
+++ b/qa/spec/service/docker_run/gitlab_runner_spec.rb
@@ -33,17 +33,21 @@ module QA
end
it 'runs non-interactively' do
- expect(subject).to have_received(:shell).with(/ --non-interactive /)
+ expect(subject).to have_received_masked_shell_command(/ --non-interactive /)
end
it 'sets pertinent information' do
- expect(subject).to have_received(:shell).with(/--name #{runner_name} /)
- expect(subject).to have_received(:shell).with(/--url #{subject.address} /)
- expect(subject).to have_received(:shell).with(/--registration-token #{subject.token} /)
+ expect(subject).to have_received_masked_shell_command(/--name #{runner_name} /)
+ expect(subject).to have_received_masked_shell_command(/--url #{subject.address} /)
+ expect(subject).to have_received_masked_shell_command(/--registration-token \S+/)
+ end
+
+ it 'masks the registration token' do
+ expect(subject).to have_received(:shell).with(/#{subject.token}/, mask_secrets: [subject.token])
end
it 'runs untagged' do
- expect(subject).to have_received(:shell).with(/--run-untagged=true /)
+ expect(subject).to have_received_masked_shell_command(/--run-untagged=true /)
end
it 'has no tags' do
@@ -51,11 +55,11 @@ module QA
end
it 'runs daemonized' do
- expect(subject).to have_received(:shell).with(/ -d /)
+ expect(subject).to have_received_masked_shell_command(/ -d /)
end
it 'cleans itself up' do
- expect(subject).to have_received(:shell).with(/ --rm /)
+ expect(subject).to have_received_masked_shell_command(/ --rm /)
end
end
@@ -65,11 +69,11 @@ module QA
end
it 'passes --run-untagged=true' do
- expect(subject).to have_received(:shell).with(/--run-untagged=true /)
+ expect(subject).to have_received_masked_shell_command(/--run-untagged=true /)
end
it 'does not pass tag list' do
- expect(subject).not_to have_received(:shell).with(/--tag-list/)
+ expect(subject).not_to have_received_masked_shell_command(/--tag-list/)
end
end
@@ -82,11 +86,11 @@ module QA
end
it 'does not pass --run-untagged' do
- expect(subject).not_to have_received(:shell).with(/--run-untagged=true/)
+ expect(subject).not_to have_received_masked_shell_command(/--run-untagged=true/)
end
it 'passes the tags with comma-separation' do
- expect(subject).to have_received(:shell).with(/--tag-list #{tags.join(',')} /)
+ expect(subject).to have_received_masked_shell_command(/--tag-list #{tags.join(',')} /)
end
end
@@ -116,7 +120,7 @@ module QA
it 'defaults to the shell executor' do
register
- expect(subject).to have_received(:shell).with(/--executor shell /)
+ expect(subject).to have_received_masked_shell_command(/--executor shell /)
end
context 'docker' do
@@ -127,31 +131,31 @@ module QA
end
it 'specifies the docker executor' do
- expect(subject).to have_received(:shell).with(/--executor docker /)
+ expect(subject).to have_received_masked_shell_command(/--executor docker /)
end
it 'mounts the docker socket to the host runner' do
- expect(subject).to have_received(:shell).with(%r{-v /var/run/docker.sock:/var/run/docker.sock })
+ expect(subject).to have_received_masked_shell_command(%r{-v /var/run/docker.sock:/var/run/docker.sock })
end
it 'runs in privileged mode' do
- expect(subject).to have_received(:shell).with(/--privileged /)
+ expect(subject).to have_received_masked_shell_command(/--privileged /)
end
it 'has a default image' do
- expect(subject).to have_received(:shell).with(/--docker-image \b.+\b /)
+ expect(subject).to have_received_masked_shell_command(/--docker-image \b.+\b /)
end
it 'does not verify TLS' do
- expect(subject).to have_received(:shell).with(/--docker-tlsverify=false /)
+ expect(subject).to have_received_masked_shell_command(/--docker-tlsverify=false /)
end
it 'passes privileged mode' do
- expect(subject).to have_received(:shell).with(/--docker-privileged=true /)
+ expect(subject).to have_received_masked_shell_command(/--docker-privileged=true /)
end
it 'passes the host network' do
- expect(subject).to have_received(:shell).with(/--docker-network-mode=#{subject.network}/)
+ expect(subject).to have_received_masked_shell_command(/--docker-network-mode=#{subject.network}/)
end
end
end
@@ -170,5 +174,15 @@ module QA
expect(subject.run_untagged).to be(false)
end
end
+
+ RSpec::Matchers.define "have_received_masked_shell_command" do |cmd|
+ match do |actual|
+ expect(actual).to have_received(:shell).with(cmd, mask_secrets: anything)
+ end
+
+ match_when_negated do |actual|
+ expect(actual).not_to have_received(:shell).with(cmd, mask_secrets: anything)
+ end
+ end
end
end
diff --git a/qa/spec/support/loglinking_spec.rb b/qa/spec/support/loglinking_spec.rb
index e02ae45ee93..d1cc76bccc4 100644
--- a/qa/spec/support/loglinking_spec.rb
+++ b/qa/spec/support/loglinking_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe QA::Support::Loglinking do
it 'if correlation_id is empty' do
expect(QA::Support::Loglinking.failure_metadata('')).to eq(nil)
end
+
it 'if correlation_id is nil' do
expect(QA::Support::Loglinking.failure_metadata(nil)).to eq(nil)
end
@@ -37,14 +38,14 @@ RSpec.describe QA::Support::Loglinking do
describe '.sentry_url' do
let(:url_hash) do
{
- :staging => 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg',
- :staging_canary => 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg-cny',
- :staging_ref => 'https://sentry.gitlab.net/gitlab/staging-ref/?environment=gstg-ref',
- :pre => 'https://sentry.gitlab.net/gitlab/pregitlabcom/?environment=pre',
- :canary => 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd',
- :production => 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd-cny',
- :foo => nil,
- nil => nil
+ :staging => 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg',
+ :staging_canary => 'https://sentry.gitlab.net/gitlab/staginggitlabcom/?environment=gstg-cny',
+ :staging_ref => 'https://sentry.gitlab.net/gitlab/staging-ref/?environment=gstg-ref',
+ :pre => 'https://sentry.gitlab.net/gitlab/pregitlabcom/?environment=pre',
+ :canary => 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd',
+ :production => 'https://sentry.gitlab.net/gitlab/gitlabcom/?environment=gprd-cny',
+ :foo => nil,
+ nil => nil
}
end
@@ -60,14 +61,14 @@ RSpec.describe QA::Support::Loglinking do
describe '.kibana_url' do
let(:url_hash) do
{
- :staging => 'https://nonprod-log.gitlab.net/',
- :staging_canary => 'https://nonprod-log.gitlab.net/',
- :staging_ref => nil,
- :pre => nil,
- :canary => 'https://log.gprd.gitlab.net/',
- :production => 'https://log.gprd.gitlab.net/',
- :foo => nil,
- nil => nil
+ :staging => 'https://nonprod-log.gitlab.net/',
+ :staging_canary => 'https://nonprod-log.gitlab.net/',
+ :staging_ref => nil,
+ :pre => nil,
+ :canary => 'https://log.gprd.gitlab.net/',
+ :production => 'https://log.gprd.gitlab.net/',
+ :foo => nil,
+ nil => nil
}
end
@@ -168,6 +169,7 @@ RSpec.describe QA::Support::Loglinking do
expect(QA::Support::Loglinking.canary?).to eq(true)
end
+
it 'and not true returns false' do
allow(QA::Support::Loglinking).to receive(:cookies).and_return({ 'gitlab_canary' => { name: 'gitlab_canary', value: 'false' } })
diff --git a/qa/spec/support/page_error_checker_spec.rb b/qa/spec/support/page_error_checker_spec.rb
index ab7014f4677..735c0f83ecd 100644
--- a/qa/spec/support/page_error_checker_spec.rb
+++ b/qa/spec/support/page_error_checker_spec.rb
@@ -113,6 +113,7 @@ RSpec.describe QA::Support::PageErrorChecker do
expect(QA::Support::PageErrorChecker.parse_five_c_page_request_id(page).to_str).to eq('req678')
end
+
it 'returns nil if not present' do
allow(page).to receive(:html).and_return(error_500_no_code_str)
allow(Nokogiri::HTML).to receive(:parse).with(error_500_no_code_str).and_return(NokogiriParse.parse(error_500_no_code_str))
@@ -217,6 +218,7 @@ RSpec.describe QA::Support::PageErrorChecker do
expect(QA::Support::PageErrorChecker).to receive(:report!).with(page, 404)
QA::Support::PageErrorChecker.check_page_for_error_code(page)
end
+
it 'calls report with 500 if 500 found' do
allow(page).to receive(:html).and_return(error_500_str)
allow(Nokogiri::HTML).to receive(:parse).with(error_500_str).and_return(NokogiriParse.parse(error_500_str))
@@ -224,6 +226,7 @@ RSpec.describe QA::Support::PageErrorChecker do
expect(QA::Support::PageErrorChecker).to receive(:report!).with(page, 500)
QA::Support::PageErrorChecker.check_page_for_error_code(page)
end
+
it 'calls report with 500 if GDK backtrace found' do
allow(page).to receive(:html).and_return(backtrace_str)
allow(Nokogiri::HTML).to receive(:parse).with(backtrace_str).and_return(NokogiriParse.parse(backtrace_str))
@@ -231,6 +234,7 @@ RSpec.describe QA::Support::PageErrorChecker do
expect(QA::Support::PageErrorChecker).to receive(:report!).with(page, 500)
QA::Support::PageErrorChecker.check_page_for_error_code(page)
end
+
it 'does not call report if 500 found in project name' do
allow(page).to receive(:html).and_return(project_name_500_str)
allow(Nokogiri::HTML).to receive(:parse).with(project_name_500_str).and_return(NokogiriParse.parse(project_name_500_str))
@@ -238,6 +242,7 @@ RSpec.describe QA::Support::PageErrorChecker do
expect(QA::Support::PageErrorChecker).not_to receive(:report!)
QA::Support::PageErrorChecker.check_page_for_error_code(page)
end
+
it 'does not call report if no 404, 500 or backtrace found' do
allow(page).to receive(:html).and_return(no_error_str)
allow(Nokogiri::HTML).to receive(:parse).with(no_error_str).and_return(NokogiriParse.parse(no_error_str))
diff --git a/qa/tasks/knapsack.rake b/qa/tasks/knapsack.rake
index fe9a9c4586f..c1225964aef 100644
--- a/qa/tasks/knapsack.rake
+++ b/qa/tasks/knapsack.rake
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-# rubocop:disable Rails/RakeEnvironment
namespace :knapsack do
desc "Run tests with knapsack runner"
task :rspec, [:rspec_args] do |_, args|
@@ -16,11 +15,26 @@ namespace :knapsack do
exit QA::Specs::KnapsackRunner.run(rspec_args)
end
- desc "Download latest knapsack report or multiple reports passed via QA_KNAPSACK_REPORTS env variable"
- task :download do
- next QA::Support::KnapsackReport.download_report unless ENV["QA_KNAPSACK_REPORTS"]
+ desc "Download latest knapsack reports for parallel jobs"
+ task :download, [:stage_name] do |_, args|
+ test_stage_name = args[:stage_name]
- ENV["QA_KNAPSACK_REPORTS"].split(",").each do |report_name|
+ # QA_KNAPSACK_REPORTS remains for changes to be backwards compatible
+ # TODO: remove and only use automated detection once changes are merged
+ unless ENV["QA_KNAPSACK_REPORTS"] || test_stage_name
+ QA::Runtime::Logger.warn("Missing QA_KNAPSACK_REPORTS environment variable or test stage name for autodetection")
+ next
+ end
+
+ reports = if test_stage_name
+ QA::Support::ParallelPipelineJobs
+ .fetch(stage_name: test_stage_name, access_token: ENV["QA_GITLAB_CI_TOKEN"])
+ .map { |job| job.tr(":", "-") }
+ else
+ ENV["QA_KNAPSACK_REPORTS"].split(",")
+ end
+
+ reports.each do |report_name|
QA::Support::KnapsackReport.new(report_name).download_report
rescue StandardError => e
QA::Runtime::Logger.error(e)
@@ -37,4 +51,3 @@ namespace :knapsack do
QA::Tools::LongRunningSpecReporter.execute
end
end
-# rubocop:enable Rails/RakeEnvironment
diff --git a/qa/tasks/reliable_report.rake b/qa/tasks/reliable_report.rake
index b4dcc2ebc01..1045fd823ab 100644
--- a/qa/tasks/reliable_report.rake
+++ b/qa/tasks/reliable_report.rake
@@ -1,8 +1,6 @@
# frozen_string_literal: true
-# rubocop:disable Rails/RakeEnvironment
desc "Fetch reliable and unreliable spec data and create report"
task :reliable_spec_report, [:range, :report_in_issue_and_slack] do |_task, args|
QA::Tools::ReliableReport.run(**args)
end
-# rubocop:enable Rails/RakeEnvironment
diff --git a/qa/tasks/vulnerabilities.rake b/qa/tasks/vulnerabilities.rake
index 79d6b8683e0..cab2f8e5ca6 100644
--- a/qa/tasks/vulnerabilities.rake
+++ b/qa/tasks/vulnerabilities.rake
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-# rubocop:disable Rails/RakeEnvironment
# How to run this rake task?
# GITLAB_QA_ACCESS_TOKEN=<access_token> GITLAB_URL="<Gitlab address>" bundle exec rake
@@ -26,4 +25,3 @@ namespace :vulnerabilities do
vuln.create_vuln_report(args[:project_id], args[:vulnerability_count].to_i)
end
end
-# rubocop:enable Rails/RakeEnvironment
diff --git a/results.txt b/results.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/results.txt
diff --git a/rubocop/code_reuse_helpers.rb b/rubocop/code_reuse_helpers.rb
index 45cfa7ba78d..2769da2389c 100644
--- a/rubocop/code_reuse_helpers.rb
+++ b/rubocop/code_reuse_helpers.rb
@@ -76,10 +76,15 @@ module RuboCop
in_app_directory?(node, 'controllers')
end
+ # Returns true if the given node resides in app/graphql or ee/app/graphql.
+ def in_graphql?(node)
+ in_app_directory?(node, 'graphql')
+ end
+
# Returns true if the given node resides in app/graphql/types,
# ee/app/graphql/types, or ee/app/graphql/ee/types.
def in_graphql_types?(node)
- in_app_directory?(node, 'graphql/types') || in_app_directory?(node, 'graphql/ee/types')
+ in_graphql_directory?(node, 'types')
end
# Returns true if the given node resides in lib/api or ee/lib/api.
@@ -113,6 +118,13 @@ module RuboCop
)
end
+ # Returns true if the given node resides in app/graphql/{directory},
+ # ee/app/graphql/{directory}, or ee/app/graphql/ee/{directory}.
+ def in_graphql_directory?(node, directory)
+ in_app_directory?(node, "graphql/#{directory}") ||
+ in_app_directory?(node, "graphql/ee/#{directory}")
+ end
+
# Returns the receiver name of a send node.
#
# For the AST node `(send (const nil? :Foo) ...)` this would return
diff --git a/rubocop/cop/code_reuse/worker.rb b/rubocop/cop/code_reuse/worker.rb
index 4902920234f..3a1120ac2a1 100644
--- a/rubocop/cop/code_reuse/worker.rb
+++ b/rubocop/cop/code_reuse/worker.rb
@@ -10,7 +10,7 @@ module RuboCop
include CodeReuseHelpers
IN_CONTROLLER = 'Workers can not be used in a controller.'
- IN_API = 'Workers can not be used in a Grape API.'
+ IN_API = 'Workers can not be used in an API endpoint.'
IN_FINDER = 'Workers can not be used in a Finder.'
IN_PRESENTER = 'Workers can not be used in a Presenter.'
IN_SERIALIZER = 'Workers can not be used in a Serializer.'
@@ -32,7 +32,7 @@ module RuboCop
message =
if in_controller?(node)
IN_CONTROLLER
- elsif in_api?(node)
+ elsif in_api?(node) || in_graphql?(node)
IN_API
elsif in_finder?(node)
IN_FINDER
diff --git a/rubocop/cop/gemspec/avoid_executing_git.rb b/rubocop/cop/gemspec/avoid_executing_git.rb
new file mode 100644
index 00000000000..09789e8208c
--- /dev/null
+++ b/rubocop/cop/gemspec/avoid_executing_git.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gemspec
+ # Checks that `git` is not executed in a vendored gemspec file.
+ # In some installed containers, `git` is not available.
+ #
+ # @example
+ #
+ # # bad
+ # Gem::Specification.new do |spec|
+ # spec.test_files = `git ls-files -- test/*`.split("\n")
+ # end
+ #
+ # # good
+ # Gem::Specification.new do |spec|
+ # spec.name = 'your_cool_gem_name'
+ # spec.test_files += Dir.glob('test/**/*')
+ # end
+ #
+ class AvoidExecutingGit < Base
+ include RangeHelp
+
+ MSG = 'Do not execute `git` in gemspec.'
+
+ # @!method gem_specification(node)
+ def_node_matcher :gem_specification, <<~PATTERN
+ (block
+ (send
+ (const
+ (const {cbase nil?} :Gem) :Specification) :new)
+ ...)
+ PATTERN
+
+ def_node_matcher :send_node?, <<~PATTERN
+ send
+ PATTERN
+
+ def_node_search :executes_string, <<~PATTERN
+ $(xstr (str $_))
+ PATTERN
+
+ def on_block(block_node)
+ return unless gem_specification(block_node)
+
+ block_node.descendants.each do |node|
+ next unless send_node?(node)
+
+ str = executes_string(node)
+
+ str.each do |execute_node, val|
+ break unless val.start_with?('git ')
+
+ add_offense(execute_node, message: message)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/deprecate_track_redis_hll_event.rb b/rubocop/cop/gitlab/deprecate_track_redis_hll_event.rb
new file mode 100644
index 00000000000..3e30f3aa4d0
--- /dev/null
+++ b/rubocop/cop/gitlab/deprecate_track_redis_hll_event.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rack/utils'
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # This cop prevents from using deprecated `track_redis_hll_event` method.
+ #
+ # @example
+ #
+ # # bad
+ # track_redis_hll_event :show, name: 'p_analytics_valuestream'
+ #
+ # # good
+ # track_event :show, name: 'g_analytics_valuestream', destinations: [:redis_hll]
+ class DeprecateTrackRedisHLLEvent < RuboCop::Cop::Cop
+ MSG = '`track_redis_hll_event` is deprecated. Use `track_event` helper instead. ' \
+ 'See https://docs.gitlab.com/ee/development/service_ping/implement.html#add-new-events'
+
+ def_node_matcher :track_redis_hll_event_used?, <<~PATTERN
+ (send _ :track_redis_hll_event ...)
+ PATTERN
+
+ def on_send(node)
+ return unless track_redis_hll_event_used?(node)
+
+ add_offense(node, location: :selector)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb
index b50bdd8ca43..f748b7d9111 100644
--- a/rubocop/cop/gitlab/feature_available_usage.rb
+++ b/rubocop/cop/gitlab/feature_available_usage.rb
@@ -23,6 +23,9 @@ module RuboCop
operations
security_and_compliance
container_registry
+ environments
+ feature_flags
+ releases
].freeze
EE_FEATURES = %i[requirements].freeze
ALL_FEATURES = (FEATURES + EE_FEATURES).freeze
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index 0bebd7901f3..63bccec31c0 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -145,7 +145,7 @@ module RuboCop
return unless node.children[opts_index]
node.children[opts_index].each_pair.find do |pair|
- pair.key.value == :feature_flag
+ pair.key.value == :_deprecated_feature_flag
end&.value
else
arg_index = rugged_method?(node) ? 3 : 2
diff --git a/rubocop/cop/migration/add_limit_to_text_columns.rb b/rubocop/cop/migration/add_limit_to_text_columns.rb
index b5780e87c19..a47fbe0bf16 100644
--- a/rubocop/cop/migration/add_limit_to_text_columns.rb
+++ b/rubocop/cop/migration/add_limit_to_text_columns.rb
@@ -104,7 +104,7 @@ module RuboCop
block_node = node.each_ancestor(:block).first
create_table_node = block_node
.children
- .find { |n| TABLE_METHODS.include?(n.children[1])}
+ .find { |n| TABLE_METHODS.include?(n.children[1]) }
if create_table_node
table_name = create_table_node.children[2].value
diff --git a/rubocop/cop/scalability/bulk_perform_with_context.rb b/rubocop/cop/scalability/bulk_perform_with_context.rb
index b96aa35bfee..bb944b2ad62 100644
--- a/rubocop/cop/scalability/bulk_perform_with_context.rb
+++ b/rubocop/cop/scalability/bulk_perform_with_context.rb
@@ -20,7 +20,7 @@ module RuboCop
being scheduled, please disable this cop with a comment explaing which
context will be applied.
- Read more about it https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#worker-context
+ Read more about it https://docs.gitlab.com/ee/development/sidekiq/logging.html#worker-context
MSG
BACKGROUND_MIGRATION_WORKER_NAMES = %w[BackgroundMigrationWorker CiDatabaseWorker].freeze
diff --git a/rubocop/cop_todo.rb b/rubocop/cop_todo.rb
new file mode 100644
index 00000000000..42e2f9fbe13
--- /dev/null
+++ b/rubocop/cop_todo.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module RuboCop
+ class CopTodo
+ attr_accessor :previously_disabled
+
+ attr_reader :cop_name, :files, :offense_count
+
+ def initialize(cop_name)
+ @cop_name = cop_name
+ @files = Set.new
+ @offense_count = 0
+ @cop_class = self.class.find_cop_by_name(cop_name)
+ @previously_disabled = false
+ end
+
+ def record(file, offense_count)
+ @files << file
+ @offense_count += offense_count
+ end
+
+ def autocorrectable?
+ @cop_class&.support_autocorrect?
+ end
+
+ def to_yaml
+ yaml = []
+ yaml << '---'
+ yaml << '# Cop supports --auto-correct.' if autocorrectable?
+ yaml << "#{cop_name}:"
+
+ if previously_disabled
+ yaml << " # Offense count: #{offense_count}"
+ yaml << ' # Temporarily disabled due to too many offenses'
+ yaml << ' Enabled: false'
+ end
+
+ yaml << ' Exclude:'
+ yaml.concat files.sort.map { |file| " - '#{file}'" }
+ yaml << ''
+
+ yaml.join("\n")
+ end
+
+ def self.find_cop_by_name(cop_name)
+ RuboCop::Cop::Registry.global.find_by_cop_name(cop_name)
+ end
+ end
+end
diff --git a/rubocop/formatter/todo_formatter.rb b/rubocop/formatter/todo_formatter.rb
index 662cc1551ff..789d0418f96 100644
--- a/rubocop/formatter/todo_formatter.rb
+++ b/rubocop/formatter/todo_formatter.rb
@@ -5,6 +5,7 @@ require 'rubocop'
require 'yaml'
require_relative '../todo_dir'
+require_relative '../cop_todo'
module RuboCop
module Formatter
@@ -14,26 +15,6 @@ module RuboCop
# For example, this formatter stores offenses for `RSpec/VariableName`
# in `.rubocop_todo/rspec/variable_name.yml`.
class TodoFormatter < BaseFormatter
- class Todo
- attr_reader :cop_name, :files, :offense_count
-
- def initialize(cop_name)
- @cop_name = cop_name
- @files = Set.new
- @offense_count = 0
- @cop_class = RuboCop::Cop::Registry.global.find_by_cop_name(cop_name)
- end
-
- def record(file, offense_count)
- @files << file
- @offense_count += offense_count
- end
-
- def autocorrectable?
- @cop_class&.support_autocorrect?
- end
- end
-
DEFAULT_BASE_DIRECTORY = File.expand_path('../../.rubocop_todo', __dir__)
class << self
@@ -44,7 +25,7 @@ module RuboCop
def initialize(output, _options = {})
@directory = self.class.base_directory
- @todos = Hash.new { |hash, cop_name| hash[cop_name] = Todo.new(cop_name) }
+ @todos = Hash.new { |hash, cop_name| hash[cop_name] = CopTodo.new(cop_name) }
@todo_dir = TodoDir.new(directory)
@config_inspect_todo_dir = load_config_inspect_todo_dir
@config_old_todo_yml = load_config_old_todo_yml
@@ -65,8 +46,8 @@ module RuboCop
def finished(_inspected_files)
@todos.values.sort_by(&:cop_name).each do |todo|
- yaml = to_yaml(todo)
- path = @todo_dir.write(todo.cop_name, yaml)
+ todo.previously_disabled = previously_disabled?(todo)
+ path = @todo_dir.write(todo.cop_name, todo.to_yaml)
output.puts "Written to #{relative_path(path)}\n"
end
@@ -90,27 +71,6 @@ module RuboCop
path.delete_prefix("#{parent}/")
end
- def to_yaml(todo)
- yaml = []
- yaml << '---'
- yaml << '# Cop supports --auto-correct.' if todo.autocorrectable?
- yaml << "#{todo.cop_name}:"
-
- if previously_disabled?(todo)
- yaml << " # Offense count: #{todo.offense_count}"
- yaml << ' # Temporarily disabled due to too many offenses'
- yaml << ' Enabled: false'
- end
-
- yaml << ' Exclude:'
-
- files = todo.files.sort.map { |file| " - '#{file}'" }
- yaml.concat files
- yaml << ''
-
- yaml.join("\n")
- end
-
def check_multiple_configurations!
cop_names = @config_inspect_todo_dir.keys & @config_old_todo_yml.keys
return if cop_names.empty?
diff --git a/scripts/lib/glfm/render_wysiwyg_html_and_json.js b/scripts/lib/glfm/render_wysiwyg_html_and_json.js
index ed8bfdb4638..8f94f50d62b 100644
--- a/scripts/lib/glfm/render_wysiwyg_html_and_json.js
+++ b/scripts/lib/glfm/render_wysiwyg_html_and_json.js
@@ -1,6 +1,5 @@
import fs from 'fs';
import jsYaml from 'js-yaml';
-import { setTestTimeout } from 'jest/__helpers__/timeout';
import { renderHtmlAndJsonForAllExamples } from 'jest/content_editor/render_html_and_json_for_all_examples';
/* eslint-disable no-undef */
@@ -24,7 +23,7 @@ jest.mock('~/emoji');
// This script should be invoked via jest with the a command similar to the following:
// yarn jest --testMatch '**/render_wysiwyg_html_and_json.js' ./scripts/lib/glfm/render_wysiwyg_html_and_json.js
it('serializes html to prosemirror json', async () => {
- setTestTimeout(20000);
+ jest.setTimeout(20000);
const inputMarkdownTempfilePath = process.env.INPUT_MARKDOWN_YML_PATH;
expect(inputMarkdownTempfilePath).not.toBeUndefined();
diff --git a/scripts/lib/glfm/update_example_snapshots.rb b/scripts/lib/glfm/update_example_snapshots.rb
index 893d8d9c014..d8d6cf3cdbc 100644
--- a/scripts/lib/glfm/update_example_snapshots.rb
+++ b/scripts/lib/glfm/update_example_snapshots.rb
@@ -29,6 +29,8 @@ module Glfm
def process(skip_static_and_wysiwyg: false)
output('Updating example snapshots...')
+ setup_environment
+
output('(Skipping static HTML generation)') if skip_static_and_wysiwyg
output("Reading #{GLFM_SPEC_TXT_PATH}...")
@@ -47,6 +49,14 @@ module Glfm
private
+ def setup_environment
+ # Set 'GITLAB_TEST_FOOTNOTE_ID' in order to override random number generation in
+ # Banzai::Filter::FootnoteFilter#random_number, and thus avoid the need to
+ # perform normalization on the value. See:
+ # https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#normalization
+ ENV['GITLAB_TEST_FOOTNOTE_ID'] = '42'
+ end
+
def add_example_names(all_examples)
# NOTE: This method and the parse_examples method assume:
# 1. Section 2 is the first section which contains examples
diff --git a/scripts/lint-vendored-gems.sh b/scripts/lint-vendored-gems.sh
new file mode 100755
index 00000000000..ac8b837bbd1
--- /dev/null
+++ b/scripts/lint-vendored-gems.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# Rubocop doesn't have a good way to run excluded files without a separate invocation:
+# https://github.com/rubocop/rubocop/issues/6323
+find vendor/gems -name \*.gemspec | xargs bundle exec rubocop --only Gemspec/AvoidExecutingGit
diff --git a/scripts/perf/query_limiting_report.rb b/scripts/perf/query_limiting_report.rb
index 2f263eeb567..89abc1b301b 100755
--- a/scripts/perf/query_limiting_report.rb
+++ b/scripts/perf/query_limiting_report.rb
@@ -124,7 +124,7 @@ class QueryLimitingReport
file_lines.each_index do |index|
line = file_lines[index]
- if line =~ /#{CODE_LINES_SEARCH_STRING}/
+ if line =~ /#{CODE_LINES_SEARCH_STRING}/o
issue_iid = line.slice(%r{issues/(\d+)\D}, 1)
line_number = index + 1
code_line = {
diff --git a/scripts/qa/testcases-check b/scripts/qa/testcases-check
index 1d7a9d04e7b..12af15fe73f 100755
--- a/scripts/qa/testcases-check
+++ b/scripts/qa/testcases-check
@@ -51,9 +51,9 @@ tests.each do |test|
end
end
-testcase_list = testcases.group_by {|testcase| testcase.shift}.transform_values(&:flatten)
+testcase_list = testcases.group_by { |testcase| testcase.shift }.transform_values(&:flatten)
-duplicates = testcase_list.select {|k, v| v.count > 1}
+duplicates = testcase_list.select { |k, v| v.count > 1 }
unless duplicates.empty?
duplicates.each do |duplicate|
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index b6ac7b4281b..e979d0f75cf 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -219,7 +219,7 @@ function create_application_secret() {
kubectl create secret generic --namespace "${namespace}" \
"shared-gitlab-initial-root-password" \
--from-literal="password=${REVIEW_APPS_ROOT_PASSWORD}" \
- --dry-run -o json | kubectl apply -f -
+ --dry-run=client -o json | kubectl apply -f -
else
echoinfo "The 'shared-gitlab-initial-root-password' secret already exists in the ${namespace} namespace."
fi
@@ -232,7 +232,7 @@ function create_application_secret() {
kubectl create secret generic --namespace "${namespace}" \
"shared-gitlab-license" \
--from-file=license="${REVIEW_APPS_EE_LICENSE_FILE}" \
- --dry-run -o json | kubectl apply -f -
+ --dry-run=client -o json | kubectl apply -f -
else
echoinfo "The 'shared-gitlab-license' secret already exists in the ${namespace} namespace."
fi
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 14d6a3deccb..1e9fe1cc724 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -11,7 +11,9 @@ class StaticAnalysis
# https://github.com/browserslist/browserslist/blob/d0ec62eb48c41c218478cd3ac28684df051cc865/node.js#L329
# warns if caniuse-lite package is older than 6 months. Ignore this
# warning message so that GitLab backports don't fail.
- "Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`"
+ "Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`",
+ # https://github.com/mime-types/mime-types-data/pull/50#issuecomment-1060908930
+ "Type application/netcdf is already registered as a variant of application/netcdf."
].freeze
Task = Struct.new(:command, :duration) do
@@ -57,7 +59,8 @@ class StaticAnalysis
Task.new(%w[yarn run block-dependencies], 1),
Task.new(%w[yarn run check-dependencies], 1),
Task.new(%w[scripts/lint-rugged], 1),
- Task.new(%w[scripts/gemfile_lock_changed.sh], 1)
+ Task.new(%w[scripts/gemfile_lock_changed.sh], 1),
+ Task.new(%w[scripts/lint-vendored-gems.sh], 1)
].compact.freeze
def run_tasks!(options = {})
diff --git a/scripts/trigger-build.rb b/scripts/trigger-build.rb
index 28b52fa916a..57cc6a8551e 100755
--- a/scripts/trigger-build.rb
+++ b/scripts/trigger-build.rb
@@ -382,9 +382,10 @@ module Trigger
private
def ops_gitlab_client
+ # No access token is needed here - we only use this client to trigger pipelines,
+ # and the trigger token authenticates the request to the pipeline
@ops_gitlab_client ||= Gitlab.client(
- endpoint: 'https://ops.gitlab.net/api/v4',
- private_token: ENV['GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN']
+ endpoint: 'https://ops.gitlab.net/api/v4'
)
end
diff --git a/scripts/undercoverage b/scripts/undercoverage
index b9266b015a7..86153671d6a 100755
--- a/scripts/undercoverage
+++ b/scripts/undercoverage
@@ -22,4 +22,5 @@ end
compare_base = ARGV[0]
compare_base ||= IO.popen(%w(git merge-base origin/master HEAD)) { |p| p.read.chomp }
-Undercover::CLI.run(%W(-c #{compare_base}))
+result = Undercover::CLI.run(%W(-c #{compare_base}))
+exit result
diff --git a/scripts/utils.sh b/scripts/utils.sh
index d9205921963..8db525abc93 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -72,10 +72,6 @@ function setup_db() {
run_timed_command "setup_db_praefect"
}
-function install_api_client_dependencies_with_apk() {
- run_timed_command "apk add --update openssl curl jq"
-}
-
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"
@@ -185,5 +181,5 @@ function danger_as_local() {
# Force danger to skip CI source GitLab and fallback to "local only git repo".
unset GITLAB_CI
# We need to base SHA to help danger determine the base commit for this shallow clone.
- bundle exec danger dry_run --fail-on-errors=true --verbose --base="${CI_MERGE_REQUEST_DIFF_BASE_SHA}" --head="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}"
+ bundle exec danger dry_run --fail-on-errors=true --verbose --base="${CI_MERGE_REQUEST_DIFF_BASE_SHA}" --head="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}" --dangerfile="${DANGER_DANGERFILE:-Dangerfile}"
}
diff --git a/scripts/validate_migration_schema b/scripts/validate_migration_schema
index dded5c64927..5c389851844 100755
--- a/scripts/validate_migration_schema
+++ b/scripts/validate_migration_schema
@@ -87,7 +87,7 @@ class MigrationSchemaValidator
def find_migration_version(filename)
file_basename = File.basename(filename)
- version_match = /\A(?<version>\d{#{VERSION_DIGITS}})_/.match(file_basename)
+ version_match = /\A(?<version>\d{#{VERSION_DIGITS}})_/o.match(file_basename)
die "#{filename} has an invalid migration version" if version_match.nil?
diff --git a/security.txt b/security.txt
index f7adb43fda6..f19a0b6283d 100644
--- a/security.txt
+++ b/security.txt
@@ -1,6 +1,16 @@
-Contact: security@gitlab.com
+# Preferred disclosure is via HackerOne
+Contact: https://hackerone.com/gitlab/
+# Additional disclosure processes are available in our handbook:
+Contact: https://about.gitlab.com/security/disclosure/
+
+Policy: https://hackerone.com/gitlab/
+
+Acknowledgments: https://hackerone.com/gitlab/
Acknowledgments: https://about.gitlab.com/security/vulnerability-acknowledgements/
+
+Canonical: https://gitlab.com/gitlab-org/gitlab/-/blob/master/security.txt
+
Preferred-Languages: en
-Canonical: https://about.gitlab.com/security/disclosure/
-Policy: https://hackerone.com/gitlab
Hiring: https://about.gitlab.com/jobs/
+
+Expires: 2023-07-31T00:00:00Z
diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb
index f5b2cdd2fca..4943669bde0 100644
--- a/spec/channels/application_cable/connection_spec.rb
+++ b/spec/channels/application_cable/connection_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do
end
context 'with a stale password' do
- let(:partial_password_hash) { build(:user, password: 'some_old_password').authenticatable_salt }
+ let(:partial_password_hash) { build(:user, password: User.random_password).authenticatable_salt }
let(:session_hash) { { 'warden.user.user.key' => [[user.id], partial_password_hash] } }
it 'sets current_user to nil' do
diff --git a/spec/channels/awareness_channel_spec.rb b/spec/channels/awareness_channel_spec.rb
index 8d6dc36f6bd..47b1cd0188f 100644
--- a/spec/channels/awareness_channel_spec.rb
+++ b/spec/channels/awareness_channel_spec.rb
@@ -36,6 +36,7 @@ RSpec.describe AwarenessChannel, :clean_gitlab_redis_shared_state, type: :channe
collaborator = {
id: user.id,
name: user.name,
+ username: user.username,
avatar_url: user.avatar_url(size: 36),
last_activity: Time.zone.now,
last_activity_humanized: ActionController::Base.helpers.distance_of_time_in_words(
@@ -63,7 +64,7 @@ RSpec.describe AwarenessChannel, :clean_gitlab_redis_shared_state, type: :channe
session = AwarenessSession.for("/test")
expect { subscription.unsubscribe_from_channel }
- .to change { session.size}.by(-1)
+ .to change { session.size }.by(-1)
end
end
end
diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb
index 55e8ab7885e..4d1a07a6a75 100644
--- a/spec/commands/sidekiq_cluster/cli_spec.rb
+++ b/spec/commands/sidekiq_cluster/cli_spec.rb
@@ -245,9 +245,9 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
it 'expands multiple queue groups correctly' do
expected_workers =
if Gitlab.ee?
- [%w[chat_notification], %w[project_export project_template_export]]
+ [%w[chat_notification], %w[project_export projects_import_export_relation_export project_template_export]]
else
- [%w[chat_notification], %w[project_export]]
+ [%w[chat_notification], %w[project_export projects_import_export_relation_export]]
end
expect(Gitlab::SidekiqCluster)
diff --git a/spec/components/diffs/overflow_warning_component_spec.rb b/spec/components/diffs/overflow_warning_component_spec.rb
index ee4014ee492..88c5de32de7 100644
--- a/spec/components/diffs/overflow_warning_component_spec.rb
+++ b/spec/components/diffs/overflow_warning_component_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Diffs::OverflowWarningComponent, type: :component do
end
describe "rendered component" do
- subject { rendered_component }
+ subject { rendered_content }
context "on a commit page" do
before do
diff --git a/spec/components/diffs/stats_component_spec.rb b/spec/components/diffs/stats_component_spec.rb
index 2e5a5f2ca26..be55c23d040 100644
--- a/spec/components/diffs/stats_component_spec.rb
+++ b/spec/components/diffs/stats_component_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Diffs::StatsComponent, type: :component do
let_it_be(:diff_files) { [diff_file] }
describe "rendered component" do
- subject { rendered_component }
+ subject { page }
let(:element) { page.find(".js-diff-stats-dropdown") }
diff --git a/spec/components/docs/01_overview.html.erb b/spec/components/docs/01_overview.html.erb
new file mode 100644
index 00000000000..da4178ebcb5
--- /dev/null
+++ b/spec/components/docs/01_overview.html.erb
@@ -0,0 +1,20 @@
+---
+title: Welcome to our Lookbook 👋
+---
+
+<p>With Lookbook we can navigate, inspect and interact with our ViewComponent previews.</p>
+
+<h2>Usage</h2>
+
+<ul>
+ <li>Use the sidebar on the left to navigate our component previews.</li>
+ <li>Many previews can be interacted with by making changes in the <em>Params</em> tab.</li>
+ <li>Some previews have additional usage instructions in their <em>Notes</em> tab.</li>
+</ul>
+
+<h2>Learn more</h2>
+
+<ul>
+ <li>Learn all about <a href="https://viewcomponent.org/">ViewComponent</a> and <a href="https://github.com/allmarkedup/lookbook">Lookbook</a>.</li>
+ <li>Have a look at our ViewComponent page in the <a href="https://docs.gitlab.com/ee/development/fe_guide/view_component.html">Frontend development docs</a>.</li>
+</ul>
diff --git a/spec/components/pajamas/avatar_component_spec.rb b/spec/components/pajamas/avatar_component_spec.rb
new file mode 100644
index 00000000000..3b4e4e49fc2
--- /dev/null
+++ b/spec/components/pajamas/avatar_component_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe Pajamas::AvatarComponent, type: :component do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+
+ let(:options) { {} }
+
+ before do
+ render_inline(described_class.new(record, **options))
+ end
+
+ describe "avatar shape" do
+ context "for a User" do
+ let(:record) { user }
+
+ it "has a circle shape" do
+ expect(page).to have_css ".gl-avatar.gl-avatar-circle"
+ end
+ end
+
+ context "for a Project" do
+ let(:record) { project }
+
+ it "has default shape (rect)" do
+ expect(page).to have_css ".gl-avatar"
+ expect(page).not_to have_css ".gl-avatar-circle"
+ end
+ end
+
+ context "for a Group" do
+ let(:record) { group }
+
+ it "has default shape (rect)" do
+ expect(page).to have_css ".gl-avatar"
+ expect(page).not_to have_css ".gl-avatar-circle"
+ end
+ end
+ end
+
+ describe "avatar image" do
+ context "when it has an uploaded image" do
+ let(:record) { project }
+
+ before do
+ allow(record).to receive(:avatar_url).and_return "/example.png"
+ render_inline(described_class.new(record, **options))
+ end
+
+ it "uses the avatar_url as image src" do
+ expect(page).to have_css "img.gl-avatar[src='/example.png?width=64']"
+ end
+
+ it "uses a srcset for higher resolution on retina displays" do
+ expect(page).to have_css "img.gl-avatar[srcset='/example.png?width=64 1x, /example.png?width=128 2x']"
+ end
+
+ it "uses lazy loading" do
+ expect(page).to have_css "img.gl-avatar[loading='lazy']"
+ end
+
+ context "with size option" do
+ let(:options) { { size: 16 } }
+
+ it "uses that size as param for image src and srcset" do
+ expect(page).to have_css(
+ "img.gl-avatar[src='/example.png?width=16'][srcset='/example.png?width=16 1x, /example.png?width=32 2x']"
+ )
+ end
+ end
+ end
+
+ context "when a project or group has no uploaded image" do
+ let(:record) { project }
+
+ it "uses an identicon with the record's initial" do
+ expect(page).to have_css "div.gl-avatar.gl-avatar-identicon", text: record.name[0].upcase
+ end
+
+ context "when the record has no id" do
+ let(:record) { build :group }
+
+ it "uses an identicon with default background color" do
+ expect(page).to have_css "div.gl-avatar.gl-avatar-identicon-bg1"
+ end
+ end
+ end
+
+ context "when a user has no uploaded image" do
+ let(:record) { user }
+
+ it "uses a gravatar" do
+ expect(rendered_component).to match /gravatar\.com/
+ end
+ end
+ end
+
+ describe "options" do
+ let(:record) { user }
+
+ describe "alt" do
+ context "with a value" do
+ let(:options) { { alt: "Profile picture" } }
+
+ it "uses given value as alt text" do
+ expect(page).to have_css ".gl-avatar[alt='Profile picture']"
+ end
+ end
+
+ context "without a value" do
+ it "uses the record's name as alt text" do
+ expect(page).to have_css ".gl-avatar[alt='#{record.name}']"
+ end
+ end
+ end
+
+ describe "class" do
+ let(:options) { { class: 'gl-m-4' } }
+
+ it 'has the correct custom class' do
+ expect(page).to have_css '.gl-avatar.gl-m-4'
+ end
+ end
+
+ describe "size" do
+ let(:options) { { size: 96 } }
+
+ it 'has the correct size class' do
+ expect(page).to have_css '.gl-avatar.gl-avatar-s96'
+ end
+ end
+ end
+end
diff --git a/spec/components/pajamas/banner_component_spec.rb b/spec/components/pajamas/banner_component_spec.rb
index 26468d80c77..861b10c3f69 100644
--- a/spec/components/pajamas/banner_component_spec.rb
+++ b/spec/components/pajamas/banner_component_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Pajamas::BannerComponent, type: :component do
end
let(:title) { "Banner title" }
- let(:content) { "Banner content"}
+ let(:content) { "Banner content" }
let(:options) { {} }
describe 'basic usage' do
diff --git a/spec/components/pajamas/button_component_spec.rb b/spec/components/pajamas/button_component_spec.rb
index a8c96042580..00423fd22a4 100644
--- a/spec/components/pajamas/button_component_spec.rb
+++ b/spec/components/pajamas/button_component_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
let(:content) { "Button content" }
let(:options) { {} }
- describe 'basic usage' do
+ RSpec.shared_examples 'basic button behavior' do
before do
render_inline(subject) do |c|
content
@@ -59,7 +59,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
describe 'disabled' do
context 'by default (false)' do
it 'does not have disabled styling and behavior' do
- expect(page).not_to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
+ expect(page).not_to have_css ".disabled[disabled][aria-disabled]"
end
end
@@ -67,7 +67,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
let(:options) { { disabled: true } }
it 'has disabled styling and behavior' do
- expect(page).to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
+ expect(page).to have_css ".disabled[disabled][aria-disabled]"
end
end
end
@@ -75,7 +75,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
describe 'loading' do
context 'by default (false)' do
it 'is not disabled' do
- expect(page).not_to have_css ".disabled[disabled='disabled']"
+ expect(page).not_to have_css ".disabled[disabled]"
end
it 'does not render a spinner' do
@@ -87,7 +87,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
let(:options) { { loading: true } }
it 'is disabled' do
- expect(page).to have_css ".disabled[disabled='disabled']"
+ expect(page).to have_css ".disabled[disabled]"
end
it 'renders a spinner' do
@@ -218,9 +218,13 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
end
end
end
+ end
+
+ context 'button component renders a button' do
+ include_examples 'basic button behavior'
describe 'type' do
- context 'by default (without href)' do
+ context 'by default' do
it 'has type "button"' do
expect(page).to have_css "button[type='button']"
end
@@ -238,34 +242,42 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
end
end
- context 'when set to unkown type' do
+ context 'when set to unknown type' do
let(:options) { { type: :madeup } }
it 'has type "button"' do
expect(page).to have_css "button[type='button']"
end
end
+ end
+ end
- context 'for links (with href)' do
- let(:options) { { href: 'https://example.com', type: :reset } }
+ context 'button component renders a link' do
+ let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
- it 'ignores type' do
- expect(page).not_to have_css "[type]"
- end
- end
+ it "renders a link instead of the button" do
+ expect(page).not_to have_css "button[type='button']"
+ expect(page).to have_css "a[href='https://gitlab.com'][target='_blank']"
end
- describe 'link button' do
- it 'renders a button tag with type="button" when "href" is not set' do
- expect(page).to have_css "button[type='button']"
+ include_examples 'basic button behavior'
+
+ describe 'type' do
+ let(:options) { { href: 'https://example.com', type: :reset } }
+
+ it 'ignores type' do
+ expect(page).not_to have_css "[type]"
end
+ end
+
+ describe 'method' do
+ where(:method) { [:get, :post, :put, :delete, :patch] }
- context 'when "href" is provided' do
- let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
+ let(:options) { { href: 'https://gitlab.com', method: method } }
- it "renders a link instead of the button" do
- expect(page).not_to have_css "button[type='button']"
- expect(page).to have_css "a[href='https://gitlab.com'][target='_blank']"
+ with_them do
+ it 'has the correct data-method attribute' do
+ expect(page).to have_css "a[data-method='#{method}']"
end
end
end
diff --git a/spec/components/pajamas/checkbox_component_spec.rb b/spec/components/pajamas/checkbox_component_spec.rb
index d79c537a30e..3d50509ef10 100644
--- a/spec/components/pajamas/checkbox_component_spec.rb
+++ b/spec/components/pajamas/checkbox_component_spec.rb
@@ -8,12 +8,6 @@ RSpec.describe Pajamas::CheckboxComponent, :aggregate_failures, type: :component
let_it_be(:label) { "Show one file at a time on merge request's Changes tab" }
let_it_be(:help_text) { 'Instead of all the files changed, show only one file at a time.' }
- RSpec.shared_examples 'it renders unchecked checkbox with value of `1`' do
- it 'renders unchecked checkbox with value of `1`' do
- expect(page).to have_unchecked_field(label, with: '1')
- end
- end
-
context 'with default options' do
before do
fake_form_for do |form|
diff --git a/spec/components/pajamas/checkbox_tag_component_spec.rb b/spec/components/pajamas/checkbox_tag_component_spec.rb
new file mode 100644
index 00000000000..bca7a6005d5
--- /dev/null
+++ b/spec/components/pajamas/checkbox_tag_component_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe Pajamas::CheckboxTagComponent, :aggregate_failures, type: :component do
+ let_it_be(:name) { :view_diffs_file_by_file }
+ let_it_be(:label) { "Show one file at a time on merge request's Changes tab" }
+ let_it_be(:help_text) { 'Instead of all the files changed, show only one file at a time.' }
+
+ context 'with default options' do
+ before do
+ render_inline(described_class.new(name: name)) do |c|
+ c.label { label }
+ end
+ end
+
+ include_examples 'it renders unchecked checkbox with value of `1`'
+ include_examples 'it does not render help text'
+ end
+
+ context 'with custom options' do
+ let_it_be(:value) { 'yes' }
+ let_it_be(:checkbox_options) { { class: 'checkbox-foo-bar', checked: true } }
+ let_it_be(:label_options) { { class: 'label-foo-bar' } }
+
+ before do
+ render_inline(
+ described_class.new(
+ name: name,
+ value: value,
+ checked: true,
+ checkbox_options: checkbox_options,
+ label_options: label_options
+ )
+ ) do |c|
+ c.label { label }
+ end
+ end
+
+ it 'renders checked checkbox with value of `yes`' do
+ expect(page).to have_checked_field(label, with: value, class: checkbox_options[:class])
+ end
+
+ it 'adds CSS class to label' do
+ expect(page).to have_selector('label.label-foo-bar')
+ end
+ end
+
+ context 'with `help_text` slot' do
+ before do
+ render_inline(described_class.new(name: name)) do |c|
+ c.label { label }
+ c.help_text { help_text }
+ end
+ end
+
+ include_examples 'it renders unchecked checkbox with value of `1`'
+ include_examples 'it renders help text'
+ end
+end
diff --git a/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
index 7a792592b3c..4994abcfb93 100644
--- a/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
+++ b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
attr_reader(
:form,
:method,
+ :name,
:label_argument,
:help_text_argument,
:label_options,
@@ -16,8 +17,9 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
)
def initialize(
- form:,
- method:,
+ form: nil,
+ method: nil,
+ name: nil,
label: nil,
help_text: nil,
label_options: {},
@@ -26,6 +28,7 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
)
@form = form
@method = method
+ @name = name
@label_argument = label
@help_text_argument = help_text
@label_options = label_options
@@ -46,19 +49,25 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
end
include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
+ include ActionView::Context
include ActionView::Helpers::TagHelper
+ include ActionView::Helpers::FormTagHelper
end
end
- let_it_be(:method) { 'username' }
+ let_it_be(:method_or_name) { 'username' }
let_it_be(:label_options) { { class: 'foo-bar' } }
let_it_be(:value) { 'Foo bar' }
+ let_it_be(:expected_label_entry) { '<span>Label argument</span>' }
+ let_it_be(:expected_label_with_help_text_entry) do
+ '<span>Label argument</span><p class="help-text" data-testid="pajamas-component-help-text">Help text argument</p>'
+ end
describe '#render_label_with_help_text' do
it 'calls `#format_options` with correct arguments' do
allow(form).to receive(:label)
- component = component_class.new(form: form, method: method, label_options: label_options, value: value)
+ component = component_class.new(form: form, method: method_or_name, label_options: label_options, value: value)
expect(component).to receive(:format_options).with(
options: label_options,
@@ -73,16 +82,13 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
it 'calls `form.label` with `label` and `help_text` arguments used in the block' do
component = component_class.new(
form: form,
- method: method,
+ method: method_or_name,
label: 'Label argument',
help_text: 'Help text argument'
)
- expected_label_entry = '<span>Label argument</span><p class="help-text"' \
- ' data-testid="pajamas-component-help-text">Help text argument</p>'
-
- expect(form).to receive(:label).with(method, {}) do |&block|
- expect(block.call).to eq(expected_label_entry)
+ expect(form).to receive(:label).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_with_help_text_entry)
end
component.render_label_with_help_text
@@ -93,13 +99,11 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
it 'calls `form.label` with `label` argument used in the block' do
component = component_class.new(
form: form,
- method: method,
+ method: method_or_name,
label: 'Label argument'
)
- expected_label_entry = '<span>Label argument</span>'
-
- expect(form).to receive(:label).with(method, {}) do |&block|
+ expect(form).to receive(:label).with(method_or_name, {}) do |&block|
expect(block.call).to eq(expected_label_entry)
end
@@ -107,4 +111,49 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
end
end
end
+
+ describe '#render_label_tag_with_help_text' do
+ it 'calls `#format_options` with correct arguments' do
+ component = component_class.new(name: method_or_name, label_options: label_options, value: value)
+
+ expect(component).to receive(:format_options).with(
+ options: label_options,
+ css_classes: ['custom-control-label'],
+ additional_options: { value: value }
+ )
+
+ component.render_label_tag_with_help_text
+ end
+
+ context 'when `help_text` argument is passed' do
+ it 'calls `label_tag` with `label` and `help_text` arguments used in the block' do
+ component = component_class.new(
+ name: method_or_name,
+ label: 'Label argument',
+ help_text: 'Help text argument'
+ )
+
+ expect(component).to receive(:label_tag).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_with_help_text_entry)
+ end
+
+ component.render_label_tag_with_help_text
+ end
+ end
+
+ context 'when `help_text` argument is not passed' do
+ it 'calls `label_tag` with `label` argument used in the block' do
+ component = component_class.new(
+ name: method_or_name,
+ label: 'Label argument'
+ )
+
+ expect(component).to receive(:label_tag).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_entry)
+ end
+
+ component.render_label_tag_with_help_text
+ end
+ end
+ end
end
diff --git a/spec/components/previews/pajamas/alert_component_preview.rb b/spec/components/previews/pajamas/alert_component_preview.rb
new file mode 100644
index 00000000000..9a6b77715f5
--- /dev/null
+++ b/spec/components/previews/pajamas/alert_component_preview.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+module Pajamas
+ class AlertComponentPreview < ViewComponent::Preview
+ # @param body text
+ # @param dismissible toggle
+ # @param variant select [info, warning, success, danger, tip]
+ def default(body: nil, dismissible: true, variant: :info)
+ render(Pajamas::AlertComponent.new(
+ title: "Title",
+ dismissible: dismissible,
+ variant: variant.to_sym
+ )) do |c|
+ if body
+ c.with_body { body }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/avatar_component_preview.rb b/spec/components/previews/pajamas/avatar_component_preview.rb
new file mode 100644
index 00000000000..e5cdde1ccef
--- /dev/null
+++ b/spec/components/previews/pajamas/avatar_component_preview.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+module Pajamas
+ class AvatarComponentPreview < ViewComponent::Preview
+ # Avatar
+ # ----
+ # See its design reference [here](https://design.gitlab.com/components/avatar).
+ def default
+ user
+ end
+
+ # We show user avatars in a circle.
+ # @param size select [16, 24, 32, 48, 64, 96]
+ def user(size: 64)
+ render(Pajamas::AvatarComponent.new(User.first, size: size))
+ end
+
+ # @param size select [16, 24, 32, 48, 64, 96]
+ def project(size: 64)
+ render(Pajamas::AvatarComponent.new(Project.first, size: size))
+ end
+
+ # @param size select [16, 24, 32, 48, 64, 96]
+ def group(size: 64)
+ render(Pajamas::AvatarComponent.new(Group.first, size: size))
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/banner_component_preview.rb b/spec/components/previews/pajamas/banner_component_preview.rb
new file mode 100644
index 00000000000..861e3ff95dc
--- /dev/null
+++ b/spec/components/previews/pajamas/banner_component_preview.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+module Pajamas
+ class BannerComponentPreview < ViewComponent::Preview
+ # Banner
+ # ----
+ # See its design reference [here](https://design.gitlab.com/components/banner).
+ #
+ # @param button_text text
+ # @param button_link text
+ # @param content textarea
+ # @param embedded toggle
+ # @param variant select [introduction, promotion]
+ def default(
+ button_text: "Learn more",
+ button_link: "https://about.gitlab.com/",
+ content: "Add your message here.",
+ embedded: false,
+ variant: :promotion
+ )
+ render(Pajamas::BannerComponent.new(
+ button_text: button_text,
+ button_link: button_link,
+ embedded: embedded,
+ svg_path: "illustrations/autodevops.svg",
+ variant: variant
+ )) do |c|
+ content_tag :p, content
+ end
+ end
+
+ # Use the `primary_action` slot instead of `button_text` and `button_link` if you need something more special,
+ # like rendering a partial that holds your button.
+ def with_primary_action_slot
+ render(Pajamas::BannerComponent.new) do |c|
+ c.primary_action do
+ # You could also `render` another partial here.
+ tag.button "I'm special", class: "btn btn-md btn-confirm gl-button"
+ end
+ content_tag :p, "This banner uses the primary_action slot."
+ end
+ end
+
+ # Use the `illustration` slot instead of `svg_path` if your illustration is not part or the asset pipeline,
+ # but for example, an inline SVG via `custom_icon`.
+ def with_illustration_slot
+ render(Pajamas::BannerComponent.new) do |c|
+ c.illustration do
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="white" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-thumbs-up"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path></svg>'.html_safe # rubocop:disable Layout/LineLength
+ end
+ content_tag :p, "This banner uses the illustration slot."
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/button_component_preview.rb b/spec/components/previews/pajamas/button_component_preview.rb
new file mode 100644
index 00000000000..1f61d9cf2bc
--- /dev/null
+++ b/spec/components/previews/pajamas/button_component_preview.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+module Pajamas
+ class ButtonComponentPreview < ViewComponent::Preview
+ # Button
+ # ----
+ # See its design reference [here](https://design.gitlab.com/components/banner).
+ #
+ # @param category select [primary, secondary, tertiary]
+ # @param variant select [default, confirm, danger, dashed, link, reset]
+ # @param size select [small, medium]
+ # @param type select [button, reset, submit]
+ # @param disabled toggle
+ # @param loading toggle
+ # @param block toggle
+ # @param selected toggle
+ # @param icon text
+ # @param text text
+ def default( # rubocop:disable Metrics/ParameterLists
+ category: :primary,
+ variant: :default,
+ size: :medium,
+ type: :button,
+ disabled: false,
+ loading: false,
+ block: false,
+ selected: false,
+ icon: "pencil",
+ text: "Edit"
+ )
+ render(Pajamas::ButtonComponent.new(
+ category: category,
+ variant: variant,
+ size: size,
+ type: type,
+ disabled: disabled,
+ loading: loading,
+ block: block,
+ selected: selected,
+ icon: icon
+ )) do
+ text.presence
+ end
+ end
+
+ # The component can also be used to create links that look and feel like buttons.
+ # Just provide a `href` and optionally a `target` to create an `<a>` tag.
+ def link
+ render(Pajamas::ButtonComponent.new(
+ href: "https://gitlab.com",
+ target: "_blank"
+ )) do
+ "This is a link"
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/card_component_preview.rb b/spec/components/previews/pajamas/card_component_preview.rb
new file mode 100644
index 00000000000..61d1f8db9e1
--- /dev/null
+++ b/spec/components/previews/pajamas/card_component_preview.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+module Pajamas
+ class CardComponentPreview < ViewComponent::Preview
+ # Card
+ # ----
+ # See its design reference [here](https://design.gitlab.com/components/card).
+ #
+ # @param header text
+ # @param body textarea
+ # @param footer text
+ def default(header: nil, body: "Every card has a body.", footer: nil)
+ render(Pajamas::CardComponent.new) do |c|
+ if header
+ c.with_header { header }
+ end
+
+ c.with_body do
+ content_tag(:p, body)
+ end
+
+ if footer
+ c.with_footer { footer }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/spinner_component_preview.rb b/spec/components/previews/pajamas/spinner_component_preview.rb
new file mode 100644
index 00000000000..149bfddcfc2
--- /dev/null
+++ b/spec/components/previews/pajamas/spinner_component_preview.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+module Pajamas
+ class SpinnerComponentPreview < ViewComponent::Preview
+ # Spinner
+ # ----
+ # See its design reference [here](https://design.gitlab.com/components/spinner).
+ #
+ # @param inline toggle
+ # @param label text
+ # @param size select [[small, sm], [medium, md], [large, lg], [extra large, xl]]
+ def default(inline: false, label: "Loading", size: :md)
+ render(Pajamas::SpinnerComponent.new(inline: inline, label: label, size: size))
+ end
+
+ # Use a light spinner on dark backgrounds
+ #
+ # @display bg_color "#222"
+ def light
+ render(Pajamas::SpinnerComponent.new(color: :light))
+ end
+ end
+end
diff --git a/spec/contracts/consumer/endpoints/project/merge_requests.js b/spec/contracts/consumer/endpoints/project/merge_requests.js
deleted file mode 100644
index 38773e5fb10..00000000000
--- a/spec/contracts/consumer/endpoints/project/merge_requests.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { request } from 'axios';
-
-export function getDiffsMetadata(endpoint) {
- const { url } = endpoint;
-
- return request({
- method: 'GET',
- baseURL: url,
- url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json',
- headers: { Accept: '*/*' },
- }).then((response) => response.data);
-}
-
-export function getDiscussions(endpoint) {
- const { url } = endpoint;
-
- return request({
- method: 'GET',
- baseURL: url,
- url: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
- headers: { Accept: '*/*' },
- }).then((response) => response.data);
-}
-
-export function getDiffsBatch(endpoint) {
- const { url } = endpoint;
-
- return request({
- method: 'GET',
- baseURL: url,
- url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json?page=0',
- headers: { Accept: '*/*' },
- }).then((response) => response.data);
-}
diff --git a/spec/contracts/consumer/endpoints/project/pipelines.js b/spec/contracts/consumer/endpoints/project/pipelines.js
deleted file mode 100644
index 33758dee75b..00000000000
--- a/spec/contracts/consumer/endpoints/project/pipelines.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import { request } from 'axios';
-
-export function getProjectPipelines(endpoint) {
- const { url } = endpoint;
-
- return request({
- method: 'GET',
- baseURL: url,
- url: '/gitlab-org/gitlab-qa/-/pipelines.json',
- headers: { Accept: '*/*' },
- params: {
- scope: 'all',
- page: 1,
- },
- }).then((response) => response.data);
-}
diff --git a/spec/contracts/consumer/fixtures/project/merge_request/diffs_batch.fixture.js b/spec/contracts/consumer/fixtures/project/merge_request/diffs_batch.fixture.js
index b53e4bb335d..673aad721b3 100644
--- a/spec/contracts/consumer/fixtures/project/merge_request/diffs_batch.fixture.js
+++ b/spec/contracts/consumer/fixtures/project/merge_request/diffs_batch.fixture.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { Matchers } from '@pact-foundation/pact';
const body = {
@@ -73,8 +71,12 @@ const DiffsBatch = {
body,
},
- request: {
+ scenario: {
+ state: 'a merge request with diffs exists',
uponReceiving: 'a request for diff lines',
+ },
+
+ request: {
withRequest: {
method: 'GET',
path: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json',
@@ -87,5 +89,3 @@ const DiffsBatch = {
};
export { DiffsBatch };
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/fixtures/project/merge_request/diffs_metadata.fixture.js b/spec/contracts/consumer/fixtures/project/merge_request/diffs_metadata.fixture.js
index 39dbcf78ee7..2fee4a02023 100644
--- a/spec/contracts/consumer/fixtures/project/merge_request/diffs_metadata.fixture.js
+++ b/spec/contracts/consumer/fixtures/project/merge_request/diffs_metadata.fixture.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { Matchers } from '@pact-foundation/pact';
const body = {
@@ -81,8 +79,12 @@ const DiffsMetadata = {
body,
},
+ scenario: {
+ state: 'a merge request exists',
+ uponReceiving: 'a request for diffs metadata',
+ },
+
request: {
- uponReceiving: 'a request for Diffs Metadata',
withRequest: {
method: 'GET',
path: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json',
@@ -94,5 +96,3 @@ const DiffsMetadata = {
};
export { DiffsMetadata };
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/fixtures/project/merge_request/discussions.fixture.js b/spec/contracts/consumer/fixtures/project/merge_request/discussions.fixture.js
index af0962a01cb..8c392395e1c 100644
--- a/spec/contracts/consumer/fixtures/project/merge_request/discussions.fixture.js
+++ b/spec/contracts/consumer/fixtures/project/merge_request/discussions.fixture.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { Matchers } from '@pact-foundation/pact';
const body = Matchers.eachLike({
@@ -70,8 +68,12 @@ const Discussions = {
body,
},
- request: {
+ scenario: {
+ state: 'a merge request with discussions exists',
uponReceiving: 'a request for discussions',
+ },
+
+ request: {
withRequest: {
method: 'GET',
path: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
@@ -83,5 +85,3 @@ const Discussions = {
};
export { Discussions };
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js
new file mode 100644
index 00000000000..68063d2fb0c
--- /dev/null
+++ b/spec/contracts/consumer/fixtures/project/pipeline/create_a_new_pipeline.fixture.js
@@ -0,0 +1,39 @@
+import { Matchers } from '@pact-foundation/pact';
+import { REDIRECT_HTML } from '../../../helpers/common_regex_patterns';
+
+const body = Matchers.term({
+ matcher: REDIRECT_HTML,
+ generate:
+ '<html><body>You are being <a href="http://example.org/gitlab-org/gitlab-qa/-/pipelines/5">redirected</a>.</body></html>',
+});
+
+const NewProjectPipeline = {
+ success: {
+ status: 302,
+ headers: {
+ 'Content-Type': 'text/html; charset=utf-8',
+ },
+ body,
+ },
+
+ scenario: {
+ state: 'a project with a valid .gitlab-ci.yml configuration exists',
+ uponReceiving: 'a request to create a new pipeline',
+ },
+
+ request: {
+ withRequest: {
+ method: 'POST',
+ path: '/gitlab-org/gitlab-qa/-/pipelines',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ body: {
+ ref: 'master',
+ },
+ },
+ },
+};
+
+export { NewProjectPipeline };
diff --git a/spec/contracts/consumer/fixtures/project/pipeline/delete_pipeline.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline/delete_pipeline.fixture.js
new file mode 100644
index 00000000000..2e3e7355b99
--- /dev/null
+++ b/spec/contracts/consumer/fixtures/project/pipeline/delete_pipeline.fixture.js
@@ -0,0 +1,24 @@
+const DeletePipeline = {
+ success: {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ },
+
+ scenario: {
+ state: 'a pipeline for a project exists',
+ uponReceiving: 'a request to delete the pipeline',
+ },
+
+ request: {
+ method: 'POST',
+ path: '/api/graphql',
+ },
+
+ variables: {
+ id: 'gid://gitlab/Ci::Pipeline/316112',
+ },
+};
+
+export { DeletePipeline };
diff --git a/spec/contracts/consumer/fixtures/project/pipeline/get_list_project_pipelines.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline/get_list_project_pipelines.fixture.js
index 8a7663325b9..a982e927572 100644
--- a/spec/contracts/consumer/fixtures/project/pipeline/get_list_project_pipelines.fixture.js
+++ b/spec/contracts/consumer/fixtures/project/pipeline/get_list_project_pipelines.fixture.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { Matchers } from '@pact-foundation/pact';
import {
URL,
@@ -225,8 +223,12 @@ const ProjectPipelines = {
body,
},
- request: {
+ scenario: {
+ state: 'a few pipelines for a project exists',
uponReceiving: 'a request for a list of project pipelines',
+ },
+
+ request: {
withRequest: {
method: 'GET',
path: '/gitlab-org/gitlab-qa/-/pipelines.json',
@@ -239,5 +241,3 @@ const ProjectPipelines = {
};
export { ProjectPipelines };
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/fixtures/project/pipeline/get_pipeline_header_data.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline/get_pipeline_header_data.fixture.js
index f51ed9c2c74..b14a230d2e0 100644
--- a/spec/contracts/consumer/fixtures/project/pipeline/get_pipeline_header_data.fixture.js
+++ b/spec/contracts/consumer/fixtures/project/pipeline/get_pipeline_header_data.fixture.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { Matchers } from '@pact-foundation/pact';
import {
JOB_STATUSES,
@@ -83,6 +81,11 @@ const PipelineHeaderData = {
body,
},
+ scenario: {
+ state: 'a pipeline for a project exists',
+ uponReceiving: 'a request for the pipeline header data',
+ },
+
request: {
method: 'POST',
path: '/api/graphql',
@@ -95,5 +98,3 @@ const PipelineHeaderData = {
};
export { PipelineHeaderData };
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js
new file mode 100644
index 00000000000..acfab14851a
--- /dev/null
+++ b/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js
@@ -0,0 +1,44 @@
+import { Matchers } from '@pact-foundation/pact';
+import { REDIRECT_HTML } from '../../../helpers/common_regex_patterns';
+
+const body = Matchers.term({
+ matcher: REDIRECT_HTML,
+ generate:
+ '<html><body>You are being <a href="http://example.org/gitlab-org/gitlab-qa/-/pipelines/5">redirected</a>.</body></html>',
+});
+
+const UpdatePipelineSchedule = {
+ success: {
+ status: 302,
+ headers: {
+ 'Content-Type': 'text/html; charset=utf-8',
+ },
+ body,
+ },
+
+ scenario: {
+ state: 'a project with a pipeline schedule exists',
+ uponReceiving: 'a request to edit a pipeline schedule',
+ },
+
+ request: {
+ withRequest: {
+ method: 'PUT',
+ path: '/gitlab-org/gitlab-qa/-/pipeline_schedules/25',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ body: {
+ schedule: {
+ description: 'bar',
+ cron: '0 1 * * *',
+ cron_timezone: 'UTC',
+ active: true,
+ },
+ },
+ },
+ },
+};
+
+export { UpdatePipelineSchedule };
diff --git a/spec/contracts/consumer/helpers/common_regex_patterns.js b/spec/contracts/consumer/helpers/common_regex_patterns.js
index 664a71ab8a9..78dfeb7748f 100644
--- a/spec/contracts/consumer/helpers/common_regex_patterns.js
+++ b/spec/contracts/consumer/helpers/common_regex_patterns.js
@@ -3,6 +3,7 @@
*/
export const URL = '^(http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$';
export const URL_PATH = '^/[a-zA-Z0-9#-=?_]+$';
+export const REDIRECT_HTML = 'You are being <a href=\\"(.)+\\">redirected</a>.';
// Pipelines
export const PIPELINE_GROUPS =
diff --git a/spec/contracts/consumer/resources/api/pipeline_schedules.js b/spec/contracts/consumer/resources/api/pipeline_schedules.js
new file mode 100644
index 00000000000..ad04e59b9cd
--- /dev/null
+++ b/spec/contracts/consumer/resources/api/pipeline_schedules.js
@@ -0,0 +1,26 @@
+import axios from 'axios';
+
+export async function updatePipelineSchedule(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'PUT',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/pipeline_schedules/25',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ data: {
+ schedule: {
+ description: 'bar',
+ cron: '0 1 * * *',
+ cron_timezone: 'UTC',
+ active: true,
+ },
+ },
+ validateStatus: (status) => {
+ return status === 302;
+ },
+ });
+}
diff --git a/spec/contracts/consumer/resources/api/project/merge_requests.js b/spec/contracts/consumer/resources/api/project/merge_requests.js
new file mode 100644
index 00000000000..e52743cede2
--- /dev/null
+++ b/spec/contracts/consumer/resources/api/project/merge_requests.js
@@ -0,0 +1,34 @@
+import axios from 'axios';
+
+export async function getDiffsMetadata(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'GET',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_metadata.json',
+ headers: { Accept: '*/*' },
+ }).then((response) => response.data);
+}
+
+export async function getDiscussions(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'GET',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/discussions.json',
+ headers: { Accept: '*/*' },
+ }).then((response) => response.data);
+}
+
+export async function getDiffsBatch(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'GET',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/merge_requests/1/diffs_batch.json?page=0',
+ headers: { Accept: '*/*' },
+ }).then((response) => response.data);
+}
diff --git a/spec/contracts/consumer/resources/api/project/pipelines.js b/spec/contracts/consumer/resources/api/project/pipelines.js
new file mode 100644
index 00000000000..8c6f5199666
--- /dev/null
+++ b/spec/contracts/consumer/resources/api/project/pipelines.js
@@ -0,0 +1,34 @@
+import axios from 'axios';
+
+export async function getProjectPipelines(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'GET',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/pipelines.json',
+ headers: { Accept: '*/*' },
+ params: {
+ scope: 'all',
+ page: 1,
+ },
+ }).then((response) => response.data);
+}
+
+export async function postProjectPipelines(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'POST',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/pipelines',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ data: { ref: 'master' },
+ validateStatus: (status) => {
+ return status === 302;
+ },
+ });
+}
diff --git a/spec/contracts/consumer/resources/graphql/pipelines.js b/spec/contracts/consumer/resources/graphql/pipelines.js
index 4f7ce58891c..48724e15eb8 100644
--- a/spec/contracts/consumer/resources/graphql/pipelines.js
+++ b/spec/contracts/consumer/resources/graphql/pipelines.js
@@ -16,6 +16,27 @@ export async function getPipelineHeaderDataRequest(endpoint) {
};
return axios({
+ method: 'POST',
+ baseURL: url,
+ url: '/api/graphql',
+ headers: { Accept: '*/*' },
+ data: graphqlQuery,
+ });
+}
+
+export async function deletePipeline(endpoint) {
+ const { url } = endpoint;
+ const query = await extractGraphQLQuery(
+ 'app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql',
+ );
+ const graphqlQuery = {
+ query,
+ variables: {
+ id: 'gid://gitlab/Ci::Pipeline/316112',
+ },
+ };
+
+ return axios({
baseURL: url,
url: '/api/graphql',
method: 'POST',
diff --git a/spec/contracts/consumer/specs/project/merge_request/show.spec.js b/spec/contracts/consumer/specs/project/merge_request/show.spec.js
index 8c6e029cb12..4183e19435a 100644
--- a/spec/contracts/consumer/specs/project/merge_request/show.spec.js
+++ b/spec/contracts/consumer/specs/project/merge_request/show.spec.js
@@ -1,5 +1,3 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { pactWith } from 'jest-pact';
import { DiffsBatch } from '../../../fixtures/project/merge_request/diffs_batch.fixture';
@@ -9,7 +7,7 @@ import {
getDiffsBatch,
getDiffsMetadata,
getDiscussions,
-} from '../../../endpoints/project/merge_requests';
+} from '../../../resources/api/project/merge_requests';
const CONSUMER_NAME = 'MergeRequest#show';
const CONSUMER_LOG = '../logs/consumer.log';
@@ -31,19 +29,19 @@ pactWith(
describe(DIFFS_BATCH_PROVIDER_NAME, () => {
beforeEach(() => {
const interaction = {
- state: 'a merge request with diffs exists',
+ ...DiffsBatch.scenario,
...DiffsBatch.request,
willRespondWith: DiffsBatch.success,
};
provider.addInteraction(interaction);
});
- it('returns a successful body', () => {
- return getDiffsBatch({
+ it('returns a successful body', async () => {
+ const diffsBatch = await getDiffsBatch({
url: provider.mockService.baseUrl,
- }).then((diffsBatch) => {
- expect(diffsBatch).toEqual(DiffsBatch.body);
});
+
+ expect(diffsBatch).toEqual(DiffsBatch.body);
});
});
},
@@ -61,19 +59,19 @@ pactWith(
describe(DISCUSSIONS_PROVIDER_NAME, () => {
beforeEach(() => {
const interaction = {
- state: 'a merge request with discussions exists',
+ ...Discussions.scenario,
...Discussions.request,
willRespondWith: Discussions.success,
};
provider.addInteraction(interaction);
});
- it('return a successful body', () => {
- return getDiscussions({
+ it('return a successful body', async () => {
+ const discussions = await getDiscussions({
url: provider.mockService.baseUrl,
- }).then((discussions) => {
- expect(discussions).toEqual(Discussions.body);
});
+
+ expect(discussions).toEqual(Discussions.body);
});
});
},
@@ -91,22 +89,20 @@ pactWith(
describe(DIFFS_METADATA_PROVIDER_NAME, () => {
beforeEach(() => {
const interaction = {
- state: 'a merge request exists',
+ ...DiffsMetadata.scenario,
...DiffsMetadata.request,
willRespondWith: DiffsMetadata.success,
};
provider.addInteraction(interaction);
});
- it('return a successful body', () => {
- return getDiffsMetadata({
+ it('return a successful body', async () => {
+ const diffsMetadata = await getDiffsMetadata({
url: provider.mockService.baseUrl,
- }).then((diffsMetadata) => {
- expect(diffsMetadata).toEqual(DiffsMetadata.body);
});
+
+ expect(diffsMetadata).toEqual(DiffsMetadata.body);
});
});
},
);
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/specs/project/pipeline/index.spec.js b/spec/contracts/consumer/specs/project/pipeline/index.spec.js
index 1c0358a3e28..1453435d637 100644
--- a/spec/contracts/consumer/specs/project/pipeline/index.spec.js
+++ b/spec/contracts/consumer/specs/project/pipeline/index.spec.js
@@ -1,9 +1,7 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { pactWith } from 'jest-pact';
import { ProjectPipelines } from '../../../fixtures/project/pipeline/get_list_project_pipelines.fixture';
-import { getProjectPipelines } from '../../../endpoints/project/pipelines';
+import { getProjectPipelines } from '../../../resources/api/project/pipelines';
const CONSUMER_NAME = 'Pipelines#index';
const CONSUMER_LOG = '../logs/consumer.log';
@@ -23,22 +21,20 @@ pactWith(
describe(PROVIDER_NAME, () => {
beforeEach(() => {
const interaction = {
- state: 'a few pipelines for a project exists',
+ ...ProjectPipelines.scenario,
...ProjectPipelines.request,
willRespondWith: ProjectPipelines.success,
};
provider.addInteraction(interaction);
});
- it('returns a successful body', () => {
- return getProjectPipelines({
+ it('returns a successful body', async () => {
+ const pipelines = await getProjectPipelines({
url: provider.mockService.baseUrl,
- }).then((pipelines) => {
- expect(pipelines).toEqual(ProjectPipelines.body);
});
+
+ expect(pipelines).toEqual(ProjectPipelines.body);
});
});
},
);
-
-/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/specs/project/pipeline/new.spec.js b/spec/contracts/consumer/specs/project/pipeline/new.spec.js
new file mode 100644
index 00000000000..c3824d5979e
--- /dev/null
+++ b/spec/contracts/consumer/specs/project/pipeline/new.spec.js
@@ -0,0 +1,41 @@
+import { pactWith } from 'jest-pact';
+
+import { NewProjectPipeline } from '../../../fixtures/project/pipeline/create_a_new_pipeline.fixture';
+import { postProjectPipelines } from '../../../resources/api/project/pipelines';
+
+const CONSUMER_NAME = 'Pipelines#new';
+const CONSUMER_LOG = '../logs/consumer.log';
+const CONTRACT_DIR = '../contracts/project/pipeline/new';
+const PROVIDER_NAME = 'POST Create a new pipeline';
+
+// API endpoint: /pipelines.json
+pactWith(
+ {
+ consumer: CONSUMER_NAME,
+ provider: PROVIDER_NAME,
+ log: CONSUMER_LOG,
+ dir: CONTRACT_DIR,
+ },
+
+ (provider) => {
+ describe(PROVIDER_NAME, () => {
+ beforeEach(async () => {
+ const interaction = {
+ ...NewProjectPipeline.scenario,
+ ...NewProjectPipeline.request,
+ willRespondWith: NewProjectPipeline.success,
+ };
+
+ provider.addInteraction(interaction);
+ });
+
+ it('returns a successful body', async () => {
+ const newPipeline = await postProjectPipelines({
+ url: provider.mockService.baseUrl,
+ });
+
+ expect(newPipeline.status).toEqual(NewProjectPipeline.success.status);
+ });
+ });
+ },
+);
diff --git a/spec/contracts/consumer/specs/project/pipeline/show.spec.js b/spec/contracts/consumer/specs/project/pipeline/show.spec.js
index 0f1cc1c3108..be6abb78eb5 100644
--- a/spec/contracts/consumer/specs/project/pipeline/show.spec.js
+++ b/spec/contracts/consumer/specs/project/pipeline/show.spec.js
@@ -1,36 +1,37 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
import { pactWith } from 'jest-pact';
import { GraphQLInteraction } from '@pact-foundation/pact';
import { extractGraphQLQuery } from '../../../helpers/graphql_query_extractor';
import { PipelineHeaderData } from '../../../fixtures/project/pipeline/get_pipeline_header_data.fixture';
-import { getPipelineHeaderDataRequest } from '../../../resources/graphql/pipelines';
+import { DeletePipeline } from '../../../fixtures/project/pipeline/delete_pipeline.fixture';
+
+import { getPipelineHeaderDataRequest, deletePipeline } from '../../../resources/graphql/pipelines';
const CONSUMER_NAME = 'Pipelines#show';
const CONSUMER_LOG = '../logs/consumer.log';
const CONTRACT_DIR = '../contracts/project/pipeline/show';
-const PROVIDER_NAME = 'GET pipeline header data';
+const GET_PIPELINE_HEADER_DATA_PROVIDER_NAME = 'GET pipeline header data';
+const DELETE_PIPELINE_PROVIDER_NAME = 'DELETE pipeline';
// GraphQL query: getPipelineHeaderData
pactWith(
{
consumer: CONSUMER_NAME,
- provider: PROVIDER_NAME,
+ provider: GET_PIPELINE_HEADER_DATA_PROVIDER_NAME,
log: CONSUMER_LOG,
dir: CONTRACT_DIR,
},
(provider) => {
- describe(PROVIDER_NAME, () => {
+ describe(GET_PIPELINE_HEADER_DATA_PROVIDER_NAME, () => {
beforeEach(async () => {
const query = await extractGraphQLQuery(
'app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql',
);
const graphqlQuery = new GraphQLInteraction()
- .given('a pipeline for a project exists')
- .uponReceiving('a request for the pipeline header data')
+ .given(PipelineHeaderData.scenario.state)
+ .uponReceiving(PipelineHeaderData.scenario.uponReceiving)
.withQuery(query)
.withRequest(PipelineHeaderData.request)
.withVariables(PipelineHeaderData.variables)
@@ -50,4 +51,39 @@ pactWith(
},
);
-/* eslint-enable @gitlab/require-i18n-strings */
+// GraphQL query: deletePipeline
+pactWith(
+ {
+ consumer: CONSUMER_NAME,
+ provider: DELETE_PIPELINE_PROVIDER_NAME,
+ log: CONSUMER_LOG,
+ dir: CONTRACT_DIR,
+ },
+
+ (provider) => {
+ describe(DELETE_PIPELINE_PROVIDER_NAME, () => {
+ beforeEach(async () => {
+ const query = await extractGraphQLQuery(
+ 'app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql',
+ );
+ const graphqlQuery = new GraphQLInteraction()
+ .given(DeletePipeline.scenario.state)
+ .uponReceiving(DeletePipeline.scenario.uponReceiving)
+ .withQuery(query)
+ .withRequest(DeletePipeline.request)
+ .withVariables(DeletePipeline.variables)
+ .willRespondWith(DeletePipeline.success);
+
+ provider.addInteraction(graphqlQuery);
+ });
+
+ it('returns a successful body', async () => {
+ const deletePipelineResponse = await deletePipeline({
+ url: provider.mockService.baseUrl,
+ });
+
+ expect(deletePipelineResponse.status).toEqual(DeletePipeline.success.status);
+ });
+ });
+ },
+);
diff --git a/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js b/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js
new file mode 100644
index 00000000000..117e6754255
--- /dev/null
+++ b/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js
@@ -0,0 +1,41 @@
+import { pactWith } from 'jest-pact';
+
+import { UpdatePipelineSchedule } from '../../../fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture';
+import { updatePipelineSchedule } from '../../../resources/api/pipeline_schedules';
+
+const CONSUMER_NAME = 'PipelineSchedules#edit';
+const CONSUMER_LOG = '../logs/consumer.log';
+const CONTRACT_DIR = '../contracts/project/pipeline_schedule/edit';
+const PROVIDER_NAME = 'PUT Edit a pipeline schedule';
+
+// API endpoint: /pipelines.json
+pactWith(
+ {
+ consumer: CONSUMER_NAME,
+ provider: PROVIDER_NAME,
+ log: CONSUMER_LOG,
+ dir: CONTRACT_DIR,
+ },
+
+ (provider) => {
+ describe(PROVIDER_NAME, () => {
+ beforeEach(() => {
+ const interaction = {
+ ...UpdatePipelineSchedule.scenario,
+ ...UpdatePipelineSchedule.request,
+ willRespondWith: UpdatePipelineSchedule.success,
+ };
+
+ provider.addInteraction(interaction);
+ });
+
+ it('returns a successful body', async () => {
+ const pipelineSchedule = await updatePipelineSchedule({
+ url: provider.mockService.baseUrl,
+ });
+
+ expect(pipelineSchedule.status).toEqual(UpdatePipelineSchedule.success.status);
+ });
+ });
+ },
+);
diff --git a/spec/contracts/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json b/spec/contracts/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json
index b98a0127e54..c59a3d55f43 100644
--- a/spec/contracts/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json
+++ b/spec/contracts/contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json
@@ -7,7 +7,7 @@
},
"interactions": [
{
- "description": "a request for Diffs Metadata",
+ "description": "a request for diffs metadata",
"providerState": "a merge request exists",
"request": {
"method": "GET",
@@ -220,4 +220,4 @@
"version": "2.0.0"
}
}
-} \ No newline at end of file
+}
diff --git a/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json b/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json
new file mode 100644
index 00000000000..4627f0cb0bf
--- /dev/null
+++ b/spec/contracts/contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json
@@ -0,0 +1,43 @@
+{
+ "consumer": {
+ "name": "Pipelines#new"
+ },
+ "provider": {
+ "name": "POST Create a new pipeline"
+ },
+ "interactions": [
+ {
+ "description": "a request to create a new pipeline",
+ "providerState": "a project with a valid .gitlab-ci.yml configuration exists",
+ "request": {
+ "method": "POST",
+ "path": "/gitlab-org/gitlab-qa/-/pipelines",
+ "headers": {
+ "Accept": "*/*",
+ "Content-Type": "application/json; charset=utf-8"
+ },
+ "body": {
+ "ref": "master"
+ }
+ },
+ "response": {
+ "status": 302,
+ "headers": {
+ "Content-Type": "text/html; charset=utf-8"
+ },
+ "body": "<html><body>You are being <a href=\"http://example.org/gitlab-org/gitlab-qa/-/pipelines/5\">redirected</a>.</body></html>",
+ "matchingRules": {
+ "$.body": {
+ "match": "regex",
+ "regex": "You are being <a href=\\\"(.)+\\/pipelines\\/[0-9]+\\\">redirected<\\/a>."
+ }
+ }
+ }
+ }
+ ],
+ "metadata": {
+ "pactSpecification": {
+ "version": "2.0.0"
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/contracts/contracts/project/pipeline/show/pipelines#show-delete_pipeline.json b/spec/contracts/contracts/project/pipeline/show/pipelines#show-delete_pipeline.json
new file mode 100644
index 00000000000..795c8a6e197
--- /dev/null
+++ b/spec/contracts/contracts/project/pipeline/show/pipelines#show-delete_pipeline.json
@@ -0,0 +1,44 @@
+{
+ "consumer": {
+ "name": "Pipelines#show"
+ },
+ "provider": {
+ "name": "DELETE pipeline"
+ },
+ "interactions": [
+ {
+ "description": "a request to delete the pipeline",
+ "providerState": "a pipeline for a project exists",
+ "request": {
+ "method": "POST",
+ "path": "/api/graphql",
+ "headers": {
+ "content-type": "application/json"
+ },
+ "body": {
+ "query": "mutation deletePipeline($id: CiPipelineID!) {\n pipelineDestroy(input: { id: $id }) {\n errors\n }\n}\n",
+ "variables": {
+ "id": "gid://gitlab/Ci::Pipeline/316112"
+ }
+ },
+ "matchingRules": {
+ "$.body.query": {
+ "match": "regex",
+ "regex": "mutation\\s*deletePipeline\\(\\$id:\\s*CiPipelineID!\\)\\s*\\{\\s*pipelineDestroy\\(input:\\s*\\{\\s*id:\\s*\\$id\\s*\\}\\)\\s*\\{\\s*errors\\s*\\}\\s*\\}\\s*"
+ }
+ }
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/json; charset=utf-8"
+ }
+ }
+ }
+ ],
+ "metadata": {
+ "pactSpecification": {
+ "version": "2.0.0"
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json b/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json
new file mode 100644
index 00000000000..e0dd68dc230
--- /dev/null
+++ b/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json
@@ -0,0 +1,48 @@
+{
+ "consumer": {
+ "name": "PipelineSchedules#edit"
+ },
+ "provider": {
+ "name": "PUT Edit a pipeline schedule"
+ },
+ "interactions": [
+ {
+ "description": "a request to edit a pipeline schedule",
+ "providerState": "a project with a pipeline schedule exists",
+ "request": {
+ "method": "PUT",
+ "path": "/gitlab-org/gitlab-qa/-/pipeline_schedules/25",
+ "headers": {
+ "Accept": "*/*",
+ "Content-Type": "application/json; charset=utf-8"
+ },
+ "body": {
+ "schedule": {
+ "description": "bar",
+ "cron": "0 1 * * *",
+ "cron_timezone": "UTC",
+ "active": true
+ }
+ }
+ },
+ "response": {
+ "status": 302,
+ "headers": {
+ "Content-Type": "text/html; charset=utf-8"
+ },
+ "body": "<html><body>You are being <a href=\"http://example.org/gitlab-org/gitlab-qa/-/pipelines/5\">redirected</a>.</body></html>",
+ "matchingRules": {
+ "$.body": {
+ "match": "regex",
+ "regex": "You are being <a href=\\\"(.)+\\\">redirected<\\/a>."
+ }
+ }
+ }
+ }
+ ],
+ "metadata": {
+ "pactSpecification": {
+ "version": "2.0.0"
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/diffs_batch_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/diffs_batch_helper.rb
deleted file mode 100644
index 7d1fbe91e86..00000000000
--- a/spec/contracts/provider/pact_helpers/project/merge_request/diffs_batch_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../spec_helper'
-require_relative '../../../states/project/merge_request/diffs_batch_state'
-
-module Provider
- module DiffsBatchHelper
- Pact.service_provider "Merge Request Diffs Batch Endpoint" do
- app { Environments::Test.app }
-
- honours_pact_with 'MergeRequest#show' do
- pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_batch_endpoint.json'
- end
- end
- end
-end
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/diffs_metadata_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/diffs_metadata_helper.rb
deleted file mode 100644
index 5f0c58d18d4..00000000000
--- a/spec/contracts/provider/pact_helpers/project/merge_request/diffs_metadata_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../spec_helper'
-require_relative '../../../states/project/merge_request/diffs_metadata_state'
-
-module Provider
- module DiffsMetadataHelper
- Pact.service_provider "Merge Request Diffs Metadata Endpoint" do
- app { Environments::Test.app }
-
- honours_pact_with 'MergeRequest#show' do
- pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json'
- end
- end
- end
-end
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/discussions_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/discussions_helper.rb
deleted file mode 100644
index 0f4244ba40a..00000000000
--- a/spec/contracts/provider/pact_helpers/project/merge_request/discussions_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../spec_helper'
-require_relative '../../../states/project/merge_request/discussions_state'
-
-module Provider
- module DiscussionsHelper
- Pact.service_provider "Merge Request Discussions Endpoint" do
- app { Environments::Test.app }
-
- honours_pact_with 'MergeRequest#show' do
- pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_discussions_endpoint.json'
- end
- end
- end
-end
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb
new file mode 100644
index 00000000000..f94ce47b1f3
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/merge_request/show_state'
+
+module Provider
+ module DiffsBatchHelper
+ Pact.service_provider "Merge Request Diffs Batch Endpoint" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'MergeRequest#show' do
+ pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_batch_endpoint.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb
new file mode 100644
index 00000000000..61567214b7a
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/merge_request/show_state'
+
+module Provider
+ module DiffsMetadataHelper
+ Pact.service_provider "Merge Request Diffs Metadata Endpoint" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'MergeRequest#show' do
+ pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb
new file mode 100644
index 00000000000..fa76ce8889a
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/merge_request/show_state'
+
+module Provider
+ module DiscussionsHelper
+ Pact.service_provider "Merge Request Discussions Endpoint" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'MergeRequest#show' do
+ pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_discussions_endpoint.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb
deleted file mode 100644
index 5307468b7c6..00000000000
--- a/spec/contracts/provider/pact_helpers/project/pipeline/get_list_project_pipelines_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../spec_helper'
-require_relative '../../../states/project/pipeline/pipelines_state'
-
-module Provider
- module GetListProjectPipelinesHelper
- Pact.service_provider "GET List project pipelines" do
- app { Environments::Test.app }
-
- honours_pact_with 'Pipelines#index' do
- pact_uri '../contracts/project/project/pipeline/index/pipelines#index-get_list_project_pipelines.json'
- end
- end
- end
-end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb
deleted file mode 100644
index abb2781f987..00000000000
--- a/spec/contracts/provider/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../../spec_helper'
-require_relative '../../../states/project/pipeline/pipeline_state'
-
-module Provider
- module GetPipelinesHeaderDataHelper
- Pact.service_provider "GET pipeline header data" do
- app { Environments::Test.app }
-
- honours_pact_with 'Pipelines#show' do
- pact_uri '../contracts/project/pipeline/show/pipelines#show-get_project_pipeline_header_data.json'
- end
- end
- end
-end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb
new file mode 100644
index 00000000000..247a7c4ca8e
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/pipeline/new_state'
+
+module Provider
+ module CreateNewPipelineHelper
+ Pact.service_provider "POST Create a new pipeline" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'Pipelines#new' do
+ pact_uri '../contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb
new file mode 100644
index 00000000000..80cbbe3b4dd
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/pipeline/index_state'
+
+module Provider
+ module GetListProjectPipelinesHelper
+ Pact.service_provider "GET List project pipelines" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'Pipelines#index' do
+ pact_uri '../contracts/project/project/pipeline/index/pipelines#index-get_list_project_pipelines.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb
new file mode 100644
index 00000000000..2d29fabfeca
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/pipeline/show_state'
+
+module Provider
+ module DeletePipelineHelper
+ Pact.service_provider "DELETE pipeline" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'Pipelines#show' do
+ pact_uri '../contracts/project/pipeline/show/pipelines#show-delete_pipeline.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb
new file mode 100644
index 00000000000..bc8c04cc455
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../../spec_helper'
+require_relative '../../../../states/project/pipeline/show_state'
+
+module Provider
+ module GetPipelinesHeaderDataHelper
+ Pact.service_provider "GET pipeline header data" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'Pipelines#show' do
+ pact_uri '../contracts/project/pipeline/show/pipelines#show-get_project_pipeline_header_data.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb
new file mode 100644
index 00000000000..a83aa9524dc
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../spec_helper'
+require_relative '../../../states/project/pipeline_schedule/edit_state'
+
+module Provider
+ module CreateNewPipelineHelper
+ Pact.service_provider "PUT Edit a pipeline schedule" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'PipelineSchedule#edit' do
+ pact_uri '../contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/project/merge_request/diffs_batch_state.rb b/spec/contracts/provider/states/project/merge_request/diffs_batch_state.rb
deleted file mode 100644
index ac20c17c187..00000000000
--- a/spec/contracts/provider/states/project/merge_request/diffs_batch_state.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-Pact.provider_states_for "MergeRequest#show" do
- provider_state "a merge request with diffs exists" do
- set_up do
- user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
- namespace = create(:namespace, name: 'gitlab-org')
- project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
-
- project.add_maintainer(user)
-
- merge_request = create(:merge_request_with_multiple_diffs, source_project: project)
- merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
-
- create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
- end
- end
-end
diff --git a/spec/contracts/provider/states/project/merge_request/diffs_metadata_state.rb b/spec/contracts/provider/states/project/merge_request/diffs_metadata_state.rb
deleted file mode 100644
index 8754232690c..00000000000
--- a/spec/contracts/provider/states/project/merge_request/diffs_metadata_state.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-Pact.provider_states_for "MergeRequest#show" do
- provider_state "a merge request exists" do
- set_up do
- user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
- namespace = create(:namespace, name: 'gitlab-org')
- project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
-
- project.add_maintainer(user)
-
- merge_request = create(:merge_request, source_project: project)
- merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
-
- create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
- end
- end
-end
diff --git a/spec/contracts/provider/states/project/merge_request/discussions_state.rb b/spec/contracts/provider/states/project/merge_request/discussions_state.rb
deleted file mode 100644
index 2d64f85eedf..00000000000
--- a/spec/contracts/provider/states/project/merge_request/discussions_state.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-Pact.provider_states_for "MergeRequest#show" do
- provider_state "a merge request with discussions exists" do
- set_up do
- user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
- namespace = create(:namespace, name: 'gitlab-org')
- project = create(:project, name: 'gitlab-qa', namespace: namespace)
-
- project.add_maintainer(user)
-
- merge_request = create(:merge_request_with_diffs, source_project: project, author: user)
-
- create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: user)
- end
- end
-end
diff --git a/spec/contracts/provider/states/project/merge_request/show_state.rb b/spec/contracts/provider/states/project/merge_request/show_state.rb
new file mode 100644
index 00000000000..46f322f723a
--- /dev/null
+++ b/spec/contracts/provider/states/project/merge_request/show_state.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "MergeRequest#show" do
+ provider_state "a merge request with diffs exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request_with_multiple_diffs, source_project: project)
+ merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
+
+ create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
+ end
+ end
+
+ provider_state "a merge request exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :custom_repo, name: 'gitlab-qa', namespace: namespace, files: {})
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request, source_project: project)
+ merge_request_diff = create(:merge_request_diff, merge_request: merge_request)
+
+ create(:merge_request_diff_file, :new_file, merge_request_diff: merge_request_diff)
+ end
+ end
+
+ provider_state "a merge request with discussions exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, name: 'gitlab-qa', namespace: namespace)
+
+ project.add_maintainer(user)
+
+ merge_request = create(:merge_request_with_diffs, source_project: project, author: user)
+
+ create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: user)
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/project/pipeline/pipelines_state.rb b/spec/contracts/provider/states/project/pipeline/index_state.rb
index 639c25e9894..639c25e9894 100644
--- a/spec/contracts/provider/states/project/pipeline/pipelines_state.rb
+++ b/spec/contracts/provider/states/project/pipeline/index_state.rb
diff --git a/spec/contracts/provider/states/project/pipeline/new_state.rb b/spec/contracts/provider/states/project/pipeline/new_state.rb
new file mode 100644
index 00000000000..95914180bec
--- /dev/null
+++ b/spec/contracts/provider/states/project/pipeline/new_state.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "Pipelines#new" do
+ provider_state "a project with a valid .gitlab-ci.yml configuration exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(
+ :project,
+ :custom_repo,
+ name: 'gitlab-qa',
+ namespace: namespace,
+ creator: user,
+ files: {
+ '.gitlab-ci.yml' => <<~YAML
+ test-success:
+ script: echo 'OK'
+ YAML
+ })
+
+ project.add_maintainer(user)
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/project/pipeline/pipeline_state.rb b/spec/contracts/provider/states/project/pipeline/pipeline_state.rb
deleted file mode 100644
index d1a4cd34bdd..00000000000
--- a/spec/contracts/provider/states/project/pipeline/pipeline_state.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-Pact.provider_states_for "Pipelines#show" do
- provider_state "a pipeline for a project exists" do
- set_up do
- user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
- namespace = create(:namespace, name: 'gitlab-org')
- project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
- scheduled_job = create(:ci_build, :scheduled)
- manual_job = create(:ci_build, :manual)
-
- project.add_maintainer(user)
-
- create(
- :ci_pipeline,
- :with_job,
- :success,
- iid: 1,
- project: project,
- user: user,
- duration: 10,
- finished_at: '2022-06-01T02:47:31.432Z',
- builds: [scheduled_job, manual_job]
- )
- end
- end
-end
diff --git a/spec/contracts/provider/states/project/pipeline/show_state.rb b/spec/contracts/provider/states/project/pipeline/show_state.rb
new file mode 100644
index 00000000000..3365647cd13
--- /dev/null
+++ b/spec/contracts/provider/states/project/pipeline/show_state.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "Pipelines#show" do
+ provider_state "a pipeline for a project exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
+ scheduled_job = create(:ci_build, :scheduled)
+ manual_job = create(:ci_build, :manual)
+
+ project.add_maintainer(user)
+
+ create(
+ :ci_pipeline,
+ :with_job,
+ :success,
+ id: 316112,
+ iid: 1,
+ project: project,
+ user: user,
+ duration: 10,
+ finished_at: '2022-06-01T02:47:31.432Z',
+ builds: [scheduled_job, manual_job]
+ )
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb b/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb
new file mode 100644
index 00000000000..4ee714f15f3
--- /dev/null
+++ b/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "PipelineSchedules#edit" do
+ provider_state "a project with a pipeline schedule exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
+
+ project.add_maintainer(user)
+
+ create(:ci_pipeline_schedule, id: 25, project: project, owner: user)
+ end
+ end
+end
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
index 49e6c0f69bd..5d7a7e089aa 100644
--- a/spec/controllers/admin/dev_ops_report_controller_spec.rb
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -28,6 +28,17 @@ RSpec.describe Admin::DevOpsReportController do
let(:request_params) { { tab: 'devops-score' } }
end
+
+ it_behaves_like 'Snowplow event tracking' do
+ subject { get :show, format: :html }
+
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:category) { described_class.name }
+ let(:action) { 'perform_analytics_usage_action' }
+ let(:label) { 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly' }
+ let(:property) { 'i_analytics_dev_ops_score' }
+ let(:namespace) { nil }
+ end
end
end
diff --git a/spec/controllers/admin/identities_controller_spec.rb b/spec/controllers/admin/identities_controller_spec.rb
index 6ac5ce13884..e32191e04e7 100644
--- a/spec/controllers/admin/identities_controller_spec.rb
+++ b/spec/controllers/admin/identities_controller_spec.rb
@@ -9,6 +9,30 @@ RSpec.describe Admin::IdentitiesController do
sign_in(admin)
end
+ describe 'GET #index' do
+ context 'when the user has no identities' do
+ it 'shows no identities' do
+ get :index, params: { user_id: admin.username }
+
+ expect(assigns(:user)).to eq(admin)
+ expect(assigns(:identities)).to be_blank
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when the user has identities' do
+ let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain', extern_uid: 'ldap-uid') }
+
+ it 'shows identities' do
+ get :index, params: { user_id: ldap_user.username }
+
+ expect(assigns(:user)).to eq(ldap_user)
+ expect(assigns(:identities)).to eq(ldap_user.identities)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
describe 'UPDATE identity' do
let(:user) { create(:omniauth_user, provider: 'ldapmain', extern_uid: 'uid=myuser,ou=people,dc=example,dc=com') }
diff --git a/spec/controllers/admin/topics_controller_spec.rb b/spec/controllers/admin/topics_controller_spec.rb
index ee36d5f1def..87093e0263b 100644
--- a/spec/controllers/admin/topics_controller_spec.rb
+++ b/spec/controllers/admin/topics_controller_spec.rb
@@ -173,4 +173,44 @@ RSpec.describe Admin::TopicsController do
end
end
end
+
+ describe 'POST #merge' do
+ let_it_be(:source_topic) { create(:topic, name: 'source_topic') }
+ let_it_be(:project) { create(:project, topic_list: source_topic.name ) }
+
+ it 'merges source topic into target topic' do
+ post :merge, params: { source_topic_id: source_topic.id, target_topic_id: topic.id }
+
+ expect(response).to redirect_to(admin_topics_path)
+ expect(topic.projects).to contain_exactly(project)
+ expect { source_topic.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'renders a 404 error for non-existing id' do
+ post :merge, params: { source_topic_id: non_existing_record_id, target_topic_id: topic.id }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect { topic.reload }.not_to raise_error
+ end
+
+ it 'renders a 400 error for identical topic ids' do
+ post :merge, params: { source_topic_id: topic, target_topic_id: topic.id }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect { topic.reload }.not_to raise_error
+ end
+
+ context 'as a normal user' do
+ before do
+ sign_in(user)
+ end
+
+ it 'renders a 404 error' do
+ post :merge, params: { source_topic_id: source_topic.id, target_topic_id: topic.id }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect { source_topic.reload }.not_to raise_error
+ end
+ end
+ end
end
diff --git a/spec/controllers/admin/usage_trends_controller_spec.rb b/spec/controllers/admin/usage_trends_controller_spec.rb
index 35fb005aacb..356f603bf57 100644
--- a/spec/controllers/admin/usage_trends_controller_spec.rb
+++ b/spec/controllers/admin/usage_trends_controller_spec.rb
@@ -13,5 +13,18 @@ RSpec.describe Admin::UsageTrendsController do
it_behaves_like 'tracking unique visits', :index do
let(:target_id) { 'i_analytics_instance_statistics' }
end
+
+ it_behaves_like 'Snowplow event tracking' do
+ subject { get :index }
+
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:category) { described_class.name }
+ let(:action) { 'perform_analytics_usage_action' }
+ let(:label) { 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly' }
+ let(:property) { 'i_analytics_instance_statistics' }
+ let(:namespace) { nil }
+ let(:project) { nil }
+ let(:user) { admin }
+ end
end
end
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index c46a12680a2..515ad9daf36 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe Admin::UsersController do
it 'displays the rejection message' do
subject
- expect(response).to redirect_to(admin_users_path)
+ expect(response).to redirect_to(admin_user_path(user))
expect(flash[:notice]).to eq("You've rejected #{user.name}")
end
@@ -612,8 +612,8 @@ RSpec.describe Admin::UsersController do
end
context 'when the new password does not match the password confirmation' do
- let(:password) { 'some_password' }
- let(:password_confirmation) { 'not_same_as_password' }
+ let(:password) { User.random_password }
+ let(:password_confirmation) { User.random_password }
it 'shows the edit page again' do
update_password(user, password, password_confirmation)
diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb
index 8fcc3a7fccf..645360289d1 100644
--- a/spec/controllers/groups/uploads_controller_spec.rb
+++ b/spec/controllers/groups/uploads_controller_spec.rb
@@ -67,30 +67,10 @@ RSpec.describe Groups::UploadsController do
end
context "when not signed in" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
+ it "responds with appropriate status" do
+ show_upload
- it "responds with appropriate status" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -100,30 +80,10 @@ RSpec.describe Groups::UploadsController do
end
context "when the user doesn't have access to the model" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
+ it "responds with status 200" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
end
@@ -135,30 +95,10 @@ RSpec.describe Groups::UploadsController do
end
context "when not signed in" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
+ it "responds with appropriate status" do
+ show_upload
- it "responds with appropriate status" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -168,30 +108,10 @@ RSpec.describe Groups::UploadsController do
end
context "when the user doesn't have access to the model" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
+ it "responds with status 200" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
end
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index 7177c8c10a6..3be12717664 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -245,11 +245,11 @@ RSpec.describe Import::BulkImportsController do
let(:bulk_import_params) do
[{ "source_type" => "group_entity",
"source_full_path" => "full_path",
- "destination_name" => "destination_name",
+ "destination_slug" => "destination_name",
"destination_namespace" => "root" },
{ "source_type" => "group_entity2",
"source_full_path" => "full_path2",
- "destination_name" => "destination_name2",
+ "destination_slug" => "destination_name2",
"destination_namespace" => "root" }]
end
@@ -258,7 +258,7 @@ RSpec.describe Import::BulkImportsController do
session[:bulk_import_gitlab_url] = instance_url
end
- it 'executes BulkImpors::CreateService' do
+ it 'executes BulkImports::CreateService' do
error_response = ServiceResponse.error(message: 'Record invalid', http_status: :unprocessable_entity)
expect_next_instance_of(
@@ -276,6 +276,38 @@ RSpec.describe Import::BulkImportsController do
expect(json_response).to eq([{ "success" => true, "id" => bulk_import.id, "message" => nil },
{ "success" => false, "id" => nil, "message" => "Record invalid" }])
end
+
+ context 'when entity destination_name is specified' do
+ let(:bulk_import_params) do
+ [
+ {
+ "source_type" => "group_entity",
+ "source_full_path" => "full_path",
+ "destination_name" => "destination_name",
+ "destination_namespace" => "root"
+ }
+ ]
+ end
+
+ it 'replaces destination_name with destination_slug and executes BulkImports::CreateService' do
+ entity = {
+ "source_type" => "group_entity",
+ "source_full_path" => "full_path",
+ "destination_slug" => "destination_name",
+ "destination_namespace" => "root"
+ }
+
+ expect_next_instance_of(
+ ::BulkImports::CreateService, user, entity, { url: instance_url, access_token: pat }) do |service|
+ allow(service).to receive(:execute).and_return(ServiceResponse.success(payload: bulk_import))
+ end
+
+ post :create, params: { bulk_import: bulk_import_params }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to match_array([{ "success" => true, "id" => bulk_import.id, "message" => nil }])
+ 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 aafea0050d3..0e531dbaf4b 100644
--- a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
+++ b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
@@ -87,6 +87,38 @@ RSpec.describe Profiles::PersonalAccessTokensController do
end
end
+ context "tokens returned are ordered" do
+ let(:expires_1_day_from_now) { 1.day.from_now.to_date }
+ let(:expires_2_day_from_now) { 2.days.from_now.to_date }
+
+ before do
+ create(:personal_access_token, user: user, name: "Token1", expires_at: expires_1_day_from_now)
+ create(:personal_access_token, user: user, name: "Token2", expires_at: expires_2_day_from_now)
+ end
+
+ it "orders token list ascending on expires_at" do
+ get :index
+
+ first_token = assigns(:active_personal_access_tokens).first.as_json
+ expect(first_token[:name]).to eq("Token1")
+ expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
+ end
+
+ it "orders tokens on id in case token has same expires_at" do
+ create(:personal_access_token, user: user, name: "Token3", expires_at: expires_1_day_from_now)
+
+ get :index
+
+ first_token = assigns(:active_personal_access_tokens).first.as_json
+ expect(first_token[:name]).to eq("Token3")
+ expect(first_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
+
+ second_token = assigns(:active_personal_access_tokens).second.as_json
+ expect(second_token[:name]).to eq("Token1")
+ expect(second_token[:expires_at]).to eq(expires_1_day_from_now.strftime("%Y-%m-%d"))
+ end
+ end
+
context "access_token_pagination feature flag is disabled" do
before do
stub_feature_flags(access_token_pagination: false)
diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb
index 6e7cc058fbc..89185a8f856 100644
--- a/spec/controllers/profiles_controller_spec.rb
+++ b/spec/controllers/profiles_controller_spec.rb
@@ -3,16 +3,16 @@
require('spec_helper')
RSpec.describe ProfilesController, :request_store do
- let(:password) { 'longsecret987!' }
+ let(:password) { User.random_password }
let(:user) { create(:user, password: password) }
describe 'POST update' do
it 'does not update password' do
sign_in(user)
-
+ new_password = User.random_password
expect do
post :update,
- params: { user: { password: 'hello12345', password_confirmation: 'hello12345' } }
+ params: { user: { password: new_password, password_confirmation: new_password } }
end.not_to change { user.reload.encrypted_password }
expect(response).to have_gitlab_http_status(:found)
diff --git a/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb b/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
index 3f0318c3973..8903592ba15 100644
--- a/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
+++ b/spec/controllers/projects/analytics/cycle_analytics/stages_controller_spec.rb
@@ -54,6 +54,32 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
end
+ shared_examples 'project-level value stream analytics with guest user' do
+ let_it_be(:guest) { create(:user) }
+
+ before do
+ project.add_guest(guest)
+ sign_out(user)
+ sign_in(guest)
+ end
+
+ %w[code review].each do |id|
+ it "disallows stage #{id}" do
+ get action, params: params.merge(id: id)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ %w[issue plan test staging].each do |id|
+ it "allows stage #{id}" do
+ get action, params: params.merge(id: id)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
describe 'GET index' do
let(:action) { :index }
@@ -78,6 +104,20 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
it_behaves_like 'project-level value stream analytics request error examples'
+
+ it 'only returns authorized stages' do
+ guest = create(:user)
+ sign_out(user)
+ sign_in(guest)
+ project.add_guest(guest)
+
+ get action, params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ expect(json_response['stages'].map { |stage| stage['title'] })
+ .to contain_exactly('Issue', 'Plan', 'Test', 'Staging')
+ end
end
describe 'GET median' do
@@ -102,6 +142,8 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
it_behaves_like 'project-level value stream analytics request error examples'
+
+ it_behaves_like 'project-level value stream analytics with guest user'
end
describe 'GET average' do
@@ -126,6 +168,8 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
it_behaves_like 'project-level value stream analytics request error examples'
+
+ it_behaves_like 'project-level value stream analytics with guest user'
end
describe 'GET count' do
@@ -150,6 +194,8 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
it_behaves_like 'project-level value stream analytics request error examples'
+
+ it_behaves_like 'project-level value stream analytics with guest user'
end
describe 'GET records' do
@@ -174,5 +220,7 @@ RSpec.describe Projects::Analytics::CycleAnalytics::StagesController do
end
it_behaves_like 'project-level value stream analytics request error examples'
+
+ it_behaves_like 'project-level value stream analytics with guest user'
end
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index cc807098498..887a5ba598f 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -352,7 +352,6 @@ RSpec.describe Projects::BlobController do
project_new_merge_request_path(
forked_project,
merge_request: {
- source_project_id: forked_project.id,
target_project_id: project.id,
source_branch: "fork-test-1",
target_branch: "master"
diff --git a/spec/controllers/projects/ci/secure_files_controller_spec.rb b/spec/controllers/projects/ci/secure_files_controller_spec.rb
deleted file mode 100644
index 200997e31b9..00000000000
--- a/spec/controllers/projects/ci/secure_files_controller_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::Ci::SecureFilesController do
- let_it_be(:project) { create(:project) }
- let_it_be(:user) { create(:user) }
-
- subject(:show_request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
-
- describe 'GET #show' do
- context 'when the :ci_secure_files feature flag is enabled' do
- context 'with enough privileges' do
- before do
- stub_feature_flags(ci_secure_files: true)
- sign_in(user)
- project.add_developer(user)
- show_request
- end
-
- it { expect(response).to have_gitlab_http_status(:ok) }
-
- it 'renders show page' do
- expect(response).to render_template :show
- end
- end
- end
-
- context 'when the :ci_secure_files feature flag is disabled' do
- context 'with enough privileges' do
- before do
- stub_feature_flags(ci_secure_files: false)
- sign_in(user)
- project.add_developer(user)
- show_request
- end
-
- it 'responds with 404' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'without enough privileges' do
- before do
- sign_in(user)
- project.add_reporter(user)
- show_request
- end
-
- it 'responds with 404' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'an unauthenticated user' do
- before do
- show_request
- end
-
- it 'redirects to sign in' do
- expect(response).to have_gitlab_http_status(:found)
- expect(response).to redirect_to('/users/sign_in')
- end
- end
- end
-end
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index d45ea268e64..12202518e1e 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -259,9 +259,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
@@ -300,9 +302,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
@@ -349,9 +353,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
@@ -401,9 +407,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_allowed_for(:developer).of(project) }
@@ -515,9 +523,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
@@ -593,9 +603,11 @@ RSpec.describe Projects::ClustersController do
it 'is allowed for admin when admin mode enabled', :enable_admin_mode do
expect { go }.to be_allowed_for(:admin)
end
+
it 'is disabled for admin when admin mode disabled' do
expect { go }.to be_denied_for(:admin)
end
+
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
it { expect { go }.to be_denied_for(:developer).of(project) }
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index a72c98552a5..edb07bbdce6 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -82,6 +82,22 @@ RSpec.describe Projects::CommitController do
expect(response).to be_successful
end
+ it 'only loads blobs in the current page' do
+ stub_feature_flags(async_commit_diff_files: false)
+ stub_const('Projects::CommitController::COMMIT_DIFFS_PER_PAGE', 1)
+
+ commit = project.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863')
+
+ expect_next_instance_of(Repository) do |repository|
+ # This commit contains 3 changed files but we expect only the blobs for the first one to be loaded
+ expect(repository).to receive(:blobs_at).with([[commit.id, '.gitignore']], anything).and_call_original
+ end
+
+ go(id: commit.id)
+
+ expect(response).to be_ok
+ end
+
shared_examples "export as" do |format|
it "does generally work" do
go(id: commit.id, format: format)
@@ -378,7 +394,6 @@ RSpec.describe Projects::CommitController do
project_new_merge_request_path(
source_project,
merge_request: {
- source_project_id: source_project.id,
target_project_id: project.id,
source_branch: branch,
target_branch: 'feature'
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index e6e0307d0ca..6ed6f7017e3 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -226,8 +226,8 @@ RSpec.describe Projects::CompareController do
context 'when page is valid' do
let(:from_project_id) { nil }
- let(:from_ref) { '08f22f25' }
- let(:to_ref) { '66eceea0' }
+ let(:from_ref) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+ let(:to_ref) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
let(:page) { 1 }
it 'shows the diff' do
@@ -237,6 +237,21 @@ RSpec.describe Projects::CompareController do
expect(assigns(:diffs).diff_files.first).to be_present
expect(assigns(:commits).length).to be >= 1
end
+
+ it 'only loads blobs in the current page' do
+ stub_const('Projects::CompareController::COMMIT_DIFFS_PER_PAGE', 1)
+
+ expect_next_instance_of(Repository) do |repository|
+ # This comparison contains 4 changed files but we expect only the blobs for the first one to be loaded
+ expect(repository).to receive(:blobs_at).with(
+ contain_exactly([from_ref, '.gitmodules'], [to_ref, '.gitmodules']), anything
+ ).and_call_original
+ end
+
+ show_request
+
+ expect(response).to be_successful
+ end
end
context 'when page is not valid' do
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index f4cad5790a3..1a6edab795d 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -233,7 +233,7 @@ RSpec.describe Projects::EnvironmentsController do
end
context "when environment params are invalid" do
- let(:params) { environment_params.merge(environment: { name: '/foo/', external_url: '/git.gitlab.com' }) }
+ let(:params) { environment_params.merge(environment: { external_url: 'javascript:alert("hello")' }) }
it 'returns bad request' do
subject
diff --git a/spec/controllers/projects/hooks_controller_spec.rb b/spec/controllers/projects/hooks_controller_spec.rb
index a275bc28631..ba7b712964c 100644
--- a/spec/controllers/projects/hooks_controller_spec.rb
+++ b/spec/controllers/projects/hooks_controller_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Projects::HooksController do
def it_renders_correctly
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:edit)
- expect(response).to render_template('projects/hook_logs/_index')
+ expect(response).to render_template('shared/hook_logs/_index')
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index badac688229..c48be8efb1b 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -1607,22 +1607,32 @@ RSpec.describe Projects::IssuesController do
project.add_developer(user)
end
- it "returns 302 for project members with developer role" do
- import_csv
+ context 'when upload proceeds correctly' do
+ it "returns 302 for project members with developer role" do
+ import_csv
- expect(flash[:notice]).to eq(_("Your issues are being imported. Once finished, you'll get a confirmation email."))
- expect(response).to redirect_to(project_issues_path(project))
- end
+ expect(flash[:notice]).to eq(_("Your issues are being imported. Once finished, you'll get a confirmation email."))
+ expect(response).to redirect_to(project_issues_path(project))
+ end
+
+ it 'enqueues an import job' do
+ expect(ImportIssuesCsvWorker).to receive(:perform_async).with(user.id, project.id, Integer)
- it "shows error when upload fails" do
- expect_next_instance_of(UploadService) do |upload_service|
- expect(upload_service).to receive(:execute).and_return(nil)
+ import_csv
end
+ end
- import_csv
+ context 'when upload fails' do
+ it "shows error when upload fails" do
+ expect_next_instance_of(UploadService) do |upload_service|
+ expect(upload_service).to receive(:execute).and_return(nil)
+ end
- expect(flash[:alert]).to include(_('File upload error.'))
- expect(response).to redirect_to(project_issues_path(project))
+ import_csv
+
+ expect(flash[:alert]).to include(_('File upload error.'))
+ expect(response).to redirect_to(project_issues_path(project))
+ end
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 8ccbc0d3fe2..ed5e32df8ea 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1894,15 +1894,12 @@ RSpec.describe Projects::MergeRequestsController do
# First run to insert test data from lets, which does take up some 30 queries
get_ci_environments_status
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { get_ci_environments_status }.count
+ control_count = ActiveRecord::QueryRecorder.new { get_ci_environments_status }
environment2 = create(:environment, project: forked)
create(:deployment, :succeed, environment: environment2, sha: sha, ref: 'master', deployable: build)
- # TODO address the last 3 queries
- # See https://gitlab.com/gitlab-org/gitlab-foss/issues/63952 (3 queries)
- leeway = 3
- expect { get_ci_environments_status }.not_to exceed_all_query_limit(control_count + leeway)
+ expect { get_ci_environments_status }.not_to exceed_all_query_limit(control_count)
end
end
@@ -2039,25 +2036,50 @@ RSpec.describe Projects::MergeRequestsController do
end
describe 'POST #rebase' do
+ let(:other_params) { {} }
+ let(:params) { { namespace_id: project.namespace, project_id: project, id: merge_request }.merge(other_params) }
+
def post_rebase
- post :rebase, params: { namespace_id: project.namespace, project_id: project, id: merge_request }
+ post :rebase, params: params
end
before do
allow(RebaseWorker).to receive(:with_status).and_return(RebaseWorker)
end
- def expect_rebase_worker_for(user)
- expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, false)
+ def expect_rebase_worker_for(user, skip_ci: false)
+ expect(RebaseWorker).to receive(:perform_async).with(merge_request.id, user.id, skip_ci)
end
context 'successfully' do
- it 'enqeues a RebaseWorker' do
- expect_rebase_worker_for(user)
+ shared_examples 'successful rebase scheduler' do
+ it 'enqueues a RebaseWorker' do
+ expect_rebase_worker_for(user, skip_ci: skip_ci)
- post_rebase
+ post_rebase
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with skip_ci not specified' do
+ let(:skip_ci) { false }
+
+ it_behaves_like 'successful rebase scheduler'
+ end
+
+ context 'with skip_ci enabled' do
+ let(:skip_ci) { true }
+ let(:other_params) { { skip_ci: 'true' } }
+
+ it_behaves_like 'successful rebase scheduler'
+ end
+
+ context 'with skip_ci disabled' do
+ let(:skip_ci) { false }
+ let(:other_params) { { skip_ci: 'false' } }
+
+ it_behaves_like 'successful rebase scheduler'
end
end
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 85e5de46afd..9050765afd6 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -345,34 +345,77 @@ RSpec.describe Projects::NotesController do
}
end
- context 'when `confidential` parameter is not provided' do
- it 'sets `confidential` to `false` in JSON response' do
+ context 'when parameter is not provided' do
+ it 'sets `confidential` and `internal` to `false` in JSON response' do
create!
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['confidential']).to be false
+ expect(json_response['internal']).to be false
end
end
- context 'when `confidential` parameter is `false`' do
- let(:extra_note_params) { { confidential: false } }
+ context 'when is not a confidential note' do
+ context 'when using the `internal` parameter' do
+ let(:extra_note_params) { { internal: false } }
- it 'sets `confidential` to `false` in JSON response' do
- create!
+ it 'sets `confidential` and `internal` to `false` in JSON response' do
+ create!
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['confidential']).to be false
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be false
+ expect(json_response['internal']).to be false
+ end
+ end
+
+ context 'when using deprecated `confidential` parameter' do
+ let(:extra_note_params) { { confidential: false } }
+
+ it 'sets `confidential` and `internal` to `false` in JSON response' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be false
+ expect(json_response['internal']).to be false
+ end
end
end
- context 'when `confidential` parameter is `true`' do
- let(:extra_note_params) { { confidential: true } }
+ context 'when is a confidential note' do
+ context 'when using the `internal` parameter' do
+ let(:extra_note_params) { { internal: true } }
- it 'sets `confidential` to `true` in JSON response' do
- create!
+ it 'sets `confidential` and `internal` to `true` in JSON response' do
+ create!
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['confidential']).to be true
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be true
+ expect(json_response['internal']).to be true
+ end
+ end
+
+ context 'when using deprecated `confidential` parameter' do
+ let(:extra_note_params) { { confidential: true } }
+
+ it 'sets `confidential` and `internal` to `true` in JSON response' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be true
+ expect(json_response['internal']).to be true
+ end
+ end
+
+ context 'when `internal` parameter is `true` and `confidential` parameter is `false`' do
+ let(:extra_note_params) { { internal: true, confidential: false } }
+
+ it 'uses the `internal` param as source of truth' do
+ create!
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['confidential']).to be true
+ expect(json_response['internal']).to be true
+ end
end
end
end
diff --git a/spec/controllers/projects/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb
index 1fa8838b548..136f98ac907 100644
--- a/spec/controllers/projects/pages_controller_spec.rb
+++ b/spec/controllers/projects/pages_controller_spec.rb
@@ -19,9 +19,9 @@ RSpec.describe Projects::PagesController do
project.add_maintainer(user)
end
- describe 'GET show' do
+ describe 'GET new' do
it 'returns 200 status' do
- get :show, params: request_params
+ get :new, params: request_params
expect(response).to have_gitlab_http_status(:ok)
end
@@ -31,13 +31,55 @@ RSpec.describe Projects::PagesController do
let(:project) { create(:project, namespace: group) }
it 'returns a 200 status code' do
- get :show, params: request_params
+ get :new, params: request_params
expect(response).to have_gitlab_http_status(:ok)
end
end
end
+ describe 'GET show' do
+ subject { get :show, params: request_params }
+
+ context 'when the project does not have onboarding complete' do
+ before do
+ project.pages_metadatum.update_attribute(:deployed, false)
+ project.pages_metadatum.update_attribute(:onboarding_complete, false)
+ end
+
+ it 'redirects to #new' do
+ expect(subject).to redirect_to(action: 'new')
+ end
+ end
+
+ context 'when the project does have onboarding complete' do
+ before do
+ project.pages_metadatum.update_attribute(:onboarding_complete, true)
+ end
+
+ it 'returns 200 status' do
+ expect(subject).to have_gitlab_http_status(:ok)
+ end
+
+ context 'when the project is in a subgroup' do
+ let(:group) { create(:group, :nested) }
+ let(:project) { create(:project, namespace: group) }
+
+ it 'returns a 200 status code' do
+ expect(subject).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'when pages is disabled' do
+ let(:project) { create(:project, :pages_disabled) }
+
+ it 'renders the disabled view' do
+ expect(subject).to render_template :disabled
+ end
+ end
+ end
+
describe 'DELETE destroy' do
it 'returns 302 status' do
delete :destroy, params: request_params
diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb
index dcfccc00347..4996bd90005 100644
--- a/spec/controllers/projects/protected_branches_controller_spec.rb
+++ b/spec/controllers/projects/protected_branches_controller_spec.rb
@@ -3,14 +3,20 @@
require('spec_helper')
RSpec.describe Projects::ProtectedBranchesController do
- let(:project) { create(:project, :repository) }
+ let_it_be_with_reload(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+
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) { create(:user) }
+ let(:user) { maintainer }
+
+ before_all do
+ project.add_maintainer(maintainer)
+ end
before do
- project.add_maintainer(user)
+ sign_in(user)
end
describe "GET #index" do
@@ -30,23 +36,16 @@ RSpec.describe Projects::ProtectedBranchesController do
let(:create_params) { attributes_for(:protected_branch).merge(access_level_params) }
- before do
- sign_in(user)
- end
-
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)
end
- context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- allow(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- 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))
+
post(:create, params: project_params.merge(protected_branch: create_params))
expect(ProtectedBranch.count).to eq 0
@@ -57,10 +56,6 @@ RSpec.describe Projects::ProtectedBranchesController do
describe "PUT #update" do
let(:update_params) { { name: 'new_name' } }
- before do
- sign_in(user)
- end
-
it 'updates the protected branch rule' do
put(:update, params: base_params.merge(protected_branch: update_params))
@@ -68,13 +63,10 @@ RSpec.describe Projects::ProtectedBranchesController do
expect(json_response["name"]).to eq('new_name')
end
- context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- allow(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
-
+ context 'when a policy restricts rule update' do
it "prevents update of the protected branch rule" do
+ disallow(:update_protected_branch, protected_branch)
+
old_name = protected_branch.name
put(:update, params: base_params.merge(protected_branch: update_params))
@@ -85,10 +77,6 @@ RSpec.describe Projects::ProtectedBranchesController do
end
describe "DELETE #destroy" do
- before do
- sign_in(user)
- end
-
it "deletes the protected branch rule" do
delete(:destroy, params: base_params)
@@ -96,16 +84,18 @@ RSpec.describe Projects::ProtectedBranchesController do
end
context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- allow(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
-
it "prevents deletion of the protected branch rule" do
+ disallow(:destroy_protected_branch, protected_branch)
+
delete(:destroy, params: base_params)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
+
+ def disallow(ability, protected_branch)
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, ability, protected_branch).and_return(false)
+ end
end
diff --git a/spec/controllers/projects/tags/releases_controller_spec.rb b/spec/controllers/projects/tags/releases_controller_spec.rb
deleted file mode 100644
index 1d2385f54f9..00000000000
--- a/spec/controllers/projects/tags/releases_controller_spec.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::Tags::ReleasesController do
- let!(:project) { create(:project, :repository) }
- let!(:user) { create(:user) }
- let!(:release) { create(:release, project: project, tag: "v1.1.0") }
- let!(:tag) { release.tag }
-
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- describe 'GET #edit' do
- it 'initializes a new release' do
- tag_id = release.tag
- project.releases.destroy_all # rubocop: disable Cop/DestroyAll
-
- response = get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: tag_id }
-
- release = assigns(:release)
- expect(release).not_to be_nil
- expect(release).not_to be_persisted
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'retrieves an existing release' do
- response = get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: tag }
-
- release = assigns(:release)
- expect(release).not_to be_nil
- expect(release).to be_persisted
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- describe 'PUT #update' do
- it 'updates release note description' do
- response = update_release(release.tag, "description updated")
-
- release = project.releases.find_by(tag: tag)
- expect(release.description).to eq("description updated")
- expect(response).to have_gitlab_http_status(:found)
- end
-
- it 'creates a release if one does not exist' do
- tag_without_release = create_new_tag
-
- expect do
- update_release(tag_without_release.name, "a new release")
- end.to change { project.releases.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:found)
- end
-
- it 'sets the release name, sha, and author for a new release' do
- tag_without_release = create_new_tag
-
- response = update_release(tag_without_release.name, "a new release")
-
- release = project.releases.find_by(tag: tag_without_release.name)
- expect(release.name).to eq(tag_without_release.name)
- expect(release.sha).to eq(tag_without_release.target_commit.sha)
- expect(release.author.id).to eq(user.id)
- expect(response).to have_gitlab_http_status(:found)
- end
-
- it 'does not delete release when description is empty' do
- expect do
- update_release(tag, "")
- end.not_to change { project.releases.count }
-
- expect(release.reload.description).to eq("")
-
- expect(response).to have_gitlab_http_status(:found)
- end
-
- it 'does nothing when description is empty and the tag does not have a release' do
- tag_without_release = create_new_tag
-
- expect do
- update_release(tag_without_release.name, "")
- end.not_to change { project.releases.count }
-
- expect(response).to have_gitlab_http_status(:found)
- end
- end
-
- def create_new_tag
- project.repository.add_tag(user, 'mytag', 'master')
- end
-
- def update_release(tag_id, description)
- put :update, params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- tag_id: tag_id,
- release: { description: description }
- }
- end
-end
diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb
index 6d2db25ade2..01635f2e158 100644
--- a/spec/controllers/projects/uploads_controller_spec.rb
+++ b/spec/controllers/projects/uploads_controller_spec.rb
@@ -86,47 +86,27 @@ RSpec.describe Projects::UploadsController do
end
context "when not signed in" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads true' do
- before do
- model.update!(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 302" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:redirect)
- end
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads false' do
- before do
- model.update!(enforce_auth_checks_on_uploads: false)
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads true' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: true)
+ end
- it "responds with status 200" do
- show_upload
+ it "responds with status 302" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ expect(response).to have_gitlab_http_status(:redirect)
end
+ end
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads false' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: false)
+ end
- it "responds with status 200" do
- show_upload
+ it "responds with status 200" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
end
@@ -137,41 +117,21 @@ RSpec.describe Projects::UploadsController do
end
context "when the user doesn't have access to the model" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads true' do
- before do
- model.update!(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 404" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads false' do
- before do
- model.update!(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads true' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: true)
+ end
+
+ it "responds with status 404" do
+ show_upload
+
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
- context "with flag disabled" do
+ context 'when the project has setting enforce_auth_checks_on_uploads false' do
before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
+ model.update!(enforce_auth_checks_on_uploads: false)
end
it "responds with status 200" do
@@ -190,47 +150,27 @@ RSpec.describe Projects::UploadsController do
end
context "when not signed in" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads true' do
- before do
- model.update!(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads true' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: true)
+ end
- context 'when the project has setting enforce_auth_checks_on_uploads false' do
- before do
- model.update!(enforce_auth_checks_on_uploads: false)
- end
+ it "responds with status 200" do
+ show_upload
- it "responds with status 200" do
- show_upload
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads false' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: false)
end
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
+ it "responds with status 200" do
+ show_upload
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
+ expect(response).to have_gitlab_http_status(:ok)
end
end
end
@@ -241,41 +181,21 @@ RSpec.describe Projects::UploadsController do
end
context "when the user doesn't have access to the model" do
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads true' do
- before do
- model.update!(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'when the project has setting enforce_auth_checks_on_uploads false' do
- before do
- model.update!(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
+ context 'when the project has setting enforce_auth_checks_on_uploads true' do
+ before do
+ model.update!(enforce_auth_checks_on_uploads: true)
+ end
+
+ it "responds with status 200" do
+ show_upload
+
+ expect(response).to have_gitlab_http_status(:ok)
end
end
- context "with flag disabled" do
+ context 'when the project has setting enforce_auth_checks_on_uploads false' do
before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
+ model.update!(enforce_auth_checks_on_uploads: false)
end
it "responds with status 200" do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 34477a7bb68..94d75ab8d7d 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -878,30 +878,82 @@ RSpec.describe ProjectsController do
end
context 'with project feature attributes' do
- using RSpec::Parameterized::TableSyntax
+ let(:initial_value) { ProjectFeature::PRIVATE }
+ let(:update_to) { ProjectFeature::ENABLED }
- where(:feature, :initial_value, :update_to) do
- :metrics_dashboard_access_level | ProjectFeature::PRIVATE | ProjectFeature::ENABLED
- :container_registry_access_level | ProjectFeature::ENABLED | ProjectFeature::PRIVATE
+ before do
+ project.project_feature.update!(feature_access_level => initial_value)
end
- with_them do
- it "updates the project_feature new" do
- params = {
- namespace_id: project.namespace,
- id: project.path,
- project: {
- project_feature_attributes: {
- "#{feature}": update_to
- }
+ def update_project_feature
+ put :update, params: {
+ namespace_id: project.namespace,
+ id: project.path,
+ project: {
+ project_feature_attributes: {
+ feature_access_level.to_s => update_to
}
}
+ }
+ end
- expect { put :update, params: params }.to change {
- project.reload.project_feature.public_send(feature)
+ shared_examples 'feature update success' do
+ it 'updates access level successfully' do
+ expect { update_project_feature }.to change {
+ project.reload.project_feature.public_send(feature_access_level)
}.from(initial_value).to(update_to)
end
end
+
+ shared_examples 'feature update failure' do
+ it 'cannot update access level' do
+ expect { update_project_feature }.not_to change {
+ project.reload.project_feature.public_send(feature_access_level)
+ }
+ end
+ end
+
+ where(:feature_access_level) do
+ %i[
+ metrics_dashboard_access_level
+ container_registry_access_level
+ environments_access_level
+ feature_flags_access_level
+ releases_access_level
+ ]
+ end
+
+ with_them do
+ it_behaves_like 'feature update success'
+ end
+
+ context 'for feature_access_level operations_access_level' do
+ let(:feature_access_level) { :operations_access_level }
+
+ include_examples 'feature update failure'
+ end
+
+ context 'with feature flag split_operations_visibility_permissions disabled' do
+ before do
+ stub_feature_flags(split_operations_visibility_permissions: false)
+ end
+
+ context 'for feature_access_level operations_access_level' do
+ let(:feature_access_level) { :operations_access_level }
+
+ include_examples 'feature update success'
+ end
+
+ where(:feature_access_level) do
+ %i[
+ environments_access_level feature_flags_access_level
+ ]
+ end
+
+ with_them do
+ it_behaves_like 'feature update failure'
+ end
+ end
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index c5a97812d1f..70d4559edc1 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe RegistrationsController do
end
let_it_be(:base_user_params) do
- { first_name: 'first', last_name: 'last', username: 'new_username', email: 'new@user.com', password: 'Any_password' }
+ { first_name: 'first', last_name: 'last', username: 'new_username', email: 'new@user.com', password: User.random_password }
end
let_it_be(:user_params) { { user: base_user_params } }
@@ -222,7 +222,7 @@ RSpec.describe RegistrationsController do
context 'when the registration fails' do
let_it_be(:member) { create(:project_member, :invited) }
let_it_be(:missing_user_params) do
- { username: '', email: member.invite_email, password: 'Any_password' }
+ { username: '', email: member.invite_email, password: User.random_password }
end
let_it_be(:user_params) { { user: missing_user_params } }
@@ -535,7 +535,7 @@ RSpec.describe RegistrationsController do
end
it 'succeeds if password is confirmed' do
- post :destroy, params: { password: '12345678' }
+ post :destroy, params: { password: user.password }
expect_success
end
@@ -576,7 +576,7 @@ RSpec.describe RegistrationsController do
end
it 'fails' do
- delete :destroy, params: { password: '12345678' }
+ delete :destroy, params: { password: user.password }
expect_failure(s_('Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account'))
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index b4d4e01e972..14b198dbefe 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -12,47 +12,6 @@ RSpec.describe SearchController do
sign_in(user)
end
- shared_examples_for 'when the user cannot read cross project' do |action, params|
- before do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?)
- .with(user, :read_cross_project, :global) { false }
- end
-
- it 'blocks access without a project_id' do
- get action, params: params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'allows access with a project_id' do
- get action, params: params.merge(project_id: create(:project, :public).id)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- shared_examples_for 'with external authorization service enabled' do |action, params|
- let(:project) { create(:project, namespace: user.namespace) }
- let(:note) { create(:note_on_issue, project: project) }
-
- before do
- enable_external_authorization_service_check
- end
-
- it 'renders a 403 when no project is given' do
- get action, params: params
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'renders a 200 when a project was set' do
- get action, params: params.merge(project_id: project.id)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
shared_examples_for 'support for active record query timeouts' do |action, params, method_to_stub, format|
before do
allow_next_instance_of(SearchService) do |service|
@@ -133,10 +92,11 @@ RSpec.describe SearchController do
{
chars_under_limit: (('a' * (term_char_limit - 1) + ' ') * (term_limit - 1))[0, char_limit],
chars_over_limit: (('a' * (term_char_limit - 1) + ' ') * (term_limit - 1))[0, char_limit + 1],
- terms_under_limit: ('abc ' * (term_limit - 1)),
+ terms_under_limit: ('abc ' * (term_limit - 1)),
terms_over_limit: ('abc ' * (term_limit + 1)),
term_length_over_limit: ('a' * (term_char_limit + 1)),
- term_length_under_limit: ('a' * (term_char_limit - 1))
+ term_length_under_limit: ('a' * (term_char_limit - 1)),
+ blank: ''
}
end
@@ -147,6 +107,7 @@ RSpec.describe SearchController do
:terms_over_limit | :set_terms_flash
:term_length_under_limit | :not_to_set_flash
:term_length_over_limit | :not_to_set_flash # abuse, so do nothing.
+ :blank | :not_to_set_flash
end
with_them do
@@ -393,6 +354,13 @@ RSpec.describe SearchController do
get(:autocomplete, params: { term: 'foo@bar.com', scope: 'users' })
end
end
+
+ it 'can be filtered with params[:filter]' do
+ get :autocomplete, params: { term: 'setting', filter: 'generic' }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.count).to eq(1)
+ expect(json_response.first['label']).to match(/User settings/)
+ end
end
describe '#append_info_to_payload' do
@@ -410,9 +378,20 @@ RSpec.describe SearchController do
expect(payload[:metadata]['meta.search.project_ids']).to eq(%w(456 789))
expect(payload[:metadata]['meta.search.type']).to eq('basic')
expect(payload[:metadata]['meta.search.level']).to eq('global')
+ expect(payload[:metadata]['meta.search.filters.language']).to eq('ruby')
end
- get :show, params: { scope: 'issues', search: 'hello world', group_id: '123', project_id: '456', project_ids: %w(456 789), confidential: true, state: true, force_search_results: true }
+ get :show, params: {
+ scope: 'issues',
+ search: 'hello world',
+ group_id: '123',
+ project_id: '456',
+ project_ids: %w(456 789),
+ confidential: true,
+ state: true,
+ force_search_results: true,
+ language: 'ruby'
+ }
end
it 'appends the default scope in meta.search.scope' do
diff --git a/spec/events/ci/pipeline_created_event_spec.rb b/spec/events/ci/pipeline_created_event_spec.rb
deleted file mode 100644
index 191c2e450dc..00000000000
--- a/spec/events/ci/pipeline_created_event_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::PipelineCreatedEvent do
- using RSpec::Parameterized::TableSyntax
-
- where(:data, :valid) do
- { pipeline_id: 1 } | true
- { pipeline_id: nil } | false
- { pipeline_id: "test" } | false
- {} | false
- { job_id: 1 } | false
- end
-
- with_them do
- let(:event) { described_class.new(data: data) }
-
- it 'validates the data according to the schema' do
- if valid
- expect { event }.not_to raise_error
- else
- expect { event }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/events/pages/page_deleted_event_spec.rb b/spec/events/pages/page_deleted_event_spec.rb
deleted file mode 100644
index 8fcd807eeb4..00000000000
--- a/spec/events/pages/page_deleted_event_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Pages::PageDeletedEvent do
- where(:data, :valid) do
- [
- [{ project_id: 1, namespace_id: 2 }, true],
- [{ project_id: 1, namespace_id: 2, root_namespace_id: 3 }, true],
- [{ project_id: 1 }, false],
- [{ namespace_id: 1 }, false],
- [{ project_id: 'foo', namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: 'foo' }, false],
- [{ project_id: [], namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: [] }, false],
- [{ project_id: {}, namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: {} }, false],
- ['foo', false],
- [123, false],
- [[], false]
- ]
- end
-
- with_them do
- it 'validates data' do
- constructor = -> { described_class.new(data: data) }
-
- if valid
- expect { constructor.call }.not_to raise_error
- else
- expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/events/pages/page_deployed_event_spec.rb b/spec/events/pages/page_deployed_event_spec.rb
deleted file mode 100644
index 0c33a95b281..00000000000
--- a/spec/events/pages/page_deployed_event_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Pages::PageDeployedEvent do
- where(:data, :valid) do
- [
- [{ project_id: 1, namespace_id: 2, root_namespace_id: 3 }, true],
- [{ project_id: 1 }, false],
- [{ namespace_id: 1 }, false],
- [{ project_id: 'foo', namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: 'foo' }, false],
- [{ project_id: [], namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: [] }, false],
- [{ project_id: {}, namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: {} }, false],
- ['foo', false],
- [123, false],
- [[], false]
- ]
- end
-
- with_them do
- it 'validates data' do
- constructor = -> { described_class.new(data: data) }
-
- if valid
- expect { constructor.call }.not_to raise_error
- else
- expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/events/projects/project_created_event_spec.rb b/spec/events/projects/project_created_event_spec.rb
deleted file mode 100644
index d70c737afb0..00000000000
--- a/spec/events/projects/project_created_event_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::ProjectCreatedEvent do
- where(:data, :valid) do
- [
- [{ project_id: 1, namespace_id: 2, root_namespace_id: 3 }, true],
- [{ project_id: 1 }, false],
- [{ namespace_id: 1 }, false],
- [{ project_id: 'foo', namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: 'foo' }, false],
- [{ project_id: [], namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: [] }, false],
- [{ project_id: {}, namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: {} }, false],
- ['foo', false],
- [123, false],
- [[], false]
- ]
- end
-
- with_them do
- it 'validates data' do
- constructor = -> { described_class.new(data: data) }
-
- if valid
- expect { constructor.call }.not_to raise_error
- else
- expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/events/projects/project_deleted_event_spec.rb b/spec/events/projects/project_deleted_event_spec.rb
deleted file mode 100644
index c3de2b22224..00000000000
--- a/spec/events/projects/project_deleted_event_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::ProjectDeletedEvent do
- where(:data, :valid) do
- [
- [{ project_id: 1, namespace_id: 2 }, true],
- [{ project_id: 1, namespace_id: 2, root_namespace_id: 3 }, true],
- [{ project_id: 1 }, false],
- [{ namespace_id: 1 }, false],
- [{ project_id: 'foo', namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: 'foo' }, false],
- [{ project_id: [], namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: [] }, false],
- [{ project_id: {}, namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: {} }, false],
- ['foo', false],
- [123, false],
- [[], false]
- ]
- end
-
- with_them do
- it 'validates data' do
- constructor = -> { described_class.new(data: data) }
-
- if valid
- expect { constructor.call }.not_to raise_error
- else
- expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/events/projects/project_path_changed_event_spec.rb b/spec/events/projects/project_path_changed_event_spec.rb
deleted file mode 100644
index a157428de04..00000000000
--- a/spec/events/projects/project_path_changed_event_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::ProjectPathChangedEvent do
- where(:data, :valid) do
- valid_event = {
- project_id: 1,
- namespace_id: 2,
- root_namespace_id: 3,
- old_path: 'old',
- new_path: 'new'
- }
-
- # All combinations of missing keys
- with_missing_keys = 0.upto(valid_event.size - 1)
- .flat_map { |size| valid_event.keys.combination(size).to_a }
- .map { |keys| [valid_event.slice(*keys), false] }
-
- [
- [valid_event, true],
- *with_missing_keys,
- [{ project_id: 'foo', namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: 'foo' }, false],
- [{ project_id: [], namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: [] }, false],
- [{ project_id: {}, namespace_id: 2 }, false],
- [{ project_id: 1, namespace_id: {} }, false],
- ['foo', false],
- [123, false],
- [[], false]
- ]
- end
-
- with_them do
- it 'validates data' do
- constructor = -> { described_class.new(data: data) }
-
- if valid
- expect { constructor.call }.not_to raise_error
- else
- expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent)
- end
- end
- end
-end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 97ddbf21b99..d684f79a518 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -504,6 +504,20 @@ FactoryBot.define do
artifacts_expire_at { 1.minute.ago }
end
+ trait :with_artifacts_paths do
+ options do
+ {
+ artifacts: {
+ name: 'artifacts_file',
+ untracked: false,
+ paths: ['out/'],
+ when: 'always',
+ expire_in: '7d'
+ }
+ }
+ end
+ end
+
trait :with_commit do
after(:build) do |build|
commit = build(:commit, :without_author)
@@ -645,6 +659,19 @@ FactoryBot.define do
end
end
+ trait :multiple_report_artifacts do
+ options do
+ {
+ artifacts: {
+ reports: {
+ sast: 'gl-sast-report.json',
+ container_scanning: 'gl-container-scanning-report.json'
+ }
+ }
+ }
+ end
+ end
+
trait :non_public_artifacts do
options do
{
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index cdbcdced5f4..114ad3a5847 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -102,6 +102,28 @@ FactoryBot.define do
end
end
+ trait :zip_with_single_file do
+ file_type { :archive }
+ file_format { :zip }
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/single_file.zip'),
+ 'application/zip')
+ end
+ end
+
+ trait :zip_with_multiple_files do
+ file_type { :archive }
+ file_format { :zip }
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/multiple_files.zip'),
+ 'application/zip')
+ end
+ end
+
trait :junit do
file_type { :junit }
file_format { :gzip }
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index 18026412261..4758986b47c 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -18,11 +18,11 @@ FactoryBot.define do
after(:build) do |runner, evaluator|
evaluator.projects.each do |proj|
- runner.runner_projects << build(:ci_runner_project, project: proj)
+ runner.runner_projects << build(:ci_runner_project, runner: runner, project: proj)
end
evaluator.groups.each do |group|
- runner.runner_namespaces << build(:ci_runner_namespace, namespace: group)
+ runner.runner_namespaces << build(:ci_runner_namespace, runner: runner, namespace: group)
end
end
diff --git a/spec/factories/ci/secure_files.rb b/spec/factories/ci/secure_files.rb
index 9afec5db858..74988202c71 100644
--- a/spec/factories/ci/secure_files.rb
+++ b/spec/factories/ci/secure_files.rb
@@ -6,5 +6,11 @@ FactoryBot.define do
file { fixture_file_upload('spec/fixtures/ci_secure_files/upload-keystore.jks', 'application/octet-stream') }
checksum { 'foo1234' }
project
+
+ trait :remote_store do
+ after(:create) do |ci_secure_file|
+ ci_secure_file.update!(file_store: ObjectStorage::Store::REMOTE)
+ end
+ end
end
end
diff --git a/spec/factories/ci/variables.rb b/spec/factories/ci/variables.rb
index a4cbf873b0b..1f9c12ecbce 100644
--- a/spec/factories/ci/variables.rb
+++ b/spec/factories/ci/variables.rb
@@ -5,6 +5,7 @@ FactoryBot.define do
sequence(:key) { |n| "VARIABLE_#{n}" }
value { 'VARIABLE_VALUE' }
masked { false }
+ variable_type { :env_var }
trait(:protected) do
add_attribute(:protected) { true }
diff --git a/spec/factories/gitlab/database/async_indexes/postgres_async_index.rb b/spec/factories/gitlab/database/async_indexes/postgres_async_index.rb
index d6b4b90bbd0..e3f366c17eb 100644
--- a/spec/factories/gitlab/database/async_indexes/postgres_async_index.rb
+++ b/spec/factories/gitlab/database/async_indexes/postgres_async_index.rb
@@ -5,5 +5,9 @@ FactoryBot.define do
sequence(:name) { |n| "users_id_#{n}" }
definition { "CREATE INDEX #{name} ON #{table_name} (id)" }
table_name { "users" }
+
+ trait :with_drop do
+ definition { "DROP INDEX #{name}" }
+ end
end
end
diff --git a/spec/factories/member_roles.rb b/spec/factories/member_roles.rb
new file mode 100644
index 00000000000..bd211844f5a
--- /dev/null
+++ b/spec/factories/member_roles.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :member_role do
+ namespace { association(:group) }
+ base_access_level { Gitlab::Access::DEVELOPER }
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index d60512e2b2a..95b72648cf5 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -37,6 +37,9 @@ FactoryBot.define do
operations_access_level { ProjectFeature::ENABLED }
container_registry_access_level { ProjectFeature::ENABLED }
security_and_compliance_access_level { ProjectFeature::PRIVATE }
+ environments_access_level { ProjectFeature::ENABLED }
+ feature_flags_access_level { ProjectFeature::ENABLED }
+ releases_access_level { ProjectFeature::ENABLED }
# we can't assign the delegated `#ci_cd_settings` attributes directly, as the
# `#ci_cd_settings` relation needs to be created first
@@ -404,6 +407,13 @@ FactoryBot.define do
end
end
+ trait :pages_published do
+ after(:create) do |project|
+ project.mark_pages_onboarding_complete
+ project.mark_pages_as_deployed
+ end
+ end
+
trait :service_desk_disabled do
service_desk_enabled { nil }
end
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 70b0af8a36c..2e7c6116fe6 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -5,7 +5,7 @@ FactoryBot.define do
email { generate(:email) }
name { generate(:name) }
username { generate(:username) }
- password { "12345678" }
+ password { User.random_password }
role { 'software_developer' }
confirmed_at { Time.now }
confirmation_token { nil }
diff --git a/spec/factories/users/project_user_callouts.rb b/spec/factories/users/project_user_callouts.rb
new file mode 100644
index 00000000000..50e85315bb9
--- /dev/null
+++ b/spec/factories/users/project_user_callouts.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_callout, class: 'Users::ProjectCallout' do
+ feature_name { :awaiting_members_banner }
+
+ user
+ project
+ end
+end
diff --git a/spec/factories/work_items.rb b/spec/factories/work_items.rb
index 81c9fb6ed87..267ea9710b3 100644
--- a/spec/factories/work_items.rb
+++ b/spec/factories/work_items.rb
@@ -10,6 +10,10 @@ FactoryBot.define do
issue_type { :issue }
association :work_item_type, :default
+ trait :confidential do
+ confidential { true }
+ end
+
trait :task do
issue_type { :task }
association :work_item_type, :default, :task
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 8bf8ef56353..b297d92b2fa 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -6,161 +6,168 @@ RSpec.describe 'Admin Appearance' do
let!(:appearance) { create(:appearance) }
let(:admin) { create(:admin) }
- it 'create new appearance' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
-
- fill_in 'appearance_title', with: 'MyCompany'
- fill_in 'appearance_description', with: 'dev server'
- fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
- fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines'
- click_button 'Update appearance settings'
-
- expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true
- expect(page).to have_content 'Appearance'
-
- expect(page).to have_field('appearance_title', with: 'MyCompany')
- expect(page).to have_field('appearance_description', with: 'dev server')
- expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines')
- expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines')
- expect(page).to have_content 'Last edit'
- end
+ flag_values = [true, false]
+ flag_values.each do |val|
+ before do
+ stub_feature_flags(restyle_login_page: val)
+ end
- it 'preview sign-in page appearance' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ it 'create new appearance' do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_application_settings_appearances_path
- visit admin_application_settings_appearances_path
- click_link "Sign-in page"
+ fill_in 'appearance_title', with: 'MyCompany'
+ fill_in 'appearance_description', with: 'dev server'
+ fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
+ fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines'
+ click_button 'Update appearance settings'
- expect(find('#login')).to be_disabled
- expect(find('#password')).to be_disabled
- expect(find('button')).to be_disabled
+ expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true
+ expect(page).to have_content 'Appearance'
- expect_custom_sign_in_appearance(appearance)
- end
+ expect(page).to have_field('appearance_title', with: 'MyCompany')
+ expect(page).to have_field('appearance_description', with: 'dev server')
+ expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines')
+ expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines')
+ expect(page).to have_content 'Last edit'
+ end
- it 'preview new project page appearance', :js do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ it 'preview sign-in page appearance' do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
- click_link "New project page"
+ visit admin_application_settings_appearances_path
+ click_link "Sign-in page"
- expect_custom_new_project_appearance(appearance)
- end
+ expect(find('#login')).to be_disabled
+ expect(find('#password')).to be_disabled
+ expect(find('button')).to be_disabled
- context 'Custom system header and footer' do
- before do
+ expect_custom_sign_in_appearance(appearance)
+ end
+
+ it 'preview new project page appearance', :js do
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- end
- context 'when system header and footer messages are empty' do
- it 'shows custom system header and footer fields' do
- visit admin_application_settings_appearances_path
+ visit admin_application_settings_appearances_path
+ click_link "New project page"
- expect(page).to have_field('appearance_header_message', with: '')
- expect(page).to have_field('appearance_footer_message', with: '')
- expect(page).to have_field('appearance_message_background_color')
- expect(page).to have_field('appearance_message_font_color')
- end
+ expect_custom_new_project_appearance(appearance)
end
- context 'when system header and footer messages are not empty' do
+ context 'Custom system header and footer' do
before do
- appearance.update!(header_message: 'Foo', footer_message: 'Bar')
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
end
- it 'shows custom system header and footer fields' do
- visit admin_application_settings_appearances_path
+ context 'when system header and footer messages are empty' do
+ it 'shows custom system header and footer fields' do
+ visit admin_application_settings_appearances_path
- expect(page).to have_field('appearance_header_message', with: appearance.header_message)
- expect(page).to have_field('appearance_footer_message', with: appearance.footer_message)
- expect(page).to have_field('appearance_message_background_color')
- expect(page).to have_field('appearance_message_font_color')
+ expect(page).to have_field('appearance_header_message', with: '')
+ expect(page).to have_field('appearance_footer_message', with: '')
+ expect(page).to have_field('appearance_message_background_color')
+ expect(page).to have_field('appearance_message_font_color')
+ end
end
- end
- end
- it 'custom sign-in page' do
- visit new_user_session_path
+ context 'when system header and footer messages are not empty' do
+ before do
+ appearance.update!(header_message: 'Foo', footer_message: 'Bar')
+ end
- expect_custom_sign_in_appearance(appearance)
- end
+ it 'shows custom system header and footer fields' do
+ visit admin_application_settings_appearances_path
- it 'custom new project page', :js do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit new_project_path
- click_link 'Create blank project'
+ expect(page).to have_field('appearance_header_message', with: appearance.header_message)
+ expect(page).to have_field('appearance_footer_message', with: appearance.footer_message)
+ expect(page).to have_field('appearance_message_background_color')
+ expect(page).to have_field('appearance_message_font_color')
+ end
+ end
+ end
- expect_custom_new_project_appearance(appearance)
- end
+ it 'custom sign-in page' do
+ visit new_user_session_path
- context 'Profile page with custom profile image guidelines' do
- before do
- sign_in(create(:admin))
+ expect_custom_sign_in_appearance(appearance)
+ end
+
+ it 'custom new project page', :js do
+ sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
- fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
- click_button 'Update appearance settings'
+ visit new_project_path
+ click_link 'Create blank project'
+
+ expect_custom_new_project_appearance(appearance)
end
- it 'renders guidelines when set' do
- sign_in create(:user)
- visit profile_path
+ context 'Profile page with custom profile image guidelines' do
+ before do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_application_settings_appearances_path
+ fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
+ click_button 'Update appearance settings'
+ end
- expect(page).to have_content 'Custom profile image guidelines, please 😄!'
+ it 'renders guidelines when set' do
+ sign_in create(:user)
+ visit profile_path
+
+ expect(page).to have_content 'Custom profile image guidelines, please 😄!'
+ end
end
- end
- it 'appearance logo' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ it 'appearance logo' do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_application_settings_appearances_path
- attach_file(:appearance_logo, logo_fixture)
- click_button 'Update appearance settings'
- expect(page).to have_css(logo_selector)
+ attach_file(:appearance_logo, logo_fixture)
+ click_button 'Update appearance settings'
+ expect(page).to have_css(logo_selector)
- click_link 'Remove logo'
- expect(page).not_to have_css(logo_selector)
- end
+ click_link 'Remove logo'
+ expect(page).not_to have_css(logo_selector)
+ end
- it 'header logos' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ it 'header logos' do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_application_settings_appearances_path
- attach_file(:appearance_header_logo, logo_fixture)
- click_button 'Update appearance settings'
- expect(page).to have_css(header_logo_selector)
+ attach_file(:appearance_header_logo, logo_fixture)
+ click_button 'Update appearance settings'
+ expect(page).to have_css(header_logo_selector)
- click_link 'Remove header logo'
- expect(page).not_to have_css(header_logo_selector)
- end
+ click_link 'Remove header logo'
+ expect(page).not_to have_css(header_logo_selector)
+ end
- it 'Favicon' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ it 'Favicon' do
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ visit admin_application_settings_appearances_path
- attach_file(:appearance_favicon, logo_fixture)
- click_button 'Update appearance settings'
+ attach_file(:appearance_favicon, logo_fixture)
+ click_button 'Update appearance settings'
- expect(page).to have_css('.appearance-light-logo-preview')
+ expect(page).to have_css('.appearance-light-logo-preview')
- click_link 'Remove favicon'
+ click_link 'Remove favicon'
- expect(page).not_to have_css('.appearance-light-logo-preview')
+ expect(page).not_to have_css('.appearance-light-logo-preview')
- # allowed file types
- attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg'))
- click_button 'Update appearance settings'
+ # allowed file types
+ attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg'))
+ click_button 'Update appearance settings'
- expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico'
+ expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico'
+ end
end
def expect_custom_sign_in_appearance(appearance)
diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb
index 659f66a67d2..6b4c9adb096 100644
--- a/spec/features/admin/admin_mode/login_spec.rb
+++ b/spec/features/admin/admin_mode/login_spec.rb
@@ -13,248 +13,252 @@ RSpec.describe 'Admin Mode Login' do
click_button 'Verify code'
end
- context 'with valid username/password' do
- let(:user) { create(:admin, :two_factor) }
-
- context 'using one-time code' do
- it 'blocks login if we reuse the same code immediately' do
- gitlab_sign_in(user, remember: true)
-
- expect(page).to have_content('Two-Factor Authentication')
-
- repeated_otp = user.current_otp
- enter_code(repeated_otp)
- gitlab_enable_admin_mode_sign_in(user)
-
- expect(page).to have_content('Two-Factor Authentication')
-
- enter_code(repeated_otp)
-
- expect(page).to have_current_path admin_session_path, ignore_query: true
- expect(page).to have_content('Invalid two-factor code')
- end
+ flag_values = [true, false]
+ flag_values.each do |val|
+ before do
+ stub_feature_flags(restyle_login_page: val)
+ end
+ context 'with valid username/password' do
+ let(:user) { create(:admin, :two_factor) }
- context 'not re-using codes' do
- before do
+ context 'using one-time code' do
+ it 'blocks login if we reuse the same code immediately' do
gitlab_sign_in(user, remember: true)
expect(page).to have_content('Two-Factor Authentication')
- enter_code(user.current_otp)
+ repeated_otp = user.current_otp
+ enter_code(repeated_otp)
gitlab_enable_admin_mode_sign_in(user)
expect(page).to have_content('Two-Factor Authentication')
- end
- it 'allows login with valid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code(user.current_otp)
+ enter_code(repeated_otp)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
-
- it 'blocks login with invalid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code('foo')
-
- expect(page).to have_content('Invalid two-factor code')
- end
+ expect(page).to have_current_path admin_session_path, ignore_query: true
+ expect(page).to have_content('Invalid two-factor code')
end
- it 'allows login with invalid code, then valid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code('foo')
+ context 'not re-using codes' do
+ before do
+ gitlab_sign_in(user, remember: true)
- expect(page).to have_content('Invalid two-factor code')
+ expect(page).to have_content('Two-factor authentication code')
enter_code(user.current_otp)
+ gitlab_enable_admin_mode_sign_in(user)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
+ expect(page).to have_content('Two-Factor Authentication')
end
- end
- context 'using backup code' do
- let(:codes) { user.generate_otp_backup_codes! }
+ it 'allows login with valid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
- before do
- expect(codes.size).to eq 10
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
+ end
+
+ it 'blocks login with invalid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code('foo')
- # Ensure the generated codes get saved
- user.save!
+ expect(page).to have_content('Invalid two-factor code')
+ end
end
- context 'with valid code' do
- it 'allows login' do
- enter_code(codes.sample)
+ it 'allows login with invalid code, then valid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code('foo')
+
+ expect(page).to have_content('Invalid two-factor code')
+
+ enter_code(user.current_otp)
expect(page).to have_current_path admin_root_path, ignore_query: true
expect(page).to have_content('Admin mode enabled')
end
-
- it 'invalidates the used code' do
- expect { enter_code(codes.sample) }
- .to change { user.reload.otp_backup_codes.size }.by(-1)
- end
end
- context 'with invalid code' do
- it 'blocks login' do
- code = codes.sample
- expect(user.invalidate_otp_backup_code!(code)).to eq true
+ context 'using backup code' do
+ let(:codes) { user.generate_otp_backup_codes! }
+
+ before do
+ expect(codes.size).to eq 10
+ # Ensure the generated codes get saved
user.save!
- expect(user.reload.otp_backup_codes.size).to eq 9
+ end
+
+ context 'with valid code' do
+ it 'allows login' do
+ enter_code(codes.sample)
- enter_code(code)
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
- expect(page).to have_content('Invalid two-factor code.')
+ it 'invalidates the used code' do
+ expect { enter_code(codes.sample) }
+ .to change { user.reload.otp_backup_codes.size }.by(-1)
+ end
end
- end
- end
- end
- end
- context 'when logging in via omniauth' do
- let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false)}
- let(:mock_saml_response) do
- File.read('spec/fixtures/authentication/saml_response.xml')
- end
+ context 'with invalid code' do
+ it 'blocks login' do
+ code = codes.sample
+ expect(user.invalidate_otp_backup_code!(code)).to eq true
+
+ user.save!
+ expect(user.reload.otp_backup_codes.size).to eq 9
+
+ enter_code(code)
- before do
- stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'],
- providers: [mock_saml_config_with_upstream_two_factor_authn_contexts])
+ expect(page).to have_content('Invalid two-factor code.')
+ end
+ end
+ end
+ end
end
- context 'when authn_context is worth two factors' do
+ context 'when logging in via omniauth' do
+ let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false) }
let(:mock_saml_response) do
File.read('spec/fixtures/authentication/saml_response.xml')
- .gsub('urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS')
end
- it 'signs user in without prompting for second factor' do
- sign_in_using_saml!
-
- expect(page).not_to have_content('Two-Factor Authentication')
-
- enable_admin_mode_using_saml!
-
- expect(page).not_to have_content('Two-Factor Authentication')
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
+ before do
+ stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config_with_upstream_two_factor_authn_contexts])
end
- end
- context 'when two factor authentication is required' do
- it 'shows 2FA prompt after omniauth login' do
- sign_in_using_saml!
-
- expect(page).to have_content('Two-Factor Authentication')
- enter_code(user.current_otp)
+ context 'when authn_context is worth two factors' do
+ let(:mock_saml_response) do
+ File.read('spec/fixtures/authentication/saml_response.xml')
+ .gsub('urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS')
+ end
- enable_admin_mode_using_saml!
+ it 'signs user in without prompting for second factor' do
+ sign_in_using_saml!
- expect(page).to have_content('Two-Factor Authentication')
+ expect(page).not_to have_content('Two-Factor Authentication')
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code(user.current_otp)
+ enable_admin_mode_using_saml!
+ expect(page).not_to have_content('Two-Factor Authentication')
expect(page).to have_current_path admin_root_path, ignore_query: true
expect(page).to have_content('Admin mode enabled')
end
end
- end
- def sign_in_using_saml!
- gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response)
- end
+ context 'when two factor authentication is required' do
+ it 'shows 2FA prompt after omniauth login' do
+ sign_in_using_saml!
- def enable_admin_mode_using_saml!
- gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response)
- end
- end
+ expect(page).to have_content('Two-Factor Authentication')
+ enter_code(user.current_otp)
- context 'when logging in via ldap' do
- let(:uid) { 'my-uid' }
- let(:provider_label) { 'Main LDAP' }
- let(:provider_name) { 'main' }
- let(:provider) { "ldap#{provider_name}" }
- let(:ldap_server_config) do
- {
- 'label' => provider_label,
- 'provider_name' => provider,
- 'attributes' => {},
- 'encryption' => 'plain',
- 'uid' => 'uid',
- 'base' => 'dc=example,dc=com'
- }
- end
+ enable_admin_mode_using_saml!
+
+ expect(page).to have_content('Two-Factor Authentication')
- let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) }
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
- before do
- setup_ldap(provider, user, uid, ldap_server_config)
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
+ end
+ end
+
+ def sign_in_using_saml!
+ gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response)
+ end
+
+ def enable_admin_mode_using_saml!
+ gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response)
+ end
end
- context 'when two factor authentication is required' do
- it 'shows 2FA prompt after ldap login' do
- sign_in_using_ldap!(user, provider_label)
+ context 'when logging in via ldap' do
+ let(:uid) { 'my-uid' }
+ let(:provider_label) { 'Main LDAP' }
+ let(:provider_name) { 'main' }
+ let(:provider) { "ldap#{provider_name}" }
+ let(:ldap_server_config) do
+ {
+ 'label' => provider_label,
+ 'provider_name' => provider,
+ 'attributes' => {},
+ 'encryption' => 'plain',
+ 'uid' => 'uid',
+ 'base' => 'dc=example,dc=com'
+ }
+ end
- expect(page).to have_content('Two-Factor Authentication')
+ let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) }
- enter_code(user.current_otp)
- enable_admin_mode_using_ldap!(user)
+ before do
+ setup_ldap(provider, user, uid, ldap_server_config)
+ end
- expect(page).to have_content('Two-Factor Authentication')
+ context 'when two factor authentication is required' do
+ it 'shows 2FA prompt after ldap login' do
+ sign_in_using_ldap!(user, provider_label)
+ expect(page).to have_content('Two-Factor Authentication')
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
enter_code(user.current_otp)
+ enable_admin_mode_using_ldap!(user)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
+ expect(page).to have_content('Two-Factor Authentication')
+
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
+
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
end
end
- end
- def setup_ldap(provider, user, uid, ldap_server_config)
- stub_ldap_setting(enabled: true)
+ def setup_ldap(provider, user, uid, ldap_server_config)
+ stub_ldap_setting(enabled: true)
- allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config])
- allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym])
+ 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!
+ 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)
+ mock_auth_hash(provider, uid, user.email)
+ allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true)
- allow_any_instance_of(ActionDispatch::Routing::RoutesProxy)
- .to receive(:"user_#{provider}_omniauth_callback_path")
- .and_return("/users/auth/#{provider}/callback")
- end
+ allow_any_instance_of(ActionDispatch::Routing::RoutesProxy)
+ .to receive(:"user_#{provider}_omniauth_callback_path")
+ .and_return("/users/auth/#{provider}/callback")
+ end
- def sign_in_using_ldap!(user, provider_label)
- visit new_user_session_path
- click_link provider_label
- fill_in 'username', with: user.username
- fill_in 'password', with: user.password
- click_button 'Sign in'
- end
+ def sign_in_using_ldap!(user, provider_label)
+ visit new_user_session_path
+ click_link provider_label
+ fill_in 'username', with: user.username
+ fill_in 'password', with: user.password
+ click_button 'Sign in'
+ end
- def enable_admin_mode_using_ldap!(user)
- visit new_admin_session_path
- click_link provider_label
- fill_in 'username', with: user.username
- fill_in 'password', with: user.password
- click_button 'Enter Admin Mode'
+ def enable_admin_mode_using_ldap!(user)
+ visit new_admin_session_path
+ click_link provider_label
+ fill_in 'username', with: user.username
+ fill_in 'password', with: user.password
+ click_button 'Enter Admin Mode'
+ end
end
end
end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index e5df6cc0fd3..236327ea687 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -357,7 +357,7 @@ RSpec.describe 'Admin::Users' do
end
it 'creates new user' do
- expect { click_button 'Create user' }.to change {User.count}.by(1)
+ expect { click_button 'Create user' }.to change { User.count }.by(1)
end
it 'applies defaults to user' do
@@ -400,7 +400,7 @@ RSpec.describe 'Admin::Users' do
let_it_be(:user_username) { 'Bing bang' }
it "doesn't create the user and shows an error message" do
- expect { click_button 'Create user' }.to change {User.count}.by(0)
+ expect { click_button 'Create user' }.to change { User.count }.by(0)
expect(page).to have_content('The form contains the following error')
expect(page).to have_content('Username can contain only letters, digits')
diff --git a/spec/features/admin_variables_spec.rb b/spec/features/admin_variables_spec.rb
new file mode 100644
index 00000000000..174d4567520
--- /dev/null
+++ b/spec/features/admin_variables_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Instance variables', :js do
+ let(:admin) { create(:admin) }
+ let(:page_path) { ci_cd_admin_application_settings_path }
+
+ let_it_be(:variable) { create(:ci_instance_variable, key: 'test_key', value: 'test_value', masked: true) }
+
+ before do
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ sign_in(admin)
+ gitlab_enable_admin_mode_sign_in(admin)
+ wait_for_requests
+ end
+
+ context 'with disabled ff `ci_variable_settings_graphql' do
+ before do
+ stub_feature_flags(ci_variable_settings_graphql: false)
+ visit page_path
+ end
+
+ it_behaves_like 'variable list', isAdmin: true
+ end
+
+ context 'with enabled ff `ci_variable_settings_graphql' do
+ before do
+ visit page_path
+ end
+
+ it_behaves_like 'variable list', isAdmin: true
+ end
+end
diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb
index 537b677cbd0..2e4dc4a29fc 100644
--- a/spec/features/boards/board_filters_spec.rb
+++ b/spec/features/boards/board_filters_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Issue board filters', :js do
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
let(:filtered_search) { find('[data-testid="issue-board-filtered-search"]') }
- let(:filter_input) { find('.gl-filtered-search-term-input')}
+ let(:filter_input) { find('.gl-filtered-search-term-input') }
let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
let(:filter_submit) { find('.gl-search-box-by-click-search-button') }
@@ -164,7 +164,7 @@ RSpec.describe 'Issue board filters', :js do
end
describe 'filters by type' do
- let_it_be(:incident) { create(:incident, project: project)}
+ let_it_be(:incident) { create(:incident, project: project) }
before do
set_filter('type')
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index e8321adeb42..f279af90aa3 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -135,6 +135,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -144,6 +145,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -153,6 +155,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -272,7 +275,7 @@ RSpec.describe 'Project issue boards', :js do
context 'issue card' do
it 'shows assignee' do
page.within(find('.board:nth-child(2)')) do
- expect(page).to have_selector('.avatar', count: 1)
+ expect(page).to have_selector('.gl-avatar', count: 1)
end
end
@@ -400,6 +403,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -409,6 +413,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
@@ -417,6 +422,7 @@ RSpec.describe 'Project issue boards', :js do
find('.board .board-list')
inspect_requests(inject_headers: { 'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/323426' }) do
+ evaluate_script("window.scrollTo(0, document.body.scrollHeight)")
evaluate_script("document.querySelectorAll('.board .board-list')[1].scrollTop = document.querySelectorAll('.board .board-list')[1].scrollHeight")
end
diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb
index 6a09e3c9506..7fa440befc1 100644
--- a/spec/features/boards/reload_boards_on_browser_back_spec.rb
+++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
- let(:project) {create(:project, :public)}
- let(:board) {create(:board, project: project)}
- let(:user) {create(:user)}
+ let(:project) { create(:project, :public) }
+ let(:board) { create(:board, project: project) }
+ let(:user) { create(:user) }
context 'authorized user' do
before do
diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb
index b879ae645f7..c44741b756b 100644
--- a/spec/features/clusters/create_agent_spec.rb
+++ b/spec/features/clusters/create_agent_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Cluster agent registration', :js do
let_it_be(:project) { create(:project, :custom_repo, files: { '.gitlab/agents/example-agent-1/config.yaml' => '' }) }
let_it_be(:current_user) { create(:user, maintainer_projects: [project]) }
+ let_it_be(:token) { Devise.friendly_token }
before do
allow(Gitlab::Kas).to receive(:enabled?).and_return(true)
@@ -18,7 +19,7 @@ RSpec.describe 'Cluster agent registration', :js do
allow(client).to receive(:get_connected_agents).and_return([])
end
- allow(Devise).to receive(:friendly_token).and_return('example-agent-token')
+ allow(Devise).to receive(:friendly_token).and_return(token)
sign_in(current_user)
visit project_clusters_path(project)
@@ -33,7 +34,7 @@ RSpec.describe 'Cluster agent registration', :js do
click_button('Register')
expect(page).to have_content('You cannot see this token again after you close this window.')
- expect(page).to have_content('example-agent-token')
+ expect(page).to have_content(token)
expect(page).to have_content('helm upgrade --install')
expect(page).to have_content('example-agent-2')
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 03d61020ff0..7714783172f 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Value Stream Analytics', :js do
+ include CycleAnalyticsHelpers
+
let_it_be(:user) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:stage_table_selector) { '[data-testid="vsa-stage-table"]' }
@@ -213,14 +215,20 @@ RSpec.describe 'Value Stream Analytics', :js do
expect(page.find(metrics_selector)).not_to have_selector("#commits")
end
- it 'needs permissions to see restricted stages' do
+ it 'does not show restricted stages', :aggregate_failures do
expect(find(stage_table_selector)).to have_content(issue.title)
- click_stage('Code')
- expect(find(stage_table_selector)).to have_content('You need permission.')
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Issue')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Plan')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Test')
+
+ expect(page).to have_selector('.gl-path-nav-list-item', text: 'Staging')
+
+ expect(page).not_to have_selector('.gl-path-nav-list-item', text: 'Code')
- click_stage('Review')
- expect(find(stage_table_selector)).to have_content('You need permission.')
+ expect(page).not_to have_selector('.gl-path-nav-list-item', text: 'Review')
end
end
diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb
index 1b349fa2276..d157d44bab7 100644
--- a/spec/features/dashboard/archived_projects_spec.rb
+++ b/spec/features/dashboard/archived_projects_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Dashboard Archived Project' do
let(:user) { create :user }
- let(:project) { create :project}
+ let(:project) { create :project }
let(:archived_project) { create(:project, :archived) }
before do
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index f8b68be7f93..91901414dde 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -8,73 +8,41 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
let(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
- describe 'feature flag mr_attention_requests is disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
-
- issue.assignees = [user]
- merge_request.update!(assignees: [user])
- sign_in(user)
- end
-
- it 'reflects dashboard issues count' do
- visit issues_path
-
- expect_counters('issues', '1', n_("%d assigned issue", "%d assigned issues", 1) % 1)
-
- issue.assignees = []
-
- user.invalidate_cache_counts
+ before do
+ issue.assignees = [user]
+ merge_request.update!(assignees: [user])
+ sign_in(user)
+ end
- travel_to(3.minutes.from_now) do
- visit issues_path
+ it 'reflects dashboard issues count' do
+ visit issues_path
- expect_counters('issues', '0', n_("%d assigned issue", "%d assigned issues", 0) % 0)
- end
- end
-
- it 'reflects dashboard merge requests count', :js do
- visit merge_requests_path
+ expect_counters('issues', '1', n_("%d assigned issue", "%d assigned issues", 1) % 1)
- expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
+ issue.assignees = []
- merge_request.update!(assignees: [])
+ user.invalidate_cache_counts
- user.invalidate_cache_counts
-
- travel_to(3.minutes.from_now) do
- visit merge_requests_path
+ travel_to(3.minutes.from_now) do
+ visit issues_path
- expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
- end
+ expect_counters('issues', '0', n_("%d assigned issue", "%d assigned issues", 0) % 0)
end
end
- describe 'feature flag mr_attention_requests is enabled' do
- before do
- merge_request.update!(assignees: [user])
-
- merge_request.find_assignee(user).update!(state: :attention_requested)
-
- user.invalidate_attention_requested_count
-
- sign_in(user)
- end
-
- it 'reflects dashboard merge requests count', :js do
- visit merge_requests_attention_path
+ it 'reflects dashboard merge requests count', :js do
+ visit merge_requests_path
- expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
+ expect_counters('merge_requests', '1', n_("%d merge request", "%d merge requests", 1) % 1)
- merge_request.find_assignee(user).update!(state: :reviewed)
+ merge_request.update!(assignees: [])
- user.invalidate_attention_requested_count
+ user.invalidate_cache_counts
- travel_to(3.minutes.from_now) do
- visit merge_requests_attention_path
+ travel_to(3.minutes.from_now) do
+ visit merge_requests_path
- expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
- end
+ expect_counters('merge_requests', '0', n_("%d merge request", "%d merge requests", 0) % 0)
end
end
@@ -86,10 +54,6 @@ RSpec.describe 'Navigation bar counter', :use_clean_rails_memory_store_caching d
merge_requests_dashboard_path(assignee_username: user.username)
end
- def merge_requests_attention_path
- merge_requests_dashboard_path(attention: user.username)
- end
-
def expect_counters(issuable_type, count, badge_label)
dashboard_count = find('.gl-tabs-nav li a.active')
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index fd580b679ad..70f614cdcef 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -112,8 +112,8 @@ RSpec.describe 'Dashboard Merge Requests' do
end
it 'includes assigned and reviewers in badge' do
- within("span[aria-label='#{n_("%d merge request", "%d merge requests", 0) % 0}']") do
- expect(page).to have_content('0')
+ within("span[aria-label='#{n_("%d merge request", "%d merge requests", 3) % 3}']") do
+ expect(page).to have_content('3')
end
find('.dashboard-shortcuts-merge_requests').click
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index d5dbe259159..2ac43f67f64 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -10,8 +10,8 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
- let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}
- let(:return_header) {{ 'Content-Type' => 'application/json' }}
+ let(:auth_token) { { 'Authorization' => 'Bearer access_token_123' } }
+ let(:return_header) { { 'Content-Type' => 'application/json' } }
before do
stub_request(:get, issues_api_url).with(headers: auth_token)
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 9af9baeb5bb..ab24162ad5a 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -23,7 +23,11 @@ RSpec.describe 'Group variables', :js do
it_behaves_like 'variable list'
end
- # TODO: Uncomment when the new graphQL app for variable settings
- # is enabled.
- # it_behaves_like 'variable list'
+ context 'with enabled ff `ci_variable_settings_graphql' do
+ before do
+ visit page_path
+ end
+
+ it_behaves_like 'variable list'
+ end
end
diff --git a/spec/features/groups/crm/contacts/create_spec.rb b/spec/features/groups/crm/contacts/create_spec.rb
index d6c6e3f1745..b10b2afe35c 100644
--- a/spec/features/groups/crm/contacts/create_spec.rb
+++ b/spec/features/groups/crm/contacts/create_spec.rb
@@ -22,7 +22,9 @@ RSpec.describe 'Create a CRM contact', :js do
fill_in 'description', with: 'VIP'
click_button 'Save changes'
- expect(page).to have_content 'gitlab@example.com'
+ wait_for_requests
+
+ expect(group.contacts.first.email).to eq('gitlab@example.com')
expect(page).to have_current_path("#{group_crm_contacts_path(group)}/", ignore_query: true)
end
end
diff --git a/spec/features/groups/group_runners_spec.rb b/spec/features/groups/group_runners_spec.rb
index a129db6cb6f..b98c94b030d 100644
--- a/spec/features/groups/group_runners_spec.rb
+++ b/spec/features/groups/group_runners_spec.rb
@@ -149,77 +149,39 @@ RSpec.describe "Group Runners" do
create(:ci_runner, :group, groups: [group], description: 'runner-foo', contacted_at: Time.zone.now)
end
- context 'when group_runner_view_ui is disabled' do
- before do
- stub_feature_flags(group_runner_view_ui: false)
- end
-
- it 'user edits the runner to be protected' do
- visit edit_group_runner_path(group, runner)
+ it 'user views runner details' do
+ visit group_runner_path(group, runner)
- expect(page.find_field('runner[access_level]')).not_to be_checked
-
- check 'runner_access_level'
- click_button 'Save changes'
-
- expect(page).to have_content 'Protected Yes'
- end
-
- context 'when a runner has a tag' do
- before do
- runner.update!(tag_list: ['tag'])
- end
+ expect(page).to have_content "#{s_('Runners|Description')} runner-foo"
+ end
- it 'user edits runner not to run untagged jobs' do
- visit edit_group_runner_path(group, runner)
+ it 'user edits the runner to be protected' do
+ visit edit_group_runner_path(group, runner)
- expect(page.find_field('runner[run_untagged]')).to be_checked
+ expect(page.find_field('runner[access_level]')).not_to be_checked
- uncheck 'runner_run_untagged'
- click_button 'Save changes'
+ check 'runner_access_level'
+ click_button _('Save changes')
- expect(page).to have_content 'Can run untagged jobs No'
- end
- end
+ expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}"
end
- context 'when group_runner_view_ui is enabled' do
+ context 'when a runner has a tag' do
before do
- stub_feature_flags(group_runner_view_ui: true)
+ runner.update!(tag_list: ['tag1'])
end
- it 'user views runner details' do
- visit group_runner_path(group, runner)
-
- expect(page).to have_content "#{s_('Runners|Description')} runner-foo"
- end
-
- it 'user edits the runner to be protected' do
+ it 'user edits runner not to run untagged jobs' do
visit edit_group_runner_path(group, runner)
- expect(page.find_field('runner[access_level]')).not_to be_checked
+ page.find_field('runner[tag_list]').set('tag1, tag2')
- check 'runner_access_level'
+ uncheck 'runner_run_untagged'
click_button _('Save changes')
- expect(page).to have_content "#{s_('Runners|Configuration')} #{s_('Runners|Protected')}"
- end
-
- context 'when a runner has a tag' do
- before do
- runner.update!(tag_list: ['tag'])
- end
-
- it 'user edits runner not to run untagged jobs' do
- visit edit_group_runner_path(group, runner)
-
- page.find_field('runner[tag_list]').set('tag, tag2')
-
- uncheck 'runner_run_untagged'
- click_button _('Save changes')
-
- expect(page).to have_content "#{s_('Runners|Tags')} tag tag2"
- end
+ # Tags can be in any order
+ expect(page).to have_content /#{s_('Runners|Tags')}.*tag1/
+ expect(page).to have_content /#{s_('Runners|Tags')}.*tag2/
end
end
end
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index c86705832b1..eec07c84cde 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -7,12 +7,12 @@ RSpec.describe 'Group issues page' do
include DragTo
let(:group) { create(:group) }
- let(:project) { create(:project, :public, group: group)}
+ let(:project) { create(:project, :public, group: group) }
let(:project_with_issues_disabled) { create(:project, :issues_disabled, group: group) }
let(:path) { issues_group_path(group) }
context 'with shared examples', :js do
- let(:issuable) { create(:issue, project: project, title: "this is my created issuable")}
+ let(:issuable) { create(:issue, project: project, title: "this is my created issuable") }
include_examples 'project features apply to issuables', Issue
@@ -68,7 +68,7 @@ RSpec.describe 'Group issues page' do
context 'issues list', :js do
let(:subgroup) { create(:group, parent: group) }
- let(:subgroup_project) { create(:project, :public, group: subgroup)}
+ let(:subgroup_project) { create(:project, :public, group: subgroup) }
let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
let!(:issue) { create(:issue, project: project, title: 'root group issue') }
let!(:subgroup_issue) { create(:issue, project: subgroup_project, title: 'subgroup issue') }
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 468001c3be6..5f28afc23f1 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -74,8 +74,8 @@ RSpec.describe 'Groups > Members > Manage members' do
invite_member(user1.name, role: 'Reporter', refresh: false)
- expect(page).to have_selector(invite_modal_selector)
- expect(page).to have_content("not authorized to update member")
+ invite_modal = page.find(invite_modal_selector)
+ expect(invite_modal).to have_content("not authorized to update member")
page.refresh
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 9a1e216c6d2..d814906a274 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'Group show page' do
it 'shows `Create new subgroup` link' do
expect(page).to have_link(
s_('GroupsEmptyState|Create new subgroup'),
- href: new_group_path(parent_id: group.id)
+ href: new_group_path(parent_id: group.id, anchor: 'create-group-pane')
)
end
@@ -97,28 +97,43 @@ RSpec.describe 'Group show page' do
end
end
- context 'when a public project is shared with a private group' do
- let_it_be(:private_group) { create(:group, :private) }
+ context 'visibility warning popover' do
let_it_be(:public_project) { create(:project, :public) }
- let_it_be(:project_group_link) { create(:project_group_link, group: private_group, project: public_project) }
- before do
- private_group.add_owner(user)
- sign_in(user)
- end
+ shared_examples 'it shows warning popover' do
+ it 'shows warning popover', :js do
+ group_to_share_with.add_owner(user)
+ sign_in(user)
+ visit group_path(group_to_share_with)
+
+ click_link _('Shared projects')
+
+ wait_for_requests
- it 'shows warning popover', :js do
- visit group_path(private_group)
+ page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
+ click_button _('Less restrictive visibility')
+ end
+
+ expect(page).to have_content _('Project visibility level is less restrictive than the group settings.')
+ end
+ end
- click_link _('Shared projects')
+ context 'when a public project is shared with a private group' do
+ let_it_be(:group_to_share_with) { create(:group, :private) }
+ let_it_be(:project_group_link) do
+ create(:project_group_link, group: group_to_share_with, project: public_project)
+ end
- wait_for_requests
+ include_examples 'it shows warning popover'
+ end
- page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
- click_button _('Less restrictive visibility')
+ context 'when a public project is shared with an internal group' do
+ let_it_be(:group_to_share_with) { create(:group, :internal) }
+ let_it_be(:project_group_link) do
+ create(:project_group_link, group: group_to_share_with, project: public_project)
end
- expect(page).to have_content _('Project visibility level is less restrictive than the group settings.')
+ include_examples 'it shows warning popover'
end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index ece6167b193..c93ed01b873 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -221,14 +221,13 @@ RSpec.describe 'Group' do
let(:user) { create(:admin) }
before do
- visit new_group_path(parent_id: group.id)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
end
context 'when admin mode is enabled', :enable_admin_mode do
it 'creates a nested group' do
- click_link 'Create group'
- fill_in 'Group name', with: 'bar'
- click_button 'Create group'
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'Create subgroup'
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
expect(page).to have_selector 'h1', text: 'bar'
@@ -237,7 +236,7 @@ RSpec.describe 'Group' do
context 'when admin mode is disabled' do
it 'is not allowed' do
- expect(page).not_to have_button('Create group')
+ expect(page).not_to have_button('Create subgroup')
end
end
end
@@ -250,11 +249,10 @@ RSpec.describe 'Group' do
sign_out(:user)
sign_in(user)
- visit new_group_path(parent_id: group.id)
- click_link 'Create group'
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
- fill_in 'Group name', with: 'bar'
- click_button 'Create group'
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'Create subgroup'
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
expect(page).to have_selector 'h1', text: 'bar'
@@ -268,7 +266,7 @@ RSpec.describe 'Group' do
end
context 'when creating subgroup' do
- let(:path) { new_group_path(parent_id: group.id) }
+ let(:path) { new_group_path(parent_id: group.id, anchor: 'create-group-pane') }
it 'does not render recaptcha' do
visit path
@@ -278,24 +276,50 @@ RSpec.describe 'Group' do
end
end
+ context 'when many parent groups are available' do
+ let_it_be(:group2) { create(:group, path: 'foo2') }
+ let_it_be(:group3) { create(:group, path: 'foo3') }
+
+ before do
+ group.add_owner(user)
+ group2.add_maintainer(user)
+ group3.add_developer(user)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
+ end
+
+ it 'creates private subgroup' do
+ fill_in 'Subgroup name', with: 'bar'
+ click_button 'foo'
+
+ expect(page).to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo2')
+ expect(page).not_to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo3')
+
+ click_button 'foo2'
+ click_button 'Create subgroup'
+
+ expect(page).to have_current_path(group_path('foo2/bar'), ignore_query: true)
+ expect(page).to have_selector('h1', text: 'bar')
+ expect(page).to have_selector('.visibility-icon [data-testid="lock-icon"]')
+ end
+ end
+
describe 'real-time group url validation', :js do
let_it_be(:subgroup) { create(:group, path: 'sub', parent: group) }
before do
group.add_owner(user)
- visit new_group_path(parent_id: group.id)
- click_link 'Create group'
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
end
it 'shows a message if group url is available' do
- fill_in 'Group URL', with: group.path
+ fill_in 'Subgroup slug', with: group.path
wait_for_requests
expect(page).to have_content('Group path is available')
end
it 'shows an error if group url is taken' do
- fill_in 'Group URL', with: subgroup.path
+ fill_in 'Subgroup slug', with: subgroup.path
wait_for_requests
expect(page).to have_content("Group path is unavailable. Path has been replaced with a suggested available path.")
@@ -308,7 +332,7 @@ RSpec.describe 'Group' do
sign_out(:user)
sign_in(create(:user))
- visit new_group_path(parent_id: group.id)
+ visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
expect(page).to have_title('Not Found')
expect(page).to have_content('Page Not Found')
@@ -354,7 +378,7 @@ RSpec.describe 'Group' do
end
it 'removes group', :sidekiq_might_not_need_inline do
- expect { remove_with_confirm('Remove group', group.path) }.to change {Group.count}.by(-1)
+ expect { remove_with_confirm('Remove group', group.path) }.to change { Group.count }.by(-1)
expect(group.members.all.count).to be_zero
expect(page).to have_content "scheduled for deletion"
end
@@ -507,8 +531,8 @@ RSpec.describe 'Group' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -518,8 +542,8 @@ RSpec.describe 'Group' do
end
it 'does not display the banner in a paid group page' do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:paid?).and_return(true)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:paid?).and_return(true)
end
visit group_path(group)
expect_page_not_to_have_storage_enforcement_banner
@@ -534,8 +558,8 @@ RSpec.describe 'Group' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -543,8 +567,12 @@ RSpec.describe 'Group' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
visit group_path(group)
@@ -554,10 +582,10 @@ RSpec.describe 'Group' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index fe804dc52d7..1baa97096d9 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -182,12 +182,14 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
context 'email confirmation disabled' do
let(:send_email_confirmation) { false }
- it 'signs up and redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
- fill_in_sign_up_form(new_user)
- fill_in_welcome_form
+ context 'the user signs up for an account with the invitation email address' do
+ it 'redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
+ fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
- expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
- 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)
+ expect(page).to have_content('You have been granted Owner access to group Owned.')
+ end
end
context 'the user sign-up using a different email address' do
@@ -227,11 +229,13 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do
- fill_in_sign_up_form(new_user)
- fill_in_welcome_form
+ context 'the user signs up for an account with the invitation email address' do
+ it 'redirects to the most recent membership activity page with all the projects/groups invitations automatically accepted' do
+ fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
- expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ expect(page).to have_current_path(activity_group_path(group), ignore_query: true)
+ end
end
context 'the user sign-up using a different email address' do
diff --git a/spec/features/issuables/user_sees_sidebar_spec.rb b/spec/features/issuables/user_sees_sidebar_spec.rb
index 04bf704b6a4..66ed6044de6 100644
--- a/spec/features/issuables/user_sees_sidebar_spec.rb
+++ b/spec/features/issuables/user_sees_sidebar_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Issue Sidebar on Mobile' do
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
let(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
sign_in(user)
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index 0700423983f..e749c555dcf 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -319,6 +319,13 @@ RSpec.describe 'New/edit issue', :js do
end
end
end
+
+ describe 'when repository contains CONTRIBUTING.md' do
+ it 'has contribution guidelines prompt' do
+ text = _('Please review the %{linkStart}contribution guidelines%{linkEnd} for this project.') % { linkStart: nil, linkEnd: nil }
+ expect(find('#new_issue')).to have_text(text)
+ end
+ end
end
describe 'new issue with query parameters' do
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 8732e2ecff2..fa4ce6fe1c1 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -414,7 +414,7 @@ RSpec.describe 'GFM autocomplete', :js do
it 'shows all contacts' do
page.within(find_autocomplete_menu) do
- expected_data = contacts.map { |c| "#{c.first_name} #{c.last_name} #{c.email}"}
+ expected_data = contacts.map { |c| "#{c.first_name} #{c.last_name} #{c.email}" }
expect(page.all('li').map(&:text)).to match_array(expected_data)
end
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index d6ec7f1c539..56be1493ed2 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Incident Detail', :js do
project.add_developer(user)
sign_in(user)
- visit project_issue_path(project, incident)
+ visit project_issues_incident_path(project, incident)
wait_for_requests
end
@@ -49,72 +49,32 @@ RSpec.describe 'Incident Detail', :js do
expect(incident_tabs).to have_content('Original alert: #1')
end
- aggregate_failures 'shows the Alert details tab' do
- click_link 'Alert details'
-
- expect(incident_tabs).to have_content('"title": "Alert title"')
- expect(incident_tabs).to have_content('"yet.another": 73')
- end
- end
- end
-
- context 'when on summary tab' do
- before do
- click_link 'Summary'
- end
-
- it 'shows the summary tab with all components' do
- page.within('.issuable-details') 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)
-
expect(hidden_items).to all(be_visible)
- end
- end
-
- it 'shows the edit title and description button' do
- edit_button = find_all('[aria-label="Edit title and description"]')
-
- expect(edit_button).to all(be_visible)
- end
- end
-
- context 'when on alert details tab' do
- before do
- click_link 'Alert details'
- 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')
- # Linked Issues/MRs and comment box are hidden on page
- expect(hidden_items.count).to eq(0)
+ edit_button = find_all('[aria-label="Edit title and description"]')
+ expect(edit_button).to all(be_visible)
end
- end
- it 'does not show the edit title and description button' do
- edit_button = find_all('[aria-label="Edit title and description"]')
-
- expect(edit_button.count).to eq(0)
- end
- end
+ aggregate_failures 'shows the Alert details tab' do
+ click_link 'Alert details'
- context 'when on timeline events tab from incident route' do
- before do
- visit project_issues_incident_path(project, incident)
- wait_for_requests
- click_link 'Timeline'
- end
+ expect(incident_tabs).to have_content('"title": "Alert title"')
+ expect(incident_tabs).to have_content('"yet.another": 73')
- it 'does not show the linked issues and notes/comment components' do
- page.within('.issuable-details') do
+ # does not show the linked issues and notes/comment components' do
hidden_items = find_all('.js-issue-widgets')
# 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"]')
+ expect(edit_button.count).to eq(0)
end
end
end
@@ -126,7 +86,7 @@ RSpec.describe 'Incident Detail', :js do
click_link 'Timeline'
end
- it 'does not show the linked issues and notes/comment commponents' do
+ it 'does not show the linked issues and notes/comment components' do
page.within('.issuable-details') do
hidden_items = find_all('.js-issue-widgets')
@@ -140,7 +100,7 @@ RSpec.describe 'Incident Detail', :js do
before do
stub_feature_flags(incident_timeline: false)
- visit project_issue_path(project, incident)
+ visit project_issues_incident_path(project, incident)
wait_for_requests
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index aaa478378a9..8819f085a5f 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -84,8 +84,10 @@ RSpec.describe 'Issue Sidebar' do
click_link user2.name
end
- find('.js-right-sidebar').click
- find('.block.assignee .edit-link').click
+ within '.js-right-sidebar' do
+ find('.block.assignee').click(x: 0, y: 0)
+ find('.block.assignee .edit-link').click
+ end
expect(page.all('.dropdown-menu-user li').length).to eq(1)
expect(find('.dropdown-input-field').value).to eq(user2.name)
@@ -182,7 +184,7 @@ RSpec.describe 'Issue Sidebar' do
page.within '.dropdown-menu-user' do
expect(page).not_to have_content 'Unassigned'
- click_link user2.name
+ click_button user2.name
end
find('.participants').click
diff --git a/spec/features/issues/related_issues_spec.rb b/spec/features/issues/related_issues_spec.rb
index a95229d4f1b..818e99f2ec9 100644
--- a/spec/features/issues/related_issues_spec.rb
+++ b/spec/features/issues/related_issues_spec.rb
@@ -232,7 +232,9 @@ RSpec.describe 'Related issues', :js do
it 'add related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_b.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -249,7 +251,9 @@ RSpec.describe 'Related issues', :js do
it 'add cross-project related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_project_b_a.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -359,7 +363,9 @@ RSpec.describe 'Related issues', :js do
it 'add related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "##{issue_d.iid} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -375,7 +381,9 @@ RSpec.describe 'Related issues', :js do
it 'add invalid related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: '#9999999 '
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
@@ -390,7 +398,9 @@ RSpec.describe 'Related issues', :js do
it 'add unauthorized related issue' do
click_button 'Add a related issue'
fill_in 'Paste issue link', with: "#{issue_project_unauthorized_a.to_reference(project)} "
- click_button 'Add'
+ page.within('.linked-issues-card-body') do
+ click_button 'Add'
+ end
wait_for_requests
diff --git a/spec/features/issues/todo_spec.rb b/spec/features/issues/todo_spec.rb
index d63d21353e5..6a53c12eda3 100644
--- a/spec/features/issues/todo_spec.rb
+++ b/spec/features/issues/todo_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Manually create a todo item from issue', :js do
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/user_bulk_edits_issues_spec.rb b/spec/features/issues/user_bulk_edits_issues_spec.rb
index 0533f1688e2..1ef2918adec 100644
--- a/spec/features/issues/user_bulk_edits_issues_spec.rb
+++ b/spec/features/issues/user_bulk_edits_issues_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Multiple issue updating from issues#index', :js do
let!(:project) { create(:project) }
let!(:issue) { create(:issue, project: project) }
- let!(:user) { create(:user)}
+ let!(:user) { create(:user) }
before do
project.add_maintainer(user)
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 151d3c60fa2..e29911e3263 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe "User creates issue" do
click_button 'Cancel'
end
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_button('Cancel')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
@@ -188,7 +188,7 @@ RSpec.describe "User creates issue" do
end
it 'does not hide the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
end
@@ -204,7 +204,7 @@ RSpec.describe "User creates issue" do
end
it 'shows the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
it 'hides the incident help text' do
@@ -265,7 +265,7 @@ RSpec.describe "User creates issue" do
end
it 'shows the milestone select' do
- expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="issuable-milestone-dropdown"]')
end
it 'hides the weight input' do
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 3b440002cb5..4eecb63c47e 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe "Issues > User edits issue", :js do
page.within '.block.labels' do
# Remove `verisimilitude` label
- within '.gl-label' do
+ within '.gl-label', text: 'verisimilitude' do
click_button 'Remove label'
end
@@ -285,7 +285,7 @@ RSpec.describe "Issues > User edits issue", :js do
end
page.within '.dropdown-menu-user' do
- click_link user.name
+ click_button user.name
end
page.within('.assignee') do
@@ -306,7 +306,7 @@ RSpec.describe "Issues > User edits issue", :js do
click_button('Edit')
wait_for_requests
- click_link user.name
+ click_button user.name
find('[data-testid="title"]').click
wait_for_requests
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 892b57bac5c..c86a2c32e2d 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'User interacts with awards' do
let(:user) { create(:user) }
describe 'User interacts with awards in an issue', :js do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
before do
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index c6d743ed38f..d458c991668 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Issues > User uses quick actions', :js do
let!(:label_feature) { create(:label, project: project, title: 'feature') }
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:issue, project: project) }
- let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature]) }
it_behaves_like 'close quick action', :issue
it_behaves_like 'issuable time tracker', :issue
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index d472134a2c7..b5bf9279371 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -109,10 +109,24 @@ RSpec.describe 'Copy as GFM', :js do
<<~GFM,
* [ ] Unchecked task
* [x] Checked task
+ * [~] Inapplicable task
+ * [~] Inapplicable task with ~~del~~ and <s>strike</s> embedded
GFM
- <<~GFM
+ <<~GFM,
1. [ ] Unchecked ordered task
1. [x] Checked ordered task
+ 1. [~] Inapplicable ordered task
+ 1. [~] Inapplicable ordered task with ~~del~~ and <s>strike</s> embedded
+ GFM
+ <<~GFM
+ * [ ] Unchecked loose list task
+ * [x] Checked loose list task
+ * [~] Inapplicable loose list task
+
+ With a paragraph
+ * [~] Inapplicable loose list task with ~~del~~ and <s>strike</s> embedded
+
+ With a paragraph
GFM
)
@@ -605,7 +619,8 @@ RSpec.describe 'Copy as GFM', :js do
'###### Heading',
'**Bold**',
'*Italics*',
- '~~Strikethrough~~',
+ '~~Strikethrough (del)~~',
+ '<s>Strikethrough</s>',
'---',
# table
<<~GFM,
diff --git a/spec/features/markdown/gitlab_flavored_markdown_spec.rb b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
index da4208318eb..e831d1be608 100644
--- a/spec/features/markdown/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/markdown/gitlab_flavored_markdown_spec.rb
@@ -3,6 +3,8 @@
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) }
diff --git a/spec/features/markdown/json_table_spec.rb b/spec/features/markdown/json_table_spec.rb
new file mode 100644
index 00000000000..6b74dbac255
--- /dev/null
+++ b/spec/features/markdown/json_table_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Rendering json:table code block in markdown', :js do
+ let_it_be(:project) { create(:project, :public) }
+
+ it 'creates table correctly' do
+ description = <<~JSONTABLE
+ Hello world!
+
+ ```json:table
+ {
+ "fields" : [
+ {"key": "a", "label": "AA"},
+ {"key": "b", "label": "BB"}
+ ],
+ "items" : [
+ {"a": "11", "b": "22"},
+ {"a": "211", "b": "222"}
+ ]
+ }
+ ```
+ JSONTABLE
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ wait_for_requests
+
+ within ".js-json-table table" do
+ headers = all("thead th").collect { |column| column.text.strip }
+ data = all("tbody td").collect { |column| column.text.strip }
+
+ expect(headers).to eql(%w[AA BB])
+ expect(data).to eql(%w[11 22 211 222])
+ end
+ end
+end
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index fafaea8ac68..f892b01e624 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
write_diff_comment
- visit_overview
+ visit_overview_with_pending_comment
end
it 'can add comment to review' do
@@ -232,6 +232,14 @@ RSpec.describe 'Merge request > Batch comments', :js do
wait_for_requests
end
+ def visit_overview_with_pending_comment
+ accept_alert do
+ visit project_merge_request_path(merge_request.project, merge_request)
+ end
+
+ wait_for_requests
+ end
+
def write_diff_comment(**params)
click_diff_line(find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']"))
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index a98bfd1c8a4..39d948bb6fb 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork', :js, :sidekiq_might_not_need_inline do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include ProjectForksHelper
let(:user) { create(:user, username: 'the-maintainer') }
let(:target_project) { create(:project, :public, :repository) }
@@ -40,12 +41,13 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork
end
it 'allows committing to the source branch' do
- execute_script("monaco.editor.getModels()[0].setValue('Updated the readme')")
+ content = 'Updated the readme'
+ editor_set_value(content)
click_button 'Commit changes'
wait_for_requests
expect(page).to have_content('Your changes have been successfully committed')
- expect(page).to have_content('Updated the readme')
+ expect(page).to have_content(content)
end
end
diff --git a/spec/features/merge_request/user_approves_spec.rb b/spec/features/merge_request/user_approves_spec.rb
index 4f7bcb58551..9670012803e 100644
--- a/spec/features/merge_request/user_approves_spec.rb
+++ b/spec/features/merge_request/user_approves_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'Merge request > User approves', :js do
def verify_approvals_count_on_index!
visit(project_merge_requests_path(project, state: :all))
- expect(page.all('li').any? { |item| item["title"] == "1 approver (you've approved)"}).to be true
+ expect(page.all('li').any? { |item| item["title"] == "1 approver (you've approved)" }).to be true
visit project_merge_request_path(project, merge_request)
end
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 43096f8e7f9..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
@@ -51,6 +51,45 @@ RSpec.describe 'User comments on a merge request', :js do
expect(page).to have_button('Resolve thread')
end
+ array = [':', '@', '#', '%', '!', '~', '$', '[contact:']
+ array.each do |x|
+ it 'handles esc key correctly when atwho is active' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: 'comment 1')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ click_button('Reply to comment')
+ fill_in('note[note]', with: x)
+ send_keys :escape
+ end
+
+ wait_for_requests
+ expect(page.html).not_to include('Are you sure you want to cancel creating this comment?')
+ end
+ end
+
+ it 'handles esc key correctly when atwho is not active' do
+ page.within('.js-main-target-form') do
+ fill_in('note[note]', with: 'comment 1')
+ click_button('Comment')
+ end
+
+ wait_for_requests
+
+ page.within('.note') do
+ click_button('Reply to comment')
+ fill_in('note[note]', with: 'comment 2')
+ send_keys :escape
+ end
+
+ wait_for_requests
+ expect(page.html).to include('Are you sure you want to cancel creating this comment?')
+ end
+
it 'loads new comment' do
# Add new comment in background in order to check
# if it's going to be loaded automatically for current user.
diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
index 059e1eb89c5..f0c0142a6cc 100644
--- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
+++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Merge request < User customizes merge commit message', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:issue_1) { create(:issue, project: project)}
- let(:issue_2) { create(:issue, project: project)}
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
let(:source_branch) { 'csv' }
let(:target_branch) { 'master' }
let(:squash) { false }
diff --git a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
index 92b9b785148..0dd87ac3e24 100644
--- a/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
+++ b/spec/features/merge_request/user_edits_assignees_sidebar_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do
context 'when GraphQL assignees widget feature flag is enabled' do
let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-item", text: assignee.username ) }
- let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item['title']}
+ let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item['title'] }
context 'when user is an owner' do
before do
diff --git a/spec/features/merge_request/user_merges_merge_request_spec.rb b/spec/features/merge_request/user_merges_merge_request_spec.rb
index 6a9a30953df..c91dc7b1c00 100644
--- a/spec/features/merge_request/user_merges_merge_request_spec.rb
+++ b/spec/features/merge_request/user_merges_merge_request_spec.rb
@@ -21,27 +21,6 @@ RSpec.describe "User merges a merge request", :js do
end
end
- context "ff-only merge" do
- let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) }
-
- before do
- stub_feature_flags(restructured_mr_widget: false)
- visit(merge_request_path(merge_request))
- end
-
- context "when branch is rebased" do
- let!(:merge_request) { create(:merge_request, :rebased, source_project: project) }
-
- it_behaves_like "fast forward merge a merge request"
- end
-
- context "when branch is merged" do
- let!(:merge_request) { create(:merge_request, :merged_target, source_project: project) }
-
- it_behaves_like "fast forward merge a merge request"
- end
- end
-
context 'sidebar merge requests counter' do
let(:project) { create(:project, :public, :repository) }
let!(:merge_request) { create(:merge_request, source_project: project) }
diff --git a/spec/features/merge_request/user_opens_context_commits_modal_spec.rb b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb
new file mode 100644
index 00000000000..2d574e57fe9
--- /dev/null
+++ b/spec/features/merge_request/user_opens_context_commits_modal_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge request > Context commits', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+
+ visit commits_project_merge_request_path(project, merge_request)
+
+ wait_for_requests
+ end
+
+ it 'opens modal' do
+ click_button 'Add previously merged commits'
+
+ expect(page).to have_selector('#add-review-item')
+ expect(page).to have_content('Add or remove previously merged commits')
+ end
+end
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index d461170c990..1eebb6c2e28 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -19,7 +19,6 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
project.add_developer(user)
sign_in(user)
- stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 104)
end
context 'when hovering over a parallel view diff file' do
diff --git a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
index 7b7fff5c936..f56db3d3dbe 100644
--- a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
+++ b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'Merge request > User sees closing issues message', :js do
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:issue_1) { create(:issue, project: project)}
- let(:issue_2) { create(:issue, project: project)}
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
let(:merge_request) do
create(
:merge_request,
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index e045f11c0d8..c02149eed87 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
let(:ref) { merge_request.target_branch }
let(:sha) { project.commit(ref).id }
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project, ref: ref) }
- let!(:manual) { }
+ let!(:manual) {}
let(:build) { create(:ci_build, :with_deployment, environment: environment.name, pipeline: pipeline) }
let!(:deployment) { build.deployment }
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index 50f4cce5c23..2e65183d26f 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
context 'when file contains html' do
let(:current_user) { project.first_owner }
- let(:branch_name) {"test_branch"}
+ let(:branch_name) { "test_branch" }
it 'escapes any HTML special characters in the diff chunk header' do
file_content =
diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
index 09c6b6bce3b..2a1b9ea6009 100644
--- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
}
end
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
before do
stub_application_setting(auto_devops_enabled: false)
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 16b1de0393f..11e542916f9 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -78,9 +78,18 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
it 'user visits merge request page' do
page.within('.merge-request-tabs') do
- expect(page).to have_no_link('Pipelines')
+ expect(page).to have_link('Pipelines')
end
end
+
+ it 'shows empty state with run pipeline button' do
+ page.within('.merge-request-tabs') do
+ click_link('Pipelines')
+ end
+
+ expect(page).to have_content('There are currently no pipelines.')
+ expect(page.find('[data-testid="run_pipeline_button"]')).to have_text('Run pipeline')
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 2c2a2dfd4a8..0e86e970f46 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -232,7 +232,7 @@ RSpec.describe 'Merge request > User sees versions', :js do
end
it 'only shows diffs from the commit' do
- diff_commit_ids = find_all('.diff-file [data-commit-id]').map {|diff| diff['data-commit-id']}
+ diff_commit_ids = find_all('.diff-file [data-commit-id]').map { |diff| diff['data-commit-id'] }
expect(diff_commit_ids).not_to be_empty
expect(diff_commit_ids).to all(eq(params[:commit_id]))
diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb
index b48659353ec..563120fc8b7 100644
--- a/spec/features/merge_request/user_uses_quick_actions_spec.rb
+++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Merge request > User uses quick actions', :js do
let!(:label_feature) { create(:label, project: project, title: 'feature') }
let!(:milestone) { create(:milestone, project: project, title: 'ASAP') }
let(:issuable) { create(:merge_request, source_project: project) }
- let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature])}
+ let(:source_issuable) { create(:issue, project: project, milestone: milestone, labels: [label_bug, label_feature]) }
it_behaves_like 'close quick action', :merge_request
it_behaves_like 'issuable time tracker', :merge_request
diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb
index fa866beb773..cf9760bcd7f 100644
--- a/spec/features/merge_requests/user_mass_updates_spec.rb
+++ b/spec/features/merge_requests/user_mass_updates_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe 'Merge requests > User mass updates', :js do
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
before do
- stub_feature_flags(mr_attention_requests: false)
-
project.add_maintainer(user)
project.add_maintainer(user2)
sign_in(user)
@@ -63,18 +61,6 @@ RSpec.describe 'Merge requests > User mass updates', :js do
expect(find('.merge-request')).to have_link "Assigned to #{user.name}"
end
-
- describe 'with attention requests feature flag on' do
- before do
- stub_feature_flags(mr_attention_requests: true)
- end
-
- it 'updates merge request with assignee' do
- change_assignee(user2.name)
-
- expect(find('.issuable-meta a.author-link')[:title]).to eq "Attention requested from assignee #{user2.name}"
- end
- end
end
describe 'remove assignee' do
diff --git a/spec/features/oauth_registration_spec.rb b/spec/features/oauth_registration_spec.rb
index 18dd10755b1..cb8343b8065 100644
--- a/spec/features/oauth_registration_spec.rb
+++ b/spec/features/oauth_registration_spec.rb
@@ -85,7 +85,46 @@ RSpec.describe 'OAuth Registration', :js, :allow_forgery_protection do
expect(page).to have_content('Please complete your profile with email address')
end
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
+ end
end
end
end
+
+ def fill_in_welcome_form
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ end
end
diff --git a/spec/features/populate_new_pipeline_vars_with_params_spec.rb b/spec/features/populate_new_pipeline_vars_with_params_spec.rb
index 937f99558ad..744543d1252 100644
--- a/spec/features/populate_new_pipeline_vars_with_params_spec.rb
+++ b/spec/features/populate_new_pipeline_vars_with_params_spec.rb
@@ -16,7 +16,6 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js do
it "var[key1]=value1 populates env_var variable correctly" do
page.within(all("[data-testid='ci-variable-row']")[0]) do
- expect(find("[data-testid='pipeline-form-ci-variable-type']").value).to eq('env_var')
expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key1')
expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value1')
end
@@ -24,7 +23,6 @@ RSpec.describe "Populate new pipeline CI variables with url params", :js do
it "file_var[key2]=value2 populates file variable correctly" do
page.within(all("[data-testid='ci-variable-row']")[1]) do
- expect(find("[data-testid='pipeline-form-ci-variable-type']").value).to eq('file')
expect(find("[data-testid='pipeline-form-ci-variable-key']").value).to eq('key2')
expect(find("[data-testid='pipeline-form-ci-variable-value']").value).to eq('value2')
end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 1013937ebb9..2836ac2f801 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'Profile account page', :js do
it 'deletes user', :js, :sidekiq_might_not_need_inline do
click_button 'Delete account'
- fill_in 'password', with: '12345678'
+ fill_in 'password', with: user.password
page.within '.modal' do
click_button 'Delete account'
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 07dfbca8cbd..1d0db488751 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe 'Profile > Password' do
end
context 'Password authentication enabled' do
+ let(:new_password) { User.random_password }
let(:user) { create(:user, password_automatically_set: true) }
before do
@@ -23,7 +24,7 @@ RSpec.describe 'Profile > Password' do
context 'User with password automatically set' do
describe 'User puts different passwords in the field and in the confirmation' do
it 'shows an error message' do
- fill_passwords('mypassword', 'mypassword2')
+ fill_passwords(new_password, "#{new_password}2")
page.within('.gl-alert-danger') do
expect(page).to have_content("Password confirmation doesn't match Password")
@@ -31,7 +32,7 @@ RSpec.describe 'Profile > Password' do
end
it 'does not contain the current password field after an error' do
- fill_passwords('mypassword', 'mypassword2')
+ fill_passwords(new_password, "#{new_password}2")
expect(page).to have_no_field('user[current_password]')
end
@@ -39,7 +40,7 @@ RSpec.describe 'Profile > Password' do
describe 'User puts the same passwords in the field and in the confirmation' do
it 'shows a success message' do
- fill_passwords('mypassword', 'mypassword')
+ fill_passwords(new_password, new_password)
page.within('[data-testid="alert-info"]') do
expect(page).to have_content('Password was successfully updated. Please sign in again.')
@@ -79,7 +80,7 @@ RSpec.describe 'Profile > Password' do
end
context 'Change password' do
- let(:new_password) { '22233344' }
+ let(:new_password) { User.random_password }
before do
sign_in(user)
@@ -156,6 +157,8 @@ RSpec.describe 'Profile > Password' do
end
context 'when password is expired' do
+ let(:new_password) { User.random_password }
+
before do
sign_in(user)
@@ -170,8 +173,8 @@ RSpec.describe 'Profile > Password' do
expect(page).to have_current_path new_profile_password_path, ignore_query: true
fill_in :user_password, with: user.password
- fill_in :user_new_password, with: '12345678'
- fill_in :user_password_confirmation, with: '12345678'
+ fill_in :user_new_password, with: new_password
+ fill_in :user_password_confirmation, with: new_password
click_button 'Set new password'
expect(page).to have_current_path new_user_session_path, ignore_query: true
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index bca1bc4df4d..088c8a7a15a 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -146,12 +146,6 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
end
end
- it 'pushes `personal_access_tokens_scoped_to_projects` feature flag to the frontend' do
- visit profile_personal_access_tokens_path
-
- expect(page).to have_pushed_frontend_feature_flags(personalAccessTokensScopedToProjects: true)
- end
-
it "prefills token details" do
name = 'My PAT'
scopes = 'api,read_user'
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 4b6ed458c68..2f7b722f553 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -294,7 +294,7 @@ RSpec.describe 'User edit profile' do
end
context 'user menu' do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
def open_modal(button_text)
@@ -536,7 +536,7 @@ RSpec.describe 'User edit profile' do
end
context 'User time preferences', :js do
- let(:issue) { create(:issue, project: project)}
+ let(:issue) { create(:issue, project: project) }
let(:project) { create(:project) }
before do
diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb
index 8b1af283765..7dd2e6aafa3 100644
--- a/spec/features/profiles/user_visits_profile_spec.rb
+++ b/spec/features/profiles/user_visits_profile_spec.rb
@@ -97,8 +97,8 @@ RSpec.describe 'User visits their profile' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Namespaces::UserNamespace) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -115,8 +115,8 @@ RSpec.describe 'User visits their profile' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Namespaces::UserNamespace) do |g|
- allow(g).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -124,8 +124,12 @@ RSpec.describe 'User visits their profile' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
visit(profile_path)
expect_page_not_to_have_storage_enforcement_banner
@@ -134,10 +138,10 @@ RSpec.describe 'User visits their profile' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
end
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index f5cafa2b2ec..13a4c1b5912 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -137,7 +137,7 @@ RSpec.describe 'File blob', :js do
context 'when ref switch' do
def switch_ref_to(ref_name)
- first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
+ first('[data-testid="branches-select"]').click
page.within '.project-refs-form' do
click_link ref_name
diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb
index 54176378de8..f198a1f42e2 100644
--- a/spec/features/projects/blobs/edit_spec.rb
+++ b/spec/features/projects/blobs/edit_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Editing file blob', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include TreeHelper
include BlobSpecHelpers
@@ -42,7 +43,7 @@ RSpec.describe 'Editing file blob', :js do
def fill_editor(content: 'class NextFeature\\nend\\n')
wait_for_requests
- execute_script("monaco.editor.getModels()[0].setValue('#{content}')")
+ editor_set_value(content)
end
context 'from MR diff' do
@@ -98,10 +99,8 @@ RSpec.describe 'Editing file blob', :js do
click_link 'Preview changes'
wait_for_requests
- old_line_count = page.all('.line_holder.old').size
new_line_count = page.all('.line_holder.new').size
- expect(old_line_count).to be > 0
expect(new_line_count).to be > 0
end
end
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index 7f10c6afcd5..608511ae5a5 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -16,16 +16,13 @@ RSpec.describe 'CI Lint', :js do
visit project_ci_lint_path(project)
editor_set_value(yaml_content)
-
- wait_for('YAML content') do
- find(content_selector).text.present?
- end
end
describe 'YAML parsing' do
shared_examples 'validates the YAML' do
before do
click_on 'Validate'
+ scroll_to(page.find('[data-testid="ci-lint-status"]'))
end
context 'YAML is correct' do
diff --git a/spec/features/projects/ci/secure_files_spec.rb b/spec/features/projects/ci/secure_files_spec.rb
deleted file mode 100644
index 412330eb5d6..00000000000
--- a/spec/features/projects/ci/secure_files_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Secure Files', :js do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
- before do
- stub_feature_flags(ci_secure_files_read_only: false)
- project.add_maintainer(user)
- sign_in(user)
- end
-
- it 'user sees the Secure Files list component' do
- visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no secure files yet.')
- end
-
- it 'prompts the user to confirm before deleting a file' do
- file = create(:ci_secure_file, project: project)
-
- visit project_ci_secure_files_path(project)
-
- expect(page).to have_content(file.name)
-
- find('button.btn-danger').click
-
- expect(page).to have_content("Delete #{file.name}?")
-
- click_on('Delete secure file')
-
- visit project_ci_secure_files_path(project)
-
- expect(page).not_to have_content(file.name)
- end
-
- it 'displays an uploaded file in the file list' do
- visit project_ci_secure_files_path(project)
- expect(page).to have_content('There are no secure files yet.')
-
- page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
- click_button 'Upload File'
- end
-
- expect(page).to have_content('upload-keystore.jks')
- end
-
- it 'displays an error when a duplicate file upload is attempted' do
- create(:ci_secure_file, project: project, name: 'upload-keystore.jks')
- visit project_ci_secure_files_path(project)
-
- expect(page).to have_content('upload-keystore.jks')
-
- page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
- click_button 'Upload File'
- end
-
- expect(page).to have_content('A file with this name already exists.')
- end
-end
diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb
index 5d931afe4a7..8c557a9c37a 100644
--- a/spec/features/projects/cluster_agents_spec.rb
+++ b/spec/features/projects/cluster_agents_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'ClusterAgents', :js do
- let_it_be(:token) { create(:cluster_agent_token, description: 'feature test token')}
+ let_it_be(:token) { create(:cluster_agent_token, description: 'feature test token') }
let(:agent) { token.agent }
let(:project) { agent.project }
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 863fdbdadaa..2719316c5dc 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -150,7 +150,7 @@ RSpec.describe 'User browses commits' do
let(:ref) { project.repository.root_ref }
let(:newrev) { project.repository.commit('master').sha }
let(:short_newrev) { project.repository.commit('master').short_id }
- let(:message) { 'Glob characters'}
+ let(:message) { 'Glob characters' }
before do
create_file_in_repo(project, ref, ref, filename, 'Test file', commit_message: message)
diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb
index bc3ef2af9b0..22b0f344606 100644
--- a/spec/features/projects/compare_spec.rb
+++ b/spec/features/projects/compare_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe "Compare", :js do
click_button('Compare')
- page.within('.gl-alert') do
+ page.within('[data-testid="too-many-changes-alert"]') do
expect(page).to have_text("Too many changes to show. To preserve performance only 3 of 3+ files are displayed.")
end
end
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 951b24eafac..a53e8beb555 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -18,10 +18,10 @@ RSpec.describe 'Environment' do
describe 'environment details page' do
let!(:environment) { create(:environment, project: project) }
- let!(:permissions) { }
- let!(:deployment) { }
- let!(:action) { }
- let!(:cluster) { }
+ let!(:permissions) {}
+ let!(:deployment) {}
+ let!(:action) {}
+ let!(:cluster) {}
context 'with auto-stop' do
let!(:environment) { create(:environment, :will_auto_stop, name: 'staging', project: project) }
diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
index 6b1e60db5b1..0ad44f31a52 100644
--- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
+++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
expect(page).to have_current_path("/-/ide/project/#{project.full_path}/edit/master/-/LICENSE", ignore_query: true)
- expect(page).to have_selector('.qa-file-templates-bar') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="file-templates-bar"]')
select_template('MIT License')
diff --git a/spec/features/projects/files/user_browses_files_spec.rb b/spec/features/projects/files/user_browses_files_spec.rb
index 53fdd5a15dd..0f3ce5a2bad 100644
--- a/spec/features/projects/files/user_browses_files_spec.rb
+++ b/spec/features/projects/files/user_browses_files_spec.rb
@@ -348,7 +348,7 @@ RSpec.describe "User browses files", :js do
end
it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
+ new_tab = window_opened_by { click_link 'Open raw' }
within_window new_tab do
expect(page).to have_content("Test file")
@@ -366,7 +366,7 @@ RSpec.describe "User browses files", :js do
end
it "shows raw file content in a new tab" do
- new_tab = window_opened_by {click_link 'Open raw'}
+ new_tab = window_opened_by { click_link 'Open raw' }
within_window new_tab do
expect(page).to have_content("*.rbc")
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index 7344c91b6dc..a81f31d663e 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User creates files', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include BlobSpecHelpers
let(:fork_message) do
@@ -89,8 +90,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
end
it 'creates and commit a new file' do
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -107,8 +107,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit a new file with new lines at the end of file' do
set_default_button('edit')
- find('#editor')
- execute_script('monaco.editor.getModels()[0].setValue("Sample\n\n\n")')
+ editor_set_value('Sample\n\n\n')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -119,8 +118,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
click_link('Edit')
- find('#editor')
- expect(evaluate_script('monaco.editor.getModels()[0].getValue()')).to eq("Sample\n\n\n")
+ expect(find('.monaco-editor')).to have_content('Sample\n\n\n')
end
it 'creates and commit a new file with a directory name' do
@@ -128,8 +126,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -143,8 +140,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit a new file specifying a new branch' do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
@@ -178,8 +174,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
it 'creates and commit new file in forked project' do
expect(page).to have_selector('.file-editor')
- find('#editor')
- execute_script("monaco.editor.getModels()[0].setValue('*.rbca')")
+ editor_set_value('*.rbca')
fill_in(:file_name, with: 'not_a_file.md')
fill_in(:commit_message, with: 'New commit message', visible: true)
diff --git a/spec/features/projects/files/user_edits_files_spec.rb b/spec/features/projects/files/user_edits_files_spec.rb
index 1ac45970828..d7460538be9 100644
--- a/spec/features/projects/files/user_edits_files_spec.rb
+++ b/spec/features/projects/files/user_edits_files_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe 'Projects > Files > User edits files', :js do
+ include Spec::Support::Helpers::Features::SourceEditorSpecHelpers
include ProjectForksHelper
include BlobSpecHelpers
@@ -50,10 +51,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
- expect(editor_value).to eq('*.rbca')
+ expect(find('.monaco-editor')).to have_content('*.rbca')
end
it 'does not show the edit link if a file is binary' do
@@ -72,8 +72,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -91,8 +90,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
click_button('Commit changes')
@@ -110,8 +108,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
click_link_or_button('Edit')
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
click_link('Preview changes')
expect(page).to have_css('.line_holder.new')
@@ -156,10 +153,9 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
- expect(editor_value).to eq('*.rbca')
+ expect(find('.monaco-editor')).to have_content('*.rbca')
end
it 'opens the Web IDE in a forked project', :sidekiq_might_not_need_inline do
@@ -187,8 +183,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
find('.file-editor', match: :first)
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
@@ -216,8 +211,7 @@ RSpec.describe 'Projects > Files > User edits files', :js do
expect(page).not_to have_link('Fork')
- find('#editor')
- set_editor_value('*.rbca')
+ editor_set_value('*.rbca')
fill_in(:commit_message, with: 'Another commit', visible: true)
click_button('Commit changes')
diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb
index 12c5820a69d..ac83de3e765 100644
--- a/spec/features/projects/issuable_templates_spec.rb
+++ b/spec/features/projects/issuable_templates_spec.rb
@@ -90,6 +90,34 @@ RSpec.describe 'issuable templates', :js do
end
end
+ context 'user creates an issue with a default template from the repo' do
+ let(:template_content) { 'this is the default template' }
+
+ before do
+ project.repository.create_file(
+ user,
+ '.gitlab/issue_templates/default.md',
+ template_content,
+ message: 'added default issue template',
+ branch_name: 'master'
+ )
+ end
+
+ it 'does not overwrite autosaved description' do
+ visit new_project_issue_path project
+ wait_for_requests
+
+ assert_template # default template is loaded the first time
+
+ fill_in 'issue_description', with: 'my own description', fill_options: { clear: :backspace }
+
+ visit new_project_issue_path project
+ wait_for_requests
+
+ assert_template(expected_content: 'my own description')
+ end
+ end
+
context 'user creates a merge request using templates' do
let(:template_content) { 'this is a test "feature-proposal" template' }
let(:bug_template_content) { 'this is merge request bug template' }
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index bb44b70bb3a..289ab8cffa5 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -74,6 +74,7 @@ RSpec.describe 'User browses jobs' do
wait_for_requests
expect(page).to have_selector('.ci-canceled')
+ expect(page).not_to have_selector('[data-testid="jobs-table-error-alert"]')
end
end
diff --git a/spec/features/projects/members/manage_groups_spec.rb b/spec/features/projects/members/manage_groups_spec.rb
index 006fa3b6eff..e86affbbca1 100644
--- a/spec/features/projects/members/manage_groups_spec.rb
+++ b/spec/features/projects/members/manage_groups_spec.rb
@@ -162,7 +162,7 @@ RSpec.describe 'Project > Members > Manage groups', :js do
let_it_be(:user) { maintainer }
let_it_be(:group) { parent_group }
let_it_be(:group_within_hierarchy) { create(:group, parent: group) }
- let_it_be(:project_within_hierarchy) { create(:project, group: group_within_hierarchy)}
+ let_it_be(:project_within_hierarchy) { create(:project, group: group_within_hierarchy) }
let_it_be(:members_page_path) { project_project_members_path(project) }
let_it_be(:members_page_path_within_hierarchy) { project_project_members_path(project_within_hierarchy) }
end
diff --git a/spec/features/projects/members/manage_members_spec.rb b/spec/features/projects/members/manage_members_spec.rb
index 8d229530ef5..56eb02607a5 100644
--- a/spec/features/projects/members/manage_members_spec.rb
+++ b/spec/features/projects/members/manage_members_spec.rb
@@ -12,106 +12,188 @@ RSpec.describe 'Projects > Members > Manage members', :js do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :internal, namespace: group) }
+ let(:project_owner) { create(:user, name: "ProjectOwner", username: "project_owner") }
+ let(:project_maintainer) { create(:user, name: "ProjectMaintainer", username: "project_maintainer") }
+ let(:group_owner) { user1 }
+ let(:project_developer) { user2 }
+
before do
- sign_in(user1)
- group.add_owner(user1)
+ project.add_maintainer(project_maintainer)
+ project.add_owner(project_owner)
+ group.add_owner(group_owner)
+
+ sign_in(group_owner)
end
it 'show members from project and group', :aggregate_failures do
- project.add_developer(user2)
+ project.add_developer(project_developer)
visit_members_page
- expect(first_row).to have_content(user1.name)
- expect(second_row).to have_content(user2.name)
+ expect(first_row).to have_content(group_owner.name)
+ expect(second_row).to have_content(project_developer.name)
end
it 'show user once if member of both group and project', :aggregate_failures do
- project.add_developer(user1)
+ group.add_reporter(project_maintainer)
visit_members_page
- expect(first_row).to have_content(user1.name)
- expect(second_row).to be_blank
+ expect(first_row).to have_content(group_owner.name)
+ expect(second_row).to have_content(project_maintainer.name)
+ expect(third_row).to have_content(project_owner.name)
+ expect(all_rows[3]).to be_blank
end
- it 'update user access level' do
- project.add_developer(user2)
+ context 'update user access level' do
+ before do
+ sign_in(current_user)
+ end
+
+ context 'as maintainer' do
+ let(:current_user) { project_maintainer }
- visit_members_page
+ it 'can update a non-Owner member' do
+ project.add_developer(project_developer)
- page.within find_member_row(user2) do
- click_button('Developer')
- click_button('Reporter')
+ visit_members_page
+
+ page.within find_member_row(project_developer) do
+ click_button('Developer')
+
+ page.within '.dropdown-menu' do
+ expect(page).not_to have_button('Owner')
+ end
+
+ click_button('Reporter')
+
+ expect(page).to have_button('Reporter')
+ end
+ end
- expect(page).to have_button('Reporter')
+ it 'cannot update an Owner member' do
+ visit_members_page
+
+ page.within find_member_row(project_owner) do
+ expect(page).not_to have_button('Owner')
+ end
+ end
end
- end
- context 'when owner' do
- it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
- visit_members_page
+ context 'as owner' do
+ let(:current_user) { group_owner }
- click_on 'Invite members'
+ it 'can update a project Owner member' do
+ visit_members_page
- click_on 'Guest'
- wait_for_requests
+ page.within find_member_row(project_owner) do
+ click_button('Owner')
+ click_button('Reporter')
- page.within '.dropdown-menu' do
- expect(page).to have_button('Guest')
- expect(page).to have_button('Reporter')
- expect(page).to have_button('Developer')
- expect(page).to have_button('Maintainer')
- expect(page).to have_button('Owner')
+ expect(page).to have_button('Reporter')
+ end
end
end
end
- context 'when maintainer' do
- let(:maintainer) { create(:user) }
-
+ context 'uses ProjectMember valid_access_level_roles for the invite members modal options', :aggregate_failures do
before do
- project.add_maintainer(maintainer)
- sign_in(maintainer)
- end
+ sign_in(current_user)
- it 'uses ProjectMember access_level_roles for the invite members modal access option', :aggregate_failures do
visit_members_page
click_on 'Invite members'
click_on 'Guest'
wait_for_requests
+ end
- page.within '.dropdown-menu' do
- expect(page).to have_button('Guest')
- expect(page).to have_button('Reporter')
- expect(page).to have_button('Developer')
- expect(page).to have_button('Maintainer')
- expect(page).not_to have_button('Owner')
+ context 'when owner' do
+ let(:current_user) { project_owner }
+
+ it 'shows Owner in the dropdown' do
+ page.within '.dropdown-menu' do
+ expect(page).to have_button('Guest')
+ expect(page).to have_button('Reporter')
+ expect(page).to have_button('Developer')
+ expect(page).to have_button('Maintainer')
+ expect(page).to have_button('Owner')
+ end
+ end
+ end
+
+ context 'when maintainer' do
+ let(:current_user) { project_maintainer }
+
+ it 'does not show the Owner option' do
+ page.within '.dropdown-menu' do
+ expect(page).to have_button('Guest')
+ expect(page).to have_button('Reporter')
+ expect(page).to have_button('Developer')
+ expect(page).to have_button('Maintainer')
+ expect(page).not_to have_button('Owner')
+ end
end
end
end
- it 'remove user from project' do
- other_user = create(:user)
- project.add_developer(other_user)
+ describe 'remove user from project' do
+ before do
+ project.add_developer(project_developer)
- visit_members_page
+ sign_in(current_user)
- # Open modal
- page.within find_member_row(other_user) do
- click_button 'Remove member'
+ visit_members_page
end
- within_modal do
- expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
- click_button('Remove member')
+ context 'when maintainer' do
+ let(:current_user) { project_maintainer }
+
+ it 'can only remove non-Owner members' do
+ page.within find_member_row(project_owner) do
+ expect(page).not_to have_button('Remove member')
+ end
+
+ # Open modal
+ page.within find_member_row(project_developer) do
+ click_button 'Remove member'
+ end
+
+ within_modal do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
+
+ wait_for_requests
+
+ expect(members_table).not_to have_content(project_developer.name)
+ expect(members_table).to have_content(project_owner.name)
+ end
end
- wait_for_requests
+ context 'when owner' do
+ let(:current_user) { group_owner }
+
+ it 'can remove any direct member' do
+ page.within find_member_row(project_owner) do
+ expect(page).to have_button('Remove member')
+ end
+
+ # Open modal
+ page.within find_member_row(project_owner) do
+ click_button 'Remove member'
+ end
- expect(members_table).not_to have_content(other_user.name)
+ within_modal do
+ expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
+ click_button('Remove member')
+ end
+
+ wait_for_requests
+
+ expect(members_table).not_to have_content(project_owner.name)
+ end
+ end
end
it_behaves_like 'inviting members', 'project-members-page' do
@@ -130,7 +212,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
external_project_bot = create(:user, :project_bot, name: '_external_project_bot_')
external_project = create(:project, group: external_group)
external_project.add_maintainer(external_project_bot)
- external_project.add_maintainer(user1)
+ external_project.add_maintainer(group_owner)
visit_members_page
@@ -143,8 +225,8 @@ RSpec.describe 'Projects > Members > Manage members', :js do
wait_for_requests
- expect(page).to have_content(user1.name)
- expect(page).to have_content(user2.name)
+ expect(page).to have_content(group_owner.name)
+ expect(page).to have_content(project_developer.name)
expect(page).not_to have_content(internal_project_bot.name)
expect(page).not_to have_content(external_project_bot.name)
end
@@ -155,7 +237,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
let_it_be(:project) { create(:project, :public) }
before do
- sign_out(user1)
+ sign_out(group_owner)
end
it 'does not show the Invite members button when not signed in' do
@@ -192,7 +274,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
end
it 'shows 2FA badge to user with "Maintainer" access level' do
- project.add_maintainer(user1)
+ sign_in(project_maintainer)
visit_members_page
@@ -209,7 +291,7 @@ RSpec.describe 'Projects > Members > Manage members', :js do
end
it 'does not show 2FA badge to users with access level below "Maintainer"' do
- group.add_developer(user1)
+ group.add_developer(group_owner)
visit_members_page
diff --git a/spec/features/projects/merge_request_button_spec.rb b/spec/features/projects/merge_request_button_spec.rb
index 335ae6794b7..eb52a7821f9 100644
--- a/spec/features/projects/merge_request_button_spec.rb
+++ b/spec/features/projects/merge_request_button_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Merge Request button' do
let(:forked_project) { fork_project(project, user, repository: true) }
shared_examples 'Merge request button only shown when allowed' do
+ let(:extra_mr_params) { {} }
+
context 'not logged in' do
it 'does not show Create merge request button' do
visit url
@@ -31,11 +33,8 @@ RSpec.describe 'Merge Request button' do
href = project_new_merge_request_path(
project,
merge_request: {
- source_project_id: project.id,
- source_branch: 'feature',
- target_project_id: project.id,
- target_branch: 'master'
- }
+ source_branch: 'feature'
+ }.merge(extra_mr_params)
)
visit url
@@ -90,11 +89,8 @@ RSpec.describe 'Merge Request button' do
href = project_new_merge_request_path(
forked_project,
merge_request: {
- source_project_id: forked_project.id,
- source_branch: 'feature',
- target_project_id: forked_project.id,
- target_branch: 'master'
- }
+ source_branch: 'feature'
+ }.merge(extra_mr_params)
)
visit fork_url
@@ -121,6 +117,7 @@ RSpec.describe 'Merge Request button' do
it_behaves_like 'Merge request button only shown when allowed' do
let(:url) { project_compare_path(project, from: 'master', to: 'feature') }
let(:fork_url) { project_compare_path(forked_project, from: 'master', to: 'feature') }
+ let(:extra_mr_params) { { target_project_id: project.id, target_branch: 'master' } }
end
it 'shows the correct merge request button when viewing across forks', :js do
@@ -128,9 +125,8 @@ RSpec.describe 'Merge Request button' do
project.add_developer(user)
href = project_new_merge_request_path(
- project,
+ forked_project,
merge_request: {
- source_project_id: forked_project.id,
source_branch: 'feature',
target_project_id: project.id,
target_branch: 'master'
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index 9d2d1454d77..f45025d079a 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -3,16 +3,44 @@
require 'spec_helper'
RSpec.describe 'New project', :js do
- include Select2Helper
include Spec::Support::Helpers::Features::TopNavSpecHelpers
context 'as a user' do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
end
+ it 'shows the project description field when it should' do
+ description_label = 'Project description (optional)'
+
+ visit new_project_path
+ click_link 'Create blank project'
+
+ page.within('#blank-project-pane') do
+ expect(page).not_to have_content(description_label)
+ end
+
+ visit new_project_path
+ click_link 'Import project'
+
+ page.within('#import-project-pane') do
+ click_button 'Repository by URL'
+
+ expect(page).to have_content(description_label)
+ end
+
+ visit new_project_path
+ click_link 'Create from template'
+
+ page.within('#create-from-template-pane') do
+ find("[data-testid='use_template_#{Gitlab::ProjectTemplate.localized_templates_table.first.name}']").click
+
+ expect(page).to have_content(description_label)
+ end
+ end
+
it 'shows a message if multiple levels are restricted' do
Gitlab::CurrentSettings.update!(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index afa3f29ce0d..5cb4fa163c8 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe 'User adds pages domain', :js do
include LetsEncryptHelpers
include Spec::Support::Helpers::ModalHelpers
- let_it_be(:project) { create(:project, pages_https_only: false) }
+ let_it_be(:project) { create(:project, :pages_published, pages_https_only: false) }
let(:user) { create(:user) }
@@ -18,8 +18,6 @@ RSpec.describe 'User adds pages domain', :js do
end
context 'when pages are exposed on external HTTP address', :http_pages_enabled do
- let(:project) { create(:project, pages_https_only: false) }
-
shared_examples 'adds new domain' do
it 'adds new domain' do
visit new_project_pages_domain_path(project)
@@ -42,7 +40,7 @@ RSpec.describe 'User adds pages domain', :js do
context 'when project in group namespace' do
it_behaves_like 'adds new domain' do
let(:group) { create :group }
- let(:project) { create(:project, namespace: group, pages_https_only: false) }
+ let(:project) { create(:project, :pages_published, namespace: group, pages_https_only: false) }
end
end
diff --git a/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb b/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb
new file mode 100644
index 00000000000..029479d6b95
--- /dev/null
+++ b/spec/features/projects/pages/user_configures_pages_pipeline_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'Pages edits pages settings', :js do
+ include Spec::Support::Helpers::ModalHelpers
+
+ let_it_be(:project) { create(:project, pages_https_only: false) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'when pipeline wizard feature is enabled' do
+ before do
+ Feature.enable(:use_pipeline_wizard_for_pages)
+ end
+
+ context 'when onboarding is not complete' do
+ it 'renders onboarding instructions' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Get started with Pages')
+ end
+ end
+
+ context 'when onboarding is complete' do
+ before do
+ project.mark_pages_onboarding_complete
+ end
+
+ it 'shows waiting screen' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Waiting for the Pages Pipeline to complete...')
+ end
+ end
+ end
+
+ context 'when pipeline wizard feature is disabled' do
+ before do
+ Feature.disable(:use_pipeline_wizard_for_pages)
+ end
+
+ it 'shows configure pages instructions' do
+ visit project_pages_path(project)
+
+ expect(page).to have_content('Configure pages')
+ end
+
+ after do
+ Feature.enable(:use_pipeline_wizard_for_pages)
+ end
+ end
+end
diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
index 4c633bea64e..2e28fa20b90 100644
--- a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb
@@ -5,7 +5,8 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
include LetsEncryptHelpers
include Spec::Support::Helpers::ModalHelpers
- let(:project) { create(:project, pages_https_only: false) }
+ let_it_be_with_reload(:project) { create(:project, :pages_published, pages_https_only: false) }
+
let(:user) { create(:user) }
let(:role) { :maintainer }
let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb
index bd163f4a109..88c27a6adf2 100644
--- a/spec/features/projects/pages/user_edits_settings_spec.rb
+++ b/spec/features/projects/pages/user_edits_settings_spec.rb
@@ -4,8 +4,8 @@ require 'spec_helper'
RSpec.describe 'Pages edits pages settings', :js do
include Spec::Support::Helpers::ModalHelpers
- let(:project) { create(:project, pages_https_only: false) }
- let(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project, :pages_published, pages_https_only: false) }
+ let_it_be(:user) { create(:user) }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
@@ -80,13 +80,6 @@ RSpec.describe 'Pages edits pages settings', :js do
end
end
- it 'does not see anything to destroy' do
- visit project_pages_path(project)
-
- expect(page).to have_content('Configure pages')
- expect(page).not_to have_link('Remove pages')
- end
-
describe 'project settings page' do
it 'renders "Pages" tab' do
visit edit_project_path(project)
@@ -151,7 +144,7 @@ RSpec.describe 'Pages edits pages settings', :js do
end
context 'non-HTTPS domain exists' do
- let(:project) { create(:project, pages_https_only: false) }
+ let(:project) { create(:project, :pages_published, pages_https_only: false) }
before do
create(:pages_domain, :without_key, :without_certificate, project: project)
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 8cf6d5bd29b..0711a30e974 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -109,7 +109,12 @@ RSpec.describe 'Pipeline Schedules', :js do
end
it 'changes ownership of the pipeline' do
- click_link 'Take ownership'
+ click_button 'Take ownership'
+
+ page.within('#pipeline-take-ownership-modal') do
+ click_link 'Take ownership'
+ end
+
page.within('.pipeline-schedule-table-row') do
expect(page).not_to have_content('No owner')
expect(page).to have_link('Sidney Jones')
diff --git a/spec/features/projects/pipelines/legacy_pipeline_spec.rb b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
index db6feecba03..14f60dfe061 100644
--- a/spec/features/projects/pipelines/legacy_pipeline_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipeline_spec.rb
@@ -385,6 +385,37 @@ RSpec.describe 'Pipeline', :js do
end
end
+ describe 'test tabs' do
+ let(:pipeline) { create(:ci_pipeline, :with_test_reports, :with_report_results, project: project) }
+
+ before do
+ stub_feature_flags(pipeline_tabs_vue: false)
+ visit_pipeline
+ wait_for_requests
+ end
+
+ context 'with test reports' do
+ it 'shows badge counter in Tests tab' do
+ expect(page.find('.js-test-report-badge-counter').text).to eq(pipeline.test_report_summary.total[:count].to_s)
+ end
+
+ it 'calls summary.json endpoint', :js do
+ find('.js-tests-tab-link').click
+
+ expect(page).to have_content('Jobs')
+ expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all)
+ end
+ end
+
+ context 'without test reports' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ it 'shows zero' do
+ expect(page.find('.js-test-report-badge-counter', visible: :all).text).to eq("0")
+ end
+ end
+ end
+
context 'retrying jobs' do
before do
visit_pipeline
diff --git a/spec/features/projects/pipelines/legacy_pipelines_spec.rb b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
index 15d889933bf..eb8f2de3aba 100644
--- a/spec/features/projects/pipelines/legacy_pipelines_spec.rb
+++ b/spec/features/projects/pipelines/legacy_pipelines_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Pipelines', :js do
include Spec::Support::Helpers::ModalHelpers
let(:project) { create(:project) }
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
context 'when user is logged in' do
let(:user) { create(:user) }
@@ -727,6 +727,7 @@ RSpec.describe 'Pipelines', :js do
end
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
stub_ci_pipeline_to_return_yaml_file
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index a83d4191f38..cfdd851cb80 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -394,7 +394,7 @@ RSpec.describe 'Pipeline', :js do
expect(page).to have_selector('button[aria-label="Cancel downstream pipeline"]')
end
- context 'when canceling' do
+ context 'when canceling', :sidekiq_inline do
before do
find('button[aria-label="Cancel downstream pipeline"]').click
wait_for_requests
@@ -515,18 +515,17 @@ RSpec.describe 'Pipeline', :js do
let(:pipeline) { create(:ci_pipeline, :with_test_reports, :with_report_results, project: project) }
before do
- stub_feature_flags(pipeline_tabs_vue: false)
visit_pipeline
wait_for_requests
end
context 'with test reports' do
it 'shows badge counter in Tests tab' do
- expect(page.find('.js-test-report-badge-counter').text).to eq(pipeline.test_report_summary.total[:count].to_s)
+ expect(page.find('[data-testid="tests-counter"]').text).to eq(pipeline.test_report_summary.total[:count].to_s)
end
it 'calls summary.json endpoint', :js do
- find('.js-tests-tab-link').click
+ find('.gl-tab-nav-item', text: 'Tests').click
expect(page).to have_content('Jobs')
expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all)
@@ -537,7 +536,7 @@ RSpec.describe 'Pipeline', :js do
let(:pipeline) { create(:ci_pipeline, project: project) }
it 'shows zero' do
- expect(page.find('.js-test-report-badge-counter', visible: :all).text).to eq("0")
+ expect(page.find('[data-testid="tests-counter"]', visible: :all).text).to eq("0")
end
end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 785edc69623..bf521971ae0 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Pipelines', :js do
include Spec::Support::Helpers::ModalHelpers
let(:project) { create(:project) }
- let(:expected_detached_mr_tag) {'merge request'}
+ let(:expected_detached_mr_tag) { 'merge request' }
context 'when user is logged in' do
let(:user) { create(:user) }
@@ -710,6 +710,7 @@ RSpec.describe 'Pipelines', :js do
end
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
stub_ci_pipeline_to_return_yaml_file
diff --git a/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb
new file mode 100644
index 00000000000..5a50b3de772
--- /dev/null
+++ b/spec/features/projects/settings/registry_settings_cleanup_tags_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project > Settings > Packages & Registries > Container registry tag expiration policy' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) }
+
+ let(:container_registry_enabled) { true }
+ let(:container_registry_enabled_on_project) { ProjectFeature::ENABLED }
+
+ subject { visit cleanup_image_tags_project_settings_packages_and_registries_path(project) }
+
+ before do
+ project.project_feature.update!(container_registry_access_level: container_registry_enabled_on_project)
+ project.container_expiration_policy.update!(enabled: true)
+
+ sign_in(user)
+ stub_container_registry_config(enabled: container_registry_enabled)
+ end
+
+ context 'as owner', :js do
+ it 'shows available section' do
+ subject
+
+ expect(find('.breadcrumbs')).to have_content('Clean up image tags')
+ end
+ end
+
+ context 'when registry is disabled' do
+ let(:container_registry_enabled) { false }
+
+ it 'does not exists' do
+ subject
+
+ expect(page).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when container registry is disabled on project' do
+ let(:container_registry_enabled_on_project) { ProjectFeature::DISABLED }
+
+ it 'does not exists' do
+ subject
+
+ expect(page).to have_gitlab_http_status(:not_found)
+ end
+ end
+end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 9468540736f..1fb46c669e7 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -31,7 +31,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
select('Every day', from: 'Run cleanup')
select('50 tags per image name', from: 'Keep the most recent:')
fill_in('Keep tags matching:', with: 'stable')
@@ -50,7 +49,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
fill_in('Remove tags matching:', with: '*-production')
submit_button = find('[data-testid="save-button"')
@@ -76,7 +74,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
expect(find('[data-testid="enable-toggle"]')).to have_content('Disabled - Tags will not be automatically deleted.')
end
end
@@ -91,7 +88,6 @@ RSpec.describe 'Project > Settings > Packages & Registries > Container registry
subject
within '[data-testid="container-expiration-policy-project-settings"]' do
- click_button('Expand')
expect(find('.gl-alert-title')).to have_content('Cleanup policy for tags is disabled')
end
end
diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb
index 0df4bd3f0d9..86c5c3d2d8c 100644
--- a/spec/features/projects/settings/service_desk_setting_spec.rb
+++ b/spec/features/projects/settings/service_desk_setting_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe 'Service Desk Setting', :js, :clean_gitlab_redis_cache do
}
end
- let_it_be_with_reload(:group) { create(:group)}
+ let_it_be_with_reload(:group) { create(:group) }
let_it_be_with_reload(:project) { create(:project, :custom_repo, group: group, files: issuable_project_template_files) }
let_it_be(:group_template_repo) { create(:project, :custom_repo, group: group, files: issuable_group_template_files) }
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
index c8438b73dc3..857d0696659 100644
--- a/spec/features/projects/tags/user_edits_tags_spec.rb
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -15,6 +15,13 @@ RSpec.describe 'Project > Tags', :js do
end
shared_examples "can create and update release" do
+ it 'shows tag information' do
+ visit page_url
+
+ expect(page).to have_content 'v1.1.0'
+ expect(page).to have_content 'Version 1.1.0'
+ end
+
it 'can create new release' do
visit page_url
page.find("a[href=\"#{new_project_release_path(project, tag_name: 'v1.1.0')}\"]").click
@@ -52,71 +59,4 @@ RSpec.describe 'Project > Tags', :js do
include_examples "can create and update release"
end
-
- # TODO: remove most of these together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
- describe 'when opening project tags' do
- before do
- stub_feature_flags(edit_tag_release_notes_via_release_page: false)
- visit project_tags_path(project)
- end
-
- context 'page with tags list' do
- it 'shows tag name' do
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Version 1.1.0'
- end
-
- it 'shows tag edit button' do
- page.within '.tags > .content-list' do
- edit_btn = page.find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']")
-
- expect(edit_btn['href']).to end_with("/#{project.full_path}/-/tags/v1.1.0/release/edit")
- end
- end
- end
-
- context 'edit tag release notes' do
- before do
- page.find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']").click
- end
-
- it 'shows tag name header' do
- page.within('.content') do
- expect(page.find('.sub-header-block')).to have_content 'Release notes for tag v1.1.0'
- end
- end
-
- it 'shows release notes form' do
- page.within('.content') do
- expect(page).to have_selector('form.release-form')
- end
- end
-
- it 'toolbar buttons on release notes form are functional' do
- page.within('.content form.release-form') do
- note_textarea = page.find('.js-gfm-input')
-
- # Click on Bold button
- page.find('.md-header-toolbar button:first-child').click
-
- expect(note_textarea.value).to eq('****')
- end
- end
-
- it 'release notes form shows "Attach a file" button', :js do
- page.within('.content form.release-form') do
- expect(page).to have_button('Attach a file')
- expect(page).not_to have_selector('.uploading-progress-container', visible: true)
- end
- end
-
- it 'shows "Attaching a file" message on uploading 1 file', :js, :capybara_ignore_server_errors do
- slow_requests do
- dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
-
- expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching a file -')
- end
- end
- end
- end
end
diff --git a/spec/features/projects/tags/user_views_tag_spec.rb b/spec/features/projects/tags/user_views_tag_spec.rb
new file mode 100644
index 00000000000..3978c5b7b78
--- /dev/null
+++ b/spec/features/projects/tags/user_views_tag_spec.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'User views tag', :feature do
+ include_examples 'user views tag' do
+ let(:tag_page) { project_tag_path(project, id: tag_name) }
+ end
+end
diff --git a/spec/features/projects/tags/user_views_tags_spec.rb b/spec/features/projects/tags/user_views_tags_spec.rb
index dfb5d5d9221..d3849df023e 100644
--- a/spec/features/projects/tags/user_views_tags_spec.rb
+++ b/spec/features/projects/tags/user_views_tags_spec.rb
@@ -2,34 +2,8 @@
require 'spec_helper'
RSpec.describe 'User views tags', :feature do
- context 'with html' do
- let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
- let(:user) { create(:user) }
- let(:tag_name) { "stable" }
- let!(:release) { create(:release, project: project, tag: tag_name) }
-
- before do
- project.add_developer(user)
- project.repository.add_tag(user, tag_name, project.default_branch_or_main)
-
- sign_in(user)
- end
-
- shared_examples 'renders the tag index page' do
- it do
- visit project_tags_path(project)
-
- expect(page).to have_content tag_name
- end
- end
-
- it_behaves_like 'renders the tag index page'
-
- context 'when tag name contains a slash' do
- let(:tag_name) { "stable/v0.1" }
-
- it_behaves_like 'renders the tag index page'
- end
+ include_examples 'user views tag' do
+ let(:tag_page) { project_tags_path(project) }
end
context 'rss' do
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index f6127b38bd6..074469a9b55 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -49,8 +49,8 @@ RSpec.describe 'Multi-file editor new directory', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist.
- if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
- find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
+ if page.has_css?('[data-testid="begin-commit-button"]')
+ find('[data-testid="begin-commit-button"]').click
end
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index 33be02a9121..85c644fa528 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -39,8 +39,8 @@ RSpec.describe 'Multi-file editor new file', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist.
- if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
- find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
+ if page.has_css?('[data-testid="begin-commit-button"]')
+ find('[data-testid="begin-commit-button"]').click
end
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb
index 53e89cd2959..163e347d03d 100644
--- a/spec/features/projects/tree/tree_show_spec.rb
+++ b/spec/features/projects/tree/tree_show_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe 'Projects tree', :js do
let(:filename) { File.join(path, 'test.txt') }
let(:newrev) { project.repository.commit('master').sha }
let(:short_newrev) { project.repository.commit('master').short_id }
- let(:message) { 'Glob characters'}
+ let(:message) { 'Glob characters' }
before do
create_file_in_repo(project, 'master', 'master', filename, 'Test file', commit_message: message)
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index f6f9c7f0d3c..d228fb084c3 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -329,7 +329,7 @@ RSpec.describe 'Project' do
it 'has working links to submodules' do
click_link('645f6c4c')
- expect(page).to have_selector('.qa-branches-select', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6') # rubocop:disable QA/SelectorUsage
+ expect(page).to have_selector('[data-testid="branches-select"]', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6')
end
context 'for signed commit on default branch', :js do
@@ -454,8 +454,8 @@ RSpec.describe 'Project' do
let_it_be(:storage_enforcement_date) { Date.today + 30 }
before do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -478,8 +478,8 @@ RSpec.describe 'Project' do
let_it_be(:project) { create(:project, namespace: user.namespace) }
before do
- allow_next_found_instance_of(Namespaces::UserNamespace) do |namspace|
- allow(namspace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Namespaces::UserNamespace) do |user_namespace|
+ allow(user_namespace).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
end
@@ -490,8 +490,8 @@ RSpec.describe 'Project' do
end
it 'does not display the banner in a paid group project page' do
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:paid?).and_return(true)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:paid?).and_return(true)
end
visit project_path(project)
expect_page_not_to_have_storage_enforcement_banner
@@ -506,8 +506,8 @@ RSpec.describe 'Project' do
expect_page_not_to_have_storage_enforcement_banner
storage_enforcement_date = Date.today + 13
- allow_next_found_instance_of(Group) do |grp|
- allow(grp).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(storage_enforcement_date)
end
page.refresh
expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
@@ -515,8 +515,12 @@ RSpec.describe 'Project' do
end
context 'with storage_enforcement_date not set' do
- # This test should break and be rewritten after the implementation of the storage_enforcement_date
- # TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
+ before do
+ allow_next_found_instance_of(Group) do |group|
+ allow(group).to receive(:storage_enforcement_date).and_return(nil)
+ end
+ end
+
it 'does not display the banner in the group page' do
stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
visit project_path(project)
@@ -526,11 +530,11 @@ RSpec.describe 'Project' do
end
def expect_page_to_have_storage_enforcement_banner(storage_enforcement_date)
- expect(page).to have_text "From #{storage_enforcement_date} storage limits will apply to this namespace"
+ expect(page).to have_text "Effective #{storage_enforcement_date}, namespace storage limits will apply"
end
def expect_page_not_to_have_storage_enforcement_banner
- expect(page).not_to have_text "storage limits will apply to this namespace"
+ expect(page).not_to have_text "namespace storage limits will apply"
end
def remove_with_confirm(button_text, confirm_with, confirm_button_text = 'Confirm')
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index 534da71e39a..2600c00346e 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -268,7 +268,7 @@ RSpec.describe 'Runners' do
it 'group runners are not available' do
visit project_runners_path(project)
- expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).not_to have_content 'To register them, go to the group\'s Runners page.'
expect(page).to have_content 'Ask your group owner to set up a group runner'
end
end
@@ -287,7 +287,7 @@ RSpec.describe 'Runners' do
expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).to have_content 'To register them, go to the group\'s Runners page.'
expect(page).not_to have_content 'Ask your group owner to set up a group runner'
end
end
@@ -313,7 +313,7 @@ RSpec.describe 'Runners' do
expect(page).to have_content 'This group does not have any group runners yet.'
- expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.'
+ expect(page).not_to have_content 'To register them, go to the group\'s Runners page.'
expect(page).to have_content 'Ask your group owner to set up a group runner.'
end
end
diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb
index 279db686aa9..2dceda09d7c 100644
--- a/spec/features/search/user_searches_for_commits_spec.rb
+++ b/spec/features/search/user_searches_for_commits_spec.rb
@@ -3,6 +3,8 @@
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) }
diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb
index dbf35567803..8725dbcafe8 100644
--- a/spec/features/signed_commits_spec.rb
+++ b/spec/features/signed_commits_spec.rb
@@ -93,7 +93,7 @@ RSpec.describe 'GPG signed commits' do
page.find('.gpg-status-box', text: 'Unverified').click
within '.popover' do
- expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.'
+ expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not associated with the GPG Key.'
expect(page).to have_content 'Bette Cartwright'
expect(page).to have_content '@bette.cartwright'
expect(page).to have_content "GPG Key ID: #{GpgHelpers::User2.primary_keyid}"
diff --git a/spec/features/tags/developer_updates_tag_spec.rb b/spec/features/tags/developer_updates_tag_spec.rb
deleted file mode 100644
index 531ed91c057..00000000000
--- a/spec/features/tags/developer_updates_tag_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# TODO: remove this file together with FF https://gitlab.com/gitlab-org/gitlab/-/issues/366244
-RSpec.describe 'Developer updates tag' do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project) { create(:project, :repository, namespace: group) }
-
- before do
- project.add_developer(user)
- sign_in(user)
- stub_feature_flags(edit_tag_release_notes_via_release_page: false)
- visit project_tags_path(project)
- end
-
- context 'from the tags list page' do
- it 'updates the release notes' do
- find("li > .row-fixed-content.controls a.btn-edit[href='/#{project.full_path}/-/tags/v1.1.0/release/edit']").click
-
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(page).to have_current_path(
- project_tag_path(project, 'v1.1.0'), ignore_query: true)
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
-
- it 'description has emoji autocomplete', :js do
- page.within(first('.content-list .controls')) do
- click_link 'Edit release notes'
- end
-
- find('#release_description').native.send_keys('')
- fill_in 'release_description', with: ':'
-
- expect(page).to have_selector('.atwho-view')
- end
- end
-
- context 'from a specific tag page' do
- it 'updates the release notes' do
- click_on 'v1.1.0'
- click_link 'Edit release notes'
- fill_in 'release_description', with: 'Awesome release notes'
- click_button 'Save changes'
-
- expect(page).to have_current_path(
- project_tag_path(project, 'v1.1.0'), ignore_query: true)
- expect(page).to have_content 'v1.1.0'
- expect(page).to have_content 'Awesome release notes'
- end
- end
-end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index 6907701de9c..07de3789c08 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("2 of 6 tasks completed")
+ expect(page).to have_content("2 of 6 checklist items completed")
end
end
@@ -108,7 +108,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("0 of 1 task completed")
+ expect(page).to have_content("0 of 1 checklist item completed")
end
end
@@ -127,7 +127,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on Issues#index' do
visit project_issues_path(project)
- expect(page).to have_content("1 of 1 task completed")
+ expect(page).to have_content("1 of 1 checklist item completed")
end
end
end
@@ -253,7 +253,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("2 of 6 tasks completed")
+ expect(page).to have_content("2 of 6 checklist items completed")
end
end
@@ -278,7 +278,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("0 of 1 task completed")
+ expect(page).to have_content("0 of 1 checklist item completed")
end
end
@@ -297,7 +297,7 @@ RSpec.describe 'Task Lists', :js do
it 'provides a summary on MergeRequests#index' do
visit project_merge_requests_path(project)
- expect(page).to have_content("1 of 1 task completed")
+ expect(page).to have_content("1 of 1 checklist item completed")
end
end
end
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 900cd72c17f..cbd2d30d726 100644
--- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'User uploads avatar to profile' do
visit user_path(user)
- expect(page).to have_selector(%Q(img[data-src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=90"]))
+ expect(page).to have_selector(%Q(img[src$="/uploads/-/system/user/avatar/#{user.id}/dk.png?width=96"]))
# Cheating here to verify something that isn't user-facing, but is important
expect(user.reload.avatar.file).to exist
diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb
index 589cc9f9b02..2547e2d274c 100644
--- a/spec/features/uploads/user_uploads_file_to_note_spec.rb
+++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb
@@ -16,8 +16,8 @@ RSpec.describe 'User uploads file to note' do
end
context 'before uploading' do
- it 'shows "Attach a file" button', :js do
- expect(page).to have_button('Attach a file')
+ it 'shows "Attach a file or image" button', :js do
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
end
@@ -30,7 +30,7 @@ RSpec.describe 'User uploads file to note' do
click_button 'Cancel'
end
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_button('Cancel')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
@@ -60,16 +60,15 @@ RSpec.describe 'User uploads file to note' do
expect(page).to have_selector('.uploading-error-message', visible: true, text: error_text)
expect(page).to have_button('Try again', visible: true)
expect(page).to have_button('attach a new file', visible: true)
- expect(page).not_to have_button('Attach a file')
end
end
context 'uploading is complete' do
- it 'shows "Attach a file" button on uploading complete', :js do
+ it 'shows "Attach a file or image" button on uploading complete', :js do
dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')])
wait_for_requests
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
diff --git a/spec/features/users/email_verification_on_login_spec.rb b/spec/features/users/email_verification_on_login_spec.rb
index 0833f7f6f8e..c8301c2fc91 100644
--- a/spec/features/users/email_verification_on_login_spec.rb
+++ b/spec/features/users/email_verification_on_login_spec.rb
@@ -335,7 +335,7 @@ RSpec.describe 'Email Verification On Login', :clean_gitlab_redis_rate_limiting
mail = find_email_for(user)
expect(mail.to).to match_array([user.email])
expect(mail.subject).to eq('Verify your identity')
- code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/]
+ code = mail.body.parts.first.to_s[/\d{#{VerifiesWithEmail::TOKEN_LENGTH}}/o]
reset_delivered_emails!
code
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 3ba3650b608..b875dbe1340 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -49,15 +49,15 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
expect(page).to have_current_path edit_user_password_path, ignore_query: true
expect(page).to have_content('Please create a password for your new account.')
- fill_in 'user_password', with: 'password'
- fill_in 'user_password_confirmation', with: 'password'
+ fill_in 'user_password', with: user.password
+ fill_in 'user_password_confirmation', with: user.password
click_button 'Change your password'
expect(page).to have_current_path new_user_session_path, ignore_query: true
expect(page).to have_content(I18n.t('devise.passwords.updated_not_active'))
fill_in 'user_login', with: user.username
- fill_in 'user_password', with: 'password'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect_single_session_with_authenticated_ttl
@@ -216,7 +216,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
before do
gitlab_sign_in(user, remember: true)
- expect(page).to have_content('Two-Factor Authentication')
+ expect(page).to have_content('Two-factor authentication code')
end
it 'does not show a "You are already signed in." error message' do
@@ -231,7 +231,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
it 'does not allow sign-in if the user password is updated before entering a one-time code' do
- user.update!(password: 'new_password')
+ user.update!(password: User.random_password)
enter_code(user.current_otp)
@@ -365,7 +365,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
context 'when logging in via OAuth' do
- let(:user) { create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml')}
+ let(:user) { create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml') }
let(:mock_saml_response) do
File.read('spec/fixtures/authentication/saml_response.xml')
end
@@ -407,7 +407,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
sign_in_using_saml!
- expect(page).to have_content('Two-Factor Authentication')
+ expect(page).to have_content('Two-factor authentication code')
enter_code(user.current_otp)
@@ -468,7 +468,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect(page).to have_current_path(new_profile_password_path, ignore_query: true)
@@ -477,14 +477,14 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
end
context 'with invalid username and password' do
- let(:user) { create(:user, password: 'not-the-default') }
+ let(:user) { create(:user) }
it 'blocks invalid login' do
expect(authentication_metrics)
.to increment(:user_unauthenticated_counter)
.and increment(:user_password_invalid_counter)
- gitlab_sign_in(user)
+ gitlab_sign_in(user, password: 'incorrect-password')
expect_single_session_with_short_ttl
expect(page).to have_content('Invalid login or password.')
@@ -788,7 +788,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -809,7 +809,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -830,7 +830,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
@@ -873,7 +873,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
fill_in 'user_otp_attempt', with: user.reload.current_otp
@@ -899,7 +899,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
visit new_user_session_path
fill_in 'user_login', with: user.email
- fill_in 'user_password', with: '12345678'
+ fill_in 'user_password', with: user.password
click_button 'Sign in'
expect_to_be_on_terms_page
@@ -907,9 +907,11 @@ RSpec.describe 'Login', :clean_gitlab_redis_sessions do
expect(page).to have_current_path(new_profile_password_path, ignore_query: true)
- fill_in 'user_password', with: '12345678'
- fill_in 'user_new_password', with: 'new password'
- fill_in 'user_password_confirmation', with: 'new password'
+ new_password = User.random_password
+
+ fill_in 'user_password', with: user.password
+ fill_in 'user_new_password', with: new_password
+ fill_in 'user_password_confirmation', with: new_password
click_button 'Set new password'
expect(page).to have_content('Password successfully changed')
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 2a444dad486..068e1fd4243 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -132,10 +132,10 @@ RSpec.describe 'User page' do
let_it_be(:followee) { create(:user) }
let_it_be(:follower) { create(:user) }
- it 'does not show link to follow' do
+ it 'does not show button to follow' do
subject
- expect(page).not_to have_link(text: 'Follow', class: 'gl-button')
+ expect(page).not_to have_button(text: 'Follow', class: 'gl-button')
end
it 'shows 0 followers and 0 following' do
@@ -155,11 +155,11 @@ RSpec.describe 'User page' do
expect(page).to have_content('1 following')
end
- it 'does show link to follow' do
+ it 'does show button to follow' do
sign_in(user)
visit user_path(followee)
- expect(page).to have_link(text: 'Follow', class: 'gl-button')
+ expect(page).to have_button(text: 'Follow', class: 'gl-button')
end
it 'does show link to unfollow' do
@@ -168,7 +168,7 @@ RSpec.describe 'User page' do
visit user_path(followee)
- expect(page).to have_link(text: 'Unfollow', class: 'gl-button')
+ expect(page).to have_button(text: 'Unfollow', class: 'gl-button')
end
end
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 30441dac7b6..f2381e41de8 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -3,39 +3,43 @@
require 'spec_helper'
RSpec.shared_examples 'Signup name validation' do |field, max_length, label|
- before do
- visit new_user_registration_path
- end
+ flag_values = [true, false]
+ flag_values.each do |val|
+ before do
+ stub_feature_flags(restyle_login_page: val)
+ visit new_user_registration_path
+ end
- describe "#{field} validation", :js do
- it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
- fill_in field, with: 'u' * max_length
+ describe "#{field} validation", :js do
+ it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do
+ fill_in field, with: 'u' * max_length
- expect(find('.name')).not_to have_css '.gl-field-error-outline'
- end
+ expect(find('.name')).not_to have_css '.gl-field-error-outline'
+ end
- it 'shows an error border if the user\'s fullname contains an emoji' do
- simulate_input("##{field}", 'Ehsan 🦋')
+ it 'shows an error border if the user\'s fullname contains an emoji' do
+ simulate_input("##{field}", 'Ehsan 🦋')
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
- it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
- fill_in field, with: 'n' * (max_length + 1)
+ it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
- expect(find('.name')).to have_css '.gl-field-error-outline'
- end
+ expect(find('.name')).to have_css '.gl-field-error-outline'
+ end
- it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do
- fill_in field, with: 'n' * (max_length + 1)
+ it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do
+ fill_in field, with: 'n' * (max_length + 1)
- expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).")
- end
+ expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).")
+ end
- it 'shows an error message if the username contains emojis' do
- simulate_input("##{field}", 'Ehsan 🦋')
+ it 'shows an error message if the username contains emojis' do
+ simulate_input("##{field}", 'Ehsan 🦋')
- expect(page).to have_content("Invalid input, please avoid emojis")
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
end
end
end
@@ -43,10 +47,6 @@ end
RSpec.describe 'Signup' do
include TermsHelper
- before do
- stub_application_setting(require_admin_approval_after_user_signup: false)
- end
-
let(:new_user) { build_stubbed(:user) }
def fill_in_signup_form
@@ -63,214 +63,309 @@ RSpec.describe 'Signup' do
visit user_confirmation_path(confirmation_token: new_user_token)
end
- describe 'username validation', :js do
+ flag_values = [true, false]
+ flag_values.each do |val|
before do
- visit new_user_registration_path
+ stub_feature_flags(restyle_login_page: val)
+ stub_application_setting(require_admin_approval_after_user_signup: false)
end
- it 'does not show an error border if the username is available' do
- fill_in 'new_user_username', with: 'new-user'
- wait_for_requests
+ describe 'username validation', :js do
+ before do
+ visit new_user_registration_path
+ end
- expect(find('.username')).not_to have_css '.gl-field-error-outline'
- end
+ it 'does not show an error border if the username is available' do
+ fill_in 'new_user_username', with: 'new-user'
+ wait_for_requests
- it 'does not show an error border if the username contains dots (.)' do
- simulate_input('#new_user_username', 'new.user.username')
- wait_for_requests
+ expect(find('.username')).not_to have_css '.gl-field-error-outline'
+ end
- expect(find('.username')).not_to have_css '.gl-field-error-outline'
- end
+ it 'does not show an error border if the username contains dots (.)' do
+ simulate_input('#new_user_username', 'new.user.username')
+ wait_for_requests
- it 'does not show an error border if the username length is not longer than 255 characters' do
- fill_in 'new_user_username', with: 'u' * 255
- wait_for_requests
+ expect(find('.username')).not_to have_css '.gl-field-error-outline'
+ end
- expect(find('.username')).not_to have_css '.gl-field-error-outline'
- end
+ it 'does not show an error border if the username length is not longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 255
+ wait_for_requests
- it 'shows an error border if the username already exists' do
- existing_user = create(:user)
+ expect(find('.username')).not_to have_css '.gl-field-error-outline'
+ end
- fill_in 'new_user_username', with: existing_user.username
- wait_for_requests
+ it 'shows an error border if the username already exists' do
+ existing_user = create(:user)
- expect(find('.username')).to have_css '.gl-field-error-outline'
- end
+ fill_in 'new_user_username', with: existing_user.username
+ wait_for_requests
- it 'shows a success border if the username is available' do
- fill_in 'new_user_username', with: 'new-user'
- wait_for_requests
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
- expect(find('.username')).to have_css '.gl-field-success-outline'
- end
+ it 'shows a success border if the username is available' do
+ fill_in 'new_user_username', with: 'new-user'
+ wait_for_requests
- it 'shows an error border if the username contains special characters' do
- fill_in 'new_user_username', with: 'new$user!username'
- wait_for_requests
+ expect(find('.username')).to have_css '.gl-field-success-outline'
+ end
- expect(find('.username')).to have_css '.gl-field-error-outline'
- end
+ it 'shows an error border if the username contains special characters' do
+ fill_in 'new_user_username', with: 'new$user!username'
+ wait_for_requests
- it 'shows an error border if the username is longer than 255 characters' do
- fill_in 'new_user_username', with: 'u' * 256
- wait_for_requests
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
- expect(find('.username')).to have_css '.gl-field-error-outline'
- end
+ it 'shows an error border if the username is longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 256
+ wait_for_requests
- it 'shows an error message if the username is longer than 255 characters' do
- fill_in 'new_user_username', with: 'u' * 256
- wait_for_requests
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
- expect(page).to have_content("Username is too long (maximum is 255 characters).")
- end
+ it 'shows an error message if the username is longer than 255 characters' do
+ fill_in 'new_user_username', with: 'u' * 256
+ wait_for_requests
- it 'shows an error message if the username is less than 2 characters' do
- fill_in 'new_user_username', with: 'u'
- wait_for_requests
+ expect(page).to have_content("Username is too long (maximum is 255 characters).")
+ end
- expect(page).to have_content("Username is too short (minimum is 2 characters).")
- end
+ it 'shows an error message if the username is less than 2 characters' do
+ fill_in 'new_user_username', with: 'u'
+ wait_for_requests
- it 'shows an error message on submit if the username contains special characters' do
- fill_in 'new_user_username', with: 'new$user!username'
- wait_for_requests
+ expect(page).to have_content("Username is too short (minimum is 2 characters).")
+ end
- click_button "Register"
+ it 'shows an error message on submit if the username contains special characters' do
+ fill_in 'new_user_username', with: 'new$user!username'
+ wait_for_requests
- expect(page).to have_content("Please create a username with only alphanumeric characters.")
- end
+ click_button "Register"
- it 'shows an error border if the username contains emojis' do
- simulate_input('#new_user_username', 'ehsan😀')
+ expect(page).to have_content("Please create a username with only alphanumeric characters.")
+ end
- expect(find('.username')).to have_css '.gl-field-error-outline'
- end
+ it 'shows an error border if the username contains emojis' do
+ simulate_input('#new_user_username', 'ehsan😀')
- it 'shows an error message if the username contains emojis' do
- simulate_input('#new_user_username', 'ehsan😀')
+ expect(find('.username')).to have_css '.gl-field-error-outline'
+ end
- expect(page).to have_content("Invalid input, please avoid emojis")
- end
+ it 'shows an error message if the username contains emojis' do
+ simulate_input('#new_user_username', 'ehsan😀')
- it 'shows a pending message if the username availability is being fetched', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31484' do
- fill_in 'new_user_username', with: 'new-user'
+ expect(page).to have_content("Invalid input, please avoid emojis")
+ end
- expect(find('.username > .validation-pending')).not_to have_css '.hide'
- end
+ it 'shows a pending message if the username availability is being fetched', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/31484' do
+ fill_in 'new_user_username', with: 'new-user'
- it 'shows a success message if the username is available' do
- fill_in 'new_user_username', with: 'new-user'
- wait_for_requests
+ expect(find('.username > .validation-pending')).not_to have_css '.hide'
+ end
- expect(find('.username > .validation-success')).not_to have_css '.hide'
- end
+ it 'shows a success message if the username is available' do
+ fill_in 'new_user_username', with: 'new-user'
+ wait_for_requests
- it 'shows an error message if the username is unavailable' do
- existing_user = create(:user)
+ expect(find('.username > .validation-success')).not_to have_css '.hide'
+ end
- fill_in 'new_user_username', with: existing_user.username
- wait_for_requests
+ it 'shows an error message if the username is unavailable' do
+ existing_user = create(:user)
- expect(find('.username > .validation-error')).not_to have_css '.hide'
- end
+ fill_in 'new_user_username', with: existing_user.username
+ wait_for_requests
- it 'shows a success message if the username is corrected and then available' do
- fill_in 'new_user_username', with: 'new-user$'
- wait_for_requests
- fill_in 'new_user_username', with: 'new-user'
- wait_for_requests
+ expect(find('.username > .validation-error')).not_to have_css '.hide'
+ end
- expect(page).to have_content("Username is available.")
+ it 'shows a success message if the username is corrected and then available' do
+ fill_in 'new_user_username', with: 'new-user$'
+ wait_for_requests
+ fill_in 'new_user_username', with: 'new-user'
+ wait_for_requests
+
+ expect(page).to have_content("Username is available.")
+ end
end
- end
- context 'with no errors' do
- context 'when sending confirmation email' do
- before do
- stub_application_setting(send_user_confirmation_email: true)
+ context 'with no errors' do
+ context 'when sending confirmation email' do
+ before do
+ stub_application_setting(send_user_confirmation_email: true)
+ end
+
+ context 'when soft email confirmation is not enabled' do
+ before do
+ stub_feature_flags(soft_email_confirmation: false)
+ end
+
+ it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do
+ visit new_user_registration_path
+
+ fill_in_signup_form
+
+ expect { click_button 'Register' }.to change { User.count }.by(1)
+ expect(page).to have_current_path users_almost_there_path, ignore_query: true
+ expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account")
+
+ confirm_email
+
+ expect(find_field('Username or email').value).to eq(new_user.email)
+ end
+ end
+
+ context 'when soft email confirmation is enabled' do
+ before do
+ stub_feature_flags(soft_email_confirmation: true)
+ end
+
+ it 'creates the user account and sends a confirmation email' do
+ visit new_user_registration_path
+
+ fill_in_signup_form
+
+ expect { click_button 'Register' }.to change { User.count }.by(1)
+ expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
+ end
+ end
end
- context 'when soft email confirmation is not enabled' do
+ context "when not sending confirmation email" do
before do
- stub_feature_flags(soft_email_confirmation: false)
+ stub_application_setting(send_user_confirmation_email: false)
end
- it 'creates the user account and sends a confirmation email, and pre-fills email address after confirming' do
+ it 'creates the user account and goes to dashboard' do
visit new_user_registration_path
fill_in_signup_form
+ click_button "Register"
- expect { click_button 'Register' }.to change { User.count }.by(1)
- expect(page).to have_current_path users_almost_there_path, ignore_query: true
- expect(page).to have_content("Please check your email (#{new_user.email}) to confirm your account")
-
- confirm_email
-
- expect(find_field('Username or email').value).to eq(new_user.email)
+ expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
end
end
- context 'when soft email confirmation is enabled' do
+ context 'with required admin approval enabled' do
before do
- stub_feature_flags(soft_email_confirmation: true)
+ stub_application_setting(require_admin_approval_after_user_signup: true)
end
- it 'creates the user account and sends a confirmation email' do
+ it 'creates the user but does not sign them in' do
visit new_user_registration_path
fill_in_signup_form
expect { click_button 'Register' }.to change { User.count }.by(1)
- expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
+ expect(page).to have_current_path new_user_session_path, ignore_query: true
+ expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator")
end
end
end
- context "when not sending confirmation email" do
- before do
- stub_application_setting(send_user_confirmation_email: false)
+ context 'with errors' do
+ it "displays the errors" do
+ create(:user, email: new_user.email)
+ visit new_user_registration_path
+
+ fill_in_signup_form
+ click_button "Register"
+
+ expect(page).to have_current_path user_registration_path, ignore_query: true
+ expect(page).to have_content("error prohibited this user from being saved")
+ expect(page).to have_content("Email has already been taken")
end
- it 'creates the user account and goes to dashboard' do
+ it 'does not redisplay the password' do
+ create(:user, email: new_user.email)
visit new_user_registration_path
fill_in_signup_form
click_button "Register"
- expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
+ expect(page).to have_current_path user_registration_path, ignore_query: true
+ expect(page.body).not_to match(/#{new_user.password}/)
end
end
- context 'with required admin approval enabled' do
+ context 'when terms are enforced' do
before do
- stub_application_setting(require_admin_approval_after_user_signup: true)
+ enforce_terms
end
- it 'creates the user but does not sign them in' do
+ it 'renders text that the user confirms terms by clicking register' do
visit new_user_registration_path
+ expect(page).to have_content(/By clicking Register, I agree that I have read and accepted the Terms of Use and Privacy Policy/)
+
fill_in_signup_form
+ click_button 'Register'
- expect { click_button 'Register' }.to change { User.count }.by(1)
- expect(page).to have_current_path new_user_session_path, ignore_query: true
- expect(page).to have_content("You have signed up successfully. However, we could not sign you in because your account is awaiting approval from your GitLab administrator")
+ expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
end
end
- end
- context 'with errors' do
- it "displays the errors" do
- create(:user, email: new_user.email)
+ context 'when reCAPTCHA and invisible captcha are enabled' do
+ before do
+ stub_application_setting(invisible_captcha_enabled: true)
+ stub_application_setting(recaptcha_enabled: true)
+ allow_next_instance_of(RegistrationsController) do |instance|
+ allow(instance).to receive(:verify_recaptcha).and_return(true)
+ end
+ end
+
+ context 'when reCAPTCHA detects malicious behaviour' do
+ before do
+ allow_next_instance_of(RegistrationsController) do |instance|
+ allow(instance).to receive(:verify_recaptcha).and_return(false)
+ end
+ end
+
+ it 'prevents from signing up' do
+ visit new_user_registration_path
+
+ fill_in_signup_form
+
+ expect { click_button 'Register' }.not_to change { User.count }
+ expect(page).to have_content(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
+ end
+ end
+
+ context 'when invisible captcha detects malicious behaviour' do
+ it 'prevents from signing up' do
+ visit new_user_registration_path
+
+ fill_in_signup_form
+
+ expect { click_button 'Register' }.not_to change { User.count }
+ expect(page).to have_content('That was a bit too quick! Please resubmit.')
+ end
+ end
+ 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
- click_button "Register"
+ click_button 'Register'
- expect(page).to have_current_path user_registration_path, ignore_query: true
- expect(page).to have_content("error prohibited this user from being saved")
- expect(page).to have_content("Email has already been taken")
+ visit new_project_path
+
+ expect(page).to have_current_path(users_sign_up_welcome_path)
+
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+
+ created_user = User.find_by_username(new_user.username)
+
+ expect(created_user.software_developer_role?).to be_truthy
+ expect(created_user.setup_for_company).to be_nil
+ expect(page).to have_current_path(new_project_path)
end
it 'does not redisplay the password' do
@@ -283,6 +378,12 @@ RSpec.describe 'Signup' do
expect(page).to have_current_path user_registration_path, ignore_query: true
expect(page.body).not_to match(/#{new_user.password}/)
end
+
+ context 'with invalid email', :saas, :js do
+ it_behaves_like 'user email validation' do
+ let(:path) { new_user_registration_path }
+ end
+ end
end
context 'when terms are enforced' do
@@ -298,69 +399,21 @@ RSpec.describe 'Signup' do
fill_in_signup_form
click_button 'Register'
- expect(page).to have_current_path users_sign_up_welcome_path, ignore_query: true
- end
- end
-
- context 'when reCAPTCHA and invisible captcha are enabled' do
- before do
- stub_application_setting(invisible_captcha_enabled: true)
- stub_application_setting(recaptcha_enabled: true)
- allow_next_instance_of(RegistrationsController) do |instance|
- allow(instance).to receive(:verify_recaptcha).and_return(true)
- end
- end
-
- context 'when reCAPTCHA detects malicious behaviour' do
- before do
- allow_next_instance_of(RegistrationsController) do |instance|
- allow(instance).to receive(:verify_recaptcha).and_return(false)
- end
- end
-
- it 'prevents from signing up' do
- visit new_user_registration_path
+ visit new_project_path
- fill_in_signup_form
+ expect(page).to have_current_path(users_sign_up_welcome_path)
- expect { click_button 'Register' }.not_to change { User.count }
- expect(page).to have_content(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
- end
- end
-
- context 'when invisible captcha detects malicious behaviour' do
- it 'prevents from signing up' do
- visit new_user_registration_path
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
- fill_in_signup_form
+ created_user = User.find_by_username(new_user.username)
- expect { click_button 'Register' }.not_to change { User.count }
- expect(page).to have_content('That was a bit too quick! Please resubmit.')
- end
+ expect(created_user.software_developer_role?).to be_truthy
+ expect(created_user.setup_for_company).to be_nil
+ expect(page).to have_current_path(new_project_path)
end
- 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
- click_button 'Register'
-
- visit new_project_path
- expect(page).to have_current_path(users_sign_up_welcome_path)
-
- select 'Software Developer', from: 'user_role'
- click_button 'Get started!'
-
- created_user = User.find_by_username(new_user.username)
-
- expect(created_user.software_developer_role?).to be_truthy
- expect(created_user.setup_for_company).to be_nil
- expect(page).to have_current_path(new_project_path)
+ it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name'
+ it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name'
end
-
- it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name'
- it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name'
end
diff --git a/spec/finders/autocomplete/deploy_keys_with_write_access_finder_spec.rb b/spec/finders/autocomplete/deploy_keys_with_write_access_finder_spec.rb
new file mode 100644
index 00000000000..ed3b1d2d0bf
--- /dev/null
+++ b/spec/finders/autocomplete/deploy_keys_with_write_access_finder_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Autocomplete::DeployKeysWithWriteAccessFinder do
+ let_it_be(:user) { create(:user) }
+
+ let(:finder) { described_class.new(user, project) }
+
+ describe '#execute' do
+ subject(:execute) { finder.execute }
+
+ context 'when project is missing' do
+ let(:project) { nil }
+
+ it 'returns an empty ActiveRecord::Relation' do
+ expect(execute).to eq(DeployKey.none)
+ end
+ end
+
+ context 'when project is present' do
+ let_it_be(:project) { create(:project, :public) }
+
+ context 'and current user cannot admin project' do
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+
+ context 'and current user can admin project' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when deploy key does not have write access to project' do
+ let(:deploy_key_project) { create(:deploy_keys_project, project: project) }
+
+ it 'returns an empty ActiveRecord::Relation' do
+ expect(execute).to eq(DeployKey.none)
+ end
+ end
+
+ context 'when deploy key has write access to project' do
+ let(:deploy_key_project) { create(:deploy_keys_project, :write_access, project: project) }
+
+ it 'returns the deploy keys' do
+ expect(execute).to match_array([deploy_key_project.deploy_key])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index aeab5a51766..96412c1e371 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -92,10 +92,8 @@ RSpec.describe Ci::RunnersFinder do
context 'set to an invalid value' do
let(:upgrade_status) { :some_invalid_status }
- it 'does not call with_upgrade_status' do
- expect(Ci::Runner).not_to receive(:with_upgrade_status)
-
- expect(execute).to match_array(Ci::Runner.all)
+ it 'raises ArgumentError' do
+ expect { execute }.to raise_error(ArgumentError)
end
end
diff --git a/spec/finders/clusters/knative_services_finder_spec.rb b/spec/finders/clusters/knative_services_finder_spec.rb
index c61fac27bd9..6f5a4db10e8 100644
--- a/spec/finders/clusters/knative_services_finder_spec.rb
+++ b/spec/finders/clusters/knative_services_finder_spec.rb
@@ -88,6 +88,7 @@ RSpec.describe Clusters::KnativeServicesFinder do
end
it { is_expected.to be_truthy }
+
it "discovers knative installation" do
expect { subject }
.to change { finder.cluster.kubeclient.knative_client.discovered }
@@ -102,6 +103,7 @@ RSpec.describe Clusters::KnativeServicesFinder do
end
it { is_expected.to be_falsy }
+
it "does not discover knative installation" do
expect { subject }.not_to change { cluster.kubeclient.knative_client.discovered }
end
diff --git a/spec/finders/concerns/finder_with_cross_project_access_spec.rb b/spec/finders/concerns/finder_with_cross_project_access_spec.rb
index 0798528c200..a4b483a8e5e 100644
--- a/spec/finders/concerns/finder_with_cross_project_access_spec.rb
+++ b/spec/finders/concerns/finder_with_cross_project_access_spec.rb
@@ -97,7 +97,11 @@ RSpec.describe FinderWithCrossProjectAccess do
end
it 're-enables the check after the find failed' do
- finder.find(non_existing_record_id) rescue ActiveRecord::RecordNotFound
+ begin
+ finder.find(non_existing_record_id)
+ rescue ActiveRecord::RecordNotFound
+ nil
+ end
expect(finder.instance_variable_get(:@should_skip_cross_project_check))
.to eq(false)
diff --git a/spec/finders/crm/contacts_finder_spec.rb b/spec/finders/crm/contacts_finder_spec.rb
index dd5274a0574..43dcced53fd 100644
--- a/spec/finders/crm/contacts_finder_spec.rb
+++ b/spec/finders/crm/contacts_finder_spec.rb
@@ -141,6 +141,67 @@ RSpec.describe Crm::ContactsFinder do
expect(finder.execute).to match_array([search_test_b])
end
end
+
+ context 'when sorting' do
+ let_it_be(:search_test_c) do
+ create(
+ :contact,
+ group: search_test_group,
+ email: "a@test.com",
+ organization: create(:organization, name: "Company Z")
+ )
+ end
+
+ let_it_be(:search_test_d) do
+ create(
+ :contact,
+ group: search_test_group,
+ email: "b@test.com",
+ organization: create(:organization, name: "Company A")
+ )
+ end
+
+ it 'returns the contacts sorted by email in ascending order' do
+ finder = described_class.new(user, group: search_test_group, sort: { field: 'email', direction: :asc })
+
+ expect(finder.execute).to eq([search_test_c, search_test_d, search_test_a, search_test_b])
+ end
+
+ it 'returns the contacts sorted by description in ascending order' do
+ finder = described_class.new(user, group: search_test_group, sort: { field: 'description', direction: :desc })
+
+ results = finder.execute
+
+ expect(results[0]).to eq(search_test_b)
+ expect(results[1]).to eq(search_test_a)
+ end
+
+ it 'returns the contacts sorted by organization in ascending order' do
+ finder = described_class.new(user, group: search_test_group, sort: { field: 'organization', direction: :asc })
+
+ results = finder.execute
+
+ expect(results[0]).to eq(search_test_d)
+ expect(results[1]).to eq(search_test_c)
+ end
+ end
+ end
+ end
+
+ describe '.counts_by_state' do
+ let_it_be(:group) { create(:group, :crm_enabled) }
+ let_it_be(:active_contacts) { create_list(:contact, 3, group: group, state: :active) }
+ let_it_be(:inactive_contacts) { create_list(:contact, 2, group: group, state: :inactive) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it 'returns correct counts' do
+ counts = described_class.counts_by_state(user, group: group)
+
+ expect(counts["active"]).to eq(3)
+ expect(counts["inactive"]).to eq(2)
end
end
end
diff --git a/spec/finders/fork_targets_finder_spec.rb b/spec/finders/fork_targets_finder_spec.rb
index fe5b50ef030..1acc38bb492 100644
--- a/spec/finders/fork_targets_finder_spec.rb
+++ b/spec/finders/fork_targets_finder_spec.rb
@@ -5,27 +5,27 @@ require 'spec_helper'
RSpec.describe ForkTargetsFinder do
subject(:finder) { described_class.new(project, user) }
- let(:project) { create(:project, namespace: create(:group)) }
- let(:user) { create(:user) }
- let!(:maintained_group) do
+ let_it_be(:project) { create(:project, namespace: create(:group)) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:maintained_group) do
create(:group).tap { |g| g.add_maintainer(user) }
end
- let!(:owned_group) do
+ let_it_be(:owned_group) do
create(:group).tap { |g| g.add_owner(user) }
end
- let!(:developer_group) do
+ let_it_be(:developer_group) do
create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS).tap do |g|
g.add_developer(user)
end
end
- let!(:reporter_group) do
+ let_it_be(:reporter_group) do
create(:group).tap { |g| g.add_reporter(user) }
end
- let!(:guest_group) do
+ let_it_be(:guest_group) do
create(:group).tap { |g| g.add_guest(user) }
end
@@ -33,7 +33,7 @@ RSpec.describe ForkTargetsFinder do
project.namespace.add_owner(user)
end
- describe '#execute' do
+ shared_examples 'returns namespaces and groups' do
it 'returns all user manageable namespaces' do
expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace, developer_group])
end
@@ -46,4 +46,28 @@ RSpec.describe ForkTargetsFinder do
expect(finder.execute(only_groups: true)).to include(a_kind_of(Group))
end
end
+
+ describe '#execute' do
+ it_behaves_like 'returns namespaces and groups'
+
+ context 'when search is provided' do
+ it 'filters the targets by the param' do
+ expect(finder.execute(search: maintained_group.path)).to eq([maintained_group])
+ end
+ end
+
+ context 'when searchable_fork_targets feature flag is disabled' do
+ before do
+ stub_feature_flags(searchable_fork_targets: false)
+ end
+
+ it_behaves_like 'returns namespaces and groups'
+
+ context 'when search is provided' do
+ it 'ignores the param and returns all user manageable namespaces' do
+ expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace, developer_group])
+ end
+ end
+ end
+ end
end
diff --git a/spec/finders/groups/accepting_project_transfers_finder_spec.rb b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
new file mode 100644
index 00000000000..e73318c763f
--- /dev/null
+++ b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::AcceptingProjectTransfersFinder do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group_where_direct_owner) { create(:group) }
+ let_it_be(:subgroup_of_group_where_direct_owner) { create(:group, parent: group_where_direct_owner) }
+ let_it_be(:group_where_direct_maintainer) { create(:group) }
+ let_it_be(:group_where_direct_maintainer_but_cant_create_projects) do
+ create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS)
+ end
+
+ let_it_be(:group_where_direct_developer) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_owner_as_owner) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_owner_as_guest) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_owner_as_maintainer) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_developer_as_owner) { create(:group) }
+ let_it_be(:subgroup_of_shared_with_group_where_direct_owner_as_maintainer) do
+ create(:group, parent: shared_with_group_where_direct_owner_as_maintainer)
+ end
+
+ before do
+ group_where_direct_owner.add_owner(user)
+ group_where_direct_maintainer.add_maintainer(user)
+ group_where_direct_developer.add_developer(user)
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_owner
+ )
+
+ create(:group_group_link, :guest,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_guest
+ )
+
+ create(:group_group_link, :maintainer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_maintainer
+ )
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_developer,
+ shared_group: shared_with_group_where_direct_developer_as_owner
+ )
+ end
+
+ describe '#execute' do
+ subject(:result) { described_class.new(user).execute }
+
+ it 'only returns groups where the user has access to transfer projects to' do
+ expect(result).to match_array([
+ group_where_direct_owner,
+ subgroup_of_group_where_direct_owner,
+ group_where_direct_maintainer,
+ shared_with_group_where_direct_owner_as_owner,
+ shared_with_group_where_direct_owner_as_maintainer,
+ subgroup_of_shared_with_group_where_direct_owner_as_maintainer
+ ])
+ end
+ end
+end
diff --git a/spec/finders/groups/user_groups_finder_spec.rb b/spec/finders/groups/user_groups_finder_spec.rb
index 9339741da79..999079468e5 100644
--- a/spec/finders/groups/user_groups_finder_spec.rb
+++ b/spec/finders/groups/user_groups_finder_spec.rb
@@ -5,17 +5,19 @@ require 'spec_helper'
RSpec.describe Groups::UserGroupsFinder do
describe '#execute' do
let_it_be(:user) { create(:user) }
+ let_it_be(:root_group) { create(:group, name: 'Root group', path: 'root-group') }
let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') }
- let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer') }
- let_it_be(:public_developer_group) { create(:group, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') }
- let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer') }
+ let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_group) }
+ let_it_be(:public_developer_group) { create(:group, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer', parent: root_group) }
+ let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_group) }
let_it_be(:public_owner_group) { create(:group, name: 'a public owner', path: 'a-public-owner') }
- subject { described_class.new(current_user, target_user, arguments).execute }
+ subject { described_class.new(current_user, target_user, arguments.merge(search_arguments)).execute }
let(:arguments) { {} }
let(:current_user) { user }
let(:target_user) { user }
+ let(:search_arguments) { {} }
before_all do
guest_group.add_guest(user)
@@ -25,15 +27,40 @@ RSpec.describe Groups::UserGroupsFinder do
public_owner_group.add_owner(user)
end
- it 'returns all groups where the user is a direct member' do
- is_expected.to match(
- [
+ shared_examples 'user group finder searching by name or path' do
+ let(:search_arguments) { { search: 'maintainer' } }
+
+ specify do
+ is_expected.to contain_exactly(
public_maintainer_group,
- public_owner_group,
- private_maintainer_group,
- public_developer_group,
- guest_group
- ]
+ private_maintainer_group
+ )
+ end
+
+ context 'when searching for a full path (including parent)' do
+ let(:search_arguments) { { search: 'root-group/b-private-maintainer' } }
+
+ specify do
+ is_expected.to contain_exactly(private_maintainer_group)
+ end
+ end
+
+ context 'when search keywords include the parent route' do
+ let(:search_arguments) { { search: 'root public' } }
+
+ specify do
+ is_expected.to match(keyword_search_expected_groups)
+ end
+ end
+ end
+
+ it 'returns all groups where the user is a direct member' do
+ is_expected.to contain_exactly(
+ public_maintainer_group,
+ public_owner_group,
+ private_maintainer_group,
+ public_developer_group,
+ guest_group
)
end
@@ -53,26 +80,20 @@ RSpec.describe Groups::UserGroupsFinder do
let(:arguments) { { permission_scope: :create_projects } }
specify do
- is_expected.to match(
+ is_expected.to contain_exactly(
+ public_maintainer_group,
+ public_owner_group,
+ private_maintainer_group,
+ public_developer_group
+ )
+ end
+
+ it_behaves_like 'user group finder searching by name or path' do
+ let(:keyword_search_expected_groups) do
[
public_maintainer_group,
- public_owner_group,
- private_maintainer_group,
public_developer_group
]
- )
- end
-
- context 'when search is provided' do
- let(:arguments) { { permission_scope: :create_projects, search: 'maintainer' } }
-
- specify do
- is_expected.to match(
- [
- public_maintainer_group,
- private_maintainer_group
- ]
- )
end
end
end
@@ -81,38 +102,15 @@ RSpec.describe Groups::UserGroupsFinder do
let(:arguments) { { permission_scope: :transfer_projects } }
specify do
- is_expected.to match(
- [
- public_maintainer_group,
- public_owner_group,
- private_maintainer_group
- ]
+ is_expected.to contain_exactly(
+ public_maintainer_group,
+ public_owner_group,
+ private_maintainer_group
)
end
- context 'when search is provided' do
- let(:arguments) { { permission_scope: :transfer_projects, search: 'owner' } }
-
- specify do
- is_expected.to match(
- [
- public_owner_group
- ]
- )
- end
- end
- end
-
- context 'when search is provided' do
- let(:arguments) { { search: 'maintainer' } }
-
- specify do
- is_expected.to match(
- [
- public_maintainer_group,
- private_maintainer_group
- ]
- )
+ it_behaves_like 'user group finder searching by name or path' do
+ let(:keyword_search_expected_groups) { [public_maintainer_group] }
end
end
end
diff --git a/spec/finders/projects/topics_finder_spec.rb b/spec/finders/projects/topics_finder_spec.rb
index 3812f0757bc..d6e90e5958f 100644
--- a/spec/finders/projects/topics_finder_spec.rb
+++ b/spec/finders/projects/topics_finder_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe Projects::TopicsFinder do
let_it_be(:user) { create(:user) }
- let!(:topic1) { create(:topic, name: 'topicB') }
- let!(:topic2) { create(:topic, name: 'topicC') }
- let!(:topic3) { create(:topic, name: 'topicA') }
+ let_it_be(:topic1) { create(:topic, name: 'topicB') }
+ let_it_be(:topic2) { create(:topic, name: 'topicC') }
+ let_it_be(:topic3) { create(:topic, name: 'topicA') }
- let!(:project1) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC, topicA, topicB') }
- let!(:project2) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC, topicA') }
- let!(:project3) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC') }
+ let_it_be(:project1) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC, topicA, topicB') }
+ let_it_be(:project2) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC, topicA') }
+ let_it_be(:project3) { create(:project, :public, namespace: user.namespace, topic_list: 'topicC') }
describe '#execute' do
it 'returns topics' do
@@ -41,5 +41,21 @@ RSpec.describe Projects::TopicsFinder do
end
end
end
+
+ context 'filter by without_projects' do
+ let_it_be(:topic4) { create(:topic, name: 'unassigned topic') }
+
+ it 'returns topics without assigned projects' do
+ topics = described_class.new(params: { without_projects: true }).execute
+
+ expect(topics).to contain_exactly(topic4)
+ end
+
+ it 'returns topics without assigned projects' do
+ topics = described_class.new(params: { without_projects: false }).execute
+
+ expect(topics).to contain_exactly(topic1, topic2, topic3, topic4)
+ end
+ end
end
end
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
index 70d79ced81d..0bf9b228c8a 100644
--- a/spec/finders/tags_finder_spec.rb
+++ b/spec/finders/tags_finder_spec.rb
@@ -175,6 +175,16 @@ RSpec.describe TagsFinder do
end
end
end
+
+ context 'pagination and search' do
+ let(:params) { { search: '1.1.1', per_page: 1 } }
+
+ it 'ignores the pagination for search' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.1))
+ end
+ end
end
context 'when Gitaly is unavailable' do
diff --git a/spec/fixtures/api/schemas/entities/discussion.json b/spec/fixtures/api/schemas/entities/discussion.json
index efc31a4f833..da2d2a83a8d 100644
--- a/spec/fixtures/api/schemas/entities/discussion.json
+++ b/spec/fixtures/api/schemas/entities/discussion.json
@@ -67,7 +67,8 @@
"toggle_award_path": { "type": "string" },
"path": { "type": "string" },
"commands_changes": { "type": "object", "additionalProperties": true },
- "confidential": { "type": ["boolean", "null"] }
+ "confidential": { "type": ["boolean", "null"] },
+ "internal": { "type": ["boolean", "null"] }
},
"required": [
"id", "attachment", "author", "created_at", "updated_at",
diff --git a/spec/fixtures/api/schemas/external_validation.json b/spec/fixtures/api/schemas/external_validation.json
index ddcabd4c61e..4a2538a020e 100644
--- a/spec/fixtures/api/schemas/external_validation.json
+++ b/spec/fixtures/api/schemas/external_validation.json
@@ -4,7 +4,8 @@
"project",
"user",
"pipeline",
- "builds"
+ "builds",
+ "total_builds_count"
],
"properties" : {
"project": {
@@ -80,6 +81,7 @@
}
}
}
- }
+ },
+ "total_builds_count": { "type": "integer" }
}
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/notes.json b/spec/fixtures/api/schemas/public_api/v4/notes.json
index 25e8f9cbed6..d6d0300a64f 100644
--- a/spec/fixtures/api/schemas/public_api/v4/notes.json
+++ b/spec/fixtures/api/schemas/public_api/v4/notes.json
@@ -32,7 +32,8 @@
"resolvable": { "type": "boolean" },
"resolved_by": { "type": ["string", "null"] },
"resolved_at": { "type": ["string", "null"] },
- "confidential": { "type": ["boolean", "null"] }
+ "confidential": { "type": ["boolean", "null"] },
+ "internal": { "type": ["boolean", "null"] }
},
"required": [
"id", "body", "attachment", "author", "created_at", "updated_at",
diff --git a/spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz b/spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz
index e99136e96b7..d6632c5121a 100644
--- a/spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz
+++ b/spec/fixtures/gitlab/import_export/corrupted_project_export.tar.gz
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/100_files.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/100_files.zip
new file mode 100644
index 00000000000..31124abc0e5
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/100_files.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/200_mb_decompressed.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/200_mb_decompressed.zip
new file mode 100644
index 00000000000..8c56cce641a
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/200_mb_decompressed.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/multiple_files.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/multiple_files.zip
new file mode 100644
index 00000000000..09ac4e5df51
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/multiple_files.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/single_file.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/single_file.zip
new file mode 100644
index 00000000000..81768a9f2b3
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/single_file.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/with_directory.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/with_directory.zip
new file mode 100644
index 00000000000..6de321ea86a
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/with_directory.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/zipbomb.zip b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/zipbomb.zip
new file mode 100644
index 00000000000..b8cfcef9739
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/ci/build/artifacts/adapters/zip_stream/zipbomb.zip
Binary files differ
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index 12dbabf833b..5bcf6521471 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -3149,6 +3149,72 @@
"created_at": "2020-01-07T11:21:21.235Z",
"updated_at": "2020-01-07T11:21:21.235Z"
}
+ ],
+ "merge_request_assignees": [
+ {
+ "user_id": 1,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "state": "unreviewed"
+ },
+ {
+ "user_id": 15,
+ "created_at": "2020-01-08T11:21:21.235Z",
+ "state": "reviewed"
+ },
+ {
+ "user_id": 16,
+ "created_at": "2020-01-09T11:21:21.235Z",
+ "state": "attention_requested"
+ },
+ {
+ "user_id": 6,
+ "created_at": "2020-01-10T11:21:21.235Z",
+ "state": "unreviewed"
+ }
+ ],
+ "merge_request_reviewers": [
+ {
+ "user_id": 1,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "state": "unreviewed"
+ },
+ {
+ "user_id": 15,
+ "created_at": "2020-01-08T11:21:21.235Z",
+ "state": "reviewed"
+ },
+ {
+ "user_id": 16,
+ "created_at": "2020-01-09T11:21:21.235Z",
+ "state": "attention_requested"
+ },
+ {
+ "user_id": 6,
+ "created_at": "2020-01-10T11:21:21.235Z",
+ "state": "unreviewed"
+ }
+ ],
+ "approvals": [
+ {
+ "user_id": 1,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "updated_at": "2020-01-08T11:21:21.235Z"
+ },
+ {
+ "user_id": 15,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "updated_at": "2020-01-08T11:21:21.235Z"
+ },
+ {
+ "user_id": 16,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "updated_at": "2020-01-08T11:21:21.235Z"
+ },
+ {
+ "user_id": 6,
+ "created_at": "2020-01-07T11:21:21.235Z",
+ "updated_at": "2020-01-08T11:21:21.235Z"
+ }
]
},
{
@@ -3416,7 +3482,10 @@
"action": 1,
"author_id": 1
}
- ]
+ ],
+ "merge_request_assignees": [],
+ "merge_request_reviewers": [],
+ "approvals": []
},
{
"id": 15,
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
index 16e45509a1b..c14221adc1c 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
+++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/merge_requests.ndjson
@@ -1,5 +1,5 @@
-{"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},"merge_when_pipeline_succeeds":true,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":669,"note":"added 3 commits\n\n<ul><li>16ea4e20...074a2a32 - 2 commits from branch <code>master</code></li><li>ca223a02 - readme: fix typos</li></ul>\n\n[Compare with previous version](/group/project/merge_requests/1/diffs?diff_id=1189&start_sha=16ea4e207fb258fe4e9c73185a725207c9a4f3e1)","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4789,"commit_count":3,"action":"commit","created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z"},"events":[],"suggestions":[]},{"id":670,"note":"unmarked as a **Work In Progress**","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4790,"commit_count":null,"action":"title","created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z"},"events":[],"suggestions":[]},{"id":671,"note":"Sit voluptatibus eveniet architecto quidem.","note_html":"<p>something else entirely</p>","cached_markdown_version":917504,"noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.632Z","updated_at":"2016-06-14T15:02:56.632Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[],"award_emoji":[{"id":1,"name":"tada","user_id":1,"awardable_type":"Note","awardable_id":1,"created_at":"2019-11-05T15:37:21.287Z","updated_at":"2019-11-05T15:37:21.287Z"}]},{"id":672,"note":"Odio maxime ratione voluptatibus sed.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.656Z","updated_at":"2016-06-14T15:02:56.656Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":673,"note":"Et deserunt et omnis nihil excepturi accusantium.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.679Z","updated_at":"2016-06-14T15:02:56.679Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":674,"note":"Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.700Z","updated_at":"2016-06-14T15:02:56.700Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[],"suggestions":[{"id":1,"note_id":674,"relative_order":0,"applied":false,"commit_id":null,"from_content":"Original line\n","to_content":"New line\n","lines_above":0,"lines_below":0,"outdated":false}]},{"id":675,"note":"Numquam est at dolor quo et sed eligendi similique.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.720Z","updated_at":"2016-06-14T15:02:56.720Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":676,"note":"Et perferendis aliquam sunt nisi labore delectus.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.742Z","updated_at":"2016-06-14T15:02:56.742Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":677,"note":"Aut ex rerum et in.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.791Z","updated_at":"2016-06-14T15:02:56.791Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":678,"note":"Dolor laborum earum ut exercitationem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:56.814Z","updated_at":"2016-06-14T15:02:56.814Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"resource_label_events":[{"id":243,"action":"add","issue_id":null,"merge_request_id":27,"label_id":null,"user_id":1,"created_at":"2018-08-28T08:24:00.494Z"}],"merge_request_diff":{"id":27,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":27,"relative_order":0,"sha":"bb5206fee213d983da88c47f9cf4cc6caf9c66dc","message":"Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-08-06T08:35:52.000+02:00","committed_date":"2014-08-06T08:35:52.000+02:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":1,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":2,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":3,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":4,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":5,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":27,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":3,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":5,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":6,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":8,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":27,"created_at":"2016-06-14T15:02:36.572Z","updated_at":"2016-06-14T15:02:36.658Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"9"},"events":[{"id":221,"target_type":"MergeRequest","target_id":27,"project_id":36,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1},{"id":187,"target_type":"MergeRequest","target_id":27,"project_id":5,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1}],"approvals_before_merge":1,"award_emoji":[{"id":1,"name":"thumbsup","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"},{"id":2,"name":"drum","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"}]}
-{"id":26,"target_branch":"master","source_branch":"feature","source_project_id":4,"author_id":1,"assignee_id":null,"title":"MR2","created_at":"2016-06-14T15:02:36.418Z","updated_at":"2016-06-14T15:02:57.013Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":8,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":679,"note":"Qui rerum totam nisi est.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.848Z","updated_at":"2016-06-14T15:02:56.848Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":680,"note":"Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.871Z","updated_at":"2016-06-14T15:02:56.871Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":681,"note":"Qui quis ut modi eos rerum ratione.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.895Z","updated_at":"2016-06-14T15:02:56.895Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":682,"note":"Illum quidem expedita mollitia fugit.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.918Z","updated_at":"2016-06-14T15:02:56.918Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":683,"note":"Consectetur voluptate sit sint possimus veritatis quod.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.942Z","updated_at":"2016-06-14T15:02:56.942Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":684,"note":"Natus libero quibusdam rem assumenda deleniti accusamus sed earum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.966Z","updated_at":"2016-06-14T15:02:56.966Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":685,"note":"Tenetur autem nihil rerum odit.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.989Z","updated_at":"2016-06-14T15:02:56.989Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":686,"note":"Quia maiores et odio sed.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:57.012Z","updated_at":"2016-06-14T15:02:57.012Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":26,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":26,"sha":"0b4bc9a49b562e85de7cc9e834518ea6828729b9","relative_order":0,"message":"Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:26:01.000+01:00","committed_date":"2014-02-27T09:26:01.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":26,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":26,"created_at":"2016-06-14T15:02:36.421Z","updated_at":"2016-06-14T15:02:36.474Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"1"},"events":[{"id":222,"target_type":"MergeRequest","target_id":26,"project_id":36,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1},{"id":186,"target_type":"MergeRequest","target_id":26,"project_id":5,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1}]}
+{"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},"merge_when_pipeline_succeeds":true,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":669,"note":"added 3 commits\n\n<ul><li>16ea4e20...074a2a32 - 2 commits from branch <code>master</code></li><li>ca223a02 - readme: fix typos</li></ul>\n\n[Compare with previous version](/group/project/merge_requests/1/diffs?diff_id=1189&start_sha=16ea4e207fb258fe4e9c73185a725207c9a4f3e1)","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4789,"commit_count":3,"action":"commit","created_at":"2020-03-28T12:47:33.461Z","updated_at":"2020-03-28T12:47:33.461Z"},"events":[],"suggestions":[]},{"id":670,"note":"unmarked as a **Work In Progress**","noteable_type":"MergeRequest","author_id":26,"created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"system":true,"st_diff":null,"updated_by_id":null,"position":null,"original_position":null,"resolved_at":null,"resolved_by_id":null,"discussion_id":null,"change_position":null,"resolved_by_push":null,"confidential":null,"type":null,"author":{"name":"User 4"},"award_emoji":[],"system_note_metadata":{"id":4790,"commit_count":null,"action":"title","created_at":"2020-03-28T12:48:36.951Z","updated_at":"2020-03-28T12:48:36.951Z"},"events":[],"suggestions":[]},{"id":671,"note":"Sit voluptatibus eveniet architecto quidem.","note_html":"<p>something else entirely</p>","cached_markdown_version":917504,"noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.632Z","updated_at":"2016-06-14T15:02:56.632Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[],"award_emoji":[{"id":1,"name":"tada","user_id":1,"awardable_type":"Note","awardable_id":1,"created_at":"2019-11-05T15:37:21.287Z","updated_at":"2019-11-05T15:37:21.287Z"}]},{"id":672,"note":"Odio maxime ratione voluptatibus sed.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.656Z","updated_at":"2016-06-14T15:02:56.656Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":673,"note":"Et deserunt et omnis nihil excepturi accusantium.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.679Z","updated_at":"2016-06-14T15:02:56.679Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":674,"note":"Saepe asperiores exercitationem non dignissimos laborum reiciendis et ipsum.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.700Z","updated_at":"2016-06-14T15:02:56.700Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[],"suggestions":[{"id":1,"note_id":674,"relative_order":0,"applied":false,"commit_id":null,"from_content":"Original line\n","to_content":"New line\n","lines_above":0,"lines_below":0,"outdated":false}]},{"id":675,"note":"Numquam est at dolor quo et sed eligendi similique.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.720Z","updated_at":"2016-06-14T15:02:56.720Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":676,"note":"Et perferendis aliquam sunt nisi labore delectus.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.742Z","updated_at":"2016-06-14T15:02:56.742Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":677,"note":"Aut ex rerum et in.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.791Z","updated_at":"2016-06-14T15:02:56.791Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":678,"note":"Dolor laborum earum ut exercitationem.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:56.814Z","updated_at":"2016-06-14T15:02:56.814Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":27,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"resource_label_events":[{"id":243,"action":"add","issue_id":null,"merge_request_id":27,"label_id":null,"user_id":1,"created_at":"2018-08-28T08:24:00.494Z"}],"merge_request_diff":{"id":27,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":27,"relative_order":0,"sha":"bb5206fee213d983da88c47f9cf4cc6caf9c66dc","message":"Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-08-06T08:35:52.000+02:00","committed_date":"2014-08-06T08:35:52.000+02:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":1,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":2,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":3,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":4,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":27,"relative_order":5,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":27,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":3,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":27,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":5,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":6,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":27,"relative_order":8,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":27,"created_at":"2016-06-14T15:02:36.572Z","updated_at":"2016-06-14T15:02:36.658Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"9"},"events":[{"id":221,"target_type":"MergeRequest","target_id":27,"project_id":36,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1},{"id":187,"target_type":"MergeRequest","target_id":27,"project_id":5,"created_at":"2016-06-14T15:02:36.703Z","updated_at":"2016-06-14T15:02:36.703Z","action":1,"author_id":1}],"approvals_before_merge":1,"award_emoji":[{"id":1,"name":"thumbsup","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"},{"id":2,"name":"drum","user_id":1,"awardable_type":"MergeRequest","awardable_id":27,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-07T11:21:21.235Z"}],"merge_request_assignees":[{"user_id":1,"created_at":"2020-01-07T11:21:21.235Z","state":"unreviewed"},{"user_id":15,"created_at":"2020-01-08T11:21:21.235Z","state":"reviewed"},{"user_id":16,"created_at":"2020-01-09T11:21:21.235Z","state":"attention_requested"},{"user_id":6,"created_at":"2020-01-10T11:21:21.235Z","state":"unreviewed"}],"merge_request_reviewers":[{"user_id":1,"created_at":"2020-01-07T11:21:21.235Z","state":"unreviewed"},{"user_id":15,"created_at":"2020-01-08T11:21:21.235Z","state":"reviewed"},{"user_id":16,"created_at":"2020-01-09T11:21:21.235Z","state":"attention_requested"},{"user_id":6,"created_at":"2020-01-10T11:21:21.235Z","state":"unreviewed"}],"approvals":[{"user_id":1,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-08T11:21:21.235Z"},{"user_id":15,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-08T11:21:21.235Z"},{"user_id":16,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-08T11:21:21.235Z"},{"user_id":6,"created_at":"2020-01-07T11:21:21.235Z","updated_at":"2020-01-08T11:21:21.235Z"}]}
+{"id":26,"target_branch":"master","source_branch":"feature","source_project_id":4,"author_id":1,"assignee_id":null,"title":"MR2","created_at":"2016-06-14T15:02:36.418Z","updated_at":"2016-06-14T15:02:57.013Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":8,"description":null,"position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":679,"note":"Qui rerum totam nisi est.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:56.848Z","updated_at":"2016-06-14T15:02:56.848Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":680,"note":"Pariatur magni corrupti consequatur debitis minima error beatae voluptatem.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:56.871Z","updated_at":"2016-06-14T15:02:56.871Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":681,"note":"Qui quis ut modi eos rerum ratione.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:56.895Z","updated_at":"2016-06-14T15:02:56.895Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":682,"note":"Illum quidem expedita mollitia fugit.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:56.918Z","updated_at":"2016-06-14T15:02:56.918Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":683,"note":"Consectetur voluptate sit sint possimus veritatis quod.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:56.942Z","updated_at":"2016-06-14T15:02:56.942Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":684,"note":"Natus libero quibusdam rem assumenda deleniti accusamus sed earum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:56.966Z","updated_at":"2016-06-14T15:02:56.966Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":685,"note":"Tenetur autem nihil rerum odit.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:56.989Z","updated_at":"2016-06-14T15:02:56.989Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":686,"note":"Quia maiores et odio sed.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:57.012Z","updated_at":"2016-06-14T15:02:57.012Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":26,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":26,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":26,"sha":"0b4bc9a49b562e85de7cc9e834518ea6828729b9","relative_order":0,"message":"Feature added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:26:01.000+01:00","committed_date":"2014-02-27T09:26:01.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":26,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/files/ruby/feature.rb\n@@ -0,0 +1,5 @@\n+class Feature\n+ def foo\n+ puts 'bar'\n+ end\n+end\n","new_path":"files/ruby/feature.rb","old_path":"files/ruby/feature.rb","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":26,"created_at":"2016-06-14T15:02:36.421Z","updated_at":"2016-06-14T15:02:36.474Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"1"},"events":[{"id":222,"target_type":"MergeRequest","target_id":26,"project_id":36,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1},{"id":186,"target_type":"MergeRequest","target_id":26,"project_id":5,"created_at":"2016-06-14T15:02:36.496Z","updated_at":"2016-06-14T15:02:36.496Z","action":1,"author_id":1}],"merge_request_assignees":[],"merge_request_reviewers":[],"approvals":[]}
{"id":15,"target_branch":"test-7","source_branch":"test-1","source_project_id":5,"author_id":22,"assignee_id":16,"title":"Qui accusantium et inventore facilis doloribus occaecati officiis.","created_at":"2016-06-14T15:02:25.168Z","updated_at":"2016-06-14T15:02:59.521Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":7,"description":"Et commodi deserunt aspernatur vero rerum. Ut non dolorum alias in odit est libero. Voluptatibus eos in et vitae repudiandae facilis ex mollitia.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":777,"note":"Pariatur voluptas placeat aspernatur culpa suscipit soluta.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.348Z","updated_at":"2016-06-14T15:02:59.348Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":778,"note":"Alias et iure mollitia suscipit molestiae voluptatum nostrum asperiores.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.372Z","updated_at":"2016-06-14T15:02:59.372Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":779,"note":"Laudantium qui eum qui sunt.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.395Z","updated_at":"2016-06-14T15:02:59.395Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":780,"note":"Quas rem est iusto ut delectus fugiat recusandae mollitia.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.418Z","updated_at":"2016-06-14T15:02:59.418Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":781,"note":"Repellendus ab et qui nesciunt.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.444Z","updated_at":"2016-06-14T15:02:59.444Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":782,"note":"Non possimus voluptatum odio qui ut.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.469Z","updated_at":"2016-06-14T15:02:59.469Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":783,"note":"Dolores repellendus eum ducimus quam ab dolorem quia.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.494Z","updated_at":"2016-06-14T15:02:59.494Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":784,"note":"Facilis dolorem aut corrupti id ratione occaecati.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.520Z","updated_at":"2016-06-14T15:02:59.520Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":15,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":15,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":15,"relative_order":0,"sha":"94b8d581c48d894b86661718582fecbc5e3ed2eb","message":"fixes #10\n","authored_date":"2016-01-19T13:22:56.000+01:00","committed_date":"2016-01-19T13:22:56.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}}],"merge_request_diff_files":[{"merge_request_diff_id":15,"relative_order":0,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":15,"created_at":"2016-06-14T15:02:25.171Z","updated_at":"2016-06-14T15:02:25.230Z","base_commit_sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","real_size":"1"},"events":[{"id":223,"target_type":"MergeRequest","target_id":15,"project_id":36,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":1},{"id":175,"target_type":"MergeRequest","target_id":15,"project_id":5,"created_at":"2016-06-14T15:02:25.262Z","updated_at":"2016-06-14T15:02:25.262Z","action":1,"author_id":22}]}
{"id":14,"target_branch":"fix","source_branch":"test-3","source_project_id":5,"author_id":20,"assignee_id":20,"title":"In voluptas aut sequi voluptatem ullam vel corporis illum consequatur.","created_at":"2016-06-14T15:02:24.760Z","updated_at":"2016-06-14T15:02:59.749Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":6,"description":"Dicta magnam non voluptates nam dignissimos nostrum deserunt. Dolorum et suscipit iure quae doloremque. Necessitatibus saepe aut labore sed.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":785,"note":"Atque cupiditate necessitatibus deserunt minus natus odit.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.559Z","updated_at":"2016-06-14T15:02:59.559Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[]},{"id":786,"note":"Non dolorem provident mollitia nesciunt optio ex eveniet.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.587Z","updated_at":"2016-06-14T15:02:59.587Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":787,"note":"Similique officia nemo quasi commodi accusantium quae qui.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.621Z","updated_at":"2016-06-14T15:02:59.621Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":788,"note":"Et est et alias ad dolor qui.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.650Z","updated_at":"2016-06-14T15:02:59.650Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":789,"note":"Numquam temporibus ratione voluptatibus aliquid.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.675Z","updated_at":"2016-06-14T15:02:59.675Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":790,"note":"Ut ex aliquam consectetur perferendis est hic aut quia.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.703Z","updated_at":"2016-06-14T15:02:59.703Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":791,"note":"Esse eos quam quaerat aut ut asperiores officiis.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.726Z","updated_at":"2016-06-14T15:02:59.726Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":792,"note":"Sint facilis accusantium iure blanditiis.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.748Z","updated_at":"2016-06-14T15:02:59.748Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":14,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":14,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":14,"relative_order":0,"sha":"ddd4ff416a931589c695eb4f5b23f844426f6928","message":"fixes #10\n","authored_date":"2016-01-19T14:14:43.000+01:00","committed_date":"2016-01-19T14:14:43.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":14,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":14,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":14,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":14,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":14,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","committed_date":"2015-01-10T22:23:29.000+01:00","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":14,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","committed_date":"2015-01-10T21:28:18.000+01:00","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}},{"merge_request_diff_id":14,"relative_order":15,"sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","message":"Add submodule from gitlab.com\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T10:01:38.000+01:00","committed_date":"2014-02-27T10:01:38.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":16,"sha":"570e7b2abdd848b95f2f578043fc23bd6f6fd24d","message":"Change some files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:57:31.000+01:00","committed_date":"2014-02-27T09:57:31.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":17,"sha":"6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9","message":"More submodules\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:54:21.000+01:00","committed_date":"2014-02-27T09:54:21.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":18,"sha":"d14d6c0abdd253381df51a723d58691b2ee1ab08","message":"Remove ds_store files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:49:50.000+01:00","committed_date":"2014-02-27T09:49:50.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}},{"merge_request_diff_id":14,"relative_order":19,"sha":"c1acaa58bbcbc3eafe538cb8274ba387047b69f8","message":"Ignore DS files\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n","authored_date":"2014-02-27T09:48:32.000+01:00","committed_date":"2014-02-27T09:48:32.000+01:00","commit_author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":14,"relative_order":0,"utf8_diff":"Binary files a/.DS_Store and /dev/null differ\n","new_path":".DS_Store","old_path":".DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":1,"utf8_diff":"--- a/.gitignore\n+++ b/.gitignore\n@@ -17,3 +17,4 @@ rerun.txt\n pickle-email-*.html\n .project\n config/initializers/secret_token.rb\n+.DS_Store\n","new_path":".gitignore","old_path":".gitignore","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":2,"utf8_diff":"--- a/.gitmodules\n+++ b/.gitmodules\n@@ -1,3 +1,9 @@\n [submodule \"six\"]\n \tpath = six\n \turl = git://github.com/randx/six.git\n+[submodule \"gitlab-shell\"]\n+\tpath = gitlab-shell\n+\turl = https://github.com/gitlabhq/gitlab-shell.git\n+[submodule \"gitlab-grack\"]\n+\tpath = gitlab-grack\n+\turl = https://gitlab.com/gitlab-org/gitlab-grack.git\n","new_path":".gitmodules","old_path":".gitmodules","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":3,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":5,"utf8_diff":"Binary files a/files/.DS_Store and /dev/null differ\n","new_path":"files/.DS_Store","old_path":"files/.DS_Store","a_mode":"100644","b_mode":"0","new_file":false,"renamed_file":false,"deleted_file":true,"too_large":false},{"merge_request_diff_id":14,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":7,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":8,"utf8_diff":"--- a/files/ruby/popen.rb\n+++ b/files/ruby/popen.rb\n@@ -6,12 +6,18 @@ module Popen\n \n def popen(cmd, path=nil)\n unless cmd.is_a?(Array)\n- raise \"System commands must be given as an array of strings\"\n+ raise RuntimeError, \"System commands must be given as an array of strings\"\n end\n \n path ||= Dir.pwd\n- vars = { \"PWD\" => path }\n- options = { chdir: path }\n+\n+ vars = {\n+ \"PWD\" => path\n+ }\n+\n+ options = {\n+ chdir: path\n+ }\n \n unless File.directory?(path)\n FileUtils.mkdir_p(path)\n@@ -19,6 +25,7 @@ module Popen\n \n @cmd_output = \"\"\n @cmd_status = 0\n+\n Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|\n @cmd_output << stdout.read\n @cmd_output << stderr.read\n","new_path":"files/ruby/popen.rb","old_path":"files/ruby/popen.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":9,"utf8_diff":"--- a/files/ruby/regex.rb\n+++ b/files/ruby/regex.rb\n@@ -19,14 +19,12 @@ module Gitlab\n end\n \n def archive_formats_regex\n- #|zip|tar| tar.gz | tar.bz2 |\n- /(zip|tar|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n+ /(zip|tar|7z|tar\\.gz|tgz|gz|tar\\.bz2|tbz|tbz2|tb2|bz2)/\n end\n \n def git_reference_regex\n # Valid git ref regex, see:\n # https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html\n-\n %r{\n (?!\n (?# doesn't begins with)\n","new_path":"files/ruby/regex.rb","old_path":"files/ruby/regex.rb","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":10,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":11,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":12,"utf8_diff":"--- /dev/null\n+++ b/gitlab-grack\n@@ -0,0 +1 @@\n+Subproject commit 645f6c4c82fd3f5e06f67134450a570b795e55a6\n","new_path":"gitlab-grack","old_path":"gitlab-grack","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":13,"utf8_diff":"--- /dev/null\n+++ b/gitlab-shell\n@@ -0,0 +1 @@\n+Subproject commit 79bceae69cb5750d6567b223597999bfa91cb3b9\n","new_path":"gitlab-shell","old_path":"gitlab-shell","a_mode":"0","b_mode":"160000","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":14,"relative_order":14,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":14,"created_at":"2016-06-14T15:02:24.770Z","updated_at":"2016-06-14T15:02:25.007Z","base_commit_sha":"ae73cb07c9eeaf35924a10f713b364d32b2dd34f","real_size":"15"},"events":[{"id":224,"target_type":"MergeRequest","target_id":14,"project_id":36,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":1},{"id":174,"target_type":"MergeRequest","target_id":14,"project_id":5,"created_at":"2016-06-14T15:02:25.113Z","updated_at":"2016-06-14T15:02:25.113Z","action":1,"author_id":20}]}
{"id":13,"target_branch":"improve/awesome","source_branch":"test-8","source_project_id":5,"author_id":16,"assignee_id":25,"title":"Voluptates consequatur eius nemo amet libero animi illum delectus tempore.","created_at":"2016-06-14T15:02:24.415Z","updated_at":"2016-06-14T15:02:59.958Z","state":"opened","merge_status":"unchecked","target_project_id":5,"iid":5,"description":"Est eaque quasi qui qui. Similique voluptatem impedit iusto ratione reprehenderit. Itaque est illum ut nulla aut.","position":0,"updated_by_id":null,"merge_error":null,"merge_params":{"force_remove_source_branch":null},"merge_when_pipeline_succeeds":false,"merge_user_id":null,"merge_commit_sha":null,"notes":[{"id":793,"note":"In illum maxime aperiam nulla est aspernatur.","noteable_type":"MergeRequest","author_id":26,"created_at":"2016-06-14T15:02:59.782Z","updated_at":"2016-06-14T15:02:59.782Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 4"},"events":[{"merge_request_diff_id":14,"id":529,"target_type":"Note","target_id":793,"project_id":4,"created_at":"2016-07-07T14:35:12.128Z","updated_at":"2016-07-07T14:35:12.128Z","action":6,"author_id":1}]},{"id":794,"note":"Enim quia perferendis cum distinctio tenetur optio voluptas veniam.","noteable_type":"MergeRequest","author_id":25,"created_at":"2016-06-14T15:02:59.807Z","updated_at":"2016-06-14T15:02:59.807Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 3"},"events":[]},{"id":795,"note":"Dolor ad quia quis pariatur ducimus.","noteable_type":"MergeRequest","author_id":22,"created_at":"2016-06-14T15:02:59.831Z","updated_at":"2016-06-14T15:02:59.831Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"User 0"},"events":[]},{"id":796,"note":"Et a odio voluptate aut.","noteable_type":"MergeRequest","author_id":20,"created_at":"2016-06-14T15:02:59.854Z","updated_at":"2016-06-14T15:02:59.854Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ottis Schuster II"},"events":[]},{"id":797,"note":"Quis nihil temporibus voluptatum modi minima a ut.","noteable_type":"MergeRequest","author_id":16,"created_at":"2016-06-14T15:02:59.879Z","updated_at":"2016-06-14T15:02:59.879Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Rhett Emmerich IV"},"events":[]},{"id":798,"note":"Ut alias consequatur in nostrum.","noteable_type":"MergeRequest","author_id":15,"created_at":"2016-06-14T15:02:59.904Z","updated_at":"2016-06-14T15:02:59.904Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Burdette Bernier"},"events":[]},{"id":799,"note":"Voluptatibus aperiam assumenda et neque sint libero.","noteable_type":"MergeRequest","author_id":6,"created_at":"2016-06-14T15:02:59.926Z","updated_at":"2016-06-14T15:02:59.926Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Ari Wintheiser"},"events":[]},{"id":800,"note":"Veritatis voluptatem dolor dolores magni quo ut ipsa fuga.","noteable_type":"MergeRequest","author_id":1,"created_at":"2016-06-14T15:02:59.956Z","updated_at":"2016-06-14T15:02:59.956Z","project_id":5,"attachment":{"url":null},"line_code":null,"commit_id":null,"noteable_id":13,"system":false,"st_diff":null,"updated_by_id":null,"author":{"name":"Administrator"},"events":[]}],"merge_request_diff":{"id":13,"state":"collected","merge_request_diff_commits":[{"merge_request_diff_id":13,"relative_order":0,"sha":"0bfedc29d30280c7e8564e19f654584b459e5868","message":"fixes #10\n","authored_date":"2016-01-19T15:25:23.000+01:00","committed_date":"2016-01-19T15:25:23.000+01:00","commit_author":{"name":"James Lopez","email":"james@jameslopez.es"},"committer":{"name":"James Lopez","email":"james@jameslopez.es"}},{"merge_request_diff_id":13,"relative_order":1,"sha":"be93687618e4b132087f430a4d8fc3a609c9b77c","message":"Merge branch 'master' into 'master'\r\n\r\nLFS object pointer.\r\n\r\n\r\n\r\nSee merge request !6","authored_date":"2015-12-07T12:52:12.000+01:00","committed_date":"2015-12-07T12:52:12.000+01:00","commit_author":{"name":"Marin Jankovski","email":"marin@gitlab.com"},"committer":{"name":"Marin Jankovski","email":"marin@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":2,"sha":"048721d90c449b244b7b4c53a9186b04330174ec","message":"LFS object pointer.\n","authored_date":"2015-12-07T11:54:28.000+01:00","committed_date":"2015-12-07T11:54:28.000+01:00","commit_author":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"},"committer":{"name":"Marin Jankovski","email":"maxlazio@gmail.com"}},{"merge_request_diff_id":13,"relative_order":3,"sha":"5f923865dde3436854e9ceb9cdb7815618d4e849","message":"GitLab currently doesn't support patches that involve a merge commit: add a commit here\n","authored_date":"2015-11-13T16:27:12.000+01:00","committed_date":"2015-11-13T16:27:12.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":4,"sha":"d2d430676773caa88cdaf7c55944073b2fd5561a","message":"Merge branch 'add-svg' into 'master'\r\n\r\nAdd GitLab SVG\r\n\r\nAdded to test preview of sanitized SVG images\r\n\r\nSee merge request !5","authored_date":"2015-11-13T08:50:17.000+01:00","committed_date":"2015-11-13T08:50:17.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":5,"sha":"2ea1f3dec713d940208fb5ce4a38765ecb5d3f73","message":"Add GitLab SVG\n","authored_date":"2015-11-13T08:39:43.000+01:00","committed_date":"2015-11-13T08:39:43.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":6,"sha":"59e29889be61e6e0e5e223bfa9ac2721d31605b8","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd whitespace test file\r\n\r\nSorry, I did a mistake.\r\nGit ignore empty files.\r\nSo I add a new whitespace test file.\r\n\r\nSee merge request !4","authored_date":"2015-11-13T07:21:40.000+01:00","committed_date":"2015-11-13T07:21:40.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":7,"sha":"66eceea0db202bb39c4e445e8ca28689645366c5","message":"add spaces in whitespace file\n","authored_date":"2015-11-13T06:01:27.000+01:00","committed_date":"2015-11-13T06:01:27.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":8,"sha":"08f22f255f082689c0d7d39d19205085311542bc","message":"remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n","authored_date":"2015-11-13T06:00:16.000+01:00","committed_date":"2015-11-13T06:00:16.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":9,"sha":"19e2e9b4ef76b422ce1154af39a91323ccc57434","message":"Merge branch 'whitespace' into 'master'\r\n\r\nadd spaces\r\n\r\nTo test this pull request.(https://github.com/gitlabhq/gitlabhq/pull/9757)\r\nJust add whitespaces.\r\n\r\nSee merge request !3","authored_date":"2015-11-13T05:23:14.000+01:00","committed_date":"2015-11-13T05:23:14.000+01:00","commit_author":{"name":"Stan Hu","email":"stanhu@gmail.com"},"committer":{"name":"Stan Hu","email":"stanhu@gmail.com"}},{"merge_request_diff_id":13,"relative_order":10,"sha":"c642fe9b8b9f28f9225d7ea953fe14e74748d53b","message":"add whitespace in empty\n","authored_date":"2015-11-13T05:08:45.000+01:00","committed_date":"2015-11-13T05:08:45.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":11,"sha":"9a944d90955aaf45f6d0c88f30e27f8d2c41cec0","message":"add empty file\n","authored_date":"2015-11-13T05:08:04.000+01:00","committed_date":"2015-11-13T05:08:04.000+01:00","commit_author":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"},"committer":{"name":"윤민ì‹","email":"minsik.yoon@samsung.com"}},{"merge_request_diff_id":13,"relative_order":12,"sha":"c7fbe50c7c7419d9701eebe64b1fdacc3df5b9dd","message":"Add ISO-8859 test file\n","authored_date":"2015-08-25T17:53:12.000+02:00","committed_date":"2015-08-25T17:53:12.000+02:00","commit_author":{"name":"Stan Hu","email":"stanhu@packetzoom.com"},"committer":{"name":"Stan Hu","email":"stanhu@packetzoom.com"}},{"merge_request_diff_id":13,"relative_order":13,"sha":"e56497bb5f03a90a51293fc6d516788730953899","message":"Merge branch 'tree_helper_spec' into 'master'\n\nAdd directory structure for tree_helper spec\n\nThis directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module\n\nSee [merge request #275](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/275#note_732774)\n\nSee merge request !2\n","authored_date":"2015-01-10T22:23:29.000+01:00","committed_date":"2015-01-10T22:23:29.000+01:00","commit_author":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"},"committer":{"name":"Sytse Sijbrandij","email":"sytse@gitlab.com"}},{"merge_request_diff_id":13,"relative_order":14,"sha":"4cd80ccab63c82b4bad16faa5193fbd2aa06df40","message":"add directory structure for tree_helper spec\n","authored_date":"2015-01-10T21:28:18.000+01:00","committed_date":"2015-01-10T21:28:18.000+01:00","commit_author":{"name":"marmis85","email":"marmis85@gmail.com"},"committer":{"name":"marmis85","email":"marmis85@gmail.com"}}],"merge_request_diff_files":[{"merge_request_diff_id":13,"relative_order":0,"utf8_diff":"--- a/CHANGELOG\n+++ b/CHANGELOG\n@@ -1,4 +1,6 @@\n-v 6.7.0\n+v6.8.0\n+\n+v6.7.0\n - Add support for Gemnasium as a Project Service (Olivier Gonzalez)\n - Add edit file button to MergeRequest diff\n - Public groups (Jason Hollingsworth)\n","new_path":"CHANGELOG","old_path":"CHANGELOG","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":1,"utf8_diff":"--- /dev/null\n+++ b/encoding/iso8859.txt\n@@ -0,0 +1 @@\n+Äü\n","new_path":"encoding/iso8859.txt","old_path":"encoding/iso8859.txt","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":2,"utf8_diff":"--- /dev/null\n+++ b/files/images/wm.svg\n@@ -0,0 +1,78 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n+<svg width=\"1300px\" height=\"680px\" viewBox=\"0 0 1300 680\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n+ <!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->\n+ <title>wm</title>\n+ <desc>Created with Sketch.</desc>\n+ <defs>\n+ <path id=\"path-1\" d=\"M-69.8,1023.54607 L1675.19996,1023.54607 L1675.19996,0 L-69.8,0 L-69.8,1023.54607 L-69.8,1023.54607 Z\"></path>\n+ </defs>\n+ <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n+ <path d=\"M1300,680 L0,680 L0,0 L1300,0 L1300,680 L1300,680 Z\" id=\"bg\" fill=\"#30353E\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"gitlab_logo\" sketch:type=\"MSLayerGroup\" transform=\"translate(-262.000000, -172.000000)\">\n+ <g id=\"g10\" transform=\"translate(872.500000, 512.354581) scale(1, -1) translate(-872.500000, -512.354581) translate(0.000000, 0.290751)\">\n+ <g id=\"g12\" transform=\"translate(1218.022652, 440.744871)\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\">\n+ <path d=\"M-50.0233338,141.900706 L-69.07059,141.900706 L-69.0100967,0.155858152 L8.04444805,0.155858152 L8.04444805,17.6840847 L-49.9628405,17.6840847 L-50.0233338,141.900706 L-50.0233338,141.900706 Z\" id=\"path14\"></path>\n+ </g>\n+ <g id=\"g16\">\n+ <g id=\"g18-Clipped\">\n+ <mask id=\"mask-2\" sketch:name=\"path22\" fill=\"white\">\n+ <use xlink:href=\"#path-1\"></use>\n+ </mask>\n+ <g id=\"path22\"></g>\n+ <g id=\"g18\" mask=\"url(#mask-2)\">\n+ <g transform=\"translate(382.736659, 312.879425)\">\n+ <g id=\"g24\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(852.718192, 124.992771)\">\n+ <path d=\"M63.9833317,27.9148929 C59.2218085,22.9379001 51.2134221,17.9597442 40.3909323,17.9597442 C25.8888194,17.9597442 20.0453962,25.1013043 20.0453962,34.4074318 C20.0453962,48.4730484 29.7848226,55.1819277 50.5642821,55.1819277 C54.4602853,55.1819277 60.7364685,54.7492469 63.9833317,54.1002256 L63.9833317,27.9148929 L63.9833317,27.9148929 Z M44.2869356,113.827628 C28.9053426,113.827628 14.7975996,108.376082 3.78897657,99.301416 L10.5211864,87.6422957 C18.3131929,92.1866076 27.8374026,96.7320827 41.4728323,96.7320827 C57.0568452,96.7320827 63.9833317,88.7239978 63.9833317,75.3074024 L63.9833317,68.3821827 C60.9528485,69.0312039 54.6766653,69.4650479 50.7806621,69.4650479 C17.4476729,69.4650479 0.565379986,57.7791759 0.565379986,33.3245665 C0.565379986,11.4683685 13.9844297,0.43151772 34.3299658,0.43151772 C48.0351955,0.43151772 61.1692285,6.70771614 65.7143717,16.8780421 L69.1776149,3.02876588 L82.5978279,3.02876588 L82.5978279,75.5237428 C82.5978279,98.462806 72.6408582,113.827628 44.2869356,113.827628 L44.2869356,113.827628 Z\" id=\"path26\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g28\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(959.546624, 124.857151)\">\n+ <path d=\"M37.2266657,17.4468081 C30.0837992,17.4468081 23.8064527,18.3121698 19.0449295,20.4767371 L19.0449295,79.2306079 L19.0449295,86.0464943 C25.538656,91.457331 33.5470425,95.3526217 43.7203922,95.3526217 C62.1173451,95.3526217 69.2602116,82.3687072 69.2602116,61.3767077 C69.2602116,31.5135879 57.7885819,17.4468081 37.2266657,17.4468081 M45.2315622,113.963713 C28.208506,113.963713 19.0449295,102.384849 19.0449295,102.384849 L19.0449295,120.67143 L18.9844362,144.908535 L10.3967097,144.908535 L0.371103324,144.908535 L0.431596656,6.62629771 C9.73826309,2.73100702 22.5081728,0.567602823 36.3611458,0.567602823 C71.8579349,0.567602823 88.9566078,23.2891625 88.9566078,62.4584098 C88.9566078,93.4043948 73.1527248,113.963713 45.2315622,113.963713\" id=\"path30\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g32\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(509.576747, 125.294950)\">\n+ <path d=\"M68.636665,129.10638 C85.5189579,129.10638 96.3414476,123.480366 103.484314,117.853189 L111.669527,132.029302 C100.513161,141.811145 85.5073245,147.06845 69.5021849,147.06845 C29.0274926,147.06845 0.673569983,122.3975 0.673569983,72.6252464 C0.673569983,20.4709215 31.2622559,0.12910638 66.2553217,0.12910638 C83.7879179,0.12910638 98.7227909,4.24073748 108.462217,8.35236859 L108.063194,64.0763105 L108.063194,70.6502677 L108.063194,81.6057001 L56.1168719,81.6057001 L56.1168719,64.0763105 L89.2323178,64.0763105 L89.6313411,21.7701271 C85.3025779,19.6055598 77.7269514,17.8748364 67.554765,17.8748364 C39.4172223,17.8748364 20.5863462,35.5717154 20.5863462,72.8415868 C20.5863462,110.711628 40.0663623,129.10638 68.636665,129.10638\" id=\"path34\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g36\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(692.388992, 124.376085)\">\n+ <path d=\"M19.7766662,145.390067 L1.16216997,145.390067 L1.2226633,121.585642 L1.2226633,111.846834 L1.2226633,106.170806 L1.2226633,96.2656714 L1.2226633,39.5681976 L1.2226633,39.3518572 C1.2226633,16.4127939 11.1796331,1.04797161 39.5335557,1.04797161 C43.4504989,1.04797161 47.2836822,1.40388649 51.0051854,2.07965952 L51.0051854,18.7925385 C48.3109055,18.3796307 45.4351455,18.1446804 42.3476589,18.1446804 C26.763646,18.1446804 19.8371595,26.1516022 19.8371595,39.5681976 L19.8371595,96.2656714 L51.0051854,96.2656714 L51.0051854,111.846834 L19.8371595,111.846834 L19.7766662,145.390067 L19.7766662,145.390067 Z\" id=\"path38\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <path d=\"M646.318899,128.021188 L664.933395,128.021188 L664.933395,236.223966 L646.318899,236.223966 L646.318899,128.021188 L646.318899,128.021188 Z\" id=\"path40\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <path d=\"M646.318899,251.154944 L664.933395,251.154944 L664.933395,269.766036 L646.318899,269.766036 L646.318899,251.154944 L646.318899,251.154944 Z\" id=\"path42\" fill=\"#8C929D\" sketch:type=\"MSShapeGroup\"></path>\n+ <g id=\"g44\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.464170, 0.676006)\">\n+ <path d=\"M429.269989,169.815599 L405.225053,243.802859 L357.571431,390.440955 C355.120288,397.984955 344.444378,397.984955 341.992071,390.440955 L294.337286,243.802859 L136.094873,243.802859 L88.4389245,390.440955 C85.9877812,397.984955 75.3118715,397.984955 72.8595648,390.440955 L25.2059427,243.802859 L1.16216997,169.815599 C-1.03187664,163.067173 1.37156997,155.674379 7.11261982,151.503429 L215.215498,0.336141836 L423.319539,151.503429 C429.060589,155.674379 431.462873,163.067173 429.269989,169.815599\" id=\"path46\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g48\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(135.410135, 1.012147)\">\n+ <path d=\"M80.269998,0 L80.269998,0 L159.391786,243.466717 L1.14820997,243.466717 L80.269998,0 L80.269998,0 Z\" id=\"path50\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g52\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path54\"></g>\n+ </g>\n+ <g id=\"g56\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(24.893471, 1.012613)\">\n+ <path d=\"M190.786662,0 L111.664874,243.465554 L0.777106647,243.465554 L190.786662,0 L190.786662,0 Z\" id=\"path58\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g60\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <g id=\"path62\"></g>\n+ </g>\n+ <g id=\"g64\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(0.077245, 0.223203)\">\n+ <path d=\"M25.5933327,244.255313 L25.5933327,244.255313 L1.54839663,170.268052 C-0.644486651,163.519627 1.75779662,156.126833 7.50000981,151.957046 L215.602888,0.789758846 L25.5933327,244.255313 L25.5933327,244.255313 Z\" id=\"path66\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g68\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012147)\">\n+ <g id=\"path70\"></g>\n+ </g>\n+ <g id=\"g72\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(25.670578, 244.478283)\">\n+ <path d=\"M0,0 L110.887767,0 L63.2329818,146.638096 C60.7806751,154.183259 50.1047654,154.183259 47.6536221,146.638096 L0,0 L0,0 Z\" id=\"path74\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g76\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(215.680133, 1.012613)\">\n+ <path d=\"M0,0 L79.121788,243.465554 L190.009555,243.465554 L0,0 L0,0 Z\" id=\"path78\" fill=\"#FC6D26\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g80\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(214.902910, 0.223203)\">\n+ <path d=\"M190.786662,244.255313 L190.786662,244.255313 L214.831598,170.268052 C217.024481,163.519627 214.622198,156.126833 208.879985,151.957046 L0.777106647,0.789758846 L190.786662,244.255313 L190.786662,244.255313 Z\" id=\"path82\" fill=\"#FCA326\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ <g id=\"g84\" stroke-width=\"1\" fill=\"none\" sketch:type=\"MSLayerGroup\" transform=\"translate(294.009575, 244.478283)\">\n+ <path d=\"M111.679997,0 L0.79222998,0 L48.4470155,146.638096 C50.8993221,154.183259 61.5752318,154.183259 64.0263751,146.638096 L111.679997,0 L111.679997,0 Z\" id=\"path86\" fill=\"#E24329\" sketch:type=\"MSShapeGroup\"></path>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+ </g>\n+</svg>\n\\ No newline at end of file\n","new_path":"files/images/wm.svg","old_path":"files/images/wm.svg","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":3,"utf8_diff":"--- /dev/null\n+++ b/files/lfs/lfs_object.iso\n@@ -0,0 +1,4 @@\n+version https://git-lfs.github.com/spec/v1\n+oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897\n+size 1575078\n+\n","new_path":"files/lfs/lfs_object.iso","old_path":"files/lfs/lfs_object.iso","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":4,"utf8_diff":"--- /dev/null\n+++ b/files/whitespace\n@@ -0,0 +1 @@\n+test \n","new_path":"files/whitespace","old_path":"files/whitespace","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":5,"utf8_diff":"--- /dev/null\n+++ b/foo/bar/.gitkeep\n","new_path":"foo/bar/.gitkeep","old_path":"foo/bar/.gitkeep","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false},{"merge_request_diff_id":13,"relative_order":6,"utf8_diff":"--- /dev/null\n+++ b/test\n","new_path":"test","old_path":"test","a_mode":"0","b_mode":"100644","new_file":true,"renamed_file":false,"deleted_file":false,"too_large":false}],"merge_request_id":13,"created_at":"2016-06-14T15:02:24.420Z","updated_at":"2016-06-14T15:02:24.561Z","base_commit_sha":"5937ac0a7beb003549fc5fd26fc247adbce4a52e","real_size":"7"},"events":[{"id":225,"target_type":"MergeRequest","target_id":13,"project_id":36,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16},{"id":173,"target_type":"MergeRequest","target_id":13,"project_id":5,"created_at":"2016-06-14T15:02:24.636Z","updated_at":"2016-06-14T15:02:24.636Z","action":1,"author_id":16}]}
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index 2da16408fbc..18cd63b7bcb 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -275,9 +275,11 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- [ ] Incomplete task 1
- [x] Complete task 1
+- [~] Inapplicable task 1
- [ ] Incomplete task 2
- [ ] Incomplete sub-task 1
- [ ] Incomplete sub-task 2
+ - [~] Inapplicable sub-task 1
- [x] Complete sub-task 1
- [X] Complete task 2
diff --git a/spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.pom.sha1 b/spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.pom.sha1
new file mode 100644
index 00000000000..33b75ee37eb
--- /dev/null
+++ b/spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.pom.sha1
@@ -0,0 +1 @@
+78f664f030d2a684f59081e88b9461257e859c14
diff --git a/spec/fixtures/whats_new/20201225_01_01.yml b/spec/fixtures/whats_new/20201225_01_01.yml
index 7bf58900cc7..45f989be01c 100644
--- a/spec/fixtures/whats_new/20201225_01_01.yml
+++ b/spec/fixtures/whats_new/20201225_01_01.yml
@@ -1,7 +1,7 @@
---
-- title: It's gonna be a bright
- body: |
+- name: It's gonna be a bright
+ description: |
## It's gonna be a bright
self-managed: true
gitlab-com: false
- packages: ["Premium", "Ultimate"]
+ available_in: ["Premium", "Ultimate"]
diff --git a/spec/fixtures/whats_new/20201225_01_02.yml b/spec/fixtures/whats_new/20201225_01_02.yml
index 90b5192897e..baea00f7b11 100644
--- a/spec/fixtures/whats_new/20201225_01_02.yml
+++ b/spec/fixtures/whats_new/20201225_01_02.yml
@@ -1,7 +1,7 @@
---
-- title: bright
- body: |
+- name: bright
+ description: |
## bright
self-managed: true
gitlab-com: false
- packages: ["Premium", "Ultimate"]
+ available_in: ["Premium", "Ultimate"]
diff --git a/spec/fixtures/whats_new/20201225_01_04.yml b/spec/fixtures/whats_new/20201225_01_04.yml
index 0dfd0d780c7..918592aecfe 100644
--- a/spec/fixtures/whats_new/20201225_01_04.yml
+++ b/spec/fixtures/whats_new/20201225_01_04.yml
@@ -1,19 +1,19 @@
---
-- title: View epics on a board
- body: |
+- name: View epics on a board
+ description: |
## View epics on a board
self-managed: true
gitlab-com: false
- packages: ["Free", "Premium", "Ultimate"]
-- title: View Jira issue details in GitLab
- body: |
+ available_in: ["Free", "Premium", "Ultimate"]
+- name: View Jira issue details in GitLab
+ description: |
## View Jira issue details in GitLab
self-managed: true
gitlab-com: false
- packages: ["Premium", "Ultimate"]
-- title: Integrate any IT alerting tool with GitLab
- body: |
+ available_in: ["Premium", "Ultimate"]
+- name: Integrate any IT alerting tool with GitLab
+ description: |
## Integrate any IT alerting tool with GitLab
self-managed: true
gitlab-com: false
- packages: ["Ultimate"] \ No newline at end of file
+ available_in: ["Ultimate"]
diff --git a/spec/fixtures/whats_new/20201225_01_05.yml b/spec/fixtures/whats_new/20201225_01_05.yml
index d707502af54..a14adfeec13 100644
--- a/spec/fixtures/whats_new/20201225_01_05.yml
+++ b/spec/fixtures/whats_new/20201225_01_05.yml
@@ -1,14 +1,14 @@
---
-- title: bright and sunshinin' day
- body: |
+- name: bright and sunshinin' day
+ description: |
bright and sunshinin' [day](https://en.wikipedia.org/wiki/Day)
self-managed: true
gitlab-com: false
- packages: ["Premium", "Ultimate"]
+ available_in: ["Premium", "Ultimate"]
release: '01.05'
-- title: I think I can make it now the pain is gone
- body: |
+- name: I think I can make it now the pain is gone
+ description: |
## I think I can make it now the pain is gone
self-managed: false
gitlab-com: true
- packages: ["Premium", "Ultimate"]
+ available_in: ["Premium", "Ultimate"]
diff --git a/spec/fixtures/whats_new/blank.yml b/spec/fixtures/whats_new/blank.yml
index 4628cae2ecc..1475db0ea82 100644
--- a/spec/fixtures/whats_new/blank.yml
+++ b/spec/fixtures/whats_new/blank.yml
@@ -1,5 +1,5 @@
-- title:
- body:
+- name:
+ description:
stage:
self-managed:
gitlab-com:
diff --git a/spec/fixtures/whats_new/invalid.yml b/spec/fixtures/whats_new/invalid.yml
index a3342be0f24..b888aba9a16 100644
--- a/spec/fixtures/whats_new/invalid.yml
+++ b/spec/fixtures/whats_new/invalid.yml
@@ -1,20 +1,20 @@
-- title: Create and view requirements in GitLab
- body: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
+- name: Create and view requirements in GitLab
+ description: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [ALL]
- url: https://docs.gitlab.com/ee/user/project/requirements/index.html
+ available_in: [ALL]
+ documentation_link: https://docs.gitlab.com/ee/user/project/requirements/index.html
image_url: https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png
published_at: 2020-04-22
release: 12.10
-- title: Retrieve CI/CD secrets from HashiCorp Vault
- body: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
+- name: Retrieve CI/CD secrets from HashiCorp Vault
+ description: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free]
- url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
+ available_in: [Free]
+ documentation_link: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
release: 12.10
diff --git a/spec/fixtures/whats_new/valid.yml b/spec/fixtures/whats_new/valid.yml
index ec465f47989..e46ff85cd9c 100644
--- a/spec/fixtures/whats_new/valid.yml
+++ b/spec/fixtures/whats_new/valid.yml
@@ -1,20 +1,20 @@
-- title: Create and view requirements in GitLab
- body: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
+- name: Create and view requirements in GitLab
+ description: The first step towards managing requirements from within GitLab is here! This initial release allows users to create and view requirements at a project level. As Requirements Management evolves in GitLab, stay tuned for support for traceability between all artifacts, creating a seamless workflow to visually demonstrate completeness and compliance.
stage: Plan
self-managed: true
gitlab-com: true
- packages: [Ultimate]
- url: https://docs.gitlab.com/ee/user/project/requirements/index.html
+ available_in: [Ultimate]
+ documentation_link: https://docs.gitlab.com/ee/user/project/requirements/index.html
image_url: https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png
published_at: 2020-04-22
release: 12.10
-- title: Retrieve CI/CD secrets from HashiCorp Vault
- body: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
+- name: Retrieve CI/CD secrets from HashiCorp Vault
+ description: In this release, GitLab adds support for lightweight JSON Web Token (JWT) authentication to integrate with your existing HashiCorp Vault. Now, you can seamlessly provide secrets to CI/CD jobs by taking advantage of HashiCorp's JWT authentication method rather than manually having to provide secrets as a variable in GitLab.
stage: Release
self-managed: true
gitlab-com: true
- packages: [Free]
- url: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
+ available_in: [Free]
+ documentation_link: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/index.html
image_url: https://about.gitlab.com/images/12_10/jwt-vault-1.png
published_at: 2020-04-22
release: 12.10
diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index bae9f33be87..e0739df7086 100644
--- a/spec/frontend/__helpers__/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
@@ -8,7 +8,6 @@ export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {
const cache = new InMemoryCache({
possibleTypes,
typePolicies,
- addTypename: false,
...cacheOptions,
});
diff --git a/spec/frontend/__helpers__/mock_dom_observer.js b/spec/frontend/__helpers__/mock_dom_observer.js
index bc2646be4c2..8c9c435041e 100644
--- a/spec/frontend/__helpers__/mock_dom_observer.js
+++ b/spec/frontend/__helpers__/mock_dom_observer.js
@@ -22,14 +22,12 @@ class MockObserver {
takeRecords() {}
- // eslint-disable-next-line camelcase
$_triggerObserve(node, { entry = {}, options = {} } = {}) {
if (this.$_hasObserver(node, options)) {
this.$_cb([{ target: node, ...entry }]);
}
}
- // eslint-disable-next-line camelcase
$_hasObserver(node, options = {}) {
return this.$_observers.some(
([obvNode, obvOptions]) => node === obvNode && isMatch(options, obvOptions),
diff --git a/spec/frontend/__helpers__/mocks/axios_utils.js b/spec/frontend/__helpers__/mocks/axios_utils.js
index b1efd29dc8d..60644c84a57 100644
--- a/spec/frontend/__helpers__/mocks/axios_utils.js
+++ b/spec/frontend/__helpers__/mocks/axios_utils.js
@@ -1,4 +1,6 @@
import EventEmitter from 'events';
+// eslint-disable-next-line no-restricted-syntax
+import { setImmediate } from 'timers';
const axios = jest.requireActual('~/lib/utils/axios_utils').default;
diff --git a/spec/frontend/__helpers__/stub_component.js b/spec/frontend/__helpers__/stub_component.js
index 96fe3a8bc45..4f9d1ee6f5d 100644
--- a/spec/frontend/__helpers__/stub_component.js
+++ b/spec/frontend/__helpers__/stub_component.js
@@ -22,6 +22,14 @@ const createStubbedMethods = (methods = {}) => {
);
};
+export const RENDER_ALL_SLOTS_TEMPLATE = `<div>
+ <template v-for="(_, name) in $scopedSlots">
+ <div :data-testid="'slot-' + name">
+ <slot :name="name" />
+ </div>
+ </template>
+</div>`;
+
export function stubComponent(Component, options = {}) {
return {
props: Component.props,
diff --git a/spec/frontend/__helpers__/timeout.js b/spec/frontend/__helpers__/timeout.js
deleted file mode 100644
index 8688625a95e..00000000000
--- a/spec/frontend/__helpers__/timeout.js
+++ /dev/null
@@ -1,59 +0,0 @@
-const NS_PER_SEC = 1e9;
-const NS_PER_MS = 1e6;
-const IS_DEBUGGING = process.execArgv.join(' ').includes('--inspect-brk');
-
-let testTimeoutNS;
-
-export const setTestTimeout = (newTimeoutMS) => {
- const newTimeoutNS = newTimeoutMS * NS_PER_MS;
- // never accept a smaller timeout than the default
- if (newTimeoutNS < testTimeoutNS) {
- return;
- }
-
- testTimeoutNS = newTimeoutNS;
- jest.setTimeout(newTimeoutMS);
-};
-
-// Allows slow tests to set their own timeout.
-// Useful for tests with jQuery, which is very slow in big DOMs.
-let temporaryTimeoutNS = null;
-export const setTestTimeoutOnce = (newTimeoutMS) => {
- const newTimeoutNS = newTimeoutMS * NS_PER_MS;
- // never accept a smaller timeout than the default
- if (newTimeoutNS < testTimeoutNS) {
- return;
- }
-
- temporaryTimeoutNS = newTimeoutNS;
-};
-
-export const initializeTestTimeout = (defaultTimeoutMS) => {
- setTestTimeout(defaultTimeoutMS);
-
- let testStartTime;
-
- // https://github.com/facebook/jest/issues/6947
- beforeEach(() => {
- testStartTime = process.hrtime();
- });
-
- afterEach(() => {
- let timeoutNS = testTimeoutNS;
- if (Number.isFinite(temporaryTimeoutNS)) {
- timeoutNS = temporaryTimeoutNS;
- temporaryTimeoutNS = null;
- }
-
- const [seconds, remainingNs] = process.hrtime(testStartTime);
- const elapsedNS = seconds * NS_PER_SEC + remainingNs;
-
- // Disable the timeout error when debugging. It is meaningless because
- // debugging always takes longer than the test timeout.
- if (elapsedNS > timeoutNS && !IS_DEBUGGING) {
- throw new Error(
- `Test took too long (${elapsedNS / NS_PER_MS}ms > ${timeoutNS / NS_PER_MS}ms)!`,
- );
- }
- });
-};
diff --git a/spec/frontend/__helpers__/vue_mount_component_helper.js b/spec/frontend/__helpers__/vue_mount_component_helper.js
index 615ff69a01c..ed43355ea5b 100644
--- a/spec/frontend/__helpers__/vue_mount_component_helper.js
+++ b/spec/frontend/__helpers__/vue_mount_component_helper.js
@@ -1,5 +1,3 @@
-import Vue from 'vue';
-
/**
* Deprecated. Please do not use.
* Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
@@ -33,31 +31,4 @@ export const mountComponentWithStore = (Component, { el, props, store }) =>
* Deprecated. Please do not use.
* Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
*/
-export const mountComponentWithSlots = (Component, { props, slots }) => {
- const component = new Component({
- propsData: props || {},
- });
-
- component.$slots = slots;
-
- return component.$mount();
-};
-
-/**
- * Mount a component with the given render method.
- *
- * -----------------------------
- * Deprecated. Please do not use.
- * Please see https://gitlab.com/groups/gitlab-org/-/epics/2445
- * -----------------------------
- *
- * This helps with inserting slots that need to be compiled.
- */
-export const mountComponentWithRender = (render, el = null) =>
- mountComponent(Vue.extend({ render }), {}, 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.js b/spec/frontend/__helpers__/vue_test_utils_helper.js
index 2aae91f8a39..75bd5df8cbf 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper.js
@@ -7,6 +7,20 @@ const vNodeContainsText = (vnode, text) =>
(vnode.children && vnode.children.filter((child) => vNodeContainsText(child, text)).length);
/**
+ * Create a VTU wrapper from an element.
+ *
+ * If a Vue instance manages the element, the wrapper is created
+ * with that Vue instance.
+ *
+ * @param {HTMLElement} element
+ * @param {Object} options
+ * @returns VTU wrapper
+ */
+const createWrapperFromElement = (element, options) =>
+ // eslint-disable-next-line no-underscore-dangle
+ createWrapper(element.__vue__ || element, options || {});
+
+/**
* Determines whether a `shallowMount` Wrapper contains text
* within one of it's slots. This will also work on Wrappers
* acquired with `find()`, but only if it's parent Wrapper
@@ -85,8 +99,7 @@ export const extendedWrapper = (wrapper) => {
if (!elements.length) {
return new ErrorWrapper(query);
}
-
- return createWrapper(elements[0], this.options || {});
+ return createWrapperFromElement(elements[0], this.options);
},
},
};
@@ -104,7 +117,7 @@ export const extendedWrapper = (wrapper) => {
);
const wrappers = elements.map((element) => {
- const elementWrapper = createWrapper(element, this.options || {});
+ const elementWrapper = createWrapperFromElement(element, this.options);
elementWrapper.selector = text;
return elementWrapper;
diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
index 3bb228f94b8..ae180c3b49d 100644
--- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
+++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js
@@ -6,6 +6,7 @@ import {
WrapperArray as VTUWrapperArray,
ErrorWrapper as VTUErrorWrapper,
} from '@vue/test-utils';
+import Vue from 'vue';
import {
extendedWrapper,
shallowMountExtended,
@@ -139,9 +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 wrapper;
beforeEach(() => {
+ jest.spyOn(vtu, 'createWrapper');
+
wrapper = extendedWrapper(
shallowMount({
template: `<div>foo bar</div>`,
@@ -164,7 +168,6 @@ describe('Vue test utils helpers', () => {
describe('when element is found', () => {
beforeEach(() => {
jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockDiv]);
- jest.spyOn(vtu, 'createWrapper');
});
it('returns a VTU wrapper', () => {
@@ -172,14 +175,27 @@ describe('Vue test utils helpers', () => {
expect(vtu.createWrapper).toHaveBeenCalledWith(mockDiv, wrapper.options);
expect(result).toBeInstanceOf(VTUWrapper);
+ expect(result.vm).toBeUndefined();
});
});
+ describe('when a Vue instance element is found', () => {
+ beforeEach(() => {
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockVm.$el]);
+ });
+
+ it('returns a VTU wrapper', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(vtu.createWrapper).toHaveBeenCalledWith(mockVm, wrapper.options);
+ expect(result).toBeInstanceOf(VTUWrapper);
+ expect(result.vm).toBeInstanceOf(Vue);
+ });
+ });
describe('when multiple elements are found', () => {
beforeEach(() => {
const mockSpan = document.createElement('span');
jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => [mockDiv, mockSpan]);
- jest.spyOn(vtu, 'createWrapper');
});
it('returns the first element as a VTU wrapper', () => {
@@ -187,6 +203,24 @@ describe('Vue test utils helpers', () => {
expect(vtu.createWrapper).toHaveBeenCalledWith(mockDiv, wrapper.options);
expect(result).toBeInstanceOf(VTUWrapper);
+ expect(result.vm).toBeUndefined();
+ });
+ });
+
+ describe('when multiple Vue instances are found', () => {
+ beforeEach(() => {
+ const mockVm2 = new Vue({ render: (h) => h('span') }).$mount();
+ jest
+ .spyOn(testingLibrary, expectedQuery)
+ .mockImplementation(() => [mockVm.$el, mockVm2.$el]);
+ });
+
+ it('returns the first element as a VTU wrapper', () => {
+ const result = wrapper[findMethod](text, options);
+
+ expect(vtu.createWrapper).toHaveBeenCalledWith(mockVm, wrapper.options);
+ expect(result).toBeInstanceOf(VTUWrapper);
+ expect(result.vm).toBeInstanceOf(Vue);
});
});
@@ -211,12 +245,17 @@ describe('Vue test utils helpers', () => {
${'findAllByAltText'} | ${'queryAllByAltText'}
`('$findMethod', ({ findMethod, expectedQuery }) => {
const text = 'foo bar';
- const options = { selector: 'div' };
+ const options = { selector: 'li' };
const mockElements = [
document.createElement('li'),
document.createElement('li'),
document.createElement('li'),
];
+ const mockVms = [
+ new Vue({ render: (h) => h('li') }).$mount(),
+ new Vue({ render: (h) => h('li') }).$mount(),
+ new Vue({ render: (h) => h('li') }).$mount(),
+ ];
let wrapper;
beforeEach(() => {
@@ -245,9 +284,13 @@ describe('Vue test utils helpers', () => {
);
});
- describe('when elements are found', () => {
+ describe.each`
+ case | mockResult | isVueInstance
+ ${'HTMLElements'} | ${mockElements} | ${false}
+ ${'Vue instance elements'} | ${mockVms} | ${true}
+ `('when $case are found', ({ mockResult, isVueInstance }) => {
beforeEach(() => {
- jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => mockElements);
+ jest.spyOn(testingLibrary, expectedQuery).mockImplementation(() => mockResult);
});
it('returns a VTU wrapper array', () => {
@@ -257,7 +300,9 @@ describe('Vue test utils helpers', () => {
expect(
result.wrappers.every(
(resultWrapper) =>
- resultWrapper instanceof VTUWrapper && resultWrapper.options === wrapper.options,
+ resultWrapper instanceof VTUWrapper &&
+ resultWrapper.vm instanceof Vue === isVueInstance &&
+ resultWrapper.options === wrapper.options,
),
).toBe(true);
expect(result.length).toBe(3);
diff --git a/spec/frontend/__helpers__/vuex_action_helper.js b/spec/frontend/__helpers__/vuex_action_helper.js
index ab2637d6024..bdd5a0a9034 100644
--- a/spec/frontend/__helpers__/vuex_action_helper.js
+++ b/spec/frontend/__helpers__/vuex_action_helper.js
@@ -1,5 +1,7 @@
-/**
- * Helper for testing action with expected mutations inspired in
+// eslint-disable-next-line no-restricted-syntax
+import { setImmediate } from 'timers';
+
+/** Helper for testing action with expected mutations inspired in
* https://vuex.vuejs.org/en/testing.html
*
* @param {(Function|Object)} action to be tested, or object of named parameters
diff --git a/spec/frontend/__helpers__/vuex_action_helper_spec.js b/spec/frontend/__helpers__/vuex_action_helper_spec.js
index 5bb2b3b26e2..182aea9c1c5 100644
--- a/spec/frontend/__helpers__/vuex_action_helper_spec.js
+++ b/spec/frontend/__helpers__/vuex_action_helper_spec.js
@@ -76,7 +76,7 @@ describe.each([testActionFn, testActionFnWithOptionsArg])(
const promise = testAction(() => {}, null, {}, assertion.mutations, assertion.actions);
- originalExpect(promise instanceof Promise).toBeTruthy();
+ originalExpect(promise instanceof Promise).toBe(true);
return promise;
});
diff --git a/spec/frontend/__helpers__/wait_for_promises.js b/spec/frontend/__helpers__/wait_for_promises.js
index 753c3c5d92b..5a15b8b74b5 100644
--- a/spec/frontend/__helpers__/wait_for_promises.js
+++ b/spec/frontend/__helpers__/wait_for_promises.js
@@ -1,4 +1,2 @@
-export default () =>
- new Promise((resolve) => {
- requestAnimationFrame(resolve);
- });
+// eslint-disable-next-line no-restricted-syntax
+export default () => new Promise(jest.requireActual('timers').setImmediate);
diff --git a/spec/frontend/__helpers__/web_worker_transformer.js b/spec/frontend/__helpers__/web_worker_transformer.js
index 5b2f7d77947..767ab3f5675 100644
--- a/spec/frontend/__helpers__/web_worker_transformer.js
+++ b/spec/frontend/__helpers__/web_worker_transformer.js
@@ -6,7 +6,7 @@ const babelJestTransformer = require('babel-jest');
// [1]: https://webpack.js.org/loaders/worker-loader/
module.exports = {
process: (contentArg, filename, ...args) => {
- const { code: content } = babelJestTransformer.process(contentArg, filename, ...args);
+ const { code: content } = babelJestTransformer.default.process(contentArg, filename, ...args);
return `const { FakeWebWorker } = require("helpers/web_worker_fake");
module.exports = class JestTransformedWorker extends FakeWebWorker {
diff --git a/spec/frontend/__mocks__/monaco-editor/index.js b/spec/frontend/__mocks__/monaco-editor/index.js
index 18b7df32f9b..384f9993150 100644
--- a/spec/frontend/__mocks__/monaco-editor/index.js
+++ b/spec/frontend/__mocks__/monaco-editor/index.js
@@ -15,4 +15,3 @@ 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';
-export default global.monaco;
diff --git a/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap b/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap
index 36003154b58..2bd2b17a12d 100644
--- a/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap
+++ b/spec/frontend/access_tokens/components/__snapshots__/expires_at_field_spec.js.snap
@@ -11,22 +11,17 @@ exports[`~/access_tokens/components/expires_at_field should render datepicker wi
arialabel=""
autocomplete=""
container=""
+ data-qa-selector="expiry_date_field"
+ defaultdate="Wed Aug 05 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"
displayfield="true"
firstday="0"
+ inputid="personal_access_token_expires_at"
inputlabel="Enter date"
+ inputname="personal_access_token[expires_at]"
mindate="Mon Jul 06 2020 00:00:00 GMT+0000 (Greenwich Mean Time)"
placeholder="YYYY-MM-DD"
+ showclearbutton="true"
theme=""
- >
- <gl-form-input-stub
- autocomplete="off"
- class="datepicker gl-datepicker-input"
- data-qa-selector="expiry_date_field"
- id="personal_access_token_expires_at"
- inputmode="none"
- name="personal_access_token[expires_at]"
- placeholder="YYYY-MM-DD"
- />
- </gl-datepicker-stub>
+ />
</gl-form-group-stub>
`;
diff --git a/spec/frontend/access_tokens/components/expires_at_field_spec.js b/spec/frontend/access_tokens/components/expires_at_field_spec.js
index cb899d10ba7..646dc0d703f 100644
--- a/spec/frontend/access_tokens/components/expires_at_field_spec.js
+++ b/spec/frontend/access_tokens/components/expires_at_field_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlDatepicker } from '@gitlab/ui';
import ExpiresAtField from '~/access_tokens/components/expires_at_field.vue';
+import { getDateInFuture } from '~/lib/utils/datetime_utility';
describe('~/access_tokens/components/expires_at_field', () => {
let wrapper;
@@ -49,4 +50,12 @@ describe('~/access_tokens/components/expires_at_field', () => {
expect(findDatepicker().props('maxDate')).toStrictEqual(maxDate);
});
+
+ it('should set the default expiration date to be 30 days', () => {
+ const today = new Date();
+ const future = getDateInFuture(today, 30);
+ createComponent();
+
+ expect(findDatepicker().props('defaultDate')).toStrictEqual(future);
+ });
});
diff --git a/spec/frontend/access_tokens/components/projects_field_spec.js b/spec/frontend/access_tokens/components/projects_field_spec.js
deleted file mode 100644
index 1c4fe7bb168..00000000000
--- a/spec/frontend/access_tokens/components/projects_field_spec.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { nextTick } from 'vue';
-import { within, fireEvent } from '@testing-library/dom';
-import { mount } from '@vue/test-utils';
-import ProjectsField from '~/access_tokens/components/projects_field.vue';
-import ProjectsTokenSelector from '~/access_tokens/components/projects_token_selector.vue';
-
-describe('ProjectsField', () => {
- let wrapper;
-
- const createComponent = ({ inputAttrsValue = '' } = {}) => {
- wrapper = mount(ProjectsField, {
- propsData: {
- inputAttrs: {
- id: 'projects',
- name: 'projects',
- value: inputAttrsValue,
- },
- },
- });
- };
-
- const queryByLabelText = (text) => within(wrapper.element).queryByLabelText(text);
- const queryByText = (text) => within(wrapper.element).queryByText(text);
- const findAllProjectsRadio = () => queryByLabelText('All projects');
- const findSelectedProjectsRadio = () => queryByLabelText('Selected projects');
- const findProjectsTokenSelector = () => wrapper.findComponent(ProjectsTokenSelector);
- const findHiddenInput = () => wrapper.find('input[type="hidden"]');
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders label and sub-label', () => {
- createComponent();
-
- expect(queryByText('Projects')).not.toBe(null);
- expect(queryByText('Set access permissions for this token.')).not.toBe(null);
- });
-
- describe('when `inputAttrs.value` is empty', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders "All projects" radio as checked', () => {
- expect(findAllProjectsRadio().checked).toBe(true);
- });
-
- it('renders "Selected projects" radio as unchecked', () => {
- expect(findSelectedProjectsRadio().checked).toBe(false);
- });
-
- it('sets `projects-token-selector` `initialProjectIds` prop to an empty array', () => {
- expect(findProjectsTokenSelector().props('initialProjectIds')).toEqual([]);
- });
- });
-
- describe('when `inputAttrs.value` is a comma separated list of project IDs', () => {
- beforeEach(() => {
- createComponent({ inputAttrsValue: '1,2' });
- });
-
- it('renders "All projects" radio as unchecked', () => {
- expect(findAllProjectsRadio().checked).toBe(false);
- });
-
- it('renders "Selected projects" radio as checked', () => {
- expect(findSelectedProjectsRadio().checked).toBe(true);
- });
-
- it('sets `projects-token-selector` `initialProjectIds` prop to an array of project IDs', () => {
- expect(findProjectsTokenSelector().props('initialProjectIds')).toEqual(['1', '2']);
- });
- });
-
- it('renders `projects-token-selector` component', () => {
- createComponent();
-
- expect(findProjectsTokenSelector().exists()).toBe(true);
- });
-
- it('renders hidden input with correct `name` and `id` attributes', () => {
- createComponent();
-
- expect(findHiddenInput().attributes()).toEqual(
- expect.objectContaining({
- id: 'projects',
- name: 'projects',
- }),
- );
- });
-
- describe('when `projects-token-selector` is focused', () => {
- beforeEach(() => {
- createComponent();
-
- findProjectsTokenSelector().vm.$emit('focus');
- });
-
- it('auto selects the "Selected projects" radio', () => {
- expect(findSelectedProjectsRadio().checked).toBe(true);
- });
-
- describe('when `projects-token-selector` is changed', () => {
- beforeEach(() => {
- findProjectsTokenSelector().vm.$emit('input', [
- {
- id: 1,
- },
- {
- id: 2,
- },
- ]);
- });
-
- it('updates the hidden input value to a comma separated list of project IDs', () => {
- expect(findHiddenInput().attributes('value')).toBe('1,2');
- });
-
- describe('when radio is changed back to "All projects"', () => {
- it('removes the hidden input value', async () => {
- fireEvent.change(findAllProjectsRadio());
- await nextTick();
-
- expect(findHiddenInput().attributes('value')).toBe('');
- });
- });
- });
- });
-});
diff --git a/spec/frontend/access_tokens/components/projects_token_selector_spec.js b/spec/frontend/access_tokens/components/projects_token_selector_spec.js
deleted file mode 100644
index 40aaf16d41f..00000000000
--- a/spec/frontend/access_tokens/components/projects_token_selector_spec.js
+++ /dev/null
@@ -1,266 +0,0 @@
-import {
- GlAvatar,
- GlAvatarLabeled,
- GlIntersectionObserver,
- GlToken,
- GlTokenSelector,
- GlLoadingIcon,
-} from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import produce from 'immer';
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-
-import getProjectsQueryResponse from 'test_fixtures/graphql/projects/access_tokens/get_projects.query.graphql.json';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import ProjectsTokenSelector from '~/access_tokens/components/projects_token_selector.vue';
-import getProjectsQuery from '~/access_tokens/graphql/queries/get_projects.query.graphql';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-
-describe('ProjectsTokenSelector', () => {
- const getProjectsQueryResponsePage2 = produce(
- getProjectsQueryResponse,
- (getProjectsQueryResponseDraft) => {
- /* eslint-disable no-param-reassign */
- getProjectsQueryResponseDraft.data.projects.pageInfo.hasNextPage = false;
- getProjectsQueryResponseDraft.data.projects.pageInfo.endCursor = null;
- getProjectsQueryResponseDraft.data.projects.nodes.splice(1, 1);
- getProjectsQueryResponseDraft.data.projects.nodes[0].id = 'gid://gitlab/Project/100';
- /* eslint-enable no-param-reassign */
- },
- );
-
- const runDebounce = () => jest.runAllTimers();
-
- const { pageInfo, nodes: projects } = getProjectsQueryResponse.data.projects;
- const project1 = projects[0];
- const project2 = projects[1];
-
- let wrapper;
-
- let resolveGetProjectsQuery;
- let resolveGetInitialProjectsQuery;
- const getProjectsQueryRequestHandler = jest.fn(
- ({ ids }) =>
- new Promise((resolve) => {
- if (ids) {
- resolveGetInitialProjectsQuery = resolve;
- } else {
- resolveGetProjectsQuery = resolve;
- }
- }),
- );
-
- const createComponent = ({
- propsData = {},
- apolloProvider = createMockApollo([[getProjectsQuery, getProjectsQueryRequestHandler]]),
- resolveQueries = true,
- } = {}) => {
- Vue.use(VueApollo);
-
- wrapper = extendedWrapper(
- mount(ProjectsTokenSelector, {
- apolloProvider,
- propsData: {
- selectedProjects: [],
- initialProjectIds: [],
- ...propsData,
- },
- stubs: ['gl-intersection-observer'],
- }),
- );
-
- runDebounce();
-
- if (resolveQueries) {
- resolveGetProjectsQuery(getProjectsQueryResponse);
-
- return waitForPromises();
- }
-
- return Promise.resolve();
- };
-
- const findTokenSelector = () => wrapper.findComponent(GlTokenSelector);
- const findTokenSelectorInput = () => findTokenSelector().find('input[type="text"]');
- const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver);
-
- it('renders dropdown items with project avatars', async () => {
- await createComponent();
-
- wrapper.findAllComponents(GlAvatarLabeled).wrappers.forEach((avatarLabeledWrapper, index) => {
- const project = projects[index];
-
- expect(avatarLabeledWrapper.attributes()).toEqual(
- expect.objectContaining({
- 'entity-id': `${getIdFromGraphQLId(project.id)}`,
- 'entity-name': project.name,
- ...(project.avatarUrl && { src: project.avatarUrl }),
- }),
- );
-
- expect(avatarLabeledWrapper.props()).toEqual(
- expect.objectContaining({
- label: project.name,
- subLabel: project.nameWithNamespace,
- }),
- );
- });
- });
-
- it('renders tokens with project avatars', () => {
- createComponent({
- propsData: {
- selectedProjects: [{ ...project2, id: getIdFromGraphQLId(project2.id) }],
- },
- });
-
- const token = wrapper.findComponent(GlToken);
- const avatar = token.findComponent(GlAvatar);
-
- expect(token.text()).toContain(project2.nameWithNamespace);
- expect(avatar.attributes('src')).toBe(project2.avatarUrl);
- expect(avatar.props()).toEqual(
- expect.objectContaining({
- entityId: getIdFromGraphQLId(project2.id),
- entityName: project2.name,
- }),
- );
- });
-
- describe('when `enter` key is pressed', () => {
- it('calls `preventDefault` so form is not submitted when user selects a project from the dropdown', () => {
- createComponent();
-
- const event = {
- preventDefault: jest.fn(),
- };
-
- findTokenSelectorInput().trigger('keydown.enter', event);
-
- expect(event.preventDefault).toHaveBeenCalled();
- });
- });
-
- describe('when text input is typed in', () => {
- const searchTerm = 'foo bar';
-
- beforeEach(async () => {
- await createComponent();
-
- await findTokenSelectorInput().setValue(searchTerm);
- runDebounce();
- });
-
- it('makes GraphQL request with `search` variable set', async () => {
- expect(getProjectsQueryRequestHandler).toHaveBeenLastCalledWith({
- search: searchTerm,
- after: null,
- first: 20,
- ids: null,
- });
- });
-
- it('sets loading state while waiting for GraphQL request to resolve', async () => {
- expect(findTokenSelector().props('loading')).toBe(true);
-
- resolveGetProjectsQuery(getProjectsQueryResponse);
- await waitForPromises();
-
- expect(findTokenSelector().props('loading')).toBe(false);
- });
- });
-
- describe('when there is a next page of projects and user scrolls to the bottom of the dropdown', () => {
- beforeEach(async () => {
- await createComponent();
-
- findIntersectionObserver().vm.$emit('appear');
- });
-
- it('makes GraphQL request with `after` variable set', async () => {
- expect(getProjectsQueryRequestHandler).toHaveBeenLastCalledWith({
- after: pageInfo.endCursor,
- first: 20,
- search: '',
- ids: null,
- });
- });
-
- it('displays loading icon while waiting for GraphQL request to resolve', async () => {
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
-
- resolveGetProjectsQuery(getProjectsQueryResponsePage2);
- await waitForPromises();
-
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
- });
- });
-
- describe('when there is not a next page of projects', () => {
- it('does not render `GlIntersectionObserver`', async () => {
- createComponent({ resolveQueries: false });
-
- resolveGetProjectsQuery(getProjectsQueryResponsePage2);
- await waitForPromises();
-
- expect(findIntersectionObserver().exists()).toBe(false);
- });
- });
-
- describe('when `GlTokenSelector` emits `input` event', () => {
- it('emits `input` event used by `v-model`', () => {
- findTokenSelector().vm.$emit('input', project1);
-
- expect(wrapper.emitted('input')[0]).toEqual([project1]);
- });
- });
-
- describe('when `GlTokenSelector` emits `focus` event', () => {
- it('emits `focus` event', () => {
- const event = { fakeEvent: 'foo' };
- findTokenSelector().vm.$emit('focus', event);
-
- expect(wrapper.emitted('focus')[0]).toEqual([event]);
- });
- });
-
- describe('when `initialProjectIds` is an empty array', () => {
- it('does not request initial projects', async () => {
- await createComponent();
-
- expect(getProjectsQueryRequestHandler).toHaveBeenCalledTimes(1);
- expect(getProjectsQueryRequestHandler).toHaveBeenCalledWith(
- expect.objectContaining({
- ids: null,
- }),
- );
- });
- });
-
- describe('when `initialProjectIds` is an array of project IDs', () => {
- it('requests those projects and emits `input` event with result', async () => {
- await createComponent({
- propsData: {
- initialProjectIds: [getIdFromGraphQLId(project1.id), getIdFromGraphQLId(project2.id)],
- },
- });
-
- resolveGetInitialProjectsQuery(getProjectsQueryResponse);
- await waitForPromises();
-
- expect(getProjectsQueryRequestHandler).toHaveBeenCalledWith({
- after: '',
- first: null,
- search: '',
- ids: [project1.id, project2.id],
- });
- expect(wrapper.emitted('input')[0][0]).toEqual([
- { ...project1, id: getIdFromGraphQLId(project1.id) },
- { ...project2, id: getIdFromGraphQLId(project2.id) },
- ]);
- });
- });
-});
diff --git a/spec/frontend/access_tokens/index_spec.js b/spec/frontend/access_tokens/index_spec.js
index b6119f1d167..0c611a4a512 100644
--- a/spec/frontend/access_tokens/index_spec.js
+++ b/spec/frontend/access_tokens/index_spec.js
@@ -8,13 +8,11 @@ import {
initAccessTokenTableApp,
initExpiresAtField,
initNewAccessTokenApp,
- initProjectsField,
initTokensApp,
} from '~/access_tokens';
import * as AccessTokenTableApp from '~/access_tokens/components/access_token_table_app.vue';
-import * as ExpiresAtField from '~/access_tokens/components/expires_at_field.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 ProjectsField from '~/access_tokens/components/projects_field.vue';
import * as TokensApp from '~/access_tokens/components/tokens_app.vue';
import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from '~/access_tokens/constants';
import { __, sprintf } from '~/locale';
@@ -115,49 +113,28 @@ describe('access tokens', () => {
});
});
- describe.each`
- initFunction | mountSelector | fieldName | expectedComponent
- ${initExpiresAtField} | ${'js-access-tokens-expires-at'} | ${'expiresAt'} | ${ExpiresAtField}
- ${initProjectsField} | ${'js-access-tokens-projects'} | ${'projects'} | ${ProjectsField}
- `('$initFunction', ({ initFunction, mountSelector, fieldName, expectedComponent }) => {
+ describe('initExpiresAtField', () => {
describe('when mount element exists', () => {
- const FakeComponent = Vue.component('FakeComponent', {
- props: ['inputAttrs'],
- render: () => null,
- });
-
- const nameAttribute = `access_tokens[${fieldName}]`;
- const idAttribute = `access_tokens_${fieldName}`;
+ const nameAttribute = 'access_tokens[expires_at]';
+ const idAttribute = 'access_tokens_expires_at';
beforeEach(() => {
- window.gon = { features: { personalAccessTokensScopedToProjects: true } };
-
setHTMLFixture(
- `<div class="${mountSelector}">
+ `<div class="js-access-tokens-expires-at">
<input
- name="${nameAttribute}"
- data-js-name="${fieldName}"
- id="${idAttribute}"
+ name="access_tokens[expires_at]"
+ data-js-name="expiresAt"
+ id="access_tokens_expires_at"
placeholder="Foo bar"
value="1,2"
/>
</div>`,
);
-
- // Mock component so we don't have to deal with mocking Apollo
- // eslint-disable-next-line no-param-reassign
- expectedComponent.default = FakeComponent;
- });
-
- afterEach(() => {
- delete window.gon;
});
it('mounts component and sets `inputAttrs` prop', async () => {
- const vueInstance = await initFunction();
-
- wrapper = createWrapper(vueInstance);
- const component = wrapper.findComponent(FakeComponent);
+ wrapper = createWrapper(initExpiresAtField());
+ const component = wrapper.findComponent(ExpiresAtField);
expect(component.exists()).toBe(true);
expect(component.props('inputAttrs')).toEqual({
@@ -171,7 +148,7 @@ describe('access tokens', () => {
describe('when mount element does not exist', () => {
it('returns `null`', () => {
- expect(initFunction()).toBe(null);
+ expect(initExpiresAtField()).toBe(null);
});
});
});
diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
index 9b93fd26fa0..bffadbde087 100644
--- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
+++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
@@ -87,7 +87,7 @@ describe('AddContextCommitsModal', () => {
it('enabled ok button when atleast one row is selected', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
await nextTick();
- expect(findModal().attributes('ok-disabled')).toBeFalsy();
+ expect(findModal().attributes('ok-disabled')).toBe(undefined);
});
});
@@ -102,7 +102,7 @@ describe('AddContextCommitsModal', () => {
it('an enabled ok button when atleast one row is selected', async () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
await nextTick();
- expect(findModal().attributes('ok-disabled')).toBeFalsy();
+ expect(findModal().attributes('ok-disabled')).toBe(undefined);
});
it('a disabled ok button in first tab, when row is selected in second tab', () => {
diff --git a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
index d6c5c5f963a..534af2a3033 100644
--- a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
+++ b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
@@ -129,7 +129,7 @@ describe('DevopsScore', () => {
});
it('displays the correct badge', () => {
- const badge = findUsageCol().find(GlBadge);
+ const badge = findUsageCol().findComponent(GlBadge);
expect(badge.exists()).toBe(true);
expect(badge.props('variant')).toBe('muted');
diff --git a/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js b/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
index ae9b6f57ee0..eecc21e206b 100644
--- a/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
+++ b/spec/frontend/admin/signup_restrictions/components/signup_checkbox_spec.js
@@ -24,7 +24,7 @@ describe('Signup Form', () => {
const findByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
const findHiddenInput = () => findByTestId('input');
- const findCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const findCheckboxLabel = () => findByTestId('label');
const findHelpText = () => findByTestId('helpText');
diff --git a/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
index 31a0c2b07e4..411126d0c89 100644
--- a/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
+++ b/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
@@ -28,7 +28,7 @@ describe('Signup Form', () => {
const findForm = () => wrapper.findByTestId('form');
const findInputCsrf = () => findForm().find('[name="authenticity_token"]');
- const findFormSubmitButton = () => findForm().find(GlButton);
+ const findFormSubmitButton = () => findForm().findComponent(GlButton);
const findDenyListRawRadio = () => queryByLabelText('Enter denylist manually');
const findDenyListFileRadio = () => queryByLabelText('Upload denylist file');
@@ -36,7 +36,7 @@ describe('Signup Form', () => {
const findDenyListRawInputGroup = () => wrapper.findByTestId('domain-denylist-raw-input-group');
const findDenyListFileInputGroup = () => wrapper.findByTestId('domain-denylist-file-input-group');
const findUserCapInput = () => wrapper.findByTestId('user-cap-input');
- const findModal = () => wrapper.find(GlModal);
+ const findModal = () => wrapper.findComponent(GlModal);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
index bac542e72fb..190f0eb94a0 100644
--- a/spec/frontend/admin/statistics_panel/components/app_spec.js
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -41,7 +41,7 @@ describe('Admin statistics app', () => {
store.dispatch('requestStatistics');
createComponent();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/admin/users/components/actions/actions_spec.js b/spec/frontend/admin/users/components/actions/actions_spec.js
index b758c15a91a..4967753b91c 100644
--- a/spec/frontend/admin/users/components/actions/actions_spec.js
+++ b/spec/frontend/admin/users/components/actions/actions_spec.js
@@ -12,7 +12,7 @@ import { paths } from '../../mock_data';
describe('Action components', () => {
let wrapper;
- const findDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const initComponent = ({ component, props } = {}) => {
wrapper = shallowMount(component, {
diff --git a/spec/frontend/admin/users/components/app_spec.js b/spec/frontend/admin/users/components/app_spec.js
index 65b13e3a40d..913732aae42 100644
--- a/spec/frontend/admin/users/components/app_spec.js
+++ b/spec/frontend/admin/users/components/app_spec.js
@@ -28,7 +28,7 @@ describe('AdminUsersApp component', () => {
});
it('renders the admin users table with props', () => {
- expect(wrapper.find(AdminUsersTable).props()).toEqual({
+ expect(wrapper.findComponent(AdminUsersTable).props()).toEqual({
users,
paths,
});
diff --git a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
index 09a345ac826..70ed9eeb3e1 100644
--- a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
+++ b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
@@ -17,7 +17,7 @@ describe('Delete user modal', () => {
const findButton = (variant, category) =>
wrapper
- .findAll(GlButton)
+ .findAllComponents(GlButton)
.filter((w) => w.attributes('variant') === variant && w.attributes('category') === category)
.at(0);
const findForm = () => wrapper.find('form');
@@ -87,8 +87,8 @@ describe('Delete user modal', () => {
});
it('has disabled buttons', () => {
- expect(findPrimaryButton().attributes('disabled')).toBeTruthy();
- expect(findSecondaryButton().attributes('disabled')).toBeTruthy();
+ expect(findPrimaryButton().attributes('disabled')).toBe('true');
+ expect(findSecondaryButton().attributes('disabled')).toBe('true');
});
});
@@ -105,8 +105,8 @@ describe('Delete user modal', () => {
});
it('has disabled buttons', () => {
- expect(findPrimaryButton().attributes('disabled')).toBeTruthy();
- expect(findSecondaryButton().attributes('disabled')).toBeTruthy();
+ expect(findPrimaryButton().attributes('disabled')).toBe('true');
+ expect(findSecondaryButton().attributes('disabled')).toBe('true');
});
});
@@ -123,8 +123,8 @@ describe('Delete user modal', () => {
});
it('has enabled buttons', () => {
- expect(findPrimaryButton().attributes('disabled')).toBeFalsy();
- expect(findSecondaryButton().attributes('disabled')).toBeFalsy();
+ expect(findPrimaryButton().attributes('disabled')).toBeUndefined();
+ expect(findSecondaryButton().attributes('disabled')).toBeUndefined();
});
describe('when primary action is clicked', () => {
diff --git a/spec/frontend/admin/users/components/user_actions_spec.js b/spec/frontend/admin/users/components/user_actions_spec.js
index e04c43ae3f2..ffc05e744c8 100644
--- a/spec/frontend/admin/users/components/user_actions_spec.js
+++ b/spec/frontend/admin/users/components/user_actions_spec.js
@@ -83,7 +83,7 @@ describe('AdminUserActions component', () => {
});
it.each(CONFIRMATION_ACTIONS)('renders an action component item for "%s"', (action) => {
- const component = wrapper.find(Actions[capitalizeFirstCharacter(action)]);
+ const component = wrapper.findComponent(Actions[capitalizeFirstCharacter(action)]);
expect(component.props('username')).toBe(user.name);
expect(component.props('path')).toBe(userPaths[action]);
@@ -119,7 +119,7 @@ describe('AdminUserActions component', () => {
});
it.each(DELETE_ACTIONS)('renders a delete action component item for "%s"', (action) => {
- const component = wrapper.find(Actions[capitalizeFirstCharacter(action)]);
+ const component = wrapper.findComponent(Actions[capitalizeFirstCharacter(action)]);
expect(component.props('username')).toBe(user.name);
expect(component.props('paths')).toEqual(userPaths);
diff --git a/spec/frontend/admin/users/components/user_avatar_spec.js b/spec/frontend/admin/users/components/user_avatar_spec.js
index 8bbfb89bec1..94fac875fbe 100644
--- a/spec/frontend/admin/users/components/user_avatar_spec.js
+++ b/spec/frontend/admin/users/components/user_avatar_spec.js
@@ -12,10 +12,10 @@ describe('AdminUserAvatar component', () => {
const user = users[0];
const adminUserPath = paths.adminUser;
- const findNote = () => wrapper.find(GlIcon);
- const findAvatar = () => wrapper.find(GlAvatarLabeled);
+ const findNote = () => wrapper.findComponent(GlIcon);
+ const findAvatar = () => wrapper.findComponent(GlAvatarLabeled);
const findUserLink = () => wrapper.find('.js-user-link');
- const findAllBadges = () => wrapper.findAll(GlBadge);
+ const findAllBadges = () => wrapper.findAllComponents(GlBadge);
const findTooltip = () => getBinding(findNote().element, 'gl-tooltip');
const initComponent = (props = {}) => {
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index ad1c45495b5..fe07f0fce00 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -30,10 +30,10 @@ describe('AdminUsersTable component', () => {
const fetchGroupCountsResponse = createFetchGroupCount([{ id: user.id, groupCount: 5 }]);
const findUserGroupCount = (id) => wrapper.findByTestId(`user-group-count-${id}`);
- const findUserGroupCountLoader = (id) => findUserGroupCount(id).find(GlSkeletonLoader);
+ const findUserGroupCountLoader = (id) => findUserGroupCount(id).findComponent(GlSkeletonLoader);
const getCellByLabel = (trIdx, label) => {
return wrapper
- .find(GlTable)
+ .findComponent(GlTable)
.find('tbody')
.findAll('tr')
.at(trIdx)
@@ -72,7 +72,7 @@ describe('AdminUsersTable component', () => {
});
it('renders the user actions', () => {
- expect(wrapper.find(AdminUserActions).exists()).toBe(true);
+ expect(wrapper.findComponent(AdminUserActions).exists()).toBe(true);
});
it.each`
@@ -81,7 +81,7 @@ describe('AdminUsersTable component', () => {
${AdminUserDate} | ${'Created on'}
${AdminUserDate} | ${'Last activity'}
`('renders the component for column $label', ({ component, label }) => {
- expect(getCellByLabel(0, label).find(component).exists()).toBe(true);
+ expect(getCellByLabel(0, label).findComponent(component).exists()).toBe(true);
});
});
diff --git a/spec/frontend/admin/users/index_spec.js b/spec/frontend/admin/users/index_spec.js
index 961fa96acdd..b51858d5129 100644
--- a/spec/frontend/admin/users/index_spec.js
+++ b/spec/frontend/admin/users/index_spec.js
@@ -8,7 +8,7 @@ describe('initAdminUsersApp', () => {
let wrapper;
let el;
- const findApp = () => wrapper.find(AdminUsersApp);
+ const findApp = () => wrapper.findComponent(AdminUsersApp);
beforeEach(() => {
el = document.createElement('div');
@@ -36,7 +36,7 @@ describe('initAdminUserActions', () => {
let wrapper;
let el;
- const findUserActions = () => wrapper.find(UserActions);
+ const findUserActions = () => wrapper.findComponent(UserActions);
beforeEach(() => {
el = document.createElement('div');
diff --git a/spec/frontend/api/groups_api_spec.js b/spec/frontend/api/groups_api_spec.js
new file mode 100644
index 00000000000..e14ead0b8eb
--- /dev/null
+++ b/spec/frontend/api/groups_api_spec.js
@@ -0,0 +1,46 @@
+import MockAdapter from 'axios-mock-adapter';
+import httpStatus from '~/lib/utils/http_status';
+import axios from '~/lib/utils/axios_utils';
+import { updateGroup } from '~/api/groups_api';
+
+const mockApiVersion = 'v4';
+const mockUrlRoot = '/gitlab';
+
+describe('GroupsApi', () => {
+ let originalGon;
+ let mock;
+
+ const dummyGon = {
+ api_version: mockApiVersion,
+ relative_url_root: mockUrlRoot,
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ originalGon = window.gon;
+ window.gon = { ...dummyGon };
+ });
+
+ afterEach(() => {
+ mock.restore();
+ window.gon = originalGon;
+ });
+
+ describe('updateGroup', () => {
+ const mockGroupId = '99';
+ const mockData = { attr: 'value' };
+ const expectedUrl = `${mockUrlRoot}/api/${mockApiVersion}/groups/${mockGroupId}`;
+
+ beforeEach(() => {
+ mock.onPut(expectedUrl).reply(({ data }) => {
+ return [httpStatus.OK, { id: mockGroupId, ...JSON.parse(data) }];
+ });
+ });
+
+ it('updates group', async () => {
+ const res = await updateGroup(mockGroupId, mockData);
+
+ expect(res.data).toMatchObject({ id: mockGroupId, ...mockData });
+ });
+ });
+});
diff --git a/spec/frontend/attention_requests/components/navigation_popover_spec.js b/spec/frontend/attention_requests/components/navigation_popover_spec.js
deleted file mode 100644
index e4d53d5dbdb..00000000000
--- a/spec/frontend/attention_requests/components/navigation_popover_spec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlPopover, GlButton, GlSprintf, GlIcon } from '@gitlab/ui';
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import NavigationPopover from '~/attention_requests/components/navigation_popover.vue';
-import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
-
-let wrapper;
-let dismiss;
-
-function createComponent(provideData = {}, shouldShowCallout = true) {
- wrapper = shallowMount(NavigationPopover, {
- provide: {
- message: ['Test'],
- observerElSelector: '.js-test',
- observerElToggledClass: 'show',
- featureName: 'attention_requests',
- popoverTarget: '.js-test-popover',
- ...provideData,
- },
- stubs: {
- UserCalloutDismisser: makeMockUserCalloutDismisser({
- dismiss,
- shouldShowCallout,
- }),
- GlSprintf,
- },
- });
-}
-
-describe('Attention requests navigation popover', () => {
- beforeEach(() => {
- setHTMLFixture('<div><div class="js-test-popover"></div><div class="js-test"></div></div>');
- dismiss = jest.fn();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- resetHTMLFixture();
- });
-
- it('hides popover if callout is disabled', () => {
- createComponent({}, false);
-
- expect(wrapper.findComponent(GlPopover).exists()).toBe(false);
- });
-
- it('shows popover if callout is enabled', () => {
- createComponent();
-
- expect(wrapper.findComponent(GlPopover).exists()).toBe(true);
- });
-
- it.each`
- isDesktop | device | expectedPlacement
- ${true} | ${'desktop'} | ${'left'}
- ${false} | ${'mobile'} | ${'bottom'}
- `(
- 'sets popover position to $expectedPlacement on $device',
- ({ isDesktop, expectedPlacement }) => {
- jest.spyOn(bp, 'isDesktop').mockReturnValue(isDesktop);
-
- createComponent();
-
- expect(wrapper.findComponent(GlPopover).props('placement')).toBe(expectedPlacement);
- },
- );
-
- it('calls dismiss when clicking action button', () => {
- createComponent();
-
- wrapper
- .findComponent(GlButton)
- .vm.$emit('click', { preventDefault() {}, stopPropagation() {} });
-
- expect(dismiss).toHaveBeenCalled();
- });
-
- it('shows icon in text', () => {
- createComponent({ showAttentionIcon: true, message: ['%{strongStart}Test%{strongEnd}'] });
-
- const icon = wrapper.findComponent(GlIcon);
-
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('attention');
- });
-});
diff --git a/spec/frontend/batch_comments/components/review_bar_spec.js b/spec/frontend/batch_comments/components/review_bar_spec.js
index f50db6ab210..f98e0a4c64a 100644
--- a/spec/frontend/batch_comments/components/review_bar_spec.js
+++ b/spec/frontend/batch_comments/components/review_bar_spec.js
@@ -6,6 +6,8 @@ import createStore from '../create_batch_comments_store';
describe('Batch comments review bar component', () => {
let store;
let wrapper;
+ let addEventListenerSpy;
+ let removeEventListenerSpy;
const createComponent = (propsData = {}) => {
store = createStore();
@@ -18,25 +20,58 @@ describe('Batch comments review bar component', () => {
beforeEach(() => {
document.body.className = '';
+
+ addEventListenerSpy = jest.spyOn(window, 'addEventListener');
+ removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
});
afterEach(() => {
+ addEventListenerSpy.mockRestore();
+ removeEventListenerSpy.mockRestore();
wrapper.destroy();
});
- it('it adds review-bar-visible class to body when review bar is mounted', async () => {
- expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(false);
+ describe('when mounted', () => {
+ it('it adds review-bar-visible class to body', async () => {
+ expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(false);
+
+ createComponent();
+
+ expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(true);
+ });
- createComponent();
+ it('it adds a blocking handler to the `beforeunload` window event', () => {
+ expect(addEventListenerSpy).not.toBeCalled();
- expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(true);
+ createComponent();
+
+ expect(addEventListenerSpy).toHaveBeenCalledTimes(1);
+ expect(addEventListenerSpy).toBeCalledWith('beforeunload', expect.any(Function), {
+ capture: true,
+ });
+ });
});
- it('it removes review-bar-visible class to body when review bar is destroyed', async () => {
- createComponent();
+ describe('before destroyed', () => {
+ it('it removes review-bar-visible class to body', async () => {
+ createComponent();
- wrapper.destroy();
+ wrapper.destroy();
- expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(false);
+ expect(document.body.classList.contains(REVIEW_BAR_VISIBLE_CLASS_NAME)).toBe(false);
+ });
+
+ it('it removes the blocking handler from the `beforeunload` window event', () => {
+ createComponent();
+
+ expect(removeEventListenerSpy).not.toBeCalled();
+
+ wrapper.destroy();
+
+ expect(removeEventListenerSpy).toHaveBeenCalledTimes(1);
+ expect(removeEventListenerSpy).toBeCalledWith('beforeunload', expect.any(Function), {
+ capture: true,
+ });
+ });
});
});
diff --git a/spec/frontend/behaviors/components/json_table_spec.js b/spec/frontend/behaviors/components/json_table_spec.js
new file mode 100644
index 00000000000..42b4a051d4d
--- /dev/null
+++ b/spec/frontend/behaviors/components/json_table_spec.js
@@ -0,0 +1,162 @@
+import { GlTable, GlFormInput } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { merge } from 'lodash';
+import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubComponent, RENDER_ALL_SLOTS_TEMPLATE } from 'helpers/stub_component';
+import JSONTable from '~/behaviors/components/json_table.vue';
+
+const TEST_FIELDS = [
+ 'A',
+ {
+ key: 'B',
+ label: 'Second',
+ sortable: true,
+ other: 'foo',
+ },
+ {
+ key: 'C',
+ label: 'Third',
+ },
+ 'D',
+];
+const TEST_ITEMS = [
+ { A: 1, B: 'lorem', C: 2, D: null, E: 'dne' },
+ { A: 2, B: 'ipsum', C: 2, D: null, E: 'dne' },
+ { A: 3, B: 'dolar', C: 2, D: null, E: 'dne' },
+];
+
+describe('behaviors/components/json_table', () => {
+ let wrapper;
+
+ const buildWrapper = ({
+ fields = [],
+ items = [],
+ filter = undefined,
+ caption = undefined,
+ } = {}) => {
+ wrapper = shallowMountExtended(JSONTable, {
+ propsData: {
+ fields,
+ items,
+ hasFilter: filter,
+ caption,
+ },
+ stubs: {
+ GlTable: merge(stubComponent(GlTable), {
+ props: {
+ fields: {
+ type: Array,
+ required: true,
+ },
+ items: {
+ type: Array,
+ required: true,
+ },
+ },
+ template: RENDER_ALL_SLOTS_TEMPLATE,
+ }),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findTableCaption = () => wrapper.findByTestId('slot-table-caption');
+ const findFilterInput = () => wrapper.findComponent(GlFormInput);
+
+ describe('default', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('renders gltable', () => {
+ expect(findTable().props()).toEqual({
+ fields: [],
+ items: [],
+ });
+ expect(findTable().attributes()).toMatchObject({
+ filter: '',
+ 'show-empty': '',
+ });
+ });
+
+ it('does not render filter input', () => {
+ expect(findFilterInput().exists()).toBe(false);
+ });
+
+ it('renders caption', () => {
+ expect(findTableCaption().text()).toBe('Generated with JSON data');
+ });
+ });
+
+ describe('with filter', () => {
+ beforeEach(() => {
+ buildWrapper({
+ filter: true,
+ });
+ });
+
+ it('renders filter input', () => {
+ expect(findFilterInput().attributes()).toMatchObject({
+ value: '',
+ placeholder: 'Type to search',
+ });
+ });
+
+ it('when input is changed, updates table filter', async () => {
+ findFilterInput().vm.$emit('input', 'New value!');
+
+ await nextTick();
+
+ expect(findTable().attributes('filter')).toBe('New value!');
+ });
+ });
+
+ describe('with fields', () => {
+ beforeEach(() => {
+ buildWrapper({
+ fields: TEST_FIELDS,
+ items: TEST_ITEMS,
+ });
+ });
+
+ it('passes cleaned fields and items to table', () => {
+ expect(findTable().props()).toEqual({
+ fields: [
+ 'A',
+ {
+ key: 'B',
+ label: 'Second',
+ sortable: true,
+ },
+ {
+ key: 'C',
+ label: 'Third',
+ sortable: false,
+ },
+ 'D',
+ ],
+ items: TEST_ITEMS,
+ });
+ });
+ });
+
+ describe('with full mount', () => {
+ beforeEach(() => {
+ wrapper = mountExtended(JSONTable, {
+ propsData: {
+ fields: [],
+ items: [],
+ },
+ });
+ });
+
+ // We want to make sure all the props are passed down nicely in integration
+ it('renders table without errors', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index 8842ad636ec..722327e94ba 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -121,7 +121,7 @@ describe('gl_emoji', () => {
window.gon.emoji_sprites_css_path = testPath;
expect(document.head.querySelector(`link[href="${testPath}"]`)).toBe(null);
- expect(window.gon.emoji_sprites_css_added).toBeFalsy();
+ expect(window.gon.emoji_sprites_css_added).toBe(undefined);
markupToDomElement(
'<gl-emoji data-fallback-sprite-class="emoji-bomb" data-name="bomb"></gl-emoji>',
diff --git a/spec/frontend/behaviors/markdown/render_json_table_spec.js b/spec/frontend/behaviors/markdown/render_json_table_spec.js
new file mode 100644
index 00000000000..488492479f3
--- /dev/null
+++ b/spec/frontend/behaviors/markdown/render_json_table_spec.js
@@ -0,0 +1,119 @@
+import { nextTick } from 'vue';
+import { renderJSONTable } from '~/behaviors/markdown/render_json_table';
+
+describe('behaviors/markdown/render_json_table', () => {
+ let element;
+
+ const TEST_DATA = {
+ fields: [
+ { label: 'Field 1', key: 'a' },
+ { label: 'F 2', key: 'b' },
+ { label: 'F 3', key: 'c' },
+ ],
+ items: [
+ {
+ a: '1',
+ b: 'b',
+ c: 'c',
+ },
+ {
+ a: '2',
+ b: 'd',
+ c: 'e',
+ },
+ ],
+ };
+ const TEST_LABELS = TEST_DATA.fields.map((x) => x.label);
+
+ const tableAsData = (table) => ({
+ head: Array.from(table.querySelectorAll('thead th')).map((td) => td.textContent),
+ body: Array.from(table.querySelectorAll('tbody > tr')).map((tr) =>
+ Array.from(tr.querySelectorAll('td')).map((x) => x.textContent),
+ ),
+ });
+
+ const createTestSubject = async (json) => {
+ if (element) {
+ throw new Error('element has already been initialized');
+ }
+
+ const parent = document.createElement('div');
+ const pre = document.createElement('pre');
+
+ pre.textContent = json;
+ parent.appendChild(pre);
+
+ document.body.appendChild(parent);
+ renderJSONTable([parent]);
+
+ element = parent;
+
+ jest.runAllTimers();
+
+ await nextTick();
+ };
+
+ const findPres = () => document.querySelectorAll('pre');
+ const findTables = () => document.querySelectorAll('table');
+ const findAlerts = () => document.querySelectorAll('.gl-alert');
+ const findInputs = () => document.querySelectorAll('.gl-form-input');
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ element = null;
+ });
+
+ describe('default', () => {
+ beforeEach(async () => {
+ await createTestSubject(JSON.stringify(TEST_DATA, null, 2));
+ });
+
+ it('removes pre', () => {
+ expect(findPres()).toHaveLength(0);
+ });
+
+ it('replaces pre with table', () => {
+ const tables = findTables();
+
+ expect(tables).toHaveLength(1);
+ expect(tableAsData(tables[0])).toEqual({
+ head: TEST_LABELS,
+ body: [
+ ['1', 'b', 'c'],
+ ['2', 'd', 'e'],
+ ],
+ });
+ });
+
+ it('does not show filter', () => {
+ expect(findInputs()).toHaveLength(0);
+ });
+ });
+
+ describe('with invalid json', () => {
+ beforeEach(() => {
+ createTestSubject('funky but not json');
+ });
+
+ it('preserves pre', () => {
+ expect(findPres()).toHaveLength(1);
+ });
+
+ it('shows alert', () => {
+ const alerts = findAlerts();
+
+ expect(alerts).toHaveLength(1);
+ expect(alerts[0].textContent).toMatchInterpolatedText('Unable to parse JSON');
+ });
+ });
+
+ describe('with filter set', () => {
+ beforeEach(() => {
+ createTestSubject(JSON.stringify({ ...TEST_DATA, filter: true }));
+ });
+
+ it('shows filter', () => {
+ expect(findInputs()).toHaveLength(1);
+ });
+ });
+});
diff --git a/spec/frontend/blob/3d_viewer/mesh_object_spec.js b/spec/frontend/blob/3d_viewer/mesh_object_spec.js
index 60be285039f..3014af073f5 100644
--- a/spec/frontend/blob/3d_viewer/mesh_object_spec.js
+++ b/spec/frontend/blob/3d_viewer/mesh_object_spec.js
@@ -5,7 +5,7 @@ describe('Mesh object', () => {
it('defaults to non-wireframe material', () => {
const object = new MeshObject(new BoxGeometry(10, 10, 10));
- expect(object.material.wireframe).toBeFalsy();
+ expect(object.material.wireframe).toBe(false);
});
it('changes to wirefame material', () => {
@@ -13,7 +13,7 @@ describe('Mesh object', () => {
object.changeMaterial('wireframe');
- expect(object.material.wireframe).toBeTruthy();
+ expect(object.material.wireframe).toBe(true);
});
it('scales object down', () => {
diff --git a/spec/frontend/blob/blob_links_tracking_spec.js b/spec/frontend/blob/blob_links_tracking_spec.js
new file mode 100644
index 00000000000..22e087bc180
--- /dev/null
+++ b/spec/frontend/blob/blob_links_tracking_spec.js
@@ -0,0 +1,60 @@
+import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import addBlobLinksTracking from '~/blob/blob_links_tracking';
+import Tracking from '~/tracking';
+
+describe('Blob links Tracking', () => {
+ const eventName = 'click_link';
+ const label = 'file_line_action';
+
+ const eventsToTrack = [
+ { selector: '.file-line-blame', property: 'blame' },
+ { selector: '.file-line-num', property: 'link' },
+ ];
+
+ const [blameLinkClickEvent, numLinkClickEvent] = eventsToTrack;
+
+ beforeEach(() => {
+ setHTMLFixture(`
+ <div id="blob-content-holder">
+ <div class="line-links diff-line-num">
+ <a href="#L5" class="file-line-blame"></a>
+ <a id="L5" href="#L5" data-line-number="5" class="file-line-num">5</a>
+ </div>
+ <pre id="LC5">Line 5 content</pre>
+ </div>
+ `);
+ addBlobLinksTracking('#blob-content-holder', eventsToTrack);
+ jest.spyOn(Tracking, 'event');
+ });
+
+ afterEach(() => {
+ resetHTMLFixture();
+ });
+
+ it('tracks blame link click event', () => {
+ const blameButton = document.querySelector(blameLinkClickEvent.selector);
+ blameButton.click();
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, eventName, {
+ label,
+ property: blameLinkClickEvent.property,
+ });
+ });
+
+ it('tracks num link click event', () => {
+ const numLinkButton = document.querySelector(numLinkClickEvent.selector);
+ numLinkButton.click();
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, eventName, {
+ label,
+ property: numLinkClickEvent.property,
+ });
+ });
+
+ it("doesn't fire tracking if the user clicks on any element that is not a link", () => {
+ const codeLine = document.querySelector('#LC5');
+ codeLine.click();
+
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/blob/components/blob_content_spec.js b/spec/frontend/blob/components/blob_content_spec.js
index 8450c6b9332..788ee0a86ab 100644
--- a/spec/frontend/blob/components/blob_content_spec.js
+++ b/spec/frontend/blob/components/blob_content_spec.js
@@ -36,20 +36,20 @@ describe('Blob Content component', () => {
describe('rendering', () => {
it('renders loader if `loading: true`', () => {
createComponent({ loading: true });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(BlobContentError).exists()).toBe(false);
- expect(wrapper.find(RichViewer).exists()).toBe(false);
- expect(wrapper.find(SimpleViewer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(BlobContentError).exists()).toBe(false);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(false);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(false);
});
it('renders error if there is any in the viewer', () => {
const renderError = 'Oops';
const viewer = { ...SimpleViewerMock, renderError };
createComponent({}, viewer);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(BlobContentError).exists()).toBe(true);
- expect(wrapper.find(RichViewer).exists()).toBe(false);
- expect(wrapper.find(SimpleViewer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(BlobContentError).exists()).toBe(true);
+ expect(wrapper.findComponent(RichViewer).exists()).toBe(false);
+ expect(wrapper.findComponent(SimpleViewer).exists()).toBe(false);
});
it.each`
@@ -60,7 +60,7 @@ describe('Blob Content component', () => {
'renders $type viewer when activeViewer is $type and no loading or error detected',
({ mock, viewer }) => {
createComponent({}, mock);
- expect(wrapper.find(viewer).exists()).toBe(true);
+ expect(wrapper.findComponent(viewer).exists()).toBe(true);
},
);
@@ -70,13 +70,13 @@ describe('Blob Content component', () => {
${RichBlobContentMock.richData} | ${RichViewerMock} | ${RichViewer}
`('renders correct content that is passed to the component', ({ content, mock, viewer }) => {
createComponent({ content }, mock);
- expect(wrapper.find(viewer).html()).toContain(content);
+ expect(wrapper.findComponent(viewer).html()).toContain(content);
});
});
describe('functionality', () => {
describe('render error', () => {
- const findErrorEl = () => wrapper.find(BlobContentError);
+ const findErrorEl = () => wrapper.findComponent(BlobContentError);
const renderError = BLOB_RENDER_ERRORS.REASONS.COLLAPSED.id;
const viewer = { ...SimpleViewerMock, renderError };
diff --git a/spec/frontend/blob/components/blob_edit_content_spec.js b/spec/frontend/blob/components/blob_edit_content_spec.js
index 9fc2356c018..5017b624292 100644
--- a/spec/frontend/blob/components/blob_edit_content_spec.js
+++ b/spec/frontend/blob/components/blob_edit_content_spec.js
@@ -69,7 +69,7 @@ describe('Blob Header Editing', () => {
});
it('initialises Source Editor', () => {
- const el = wrapper.find({ ref: 'editor' }).element;
+ const el = wrapper.findComponent({ ref: 'editor' }).element;
expect(utils.initSourceEditor).toHaveBeenCalledWith({
el,
blobPath: fileName,
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index b1ce0e9a4c5..c84b5896348 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -16,7 +16,7 @@ describe('Blob Header Editing', () => {
});
};
const findDeleteButton = () =>
- wrapper.findAll(GlButton).wrappers.find((x) => x.text() === 'Delete file');
+ wrapper.findAllComponents(GlButton).wrappers.find((x) => x.text() === 'Delete file');
beforeEach(() => {
createComponent();
@@ -32,7 +32,7 @@ describe('Blob Header Editing', () => {
});
it('contains a form input field', () => {
- expect(wrapper.find(GlFormInput).exists()).toBe(true);
+ expect(wrapper.findComponent(GlFormInput).exists()).toBe(true);
});
it('does not show delete button', () => {
@@ -42,7 +42,7 @@ describe('Blob Header Editing', () => {
describe('functionality', () => {
it('emits input event when the blob name is changed', async () => {
- const inputComponent = wrapper.find(GlFormInput);
+ const inputComponent = wrapper.findComponent(GlFormInput);
const newValue = 'bar.txt';
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
diff --git a/spec/frontend/blob/components/blob_header_default_actions_spec.js b/spec/frontend/blob/components/blob_header_default_actions_spec.js
index aa538facae2..0f015715dc2 100644
--- a/spec/frontend/blob/components/blob_header_default_actions_spec.js
+++ b/spec/frontend/blob/components/blob_header_default_actions_spec.js
@@ -30,8 +30,8 @@ describe('Blob Header Default Actions', () => {
beforeEach(() => {
createComponent();
- btnGroup = wrapper.find(GlButtonGroup);
- buttons = wrapper.findAll(GlButton);
+ btnGroup = wrapper.findComponent(GlButtonGroup);
+ buttons = wrapper.findAllComponents(GlButton);
});
afterEach(() => {
@@ -69,9 +69,9 @@ describe('Blob Header Default Actions', () => {
createComponent({
activeViewer: RICH_BLOB_VIEWER,
});
- buttons = wrapper.findAll(GlButton);
+ buttons = wrapper.findAllComponents(GlButton);
- expect(buttons.at(0).attributes('disabled')).toBeTruthy();
+ expect(buttons.at(0).attributes('disabled')).toBe('true');
});
it('does not render the copy button if a rendering error is set', () => {
diff --git a/spec/frontend/blob/components/blob_header_filepath_spec.js b/spec/frontend/blob/components/blob_header_filepath_spec.js
index 8220b598ff6..8c32cba1ba4 100644
--- a/spec/frontend/blob/components/blob_header_filepath_spec.js
+++ b/spec/frontend/blob/components/blob_header_filepath_spec.js
@@ -25,7 +25,7 @@ describe('Blob Header Filepath', () => {
wrapper.destroy();
});
- const findBadge = () => wrapper.find(GlBadge);
+ const findBadge = () => wrapper.findComponent(GlBadge);
describe('rendering', () => {
it('matches the snapshot', () => {
@@ -46,7 +46,7 @@ describe('Blob Header Filepath', () => {
it('renders copy-to-clipboard icon that copies path of the Blob', () => {
createComponent();
- const btn = wrapper.find(ClipboardButton);
+ const btn = wrapper.findComponent(ClipboardButton);
expect(btn.exists()).toBe(true);
expect(btn.vm.text).toBe(MockBlob.path);
});
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
index ee42c2387ae..46740958090 100644
--- a/spec/frontend/blob/components/blob_header_spec.js
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -31,7 +31,7 @@ describe('Blob Header Default Actions', () => {
});
describe('rendering', () => {
- const findDefaultActions = () => wrapper.find(DefaultActions);
+ const findDefaultActions = () => wrapper.findComponent(DefaultActions);
const slots = {
prepend: 'Foo Prepend',
@@ -45,17 +45,17 @@ describe('Blob Header Default Actions', () => {
it('renders all components', () => {
createComponent();
- expect(wrapper.find(TableContents).exists()).toBe(true);
- expect(wrapper.find(ViewerSwitcher).exists()).toBe(true);
+ expect(wrapper.findComponent(TableContents).exists()).toBe(true);
+ expect(wrapper.findComponent(ViewerSwitcher).exists()).toBe(true);
expect(findDefaultActions().exists()).toBe(true);
- expect(wrapper.find(BlobFilepath).exists()).toBe(true);
+ expect(wrapper.findComponent(BlobFilepath).exists()).toBe(true);
});
it('does not render viewer switcher if the blob has only the simple viewer', () => {
createComponent({
richViewer: null,
});
- expect(wrapper.find(ViewerSwitcher).exists()).toBe(false);
+ expect(wrapper.findComponent(ViewerSwitcher).exists()).toBe(false);
});
it('does not render viewer switcher if a corresponding prop is passed', () => {
@@ -66,7 +66,7 @@ describe('Blob Header Default Actions', () => {
hideViewerSwitcher: true,
},
);
- expect(wrapper.find(ViewerSwitcher).exists()).toBe(false);
+ expect(wrapper.findComponent(ViewerSwitcher).exists()).toBe(false);
});
it('does not render default actions is corresponding prop is passed', () => {
@@ -77,7 +77,7 @@ describe('Blob Header Default Actions', () => {
hideDefaultActions: true,
},
);
- expect(wrapper.find(DefaultActions).exists()).toBe(false);
+ expect(wrapper.findComponent(DefaultActions).exists()).toBe(false);
});
Object.keys(slots).forEach((slot) => {
diff --git a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
index 91baaf3ea69..1eac0733646 100644
--- a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
+++ b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
@@ -35,8 +35,8 @@ describe('Blob Header Viewer Switcher', () => {
beforeEach(() => {
createComponent();
- btnGroup = wrapper.find(GlButtonGroup);
- buttons = wrapper.findAll(GlButton);
+ btnGroup = wrapper.findComponent(GlButtonGroup);
+ buttons = wrapper.findAllComponents(GlButton);
});
it('renders gl-button-group component', () => {
@@ -58,7 +58,7 @@ describe('Blob Header Viewer Switcher', () => {
function factory(propsData = {}) {
createComponent(propsData);
- buttons = wrapper.findAll(GlButton);
+ buttons = wrapper.findAllComponents(GlButton);
simpleBtn = buttons.at(0);
richBtn = buttons.at(1);
diff --git a/spec/frontend/blob/notebook/notebook_viever_spec.js b/spec/frontend/blob/notebook/notebook_viever_spec.js
index 93406db2675..ea4badc03fb 100644
--- a/spec/frontend/blob/notebook/notebook_viever_spec.js
+++ b/spec/frontend/blob/notebook/notebook_viever_spec.js
@@ -31,10 +31,10 @@ describe('iPython notebook renderer', () => {
wrapper = shallowMount(component, { propsData: { endpoint, relativeRawPath } });
};
- const findLoading = () => wrapper.find(GlLoadingIcon);
- const findNotebookLab = () => wrapper.find(NotebookLab);
- const findLoadErrorMessage = () => wrapper.find({ ref: 'loadErrorMessage' });
- const findParseErrorMessage = () => wrapper.find({ ref: 'parsingErrorMessage' });
+ const findLoading = () => wrapper.findComponent(GlLoadingIcon);
+ const findNotebookLab = () => wrapper.findComponent(NotebookLab);
+ const findLoadErrorMessage = () => wrapper.findComponent({ ref: 'loadErrorMessage' });
+ const findParseErrorMessage = () => wrapper.findComponent({ ref: 'parsingErrorMessage' });
beforeEach(() => {
mock = new MockAdapter(axios);
diff --git a/spec/frontend/blob/pdf/pdf_viewer_spec.js b/spec/frontend/blob/pdf/pdf_viewer_spec.js
index e332ea49fa6..23227df6357 100644
--- a/spec/frontend/blob/pdf/pdf_viewer_spec.js
+++ b/spec/frontend/blob/pdf/pdf_viewer_spec.js
@@ -18,9 +18,9 @@ describe('PDF renderer', () => {
});
};
- const findLoading = () => wrapper.find(GlLoadingIcon);
- const findPdfLab = () => wrapper.find(PdfLab);
- const findLoadError = () => wrapper.find({ ref: 'loadError' });
+ const findLoading = () => wrapper.findComponent(GlLoadingIcon);
+ const findPdfLab = () => wrapper.findComponent(PdfLab);
+ const findLoadError = () => wrapper.findComponent({ ref: 'loadError' });
beforeEach(() => {
mountComponent();
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index 750dd8f0a72..81b38cfc278 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -52,7 +52,7 @@ describe('PipelineTourSuccessModal', () => {
});
it('renders the path from the commit cookie for back to the merge request button', () => {
- const goToMrBtn = wrapper.find({ ref: 'goToMergeRequest' });
+ const goToMrBtn = wrapper.findComponent({ ref: 'goToMergeRequest' });
expect(goToMrBtn.attributes('href')).toBe(expectedMrPath);
});
@@ -67,16 +67,16 @@ describe('PipelineTourSuccessModal', () => {
});
it('renders the path from projectMergeRequestsPath for back to the merge request button', () => {
- const goToMrBtn = wrapper.find({ ref: 'goToMergeRequest' });
+ const goToMrBtn = wrapper.findComponent({ ref: 'goToMergeRequest' });
expect(goToMrBtn.attributes('href')).toBe(expectedMrPath);
});
});
it('has expected structure', () => {
- const modal = wrapper.find(GlModal);
- const sprintf = modal.find(GlSprintf);
- const emoji = modal.find(GlEmoji);
+ const modal = wrapper.findComponent(GlModal);
+ const sprintf = modal.findComponent(GlSprintf);
+ const emoji = modal.findComponent(GlEmoji);
expect(wrapper.text()).toContain("That's it, well done!");
expect(sprintf.exists()).toBe(true);
@@ -84,7 +84,7 @@ describe('PipelineTourSuccessModal', () => {
});
it('renders the link for codeQualityLink', () => {
- expect(wrapper.find(GlLink).attributes('href')).toBe('/code-quality-link');
+ expect(wrapper.findComponent(GlLink).attributes('href')).toBe('/code-quality-link');
});
it('calls to remove cookie', () => {
@@ -103,7 +103,7 @@ describe('PipelineTourSuccessModal', () => {
it('send an event when go to pipelines is clicked', () => {
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- const goToBtn = wrapper.find({ ref: 'goToPipelines' });
+ const goToBtn = wrapper.findComponent({ ref: 'goToPipelines' });
triggerEvent(goToBtn.element);
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
@@ -115,7 +115,7 @@ describe('PipelineTourSuccessModal', () => {
it('sends an event when back to the merge request is clicked', () => {
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- const goToBtn = wrapper.find({ ref: 'goToMergeRequest' });
+ const goToBtn = wrapper.findComponent({ ref: 'goToMergeRequest' });
triggerEvent(goToBtn.element);
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
diff --git a/spec/frontend/blob/sketch/index_spec.js b/spec/frontend/blob/sketch/index_spec.js
index 5e1922a24f4..e8d1f724c4b 100644
--- a/spec/frontend/blob/sketch/index_spec.js
+++ b/spec/frontend/blob/sketch/index_spec.js
@@ -69,7 +69,7 @@ describe('Sketch viewer', () => {
const img = document.querySelector('#js-sketch-viewer img');
expect(img).not.toBeNull();
- expect(img.classList.contains('img-fluid')).toBeTruthy();
+ expect(img.classList.contains('img-fluid')).toBe(true);
});
it('renders link to image', () => {
diff --git a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
index 7e13994f2b7..6b329dc078a 100644
--- a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
+++ b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
@@ -98,7 +98,7 @@ describe('Suggest gitlab-ci.yml Popover', () => {
const expectedAction = 'click_button';
const expectedProperty = 'owner';
const expectedValue = '10';
- const dismissButton = wrapper.find(GlButton);
+ const dismissButton = wrapper.findComponent(GlButton);
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
triggerEvent(dismissButton.element);
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index c6de3ee69f3..985902b4a3b 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -238,7 +238,7 @@ describe('Board card component', () => {
});
it('renders assignee', () => {
- expect(wrapper.find('.board-card-assignee .avatar').exists()).toBe(true);
+ expect(wrapper.find('.board-card-assignee .gl-avatar').exists()).toBe(true);
});
it('sets title', () => {
@@ -336,7 +336,7 @@ describe('Board card component', () => {
});
it('renders all three assignees', () => {
- expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(3);
+ expect(wrapper.findAll('.board-card-assignee .gl-avatar').length).toEqual(3);
});
describe('more than three assignees', () => {
@@ -362,7 +362,7 @@ describe('Board card component', () => {
});
it('renders two assignees', () => {
- expect(wrapper.findAll('.board-card-assignee .avatar').length).toEqual(2);
+ expect(wrapper.findAll('.board-card-assignee .gl-avatar').length).toEqual(2);
});
it('renders 99+ avatar counter', async () => {
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index fd9d2b6823d..9b0c0b93ffb 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -56,7 +56,7 @@ describe('Board list component', () => {
});
it('renders issues', () => {
- expect(wrapper.findAll(BoardCard).length).toBe(1);
+ expect(wrapper.findAllComponents(BoardCard).length).toBe(1);
});
it('sets data attribute with issue id', () => {
diff --git a/spec/frontend/boards/components/board_add_new_column_form_spec.js b/spec/frontend/boards/components/board_add_new_column_form_spec.js
index 3b26ca57d6f..0b3c6cb24c4 100644
--- a/spec/frontend/boards/components/board_add_new_column_form_spec.js
+++ b/spec/frontend/boards/components/board_add_new_column_form_spec.js
@@ -60,8 +60,8 @@ describe('Board card layout', () => {
});
const formTitle = () => wrapper.findByTestId('board-add-column-form-title').text();
- const findSearchInput = () => wrapper.find(GlSearchBoxByType);
- const findSearchLabel = () => wrapper.find(GlFormGroup);
+ const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
+ const findSearchLabelFormGroup = () => wrapper.findComponent(GlFormGroup);
const cancelButton = () => wrapper.findByTestId('cancelAddNewColumn');
const submitButton = () => wrapper.findByTestId('addNewColumnButton');
const findDropdown = () => wrapper.findComponent(GlDropdown);
@@ -121,10 +121,17 @@ describe('Board card layout', () => {
mountComponent(props);
- expect(findSearchLabel().attributes('label')).toEqual(props.searchLabel);
+ expect(findSearchLabelFormGroup().attributes('label')).toEqual(props.searchLabel);
expect(findSearchInput().attributes('placeholder')).toEqual(props.searchPlaceholder);
});
+ it('does not show the dropdown as invalid by default', () => {
+ mountComponent();
+
+ expect(findSearchLabelFormGroup().attributes('state')).toBe('true');
+ expect(findDropdown().props('toggleClass')).not.toContain('gl-inset-border-1-red-400!');
+ });
+
it('emits filter event on input', () => {
mountComponent();
@@ -137,13 +144,13 @@ describe('Board card layout', () => {
});
describe('Add list button', () => {
- it('is disabled if no item is selected', () => {
+ it('is enabled by default', () => {
mountComponent();
- expect(submitButton().props('disabled')).toBe(true);
+ expect(submitButton().props('disabled')).toBe(false);
});
- it('emits add-list event on click', () => {
+ it('emits add-list event on click when an ID is selected', () => {
mountComponent({
selectedId: mockLabelList.label.id,
});
@@ -152,5 +159,16 @@ describe('Board card layout', () => {
expect(wrapper.emitted('add-list')).toEqual([[]]);
});
+
+ it('does not emit the add-list event on click and shows the dropdown as invalid when no ID is selected', async () => {
+ mountComponent();
+
+ await submitButton().vm.$emit('click');
+
+ expect(findSearchLabelFormGroup().attributes('state')).toBeUndefined();
+ expect(findDropdown().props('toggleClass')).toContain('gl-inset-border-1-red-400!');
+
+ expect(wrapper.emitted('add-list')).toBeUndefined();
+ });
});
});
diff --git a/spec/frontend/boards/components/board_add_new_column_trigger_spec.js b/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
index 7dd02bf1d35..354eb7bff16 100644
--- a/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
+++ b/spec/frontend/boards/components/board_add_new_column_trigger_spec.js
@@ -39,7 +39,7 @@ describe('BoardAddNewColumnTrigger', () => {
});
it('renders an enabled button', () => {
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.props('disabled')).toBe(false);
});
@@ -47,7 +47,7 @@ describe('BoardAddNewColumnTrigger', () => {
describe('when button is disabled', () => {
it('shows the tooltip', async () => {
- wrapper.find(GlButton).vm.$emit('click');
+ wrapper.findComponent(GlButton).vm.$emit('click');
await nextTick();
diff --git a/spec/frontend/boards/components/board_blocked_icon_spec.js b/spec/frontend/boards/components/board_blocked_icon_spec.js
index 7a5c49bd488..cf4ba07da16 100644
--- a/spec/frontend/boards/components/board_blocked_icon_spec.js
+++ b/spec/frontend/boards/components/board_blocked_icon_spec.js
@@ -23,9 +23,9 @@ describe('BoardBlockedIcon', () => {
let wrapper;
let mockApollo;
- const findGlIcon = () => wrapper.find(GlIcon);
- const findGlPopover = () => wrapper.find(GlPopover);
- const findGlLink = () => wrapper.find(GlLink);
+ 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');
@@ -114,7 +114,7 @@ describe('BoardBlockedIcon', () => {
it('should display a loading spinner while loading', () => {
createWrapper({ loading: true });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('should not query for blocking issuables by default', async () => {
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 17a5383a31e..bb1e63a581e 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -88,7 +88,7 @@ describe('Board card', () => {
createStore({ initialState: { isShowingLabels: true } });
mountComponent({ mountFn: mount, stubs: {} });
- wrapper.find(GlLabel).trigger('mouseup');
+ wrapper.findComponent(GlLabel).trigger('mouseup');
expect(mockActions.toggleBoardItem).toHaveBeenCalledTimes(0);
});
diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js
index 368c7d561f8..7e35c39cd48 100644
--- a/spec/frontend/boards/components/board_content_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_content_sidebar_spec.js
@@ -108,7 +108,7 @@ describe('BoardContentSidebar', () => {
createStore({ mockGetters: { isSidebarOpen: () => false } });
createComponent();
- expect(wrapper.findComponent(GlDrawer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDrawer).props('open')).toBe(false);
});
it('applies an open attribute', () => {
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
index f535679b8a0..97d9e08f5d4 100644
--- a/spec/frontend/boards/components/board_content_spec.js
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -67,12 +67,12 @@ describe('BoardContent', () => {
});
it('renders BoardContentSidebar', () => {
- expect(wrapper.find(BoardContentSidebar).exists()).toBe(true);
+ expect(wrapper.findComponent(BoardContentSidebar).exists()).toBe(true);
});
it('does not display EpicsSwimlanes component', () => {
- expect(wrapper.find(EpicsSwimlanes).exists()).toBe(false);
- expect(wrapper.find(GlAlert).exists()).toBe(false);
+ expect(wrapper.findComponent(EpicsSwimlanes).exists()).toBe(false);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
});
});
@@ -82,7 +82,7 @@ describe('BoardContent', () => {
});
it('does not render BoardContentSidebar', () => {
- expect(wrapper.find(BoardContentSidebar).exists()).toBe(false);
+ expect(wrapper.findComponent(BoardContentSidebar).exists()).toBe(false);
});
});
@@ -92,7 +92,7 @@ describe('BoardContent', () => {
});
it('renders draggable component', () => {
- expect(wrapper.find(Draggable).exists()).toBe(true);
+ expect(wrapper.findComponent(Draggable).exists()).toBe(true);
});
});
@@ -102,7 +102,7 @@ describe('BoardContent', () => {
});
it('does not render draggable component', () => {
- expect(wrapper.find(Draggable).exists()).toBe(false);
+ expect(wrapper.findComponent(Draggable).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 2f9677680eb..50901f3fe84 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -83,7 +83,7 @@ describe('Board List Header Component', () => {
const isCollapsed = () => wrapper.vm.list.collapsed;
- const findAddIssueButton = () => wrapper.find({ ref: 'newIssueBtn' });
+ const findAddIssueButton = () => wrapper.findComponent({ ref: 'newIssueBtn' });
const findTitle = () => wrapper.find('.board-title');
const findCaret = () => wrapper.findByTestId('board-title-caret');
diff --git a/spec/frontend/boards/components/board_new_item_spec.js b/spec/frontend/boards/components/board_new_item_spec.js
index 86cebc8a719..f4e9901aad2 100644
--- a/spec/frontend/boards/components/board_new_item_spec.js
+++ b/spec/frontend/boards/components/board_new_item_spec.js
@@ -44,7 +44,7 @@ describe('BoardNewItem', () => {
it('finds an enabled create button', async () => {
expect(wrapper.findByTestId('create-button').props('disabled')).toBe(true);
- wrapper.find(GlFormInput).vm.$emit('input', 'hello');
+ wrapper.findComponent(GlFormInput).vm.$emit('input', 'hello');
await nextTick();
expect(wrapper.findByTestId('create-button').props('disabled')).toBe(false);
@@ -53,7 +53,7 @@ describe('BoardNewItem', () => {
describe('when the user types in a string with only spaces', () => {
it('disables the Create Issue button', async () => {
- wrapper.find(GlFormInput).vm.$emit('input', ' ');
+ wrapper.findComponent(GlFormInput).vm.$emit('input', ' ');
await nextTick();
@@ -93,7 +93,7 @@ describe('BoardNewItem', () => {
titleInput().setValue('Foo');
await glForm().trigger('submit');
- expect(wrapper.emitted('form-submit')).toBeTruthy();
+ expect(wrapper.emitted('form-submit')).toHaveLength(1);
expect(wrapper.emitted('form-submit')[0]).toEqual([
{
title: 'Foo',
@@ -131,7 +131,7 @@ describe('BoardNewItem', () => {
await glForm().trigger('reset');
expect(titleInput().element.value).toBe('');
- expect(wrapper.emitted('form-cancel')).toBeTruthy();
+ expect(wrapper.emitted('form-cancel')).toHaveLength(1);
});
});
});
diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js
index 7f40c426b30..4171a6236de 100644
--- a/spec/frontend/boards/components/board_settings_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js
@@ -57,10 +57,10 @@ describe('BoardSettingsSidebar', () => {
}),
);
};
- const findLabel = () => wrapper.find(GlLabel);
- const findDrawer = () => wrapper.find(GlDrawer);
- const findModal = () => wrapper.find(GlModal);
- const findRemoveButton = () => wrapper.find(GlButton);
+ const findLabel = () => wrapper.findComponent(GlLabel);
+ const findDrawer = () => wrapper.findComponent(GlDrawer);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findRemoveButton = () => wrapper.findComponent(GlButton);
afterEach(() => {
jest.restoreAllMocks();
@@ -71,7 +71,7 @@ describe('BoardSettingsSidebar', () => {
it('finds a MountingPortal component', () => {
createComponent();
- expect(wrapper.find(MountingPortal).props()).toMatchObject({
+ expect(wrapper.findComponent(MountingPortal).props()).toMatchObject({
mountTo: '#js-right-sidebar-portal',
append: true,
name: 'board-settings-sidebar',
@@ -93,7 +93,7 @@ describe('BoardSettingsSidebar', () => {
await nextTick();
- expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDrawer).props('open')).toBe(false);
});
it('closes the sidebar when emitting the correct event', async () => {
@@ -103,7 +103,7 @@ describe('BoardSettingsSidebar', () => {
await nextTick();
- expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDrawer).props('open')).toBe(false);
});
});
@@ -150,7 +150,7 @@ describe('BoardSettingsSidebar', () => {
it('does not render GlDrawer', () => {
createComponent({ sidebarType: '' });
- expect(findDrawer().exists()).toBe(false);
+ expect(findDrawer().props('open')).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index d91e81fe4d0..f3be66db36f 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -53,7 +53,7 @@ describe('BoardsSelector', () => {
};
const fillSearchBox = (filterTerm) => {
- const searchBox = wrapper.find({ ref: 'searchBox' });
+ const searchBox = wrapper.findComponent({ ref: 'searchBox' });
const searchBoxInput = searchBox.find('input');
searchBoxInput.setValue(filterTerm);
searchBoxInput.trigger('input');
diff --git a/spec/frontend/boards/components/new_board_button_spec.js b/spec/frontend/boards/components/new_board_button_spec.js
index 075fe225ec2..2bbd3797abf 100644
--- a/spec/frontend/boards/components/new_board_button_spec.js
+++ b/spec/frontend/boards/components/new_board_button_spec.js
@@ -53,13 +53,13 @@ describe('NewBoardButton', () => {
it('renders nothing when `canAdminBoard` is `false`', () => {
wrapper = createComponent({ canAdminBoard: false });
- expect(wrapper.find(GlButton).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(false);
});
it('renders nothing when `multipleIssueBoardsAvailable` is `false`', () => {
wrapper = createComponent({ multipleIssueBoardsAvailable: false });
- expect(wrapper.find(GlButton).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(false);
});
it('emits `showBoardModal` when button is clicked', () => {
@@ -67,7 +67,7 @@ describe('NewBoardButton', () => {
wrapper = createComponent();
- wrapper.find(GlButton).vm.$emit('click', { preventDefault: () => {} });
+ wrapper.findComponent(GlButton).vm.$emit('click', { preventDefault: () => {} });
expect(eventHub.$emit).toHaveBeenCalledWith('showBoardModal', 'new');
});
diff --git a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
index 0c76c711b3a..5e2222ac3d7 100644
--- a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
@@ -6,7 +6,7 @@ import BoardSidebarItem from '~/boards/components/sidebar/board_editable_item.vu
describe('boards sidebar remove issue', () => {
let wrapper;
- const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findLoader = () => wrapper.findComponent(GlLoadingIcon);
const findEditButton = () => wrapper.find('[data-testid="edit-button"]');
const findTitle = () => wrapper.find('[data-testid="title"]');
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
index 7c8996be0b8..5c435643425 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_time_tracker_spec.js
@@ -47,7 +47,7 @@ describe('BoardSidebarTimeTracker', () => {
(timeTrackingLimitToHours) => {
createComponent({ provide: { timeTrackingLimitToHours } });
- expect(wrapper.find(IssuableTimeTracker).props()).toEqual({
+ expect(wrapper.findComponent(IssuableTimeTracker).props()).toEqual({
limitToHours: timeTrackingLimitToHours,
showCollapsed: false,
issuableId: '1',
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
index 5364d929c38..cc1e5de15c1 100644
--- a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
+++ b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js
@@ -46,10 +46,10 @@ describe('~/boards/components/sidebar/board_sidebar_title.vue', () => {
});
};
- const findForm = () => wrapper.find(GlForm);
- const findAlert = () => wrapper.find(GlAlert);
- const findFormInput = () => wrapper.find(GlFormInput);
- const findEditableItem = () => wrapper.find(BoardEditableItem);
+ const findForm = () => wrapper.findComponent(GlForm);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findFormInput = () => wrapper.findComponent(GlFormInput);
+ const findEditableItem = () => wrapper.findComponent(BoardEditableItem);
const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
const findTitle = () => wrapper.find('[data-testid="item-title"]');
const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js
index c45cd545155..7ff34ffdf9e 100644
--- a/spec/frontend/boards/project_select_spec.js
+++ b/spec/frontend/boards/project_select_spec.js
@@ -10,7 +10,6 @@ import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import ProjectSelect from '~/boards/components/project_select.vue';
import defaultState from '~/boards/stores/state';
-import waitForPromises from 'helpers/wait_for_promises';
import { mockList, mockActiveGroupProjects } from './mock_data';
@@ -23,9 +22,9 @@ describe('ProjectSelect component', () => {
const findLabel = () => wrapper.find("[data-testid='header-label']");
const findGlDropdown = () => wrapper.findComponent(GlDropdown);
const findGlDropdownLoadingIcon = () =>
- findGlDropdown().find('button:first-child').find(GlLoadingIcon);
- const findGlSearchBoxByType = () => wrapper.find(GlSearchBoxByType);
- const findGlDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ findGlDropdown().find('button:first-child').findComponent(GlLoadingIcon);
+ const findGlSearchBoxByType = () => wrapper.findComponent(GlSearchBoxByType);
+ const findGlDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findFirstGlDropdownItem = () => findGlDropdownItems().at(0);
const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']");
const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']");
@@ -133,7 +132,7 @@ describe('ProjectSelect component', () => {
const dropdownToggle = findGlDropdown().find('.dropdown-toggle');
await dropdownToggle.trigger('click');
- await waitForPromises();
+ jest.runOnlyPendingTimers();
await nextTick();
const searchInput = findGlDropdown().findComponent(GlFormInput).element;
diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js
index 7d79993a0ee..1606ca09d8f 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -518,17 +518,6 @@ describe('Board Store Mutations', () => {
expect(state.boardItemsByListId[payload.listId]).toEqual(listState);
});
-
- it("updates the list's items count", () => {
- expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(1);
-
- mutations.ADD_BOARD_ITEM_TO_LIST(state, {
- itemId: mockIssue2.id,
- listId: mockList.id,
- });
-
- expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(2);
- });
});
describe('REMOVE_BOARD_ITEM_FROM_LIST', () => {
@@ -536,8 +525,7 @@ describe('Board Store Mutations', () => {
setBoardsListsState();
});
- it("removes an item from a list and updates the list's items count", () => {
- expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(1);
+ it('removes an item from a list', () => {
expect(state.boardItemsByListId['gid://gitlab/List/1']).toContain(mockIssue.id);
mutations.REMOVE_BOARD_ITEM_FROM_LIST(state, {
@@ -546,7 +534,6 @@ describe('Board Store Mutations', () => {
});
expect(state.boardItemsByListId['gid://gitlab/List/1']).not.toContain(mockIssue.id);
- expect(state.boardLists['gid://gitlab/List/1'].issuesCount).toBe(0);
});
});
diff --git a/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js b/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js
index 08d031a4fa7..2263d2bbeed 100644
--- a/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js
+++ b/spec/frontend/captcha/wait_for_captcha_to_be_solved_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import CaptchaModal from '~/captcha/captcha_modal.vue';
import { waitForCaptchaToBeSolved } from '~/captcha/wait_for_captcha_to_be_solved';
@@ -15,7 +16,7 @@ describe('waitForCaptchaToBeSolved', () => {
it('opens a modal, resolves with captcha response on success', async () => {
CaptchaModal.mounted.mockImplementationOnce(function mounted() {
- requestAnimationFrame(() => {
+ return nextTick().then(() => {
this.$emit('receivedCaptchaResponse', response);
this.$emit('hidden');
});
@@ -36,7 +37,7 @@ describe('waitForCaptchaToBeSolved', () => {
it("opens a modal, rejects with error in case the captcha isn't solved", async () => {
CaptchaModal.mounted.mockImplementationOnce(function mounted() {
- requestAnimationFrame(() => {
+ return nextTick().then(() => {
this.$emit('receivedCaptchaResponse', null);
this.$emit('hidden');
});
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
new file mode 100644
index 00000000000..920ceaefb70
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
@@ -0,0 +1,178 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+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 ciAdminVariables from '~/ci_variable_list/components/ci_admin_variables.vue';
+import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
+import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
+import getAdminVariables from '~/ci_variable_list/graphql/queries/variables.query.graphql';
+
+import addAdminVariable from '~/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql';
+import deleteAdminVariable from '~/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql';
+import updateAdminVariable from '~/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql';
+
+import { genericMutationErrorText, variableFetchErrorText } from '~/ci_variable_list/constants';
+
+import { mockAdminVariables, newVariable } from '../mocks';
+
+jest.mock('~/flash');
+
+Vue.use(VueApollo);
+
+const mockProvide = {
+ endpoint: '/variables',
+};
+
+describe('Ci Admin Variable list', () => {
+ let wrapper;
+
+ let mockApollo;
+ let mockVariables;
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findCiTable = () => wrapper.findComponent(GlTable);
+ const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
+
+ // eslint-disable-next-line consistent-return
+ const createComponentWithApollo = async ({ isLoading = false } = {}) => {
+ const handlers = [[getAdminVariables, mockVariables]];
+
+ mockApollo = createMockApollo(handlers, resolvers);
+
+ wrapper = shallowMount(ciAdminVariables, {
+ provide: mockProvide,
+ apolloProvider: mockApollo,
+ stubs: { ciVariableSettings, ciVariableTable },
+ });
+
+ if (!isLoading) {
+ return waitForPromises();
+ }
+ };
+
+ beforeEach(() => {
+ mockVariables = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('while queries are being fetch', () => {
+ beforeEach(() => {
+ createComponentWithApollo({ isLoading: true });
+ });
+
+ it('shows a loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findCiTable().exists()).toBe(false);
+ });
+ });
+
+ describe('when queries are resolved', () => {
+ describe('successfuly', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockAdminVariables);
+
+ await createComponentWithApollo();
+ });
+
+ it('passes down the expected environments as props', () => {
+ expect(findCiSettings().props('environments')).toEqual([]);
+ });
+
+ it('passes down the expected variables as props', () => {
+ expect(findCiSettings().props('variables')).toEqual(
+ mockAdminVariables.data.ciVariables.nodes,
+ );
+ });
+
+ it('createFlash was not called', () => {
+ expect(createFlash).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('with an error for variables', () => {
+ beforeEach(async () => {
+ mockVariables.mockRejectedValue();
+
+ await createComponentWithApollo();
+ });
+
+ it('calls createFlash with the expected error message', () => {
+ expect(createFlash).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ });
+ });
+ });
+
+ describe('mutations', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockAdminVariables);
+
+ await createComponentWithApollo();
+ });
+ it.each`
+ actionName | mutation | event
+ ${'add'} | ${addAdminVariable} | ${'add-variable'}
+ ${'update'} | ${updateAdminVariable} | ${'update-variable'}
+ ${'delete'} | ${deleteAdminVariable} | ${'delete-variable'}
+ `(
+ 'calls the right mutation when user performs $actionName variable',
+ async ({ event, mutation }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation,
+ variables: {
+ endpoint: mockProvide.endpoint,
+ variable: newVariable,
+ },
+ });
+ },
+ );
+
+ it.each`
+ actionName | event | mutationName
+ ${'add'} | ${'add-variable'} | ${'addAdminVariable'}
+ ${'update'} | ${'update-variable'} | ${'updateAdminVariable'}
+ ${'delete'} | ${'delete-variable'} | ${'deleteAdminVariable'}
+ `(
+ 'throws with the specific graphql error if present when user performs $actionName variable',
+ async ({ event, mutationName }) => {
+ const graphQLErrorMessage = 'There is a problem with this graphQL action';
+ jest
+ .spyOn(wrapper.vm.$apollo, 'mutate')
+ .mockResolvedValue({ data: { [mutationName]: { errors: [graphQLErrorMessage] } } });
+ await findCiSettings().vm.$emit(event, newVariable);
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ },
+ );
+
+ it.each`
+ actionName | event
+ ${'add'} | ${'add-variable'}
+ ${'update'} | ${'update-variable'}
+ ${'delete'} | ${'delete-variable'}
+ `(
+ 'throws generic error when the mutation fails with no graphql errors and user performs $actionName variable',
+ async ({ event }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
+ throw new Error();
+ });
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js b/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js
new file mode 100644
index 00000000000..e9966576cab
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_environments_dropdown_spec.js
@@ -0,0 +1,139 @@
+import { GlDropdown, GlDropdownItem, GlIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { allEnvironments } from '~/ci_variable_list/constants';
+import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
+
+describe('Ci environments dropdown', () => {
+ let wrapper;
+
+ const envs = ['dev', 'prod', 'staging'];
+ const defaultProps = { environments: envs, selectedEnvironmentScope: '' };
+
+ const findDropdownText = () => wrapper.findComponent(GlDropdown).text();
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
+ const findActiveIconByIndex = (index) => findDropdownItemByIndex(index).findComponent(GlIcon);
+ const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
+
+ const createComponent = ({ props = {}, searchTerm = '' } = {}) => {
+ wrapper = mount(CiEnvironmentsDropdown, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+
+ findSearchBox().vm.$emit('input', searchTerm);
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('No environments found', () => {
+ beforeEach(() => {
+ createComponent({ searchTerm: 'stable' });
+ });
+
+ it('renders create button with search term if environments do not contain search term', () => {
+ expect(findAllDropdownItems()).toHaveLength(2);
+ expect(findDropdownItemByIndex(1).text()).toBe('Create wildcard: stable');
+ });
+
+ it('renders empty results message', () => {
+ expect(findDropdownItemByIndex(0).text()).toBe('No matching results');
+ });
+ });
+
+ describe('Search term is empty', () => {
+ beforeEach(() => {
+ createComponent({ props: { environments: envs } });
+ });
+
+ it('renders all environments when search term is empty', () => {
+ expect(findAllDropdownItems()).toHaveLength(3);
+ expect(findDropdownItemByIndex(0).text()).toBe(envs[0]);
+ expect(findDropdownItemByIndex(1).text()).toBe(envs[1]);
+ expect(findDropdownItemByIndex(2).text()).toBe(envs[2]);
+ });
+
+ it('should not display active checkmark on the inactive stage', () => {
+ expect(findActiveIconByIndex(0).classes('gl-visibility-hidden')).toBe(true);
+ });
+ });
+
+ describe('when `*` is the value of selectedEnvironmentScope props', () => {
+ const wildcardScope = '*';
+
+ beforeEach(() => {
+ createComponent({ props: { selectedEnvironmentScope: wildcardScope } });
+ });
+
+ it('shows the `All environments` text and not the wildcard', () => {
+ expect(findDropdownText()).toContain(allEnvironments.text);
+ expect(findDropdownText()).not.toContain(wildcardScope);
+ });
+ });
+
+ describe('Environments found', () => {
+ const currentEnv = envs[2];
+
+ beforeEach(async () => {
+ createComponent({ searchTerm: currentEnv });
+ await nextTick();
+ });
+
+ it('renders only the environment searched for', () => {
+ expect(findAllDropdownItems()).toHaveLength(1);
+ expect(findDropdownItemByIndex(0).text()).toBe(currentEnv);
+ });
+
+ it('should not display create button', () => {
+ const environments = findAllDropdownItems().filter((env) => env.text().startsWith('Create'));
+ expect(environments).toHaveLength(0);
+ expect(findAllDropdownItems()).toHaveLength(1);
+ });
+
+ it('should not display empty results message', () => {
+ expect(wrapper.findComponent({ ref: 'noMatchingResults' }).exists()).toBe(false);
+ });
+
+ it('should clear the search term when showing the dropdown', () => {
+ wrapper.findComponent(GlDropdown).trigger('click');
+
+ expect(findSearchBox().text()).toBe('');
+ });
+
+ describe('Custom events', () => {
+ describe('when clicking on an environment', () => {
+ const itemIndex = 0;
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should emit `select-environment` if an environment is clicked', async () => {
+ await nextTick();
+
+ await findDropdownItemByIndex(itemIndex).vm.$emit('click');
+
+ expect(wrapper.emitted('select-environment')).toEqual([[envs[itemIndex]]]);
+ });
+ });
+
+ describe('when creating a new environment from a search term', () => {
+ const search = 'new-env';
+ beforeEach(() => {
+ createComponent({ searchTerm: search });
+ });
+
+ it('should emit createClicked if an environment is clicked', async () => {
+ await nextTick();
+ findDropdownItemByIndex(1).vm.$emit('click');
+ expect(wrapper.emitted('create-environment-scope')).toEqual([[search]]);
+ });
+ });
+ });
+ });
+});
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
new file mode 100644
index 00000000000..e45656acfd8
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
@@ -0,0 +1,183 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+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 { convertToGraphQLId } from '~/graphql_shared/utils';
+
+import ciGroupVariables from '~/ci_variable_list/components/ci_group_variables.vue';
+import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
+import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
+import getGroupVariables from '~/ci_variable_list/graphql/queries/group_variables.query.graphql';
+
+import addGroupVariable from '~/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql';
+import deleteGroupVariable from '~/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql';
+import updateGroupVariable from '~/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql';
+
+import { genericMutationErrorText, variableFetchErrorText } from '~/ci_variable_list/constants';
+
+import { mockGroupVariables, newVariable } from '../mocks';
+
+jest.mock('~/flash');
+
+Vue.use(VueApollo);
+
+const mockProvide = {
+ endpoint: '/variables',
+ groupPath: '/namespace/group',
+ groupId: 1,
+};
+
+describe('Ci Group Variable list', () => {
+ let wrapper;
+
+ let mockApollo;
+ let mockVariables;
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findCiTable = () => wrapper.findComponent(GlTable);
+ const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
+
+ // eslint-disable-next-line consistent-return
+ const createComponentWithApollo = async ({ isLoading = false } = {}) => {
+ const handlers = [[getGroupVariables, mockVariables]];
+
+ mockApollo = createMockApollo(handlers, resolvers);
+
+ wrapper = shallowMount(ciGroupVariables, {
+ provide: mockProvide,
+ apolloProvider: mockApollo,
+ stubs: { ciVariableSettings, ciVariableTable },
+ });
+
+ if (!isLoading) {
+ return waitForPromises();
+ }
+ };
+
+ beforeEach(() => {
+ mockVariables = jest.fn();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('while queries are being fetch', () => {
+ beforeEach(() => {
+ createComponentWithApollo({ isLoading: true });
+ });
+
+ it('shows a loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findCiTable().exists()).toBe(false);
+ });
+ });
+
+ describe('when queries are resolved', () => {
+ describe('successfuly', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+
+ await createComponentWithApollo();
+ });
+
+ it('passes down the expected environments as props', () => {
+ expect(findCiSettings().props('environments')).toEqual([]);
+ });
+
+ it('passes down the expected variables as props', () => {
+ expect(findCiSettings().props('variables')).toEqual(
+ mockGroupVariables.data.group.ciVariables.nodes,
+ );
+ });
+
+ it('createFlash was not called', () => {
+ expect(createFlash).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('with an error for variables', () => {
+ beforeEach(async () => {
+ mockVariables.mockRejectedValue();
+
+ await createComponentWithApollo();
+ });
+
+ it('calls createFlash with the expected error message', () => {
+ expect(createFlash).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ });
+ });
+ });
+
+ describe('mutations', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+
+ await createComponentWithApollo();
+ });
+ it.each`
+ actionName | mutation | event
+ ${'add'} | ${addGroupVariable} | ${'add-variable'}
+ ${'update'} | ${updateGroupVariable} | ${'update-variable'}
+ ${'delete'} | ${deleteGroupVariable} | ${'delete-variable'}
+ `(
+ 'calls the right mutation when user performs $actionName variable',
+ async ({ event, mutation }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation,
+ variables: {
+ endpoint: mockProvide.endpoint,
+ fullPath: mockProvide.groupPath,
+ groupId: convertToGraphQLId('Group', mockProvide.groupId),
+ variable: newVariable,
+ },
+ });
+ },
+ );
+
+ it.each`
+ actionName | event | mutationName
+ ${'add'} | ${'add-variable'} | ${'addGroupVariable'}
+ ${'update'} | ${'update-variable'} | ${'updateGroupVariable'}
+ ${'delete'} | ${'delete-variable'} | ${'deleteGroupVariable'}
+ `(
+ 'throws with the specific graphql error if present when user performs $actionName variable',
+ async ({ event, mutationName }) => {
+ const graphQLErrorMessage = 'There is a problem with this graphQL action';
+ jest
+ .spyOn(wrapper.vm.$apollo, 'mutate')
+ .mockResolvedValue({ data: { [mutationName]: { errors: [graphQLErrorMessage] } } });
+ await findCiSettings().vm.$emit(event, newVariable);
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ },
+ );
+
+ it.each`
+ actionName | event
+ ${'add'} | ${'add-variable'}
+ ${'update'} | ${'update-variable'}
+ ${'delete'} | ${'delete-variable'}
+ `(
+ 'throws generic error when the mutation fails with no graphql errors and user performs $actionName variable',
+ async ({ event }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
+ throw new Error();
+ });
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
new file mode 100644
index 00000000000..e5019e3261e
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
@@ -0,0 +1,383 @@
+import { GlButton, GlFormInput } from '@gitlab/ui';
+import { mockTracking } from 'helpers/tracking_helper';
+import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
+import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
+import CiVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
+import {
+ ADD_VARIABLE_ACTION,
+ AWS_ACCESS_KEY_ID,
+ EDIT_VARIABLE_ACTION,
+ EVENT_LABEL,
+ EVENT_ACTION,
+ ENVIRONMENT_SCOPE_LINK_TITLE,
+ instanceString,
+} from '~/ci_variable_list/constants';
+import { mockVariablesWithScopes } from '../mocks';
+import ModalStub from '../stubs';
+
+describe('Ci variable modal', () => {
+ let wrapper;
+ let trackingSpy;
+
+ const maskableRegex = '^[a-zA-Z0-9_+=/@:.~-]{8,}$';
+ const mockVariables = mockVariablesWithScopes(instanceString);
+
+ const defaultProvide = {
+ awsLogoSvgPath: '/logo',
+ awsTipCommandsLink: '/tips',
+ awsTipDeployLink: '/deploy',
+ awsTipLearnLink: '/learn-link',
+ containsVariableReferenceLink: '/reference',
+ environmentScopeLink: '/help/environments',
+ isProtectedByDefault: false,
+ maskedEnvironmentVariablesLink: '/variables-link',
+ maskableRegex,
+ protectedEnvironmentVariablesLink: '/protected-link',
+ };
+
+ const defaultProps = {
+ areScopedVariablesAvailable: true,
+ environments: [],
+ mode: ADD_VARIABLE_ACTION,
+ selectedVariable: {},
+ variable: [],
+ };
+
+ const createComponent = ({ mountFn = shallowMountExtended, props = {}, provide = {} } = {}) => {
+ wrapper = mountFn(CiVariableModal, {
+ attachTo: document.body,
+ provide: { ...defaultProvide, ...provide },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ GlModal: ModalStub,
+ },
+ });
+ };
+
+ const findCiEnvironmentsDropdown = () => wrapper.find(CiEnvironmentsDropdown);
+ const findReferenceWarning = () => wrapper.findByTestId('contains-variable-reference');
+ const findModal = () => wrapper.find(ModalStub);
+ const findAWSTip = () => wrapper.findByTestId('aws-guidance-tip');
+ const findAddorUpdateButton = () => wrapper.findByTestId('ciUpdateOrAddVariableBtn');
+ const deleteVariableButton = () =>
+ findModal()
+ .findAll(GlButton)
+ .wrappers.find((button) => button.props('variant') === 'danger');
+ const findProtectedVariableCheckbox = () =>
+ wrapper.findByTestId('ci-variable-protected-checkbox');
+ const findMaskedVariableCheckbox = () => wrapper.findByTestId('ci-variable-masked-checkbox');
+ const findValueField = () => wrapper.find('#ci-variable-value');
+ const findEnvScopeLink = () => wrapper.findByTestId('environment-scope-link');
+ const findEnvScopeInput = () => wrapper.findByTestId('environment-scope').find(GlFormInput);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Adding a variable', () => {
+ describe('when no key/value pair are present', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('shows the submit button as disabled ', () => {
+ expect(findAddorUpdateButton().attributes('disabled')).toBe('true');
+ });
+ });
+
+ describe('when a key/value pair is present', () => {
+ beforeEach(() => {
+ createComponent({ props: { selectedVariable: mockVariables[0] } });
+ });
+
+ it('shows the submit button as enabled ', () => {
+ expect(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
+ });
+ });
+
+ describe('events', () => {
+ const [currentVariable] = mockVariables;
+
+ beforeEach(() => {
+ createComponent({ props: { selectedVariable: currentVariable } });
+ jest.spyOn(wrapper.vm, '$emit');
+ });
+
+ it('Dispatches `add-variable` action on submit', () => {
+ findAddorUpdateButton().vm.$emit('click');
+ expect(wrapper.emitted('add-variable')).toEqual([[currentVariable]]);
+ });
+
+ it('Dispatches the `hideModal` event when dismissing', () => {
+ findModal().vm.$emit('hidden');
+ expect(wrapper.emitted('hideModal')).toEqual([[]]);
+ });
+ });
+ });
+
+ describe('when protected by default', () => {
+ describe('when adding a new variable', () => {
+ beforeEach(() => {
+ createComponent({ provide: { isProtectedByDefault: true } });
+ findModal().vm.$emit('shown');
+ });
+
+ it('updates the protected value to true', () => {
+ expect(findProtectedVariableCheckbox().attributes('data-is-protected-checked')).toBe(
+ 'true',
+ );
+ });
+ });
+
+ describe('when editing a variable', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: { isProtectedByDefault: false },
+ props: {
+ selectedVariable: {},
+ mode: EDIT_VARIABLE_ACTION,
+ },
+ });
+ findModal().vm.$emit('shown');
+ });
+
+ it('keeps the value as false', async () => {
+ expect(
+ findProtectedVariableCheckbox().attributes('data-is-protected-checked'),
+ ).toBeUndefined();
+ });
+ });
+ });
+
+ describe('Adding a new non-AWS variable', () => {
+ beforeEach(() => {
+ const [variable] = mockVariables;
+ createComponent({ mountFn: mountExtended, props: { selectedVariable: variable } });
+ });
+
+ it('does not show AWS guidance tip', () => {
+ const tip = findAWSTip();
+ expect(tip.exists()).toBe(true);
+ expect(tip.isVisible()).toBe(false);
+ });
+ });
+
+ describe('Adding a new AWS variable', () => {
+ beforeEach(() => {
+ const [variable] = mockVariables;
+ const AWSKeyVariable = {
+ ...variable,
+ key: AWS_ACCESS_KEY_ID,
+ value: 'AKIAIOSFODNN7EXAMPLEjdhy',
+ };
+ createComponent({ mountFn: mountExtended, props: { selectedVariable: AWSKeyVariable } });
+ });
+
+ it('shows AWS guidance tip', () => {
+ const tip = findAWSTip();
+ expect(tip.exists()).toBe(true);
+ expect(tip.isVisible()).toBe(true);
+ });
+ });
+
+ describe('Reference warning when adding a variable', () => {
+ describe('with a $ character', () => {
+ beforeEach(() => {
+ const [variable] = mockVariables;
+ const variableWithDollarSign = {
+ ...variable,
+ value: 'valueWith$',
+ };
+ createComponent({
+ mountFn: mountExtended,
+ props: { selectedVariable: variableWithDollarSign },
+ });
+ });
+
+ it(`renders the variable reference warning`, () => {
+ expect(findReferenceWarning().exists()).toBe(true);
+ });
+ });
+
+ describe('without a $ character', () => {
+ beforeEach(() => {
+ const [variable] = mockVariables;
+ createComponent({
+ mountFn: mountExtended,
+ props: { selectedVariable: variable },
+ });
+ });
+
+ it(`does not render the variable reference warning`, () => {
+ expect(findReferenceWarning().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('Editing a variable', () => {
+ const [variable] = mockVariables;
+
+ beforeEach(() => {
+ createComponent({ props: { selectedVariable: variable, mode: EDIT_VARIABLE_ACTION } });
+ jest.spyOn(wrapper.vm, '$emit');
+ });
+
+ it('button text is Update variable when updating', () => {
+ expect(findAddorUpdateButton().text()).toBe('Update variable');
+ });
+
+ it('Update variable button dispatches updateVariable with correct variable', () => {
+ findAddorUpdateButton().vm.$emit('click');
+ expect(wrapper.emitted('update-variable')).toEqual([[variable]]);
+ });
+
+ it('Propagates the `hideModal` event', () => {
+ findModal().vm.$emit('hidden');
+ expect(wrapper.emitted('hideModal')).toEqual([[]]);
+ });
+
+ it('dispatches `delete-variable` with correct variable to delete', () => {
+ deleteVariableButton().vm.$emit('click');
+ expect(wrapper.emitted('delete-variable')).toEqual([[variable]]);
+ });
+ });
+
+ describe('Environment scope', () => {
+ describe('when feature is available', () => {
+ it('renders the environment dropdown', () => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: true,
+ },
+ });
+
+ expect(findCiEnvironmentsDropdown().exists()).toBe(true);
+ expect(findCiEnvironmentsDropdown().isVisible()).toBe(true);
+ });
+
+ it('renders a link to documentation on scopes', () => {
+ createComponent({ mountFn: mountExtended });
+
+ const link = findEnvScopeLink();
+
+ expect(link.attributes('title')).toBe(ENVIRONMENT_SCOPE_LINK_TITLE);
+ expect(link.attributes('href')).toBe(defaultProvide.environmentScopeLink);
+ });
+ });
+
+ describe('when feature is not available', () => {
+ it('disables the dropdown', () => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: false,
+ },
+ });
+
+ expect(findCiEnvironmentsDropdown().exists()).toBe(false);
+ expect(findEnvScopeInput().attributes('readonly')).toBe('readonly');
+ });
+ });
+ });
+
+ describe('Validations', () => {
+ const maskError = 'This variable can not be masked.';
+
+ describe('when the mask state is invalid', () => {
+ beforeEach(async () => {
+ const [variable] = mockVariables;
+ const invalidMaskVariable = {
+ ...variable,
+ value: 'd:;',
+ masked: false,
+ };
+ createComponent({
+ mountFn: mountExtended,
+ props: { selectedVariable: invalidMaskVariable },
+ });
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ await findMaskedVariableCheckbox().trigger('click');
+ });
+
+ it('disables the submit button', () => {
+ expect(findAddorUpdateButton().attributes('disabled')).toBe('disabled');
+ });
+
+ it('shows the correct error text', () => {
+ expect(findModal().text()).toContain(maskError);
+ });
+
+ it('sends the correct tracking event', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
+ label: EVENT_LABEL,
+ property: ';',
+ });
+ });
+ });
+
+ describe.each`
+ value | masked | eventSent | trackingErrorProperty
+ ${'secretValue'} | ${false} | ${0} | ${null}
+ ${'short'} | ${true} | ${0} | ${null}
+ ${'dollar$ign'} | ${false} | ${1} | ${'$'}
+ ${'dollar$ign'} | ${true} | ${1} | ${'$'}
+ ${'unsupported|char'} | ${true} | ${1} | ${'|'}
+ ${'unsupported|char'} | ${false} | ${0} | ${null}
+ `('Adding a new variable', ({ value, masked, eventSent, trackingErrorProperty }) => {
+ beforeEach(async () => {
+ const [variable] = mockVariables;
+ const invalidKeyVariable = {
+ ...variable,
+ value: '',
+ masked: false,
+ };
+ createComponent({
+ mountFn: mountExtended,
+ props: { selectedVariable: invalidKeyVariable },
+ });
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ await findValueField().vm.$emit('input', value);
+ if (masked) {
+ await findMaskedVariableCheckbox().trigger('click');
+ }
+ });
+
+ it(`${
+ eventSent > 0 ? 'sends the correct' : 'does not send the'
+ } variable validation tracking event with ${value}`, () => {
+ expect(trackingSpy).toHaveBeenCalledTimes(eventSent);
+
+ if (eventSent > 0) {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
+ label: EVENT_LABEL,
+ property: trackingErrorProperty,
+ });
+ }
+ });
+ });
+
+ describe('when masked variable has acceptable value', () => {
+ beforeEach(() => {
+ const [variable] = mockVariables;
+ const validMaskandKeyVariable = {
+ ...variable,
+ key: AWS_ACCESS_KEY_ID,
+ value: '12345678',
+ masked: true,
+ };
+ createComponent({
+ mountFn: mountExtended,
+ props: { selectedVariable: validMaskandKeyVariable },
+ });
+ });
+
+ it('does not disable the submit button', () => {
+ expect(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
new file mode 100644
index 00000000000..5c77ce71b41
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
@@ -0,0 +1,128 @@
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import CiVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
+import ciVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
+import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
+import {
+ ADD_VARIABLE_ACTION,
+ EDIT_VARIABLE_ACTION,
+ projectString,
+} from '~/ci_variable_list/constants';
+import { mapEnvironmentNames } from '~/ci_variable_list/utils';
+
+import { mockEnvs, mockVariablesWithScopes, newVariable } from '../mocks';
+
+describe('Ci variable table', () => {
+ let wrapper;
+
+ const defaultProps = {
+ areScopedVariablesAvailable: true,
+ environments: mapEnvironmentNames(mockEnvs),
+ isLoading: false,
+ variables: mockVariablesWithScopes(projectString),
+ };
+
+ const findCiVariableTable = () => wrapper.findComponent(ciVariableTable);
+ const findCiVariableModal = () => wrapper.findComponent(ciVariableModal);
+
+ const createComponent = () => {
+ wrapper = shallowMount(CiVariableSettings, {
+ propsData: {
+ ...defaultProps,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('props passing', () => {
+ it('passes props down correctly to the ci table', () => {
+ expect(findCiVariableTable().props()).toEqual({
+ isLoading: defaultProps.isLoading,
+ variables: defaultProps.variables,
+ });
+ });
+
+ it('passes props down correctly to the ci modal', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable');
+ await nextTick();
+
+ expect(findCiVariableModal().props()).toEqual({
+ areScopedVariablesAvailable: defaultProps.areScopedVariablesAvailable,
+ environments: defaultProps.environments,
+ variables: defaultProps.variables,
+ mode: ADD_VARIABLE_ACTION,
+ selectedVariable: {},
+ });
+ });
+ });
+
+ describe('modal mode', () => {
+ it('passes down ADD mode when receiving an empty variable', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable');
+ await nextTick();
+
+ expect(findCiVariableModal().props('mode')).toBe(ADD_VARIABLE_ACTION);
+ });
+
+ it('passes down EDIT mode when receiving a variable', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable', newVariable);
+ await nextTick();
+
+ expect(findCiVariableModal().props('mode')).toBe(EDIT_VARIABLE_ACTION);
+ });
+ });
+
+ describe('variable modal', () => {
+ it('is hidden by default', () => {
+ expect(findCiVariableModal().exists()).toBe(false);
+ });
+
+ it('shows modal when adding a new variable', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable');
+ await nextTick();
+
+ expect(findCiVariableModal().exists()).toBe(true);
+ });
+
+ it('shows modal when updating a variable', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable', newVariable);
+ await nextTick();
+
+ expect(findCiVariableModal().exists()).toBe(true);
+ });
+
+ it('hides modal when receiving the event from the modal', async () => {
+ findCiVariableTable().vm.$emit('set-selected-variable');
+ await nextTick();
+
+ findCiVariableModal().vm.$emit('hideModal');
+ await nextTick();
+
+ expect(findCiVariableModal().exists()).toBe(false);
+ });
+ });
+
+ describe('variable events', () => {
+ it.each`
+ eventName
+ ${'add-variable'}
+ ${'update-variable'}
+ ${'delete-variable'}
+ `('bubbles up the $eventName event', async ({ eventName }) => {
+ findCiVariableTable().vm.$emit('set-selected-variable');
+ await nextTick();
+
+ findCiVariableModal().vm.$emit(eventName, newVariable);
+ await nextTick();
+
+ expect(wrapper.emitted(eventName)).toEqual([[newVariable]]);
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
new file mode 100644
index 00000000000..8a4c35173ec
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_variable_table_spec.js
@@ -0,0 +1,98 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import CiVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
+import { projectString } from '~/ci_variable_list/constants';
+import { mockVariables } from '../mocks';
+
+describe('Ci variable table', () => {
+ let wrapper;
+
+ const defaultProps = {
+ isLoading: false,
+ variables: mockVariables(projectString),
+ };
+
+ const createComponent = ({ props = {} } = {}) => {
+ wrapper = mountExtended(CiVariableTable, {
+ attachTo: document.body,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ const findRevealButton = () => wrapper.findByText('Reveal values');
+ const findAddButton = () => wrapper.findByLabelText('Add');
+ const findEditButton = () => wrapper.findByLabelText('Edit');
+ const findEmptyVariablesPlaceholder = () => wrapper.findByText('There are no variables yet.');
+ const findHiddenValues = () => wrapper.findAll('[data-testid="hiddenValue"]');
+ const findRevealedValues = () => wrapper.findAll('[data-testid="revealedValue"]');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('When table is empty', () => {
+ beforeEach(() => {
+ createComponent({ props: { variables: [] } });
+ });
+
+ it('displays empty message', () => {
+ expect(findEmptyVariablesPlaceholder().exists()).toBe(true);
+ });
+
+ it('hides the reveal button', () => {
+ expect(findRevealButton().exists()).toBe(false);
+ });
+ });
+
+ describe('When table has variables', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('does not display the empty message', () => {
+ expect(findEmptyVariablesPlaceholder().exists()).toBe(false);
+ });
+
+ it('displays the reveal button', () => {
+ expect(findRevealButton().exists()).toBe(true);
+ });
+
+ it('displays the correct amount of variables', async () => {
+ expect(wrapper.findAll('.js-ci-variable-row')).toHaveLength(defaultProps.variables.length);
+ });
+ });
+
+ describe('Table click actions', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('reveals secret values when button is clicked', async () => {
+ expect(findHiddenValues()).toHaveLength(defaultProps.variables.length);
+ expect(findRevealedValues()).toHaveLength(0);
+
+ await findRevealButton().trigger('click');
+
+ expect(findHiddenValues()).toHaveLength(0);
+ expect(findRevealedValues()).toHaveLength(defaultProps.variables.length);
+ });
+
+ it('dispatches `setSelectedVariable` with correct variable to edit', async () => {
+ await findEditButton().trigger('click');
+
+ expect(wrapper.emitted('set-selected-variable')).toEqual([[defaultProps.variables[0]]]);
+ });
+
+ it('dispatches `setSelectedVariable` with no variable when adding a new one', async () => {
+ await findAddButton().trigger('click');
+
+ expect(wrapper.emitted('set-selected-variable')).toEqual([[null]]);
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js
index 42c6501dcce..6681ab91a4a 100644
--- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js
+++ b/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js
@@ -58,7 +58,7 @@ describe('Ci variable modal', () => {
});
it('button is disabled when no key/value pair are present', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBeTruthy();
+ expect(findAddorUpdateButton().attributes('disabled')).toBe('true');
});
});
@@ -71,7 +71,7 @@ describe('Ci variable modal', () => {
});
it('button is enabled when key/value pair are present', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBeFalsy();
+ expect(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
});
it('Add variable button dispatches addVariable action', () => {
@@ -249,7 +249,7 @@ describe('Ci variable modal', () => {
});
it('disables the submit button', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBeTruthy();
+ expect(findAddorUpdateButton().attributes('disabled')).toBe('disabled');
});
it('shows the correct error text', () => {
@@ -316,7 +316,7 @@ describe('Ci variable modal', () => {
});
it('does not disable the submit button', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBeFalsy();
+ expect(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
});
});
});
diff --git a/spec/frontend/ci_variable_list/mocks.js b/spec/frontend/ci_variable_list/mocks.js
new file mode 100644
index 00000000000..89ba77858dc
--- /dev/null
+++ b/spec/frontend/ci_variable_list/mocks.js
@@ -0,0 +1,109 @@
+import { variableTypes, groupString, instanceString } from '~/ci_variable_list/constants';
+
+export const devName = 'dev';
+export const prodName = 'prod';
+
+export const mockVariables = (kind) => {
+ return [
+ {
+ __typename: `Ci${kind}Variable`,
+ id: 1,
+ key: 'my-var',
+ masked: false,
+ protected: true,
+ value: 'env_val',
+ variableType: variableTypes.variableType,
+ },
+ {
+ __typename: `Ci${kind}Variable`,
+ id: 2,
+ key: 'secret',
+ masked: true,
+ protected: false,
+ value: 'the_secret_value',
+ variableType: variableTypes.fileType,
+ },
+ ];
+};
+
+export const mockVariablesWithScopes = (kind) =>
+ mockVariables(kind).map((variable) => {
+ return { ...variable, environmentScope: '*' };
+ });
+
+const createDefaultVars = ({ withScope = true, kind } = {}) => {
+ let base = mockVariables(kind);
+
+ if (withScope) {
+ base = mockVariablesWithScopes(kind);
+ }
+
+ return {
+ __typename: `Ci${kind}VariableConnection`,
+ nodes: base,
+ };
+};
+
+const defaultEnvs = {
+ __typename: 'EnvironmentConnection',
+ nodes: [
+ {
+ __typename: 'Environment',
+ id: 1,
+ name: prodName,
+ },
+ {
+ __typename: 'Environment',
+ id: 2,
+ name: devName,
+ },
+ ],
+};
+
+export const mockEnvs = defaultEnvs.nodes;
+
+export const mockProjectEnvironments = {
+ data: {
+ project: {
+ __typename: 'Project',
+ id: 1,
+ environments: defaultEnvs,
+ },
+ },
+};
+
+export const mockProjectVariables = {
+ data: {
+ project: {
+ __typename: 'Project',
+ id: 1,
+ ciVariables: createDefaultVars(),
+ },
+ },
+};
+
+export const mockGroupVariables = {
+ data: {
+ group: {
+ __typename: 'Group',
+ id: 1,
+ ciVariables: createDefaultVars({ kind: groupString }),
+ },
+ },
+};
+
+export const mockAdminVariables = {
+ data: {
+ ciVariables: createDefaultVars({ withScope: false, kind: instanceString }),
+ },
+};
+
+export const newVariable = {
+ id: 3,
+ environmentScope: 'new',
+ key: 'AWS_RANDOM_THING',
+ masked: true,
+ protected: false,
+ value: 'devops',
+ variableType: variableTypes.variableType,
+};
diff --git a/spec/frontend/ci_variable_list/utils_spec.js b/spec/frontend/ci_variable_list/utils_spec.js
new file mode 100644
index 00000000000..081c399792f
--- /dev/null
+++ b/spec/frontend/ci_variable_list/utils_spec.js
@@ -0,0 +1,78 @@
+import {
+ createJoinedEnvironments,
+ convertEnvironmentScope,
+ mapEnvironmentNames,
+} from '~/ci_variable_list/utils';
+import { allEnvironments } from '~/ci_variable_list/constants';
+
+describe('utils', () => {
+ const environments = ['dev', 'prod'];
+ const newEnvironments = ['staging'];
+
+ describe('createJoinedEnvironments', () => {
+ it('returns only `environments` if `variables` argument is undefined', () => {
+ const variables = undefined;
+
+ expect(createJoinedEnvironments(variables, environments, [])).toEqual(environments);
+ });
+
+ it('returns a list of environments and environment scopes taken from variables in alphabetical order', () => {
+ const envScope1 = 'new1';
+ const envScope2 = 'new2';
+
+ const variables = [{ environmentScope: envScope1 }, { environmentScope: envScope2 }];
+
+ expect(createJoinedEnvironments(variables, environments, [])).toEqual([
+ environments[0],
+ envScope1,
+ envScope2,
+ environments[1],
+ ]);
+ });
+
+ it('returns combined list with new environments included', () => {
+ const variables = undefined;
+
+ expect(createJoinedEnvironments(variables, environments, newEnvironments)).toEqual([
+ ...environments,
+ ...newEnvironments,
+ ]);
+ });
+
+ it('removes duplicate environments', () => {
+ const envScope1 = environments[0];
+ const envScope2 = 'new2';
+
+ const variables = [{ environmentScope: envScope1 }, { environmentScope: envScope2 }];
+
+ expect(createJoinedEnvironments(variables, environments, [])).toEqual([
+ environments[0],
+ envScope2,
+ environments[1],
+ ]);
+ });
+ });
+
+ describe('convertEnvironmentScope', () => {
+ it('converts the * to the `All environments` text', () => {
+ expect(convertEnvironmentScope('*')).toBe(allEnvironments.text);
+ });
+
+ it('returns the environment as is if not the *', () => {
+ expect(convertEnvironmentScope('prod')).toBe('prod');
+ });
+ });
+
+ describe('mapEnvironmentNames', () => {
+ const envName = 'dev';
+ const envName2 = 'prod';
+
+ const nodes = [
+ { name: envName, otherProp: {} },
+ { name: envName2, otherProp: {} },
+ ];
+ it('flatten a nodes array with only their names', () => {
+ expect(mapEnvironmentNames(nodes)).toEqual([envName, envName2]);
+ });
+ });
+});
diff --git a/spec/frontend/clusters/agents/components/activity_history_item_spec.js b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
index 100a280d0cc..68f6f11aa8f 100644
--- a/spec/frontend/clusters/agents/components/activity_history_item_spec.js
+++ b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
@@ -23,7 +23,7 @@ describe('ActivityHistoryItem', () => {
};
const findHistoryItem = () => wrapper.findComponent(HistoryItem);
- const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
+ const findTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/clusters/agents/components/create_token_modal_spec.js b/spec/frontend/clusters/agents/components/create_token_modal_spec.js
index ad48afe10b6..0d10801e80e 100644
--- a/spec/frontend/clusters/agents/components/create_token_modal_spec.js
+++ b/spec/frontend/clusters/agents/components/create_token_modal_spec.js
@@ -55,7 +55,7 @@ describe('CreateTokenModal', () => {
const findAgentInstructions = () => findModal().findComponent(AgentToken);
const findButtonByVariant = (variant) =>
findModal()
- .findAll(GlButton)
+ .findAllComponents(GlButton)
.wrappers.find((button) => button.props('variant') === variant);
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => wrapper.findByTestId('agent-token-close-button');
diff --git a/spec/frontend/clusters/agents/components/token_table_spec.js b/spec/frontend/clusters/agents/components/token_table_spec.js
index 6caeaf5c192..334615f1818 100644
--- a/spec/frontend/clusters/agents/components/token_table_spec.js
+++ b/spec/frontend/clusters/agents/components/token_table_spec.js
@@ -136,8 +136,8 @@ describe('ClusterAgentTokenTable', () => {
const token = tokens.at(lineNumber);
expect(token.text()).toContain(description);
- expect(token.find(GlTruncate).exists()).toBe(truncatesText);
- expect(token.find(GlTooltip).exists()).toBe(hasTooltip);
+ expect(token.findComponent(GlTruncate).exists()).toBe(truncatesText);
+ expect(token.findComponent(GlTooltip).exists()).toBe(hasTooltip);
},
);
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
index b5345ea8915..ad2aa4acbaf 100644
--- a/spec/frontend/clusters/clusters_bundle_spec.js
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -1,7 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
-import { setTestTimeout } from 'helpers/timeout';
import Clusters from '~/clusters/clusters_bundle';
import axios from '~/lib/utils/axios_utils';
import initProjectSelectDropdown from '~/project_select';
@@ -12,8 +11,6 @@ jest.mock('~/project_select');
useMockLocationHelper();
describe('Clusters', () => {
- setTestTimeout(1000);
-
let cluster;
let mock;
@@ -60,9 +57,9 @@ describe('Clusters', () => {
it('should show the creating container', () => {
cluster.updateContainer(null, 'creating');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy();
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(false);
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(true);
expect(window.location.reload).not.toHaveBeenCalled();
});
@@ -70,9 +67,9 @@ describe('Clusters', () => {
cluster.updateContainer(null, 'creating');
cluster.updateContainer('creating', 'creating');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy();
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(false);
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(true);
expect(window.location.reload).not.toHaveBeenCalled();
});
});
@@ -83,9 +80,9 @@ describe('Clusters', () => {
cluster.updateContainer(null, 'creating');
cluster.updateContainer('creating', 'created');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(true);
expect(window.location.reload).toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(true);
});
@@ -97,9 +94,9 @@ describe('Clusters', () => {
cluster.updateContainer(null, 'created');
cluster.updateContainer('created', 'created');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy();
- expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(false);
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(true);
expect(window.location.reload).not.toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).toHaveBeenCalledWith(false);
});
@@ -111,9 +108,9 @@ describe('Clusters', () => {
cluster.updateContainer(null, 'created');
cluster.updateContainer('created', 'created');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
- expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(true);
expect(window.location.reload).not.toHaveBeenCalled();
expect(cluster.setClusterNewlyCreated).not.toHaveBeenCalled();
});
@@ -123,11 +120,11 @@ describe('Clusters', () => {
it('should show the error container', () => {
cluster.updateContainer(null, 'errored', 'this is an error');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(true);
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
- expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(false);
expect(cluster.errorReasonContainer.textContent).toContain('this is an error');
});
@@ -135,11 +132,11 @@ describe('Clusters', () => {
it('should show `error` banner when previously `creating`', () => {
cluster.updateContainer('creating', 'errored');
- expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBe(true);
- expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+ expect(cluster.successContainer.classList.contains('hidden')).toBe(true);
- expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
+ expect(cluster.errorContainer.classList.contains('hidden')).toBe(false);
});
});
diff --git a/spec/frontend/clusters/components/new_cluster_spec.js b/spec/frontend/clusters/components/new_cluster_spec.js
index f9df70b9f87..ef39c90aaef 100644
--- a/spec/frontend/clusters/components/new_cluster_spec.js
+++ b/spec/frontend/clusters/components/new_cluster_spec.js
@@ -12,9 +12,9 @@ describe('NewCluster', () => {
await nextTick();
};
- const findDescription = () => wrapper.find(GlSprintf);
+ const findDescription = () => wrapper.findComponent(GlSprintf);
- const findLink = () => wrapper.find(GlLink);
+ const findLink = () => wrapper.findComponent(GlLink);
beforeEach(() => {
return createWrapper();
diff --git a/spec/frontend/clusters/forms/components/integration_form_spec.js b/spec/frontend/clusters/forms/components/integration_form_spec.js
index 67d442bfdc5..b17886a5826 100644
--- a/spec/frontend/clusters/forms/components/integration_form_spec.js
+++ b/spec/frontend/clusters/forms/components/integration_form_spec.js
@@ -32,8 +32,8 @@ describe('ClusterIntegrationForm', () => {
wrapper = null;
};
- const findSubmitButton = () => wrapper.find(GlButton);
- const findGlToggle = () => wrapper.find(GlToggle);
+ const findSubmitButton = () => wrapper.findComponent(GlButton);
+ const findGlToggle = () => wrapper.findComponent(GlToggle);
afterEach(() => {
destroyWrapper();
diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
index 29884675b24..964dd005a27 100644
--- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js
+++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
@@ -150,7 +150,6 @@ describe('InstallAgentModal', () => {
});
it("doesn't render agent installation instructions", () => {
- expect(findModal().text()).not.toContain(i18n.basicInstallTitle);
expect(findModal().findComponent(GlFormInputGroup).exists()).toBe(false);
expect(findModal().findComponent(GlAlert).exists()).toBe(false);
});
diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js
index 9b01af1e585..71ee12cf02d 100644
--- a/spec/frontend/commit/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlLoadingIcon, GlModal, GlTableLite } from '@gitlab/ui';
+import { GlLoadingIcon, GlModal, GlTableLite } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
@@ -8,7 +8,7 @@ import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
import PipelinesTable from '~/commit/pipelines/pipelines_table.vue';
import httpStatusCodes from '~/lib/utils/http_status';
-import createFlash from '~/flash';
+import { createAlert } from '~/flash';
import { TOAST_MESSAGE } from '~/pipelines/constants';
import axios from '~/lib/utils/axios_utils';
@@ -26,10 +26,12 @@ describe('Pipelines table in Commits and Merge requests', () => {
const findRunPipelineBtn = () => wrapper.findByTestId('run_pipeline_button');
const findRunPipelineBtnMobile = () => wrapper.findByTestId('run_pipeline_button_mobile');
const findLoadingState = () => wrapper.findComponent(GlLoadingIcon);
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findErrorEmptyState = () => wrapper.findByTestId('pipeline-error-empty-state');
+ const findEmptyState = () => wrapper.findByTestId('pipeline-empty-state');
const findTable = () => wrapper.findComponent(GlTableLite);
const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findModal = () => wrapper.findComponent(GlModal);
+ const findMrPipelinesDocsLink = () => wrapper.findByTestId('mr-pipelines-docs-link');
const createComponent = (props = {}) => {
wrapper = extendedWrapper(
@@ -73,7 +75,18 @@ describe('Pipelines table in Commits and Merge requests', () => {
it('should render the empty state', () => {
expect(findTableRows()).toHaveLength(0);
expect(findLoadingState().exists()).toBe(false);
- expect(findEmptyState().exists()).toBe(false);
+ expect(findErrorEmptyState().exists()).toBe(false);
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('should render correct empty state content', () => {
+ expect(findRunPipelineBtn().exists()).toBe(true);
+ expect(findMrPipelinesDocsLink().attributes('href')).toBe(
+ '/help/ci/pipelines/merge_request_pipelines.md#prerequisites',
+ );
+ expect(findEmptyState().text()).toContain(
+ 'To run a merge request pipeline, the jobs in the CI/CD configuration file must be configured to run in merge request pipelines.',
+ );
});
});
@@ -90,7 +103,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
expect(findTable().exists()).toBe(true);
expect(findTableRows()).toHaveLength(1);
expect(findLoadingState().exists()).toBe(false);
- expect(findEmptyState().exists()).toBe(false);
+ expect(findErrorEmptyState().exists()).toBe(false);
});
describe('with pagination', () => {
@@ -226,12 +239,14 @@ describe('Pipelines table in Commits and Merge requests', () => {
describe('failure', () => {
const permissionsMsg = 'You do not have permission to run a pipeline on this branch.';
+ const defaultMsg =
+ 'An error occurred while trying to run a new pipeline for this merge request.';
it.each`
status | message
- ${httpStatusCodes.BAD_REQUEST} | ${permissionsMsg}
+ ${httpStatusCodes.BAD_REQUEST} | ${defaultMsg}
${httpStatusCodes.UNAUTHORIZED} | ${permissionsMsg}
- ${httpStatusCodes.INTERNAL_SERVER_ERROR} | ${'An error occurred while trying to run a new pipeline for this merge request.'}
+ ${httpStatusCodes.INTERNAL_SERVER_ERROR} | ${defaultMsg}
`('displays permissions error message', async ({ status, message }) => {
const response = { response: { status } };
@@ -243,7 +258,13 @@ describe('Pipelines table in Commits and Merge requests', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({ message });
+ expect(createAlert).toHaveBeenCalledWith({
+ message,
+ primaryButton: {
+ text: 'Learn more',
+ link: '/help/ci/pipelines/merge_request_pipelines.md',
+ },
+ });
});
});
});
@@ -293,7 +314,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
});
it('should render error state', () => {
- expect(findEmptyState().text()).toBe(
+ expect(findErrorEmptyState().text()).toBe(
'There was an error fetching the pipelines. Try again in a few moments or contact your support team.',
);
});
diff --git a/spec/frontend/content_editor/components/bubble_menus/link_spec.js b/spec/frontend/content_editor/components/bubble_menus/link_spec.js
index ba6d8da9584..93204deb68c 100644
--- a/spec/frontend/content_editor/components/bubble_menus/link_spec.js
+++ b/spec/frontend/content_editor/components/bubble_menus/link_spec.js
@@ -182,7 +182,7 @@ describe('content_editor/components/bubble_menus/link', () => {
it('updates prosemirror doc with new link', async () => {
expect(tiptapEditor.getHTML()).toBe(
- '<p>Download <a target="_blank" rel="noopener noreferrer nofollow" href="https://google.com" title="Search Google" canonicalsrc="https://google.com">PDF File</a></p>',
+ '<p>Download <a target="_blank" rel="noopener noreferrer nofollow" href="https://google.com" title="Search Google">PDF File</a></p>',
);
});
diff --git a/spec/frontend/content_editor/components/bubble_menus/media_spec.js b/spec/frontend/content_editor/components/bubble_menus/media_spec.js
index 8839caea80e..fada4f06743 100644
--- a/spec/frontend/content_editor/components/bubble_menus/media_spec.js
+++ b/spec/frontend/content_editor/components/bubble_menus/media_spec.js
@@ -14,7 +14,7 @@ import {
} from '../../test_constants';
const TIPTAP_IMAGE_HTML = `<p>
- <img src="https://gitlab.com/favicon.png" alt="gitlab favicon" title="gitlab favicon" data-canonical-src="https://gitlab.com/favicon.png">
+ <img src="https://gitlab.com/favicon.png" alt="gitlab favicon" title="gitlab favicon">
</p>`;
const TIPTAP_AUDIO_HTML = `<p>
diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js
index 9ee3b017831..0ba2672100b 100644
--- a/spec/frontend/content_editor/components/content_editor_spec.js
+++ b/spec/frontend/content_editor/components/content_editor_spec.js
@@ -19,6 +19,7 @@ describe('ContentEditor', () => {
const findEditorElement = () => wrapper.findByTestId('content-editor');
const findEditorContent = () => wrapper.findComponent(EditorContent);
+ const findEditorStateObserver = () => wrapper.findComponent(EditorStateObserver);
const createWrapper = (propsData = {}) => {
renderMarkdown = jest.fn();
@@ -119,4 +120,17 @@ describe('ContentEditor', () => {
expect(wrapper.findComponent(FormattingBubbleMenu).exists()).toBe(true);
});
+
+ it.each`
+ event
+ ${'loading'}
+ ${'loadingSuccess'}
+ ${'loadingError'}
+ `('broadcasts $event event triggered by editor-state-observer component', ({ event }) => {
+ createWrapper();
+
+ findEditorStateObserver().vm.$emit(event);
+
+ expect(wrapper.emitted(event)).toHaveLength(1);
+ });
});
diff --git a/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js b/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js
index 351fd967719..62fec8d4e72 100644
--- a/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js
+++ b/spec/frontend/content_editor/components/toolbar_more_dropdown_spec.js
@@ -37,16 +37,17 @@ describe('content_editor/components/toolbar_more_dropdown', () => {
});
describe.each`
- name | contentType | command | params
- ${'Code block'} | ${'codeBlock'} | ${'setNode'} | ${['codeBlock']}
- ${'Details block'} | ${'details'} | ${'toggleList'} | ${['details', 'detailsContent']}
- ${'Bullet list'} | ${'bulletList'} | ${'toggleList'} | ${['bulletList', 'listItem']}
- ${'Ordered list'} | ${'orderedList'} | ${'toggleList'} | ${['orderedList', 'listItem']}
- ${'Task list'} | ${'taskList'} | ${'toggleList'} | ${['taskList', 'taskItem']}
- ${'Mermaid diagram'} | ${'diagram'} | ${'setNode'} | ${['diagram', { language: 'mermaid' }]}
- ${'PlantUML diagram'} | ${'diagram'} | ${'setNode'} | ${['diagram', { language: 'plantuml' }]}
- ${'Horizontal rule'} | ${'horizontalRule'} | ${'setHorizontalRule'} | ${[]}
- `('when option $label is clicked', ({ name, command, contentType, params }) => {
+ name | contentType | command | params
+ ${'Code block'} | ${'codeBlock'} | ${'setNode'} | ${['codeBlock']}
+ ${'Details block'} | ${'details'} | ${'toggleList'} | ${['details', 'detailsContent']}
+ ${'Bullet list'} | ${'bulletList'} | ${'toggleList'} | ${['bulletList', 'listItem']}
+ ${'Ordered list'} | ${'orderedList'} | ${'toggleList'} | ${['orderedList', 'listItem']}
+ ${'Task list'} | ${'taskList'} | ${'toggleList'} | ${['taskList', 'taskItem']}
+ ${'Mermaid diagram'} | ${'diagram'} | ${'setNode'} | ${['diagram', { language: 'mermaid' }]}
+ ${'PlantUML diagram'} | ${'diagram'} | ${'setNode'} | ${['diagram', { language: 'plantuml' }]}
+ ${'Table of contents'} | ${'tableOfContents'} | ${'insertTableOfContents'} | ${[]}
+ ${'Horizontal rule'} | ${'horizontalRule'} | ${'setHorizontalRule'} | ${[]}
+ `('when option $name is clicked', ({ name, command, contentType, params }) => {
let commands;
let btn;
diff --git a/spec/frontend/content_editor/components/top_toolbar_spec.js b/spec/frontend/content_editor/components/top_toolbar_spec.js
index 2acb6e14ce0..8f194ff32e2 100644
--- a/spec/frontend/content_editor/components/top_toolbar_spec.js
+++ b/spec/frontend/content_editor/components/top_toolbar_spec.js
@@ -32,7 +32,7 @@ describe('content_editor/components/top_toolbar', () => {
${'link'} | ${{}}
${'bullet-list'} | ${{ contentType: 'bulletList', iconName: 'list-bulleted', label: 'Add a bullet list', editorCommand: 'toggleBulletList' }}
${'ordered-list'} | ${{ contentType: 'orderedList', iconName: 'list-numbered', label: 'Add a numbered list', editorCommand: 'toggleOrderedList' }}
- ${'task-list'} | ${{ contentType: 'taskList', iconName: 'list-task', label: 'Add a task list', editorCommand: 'toggleTaskList' }}
+ ${'task-list'} | ${{ contentType: 'taskList', iconName: 'list-task', label: 'Add a checklist', editorCommand: 'toggleTaskList' }}
${'image'} | ${{}}
${'table'} | ${{}}
${'more'} | ${{}}
diff --git a/spec/frontend/content_editor/components/wrappers/__snapshots__/table_of_contents_spec.js.snap b/spec/frontend/content_editor/components/wrappers/__snapshots__/table_of_contents_spec.js.snap
new file mode 100644
index 00000000000..fb091419ad9
--- /dev/null
+++ b/spec/frontend/content_editor/components/wrappers/__snapshots__/table_of_contents_spec.js.snap
@@ -0,0 +1,115 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`content/components/wrappers/table_of_contents collects all headings and renders a nested list of headings 1`] = `
+<div
+ class="table-of-contents gl-border-1 gl-border-solid gl-border-gray-100 gl-mb-5 gl-p-4!"
+ data-testid="table-of-contents"
+>
+
+ Table of contents
+
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1
+
+ </a>
+
+ <ul>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.1
+
+ </a>
+
+ <ul>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.1.1
+
+ </a>
+
+ <!---->
+ </li>
+ </ul>
+ </li>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.2
+
+ </a>
+
+ <ul>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.2.1
+
+ </a>
+
+ <!---->
+ </li>
+ </ul>
+ </li>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.3
+
+ </a>
+
+ <!---->
+ </li>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.4
+
+ </a>
+
+ <ul>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 1.4.1
+
+ </a>
+
+ <!---->
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <a
+ href="#"
+ >
+
+ Heading 2
+
+ </a>
+
+ <!---->
+ </li>
+</div>
+`;
diff --git a/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js b/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
index 6017a145a87..1fdddce3962 100644
--- a/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
+++ b/spec/frontend/content_editor/components/wrappers/table_cell_base_spec.js
@@ -1,12 +1,12 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { NodeViewWrapper } from '@tiptap/vue-2';
-import { selectedRect as getSelectedRect } from 'prosemirror-tables';
+import { selectedRect as getSelectedRect } from '@_ueberdosis/prosemirror-tables';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import TableCellBaseWrapper from '~/content_editor/components/wrappers/table_cell_base.vue';
import { createTestEditor, mockChainedCommands, emitEditorEvent } from '../../test_utils';
-jest.mock('prosemirror-tables');
+jest.mock('@_ueberdosis/prosemirror-tables');
describe('content/components/wrappers/table_cell_base', () => {
let wrapper;
diff --git a/spec/frontend/content_editor/components/wrappers/table_of_contents_spec.js b/spec/frontend/content_editor/components/wrappers/table_of_contents_spec.js
new file mode 100644
index 00000000000..bfda89a8b09
--- /dev/null
+++ b/spec/frontend/content_editor/components/wrappers/table_of_contents_spec.js
@@ -0,0 +1,84 @@
+import { nextTick } from 'vue';
+import { NodeViewWrapper } from '@tiptap/vue-2';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubComponent } from 'helpers/stub_component';
+import eventHubFactory from '~/helpers/event_hub_factory';
+import Heading from '~/content_editor/extensions/heading';
+import Diagram from '~/content_editor/extensions/diagram';
+import TableOfContentsWrapper from '~/content_editor/components/wrappers/table_of_contents.vue';
+import { createTestEditor, createDocBuilder, emitEditorEvent } from '../../test_utils';
+
+describe('content/components/wrappers/table_of_contents', () => {
+ let wrapper;
+ let tiptapEditor;
+ let contentEditor;
+ let eventHub;
+
+ const buildEditor = () => {
+ tiptapEditor = createTestEditor({ extensions: [Heading, Diagram] });
+ contentEditor = { renderDiagram: jest.fn().mockResolvedValue('url/to/some/diagram') };
+ eventHub = eventHubFactory();
+ };
+
+ const createWrapper = async () => {
+ wrapper = mountExtended(TableOfContentsWrapper, {
+ propsData: {
+ editor: tiptapEditor,
+ node: {
+ attrs: {},
+ },
+ },
+ stubs: {
+ NodeViewWrapper: stubComponent(NodeViewWrapper),
+ },
+ provide: {
+ contentEditor,
+ tiptapEditor,
+ eventHub,
+ },
+ });
+ };
+
+ beforeEach(async () => {
+ buildEditor();
+ createWrapper();
+
+ const {
+ builders: { heading, doc },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ heading: { nodeType: Heading.name },
+ },
+ });
+
+ const initialDoc = doc(
+ heading({ level: 1 }, 'Heading 1'),
+ heading({ level: 2 }, 'Heading 1.1'),
+ heading({ level: 3 }, 'Heading 1.1.1'),
+ heading({ level: 2 }, 'Heading 1.2'),
+ heading({ level: 3 }, 'Heading 1.2.1'),
+ heading({ level: 2 }, 'Heading 1.3'),
+ heading({ level: 2 }, 'Heading 1.4'),
+ heading({ level: 3 }, 'Heading 1.4.1'),
+ heading({ level: 1 }, 'Heading 2'),
+ );
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+ await emitEditorEvent({ event: 'update', tiptapEditor });
+ await nextTick();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a node-view-wrapper as a ul element', () => {
+ expect(wrapper.findComponent(NodeViewWrapper).props().as).toBe('ul');
+ });
+
+ it('collects all headings and renders a nested list of headings', () => {
+ expect(wrapper.findComponent(NodeViewWrapper).element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/content_editor/extensions/image_spec.js b/spec/frontend/content_editor/extensions/image_spec.js
index 256f7bad309..f73b0143fd9 100644
--- a/spec/frontend/content_editor/extensions/image_spec.js
+++ b/spec/frontend/content_editor/extensions/image_spec.js
@@ -35,7 +35,7 @@ describe('content_editor/extensions/image', () => {
tiptapEditor.commands.setContent(initialDoc.toJSON());
expect(tiptapEditor.getHTML()).toEqual(
- '<p><img src="/-/wikis/uploads/image.jpg" alt="image" title="this is an image" data-canonical-src="uploads/image.jpg"></p>',
+ '<p><img src="/-/wikis/uploads/image.jpg" alt="image" title="this is an image"></p>',
);
});
});
diff --git a/spec/frontend/content_editor/markdown_processing_spec_helper.js b/spec/frontend/content_editor/markdown_processing_spec_helper.js
index 41442dd8388..228d009e42c 100644
--- a/spec/frontend/content_editor/markdown_processing_spec_helper.js
+++ b/spec/frontend/content_editor/markdown_processing_spec_helper.js
@@ -2,7 +2,6 @@ import fs from 'fs';
import jsYaml from 'js-yaml';
import { memoize } from 'lodash';
import { createContentEditor } from '~/content_editor';
-import { setTestTimeoutOnce } from 'helpers/timeout';
const getFocusedMarkdownExamples = memoize(
() => process.env.FOCUSED_MARKDOWN_EXAMPLES?.split(',') || [],
@@ -76,9 +75,6 @@ export const describeMarkdownProcessing = (description, markdownYamlPath) => {
}
it(exampleName, async () => {
- if (name === 'frontmatter_toml') {
- setTestTimeoutOnce(2000);
- }
await testSerializesHtmlToMarkdownForElement(example);
});
});
diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js
index 48adceaab58..7ae0a7c13c1 100644
--- a/spec/frontend/content_editor/remark_markdown_processing_spec.js
+++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js
@@ -5,6 +5,7 @@ import Code from '~/content_editor/extensions/code';
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
import FootnoteDefinition from '~/content_editor/extensions/footnote_definition';
import FootnoteReference from '~/content_editor/extensions/footnote_reference';
+import Frontmatter from '~/content_editor/extensions/frontmatter';
import HardBreak from '~/content_editor/extensions/hard_break';
import HTMLNodes from '~/content_editor/extensions/html_nodes';
import Heading from '~/content_editor/extensions/heading';
@@ -15,6 +16,7 @@ import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import Paragraph from '~/content_editor/extensions/paragraph';
+import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Sourcemap from '~/content_editor/extensions/sourcemap';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
@@ -37,6 +39,7 @@ const tiptapEditor = createTestEditor({
CodeBlockHighlight,
FootnoteDefinition,
FootnoteReference,
+ Frontmatter,
HardBreak,
Heading,
HorizontalRule,
@@ -45,6 +48,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
+ ReferenceDefinition,
Sourcemap,
Strike,
Table,
@@ -69,6 +73,7 @@ const {
div,
footnoteDefinition,
footnoteReference,
+ frontmatter,
hardBreak,
heading,
horizontalRule,
@@ -78,6 +83,7 @@ const {
listItem,
orderedList,
pre,
+ referenceDefinition,
strike,
table,
tableRow,
@@ -96,6 +102,7 @@ const {
codeBlock: { nodeType: CodeBlockHighlight.name },
footnoteDefinition: { nodeType: FootnoteDefinition.name },
footnoteReference: { nodeType: FootnoteReference.name },
+ frontmatter: { nodeType: Frontmatter.name },
hardBreak: { nodeType: HardBreak.name },
heading: { nodeType: Heading.name },
horizontalRule: { nodeType: HorizontalRule.name },
@@ -105,6 +112,7 @@ const {
listItem: { nodeType: ListItem.name },
orderedList: { nodeType: OrderedList.name },
paragraph: { nodeType: Paragraph.name },
+ referenceDefinition: { nodeType: ReferenceDefinition.name },
strike: { nodeType: Strike.name },
table: { nodeType: Table.name },
tableCell: { nodeType: TableCell.name },
@@ -253,7 +261,12 @@ describe('Client side Markdown processing', () => {
expectedDoc: doc(
paragraph(
source('<img src="bar" alt="foo" />'),
- image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
+ image({
+ ...source('<img src="bar" alt="foo" />'),
+ alt: 'foo',
+ canonicalSrc: 'bar',
+ src: 'bar',
+ }),
),
),
},
@@ -271,7 +284,12 @@ describe('Client side Markdown processing', () => {
),
paragraph(
source('<img src="bar" alt="foo" />'),
- image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
+ image({
+ ...source('<img src="bar" alt="foo" />'),
+ alt: 'foo',
+ src: 'bar',
+ canonicalSrc: 'bar',
+ }),
),
),
},
@@ -284,6 +302,7 @@ describe('Client side Markdown processing', () => {
{
...source('[GitLab](https://gitlab.com "Go to GitLab")'),
href: 'https://gitlab.com',
+ canonicalSrc: 'https://gitlab.com',
title: 'Go to GitLab',
},
'GitLab',
@@ -302,6 +321,7 @@ describe('Client side Markdown processing', () => {
{
...source('[GitLab](https://gitlab.com "Go to GitLab")'),
href: 'https://gitlab.com',
+ canonicalSrc: 'https://gitlab.com',
title: 'Go to GitLab',
},
'GitLab',
@@ -318,6 +338,7 @@ describe('Client side Markdown processing', () => {
link(
{
...source('www.commonmark.org'),
+ canonicalSrc: 'http://www.commonmark.org',
href: 'http://www.commonmark.org',
},
'www.commonmark.org',
@@ -334,6 +355,7 @@ describe('Client side Markdown processing', () => {
link(
{
...source('www.commonmark.org/help'),
+ canonicalSrc: 'http://www.commonmark.org/help',
href: 'http://www.commonmark.org/help',
},
'www.commonmark.org/help',
@@ -351,6 +373,7 @@ describe('Client side Markdown processing', () => {
link(
{
...source('hello+xyz@mail.example'),
+ canonicalSrc: 'mailto:hello+xyz@mail.example',
href: 'mailto:hello+xyz@mail.example',
},
'hello+xyz@mail.example',
@@ -369,6 +392,7 @@ describe('Client side Markdown processing', () => {
{
sourceMapKey: null,
sourceMarkdown: null,
+ canonicalSrc: 'https://gitlab.com',
href: 'https://gitlab.com',
},
'https://gitlab.com',
@@ -398,6 +422,7 @@ hard line break`,
image({
...source('![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")'),
alt: 'GitLab Logo',
+ canonicalSrc: 'https://gitlab.com/logo.png',
src: 'https://gitlab.com/logo.png',
title: 'GitLab Logo',
}),
@@ -591,7 +616,12 @@ two
paragraph(
source('List item with an image ![bar](foo.png)'),
'List item with an image',
- image({ ...source('![bar](foo.png)'), alt: 'bar', src: 'foo.png' }),
+ image({
+ ...source('![bar](foo.png)'),
+ alt: 'bar',
+ canonicalSrc: 'foo.png',
+ src: 'foo.png',
+ }),
),
),
),
@@ -940,8 +970,17 @@ Paragraph
paragraph(
source('[![moon](moon.jpg)](/uri)'),
link(
- { ...source('[![moon](moon.jpg)](/uri)'), href: '/uri' },
- image({ ...source('![moon](moon.jpg)'), src: 'moon.jpg', alt: 'moon' }),
+ {
+ ...source('[![moon](moon.jpg)](/uri)'),
+ canonicalSrc: '/uri',
+ href: '/uri',
+ },
+ image({
+ ...source('![moon](moon.jpg)'),
+ canonicalSrc: 'moon.jpg',
+ src: 'moon.jpg',
+ alt: 'moon',
+ }),
),
),
),
@@ -971,12 +1010,26 @@ Paragraph
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
strike(
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
- link({ ...source('[moon](moon.jpg)'), href: 'moon.jpg' }, 'moon'),
+ link(
+ {
+ ...source('[moon](moon.jpg)'),
+ canonicalSrc: 'moon.jpg',
+ href: 'moon.jpg',
+ },
+ 'moon',
+ ),
),
strike(source('~[moon](moon.jpg) and [sun](sun.jpg)~'), ' and '),
strike(
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
- link({ ...source('[sun](sun.jpg)'), href: 'sun.jpg' }, 'sun'),
+ link(
+ {
+ ...source('[sun](sun.jpg)'),
+ href: 'sun.jpg',
+ canonicalSrc: 'sun.jpg',
+ },
+ 'sun',
+ ),
),
),
),
@@ -1079,6 +1132,107 @@ _world_.
),
),
},
+ {
+ markdown: `
+[GitLab][gitlab-url]
+
+[gitlab-url]: https://gitlab.com "GitLab"
+
+ `,
+ expectedDoc: doc(
+ paragraph(
+ source('[GitLab][gitlab-url]'),
+ link(
+ {
+ ...source('[GitLab][gitlab-url]'),
+ href: 'https://gitlab.com',
+ canonicalSrc: 'gitlab-url',
+ title: 'GitLab',
+ isReference: true,
+ },
+ 'GitLab',
+ ),
+ ),
+ referenceDefinition(
+ {
+ ...source('[gitlab-url]: https://gitlab.com "GitLab"'),
+ identifier: 'gitlab-url',
+ url: 'https://gitlab.com',
+ title: 'GitLab',
+ },
+ '[gitlab-url]: https://gitlab.com "GitLab"',
+ ),
+ ),
+ },
+ {
+ markdown: `
+![GitLab Logo][gitlab-logo]
+
+[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"
+
+ `,
+ expectedDoc: doc(
+ paragraph(
+ source('![GitLab Logo][gitlab-logo]'),
+ image({
+ ...source('![GitLab Logo][gitlab-logo]'),
+ src: 'https://gitlab.com/gitlab-logo.png',
+ canonicalSrc: 'gitlab-logo',
+ alt: 'GitLab Logo',
+ title: 'GitLab Logo',
+ isReference: true,
+ }),
+ ),
+ referenceDefinition(
+ {
+ ...source('[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"'),
+ identifier: 'gitlab-logo',
+ url: 'https://gitlab.com/gitlab-logo.png',
+ title: 'GitLab Logo',
+ },
+ '[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"',
+ ),
+ ),
+ },
+ {
+ markdown: `
+---
+title: 'layout'
+---
+ `,
+ expectedDoc: doc(
+ frontmatter(
+ { ...source("---\ntitle: 'layout'\n---"), language: 'yaml' },
+ "title: 'layout'",
+ ),
+ ),
+ },
+ {
+ markdown: `
++++
+title: 'layout'
++++
+ `,
+ expectedDoc: doc(
+ frontmatter(
+ { ...source("+++\ntitle: 'layout'\n+++"), language: 'toml' },
+ "title: 'layout'",
+ ),
+ ),
+ },
+ {
+ markdown: `
+;;;
+{ title: 'layout' }
+;;;
+ `,
+ expectedDoc: doc(
+ frontmatter(
+ { ...source(";;;\n{ title: 'layout' }\n;;;"), language: 'json' },
+ "{ title: 'layout' }",
+ ),
+ ),
+ },
];
const runOnly = examples.find((example) => example.only === true);
@@ -1090,7 +1244,7 @@ _world_.
const trimmed = markdown.trim();
const document = await deserialize(trimmed);
- expect(expectedDoc).not.toBeFalsy();
+ expect(expectedDoc).not.toBe(false);
expect(document.toJSON()).toEqual(expectedDoc.toJSON());
expect(serialize(document)).toEqual(expectedMarkdown ?? trimmed);
},
@@ -1155,4 +1309,72 @@ body {
expect(tiptapEditor.getHTML()).toEqual(expectedHtml);
},
);
+
+ describe('attribute sanitization', () => {
+ // eslint-disable-next-line no-script-url
+ const protocolBasedInjectionSimpleNoSpaces = "javascript:alert('XSS');";
+ // eslint-disable-next-line no-script-url
+ const protocolBasedInjectionSimpleSpacesBefore = "javascript: alert('XSS');";
+
+ const docWithImageFactory = (urlInput, urlOutput) => {
+ const input = `<img src="${urlInput}">`;
+
+ return {
+ input,
+ expectedDoc: doc(
+ paragraph(
+ source(input),
+ image({
+ ...source(input),
+ src: urlOutput,
+ canonicalSrc: urlOutput,
+ }),
+ ),
+ ),
+ };
+ };
+
+ const docWithLinkFactory = (urlInput, urlOutput) => {
+ const input = `<a href="${urlInput}">foo</a>`;
+
+ return {
+ input,
+ expectedDoc: doc(
+ paragraph(
+ source(input),
+ link({ ...source(input), href: urlOutput, canonicalSrc: urlOutput }, 'foo'),
+ ),
+ ),
+ };
+ };
+
+ it.each`
+ desc | urlInput | urlOutput
+ ${'protocol-based JS injection: simple, no spaces'} | ${protocolBasedInjectionSimpleNoSpaces} | ${null}
+ ${'protocol-based JS injection: simple, spaces before'} | ${"javascript :alert('XSS');"} | ${null}
+ ${'protocol-based JS injection: simple, spaces after'} | ${protocolBasedInjectionSimpleSpacesBefore} | ${null}
+ ${'protocol-based JS injection: simple, spaces before and after'} | ${"javascript : alert('XSS');"} | ${null}
+ ${'protocol-based JS injection: UTF-8 encoding'} | ${'javascript&#58;'} | ${null}
+ ${'protocol-based JS injection: long UTF-8 encoding'} | ${'javascript&#0058;'} | ${null}
+ ${'protocol-based JS injection: long UTF-8 encoding without semicolons'} | ${'&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041'} | ${null}
+ ${'protocol-based JS injection: hex encoding'} | ${'javascript&#x3A;'} | ${null}
+ ${'protocol-based JS injection: long hex encoding'} | ${'javascript&#x003A;'} | ${null}
+ ${'protocol-based JS injection: hex encoding without semicolons'} | ${'&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29'} | ${null}
+ ${'protocol-based JS injection: Unicode'} | ${"\u0001java\u0003script:alert('XSS')"} | ${null}
+ ${'protocol-based JS injection: spaces and entities'} | ${"&#14; javascript:alert('XSS');"} | ${null}
+ ${'vbscript'} | ${'vbscript:alert(document.domain)'} | ${null}
+ ${'protocol-based JS injection: preceding colon'} | ${":javascript:alert('XSS');"} | ${":javascript:alert('XSS');"}
+ ${'protocol-based JS injection: null char'} | ${"java\0script:alert('XSS')"} | ${"java�script:alert('XSS')"}
+ ${'protocol-based JS injection: invalid URL char'} | ${"java\\script:alert('XSS')"} | ${"java\\script:alert('XSS')"}
+ `('sanitize $desc:\n\tURL "$urlInput" becomes "$urlOutput"', ({ urlInput, urlOutput }) => {
+ const exampleFactories = [docWithImageFactory, docWithLinkFactory];
+
+ exampleFactories.forEach(async (exampleFactory) => {
+ const { input, expectedDoc } = exampleFactory(urlInput, urlOutput);
+ const document = await deserialize(input);
+
+ expect(document.toJSON()).toEqual(expectedDoc.toJSON());
+ });
+ });
+ });
});
diff --git a/spec/frontend/content_editor/render_html_and_json_for_all_examples.js b/spec/frontend/content_editor/render_html_and_json_for_all_examples.js
index 116a26cf7d5..4a57c7b1942 100644
--- a/spec/frontend/content_editor/render_html_and_json_for_all_examples.js
+++ b/spec/frontend/content_editor/render_html_and_json_for_all_examples.js
@@ -16,6 +16,7 @@ import FigureCaption from '~/content_editor/extensions/figure_caption';
import FootnoteDefinition from '~/content_editor/extensions/footnote_definition';
import FootnoteReference from '~/content_editor/extensions/footnote_reference';
import FootnotesSection from '~/content_editor/extensions/footnotes_section';
+import Frontmatter from '~/content_editor/extensions/frontmatter';
import HardBreak from '~/content_editor/extensions/hard_break';
import Heading from '~/content_editor/extensions/heading';
import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
@@ -26,6 +27,7 @@ import Italic from '~/content_editor/extensions/italic';
import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
+import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
import TableCell from '~/content_editor/extensions/table_cell';
@@ -51,6 +53,7 @@ const tiptapEditor = createTestEditor({
FootnoteDefinition,
FootnoteReference,
FootnotesSection,
+ Frontmatter,
Figure,
FigureCaption,
HardBreak,
@@ -63,6 +66,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
+ ReferenceDefinition,
Strike,
Table,
TableCell,
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 509cda3046c..0e5281be9bf 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -24,6 +24,7 @@ import Link from '~/content_editor/extensions/link';
import ListItem from '~/content_editor/extensions/list_item';
import OrderedList from '~/content_editor/extensions/ordered_list';
import Paragraph from '~/content_editor/extensions/paragraph';
+import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
import Sourcemap from '~/content_editor/extensions/sourcemap';
import Strike from '~/content_editor/extensions/strike';
import Table from '~/content_editor/extensions/table';
@@ -63,6 +64,7 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
+ ReferenceDefinition,
Sourcemap,
Strike,
Table,
@@ -104,6 +106,7 @@ const {
listItem,
orderedList,
paragraph,
+ referenceDefinition,
strike,
table,
tableCell,
@@ -139,6 +142,7 @@ const {
listItem: { nodeType: ListItem.name },
orderedList: { nodeType: OrderedList.name },
paragraph: { nodeType: Paragraph.name },
+ referenceDefinition: { nodeType: ReferenceDefinition.name },
strike: { markType: Strike.name },
table: { nodeType: Table.name },
tableCell: { nodeType: TableCell.name },
@@ -243,6 +247,37 @@ describe('markdownSerializer', () => {
).toBe('[download file](file.zip "click here to download")');
});
+ it('correctly serializes link references', () => {
+ expect(
+ serialize(
+ paragraph(
+ link(
+ {
+ href: 'gitlab-url',
+ isReference: true,
+ },
+ 'GitLab',
+ ),
+ ),
+ ),
+ ).toBe('[GitLab][gitlab-url]');
+ });
+
+ it('correctly serializes image references', () => {
+ expect(
+ serialize(
+ paragraph(
+ image({
+ canonicalSrc: 'gitlab-url',
+ src: 'image.svg',
+ alt: 'GitLab',
+ isReference: true,
+ }),
+ ),
+ ),
+ ).toBe('![GitLab][gitlab-url]');
+ });
+
it('correctly serializes strikethrough', () => {
expect(serialize(paragraph(strike('deleted content')))).toBe('~~deleted content~~');
});
@@ -1163,6 +1198,38 @@ Oranges are orange [^1]
);
});
+ it('correctly serializes reference definition', () => {
+ expect(
+ serialize(
+ referenceDefinition('[gitlab]: https://gitlab.com'),
+ referenceDefinition('[foobar]: foobar.com'),
+ ),
+ ).toBe(
+ `
+[gitlab]: https://gitlab.com
+[foobar]: foobar.com`.trimLeft(),
+ );
+ });
+
+ it('correctly adds a space between a reference definition and a block content', () => {
+ expect(
+ serialize(
+ paragraph('paragraph'),
+ referenceDefinition('[gitlab]: https://gitlab.com'),
+ referenceDefinition('[foobar]: foobar.com'),
+ heading({ level: 2 }, 'heading'),
+ ),
+ ).toBe(
+ `
+paragraph
+
+[gitlab]: https://gitlab.com
+[foobar]: foobar.com
+
+## heading`.trimLeft(),
+ );
+ });
+
const defaultEditAction = (initialContent) => {
tiptapEditor.chain().setContent(initialContent.toJSON()).insertContent(' modified').run();
};
@@ -1177,42 +1244,49 @@ Oranges are orange [^1]
};
it.each`
- mark | markdown | modifiedMarkdown | editAction
- ${'bold'} | ${'**bold**'} | ${'**bold modified**'} | ${defaultEditAction}
- ${'bold'} | ${'__bold__'} | ${'__bold modified__'} | ${defaultEditAction}
- ${'bold'} | ${'<strong>bold</strong>'} | ${'<strong>bold modified</strong>'} | ${defaultEditAction}
- ${'bold'} | ${'<b>bold</b>'} | ${'<b>bold modified</b>'} | ${defaultEditAction}
- ${'italic'} | ${'_italic_'} | ${'_italic modified_'} | ${defaultEditAction}
- ${'italic'} | ${'*italic*'} | ${'*italic modified*'} | ${defaultEditAction}
- ${'italic'} | ${'<em>italic</em>'} | ${'<em>italic modified</em>'} | ${defaultEditAction}
- ${'italic'} | ${'<i>italic</i>'} | ${'<i>italic modified</i>'} | ${defaultEditAction}
- ${'link'} | ${'[gitlab](https://gitlab.com)'} | ${'[gitlab modified](https://gitlab.com)'} | ${defaultEditAction}
- ${'link'} | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com">link modified</a>'} | ${defaultEditAction}
- ${'link'} | ${'link www.gitlab.com'} | ${'modified link www.gitlab.com'} | ${prependContentEditAction}
- ${'link'} | ${'link https://www.gitlab.com'} | ${'modified link https://www.gitlab.com'} | ${prependContentEditAction}
- ${'link'} | ${'link(https://www.gitlab.com)'} | ${'modified link(https://www.gitlab.com)'} | ${prependContentEditAction}
- ${'link'} | ${'link(engineering@gitlab.com)'} | ${'modified link(engineering@gitlab.com)'} | ${prependContentEditAction}
- ${'link'} | ${'link <https://www.gitlab.com>'} | ${'modified link <https://www.gitlab.com>'} | ${prependContentEditAction}
- ${'link'} | ${'link [https://www.gitlab.com>'} | ${'modified link \\[https://www.gitlab.com>'} | ${prependContentEditAction}
- ${'link'} | ${'link <https://www.gitlab.com'} | ${'modified link <https://www.gitlab.com'} | ${prependContentEditAction}
- ${'link'} | ${'link https://www.gitlab.com>'} | ${'modified link https://www.gitlab.com>'} | ${prependContentEditAction}
- ${'link'} | ${'link **https://www.gitlab.com]**'} | ${'modified link [**https://www.gitlab.com\\]**](https://www.gitlab.com%5D)'} | ${prependContentEditAction}
- ${'code'} | ${'`code`'} | ${'`code modified`'} | ${defaultEditAction}
- ${'code'} | ${'<code>code</code>'} | ${'<code>code modified</code>'} | ${defaultEditAction}
- ${'strike'} | ${'~~striked~~'} | ${'~~striked modified~~'} | ${defaultEditAction}
- ${'strike'} | ${'<del>striked</del>'} | ${'<del>striked modified</del>'} | ${defaultEditAction}
- ${'strike'} | ${'<strike>striked</strike>'} | ${'<strike>striked modified</strike>'} | ${defaultEditAction}
- ${'strike'} | ${'<s>striked</s>'} | ${'<s>striked modified</s>'} | ${defaultEditAction}
- ${'list'} | ${'- list item'} | ${'- list item modified'} | ${defaultEditAction}
- ${'list'} | ${'* list item'} | ${'* list item modified'} | ${defaultEditAction}
- ${'list'} | ${'+ list item'} | ${'+ list item modified'} | ${defaultEditAction}
- ${'list'} | ${'- list item 1\n- list item 2'} | ${'- list item 1\n- list item 2 modified'} | ${defaultEditAction}
- ${'list'} | ${'2) list item'} | ${'2) list item modified'} | ${defaultEditAction}
- ${'list'} | ${'1. list item'} | ${'1. list item modified'} | ${defaultEditAction}
- ${'taskList'} | ${'2) [ ] task list item'} | ${'2) [ ] task list item modified'} | ${defaultEditAction}
- ${'taskList'} | ${'2) [x] task list item'} | ${'2) [x] task list item modified'} | ${defaultEditAction}
+ mark | markdown | modifiedMarkdown | editAction
+ ${'bold'} | ${'**bold**'} | ${'**bold modified**'} | ${defaultEditAction}
+ ${'bold'} | ${'__bold__'} | ${'__bold modified__'} | ${defaultEditAction}
+ ${'bold'} | ${'<strong>bold</strong>'} | ${'<strong>bold modified</strong>'} | ${defaultEditAction}
+ ${'bold'} | ${'<b>bold</b>'} | ${'<b>bold modified</b>'} | ${defaultEditAction}
+ ${'italic'} | ${'_italic_'} | ${'_italic modified_'} | ${defaultEditAction}
+ ${'italic'} | ${'*italic*'} | ${'*italic modified*'} | ${defaultEditAction}
+ ${'italic'} | ${'<em>italic</em>'} | ${'<em>italic modified</em>'} | ${defaultEditAction}
+ ${'italic'} | ${'<i>italic</i>'} | ${'<i>italic modified</i>'} | ${defaultEditAction}
+ ${'link'} | ${'[gitlab](https://gitlab.com)'} | ${'[gitlab modified](https://gitlab.com)'} | ${defaultEditAction}
+ ${'link'} | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com">link modified</a>'} | ${defaultEditAction}
+ ${'link'} | ${'link www.gitlab.com'} | ${'modified link www.gitlab.com'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com'} | ${'modified link https://www.gitlab.com'} | ${prependContentEditAction}
+ ${'link'} | ${'link(https://www.gitlab.com)'} | ${'modified link(https://www.gitlab.com)'} | ${prependContentEditAction}
+ ${'link'} | ${'link(engineering@gitlab.com)'} | ${'modified link(engineering@gitlab.com)'} | ${prependContentEditAction}
+ ${'link'} | ${'link <https://www.gitlab.com>'} | ${'modified link <https://www.gitlab.com>'} | ${prependContentEditAction}
+ ${'link'} | ${'link [https://www.gitlab.com>'} | ${'modified link \\[https://www.gitlab.com>'} | ${prependContentEditAction}
+ ${'link'} | ${'link <https://www.gitlab.com'} | ${'modified link <https://www.gitlab.com'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com>'} | ${'modified link https://www.gitlab.com>'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com/path'} | ${'modified link https://www.gitlab.com/path'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com?query=search'} | ${'modified link https://www.gitlab.com?query=search'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com/#fragment'} | ${'modified link https://www.gitlab.com/#fragment'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com/?query=search'} | ${'modified link https://www.gitlab.com/?query=search'} | ${prependContentEditAction}
+ ${'link'} | ${'link https://www.gitlab.com#fragment'} | ${'modified link https://www.gitlab.com#fragment'} | ${prependContentEditAction}
+ ${'link'} | ${'link **https://www.gitlab.com]**'} | ${'modified link **https://www.gitlab.com\\]**'} | ${prependContentEditAction}
+ ${'code'} | ${'`code`'} | ${'`code modified`'} | ${defaultEditAction}
+ ${'code'} | ${'<code>code</code>'} | ${'<code>code modified</code>'} | ${defaultEditAction}
+ ${'strike'} | ${'~~striked~~'} | ${'~~striked modified~~'} | ${defaultEditAction}
+ ${'strike'} | ${'<del>striked</del>'} | ${'<del>striked modified</del>'} | ${defaultEditAction}
+ ${'strike'} | ${'<strike>striked</strike>'} | ${'<strike>striked modified</strike>'} | ${defaultEditAction}
+ ${'strike'} | ${'<s>striked</s>'} | ${'<s>striked modified</s>'} | ${defaultEditAction}
+ ${'list'} | ${'- list item'} | ${'- list item modified'} | ${defaultEditAction}
+ ${'list'} | ${'* list item'} | ${'* list item modified'} | ${defaultEditAction}
+ ${'list'} | ${'+ list item'} | ${'+ list item modified'} | ${defaultEditAction}
+ ${'list'} | ${'- list item 1\n- list item 2'} | ${'- list item 1\n- list item 2 modified'} | ${defaultEditAction}
+ ${'list'} | ${'2) list item'} | ${'2) list item modified'} | ${defaultEditAction}
+ ${'list'} | ${'1. list item'} | ${'1. list item modified'} | ${defaultEditAction}
+ ${'taskList'} | ${'2) [ ] task list item'} | ${'2) [ ] task list item modified'} | ${defaultEditAction}
+ ${'taskList'} | ${'2) [x] task list item'} | ${'2) [x] task list item modified'} | ${defaultEditAction}
+ ${'image'} | ${'![image](image.png)'} | ${'![image](image.png) modified'} | ${defaultEditAction}
+ ${'footnoteReference'} | ${'[^1] footnote\n\n[^1]: footnote definition'} | ${'modified [^1] footnote\n\n[^1]: footnote definition'} | ${prependContentEditAction}
`(
- 'preserves original $mark syntax when sourceMarkdown is available for $content',
+ 'preserves original $mark syntax when sourceMarkdown is available for $markdown',
async ({ markdown, modifiedMarkdown, editAction }) => {
const { document } = await remarkMarkdownDeserializer().deserialize({
schema: tiptapEditor.schema,
diff --git a/spec/frontend/content_editor/services/table_of_contents_utils_spec.js b/spec/frontend/content_editor/services/table_of_contents_utils_spec.js
new file mode 100644
index 00000000000..7f63c2171c2
--- /dev/null
+++ b/spec/frontend/content_editor/services/table_of_contents_utils_spec.js
@@ -0,0 +1,96 @@
+import Heading from '~/content_editor/extensions/heading';
+import { toTree, getHeadings } from '~/content_editor/services/table_of_contents_utils';
+import { createTestEditor, createDocBuilder } from '../test_utils';
+
+describe('content_editor/services/table_of_content_utils', () => {
+ describe('toTree', () => {
+ it('should fills in gaps in heading levels and convert headings to a tree', () => {
+ expect(
+ toTree([
+ { level: 3, text: '3' },
+ { level: 2, text: '2' },
+ ]),
+ ).toEqual([
+ expect.objectContaining({
+ level: 1,
+ text: '',
+ subHeadings: [
+ expect.objectContaining({
+ level: 2,
+ text: '',
+ subHeadings: [expect.objectContaining({ level: 3, text: '3', subHeadings: [] })],
+ }),
+ expect.objectContaining({ level: 2, text: '2', subHeadings: [] }),
+ ],
+ }),
+ ]);
+ });
+ });
+
+ describe('getHeadings', () => {
+ const tiptapEditor = createTestEditor({
+ extensions: [Heading],
+ });
+
+ const {
+ builders: { heading, doc },
+ } = createDocBuilder({
+ tiptapEditor,
+ names: {
+ heading: { nodeType: Heading.name },
+ },
+ });
+
+ it('gets all headings as a tree in a tiptap document', () => {
+ const initialDoc = doc(
+ heading({ level: 1 }, 'Heading 1'),
+ heading({ level: 2 }, 'Heading 1.1'),
+ heading({ level: 3 }, 'Heading 1.1.1'),
+ heading({ level: 2 }, 'Heading 1.2'),
+ heading({ level: 3 }, 'Heading 1.2.1'),
+ heading({ level: 2 }, 'Heading 1.3'),
+ heading({ level: 2 }, 'Heading 1.4'),
+ heading({ level: 3 }, 'Heading 1.4.1'),
+ heading({ level: 1 }, 'Heading 2'),
+ );
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+
+ expect(getHeadings(tiptapEditor)).toEqual([
+ expect.objectContaining({
+ level: 1,
+ text: 'Heading 1',
+ subHeadings: [
+ expect.objectContaining({
+ level: 2,
+ text: 'Heading 1.1',
+ subHeadings: [
+ expect.objectContaining({ level: 3, text: 'Heading 1.1.1', subHeadings: [] }),
+ ],
+ }),
+ expect.objectContaining({
+ level: 2,
+ text: 'Heading 1.2',
+ subHeadings: [
+ expect.objectContaining({ level: 3, text: 'Heading 1.2.1', subHeadings: [] }),
+ ],
+ }),
+ expect.objectContaining({ level: 2, text: 'Heading 1.3', subHeadings: [] }),
+ expect.objectContaining({
+ level: 2,
+ text: 'Heading 1.4',
+ subHeadings: [
+ expect.objectContaining({ level: 3, text: 'Heading 1.4.1', subHeadings: [] }),
+ ],
+ }),
+ ],
+ }),
+ expect.objectContaining({
+ level: 1,
+ text: 'Heading 2',
+ subHeadings: [],
+ }),
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/crm/contact_form_wrapper_spec.js b/spec/frontend/crm/contact_form_wrapper_spec.js
index 5e1743701e4..e49b553e4b5 100644
--- a/spec/frontend/crm/contact_form_wrapper_spec.js
+++ b/spec/frontend/crm/contact_form_wrapper_spec.js
@@ -56,8 +56,9 @@ describe('Customer relations contact form wrapper', () => {
${'edit'} | ${'Edit contact'} | ${'Contact has been updated.'} | ${updateContactMutation} | ${contacts[0].id}
${'create'} | ${'New contact'} | ${'Contact has been added.'} | ${createContactMutation} | ${null}
`('in $mode mode', ({ mode, title, successMessage, mutation, existingId }) => {
+ const isEditMode = mode === 'edit';
+
beforeEach(() => {
- const isEditMode = mode === 'edit';
mountComponent({ isEditMode });
return waitForPromises();
@@ -82,7 +83,7 @@ describe('Customer relations contact form wrapper', () => {
});
it('renders correct fields prop', () => {
- expect(findContactForm().props('fields')).toEqual([
+ const fields = [
{ name: 'firstName', label: 'First name', required: true },
{ name: 'lastName', label: 'Last name', required: true },
{ name: 'email', label: 'Email', required: true },
@@ -98,7 +99,9 @@ describe('Customer relations contact form wrapper', () => {
],
},
{ name: 'description', label: 'Description' },
- ]);
+ ];
+ if (isEditMode) fields.push({ name: 'active', label: 'Active', required: true, bool: true });
+ expect(findContactForm().props('fields')).toEqual(fields);
});
it('renders correct title prop', () => {
diff --git a/spec/frontend/crm/contacts_root_spec.js b/spec/frontend/crm/contacts_root_spec.js
index 3a6989a00f1..7aaaf480c44 100644
--- a/spec/frontend/crm/contacts_root_spec.js
+++ b/spec/frontend/crm/contacts_root_spec.js
@@ -1,14 +1,16 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
-import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ContactsRoot from '~/crm/contacts/components/contacts_root.vue';
import getGroupContactsQuery from '~/crm/contacts/components/graphql/get_group_contacts.query.graphql';
+import getGroupContactsCountByStateQuery from '~/crm/contacts/components/graphql/get_group_contacts_count_by_state.graphql';
import routes from '~/crm/contacts/routes';
-import { getGroupContactsQueryResponse } from './mock_data';
+import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
+import { getGroupContactsQueryResponse, getGroupContactsCountQueryResponse } from './mock_data';
describe('Customer relations contacts root app', () => {
Vue.use(VueApollo);
@@ -21,24 +23,30 @@ describe('Customer relations contacts root app', () => {
const findRowByName = (rowName) => wrapper.findAllByRole('row', { name: rowName });
const findIssuesLinks = () => wrapper.findAllByTestId('issues-link');
const findNewContactButton = () => wrapper.findByTestId('new-contact-button');
- const findError = () => wrapper.findComponent(GlAlert);
+ const findTable = () => wrapper.findComponent(PaginatedTableWithSearchAndTabs);
const successQueryHandler = jest.fn().mockResolvedValue(getGroupContactsQueryResponse);
+ const successCountQueryHandler = jest.fn().mockResolvedValue(getGroupContactsCountQueryResponse);
const basePath = '/groups/flightjs/-/crm/contacts';
const mountComponent = ({
queryHandler = successQueryHandler,
- mountFunction = shallowMountExtended,
+ countQueryHandler = successCountQueryHandler,
canAdminCrmContact = true,
+ textQuery = null,
} = {}) => {
- fakeApollo = createMockApollo([[getGroupContactsQuery, queryHandler]]);
- wrapper = mountFunction(ContactsRoot, {
+ fakeApollo = createMockApollo([
+ [getGroupContactsQuery, queryHandler],
+ [getGroupContactsCountByStateQuery, countQueryHandler],
+ ]);
+ wrapper = mountExtended(ContactsRoot, {
router,
provide: {
groupFullPath: 'flightjs',
groupId: 26,
groupIssuesPath: '/issues',
canAdminCrmContact,
+ textQuery,
},
apolloProvider: fakeApollo,
});
@@ -58,9 +66,33 @@ describe('Customer relations contacts root app', () => {
router = null;
});
- it('should render loading spinner', () => {
+ it('should render table with default props and loading state', () => {
mountComponent();
+ expect(findTable().props()).toMatchObject({
+ items: [],
+ itemsCount: {},
+ pageInfo: {},
+ statusTabs: [
+ { title: 'Active', status: 'ACTIVE', filters: 'active' },
+ { title: 'Inactive', status: 'INACTIVE', filters: 'inactive' },
+ { title: 'All', status: 'ALL', filters: 'all' },
+ ],
+ showItems: true,
+ showErrorMsg: false,
+ trackViewsOptions: { category: 'Customer Relations', action: 'view_contacts_list' },
+ i18n: {
+ emptyText: 'No contacts found',
+ issuesButtonLabel: 'View issues',
+ editButtonLabel: 'Edit',
+ title: 'Customer relations contacts',
+ newContact: 'New contact',
+ errorText: 'Something went wrong. Please try again.',
+ },
+ serverErrorMessage: '',
+ filterSearchKey: 'contacts',
+ filterSearchTokens: [],
+ });
expect(findLoadingIcon().exists()).toBe(true);
});
@@ -83,7 +115,7 @@ describe('Customer relations contacts root app', () => {
mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
await waitForPromises();
- expect(findError().exists()).toBe(true);
+ expect(wrapper.text()).toContain('Something went wrong. Please try again.');
});
});
@@ -92,11 +124,11 @@ describe('Customer relations contacts root app', () => {
mountComponent();
await waitForPromises();
- expect(findError().exists()).toBe(false);
+ expect(wrapper.text()).not.toContain('Something went wrong. Please try again.');
});
it('renders correct results', async () => {
- mountComponent({ mountFunction: mountExtended });
+ mountComponent();
await waitForPromises();
expect(findRowByName(/Marty/i)).toHaveLength(1);
@@ -105,7 +137,7 @@ describe('Customer relations contacts root app', () => {
const issueLink = findIssuesLinks().at(0);
expect(issueLink.exists()).toBe(true);
- expect(issueLink.attributes('href')).toBe('/issues?crm_contact_id=16');
+ expect(issueLink.attributes('href')).toBe('/issues?crm_contact_id=12');
});
});
});
diff --git a/spec/frontend/crm/form_spec.js b/spec/frontend/crm/form_spec.js
index d39f0795f5f..f0e9150cada 100644
--- a/spec/frontend/crm/form_spec.js
+++ b/spec/frontend/crm/form_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlFormInput, GlFormSelect, GlFormGroup } from '@gitlab/ui';
+import { GlAlert, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormGroup } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
@@ -78,6 +78,7 @@ describe('Reusable form component', () => {
const findSaveButton = () => wrapper.findByTestId('save-button');
const findForm = () => wrapper.find('form');
const findError = () => wrapper.findComponent(GlAlert);
+ const findFormGroup = (at) => wrapper.findAllComponents(GlFormGroup).at(at);
const mountComponent = (propsData) => {
wrapper = shallowMountExtended(Form, {
@@ -92,7 +93,7 @@ describe('Reusable form component', () => {
});
};
- const mountContact = ({ propsData } = {}) => {
+ const mountContact = ({ propsData, extraFields = [] } = {}) => {
mountComponent({
fields: [
{ name: 'firstName', label: 'First name', required: true },
@@ -108,6 +109,7 @@ describe('Reusable form component', () => {
{ key: 'gid://gitlab/CustomerRelations::Organization/2', value: 'ABC Corp' },
],
},
+ ...extraFields,
],
getQuery: {
query: getGroupContactsQuery,
@@ -136,7 +138,8 @@ describe('Reusable form component', () => {
mutation: updateContactMutation,
existingId: 'gid://gitlab/CustomerRelations::Contact/12',
};
- mountContact({ propsData });
+ const extraFields = [{ name: 'active', label: 'Active', required: true, bool: true }];
+ mountContact({ propsData, extraFields });
};
const mountOrganization = ({ propsData } = {}) => {
@@ -285,18 +288,16 @@ describe('Reusable form component', () => {
});
it.each`
- index | id | componentName | value
- ${0} | ${'firstName'} | ${'GlFormInput'} | ${'Marty'}
- ${1} | ${'lastName'} | ${'GlFormInput'} | ${'McFly'}
- ${2} | ${'email'} | ${'GlFormInput'} | ${'example@gitlab.com'}
- ${4} | ${'description'} | ${'GlFormInput'} | ${undefined}
- ${3} | ${'phone'} | ${'GlFormInput'} | ${undefined}
- ${5} | ${'organizationId'} | ${'GlFormSelect'} | ${'gid://gitlab/CustomerRelations::Organization/2'}
+ index | id | component | value
+ ${0} | ${'firstName'} | ${GlFormInput} | ${'Marty'}
+ ${1} | ${'lastName'} | ${GlFormInput} | ${'McFly'}
+ ${2} | ${'email'} | ${GlFormInput} | ${'example@gitlab.com'}
+ ${4} | ${'description'} | ${GlFormInput} | ${undefined}
+ ${3} | ${'phone'} | ${GlFormInput} | ${undefined}
+ ${5} | ${'organizationId'} | ${GlFormSelect} | ${'gid://gitlab/CustomerRelations::Organization/2'}
`(
- 'should render a $componentName for #$id with the value "$value"',
- ({ index, id, componentName, value }) => {
- const component = componentName === 'GlFormInput' ? GlFormInput : GlFormSelect;
- const findFormGroup = (at) => wrapper.findAllComponents(GlFormGroup).at(at);
+ 'should render the correct component for #$id with the value "$value"',
+ ({ index, id, component, value }) => {
const findFormElement = () => findFormGroup(index).find(component);
expect(findFormElement().attributes('id')).toBe(id);
@@ -304,6 +305,14 @@ describe('Reusable form component', () => {
},
);
+ it('should render a checked GlFormCheckbox for #active', () => {
+ const activeCheckboxIndex = 6;
+ const findFormElement = () => findFormGroup(activeCheckboxIndex).find(GlFormCheckbox);
+
+ expect(findFormElement().attributes('id')).toBe('active');
+ expect(findFormElement().attributes('checked')).toBe('true');
+ });
+
it('should include updated values in update mutation', () => {
wrapper.find('#firstName').vm.$emit('input', 'Michael');
wrapper
@@ -314,6 +323,7 @@ describe('Reusable form component', () => {
expect(handler).toHaveBeenCalledWith('updateContact', {
input: {
+ active: true,
description: null,
email: 'example@gitlab.com',
firstName: 'Michael',
diff --git a/spec/frontend/crm/mock_data.js b/spec/frontend/crm/mock_data.js
index 35bc7fb69b4..a2e2e88ac60 100644
--- a/spec/frontend/crm/mock_data.js
+++ b/spec/frontend/crm/mock_data.js
@@ -13,6 +13,7 @@ export const getGroupContactsQueryResponse = {
email: 'example@gitlab.com',
phone: null,
description: null,
+ active: true,
organization: {
__typename: 'CustomerRelationsOrganization',
id: 'gid://gitlab/CustomerRelations::Organization/2',
@@ -27,6 +28,7 @@ export const getGroupContactsQueryResponse = {
email: null,
phone: null,
description: null,
+ active: true,
organization: null,
},
{
@@ -37,9 +39,32 @@ export const getGroupContactsQueryResponse = {
email: 'jd@gitlab.com',
phone: '+44 44 4444 4444',
description: 'Vice President',
+ active: true,
organization: null,
},
],
+ pageInfo: {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ endCursor: 'eyJsYXN0X25hbWUiOiJMZWRuZXIiLCJpZCI6IjE3OSJ9',
+ hasPreviousPage: false,
+ startCursor: 'eyJsYXN0X25hbWUiOiJCYXJ0b24iLCJpZCI6IjE5MyJ9',
+ },
+ },
+ },
+ },
+};
+
+export const getGroupContactsCountQueryResponse = {
+ data: {
+ group: {
+ __typename: 'Group',
+ id: 'gid://gitlab/Group/26',
+ contactStateCounts: {
+ all: 241,
+ active: 239,
+ inactive: 2,
+ __typename: 'ContactStateCountsType',
},
},
},
@@ -58,6 +83,7 @@ export const getGroupOrganizationsQueryResponse = {
name: 'Test Inc',
defaultRate: 100,
description: null,
+ active: true,
},
{
__typename: 'CustomerRelationsOrganization',
@@ -65,6 +91,7 @@ export const getGroupOrganizationsQueryResponse = {
name: 'ABC Company',
defaultRate: 110,
description: 'VIP',
+ active: true,
},
{
__typename: 'CustomerRelationsOrganization',
@@ -72,6 +99,7 @@ export const getGroupOrganizationsQueryResponse = {
name: 'GitLab',
defaultRate: 120,
description: null,
+ active: true,
},
],
},
@@ -91,6 +119,7 @@ export const createContactMutationResponse = {
phone: null,
description: null,
organization: null,
+ active: true,
},
errors: [],
},
@@ -119,6 +148,7 @@ export const updateContactMutationResponse = {
phone: null,
description: null,
organization: null,
+ active: true,
},
errors: [],
},
@@ -143,6 +173,7 @@ export const createOrganizationMutationResponse = {
name: 'A',
defaultRate: null,
description: null,
+ active: true,
},
errors: [],
},
@@ -168,6 +199,7 @@ export const updateOrganizationMutationResponse = {
name: 'A',
defaultRate: null,
description: null,
+ active: true,
},
errors: [],
},
diff --git a/spec/frontend/crm/organization_form_wrapper_spec.js b/spec/frontend/crm/organization_form_wrapper_spec.js
index 1a5a7c6ca5d..9f26b9157e6 100644
--- a/spec/frontend/crm/organization_form_wrapper_spec.js
+++ b/spec/frontend/crm/organization_form_wrapper_spec.js
@@ -49,7 +49,7 @@ describe('Customer relations organization form wrapper', () => {
mountComponent({ isEditMode: true });
const organizationForm = findOrganizationForm();
- expect(organizationForm.props('fields')).toHaveLength(3);
+ expect(organizationForm.props('fields')).toHaveLength(4);
expect(organizationForm.props('title')).toBe('Edit organization');
expect(organizationForm.props('successMessage')).toBe('Organization has been updated.');
expect(organizationForm.props('mutation')).toBe(updateOrganizationMutation);
diff --git a/spec/frontend/cycle_analytics/base_spec.js b/spec/frontend/cycle_analytics/base_spec.js
index 7b1ef71da63..ea3da86c7b2 100644
--- a/spec/frontend/cycle_analytics/base_spec.js
+++ b/spec/frontend/cycle_analytics/base_spec.js
@@ -11,7 +11,6 @@ import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filter
import { NOT_ENOUGH_DATA_ERROR } from '~/cycle_analytics/constants';
import initState from '~/cycle_analytics/store/state';
import {
- permissions,
transformedProjectStagePathData,
selectedStage,
issueEvents,
@@ -34,7 +33,6 @@ let wrapper;
const { id: groupId, path: groupPath } = currentGroup;
const defaultState = {
- permissions,
currentGroup,
createdBefore,
createdAfter,
@@ -240,24 +238,6 @@ describe('Value stream analytics component', () => {
});
});
- describe('without enough permissions', () => {
- beforeEach(() => {
- wrapper = createComponent({
- initialState: {
- selectedStage,
- permissions: {
- ...permissions,
- [selectedStage.id]: false,
- },
- },
- });
- });
-
- it('renders the empty stage with `You need permission.` message', () => {
- expect(findEmptyStageTitle()).toBe('You need permission.');
- });
- });
-
describe('without a selected stage', () => {
beforeEach(() => {
wrapper = createComponent({
diff --git a/spec/frontend/cycle_analytics/mock_data.js b/spec/frontend/cycle_analytics/mock_data.js
index 1fe1dbbb75c..02666260cdb 100644
--- a/spec/frontend/cycle_analytics/mock_data.js
+++ b/spec/frontend/cycle_analytics/mock_data.js
@@ -101,30 +101,12 @@ export const selectedStage = {
...issueStage,
value: null,
active: false,
- isUserAllowed: true,
emptyStageText:
'The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.',
slug: 'issue',
};
-export const stats = [issueStage, planStage, codeStage, testStage, reviewStage, stagingStage];
-
-export const permissions = {
- issue: true,
- plan: true,
- code: true,
- test: true,
- review: true,
- staging: true,
-};
-
-export const rawData = {
- summary,
- stats,
- permissions,
-};
-
export const convertedData = {
summary: [
{ value: '20', title: 'New Issues' },
diff --git a/spec/frontend/cycle_analytics/store/actions_spec.js b/spec/frontend/cycle_analytics/store/actions_spec.js
index e775e941b4c..94b6de85a5c 100644
--- a/spec/frontend/cycle_analytics/store/actions_spec.js
+++ b/spec/frontend/cycle_analytics/store/actions_spec.js
@@ -153,6 +153,19 @@ describe('Project Value Stream Analytics actions', () => {
});
});
});
+
+ describe('with no value stream stages available', () => {
+ it('will return SET_NO_ACCESS_ERROR', () => {
+ state = { ...state, stages: [] };
+ testAction({
+ action: actions.setInitialStage,
+ state,
+ payload: null,
+ expectedMutations: [{ type: 'SET_NO_ACCESS_ERROR' }],
+ expectedActions: [],
+ });
+ });
+ });
});
describe('updateStageTablePagination', () => {
@@ -170,46 +183,6 @@ describe('Project Value Stream Analytics actions', () => {
});
});
- describe('fetchCycleAnalyticsData', () => {
- beforeEach(() => {
- state = { ...defaultState, endpoints: mockEndpoints };
- mock = new MockAdapter(axios);
- mock.onGet(mockRequestPath).reply(httpStatusCodes.OK);
- });
-
- it(`dispatches the 'setSelectedStage' and 'fetchStageData' actions`, () =>
- testAction({
- action: actions.fetchCycleAnalyticsData,
- state,
- payload: {},
- expectedMutations: [
- { type: 'REQUEST_CYCLE_ANALYTICS_DATA' },
- { type: 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS' },
- ],
- expectedActions: [],
- }));
-
- describe('with a failing request', () => {
- beforeEach(() => {
- state = { endpoints: mockEndpoints };
- mock = new MockAdapter(axios);
- mock.onGet(mockRequestPath).reply(httpStatusCodes.BAD_REQUEST);
- });
-
- it(`commits the 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR' mutation`, () =>
- testAction({
- action: actions.fetchCycleAnalyticsData,
- state,
- payload: {},
- expectedMutations: [
- { type: 'REQUEST_CYCLE_ANALYTICS_DATA' },
- { type: 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR' },
- ],
- expectedActions: [],
- }));
- });
- });
-
describe('fetchStageData', () => {
const mockStagePath = /value_streams\/\w+\/stages\/\w+\/records/;
const headers = {
@@ -529,14 +502,13 @@ describe('Project Value Stream Analytics actions', () => {
});
describe('fetchValueStreamStageData', () => {
- it('will dispatch the fetchCycleAnalyticsData, fetchStageData, fetchStageMedians and fetchStageCountValues actions', () =>
+ it('will dispatch the fetchStageData, fetchStageMedians and fetchStageCountValues actions', () =>
testAction({
action: actions.fetchValueStreamStageData,
state,
payload: {},
expectedMutations: [],
expectedActions: [
- { type: 'fetchCycleAnalyticsData' },
{ type: 'fetchStageData' },
{ type: 'fetchStageMedians' },
{ type: 'fetchStageCountValues' },
diff --git a/spec/frontend/cycle_analytics/store/mutations_spec.js b/spec/frontend/cycle_analytics/store/mutations_spec.js
index 2670a390e9c..2e9e5d91471 100644
--- a/spec/frontend/cycle_analytics/store/mutations_spec.js
+++ b/spec/frontend/cycle_analytics/store/mutations_spec.js
@@ -38,31 +38,24 @@ describe('Project Value Stream Analytics mutations', () => {
});
it.each`
- mutation | stateKey | value
- ${types.REQUEST_VALUE_STREAMS} | ${'valueStreams'} | ${[]}
- ${types.RECEIVE_VALUE_STREAMS_ERROR} | ${'valueStreams'} | ${[]}
- ${types.REQUEST_VALUE_STREAM_STAGES} | ${'stages'} | ${[]}
- ${types.RECEIVE_VALUE_STREAM_STAGES_ERROR} | ${'stages'} | ${[]}
- ${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'isLoading'} | ${true}
- ${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'hasError'} | ${false}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${'hasError'} | ${false}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'isLoading'} | ${false}
- ${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'hasError'} | ${true}
- ${types.REQUEST_STAGE_DATA} | ${'isLoadingStage'} | ${true}
- ${types.REQUEST_STAGE_DATA} | ${'isEmptyStage'} | ${false}
- ${types.REQUEST_STAGE_DATA} | ${'hasError'} | ${false}
- ${types.REQUEST_STAGE_DATA} | ${'selectedStageEvents'} | ${[]}
- ${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'isLoadingStage'} | ${false}
- ${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'selectedStageEvents'} | ${[]}
- ${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'hasError'} | ${false}
- ${types.RECEIVE_STAGE_DATA_ERROR} | ${'isLoadingStage'} | ${false}
- ${types.RECEIVE_STAGE_DATA_ERROR} | ${'selectedStageEvents'} | ${[]}
- ${types.RECEIVE_STAGE_DATA_ERROR} | ${'hasError'} | ${true}
- ${types.RECEIVE_STAGE_DATA_ERROR} | ${'isEmptyStage'} | ${true}
- ${types.REQUEST_STAGE_MEDIANS} | ${'medians'} | ${{}}
- ${types.RECEIVE_STAGE_MEDIANS_ERROR} | ${'medians'} | ${{}}
- ${types.REQUEST_STAGE_COUNTS} | ${'stageCounts'} | ${{}}
- ${types.RECEIVE_STAGE_COUNTS_ERROR} | ${'stageCounts'} | ${{}}
+ mutation | stateKey | value
+ ${types.REQUEST_VALUE_STREAMS} | ${'valueStreams'} | ${[]}
+ ${types.RECEIVE_VALUE_STREAMS_ERROR} | ${'valueStreams'} | ${[]}
+ ${types.REQUEST_VALUE_STREAM_STAGES} | ${'stages'} | ${[]}
+ ${types.RECEIVE_VALUE_STREAM_STAGES_ERROR} | ${'stages'} | ${[]}
+ ${types.REQUEST_STAGE_DATA} | ${'isLoadingStage'} | ${true}
+ ${types.REQUEST_STAGE_DATA} | ${'isEmptyStage'} | ${false}
+ ${types.REQUEST_STAGE_DATA} | ${'selectedStageEvents'} | ${[]}
+ ${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'isLoadingStage'} | ${false}
+ ${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'selectedStageEvents'} | ${[]}
+ ${types.RECEIVE_STAGE_DATA_ERROR} | ${'isLoadingStage'} | ${false}
+ ${types.RECEIVE_STAGE_DATA_ERROR} | ${'selectedStageEvents'} | ${[]}
+ ${types.RECEIVE_STAGE_DATA_ERROR} | ${'isEmptyStage'} | ${true}
+ ${types.REQUEST_STAGE_MEDIANS} | ${'medians'} | ${{}}
+ ${types.RECEIVE_STAGE_MEDIANS_ERROR} | ${'medians'} | ${{}}
+ ${types.REQUEST_STAGE_COUNTS} | ${'stageCounts'} | ${{}}
+ ${types.RECEIVE_STAGE_COUNTS_ERROR} | ${'stageCounts'} | ${{}}
+ ${types.SET_NO_ACCESS_ERROR} | ${'hasNoAccessError'} | ${true}
`('$mutation will set $stateKey to $value', ({ mutation, stateKey, value }) => {
mutations[mutation](state);
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index e3907fdbe15..cee1eec792d 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -6,8 +6,8 @@ import BatchDeleteButton from '~/design_management/components/delete_button.vue'
describe('Batch delete button component', () => {
let wrapper;
- const findButton = () => wrapper.find(GlButton);
- const findModal = () => wrapper.find(GlModal);
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findModal = () => wrapper.findComponent(GlModal);
function createComponent({ isDeleting = false } = {}, { slots = {} } = {}) {
wrapper = shallowMount(BatchDeleteButton, {
diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
index 77935fbde11..2091e1e08dd 100644
--- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js
@@ -26,13 +26,13 @@ describe('Design discussions component', () => {
const originalGon = window.gon;
let wrapper;
- const findDesignNotes = () => wrapper.findAll(DesignNote);
- const findReplyPlaceholder = () => wrapper.find(ReplyPlaceholder);
- const findReplyForm = () => wrapper.find(DesignReplyForm);
- const findRepliesWidget = () => wrapper.find(ToggleRepliesWidget);
+ const findDesignNotes = () => wrapper.findAllComponents(DesignNote);
+ const findReplyPlaceholder = () => wrapper.findComponent(ReplyPlaceholder);
+ const findReplyForm = () => wrapper.findComponent(DesignReplyForm);
+ const findRepliesWidget = () => wrapper.findComponent(ToggleRepliesWidget);
const findResolveButton = () => wrapper.find('[data-testid="resolve-button"]');
const findResolvedMessage = () => wrapper.find('[data-testid="resolved-message"]');
- const findResolveLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findResolveLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findResolveCheckbox = () => wrapper.find('[data-testid="resolve-checkbox"]');
const findApolloMutation = () => wrapper.findComponent(ApolloMutation);
@@ -307,7 +307,7 @@ describe('Design discussions component', () => {
expect(
wrapper
- .findAll(DesignNote)
+ .findAllComponents(DesignNote)
.wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')),
).toBe(true);
},
@@ -351,7 +351,7 @@ describe('Design discussions component', () => {
createComponent();
findReplyPlaceholder().vm.$emit('focus');
- expect(wrapper.emitted('open-form')).toBeTruthy();
+ expect(wrapper.emitted('open-form')).toHaveLength(1);
});
describe('when user is not logged in', () => {
diff --git a/spec/frontend/design_management/components/design_notes/design_note_spec.js b/spec/frontend/design_management/components/design_notes/design_note_spec.js
index 1f84fde9f7f..28833b4af5c 100644
--- a/spec/frontend/design_management/components/design_notes/design_note_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_note_spec.js
@@ -100,7 +100,7 @@ describe('Design note component', () => {
note,
});
- expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
+ expect(wrapper.findComponent(TimeAgoTooltip).exists()).toBe(true);
});
it('should not render edit icon when user does not have a permission', () => {
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 d2d1fe6b2d8..f7ce742b933 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
@@ -15,9 +15,9 @@ describe('Design reply form component', () => {
let wrapper;
const findTextarea = () => wrapper.find('textarea');
- const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
- const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
- const findModal = () => wrapper.find({ ref: 'cancelCommentModal' });
+ 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, {
@@ -42,6 +42,18 @@ describe('Design reply form component', () => {
expect(findTextarea().element).toEqual(document.activeElement);
});
+ it('renders "Attach a file or image" button in markdown toolbar', () => {
+ createComponent();
+
+ expect(wrapper.find('[data-testid="button-attach-file"]').exists()).toBe(true);
+ });
+
+ it('renders file upload progress container', () => {
+ createComponent();
+
+ expect(wrapper.find('.comment-toolbar .uploading-container').exists()).toBe(true);
+ });
+
it('renders button text as "Comment" when creating a comment', () => {
createComponent();
diff --git a/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js b/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
index f87228663b6..41129e2b58d 100644
--- a/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
+++ b/spec/frontend/design_management/components/design_notes/toggle_replies_widget_spec.js
@@ -8,10 +8,10 @@ describe('Toggle replies widget component', () => {
let wrapper;
const findToggleWrapper = () => wrapper.find('[data-testid="toggle-comments-wrapper"]');
- const findIcon = () => wrapper.find(GlIcon);
- const findButton = () => wrapper.find(GlButton);
- const findAuthorLink = () => wrapper.find(GlLink);
- const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findButton = () => wrapper.findComponent(GlButton);
+ const findAuthorLink = () => wrapper.findComponent(GlLink);
+ const findTimeAgo = () => wrapper.findComponent(TimeAgoTooltip);
function createComponent(props = {}) {
wrapper = shallowMount(ToggleRepliesWidget, {
diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js
index a04e2ebda5b..e1a66cea329 100644
--- a/spec/frontend/design_management/components/design_scaler_spec.js
+++ b/spec/frontend/design_management/components/design_scaler_spec.js
@@ -6,7 +6,7 @@ import DesignScaler from '~/design_management/components/design_scaler.vue';
describe('Design management design scaler component', () => {
let wrapper;
- const getButtons = () => wrapper.findAll(GlButton);
+ const getButtons = () => wrapper.findAllComponents(GlButton);
const getDecreaseScaleButton = () => getButtons().at(0);
const getResetScaleButton = () => getButtons().at(1);
const getIncreaseScaleButton = () => getButtons().at(2);
diff --git a/spec/frontend/design_management/components/design_sidebar_spec.js b/spec/frontend/design_management/components/design_sidebar_spec.js
index f13796138bd..af995f75ddc 100644
--- a/spec/frontend/design_management/components/design_sidebar_spec.js
+++ b/spec/frontend/design_management/components/design_sidebar_spec.js
@@ -32,12 +32,12 @@ describe('Design management design sidebar component', () => {
const originalGon = window.gon;
let wrapper;
- const findDiscussions = () => wrapper.findAll(DesignDiscussion);
+ const findDiscussions = () => wrapper.findAllComponents(DesignDiscussion);
const findFirstDiscussion = () => findDiscussions().at(0);
const findUnresolvedDiscussions = () => wrapper.findAll('[data-testid="unresolved-discussion"]');
const findResolvedDiscussions = () => wrapper.findAll('[data-testid="resolved-discussion"]');
- const findParticipants = () => wrapper.find(Participants);
- const findResolvedCommentsToggle = () => wrapper.find(GlAccordionItem);
+ const findParticipants = () => wrapper.findComponent(Participants);
+ const findResolvedCommentsToggle = () => wrapper.findComponent(GlAccordionItem);
const findNewDiscussionDisclaimer = () =>
wrapper.find('[data-testid="new-discussion-disclaimer"]');
@@ -87,7 +87,7 @@ describe('Design management design sidebar component', () => {
it('renders To-Do button', () => {
createComponent();
- expect(wrapper.find(DesignTodoButton).exists()).toBe(true);
+ expect(wrapper.findComponent(DesignTodoButton).exists()).toBe(true);
});
describe('when has no discussions', () => {
diff --git a/spec/frontend/design_management/components/design_todo_button_spec.js b/spec/frontend/design_management/components/design_todo_button_spec.js
index 73661c9fcb0..b3afcefe1ed 100644
--- a/spec/frontend/design_management/components/design_todo_button_spec.js
+++ b/spec/frontend/design_management/components/design_todo_button_spec.js
@@ -57,7 +57,7 @@ describe('Design management design todo button', () => {
});
it('renders TodoButton component', () => {
- expect(wrapper.find(TodoButton).exists()).toBe(true);
+ expect(wrapper.findComponent(TodoButton).exists()).toBe(true);
});
describe('when design has a pending todo', () => {
diff --git a/spec/frontend/design_management/components/image_spec.js b/spec/frontend/design_management/components/image_spec.js
index 65ee0ae6238..8163cb0d87a 100644
--- a/spec/frontend/design_management/components/image_spec.js
+++ b/spec/frontend/design_management/components/image_spec.js
@@ -71,7 +71,7 @@ describe('Design management large image component', () => {
image.trigger('error');
await nextTick();
expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
+ expect(wrapper.findComponent(GlIcon).element).toMatchSnapshot();
});
describe('zoom', () => {
diff --git a/spec/frontend/design_management/components/list/item_spec.js b/spec/frontend/design_management/components/list/item_spec.js
index e00dda2015e..66d3f883960 100644
--- a/spec/frontend/design_management/components/list/item_spec.js
+++ b/spec/frontend/design_management/components/list/item_spec.js
@@ -23,8 +23,8 @@ describe('Design management list item component', () => {
const findDesignEvent = () => wrapper.findByTestId('design-event');
const findImgFilename = (id = imgId) => wrapper.findByTestId(`design-img-filename-${id}`);
- const findEventIcon = () => findDesignEvent().find(GlIcon);
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findEventIcon = () => findDesignEvent().findComponent(GlIcon);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
function createComponent({
notesCount = 0,
@@ -74,7 +74,7 @@ describe('Design management list item component', () => {
beforeEach(async () => {
createComponent();
image = wrapper.find('img');
- glIntersectionObserver = wrapper.find(GlIntersectionObserver);
+ glIntersectionObserver = wrapper.findComponent(GlIntersectionObserver);
glIntersectionObserver.vm.$emit('appear');
await nextTick();
@@ -86,7 +86,7 @@ describe('Design management list item component', () => {
describe('before image is loaded', () => {
it('renders loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -105,7 +105,7 @@ describe('Design management list item component', () => {
image.trigger('error');
await nextTick();
expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
+ expect(wrapper.findComponent(GlIcon).element).toMatchSnapshot();
});
describe('when imageV432x230 and image provided', () => {
diff --git a/spec/frontend/design_management/components/toolbar/index_spec.js b/spec/frontend/design_management/components/toolbar/index_spec.js
index 412f3de911e..b6137ba2eee 100644
--- a/spec/frontend/design_management/components/toolbar/index_spec.js
+++ b/spec/frontend/design_management/components/toolbar/index_spec.js
@@ -85,35 +85,35 @@ describe('Design management toolbar component', () => {
createComponent();
await nextTick();
- expect(wrapper.find(DeleteButton).exists()).toBe(true);
+ expect(wrapper.findComponent(DeleteButton).exists()).toBe(true);
});
it('does not render delete button on non-latest version', async () => {
createComponent(false, true, { isLatestVersion: false });
await nextTick();
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
+ expect(wrapper.findComponent(DeleteButton).exists()).toBe(false);
});
it('does not render delete button when user is not logged in', async () => {
createComponent(false, false);
await nextTick();
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
+ expect(wrapper.findComponent(DeleteButton).exists()).toBe(false);
});
it('emits `delete` event on deleteButton `delete-selected-designs` event', async () => {
createComponent();
await nextTick();
- wrapper.find(DeleteButton).vm.$emit('delete-selected-designs');
+ wrapper.findComponent(DeleteButton).vm.$emit('delete-selected-designs');
expect(wrapper.emitted().delete).toBeTruthy();
});
it('renders download button with correct link', () => {
createComponent();
- expect(wrapper.find(GlButton).attributes('href')).toBe(
+ expect(wrapper.findComponent(GlButton).attributes('href')).toBe(
'/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d',
);
});
diff --git a/spec/frontend/design_management/components/upload/button_spec.js b/spec/frontend/design_management/components/upload/button_spec.js
index d123db43ce6..59821218ab8 100644
--- a/spec/frontend/design_management/components/upload/button_spec.js
+++ b/spec/frontend/design_management/components/upload/button_spec.js
@@ -34,7 +34,7 @@ describe('Design management upload button component', () => {
it('Button `loading` prop is `true`', () => {
createComponent({ isSaving: true });
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.exists()).toBe(true);
expect(button.props('loading')).toBe(true);
});
diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
index ec5db04bb80..7c26ab9739b 100644
--- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
+++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
@@ -46,7 +46,7 @@ describe('Design management design version dropdown component', () => {
wrapper.destroy();
});
- const findVersionLink = (index) => wrapper.findAll(GlDropdownItem).at(index);
+ const findVersionLink = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
it('renders design version dropdown button', async () => {
createComponent();
@@ -76,35 +76,35 @@ describe('Design management design version dropdown component', () => {
createComponent();
await nextTick();
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
});
it('displays latest version text when only 1 version is present', async () => {
createComponent({ maxVersions: 1 });
await nextTick();
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
});
it('displays version text when the current version is not the latest', async () => {
createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
await nextTick();
- expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
+ expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe(`Showing version #1`);
});
it('displays latest version text when the current version is the latest', async () => {
createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
await nextTick();
- expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.findComponent(GlDropdown).attributes('text')).toBe('Showing latest version');
});
it('should have the same length as apollo query', async () => {
createComponent();
await nextTick();
- expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
+ expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
});
it('should render TimeAgo', async () => {
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index 17a299c5de1..774e37a8b21 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -85,9 +85,9 @@ describe('Design management design index page', () => {
let wrapper;
let router;
- const findDiscussionForm = () => wrapper.find(DesignReplyForm);
- const findSidebar = () => wrapper.find(DesignSidebar);
- const findDesignPresentation = () => wrapper.find(DesignPresentation);
+ const findDiscussionForm = () => wrapper.findComponent(DesignReplyForm);
+ const findSidebar = () => wrapper.findComponent(DesignSidebar);
+ const findDesignPresentation = () => wrapper.findComponent(DesignPresentation);
function createComponent(
{ loading = false } = {},
@@ -181,15 +181,15 @@ describe('Design management design index page', () => {
it('sets loading state', () => {
createComponent({ loading: true });
- expect(wrapper.find(DesignPresentation).props('isLoading')).toBe(true);
- expect(wrapper.find(DesignSidebar).props('isLoading')).toBe(true);
+ expect(wrapper.findComponent(DesignPresentation).props('isLoading')).toBe(true);
+ expect(wrapper.findComponent(DesignSidebar).props('isLoading')).toBe(true);
});
it('renders design index', () => {
createComponent({ loading: false }, { data: { design } });
expect(wrapper.element).toMatchSnapshot();
- expect(wrapper.find(GlAlert).exists()).toBe(false);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
});
it('passes correct props to sidebar component', () => {
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 21be7bd148b..f90feaadfb0 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -111,8 +111,8 @@ describe('Design management index page', () => {
const findDropzoneWrapper = () => wrapper.findByTestId('design-dropzone-wrapper');
const findFirstDropzoneWithDesign = () => wrapper.findAllComponents(DesignDropzone).at(1);
const findDesignsWrapper = () => wrapper.findByTestId('designs-root');
- const findDesigns = () => wrapper.findAll(Design);
- const draggableAttributes = () => wrapper.find(VueDraggable).vm.$attrs;
+ const findDesigns = () => wrapper.findAllComponents(Design);
+ const draggableAttributes = () => wrapper.findComponent(VueDraggable).vm.$attrs;
const findDesignUploadButton = () => wrapper.findByTestId('design-upload-button');
const findDesignToolbarWrapper = () => wrapper.findByTestId('design-toolbar-wrapper');
const findDesignUpdateAlert = () => wrapper.findByTestId('design-update-alert');
@@ -120,8 +120,8 @@ describe('Design management index page', () => {
async function moveDesigns(localWrapper) {
await waitForPromises();
- localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
- localWrapper.find(VueDraggable).vm.$emit('change', {
+ localWrapper.findComponent(VueDraggable).vm.$emit('input', reorderedDesigns);
+ localWrapper.findComponent(VueDraggable).vm.$emit('change', {
moved: {
newIndex: 0,
element: designToMove,
@@ -369,7 +369,7 @@ describe('Design management index page', () => {
findDropzone().vm.$emit('change', [{ name: 'test' }]);
expect(mutate).toHaveBeenCalledWith(mutationVariables);
expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]);
- expect(wrapper.vm.isSaving).toBeTruthy();
+ expect(wrapper.vm.isSaving).toBe(true);
expect(dropzoneClasses()).toContain('design-list-item');
expect(dropzoneClasses()).toContain('design-list-item-new');
});
@@ -399,7 +399,7 @@ describe('Design management index page', () => {
await nextTick();
expect(wrapper.vm.filesToBeSaved).toEqual([]);
- expect(wrapper.vm.isSaving).toBeFalsy();
+ expect(wrapper.vm.isSaving).toBe(false);
expect(wrapper.vm.isLatestVersion).toBe(true);
});
@@ -412,7 +412,7 @@ describe('Design management index page', () => {
wrapper.vm.onUploadDesignError();
await nextTick();
expect(wrapper.vm.filesToBeSaved).toEqual([]);
- expect(wrapper.vm.isSaving).toBeFalsy();
+ expect(wrapper.vm.isSaving).toBe(false);
expect(findDesignUpdateAlert().exists()).toBe(true);
expect(findDesignUpdateAlert().text()).toBe(UPLOAD_DESIGN_ERROR);
});
diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js
index b9c62334223..b9edde559c8 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -44,7 +44,7 @@ describe('Design management router', () => {
it('pushes home component', () => {
const wrapper = factory(routeArg);
- expect(wrapper.find(Designs).exists()).toBe(true);
+ expect(wrapper.findComponent(Designs).exists()).toBe(true);
});
});
@@ -55,7 +55,7 @@ describe('Design management router', () => {
const wrapper = factory(routeArg);
return nextTick().then(() => {
- const detail = wrapper.find(DesignDetail);
+ const detail = wrapper.findComponent(DesignDetail);
expect(detail.exists()).toBe(true);
expect(detail.props('id')).toEqual('1');
});
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index d90afeb6b82..92b8b2d4aa3 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -263,7 +263,7 @@ describe('DiffFileHeader component', () => {
},
},
});
- expect(findModeChangedLine().exists()).toBeFalsy();
+ expect(findModeChangedLine().exists()).toBe(false);
},
);
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index be81508213b..a74013dc2d4 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -239,7 +239,7 @@ describe('DiffRow', () => {
const coverage = wrapper.find('.line-coverage.right-side');
expect(coverage.attributes('title')).toContain('Test coverage: 5 hits');
- expect(coverage.classes('coverage')).toBeTruthy();
+ expect(coverage.classes('coverage')).toBe(true);
});
it('for lines without coverage', () => {
@@ -248,7 +248,7 @@ describe('DiffRow', () => {
const coverage = wrapper.find('.line-coverage.right-side');
expect(coverage.attributes('title')).toContain('No test coverage');
- expect(coverage.classes('no-coverage')).toBeTruthy();
+ expect(coverage.classes('no-coverage')).toBe(true);
});
it('for unknown lines', () => {
@@ -256,9 +256,9 @@ describe('DiffRow', () => {
wrapper = createWrapper({ props, state: { coverageFiles } });
const coverage = wrapper.find('.line-coverage.right-side');
- expect(coverage.attributes('title')).toBeFalsy();
- expect(coverage.classes('coverage')).toBeFalsy();
- expect(coverage.classes('no-coverage')).toBeFalsy();
+ expect(coverage.attributes('title')).toBeUndefined();
+ expect(coverage.classes('coverage')).toBe(false);
+ expect(coverage.classes('no-coverage')).toBe(false);
});
});
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 8852c6c62c5..3f870a98396 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -424,8 +424,8 @@ describe('DiffsStoreUtils', () => {
expect(firstChar).not.toBe('+');
expect(firstChar).not.toBe('-');
- expect(preparedDiff.diff_files[0].renderIt).toBeTruthy();
- expect(preparedDiff.diff_files[0].collapsed).toBeFalsy();
+ expect(preparedDiff.diff_files[0].renderIt).toBe(true);
+ expect(preparedDiff.diff_files[0].collapsed).toBe(false);
});
it('guarantees an empty array for both diff styles', () => {
@@ -506,8 +506,8 @@ describe('DiffsStoreUtils', () => {
});
it('sets the renderIt and collapsed attribute on files', () => {
- expect(preparedDiffFiles[0].renderIt).toBeTruthy();
- expect(preparedDiffFiles[0].collapsed).toBeFalsy();
+ expect(preparedDiffFiles[0].renderIt).toBe(true);
+ expect(preparedDiffFiles[0].collapsed).toBeUndefined();
});
it('guarantees an empty array of lines for both diff styles', () => {
diff --git a/spec/frontend/dropzone_input_spec.js b/spec/frontend/dropzone_input_spec.js
index a633de9ef56..0fe70bac6b7 100644
--- a/spec/frontend/dropzone_input_spec.js
+++ b/spec/frontend/dropzone_input_spec.js
@@ -29,7 +29,9 @@ describe('dropzone_input', () => {
it('returns valid dropzone when successfully initialize', () => {
const dropzone = dropzoneInput($(TEMPLATE));
- expect(dropzone.version).toBeTruthy();
+ expect(dropzone).toMatchObject({
+ version: expect.any(String),
+ });
});
describe('handlePaste', () => {
diff --git a/spec/frontend/editor/schema/ci/ci_schema_spec.js b/spec/frontend/editor/schema/ci/ci_schema_spec.js
index c59806a5d60..c9010fbec0c 100644
--- a/spec/frontend/editor/schema/ci/ci_schema_spec.js
+++ b/spec/frontend/editor/schema/ci/ci_schema_spec.js
@@ -2,7 +2,7 @@ import Ajv from 'ajv';
import AjvFormats from 'ajv-formats';
import CiSchema from '~/editor/schema/ci.json';
-// JSON POSITIVE TESTS
+// JSON POSITIVE TESTS (LEGACY)
import AllowFailureJson from './json_tests/positive_tests/allow_failure.json';
import EnvironmentJson from './json_tests/positive_tests/environment.json';
import GitlabCiDependenciesJson from './json_tests/positive_tests/gitlab-ci-dependencies.json';
@@ -14,7 +14,7 @@ import TerraformReportJson from './json_tests/positive_tests/terraform_report.js
import VariablesMixStringAndUserInputJson from './json_tests/positive_tests/variables_mix_string_and_user_input.json';
import VariablesJson from './json_tests/positive_tests/variables.json';
-// JSON NEGATIVE TESTS
+// JSON NEGATIVE TESTS (LEGACY)
import DefaultNoAdditionalPropertiesJson from './json_tests/negative_tests/default_no_additional_properties.json';
import InheritDefaultNoAdditionalPropertiesJson from './json_tests/negative_tests/inherit_default_no_additional_properties.json';
import JobVariablesMustNotContainObjectsJson from './json_tests/negative_tests/job_variables_must_not_contain_objects.json';
@@ -24,14 +24,17 @@ import ReleaseAssetsLinksMissingJson from './json_tests/negative_tests/release_a
import RetryUnknownWhenJson from './json_tests/negative_tests/retry_unknown_when.json';
// YAML POSITIVE TEST
+import ArtifactsYaml from './yaml_tests/positive_tests/artifacts.yml';
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';
// 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';
const ajv = new Ajv({
strictTypes: false,
@@ -59,6 +62,7 @@ describe('positive tests', () => {
VariablesJson,
// YAML
+ ArtifactsYaml,
CacheYaml,
FilterYaml,
IncludeYaml,
@@ -82,8 +86,10 @@ describe('negative tests', () => {
RetryUnknownWhenJson,
// YAML
+ ArtifactsNegativeYaml,
CacheNegativeYaml,
IncludeNegativeYaml,
+ RulesNegativeYaml,
}),
)('schema validates %s', (_, input) => {
expect(input).not.toValidateJsonSchema(schema);
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
new file mode 100644
index 00000000000..f5670376efc
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/artifacts.yml
@@ -0,0 +1,18 @@
+# invalid artifact:reports:cyclonedx
+
+cyclonedx no paths:
+ artifacts:
+ reports:
+ cyclonedx:
+
+cyclonedx not a report:
+ artifacts:
+ cyclonedx: foo
+
+cyclonedx not an array or string:
+ artifacts:
+ reports:
+ cyclonedx:
+ paths:
+ - foo
+ - bar
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
index ee533f54d3b..04020c06753 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/cache.yml
@@ -1,15 +1,13 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70779
stages:
- prepare
-# invalid cache:when value
-job1:
+# invalid cache:when values
+when no integer:
stage: prepare
cache:
when: 0
-# invalid cache:when value
-job2:
+when must be a reserved word:
stage: prepare
cache:
when: 'never'
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/include.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/include.yml
index 287150a765f..1e16bb55405 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/include.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/include.yml
@@ -1,16 +1,14 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70779
stages:
- prepare
-# missing file property
-childPipeline:
+# invalid trigger:include
+trigger missing file property:
stage: prepare
trigger:
include:
- project: 'my-group/my-pipeline-library'
-# missing project property
-childPipeline2:
+trigger missing project property:
stage: prepare
trigger:
include:
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/rules.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/rules.yml
new file mode 100644
index 00000000000..d74a681b23b
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/rules.yml
@@ -0,0 +1,14 @@
+# invalid rules:changes
+unnecessary ref declaration:
+ script: exit 0
+ rules:
+ - changes:
+ paths:
+ - README.md
+ compare_to: { ref: 'main' }
+
+wrong path declaration:
+ script: exit 0
+ rules:
+ - changes:
+ paths: { file: 'DOCKER' }
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml
new file mode 100644
index 00000000000..20c1fc2c50f
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/artifacts.yml
@@ -0,0 +1,25 @@
+# valid artifact:reports:cyclonedx
+
+cyclonedx string path:
+ artifacts:
+ reports:
+ cyclonedx: foo
+
+cyclonedx glob path:
+ artifacts:
+ reports:
+ cyclonedx: "*.foo"
+
+cylonedx list of string paths:
+ artifacts:
+ reports:
+ cyclonedx:
+ - foo
+ - ./bar/baz
+
+cylonedx mixed list of string paths and globs:
+ artifacts:
+ reports:
+ cyclonedx:
+ - ./foo
+ - "bar/*.baz"
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
index 436c7d72699..d83e14fdc6a 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/cache.yml
@@ -1,8 +1,7 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70779
stages:
- prepare
-# test for cache:when values
+# valid cache:when values
job1:
stage: prepare
script:
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/filter.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/filter.yml
index 2b29c24fa3c..f82ea71dcf3 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/filter.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/filter.yml
@@ -1,5 +1,5 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79335
-deploy-template:
+# valid only/except values
+only and except as array of strings:
script:
- echo "hello world"
only:
@@ -7,12 +7,10 @@ deploy-template:
except:
- bar
-# null value allowed
-deploy-without-only:
+only as null value:
extends: deploy-template
only:
-# null value allowed
-deploy-without-except:
+except as null value:
extends: deploy-template
except:
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml
index 3497be28058..c00ab0d464a 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/include.yml
@@ -1,17 +1,15 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70779
+stages:
+ - prepare
-# test for include:rules
+# valid include:rules
include:
- local: builds.yml
rules:
- if: '$INCLUDE_BUILDS == "true"'
when: always
-stages:
- - prepare
-
-# test for trigger:include
-childPipeline:
+# valid trigger:include
+trigger:include accepts project and file properties:
stage: prepare
script:
- echo 'creating pipeline...'
@@ -20,8 +18,7 @@ childPipeline:
- project: 'my-group/my-pipeline-library'
file: '.gitlab-ci.yml'
-# accepts optional ref property
-childPipeline2:
+trigger:include accepts optional ref property:
stage: prepare
script:
- echo 'creating pipeline...'
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 27a199cff13..37cae6b4264 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
@@ -1,13 +1,28 @@
-# Covers https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74164
+# valid workflow:rules:changes
+rules:changes with paths and compare_to properties:
+ script: exit 0
+ rules:
+ - changes:
+ paths:
+ - README.md
+ compare_to: main
+
+rules:changes as array of strings:
+ script: exit 0
+ rules:
+ - changes:
+ - README.md
-# test for workflow:rules:changes and workflow:rules:exists
+# valid workflow:rules:exists
+# valid rules:changes:path
workflow:
rules:
+ - changes:
+ paths:
+ - README.md
- if: '$CI_PIPELINE_SOURCE == "schedule"'
exists:
- Dockerfile
- changes:
- - Dockerfile
variables:
IS_A_FEATURE: 'true'
when: always
diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js
index 99c4ff4f3fa..1223fee320e 100644
--- a/spec/frontend/editor/source_editor_instance_spec.js
+++ b/spec/frontend/editor/source_editor_instance_spec.js
@@ -423,7 +423,7 @@ describe('Source Editor Instance', () => {
'changes language of an attached model to "$expectedLanguage" when filepath is "$path"',
({ path, expectedLanguage }) => {
seInstance.updateModelLanguage(path);
- expect(instanceModel.getLanguageIdentifier().language).toBe(expectedLanguage);
+ expect(instanceModel.getLanguageId()).toBe(expectedLanguage);
},
);
});
diff --git a/spec/frontend/editor/source_editor_spec.js b/spec/frontend/editor/source_editor_spec.js
index 74aae7b899b..6a8e7b296aa 100644
--- a/spec/frontend/editor/source_editor_spec.js
+++ b/spec/frontend/editor/source_editor_spec.js
@@ -267,7 +267,6 @@ describe('Base editor', () => {
let editorEl2;
let inst1;
let inst2;
- const readOnlyIndex = '78'; // readOnly option has the internal index of 78 in the editor's options
beforeEach(() => {
setHTMLFixture('<div id="editor1"></div><div id="editor2"></div>');
@@ -331,10 +330,10 @@ describe('Base editor', () => {
});
inst1 = editor.createInstance(inst1Args);
- expect(inst1.getOption(readOnlyIndex)).toBe(true);
+ expect(inst1.getRawOptions().readOnly).toBe(true);
inst2 = editor.createInstance(inst2Args);
- expect(inst2.getOption(readOnlyIndex)).toBe(true);
+ expect(inst2.getRawOptions().readOnly).toBe(true);
});
it('allows overriding editor options on the instance level', () => {
@@ -346,7 +345,7 @@ describe('Base editor', () => {
readOnly: false,
});
- expect(inst1.getOption(readOnlyIndex)).toBe(false);
+ expect(inst1.getRawOptions().readOnly).toBe(false);
});
it('disposes instances and relevant models independently from each other', () => {
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index dc1c1dfbe4a..1c84350bd8e 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -70,7 +70,6 @@ class CustomEnvironment extends JSDOMEnvironment {
//
// Monaco-related environment variables
//
- this.global.MonacoEnvironment = { globalAPI: true };
Object.defineProperty(this.global, 'matchMedia', {
writable: true,
value: (query) => ({
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
index d58f9f9b8a2..340740e6499 100644
--- a/spec/frontend/environments/canary_ingress_spec.js
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -10,7 +10,7 @@ describe('/environments/components/canary_ingress.vue', () => {
const setWeightTo = (weightWrapper, x) =>
weightWrapper
- .findAll(GlDropdownItem)
+ .findAllComponents(GlDropdownItem)
.at(x / 5)
.vm.$emit('click');
@@ -59,14 +59,14 @@ describe('/environments/components/canary_ingress.vue', () => {
});
it('lists options from 0 to 100 in increments of 5', () => {
- const options = stableWeightDropdown.findAll(GlDropdownItem);
+ const options = stableWeightDropdown.findAllComponents(GlDropdownItem);
expect(options).toHaveLength(21);
options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
});
it('is set to open the change modal', () => {
stableWeightDropdown
- .findAll(GlDropdownItem)
+ .findAllComponents(GlDropdownItem)
.wrappers.forEach((w) =>
expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
);
@@ -92,13 +92,13 @@ describe('/environments/components/canary_ingress.vue', () => {
it('lists options from 0 to 100 in increments of 5', () => {
canaryWeightDropdown
- .findAll(GlDropdownItem)
+ .findAllComponents(GlDropdownItem)
.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
});
it('is set to open the change modal', () => {
canaryWeightDropdown
- .findAll(GlDropdownItem)
+ .findAllComponents(GlDropdownItem)
.wrappers.forEach((w) =>
expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
);
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
index 16792dcda1e..31b1770da59 100644
--- a/spec/frontend/environments/canary_update_modal_spec.js
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -10,7 +10,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
let modal;
let mutate;
- const findAlert = () => wrapper.find(GlAlert);
+ const findAlert = () => wrapper.findComponent(GlAlert);
const createComponent = () => {
mutate = jest.fn().mockResolvedValue();
@@ -27,7 +27,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
$apollo: { mutate },
},
});
- modal = wrapper.find(GlModal);
+ modal = wrapper.findComponent(GlModal);
};
afterEach(() => {
diff --git a/spec/frontend/environments/confirm_rollback_modal_spec.js b/spec/frontend/environments/confirm_rollback_modal_spec.js
index c4763933468..2163814528a 100644
--- a/spec/frontend/environments/confirm_rollback_modal_spec.js
+++ b/spec/frontend/environments/confirm_rollback_modal_spec.js
@@ -73,7 +73,7 @@ describe('Confirm Rollback Modal Component', () => {
hasMultipleCommits,
retryUrl,
});
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
expect(modal.attributes('title')).toContain('Rollback');
expect(modal.attributes('title')).toContain('test');
@@ -92,7 +92,7 @@ describe('Confirm Rollback Modal Component', () => {
hasMultipleCommits,
});
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
expect(modal.attributes('title')).toContain('Re-deploy');
expect(modal.attributes('title')).toContain('test');
@@ -110,7 +110,7 @@ describe('Confirm Rollback Modal Component', () => {
});
const eventHubSpy = jest.spyOn(eventHub, '$emit');
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
modal.vm.$emit('ok');
expect(eventHubSpy).toHaveBeenCalledWith('rollbackEnvironment', env);
@@ -155,7 +155,7 @@ describe('Confirm Rollback Modal Component', () => {
},
{ apolloProvider },
);
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
expect(trimText(modal.text())).toContain('commit abc0123');
expect(modal.text()).toContain('Are you sure you want to continue?');
@@ -177,7 +177,7 @@ describe('Confirm Rollback Modal Component', () => {
},
{ apolloProvider },
);
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
expect(modal.attributes('title')).toContain('Rollback');
expect(modal.attributes('title')).toContain('test');
@@ -201,7 +201,7 @@ describe('Confirm Rollback Modal Component', () => {
{ apolloProvider },
);
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
expect(modal.attributes('title')).toContain('Re-deploy');
expect(modal.attributes('title')).toContain('test');
@@ -220,7 +220,7 @@ describe('Confirm Rollback Modal Component', () => {
{ apolloProvider },
);
- const modal = component.find(GlModal);
+ const modal = component.findComponent(GlModal);
modal.vm.$emit('ok');
await nextTick();
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
index 4d63648dd48..c005ca22070 100644
--- a/spec/frontend/environments/deploy_board_component_spec.js
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -26,7 +26,9 @@ describe('Deploy Board', () => {
});
it('should render percentage with completion value provided', () => {
- expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${deployBoardMockData.completion}%`);
+ expect(wrapper.findComponent({ ref: 'percentage' }).text()).toBe(
+ `${deployBoardMockData.completion}%`,
+ );
});
it('should render total instance count', () => {
@@ -79,7 +81,9 @@ describe('Deploy Board', () => {
});
it('should render percentage with completion value provided', () => {
- expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${rolloutStatus.completion}%`);
+ expect(wrapper.findComponent({ ref: 'percentage' }).text()).toBe(
+ `${rolloutStatus.completion}%`,
+ );
});
it('should render total instance count', () => {
diff --git a/spec/frontend/environments/edit_environment_spec.js b/spec/frontend/environments/edit_environment_spec.js
index 2c8c054ccbd..0f2d6e95bf0 100644
--- a/spec/frontend/environments/edit_environment_spec.js
+++ b/spec/frontend/environments/edit_environment_spec.js
@@ -42,7 +42,7 @@ describe('~/environments/components/edit.vue', () => {
const findExternalUrlInput = () => wrapper.findByLabelText('External URL');
const findForm = () => wrapper.findByRole('form', { name: 'Edit environment' });
- const showsLoading = () => wrapper.find(GlLoadingIcon).exists();
+ const showsLoading = () => wrapper.findComponent(GlLoadingIcon).exists();
const submitForm = async (expected, response) => {
mock
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index ada79e2d415..68895b194a1 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -51,7 +51,7 @@ describe('EnvironmentActions Component', () => {
}
const findDropdownItem = (action) => {
- const buttons = wrapper.findAll(GlDropdownItem);
+ const buttons = wrapper.findAllComponents(GlDropdownItem);
return buttons.filter((button) => button.text().startsWith(action.name)).at(0);
};
@@ -62,12 +62,12 @@ describe('EnvironmentActions Component', () => {
it('should render a dropdown button with 2 icons', () => {
createComponent({}, { mountFn: mount });
- expect(wrapper.find(GlDropdown).findAll(GlIcon).length).toBe(2);
+ expect(wrapper.findComponent(GlDropdown).findAllComponents(GlIcon).length).toBe(2);
});
it('should render a dropdown button with aria-label description', () => {
createComponent();
- expect(wrapper.find(GlDropdown).attributes('aria-label')).toBe('Deploy to...');
+ expect(wrapper.findComponent(GlDropdown).attributes('aria-label')).toBe('Deploy to...');
});
it('should render a tooltip', () => {
@@ -98,11 +98,11 @@ describe('EnvironmentActions Component', () => {
});
it('should render a dropdown with the provided list of actions', () => {
- expect(wrapper.findAll(GlDropdownItem)).toHaveLength(actions.length);
+ expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(actions.length);
});
it("should render a disabled action when it's not playable", () => {
- const dropdownItems = wrapper.findAll(GlDropdownItem);
+ const dropdownItems = wrapper.findAllComponents(GlDropdownItem);
const lastDropdownItem = dropdownItems.at(dropdownItems.length - 1);
expect(lastDropdownItem.attributes('disabled')).toBe('true');
});
@@ -136,7 +136,7 @@ describe('EnvironmentActions Component', () => {
});
it('should render a dropdown button with a loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).isVisible()).toBe(true);
});
});
diff --git a/spec/frontend/environments/environment_delete_spec.js b/spec/frontend/environments/environment_delete_spec.js
index 057cb9858c4..530f9f55088 100644
--- a/spec/frontend/environments/environment_delete_spec.js
+++ b/spec/frontend/environments/environment_delete_spec.js
@@ -21,7 +21,7 @@ describe('External URL Component', () => {
});
};
- const findDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findDropdownItem = () => wrapper.findComponent(GlDropdownItem);
describe('event hub', () => {
beforeEach(() => {
diff --git a/spec/frontend/environments/environment_item_spec.js b/spec/frontend/environments/environment_item_spec.js
index 1c86a66d9b8..dd909cf4473 100644
--- a/spec/frontend/environments/environment_item_spec.js
+++ b/spec/frontend/environments/environment_item_spec.js
@@ -88,11 +88,11 @@ describe('Environment item', () => {
it('should render user avatar with link to profile', () => {
const avatarLink = findLastDeploymentAvatarLink();
const avatar = findLastDeploymentAvatar();
- const { username, avatar_url, web_url } = environment.last_deployment.user;
+ const { username, avatar_url: src, web_url } = environment.last_deployment.user;
expect(avatarLink.attributes('href')).toBe(web_url);
expect(avatar.props()).toMatchObject({
- src: avatar_url,
+ src,
entityName: username,
});
expect(avatar.attributes()).toMatchObject({
@@ -127,12 +127,12 @@ describe('Environment item', () => {
it('should render the build ID and user', () => {
const avatarLink = findUpcomingDeploymentAvatarLink();
const avatar = findUpcomingDeploymentAvatar();
- const { username, avatar_url, web_url } = environment.upcoming_deployment.user;
+ const { username, avatar_url: src, web_url } = environment.upcoming_deployment.user;
expect(findUpcomingDeploymentContent().text()).toMatchInterpolatedText('#27 by');
expect(avatarLink.attributes('href')).toBe(web_url);
expect(avatar.props()).toMatchObject({
- src: avatar_url,
+ src,
entityName: username,
});
});
@@ -166,12 +166,12 @@ describe('Environment item', () => {
it('should still render the build ID and user avatar', () => {
const avatarLink = findUpcomingDeploymentAvatarLink();
const avatar = findUpcomingDeploymentAvatar();
- const { username, avatar_url, web_url } = environment.upcoming_deployment.user;
+ const { username, avatar_url: src, web_url } = environment.upcoming_deployment.user;
expect(findUpcomingDeploymentContent().text()).toMatchInterpolatedText('#27 by');
expect(avatarLink.attributes('href')).toBe(web_url);
expect(avatar.props()).toMatchObject({
- src: avatar_url,
+ src,
entityName: username,
});
});
diff --git a/spec/frontend/environments/environment_pin_spec.js b/spec/frontend/environments/environment_pin_spec.js
index 669c974ea4f..170036b5b00 100644
--- a/spec/frontend/environments/environment_pin_spec.js
+++ b/spec/frontend/environments/environment_pin_spec.js
@@ -41,7 +41,7 @@ describe('Pin Component', () => {
it('should emit onPinClick when clicked', () => {
const eventHubSpy = jest.spyOn(eventHub, '$emit');
- const item = wrapper.find(GlDropdownItem);
+ const item = wrapper.findComponent(GlDropdownItem);
item.vm.$emit('click');
@@ -74,7 +74,7 @@ describe('Pin Component', () => {
it('should emit onPinClick when clicked', () => {
jest.spyOn(mockApollo.defaultClient, 'mutate');
- const item = wrapper.find(GlDropdownItem);
+ const item = wrapper.findComponent(GlDropdownItem);
item.vm.$emit('click');
diff --git a/spec/frontend/environments/environment_rollback_spec.js b/spec/frontend/environments/environment_rollback_spec.js
index 7eff46baaf7..be61c6fcc90 100644
--- a/spec/frontend/environments/environment_rollback_spec.js
+++ b/spec/frontend/environments/environment_rollback_spec.js
@@ -44,7 +44,7 @@ describe('Rollback Component', () => {
},
},
});
- const button = wrapper.find(GlDropdownItem);
+ const button = wrapper.findComponent(GlDropdownItem);
button.vm.$emit('click');
@@ -71,7 +71,7 @@ describe('Rollback Component', () => {
},
apolloProvider,
});
- const button = wrapper.find(GlDropdownItem);
+ const button = wrapper.findComponent(GlDropdownItem);
button.vm.$emit('click');
expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
diff --git a/spec/frontend/environments/environment_stop_spec.js b/spec/frontend/environments/environment_stop_spec.js
index 358abca2f77..851e24c22cc 100644
--- a/spec/frontend/environments/environment_stop_spec.js
+++ b/spec/frontend/environments/environment_stop_spec.js
@@ -22,7 +22,7 @@ describe('Stop Component', () => {
});
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
describe('eventHub', () => {
beforeEach(() => {
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index aff6b1327f0..49a643aaac8 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -177,10 +177,10 @@ describe('Environment table', () => {
},
});
- wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
+ wrapper.findComponent(DeployBoard).vm.$emit('changeCanaryWeight', 40);
await nextTick();
- expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
+ expect(wrapper.findComponent(CanaryUpdateModal).props()).toMatchObject({
weight: 40,
environment: mockItem,
});
diff --git a/spec/frontend/environments/environments_detail_header_spec.js b/spec/frontend/environments/environments_detail_header_spec.js
index 305e7385b43..4687119127d 100644
--- a/spec/frontend/environments/environments_detail_header_spec.js
+++ b/spec/frontend/environments/environments_detail_header_spec.js
@@ -1,5 +1,6 @@
import { GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
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';
@@ -43,6 +44,9 @@ describe('Environments detail header component', () => {
GlSprintf,
TimeAgo,
},
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
propsData: {
canAdminEnvironment: false,
canUpdateEnvironment: false,
@@ -185,6 +189,14 @@ describe('Environments detail header component', () => {
it('displays the metrics button with correct path', () => {
expect(findMetricsButton().attributes('href')).toBe(metricsPath);
});
+
+ it('uses a gl tooltip for the title', () => {
+ const button = findMetricsButton();
+ const tooltip = getBinding(button.element, 'gl-tooltip');
+
+ expect(tooltip).toBeDefined();
+ expect(button.attributes('title')).toBe('See metrics');
+ });
});
describe('when has all admin rights', () => {
diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js
index 9eb57b2682f..f8b8465cf6f 100644
--- a/spec/frontend/environments/folder/environments_folder_view_spec.js
+++ b/spec/frontend/environments/folder/environments_folder_view_spec.js
@@ -65,7 +65,7 @@ describe('Environments Folder View', () => {
});
it('should render a table with environments', () => {
- const table = wrapper.find(EnvironmentTable);
+ const table = wrapper.findComponent(EnvironmentTable);
expect(table.exists()).toBe(true);
expect(table.find('.environment-name').text()).toEqual(environmentsList[0].name);
@@ -93,7 +93,7 @@ describe('Environments Folder View', () => {
describe('pagination', () => {
it('should render pagination', () => {
- expect(wrapper.find(GlPagination).exists()).toBe(true);
+ expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
});
it('should make an API request when changing page', () => {
@@ -126,7 +126,7 @@ describe('Environments Folder View', () => {
});
it('should not render a table', () => {
- expect(wrapper.find(EnvironmentTable).exists()).toBe(false);
+ expect(wrapper.findComponent(EnvironmentTable).exists()).toBe(false);
});
it('should render available tab with count 0', () => {
diff --git a/spec/frontend/environments/new_environment_spec.js b/spec/frontend/environments/new_environment_spec.js
index f6d970e02d8..5a1c1c7714c 100644
--- a/spec/frontend/environments/new_environment_spec.js
+++ b/spec/frontend/environments/new_environment_spec.js
@@ -40,7 +40,7 @@ describe('~/environments/components/new.vue', () => {
wrapper.destroy();
});
- const showsLoading = () => wrapper.find(GlLoadingIcon).exists();
+ const showsLoading = () => wrapper.findComponent(GlLoadingIcon).exists();
const submitForm = async (expected, response) => {
mock
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 4273da6c735..732eff65495 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -35,7 +35,9 @@ describe('ErrorDetails', () => {
const externalUrl = 'https://sentry.io/organizations/test-sentry-nk/issues/1/?project=1';
const findInput = (name) => {
- const inputs = wrapper.findAll(GlFormInput).filter((c) => c.attributes('name') === name);
+ const inputs = wrapper
+ .findAllComponents(GlFormInput)
+ .filter((c) => c.attributes('name') === name);
return inputs.length ? inputs.at(0) : inputs;
};
@@ -44,7 +46,7 @@ describe('ErrorDetails', () => {
const findUpdateResolveStatusButton = () =>
wrapper.find('[data-testid="update-resolve-status-btn"]');
const findExternalUrl = () => wrapper.find('[data-testid="external-url-link"]');
- const findAlert = () => wrapper.find(GlAlert);
+ const findAlert = () => wrapper.findComponent(GlAlert);
function mountComponent() {
wrapper = shallowMount(ErrorDetails, {
@@ -119,9 +121,9 @@ describe('ErrorDetails', () => {
});
it('should show spinner while loading', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(GlLink).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(false);
+ expect(wrapper.findComponent(Stacktrace).exists()).toBe(false);
});
});
@@ -141,7 +143,7 @@ describe('ErrorDetails', () => {
wrapper.vm.onNoApolloResult();
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
expect(createFlash).not.toHaveBeenCalled();
expect(mocks.$apollo.queries.error.stopPolling).not.toHaveBeenCalled();
});
@@ -152,8 +154,8 @@ describe('ErrorDetails', () => {
wrapper.vm.onNoApolloResult();
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlLink).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(false);
expect(createFlash).toHaveBeenCalledWith({
message: 'Could not connect to Sentry. Refresh the page to try again.',
type: 'warning',
@@ -186,11 +188,11 @@ describe('ErrorDetails', () => {
});
it('should show Sentry error details without stacktrace', () => {
- expect(wrapper.find(GlLink).exists()).toBe(true);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
- expect(wrapper.find(GlBadge).exists()).toBe(false);
- expect(wrapper.findAll(GlButton)).toHaveLength(3);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(Stacktrace).exists()).toBe(false);
+ expect(wrapper.findComponent(GlBadge).exists()).toBe(false);
+ expect(wrapper.findAllComponents(GlButton)).toHaveLength(3);
});
describe('unsafe chars for culprit field', () => {
@@ -227,7 +229,7 @@ describe('ErrorDetails', () => {
},
});
await nextTick();
- expect(wrapper.findAll(GlBadge).length).toBe(2);
+ expect(wrapper.findAllComponents(GlBadge).length).toBe(2);
});
it('should NOT show the badge if the tag is not present', async () => {
@@ -239,7 +241,7 @@ describe('ErrorDetails', () => {
},
});
await nextTick();
- expect(wrapper.findAll(GlBadge).length).toBe(1);
+ expect(wrapper.findAllComponents(GlBadge).length).toBe(1);
});
it.each(Object.keys(severityLevel))(
@@ -253,7 +255,7 @@ describe('ErrorDetails', () => {
},
});
await nextTick();
- expect(wrapper.find(GlBadge).props('variant')).toEqual(
+ expect(wrapper.findComponent(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel[level]],
);
},
@@ -268,7 +270,7 @@ describe('ErrorDetails', () => {
},
});
await nextTick();
- expect(wrapper.find(GlBadge).props('variant')).toEqual(
+ expect(wrapper.findComponent(GlBadge).props('variant')).toEqual(
severityLevelVariant[severityLevel.ERROR],
);
});
@@ -278,8 +280,8 @@ describe('ErrorDetails', () => {
it('should show stacktrace', async () => {
store.state.details.loadingStacktrace = false;
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(Stacktrace).exists()).toBe(true);
expect(findAlert().exists()).toBe(false);
});
@@ -287,8 +289,8 @@ describe('ErrorDetails', () => {
store.state.details.loadingStacktrace = false;
store.getters = { 'details/sentryUrl': () => 'sentry.io', 'details/stacktrace': () => [] };
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(Stacktrace).exists()).toBe(false);
expect(findAlert().text()).toBe('No stack trace for this error');
});
});
diff --git a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
index 7ed4e5f6b05..5f6c9ddb4d7 100644
--- a/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_actions_spec.js
@@ -35,7 +35,7 @@ describe('Error Tracking Actions', () => {
}
});
- const findButtons = () => wrapper.findAll(GlButton);
+ const findButtons = () => wrapper.findAllComponents(GlButton);
describe('when error status is unresolved', () => {
it('renders the correct actions buttons to allow ignore and resolve', async () => {
diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
index 23d448f3964..b7dffbbec04 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -19,13 +19,13 @@ describe('ErrorTrackingList', () => {
const findErrorListTable = () => wrapper.find('table');
const findErrorListRows = () => wrapper.findAll('tbody tr');
- const dropdownsArray = () => wrapper.findAll(GlDropdown);
- const findRecentSearchesDropdown = () => dropdownsArray().at(0).find(GlDropdown);
- const findStatusFilterDropdown = () => dropdownsArray().at(1).find(GlDropdown);
- const findSortDropdown = () => dropdownsArray().at(2).find(GlDropdown);
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findPagination = () => wrapper.find(GlPagination);
- const findErrorActions = () => wrapper.find(ErrorTrackingActions);
+ const dropdownsArray = () => wrapper.findAllComponents(GlDropdown);
+ const findRecentSearchesDropdown = () => dropdownsArray().at(0).findComponent(GlDropdown);
+ const findStatusFilterDropdown = () => dropdownsArray().at(1).findComponent(GlDropdown);
+ const findSortDropdown = () => dropdownsArray().at(2).findComponent(GlDropdown);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findPagination = () => wrapper.findComponent(GlPagination);
+ const findErrorActions = () => wrapper.findComponent(ErrorTrackingActions);
const findIntegratedDisabledAlert = () => wrapper.findByTestId('integrated-disabled-alert');
function mountComponent({
@@ -152,12 +152,12 @@ describe('ErrorTrackingList', () => {
it('each error in the list should have an action button set', () => {
findErrorListRows().wrappers.forEach((row) => {
- expect(row.find(ErrorTrackingActions).exists()).toBe(true);
+ expect(row.findComponent(ErrorTrackingActions).exists()).toBe(true);
});
});
describe('filtering', () => {
- const findSearchBox = () => wrapper.find(GlFormInput);
+ const findSearchBox = () => wrapper.findComponent(GlFormInput);
it('shows search box & sort dropdown', () => {
expect(findSearchBox().exists()).toBe(true);
@@ -222,7 +222,7 @@ describe('ErrorTrackingList', () => {
});
it('shows empty state', () => {
- expect(wrapper.find(GlEmptyState).exists()).toBe(true);
+ expect(wrapper.findComponent(GlEmptyState).exists()).toBe(true);
expect(findLoadingIcon().exists()).toBe(false);
expect(findErrorListTable().exists()).toBe(false);
expect(dropdownsArray().length).toBe(0);
@@ -327,7 +327,7 @@ describe('ErrorTrackingList', () => {
});
it('shows empty state', () => {
- expect(wrapper.find(GlEmptyState).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlEmptyState).isVisible()).toBe(true);
});
});
@@ -358,7 +358,7 @@ describe('ErrorTrackingList', () => {
});
describe('clear', () => {
- const clearRecentButton = () => wrapper.find({ ref: 'clearRecentSearches' });
+ const clearRecentButton = () => wrapper.findComponent({ ref: 'clearRecentSearches' });
it('is hidden when list empty', () => {
store.state.list.recentSearches = [];
diff --git a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
index 0b43167c19b..693fcff50ca 100644
--- a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
+++ b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
@@ -36,10 +36,10 @@ describe('Stacktrace Entry', () => {
it('should render stacktrace entry collapsed', () => {
mountComponent({ lines });
- expect(wrapper.find(StackTraceEntry).exists()).toBe(true);
- expect(wrapper.find(ClipboardButton).exists()).toBe(true);
- expect(wrapper.find(GlIcon).exists()).toBe(true);
- expect(wrapper.find(FileIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(StackTraceEntry).exists()).toBe(true);
+ expect(wrapper.findComponent(ClipboardButton).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(FileIcon).exists()).toBe(true);
expect(wrapper.find('table').exists()).toBe(false);
});
@@ -56,7 +56,7 @@ describe('Stacktrace Entry', () => {
it('should hide collapse icon and render error fn name and error line when there is no code block', () => {
const extraInfo = { errorLine: 34, errorFn: 'errorFn', errorColumn: 77 };
mountComponent({ expanded: false, lines: [], ...extraInfo });
- expect(wrapper.find(GlIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(false);
expect(trimText(findFileHeaderContent())).toContain(
`in ${extraInfo.errorFn} at line ${extraInfo.errorLine}:${extraInfo.errorColumn}`,
);
diff --git a/spec/frontend/error_tracking/components/stacktrace_spec.js b/spec/frontend/error_tracking/components/stacktrace_spec.js
index 4f4a60acba4..cd5a57f5683 100644
--- a/spec/frontend/error_tracking/components/stacktrace_spec.js
+++ b/spec/frontend/error_tracking/components/stacktrace_spec.js
@@ -33,13 +33,13 @@ describe('ErrorDetails', () => {
it('should render single Stacktrace entry', () => {
mountComponent([stackTraceEntry]);
- expect(wrapper.findAll(StackTraceEntry).length).toBe(1);
+ expect(wrapper.findAllComponents(StackTraceEntry).length).toBe(1);
});
it('should render multiple Stacktrace entry', () => {
const entriesNum = 3;
mountComponent(new Array(entriesNum).fill(stackTraceEntry));
- expect(wrapper.findAll(StackTraceEntry).length).toBe(entriesNum);
+ expect(wrapper.findAllComponents(StackTraceEntry).length).toBe(entriesNum);
});
});
});
diff --git a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
index 1ba5a505f57..b44af547658 100644
--- a/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
+++ b/spec/frontend/error_tracking_settings/components/project_dropdown_spec.js
@@ -41,23 +41,23 @@ describe('error tracking settings project dropdown', () => {
describe('empty project list', () => {
it('renders the dropdown', () => {
- expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ expect(wrapper.find('#project-dropdown').exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
it('shows helper text', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeTruthy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(true);
expect(wrapper.find('.js-project-dropdown-label').text()).toContain(
'To enable project selection',
);
});
it('does not show an error', () => {
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(false);
});
it('does not contain any dropdown items', () => {
- expect(wrapper.find(GlDropdownItem).exists()).toBeFalsy();
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(false);
expect(wrapper.find(GlDropdown).props('text')).toBe('No projects available');
});
});
@@ -70,12 +70,12 @@ describe('error tracking settings project dropdown', () => {
});
it('renders the dropdown', () => {
- expect(wrapper.find('#project-dropdown').exists()).toBeTruthy();
- expect(wrapper.find(GlDropdown).exists()).toBeTruthy();
+ expect(wrapper.find('#project-dropdown').exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
});
it('contains a number of dropdown items', () => {
- expect(wrapper.find(GlDropdownItem).exists()).toBeTruthy();
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(true);
expect(wrapper.findAll(GlDropdownItem).length).toBe(2);
});
});
@@ -89,8 +89,8 @@ describe('error tracking settings project dropdown', () => {
});
it('does not show helper text', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeFalsy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(false);
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(false);
});
});
@@ -105,8 +105,8 @@ describe('error tracking settings project dropdown', () => {
});
it('displays a error', () => {
- expect(wrapper.find('.js-project-dropdown-label').exists()).toBeFalsy();
- expect(wrapper.find('.js-project-dropdown-error').exists()).toBeTruthy();
+ expect(wrapper.find('.js-project-dropdown-label').exists()).toBe(false);
+ expect(wrapper.find('.js-project-dropdown-error').exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
index 4a0242b4a46..c1051a14a08 100644
--- a/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
+++ b/spec/frontend/feature_flags/components/configure_feature_flags_modal_spec.js
@@ -39,7 +39,7 @@ describe('Configure Feature Flags Modal', () => {
const findSecondaryAction = () => findGlModal().props('actionSecondary');
const findProjectNameInput = () => wrapper.find('#project_name_verification');
const findDangerGlAlert = () =>
- wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'danger');
+ wrapper.findAllComponents(GlAlert).filter((c) => c.props('variant') === 'danger');
describe('idle', () => {
afterEach(() => wrapper.destroy());
@@ -157,7 +157,7 @@ describe('Configure Feature Flags Modal', () => {
beforeEach(factory.bind(null, { isRotating: true }));
it('should disable the project name input', async () => {
- expect(findProjectNameInput().attributes('disabled')).toBeTruthy();
+ expect(findProjectNameInput().attributes('disabled')).toBe('true');
});
});
});
diff --git a/spec/frontend/feature_flags/components/empty_state_spec.js b/spec/frontend/feature_flags/components/empty_state_spec.js
index 4ac82ae44a6..e3cc6f703c4 100644
--- a/spec/frontend/feature_flags/components/empty_state_spec.js
+++ b/spec/frontend/feature_flags/components/empty_state_spec.js
@@ -57,7 +57,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
beforeEach(() => {
wrapper = factory();
- alerts = wrapper.findAll(GlAlert);
+ alerts = wrapper.findAllComponents(GlAlert);
});
it('should show any alerts', () => {
@@ -68,7 +68,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
it('should emit a dismiss event for a dismissed alert', () => {
alerts.at(0).vm.$emit('dismiss');
- expect(wrapper.find(EmptyState).emitted('dismissAlert')).toEqual([[0]]);
+ expect(wrapper.findComponent(EmptyState).emitted('dismissAlert')).toEqual([[0]]);
});
});
@@ -78,8 +78,8 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
});
it('should show a loading icon and nothing else', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.findAll(GlEmptyState)).toHaveLength(0);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findAllComponents(GlEmptyState)).toHaveLength(0);
});
});
@@ -88,7 +88,7 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
beforeEach(() => {
wrapper = factory({ errorState: true });
- emptyState = wrapper.find(GlEmptyState);
+ emptyState = wrapper.findComponent(GlEmptyState);
});
it('should show an error state if there has been an error', () => {
@@ -106,8 +106,8 @@ describe('feature_flags/components/feature_flags_tab.vue', () => {
beforeEach(() => {
wrapper = factory({ emptyState: true });
- emptyState = wrapper.find(GlEmptyState);
- emptyStateLink = emptyState.find(GlLink);
+ emptyState = wrapper.findComponent(GlEmptyState);
+ emptyStateLink = emptyState.findComponent(GlLink);
});
it('should show an empty state if it is empty', () => {
diff --git a/spec/frontend/feature_flags/components/environments_dropdown_spec.js b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
index cca472012e9..e8103df78bc 100644
--- a/spec/frontend/feature_flags/components/environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/environments_dropdown_spec.js
@@ -23,7 +23,7 @@ describe('Feature flags > Environments dropdown ', () => {
});
};
- const findEnvironmentSearchInput = () => wrapper.find(GlSearchBoxByType);
+ const findEnvironmentSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
const findDropdownMenu = () => wrapper.find('.dropdown-menu');
afterEach(() => {
@@ -91,7 +91,7 @@ describe('Feature flags > Environments dropdown ', () => {
describe('with received data', () => {
it('sets is loading to false', () => {
expect(wrapper.vm.isLoading).toBe(false);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('shows the suggestions', () => {
@@ -100,7 +100,7 @@ describe('Feature flags > Environments dropdown ', () => {
it('emits event when a suggestion is clicked', async () => {
const button = wrapper
- .findAll(GlButton)
+ .findAllComponents(GlButton)
.filter((b) => b.text() === 'production')
.at(0);
button.vm.$emit('click');
@@ -111,7 +111,7 @@ describe('Feature flags > Environments dropdown ', () => {
describe('on click clear button', () => {
beforeEach(async () => {
- wrapper.find(GlButton).vm.$emit('click');
+ wrapper.findComponent(GlButton).vm.$emit('click');
await nextTick();
});
@@ -137,7 +137,7 @@ describe('Feature flags > Environments dropdown ', () => {
});
it('emits create event', async () => {
- wrapper.findAll(GlButton).at(0).vm.$emit('click');
+ wrapper.findAllComponents(GlButton).at(0).vm.$emit('click');
await nextTick();
expect(wrapper.emitted('createClicked')).toEqual([['production']]);
});
diff --git a/spec/frontend/feature_flags/components/feature_flags_table_spec.js b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
index 99864a95f59..47f12f70056 100644
--- a/spec/frontend/feature_flags/components/feature_flags_table_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_table_spec.js
@@ -119,7 +119,7 @@ describe('Feature flag table', () => {
it('should render an environments specs badge with active class', () => {
const envColumn = wrapper.find('.js-feature-flag-environments');
- expect(trimText(envColumn.find(GlBadge).text())).toBe('All Users: All Environments');
+ expect(trimText(envColumn.findComponent(GlBadge).text())).toBe('All Users: All Environments');
});
it('should render an actions column', () => {
@@ -137,7 +137,7 @@ describe('Feature flag table', () => {
beforeEach(() => {
props.featureFlags[0].update_path = props.featureFlags[0].destroy_path;
createWrapper(props);
- toggle = wrapper.find(GlToggle);
+ toggle = wrapper.findComponent(GlToggle);
spy = mockTracking('_category_', toggle.element, jest.spyOn);
});
diff --git a/spec/frontend/feature_flags/components/form_spec.js b/spec/frontend/feature_flags/components/form_spec.js
index 3ad1225906b..7dd7c709c94 100644
--- a/spec/frontend/feature_flags/components/form_spec.js
+++ b/spec/frontend/feature_flags/components/form_spec.js
@@ -61,7 +61,7 @@ describe('feature flag form', () => {
it('does not render the related issues widget without the featureFlagIssuesEndpoint', () => {
factory(requiredProps);
- expect(wrapper.find(RelatedIssuesRoot).exists()).toBe(false);
+ expect(wrapper.findComponent(RelatedIssuesRoot).exists()).toBe(false);
});
it('renders the related issues widget when the featureFlagIssuesEndpoint is provided', () => {
@@ -73,7 +73,7 @@ describe('feature flag form', () => {
},
);
- expect(wrapper.find(RelatedIssuesRoot).exists()).toBe(true);
+ expect(wrapper.findComponent(RelatedIssuesRoot).exists()).toBe(true);
});
describe('without provided data', () => {
@@ -114,7 +114,7 @@ describe('feature flag form', () => {
});
it('should show the strategy component', () => {
- const strategy = wrapper.find(Strategy);
+ const strategy = wrapper.findComponent(Strategy);
expect(strategy.exists()).toBe(true);
expect(strategy.props('strategy')).toEqual({
type: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
@@ -124,14 +124,14 @@ describe('feature flag form', () => {
});
it('should show one strategy component per strategy', () => {
- expect(wrapper.findAll(Strategy)).toHaveLength(2);
+ expect(wrapper.findAllComponents(Strategy)).toHaveLength(2);
});
it('adds an all users strategy when clicking the Add button', async () => {
- wrapper.find(GlButton).vm.$emit('click');
+ wrapper.findComponent(GlButton).vm.$emit('click');
await nextTick();
- const strategies = wrapper.findAll(Strategy);
+ const strategies = wrapper.findAllComponents(Strategy);
expect(strategies).toHaveLength(3);
expect(strategies.at(2).props('strategy')).toEqual(allUsersStrategy);
@@ -143,10 +143,10 @@ describe('feature flag form', () => {
parameters: { percentage: '30' },
scopes: [],
};
- wrapper.find(Strategy).vm.$emit('delete');
+ wrapper.findComponent(Strategy).vm.$emit('delete');
await nextTick();
- expect(wrapper.findAll(Strategy)).toHaveLength(1);
- expect(wrapper.find(Strategy).props('strategy')).not.toEqual(strategy);
+ expect(wrapper.findAllComponents(Strategy)).toHaveLength(1);
+ expect(wrapper.findComponent(Strategy).props('strategy')).not.toEqual(strategy);
});
});
});
diff --git a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
index 63fa5d19982..1c0c444c296 100644
--- a/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
+++ b/spec/frontend/feature_flags/components/new_environments_dropdown_spec.js
@@ -31,17 +31,17 @@ describe('New Environments Dropdown', () => {
describe('before results', () => {
it('should show a loading icon', () => {
axiosMock.onGet(TEST_HOST).reply(() => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
- wrapper.find(GlSearchBoxByType).vm.$emit('focus');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('focus');
return axios.waitForAll();
});
it('should not show any dropdown items', () => {
axiosMock.onGet(TEST_HOST).reply(() => {
- expect(wrapper.findAll(GlDropdownItem)).toHaveLength(0);
+ expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(0);
});
- wrapper.find(GlSearchBoxByType).vm.$emit('focus');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('focus');
return axios.waitForAll();
});
});
@@ -50,11 +50,11 @@ describe('New Environments Dropdown', () => {
let item;
beforeEach(async () => {
axiosMock.onGet(TEST_HOST).reply(200, []);
- wrapper.find(GlSearchBoxByType).vm.$emit('focus');
- wrapper.find(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH);
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('focus');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', TEST_SEARCH);
await axios.waitForAll();
await nextTick();
- item = wrapper.find(GlDropdownItem);
+ item = wrapper.findComponent(GlDropdownItem);
});
it('should display a Create item label', () => {
@@ -62,7 +62,7 @@ describe('New Environments Dropdown', () => {
});
it('should display that no matching items are found', () => {
- expect(wrapper.find({ ref: 'noResults' }).exists()).toBe(true);
+ expect(wrapper.findComponent({ ref: 'noResults' }).exists()).toBe(true);
});
it('should emit a new scope when selected', () => {
@@ -75,10 +75,10 @@ describe('New Environments Dropdown', () => {
let items;
beforeEach(() => {
axiosMock.onGet(TEST_HOST).reply(httpStatusCodes.OK, ['prod', 'production']);
- wrapper.find(GlSearchBoxByType).vm.$emit('focus');
- wrapper.find(GlSearchBoxByType).vm.$emit('input', 'prod');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('focus');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'prod');
return axios.waitForAll().then(() => {
- items = wrapper.findAll(GlDropdownItem);
+ items = wrapper.findAllComponents(GlDropdownItem);
});
});
@@ -97,7 +97,7 @@ describe('New Environments Dropdown', () => {
});
it('should not display a message about no results', () => {
- expect(wrapper.find({ ref: 'noResults' }).exists()).toBe(false);
+ expect(wrapper.findComponent({ ref: 'noResults' }).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/feature_flags/components/new_feature_flag_spec.js b/spec/frontend/feature_flags/components/new_feature_flag_spec.js
index 688ba54f919..300d0e47082 100644
--- a/spec/frontend/feature_flags/components/new_feature_flag_spec.js
+++ b/spec/frontend/feature_flags/components/new_feature_flag_spec.js
@@ -40,7 +40,7 @@ describe('New feature flag form', () => {
};
const findWarningGlAlert = () =>
- wrapper.findAll(GlAlert).filter((c) => c.props('variant') === 'warning');
+ wrapper.findAllComponents(GlAlert).filter((c) => c.props('variant') === 'warning');
beforeEach(() => {
factory();
@@ -65,11 +65,11 @@ describe('New feature flag form', () => {
});
it('should render feature flag form', () => {
- expect(wrapper.find(Form).exists()).toEqual(true);
+ expect(wrapper.findComponent(Form).exists()).toEqual(true);
});
it('has an all users strategy by default', () => {
- const strategies = wrapper.find(Form).props('strategies');
+ const strategies = wrapper.findComponent(Form).props('strategies');
expect(strategies).toEqual([allUsersStrategy]);
});
diff --git a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
index 56b14d80ab3..70a9156b5a9 100644
--- a/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/flexible_rollout_spec.js
@@ -34,12 +34,12 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
percentageFormGroup = wrapper
.find('[data-testid="strategy-flexible-rollout-percentage"]')
- .find(ParameterFormGroup);
- percentageInput = percentageFormGroup.find(GlFormInput);
+ .findComponent(ParameterFormGroup);
+ percentageInput = percentageFormGroup.findComponent(GlFormInput);
stickinessFormGroup = wrapper
.find('[data-testid="strategy-flexible-rollout-stickiness"]')
- .find(ParameterFormGroup);
- stickinessSelect = stickinessFormGroup.find(GlFormSelect);
+ .findComponent(ParameterFormGroup);
+ stickinessSelect = stickinessFormGroup.findComponent(GlFormSelect);
});
it('displays the current percentage value', () => {
@@ -94,7 +94,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
it('shows errors', () => {
const formGroup = wrapper
.find('[data-testid="strategy-flexible-rollout-percentage"]')
- .find(ParameterFormGroup);
+ .findComponent(ParameterFormGroup);
expect(formGroup.attributes('state')).toBeUndefined();
});
@@ -108,7 +108,7 @@ describe('feature_flags/components/strategies/flexible_rollout.vue', () => {
it('shows errors', () => {
const formGroup = wrapper
.find('[data-testid="strategy-flexible-rollout-percentage"]')
- .find(ParameterFormGroup);
+ .findComponent(ParameterFormGroup);
expect(formGroup.attributes('state')).toBeUndefined();
});
diff --git a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
index 3b69194494f..96b9434f3ec 100644
--- a/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/gitlab_user_list_spec.js
@@ -24,10 +24,10 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
propsData: { ...DEFAULT_PROPS, ...props },
});
- const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
describe('with user lists', () => {
- const findDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findDropdownItem = () => wrapper.findComponent(GlDropdownItem);
beforeEach(() => {
Api.searchFeatureFlagUserLists.mockResolvedValue({ data: [userList] });
@@ -69,10 +69,10 @@ describe('~/feature_flags/components/strategies/gitlab_user_list.vue', () => {
r = resolve;
}),
);
- const searchWrapper = wrapper.find(GlSearchBoxByType);
+ const searchWrapper = wrapper.findComponent(GlSearchBoxByType);
searchWrapper.vm.$emit('input', 'new');
await nextTick();
- const loadingIcon = wrapper.find(GlLoadingIcon);
+ const loadingIcon = wrapper.findComponent(GlLoadingIcon);
expect(loadingIcon.exists()).toBe(true);
expect(Api.searchFeatureFlagUserLists).toHaveBeenCalledWith('1', 'new');
diff --git a/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js b/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
index 33696064d55..23ad0d3a08d 100644
--- a/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/parameter_form_group_spec.js
@@ -20,7 +20,7 @@ describe('~/feature_flags/strategies/parameter_form_group.vue', () => {
},
});
- formGroup = wrapper.find(GlFormGroup);
+ formGroup = wrapper.findComponent(GlFormGroup);
slot = wrapper.find('[data-testid="slot"]');
});
diff --git a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
index 180697e93e4..cb422a018f9 100644
--- a/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/percent_rollout_spec.js
@@ -30,8 +30,8 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
beforeEach(() => {
wrapper = factory();
- input = wrapper.find(GlFormInput);
- formGroup = wrapper.find(ParameterFormGroup);
+ input = wrapper.findComponent(GlFormInput);
+ formGroup = wrapper.findComponent(ParameterFormGroup);
});
it('displays the current value', () => {
@@ -55,8 +55,8 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
beforeEach(() => {
wrapper = factory({ strategy: { parameters: { percentage: '101' } } });
- input = wrapper.find(GlFormInput);
- formGroup = wrapper.find(ParameterFormGroup);
+ input = wrapper.findComponent(GlFormInput);
+ formGroup = wrapper.findComponent(ParameterFormGroup);
});
it('shows errors', () => {
@@ -68,8 +68,8 @@ describe('~/feature_flags/components/strategies/percent_rollout.vue', () => {
beforeEach(() => {
wrapper = factory({ strategy: { parameters: { percentage: '3.14' } } });
- input = wrapper.find(GlFormInput);
- formGroup = wrapper.find(ParameterFormGroup);
+ input = wrapper.findComponent(GlFormInput);
+ formGroup = wrapper.findComponent(ParameterFormGroup);
});
it('shows errors', () => {
diff --git a/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js b/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
index 745fbca00fe..0a72714c22a 100644
--- a/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
+++ b/spec/frontend/feature_flags/components/strategies/users_with_id_spec.js
@@ -15,7 +15,7 @@ describe('~/feature_flags/components/users_with_id.vue', () => {
beforeEach(() => {
wrapper = factory();
- textarea = wrapper.find(GlFormTextarea);
+ textarea = wrapper.findComponent(GlFormTextarea);
});
afterEach(() => {
diff --git a/spec/frontend/feature_flags/components/strategy_parameters_spec.js b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
index 979ca255b08..d0f1f7d0e2a 100644
--- a/spec/frontend/feature_flags/components/strategy_parameters_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_parameters_spec.js
@@ -51,11 +51,11 @@ describe('~/feature_flags/components/strategy_parameters.vue', () => {
});
it('should show the correct component', () => {
- expect(wrapper.find(component).exists()).toBe(true);
+ expect(wrapper.findComponent(component).exists()).toBe(true);
});
it('should emit changes from the lower component', () => {
- const strategyParameterWrapper = wrapper.find(component);
+ const strategyParameterWrapper = wrapper.findComponent(component);
strategyParameterWrapper.vm.$emit('change', { parameters: { foo: 'bar' } });
@@ -77,7 +77,7 @@ describe('~/feature_flags/components/strategy_parameters.vue', () => {
strategy,
});
- expect(wrapper.find(UsersWithId).props('strategy')).toEqual(strategy);
+ expect(wrapper.findComponent(UsersWithId).props('strategy')).toEqual(strategy);
});
});
});
diff --git a/spec/frontend/feature_flags/components/strategy_spec.js b/spec/frontend/feature_flags/components/strategy_spec.js
index aee3873721c..84d4180fe63 100644
--- a/spec/frontend/feature_flags/components/strategy_spec.js
+++ b/spec/frontend/feature_flags/components/strategy_spec.js
@@ -32,8 +32,8 @@ Vue.use(Vuex);
describe('Feature flags strategy', () => {
let wrapper;
- const findStrategyParameters = () => wrapper.find(StrategyParameters);
- const findDocsLinks = () => wrapper.findAll(GlLink);
+ const findStrategyParameters = () => wrapper.findComponent(StrategyParameters);
+ const findDocsLinks = () => wrapper.findAllComponents(GlLink);
const factory = (
opts = {
@@ -93,7 +93,7 @@ describe('Feature flags strategy', () => {
});
it('should set the select to match the strategy name', () => {
- expect(wrapper.find(GlFormSelect).element.value).toBe(name);
+ expect(wrapper.findComponent(GlFormSelect).element.value).toBe(name);
});
it('should emit a change if the parameters component does', () => {
@@ -118,7 +118,7 @@ describe('Feature flags strategy', () => {
});
it('shows an alert asking users to consider using flexibleRollout instead', () => {
- expect(wrapper.find(GlAlert).text()).toContain(
+ expect(wrapper.findComponent(GlAlert).text()).toContain(
'Consider using the more flexible "Percent rollout" strategy instead.',
);
});
@@ -139,10 +139,10 @@ describe('Feature flags strategy', () => {
});
it('should revert to all-environments scope when last scope is removed', async () => {
- const token = wrapper.find(GlToken);
+ const token = wrapper.findComponent(GlToken);
token.vm.$emit('close');
await nextTick();
- expect(wrapper.findAll(GlToken)).toHaveLength(0);
+ expect(wrapper.findAllComponents(GlToken)).toHaveLength(0);
expect(last(wrapper.emitted('change'))).toEqual([
{
name: ROLLOUT_STRATEGY_PERCENT_ROLLOUT,
@@ -167,7 +167,7 @@ describe('Feature flags strategy', () => {
});
it('should change the parameters if a different strategy is chosen', async () => {
- const select = wrapper.find(GlFormSelect);
+ const select = wrapper.findComponent(GlFormSelect);
select.setValue(ROLLOUT_STRATEGY_ALL_USERS);
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
@@ -180,26 +180,26 @@ describe('Feature flags strategy', () => {
});
it('should display selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
await nextTick();
- expect(wrapper.findAll(GlToken)).toHaveLength(1);
- expect(wrapper.find(GlToken).text()).toBe('production');
+ expect(wrapper.findAllComponents(GlToken)).toHaveLength(1);
+ expect(wrapper.findComponent(GlToken).text()).toBe('production');
});
it('should display all selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
await nextTick();
- const tokens = wrapper.findAll(GlToken);
+ const tokens = wrapper.findAllComponents(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
it('should emit selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
@@ -215,7 +215,7 @@ describe('Feature flags strategy', () => {
});
it('should emit a delete if the delete button is clicked', () => {
- wrapper.find(GlButton).vm.$emit('click');
+ wrapper.findComponent(GlButton).vm.$emit('click');
expect(wrapper.emitted('delete')).toEqual([[]]);
});
});
@@ -232,26 +232,26 @@ describe('Feature flags strategy', () => {
});
it('should display selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
await nextTick();
- expect(wrapper.findAll(GlToken)).toHaveLength(1);
- expect(wrapper.find(GlToken).text()).toBe('production');
+ expect(wrapper.findAllComponents(GlToken)).toHaveLength(1);
+ expect(wrapper.findComponent(GlToken).text()).toBe('production');
});
it('should display all selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
dropdown.vm.$emit('add', 'staging');
await nextTick();
- const tokens = wrapper.findAll(GlToken);
+ const tokens = wrapper.findAllComponents(GlToken);
expect(tokens).toHaveLength(2);
expect(tokens.at(0).text()).toBe('production');
expect(tokens.at(1).text()).toBe('staging');
});
it('should emit selected scopes', async () => {
- const dropdown = wrapper.find(NewEnvironmentsDropdown);
+ const dropdown = wrapper.findComponent(NewEnvironmentsDropdown);
dropdown.vm.$emit('add', 'production');
await nextTick();
expect(last(wrapper.emitted('change'))).toEqual([
diff --git a/spec/frontend/fixtures/integrations.rb b/spec/frontend/fixtures/integrations.rb
index 1bafb0bfe78..45d1c400f5d 100644
--- a/spec/frontend/fixtures/integrations.rb
+++ b/spec/frontend/fixtures/integrations.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::Settings::IntegrationsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'integrations-project') }
let!(:service) { create(:custom_issue_tracker_integration, project: project) }
let(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb
index 8bedb802242..cde796497d4 100644
--- a/spec/frontend/fixtures/issues.rb
+++ b/spec/frontend/fixtures/issues.rb
@@ -106,3 +106,43 @@ RSpec.describe API::Issues, '(JavaScript fixtures)', type: :request do
expect(response).to be_successful
end
end
+
+RSpec.describe GraphQL::Query, type: :request do
+ include ApiHelpers
+ include GraphqlHelpers
+ include JavaScriptFixturesHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue_type) { 'issue' }
+
+ before_all do
+ project.add_reporter(user)
+ end
+
+ issue_popover_query_path = 'issuable/popover/queries/issue.query.graphql'
+
+ it "graphql/#{issue_popover_query_path}.json" do
+ query = get_graphql_query_as_string(issue_popover_query_path, ee: Gitlab.ee?)
+
+ issue = create(
+ :issue,
+ project: project,
+ confidential: true,
+ created_at: Time.parse('2020-07-01T04:08:01Z'),
+ due_date: Date.new(2020, 7, 5),
+ milestone: create(
+ :milestone,
+ project: project,
+ title: '15.2',
+ start_date: Date.new(2020, 7, 1),
+ due_date: Date.new(2020, 7, 30)
+ ),
+ issue_type: issue_type
+ )
+
+ post_graphql(query, current_user: user, variables: { projectPath: project.full_path, iid: issue.iid.to_s })
+
+ expect_graphql_errors_to_be_empty
+ end
+end
diff --git a/spec/frontend/fixtures/namespaces.rb b/spec/frontend/fixtures/namespaces.rb
new file mode 100644
index 00000000000..b11f661fe09
--- /dev/null
+++ b/spec/frontend/fixtures/namespaces.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Jobs (JavaScript fixtures)' do
+ include ApiHelpers
+ include JavaScriptFixturesHelpers
+ include GraphqlHelpers
+
+ describe GraphQL::Query, 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
+
+ query_name = 'search_namespaces_where_user_can_transfer_projects'
+ query_extension = '.query.graphql'
+
+ full_input_path = "projects/settings/graphql/queries/#{query_name}#{query_extension}"
+ base_output_path = "graphql/projects/settings/#{query_name}"
+
+ it "#{base_output_path}_page_1#{query_extension}.json" do
+ query = get_graphql_query_as_string(full_input_path)
+
+ post_graphql(query, current_user: user, variables: { first: 2 })
+
+ expect_graphql_errors_to_be_empty
+ end
+
+ it "#{base_output_path}_page_2#{query_extension}.json" do
+ query = get_graphql_query_as_string(full_input_path)
+
+ post_graphql(query, current_user: user, variables: { first: 2 })
+
+ post_graphql(
+ query,
+ current_user: user,
+ variables: { first: 2, after: graphql_data_at('currentUser', 'groups', 'pageInfo', 'endCursor') }
+ )
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+end
diff --git a/spec/frontend/fixtures/prometheus_integration.rb b/spec/frontend/fixtures/prometheus_integration.rb
index 883dbb929a2..250c50bc8bb 100644
--- a/spec/frontend/fixtures/prometheus_integration.rb
+++ b/spec/frontend/fixtures/prometheus_integration.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::Settings::IntegrationsController, '(JavaScript fixtures)', type: :controller do
include JavaScriptFixturesHelpers
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
+ let(:namespace) { create(:namespace, name: 'frontend-fixtures' ) }
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'integrations-project') }
let!(:integration) { create(:prometheus_integration, project: project) }
let(:user) { project.first_owner }
diff --git a/spec/frontend/fixtures/runner.rb b/spec/frontend/fixtures/runner.rb
index 36281af0219..b523650dda5 100644
--- a/spec/frontend/fixtures/runner.rb
+++ b/spec/frontend/fixtures/runner.rb
@@ -13,11 +13,12 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:project_2) { create(:project, :repository, :public) }
- let_it_be(:instance_runner) { create(:ci_runner, :instance, version: '1.0.0', revision: '123', description: 'Instance runner', ip_address: '127.0.0.1') }
- let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], active: false, version: '2.0.0', revision: '456', description: 'Group runner', ip_address: '127.0.0.1') }
- let_it_be(:group_runner_2) { create(:ci_runner, :group, groups: [group], active: false, version: '2.0.0', revision: '456', description: 'Group runner 2', ip_address: '127.0.0.1') }
- let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project, project_2], active: false, version: '2.0.0', revision: '456', description: 'Project runner', ip_address: '127.0.0.1') }
- let_it_be(:build) { create(:ci_build, runner: instance_runner) }
+ let_it_be(:runner) { create(:ci_runner, :instance, description: 'My Runner', version: '1.0.0') }
+ let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], version: '2.0.0') }
+ let_it_be(:group_runner_2) { create(:ci_runner, :group, groups: [group], version: '2.0.0') }
+ let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project, project_2], version: '2.0.0') }
+
+ let_it_be(:build) { create(:ci_build, runner: runner) }
query_path = 'runner/graphql/'
fixtures_path = 'graphql/runner/'
@@ -27,18 +28,19 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
before do
- allow(Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
- .and_return({ not_available: nil })
+ allow_next_instance_of(::Gitlab::Ci::RunnerUpgradeCheck) do |instance|
+ allow(instance).to receive(:check_runner_upgrade_suggestion)
+ .and_return([nil, :not_available])
+ end
end
- describe do
+ describe 'as admin', GraphQL::Query do
before do
sign_in(admin)
enable_admin_mode!(admin)
end
- describe GraphQL::Query, type: :request do
+ describe 'all_runners.query.graphql', type: :request do
all_runners_query = 'list/all_runners.query.graphql'
let_it_be(:query) do
@@ -58,7 +60,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe GraphQL::Query, type: :request do
+ describe 'all_runners_count.query.graphql', type: :request do
all_runners_count_query = 'list/all_runners_count.query.graphql'
let_it_be(:query) do
@@ -72,7 +74,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe GraphQL::Query, type: :request do
+ describe 'runner.query.graphql', type: :request do
runner_query = 'show/runner.query.graphql'
let_it_be(:query) do
@@ -81,7 +83,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
it "#{fixtures_path}#{runner_query}.json" do
post_graphql(query, current_user: admin, variables: {
- id: instance_runner.to_global_id.to_s
+ id: runner.to_global_id.to_s
})
expect_graphql_errors_to_be_empty
@@ -96,7 +98,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe GraphQL::Query, type: :request do
+ describe 'runner_projects.query.graphql', type: :request do
runner_projects_query = 'show/runner_projects.query.graphql'
let_it_be(:query) do
@@ -112,7 +114,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe GraphQL::Query, type: :request do
+ describe 'runner_jobs.query.graphql', type: :request do
runner_jobs_query = 'show/runner_jobs.query.graphql'
let_it_be(:query) do
@@ -121,14 +123,14 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
it "#{fixtures_path}#{runner_jobs_query}.json" do
post_graphql(query, current_user: admin, variables: {
- id: instance_runner.to_global_id.to_s
+ id: runner.to_global_id.to_s
})
expect_graphql_errors_to_be_empty
end
end
- describe GraphQL::Query, type: :request do
+ describe 'runner_form.query.graphql', type: :request do
runner_jobs_query = 'edit/runner_form.query.graphql'
let_it_be(:query) do
@@ -137,7 +139,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
it "#{fixtures_path}#{runner_jobs_query}.json" do
post_graphql(query, current_user: admin, variables: {
- id: instance_runner.to_global_id.to_s
+ id: runner.to_global_id.to_s
})
expect_graphql_errors_to_be_empty
@@ -145,14 +147,14 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe do
+ describe 'as group owner', GraphQL::Query do
let_it_be(:group_owner) { create(:user) }
before do
group.add_owner(group_owner)
end
- describe GraphQL::Query, type: :request do
+ describe 'group_runners.query.graphql', type: :request do
group_runners_query = 'list/group_runners.query.graphql'
let_it_be(:query) do
@@ -177,7 +179,7 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
end
- describe GraphQL::Query, type: :request do
+ describe 'group_runners_count.query.graphql', type: :request do
group_runners_count_query = 'list/group_runners_count.query.graphql'
let_it_be(:query) do
diff --git a/spec/frontend/frequent_items/components/app_spec.js b/spec/frontend/frequent_items/components/app_spec.js
index 32c66c0d288..c201bbf4af2 100644
--- a/spec/frontend/frequent_items/components/app_spec.js
+++ b/spec/frontend/frequent_items/components/app_spec.js
@@ -145,11 +145,16 @@ describe('Frequent Items App Component', () => {
expect(findFrequentItemsList().props()).toEqual(
expect.objectContaining({
items: mockSearchedProjects.data.map(
- ({ avatar_url, web_url, name_with_namespace, ...item }) => ({
+ ({
+ avatar_url: avatarUrl,
+ web_url: webUrl,
+ name_with_namespace: namespace,
+ ...item
+ }) => ({
...item,
- avatarUrl: avatar_url,
- webUrl: web_url,
- namespace: name_with_namespace,
+ avatarUrl,
+ webUrl,
+ namespace,
}),
),
namespace: TEST_NAMESPACE,
diff --git a/spec/frontend/gfm_auto_complete/mock_data.js b/spec/frontend/gfm_auto_complete/mock_data.js
new file mode 100644
index 00000000000..86795ffd0a5
--- /dev/null
+++ b/spec/frontend/gfm_auto_complete/mock_data.js
@@ -0,0 +1,34 @@
+export const eventlistenersMockDefaultMap = [
+ {
+ key: 'shown',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-users',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-issues',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-milestones',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-mergerequests',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-labels',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-snippets',
+ namespace: 'atwho',
+ },
+ {
+ key: 'shown-contacts',
+ namespace: 'atwho',
+ },
+];
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 072cf34d0ef..c3dfc4570f9 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -10,6 +10,7 @@ import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import AjaxCache from '~/lib/utils/ajax_cache';
import axios from '~/lib/utils/axios_utils';
+import { eventlistenersMockDefaultMap } from 'ee_else_ce_jest/gfm_auto_complete/mock_data';
describe('GfmAutoComplete', () => {
const fetchDataMock = { fetchData: jest.fn() };
@@ -457,12 +458,12 @@ describe('GfmAutoComplete', () => {
it('should be false with actual array data', () => {
expect(
- GfmAutoComplete.isLoading([{ title: 'Foo' }, { title: 'Bar' }, { title: 'Qux' }]),
+ GfmAutoComplete.isLoading([{ title: 'events' }, { title: 'Bar' }, { title: 'Qux' }]),
).toBe(false);
});
it('should be false with actual data item', () => {
- expect(GfmAutoComplete.isLoading({ title: 'Foo' })).toBe(false);
+ expect(GfmAutoComplete.isLoading({ title: 'events' })).toBe(false);
});
});
@@ -884,4 +885,47 @@ describe('GfmAutoComplete', () => {
).toBe(`<li><small>${escapedPayload} ${escapedPayload}</small> ${escapedPayload}</li>`);
});
});
+
+ describe('autocomplete show eventlisteners', () => {
+ let $textarea;
+
+ beforeEach(() => {
+ setHTMLFixture('<textarea></textarea>');
+ $textarea = $('textarea');
+ });
+
+ it('sets correct eventlisteners when autocomplete features are enabled', () => {
+ const autocomplete = new GfmAutoComplete({});
+ autocomplete.setup($textarea);
+ autocomplete.setupAtWho($textarea);
+ /* eslint-disable-next-line no-underscore-dangle */
+ const events = $._data($textarea[0], 'events');
+ expect(
+ Object.keys(events)
+ .filter((x) => {
+ return x.startsWith('shown');
+ })
+ .map((e) => {
+ return { key: e, namespace: events[e][0].namespace };
+ }),
+ ).toEqual(expect.arrayContaining(eventlistenersMockDefaultMap));
+ });
+
+ it('sets no eventlisteners when features are disabled', () => {
+ const autocomplete = new GfmAutoComplete({});
+ autocomplete.setup($textarea, {});
+ autocomplete.setupAtWho($textarea);
+ /* eslint-disable-next-line no-underscore-dangle */
+ const events = $._data($textarea[0], 'events');
+ expect(
+ Object.keys(events)
+ .filter((x) => {
+ return x.startsWith('shown');
+ })
+ .map((e) => {
+ return { key: e, namespace: events[e][0].namespace };
+ }),
+ ).toStrictEqual([]);
+ });
+ });
});
diff --git a/spec/frontend/group_settings/components/shared_runners_form_spec.js b/spec/frontend/group_settings/components/shared_runners_form_spec.js
index 70a22c86e62..5282c0ed839 100644
--- a/spec/frontend/group_settings/components/shared_runners_form_spec.js
+++ b/spec/frontend/group_settings/components/shared_runners_form_spec.js
@@ -1,24 +1,24 @@
import { GlAlert } from '@gitlab/ui';
-import MockAxiosAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import SharedRunnersForm from '~/group_settings/components/shared_runners_form.vue';
-import axios from '~/lib/utils/axios_utils';
+import { updateGroup } from '~/api/groups_api';
-const UPDATE_PATH = '/test/update';
+jest.mock('~/api/groups_api');
+
+const GROUP_ID = '99';
const RUNNER_ENABLED_VALUE = 'enabled';
const RUNNER_DISABLED_VALUE = 'disabled_and_unoverridable';
const RUNNER_ALLOW_OVERRIDE_VALUE = 'disabled_with_override';
describe('group_settings/components/shared_runners_form', () => {
let wrapper;
- let mock;
const createComponent = (provide = {}) => {
wrapper = shallowMountExtended(SharedRunnersForm, {
provide: {
- updatePath: UPDATE_PATH,
+ groupId: GROUP_ID,
sharedRunnersSetting: RUNNER_ENABLED_VALUE,
parentSharedRunnersSetting: null,
runnerEnabledValue: RUNNER_ENABLED_VALUE,
@@ -36,18 +36,19 @@ describe('group_settings/components/shared_runners_form', () => {
.at(0);
const findSharedRunnersToggle = () => wrapper.findByTestId('shared-runners-toggle');
const findOverrideToggle = () => wrapper.findByTestId('override-runners-toggle');
- const getSharedRunnersSetting = () => JSON.parse(mock.history.put[0].data).shared_runners_setting;
+ const getSharedRunnersSetting = () => {
+ return updateGroup.mock.calls[0][1].shared_runners_setting;
+ };
beforeEach(() => {
- mock = new MockAxiosAdapter(axios);
- mock.onPut(UPDATE_PATH).reply(200);
+ updateGroup.mockResolvedValue({});
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
- mock.restore();
+ updateGroup.mockReset();
});
describe('default state', () => {
@@ -115,7 +116,7 @@ describe('group_settings/components/shared_runners_form', () => {
findSharedRunnersToggle().vm.$emit('change', false);
await waitForPromises();
- expect(mock.history.put.length).toBe(1);
+ expect(updateGroup).toHaveBeenCalledTimes(1);
});
it('is not loading state after completed request', async () => {
@@ -170,12 +171,14 @@ describe('group_settings/components/shared_runners_form', () => {
});
describe.each`
- errorObj | message
+ errorData | message
${{}} | ${'An error occurred while updating configuration. Refresh the page and try again.'}
${{ error: 'Undefined error' }} | ${'Undefined error Refresh the page and try again.'}
- `(`with error $errorObj`, ({ errorObj, message }) => {
+ `(`with error $errorObj`, ({ errorData, message }) => {
beforeEach(async () => {
- mock.onPut(UPDATE_PATH).reply(500, errorObj);
+ updateGroup.mockRejectedValue({
+ response: { data: errorData },
+ });
createComponent();
findSharedRunnersToggle().vm.$emit('change', false);
diff --git a/spec/frontend/groups/components/app_spec.js b/spec/frontend/groups/components/app_spec.js
index 9e4666ffc70..a6bbea648d2 100644
--- a/spec/frontend/groups/components/app_spec.js
+++ b/spec/frontend/groups/components/app_spec.js
@@ -85,30 +85,6 @@ describe('AppComponent', () => {
await nextTick();
});
- describe('computed', () => {
- describe('groups', () => {
- it('should return list of groups from store', () => {
- jest.spyOn(vm.store, 'getGroups').mockImplementation(() => {});
-
- const { groups } = vm;
-
- expect(vm.store.getGroups).toHaveBeenCalled();
- expect(groups).not.toBeDefined();
- });
- });
-
- describe('pageInfo', () => {
- it('should return pagination info from store', () => {
- jest.spyOn(vm.store, 'getPaginationInfo').mockImplementation(() => {});
-
- const { pageInfo } = vm;
-
- expect(vm.store.getPaginationInfo).toHaveBeenCalled();
- expect(pageInfo).not.toBeDefined();
- });
- });
- });
-
describe('methods', () => {
describe('fetchGroups', () => {
it('should call `getGroups` with all the params provided', () => {
diff --git a/spec/frontend/groups/components/group_item_spec.js b/spec/frontend/groups/components/group_item_spec.js
index 0bc80df6535..9906f62878f 100644
--- a/spec/frontend/groups/components/group_item_spec.js
+++ b/spec/frontend/groups/components/group_item_spec.js
@@ -6,19 +6,20 @@ import ItemActions from '~/groups/components/item_actions.vue';
import eventHub from '~/groups/event_hub';
import { getGroupItemMicrodata } from '~/groups/store/utils';
import * as urlUtilities from '~/lib/utils/url_utility';
+import { ITEM_TYPE } from '~/groups/constants';
import {
- ITEM_TYPE,
- VISIBILITY_INTERNAL,
- VISIBILITY_PRIVATE,
- VISIBILITY_PUBLIC,
-} from '~/groups/constants';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
+ VISIBILITY_LEVEL_PRIVATE,
+ VISIBILITY_LEVEL_INTERNAL,
+ VISIBILITY_LEVEL_PUBLIC,
+} from '~/visibility_level/constants';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import { mockParentGroupItem, mockChildren } from '../mock_data';
const createComponent = (
propsData = { group: mockParentGroupItem, parentGroup: mockChildren[0] },
provide = {
- currentGroupVisibility: VISIBILITY_PRIVATE,
+ currentGroupVisibility: VISIBILITY_LEVEL_PRIVATE,
},
) => {
return mountExtended(GroupItem, {
@@ -289,7 +290,7 @@ describe('GroupItemComponent', () => {
});
describe('visibility warning popover', () => {
- const findPopover = () => wrapper.findComponent(GlPopover);
+ const findPopover = () => extendedWrapper(wrapper.findComponent(GlPopover));
const itDoesNotRenderVisibilityWarningPopover = () => {
it('does not render visibility warning popover', () => {
@@ -319,13 +320,16 @@ describe('GroupItemComponent', () => {
describe('when showing projects', () => {
describe.each`
- itemVisibility | currentGroupVisibility | isPopoverShown
- ${VISIBILITY_PRIVATE} | ${VISIBILITY_PUBLIC} | ${false}
- ${VISIBILITY_INTERNAL} | ${VISIBILITY_PUBLIC} | ${false}
- ${VISIBILITY_PUBLIC} | ${VISIBILITY_PUBLIC} | ${false}
- ${VISIBILITY_PRIVATE} | ${VISIBILITY_PRIVATE} | ${false}
- ${VISIBILITY_INTERNAL} | ${VISIBILITY_PRIVATE} | ${true}
- ${VISIBILITY_PUBLIC} | ${VISIBILITY_PRIVATE} | ${true}
+ itemVisibility | currentGroupVisibility | isPopoverShown
+ ${VISIBILITY_LEVEL_PRIVATE} | ${VISIBILITY_LEVEL_PUBLIC} | ${false}
+ ${VISIBILITY_LEVEL_INTERNAL} | ${VISIBILITY_LEVEL_PUBLIC} | ${false}
+ ${VISIBILITY_LEVEL_PUBLIC} | ${VISIBILITY_LEVEL_PUBLIC} | ${false}
+ ${VISIBILITY_LEVEL_PRIVATE} | ${VISIBILITY_LEVEL_PRIVATE} | ${false}
+ ${VISIBILITY_LEVEL_INTERNAL} | ${VISIBILITY_LEVEL_PRIVATE} | ${true}
+ ${VISIBILITY_LEVEL_PUBLIC} | ${VISIBILITY_LEVEL_PRIVATE} | ${true}
+ ${VISIBILITY_LEVEL_PRIVATE} | ${VISIBILITY_LEVEL_INTERNAL} | ${false}
+ ${VISIBILITY_LEVEL_INTERNAL} | ${VISIBILITY_LEVEL_INTERNAL} | ${false}
+ ${VISIBILITY_LEVEL_PUBLIC} | ${VISIBILITY_LEVEL_INTERNAL} | ${true}
`(
'when item visibility is $itemVisibility and parent group visibility is $currentGroupVisibility',
({ itemVisibility, currentGroupVisibility, isPopoverShown }) => {
@@ -347,8 +351,17 @@ describe('GroupItemComponent', () => {
});
if (isPopoverShown) {
- it('renders visibility warning popover', () => {
- expect(findPopover().exists()).toBe(true);
+ it('renders visibility warning popover with `Learn more` link', () => {
+ const popover = findPopover();
+
+ expect(popover.exists()).toBe(true);
+ expect(
+ popover.findByRole('link', { name: GroupItem.i18n.learnMore }).attributes('href'),
+ ).toBe(
+ helpPagePath('user/project/members/share_project_with_groups', {
+ anchor: 'sharing-projects-with-groups-of-a-higher-restrictive-visibility-level',
+ }),
+ );
});
} else {
itDoesNotRenderVisibilityWarningPopover();
@@ -361,7 +374,7 @@ describe('GroupItemComponent', () => {
wrapper = createComponent({
group: {
...mockParentGroupItem,
- visibility: VISIBILITY_PUBLIC,
+ visibility: VISIBILITY_LEVEL_PUBLIC,
type: ITEM_TYPE.PROJECT,
},
parentGroup: mockChildren[0],
diff --git a/spec/frontend/groups/components/group_name_and_path_spec.js b/spec/frontend/groups/components/group_name_and_path_spec.js
index 9c9bdead6fa..823d2ed286a 100644
--- a/spec/frontend/groups/components/group_name_and_path_spec.js
+++ b/spec/frontend/groups/components/group_name_and_path_spec.js
@@ -1,18 +1,23 @@
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
import { merge } from 'lodash';
-import { GlAlert } from '@gitlab/ui';
+import { GlAlert, GlDropdown, GlTruncate, GlDropdownItem } from '@gitlab/ui';
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'helpers/mock_apollo_helper';
import GroupNameAndPath from '~/groups/components/group_name_and_path.vue';
import { getGroupPathAvailability } from '~/rest_api';
import { createAlert } from '~/flash';
import { helpPagePath } from '~/helpers/help_page_helper';
+import searchGroupsWhereUserCanCreateSubgroups from '~/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql';
jest.mock('~/flash');
jest.mock('~/rest_api', () => ({
getGroupPathAvailability: jest.fn(),
}));
+Vue.use(VueApollo);
+
describe('GroupNameAndPath', () => {
let wrapper;
@@ -20,6 +25,17 @@ describe('GroupNameAndPath', () => {
const mockGroupUrl = 'my-awesome-group';
const mockGroupUrlSuggested = 'my-awesome-group1';
+ const mockQueryResponse = jest.fn().mockResolvedValue({
+ data: {
+ currentUser: {
+ id: '1',
+ groups: {
+ nodes: [{ id: '2', fullPath: '/path2' }],
+ },
+ },
+ },
+ });
+
const defaultProvide = {
basePath: 'http://gitlab.com/',
fields: {
@@ -32,13 +48,20 @@ describe('GroupNameAndPath', () => {
pattern: '[a-zA-Z0-9_\\.][a-zA-Z0-9_\\-\\.]*[a-zA-Z0-9_\\-]|[a-zA-Z0-9_]',
},
parentId: { name: 'group[parent_id]', id: 'group_parent_id', value: '1' },
+ parentFullPath: { name: 'group[parent_full_path]', id: 'group_full_path', value: '/path1' },
groupId: { name: 'group[id]', id: 'group_id', value: '' },
},
+ newSubgroup: false,
mattermostEnabled: false,
};
const createComponent = ({ provide = {} } = {}) => {
- wrapper = mountExtended(GroupNameAndPath, { provide: merge({}, defaultProvide, provide) });
+ wrapper = mountExtended(GroupNameAndPath, {
+ provide: merge({}, defaultProvide, provide),
+ apolloProvider: createMockApollo([
+ [searchGroupsWhereUserCanCreateSubgroups, mockQueryResponse],
+ ]),
+ });
};
const createComponentEditGroup = ({ path = mockGroupUrl } = {}) => {
createComponent({
@@ -46,8 +69,11 @@ describe('GroupNameAndPath', () => {
});
};
- const findGroupNameField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.name.label);
- const findGroupUrlField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.path.label);
+ const findGroupNameField = () => wrapper.findByLabelText('Group name');
+ const findGroupUrlField = () => wrapper.findByLabelText('Group URL');
+ const findSubgroupNameField = () => wrapper.findByLabelText('Subgroup name');
+ const findSubgroupSlugField = () => wrapper.findByLabelText('Subgroup slug');
+ const findSelectedGroup = () => wrapper.findComponent(GlTruncate);
const findAlert = () => extendedWrapper(wrapper.findComponent(GlAlert));
const apiMockAvailablePath = () => {
@@ -79,6 +105,41 @@ describe('GroupNameAndPath', () => {
});
});
+ describe('when creating a new subgroup', () => {
+ beforeEach(() => {
+ createComponent({ provide: { newSubgroup: true } });
+ });
+
+ it('updates `Subgroup slug` field as user types', async () => {
+ await findSubgroupNameField().setValue(mockGroupName);
+
+ expect(findSubgroupSlugField().element.value).toBe(mockGroupUrl);
+ });
+
+ describe('when user selects parent group', () => {
+ it('updates `Subgroup URL` dropdown and calls API', async () => {
+ expect(findSelectedGroup().text()).toContain('/path1');
+
+ await findSubgroupNameField().setValue(mockGroupName);
+
+ wrapper.findComponent(GlDropdown).vm.$emit('shown');
+ await wrapper.vm.$apollo.queries.currentUserGroups.refetch();
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
+
+ wrapper.findComponent(GlDropdownItem).vm.$emit('click');
+ await nextTick();
+
+ expect(findSelectedGroup().text()).toContain('/path2');
+ expect(getGroupPathAvailability).toHaveBeenCalled();
+
+ expect(wrapper.findByText(GroupNameAndPath.i18n.inputs.path.validFeedback).exists()).toBe(
+ true,
+ );
+ });
+ });
+ });
+
describe('when editing a group', () => {
it('does not update `Group URL` field and does not call API', async () => {
const groupUrl = 'foo-bar';
@@ -346,9 +407,7 @@ describe('GroupNameAndPath', () => {
it('shows `Group ID` field', () => {
createComponentEditGroup();
- expect(
- wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.groupId.label).element.value,
- ).toBe('1');
+ expect(wrapper.findByLabelText('Group ID').element.value).toBe('1');
});
});
});
diff --git a/spec/frontend/groups/components/groups_spec.js b/spec/frontend/groups/components/groups_spec.js
index 48a2319cf96..6c1eb373b7e 100644
--- a/spec/frontend/groups/components/groups_spec.js
+++ b/spec/frontend/groups/components/groups_spec.js
@@ -6,7 +6,7 @@ import GroupItemComponent from '~/groups/components/group_item.vue';
import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
import GroupsComponent from '~/groups/components/groups.vue';
import eventHub from '~/groups/event_hub';
-import { VISIBILITY_PRIVATE } from '~/groups/constants';
+import { VISIBILITY_LEVEL_PRIVATE } from '~/visibility_level/constants';
import { mockGroups, mockPageInfo } from '../mock_data';
describe('GroupsComponent', () => {
@@ -26,7 +26,7 @@ describe('GroupsComponent', () => {
...propsData,
},
provide: {
- currentGroupVisibility: VISIBILITY_PRIVATE,
+ currentGroupVisibility: VISIBILITY_LEVEL_PRIVATE,
},
});
};
diff --git a/spec/frontend/groups/components/transfer_group_form_spec.js b/spec/frontend/groups/components/transfer_group_form_spec.js
index 6dc760f4f7c..8cfe8ce8e18 100644
--- a/spec/frontend/groups/components/transfer_group_form_spec.js
+++ b/spec/frontend/groups/components/transfer_group_form_spec.js
@@ -82,7 +82,6 @@ describe('Transfer group form', () => {
it('sets the confirm danger properties', () => {
expect(findConfirmDanger().props()).toMatchObject({
- buttonClass: 'qa-transfer-button',
disabled: true,
buttonText: confirmButtonText,
phrase: confirmationPhrase,
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
index d89218f5542..6a138f9a247 100644
--- a/spec/frontend/header_search/components/app_spec.js
+++ b/spec/frontend/header_search/components/app_spec.js
@@ -15,6 +15,10 @@ import {
ICON_GROUP,
ICON_SUBGROUP,
SCOPE_TOKEN_MAX_LENGTH,
+ IS_SEARCHING,
+ IS_NOT_FOCUSED,
+ IS_FOCUSED,
+ SEARCH_SHORTCUTS_MIN_CHARACTERS,
} from '~/header_search/constants';
import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
import { ENTER_KEY } from '~/lib/utils/keys';
@@ -170,6 +174,14 @@ describe('HeaderSearchApp', () => {
it(`should render the Dropdown Navigation Component`, () => {
expect(findDropdownKeyboardNavigation().exists()).toBe(true);
});
+
+ it(`should close the dropdown when press escape key`, async () => {
+ findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: 27 }));
+ await nextTick();
+ expect(findHeaderSearchDropdown().exists()).toBe(false);
+ // only one event emmited from findHeaderSearchInput().vm.$emit('click');
+ expect(wrapper.emitted().expandSearchBar.length).toBe(1);
+ });
});
});
@@ -245,6 +257,7 @@ describe('HeaderSearchApp', () => {
searchOptions: () => searchOptions,
},
);
+ findHeaderSearchInput().vm.$emit('click');
});
it(`${hasToken ? 'is' : 'is NOT'} rendered when data set has type "${
@@ -263,47 +276,43 @@ describe('HeaderSearchApp', () => {
});
});
- describe('form wrapper', () => {
+ describe('form', () => {
describe.each`
- searchContext | search | searchOptions
- ${MOCK_SEARCH_CONTEXT_FULL} | ${null} | ${[]}
- ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${[]}
- ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS}
- ${null} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS}
- ${null} | ${null} | ${MOCK_SCOPED_SEARCH_OPTIONS}
- ${null} | ${null} | ${[]}
- `('', ({ searchContext, search, searchOptions }) => {
+ searchContext | search | searchOptions | isFocused
+ ${MOCK_SEARCH_CONTEXT_FULL} | ${null} | ${[]} | ${true}
+ ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${[]} | ${true}
+ ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
+ ${MOCK_SEARCH_CONTEXT_FULL} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${false}
+ ${null} | ${MOCK_SEARCH} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
+ ${null} | ${null} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${true}
+ ${null} | ${null} | ${[]} | ${true}
+ `('wrapper', ({ searchContext, search, searchOptions, isFocused }) => {
beforeEach(() => {
window.gon.current_username = MOCK_USERNAME;
-
createComponent({ search, searchContext }, { searchOptions: () => searchOptions });
-
- findHeaderSearchInput().vm.$emit('click');
+ if (isFocused) {
+ findHeaderSearchInput().vm.$emit('click');
+ }
});
- const hasIcon = Boolean(searchContext?.group);
- const isSearching = Boolean(search);
- const isActive = Boolean(searchOptions.length > 0);
+ const isSearching = search?.length > SEARCH_SHORTCUTS_MIN_CHARACTERS;
- it(`${hasIcon ? 'with' : 'without'} search context classes contain "${
- hasIcon ? 'has-icon' : 'has-no-icon'
- }"`, () => {
- const iconClassRegex = hasIcon ? 'has-icon' : 'has-no-icon';
- expect(findHeaderSearchForm().classes()).toContain(iconClassRegex);
+ it(`classes ${isSearching ? 'contain' : 'do not contain'} "${IS_SEARCHING}"`, () => {
+ if (isSearching) {
+ expect(findHeaderSearchForm().classes()).toContain(IS_SEARCHING);
+ return;
+ }
+ if (!isSearching) {
+ expect(findHeaderSearchForm().classes()).not.toContain(IS_SEARCHING);
+ }
});
- it(`${isSearching ? 'with' : 'without'} search string classes contain "${
- isSearching ? 'is-searching' : 'is-not-searching'
+ it(`classes ${isSearching ? 'contain' : 'do not contain'} "${
+ isFocused ? IS_FOCUSED : IS_NOT_FOCUSED
}"`, () => {
- const iconClassRegex = isSearching ? 'is-searching' : 'is-not-searching';
- expect(findHeaderSearchForm().classes()).toContain(iconClassRegex);
- });
-
- it(`${isActive ? 'with' : 'without'} search results classes contain "${
- isActive ? 'is-active' : 'is-not-active'
- }"`, () => {
- const iconClassRegex = isActive ? 'is-active' : 'is-not-active';
- expect(findHeaderSearchForm().classes()).toContain(iconClassRegex);
+ expect(findHeaderSearchForm().classes()).toContain(
+ isFocused ? IS_FOCUSED : IS_NOT_FOCUSED,
+ );
});
});
});
@@ -323,6 +332,7 @@ describe('HeaderSearchApp', () => {
searchOptions: () => searchOptions,
},
);
+ findHeaderSearchInput().vm.$emit('click');
});
it(`icon for data set type "${searchOptions[0]?.html_id}" ${
diff --git a/spec/frontend/helpers/diffs_helper_spec.js b/spec/frontend/helpers/diffs_helper_spec.js
index b223d48bf5c..c1ac7fac3fd 100644
--- a/spec/frontend/helpers/diffs_helper_spec.js
+++ b/spec/frontend/helpers/diffs_helper_spec.js
@@ -14,45 +14,45 @@ describe('diffs helper', () => {
describe('hasInlineLines', () => {
it('is false when the file does not exist', () => {
- expect(diffsHelper.hasInlineLines()).toBeFalsy();
+ expect(diffsHelper.hasInlineLines()).toBe(false);
});
it('is false when the file does not have the highlighted_diff_lines property', () => {
const missingInline = getDiffFile({ highlighted_diff_lines: undefined });
- expect(diffsHelper.hasInlineLines(missingInline)).toBeFalsy();
+ expect(diffsHelper.hasInlineLines(missingInline)).toBe(false);
});
it('is false when the file has zero highlighted_diff_lines', () => {
const emptyInline = getDiffFile({ highlighted_diff_lines: [] });
- expect(diffsHelper.hasInlineLines(emptyInline)).toBeFalsy();
+ expect(diffsHelper.hasInlineLines(emptyInline)).toBe(false);
});
it('is true when the file has at least 1 highlighted_diff_lines', () => {
- expect(diffsHelper.hasInlineLines(getDiffFile())).toBeTruthy();
+ expect(diffsHelper.hasInlineLines(getDiffFile())).toBe(true);
});
});
describe('hasParallelLines', () => {
it('is false when the file does not exist', () => {
- expect(diffsHelper.hasParallelLines()).toBeFalsy();
+ expect(diffsHelper.hasParallelLines()).toBe(false);
});
it('is false when the file does not have the parallel_diff_lines property', () => {
const missingInline = getDiffFile({ parallel_diff_lines: undefined });
- expect(diffsHelper.hasParallelLines(missingInline)).toBeFalsy();
+ expect(diffsHelper.hasParallelLines(missingInline)).toBe(false);
});
it('is false when the file has zero parallel_diff_lines', () => {
const emptyInline = getDiffFile({ parallel_diff_lines: [] });
- expect(diffsHelper.hasParallelLines(emptyInline)).toBeFalsy();
+ expect(diffsHelper.hasParallelLines(emptyInline)).toBe(false);
});
it('is true when the file has at least 1 parallel_diff_lines', () => {
- expect(diffsHelper.hasParallelLines(getDiffFile())).toBeTruthy();
+ expect(diffsHelper.hasParallelLines(getDiffFile())).toBe(true);
});
});
@@ -61,16 +61,16 @@ describe('diffs helper', () => {
const noParallelLines = getDiffFile({ parallel_diff_lines: undefined });
const emptyParallelLines = getDiffFile({ parallel_diff_lines: [] });
- expect(diffsHelper.isSingleViewStyle(noParallelLines)).toBeTruthy();
- expect(diffsHelper.isSingleViewStyle(emptyParallelLines)).toBeTruthy();
+ expect(diffsHelper.isSingleViewStyle(noParallelLines)).toBe(true);
+ expect(diffsHelper.isSingleViewStyle(emptyParallelLines)).toBe(true);
});
it('is true when the file has at least 1 parallel line but no inline lines for any reason', () => {
const noInlineLines = getDiffFile({ highlighted_diff_lines: undefined });
const emptyInlineLines = getDiffFile({ highlighted_diff_lines: [] });
- expect(diffsHelper.isSingleViewStyle(noInlineLines)).toBeTruthy();
- expect(diffsHelper.isSingleViewStyle(emptyInlineLines)).toBeTruthy();
+ expect(diffsHelper.isSingleViewStyle(noInlineLines)).toBe(true);
+ expect(diffsHelper.isSingleViewStyle(emptyInlineLines)).toBe(true);
});
it('is true when the file does not have any inline lines or parallel lines for any reason', () => {
@@ -83,13 +83,13 @@ describe('diffs helper', () => {
parallel_diff_lines: [],
});
- expect(diffsHelper.isSingleViewStyle(noLines)).toBeTruthy();
- expect(diffsHelper.isSingleViewStyle(emptyLines)).toBeTruthy();
- expect(diffsHelper.isSingleViewStyle()).toBeTruthy();
+ expect(diffsHelper.isSingleViewStyle(noLines)).toBe(true);
+ expect(diffsHelper.isSingleViewStyle(emptyLines)).toBe(true);
+ expect(diffsHelper.isSingleViewStyle()).toBe(true);
});
it('is false when the file has both inline and parallel lines', () => {
- expect(diffsHelper.isSingleViewStyle(getDiffFile())).toBeFalsy();
+ expect(diffsHelper.isSingleViewStyle(getDiffFile())).toBe(false);
});
});
diff --git a/spec/frontend/ide/components/activity_bar_spec.js b/spec/frontend/ide/components/activity_bar_spec.js
index 39fe2c7e723..a97e883a8bf 100644
--- a/spec/frontend/ide/components/activity_bar_spec.js
+++ b/spec/frontend/ide/components/activity_bar_spec.js
@@ -1,86 +1,82 @@
-import Vue, { nextTick } from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import ActivityBar from '~/ide/components/activity_bar.vue';
import { leftSidebarViews } from '~/ide/constants';
import { createStore } from '~/ide/stores';
-describe('IDE activity bar', () => {
- const Component = Vue.extend(ActivityBar);
- let vm;
+describe('IDE ActivityBar component', () => {
+ let wrapper;
let store;
- const findChangesBadge = () => vm.$el.querySelector('.badge');
+ const findChangesBadge = () => wrapper.findComponent(GlBadge);
- beforeEach(() => {
+ const mountComponent = (state) => {
store = createStore();
-
- Vue.set(store.state.projects, 'abcproject', {
- web_url: 'testing',
+ store.replaceState({
+ ...store.state,
+ projects: { abcproject: { web_url: 'testing' } },
+ currentProjectId: 'abcproject',
+ ...state,
});
- Vue.set(store.state, 'currentProjectId', 'abcproject');
- vm = createComponentWithStore(Component, store);
- });
+ wrapper = shallowMount(ActivityBar, { store });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('updateActivityBarView', () => {
beforeEach(() => {
- jest.spyOn(vm, 'updateActivityBarView').mockImplementation(() => {});
-
- vm.$mount();
+ mountComponent();
+ jest.spyOn(wrapper.vm, 'updateActivityBarView').mockImplementation(() => {});
});
it('calls updateActivityBarView with edit value on click', () => {
- vm.$el.querySelector('.js-ide-edit-mode').click();
+ wrapper.find('.js-ide-edit-mode').trigger('click');
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.edit.name);
+ expect(wrapper.vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.edit.name);
});
it('calls updateActivityBarView with commit value on click', () => {
- vm.$el.querySelector('.js-ide-commit-mode').click();
+ wrapper.find('.js-ide-commit-mode').trigger('click');
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.commit.name);
+ expect(wrapper.vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.commit.name);
});
it('calls updateActivityBarView with review value on click', () => {
- vm.$el.querySelector('.js-ide-review-mode').click();
+ wrapper.find('.js-ide-review-mode').trigger('click');
- expect(vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.review.name);
+ expect(wrapper.vm.updateActivityBarView).toHaveBeenCalledWith(leftSidebarViews.review.name);
});
});
describe('active item', () => {
- beforeEach(() => {
- vm.$mount();
- });
-
it('sets edit item active', () => {
- expect(vm.$el.querySelector('.js-ide-edit-mode').classList).toContain('active');
+ mountComponent();
+
+ expect(wrapper.find('.js-ide-edit-mode').classes()).toContain('active');
});
- it('sets commit item active', async () => {
- vm.$store.state.currentActivityView = leftSidebarViews.commit.name;
+ it('sets commit item active', () => {
+ mountComponent({ currentActivityView: leftSidebarViews.commit.name });
- await nextTick();
- expect(vm.$el.querySelector('.js-ide-commit-mode').classList).toContain('active');
+ expect(wrapper.find('.js-ide-commit-mode').classes()).toContain('active');
});
});
describe('changes badge', () => {
it('is rendered when files are staged', () => {
- store.state.stagedFiles = [{ path: '/path/to/file' }];
- vm.$mount();
+ mountComponent({ stagedFiles: [{ path: '/path/to/file' }] });
- expect(findChangesBadge()).toBeTruthy();
- expect(findChangesBadge().textContent.trim()).toBe('1');
+ expect(findChangesBadge().exists()).toBe(true);
+ expect(findChangesBadge().text()).toBe('1');
});
it('is not rendered when no changes are present', () => {
- vm.$mount();
- expect(findChangesBadge()).toBeFalsy();
+ mountComponent();
+
+ expect(findChangesBadge().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/branches/item_spec.js b/spec/frontend/ide/components/branches/item_spec.js
index 271d0600e16..3dbd1210916 100644
--- a/spec/frontend/ide/components/branches/item_spec.js
+++ b/spec/frontend/ide/components/branches/item_spec.js
@@ -44,8 +44,8 @@ describe('IDE branch item', () => {
});
it('renders branch name and timeago', () => {
expect(wrapper.text()).toContain(TEST_BRANCH.name);
- expect(wrapper.find(Timeago).props('time')).toBe(TEST_BRANCH.committedDate);
- expect(wrapper.find(GlIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(Timeago).props('time')).toBe(TEST_BRANCH.committedDate);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(false);
});
it('renders link to branch', () => {
@@ -60,6 +60,6 @@ describe('IDE branch item', () => {
it('renders icon if is not active', () => {
createComponent({ isActive: true });
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/branches/search_list_spec.js b/spec/frontend/ide/components/branches/search_list_spec.js
index b6e3274153a..bbde45d700f 100644
--- a/spec/frontend/ide/components/branches/search_list_spec.js
+++ b/spec/frontend/ide/components/branches/search_list_spec.js
@@ -47,7 +47,7 @@ describe('IDE branches search list', () => {
it('renders loading icon when `isLoading` is true', () => {
createComponent({ isLoading: true });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('renders branches not found when search is not empty and branches list is empty', async () => {
@@ -61,7 +61,7 @@ describe('IDE branches search list', () => {
describe('with branches', () => {
it('renders list', () => {
createComponent({ branches });
- const items = wrapper.findAll(Item);
+ const items = wrapper.findAllComponents(Item);
expect(items.length).toBe(branches.length);
});
@@ -69,7 +69,7 @@ describe('IDE branches search list', () => {
it('renders check next to active branch', () => {
const activeBranch = 'regular';
createComponent({ branches }, activeBranch);
- const items = wrapper.findAll(Item).filter((w) => w.props('isActive'));
+ const items = wrapper.findAllComponents(Item).filter((w) => w.props('isActive'));
expect(items.length).toBe(1);
expect(items.at(0).props('item').name).toBe(activeBranch);
diff --git a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
index d77e8e3d04c..f6d5833edee 100644
--- a/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/editor_header_spec.js
@@ -26,8 +26,8 @@ describe('IDE commit editor header', () => {
});
};
- const findDiscardModal = () => wrapper.find({ ref: 'discardModal' });
- const findDiscardButton = () => wrapper.find({ ref: 'discardButton' });
+ const findDiscardModal = () => wrapper.findComponent({ ref: 'discardModal' });
+ const findDiscardButton = () => wrapper.findComponent({ ref: 'discardButton' });
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index 28f62a9775a..a8ee81afa0b 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -58,7 +58,7 @@ describe('IDE commit form', () => {
});
const findForm = () => wrapper.find('form');
const submitForm = () => findForm().trigger('submit');
- const findCommitMessageInput = () => wrapper.find(CommitMessageField);
+ const findCommitMessageInput = () => wrapper.findComponent(CommitMessageField);
const setCommitMessageInput = (val) => findCommitMessageInput().vm.$emit('input', val);
const findDiscardDraftButton = () => wrapper.find('[data-testid="discard-draft"]');
@@ -302,7 +302,7 @@ describe('IDE commit form', () => {
${() => createCodeownersCommitError('test message')} | ${{ actionPrimary: { text: 'Create new branch' } }}
${createUnexpectedCommitError} | ${{ actionPrimary: null }}
`('opens error modal if commitError with $error', async ({ createError, props }) => {
- const modal = wrapper.find(GlModal);
+ const modal = wrapper.findComponent(GlModal);
modal.vm.show = jest.fn();
const error = createError();
@@ -343,7 +343,7 @@ describe('IDE commit form', () => {
await nextTick();
- wrapper.find(GlModal).vm.$emit('ok');
+ wrapper.findComponent(GlModal).vm.$emit('ok');
await waitForPromises();
diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js
index 17568158131..204d39de741 100644
--- a/spec/frontend/ide/components/error_message_spec.js
+++ b/spec/frontend/ide/components/error_message_spec.js
@@ -105,7 +105,7 @@ describe('IDE error message component', () => {
findActionButton().trigger('click');
await nextTick();
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).isVisible()).toBe(true);
resolveAction();
});
@@ -113,7 +113,7 @@ describe('IDE error message component', () => {
findActionButton().trigger('click');
await actionMock();
await nextTick();
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).isVisible()).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/file_templates/dropdown_spec.js b/spec/frontend/ide/components/file_templates/dropdown_spec.js
index e54b322b9db..ee90d87357c 100644
--- a/spec/frontend/ide/components/file_templates/dropdown_spec.js
+++ b/spec/frontend/ide/components/file_templates/dropdown_spec.js
@@ -94,7 +94,7 @@ describe('IDE file templates dropdown component', () => {
it('shows loader when isLoading is true', () => {
createComponent({ props: defaultAsyncProps, state: { isLoading: true } });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('renders templates', () => {
diff --git a/spec/frontend/ide/components/ide_file_row_spec.js b/spec/frontend/ide/components/ide_file_row_spec.js
index baf3d7cca9d..aa66224fa19 100644
--- a/spec/frontend/ide/components/ide_file_row_spec.js
+++ b/spec/frontend/ide/components/ide_file_row_spec.js
@@ -39,8 +39,8 @@ describe('Ide File Row component', () => {
wrapper = null;
});
- const findFileRowExtra = () => wrapper.find(FileRowExtra);
- const findFileRow = () => wrapper.find(FileRow);
+ const findFileRowExtra = () => wrapper.findComponent(FileRowExtra);
+ const findFileRow = () => wrapper.findComponent(FileRow);
const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen');
it('fileRow component has listeners', async () => {
diff --git a/spec/frontend/ide/components/ide_project_header_spec.js b/spec/frontend/ide/components/ide_project_header_spec.js
index fc39651c661..d0636352a3f 100644
--- a/spec/frontend/ide/components/ide_project_header_spec.js
+++ b/spec/frontend/ide/components/ide_project_header_spec.js
@@ -3,6 +3,7 @@ import IDEProjectHeader from '~/ide/components/ide_project_header.vue';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
const mockProject = {
+ id: 1,
name: 'test proj',
avatar_url: 'https://gitlab.com',
path_with_namespace: 'path/with-namespace',
@@ -30,6 +31,7 @@ describe('IDE project header', () => {
it('renders ProjectAvatar with correct props', () => {
expect(findProjectAvatar().props()).toMatchObject({
+ projectId: mockProject.id,
projectName: mockProject.name,
projectAvatarUrl: mockProject.avatar_url,
});
diff --git a/spec/frontend/ide/components/ide_review_spec.js b/spec/frontend/ide/components/ide_review_spec.js
index 13d20761263..0759f957374 100644
--- a/spec/frontend/ide/components/ide_review_spec.js
+++ b/spec/frontend/ide/components/ide_review_spec.js
@@ -42,7 +42,7 @@ describe('IDE review mode', () => {
let inititializeSpy;
beforeEach(async () => {
- inititializeSpy = jest.spyOn(wrapper.find(IdeReview).vm, 'initialize');
+ inititializeSpy = jest.spyOn(wrapper.findComponent(IdeReview).vm, 'initialize');
store.state.viewer = 'editor';
await wrapper.vm.reactivate();
@@ -85,7 +85,7 @@ describe('IDE review mode', () => {
});
it('renders edit dropdown', () => {
- expect(wrapper.find(EditorModeDropdown).exists()).toBe(true);
+ expect(wrapper.findComponent(EditorModeDropdown).exists()).toBe(true);
});
it('renders merge request link & IID', async () => {
diff --git a/spec/frontend/ide/components/ide_side_bar_spec.js b/spec/frontend/ide/components/ide_side_bar_spec.js
index 4469c3fc901..4784d6c516f 100644
--- a/spec/frontend/ide/components/ide_side_bar_spec.js
+++ b/spec/frontend/ide/components/ide_side_bar_spec.js
@@ -47,32 +47,32 @@ describe('IdeSidebar', () => {
await nextTick();
- expect(wrapper.findAll(GlSkeletonLoader)).toHaveLength(3);
+ expect(wrapper.findAllComponents(GlSkeletonLoader)).toHaveLength(3);
});
describe('deferred rendering components', () => {
it('fetches components on demand', async () => {
wrapper = createComponent();
- expect(wrapper.find(IdeTree).exists()).toBe(true);
- expect(wrapper.find(IdeReview).exists()).toBe(false);
- expect(wrapper.find(RepoCommitSection).exists()).toBe(false);
+ expect(wrapper.findComponent(IdeTree).exists()).toBe(true);
+ expect(wrapper.findComponent(IdeReview).exists()).toBe(false);
+ expect(wrapper.findComponent(RepoCommitSection).exists()).toBe(false);
store.state.currentActivityView = leftSidebarViews.review.name;
await waitForPromises();
await nextTick();
- expect(wrapper.find(IdeTree).exists()).toBe(false);
- expect(wrapper.find(IdeReview).exists()).toBe(true);
- expect(wrapper.find(RepoCommitSection).exists()).toBe(false);
+ expect(wrapper.findComponent(IdeTree).exists()).toBe(false);
+ expect(wrapper.findComponent(IdeReview).exists()).toBe(true);
+ expect(wrapper.findComponent(RepoCommitSection).exists()).toBe(false);
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
await nextTick();
- expect(wrapper.find(IdeTree).exists()).toBe(false);
- expect(wrapper.find(IdeReview).exists()).toBe(false);
- expect(wrapper.find(RepoCommitSection).exists()).toBe(true);
+ expect(wrapper.findComponent(IdeTree).exists()).toBe(false);
+ expect(wrapper.findComponent(IdeReview).exists()).toBe(false);
+ expect(wrapper.findComponent(RepoCommitSection).exists()).toBe(true);
});
it.each`
view | tree | review | commit
@@ -86,23 +86,23 @@ describe('IdeSidebar', () => {
await waitForPromises();
await nextTick();
- expect(wrapper.find(IdeTree).exists()).toBe(tree);
- expect(wrapper.find(IdeReview).exists()).toBe(review);
- expect(wrapper.find(RepoCommitSection).exists()).toBe(commit);
+ expect(wrapper.findComponent(IdeTree).exists()).toBe(tree);
+ expect(wrapper.findComponent(IdeReview).exists()).toBe(review);
+ expect(wrapper.findComponent(RepoCommitSection).exists()).toBe(commit);
});
});
it('keeps the current activity view components alive', async () => {
wrapper = createComponent();
- const ideTreeComponent = wrapper.find(IdeTree).element;
+ const ideTreeComponent = wrapper.findComponent(IdeTree).element;
store.state.currentActivityView = leftSidebarViews.commit.name;
await waitForPromises();
await nextTick();
- expect(wrapper.find(IdeTree).exists()).toBe(false);
- expect(wrapper.find(RepoCommitSection).exists()).toBe(true);
+ expect(wrapper.findComponent(IdeTree).exists()).toBe(false);
+ expect(wrapper.findComponent(RepoCommitSection).exists()).toBe(true);
store.state.currentActivityView = leftSidebarViews.edit.name;
@@ -110,6 +110,6 @@ describe('IdeSidebar', () => {
await nextTick();
// reference to the elements remains the same, meaning the components were kept alive
- expect(wrapper.find(IdeTree).element).toEqual(ideTreeComponent);
+ expect(wrapper.findComponent(IdeTree).element).toEqual(ideTreeComponent);
});
});
diff --git a/spec/frontend/ide/components/ide_sidebar_nav_spec.js b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
index 2ea0c250794..80e8aba4072 100644
--- a/spec/frontend/ide/components/ide_sidebar_nav_spec.js
+++ b/spec/frontend/ide/components/ide_sidebar_nav_spec.js
@@ -8,12 +8,12 @@ import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
const TEST_TABS = [
{
title: 'Lorem',
- icon: 'angle-up',
+ icon: 'chevron-lg-up',
views: [{ name: 'lorem-1' }, { name: 'lorem-2' }],
},
{
title: 'Ipsum',
- icon: 'angle-down',
+ icon: 'chevron-lg-down',
views: [{ name: 'ipsum-1' }, { name: 'ipsum-2' }],
},
];
@@ -55,7 +55,7 @@ describe('ide/components/ide_sidebar_nav', () => {
ariaLabel: button.attributes('aria-label'),
classes: button.classes(),
qaSelector: button.attributes('data-qa-selector'),
- icon: button.find(GlIcon).props('name'),
+ icon: button.findComponent(GlIcon).props('name'),
tooltip: getBinding(button.element, 'tooltip').value,
};
});
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index 9172c69b10e..48c670757a2 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -82,7 +82,7 @@ describe('WebIDE', () => {
await waitForPromises();
- expect(wrapper.find(ErrorMessage).exists()).toBe(exists);
+ expect(wrapper.findComponent(ErrorMessage).exists()).toBe(exists);
},
);
});
diff --git a/spec/frontend/ide/components/ide_status_bar_spec.js b/spec/frontend/ide/components/ide_status_bar_spec.js
index 17a5aa17b1f..e6e0ebaf1e8 100644
--- a/spec/frontend/ide/components/ide_status_bar_spec.js
+++ b/spec/frontend/ide/components/ide_status_bar_spec.js
@@ -1,8 +1,8 @@
+import { mount } from '@vue/test-utils';
import _ from 'lodash';
-import Vue, { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
+import IdeStatusMR from '~/ide/components/ide_status_mr.vue';
import { rightSidebarViews } from '~/ide/constants';
import { createStore } from '~/ide/stores';
import { projectData } from '../mock_data';
@@ -13,42 +13,48 @@ const TEST_MERGE_REQUEST_URL = `${TEST_HOST}merge-requests/${TEST_MERGE_REQUEST_
jest.mock('~/lib/utils/poll');
-describe('ideStatusBar', () => {
- let store;
- let vm;
+describe('IdeStatusBar component', () => {
+ let wrapper;
+
+ const findMRStatus = () => wrapper.findComponent(IdeStatusMR);
+
+ const mountComponent = (state = {}) => {
+ const store = createStore();
+ store.replaceState({
+ ...store.state,
+ currentBranchId: 'main',
+ currentProjectId: TEST_PROJECT_ID,
+ projects: {
+ ...store.state.projects,
+ [TEST_PROJECT_ID]: _.clone(projectData),
+ },
+ ...state,
+ });
- const createComponent = () => {
- vm = createComponentWithStore(Vue.extend(IdeStatusBar), store).$mount();
+ wrapper = mount(IdeStatusBar, { store });
};
- const findMRStatus = () => vm.$el.querySelector('.js-ide-status-mr');
-
- beforeEach(() => {
- store = createStore();
- store.state.currentProjectId = TEST_PROJECT_ID;
- store.state.projects[TEST_PROJECT_ID] = _.clone(projectData);
- store.state.currentBranchId = 'main';
- });
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('default', () => {
- beforeEach(() => {
- createComponent();
- });
-
it('triggers a setInterval', () => {
- expect(vm.intervalId).not.toBe(null);
+ mountComponent();
+
+ expect(wrapper.vm.intervalId).not.toBe(null);
});
it('renders the statusbar', () => {
- expect(vm.$el.className).toBe('ide-status-bar');
+ mountComponent();
+
+ expect(wrapper.classes()).toEqual(['ide-status-bar']);
});
describe('commitAgeUpdate', () => {
beforeEach(() => {
- jest.spyOn(vm, 'commitAgeUpdate').mockImplementation(() => {});
+ mountComponent();
+ jest.spyOn(wrapper.vm, 'commitAgeUpdate').mockImplementation(() => {});
});
afterEach(() => {
@@ -56,70 +62,82 @@ describe('ideStatusBar', () => {
});
it('gets called every second', () => {
- expect(vm.commitAgeUpdate).not.toHaveBeenCalled();
+ expect(wrapper.vm.commitAgeUpdate).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
- expect(vm.commitAgeUpdate.mock.calls.length).toEqual(1);
+ expect(wrapper.vm.commitAgeUpdate.mock.calls).toHaveLength(1);
jest.advanceTimersByTime(1000);
- expect(vm.commitAgeUpdate.mock.calls.length).toEqual(2);
+ expect(wrapper.vm.commitAgeUpdate.mock.calls).toHaveLength(2);
});
});
describe('getCommitPath', () => {
it('returns the path to the commit details', () => {
- expect(vm.getCommitPath('abc123de')).toBe('/commit/abc123de');
+ mountComponent();
+
+ expect(wrapper.vm.getCommitPath('abc123de')).toBe('/commit/abc123de');
});
});
describe('pipeline status', () => {
- it('opens right sidebar on clicking icon', async () => {
- jest.spyOn(vm, 'openRightPane').mockImplementation(() => {});
- Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
- details: {
- status: {
- text: 'success',
- details_path: 'test',
- icon: 'status_success',
+ it('opens right sidebar on clicking icon', () => {
+ const pipelines = {
+ latestPipeline: {
+ details: {
+ status: {
+ text: 'success',
+ details_path: 'test',
+ icon: 'status_success',
+ },
+ },
+ commit: {
+ author_gravatar_url: 'www',
},
},
- commit: {
- author_gravatar_url: 'www',
- },
- });
+ };
+ mountComponent({ pipelines });
+ jest.spyOn(wrapper.vm, 'openRightPane').mockImplementation(() => {});
- await nextTick();
- vm.$el.querySelector('.ide-status-pipeline button').click();
+ wrapper.find('button').trigger('click');
- expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
+ expect(wrapper.vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
});
});
it('does not show merge request status', () => {
- expect(findMRStatus()).toBe(null);
+ mountComponent();
+
+ expect(findMRStatus().exists()).toBe(false);
});
});
describe('with merge request in store', () => {
beforeEach(() => {
- store.state.projects[TEST_PROJECT_ID].mergeRequests = {
- [TEST_MERGE_REQUEST_ID]: {
- web_url: TEST_MERGE_REQUEST_URL,
- references: {
- short: `!${TEST_MERGE_REQUEST_ID}`,
+ const state = {
+ currentMergeRequestId: TEST_MERGE_REQUEST_ID,
+ projects: {
+ [TEST_PROJECT_ID]: {
+ ..._.clone(projectData),
+ mergeRequests: {
+ [TEST_MERGE_REQUEST_ID]: {
+ web_url: TEST_MERGE_REQUEST_URL,
+ references: {
+ short: `!${TEST_MERGE_REQUEST_ID}`,
+ },
+ },
+ },
},
},
};
- store.state.currentMergeRequestId = TEST_MERGE_REQUEST_ID;
-
- createComponent();
+ mountComponent(state);
});
it('shows merge request status', () => {
- expect(findMRStatus().textContent.trim()).toEqual(`Merge request !${TEST_MERGE_REQUEST_ID}`);
- expect(findMRStatus().querySelector('a').href).toEqual(TEST_MERGE_REQUEST_URL);
+ expect(findMRStatus().text()).toBe(`Merge request !${TEST_MERGE_REQUEST_ID}`);
+ expect(findMRStatus().find('a').attributes('href')).toBe(TEST_MERGE_REQUEST_URL);
});
});
});
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index 371fbc6becd..0b54e8b6afb 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -25,7 +25,7 @@ describe('ide/components/ide_status_list', () => {
let store;
let wrapper;
- const findLink = () => wrapper.find(GlLink);
+ const findLink = () => wrapper.findComponent(GlLink);
const createComponent = (options = {}) => {
store = new Vuex.Store({
getters: {
@@ -98,6 +98,6 @@ describe('ide/components/ide_status_list', () => {
it('renders terminal sync status', () => {
createComponent();
- expect(wrapper.find(TerminalSyncStatusSafe).exists()).toBe(true);
+ expect(wrapper.findComponent(TerminalSyncStatusSafe).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/ide_status_mr_spec.js b/spec/frontend/ide/components/ide_status_mr_spec.js
index 0526d4653f8..0b9111c0e2a 100644
--- a/spec/frontend/ide/components/ide_status_mr_spec.js
+++ b/spec/frontend/ide/components/ide_status_mr_spec.js
@@ -14,8 +14,8 @@ describe('ide/components/ide_status_mr', () => {
propsData: props,
});
};
- const findIcon = () => wrapper.find(GlIcon);
- const findLink = () => wrapper.find(GlLink);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findLink = () => wrapper.findComponent(GlLink);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/ide/components/ide_tree_spec.js b/spec/frontend/ide/components/ide_tree_spec.js
index 8465ef9f5f3..f00017a2736 100644
--- a/spec/frontend/ide/components/ide_tree_spec.js
+++ b/spec/frontend/ide/components/ide_tree_spec.js
@@ -41,7 +41,7 @@ describe('IdeTree', () => {
let inititializeSpy;
beforeEach(async () => {
- inititializeSpy = jest.spyOn(wrapper.find(IdeTree).vm, 'initialize');
+ inititializeSpy = jest.spyOn(wrapper.findComponent(IdeTree).vm, 'initialize');
store.state.viewer = 'diff';
await wrapper.vm.reactivate();
diff --git a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
index d632a34266a..5eb66f75978 100644
--- a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
@@ -27,7 +27,7 @@ describe('IDE job log scroll button', () => {
beforeEach(() => createComponent({ direction }));
it('returns proper icon name', () => {
- expect(wrapper.find(GlIcon).props('name')).toBe(icon);
+ expect(wrapper.findComponent(GlIcon).props('name')).toBe(icon);
});
it('returns proper title', () => {
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js
index cb2c9f8f04f..b4c7eb51781 100644
--- a/spec/frontend/ide/components/jobs/list_spec.js
+++ b/spec/frontend/ide/components/jobs/list_spec.js
@@ -58,29 +58,29 @@ describe('IDE stages list', () => {
it('renders loading icon when no stages & loading', () => {
createComponent({ loading: true, stages: [] });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('renders stages components for each stage', () => {
createComponent({ stages });
- expect(wrapper.findAll(Stage).length).toBe(stages.length);
+ expect(wrapper.findAllComponents(Stage).length).toBe(stages.length);
});
it('triggers fetchJobs action when stage emits fetch event', () => {
createComponent({ stages });
- wrapper.find(Stage).vm.$emit('fetch');
+ wrapper.findComponent(Stage).vm.$emit('fetch');
expect(storeActions.fetchJobs).toHaveBeenCalled();
});
it('triggers toggleStageCollapsed action when stage emits toggleCollapsed event', () => {
createComponent({ stages });
- wrapper.find(Stage).vm.$emit('toggleCollapsed');
+ wrapper.findComponent(Stage).vm.$emit('toggleCollapsed');
expect(storeActions.toggleStageCollapsed).toHaveBeenCalled();
});
it('triggers setDetailJob action when stage emits clickViewLog event', () => {
createComponent({ stages });
- wrapper.find(Stage).vm.$emit('clickViewLog');
+ wrapper.findComponent(Stage).vm.$emit('clickViewLog');
expect(storeActions.setDetailJob).toHaveBeenCalled();
});
diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js
index f158c59cd32..1d5e5743a4d 100644
--- a/spec/frontend/ide/components/jobs/stage_spec.js
+++ b/spec/frontend/ide/components/jobs/stage_spec.js
@@ -18,8 +18,8 @@ describe('IDE pipeline stage', () => {
},
};
- const findHeader = () => wrapper.find({ ref: 'cardHeader' });
- const findJobList = () => wrapper.find({ ref: 'jobList' });
+ const findHeader = () => wrapper.findComponent({ ref: 'cardHeader' });
+ const findJobList = () => wrapper.findComponent({ ref: 'jobList' });
const createComponent = (props) => {
wrapper = shallowMount(Stage, {
@@ -45,7 +45,7 @@ describe('IDE pipeline stage', () => {
stage: { ...defaultProps.stage, isLoading: true, jobs: [] },
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('emits toggleCollaped event with stage id when clicking header', async () => {
@@ -60,7 +60,7 @@ describe('IDE pipeline stage', () => {
it('emits clickViewLog entity with job', async () => {
const [job] = defaultProps.stage.jobs;
createComponent();
- wrapper.findAll(Item).at(0).vm.$emit('clickViewLog', job);
+ wrapper.findAllComponents(Item).at(0).vm.$emit('clickViewLog', job);
await nextTick();
expect(wrapper.emitted().clickViewLog[0][0]).toBe(job);
});
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index 583671a0af6..ea6e2741a85 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -14,7 +14,7 @@ describe('IDE merge requests list', () => {
let fetchMergeRequestsMock;
const findSearchTypeButtons = () => wrapper.findAll('button');
- const findTokenedInput = () => wrapper.find(TokenedInput);
+ const findTokenedInput = () => wrapper.findComponent(TokenedInput);
const createComponent = (state = {}) => {
const { mergeRequests = {}, ...restOfState } = state;
@@ -63,7 +63,7 @@ describe('IDE merge requests list', () => {
it('renders loading icon when merge request is loading', () => {
createComponent({ mergeRequests: { isLoading: true } });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('renders no search results text when search is not empty', async () => {
@@ -107,8 +107,8 @@ describe('IDE merge requests list', () => {
it('renders list', () => {
createComponent(defaultStateWithMergeRequests);
- expect(wrapper.findAll(Item).length).toBe(1);
- expect(wrapper.find(Item).props('item')).toBe(
+ expect(wrapper.findAllComponents(Item).length).toBe(1);
+ expect(wrapper.findComponent(Item).props('item')).toBe(
defaultStateWithMergeRequests.mergeRequests.mergeRequests[0],
);
});
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index 19dcd9569b3..747c099db33 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -1,70 +1,66 @@
-import Vue, { nextTick } from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
-import newDropdown from '~/ide/components/new_dropdown/index.vue';
+import { mount } from '@vue/test-utils';
+import NewDropdown from '~/ide/components/new_dropdown/index.vue';
+import Button from '~/ide/components/new_dropdown/button.vue';
import { createStore } from '~/ide/stores';
describe('new dropdown component', () => {
- let store;
- let vm;
-
- beforeEach(() => {
- store = createStore();
-
- const component = Vue.extend(newDropdown);
-
- vm = createComponentWithStore(component, store, {
- branch: 'main',
- path: '',
- mouseOver: false,
- type: 'tree',
+ let wrapper;
+
+ const findAllButtons = () => wrapper.findAllComponents(Button);
+
+ const mountComponent = () => {
+ const store = createStore();
+ store.state.currentProjectId = 'abcproject';
+ store.state.path = '';
+ store.state.trees['abcproject/mybranch'] = { tree: [] };
+
+ wrapper = mount(NewDropdown, {
+ store,
+ propsData: {
+ branch: 'main',
+ path: '',
+ mouseOver: false,
+ type: 'tree',
+ },
});
+ };
- vm.$store.state.currentProjectId = 'abcproject';
- vm.$store.state.path = '';
- vm.$store.state.trees['abcproject/mybranch'] = {
- tree: [],
- };
-
- vm.$mount();
-
- jest.spyOn(vm.$refs.newModal, 'open').mockImplementation(() => {});
+ beforeEach(() => {
+ mountComponent();
+ jest.spyOn(wrapper.vm.$refs.newModal, 'open').mockImplementation(() => {});
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders new file, upload and new directory links', () => {
- const buttons = vm.$el.querySelectorAll('.dropdown-menu button');
-
- expect(buttons[0].textContent.trim()).toBe('New file');
- expect(buttons[1].textContent.trim()).toBe('Upload file');
- expect(buttons[2].textContent.trim()).toBe('New directory');
+ expect(findAllButtons().at(0).text()).toBe('New file');
+ expect(findAllButtons().at(1).text()).toBe('Upload file');
+ expect(findAllButtons().at(2).text()).toBe('New directory');
});
describe('createNewItem', () => {
it('opens modal for a blob when new file is clicked', () => {
- vm.$el.querySelectorAll('.dropdown-menu button')[0].click();
+ findAllButtons().at(0).trigger('click');
- expect(vm.$refs.newModal.open).toHaveBeenCalledWith('blob', '');
+ expect(wrapper.vm.$refs.newModal.open).toHaveBeenCalledWith('blob', '');
});
it('opens modal for a tree when new directory is clicked', () => {
- vm.$el.querySelectorAll('.dropdown-menu button')[2].click();
+ findAllButtons().at(2).trigger('click');
- expect(vm.$refs.newModal.open).toHaveBeenCalledWith('tree', '');
+ expect(wrapper.vm.$refs.newModal.open).toHaveBeenCalledWith('tree', '');
});
});
describe('isOpen', () => {
it('scrolls dropdown into view', async () => {
- jest.spyOn(vm.$refs.dropdownMenu, 'scrollIntoView').mockImplementation(() => {});
-
- vm.isOpen = true;
+ jest.spyOn(wrapper.vm.$refs.dropdownMenu, 'scrollIntoView').mockImplementation(() => {});
- await nextTick();
+ await wrapper.setProps({ isOpen: true });
- expect(vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
+ expect(wrapper.vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({
block: 'nearest',
});
});
@@ -72,11 +68,11 @@ describe('new dropdown component', () => {
describe('delete entry', () => {
it('calls delete action', () => {
- jest.spyOn(vm, 'deleteEntry').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'deleteEntry').mockImplementation(() => {});
- vm.$el.querySelectorAll('.dropdown-menu button')[4].click();
+ findAllButtons().at(4).trigger('click');
- expect(vm.deleteEntry).toHaveBeenCalledWith('');
+ expect(wrapper.vm.deleteEntry).toHaveBeenCalledWith('');
});
});
});
diff --git a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
index 7f2ee0fe7d9..1d38231a767 100644
--- a/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
+++ b/spec/frontend/ide/components/panes/collapsible_sidebar_spec.js
@@ -27,7 +27,7 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
});
};
- const findSidebarNav = () => wrapper.find(IdeSidebarNav);
+ const findSidebarNav = () => wrapper.findComponent(IdeSidebarNav);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/ide/components/panes/right_spec.js b/spec/frontend/ide/components/panes/right_spec.js
index d12acd6dc4c..4555f519bc2 100644
--- a/spec/frontend/ide/components/panes/right_spec.js
+++ b/spec/frontend/ide/components/panes/right_spec.js
@@ -37,7 +37,7 @@ describe('ide/components/panes/right.vue', () => {
it('is always shown', () => {
createComponent();
- expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
+ expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
@@ -65,7 +65,7 @@ describe('ide/components/panes/right.vue', () => {
createComponent();
- expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
+ expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
@@ -90,7 +90,7 @@ describe('ide/components/panes/right.vue', () => {
store.state.terminal.isVisible = true;
await nextTick();
- expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
+ expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: true,
@@ -103,7 +103,7 @@ describe('ide/components/panes/right.vue', () => {
it('hides terminal tab when not visible', () => {
store.state.terminal.isVisible = false;
- expect(wrapper.find(CollapsibleSidebar).props('extensionTabs')).toEqual(
+ expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: false,
diff --git a/spec/frontend/ide/components/pipelines/empty_state_spec.js b/spec/frontend/ide/components/pipelines/empty_state_spec.js
index f7409fc36be..31081e8f9d5 100644
--- a/spec/frontend/ide/components/pipelines/empty_state_spec.js
+++ b/spec/frontend/ide/components/pipelines/empty_state_spec.js
@@ -32,7 +32,7 @@ describe('~/ide/components/pipelines/empty_state.vue', () => {
});
it('renders empty state', () => {
- expect(wrapper.find(GlEmptyState).props()).toMatchObject({
+ expect(wrapper.findComponent(GlEmptyState).props()).toMatchObject({
title: EmptyState.i18n.title,
description: EmptyState.i18n.description,
primaryButtonText: EmptyState.i18n.primaryButtonText,
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index 8a3606e27eb..545924c9c11 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -99,7 +99,7 @@ describe('IDE pipelines list', () => {
},
);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('renders loading state', () => {
@@ -111,7 +111,7 @@ describe('IDE pipelines list', () => {
},
);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -128,7 +128,7 @@ describe('IDE pipelines list', () => {
it('renders empty state when no latestPipeline', () => {
createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null });
- expect(wrapper.find(EmptyState).exists()).toBe(true);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot();
});
@@ -144,7 +144,7 @@ describe('IDE pipelines list', () => {
it('renders ci icon', () => {
createComponent({}, withLatestPipelineState);
- expect(wrapper.find(CiIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(CiIcon).exists()).toBe(true);
});
it('renders pipeline data', () => {
@@ -158,7 +158,7 @@ describe('IDE pipelines list', () => {
const isLoadingJobs = true;
createComponent({}, { ...withLatestPipelineState, stages, isLoadingJobs });
- const jobProps = wrapper.findAll(GlTab).at(0).find(JobsList).props();
+ const jobProps = wrapper.findAllComponents(GlTab).at(0).findComponent(JobsList).props();
expect(jobProps.stages).toBe(stages);
expect(jobProps.loading).toBe(isLoadingJobs);
});
@@ -169,7 +169,7 @@ describe('IDE pipelines list', () => {
const isLoadingJobs = true;
createComponent({}, { ...withLatestPipelineState, isLoadingJobs });
- const jobProps = wrapper.findAll(GlTab).at(1).find(JobsList).props();
+ const jobProps = wrapper.findAllComponents(GlTab).at(1).findComponent(JobsList).props();
expect(jobProps.stages).toBe(failedStages);
expect(jobProps.loading).toBe(isLoadingJobs);
});
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index 426fbd5c04c..cf768114e70 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -396,7 +396,7 @@ describe('IDE clientside preview', () => {
wrapper.setData({ loading: true });
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/preview/navigator_spec.js b/spec/frontend/ide/components/preview/navigator_spec.js
index a199f4704f7..9c4f825ccf5 100644
--- a/spec/frontend/ide/components/preview/navigator_spec.js
+++ b/spec/frontend/ide/components/preview/navigator_spec.js
@@ -37,13 +37,13 @@ describe('IDE clientside preview navigator', () => {
});
it('renders loading icon by default', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('removes loading icon when done event is fired', async () => {
listenHandler({ type: 'done' });
await nextTick();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
it('does not count visiting same url multiple times', async () => {
diff --git a/spec/frontend/ide/components/repo_commit_section_spec.js b/spec/frontend/ide/components/repo_commit_section_spec.js
index db4181395d3..d3312358402 100644
--- a/spec/frontend/ide/components/repo_commit_section_spec.js
+++ b/spec/frontend/ide/components/repo_commit_section_spec.js
@@ -77,8 +77,10 @@ describe('RepoCommitSection', () => {
});
it('renders no changes text', () => {
- expect(wrapper.find(EmptyState).text().trim()).toContain('No changes');
- expect(wrapper.find(EmptyState).find('img').attributes('src')).toBe(TEST_NO_CHANGES_SVG);
+ expect(wrapper.findComponent(EmptyState).text().trim()).toContain('No changes');
+ expect(wrapper.findComponent(EmptyState).find('img').attributes('src')).toBe(
+ TEST_NO_CHANGES_SVG,
+ );
});
});
@@ -111,7 +113,7 @@ describe('RepoCommitSection', () => {
});
it('does not show empty state', () => {
- expect(wrapper.find(EmptyState).exists()).toBe(false);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(false);
});
});
@@ -157,7 +159,7 @@ describe('RepoCommitSection', () => {
});
it('does not show empty state', () => {
- expect(wrapper.find(EmptyState).exists()).toBe(false);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(false);
});
});
@@ -167,7 +169,7 @@ describe('RepoCommitSection', () => {
beforeEach(async () => {
createComponent();
- inititializeSpy = jest.spyOn(wrapper.find(RepoCommitSection).vm, 'initialize');
+ inititializeSpy = jest.spyOn(wrapper.findComponent(RepoCommitSection).vm, 'initialize');
store.state.viewer = 'diff';
await wrapper.vm.reactivate();
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index 7a0bcda1b7a..9921d8cba18 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -145,8 +145,7 @@ describe('RepoEditor', () => {
jest.clearAllMocks();
// create a new model each time, otherwise tests conflict with each other
// because of same model being used in multiple tests
- // eslint-disable-next-line no-undef
- monaco.editor.getModels().forEach((model) => model.dispose());
+ monacoEditor.getModels().forEach((model) => model.dispose());
wrapper.destroy();
wrapper = null;
});
@@ -212,7 +211,7 @@ describe('RepoEditor', () => {
it('renders markdown for tempFile', async () => {
findPreviewTab().vm.$emit('click');
await waitForPromises();
- expect(wrapper.find(ContentViewer).html()).toContain(dummyFile.text.content);
+ expect(wrapper.findComponent(ContentViewer).html()).toContain(dummyFile.text.content);
});
describe('when file changes to non-markdown file', () => {
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index b16fd8f80ba..b26edc5a85b 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -19,7 +19,7 @@ describe('RepoTab', () => {
let store;
let router;
- const findTab = () => wrapper.find(GlTabStub);
+ const findTab = () => wrapper.findComponent(GlTabStub);
function createComponent(propsData) {
wrapper = mount(RepoTab, {
@@ -164,7 +164,7 @@ describe('RepoTab', () => {
await wrapper.find('.multi-file-tab-close').trigger('click');
- expect(tab.opened).toBeFalsy();
+ expect(tab.opened).toBe(false);
expect(wrapper.vm.$store.state.changedFiles).toHaveLength(1);
});
@@ -180,7 +180,7 @@ describe('RepoTab', () => {
await wrapper.find('.multi-file-tab-close').trigger('click');
- expect(tab.opened).toBeFalsy();
+ expect(tab.opened).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/resizable_panel_spec.js b/spec/frontend/ide/components/resizable_panel_spec.js
index 55b9423aba8..fe2a128c9c8 100644
--- a/spec/frontend/ide/components/resizable_panel_spec.js
+++ b/spec/frontend/ide/components/resizable_panel_spec.js
@@ -35,7 +35,7 @@ describe('~/ide/components/resizable_panel', () => {
store,
});
};
- const findResizer = () => wrapper.find(PanelResizer);
+ const findResizer = () => wrapper.findComponent(PanelResizer);
const findInlineStyle = () => wrapper.element.style.cssText;
const createInlineStyle = (width) => `width: ${width}px;`;
diff --git a/spec/frontend/ide/components/shared/commit_message_field_spec.js b/spec/frontend/ide/components/shared/commit_message_field_spec.js
index f4f9b95b233..94da06f4cb2 100644
--- a/spec/frontend/ide/components/shared/commit_message_field_spec.js
+++ b/spec/frontend/ide/components/shared/commit_message_field_spec.js
@@ -79,7 +79,7 @@ describe('CommitMessageField', () => {
await fillText(text);
expect(findHighlightsText().text()).toEqual(text);
- expect(findHighlightsMark().text()).toBeFalsy();
+ expect(findHighlightsMark().text()).toBe('');
});
it('highlights characters over 50 length', async () => {
diff --git a/spec/frontend/ide/components/terminal/empty_state_spec.js b/spec/frontend/ide/components/terminal/empty_state_spec.js
index 57c816747aa..15fb0fe9013 100644
--- a/spec/frontend/ide/components/terminal/empty_state_spec.js
+++ b/spec/frontend/ide/components/terminal/empty_state_spec.js
@@ -46,7 +46,7 @@ describe('IDE TerminalEmptyState', () => {
},
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('when not loading, does not show loading icon', () => {
@@ -56,7 +56,7 @@ describe('IDE TerminalEmptyState', () => {
},
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
describe('when valid', () => {
@@ -71,7 +71,7 @@ describe('IDE TerminalEmptyState', () => {
},
});
- button = wrapper.find(GlButton);
+ button = wrapper.findComponent(GlButton);
});
it('shows button', () => {
@@ -100,7 +100,7 @@ describe('IDE TerminalEmptyState', () => {
},
});
- expect(wrapper.find(GlButton).props('disabled')).toBe(true);
- expect(wrapper.find(GlAlert).html()).toContain(TEST_HTML_MESSAGE);
+ expect(wrapper.findComponent(GlButton).props('disabled')).toBe(true);
+ expect(wrapper.findComponent(GlAlert).html()).toContain(TEST_HTML_MESSAGE);
});
});
diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js
index 6a70ddb46a8..7e4a56b0610 100644
--- a/spec/frontend/ide/components/terminal/session_spec.js
+++ b/spec/frontend/ide/components/terminal/session_spec.js
@@ -38,7 +38,7 @@ describe('IDE TerminalSession', () => {
});
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
state = {
@@ -60,7 +60,7 @@ describe('IDE TerminalSession', () => {
it('shows terminal', () => {
factory();
- expect(wrapper.find(Terminal).props()).toEqual({
+ expect(wrapper.findComponent(Terminal).props()).toEqual({
terminalPath: TEST_TERMINAL_PATH,
status: RUNNING,
});
diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
index 71ec0dca89d..c18934f0f3b 100644
--- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
@@ -12,7 +12,7 @@ describe('IDE TerminalControls', () => {
...options,
});
- buttons = wrapper.findAll(ScrollButton);
+ buttons = wrapper.findAllComponents(ScrollButton);
};
it('shows an up and down scroll button', () => {
diff --git a/spec/frontend/ide/components/terminal/terminal_spec.js b/spec/frontend/ide/components/terminal/terminal_spec.js
index afc49e22c83..4da3e1910e9 100644
--- a/spec/frontend/ide/components/terminal/terminal_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_spec.js
@@ -68,7 +68,7 @@ describe('IDE Terminal', () => {
it(`shows when starting (${status})`, () => {
factory({ status });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find('.top-bar').text()).toBe('Starting...');
});
});
@@ -76,7 +76,7 @@ describe('IDE Terminal', () => {
it(`shows when stopping`, () => {
factory({ status: STOPPING });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
expect(wrapper.find('.top-bar').text()).toBe('Stopping...');
});
@@ -84,7 +84,7 @@ describe('IDE Terminal', () => {
it('hides when not loading', () => {
factory({ status });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find('.top-bar').text()).toBe('');
});
});
@@ -107,23 +107,23 @@ describe('IDE Terminal', () => {
});
it('is visible if terminal is created', () => {
- expect(wrapper.find(TerminalControls).exists()).toBe(true);
+ expect(wrapper.findComponent(TerminalControls).exists()).toBe(true);
});
it('scrolls glterminal on scroll-up', () => {
- wrapper.find(TerminalControls).vm.$emit('scroll-up');
+ wrapper.findComponent(TerminalControls).vm.$emit('scroll-up');
expect(wrapper.vm.glterminal.scrollToTop).toHaveBeenCalled();
});
it('scrolls glterminal on scroll-down', () => {
- wrapper.find(TerminalControls).vm.$emit('scroll-down');
+ wrapper.findComponent(TerminalControls).vm.$emit('scroll-down');
expect(wrapper.vm.glterminal.scrollToBottom).toHaveBeenCalled();
});
it('has props set', () => {
- expect(wrapper.find(TerminalControls).props()).toEqual({
+ expect(wrapper.findComponent(TerminalControls).props()).toEqual({
canScrollUp: false,
canScrollDown: false,
});
@@ -133,7 +133,7 @@ describe('IDE Terminal', () => {
wrapper.setData({ canScrollUp: true, canScrollDown: true });
return nextTick().then(() => {
- expect(wrapper.find(TerminalControls).props()).toEqual({
+ expect(wrapper.findComponent(TerminalControls).props()).toEqual({
canScrollUp: true,
canScrollDown: true,
});
diff --git a/spec/frontend/ide/components/terminal/view_spec.js b/spec/frontend/ide/components/terminal/view_spec.js
index 49f9513d2ac..57c8da9f5b7 100644
--- a/spec/frontend/ide/components/terminal/view_spec.js
+++ b/spec/frontend/ide/components/terminal/view_spec.js
@@ -66,7 +66,7 @@ describe('IDE TerminalView', () => {
it('renders empty state', async () => {
await factory();
- expect(wrapper.find(TerminalEmptyState).props()).toEqual({
+ expect(wrapper.findComponent(TerminalEmptyState).props()).toEqual({
helpPath: TEST_HELP_PATH,
illustrationPath: TEST_SVG_PATH,
...getters.allCheck(),
@@ -79,7 +79,7 @@ describe('IDE TerminalView', () => {
expect(actions.startSession).not.toHaveBeenCalled();
expect(actions.hideSplash).not.toHaveBeenCalled();
- wrapper.find(TerminalEmptyState).vm.$emit('start');
+ wrapper.findComponent(TerminalEmptyState).vm.$emit('start');
expect(actions.startSession).toHaveBeenCalled();
expect(actions.hideSplash).toHaveBeenCalled();
@@ -89,7 +89,7 @@ describe('IDE TerminalView', () => {
state.isShowSplash = false;
await factory();
- expect(wrapper.find(TerminalEmptyState).exists()).toBe(false);
- expect(wrapper.find(TerminalSession).exists()).toBe(true);
+ expect(wrapper.findComponent(TerminalEmptyState).exists()).toBe(false);
+ expect(wrapper.findComponent(TerminalSession).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
index f921037d744..5b1502cc190 100644
--- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
+++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_safe_spec.js
@@ -34,13 +34,13 @@ describe('ide/components/terminal_sync/terminal_sync_status_safe', () => {
});
it('renders terminal sync status', () => {
- expect(wrapper.find(TerminalSyncStatus).exists()).toBe(true);
+ expect(wrapper.findComponent(TerminalSyncStatus).exists()).toBe(true);
});
});
describe('without terminal sync module', () => {
it('does not render terminal sync status', () => {
- expect(wrapper.find(TerminalSyncStatus).exists()).toBe(false);
+ expect(wrapper.findComponent(TerminalSyncStatus).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
index 3a326b08fff..147235abc8e 100644
--- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
+++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
@@ -78,19 +78,19 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
if (!icon) {
it('does not render icon', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(false);
});
it('renders loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
} else {
it('renders icon', () => {
- expect(wrapper.find(GlIcon).props('name')).toEqual(icon);
+ expect(wrapper.findComponent(GlIcon).props('name')).toEqual(icon);
});
it('does not render loading icon', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
});
}
});
diff --git a/spec/frontend/ide/lib/common/model_manager_spec.js b/spec/frontend/ide/lib/common/model_manager_spec.js
index 08e4ab0f113..e485873e8da 100644
--- a/spec/frontend/ide/lib/common/model_manager_spec.js
+++ b/spec/frontend/ide/lib/common/model_manager_spec.js
@@ -59,7 +59,7 @@ describe('Multi-file editor library model manager', () => {
describe('hasCachedModel', () => {
it('returns false when no models exist', () => {
- expect(instance.hasCachedModel('path')).toBeFalsy();
+ expect(instance.hasCachedModel('path')).toBe(false);
});
it('returns true when model exists', () => {
@@ -67,7 +67,7 @@ describe('Multi-file editor library model manager', () => {
instance.addModel(f);
- expect(instance.hasCachedModel(f.key)).toBeTruthy();
+ expect(instance.hasCachedModel(f.key)).toBe(true);
});
});
diff --git a/spec/frontend/ide/lib/diff/diff_spec.js b/spec/frontend/ide/lib/diff/diff_spec.js
index 901f9e7cfd1..208ed9bf759 100644
--- a/spec/frontend/ide/lib/diff/diff_spec.js
+++ b/spec/frontend/ide/lib/diff/diff_spec.js
@@ -18,8 +18,8 @@ describe('Multi-file editor library diff calculator', () => {
({ originalContent, newContent, lineNumber }) => {
const diff = computeDiff(originalContent, newContent)[0];
- expect(diff.added).toBeTruthy();
- expect(diff.modified).toBeTruthy();
+ expect(diff.added).toBe(true);
+ expect(diff.modified).toBe(true);
expect(diff.removed).toBeUndefined();
expect(diff.lineNumber).toBe(lineNumber);
},
@@ -36,7 +36,7 @@ describe('Multi-file editor library diff calculator', () => {
({ originalContent, newContent, lineNumber }) => {
const diff = computeDiff(originalContent, newContent)[0];
- expect(diff.added).toBeTruthy();
+ expect(diff.added).toBe(true);
expect(diff.modified).toBeUndefined();
expect(diff.removed).toBeUndefined();
expect(diff.lineNumber).toBe(lineNumber);
@@ -56,7 +56,7 @@ describe('Multi-file editor library diff calculator', () => {
expect(diff.added).toBeUndefined();
expect(diff.modified).toBe(modified);
- expect(diff.removed).toBeTruthy();
+ expect(diff.removed).toBe(true);
expect(diff.lineNumber).toBe(lineNumber);
},
);
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 6c1dee1e5ca..d1c31cd412b 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -60,8 +60,8 @@ describe('IDE store file actions', () => {
it('closes open files', () => {
return store.dispatch('closeFile', localFile).then(() => {
- expect(localFile.opened).toBeFalsy();
- expect(localFile.active).toBeFalsy();
+ expect(localFile.opened).toBe(false);
+ expect(localFile.active).toBe(false);
expect(store.state.openFiles.length).toBe(0);
});
});
@@ -269,7 +269,7 @@ describe('IDE store file actions', () => {
it('sets the file as active', () => {
return store.dispatch('getFileData', { path: localFile.path }).then(() => {
- expect(localFile.active).toBeTruthy();
+ expect(localFile.active).toBe(true);
});
});
@@ -277,7 +277,7 @@ describe('IDE store file actions', () => {
return store
.dispatch('getFileData', { path: localFile.path, makeFileActive: false })
.then(() => {
- expect(localFile.active).toBeFalsy();
+ expect(localFile.active).toBe(false);
});
});
diff --git a/spec/frontend/ide/stores/actions/tree_spec.js b/spec/frontend/ide/stores/actions/tree_spec.js
index d43393875eb..6e8a03b47ad 100644
--- a/spec/frontend/ide/stores/actions/tree_spec.js
+++ b/spec/frontend/ide/stores/actions/tree_spec.js
@@ -134,7 +134,7 @@ describe('Multi-file store tree actions', () => {
it('toggles the tree open', async () => {
await store.dispatch('toggleTreeOpen', tree.path);
- expect(tree.opened).toBeTruthy();
+ expect(tree.opened).toBe(true);
});
});
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index 53d161ae5c9..24661e21cd0 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -268,7 +268,7 @@ describe('IDE store getters', () => {
currentProject: undefined,
};
- expect(getters.isOnDefaultBranch({}, localGetters)).toBeFalsy();
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBe(undefined);
});
it("returns true when project's default branch matches current branch", () => {
@@ -279,7 +279,7 @@ describe('IDE store getters', () => {
branchName: 'main',
};
- expect(getters.isOnDefaultBranch({}, localGetters)).toBeTruthy();
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBe(true);
});
it("returns false when project's default branch doesn't match current branch", () => {
@@ -290,7 +290,7 @@ describe('IDE store getters', () => {
branchName: 'feature',
};
- expect(getters.isOnDefaultBranch({}, localGetters)).toBeFalsy();
+ expect(getters.isOnDefaultBranch({}, localGetters)).toBe(false);
});
});
diff --git a/spec/frontend/ide/stores/modules/commit/getters_spec.js b/spec/frontend/ide/stores/modules/commit/getters_spec.js
index 1e34087b290..38ebe36c2c5 100644
--- a/spec/frontend/ide/stores/modules/commit/getters_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/getters_spec.js
@@ -14,21 +14,21 @@ describe('IDE commit module getters', () => {
describe('discardDraftButtonDisabled', () => {
it('returns true when commitMessage is empty', () => {
- expect(getters.discardDraftButtonDisabled(state)).toBeTruthy();
+ expect(getters.discardDraftButtonDisabled(state)).toBe(true);
});
it('returns false when commitMessage is not empty & loading is false', () => {
state.commitMessage = 'test';
state.submitCommitLoading = false;
- expect(getters.discardDraftButtonDisabled(state)).toBeFalsy();
+ expect(getters.discardDraftButtonDisabled(state)).toBe(false);
});
it('returns true when commitMessage is not empty & loading is true', () => {
state.commitMessage = 'test';
state.submitCommitLoading = true;
- expect(getters.discardDraftButtonDisabled(state)).toBeTruthy();
+ expect(getters.discardDraftButtonDisabled(state)).toBe(true);
});
});
@@ -152,13 +152,13 @@ describe('IDE commit module getters', () => {
it('returns false if NOT creating a new branch', () => {
state.commitAction = COMMIT_TO_CURRENT_BRANCH;
- expect(getters.isCreatingNewBranch(state)).toBeFalsy();
+ expect(getters.isCreatingNewBranch(state)).toBe(false);
});
it('returns true if creating a new branch', () => {
state.commitAction = COMMIT_TO_NEW_BRANCH;
- expect(getters.isCreatingNewBranch(state)).toBeTruthy();
+ expect(getters.isCreatingNewBranch(state)).toBe(true);
});
});
@@ -183,7 +183,7 @@ describe('IDE commit module getters', () => {
});
it('should never hide "New MR" option', () => {
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeNull();
});
});
@@ -195,13 +195,13 @@ describe('IDE commit module getters', () => {
it('should NOT hide "New MR" option if user can NOT push to the current branch', () => {
rootGetters.canPushToBranch = false;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(false);
});
it('should hide "New MR" option if user can push to the current branch', () => {
rootGetters.canPushToBranch = true;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeTruthy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(true);
});
});
@@ -211,7 +211,7 @@ describe('IDE commit module getters', () => {
});
it('should never hide "New MR" option', () => {
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeNull();
});
});
@@ -223,13 +223,13 @@ describe('IDE commit module getters', () => {
it('should NOT hide "New MR" option if there is NO existing MR for the current branch', () => {
rootGetters.hasMergeRequest = false;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeNull();
});
it('should hide "New MR" option if there is existing MR for the current branch', () => {
rootGetters.hasMergeRequest = true;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeTruthy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(true);
});
});
@@ -247,17 +247,13 @@ describe('IDE commit module getters', () => {
it('should hide "New MR" when there is an existing MR', () => {
rootGetters.hasMergeRequest = true;
- expect(
- getters.shouldHideNewMrOption(state, localGetters, null, rootGetters),
- ).toBeTruthy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(true);
});
it('should hide "New MR" when there is no existing MR', () => {
rootGetters.hasMergeRequest = false;
- expect(
- getters.shouldHideNewMrOption(state, localGetters, null, rootGetters),
- ).toBeTruthy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(true);
});
});
@@ -270,17 +266,17 @@ describe('IDE commit module getters', () => {
rootGetters.hasMergeRequest = false;
rootGetters.canPushToBranch = true;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(false);
rootGetters.hasMergeRequest = true;
rootGetters.canPushToBranch = true;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(false);
rootGetters.hasMergeRequest = false;
rootGetters.canPushToBranch = false;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(false);
});
});
});
@@ -292,7 +288,7 @@ describe('IDE commit module getters', () => {
rootGetters.hasMergeRequest = true;
rootGetters.canPushToBranch = true;
- expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBeFalsy();
+ expect(getters.shouldHideNewMrOption(state, localGetters, null, rootGetters)).toBe(false);
});
});
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index 1453f26c1d9..69ec2e7a6f5 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -22,7 +22,7 @@ describe('IDE store file mutations', () => {
active: true,
});
- expect(localFile.active).toBeTruthy();
+ expect(localFile.active).toBe(true);
});
it('sets pending tab as not active', () => {
@@ -41,7 +41,7 @@ describe('IDE store file mutations', () => {
it('adds into opened files', () => {
mutations.TOGGLE_FILE_OPEN(localState, localFile.path);
- expect(localFile.opened).toBeTruthy();
+ expect(localFile.opened).toBe(true);
expect(localState.openFiles.length).toBe(1);
});
@@ -50,7 +50,7 @@ describe('IDE store file mutations', () => {
mutations.TOGGLE_FILE_OPEN(localState, localFile.path);
mutations.TOGGLE_FILE_OPEN(localState, localFile.path);
- expect(localFile.opened).toBeFalsy();
+ expect(localFile.opened).toBe(false);
expect(localState.openFiles.length).toBe(0);
});
});
@@ -162,7 +162,7 @@ describe('IDE store file mutations', () => {
callMutationForFile(localFile);
- expect(localFile.raw).toBeFalsy();
+ expect(localFile.raw).toEqual('');
expect(localState.stagedFiles[0].raw).toBe('testing');
});
@@ -172,7 +172,7 @@ describe('IDE store file mutations', () => {
callMutationForFile(localFile);
- expect(localFile.raw).toBeFalsy();
+ expect(localFile.raw).toEqual('');
expect(localFile.content).toBe('testing');
});
@@ -202,7 +202,7 @@ describe('IDE store file mutations', () => {
callMutationForFile(localFile);
- expect(localFile.raw).toBeFalsy();
+ expect(localFile.raw).toEqual('');
expect(localState.stagedFiles[0].raw).toBe('testing');
});
});
@@ -239,7 +239,7 @@ describe('IDE store file mutations', () => {
});
expect(localFile.content).toBe('testing');
- expect(localFile.changed).toBeTruthy();
+ expect(localFile.changed).toBe(true);
});
it('sets changed if file is a temp file', () => {
@@ -250,7 +250,7 @@ describe('IDE store file mutations', () => {
content: '',
});
- expect(localFile.changed).toBeTruthy();
+ expect(localFile.changed).toBe(true);
});
});
@@ -329,7 +329,7 @@ describe('IDE store file mutations', () => {
mutations.DISCARD_FILE_CHANGES(localState, localFile.path);
expect(localFile.content).toBe('');
- expect(localFile.changed).toBeFalsy();
+ expect(localFile.changed).toBe(false);
});
it('adds to root tree if deleted', () => {
@@ -527,7 +527,7 @@ describe('IDE store file mutations', () => {
changed: true,
});
- expect(localFile.changed).toBeTruthy();
+ expect(localFile.changed).toBe(true);
});
});
diff --git a/spec/frontend/ide/stores/mutations/merge_request_spec.js b/spec/frontend/ide/stores/mutations/merge_request_spec.js
index afbe6770c0d..2af06835181 100644
--- a/spec/frontend/ide/stores/mutations/merge_request_spec.js
+++ b/spec/frontend/ide/stores/mutations/merge_request_spec.js
@@ -30,7 +30,7 @@ describe('IDE store merge request mutations', () => {
const newMr = localState.projects.abcproject.mergeRequests[1];
expect(newMr.title).toBe('mr');
- expect(newMr.active).toBeTruthy();
+ expect(newMr.active).toBe(true);
});
it('keeps original data', () => {
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index 2f8447af518..fd9d481251d 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -46,7 +46,7 @@ describe('WebIDE utils', () => {
content: 'SELECT "éêė" from tablename',
mimeType: 'application/sql',
}),
- ).toBeFalsy();
+ ).toBe(false);
});
it('returns true for ASCII only content for unknown types', () => {
@@ -56,7 +56,7 @@ describe('WebIDE utils', () => {
content: 'plain text',
mimeType: 'application/x-new-type',
}),
- ).toBeTruthy();
+ ).toBe(true);
});
it('returns false for non-ASCII content for unknown types', () => {
@@ -66,7 +66,7 @@ describe('WebIDE utils', () => {
content: '{"éêė":"value"}',
mimeType: 'application/octet-stream',
}),
- ).toBeFalsy();
+ ).toBe(false);
});
it.each`
diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
index ee2f6541b03..5af0e272285 100644
--- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
+++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
@@ -204,7 +204,7 @@ describe('DynamicField', () => {
});
expect(findGlFormGroup().find('small').html()).toContain(
- '[<code>1</code> <a>3</a> <a target="_blank" href="foo">4</a>]',
+ '[<code>1</code> <a>3</a> <a href="foo">4</a>]',
);
});
});
diff --git a/spec/frontend/integrations/overrides/components/integration_overrides_spec.js b/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
index 6aa3e661677..fd60d7f817f 100644
--- a/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
+++ b/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
@@ -15,6 +15,7 @@ import UrlSync from '~/vue_shared/components/url_sync.vue';
const mockOverrides = Array(DEFAULT_PER_PAGE * 3)
.fill(1)
.map((_, index) => ({
+ id: index,
name: `test-proj-${index}`,
avatar_url: `avatar-${index}`,
full_path: `test-proj-${index}`,
@@ -59,6 +60,7 @@ describe('IntegrationOverrides', () => {
const avatar = link.findComponent(ProjectAvatar);
return {
+ id: avatar.props('projectId'),
href: link.attributes('href'),
avatarUrl: avatar.props('projectAvatarUrl'),
avatarName: avatar.props('projectName'),
@@ -90,7 +92,7 @@ describe('IntegrationOverrides', () => {
const table = findGlTable();
expect(table.exists()).toBe(true);
- expect(table.attributes('busy')).toBeFalsy();
+ expect(table.attributes('busy')).toBeUndefined();
});
it('renders IntegrationTabs with count', async () => {
@@ -109,6 +111,7 @@ describe('IntegrationOverrides', () => {
it('renders overrides as rows in table', () => {
expect(findRowsAsModel()).toEqual(
mockOverrides.map((x) => ({
+ id: x.id,
href: x.full_path,
avatarUrl: x.avatar_url,
avatarName: x.name,
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 045a454e63a..2058784b033 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -1,4 +1,4 @@
-import { GlLink, GlModal, GlSprintf, GlFormGroup } from '@gitlab/ui';
+import { GlLink, GlModal, GlSprintf, GlFormGroup, GlCollapse, GlIcon } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { stubComponent } from 'helpers/stub_component';
@@ -18,6 +18,7 @@ import {
MEMBERS_PLACEHOLDER_DISABLED,
MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
LEARN_GITLAB,
+ EXPANDED_ERRORS,
} from '~/invite_members/constants';
import eventHub from '~/invite_members/event_hub';
import ContentTransition from '~/vue_shared/components/content_transition.vue';
@@ -36,6 +37,7 @@ import {
user3,
user4,
user5,
+ user6,
GlEmoji,
} from '../mock_data/member_modal';
@@ -95,9 +97,12 @@ describe('InviteMembersModal', () => {
const findBase = () => wrapper.findComponent(InviteModalBase);
const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text();
const findMemberErrorAlert = () => wrapper.findByTestId('alert-member-error');
+ const findMoreInviteErrorsButton = () => wrapper.findByTestId('accordion-button');
+ const findAccordion = () => wrapper.findComponent(GlCollapse);
+ const findErrorsIcon = () => wrapper.findComponent(GlIcon);
const findMemberErrorMessage = (element) =>
- `${Object.keys(invitationsApiResponse.MULTIPLE_RESTRICTED.message)[element]}: ${
- Object.values(invitationsApiResponse.MULTIPLE_RESTRICTED.message)[element]
+ `${Object.keys(invitationsApiResponse.EXPANDED_RESTRICTED.message)[element]}: ${
+ Object.values(invitationsApiResponse.EXPANDED_RESTRICTED.message)[element]
}`;
const emitEventFromModal = (eventName) => () =>
findModal().vm.$emit(eventName, { preventDefault: jest.fn() });
@@ -666,8 +671,8 @@ describe('InviteMembersModal', () => {
it('displays errors for multiple and allows clearing', async () => {
createInviteMembersToGroupWrapper();
- await triggerMembersTokenSelect([user3, user4, user5]);
- mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED);
+ await triggerMembersTokenSelect([user3, user4, user5, user6]);
+ mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EXPANDED_RESTRICTED);
clickInviteButton();
@@ -675,19 +680,44 @@ describe('InviteMembersModal', () => {
expect(findMemberErrorAlert().exists()).toBe(true);
expect(findMemberErrorAlert().props('title')).toContain(
- "The following 3 members couldn't be invited",
+ "The following 4 members couldn't be invited",
);
expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(0));
expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(1));
expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(2));
+ expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(3));
+ expect(findAccordion().exists()).toBe(true);
+ expect(findMoreInviteErrorsButton().text()).toContain('Show more (2)');
+ expect(findErrorsIcon().attributes('class')).not.toContain('gl-rotate-180');
+ expect(findAccordion().attributes('visible')).toBeUndefined();
+
+ await findMoreInviteErrorsButton().vm.$emit('click');
+
+ expect(findMoreInviteErrorsButton().text()).toContain(EXPANDED_ERRORS);
+ expect(findErrorsIcon().attributes('class')).toContain('gl-rotate-180');
+ expect(findAccordion().attributes('visible')).toBeDefined();
+
+ await findMoreInviteErrorsButton().vm.$emit('click');
+
+ expect(findMoreInviteErrorsButton().text()).toContain('Show more (2)');
+ expect(findAccordion().attributes('visible')).toBeUndefined();
await removeMembersToken(user3);
+ expect(findMoreInviteErrorsButton().text()).toContain('Show more (1)');
expect(findMemberErrorAlert().props('title')).toContain(
- "The following 2 members couldn't be invited",
+ "The following 3 members couldn't be invited",
);
expect(findMemberErrorAlert().text()).not.toContain(findMemberErrorMessage(0));
+ await removeMembersToken(user6);
+
+ expect(findMoreInviteErrorsButton().exists()).toBe(false);
+ expect(findMemberErrorAlert().props('title')).toContain(
+ "The following 2 members couldn't be invited",
+ );
+ expect(findMemberErrorAlert().text()).not.toContain(findMemberErrorMessage(2));
+
await removeMembersToken(user4);
expect(findMemberErrorAlert().props('title')).toContain(
diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js
index 6375d0f7e2e..0455460918c 100644
--- a/spec/frontend/invite_members/components/members_token_select_spec.js
+++ b/spec/frontend/invite_members/components/members_token_select_spec.js
@@ -5,6 +5,7 @@ import { stubComponent } from 'helpers/stub_component';
import waitForPromises from 'helpers/wait_for_promises';
import * as UserApi from '~/api/user_api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
+import { VALID_TOKEN_BACKGROUND, INVALID_TOKEN_BACKGROUND } from '~/invite_members/constants';
const label = 'testgroup';
const placeholder = 'Search for a member';
@@ -49,6 +50,39 @@ describe('MembersTokenSelect', () => {
});
});
+ describe('when there are invalidMembers', () => {
+ it('adds in the correct class values for the tokens', async () => {
+ const badToken = { ...user1, class: INVALID_TOKEN_BACKGROUND };
+ const goodToken = { ...user2, class: VALID_TOKEN_BACKGROUND };
+
+ wrapper = createComponent();
+
+ findTokenSelector().vm.$emit('input', [user1, user2]);
+
+ await waitForPromises();
+
+ expect(findTokenSelector().props('selectedTokens')).toEqual([user1, user2]);
+
+ await wrapper.setProps({ invalidMembers: { one_1: 'bad stuff' } });
+
+ expect(findTokenSelector().props('selectedTokens')).toEqual([badToken, goodToken]);
+ });
+
+ it('does not change class when invalid members are cleared', async () => {
+ // arrange - invalidMembers is non-empty and then tokens are added
+ wrapper = createComponent();
+ await wrapper.setProps({ invalidMembers: { one_1: 'bad stuff' } });
+ findTokenSelector().vm.$emit('input', [user1, user2]);
+ await waitForPromises();
+
+ // act - invalidMembers clears out
+ await wrapper.setProps({ invalidMembers: {} });
+
+ // assert - we didn't try to update the tokens
+ expect(findTokenSelector().props('selectedTokens')).toEqual([user1, user2]);
+ });
+ });
+
describe('users', () => {
beforeEach(() => {
jest.spyOn(UserApi, 'getUsers').mockResolvedValue({ data: allUsers });
diff --git a/spec/frontend/invite_members/components/user_limit_notification_spec.js b/spec/frontend/invite_members/components/user_limit_notification_spec.js
index bbc17932a49..543fc28a342 100644
--- a/spec/frontend/invite_members/components/user_limit_notification_spec.js
+++ b/spec/frontend/invite_members/components/user_limit_notification_spec.js
@@ -9,6 +9,8 @@ import {
import { freeUsersLimit, membersCount } from '../mock_data/member_modal';
+const WARNING_ALERT_TITLE = 'You only have space for 2 more members in name';
+
describe('UserLimitNotification', () => {
let wrapper;
@@ -33,7 +35,7 @@ describe('UserLimitNotification', () => {
},
...props,
},
- provide: { name: 'my group' },
+ provide: { name: 'name' },
stubs: { GlSprintf },
});
};
@@ -50,7 +52,7 @@ describe('UserLimitNotification', () => {
});
});
- describe('when close to limit with a personal namepace', () => {
+ describe('when close to limit within a personal namepace', () => {
beforeEach(() => {
createComponent(true, false, { membersCount: 3, userNamespace: true });
});
@@ -58,27 +60,24 @@ describe('UserLimitNotification', () => {
it('renders the limit for a personal namespace', () => {
const alert = findAlert();
- expect(alert.attributes('title')).toEqual(
- 'You only have space for 2 more members in your personal projects',
- );
+ expect(alert.attributes('title')).toEqual(WARNING_ALERT_TITLE);
+
expect(alert.text()).toEqual(
'To make more space, you can remove members who no longer need access.',
);
});
});
- describe('when close to limit', () => {
+ describe('when close to limit within a group', () => {
it("renders user's limit notification", () => {
createComponent(true, false, { membersCount: 3 });
const alert = findAlert();
- expect(alert.attributes('title')).toEqual(
- 'You only have space for 2 more members in my group',
- );
+ expect(alert.attributes('title')).toEqual(WARNING_ALERT_TITLE);
expect(alert.text()).toEqual(
- 'To get more members an owner of this namespace can start a trial or upgrade to a paid tier.',
+ 'To get more members an owner of the group can start a trial or upgrade to a paid tier.',
);
});
});
@@ -89,7 +88,7 @@ describe('UserLimitNotification', () => {
const alert = findAlert();
- expect(alert.attributes('title')).toEqual("You've reached your 5 members limit for my group");
+ expect(alert.attributes('title')).toEqual("You've reached your 5 members limit for name");
expect(alert.text()).toEqual(REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE);
});
diff --git a/spec/frontend/invite_members/mock_data/api_responses.js b/spec/frontend/invite_members/mock_data/api_responses.js
index 4ad3b6aeb66..6fe06decb6b 100644
--- a/spec/frontend/invite_members/mock_data/api_responses.js
+++ b/spec/frontend/invite_members/mock_data/api_responses.js
@@ -26,6 +26,20 @@ const MULTIPLE_RESTRICTED = {
status: 'error',
};
+const EXPANDED_RESTRICTED = {
+ message: {
+ 'email@example.com':
+ "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
+ 'email4@example.com':
+ "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist.",
+ 'email5@example.com':
+ "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist.",
+ root:
+ "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.",
+ },
+ status: 'error',
+};
+
const EMAIL_TAKEN = {
message: {
'email@example.org': "The member's email address has already been taken",
@@ -41,4 +55,5 @@ export const invitationsApiResponse = {
EMAIL_RESTRICTED,
MULTIPLE_RESTRICTED,
EMAIL_TAKEN,
+ EXPANDED_RESTRICTED,
};
diff --git a/spec/frontend/invite_members/mock_data/member_modal.js b/spec/frontend/invite_members/mock_data/member_modal.js
index 7d675b6206c..4f4e9345e46 100644
--- a/spec/frontend/invite_members/mock_data/member_modal.js
+++ b/spec/frontend/invite_members/mock_data/member_modal.js
@@ -39,5 +39,10 @@ export const user5 = {
name: 'root',
avatar_url: '',
};
+export const user6 = {
+ id: 'user-defined-token3',
+ name: 'email5@example.com',
+ avatar_url: '',
+};
export const GlEmoji = { template: '<img/>' };
diff --git a/spec/frontend/issuable/components/related_issuable_item_spec.js b/spec/frontend/issuable/components/related_issuable_item_spec.js
index 6b48f83041a..3f9f048605a 100644
--- a/spec/frontend/issuable/components/related_issuable_item_spec.js
+++ b/spec/frontend/issuable/components/related_issuable_item_spec.js
@@ -1,23 +1,25 @@
-import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { GlIcon, GlLink, GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
+import { updateHistory } from '~/lib/utils/url_utility';
+import { __ } from '~/locale';
import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
+import IssueMilestone from '~/issuable/components/issue_milestone.vue';
+import IssueAssignees from '~/issuable/components/issue_assignees.vue';
+import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import { defaultAssignees, defaultMilestone } from './related_issuable_mock_data';
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ updateHistory: jest.fn(),
+}));
+
describe('RelatedIssuableItem', () => {
let wrapper;
- function mountComponent({ mountMethod = mount, stubs = {}, props = {}, slots = {} } = {}) {
- wrapper = mountMethod(RelatedIssuableItem, {
- propsData: props,
- slots,
- stubs,
- });
- }
-
- const props = {
+ const defaultProps = {
idKey: 1,
displayReference: 'gitlab-org/gitlab-test#1',
pathIdSeparator: '#',
@@ -31,84 +33,94 @@ describe('RelatedIssuableItem', () => {
assignees: defaultAssignees,
eventNamespace: 'relatedIssue',
};
- const slots = {
- dueDate: '<div class="js-due-date-slot"></div>',
- weight: '<div class="js-weight-slot"></div>',
- };
-
- const findRemoveButton = () => wrapper.find({ ref: 'removeButton' });
- const findLockIcon = () => wrapper.find({ ref: 'lockIcon' });
- beforeEach(() => {
- mountComponent({ props, slots });
- });
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findIssueDueDate = () => wrapper.findComponent(IssueDueDate);
+ const findLockIcon = () => wrapper.find('[data-testid="lockIcon"]');
+ const findRemoveButton = () => wrapper.findComponent(GlButton);
+ const findTitleLink = () => wrapper.findComponent(GlLink);
+ const findWorkItemDetailModal = () => wrapper.findComponent(WorkItemDetailModal);
+
+ function mountComponent({ data = {}, props = {} } = {}) {
+ wrapper = shallowMount(RelatedIssuableItem, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ });
+ }
afterEach(() => {
wrapper.destroy();
});
it('contains issuable-info-container class when canReorder is false', () => {
- expect(wrapper.props('canReorder')).toBe(false);
- expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
+ mountComponent({ props: { canReorder: false } });
+
+ expect(wrapper.classes('issuable-info-container')).toBe(true);
});
it('does not render token state', () => {
+ mountComponent();
+
expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
});
it('does not render remove button', () => {
- expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
+ mountComponent();
+
+ expect(findRemoveButton().exists()).toBe(false);
});
describe('token title', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
it('links to computedPath', () => {
- expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
+ expect(findTitleLink().attributes('href')).toBe(defaultProps.path);
});
it('renders confidential icon', () => {
- expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ expect(findIcon().attributes('title')).toBe(__('Confidential'));
});
it('renders title', () => {
- expect(wrapper.find('.item-title a').text()).toEqual(props.title);
+ expect(findTitleLink().text()).toBe(defaultProps.title);
});
});
describe('token state', () => {
- const tokenState = () => wrapper.find({ ref: 'iconElementXL' });
-
- beforeEach(() => {
- wrapper.setProps({ state: 'opened' });
- });
-
- it('renders if hasState', () => {
- expect(tokenState().exists()).toBe(true);
- });
-
it('renders state title', () => {
- const stateTitle = tokenState().attributes('title');
- const formattedCreateDate = formatDate(props.createdAt);
+ mountComponent({ props: { state: 'opened' } });
+ const stateTitle = findIcon().attributes('title');
+ const formattedCreateDate = formatDate(defaultProps.createdAt);
expect(stateTitle).toContain('<span class="bold">Created</span>');
expect(stateTitle).toContain(`<span class="text-tertiary">${formattedCreateDate}</span>`);
});
it('renders aria label', () => {
- expect(tokenState().attributes('aria-label')).toEqual('opened');
+ mountComponent({ props: { state: 'opened' } });
+
+ expect(findIcon().attributes('arialabel')).toBe('opened');
});
it('renders open icon when open state', () => {
- expect(tokenState().classes('issue-token-state-icon-open')).toBe(true);
+ mountComponent({ props: { state: 'opened' } });
+
+ expect(findIcon().props('name')).toBe('issue-open-m');
+ expect(findIcon().classes('issue-token-state-icon-open')).toBe(true);
});
- it('renders close icon when close state', async () => {
- wrapper.setProps({
- state: 'closed',
- closedAt: '2018-12-01T00:00:00.00Z',
- });
- await nextTick();
+ it('renders close icon when close state', () => {
+ mountComponent({ props: { state: 'closed', closedAt: '2018-12-01T00:00:00.00Z' } });
- expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true);
+ expect(findIcon().props('name')).toBe('issue-close');
+ expect(findIcon().classes('issue-token-state-icon-closed')).toBe(true);
});
});
@@ -116,75 +128,66 @@ describe('RelatedIssuableItem', () => {
const tokenMetadata = () => wrapper.find('.item-meta');
it('renders item path and ID', () => {
+ mountComponent();
const pathAndID = tokenMetadata().find('.item-path-id').text();
expect(pathAndID).toContain('gitlab-org/gitlab-test');
expect(pathAndID).toContain('#1');
});
- it('renders milestone icon and name', () => {
- const milestoneIcon = tokenMetadata().find('.item-milestone svg');
- const milestoneTitle = tokenMetadata().find('.item-milestone .milestone-title');
+ it('renders milestone', () => {
+ mountComponent();
- expect(milestoneIcon.attributes('data-testid')).toBe('clock-icon');
- expect(milestoneTitle.text()).toContain('Milestone title');
+ expect(wrapper.findComponent(IssueMilestone).props('milestone')).toEqual(
+ defaultProps.milestone,
+ );
});
it('renders due date component with correct due date', () => {
- expect(wrapper.find(IssueDueDate).props('date')).toBe(props.dueDate);
+ mountComponent();
+
+ expect(findIssueDueDate().props('date')).toBe(defaultProps.dueDate);
});
- it('does not render red icon for overdue issue that is closed', async () => {
- mountComponent({
- props: {
- ...props,
- closedAt: '2018-12-01T00:00:00.00Z',
- },
- });
- await nextTick();
+ it('does not render red icon for overdue issue that is closed', () => {
+ mountComponent({ props: { closedAt: '2018-12-01T00:00:00.00Z' } });
- expect(wrapper.find(IssueDueDate).props('closed')).toBe(true);
+ expect(findIssueDueDate().props('closed')).toBe(true);
});
});
describe('token assignees', () => {
it('renders assignees avatars', () => {
- // Expect 2 times 2 because assignees are rendered twice, due to layout issues
- expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBeDefined();
+ mountComponent();
- expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
+ expect(wrapper.findComponent(IssueAssignees).props('assignees')).toEqual(
+ defaultProps.assignees,
+ );
});
});
describe('remove button', () => {
beforeEach(() => {
- wrapper.setProps({ canRemove: true });
+ mountComponent({ props: { canRemove: true }, data: { removeDisabled: true } });
});
it('renders if canRemove', () => {
- expect(findRemoveButton().exists()).toBe(true);
+ expect(findRemoveButton().props('icon')).toBe('close');
+ expect(findRemoveButton().attributes('aria-label')).toBe(__('Remove'));
});
it('does not render the lock icon', () => {
expect(findLockIcon().exists()).toBe(false);
});
- it('renders disabled button when removeDisabled', async () => {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ removeDisabled: true });
- await nextTick();
-
- expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
+ it('renders disabled button when removeDisabled', () => {
+ expect(findRemoveButton().attributes('disabled')).toBe('true');
});
- it('triggers onRemoveRequest when clicked', async () => {
- findRemoveButton().trigger('click');
- await nextTick();
- const { relatedIssueRemoveRequest } = wrapper.emitted();
+ it('triggers onRemoveRequest when clicked', () => {
+ findRemoveButton().vm.$emit('click');
- expect(relatedIssueRemoveRequest.length).toBe(1);
- expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
+ expect(wrapper.emitted('relatedIssueRemoveRequest')).toEqual([[defaultProps.idKey]]);
});
});
@@ -192,10 +195,7 @@ describe('RelatedIssuableItem', () => {
const lockedMessage = 'Issues created from a vulnerability cannot be removed';
beforeEach(() => {
- wrapper.setProps({
- isLocked: true,
- lockedMessage,
- });
+ mountComponent({ props: { isLocked: true, lockedMessage } });
});
it('does not render the remove button', () => {
@@ -206,4 +206,67 @@ describe('RelatedIssuableItem', () => {
expect(findLockIcon().attributes('title')).toBe(lockedMessage);
});
});
+
+ describe('work item modal', () => {
+ const workItem = 'gid://gitlab/WorkItem/1';
+
+ it('renders', () => {
+ mountComponent();
+
+ expect(findWorkItemDetailModal().props('workItemId')).toBe(workItem);
+ });
+
+ describe('when work item is issue and the related issue title is clicked', () => {
+ it('does not open', () => {
+ mountComponent({ props: { workItemType: 'ISSUE' } });
+ wrapper.vm.$refs.modal.show = jest.fn();
+
+ findTitleLink().vm.$emit('click', { preventDefault: () => {} });
+
+ expect(wrapper.vm.$refs.modal.show).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('when work item is task and the related issue title is clicked', () => {
+ beforeEach(() => {
+ mountComponent({ props: { workItemType: 'TASK' } });
+ wrapper.vm.$refs.modal.show = jest.fn();
+ findTitleLink().vm.$emit('click', { preventDefault: () => {} });
+ });
+
+ it('opens', () => {
+ expect(wrapper.vm.$refs.modal.show).toHaveBeenCalled();
+ });
+
+ it('updates the url params with the work item id', () => {
+ expect(updateHistory).toHaveBeenCalledWith({
+ url: `${TEST_HOST}/?work_item_id=1`,
+ replace: true,
+ });
+ });
+ });
+
+ describe('when it emits "workItemDeleted" event', () => {
+ it('emits "relatedIssueRemoveRequest" event', () => {
+ mountComponent();
+
+ findWorkItemDetailModal().vm.$emit('workItemDeleted', workItem);
+
+ expect(wrapper.emitted('relatedIssueRemoveRequest')).toEqual([[workItem]]);
+ });
+ });
+
+ describe('when it emits "close" event', () => {
+ it('removes the work item id from the url params', () => {
+ mountComponent();
+
+ findWorkItemDetailModal().vm.$emit('close');
+
+ expect(updateHistory).toHaveBeenCalledWith({
+ url: `${TEST_HOST}/`,
+ replace: true,
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/issuable/popover/components/issue_popover_spec.js b/spec/frontend/issuable/popover/components/issue_popover_spec.js
index 3e77e750f3a..444165f61c7 100644
--- a/spec/frontend/issuable/popover/components/issue_popover_spec.js
+++ b/spec/frontend/issuable/popover/components/issue_popover_spec.js
@@ -1,33 +1,23 @@
-import { GlSkeletonLoader } from '@gitlab/ui';
+import { GlIcon, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import issueQueryResponse from 'test_fixtures/graphql/issuable/popover/queries/issue.query.graphql.json';
+import issueQuery from 'ee_else_ce/issuable/popover/queries/issue.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import IssueMilestone from '~/issuable/components/issue_milestone.vue';
import StatusBox from '~/issuable/components/status_box.vue';
import IssuePopover from '~/issuable/popover/components/issue_popover.vue';
-import issueQuery from '~/issuable/popover/queries/issue.query.graphql';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
describe('Issue Popover', () => {
let wrapper;
Vue.use(VueApollo);
- const issueQueryResponse = {
- data: {
- project: {
- __typename: 'Project',
- id: '1',
- issue: {
- __typename: 'Issue',
- id: 'gid://gitlab/Issue/1',
- createdAt: '2020-07-01T04:08:01Z',
- state: 'opened',
- title: 'Issue title',
- },
- },
- },
- };
+ const findWorkItemIcon = () => wrapper.findComponent(WorkItemTypeIcon);
const mountComponent = ({
queryResponse = jest.fn().mockResolvedValue(issueQueryResponse),
@@ -53,6 +43,12 @@ describe('Issue Popover', () => {
expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
});
+ it('should not show any work item icon while apollo is loading', () => {
+ mountComponent();
+
+ expect(findWorkItemIcon().exists()).toBe(false);
+ });
+
describe('when loaded', () => {
beforeEach(() => {
mountComponent();
@@ -74,8 +70,40 @@ describe('Issue Popover', () => {
expect(wrapper.find('h5').text()).toBe(issueQueryResponse.data.project.issue.title);
});
+ it('shows the work type icon', () => {
+ expect(findWorkItemIcon().props('workItemType')).toBe(
+ issueQueryResponse.data.project.issue.type,
+ );
+ });
+
it('shows reference', () => {
expect(wrapper.text()).toContain('foo/bar#1');
});
+
+ it('shows confidential icon', () => {
+ const icon = wrapper.findComponent(GlIcon);
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('eye-slash');
+ });
+
+ it('shows due date', () => {
+ const component = wrapper.findComponent(IssueDueDate);
+
+ expect(component.exists()).toBe(true);
+ expect(component.props('date')).toBe('2020-07-05');
+ expect(component.props('closed')).toBe(false);
+ });
+
+ it('shows milestone', () => {
+ const component = wrapper.findComponent(IssueMilestone);
+
+ expect(component.exists()).toBe(true);
+ expect(component.props('milestone')).toMatchObject({
+ title: '15.2',
+ startDate: '2020-07-01',
+ dueDate: '2020-07-30',
+ });
+ });
});
});
diff --git a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
index ce98a16dbb7..16d4459f597 100644
--- a/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
+++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
@@ -157,8 +157,8 @@ describe('AddIssuableForm', () => {
describe('categorized issuables', () => {
it.each`
issuableType | pathIdSeparator | contextHeader | contextFooter
- ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issue(s)'}
- ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epic(s)'}
+ ${issuableTypesMap.ISSUE} | ${PathIdSeparator.Issue} | ${'The current issue'} | ${'the following issues'}
+ ${issuableTypesMap.EPIC} | ${PathIdSeparator.Epic} | ${'The current epic'} | ${'the following epics'}
`(
'show header text as "$contextHeader" and footer text as "$contextFooter" issuableType is set to $issuableType',
({ issuableType, contextHeader, contextFooter }) => {
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
index 7a350df0ba6..772cc75a205 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -1,5 +1,6 @@
-import { GlButton, GlIcon } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { GlIcon } from '@gitlab/ui';
+import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
issuable1,
issuable2,
@@ -17,7 +18,9 @@ import {
describe('RelatedIssuesBlock', () => {
let wrapper;
- const findIssueCountBadgeAddButton = () => wrapper.find(GlButton);
+ const findToggleButton = () => wrapper.findByTestId('toggle-links');
+ const findRelatedIssuesBody = () => wrapper.findByTestId('related-issues-body');
+ const findIssueCountBadgeAddButton = () => wrapper.findByTestId('related-issues-plus-button');
afterEach(() => {
if (wrapper) {
@@ -28,7 +31,7 @@ describe('RelatedIssuesBlock', () => {
describe('with defaults', () => {
beforeEach(() => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: issuableTypesMap.ISSUE,
@@ -37,13 +40,13 @@ describe('RelatedIssuesBlock', () => {
});
it.each`
- issuableType | pathIdSeparator | titleText | helpLinkText | addButtonText
- ${'issue'} | ${PathIdSeparator.Issue} | ${'Linked issues'} | ${'Read more about related issues'} | ${'Add a related issue'}
- ${'epic'} | ${PathIdSeparator.Epic} | ${'Linked epics'} | ${'Read more about related epics'} | ${'Add a related epic'}
+ issuableType | pathIdSeparator | titleText | helpLinkText | addButtonText
+ ${'issue'} | ${PathIdSeparator.Issue} | ${'Linked items'} | ${'Read more about related issues'} | ${'Add a related issue'}
+ ${'epic'} | ${PathIdSeparator.Epic} | ${'Linked epics'} | ${'Read more about related epics'} | ${'Add a related epic'}
`(
'displays "$titleText" in the header, "$helpLinkText" aria-label for help link, and "$addButtonText" aria-label for add button when issuableType is set to "$issuableType"',
({ issuableType, pathIdSeparator, titleText, helpLinkText, addButtonText }) => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator,
issuableType,
@@ -73,7 +76,7 @@ describe('RelatedIssuesBlock', () => {
it('displays header text slot data', () => {
const headerText = '<div>custom header text</div>';
- wrapper = shallowMount(RelatedIssuesBlock, {
+ wrapper = shallowMountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
@@ -89,7 +92,7 @@ describe('RelatedIssuesBlock', () => {
it('displays header actions slot data', () => {
const headerActions = '<button data-testid="custom-button">custom button</button>';
- wrapper = shallowMount(RelatedIssuesBlock, {
+ wrapper = shallowMountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType: 'issue',
@@ -103,7 +106,7 @@ describe('RelatedIssuesBlock', () => {
describe('with isFetching=true', () => {
beforeEach(() => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
isFetching: true,
@@ -119,7 +122,7 @@ describe('RelatedIssuesBlock', () => {
describe('with canAddRelatedIssues=true', () => {
beforeEach(() => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
canAdmin: true,
@@ -135,7 +138,7 @@ describe('RelatedIssuesBlock', () => {
describe('with isFormVisible=true', () => {
beforeEach(() => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
isFormVisible: true,
@@ -159,7 +162,7 @@ describe('RelatedIssuesBlock', () => {
const categorizedHeadings = () => wrapper.findAll('h4');
const headingTextAt = (index) => categorizedHeadings().at(index).text();
const mountComponent = (showCategorizedIssues) => {
- wrapper = mount(RelatedIssuesBlock, {
+ wrapper = mountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
relatedIssues: [issuable1, issuable2, issuable3],
@@ -217,7 +220,7 @@ describe('RelatedIssuesBlock', () => {
},
].forEach(({ issuableType, icon }) => {
it(`issuableType=${issuableType} is passed`, () => {
- wrapper = shallowMount(RelatedIssuesBlock, {
+ wrapper = shallowMountExtended(RelatedIssuesBlock, {
propsData: {
pathIdSeparator: PathIdSeparator.Issue,
issuableType,
@@ -230,4 +233,42 @@ describe('RelatedIssuesBlock', () => {
});
});
});
+
+ describe('toggle', () => {
+ beforeEach(() => {
+ wrapper = shallowMountExtended(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ relatedIssues: [issuable1, issuable2, issuable3],
+ issuableType: issuableTypesMap.ISSUE,
+ },
+ });
+ });
+
+ it('is expanded by default', () => {
+ expect(findToggleButton().props('icon')).toBe('chevron-lg-up');
+ expect(findToggleButton().props('disabled')).toBe(false);
+ expect(findRelatedIssuesBody().exists()).toBe(true);
+ });
+
+ it('expands on click toggle button', async () => {
+ findToggleButton().vm.$emit('click');
+ await nextTick();
+
+ expect(findToggleButton().props('icon')).toBe('chevron-lg-down');
+ expect(findRelatedIssuesBody().exists()).toBe(false);
+ });
+ });
+
+ it('toggle button is disabled when issue has no related items', () => {
+ wrapper = shallowMountExtended(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ relatedIssues: [],
+ issuableType: 'issue',
+ },
+ });
+
+ expect(findToggleButton().props('disabled')).toBe(true);
+ });
});
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 1a03ea58b60..b518d2fbdec 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
@@ -1,4 +1,4 @@
-import { mount, shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
@@ -9,8 +9,9 @@ import {
} from 'jest/issuable/components/related_issuable_mock_data';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import { linkedIssueTypesMap } from '~/related_issues/constants';
+import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
+import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
import relatedIssuesService from '~/related_issues/services/related_issues_service';
jest.mock('~/flash');
@@ -19,6 +20,8 @@ describe('RelatedIssuesRoot', () => {
let wrapper;
let mock;
+ const findRelatedIssuesBlock = () => wrapper.findComponent(RelatedIssuesBlock);
+
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet(defaultProps.endpoint).reply(200, []);
@@ -26,100 +29,114 @@ describe('RelatedIssuesRoot', () => {
afterEach(() => {
mock.restore();
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
- const createComponent = (mountFn = mount) => {
- wrapper = mountFn(RelatedIssuesRoot, {
- propsData: defaultProps,
+ const createComponent = ({ props = {}, data = {} } = {}) => {
+ wrapper = mount(RelatedIssuesRoot, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ data() {
+ return data;
+ },
});
// Wait for fetch request `fetchRelatedIssues` to complete before starting to test
return waitForPromises();
};
- describe('methods', () => {
- describe('onRelatedIssueRemoveRequest', () => {
- beforeEach(() => {
- jest
- .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues')
- .mockReturnValue(Promise.reject());
-
- return createComponent().then(() => {
+ describe('events', () => {
+ describe('when "relatedIssueRemoveRequest" event is emitted', () => {
+ describe('when emitted value is a numerical issue', () => {
+ beforeEach(async () => {
+ jest
+ .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues')
+ .mockReturnValue(Promise.reject());
+ await createComponent();
wrapper.vm.store.setRelatedIssues([issuable1]);
});
- });
- it('remove related issue and succeeds', () => {
- mock.onDelete(issuable1.referencePath).reply(200, { issues: [] });
+ it('removes related issue on API success', async () => {
+ mock.onDelete(issuable1.referencePath).reply(200, { issues: [] });
+
+ findRelatedIssuesBlock().vm.$emit('relatedIssueRemoveRequest', issuable1.id);
+ await axios.waitForAll();
+
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toEqual([]);
+ });
+
+ it('does not remove related issue on API error', async () => {
+ mock.onDelete(issuable1.referencePath).reply(422, {});
- wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id);
+ findRelatedIssuesBlock().vm.$emit('relatedIssueRemoveRequest', issuable1.id);
+ await axios.waitForAll();
- return axios.waitForAll().then(() => {
- expect(wrapper.vm.state.relatedIssues).toEqual([]);
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toEqual([
+ expect.objectContaining({ id: issuable1.id }),
+ ]);
});
});
- it('remove related issue, fails, and restores to related issues', () => {
- mock.onDelete(issuable1.referencePath).reply(422, {});
+ describe('when emitted value is a work item id', () => {
+ it('removes related issue', async () => {
+ const workItem = `gid://gitlab/WorkItem/${issuable1.id}`;
+ createComponent({ data: { state: { relatedIssues: [issuable1] } } });
- wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id);
+ findRelatedIssuesBlock().vm.$emit('relatedIssueRemoveRequest', workItem);
+ await nextTick();
- return axios.waitForAll().then(() => {
- expect(wrapper.vm.state.relatedIssues).toHaveLength(1);
- expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toEqual([]);
});
});
});
- describe('onToggleAddRelatedIssuesForm', () => {
- beforeEach(() => createComponent(shallowMount));
+ describe('when "toggleAddRelatedIssuesForm" event is emitted', () => {
+ it('toggles related issues form to visible from hidden', async () => {
+ createComponent();
- it('toggle related issues form to visible', () => {
- wrapper.vm.onToggleAddRelatedIssuesForm();
+ findRelatedIssuesBlock().vm.$emit('toggleAddRelatedIssuesForm');
+ await nextTick();
- expect(wrapper.vm.isFormVisible).toEqual(true);
+ expect(findRelatedIssuesBlock().props('isFormVisible')).toBe(true);
});
- it('show add related issues form to hidden', () => {
- wrapper.vm.isFormVisible = true;
+ it('toggles related issues form to hidden from visible', async () => {
+ createComponent({ data: { isFormVisible: true } });
- wrapper.vm.onToggleAddRelatedIssuesForm();
+ findRelatedIssuesBlock().vm.$emit('toggleAddRelatedIssuesForm');
+ await nextTick();
- expect(wrapper.vm.isFormVisible).toEqual(false);
+ expect(findRelatedIssuesBlock().props('isFormVisible')).toBe(false);
});
});
- describe('onPendingIssueRemoveRequest', () => {
- beforeEach(() =>
- createComponent().then(() => {
- wrapper.vm.store.setPendingReferences([issuable1.reference]);
- }),
- );
+ describe('when "pendingIssuableRemoveRequest" event is emitted', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.vm.store.setPendingReferences([issuable1.reference]);
+ });
- it('remove pending related issue', () => {
- expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+ it('removes pending related issue', async () => {
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(1);
- wrapper.vm.onPendingIssueRemoveRequest(0);
+ findRelatedIssuesBlock().vm.$emit('pendingIssuableRemoveRequest', 0);
+ await nextTick();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(0);
});
});
- describe('onPendingFormSubmit', () => {
- beforeEach(() => {
+ describe('when "addIssuableFormSubmit" event is emitted', () => {
+ beforeEach(async () => {
jest
.spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues')
.mockReturnValue(Promise.reject());
-
- return createComponent().then(() => {
- jest.spyOn(wrapper.vm, 'processAllReferences');
- jest.spyOn(wrapper.vm.service, 'addRelatedIssues');
- createFlash.mockClear();
- });
+ await createComponent();
+ jest.spyOn(wrapper.vm, 'processAllReferences');
+ jest.spyOn(wrapper.vm.service, 'addRelatedIssues');
+ createFlash.mockClear();
});
it('processes references before submitting', () => {
@@ -130,23 +147,22 @@ describe('RelatedIssuesRoot', () => {
linkedIssueType,
};
- wrapper.vm.onPendingFormSubmit(emitObj);
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', emitObj);
expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input);
expect(wrapper.vm.service.addRelatedIssues).toHaveBeenCalledWith([input], linkedIssueType);
});
- it('submit zero pending issue as related issue', () => {
+ it('submits zero pending issues as related issue', () => {
wrapper.vm.store.setPendingReferences([]);
- wrapper.vm.onPendingFormSubmit({});
- return waitForPromises().then(() => {
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
- expect(wrapper.vm.state.relatedIssues).toHaveLength(0);
- });
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', {});
+
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(0);
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toHaveLength(0);
});
- it('submit pending issue as related issue', () => {
+ it('submits pending issue as related issue', async () => {
mock.onPost(defaultProps.endpoint).reply(200, {
issuables: [issuable1],
result: {
@@ -154,18 +170,18 @@ describe('RelatedIssuesRoot', () => {
status: 'success',
},
});
-
wrapper.vm.store.setPendingReferences([issuable1.reference]);
- wrapper.vm.onPendingFormSubmit({});
- return waitForPromises().then(() => {
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
- expect(wrapper.vm.state.relatedIssues).toHaveLength(1);
- expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
- });
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', {});
+ await waitForPromises();
+
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(0);
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toEqual([
+ expect.objectContaining({ id: issuable1.id }),
+ ]);
});
- it('submit multiple pending issues as related issues', () => {
+ it('submits multiple pending issues as related issues', async () => {
mock.onPost(defaultProps.endpoint).reply(200, {
issuables: [issuable1, issuable2],
result: {
@@ -173,201 +189,148 @@ describe('RelatedIssuesRoot', () => {
status: 'success',
},
});
-
wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]);
- wrapper.vm.onPendingFormSubmit({});
- return waitForPromises().then(() => {
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
- expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
- expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
- expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
- });
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', {});
+ await waitForPromises();
+
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(0);
+ expect(findRelatedIssuesBlock().props('relatedIssues')).toEqual([
+ expect.objectContaining({ id: issuable1.id }),
+ expect.objectContaining({ id: issuable2.id }),
+ ]);
});
- it('displays a message from the backend upon error', () => {
+ it('displays a message from the backend upon error', async () => {
const input = '#123';
const message = 'error';
-
mock.onPost(defaultProps.endpoint).reply(409, { message });
wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]);
expect(createFlash).not.toHaveBeenCalled();
- wrapper.vm.onPendingFormSubmit(input);
-
- return waitForPromises().then(() => {
- expect(createFlash).toHaveBeenCalledWith({
- message,
- });
- });
- });
- });
- describe('onPendingFormCancel', () => {
- beforeEach(() =>
- createComponent().then(() => {
- wrapper.vm.isFormVisible = true;
- wrapper.vm.inputValue = 'foo';
- }),
- );
-
- it('when canceling and hiding add issuable form', async () => {
- wrapper.vm.onPendingFormCancel();
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormSubmit', input);
+ await waitForPromises();
- await nextTick();
- expect(wrapper.vm.isFormVisible).toEqual(false);
- expect(wrapper.vm.inputValue).toEqual('');
- expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ expect(createFlash).toHaveBeenCalledWith({ message });
});
});
- describe('fetchRelatedIssues', () => {
- beforeEach(() => createComponent());
-
- it('sets isFetching while fetching', async () => {
- wrapper.vm.fetchRelatedIssues();
+ describe('when "addIssuableFormCancel" event is emitted', () => {
+ beforeEach(() => createComponent({ data: { isFormVisible: true, inputValue: 'foo' } }));
- expect(wrapper.vm.isFetching).toEqual(true);
+ it('hides form and resets input', async () => {
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormCancel');
+ await nextTick();
- await waitForPromises();
- expect(wrapper.vm.isFetching).toEqual(false);
- });
-
- it('should fetch related issues', async () => {
- mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]);
-
- wrapper.vm.fetchRelatedIssues();
-
- await waitForPromises();
- expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
- expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
- expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
+ expect(findRelatedIssuesBlock().props('isFormVisible')).toBe(false);
+ expect(findRelatedIssuesBlock().props('inputValue')).toBe('');
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toHaveLength(0);
});
});
- describe('onInput', () => {
- beforeEach(() => createComponent());
-
- it('fill in issue number reference and adds to pending related issues', () => {
+ describe('when "addIssuableFormInput" event is emitted', () => {
+ it('updates pending references with issue reference', async () => {
const input = '#123 ';
- wrapper.vm.onInput({
+ createComponent();
+
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
untouchedRawReferences: [input.trim()],
touchedReference: input,
});
+ await nextTick();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123');
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toEqual([input.trim()]);
});
- it('fill in with full reference', () => {
+ it('updates pending references with full reference', async () => {
const input = 'asdf/qwer#444 ';
- wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input });
+ createComponent();
+
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
+ untouchedRawReferences: [input.trim()],
+ touchedReference: input,
+ });
+ await nextTick();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444');
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toEqual([input.trim()]);
});
- it('fill in with issue link', () => {
+ it('updates pending references with issue link', async () => {
const link = 'http://localhost:3000/foo/bar/issues/111';
const input = `${link} `;
- wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input });
+ createComponent();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual(link);
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
+ untouchedRawReferences: [input.trim()],
+ touchedReference: input,
+ });
+ await nextTick();
+
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toEqual([link]);
});
- it('fill in with multiple references', () => {
+ it('updates pending references with multiple references', async () => {
const input = 'asdf/qwer#444 #12 ';
- wrapper.vm.onInput({
+ createComponent();
+
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
untouchedRawReferences: input.trim().split(/\s/),
touchedReference: '2',
});
+ await nextTick();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444');
- expect(wrapper.vm.state.pendingReferences[1]).toEqual('#12');
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toEqual([
+ 'asdf/qwer#444',
+ '#12',
+ ]);
});
- it('fill in with some invalid things', () => {
+ it('updates pending references with invalid values', async () => {
const input = 'something random ';
- wrapper.vm.onInput({
+ createComponent();
+
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
untouchedRawReferences: input.trim().split(/\s/),
touchedReference: '2',
});
+ await nextTick();
- expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('something');
- expect(wrapper.vm.state.pendingReferences[1]).toEqual('random');
+ expect(findRelatedIssuesBlock().props('pendingReferences')).toEqual([
+ 'something',
+ 'random',
+ ]);
});
- it.each`
- pathIdSeparator
- ${'#'}
- ${'&'}
- `(
- 'prepends $pathIdSeparator when user enters a numeric value [0-9]',
- async ({ pathIdSeparator }) => {
+ it.each(['#', '&'])(
+ 'prepends %s when user enters a numeric value [0-9]',
+ async (pathIdSeparator) => {
const input = '23';
+ createComponent({ props: { pathIdSeparator } });
- await wrapper.setProps({
- pathIdSeparator,
- });
-
- wrapper.vm.onInput({
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormInput', {
untouchedRawReferences: input.trim().split(/\s/),
touchedReference: input,
});
+ await nextTick();
- expect(wrapper.vm.inputValue).toBe(`${pathIdSeparator}${input}`);
+ expect(findRelatedIssuesBlock().props('inputValue')).toBe(`${pathIdSeparator}${input}`);
},
);
-
- it('prepends # when user enters a number', async () => {
- const input = 23;
-
- wrapper.vm.onInput({
- untouchedRawReferences: String(input).trim().split(/\s/),
- touchedReference: input,
- });
-
- expect(wrapper.vm.inputValue).toBe(`#${input}`);
- });
});
- describe('onBlur', () => {
- beforeEach(() =>
- createComponent().then(() => {
- jest.spyOn(wrapper.vm, 'processAllReferences').mockImplementation(() => {});
- }),
- );
-
- it('add any references to pending when blurring', () => {
- const input = '#123';
-
- wrapper.vm.onBlur(input);
-
- expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input);
+ describe('when "addIssuableFormBlur" event is emitted', () => {
+ beforeEach(() => {
+ createComponent();
+ jest.spyOn(wrapper.vm, 'processAllReferences').mockImplementation(() => {});
});
- });
-
- describe('processAllReferences', () => {
- beforeEach(() => createComponent());
- it('add valid reference to pending', () => {
+ it('adds any references to pending when blurring', () => {
const input = '#123';
- wrapper.vm.processAllReferences(input);
- expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123');
- });
+ findRelatedIssuesBlock().vm.$emit('addIssuableFormBlur', input);
- it('add any valid references to pending', () => {
- const input = 'asdf #123';
- wrapper.vm.processAllReferences(input);
-
- expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
- expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf');
- expect(wrapper.vm.state.pendingReferences[1]).toEqual('#123');
+ expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input);
});
});
});
diff --git a/spec/frontend/issues/list/components/issues_list_app_spec.js b/spec/frontend/issues/list/components/issues_list_app_spec.js
index 3d3dbfa6853..a39853fd29c 100644
--- a/spec/frontend/issues/list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues/list/components/issues_list_app_spec.js
@@ -52,6 +52,12 @@ import { getSortKey, getSortOptions } from '~/issues/list/utils';
import axios from '~/lib/utils/axios_utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
import { joinPaths } from '~/lib/utils/url_utility';
+import {
+ WORK_ITEM_TYPE_ENUM_INCIDENT,
+ WORK_ITEM_TYPE_ENUM_ISSUE,
+ WORK_ITEM_TYPE_ENUM_TASK,
+ WORK_ITEM_TYPE_ENUM_TEST_CASE,
+} from '~/work_items/constants';
jest.mock('@sentry/browser');
jest.mock('~/flash');
@@ -123,6 +129,7 @@ describe('CE IssuesListApp component', () => {
const mountComponent = ({
provide = {},
data = {},
+ workItems = false,
issuesQueryResponse = mockIssuesQueryResponse,
issuesCountsQueryResponse = mockIssuesCountsQueryResponse,
sortPreferenceMutationResponse = jest.fn().mockResolvedValue(setSortPreferenceMutationResponse),
@@ -141,6 +148,9 @@ describe('CE IssuesListApp component', () => {
apolloProvider: createMockApollo(requestHandlers),
router,
provide: {
+ glFeatures: {
+ workItems,
+ },
...defaultProvide,
...provide,
},
@@ -168,22 +178,6 @@ describe('CE IssuesListApp component', () => {
return waitForPromises();
});
- it('queries list with types `ISSUE` and `INCIDENT', () => {
- const expectedTypes = ['ISSUE', 'INCIDENT', 'TEST_CASE'];
-
- expect(mockIssuesQueryResponse).toHaveBeenCalledWith(
- expect.objectContaining({
- types: expectedTypes,
- }),
- );
-
- expect(mockIssuesCountsQueryResponse).toHaveBeenCalledWith(
- expect.objectContaining({
- types: expectedTypes,
- }),
- );
- });
-
it('renders', () => {
expect(findIssuableList().props()).toMatchObject({
namespace: defaultProvide.fullPath,
@@ -1024,6 +1018,21 @@ describe('CE IssuesListApp component', () => {
});
});
});
+
+ describe('when "page-size-change" event is emitted by IssuableList', () => {
+ it('updates url params with new page size', async () => {
+ wrapper = mountComponent();
+ router.push = jest.fn();
+
+ findIssuableList().vm.$emit('page-size-change', 50);
+ await nextTick();
+
+ expect(router.push).toHaveBeenCalledTimes(1);
+ expect(router.push).toHaveBeenCalledWith({
+ query: expect.objectContaining({ first_page_size: 50 }),
+ });
+ });
+ });
});
describe('public visibility', () => {
@@ -1045,17 +1054,45 @@ describe('CE IssuesListApp component', () => {
});
});
- describe('when "page-size-change" event is emitted by IssuableList', () => {
- it('updates url params with new page size', async () => {
- wrapper = mountComponent();
- router.push = jest.fn();
+ describe('fetching issues', () => {
+ describe('when work_items feature flag is disabled', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ workItems: false });
+ jest.runOnlyPendingTimers();
+ });
- findIssuableList().vm.$emit('page-size-change', 50);
- await nextTick();
+ it('fetches issue, incident, and test case types', () => {
+ const types = [
+ WORK_ITEM_TYPE_ENUM_ISSUE,
+ WORK_ITEM_TYPE_ENUM_INCIDENT,
+ WORK_ITEM_TYPE_ENUM_TEST_CASE,
+ ];
- expect(router.push).toHaveBeenCalledTimes(1);
- expect(router.push).toHaveBeenCalledWith({
- query: expect.objectContaining({ first_page_size: 50 }),
+ expect(mockIssuesQueryResponse).toHaveBeenCalledWith(expect.objectContaining({ types }));
+ expect(mockIssuesCountsQueryResponse).toHaveBeenCalledWith(
+ expect.objectContaining({ types }),
+ );
+ });
+ });
+
+ describe('when work_items feature flag is enabled', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({ workItems: true });
+ jest.runOnlyPendingTimers();
+ });
+
+ it('fetches issue, incident, test case, and task types', () => {
+ const types = [
+ WORK_ITEM_TYPE_ENUM_ISSUE,
+ WORK_ITEM_TYPE_ENUM_INCIDENT,
+ WORK_ITEM_TYPE_ENUM_TEST_CASE,
+ WORK_ITEM_TYPE_ENUM_TASK,
+ ];
+
+ expect(mockIssuesQueryResponse).toHaveBeenCalledWith(expect.objectContaining({ types }));
+ expect(mockIssuesCountsQueryResponse).toHaveBeenCalledWith(
+ expect.objectContaining({ types }),
+ );
});
});
});
diff --git a/spec/frontend/issues/list/mock_data.js b/spec/frontend/issues/list/mock_data.js
index 4347c580a4d..42e9d348b16 100644
--- a/spec/frontend/issues/list/mock_data.js
+++ b/spec/frontend/issues/list/mock_data.js
@@ -37,6 +37,7 @@ export const getIssuesQueryResponse = {
userDiscussionsCount: 4,
webPath: 'project/-/issues/789',
webUrl: 'project/-/issues/789',
+ type: 'issue',
assignees: {
nodes: [
{
diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js
index 27604b8ccf3..12f9707da04 100644
--- a/spec/frontend/issues/show/components/app_spec.js
+++ b/spec/frontend/issues/show/components/app_spec.js
@@ -119,7 +119,7 @@ describe('Issuable output', () => {
expect(findEdited().exists()).toBe(true);
expect(findEdited().props('updatedByPath')).toMatch(/\/some_user$/);
- expect(findEdited().props('updatedAt')).toBeTruthy();
+ expect(findEdited().props('updatedAt')).toBe(initialRequest.updated_at);
expect(wrapper.vm.state.lock_version).toBe(initialRequest.lock_version);
})
.then(() => {
@@ -133,7 +133,7 @@ describe('Issuable output', () => {
expect(findEdited().exists()).toBe(true);
expect(findEdited().props('updatedByName')).toBe('Other User');
expect(findEdited().props('updatedByPath')).toMatch(/\/other_user$/);
- expect(findEdited().props('updatedAt')).toBeTruthy();
+ expect(findEdited().props('updatedAt')).toBe(secondRequest.updated_at);
});
});
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
index 8ee57f97754..bdb1448148e 100644
--- a/spec/frontend/issues/show/components/description_spec.js
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -249,7 +249,7 @@ describe('Description component', () => {
await nextTick();
expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
- '1/1 task',
+ '1/1 checklist item',
);
});
@@ -266,7 +266,7 @@ describe('Description component', () => {
});
});
- describe('with work items feature flag is enabled', () => {
+ describe('with work_items_create_from_markdown feature flag enabled', () => {
describe('empty description', () => {
beforeEach(() => {
createComponent({
@@ -275,7 +275,7 @@ describe('Description component', () => {
},
provide: {
glFeatures: {
- workItems: true,
+ workItemsCreateFromMarkdown: true,
},
},
});
@@ -295,7 +295,7 @@ describe('Description component', () => {
},
provide: {
glFeatures: {
- workItems: true,
+ workItemsCreateFromMarkdown: true,
},
},
});
@@ -344,7 +344,7 @@ describe('Description component', () => {
descriptionHtml: descriptionHtmlWithTask,
},
provide: {
- glFeatures: { workItems: true },
+ glFeatures: { workItemsCreateFromMarkdown: true },
},
});
return nextTick();
@@ -406,7 +406,7 @@ describe('Description component', () => {
createComponent({
props: { descriptionHtml: descriptionHtmlWithTask },
- provide: { glFeatures: { workItems: true } },
+ provide: { glFeatures: { workItemsCreateFromMarkdown: true } },
});
expect(showDetailsModal).toHaveBeenCalledTimes(modalOpened);
@@ -422,7 +422,7 @@ describe('Description component', () => {
descriptionHtml: descriptionHtmlWithTask,
},
provide: {
- glFeatures: { workItems: true },
+ glFeatures: { workItemsCreateFromMarkdown: true },
},
});
return nextTick();
diff --git a/spec/frontend/issues/show/components/edit_actions_spec.js b/spec/frontend/issues/show/components/edit_actions_spec.js
index 79368023d76..d58bf1be812 100644
--- a/spec/frontend/issues/show/components/edit_actions_spec.js
+++ b/spec/frontend/issues/show/components/edit_actions_spec.js
@@ -75,7 +75,7 @@ describe('Edit Actions component', () => {
it('renders all buttons as enabled', () => {
const buttons = findEditButtons().wrappers;
buttons.forEach((button) => {
- expect(button.attributes('disabled')).toBeFalsy();
+ expect(button.attributes('disabled')).toBeUndefined();
});
});
diff --git a/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js b/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
new file mode 100644
index 00000000000..3ab2bb3460b
--- /dev/null
+++ b/spec/frontend/issues/show/components/incidents/create_timeline_events_form_spec.js
@@ -0,0 +1,189 @@
+import VueApollo from 'vue-apollo';
+import Vue from 'vue';
+import { GlDatepicker } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import CreateTimelineEvent from '~/issues/show/components/incidents/create_timeline_event.vue';
+import TimelineEventsForm from '~/issues/show/components/incidents/timeline_events_form.vue';
+import createTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/create_timeline_event.mutation.graphql';
+import getTimelineEvents from '~/issues/show/components/incidents/graphql/queries/get_timeline_events.query.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { createAlert } from '~/flash';
+import { useFakeDate } from 'helpers/fake_date';
+import {
+ timelineEventsCreateEventResponse,
+ timelineEventsCreateEventError,
+ mockGetTimelineData,
+} from './mock_data';
+
+Vue.use(VueApollo);
+
+jest.mock('~/flash');
+
+const fakeDate = '2020-07-08T00:00:00.000Z';
+
+const mockInputData = {
+ incidentId: 'gid://gitlab/Issue/1',
+ note: 'test',
+ occurredAt: '2020-07-08T00:00:00.000Z',
+};
+
+describe('Create Timeline events', () => {
+ useFakeDate(fakeDate);
+ let wrapper;
+ let responseSpy;
+ let apolloProvider;
+
+ const findSubmitButton = () => wrapper.findByText(__('Save'));
+ const findSubmitAndAddButton = () =>
+ wrapper.findByText(s__('Incident|Save and add another event'));
+ const findCancelButton = () => wrapper.findByText(__('Cancel'));
+ const findDatePicker = () => wrapper.findComponent(GlDatepicker);
+ const findNoteInput = () => wrapper.findByTestId('input-note');
+ const setNoteInput = () => {
+ const textarea = findNoteInput().element;
+ textarea.value = mockInputData.note;
+ textarea.dispatchEvent(new Event('input'));
+ };
+ const findHourInput = () => wrapper.findByTestId('input-hours');
+ const findMinuteInput = () => wrapper.findByTestId('input-minutes');
+ const setDatetime = () => {
+ const inputDate = new Date(mockInputData.occurredAt);
+ findDatePicker().vm.$emit('input', inputDate);
+ findHourInput().vm.$emit('input', inputDate.getHours());
+ findMinuteInput().vm.$emit('input', inputDate.getMinutes());
+ };
+ const fillForm = () => {
+ setDatetime();
+ setNoteInput();
+ };
+
+ function createMockApolloProvider() {
+ const requestHandlers = [[createTimelineEventMutation, responseSpy]];
+ const mockApollo = createMockApollo(requestHandlers);
+
+ mockApollo.clients.defaultClient.cache.writeQuery({
+ query: getTimelineEvents,
+ data: mockGetTimelineData,
+ variables: {
+ fullPath: 'group/project',
+ incidentId: 'gid://gitlab/Issue/1',
+ },
+ });
+
+ return mockApollo;
+ }
+
+ const mountComponent = () => {
+ wrapper = mountExtended(CreateTimelineEvent, {
+ propsData: {
+ hasTimelineEvents: true,
+ },
+ provide: {
+ fullPath: 'group/project',
+ issuableId: '1',
+ },
+ apolloProvider,
+ });
+ };
+
+ beforeEach(() => {
+ responseSpy = jest.fn().mockResolvedValue(timelineEventsCreateEventResponse);
+ apolloProvider = createMockApolloProvider();
+ });
+
+ afterEach(() => {
+ createAlert.mockReset();
+ wrapper.destroy();
+ });
+
+ describe('createIncidentTimelineEvent', () => {
+ const closeFormEvent = { 'hide-new-timeline-events-form': [[]] };
+
+ const expectedData = {
+ input: mockInputData,
+ };
+
+ beforeEach(() => {
+ mountComponent();
+ fillForm();
+ });
+
+ describe('on submit', () => {
+ beforeEach(async () => {
+ findSubmitButton().trigger('click');
+ await waitForPromises();
+ });
+
+ it('should call the mutation with the right variables', () => {
+ expect(responseSpy).toHaveBeenCalledWith(expectedData);
+ });
+
+ it('should close the form on successful addition', () => {
+ expect(wrapper.emitted()).toEqual(closeFormEvent);
+ });
+ });
+
+ describe('on submit and add', () => {
+ beforeEach(async () => {
+ findSubmitAndAddButton().trigger('click');
+ await waitForPromises();
+ });
+
+ it('should keep the form open for save and add another', () => {
+ expect(wrapper.emitted()).toEqual({});
+ });
+ });
+
+ describe('on cancel', () => {
+ beforeEach(async () => {
+ findCancelButton().trigger('click');
+ await waitForPromises();
+ });
+
+ it('should close the form', () => {
+ expect(wrapper.emitted()).toEqual(closeFormEvent);
+ });
+ });
+ });
+
+ describe('error handling', () => {
+ it('should show an error when submission returns an error', async () => {
+ const expectedAlertArgs = {
+ message: `Error creating incident timeline event: ${timelineEventsCreateEventError.data.timelineEventCreate.errors[0]}`,
+ };
+ responseSpy.mockResolvedValueOnce(timelineEventsCreateEventError);
+ mountComponent();
+
+ findSubmitButton().trigger('click');
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
+ });
+
+ it('should show an error when submission fails', async () => {
+ const expectedAlertArgs = {
+ captureError: true,
+ error: new Error(),
+ message: 'Something went wrong while creating the incident timeline event.',
+ };
+ responseSpy.mockRejectedValueOnce();
+ mountComponent();
+
+ findSubmitButton().trigger('click');
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
+ });
+
+ it('should keep the form open on failed addition', async () => {
+ responseSpy.mockResolvedValueOnce(timelineEventsCreateEventError);
+ mountComponent();
+
+ await wrapper.findComponent(TimelineEventsForm).vm.$emit('save-event', mockInputData);
+ await waitForPromises;
+ expect(wrapper.emitted()).toEqual({});
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/incidents/mock_data.js b/spec/frontend/issues/show/components/incidents/mock_data.js
index afc6099caf4..75c0a7350ae 100644
--- a/spec/frontend/issues/show/components/incidents/mock_data.js
+++ b/spec/frontend/issues/show/components/incidents/mock_data.js
@@ -72,10 +72,14 @@ export const timelineEventsQueryEmptyResponse = {
};
export const timelineEventsCreateEventResponse = {
- timelineEvent: {
- ...mockEvents[0],
+ data: {
+ timelineEventCreate: {
+ timelineEvent: {
+ ...mockEvents[0],
+ },
+ errors: [],
+ },
},
- errors: [],
};
export const timelineEventsCreateEventError = {
@@ -103,3 +107,21 @@ const timelineEventDeleteData = (errors = []) => {
export const timelineEventsDeleteEventResponse = timelineEventDeleteData();
export const timelineEventsDeleteEventError = timelineEventDeleteData(['Item does not exist']);
+
+export const mockGetTimelineData = {
+ project: {
+ id: 'gid://gitlab/Project/19',
+ incidentManagementTimelineEvents: {
+ nodes: [
+ {
+ id: 'gid://gitlab/IncidentManagement::TimelineEvent/8',
+ note: 'another one2',
+ noteHtml: '<p>another one2</p>',
+ action: 'comment',
+ occurredAt: '2022-07-01T12:47:00Z',
+ createdAt: '2022-07-20T12:47:40Z',
+ },
+ ],
+ },
+ },
+};
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 620cdfc53b0..cd2cbb63246 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
@@ -3,49 +3,33 @@ import Vue, { nextTick } from 'vue';
import { GlDatepicker } from '@gitlab/ui';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import IncidentTimelineEventForm from '~/issues/show/components/incidents/timeline_events_form.vue';
-import createTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/create_timeline_event.mutation.graphql';
-import createMockApollo from 'helpers/mock_apollo_helper';
+import TimelineEventsForm from '~/issues/show/components/incidents/timeline_events_form.vue';
import { createAlert } from '~/flash';
import { useFakeDate } from 'helpers/fake_date';
-import { timelineEventsCreateEventResponse, timelineEventsCreateEventError } from './mock_data';
Vue.use(VueApollo);
jest.mock('~/flash');
-const addEventResponse = jest.fn().mockResolvedValue(timelineEventsCreateEventResponse);
-
-function createMockApolloProvider(response = addEventResponse) {
- const requestHandlers = [[createTimelineEventMutation, response]];
- return createMockApollo(requestHandlers);
-}
+const fakeDate = '2020-07-08T00:00:00.000Z';
describe('Timeline events form', () => {
// July 8 2020
- useFakeDate(2020, 6, 8);
+ useFakeDate(fakeDate);
let wrapper;
- const mountComponent = ({ mockApollo, mountMethod = shallowMountExtended, stubs }) => {
- wrapper = mountMethod(IncidentTimelineEventForm, {
+ const mountComponent = ({ mountMethod = shallowMountExtended }) => {
+ wrapper = mountMethod(TimelineEventsForm, {
propsData: {
hasTimelineEvents: true,
+ isEventProcessed: false,
},
- provide: {
- fullPath: 'group/project',
- issuableId: '1',
- },
- apolloProvider: mockApollo,
- stubs,
});
};
afterEach(() => {
- addEventResponse.mockReset();
createAlert.mockReset();
- if (wrapper) {
- wrapper.destroy();
- }
+ wrapper.destroy();
});
const findSubmitButton = () => wrapper.findByText('Save');
@@ -75,24 +59,28 @@ describe('Timeline events form', () => {
};
describe('form button behaviour', () => {
- const closeFormEvent = { 'hide-incident-timeline-event-form': [[]] };
beforeEach(() => {
- mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
+ mountComponent({ mountMethod: mountExtended });
});
- it('should close the form on submit', async () => {
+ it('should save event on submit', async () => {
await submitForm();
- expect(wrapper.emitted()).toEqual(closeFormEvent);
+
+ expect(wrapper.emitted()).toEqual({
+ 'save-event': [[{ note: '', occurredAt: fakeDate }, false]],
+ });
});
- it('should not close the form on "submit and add another"', async () => {
+ it('should save event on "submit and add another"', async () => {
await submitFormAndAddAnother();
- expect(wrapper.emitted()).toEqual({});
+ expect(wrapper.emitted()).toEqual({
+ 'save-event': [[{ note: '', occurredAt: fakeDate }, true]],
+ });
});
- it('should close the form on cancel', async () => {
+ it('should emit cancel on cancel', async () => {
await cancelForm();
- expect(wrapper.emitted()).toEqual(closeFormEvent);
+ expect(wrapper.emitted()).toEqual({ cancel: [[]] });
});
it('should clear the form', async () => {
@@ -111,71 +99,4 @@ describe('Timeline events form', () => {
expect(findMinuteInput().element.value).toBe('0');
});
});
-
- describe('addTimelineEventQuery', () => {
- const expectedData = {
- input: {
- incidentId: 'gid://gitlab/Issue/1',
- note: '',
- occurredAt: '2020-07-08T00:00:00.000Z',
- },
- };
-
- let mockApollo;
-
- beforeEach(() => {
- mockApollo = createMockApolloProvider();
- mountComponent({ mockApollo, mountMethod: mountExtended });
- });
-
- it('should call the mutation with the right variables', async () => {
- await submitForm();
-
- expect(addEventResponse).toHaveBeenCalledWith(expectedData);
- });
-
- it('should call the mutation with user selected variables', async () => {
- const expectedUserSelectedData = {
- input: {
- ...expectedData.input,
- occurredAt: '2021-08-12T05:45:00.000Z',
- },
- };
-
- setDatetime();
-
- await nextTick();
- await submitForm();
-
- expect(addEventResponse).toHaveBeenCalledWith(expectedUserSelectedData);
- });
- });
-
- describe('error handling', () => {
- it('should show an error when submission returns an error', async () => {
- const expectedAlertArgs = {
- message: 'Error creating incident timeline event: Create error',
- };
- addEventResponse.mockResolvedValueOnce(timelineEventsCreateEventError);
- mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
-
- await submitForm();
-
- expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
- });
-
- it('should show an error when submission fails', async () => {
- const expectedAlertArgs = {
- captureError: true,
- error: new Error(),
- message: 'Something went wrong while creating the incident timeline event.',
- };
- addEventResponse.mockRejectedValueOnce();
- mountComponent({ mockApollo: createMockApolloProvider(), mountMethod: mountExtended });
-
- await submitForm();
-
- expect(createAlert).toHaveBeenCalledWith(expectedAlertArgs);
- });
- });
});
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_item_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_item_spec.js
new file mode 100644
index 00000000000..90e55003ab3
--- /dev/null
+++ b/spec/frontend/issues/show/components/incidents/timeline_events_item_spec.js
@@ -0,0 +1,116 @@
+import timezoneMock from 'timezone-mock';
+import { GlIcon, GlDropdown } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import IncidentTimelineEventItem from '~/issues/show/components/incidents/timeline_events_item.vue';
+import { mockEvents } from './mock_data';
+
+describe('IncidentTimelineEventList', () => {
+ let wrapper;
+
+ const mountComponent = ({ propsData, provide } = {}) => {
+ const { action, noteHtml, occurredAt } = mockEvents[0];
+ wrapper = mountExtended(IncidentTimelineEventItem, {
+ propsData: {
+ action,
+ noteHtml,
+ occurredAt,
+ isLastItem: false,
+ ...propsData,
+ },
+ provide: {
+ canUpdate: false,
+ ...provide,
+ },
+ });
+ };
+
+ const findCommentIcon = () => wrapper.findComponent(GlIcon);
+ const findTextContainer = () => wrapper.findByTestId('event-text-container');
+ const findEventTime = () => wrapper.findByTestId('event-time');
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDeleteButton = () => wrapper.findByText('Delete');
+
+ describe('template', () => {
+ it('shows comment icon', () => {
+ mountComponent();
+
+ expect(findCommentIcon().exists()).toBe(true);
+ });
+
+ it('sets correct props for icon', () => {
+ mountComponent();
+
+ expect(findCommentIcon().props('name')).toBe(mockEvents[0].action);
+ });
+
+ it('displays the correct time', () => {
+ mountComponent();
+
+ expect(findEventTime().text()).toBe('15:59 UTC');
+ });
+
+ describe('last item in list', () => {
+ it('shows a bottom border when not the last item', () => {
+ mountComponent();
+
+ expect(findTextContainer().classes()).toContain('gl-border-1');
+ });
+
+ it('does not show a bottom border when the last item', () => {
+ mountComponent({ propsData: { isLastItem: true } });
+
+ expect(wrapper.classes()).not.toContain('gl-border-1');
+ });
+ });
+
+ describe.each`
+ timezone
+ ${'Europe/London'}
+ ${'US/Pacific'}
+ ${'Australia/Adelaide'}
+ `('when viewing in timezone', ({ timezone }) => {
+ describe(timezone, () => {
+ beforeEach(() => {
+ timezoneMock.register(timezone);
+
+ mountComponent();
+ });
+
+ afterEach(() => {
+ timezoneMock.unregister();
+ });
+
+ it('displays the correct time', () => {
+ expect(findEventTime().text()).toBe('15:59 UTC');
+ });
+ });
+ });
+
+ describe('action dropdown', () => {
+ it('does not show the action dropdown by default', () => {
+ mountComponent();
+
+ expect(findDropdown().exists()).toBe(false);
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ it('shows dropdown and delete item when user has update permission', () => {
+ mountComponent({ provide: { canUpdate: true } });
+
+ expect(findDropdown().exists()).toBe(true);
+ expect(findDeleteButton().exists()).toBe(true);
+ });
+
+ it('triggers a delete when the delete button is clicked', async () => {
+ mountComponent({ provide: { canUpdate: true } });
+
+ findDeleteButton().trigger('click');
+
+ await nextTick();
+
+ expect(wrapper.emitted().delete).toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_list_item_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_list_item_spec.js
deleted file mode 100644
index e686f2eb4ec..00000000000
--- a/spec/frontend/issues/show/components/incidents/timeline_events_list_item_spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import timezoneMock from 'timezone-mock';
-import { GlIcon, GlDropdown } from '@gitlab/ui';
-import { nextTick } from 'vue';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import IncidentTimelineEventListItem from '~/issues/show/components/incidents/timeline_events_list_item.vue';
-import { mockEvents } from './mock_data';
-
-describe('IncidentTimelineEventList', () => {
- let wrapper;
-
- const mountComponent = ({ propsData, provide } = {}) => {
- const { action, noteHtml, occurredAt } = mockEvents[0];
- wrapper = mountExtended(IncidentTimelineEventListItem, {
- propsData: {
- action,
- noteHtml,
- occurredAt,
- isLastItem: false,
- ...propsData,
- },
- provide: {
- canUpdate: false,
- ...provide,
- },
- });
- };
-
- const findCommentIcon = () => wrapper.findComponent(GlIcon);
- const findTextContainer = () => wrapper.findByTestId('event-text-container');
- const findEventTime = () => wrapper.findByTestId('event-time');
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDeleteButton = () => wrapper.findByText('Delete');
-
- describe('template', () => {
- it('shows comment icon', () => {
- mountComponent();
-
- expect(findCommentIcon().exists()).toBe(true);
- });
-
- it('sets correct props for icon', () => {
- mountComponent();
-
- expect(findCommentIcon().props('name')).toBe(mockEvents[0].action);
- });
-
- it('displays the correct time', () => {
- mountComponent();
-
- expect(findEventTime().text()).toBe('15:59 UTC');
- });
-
- describe('last item in list', () => {
- it('shows a bottom border when not the last item', () => {
- mountComponent();
-
- expect(findTextContainer().classes()).toContain('gl-border-1');
- });
-
- it('does not show a bottom border when the last item', () => {
- mountComponent({ propsData: { isLastItem: true } });
-
- expect(wrapper.classes()).not.toContain('gl-border-1');
- });
- });
-
- describe.each`
- timezone
- ${'Europe/London'}
- ${'US/Pacific'}
- ${'Australia/Adelaide'}
- `('when viewing in timezone', ({ timezone }) => {
- describe(timezone, () => {
- beforeEach(() => {
- timezoneMock.register(timezone);
-
- mountComponent();
- });
-
- afterEach(() => {
- timezoneMock.unregister();
- });
-
- it('displays the correct time', () => {
- expect(findEventTime().text()).toBe('15:59 UTC');
- });
- });
- });
-
- describe('action dropdown', () => {
- it('does not show the action dropdown by default', () => {
- mountComponent();
-
- expect(findDropdown().exists()).toBe(false);
- expect(findDeleteButton().exists()).toBe(false);
- });
-
- it('shows dropdown and delete item when user has update permission', () => {
- mountComponent({ provide: { canUpdate: true } });
-
- expect(findDropdown().exists()).toBe(true);
- expect(findDeleteButton().exists()).toBe(true);
- });
-
- it('triggers a delete when the delete button is clicked', async () => {
- mountComponent({ provide: { canUpdate: true } });
-
- findDeleteButton().trigger('click');
-
- await nextTick();
-
- expect(wrapper.emitted().delete).toBeTruthy();
- });
- });
- });
-});
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js
index ae07237cf7d..4d2d53c990e 100644
--- a/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js
+++ b/spec/frontend/issues/show/components/incidents/timeline_events_list_spec.js
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import IncidentTimelineEventList from '~/issues/show/components/incidents/timeline_events_list.vue';
-import IncidentTimelineEventListItem from '~/issues/show/components/incidents/timeline_events_list_item.vue';
+import IncidentTimelineEventListItem from '~/issues/show/components/incidents/timeline_events_item.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import deleteTimelineEventMutation from '~/issues/show/components/incidents/graphql/queries/delete_timeline_event.mutation.graphql';
diff --git a/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js b/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js
index 2d87851a761..2cdb971395d 100644
--- a/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js
+++ b/spec/frontend/issues/show/components/incidents/timeline_events_tab_spec.js
@@ -5,7 +5,7 @@ import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_help
import waitForPromises from 'helpers/wait_for_promises';
import TimelineEventsTab from '~/issues/show/components/incidents/timeline_events_tab.vue';
import IncidentTimelineEventsList from '~/issues/show/components/incidents/timeline_events_list.vue';
-import IncidentTimelineEventForm from '~/issues/show/components/incidents/timeline_events_form.vue';
+import CreateTimelineEvent from '~/issues/show/components/incidents/create_timeline_event.vue';
import timelineEventsQuery from '~/issues/show/components/incidents/graphql/queries/get_timeline_events.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createAlert } from '~/flash';
@@ -53,7 +53,7 @@ describe('TimelineEventsTab', () => {
const findLoadingSpinner = () => wrapper.findComponent(GlLoadingIcon);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findTimelineEventsList = () => wrapper.findComponent(IncidentTimelineEventsList);
- const findTimelineEventForm = () => wrapper.findComponent(IncidentTimelineEventForm);
+ const findCreateTimelineEvent = () => wrapper.findComponent(CreateTimelineEvent);
const findAddEventButton = () => wrapper.findByText(timelineTabI18n.addEventButton);
describe('Timeline events tab', () => {
@@ -143,18 +143,18 @@ describe('TimelineEventsTab', () => {
});
it('should not show a form by default', () => {
- expect(findTimelineEventForm().isVisible()).toBe(false);
+ expect(findCreateTimelineEvent().isVisible()).toBe(false);
});
it('should show a form when button is clicked', async () => {
await findAddEventButton().trigger('click');
- expect(findTimelineEventForm().isVisible()).toBe(true);
+ expect(findCreateTimelineEvent().isVisible()).toBe(true);
});
it('should clear the form when button is clicked', async () => {
const mockClear = jest.fn();
- wrapper.vm.$refs.eventForm.clear = mockClear;
+ wrapper.vm.$refs.createEventForm.clearForm = mockClear;
await findAddEventButton().trigger('click');
@@ -165,9 +165,9 @@ describe('TimelineEventsTab', () => {
// open the form
await findAddEventButton().trigger('click');
- await findTimelineEventForm().vm.$emit('hide-incident-timeline-event-form');
+ await findCreateTimelineEvent().vm.$emit('hide-new-timeline-events-form');
- expect(findTimelineEventForm().isVisible()).toBe(false);
+ expect(findCreateTimelineEvent().isVisible()).toBe(false);
});
});
});
diff --git a/spec/frontend/issues/show/components/incidents/utils_spec.js b/spec/frontend/issues/show/components/incidents/utils_spec.js
index 0da0114c654..d3a86680f14 100644
--- a/spec/frontend/issues/show/components/incidents/utils_spec.js
+++ b/spec/frontend/issues/show/components/incidents/utils_spec.js
@@ -24,7 +24,7 @@ describe('incident utils', () => {
describe('get event icon', () => {
it('should display a matching event icon name', () => {
- ['comment', 'issues', 'status'].forEach((name) => {
+ ['comment', 'issues', 'label', 'status'].forEach((name) => {
expect(getEventIcon(name)).toBe(name);
});
});
diff --git a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
index 136a5967ee4..b0218a9df12 100644
--- a/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
+++ b/spec/frontend/jira_connect/branches/components/project_dropdown_spec.js
@@ -148,7 +148,7 @@ describe('ProjectDropdown', () => {
});
it('emits `error` event', () => {
- expect(wrapper.emitted('error')).toBeTruthy();
+ expect(wrapper.emitted('error')).toHaveLength(1);
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js
index 5ec1b7b7932..9f92ad2adc1 100644
--- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js
@@ -38,7 +38,6 @@ describe('AddNamespaceButton', () => {
it('button is bound to the modal', () => {
const { value } = getBinding(findButton().element, 'gl-modal');
- expect(value).toBeTruthy();
expect(value).toBe(ADD_NAMESPACE_MODAL_ID);
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js
index 8f79c74368f..ed0abaaf576 100644
--- a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js
@@ -128,7 +128,7 @@ describe('SignInOauthButton', () => {
});
it('does not emit `sign-in` event', () => {
- expect(wrapper.emitted('sign-in')).toBeFalsy();
+ expect(wrapper.emitted('sign-in')).toBeUndefined();
});
it('sets `loading` prop of button to `false`', () => {
@@ -179,7 +179,7 @@ describe('SignInOauthButton', () => {
});
it('emits `sign-in` event with user data', () => {
- expect(wrapper.emitted('sign-in')[0]).toBeTruthy();
+ expect(wrapper.emitted('sign-in')).toHaveLength(1);
});
});
@@ -200,7 +200,7 @@ describe('SignInOauthButton', () => {
});
it('does not emit `sign-in` event', () => {
- expect(wrapper.emitted('sign-in')).toBeFalsy();
+ expect(wrapper.emitted('sign-in')).toBeUndefined();
});
it('sets `loading` prop of button to `false`', () => {
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
index 65b08fba592..c12a45b2f41 100644
--- a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
@@ -68,7 +68,7 @@ describe('SignInPage', () => {
describe('when error event is emitted', () => {
it('emits another error event', () => {
findSignInGitlabCom().vm.$emit('error');
- expect(wrapper.emitted('error')[0]).toBeTruthy();
+ expect(wrapper.emitted('error')).toHaveLength(1);
});
});
diff --git a/spec/frontend/jobs/components/job_log_controllers_spec.js b/spec/frontend/jobs/components/job_log_controllers_spec.js
index cc97d111c06..aa85253a177 100644
--- a/spec/frontend/jobs/components/job_log_controllers_spec.js
+++ b/spec/frontend/jobs/components/job_log_controllers_spec.js
@@ -1,8 +1,9 @@
import { GlSearchBoxByClick } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
import JobLogControllers from '~/jobs/components/job_log_controllers.vue';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
+import { backoffMockImplementation } from 'helpers/backoff_helper';
+import * as commonUtils from '~/lib/utils/common_utils';
import { mockJobLog } from '../mock_data';
const mockToastShow = jest.fn();
@@ -10,10 +11,15 @@ const mockToastShow = jest.fn();
describe('Job log controllers', () => {
let wrapper;
+ beforeEach(() => {
+ jest.spyOn(commonUtils, 'backOff').mockImplementation(backoffMockImplementation);
+ });
+
afterEach(() => {
if (wrapper?.destroy) {
wrapper.destroy();
}
+ commonUtils.backOff.mockReset();
});
const defaultProps = {
@@ -24,10 +30,11 @@ describe('Job log controllers', () => {
isScrollBottomDisabled: false,
isScrollingDown: true,
isJobLogSizeVisible: true,
+ isComplete: true,
jobLog: mockJobLog,
};
- const createWrapper = (props, jobLogSearch = false) => {
+ const createWrapper = (props, { jobLogJumpToFailures = false } = {}) => {
wrapper = mount(JobLogControllers, {
propsData: {
...defaultProps,
@@ -35,7 +42,7 @@ describe('Job log controllers', () => {
},
provide: {
glFeatures: {
- jobLogSearch,
+ jobLogJumpToFailures,
},
},
data() {
@@ -58,6 +65,7 @@ describe('Job log controllers', () => {
const findScrollBottom = () => wrapper.find('[data-testid="job-controller-scroll-bottom"]');
const findJobLogSearch = () => wrapper.findComponent(GlSearchBoxByClick);
const findSearchHelp = () => wrapper.findComponent(HelpPopover);
+ const findScrollFailure = () => wrapper.find('[data-testid="job-controller-scroll-to-failure"]');
describe('Truncate information', () => {
describe('with isJobLogSizeVisible', () => {
@@ -109,9 +117,7 @@ describe('Job log controllers', () => {
});
it('emits scrollJobLogTop event on click', async () => {
- findScrollTop().trigger('click');
-
- await nextTick();
+ await findScrollTop().trigger('click');
expect(wrapper.emitted().scrollJobLogTop).toHaveLength(1);
});
@@ -131,9 +137,7 @@ describe('Job log controllers', () => {
});
it('does not emit scrollJobLogTop event on click', async () => {
- findScrollTop().trigger('click');
-
- await nextTick();
+ await findScrollTop().trigger('click');
expect(wrapper.emitted().scrollJobLogTop).toBeUndefined();
});
@@ -147,9 +151,7 @@ describe('Job log controllers', () => {
});
it('emits scrollJobLogBottom event on click', async () => {
- findScrollBottom().trigger('click');
-
- await nextTick();
+ await findScrollBottom().trigger('click');
expect(wrapper.emitted().scrollJobLogBottom).toHaveLength(1);
});
@@ -169,9 +171,7 @@ describe('Job log controllers', () => {
});
it('does not emit scrollJobLogBottom event on click', async () => {
- findScrollBottom().trigger('click');
-
- await nextTick();
+ await findScrollBottom().trigger('click');
expect(wrapper.emitted().scrollJobLogBottom).toBeUndefined();
});
@@ -201,41 +201,115 @@ describe('Job log controllers', () => {
});
});
});
- });
- describe('Job log search', () => {
- describe('with feature flag off', () => {
- it('does not display job log search', () => {
- createWrapper();
+ describe('scroll to failure button', () => {
+ describe('with feature flag disabled', () => {
+ it('does not display button', () => {
+ createWrapper();
- expect(findJobLogSearch().exists()).toBe(false);
- expect(findSearchHelp().exists()).toBe(false);
+ expect(findScrollFailure().exists()).toBe(false);
+ });
});
- });
- describe('with feature flag on', () => {
- beforeEach(() => {
- createWrapper({}, { jobLogSearch: true });
- });
+ describe('with red text failures on the page', () => {
+ let firstFailure;
+ let secondFailure;
+
+ beforeEach(() => {
+ jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce(['mock-element']);
+
+ createWrapper({}, { jobLogJumpToFailures: true });
+
+ firstFailure = document.createElement('div');
+ firstFailure.className = 'term-fg-l-red';
+ document.body.appendChild(firstFailure);
+
+ secondFailure = document.createElement('div');
+ secondFailure.className = 'term-fg-l-red';
+ document.body.appendChild(secondFailure);
+ });
+
+ afterEach(() => {
+ if (firstFailure) {
+ firstFailure.remove();
+ firstFailure = null;
+ }
+
+ if (secondFailure) {
+ secondFailure.remove();
+ secondFailure = null;
+ }
+ });
+
+ it('is enabled', () => {
+ expect(findScrollFailure().props('disabled')).toBe(false);
+ });
+
+ it('scrolls to each failure', async () => {
+ jest.spyOn(firstFailure, 'scrollIntoView');
- it('displays job log search', () => {
- expect(findJobLogSearch().exists()).toBe(true);
- expect(findSearchHelp().exists()).toBe(true);
+ await findScrollFailure().trigger('click');
+
+ expect(firstFailure.scrollIntoView).toHaveBeenCalled();
+
+ await findScrollFailure().trigger('click');
+
+ expect(secondFailure.scrollIntoView).toHaveBeenCalled();
+
+ await findScrollFailure().trigger('click');
+
+ expect(firstFailure.scrollIntoView).toHaveBeenCalled();
+ });
});
- it('emits search results', () => {
- const expectedSearchResults = [[[mockJobLog[6].lines[1], mockJobLog[6].lines[2]]]];
+ describe('with no red text failures on the page', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce([]);
- findJobLogSearch().vm.$emit('submit');
+ createWrapper({}, { jobLogJumpToFailures: true });
+ });
- expect(wrapper.emitted('searchResults')).toEqual(expectedSearchResults);
+ it('is disabled', () => {
+ expect(findScrollFailure().props('disabled')).toBe(true);
+ });
});
- it('clears search results', () => {
- findJobLogSearch().vm.$emit('clear');
+ describe('when the job log is not complete', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce(['mock-element']);
+
+ createWrapper({ isComplete: false }, { jobLogJumpToFailures: true });
+ });
- expect(wrapper.emitted('searchResults')).toEqual([[[]]]);
+ it('is enabled', () => {
+ expect(findScrollFailure().props('disabled')).toBe(false);
+ });
});
});
});
+
+ describe('Job log search', () => {
+ beforeEach(() => {
+ createWrapper();
+ });
+
+ it('displays job log search', () => {
+ expect(findJobLogSearch().exists()).toBe(true);
+ expect(findSearchHelp().exists()).toBe(true);
+ });
+
+ it('emits search results', () => {
+ const expectedSearchResults = [[[mockJobLog[6].lines[1], mockJobLog[6].lines[2]]]];
+
+ findJobLogSearch().vm.$emit('submit');
+
+ expect(wrapper.emitted('searchResults')).toEqual(expectedSearchResults);
+ });
+
+ it('clears search results', () => {
+ findJobLogSearch().vm.$emit('clear');
+
+ expect(wrapper.emitted('searchResults')).toEqual([[[]]]);
+ });
+ });
});
diff --git a/spec/frontend/jobs/components/sidebar_detail_row_spec.js b/spec/frontend/jobs/components/sidebar_detail_row_spec.js
index 43f2e022dd8..8d2680608ab 100644
--- a/spec/frontend/jobs/components/sidebar_detail_row_spec.js
+++ b/spec/frontend/jobs/components/sidebar_detail_row_spec.js
@@ -7,7 +7,7 @@ describe('Sidebar detail row', () => {
const title = 'this is the title';
const value = 'this is the value';
- const helpUrl = '/help/ci/runners/index.html';
+ const helpUrl = 'https://docs.gitlab.com/runner/register/index.html';
const findHelpLink = () => wrapper.findComponent(GlLink);
diff --git a/spec/frontend/labels/labels_select_spec.js b/spec/frontend/labels/labels_select_spec.js
index f6e280564cc..63f7c725bc7 100644
--- a/spec/frontend/labels/labels_select_spec.js
+++ b/spec/frontend/labels/labels_select_spec.js
@@ -101,6 +101,12 @@ describe('LabelsSelect', () => {
expect($labelEl.find('a').attr('data-html')).toBe('true');
});
+ it('generated label item template has correct title for tooltip', () => {
+ expect($labelEl.find('a').attr('title')).toBe(
+ "<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span><br>Foobar",
+ );
+ });
+
it('generated label item template has correct label styles and classes', () => {
expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
`background-color: ${label.color};`,
diff --git a/spec/frontend/lib/dompurify_spec.js b/spec/frontend/lib/dompurify_spec.js
index b585c69e911..29b927ef628 100644
--- a/spec/frontend/lib/dompurify_spec.js
+++ b/spec/frontend/lib/dompurify_spec.js
@@ -173,4 +173,50 @@ describe('~/lib/dompurify', () => {
expect(sanitize(html)).toBe(`<a>internal link</a>`);
});
});
+
+ describe('links with target attribute', () => {
+ const getSanitizedNode = (html) => {
+ return document.createRange().createContextualFragment(sanitize(html)).firstElementChild;
+ };
+
+ it('adds secure context', () => {
+ const html = `<a href="https://example.com" target="_blank">link</a>`;
+ const el = getSanitizedNode(html);
+
+ expect(el.getAttribute('target')).toBe('_blank');
+ expect(el.getAttribute('rel')).toBe('noopener noreferrer');
+ });
+
+ it('adds secure context and merge existing `rel` values', () => {
+ const html = `<a href="https://example.com" target="_blank" rel="help External">link</a>`;
+ const el = getSanitizedNode(html);
+
+ expect(el.getAttribute('target')).toBe('_blank');
+ expect(el.getAttribute('rel')).toBe('help external noopener noreferrer');
+ });
+
+ it('does not duplicate noopener/noreferrer `rel` values', () => {
+ const html = `<a href="https://example.com" target="_blank" rel="noreferrer noopener">link</a>`;
+ const el = getSanitizedNode(html);
+
+ expect(el.getAttribute('target')).toBe('_blank');
+ expect(el.getAttribute('rel')).toBe('noreferrer noopener');
+ });
+
+ it('does not update `rel` values when target is not `_blank` ', () => {
+ const html = `<a href="https://example.com" target="_self" rel="help">internal</a>`;
+ const el = getSanitizedNode(html);
+
+ expect(el.getAttribute('target')).toBe('_self');
+ expect(el.getAttribute('rel')).toBe('help');
+ });
+
+ it('does not update `rel` values when target attribute is not present', () => {
+ const html = `<a href="https://example.com">link</a>`;
+ const el = getSanitizedNode(html);
+
+ expect(el.hasAttribute('target')).toBe(false);
+ expect(el.hasAttribute('rel')).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/lib/gfm/index_spec.js b/spec/frontend/lib/gfm/index_spec.js
index b722315d63a..f53f809b799 100644
--- a/spec/frontend/lib/gfm/index_spec.js
+++ b/spec/frontend/lib/gfm/index_spec.js
@@ -96,26 +96,164 @@ describe('gfm', () => {
);
});
});
- });
- describe('when skipping the rendering of code blocks', () => {
- it('transforms code nodes into codeblock html tags', async () => {
- const result = await markdownToAST(
- `
+ describe('when skipping the rendering of code blocks', () => {
+ it('transforms code nodes into codeblock html tags', async () => {
+ const result = await markdownToAST(
+ `
\`\`\`javascript
console.log('Hola');
\`\`\`\
`,
- ['code'],
- );
+ ['code'],
+ );
+
+ expectInRoot(
+ result,
+ expect.objectContaining({
+ tagName: 'codeblock',
+ properties: {
+ language: 'javascript',
+ },
+ }),
+ );
+ });
+ });
+
+ describe('when skipping the rendering of reference definitions', () => {
+ it('transforms code nodes into codeblock html tags', async () => {
+ const result = await markdownToAST(
+ `
+[gitlab][gitlab]
+
+[gitlab]: https://gitlab.com "GitLab"
+ `,
+ ['definition'],
+ );
+
+ expectInRoot(
+ result,
+ expect.objectContaining({
+ type: 'element',
+ tagName: 'referencedefinition',
+ properties: {
+ identifier: 'gitlab',
+ title: 'GitLab',
+ url: 'https://gitlab.com',
+ },
+ children: [
+ {
+ type: 'text',
+ value: '[gitlab]: https://gitlab.com "GitLab"',
+ },
+ ],
+ }),
+ );
+ });
+ });
+
+ describe('when skipping the rendering of link and image references', () => {
+ it('transforms linkReference and imageReference nodes into html tags', async () => {
+ const result = await markdownToAST(
+ `
+[gitlab][gitlab] and ![GitLab Logo][gitlab-logo]
+
+[gitlab]: https://gitlab.com "GitLab"
+[gitlab-logo]: https://gitlab.com/gitlab-logo.png "GitLab Logo"
+ `,
+ ['linkReference', 'imageReference'],
+ );
+
+ expectInRoot(
+ result,
+ expect.objectContaining({
+ tagName: 'p',
+ children: expect.arrayContaining([
+ expect.objectContaining({
+ type: 'element',
+ tagName: 'a',
+ properties: expect.objectContaining({
+ href: 'https://gitlab.com',
+ isReference: 'true',
+ identifier: 'gitlab',
+ title: 'GitLab',
+ }),
+ }),
+ expect.objectContaining({
+ type: 'element',
+ tagName: 'img',
+ properties: expect.objectContaining({
+ src: 'https://gitlab.com/gitlab-logo.png',
+ isReference: 'true',
+ identifier: 'gitlab-logo',
+ title: 'GitLab Logo',
+ alt: 'GitLab Logo',
+ }),
+ }),
+ ]),
+ }),
+ );
+ });
+
+ it('normalizes the urls extracted from the reference definitions', async () => {
+ const result = await markdownToAST(
+ `
+[gitlab][gitlab] and ![GitLab Logo][gitlab]
+
+[gitlab]: /url\\bar*baz
+ `,
+ ['linkReference', 'imageReference'],
+ );
+
+ expectInRoot(
+ result,
+ expect.objectContaining({
+ tagName: 'p',
+ children: expect.arrayContaining([
+ expect.objectContaining({
+ type: 'element',
+ tagName: 'a',
+ properties: expect.objectContaining({
+ href: '/url%5Cbar*baz',
+ }),
+ }),
+ expect.objectContaining({
+ type: 'element',
+ tagName: 'img',
+ properties: expect.objectContaining({
+ src: '/url%5Cbar*baz',
+ }),
+ }),
+ ]),
+ }),
+ );
+ });
+ });
+ });
+
+ describe('when skipping the rendering of frontmatter types', () => {
+ it.each`
+ type | input
+ ${'yaml'} | ${'---\ntitle: page\n---'}
+ ${'toml'} | ${'+++\ntitle: page\n+++'}
+ ${'json'} | ${';;;\ntitle: page\n;;;'}
+ `('transforms $type nodes into frontmatter html tags', async ({ input, type }) => {
+ const result = await markdownToAST(input, [type]);
expectInRoot(
result,
expect.objectContaining({
- tagName: 'codeblock',
+ type: 'element',
+ tagName: 'frontmatter',
properties: {
- language: 'javascript',
+ language: type,
},
+ children: [
+ {
+ type: 'text',
+ value: 'title: page',
+ },
+ ],
}),
);
});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index 7cf101a5e59..a2ace8857ed 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -292,16 +292,11 @@ describe('common_utils', () => {
const spy = jest.fn();
const debouncedSpy = commonUtils.debounceByAnimationFrame(spy);
- return new Promise((resolve) => {
- window.requestAnimationFrame(() => {
- debouncedSpy();
- debouncedSpy();
- window.requestAnimationFrame(() => {
- expect(spy).toHaveBeenCalledTimes(1);
- resolve();
- });
- });
- });
+ debouncedSpy();
+ debouncedSpy();
+ jest.runOnlyPendingTimers();
+
+ expect(spy).toHaveBeenCalledTimes(1);
});
});
@@ -633,7 +628,7 @@ describe('common_utils', () => {
it('returns an empty object if `conversionFunction` parameter is not a function', () => {
const result = commonUtils.convertObjectProps(null, mockObjects.convertObjectProps.obj);
- expect(isEmptyObject(result)).toBeTruthy();
+ expect(isEmptyObject(result)).toBe(true);
});
});
@@ -650,9 +645,9 @@ describe('common_utils', () => {
: commonUtils[functionName];
it('returns an empty object if `obj` parameter is null, undefined or an empty object', () => {
- expect(isEmptyObject(testFunction(null))).toBeTruthy();
- expect(isEmptyObject(testFunction())).toBeTruthy();
- expect(isEmptyObject(testFunction({}))).toBeTruthy();
+ expect(isEmptyObject(testFunction(null))).toBe(true);
+ expect(isEmptyObject(testFunction())).toBe(true);
+ expect(isEmptyObject(testFunction({}))).toBe(true);
});
it('converts object properties', () => {
diff --git a/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
index d6131b1a1d7..313e028d861 100644
--- a/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
+++ b/spec/frontend/lib/utils/confirm_via_gl_modal/confirm_modal_spec.js
@@ -42,12 +42,12 @@ describe('Confirm Modal', () => {
it('should emit `confirmed` event on `primary` modal event', () => {
findGlModal().vm.$emit('primary');
- expect(wrapper.emitted('confirmed')).toBeTruthy();
+ expect(wrapper.emitted('confirmed')).toHaveLength(1);
});
it('should emit closed` event on `hidden` modal event', () => {
modal.vm.$emit('hidden');
- expect(wrapper.emitted('closed')).toBeTruthy();
+ expect(wrapper.emitted('closed')).toHaveLength(1);
});
});
diff --git a/spec/frontend/lib/utils/rails_ujs_spec.js b/spec/frontend/lib/utils/rails_ujs_spec.js
index c10301523c9..da9cc5c6f3c 100644
--- a/spec/frontend/lib/utils/rails_ujs_spec.js
+++ b/spec/frontend/lib/utils/rails_ujs_spec.js
@@ -18,14 +18,12 @@ function mockXHRResponse({ responseText, responseContentType } = {}) {
.mockReturnValue(responseContentType);
jest.spyOn(global.XMLHttpRequest.prototype, 'send').mockImplementation(function send() {
- requestAnimationFrame(() => {
- Object.defineProperties(this, {
- readyState: { value: XMLHttpRequest.DONE },
- status: { value: 200 },
- response: { value: responseText },
- });
- this.onreadystatechange();
+ Object.defineProperties(this, {
+ readyState: { value: XMLHttpRequest.DONE },
+ status: { value: 200 },
+ response: { value: responseText },
});
+ this.onreadystatechange();
});
}
diff --git a/spec/frontend/lib/utils/recurrence_spec.js b/spec/frontend/lib/utils/recurrence_spec.js
index fc22529dffc..8bf3ea4e25a 100644
--- a/spec/frontend/lib/utils/recurrence_spec.js
+++ b/spec/frontend/lib/utils/recurrence_spec.js
@@ -211,9 +211,10 @@ describe('recurrence', () => {
describe('eject', () => {
it('removes the handler assigned to the particular count slot', () => {
- recurInstance.handle(1, jest.fn());
+ const func = jest.fn();
+ recurInstance.handle(1, func);
- expect(recurInstance.handlers[1]).toBeTruthy();
+ expect(recurInstance.handlers[1]).toStrictEqual(func);
recurInstance.eject(1);
diff --git a/spec/frontend/lib/utils/sticky_spec.js b/spec/frontend/lib/utils/sticky_spec.js
index 01e8fe777af..ec9e746c838 100644
--- a/spec/frontend/lib/utils/sticky_spec.js
+++ b/spec/frontend/lib/utils/sticky_spec.js
@@ -34,13 +34,13 @@ describe('sticky', () => {
isSticky(el, 0, el.offsetTop);
isSticky(el, 0, el.offsetTop);
- expect(el.classList.contains('is-stuck')).toBeTruthy();
+ expect(el.classList.contains('is-stuck')).toBe(true);
});
it('adds is-stuck class', () => {
isSticky(el, 0, el.offsetTop);
- expect(el.classList.contains('is-stuck')).toBeTruthy();
+ expect(el.classList.contains('is-stuck')).toBe(true);
});
it('inserts placeholder element', () => {
@@ -64,7 +64,7 @@ describe('sticky', () => {
it('does not add is-stuck class', () => {
isSticky(el, 0, 0);
- expect(el.classList.contains('is-stuck')).toBeFalsy();
+ expect(el.classList.contains('is-stuck')).toBe(false);
});
it('removes placeholder', () => {
diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js
index d1bca3c73b6..733d89fe08c 100644
--- a/spec/frontend/lib/utils/text_markdown_spec.js
+++ b/spec/frontend/lib/utils/text_markdown_spec.js
@@ -193,6 +193,7 @@ describe('init markdown', () => {
${'- [ ] item'} | ${'- [ ] item\n- [ ] '}
${'- [x] item'} | ${'- [x] item\n- [ ] '}
${'- [X] item'} | ${'- [X] item\n- [ ] '}
+ ${'- [~] item'} | ${'- [~] item\n- [ ] '}
${'- [ ] nbsp (U+00A0)'} | ${'- [ ] nbsp (U+00A0)\n- [ ] '}
${'- item\n - second'} | ${'- item\n - second\n - '}
${'- - -'} | ${'- - -'}
@@ -205,6 +206,7 @@ describe('init markdown', () => {
${'1. [ ] item'} | ${'1. [ ] item\n2. [ ] '}
${'1. [x] item'} | ${'1. [x] item\n2. [ ] '}
${'1. [X] item'} | ${'1. [X] item\n2. [ ] '}
+ ${'1. [~] item'} | ${'1. [~] item\n2. [ ] '}
${'108. item'} | ${'108. item\n109. '}
${'108. item\n - second'} | ${'108. item\n - second\n - '}
${'108. item\n 1. second'} | ${'108. item\n 1. second\n 2. '}
@@ -228,11 +230,13 @@ describe('init markdown', () => {
${'- [ ] item\n- [ ] '} | ${'- [ ] item\n'}
${'- [x] item\n- [x] '} | ${'- [x] item\n'}
${'- [X] item\n- [X] '} | ${'- [X] item\n'}
+ ${'- [~] item\n- [~] '} | ${'- [~] item\n'}
${'- item\n - second\n - '} | ${'- item\n - second\n'}
${'1. item\n2. '} | ${'1. item\n'}
${'1. [ ] item\n2. [ ] '} | ${'1. [ ] item\n'}
${'1. [x] item\n2. [x] '} | ${'1. [x] item\n'}
${'1. [X] item\n2. [X] '} | ${'1. [X] item\n'}
+ ${'1. [~] item\n2. [~] '} | ${'1. [~] item\n'}
${'108. item\n109. '} | ${'108. item\n'}
${'108. item\n - second\n - '} | ${'108. item\n - second\n'}
${'108. item\n 1. second\n 1. '} | ${'108. item\n 1. second\n'}
@@ -301,6 +305,129 @@ describe('init markdown', () => {
});
});
+ describe('shifting selected lines left or right', () => {
+ const indentEvent = new KeyboardEvent('keydown', { key: ']', metaKey: true });
+ const outdentEvent = new KeyboardEvent('keydown', { key: '[', metaKey: true });
+
+ beforeEach(() => {
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.addEventListener('compositionstart', compositionStartNoteText);
+ textArea.addEventListener('compositionend', compositionEndNoteText);
+ });
+
+ it.each`
+ selectionStart | selectionEnd | expected | expectedSelectionStart | expectedSelectionEnd
+ ${0} | ${0} | ${' 012\n456\n89'} | ${2} | ${2}
+ ${5} | ${5} | ${'012\n 456\n89'} | ${7} | ${7}
+ ${10} | ${10} | ${'012\n456\n 89'} | ${12} | ${12}
+ ${0} | ${2} | ${' 012\n456\n89'} | ${0} | ${4}
+ ${1} | ${2} | ${' 012\n456\n89'} | ${3} | ${4}
+ ${5} | ${7} | ${'012\n 456\n89'} | ${7} | ${9}
+ ${0} | ${7} | ${' 012\n 456\n89'} | ${0} | ${11}
+ ${2} | ${9} | ${' 012\n 456\n 89'} | ${4} | ${15}
+ `(
+ 'indents the selected lines two spaces to the right',
+ ({
+ selectionStart,
+ selectionEnd,
+ expected,
+ expectedSelectionStart,
+ expectedSelectionEnd,
+ }) => {
+ const text = '012\n456\n89';
+ textArea.value = text;
+ textArea.setSelectionRange(selectionStart, selectionEnd);
+
+ textArea.dispatchEvent(indentEvent);
+
+ expect(textArea.value).toEqual(expected);
+ expect(textArea.selectionStart).toEqual(expectedSelectionStart);
+ expect(textArea.selectionEnd).toEqual(expectedSelectionEnd);
+ },
+ );
+
+ it('indents a blank line two spaces to the right', () => {
+ textArea.value = '012\n\n89';
+ textArea.setSelectionRange(4, 4);
+
+ textArea.dispatchEvent(indentEvent);
+
+ expect(textArea.value).toEqual('012\n \n89');
+ expect(textArea.selectionStart).toEqual(6);
+ expect(textArea.selectionEnd).toEqual(6);
+ });
+
+ it.each`
+ selectionStart | selectionEnd | expected | expectedSelectionStart | expectedSelectionEnd
+ ${0} | ${0} | ${'234\n 789\n 34'} | ${0} | ${0}
+ ${3} | ${3} | ${'234\n 789\n 34'} | ${1} | ${1}
+ ${7} | ${7} | ${' 234\n789\n 34'} | ${6} | ${6}
+ ${0} | ${3} | ${'234\n 789\n 34'} | ${0} | ${1}
+ ${8} | ${10} | ${' 234\n789\n 34'} | ${7} | ${9}
+ ${14} | ${15} | ${' 234\n 789\n34'} | ${12} | ${13}
+ ${0} | ${15} | ${'234\n789\n34'} | ${0} | ${10}
+ ${3} | ${13} | ${'234\n789\n34'} | ${1} | ${8}
+ ${6} | ${6} | ${' 234\n789\n 34'} | ${6} | ${6}
+ `(
+ 'outdents the selected lines two spaces to the left',
+ ({
+ selectionStart,
+ selectionEnd,
+ expected,
+ expectedSelectionStart,
+ expectedSelectionEnd,
+ }) => {
+ const text = ' 234\n 789\n 34';
+ textArea.value = text;
+ textArea.setSelectionRange(selectionStart, selectionEnd);
+
+ textArea.dispatchEvent(outdentEvent);
+
+ expect(textArea.value).toEqual(expected);
+ expect(textArea.selectionStart).toEqual(expectedSelectionStart);
+ expect(textArea.selectionEnd).toEqual(expectedSelectionEnd);
+ },
+ );
+
+ it('outdent a blank line has no effect', () => {
+ textArea.value = '012\n\n89';
+ textArea.setSelectionRange(4, 4);
+
+ textArea.dispatchEvent(outdentEvent);
+
+ expect(textArea.value).toEqual('012\n\n89');
+ expect(textArea.selectionStart).toEqual(4);
+ expect(textArea.selectionEnd).toEqual(4);
+ });
+
+ it('does not indent if meta is not set', () => {
+ const indentNoMetaEvent = new KeyboardEvent('keydown', { key: ']' });
+ const text = '012\n456\n89';
+ textArea.value = text;
+ textArea.setSelectionRange(0, 0);
+
+ textArea.dispatchEvent(indentNoMetaEvent);
+
+ expect(textArea.value).toEqual(text);
+ });
+
+ it.each`
+ keyEvent
+ ${new KeyboardEvent('keydown', { key: ']', metaKey: false })}
+ ${new KeyboardEvent('keydown', { key: ']', metaKey: true, shiftKey: true })}
+ ${new KeyboardEvent('keydown', { key: ']', metaKey: true, altKey: true })}
+ ${new KeyboardEvent('keydown', { key: ']', metaKey: true, ctrlKey: true })}
+ `('does not indent if meta is not set', ({ keyEvent }) => {
+ const text = '012\n456\n89';
+ textArea.value = text;
+ textArea.setSelectionRange(0, 0);
+
+ textArea.dispatchEvent(keyEvent);
+
+ expect(textArea.value).toEqual(text);
+ });
+ });
+
describe('with selection', () => {
let text = 'initial selected value';
let selected = 'selected';
@@ -377,6 +504,15 @@ describe('init markdown', () => {
expect(textArea.value).toEqual(text);
});
+
+ it('does nothing if meta is set', () => {
+ const event = new KeyboardEvent('keydown', { key: '[', metaKey: true });
+
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.dispatchEvent(event);
+
+ expect(textArea.value).toEqual(text);
+ });
});
describe('and text to be selected', () => {
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index 81cf4bd293b..2c6b603197d 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -348,15 +348,13 @@ describe('URL utility', () => {
describe('urlContainsSha', () => {
it('returns true when there is a valid 40-character SHA1 hash in the URL', () => {
shas.valid.forEach((sha) => {
- expect(
- urlUtils.urlContainsSha({ url: `http://urlstuff/${sha}/moreurlstuff` }),
- ).toBeTruthy();
+ expect(urlUtils.urlContainsSha({ url: `http://urlstuff/${sha}/moreurlstuff` })).toBe(true);
});
});
it('returns false when there is not a valid 40-character SHA1 hash in the URL', () => {
shas.invalid.forEach((str) => {
- expect(urlUtils.urlContainsSha({ url: `http://urlstuff/${str}/moreurlstuff` })).toBeFalsy();
+ expect(urlUtils.urlContainsSha({ url: `http://urlstuff/${str}/moreurlstuff` })).toBe(false);
});
});
});
@@ -555,18 +553,22 @@ describe('URL utility', () => {
describe('relativePathToAbsolute', () => {
it.each`
- path | base | result
- ${'./foo'} | ${'bar/'} | ${'/bar/foo'}
- ${'../john.md'} | ${'bar/baz/foo.php'} | ${'/bar/john.md'}
- ${'../images/img.png'} | ${'bar/baz/foo.php'} | ${'/bar/images/img.png'}
- ${'../images/Image 1.png'} | ${'bar/baz/foo.php'} | ${'/bar/images/Image 1.png'}
- ${'/images/img.png'} | ${'bar/baz/foo.php'} | ${'/images/img.png'}
- ${'/images/img.png'} | ${'/bar/baz/foo.php'} | ${'/images/img.png'}
- ${'../john.md'} | ${'/bar/baz/foo.php'} | ${'/bar/john.md'}
- ${'../john.md'} | ${'///bar/baz/foo.php'} | ${'/bar/john.md'}
- ${'/images/img.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/images/img.png'}
- ${'../images/img.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/user/images/img.png'}
- ${'../images/Image 1.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/user/images/Image%201.png'}
+ path | base | result
+ ${'./foo'} | ${'bar/'} | ${'/bar/foo'}
+ ${'../john.md'} | ${'bar/baz/foo.php'} | ${'/bar/john.md'}
+ ${'../images/img.png'} | ${'bar/baz/foo.php'} | ${'/bar/images/img.png'}
+ ${'../images/Image 1.png'} | ${'bar/baz/foo.php'} | ${'/bar/images/Image 1.png'}
+ ${'/images/img.png'} | ${'bar/baz/foo.php'} | ${'/images/img.png'}
+ ${'/images/img.png'} | ${'bar/baz//foo.php'} | ${'/images/img.png'}
+ ${'/images//img.png'} | ${'bar/baz/foo.php'} | ${'/images/img.png'}
+ ${'/images/img.png'} | ${'/bar/baz/foo.php'} | ${'/images/img.png'}
+ ${'../john.md'} | ${'/bar/baz/foo.php'} | ${'/bar/john.md'}
+ ${'../john.md'} | ${'///bar/baz/foo.php'} | ${'/bar/john.md'}
+ ${'/images/img.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/images/img.png'}
+ ${'/images/img.png'} | ${'https://gitlab.com////user/project/'} | ${'https://gitlab.com/images/img.png'}
+ ${'/images////img.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/images/img.png'}
+ ${'../images/img.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/user/images/img.png'}
+ ${'../images/Image 1.png'} | ${'https://gitlab.com/user/project/'} | ${'https://gitlab.com/user/images/Image%201.png'}
`(
'converts relative path "$path" with base "$base" to absolute path => "expected"',
({ path, base, result }) => {
@@ -809,13 +811,13 @@ describe('URL utility', () => {
});
it('should compare against the window location if no compare value is provided', () => {
- expect(urlUtils.urlIsDifferent('different')).toBeTruthy();
- expect(urlUtils.urlIsDifferent(current)).toBeFalsy();
+ expect(urlUtils.urlIsDifferent('different')).toBe(true);
+ expect(urlUtils.urlIsDifferent(current)).toBe(false);
});
it('should use the provided compare value', () => {
- expect(urlUtils.urlIsDifferent('different', current)).toBeTruthy();
- expect(urlUtils.urlIsDifferent(current, current)).toBeFalsy();
+ expect(urlUtils.urlIsDifferent('different', current)).toBe(true);
+ expect(urlUtils.urlIsDifferent(current, current)).toBe(false);
});
});
@@ -1058,4 +1060,28 @@ describe('URL utility', () => {
expect(urlUtils.PROMO_URL).toBe(url);
});
});
+
+ describe('removeUrlProtocol', () => {
+ it.each`
+ input | output
+ ${'http://gitlab.com'} | ${'gitlab.com'}
+ ${'https://gitlab.com'} | ${'gitlab.com'}
+ ${'foo:bar.com'} | ${'bar.com'}
+ ${'gitlab.com'} | ${'gitlab.com'}
+ `('transforms $input to $output', ({ input, output }) => {
+ expect(urlUtils.removeUrlProtocol(input)).toBe(output);
+ });
+ });
+
+ describe('removeLastSlashInUrlPath', () => {
+ it.each`
+ input | output
+ ${'https://www.gitlab.com/path/'} | ${'https://www.gitlab.com/path'}
+ ${'https://www.gitlab.com/?query=search'} | ${'https://www.gitlab.com?query=search'}
+ ${'https://www.gitlab.com/#fragment'} | ${'https://www.gitlab.com#fragment'}
+ ${'https://www.gitlab.com/hello'} | ${'https://www.gitlab.com/hello'}
+ `('transforms $input to $output', ({ input, output }) => {
+ expect(urlUtils.removeLastSlashInUrlPath(input)).toBe(output);
+ });
+ });
});
diff --git a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
index f1471f625f8..3dac47974e7 100644
--- a/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/access_request_action_buttons_spec.js
@@ -17,8 +17,8 @@ describe('AccessRequestActionButtons', () => {
});
};
- const findRemoveMemberButton = () => wrapper.find(RemoveMemberButton);
- const findApproveButton = () => wrapper.find(ApproveAccessRequestButton);
+ const findRemoveMemberButton = () => wrapper.findComponent(RemoveMemberButton);
+ const findApproveButton = () => wrapper.findComponent(ApproveAccessRequestButton);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
index 08d7cf3c932..15bb03480e1 100644
--- a/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/approve_access_request_button_spec.js
@@ -43,8 +43,8 @@ describe('ApproveAccessRequestButton', () => {
});
};
- const findForm = () => wrapper.find(GlForm);
- const findButton = () => findForm().find(GlButton);
+ const findForm = () => wrapper.findComponent(GlForm);
+ const findButton = () => findForm().findComponent(GlButton);
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
index 79252456f67..ea819b4fb83 100644
--- a/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/invite_action_buttons_spec.js
@@ -16,8 +16,8 @@ describe('InviteActionButtons', () => {
});
};
- const findRemoveMemberButton = () => wrapper.find(RemoveMemberButton);
- const findResendInviteButton = () => wrapper.find(ResendInviteButton);
+ const findRemoveMemberButton = () => wrapper.findComponent(RemoveMemberButton);
+ const findResendInviteButton = () => wrapper.findComponent(ResendInviteButton);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/components/action_buttons/leave_button_spec.js b/spec/frontend/members/components/action_buttons/leave_button_spec.js
index 4859d033464..ecfbf4460a6 100644
--- a/spec/frontend/members/components/action_buttons/leave_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/leave_button_spec.js
@@ -22,7 +22,7 @@ describe('LeaveButton', () => {
});
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
createComponent();
@@ -44,7 +44,7 @@ describe('LeaveButton', () => {
});
it('renders leave modal', () => {
- const leaveModal = wrapper.find(LeaveModal);
+ const leaveModal = wrapper.findComponent(LeaveModal);
expect(leaveModal.exists()).toBe(true);
expect(leaveModal.props('member')).toEqual(member);
diff --git a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
index ca655e36c42..b511cebdf28 100644
--- a/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/remove_group_link_button_spec.js
@@ -42,7 +42,7 @@ describe('RemoveGroupLinkButton', () => {
});
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
index 8e933d16463..51cfd47ddf4 100644
--- a/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
+++ b/spec/frontend/members/components/action_buttons/resend_invite_button_spec.js
@@ -44,7 +44,7 @@ describe('ResendInviteButton', () => {
};
const findForm = () => wrapper.find('form');
- const findButton = () => findForm().find(GlButton);
+ const findButton = () => findForm().findComponent(GlButton);
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
index 3e4ffb6e61b..6ac46619bc9 100644
--- a/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
+++ b/spec/frontend/members/components/action_buttons/user_action_buttons_spec.js
@@ -19,7 +19,7 @@ describe('UserActionButtons', () => {
});
};
- const findRemoveMemberButton = () => wrapper.find(RemoveMemberButton);
+ const findRemoveMemberButton = () => wrapper.findComponent(RemoveMemberButton);
afterEach(() => {
wrapper.destroy();
@@ -80,7 +80,7 @@ describe('UserActionButtons', () => {
},
});
- expect(wrapper.find(LeaveButton).exists()).toBe(true);
+ expect(wrapper.findComponent(LeaveButton).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/members/components/app_spec.js b/spec/frontend/members/components/app_spec.js
index 4124a1870a6..d105a4d9fde 100644
--- a/spec/frontend/members/components/app_spec.js
+++ b/spec/frontend/members/components/app_spec.js
@@ -41,8 +41,8 @@ describe('MembersApp', () => {
});
};
- const findAlert = () => wrapper.find(GlAlert);
- const findFilterSortContainer = () => wrapper.find(FilterSortContainer);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findFilterSortContainer = () => wrapper.findComponent(FilterSortContainer);
beforeEach(() => {
commonUtils.scrollToElement = jest.fn();
diff --git a/spec/frontend/members/components/avatars/group_avatar_spec.js b/spec/frontend/members/components/avatars/group_avatar_spec.js
index 9c1574a84ee..13c50de9835 100644
--- a/spec/frontend/members/components/avatars/group_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/group_avatar_spec.js
@@ -30,7 +30,7 @@ describe('MemberList', () => {
});
it('renders link to group', () => {
- const link = wrapper.find(GlAvatarLink);
+ const link = wrapper.findComponent(GlAvatarLink);
expect(link.exists()).toBe(true);
expect(link.attributes('href')).toBe(group.webUrl);
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 7bcf4a11413..9b908e5b6f0 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -33,7 +33,7 @@ describe('UserAvatar', () => {
it("renders link to user's profile", () => {
createComponent();
- const link = wrapper.find(GlAvatarLink);
+ const link = wrapper.findComponent(GlAvatarLink);
expect(link.exists()).toBe(true);
expect(link.attributes()).toMatchObject({
@@ -77,7 +77,7 @@ describe('UserAvatar', () => {
`('renders the "$badgeText" badge', ({ member, badgeText }) => {
createComponent({ member });
- expect(wrapper.find(GlBadge).text()).toBe(badgeText);
+ expect(wrapper.findComponent(GlBadge).text()).toBe(badgeText);
});
it('renders the "It\'s you" badge when member is current user', () => {
diff --git a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
index 4ca8a3bdc36..de2f6e6dd47 100644
--- a/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
+++ b/spec/frontend/members/components/filter_sort/filter_sort_container_spec.js
@@ -60,7 +60,7 @@ describe('FilterSortContainer', () => {
},
});
- expect(wrapper.find(MembersFilteredSearchBar).exists()).toBe(true);
+ expect(wrapper.findComponent(MembersFilteredSearchBar).exists()).toBe(true);
});
});
@@ -70,7 +70,7 @@ describe('FilterSortContainer', () => {
tableSortableFields: ['account'],
});
- expect(wrapper.find(SortDropdown).exists()).toBe(true);
+ expect(wrapper.findComponent(SortDropdown).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index b692eea4aa5..4580fdb06f2 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -56,7 +56,7 @@ describe('MembersFilteredSearchBar', () => {
});
};
- const findFilteredSearchBar = () => wrapper.find(FilteredSearchBar);
+ const findFilteredSearchBar = () => wrapper.findComponent(FilteredSearchBar);
it('passes correct props to `FilteredSearchBar` component', () => {
createComponent();
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 709ad907a38..5581fd52458 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -43,13 +43,13 @@ describe('SortDropdown', () => {
});
};
- const findSortingComponent = () => wrapper.find(GlSorting);
+ const findSortingComponent = () => wrapper.findComponent(GlSorting);
const findSortDirectionToggle = () =>
findSortingComponent().find('button[title="Sort direction"]');
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
const findDropdownItemByText = (text) =>
wrapper
- .findAll(GlSortingItem)
+ .findAllComponents(GlSortingItem)
.wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.text() === text);
beforeEach(() => {
diff --git a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
index 447496910b8..af96396f09f 100644
--- a/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
+++ b/spec/frontend/members/components/modals/remove_group_link_modal_spec.js
@@ -47,8 +47,8 @@ describe('RemoveGroupLinkModal', () => {
});
};
- const findModal = () => wrapper.find(GlModal);
- const findForm = () => findModal().find(GlForm);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findForm = () => findModal().findComponent(GlForm);
const getByText = (text, options) =>
createWrapper(within(findModal().element).getByText(text, options));
diff --git a/spec/frontend/members/components/modals/remove_member_modal_spec.js b/spec/frontend/members/components/modals/remove_member_modal_spec.js
index 1d39c4b3175..59b112492b8 100644
--- a/spec/frontend/members/components/modals/remove_member_modal_spec.js
+++ b/spec/frontend/members/components/modals/remove_member_modal_spec.js
@@ -46,7 +46,7 @@ describe('RemoveMemberModal', () => {
});
};
- const findForm = () => wrapper.find({ ref: 'form' });
+ const findForm = () => wrapper.findComponent({ ref: 'form' });
const findGlModal = () => wrapper.findComponent(GlModal);
const findUserDeletionObstaclesList = () => wrapper.findComponent(UserDeletionObstaclesList);
diff --git a/spec/frontend/members/components/table/created_at_spec.js b/spec/frontend/members/components/table/created_at_spec.js
index 74b71e22893..793c122587d 100644
--- a/spec/frontend/members/components/table/created_at_spec.js
+++ b/spec/frontend/members/components/table/created_at_spec.js
@@ -39,7 +39,7 @@ describe('CreatedAt', () => {
});
it('uses `TimeAgoTooltip` component to display tooltip', () => {
- expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
+ expect(wrapper.findComponent(TimeAgoTooltip).exists()).toBe(true);
});
});
diff --git a/spec/frontend/members/components/table/expiration_datepicker_spec.js b/spec/frontend/members/components/table/expiration_datepicker_spec.js
index 4fb43fbd888..9b8f053348b 100644
--- a/spec/frontend/members/components/table/expiration_datepicker_spec.js
+++ b/spec/frontend/members/components/table/expiration_datepicker_spec.js
@@ -56,7 +56,7 @@ describe('ExpirationDatepicker', () => {
};
const findInput = () => wrapper.find('input');
- const findDatepicker = () => wrapper.find(GlDatepicker);
+ const findDatepicker = () => wrapper.findComponent(GlDatepicker);
afterEach(() => {
wrapper.destroy();
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 1379b2d26ce..f3f50bf620a 100644
--- a/spec/frontend/members/components/table/member_action_buttons_spec.js
+++ b/spec/frontend/members/components/table/member_action_buttons_spec.js
@@ -38,7 +38,7 @@ describe('MemberActionButtons', () => {
({ memberType, member, expectedComponent }) => {
createComponent({ memberType, member });
- expect(wrapper.find(expectedComponent).exists()).toBe(true);
+ expect(wrapper.findComponent(expectedComponent).exists()).toBe(true);
},
);
});
diff --git a/spec/frontend/members/components/table/member_avatar_spec.js b/spec/frontend/members/components/table/member_avatar_spec.js
index 3cce64effbc..35f82c28fc5 100644
--- a/spec/frontend/members/components/table/member_avatar_spec.js
+++ b/spec/frontend/members/components/table/member_avatar_spec.js
@@ -33,7 +33,7 @@ describe('MemberList', () => {
({ memberType, member, expectedComponent }) => {
createComponent({ memberType, member });
- expect(wrapper.find(expectedComponent).exists()).toBe(true);
+ expect(wrapper.findComponent(expectedComponent).exists()).toBe(true);
},
);
});
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 6575a7c7126..fd56699602e 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -69,7 +69,7 @@ describe('MembersTableCell', () => {
});
};
- const findWrappedComponent = () => wrapper.find(WrappedComponent);
+ const findWrappedComponent = () => wrapper.findComponent(WrappedComponent);
const memberCurrentUser = {
...memberMock,
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 08baa663bf0..0ed01396fcb 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -81,13 +81,13 @@ describe('MembersTable', () => {
const url = 'https://localhost/foo-bar/-/project_members?tab=invited';
- const findTable = () => wrapper.find(GlTable);
+ const findTable = () => wrapper.findComponent(GlTable);
const findTableCellByMemberId = (tableCellLabel, memberId) =>
wrapper
.findByTestId(`members-table-row-${memberId}`)
.find(`[data-label="${tableCellLabel}"][role="cell"]`);
- const findPagination = () => extendedWrapper(wrapper.find(GlPagination));
+ const findPagination = () => extendedWrapper(wrapper.findComponent(GlPagination));
const expectCorrectLinkToPage2 = () => {
expect(findPagination().findByText('2', { selector: 'a' }).attributes('href')).toBe(
@@ -126,7 +126,10 @@ describe('MembersTable', () => {
if (expectedComponent) {
expect(
- wrapper.find(`[data-label="${label}"][role="cell"]`).find(expectedComponent).exists(),
+ wrapper
+ .find(`[data-label="${label}"][role="cell"]`)
+ .findComponent(expectedComponent)
+ .exists(),
).toBe(true);
}
});
@@ -179,7 +182,10 @@ describe('MembersTable', () => {
expect(actionField.exists()).toBe(true);
expect(actionField.classes('gl-sr-only')).toBe(true);
expect(
- wrapper.find(`[data-label="Actions"][role="cell"]`).find(MemberActionButtons).exists(),
+ wrapper
+ .find(`[data-label="Actions"][role="cell"]`)
+ .findComponent(MemberActionButtons)
+ .exists(),
).toBe(true);
});
@@ -250,9 +256,9 @@ describe('MembersTable', () => {
it('renders badge in "Max role" field', () => {
createComponent({ members: [memberMock], tableFields: ['maxRole'] });
- expect(wrapper.find(`[data-label="Max role"][role="cell"]`).find(GlBadge).text()).toBe(
- memberMock.accessLevel.stringValue,
- );
+ expect(
+ wrapper.find(`[data-label="Max role"][role="cell"]`).findComponent(GlBadge).text(),
+ ).toBe(memberMock.accessLevel.stringValue);
});
});
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index 2f1626a7044..b254cce4d72 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -57,11 +57,11 @@ describe('RoleDropdown', () => {
);
const getCheckedDropdownItem = () =>
wrapper
- .findAll(GlDropdownItem)
+ .findAllComponents(GlDropdownItem)
.wrappers.find((dropdownItemWrapper) => dropdownItemWrapper.props('isChecked'));
const findDropdownToggle = () => wrapper.find('button[aria-haspopup="true"]');
- const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js
index 251a8b0b774..5c813eb2a67 100644
--- a/spec/frontend/members/index_spec.js
+++ b/spec/frontend/members/index_spec.js
@@ -39,7 +39,7 @@ describe('initMembersApp', () => {
it('renders `MembersTabs`', () => {
setup();
- expect(wrapper.find(MembersTabs).exists()).toBe(true);
+ expect(wrapper.findComponent(MembersTabs).exists()).toBe(true);
});
it('parses and sets `members` in Vuex store', () => {
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index 8dc6132709e..3674a49f42c 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -20,7 +20,7 @@ describe('Anomaly chart component', () => {
propsData: { ...props },
});
};
- const findTimeSeries = () => wrapper.find(MonitorTimeSeriesChart);
+ const findTimeSeries = () => wrapper.findComponent(MonitorTimeSeriesChart);
const getTimeSeriesProps = () => findTimeSeries().props();
describe('wrapped monitor-time-series-chart component', () => {
diff --git a/spec/frontend/monitoring/components/charts/bar_spec.js b/spec/frontend/monitoring/components/charts/bar_spec.js
index 6368c53943a..5339a7a525b 100644
--- a/spec/frontend/monitoring/components/charts/bar_spec.js
+++ b/spec/frontend/monitoring/components/charts/bar_spec.js
@@ -33,7 +33,7 @@ describe('Bar component', () => {
let chartData;
beforeEach(() => {
- glbarChart = barChart.find(GlBarChart);
+ glbarChart = barChart.findComponent(GlBarChart);
chartData = barChart.vm.chartData[graphData.metrics[0].label];
});
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index e10cb3a456a..0158966997f 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -44,7 +44,7 @@ describe('Column component', () => {
},
});
};
- const findChart = () => wrapper.find(GlColumnChart);
+ const findChart = () => wrapper.findComponent(GlColumnChart);
const chartProps = (prop) => findChart().props(prop);
beforeEach(() => {
diff --git a/spec/frontend/monitoring/components/charts/gauge_spec.js b/spec/frontend/monitoring/components/charts/gauge_spec.js
index c8f67d5d8c7..484199698ea 100644
--- a/spec/frontend/monitoring/components/charts/gauge_spec.js
+++ b/spec/frontend/monitoring/components/charts/gauge_spec.js
@@ -8,7 +8,7 @@ describe('Gauge Chart component', () => {
let wrapper;
- const findGaugeChart = () => wrapper.find(GlGaugeChart);
+ const findGaugeChart = () => wrapper.findComponent(GlGaugeChart);
const createWrapper = ({ ...graphProps } = {}) => {
wrapper = shallowMount(GaugeChart, {
diff --git a/spec/frontend/monitoring/components/charts/heatmap_spec.js b/spec/frontend/monitoring/components/charts/heatmap_spec.js
index 841b7e0648a..e163d4e73a0 100644
--- a/spec/frontend/monitoring/components/charts/heatmap_spec.js
+++ b/spec/frontend/monitoring/components/charts/heatmap_spec.js
@@ -8,7 +8,7 @@ describe('Heatmap component', () => {
let wrapper;
let store;
- const findChart = () => wrapper.find(GlHeatmap);
+ const findChart = () => wrapper.findComponent(GlHeatmap);
const graphData = heatmapGraphData();
diff --git a/spec/frontend/monitoring/components/charts/single_stat_spec.js b/spec/frontend/monitoring/components/charts/single_stat_spec.js
index 8633b49565f..62a0b7e6ad3 100644
--- a/spec/frontend/monitoring/components/charts/single_stat_spec.js
+++ b/spec/frontend/monitoring/components/charts/single_stat_spec.js
@@ -15,7 +15,7 @@ describe('Single Stat Chart component', () => {
});
};
- const findChart = () => wrapper.find(GlSingleStat);
+ const findChart = () => wrapper.findComponent(GlSingleStat);
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index 9cab3650f28..91fe36bc6e4 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -15,8 +15,8 @@ describe('Stacked column chart component', () => {
let wrapper;
- const findChart = () => wrapper.find(GlStackedColumnChart);
- const findLegend = () => wrapper.find(GlChartLegend);
+ const findChart = () => wrapper.findComponent(GlStackedColumnChart);
+ const findLegend = () => wrapper.findComponent(GlChartLegend);
const createWrapper = (props = {}, mountingMethod = shallowMount) =>
mountingMethod(StackedColumnChart, {
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index f4bca26f659..503dee7b937 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -9,7 +9,6 @@ import { mount, shallowMount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import { setTestTimeout } from 'helpers/timeout';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import { panelTypes, chartHeight } from '~/monitoring/constants';
@@ -59,17 +58,13 @@ describe('Time series component', () => {
});
};
- beforeEach(() => {
- setTestTimeout(1000);
- });
-
afterEach(() => {
wrapper.destroy();
});
describe('With a single time series', () => {
describe('general functions', () => {
- const findChart = () => wrapper.find({ ref: 'chart' });
+ const findChart = () => wrapper.findComponent({ ref: 'chart' });
beforeEach(async () => {
createWrapper({}, mount);
@@ -215,7 +210,7 @@ describe('Time series component', () => {
const name = 'Metric 1';
const value = '5.556';
const dataIndex = 0;
- const seriesLabel = wrapper.find(GlChartSeriesLabel);
+ const seriesLabel = wrapper.findComponent(GlChartSeriesLabel);
expect(seriesLabel.vm.color).toBe('');
@@ -225,7 +220,11 @@ describe('Time series component', () => {
]);
expect(
- shallowWrapperContainsSlotText(wrapper.find(GlLineChart), 'tooltip-content', value),
+ shallowWrapperContainsSlotText(
+ wrapper.findComponent(GlLineChart),
+ 'tooltip-content',
+ value,
+ ),
).toBe(true);
});
@@ -598,7 +597,7 @@ describe('Time series component', () => {
glChartComponents.forEach((dynamicComponent) => {
describe(`GitLab UI: ${dynamicComponent.chartType}`, () => {
- const findChartComponent = () => wrapper.find(dynamicComponent.component);
+ const findChartComponent = () => wrapper.findComponent(dynamicComponent.component);
beforeEach(async () => {
createWrapper(
@@ -656,7 +655,7 @@ describe('Time series component', () => {
wrapper.vm.tooltip.commitUrl = commitUrl;
await nextTick();
- const commitLink = wrapper.find(GlLink);
+ const commitLink = wrapper.findComponent(GlLink);
expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true);
expect(commitLink.attributes('href')).toEqual(commitUrl);
@@ -680,7 +679,9 @@ describe('Time series component', () => {
let lineColors;
beforeEach(() => {
- lineColors = wrapper.find(GlAreaChart).vm.series.map((item) => item.lineStyle.color);
+ lineColors = wrapper
+ .findComponent(GlAreaChart)
+ .vm.series.map((item) => item.lineStyle.color);
});
it('should contain different colors for contiguous time series', () => {
@@ -690,7 +691,7 @@ describe('Time series component', () => {
});
it('should match series color with tooltip label color', () => {
- const labels = wrapper.findAll(GlChartSeriesLabel);
+ const labels = wrapper.findAllComponents(GlChartSeriesLabel);
lineColors.forEach((color, index) => {
const labelColor = labels.at(index).props('color');
@@ -700,7 +701,7 @@ describe('Time series component', () => {
it('should match series color with legend color', () => {
const legendColors = wrapper
- .find(GlChartLegend)
+ .findComponent(GlChartLegend)
.props('seriesInfo')
.map((item) => item.color);
@@ -713,7 +714,7 @@ describe('Time series component', () => {
});
describe('legend layout', () => {
- const findLegend = () => wrapper.find(GlChartLegend);
+ const findLegend = () => wrapper.findComponent(GlChartLegend);
beforeEach(async () => {
createWrapper({}, mount);
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index d74f959ac0f..bb57420d406 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -92,7 +92,7 @@ describe('Actions menu', () => {
});
it('renders custom metrics form fields', () => {
- expect(wrapper.find(CustomMetricsFormFields).exists()).toBe(true);
+ expect(wrapper.findComponent(CustomMetricsFormFields).exists()).toBe(true);
});
});
@@ -316,7 +316,7 @@ describe('Actions menu', () => {
});
it('is not disabled', () => {
- expect(findStarDashboardItem().attributes('disabled')).toBeFalsy();
+ expect(findStarDashboardItem().attributes('disabled')).toBeUndefined();
});
it('is disabled when starring is taking place', async () => {
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index e28c2913949..18ccda2c41c 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -29,18 +29,19 @@ describe('Dashboard header', () => {
let store;
let wrapper;
- const findDashboardDropdown = () => wrapper.find(DashboardsDropdown);
+ const findDashboardDropdown = () => wrapper.findComponent(DashboardsDropdown);
- const findEnvsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
- const findEnvsDropdownItems = () => findEnvsDropdown().findAll(GlDropdownItem);
- const findEnvsDropdownSearch = () => findEnvsDropdown().find(GlSearchBoxByType);
- const findEnvsDropdownSearchMsg = () => wrapper.find({ ref: 'monitorEnvironmentsDropdownMsg' });
- const findEnvsDropdownLoadingIcon = () => findEnvsDropdown().find(GlLoadingIcon);
+ const findEnvsDropdown = () => wrapper.findComponent({ ref: 'monitorEnvironmentsDropdown' });
+ const findEnvsDropdownItems = () => findEnvsDropdown().findAllComponents(GlDropdownItem);
+ const findEnvsDropdownSearch = () => findEnvsDropdown().findComponent(GlSearchBoxByType);
+ const findEnvsDropdownSearchMsg = () =>
+ wrapper.findComponent({ ref: 'monitorEnvironmentsDropdownMsg' });
+ const findEnvsDropdownLoadingIcon = () => findEnvsDropdown().findComponent(GlLoadingIcon);
- const findDateTimePicker = () => wrapper.find(DateTimePicker);
- const findRefreshButton = () => wrapper.find(RefreshButton);
+ const findDateTimePicker = () => wrapper.findComponent(DateTimePicker);
+ const findRefreshButton = () => wrapper.findComponent(RefreshButton);
- const findActionsMenu = () => wrapper.find(ActionsMenu);
+ const findActionsMenu = () => wrapper.findComponent(ActionsMenu);
const setSearchTerm = (searchTerm) => {
store.commit(`monitoringDashboard/${types.SET_ENVIRONMENTS_FILTER}`, searchTerm);
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
index f19ef6c6fb7..d71f6374967 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
@@ -32,14 +32,14 @@ describe('dashboard invalid url parameters', () => {
});
};
- const findForm = () => wrapper.find(GlForm);
- const findTxtArea = () => findForm().find(GlFormTextarea);
+ const findForm = () => wrapper.findComponent(GlForm);
+ const findTxtArea = () => findForm().findComponent(GlFormTextarea);
const findSubmitBtn = () => findForm().find('[type="submit"]');
- const findClipboardCopyBtn = () => wrapper.find({ ref: 'clipboardCopyBtn' });
- const findViewDocumentationBtn = () => wrapper.find({ ref: 'viewDocumentationBtn' });
- const findOpenRepositoryBtn = () => wrapper.find({ ref: 'openRepositoryBtn' });
- const findPanel = () => wrapper.find(DashboardPanel);
- const findTimeRangePicker = () => wrapper.find(DateTimePicker);
+ const findClipboardCopyBtn = () => wrapper.findComponent({ ref: 'clipboardCopyBtn' });
+ const findViewDocumentationBtn = () => wrapper.findComponent({ ref: 'viewDocumentationBtn' });
+ const findOpenRepositoryBtn = () => wrapper.findComponent({ ref: 'openRepositoryBtn' });
+ const findPanel = () => wrapper.findComponent(DashboardPanel);
+ const findTimeRangePicker = () => wrapper.findComponent(DateTimePicker);
const findRefreshButton = () => wrapper.find('[data-testid="previewRefreshButton"]');
beforeEach(() => {
@@ -192,8 +192,8 @@ describe('dashboard invalid url parameters', () => {
});
it('displays an alert', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(true);
- expect(wrapper.find(GlAlert).text()).toBe(mockError);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
+ expect(wrapper.findComponent(GlAlert).text()).toBe(mockError);
});
it('displays an empty dashboard panel', () => {
@@ -215,11 +215,11 @@ describe('dashboard invalid url parameters', () => {
});
it('displays no alert', () => {
- expect(wrapper.find(GlAlert).exists()).toBe(false);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
});
it('displays panel with data', () => {
- const { title, type } = wrapper.find(DashboardPanel).props('graphData');
+ const { title, type } = wrapper.findComponent(DashboardPanel).props('graphData');
expect(title).toBe(mockPanel.title);
expect(type).toBe(mockPanel.type);
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index 7c54a4742ac..d797d9e2ad0 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -3,7 +3,6 @@ import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import { nextTick } from 'vue';
-import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import MonitorAnomalyChart from '~/monitoring/components/charts/anomaly.vue';
@@ -42,11 +41,11 @@ describe('Dashboard Panel', () => {
const exampleText = 'example_text';
- const findCopyLink = () => wrapper.find({ ref: 'copyChartLink' });
- const findTimeChart = () => wrapper.find({ ref: 'timeSeriesChart' });
- const findTitle = () => wrapper.find({ ref: 'graphTitle' });
- const findCtxMenu = () => wrapper.find({ ref: 'contextualMenu' });
- const findMenuItems = () => wrapper.findAll(GlDropdownItem);
+ const findCopyLink = () => wrapper.findComponent({ ref: 'copyChartLink' });
+ const findTimeChart = () => wrapper.findComponent({ ref: 'timeSeriesChart' });
+ const findTitle = () => wrapper.findComponent({ ref: 'graphTitle' });
+ const findCtxMenu = () => wrapper.findComponent({ ref: 'contextualMenu' });
+ const findMenuItems = () => wrapper.findAllComponents(GlDropdownItem);
const findMenuItemByText = (text) => findMenuItems().filter((i) => i.text() === text);
const createWrapper = (props, { mountFn = shallowMount, ...options } = {}) => {
@@ -72,8 +71,6 @@ describe('Dashboard Panel', () => {
};
beforeEach(() => {
- setTestTimeout(1000);
-
store = createStore();
state = store.state.monitoringDashboard;
@@ -118,7 +115,7 @@ describe('Dashboard Panel', () => {
});
it('renders no download csv link', () => {
- expect(wrapper.find({ ref: 'downloadCsvLink' }).exists()).toBe(false);
+ expect(wrapper.findComponent({ ref: 'downloadCsvLink' }).exists()).toBe(false);
});
it('does not contain graph widgets', () => {
@@ -126,7 +123,7 @@ describe('Dashboard Panel', () => {
});
it('The Empty Chart component is rendered and is a Vue instance', () => {
- expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
+ expect(wrapper.findComponent(MonitorEmptyChart).exists()).toBe(true);
});
});
@@ -146,7 +143,7 @@ describe('Dashboard Panel', () => {
});
it('renders no download csv link', () => {
- expect(wrapper.find({ ref: 'downloadCsvLink' }).exists()).toBe(false);
+ expect(wrapper.findComponent({ ref: 'downloadCsvLink' }).exists()).toBe(false);
});
it('does not contain graph widgets', () => {
@@ -154,7 +151,7 @@ describe('Dashboard Panel', () => {
});
it('The Empty Chart component is rendered and is a Vue instance', () => {
- expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
+ expect(wrapper.findComponent(MonitorEmptyChart).exists()).toBe(true);
});
});
@@ -173,7 +170,7 @@ describe('Dashboard Panel', () => {
it('contains graph widgets', () => {
expect(findCtxMenu().exists()).toBe(true);
- expect(wrapper.find({ ref: 'downloadCsvLink' }).exists()).toBe(true);
+ expect(wrapper.findComponent({ ref: 'downloadCsvLink' }).exists()).toBe(true);
});
it('sets no clipboard copy link on dropdown by default', () => {
@@ -208,12 +205,12 @@ describe('Dashboard Panel', () => {
it('empty chart is rendered for empty results', () => {
createWrapper({ graphData: graphDataEmpty });
- expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
+ expect(wrapper.findComponent(MonitorEmptyChart).exists()).toBe(true);
});
it('area chart is rendered by default', () => {
createWrapper();
- expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
+ expect(wrapper.findComponent(MonitorTimeSeriesChart).exists()).toBe(true);
});
describe.each`
@@ -234,8 +231,8 @@ describe('Dashboard Panel', () => {
});
it(`renders the chart component and binds attributes`, () => {
- expect(wrapper.find(component).exists()).toBe(true);
- expect(wrapper.find(component).attributes()).toMatchObject(attrs);
+ expect(wrapper.findComponent(component).exists()).toBe(true);
+ expect(wrapper.findComponent(component).attributes()).toMatchObject(attrs);
});
it(`contextual menu is ${hasCtxMenu ? '' : 'not '}shown`, () => {
@@ -273,7 +270,7 @@ describe('Dashboard Panel', () => {
});
describe('Edit custom metric dropdown item', () => {
- const findEditCustomMetricLink = () => wrapper.find({ ref: 'editMetricLink' });
+ const findEditCustomMetricLink = () => wrapper.findComponent({ ref: 'editMetricLink' });
const mockEditPath = '/root/kubernetes-gke-project/prometheus/metrics/23/edit';
beforeEach(async () => {
@@ -434,7 +431,7 @@ describe('Dashboard Panel', () => {
});
it('it renders a time series chart with no errors', () => {
- expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
+ expect(wrapper.findComponent(MonitorTimeSeriesChart).exists()).toBe(true);
});
});
@@ -446,7 +443,7 @@ describe('Dashboard Panel', () => {
it('displays a heatmap in local timezone', () => {
createWrapper({ graphData: heatmapGraphData() });
- expect(wrapper.find(MonitorHeatmapChart).props('timezone')).toBe('LOCAL');
+ expect(wrapper.findComponent(MonitorHeatmapChart).props('timezone')).toBe('LOCAL');
});
describe('when timezone is set to UTC', () => {
@@ -461,13 +458,13 @@ describe('Dashboard Panel', () => {
it('displays a heatmap with UTC', () => {
createWrapper({ graphData: heatmapGraphData() });
- expect(wrapper.find(MonitorHeatmapChart).props('timezone')).toBe('UTC');
+ expect(wrapper.findComponent(MonitorHeatmapChart).props('timezone')).toBe('UTC');
});
});
});
describe('Expand to full screen', () => {
- const findExpandBtn = () => wrapper.find({ ref: 'expandBtn' });
+ const findExpandBtn = () => wrapper.findComponent({ ref: 'expandBtn' });
describe('when there is no @expand listener', () => {
it('does not show `View full screen` option', () => {
@@ -495,7 +492,7 @@ describe('Dashboard Panel', () => {
});
describe('When graphData contains links', () => {
- const findManageLinksItem = () => wrapper.find({ ref: 'manageLinksItem' });
+ const findManageLinksItem = () => wrapper.findComponent({ ref: 'manageLinksItem' });
const mockLinks = [
{
url: 'https://example.com',
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 90171cfc65e..608404e5c5b 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -97,8 +97,10 @@ describe('Dashboard', () => {
createShallowWrapper({ hasMetrics: true });
await nextTick();
- expect(wrapper.find(EmptyState).exists()).toBe(true);
- expect(wrapper.find(EmptyState).props('selectedState')).toBe(dashboardEmptyStates.LOADING);
+ expect(wrapper.findComponent(EmptyState).exists()).toBe(true);
+ expect(wrapper.findComponent(EmptyState).props('selectedState')).toBe(
+ dashboardEmptyStates.LOADING,
+ );
});
it('hides the group panels when showPanels is false', async () => {
@@ -126,7 +128,7 @@ describe('Dashboard', () => {
describe('panel containers layout', () => {
const findPanelLayoutWrapperAt = (index) => {
return wrapper
- .find(GraphGroup)
+ .findComponent(GraphGroup)
.findAll('[data-testid="dashboard-panel-layout-wrapper"]')
.at(index);
};
@@ -366,7 +368,7 @@ describe('Dashboard', () => {
});
describe('when all panels in the first group are loading', () => {
- const findGroupAt = (i) => wrapper.findAll(GraphGroup).at(i);
+ const findGroupAt = (i) => wrapper.findAllComponents(GraphGroup).at(i);
beforeEach(async () => {
setupStoreWithDashboard(store);
@@ -409,7 +411,7 @@ describe('Dashboard', () => {
setupStoreWithData(store);
await nextTick();
- wrapper.findAll(GraphGroup).wrappers.forEach((groupWrapper) => {
+ wrapper.findAllComponents(GraphGroup).wrappers.forEach((groupWrapper) => {
expect(groupWrapper.props('isLoading')).toBe(false);
});
});
@@ -443,7 +445,7 @@ describe('Dashboard', () => {
});
describe('single panel expands to "full screen" mode', () => {
- const findExpandedPanel = () => wrapper.find({ ref: 'expandedPanel' });
+ const findExpandedPanel = () => wrapper.findComponent({ ref: 'expandedPanel' });
describe('when the panel is not expanded', () => {
beforeEach(async () => {
@@ -457,7 +459,7 @@ describe('Dashboard', () => {
});
it('can set a panel as expanded', () => {
- const panel = wrapper.findAll(DashboardPanel).at(1);
+ const panel = wrapper.findAllComponents(DashboardPanel).at(1);
jest.spyOn(store, 'dispatch');
@@ -503,7 +505,7 @@ describe('Dashboard', () => {
});
it('displays a single panel and others are hidden', () => {
- const panels = wrapper.findAll(MockPanel);
+ const panels = wrapper.findAllComponents(MockPanel);
const visiblePanels = panels.filter((w) => w.isVisible());
expect(findExpandedPanel().isVisible()).toBe(true);
@@ -523,7 +525,7 @@ describe('Dashboard', () => {
});
it('restores full dashboard by clicking `back`', () => {
- wrapper.find({ ref: 'goBackBtn' }).vm.$emit('click');
+ wrapper.findComponent({ ref: 'goBackBtn' }).vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith(
'monitoringDashboard/clearExpandedPanel',
@@ -551,21 +553,21 @@ describe('Dashboard', () => {
});
it('shows a group empty area', () => {
- const emptyGroup = wrapper.findAll({ ref: 'empty-group' });
+ const emptyGroup = wrapper.findAllComponents({ ref: 'empty-group' });
expect(emptyGroup).toHaveLength(1);
expect(emptyGroup.is(GroupEmptyState)).toBe(true);
});
it('group empty area displays a NO_DATA state', () => {
- expect(wrapper.findAll({ ref: 'empty-group' }).at(0).props('selectedState')).toEqual(
- metricStates.NO_DATA,
- );
+ expect(
+ wrapper.findAllComponents({ ref: 'empty-group' }).at(0).props('selectedState'),
+ ).toEqual(metricStates.NO_DATA);
});
});
describe('drag and drop function', () => {
- const findDraggables = () => wrapper.findAll(VueDraggable);
+ const findDraggables = () => wrapper.findAllComponents(VueDraggable);
const findEnabledDraggables = () => findDraggables().filter((f) => !f.attributes('disabled'));
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
@@ -677,7 +679,7 @@ describe('Dashboard', () => {
});
it('hides dashboard header by default', () => {
- expect(wrapper.find({ ref: 'prometheusGraphsHeader' }).exists()).toEqual(false);
+ expect(wrapper.findComponent({ ref: 'prometheusGraphsHeader' }).exists()).toEqual(false);
});
it('renders correctly', () => {
@@ -742,7 +744,7 @@ describe('Dashboard', () => {
const panelIndex = 1; // skip expanded panel
const getClipboardTextFirstPanel = () =>
- wrapper.findAll(DashboardPanel).at(panelIndex).props('clipboardText');
+ wrapper.findAllComponents(DashboardPanel).at(panelIndex).props('clipboardText');
beforeEach(async () => {
setupStoreWithData(store);
@@ -770,7 +772,7 @@ describe('Dashboard', () => {
// While the recommendation in the documentation is to test
// with a data-testid attribute, I want to make sure that
// the dashboard panels have a ref attribute set.
- const getDashboardPanel = () => wrapper.find({ ref: panelRef });
+ const getDashboardPanel = () => wrapper.findComponent({ ref: panelRef });
beforeEach(async () => {
setupStoreWithData(store);
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index 64c48100b31..a327e234581 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -35,7 +35,8 @@ describe('dashboard invalid url parameters', () => {
});
};
- const findDateTimePicker = () => wrapper.find(DashboardHeader).find({ ref: 'dateTimePicker' });
+ const findDateTimePicker = () =>
+ wrapper.findComponent(DashboardHeader).findComponent({ ref: 'dateTimePicker' });
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
index f6d30384847..721992e710a 100644
--- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
+++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
@@ -33,11 +33,11 @@ describe('DashboardsDropdown', () => {
});
}
- const findItems = () => wrapper.findAll(GlDropdownItem);
- const findItemAt = (i) => wrapper.findAll(GlDropdownItem).at(i);
- const findSearchInput = () => wrapper.find({ ref: 'monitorDashboardsDropdownSearch' });
- const findNoItemsMsg = () => wrapper.find({ ref: 'monitorDashboardsDropdownMsg' });
- const findStarredListDivider = () => wrapper.find({ ref: 'starredListDivider' });
+ const findItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findItemAt = (i) => wrapper.findAllComponents(GlDropdownItem).at(i);
+ const findSearchInput = () => wrapper.findComponent({ ref: 'monitorDashboardsDropdownSearch' });
+ const findNoItemsMsg = () => wrapper.findComponent({ ref: 'monitorDashboardsDropdownMsg' });
+ const findStarredListDivider = () => wrapper.findComponent({ ref: 'starredListDivider' });
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
const setSearchTerm = (searchTerm) => wrapper.setData({ searchTerm });
@@ -127,7 +127,7 @@ describe('DashboardsDropdown', () => {
});
it('displays a star icon', () => {
- const star = findItemAt(0).find(GlIcon);
+ const star = findItemAt(0).findComponent(GlIcon);
expect(star.exists()).toBe(true);
expect(star.attributes('name')).toBe('star');
});
@@ -148,7 +148,7 @@ describe('DashboardsDropdown', () => {
});
it('displays no star icon', () => {
- const star = findItemAt(0).find(GlIcon);
+ const star = findItemAt(0).findComponent(GlIcon);
expect(star.exists()).toBe(false);
});
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
index 0dd3afd7c83..755204dc721 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
@@ -18,7 +18,7 @@ const createMountedWrapper = (props = {}) => {
describe('DuplicateDashboardForm', () => {
const defaultBranch = 'main';
- const findByRef = (ref) => wrapper.find({ ref });
+ const findByRef = (ref) => wrapper.findComponent({ ref });
const setValue = (ref, val) => {
findByRef(ref).setValue(val);
};
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
index 7e7a7a66d77..3032c236741 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_modal_spec.js
@@ -44,9 +44,9 @@ describe('duplicate dashboard modal', () => {
});
}
- const findAlert = () => wrapper.find(GlAlert);
- const findModal = () => wrapper.find(GlModal);
- const findDuplicateDashboardForm = () => wrapper.find(DuplicateDashboardForm);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findDuplicateDashboardForm = () => wrapper.findComponent(DuplicateDashboardForm);
beforeEach(() => {
mockDashboards = dashboardGitResponse;
@@ -74,7 +74,7 @@ describe('duplicate dashboard modal', () => {
expect(okEvent.preventDefault).toHaveBeenCalled();
expect(wrapper.emitted().dashboardDuplicated).toBeTruthy();
expect(wrapper.emitted().dashboardDuplicated[0]).toEqual([dashboardGitResponse[0]]);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.vm.$refs.duplicateDashboardModal.hide).toHaveBeenCalled();
expect(findAlert().exists()).toBe(false);
});
@@ -92,7 +92,7 @@ describe('duplicate dashboard modal', () => {
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toBe(errMsg);
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.vm.$refs.duplicateDashboardModal.hide).not.toHaveBeenCalled();
});
@@ -102,7 +102,7 @@ describe('duplicate dashboard modal', () => {
commitMessage: 'A commit message',
};
- findModal().find(DuplicateDashboardForm).vm.$emit('change', formVals);
+ findModal().findComponent(DuplicateDashboardForm).vm.$emit('change', formVals);
// Binding's second argument contains the modal id
expect(wrapper.vm.form).toEqual(formVals);
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index 47366b345a8..6695353bdb5 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -58,14 +58,14 @@ describe('Embed Group', () => {
metricsWithDataGetter.mockReturnValue([]);
mountComponent();
- expect(wrapper.find(GlCard).isVisible()).toBe(false);
+ expect(wrapper.findComponent(GlCard).isVisible()).toBe(false);
});
it('shows the component when chart data is loaded', () => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent();
- expect(wrapper.find(GlCard).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlCard).isVisible()).toBe(true);
});
it('is expanded by default', () => {
@@ -79,7 +79,7 @@ describe('Embed Group', () => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- wrapper.find(GlButton).trigger('click');
+ wrapper.findComponent(GlButton).trigger('click');
await nextTick();
expect(wrapper.find('.gl-card-body').classes()).toContain('d-none');
@@ -93,11 +93,11 @@ describe('Embed Group', () => {
});
it('renders an Embed component', () => {
- expect(wrapper.find(MetricEmbed).exists()).toBe(true);
+ expect(wrapper.findComponent(MetricEmbed).exists()).toBe(true);
});
it('passes the correct props to the Embed component', () => {
- expect(wrapper.find(MetricEmbed).props()).toEqual(singleEmbedProps());
+ expect(wrapper.findComponent(MetricEmbed).props()).toEqual(singleEmbedProps());
});
it('adds the monitoring dashboard module', () => {
@@ -112,7 +112,7 @@ describe('Embed Group', () => {
});
it('passes the correct props to the dashboard Embed component', () => {
- expect(wrapper.find(MetricEmbed).props()).toEqual(dashboardEmbedProps());
+ expect(wrapper.findComponent(MetricEmbed).props()).toEqual(dashboardEmbedProps());
});
it('adds the monitoring dashboard module', () => {
@@ -127,11 +127,11 @@ describe('Embed Group', () => {
});
it('creates Embed components', () => {
- expect(wrapper.findAll(MetricEmbed)).toHaveLength(2);
+ expect(wrapper.findAllComponents(MetricEmbed)).toHaveLength(2);
});
it('passes the correct props to the Embed components', () => {
- expect(wrapper.findAll(MetricEmbed).wrappers.map((item) => item.props())).toEqual(
+ expect(wrapper.findAllComponents(MetricEmbed).wrappers.map((item) => item.props())).toEqual(
multipleEmbedProps(),
);
});
@@ -147,14 +147,14 @@ describe('Embed Group', () => {
metricsWithDataGetter.mockReturnValue([1]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- expect(wrapper.find(GlButton).text()).toBe('Hide chart');
+ expect(wrapper.findComponent(GlButton).text()).toBe('Hide chart');
});
it('has a plural label when there are multiple embeds', () => {
metricsWithDataGetter.mockReturnValue([2]);
mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- expect(wrapper.find(GlButton).text()).toBe('Hide charts');
+ expect(wrapper.findComponent(GlButton).text()).toBe('Hide charts');
});
});
});
diff --git a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
index f9f1be4f277..beff3da2baf 100644
--- a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
+++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
@@ -64,7 +64,7 @@ describe('MetricEmbed', () => {
it('shows an empty state when no metrics are present', () => {
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
- expect(wrapper.find(DashboardPanel).exists()).toBe(false);
+ expect(wrapper.findComponent(DashboardPanel).exists()).toBe(false);
});
});
@@ -92,12 +92,12 @@ describe('MetricEmbed', () => {
it('shows a chart when metrics are present', () => {
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
- expect(wrapper.find(DashboardPanel).exists()).toBe(true);
- expect(wrapper.findAll(DashboardPanel).length).toBe(2);
+ expect(wrapper.findComponent(DashboardPanel).exists()).toBe(true);
+ expect(wrapper.findAllComponents(DashboardPanel).length).toBe(2);
});
it('includes groupId with dashboardUrl', () => {
- expect(wrapper.find(DashboardPanel).props('groupId')).toBe(TEST_HOST);
+ expect(wrapper.findComponent(DashboardPanel).props('groupId')).toBe(TEST_HOST);
});
});
});
diff --git a/spec/frontend/monitoring/components/empty_state_spec.js b/spec/frontend/monitoring/components/empty_state_spec.js
index 1ecb101574b..ddefa8c5cd0 100644
--- a/spec/frontend/monitoring/components/empty_state_spec.js
+++ b/spec/frontend/monitoring/components/empty_state_spec.js
@@ -25,8 +25,8 @@ describe('EmptyState', () => {
selectedState: dashboardEmptyStates.LOADING,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(GlEmptyState).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlEmptyState).exists()).toBe(false);
});
it('shows gettingStarted state', () => {
diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js
index 31f52f6627b..104263e73e0 100644
--- a/spec/frontend/monitoring/components/graph_group_spec.js
+++ b/spec/frontend/monitoring/components/graph_group_spec.js
@@ -6,10 +6,10 @@ import GraphGroup from '~/monitoring/components/graph_group.vue';
describe('Graph group component', () => {
let wrapper;
- const findGroup = () => wrapper.find({ ref: 'graph-group' });
- const findContent = () => wrapper.find({ ref: 'graph-group-content' });
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findCaretIcon = () => wrapper.find(GlIcon);
+ const findGroup = () => wrapper.findComponent({ ref: 'graph-group' });
+ const findContent = () => wrapper.findComponent({ ref: 'graph-group-content' });
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findCaretIcon = () => wrapper.findComponent(GlIcon);
const findToggleButton = () => wrapper.find('[data-testid="group-toggle-button"]');
const createComponent = (propsData) => {
diff --git a/spec/frontend/monitoring/components/group_empty_state_spec.js b/spec/frontend/monitoring/components/group_empty_state_spec.js
index 1dd2ed4e141..e3cd26b0e48 100644
--- a/spec/frontend/monitoring/components/group_empty_state_spec.js
+++ b/spec/frontend/monitoring/components/group_empty_state_spec.js
@@ -45,7 +45,7 @@ describe('GroupEmptyState', () => {
});
it('passes the expected props to GlEmptyState', () => {
- expect(wrapper.find(GlEmptyState).props()).toMatchSnapshot();
+ expect(wrapper.findComponent(GlEmptyState).props()).toMatchSnapshot();
});
});
});
diff --git a/spec/frontend/monitoring/components/links_section_spec.js b/spec/frontend/monitoring/components/links_section_spec.js
index c9b5aeeecb8..94938e7f459 100644
--- a/spec/frontend/monitoring/components/links_section_spec.js
+++ b/spec/frontend/monitoring/components/links_section_spec.js
@@ -21,7 +21,7 @@ describe('Links Section component', () => {
links,
};
};
- const findLinks = () => wrapper.findAll(GlLink);
+ const findLinks = () => wrapper.findAllComponents(GlLink);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index 0e45cc021c5..e00736954a9 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -15,9 +15,9 @@ describe('RefreshButton', () => {
wrapper = shallowMount(RefreshButton, { store, ...options });
};
- const findRefreshBtn = () => wrapper.find(GlButton);
- const findDropdown = () => wrapper.find(GlDropdown);
- const findOptions = () => findDropdown().findAll(GlDropdownItem);
+ const findRefreshBtn = () => wrapper.findComponent(GlButton);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findOptions = () => findDropdown().findAllComponents(GlDropdownItem);
const findOptionAt = (index) => findOptions().at(index);
const expectFetchDataToHaveBeenCalledTimes = (times) => {
diff --git a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
index 643bbb39f04..012e2e9c3e2 100644
--- a/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
+++ b/spec/frontend/monitoring/components/variables/dropdown_field_spec.js
@@ -27,8 +27,8 @@ describe('Custom variable component', () => {
});
};
- const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
it('renders dropdown element when all necessary props are passed', () => {
createShallowWrapper();
diff --git a/spec/frontend/monitoring/components/variables_section_spec.js b/spec/frontend/monitoring/components/variables_section_spec.js
index 64b93bd3027..d6f8aac99aa 100644
--- a/spec/frontend/monitoring/components/variables_section_spec.js
+++ b/spec/frontend/monitoring/components/variables_section_spec.js
@@ -24,8 +24,8 @@ describe('Metrics dashboard/variables section component', () => {
});
};
- const findTextInputs = () => wrapper.findAll(TextField);
- const findCustomInputs = () => wrapper.findAll(DropdownField);
+ const findTextInputs = () => wrapper.findAllComponents(TextField);
+ const findCustomInputs = () => wrapper.findAllComponents(DropdownField);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/monitoring/pages/panel_new_page_spec.js b/spec/frontend/monitoring/pages/panel_new_page_spec.js
index c89cbc52bcb..fa112fca2db 100644
--- a/spec/frontend/monitoring/pages/panel_new_page_spec.js
+++ b/spec/frontend/monitoring/pages/panel_new_page_spec.js
@@ -41,8 +41,8 @@ describe('monitoring/pages/panel_new_page', () => {
});
};
- const findBackButton = () => wrapper.find(GlButtonStub);
- const findPanelBuilder = () => wrapper.find(DashboardPanelBuilder);
+ const findBackButton = () => wrapper.findComponent(GlButtonStub);
+ const findPanelBuilder = () => wrapper.findComponent(DashboardPanelBuilder);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/monitoring/router_spec.js b/spec/frontend/monitoring/router_spec.js
index 7758dd351b7..368bd955fb3 100644
--- a/spec/frontend/monitoring/router_spec.js
+++ b/spec/frontend/monitoring/router_spec.js
@@ -61,8 +61,8 @@ describe('Monitoring router', () => {
currentDashboard,
});
- expect(wrapper.find(DashboardPage).exists()).toBe(true);
- expect(wrapper.find(DashboardPage).find(Dashboard).exists()).toBe(true);
+ expect(wrapper.findComponent(DashboardPage).exists()).toBe(true);
+ expect(wrapper.findComponent(DashboardPage).findComponent(Dashboard).exists()).toBe(true);
});
});
@@ -84,8 +84,8 @@ describe('Monitoring router', () => {
currentDashboard,
});
- expect(wrapper.find(DashboardPage).exists()).toBe(true);
- expect(wrapper.find(DashboardPage).find(Dashboard).exists()).toBe(true);
+ expect(wrapper.findComponent(DashboardPage).exists()).toBe(true);
+ expect(wrapper.findComponent(DashboardPage).findComponent(Dashboard).exists()).toBe(true);
});
});
@@ -100,7 +100,7 @@ describe('Monitoring router', () => {
const wrapper = createWrapper(BASE_PATH, path);
expect(wrapper.vm.$route.params.dashboard).toBe(currentDashboard);
- expect(wrapper.find(PanelNewPage).exists()).toBe(true);
+ expect(wrapper.findComponent(PanelNewPage).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js
index c25de8caa95..54f9c59308e 100644
--- a/spec/frontend/monitoring/store/utils_spec.js
+++ b/spec/frontend/monitoring/store/utils_spec.js
@@ -511,10 +511,10 @@ describe('mapToDashboardViewModel', () => {
describe('uniqMetricsId', () => {
[
{ input: { id: 1 }, expected: `${NOT_IN_DB_PREFIX}_1` },
- { input: { metric_id: 2 }, expected: '2_undefined' },
- { input: { metric_id: 2, id: 21 }, expected: '2_21' },
- { input: { metric_id: 22, id: 1 }, expected: '22_1' },
- { input: { metric_id: 'aaa', id: '_a' }, expected: 'aaa__a' },
+ { input: { metricId: 2 }, expected: '2_undefined' },
+ { input: { metricId: 2, id: 21 }, expected: '2_21' },
+ { input: { metricId: 22, id: 1 }, expected: '22_1' },
+ { input: { metricId: 'aaa', id: '_a' }, expected: 'aaa__a' },
].forEach(({ input, expected }) => {
it(`creates unique metric ID with ${JSON.stringify(input)}`, () => {
expect(uniqMetricsId(input)).toEqual(expected);
diff --git a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
index 70df05a2781..6cfbdb16111 100644
--- a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
+++ b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js
@@ -124,7 +124,7 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => {
});
it('clicked on link with view', () => {
- expect(primaryLink.props('menuItem').view).toBeTruthy();
+ expect(primaryLink.props('menuItem').view).toBe(TEST_NAV_DATA.views.projects.namespace);
});
it('changes active view', () => {
diff --git a/spec/frontend/notes/components/comment_field_layout_spec.js b/spec/frontend/notes/components/comment_field_layout_spec.js
index d69c2c4adfa..6662492fd81 100644
--- a/spec/frontend/notes/components/comment_field_layout_spec.js
+++ b/spec/frontend/notes/components/comment_field_layout_spec.js
@@ -22,8 +22,8 @@ describe('Comment Field Layout Component', () => {
confidential_issues_docs_path: CONFIDENTIAL_ISSUES_DOCS_PATH,
};
- const findIssuableNoteWarning = () => wrapper.find(NoteableWarning);
- const findEmailParticipantsWarning = () => wrapper.find(EmailParticipantsWarning);
+ const findIssuableNoteWarning = () => wrapper.findComponent(NoteableWarning);
+ const findEmailParticipantsWarning = () => wrapper.findComponent(EmailParticipantsWarning);
const findErrorAlert = () => wrapper.findByTestId('comment-field-alert-container');
const createWrapper = (props = {}, slots = {}) => {
diff --git a/spec/frontend/notes/components/diff_discussion_header_spec.js b/spec/frontend/notes/components/diff_discussion_header_spec.js
index 7878737fd31..5800f68b114 100644
--- a/spec/frontend/notes/components/diff_discussion_header_spec.js
+++ b/spec/frontend/notes/components/diff_discussion_header_spec.js
@@ -1,6 +1,7 @@
-import { mount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
+import { GlAvatar, GlAvatarLink } from '@gitlab/ui';
import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue';
import createStore from '~/notes/stores';
@@ -15,7 +16,7 @@ describe('diff_discussion_header component', () => {
window.mrTabs = {};
store = createStore();
- wrapper = mount(diffDiscussionHeader, {
+ wrapper = shallowMount(diffDiscussionHeader, {
store,
propsData: { discussion: discussionMock },
});
@@ -25,15 +26,25 @@ describe('diff_discussion_header component', () => {
wrapper.destroy();
});
- it('should render user avatar', async () => {
- const discussion = { ...discussionMock };
- discussion.diff_file = mockDiffFile;
- discussion.diff_discussion = true;
+ describe('Avatar', () => {
+ const firstNoteAuthor = discussionMock.notes[0].author;
+ const findAvatarLink = () => wrapper.findComponent(GlAvatarLink);
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
- wrapper.setProps({ discussion });
+ it('should render user avatar and user avatar link', () => {
+ expect(findAvatar().exists()).toBe(true);
+ expect(findAvatarLink().exists()).toBe(true);
+ });
+
+ it('renders avatar of the first note author', () => {
+ const props = findAvatar().props();
- await nextTick();
- expect(wrapper.find('.user-avatar-link').exists()).toBe(true);
+ expect(props).toMatchObject({
+ src: firstNoteAuthor.avatar_url,
+ alt: firstNoteAuthor.name,
+ size: { default: 24, md: 32 },
+ });
+ });
});
describe('action text', () => {
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index 925dbcc09ec..d16c13d6fd3 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -47,9 +47,9 @@ describe('DiscussionActions', () => {
it('renders reply placeholder, resolve discussion button, resolve with issue button and jump to next discussion button', () => {
createComponent();
- expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
- expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(true);
- expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(true);
+ expect(wrapper.findComponent(ReplyPlaceholder).exists()).toBe(true);
+ expect(wrapper.findComponent(ResolveDiscussionButton).exists()).toBe(true);
+ expect(wrapper.findComponent(ResolveWithIssueButton).exists()).toBe(true);
});
it('only renders reply placholder if disccusion is not resolvable', () => {
@@ -57,15 +57,15 @@ describe('DiscussionActions', () => {
discussion.resolvable = false;
createComponent({ discussion });
- expect(wrapper.find(ReplyPlaceholder).exists()).toBe(true);
- expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false);
- expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
+ expect(wrapper.findComponent(ReplyPlaceholder).exists()).toBe(true);
+ expect(wrapper.findComponent(ResolveDiscussionButton).exists()).toBe(false);
+ expect(wrapper.findComponent(ResolveWithIssueButton).exists()).toBe(false);
});
it('does not render resolve with issue button if resolveWithIssuePath is falsy', () => {
createComponent({ resolveWithIssuePath: '' });
- expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
+ expect(wrapper.findComponent(ResolveWithIssueButton).exists()).toBe(false);
});
describe.each`
@@ -82,8 +82,8 @@ describe('DiscussionActions', () => {
});
it(shouldRender ? 'renders resolve buttons' : 'does not render resolve buttons', () => {
- expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(shouldRender);
- expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(shouldRender);
+ expect(wrapper.findComponent(ResolveDiscussionButton).exists()).toBe(shouldRender);
+ expect(wrapper.findComponent(ResolveWithIssueButton).exists()).toBe(shouldRender);
});
});
});
@@ -95,7 +95,7 @@ describe('DiscussionActions', () => {
createComponent({}, { attachTo: document.body });
jest.spyOn(wrapper.vm, '$emit');
- wrapper.find(ReplyPlaceholder).find('textarea').trigger('focus');
+ wrapper.findComponent(ReplyPlaceholder).find('textarea').trigger('focus');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('showReplyForm');
});
@@ -103,7 +103,7 @@ describe('DiscussionActions', () => {
createComponent();
jest.spyOn(wrapper.vm, '$emit');
- wrapper.find(ResolveDiscussionButton).find('button').trigger('click');
+ wrapper.findComponent(ResolveDiscussionButton).find('button').trigger('click');
expect(wrapper.vm.$emit).toHaveBeenCalledWith('resolve');
});
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index f016cef18e6..a7e2f1efa09 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -47,7 +47,7 @@ describe('DiscussionCounter component', () => {
it('does not render', () => {
wrapper = shallowMount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
- expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(false);
+ expect(wrapper.findComponent({ ref: 'discussionCounter' }).exists()).toBe(false);
});
});
@@ -57,7 +57,7 @@ describe('DiscussionCounter component', () => {
store.dispatch('updateResolvableDiscussionsCounts');
wrapper = shallowMount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
- expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(false);
+ expect(wrapper.findComponent({ ref: 'discussionCounter' }).exists()).toBe(false);
});
});
@@ -77,7 +77,7 @@ describe('DiscussionCounter component', () => {
updateStore();
wrapper = shallowMount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
- expect(wrapper.find({ ref: 'discussionCounter' }).exists()).toBe(true);
+ expect(wrapper.findComponent({ ref: 'discussionCounter' }).exists()).toBe(true);
});
it.each`
@@ -103,7 +103,7 @@ describe('DiscussionCounter component', () => {
updateStore({ resolvable: true, resolved });
wrapper = shallowMount(DiscussionCounter, { store, propsData: { blocksMerge: true } });
- expect(wrapper.findAll(GlButton)).toHaveLength(groupLength);
+ expect(wrapper.findAllComponents(GlButton)).toHaveLength(groupLength);
});
});
diff --git a/spec/frontend/notes/components/discussion_filter_note_spec.js b/spec/frontend/notes/components/discussion_filter_note_spec.js
index ad9a2e898eb..48f5030aa1a 100644
--- a/spec/frontend/notes/components/discussion_filter_note_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_note_spec.js
@@ -31,14 +31,14 @@ describe('DiscussionFilterNote component', () => {
it('emits `dropdownSelect` event with 0 parameter on clicking Show all activity button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper.findAll(GlButton).at(0).vm.$emit('click');
+ wrapper.findAllComponents(GlButton).at(0).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 0);
});
it('emits `dropdownSelect` event with 1 parameter on clicking Show comments only button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- wrapper.findAll(GlButton).at(1).vm.$emit('click');
+ wrapper.findAllComponents(GlButton).at(1).vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
});
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 3506b6ac9f3..1b8b6bec490 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -61,13 +61,13 @@ describe('DiscussionNotes', () => {
it('renders an element for each note in the discussion', () => {
createComponent();
const notesCount = discussionMock.notes.length;
- const els = wrapper.findAll(NoteableNote);
+ const els = wrapper.findAllComponents(NoteableNote);
expect(els.length).toBe(notesCount);
});
it('renders one element if replies groupping is enabled', () => {
createComponent({ shouldGroupReplies: true });
- const els = wrapper.findAll(NoteableNote);
+ const els = wrapper.findAllComponents(NoteableNote);
expect(els.length).toBe(1);
});
diff --git a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
index 3932f818c4e..971e3987929 100644
--- a/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
+++ b/spec/frontend/notes/components/discussion_reply_placeholder_spec.js
@@ -15,7 +15,7 @@ describe('ReplyPlaceholder', () => {
});
};
- const findTextarea = () => wrapper.find({ ref: 'textarea' });
+ const findTextarea = () => wrapper.findComponent({ ref: 'textarea' });
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index ca0c0ca6de8..17c3523cf48 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -28,7 +28,7 @@ describe('resolveDiscussionButton', () => {
});
it('should emit a onClick event on button click', async () => {
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
button.vm.$emit('click');
@@ -39,7 +39,7 @@ describe('resolveDiscussionButton', () => {
});
it('should contain the provided button title', () => {
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.text()).toContain(buttonTitle);
});
@@ -52,7 +52,7 @@ describe('resolveDiscussionButton', () => {
},
});
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.props('loading')).toEqual(true);
});
@@ -65,7 +65,7 @@ describe('resolveDiscussionButton', () => {
},
});
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
await nextTick();
expect(button.props('loading')).toEqual(false);
diff --git a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
index 5bc6282db03..71406eeb7b4 100644
--- a/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_with_issue_button_spec.js
@@ -20,7 +20,7 @@ describe('ResolveWithIssueButton', () => {
});
it('it should have a link with the provided link property as href', () => {
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
expect(button.attributes().href).toBe(url);
});
diff --git a/spec/frontend/notes/components/note_actions/reply_button_spec.js b/spec/frontend/notes/components/note_actions/reply_button_spec.js
index 4993ded365d..20b32b8c178 100644
--- a/spec/frontend/notes/components/note_actions/reply_button_spec.js
+++ b/spec/frontend/notes/components/note_actions/reply_button_spec.js
@@ -15,7 +15,7 @@ describe('ReplyButton', () => {
});
it('emits startReplying on click', () => {
- wrapper.find(GlButton).vm.$emit('click');
+ wrapper.findComponent(GlButton).vm.$emit('click');
expect(wrapper.emitted('startReplying')).toEqual([[]]);
});
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index bf5a6b4966a..cbe11c20798 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -16,7 +16,7 @@ describe('noteActions', () => {
let actions;
let axiosMock;
- const findUserAccessRoleBadge = (idx) => wrapper.findAll(UserAccessRoleBadge).at(idx);
+ const findUserAccessRoleBadge = (idx) => wrapper.findAllComponents(UserAccessRoleBadge).at(idx);
const findUserAccessRoleBadgeText = (idx) => findUserAccessRoleBadge(idx).text().trim();
const mountNoteActions = (propsData, computed) => {
@@ -159,7 +159,7 @@ describe('noteActions', () => {
});
});
- describe('when a user has access to edit an issue', () => {
+ describe('when a user can set metadata of an issue', () => {
const testButtonClickTriggersAction = () => {
axiosMock.onPut(`${TEST_HOST}/api/v4/projects/group/project/issues/1`).reply(() => {
expect(actions.updateAssignees).toHaveBeenCalled();
@@ -176,7 +176,7 @@ describe('noteActions', () => {
});
store.state.noteableData = {
current_user: {
- can_update: true,
+ can_set_issue_metadata: true,
},
};
store.state.userData = userDataMock;
@@ -191,6 +191,31 @@ describe('noteActions', () => {
it('should be possible to unassign the comment author', testButtonClickTriggersAction);
});
+ describe('when a user can update but not set metadata of an issue', () => {
+ beforeEach(() => {
+ wrapper = mountNoteActions(props, {
+ targetType: () => 'issue',
+ });
+ store.state.noteableData = {
+ current_user: {
+ can_update: true,
+ can_set_issue_metadata: false,
+ },
+ };
+ store.state.userData = userDataMock;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ axiosMock.restore();
+ });
+
+ it('should not be possible to assign or unassign the comment author', () => {
+ const assignUserButton = wrapper.find('[data-testid="assign-user"]');
+ expect(assignUserButton.exists()).toBe(false);
+ });
+ });
+
describe('when a user does not have access to edit an issue', () => {
const testButtonDoesNotRender = () => {
const assignUserButton = wrapper.find('[data-testid="assign-user"]');
@@ -241,7 +266,7 @@ describe('noteActions', () => {
});
it('shows a reply button', () => {
- const replyButton = wrapper.find({ ref: 'replyButton' });
+ const replyButton = wrapper.findComponent({ ref: 'replyButton' });
expect(replyButton.exists()).toBe(true);
});
@@ -256,7 +281,7 @@ describe('noteActions', () => {
});
it('does not show a reply button', () => {
- const replyButton = wrapper.find({ ref: 'replyButton' });
+ const replyButton = wrapper.findComponent({ ref: 'replyButton' });
expect(replyButton.exists()).toBe(false);
});
@@ -270,7 +295,7 @@ describe('noteActions', () => {
});
it('should render the right resolve button title', () => {
- const resolveButton = wrapper.find({ ref: 'resolveButton' });
+ const resolveButton = wrapper.findComponent({ ref: 'resolveButton' });
expect(resolveButton.exists()).toBe(true);
expect(resolveButton.attributes('title')).toBe('Thread stays unresolved');
diff --git a/spec/frontend/notes/components/note_attachment_spec.js b/spec/frontend/notes/components/note_attachment_spec.js
index d47c2beaaf8..24632f8e427 100644
--- a/spec/frontend/notes/components/note_attachment_spec.js
+++ b/spec/frontend/notes/components/note_attachment_spec.js
@@ -4,8 +4,8 @@ import NoteAttachment from '~/notes/components/note_attachment.vue';
describe('Issue note attachment', () => {
let wrapper;
- const findImage = () => wrapper.find({ ref: 'attachmentImage' });
- const findUrl = () => wrapper.find({ ref: 'attachmentUrl' });
+ const findImage = () => wrapper.findComponent({ ref: 'attachmentImage' });
+ const findUrl = () => wrapper.findComponent({ ref: 'attachmentUrl' });
const createComponent = (attachment) => {
wrapper = shallowMount(NoteAttachment, {
diff --git a/spec/frontend/notes/components/note_body_spec.js b/spec/frontend/notes/components/note_body_spec.js
index 0f765a8da87..c2e56d3e7a7 100644
--- a/spec/frontend/notes/components/note_body_spec.js
+++ b/spec/frontend/notes/components/note_body_spec.js
@@ -7,7 +7,6 @@ import NoteAwardsList from '~/notes/components/note_awards_list.vue';
import NoteForm from '~/notes/components/note_form.vue';
import createStore from '~/notes/stores';
import notes from '~/notes/stores/modules/index';
-import { INTERNAL_NOTE_CLASSES } from '~/notes/constants';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
@@ -59,22 +58,10 @@ describe('issue_note_body component', () => {
expect(wrapper.findComponent(NoteAwardsList).exists()).toBe(true);
});
- it('should not have internal note classes', () => {
- expect(wrapper.findByTestId('note-internal-container').classes()).not.toEqual(
- INTERNAL_NOTE_CLASSES,
- );
- });
-
describe('isInternalNote', () => {
beforeEach(() => {
wrapper = createComponent({ props: { isInternalNote: true } });
});
-
- it('should have internal note classes', () => {
- expect(wrapper.findByTestId('note-internal-container').classes()).toEqual(
- INTERNAL_NOTE_CLASSES,
- );
- });
});
describe('isEditing', () => {
@@ -110,12 +97,6 @@ describe('issue_note_body component', () => {
beforeEach(() => {
wrapper.setProps({ isInternalNote: true });
});
-
- it('should not have internal note classes', () => {
- expect(wrapper.findByTestId('note-internal-container').classes()).not.toEqual(
- INTERNAL_NOTE_CLASSES,
- );
- });
});
});
@@ -162,7 +143,7 @@ describe('issue_note_body component', () => {
});
it('passes the correct default placeholder commit message for a suggestion to the suggestions component', () => {
- const commitMessage = wrapper.find(Suggestions).attributes('defaultcommitmessage');
+ const commitMessage = wrapper.findComponent(Suggestions).attributes('defaultcommitmessage');
expect(commitMessage).toBe('branch/pathnameuseruser usertonabc11');
});
diff --git a/spec/frontend/notes/components/note_form_spec.js b/spec/frontend/notes/components/note_form_spec.js
index 252c24d1117..fad04e9063d 100644
--- a/spec/frontend/notes/components/note_form_spec.js
+++ b/spec/frontend/notes/components/note_form_spec.js
@@ -6,6 +6,7 @@ import { getDraft, updateDraft } from '~/lib/utils/autosave';
import NoteForm from '~/notes/components/note_form.vue';
import createStore from '~/notes/stores';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import { AT_WHO_ACTIVE_CLASS } from '~/gfm_auto_complete';
import { noteableDataMock, notesDataMock, discussionMock, note } from '../mock_data';
jest.mock('~/lib/utils/autosave');
@@ -91,7 +92,7 @@ describe('issue_note_form component', () => {
expect(conflictWarning.exists()).toBe(true);
expect(conflictWarning.text().replace(/\s+/g, ' ').trim()).toBe(message);
- expect(conflictWarning.find(GlLink).attributes('href')).toBe('#note_545');
+ expect(conflictWarning.findComponent(GlLink).attributes('href')).toBe('#note_545');
});
});
@@ -133,7 +134,7 @@ describe('issue_note_form component', () => {
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
- const markdownField = wrapper.find(MarkdownField);
+ const markdownField = wrapper.findComponent(MarkdownField);
const markdownFieldProps = markdownField.props();
expect(markdownFieldProps.markdownDocsPath).toBe(markdownDocsPath);
@@ -201,6 +202,21 @@ describe('issue_note_form component', () => {
expect(wrapper.emitted().cancelForm).toHaveLength(1);
});
+ it('will not cancel form if there is an active at-who-active class', async () => {
+ wrapper.setProps({
+ ...props,
+ });
+ await nextTick();
+
+ const textareaEl = wrapper.vm.$refs.textarea;
+ const cancelButton = findCancelButton();
+ textareaEl.classList.add(AT_WHO_ACTIVE_CLASS);
+ cancelButton.vm.$emit('click');
+ await nextTick();
+
+ expect(wrapper.emitted().cancelForm).toBeUndefined();
+ });
+
it('should be possible to update the note', async () => {
wrapper.setProps({
...props,
diff --git a/spec/frontend/notes/components/note_header_spec.js b/spec/frontend/notes/components/note_header_spec.js
index ad2cf1c5a35..43fbc5e26dc 100644
--- a/spec/frontend/notes/components/note_header_spec.js
+++ b/spec/frontend/notes/components/note_header_spec.js
@@ -15,15 +15,15 @@ const actions = {
describe('NoteHeader component', () => {
let wrapper;
- const findActionsWrapper = () => wrapper.find({ ref: 'discussionActions' });
+ const findActionsWrapper = () => wrapper.findComponent({ ref: 'discussionActions' });
const findToggleThreadButton = () => wrapper.findByTestId('thread-toggle');
- const findChevronIcon = () => wrapper.find({ ref: 'chevronIcon' });
- const findActionText = () => wrapper.find({ ref: 'actionText' });
- const findTimestampLink = () => wrapper.find({ ref: 'noteTimestampLink' });
- const findTimestamp = () => wrapper.find({ ref: 'noteTimestamp' });
+ const findChevronIcon = () => wrapper.findComponent({ ref: 'chevronIcon' });
+ const findActionText = () => wrapper.findComponent({ ref: 'actionText' });
+ const findTimestampLink = () => wrapper.findComponent({ ref: 'noteTimestampLink' });
+ const findTimestamp = () => wrapper.findComponent({ ref: 'noteTimestamp' });
const findInternalNoteIndicator = () => wrapper.findByTestId('internalNoteIndicator');
- const findSpinner = () => wrapper.find({ ref: 'spinner' });
- const findAuthorStatus = () => wrapper.find({ ref: 'authorStatus' });
+ 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>"';
@@ -228,7 +228,7 @@ describe('NoteHeader component', () => {
const dispatchEvent = jest.spyOn(wrapper.vm.$refs.authorNameLink, 'dispatchEvent');
- wrapper.find({ ref: 'authorUsernameLink' }).trigger('mouseenter');
+ wrapper.findComponent({ ref: 'authorUsernameLink' }).trigger('mouseenter');
expect(dispatchEvent).toHaveBeenCalledWith(new Event('mouseenter'));
});
@@ -238,7 +238,7 @@ describe('NoteHeader component', () => {
const dispatchEvent = jest.spyOn(wrapper.vm.$refs.authorNameLink, 'dispatchEvent');
- wrapper.find({ ref: 'authorUsernameLink' }).trigger('mouseleave');
+ wrapper.findComponent({ ref: 'authorUsernameLink' }).trigger('mouseleave');
expect(dispatchEvent).toHaveBeenCalledWith(new Event('mouseleave'));
});
@@ -266,8 +266,8 @@ describe('NoteHeader component', () => {
it('toggles hover specific CSS classes on author name link', async () => {
createComponent({ author });
- const authorUsernameLink = wrapper.find({ ref: 'authorUsernameLink' });
- const authorNameLink = wrapper.find({ ref: 'authorNameLink' });
+ const authorUsernameLink = wrapper.findComponent({ ref: 'authorUsernameLink' });
+ const authorNameLink = wrapper.findComponent({ ref: 'authorNameLink' });
authorUsernameLink.trigger('mouseenter');
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 603db56a098..b34305688d9 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -73,13 +73,13 @@ describe('noteable_discussion component', () => {
expect(wrapper.vm.isReplying).toEqual(false);
- const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ const replyPlaceholder = wrapper.findComponent(ReplyPlaceholder);
replyPlaceholder.vm.$emit('focus');
await nextTick();
expect(wrapper.vm.isReplying).toEqual(true);
- const noteForm = wrapper.find(NoteForm);
+ const noteForm = wrapper.findComponent(NoteForm);
expect(noteForm.exists()).toBe(true);
@@ -100,11 +100,11 @@ describe('noteable_discussion component', () => {
wrapper.setProps({ discussion: { ...discussionMock, confidential: isNoteInternal } });
await nextTick();
- const replyPlaceholder = wrapper.find(ReplyPlaceholder);
+ const replyPlaceholder = wrapper.findComponent(ReplyPlaceholder);
replyPlaceholder.vm.$emit('focus');
await nextTick();
- expect(wrapper.find(NoteForm).props('saveButtonTitle')).toBe(saveButtonTitle);
+ expect(wrapper.findComponent(NoteForm).props('saveButtonTitle')).toBe(saveButtonTitle);
},
);
@@ -116,7 +116,7 @@ describe('noteable_discussion component', () => {
await nextTick();
- wrapper.find(DiscussionNotes).vm.$emit('startReplying');
+ wrapper.findComponent(DiscussionNotes).vm.$emit('startReplying');
await nextTick();
@@ -139,7 +139,7 @@ describe('noteable_discussion component', () => {
});
it('does not display a button to resolve with issue', () => {
- const button = wrapper.find(ResolveWithIssueButton);
+ const button = wrapper.findComponent(ResolveWithIssueButton);
expect(button.exists()).toBe(false);
});
@@ -159,7 +159,7 @@ describe('noteable_discussion component', () => {
});
it('displays a button to resolve with issue', () => {
- const button = wrapper.find(ResolveWithIssueButton);
+ const button = wrapper.findComponent(ResolveWithIssueButton);
expect(button.exists()).toBe(true);
});
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 3350609bb90..e049c5bc0c8 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -285,11 +285,25 @@ describe('issue_note', () => {
await waitForPromises();
expect(alertSpy).not.toHaveBeenCalled();
expect(wrapper.vm.note.note_html).toBe(
- '<p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"></p>\n',
+ '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">',
);
});
});
+ describe('internal note', () => {
+ it('has internal note class for internal notes', () => {
+ createWrapper({ note: { ...note, confidential: true } });
+
+ expect(wrapper.classes()).toContain('internal-note');
+ });
+
+ it('does not have internal note class for external notes', () => {
+ createWrapper({ note });
+
+ expect(wrapper.classes()).not.toContain('internal-note');
+ });
+ });
+
describe('cancel edit', () => {
beforeEach(() => {
createWrapper();
@@ -357,7 +371,7 @@ describe('issue_note', () => {
createWrapper();
updateActions();
wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', params);
- expect(wrapper.emitted('handleUpdateNote')).toBeTruthy();
+ expect(wrapper.emitted('handleUpdateNote')).toHaveLength(1);
});
it('does not stringify empty position', () => {
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index 36a68118fa7..d4cb07d97dc 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -4,7 +4,6 @@ import $ from 'jquery';
import { nextTick } from 'vue';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import setWindowLocation from 'helpers/set_window_location_helper';
-import { setTestTimeout } from 'helpers/timeout';
import waitForPromises from 'helpers/wait_for_promises';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
@@ -19,8 +18,6 @@ import '~/behaviors/markdown/render_gfm';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import * as mockData from '../mock_data';
-setTestTimeout(1000);
-
const TYPE_COMMENT_FORM = 'comment-form';
const TYPE_NOTES_LIST = 'notes-list';
@@ -359,7 +356,7 @@ describe('note_app', () => {
});
it('should listen hashchange event', () => {
- const notesApp = wrapper.find(NotesApp);
+ const notesApp = wrapper.findComponent(NotesApp);
const hash = 'some dummy hash';
jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce(hash);
const setTargetNoteHash = jest.spyOn(notesApp.vm, 'setTargetNoteHash');
@@ -439,7 +436,7 @@ describe('note_app', () => {
});
it('correctly finds only draft comments', () => {
- const drafts = wrapper.findAll(DraftNote).wrappers;
+ const drafts = wrapper.findAllComponents(DraftNote).wrappers;
expect(drafts.map((x) => x.props('draft'))).toEqual(
mockData.draftComments.map(({ note }) => expect.objectContaining({ note })),
diff --git a/spec/frontend/notes/components/sort_discussion_spec.js b/spec/frontend/notes/components/sort_discussion_spec.js
index bde27b7e5fc..8b6e05da3c0 100644
--- a/spec/frontend/notes/components/sort_discussion_spec.js
+++ b/spec/frontend/notes/components/sort_discussion_spec.js
@@ -21,7 +21,7 @@ describe('Sort Discussion component', () => {
});
};
- const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/notes/components/timeline_toggle_spec.js b/spec/frontend/notes/components/timeline_toggle_spec.js
index 84fa3008835..cf79416d300 100644
--- a/spec/frontend/notes/components/timeline_toggle_spec.js
+++ b/spec/frontend/notes/components/timeline_toggle_spec.js
@@ -27,7 +27,7 @@ describe('Timeline toggle', () => {
});
};
- const findGlButton = () => wrapper.find(GlButton);
+ const findGlButton = () => wrapper.findComponent(GlButton);
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/notes/deprecated_notes_spec.js b/spec/frontend/notes/deprecated_notes_spec.js
index 40b124b9029..d5e2a189afe 100644
--- a/spec/frontend/notes/deprecated_notes_spec.js
+++ b/spec/frontend/notes/deprecated_notes_spec.js
@@ -7,7 +7,6 @@ import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { createSpyObj } from 'helpers/jest_helpers';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
-import { setTestTimeoutOnce } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -48,7 +47,6 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
// random failures.
// It seems that running tests in parallel increases failure rate.
jest.setTimeout(4000);
- setTestTimeoutOnce(4000);
});
afterEach(async () => {
@@ -510,7 +508,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
notes.putEditFormInPlace($el);
- expect(notes.glForm.enableGFM).toBeTruthy();
+ expect(notes.glForm.enableGFM).toBe('');
});
});
@@ -783,21 +781,21 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
const hasQuickActions = notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeTruthy();
+ expect(hasQuickActions).toBe(true);
});
it('should return false when comment does NOT begin with a quick action', () => {
const sampleComment = 'Hey, /unassign Merging this';
const hasQuickActions = notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeFalsy();
+ expect(hasQuickActions).toBe(false);
});
it('should return false when comment does NOT have any quick actions', () => {
const sampleComment = 'Looking good, Awesome!';
const hasQuickActions = notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeFalsy();
+ expect(hasQuickActions).toBe(false);
});
});
@@ -887,14 +885,14 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
expect($tempNote.prop('nodeName')).toEqual('LI');
expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ expect($tempNote.hasClass('being-posted')).toBe(true);
+ expect($tempNote.hasClass('fade-in-half')).toBe(true);
$tempNote.find('.timeline-icon > a, .note-header-info > a').each((i, el) => {
expect(el.getAttribute('href')).toEqual(`/${currentUsername}`);
});
expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBe(false);
expect($tempNoteHeader.find('.d-none.d-sm-inline-block').text().trim()).toEqual(
currentUserFullname,
);
@@ -916,7 +914,7 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
});
expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeTruthy();
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBe(true);
});
it('should return a escaped user name', () => {
@@ -954,8 +952,8 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
expect($tempNote.prop('nodeName')).toEqual('LI');
expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ expect($tempNote.hasClass('being-posted')).toBe(true);
+ expect($tempNote.hasClass('fade-in-half')).toBe(true);
expect($tempNote.find('.timeline-content i').text().trim()).toEqual(sampleCommandDescription);
});
});
diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js
index c1fa1d24a82..21145466016 100644
--- a/spec/frontend/operation_settings/components/metrics_settings_spec.js
+++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js
@@ -105,7 +105,10 @@ describe('operation settings external dashboard component', () => {
it('uses description text', () => {
const description = formGroup.find('small');
- expect(description.text()).not.toBeFalsy();
+ const expectedDescription =
+ "Choose whether to display dashboard metrics in UTC or the user's local timezone.";
+
+ expect(description.text()).toBe(expectedDescription);
});
});
@@ -138,7 +141,10 @@ describe('operation settings external dashboard component', () => {
it('uses description text', () => {
const description = formGroup.find('small');
- expect(description.text()).not.toBeFalsy();
+ const expectedDescription =
+ 'Add a button to the metrics dashboard linking directly to your existing external dashboard.';
+
+ expect(description.text()).toBe(expectedDescription);
});
});
@@ -151,7 +157,6 @@ describe('operation settings external dashboard component', () => {
});
it('defaults to externalDashboardUrl', () => {
- expect(input.attributes().value).toBeTruthy();
expect(input.attributes().value).toBe(externalDashboardUrl);
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index ef6c4a1fa32..b163557618e 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -4,7 +4,6 @@ import { GlEmptyState } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { stripTypenames } from 'helpers/graphql_helpers';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
@@ -96,8 +95,8 @@ describe('Tags List', () => {
it('binds the correct props', () => {
expect(findRegistryList().props()).toMatchObject({
title: '2 tags',
- pagination: stripTypenames(tagsPageInfo),
- items: stripTypenames(tags),
+ pagination: tagsPageInfo,
+ items: tags,
idProperty: 'name',
});
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
index a5b2b1d7cf8..61503d0f3bf 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
@@ -90,18 +90,26 @@ describe('cleanup_status', () => {
`(
'when the status is $status is $visible that the extra icon is visible',
({ status, visible }) => {
- mountComponent({ status });
+ mountComponent({ status, expirationPolicy: { next_run_at: '2063-04-08T01:44:03Z' } });
expect(findExtraInfoIcon().exists()).toBe(visible);
},
);
+ it(`when the status is ${UNFINISHED_STATUS} & expirationPolicy does not exist the extra icon is not visible`, () => {
+ mountComponent({
+ status: UNFINISHED_STATUS,
+ });
+
+ expect(findExtraInfoIcon().exists()).toBe(false);
+ });
+
it(`has a popover with a learn more link and a time frame for the next run`, () => {
jest.spyOn(Date, 'now').mockImplementation(() => new Date('2063-04-04T00:42:00Z').getTime());
mountComponent({
status: UNFINISHED_STATUS,
- expirationPolicy: { next_run: '2063-04-08T01:44:03Z' },
+ expirationPolicy: { next_run_at: '2063-04-08T01:44:03Z' },
});
expect(findPopover().exists()).toBe(true);
@@ -113,7 +121,7 @@ describe('cleanup_status', () => {
it('id matches popover target attribute', () => {
mountComponent({
status: UNFINISHED_STATUS,
- next_run_at: '2063-04-08T01:44:03Z',
+ expirationPolicy: { next_run_at: '2063-04-08T01:44:03Z' },
});
const id = findExtraInfoIcon().attributes('id');
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index f9739509ef9..b11048cd7a2 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
@@ -13,7 +13,7 @@ export const imagesListResponse = [
expirationPolicyCleanupStatus: 'UNSCHEDULED',
project: {
id: 'gid://gitlab/Project/22',
- path: 'gitlab-test',
+ path: 'GITLAB-TEST',
},
},
{
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index f2901148e17..fb50d623543 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -50,6 +50,7 @@ describe('DependencyProxyApp', () => {
groupPath: 'gitlab-org',
groupId: dummyGrouptId,
noManifestsIllustration: 'noManifestsIllustration',
+ canClearCache: true,
};
function createComponent({ provide = provideDefaults } = {}) {
@@ -268,6 +269,23 @@ describe('DependencyProxyApp', () => {
'All items in the cache are scheduled for removal.',
);
});
+
+ describe('when user has no permission to clear cache', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ groupPath: 'gitlab-org',
+ groupId: dummyGrouptId,
+ noManifestsIllustration: 'noManifestsIllustration',
+ canClearCache: false,
+ },
+ });
+ });
+
+ it('does not show the clear cache dropdown list', () => {
+ expect(findClearCacheDropdownList().exists()).toBe(false);
+ });
+ });
});
});
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
index 79c1b18c9f9..721bdd34a4f 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
@@ -128,7 +128,7 @@ describe('packages_list_row', () => {
findDeleteButton().vm.$emit('click');
await nextTick();
- expect(wrapper.emitted('packageToDelete')).toBeTruthy();
+ expect(wrapper.emitted('packageToDelete')).toHaveLength(1);
expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
});
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 fdddc131412..61923233d2e 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
@@ -29,19 +29,25 @@ exports[`PackageTitle renders with tags 1`] = `
<div
class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
>
- <span
+ <div
+ class="gl-display-flex gl-gap-3"
data-testid="sub-header"
>
v
1.0.0
published
<time-ago-tooltip-stub
- class="gl-ml-2"
cssclass=""
time="2020-08-17T14:23:32Z"
tooltipplacement="top"
/>
- </span>
+
+ <package-tags-stub
+ hidelabel="true"
+ tagdisplaylimit="2"
+ tags="[object Object],[object Object],[object Object]"
+ />
+ </div>
</div>
</div>
</div>
@@ -73,15 +79,6 @@ exports[`PackageTitle renders with tags 1`] = `
texttooltip=""
/>
</div>
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <package-tags-stub
- hidelabel="true"
- tagdisplaylimit="2"
- tags="[object Object],[object Object],[object Object]"
- />
- </div>
</div>
</div>
@@ -121,19 +118,21 @@ exports[`PackageTitle renders without tags 1`] = `
<div
class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-3"
>
- <span
+ <div
+ class="gl-display-flex gl-gap-3"
data-testid="sub-header"
>
v
1.0.0
published
<time-ago-tooltip-stub
- class="gl-ml-2"
cssclass=""
time="2020-08-17T14:23:32Z"
tooltipplacement="top"
/>
- </span>
+
+ <!---->
+ </div>
</div>
</div>
</div>
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
index 06ae8645101..92c2cd90568 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
@@ -2,19 +2,161 @@
exports[`PypiInstallation renders all the messages 1`] = `
<div>
- <installation-title-stub
- options="[object Object]"
- packagetype="pypi"
- />
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center"
+ >
+ <h3
+ class="gl-font-lg"
+ >
+ Installation
+ </h3>
+
+ <div>
+ <div
+ class="dropdown b-dropdown gl-new-dropdown btn-group"
+ id="__BVID__27"
+ lazy=""
+ >
+ <!---->
+ <button
+ aria-expanded="false"
+ aria-haspopup="true"
+ class="btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle"
+ id="__BVID__27__BV_toggle_"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-new-dropdown-button-text"
+ >
+ Show PyPi commands
+ </span>
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon dropdown-chevron gl-icon s16"
+ data-testid="chevron-down-icon"
+ role="img"
+ >
+ <use
+ href="#chevron-down"
+ />
+ </svg>
+ </button>
+ <ul
+ aria-labelledby="__BVID__27__BV_toggle_"
+ class="dropdown-menu"
+ role="menu"
+ tabindex="-1"
+ >
+ <!---->
+ </ul>
+ </div>
+ </div>
+ </div>
- <code-instruction-stub
- copytext="Copy Pip command"
- data-testid="pip-command"
- instruction="pip install @gitlab-org/package-15 --extra-index-url http://__token__:<your_personal_token>@gdk.test:3000/api/v4/projects/1/packages/pypi/simple"
- label="Pip Command"
- trackingaction="copy_pip_install_command"
- trackinglabel="code_instruction"
- />
+ <fieldset
+ aria-describedby="installation-pip-command-group__BV_description_"
+ class="form-group gl-form-group"
+ id="installation-pip-command-group"
+ >
+ <legend
+ class="bv-no-focus-ring col-form-label pt-0 col-form-label"
+ id="installation-pip-command-group__BV_label_"
+ tabindex="-1"
+ >
+
+
+
+ <!---->
+
+ <!---->
+ </legend>
+ <div
+ aria-labelledby="installation-pip-command-group__BV_label_"
+ class="bv-no-focus-ring"
+ role="group"
+ tabindex="-1"
+ >
+ <div
+ data-testid="pip-command"
+ id="installation-pip-command"
+ >
+ <label
+ for="instruction-input_5"
+ >
+ Pip Command
+ </label>
+
+ <div
+ class="gl-mb-3"
+ >
+ <div
+ class="input-group gl-mb-3"
+ >
+ <input
+ class="form-control gl-font-monospace"
+ data-testid="instruction-input"
+ id="instruction-input_5"
+ readonly="readonly"
+ type="text"
+ />
+
+ <span
+ class="input-group-append"
+ data-testid="instruction-button"
+ >
+ <button
+ aria-label="Copy Pip command"
+ aria-live="polite"
+ class="btn input-group-text btn-default btn-md gl-button btn-default-secondary btn-icon"
+ data-clipboard-handle-tooltip="false"
+ data-clipboard-text="pip install @gitlab-org/package-15 --extra-index-url http://__token__:<your_personal_token>@gdk.test:3000/api/v4/projects/1/packages/pypi/simple"
+ id="clipboard-button-6"
+ title="Copy Pip command"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon gl-icon s16"
+ data-testid="copy-to-clipboard-icon"
+ role="img"
+ >
+ <use
+ href="#copy-to-clipboard"
+ />
+ </svg>
+
+ <!---->
+ </button>
+ </span>
+ </div>
+ </div>
+ </div>
+ <!---->
+ <!---->
+ <small
+ class="form-text text-muted"
+ id="installation-pip-command-group__BV_description_"
+ tabindex="-1"
+ >
+ You will need a
+ <a
+ class="gl-link"
+ data-testid="access-token-link"
+ href="/help/user/profile/personal_access_tokens"
+ >
+ personal access token
+ </a>
+ .
+ </small>
+ </div>
+ </fieldset>
<h3
class="gl-font-lg"
@@ -30,25 +172,33 @@ exports[`PypiInstallation renders all the messages 1`] = `
file.
</p>
- <code-instruction-stub
- copytext="Copy .pypirc content"
+ <div
data-testid="pypi-setup-content"
- instruction="[gitlab]
+ >
+ <!---->
+
+ <div>
+ <pre
+ class="gl-font-monospace"
+ data-testid="multiline-instruction"
+ >
+ [gitlab]
repository = http://gdk.test:3000/api/v4/projects/1/packages/pypi
username = __token__
-password = <your personal access token>"
- label=""
- multiline="true"
- trackingaction="copy_pypi_setup_command"
- trackinglabel="code_instruction"
- />
+password = &lt;your personal access token&gt;
+ </pre>
+ </div>
+ </div>
For more information on the PyPi registry,
- <gl-link-stub
+ <a
+ class="gl-link"
+ data-testid="pypi-docs-link"
href="/help/user/packages/pypi_repository/index"
+ rel="noopener"
target="_blank"
>
see the documentation
- </gl-link-stub>
+ </a>
.
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
index 0447ead0830..529a6a22ddf 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
@@ -1,6 +1,6 @@
-import { GlDropdown, GlButton } from '@gitlab/ui';
+import { GlDropdown, GlButton, GlFormCheckbox } from '@gitlab/ui';
import { nextTick } from 'vue';
-import stubChildren from 'helpers/stub_children';
+import { stubComponent } from 'helpers/stub_component';
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import { packageFiles as packageFilesMock } from 'jest/packages_and_registries/package_registry/mock_data';
import PackageFiles from '~/packages_and_registries/package_registry/components/details/package_files.vue';
@@ -11,6 +11,7 @@ describe('Package Files', () => {
let wrapper;
const findAllRows = () => wrapper.findAllByTestId('file-row');
+ const findDeleteSelectedButton = () => wrapper.findByTestId('delete-selected');
const findFirstRow = () => extendedWrapper(findAllRows().at(0));
const findSecondRow = () => extendedWrapper(findAllRows().at(1));
const findFirstRowDownloadLink = () => findFirstRow().findByTestId('download-link');
@@ -22,19 +23,27 @@ describe('Package Files', () => {
const findActionMenuDelete = () => findFirstActionMenu().findByTestId('delete-file');
const findFirstToggleDetailsButton = () => findFirstRow().findComponent(GlButton);
const findFirstRowShaComponent = (id) => wrapper.findByTestId(id);
+ const findCheckAllCheckbox = () => wrapper.findByTestId('package-files-checkbox-all');
+ const findAllRowCheckboxes = () => wrapper.findAllByTestId('package-files-checkbox');
const files = packageFilesMock();
const [file] = files;
- const createComponent = ({ packageFiles = [file], canDelete = true } = {}) => {
+ const createComponent = ({
+ packageFiles = [file],
+ isLoading = false,
+ canDelete = true,
+ stubs,
+ } = {}) => {
wrapper = mountExtended(PackageFiles, {
propsData: {
canDelete,
+ isLoading,
packageFiles,
},
stubs: {
- ...stubChildren(PackageFiles),
- GlTableLite: false,
+ GlTable: false,
+ ...stubs,
},
});
};
@@ -157,43 +166,170 @@ describe('Package Files', () => {
expect(findSecondRowCommitLink().exists()).toBe(false);
});
});
+ });
- describe('action menu', () => {
- describe('when the user can delete', () => {
- it('exists', () => {
- createComponent();
+ describe('action menu', () => {
+ describe('when the user can delete', () => {
+ it('exists', () => {
+ createComponent();
- expect(findFirstActionMenu().exists()).toBe(true);
- });
+ expect(findFirstActionMenu().exists()).toBe(true);
+ expect(findFirstActionMenu().props('icon')).toBe('ellipsis_v');
+ expect(findFirstActionMenu().props('textSrOnly')).toBe(true);
+ expect(findFirstActionMenu().props('text')).toMatchInterpolatedText('More actions');
+ });
- describe('menu items', () => {
- describe('delete file', () => {
- it('exists', () => {
- createComponent();
+ describe('menu items', () => {
+ describe('delete file', () => {
+ it('exists', () => {
+ createComponent();
- expect(findActionMenuDelete().exists()).toBe(true);
- });
+ expect(findActionMenuDelete().exists()).toBe(true);
+ });
- it('emits a delete event when clicked', () => {
- createComponent();
+ it('emits a delete event when clicked', async () => {
+ createComponent();
- findActionMenuDelete().vm.$emit('click');
+ await findActionMenuDelete().trigger('click');
- const [[{ id }]] = wrapper.emitted('delete-file');
- expect(id).toBe(file.id);
- });
+ const [[items]] = wrapper.emitted('delete-files');
+ const [{ id }] = items;
+ expect(id).toBe(file.id);
});
});
});
+ });
+
+ describe('when the user can not delete', () => {
+ const canDelete = false;
+
+ it('does not exist', () => {
+ createComponent({ canDelete });
+
+ expect(findFirstActionMenu().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('multi select', () => {
+ describe('when user can delete', () => {
+ it('delete selected button exists & is disabled', () => {
+ createComponent();
+
+ expect(findDeleteSelectedButton().exists()).toBe(true);
+ expect(findDeleteSelectedButton().text()).toMatchInterpolatedText('Delete selected');
+ expect(findDeleteSelectedButton().props('disabled')).toBe(true);
+ });
+
+ it('delete selected button exists & is disabled when isLoading prop is true', () => {
+ createComponent({ isLoading: true });
+
+ expect(findDeleteSelectedButton().props('disabled')).toBe(true);
+ });
+
+ it('checkboxes to select file are visible', () => {
+ createComponent({ packageFiles: files });
+
+ expect(findCheckAllCheckbox().exists()).toBe(true);
+ expect(findAllRowCheckboxes()).toHaveLength(2);
+ });
+
+ it('selecting a checkbox enables delete selected button', async () => {
+ createComponent();
+
+ const first = findAllRowCheckboxes().at(0);
+
+ await first.setChecked(true);
+
+ expect(findDeleteSelectedButton().props('disabled')).toBe(false);
+ });
+
+ describe('select all checkbox', () => {
+ it('will toggle between selecting all and deselecting all files', async () => {
+ const getChecked = () => findAllRowCheckboxes().filter((x) => x.element.checked === true);
+
+ createComponent({ packageFiles: files });
+
+ expect(getChecked()).toHaveLength(0);
+
+ await findCheckAllCheckbox().setChecked(true);
- describe('when the user can not delete', () => {
- const canDelete = false;
+ expect(getChecked()).toHaveLength(files.length);
- it('does not exist', () => {
- createComponent({ canDelete });
+ await findCheckAllCheckbox().setChecked(false);
- expect(findFirstActionMenu().exists()).toBe(false);
+ expect(getChecked()).toHaveLength(0);
});
+
+ it('will toggle the indeterminate state when some but not all files are selected', async () => {
+ const expectIndeterminateState = (state) =>
+ expect(findCheckAllCheckbox().props('indeterminate')).toBe(state);
+
+ createComponent({
+ packageFiles: files,
+ stubs: { GlFormCheckbox: stubComponent(GlFormCheckbox, { props: ['indeterminate'] }) },
+ });
+
+ expectIndeterminateState(false);
+
+ await findSecondRow().trigger('click');
+
+ expectIndeterminateState(true);
+
+ await findSecondRow().trigger('click');
+
+ expectIndeterminateState(false);
+
+ findCheckAllCheckbox().trigger('click');
+
+ expectIndeterminateState(false);
+
+ await findSecondRow().trigger('click');
+
+ expectIndeterminateState(true);
+ });
+ });
+
+ it('emits a delete event when selected', async () => {
+ createComponent();
+
+ const first = findAllRowCheckboxes().at(0);
+
+ await first.setChecked(true);
+
+ await findDeleteSelectedButton().trigger('click');
+
+ const [[items]] = wrapper.emitted('delete-files');
+ const [{ id }] = items;
+ expect(id).toBe(file.id);
+ });
+
+ it('emits delete event with both items when all are selected', async () => {
+ createComponent({ packageFiles: files });
+
+ await findCheckAllCheckbox().setChecked(true);
+
+ await findDeleteSelectedButton().trigger('click');
+
+ const [[items]] = wrapper.emitted('delete-files');
+ expect(items).toHaveLength(2);
+ });
+ });
+
+ describe('when user cannot delete', () => {
+ const canDelete = false;
+
+ it('delete selected button does not exist', () => {
+ createComponent({ canDelete });
+
+ expect(findDeleteSelectedButton().exists()).toBe(false);
+ });
+
+ it('checkboxes to select file are not visible', () => {
+ createComponent({ packageFiles: files, canDelete });
+
+ expect(findCheckAllCheckbox().exists()).toBe(false);
+ expect(findAllRowCheckboxes()).toHaveLength(0);
});
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
index f4e6d43812d..ec2e833552a 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_history_spec.js
@@ -17,6 +17,12 @@ import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import waitForPromises from 'helpers/wait_for_promises';
import getPackagePipelines from '~/packages_and_registries/package_registry/graphql/queries/get_package_pipelines.query.graphql';
+import Tracking from '~/tracking';
+import {
+ TRACKING_ACTION_CLICK_PIPELINE_LINK,
+ TRACKING_ACTION_CLICK_COMMIT_LINK,
+ TRACKING_LABEL_PACKAGE_HISTORY,
+} from '~/packages_and_registries/package_registry/constants';
Vue.use(VueApollo);
@@ -181,7 +187,6 @@ describe('Package History', () => {
it('link', () => {
const linkElement = findElementLink(element);
const exist = Boolean(link);
-
expect(linkElement.exists()).toBe(exist);
if (exist) {
expect(linkElement.attributes('href')).toBe(link);
@@ -189,4 +194,29 @@ describe('Package History', () => {
});
},
);
+ describe('tracking', () => {
+ let eventSpy;
+ const category = 'UI::Packages';
+
+ beforeEach(() => {
+ mountComponent();
+ eventSpy = jest.spyOn(Tracking, 'event');
+ });
+
+ it('clicking pipeline link tracks the right action', () => {
+ wrapper.vm.trackPipelineClick();
+ expect(eventSpy).toHaveBeenCalledWith(category, TRACKING_ACTION_CLICK_PIPELINE_LINK, {
+ category,
+ label: TRACKING_LABEL_PACKAGE_HISTORY,
+ });
+ });
+
+ it('clicking commit link tracks the right action', () => {
+ wrapper.vm.trackCommitClick();
+ expect(eventSpy).toHaveBeenCalledWith(category, TRACKING_ACTION_CLICK_COMMIT_LINK, {
+ category,
+ label: TRACKING_LABEL_PACKAGE_HISTORY,
+ });
+ });
+ });
});
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 d306f7834f0..37416dcd4e7 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
@@ -22,16 +22,21 @@ const packageWithTags = {
packageFiles: { nodes: packageFiles() },
};
+const defaultProvide = {
+ isGroupPage: false,
+};
+
describe('PackageTitle', () => {
let wrapper;
- async function createComponent(packageEntity = packageWithTags) {
+ async function createComponent(packageEntity = packageWithTags, provide = defaultProvide) {
wrapper = shallowMountExtended(PackageTitle, {
propsData: { packageEntity },
stubs: {
TitleArea,
GlSprintf,
},
+ provide,
directives: {
GlResizeObserver: createMockDirective(),
},
@@ -199,11 +204,22 @@ describe('PackageTitle', () => {
expect(findPipelineProject().exists()).toBe(false);
});
- it('correctly shows the pipeline project if there is one', async () => {
+ it('does not display the pipeline project on project page even if it exists', async () => {
await createComponent({
...packageData(),
pipelines: { nodes: packagePipelines() },
});
+ expect(findPipelineProject().exists()).toBe(false);
+ });
+
+ it('correctly shows the pipeline project on group page if there is one', async () => {
+ await createComponent(
+ {
+ ...packageData(),
+ pipelines: { nodes: packagePipelines() },
+ },
+ { isGroupPage: true },
+ );
expect(findPipelineProject().props()).toMatchObject({
text: packagePipelines()[0].project.name,
icon: 'review-list',
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
index f2fef6436a6..20acb0872e5 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
@@ -1,9 +1,10 @@
-import { GlLink, GlSprintf } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { GlSprintf } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { packageData } from 'jest/packages_and_registries/package_registry/mock_data';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
import PypiInstallation from '~/packages_and_registries/package_registry/components/details/pypi_installation.vue';
import {
+ PERSONAL_ACCESS_TOKEN_HELP_URL,
PACKAGE_TYPE_PYPI,
TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND,
TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
@@ -24,11 +25,12 @@ password = <your personal access token>`;
const pipCommand = () => wrapper.findByTestId('pip-command');
const setupInstruction = () => wrapper.findByTestId('pypi-setup-content');
+ const findAccessTokenLink = () => wrapper.findByTestId('access-token-link');
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
- const findSetupDocsLink = () => wrapper.findComponent(GlLink);
+ const findSetupDocsLink = () => wrapper.findByTestId('pypi-docs-link');
function createComponent() {
- wrapper = shallowMountExtended(PypiInstallation, {
+ wrapper = mountExtended(PypiInstallation, {
propsData: {
packageEntity,
},
@@ -78,6 +80,12 @@ password = <your personal access token>`;
});
});
+ it('has a link to personal access token docs', () => {
+ expect(findAccessTokenLink().attributes()).toMatchObject({
+ href: PERSONAL_ACCESS_TOKEN_HELP_URL,
+ });
+ });
+
it('has a link to the docs', () => {
expect(findSetupDocsLink().attributes()).toMatchObject({
href: PYPI_HELP_PATH,
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
index c16c09b5326..eb1e76377ff 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
@@ -123,7 +123,7 @@ describe('packages_list_row', () => {
findDeleteDropdown().vm.$emit('click');
await nextTick();
- expect(wrapper.emitted('packageToDelete')).toBeTruthy();
+ expect(wrapper.emitted('packageToDelete')).toHaveLength(1);
expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
});
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 d40feee582f..22236424e6a 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -141,6 +141,7 @@ export const packageData = (extend) => ({
});
export const conanMetadata = () => ({
+ __typename: 'ConanMetadata',
id: 'conan-1',
packageChannel: 'stable',
packageUsername: 'gitlab-org+gitlab-test',
@@ -148,9 +149,8 @@ export const conanMetadata = () => ({
recipePath: 'package-8/1.0.0/gitlab-org+gitlab-test/stable',
});
-const conanMetadataQuery = () => ({ ...conanMetadata(), __typename: 'ConanMetadata' });
-
export const composerMetadata = () => ({
+ __typename: 'ComposerMetadata',
targetSha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
composerJson: {
license: 'MIT',
@@ -158,19 +158,14 @@ export const composerMetadata = () => ({
},
});
-const composerMetadataQuery = () => ({
- ...composerMetadata(),
- __typename: 'ComposerMetadata',
-});
-
export const pypiMetadata = () => ({
+ __typename: 'PypiMetadata',
id: 'pypi-1',
requiredPython: '1.0.0',
});
-const pypiMetadataQuery = () => ({ ...pypiMetadata(), __typename: 'PypiMetadata' });
-
export const mavenMetadata = () => ({
+ __typename: 'MavenMetadata',
id: 'maven-1',
appName: 'appName',
appGroup: 'appGroup',
@@ -178,23 +173,20 @@ export const mavenMetadata = () => ({
path: 'path',
});
-const mavenMetadataQuery = () => ({ ...mavenMetadata(), __typename: 'MavenMetadata' });
-
export const nugetMetadata = () => ({
+ __typename: 'NugetMetadata',
id: 'nuget-1',
iconUrl: 'iconUrl',
licenseUrl: 'licenseUrl',
projectUrl: 'projectUrl',
});
-const nugetMetadataQuery = () => ({ ...nugetMetadata(), __typename: 'NugetMetadata' });
-
const packageTypeMetadataQueryMapping = {
- CONAN: conanMetadataQuery,
- COMPOSER: composerMetadataQuery,
- PYPI: pypiMetadataQuery,
- MAVEN: mavenMetadataQuery,
- NUGET: nugetMetadataQuery,
+ CONAN: conanMetadata,
+ COMPOSER: composerMetadata,
+ PYPI: pypiMetadata,
+ MAVEN: mavenMetadata,
+ NUGET: nugetMetadata,
};
export const pagination = (extend) => ({
@@ -221,6 +213,7 @@ export const packageDetailsQuery = (extendPackage) => ({
id: '1',
path: 'projectPath',
name: 'gitlab-test',
+ fullPath: 'gitlab-test',
},
tags: {
nodes: packageTags(),
@@ -231,6 +224,9 @@ export const packageDetailsQuery = (extendPackage) => ({
__typename: 'PipelineConnection',
},
packageFiles: {
+ pageInfo: {
+ hasNextPage: true,
+ },
nodes: packageFiles(),
__typename: 'PackageFileConnection',
},
@@ -310,16 +306,16 @@ export const packageDestroyMutationError = () => ({
],
});
-export const packageDestroyFileMutation = () => ({
+export const packageDestroyFilesMutation = () => ({
data: {
- destroyPackageFile: {
+ destroyPackageFiles: {
errors: [],
},
},
});
-export const packageDestroyFileMutationError = () => ({
+export const packageDestroyFilesMutationError = () => ({
data: {
- destroyPackageFile: null,
+ destroyPackageFiles: null,
},
errors: [
{
@@ -331,7 +327,7 @@ export const packageDestroyFileMutationError = () => ({
column: 3,
},
],
- path: ['destroyPackageFile'],
+ path: ['destroyPackageFiles'],
},
],
});
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 3cadb001c58..de78e6bb87b 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
@@ -22,6 +22,8 @@ import {
PACKAGE_TYPE_COMPOSER,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
+ DELETE_PACKAGE_FILES_ERROR_MESSAGE,
PACKAGE_TYPE_NUGET,
PACKAGE_TYPE_MAVEN,
PACKAGE_TYPE_CONAN,
@@ -29,7 +31,7 @@ import {
PACKAGE_TYPE_NPM,
} from '~/packages_and_registries/package_registry/constants';
-import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql';
+import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import {
packageDetailsQuery,
@@ -38,8 +40,8 @@ import {
dependencyLinks,
emptyPackageDetailsQuery,
packageFiles,
- packageDestroyFileMutation,
- packageDestroyFileMutationError,
+ packageDestroyFilesMutation,
+ packageDestroyFilesMutationError,
} from '../mock_data';
jest.mock('~/flash');
@@ -58,6 +60,7 @@ describe('PackagesApp', () => {
emptyListIllustration: 'svgPath',
projectListUrl: 'projectListUrl',
groupListUrl: 'groupListUrl',
+ isGroupPage: false,
breadCrumbState,
};
@@ -65,14 +68,14 @@ describe('PackagesApp', () => {
function createComponent({
resolver = jest.fn().mockResolvedValue(packageDetailsQuery()),
- fileDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFileMutation()),
+ filesDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFilesMutation()),
routeId = '1',
} = {}) {
Vue.use(VueApollo);
const requestHandlers = [
[getPackageDetails, resolver],
- [destroyPackageFileMutation, fileDeleteMutationResolver],
+ [destroyPackageFilesMutation, filesDeleteMutationResolver],
];
apolloProvider = createMockApollo(requestHandlers);
@@ -110,6 +113,7 @@ describe('PackagesApp', () => {
const findDeleteButton = () => wrapper.findByTestId('delete-package');
const findPackageFiles = () => wrapper.findComponent(PackageFiles);
const findDeleteFileModal = () => wrapper.findByTestId('delete-file-modal');
+ const findDeleteFilesModal = () => wrapper.findByTestId('delete-files-modal');
const findVersionRows = () => wrapper.findAllComponents(VersionRow);
const noVersionsMessage = () => wrapper.findByTestId('no-versions-message');
const findDependenciesCountBadge = () => wrapper.findComponent(GlBadge);
@@ -288,6 +292,7 @@ describe('PackagesApp', () => {
expect(findPackageFiles().props('packageFiles')[0]).toMatchObject(expectedFile);
expect(findPackageFiles().props('canDelete')).toBe(packageData().canDestroy);
+ expect(findPackageFiles().props('isLoading')).toEqual(false);
});
it('does not render the package files table when the package is composer', async () => {
@@ -305,24 +310,69 @@ describe('PackagesApp', () => {
describe('deleting a file', () => {
const [fileToDelete] = packageFiles();
- const doDeleteFile = () => {
- findPackageFiles().vm.$emit('delete-file', fileToDelete);
+ const doDeleteFile = async () => {
+ findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
findDeleteFileModal().vm.$emit('primary');
return waitForPromises();
};
- it('opens a confirmation modal', async () => {
+ it('opens delete file confirmation modal', async () => {
createComponent();
await waitForPromises();
- findPackageFiles().vm.$emit('delete-file', fileToDelete);
+ const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
+ const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
+
+ findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
+
+ expect(showDeletePackageSpy).not.toBeCalled();
+ expect(showDeleteFileSpy).toBeCalled();
+ });
+
+ it('when its the only file opens delete package confirmation modal', async () => {
+ const [packageFile] = packageFiles();
+ const resolver = jest.fn().mockResolvedValue(
+ packageDetailsQuery({
+ packageFiles: {
+ pageInfo: {
+ hasNextPage: false,
+ },
+ nodes: [packageFile],
+ __typename: 'PackageFileConnection',
+ },
+ }),
+ );
+
+ createComponent({
+ resolver,
+ });
+
+ await waitForPromises();
+
+ const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show');
+ const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
+
+ findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
+
+ expect(showDeletePackageSpy).toBeCalled();
+ expect(showDeleteFileSpy).not.toBeCalled();
+ });
+
+ it('confirming on the modal sets the loading state', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ findPackageFiles().vm.$emit('delete-files', [fileToDelete]);
+
+ findDeleteFileModal().vm.$emit('primary');
await nextTick();
- expect(findDeleteFileModal().exists()).toBe(true);
+ expect(findPackageFiles().props('isLoading')).toEqual(true);
});
it('confirming on the modal deletes the file and shows a success message', async () => {
@@ -344,7 +394,7 @@ describe('PackagesApp', () => {
describe('errors', () => {
it('shows an error when the mutation request fails', async () => {
- createComponent({ fileDeleteMutationResolver: jest.fn().mockRejectedValue() });
+ createComponent({ filesDeleteMutationResolver: jest.fn().mockRejectedValue() });
await waitForPromises();
await doDeleteFile();
@@ -358,9 +408,9 @@ describe('PackagesApp', () => {
it('shows an error when the mutation request returns an error payload', async () => {
createComponent({
- fileDeleteMutationResolver: jest
+ filesDeleteMutationResolver: jest
.fn()
- .mockResolvedValue(packageDestroyFileMutationError()),
+ .mockResolvedValue(packageDestroyFilesMutationError()),
});
await waitForPromises();
@@ -374,6 +424,117 @@ describe('PackagesApp', () => {
});
});
});
+
+ describe('deleting multiple files', () => {
+ const doDeleteFiles = async () => {
+ findPackageFiles().vm.$emit('delete-files', packageFiles());
+
+ findDeleteFilesModal().vm.$emit('primary');
+
+ return waitForPromises();
+ };
+
+ it('opens delete files confirmation modal', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ const showDeleteFilesSpy = jest.spyOn(wrapper.vm.$refs.deleteFilesModal, 'show');
+
+ findPackageFiles().vm.$emit('delete-files', packageFiles());
+
+ expect(showDeleteFilesSpy).toBeCalled();
+ });
+
+ it('confirming on the modal sets the loading state', async () => {
+ createComponent();
+
+ await waitForPromises();
+
+ findPackageFiles().vm.$emit('delete-files', packageFiles());
+
+ findDeleteFilesModal().vm.$emit('primary');
+
+ await nextTick();
+
+ expect(findPackageFiles().props('isLoading')).toEqual(true);
+ });
+
+ it('confirming on the modal deletes the file and shows a success message', async () => {
+ const resolver = jest.fn().mockResolvedValue(packageDetailsQuery());
+ createComponent({ resolver });
+
+ await waitForPromises();
+
+ await doDeleteFiles();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
+ }),
+ );
+ // we are re-fetching the package details, so we expect the resolver to have been called twice
+ expect(resolver).toHaveBeenCalledTimes(2);
+ });
+
+ describe('errors', () => {
+ it('shows an error when the mutation request fails', async () => {
+ createComponent({ filesDeleteMutationResolver: jest.fn().mockRejectedValue() });
+ await waitForPromises();
+
+ await doDeleteFiles();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ }),
+ );
+ });
+
+ it('shows an error when the mutation request returns an error payload', async () => {
+ createComponent({
+ filesDeleteMutationResolver: jest
+ .fn()
+ .mockResolvedValue(packageDestroyFilesMutationError()),
+ });
+ await waitForPromises();
+
+ await doDeleteFiles();
+
+ expect(createFlash).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ }),
+ );
+ });
+ });
+ });
+
+ describe('deleting all files', () => {
+ it('opens the delete package confirmation modal', async () => {
+ const resolver = jest.fn().mockResolvedValue(
+ packageDetailsQuery({
+ packageFiles: {
+ pageInfo: {
+ hasNextPage: false,
+ },
+ nodes: packageFiles(),
+ },
+ }),
+ );
+ createComponent({
+ resolver,
+ });
+
+ await waitForPromises();
+
+ const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show');
+
+ findPackageFiles().vm.$emit('delete-files', packageFiles());
+
+ expect(showDeletePackageSpy).toBeCalled();
+ });
+ });
});
describe('versions', () => {
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/__snapshots__/container_expiration_policy_form_spec.js.snap b/spec/frontend/packages_and_registries/settings/project/settings/components/__snapshots__/container_expiration_policy_form_spec.js.snap
index 108d9478788..5d08574234c 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/__snapshots__/container_expiration_policy_form_spec.js.snap
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/__snapshots__/container_expiration_policy_form_spec.js.snap
@@ -5,6 +5,7 @@ exports[`Container Expiration Policy Settings Form Cadence matches snapshot 1`]
class="gl-mr-7 gl-mb-0!"
data-testid="cadence-dropdown"
description=""
+ dropdownclass=""
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object]"
label="Run cleanup:"
name="cadence"
@@ -24,6 +25,7 @@ exports[`Container Expiration Policy Settings Form Keep N matches snapshot 1`] =
<expiration-dropdown-stub
data-testid="keep-n-dropdown"
description=""
+ dropdownclass=""
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
label="Keep the most recent:"
name="keep-n"
@@ -47,6 +49,7 @@ exports[`Container Expiration Policy Settings Form OlderThan matches snapshot 1`
<expiration-dropdown-stub
data-testid="older-than-dropdown"
description=""
+ dropdownclass=""
formoptions="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]"
label="Remove tags older than:"
name="older-than"
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 d4b6c66ddeb..0696144215c 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
@@ -1,4 +1,5 @@
export const containerExpirationPolicyData = () => ({
+ __typename: 'ContainerExpirationPolicy',
cadence: 'EVERY_DAY',
enabled: true,
keepN: 'TEN_TAGS',
@@ -13,7 +14,6 @@ export const expirationPolicyPayload = (override) => ({
project: {
id: '1',
containerExpirationPolicy: {
- __typename: 'ContainerExpirationPolicy',
...containerExpirationPolicyData(),
...override,
},
@@ -42,6 +42,7 @@ export const expirationPolicyMutationPayload = ({ override, errors = [] } = {})
});
export const packagesCleanupPolicyData = {
+ __typename: 'PackagesCleanupPolicy',
keepNDuplicatedPackageFiles: 'ALL_PACKAGE_FILES',
nextRunAt: '2020-11-19T07:37:03.941Z',
};
@@ -51,7 +52,6 @@ export const packagesCleanupPolicyPayload = (override) => ({
project: {
id: '1',
packagesCleanupPolicy: {
- __typename: 'PackagesCleanupPolicy',
...packagesCleanupPolicyData,
...override,
},
diff --git a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
index 542eb2f3ab8..85ed94b748d 100644
--- a/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
+++ b/spec/frontend/pages/admin/application_settings/account_and_limits_spec.js
@@ -23,17 +23,17 @@ describe('AccountAndLimits', () => {
describe('Changing of userInternalRegex when userDefaultExternal', () => {
it('is unchecked', () => {
- expect($userDefaultExternal.prop('checked')).toBeFalsy();
+ expect($userDefaultExternal.prop('checked')).toBe(false);
expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE);
- expect($userInternalRegex.readOnly).toBeTruthy();
+ expect($userInternalRegex.readOnly).toBe(true);
});
it('is checked', () => {
if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click();
- expect($userDefaultExternal.prop('checked')).toBeTruthy();
+ expect($userDefaultExternal.prop('checked')).toBe(true);
expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE);
- expect($userInternalRegex.readOnly).toBeFalsy();
+ expect($userInternalRegex.readOnly).toBe(false);
});
});
});
diff --git a/spec/frontend/pages/groups/new/components/app_spec.js b/spec/frontend/pages/groups/new/components/app_spec.js
new file mode 100644
index 00000000000..ab483316086
--- /dev/null
+++ b/spec/frontend/pages/groups/new/components/app_spec.js
@@ -0,0 +1,39 @@
+import { shallowMount } from '@vue/test-utils';
+import App from '~/pages/groups/new/components/app.vue';
+import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
+
+describe('App component', () => {
+ let wrapper;
+
+ const createComponent = (propsData = {}) => {
+ wrapper = shallowMount(App, { propsData });
+ };
+
+ const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage);
+
+ const findCreateGroupPanel = () =>
+ findNewNamespacePage()
+ .props('panels')
+ .find((panel) => panel.name === 'create-group-pane');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('creates correct component for group creation', () => {
+ createComponent();
+
+ expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('New group');
+ expect(findCreateGroupPanel().title).toBe('Create group');
+ });
+
+ it('creates correct component for subgroup creation', () => {
+ const props = { parentGroupName: 'parent', importExistingGroupPath: '/path' };
+
+ createComponent(props);
+
+ expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('parent');
+ expect(findCreateGroupPanel().title).toBe('Create subgroup');
+ expect(findCreateGroupPanel().detailProps).toEqual(props);
+ });
+});
diff --git a/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js b/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js
new file mode 100644
index 00000000000..56a1fd03f71
--- /dev/null
+++ b/spec/frontend/pages/groups/new/components/create_group_description_details_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import CreateGroupDescriptionDetails from '~/pages/groups/new/components/create_group_description_details.vue';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+describe('CreateGroupDescriptionDetails component', () => {
+ let wrapper;
+
+ const createComponent = (propsData = {}) => {
+ wrapper = shallowMount(CreateGroupDescriptionDetails, {
+ propsData,
+ stubs: { GlSprintf, GlLink },
+ });
+ };
+
+ const findLinkHref = (at) => wrapper.findAllComponents(GlLink).at(at);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('creates correct component for group creation', () => {
+ createComponent();
+
+ const groupsLink = findLinkHref(0);
+ expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index'));
+ expect(groupsLink.text()).toBe('Groups');
+
+ const subgroupsLink = findLinkHref(1);
+ expect(subgroupsLink.text()).toBe('subgroups');
+ expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index'));
+
+ expect(wrapper.text()).toBe(
+ 'Groups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.',
+ );
+ });
+
+ it('creates correct component for subgroup creation', () => {
+ createComponent({ parentGroupName: 'parent', importExistingGroupPath: '/path' });
+
+ const groupsLink = findLinkHref(0);
+ expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index'));
+ expect(groupsLink.text()).toBe('Groups');
+
+ const subgroupsLink = findLinkHref(1);
+ expect(subgroupsLink.text()).toBe('subgroups');
+ expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index'));
+
+ const importGroupLink = findLinkHref(2);
+ expect(importGroupLink.text()).toBe('import an existing group');
+ expect(importGroupLink.attributes('href')).toBe('/path');
+
+ expect(wrapper.text()).toBe(
+ 'Groups and subgroups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. You can also import an existing group.',
+ );
+ });
+});
diff --git a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
index 43361bb6f24..21a38f066d9 100644
--- a/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
+++ b/spec/frontend/pages/projects/graphs/__snapshots__/code_coverage_spec.js.snap
@@ -3,6 +3,33 @@
exports[`Code Coverage when fetching data is successful matches the snapshot 1`] = `
<div>
<div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-t gl-pt-4 gl-mb-3"
+ >
+ <h4
+ class="gl-m-0"
+ sub-header=""
+ >
+ <gl-sprintf-stub
+ message="Code coverage statistics for %{ref} %{start_date} - %{end_date}"
+ />
+ </h4>
+
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ data-testid="download-button"
+ href="url/"
+ icon=""
+ size="small"
+ variant="default"
+ >
+
+ Download raw data (.csv)
+
+ </gl-button-stub>
+ </div>
+
+ <div
class="gl-mt-3 gl-mb-3"
>
<!---->
@@ -79,6 +106,7 @@ exports[`Code Coverage when fetching data is successful matches the snapshot 1`]
legendmaxtext="Max"
legendmintext="Min"
option="[object Object]"
+ responsive=""
thresholds=""
/>
</div>
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 0f763e3220a..f272891919d 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -15,17 +15,26 @@ describe('Code Coverage', () => {
let mockAxios;
const graphEndpoint = '/graph';
+ const graphStartDate = '13 February';
+ const graphEndDate = '12 May';
+ const graphRef = 'master';
+ const graphCsvPath = 'url/';
const findAlert = () => wrapper.find(GlAlert);
const findAreaChart = () => wrapper.find(GlAreaChart);
const findAllDropdownItems = () => wrapper.findAll(GlDropdownItem);
const findFirstDropdownItem = () => findAllDropdownItems().at(0);
const findSecondDropdownItem = () => findAllDropdownItems().at(1);
+ const findDownloadButton = () => wrapper.find('[data-testid="download-button"]');
const createComponent = () => {
wrapper = shallowMount(CodeCoverage, {
propsData: {
graphEndpoint,
+ graphStartDate,
+ graphEndDate,
+ graphRef,
+ graphCsvPath,
},
});
};
@@ -64,6 +73,10 @@ describe('Code Coverage', () => {
it('shows no error messages', () => {
expect(findAlert().exists()).toBe(false);
});
+
+ it('does not render download button', () => {
+ expect(findDownloadButton().exists()).toBe(true);
+ });
});
describe('when fetching data fails', () => {
@@ -112,6 +125,10 @@ describe('Code Coverage', () => {
it('still renders an empty graph', () => {
expect(findAreaChart().exists()).toBe(true);
});
+
+ it('does not render download button', () => {
+ expect(findDownloadButton().exists()).toBe(false);
+ });
});
describe('dropdown options', () => {
@@ -146,8 +163,8 @@ describe('Code Coverage', () => {
await nextTick();
- expect(findFirstDropdownItem().attributes('ischecked')).toBeFalsy();
- expect(findSecondDropdownItem().attributes('ischecked')).toBeTruthy();
+ expect(findFirstDropdownItem().attributes('ischecked')).toBe(undefined);
+ expect(findSecondDropdownItem().attributes('ischecked')).toBe('true');
});
it('updates the graph data when selecting a different option in dropdown', async () => {
diff --git a/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index 42eeff89bf4..5b9c48f0d9b 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
@@ -226,7 +226,6 @@ describe('Timezone Dropdown', () => {
it('returns the correct object if the identifier exists', () => {
const res = findTimezoneByIdentifier(tzList, identifier);
- expect(res).toBeTruthy();
expect(res).toBe(tzList[2]);
});
diff --git a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
index 85660d09baa..f908508c4b5 100644
--- a/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
+++ b/spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js
@@ -127,6 +127,7 @@ describe('Settings Panel', () => {
const findOperationsVisibilityInput = () =>
findOperationsSettings().findComponent(ProjectFeatureSetting);
const findConfirmDangerButton = () => wrapper.findComponent(ConfirmDanger);
+ const findEnvironmentsSettings = () => wrapper.findComponent({ ref: 'environments-settings' });
afterEach(() => {
wrapper.destroy();
@@ -786,4 +787,23 @@ describe('Settings Panel', () => {
expect(findOperationsSettings().exists()).toBe(true);
});
});
+
+ describe('Environments', () => {
+ describe('with feature flag', () => {
+ it('should show the environments toggle', () => {
+ wrapper = mountComponent({
+ glFeatures: { splitOperationsVisibilityPermissions: true },
+ });
+
+ expect(findEnvironmentsSettings().exists()).toBe(true);
+ });
+ });
+ describe('without feature flag', () => {
+ it('should not show the environments toggle', () => {
+ wrapper = mountComponent({});
+
+ expect(findEnvironmentsSettings().exists()).toBe(false);
+ });
+ });
+ });
});
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 a5db10d106d..204c48f8de1 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -1,5 +1,5 @@
import { nextTick } from 'vue';
-import { GlAlert, GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import { GlAlert, GlButton, GlFormInput, GlFormGroup, GlSegmentedControl } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
@@ -106,6 +106,7 @@ describe('WikiForm', () => {
MarkdownField,
GlAlert,
GlButton,
+ GlSegmentedControl,
LocalStorageSync: stubComponent(LocalStorageSync),
GlFormInput,
GlFormGroup,
@@ -317,20 +318,20 @@ describe('WikiForm', () => {
});
describe('when content editor is not active', () => {
- it('displays "Edit rich text" label in the toggle editing mode button', () => {
- expect(findToggleEditingModeButton().text()).toBe('Edit rich text');
+ it('displays "Source" label in the toggle editing mode button', () => {
+ expect(findToggleEditingModeButton().props().checked).toBe('source');
});
describe('when clicking the toggle editing mode button', () => {
beforeEach(async () => {
- await findToggleEditingModeButton().trigger('click');
+ await findToggleEditingModeButton().vm.$emit('input', 'richText');
});
it('hides the classic editor', () => {
expect(findClassicEditor().exists()).toBe(false);
});
- it('hides the content editor', () => {
+ it('shows the content editor', () => {
expect(findContentEditor().exists()).toBe(true);
});
});
@@ -342,7 +343,7 @@ describe('WikiForm', () => {
expect(findContentEditor().exists()).toBe(false);
// enable content editor
- await findLocalStorageSync().vm.$emit('input', true);
+ await findLocalStorageSync().vm.$emit('input', 'richText');
expect(findContentEditor().exists()).toBe(true);
expect(findClassicEditor().exists()).toBe(false);
@@ -352,17 +353,18 @@ describe('WikiForm', () => {
describe('when content editor is active', () => {
let mockContentEditor;
- beforeEach(async () => {
+ beforeEach(() => {
+ createWrapper();
mockContentEditor = {
getSerializedContent: jest.fn(),
setSerializedContent: jest.fn(),
};
- await findToggleEditingModeButton().trigger('click');
+ findToggleEditingModeButton().vm.$emit('input', 'richText');
});
- it('displays "Edit source" label in the toggle editing mode button', () => {
- expect(findToggleEditingModeButton().text()).toBe('Edit source');
+ 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', () => {
@@ -374,7 +376,8 @@ describe('WikiForm', () => {
);
findContentEditor().vm.$emit('initialized', mockContentEditor);
- await findToggleEditingModeButton().trigger('click');
+ await findToggleEditingModeButton().vm.$emit('input', 'source');
+ await nextTick();
});
it('hides the content editor', () => {
@@ -389,6 +392,38 @@ describe('WikiForm', () => {
expect(findContent().element.value).toBe(contentEditorFakeSerializedContent);
});
});
+
+ 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();
+ });
+ });
+ });
});
});
@@ -398,7 +433,7 @@ describe('WikiForm', () => {
createWrapper({ mountFn: mount });
mock.onPost(/preview-markdown/).reply(400);
- await findToggleEditingModeButton().trigger('click');
+ await findToggleEditingModeButton().vm.$emit('input', 'richText');
// try waiting for content editor to load (but it will never actually load)
await waitForPromises();
@@ -410,7 +445,7 @@ describe('WikiForm', () => {
describe('toggling editing modes to the classic editor', () => {
beforeEach(() => {
- return findToggleEditingModeButton().trigger('click');
+ return findToggleEditingModeButton().vm.$emit('input', 'source');
});
it('switches to classic editor', () => {
@@ -426,7 +461,7 @@ describe('WikiForm', () => {
mock.onPost(/preview-markdown/).reply(200, { body: '<p>hello <strong>world</strong></p>' });
- await findToggleEditingModeButton().trigger('click');
+ await findToggleEditingModeButton().vm.$emit('input', 'richText');
await waitForPromises();
});
@@ -463,7 +498,6 @@ describe('WikiForm', () => {
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,
});
diff --git a/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js b/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
index bf5d15516c2..7e1e5004d91 100644
--- a/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
+++ b/spec/frontend/pipeline_editor/components/drawer/cards/first_pipeline_card_spec.js
@@ -8,16 +8,8 @@ describe('First pipeline card', () => {
let wrapper;
let trackingSpy;
- const defaultProvide = {
- runnerHelpPagePath: '/help/runners',
- };
-
const createComponent = () => {
- wrapper = mount(FirstPipelineCard, {
- provide: {
- ...defaultProvide,
- },
- });
+ wrapper = mount(FirstPipelineCard);
};
const getLinkByName = (name) => getByRole(wrapper.element, 'link', { name });
@@ -43,7 +35,7 @@ describe('First pipeline card', () => {
});
it('renders the link', () => {
- expect(findRunnersLink().href).toContain(defaultProvide.runnerHelpPagePath);
+ expect(findRunnersLink().href).toBe(wrapper.vm.$options.RUNNER_HELP_URL);
});
describe('tracking', () => {
diff --git a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js b/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
deleted file mode 100644
index 238942a34ff..00000000000
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_spec.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import { GlAlert, GlLink } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
-import { mergeUnwrappedCiConfig, mockLintHelpPagePath } from '../../mock_data';
-
-describe('~/pipeline_editor/components/lint/ci_lint.vue', () => {
- let wrapper;
-
- const createComponent = ({ props, mountFn = shallowMount } = {}) => {
- wrapper = mountFn(CiLint, {
- provide: {
- lintHelpPagePath: mockLintHelpPagePath,
- },
- propsData: {
- ciConfig: mergeUnwrappedCiConfig(),
- ...props,
- },
- });
- };
-
- const findAllByTestId = (selector) => wrapper.findAll(`[data-testid="${selector}"]`);
- const findAlert = () => wrapper.find(GlAlert);
- const findLintParameters = () => findAllByTestId('ci-lint-parameter');
- const findLintParameterAt = (i) => findLintParameters().at(i);
- const findLintValueAt = (i) => findAllByTestId('ci-lint-value').at(i);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('Valid Results', () => {
- beforeEach(() => {
- createComponent({ props: { isValid: true }, mountFn: mount });
- });
-
- it('displays valid results', () => {
- expect(findAlert().text()).toMatch('Status: Syntax is correct.');
- });
-
- it('displays link to the right help page', () => {
- expect(findAlert().find(GlLink).attributes('href')).toBe(mockLintHelpPagePath);
- });
-
- it('displays jobs', () => {
- expect(findLintParameters()).toHaveLength(3);
-
- expect(findLintParameterAt(0).text()).toBe('Test Job - job_test_1');
- expect(findLintParameterAt(1).text()).toBe('Test Job - job_test_2');
- expect(findLintParameterAt(2).text()).toBe('Build Job - job_build');
- });
-
- it('displays jobs details', () => {
- expect(findLintParameters()).toHaveLength(3);
-
- expect(findLintValueAt(0).text()).toMatchInterpolatedText(
- 'echo "test 1" Only policy: branches, tags When: on_success',
- );
- expect(findLintValueAt(1).text()).toMatchInterpolatedText(
- 'echo "test 2" Only policy: branches, tags When: on_success',
- );
- expect(findLintValueAt(2).text()).toMatchInterpolatedText(
- 'echo "build" Only policy: branches, tags When: on_success',
- );
- });
-
- it('displays invalid results', () => {
- createComponent({ props: { isValid: false }, mountFn: mount });
-
- expect(findAlert().text()).toMatch('Status: Syntax is incorrect.');
- });
- });
-});
diff --git a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
index 87a7f07f7d4..2f3e1b49b37 100644
--- a/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
+++ b/spec/frontend/pipeline_editor/components/pipeline_editor_tabs_spec.js
@@ -1,11 +1,12 @@
+// TODO
+
import { GlAlert, GlBadge, GlLoadingIcon, GlTabs } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import Vue, { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import CiConfigMergedPreview from '~/pipeline_editor/components/editor/ci_config_merged_preview.vue';
-import CiLint from '~/pipeline_editor/components/lint/ci_lint.vue';
import CiValidate from '~/pipeline_editor/components/validate/ci_validate.vue';
import WalkthroughPopover from '~/pipeline_editor/components/popovers/walkthrough_popover.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
@@ -30,8 +31,7 @@ import {
mockLintResponseWithoutMerged,
} from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
Vue.config.ignoredElements = ['gl-emoji'];
@@ -64,7 +64,12 @@ describe('Pipeline editor tabs component', () => {
};
},
provide: {
+ ciConfigPath: '/path/to/ci-config',
ciLintPath: mockCiLintPath,
+ currentBranch: 'main',
+ projectFullPath: '/path/to/project',
+ simulatePipelineHelpPagePath: 'path/to/help/page',
+ validateTabIllustrationPath: 'path/to/svg',
...provide,
},
stubs: {
@@ -88,21 +93,18 @@ describe('Pipeline editor tabs component', () => {
provide,
mountFn,
options: {
- localVue,
apolloProvider: mockApollo,
},
});
};
const findEditorTab = () => wrapper.find('[data-testid="editor-tab"]');
- const findLintTab = () => wrapper.find('[data-testid="lint-tab"]');
const findMergedTab = () => wrapper.find('[data-testid="merged-tab"]');
const findValidateTab = () => wrapper.find('[data-testid="validate-tab"]');
const findVisualizationTab = () => wrapper.find('[data-testid="visualization-tab"]');
const findAlert = () => wrapper.findComponent(GlAlert);
const findBadge = () => wrapper.findComponent(GlBadge);
- const findCiLint = () => wrapper.findComponent(CiLint);
const findCiValidate = () => wrapper.findComponent(CiValidate);
const findGlTabs = () => wrapper.findComponent(GlTabs);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -121,7 +123,8 @@ describe('Pipeline editor tabs component', () => {
describe('editor tab', () => {
it('displays editor only after the tab is mounted', async () => {
- createComponent({ mountFn: mount });
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ createComponentWithApollo({ mountFn: mount });
expect(findTextEditor().exists()).toBe(false);
@@ -156,138 +159,57 @@ describe('Pipeline editor tabs component', () => {
});
describe('validate tab', () => {
- describe('with simulatePipeline feature flag ON', () => {
- describe('after loading', () => {
- beforeEach(() => {
- createComponent({
- provide: { glFeatures: { simulatePipeline: true } },
- });
- });
-
- it('displays the tab and the validate component', () => {
- expect(findValidateTab().exists()).toBe(true);
- expect(findCiValidate().exists()).toBe(true);
- });
+ describe('after loading', () => {
+ beforeEach(() => {
+ createComponent();
});
- describe('NEW badge', () => {
- describe('default', () => {
- beforeEach(() => {
- mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
- createComponentWithApollo({
- mountFn: mount,
- props: {
- currentTab: VALIDATE_TAB,
- },
- provide: {
- glFeatures: { simulatePipeline: true },
- ciConfigPath: '/path/to/ci-config',
- currentBranch: 'main',
- projectFullPath: '/path/to/project',
- simulatePipelineHelpPagePath: 'path/to/help/page',
- validateTabIllustrationPath: 'path/to/svg',
- },
- });
- });
-
- it('renders badge by default', () => {
- expect(findBadge().exists()).toBe(true);
- expect(findBadge().text()).toBe(wrapper.vm.$options.i18n.new);
- });
-
- it('hides badge when moving away from the validate tab', async () => {
- expect(findBadge().exists()).toBe(true);
-
- await findEditorTab().vm.$emit('click');
-
- expect(findBadge().exists()).toBe(false);
- });
- });
-
- describe('if badge has been dismissed before', () => {
- beforeEach(() => {
- localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true');
- mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
- createComponentWithApollo({
- mountFn: mount,
- provide: {
- glFeatures: { simulatePipeline: true },
- ciConfigPath: '/path/to/ci-config',
- currentBranch: 'main',
- projectFullPath: '/path/to/project',
- simulatePipelineHelpPagePath: 'path/to/help/page',
- validateTabIllustrationPath: 'path/to/svg',
- },
- });
- });
-
- it('does not render badge if it has been dismissed before', () => {
- expect(findBadge().exists()).toBe(false);
- });
- });
+ it('displays the tab and the validate component', () => {
+ expect(findValidateTab().exists()).toBe(true);
+ expect(findCiValidate().exists()).toBe(true);
});
});
- describe('with simulatePipeline feature flag OFF', () => {
- beforeEach(() => {
- createComponent({
- provide: {
- glFeatures: {
- simulatePipeline: false,
+ describe('NEW badge', () => {
+ describe('default', () => {
+ beforeEach(() => {
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ createComponentWithApollo({
+ mountFn: mount,
+ props: {
+ currentTab: VALIDATE_TAB,
},
- },
+ });
});
- });
- it('does not render the tab and the validate component', () => {
- expect(findValidateTab().exists()).toBe(false);
- expect(findCiValidate().exists()).toBe(false);
- });
- });
- });
+ it('renders badge by default', () => {
+ expect(findBadge().exists()).toBe(true);
+ expect(findBadge().text()).toBe(wrapper.vm.$options.i18n.new);
+ });
- describe('lint tab', () => {
- describe('while loading', () => {
- beforeEach(() => {
- createComponent({ appStatus: EDITOR_APP_STATUS_LOADING });
- });
+ it('hides badge when moving away from the validate tab', async () => {
+ expect(findBadge().exists()).toBe(true);
- it('displays a loading icon if the lint query is loading', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- });
+ await findEditorTab().vm.$emit('click');
- it('does not display the lint component', () => {
- expect(findCiLint().exists()).toBe(false);
- });
- });
- describe('after loading', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('display the tab and the lint component', () => {
- expect(findLintTab().exists()).toBe(true);
- expect(findCiLint().exists()).toBe(true);
+ expect(findBadge().exists()).toBe(false);
+ });
});
- });
- describe('with simulatePipeline feature flag ON', () => {
- beforeEach(() => {
- createComponent({
- provide: {
- glFeatures: {
- simulatePipeline: true,
- },
- },
+ describe('if badge has been dismissed before', () => {
+ beforeEach(() => {
+ localStorage.setItem(VALIDATE_TAB_BADGE_DISMISSED_KEY, 'true');
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ createComponentWithApollo({ mountFn: mount });
});
- });
- it('does not render the tab and the lint component', () => {
- expect(findLintTab().exists()).toBe(false);
- expect(findCiLint().exists()).toBe(false);
+ it('does not render badge if it has been dismissed before', () => {
+ expect(findBadge().exists()).toBe(false);
+ });
});
});
});
+
describe('merged tab', () => {
describe('while loading', () => {
beforeEach(() => {
@@ -328,19 +250,19 @@ describe('Pipeline editor tabs component', () => {
describe('show tab content based on status', () => {
it.each`
- appStatus | editor | viz | lint | merged
+ appStatus | editor | viz | validate | merged
${undefined} | ${true} | ${true} | ${true} | ${true}
- ${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${false} | ${false}
+ ${EDITOR_APP_STATUS_EMPTY} | ${true} | ${false} | ${true} | ${false}
${EDITOR_APP_STATUS_INVALID} | ${true} | ${false} | ${true} | ${false}
${EDITOR_APP_STATUS_VALID} | ${true} | ${true} | ${true} | ${true}
`(
- 'when status is $appStatus, we show - editor:$editor | viz:$viz | lint:$lint | merged:$merged ',
- ({ appStatus, editor, viz, lint, merged }) => {
+ 'when status is $appStatus, we show - editor:$editor | viz:$viz | validate:$validate | merged:$merged ',
+ ({ appStatus, editor, viz, validate, merged }) => {
createComponent({ appStatus });
expect(findTextEditor().exists()).toBe(editor);
expect(findPipelineGraph().exists()).toBe(viz);
- expect(findCiLint().exists()).toBe(lint);
+ expect(findValidateTab().exists()).toBe(validate);
expect(findMergedPreview().exists()).toBe(merged);
},
);
@@ -386,11 +308,8 @@ describe('Pipeline editor tabs component', () => {
describe('pipeline editor walkthrough', () => {
describe('when isNewCiConfigFile prop is true (default)', () => {
- beforeEach(async () => {
- createComponent({
- mountFn: mount,
- });
- await nextTick();
+ beforeEach(() => {
+ createComponent();
});
it('shows walkthrough popover', async () => {
@@ -400,8 +319,7 @@ describe('Pipeline editor tabs component', () => {
describe('when isNewCiConfigFile prop is false', () => {
it('does not show walkthrough popover', async () => {
- createComponent({ props: { isNewCiConfigFile: false }, mountFn: mount });
- await nextTick();
+ createComponent({ props: { isNewCiConfigFile: false } });
expect(findWalkthroughPopover().exists()).toBe(false);
});
});
@@ -411,7 +329,6 @@ describe('Pipeline editor tabs component', () => {
const handler = jest.fn();
createComponent({
- mountFn: mount,
listeners: {
event: handler,
},
diff --git a/spec/frontend/pipeline_editor/components/validate/ci_validate_spec.js b/spec/frontend/pipeline_editor/components/validate/ci_validate_spec.js
index f5f01b675b2..09d4f9736ad 100644
--- a/spec/frontend/pipeline_editor/components/validate/ci_validate_spec.js
+++ b/spec/frontend/pipeline_editor/components/validate/ci_validate_spec.js
@@ -2,6 +2,7 @@ import { GlAlert, GlDropdown, GlIcon, GlLoadingIcon, GlPopover } from '@gitlab/u
import { nextTick } from 'vue';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
@@ -9,6 +10,7 @@ import CiValidate, { i18n } from '~/pipeline_editor/components/validate/ci_valid
import ValidatePipelinePopover from '~/pipeline_editor/components/popovers/validate_pipeline_popover.vue';
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
import lintCIMutation from '~/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql';
+import { pipelineEditorTrackingOptions } from '~/pipeline_editor/constants';
import {
mockBlobContentQueryResponse,
mockCiLintPath,
@@ -24,6 +26,7 @@ describe('Pipeline Editor Validate Tab', () => {
let wrapper;
let mockApollo;
let mockBlobContentData;
+ let trackingSpy;
const createComponent = ({
props,
@@ -140,9 +143,24 @@ describe('Pipeline Editor Validate Tab', () => {
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
await createComponentWithApollo();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockLintDataValid);
});
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('tracks the simulation event', () => {
+ const {
+ label,
+ actions: { simulatePipeline },
+ } = pipelineEditorTrackingOptions;
+ findCta().vm.$emit('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, simulatePipeline, { label });
+ });
+
it('renders loading state while simulation is ongoing', async () => {
findCta().vm.$emit('click');
await nextTick();
@@ -159,7 +177,7 @@ describe('Pipeline Editor Validate Tab', () => {
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: lintCIMutation,
variables: {
- dry_run: true,
+ dry: true,
content: mockCiYml,
endpoint: mockCiLintPath,
},
@@ -224,10 +242,27 @@ describe('Pipeline Editor Validate Tab', () => {
mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
await createComponentWithApollo();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockLintDataValid);
await findCta().vm.$emit('click');
});
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('tracks the second simulation event', async () => {
+ const {
+ label,
+ actions: { resimulatePipeline },
+ } = pipelineEditorTrackingOptions;
+
+ await wrapper.setProps({ ciFileContent: 'new yaml content' });
+ findResultsCta().vm.$emit('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, resimulatePipeline, { label });
+ });
+
it('renders content change status', async () => {
await wrapper.setProps({ ciFileContent: 'new yaml content' });
@@ -243,7 +278,7 @@ describe('Pipeline Editor Validate Tab', () => {
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: lintCIMutation,
variables: {
- dry_run: true,
+ dry: true,
content: 'new yaml content',
endpoint: mockCiLintPath,
},
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
index c6964f190b4..0cb7155c8c0 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_home_spec.js
@@ -14,7 +14,7 @@ import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tab
import {
CREATE_TAB,
FILE_TREE_DISPLAY_KEY,
- LINT_TAB,
+ VALIDATE_TAB,
MERGED_TAB,
TABS_INDEX,
VISUALIZE_TAB,
@@ -138,7 +138,7 @@ describe('Pipeline editor home wrapper', () => {
tab | shouldShow
${MERGED_TAB} | ${false}
${VISUALIZE_TAB} | ${false}
- ${LINT_TAB} | ${false}
+ ${VALIDATE_TAB} | ${false}
${CREATE_TAB} | ${true}
`(
'when the active tab is $tab the commit form is shown: $shouldShow',
@@ -170,7 +170,7 @@ describe('Pipeline editor home wrapper', () => {
tab | shouldShow
${MERGED_TAB} | ${false}
${VISUALIZE_TAB} | ${false}
- ${LINT_TAB} | ${false}
+ ${VALIDATE_TAB} | ${false}
${CREATE_TAB} | ${true}
`(
'when the tab query param is $tab the commit form is shown: $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 eec55091efa..18dbd1ce9d6 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -39,6 +39,7 @@ describe('Pipeline New Form', () => {
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"]');
@@ -102,6 +103,8 @@ describe('Pipeline New Form', () => {
});
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(findRefsDropdown().props('value')).toEqual({ shortName: 'tag-1' });
expect(findVariableRows()).toHaveLength(3);
});
@@ -114,6 +117,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');
});
it('does not display remove icon for last row', () => {
diff --git a/spec/frontend/pipeline_schedules/components/take_ownership_modal_spec.js b/spec/frontend/pipeline_schedules/components/take_ownership_modal_spec.js
new file mode 100644
index 00000000000..d787611fe8f
--- /dev/null
+++ b/spec/frontend/pipeline_schedules/components/take_ownership_modal_spec.js
@@ -0,0 +1,54 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import TakeOwnershipModal from '~/pipeline_schedules/components/take_ownership_modal.vue';
+
+describe('Take ownership modal', () => {
+ let wrapper;
+ const url = `/root/job-log-tester/-/pipeline_schedules/3/take_ownership`;
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMountExtended(TakeOwnershipModal, {
+ propsData: {
+ ownershipUrl: url,
+ ...props,
+ },
+ });
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has a primary action set to a url and a post data-method', () => {
+ const actionPrimary = findModal().props('actionPrimary');
+
+ expect(actionPrimary.attributes).toEqual(
+ expect.objectContaining([
+ {
+ category: 'primary',
+ variant: 'confirm',
+ href: url,
+ 'data-method': 'post',
+ },
+ ]),
+ );
+ });
+
+ it('shows a take ownership message', () => {
+ expect(findModal().text()).toBe(
+ 'Only the owner of a pipeline schedule can make changes to it. Do you want to take ownership of this schedule?',
+ );
+ });
+
+ it('emits the cancel event when clicking on cancel', async () => {
+ findModal().vm.$emit('cancel');
+
+ expect(findModal().emitted('cancel')).toHaveLength(1);
+ });
+});
diff --git a/spec/frontend/pipeline_wizard/components/editor_spec.js b/spec/frontend/pipeline_wizard/components/editor_spec.js
index 446412a4f02..540a08d2c7f 100644
--- a/spec/frontend/pipeline_wizard/components/editor_spec.js
+++ b/spec/frontend/pipeline_wizard/components/editor_spec.js
@@ -42,7 +42,7 @@ describe('Pages Yaml Editor wrapper', () => {
it('does not cause the touch event to be emitted', () => {
wrapper.setProps({ doc });
- expect(wrapper.emitted('touch')).not.toBeTruthy();
+ expect(wrapper.emitted('touch')).toBeUndefined();
});
});
@@ -63,7 +63,7 @@ describe('Pages Yaml Editor wrapper', () => {
it('emits touch if content is changed in editor', async () => {
await wrapper.vm.editor.setValue('foo: boo');
- expect(wrapper.emitted('touch')).toBeTruthy();
+ expect(wrapper.emitted('touch')).toEqual([expect.any(Array)]);
});
});
});
diff --git a/spec/frontend/pipeline_wizard/components/step_spec.js b/spec/frontend/pipeline_wizard/components/step_spec.js
index aa87b1d0b04..00b57f95ccc 100644
--- a/spec/frontend/pipeline_wizard/components/step_spec.js
+++ b/spec/frontend/pipeline_wizard/components/step_spec.js
@@ -139,7 +139,7 @@ describe('Pipeline Wizard - Step Page', () => {
await mockPrevClick();
await nextTick();
- expect(wrapper.emitted().back).toBeTruthy();
+ expect(wrapper.emitted().back).toEqual(expect.arrayContaining([]));
});
it('lets "next" event bubble upwards', async () => {
@@ -148,7 +148,7 @@ describe('Pipeline Wizard - Step Page', () => {
await mockNextClick();
await nextTick();
- expect(wrapper.emitted().next).toBeTruthy();
+ expect(wrapper.emitted().next).toEqual(expect.arrayContaining([]));
});
});
diff --git a/spec/frontend/pipeline_wizard/components/widgets/checklist_spec.js b/spec/frontend/pipeline_wizard/components/widgets/checklist_spec.js
index 43719595c5c..b8e194015b0 100644
--- a/spec/frontend/pipeline_wizard/components/widgets/checklist_spec.js
+++ b/spec/frontend/pipeline_wizard/components/widgets/checklist_spec.js
@@ -1,4 +1,4 @@
-import { GlFormCheckbox, GlFormCheckboxGroup } from '@gitlab/ui';
+import { GlFormCheckbox, GlFormGroup, GlFormCheckboxGroup } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ChecklistWidget from '~/pipeline_wizard/components/widgets/checklist.vue';
@@ -21,6 +21,7 @@ describe('Pipeline Wizard - Checklist Widget', () => {
return eventArray[eventArray.length - 1];
};
const findItem = (atIndex = 0) => wrapper.findAllComponents(GlFormCheckbox).at(atIndex);
+ const getGlFormGroup = () => wrapper.getComponent(GlFormGroup);
const getGlFormCheckboxGroup = () => wrapper.getComponent(GlFormCheckboxGroup);
// The item.ids *can* be passed inside props.items, but are usually
@@ -57,6 +58,16 @@ describe('Pipeline Wizard - Checklist Widget', () => {
expect(findItem().text()).toBe(props.items[0]);
});
+ it('assigns the same non-null value to label-for and form id', () => {
+ createComponent();
+ const formGroupLabelFor = getGlFormGroup().attributes('label-for');
+ const formCheckboxGroupId = getGlFormCheckboxGroup().attributes('id');
+
+ expect(formGroupLabelFor).not.toBeNull();
+ expect(formCheckboxGroupId).not.toBeNull();
+ expect(formGroupLabelFor).toBe(formCheckboxGroupId);
+ });
+
it('displays an item with a help text', () => {
createComponent();
const { text, help } = props.items[1];
diff --git a/spec/frontend/pipelines/components/pipeline_tabs_spec.js b/spec/frontend/pipelines/components/pipeline_tabs_spec.js
index e0210307823..3680d9d62c7 100644
--- a/spec/frontend/pipelines/components/pipeline_tabs_spec.js
+++ b/spec/frontend/pipelines/components/pipeline_tabs_spec.js
@@ -24,12 +24,14 @@ describe('The Pipeline Tabs', () => {
const findFailedJobsBadge = () => wrapper.findByTestId('failed-builds-counter');
const findJobsBadge = () => wrapper.findByTestId('builds-counter');
+ const findTestsBadge = () => wrapper.findByTestId('tests-counter');
const defaultProvide = {
defaultTabValue: '',
failedJobsCount: 1,
failedJobsSummary: [],
totalJobCount: 10,
+ testsCount: 123,
};
const createComponent = (provide = {}) => {
@@ -41,7 +43,6 @@ describe('The Pipeline Tabs', () => {
},
stubs: {
GlTab,
- TestReports: { template: '<div id="tests" />' },
},
}),
);
@@ -82,6 +83,7 @@ describe('The Pipeline Tabs', () => {
tabName | badgeComponent | badgeText
${'Jobs'} | ${findJobsBadge} | ${String(defaultProvide.totalJobCount)}
${'Failed Jobs'} | ${findFailedJobsBadge} | ${String(defaultProvide.failedJobsCount)}
+ ${'Tests'} | ${findTestsBadge} | ${String(defaultProvide.testsCount)}
`('shows badge for $tabName with the correct text', ({ badgeComponent, badgeText }) => {
createComponent();
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index 6c743f92116..f958f12acd4 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -102,7 +102,7 @@ describe('Pipelines filtered search', () => {
it('emits filterPipelines on submit with correct filter', () => {
findFilteredSearch().vm.$emit('submit', mockSearch);
- expect(wrapper.emitted('filterPipelines')).toBeTruthy();
+ expect(wrapper.emitted('filterPipelines')).toHaveLength(1);
expect(wrapper.emitted('filterPipelines')[0]).toEqual([mockSearch]);
});
diff --git a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
index 1ff32b03344..e712cdeaea2 100644
--- a/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_list/pipeline_stage_spec.js
@@ -1,4 +1,5 @@
import { GlDropdown } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -61,11 +62,10 @@ describe('Pipelines stage component', () => {
const findMergeTrainWarning = () => wrapper.find('[data-testid="warning-message-merge-trains"]');
const findLoadingState = () => wrapper.find('[data-testid="pipeline-stage-loading-state"]');
- const openStageDropdown = () => {
- findDropdownToggle().trigger('click');
- return new Promise((resolve) => {
- wrapper.vm.$root.$on('bv::dropdown::show', resolve);
- });
+ const openStageDropdown = async () => {
+ await findDropdownToggle().trigger('click');
+ await waitForPromises();
+ await nextTick();
};
describe('loading state', () => {
@@ -77,7 +77,10 @@ describe('Pipelines stage component', () => {
await openStageDropdown();
});
- it('displays loading state while jobs are being fetched', () => {
+ it('displays loading state while jobs are being fetched', async () => {
+ jest.runOnlyPendingTimers();
+ await nextTick();
+
expect(findLoadingState().exists()).toBe(true);
expect(findLoadingState().text()).toBe(PipelineStage.i18n.loadingText);
});
@@ -98,46 +101,41 @@ describe('Pipelines stage component', () => {
expect(glTooltipDirectiveMock.mock.calls[0][1].modifiers.ds0).toBe(true);
});
- it('should render a dropdown with the status icon', () => {
+ it('renders a dropdown with the status icon', () => {
expect(findDropdown().exists()).toBe(true);
expect(findDropdownToggle().exists()).toBe(true);
expect(findCiIcon().exists()).toBe(true);
});
- it('should render a borderless ci-icon', () => {
+ it('renders a borderless ci-icon', () => {
expect(findCiIcon().exists()).toBe(true);
expect(findCiIcon().props('isBorderless')).toBe(true);
expect(findCiIcon().classes('borderless')).toBe(true);
});
- it('should render a ci-icon with a custom border class', () => {
+ it('renders a ci-icon with a custom border class', () => {
expect(findCiIcon().exists()).toBe(true);
expect(findCiIcon().classes('gl-border')).toBe(true);
});
});
- describe('when update dropdown is changed', () => {
- beforeEach(() => {
- createComponent();
- });
- });
-
describe('when user opens dropdown and stage request is successful', () => {
beforeEach(async () => {
mock.onGet(dropdownPath).reply(200, stageReply);
createComponent();
await openStageDropdown();
+ await jest.runAllTimers();
await axios.waitForAll();
});
- it('should render the received data and emit `clickedDropdown` event', async () => {
+ it('renders the received data and emit `clickedDropdown` event', async () => {
expect(findDropdownMenu().text()).toContain(stageReply.latest_statuses[0].name);
expect(findDropdownMenuTitle().text()).toContain(stageReply.name);
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
});
- it('should refresh when updateDropdown is set to true', async () => {
+ it('refreshes when updateDropdown is set to true', async () => {
expect(mock.history.get).toHaveLength(1);
wrapper.setProps({ updateDropdown: true });
@@ -148,15 +146,14 @@ describe('Pipelines stage component', () => {
});
describe('when user opens dropdown and stage request fails', () => {
- beforeEach(async () => {
+ it('should close the dropdown', async () => {
mock.onGet(dropdownPath).reply(500);
createComponent();
await openStageDropdown();
await axios.waitForAll();
- });
+ await waitForPromises();
- it('should close the dropdown', () => {
expect(findDropdown().classes('show')).toBe(false);
});
});
@@ -181,26 +178,29 @@ describe('Pipelines stage component', () => {
it('should update the stage to request the new endpoint provided', async () => {
await openStageDropdown();
- await axios.waitForAll();
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
expect(findDropdownMenu().text()).toContain('this is the updated content');
});
});
describe('pipelineActionRequestComplete', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mock.onGet(dropdownPath).reply(200, stageReply);
mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
createComponent();
+ await waitForPromises();
+ await nextTick();
});
const clickCiAction = async () => {
await openStageDropdown();
- await axios.waitForAll();
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
- findCiActionBtn().trigger('click');
- await axios.waitForAll();
+ await findCiActionBtn().trigger('click');
};
it('closes dropdown when job item action is clicked', async () => {
@@ -211,29 +211,30 @@ describe('Pipelines stage component', () => {
expect(hidden).toHaveBeenCalledTimes(0);
await clickCiAction();
+ await waitForPromises();
expect(hidden).toHaveBeenCalledTimes(1);
});
it('emits `pipelineActionRequestComplete` when job item action is clicked', async () => {
await clickCiAction();
+ await waitForPromises();
expect(wrapper.emitted('pipelineActionRequestComplete')).toHaveLength(1);
});
});
describe('With merge trains enabled', () => {
- beforeEach(async () => {
+ it('shows a warning on the dropdown', async () => {
mock.onGet(dropdownPath).reply(200, stageReply);
createComponent({
isMergeTrain: true,
});
await openStageDropdown();
- await axios.waitForAll();
- });
+ jest.runOnlyPendingTimers();
+ await waitForPromises();
- it('shows a warning on the dropdown', () => {
const warning = findMergeTrainWarning();
expect(warning.text()).toBe('Merge train pipeline jobs can not be retried');
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index cdeaa0db61d..7d1e4774a24 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -426,7 +426,7 @@ describe('Linked pipeline', () => {
jest.spyOn(wrapper.vm, '$emit');
findButton().trigger('click');
- expect(wrapper.emitted().pipelineClicked).toBeTruthy();
+ expect(wrapper.emitted().pipelineClicked).toHaveLength(1);
});
it(`should emit ${BV_HIDE_TOOLTIP} to close the tooltip`, () => {
diff --git a/spec/frontend/pipelines/performance_insights_modal_spec.js b/spec/frontend/pipelines/performance_insights_modal_spec.js
index b745eb1d78e..8c802be7718 100644
--- a/spec/frontend/pipelines/performance_insights_modal_spec.js
+++ b/spec/frontend/pipelines/performance_insights_modal_spec.js
@@ -20,6 +20,7 @@ describe('Performance insights modal', () => {
const findModal = () => wrapper.findComponent(GlModal);
const findAlert = () => wrapper.findComponent(GlAlert);
const findLink = () => wrapper.findComponent(GlLink);
+ const findLimitText = () => wrapper.findByTestId('limit-alert-text');
const findQueuedCardData = () => wrapper.findByTestId('insights-queued-card-data');
const findQueuedCardLink = () => wrapper.findByTestId('insights-queued-card-link');
const findExecutedCardData = () => wrapper.findByTestId('insights-executed-card-data');
@@ -62,8 +63,19 @@ describe('Performance insights modal', () => {
expect(findModal().exists()).toBe(true);
});
- it('does not dispaly alert', () => {
- expect(findAlert().exists()).toBe(false);
+ it('displays alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('displays feedback issue link', () => {
+ expect(findLink().text()).toBe('Feedback issue');
+ expect(findLink().attributes('href')).toBe(
+ 'https://gitlab.com/gitlab-org/gitlab/-/issues/365902',
+ );
+ });
+
+ it('does not display limit text', () => {
+ expect(findLimitText().exists()).toBe(false);
});
describe('queued duration card', () => {
@@ -107,16 +119,13 @@ describe('Performance insights modal', () => {
});
});
- describe('limit alert', () => {
- it('displays limit alert when there is a next page', async () => {
+ describe('with next page', () => {
+ it('displays limit text when there is a next page', async () => {
createComponent([[getPerformanceInsights, getPerformanceInsightsNextPageHandler]]);
await waitForPromises();
- expect(findAlert().exists()).toBe(true);
- expect(findLink().attributes('href')).toBe(
- 'https://gitlab.com/gitlab-org/gitlab/-/issues/365902',
- );
+ expect(findLimitText().exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/pipelines/pipeline_multi_actions_spec.js b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
index e24d2e51f08..f554166da33 100644
--- a/spec/frontend/pipelines/pipeline_multi_actions_spec.js
+++ b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
@@ -84,13 +84,22 @@ describe('Pipeline Multi Actions Dropdown', () => {
expect(wrapper.vm.artifacts).toEqual(artifacts);
});
- it('should render all the provided artifacts', () => {
- createComponent({ mockData: { artifacts } });
+ it('should render all the provided artifacts when search query is empty', () => {
+ const searchQuery = '';
+ createComponent({ mockData: { searchQuery, artifacts } });
expect(findAllArtifactItems()).toHaveLength(artifacts.length);
expect(findEmptyMessage().exists()).toBe(false);
});
+ it('should render filtered artifacts when search query is not empty', () => {
+ const searchQuery = 'job-2';
+ createComponent({ mockData: { searchQuery, artifacts } });
+
+ expect(findAllArtifactItems()).toHaveLength(1);
+ expect(findEmptyMessage().exists()).toBe(false);
+ });
+
it('should render the correct artifact name and path', () => {
createComponent({ mockData: { artifacts } });
diff --git a/spec/frontend/pipelines/pipeline_url_spec.js b/spec/frontend/pipelines/pipeline_url_spec.js
index c6104a13216..25a97ecf49d 100644
--- a/spec/frontend/pipelines/pipeline_url_spec.js
+++ b/spec/frontend/pipelines/pipeline_url_spec.js
@@ -61,14 +61,14 @@ describe('Pipeline Url Component', () => {
describe('commit user avatar', () => {
it('renders when commit author exists', () => {
const pipelineBranch = mockPipelineBranch();
- const { avatar_url, name, path } = pipelineBranch.pipeline.commit.author;
+ const { avatar_url: imgSrc, name, path } = pipelineBranch.pipeline.commit.author;
createComponent(pipelineBranch);
const component = wrapper.findComponent(UserAvatarLink);
expect(component.exists()).toBe(true);
expect(component.props()).toMatchObject({
imgSize: 16,
- imgSrc: avatar_url,
+ imgSrc,
imgAlt: name,
linkHref: path,
tooltipText: name,
diff --git a/spec/frontend/pipelines/pipelines_spec.js b/spec/frontend/pipelines/pipelines_spec.js
index ad6d650670a..0bed24e588e 100644
--- a/spec/frontend/pipelines/pipelines_spec.js
+++ b/spec/frontend/pipelines/pipelines_spec.js
@@ -45,6 +45,7 @@ describe('Pipelines', () => {
ciLintPath: '/ci/lint',
resetCachePath: `${mockProjectPath}/settings/ci_cd/reset_cache`,
newPipelinePath: `${mockProjectPath}/pipelines/new`,
+
ciRunnerSettingsPath: `${mockProjectPath}/-/settings/ci_cd#js-runners-settings`,
};
@@ -654,7 +655,12 @@ describe('Pipelines', () => {
// Mock init a polling cycle
wrapper.vm.poll.options.notificationCallback(true);
- findStagesDropdownToggle().trigger('click');
+ await findStagesDropdownToggle().trigger('click');
+ jest.runOnlyPendingTimers();
+
+ // cancelMock is getting overwritten in pipelines_service.js#L29
+ // so we have to spy on it again here
+ cancelMock = jest.spyOn(wrapper.vm.service.cancelationSource, 'cancel');
await waitForPromises();
@@ -664,7 +670,8 @@ describe('Pipelines', () => {
});
it('stops polling & restarts polling', async () => {
- findStagesDropdownToggle().trigger('click');
+ await findStagesDropdownToggle().trigger('click');
+ jest.runOnlyPendingTimers();
await waitForPromises();
expect(cancelMock).not.toHaveBeenCalled();
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index 3c3143b1865..9b9ee4172f9 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -94,8 +94,8 @@ describe('Test reports app', () => {
beforeEach(() => createComponent());
it('sets testReports and shows tests', () => {
- expect(wrapper.vm.testReports).toBeTruthy();
- expect(wrapper.vm.showTests).toBeTruthy();
+ expect(wrapper.vm.testReports).toEqual(expect.any(Object));
+ expect(wrapper.vm.showTests).toBe(true);
});
it('shows tests details', () => {
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index d11090cba8a..57e5ef0ed1d 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -71,7 +71,7 @@ describe('Author Select', () => {
wrapper.setData({ hasSearchParam: true });
await nextTick();
- expect(findDropdownContainer().attributes('disabled')).toBeFalsy();
+ expect(findDropdownContainer().attributes('disabled')).toBeUndefined();
});
it('has correct tooltip message', async () => {
@@ -91,13 +91,13 @@ describe('Author Select', () => {
wrapper.setData({ hasSearchParam: false });
await nextTick();
- expect(findDropdown().attributes('disabled')).toBeFalsy();
+ expect(findDropdown().attributes('disabled')).toBeUndefined();
});
it('hasSearchParam if user types a truthy string', () => {
wrapper.vm.setSearchParam('false');
- expect(wrapper.vm.hasSearchParam).toBeTruthy();
+ expect(wrapper.vm.hasSearchParam).toBe(true);
});
});
@@ -153,9 +153,9 @@ describe('Author Select', () => {
});
it('has the correct props', async () => {
- const [{ avatar_url, username }] = authors;
+ const [{ avatar_url: avatarUrl, username }] = authors;
const result = {
- avatarUrl: avatar_url,
+ avatarUrl,
secondaryText: username,
isChecked: true,
};
diff --git a/spec/frontend/projects/compare/components/app_spec.js b/spec/frontend/projects/compare/components/app_spec.js
index 18e7f2e0f6e..c9ffdf20c32 100644
--- a/spec/frontend/projects/compare/components/app_spec.js
+++ b/spec/frontend/projects/compare/components/app_spec.js
@@ -34,7 +34,8 @@ describe('CompareApp component', () => {
expect(wrapper.props()).toEqual(
expect.objectContaining({
projectCompareIndexPath: defaultProps.projectCompareIndexPath,
- refsProjectPath: defaultProps.refsProjectPath,
+ sourceProjectRefsPath: defaultProps.sourceProjectRefsPath,
+ targetProjectRefsPath: defaultProps.targetProjectRefsPath,
paramsFrom: defaultProps.paramsFrom,
paramsTo: defaultProps.paramsTo,
}),
diff --git a/spec/frontend/projects/compare/components/mock_data.js b/spec/frontend/projects/compare/components/mock_data.js
index 61309928c26..81d64469a2a 100644
--- a/spec/frontend/projects/compare/components/mock_data.js
+++ b/spec/frontend/projects/compare/components/mock_data.js
@@ -1,7 +1,12 @@
-const refsProjectPath = 'some/refs/path';
+const sourceProjectRefsPath = 'some/refs/path';
+const targetProjectRefsPath = 'some/refs/path';
const paramsName = 'to';
const paramsBranch = 'main';
-const defaultProject = {
+const sourceProject = {
+ name: 'some-to-name',
+ id: '2',
+};
+const targetProject = {
name: 'some-to-name',
id: '1',
};
@@ -9,29 +14,31 @@ const defaultProject = {
export const appDefaultProps = {
projectCompareIndexPath: 'some/path',
projectMergeRequestPath: '',
- projects: [defaultProject],
+ projects: [sourceProject],
paramsFrom: 'main',
paramsTo: 'target/branch',
createMrPath: '',
- refsProjectPath,
- defaultProject,
+ sourceProjectRefsPath,
+ targetProjectRefsPath,
+ sourceProject,
+ targetProject,
};
export const revisionCardDefaultProps = {
- selectedProject: defaultProject,
+ selectedProject: targetProject,
paramsBranch,
revisionText: 'Source',
- refsProjectPath,
+ refsProjectPath: sourceProjectRefsPath,
paramsName,
};
export const repoDropdownDefaultProps = {
- selectedProject: defaultProject,
+ selectedProject: targetProject,
paramsName,
};
export const revisionDropdownDefaultProps = {
- refsProjectPath,
+ refsProjectPath: sourceProjectRefsPath,
paramsBranch,
paramsName,
};
diff --git a/spec/frontend/projects/project_new_spec.js b/spec/frontend/projects/project_new_spec.js
index 3034037fb1d..4fcecc3a307 100644
--- a/spec/frontend/projects/project_new_spec.js
+++ b/spec/frontend/projects/project_new_spec.js
@@ -1,6 +1,7 @@
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import projectNew from '~/projects/project_new';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
describe('New Project', () => {
let $projectImportUrl;
@@ -12,21 +13,27 @@ describe('New Project', () => {
beforeEach(() => {
setHTMLFixture(`
- <div class='toggle-import-form'>
- <div class='import-url-data'>
- <div class="form-group">
- <input id="project_import_url" />
- </div>
- <div id="import-url-auth-method">
- <div class="form-group">
- <input id="project-import-url-user" />
+ <div class="tab-pane active">
+ <div class='toggle-import-form'>
+ <form id="new_project">
+ <div class='import-url-data'>
+ <div class="form-group">
+ <input id="project_import_url" />
+ </div>
+ <div id="import-url-auth-method">
+ <div class="form-group">
+ <input id="project-import-url-user" />
+ </div>
+ <div class="form-group">
+ <input id="project_import_url_password" />
+ </div>
+ </div>
+ <input id="project_name" />
+ <input id="project_path" />
</div>
- <div class="form-group">
- <input id="project_import_url_password" />
- </div>
- </div>
- <input id="project_name" />
- <input id="project_path" />
+ <div class="js-user-readme-repo"></div>
+ <button class="js-create-project-button"/>
+ </form>
</div>
</div>
`);
@@ -45,6 +52,38 @@ describe('New Project', () => {
el.value = value;
};
+ describe('tracks manual path input', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
+ projectNew.bindEvents();
+ $projectPath.oldInputValue = '_old_value_';
+ });
+
+ afterEach(() => {
+ unmockTracking();
+ });
+
+ it('tracks the event', () => {
+ $projectPath.value = '_new_value_';
+
+ triggerEvent($projectPath, 'blur');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'user_input_path_slug', {
+ label: 'new_project_form',
+ });
+ });
+
+ it('does not track the event when there has been no change', () => {
+ $projectPath.value = '_old_value_';
+
+ triggerEvent($projectPath, 'blur');
+
+ expect(trackingSpy).not.toHaveBeenCalled();
+ });
+ });
+
describe('deriveProjectPathFromUrl', () => {
const dummyImportUrl = `${TEST_HOST}/dummy/import/url.git`;
diff --git a/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js b/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js
index 5997c2a083c..79bce5a4b3f 100644
--- a/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js
+++ b/spec/frontend/projects/settings/branch_rules/branch_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { GlDropdown, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlSearchBoxByType, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import BranchDropdown, {
i18n,
@@ -36,15 +36,20 @@ describe('Branch dropdown', () => {
await waitForPromises();
};
- const findGlDropdown = () => wrapper.find(GlDropdown);
- const findAllBranches = () => wrapper.findAll(GlDropdownItem);
+ const findGlDropdown = () => wrapper.findComponent(GlDropdown);
+ const findAllBranches = () => wrapper.findAllComponents(GlDropdownItem);
const findNoDataMsg = () => wrapper.findByTestId('no-data');
- const findGlSearchBoxByType = () => wrapper.find(GlSearchBoxByType);
+ 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 });
});
@@ -85,6 +90,10 @@ describe('Branch dropdown', () => {
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 () => {
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
new file mode 100644
index 00000000000..3592fa50622
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/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/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
new file mode 100644
index 00000000000..0e168a2ad78
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/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/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
new file mode 100644
index 00000000000..d54dad08338
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/components/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/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/mock_data.js b/spec/frontend/projects/settings/branch_rules/mock_data.js
new file mode 100644
index 00000000000..32cca027d19
--- /dev/null
+++ b/spec/frontend/projects/settings/branch_rules/mock_data.js
@@ -0,0 +1,10 @@
+export const membersAllowedToPush = ['Maintainers', 'Developers'];
+export const allowForcePush = false;
+export const membersAllowedToMerge = ['Maintainers'];
+export const requireCodeOwnersApproval = false;
+export const protections = {
+ membersAllowedToPush,
+ allowForcePush,
+ membersAllowedToMerge,
+ requireCodeOwnersApproval,
+};
diff --git a/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js b/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js
index 66ae6ddc02d..b0b2b9191d4 100644
--- a/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js
+++ b/spec/frontend/projects/settings/branch_rules/rule_edit_spec.js
@@ -3,9 +3,12 @@ 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', () => {
@@ -16,10 +19,15 @@ describe('Edit branch rule', () => {
wrapper = shallowMountExtended(RuleEdit, { propsData: { projectPath } });
};
- const findBranchDropdown = () => wrapper.find(BranchDropdown);
+ 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');
});
@@ -46,4 +54,55 @@ describe('Edit branch rule', () => {
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/transfer_project_form_spec.js b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
index 85b09ced024..bde7148078d 100644
--- a/spec/frontend/projects/settings/components/transfer_project_form_spec.js
+++ b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
@@ -1,11 +1,19 @@
+import Vue, { nextTick } from 'vue';
+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 { 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 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 waitForPromises from 'helpers/wait_for_promises';
describe('Transfer project form', () => {
let wrapper;
@@ -13,36 +21,50 @@ describe('Transfer project form', () => {
const confirmButtonText = 'Confirm';
const confirmationPhrase = 'You must construct additional pylons!';
- const createComponent = () =>
- shallowMountExtended(TransferProjectForm, {
+ const runDebounce = () => jest.runAllTimers();
+
+ Vue.use(VueApollo);
+
+ const defaultQueryHandler = jest
+ .fn()
+ .mockResolvedValue(searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1);
+
+ const createComponent = ({
+ requestHandlers = [[searchNamespacesWhereUserCanTransferProjectsQuery, defaultQueryHandler]],
+ } = {}) => {
+ wrapper = shallowMountExtended(TransferProjectForm, {
propsData: {
userNamespaces,
groupNamespaces,
confirmButtonText,
confirmationPhrase,
},
+ apolloProvider: createMockApollo(requestHandlers),
});
+ };
const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect);
const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger);
- beforeEach(() => {
- wrapper = createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
});
it('renders the namespace selector', () => {
+ createComponent();
+
expect(findNamespaceSelect().exists()).toBe(true);
});
it('renders the confirm button', () => {
+ createComponent();
+
expect(findConfirmDanger().exists()).toBe(true);
});
it('disables the confirm button by default', () => {
+ createComponent();
+
expect(findConfirmDanger().attributes('disabled')).toBe('true');
});
@@ -50,6 +72,8 @@ describe('Transfer project form', () => {
const [selectedItem] = groupNamespaces;
beforeEach(() => {
+ createComponent();
+
findNamespaceSelect().vm.$emit('select', selectedItem);
});
@@ -69,4 +93,132 @@ describe('Transfer project form', () => {
expect(wrapper.emitted('confirm')).toBeDefined();
});
});
+
+ it('passes correct props to `NamespaceSelect` component', async () => {
+ createComponent();
+
+ runDebounce();
+ await waitForPromises();
+
+ 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,
+ });
+ });
+
+ describe('when `search` event is fired', () => {
+ const arrange = async () => {
+ createComponent();
+
+ findNamespaceSelect().vm.$emit('search', 'foo');
+
+ await nextTick();
+ };
+
+ it('sets `isSearchLoading` prop to `true`', async () => {
+ await arrange();
+
+ expect(findNamespaceSelect().props('isSearchLoading')).toBe(true);
+ });
+
+ it('passes `search` variable to query', async () => {
+ await arrange();
+
+ runDebounce();
+ await waitForPromises();
+
+ expect(defaultQueryHandler).toHaveBeenCalledWith(expect.objectContaining({ search: 'foo' }));
+ });
+ });
+
+ describe('when `load-more-groups` event is fired', () => {
+ let queryHandler;
+
+ const arrange = async () => {
+ queryHandler = jest.fn();
+ queryHandler.mockResolvedValueOnce(
+ searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1,
+ );
+ queryHandler.mockResolvedValueOnce(
+ searchNamespacesWhereUserCanTransferProjectsQueryResponsePage2,
+ );
+
+ createComponent({
+ requestHandlers: [[searchNamespacesWhereUserCanTransferProjectsQuery, queryHandler]],
+ });
+
+ runDebounce();
+ await waitForPromises();
+
+ findNamespaceSelect().vm.$emit('load-more-groups');
+ await nextTick();
+ };
+
+ it('sets `isLoadingMoreGroups` prop to `true`', async () => {
+ await arrange();
+
+ expect(findNamespaceSelect().props('isLoadingMoreGroups')).toBe(true);
+ });
+
+ it('passes `after` and `first` variables to query', async () => {
+ await arrange();
+
+ runDebounce();
+ await waitForPromises();
+
+ expect(queryHandler).toHaveBeenCalledWith(
+ expect.objectContaining({
+ first: 25,
+ after:
+ searchNamespacesWhereUserCanTransferProjectsQueryResponsePage1.data.currentUser.groups
+ .pageInfo.endCursor,
+ }),
+ );
+ });
+
+ 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,
+ })),
+ );
+ });
+
+ it('updates `hasNextPageOfGroups` prop', async () => {
+ await arrange();
+
+ runDebounce();
+ await waitForPromises();
+
+ expect(findNamespaceSelect().props('hasNextPageOfGroups')).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/prometheus_metrics/custom_metrics_spec.js b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
index fc906194059..a079b0b97fd 100644
--- a/spec/frontend/prometheus_metrics/custom_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/custom_metrics_spec.js
@@ -50,39 +50,33 @@ describe('PrometheusMetrics', () => {
customMetrics.showMonitoringCustomMetricsPanelState(PANEL_STATE.LOADING);
expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toEqual(false);
- expect(customMetrics.$monitoredCustomMetricsEmpty.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBeTruthy();
- expect(
- customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden'),
- ).toBeTruthy();
-
- expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsEmpty.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden')).toBe(true);
+
+ expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBe(true);
});
it('should show metrics list when called with `list`', () => {
customMetrics.showMonitoringCustomMetricsPanelState(PANEL_STATE.LIST);
- expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$monitoredCustomMetricsEmpty.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$monitoredCustomMetricsEmpty.hasClass('hidden')).toBe(true);
expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toEqual(false);
- expect(
- customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden'),
- ).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden')).toBe(true);
expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toEqual(false);
- expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBe(true);
});
it('should show empty state when called with `empty`', () => {
customMetrics.showMonitoringCustomMetricsPanelState(PANEL_STATE.EMPTY);
- expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBe(true);
expect(customMetrics.$monitoredCustomMetricsEmpty.hasClass('hidden')).toEqual(false);
- expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBeTruthy();
- expect(
- customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden'),
- ).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden')).toBe(true);
expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toEqual(false);
expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toEqual(false);
@@ -94,14 +88,12 @@ describe('PrometheusMetrics', () => {
const $metricsListLi = customMetrics.$monitoredCustomMetricsList.find('li');
- expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBe(true);
expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toEqual(false);
- expect(
- customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden'),
- ).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsNoIntegrationText.hasClass('hidden')).toBe(true);
expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toEqual(false);
- expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBe(true);
expect($metricsListLi.length).toEqual(metrics.length);
});
@@ -114,10 +106,10 @@ describe('PrometheusMetrics', () => {
false,
);
- expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toBeTruthy();
- expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBeTruthy();
+ expect(customMetrics.$monitoredCustomMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$monitoredCustomMetricsList.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$newCustomMetricButton.hasClass('hidden')).toBe(true);
+ expect(customMetrics.$newCustomMetricText.hasClass('hidden')).toBe(true);
});
});
});
diff --git a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
index 0df2aad5882..a65cbe1a47a 100644
--- a/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/frontend/prometheus_metrics/prometheus_metrics_spec.js
@@ -54,25 +54,25 @@ describe('PrometheusMetrics', () => {
it('should show loading state when called with `loading`', () => {
prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeFalsy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeTruthy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(false);
+ expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBe(true);
});
it('should show metrics list when called with `list`', () => {
prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.LIST);
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeFalsy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBe(false);
});
it('should show empty state when called with `empty`', () => {
prometheusMetrics.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeTruthy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBe(false);
+ expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBe(true);
});
});
@@ -88,8 +88,8 @@ describe('PrometheusMetrics', () => {
const $metricsListLi = prometheusMetrics.$monitoredMetricsList.find('li');
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeFalsy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBe(false);
expect(prometheusMetrics.$monitoredMetricsCount.text()).toEqual(
'3 exporters with 12 metrics were found',
@@ -102,8 +102,8 @@ describe('PrometheusMetrics', () => {
it('should show missing environment variables list', () => {
prometheusMetrics.populateActiveMetrics(missingVarMetrics);
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$missingEnvVarPanel.hasClass('hidden')).toBeFalsy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$missingEnvVarPanel.hasClass('hidden')).toBe(false);
expect(prometheusMetrics.$missingEnvVarMetricCount.text()).toEqual('2');
expect(prometheusMetrics.$missingEnvVarPanel.find('li').length).toEqual(2);
@@ -143,12 +143,12 @@ describe('PrometheusMetrics', () => {
prometheusMetrics.loadActiveMetrics();
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeFalsy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(false);
expect(axios.get).toHaveBeenCalledWith(prometheusMetrics.activeMetricsEndpoint);
await waitForPromises();
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
});
it('should show empty state if response failed to load', async () => {
@@ -158,8 +158,8 @@ describe('PrometheusMetrics', () => {
await waitForPromises();
- expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
- expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBeFalsy();
+ expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBe(true);
+ expect(prometheusMetrics.$monitoredMetricsEmpty.hasClass('hidden')).toBe(false);
});
it('should populate metrics list once response is loaded', async () => {
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index 90a33152877..55e3dda60a0 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -55,6 +55,7 @@ Object {
"commitPath": "http://localhost/releases-namespace/releases-project/-/commit/b83d6e391c22777fca1ed3012fce84f633d7fed0",
"descriptionHtml": "<p data-sourcepos=\\"1:1-1:23\\" dir=\\"auto\\">An okay release <gl-emoji title=\\"shrug\\" data-name=\\"shrug\\" data-unicode-version=\\"9.0\\">🤷</gl-emoji></p>",
"evidences": Array [],
+ "historicalRelease": false,
"milestones": Array [],
"name": "The second release",
"releasedAt": 2019-01-10T00:00:00.000Z,
@@ -159,6 +160,7 @@ Object {
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
+ "historicalRelease": false,
"milestones": Array [
Object {
"__typename": "Milestone",
@@ -208,6 +210,7 @@ exports[`releases/util.js convertOneReleaseForEditingGraphQLResponse matches sna
Object {
"data": Object {
"_links": Object {
+ "__typename": "ReleaseLinks",
"self": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
"selfUrl": "http://localhost/releases-namespace/releases-project/-/releases/v1.1",
},
@@ -215,6 +218,7 @@ Object {
"count": undefined,
"links": Array [
Object {
+ "__typename": "ReleaseAssetLink",
"directAssetPath": "/binaries/awesome-app-3",
"id": "gid://gitlab/Releases::Link/13",
"linkType": "image",
@@ -222,6 +226,7 @@ Object {
"url": "https://example.com/image",
},
Object {
+ "__typename": "ReleaseAssetLink",
"directAssetPath": "/binaries/awesome-app-2",
"id": "gid://gitlab/Releases::Link/12",
"linkType": "package",
@@ -229,6 +234,7 @@ Object {
"url": "https://example.com/package",
},
Object {
+ "__typename": "ReleaseAssetLink",
"directAssetPath": "/binaries/awesome-app-1",
"id": "gid://gitlab/Releases::Link/11",
"linkType": "runbook",
@@ -236,6 +242,7 @@ Object {
"url": "http://localhost/releases-namespace/releases-project/runbook",
},
Object {
+ "__typename": "ReleaseAssetLink",
"directAssetPath": "/binaries/linux-amd64",
"id": "gid://gitlab/Releases::Link/10",
"linkType": "other",
@@ -250,6 +257,7 @@ Object {
"evidences": Array [],
"milestones": Array [
Object {
+ "__typename": "Milestone",
"id": "gid://gitlab/Milestone/123",
"issueStats": Object {},
"stats": undefined,
@@ -258,6 +266,7 @@ Object {
"webUrl": undefined,
},
Object {
+ "__typename": "Milestone",
"id": "gid://gitlab/Milestone/124",
"issueStats": Object {},
"stats": undefined,
@@ -373,6 +382,7 @@ Object {
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
+ "historicalRelease": false,
"milestones": Array [
Object {
"__typename": "Milestone",
diff --git a/spec/frontend/releases/components/release_block_header_spec.js b/spec/frontend/releases/components/release_block_header_spec.js
index 167ae4f32a2..c9921185bad 100644
--- a/spec/frontend/releases/components/release_block_header_spec.js
+++ b/spec/frontend/releases/components/release_block_header_spec.js
@@ -1,8 +1,9 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlLink, GlBadge } from '@gitlab/ui';
import { merge } from 'lodash';
import originalRelease from 'test_fixtures/api/releases/release.json';
import setWindowLocation from 'helpers/set_window_location_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { __ } from '~/locale';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import ReleaseBlockHeader from '~/releases/components/release_block_header.vue';
import { BACK_URL_PARAM } from '~/releases/constants';
@@ -12,10 +13,11 @@ describe('Release block header', () => {
let release;
const factory = (releaseUpdates = {}) => {
- wrapper = shallowMount(ReleaseBlockHeader, {
+ wrapper = shallowMountExtended(ReleaseBlockHeader, {
propsData: {
release: merge({}, release, releaseUpdates),
},
+ stubs: { GlBadge },
});
};
@@ -30,6 +32,7 @@ describe('Release block header', () => {
const findHeader = () => wrapper.find('h2');
const findHeaderLink = () => findHeader().find(GlLink);
const findEditButton = () => wrapper.find('.js-edit-button');
+ const findBadge = () => wrapper.findComponent(GlBadge);
describe('when _links.self is provided', () => {
beforeEach(() => {
@@ -84,4 +87,34 @@ describe('Release block header', () => {
expect(findEditButton().exists()).toBe(false);
});
});
+
+ describe('upcoming release', () => {
+ beforeEach(() => {
+ factory({ upcomingRelease: true, historicalRelease: false });
+ });
+
+ it('shows a badge that the release is upcoming', () => {
+ const badge = findBadge();
+
+ expect(badge.text()).toBe(__('Upcoming Release'));
+ expect(badge.props('variant')).toBe('warning');
+ });
+ });
+
+ describe('historical release', () => {
+ beforeEach(() => {
+ factory({ upcomingRelease: false, historicalRelease: true });
+ });
+
+ it('shows a badge that the release is historical', () => {
+ const badge = findBadge();
+
+ expect(badge.text()).toBe(__('Historical release'));
+ expect(badge.attributes('title')).toBe(
+ __(
+ 'This release was created with a date in the past. Evidence collection at the moment of the release is unavailable.',
+ ),
+ );
+ });
+ });
});
diff --git a/spec/frontend/reports/components/report_section_spec.js b/spec/frontend/reports/components/report_section_spec.js
index 888b49f3e0c..bdfba8d6878 100644
--- a/spec/frontend/reports/components/report_section_spec.js
+++ b/spec/frontend/reports/components/report_section_spec.js
@@ -1,16 +1,15 @@
-import { mount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
-import mountComponent, { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import { GlButton } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
-import reportSection from '~/reports/components/report_section.vue';
+import ReportItem from '~/reports/components/report_item.vue';
+import ReportSection from '~/reports/components/report_section.vue';
-describe('Report section', () => {
- let vm;
+describe('ReportSection component', () => {
let wrapper;
- const ReportSection = Vue.extend(reportSection);
- const findCollapseButton = () => wrapper.findByTestId('report-section-expand-button');
+
+ const findButton = () => wrapper.findComponent(GlButton);
const findPopover = () => wrapper.findComponent(HelpPopover);
+ const findReportSection = () => wrapper.find('.js-report-section-container');
const resolvedIssues = [
{
@@ -33,34 +32,24 @@ describe('Report section', () => {
alwaysOpen: false,
};
- const createComponent = (props) => {
- wrapper = extendedWrapper(
- mount(reportSection, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- }),
- );
- return wrapper;
+ const createComponent = ({ props = {}, data = {}, slots = {} } = {}) => {
+ wrapper = mountExtended(ReportSection, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ slots,
+ });
};
afterEach(() => {
- if (vm) {
- vm.$destroy();
- vm = null;
- }
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
+ wrapper.destroy();
});
describe('computed', () => {
- beforeEach(() => {
- vm = mountComponent(ReportSection, defaultProps);
- });
-
describe('isCollapsible', () => {
const testMatrix = [
{ hasIssues: false, alwaysOpen: false, isCollapsible: false },
@@ -73,12 +62,10 @@ describe('Report section', () => {
const issues = hasIssues ? 'has issues' : 'has no issues';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isCollapsible}, if the report ${issues} and ${open}`, async () => {
- vm.hasIssues = hasIssues;
- vm.alwaysOpen = alwaysOpen;
+ it(`is ${isCollapsible}, if the report ${issues} and ${open}`, () => {
+ createComponent({ props: { hasIssues, alwaysOpen } });
- await nextTick();
- expect(vm.isCollapsible).toBe(isCollapsible);
+ expect(wrapper.vm.isCollapsible).toBe(isCollapsible);
});
});
});
@@ -95,12 +82,10 @@ describe('Report section', () => {
const issues = isCollapsed ? 'is collapsed' : 'is not collapsed';
const open = alwaysOpen ? 'is always open' : 'is not always open';
- it(`is ${isExpanded}, if the report ${issues} and ${open}`, async () => {
- vm.isCollapsed = isCollapsed;
- vm.alwaysOpen = alwaysOpen;
+ it(`is ${isExpanded}, if the report ${issues} and ${open}`, () => {
+ createComponent({ props: { alwaysOpen }, data: { isCollapsed } });
- await nextTick();
- expect(vm.isExpanded).toBe(isExpanded);
+ expect(wrapper.vm.isExpanded).toBe(isExpanded);
});
});
});
@@ -108,110 +93,105 @@ describe('Report section', () => {
describe('when it is loading', () => {
it('should render loading indicator', () => {
- vm = mountComponent(ReportSection, {
- component: '',
- status: 'LOADING',
- loadingText: 'Loading Code Quality report',
- errorText: 'foo',
- successText: 'Code quality improved on 1 point and degraded on 1 point',
- hasIssues: false,
+ createComponent({
+ props: {
+ component: '',
+ status: 'LOADING',
+ loadingText: 'Loading Code Quality report',
+ errorText: 'foo',
+ successText: 'Code quality improved on 1 point and degraded on 1 point',
+ hasIssues: false,
+ },
});
- expect(vm.$el.textContent.trim()).toEqual('Loading Code Quality report');
+ expect(wrapper.text()).toBe('Loading Code Quality report');
});
});
describe('with success status', () => {
- beforeEach(() => {
- vm = mountComponent(ReportSection, {
- ...defaultProps,
- hasIssues: true,
- });
- });
-
it('should render provided data', () => {
- expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
- 'Code quality improved on 1 point and degraded on 1 point',
- );
+ createComponent({ props: { hasIssues: true } });
- expect(vm.$el.querySelectorAll('.report-block-container li').length).toEqual(
- resolvedIssues.length,
+ expect(wrapper.find('.js-code-text').text()).toBe(
+ 'Code quality improved on 1 point and degraded on 1 point',
);
+ expect(wrapper.findAllComponents(ReportItem)).toHaveLength(resolvedIssues.length);
});
describe('toggleCollapsed', () => {
- const hiddenCss = { display: 'none' };
-
it('toggles issues', async () => {
- vm.$el.querySelector('button').click();
+ createComponent({ props: { hasIssues: true } });
+
+ await findButton().trigger('click');
- await nextTick();
- expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse');
+ expect(findReportSection().isVisible()).toBe(true);
+ expect(findButton().text()).toBe('Collapse');
- vm.$el.querySelector('button').click();
+ await findButton().trigger('click');
- await nextTick();
- expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand');
+ expect(findReportSection().isVisible()).toBe(false);
+ expect(findButton().text()).toBe('Expand');
});
- it('is always expanded, if always-open is set to true', async () => {
- vm.alwaysOpen = true;
- await nextTick();
- expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss);
- expect(vm.$el.querySelector('button')).toBeNull();
+ 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);
});
});
});
describe('snowplow events', () => {
- it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', async () => {
- createComponent({ hasIssues: true, shouldEmitToggleEvent: true });
+ it('does emit an event on issue toggle if the shouldEmitToggleEvent prop does exist', () => {
+ createComponent({ props: { hasIssues: true, shouldEmitToggleEvent: true } });
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
- findCollapseButton().trigger('click');
- await nextTick();
- expect(wrapper.emitted().toggleEvent).toHaveLength(1);
+ findButton().trigger('click');
+
+ expect(wrapper.emitted('toggleEvent')).toEqual([[]]);
});
- it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', async () => {
- createComponent({ hasIssues: true });
+ it('does not emit an event on issue toggle if the shouldEmitToggleEvent prop does not exist', () => {
+ createComponent({ props: { hasIssues: true } });
+
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
+ findButton().trigger('click');
- findCollapseButton().trigger('click');
- await nextTick();
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
});
- it('does not emit an event if always-open is set to true', async () => {
- createComponent({ alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true });
+ it('does not emit an event if always-open is set to true', () => {
+ createComponent({
+ props: { alwaysOpen: true, hasIssues: true, shouldEmitToggleEvent: true },
+ });
- await nextTick();
- expect(wrapper.emitted().toggleEvent).toBeUndefined();
+ expect(wrapper.emitted('toggleEvent')).toBeUndefined();
});
});
describe('with failed request', () => {
it('should render error indicator', () => {
- vm = mountComponent(ReportSection, {
- component: '',
- status: 'ERROR',
- loadingText: 'Loading Code Quality report',
- errorText: 'Failed to load Code Quality report',
- successText: 'Code quality improved on 1 point and degraded on 1 point',
- hasIssues: false,
+ createComponent({
+ props: {
+ component: '',
+ status: 'ERROR',
+ loadingText: 'Loading Code Quality report',
+ errorText: 'Failed to load Code Quality report',
+ successText: 'Code quality improved on 1 point and degraded on 1 point',
+ hasIssues: false,
+ },
});
- expect(vm.$el.textContent.trim()).toEqual('Failed to load Code Quality report');
+ expect(wrapper.text()).toBe('Failed to load Code Quality report');
});
});
describe('with action buttons passed to the slot', () => {
beforeEach(() => {
- vm = mountComponentWithSlots(ReportSection, {
+ createComponent({
props: {
status: 'SUCCESS',
successText: 'success',
@@ -224,17 +204,17 @@ describe('Report section', () => {
});
it('should render the passed button', () => {
- expect(vm.$el.textContent.trim()).toContain('Action!');
+ expect(wrapper.text()).toContain('Action!');
});
it('should still render the expand/collapse button', () => {
- expect(vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual('Expand');
+ expect(findButton().text()).toBe('Expand');
});
});
describe('Success and Error slots', () => {
const createComponentWithSlots = (status) => {
- vm = mountComponentWithSlots(ReportSection, {
+ createComponent({
props: {
status,
hasIssues: true,
@@ -250,25 +230,25 @@ describe('Report section', () => {
it('only renders success slot when status is "SUCCESS"', () => {
createComponentWithSlots('SUCCESS');
- expect(vm.$el.textContent.trim()).toContain('This is a success');
- expect(vm.$el.textContent.trim()).not.toContain('This is an error');
- expect(vm.$el.textContent.trim()).not.toContain('This is loading');
+ expect(wrapper.text()).toContain('This is a success');
+ expect(wrapper.text()).not.toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is loading');
});
it('only renders error slot when status is "ERROR"', () => {
createComponentWithSlots('ERROR');
- expect(vm.$el.textContent.trim()).toContain('This is an error');
- expect(vm.$el.textContent.trim()).not.toContain('This is a success');
- expect(vm.$el.textContent.trim()).not.toContain('This is loading');
+ expect(wrapper.text()).toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is a success');
+ expect(wrapper.text()).not.toContain('This is loading');
});
it('only renders loading slot when status is "LOADING"', () => {
createComponentWithSlots('LOADING');
- expect(vm.$el.textContent.trim()).toContain('This is loading');
- expect(vm.$el.textContent.trim()).not.toContain('This is an error');
- expect(vm.$el.textContent.trim()).not.toContain('This is a success');
+ expect(wrapper.text()).toContain('This is loading');
+ expect(wrapper.text()).not.toContain('This is an error');
+ expect(wrapper.text()).not.toContain('This is a success');
});
});
@@ -280,9 +260,7 @@ describe('Report section', () => {
};
beforeEach(() => {
- createComponent({
- popoverOptions: options,
- });
+ createComponent({ props: { popoverOptions: options } });
});
it('popover is shown with options', () => {
@@ -292,7 +270,7 @@ describe('Report section', () => {
describe('when popover options are not defined', () => {
beforeEach(() => {
- createComponent({ popoverOptions: {} });
+ createComponent({ props: { popoverOptions: {} } });
});
it('popover is not shown', () => {
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index 2b70cb84c67..0f7cf4e61b2 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -21,12 +21,13 @@ import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
import userInfoQuery from '~/repository/queries/user_info.query.graphql';
import applicationInfoQuery from '~/repository/queries/application_info.query.graphql';
import CodeIntelligence from '~/code_navigation/components/app.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import * as urlUtility from '~/lib/utils/url_utility';
import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import httpStatusCodes from '~/lib/utils/http_status';
import LineHighlighter from '~/blob/line_highlighter';
import { LEGACY_FILE_TYPES } from '~/repository/constants';
+import { SIMPLE_BLOB_VIEWER, RICH_BLOB_VIEWER } from '~/blob/components/constants';
import {
simpleViewerMock,
richViewerMock,
@@ -53,7 +54,12 @@ const mockAxios = new MockAdapter(axios);
const createMockStore = () =>
new Vuex.Store({ actions: { fetchData: jest.fn, setInitialData: jest.fn() } });
-const createComponent = async (mockData = {}, mountFn = shallowMount) => {
+const mockRouterPush = jest.fn();
+const mockRouter = {
+ push: mockRouterPush,
+};
+
+const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute = {}) => {
Vue.use(VueApollo);
const {
@@ -106,6 +112,10 @@ const createComponent = async (mockData = {}, mountFn = shallowMount) => {
apolloProvider: fakeApollo,
propsData: propsMock,
mixins: [{ data: () => ({ ref: refMock }) }],
+ mocks: {
+ $route: mockRoute,
+ $router: mockRouter,
+ },
provide: {
targetBranch: 'test',
originalBranch: 'default-ref',
@@ -158,10 +168,11 @@ describe('Blob content viewer component', () => {
it('renders a BlobHeader component', async () => {
await createComponent();
- expect(findBlobHeader().props('activeViewerType')).toEqual('simple');
+ expect(findBlobHeader().props('activeViewerType')).toEqual(SIMPLE_BLOB_VIEWER);
expect(findBlobHeader().props('hasRenderError')).toEqual(false);
expect(findBlobHeader().props('hideViewerSwitcher')).toEqual(true);
expect(findBlobHeader().props('blob')).toEqual(simpleViewerMock);
+ expect(mockRouterPush).not.toHaveBeenCalled();
});
it('copies blob text to clipboard', async () => {
@@ -179,7 +190,7 @@ describe('Blob content viewer component', () => {
expect(findBlobContent().props('activeViewer')).toEqual({
fileType: 'text',
tooLarge: false,
- type: 'simple',
+ type: SIMPLE_BLOB_VIEWER,
renderError: null,
});
});
@@ -229,6 +240,12 @@ describe('Blob content viewer component', () => {
expect(LineHighlighter).toHaveBeenCalled();
});
+ it('does not load the LineHighlighter for RichViewers', async () => {
+ mockAxios.onGet(legacyViewerUrl).replyOnce(httpStatusCodes.OK, 'test');
+ await createComponent({ blob: { ...richViewerMock, fileType, highlightJs } });
+ expect(LineHighlighter).not.toHaveBeenCalled();
+ });
+
it('scrolls to the hash', async () => {
mockAxios.onGet(legacyViewerUrl).replyOnce(httpStatusCodes.OK, 'test');
await createComponent({ blob: { ...simpleViewerMock, fileType, highlightJs } });
@@ -241,10 +258,11 @@ describe('Blob content viewer component', () => {
it('renders a BlobHeader component', async () => {
await createComponent({ blob: richViewerMock });
- expect(findBlobHeader().props('activeViewerType')).toEqual('rich');
+ expect(findBlobHeader().props('activeViewerType')).toEqual(RICH_BLOB_VIEWER);
expect(findBlobHeader().props('hasRenderError')).toEqual(false);
expect(findBlobHeader().props('hideViewerSwitcher')).toEqual(false);
expect(findBlobHeader().props('blob')).toEqual(richViewerMock);
+ expect(mockRouterPush).not.toHaveBeenCalled();
});
it('renders a BlobContent component', async () => {
@@ -254,30 +272,49 @@ describe('Blob content viewer component', () => {
expect(findBlobContent().props('activeViewer')).toEqual({
fileType: 'markup',
tooLarge: false,
- type: 'rich',
+ type: RICH_BLOB_VIEWER,
renderError: null,
});
});
- it('updates viewer type when viewer changed is clicked', async () => {
+ it('changes to simple viewer when URL has code line hash', async () => {
+ jest.spyOn(urlUtility, 'getLocationHash').mockReturnValueOnce('L5');
+
await createComponent({ blob: richViewerMock });
expect(findBlobContent().props('activeViewer')).toEqual(
expect.objectContaining({
- type: 'rich',
+ type: SIMPLE_BLOB_VIEWER,
+ }),
+ );
+ expect(findBlobHeader().props('activeViewerType')).toEqual(SIMPLE_BLOB_VIEWER);
+ });
+
+ it('updates viewer type when viewer changed is clicked', async () => {
+ await createComponent({ blob: richViewerMock }, shallowMount, { path: '/mock_path' });
+
+ expect(findBlobContent().props('activeViewer')).toEqual(
+ expect.objectContaining({
+ type: RICH_BLOB_VIEWER,
}),
);
- expect(findBlobHeader().props('activeViewerType')).toEqual('rich');
+ expect(findBlobHeader().props('activeViewerType')).toEqual(RICH_BLOB_VIEWER);
- findBlobHeader().vm.$emit('viewer-changed', 'simple');
+ findBlobHeader().vm.$emit('viewer-changed', SIMPLE_BLOB_VIEWER);
await nextTick();
- expect(findBlobHeader().props('activeViewerType')).toEqual('simple');
+ expect(findBlobHeader().props('activeViewerType')).toEqual(SIMPLE_BLOB_VIEWER);
expect(findBlobContent().props('activeViewer')).toEqual(
expect.objectContaining({
- type: 'simple',
+ type: SIMPLE_BLOB_VIEWER,
}),
);
+ expect(mockRouterPush).toHaveBeenCalledWith({
+ path: '/mock_path',
+ query: {
+ plain: '1',
+ },
+ });
});
});
@@ -497,12 +534,12 @@ describe('Blob content viewer component', () => {
it('simple edit redirects to the simple editor', () => {
findWebIdeLink().vm.$emit('edit', 'simple');
- expect(redirectTo).toHaveBeenCalledWith(simpleViewerMock.editBlobPath);
+ expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.editBlobPath);
});
it('IDE edit redirects to the IDE editor', () => {
findWebIdeLink().vm.$emit('edit', 'ide');
- expect(redirectTo).toHaveBeenCalledWith(simpleViewerMock.ideEditPath);
+ expect(urlUtility.redirectTo).toHaveBeenCalledWith(simpleViewerMock.ideEditPath);
});
it.each`
@@ -537,4 +574,32 @@ describe('Blob content viewer component', () => {
},
);
});
+
+ describe('active viewer based on plain attribute', () => {
+ it.each`
+ hasRichViewer | plain | activeViewerType
+ ${true} | ${'0'} | ${RICH_BLOB_VIEWER}
+ ${true} | ${'1'} | ${SIMPLE_BLOB_VIEWER}
+ ${false} | ${'0'} | ${SIMPLE_BLOB_VIEWER}
+ ${false} | ${'1'} | ${SIMPLE_BLOB_VIEWER}
+ `(
+ 'activeViewerType is `$activeViewerType` when hasRichViewer is $hasRichViewer and plain is set to $plain',
+ async ({ hasRichViewer, plain, activeViewerType }) => {
+ await createComponent(
+ { blob: hasRichViewer ? richViewerMock : simpleViewerMock },
+ shallowMount,
+ { query: { plain } },
+ );
+
+ await nextTick();
+
+ expect(findBlobContent().props('activeViewer')).toEqual(
+ expect.objectContaining({
+ type: activeViewerType,
+ }),
+ );
+ expect(findBlobHeader().props('activeViewerType')).toEqual(activeViewerType);
+ },
+ );
+ });
});
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
index 0a5766a25f9..4db295fe0b7 100644
--- a/spec/frontend/repository/mock_data.js
+++ b/spec/frontend/repository/mock_data.js
@@ -8,6 +8,7 @@ export const simpleViewerMock = {
language: 'javascript',
path: 'some_file.js',
webPath: 'some_file.js',
+ blamePath: 'blame/file.js',
editBlobPath: 'some_file.js/edit',
gitpodBlobUrl: 'https://gitpod.io#path/to/blob.js',
ideEditPath: 'some_file.js/ide/edit',
diff --git a/spec/frontend/right_sidebar_spec.js b/spec/frontend/right_sidebar_spec.js
index 5847842f5a6..3b220ba8351 100644
--- a/spec/frontend/right_sidebar_spec.js
+++ b/spec/frontend/right_sidebar_spec.js
@@ -70,7 +70,7 @@ describe('RightSidebar', () => {
it('should not hide collapsed icons', () => {
[].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), (el) => {
- expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBeFalsy();
+ expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBe(false);
});
});
});
diff --git a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
index 8a34cb14d8b..ffe3599ac64 100644
--- a/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
+++ b/spec/frontend/runner/admin_runner_edit/admin_runner_edit_app_spec.js
@@ -87,10 +87,10 @@ describe('AdminRunnerEditApp', () => {
await createComponentWithApollo();
expect(findRunnerUpdateForm().props()).toMatchObject({
- runner: mockRunner,
loading: false,
runnerPath: mockRunnerPath,
});
+ expect(findRunnerUpdateForm().props('runner')).toEqual(mockRunner);
});
describe('When there is an error', () => {
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 433be5d5027..509681c5a77 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
@@ -14,6 +14,7 @@ import RunnerPauseButton from '~/runner/components/runner_pause_button.vue';
import RunnerDeleteButton from '~/runner/components/runner_delete_button.vue';
import RunnerEditButton from '~/runner/components/runner_edit_button.vue';
import RunnersJobs from '~/runner/components/runner_jobs.vue';
+
import runnerQuery from '~/runner/graphql/show/runner.query.graphql';
import AdminRunnerShowApp from '~/runner/admin_runner_show/admin_runner_show_app.vue';
import { captureException } from '~/runner/sentry_utils';
@@ -94,10 +95,10 @@ describe('AdminRunnerShowApp', () => {
});
it('shows basic runner details', async () => {
- const expected = `Description Instance runner
+ const expected = `Description My Runner
Last contact Never contacted
Version 1.0.0
- IP Address 127.0.0.1
+ IP Address None
Executor None
Architecture None
Platform darwin
@@ -182,17 +183,19 @@ describe('AdminRunnerShowApp', () => {
});
describe('When loading', () => {
- beforeEach(() => {
+ it('does not show runner details', () => {
mockRunnerQueryResult();
createComponent();
- });
- it('does not show runner details', () => {
expect(findRunnerDetails().exists()).toBe(false);
});
it('does not show runner jobs', () => {
+ mockRunnerQueryResult();
+
+ createComponent();
+
expect(findRunnersJobs().exists()).toBe(false);
});
});
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index aa1aa723491..97341be7d5d 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import { GlToast, GlLink } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -19,10 +19,11 @@ import { createLocalState } from '~/runner/graphql/list/local_state';
import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.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';
-import RunnerCount from '~/runner/components/stat/runner_count.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';
@@ -37,12 +38,10 @@ import {
PARAM_KEY_STATUS,
PARAM_KEY_TAG,
STATUS_ONLINE,
- STATUS_OFFLINE,
- STATUS_STALE,
RUNNER_PAGE_SIZE,
} from '~/runner/constants';
import allRunnersQuery from 'ee_else_ce/runner/graphql/list/all_runners.query.graphql';
-import allRunnersCountQuery from '~/runner/graphql/list/all_runners_count.query.graphql';
+import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_count.query.graphql';
import { captureException } from '~/runner/sentry_utils';
import {
@@ -51,6 +50,7 @@ import {
allRunnersDataPaginated,
onlineContactTimeoutSecs,
staleTimeoutSecs,
+ emptyPageInfo,
emptyStateSvgPath,
emptyStateFilteredSvgPath,
} from '../mock_data';
@@ -72,19 +72,24 @@ jest.mock('~/lib/utils/url_utility', () => ({
Vue.use(VueApollo);
Vue.use(GlToast);
+const COUNT_QUERIES = 7; // 4 tabs + 3 status queries
+
describe('AdminRunnersApp', () => {
let wrapper;
let cacheConfig;
let localMutations;
+ let showToast;
const findRunnerStats = () => wrapper.findComponent(RunnerStats);
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));
- const findRunnerPaginationNext = () => findRunnerPagination().findByLabelText('Go to next page');
+ const findRunnerPaginationNext = () => findRunnerPagination().findByText(s__('Pagination|Next'));
const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
const createComponent = ({
@@ -117,6 +122,8 @@ describe('AdminRunnersApp', () => {
...options,
});
+ showToast = jest.spyOn(wrapper.vm.$root.$toast, 'show');
+
return waitForPromises();
};
@@ -128,17 +135,10 @@ describe('AdminRunnersApp', () => {
afterEach(() => {
mockRunnersHandler.mockReset();
mockRunnersCountHandler.mockReset();
+ showToast.mockReset();
wrapper.destroy();
});
- it('shows the runner tabs with a runner count for each type', async () => {
- await createComponent({ mountFn: mountExtended });
-
- expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
- `All ${mockRunnersCount} Instance ${mockRunnersCount} Group ${mockRunnersCount} Project ${mockRunnersCount}`,
- );
- });
-
it('shows the runner setup instructions', () => {
createComponent();
@@ -146,27 +146,38 @@ describe('AdminRunnersApp', () => {
expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE);
});
- it('shows total runner counts', async () => {
- await createComponent({ mountFn: mountExtended });
+ describe('shows total runner counts', () => {
+ beforeEach(async () => {
+ await createComponent({ mountFn: mountExtended });
+ });
+
+ it('fetches counts', () => {
+ expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES);
+ });
+
+ it('shows the runner tabs', () => {
+ expect(findRunnerTypeTabs().text()).toMatchInterpolatedText(
+ `All ${mockRunnersCount} Instance ${mockRunnersCount} Group ${mockRunnersCount} Project ${mockRunnersCount}`,
+ );
+ });
- expect(mockRunnersCountHandler).toHaveBeenCalledWith({ status: STATUS_ONLINE });
- expect(mockRunnersCountHandler).toHaveBeenCalledWith({ status: STATUS_OFFLINE });
- expect(mockRunnersCountHandler).toHaveBeenCalledWith({ status: STATUS_STALE });
-
- expect(findRunnerStats().text()).toContain(
- `${s__('Runners|Online runners')} ${mockRunnersCount}`,
- );
- expect(findRunnerStats().text()).toContain(
- `${s__('Runners|Offline runners')} ${mockRunnersCount}`,
- );
- expect(findRunnerStats().text()).toContain(
- `${s__('Runners|Stale runners')} ${mockRunnersCount}`,
- );
+ it('shows the total', () => {
+ expect(findRunnerStats().text()).toContain(
+ `${s__('Runners|Online runners')} ${mockRunnersCount}`,
+ );
+ expect(findRunnerStats().text()).toContain(
+ `${s__('Runners|Offline runners')} ${mockRunnersCount}`,
+ );
+ expect(findRunnerStats().text()).toContain(
+ `${s__('Runners|Stale runners')} ${mockRunnersCount}`,
+ );
+ });
});
it('shows the runners list', async () => {
await createComponent();
+ expect(mockRunnersHandler).toHaveBeenCalledTimes(1);
expect(findRunnerList().props('runners')).toEqual(mockRunners);
});
@@ -226,18 +237,13 @@ describe('AdminRunnersApp', () => {
});
describe('Single runner row', () => {
- let showToast;
-
const { id: graphqlId, shortSha } = mockRunners[0];
const id = getIdFromGraphQLId(graphqlId);
- const COUNT_QUERIES = 7; // Smart queries that display a filtered count of runners
- const FILTERED_COUNT_QUERIES = 4; // Smart queries that display a count of runners in tabs
beforeEach(async () => {
mockRunnersCountHandler.mockClear();
await createComponent({ mountFn: mountExtended });
- showToast = jest.spyOn(wrapper.vm.$root.$toast, 'show');
});
it('Links to the runner page', async () => {
@@ -252,7 +258,7 @@ describe('AdminRunnersApp', () => {
findRunnerActionsCell().vm.$emit('toggledPaused');
- expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES + FILTERED_COUNT_QUERIES);
+ expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES * 2);
expect(showToast).toHaveBeenCalledTimes(0);
});
@@ -266,25 +272,20 @@ describe('AdminRunnersApp', () => {
describe('when a filter is preselected', () => {
beforeEach(async () => {
- setWindowLocation(`?status[]=${STATUS_ONLINE}&runner_type[]=${INSTANCE_TYPE}&tag[]=tag1`);
+ setWindowLocation(`?status[]=${STATUS_ONLINE}&runner_type[]=${INSTANCE_TYPE}&paused[]=true`);
- await createComponent({
- stubs: {
- RunnerStats,
- RunnerCount,
- },
- });
+ await createComponent({ mountFn: mountExtended });
});
it('sets the filters in the search bar', () => {
expect(findRunnerFilteredSearchBar().props('value')).toEqual({
runnerType: INSTANCE_TYPE,
filters: [
- { type: 'status', value: { data: STATUS_ONLINE, operator: '=' } },
- { type: 'tag', value: { data: 'tag1', operator: '=' } },
+ { type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } },
+ { type: PARAM_KEY_PAUSED, value: { data: 'true', operator: '=' } },
],
sort: 'CREATED_DESC',
- pagination: { page: 1 },
+ pagination: {},
});
});
@@ -292,7 +293,7 @@ describe('AdminRunnersApp', () => {
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
status: STATUS_ONLINE,
type: INSTANCE_TYPE,
- tagList: ['tag1'],
+ paused: true,
sort: DEFAULT_SORT,
first: RUNNER_PAGE_SIZE,
});
@@ -302,41 +303,34 @@ describe('AdminRunnersApp', () => {
expect(mockRunnersCountHandler).toHaveBeenCalledWith({
type: INSTANCE_TYPE,
status: STATUS_ONLINE,
- tagList: ['tag1'],
+ paused: true,
});
});
});
describe('when a filter is selected by the user', () => {
- beforeEach(() => {
- createComponent({
- stubs: {
- RunnerStats,
- RunnerCount,
- },
- });
+ beforeEach(async () => {
+ await createComponent({ mountFn: mountExtended });
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
- filters: [
- { type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } },
- { type: PARAM_KEY_TAG, value: { data: 'tag1', operator: '=' } },
- ],
+ filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } }],
sort: CREATED_ASC,
});
+
+ await nextTick();
});
it('updates the browser url', () => {
expect(updateHistory).toHaveBeenLastCalledWith({
title: expect.any(String),
- url: expect.stringContaining('?status[]=ONLINE&tag[]=tag1&sort=CREATED_ASC'),
+ url: expect.stringContaining('?status[]=ONLINE&sort=CREATED_ASC'),
});
});
it('requests the runners with filters', () => {
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
status: STATUS_ONLINE,
- tagList: ['tag1'],
sort: CREATED_ASC,
first: RUNNER_PAGE_SIZE,
});
@@ -344,7 +338,6 @@ describe('AdminRunnersApp', () => {
it('fetches count results for requested status', () => {
expect(mockRunnersCountHandler).toHaveBeenCalledWith({
- tagList: ['tag1'],
status: STATUS_ONLINE,
});
});
@@ -353,39 +346,79 @@ describe('AdminRunnersApp', () => {
it('when runners have not loaded, shows a loading state', () => {
createComponent();
expect(findRunnerList().props('loading')).toBe(true);
+ expect(findRunnerPagination().attributes('disabled')).toBe('true');
});
describe('when bulk delete is enabled', () => {
- beforeEach(() => {
- createComponent({
- provide: {
- glFeatures: { adminRunnersBulkDelete: true },
- },
+ describe('Before runners are deleted', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mountFn: mountExtended,
+ provide: {
+ glFeatures: { adminRunnersBulkDelete: true },
+ },
+ });
});
- });
- it('runner list is checkable', () => {
- expect(findRunnerList().props('checkable')).toBe(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);
+ });
+
+ 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,
+ });
+ });
});
- it('responds to checked items by updating the local cache', () => {
- const setRunnerCheckedMock = jest
- .spyOn(localMutations, 'setRunnerChecked')
- .mockImplementation(() => {});
+ describe('When runners are deleted', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mountFn: mountExtended,
+ provide: {
+ glFeatures: { adminRunnersBulkDelete: true },
+ },
+ });
+ });
- const runner = mockRunners[0];
+ it('count data is refetched', async () => {
+ expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES);
- expect(setRunnerCheckedMock).toHaveBeenCalledTimes(0);
+ findRunnerBulkDelete().vm.$emit('deleted', { message: 'Runners deleted' });
- findRunnerList().vm.$emit('checked', {
- runner,
- isChecked: true,
+ expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES * 2);
});
- expect(setRunnerCheckedMock).toHaveBeenCalledTimes(1);
- expect(setRunnerCheckedMock).toHaveBeenCalledWith({
- runner,
- isChecked: true,
+ it('toast is shown', async () => {
+ expect(showToast).toHaveBeenCalledTimes(0);
+
+ findRunnerBulkDelete().vm.$emit('deleted', { message: 'Runners deleted' });
+
+ expect(showToast).toHaveBeenCalledTimes(1);
+ expect(showToast).toHaveBeenCalledWith('Runners deleted');
});
});
});
@@ -394,13 +427,20 @@ describe('AdminRunnersApp', () => {
beforeEach(async () => {
mockRunnersHandler.mockResolvedValue({
data: {
- runners: { nodes: [] },
+ runners: {
+ nodes: [],
+ pageInfo: emptyPageInfo,
+ },
},
});
await createComponent();
});
+ it('shows no errors', () => {
+ expect(createAlert).not.toHaveBeenCalled();
+ });
+
it('shows an empty state', () => {
expect(findRunnerListEmptyState().props('isSearchFiltered')).toBe(false);
});
@@ -440,19 +480,25 @@ describe('AdminRunnersApp', () => {
});
describe('Pagination', () => {
+ const { pageInfo } = allRunnersDataPaginated.data.runners;
+
beforeEach(async () => {
mockRunnersHandler.mockResolvedValue(allRunnersDataPaginated);
await createComponent({ mountFn: mountExtended });
});
+ it('passes the page info', () => {
+ expect(findRunnerPagination().props('pageInfo')).toEqual(pageInfo);
+ });
+
it('navigates to the next page', async () => {
await findRunnerPaginationNext().trigger('click');
expect(mockRunnersHandler).toHaveBeenLastCalledWith({
sort: CREATED_DESC,
first: RUNNER_PAGE_SIZE,
- after: allRunnersDataPaginated.data.runners.pageInfo.endCursor,
+ after: pageInfo.endCursor,
});
});
});
diff --git a/spec/frontend/runner/components/cells/runner_summary_cell_spec.js b/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
index b2e8c5a3ad9..b06ab652212 100644
--- a/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_summary_cell_spec.js
@@ -1,3 +1,4 @@
+import { __ } from '~/locale';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import RunnerSummaryCell from '~/runner/components/cells/runner_summary_cell.vue';
import { INSTANCE_TYPE, PROJECT_TYPE } from '~/runner/constants';
@@ -61,8 +62,16 @@ describe('RunnerTypeCell', () => {
expect(wrapper.text()).toContain(mockDescription);
});
- it('Displays the runner ip address', () => {
- expect(wrapper.text()).toContain(mockIpAddress);
+ it('Displays ip address', () => {
+ expect(wrapper.text()).toContain(`${__('IP Address')} ${mockIpAddress}`);
+ });
+
+ it('Displays no ip address', () => {
+ createComponent({
+ ipAddress: null,
+ });
+
+ expect(wrapper.text()).not.toContain(__('IP Address'));
});
it('Displays a custom slot', () => {
diff --git a/spec/frontend/runner/components/registration/registration_token_spec.js b/spec/frontend/runner/components/registration/registration_token_spec.js
index ed1a698d36f..19344a68f79 100644
--- a/spec/frontend/runner/components/registration/registration_token_spec.js
+++ b/spec/frontend/runner/components/registration/registration_token_spec.js
@@ -1,5 +1,5 @@
import { GlToast } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RegistrationToken from '~/runner/components/registration/registration_token.vue';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
@@ -11,28 +11,17 @@ describe('RegistrationToken', () => {
let wrapper;
let showToast;
- const findInputCopyToggleVisibility = () => wrapper.findComponent(InputCopyToggleVisibility);
-
- const vueWithGlToast = () => {
- const localVue = createLocalVue();
- localVue.use(GlToast);
- return localVue;
- };
+ Vue.use(GlToast);
- const createComponent = ({
- props = {},
- withGlToast = true,
- mountFn = shallowMountExtended,
- } = {}) => {
- const localVue = withGlToast ? vueWithGlToast() : undefined;
+ const findInputCopyToggleVisibility = () => wrapper.findComponent(InputCopyToggleVisibility);
+ const createComponent = ({ props = {}, mountFn = shallowMountExtended } = {}) => {
wrapper = mountFn(RegistrationToken, {
propsData: {
value: mockToken,
inputId: 'token-value',
...props,
},
- localVue,
});
showToast = wrapper.vm.$toast ? jest.spyOn(wrapper.vm.$toast, 'show') : null;
@@ -69,13 +58,5 @@ describe('RegistrationToken', () => {
expect(showToast).toHaveBeenCalledTimes(1);
expect(showToast).toHaveBeenCalledWith('Registration token copied!');
});
-
- it('does not fail when toast is not defined', () => {
- createComponent({ withGlToast: false });
- findInputCopyToggleVisibility().vm.$emit('copy');
-
- // This block also tests for unhandled errors
- expect(showToast).toBeNull();
- });
});
});
diff --git a/spec/frontend/runner/components/runner_assigned_item_spec.js b/spec/frontend/runner/components/runner_assigned_item_spec.js
index 1ff6983fbe7..cc09046c000 100644
--- a/spec/frontend/runner/components/runner_assigned_item_spec.js
+++ b/spec/frontend/runner/components/runner_assigned_item_spec.js
@@ -1,10 +1,12 @@
-import { GlAvatar } from '@gitlab/ui';
+import { GlAvatar, GlBadge } from '@gitlab/ui';
+import { s__ } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RunnerAssignedItem from '~/runner/components/runner_assigned_item.vue';
import { AVATAR_SHAPE_OPTION_RECT } from '~/vue_shared/constants';
const mockHref = '/group/project';
const mockName = 'Project';
+const mockDescription = 'Project description';
const mockFullName = 'Group / Project';
const mockAvatarUrl = '/avatar.png';
@@ -12,6 +14,7 @@ describe('RunnerAssignedItem', () => {
let wrapper;
const findAvatar = () => wrapper.findByTestId('item-avatar');
+ const findBadge = () => wrapper.findComponent(GlBadge);
const createComponent = ({ props = {} } = {}) => {
wrapper = shallowMountExtended(RunnerAssignedItem, {
@@ -20,6 +23,7 @@ describe('RunnerAssignedItem', () => {
name: mockName,
fullName: mockFullName,
avatarUrl: mockAvatarUrl,
+ description: mockDescription,
...props,
},
});
@@ -51,4 +55,14 @@ describe('RunnerAssignedItem', () => {
expect(groupFullName.attributes('href')).toBe(mockHref);
});
+
+ it('Shows description', () => {
+ expect(wrapper.text()).toContain(mockDescription);
+ });
+
+ it('Shows owner badge', () => {
+ createComponent({ props: { isOwner: true } });
+
+ expect(findBadge().text()).toBe(s__('Runner|Owner'));
+ });
});
diff --git a/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js b/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js
new file mode 100644
index 00000000000..0ac89e82314
--- /dev/null
+++ b/spec/frontend/runner/components/runner_bulk_delete_checkbox_spec.js
@@ -0,0 +1,101 @@
+import Vue from 'vue';
+import { GlFormCheckbox } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+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');
+
+describe('RunnerBulkDeleteCheckbox', () => {
+ let wrapper;
+ let mockState;
+ let mockCheckedRunnerIds;
+
+ 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 createComponent = ({ props = {} } = {}) => {
+ const { cacheConfig, localMutations } = mockState;
+ const apolloProvider = createMockApollo(undefined, undefined, cacheConfig);
+
+ wrapper = shallowMountExtended(RunnerBulkDeleteCheckbox, {
+ apolloProvider,
+ provide: {
+ localMutations,
+ },
+ propsData: {
+ runners: mockRunners,
+ ...props,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockState = createLocalState();
+
+ jest
+ .spyOn(mockState.cacheConfig.typePolicies.Query.fields, 'checkedRunnerIds')
+ .mockImplementation(() => mockCheckedRunnerIds);
+
+ 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 () => {
+ mockCheckedRunnerIds = checkedRunnerIds;
+
+ createComponent();
+ });
+
+ it(`is ${is}`, () => {
+ expect(findCheckbox().attributes('disabled')).toBe(disabled);
+ expect(findCheckbox().attributes('checked')).toBe(checked);
+ expect(findCheckbox().attributes('indeterminate')).toBe(indeterminate);
+ });
+ });
+
+ describe('When user selects', () => {
+ beforeEach(() => {
+ mockCheckedRunnerIds = mockIds;
+ createComponent();
+ });
+
+ it.each([[true], [false]])('sets checked to %s', (checked) => {
+ findCheckbox().vm.$emit('change', checked);
+
+ expect(mockState.localMutations.setRunnersChecked).toHaveBeenCalledTimes(1);
+ expect(mockState.localMutations.setRunnersChecked).toHaveBeenCalledWith({
+ isChecked: checked,
+ runners: mockRunners,
+ });
+ });
+ });
+
+ describe('When runners are loading', () => {
+ beforeEach(() => {
+ createComponent({ props: { runners: [] } });
+ });
+
+ it(`is disabled`, () => {
+ expect(findCheckbox().attributes('disabled')).toBe('true');
+ expect(findCheckbox().attributes('checked')).toBe(undefined);
+ expect(findCheckbox().attributes('indeterminate')).toBe(undefined);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_bulk_delete_spec.js b/spec/frontend/runner/components/runner_bulk_delete_spec.js
index f5b56396cf1..6df918c684f 100644
--- a/spec/frontend/runner/components/runner_bulk_delete_spec.js
+++ b/spec/frontend/runner/components/runner_bulk_delete_spec.js
@@ -1,37 +1,65 @@
import Vue from 'vue';
-import { GlSprintf } from '@gitlab/ui';
+import { GlModal, GlSprintf } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
+import { createAlert } from '~/flash';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
+import { s__ } from '~/locale';
import RunnerBulkDelete from '~/runner/components/runner_bulk_delete.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
+import BulkRunnerDeleteMutation from '~/runner/graphql/list/bulk_runner_delete.mutation.graphql';
import { createLocalState } from '~/runner/graphql/list/local_state';
import waitForPromises from 'helpers/wait_for_promises';
+import { allRunnersData } from '../mock_data';
Vue.use(VueApollo);
-jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
+jest.mock('~/flash');
describe('RunnerBulkDelete', () => {
let wrapper;
+ let apolloCache;
let mockState;
let mockCheckedRunnerIds;
- const findClearBtn = () => wrapper.findByTestId('clear-btn');
- const findDeleteBtn = () => wrapper.findByTestId('delete-btn');
+ const findClearBtn = () => wrapper.findByText(s__('Runners|Clear selection'));
+ const findDeleteBtn = () => wrapper.findByText(s__('Runners|Delete selected'));
+ const findModal = () => wrapper.findComponent(GlModal);
+
+ const mockRunners = allRunnersData.data.runners.nodes;
+ const mockId1 = allRunnersData.data.runners.nodes[0].id;
+ const mockId2 = allRunnersData.data.runners.nodes[1].id;
+
+ const bulkRunnerDeleteHandler = jest.fn();
const createComponent = () => {
const { cacheConfig, localMutations } = mockState;
+ const apolloProvider = createMockApollo(
+ [[BulkRunnerDeleteMutation, bulkRunnerDeleteHandler]],
+ undefined,
+ cacheConfig,
+ );
wrapper = shallowMountExtended(RunnerBulkDelete, {
- apolloProvider: createMockApollo(undefined, undefined, cacheConfig),
+ apolloProvider,
provide: {
localMutations,
},
+ propsData: {
+ runners: mockRunners,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
stubs: {
GlSprintf,
+ GlModal,
},
});
+
+ apolloCache = apolloProvider.defaultClient.cache;
+ jest.spyOn(apolloCache, 'evict');
+ jest.spyOn(apolloCache, 'gc');
};
beforeEach(() => {
@@ -43,6 +71,7 @@ describe('RunnerBulkDelete', () => {
});
afterEach(() => {
+ bulkRunnerDeleteHandler.mockReset();
wrapper.destroy();
});
@@ -61,10 +90,10 @@ describe('RunnerBulkDelete', () => {
});
describe.each`
- count | ids | text
- ${1} | ${['gid:Runner/1']} | ${'1 runner'}
- ${2} | ${['gid:Runner/1', 'gid:Runner/2']} | ${'2 runners'}
- `('When $count runner(s) are checked', ({ count, ids, text }) => {
+ count | ids | text
+ ${1} | ${[mockId1]} | ${'1 runner'}
+ ${2} | ${[mockId1, mockId2]} | ${'2 runners'}
+ `('When $count runner(s) are checked', ({ ids, text }) => {
beforeEach(() => {
mockCheckedRunnerIds = ids;
@@ -86,18 +115,129 @@ describe('RunnerBulkDelete', () => {
});
it('shows confirmation modal', () => {
- expect(confirmAction).toHaveBeenCalledTimes(0);
+ const modalId = getBinding(findDeleteBtn().element, 'gl-modal');
+
+ expect(findModal().props('modal-id')).toBe(modalId);
+ expect(findModal().text()).toContain(text);
+ });
+ });
+
+ describe('when runners are deleted', () => {
+ let evt;
+ let mockHideModal;
+
+ beforeEach(() => {
+ mockCheckedRunnerIds = [mockId1, mockId2];
+
+ createComponent();
+
+ jest.spyOn(mockState.localMutations, 'clearChecked').mockImplementation(() => {});
+ mockHideModal = jest.spyOn(findModal().vm, 'hide');
+ });
+
+ describe('when deletion is successful', () => {
+ beforeEach(() => {
+ bulkRunnerDeleteHandler.mockResolvedValue({
+ data: {
+ bulkRunnerDelete: { deletedIds: mockCheckedRunnerIds, errors: [] },
+ },
+ });
+
+ evt = {
+ preventDefault: jest.fn(),
+ };
+ findModal().vm.$emit('primary', evt);
+ });
+
+ it('has loading state', async () => {
+ expect(findModal().props('actionPrimary').attributes.loading).toBe(true);
+ expect(findModal().props('actionCancel').attributes.loading).toBe(true);
+
+ await waitForPromises();
+
+ expect(findModal().props('actionPrimary').attributes.loading).toBe(false);
+ expect(findModal().props('actionCancel').attributes.loading).toBe(false);
+ });
+
+ it('modal is not prevented from closing', () => {
+ expect(evt.preventDefault).toHaveBeenCalledTimes(1);
+ });
+
+ it('mutation is called', async () => {
+ expect(bulkRunnerDeleteHandler).toHaveBeenCalledWith({
+ input: { ids: mockCheckedRunnerIds },
+ });
+ });
+
+ it('user interface is updated', async () => {
+ const { evict, gc } = apolloCache;
+
+ expect(evict).toHaveBeenCalledTimes(mockCheckedRunnerIds.length);
+ expect(evict).toHaveBeenCalledWith({
+ id: expect.stringContaining(mockCheckedRunnerIds[0]),
+ });
+ expect(evict).toHaveBeenCalledWith({
+ id: expect.stringContaining(mockCheckedRunnerIds[1]),
+ });
+
+ expect(gc).toHaveBeenCalledTimes(1);
+ });
+
+ it('modal is hidden', () => {
+ expect(mockHideModal).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('when deletion fails', () => {
+ beforeEach(() => {
+ bulkRunnerDeleteHandler.mockRejectedValue(new Error('error!'));
+
+ evt = {
+ preventDefault: jest.fn(),
+ };
+ findModal().vm.$emit('primary', evt);
+ });
+
+ it('has loading state', async () => {
+ expect(findModal().props('actionPrimary').attributes.loading).toBe(true);
+ expect(findModal().props('actionCancel').attributes.loading).toBe(true);
+
+ await waitForPromises();
+
+ expect(findModal().props('actionPrimary').attributes.loading).toBe(false);
+ expect(findModal().props('actionCancel').attributes.loading).toBe(false);
+ });
+
+ it('modal is not prevented from closing', () => {
+ expect(evt.preventDefault).toHaveBeenCalledTimes(1);
+ });
+
+ it('mutation is called', () => {
+ expect(bulkRunnerDeleteHandler).toHaveBeenCalledWith({
+ input: { ids: mockCheckedRunnerIds },
+ });
+ });
+
+ it('user interface is not updated', async () => {
+ await waitForPromises();
- findDeleteBtn().vm.$emit('click');
+ const { evict, gc } = apolloCache;
- expect(confirmAction).toHaveBeenCalledTimes(1);
+ expect(evict).not.toHaveBeenCalled();
+ expect(gc).not.toHaveBeenCalled();
+ expect(mockState.localMutations.clearChecked).not.toHaveBeenCalled();
+ });
- const [, confirmOptions] = confirmAction.mock.calls[0];
- const { title, modalHtmlMessage, primaryBtnText } = confirmOptions;
+ it('alert is called', async () => {
+ await waitForPromises();
- expect(title).toMatch(text);
- expect(primaryBtnText).toMatch(text);
- expect(modalHtmlMessage).toMatch(`<strong>${count}</strong>`);
+ expect(createAlert).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalledWith({
+ message: expect.any(String),
+ captureError: true,
+ error: expect.any(Error),
+ });
+ });
});
});
});
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 83fb1764c6d..e35bec3aa38 100644
--- a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -143,7 +143,7 @@ describe('RunnerList', () => {
runnerType: INSTANCE_TYPE,
filters: mockFilters,
sort: mockOtherSort,
- pagination: { page: 1 },
+ pagination: {},
});
});
});
@@ -156,7 +156,7 @@ describe('RunnerList', () => {
runnerType: null,
filters: mockFilters,
sort: mockDefaultSort,
- pagination: { page: 1 },
+ pagination: {},
});
});
@@ -167,7 +167,7 @@ describe('RunnerList', () => {
runnerType: null,
filters: [],
sort: mockOtherSort,
- pagination: { page: 1 },
+ pagination: {},
});
});
});
diff --git a/spec/frontend/runner/components/runner_jobs_spec.js b/spec/frontend/runner/components/runner_jobs_spec.js
index 20582aaaf40..4d38afb25ee 100644
--- a/spec/frontend/runner/components/runner_jobs_spec.js
+++ b/spec/frontend/runner/components/runner_jobs_spec.js
@@ -73,8 +73,7 @@ describe('RunnerJobs', () => {
it('Shows jobs', () => {
const jobs = findRunnerJobsTable().props('jobs');
- expect(jobs).toHaveLength(mockJobs.length);
- expect(jobs[0]).toMatchObject(mockJobs[0]);
+ expect(jobs).toEqual(mockJobs);
});
describe('When "Next" page is clicked', () => {
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index eca4bbc3490..7b58a81bb0d 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -88,9 +88,7 @@ describe('RunnerList', () => {
createComponent({}, mountExtended);
// Badges
- expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText(
- 'never contacted paused',
- );
+ expect(findCell({ fieldKey: 'status' }).text()).toMatchInterpolatedText('never contacted');
// Runner summary
expect(findCell({ fieldKey: 'summary' }).text()).toContain(
@@ -124,10 +122,10 @@ describe('RunnerList', () => {
expect(findCell({ fieldKey: 'checkbox' }).find('input').exists()).toBe(true);
});
- it('Emits a checked event', () => {
+ it('Emits a checked event', async () => {
const checkbox = findCell({ fieldKey: 'checkbox' }).find('input');
- checkbox.setChecked();
+ await checkbox.setChecked();
expect(wrapper.emitted('checked')).toHaveLength(1);
expect(wrapper.emitted('checked')[0][0]).toEqual({
diff --git a/spec/frontend/runner/components/runner_pagination_spec.js b/spec/frontend/runner/components/runner_pagination_spec.js
index e144b52ceb3..499cc59250d 100644
--- a/spec/frontend/runner/components/runner_pagination_spec.js
+++ b/spec/frontend/runner/components/runner_pagination_spec.js
@@ -1,5 +1,5 @@
-import { GlPagination } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { GlKeysetPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
import RunnerPagination from '~/runner/components/runner_pagination.vue';
const mockStartCursor = 'START_CURSOR';
@@ -8,21 +8,11 @@ const mockEndCursor = 'END_CURSOR';
describe('RunnerPagination', () => {
let wrapper;
- const findPagination = () => wrapper.findComponent(GlPagination);
+ const findPagination = () => wrapper.findComponent(GlKeysetPagination);
- const createComponent = ({ page = 1, hasPreviousPage = false, hasNextPage = true } = {}) => {
- wrapper = mount(RunnerPagination, {
- propsData: {
- value: {
- page,
- },
- pageInfo: {
- hasPreviousPage,
- hasNextPage,
- startCursor: mockStartCursor,
- endCursor: mockEndCursor,
- },
- },
+ const createComponent = (propsData = {}) => {
+ wrapper = shallowMount(RunnerPagination, {
+ propsData,
});
};
@@ -30,114 +20,96 @@ describe('RunnerPagination', () => {
wrapper.destroy();
});
- describe('When on the first page', () => {
- beforeEach(() => {
- createComponent({
- page: 1,
- hasPreviousPage: false,
- hasNextPage: true,
- });
- });
-
- it('Contains the current page information', () => {
- expect(findPagination().props('value')).toBe(1);
- expect(findPagination().props('prevPage')).toBe(null);
- expect(findPagination().props('nextPage')).toBe(2);
- });
-
- it('Goes to the second page', () => {
- findPagination().vm.$emit('input', 2);
-
- expect(wrapper.emitted('input')[0]).toEqual([
- {
- after: mockEndCursor,
- page: 2,
- },
- ]);
- });
- });
-
describe('When in between pages', () => {
+ const mockPageInfo = {
+ startCursor: mockStartCursor,
+ endCursor: mockEndCursor,
+ hasPreviousPage: true,
+ hasNextPage: true,
+ };
+
beforeEach(() => {
createComponent({
- page: 2,
- hasPreviousPage: true,
- hasNextPage: true,
+ pageInfo: mockPageInfo,
});
});
it('Contains the current page information', () => {
- expect(findPagination().props('value')).toBe(2);
- expect(findPagination().props('prevPage')).toBe(1);
- expect(findPagination().props('nextPage')).toBe(3);
+ expect(findPagination().props()).toMatchObject(mockPageInfo);
});
- it('Shows the next and previous pages', () => {
- const links = findPagination().findAll('a');
-
- expect(links).toHaveLength(2);
- expect(links.at(0).text()).toBe('Previous');
- expect(links.at(1).text()).toBe('Next');
- });
-
- it('Goes to the last page', () => {
- findPagination().vm.$emit('input', 3);
+ it('Goes to the prev page', () => {
+ findPagination().vm.$emit('prev');
expect(wrapper.emitted('input')[0]).toEqual([
{
- after: mockEndCursor,
- page: 3,
+ before: mockStartCursor,
},
]);
});
- it('Goes to the first page', () => {
- findPagination().vm.$emit('input', 1);
+ it('Goes to the next page', () => {
+ findPagination().vm.$emit('next');
expect(wrapper.emitted('input')[0]).toEqual([
{
- page: 1,
+ after: mockEndCursor,
},
]);
});
});
- describe('When in the last page', () => {
+ describe.each`
+ page | hasPreviousPage | hasNextPage
+ ${'first'} | ${false} | ${true}
+ ${'last'} | ${true} | ${false}
+ `('When on the $page page', ({ page, hasPreviousPage, hasNextPage }) => {
+ const mockPageInfo = {
+ startCursor: mockStartCursor,
+ endCursor: mockEndCursor,
+ hasPreviousPage,
+ hasNextPage,
+ };
+
beforeEach(() => {
createComponent({
- page: 3,
- hasPreviousPage: true,
- hasNextPage: false,
+ pageInfo: mockPageInfo,
});
});
- it('Contains the current page', () => {
- expect(findPagination().props('value')).toBe(3);
- expect(findPagination().props('prevPage')).toBe(2);
- expect(findPagination().props('nextPage')).toBe(null);
+ it(`Contains the ${page} page information`, () => {
+ expect(findPagination().props()).toMatchObject(mockPageInfo);
});
});
- describe('When only one page', () => {
+ describe('When no other pages', () => {
beforeEach(() => {
createComponent({
- page: 1,
- hasPreviousPage: false,
- hasNextPage: false,
+ pageInfo: {
+ hasPreviousPage: false,
+ hasNextPage: false,
+ },
});
});
- it('does not display pagination', () => {
- expect(wrapper.html()).toBe('');
+ it('is not shown', () => {
+ expect(findPagination().exists()).toBe(false);
});
+ });
- it('Contains the current page', () => {
- expect(findPagination().props('value')).toBe(1);
+ describe('When adding more attributes', () => {
+ beforeEach(() => {
+ createComponent({
+ pageInfo: {
+ hasPreviousPage: true,
+ hasNextPage: false,
+ },
+ disabled: true,
+ });
});
- it('Shows no more page buttons', () => {
- expect(findPagination().props('prevPage')).toBe(null);
- expect(findPagination().props('nextPage')).toBe(null);
+ it('attributes are passed', () => {
+ expect(findPagination().props('disabled')).toBe(true);
});
});
});
diff --git a/spec/frontend/runner/components/runner_projects_spec.js b/spec/frontend/runner/components/runner_projects_spec.js
index 6932b3b5197..c988fb8477d 100644
--- a/spec/frontend/runner/components/runner_projects_spec.js
+++ b/spec/frontend/runner/components/runner_projects_spec.js
@@ -95,6 +95,7 @@ describe('RunnerProjects', () => {
name,
fullName: nameWithNamespace,
avatarUrl,
+ isOwner: true, // first project is always owner
});
});
diff --git a/spec/frontend/runner/components/stat/runner_count_spec.js b/spec/frontend/runner/components/stat/runner_count_spec.js
index 89b51b1b4a7..2a6a745099f 100644
--- a/spec/frontend/runner/components/stat/runner_count_spec.js
+++ b/spec/frontend/runner/components/stat/runner_count_spec.js
@@ -7,8 +7,8 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { captureException } from '~/runner/sentry_utils';
-import allRunnersCountQuery from '~/runner/graphql/list/all_runners_count.query.graphql';
-import groupRunnersCountQuery from '~/runner/graphql/list/group_runners_count.query.graphql';
+import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_count.query.graphql';
+import groupRunnersCountQuery from 'ee_else_ce/runner/graphql/list/group_runners_count.query.graphql';
import { runnersCountData, groupRunnersCountData } from '../../mock_data';
diff --git a/spec/frontend/runner/components/stat/runner_single_stat_spec.js b/spec/frontend/runner/components/stat/runner_single_stat_spec.js
new file mode 100644
index 00000000000..964a6a6ff71
--- /dev/null
+++ b/spec/frontend/runner/components/stat/runner_single_stat_spec.js
@@ -0,0 +1,61 @@
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { shallowMount } from '@vue/test-utils';
+import RunnerSingleStat from '~/runner/components/stat/runner_single_stat.vue';
+import RunnerCount from '~/runner/components/stat/runner_count.vue';
+import { INSTANCE_TYPE, GROUP_TYPE } from '~/runner/constants';
+
+describe('RunnerStats', () => {
+ let wrapper;
+
+ const findRunnerCount = () => wrapper.findComponent(RunnerCount);
+ const findGlSingleStat = () => wrapper.findComponent(GlSingleStat);
+
+ const createComponent = ({ props = {}, count, mountFn = shallowMount, ...options } = {}) => {
+ wrapper = mountFn(RunnerSingleStat, {
+ propsData: {
+ scope: INSTANCE_TYPE,
+ title: 'My title',
+ variables: {},
+ ...props,
+ },
+ stubs: {
+ RunnerCount: {
+ props: ['scope', 'variables', 'skip'],
+ render() {
+ return this.$scopedSlots.default({
+ count,
+ });
+ },
+ },
+ },
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ case | count | value
+ ${'number'} | ${99} | ${'99'}
+ ${'long number'} | ${1000} | ${'1,000'}
+ ${'empty number'} | ${null} | ${'-'}
+ `('formats $case', ({ count, value }) => {
+ createComponent({ count });
+
+ expect(findGlSingleStat().props('value')).toBe(value);
+ });
+
+ it('Passes runner count props', () => {
+ const props = {
+ scope: GROUP_TYPE,
+ variables: { paused: true },
+ skip: true,
+ };
+
+ createComponent({ props });
+
+ expect(findRunnerCount().props()).toEqual(props);
+ });
+});
diff --git a/spec/frontend/runner/components/stat/runner_stats_spec.js b/spec/frontend/runner/components/stat/runner_stats_spec.js
index f1ba6403dfb..7f1f22be94f 100644
--- a/spec/frontend/runner/components/stat/runner_stats_spec.js
+++ b/spec/frontend/runner/components/stat/runner_stats_spec.js
@@ -1,15 +1,13 @@
import { shallowMount, mount } from '@vue/test-utils';
import { s__ } from '~/locale';
import RunnerStats from '~/runner/components/stat/runner_stats.vue';
-import RunnerCount from '~/runner/components/stat/runner_count.vue';
-import RunnerStatusStat from '~/runner/components/stat/runner_status_stat.vue';
+import RunnerSingleStat from '~/runner/components/stat/runner_single_stat.vue';
import { INSTANCE_TYPE, STATUS_ONLINE, STATUS_OFFLINE, STATUS_STALE } from '~/runner/constants';
describe('RunnerStats', () => {
let wrapper;
- const findRunnerCountAt = (i) => wrapper.findAllComponents(RunnerCount).at(i);
- const findRunnerStatusStatAt = (i) => wrapper.findAllComponents(RunnerStatusStat).at(i);
+ const findSingleStats = () => wrapper.findAllComponents(RunnerSingleStat).wrappers;
const createComponent = ({ props = {}, mountFn = shallowMount, ...options } = {}) => {
wrapper = mountFn(RunnerStats, {
@@ -53,31 +51,12 @@ describe('RunnerStats', () => {
expect(text).toMatch(`${s__('Runners|Stale runners')} 1`);
});
- it('Displays counts for filtered searches', () => {
- createComponent({ props: { variables: { paused: true } } });
+ it('Displays all counts for filtered searches', () => {
+ const mockVariables = { paused: true };
+ createComponent({ props: { variables: mockVariables } });
- expect(findRunnerCountAt(0).props('variables').paused).toBe(true);
- expect(findRunnerCountAt(1).props('variables').paused).toBe(true);
- expect(findRunnerCountAt(2).props('variables').paused).toBe(true);
- });
-
- it('Skips overlapping statuses', () => {
- createComponent({ props: { variables: { status: STATUS_ONLINE } } });
-
- expect(findRunnerCountAt(0).props('skip')).toBe(false);
- expect(findRunnerCountAt(1).props('skip')).toBe(true);
- expect(findRunnerCountAt(2).props('skip')).toBe(true);
- });
-
- it.each`
- i | status
- ${0} | ${STATUS_ONLINE}
- ${1} | ${STATUS_OFFLINE}
- ${2} | ${STATUS_STALE}
- `('Displays status $status at index $i', ({ i, status }) => {
- createComponent({ mountFn: mount });
-
- expect(findRunnerCountAt(i).props('variables').status).toBe(status);
- expect(findRunnerStatusStatAt(i).props('status')).toBe(status);
+ findSingleStats().forEach((stat) => {
+ expect(stat.props('variables')).toMatchObject(mockVariables);
+ });
});
});
diff --git a/spec/frontend/runner/components/stat/runner_status_stat_spec.js b/spec/frontend/runner/components/stat/runner_status_stat_spec.js
deleted file mode 100644
index 3218272eac7..00000000000
--- a/spec/frontend/runner/components/stat/runner_status_stat_spec.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import { GlSingleStat } from '@gitlab/ui/dist/charts';
-import { shallowMount, mount } from '@vue/test-utils';
-import RunnerStatusStat from '~/runner/components/stat/runner_status_stat.vue';
-import { STATUS_ONLINE, STATUS_OFFLINE, STATUS_STALE } from '~/runner/constants';
-
-describe('RunnerStatusStat', () => {
- let wrapper;
-
- const findSingleStat = () => wrapper.findComponent(GlSingleStat);
-
- const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
- wrapper = mountFn(RunnerStatusStat, {
- propsData: {
- status: STATUS_ONLINE,
- value: 99,
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe.each`
- status | variant | title | badge
- ${STATUS_ONLINE} | ${'success'} | ${'Online runners'} | ${'online'}
- ${STATUS_OFFLINE} | ${'muted'} | ${'Offline runners'} | ${'offline'}
- ${STATUS_STALE} | ${'warning'} | ${'Stale runners'} | ${'stale'}
- `('Renders a stat for status "$status"', ({ status, variant, title, badge }) => {
- beforeEach(() => {
- createComponent({ props: { status } }, mount);
- });
-
- it('Renders text', () => {
- expect(wrapper.text()).toMatch(new RegExp(`${title} 99\\s+${badge}`));
- });
-
- it(`Uses variant ${variant}`, () => {
- expect(findSingleStat().props('variant')).toBe(variant);
- });
- });
-
- it('Formats stat number', () => {
- createComponent({ props: { value: 1000 } }, mount);
-
- expect(wrapper.text()).toMatch('Online runners 1,000');
- });
-
- it('Shows a null result', () => {
- createComponent({ props: { value: null } }, mount);
-
- expect(wrapper.text()).toMatch('Online runners -');
- });
-
- it('Shows an undefined result', () => {
- createComponent({ props: { value: undefined } }, mount);
-
- expect(wrapper.text()).toMatch('Online runners -');
- });
-
- it('Shows result for an unknown status', () => {
- createComponent({ props: { status: 'UNKNOWN' } }, mount);
-
- expect(wrapper.text()).toMatch('Runners 99');
- });
-});
diff --git a/spec/frontend/runner/graphql/local_state_spec.js b/spec/frontend/runner/graphql/local_state_spec.js
index 5c4302e4aa2..ae874fef00d 100644
--- a/spec/frontend/runner/graphql/local_state_spec.js
+++ b/spec/frontend/runner/graphql/local_state_spec.js
@@ -1,6 +1,8 @@
+import { gql } from '@apollo/client/core';
import createApolloClient from '~/lib/graphql';
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';
describe('~/runner/graphql/list/local_state', () => {
let localState;
@@ -18,6 +20,21 @@ describe('~/runner/graphql/list/local_state', () => {
apolloClient = createApolloClient({}, { cacheConfig, typeDefs });
};
+ const addMockRunnerToCache = (id) => {
+ // mock some runners in the cache to prevent dangling references
+ apolloClient.writeFragment({
+ id: `${RUNNER_TYPENAME}:${id}`,
+ fragment: gql`
+ fragment DummyRunner on CiRunner {
+ __typename
+ }
+ `,
+ data: {
+ __typename: RUNNER_TYPENAME,
+ },
+ });
+ };
+
const queryCheckedRunnerIds = () => {
const { checkedRunnerIds } = apolloClient.readQuery({
query: getCheckedRunnerIdsQuery,
@@ -34,10 +51,25 @@ describe('~/runner/graphql/list/local_state', () => {
apolloClient = null;
});
- describe('default', () => {
- it('has empty checked list', () => {
+ describe('queryCheckedRunnerIds', () => {
+ it('has empty checked list by default', () => {
expect(queryCheckedRunnerIds()).toEqual([]);
});
+
+ it('returns checked runners that have a reference in the cache', () => {
+ addMockRunnerToCache('a');
+ localState.localMutations.setRunnerChecked({ runner: { id: 'a' }, 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 });
+
+ expect(queryCheckedRunnerIds()).toEqual(['a']);
+ });
});
describe.each`
@@ -48,6 +80,7 @@ describe('~/runner/graphql/list/local_state', () => {
`('setRunnerChecked', ({ inputs, expected }) => {
beforeEach(() => {
inputs.forEach(([id, isChecked]) => {
+ addMockRunnerToCache(id);
localState.localMutations.setRunnerChecked({ runner: { id }, isChecked });
});
});
@@ -56,9 +89,34 @@ describe('~/runner/graphql/list/local_state', () => {
});
});
+ describe.each`
+ inputs | expected
+ ${[[['a', 'b'], true]]} | ${['a', 'b']}
+ ${[[['a', 'b'], false]]} | ${[]}
+ ${[[['a', 'b'], true], [['c', 'd'], true]]} | ${['a', 'b', 'c', 'd']}
+ ${[[['a', 'b'], true], [['a', 'b'], false]]} | ${[]}
+ ${[[['a', 'b'], true], [['b'], false]]} | ${['a']}
+ `('setRunnersChecked', ({ inputs, expected }) => {
+ beforeEach(() => {
+ inputs.forEach(([ids, isChecked]) => {
+ ids.forEach(addMockRunnerToCache);
+
+ localState.localMutations.setRunnersChecked({
+ runners: ids.map((id) => ({ id })),
+ isChecked,
+ });
+ });
+ });
+
+ it(`for inputs="${inputs}" has a ids="[${expected}]"`, () => {
+ expect(queryCheckedRunnerIds()).toEqual(expected);
+ });
+ });
+
describe('clearChecked', () => {
it('clears all checked items', () => {
['a', 'b', 'c'].forEach((id) => {
+ addMockRunnerToCache(id);
localState.localMutations.setRunnerChecked({ runner: { id }, isChecked: true });
});
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 2065874c288..cee1d436942 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
@@ -92,10 +92,10 @@ describe('GroupRunnerShowApp', () => {
});
it('shows basic runner details', () => {
- const expected = `Description Instance runner
+ const expected = `Description My Runner
Last contact Never contacted
Version 1.0.0
- IP Address 127.0.0.1
+ IP Address None
Executor None
Architecture None
Platform darwin
@@ -178,13 +178,10 @@ describe('GroupRunnerShowApp', () => {
});
describe('When loading', () => {
- beforeEach(() => {
+ it('does not show runner details', () => {
mockRunnerQueryResult();
createComponent();
- });
-
- it('does not show runner details', () => {
expect(findRunnerDetails().exists()).toBe(false);
});
});
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 9c42b0d6865..57d64202219 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -13,13 +13,13 @@ import { createAlert } from '~/flash';
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 RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.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';
-import RunnerCount from '~/runner/components/stat/runner_count.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';
@@ -32,15 +32,14 @@ import {
GROUP_TYPE,
PARAM_KEY_PAUSED,
PARAM_KEY_STATUS,
- PARAM_KEY_TAG,
STATUS_ONLINE,
STATUS_OFFLINE,
STATUS_STALE,
RUNNER_PAGE_SIZE,
I18N_EDIT,
} from '~/runner/constants';
-import groupRunnersQuery from '~/runner/graphql/list/group_runners.query.graphql';
-import groupRunnersCountQuery from '~/runner/graphql/list/group_runners_count.query.graphql';
+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 GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue';
import { captureException } from '~/runner/sentry_utils';
import {
@@ -49,6 +48,7 @@ import {
groupRunnersCountData,
onlineContactTimeoutSecs,
staleTimeoutSecs,
+ emptyPageInfo,
emptyStateSvgPath,
emptyStateFilteredSvgPath,
} from '../mock_data';
@@ -82,7 +82,7 @@ describe('GroupRunnersApp', () => {
const findRunnerListEmptyState = () => wrapper.findComponent(RunnerListEmptyState);
const findRunnerRow = (id) => extendedWrapper(wrapper.findByTestId(`runner-row-${id}`));
const findRunnerPagination = () => extendedWrapper(wrapper.findComponent(RunnerPagination));
- const findRunnerPaginationNext = () => findRunnerPagination().findByLabelText('Go to next page');
+ const findRunnerPaginationNext = () => findRunnerPagination().findByText(s__('Pagination|Next'));
const findRunnerFilteredSearchBar = () => wrapper.findComponent(RunnerFilteredSearchBar);
const createComponent = ({ props = {}, mountFn = shallowMountExtended, ...options } = {}) => {
@@ -111,7 +111,7 @@ describe('GroupRunnersApp', () => {
return waitForPromises();
};
- beforeEach(async () => {
+ beforeEach(() => {
mockGroupRunnersHandler.mockResolvedValue(groupRunnersData);
mockGroupRunnersCountHandler.mockResolvedValue(groupRunnersCountData);
});
@@ -197,6 +197,7 @@ describe('GroupRunnersApp', () => {
type: PARAM_KEY_STATUS,
options: expect.any(Array),
}),
+ upgradeStatusTokenConfig,
]);
});
@@ -254,12 +255,7 @@ describe('GroupRunnersApp', () => {
beforeEach(async () => {
setWindowLocation(`?status[]=${STATUS_ONLINE}&runner_type[]=${INSTANCE_TYPE}`);
- await createComponent({
- stubs: {
- RunnerStats,
- RunnerCount,
- },
- });
+ await createComponent({ mountFn: mountExtended });
});
it('sets the filters in the search bar', () => {
@@ -267,7 +263,7 @@ describe('GroupRunnersApp', () => {
runnerType: INSTANCE_TYPE,
filters: [{ type: 'status', value: { data: STATUS_ONLINE, operator: '=' } }],
sort: 'CREATED_DESC',
- pagination: { page: 1 },
+ pagination: {},
});
});
@@ -292,19 +288,11 @@ describe('GroupRunnersApp', () => {
describe('when a filter is selected by the user', () => {
beforeEach(async () => {
- createComponent({
- stubs: {
- RunnerStats,
- RunnerCount,
- },
- });
+ await createComponent({ mountFn: mountExtended });
findRunnerFilteredSearchBar().vm.$emit('input', {
runnerType: null,
- filters: [
- { type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } },
- { type: PARAM_KEY_TAG, value: { data: 'tag1', operator: '=' } },
- ],
+ filters: [{ type: PARAM_KEY_STATUS, value: { data: STATUS_ONLINE, operator: '=' } }],
sort: CREATED_ASC,
});
@@ -314,7 +302,7 @@ describe('GroupRunnersApp', () => {
it('updates the browser url', () => {
expect(updateHistory).toHaveBeenLastCalledWith({
title: expect.any(String),
- url: expect.stringContaining('?status[]=ONLINE&tag[]=tag1&sort=CREATED_ASC'),
+ url: expect.stringContaining('?status[]=ONLINE&sort=CREATED_ASC'),
});
});
@@ -322,7 +310,6 @@ describe('GroupRunnersApp', () => {
expect(mockGroupRunnersHandler).toHaveBeenLastCalledWith({
groupFullPath: mockGroupFullPath,
status: STATUS_ONLINE,
- tagList: ['tag1'],
sort: CREATED_ASC,
first: RUNNER_PAGE_SIZE,
});
@@ -331,7 +318,6 @@ describe('GroupRunnersApp', () => {
it('fetches count results for requested status', () => {
expect(mockGroupRunnersCountHandler).toHaveBeenCalledWith({
groupFullPath: mockGroupFullPath,
- tagList: ['tag1'],
status: STATUS_ONLINE,
});
});
@@ -340,6 +326,7 @@ describe('GroupRunnersApp', () => {
it('when runners have not loaded, shows a loading state', () => {
createComponent();
expect(findRunnerList().props('loading')).toBe(true);
+ expect(findRunnerPagination().attributes('disabled')).toBe('true');
});
describe('when no runners are found', () => {
@@ -348,13 +335,20 @@ describe('GroupRunnersApp', () => {
data: {
group: {
id: '1',
- runners: { nodes: [] },
+ runners: {
+ edges: [],
+ pageInfo: emptyPageInfo,
+ },
},
},
});
await createComponent();
});
+ it('shows no errors', () => {
+ expect(createAlert).not.toHaveBeenCalled();
+ });
+
it('shows an empty state', async () => {
expect(findRunnerListEmptyState().exists()).toBe(true);
});
@@ -379,12 +373,18 @@ describe('GroupRunnersApp', () => {
});
describe('Pagination', () => {
+ const { pageInfo } = groupRunnersDataPaginated.data.group.runners;
+
beforeEach(async () => {
mockGroupRunnersHandler.mockResolvedValue(groupRunnersDataPaginated);
await createComponent({ mountFn: mountExtended });
});
+ it('passes the page info', () => {
+ expect(findRunnerPagination().props('pageInfo')).toEqual(pageInfo);
+ });
+
it('navigates to the next page', async () => {
await findRunnerPaginationNext().trigger('click');
@@ -392,7 +392,7 @@ describe('GroupRunnersApp', () => {
groupFullPath: mockGroupFullPath,
sort: CREATED_DESC,
first: RUNNER_PAGE_SIZE,
- after: groupRunnersDataPaginated.data.group.runners.pageInfo.endCursor,
+ after: pageInfo.endCursor,
});
});
});
diff --git a/spec/frontend/runner/mock_data.js b/spec/frontend/runner/mock_data.js
index e5472ace817..555ec40184f 100644
--- a/spec/frontend/runner/mock_data.js
+++ b/spec/frontend/runner/mock_data.js
@@ -19,6 +19,14 @@ import groupRunnersCountData from 'test_fixtures/graphql/runner/list/group_runne
import { RUNNER_PAGE_SIZE } from '~/runner/constants';
+const emptyPageInfo = {
+ __typename: 'PageInfo',
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: '',
+ endCursor: '',
+};
+
// Other mock data
// Mock searches and their corresponding urls
@@ -26,7 +34,7 @@ export const mockSearchExamples = [
{
name: 'a default query',
urlQuery: '',
- search: { runnerType: null, filters: [], pagination: { page: 1 }, sort: 'CREATED_DESC' },
+ search: { runnerType: null, filters: [], pagination: {}, sort: 'CREATED_DESC' },
graphqlVariables: { sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
isDefault: true,
},
@@ -36,7 +44,7 @@ export const mockSearchExamples = [
search: {
runnerType: null,
filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -52,7 +60,7 @@ export const mockSearchExamples = [
value: { data: 'something' },
},
],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { search: 'something', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -72,7 +80,7 @@ export const mockSearchExamples = [
value: { data: 'else' },
},
],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { search: 'something else', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -83,7 +91,7 @@ export const mockSearchExamples = [
search: {
runnerType: 'INSTANCE_TYPE',
filters: [],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { type: 'INSTANCE_TYPE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -97,7 +105,7 @@ export const mockSearchExamples = [
{ type: 'status', value: { data: 'ACTIVE', operator: '=' } },
{ type: 'status', value: { data: 'PAUSED', operator: '=' } },
],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { status: 'ACTIVE', sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -108,7 +116,7 @@ export const mockSearchExamples = [
search: {
runnerType: 'INSTANCE_TYPE',
filters: [{ type: 'status', value: { data: 'ACTIVE', operator: '=' } }],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_ASC',
},
graphqlVariables: {
@@ -124,7 +132,7 @@ export const mockSearchExamples = [
search: {
runnerType: null,
filters: [{ type: 'tag', value: { data: 'tag-1', operator: '=' } }],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: {
@@ -142,7 +150,7 @@ export const mockSearchExamples = [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'tag', value: { data: 'tag-2', operator: '=' } },
],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: {
@@ -153,22 +161,22 @@ export const mockSearchExamples = [
},
{
name: 'the next page',
- urlQuery: '?page=2&after=AFTER_CURSOR',
+ urlQuery: '?after=AFTER_CURSOR',
search: {
runnerType: null,
filters: [],
- pagination: { page: 2, after: 'AFTER_CURSOR' },
+ pagination: { after: 'AFTER_CURSOR' },
sort: 'CREATED_DESC',
},
graphqlVariables: { sort: 'CREATED_DESC', after: 'AFTER_CURSOR', first: RUNNER_PAGE_SIZE },
},
{
name: 'the previous page',
- urlQuery: '?page=2&before=BEFORE_CURSOR',
+ urlQuery: '?before=BEFORE_CURSOR',
search: {
runnerType: null,
filters: [],
- pagination: { page: 2, before: 'BEFORE_CURSOR' },
+ pagination: { before: 'BEFORE_CURSOR' },
sort: 'CREATED_DESC',
},
graphqlVariables: { sort: 'CREATED_DESC', before: 'BEFORE_CURSOR', last: RUNNER_PAGE_SIZE },
@@ -176,7 +184,7 @@ export const mockSearchExamples = [
{
name: 'the next page filtered by a status, an instance type, tags and a non default sort',
urlQuery:
- '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&tag[]=tag-1&tag[]=tag-2&sort=CREATED_ASC&page=2&after=AFTER_CURSOR',
+ '?status[]=ACTIVE&runner_type[]=INSTANCE_TYPE&tag[]=tag-1&tag[]=tag-2&sort=CREATED_ASC&after=AFTER_CURSOR',
search: {
runnerType: 'INSTANCE_TYPE',
filters: [
@@ -184,7 +192,7 @@ export const mockSearchExamples = [
{ type: 'tag', value: { data: 'tag-1', operator: '=' } },
{ type: 'tag', value: { data: 'tag-2', operator: '=' } },
],
- pagination: { page: 2, after: 'AFTER_CURSOR' },
+ pagination: { after: 'AFTER_CURSOR' },
sort: 'CREATED_ASC',
},
graphqlVariables: {
@@ -202,7 +210,7 @@ export const mockSearchExamples = [
search: {
runnerType: null,
filters: [{ type: 'paused', value: { data: 'true', operator: '=' } }],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { paused: true, sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -213,7 +221,7 @@ export const mockSearchExamples = [
search: {
runnerType: null,
filters: [{ type: 'paused', value: { data: 'false', operator: '=' } }],
- pagination: { page: 1 },
+ pagination: {},
sort: 'CREATED_DESC',
},
graphqlVariables: { paused: false, sort: 'CREATED_DESC', first: RUNNER_PAGE_SIZE },
@@ -233,6 +241,7 @@ export {
groupRunnersData,
groupRunnersDataPaginated,
groupRunnersCountData,
+ emptyPageInfo,
runnerData,
runnerWithGroupData,
runnerProjectsData,
diff --git a/spec/frontend/runner/runner_search_utils_spec.js b/spec/frontend/runner/runner_search_utils_spec.js
index 6f954143ab1..e1f90482b34 100644
--- a/spec/frontend/runner/runner_search_utils_spec.js
+++ b/spec/frontend/runner/runner_search_utils_spec.js
@@ -24,11 +24,14 @@ describe('search_params.js', () => {
});
it.each`
- query | updatedQuery
- ${'status[]=ACTIVE'} | ${'paused[]=false'}
- ${'status[]=ACTIVE&a=b'} | ${'a=b&paused[]=false'}
- ${'status[]=ACTIVE'} | ${'paused[]=false'}
- ${'status[]=PAUSED'} | ${'paused[]=true'}
+ query | updatedQuery
+ ${'status[]=ACTIVE'} | ${'paused[]=false'}
+ ${'status[]=ACTIVE&a=b'} | ${'a=b&paused[]=false'}
+ ${'status[]=ACTIVE'} | ${'paused[]=false'}
+ ${'status[]=PAUSED'} | ${'paused[]=true'}
+ ${'page=2&after=AFTER'} | ${'after=AFTER'}
+ ${'page=2&before=BEFORE'} | ${'before=BEFORE'}
+ ${'status[]=PAUSED&page=2&after=AFTER'} | ${'after=AFTER&paused[]=true'}
`('updates "$query" to "$updatedQuery"', ({ query, updatedQuery }) => {
const mockUrl = 'http://test.host/admin/runners?';
@@ -49,24 +52,6 @@ describe('search_params.js', () => {
{ type: 'filtered-search-term', value: { data: 'text' } },
]);
});
-
- it('When a page cannot be parsed as a number, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=NONSENSE&after=AFTER_CURSOR').pagination).toEqual({
- page: 1,
- });
- });
-
- it('When a page is less than 1, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=0&after=AFTER_CURSOR').pagination).toEqual({
- page: 1,
- });
- });
-
- it('When a page with no cursor is given, it defaults to `1`', () => {
- expect(fromUrlQueryToSearch('?page=2').pagination).toEqual({
- page: 1,
- });
- });
});
describe('fromSearchToUrl', () => {
@@ -143,8 +128,11 @@ describe('search_params.js', () => {
});
});
- it('given a missing pagination, evaluates as not filtered', () => {
- expect(isSearchFiltered({ pagination: null })).toBe(false);
- });
+ it.each([null, undefined, {}])(
+ 'given a missing pagination, evaluates as not filtered',
+ (mockPagination) => {
+ expect(isSearchFiltered({ pagination: mockPagination })).toBe(false);
+ },
+ );
});
});
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index 184c16fda6e..b6451af57d7 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -402,7 +402,7 @@ describe('TrainingProviderList component', () => {
it('has disabled state for radio', () => {
findPrimaryProviderRadios().wrappers.forEach((radio) => {
- expect(radio.attributes('disabled')).toBeTruthy();
+ expect(radio.attributes('disabled')).toBe('true');
});
});
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index a4474ead956..c2aff456abb 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -70,7 +70,7 @@ describe('Assignee component', () => {
wrapper.find('[data-testid="assign-yourself"]').trigger('click');
await nextTick();
- expect(wrapper.emitted('assign-self')).toBeTruthy();
+ expect(wrapper.emitted('assign-self')).toHaveLength(1);
});
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
index 5fd364afbe4..88015ed42a3 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -148,6 +148,7 @@ describe('Sidebar assignees widget', () => {
expect(findAssignees().props('users')).toEqual([
{
+ __typename: 'UserCore',
id: 'gid://gitlab/User/2',
avatarUrl:
'https://www.gravatar.com/avatar/a95e5b71488f4b9d69ce5ff58bfd28d6?s=80\u0026d=identicon',
diff --git a/spec/frontend/sidebar/components/attention_requested_toggle_spec.js b/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
deleted file mode 100644
index 58fa878a189..00000000000
--- a/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
-
-let wrapper;
-
-function factory(propsData = {}) {
- wrapper = mount(AttentionRequestedToggle, { propsData });
-}
-
-const findToggle = () => wrapper.findComponent(GlButton);
-
-describe('Attention require toggle', () => {
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders button', () => {
- factory({
- type: 'reviewer',
- user: { attention_requested: false, can_update_merge_request: true },
- });
-
- expect(findToggle().exists()).toBe(true);
- });
-
- it.each`
- attentionRequested | icon
- ${true} | ${'attention-solid'}
- ${false} | ${'attention'}
- `(
- 'renders $icon icon when attention_requested is $attentionRequested',
- ({ attentionRequested, icon }) => {
- factory({
- type: 'reviewer',
- user: { attention_requested: attentionRequested, can_update_merge_request: true },
- });
-
- expect(findToggle().props('icon')).toBe(icon);
- },
- );
-
- it.each`
- attentionRequested | selected
- ${true} | ${true}
- ${false} | ${false}
- `(
- 'renders button with as selected when $selected when attention_requested is $attentionRequested',
- ({ attentionRequested, selected }) => {
- factory({
- type: 'reviewer',
- user: { attention_requested: attentionRequested, can_update_merge_request: true },
- });
-
- expect(findToggle().props('selected')).toBe(selected);
- },
- );
-
- it('emits toggle-attention-requested on click', async () => {
- factory({
- type: 'reviewer',
- user: { attention_requested: true, can_update_merge_request: true },
- });
-
- await findToggle().trigger('click');
-
- expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual([
- {
- user: { attention_requested: true, can_update_merge_request: true },
- callback: expect.anything(),
- direction: 'remove',
- },
- ]);
- });
-
- it('does not emit toggle-attention-requested on click if can_update_merge_request is false', async () => {
- factory({
- type: 'reviewer',
- user: { attention_requested: true, can_update_merge_request: false },
- });
-
- await findToggle().trigger('click');
-
- expect(wrapper.emitted('toggle-attention-requested')).toBe(undefined);
- });
-
- it('sets loading on click', async () => {
- factory({
- type: 'reviewer',
- user: { attention_requested: true, can_update_merge_request: true },
- });
-
- await findToggle().trigger('click');
-
- expect(findToggle().props('loading')).toBe(true);
- });
-
- it.each`
- type | attentionRequested | tooltip | canUpdateMergeRequest
- ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequest} | ${true}
- ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.addAttentionRequest} | ${true}
- ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.addAttentionRequest} | ${true}
- ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.attentionRequestedNoPermission} | ${false}
- ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.noAttentionRequestedNoPermission} | ${false}
- ${'assignee'} | ${true} | ${AttentionRequestedToggle.i18n.attentionRequestedNoPermission} | ${false}
- ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.noAttentionRequestedNoPermission} | ${false}
- `(
- 'sets tooltip as $tooltip when attention_requested is $attentionRequested, type is $type and, can_update_merge_request is $canUpdateMergeRequest',
- ({ type, attentionRequested, tooltip, canUpdateMergeRequest }) => {
- factory({
- type,
- user: {
- attention_requested: attentionRequested,
- can_update_merge_request: canUpdateMergeRequest,
- },
- });
-
- expect(findToggle().attributes('aria-label')).toBe(tooltip);
- },
- );
-});
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..7775ed6aa37 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_form_spec.js
@@ -71,7 +71,12 @@ describe('Sidebar Confidentiality Form', () => {
it('creates a flash if mutation contains errors', async () => {
createComponent({
mutate: jest.fn().mockResolvedValue({
- data: { issuableSetConfidential: { errors: ['Houston, we have a problem!'] } },
+ data: {
+ issuableSetConfidential: {
+ issuable: { confidential: false },
+ errors: ['Houston, we have a problem!'],
+ },
+ },
}),
});
findConfidentialToggle().vm.$emit('click', new MouseEvent('click'));
@@ -82,6 +87,24 @@ describe('Sidebar Confidentiality Form', () => {
});
});
+ it('emits `closeForm` event with confidentiality value when mutation is successful', async () => {
+ createComponent({
+ mutate: jest.fn().mockResolvedValue({
+ data: {
+ issuableSetConfidential: {
+ issuable: { confidential: true },
+ errors: [],
+ },
+ },
+ }),
+ });
+
+ findConfidentialToggle().vm.$emit('click', new MouseEvent('click'));
+ await waitForPromises();
+
+ expect(wrapper.emitted('closeForm')).toEqual([[{ confidential: true }]]);
+ });
+
describe('when issue is not confidential', () => {
beforeEach(() => {
createComponent();
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 1de71e52264..18ee423d12e 100644
--- a/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
+++ b/spec/frontend/sidebar/components/confidential/sidebar_confidentiality_widget_spec.js
@@ -132,6 +132,7 @@ describe('Sidebar Confidentiality Widget', () => {
it('closes the form and dispatches an event when `closeForm` is emitted', async () => {
createComponent();
const el = wrapper.vm.$el;
+ const closeFormPayload = { confidential: true };
jest.spyOn(el, 'dispatchEvent');
await waitForPromises();
@@ -140,12 +141,12 @@ describe('Sidebar Confidentiality Widget', () => {
expect(findConfidentialityForm().isVisible()).toBe(true);
- findConfidentialityForm().vm.$emit('closeForm');
+ findConfidentialityForm().vm.$emit('closeForm', closeFormPayload);
await nextTick();
expect(findConfidentialityForm().isVisible()).toBe(false);
expect(el.dispatchEvent).toHaveBeenCalled();
- expect(wrapper.emitted('closeForm')).toHaveLength(1);
+ expect(wrapper.emitted('closeForm')).toEqual([[closeFormPayload]]);
});
it('emits `expandSidebar` event when it is emitted from child component', async () => {
diff --git a/spec/frontend/sidebar/components/incidents/escalation_status_spec.js b/spec/frontend/sidebar/components/incidents/escalation_status_spec.js
index 8d8c10d10f1..83764cb6739 100644
--- a/spec/frontend/sidebar/components/incidents/escalation_status_spec.js
+++ b/spec/frontend/sidebar/components/incidents/escalation_status_spec.js
@@ -1,4 +1,5 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import EscalationStatus from '~/sidebar/components/incidents/escalation_status.vue';
@@ -61,6 +62,8 @@ describe('EscalationStatus', () => {
createComponent();
// Open dropdown
await toggleDropdown();
+ jest.runOnlyPendingTimers();
+ await nextTick();
expect(findDropdownMenu().classes('show')).toBe(true);
@@ -74,6 +77,8 @@ describe('EscalationStatus', () => {
createComponent({ preventDropdownClose: true });
// Open dropdown
await toggleDropdown();
+ jest.runOnlyPendingTimers();
+ await nextTick();
expect(findDropdownMenu().classes('show')).toBe(true);
diff --git a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
index 338ecf944f3..859e63b3df6 100644
--- a/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
+++ b/spec/frontend/sidebar/components/participants/sidebar_participants_widget_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { stripTypenames } from 'helpers/graphql_helpers';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Participants from '~/sidebar/components/participants/participants.vue';
@@ -67,11 +66,9 @@ describe('Sidebar Participants Widget', () => {
});
it('passes participants to child component', () => {
- const participantsWithoutTypename = stripTypenames(
+ expect(findParticipants().props('participants')).toEqual(
epicParticipantsResponse().data.workspace.issuable.participants.nodes,
);
-
- expect(findParticipants().props('participants')).toEqual(participantsWithoutTypename);
});
});
diff --git a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
index 8999f120a0f..2c24df2436a 100644
--- a/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
+++ b/spec/frontend/sidebar/components/reviewers/uncollapsed_reviewer_list_spec.js
@@ -1,9 +1,22 @@
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
import ReviewerAvatarLink from '~/sidebar/components/reviewers/reviewer_avatar_link.vue';
import UncollapsedReviewerList from '~/sidebar/components/reviewers/uncollapsed_reviewer_list.vue';
-import userDataMock from '../../user_data_mock';
+
+const userDataMock = () => ({
+ id: 1,
+ name: 'Root',
+ state: 'active',
+ username: 'root',
+ webUrl: `${TEST_HOST}/root`,
+ avatarUrl: `${TEST_HOST}/avatar/root.png`,
+ mergeRequestInteraction: {
+ canMerge: true,
+ canUpdate: true,
+ reviewed: true,
+ approved: false,
+ },
+});
describe('UncollapsedReviewerList component', () => {
let wrapper;
@@ -70,7 +83,10 @@ describe('UncollapsedReviewerList component', () => {
id: 2,
name: 'nonrooty-nonrootersen',
username: 'hello-world',
- approved: true,
+ mergeRequestInteraction: {
+ ...user.mergeRequestInteraction,
+ approved: true,
+ },
};
beforeEach(() => {
@@ -119,18 +135,4 @@ describe('UncollapsedReviewerList component', () => {
expect(wrapper.find('[data-testid="re-request-success"]').exists()).toBe(true);
});
});
-
- it('hides re-request review button when attentionRequired feature flag is enabled', () => {
- createComponent({ users: [userDataMock()] }, { mrAttentionRequests: true });
-
- expect(wrapper.findAll('[data-testid="re-request-button"]').length).toBe(0);
- });
-
- it('emits toggle-attention-requested', () => {
- createComponent({ users: [userDataMock()] }, { mrAttentionRequests: true });
-
- wrapper.find(AttentionRequestedToggle).vm.$emit('toggle-attention-requested', 'data');
-
- expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual(['data']);
- });
});
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index 229757ff40c..9c6e23e928c 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -343,6 +343,14 @@ export const issuableQueryResponse = {
__typename: 'Issue',
id: 'gid://gitlab/Issue/1',
iid: '1',
+ author: {
+ id: '1',
+ avatarUrl: '/avatar',
+ name: 'root',
+ username: 'root',
+ webUrl: 'root',
+ status: null,
+ },
assignees: {
nodes: [
{
@@ -450,7 +458,7 @@ export const subscriptionResponse = {
},
};
-const mockUser1 = {
+export const mockUser1 = {
__typename: 'UserCore',
id: 'gid://gitlab/User/1',
avatarUrl:
@@ -459,6 +467,7 @@ const mockUser1 = {
username: 'root',
webUrl: '/root',
status: null,
+ canMerge: false,
};
export const mockUser2 = {
@@ -469,6 +478,7 @@ export const mockUser2 = {
username: 'rookie',
webUrl: 'rookie',
status: null,
+ canMerge: false,
};
export const searchResponse = {
diff --git a/spec/frontend/sidebar/reviewer_title_spec.js b/spec/frontend/sidebar/reviewer_title_spec.js
index 3c250be5d5e..6b4eed5ad0f 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()).toBeFalsy();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('renders spinner when loading', () => {
@@ -57,7 +57,7 @@ describe('ReviewerTitle component', () => {
editable: false,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBeTruthy();
+ expect(wrapper.find(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 351dfc9a6ed..88bacc9b7f7 100644
--- a/spec/frontend/sidebar/reviewers_spec.js
+++ b/spec/frontend/sidebar/reviewers_spec.js
@@ -1,9 +1,23 @@
import { GlIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
-import UsersMockHelper from 'helpers/user_mock_data_helper';
+import { TEST_HOST } from 'helpers/test_constants';
import Reviewer from '~/sidebar/components/reviewers/reviewers.vue';
-import UsersMock from './mock_data';
+
+const usersMock = (id = 1) => ({
+ id,
+ name: 'Root',
+ state: 'active',
+ username: 'root',
+ webUrl: `${TEST_HOST}/root`,
+ avatarUrl: `${TEST_HOST}/avatar/root.png`,
+ mergeRequestInteraction: {
+ canMerge: true,
+ canUpdate: true,
+ reviewed: true,
+ approved: false,
+ },
+});
describe('Reviewer component', () => {
const getDefaultProps = () => ({
@@ -42,23 +56,23 @@ describe('Reviewer component', () => {
it('displays one reviewer icon when collapsed', () => {
createWrapper({
...getDefaultProps(),
- users: [UsersMock.user],
+ users: [usersMock()],
});
const collapsedChildren = findCollapsedChildren();
const reviewer = collapsedChildren.at(0);
expect(collapsedChildren.length).toBe(1);
- expect(reviewer.find('.avatar').attributes('src')).toBe(UsersMock.user.avatar);
- expect(reviewer.find('.avatar').attributes('alt')).toBe(`${UsersMock.user.name}'s avatar`);
+ expect(reviewer.find('.avatar').attributes('src')).toContain('avatar/root.png');
+ expect(reviewer.find('.avatar').attributes('alt')).toBe(`Root's avatar`);
- expect(trimText(reviewer.find('.author').text())).toBe(UsersMock.user.name);
+ expect(trimText(reviewer.find('.author').text())).toBe('Root');
});
});
describe('Two or more reviewers/users', () => {
it('displays two reviewer icons when collapsed', () => {
- const users = UsersMockHelper.createNumberRandomUsers(2);
+ const users = [usersMock(), usersMock(2)];
createWrapper({
...getDefaultProps(),
users,
@@ -70,21 +84,21 @@ describe('Reviewer component', () => {
const first = collapsedChildren.at(0);
- expect(first.find('.avatar').attributes('src')).toBe(users[0].avatar_url);
+ expect(first.find('.avatar').attributes('src')).toBe(users[0].avatarUrl);
expect(first.find('.avatar').attributes('alt')).toBe(`${users[0].name}'s avatar`);
expect(trimText(first.find('.author').text())).toBe(users[0].name);
const second = collapsedChildren.at(1);
- expect(second.find('.avatar').attributes('src')).toBe(users[1].avatar_url);
+ expect(second.find('.avatar').attributes('src')).toBe(users[1].avatarUrl);
expect(second.find('.avatar').attributes('alt')).toBe(`${users[1].name}'s avatar`);
expect(trimText(second.find('.author').text())).toBe(users[1].name);
});
it('displays one reviewer icon and counter when collapsed', () => {
- const users = UsersMockHelper.createNumberRandomUsers(3);
+ const users = [usersMock(), usersMock(2), usersMock(3)];
createWrapper({
...getDefaultProps(),
users,
@@ -96,7 +110,7 @@ describe('Reviewer component', () => {
const first = collapsedChildren.at(0);
- expect(first.find('.avatar').attributes('src')).toBe(users[0].avatar_url);
+ expect(first.find('.avatar').attributes('src')).toBe(users[0].avatarUrl);
expect(first.find('.avatar').attributes('alt')).toBe(`${users[0].name}'s avatar`);
expect(trimText(first.find('.author').text())).toBe(users[0].name);
@@ -107,7 +121,7 @@ describe('Reviewer component', () => {
});
it('Shows two reviewers', () => {
- const users = UsersMockHelper.createNumberRandomUsers(2);
+ const users = [usersMock(), usersMock(2)];
createWrapper({
...getDefaultProps(),
users,
@@ -118,10 +132,10 @@ describe('Reviewer component', () => {
});
it('shows sorted reviewer where "can merge" users are sorted first', () => {
- const users = UsersMockHelper.createNumberRandomUsers(3);
- users[0].can_merge = false;
- users[1].can_merge = false;
- users[2].can_merge = true;
+ const users = [usersMock(), usersMock(2), usersMock(3)];
+ users[0].mergeRequestInteraction.canMerge = false;
+ users[1].mergeRequestInteraction.canMerge = false;
+ users[2].mergeRequestInteraction.canMerge = true;
createWrapper({
...getDefaultProps(),
@@ -129,14 +143,14 @@ describe('Reviewer component', () => {
editable: true,
});
- expect(wrapper.vm.sortedReviewers[0].can_merge).toBe(true);
+ expect(wrapper.vm.sortedReviewers[0].mergeRequestInteraction.canMerge).toBe(true);
});
it('passes the sorted reviewers to the uncollapsed-reviewer-list', () => {
- const users = UsersMockHelper.createNumberRandomUsers(3);
- users[0].can_merge = false;
- users[1].can_merge = false;
- users[2].can_merge = true;
+ const users = [usersMock(), usersMock(2), usersMock(3)];
+ users[0].mergeRequestInteraction.canMerge = false;
+ users[1].mergeRequestInteraction.canMerge = false;
+ users[2].mergeRequestInteraction.canMerge = true;
createWrapper({
...getDefaultProps(),
@@ -149,10 +163,10 @@ describe('Reviewer component', () => {
});
it('passes the sorted reviewers to the collapsed-reviewer-list', () => {
- const users = UsersMockHelper.createNumberRandomUsers(3);
- users[0].can_merge = false;
- users[1].can_merge = false;
- users[2].can_merge = true;
+ const users = [usersMock(), usersMock(2), usersMock(3)];
+ users[0].mergeRequestInteraction.canMerge = false;
+ users[1].mergeRequestInteraction.canMerge = false;
+ users[2].mergeRequestInteraction.canMerge = true;
createWrapper({
...getDefaultProps(),
diff --git a/spec/frontend/sidebar/sidebar_mediator_spec.js b/spec/frontend/sidebar/sidebar_mediator_spec.js
index 82fb10ab1d2..e32694abcce 100644
--- a/spec/frontend/sidebar/sidebar_mediator_spec.js
+++ b/spec/frontend/sidebar/sidebar_mediator_spec.js
@@ -1,12 +1,9 @@
import MockAdapter from 'axios-mock-adapter';
-import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import * as urlUtility from '~/lib/utils/url_utility';
import SidebarService, { gqClient } from '~/sidebar/services/sidebar_service';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
-import toast from '~/vue_shared/plugins/global_toast';
-import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import Mock from './mock_data';
jest.mock('~/flash');
@@ -122,93 +119,4 @@ describe('Sidebar mediator', () => {
urlSpy.mockRestore();
});
});
-
- describe('toggleAttentionRequested', () => {
- let requestAttentionMock;
- let removeAttentionRequestMock;
-
- beforeEach(() => {
- requestAttentionMock = jest.spyOn(mediator.service, 'requestAttention').mockResolvedValue();
- removeAttentionRequestMock = jest
- .spyOn(mediator.service, 'removeAttentionRequest')
- .mockResolvedValue();
- });
-
- it.each`
- attentionIsCurrentlyRequested | serviceMethod
- ${true} | ${'remove'}
- ${false} | ${'add'}
- `(
- "calls the $serviceMethod service method when the user's attention request is set to $attentionIsCurrentlyRequested",
- async ({ serviceMethod }) => {
- const methods = {
- add: requestAttentionMock,
- remove: removeAttentionRequestMock,
- };
- mediator.store.reviewers = [{ id: 1, attention_requested: false, username: 'root' }];
-
- await mediator.toggleAttentionRequested('reviewer', {
- user: { id: 1, username: 'root' },
- callback: jest.fn(),
- direction: serviceMethod,
- });
-
- expect(methods[serviceMethod]).toHaveBeenCalledWith(1);
- expect(refreshUserMergeRequestCounts).toHaveBeenCalled();
- },
- );
-
- it.each`
- type | method
- ${'reviewer'} | ${'findReviewer'}
- `('finds $type', ({ type, method }) => {
- const methodSpy = jest.spyOn(mediator.store, method);
-
- mediator.toggleAttentionRequested(type, { user: { id: 1 }, callback: jest.fn() });
-
- expect(methodSpy).toHaveBeenCalledWith({ id: 1 });
- });
-
- it.each`
- attentionRequested | toastMessage
- ${true} | ${'Removed attention request from @root'}
- ${false} | ${'Requested attention from @root'}
- `(
- 'it creates toast $toastMessage when attention_requested is $attentionRequested',
- async ({ attentionRequested, toastMessage }) => {
- mediator.store.reviewers = [
- { id: 1, attention_requested: attentionRequested, username: 'root' },
- ];
-
- await mediator.toggleAttentionRequested('reviewer', {
- user: { id: 1, username: 'root' },
- callback: jest.fn(),
- });
-
- expect(toast).toHaveBeenCalledWith(toastMessage);
- },
- );
-
- describe('errors', () => {
- beforeEach(() => {
- jest
- .spyOn(mediator.service, 'removeAttentionRequest')
- .mockRejectedValueOnce(new Error('Something went wrong'));
- });
-
- it('shows an error message', async () => {
- await mediator.toggleAttentionRequested('reviewer', {
- user: { id: 1, username: 'root' },
- callback: jest.fn(),
- direction: 'remove',
- });
-
- expect(createFlash).toHaveBeenCalledWith(
- expect.objectContaining({
- message: 'Updating the attention request for root failed.',
- }),
- );
- });
- });
- });
});
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
index 6fc358a6a15..76e84fa183c 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_blob_edit_spec.js.snap
@@ -16,6 +16,7 @@ exports[`Snippet Blob Edit component with loaded blob matches snapshot 1`] = `
<source-editor-stub
debouncevalue="250"
editoroptions="[object Object]"
+ extensions="[object Object]"
fileglobalid="blob_local_7"
filename="foo/bar/test.md"
value="Lorem ipsum dolar sit amet,
diff --git a/spec/frontend/surveys/merge_request_performance/app_spec.js b/spec/frontend/surveys/merge_request_performance/app_spec.js
index 6e8cc660b1d..cd549155914 100644
--- a/spec/frontend/surveys/merge_request_performance/app_spec.js
+++ b/spec/frontend/surveys/merge_request_performance/app_spec.js
@@ -25,6 +25,9 @@ describe('MergeRequestExperienceSurveyApp', () => {
shouldShowCallout,
});
wrapper = shallowMountExtended(MergeRequestExperienceSurveyApp, {
+ propsData: {
+ accountAge: 0,
+ },
stubs: {
UserCalloutDismisser: dismisserComponent,
GlSprintf,
@@ -82,11 +85,17 @@ describe('MergeRequestExperienceSurveyApp', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'survey:mr_experience', {
value: 5,
label: 'overall',
+ extra: {
+ accountAge: 0,
+ },
});
rate.vm.$emit('rate', 4);
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'survey:mr_experience', {
value: 4,
label: 'performance',
+ extra: {
+ accountAge: 0,
+ },
});
});
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index b4626625f31..3fb226e5ed3 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -1,8 +1,7 @@
/* Setup for unit test environment */
+// eslint-disable-next-line no-restricted-syntax
+import { setImmediate } from 'timers';
import 'helpers/shared_test_setup';
-import { initializeTestTimeout } from 'helpers/timeout';
-
-initializeTestTimeout(process.env.CI ? 6000 : 500);
afterEach(() =>
// give Promises a bit more time so they fail the right test
diff --git a/spec/frontend/user_popovers_spec.js b/spec/frontend/user_popovers_spec.js
index b171c8fc9ed..0530569c9df 100644
--- a/spec/frontend/user_popovers_spec.js
+++ b/spec/frontend/user_popovers_spec.js
@@ -10,6 +10,8 @@ jest.mock('~/api/user_api', () => ({
}));
describe('User Popovers', () => {
+ let origGon;
+
const fixtureTemplate = 'merge_requests/merge_request_with_mentions.html';
const selector = '.js-user-link[data-user], .js-user-link[data-user-id]';
@@ -39,7 +41,7 @@ describe('User Popovers', () => {
el.dispatchEvent(event);
};
- beforeEach(() => {
+ const setupTestSubject = () => {
loadHTMLFixture(fixtureTemplate);
const usersCacheSpy = () => Promise.resolve(dummyUser);
@@ -56,147 +58,179 @@ describe('User Popovers', () => {
document.body.appendChild(mountingRoot);
popoverInstance.$mount(mountingRoot);
});
+ };
+
+ beforeEach(() => {
+ origGon = window.gon;
+ window.gon = {};
});
afterEach(() => {
- resetHTMLFixture();
+ window.gon = origGon;
});
- describe('shows a placeholder popover on hover', () => {
- let linksWithUsers;
+ describe('when signed out', () => {
beforeEach(() => {
- linksWithUsers = findFixtureLinks();
+ setupTestSubject();
+ });
+
+ it('does not show a placeholder popover on hover', () => {
+ const linksWithUsers = findFixtureLinks();
linksWithUsers.forEach((el) => {
triggerEvent('mouseover', el);
});
+
+ expect(findPopovers().length).toBe(0);
});
+ });
- it('for initial links', () => {
- expect(findPopovers().length).toBe(linksWithUsers.length);
+ describe('when signed in', () => {
+ beforeEach(() => {
+ window.gon.current_user_id = 7;
+
+ setupTestSubject();
});
- it('for elements added after initial load', async () => {
- const addedLinks = [createUserLink(), createUserLink()];
- addedLinks.forEach((link) => {
- document.body.appendChild(link);
- });
+ afterEach(() => {
+ resetHTMLFixture();
+ });
- jest.runOnlyPendingTimers();
+ describe('shows a placeholder popover on hover', () => {
+ let linksWithUsers;
+ beforeEach(() => {
+ linksWithUsers = findFixtureLinks();
+ linksWithUsers.forEach((el) => {
+ triggerEvent('mouseover', el);
+ });
+ });
- addedLinks.forEach((link) => {
- triggerEvent('mouseover', link);
+ it('for initial links', () => {
+ expect(findPopovers().length).toBe(linksWithUsers.length);
});
- expect(findPopovers().length).toBe(linksWithUsers.length + addedLinks.length);
+ it('for elements added after initial load', async () => {
+ const addedLinks = [createUserLink(), createUserLink()];
+ addedLinks.forEach((link) => {
+ document.body.appendChild(link);
+ });
+
+ jest.runOnlyPendingTimers();
+
+ addedLinks.forEach((link) => {
+ triggerEvent('mouseover', link);
+ });
+
+ expect(findPopovers().length).toBe(linksWithUsers.length + addedLinks.length);
+ });
});
- });
- it('does not initialize the popovers for group references', async () => {
- const [groupLink] = Array.from(document.querySelectorAll('.js-user-link[data-group]'));
+ it('does not initialize the popovers for group references', async () => {
+ const [groupLink] = Array.from(document.querySelectorAll('.js-user-link[data-group]'));
- triggerEvent('mouseover', groupLink);
- jest.runOnlyPendingTimers();
+ triggerEvent('mouseover', groupLink);
+ jest.runOnlyPendingTimers();
- expect(findPopovers().length).toBe(0);
- });
+ expect(findPopovers().length).toBe(0);
+ });
- it('does not initialize the popovers for @all references', async () => {
- const [projectLink] = Array.from(document.querySelectorAll('.js-user-link[data-project]'));
+ it('does not initialize the popovers for @all references', async () => {
+ const [projectLink] = Array.from(document.querySelectorAll('.js-user-link[data-project]'));
- triggerEvent('mouseover', projectLink);
- jest.runOnlyPendingTimers();
+ triggerEvent('mouseover', projectLink);
+ jest.runOnlyPendingTimers();
- expect(findPopovers().length).toBe(0);
- });
+ expect(findPopovers().length).toBe(0);
+ });
- it('does not initialize the user popovers twice for the same element', async () => {
- const [firstUserLink] = findFixtureLinks();
- triggerEvent('mouseover', firstUserLink);
- jest.runOnlyPendingTimers();
- triggerEvent('mouseleave', firstUserLink);
- jest.runOnlyPendingTimers();
- triggerEvent('mouseover', firstUserLink);
- jest.runOnlyPendingTimers();
+ it('does not initialize the user popovers twice for the same element', async () => {
+ const [firstUserLink] = findFixtureLinks();
+ triggerEvent('mouseover', firstUserLink);
+ jest.runOnlyPendingTimers();
+ triggerEvent('mouseleave', firstUserLink);
+ jest.runOnlyPendingTimers();
+ triggerEvent('mouseover', firstUserLink);
+ jest.runOnlyPendingTimers();
- expect(findPopovers().length).toBe(1);
- });
+ expect(findPopovers().length).toBe(1);
+ });
- describe('when user link emits mouseenter event with empty user cache', () => {
- let userLink;
+ describe('when user link emits mouseenter event with empty user cache', () => {
+ let userLink;
- beforeEach(() => {
- UsersCache.retrieveById.mockReset();
+ beforeEach(() => {
+ UsersCache.retrieveById.mockReset();
- [userLink] = findFixtureLinks();
+ [userLink] = findFixtureLinks();
- triggerEvent('mouseover', userLink);
- });
+ triggerEvent('mouseover', userLink);
+ });
- it('populates popover with preloaded user data', () => {
- const { name, userId, username } = userLink.dataset;
+ it('populates popover with preloaded user data', () => {
+ const { name, userId, username } = userLink.dataset;
- expect(userLink.user).toEqual(
- expect.objectContaining({
- name,
- userId,
- username,
- }),
- );
+ expect(userLink.user).toEqual(
+ expect.objectContaining({
+ name,
+ userId,
+ username,
+ }),
+ );
+ });
});
- });
- describe('when user link emits mouseenter event', () => {
- let userLink;
+ describe('when user link emits mouseenter event', () => {
+ let userLink;
- beforeEach(() => {
- [userLink] = findFixtureLinks();
+ beforeEach(() => {
+ [userLink] = findFixtureLinks();
- triggerEvent('mouseover', userLink);
- });
+ triggerEvent('mouseover', userLink);
+ });
- it('removes title attribute from user links', () => {
- expect(userLink.getAttribute('title')).toBeFalsy();
- expect(userLink.dataset.originalTitle).toBeFalsy();
- });
+ it('removes title attribute from user links', () => {
+ expect(userLink.getAttribute('title')).toBeFalsy();
+ expect(userLink.dataset.originalTitle).toBeFalsy();
+ });
- it('fetches user info and status from the user cache', () => {
- const { userId } = userLink.dataset;
+ it('fetches user info and status from the user cache', () => {
+ const { userId } = userLink.dataset;
- expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId);
- expect(UsersCache.retrieveStatusById).toHaveBeenCalledWith(userId);
- });
+ expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId);
+ expect(UsersCache.retrieveStatusById).toHaveBeenCalledWith(userId);
+ });
- it('removes aria-describedby attribute from the user link on mouseleave', () => {
- userLink.setAttribute('aria-describedby', 'popover');
- triggerEvent('mouseleave', userLink);
+ it('removes aria-describedby attribute from the user link on mouseleave', () => {
+ userLink.setAttribute('aria-describedby', 'popover');
+ triggerEvent('mouseleave', userLink);
- expect(userLink.getAttribute('aria-describedby')).toBe(null);
- });
+ expect(userLink.getAttribute('aria-describedby')).toBe(null);
+ });
- it('updates toggle follow button and `UsersCache` when toggle follow button is clicked', async () => {
- const [firstPopover] = findPopovers();
- const withinFirstPopover = within(firstPopover);
- const findFollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Follow' });
- const findUnfollowButton = () =>
- withinFirstPopover.queryByRole('button', { name: 'Unfollow' });
+ it('updates toggle follow button and `UsersCache` when toggle follow button is clicked', async () => {
+ const [firstPopover] = findPopovers();
+ const withinFirstPopover = within(firstPopover);
+ const findFollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Follow' });
+ const findUnfollowButton = () =>
+ withinFirstPopover.queryByRole('button', { name: 'Unfollow' });
- jest.runOnlyPendingTimers();
+ jest.runOnlyPendingTimers();
- const { userId } = document.querySelector(selector).dataset;
+ const { userId } = document.querySelector(selector).dataset;
- triggerEvent('click', findFollowButton());
+ triggerEvent('click', findFollowButton());
- await waitForPromises();
+ await waitForPromises();
- expect(findUnfollowButton()).not.toBe(null);
- expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: true });
+ expect(findUnfollowButton()).not.toBe(null);
+ expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: true });
- triggerEvent('click', findUnfollowButton());
+ triggerEvent('click', findUnfollowButton());
- await waitForPromises();
+ await waitForPromises();
- expect(findFollowButton()).not.toBe(null);
- expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: false });
+ expect(findFollowButton()).not.toBe(null);
+ expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: false });
+ });
});
});
});
diff --git a/spec/frontend/vue_merge_request_widget/components/action_buttons.js b/spec/frontend/vue_merge_request_widget/components/action_buttons.js
new file mode 100644
index 00000000000..6d714aeaf18
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/action_buttons.js
@@ -0,0 +1,47 @@
+import { GlButton, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Actions from '~/vue_merge_request_widget/components/action_buttons.vue';
+
+let wrapper;
+
+function factory(propsData = {}) {
+ wrapper = shallowMount(Actions, {
+ propsData: { ...propsData, widget: 'test' },
+ });
+}
+
+describe('MR widget extension actions', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('tertiaryButtons', () => {
+ it('renders buttons', () => {
+ factory({
+ tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
+ });
+
+ expect(wrapper.findAllComponents(GlButton)).toHaveLength(1);
+ });
+
+ it('calls action click handler', async () => {
+ const onClick = jest.fn();
+
+ factory({
+ tertiaryButtons: [{ text: 'hello world', onClick }],
+ });
+
+ await wrapper.findComponent(GlButton).vm.$emit('click');
+
+ expect(onClick).toHaveBeenCalled();
+ });
+
+ it('renders tertiary actions in dropdown', () => {
+ factory({
+ tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
+ });
+
+ expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(1);
+ });
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/added_commit_message_spec.js b/spec/frontend/vue_merge_request_widget/components/added_commit_message_spec.js
new file mode 100644
index 00000000000..cb53dc1fb61
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/added_commit_message_spec.js
@@ -0,0 +1,26 @@
+import { shallowMount } from '@vue/test-utils';
+import AddedCommentMessage from '~/vue_merge_request_widget/components/added_commit_message.vue';
+
+let wrapper;
+
+function factory(propsData) {
+ wrapper = shallowMount(AddedCommentMessage, {
+ propsData: {
+ isFastForwardEnabled: false,
+ targetBranch: 'main',
+ ...propsData,
+ },
+ });
+}
+
+describe('Widget added commit message', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays changes where not merged when state is closed', () => {
+ factory({ state: 'closed' });
+
+ expect(wrapper.element.outerHTML).toContain('The changes were not merged');
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
index 05cd1bb5b3d..05cd1bb5b3d 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js
index 65cafc647e0..65cafc647e0 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_optional_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_optional_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js
index c2606346292..c2606346292 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/approvals_summary_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_summary_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/approvals/humanized_text_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/humanized_text_spec.js
index d6776c00b29..d6776c00b29 100644
--- a/spec/frontend/vue_mr_widget/components/approvals/humanized_text_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/humanized_text_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js
index e2386bc7f2b..e2386bc7f2b 100644
--- a/spec/frontend/vue_mr_widget/components/artifacts_list_app_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_app_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js
index 712abfe228a..712abfe228a 100644
--- a/spec/frontend/vue_mr_widget/components/artifacts_list_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/artifacts_list_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/extensions/child_content_spec.js b/spec/frontend/vue_merge_request_widget/components/extensions/child_content_spec.js
index 198a4c2823a..198a4c2823a 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/child_content_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/extensions/child_content_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/extensions/index_spec.js b/spec/frontend/vue_merge_request_widget/components/extensions/index_spec.js
index dc25596655a..dc25596655a 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/extensions/index_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/extensions/status_icon_spec.js b/spec/frontend/vue_merge_request_widget/components/extensions/status_icon_spec.js
index f3aa5bb774f..f3aa5bb774f 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/status_icon_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/extensions/status_icon_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js b/spec/frontend/vue_merge_request_widget/components/extensions/utils_spec.js
index 5799799ad5e..5799799ad5e 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/extensions/utils_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js
index 01fbcb2154f..01fbcb2154f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_collapsible_extension_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_collapsible_extension_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_alert_message_spec.js
index 5d923d0383f..5d923d0383f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_alert_message_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_alert_message_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_spec.js
index 8a42e2e2ce7..8a42e2e2ce7 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_author_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js
index 8fd93809e01..8fd93809e01 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_author_time_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_author_time_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_container_spec.js
index 4e3e918f7fb..4e3e918f7fb 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_container_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js
index 631aef412a6..631aef412a6 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_expandable_section_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js
index ebd10f31fa7..ebd10f31fa7 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_icon_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js
new file mode 100644
index 00000000000..193a16bae8d
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_memory_usage_spec.js
@@ -0,0 +1,227 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import Vue, { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
+import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
+import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
+
+const url = '/root/acets-review-apps/environments/15/deployments/1/metrics';
+const monitoringUrl = '/root/acets-review-apps/environments/15/metrics';
+
+const metricsMockData = {
+ success: true,
+ metrics: {
+ memory_before: [
+ {
+ metric: {},
+ value: [1495785220.607, '9572875.906976745'],
+ },
+ ],
+ memory_after: [
+ {
+ metric: {},
+ value: [1495787020.607, '4485853.130206379'],
+ },
+ ],
+ memory_values: [
+ {
+ metric: {},
+ values: [[1493716685, '4.30859375']],
+ },
+ ],
+ },
+ last_update: '2017-05-02T12:34:49.628Z',
+ deployment_time: 1493718485,
+};
+
+const createComponent = () => {
+ const Component = Vue.extend(MemoryUsage);
+
+ return new Component({
+ el: document.createElement('div'),
+ propsData: {
+ metricsUrl: url,
+ metricsMonitoringUrl: monitoringUrl,
+ memoryMetrics: [],
+ deploymentTime: 0,
+ hasMetrics: false,
+ loadFailed: false,
+ loadingMetrics: true,
+ backOffRequestCounter: 0,
+ },
+ });
+};
+
+const messages = {
+ loadingMetrics: 'Loading deployment statistics',
+ hasMetrics: 'Memory usage is unchanged at 0MB',
+ loadFailed: 'Failed to load deployment statistics',
+ metricsUnavailable: 'Deployment statistics are not available currently',
+};
+
+describe('MemoryUsage', () => {
+ let vm;
+ let el;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(`${url}.json`).reply(200);
+
+ vm = createComponent();
+ el = vm.$el;
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('data', () => {
+ it('should have default data', () => {
+ const data = MemoryUsage.data();
+
+ expect(Array.isArray(data.memoryMetrics)).toBe(true);
+ expect(data.memoryMetrics.length).toBe(0);
+
+ expect(typeof data.deploymentTime).toBe('number');
+ expect(data.deploymentTime).toBe(0);
+
+ expect(typeof data.hasMetrics).toBe('boolean');
+ expect(data.hasMetrics).toBe(false);
+
+ expect(typeof data.loadFailed).toBe('boolean');
+ expect(data.loadFailed).toBe(false);
+
+ expect(typeof data.loadingMetrics).toBe('boolean');
+ expect(data.loadingMetrics).toBe(true);
+
+ expect(typeof data.backOffRequestCounter).toBe('number');
+ expect(data.backOffRequestCounter).toBe(0);
+ });
+ });
+
+ describe('computed', () => {
+ describe('memoryChangeMessage', () => {
+ it('should contain "increased" if memoryFrom value is less than memoryTo value', () => {
+ vm.memoryFrom = 4.28;
+ vm.memoryTo = 9.13;
+
+ expect(vm.memoryChangeMessage.indexOf('increased')).not.toEqual('-1');
+ });
+
+ it('should contain "decreased" if memoryFrom value is less than memoryTo value', () => {
+ vm.memoryFrom = 9.13;
+ vm.memoryTo = 4.28;
+
+ expect(vm.memoryChangeMessage.indexOf('decreased')).not.toEqual('-1');
+ });
+
+ it('should contain "unchanged" if memoryFrom value equal to memoryTo value', () => {
+ vm.memoryFrom = 1;
+ vm.memoryTo = 1;
+
+ expect(vm.memoryChangeMessage.indexOf('unchanged')).not.toEqual('-1');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ const { metrics, deployment_time } = metricsMockData;
+
+ describe('getMegabytes', () => {
+ it('should return Megabytes from provided Bytes value', () => {
+ const memoryInBytes = '9572875.906976745';
+
+ expect(vm.getMegabytes(memoryInBytes)).toEqual('9.13');
+ });
+ });
+
+ describe('computeGraphData', () => {
+ it('should populate sparkline graph', () => {
+ // ignore BoostrapVue warnings
+ jest.spyOn(console, 'warn').mockImplementation();
+
+ vm.computeGraphData(metrics, deployment_time);
+ const { hasMetrics, memoryMetrics, deploymentTime, memoryFrom, memoryTo } = vm;
+
+ expect(hasMetrics).toBe(true);
+ expect(memoryMetrics.length).toBeGreaterThan(0);
+ expect(deploymentTime).toEqual(deployment_time);
+ expect(memoryFrom).toEqual('9.13');
+ expect(memoryTo).toEqual('4.28');
+ });
+ });
+
+ describe('loadMetrics', () => {
+ it('should load metrics data using MRWidgetService', async () => {
+ jest.spyOn(MRWidgetService, 'fetchMetrics').mockResolvedValue({
+ data: metricsMockData,
+ });
+ jest.spyOn(vm, 'computeGraphData').mockImplementation(() => {});
+
+ vm.loadMetrics();
+
+ await waitForPromises();
+
+ expect(MRWidgetService.fetchMetrics).toHaveBeenCalledWith(url);
+ expect(vm.computeGraphData).toHaveBeenCalledWith(metrics, deployment_time);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('should render template elements correctly', () => {
+ expect(el.classList.contains('mr-memory-usage')).toBe(true);
+ expect(el.querySelector('.js-usage-info')).toBeDefined();
+ });
+
+ it('should show loading metrics message while metrics are being loaded', async () => {
+ vm.loadingMetrics = true;
+ vm.hasMetrics = false;
+ vm.loadFailed = false;
+
+ await nextTick();
+
+ expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined();
+ expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined();
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadingMetrics);
+ });
+
+ it('should show deployment memory usage when metrics are loaded', async () => {
+ // ignore BoostrapVue warnings
+ jest.spyOn(console, 'warn').mockImplementation();
+
+ vm.loadingMetrics = false;
+ vm.hasMetrics = true;
+ vm.loadFailed = false;
+ vm.memoryMetrics = metricsMockData.metrics.memory_values[0].values;
+
+ await nextTick();
+
+ expect(el.querySelector('.memory-graph-container')).toBeDefined();
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics);
+ });
+
+ it('should show failure message when metrics loading failed', async () => {
+ vm.loadingMetrics = false;
+ vm.hasMetrics = false;
+ vm.loadFailed = true;
+
+ await nextTick();
+
+ expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined();
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed);
+ });
+
+ it('should show metrics unavailable message when metrics loading failed', async () => {
+ vm.loadingMetrics = false;
+ vm.hasMetrics = false;
+ vm.loadFailed = false;
+
+ await nextTick();
+
+ expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined();
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable);
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
index efe2bf75c3f..efe2bf75c3f 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_container_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
index 6347e3c3be3..6347e3c3be3 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_pipeline_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_rebase_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_rebase_spec.js
new file mode 100644
index 00000000000..534c0baf35d
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_rebase_spec.js
@@ -0,0 +1,245 @@
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import WidgetRebase from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import toast from '~/vue_shared/plugins/global_toast';
+
+jest.mock('~/vue_shared/plugins/global_toast');
+
+let wrapper;
+
+function createWrapper(propsData, mergeRequestWidgetGraphql) {
+ wrapper = mount(WidgetRebase, {
+ propsData,
+ data() {
+ return {
+ state: {
+ rebaseInProgress: propsData.mr.rebaseInProgress,
+ targetBranch: propsData.mr.targetBranch,
+ userPermissions: {
+ pushToSourceBranch: propsData.mr.canPushToSourceBranch,
+ },
+ },
+ };
+ },
+ provide: { glFeatures: { mergeRequestWidgetGraphql } },
+ mocks: {
+ $apollo: {
+ queries: {
+ state: { loading: false },
+ },
+ },
+ },
+ });
+}
+
+describe('Merge request widget rebase component', () => {
+ const findRebaseMessage = () => wrapper.find('[data-testid="rebase-message"]');
+ const findRebaseMessageText = () => findRebaseMessage().text();
+ const findStandardRebaseButton = () => wrapper.find('[data-testid="standard-rebase-button"]');
+ const findRebaseWithoutCiButton = () => wrapper.find('[data-testid="rebase-without-ci-button"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`widget graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'disabled'}`, () => {
+ describe('while rebasing', () => {
+ it('should show progress message', () => {
+ createWrapper(
+ {
+ mr: { rebaseInProgress: true },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ expect(findRebaseMessageText()).toContain('Rebase in progress');
+ });
+ });
+
+ describe('with permissions', () => {
+ const rebaseMock = jest.fn().mockResolvedValue();
+ const pollMock = jest.fn().mockResolvedValue({});
+
+ it('renders the warning message', () => {
+ createWrapper(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {
+ rebase: rebaseMock,
+ poll: pollMock,
+ },
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ const text = findRebaseMessageText();
+
+ expect(text).toContain('Merge blocked');
+ expect(text.replace(/\s\s+/g, ' ')).toContain(
+ 'the source branch must be rebased onto the target branch',
+ );
+ });
+
+ it('renders an error message when rebasing has failed', async () => {
+ createWrapper(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {
+ rebase: rebaseMock,
+ poll: pollMock,
+ },
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ rebasingError: 'Something went wrong!' });
+
+ await nextTick();
+ expect(findRebaseMessageText()).toContain('Something went wrong!');
+ });
+
+ describe('Rebase buttons with', () => {
+ beforeEach(() => {
+ createWrapper(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: true,
+ },
+ service: {
+ rebase: rebaseMock,
+ poll: pollMock,
+ },
+ },
+ mergeRequestWidgetGraphql,
+ );
+ });
+
+ it('renders both buttons', () => {
+ expect(findRebaseWithoutCiButton().exists()).toBe(true);
+ expect(findStandardRebaseButton().exists()).toBe(true);
+ });
+
+ it('starts the rebase when clicking', async () => {
+ findStandardRebaseButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(rebaseMock).toHaveBeenCalledWith({ skipCi: false });
+ });
+
+ it('starts the CI-skipping rebase when clicking on "Rebase without CI"', async () => {
+ findRebaseWithoutCiButton().vm.$emit('click');
+
+ await nextTick();
+
+ expect(rebaseMock).toHaveBeenCalledWith({ skipCi: true });
+ });
+ });
+ });
+
+ describe('without permissions', () => {
+ const exampleTargetBranch = 'fake-branch-to-test-with';
+
+ describe('UI text', () => {
+ beforeEach(() => {
+ createWrapper(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: false,
+ targetBranch: exampleTargetBranch,
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+ });
+
+ it('renders a message explaining user does not have permissions', () => {
+ const text = findRebaseMessageText();
+
+ expect(text).toContain(
+ 'Merge blocked: the source branch must be rebased onto the target branch.',
+ );
+ expect(text).toContain('the source branch must be rebased');
+ });
+
+ it('renders the correct target branch name', () => {
+ const elem = findRebaseMessage();
+
+ expect(elem.text()).toContain(
+ 'Merge blocked: the source branch must be rebased onto the target branch.',
+ );
+ });
+ });
+
+ it('does render the "Rebase without pipeline" button', () => {
+ createWrapper(
+ {
+ mr: {
+ rebaseInProgress: false,
+ canPushToSourceBranch: false,
+ targetBranch: exampleTargetBranch,
+ },
+ service: {},
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ expect(findRebaseWithoutCiButton().exists()).toBe(true);
+ });
+ });
+
+ describe('methods', () => {
+ it('checkRebaseStatus', async () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ createWrapper(
+ {
+ mr: {},
+ service: {
+ rebase() {
+ return Promise.resolve();
+ },
+ poll() {
+ return Promise.resolve({
+ data: {
+ rebase_in_progress: false,
+ should_be_rebased: false,
+ merge_error: null,
+ },
+ });
+ },
+ },
+ },
+ mergeRequestWidgetGraphql,
+ );
+
+ wrapper.vm.rebase();
+
+ // Wait for the rebase request
+ await nextTick();
+ // Wait for the polling request
+ await nextTick();
+ // Wait for the eventHub to be called
+ await nextTick();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetRebaseSuccess');
+ expect(toast).toHaveBeenCalledWith('Rebase completed');
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_related_links_spec.js
index 15522f7ac1d..15522f7ac1d 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_related_links_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_related_links_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/mr_widget_status_icon_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_status_icon_spec.js
new file mode 100644
index 00000000000..11373be578a
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_status_icon_spec.js
@@ -0,0 +1,43 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { shallowMount, mount } from '@vue/test-utils';
+import mrStatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
+
+describe('MR widget status icon component', () => {
+ let wrapper;
+
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+
+ const createWrapper = (props, mountFn = shallowMount) => {
+ wrapper = mountFn(mrStatusIcon, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('while loading', () => {
+ it('renders loading icon', () => {
+ createWrapper({ status: 'loading' });
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+ });
+
+ describe('with status icon', () => {
+ it('renders success status icon', () => {
+ createWrapper({ status: 'success' }, mount);
+
+ expect(wrapper.find('[data-testid="status_success-icon"]').exists()).toBe(true);
+ });
+
+ it('renders failed status icon', () => {
+ createWrapper({ status: 'failed' }, mount);
+
+ expect(wrapper.find('[data-testid="status_failed-icon"]').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js b/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js
index 352bc1a08ea..352bc1a08ea 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_suggest_pipeline_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/mr_widget_suggest_pipeline_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/pipeline_tour_mock_data.js b/spec/frontend/vue_merge_request_widget/components/pipeline_tour_mock_data.js
index eef087d62b8..eef087d62b8 100644
--- a/spec/frontend/vue_mr_widget/components/pipeline_tour_mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/components/pipeline_tour_mock_data.js
diff --git a/spec/frontend/vue_mr_widget/components/review_app_link_spec.js b/spec/frontend/vue_merge_request_widget/components/review_app_link_spec.js
index e393b56034d..e393b56034d 100644
--- a/spec/frontend/vue_mr_widget/components/review_app_link_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/review_app_link_spec.js
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
new file mode 100644
index 00000000000..de25e2a0450
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
@@ -0,0 +1,241 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have correct elements 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <svg
+ aria-hidden="true"
+ class="gl-text-blue-500 gl-mr-3 gl-mt-1 gl-icon s24"
+ data-testid="status_scheduled-icon"
+ role="img"
+ >
+ <use
+ href="#status_scheduled"
+ />
+ </svg>
+
+ <div
+ class="media-body gl-display-flex"
+ >
+
+ <h4
+ class="gl-mr-3"
+ data-testid="statusText"
+ >
+ Set by
+ <a
+ class="author-link inline"
+ >
+ <img
+ class="avatar avatar-inline s16"
+ src="no_avatar.png"
+ />
+
+ <span
+ class="author"
+ >
+
+ </span>
+ </a>
+ to be merged automatically when the pipeline succeeds
+ </h4>
+
+ <div
+ class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto gl-mt-1"
+ >
+ <div>
+ <div
+ class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
+ lazy=""
+ no-caret=""
+ >
+ <!---->
+ <button
+ aria-expanded="false"
+ aria-haspopup="true"
+ class="btn dropdown-toggle btn-default btn-sm gl-p-2! gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ aria-hidden="true"
+ class="dropdown-icon gl-icon s16"
+ data-testid="ellipsis_v-icon"
+ role="img"
+ >
+ <use
+ href="#ellipsis_v"
+ />
+ </svg>
+
+ <span
+ class="gl-new-dropdown-button-text gl-sr-only"
+ >
+
+ </span>
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon dropdown-chevron gl-icon s16"
+ data-testid="chevron-down-icon"
+ role="img"
+ >
+ <use
+ href="#chevron-down"
+ />
+ </svg>
+ </button>
+ <ul
+ class="dropdown-menu dropdown-menu-right"
+ role="menu"
+ tabindex="-1"
+ >
+ <!---->
+ </ul>
+ </div>
+
+ <button
+ class="btn gl-display-none gl-md-display-block gl-float-left btn-confirm btn-sm gl-button btn-confirm-tertiary js-cancel-auto-merge"
+ data-qa-selector="cancel_auto_merge_button"
+ data-testid="cancelAutomaticMergeButton"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+
+ Cancel auto-merge
+
+ </span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have correct elements 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <svg
+ aria-hidden="true"
+ class="gl-text-blue-500 gl-mr-3 gl-mt-1 gl-icon s24"
+ data-testid="status_scheduled-icon"
+ role="img"
+ >
+ <use
+ href="#status_scheduled"
+ />
+ </svg>
+
+ <div
+ class="media-body gl-display-flex"
+ >
+
+ <h4
+ class="gl-mr-3"
+ data-testid="statusText"
+ >
+ Set by
+ <a
+ class="author-link inline"
+ >
+ <img
+ class="avatar avatar-inline s16"
+ src="no_avatar.png"
+ />
+
+ <span
+ class="author"
+ >
+
+ </span>
+ </a>
+ to be merged automatically when the pipeline succeeds
+ </h4>
+
+ <div
+ class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto gl-mt-1"
+ >
+ <div>
+ <div
+ class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
+ lazy=""
+ no-caret=""
+ >
+ <!---->
+ <button
+ aria-expanded="false"
+ aria-haspopup="true"
+ class="btn dropdown-toggle btn-default btn-sm gl-p-2! gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ aria-hidden="true"
+ class="dropdown-icon gl-icon s16"
+ data-testid="ellipsis_v-icon"
+ role="img"
+ >
+ <use
+ href="#ellipsis_v"
+ />
+ </svg>
+
+ <span
+ class="gl-new-dropdown-button-text gl-sr-only"
+ >
+
+ </span>
+
+ <svg
+ aria-hidden="true"
+ class="gl-button-icon dropdown-chevron gl-icon s16"
+ data-testid="chevron-down-icon"
+ role="img"
+ >
+ <use
+ href="#chevron-down"
+ />
+ </svg>
+ </button>
+ <ul
+ class="dropdown-menu dropdown-menu-right"
+ role="menu"
+ tabindex="-1"
+ >
+ <!---->
+ </ul>
+ </div>
+
+ <button
+ class="btn gl-display-none gl-md-display-block gl-float-left btn-confirm btn-sm gl-button btn-confirm-tertiary js-cancel-auto-merge"
+ data-qa-selector="cancel_auto_merge_button"
+ data-testid="cancelAutomaticMergeButton"
+ type="button"
+ >
+ <!---->
+
+ <!---->
+
+ <span
+ class="gl-button-text"
+ >
+
+ Cancel auto-merge
+
+ </span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
new file mode 100644
index 00000000000..7e741bf4660
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
@@ -0,0 +1,24 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PipelineFailed should render error message with a disabled merge button 1`] = `
+<div
+ class="mr-widget-body media"
+>
+ <status-icon-stub
+ show-disabled-button="true"
+ status="warning"
+ />
+
+ <div
+ class="media-body space-children"
+ >
+ <span
+ class="gl-ml-0! gl-text-body! bold"
+ >
+ <gl-sprintf-stub
+ message="Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
+ />
+ </span>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
index f9936f22ea3..f9936f22ea3 100644
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
+++ b/spec/frontend/vue_merge_request_widget/components/states/__snapshots__/new_ready_to_merge_spec.js.snap
diff --git a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js b/spec/frontend/vue_merge_request_widget/components/states/commit_edit_spec.js
index c0add94e6ed..c0add94e6ed 100644
--- a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/commit_edit_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
index 1900b53ac11..1900b53ac11 100644
--- a/spec/frontend/vue_mr_widget/components/states/merge_checks_failed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/merge_checks_failed_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js b/spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
new file mode 100644
index 00000000000..c9aca01083d
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
@@ -0,0 +1,78 @@
+import { shallowMount } from '@vue/test-utils';
+import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
+import { trimText } from 'helpers/text_helper';
+
+describe('MergeFailedPipelineConfirmationDialog', () => {
+ let wrapper;
+
+ const GlModal = {
+ template: `
+ <div>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>
+ `,
+ methods: {
+ hide: jest.fn(),
+ },
+ };
+
+ const createComponent = () => {
+ wrapper = shallowMount(MergeFailedPipelineConfirmationDialog, {
+ propsData: {
+ visible: true,
+ },
+ stubs: {
+ GlModal,
+ },
+ attachTo: document.body,
+ });
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findMergeBtn = () => wrapper.find('[data-testid="merge-unverified-changes"]');
+ const findCancelBtn = () => wrapper.find('[data-testid="merge-cancel-btn"]');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render informational text explaining why merging immediately can be dangerous', () => {
+ expect(trimText(wrapper.text())).toContain(
+ 'The latest pipeline for this merge request did not succeed. The latest changes are unverified. Are you sure you want to attempt to merge?',
+ );
+ });
+
+ it('should emit the mergeWithFailedPipeline event', () => {
+ findMergeBtn().vm.$emit('click');
+
+ expect(wrapper.emitted('mergeWithFailedPipeline')).toHaveLength(1);
+ });
+
+ it('when the cancel button is clicked should emit cancel and call hide', () => {
+ jest.spyOn(findModal().vm, 'hide');
+
+ findCancelBtn().vm.$emit('click');
+
+ expect(wrapper.emitted('cancel')).toHaveLength(1);
+ expect(findModal().vm.hide).toHaveBeenCalled();
+ });
+
+ it('should emit cancel when the hide event is emitted', () => {
+ findModal().vm.$emit('hide');
+
+ expect(wrapper.emitted('cancel')).toHaveLength(1);
+ });
+
+ it('when modal is shown it will focus the cancel button', () => {
+ jest.spyOn(findCancelBtn().element, 'focus');
+
+ findModal().vm.$emit('shown');
+
+ expect(findCancelBtn().element.focus).toHaveBeenCalled();
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_archived_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_archived_spec.js
new file mode 100644
index 00000000000..9332b7e334a
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_archived_spec.js
@@ -0,0 +1,26 @@
+import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import archivedComponent from '~/vue_merge_request_widget/components/states/mr_widget_archived.vue';
+
+describe('MRWidgetArchived', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(archivedComponent);
+ vm = mountComponent(Component);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders a ci status failed icon', () => {
+ expect(vm.$el.querySelector('.ci-status-icon')).not.toBeNull();
+ });
+
+ it('renders information', () => {
+ expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual(
+ 'Merge unavailable: merge requests are read-only on archived projects.',
+ );
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled_spec.js
new file mode 100644
index 00000000000..28182793683
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled_spec.js
@@ -0,0 +1,224 @@
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { trimText } from 'helpers/text_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
+import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
+
+let wrapper;
+let mergeRequestWidgetGraphqlEnabled = false;
+
+function convertPropsToGraphqlState(props) {
+ return {
+ autoMergeStrategy: props.autoMergeStrategy,
+ cancelAutoMergePath: 'http://text.com',
+ mergeUser: {
+ id: props.mergeUserId,
+ ...props.setToAutoMergeBy,
+ },
+ targetBranch: props.targetBranch,
+ targetBranchCommitsPath: props.targetBranchPath,
+ shouldRemoveSourceBranch: props.shouldRemoveSourceBranch,
+ forceRemoveSourceBranch: props.shouldRemoveSourceBranch,
+ userPermissions: {
+ removeSourceBranch: props.canRemoveSourceBranch,
+ },
+ };
+}
+
+function factory(propsData, stateOverride = {}) {
+ let state = {};
+
+ if (mergeRequestWidgetGraphqlEnabled) {
+ state = { ...convertPropsToGraphqlState(propsData), ...stateOverride };
+ }
+
+ wrapper = extendedWrapper(
+ mount(autoMergeEnabledComponent, {
+ propsData: {
+ mr: propsData,
+ service: new MRWidgetService({}),
+ },
+ data() {
+ return { state };
+ },
+ provide: { glFeatures: { mergeRequestWidgetGraphql: mergeRequestWidgetGraphqlEnabled } },
+ mocks: {
+ $apollo: {
+ queries: {
+ state: { loading: false },
+ },
+ },
+ },
+ }),
+ );
+}
+
+const targetBranchPath = '/foo/bar';
+const targetBranch = 'foo';
+const sha = '1EA2EZ34';
+const defaultMrProps = () => ({
+ shouldRemoveSourceBranch: false,
+ canRemoveSourceBranch: true,
+ canCancelAutomaticMerge: true,
+ mergeUserId: 1,
+ currentUserId: 1,
+ setToAutoMergeBy: {},
+ sha,
+ targetBranchPath,
+ targetBranch,
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+});
+
+const getStatusText = () => wrapper.findByTestId('statusText').text();
+
+describe('MRWidgetAutoMergeEnabled', () => {
+ let oldWindowGl;
+
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+
+ oldWindowGl = window.gl;
+ window.gl = {
+ mrWidgetData: {
+ defaultAvatarUrl: 'no_avatar.png',
+ },
+ };
+ });
+
+ afterEach(() => {
+ window.gl = oldWindowGl;
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'disabled'}`, () => {
+ beforeEach(() => {
+ mergeRequestWidgetGraphqlEnabled = mergeRequestWidgetGraphql;
+ });
+
+ describe('computed', () => {
+ describe('cancelButtonText', () => {
+ it('should return "Cancel" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
+
+ expect(wrapper.findByTestId('cancelAutomaticMergeButton').text()).toBe(
+ 'Cancel auto-merge',
+ );
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('cancelAutomaticMerge', () => {
+ it('should set flag and call service then tell main component to update the widget with data', async () => {
+ factory({
+ ...defaultMrProps(),
+ });
+ const mrObj = {
+ is_new_mr_data: true,
+ };
+ jest.spyOn(wrapper.vm.service, 'cancelAutomaticMerge').mockReturnValue(
+ new Promise((resolve) => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
+
+ wrapper.vm.cancelAutomaticMerge();
+
+ await waitForPromises();
+
+ expect(wrapper.vm.isCancellingAutoMerge).toBe(true);
+ if (mergeRequestWidgetGraphql) {
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ } else {
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ }
+ });
+ });
+
+ describe('removeSourceBranch', () => {
+ it('should set flag and call service then request main component to update the widget', async () => {
+ factory({
+ ...defaultMrProps(),
+ });
+ jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(
+ Promise.resolve({
+ data: {
+ status: MWPS_MERGE_STRATEGY,
+ },
+ }),
+ );
+
+ wrapper.vm.removeSourceBranch();
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(wrapper.vm.service.merge).toHaveBeenCalledWith({
+ sha,
+ auto_merge_strategy: MWPS_MERGE_STRATEGY,
+ should_remove_source_branch: true,
+ });
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('should have correct elements', () => {
+ factory({
+ ...defaultMrProps(),
+ });
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should disable cancel auto merge button when the action is in progress', async () => {
+ factory({
+ ...defaultMrProps(),
+ });
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ isCancellingAutoMerge: true,
+ });
+
+ await nextTick();
+
+ expect(wrapper.find('.js-cancel-auto-merge').props('loading')).toBe(true);
+ });
+
+ it('should render the status text as "...to merged automatically" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
+
+ expect(getStatusText()).toContain(
+ 'to be merged automatically when the pipeline succeeds',
+ );
+ });
+
+ it('should render the cancel button as "Cancel" if MWPS is selected', () => {
+ factory({
+ ...defaultMrProps(),
+ autoMergeStrategy: MWPS_MERGE_STRATEGY,
+ });
+
+ const cancelButtonText = trimText(wrapper.find('.js-cancel-auto-merge').text());
+
+ expect(cancelButtonText).toBe('Cancel auto-merge');
+ });
+ });
+ });
+ });
+});
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
new file mode 100644
index 00000000000..9320e733636
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed_spec.js
@@ -0,0 +1,68 @@
+import { GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import AutoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue';
+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 createComponent = (props = {}, mergeRequestWidgetGraphql = false) => {
+ wrapper = mount(AutoMergeFailedComponent, {
+ propsData: { ...props },
+ data() {
+ if (mergeRequestWidgetGraphql) {
+ return { mergeError: props.mr?.mergeError };
+ }
+
+ return {};
+ },
+ provide: {
+ glFeatures: { mergeRequestWidgetGraphql },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ [true, false].forEach((mergeRequestWidgetGraphql) => {
+ describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'dislabed'}`, () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ mr: { mergeError },
+ },
+ mergeRequestWidgetGraphql,
+ );
+ });
+
+ it('renders failed message', () => {
+ expect(wrapper.text()).toContain('This merge request failed to be merged automatically');
+ });
+
+ it('renders merge error provided', () => {
+ expect(wrapper.text()).toContain(mergeError);
+ });
+
+ it('render refresh button', () => {
+ expect(findButton().text()).toBe('Refresh');
+ });
+
+ it('emits event and shows loading icon when button is clicked', async () => {
+ jest.spyOn(eventHub, '$emit');
+ findButton().vm.$emit('click');
+
+ expect(eventHub.$emit.mock.calls[0][0]).toBe('MRWidgetUpdateRequested');
+
+ await nextTick();
+
+ expect(findButton().attributes('disabled')).toBe('disabled');
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_checking_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_checking_spec.js
new file mode 100644
index 00000000000..02de426204b
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_checking_spec.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import checkingComponent from '~/vue_merge_request_widget/components/states/mr_widget_checking.vue';
+
+describe('MRWidgetChecking', () => {
+ let Component;
+ let vm;
+
+ beforeEach(() => {
+ Component = Vue.extend(checkingComponent);
+ vm = mountComponent(Component);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders loading icon', () => {
+ expect(vm.$el.querySelector('.mr-widget-icon span').classList).toContain('gl-spinner');
+ });
+
+ it('renders information about merging', () => {
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual(
+ 'Checking if merge request can be merged…',
+ );
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js
new file mode 100644
index 00000000000..f7d046eb8f9
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_closed_spec.js
@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import closedComponent from '~/vue_merge_request_widget/components/states/mr_widget_closed.vue';
+
+describe('MRWidgetClosed', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(closedComponent);
+ vm = mountComponent(Component, {
+ mr: {
+ metrics: {
+ mergedBy: {},
+ closedBy: {
+ 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',
+ closedAt: 'Jan 24, 2018 1:02pm UTC',
+ readableMergedAt: '',
+ readableClosedAt: 'less than a minute ago',
+ },
+ targetBranchPath: '/twitter/flight/commits/so_long_jquery',
+ targetBranch: 'so_long_jquery',
+ },
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders warning icon', () => {
+ expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull();
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js
index 663fabb761c..663fabb761c 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commit_message_dropdown_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js
new file mode 100644
index 00000000000..774e2bafed3
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js
@@ -0,0 +1,135 @@
+import { mount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
+
+describe('Commits header component', () => {
+ let wrapper;
+
+ const createComponent = (props) => {
+ wrapper = mount(CommitsHeader, {
+ stubs: {
+ GlSprintf,
+ },
+ propsData: {
+ isSquashEnabled: false,
+ targetBranch: 'main',
+ commitsCount: 5,
+ isFastForwardEnabled: false,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findHeaderWrapper = () => wrapper.find('.js-mr-widget-commits-count');
+ const findCommitToggle = () => wrapper.find('.commit-edit-toggle');
+ const findTargetBranchMessage = () => wrapper.find('.label-branch');
+ const findModifyButton = () => wrapper.find('.modify-message-button');
+
+ describe('when fast-forward is enabled', () => {
+ beforeEach(() => {
+ createComponent({
+ isFastForwardEnabled: true,
+ isSquashEnabled: true,
+ });
+ });
+
+ it('has commits count message showing 1 commit', () => {
+ expect(wrapper.text()).toContain('1 commit');
+ });
+
+ it('has button with modify commit message', () => {
+ expect(findModifyButton().text()).toBe('Modify commit message');
+ });
+
+ it('does not have merge commit part of the message', () => {
+ expect(findHeaderWrapper().text()).not.toContain('1 merge commit');
+ });
+ });
+
+ describe('when collapsed', () => {
+ it('toggle has aria-label equal to Expand', () => {
+ createComponent();
+
+ expect(findCommitToggle().attributes('aria-label')).toBe('Expand');
+ });
+
+ it('has a chevron-right icon', async () => {
+ createComponent();
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ expanded: false });
+
+ await nextTick();
+ expect(findCommitToggle().props('icon')).toBe('chevron-right');
+ });
+
+ describe('when squash is disabled', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('has commits count message showing correct amount of commits', () => {
+ expect(wrapper.text()).toContain('5 commits');
+ });
+
+ it('has button with modify merge commit message', () => {
+ expect(findModifyButton().text()).toBe('Modify merge commit');
+ });
+ });
+
+ describe('when squash is enabled', () => {
+ beforeEach(() => {
+ createComponent({ isSquashEnabled: true });
+ });
+
+ it('has commits count message showing one commit when squash is enabled', () => {
+ expect(wrapper.text()).toContain('1 commit');
+ });
+
+ it('has button with modify commit messages text', () => {
+ expect(findModifyButton().text()).toBe('Modify commit messages');
+ });
+ });
+
+ it('has correct target branch displayed', () => {
+ createComponent();
+
+ expect(findTargetBranchMessage().text()).toBe('main');
+ });
+
+ it('does has merge commit part of the message', () => {
+ createComponent();
+
+ expect(findHeaderWrapper().text()).toContain('1 merge commit');
+ });
+ });
+
+ describe('when expanded', () => {
+ beforeEach(() => {
+ createComponent();
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ expanded: true });
+ });
+
+ it('toggle has aria-label equal to collapse', async () => {
+ await nextTick();
+ expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
+ });
+
+ it('has a chevron-down icon', async () => {
+ await nextTick();
+ expect(findCommitToggle().props('icon')).toBe('chevron-down');
+ });
+
+ it('has a collapse text', async () => {
+ await nextTick();
+ expect(findHeaderWrapper().text()).toBe('Collapse');
+ });
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_conflicts_spec.js
new file mode 100644
index 00000000000..7a9fd5b002d
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_conflicts_spec.js
@@ -0,0 +1,252 @@
+import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { TEST_HOST } from 'helpers/test_constants';
+import { removeBreakLine } from 'helpers/text_helper';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import ConflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
+
+describe('MRWidgetConflicts', () => {
+ let wrapper;
+ let mergeRequestWidgetGraphql = null;
+ const path = '/conflicts';
+
+ const findResolveButton = () => wrapper.findByTestId('resolve-conflicts-button');
+ const findMergeLocalButton = () => wrapper.findByTestId('merge-locally-button');
+
+ const mergeConflictsText = 'Merge blocked: merge conflicts must be resolved.';
+ const fastForwardMergeText =
+ 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.';
+ const userCannotMergeText =
+ 'Users who can write to the source or target branches can resolve the conflicts.';
+ const resolveConflictsBtnText = 'Resolve conflicts';
+ const mergeLocallyBtnText = 'Resolve locally';
+
+ async function createComponent(propsData = {}) {
+ wrapper = extendedWrapper(
+ mount(ConflictsComponent, {
+ propsData,
+ provide: {
+ glFeatures: {
+ mergeRequestWidgetGraphql,
+ },
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ userPermissions: { loading: false },
+ stateData: { loading: false },
+ },
+ },
+ },
+ }),
+ );
+
+ if (mergeRequestWidgetGraphql) {
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({
+ userPermissions: {
+ canMerge: propsData.mr.canMerge,
+ pushToSourceBranch: propsData.mr.canPushToSourceBranch,
+ },
+ stateData: {
+ shouldBeRebased: propsData.mr.shouldBeRebased,
+ sourceBranchProtected: propsData.mr.sourceBranchProtected,
+ },
+ });
+ }
+
+ await nextTick();
+ }
+
+ afterEach(() => {
+ mergeRequestWidgetGraphql = null;
+ wrapper.destroy();
+ });
+
+ [false, true].forEach((featureEnabled) => {
+ describe(`with GraphQL feature flag ${featureEnabled ? 'enabled' : 'disabled'}`, () => {
+ beforeEach(() => {
+ mergeRequestWidgetGraphql = featureEnabled;
+ });
+
+ // There are two permissions we need to consider:
+ //
+ // 1. Is the user allowed to merge to the target branch?
+ // 2. Is the user allowed to push to the source branch?
+ //
+ // This yields 4 possible permutations that we need to test, and
+ // we test them below. A user who can push to the source
+ // branch should be allowed to resolve conflicts. This is
+ // consistent with what the backend does.
+ describe('when allowed to merge but not allowed to push to source branch', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mr: {
+ canMerge: true,
+ canPushToSourceBranch: false,
+ conflictResolutionPath: path,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should tell you about conflicts without bothering other people', () => {
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
+ });
+
+ it('should not allow you to resolve the conflicts', () => {
+ expect(wrapper.text()).not.toContain(resolveConflictsBtnText);
+ });
+
+ it('should have merge buttons', () => {
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
+ });
+ });
+
+ describe('when not allowed to merge but allowed to push to source branch', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mr: {
+ canMerge: false,
+ canPushToSourceBranch: true,
+ conflictResolutionPath: path,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should tell you about conflicts', () => {
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).toContain(userCannotMergeText);
+ });
+
+ it('should allow you to resolve the conflicts', () => {
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
+ expect(findResolveButton().attributes('href')).toEqual(path);
+ });
+
+ it('should not have merge buttons', () => {
+ expect(wrapper.text()).not.toContain(mergeLocallyBtnText);
+ });
+ });
+
+ describe('when allowed to merge and push to source branch', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mr: {
+ canMerge: true,
+ canPushToSourceBranch: true,
+ conflictResolutionPath: path,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should tell you about conflicts without bothering other people', () => {
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
+ });
+
+ it('should allow you to resolve the conflicts', () => {
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
+ expect(findResolveButton().attributes('href')).toEqual(path);
+ });
+
+ it('should have merge buttons', () => {
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
+ });
+ });
+
+ describe('when user does not have permission to push to source branch', () => {
+ it('should show proper message', async () => {
+ await createComponent({
+ mr: {
+ canMerge: false,
+ canPushToSourceBranch: false,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(userCannotMergeText);
+ });
+
+ it('should not have action buttons', async () => {
+ await createComponent({
+ mr: {
+ canMerge: false,
+ canPushToSourceBranch: false,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(findResolveButton().exists()).toBe(false);
+ expect(findMergeLocalButton().exists()).toBe(false);
+ });
+
+ it('should not have resolve button when no conflict resolution path', async () => {
+ await createComponent({
+ mr: {
+ canMerge: true,
+ conflictResolutionPath: null,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(findResolveButton().exists()).toBe(false);
+ });
+ });
+
+ describe('when fast-forward or semi-linear merge enabled', () => {
+ it('should tell you to rebase locally', async () => {
+ await createComponent({
+ mr: {
+ shouldBeRebased: true,
+ conflictsDocsPath: '',
+ },
+ });
+
+ expect(removeBreakLine(wrapper.text()).trim()).toContain(fastForwardMergeText);
+ });
+ });
+
+ describe('when source branch protected', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mr: {
+ canMerge: true,
+ canPushToSourceBranch: true,
+ conflictResolutionPath: TEST_HOST,
+ sourceBranchProtected: true,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should allow you to resolve the conflicts', () => {
+ expect(findResolveButton().exists()).toBe(true);
+ });
+ });
+
+ describe('when source branch not protected', () => {
+ beforeEach(async () => {
+ await createComponent({
+ mr: {
+ canMerge: true,
+ canPushToSourceBranch: true,
+ conflictResolutionPath: TEST_HOST,
+ sourceBranchProtected: false,
+ conflictsDocsPath: '',
+ },
+ });
+ });
+
+ it('should allow you to resolve the conflicts', () => {
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
+ expect(findResolveButton().attributes('href')).toEqual(TEST_HOST);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_failed_to_merge_spec.js
new file mode 100644
index 00000000000..989aa76f09b
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -0,0 +1,180 @@
+import { shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import MrWidgetFailedToMerge from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+
+describe('MRWidgetFailedToMerge', () => {
+ const dummyIntervalId = 1337;
+ let wrapper;
+
+ const createComponent = (props = {}, data = {}) => {
+ wrapper = shallowMount(MrWidgetFailedToMerge, {
+ propsData: {
+ mr: {
+ mergeError: 'Merge error happened',
+ },
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ });
+ };
+
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(window, 'setInterval').mockReturnValue(dummyIntervalId);
+ jest.spyOn(window, 'clearInterval').mockImplementation();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('interval', () => {
+ it('sets interval to refresh', () => {
+ createComponent();
+
+ expect(window.setInterval).toHaveBeenCalledWith(wrapper.vm.updateTimer, 1000);
+ expect(wrapper.vm.intervalId).toBe(dummyIntervalId);
+ });
+
+ it('clears interval when destroying ', () => {
+ createComponent();
+ wrapper.destroy();
+
+ expect(window.clearInterval).toHaveBeenCalledWith(dummyIntervalId);
+ });
+ });
+
+ describe('mergeError', () => {
+ it('removes forced line breaks', async () => {
+ createComponent({ mr: { mergeError: 'contains<br />line breaks<br />' } });
+
+ await nextTick();
+
+ expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains line breaks.');
+ });
+
+ it('does not append an extra period', async () => {
+ createComponent({ mr: { mergeError: 'contains a period.' } });
+
+ await nextTick();
+
+ expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a period.');
+ });
+
+ it('does not insert an extra space between the final character and the period', async () => {
+ createComponent({ mr: { mergeError: 'contains a <a href="http://example.com">link</a>.' } });
+
+ await nextTick();
+
+ expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a link.');
+ });
+
+ it('removes extra spaces', async () => {
+ createComponent({ mr: { mergeError: 'contains a lot of spaces .' } });
+
+ await nextTick();
+
+ expect(wrapper.find('[data-testid="merge-error"]').text()).toBe('contains a lot of spaces.');
+ });
+ });
+
+ describe('created', () => {
+ it('should disable polling', () => {
+ createComponent();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('DisablePolling');
+ });
+ });
+
+ describe('methods', () => {
+ describe('refresh', () => {
+ it('should emit event to request component refresh', () => {
+ createComponent();
+
+ expect(wrapper.vm.isRefreshing).toBe(false);
+
+ wrapper.vm.refresh();
+
+ expect(wrapper.vm.isRefreshing).toBe(true);
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling');
+ });
+ });
+
+ describe('updateTimer', () => {
+ it('should update timer and emit event when timer end', () => {
+ createComponent();
+
+ jest.spyOn(wrapper.vm, 'refresh').mockImplementation(() => {});
+
+ expect(wrapper.vm.timer).toEqual(10);
+
+ for (let i = 0; i < 10; i += 1) {
+ expect(wrapper.vm.timer).toEqual(10 - i);
+ wrapper.vm.updateTimer();
+ }
+
+ expect(wrapper.vm.refresh).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('while it is refreshing', () => {
+ it('renders Refresing now', async () => {
+ createComponent({}, { isRefreshing: true });
+
+ await nextTick();
+
+ expect(wrapper.find('.js-refresh-label').text().trim()).toBe('Refreshing now');
+ });
+ });
+
+ describe('while it is not regresing', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders warning icon and disabled merge button', () => {
+ expect(wrapper.find('.js-ci-status-icon-warning')).not.toBeNull();
+ });
+
+ it('renders given error', () => {
+ expect(wrapper.find('.has-error-message').text().trim()).toBe('Merge error happened.');
+ });
+
+ it('renders refresh button', () => {
+ expect(
+ wrapper.find('[data-testid="merge-request-failed-refresh-button"]').text().trim(),
+ ).toBe('Refresh now');
+ });
+
+ it('renders remaining time', () => {
+ expect(wrapper.find('.has-custom-error').text().trim()).toBe(
+ 'Refreshing in 10 seconds to show the updated status...',
+ );
+ });
+ });
+
+ it('should just generic merge failed message if merge_error is not available', async () => {
+ createComponent({ mr: { mergeError: null } });
+
+ await nextTick();
+
+ expect(wrapper.text().trim()).toContain('Merge failed.');
+ expect(wrapper.text().trim()).not.toContain('Merge error happened.');
+ });
+
+ it('should show refresh label when refresh requested', async () => {
+ createComponent();
+
+ wrapper.vm.refresh();
+
+ await nextTick();
+
+ expect(wrapper.text().trim()).not.toContain('Merge failed. Refreshing');
+ expect(wrapper.text().trim()).toContain('Refreshing now');
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js
new file mode 100644
index 00000000000..2606933450e
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merged_spec.js
@@ -0,0 +1,180 @@
+import { getByRole } from '@testing-library/dom';
+import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+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 eventHub from '~/vue_merge_request_widget/event_hub';
+
+describe('MRWidgetMerged', () => {
+ let vm;
+ 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',
+ },
+ 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() {},
+ };
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+
+ vm = mountComponent(Component, { mr, service });
+ });
+
+ afterEach(() => {
+ vm.$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);
+ });
+
+ it('returns true when all are true', () => {
+ vm.mr.isRemovingSourceBranch = true;
+ vm.mr.canRemoveSourceBranch = true;
+ vm.isMakingRequest = true;
+
+ expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
+ });
+ });
+
+ describe('shouldShowSourceBranchRemoving', () => {
+ it('should correct value when fields changed', () => {
+ vm.mr.sourceBranchRemoved = false;
+
+ expect(vm.shouldShowSourceBranchRemoving).toEqual(false);
+
+ vm.mr.sourceBranchRemoved = true;
+
+ expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
+
+ vm.mr.sourceBranchRemoved = false;
+ vm.isMakingRequest = true;
+
+ expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
+
+ vm.isMakingRequest = false;
+ vm.mr.isRemovingSourceBranch = true;
+
+ expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
+ });
+ });
+ });
+
+ 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',
+ },
+ });
+ }),
+ );
+
+ vm.removeSourceBranch();
+
+ await waitForPromises();
+
+ const args = eventHub.$emit.mock.calls[0];
+
+ expect(vm.isMakingRequest).toEqual(true);
+ expect(args[0]).toEqual('MRWidgetUpdateRequested');
+ expect(args[1]).not.toThrow();
+ });
+ });
+ });
+
+ it('calls dispatchDocumentEvent to load in the modal component', () => {
+ expect(document.dispatchEvent).toHaveBeenCalledWith(new CustomEvent('merged:UpdateActions'));
+ });
+
+ it('emits event to open the revert modal on revert button click', () => {
+ const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
+
+ getByRole(vm.$el, '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', () => {
+ const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
+
+ getByRole(vm.$el, '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');
+ });
+
+ it('shows revert and cherry-pick buttons', () => {
+ expect(vm.$el.textContent).toContain('Revert');
+ expect(vm.$el.textContent).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');
+ });
+});
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merging_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merging_spec.js
new file mode 100644
index 00000000000..49bd3739fdb
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_merging_spec.js
@@ -0,0 +1,61 @@
+import { shallowMount } from '@vue/test-utils';
+import simplePoll from '~/lib/utils/simple_poll';
+import MrWidgetMerging from '~/vue_merge_request_widget/components/states/mr_widget_merging.vue';
+
+jest.mock('~/lib/utils/simple_poll', () =>
+ jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
+);
+
+describe('MRWidgetMerging', () => {
+ let wrapper;
+
+ const GlEmoji = { template: '<img />' };
+ beforeEach(() => {
+ wrapper = shallowMount(MrWidgetMerging, {
+ propsData: {
+ mr: {
+ targetBranchPath: '/branch-path',
+ targetBranch: 'branch',
+ transitionStateMachine() {},
+ },
+ service: {
+ poll: jest.fn().mockResolvedValue(),
+ },
+ },
+ stubs: {
+ GlEmoji,
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders information about merge request being merged', () => {
+ expect(
+ wrapper
+ .find('.media-body')
+ .text()
+ .trim()
+ .replace(/\s\s+/g, ' ')
+ .replace(/[\r\n]+/g, ' '),
+ ).toContain('Merging!');
+ });
+
+ describe('initiateMergePolling', () => {
+ it('should call simplePoll', () => {
+ wrapper.vm.initiateMergePolling();
+
+ expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 });
+ });
+
+ it('should call handleMergePolling', () => {
+ jest.spyOn(wrapper.vm, 'handleMergePolling').mockImplementation(() => {});
+
+ wrapper.vm.initiateMergePolling();
+
+ expect(wrapper.vm.handleMergePolling).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_missing_branch_spec.js
index ddce07954ab..ddce07954ab 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_missing_branch_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_not_allowed_spec.js
index 63e93074857..63e93074857 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_not_allowed_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge_spec.js
new file mode 100644
index 00000000000..6de0c06c33d
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge_spec.js
@@ -0,0 +1,28 @@
+import Vue, { nextTick } from 'vue';
+import NothingToMerge from '~/vue_merge_request_widget/components/states/nothing_to_merge.vue';
+
+describe('NothingToMerge', () => {
+ describe('template', () => {
+ const Component = Vue.extend(NothingToMerge);
+ const newBlobPath = '/foo';
+ const vm = new Component({
+ el: document.createElement('div'),
+ propsData: {
+ mr: { newBlobPath },
+ },
+ });
+
+ it('should have correct elements', () => {
+ expect(vm.$el.classList.contains('mr-widget-body')).toBe(true);
+ expect(vm.$el.querySelector('[data-testid="createFileButton"]').href).toContain(newBlobPath);
+ expect(vm.$el.innerText).toContain('Use merge requests to propose changes to your project');
+ });
+
+ it('should not show new blob link if there is no link available', () => {
+ vm.mr.newBlobPath = null;
+ nextTick(() => {
+ expect(vm.$el.querySelector('[data-testid="createFileButton"]')).toEqual(null);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked_spec.js
index 9b10b078e89..9b10b078e89 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked_spec.js
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
new file mode 100644
index 00000000000..4e44ac539f2
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -0,0 +1,23 @@
+import { shallowMount } from '@vue/test-utils';
+import PipelineFailed from '~/vue_merge_request_widget/components/states/pipeline_failed.vue';
+
+describe('PipelineFailed', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(PipelineFailed);
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('should render error message with a disabled merge button', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
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
new file mode 100644
index 00000000000..6e89cd41559
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -0,0 +1,819 @@
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import { GlSprintf } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import produce from 'immer';
+import readyToMergeResponse from 'test_fixtures/graphql/merge_requests/states/ready_to_merge.query.graphql.json';
+import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
+import simplePoll from '~/lib/utils/simple_poll';
+import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
+import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
+import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
+import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
+import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
+import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+
+jest.mock('~/lib/utils/simple_poll', () =>
+ jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
+);
+jest.mock('~/commons/nav/user_merge_requests', () => ({
+ refreshUserMergeRequestCounts: jest.fn(),
+}));
+
+const commitMessage = readyToMergeResponse.data.project.mergeRequest.defaultMergeCommitMessage;
+const squashCommitMessage =
+ readyToMergeResponse.data.project.mergeRequest.defaultSquashCommitMessage;
+const commitMessageWithDescription =
+ readyToMergeResponse.data.project.mergeRequest.defaultMergeCommitMessageWithDescription;
+const createTestMr = (customConfig) => {
+ const mr = {
+ isPipelineActive: false,
+ pipeline: null,
+ isPipelineFailed: false,
+ isPipelinePassing: false,
+ isMergeAllowed: true,
+ isApproved: true,
+ onlyAllowMergeIfPipelineSucceeds: false,
+ ffOnlyEnabled: false,
+ hasCI: false,
+ ciStatus: null,
+ sha: '12345678',
+ squash: false,
+ squashIsEnabledByDefault: false,
+ squashIsReadonly: false,
+ squashIsSelected: false,
+ commitMessage,
+ squashCommitMessage,
+ commitMessageWithDescription,
+ defaultMergeCommitMessage: commitMessage,
+ defaultSquashCommitMessage: squashCommitMessage,
+ shouldRemoveSourceBranch: true,
+ canRemoveSourceBranch: false,
+ targetBranch: 'main',
+ preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY,
+ availableAutoMergeStrategies: [MWPS_MERGE_STRATEGY],
+ mergeImmediatelyDocsPath: 'path/to/merge/immediately/docs',
+ transitionStateMachine: (transition) => eventHub.$emit('StateMachineValueChanged', transition),
+ translateStateToMachine: () => this.transitionStateMachine(),
+ state: 'open',
+ canMerge: true,
+ };
+
+ Object.assign(mr, customConfig.mr);
+
+ return mr;
+};
+
+const createTestService = () => ({
+ merge: jest.fn(),
+ poll: jest.fn().mockResolvedValue(),
+});
+
+Vue.use(VueApollo);
+
+let wrapper;
+let readyToMergeResponseSpy;
+
+const findMergeButton = () => wrapper.find('[data-testid="merge-button"]');
+const findPipelineFailedConfirmModal = () =>
+ wrapper.findComponent(MergeFailedPipelineConfirmationDialog);
+
+const createReadyToMergeResponse = (customMr) => {
+ return produce(readyToMergeResponse, (draft) => {
+ Object.assign(draft.data.project.mergeRequest, customMr);
+ });
+};
+
+const createComponent = (
+ customConfig = {},
+ mergeRequestWidgetGraphql = false,
+ restructuredMrWidget = true,
+) => {
+ wrapper = shallowMount(ReadyToMerge, {
+ propsData: {
+ mr: createTestMr(customConfig),
+ service: createTestService(),
+ },
+ provide: {
+ glFeatures: {
+ mergeRequestWidgetGraphql,
+ restructuredMrWidget,
+ },
+ },
+ stubs: {
+ CommitEdit,
+ },
+ apolloProvider: createMockApollo([[readyToMergeQuery, readyToMergeResponseSpy]]),
+ });
+};
+
+const findCheckboxElement = () => wrapper.find(SquashBeforeMerge);
+const findCommitEditElements = () => wrapper.findAll(CommitEdit);
+const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
+const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
+const findTipLink = () => wrapper.find(GlSprintf);
+const findCommitEditWithInputId = (inputId) =>
+ findCommitEditElements().wrappers.find((x) => x.props('inputId') === inputId);
+const findMergeCommitMessage = () => findCommitEditWithInputId('merge-message-edit').props('value');
+const findSquashCommitMessage = () =>
+ findCommitEditWithInputId('squash-message-edit').props('value');
+
+const triggerApprovalUpdated = () => eventHub.$emit('ApprovalUpdated');
+
+describe('ReadyToMerge', () => {
+ beforeEach(() => {
+ readyToMergeResponseSpy = jest.fn().mockResolvedValueOnce(readyToMergeResponse);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isAutoMergeAvailable', () => {
+ it('should return true when at least one merge strategy is available', () => {
+ createComponent();
+
+ expect(wrapper.vm.isAutoMergeAvailable).toBe(true);
+ });
+
+ it('should return false when no merge strategies are available', () => {
+ createComponent({ mr: { availableAutoMergeStrategies: [] } });
+
+ expect(wrapper.vm.isAutoMergeAvailable).toBe(false);
+ });
+ });
+
+ describe('status', () => {
+ it('defaults to success', () => {
+ createComponent({ mr: { pipeline: true, availableAutoMergeStrategies: [] } });
+
+ expect(wrapper.vm.status).toEqual('success');
+ });
+
+ it('returns failed when MR has CI but also has an unknown status', () => {
+ createComponent({ mr: { hasCI: true } });
+
+ expect(wrapper.vm.status).toEqual('failed');
+ });
+
+ it('returns default when MR has no pipeline', () => {
+ createComponent({ mr: { availableAutoMergeStrategies: [] } });
+
+ expect(wrapper.vm.status).toEqual('success');
+ });
+
+ it('returns pending when pipeline is active', () => {
+ createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
+
+ expect(wrapper.vm.status).toEqual('pending');
+ });
+
+ it('returns failed when pipeline is failed', () => {
+ createComponent({
+ mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
+ });
+
+ expect(wrapper.vm.status).toEqual('failed');
+ });
+ });
+
+ describe('Merge Button Variant', () => {
+ it('defaults to confirm class', () => {
+ createComponent({
+ mr: { availableAutoMergeStrategies: [] },
+ });
+
+ expect(findMergeButton().attributes('variant')).toBe('confirm');
+ });
+ });
+
+ describe('status icon', () => {
+ it('defaults to tick icon', () => {
+ createComponent();
+
+ expect(wrapper.vm.iconClass).toEqual('success');
+ });
+
+ it('shows tick for success status', () => {
+ createComponent({ mr: { pipeline: true } });
+
+ expect(wrapper.vm.iconClass).toEqual('success');
+ });
+
+ it('shows tick for pending status', () => {
+ createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
+
+ expect(wrapper.vm.iconClass).toEqual('success');
+ });
+ });
+
+ describe('mergeButtonText', () => {
+ it('should return "Merge" when no auto merge strategies are available', () => {
+ createComponent({ mr: { availableAutoMergeStrategies: [] } });
+
+ expect(wrapper.vm.mergeButtonText).toEqual('Merge');
+ });
+
+ it('should return "Merge in progress"', async () => {
+ createComponent();
+
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ isMergingImmediately: true });
+
+ await nextTick();
+
+ expect(wrapper.vm.mergeButtonText).toEqual('Merge in progress');
+ });
+
+ it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => {
+ createComponent({
+ mr: { isMergingImmediately: false, preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY },
+ });
+
+ expect(wrapper.vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
+ });
+ });
+
+ describe('autoMergeText', () => {
+ it('should return Merge when pipeline succeeds', () => {
+ createComponent({ mr: { preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY } });
+
+ expect(wrapper.vm.autoMergeText).toEqual('Merge when pipeline succeeds');
+ });
+ });
+
+ describe('shouldShowMergeImmediatelyDropdown', () => {
+ it('should return false if no pipeline is active', () => {
+ createComponent({
+ mr: { isPipelineActive: false, onlyAllowMergeIfPipelineSucceeds: false },
+ });
+
+ expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
+ });
+
+ it('should return false if "Pipelines must succeed" is enabled for the current project', () => {
+ createComponent({ mr: { isPipelineActive: true, onlyAllowMergeIfPipelineSucceeds: true } });
+
+ expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
+ });
+ });
+
+ describe('isMergeButtonDisabled', () => {
+ it('should return false with initial data', () => {
+ createComponent({ mr: { isMergeAllowed: true } });
+
+ expect(wrapper.vm.isMergeButtonDisabled).toBe(false);
+ });
+
+ it('should return true when there is no commit message', () => {
+ createComponent({ mr: { isMergeAllowed: true, commitMessage: '' } });
+
+ expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
+ });
+
+ it('should return true if merge is not allowed', () => {
+ createComponent({
+ mr: {
+ isMergeAllowed: false,
+ availableAutoMergeStrategies: [],
+ onlyAllowMergeIfPipelineSucceeds: true,
+ },
+ });
+
+ expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
+ });
+
+ it('should return true when the vm instance is making request', async () => {
+ createComponent({ mr: { isMergeAllowed: true } });
+
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ isMakingRequest: true });
+
+ await nextTick();
+
+ expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleMergeButtonClick', () => {
+ const response = (status) => ({
+ data: {
+ status,
+ },
+ });
+
+ beforeEach(() => {
+ readyToMergeResponseSpy = jest
+ .fn()
+ .mockResolvedValueOnce(createReadyToMergeResponse({ squash: true, squashOnMerge: true }))
+ .mockResolvedValue(
+ createReadyToMergeResponse({
+ squash: true,
+ squashOnMerge: true,
+ defaultMergeCommitMessage: '',
+ defaultSquashCommitMessage: '',
+ }),
+ );
+ });
+
+ it('should handle merge when pipeline succeeds', async () => {
+ createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest
+ .spyOn(wrapper.vm.service, 'merge')
+ .mockResolvedValue(response('merge_when_pipeline_succeeds'));
+ // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
+ // eslint-disable-next-line no-restricted-syntax
+ wrapper.setData({ removeSourceBranch: false });
+
+ wrapper.vm.handleMergeButtonClick(true);
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
+ expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
+ transition: 'start-auto-merge',
+ });
+
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
+
+ expect(params).toEqual(
+ expect.objectContaining({
+ sha: wrapper.vm.mr.sha,
+ commit_message: wrapper.vm.mr.commitMessage,
+ should_remove_source_branch: false,
+ auto_merge_strategy: 'merge_when_pipeline_succeeds',
+ }),
+ );
+ });
+
+ it('should handle merge failed', async () => {
+ createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('failed'));
+ wrapper.vm.handleMergeButtonClick(false, true);
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
+
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
+
+ expect(params.should_remove_source_branch).toBe(true);
+ expect(params.auto_merge_strategy).toBeUndefined();
+ });
+
+ it('should handle merge action accepted case', async () => {
+ createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('success'));
+ jest.spyOn(wrapper.vm.mr, 'transitionStateMachine');
+ wrapper.vm.handleMergeButtonClick();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
+ transition: 'start-merge',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.vm.mr.transitionStateMachine).toHaveBeenCalledWith({
+ transition: 'start-merge',
+ });
+
+ const params = wrapper.vm.service.merge.mock.calls[0][0];
+
+ expect(params.should_remove_source_branch).toBe(true);
+ expect(params.auto_merge_strategy).toBeUndefined();
+ });
+
+ it('hides edit commit message', async () => {
+ createComponent({}, true, true);
+
+ await waitForPromises();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('success'));
+
+ await wrapper
+ .findComponent('[data-testid="widget_edit_commit_message"]')
+ .vm.$emit('input', true);
+
+ expect(wrapper.findComponent('[data-testid="edit_commit_message"]').exists()).toBe(true);
+
+ wrapper.vm.handleMergeButtonClick();
+
+ await waitForPromises();
+
+ expect(wrapper.findComponent('[data-testid="edit_commit_message"]').exists()).toBe(false);
+ });
+ });
+
+ describe('initiateRemoveSourceBranchPolling', () => {
+ it('should emit event and call simplePoll', () => {
+ createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+
+ wrapper.vm.initiateRemoveSourceBranchPolling();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
+ expect(simplePoll).toHaveBeenCalled();
+ });
+ });
+
+ describe('handleRemoveBranchPolling', () => {
+ const response = (state) => ({
+ data: {
+ source_branch_exists: state,
+ },
+ });
+
+ it('should call start and stop polling when MR merged', async () => {
+ createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(false));
+
+ let cpc = false; // continuePollingCalled
+ let spc = false; // stopPollingCalled
+
+ wrapper.vm.handleRemoveBranchPolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
+
+ await waitForPromises();
+
+ expect(wrapper.vm.service.poll).toHaveBeenCalled();
+
+ const args = eventHub.$emit.mock.calls[0];
+
+ expect(args[0]).toEqual('MRWidgetUpdateRequested');
+ expect(args[1]).toBeDefined();
+ args[1]();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
+
+ expect(cpc).toBe(false);
+ expect(spc).toBe(true);
+ });
+
+ it('should continue polling until MR is merged', async () => {
+ createComponent();
+
+ jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(true));
+
+ let cpc = false; // continuePollingCalled
+ let spc = false; // stopPollingCalled
+
+ wrapper.vm.handleRemoveBranchPolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
+
+ await waitForPromises();
+
+ expect(cpc).toBe(true);
+ expect(spc).toBe(false);
+ });
+ });
+ });
+
+ describe('Remove source branch checkbox', () => {
+ describe('when user can merge but cannot delete branch', () => {
+ it('should be disabled in the rendered output', () => {
+ createComponent();
+
+ expect(wrapper.find('#remove-source-branch-input').exists()).toBe(false);
+ });
+ });
+
+ describe('when user can merge and can delete branch', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: { canRemoveSourceBranch: true },
+ });
+ });
+
+ it('isRemoveSourceBranchButtonDisabled should be false', () => {
+ expect(wrapper.find('#remove-source-branch-input').props('disabled')).toBe(undefined);
+ });
+ });
+ });
+
+ describe('render children components', () => {
+ describe('squash checkbox', () => {
+ it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
+ createComponent({
+ mr: { commitsCount: 2, enableSquashBeforeMerge: true },
+ });
+
+ expect(findCheckboxElement().exists()).toBe(true);
+ });
+
+ it('should not be rendered when squash before merge is disabled', () => {
+ createComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: false } });
+
+ expect(findCheckboxElement().exists()).toBe(false);
+ });
+
+ it('should be rendered when there is only 1 commit', () => {
+ createComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
+
+ expect(findCheckboxElement().exists()).toBe(true);
+ });
+
+ describe('squash options', () => {
+ it.each`
+ squashState | state | prop | expectation
+ ${'squashIsReadonly'} | ${'enabled'} | ${'isDisabled'} | ${false}
+ ${'squashIsSelected'} | ${'selected'} | ${'value'} | ${false}
+ ${'squashIsSelected'} | ${'unselected'} | ${'value'} | ${false}
+ `(
+ 'is $state when squashIsReadonly returns $expectation ',
+ ({ squashState, prop, expectation }) => {
+ createComponent({
+ mr: { commitsCount: 2, enableSquashBeforeMerge: true, [squashState]: expectation },
+ });
+
+ expect(findCheckboxElement().props(prop)).toBe(expectation);
+ },
+ );
+
+ it('is not rendered for "Do not allow" option', () => {
+ createComponent({
+ mr: {
+ commitsCount: 2,
+ enableSquashBeforeMerge: true,
+ squashIsReadonly: true,
+ squashIsSelected: false,
+ },
+ });
+
+ expect(findCheckboxElement().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('commits edit components', () => {
+ describe('when fast-forward merge is enabled', () => {
+ it('should not be rendered if squash is disabled', async () => {
+ createComponent({
+ mr: {
+ ffOnlyEnabled: true,
+ squash: false,
+ enableSquashBeforeMerge: true,
+ commitsCount: 2,
+ },
+ });
+
+ expect(findCommitEditElements().length).toBe(0);
+ });
+
+ it('should not be rendered if squash before merge is disabled', () => {
+ createComponent({
+ mr: {
+ ffOnlyEnabled: true,
+ squash: true,
+ enableSquashBeforeMerge: false,
+ commitsCount: 2,
+ },
+ });
+
+ expect(findCommitEditElements().length).toBe(0);
+ });
+
+ it('should not be rendered if there is only one commit', () => {
+ createComponent({
+ mr: {
+ ffOnlyEnabled: true,
+ squash: true,
+ enableSquashBeforeMerge: true,
+ commitsCount: 1,
+ },
+ });
+
+ expect(findCommitEditElements().length).toBe(0);
+ });
+
+ it('should have one edit component if squash is enabled and there is more than 1 commit', async () => {
+ createComponent({
+ mr: {
+ ffOnlyEnabled: true,
+ squashIsSelected: true,
+ enableSquashBeforeMerge: true,
+ commitsCount: 2,
+ },
+ });
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findCommitEditElements().length).toBe(1);
+ expect(findFirstCommitEditLabel()).toBe('Squash commit message');
+ });
+ });
+
+ it('should have two edit components when squash is enabled and there is more than 1 commit', async () => {
+ createComponent({
+ mr: {
+ commitsCount: 2,
+ squashIsSelected: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findCommitEditElements().length).toBe(2);
+ });
+
+ it('should have two edit components when squash is enabled and there is more than 1 commit and mergeRequestWidgetGraphql is enabled', async () => {
+ createComponent(
+ {
+ mr: {
+ commitsCount: 2,
+ squashIsSelected: true,
+ enableSquashBeforeMerge: true,
+ },
+ },
+ true,
+ );
+
+ // 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: false,
+ state: {
+ ...createTestMr({}),
+ userPermissions: {},
+ squash: true,
+ mergeable: true,
+ commitCount: 2,
+ commitsWithoutMergeCommits: {},
+ },
+ });
+ await nextTick();
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findCommitEditElements().length).toBe(2);
+ });
+
+ it('should have one edit components when squash is enabled and there is 1 commit only', async () => {
+ createComponent({
+ mr: {
+ commitsCount: 1,
+ squash: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findCommitEditElements().length).toBe(1);
+ });
+
+ it('should have correct edit squash commit label', async () => {
+ createComponent({
+ mr: {
+ commitsCount: 2,
+ squashIsSelected: true,
+ enableSquashBeforeMerge: true,
+ },
+ });
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findFirstCommitEditLabel()).toBe('Squash commit message');
+ });
+ });
+
+ describe('commits dropdown', () => {
+ it('should not be rendered if squash is disabled', () => {
+ createComponent();
+
+ expect(findCommitDropdownElement().exists()).toBe(false);
+ });
+
+ it('should be rendered if squash is enabled and there is more than 1 commit', async () => {
+ createComponent({
+ mr: { enableSquashBeforeMerge: true, squashIsSelected: true, commitsCount: 2 },
+ });
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findCommitDropdownElement().exists()).toBe(true);
+ });
+ });
+
+ it('renders a tip including a link to docs on templates', async () => {
+ createComponent();
+
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(findTipLink().exists()).toBe(true);
+ });
+ });
+
+ describe('Merge button when pipeline has failed', () => {
+ beforeEach(() => {
+ createComponent({
+ mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
+ });
+ });
+
+ it('should display the correct merge text', () => {
+ expect(findMergeButton().text()).toBe('Merge...');
+ });
+
+ it('should display confirmation modal when merge button is clicked', async () => {
+ expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: false });
+
+ await findMergeButton().vm.$emit('click');
+
+ expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: true });
+ });
+ });
+
+ describe('updating graphql data triggers commit message update when default changed', () => {
+ const UPDATED_MERGE_COMMIT_MESSAGE = 'New merge message from BE';
+ const UPDATED_SQUASH_COMMIT_MESSAGE = 'New squash message from BE';
+ const USER_COMMIT_MESSAGE = 'Merge message provided manually by user';
+
+ const createDefaultGqlComponent = () =>
+ createComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: true } }, true);
+
+ beforeEach(() => {
+ readyToMergeResponseSpy = jest
+ .fn()
+ .mockResolvedValueOnce(createReadyToMergeResponse({ squash: true, squashOnMerge: true }))
+ .mockResolvedValue(
+ createReadyToMergeResponse({
+ squash: true,
+ squashOnMerge: true,
+ defaultMergeCommitMessage: UPDATED_MERGE_COMMIT_MESSAGE,
+ defaultSquashCommitMessage: UPDATED_SQUASH_COMMIT_MESSAGE,
+ }),
+ );
+ });
+
+ describe.each`
+ desc | finderFn | initialValue | updatedValue | inputId
+ ${'merge commit message'} | ${findMergeCommitMessage} | ${commitMessage} | ${UPDATED_MERGE_COMMIT_MESSAGE} | ${'#merge-message-edit'}
+ ${'squash commit message'} | ${findSquashCommitMessage} | ${squashCommitMessage} | ${UPDATED_SQUASH_COMMIT_MESSAGE} | ${'#squash-message-edit'}
+ `('with $desc', ({ finderFn, initialValue, updatedValue, inputId }) => {
+ it('should have initial value', async () => {
+ createDefaultGqlComponent();
+
+ await waitForPromises();
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ expect(finderFn()).toBe(initialValue);
+ });
+
+ it('should have updated value after graphql refetch', async () => {
+ createDefaultGqlComponent();
+ await waitForPromises();
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ triggerApprovalUpdated();
+ await waitForPromises();
+
+ expect(finderFn()).toBe(updatedValue);
+ });
+
+ it('should not update if user has touched', async () => {
+ createDefaultGqlComponent();
+ await waitForPromises();
+ await wrapper.find('[data-testid="widget_edit_commit_message"]').vm.$emit('input', true);
+
+ const input = wrapper.find(inputId);
+ input.element.value = USER_COMMIT_MESSAGE;
+ input.trigger('input');
+
+ triggerApprovalUpdated();
+ await waitForPromises();
+
+ expect(finderFn()).toBe(USER_COMMIT_MESSAGE);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_sha_mismatch_spec.js
index 2a343997cf5..2a343997cf5 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_sha_mismatch_spec.js
diff --git a/spec/frontend/vue_mr_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..6ea2e8675d3 100644
--- a/spec/frontend/vue_mr_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
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions_spec.js
index e2d79c61b9b..e2d79c61b9b 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions_spec.js
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
new file mode 100644
index 00000000000..af52901f508
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_wip_spec.js
@@ -0,0 +1,101 @@
+import Vue, { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
+import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
+import toast from '~/vue_shared/plugins/global_toast';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+
+jest.mock('~/vue_shared/plugins/global_toast');
+
+const createComponent = () => {
+ const Component = Vue.extend(WorkInProgress);
+ const mr = {
+ title: 'The best MR ever',
+ removeWIPPath: '/path/to/remove/wip',
+ };
+ const service = {
+ removeWIP() {},
+ };
+ return new Component({
+ el: document.createElement('div'),
+ propsData: { mr, service },
+ });
+};
+
+describe('Wip', () => {
+ describe('props', () => {
+ it('should have props', () => {
+ const { mr, service } = WorkInProgress.props;
+
+ expect(mr.type instanceof Object).toBe(true);
+ expect(mr.required).toBe(true);
+
+ expect(service.type instanceof Object).toBe(true);
+ expect(service.required).toBe(true);
+ });
+ });
+
+ describe('data', () => {
+ it('should have default data', () => {
+ const vm = createComponent();
+
+ expect(vm.isMakingRequest).toBeFalsy();
+ });
+ });
+
+ describe('methods', () => {
+ const mrObj = {
+ is_new_mr_data: true,
+ };
+
+ describe('handleRemoveDraft', () => {
+ it('should make a request to service and handle response', async () => {
+ const vm = createComponent();
+
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ jest.spyOn(vm.service, 'removeWIP').mockReturnValue(
+ new Promise((resolve) => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
+
+ vm.handleRemoveDraft();
+
+ await waitForPromises();
+
+ expect(vm.isMakingRequest).toBe(true);
+ expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
+ expect(toast).toHaveBeenCalledWith('Marked as ready. Merging is now allowed.');
+ });
+ });
+ });
+
+ describe('template', () => {
+ let vm;
+ let el;
+
+ beforeEach(() => {
+ vm = createComponent();
+ el = vm.$el;
+ });
+
+ it('should have correct elements', () => {
+ expect(el.classList.contains('mr-widget-body')).toBe(true);
+ expect(el.innerText).toContain(
+ "Merge blocked: merge request must be marked as ready. It's still marked as draft.",
+ );
+ expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain(
+ 'Mark as ready',
+ );
+ });
+
+ it('should not show removeWIP button is user cannot update MR', async () => {
+ vm.mr.removeWIPPath = '';
+
+ await nextTick();
+
+ expect(el.querySelector('.js-remove-draft')).toBeNull();
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/new_ready_to_merge_spec.js b/spec/frontend/vue_merge_request_widget/components/states/new_ready_to_merge_spec.js
index 5ec9654a4af..5ec9654a4af 100644
--- a/spec/frontend/vue_mr_widget/components/states/new_ready_to_merge_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/states/new_ready_to_merge_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/terraform/mock_data.js b/spec/frontend/vue_merge_request_widget/components/terraform/mock_data.js
index 8e46af5dfd6..8e46af5dfd6 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/components/terraform/mock_data.js
diff --git a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
index 8f20d6a8fc9..8f20d6a8fc9 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/terraform/mr_widget_terraform_container_spec.js
diff --git a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
index 3c9f6c2e165..3c9f6c2e165 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/terraform/terraform_plan_spec.js
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/app_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/app_spec.js
new file mode 100644
index 00000000000..6bb718082a4
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/widget/app_spec.js
@@ -0,0 +1,19 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import App from '~/vue_merge_request_widget/components/widget/app.vue';
+
+describe('MR Widget App', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(App, {
+ propsData: {
+ mr: {},
+ },
+ });
+ };
+
+ it('mounts the component', () => {
+ createComponent();
+ expect(wrapper.findByTestId('mr-widget-app').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
new file mode 100644
index 00000000000..3c08ffdef18
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
@@ -0,0 +1,167 @@
+import { nextTick } from 'vue';
+import * as Sentry from '@sentry/browser';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
+import Widget from '~/vue_merge_request_widget/components/widget/widget.vue';
+
+describe('MR Widget', () => {
+ let wrapper;
+
+ const findStatusIcon = () => wrapper.findComponent(StatusIcon);
+
+ const createComponent = ({ propsData, slots } = {}) => {
+ wrapper = shallowMountExtended(Widget, {
+ propsData: {
+ loadingText: 'Loading widget',
+ widgetName: 'MyWidget',
+ value: {
+ collapsed: null,
+ expanded: null,
+ },
+ ...propsData,
+ },
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('on mount', () => {
+ it('fetches collapsed', async () => {
+ const fetchCollapsedData = jest
+ .fn()
+ .mockReturnValue(Promise.resolve({ headers: {}, status: 200, data: {} }));
+
+ createComponent({ propsData: { fetchCollapsedData } });
+ await waitForPromises();
+ expect(fetchCollapsedData).toHaveBeenCalled();
+ expect(wrapper.vm.error).toBe(null);
+ });
+
+ it('sets the error text when fetch method fails', async () => {
+ const fetchCollapsedData = jest.fn().mockReturnValue(() => Promise.reject());
+ createComponent({ propsData: { fetchCollapsedData } });
+ await waitForPromises();
+ expect(wrapper.vm.error).toBe('Failed to load');
+ });
+
+ it('displays loading icon until request is made and then displays status icon when the request is complete', async () => {
+ const fetchCollapsedData = jest
+ .fn()
+ .mockReturnValue(Promise.resolve({ headers: {}, status: 200, data: {} }));
+
+ createComponent({ propsData: { fetchCollapsedData, statusIconName: 'warning' } });
+
+ // Let on mount be called
+ await nextTick();
+
+ expect(findStatusIcon().props('isLoading')).toBe(true);
+
+ // Wait until `fetchCollapsedData` is resolved
+ await waitForPromises();
+
+ expect(findStatusIcon().props('isLoading')).toBe(false);
+ expect(findStatusIcon().props('iconName')).toBe('warning');
+ });
+
+ it('displays the loading text', async () => {
+ const fetchCollapsedData = jest.fn().mockReturnValue(() => Promise.reject());
+ createComponent({ propsData: { fetchCollapsedData, statusIconName: 'warning' } });
+ expect(wrapper.text()).not.toContain('Loading');
+ await nextTick();
+ expect(wrapper.text()).toContain('Loading');
+ });
+ });
+
+ describe('fetch', () => {
+ it('sets the data.collapsed property after a successfull call - multiPolling: false', async () => {
+ const mockData = { headers: {}, status: 200, data: { vulnerabilities: [] } };
+ createComponent({ propsData: { fetchCollapsedData: async () => mockData } });
+ await waitForPromises();
+ expect(wrapper.emitted('input')[0][0]).toEqual({ collapsed: mockData.data, expanded: null });
+ });
+
+ it('sets the data.collapsed property after a successfull call - multiPolling: true', async () => {
+ const mockData1 = { headers: {}, status: 200, data: { vulnerabilities: [{ vuln: 1 }] } };
+ const mockData2 = { headers: {}, status: 200, data: { vulnerabilities: [{ vuln: 2 }] } };
+
+ createComponent({
+ propsData: {
+ multiPolling: true,
+ fetchCollapsedData: () => [
+ () => Promise.resolve(mockData1),
+ () => Promise.resolve(mockData2),
+ ],
+ },
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('input')[0][0]).toEqual({
+ collapsed: [mockData1.data, mockData2.data],
+ expanded: null,
+ });
+ });
+
+ it('calls sentry when failed', async () => {
+ const error = new Error('Something went wrong');
+ jest.spyOn(Sentry, 'captureException').mockImplementation();
+ createComponent({
+ propsData: {
+ fetchCollapsedData: async () => Promise.reject(error),
+ },
+ });
+ await waitForPromises();
+ expect(wrapper.emitted('input')).toBeUndefined();
+ expect(Sentry.captureException).toHaveBeenCalledWith(error);
+ });
+ });
+
+ describe('content', () => {
+ it('displays summary property when summary slot is not provided', () => {
+ createComponent({
+ propsData: {
+ summary: 'Hello world',
+ fetchCollapsedData: async () => Promise.resolve(),
+ },
+ });
+
+ expect(wrapper.findByTestId('widget-extension-top-level-summary').text()).toBe('Hello world');
+ });
+
+ it.todo('displays content property when content slot is not provided');
+
+ it('displays the summary slot when provided', () => {
+ createComponent({
+ propsData: {
+ fetchCollapsedData: async () => Promise.resolve(),
+ },
+ slots: {
+ summary: '<b>More complex summary</b>',
+ },
+ });
+
+ expect(wrapper.findByTestId('widget-extension-top-level-summary').text()).toBe(
+ 'More complex summary',
+ );
+ });
+
+ it('displays the content slot when provided', () => {
+ createComponent({
+ propsData: {
+ fetchCollapsedData: async () => Promise.resolve(),
+ },
+ slots: {
+ content: '<b>More complex content</b>',
+ },
+ });
+
+ expect(wrapper.findByTestId('widget-extension-collapsed-section').text()).toBe(
+ 'More complex content',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js
index 7e7438bcc0f..7e7438bcc0f 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_action_button_spec.js
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
index a285d26f404..a285d26f404 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_actions_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_actions_spec.js
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_list_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_list_spec.js
index 948d7ebab5e..948d7ebab5e 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_list_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_list_spec.js
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js
index e98b1160ae4..e98b1160ae4 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_mock_data.js
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
index c27cbd8b781..c27cbd8b781 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_spec.js
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
index eb6e3711e2e..eb6e3711e2e 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_view_button_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
diff --git a/spec/frontend/vue_mr_widget/extensions/test_report/index_spec.js b/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js
index 5c1d3c8e8e8..5c1d3c8e8e8 100644
--- a/spec/frontend/vue_mr_widget/extensions/test_report/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extensions/test_report/index_spec.js
diff --git a/spec/frontend/vue_mr_widget/extensions/test_report/utils_spec.js b/spec/frontend/vue_merge_request_widget/extensions/test_report/utils_spec.js
index 69ea70549fe..69ea70549fe 100644
--- a/spec/frontend/vue_mr_widget/extensions/test_report/utils_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extensions/test_report/utils_spec.js
diff --git a/spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js b/spec/frontend/vue_merge_request_widget/extentions/accessibility/index_spec.js
index a06ad930abe..a06ad930abe 100644
--- a/spec/frontend/vue_mr_widget/extentions/accessibility/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extentions/accessibility/index_spec.js
diff --git a/spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js b/spec/frontend/vue_merge_request_widget/extentions/accessibility/mock_data.js
index 06dc93d101f..06dc93d101f 100644
--- a/spec/frontend/vue_mr_widget/extentions/accessibility/mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/extentions/accessibility/mock_data.js
diff --git a/spec/frontend/vue_mr_widget/extentions/code_quality/index_spec.js b/spec/frontend/vue_merge_request_widget/extentions/code_quality/index_spec.js
index 9a72e4a086b..9a72e4a086b 100644
--- a/spec/frontend/vue_mr_widget/extentions/code_quality/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extentions/code_quality/index_spec.js
diff --git a/spec/frontend/vue_mr_widget/extentions/code_quality/mock_data.js b/spec/frontend/vue_merge_request_widget/extentions/code_quality/mock_data.js
index f5ad0ce7377..f5ad0ce7377 100644
--- a/spec/frontend/vue_mr_widget/extentions/code_quality/mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/extentions/code_quality/mock_data.js
diff --git a/spec/frontend/vue_mr_widget/extentions/terraform/index_spec.js b/spec/frontend/vue_merge_request_widget/extentions/terraform/index_spec.js
index d9faa7b2d25..d9faa7b2d25 100644
--- a/spec/frontend/vue_mr_widget/extentions/terraform/index_spec.js
+++ b/spec/frontend/vue_merge_request_widget/extentions/terraform/index_spec.js
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_merge_request_widget/mock_data.js
index 20d00a116bb..20d00a116bb 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/mock_data.js
diff --git a/spec/frontend/vue_mr_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..295b9df30b9 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_how_to_merge_modal_spec.js
+++ b/spec/frontend/vue_merge_request_widget/mr_widget_how_to_merge_modal_spec.js
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
new file mode 100644
index 00000000000..819841317f9
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js
@@ -0,0 +1,1198 @@
+import { GlBadge, GlLink, GlIcon, GlButton, GlDropdown } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import * as Sentry from '@sentry/browser';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
+import api from '~/api';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+import { setFaviconOverlay } from '~/lib/utils/favicon';
+import notify from '~/lib/utils/notify';
+import SmartInterval from '~/smart_interval';
+import {
+ registerExtension,
+ registeredExtensions,
+} from '~/vue_merge_request_widget/components/extensions';
+import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
+import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
+import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql';
+import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
+import mockData from './mock_data';
+import {
+ workingExtension,
+ collapsedDataErrorExtension,
+ fullDataErrorExtension,
+ fullReportExtension,
+ noTelemetryExtension,
+ pollingExtension,
+ pollingFullDataExtension,
+ pollingErrorExtension,
+ multiPollingExtension,
+} from './test_extensions';
+
+jest.mock('~/api.js');
+
+jest.mock('~/smart_interval');
+
+jest.mock('~/lib/utils/favicon');
+
+jest.mock('@sentry/browser', () => ({
+ setExtra: jest.fn(),
+ setExtras: jest.fn(),
+ captureMessage: jest.fn(),
+ captureException: jest.fn(),
+}));
+
+Vue.use(VueApollo);
+
+describe('MrWidgetOptions', () => {
+ let wrapper;
+ let mock;
+
+ const COLLABORATION_MESSAGE = 'Members who can merge are allowed to add commits';
+ const findExtensionToggleButton = () =>
+ wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]');
+ const findExtensionLink = (linkHref) =>
+ wrapper.find(`[data-testid="widget-extension"] [href="${linkHref}"]`);
+
+ beforeEach(() => {
+ gl.mrWidgetData = { ...mockData };
+ gon.features = { asyncMrWidget: true };
+
+ mock = new MockAdapter(axios);
+ mock.onGet(mockData.merge_request_widget_path).reply(() => [200, { ...mockData }]);
+ mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, { ...mockData }]);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+
+ gl.mrWidgetData = {};
+ gon.features = {};
+ });
+
+ const createComponent = (mrData = mockData, options = {}) => {
+ wrapper = mount(MrWidgetOptions, {
+ propsData: {
+ mrData: { ...mrData },
+ },
+ ...options,
+ });
+
+ return axios.waitForAll();
+ };
+
+ const findSuggestPipeline = () => wrapper.find('[data-testid="mr-suggest-pipeline"]');
+ const findSuggestPipelineButton = () => findSuggestPipeline().find('button');
+ const findSecurityMrWidget = () => wrapper.find('[data-testid="security-mr-widget"]');
+
+ describe('default', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
+ return createComponent();
+ });
+
+ describe('data', () => {
+ it('should instantiate Store and Service', () => {
+ expect(wrapper.vm.mr).toBeDefined();
+ expect(wrapper.vm.service).toBeDefined();
+ });
+ });
+
+ describe('computed', () => {
+ describe('componentName', () => {
+ it.each`
+ state | componentName
+ ${'merged'} | ${'mr-widget-merged'}
+ ${'conflicts'} | ${'mr-widget-conflicts'}
+ ${'shaMismatch'} | ${'sha-mismatch'}
+ `('should translate $state into $componentName', ({ state, componentName }) => {
+ wrapper.vm.mr.state = state;
+
+ expect(wrapper.vm.componentName).toEqual(componentName);
+ });
+ });
+
+ describe('shouldRenderPipelines', () => {
+ it('should return true when hasCI is true', () => {
+ wrapper.vm.mr.hasCI = true;
+
+ expect(wrapper.vm.shouldRenderPipelines).toBe(true);
+ });
+
+ it('should return false when hasCI is false', () => {
+ wrapper.vm.mr.hasCI = false;
+
+ expect(wrapper.vm.shouldRenderPipelines).toBe(false);
+ });
+ });
+
+ describe('shouldRenderSourceBranchRemovalStatus', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.state = 'readyToMerge';
+ });
+
+ it('should return true when cannot remove source branch and branch will be removed', () => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(true);
+ });
+
+ it('should return false when can remove source branch and branch will be removed', () => {
+ wrapper.vm.mr.canRemoveSourceBranch = true;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ });
+
+ it('should return false when cannot remove source branch and branch will not be removed', () => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = false;
+
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ });
+
+ it('should return false when in merged state', () => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'merged';
+
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ });
+
+ it('should return false when in nothing to merge state', () => {
+ wrapper.vm.mr.canRemoveSourceBranch = false;
+ wrapper.vm.mr.shouldRemoveSourceBranch = true;
+ wrapper.vm.mr.state = 'nothingToMerge';
+
+ expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
+ });
+ });
+
+ describe('shouldRenderCollaborationStatus', () => {
+ describe('when collaboration is allowed', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.allowCollaboration = true;
+ });
+
+ describe('when merge request is opened', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.isOpen = true;
+ return nextTick();
+ });
+
+ it('should render collaboration status', () => {
+ expect(wrapper.text()).toContain(COLLABORATION_MESSAGE);
+ });
+ });
+
+ describe('when merge request is not opened', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.isOpen = false;
+ return nextTick();
+ });
+
+ it('should not render collaboration status', () => {
+ expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
+ });
+ });
+ });
+
+ describe('when collaboration is not allowed', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.allowCollaboration = false;
+ });
+
+ describe('when merge request is opened', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.isOpen = true;
+ return nextTick();
+ });
+
+ it('should not render collaboration status', () => {
+ expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
+ });
+ });
+ });
+ });
+
+ describe('showMergePipelineForkWarning', () => {
+ describe('when the source project and target project are the same', () => {
+ beforeEach(() => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 1);
+ return nextTick();
+ });
+
+ it('should be false', () => {
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
+ });
+ });
+
+ describe('when merge pipelines are not enabled', () => {
+ beforeEach(() => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', false);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
+ return nextTick();
+ });
+
+ it('should be false', () => {
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
+ });
+ });
+
+ describe('when merge pipelines are enabled _and_ the source project and target project are different', () => {
+ beforeEach(() => {
+ Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
+ Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
+ Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
+ return nextTick();
+ });
+
+ it('should be true', () => {
+ expect(wrapper.vm.showMergePipelineForkWarning).toEqual(true);
+ });
+ });
+ });
+
+ describe('formattedHumanAccess', () => {
+ it('when user is a tool admin but not a member of project', () => {
+ wrapper.vm.mr.humanAccess = null;
+
+ expect(wrapper.vm.formattedHumanAccess).toEqual('');
+ });
+
+ it('when user a member of the project', () => {
+ wrapper.vm.mr.humanAccess = 'Owner';
+
+ expect(wrapper.vm.formattedHumanAccess).toEqual('owner');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('checkStatus', () => {
+ let cb;
+ let isCbExecuted;
+
+ beforeEach(() => {
+ jest.spyOn(wrapper.vm.service, 'checkStatus').mockResolvedValue({ data: mockData });
+ jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'handleNotification').mockImplementation(() => {});
+
+ isCbExecuted = false;
+ cb = () => {
+ isCbExecuted = true;
+ };
+ });
+
+ it('should tell service to check status if document is visible', () => {
+ wrapper.vm.checkStatus(cb);
+
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.checkStatus).toHaveBeenCalled();
+ expect(wrapper.vm.mr.setData).toHaveBeenCalled();
+ expect(wrapper.vm.handleNotification).toHaveBeenCalledWith(mockData);
+ expect(isCbExecuted).toBe(true);
+ });
+ });
+ });
+
+ describe('initPolling', () => {
+ it('should call SmartInterval', () => {
+ wrapper.vm.initPolling();
+
+ expect(SmartInterval).toHaveBeenCalledWith(
+ expect.objectContaining({
+ callback: wrapper.vm.checkStatus,
+ }),
+ );
+ });
+ });
+
+ describe('initDeploymentsPolling', () => {
+ it('should call SmartInterval', () => {
+ wrapper.vm.initDeploymentsPolling();
+
+ expect(SmartInterval).toHaveBeenCalledWith(
+ expect.objectContaining({
+ callback: wrapper.vm.fetchPreMergeDeployments,
+ }),
+ );
+ });
+ });
+
+ describe('fetchDeployments', () => {
+ it('should fetch deployments', () => {
+ jest
+ .spyOn(wrapper.vm.service, 'fetchDeployments')
+ .mockResolvedValue({ data: [{ id: 1, status: SUCCESS }] });
+
+ wrapper.vm.fetchPreMergeDeployments();
+
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.fetchDeployments).toHaveBeenCalled();
+ expect(wrapper.vm.mr.deployments.length).toEqual(1);
+ expect(wrapper.vm.mr.deployments[0].id).toBe(1);
+ });
+ });
+ });
+
+ describe('fetchActionsContent', () => {
+ it('should fetch content of Cherry Pick and Revert modals', () => {
+ jest
+ .spyOn(wrapper.vm.service, 'fetchMergeActionsContent')
+ .mockResolvedValue({ data: 'hello world' });
+
+ wrapper.vm.fetchActionsContent();
+
+ return nextTick().then(() => {
+ expect(wrapper.vm.service.fetchMergeActionsContent).toHaveBeenCalled();
+ expect(document.body.textContent).toContain('hello world');
+ expect(document.dispatchEvent).toHaveBeenCalledWith(
+ new CustomEvent('merged:UpdateActions'),
+ );
+ });
+ });
+ });
+
+ describe('bindEventHubListeners', () => {
+ it.each`
+ event | method | methodArgs
+ ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${(x) => [x]}
+ ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${(x) => [x, true]}
+ ${'FetchActionsContent'} | ${'fetchActionsContent'} | ${() => []}
+ ${'EnablePolling'} | ${'resumePolling'} | ${() => []}
+ ${'DisablePolling'} | ${'stopPolling'} | ${() => []}
+ `('should bind to $event', ({ event, method, methodArgs }) => {
+ jest.spyOn(wrapper.vm, method).mockImplementation();
+
+ const eventArg = {};
+ eventHub.$emit(event, eventArg);
+
+ expect(wrapper.vm[method]).toHaveBeenCalledWith(...methodArgs(eventArg));
+ });
+
+ it('should bind to SetBranchRemoveFlag', () => {
+ expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(false);
+
+ eventHub.$emit('SetBranchRemoveFlag', [true]);
+
+ expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(true);
+ });
+
+ it('should bind to FailedToMerge', () => {
+ wrapper.vm.mr.state = '';
+ wrapper.vm.mr.mergeError = '';
+
+ const mergeError = 'Something bad happened!';
+ eventHub.$emit('FailedToMerge', mergeError);
+
+ expect(wrapper.vm.mr.state).toBe('failedToMerge');
+ expect(wrapper.vm.mr.mergeError).toBe(mergeError);
+ });
+
+ it('should bind to UpdateWidgetData', () => {
+ jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation();
+
+ const data = { ...mockData };
+ eventHub.$emit('UpdateWidgetData', data);
+
+ expect(wrapper.vm.mr.setData).toHaveBeenCalledWith(data);
+ });
+ });
+
+ describe('setFavicon', () => {
+ let faviconElement;
+
+ beforeEach(() => {
+ const favicon = document.createElement('link');
+ favicon.setAttribute('id', 'favicon');
+ favicon.dataset.originalHref = faviconDataUrl;
+ document.body.appendChild(favicon);
+
+ faviconElement = document.getElementById('favicon');
+ });
+
+ afterEach(() => {
+ document.body.removeChild(document.getElementById('favicon'));
+ });
+
+ it('should call setFavicon method', async () => {
+ wrapper.vm.mr.ciStatusFaviconPath = overlayDataUrl;
+
+ await wrapper.vm.setFaviconHelper();
+
+ expect(setFaviconOverlay).toHaveBeenCalledWith(overlayDataUrl);
+ });
+
+ it('should not call setFavicon when there is no ciStatusFaviconPath', async () => {
+ wrapper.vm.mr.ciStatusFaviconPath = null;
+ await wrapper.vm.setFaviconHelper();
+ expect(faviconElement.getAttribute('href')).toEqual(null);
+ });
+ });
+
+ describe('handleNotification', () => {
+ const data = {
+ ci_status: 'running',
+ title: 'title',
+ pipeline: { details: { status: { label: 'running-label' } } },
+ };
+
+ beforeEach(() => {
+ jest.spyOn(notify, 'notifyMe').mockImplementation(() => {});
+
+ wrapper.vm.mr.ciStatus = 'failed';
+ wrapper.vm.mr.gitlabLogo = 'logo.png';
+ });
+
+ it('should call notifyMe', () => {
+ wrapper.vm.handleNotification(data);
+
+ expect(notify.notifyMe).toHaveBeenCalledWith(
+ 'Pipeline running-label',
+ 'Pipeline running-label for "title"',
+ 'logo.png',
+ );
+ });
+
+ it('should not call notifyMe if the status has not changed', () => {
+ wrapper.vm.mr.ciStatus = data.ci_status;
+
+ wrapper.vm.handleNotification(data);
+
+ expect(notify.notifyMe).not.toHaveBeenCalled();
+ });
+
+ it('should not notify if no pipeline provided', () => {
+ wrapper.vm.handleNotification({
+ ...data,
+ pipeline: undefined,
+ });
+
+ expect(notify.notifyMe).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('resumePolling', () => {
+ it('should call stopTimer on pollingInterval', () => {
+ jest.spyOn(wrapper.vm.pollingInterval, 'resume').mockImplementation(() => {});
+
+ wrapper.vm.resumePolling();
+
+ expect(wrapper.vm.pollingInterval.resume).toHaveBeenCalled();
+ });
+ });
+
+ describe('stopPolling', () => {
+ it('should call stopTimer on pollingInterval', () => {
+ jest.spyOn(wrapper.vm.pollingInterval, 'stopTimer').mockImplementation(() => {});
+
+ wrapper.vm.stopPolling();
+
+ expect(wrapper.vm.pollingInterval.stopTimer).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('rendering deployments', () => {
+ const changes = [
+ {
+ path: 'index.html',
+ external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ];
+ const deploymentMockData = {
+ id: 15,
+ name: 'review/diplo',
+ url: '/root/acets-review-apps/environments/15',
+ stop_url: '/root/acets-review-apps/environments/15/stop',
+ metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
+ metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
+ external_url: 'http://diplo.',
+ external_url_formatted: 'diplo.',
+ deployed_at: '2017-03-22T22:44:42.258Z',
+ deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes,
+ status: SUCCESS,
+ };
+
+ beforeEach(() => {
+ wrapper.vm.mr.deployments.push(
+ {
+ ...deploymentMockData,
+ },
+ {
+ ...deploymentMockData,
+ id: deploymentMockData.id + 1,
+ },
+ );
+
+ return nextTick();
+ });
+
+ it('renders multiple deployments', () => {
+ expect(wrapper.findAll('.deploy-heading').length).toBe(2);
+ });
+
+ it('renders dropdpown with multiple file changes', () => {
+ expect(
+ wrapper.find('.js-mr-wigdet-deployment-dropdown').findAll('.js-filtered-dropdown-result')
+ .length,
+ ).toEqual(changes.length);
+ });
+ });
+
+ describe('code quality widget', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'dispatchEvent');
+ });
+ it('renders the component when refactorCodeQualityExtension is false', () => {
+ createComponent(mockData, {}, { refactorCodeQualityExtension: false });
+ expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
+ });
+
+ it('does not render the component when refactorCodeQualityExtension is true', () => {
+ createComponent(mockData, {}, { refactorCodeQualityExtension: true });
+ expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
+ });
+ });
+
+ describe('pipeline for target branch after merge', () => {
+ describe('with information for target branch pipeline', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.state = 'merged';
+ wrapper.vm.mr.mergePipeline = {
+ id: 127,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/root',
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ active: true,
+ coverage: null,
+ source: 'push',
+ created_at: '2018-10-22T11:41:35.186Z',
+ updated_at: '2018-10-22T11:41:35.433Z',
+ path: '/root/ci-web-terminal/pipelines/127',
+ flags: {
+ latest: true,
+ stuck: true,
+ auto_devops: false,
+ yaml_errors: false,
+ retryable: false,
+ cancelable: true,
+ failure_reason: false,
+ },
+ details: {
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/root/ci-web-terminal/pipelines/127',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ },
+ duration: null,
+ finished_at: null,
+ stages: [
+ {
+ name: 'test',
+ title: 'test: pending',
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/root/ci-web-terminal/pipelines/127#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ },
+ path: '/root/ci-web-terminal/pipelines/127#test',
+ dropdown_path: '/root/ci-web-terminal/pipelines/127/stage.json?stage=test',
+ },
+ ],
+ artifacts: [],
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'main',
+ path: '/root/ci-web-terminal/commits/main',
+ tag: false,
+ branch: true,
+ },
+ commit: {
+ id: 'aa1939133d373c94879becb79d91828a892ee319',
+ short_id: 'aa193913',
+ title: "Merge branch 'main-test' into 'main'",
+ created_at: '2018-10-22T11:41:33.000Z',
+ parent_ids: [
+ '4622f4dd792468993003caf2e3be978798cbe096',
+ '76598df914cdfe87132d0c3c40f80db9fa9396a4',
+ ],
+ message:
+ "Merge branch 'main-test' into 'main'\n\nUpdate .gitlab-ci.yml\n\nSee merge request root/ci-web-terminal!1",
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2018-10-22T11:41:33.000Z',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2018-10-22T11:41:33.000Z',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/root',
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ author_gravatar_url: null,
+ commit_url:
+ 'http://localhost:3000/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
+ commit_path: '/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
+ },
+ cancel_path: '/root/ci-web-terminal/pipelines/127/cancel',
+ };
+ return nextTick();
+ });
+
+ it('renders pipeline block', () => {
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(true);
+ });
+
+ describe('with post merge deployments', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.postMergeDeployments = [
+ {
+ id: 15,
+ name: 'review/diplo',
+ url: '/root/acets-review-apps/environments/15',
+ stop_url: '/root/acets-review-apps/environments/15/stop',
+ metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
+ metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
+ external_url: 'http://diplo.',
+ external_url_formatted: 'diplo.',
+ deployed_at: '2017-03-22T22:44:42.258Z',
+ deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes: [
+ {
+ path: 'index.html',
+ external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url:
+ 'http://root-main-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ],
+ status: 'success',
+ },
+ ];
+
+ return nextTick();
+ });
+
+ it('renders post deployment information', () => {
+ expect(wrapper.find('.js-post-deployment').exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('without information for target branch pipeline', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.state = 'merged';
+
+ return nextTick();
+ });
+
+ it('does not render pipeline block', () => {
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
+ });
+ });
+
+ describe('when state is not merged', () => {
+ beforeEach(() => {
+ wrapper.vm.mr.state = 'archived';
+
+ return nextTick();
+ });
+
+ it('does not render pipeline block', () => {
+ expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
+ });
+
+ it('does not render post deployment information', () => {
+ expect(wrapper.find('.js-post-deployment').exists()).toBe(false);
+ });
+ });
+ });
+
+ it('should not suggest pipelines when feature flag is not present', () => {
+ expect(findSuggestPipeline().exists()).toBe(false);
+ });
+ });
+
+ 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 }),
+ };
+
+ // 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 }),
+ ],
+ ]),
+ });
+ });
+
+ it(shouldRender ? 'renders' : 'does not render', () => {
+ expect(findSecurityMrWidget().exists()).toBe(shouldRender);
+ });
+ });
+ });
+
+ describe('suggestPipeline', () => {
+ beforeEach(() => {
+ mock.onAny().reply(200);
+ });
+
+ describe('given feature flag is enabled', () => {
+ beforeEach(async () => {
+ await createComponent();
+
+ wrapper.vm.mr.hasCI = false;
+ });
+
+ it('should suggest pipelines when none exist', () => {
+ expect(findSuggestPipeline().exists()).toBe(true);
+ });
+
+ it.each([
+ { isDismissedSuggestPipeline: true },
+ { mergeRequestAddCiConfigPath: null },
+ { hasCI: true },
+ ])('with %s, should not suggest pipeline', async (obj) => {
+ Object.assign(wrapper.vm.mr, obj);
+
+ await nextTick();
+
+ expect(findSuggestPipeline().exists()).toBe(false);
+ });
+
+ it('should allow dismiss of the suggest pipeline message', async () => {
+ await findSuggestPipelineButton().trigger('click');
+
+ expect(findSuggestPipeline().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('merge error', () => {
+ it.each`
+ state | show | showText
+ ${'closed'} | ${false} | ${'hides'}
+ ${'merged'} | ${true} | ${'shows'}
+ ${'open'} | ${true} | ${'shows'}
+ `('it $showText merge error when state is $state', ({ state, show }) => {
+ createComponent({ ...mockData, state, merge_error: 'Error!' });
+
+ expect(wrapper.find('[data-testid="merge_error"]').exists()).toBe(show);
+ });
+ });
+
+ describe('mock extension', () => {
+ let pollRequest;
+
+ beforeEach(() => {
+ pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
+
+ registerExtension(workingExtension());
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it('renders collapsed data', async () => {
+ await waitForPromises();
+
+ expect(wrapper.text()).toContain('Test extension summary count: 1');
+ });
+
+ it('renders full data', async () => {
+ await waitForPromises();
+
+ findExtensionToggleButton().trigger('click');
+
+ await nextTick();
+
+ expect(
+ wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
+ ).toBe(false);
+
+ await nextTick();
+
+ const collapsedSection = wrapper.find('[data-testid="widget-extension-collapsed-section"]');
+ expect(collapsedSection.exists()).toBe(true);
+ 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');
+
+ // Renders badge in the row
+ expect(collapsedSection.find(GlBadge).exists()).toBe(true);
+ expect(collapsedSection.find(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.find(GlButton).exists()).toBe(true);
+ expect(collapsedSection.find(GlButton).text()).toBe('Full report');
+ });
+
+ it('extension polling is not called if enablePolling flag is not passed', () => {
+ // called one time due to parent component polling (mount)
+ expect(pollRequest).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('expansion', () => {
+ it('hides collapse button', async () => {
+ registerExtension(workingExtension(false));
+ await createComponent();
+
+ expect(findExtensionToggleButton().exists()).toBe(false);
+ });
+
+ it('shows collapse button', async () => {
+ registerExtension(workingExtension(true));
+ await createComponent();
+
+ expect(findExtensionToggleButton().exists()).toBe(true);
+ });
+ });
+
+ describe('mock polling extension', () => {
+ let pollRequest;
+
+ const findWidgetTestExtension = () => wrapper.find('[data-testid="widget-extension"]');
+
+ beforeEach(() => {
+ pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
+
+ registeredExtensions.extensions = [];
+ });
+
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ describe('success - multi polling', () => {
+ it('sets data when polling is complete', async () => {
+ registerExtension(
+ multiPollingExtension([
+ () =>
+ Promise.resolve({
+ headers: { 'poll-interval': 0 },
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ () =>
+ Promise.resolve({
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ ]),
+ );
+
+ await createComponent();
+ expect(findWidgetTestExtension().html()).toContain(
+ 'Multi polling test extension reports: parsed, count: 2',
+ );
+ });
+
+ it('shows loading state until polling is complete', async () => {
+ registerExtension(
+ multiPollingExtension([
+ () =>
+ Promise.resolve({
+ headers: { 'poll-interval': 1 },
+ status: 204,
+ }),
+ () =>
+ Promise.resolve({
+ status: 200,
+ data: { reports: 'parsed' },
+ }),
+ ]),
+ );
+
+ await createComponent();
+ expect(findWidgetTestExtension().html()).toContain('Test extension loading...');
+ });
+ });
+
+ describe('success', () => {
+ it('does not make additional requests after poll is successful', async () => {
+ registerExtension(pollingExtension);
+
+ await createComponent();
+
+ expect(pollRequest).toHaveBeenCalledTimes(4);
+ });
+ });
+
+ describe('success - full data polling', () => {
+ it('sets data when polling is complete', async () => {
+ registerExtension(pollingFullDataExtension);
+
+ await createComponent();
+
+ api.trackRedisHllUserEvent.mockClear();
+ api.trackRedisCounterEvent.mockClear();
+
+ findExtensionToggleButton().trigger('click');
+
+ // The default working extension is a "warning" type, which generates a second - more specific - telemetry event for expansions
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_expand',
+ );
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_expand_warning',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_expand',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_expand_warning',
+ );
+ });
+ });
+
+ describe('error', () => {
+ it('does not make additional requests after poll has failed', async () => {
+ registerExtension(pollingErrorExtension);
+ await createComponent();
+
+ expect(pollRequest).toHaveBeenCalledTimes(4);
+ });
+
+ it('captures sentry error and displays error when poll has failed', async () => {
+ registerExtension(pollingErrorExtension);
+ await createComponent();
+
+ expect(Sentry.captureException).toHaveBeenCalled();
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
+ });
+ });
+ });
+
+ describe('mock extension errors', () => {
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it('handles collapsed data fetch errors', async () => {
+ registerExtension(collapsedDataErrorExtension);
+ await createComponent();
+
+ expect(
+ wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(),
+ ).toBe(false);
+ expect(Sentry.captureException).toHaveBeenCalled();
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
+ });
+
+ it('handles full data fetch errors', async () => {
+ registerExtension(fullDataErrorExtension);
+ await createComponent();
+
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).not.toBe('error');
+ wrapper
+ .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
+ .trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(Sentry.captureException).toHaveBeenCalledTimes(1);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
+ });
+ });
+
+ describe('telemetry', () => {
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it('triggers view events when mounted', () => {
+ registerExtension(workingExtension());
+ createComponent();
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_view',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_view',
+ );
+ });
+
+ describe('expand button', () => {
+ it('triggers expand events when clicked', async () => {
+ registerExtension(workingExtension());
+ createComponent();
+
+ await waitForPromises();
+
+ api.trackRedisHllUserEvent.mockClear();
+ api.trackRedisCounterEvent.mockClear();
+
+ findExtensionToggleButton().trigger('click');
+
+ // The default working extension is a "warning" type, which generates a second - more specific - telemetry event for expansions
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_expand',
+ );
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_expand_warning',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(2);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_expand',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_expand_warning',
+ );
+ });
+
+ it.each`
+ widgetName | nonStandardEvent
+ ${'WidgetCodeQuality'} | ${'i_testing_code_quality_widget_total'}
+ ${'WidgetTerraform'} | ${'i_testing_terraform_widget_total'}
+ ${'WidgetIssues'} | ${'i_testing_load_performance_widget_total'}
+ ${'WidgetTestReport'} | ${'i_testing_summary_widget_total'}
+ `(
+ "sends non-standard events for the '$widgetName' widget",
+ async ({ widgetName, nonStandardEvent }) => {
+ const definition = {
+ ...workingExtension(),
+ name: widgetName,
+ };
+
+ registerExtension(definition);
+ createComponent();
+
+ await waitForPromises();
+
+ api.trackRedisHllUserEvent.mockClear();
+
+ findExtensionToggleButton().trigger('click');
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(nonStandardEvent);
+ },
+ );
+ });
+
+ it('triggers the "full report clicked" events when the appropriate button is clicked', () => {
+ registerExtension(fullReportExtension);
+ createComponent();
+
+ api.trackRedisHllUserEvent.mockClear();
+ api.trackRedisCounterEvent.mockClear();
+
+ findExtensionLink('testref').trigger('click');
+
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_click_full_report',
+ );
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
+ expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
+ 'i_code_review_merge_request_widget_test_extension_count_click_full_report',
+ );
+ });
+
+ describe('when disabled', () => {
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ });
+
+ it("doesn't emit any telemetry events", async () => {
+ registerExtension(noTelemetryExtension);
+ createComponent();
+
+ await waitForPromises();
+
+ findExtensionToggleButton().trigger('click');
+ findExtensionLink('testref').trigger('click'); // The "full report" link
+
+ expect(api.trackRedisHllUserEvent).not.toHaveBeenCalled();
+ expect(api.trackRedisCounterEvent).not.toHaveBeenCalled();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/actions_spec.js
index 22562bb4ddb..22562bb4ddb 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/actions_spec.js
+++ b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/actions_spec.js
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/getters_spec.js
index dc90fef63c6..dc90fef63c6 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/getters_spec.js
+++ b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/getters_spec.js
diff --git a/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/mutations_spec.js
index a4e6788c7f6..a4e6788c7f6 100644
--- a/spec/frontend/vue_mr_widget/stores/artifacts_list/mutations_spec.js
+++ b/spec/frontend/vue_merge_request_widget/stores/artifacts_list/mutations_spec.js
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
new file mode 100644
index 00000000000..0246a8d4b0f
--- /dev/null
+++ b/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js
@@ -0,0 +1,104 @@
+import getStateKey from '~/vue_merge_request_widget/stores/get_state_key';
+
+describe('getStateKey', () => {
+ it('should return proper state name', () => {
+ const context = {
+ mergeStatus: 'checked',
+ autoMergeEnabled: false,
+ canMerge: true,
+ onlyAllowMergeIfPipelineSucceeds: false,
+ isPipelineFailed: false,
+ hasMergeableDiscussionsState: false,
+ isPipelineBlocked: false,
+ canBeMerged: false,
+ projectArchived: false,
+ branchMissing: false,
+ commitsCount: 2,
+ hasConflicts: false,
+ draft: false,
+ };
+ const bound = getStateKey.bind(context);
+
+ expect(bound()).toEqual(null);
+
+ context.canBeMerged = true;
+
+ expect(bound()).toEqual('readyToMerge');
+
+ context.autoMergeEnabled = true;
+ context.hasMergeableDiscussionsState = true;
+
+ expect(bound()).toEqual('autoMergeEnabled');
+
+ context.canMerge = true;
+ context.isSHAMismatch = true;
+
+ expect(bound()).toEqual('shaMismatch');
+
+ context.canMerge = false;
+ context.isPipelineBlocked = true;
+
+ expect(bound()).toEqual('pipelineBlocked');
+
+ context.hasMergeableDiscussionsState = true;
+ context.autoMergeEnabled = false;
+
+ expect(bound()).toEqual('unresolvedDiscussions');
+
+ context.draft = true;
+
+ expect(bound()).toEqual('draft');
+
+ context.onlyAllowMergeIfPipelineSucceeds = true;
+ context.isPipelineFailed = true;
+
+ expect(bound()).toEqual('pipelineFailed');
+
+ context.shouldBeRebased = true;
+
+ expect(bound()).toEqual('rebase');
+
+ context.hasConflicts = true;
+
+ expect(bound()).toEqual('conflicts');
+
+ context.mergeStatus = 'unchecked';
+
+ expect(bound()).toEqual('checking');
+
+ context.commitsCount = 0;
+
+ expect(bound()).toEqual('nothingToMerge');
+
+ context.commitsCount = 1;
+ context.branchMissing = true;
+
+ expect(bound()).toEqual('missingBranch');
+
+ context.projectArchived = true;
+
+ expect(bound()).toEqual('archived');
+ });
+
+ it('returns rebased state key', () => {
+ const context = {
+ mergeStatus: 'checked',
+ autoMergeEnabled: false,
+ canMerge: true,
+ onlyAllowMergeIfPipelineSucceeds: true,
+ isPipelineFailed: true,
+ hasMergeableDiscussionsState: false,
+ isPipelineBlocked: false,
+ canBeMerged: false,
+ shouldBeRebased: true,
+ projectArchived: false,
+ branchMissing: false,
+ commitsCount: 2,
+ hasConflicts: false,
+ draft: false,
+ };
+ const bound = getStateKey.bind(context);
+
+ expect(bound()).toEqual('rebase');
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/frontend/vue_merge_request_widget/stores/mr_widget_store_spec.js
index 3cdb4265ef0..3cdb4265ef0 100644
--- a/spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/frontend/vue_merge_request_widget/stores/mr_widget_store_spec.js
diff --git a/spec/frontend/vue_mr_widget/test_extensions.js b/spec/frontend/vue_merge_request_widget/test_extensions.js
index 1977f550577..1977f550577 100644
--- a/spec/frontend/vue_mr_widget/test_extensions.js
+++ b/spec/frontend/vue_merge_request_widget/test_extensions.js
diff --git a/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js b/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js
deleted file mode 100644
index 150680caa7e..00000000000
--- a/spec/frontend/vue_mr_widget/components/added_commit_message_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import AddedCommentMessage from '~/vue_merge_request_widget/components/added_commit_message.vue';
-
-let wrapper;
-
-function factory(propsData) {
- wrapper = shallowMount(AddedCommentMessage, {
- propsData: {
- isFastForwardEnabled: false,
- targetBranch: 'main',
- ...propsData,
- },
- provide: {
- glFeatures: {
- restructuredMrWidget: true.valueOf,
- },
- },
- });
-}
-
-describe('Widget added commit message', () => {
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('displays changes where not merged when state is closed', () => {
- factory({ state: 'closed' });
-
- expect(wrapper.element.outerHTML).toContain('The changes were not merged');
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js b/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js
deleted file mode 100644
index a13db2f4d72..00000000000
--- a/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import { GlButton, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Actions from '~/vue_merge_request_widget/components/extensions/actions.vue';
-
-let wrapper;
-
-function factory(propsData = {}) {
- wrapper = shallowMount(Actions, {
- propsData: { ...propsData, widget: 'test' },
- });
-}
-
-describe('MR widget extension actions', () => {
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('tertiaryButtons', () => {
- it('renders buttons', () => {
- factory({
- tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
- });
-
- expect(wrapper.findAllComponents(GlButton)).toHaveLength(1);
- });
-
- it('calls action click handler', async () => {
- const onClick = jest.fn();
-
- factory({
- tertiaryButtons: [{ text: 'hello world', onClick }],
- });
-
- await wrapper.findComponent(GlButton).vm.$emit('click');
-
- expect(onClick).toHaveBeenCalled();
- });
-
- it('renders tertiary actions in dropdown', () => {
- factory({
- tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
- });
-
- expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(1);
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js
deleted file mode 100644
index f0106914674..00000000000
--- a/spec/frontend/vue_mr_widget/components/mr_widget_memory_usage_spec.js
+++ /dev/null
@@ -1,227 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
-import waitForPromises from 'helpers/wait_for_promises';
-import MemoryUsage from '~/vue_merge_request_widget/components/deployment/memory_usage.vue';
-import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-
-const url = '/root/acets-review-apps/environments/15/deployments/1/metrics';
-const monitoringUrl = '/root/acets-review-apps/environments/15/metrics';
-
-const metricsMockData = {
- success: true,
- metrics: {
- memory_before: [
- {
- metric: {},
- value: [1495785220.607, '9572875.906976745'],
- },
- ],
- memory_after: [
- {
- metric: {},
- value: [1495787020.607, '4485853.130206379'],
- },
- ],
- memory_values: [
- {
- metric: {},
- values: [[1493716685, '4.30859375']],
- },
- ],
- },
- last_update: '2017-05-02T12:34:49.628Z',
- deployment_time: 1493718485,
-};
-
-const createComponent = () => {
- const Component = Vue.extend(MemoryUsage);
-
- return new Component({
- el: document.createElement('div'),
- propsData: {
- metricsUrl: url,
- metricsMonitoringUrl: monitoringUrl,
- memoryMetrics: [],
- deploymentTime: 0,
- hasMetrics: false,
- loadFailed: false,
- loadingMetrics: true,
- backOffRequestCounter: 0,
- },
- });
-};
-
-const messages = {
- loadingMetrics: 'Loading deployment statistics',
- hasMetrics: 'Memory usage is unchanged at 0MB',
- loadFailed: 'Failed to load deployment statistics',
- metricsUnavailable: 'Deployment statistics are not available currently',
-};
-
-describe('MemoryUsage', () => {
- let vm;
- let el;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet(`${url}.json`).reply(200);
-
- vm = createComponent();
- el = vm.$el;
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('data', () => {
- it('should have default data', () => {
- const data = MemoryUsage.data();
-
- expect(Array.isArray(data.memoryMetrics)).toBeTruthy();
- expect(data.memoryMetrics.length).toBe(0);
-
- expect(typeof data.deploymentTime).toBe('number');
- expect(data.deploymentTime).toBe(0);
-
- expect(typeof data.hasMetrics).toBe('boolean');
- expect(data.hasMetrics).toBeFalsy();
-
- expect(typeof data.loadFailed).toBe('boolean');
- expect(data.loadFailed).toBeFalsy();
-
- expect(typeof data.loadingMetrics).toBe('boolean');
- expect(data.loadingMetrics).toBeTruthy();
-
- expect(typeof data.backOffRequestCounter).toBe('number');
- expect(data.backOffRequestCounter).toBe(0);
- });
- });
-
- describe('computed', () => {
- describe('memoryChangeMessage', () => {
- it('should contain "increased" if memoryFrom value is less than memoryTo value', () => {
- vm.memoryFrom = 4.28;
- vm.memoryTo = 9.13;
-
- expect(vm.memoryChangeMessage.indexOf('increased')).not.toEqual('-1');
- });
-
- it('should contain "decreased" if memoryFrom value is less than memoryTo value', () => {
- vm.memoryFrom = 9.13;
- vm.memoryTo = 4.28;
-
- expect(vm.memoryChangeMessage.indexOf('decreased')).not.toEqual('-1');
- });
-
- it('should contain "unchanged" if memoryFrom value equal to memoryTo value', () => {
- vm.memoryFrom = 1;
- vm.memoryTo = 1;
-
- expect(vm.memoryChangeMessage.indexOf('unchanged')).not.toEqual('-1');
- });
- });
- });
-
- describe('methods', () => {
- const { metrics, deployment_time } = metricsMockData;
-
- describe('getMegabytes', () => {
- it('should return Megabytes from provided Bytes value', () => {
- const memoryInBytes = '9572875.906976745';
-
- expect(vm.getMegabytes(memoryInBytes)).toEqual('9.13');
- });
- });
-
- describe('computeGraphData', () => {
- it('should populate sparkline graph', () => {
- // ignore BoostrapVue warnings
- jest.spyOn(console, 'warn').mockImplementation();
-
- vm.computeGraphData(metrics, deployment_time);
- const { hasMetrics, memoryMetrics, deploymentTime, memoryFrom, memoryTo } = vm;
-
- expect(hasMetrics).toBeTruthy();
- expect(memoryMetrics.length).toBeGreaterThan(0);
- expect(deploymentTime).toEqual(deployment_time);
- expect(memoryFrom).toEqual('9.13');
- expect(memoryTo).toEqual('4.28');
- });
- });
-
- describe('loadMetrics', () => {
- it('should load metrics data using MRWidgetService', async () => {
- jest.spyOn(MRWidgetService, 'fetchMetrics').mockResolvedValue({
- data: metricsMockData,
- });
- jest.spyOn(vm, 'computeGraphData').mockImplementation(() => {});
-
- vm.loadMetrics();
-
- await waitForPromises();
-
- expect(MRWidgetService.fetchMetrics).toHaveBeenCalledWith(url);
- expect(vm.computeGraphData).toHaveBeenCalledWith(metrics, deployment_time);
- });
- });
- });
-
- describe('template', () => {
- it('should render template elements correctly', () => {
- expect(el.classList.contains('mr-memory-usage')).toBeTruthy();
- expect(el.querySelector('.js-usage-info')).toBeDefined();
- });
-
- it('should show loading metrics message while metrics are being loaded', async () => {
- vm.loadingMetrics = true;
- vm.hasMetrics = false;
- vm.loadFailed = false;
-
- await nextTick();
-
- expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined();
- expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadingMetrics);
- });
-
- it('should show deployment memory usage when metrics are loaded', async () => {
- // ignore BoostrapVue warnings
- jest.spyOn(console, 'warn').mockImplementation();
-
- vm.loadingMetrics = false;
- vm.hasMetrics = true;
- vm.loadFailed = false;
- vm.memoryMetrics = metricsMockData.metrics.memory_values[0].values;
-
- await nextTick();
-
- expect(el.querySelector('.memory-graph-container')).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics);
- });
-
- it('should show failure message when metrics loading failed', async () => {
- vm.loadingMetrics = false;
- vm.hasMetrics = false;
- vm.loadFailed = true;
-
- await nextTick();
-
- expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed);
- });
-
- it('should show metrics unavailable message when metrics loading failed', async () => {
- vm.loadingMetrics = false;
- vm.hasMetrics = false;
- vm.loadFailed = false;
-
- await nextTick();
-
- expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable);
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js
deleted file mode 100644
index 6db82cedd80..00000000000
--- a/spec/frontend/vue_mr_widget/components/mr_widget_rebase_spec.js
+++ /dev/null
@@ -1,292 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import WidgetRebase from '~/vue_merge_request_widget/components/states/mr_widget_rebase.vue';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-import toast from '~/vue_shared/plugins/global_toast';
-
-jest.mock('~/vue_shared/plugins/global_toast');
-
-let wrapper;
-
-function createWrapper(propsData, mergeRequestWidgetGraphql, rebaseWithoutCiUi) {
- wrapper = shallowMount(WidgetRebase, {
- propsData,
- data() {
- return {
- state: {
- rebaseInProgress: propsData.mr.rebaseInProgress,
- targetBranch: propsData.mr.targetBranch,
- userPermissions: {
- pushToSourceBranch: propsData.mr.canPushToSourceBranch,
- },
- },
- };
- },
- provide: { glFeatures: { mergeRequestWidgetGraphql, rebaseWithoutCiUi } },
- mocks: {
- $apollo: {
- queries: {
- state: { loading: false },
- },
- },
- },
- });
-}
-
-describe('Merge request widget rebase component', () => {
- const findRebaseMessage = () => wrapper.find('[data-testid="rebase-message"]');
- const findRebaseMessageText = () => findRebaseMessage().text();
- const findStandardRebaseButton = () => wrapper.find('[data-testid="standard-rebase-button"]');
- const findRebaseWithoutCiButton = () => wrapper.find('[data-testid="rebase-without-ci-button"]');
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- [true, false].forEach((mergeRequestWidgetGraphql) => {
- describe(`widget graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'disabled'}`, () => {
- describe('while rebasing', () => {
- it('should show progress message', () => {
- createWrapper(
- {
- mr: { rebaseInProgress: true },
- service: {},
- },
- mergeRequestWidgetGraphql,
- );
-
- expect(findRebaseMessageText()).toContain('Rebase in progress');
- });
- });
-
- describe('with permissions', () => {
- const rebaseMock = jest.fn().mockResolvedValue();
- const pollMock = jest.fn().mockResolvedValue({});
-
- it('renders the warning message', () => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: true,
- },
- service: {
- rebase: rebaseMock,
- poll: pollMock,
- },
- },
- mergeRequestWidgetGraphql,
- );
-
- const text = findRebaseMessageText();
-
- expect(text).toContain('Merge blocked');
- expect(text.replace(/\s\s+/g, ' ')).toContain(
- 'the source branch must be rebased onto the target branch',
- );
- });
-
- it('renders an error message when rebasing has failed', async () => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: true,
- },
- service: {
- rebase: rebaseMock,
- poll: pollMock,
- },
- },
- mergeRequestWidgetGraphql,
- );
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ rebasingError: 'Something went wrong!' });
-
- await nextTick();
- expect(findRebaseMessageText()).toContain('Something went wrong!');
- });
-
- describe('Rebase buttons with flag rebaseWithoutCiUi', () => {
- beforeEach(() => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: true,
- },
- service: {
- rebase: rebaseMock,
- poll: pollMock,
- },
- },
- mergeRequestWidgetGraphql,
- { rebaseWithoutCiUi: true },
- );
- });
-
- it('renders both buttons', () => {
- expect(findRebaseWithoutCiButton().exists()).toBe(true);
- expect(findStandardRebaseButton().exists()).toBe(true);
- });
-
- it('starts the rebase when clicking', async () => {
- findStandardRebaseButton().vm.$emit('click');
-
- await nextTick();
-
- expect(rebaseMock).toHaveBeenCalledWith({ skipCi: false });
- });
-
- it('starts the CI-skipping rebase when clicking on "Rebase without CI"', async () => {
- findRebaseWithoutCiButton().vm.$emit('click');
-
- await nextTick();
-
- expect(rebaseMock).toHaveBeenCalledWith({ skipCi: true });
- });
- });
-
- describe('Rebase button with rebaseWithoutCiUI flag disabled', () => {
- beforeEach(() => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: true,
- },
- service: {
- rebase: rebaseMock,
- poll: pollMock,
- },
- },
- mergeRequestWidgetGraphql,
- );
- });
-
- it('standard rebase button is rendered', () => {
- expect(findStandardRebaseButton().exists()).toBe(true);
- expect(findRebaseWithoutCiButton().exists()).toBe(false);
- });
-
- it('calls rebase method with skip_ci false', () => {
- findStandardRebaseButton().vm.$emit('click');
-
- expect(rebaseMock).toHaveBeenCalledWith({ skipCi: false });
- });
- });
- });
-
- describe('without permissions', () => {
- const exampleTargetBranch = 'fake-branch-to-test-with';
-
- describe('UI text', () => {
- beforeEach(() => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: false,
- targetBranch: exampleTargetBranch,
- },
- service: {},
- },
- mergeRequestWidgetGraphql,
- );
- });
-
- it('renders a message explaining user does not have permissions', () => {
- const text = findRebaseMessageText();
-
- expect(text).toContain(
- 'Merge blocked: the source branch must be rebased onto the target branch.',
- );
- expect(text).toContain('the source branch must be rebased');
- });
-
- it('renders the correct target branch name', () => {
- const elem = findRebaseMessage();
-
- expect(elem.text()).toContain(
- 'Merge blocked: the source branch must be rebased onto the target branch.',
- );
- });
- });
-
- it('does not render the "Rebase without pipeline" button with rebaseWithoutCiUI flag enabled', () => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: false,
- targetBranch: exampleTargetBranch,
- },
- service: {},
- },
- mergeRequestWidgetGraphql,
- { rebaseWithoutCiUi: true },
- );
-
- expect(findRebaseWithoutCiButton().exists()).toBe(false);
- });
-
- it('does not render the standard rebase button with rebaseWithoutCiUI flag disabled', () => {
- createWrapper(
- {
- mr: {
- rebaseInProgress: false,
- canPushToSourceBranch: false,
- targetBranch: exampleTargetBranch,
- },
- service: {},
- },
- mergeRequestWidgetGraphql,
- );
-
- expect(findStandardRebaseButton().exists()).toBe(false);
- });
- });
-
- describe('methods', () => {
- it('checkRebaseStatus', async () => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- createWrapper(
- {
- mr: {},
- service: {
- rebase() {
- return Promise.resolve();
- },
- poll() {
- return Promise.resolve({
- data: {
- rebase_in_progress: false,
- should_be_rebased: false,
- merge_error: null,
- },
- });
- },
- },
- },
- mergeRequestWidgetGraphql,
- );
-
- wrapper.vm.rebase();
-
- // Wait for the rebase request
- await nextTick();
- // Wait for the polling request
- await nextTick();
- // Wait for the eventHub to be called
- await nextTick();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetRebaseSuccess');
- expect(toast).toHaveBeenCalledWith('Rebase completed');
- });
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js
deleted file mode 100644
index c25e10c5249..00000000000
--- a/spec/frontend/vue_mr_widget/components/mr_widget_status_icon_spec.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
-import mrStatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
-
-describe('MR widget status icon component', () => {
- let wrapper;
-
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findDisabledMergeButton = () => wrapper.find('[data-testid="disabled-merge-button"]');
-
- const createWrapper = (props, mountFn = shallowMount) => {
- wrapper = mountFn(mrStatusIcon, {
- propsData: {
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('while loading', () => {
- it('renders loading icon', () => {
- createWrapper({ status: 'loading' });
-
- expect(findLoadingIcon().exists()).toBe(true);
- });
- });
-
- describe('with status icon', () => {
- it('renders success status icon', () => {
- createWrapper({ status: 'success' }, mount);
-
- expect(wrapper.find('[data-testid="status_success-icon"]').exists()).toBe(true);
- });
-
- it('renders failed status icon', () => {
- createWrapper({ status: 'failed' }, mount);
-
- expect(wrapper.find('[data-testid="status_failed-icon"]').exists()).toBe(true);
- });
- });
-
- describe('with disabled button', () => {
- it('renders a disabled button', () => {
- createWrapper({ status: 'failed', showDisabledButton: true });
-
- expect(findDisabledMergeButton().exists()).toBe(true);
- });
- });
-
- describe('without disabled button', () => {
- it('does not render a disabled button', () => {
- createWrapper({ status: 'failed' });
-
- expect(findDisabledMergeButton().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
deleted file mode 100644
index 56a0218b374..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_auto_merge_enabled_spec.js.snap
+++ /dev/null
@@ -1,145 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have correct elements 1`] = `
-<div
- class="mr-widget-body media"
->
- <gl-icon-stub
- class="gl-text-blue-500 gl-mr-3 gl-mt-1"
- name="status_scheduled"
- size="24"
- />
-
- <div
- class="media-body"
- >
- <h4
- class="gl-display-flex"
- >
- <span
- class="gl-mr-3"
- >
- <gl-sprintf-stub
- data-testid="statusText"
- message="Set by %{merge_author} to be merged automatically when the pipeline succeeds"
- />
- </span>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-cancel-auto-merge"
- data-qa-selector="cancel_auto_merge_button"
- data-testid="cancelAutomaticMergeButton"
- icon=""
- size="small"
- variant="default"
- >
-
- Cancel auto-merge
-
- </gl-button-stub>
- </h4>
-
- <section
- class="mr-info-list"
- >
- <p
- class="gl-display-flex"
- >
- <span
- class="gl-mr-3"
- >
- Does not delete the source branch
- </span>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-remove-source-branch"
- data-testid="removeSourceBranchButton"
- icon=""
- size="small"
- variant="default"
- >
-
- Delete source branch
-
- </gl-button-stub>
- </p>
- </section>
- </div>
-</div>
-`;
-
-exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have correct elements 1`] = `
-<div
- class="mr-widget-body media"
->
- <gl-icon-stub
- class="gl-text-blue-500 gl-mr-3 gl-mt-1"
- name="status_scheduled"
- size="24"
- />
-
- <div
- class="media-body"
- >
- <h4
- class="gl-display-flex"
- >
- <span
- class="gl-mr-3"
- >
- <gl-sprintf-stub
- data-testid="statusText"
- message="Set by %{merge_author} to be merged automatically when the pipeline succeeds"
- />
- </span>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-cancel-auto-merge"
- data-qa-selector="cancel_auto_merge_button"
- data-testid="cancelAutomaticMergeButton"
- icon=""
- size="small"
- variant="default"
- >
-
- Cancel auto-merge
-
- </gl-button-stub>
- </h4>
-
- <section
- class="mr-info-list"
- >
- <p
- class="gl-display-flex"
- >
- <span
- class="gl-mr-3"
- >
- Does not delete the source branch
- </span>
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-remove-source-branch"
- data-testid="removeSourceBranchButton"
- icon=""
- size="small"
- variant="default"
- >
-
- Delete source branch
-
- </gl-button-stub>
- </p>
- </section>
- </div>
-</div>
-`;
diff --git a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap b/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
deleted file mode 100644
index 98297630792..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/__snapshots__/mr_widget_pipeline_failed_spec.js.snap
+++ /dev/null
@@ -1,24 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PipelineFailed should render error message with a disabled merge button 1`] = `
-<div
- class="mr-widget-body media"
->
- <status-icon-stub
- showdisabledbutton="true"
- status="warning"
- />
-
- <div
- class="media-body space-children"
- >
- <span
- class="bold"
- >
- <gl-sprintf-stub
- message="Merge blocked: pipeline must succeed. Push a commit that fixes the failure, or %{linkStart}learn about other solutions.%{linkEnd}"
- />
- </span>
- </div>
-</div>
-`;
diff --git a/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js b/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
deleted file mode 100644
index 0e1c38437f0..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/merge_failed_pipeline_confirmation_dialog_spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
-import { trimText } from 'helpers/text_helper';
-
-describe('MergeFailedPipelineConfirmationDialog', () => {
- let wrapper;
-
- const GlModal = {
- template: `
- <div>
- <slot></slot>
- <slot name="modal-footer"></slot>
- </div>
- `,
- methods: {
- hide: jest.fn(),
- },
- };
-
- const createComponent = () => {
- wrapper = shallowMount(MergeFailedPipelineConfirmationDialog, {
- propsData: {
- visible: true,
- },
- stubs: {
- GlModal,
- },
- attachTo: document.body,
- });
- };
-
- const findModal = () => wrapper.findComponent(GlModal);
- const findMergeBtn = () => wrapper.find('[data-testid="merge-unverified-changes"]');
- const findCancelBtn = () => wrapper.find('[data-testid="merge-cancel-btn"]');
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should render informational text explaining why merging immediately can be dangerous', () => {
- expect(trimText(wrapper.text())).toContain(
- 'The latest pipeline for this merge request did not succeed. The latest changes are unverified. Are you sure you want to attempt to merge?',
- );
- });
-
- it('should emit the mergeWithFailedPipeline event', () => {
- findMergeBtn().vm.$emit('click');
-
- expect(wrapper.emitted('mergeWithFailedPipeline')).toBeTruthy();
- });
-
- it('when the cancel button is clicked should emit cancel and call hide', () => {
- jest.spyOn(findModal().vm, 'hide');
-
- findCancelBtn().vm.$emit('click');
-
- expect(wrapper.emitted('cancel')).toBeTruthy();
- expect(findModal().vm.hide).toHaveBeenCalled();
- });
-
- it('should emit cancel when the hide event is emitted', () => {
- findModal().vm.$emit('hide');
-
- expect(wrapper.emitted('cancel')).toBeTruthy();
- });
-
- it('when modal is shown it will focus the cancel button', () => {
- jest.spyOn(findCancelBtn().element, 'focus');
-
- findModal().vm.$emit('shown');
-
- expect(findCancelBtn().element.focus).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
deleted file mode 100644
index f3061d792d0..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import archivedComponent from '~/vue_merge_request_widget/components/states/mr_widget_archived.vue';
-
-describe('MRWidgetArchived', () => {
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(archivedComponent);
- vm = mountComponent(Component);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders a ci status failed icon', () => {
- expect(vm.$el.querySelector('.ci-status-icon')).not.toBeNull();
- });
-
- it('renders a disabled button', () => {
- expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled');
- expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Merge');
- });
-
- it('renders information', () => {
- expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual(
- 'Merge unavailable: merge requests are read-only on archived projects.',
- );
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
deleted file mode 100644
index 7387ed2d5e9..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_enabled_spec.js
+++ /dev/null
@@ -1,328 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import { trimText } from 'helpers/text_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import autoMergeEnabledComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue';
-import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
-
-let wrapper;
-let mergeRequestWidgetGraphqlEnabled = false;
-
-function convertPropsToGraphqlState(props) {
- return {
- autoMergeStrategy: props.autoMergeStrategy,
- cancelAutoMergePath: 'http://text.com',
- mergeUser: {
- id: props.mergeUserId,
- ...props.setToAutoMergeBy,
- },
- targetBranch: props.targetBranch,
- targetBranchCommitsPath: props.targetBranchPath,
- shouldRemoveSourceBranch: props.shouldRemoveSourceBranch,
- forceRemoveSourceBranch: props.shouldRemoveSourceBranch,
- userPermissions: {
- removeSourceBranch: props.canRemoveSourceBranch,
- },
- };
-}
-
-function factory(propsData, stateOverride = {}) {
- let state = {};
-
- if (mergeRequestWidgetGraphqlEnabled) {
- state = { ...convertPropsToGraphqlState(propsData), ...stateOverride };
- }
-
- wrapper = extendedWrapper(
- shallowMount(autoMergeEnabledComponent, {
- propsData: {
- mr: propsData,
- service: new MRWidgetService({}),
- },
- data() {
- return { state };
- },
- provide: { glFeatures: { mergeRequestWidgetGraphql: mergeRequestWidgetGraphqlEnabled } },
- mocks: {
- $apollo: {
- queries: {
- state: { loading: false },
- },
- },
- },
- }),
- );
-}
-
-const targetBranchPath = '/foo/bar';
-const targetBranch = 'foo';
-const sha = '1EA2EZ34';
-const defaultMrProps = () => ({
- shouldRemoveSourceBranch: false,
- canRemoveSourceBranch: true,
- canCancelAutomaticMerge: true,
- mergeUserId: 1,
- currentUserId: 1,
- setToAutoMergeBy: {},
- sha,
- targetBranchPath,
- targetBranch,
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
-});
-
-const getStatusText = () => wrapper.findByTestId('statusText').attributes('message');
-
-describe('MRWidgetAutoMergeEnabled', () => {
- let oldWindowGl;
-
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- oldWindowGl = window.gl;
- window.gl = {
- mrWidgetData: {
- defaultAvatarUrl: 'no_avatar.png',
- },
- };
- });
-
- afterEach(() => {
- window.gl = oldWindowGl;
- wrapper.destroy();
- wrapper = null;
- });
-
- [true, false].forEach((mergeRequestWidgetGraphql) => {
- describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'disabled'}`, () => {
- beforeEach(() => {
- mergeRequestWidgetGraphqlEnabled = mergeRequestWidgetGraphql;
- });
-
- describe('computed', () => {
- describe('canRemoveSourceBranch', () => {
- it('should return true when user is able to remove source branch', () => {
- factory({
- ...defaultMrProps(),
- });
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
- });
-
- it.each`
- mergeUserId | currentUserId
- ${2} | ${1}
- ${1} | ${2}
- `(
- 'should return false when user id is not the same with who set the MWPS',
- ({ mergeUserId, currentUserId }) => {
- factory({
- ...defaultMrProps(),
- mergeUserId,
- currentUserId,
- });
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
- },
- );
-
- it('should not find "Delete" button when shouldRemoveSourceBranch set to true', () => {
- factory({
- ...defaultMrProps(),
- shouldRemoveSourceBranch: true,
- });
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
- });
-
- it('should find "Delete" button when shouldRemoveSourceBranch overrides state.forceRemoveSourceBranch', () => {
- factory(
- {
- ...defaultMrProps(),
- shouldRemoveSourceBranch: false,
- },
- {
- forceRemoveSourceBranch: true,
- },
- );
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
- });
-
- it('should find "Delete" button when shouldRemoveSourceBranch set to false', () => {
- factory({
- ...defaultMrProps(),
- shouldRemoveSourceBranch: false,
- });
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(true);
- });
-
- it('should return false if user is not able to remove the source branch', () => {
- factory({
- ...defaultMrProps(),
- canRemoveSourceBranch: false,
- });
-
- expect(wrapper.findByTestId('removeSourceBranchButton').exists()).toBe(false);
- });
- });
-
- describe('cancelButtonText', () => {
- it('should return "Cancel" if MWPS is selected', () => {
- factory({
- ...defaultMrProps(),
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- });
-
- expect(wrapper.findByTestId('cancelAutomaticMergeButton').text()).toBe(
- 'Cancel auto-merge',
- );
- });
- });
- });
-
- describe('methods', () => {
- describe('cancelAutomaticMerge', () => {
- it('should set flag and call service then tell main component to update the widget with data', async () => {
- factory({
- ...defaultMrProps(),
- });
- const mrObj = {
- is_new_mr_data: true,
- };
- jest.spyOn(wrapper.vm.service, 'cancelAutomaticMerge').mockReturnValue(
- new Promise((resolve) => {
- resolve({
- data: mrObj,
- });
- }),
- );
-
- wrapper.vm.cancelAutomaticMerge();
-
- await waitForPromises();
-
- expect(wrapper.vm.isCancellingAutoMerge).toBeTruthy();
- if (mergeRequestWidgetGraphql) {
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- } else {
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- }
- });
- });
-
- describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', async () => {
- factory({
- ...defaultMrProps(),
- });
- jest.spyOn(wrapper.vm.service, 'merge').mockReturnValue(
- Promise.resolve({
- data: {
- status: MWPS_MERGE_STRATEGY,
- },
- }),
- );
-
- wrapper.vm.removeSourceBranch();
-
- await waitForPromises();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(wrapper.vm.service.merge).toHaveBeenCalledWith({
- sha,
- auto_merge_strategy: MWPS_MERGE_STRATEGY,
- should_remove_source_branch: true,
- });
- });
- });
- });
-
- describe('template', () => {
- it('should have correct elements', () => {
- factory({
- ...defaultMrProps(),
- });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('should disable cancel auto merge button when the action is in progress', async () => {
- factory({
- ...defaultMrProps(),
- });
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- isCancellingAutoMerge: true,
- });
-
- await nextTick();
-
- expect(wrapper.find('.js-cancel-auto-merge').props('loading')).toBe(true);
- });
-
- it('should show source branch will be deleted text when it source branch set to remove', () => {
- factory({
- ...defaultMrProps(),
- shouldRemoveSourceBranch: true,
- });
-
- const normalizedText = wrapper.text().replace(/\s+/g, ' ');
-
- expect(normalizedText).toContain('Deletes the source branch');
- expect(normalizedText).not.toContain('Does not delete the source branch');
- });
-
- it('should not show delete source branch button when user not able to delete source branch', () => {
- factory({
- ...defaultMrProps(),
- currentUserId: 4,
- });
-
- expect(wrapper.find('.js-remove-source-branch').exists()).toBe(false);
- });
-
- it('should disable delete source branch button when the action is in progress', async () => {
- factory({
- ...defaultMrProps(),
- });
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- isRemovingSourceBranch: true,
- });
-
- await nextTick();
-
- expect(wrapper.find('.js-remove-source-branch').props('loading')).toBe(true);
- });
-
- it('should render the status text as "...to merged automatically" if MWPS is selected', () => {
- factory({
- ...defaultMrProps(),
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- });
-
- expect(getStatusText()).toBe(
- 'Set by %{merge_author} to be merged automatically when the pipeline succeeds',
- );
- });
-
- it('should render the cancel button as "Cancel" if MWPS is selected', () => {
- factory({
- ...defaultMrProps(),
- autoMergeStrategy: MWPS_MERGE_STRATEGY,
- });
-
- const cancelButtonText = trimText(wrapper.find('.js-cancel-auto-merge').text());
-
- expect(cancelButtonText).toBe('Cancel auto-merge');
- });
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
deleted file mode 100644
index 24198096564..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { GlLoadingIcon, GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import AutoMergeFailedComponent from '~/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue';
-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 createComponent = (props = {}, mergeRequestWidgetGraphql = false) => {
- wrapper = shallowMount(AutoMergeFailedComponent, {
- propsData: { ...props },
- data() {
- if (mergeRequestWidgetGraphql) {
- return { mergeError: props.mr?.mergeError };
- }
-
- return {};
- },
- provide: {
- glFeatures: { mergeRequestWidgetGraphql },
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- [true, false].forEach((mergeRequestWidgetGraphql) => {
- describe(`when graphql is ${mergeRequestWidgetGraphql ? 'enabled' : 'dislabed'}`, () => {
- beforeEach(() => {
- createComponent(
- {
- mr: { mergeError },
- },
- mergeRequestWidgetGraphql,
- );
- });
-
- it('renders failed message', () => {
- expect(wrapper.text()).toContain('This merge request failed to be merged automatically');
- });
-
- it('renders merge error provided', () => {
- expect(wrapper.text()).toContain(mergeError);
- });
-
- it('render refresh button', () => {
- expect(findButton().text()).toBe('Refresh');
- });
-
- it('emits event and shows loading icon when button is clicked', async () => {
- jest.spyOn(eventHub, '$emit');
- findButton().vm.$emit('click');
-
- expect(eventHub.$emit.mock.calls[0][0]).toBe('MRWidgetUpdateRequested');
-
- await nextTick();
-
- expect(findButton().attributes('disabled')).toBe('true');
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js
deleted file mode 100644
index afe6bd0e767..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_checking_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import checkingComponent from '~/vue_merge_request_widget/components/states/mr_widget_checking.vue';
-
-describe('MRWidgetChecking', () => {
- let Component;
- let vm;
-
- beforeEach(() => {
- Component = Vue.extend(checkingComponent);
- vm = mountComponent(Component);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders disabled button', () => {
- expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled');
- });
-
- it('renders loading icon', () => {
- expect(vm.$el.querySelector('.mr-widget-icon span').classList).toContain('gl-spinner');
- });
-
- it('renders information about merging', () => {
- expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual(
- 'Checking if merge request can be merged…',
- );
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
deleted file mode 100644
index 6ae218ce6f8..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_closed_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import closedComponent from '~/vue_merge_request_widget/components/states/mr_widget_closed.vue';
-
-describe('MRWidgetClosed', () => {
- let vm;
-
- beforeEach(() => {
- const Component = Vue.extend(closedComponent);
- vm = mountComponent(Component, {
- mr: {
- metrics: {
- mergedBy: {},
- closedBy: {
- 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',
- closedAt: 'Jan 24, 2018 1:02pm UTC',
- readableMergedAt: '',
- readableClosedAt: 'less than a minute ago',
- },
- targetBranchPath: '/twitter/flight/commits/so_long_jquery',
- targetBranch: 'so_long_jquery',
- },
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders warning icon', () => {
- expect(vm.$el.querySelector('.js-ci-status-icon-warning')).not.toBeNull();
- });
-
- it('renders closed by information with author and time', () => {
- expect(
- vm.$el.querySelector('.js-mr-widget-author').textContent.trim().replace(/\s\s+/g, ' '),
- ).toContain('Closed by Administrator less than a minute ago');
- });
-
- it('links to the user that closed the MR', () => {
- expect(vm.$el.querySelector('.author-link').getAttribute('href')).toEqual(
- 'http://localhost:3000/root',
- );
- });
-
- it('renders information about the changes not being merged', () => {
- expect(
- vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' '),
- ).toContain('The changes were not merged into so_long_jquery');
- });
-
- it('renders link for target branch', () => {
- expect(vm.$el.querySelector('.label-branch').getAttribute('href')).toEqual(
- '/twitter/flight/commits/so_long_jquery',
- );
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
deleted file mode 100644
index 2796403b7d0..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlSprintf } from '@gitlab/ui';
-import { nextTick } from 'vue';
-import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
-
-describe('Commits header component', () => {
- let wrapper;
-
- const createComponent = (props) => {
- wrapper = mount(CommitsHeader, {
- stubs: {
- GlSprintf,
- },
- propsData: {
- isSquashEnabled: false,
- targetBranch: 'main',
- commitsCount: 5,
- isFastForwardEnabled: false,
- ...props,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findHeaderWrapper = () => wrapper.find('.js-mr-widget-commits-count');
- const findCommitToggle = () => wrapper.find('.commit-edit-toggle');
- const findCommitsCountMessage = () => wrapper.find('.commits-count-message');
- const findTargetBranchMessage = () => wrapper.find('.label-branch');
- const findModifyButton = () => wrapper.find('.modify-message-button');
-
- describe('when fast-forward is enabled', () => {
- beforeEach(() => {
- createComponent({
- isFastForwardEnabled: true,
- isSquashEnabled: true,
- });
- });
-
- it('has commits count message showing 1 commit', () => {
- expect(findCommitsCountMessage().text()).toBe('1 commit');
- });
-
- it('has button with modify commit message', () => {
- expect(findModifyButton().text()).toBe('Modify commit message');
- });
-
- it('does not have merge commit part of the message', () => {
- expect(findHeaderWrapper().text()).not.toContain('1 merge commit');
- });
- });
-
- describe('when collapsed', () => {
- it('toggle has aria-label equal to Expand', () => {
- createComponent();
-
- expect(findCommitToggle().attributes('aria-label')).toBe('Expand');
- });
-
- it('has a chevron-right icon', async () => {
- createComponent();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ expanded: false });
-
- await nextTick();
- expect(findCommitToggle().props('icon')).toBe('chevron-right');
- });
-
- describe('when squash is disabled', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('has commits count message showing correct amount of commits', () => {
- expect(findCommitsCountMessage().text()).toBe('5 commits');
- });
-
- it('has button with modify merge commit message', () => {
- expect(findModifyButton().text()).toBe('Modify merge commit');
- });
- });
-
- describe('when squash is enabled', () => {
- beforeEach(() => {
- createComponent({ isSquashEnabled: true });
- });
-
- it('has commits count message showing one commit when squash is enabled', () => {
- expect(findCommitsCountMessage().text()).toBe('1 commit');
- });
-
- it('has button with modify commit messages text', () => {
- expect(findModifyButton().text()).toBe('Modify commit messages');
- });
- });
-
- it('has correct target branch displayed', () => {
- createComponent();
-
- expect(findTargetBranchMessage().text()).toBe('main');
- });
-
- it('does has merge commit part of the message', () => {
- createComponent();
-
- expect(findHeaderWrapper().text()).toContain('1 merge commit');
- });
- });
-
- describe('when expanded', () => {
- beforeEach(() => {
- createComponent();
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ expanded: true });
- });
-
- it('toggle has aria-label equal to collapse', async () => {
- await nextTick();
- expect(findCommitToggle().attributes('aria-label')).toBe('Collapse');
- });
-
- it('has a chevron-down icon', async () => {
- await nextTick();
- expect(findCommitToggle().props('icon')).toBe('chevron-down');
- });
-
- it('has a collapse text', async () => {
- await nextTick();
- expect(findHeaderWrapper().text()).toBe('Collapse');
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
deleted file mode 100644
index 7a92484695c..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ /dev/null
@@ -1,252 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import { TEST_HOST } from 'helpers/test_constants';
-import { removeBreakLine } from 'helpers/text_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import ConflictsComponent from '~/vue_merge_request_widget/components/states/mr_widget_conflicts.vue';
-
-describe('MRWidgetConflicts', () => {
- let wrapper;
- let mergeRequestWidgetGraphql = null;
- const path = '/conflicts';
-
- const findResolveButton = () => wrapper.findByTestId('resolve-conflicts-button');
- const findMergeLocalButton = () => wrapper.findByTestId('merge-locally-button');
-
- const mergeConflictsText = 'Merge blocked: merge conflicts must be resolved.';
- const fastForwardMergeText =
- 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.';
- const userCannotMergeText =
- 'Users who can write to the source or target branches can resolve the conflicts.';
- const resolveConflictsBtnText = 'Resolve conflicts';
- const mergeLocallyBtnText = 'Resolve locally';
-
- async function createComponent(propsData = {}) {
- wrapper = extendedWrapper(
- shallowMount(ConflictsComponent, {
- propsData,
- provide: {
- glFeatures: {
- mergeRequestWidgetGraphql,
- },
- },
- mocks: {
- $apollo: {
- queries: {
- userPermissions: { loading: false },
- stateData: { loading: false },
- },
- },
- },
- }),
- );
-
- if (mergeRequestWidgetGraphql) {
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({
- userPermissions: {
- canMerge: propsData.mr.canMerge,
- pushToSourceBranch: propsData.mr.canPushToSourceBranch,
- },
- stateData: {
- shouldBeRebased: propsData.mr.shouldBeRebased,
- sourceBranchProtected: propsData.mr.sourceBranchProtected,
- },
- });
- }
-
- await nextTick();
- }
-
- afterEach(() => {
- mergeRequestWidgetGraphql = null;
- wrapper.destroy();
- });
-
- [false, true].forEach((featureEnabled) => {
- describe(`with GraphQL feature flag ${featureEnabled ? 'enabled' : 'disabled'}`, () => {
- beforeEach(() => {
- mergeRequestWidgetGraphql = featureEnabled;
- });
-
- // There are two permissions we need to consider:
- //
- // 1. Is the user allowed to merge to the target branch?
- // 2. Is the user allowed to push to the source branch?
- //
- // This yields 4 possible permutations that we need to test, and
- // we test them below. A user who can push to the source
- // branch should be allowed to resolve conflicts. This is
- // consistent with what the backend does.
- describe('when allowed to merge but not allowed to push to source branch', () => {
- beforeEach(async () => {
- await createComponent({
- mr: {
- canMerge: true,
- canPushToSourceBranch: false,
- conflictResolutionPath: path,
- conflictsDocsPath: '',
- },
- });
- });
-
- it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain(mergeConflictsText);
- expect(wrapper.text()).not.toContain(userCannotMergeText);
- });
-
- it('should not allow you to resolve the conflicts', () => {
- expect(wrapper.text()).not.toContain(resolveConflictsBtnText);
- });
-
- it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
- });
- });
-
- describe('when not allowed to merge but allowed to push to source branch', () => {
- beforeEach(async () => {
- await createComponent({
- mr: {
- canMerge: false,
- canPushToSourceBranch: true,
- conflictResolutionPath: path,
- conflictsDocsPath: '',
- },
- });
- });
-
- it('should tell you about conflicts', () => {
- expect(wrapper.text()).toContain(mergeConflictsText);
- expect(wrapper.text()).toContain(userCannotMergeText);
- });
-
- it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
- expect(findResolveButton().attributes('href')).toEqual(path);
- });
-
- it('should not have merge buttons', () => {
- expect(wrapper.text()).not.toContain(mergeLocallyBtnText);
- });
- });
-
- describe('when allowed to merge and push to source branch', () => {
- beforeEach(async () => {
- await createComponent({
- mr: {
- canMerge: true,
- canPushToSourceBranch: true,
- conflictResolutionPath: path,
- conflictsDocsPath: '',
- },
- });
- });
-
- it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain(mergeConflictsText);
- expect(wrapper.text()).not.toContain(userCannotMergeText);
- });
-
- it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
- expect(findResolveButton().attributes('href')).toEqual(path);
- });
-
- it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
- });
- });
-
- describe('when user does not have permission to push to source branch', () => {
- it('should show proper message', async () => {
- await createComponent({
- mr: {
- canMerge: false,
- canPushToSourceBranch: false,
- conflictsDocsPath: '',
- },
- });
-
- expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(userCannotMergeText);
- });
-
- it('should not have action buttons', async () => {
- await createComponent({
- mr: {
- canMerge: false,
- canPushToSourceBranch: false,
- conflictsDocsPath: '',
- },
- });
-
- expect(findResolveButton().exists()).toBe(false);
- expect(findMergeLocalButton().exists()).toBe(false);
- });
-
- it('should not have resolve button when no conflict resolution path', async () => {
- await createComponent({
- mr: {
- canMerge: true,
- conflictResolutionPath: null,
- conflictsDocsPath: '',
- },
- });
-
- expect(findResolveButton().exists()).toBe(false);
- });
- });
-
- describe('when fast-forward or semi-linear merge enabled', () => {
- it('should tell you to rebase locally', async () => {
- await createComponent({
- mr: {
- shouldBeRebased: true,
- conflictsDocsPath: '',
- },
- });
-
- expect(removeBreakLine(wrapper.text()).trim()).toContain(fastForwardMergeText);
- });
- });
-
- describe('when source branch protected', () => {
- beforeEach(async () => {
- await createComponent({
- mr: {
- canMerge: true,
- canPushToSourceBranch: true,
- conflictResolutionPath: TEST_HOST,
- sourceBranchProtected: true,
- conflictsDocsPath: '',
- },
- });
- });
-
- it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().exists()).toBe(true);
- });
- });
-
- describe('when source branch not protected', () => {
- beforeEach(async () => {
- await createComponent({
- mr: {
- canMerge: true,
- canPushToSourceBranch: true,
- conflictResolutionPath: TEST_HOST,
- sourceBranchProtected: false,
- conflictsDocsPath: '',
- },
- });
- });
-
- it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
- expect(findResolveButton().attributes('href')).toEqual(TEST_HOST);
- });
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
deleted file mode 100644
index 6d8e7056366..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
-import MrWidgetFailedToMerge from '~/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-
-describe('MRWidgetFailedToMerge', () => {
- const dummyIntervalId = 1337;
- let wrapper;
-
- const createComponent = (props = {}, data = {}) => {
- wrapper = shallowMount(MrWidgetFailedToMerge, {
- propsData: {
- mr: {
- mergeError: 'Merge error happened',
- },
- ...props,
- },
- data() {
- return data;
- },
- });
- };
-
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(window, 'setInterval').mockReturnValue(dummyIntervalId);
- jest.spyOn(window, 'clearInterval').mockImplementation();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('interval', () => {
- it('sets interval to refresh', () => {
- createComponent();
-
- expect(window.setInterval).toHaveBeenCalledWith(wrapper.vm.updateTimer, 1000);
- expect(wrapper.vm.intervalId).toBe(dummyIntervalId);
- });
-
- it('clears interval when destroying ', () => {
- createComponent();
- wrapper.destroy();
-
- expect(window.clearInterval).toHaveBeenCalledWith(dummyIntervalId);
- });
- });
-
- describe('mergeError', () => {
- it('removes forced line breaks', async () => {
- createComponent({ mr: { mergeError: 'contains<br />line breaks<br />' } });
-
- await nextTick();
-
- expect(wrapper.vm.mergeError).toBe('contains line breaks.');
- });
- });
-
- describe('created', () => {
- it('should disable polling', () => {
- createComponent();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('DisablePolling');
- });
- });
-
- describe('methods', () => {
- describe('refresh', () => {
- it('should emit event to request component refresh', () => {
- createComponent();
-
- expect(wrapper.vm.isRefreshing).toBe(false);
-
- wrapper.vm.refresh();
-
- expect(wrapper.vm.isRefreshing).toBe(true);
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling');
- });
- });
-
- describe('updateTimer', () => {
- it('should update timer and emit event when timer end', () => {
- createComponent();
-
- jest.spyOn(wrapper.vm, 'refresh').mockImplementation(() => {});
-
- expect(wrapper.vm.timer).toEqual(10);
-
- for (let i = 0; i < 10; i += 1) {
- expect(wrapper.vm.timer).toEqual(10 - i);
- wrapper.vm.updateTimer();
- }
-
- expect(wrapper.vm.refresh).toHaveBeenCalled();
- });
- });
- });
-
- describe('while it is refreshing', () => {
- it('renders Refresing now', async () => {
- createComponent({}, { isRefreshing: true });
-
- await nextTick();
-
- expect(wrapper.find('.js-refresh-label').text().trim()).toBe('Refreshing now');
- });
- });
-
- describe('while it is not regresing', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders warning icon and disabled merge button', () => {
- expect(wrapper.find('.js-ci-status-icon-warning')).not.toBeNull();
- expect(wrapper.find(StatusIcon).props('showDisabledButton')).toBe(true);
- });
-
- it('renders given error', () => {
- expect(wrapper.find('.has-error-message').text().trim()).toBe('Merge error happened.');
- });
-
- it('renders refresh button', () => {
- expect(
- wrapper.find('[data-testid="merge-request-failed-refresh-button"]').text().trim(),
- ).toBe('Refresh now');
- });
-
- it('renders remaining time', () => {
- expect(wrapper.find('.has-custom-error').text().trim()).toBe(
- 'Refreshing in 10 seconds to show the updated status...',
- );
- });
- });
-
- it('should just generic merge failed message if merge_error is not available', async () => {
- createComponent({ mr: { mergeError: null } });
-
- await nextTick();
-
- expect(wrapper.text().trim()).toContain('Merge failed.');
- expect(wrapper.text().trim()).not.toContain('Merge error happened.');
- });
-
- it('should show refresh label when refresh requested', async () => {
- createComponent();
-
- wrapper.vm.refresh();
-
- await nextTick();
-
- expect(wrapper.text().trim()).not.toContain('Merge failed. Refreshing');
- expect(wrapper.text().trim()).toContain('Refreshing now');
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
deleted file mode 100644
index 29ee7e0010f..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ /dev/null
@@ -1,235 +0,0 @@
-import { getByRole } from '@testing-library/dom';
-import Vue, { nextTick } from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-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 eventHub from '~/vue_merge_request_widget/event_hub';
-
-describe('MRWidgetMerged', () => {
- let vm;
- const targetBranch = 'foo';
- const selectors = {
- get copyMergeShaButton() {
- return vm.$el.querySelector('button.js-mr-merged-copy-sha');
- },
- get mergeCommitShaLink() {
- return vm.$el.querySelector('a.js-mr-merged-commit-sha');
- },
- };
-
- 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',
- },
- 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() {},
- };
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- vm = mountComponent(Component, { mr, service });
- });
-
- afterEach(() => {
- vm.$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);
- });
-
- it('returns true when all are true', () => {
- vm.mr.isRemovingSourceBranch = true;
- vm.mr.canRemoveSourceBranch = true;
- vm.isMakingRequest = true;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
- });
- });
-
- describe('shouldShowSourceBranchRemoving', () => {
- it('should correct value when fields changed', () => {
- vm.mr.sourceBranchRemoved = false;
-
- expect(vm.shouldShowSourceBranchRemoving).toEqual(false);
-
- vm.mr.sourceBranchRemoved = true;
-
- expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
-
- vm.mr.sourceBranchRemoved = false;
- vm.isMakingRequest = true;
-
- expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
-
- vm.isMakingRequest = false;
- vm.mr.isRemovingSourceBranch = true;
-
- expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
- });
- });
- });
-
- 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',
- },
- });
- }),
- );
-
- vm.removeSourceBranch();
-
- await waitForPromises();
-
- const args = eventHub.$emit.mock.calls[0];
-
- expect(vm.isMakingRequest).toEqual(true);
- expect(args[0]).toEqual('MRWidgetUpdateRequested');
- expect(args[1]).not.toThrow();
- });
- });
- });
-
- it('calls dispatchDocumentEvent to load in the modal component', () => {
- expect(document.dispatchEvent).toHaveBeenCalledWith(new CustomEvent('merged:UpdateActions'));
- });
-
- it('emits event to open the revert modal on revert button click', () => {
- const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
-
- getByRole(vm.$el, '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', () => {
- const eventHubSpy = jest.spyOn(modalEventHub, '$emit');
-
- getByRole(vm.$el, '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');
- });
-
- it('renders branch information', () => {
- expect(vm.$el.textContent).toContain('The changes were merged into');
- expect(vm.$el.textContent).toContain(targetBranch);
- });
-
- it('renders information about branch being deleted', () => {
- expect(vm.$el.textContent).toContain('The source branch has been deleted');
- });
-
- it('shows revert and cherry-pick buttons', () => {
- expect(vm.$el.textContent).toContain('Revert');
- expect(vm.$el.textContent).toContain('Cherry-pick');
- });
-
- it('shows button to copy commit SHA to clipboard', () => {
- expect(selectors.copyMergeShaButton).not.toBe(null);
- expect(selectors.copyMergeShaButton.dataset.clipboardText).toBe(vm.mr.mergeCommitSha);
- });
-
- it('hides button to copy commit SHA if SHA does not exist', async () => {
- vm.mr.mergeCommitSha = null;
-
- await nextTick();
-
- expect(selectors.copyMergeShaButton).toBe(null);
- expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
- });
-
- it('shows merge commit SHA link', () => {
- expect(selectors.mergeCommitShaLink).not.toBe(null);
- expect(selectors.mergeCommitShaLink.text).toContain(vm.mr.shortMergeCommitSha);
- expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath);
- });
-
- it('should not show source branch deleted text', async () => {
- vm.mr.sourceBranchRemoved = false;
-
- await nextTick();
-
- expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
- });
-
- it('should show source branch deleting text', async () => {
- vm.mr.isRemovingSourceBranch = true;
- vm.mr.sourceBranchRemoved = false;
-
- await nextTick();
-
- expect(vm.$el.innerText).toContain('The source branch is being deleted');
- expect(vm.$el.innerText).not.toContain('The source branch has been deleted');
- });
-
- it('should use mergedEvent mergedAt as tooltip title', () => {
- expect(vm.$el.querySelector('time').getAttribute('title')).toBe('Jan 24, 2018 1:02pm UTC');
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
deleted file mode 100644
index e16c897a49b..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_merging_spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import simplePoll from '~/lib/utils/simple_poll';
-import MrWidgetMerging from '~/vue_merge_request_widget/components/states/mr_widget_merging.vue';
-
-jest.mock('~/lib/utils/simple_poll', () =>
- jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
-);
-
-describe('MRWidgetMerging', () => {
- let wrapper;
-
- const GlEmoji = { template: '<img />' };
- beforeEach(() => {
- wrapper = shallowMount(MrWidgetMerging, {
- propsData: {
- mr: {
- targetBranchPath: '/branch-path',
- targetBranch: 'branch',
- transitionStateMachine() {},
- },
- service: {
- poll: jest.fn().mockResolvedValue(),
- },
- },
- stubs: {
- GlEmoji,
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders information about merge request being merged', () => {
- expect(
- wrapper
- .find('.media-body')
- .text()
- .trim()
- .replace(/\s\s+/g, ' ')
- .replace(/[\r\n]+/g, ' '),
- ).toContain('Merging!');
- });
-
- it('renders branch information', () => {
- expect(
- wrapper
- .find('.mr-info-list')
- .text()
- .trim()
- .replace(/\s\s+/g, ' ')
- .replace(/[\r\n]+/g, ' '),
- ).toEqual('Merges changes into branch');
-
- expect(wrapper.find('a').attributes('href')).toBe('/branch-path');
- });
-
- describe('initiateMergePolling', () => {
- it('should call simplePoll', () => {
- wrapper.vm.initiateMergePolling();
-
- expect(simplePoll).toHaveBeenCalledWith(expect.any(Function), { timeout: 0 });
- });
-
- it('should call handleMergePolling', () => {
- jest.spyOn(wrapper.vm, 'handleMergePolling').mockImplementation(() => {});
-
- wrapper.vm.initiateMergePolling();
-
- expect(wrapper.vm.handleMergePolling).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
deleted file mode 100644
index c7c0b69425d..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import Vue, { nextTick } from 'vue';
-import NothingToMerge from '~/vue_merge_request_widget/components/states/nothing_to_merge.vue';
-
-describe('NothingToMerge', () => {
- describe('template', () => {
- const Component = Vue.extend(NothingToMerge);
- const newBlobPath = '/foo';
- const vm = new Component({
- el: document.createElement('div'),
- propsData: {
- mr: { newBlobPath },
- },
- });
-
- it('should have correct elements', () => {
- expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(vm.$el.querySelector('[data-testid="createFileButton"]').href).toContain(newBlobPath);
- expect(vm.$el.innerText).toContain('Use merge requests to propose changes to your project');
- });
-
- it('should not show new blob link if there is no link available', () => {
- vm.mr.newBlobPath = null;
- nextTick(() => {
- expect(vm.$el.querySelector('[data-testid="createFileButton"]')).toEqual(null);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
deleted file mode 100644
index 3e0840fef4e..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
-import PipelineFailed from '~/vue_merge_request_widget/components/states/pipeline_failed.vue';
-
-describe('PipelineFailed', () => {
- let wrapper;
-
- const createComponent = () => {
- wrapper = shallowMount(PipelineFailed);
- };
-
- const findStatusIcon = () => wrapper.find(statusIcon);
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('should render error message with a disabled merge button', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('merge button should be disabled', () => {
- expect(findStatusIcon().props('showDisabledButton')).toBe(true);
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
deleted file mode 100644
index 46d90ddc83c..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ /dev/null
@@ -1,905 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import { GlSprintf } from '@gitlab/ui';
-import VueApollo from 'vue-apollo';
-import produce from 'immer';
-import readyToMergeResponse from 'test_fixtures/graphql/merge_requests/states/ready_to_merge.query.graphql.json';
-import waitForPromises from 'helpers/wait_for_promises';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import readyToMergeQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/ready_to_merge.query.graphql';
-import simplePoll from '~/lib/utils/simple_poll';
-import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
-import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
-import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
-import ReadyToMerge from '~/vue_merge_request_widget/components/states/ready_to_merge.vue';
-import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
-import MergeFailedPipelineConfirmationDialog from '~/vue_merge_request_widget/components/states/merge_failed_pipeline_confirmation_dialog.vue';
-import { MWPS_MERGE_STRATEGY } from '~/vue_merge_request_widget/constants';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-
-jest.mock('~/lib/utils/simple_poll', () =>
- jest.fn().mockImplementation(jest.requireActual('~/lib/utils/simple_poll').default),
-);
-jest.mock('~/commons/nav/user_merge_requests', () => ({
- refreshUserMergeRequestCounts: jest.fn(),
-}));
-
-const commitMessage = readyToMergeResponse.data.project.mergeRequest.defaultMergeCommitMessage;
-const squashCommitMessage =
- readyToMergeResponse.data.project.mergeRequest.defaultSquashCommitMessage;
-const commitMessageWithDescription =
- readyToMergeResponse.data.project.mergeRequest.defaultMergeCommitMessageWithDescription;
-const createTestMr = (customConfig) => {
- const mr = {
- isPipelineActive: false,
- pipeline: null,
- isPipelineFailed: false,
- isPipelinePassing: false,
- isMergeAllowed: true,
- isApproved: true,
- onlyAllowMergeIfPipelineSucceeds: false,
- ffOnlyEnabled: false,
- hasCI: false,
- ciStatus: null,
- sha: '12345678',
- squash: false,
- squashIsEnabledByDefault: false,
- squashIsReadonly: false,
- squashIsSelected: false,
- commitMessage,
- squashCommitMessage,
- commitMessageWithDescription,
- defaultMergeCommitMessage: commitMessage,
- defaultSquashCommitMessage: squashCommitMessage,
- shouldRemoveSourceBranch: true,
- canRemoveSourceBranch: false,
- targetBranch: 'main',
- preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY,
- availableAutoMergeStrategies: [MWPS_MERGE_STRATEGY],
- mergeImmediatelyDocsPath: 'path/to/merge/immediately/docs',
- transitionStateMachine: (transition) => eventHub.$emit('StateMachineValueChanged', transition),
- translateStateToMachine: () => this.transitionStateMachine(),
- state: 'open',
- };
-
- Object.assign(mr, customConfig.mr);
-
- return mr;
-};
-
-const createTestService = () => ({
- merge: jest.fn(),
- poll: jest.fn().mockResolvedValue(),
-});
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-let wrapper;
-let readyToMergeResponseSpy;
-
-const findMergeButton = () => wrapper.find('[data-testid="merge-button"]');
-const findPipelineFailedConfirmModal = () =>
- wrapper.findComponent(MergeFailedPipelineConfirmationDialog);
-
-const createReadyToMergeResponse = (customMr) => {
- return produce(readyToMergeResponse, (draft) => {
- Object.assign(draft.data.project.mergeRequest, customMr);
- });
-};
-
-const createComponent = (
- customConfig = {},
- mergeRequestWidgetGraphql = false,
- restructuredMrWidget = false,
-) => {
- wrapper = shallowMount(ReadyToMerge, {
- localVue,
- propsData: {
- mr: createTestMr(customConfig),
- service: createTestService(),
- },
- provide: {
- glFeatures: {
- mergeRequestWidgetGraphql,
- restructuredMrWidget,
- },
- },
- stubs: {
- CommitEdit,
- },
- apolloProvider: createMockApollo([[readyToMergeQuery, readyToMergeResponseSpy]]),
- });
-};
-
-const findCheckboxElement = () => wrapper.find(SquashBeforeMerge);
-const findCommitsHeaderElement = () => wrapper.find(CommitsHeader);
-const findCommitEditElements = () => wrapper.findAll(CommitEdit);
-const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
-const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
-const findTipLink = () => wrapper.find(GlSprintf);
-const findCommitEditWithInputId = (inputId) =>
- findCommitEditElements().wrappers.find((x) => x.props('inputId') === inputId);
-const findMergeCommitMessage = () => findCommitEditWithInputId('merge-message-edit').props('value');
-const findSquashCommitMessage = () =>
- findCommitEditWithInputId('squash-message-edit').props('value');
-
-const triggerApprovalUpdated = () => eventHub.$emit('ApprovalUpdated');
-
-describe('ReadyToMerge', () => {
- beforeEach(() => {
- readyToMergeResponseSpy = jest.fn().mockResolvedValueOnce(readyToMergeResponse);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('computed', () => {
- describe('isAutoMergeAvailable', () => {
- it('should return true when at least one merge strategy is available', () => {
- createComponent();
-
- expect(wrapper.vm.isAutoMergeAvailable).toBe(true);
- });
-
- it('should return false when no merge strategies are available', () => {
- createComponent({ mr: { availableAutoMergeStrategies: [] } });
-
- expect(wrapper.vm.isAutoMergeAvailable).toBe(false);
- });
- });
-
- describe('status', () => {
- it('defaults to success', () => {
- createComponent({ mr: { pipeline: true, availableAutoMergeStrategies: [] } });
-
- expect(wrapper.vm.status).toEqual('success');
- });
-
- it('returns failed when MR has CI but also has an unknown status', () => {
- createComponent({ mr: { hasCI: true } });
-
- expect(wrapper.vm.status).toEqual('failed');
- });
-
- it('returns default when MR has no pipeline', () => {
- createComponent({ mr: { availableAutoMergeStrategies: [] } });
-
- expect(wrapper.vm.status).toEqual('success');
- });
-
- it('returns pending when pipeline is active', () => {
- createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
-
- expect(wrapper.vm.status).toEqual('pending');
- });
-
- it('returns failed when pipeline is failed', () => {
- createComponent({
- mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
- });
-
- expect(wrapper.vm.status).toEqual('failed');
- });
- });
-
- describe('Merge Button Variant', () => {
- it('defaults to confirm class', () => {
- createComponent({
- mr: { availableAutoMergeStrategies: [] },
- });
-
- expect(findMergeButton().attributes('variant')).toBe('confirm');
- });
- });
-
- describe('status icon', () => {
- it('defaults to tick icon', () => {
- createComponent();
-
- expect(wrapper.vm.iconClass).toEqual('success');
- });
-
- it('shows tick for success status', () => {
- createComponent({ mr: { pipeline: true } });
-
- expect(wrapper.vm.iconClass).toEqual('success');
- });
-
- it('shows tick for pending status', () => {
- createComponent({ mr: { pipeline: {}, isPipelineActive: true } });
-
- expect(wrapper.vm.iconClass).toEqual('success');
- });
- });
-
- describe('mergeButtonText', () => {
- it('should return "Merge" when no auto merge strategies are available', () => {
- createComponent({ mr: { availableAutoMergeStrategies: [] } });
-
- expect(wrapper.vm.mergeButtonText).toEqual('Merge');
- });
-
- it('should return "Merge in progress"', async () => {
- createComponent();
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ isMergingImmediately: true });
-
- await nextTick();
-
- expect(wrapper.vm.mergeButtonText).toEqual('Merge in progress');
- });
-
- it('should return "Merge when pipeline succeeds" when the MWPS auto merge strategy is available', () => {
- createComponent({
- mr: { isMergingImmediately: false, preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY },
- });
-
- expect(wrapper.vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
- });
- });
-
- describe('autoMergeText', () => {
- it('should return Merge when pipeline succeeds', () => {
- createComponent({ mr: { preferredAutoMergeStrategy: MWPS_MERGE_STRATEGY } });
-
- expect(wrapper.vm.autoMergeText).toEqual('Merge when pipeline succeeds');
- });
- });
-
- describe('shouldShowMergeImmediatelyDropdown', () => {
- it('should return false if no pipeline is active', () => {
- createComponent({
- mr: { isPipelineActive: false, onlyAllowMergeIfPipelineSucceeds: false },
- });
-
- expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
- });
-
- it('should return false if "Pipelines must succeed" is enabled for the current project', () => {
- createComponent({ mr: { isPipelineActive: true, onlyAllowMergeIfPipelineSucceeds: true } });
-
- expect(wrapper.vm.shouldShowMergeImmediatelyDropdown).toBe(false);
- });
- });
-
- describe('isMergeButtonDisabled', () => {
- it('should return false with initial data', () => {
- createComponent({ mr: { isMergeAllowed: true } });
-
- expect(wrapper.vm.isMergeButtonDisabled).toBe(false);
- });
-
- it('should return true when there is no commit message', () => {
- createComponent({ mr: { isMergeAllowed: true, commitMessage: '' } });
-
- expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
- });
-
- it('should return true if merge is not allowed', () => {
- createComponent({
- mr: {
- isMergeAllowed: false,
- availableAutoMergeStrategies: [],
- onlyAllowMergeIfPipelineSucceeds: true,
- },
- });
-
- expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
- });
-
- it('should return true when the vm instance is making request', async () => {
- createComponent({ mr: { isMergeAllowed: true } });
-
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ isMakingRequest: true });
-
- await nextTick();
-
- expect(wrapper.vm.isMergeButtonDisabled).toBe(true);
- });
- });
- });
-
- describe('methods', () => {
- describe('handleMergeButtonClick', () => {
- const response = (status) => ({
- data: {
- status,
- },
- });
-
- beforeEach(() => {
- readyToMergeResponseSpy = jest
- .fn()
- .mockResolvedValueOnce(createReadyToMergeResponse({ squash: true, squashOnMerge: true }))
- .mockResolvedValue(
- createReadyToMergeResponse({
- squash: true,
- squashOnMerge: true,
- defaultMergeCommitMessage: '',
- defaultSquashCommitMessage: '',
- }),
- );
- });
-
- it('should handle merge when pipeline succeeds', async () => {
- createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest
- .spyOn(wrapper.vm.service, 'merge')
- .mockResolvedValue(response('merge_when_pipeline_succeeds'));
- // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ removeSourceBranch: false });
-
- wrapper.vm.handleMergeButtonClick(true);
-
- await waitForPromises();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
- expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
- transition: 'start-auto-merge',
- });
-
- const params = wrapper.vm.service.merge.mock.calls[0][0];
-
- expect(params).toEqual(
- expect.objectContaining({
- sha: wrapper.vm.mr.sha,
- commit_message: wrapper.vm.mr.commitMessage,
- should_remove_source_branch: false,
- auto_merge_strategy: 'merge_when_pipeline_succeeds',
- }),
- );
- });
-
- it('should handle merge failed', async () => {
- createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('failed'));
- wrapper.vm.handleMergeButtonClick(false, true);
-
- await waitForPromises();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
-
- const params = wrapper.vm.service.merge.mock.calls[0][0];
-
- expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.auto_merge_strategy).toBeUndefined();
- });
-
- it('should handle merge action accepted case', async () => {
- createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('success'));
- jest.spyOn(wrapper.vm.mr, 'transitionStateMachine');
- wrapper.vm.handleMergeButtonClick();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('StateMachineValueChanged', {
- transition: 'start-merge',
- });
-
- await waitForPromises();
-
- expect(wrapper.vm.mr.transitionStateMachine).toHaveBeenCalledWith({
- transition: 'start-merge',
- });
-
- const params = wrapper.vm.service.merge.mock.calls[0][0];
-
- expect(params.should_remove_source_branch).toBeTruthy();
- expect(params.auto_merge_strategy).toBeUndefined();
- });
-
- it('hides edit commit message', async () => {
- createComponent({}, true, true);
-
- await waitForPromises();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'merge').mockResolvedValue(response('success'));
-
- await wrapper
- .findComponent('[data-testid="widget_edit_commit_message"]')
- .vm.$emit('input', true);
-
- expect(wrapper.findComponent('[data-testid="edit_commit_message"]').exists()).toBe(true);
-
- wrapper.vm.handleMergeButtonClick();
-
- await waitForPromises();
-
- expect(wrapper.findComponent('[data-testid="edit_commit_message"]').exists()).toBe(false);
- });
- });
-
- describe('initiateRemoveSourceBranchPolling', () => {
- it('should emit event and call simplePoll', () => {
- createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- wrapper.vm.initiateRemoveSourceBranchPolling();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
- expect(simplePoll).toHaveBeenCalled();
- });
- });
-
- describe('handleRemoveBranchPolling', () => {
- const response = (state) => ({
- data: {
- source_branch_exists: state,
- },
- });
-
- it('should call start and stop polling when MR merged', async () => {
- createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(false));
-
- let cpc = false; // continuePollingCalled
- let spc = false; // stopPollingCalled
-
- wrapper.vm.handleRemoveBranchPolling(
- () => {
- cpc = true;
- },
- () => {
- spc = true;
- },
- );
-
- await waitForPromises();
-
- expect(wrapper.vm.service.poll).toHaveBeenCalled();
-
- const args = eventHub.$emit.mock.calls[0];
-
- expect(args[0]).toEqual('MRWidgetUpdateRequested');
- expect(args[1]).toBeDefined();
- args[1]();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
-
- expect(cpc).toBeFalsy();
- expect(spc).toBeTruthy();
- });
-
- it('should continue polling until MR is merged', async () => {
- createComponent();
-
- jest.spyOn(wrapper.vm.service, 'poll').mockResolvedValue(response(true));
-
- let cpc = false; // continuePollingCalled
- let spc = false; // stopPollingCalled
-
- wrapper.vm.handleRemoveBranchPolling(
- () => {
- cpc = true;
- },
- () => {
- spc = true;
- },
- );
-
- await waitForPromises();
-
- expect(cpc).toBeTruthy();
- expect(spc).toBeFalsy();
- });
- });
- });
-
- describe('Remove source branch checkbox', () => {
- describe('when user can merge but cannot delete branch', () => {
- it('should be disabled in the rendered output', () => {
- createComponent();
-
- expect(wrapper.find('#remove-source-branch-input').exists()).toBe(false);
- });
- });
-
- describe('when user can merge and can delete branch', () => {
- beforeEach(() => {
- createComponent({
- mr: { canRemoveSourceBranch: true },
- });
- });
-
- it('isRemoveSourceBranchButtonDisabled should be false', () => {
- expect(wrapper.find('#remove-source-branch-input').props('disabled')).toBe(undefined);
- });
- });
- });
-
- describe('render children components', () => {
- describe('squash checkbox', () => {
- it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
- createComponent({
- mr: { commitsCount: 2, enableSquashBeforeMerge: true },
- });
-
- expect(findCheckboxElement().exists()).toBeTruthy();
- });
-
- it('should not be rendered when squash before merge is disabled', () => {
- createComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: false } });
-
- expect(findCheckboxElement().exists()).toBeFalsy();
- });
-
- it('should be rendered when there is only 1 commit', () => {
- createComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
-
- expect(findCheckboxElement().exists()).toBe(true);
- });
-
- describe('squash options', () => {
- it.each`
- squashState | state | prop | expectation
- ${'squashIsReadonly'} | ${'enabled'} | ${'isDisabled'} | ${false}
- ${'squashIsSelected'} | ${'selected'} | ${'value'} | ${false}
- ${'squashIsSelected'} | ${'unselected'} | ${'value'} | ${false}
- `(
- 'is $state when squashIsReadonly returns $expectation ',
- ({ squashState, prop, expectation }) => {
- createComponent({
- mr: { commitsCount: 2, enableSquashBeforeMerge: true, [squashState]: expectation },
- });
-
- expect(findCheckboxElement().props(prop)).toBe(expectation);
- },
- );
-
- it('is not rendered for "Do not allow" option', () => {
- createComponent({
- mr: {
- commitsCount: 2,
- enableSquashBeforeMerge: true,
- squashIsReadonly: true,
- squashIsSelected: false,
- },
- });
-
- expect(findCheckboxElement().exists()).toBe(false);
- });
- });
- });
-
- describe('commits count collapsible header', () => {
- it('should be rendered when fast-forward is disabled', () => {
- createComponent();
-
- expect(findCommitsHeaderElement().exists()).toBeTruthy();
- });
-
- describe('when fast-forward is enabled', () => {
- it('should be rendered if squash and squash before are enabled and there is more than 1 commit', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- enableSquashBeforeMerge: true,
- squashIsSelected: true,
- commitsCount: 2,
- },
- });
-
- expect(findCommitsHeaderElement().exists()).toBeTruthy();
- });
-
- it('should not be rendered if squash before merge is disabled', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- enableSquashBeforeMerge: false,
- squash: true,
- commitsCount: 2,
- },
- });
-
- expect(findCommitsHeaderElement().exists()).toBeFalsy();
- });
-
- it('should not be rendered if squash is disabled', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squash: false,
- enableSquashBeforeMerge: true,
- commitsCount: 2,
- },
- });
-
- expect(findCommitsHeaderElement().exists()).toBeFalsy();
- });
-
- it('should not be rendered if commits count is 1', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squash: true,
- enableSquashBeforeMerge: true,
- commitsCount: 1,
- },
- });
-
- expect(findCommitsHeaderElement().exists()).toBeFalsy();
- });
- });
- });
-
- describe('commits edit components', () => {
- describe('when fast-forward merge is enabled', () => {
- it('should not be rendered if squash is disabled', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squash: false,
- enableSquashBeforeMerge: true,
- commitsCount: 2,
- },
- });
-
- expect(findCommitEditElements().length).toBe(0);
- });
-
- it('should not be rendered if squash before merge is disabled', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squash: true,
- enableSquashBeforeMerge: false,
- commitsCount: 2,
- },
- });
-
- expect(findCommitEditElements().length).toBe(0);
- });
-
- it('should not be rendered if there is only one commit', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squash: true,
- enableSquashBeforeMerge: true,
- commitsCount: 1,
- },
- });
-
- expect(findCommitEditElements().length).toBe(0);
- });
-
- it('should have one edit component if squash is enabled and there is more than 1 commit', () => {
- createComponent({
- mr: {
- ffOnlyEnabled: true,
- squashIsSelected: true,
- enableSquashBeforeMerge: true,
- commitsCount: 2,
- },
- });
-
- expect(findCommitEditElements().length).toBe(1);
- expect(findFirstCommitEditLabel()).toBe('Squash commit message');
- });
- });
-
- it('should have one edit component when squash is disabled', () => {
- createComponent();
-
- expect(findCommitEditElements().length).toBe(1);
- });
-
- it('should have two edit components when squash is enabled and there is more than 1 commit', () => {
- createComponent({
- mr: {
- commitsCount: 2,
- squashIsSelected: true,
- enableSquashBeforeMerge: true,
- },
- });
-
- expect(findCommitEditElements().length).toBe(2);
- });
-
- it('should have two edit components when squash is enabled and there is more than 1 commit and mergeRequestWidgetGraphql is enabled', async () => {
- createComponent(
- {
- mr: {
- commitsCount: 2,
- squashIsSelected: true,
- enableSquashBeforeMerge: true,
- },
- },
- true,
- );
-
- // 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: false,
- state: {
- ...createTestMr({}),
- userPermissions: {},
- squash: true,
- mergeable: true,
- commitCount: 2,
- commitsWithoutMergeCommits: {},
- },
- });
- await nextTick();
-
- expect(findCommitEditElements().length).toBe(2);
- });
-
- it('should have one edit components when squash is enabled and there is 1 commit only', () => {
- createComponent({
- mr: {
- commitsCount: 1,
- squash: true,
- enableSquashBeforeMerge: true,
- },
- });
-
- expect(findCommitEditElements().length).toBe(1);
- });
-
- it('should have correct edit merge commit label', () => {
- createComponent();
-
- expect(findFirstCommitEditLabel()).toBe('Merge commit message');
- });
-
- it('should have correct edit squash commit label', () => {
- createComponent({
- mr: {
- commitsCount: 2,
- squashIsSelected: true,
- enableSquashBeforeMerge: true,
- },
- });
-
- expect(findFirstCommitEditLabel()).toBe('Squash commit message');
- });
- });
-
- describe('commits dropdown', () => {
- it('should not be rendered if squash is disabled', () => {
- createComponent();
-
- expect(findCommitDropdownElement().exists()).toBeFalsy();
- });
-
- it('should be rendered if squash is enabled and there is more than 1 commit', () => {
- createComponent({
- mr: { enableSquashBeforeMerge: true, squashIsSelected: true, commitsCount: 2 },
- });
-
- expect(findCommitDropdownElement().exists()).toBeTruthy();
- });
- });
-
- it('renders a tip including a link to docs on templates', () => {
- createComponent();
-
- expect(findTipLink().exists()).toBe(true);
- });
- });
-
- describe('Merge request project settings', () => {
- describe('when the merge commit merge method is enabled', () => {
- beforeEach(() => {
- createComponent({
- mr: { ffOnlyEnabled: false },
- });
- });
-
- it('should not show fast forward message', () => {
- expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(false);
- });
- });
-
- describe('when the fast-forward merge method is enabled', () => {
- beforeEach(() => {
- createComponent({
- mr: { ffOnlyEnabled: true },
- });
- });
-
- it('should show fast forward message', () => {
- expect(wrapper.find('.mr-fast-forward-message').exists()).toBe(true);
- });
- });
- });
-
- describe('Merge button when pipeline has failed', () => {
- beforeEach(() => {
- createComponent({
- mr: { pipeline: {}, isPipelineFailed: true, availableAutoMergeStrategies: [] },
- });
- });
-
- it('should display the correct merge text', () => {
- expect(findMergeButton().text()).toBe('Merge...');
- });
-
- it('should display confirmation modal when merge button is clicked', async () => {
- expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: false });
-
- await findMergeButton().vm.$emit('click');
-
- expect(findPipelineFailedConfirmModal().props()).toEqual({ visible: true });
- });
- });
-
- describe('updating graphql data triggers commit message update when default changed', () => {
- const UPDATED_MERGE_COMMIT_MESSAGE = 'New merge message from BE';
- const UPDATED_SQUASH_COMMIT_MESSAGE = 'New squash message from BE';
- const USER_COMMIT_MESSAGE = 'Merge message provided manually by user';
-
- const createDefaultGqlComponent = () =>
- createComponent({ mr: { commitsCount: 2, enableSquashBeforeMerge: true } }, true);
-
- beforeEach(() => {
- readyToMergeResponseSpy = jest
- .fn()
- .mockResolvedValueOnce(createReadyToMergeResponse({ squash: true, squashOnMerge: true }))
- .mockResolvedValue(
- createReadyToMergeResponse({
- squash: true,
- squashOnMerge: true,
- defaultMergeCommitMessage: UPDATED_MERGE_COMMIT_MESSAGE,
- defaultSquashCommitMessage: UPDATED_SQUASH_COMMIT_MESSAGE,
- }),
- );
- });
-
- describe.each`
- desc | finderFn | initialValue | updatedValue | inputId
- ${'merge commit message'} | ${findMergeCommitMessage} | ${commitMessage} | ${UPDATED_MERGE_COMMIT_MESSAGE} | ${'#merge-message-edit'}
- ${'squash commit message'} | ${findSquashCommitMessage} | ${squashCommitMessage} | ${UPDATED_SQUASH_COMMIT_MESSAGE} | ${'#squash-message-edit'}
- `('with $desc', ({ finderFn, initialValue, updatedValue, inputId }) => {
- it('should have initial value', async () => {
- createDefaultGqlComponent();
-
- await waitForPromises();
-
- expect(finderFn()).toBe(initialValue);
- });
-
- it('should have updated value after graphql refetch', async () => {
- createDefaultGqlComponent();
- await waitForPromises();
-
- triggerApprovalUpdated();
- await waitForPromises();
-
- expect(finderFn()).toBe(updatedValue);
- });
-
- it('should not update if user has touched', async () => {
- createDefaultGqlComponent();
- await waitForPromises();
-
- const input = wrapper.find(inputId);
- input.element.value = USER_COMMIT_MESSAGE;
- input.trigger('input');
-
- triggerApprovalUpdated();
- await waitForPromises();
-
- expect(finderFn()).toBe(USER_COMMIT_MESSAGE);
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
deleted file mode 100644
index 4998147c6b6..00000000000
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import Vue, { nextTick } from 'vue';
-import waitForPromises from 'helpers/wait_for_promises';
-import WorkInProgress from '~/vue_merge_request_widget/components/states/work_in_progress.vue';
-import toast from '~/vue_shared/plugins/global_toast';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-
-jest.mock('~/vue_shared/plugins/global_toast');
-
-const createComponent = () => {
- const Component = Vue.extend(WorkInProgress);
- const mr = {
- title: 'The best MR ever',
- removeWIPPath: '/path/to/remove/wip',
- };
- const service = {
- removeWIP() {},
- };
- return new Component({
- el: document.createElement('div'),
- propsData: { mr, service },
- });
-};
-
-describe('Wip', () => {
- describe('props', () => {
- it('should have props', () => {
- const { mr, service } = WorkInProgress.props;
-
- expect(mr.type instanceof Object).toBeTruthy();
- expect(mr.required).toBeTruthy();
-
- expect(service.type instanceof Object).toBeTruthy();
- expect(service.required).toBeTruthy();
- });
- });
-
- describe('data', () => {
- it('should have default data', () => {
- const vm = createComponent();
-
- expect(vm.isMakingRequest).toBeFalsy();
- });
- });
-
- describe('methods', () => {
- const mrObj = {
- is_new_mr_data: true,
- };
-
- describe('handleRemoveDraft', () => {
- it('should make a request to service and handle response', async () => {
- const vm = createComponent();
-
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- jest.spyOn(vm.service, 'removeWIP').mockReturnValue(
- new Promise((resolve) => {
- resolve({
- data: mrObj,
- });
- }),
- );
-
- vm.handleRemoveDraft();
-
- await waitForPromises();
-
- expect(vm.isMakingRequest).toBeTruthy();
- expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- expect(toast).toHaveBeenCalledWith('Marked as ready. Merging is now allowed.');
- });
- });
- });
-
- describe('template', () => {
- let vm;
- let el;
-
- beforeEach(() => {
- vm = createComponent();
- el = vm.$el;
- });
-
- it('should have correct elements', () => {
- expect(el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(el.innerText).toContain(
- "Merge blocked: merge request must be marked as ready. It's still marked as draft.",
- );
- expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
- expect(el.querySelector('button').innerText).toContain('Merge');
- expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain(
- 'Mark as ready',
- );
- });
-
- it('should not show removeWIP button is user cannot update MR', async () => {
- vm.mr.removeWIPPath = '';
-
- await nextTick();
-
- expect(el.querySelector('.js-remove-draft')).toEqual(null);
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
deleted file mode 100644
index b3af5eba364..00000000000
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ /dev/null
@@ -1,1266 +0,0 @@
-import { GlBadge, GlLink, GlIcon, GlButton, GlDropdown } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import * as Sentry from '@sentry/browser';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
-import api from '~/api';
-import axios from '~/lib/utils/axios_utils';
-import Poll from '~/lib/utils/poll';
-import { setFaviconOverlay } from '~/lib/utils/favicon';
-import notify from '~/lib/utils/notify';
-import SmartInterval from '~/smart_interval';
-import {
- registerExtension,
- registeredExtensions,
-} from '~/vue_merge_request_widget/components/extensions';
-import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/constants';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
-import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
-import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
-import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql';
-import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
-import mockData from './mock_data';
-import {
- workingExtension,
- collapsedDataErrorExtension,
- fullDataErrorExtension,
- fullReportExtension,
- noTelemetryExtension,
- pollingExtension,
- pollingFullDataExtension,
- pollingErrorExtension,
- multiPollingExtension,
-} from './test_extensions';
-
-jest.mock('~/api.js');
-
-jest.mock('~/smart_interval');
-
-jest.mock('~/lib/utils/favicon');
-
-jest.mock('@sentry/browser', () => ({
- setExtra: jest.fn(),
- setExtras: jest.fn(),
- captureMessage: jest.fn(),
- captureException: jest.fn(),
-}));
-
-Vue.use(VueApollo);
-
-describe('MrWidgetOptions', () => {
- let wrapper;
- let mock;
-
- const COLLABORATION_MESSAGE = 'Members who can merge are allowed to add commits';
- const findExtensionToggleButton = () =>
- wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]');
- const findExtensionLink = (linkHref) =>
- wrapper.find(`[data-testid="widget-extension"] [href="${linkHref}"]`);
-
- beforeEach(() => {
- gl.mrWidgetData = { ...mockData };
- gon.features = { asyncMrWidget: true };
-
- mock = new MockAdapter(axios);
- mock.onGet(mockData.merge_request_widget_path).reply(() => [200, { ...mockData }]);
- mock.onGet(mockData.merge_request_cached_widget_path).reply(() => [200, { ...mockData }]);
- });
-
- afterEach(() => {
- mock.restore();
- wrapper.destroy();
-
- gl.mrWidgetData = {};
- gon.features = {};
- });
-
- const createComponent = (mrData = mockData, options = {}) => {
- wrapper = mount(MrWidgetOptions, {
- propsData: {
- mrData: { ...mrData },
- },
- ...options,
- });
-
- return axios.waitForAll();
- };
-
- const findSuggestPipeline = () => wrapper.find('[data-testid="mr-suggest-pipeline"]');
- const findSuggestPipelineButton = () => findSuggestPipeline().find('button');
- const findSecurityMrWidget = () => wrapper.find('[data-testid="security-mr-widget"]');
-
- describe('default', () => {
- beforeEach(() => {
- jest.spyOn(document, 'dispatchEvent');
- return createComponent();
- });
-
- describe('data', () => {
- it('should instantiate Store and Service', () => {
- expect(wrapper.vm.mr).toBeDefined();
- expect(wrapper.vm.service).toBeDefined();
- });
- });
-
- describe('computed', () => {
- describe('componentName', () => {
- it.each`
- state | componentName
- ${'merged'} | ${'mr-widget-merged'}
- ${'conflicts'} | ${'mr-widget-conflicts'}
- ${'shaMismatch'} | ${'sha-mismatch'}
- `('should translate $state into $componentName', ({ state, componentName }) => {
- wrapper.vm.mr.state = state;
-
- expect(wrapper.vm.componentName).toEqual(componentName);
- });
- });
-
- describe('shouldRenderPipelines', () => {
- it('should return true when hasCI is true', () => {
- wrapper.vm.mr.hasCI = true;
-
- expect(wrapper.vm.shouldRenderPipelines).toBeTruthy();
- });
-
- it('should return false when hasCI is false', () => {
- wrapper.vm.mr.hasCI = false;
-
- expect(wrapper.vm.shouldRenderPipelines).toBeFalsy();
- });
- });
-
- describe('shouldRenderRelatedLinks', () => {
- it('should return false for the initial data', () => {
- expect(wrapper.vm.shouldRenderRelatedLinks).toBeFalsy();
- });
-
- it('should return true if there is relatedLinks in MR', () => {
- Vue.set(wrapper.vm.mr, 'relatedLinks', {});
-
- expect(wrapper.vm.shouldRenderRelatedLinks).toBeTruthy();
- });
- });
-
- describe('shouldRenderSourceBranchRemovalStatus', () => {
- beforeEach(() => {
- wrapper.vm.mr.state = 'readyToMerge';
- });
-
- it('should return true when cannot remove source branch and branch will be removed', () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
-
- expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(true);
- });
-
- it('should return false when can remove source branch and branch will be removed', () => {
- wrapper.vm.mr.canRemoveSourceBranch = true;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
-
- expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
- });
-
- it('should return false when cannot remove source branch and branch will not be removed', () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = false;
-
- expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
- });
-
- it('should return false when in merged state', () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
- wrapper.vm.mr.state = 'merged';
-
- expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
- });
-
- it('should return false when in nothing to merge state', () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
- wrapper.vm.mr.state = 'nothingToMerge';
-
- expect(wrapper.vm.shouldRenderSourceBranchRemovalStatus).toEqual(false);
- });
- });
-
- describe('shouldRenderCollaborationStatus', () => {
- describe('when collaboration is allowed', () => {
- beforeEach(() => {
- wrapper.vm.mr.allowCollaboration = true;
- });
-
- describe('when merge request is opened', () => {
- beforeEach(() => {
- wrapper.vm.mr.isOpen = true;
- return nextTick();
- });
-
- it('should render collaboration status', () => {
- expect(wrapper.text()).toContain(COLLABORATION_MESSAGE);
- });
- });
-
- describe('when merge request is not opened', () => {
- beforeEach(() => {
- wrapper.vm.mr.isOpen = false;
- return nextTick();
- });
-
- it('should not render collaboration status', () => {
- expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
- });
- });
- });
-
- describe('when collaboration is not allowed', () => {
- beforeEach(() => {
- wrapper.vm.mr.allowCollaboration = false;
- });
-
- describe('when merge request is opened', () => {
- beforeEach(() => {
- wrapper.vm.mr.isOpen = true;
- return nextTick();
- });
-
- it('should not render collaboration status', () => {
- expect(wrapper.text()).not.toContain(COLLABORATION_MESSAGE);
- });
- });
- });
- });
-
- describe('showMergePipelineForkWarning', () => {
- describe('when the source project and target project are the same', () => {
- beforeEach(() => {
- Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
- Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
- Vue.set(wrapper.vm.mr, 'targetProjectId', 1);
- return nextTick();
- });
-
- it('should be false', () => {
- expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
- });
- });
-
- describe('when merge pipelines are not enabled', () => {
- beforeEach(() => {
- Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', false);
- Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
- Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
- return nextTick();
- });
-
- it('should be false', () => {
- expect(wrapper.vm.showMergePipelineForkWarning).toEqual(false);
- });
- });
-
- describe('when merge pipelines are enabled _and_ the source project and target project are different', () => {
- beforeEach(() => {
- Vue.set(wrapper.vm.mr, 'mergePipelinesEnabled', true);
- Vue.set(wrapper.vm.mr, 'sourceProjectId', 1);
- Vue.set(wrapper.vm.mr, 'targetProjectId', 2);
- return nextTick();
- });
-
- it('should be true', () => {
- expect(wrapper.vm.showMergePipelineForkWarning).toEqual(true);
- });
- });
- });
-
- describe('formattedHumanAccess', () => {
- it('when user is a tool admin but not a member of project', () => {
- wrapper.vm.mr.humanAccess = null;
-
- expect(wrapper.vm.formattedHumanAccess).toEqual('');
- });
-
- it('when user a member of the project', () => {
- wrapper.vm.mr.humanAccess = 'Owner';
-
- expect(wrapper.vm.formattedHumanAccess).toEqual('owner');
- });
- });
- });
-
- describe('methods', () => {
- describe('checkStatus', () => {
- let cb;
- let isCbExecuted;
-
- beforeEach(() => {
- jest.spyOn(wrapper.vm.service, 'checkStatus').mockResolvedValue({ data: mockData });
- jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation(() => {});
- jest.spyOn(wrapper.vm, 'handleNotification').mockImplementation(() => {});
-
- isCbExecuted = false;
- cb = () => {
- isCbExecuted = true;
- };
- });
-
- it('should tell service to check status if document is visible', () => {
- wrapper.vm.checkStatus(cb);
-
- return nextTick().then(() => {
- expect(wrapper.vm.service.checkStatus).toHaveBeenCalled();
- expect(wrapper.vm.mr.setData).toHaveBeenCalled();
- expect(wrapper.vm.handleNotification).toHaveBeenCalledWith(mockData);
- expect(isCbExecuted).toBeTruthy();
- });
- });
- });
-
- describe('initPolling', () => {
- it('should call SmartInterval', () => {
- wrapper.vm.initPolling();
-
- expect(SmartInterval).toHaveBeenCalledWith(
- expect.objectContaining({
- callback: wrapper.vm.checkStatus,
- }),
- );
- });
- });
-
- describe('initDeploymentsPolling', () => {
- it('should call SmartInterval', () => {
- wrapper.vm.initDeploymentsPolling();
-
- expect(SmartInterval).toHaveBeenCalledWith(
- expect.objectContaining({
- callback: wrapper.vm.fetchPreMergeDeployments,
- }),
- );
- });
- });
-
- describe('fetchDeployments', () => {
- it('should fetch deployments', () => {
- jest
- .spyOn(wrapper.vm.service, 'fetchDeployments')
- .mockResolvedValue({ data: [{ id: 1, status: SUCCESS }] });
-
- wrapper.vm.fetchPreMergeDeployments();
-
- return nextTick().then(() => {
- expect(wrapper.vm.service.fetchDeployments).toHaveBeenCalled();
- expect(wrapper.vm.mr.deployments.length).toEqual(1);
- expect(wrapper.vm.mr.deployments[0].id).toBe(1);
- });
- });
- });
-
- describe('fetchActionsContent', () => {
- it('should fetch content of Cherry Pick and Revert modals', () => {
- jest
- .spyOn(wrapper.vm.service, 'fetchMergeActionsContent')
- .mockResolvedValue({ data: 'hello world' });
-
- wrapper.vm.fetchActionsContent();
-
- return nextTick().then(() => {
- expect(wrapper.vm.service.fetchMergeActionsContent).toHaveBeenCalled();
- expect(document.body.textContent).toContain('hello world');
- expect(document.dispatchEvent).toHaveBeenCalledWith(
- new CustomEvent('merged:UpdateActions'),
- );
- });
- });
- });
-
- describe('bindEventHubListeners', () => {
- it.each`
- event | method | methodArgs
- ${'MRWidgetUpdateRequested'} | ${'checkStatus'} | ${(x) => [x]}
- ${'MRWidgetRebaseSuccess'} | ${'checkStatus'} | ${(x) => [x, true]}
- ${'FetchActionsContent'} | ${'fetchActionsContent'} | ${() => []}
- ${'EnablePolling'} | ${'resumePolling'} | ${() => []}
- ${'DisablePolling'} | ${'stopPolling'} | ${() => []}
- `('should bind to $event', ({ event, method, methodArgs }) => {
- jest.spyOn(wrapper.vm, method).mockImplementation();
-
- const eventArg = {};
- eventHub.$emit(event, eventArg);
-
- expect(wrapper.vm[method]).toHaveBeenCalledWith(...methodArgs(eventArg));
- });
-
- it('should bind to SetBranchRemoveFlag', () => {
- expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(false);
-
- eventHub.$emit('SetBranchRemoveFlag', [true]);
-
- expect(wrapper.vm.mr.isRemovingSourceBranch).toBe(true);
- });
-
- it('should bind to FailedToMerge', () => {
- wrapper.vm.mr.state = '';
- wrapper.vm.mr.mergeError = '';
-
- const mergeError = 'Something bad happened!';
- eventHub.$emit('FailedToMerge', mergeError);
-
- expect(wrapper.vm.mr.state).toBe('failedToMerge');
- expect(wrapper.vm.mr.mergeError).toBe(mergeError);
- });
-
- it('should bind to UpdateWidgetData', () => {
- jest.spyOn(wrapper.vm.mr, 'setData').mockImplementation();
-
- const data = { ...mockData };
- eventHub.$emit('UpdateWidgetData', data);
-
- expect(wrapper.vm.mr.setData).toHaveBeenCalledWith(data);
- });
- });
-
- describe('setFavicon', () => {
- let faviconElement;
-
- beforeEach(() => {
- const favicon = document.createElement('link');
- favicon.setAttribute('id', 'favicon');
- favicon.dataset.originalHref = faviconDataUrl;
- document.body.appendChild(favicon);
-
- faviconElement = document.getElementById('favicon');
- });
-
- afterEach(() => {
- document.body.removeChild(document.getElementById('favicon'));
- });
-
- it('should call setFavicon method', async () => {
- wrapper.vm.mr.ciStatusFaviconPath = overlayDataUrl;
-
- await wrapper.vm.setFaviconHelper();
-
- expect(setFaviconOverlay).toHaveBeenCalledWith(overlayDataUrl);
- });
-
- it('should not call setFavicon when there is no ciStatusFaviconPath', async () => {
- wrapper.vm.mr.ciStatusFaviconPath = null;
- await wrapper.vm.setFaviconHelper();
- expect(faviconElement.getAttribute('href')).toEqual(null);
- });
- });
-
- describe('handleNotification', () => {
- const data = {
- ci_status: 'running',
- title: 'title',
- pipeline: { details: { status: { label: 'running-label' } } },
- };
-
- beforeEach(() => {
- jest.spyOn(notify, 'notifyMe').mockImplementation(() => {});
-
- wrapper.vm.mr.ciStatus = 'failed';
- wrapper.vm.mr.gitlabLogo = 'logo.png';
- });
-
- it('should call notifyMe', () => {
- wrapper.vm.handleNotification(data);
-
- expect(notify.notifyMe).toHaveBeenCalledWith(
- 'Pipeline running-label',
- 'Pipeline running-label for "title"',
- 'logo.png',
- );
- });
-
- it('should not call notifyMe if the status has not changed', () => {
- wrapper.vm.mr.ciStatus = data.ci_status;
-
- wrapper.vm.handleNotification(data);
-
- expect(notify.notifyMe).not.toHaveBeenCalled();
- });
-
- it('should not notify if no pipeline provided', () => {
- wrapper.vm.handleNotification({
- ...data,
- pipeline: undefined,
- });
-
- expect(notify.notifyMe).not.toHaveBeenCalled();
- });
- });
-
- describe('resumePolling', () => {
- it('should call stopTimer on pollingInterval', () => {
- jest.spyOn(wrapper.vm.pollingInterval, 'resume').mockImplementation(() => {});
-
- wrapper.vm.resumePolling();
-
- expect(wrapper.vm.pollingInterval.resume).toHaveBeenCalled();
- });
- });
-
- describe('stopPolling', () => {
- it('should call stopTimer on pollingInterval', () => {
- jest.spyOn(wrapper.vm.pollingInterval, 'stopTimer').mockImplementation(() => {});
-
- wrapper.vm.stopPolling();
-
- expect(wrapper.vm.pollingInterval.stopTimer).toHaveBeenCalled();
- });
- });
- });
-
- describe('rendering relatedLinks', () => {
- beforeEach(() => {
- return createComponent({
- ...mockData,
- issues_links: {
- closing: `
- <a class="close-related-link" href="#">
- Close
- </a>
- `,
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders if there are relatedLinks', () => {
- expect(wrapper.find('.close-related-link').exists()).toBe(true);
- });
-
- it('does not render if state is nothingToMerge', async () => {
- wrapper.vm.mr.state = stateKey.nothingToMerge;
- await nextTick();
- expect(wrapper.find('.close-related-link').exists()).toBe(false);
- });
- });
-
- describe('rendering source branch removal status', () => {
- it('renders when user cannot remove branch and branch should be removed', async () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
- wrapper.vm.mr.state = 'readyToMerge';
-
- await nextTick();
- const tooltip = wrapper.find('[data-testid="question-o-icon"]');
-
- expect(wrapper.text()).toContain('Deletes the source branch');
- expect(tooltip.attributes('title')).toBe(
- 'A user with write access to the source branch selected this option',
- );
- });
-
- it('does not render in merged state', async () => {
- wrapper.vm.mr.canRemoveSourceBranch = false;
- wrapper.vm.mr.shouldRemoveSourceBranch = true;
- wrapper.vm.mr.state = 'merged';
-
- await nextTick();
- expect(wrapper.text()).toContain('The source branch has been deleted');
- expect(wrapper.text()).not.toContain('Deletes the source branch');
- });
- });
-
- describe('rendering deployments', () => {
- const changes = [
- {
- path: 'index.html',
- external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/index.html',
- },
- {
- path: 'imgs/gallery.html',
- external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
- },
- {
- path: 'about/',
- external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/about/',
- },
- ];
- const deploymentMockData = {
- id: 15,
- name: 'review/diplo',
- url: '/root/acets-review-apps/environments/15',
- stop_url: '/root/acets-review-apps/environments/15/stop',
- metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
- metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
- external_url: 'http://diplo.',
- external_url_formatted: 'diplo.',
- deployed_at: '2017-03-22T22:44:42.258Z',
- deployed_at_formatted: 'Mar 22, 2017 10:44pm',
- changes,
- status: SUCCESS,
- };
-
- beforeEach(() => {
- wrapper.vm.mr.deployments.push(
- {
- ...deploymentMockData,
- },
- {
- ...deploymentMockData,
- id: deploymentMockData.id + 1,
- },
- );
-
- return nextTick();
- });
-
- it('renders multiple deployments', () => {
- expect(wrapper.findAll('.deploy-heading').length).toBe(2);
- });
-
- it('renders dropdpown with multiple file changes', () => {
- expect(
- wrapper.find('.js-mr-wigdet-deployment-dropdown').findAll('.js-filtered-dropdown-result')
- .length,
- ).toEqual(changes.length);
- });
- });
-
- describe('code quality widget', () => {
- beforeEach(() => {
- jest.spyOn(document, 'dispatchEvent');
- });
- it('renders the component when refactorCodeQualityExtension is false', () => {
- createComponent(mockData, {}, { refactorCodeQualityExtension: false });
- expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
- });
-
- it('does not render the component when refactorCodeQualityExtension is true', () => {
- createComponent(mockData, {}, { refactorCodeQualityExtension: true });
- expect(wrapper.find('.js-codequality-widget').exists()).toBe(true);
- });
- });
-
- describe('pipeline for target branch after merge', () => {
- describe('with information for target branch pipeline', () => {
- beforeEach(() => {
- wrapper.vm.mr.state = 'merged';
- wrapper.vm.mr.mergePipeline = {
- id: 127,
- user: {
- id: 1,
- name: 'Administrator',
- username: 'root',
- state: 'active',
- avatar_url: null,
- web_url: 'http://localhost:3000/root',
- status_tooltip_html: null,
- path: '/root',
- },
- active: true,
- coverage: null,
- source: 'push',
- created_at: '2018-10-22T11:41:35.186Z',
- updated_at: '2018-10-22T11:41:35.433Z',
- path: '/root/ci-web-terminal/pipelines/127',
- flags: {
- latest: true,
- stuck: true,
- auto_devops: false,
- yaml_errors: false,
- retryable: false,
- cancelable: true,
- failure_reason: false,
- },
- details: {
- status: {
- icon: 'status_pending',
- text: 'pending',
- label: 'pending',
- group: 'pending',
- tooltip: 'pending',
- has_details: true,
- details_path: '/root/ci-web-terminal/pipelines/127',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
- },
- duration: null,
- finished_at: null,
- stages: [
- {
- name: 'test',
- title: 'test: pending',
- status: {
- icon: 'status_pending',
- text: 'pending',
- label: 'pending',
- group: 'pending',
- tooltip: 'pending',
- has_details: true,
- details_path: '/root/ci-web-terminal/pipelines/127#test',
- illustration: null,
- favicon:
- '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
- },
- path: '/root/ci-web-terminal/pipelines/127#test',
- dropdown_path: '/root/ci-web-terminal/pipelines/127/stage.json?stage=test',
- },
- ],
- artifacts: [],
- manual_actions: [],
- scheduled_actions: [],
- },
- ref: {
- name: 'main',
- path: '/root/ci-web-terminal/commits/main',
- tag: false,
- branch: true,
- },
- commit: {
- id: 'aa1939133d373c94879becb79d91828a892ee319',
- short_id: 'aa193913',
- title: "Merge branch 'main-test' into 'main'",
- created_at: '2018-10-22T11:41:33.000Z',
- parent_ids: [
- '4622f4dd792468993003caf2e3be978798cbe096',
- '76598df914cdfe87132d0c3c40f80db9fa9396a4',
- ],
- message:
- "Merge branch 'main-test' into 'main'\n\nUpdate .gitlab-ci.yml\n\nSee merge request root/ci-web-terminal!1",
- author_name: 'Administrator',
- author_email: 'admin@example.com',
- authored_date: '2018-10-22T11:41:33.000Z',
- committer_name: 'Administrator',
- committer_email: 'admin@example.com',
- committed_date: '2018-10-22T11:41:33.000Z',
- author: {
- id: 1,
- name: 'Administrator',
- username: 'root',
- state: 'active',
- avatar_url: null,
- web_url: 'http://localhost:3000/root',
- status_tooltip_html: null,
- path: '/root',
- },
- author_gravatar_url: null,
- commit_url:
- 'http://localhost:3000/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
- commit_path: '/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
- },
- cancel_path: '/root/ci-web-terminal/pipelines/127/cancel',
- };
- return nextTick();
- });
-
- it('renders pipeline block', () => {
- expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(true);
- });
-
- describe('with post merge deployments', () => {
- beforeEach(() => {
- wrapper.vm.mr.postMergeDeployments = [
- {
- id: 15,
- name: 'review/diplo',
- url: '/root/acets-review-apps/environments/15',
- stop_url: '/root/acets-review-apps/environments/15/stop',
- metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
- metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
- external_url: 'http://diplo.',
- external_url_formatted: 'diplo.',
- deployed_at: '2017-03-22T22:44:42.258Z',
- deployed_at_formatted: 'Mar 22, 2017 10:44pm',
- changes: [
- {
- path: 'index.html',
- external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/index.html',
- },
- {
- path: 'imgs/gallery.html',
- external_url:
- 'http://root-main-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
- },
- {
- path: 'about/',
- external_url: 'http://root-main-patch-91341.volatile-watch.surge.sh/about/',
- },
- ],
- status: 'success',
- },
- ];
-
- return nextTick();
- });
-
- it('renders post deployment information', () => {
- expect(wrapper.find('.js-post-deployment').exists()).toBe(true);
- });
- });
- });
-
- describe('without information for target branch pipeline', () => {
- beforeEach(() => {
- wrapper.vm.mr.state = 'merged';
-
- return nextTick();
- });
-
- it('does not render pipeline block', () => {
- expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
- });
- });
-
- describe('when state is not merged', () => {
- beforeEach(() => {
- wrapper.vm.mr.state = 'archived';
-
- return nextTick();
- });
-
- it('does not render pipeline block', () => {
- expect(wrapper.find('.js-post-merge-pipeline').exists()).toBe(false);
- });
-
- it('does not render post deployment information', () => {
- expect(wrapper.find('.js-post-deployment').exists()).toBe(false);
- });
- });
- });
-
- it('should not suggest pipelines when feature flag is not present', () => {
- expect(findSuggestPipeline().exists()).toBe(false);
- });
- });
-
- 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 }),
- };
-
- // 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 }),
- ],
- ]),
- });
- });
-
- it(shouldRender ? 'renders' : 'does not render', () => {
- expect(findSecurityMrWidget().exists()).toBe(shouldRender);
- });
- });
- });
-
- describe('suggestPipeline', () => {
- beforeEach(() => {
- mock.onAny().reply(200);
- });
-
- describe('given feature flag is enabled', () => {
- beforeEach(async () => {
- await createComponent();
-
- wrapper.vm.mr.hasCI = false;
- });
-
- it('should suggest pipelines when none exist', () => {
- expect(findSuggestPipeline().exists()).toBe(true);
- });
-
- it.each([
- { isDismissedSuggestPipeline: true },
- { mergeRequestAddCiConfigPath: null },
- { hasCI: true },
- ])('with %s, should not suggest pipeline', async (obj) => {
- Object.assign(wrapper.vm.mr, obj);
-
- await nextTick();
-
- expect(findSuggestPipeline().exists()).toBe(false);
- });
-
- it('should allow dismiss of the suggest pipeline message', async () => {
- await findSuggestPipelineButton().trigger('click');
-
- expect(findSuggestPipeline().exists()).toBe(false);
- });
- });
- });
-
- describe('merge error', () => {
- it.each`
- state | show | showText
- ${'closed'} | ${false} | ${'hides'}
- ${'merged'} | ${true} | ${'shows'}
- ${'open'} | ${true} | ${'shows'}
- `('it $showText merge error when state is $state', ({ state, show }) => {
- createComponent({ ...mockData, state, merge_error: 'Error!' });
-
- expect(wrapper.find('[data-testid="merge_error"]').exists()).toBe(show);
- });
- });
-
- describe('mock extension', () => {
- let pollRequest;
-
- beforeEach(() => {
- pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
-
- registerExtension(workingExtension());
-
- createComponent();
- });
-
- afterEach(() => {
- registeredExtensions.extensions = [];
- });
-
- it('renders collapsed data', async () => {
- await waitForPromises();
-
- expect(wrapper.text()).toContain('Test extension summary count: 1');
- });
-
- it('renders full data', async () => {
- await waitForPromises();
-
- findExtensionToggleButton().trigger('click');
-
- await nextTick();
-
- expect(
- wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
- ).toBe(false);
-
- await nextTick();
-
- const collapsedSection = wrapper.find('[data-testid="widget-extension-collapsed-section"]');
- expect(collapsedSection.exists()).toBe(true);
- 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');
-
- // Renders badge in the row
- expect(collapsedSection.find(GlBadge).exists()).toBe(true);
- expect(collapsedSection.find(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.find(GlButton).exists()).toBe(true);
- expect(collapsedSection.find(GlButton).text()).toBe('Full report');
- });
-
- it('extension polling is not called if enablePolling flag is not passed', () => {
- // called one time due to parent component polling (mount)
- expect(pollRequest).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('expansion', () => {
- it('hides collapse button', async () => {
- registerExtension(workingExtension(false));
- await createComponent();
-
- expect(findExtensionToggleButton().exists()).toBe(false);
- });
-
- it('shows collapse button', async () => {
- registerExtension(workingExtension(true));
- await createComponent();
-
- expect(findExtensionToggleButton().exists()).toBe(true);
- });
- });
-
- describe('mock polling extension', () => {
- let pollRequest;
-
- const findWidgetTestExtension = () => wrapper.find('[data-testid="widget-extension"]');
-
- beforeEach(() => {
- pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
-
- registeredExtensions.extensions = [];
- });
-
- afterEach(() => {
- registeredExtensions.extensions = [];
- });
-
- describe('success - multi polling', () => {
- it('sets data when polling is complete', async () => {
- registerExtension(
- multiPollingExtension([
- () =>
- Promise.resolve({
- headers: { 'poll-interval': 0 },
- status: 200,
- data: { reports: 'parsed' },
- }),
- () =>
- Promise.resolve({
- status: 200,
- data: { reports: 'parsed' },
- }),
- ]),
- );
-
- await createComponent();
- expect(findWidgetTestExtension().html()).toContain(
- 'Multi polling test extension reports: parsed, count: 2',
- );
- });
-
- it('shows loading state until polling is complete', async () => {
- registerExtension(
- multiPollingExtension([
- () =>
- Promise.resolve({
- headers: { 'poll-interval': 1 },
- status: 204,
- }),
- () =>
- Promise.resolve({
- status: 200,
- data: { reports: 'parsed' },
- }),
- ]),
- );
-
- await createComponent();
- expect(findWidgetTestExtension().html()).toContain('Test extension loading...');
- });
- });
-
- describe('success', () => {
- it('does not make additional requests after poll is successful', async () => {
- registerExtension(pollingExtension);
-
- await createComponent();
-
- expect(pollRequest).toHaveBeenCalledTimes(6);
- });
- });
-
- describe('success - full data polling', () => {
- it('sets data when polling is complete', async () => {
- registerExtension(pollingFullDataExtension);
-
- await createComponent();
-
- api.trackRedisHllUserEvent.mockClear();
- api.trackRedisCounterEvent.mockClear();
-
- findExtensionToggleButton().trigger('click');
-
- // The default working extension is a "warning" type, which generates a second - more specific - telemetry event for expansions
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(2);
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_expand',
- );
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_expand_warning',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(2);
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_expand',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_expand_warning',
- );
- });
- });
-
- describe('error', () => {
- it('does not make additional requests after poll has failed', async () => {
- registerExtension(pollingErrorExtension);
- await createComponent();
-
- expect(pollRequest).toHaveBeenCalledTimes(6);
- });
-
- it('captures sentry error and displays error when poll has failed', async () => {
- registerExtension(pollingErrorExtension);
- await createComponent();
-
- expect(Sentry.captureException).toHaveBeenCalledTimes(5);
- expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
- expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
- });
- });
- });
-
- describe('mock extension errors', () => {
- afterEach(() => {
- registeredExtensions.extensions = [];
- });
-
- it('handles collapsed data fetch errors', async () => {
- registerExtension(collapsedDataErrorExtension);
- await createComponent();
-
- expect(
- wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(),
- ).toBe(false);
- expect(Sentry.captureException).toHaveBeenCalledTimes(5);
- expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
- expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
- });
-
- it('handles full data fetch errors', async () => {
- registerExtension(fullDataErrorExtension);
- await createComponent();
-
- expect(wrapper.findComponent(StatusIcon).props('iconName')).not.toBe('error');
- wrapper
- .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
- .trigger('click');
-
- await nextTick();
- await waitForPromises();
-
- expect(Sentry.captureException).toHaveBeenCalledTimes(1);
- expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Fetch error'));
- expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('failed');
- });
- });
-
- describe('telemetry', () => {
- afterEach(() => {
- registeredExtensions.extensions = [];
- });
-
- it('triggers view events when mounted', () => {
- registerExtension(workingExtension());
- createComponent();
-
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_view',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_view',
- );
- });
-
- describe('expand button', () => {
- it('triggers expand events when clicked', async () => {
- registerExtension(workingExtension());
- createComponent();
-
- await waitForPromises();
-
- api.trackRedisHllUserEvent.mockClear();
- api.trackRedisCounterEvent.mockClear();
-
- findExtensionToggleButton().trigger('click');
-
- // The default working extension is a "warning" type, which generates a second - more specific - telemetry event for expansions
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(2);
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_expand',
- );
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_expand_warning',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(2);
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_expand',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_expand_warning',
- );
- });
-
- it.each`
- widgetName | nonStandardEvent
- ${'WidgetCodeQuality'} | ${'i_testing_code_quality_widget_total'}
- ${'WidgetTerraform'} | ${'i_testing_terraform_widget_total'}
- ${'WidgetIssues'} | ${'i_testing_load_performance_widget_total'}
- ${'WidgetTestReport'} | ${'i_testing_summary_widget_total'}
- `(
- "sends non-standard events for the '$widgetName' widget",
- async ({ widgetName, nonStandardEvent }) => {
- const definition = {
- ...workingExtension(),
- name: widgetName,
- };
-
- registerExtension(definition);
- createComponent();
-
- await waitForPromises();
-
- api.trackRedisHllUserEvent.mockClear();
-
- findExtensionToggleButton().trigger('click');
-
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(nonStandardEvent);
- },
- );
- });
-
- it('triggers the "full report clicked" events when the appropriate button is clicked', () => {
- registerExtension(fullReportExtension);
- createComponent();
-
- api.trackRedisHllUserEvent.mockClear();
- api.trackRedisCounterEvent.mockClear();
-
- findExtensionLink('testref').trigger('click');
-
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
- expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_click_full_report',
- );
- expect(api.trackRedisCounterEvent).toHaveBeenCalledTimes(1);
- expect(api.trackRedisCounterEvent).toHaveBeenCalledWith(
- 'i_code_review_merge_request_widget_test_extension_count_click_full_report',
- );
- });
-
- describe('when disabled', () => {
- afterEach(() => {
- registeredExtensions.extensions = [];
- });
-
- it("doesn't emit any telemetry events", async () => {
- registerExtension(noTelemetryExtension);
- createComponent();
-
- await waitForPromises();
-
- findExtensionToggleButton().trigger('click');
- findExtensionLink('testref').trigger('click'); // The "full report" link
-
- expect(api.trackRedisHllUserEvent).not.toHaveBeenCalled();
- expect(api.trackRedisCounterEvent).not.toHaveBeenCalled();
- });
- });
- });
-});
diff --git a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
deleted file mode 100644
index fc760f5c5be..00000000000
--- a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import getStateKey from '~/vue_merge_request_widget/stores/get_state_key';
-
-describe('getStateKey', () => {
- it('should return proper state name', () => {
- const context = {
- mergeStatus: 'checked',
- autoMergeEnabled: false,
- canMerge: true,
- onlyAllowMergeIfPipelineSucceeds: false,
- isPipelineFailed: false,
- hasMergeableDiscussionsState: false,
- isPipelineBlocked: false,
- canBeMerged: false,
- projectArchived: false,
- branchMissing: false,
- commitsCount: 2,
- hasConflicts: false,
- draft: false,
- };
- const bound = getStateKey.bind(context);
-
- expect(bound()).toEqual(null);
-
- context.canBeMerged = true;
-
- expect(bound()).toEqual('readyToMerge');
-
- context.canMerge = false;
-
- expect(bound()).toEqual('notAllowedToMerge');
-
- context.autoMergeEnabled = true;
- context.hasMergeableDiscussionsState = true;
-
- expect(bound()).toEqual('autoMergeEnabled');
-
- context.canMerge = true;
- context.isSHAMismatch = true;
-
- expect(bound()).toEqual('shaMismatch');
-
- context.canMerge = false;
- context.isPipelineBlocked = true;
-
- expect(bound()).toEqual('pipelineBlocked');
-
- context.hasMergeableDiscussionsState = true;
- context.autoMergeEnabled = false;
-
- expect(bound()).toEqual('unresolvedDiscussions');
-
- context.draft = true;
-
- expect(bound()).toEqual('draft');
-
- context.onlyAllowMergeIfPipelineSucceeds = true;
- context.isPipelineFailed = true;
-
- expect(bound()).toEqual('pipelineFailed');
-
- context.shouldBeRebased = true;
-
- expect(bound()).toEqual('rebase');
-
- context.hasConflicts = true;
-
- expect(bound()).toEqual('conflicts');
-
- context.mergeStatus = 'unchecked';
-
- expect(bound()).toEqual('checking');
-
- context.commitsCount = 0;
-
- expect(bound()).toEqual('nothingToMerge');
-
- context.commitsCount = 1;
- context.branchMissing = true;
-
- expect(bound()).toEqual('missingBranch');
-
- context.projectArchived = true;
-
- expect(bound()).toEqual('archived');
- });
-
- it('returns rebased state key', () => {
- const context = {
- mergeStatus: 'checked',
- autoMergeEnabled: false,
- canMerge: true,
- onlyAllowMergeIfPipelineSucceeds: true,
- isPipelineFailed: true,
- hasMergeableDiscussionsState: false,
- isPipelineBlocked: false,
- canBeMerged: false,
- shouldBeRebased: true,
- projectArchived: false,
- branchMissing: false,
- commitsCount: 2,
- hasConflicts: false,
- draft: false,
- };
- const bound = getStateKey.bind(context);
-
- expect(bound()).toEqual('rebase');
- });
-
- it.each`
- canMerge | isSHAMismatch | stateKey
- ${true} | ${true} | ${'shaMismatch'}
- ${false} | ${true} | ${'notAllowedToMerge'}
- ${false} | ${false} | ${'notAllowedToMerge'}
- `(
- 'returns $stateKey when canMerge is $canMerge and isSHAMismatch is $isSHAMismatch',
- ({ canMerge, isSHAMismatch, stateKey }) => {
- const bound = getStateKey.bind({
- canMerge,
- isSHAMismatch,
- commitsCount: 2,
- });
-
- expect(bound()).toEqual(stateKey);
- },
- );
-});
diff --git a/spec/frontend/vue_shared/alert_details/alert_details_spec.js b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
index ce51af31a70..59e21b2ff40 100644
--- a/spec/frontend/vue_shared/alert_details/alert_details_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_details_spec.js
@@ -285,14 +285,14 @@ describe('AlertDetails', () => {
});
it('displays a loading state when loading', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
describe('error state', () => {
it('displays a error state correctly', () => {
mountComponent({ data: { errored: true } });
- expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(true);
});
it('renders html-errors correctly', () => {
@@ -304,7 +304,7 @@ describe('AlertDetails', () => {
it('does not display an error when dismissed', () => {
mountComponent({ data: { errored: true, isErrorDismissed: true } });
- expect(wrapper.find(GlAlert).exists()).toBe(false);
+ expect(wrapper.findComponent(GlAlert).exists()).toBe(false);
});
});
diff --git a/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
index 1216681038f..cf04c1eb24a 100644
--- a/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_metrics_spec.js
@@ -28,8 +28,8 @@ describe('Alert Metrics', () => {
});
}
- const findChart = () => wrapper.find(MetricEmbed);
- const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
+ const findChart = () => wrapper.findComponent(MetricEmbed);
+ const findEmptyState = () => wrapper.findComponent({ ref: 'emptyState' });
afterEach(() => {
if (wrapper) {
diff --git a/spec/frontend/vue_shared/alert_details/alert_status_spec.js b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
index ba3b0335a8e..2a37ff2b784 100644
--- a/spec/frontend/vue_shared/alert_details/alert_status_spec.js
+++ b/spec/frontend/vue_shared/alert_details/alert_status_spec.js
@@ -13,7 +13,7 @@ describe('AlertManagementStatus', () => {
let wrapper;
const findStatusDropdown = () => wrapper.findComponent(GlDropdown);
const findFirstStatusOption = () => findStatusDropdown().findComponent(GlDropdownItem);
- const findAllStatusOptions = () => findStatusDropdown().findAll(GlDropdownItem);
+ const findAllStatusOptions = () => findStatusDropdown().findAllComponents(GlDropdownItem);
const findStatusDropdownHeader = () => wrapper.findByTestId('dropdown-header');
const selectFirstStatusOption = () => {
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
index 29569734621..5a0ee5a59ba 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_assignees_spec.js
@@ -128,7 +128,7 @@ describe('Alert Details Sidebar Assignees', () => {
wrapper.setData({ isDropdownSearching: false });
await nextTick();
- wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
+ wrapper.findComponent(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: AlertSetAssignees,
@@ -156,7 +156,7 @@ describe('Alert Details Sidebar Assignees', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(errorMutationResult);
await nextTick();
- const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
+ const SideBarAssigneeItem = wrapper.findAllComponents(SidebarAssignee).at(0);
await SideBarAssigneeItem.vm.$emit('update-alert-assignees');
expect(wrapper.emitted('alert-error')).toBeDefined();
});
diff --git a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
index ef75e038bff..3b38349622f 100644
--- a/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
+++ b/spec/frontend/vue_shared/alert_details/sidebar/alert_sidebar_spec.js
@@ -65,7 +65,7 @@ describe('Alert Details Sidebar', () => {
mountMethod: mount,
alert: mockAlert,
});
- expect(wrapper.find(SidebarAssignees).exists()).toBe(true);
+ expect(wrapper.findComponent(SidebarAssignees).exists()).toBe(true);
});
it('should render side bar status dropdown', () => {
@@ -73,7 +73,7 @@ describe('Alert Details Sidebar', () => {
mountMethod: mount,
alert: mockAlert,
});
- expect(wrapper.find(SidebarStatus).exists()).toBe(true);
+ expect(wrapper.findComponent(SidebarStatus).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js b/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js
index a5a9fb55737..6a750bb99c0 100644
--- a/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js
+++ b/spec/frontend/vue_shared/alert_details/system_notes/alert_management_system_note_spec.js
@@ -31,7 +31,7 @@ describe('Alert Details System Note', () => {
it('renders the correct system note', () => {
const noteId = wrapper.find('.note-wrapper').attributes('id');
- const iconName = wrapper.find(GlIcon).attributes('name');
+ const iconName = wrapper.findComponent(GlIcon).attributes('name');
expect(noteId).toBe('note_1628');
expect(iconName).toBe(mockAlert.notes.nodes[0].systemNoteIconName);
diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js
index e5b7b693cb5..07c53c04723 100644
--- a/spec/frontend/vue_shared/components/actions_button_spec.js
+++ b/spec/frontend/vue_shared/components/actions_button_spec.js
@@ -45,9 +45,9 @@ describe('Actions button component', () => {
return directiveBinding.value;
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
const findButtonTooltip = () => getTooltip(findButton());
- const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
const findDropdownTooltip = () => getTooltip(findDropdown());
const parseDropdownItems = () =>
findDropdown()
diff --git a/spec/frontend/vue_shared/components/alert_details_table_spec.js b/spec/frontend/vue_shared/components/alert_details_table_spec.js
index b9a8a5bee97..8a9ee4699bd 100644
--- a/spec/frontend/vue_shared/components/alert_details_table_spec.js
+++ b/spec/frontend/vue_shared/components/alert_details_table_spec.js
@@ -74,7 +74,7 @@ describe('AlertDetails', () => {
});
it('displays a loading state when loading', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -130,7 +130,7 @@ describe('AlertDetails', () => {
environmentData = { name: null, path: null };
mountComponent();
- expect(findTableFieldValueByKey('Environment').text()).toBeFalsy();
+ expect(findTableFieldValueByKey('Environment').text()).toBe('');
});
});
diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
index d14f3e5559f..ce7fd40937f 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
@@ -43,6 +43,6 @@ describe('Blob Rich Viewer component', () => {
});
it('is using Markdown View Field', () => {
- expect(wrapper.find(MarkdownFieldView).exists()).toBe(true);
+ expect(wrapper.findComponent(MarkdownFieldView).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
index 6b9658a6d18..ea708b6f3fe 100644
--- a/spec/frontend/vue_shared/components/changed_file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
@@ -25,7 +25,7 @@ describe('Changed file icon', () => {
wrapper.destroy();
});
- const findIcon = () => wrapper.find(GlIcon);
+ const findIcon = () => wrapper.findComponent(GlIcon);
const findIconName = () => findIcon().props('name');
const findIconClasses = () => findIcon().classes();
const findTooltipText = () => wrapper.attributes('title');
@@ -51,7 +51,7 @@ describe('Changed file icon', () => {
showTooltip: false,
});
- expect(findTooltipText()).toBeFalsy();
+ expect(findTooltipText()).toBeUndefined();
});
describe.each`
@@ -87,7 +87,7 @@ describe('Changed file icon', () => {
});
it('does not have tooltip text', () => {
- expect(findTooltipText()).toBeFalsy();
+ expect(findTooltipText()).toBeUndefined();
});
});
diff --git a/spec/frontend/vue_shared/components/ci_icon_spec.js b/spec/frontend/vue_shared/components/ci_icon_spec.js
index 1b502f9587c..2064bee9673 100644
--- a/spec/frontend/vue_shared/components/ci_icon_spec.js
+++ b/spec/frontend/vue_shared/components/ci_icon_spec.js
@@ -22,7 +22,7 @@ describe('CI Icon component', () => {
});
expect(wrapper.find('span').exists()).toBe(true);
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
});
describe('active icons', () => {
diff --git a/spec/frontend/vue_shared/components/clipboard_button_spec.js b/spec/frontend/vue_shared/components/clipboard_button_spec.js
index fca5e664a96..b18b00e70bb 100644
--- a/spec/frontend/vue_shared/components/clipboard_button_spec.js
+++ b/spec/frontend/vue_shared/components/clipboard_button_spec.js
@@ -21,7 +21,7 @@ describe('clipboard button', () => {
});
};
- const findButton = () => wrapper.find(GlButton);
+ const findButton = () => wrapper.findComponent(GlButton);
const expectConfirmationTooltip = async ({ event, message }) => {
const title = 'Copy this value';
diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
index eefd1838988..31c08260dd0 100644
--- a/spec/frontend/vue_shared/components/clone_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
@@ -38,9 +38,9 @@ describe('Clone Dropdown Button', () => {
${'HTTP'} | ${1} | ${httpLink}
`('renders correct link and a copy-button for $name', ({ index, value }) => {
createComponent();
- const group = wrapper.findAll(GlFormInputGroup).at(index);
+ const group = wrapper.findAllComponents(GlFormInputGroup).at(index);
expect(group.props('value')).toBe(value);
- expect(group.find(GlFormInputGroup).exists()).toBe(true);
+ expect(group.findComponent(GlFormInputGroup).exists()).toBe(true);
});
it.each`
@@ -50,8 +50,8 @@ describe('Clone Dropdown Button', () => {
`('does not fail if only $name is set', ({ name, value }) => {
createComponent({ [name]: value });
- expect(wrapper.find(GlFormInputGroup).props('value')).toBe(value);
- expect(wrapper.findAll(GlDropdownSectionHeader).length).toBe(1);
+ expect(wrapper.findComponent(GlFormInputGroup).props('value')).toBe(value);
+ expect(wrapper.findAllComponents(GlDropdownSectionHeader).length).toBe(1);
});
});
@@ -63,12 +63,12 @@ describe('Clone Dropdown Button', () => {
`('allows null values for the props', ({ name, value }) => {
createComponent({ ...defaultPropsData, [name]: value });
- expect(wrapper.findAll(GlDropdownSectionHeader).length).toBe(1);
+ expect(wrapper.findAllComponents(GlDropdownSectionHeader).length).toBe(1);
});
it('correctly calculates httpLabel for HTTPS protocol', () => {
createComponent({ httpLink: httpsLink });
- expect(wrapper.find(GlDropdownSectionHeader).text()).toContain('HTTPS');
+ expect(wrapper.findComponent(GlDropdownSectionHeader).text()).toContain('HTTPS');
});
});
});
diff --git a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
index 8cbe0630426..060048c4bbd 100644
--- a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
+++ b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js
@@ -16,14 +16,14 @@ describe('ColorPicker', () => {
const setColor = '#000000';
const invalidText = 'Please enter a valid hex (#RRGGBB or #RGB) color value';
- const findGlFormGroup = () => wrapper.find(GlFormGroup);
+ const findGlFormGroup = () => wrapper.findComponent(GlFormGroup);
const colorPreview = () => wrapper.find('[data-testid="color-preview"]');
- const colorPicker = () => wrapper.find(GlFormInput);
+ const colorPicker = () => wrapper.findComponent(GlFormInput);
const colorInput = () => wrapper.find('input[type="color"]');
- const colorTextInput = () => wrapper.find(GlFormInputGroup).find('input[type="text"]');
+ const colorTextInput = () => wrapper.findComponent(GlFormInputGroup).find('input[type="text"]');
const invalidFeedback = () => wrapper.find('.invalid-feedback');
- const description = () => wrapper.find(GlFormGroup).attributes('description');
- const presetColors = () => wrapper.findAll(GlLink);
+ const description = () => wrapper.findComponent(GlFormGroup).attributes('description');
+ const presetColors = () => wrapper.findAllComponents(GlLink);
beforeEach(() => {
gon.suggested_label_colors = {
diff --git a/spec/frontend/vue_shared/components/commit_spec.js b/spec/frontend/vue_shared/components/commit_spec.js
index d91853e7b79..1893e127f6f 100644
--- a/spec/frontend/vue_shared/components/commit_spec.js
+++ b/spec/frontend/vue_shared/components/commit_spec.js
@@ -9,11 +9,11 @@ describe('Commit component', () => {
let wrapper;
const findIcon = (name) => {
- const icons = wrapper.findAll(GlIcon).filter((c) => c.attributes('name') === name);
+ const icons = wrapper.findAllComponents(GlIcon).filter((c) => c.attributes('name') === name);
return icons.length ? icons.at(0) : icons;
};
- const findUserAvatar = () => wrapper.find(UserAvatarLink);
+ const findUserAvatar = () => wrapper.findComponent(UserAvatarLink);
const findRefName = () => wrapper.findByTestId('ref-name');
const createComponent = (propsData) => {
@@ -47,7 +47,7 @@ describe('Commit component', () => {
},
});
- expect(wrapper.find('.icon-container').find(GlIcon).exists()).toBe(true);
+ expect(wrapper.find('.icon-container').findComponent(GlIcon).exists()).toBe(true);
});
describe('Given all the props', () => {
diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js
index 3ca1c943398..c1e682a1aae 100644
--- a/spec/frontend/vue_shared/components/confirm_modal_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js
@@ -51,13 +51,13 @@ describe('vue_shared/components/confirm_modal', () => {
wrapper.destroy();
});
- const findModal = () => wrapper.find(GlModalStub);
+ const findModal = () => wrapper.findComponent(GlModalStub);
const findForm = () => wrapper.find('form');
const findFormData = () =>
findForm()
.findAll('input')
.wrappers.map((x) => ({ name: x.attributes('name'), value: x.attributes('value') }));
- const findDomElementListener = () => wrapper.find(DomElementListener);
+ const findDomElementListener = () => wrapper.findComponent(DomElementListener);
const triggerOpenWithEventHub = (modalData) => {
eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, modalData);
};
@@ -104,7 +104,7 @@ describe('vue_shared/components/confirm_modal', () => {
});
it('renders GlModal with data', () => {
- expect(findModal().exists()).toBeTruthy();
+ expect(findModal().exists()).toBe(true);
expect(findModal().attributes()).toEqual(
expect.objectContaining({
oktitle: MOCK_MODAL_DATA.modalAttributes.okTitle,
diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
index 879d4aba441..8b1189f25d5 100644
--- a/spec/frontend/vue_shared/components/dismissible_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
@@ -20,7 +20,7 @@ describe('vue_shared/components/dismissible_alert', () => {
wrapper.destroy();
});
- const findAlert = () => wrapper.find(GlAlert);
+ const findAlert = () => wrapper.findComponent(GlAlert);
describe('default', () => {
beforeEach(() => {
@@ -45,7 +45,7 @@ describe('vue_shared/components/dismissible_alert', () => {
});
it('emmits alertDismissed', () => {
- expect(wrapper.emitted('alertDismissed')).toBeTruthy();
+ expect(wrapper.emitted()).toHaveProperty('alertDismissed');
});
});
});
diff --git a/spec/frontend/vue_shared/components/dismissible_container_spec.js b/spec/frontend/vue_shared/components/dismissible_container_spec.js
index b8aeea38e77..f7030f38709 100644
--- a/spec/frontend/vue_shared/components/dismissible_container_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_container_spec.js
@@ -33,7 +33,7 @@ describe('DismissibleContainer', () => {
button.trigger('click');
- expect(wrapper.emitted().dismiss).toBeTruthy();
+ expect(wrapper.emitted().dismiss).toEqual(expect.any(Array));
});
});
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
index 08e5d828b8f..e34ed31b4bf 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_button_spec.js
@@ -1,80 +1,71 @@
-import Vue from 'vue';
+import { mount } from '@vue/test-utils';
+import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import { mountComponentWithSlots } from 'helpers/vue_mount_component_helper';
-import dropdownButtonComponent from '~/vue_shared/components/dropdown/dropdown_button.vue';
+describe('DropdownButton component', () => {
+ let wrapper;
-const defaultLabel = 'Select';
-const customLabel = 'Select project';
+ const defaultLabel = 'Select';
+ const customLabel = 'Select project';
-const createComponent = (props, slots = {}) => {
- const Component = Vue.extend(dropdownButtonComponent);
-
- return mountComponentWithSlots(Component, { props, slots });
-};
-
-describe('DropdownButtonComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
+ const createComponent = (props, slots = {}) => {
+ wrapper = mount(DropdownButton, { propsData: props, slots });
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
describe('computed', () => {
describe('dropdownToggleText', () => {
it('returns default toggle text', () => {
- expect(vm.toggleText).toBe(defaultLabel);
+ createComponent();
+
+ expect(wrapper.vm.toggleText).toBe(defaultLabel);
});
it('returns custom toggle text when provided via props', () => {
- const vmEmptyLabels = createComponent({ toggleText: customLabel });
+ createComponent({ toggleText: customLabel });
- expect(vmEmptyLabels.toggleText).toBe(customLabel);
- vmEmptyLabels.$destroy();
+ expect(wrapper.vm.toggleText).toBe(customLabel);
});
});
});
describe('template', () => {
it('renders component container element of type `button`', () => {
- expect(vm.$el.nodeName).toBe('BUTTON');
+ createComponent();
+
+ expect(wrapper.element.nodeName).toBe('BUTTON');
});
it('renders component container element with required data attributes', () => {
- expect(vm.$el.dataset.abilityName).toBe(vm.abilityName);
- expect(vm.$el.dataset.fieldName).toBe(vm.fieldName);
- expect(vm.$el.dataset.issueUpdate).toBe(vm.updatePath);
- expect(vm.$el.dataset.labels).toBe(vm.labelsPath);
- expect(vm.$el.dataset.namespacePath).toBe(vm.namespace);
- expect(vm.$el.dataset.showAny).not.toBeDefined();
+ createComponent();
+
+ expect(wrapper.element.dataset.abilityName).toBe(wrapper.vm.abilityName);
+ expect(wrapper.element.dataset.fieldName).toBe(wrapper.vm.fieldName);
+ expect(wrapper.element.dataset.issueUpdate).toBe(wrapper.vm.updatePath);
+ expect(wrapper.element.dataset.labels).toBe(wrapper.vm.labelsPath);
+ expect(wrapper.element.dataset.namespacePath).toBe(wrapper.vm.namespace);
+ expect(wrapper.element.dataset.showAny).toBeUndefined();
});
it('renders dropdown toggle text element', () => {
- const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
+ createComponent();
- expect(dropdownToggleTextEl).not.toBeNull();
- expect(dropdownToggleTextEl.innerText.trim()).toBe(defaultLabel);
+ expect(wrapper.find('.dropdown-toggle-text').text()).toBe(defaultLabel);
});
it('renders dropdown button icon', () => {
- const dropdownIconEl = vm.$el.querySelector('[data-testid="chevron-down-icon"]');
+ createComponent();
- expect(dropdownIconEl).not.toBeNull();
+ expect(wrapper.find('[data-testid="chevron-down-icon"]').exists()).toBe(true);
});
it('renders slot, if default slot exists', () => {
- vm = createComponent(
- {},
- {
- default: ['Lorem Ipsum Dolar'],
- },
- );
-
- expect(vm.$el.querySelector('.dropdown-toggle-text')).toBeNull();
- expect(vm.$el).toHaveText('Lorem Ipsum Dolar');
+ createComponent({}, { default: ['Lorem Ipsum Dolar'] });
+
+ expect(wrapper.find('.dropdown-toggle-text').exists()).toBe(false);
+ expect(wrapper.text()).toBe('Lorem Ipsum Dolar');
});
});
});
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
index 084d0559665..dd3e55c82bb 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_widget_spec.js
@@ -8,7 +8,7 @@ describe('DropdownWidget component', () => {
let wrapper;
const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findSearch = () => wrapper.findComponent(GlSearchBoxByType);
const createComponent = ({ props = {} } = {}) => {
diff --git a/spec/frontend/vue_shared/components/expand_button_spec.js b/spec/frontend/vue_shared/components/expand_button_spec.js
index 87d6ed6b21f..170c947e520 100644
--- a/spec/frontend/vue_shared/components/expand_button_spec.js
+++ b/spec/frontend/vue_shared/components/expand_button_spec.js
@@ -37,11 +37,11 @@ describe('Expand button', () => {
});
it('renders no text when short text is not provided', () => {
- expect(wrapper.find(ExpandButton).text()).toBe('');
+ expect(wrapper.findComponent(ExpandButton).text()).toBe('');
});
it('does not render expanded text', () => {
- expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.short);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).not.toBe(text.short);
});
describe('when short text is provided', () => {
@@ -55,13 +55,13 @@ describe('Expand button', () => {
});
it('renders short text', () => {
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).toBe(text.short);
});
it('renders button before text', () => {
expect(expanderPrependEl().isVisible()).toBe(true);
expect(expanderAppendEl().isVisible()).toBe(false);
- expect(wrapper.find(ExpandButton).element).toMatchSnapshot();
+ expect(wrapper.findComponent(ExpandButton).element).toMatchSnapshot();
});
});
@@ -81,7 +81,7 @@ describe('Expand button', () => {
});
it('renders the expanded text', () => {
- expect(wrapper.find(ExpandButton).text()).toContain(text.expanded);
+ expect(wrapper.findComponent(ExpandButton).text()).toContain(text.expanded);
});
describe('when short text is provided', () => {
@@ -98,13 +98,13 @@ describe('Expand button', () => {
});
it('only renders expanded text', () => {
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).toBe(text.expanded);
});
it('renders button after text', () => {
expect(expanderPrependEl().isVisible()).toBe(false);
expect(expanderAppendEl().isVisible()).toBe(true);
- expect(wrapper.find(ExpandButton).element).toMatchSnapshot();
+ expect(wrapper.findComponent(ExpandButton).element).toMatchSnapshot();
});
});
});
@@ -124,11 +124,11 @@ describe('Expand button', () => {
});
it('clicking hides expanded text', async () => {
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
await nextTick();
- expect(wrapper.find(ExpandButton).text().trim()).not.toBe(text.expanded);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).not.toBe(text.expanded);
});
describe('when short text is provided', () => {
@@ -145,11 +145,11 @@ describe('Expand button', () => {
});
it('clicking reveals short text', async () => {
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.expanded);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).toBe(text.expanded);
expanderAppendEl().trigger('click');
await nextTick();
- expect(wrapper.find(ExpandButton).text().trim()).toBe(text.short);
+ expect(wrapper.findComponent(ExpandButton).text().trim()).toBe(text.short);
});
});
});
diff --git a/spec/frontend/vue_shared/components/file_icon_spec.js b/spec/frontend/vue_shared/components/file_icon_spec.js
index b0e623520a8..3f4bfc86b67 100644
--- a/spec/frontend/vue_shared/components/file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/file_icon_spec.js
@@ -6,7 +6,7 @@ import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
describe('File Icon component', () => {
let wrapper;
const findSvgIcon = () => wrapper.find('svg');
- const findGlIcon = () => wrapper.find(GlIcon);
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
const getIconName = () =>
findSvgIcon()
.find('use')
@@ -61,7 +61,7 @@ describe('File Icon component', () => {
loading: true,
});
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('should add a special class and a size class', () => {
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index 62fb29c455c..f5a545891d5 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -119,7 +119,7 @@ describe('File row component', () => {
level: 0,
});
- expect(wrapper.find(FileHeader).exists()).toBe(true);
+ expect(wrapper.findComponent(FileHeader).exists()).toBe(true);
});
it('matches the current route against encoded file URL', () => {
@@ -164,6 +164,6 @@ describe('File row component', () => {
level: 0,
});
- expect(wrapper.find(FileIcon).props('submodule')).toBe(submodule);
+ expect(wrapper.findComponent(FileIcon).props('submodule')).toBe(submodule);
});
});
diff --git a/spec/frontend/vue_shared/components/file_tree_spec.js b/spec/frontend/vue_shared/components/file_tree_spec.js
index 39a7c7a2b3a..e8818e09dc0 100644
--- a/spec/frontend/vue_shared/components/file_tree_spec.js
+++ b/spec/frontend/vue_shared/components/file_tree_spec.js
@@ -25,8 +25,8 @@ describe('File Tree component', () => {
});
};
- const findFileRow = () => wrapper.find(MockFileRow);
- const findChildrenTrees = () => wrapper.findAll(FileTree).wrappers.slice(1);
+ const findFileRow = () => wrapper.findComponent(MockFileRow);
+ const findChildrenTrees = () => wrapper.findAllComponents(FileTree).wrappers.slice(1);
const findChildrenTreeProps = () =>
findChildrenTrees().map((x) => ({
...x.props(),
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
index e44bc8771f5..1b9ca8e6092 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -88,10 +88,10 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapper.vm.filterValue).toEqual([]);
expect(wrapper.vm.selectedSortOption).toBe(mockSortOptions[0]);
expect(wrapper.vm.selectedSortDirection).toBe(SortDirection.descending);
- expect(wrapper.find(GlButtonGroup).exists()).toBe(true);
- expect(wrapper.find(GlButton).exists()).toBe(true);
- expect(wrapper.find(GlDropdown).exists()).toBe(true);
- expect(wrapper.find(GlDropdownItem).exists()).toBe(true);
+ expect(wrapper.findComponent(GlButtonGroup).exists()).toBe(true);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdown).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdownItem).exists()).toBe(true);
});
it('does not initialize `selectedSortOption` and `selectedSortDirection` when `sortOptions` is not applied and hides the sort dropdown', () => {
@@ -99,10 +99,10 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapperNoSort.vm.filterValue).toEqual([]);
expect(wrapperNoSort.vm.selectedSortOption).toBe(undefined);
- expect(wrapperNoSort.find(GlButtonGroup).exists()).toBe(false);
- expect(wrapperNoSort.find(GlButton).exists()).toBe(false);
- expect(wrapperNoSort.find(GlDropdown).exists()).toBe(false);
- expect(wrapperNoSort.find(GlDropdownItem).exists()).toBe(false);
+ expect(wrapperNoSort.findComponent(GlButtonGroup).exists()).toBe(false);
+ expect(wrapperNoSort.findComponent(GlButton).exists()).toBe(false);
+ expect(wrapperNoSort.findComponent(GlDropdown).exists()).toBe(false);
+ expect(wrapperNoSort.findComponent(GlDropdownItem).exists()).toBe(false);
});
});
@@ -217,7 +217,7 @@ describe('FilteredSearchBarRoot', () => {
it('emits component event `onFilter` with empty array and true when initially selected filter value was cleared', async () => {
wrapper = createComponent({ initialFilterValue: [tokenValueLabel] });
- wrapper.find(GlFilteredSearch).vm.$emit('clear');
+ wrapper.findComponent(GlFilteredSearch).vm.$emit('clear');
await nextTick();
expect(wrapper.emitted('onFilter')[0]).toEqual([[], true]);
@@ -362,7 +362,7 @@ describe('FilteredSearchBarRoot', () => {
it('calls `blurSearchInput` method to remove focus from filter input field', () => {
jest.spyOn(wrapper.vm, 'blurSearchInput');
- wrapper.find(GlFilteredSearch).vm.$emit('submit', mockFilters);
+ wrapper.findComponent(GlFilteredSearch).vm.$emit('submit', mockFilters);
expect(wrapper.vm.blurSearchInput).toHaveBeenCalled();
});
@@ -392,7 +392,7 @@ describe('FilteredSearchBarRoot', () => {
});
it('renders gl-filtered-search component', () => {
- const glFilteredSearchEl = wrapper.find(GlFilteredSearch);
+ const glFilteredSearchEl = wrapper.findComponent(GlFilteredSearch);
expect(glFilteredSearchEl.props('placeholder')).toBe('Filter requirements');
expect(glFilteredSearchEl.props('availableTokens')).toEqual(mockAvailableTokens);
@@ -404,8 +404,10 @@ describe('FilteredSearchBarRoot', () => {
showCheckbox: true,
});
- expect(wrapperWithCheckbox.find(GlFormCheckbox).exists()).toBe(true);
- expect(wrapperWithCheckbox.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
+ expect(wrapperWithCheckbox.findComponent(GlFormCheckbox).exists()).toBe(true);
+ expect(
+ wrapperWithCheckbox.findComponent(GlFormCheckbox).attributes('checked'),
+ ).not.toBeDefined();
wrapperWithCheckbox.destroy();
@@ -414,7 +416,7 @@ describe('FilteredSearchBarRoot', () => {
checkboxChecked: true,
});
- expect(wrapperWithCheckbox.find(GlFormCheckbox).attributes('checked')).toBe('true');
+ expect(wrapperWithCheckbox.findComponent(GlFormCheckbox).attributes('checked')).toBe('true');
wrapperWithCheckbox.destroy();
});
@@ -448,7 +450,7 @@ describe('FilteredSearchBarRoot', () => {
await nextTick();
- expect(wrapperFullMount.find(GlDropdownItem).text()).toBe('Membership := Direct');
+ expect(wrapperFullMount.findComponent(GlDropdownItem).text()).toBe('Membership := Direct');
wrapperFullMount.destroy();
});
@@ -466,20 +468,20 @@ describe('FilteredSearchBarRoot', () => {
await nextTick();
- expect(wrapperFullMount.find(GlDropdownItem).text()).toBe('Membership := exclude');
+ expect(wrapperFullMount.findComponent(GlDropdownItem).text()).toBe('Membership := exclude');
wrapperFullMount.destroy();
});
});
it('renders sort dropdown component', () => {
- expect(wrapper.find(GlButtonGroup).exists()).toBe(true);
- expect(wrapper.find(GlDropdown).exists()).toBe(true);
- expect(wrapper.find(GlDropdown).props('text')).toBe(mockSortOptions[0].title);
+ expect(wrapper.findComponent(GlButtonGroup).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdown).exists()).toBe(true);
+ expect(wrapper.findComponent(GlDropdown).props('text')).toBe(mockSortOptions[0].title);
});
it('renders sort dropdown items', () => {
- const dropdownItemsEl = wrapper.findAll(GlDropdownItem);
+ const dropdownItemsEl = wrapper.findAllComponents(GlDropdownItem);
expect(dropdownItemsEl).toHaveLength(mockSortOptions.length);
expect(dropdownItemsEl.at(0).text()).toBe(mockSortOptions[0].title);
@@ -488,7 +490,7 @@ describe('FilteredSearchBarRoot', () => {
});
it('renders sort direction button', () => {
- const sortButtonEl = wrapper.find(GlButton);
+ const sortButtonEl = wrapper.findComponent(GlButton);
expect(sortButtonEl.attributes('title')).toBe('Sort direction: Descending');
expect(sortButtonEl.props('icon')).toBe('sort-highest');
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
index 86d1f21fd04..a6713b7e7e4 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js
@@ -66,12 +66,14 @@ export const mockMilestones = [
export const mockCrmContacts = [
{
+ __typename: 'CustomerRelationsContact',
id: 'gid://gitlab/CustomerRelations::Contact/1',
firstName: 'John',
lastName: 'Smith',
email: 'john@smith.com',
},
{
+ __typename: 'CustomerRelationsContact',
id: 'gid://gitlab/CustomerRelations::Contact/2',
firstName: 'Andy',
lastName: 'Green',
@@ -81,10 +83,12 @@ export const mockCrmContacts = [
export const mockCrmOrganizations = [
{
+ __typename: 'CustomerRelationsOrganization',
id: 'gid://gitlab/CustomerRelations::Organization/1',
name: 'First Org Ltd.',
},
{
+ __typename: 'CustomerRelationsOrganization',
id: 'gid://gitlab/CustomerRelations::Organization/2',
name: 'Organizer S.p.a.',
},
@@ -102,11 +106,9 @@ export const mockProjectCrmContactsQueryResponse = {
__typename: 'CustomerRelationsContactConnection',
nodes: [
{
- __typename: 'CustomerRelationsContact',
...mockCrmContacts[0],
},
{
- __typename: 'CustomerRelationsContact',
...mockCrmContacts[1],
},
],
@@ -128,11 +130,9 @@ export const mockProjectCrmOrganizationsQueryResponse = {
__typename: 'CustomerRelationsOrganizationConnection',
nodes: [
{
- __typename: 'CustomerRelationsOrganization',
...mockCrmOrganizations[0],
},
{
- __typename: 'CustomerRelationsOrganization',
...mockCrmOrganizations[1],
},
],
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 3f24d5df858..302dfabffb2 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
@@ -195,7 +195,7 @@ describe('AuthorToken', () => {
});
await nextTick();
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Author, =, "Administrator"
@@ -207,7 +207,7 @@ describe('AuthorToken', () => {
it('renders token value with correct avatarUrl from author object', async () => {
const getAvatarEl = () =>
- wrapper.findAll(GlFilteredSearchTokenSegment).at(2).findComponent(GlAvatar);
+ wrapper.findAllComponents(GlFilteredSearchTokenSegment).at(2).findComponent(GlAvatar);
wrapper = createComponent({
value: { data: mockAuthors[0].username },
@@ -252,7 +252,7 @@ describe('AuthorToken', () => {
await activateSuggestionsList();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultAuthors.length + currentUserLength);
defaultAuthors.forEach((label, index) => {
@@ -266,12 +266,12 @@ describe('AuthorToken', () => {
config: { ...mockAuthorToken, defaultAuthors: [] },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_NONE_ANY` as default suggestions', async () => {
@@ -283,7 +283,7 @@ describe('AuthorToken', () => {
await activateSuggestionsList();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(2 + currentUserLength);
expect(suggestions.at(0).text()).toBe(DEFAULT_NONE_ANY[0].text);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index 7b495ec9bee..1de35daa3a5 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
@@ -114,7 +114,7 @@ describe('BranchToken', () => {
describe('template', () => {
const defaultBranches = DEFAULT_NONE_ANY;
async function showSuggestions() {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
@@ -133,11 +133,11 @@ describe('BranchToken', () => {
});
it('renders gl-filtered-search-token component', () => {
- expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ expect(wrapper.findComponent(GlFilteredSearchToken).exists()).toBe(true);
});
it('renders token item when value is selected', () => {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3);
expect(tokenSegments.at(2).text()).toBe(mockBranches[0].name);
@@ -150,7 +150,7 @@ describe('BranchToken', () => {
stubs: { Portal: true },
});
await showSuggestions();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultBranches.length);
defaultBranches.forEach((branch, index) => {
@@ -166,8 +166,8 @@ describe('BranchToken', () => {
});
await showSuggestions();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders no suggestions as default', async () => {
@@ -177,7 +177,7 @@ describe('BranchToken', () => {
stubs: { Portal: true },
});
await showSuggestions();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(0);
});
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 157e021fc60..c9879987931 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
@@ -195,7 +195,7 @@ describe('CrmContactToken', () => {
value: { data: '1' },
});
- const baseTokenEl = wrapper.find(BaseToken);
+ const baseTokenEl = wrapper.findComponent(BaseToken);
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
@@ -210,7 +210,7 @@ describe('CrmContactToken', () => {
value: { data: `${getIdFromGraphQLId(contact.id)}` },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Contact, =, Contact name
expect(tokenSegments.at(2).text()).toBe(`${contact.firstName} ${contact.lastName}`); // Contact name
@@ -222,12 +222,12 @@ describe('CrmContactToken', () => {
config: { ...mockCrmContactToken, defaultContacts },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultContacts.length);
defaultContacts.forEach((contact, index) => {
@@ -241,13 +241,13 @@ describe('CrmContactToken', () => {
config: { ...mockCrmContactToken, defaultContacts: [] },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_NONE_ANY` as default suggestions', () => {
@@ -256,11 +256,11 @@ describe('CrmContactToken', () => {
config: { ...mockCrmContactToken },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(DEFAULT_NONE_ANY.length);
DEFAULT_NONE_ANY.forEach((contact, index) => {
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 977f8bbef61..16333b052e6 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
@@ -194,7 +194,7 @@ describe('CrmOrganizationToken', () => {
value: { data: '1' },
});
- const baseTokenEl = wrapper.find(BaseToken);
+ const baseTokenEl = wrapper.findComponent(BaseToken);
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
@@ -209,7 +209,7 @@ describe('CrmOrganizationToken', () => {
value: { data: `${getIdFromGraphQLId(organization.id)}` },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Organization, =, Organization name
expect(tokenSegments.at(2).text()).toBe(organization.name); // Organization name
@@ -221,12 +221,12 @@ describe('CrmOrganizationToken', () => {
config: { ...mockCrmOrganizationToken, defaultOrganizations },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultOrganizations.length);
defaultOrganizations.forEach((organization, index) => {
@@ -240,13 +240,13 @@ describe('CrmOrganizationToken', () => {
config: { ...mockCrmOrganizationToken, defaultOrganizations: [] },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_NONE_ANY` as default suggestions', () => {
@@ -255,11 +255,11 @@ describe('CrmOrganizationToken', () => {
config: { ...mockCrmOrganizationToken },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(DEFAULT_NONE_ANY.length);
DEFAULT_NONE_ANY.forEach((organization, index) => {
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 dcb0d095b1b..bf4a6eb7635 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
@@ -135,14 +135,16 @@ describe('EmojiToken', () => {
});
it('renders gl-filtered-search-token component', () => {
- expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ expect(wrapper.findComponent(GlFilteredSearchToken).exists()).toBe(true);
});
it('renders token item when value is selected', () => {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // My Reaction, =, "thumbsup"
- expect(tokenSegments.at(2).find(GlEmoji).attributes('data-name')).toEqual('thumbsup');
+ expect(tokenSegments.at(2).findComponent(GlEmoji).attributes('data-name')).toEqual(
+ 'thumbsup',
+ );
});
it('renders provided defaultEmojis as suggestions', async () => {
@@ -151,12 +153,12 @@ describe('EmojiToken', () => {
config: { ...mockReactionEmojiToken, defaultEmojis },
stubs: { Portal: true, GlEmoji },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultEmojis.length);
defaultEmojis.forEach((emoji, index) => {
@@ -170,13 +172,13 @@ describe('EmojiToken', () => {
config: { ...mockReactionEmojiToken, defaultEmojis: [] },
stubs: { Portal: true, GlEmoji },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_LABEL_NONE` and `DEFAULT_LABEL_ANY` as default suggestions', async () => {
@@ -185,12 +187,12 @@ describe('EmojiToken', () => {
config: { ...mockReactionEmojiToken },
stubs: { Portal: true, GlEmoji },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(2);
expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_NONE.text);
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 51161a1a0ef..01e281884ed 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
@@ -156,7 +156,7 @@ describe('LabelToken', () => {
});
it('renders base-token component', () => {
- const baseTokenEl = wrapper.find(BaseToken);
+ const baseTokenEl = wrapper.findComponent(BaseToken);
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
@@ -166,7 +166,7 @@ describe('LabelToken', () => {
});
it('renders token item when value is selected', () => {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Label, =, "Foo Label"
expect(tokenSegments.at(2).text()).toBe(`~${mockRegularLabel.title}`); // "Foo Label"
@@ -181,12 +181,12 @@ describe('LabelToken', () => {
config: { ...mockLabelToken, defaultLabels },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultLabels.length);
defaultLabels.forEach((label, index) => {
@@ -200,13 +200,13 @@ describe('LabelToken', () => {
config: { ...mockLabelToken, defaultLabels: [] },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_NONE_ANY` as default suggestions', () => {
@@ -215,11 +215,11 @@ describe('LabelToken', () => {
config: { ...mockLabelToken },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(DEFAULT_NONE_ANY.length);
DEFAULT_NONE_ANY.forEach((label, index) => {
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 7c545f76c0b..f71ba51fc5b 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
@@ -155,11 +155,11 @@ describe('MilestoneToken', () => {
});
it('renders gl-filtered-search-token component', () => {
- expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ expect(wrapper.findComponent(GlFilteredSearchToken).exists()).toBe(true);
});
it('renders token item when value is selected', () => {
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Milestone, =, '%"4.0"'
expect(tokenSegments.at(2).text()).toBe(`%${mockRegularMilestone.title}`); // "4.0 RC1"
@@ -171,12 +171,12 @@ describe('MilestoneToken', () => {
config: { ...mockMilestoneToken, defaultMilestones },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultMilestones.length);
defaultMilestones.forEach((milestone, index) => {
@@ -190,13 +190,13 @@ describe('MilestoneToken', () => {
config: { ...mockMilestoneToken, defaultMilestones: [] },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- expect(wrapper.find(GlFilteredSearchSuggestion).exists()).toBe(false);
- expect(wrapper.find(GlDropdownDivider).exists()).toBe(false);
+ expect(wrapper.findComponent(GlFilteredSearchSuggestion).exists()).toBe(false);
+ expect(wrapper.findComponent(GlDropdownDivider).exists()).toBe(false);
});
it('renders `DEFAULT_MILESTONES` as default suggestions', async () => {
@@ -205,12 +205,12 @@ describe('MilestoneToken', () => {
config: { ...mockMilestoneToken },
stubs: { Portal: true },
});
- const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await nextTick();
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+ const suggestions = wrapper.findAllComponents(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(DEFAULT_MILESTONES.length);
DEFAULT_MILESTONES.forEach((milestone, index) => {
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 b180e8c12dd..6699ae5fb69 100644
--- a/spec/frontend/vue_shared/components/gitlab_version_check_spec.js
+++ b/spec/frontend/vue_shared/components/gitlab_version_check_spec.js
@@ -26,13 +26,44 @@ describe('GitlabVersionCheck', () => {
wrapper = shallowMount(GitlabVersionCheck);
};
+ const dummyGon = {
+ relative_url_root: '/',
+ };
+
+ let originalGon;
+
afterEach(() => {
wrapper.destroy();
mock.restore();
+ window.gon = originalGon;
});
const findGlBadge = () => wrapper.findComponent(GlBadge);
+ describe.each`
+ root | description
+ ${'/'} | ${'not used (uses its own (sub)domain)'}
+ ${'/gitlab'} | ${'custom path'}
+ ${'/service/gitlab'} | ${'custom path with 2 depth'}
+ `('path for version_check.json', ({ root, description }) => {
+ describe(`when relative url is ${description}: ${root}`, () => {
+ beforeEach(async () => {
+ originalGon = window.gon;
+ window.gon = { ...dummyGon };
+ window.gon.relative_url_root = root;
+ createComponent(defaultResponse);
+ await waitForPromises(); // Ensure we wrap up the axios call
+ });
+
+ it('reflects the relative url setting', () => {
+ expect(mock.history.get.length).toBe(1);
+
+ const pathRegex = new RegExp(`^${root}`);
+ expect(mock.history.get[0].url).toMatch(pathRegex);
+ });
+ });
+ });
+
describe('template', () => {
describe.each`
description | mockResponse | renders
diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
index c0a6588833e..2dcd91f737f 100644
--- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
+++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
@@ -59,7 +59,7 @@ describe('GlModalVuex', () => {
default: `<div>${TEST_SLOT}</div>`,
},
});
- const glModal = wrapper.find(GlModal);
+ const glModal = wrapper.findComponent(GlModal);
expect(glModal.props('modalId')).toBe(TEST_MODAL_ID);
expect(glModal.text()).toContain(TEST_SLOT);
@@ -76,7 +76,7 @@ describe('GlModalVuex', () => {
okVariant,
},
});
- const glModal = wrapper.find(GlModal);
+ const glModal = wrapper.findComponent(GlModal);
expect(glModal.attributes('title')).toEqual(title);
expect(glModal.attributes('oktitle')).toEqual(title);
@@ -90,7 +90,7 @@ describe('GlModalVuex', () => {
listeners: { ok },
});
- const glModal = wrapper.find(GlModal);
+ const glModal = wrapper.findComponent(GlModal);
glModal.vm.$emit('ok');
expect(ok).toHaveBeenCalledTimes(1);
@@ -101,7 +101,7 @@ describe('GlModalVuex', () => {
factory();
- const glModal = wrapper.find(GlModal);
+ const glModal = wrapper.findComponent(GlModal);
glModal.vm.$emit('shown');
expect(actions.show).toHaveBeenCalledTimes(1);
@@ -112,7 +112,7 @@ describe('GlModalVuex', () => {
factory();
- const glModal = wrapper.find(GlModal);
+ const glModal = wrapper.findComponent(GlModal);
glModal.vm.$emit('hidden');
expect(actions.hide).toHaveBeenCalledTimes(1);
diff --git a/spec/frontend/vue_shared/components/help_popover_spec.js b/spec/frontend/vue_shared/components/help_popover_spec.js
index 64dce194327..6fd5ae0e946 100644
--- a/spec/frontend/vue_shared/components/help_popover_spec.js
+++ b/spec/frontend/vue_shared/components/help_popover_spec.js
@@ -7,8 +7,8 @@ describe('HelpPopover', () => {
const title = 'popover <strong>title</strong>';
const content = 'popover <b>content</b>';
- const findQuestionButton = () => wrapper.find(GlButton);
- const findPopover = () => wrapper.find(GlPopover);
+ const findQuestionButton = () => wrapper.findComponent(GlButton);
+ const findPopover = () => wrapper.findComponent(GlPopover);
const createComponent = ({ props, ...opts } = {}) => {
wrapper = mount(HelpPopover, {
diff --git a/spec/frontend/vue_shared/components/integration_help_text_spec.js b/spec/frontend/vue_shared/components/integration_help_text_spec.js
index c0e8b719007..c63e46313b3 100644
--- a/spec/frontend/vue_shared/components/integration_help_text_spec.js
+++ b/spec/frontend/vue_shared/components/integration_help_text_spec.js
@@ -30,9 +30,9 @@ describe('IntegrationHelpText component', () => {
it('should use the gl components', () => {
wrapper = createComponent();
- expect(wrapper.find(GlSprintf).exists()).toBe(true);
- expect(wrapper.find(GlIcon).exists()).toBe(true);
- expect(wrapper.find(GlLink).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSprintf).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(true);
});
it('should render the help text', () => {
@@ -44,9 +44,9 @@ describe('IntegrationHelpText component', () => {
it('should not use the gl-link and gl-icon components', () => {
wrapper = createComponent({ message: 'Click nowhere!' });
- expect(wrapper.find(GlSprintf).exists()).toBe(true);
- expect(wrapper.find(GlIcon).exists()).toBe(false);
- expect(wrapper.find(GlLink).exists()).toBe(false);
+ expect(wrapper.findComponent(GlSprintf).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(false);
});
it('should not render the link when start and end is not provided', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js
index 85a135d2b89..50864a4bf25 100644
--- a/spec/frontend/vue_shared/components/markdown/field_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/field_spec.js
@@ -76,7 +76,7 @@ describe('Markdown field component', () => {
const getMarkdownButton = () => subject.find('.js-md');
const getListBulletedButton = () => subject.findAll('.js-md[title="Add a bullet list"]');
const getVideo = () => subject.find('video');
- const getAttachButton = () => subject.find('.button-attach-file');
+ const getAttachButton = () => subject.findByTestId('button-attach-file');
const clickAttachButton = () => getAttachButton().trigger('click');
const findDropzone = () => subject.find('.div-dropzone');
const findMarkdownHeader = () => subject.findComponent(MarkdownFieldHeader);
@@ -232,13 +232,10 @@ describe('Markdown field component', () => {
});
});
- it('should render attach a file button', () => {
- expect(getAttachButton().text()).toBe('Attach a file');
- });
-
it('should trigger dropzone when attach button is clicked', () => {
expect(dropzoneSpy).not.toHaveBeenCalled();
+ getAttachButton().trigger('click');
clickAttachButton();
expect(dropzoneSpy).toHaveBeenCalled();
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index 67222cab247..9831908f806 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -21,7 +21,7 @@ describe('Markdown field header component', () => {
const findWriteTab = () => wrapper.findByTestId('write-tab');
const findPreviewTab = () => wrapper.findByTestId('preview-tab');
const findToolbar = () => wrapper.findByTestId('md-header-toolbar');
- const findToolbarButtons = () => wrapper.findAll(ToolbarButton);
+ const findToolbarButtons = () => wrapper.findAllComponents(ToolbarButton);
const findToolbarButtonByProp = (prop, value) =>
findToolbarButtons()
.filter((button) => button.props(prop) === value)
@@ -44,16 +44,16 @@ describe('Markdown field header component', () => {
describe('markdown header buttons', () => {
it('renders the buttons with the correct title', () => {
const buttons = [
+ 'Insert suggestion',
'Add bold text (⌘B)',
'Add italic text (⌘I)',
'Add strikethrough text (⌘⇧X)',
'Insert a quote',
- 'Insert suggestion',
'Insert code',
'Add a link (⌘K)',
'Add a bullet list',
'Add a numbered list',
- 'Add a task list',
+ 'Add a checklist',
'Add a collapsible section',
'Add a table',
'Go full screen',
@@ -65,6 +65,13 @@ describe('Markdown field header component', () => {
});
});
+ it('renders "Attach a file or image" button using gl-button', () => {
+ const button = wrapper.findByTestId('button-attach-file');
+
+ expect(button.element.tagName).toBe('GL-BUTTON-STUB');
+ expect(button.attributes('title')).toBe('Attach a file or image');
+ });
+
describe('when the user is on a non-Mac', () => {
beforeEach(() => {
delete window.gl.client.isMac;
@@ -118,8 +125,8 @@ describe('Markdown field header component', () => {
),
]);
- expect(wrapper.emitted('preview-markdown')).toBeFalsy();
- expect(wrapper.emitted('write-markdown')).toBeFalsy();
+ expect(wrapper.emitted('preview-markdown')).toBeUndefined();
+ expect(wrapper.emitted('write-markdown')).toBeUndefined();
});
it('blurs preview link after click', () => {
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
index 9944267cf24..9db1b779a04 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js
@@ -38,13 +38,13 @@ describe('Suggestion Diff component', () => {
wrapper.destroy();
});
- const findApplyButton = () => wrapper.find(ApplySuggestion);
+ const findApplyButton = () => wrapper.findComponent(ApplySuggestion);
const findApplyBatchButton = () => wrapper.find('.js-apply-batch-btn');
const findAddToBatchButton = () => wrapper.find('.js-add-to-batch-btn');
const findRemoveFromBatchButton = () => wrapper.find('.js-remove-from-batch-btn');
const findHeader = () => wrapper.find('.js-suggestion-diff-header');
const findHelpButton = () => wrapper.find('.js-help-btn');
- const findLoading = () => wrapper.find(GlLoadingIcon);
+ const findLoading = () => wrapper.findComponent(GlLoadingIcon);
it('renders a suggestion header', () => {
createComponent();
diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
index af27e953776..d84483c1663 100644
--- a/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js
@@ -71,7 +71,7 @@ describe('Suggestion Diff component', () => {
});
it('renders a correct amount of suggestion diff rows', () => {
- expect(wrapper.findAll(SuggestionDiffRow)).toHaveLength(3);
+ expect(wrapper.findAllComponents(SuggestionDiffRow)).toHaveLength(3);
});
it.each`
@@ -81,14 +81,14 @@ describe('Suggestion Diff component', () => {
${'addToBatch'} | ${[]} | ${[suggestionId]}
${'removeFromBatch'} | ${[]} | ${[suggestionId]}
`('emits $event event on sugestion diff header $event', ({ event, childArgs, args }) => {
- wrapper.find(SuggestionDiffHeader).vm.$emit(event, ...childArgs);
+ wrapper.findComponent(SuggestionDiffHeader).vm.$emit(event, ...childArgs);
expect(wrapper.emitted(event)).toBeDefined();
expect(wrapper.emitted(event)).toEqual([args]);
});
it('passes suggestion batch props to suggestion diff header', () => {
- expect(wrapper.find(SuggestionDiffHeader).props()).toMatchObject({
+ expect(wrapper.findComponent(SuggestionDiffHeader).props()).toMatchObject({
batchSuggestionsCount: 1,
isBatched: true,
isApplyingBatch: MOCK_DATA.suggestion.is_applying_batch,
diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
index 19e4f2d8c92..82210e79799 100644
--- a/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
@@ -26,7 +26,7 @@ describe('toolbar_button', () => {
});
const getButtonShortcutsAttr = () => {
- return wrapper.find(GlButton).attributes('data-md-shortcuts');
+ return wrapper.findComponent(GlButton).attributes('data-md-shortcuts');
};
describe('keyboard shortcuts', () => {
diff --git a/spec/frontend/vue_shared/components/memory_graph_spec.js b/spec/frontend/vue_shared/components/memory_graph_spec.js
index 53b96bd1b98..ae8d5ff78ba 100644
--- a/spec/frontend/vue_shared/components/memory_graph_spec.js
+++ b/spec/frontend/vue_shared/components/memory_graph_spec.js
@@ -47,7 +47,7 @@ describe('MemoryGraph', () => {
it('should draw container with chart', () => {
expect(wrapper.element).toMatchSnapshot();
expect(wrapper.find('.memory-graph-container').exists()).toBe(true);
- expect(wrapper.find(GlSparklineChart).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSparklineChart).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js b/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
index 2cefa77b72d..1789610dba9 100644
--- a/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
+++ b/spec/frontend/vue_shared/components/metric_images/metric_images_tab_spec.js
@@ -114,7 +114,7 @@ describe('Metric images tab', () => {
await waitForPromises();
- expect(findModal().attributes('visible')).toBeFalsy();
+ expect(findModal().attributes('visible')).toBeUndefined();
});
it('should add files and url when selected', async () => {
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
index c11b20a692e..2c14d65186b 100644
--- a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
+++ b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
@@ -1,5 +1,12 @@
import { nextTick } from 'vue';
-import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ GlIntersectionObserver,
+ GlLoadingIcon,
+} from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import NamespaceSelect, {
i18n,
@@ -7,7 +14,7 @@ import NamespaceSelect, {
} from '~/vue_shared/components/namespace_select/namespace_select.vue';
import { userNamespaces, groupNamespaces } from './mock_data';
-const FLAT_NAMESPACES = [...groupNamespaces, ...userNamespaces];
+const FLAT_NAMESPACES = [...userNamespaces, ...groupNamespaces];
const EMPTY_NAMESPACE_TITLE = 'Empty namespace TEST';
const EMPTY_NAMESPACE_ITEM = { id: EMPTY_NAMESPACE_ID, humanName: EMPTY_NAMESPACE_TITLE };
@@ -31,6 +38,8 @@ describe('Namespace Select', () => {
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);
@@ -59,7 +68,7 @@ describe('Namespace Select', () => {
it('splits group and user namespaces', () => {
const headers = findSectionHeaders();
- expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
+ expect(wrappersText(headers)).toEqual([i18n.USERS, i18n.GROUPS]);
});
it('does not render wrapper as full width', () => {
@@ -89,18 +98,20 @@ describe('Namespace Select', () => {
describe('with search', () => {
it.each`
- term | includeEmptyNamespace | expectedItems
- ${''} | ${false} | ${[...groupNamespaces, ...userNamespaces]}
- ${'sub'} | ${false} | ${[groupNamespaces[1]]}
- ${'User'} | ${false} | ${[...userNamespaces]}
- ${'User'} | ${true} | ${[...userNamespaces]}
- ${'namespace'} | ${true} | ${[EMPTY_NAMESPACE_ITEM, ...userNamespaces]}
+ 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 and includeEmptyNamespace=$includeEmptyNamespace, should show $expectedItems.length',
- async ({ term, includeEmptyNamespace, expectedItems }) => {
+ '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);
@@ -114,6 +125,18 @@ describe('Namespace Select', () => {
);
});
+ 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];
@@ -121,7 +144,8 @@ describe('Namespace Select', () => {
beforeEach(() => {
wrapper = createComponent();
- findDropdownItems().at(selectedGroupIndex).vm.$emit('click');
+ wrapper.findComponent(GlSearchBoxByType).vm.$emit('input', 'foo');
+ findGroupDropdownItems().at(selectedGroupIndex).vm.$emit('click');
});
it('sets the dropdown text', () => {
@@ -132,6 +156,10 @@ describe('Namespace Select', () => {
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', () => {
@@ -166,4 +194,33 @@ describe('Namespace Select', () => {
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/navigation_tabs_spec.js b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
index 30a89fed12f..b1bec28bffb 100644
--- a/spec/frontend/vue_shared/components/navigation_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/navigation_tabs_spec.js
@@ -44,7 +44,7 @@ describe('navigation tabs component', () => {
});
it('should render tabs', () => {
- expect(wrapper.findAll(GlTab)).toHaveLength(data.length);
+ expect(wrapper.findAllComponents(GlTab)).toHaveLength(data.length);
});
it('should render active tab', () => {
diff --git a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
index 99b65ca6937..17a62ae8a33 100644
--- a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
+++ b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
@@ -6,10 +6,11 @@ import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue'
describe('Issue Warning Component', () => {
let wrapper;
- const findIcon = (w = wrapper) => w.find(GlIcon);
- const findLockedBlock = (w = wrapper) => w.find({ ref: 'locked' });
- const findConfidentialBlock = (w = wrapper) => w.find({ ref: 'confidential' });
- const findLockedAndConfidentialBlock = (w = wrapper) => w.find({ ref: 'lockedAndConfidential' });
+ const findIcon = (w = wrapper) => w.findComponent(GlIcon);
+ const findLockedBlock = (w = wrapper) => w.findComponent({ ref: 'locked' });
+ const findConfidentialBlock = (w = wrapper) => w.findComponent({ ref: 'confidential' });
+ const findLockedAndConfidentialBlock = (w = wrapper) =>
+ w.findComponent({ ref: 'lockedAndConfidential' });
const createComponent = (props) =>
shallowMount(NoteableWarning, {
@@ -73,7 +74,7 @@ describe('Issue Warning Component', () => {
});
it('renders warning icon', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(true);
});
it('does not render information about locked noteable', () => {
@@ -99,7 +100,7 @@ describe('Issue Warning Component', () => {
});
it('does not render warning icon', () => {
- expect(wrapper.find(GlIcon).exists()).toBe(false);
+ expect(wrapper.findComponent(GlIcon).exists()).toBe(false);
});
it('does not render information about locked noteable', () => {
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 f951cfd5cd9..b86c8946e96 100644
--- a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
@@ -14,7 +14,7 @@ const getters = {
describe('Issue placeholder note component', () => {
let wrapper;
- const findNote = () => wrapper.find({ ref: 'note' });
+ const findNote = () => wrapper.findComponent({ ref: 'note' });
const createComponent = (isIndividual = false, propsData = {}) => {
wrapper = shallowMount(IssuePlaceholderNote, {
diff --git a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
index 51a936c0509..c0c3c4a9729 100644
--- a/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs_spec.js
@@ -92,15 +92,15 @@ describe('AlertManagementEmptyState', () => {
const EmptyState = () => wrapper.find('.empty-state');
const ItemsTable = () => wrapper.find('.gl-table');
- const ErrorAlert = () => wrapper.find(GlAlert);
- const Pagination = () => wrapper.find(GlPagination);
- const Tabs = () => wrapper.find(GlTabs);
+ const ErrorAlert = () => wrapper.findComponent(GlAlert);
+ const Pagination = () => wrapper.findComponent(GlPagination);
+ const Tabs = () => wrapper.findComponent(GlTabs);
const ActionButton = () => wrapper.find('.header-actions > button');
- const Filters = () => wrapper.find(FilteredSearchBar);
- const findPagination = () => wrapper.find(GlPagination);
- const findStatusFilterTabs = () => wrapper.findAll(GlTab);
- const findStatusTabs = () => wrapper.find(GlTabs);
- const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
+ const Filters = () => wrapper.findComponent(FilteredSearchBar);
+ const findPagination = () => wrapper.findComponent(GlPagination);
+ const findStatusFilterTabs = () => wrapper.findAllComponents(GlTab);
+ const findStatusTabs = () => wrapper.findComponent(GlTabs);
+ const findStatusFilterBadge = () => wrapper.findAllComponents(GlBadge);
describe('Snowplow tracking', () => {
beforeEach(() => {
@@ -213,7 +213,7 @@ describe('AlertManagementEmptyState', () => {
});
it('should render pagination', () => {
- expect(wrapper.find(GlPagination).exists()).toBe(true);
+ expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
});
describe('prevPage', () => {
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 08119dee8af..b3be2f8a775 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
@@ -64,7 +64,7 @@ describe('Pagination bar', () => {
},
});
- expect(wrapper.find(GlDropdown).find('button').text()).toMatchInterpolatedText(
+ expect(wrapper.findComponent(GlDropdown).find('button').text()).toMatchInterpolatedText(
`${CURRENT_PAGE_SIZE} items per page`,
);
});
diff --git a/spec/frontend/vue_shared/components/pagination_links_spec.js b/spec/frontend/vue_shared/components/pagination_links_spec.js
index 83f1e2844f9..d444ad7a733 100644
--- a/spec/frontend/vue_shared/components/pagination_links_spec.js
+++ b/spec/frontend/vue_shared/components/pagination_links_spec.js
@@ -41,7 +41,7 @@ describe('Pagination links component', () => {
beforeEach(() => {
createComponent();
- glPagination = wrapper.find(GlPagination);
+ glPagination = wrapper.findComponent(GlPagination);
});
afterEach(() => {
diff --git a/spec/frontend/vue_shared/components/project_avatar_spec.js b/spec/frontend/vue_shared/components/project_avatar_spec.js
index d55f3127a74..af828fbca51 100644
--- a/spec/frontend/vue_shared/components/project_avatar_spec.js
+++ b/spec/frontend/vue_shared/components/project_avatar_spec.js
@@ -42,6 +42,42 @@ describe('ProjectAvatar', () => {
});
});
+ describe('with `projectId` prop', () => {
+ const validatorFunc = ProjectAvatar.props.projectId.validator;
+
+ it('prop validators return true for valid types', () => {
+ expect(validatorFunc(1)).toBe(true);
+ expect(validatorFunc('gid://gitlab/Project/1')).toBe(true);
+ });
+
+ it('prop validators return false for invalid types', () => {
+ expect(validatorFunc('1')).toBe(false);
+ });
+
+ it('renders GlAvatar with `entityId` 0 when `projectId` is not informed', () => {
+ createComponent({ props: { projectId: undefined } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('entityId')).toBe(0);
+ });
+
+ it('renders GlAvatar with specified `entityId` when `projectId` is a Number', () => {
+ const mockProjectId = 1;
+ createComponent({ props: { projectId: mockProjectId } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('entityId')).toBe(mockProjectId);
+ });
+
+ it('renders GlAvatar with specified `entityId` when `projectId` is a gid String', () => {
+ const mockProjectId = 'gid://gitlab/Project/1';
+ createComponent({ props: { projectId: mockProjectId } });
+
+ const avatar = findGlAvatar();
+ expect(avatar.props('entityId')).toBe(1);
+ });
+ });
+
describe('with `projectAvatarUrl` prop', () => {
it('renders GlAvatar with specified `src` prop', () => {
const mockProjectAvatarUrl = 'https://gitlab.com';
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 397ab2254b9..4e0c318c84e 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -56,6 +56,7 @@ describe('ProjectListItem component', () => {
expect(avatar.exists()).toBe(true);
expect(avatar.props()).toMatchObject({
+ projectId: project.id,
projectAvatarUrl: '',
projectName: project.name_with_namespace,
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
index 379e60c1b2d..a0832dd7030 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
@@ -15,7 +15,7 @@ describe('ProjectSelector component', () => {
let selected = [];
selected = selected.concat(allProjects.slice(0, 3)).concat(allProjects.slice(5, 8));
- const findSearchInput = () => wrapper.find(GlSearchBoxByType).find('input');
+ const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType).find('input');
const findLegendText = () => wrapper.find('[data-testid="legend-text"]').text();
const search = (query) => {
const searchInput = findSearchInput();
@@ -65,14 +65,14 @@ describe('ProjectSelector component', () => {
it(`triggers a "bottomReached" event when user has scrolled to the bottom of the list`, () => {
jest.spyOn(vm, '$emit').mockImplementation(() => {});
- wrapper.find(GlInfiniteScroll).vm.$emit('bottomReached');
+ wrapper.findComponent(GlInfiniteScroll).vm.$emit('bottomReached');
expect(vm.$emit).toHaveBeenCalledWith('bottomReached');
});
it(`triggers a "projectClicked" event when a project is clicked`, () => {
jest.spyOn(vm, '$emit').mockImplementation(() => {});
- wrapper.find(ProjectListItem).vm.$emit('click', head(searchResults));
+ wrapper.findComponent(ProjectListItem).vm.$emit('click', head(searchResults));
expect(vm.$emit).toHaveBeenCalledWith('projectClicked', head(searchResults));
});
diff --git a/spec/frontend/vue_shared/components/registry/code_instruction_spec.js b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
index 3a2ea263a05..8f19f0ea14d 100644
--- a/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
+++ b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
@@ -22,7 +22,7 @@ describe('Package code instruction', () => {
});
}
- const findCopyButton = () => wrapper.find(ClipboardButton);
+ const findCopyButton = () => wrapper.findComponent(ClipboardButton);
const findInputElement = () => wrapper.find('[data-testid="instruction-input"]');
const findMultilineInstruction = () => wrapper.find('[data-testid="multiline-instruction"]');
diff --git a/spec/frontend/vue_shared/components/registry/details_row_spec.js b/spec/frontend/vue_shared/components/registry/details_row_spec.js
index 3134e0d3e21..ebc9816f983 100644
--- a/spec/frontend/vue_shared/components/registry/details_row_spec.js
+++ b/spec/frontend/vue_shared/components/registry/details_row_spec.js
@@ -5,7 +5,7 @@ import component from '~/vue_shared/components/registry/details_row.vue';
describe('DetailsRow', () => {
let wrapper;
- const findIcon = () => wrapper.find(GlIcon);
+ const findIcon = () => wrapper.findComponent(GlIcon);
const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
const mountComponent = (props) => {
diff --git a/spec/frontend/vue_shared/components/registry/history_item_spec.js b/spec/frontend/vue_shared/components/registry/history_item_spec.js
index f146f87342f..947520567e6 100644
--- a/spec/frontend/vue_shared/components/registry/history_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/history_item_spec.js
@@ -27,8 +27,8 @@ describe('History Item', () => {
wrapper = null;
});
- const findTimelineEntry = () => wrapper.find(TimelineEntryItem);
- const findGlIcon = () => wrapper.find(GlIcon);
+ const findTimelineEntry = () => wrapper.findComponent(TimelineEntryItem);
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
const findBodySlot = () => wrapper.find('[data-testid="body-slot"]');
diff --git a/spec/frontend/vue_shared/components/registry/list_item_spec.js b/spec/frontend/vue_shared/components/registry/list_item_spec.js
index 6e9abb2bfb3..b941eb77c32 100644
--- a/spec/frontend/vue_shared/components/registry/list_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/list_item_spec.js
@@ -13,7 +13,7 @@ describe('list item', () => {
const findRightSecondarySlot = () => wrapper.find('[data-testid="right-secondary"]');
const findRightActionSlot = () => wrapper.find('[data-testid="right-action"]');
const findDetailsSlot = (name) => wrapper.find(`[data-testid="${name}"]`);
- const findToggleDetailsButton = () => wrapper.find(GlButton);
+ const findToggleDetailsButton = () => wrapper.findComponent(GlButton);
const mountComponent = (propsData, slots) => {
wrapper = shallowMount(component, {
diff --git a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
index e4abdc15fd5..a04e1e237d4 100644
--- a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
@@ -24,10 +24,10 @@ describe('Metadata Item', () => {
wrapper = null;
});
- const findIcon = () => wrapper.find(GlIcon);
- const findLink = (w = wrapper) => w.find(GlLink);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findLink = (w = wrapper) => w.findComponent(GlLink);
const findText = () => wrapper.find('[data-testid="metadata-item-text"]');
- const findTooltipOnTruncate = (w = wrapper) => w.find(TooltipOnTruncate);
+ const findTooltipOnTruncate = (w = wrapper) => w.findComponent(TooltipOnTruncate);
const findTextTooltip = () => wrapper.find('[data-testid="text-tooltip-container"]');
describe.each(['xs', 's', 'm', 'l', 'xl'])('size class', (size) => {
diff --git a/spec/frontend/vue_shared/components/registry/registry_search_spec.js b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
index 20716e79a04..70f4693ae81 100644
--- a/spec/frontend/vue_shared/components/registry/registry_search_spec.js
+++ b/spec/frontend/vue_shared/components/registry/registry_search_spec.js
@@ -6,9 +6,9 @@ import component from '~/vue_shared/components/registry/registry_search.vue';
describe('Registry Search', () => {
let wrapper;
- const findPackageListSorting = () => wrapper.find(GlSorting);
- const findSortingItems = () => wrapper.findAll(GlSortingItem);
- const findFilteredSearch = () => wrapper.find(GlFilteredSearch);
+ const findPackageListSorting = () => wrapper.findComponent(GlSorting);
+ const findSortingItems = () => wrapper.findAllComponents(GlSortingItem);
+ const findFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
const defaultProps = {
filters: [],
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
index b62676b35be..efb57ddd310 100644
--- a/spec/frontend/vue_shared/components/registry/title_area_spec.js
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -199,7 +199,7 @@ describe('title area', () => {
const message = findInfoMessages().at(0);
- expect(message.find(GlLink).attributes('href')).toBe('bar');
+ expect(message.findComponent(GlLink).attributes('href')).toBe('bar');
expect(message.text()).toBe('foo link');
});
diff --git a/spec/frontend/vue_shared/components/rich_timestamp_tooltip_spec.js b/spec/frontend/vue_shared/components/rich_timestamp_tooltip_spec.js
new file mode 100644
index 00000000000..5d96fe27676
--- /dev/null
+++ b/spec/frontend/vue_shared/components/rich_timestamp_tooltip_spec.js
@@ -0,0 +1,41 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import { formatDate } from '~/lib/utils/datetime_utility';
+import RichTimestampTooltip from '~/vue_shared/components/rich_timestamp_tooltip.vue';
+
+describe('RichTimestampTooltip', () => {
+ const currentDate = new Date();
+ const mockRawTimestamp = currentDate.toISOString();
+ const mockTimestamp = formatDate(currentDate);
+ let wrapper;
+
+ const createComponent = ({
+ target = 'some-element',
+ rawTimestamp = mockRawTimestamp,
+ timestampTypeText = 'Created',
+ } = {}) => {
+ wrapper = shallowMountExtended(RichTimestampTooltip, {
+ propsData: {
+ target,
+ rawTimestamp,
+ timestampTypeText,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the tooltip text header', () => {
+ expect(wrapper.findByTestId('header-text').text()).toBe('Created just now');
+ });
+
+ it('renders the tooltip text body', () => {
+ expect(wrapper.findByTestId('body-text').text()).toBe(mockTimestamp);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
index a38dcd626f4..7c5fc63856a 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
@@ -166,7 +166,7 @@ describe('RunnerInstructionsModal component', () => {
});
it('sets the focus on the default selected platform', () => {
- const findOsxPlatformButton = () => wrapper.find({ ref: 'osx' });
+ const findOsxPlatformButton = () => wrapper.findComponent({ ref: 'osx' });
findOsxPlatformButton().element.focus = jest.fn();
@@ -234,14 +234,14 @@ describe('RunnerInstructionsModal component', () => {
MockResizeObserver.mockResize('xs');
await nextTick();
- expect(findPlatformButtonGroup().attributes('vertical')).toBeTruthy();
+ expect(findPlatformButtonGroup().attributes('vertical')).toEqual('true');
});
it('to a non-xs viewport', async () => {
MockResizeObserver.mockResize('sm');
await nextTick();
- expect(findPlatformButtonGroup().props('vertical')).toBeFalsy();
+ expect(findPlatformButtonGroup().props('vertical')).toBeUndefined();
});
});
});
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 71ebe561def..c5672bc28cc 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
@@ -50,7 +50,7 @@ describe('Merge request artifact Download', () => {
return createMockApollo(requestHandlers);
};
- const findDownloadDropdown = () => wrapper.find(SecurityReportDownloadDropdown);
+ const findDownloadDropdown = () => wrapper.findComponent(SecurityReportDownloadDropdown);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js b/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
index ae86106d86e..08d3d5b19d4 100644
--- a/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
+++ b/spec/frontend/vue_shared/components/security_reports/help_icon_spec.js
@@ -17,9 +17,9 @@ describe('HelpIcon component', () => {
});
};
- const findLink = () => wrapper.find(GlLink);
- const findPopover = () => wrapper.find(GlPopover);
- const findPopoverTarget = () => wrapper.find({ ref: 'discoverProjectSecurity' });
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findPopover = () => wrapper.findComponent(GlPopover);
+ const findPopoverTarget = () => wrapper.findComponent({ ref: 'discoverProjectSecurity' });
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
index f213e37cbc1..9b1316677d7 100644
--- a/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/issuable_move_dropdown_spec.js
@@ -173,15 +173,15 @@ describe('IssuableMoveDropdown', () => {
});
describe('template', () => {
- const findDropdownEl = () => wrapper.find(GlDropdown);
+ const findDropdownEl = () => wrapper.findComponent(GlDropdown);
it('renders collapsed state element with icon', () => {
const collapsedEl = wrapper.find('[data-testid="move-collapsed"]');
expect(collapsedEl.exists()).toBe(true);
expect(collapsedEl.attributes('title')).toBe(mockProps.dropdownButtonTitle);
- expect(collapsedEl.find(GlIcon).exists()).toBe(true);
- expect(collapsedEl.find(GlIcon).props('name')).toBe('arrow-right');
+ expect(collapsedEl.findComponent(GlIcon).exists()).toBe(true);
+ expect(collapsedEl.findComponent(GlIcon).props('name')).toBe('arrow-right');
});
describe('gl-dropdown component', () => {
@@ -191,7 +191,7 @@ describe('IssuableMoveDropdown', () => {
});
it('renders gl-dropdown-form component', () => {
- expect(findDropdownEl().find(GlDropdownForm).exists()).toBe(true);
+ expect(findDropdownEl().findComponent(GlDropdownForm).exists()).toBe(true);
});
it('renders header element', () => {
@@ -199,11 +199,11 @@ describe('IssuableMoveDropdown', () => {
expect(headerEl.exists()).toBe(true);
expect(headerEl.find('span').text()).toBe(mockProps.dropdownHeaderTitle);
- expect(headerEl.find(GlButton).props('icon')).toBe('close');
+ expect(headerEl.findComponent(GlButton).props('icon')).toBe('close');
});
it('renders gl-search-box-by-type component', () => {
- const searchEl = findDropdownEl().find(GlSearchBoxByType);
+ const searchEl = findDropdownEl().findComponent(GlSearchBoxByType);
expect(searchEl.exists()).toBe(true);
expect(searchEl.attributes()).toMatchObject({
@@ -221,7 +221,7 @@ describe('IssuableMoveDropdown', () => {
await nextTick();
- expect(findDropdownEl().find(GlLoadingIcon).exists()).toBe(true);
+ expect(findDropdownEl().findComponent(GlLoadingIcon).exists()).toBe(true);
});
it('renders gl-dropdown-item components for available projects', async () => {
@@ -234,7 +234,7 @@ describe('IssuableMoveDropdown', () => {
await nextTick();
- const dropdownItems = wrapper.findAll(GlDropdownItem);
+ const dropdownItems = wrapper.findAllComponents(GlDropdownItem);
expect(dropdownItems).toHaveLength(mockProjects.length);
expect(dropdownItems.at(0).props()).toMatchObject({
@@ -285,7 +285,7 @@ describe('IssuableMoveDropdown', () => {
});
it('renders gl-button within footer', async () => {
- const moveButtonEl = wrapper.find('[data-testid="footer"]').find(GlButton);
+ const moveButtonEl = wrapper.find('[data-testid="footer"]').findComponent(GlButton);
expect(moveButtonEl.text()).toBe('Move');
expect(moveButtonEl.attributes('disabled')).toBe('true');
@@ -299,7 +299,7 @@ describe('IssuableMoveDropdown', () => {
await nextTick();
expect(
- wrapper.find('[data-testid="footer"]').find(GlButton).attributes('disabled'),
+ wrapper.find('[data-testid="footer"]').findComponent(GlButton).attributes('disabled'),
).not.toBeDefined();
});
});
@@ -308,7 +308,7 @@ describe('IssuableMoveDropdown', () => {
it('collapsed state element emits `toggle-collapse` event on component when clicked', () => {
wrapper.find('[data-testid="move-collapsed"]').trigger('click');
- expect(wrapper.emitted('toggle-collapse')).toBeTruthy();
+ expect(wrapper.emitted('toggle-collapse')).toHaveLength(1);
});
it('gl-dropdown component calls `fetchProjects` on `shown` event', () => {
@@ -337,11 +337,11 @@ describe('IssuableMoveDropdown', () => {
it('gl-dropdown component emits `dropdown-close` event on component from `hide` event', async () => {
findDropdownEl().vm.$emit('hide');
- expect(wrapper.emitted('dropdown-close')).toBeTruthy();
+ expect(wrapper.emitted('dropdown-close')).toHaveLength(1);
});
it('close icon in dropdown header closes the dropdown when clicked', () => {
- wrapper.find('[data-testid="header"]').find(GlButton).vm.$emit('click', mockEvent);
+ wrapper.find('[data-testid="header"]').findComponent(GlButton).vm.$emit('click', mockEvent);
expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
});
@@ -355,7 +355,7 @@ describe('IssuableMoveDropdown', () => {
await nextTick();
- wrapper.findAll(GlDropdownItem).at(0).vm.$emit('click', mockEvent);
+ wrapper.findAllComponents(GlDropdownItem).at(0).vm.$emit('click', mockEvent);
expect(wrapper.vm.selectedProject).toBe(mockProjects[0]);
});
@@ -369,10 +369,10 @@ describe('IssuableMoveDropdown', () => {
await nextTick();
- wrapper.find('[data-testid="footer"]').find(GlButton).vm.$emit('click');
+ wrapper.find('[data-testid="footer"]').findComponent(GlButton).vm.$emit('click');
expect(wrapper.vm.$refs.dropdown.hide).toHaveBeenCalled();
- expect(wrapper.emitted('move-issuable')).toBeTruthy();
+ expect(wrapper.emitted('move-issuable')).toHaveLength(1);
expect(wrapper.emitted('move-issuable')[0]).toEqual([mockProjects[0]]);
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
index c05513a6d5f..c0e5408e1bd 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
@@ -33,9 +33,9 @@ describe('DropdownButton', () => {
wrapper.destroy();
});
- const findDropdownButton = () => wrapper.find(GlButton);
+ const findDropdownButton = () => wrapper.findComponent(GlButton);
const findDropdownText = () => wrapper.find('.dropdown-toggle-text');
- const findDropdownIcon = () => wrapper.find(GlIcon);
+ const findDropdownIcon = () => wrapper.findComponent(GlIcon);
describe('methods', () => {
describe('handleButtonClick', () => {
@@ -61,7 +61,7 @@ describe('DropdownButton', () => {
describe('template', () => {
it('renders component container element', () => {
- expect(wrapper.find(GlButton).element).toBe(wrapper.element);
+ expect(wrapper.findComponent(GlButton).element).toBe(wrapper.element);
});
it('renders default button text element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
index 0673ffee22b..799e2c1d08e 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
@@ -127,7 +127,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders dropdown back button element', () => {
- const backBtnEl = wrapper.find('.dropdown-title').findAll(GlButton).at(0);
+ const backBtnEl = wrapper.find('.dropdown-title').findAllComponents(GlButton).at(0);
expect(backBtnEl.exists()).toBe(true);
expect(backBtnEl.attributes('aria-label')).toBe('Go back');
@@ -142,7 +142,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders dropdown close button element', () => {
- const closeBtnEl = wrapper.find('.dropdown-title').findAll(GlButton).at(1);
+ const closeBtnEl = wrapper.find('.dropdown-title').findAllComponents(GlButton).at(1);
expect(closeBtnEl.exists()).toBe(true);
expect(closeBtnEl.attributes('aria-label')).toBe('Close');
@@ -150,7 +150,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders label title input element', () => {
- const titleInputEl = wrapper.find('.dropdown-input').find(GlFormInput);
+ const titleInputEl = wrapper.find('.dropdown-input').findComponent(GlFormInput);
expect(titleInputEl.exists()).toBe(true);
expect(titleInputEl.attributes('placeholder')).toBe('Name new label');
@@ -158,7 +158,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders color block element for all suggested colors', () => {
- const colorBlocksEl = wrapper.find('.dropdown-content').findAll(GlLink);
+ const colorBlocksEl = wrapper.find('.dropdown-content').findAllComponents(GlLink);
colorBlocksEl.wrappers.forEach((colorBlock, index) => {
expect(colorBlock.attributes('style')).toContain('background-color');
@@ -175,7 +175,7 @@ describe('DropdownContentsCreateView', () => {
await nextTick();
const colorPreviewEl = wrapper.find('.color-input-container > .dropdown-label-color-preview');
- const colorInputEl = wrapper.find('.color-input-container').find(GlFormInput);
+ const colorInputEl = wrapper.find('.color-input-container').findComponent(GlFormInput);
expect(colorPreviewEl.exists()).toBe(true);
expect(colorPreviewEl.attributes('style')).toContain('background-color');
@@ -185,7 +185,7 @@ describe('DropdownContentsCreateView', () => {
});
it('renders create button element', () => {
- const createBtnEl = wrapper.find('.dropdown-actions').findAll(GlButton).at(0);
+ const createBtnEl = wrapper.find('.dropdown-actions').findAllComponents(GlButton).at(0);
expect(createBtnEl.exists()).toBe(true);
expect(createBtnEl.text()).toContain('Create');
@@ -195,14 +195,14 @@ describe('DropdownContentsCreateView', () => {
wrapper.vm.$store.dispatch('requestCreateLabel');
await nextTick();
- const loadingIconEl = wrapper.find('.dropdown-actions').find(GlLoadingIcon);
+ const loadingIconEl = wrapper.find('.dropdown-actions').findComponent(GlLoadingIcon);
expect(loadingIconEl.exists()).toBe(true);
expect(loadingIconEl.isVisible()).toBe(true);
});
it('renders cancel button element', () => {
- const cancelBtnEl = wrapper.find('.dropdown-actions').findAll(GlButton).at(1);
+ const cancelBtnEl = wrapper.find('.dropdown-actions').findAllComponents(GlButton).at(1);
expect(cancelBtnEl.exists()).toBe(true);
expect(cancelBtnEl.text()).toContain('Cancel');
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index 00c8e3a814a..cc9b9f393ce 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -58,7 +58,7 @@ describe('DropdownContentsLabelsView', () => {
const findDropdownContent = () => wrapper.find('[data-testid="dropdown-content"]');
const findDropdownTitle = () => wrapper.find('[data-testid="dropdown-title"]');
const findDropdownFooter = () => wrapper.find('[data-testid="dropdown-footer"]');
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
describe('computed', () => {
describe('visibleLabels', () => {
@@ -285,7 +285,7 @@ describe('DropdownContentsLabelsView', () => {
describe('template', () => {
it('renders gl-intersection-observer as component root', () => {
- expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true);
+ expect(wrapper.findComponent(GlIntersectionObserver).exists()).toBe(true);
});
it('renders gl-loading-icon component when `labelsFetchInProgress` prop is true', async () => {
@@ -316,20 +316,20 @@ describe('DropdownContentsLabelsView', () => {
});
it('renders dropdown close button element', () => {
- const closeButtonEl = findDropdownTitle().find(GlButton);
+ const closeButtonEl = findDropdownTitle().findComponent(GlButton);
expect(closeButtonEl.exists()).toBe(true);
expect(closeButtonEl.props('icon')).toBe('close');
});
it('renders label search input element', () => {
- const searchInputEl = wrapper.find(GlSearchBoxByType);
+ const searchInputEl = wrapper.findComponent(GlSearchBoxByType);
expect(searchInputEl.exists()).toBe(true);
});
it('renders label elements for all labels', () => {
- expect(wrapper.findAll(LabelItem)).toHaveLength(mockLabels.length);
+ expect(wrapper.findAllComponents(LabelItem)).toHaveLength(mockLabels.length);
});
it('renders label element with `highlight` set to true when value of `currentHighlightItem` is more than -1', async () => {
@@ -340,7 +340,7 @@ describe('DropdownContentsLabelsView', () => {
});
await nextTick();
- const labelItemEl = findDropdownContent().find(LabelItem);
+ const labelItemEl = findDropdownContent().findComponent(LabelItem);
expect(labelItemEl.attributes('highlight')).toBe('true');
});
@@ -373,7 +373,7 @@ describe('DropdownContentsLabelsView', () => {
});
it('renders footer list items', () => {
- const footerLinks = findDropdownFooter().findAll(GlLink);
+ const footerLinks = findDropdownFooter().findAllComponents(GlLink);
const createLabelLink = footerLinks.at(0);
const manageLabelsLink = footerLinks.at(1);
@@ -387,7 +387,7 @@ describe('DropdownContentsLabelsView', () => {
wrapper.vm.$store.state.allowLabelCreate = false;
await nextTick();
- const createLabelLink = findDropdownFooter().findAll(GlLink).at(0);
+ const createLabelLink = findDropdownFooter().findAllComponents(GlLink).at(0);
expect(createLabelLink.text()).not.toBe('Create label');
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
index 84e9f3f41c3..54804f85f81 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
@@ -41,7 +41,7 @@ describe('DropdownTitle', () => {
});
it('renders edit link', () => {
- const editBtnEl = wrapper.find(GlButton);
+ const editBtnEl = wrapper.findComponent(GlButton);
expect(editBtnEl.exists()).toBe(true);
expect(editBtnEl.text()).toBe('Edit');
@@ -53,7 +53,7 @@ describe('DropdownTitle', () => {
});
await nextTick();
- expect(wrapper.find(GlLoadingIcon).isVisible()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).isVisible()).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
index bedb6204088..bb0f1777de6 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/label_item_spec.js
@@ -32,7 +32,7 @@ describe('LabelItem', () => {
describe('template', () => {
it('renders gl-link component', () => {
- expect(wrapper.find(GlLink).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLink).exists()).toBe(true);
});
it('renders component root with class `is-focused` when `highlight` prop is true', () => {
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 c150410ff8e..4c7ac6e9a6f 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
@@ -138,13 +138,13 @@ describe('LabelsSelectRoot', () => {
it('renders `dropdown-value-collapsed` component when `allowLabelCreate` prop is `true`', async () => {
createComponent();
await nextTick();
- expect(wrapper.find(DropdownValueCollapsed).exists()).toBe(true);
+ expect(wrapper.findComponent(DropdownValueCollapsed).exists()).toBe(true);
});
it('renders `dropdown-title` component', async () => {
createComponent();
await nextTick();
- expect(wrapper.find(DropdownTitle).exists()).toBe(true);
+ expect(wrapper.findComponent(DropdownTitle).exists()).toBe(true);
});
it('renders `dropdown-value` component', async () => {
@@ -153,7 +153,7 @@ describe('LabelsSelectRoot', () => {
});
await nextTick();
- const valueComp = wrapper.find(DropdownValue);
+ const valueComp = wrapper.findComponent(DropdownValue);
expect(valueComp.exists()).toBe(true);
expect(valueComp.text()).toBe('None');
@@ -163,14 +163,14 @@ describe('LabelsSelectRoot', () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownButton');
await nextTick();
- expect(wrapper.find(DropdownButton).exists()).toBe(true);
+ expect(wrapper.findComponent(DropdownButton).exists()).toBe(true);
});
it('renders `dropdown-contents` component when `showDropdownButton` & `showDropdownContents` prop is `true`', async () => {
createComponent();
wrapper.vm.$store.dispatch('toggleDropdownContents');
await nextTick();
- expect(wrapper.find(DropdownContents).exists()).toBe(true);
+ expect(wrapper.findComponent(DropdownContents).exists()).toBe(true);
});
describe('sets content direction based on viewport', () => {
@@ -187,7 +187,7 @@ describe('LabelsSelectRoot', () => {
wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
await nextTick();
- expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(true);
+ expect(wrapper.findComponent(DropdownContents).props('renderOnTop')).toBe(true);
});
it('does not set direction when inside of viewport', async () => {
@@ -195,7 +195,7 @@ describe('LabelsSelectRoot', () => {
wrapper.vm.setContentIsOnViewport(wrapper.vm.$store.state);
await nextTick();
- expect(wrapper.find(DropdownContents).props('renderOnTop')).toBe(false);
+ expect(wrapper.findComponent(DropdownContents).props('renderOnTop')).toBe(false);
});
},
);
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 1b27a294b90..cad401e0013 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
@@ -131,6 +131,7 @@ describe('LabelsSelectRoot', () => {
expect(findDropdownValue().exists()).toBe(true);
expect(findDropdownValue().props('selectedLabels')).toEqual([
{
+ __typename: 'Label',
color: '#330066',
description: null,
id: 'gid://gitlab/ProjectLabel/1',
diff --git a/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js b/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js
index de3e1ccfb03..01958a144ed 100644
--- a/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/todo_button_spec.js
@@ -30,19 +30,19 @@ describe('Todo Button', () => {
it('renders GlButton', () => {
createComponent();
- expect(wrapper.find(GlButton).exists()).toBe(true);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(true);
});
it('emits click event when clicked', () => {
createComponent({}, mount);
- wrapper.find(GlButton).trigger('click');
+ wrapper.findComponent(GlButton).trigger('click');
- expect(wrapper.emitted().click).toBeTruthy();
+ expect(wrapper.emitted().click).toHaveLength(1);
});
it('calls dispatchDocumentEvent to update global To-Do counter correctly', () => {
createComponent({}, mount);
- wrapper.find(GlButton).trigger('click');
+ wrapper.findComponent(GlButton).trigger('click');
const dispatchedEvent = dispatchEventSpy.mock.calls[0][0];
expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
@@ -57,12 +57,12 @@ describe('Todo Button', () => {
`('sets correct label when isTodo is $isTodo', ({ label, isTodo }) => {
createComponent({ isTodo });
- expect(wrapper.find(GlButton).text()).toBe(label);
+ expect(wrapper.findComponent(GlButton).text()).toBe(label);
});
it('binds additional props to GlButton', () => {
createComponent({ loading: true });
- expect(wrapper.find(GlButton).props('loading')).toBe(true);
+ expect(wrapper.findComponent(GlButton).props('loading')).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/source_editor_spec.js b/spec/frontend/vue_shared/components/source_editor_spec.js
index dca4d60e23c..ca5b990bc29 100644
--- a/spec/frontend/vue_shared/components/source_editor_spec.js
+++ b/spec/frontend/vue_shared/components/source_editor_spec.js
@@ -3,6 +3,7 @@ import { nextTick } from 'vue';
import { EDITOR_READY_EVENT } from '~/editor/constants';
import Editor from '~/editor/source_editor';
import SourceEditor from '~/vue_shared/components/source_editor.vue';
+import * as helpers from 'jest/editor/helpers';
jest.mock('~/editor/source_editor');
@@ -13,6 +14,7 @@ describe('Source Editor component', () => {
const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
const fileName = 'lorem.txt';
const fileGlobalId = 'snippet_777';
+ const useSpy = jest.fn();
const createInstanceMock = jest.fn().mockImplementation(() => {
mockInstance = {
onDidChangeModelContent: jest.fn(),
@@ -20,6 +22,7 @@ describe('Source Editor component', () => {
getValue: jest.fn(),
setValue: jest.fn(),
dispose: jest.fn(),
+ use: useSpy,
};
return mockInstance;
});
@@ -77,16 +80,33 @@ describe('Source Editor component', () => {
});
it('initialises Source Editor instance', () => {
- const el = wrapper.find({ ref: 'editor' }).element;
+ const el = wrapper.findComponent({ ref: 'editor' }).element;
expect(createInstanceMock).toHaveBeenCalledWith({
el,
blobPath: fileName,
blobGlobalId: fileGlobalId,
blobContent: value,
- extensions: null,
});
});
+ it.each`
+ description | extensions | toBeCalled
+ ${'no extension when `undefined` is'} | ${undefined} | ${false}
+ ${'no extension when {} is'} | ${{}} | ${false}
+ ${'no extension when [] is'} | ${[]} | ${false}
+ ${'single extension'} | ${{ definition: helpers.SEClassExtension }} | ${true}
+ ${'single extension with options'} | ${{ definition: helpers.SEWithSetupExt, setupOptions: { foo: 'bar' } }} | ${true}
+ ${'multiple extensions'} | ${[{ definition: helpers.SEClassExtension }, { definition: helpers.SEWithSetupExt }]} | ${true}
+ ${'multiple extensions with options'} | ${[{ definition: helpers.SEClassExtension }, { definition: helpers.SEWithSetupExt, setupOptions: { foo: 'bar' } }]} | ${true}
+ `('installs $description passed as a prop', ({ extensions, toBeCalled }) => {
+ createComponent({ extensions });
+ if (toBeCalled) {
+ expect(useSpy).toHaveBeenCalledWith(extensions);
+ } else {
+ expect(useSpy).not.toHaveBeenCalled();
+ }
+ });
+
it('reacts to the changes in fileName', () => {
const newFileName = 'ipsum.txt';
@@ -112,7 +132,7 @@ describe('Source Editor component', () => {
});
it('emits EDITOR_READY_EVENT event when the Source Editor is ready', async () => {
- const el = wrapper.find({ ref: 'editor' }).element;
+ const el = wrapper.findComponent({ ref: 'editor' }).element;
expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined();
await el.dispatchEvent(new Event(EDITOR_READY_EVENT));
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 eb2eec92534..fd3ff9ce892 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,4 +1,3 @@
-import { GlLink } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ChunkLine from '~/vue_shared/components/source_viewer/components/chunk_line.vue';
import {
@@ -11,16 +10,26 @@ const DEFAULT_PROPS = {
number: 2,
content: '// Line content',
language: 'javascript',
+ blamePath: 'blame/file.js',
};
describe('Chunk Line component', () => {
let wrapper;
+ const fileLineBlame = true;
const createComponent = (props = {}) => {
- wrapper = shallowMountExtended(ChunkLine, { propsData: { ...DEFAULT_PROPS, ...props } });
+ wrapper = shallowMountExtended(ChunkLine, {
+ propsData: { ...DEFAULT_PROPS, ...props },
+ provide: {
+ glFeatures: {
+ fileLineBlame,
+ },
+ },
+ });
};
- const findLink = () => wrapper.findComponent(GlLink);
+ 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');
@@ -47,14 +56,22 @@ describe('Chunk Line component', () => {
});
});
+ it('renders a blame link', () => {
+ expect(findBlameLink().attributes()).toMatchObject({
+ href: `${DEFAULT_PROPS.blamePath}#L${DEFAULT_PROPS.number}`,
+ });
+
+ expect(findBlameLink().text()).toBe('');
+ });
+
it('renders a line number', () => {
- expect(findLink().attributes()).toMatchObject({
+ expect(findLineLink().attributes()).toMatchObject({
'data-line-number': `${DEFAULT_PROPS.number}`,
- to: `#L${DEFAULT_PROPS.number}`,
+ href: `#L${DEFAULT_PROPS.number}`,
id: `L${DEFAULT_PROPS.number}`,
});
- expect(findLink().text()).toBe(DEFAULT_PROPS.number.toString());
+ expect(findLineLink().text()).toBe(DEFAULT_PROPS.number.toString());
});
it('renders content', () => {
diff --git a/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js b/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js
index 42c4f2eacb8..8dc3348acfa 100644
--- a/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js
@@ -10,6 +10,7 @@ const DEFAULT_PROPS = {
startingFrom: 140,
totalLines: 50,
language: 'javascript',
+ blamePath: 'blame/file.js',
};
describe('Chunk component', () => {
@@ -76,6 +77,7 @@ describe('Chunk component', () => {
number: DEFAULT_PROPS.startingFrom + 1,
content: splitContent[0],
language: DEFAULT_PROPS.language,
+ blamePath: DEFAULT_PROPS.blamePath,
});
});
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js
index 3036ce43888..375b1307616 100644
--- a/spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/link_dependencies_spec.js
@@ -1,8 +1,10 @@
import packageJsonLinker from '~/vue_shared/components/source_viewer/plugins/utils/package_json_linker';
+import gemspecLinker from '~/vue_shared/components/source_viewer/plugins/utils/gemspec_linker';
import linkDependencies from '~/vue_shared/components/source_viewer/plugins/link_dependencies';
-import { PACKAGE_JSON_FILE_TYPE, PACKAGE_JSON_CONTENT } from './mock_data';
+import { PACKAGE_JSON_FILE_TYPE, PACKAGE_JSON_CONTENT, GEMSPEC_FILE_TYPE } from './mock_data';
jest.mock('~/vue_shared/components/source_viewer/plugins/utils/package_json_linker');
+jest.mock('~/vue_shared/components/source_viewer/plugins/utils/gemspec_linker');
describe('Highlight.js plugin for linking dependencies', () => {
const hljsResultMock = { value: 'test' };
@@ -11,4 +13,9 @@ describe('Highlight.js plugin for linking dependencies', () => {
linkDependencies(hljsResultMock, PACKAGE_JSON_FILE_TYPE, PACKAGE_JSON_CONTENT);
expect(packageJsonLinker).toHaveBeenCalled();
});
+
+ it('calls gemspecLinker for gemspec file types', () => {
+ linkDependencies(hljsResultMock, GEMSPEC_FILE_TYPE);
+ expect(gemspecLinker).toHaveBeenCalled();
+ });
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/mock_data.js b/spec/frontend/vue_shared/components/source_viewer/plugins/mock_data.js
index 75659770e2c..aa874c9c081 100644
--- a/spec/frontend/vue_shared/components/source_viewer/plugins/mock_data.js
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/mock_data.js
@@ -1,2 +1,4 @@
export const PACKAGE_JSON_FILE_TYPE = 'package_json';
export const PACKAGE_JSON_CONTENT = '{ "dependencies": { "@babel/core": "^7.18.5" } }';
+
+export const GEMSPEC_FILE_TYPE = 'gemspec';
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 ee200747af9..8079d5ad99a 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
@@ -14,10 +14,11 @@ describe('createLink', () => {
it('escapes the user-controlled content', () => {
const unescapedXSS = '<script>XSS</script>';
- const escapedXSS = '&amp;lt;script&amp;gt;XSS&amp;lt;/script&amp;gt;';
+ const escapedPackageName = '&lt;script&gt;XSS&lt;/script&gt;';
+ const escapedHref = '&amp;lt;script&amp;gt;XSS&amp;lt;/script&amp;gt;';
const href = `http://test.com/${unescapedXSS}`;
const innerText = `testing${unescapedXSS}`;
- const result = `<a href="http://test.com/${escapedXSS}" rel="nofollow noreferrer noopener">testing${escapedXSS}</a>`;
+ const result = `<a href="http://test.com/${escapedHref}" rel="nofollow noreferrer noopener">testing${escapedPackageName}</a>`;
expect(createLink(href, innerText)).toBe(result);
});
diff --git a/spec/frontend/vue_shared/components/source_viewer/plugins/utils/gemspec_linker_spec.js b/spec/frontend/vue_shared/components/source_viewer/plugins/utils/gemspec_linker_spec.js
new file mode 100644
index 00000000000..3f74bfa117f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer/plugins/utils/gemspec_linker_spec.js
@@ -0,0 +1,14 @@
+import gemspecLinker from '~/vue_shared/components/source_viewer/plugins/utils/gemspec_linker';
+
+describe('Highlight.js plugin for linking gemspec dependencies', () => {
+ it('mutates the input value by wrapping dependency names in anchors', () => {
+ const inputValue =
+ 's.add_dependency(<span class="hljs-string">&#x27;rugged&#x27;</span>, <span class="hljs-string">&#x27;~&gt; 0.24.0&#x27;</span>)';
+ const outputValue =
+ 's.add_dependency(<span class="hljs-string linked">&#x27;<a href="https://rubygems.org/gems/rugged" rel="nofollow noreferrer noopener">rugged</a>&#x27;</span>, <span class="hljs-string">&#x27;~&gt; 0.24.0&#x27;</span>)';
+ const hljsResultMock = { value: inputValue };
+
+ const output = gemspecLinker(hljsResultMock);
+ expect(output).toBe(outputValue);
+ });
+});
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 2c03b7aa7d3..4fbc907a813 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
@@ -40,8 +40,9 @@ describe('Source Viewer component', () => {
const chunk2 = generateContent('// Some source code 2', 70);
const content = chunk1 + chunk2;
const path = 'some/path.js';
+ const blamePath = 'some/blame/path.js';
const fileType = 'javascript';
- const DEFAULT_BLOB_DATA = { language, rawTextBlob: content, path, fileType };
+ const DEFAULT_BLOB_DATA = { language, rawTextBlob: content, path, blamePath, fileType };
const highlightedContent = `<span data-testid='test-highlighted' id='LC1'>${content}</span><span id='LC2'></span>`;
const createComponent = async (blob = {}) => {
diff --git a/spec/frontend/vue_shared/components/split_button_spec.js b/spec/frontend/vue_shared/components/split_button_spec.js
index 4965969bc3e..6b869db4058 100644
--- a/spec/frontend/vue_shared/components/split_button_spec.js
+++ b/spec/frontend/vue_shared/components/split_button_spec.js
@@ -26,8 +26,9 @@ describe('SplitButton', () => {
});
};
- const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItem = (index = 0) => findDropdown().findAll(GlDropdownItem).at(index);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItem = (index = 0) =>
+ findDropdown().findAllComponents(GlDropdownItem).at(index);
const selectItem = async (index) => {
findDropdownItem(index).vm.$emit('click');
diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js
index ed23a47c328..99de26ce2ae 100644
--- a/spec/frontend/vue_shared/components/table_pagination_spec.js
+++ b/spec/frontend/vue_shared/components/table_pagination_spec.js
@@ -50,7 +50,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(wrapper.find(GlPagination).exists()).toBe(true);
+ expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
});
it('renders if there is a prev page', () => {
@@ -66,7 +66,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(wrapper.find(GlPagination).exists()).toBe(true);
+ expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
});
});
@@ -83,7 +83,7 @@ describe('Pagination component', () => {
},
change: spy,
});
- wrapper.find(GlPagination).vm.$emit('input', 3);
+ wrapper.findComponent(GlPagination).vm.$emit('input', 3);
expect(spy).toHaveBeenCalledWith(3);
});
});
diff --git a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
index 9e7e5c1263f..ca1f7996ad6 100644
--- a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
+++ b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
@@ -68,7 +68,7 @@ describe('TooltipOnTruncate component', () => {
},
);
- wrapper = parent.find(WrappedTooltipOnTruncate);
+ wrapper = parent.findComponent(WrappedTooltipOnTruncate);
};
const getTooltipValue = () => getBinding(wrapper.element, 'gl-tooltip')?.value;
diff --git a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
index 21e9b401215..a063a5591e3 100644
--- a/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
+++ b/spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
@@ -14,7 +14,7 @@ describe('Upload dropzone component', () => {
const findDropzoneCard = () => wrapper.find('.upload-dropzone-card');
const findDropzoneArea = () => wrapper.find('[data-testid="dropzone-area"]');
- const findIcon = () => wrapper.find(GlIcon);
+ const findIcon = () => wrapper.findComponent(GlIcon);
const findUploadText = () => wrapper.find('[data-testid="upload-text"]').text();
const findFileInput = () => wrapper.find('input[type="file"]');
diff --git a/spec/frontend/vue_shared/components/user_access_role_badge_spec.js b/spec/frontend/vue_shared/components/user_access_role_badge_spec.js
index 7f25f7c08e7..cea6fcac8c8 100644
--- a/spec/frontend/vue_shared/components/user_access_role_badge_spec.js
+++ b/spec/frontend/vue_shared/components/user_access_role_badge_spec.js
@@ -18,7 +18,7 @@ describe('UserAccessRoleBadge', () => {
},
});
- const badge = wrapper.find(GlBadge);
+ const badge = wrapper.findComponent(GlBadge);
expect(badge.exists()).toBe(true);
expect(badge.html()).toContain('test slot content');
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
index 5e05b54cb8c..f87737ca86a 100644
--- 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
@@ -18,6 +18,8 @@ const PROVIDED_PROPS = {
describe('User Avatar Image Component', () => {
let wrapper;
+ const findAvatar = () => wrapper.findComponent(GlAvatar);
+
afterEach(() => {
wrapper.destroy();
});
@@ -28,21 +30,14 @@ describe('User Avatar Image Component', () => {
propsData: {
...PROVIDED_PROPS,
},
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
});
});
it('should render `GlAvatar` and provide correct properties to it', () => {
- const avatar = wrapper.findComponent(GlAvatar);
-
- expect(avatar.attributes('data-src')).toBe(
+ expect(findAvatar().attributes('data-src')).toBe(
`${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
);
- expect(avatar.props()).toMatchObject({
+ expect(findAvatar().props()).toMatchObject({
src: `${PROVIDED_PROPS.imgSrc}?width=${PROVIDED_PROPS.size}`,
alt: PROVIDED_PROPS.imgAlt,
size: PROVIDED_PROPS.size,
@@ -63,23 +58,28 @@ describe('User Avatar Image Component', () => {
...PROVIDED_PROPS,
lazy: true,
},
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
});
});
it('should add lazy attributes', () => {
- const avatar = wrapper.findComponent(GlAvatar);
-
- expect(avatar.classes()).toContain('lazy');
- expect(avatar.attributes()).toMatchObject({
+ 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', () => {
@@ -89,18 +89,11 @@ describe('User Avatar Image Component', () => {
...PROVIDED_PROPS,
imgSrc: null,
},
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
});
});
it('should have default avatar image', () => {
- const avatar = wrapper.findComponent(GlAvatar);
-
- expect(avatar.props('src')).toBe(`${defaultAvatarUrl}?width=${PROVIDED_PROPS.size}`);
+ expect(findAvatar().props('src')).toBe(`${defaultAvatarUrl}?width=${PROVIDED_PROPS.size}`);
});
});
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 75d2a936b34..6ad2ef226c2 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
@@ -15,47 +15,37 @@ const PROVIDED_PROPS = {
describe('User Avatar Image Component', () => {
let wrapper;
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when `glAvatarForAllUserAvatars` feature flag enabled', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
+ const createWrapper = (props = {}, { glAvatarForAllUserAvatars } = {}) => {
+ wrapper = shallowMount(UserAvatarImage, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ ...props,
+ },
+ provide: {
+ glFeatures: {
+ glAvatarForAllUserAvatars,
},
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
- });
+ },
});
+ };
- it('should render `UserAvatarImageNew` component', () => {
- expect(wrapper.findComponent(UserAvatarImageNew).exists()).toBe(true);
- expect(wrapper.findComponent(UserAvatarImageOld).exists()).toBe(false);
- });
+ afterEach(() => {
+ wrapper.destroy();
});
- describe('when `glAvatarForAllUserAvatars` feature flag disabled', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarImage, {
- propsData: {
- ...PROVIDED_PROPS,
- },
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: false,
- },
- },
+ 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);
});
- });
-
- it('should render `UserAvatarImageOld` component', () => {
- expect(wrapper.findComponent(UserAvatarImageNew).exists()).toBe(false);
- expect(wrapper.findComponent(UserAvatarImageOld).exists()).toBe(true);
- });
- });
+ },
+ );
});
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
index 5ba80b31b99..f485a14cfea 100644
--- 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
@@ -54,6 +54,7 @@ describe('User Avatar Link Component', () => {
size: defaultProps.imgSize,
tooltipPlacement: defaultProps.tooltipPlacement,
tooltipText: '',
+ enforceGlAvatar: false,
});
});
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
index 2d513c46e77..cf7a1025dba 100644
--- 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
@@ -54,6 +54,7 @@ describe('User Avatar Link Component', () => {
size: defaultProps.imgSize,
tooltipPlacement: defaultProps.tooltipPlacement,
tooltipText: '',
+ enforceGlAvatar: false,
});
});
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 b36b83d1fea..fd3f59008ec 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
@@ -15,47 +15,37 @@ const PROVIDED_PROPS = {
describe('User Avatar Link Component', () => {
let wrapper;
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when `glAvatarForAllUserAvatars` feature flag enabled', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarLink, {
- propsData: {
- ...PROVIDED_PROPS,
+ const createWrapper = (props = {}, { glAvatarForAllUserAvatars } = {}) => {
+ wrapper = shallowMount(UserAvatarLink, {
+ propsData: {
+ ...PROVIDED_PROPS,
+ ...props,
+ },
+ provide: {
+ glFeatures: {
+ glAvatarForAllUserAvatars,
},
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: true,
- },
- },
- });
+ },
});
+ };
- it('should render `UserAvatarLinkNew` component', () => {
- expect(wrapper.findComponent(UserAvatarLinkNew).exists()).toBe(true);
- expect(wrapper.findComponent(UserAvatarLinkOld).exists()).toBe(false);
- });
+ afterEach(() => {
+ wrapper.destroy();
});
- describe('when `glAvatarForAllUserAvatars` feature flag disabled', () => {
- beforeEach(() => {
- wrapper = shallowMount(UserAvatarLink, {
- propsData: {
- ...PROVIDED_PROPS,
- },
- provide: {
- glFeatures: {
- glAvatarForAllUserAvatars: false,
- },
- },
+ 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 `UserAvatarLinkOld` component', () => {
- expect(wrapper.findComponent(UserAvatarLinkNew).exists()).toBe(false);
- expect(wrapper.findComponent(UserAvatarLinkOld).exists()).toBe(true);
- });
- });
+ },
+ );
});
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 20ff0848cff..b9accbf0373 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
@@ -38,7 +38,7 @@ describe('UserAvatarList', () => {
};
const clickButton = () => {
- const button = wrapper.find(GlButton);
+ const button = wrapper.findComponent(GlButton);
button.vm.$emit('click');
};
@@ -79,7 +79,7 @@ describe('UserAvatarList', () => {
const items = createList(20);
factory({ propsData: { items } });
- const links = wrapper.findAll(UserAvatarLink);
+ const links = wrapper.findAllComponents(UserAvatarLink);
const linkProps = links.wrappers.map((x) => x.props());
expect(linkProps).toEqual(
@@ -105,7 +105,7 @@ describe('UserAvatarList', () => {
it('renders all avatars if length is <= breakpoint', () => {
factory();
- const links = wrapper.findAll(UserAvatarLink);
+ const links = wrapper.findAllComponents(UserAvatarLink);
expect(links.length).toEqual(props.items.length);
});
@@ -113,7 +113,7 @@ describe('UserAvatarList', () => {
it('does not show button', () => {
factory();
- expect(wrapper.find(GlButton).exists()).toBe(false);
+ expect(wrapper.findComponent(GlButton).exists()).toBe(false);
});
});
@@ -126,7 +126,7 @@ describe('UserAvatarList', () => {
it('renders avatars up to breakpoint', () => {
factory();
- const links = wrapper.findAll(UserAvatarLink);
+ const links = wrapper.findAllComponents(UserAvatarLink);
expect(links.length).toEqual(TEST_BREAKPOINT);
});
@@ -138,7 +138,7 @@ describe('UserAvatarList', () => {
});
it('renders all avatars', () => {
- const links = wrapper.findAll(UserAvatarLink);
+ const links = wrapper.findAllComponents(UserAvatarLink);
expect(links.length).toEqual(props.items.length);
});
@@ -147,7 +147,7 @@ describe('UserAvatarList', () => {
clickButton();
await nextTick();
- const links = wrapper.findAll(UserAvatarLink);
+ const links = wrapper.findAllComponents(UserAvatarLink);
expect(links.length).toEqual(TEST_BREAKPOINT);
});
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 9550368eefc..b7ce3e47cef 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
@@ -6,6 +6,7 @@ import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { followUser, unfollowUser } from '~/api/user_api';
+import { mockTracking } from 'helpers/tracking_helper';
jest.mock('~/flash');
jest.mock('~/api/user_api', () => ({
@@ -51,6 +52,18 @@ describe('User Popover Component', () => {
const findUserLocalTime = () => wrapper.findByTestId('user-popover-local-time');
const findToggleFollowButton = () => wrapper.findByTestId('toggle-follow-button');
+ const itTracksToggleFollowButtonClick = (expectedLabel) => {
+ it('tracks click', async () => {
+ const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+
+ await findToggleFollowButton().trigger('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: expectedLabel,
+ });
+ });
+ };
+
const createWrapper = (props = {}) => {
wrapper = mountExtended(UserPopover, {
propsData: {
@@ -75,7 +88,7 @@ describe('User Popover Component', () => {
},
});
- expect(wrapper.find(GlSkeletonLoader).exists()).toBe(true);
+ expect(wrapper.findComponent(GlSkeletonLoader).exists()).toBe(true);
});
});
@@ -89,7 +102,7 @@ describe('User Popover Component', () => {
it('shows icon for location', () => {
createWrapper();
- const iconEl = wrapper.find(GlIcon);
+ const iconEl = wrapper.findComponent(GlIcon);
expect(iconEl.props('name')).toEqual('location');
});
@@ -102,8 +115,8 @@ describe('User Popover Component', () => {
});
describe('job data', () => {
- const findWorkInformation = () => wrapper.find({ ref: 'workInformation' });
- const findBio = () => wrapper.find({ ref: 'bio' });
+ const findWorkInformation = () => wrapper.findComponent({ ref: 'workInformation' });
+ const findBio = () => wrapper.findComponent({ ref: 'bio' });
const bio = 'My super interesting bio';
it('should show only bio if work information is not available', () => {
@@ -159,7 +172,7 @@ describe('User Popover Component', () => {
createWrapper({ user });
expect(
- wrapper.findAll(GlIcon).filter((icon) => icon.props('name') === 'profile').length,
+ wrapper.findAllComponents(GlIcon).filter((icon) => icon.props('name') === 'profile').length,
).toEqual(1);
});
@@ -172,7 +185,7 @@ describe('User Popover Component', () => {
createWrapper({ user });
expect(
- wrapper.findAll(GlIcon).filter((icon) => icon.props('name') === 'work').length,
+ wrapper.findAllComponents(GlIcon).filter((icon) => icon.props('name') === 'work').length,
).toEqual(1);
});
});
@@ -338,9 +351,11 @@ describe('User Popover Component', () => {
await axios.waitForAll();
expect(wrapper.emitted().follow.length).toBe(1);
- expect(wrapper.emitted().unfollow).toBeFalsy();
+ expect(wrapper.emitted().unfollow).toBeUndefined();
});
+ itTracksToggleFollowButtonClick('follow_from_user_popover');
+
describe('when an error occurs', () => {
beforeEach(() => {
followUser.mockRejectedValue({});
@@ -361,8 +376,8 @@ describe('User Popover Component', () => {
it('emits no events', async () => {
await axios.waitForAll();
- expect(wrapper.emitted().follow).toBe(undefined);
- expect(wrapper.emitted().unfollow).toBe(undefined);
+ expect(wrapper.emitted().follow).toBeUndefined();
+ expect(wrapper.emitted().unfollow).toBeUndefined();
});
});
});
@@ -388,6 +403,8 @@ describe('User Popover Component', () => {
expect(wrapper.emitted().unfollow.length).toBe(1);
});
+ itTracksToggleFollowButtonClick('unfollow_from_user_popover');
+
describe('when an error occurs', () => {
beforeEach(async () => {
unfollowUser.mockRejectedValue({});
@@ -406,8 +423,8 @@ describe('User Popover Component', () => {
});
it('emits no events', () => {
- expect(wrapper.emitted().follow).toBe(undefined);
- expect(wrapper.emitted().unfollow).toBe(undefined);
+ expect(wrapper.emitted().follow).toBeUndefined();
+ expect(wrapper.emitted().unfollow).toBeUndefined();
});
});
});
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index ec9128d5e38..4188adc72a1 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -9,6 +9,7 @@ import searchUsersQuery from '~/graphql_shared/queries/users_search.query.graphq
import searchUsersQueryOnMR from '~/graphql_shared/queries/users_search_with_mr_permissions.graphql';
import { IssuableType } from '~/issues/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import SidebarParticipant from '~/sidebar/components/assignees/sidebar_participant.vue';
import getIssueParticipantsQuery from '~/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql';
import UserSelect from '~/vue_shared/components/user_select/user_select.vue';
import {
@@ -16,6 +17,8 @@ import {
searchResponseOnMR,
projectMembersResponse,
participantsQueryResponse,
+ mockUser1,
+ mockUser2,
} from 'jest/sidebar/mock_data';
const assignee = {
@@ -45,9 +48,14 @@ describe('User select dropdown', () => {
const findSearchField = () => wrapper.findComponent(GlSearchBoxByType);
const findParticipantsLoading = () => wrapper.find('[data-testid="loading-participants"]');
const findSelectedParticipants = () => wrapper.findAll('[data-testid="selected-participant"]');
+ const findSelectedParticipantByIndex = (index) =>
+ findSelectedParticipants().at(index).findComponent(SidebarParticipant);
const findUnselectedParticipants = () =>
wrapper.findAll('[data-testid="unselected-participant"]');
+ const findUnselectedParticipantByIndex = (index) =>
+ findUnselectedParticipants().at(index).findComponent(SidebarParticipant);
const findCurrentUser = () => wrapper.findAll('[data-testid="current-user"]');
+ const findIssuableAuthor = () => wrapper.findAll('[data-testid="issuable-author"]');
const findUnassignLink = () => wrapper.find('[data-testid="unassign"]');
const findEmptySearchResults = () => wrapper.find('[data-testid="empty-results"]');
@@ -136,6 +144,93 @@ describe('User select dropdown', () => {
expect(findCurrentUser().exists()).toBe(true);
});
+ it('does not render current user if user is not logged in', async () => {
+ createComponent({
+ props: {
+ currentUser: {},
+ },
+ });
+ await waitForPromises();
+
+ expect(findCurrentUser().exists()).toBe(false);
+ });
+
+ it('does not render issuable author if author is not passed as a prop', async () => {
+ createComponent();
+ await waitForPromises();
+
+ expect(findIssuableAuthor().exists()).toBe(false);
+ });
+
+ describe('when issuable author is passed as a prop', () => {
+ it('moves issuable author on top of assigned list, if author is assigned', async () => {
+ createComponent({
+ props: {
+ value: [assignee, mockUser2],
+ issuableAuthor: mockUser2,
+ },
+ });
+ await waitForPromises();
+
+ expect(findSelectedParticipantByIndex(0).props('user')).toEqual(mockUser2);
+ });
+
+ it('moves issuable author on top of assigned list after current user, if author and current user are assigned', async () => {
+ const currentUser = mockUser1;
+ const issuableAuthor = mockUser2;
+
+ createComponent({
+ props: {
+ value: [assignee, issuableAuthor, currentUser],
+ issuableAuthor,
+ currentUser,
+ },
+ });
+ await waitForPromises();
+
+ expect(findSelectedParticipantByIndex(0).props('user')).toEqual(currentUser);
+ expect(findSelectedParticipantByIndex(1).props('user')).toEqual(issuableAuthor);
+ });
+
+ it('moves issuable author on top of unassigned list, if author is unassigned project member', async () => {
+ createComponent({
+ props: {
+ issuableAuthor: mockUser2,
+ },
+ });
+ await waitForPromises();
+
+ expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(mockUser2);
+ });
+
+ it('moves issuable author on top of unassigned list after current user, if author and current user are unassigned project members', async () => {
+ const currentUser = mockUser2;
+ const issuableAuthor = mockUser1;
+
+ createComponent({
+ props: {
+ issuableAuthor,
+ currentUser,
+ },
+ });
+ await waitForPromises();
+
+ expect(findUnselectedParticipantByIndex(0).props('user')).toEqual(currentUser);
+ expect(findUnselectedParticipantByIndex(1).props('user')).toMatchObject(issuableAuthor);
+ });
+
+ it('displays author in a designated position if author is not assigned and not a project member', async () => {
+ createComponent({
+ props: {
+ issuableAuthor: assignee,
+ },
+ });
+ await waitForPromises();
+
+ expect(findIssuableAuthor().exists()).toBe(true);
+ });
+ });
+
it('displays correct amount of selected users', async () => {
createComponent({
props: {
diff --git a/spec/frontend/vue_shared/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js
index 040461f6be4..a0b868d1d52 100644
--- a/spec/frontend/vue_shared/components/web_ide_link_spec.js
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -3,7 +3,7 @@ import { nextTick } from 'vue';
import ActionsButton from '~/vue_shared/components/actions_button.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
-import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+import WebIdeLink, { i18n } from '~/vue_shared/components/web_ide_link.vue';
import ConfirmForkModal from '~/vue_shared/components/confirm_fork_modal.vue';
import { stubComponent } from 'helpers/stub_component';
@@ -37,8 +37,8 @@ const ACTION_EDIT_CONFIRM_FORK = {
const ACTION_WEB_IDE = {
href: TEST_WEB_IDE_URL,
key: 'webide',
- secondaryText: 'Quickly and easily edit multiple files in your project.',
- tooltip: '',
+ secondaryText: i18n.webIdeText,
+ tooltip: i18n.webIdeTooltip,
text: 'Web IDE',
attrs: {
'data-qa-selector': 'web_ide_button',
@@ -108,8 +108,8 @@ describe('Web IDE link component', () => {
wrapper.destroy();
});
- const findActionsButton = () => wrapper.find(ActionsButton);
- const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
+ const findActionsButton = () => wrapper.findComponent(ActionsButton);
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
const findModal = () => wrapper.findComponent(GlModal);
const findForkConfirmModal = () => wrapper.findComponent(ConfirmForkModal);
diff --git a/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js b/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js
index 81362edaf37..7b0f0f7e344 100644
--- a/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js
@@ -51,11 +51,11 @@ describe('IssuableCreateRoot', () => {
});
it('renders issuable-form component', () => {
- expect(wrapper.find(IssuableForm).exists()).toBe(true);
+ expect(wrapper.findComponent(IssuableForm).exists()).toBe(true);
});
it('renders contents for slot "actions" within issuable-form component', () => {
- const buttonEl = wrapper.find(IssuableForm).find('button.js-issuable-save');
+ const buttonEl = wrapper.findComponent(IssuableForm).find('button.js-issuable-save');
expect(buttonEl.exists()).toBe(true);
expect(buttonEl.text()).toBe('Submit issuable');
diff --git a/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js b/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js
index cbfd05e7903..f98e7a678f4 100644
--- a/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js
+++ b/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js
@@ -65,9 +65,9 @@ describe('IssuableForm', () => {
expect(titleFieldEl.exists()).toBe(true);
expect(titleFieldEl.find('label').text()).toBe('Title');
- expect(titleFieldEl.find(GlFormInput).exists()).toBe(true);
- expect(titleFieldEl.find(GlFormInput).attributes('placeholder')).toBe('Title');
- expect(titleFieldEl.find(GlFormInput).attributes('autofocus')).toBe('true');
+ expect(titleFieldEl.findComponent(GlFormInput).exists()).toBe(true);
+ expect(titleFieldEl.findComponent(GlFormInput).attributes('placeholder')).toBe('Title');
+ expect(titleFieldEl.findComponent(GlFormInput).attributes('autofocus')).toBe('true');
});
it('renders issuable description input field', () => {
@@ -75,8 +75,8 @@ describe('IssuableForm', () => {
expect(descriptionFieldEl.exists()).toBe(true);
expect(descriptionFieldEl.find('label').text()).toBe('Description');
- expect(descriptionFieldEl.find(MarkdownField).exists()).toBe(true);
- expect(descriptionFieldEl.find(MarkdownField).props()).toMatchObject({
+ expect(descriptionFieldEl.findComponent(MarkdownField).exists()).toBe(true);
+ expect(descriptionFieldEl.findComponent(MarkdownField).props()).toMatchObject({
markdownPreviewPath: wrapper.vm.descriptionPreviewPath,
markdownDocsPath: wrapper.vm.descriptionHelpPath,
addSpacingClasses: false,
@@ -94,8 +94,8 @@ describe('IssuableForm', () => {
expect(labelsSelectEl.exists()).toBe(true);
expect(labelsSelectEl.find('label').text()).toBe('Labels');
- expect(labelsSelectEl.find(LabelsSelect).exists()).toBe(true);
- expect(labelsSelectEl.find(LabelsSelect).props()).toMatchObject({
+ expect(labelsSelectEl.findComponent(LabelsSelect).exists()).toBe(true);
+ expect(labelsSelectEl.findComponent(LabelsSelect).props()).toMatchObject({
allowLabelEdit: true,
allowLabelCreate: true,
allowMultiselect: true,
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
index 80f14dffd08..f55d3156581 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
@@ -3,6 +3,7 @@ import { nextTick } from 'vue';
import { useFakeDate } from 'helpers/fake_date';
import { shallowMountExtended as shallowMount } from 'helpers/vue_test_utils_helper';
import IssuableItem from '~/vue_shared/issuable/list/components/issuable_item.vue';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import IssuableAssignees from '~/issuable/components/issue_assignees.vue';
import { mockIssuable, mockRegularLabel } from '../mock_data';
@@ -13,6 +14,7 @@ const createComponent = ({
issuable = mockIssuable,
showCheckbox = true,
slots = {},
+ showWorkItemTypeIcon = false,
} = {}) =>
shallowMount(IssuableItem, {
propsData: {
@@ -21,6 +23,7 @@ const createComponent = ({
issuable,
showDiscussions: true,
showCheckbox,
+ showWorkItemTypeIcon,
},
slots,
stubs: {
@@ -40,6 +43,7 @@ describe('IssuableItem', () => {
let wrapper;
const findTimestampWrapper = () => wrapper.find('[data-testid="issuable-timestamp"]');
+ const findWorkItemTypeIcon = () => wrapper.findComponent(WorkItemTypeIcon);
beforeEach(() => {
gon.gitlab_url = MOCK_GITLAB_URL;
@@ -273,9 +277,9 @@ describe('IssuableItem', () => {
const titleEl = wrapper.find('[data-testid="issuable-title"]');
expect(titleEl.exists()).toBe(true);
- expect(titleEl.find(GlLink).attributes('href')).toBe(expectedHref);
- expect(titleEl.find(GlLink).attributes('target')).toBe(expectedTarget);
- expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
+ expect(titleEl.findComponent(GlLink).attributes('href')).toBe(expectedHref);
+ expect(titleEl.findComponent(GlLink).attributes('target')).toBe(expectedTarget);
+ expect(titleEl.findComponent(GlLink).text()).toBe(mockIssuable.title);
},
);
@@ -286,8 +290,8 @@ describe('IssuableItem', () => {
await nextTick();
- expect(wrapper.find(GlFormCheckbox).exists()).toBe(true);
- expect(wrapper.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
+ expect(wrapper.findComponent(GlFormCheckbox).exists()).toBe(true);
+ expect(wrapper.findComponent(GlFormCheckbox).attributes('checked')).not.toBeDefined();
wrapper.setProps({
checked: true,
@@ -295,7 +299,7 @@ describe('IssuableItem', () => {
await nextTick();
- expect(wrapper.find(GlFormCheckbox).attributes('checked')).toBe('true');
+ expect(wrapper.findComponent(GlFormCheckbox).attributes('checked')).toBe('true');
});
it('renders issuable title with `target` set as "_blank" when issuable.webUrl is external', async () => {
@@ -308,9 +312,9 @@ describe('IssuableItem', () => {
await nextTick();
- expect(wrapper.find('[data-testid="issuable-title"]').find(GlLink).attributes('target')).toBe(
- '_blank',
- );
+ expect(
+ wrapper.find('[data-testid="issuable-title"]').findComponent(GlLink).attributes('target'),
+ ).toBe('_blank');
});
it('renders issuable confidential icon when issuable is confidential', async () => {
@@ -323,7 +327,7 @@ describe('IssuableItem', () => {
await nextTick();
- const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
+ const confidentialEl = wrapper.find('[data-testid="issuable-title"]').findComponent(GlIcon);
expect(confidentialEl.exists()).toBe(true);
expect(confidentialEl.props('name')).toBe('eye-slash');
@@ -349,11 +353,23 @@ describe('IssuableItem', () => {
wrapper = createComponent();
const taskStatus = wrapper.find('[data-testid="task-status"]');
- const expected = `${mockIssuable.taskCompletionStatus.completedCount} of ${mockIssuable.taskCompletionStatus.count} tasks completed`;
+ const expected = `${mockIssuable.taskCompletionStatus.completedCount} of ${mockIssuable.taskCompletionStatus.count} checklist items completed`;
expect(taskStatus.text()).toBe(expected);
});
+ it('does not renders work item type icon by default', () => {
+ wrapper = createComponent();
+
+ expect(findWorkItemTypeIcon().exists()).toBe(false);
+ });
+
+ it('renders work item type icon when props passed', () => {
+ wrapper = createComponent({ showWorkItemTypeIcon: true });
+
+ expect(findWorkItemTypeIcon().props('workItemType')).toBe(mockIssuable.type);
+ });
+
it('renders issuable reference', () => {
wrapper = createComponent();
@@ -440,7 +456,7 @@ describe('IssuableItem', () => {
it('renders gl-label component for each label present within `issuable` prop', () => {
wrapper = createComponent();
- const labelsEl = wrapper.findAll(GlLabel);
+ const labelsEl = wrapper.findAllComponents(GlLabel);
expect(labelsEl.exists()).toBe(true);
expect(labelsEl).toHaveLength(mockLabels.length);
@@ -476,18 +492,18 @@ describe('IssuableItem', () => {
const discussionsEl = wrapper.find('[data-testid="issuable-discussions"]');
expect(discussionsEl.exists()).toBe(true);
- expect(discussionsEl.find(GlLink).attributes()).toMatchObject({
+ expect(discussionsEl.findComponent(GlLink).attributes()).toMatchObject({
title: 'Comments',
href: `${mockIssuable.webUrl}#notes`,
});
- expect(discussionsEl.find(GlIcon).props('name')).toBe('comments');
- expect(discussionsEl.find(GlLink).text()).toContain('2');
+ expect(discussionsEl.findComponent(GlIcon).props('name')).toBe('comments');
+ expect(discussionsEl.findComponent(GlLink).text()).toContain('2');
});
it('renders issuable-assignees component', () => {
wrapper = createComponent();
- const assigneesEl = wrapper.find(IssuableAssignees);
+ const assigneesEl = wrapper.findComponent(IssuableAssignees);
expect(assigneesEl.exists()).toBe(true);
expect(assigneesEl.props()).toMatchObject({
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
index 50e79dbe589..0c53f599d55 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
@@ -359,7 +359,7 @@ describe('IssuableListRoot', () => {
findIssuableTabs().vm.$emit('click');
- expect(wrapper.emitted('click-tab')).toBeTruthy();
+ expect(wrapper.emitted('click-tab')).toHaveLength(1);
});
it('sets all issuables as checked when filtered-search-bar component emits `checked-input` event', () => {
@@ -369,7 +369,7 @@ describe('IssuableListRoot', () => {
searchEl.vm.$emit('checked-input', true);
- expect(searchEl.emitted('checked-input')).toBeTruthy();
+ expect(searchEl.emitted('checked-input')).toHaveLength(1);
expect(searchEl.emitted('checked-input').length).toBe(1);
expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
@@ -384,9 +384,9 @@ describe('IssuableListRoot', () => {
const searchEl = findFilteredSearchBar();
searchEl.vm.$emit('onFilter');
- expect(wrapper.emitted('filter')).toBeTruthy();
+ expect(wrapper.emitted('filter')).toHaveLength(1);
searchEl.vm.$emit('onSort');
- expect(wrapper.emitted('sort')).toBeTruthy();
+ expect(wrapper.emitted('sort')).toHaveLength(1);
});
it('sets an issuable as checked when issuable-item component emits `checked-input` event', () => {
@@ -396,7 +396,7 @@ describe('IssuableListRoot', () => {
issuableItem.vm.$emit('checked-input', true);
- expect(issuableItem.emitted('checked-input')).toBeTruthy();
+ expect(issuableItem.emitted('checked-input')).toHaveLength(1);
expect(issuableItem.emitted('checked-input').length).toBe(1);
expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
@@ -425,7 +425,7 @@ describe('IssuableListRoot', () => {
wrapper = createComponent({ data, props: { showPaginationControls: true } });
findGlPagination().vm.$emit('input');
- expect(wrapper.emitted('page-change')).toBeTruthy();
+ expect(wrapper.emitted('page-change')).toHaveLength(1);
});
it.each`
diff --git a/spec/frontend/vue_shared/issuable/list/mock_data.js b/spec/frontend/vue_shared/issuable/list/mock_data.js
index 8640f4a2cd5..b67bd0f42fe 100644
--- a/spec/frontend/vue_shared/issuable/list/mock_data.js
+++ b/spec/frontend/vue_shared/issuable/list/mock_data.js
@@ -57,6 +57,7 @@ export const mockIssuable = {
count: 2,
completedCount: 1,
},
+ type: 'issue',
};
export const mockIssuables = [
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 7c582360637..39a76a51191 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
@@ -154,7 +154,7 @@ describe('IssuableBody', () => {
describe('template', () => {
it('renders issuable-title component', () => {
- const titleEl = wrapper.find(IssuableTitle);
+ const titleEl = wrapper.findComponent(IssuableTitle);
expect(titleEl.exists()).toBe(true);
expect(titleEl.props()).toMatchObject({
@@ -165,7 +165,7 @@ describe('IssuableBody', () => {
});
it('renders issuable-description component', () => {
- const descriptionEl = wrapper.find(IssuableDescription);
+ const descriptionEl = wrapper.findComponent(IssuableDescription);
expect(descriptionEl.exists()).toBe(true);
expect(descriptionEl.props('issuable')).toEqual(issuableBodyProps.issuable);
@@ -184,7 +184,7 @@ describe('IssuableBody', () => {
await nextTick();
- const editFormEl = wrapper.find(IssuableEditForm);
+ const editFormEl = wrapper.findComponent(IssuableEditForm);
expect(editFormEl.exists()).toBe(true);
expect(editFormEl.props()).toMatchObject({
issuable: issuableBodyProps.issuable,
@@ -198,7 +198,7 @@ describe('IssuableBody', () => {
describe('events', () => {
it('component emits `edit-issuable` event bubbled via issuable-title', () => {
- const issuableTitle = wrapper.find(IssuableTitle);
+ const issuableTitle = wrapper.findComponent(IssuableTitle);
issuableTitle.vm.$emit('edit-issuable');
@@ -223,7 +223,7 @@ describe('IssuableBody', () => {
await nextTick();
- const issuableEditForm = wrapper.find(IssuableEditForm);
+ const issuableEditForm = wrapper.findComponent(IssuableEditForm);
issuableEditForm.vm.$emit(eventName, eventObj, issuableMeta);
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
index d3e484cf913..d843da4da5b 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
@@ -124,7 +124,7 @@ describe('IssuableEditForm', () => {
const titleInputEl = wrapper.find('[data-testid="title"]');
expect(titleInputEl.exists()).toBe(true);
- expect(titleInputEl.find(GlFormInput).attributes()).toMatchObject({
+ expect(titleInputEl.findComponent(GlFormInput).attributes()).toMatchObject({
'aria-label': 'Title',
placeholder: 'Title',
});
@@ -134,7 +134,7 @@ describe('IssuableEditForm', () => {
const descriptionEl = wrapper.find('[data-testid="description"]');
expect(descriptionEl.exists()).toBe(true);
- expect(descriptionEl.find(MarkdownField).props()).toMatchObject({
+ expect(descriptionEl.findComponent(MarkdownField).props()).toMatchObject({
markdownPreviewPath: issuableEditFormProps.descriptionPreviewPath,
markdownDocsPath: issuableEditFormProps.descriptionHelpPath,
enableAutocomplete: issuableEditFormProps.enableAutocomplete,
@@ -161,7 +161,7 @@ describe('IssuableEditForm', () => {
};
it('component emits `keydown-title` event with event object and issuableMeta params via gl-form-input', async () => {
- const titleInputEl = wrapper.find(GlFormInput);
+ const titleInputEl = wrapper.findComponent(GlFormInput);
titleInputEl.vm.$emit('keydown', eventObj, 'title');
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
index e00bb184535..6a8b9ef77a9 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
@@ -86,7 +86,7 @@ describe('IssuableHeader', () => {
const blockedEl = wrapper.findByTestId('blocked');
expect(blockedEl.exists()).toBe(true);
- expect(blockedEl.find(GlIcon).props('name')).toBe('lock');
+ expect(blockedEl.findComponent(GlIcon).props('name')).toBe('lock');
});
it('renders confidential icon when issuable is confidential', async () => {
@@ -97,7 +97,7 @@ describe('IssuableHeader', () => {
const confidentialEl = wrapper.findByTestId('confidential');
expect(confidentialEl.exists()).toBe(true);
- expect(confidentialEl.find(GlIcon).props('name')).toBe('eye-slash');
+ expect(confidentialEl.findComponent(GlIcon).props('name')).toBe('eye-slash');
});
it('renders issuable author avatar', () => {
@@ -113,19 +113,19 @@ describe('IssuableHeader', () => {
const avatarEl = wrapper.findByTestId('avatar');
expect(avatarEl.exists()).toBe(true);
expect(avatarEl.attributes()).toMatchObject(avatarElAttrs);
- expect(avatarEl.find(GlAvatarLabeled).attributes()).toMatchObject({
+ expect(avatarEl.findComponent(GlAvatarLabeled).attributes()).toMatchObject({
size: '24',
src: avatarUrl,
label: name,
});
- expect(avatarEl.find(GlAvatarLabeled).find(GlIcon).exists()).toBe(false);
+ expect(avatarEl.findComponent(GlAvatarLabeled).findComponent(GlIcon).exists()).toBe(false);
});
it('renders task status text when `taskCompletionStatus` prop is defined', () => {
createComponent();
expect(findTaskStatusEl().exists()).toBe(true);
- expect(findTaskStatusEl().text()).toContain('0 of 5 tasks completed');
+ expect(findTaskStatusEl().text()).toContain('0 of 5 checklist items completed');
});
it('does not render task status text when tasks count is 0', () => {
@@ -172,7 +172,7 @@ describe('IssuableHeader', () => {
);
const avatarEl = wrapper.findComponent(GlAvatarLabeled);
- const icon = avatarEl.find(GlIcon);
+ const icon = avatarEl.findComponent(GlIcon);
expect(icon.exists()).toBe(true);
expect(icon.props('name')).toBe('external-link');
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js
index f56064ed8e1..edfd55c8bb4 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js
@@ -63,7 +63,7 @@ describe('IssuableShowRoot', () => {
});
it('renders issuable-header component', () => {
- const issuableHeader = wrapper.find(IssuableHeader);
+ const issuableHeader = wrapper.findComponent(IssuableHeader);
expect(issuableHeader.exists()).toBe(true);
expect(issuableHeader.props()).toMatchObject({
@@ -84,7 +84,7 @@ describe('IssuableShowRoot', () => {
});
it('renders issuable-body component', () => {
- const issuableBody = wrapper.find(IssuableBody);
+ const issuableBody = wrapper.findComponent(IssuableBody);
expect(issuableBody.exists()).toBe(true);
expect(issuableBody.props()).toMatchObject({
@@ -99,38 +99,38 @@ describe('IssuableShowRoot', () => {
});
it('renders issuable-sidebar component', () => {
- const issuableSidebar = wrapper.find(IssuableSidebar);
+ const issuableSidebar = wrapper.findComponent(IssuableSidebar);
expect(issuableSidebar.exists()).toBe(true);
});
describe('events', () => {
it('component emits `edit-issuable` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
+ const issuableBody = wrapper.findComponent(IssuableBody);
issuableBody.vm.$emit('edit-issuable');
- expect(wrapper.emitted('edit-issuable')).toBeTruthy();
+ expect(wrapper.emitted('edit-issuable')).toHaveLength(1);
});
it('component emits `task-list-update-success` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
+ const issuableBody = wrapper.findComponent(IssuableBody);
const eventParam = {
foo: 'bar',
};
issuableBody.vm.$emit('task-list-update-success', eventParam);
- expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-success')).toHaveLength(1);
expect(wrapper.emitted('task-list-update-success')[0]).toEqual([eventParam]);
});
it('component emits `task-list-update-failure` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
+ const issuableBody = wrapper.findComponent(IssuableBody);
issuableBody.vm.$emit('task-list-update-failure');
- expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-failure')).toHaveLength(1);
});
it.each(['keydown-title', 'keydown-description'])(
@@ -145,11 +145,11 @@ describe('IssuableShowRoot', () => {
issuableDescription: 'foobar',
};
- const issuableBody = wrapper.find(IssuableBody);
+ const issuableBody = wrapper.findComponent(IssuableBody);
issuableBody.vm.$emit(eventName, eventObj, issuableMeta);
- expect(wrapper.emitted(eventName)).toBeTruthy();
+ expect(wrapper.emitted()).toHaveProperty(eventName);
expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
},
);
diff --git a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
index 4b75da0b126..5f2b13a79c9 100644
--- a/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
+++ b/spec/frontend/vue_shared/security_reports/components/security_report_download_dropdown_spec.js
@@ -12,8 +12,8 @@ describe('SecurityReportDownloadDropdown component', () => {
});
};
- const findDropdown = () => wrapper.find(GlDropdown);
- const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
afterEach(() => {
wrapper.destroy();
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 68a97103d3a..a9651cf8bac 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
@@ -70,8 +70,8 @@ describe('Security reports app', () => {
return createMockApollo(requestHandlers);
};
- const findDownloadDropdown = () => wrapper.find(SecurityReportDownloadDropdown);
- const findHelpIconComponent = () => wrapper.find(HelpIcon);
+ const findDownloadDropdown = () => wrapper.findComponent(SecurityReportDownloadDropdown);
+ const findHelpIconComponent = () => wrapper.findComponent(HelpIcon);
afterEach(() => {
wrapper.destroy();
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index 945727cd664..de5a814d3e7 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -64,7 +64,7 @@ describe('App', () => {
buildWrapper();
wrapper.vm.$store.state.features = [
- { title: 'Whats New Drawer', url: 'www.url.com', release: 3.11 },
+ { name: 'Whats New Drawer', documentation_link: 'www.url.com', release: 3.11 },
];
wrapper.vm.$store.state.drawerBodyHeight = MOCK_DRAWER_BODY_HEIGHT;
await nextTick();
@@ -115,7 +115,7 @@ describe('App', () => {
it('renders features when provided via ajax', () => {
expect(actions.fetchItems).toHaveBeenCalled();
- expect(wrapper.find('[data-test-id="feature-title"]').text()).toBe('Whats New Drawer');
+ expect(wrapper.find('[data-test-id="feature-name"]').text()).toBe('Whats New Drawer');
});
it('send an event when feature item is clicked', () => {
diff --git a/spec/frontend/whats_new/components/feature_spec.js b/spec/frontend/whats_new/components/feature_spec.js
index b6627c257ff..099054bf8ca 100644
--- a/spec/frontend/whats_new/components/feature_spec.js
+++ b/spec/frontend/whats_new/components/feature_spec.js
@@ -6,14 +6,15 @@ describe("What's new single feature", () => {
let wrapper;
const exampleFeature = {
- title: 'Compliance pipeline configurations',
- body:
+ name: 'Compliance pipeline configurations',
+ description:
'<p data-testid="body-content">We are thrilled to announce that it is now possible to define enforceable pipelines that will run for any project assigned a corresponding <a href="https://en.wikipedia.org/wiki/Compliance_(psychology)" target="_blank" rel="noopener noreferrer" onload="alert(xss)">compliance</a> framework.</p>',
stage: 'Manage',
'self-managed': true,
'gitlab-com': true,
- packages: ['Ultimate'],
- url: 'https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration',
+ available_in: ['Ultimate'],
+ documentation_link:
+ 'https://docs.gitlab.com/ee/user/project/settings/#compliance-pipeline-configuration',
image_url: 'https://img.youtube.com/vi/upLJ_equomw/hqdefault.jpg',
published_at: '2021-04-22T00:00:00.000Z',
release: '13.11',
diff --git a/spec/frontend/work_items/components/item_state_spec.js b/spec/frontend/work_items/components/item_state_spec.js
index 79b76f3c061..c3cc2fbc556 100644
--- a/spec/frontend/work_items/components/item_state_spec.js
+++ b/spec/frontend/work_items/components/item_state_spec.js
@@ -1,3 +1,4 @@
+import { GlFormSelect } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { STATE_OPEN, STATE_CLOSED } from '~/work_items/constants';
import ItemState from '~/work_items/components/item_state.vue';
@@ -6,6 +7,7 @@ describe('ItemState', () => {
let wrapper;
const findLabel = () => wrapper.find('label').text();
+ const findFormSelect = () => wrapper.findComponent(GlFormSelect);
const selectedValue = () => wrapper.find('option:checked').element.value;
const clickOpen = () => wrapper.findAll('option').at(0).setSelected();
@@ -51,4 +53,18 @@ describe('ItemState', () => {
expect(wrapper.emitted('changed')).toBeUndefined();
});
+
+ describe('form select disabled prop', () => {
+ describe.each`
+ description | disabled | value
+ ${'when not disabled'} | ${false} | ${undefined}
+ ${'when disabled'} | ${true} | ${'disabled'}
+ `('$description', ({ disabled, value }) => {
+ it(`renders form select component with disabled=${value}`, () => {
+ createComponent({ disabled });
+
+ expect(findFormSelect().attributes('disabled')).toBe(value);
+ });
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/item_title_spec.js b/spec/frontend/work_items/components/item_title_spec.js
index a55f448c9a2..de20369eb1b 100644
--- a/spec/frontend/work_items/components/item_title_spec.js
+++ b/spec/frontend/work_items/components/item_title_spec.js
@@ -37,7 +37,7 @@ describe('ItemTitle', () => {
disabled: true,
});
- expect(wrapper.classes()).toContain('gl-cursor-not-allowed');
+ expect(wrapper.classes()).toContain('gl-cursor-text');
expect(findInputEl().attributes('contenteditable')).toBe('false');
});
diff --git a/spec/frontend/work_items/components/work_item_actions_spec.js b/spec/frontend/work_items/components/work_item_actions_spec.js
index 137a0a7326d..a1f1d47ab90 100644
--- a/spec/frontend/work_items/components/work_item_actions_spec.js
+++ b/spec/frontend/work_items/components/work_item_actions_spec.js
@@ -1,5 +1,5 @@
-import { GlDropdownItem, GlModal } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import WorkItemActions from '~/work_items/components/work_item_actions.vue';
describe('WorkItemActions component', () => {
@@ -7,12 +7,19 @@ describe('WorkItemActions component', () => {
let glModalDirective;
const findModal = () => wrapper.findComponent(GlModal);
- const findDeleteButton = () => wrapper.findComponent(GlDropdownItem);
+ const findConfidentialityToggleButton = () =>
+ wrapper.findByTestId('confidentiality-toggle-action');
+ const findDeleteButton = () => wrapper.findByTestId('delete-action');
- const createComponent = ({ canDelete = true } = {}) => {
+ const createComponent = ({
+ canUpdate = true,
+ canDelete = true,
+ isConfidential = false,
+ isParentConfidential = false,
+ } = {}) => {
glModalDirective = jest.fn();
- wrapper = shallowMount(WorkItemActions, {
- propsData: { workItemId: '123', canDelete },
+ wrapper = shallowMountExtended(WorkItemActions, {
+ propsData: { workItemId: '123', canUpdate, canDelete, isConfidential, isParentConfidential },
directives: {
glModal: {
bind(_, { value }) {
@@ -34,27 +41,69 @@ describe('WorkItemActions component', () => {
expect(findModal().props('visible')).toBe(false);
});
- it('shows confirm modal when clicking Delete work item', () => {
+ it('renders dropdown actions', () => {
createComponent();
- findDeleteButton().vm.$emit('click');
-
- expect(glModalDirective).toHaveBeenCalled();
+ expect(findConfidentialityToggleButton().exists()).toBe(true);
+ expect(findDeleteButton().exists()).toBe(true);
});
- it('emits event when clicking OK button', () => {
- createComponent();
+ describe('toggle confidentiality action', () => {
+ it.each`
+ isConfidential | buttonText
+ ${true} | ${'Turn off confidentiality'}
+ ${false} | ${'Turn on confidentiality'}
+ `(
+ 'renders confidentiality toggle button with text "$buttonText"',
+ ({ isConfidential, buttonText }) => {
+ createComponent({ isConfidential });
+
+ expect(findConfidentialityToggleButton().text()).toBe(buttonText);
+ },
+ );
+
+ it('emits `toggleWorkItemConfidentiality` event when clicked', () => {
+ createComponent();
- findModal().vm.$emit('ok');
+ findConfidentialityToggleButton().vm.$emit('click');
- expect(wrapper.emitted('deleteWorkItem')).toEqual([[]]);
+ expect(wrapper.emitted('toggleWorkItemConfidentiality')[0]).toEqual([true]);
+ });
+
+ it.each`
+ props | propName | value
+ ${{ isParentConfidential: true }} | ${'isParentConfidential'} | ${true}
+ ${{ canUpdate: false }} | ${'canUpdate'} | ${false}
+ `('does not render when $propName is $value', ({ props }) => {
+ createComponent(props);
+
+ expect(findConfidentialityToggleButton().exists()).toBe(false);
+ });
});
- it('does not render when canDelete is false', () => {
- createComponent({
- canDelete: false,
+ describe('delete action', () => {
+ it('shows confirm modal when clicked', () => {
+ createComponent();
+
+ findDeleteButton().vm.$emit('click');
+
+ expect(glModalDirective).toHaveBeenCalled();
+ });
+
+ it('emits event when clicking OK button', () => {
+ createComponent();
+
+ findModal().vm.$emit('ok');
+
+ expect(wrapper.emitted('deleteWorkItem')).toEqual([[]]);
});
- expect(wrapper.html()).toBe('');
+ it('does not render when canDelete is false', () => {
+ createComponent({
+ canDelete: false,
+ });
+
+ expect(wrapper.findByTestId('delete-action').exists()).toBe(false);
+ });
});
});
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 299949a4baa..f0ef8aee7a9 100644
--- a/spec/frontend/work_items/components/work_item_assignees_spec.js
+++ b/spec/frontend/work_items/components/work_item_assignees_spec.js
@@ -5,14 +5,15 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { mockTracking } from 'helpers/tracking_helper';
-import { stripTypenames } from 'helpers/graphql_helpers';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
+import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import WorkItemAssignees from '~/work_items/components/work_item_assignees.vue';
import { i18n, TASK_TYPE_NAME, TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
-import { temporaryConfig, resolvers } from '~/work_items/graphql/provider';
+import { temporaryConfig } from '~/work_items/graphql/provider';
import {
projectMembersResponseWithCurrentUser,
mockAssignees,
@@ -20,6 +21,7 @@ import {
currentUserResponse,
currentUserNullResponse,
projectMembersResponseWithoutCurrentUser,
+ updateWorkItemMutationResponse,
} from '../mock_data';
Vue.use(VueApollo);
@@ -33,6 +35,7 @@ describe('WorkItemAssignees component', () => {
const findAssigneeLinks = () => wrapper.findAllComponents(GlLink);
const findTokenSelector = () => wrapper.findComponent(GlTokenSelector);
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findInviteMembersTrigger = () => wrapper.findComponent(InviteMembersTrigger);
const findEmptyState = () => wrapper.findByTestId('empty-state');
const findAssignSelfButton = () => wrapper.findByTestId('assign-self');
@@ -43,6 +46,9 @@ describe('WorkItemAssignees component', () => {
.mockResolvedValue(projectMembersResponseWithCurrentUser);
const successCurrentUserQueryHandler = jest.fn().mockResolvedValue(currentUserResponse);
const noCurrentUserQueryHandler = jest.fn().mockResolvedValue(currentUserNullResponse);
+ const successUpdateWorkItemMutationHandler = jest
+ .fn()
+ .mockResolvedValue(updateWorkItemMutationResponse);
const errorHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
@@ -50,15 +56,18 @@ describe('WorkItemAssignees component', () => {
assignees = mockAssignees,
searchQueryHandler = successSearchQueryHandler,
currentUserQueryHandler = successCurrentUserQueryHandler,
+ updateWorkItemMutationHandler = successUpdateWorkItemMutationHandler,
allowsMultipleAssignees = true,
+ canInviteMembers = false,
canUpdate = true,
} = {}) => {
const apolloProvider = createMockApollo(
[
[userSearchQuery, searchQueryHandler],
[currentUserQuery, currentUserQueryHandler],
+ [updateWorkItemMutation, updateWorkItemMutationHandler],
],
- resolvers,
+ {},
{
typePolicies: temporaryConfig.cacheConfig.typePolicies,
},
@@ -82,6 +91,7 @@ describe('WorkItemAssignees component', () => {
allowsMultipleAssignees,
workItemType: TASK_TYPE_NAME,
canUpdate,
+ canInviteMembers,
},
attachTo: document.body,
apolloProvider,
@@ -120,15 +130,6 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().element.contains(document.activeElement)).toBe(true);
});
- it('calls a mutation on clicking outside the token selector', async () => {
- createComponent();
- findTokenSelector().vm.$emit('input', [mockAssignees[0]]);
- findTokenSelector().vm.$emit('blur', new FocusEvent({ relatedTarget: null }));
- await waitForPromises();
-
- expect(findTokenSelector().props('selectedTokens')).toEqual([mockAssignees[0]]);
- });
-
it('passes `false` to `viewOnly` token selector prop if user can update assignees', () => {
createComponent();
@@ -141,6 +142,36 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().props('viewOnly')).toBe(true);
});
+ describe('when clicking outside the token selector', () => {
+ function arrange(args) {
+ createComponent(args);
+ findTokenSelector().vm.$emit('input', [mockAssignees[0]]);
+ findTokenSelector().vm.$emit('blur', new FocusEvent({ relatedTarget: null }));
+ }
+
+ it('calls a mutation with correct variables', () => {
+ arrange({ assignees: [] });
+
+ expect(successUpdateWorkItemMutationHandler).toHaveBeenCalledWith({
+ input: {
+ assigneesWidget: { assigneeIds: [mockAssignees[0].id] },
+ id: 'gid://gitlab/WorkItem/1',
+ },
+ });
+ });
+
+ it('emits an error and resets assignees if mutation was rejected', async () => {
+ arrange({ updateWorkItemMutationHandler: errorHandler, assignees: [mockAssignees[1]] });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
+ expect(findTokenSelector().props('selectedTokens')).toEqual([
+ { ...mockAssignees[1], class: expect.anything() },
+ ]);
+ });
+ });
+
describe('when searching for users', () => {
beforeEach(() => {
createComponent();
@@ -204,7 +235,7 @@ describe('WorkItemAssignees component', () => {
expect(findTokenSelector().props('dropdownItems')).toHaveLength(2);
});
- it('should search for users with correct key after text input', async () => {
+ it('searches for users with correct key after text input', async () => {
const searchKey = 'Hello';
findTokenSelector().vm.$emit('focus');
@@ -225,6 +256,18 @@ describe('WorkItemAssignees component', () => {
expect(wrapper.emitted('error')).toEqual([[i18n.fetchError]]);
});
+ it('updates localAssignees when assignees prop is updated', async () => {
+ createComponent({ assignees: [] });
+
+ expect(findTokenSelector().props('selectedTokens')).toEqual([]);
+
+ await wrapper.setProps({ assignees: [mockAssignees[0]] });
+
+ expect(findTokenSelector().props('selectedTokens')).toEqual([
+ { ...mockAssignees[0], class: expect.anything() },
+ ]);
+ });
+
describe('when assigning to current user', () => {
it('does not show `Assign myself` button if current user is loading', () => {
createComponent();
@@ -261,23 +304,21 @@ describe('WorkItemAssignees component', () => {
expect(findAssignSelfButton().exists()).toBe(true);
});
- it('calls update work item assignees mutation with current user as a variable on button click', () => {
- // TODO: replace this test as soon as we have a real mutation implemented
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementation(jest.fn());
-
+ it('calls update work item assignees mutation with current user as a variable on button click', async () => {
+ const { currentUser } = currentUserResponse.data;
findTokenSelector().trigger('mouseover');
findAssignSelfButton().vm.$emit('click', new MouseEvent('click'));
+ await nextTick();
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith(
- expect.objectContaining({
- variables: {
- input: {
- assignees: [stripTypenames(currentUserResponse.data.currentUser)],
- id: workItemId,
- },
+ expect(findTokenSelector().props('selectedTokens')).toMatchObject([currentUser]);
+ expect(successUpdateWorkItemMutationHandler).toHaveBeenCalledWith({
+ input: {
+ id: workItemId,
+ assigneesWidget: {
+ assigneeIds: [currentUser.id],
},
- }),
- );
+ },
+ });
});
});
@@ -286,9 +327,7 @@ describe('WorkItemAssignees component', () => {
await waitForPromises();
expect(findTokenSelector().props('dropdownItems')[0]).toEqual(
- expect.objectContaining({
- ...stripTypenames(currentUserResponse.data.currentUser),
- }),
+ expect.objectContaining(currentUserResponse.data.currentUser),
);
});
@@ -303,9 +342,10 @@ describe('WorkItemAssignees component', () => {
});
it('adds current user to the top of dropdown items', () => {
- expect(findTokenSelector().props('dropdownItems')[0]).toEqual(
- stripTypenames(currentUserResponse.data.currentUser),
- );
+ expect(findTokenSelector().props('dropdownItems')[0]).toEqual({
+ ...currentUserResponse.data.currentUser,
+ class: expect.anything(),
+ });
});
it('does not add current user if search is not empty', async () => {
@@ -313,7 +353,7 @@ describe('WorkItemAssignees component', () => {
await waitForPromises();
expect(findTokenSelector().props('dropdownItems')[0]).not.toEqual(
- stripTypenames(currentUserResponse.data.currentUser),
+ currentUserResponse.data.currentUser,
);
});
});
@@ -405,4 +445,18 @@ describe('WorkItemAssignees component', () => {
});
});
});
+
+ describe('invite members', () => {
+ it('does not render `Invite members` link if user has no permission to invite members', () => {
+ createComponent();
+
+ expect(findInviteMembersTrigger().exists()).toBe(false);
+ });
+
+ it('renders `Invite members` link if user has a permission to invite members', () => {
+ createComponent({ canInviteMembers: true });
+
+ expect(findInviteMembersTrigger().exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/work_item_detail_modal_spec.js b/spec/frontend/work_items/components/work_item_detail_modal_spec.js
index 70b1261bdb7..01891012f99 100644
--- a/spec/frontend/work_items/components/work_item_detail_modal_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_modal_spec.js
@@ -7,6 +7,13 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import WorkItemDetail from '~/work_items/components/work_item_detail.vue';
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
import deleteWorkItemFromTaskMutation from '~/work_items/graphql/delete_task_from_work_item.mutation.graphql';
+import deleteWorkItemMutation from '~/work_items/graphql/delete_work_item.mutation.graphql';
+import {
+ deleteWorkItemFromTaskMutationErrorResponse,
+ deleteWorkItemFromTaskMutationResponse,
+ deleteWorkItemMutationErrorResponse,
+ deleteWorkItemResponse,
+} from '../mock_data';
describe('WorkItemDetailModal component', () => {
let wrapper;
@@ -25,28 +32,38 @@ describe('WorkItemDetailModal component', () => {
},
};
+ const defaultPropsData = {
+ issueGid: 'gid://gitlab/WorkItem/1',
+ workItemId: 'gid://gitlab/WorkItem/2',
+ };
+
const findModal = () => wrapper.findComponent(GlModal);
const findAlert = () => wrapper.findComponent(GlAlert);
const findWorkItemDetail = () => wrapper.findComponent(WorkItemDetail);
- const createComponent = ({ workItemId = '1', issueGid = '2', error = false } = {}) => {
+ const createComponent = ({
+ lockVersion,
+ lineNumberStart,
+ lineNumberEnd,
+ error = false,
+ deleteWorkItemFromTaskMutationHandler = jest
+ .fn()
+ .mockResolvedValue(deleteWorkItemFromTaskMutationResponse),
+ deleteWorkItemMutationHandler = jest.fn().mockResolvedValue(deleteWorkItemResponse),
+ } = {}) => {
const apolloProvider = createMockApollo([
- [
- deleteWorkItemFromTaskMutation,
- jest.fn().mockResolvedValue({
- data: {
- workItemDeleteTask: {
- workItem: { id: 123, descriptionHtml: 'updated work item desc' },
- errors: [],
- },
- },
- }),
- ],
+ [deleteWorkItemFromTaskMutation, deleteWorkItemFromTaskMutationHandler],
+ [deleteWorkItemMutation, deleteWorkItemMutationHandler],
]);
wrapper = shallowMount(WorkItemDetailModal, {
apolloProvider,
- propsData: { workItemId, issueGid },
+ propsData: {
+ ...defaultPropsData,
+ lockVersion,
+ lineNumberStart,
+ lineNumberEnd,
+ },
data() {
return {
error,
@@ -67,8 +84,8 @@ describe('WorkItemDetailModal component', () => {
expect(findWorkItemDetail().props()).toEqual({
isModal: true,
- workItemId: '1',
- workItemParentId: '2',
+ workItemId: defaultPropsData.workItemId,
+ workItemParentId: defaultPropsData.issueGid,
});
});
@@ -109,16 +126,85 @@ describe('WorkItemDetailModal component', () => {
});
describe('delete work item', () => {
- it('emits workItemDeleted and closes modal', async () => {
- createComponent();
- const newDesc = 'updated work item desc';
-
- findWorkItemDetail().vm.$emit('deleteWorkItem');
-
- await waitForPromises();
+ describe('when there is task data', () => {
+ it('emits workItemDeleted and closes modal', async () => {
+ const mutationMock = jest.fn().mockResolvedValue(deleteWorkItemFromTaskMutationResponse);
+ createComponent({
+ lockVersion: 1,
+ lineNumberStart: '3',
+ lineNumberEnd: '3',
+ deleteWorkItemFromTaskMutationHandler: mutationMock,
+ });
+ const newDesc = 'updated work item desc';
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toEqual([[newDesc]]);
+ expect(hideModal).toHaveBeenCalled();
+ expect(mutationMock).toHaveBeenCalledWith({
+ input: {
+ id: defaultPropsData.issueGid,
+ lockVersion: 1,
+ taskData: { id: defaultPropsData.workItemId, lineNumberEnd: 3, lineNumberStart: 3 },
+ },
+ });
+ });
+
+ it.each`
+ errorType | mutationMock | errorMessage
+ ${'an error in the mutation response'} | ${jest.fn().mockResolvedValue(deleteWorkItemFromTaskMutationErrorResponse)} | ${'Error'}
+ ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('GraphQL networkError'))} | ${'GraphQL networkError'}
+ `(
+ 'shows an error message when there is $errorType',
+ async ({ mutationMock, errorMessage }) => {
+ createComponent({
+ lockVersion: 1,
+ lineNumberStart: '3',
+ lineNumberEnd: '3',
+ deleteWorkItemFromTaskMutationHandler: mutationMock,
+ });
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toBeUndefined();
+ expect(hideModal).not.toHaveBeenCalled();
+ expect(findAlert().text()).toBe(errorMessage);
+ },
+ );
+ });
- expect(wrapper.emitted('workItemDeleted')).toEqual([[newDesc]]);
- expect(hideModal).toHaveBeenCalled();
+ describe('when there is no task data', () => {
+ it('emits workItemDeleted and closes modal', async () => {
+ const mutationMock = jest.fn().mockResolvedValue(deleteWorkItemResponse);
+ createComponent({ deleteWorkItemMutationHandler: mutationMock });
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toEqual([[defaultPropsData.workItemId]]);
+ expect(hideModal).toHaveBeenCalled();
+ expect(mutationMock).toHaveBeenCalledWith({ input: { id: defaultPropsData.workItemId } });
+ });
+
+ it.each`
+ errorType | mutationMock | errorMessage
+ ${'an error in the mutation response'} | ${jest.fn().mockResolvedValue(deleteWorkItemMutationErrorResponse)} | ${'Error'}
+ ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('GraphQL networkError'))} | ${'GraphQL networkError'}
+ `(
+ 'shows an error message when there is $errorType',
+ async ({ mutationMock, errorMessage }) => {
+ createComponent({ deleteWorkItemMutationHandler: mutationMock });
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toBeUndefined();
+ expect(hideModal).not.toHaveBeenCalled();
+ expect(findAlert().text()).toBe(errorMessage);
+ },
+ );
});
});
});
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 93bf7286aa7..434c1db8a2c 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
@@ -1,13 +1,20 @@
import Vue from 'vue';
-import { GlForm, GlFormCombobox } from '@gitlab/ui';
+import { GlForm, GlFormInput, GlFormCombobox } from '@gitlab/ui';
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 WorkItemLinksForm from '~/work_items/components/work_item_links/work_item_links_form.vue';
import projectWorkItemsQuery from '~/work_items/graphql/project_work_items.query.graphql';
+import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql';
+import createWorkItemMutation from '~/work_items/graphql/create_work_item.mutation.graphql';
import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
-import { availableWorkItemsResponse, updateWorkItemMutationResponse } from '../../mock_data';
+import {
+ availableWorkItemsResponse,
+ projectWorkItemTypesQueryResponse,
+ createWorkItemMutationResponse,
+ updateWorkItemMutationResponse,
+} from '../../mock_data';
Vue.use(VueApollo);
@@ -15,14 +22,21 @@ describe('WorkItemLinksForm', () => {
let wrapper;
const updateMutationResolver = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
+ const createMutationResolver = jest.fn().mockResolvedValue(createWorkItemMutationResponse);
- const createComponent = async ({ listResponse = availableWorkItemsResponse } = {}) => {
+ const createComponent = async ({
+ listResponse = availableWorkItemsResponse,
+ typesResponse = projectWorkItemTypesQueryResponse,
+ parentConfidential = false,
+ } = {}) => {
wrapper = shallowMountExtended(WorkItemLinksForm, {
apolloProvider: createMockApollo([
[projectWorkItemsQuery, jest.fn().mockResolvedValue(listResponse)],
+ [projectWorkItemTypesQuery, jest.fn().mockResolvedValue(typesResponse)],
[updateWorkItemMutation, updateMutationResolver],
+ [createWorkItemMutation, createMutationResolver],
]),
- propsData: { issuableGid: 'gid://gitlab/WorkItem/1' },
+ propsData: { issuableGid: 'gid://gitlab/WorkItem/1', parentConfidential },
provide: {
projectPath: 'project/path',
},
@@ -33,6 +47,7 @@ describe('WorkItemLinksForm', () => {
const findForm = () => wrapper.findComponent(GlForm);
const findCombobox = () => wrapper.findComponent(GlFormCombobox);
+ const findInput = () => wrapper.findComponent(GlFormInput);
const findAddChildButton = () => wrapper.findByTestId('add-child-button');
beforeEach(async () => {
@@ -47,19 +62,73 @@ describe('WorkItemLinksForm', () => {
expect(findForm().exists()).toBe(true);
});
- it('passes available work items as prop when typing in combobox', async () => {
- findCombobox().vm.$emit('input', 'Task');
+ it('creates child task in non confidential parent', async () => {
+ findInput().vm.$emit('input', 'Create task test');
+
+ findForm().vm.$emit('submit', {
+ preventDefault: jest.fn(),
+ });
await waitForPromises();
+ expect(createMutationResolver).toHaveBeenCalledWith({
+ input: {
+ title: 'Create task test',
+ projectPath: 'project/path',
+ workItemTypeId: 'gid://gitlab/WorkItems::Type/3',
+ hierarchyWidget: {
+ parentId: 'gid://gitlab/WorkItem/1',
+ },
+ confidential: false,
+ },
+ });
+ });
+
+ it('creates child task in confidential parent', async () => {
+ await createComponent({ parentConfidential: true });
+
+ findInput().vm.$emit('input', 'Create confidential task');
- expect(findCombobox().exists()).toBe(true);
- expect(findCombobox().props('tokenList').length).toBe(2);
+ findForm().vm.$emit('submit', {
+ preventDefault: jest.fn(),
+ });
+ await waitForPromises();
+ expect(createMutationResolver).toHaveBeenCalledWith({
+ input: {
+ title: 'Create confidential task',
+ projectPath: 'project/path',
+ workItemTypeId: 'gid://gitlab/WorkItems::Type/3',
+ hierarchyWidget: {
+ parentId: 'gid://gitlab/WorkItem/1',
+ },
+ confidential: true,
+ },
+ });
});
- it('selects and add child', async () => {
+ // Follow up issue to turn this functionality back on https://gitlab.com/gitlab-org/gitlab/-/issues/368757
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip('selects and add child', async () => {
findCombobox().vm.$emit('input', availableWorkItemsResponse.data.workspace.workItems.edges[0]);
findAddChildButton().vm.$emit('click');
await waitForPromises();
expect(updateMutationResolver).toHaveBeenCalled();
});
+
+ // eslint-disable-next-line jest/no-disabled-tests
+ describe.skip('when typing in combobox', () => {
+ beforeEach(async () => {
+ findCombobox().vm.$emit('input', 'Task');
+ await waitForPromises();
+ await jest.runOnlyPendingTimers();
+ });
+
+ it('passes available work items as prop', () => {
+ expect(findCombobox().exists()).toBe(true);
+ expect(findCombobox().props('tokenList').length).toBe(2);
+ });
+
+ it('passes action to create task', () => {
+ expect(findCombobox().props('actionList').length).toBe(1);
+ });
+ });
});
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 f8471b7f167..287ec022d3f 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
@@ -1,75 +1,24 @@
-import Vue from 'vue';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { cloneDeep } from 'lodash';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
+
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
import WorkItemLinksMenu from '~/work_items/components/work_item_links/work_item_links_menu.vue';
-import changeWorkItemParentMutation from '~/work_items/graphql/change_work_item_parent_link.mutation.graphql';
-import getWorkItemLinksQuery from '~/work_items/graphql/work_item_links.query.graphql';
-import { WIDGET_TYPE_HIERARCHY } from '~/work_items/constants';
-import { workItemHierarchyResponse, changeWorkItemParentMutationResponse } from '../../mock_data';
-
-Vue.use(VueApollo);
-
-const PARENT_ID = 'gid://gitlab/WorkItem/1';
-const WORK_ITEM_ID = 'gid://gitlab/WorkItem/3';
describe('WorkItemLinksMenu', () => {
let wrapper;
- let mockApollo;
-
- const $toast = {
- show: jest.fn(),
- };
-
- const createComponent = async ({
- data = {},
- mutationHandler = jest.fn().mockResolvedValue(changeWorkItemParentMutationResponse),
- } = {}) => {
- mockApollo = createMockApollo([
- [getWorkItemLinksQuery, jest.fn().mockResolvedValue(workItemHierarchyResponse)],
- [changeWorkItemParentMutation, mutationHandler],
- ]);
-
- mockApollo.clients.defaultClient.cache.writeQuery({
- query: getWorkItemLinksQuery,
- variables: {
- id: PARENT_ID,
- },
- data: workItemHierarchyResponse.data,
- });
- wrapper = shallowMountExtended(WorkItemLinksMenu, {
- data() {
- return {
- ...data,
- };
- },
- propsData: {
- workItemId: WORK_ITEM_ID,
- parentWorkItemId: PARENT_ID,
- },
- apolloProvider: mockApollo,
- mocks: {
- $toast,
- },
- });
-
- await waitForPromises();
+ const createComponent = () => {
+ wrapper = shallowMountExtended(WorkItemLinksMenu);
};
const findDropdown = () => wrapper.find(GlDropdown);
const findRemoveDropdownItem = () => wrapper.find(GlDropdownItem);
beforeEach(async () => {
- await createComponent();
+ createComponent();
});
afterEach(() => {
wrapper.destroy();
- mockApollo = null;
});
it('renders dropdown and dropdown items', () => {
@@ -77,65 +26,9 @@ describe('WorkItemLinksMenu', () => {
expect(findRemoveDropdownItem().exists()).toBe(true);
});
- it('calls correct mutation with correct variables', async () => {
- const mutationHandler = jest.fn().mockResolvedValue(changeWorkItemParentMutationResponse);
-
- createComponent({ mutationHandler });
-
- findRemoveDropdownItem().vm.$emit('click');
-
- await waitForPromises();
-
- expect(mutationHandler).toHaveBeenCalledWith({
- id: WORK_ITEM_ID,
- parentId: null,
- });
- });
-
- it('shows toast when mutation succeeds', async () => {
- const mutationHandler = jest.fn().mockResolvedValue(changeWorkItemParentMutationResponse);
-
- createComponent({ mutationHandler });
-
- findRemoveDropdownItem().vm.$emit('click');
-
- await waitForPromises();
-
- expect($toast.show).toHaveBeenCalledWith('Child removed', {
- action: { onClick: expect.anything(), text: 'Undo' },
- });
- });
-
- it('updates the cache when mutation succeeds', async () => {
- const mutationHandler = jest.fn().mockResolvedValue(changeWorkItemParentMutationResponse);
-
- createComponent({ mutationHandler });
-
- mockApollo.clients.defaultClient.cache.readQuery = jest.fn(
- () => workItemHierarchyResponse.data,
- );
-
- mockApollo.clients.defaultClient.cache.writeQuery = jest.fn();
-
+ it('emits removeChild event on click Remove', () => {
findRemoveDropdownItem().vm.$emit('click');
- await waitForPromises();
-
- // Remove the work item from parent's children
- const resp = cloneDeep(workItemHierarchyResponse);
- const index = resp.data.workItem.widgets
- .find((widget) => widget.type === WIDGET_TYPE_HIERARCHY)
- .children.nodes.findIndex((child) => child.id === WORK_ITEM_ID);
- resp.data.workItem.widgets
- .find((widget) => widget.type === WIDGET_TYPE_HIERARCHY)
- .children.nodes.splice(index, 1);
-
- expect(mockApollo.clients.defaultClient.cache.writeQuery).toHaveBeenCalledWith(
- expect.objectContaining({
- query: expect.anything(),
- variables: { id: PARENT_ID },
- data: resp.data,
- }),
- );
+ expect(wrapper.emitted('removeChild')).toHaveLength(1);
});
});
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 2ec9b1ec0ac..00f508f1548 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
@@ -1,34 +1,85 @@
import Vue, { nextTick } from 'vue';
-import { GlBadge } from '@gitlab/ui';
+import { GlButton, GlIcon, GlAlert } from '@gitlab/ui';
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 SidebarEventHub from '~/sidebar/event_hub';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import WorkItemLinks from '~/work_items/components/work_item_links/work_item_links.vue';
+import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import changeWorkItemParentMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import getWorkItemLinksQuery from '~/work_items/graphql/work_item_links.query.graphql';
-import { workItemHierarchyResponse, workItemHierarchyEmptyResponse } from '../../mock_data';
+import {
+ workItemHierarchyResponse,
+ workItemHierarchyEmptyResponse,
+ workItemHierarchyNoUpdatePermissionResponse,
+ changeWorkItemParentMutationResponse,
+ workItemQueryResponse,
+} from '../../mock_data';
Vue.use(VueApollo);
describe('WorkItemLinks', () => {
let wrapper;
+ let mockApollo;
+
+ const WORK_ITEM_ID = 'gid://gitlab/WorkItem/2';
+
+ const $toast = {
+ show: jest.fn(),
+ };
+
+ const mutationChangeParentHandler = jest
+ .fn()
+ .mockResolvedValue(changeWorkItemParentMutationResponse);
+
+ const childWorkItemQueryHandler = jest.fn().mockResolvedValue(workItemQueryResponse);
+
+ const findChildren = () => wrapper.findAll('[data-testid="links-child"]');
+
+ const createComponent = async ({
+ data = {},
+ fetchHandler = jest.fn().mockResolvedValue(workItemHierarchyResponse),
+ mutationHandler = mutationChangeParentHandler,
+ } = {}) => {
+ mockApollo = createMockApollo(
+ [
+ [getWorkItemLinksQuery, fetchHandler],
+ [changeWorkItemParentMutation, mutationHandler],
+ [workItemQuery, childWorkItemQueryHandler],
+ ],
+ {},
+ { addTypename: true },
+ );
- const createComponent = async ({ response = workItemHierarchyResponse } = {}) => {
wrapper = shallowMountExtended(WorkItemLinks, {
- apolloProvider: createMockApollo([
- [getWorkItemLinksQuery, jest.fn().mockResolvedValue(response)],
- ]),
+ data() {
+ return {
+ ...data,
+ };
+ },
+ provide: {
+ projectPath: 'project/path',
+ },
propsData: { issuableId: 1 },
+ apolloProvider: mockApollo,
+ mocks: {
+ $toast,
+ },
});
await waitForPromises();
};
+ const findAlert = () => wrapper.findComponent(GlAlert);
const findToggleButton = () => wrapper.findByTestId('toggle-links');
const findLinksBody = () => wrapper.findByTestId('links-body');
const findEmptyState = () => wrapper.findByTestId('links-empty');
const findToggleAddFormButton = () => wrapper.findByTestId('toggle-add-form');
const findAddLinksForm = () => wrapper.findByTestId('add-links-form');
+ const findFirstLinksMenu = () => wrapper.findByTestId('links-menu');
+ const findChildrenCount = () => wrapper.findByTestId('children-count');
beforeEach(async () => {
await createComponent();
@@ -36,6 +87,7 @@ describe('WorkItemLinks', () => {
afterEach(() => {
wrapper.destroy();
+ mockApollo = null;
});
it('is expanded by default', () => {
@@ -43,7 +95,7 @@ describe('WorkItemLinks', () => {
expect(findLinksBody().exists()).toBe(true);
});
- it('expands on click toggle button', async () => {
+ it('collapses on click toggle button', async () => {
findToggleButton().vm.$emit('click');
await nextTick();
@@ -67,7 +119,9 @@ describe('WorkItemLinks', () => {
describe('when no child links', () => {
beforeEach(async () => {
- await createComponent({ response: workItemHierarchyEmptyResponse });
+ await createComponent({
+ fetchHandler: jest.fn().mockResolvedValue(workItemHierarchyEmptyResponse),
+ });
});
it('displays empty state if there are no children', () => {
@@ -78,9 +132,140 @@ describe('WorkItemLinks', () => {
it('renders all hierarchy widget children', () => {
expect(findLinksBody().exists()).toBe(true);
+ expect(findChildren()).toHaveLength(4);
+ expect(findFirstLinksMenu().exists()).toBe(true);
+ });
+
+ it('shows alert when list loading fails', async () => {
+ const errorMessage = 'Some error';
+ await createComponent({
+ fetchHandler: jest.fn().mockRejectedValue(new Error(errorMessage)),
+ });
+
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(errorMessage);
+ });
+
+ it('renders widget child icon and tooltip', () => {
+ expect(findChildren().at(0).findComponent(GlIcon).props('name')).toBe('issue-open-m');
+ expect(findChildren().at(1).findComponent(GlIcon).props('name')).toBe('issue-close');
+ });
+
+ it('renders confidentiality icon when child item is confidential', () => {
const children = wrapper.findAll('[data-testid="links-child"]');
+ const confidentialIcon = children.at(0).find('[data-testid="confidential-icon"]');
+
+ expect(confidentialIcon.exists()).toBe(true);
+ expect(confidentialIcon.props('name')).toBe('eye-slash');
+ });
+
+ it('displays number if children', () => {
+ expect(findChildrenCount().exists()).toBe(true);
+
+ expect(findChildrenCount().text()).toContain('4');
+ });
+
+ it('refetches child items when `confidentialityUpdated` event is emitted on SidebarEventhub', async () => {
+ const fetchHandler = jest.fn().mockResolvedValue(workItemHierarchyResponse);
+ await createComponent({
+ fetchHandler,
+ });
+ await waitForPromises();
+
+ SidebarEventHub.$emit('confidentialityUpdated');
+ await nextTick();
+
+ // First call is done on component mount.
+ // Second call is done on confidentialityUpdated event.
+ expect(fetchHandler).toHaveBeenCalledTimes(2);
+ });
+
+ describe('when no permission to update', () => {
+ beforeEach(async () => {
+ await createComponent({
+ fetchHandler: jest.fn().mockResolvedValue(workItemHierarchyNoUpdatePermissionResponse),
+ });
+ });
- expect(children).toHaveLength(4);
- expect(children.at(0).findComponent(GlBadge).text()).toBe('Open');
+ it('does not display button to toggle Add form', () => {
+ expect(findToggleAddFormButton().exists()).toBe(false);
+ });
+
+ it('does not display link menu on children', () => {
+ expect(findFirstLinksMenu().exists()).toBe(false);
+ });
+ });
+
+ describe('remove child', () => {
+ beforeEach(async () => {
+ await createComponent({ mutationHandler: mutationChangeParentHandler });
+ });
+
+ it('calls correct mutation with correct variables', async () => {
+ findFirstLinksMenu().vm.$emit('removeChild');
+
+ await waitForPromises();
+
+ expect(mutationChangeParentHandler).toHaveBeenCalledWith({
+ input: {
+ id: WORK_ITEM_ID,
+ hierarchyWidget: {
+ parentId: null,
+ },
+ },
+ });
+ });
+
+ it('shows toast when mutation succeeds', async () => {
+ findFirstLinksMenu().vm.$emit('removeChild');
+
+ await waitForPromises();
+
+ expect($toast.show).toHaveBeenCalledWith('Child removed', {
+ action: { onClick: expect.anything(), text: 'Undo' },
+ });
+ });
+
+ it('renders correct number of children after removal', async () => {
+ expect(findChildren()).toHaveLength(4);
+
+ findFirstLinksMenu().vm.$emit('removeChild');
+ await waitForPromises();
+
+ expect(findChildren()).toHaveLength(3);
+ });
+ });
+
+ describe('prefetching child items', () => {
+ beforeEach(async () => {
+ await createComponent();
+ });
+
+ const findChildLink = () => findChildren().at(0).findComponent(GlButton);
+
+ it('does not fetch the child work item before hovering work item links', () => {
+ expect(childWorkItemQueryHandler).not.toHaveBeenCalled();
+ });
+
+ it('fetches the child work item if link is hovered for 250+ ms', async () => {
+ findChildLink().vm.$emit('mouseover');
+ jest.advanceTimersByTime(DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ await waitForPromises();
+
+ expect(childWorkItemQueryHandler).toHaveBeenCalledWith({
+ id: 'gid://gitlab/WorkItem/2',
+ });
+ });
+
+ it('does not fetch the child work item if link is hovered for less than 250 ms', async () => {
+ findChildLink().vm.$emit('mouseover');
+ jest.advanceTimersByTime(200);
+ findChildLink().vm.$emit('mouseout');
+ await waitForPromises();
+
+ expect(childWorkItemQueryHandler).not.toHaveBeenCalled();
+ });
});
});
diff --git a/spec/frontend/work_items/components/work_item_state_spec.js b/spec/frontend/work_items/components/work_item_state_spec.js
index b379d1fc846..6b23a6e4795 100644
--- a/spec/frontend/work_items/components/work_item_state_spec.js
+++ b/spec/frontend/work_items/components/work_item_state_spec.js
@@ -29,6 +29,7 @@ describe('WorkItemState component', () => {
const createComponent = ({
state = STATE_OPEN,
mutationHandler = mutationSuccessHandler,
+ canUpdate = true,
} = {}) => {
const { id, workItemType } = workItemQueryResponse.data.workItem;
wrapper = shallowMount(WorkItemState, {
@@ -39,6 +40,7 @@ describe('WorkItemState component', () => {
state,
workItemType,
},
+ canUpdate,
},
});
};
@@ -53,6 +55,20 @@ describe('WorkItemState component', () => {
expect(findItemState().props('state')).toBe(workItemQueryResponse.data.workItem.state);
});
+ describe('item state disabled prop', () => {
+ describe.each`
+ description | canUpdate | value
+ ${'when cannot update'} | ${false} | ${true}
+ ${'when can update'} | ${true} | ${false}
+ `('$description', ({ canUpdate, value }) => {
+ it(`renders item state component with disabled=${value}`, () => {
+ createComponent({ canUpdate });
+
+ expect(findItemState().props('disabled')).toBe(value);
+ });
+ });
+ });
+
describe('when updating the state', () => {
it('calls a mutation', () => {
createComponent();
diff --git a/spec/frontend/work_items/components/work_item_title_spec.js b/spec/frontend/work_items/components/work_item_title_spec.js
index a48449bb636..c0d966abab8 100644
--- a/spec/frontend/work_items/components/work_item_title_spec.js
+++ b/spec/frontend/work_items/components/work_item_title_spec.js
@@ -20,7 +20,11 @@ describe('WorkItemTitle component', () => {
const findItemTitle = () => wrapper.findComponent(ItemTitle);
- const createComponent = ({ workItemParentId, mutationHandler = mutationSuccessHandler } = {}) => {
+ const createComponent = ({
+ workItemParentId,
+ mutationHandler = mutationSuccessHandler,
+ canUpdate = true,
+ } = {}) => {
const { id, title, workItemType } = workItemQueryResponse.data.workItem;
wrapper = shallowMount(WorkItemTitle, {
apolloProvider: createMockApollo([
@@ -32,6 +36,7 @@ describe('WorkItemTitle component', () => {
workItemTitle: title,
workItemType: workItemType.name,
workItemParentId,
+ canUpdate,
},
});
};
@@ -46,6 +51,20 @@ describe('WorkItemTitle component', () => {
expect(findItemTitle().props('title')).toBe(workItemQueryResponse.data.workItem.title);
});
+ describe('item title disabled prop', () => {
+ describe.each`
+ description | canUpdate | value
+ ${'when cannot update'} | ${false} | ${true}
+ ${'when can update'} | ${true} | ${false}
+ `('$description', ({ canUpdate, value }) => {
+ it(`renders item title component with disabled=${value}`, () => {
+ createComponent({ canUpdate });
+
+ expect(findItemTitle().props('disabled')).toBe(value);
+ });
+ });
+ });
+
describe('when updating the title', () => {
it('calls a mutation', () => {
const title = 'new title!';
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
new file mode 100644
index 00000000000..85466578e18
--- /dev/null
+++ b/spec/frontend/work_items/components/work_item_type_icon_spec.js
@@ -0,0 +1,47 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
+
+let wrapper;
+
+function createComponent(propsData) {
+ wrapper = shallowMount(WorkItemTypeIcon, { propsData });
+}
+
+describe('Work Item type component', () => {
+ const findIcon = () => wrapper.findComponent(GlIcon);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ workItemType | workItemIconName | iconName | text
+ ${'TASK'} | ${''} | ${'issue-type-task'} | ${'Task'}
+ ${''} | ${'issue-type-task'} | ${'issue-type-task'} | ${''}
+ ${'ISSUE'} | ${''} | ${'issue-type-issue'} | ${'Issue'}
+ ${''} | ${'issue-type-issue'} | ${'issue-type-issue'} | ${''}
+ ${'REQUIREMENTS'} | ${''} | ${'issue-type-requirements'} | ${'Requirements'}
+ ${'INCIDENT'} | ${''} | ${'issue-type-incident'} | ${'Incident'}
+ ${'TEST_CASE'} | ${''} | ${'issue-type-test-case'} | ${'Test case'}
+ ${'random-issue-type'} | ${''} | ${'issue-type-issue'} | ${''}
+ `(
+ 'with workItemType set to "$workItemType" and workItemIconName set to "$workItemIconName"',
+ ({ workItemType, workItemIconName, iconName, text }) => {
+ beforeEach(() => {
+ createComponent({
+ workItemType,
+ workItemIconName,
+ });
+ });
+
+ it(`renders icon with name '${iconName}'`, () => {
+ expect(findIcon().props('name')).toBe(iconName);
+ });
+
+ it(`renders correct text`, () => {
+ expect(wrapper.text()).toBe(text);
+ });
+ },
+ );
+});
diff --git a/spec/frontend/work_items/components/work_item_weight_spec.js b/spec/frontend/work_items/components/work_item_weight_spec.js
index c3bbea26cda..94bdb336deb 100644
--- a/spec/frontend/work_items/components/work_item_weight_spec.js
+++ b/spec/frontend/work_items/components/work_item_weight_spec.js
@@ -1,16 +1,21 @@
import { GlForm, GlFormInput } from '@gitlab/ui';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking } from 'helpers/tracking_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import { __ } from '~/locale';
import WorkItemWeight from '~/work_items/components/work_item_weight.vue';
-import { TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
-import localUpdateWorkItemMutation from '~/work_items/graphql/local_update_work_item.mutation.graphql';
+import { i18n, TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
+import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
+import { updateWorkItemMutationResponse } from 'jest/work_items/mock_data';
describe('WorkItemWeight component', () => {
+ Vue.use(VueApollo);
+
let wrapper;
- const mutateSpy = jest.fn();
const workItemId = 'gid://gitlab/WorkItem/1';
const workItemType = 'Task';
@@ -22,8 +27,10 @@ describe('WorkItemWeight component', () => {
hasIssueWeightsFeature = true,
isEditing = false,
weight,
+ mutationHandler = jest.fn().mockResolvedValue(updateWorkItemMutationResponse),
} = {}) => {
wrapper = mountExtended(WorkItemWeight, {
+ apolloProvider: createMockApollo([[updateWorkItemMutation, mutationHandler]]),
propsData: {
canUpdate,
weight,
@@ -33,11 +40,6 @@ describe('WorkItemWeight component', () => {
provide: {
hasIssueWeightsFeature,
},
- mocks: {
- $apollo: {
- mutate: mutateSpy,
- },
- },
});
if (isEditing) {
@@ -131,26 +133,73 @@ describe('WorkItemWeight component', () => {
});
describe('when blurred', () => {
- it('calls a mutation to update the weight', () => {
- const weight = 0;
- createComponent({ isEditing: true, weight });
+ it('calls a mutation to update the weight when the input value is different', () => {
+ const mutationSpy = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
+ createComponent({
+ isEditing: true,
+ weight: 0,
+ mutationHandler: mutationSpy,
+ canUpdate: true,
+ });
+
+ findInput().vm.$emit('blur', { target: { value: 1 } });
+
+ expect(mutationSpy).toHaveBeenCalledWith({
+ input: {
+ id: workItemId,
+ weightWidget: {
+ weight: 1,
+ },
+ },
+ });
+ });
+
+ it('does not call a mutation to update the weight when the input value is the same', () => {
+ const mutationSpy = jest.fn().mockResolvedValue(updateWorkItemMutationResponse);
+ createComponent({ isEditing: true, mutationHandler: mutationSpy, canUpdate: true });
findInput().trigger('blur');
- expect(mutateSpy).toHaveBeenCalledWith({
- mutation: localUpdateWorkItemMutation,
- variables: {
- input: {
- id: workItemId,
- weight,
+ expect(mutationSpy).not.toHaveBeenCalledWith();
+ });
+
+ it('emits an error when there is a GraphQL error', async () => {
+ const response = {
+ data: {
+ workItemUpdate: {
+ errors: ['Error!'],
+ workItem: {},
},
},
+ };
+ createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockResolvedValue(response),
+ canUpdate: true,
+ });
+
+ findInput().trigger('blur');
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
+ });
+
+ it('emits an error when there is a network error', async () => {
+ createComponent({
+ isEditing: true,
+ mutationHandler: jest.fn().mockRejectedValue(new Error()),
+ canUpdate: true,
});
+
+ findInput().trigger('blur');
+ await waitForPromises();
+
+ expect(wrapper.emitted('error')).toEqual([[i18n.updateError]]);
});
it('tracks updating the weight', () => {
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- createComponent();
+ createComponent({ canUpdate: true });
findInput().trigger('blur');
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index 0359caf7116..d24ac2a9f93 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -25,10 +25,14 @@ export const workItemQueryResponse = {
title: 'Test',
state: 'OPEN',
description: 'description',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
deleteWorkItem: false,
@@ -46,6 +50,7 @@ export const workItemQueryResponse = {
__typename: 'WorkItemWidgetAssignees',
type: 'ASSIGNEES',
allowsMultipleAssignees: true,
+ canInviteMembers: true,
assignees: {
nodes: mockAssignees,
},
@@ -57,13 +62,14 @@ export const workItemQueryResponse = {
id: 'gid://gitlab/Issue/1',
iid: '5',
title: 'Parent title',
+ confidential: false,
},
children: {
- edges: [
+ nodes: [
{
- node: {
- id: 'gid://gitlab/WorkItem/444',
- },
+ id: 'gid://gitlab/WorkItem/444',
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
},
],
},
@@ -77,16 +83,21 @@ export const updateWorkItemMutationResponse = {
data: {
workItemUpdate: {
__typename: 'WorkItemUpdatePayload',
+ errors: [],
workItem: {
__typename: 'WorkItem',
id: 'gid://gitlab/WorkItem/1',
title: 'Updated title',
state: 'OPEN',
description: 'description',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
deleteWorkItem: false,
@@ -95,24 +106,46 @@ export const updateWorkItemMutationResponse = {
widgets: [
{
children: {
- edges: [
+ nodes: [
{
- node: 'gid://gitlab/WorkItem/444',
+ id: 'gid://gitlab/WorkItem/444',
},
],
},
},
+ {
+ __typename: 'WorkItemWidgetAssignees',
+ type: 'ASSIGNEES',
+ allowsMultipleAssignees: true,
+ canInviteMembers: true,
+ assignees: {
+ nodes: [mockAssignees[0]],
+ },
+ },
],
},
},
},
};
+export const mockParent = {
+ parent: {
+ id: 'gid://gitlab/Issue/1',
+ iid: '5',
+ title: 'Parent title',
+ confidential: false,
+ },
+};
+
export const workItemResponseFactory = ({
canUpdate = false,
+ canDelete = false,
allowsMultipleAssignees = true,
assigneesWidgetPresent = true,
- parent = null,
+ weightWidgetPresent = true,
+ confidential = false,
+ canInviteMembers = false,
+ parent = mockParent.parent,
} = {}) => ({
data: {
workItem: {
@@ -121,13 +154,17 @@ export const workItemResponseFactory = ({
title: 'Updated title',
state: 'OPEN',
description: 'description',
+ confidential,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
- deleteWorkItem: false,
+ deleteWorkItem: canDelete,
updateWorkItem: canUpdate,
},
widgets: [
@@ -143,20 +180,28 @@ export const workItemResponseFactory = ({
__typename: 'WorkItemWidgetAssignees',
type: 'ASSIGNEES',
allowsMultipleAssignees,
+ canInviteMembers,
assignees: {
nodes: mockAssignees,
},
}
: { type: 'MOCK TYPE' },
+ weightWidgetPresent
+ ? {
+ __typename: 'WorkItemWidgetWeight',
+ type: 'WEIGHT',
+ weight: 0,
+ }
+ : { type: 'MOCK TYPE' },
{
__typename: 'WorkItemWidgetHierarchy',
type: 'HIERARCHY',
children: {
- edges: [
+ nodes: [
{
- node: {
- id: 'gid://gitlab/WorkItem/444',
- },
+ id: 'gid://gitlab/WorkItem/444',
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
},
],
},
@@ -203,10 +248,14 @@ export const createWorkItemMutationResponse = {
title: 'Updated title',
state: 'OPEN',
description: 'description',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
deleteWorkItem: false,
@@ -214,6 +263,7 @@ export const createWorkItemMutationResponse = {
},
widgets: [],
},
+ errors: [],
},
},
};
@@ -229,10 +279,14 @@ export const createWorkItemFromTaskMutationResponse = {
id: 'gid://gitlab/WorkItem/1',
title: 'Updated title',
state: 'OPEN',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
deleteWorkItem: false,
@@ -252,11 +306,15 @@ export const createWorkItemFromTaskMutationResponse = {
id: 'gid://gitlab/WorkItem/1000000',
title: 'Updated title',
state: 'OPEN',
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
description: '',
+ confidential: false,
workItemType: {
__typename: 'WorkItemType',
id: 'gid://gitlab/WorkItems::Type/5',
name: 'Task',
+ iconName: 'issue-type-task',
},
userPermissions: {
deleteWorkItem: false,
@@ -284,6 +342,32 @@ export const deleteWorkItemFailureResponse = {
],
};
+export const deleteWorkItemMutationErrorResponse = {
+ data: {
+ workItemDelete: {
+ errors: ['Error'],
+ },
+ },
+};
+
+export const deleteWorkItemFromTaskMutationResponse = {
+ data: {
+ workItemDeleteTask: {
+ workItem: { id: 123, descriptionHtml: 'updated work item desc' },
+ errors: [],
+ },
+ },
+};
+
+export const deleteWorkItemFromTaskMutationErrorResponse = {
+ data: {
+ workItemDeleteTask: {
+ workItem: { id: 123, descriptionHtml: 'updated work item desc' },
+ errors: ['Error'],
+ },
+ },
+};
+
export const workItemTitleSubscriptionResponse = {
data: {
issuableTitleUpdated: {
@@ -302,6 +386,13 @@ export const workItemHierarchyEmptyResponse = {
__typename: 'WorkItemType',
},
title: 'New title',
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
+ userPermissions: {
+ deleteWorkItem: false,
+ updateWorkItem: false,
+ },
+ confidential: false,
widgets: [
{
type: 'DESCRIPTION',
@@ -322,6 +413,54 @@ export const workItemHierarchyEmptyResponse = {
},
};
+export const workItemHierarchyNoUpdatePermissionResponse = {
+ data: {
+ workItem: {
+ id: 'gid://gitlab/WorkItem/1',
+ workItemType: {
+ id: 'gid://gitlab/WorkItems::Type/6',
+ __typename: 'WorkItemType',
+ },
+ title: 'New title',
+ userPermissions: {
+ deleteWorkItem: false,
+ updateWorkItem: false,
+ },
+ confidential: false,
+ widgets: [
+ {
+ type: 'DESCRIPTION',
+ __typename: 'WorkItemWidgetDescription',
+ },
+ {
+ type: 'HIERARCHY',
+ parent: null,
+ children: {
+ nodes: [
+ {
+ id: 'gid://gitlab/WorkItem/2',
+ workItemType: {
+ id: 'gid://gitlab/WorkItems::Type/5',
+ __typename: 'WorkItemType',
+ },
+ title: 'xyz',
+ state: 'OPEN',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
+ __typename: 'WorkItem',
+ },
+ ],
+ __typename: 'WorkItemConnection',
+ },
+ __typename: 'WorkItemWidgetHierarchy',
+ },
+ ],
+ __typename: 'WorkItem',
+ },
+ },
+};
+
export const workItemHierarchyResponse = {
data: {
workItem: {
@@ -331,6 +470,11 @@ export const workItemHierarchyResponse = {
__typename: 'WorkItemType',
},
title: 'New title',
+ userPermissions: {
+ deleteWorkItem: true,
+ updateWorkItem: true,
+ },
+ confidential: false,
widgets: [
{
type: 'DESCRIPTION',
@@ -349,6 +493,9 @@ export const workItemHierarchyResponse = {
},
title: 'xyz',
state: 'OPEN',
+ confidential: true,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
__typename: 'WorkItem',
},
{
@@ -359,6 +506,9 @@ export const workItemHierarchyResponse = {
},
title: 'abc',
state: 'CLOSED',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: '2022-08-12T13:07:52Z',
__typename: 'WorkItem',
},
{
@@ -369,6 +519,9 @@ export const workItemHierarchyResponse = {
},
title: 'bar',
state: 'OPEN',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
__typename: 'WorkItem',
},
{
@@ -379,6 +532,9 @@ export const workItemHierarchyResponse = {
},
title: 'foobar',
state: 'OPEN',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
__typename: 'WorkItem',
},
],
@@ -396,14 +552,34 @@ export const changeWorkItemParentMutationResponse = {
data: {
workItemUpdate: {
workItem: {
- id: 'gid://gitlab/WorkItem/2',
+ __typename: 'WorkItem',
workItemType: {
- id: 'gid://gitlab/WorkItems::Type/5',
__typename: 'WorkItemType',
+ id: 'gid://gitlab/WorkItems::Type/1',
+ name: 'Issue',
+ iconName: 'issue-type-issue',
},
- title: 'Foo',
+ userPermissions: {
+ deleteWorkItem: true,
+ updateWorkItem: true,
+ },
+ description: null,
+ id: 'gid://gitlab/WorkItem/2',
state: 'OPEN',
- __typename: 'WorkItem',
+ title: 'Foo',
+ confidential: false,
+ createdAt: '2022-08-03T12:41:54Z',
+ closedAt: null,
+ widgets: [
+ {
+ __typename: 'WorkItemWidgetHierarchy',
+ type: 'HIERARCHY',
+ parent: null,
+ children: {
+ nodes: [],
+ },
+ },
+ ],
},
errors: [],
__typename: 'WorkItemUpdatePayload',
@@ -423,6 +599,7 @@ export const availableWorkItemsResponse = {
id: 'gid://gitlab/WorkItem/458',
title: 'Task 1',
state: 'OPEN',
+ createdAt: '2022-08-03T12:41:54Z',
},
},
{
@@ -430,6 +607,7 @@ export const availableWorkItemsResponse = {
id: 'gid://gitlab/WorkItem/459',
title: 'Task 2',
state: 'OPEN',
+ createdAt: '2022-08-03T12:41:54Z',
},
},
],
@@ -551,11 +729,3 @@ export const projectLabelsResponse = {
},
},
};
-
-export const mockParent = {
- parent: {
- id: 'gid://gitlab/Issue/1',
- iid: '5',
- title: 'Parent title',
- },
-};
diff --git a/spec/frontend/work_items/pages/work_item_detail_spec.js b/spec/frontend/work_items/pages/work_item_detail_spec.js
index 43869468ad0..823981df880 100644
--- a/spec/frontend/work_items/pages/work_item_detail_spec.js
+++ b/spec/frontend/work_items/pages/work_item_detail_spec.js
@@ -1,11 +1,12 @@
-import { GlAlert, GlSkeletonLoader, GlButton } from '@gitlab/ui';
+import { GlAlert, GlBadge, GlLoadingIcon, GlSkeletonLoader, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import WorkItemDetail from '~/work_items/components/work_item_detail.vue';
+import WorkItemActions from '~/work_items/components/work_item_actions.vue';
import WorkItemDescription from '~/work_items/components/work_item_description.vue';
import WorkItemState from '~/work_items/components/work_item_state.vue';
import WorkItemTitle from '~/work_items/components/work_item_title.vue';
@@ -16,6 +17,8 @@ import WorkItemInformation from '~/work_items/components/work_item_information.v
import { i18n } from '~/work_items/constants';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
import workItemTitleSubscription from '~/work_items/graphql/work_item_title.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 '~/work_items/graphql/provider';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import {
@@ -30,12 +33,19 @@ describe('WorkItemDetail component', () => {
Vue.use(VueApollo);
- const workItemQueryResponse = workItemResponseFactory();
+ const workItemQueryResponse = workItemResponseFactory({ canUpdate: true, canDelete: true });
+ const workItemQueryResponseWithoutParent = workItemResponseFactory({
+ parent: null,
+ canUpdate: true,
+ canDelete: true,
+ });
const successHandler = jest.fn().mockResolvedValue(workItemQueryResponse);
const initialSubscriptionHandler = jest.fn().mockResolvedValue(workItemTitleSubscriptionResponse);
const findAlert = () => wrapper.findComponent(GlAlert);
const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findWorkItemActions = () => wrapper.findComponent(WorkItemActions);
const findWorkItemTitle = () => wrapper.findComponent(WorkItemTitle);
const findWorkItemState = () => wrapper.findComponent(WorkItemState);
const findWorkItemDescription = () => wrapper.findComponent(WorkItemDescription);
@@ -51,17 +61,21 @@ describe('WorkItemDetail component', () => {
const createComponent = ({
isModal = false,
+ updateInProgress = false,
workItemId = workItemQueryResponse.data.workItem.id,
handler = successHandler,
subscriptionHandler = initialSubscriptionHandler,
+ confidentialityMock = [updateWorkItemMutation, jest.fn()],
workItemsMvc2Enabled = false,
includeWidgets = false,
+ error = undefined,
} = {}) => {
wrapper = shallowMount(WorkItemDetail, {
apolloProvider: createMockApollo(
[
[workItemQuery, handler],
[workItemTitleSubscription, subscriptionHandler],
+ confidentialityMock,
],
{},
{
@@ -69,6 +83,12 @@ describe('WorkItemDetail component', () => {
},
),
propsData: { isModal, workItemId },
+ data() {
+ return {
+ updateInProgress,
+ error,
+ };
+ },
provide: {
glFeatures: {
workItemsMvc2: workItemsMvc2Enabled,
@@ -146,6 +166,148 @@ describe('WorkItemDetail component', () => {
});
});
+ describe('confidentiality', () => {
+ const errorMessage = 'Mutation failed';
+ const confidentialWorkItem = workItemResponseFactory({
+ confidential: true,
+ });
+
+ // Mocks for work item without parent
+ const withoutParentExpectedInputVars = {
+ id: workItemQueryResponse.data.workItem.id,
+ confidential: true,
+ };
+ const toggleConfidentialityWithoutParentHandler = jest.fn().mockResolvedValue({
+ data: {
+ workItemUpdate: {
+ workItem: confidentialWorkItem.data.workItem,
+ errors: [],
+ },
+ },
+ });
+ const withoutParentHandlerMock = jest
+ .fn()
+ .mockResolvedValue(workItemQueryResponseWithoutParent);
+ const confidentialityWithoutParentMock = [
+ updateWorkItemMutation,
+ toggleConfidentialityWithoutParentHandler,
+ ];
+ const confidentialityWithoutParentFailureMock = [
+ updateWorkItemMutation,
+ jest.fn().mockRejectedValue(new Error(errorMessage)),
+ ];
+
+ // Mocks for work item with parent
+ const withParentExpectedInputVars = {
+ id: mockParent.parent.id,
+ taskData: { id: workItemQueryResponse.data.workItem.id, confidential: true },
+ };
+ const toggleConfidentialityWithParentHandler = jest.fn().mockResolvedValue({
+ data: {
+ workItemUpdate: {
+ workItem: {
+ id: confidentialWorkItem.data.workItem.id,
+ descriptionHtml: confidentialWorkItem.data.workItem.description,
+ },
+ task: {
+ workItem: confidentialWorkItem.data.workItem,
+ confidential: true,
+ },
+ errors: [],
+ },
+ },
+ });
+ const confidentialityWithParentMock = [
+ updateWorkItemTaskMutation,
+ toggleConfidentialityWithParentHandler,
+ ];
+ const confidentialityWithParentFailureMock = [
+ updateWorkItemTaskMutation,
+ jest.fn().mockRejectedValue(new Error(errorMessage)),
+ ];
+
+ describe.each`
+ context | handlerMock | confidentialityMock | confidentialityFailureMock | inputVariables
+ ${'no parent'} | ${withoutParentHandlerMock} | ${confidentialityWithoutParentMock} | ${confidentialityWithoutParentFailureMock} | ${withoutParentExpectedInputVars}
+ ${'parent'} | ${successHandler} | ${confidentialityWithParentMock} | ${confidentialityWithParentFailureMock} | ${withParentExpectedInputVars}
+ `(
+ 'when work item has $context',
+ ({ handlerMock, confidentialityMock, confidentialityFailureMock, inputVariables }) => {
+ it('renders confidential badge when work item is confidential', async () => {
+ createComponent({
+ handler: jest.fn().mockResolvedValue(confidentialWorkItem),
+ confidentialityMock,
+ });
+
+ await waitForPromises();
+
+ const confidentialBadge = wrapper.findComponent(GlBadge);
+ expect(confidentialBadge.exists()).toBe(true);
+ expect(confidentialBadge.props()).toMatchObject({
+ variant: 'warning',
+ icon: 'eye-slash',
+ });
+ expect(confidentialBadge.attributes('title')).toBe(
+ 'Only project members with at least the Reporter role, the author, and assignees can view or be notified about this task.',
+ );
+ expect(confidentialBadge.text()).toBe('Confidential');
+ });
+
+ it('renders gl-loading-icon while update mutation is in progress', async () => {
+ createComponent({
+ handler: handlerMock,
+ confidentialityMock,
+ });
+
+ await waitForPromises();
+
+ findWorkItemActions().vm.$emit('toggleWorkItemConfidentiality', true);
+
+ await nextTick();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
+
+ it('emits workItemUpdated and shows confidentiality badge when mutation is successful', async () => {
+ createComponent({
+ handler: handlerMock,
+ confidentialityMock,
+ });
+
+ await waitForPromises();
+
+ findWorkItemActions().vm.$emit('toggleWorkItemConfidentiality', true);
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemUpdated')).toEqual([[{ confidential: true }]]);
+ expect(confidentialityMock[1]).toHaveBeenCalledWith({
+ input: inputVariables,
+ });
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+
+ it('shows alert message when mutation fails', async () => {
+ createComponent({
+ handler: handlerMock,
+ confidentialityMock: confidentialityFailureMock,
+ });
+
+ await waitForPromises();
+ findWorkItemActions().vm.$emit('toggleWorkItemConfidentiality', true);
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemUpdated')).toBeFalsy();
+
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(errorMessage);
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ },
+ );
+ });
+
describe('description', () => {
it('does not show description widget if loading description fails', () => {
createComponent();
@@ -169,7 +331,7 @@ describe('WorkItemDetail component', () => {
});
it('does not show secondary breadcrumbs if there is not a parent', async () => {
- createComponent();
+ createComponent({ handler: jest.fn().mockResolvedValue(workItemQueryResponseWithoutParent) });
await waitForPromises();
@@ -177,7 +339,7 @@ describe('WorkItemDetail component', () => {
});
it('shows work item type if there is not a parent', async () => {
- createComponent();
+ createComponent({ handler: jest.fn().mockResolvedValue(workItemQueryResponseWithoutParent) });
await waitForPromises();
expect(findWorkItemType().exists()).toBe(true);
@@ -276,34 +438,29 @@ describe('WorkItemDetail component', () => {
});
describe('weight widget', () => {
- describe('when work_items_mvc_2 feature flag is enabled', () => {
- describe.each`
- description | includeWidgets | exists
- ${'when widget is returned from API'} | ${true} | ${true}
- ${'when widget is not returned from API'} | ${false} | ${false}
- `('$description', ({ includeWidgets, exists }) => {
- it(`${includeWidgets ? 'renders' : 'does not render'} weight component`, async () => {
- createComponent({ includeWidgets, workItemsMvc2Enabled: true });
- await waitForPromises();
+ describe.each`
+ description | weightWidgetPresent | exists
+ ${'when widget is returned from API'} | ${true} | ${true}
+ ${'when widget is not returned from API'} | ${false} | ${false}
+ `('$description', ({ weightWidgetPresent, exists }) => {
+ it(`${weightWidgetPresent ? 'renders' : 'does not render'} weight component`, async () => {
+ const response = workItemResponseFactory({ weightWidgetPresent });
+ const handler = jest.fn().mockResolvedValue(response);
+ createComponent({ handler });
+ await waitForPromises();
- expect(findWorkItemWeight().exists()).toBe(exists);
- });
+ expect(findWorkItemWeight().exists()).toBe(exists);
});
});
- describe('when work_items_mvc_2 feature flag is disabled', () => {
- describe.each`
- description | includeWidgets | exists
- ${'when widget is returned from API'} | ${true} | ${false}
- ${'when widget is not returned from API'} | ${false} | ${false}
- `('$description', ({ includeWidgets, exists }) => {
- it(`${includeWidgets ? 'renders' : 'does not render'} weight component`, async () => {
- createComponent({ includeWidgets, workItemsMvc2Enabled: false });
- await waitForPromises();
+ it('shows an error message when it emits an `error` event', async () => {
+ createComponent({ workItemsMvc2Enabled: true });
+ await waitForPromises();
- expect(findWorkItemWeight().exists()).toBe(exists);
- });
- });
+ findWorkItemWeight().vm.$emit('error', i18n.updateError);
+ await waitForPromises();
+
+ expect(findAlert().text()).toBe(i18n.updateError);
});
});
diff --git a/spec/frontend/work_items_hierarchy/components/app_spec.js b/spec/frontend/work_items_hierarchy/components/app_spec.js
index 092e9c90553..1426fbfab80 100644
--- a/spec/frontend/work_items_hierarchy/components/app_spec.js
+++ b/spec/frontend/work_items_hierarchy/components/app_spec.js
@@ -1,19 +1,17 @@
-import { nextTick } from 'vue';
-import { createLocalVue, mount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import { mount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { GlBanner } from '@gitlab/ui';
import App from '~/work_items_hierarchy/components/app.vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('WorkItemsHierarchy App', () => {
let wrapper;
const createComponent = (props = {}, data = {}) => {
wrapper = extendedWrapper(
mount(App, {
- localVue,
provide: {
illustrationPath: '/foo.svg',
licensePlan: 'free',
diff --git a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
index 74774e38d6b..67420e7fc2a 100644
--- a/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
+++ b/spec/frontend/work_items_hierarchy/components/hierarchy_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GlBadge } from '@gitlab/ui';
import Hierarchy from '~/work_items_hierarchy/components/hierarchy.vue';
@@ -6,8 +7,7 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import RESPONSE from '~/work_items_hierarchy/static_response';
import { workItemTypes } from '~/work_items_hierarchy/constants';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('WorkItemsHierarchy Hierarchy', () => {
let wrapper;
@@ -32,7 +32,6 @@ describe('WorkItemsHierarchy Hierarchy', () => {
const createComponent = (props = {}) => {
wrapper = extendedWrapper(
mount(Hierarchy, {
- localVue,
propsData: {
workItemTypes: props.workItemTypes,
...props,
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 89b8d8d6d94..12cd6dcad83 100644
--- a/spec/frontend_integration/content_editor/content_editor_integration_spec.js
+++ b/spec/frontend_integration/content_editor/content_editor_integration_spec.js
@@ -61,29 +61,69 @@ describe('content_editor', () => {
});
});
- it('renders footnote ids alongside the footnote definition', async () => {
+ describe('when preserveUnchangedMarkdown feature flag is enabled', () => {
+ beforeEach(() => {
+ gon.features = { preserveUnchangedMarkdown: true };
+ });
+ afterEach(() => {
+ gon.features = { preserveUnchangedMarkdown: false };
+ });
+
+ it('processes and renders footnote ids alongside the footnote definition', async () => {
+ buildWrapper();
+
+ await contentEditorService.setSerializedContent(`
+This reference tag is a mix of letters and numbers [^footnote].
+
+[^footnote]: This is another footnote.
+ `);
+ await nextTick();
+
+ expect(wrapper.text()).toContain('footnote: This is another footnote');
+ });
+
+ it('processes and displays reference definitions', async () => {
+ buildWrapper();
+
+ await contentEditorService.setSerializedContent(`
+[GitLab][gitlab]
+
+[gitlab]: https://gitlab.com
+ `);
+ await nextTick();
+
+ expect(wrapper.find('pre').text()).toContain('[gitlab]: https://gitlab.com');
+ });
+ });
+
+ it('renders table of contents', async () => {
+ jest.useFakeTimers();
+
buildWrapper();
renderMarkdown.mockResolvedValue(`
- <p data-sourcepos="3:1-3:56" dir="auto">
- This reference tag is a mix of letters and numbers. <sup class="footnote-ref"><a href="#fn-footnote-2717" id="fnref-footnote-2717" data-footnote-ref="">2</a></sup>
- </p>
- <section class="footnotes" data-footnotes>
- <ol>
- <li id="fn-footnote-2717">
- <p data-sourcepos="6:7-6:31">This is another footnote. <a href="#fnref-footnote-2717" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
- </li>
- </ol>
- </section>
+<ul class="section-nav">
+</ul>
+<h1 dir="auto" data-sourcepos="3:1-3:11">
+ Heading 1
+</h1>
+<h2 dir="auto" data-sourcepos="5:1-5:12">
+ Heading 2
+</h2>
`);
await contentEditorService.setSerializedContent(`
- This reference tag is a mix of letters and numbers [^footnote].
+[TOC]
- [^footnote]: This is another footnote.
+# Heading 1
+
+## Heading 2
`);
+
await nextTick();
+ jest.runAllTimers();
- expect(wrapper.text()).toContain('footnote: This is another footnote');
+ expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 1');
+ expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 2');
});
});
diff --git a/spec/frontend_integration/fly_out_nav_browser_spec.js b/spec/frontend_integration/fly_out_nav_browser_spec.js
index 47f3c6a0ac2..07ddc0220e6 100644
--- a/spec/frontend_integration/fly_out_nav_browser_spec.js
+++ b/spec/frontend_integration/fly_out_nav_browser_spec.js
@@ -308,19 +308,19 @@ describe('Fly out sidebar navigation', () => {
describe('canShowSubItems', () => {
it('returns true if on desktop size', () => {
- expect(canShowSubItems()).toBeTruthy();
+ expect(canShowSubItems()).toBe(true);
});
it('returns false if on mobile size', () => {
breakpointSize = 'xs';
- expect(canShowSubItems()).toBeFalsy();
+ expect(canShowSubItems()).toBe(false);
});
});
describe('canShowActiveSubItems', () => {
it('returns true by default', () => {
- expect(canShowActiveSubItems(el)).toBeTruthy();
+ expect(canShowActiveSubItems(el)).toBe(true);
});
it('returns false when active & expanded sidebar', () => {
@@ -329,7 +329,7 @@ describe('Fly out sidebar navigation', () => {
setSidebar(sidebar);
- expect(canShowActiveSubItems(el)).toBeFalsy();
+ expect(canShowActiveSubItems(el)).toBe(false);
});
it('returns true when active & collapsed sidebar', () => {
@@ -339,7 +339,7 @@ describe('Fly out sidebar navigation', () => {
setSidebar(sidebar);
- expect(canShowActiveSubItems(el)).toBeTruthy();
+ expect(canShowActiveSubItems(el)).toBe(true);
});
});
diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js
index 3c5ed9dfe20..925db12f36e 100644
--- a/spec/frontend_integration/ide/helpers/start.js
+++ b/spec/frontend_integration/ide/helpers/start.js
@@ -1,5 +1,4 @@
-/* global monaco */
-
+import { editor as monacoEditor } from 'monaco-editor';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { initIde } from '~/ide';
@@ -20,7 +19,7 @@ export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) =
const vm = initIde(el, { extendStore });
// We need to dispose of editor Singleton things or tests will bump into eachother
- vm.$on('destroy', () => monaco.editor.getModels().forEach((model) => model.dispose()));
+ vm.$on('destroy', () => monacoEditor.getModels().forEach((model) => model.dispose()));
return vm;
};
diff --git a/spec/frontend_integration/ide/ide_integration_spec.js b/spec/frontend_integration/ide/ide_integration_spec.js
index da48c600764..a6108fd71e1 100644
--- a/spec/frontend_integration/ide/ide_integration_spec.js
+++ b/spec/frontend_integration/ide/ide_integration_spec.js
@@ -1,6 +1,5 @@
import { nextTick } from 'vue';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
-import { setTestTimeout } from 'helpers/timeout';
import waitForPromises from 'helpers/wait_for_promises';
import { waitForText } from 'helpers/wait_for_text';
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
@@ -17,9 +16,6 @@ describe('WebIDE', () => {
beforeEach(() => {
stubPerformanceWebAPI();
- // For some reason these tests were timing out in CI.
- // We will investigate in https://gitlab.com/gitlab-org/gitlab/-/issues/298714
- setTestTimeout(20000);
setHTMLFixture('<div class="webide-container"></div>');
container = document.querySelector('.webide-container');
});
diff --git a/spec/frontend_integration/snippets/snippets_notes_spec.js b/spec/frontend_integration/snippets/snippets_notes_spec.js
index fdd3289bf58..5e9eaa1aada 100644
--- a/spec/frontend_integration/snippets/snippets_notes_spec.js
+++ b/spec/frontend_integration/snippets/snippets_notes_spec.js
@@ -50,6 +50,11 @@ describe('Integration Snippets notes', () => {
'circled latin capital letter m',
],
],
+ [':', ['100', '1234', '8ball', 'a', 'ab']],
+ // We do not want the search to start with space https://gitlab.com/gitlab-org/gitlab/-/issues/322548
+ [': ', []],
+ // We want to preserve that we can have space INSIDE the search
+ [':red ci', ['large red circle']],
])('shows a correct list of matching emojis when user enters %s', async (input, expected) => {
fillNoteTextarea(input);
diff --git a/spec/frontend_integration/test_helpers/setup/setup_globals.js b/spec/frontend_integration/test_helpers/setup/setup_globals.js
index ac5aeb1dd72..4f2eced40a5 100644
--- a/spec/frontend_integration/test_helpers/setup/setup_globals.js
+++ b/spec/frontend_integration/test_helpers/setup/setup_globals.js
@@ -1,7 +1,3 @@
-import { initializeTestTimeout } from 'helpers/timeout';
-
-initializeTestTimeout(process.env.CI ? 20000 : 7000);
-
beforeEach(() => {
window.gon = {
api_version: 'v4',
diff --git a/spec/graphql/features/feature_flag_spec.rb b/spec/graphql/features/feature_flag_spec.rb
index e5560fccf89..b06718eb16a 100644
--- a/spec/graphql/features/feature_flag_spec.rb
+++ b/spec/graphql/features/feature_flag_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Graphql Field feature flags' do
let(:query_type) do
query_factory do |query|
- query.field :item, type, null: true, feature_flag: feature_flag, resolver: new_resolver(test_object)
+ query.field :item, type, null: true, _deprecated_feature_flag: feature_flag, resolver: new_resolver(test_object)
end
end
diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb
index 84af33a5cb3..5e2ab74a0e5 100644
--- a/spec/graphql/graphql_triggers_spec.rb
+++ b/spec/graphql/graphql_triggers_spec.rb
@@ -47,4 +47,18 @@ RSpec.describe GraphqlTriggers do
GraphqlTriggers.issuable_labels_updated(issue)
end
end
+
+ describe '.issuable_dates_updated' do
+ it 'triggers the issuableDatesUpdated subscription' do
+ work_item = create(:work_item)
+
+ expect(GitlabSchema.subscriptions).to receive(:trigger).with(
+ 'issuableDatesUpdated',
+ { issuable_id: work_item.to_gid },
+ work_item
+ ).and_call_original
+
+ GraphqlTriggers.issuable_dates_updated(work_item)
+ end
+ end
end
diff --git a/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb
new file mode 100644
index 00000000000..f47f1b9869e
--- /dev/null
+++ b/spec/graphql/mutations/ci/runner/bulk_delete_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Ci::Runner::BulkDelete do
+ include GraphqlHelpers
+
+ let_it_be(:admin_user) { create(:user, :admin) }
+ let_it_be(:user) { create(:user) }
+
+ let(:current_ctx) { { current_user: user } }
+
+ let(:mutation_params) do
+ {}
+ end
+
+ describe '#resolve' do
+ subject(:response) do
+ sync(resolve(described_class, args: mutation_params, ctx: current_ctx))
+ end
+
+ context 'when the user cannot admin the runner' do
+ let(:runner) { create(:ci_runner) }
+ let(:mutation_params) do
+ { ids: [runner.to_global_id] }
+ end
+
+ it 'generates an error' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) { response }
+ end
+ end
+
+ context 'when user can delete runners' do
+ let(:user) { admin_user }
+ let!(:runners) do
+ create_list(:ci_runner, 2, :instance)
+ end
+
+ context 'when required arguments are missing' do
+ let(:mutation_params) { {} }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'does not return an error' do
+ is_expected.to match a_hash_including(errors: [])
+ end
+ end
+ end
+
+ context 'with runners specified by id' do
+ let(:mutation_params) do
+ { ids: runners.map(&:to_global_id) }
+ end
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'deletes runners', :aggregate_failures do
+ expect_next_instance_of(
+ ::Ci::Runners::BulkDeleteRunnersService, { runners: runners }
+ ) do |service|
+ expect(service).to receive(:execute).once.and_call_original
+ end
+
+ expect { response }.to change { Ci::Runner.count }.by(-2)
+ expect(response[:errors]).to be_empty
+ end
+
+ context 'when runner list is is above limit' do
+ before do
+ stub_const('::Ci::Runners::BulkDeleteRunnersService::RUNNER_LIMIT', 1)
+ end
+
+ it 'only deletes up to the defined limit', :aggregate_failures do
+ expect { response }.to change { Ci::Runner.count }
+ .by(-::Ci::Runners::BulkDeleteRunnersService::RUNNER_LIMIT)
+ expect(response[:errors]).to be_empty
+ end
+ end
+ end
+
+ context 'when admin mode is disabled', :aggregate_failures do
+ it 'returns error', :aggregate_failures do
+ expect do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ response
+ end
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb
index ffaa6e93d1b..b8efd4213fa 100644
--- a/spec/graphql/mutations/ci/runner/update_spec.rb
+++ b/spec/graphql/mutations/ci/runner/update_spec.rb
@@ -2,12 +2,11 @@
require 'spec_helper'
-RSpec.describe 'Mutations::Ci::Runner::Update' do
+RSpec.describe Mutations::Ci::Runner::Update do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:runner) { create(:ci_runner, active: true, locked: false, run_untagged: true) }
- let_it_be(:described_class) { Mutations::Ci::Runner::Update }
let(:current_ctx) { { current_user: user } }
let(:mutated_runner) { subject[:runner] }
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 8296e5c6c15..102d33378c6 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
@@ -57,17 +57,40 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Update do
end
context 'when there is a validation error' do
- let(:occurred_at) { 'invalid date' }
+ context 'when note is blank' do
+ let(:note) { '' }
- it 'does not update the timeline event' do
- expect { resolve }.not_to change { timeline_event.reload.updated_at }
+ it 'does not update the timeline event' do
+ expect { resolve }.not_to change { timeline_event.reload.updated_at }
+ end
+
+ it 'responds with error' do
+ expect(resolve).to eq(timeline_event: nil, errors: ["Note can't be blank"])
+ end
end
- it 'responds with error' do
- expect(resolve).to eq(
- timeline_event: nil,
- errors: ["Occurred at can't be blank"]
- )
+ context 'when occurred_at is blank' do
+ let(:occurred_at) { '' }
+
+ it 'does not update the timeline event' do
+ expect { resolve }.not_to change { timeline_event.reload.updated_at }
+ end
+
+ it 'responds with error' do
+ expect(resolve).to eq(timeline_event: nil, errors: ["Occurred at can't be blank"])
+ end
+ end
+
+ context 'when occurred_at is invalid' do
+ let(:occurred_at) { 'invalid date' }
+
+ it 'does not update the timeline event' do
+ expect { resolve }.not_to change { timeline_event.reload.updated_at }
+ end
+
+ it 'responds with error' do
+ expect(resolve).to eq(timeline_event: nil, errors: ["Occurred at can't be blank"])
+ end
end
end
end
diff --git a/spec/graphql/mutations/merge_requests/set_labels_spec.rb b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
index 1bb303cf99b..44bd9342b8e 100644
--- a/spec/graphql/mutations/merge_requests/set_labels_spec.rb
+++ b/spec/graphql/mutations/merge_requests/set_labels_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Mutations::MergeRequests::SetLabels do
end
context 'when passing operation_mode as REMOVE' do
- subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids, operation_mode: Types::MutationOperationModeEnum.enum[:remove])}
+ subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids, operation_mode: Types::MutationOperationModeEnum.enum[:remove]) }
it 'removes the labels, without removing others' do
merge_request.update!(labels: [label, label2])
diff --git a/spec/graphql/mutations/merge_requests/set_reviewers_spec.rb b/spec/graphql/mutations/merge_requests/set_reviewers_spec.rb
new file mode 100644
index 00000000000..df4aa885bbf
--- /dev/null
+++ b/spec/graphql/mutations/merge_requests/set_reviewers_spec.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::MergeRequests::SetReviewers do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request, reload: true) { create(:merge_request) }
+ let_it_be(:reviewer) { create(:user) }
+ let_it_be(:reviewer2) { create(:user) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ describe '#resolve' do
+ let(:reviewer_usernames) { [reviewer.username] }
+ let(:mutated_merge_request) { subject[:merge_request] }
+ let(:mode) { described_class.arguments['operationMode'].default_value }
+
+ subject do
+ mutation.resolve(project_path: merge_request.project.full_path,
+ iid: merge_request.iid,
+ operation_mode: mode,
+ reviewer_usernames: reviewer_usernames)
+ end
+
+ it 'does not change reviewers if the merge_request is not accessible to the reviewers' do
+ merge_request.project.add_developer(user)
+
+ expect { subject }.not_to change { merge_request.reload.reviewer_ids }
+ end
+
+ it 'returns an operational error if the merge_request is not accessible to the reviewers' do
+ merge_request.project.add_developer(user)
+
+ result = subject
+
+ expect(result[:errors]).to include a_string_matching(/Cannot assign/)
+ end
+
+ context 'when the user does not have permissions' do
+ it_behaves_like 'permission level for merge request mutation is correctly verified'
+ end
+
+ context 'when the user can update the merge_request' do
+ before do
+ merge_request.project.add_developer(reviewer)
+ merge_request.project.add_developer(reviewer2)
+ merge_request.project.add_developer(user)
+ end
+
+ it 'replaces the reviewer' do
+ merge_request.reviewers = [reviewer2]
+ merge_request.save!
+
+ expect(mutated_merge_request).to eq(merge_request)
+ expect(mutated_merge_request.reviewers).to contain_exactly(reviewer)
+ expect(subject[:errors]).to be_empty
+ end
+
+ it 'returns errors when merge_request could not be updated' do
+ allow(merge_request).to receive(:errors_on_object).and_return(['foo'])
+
+ expect(subject[:errors]).not_to match_array(['foo'])
+ end
+
+ context 'when passing an empty reviewer list' do
+ let(:reviewer_usernames) { [] }
+
+ before do
+ merge_request.reviewers = [reviewer]
+ merge_request.save!
+ end
+
+ it 'removes all reviewers' do
+ expect(mutated_merge_request).to eq(merge_request)
+ expect(mutated_merge_request.reviewers).to eq([])
+ expect(subject[:errors]).to be_empty
+ end
+ end
+
+ context 'when passing "append" as true' do
+ subject do
+ mutation.resolve(
+ project_path: merge_request.project.full_path,
+ iid: merge_request.iid,
+ reviewer_usernames: reviewer_usernames,
+ operation_mode: Types::MutationOperationModeEnum.enum[:append]
+ )
+ end
+
+ before do
+ merge_request.reviewers = [reviewer2]
+ merge_request.save!
+
+ # In CE, APPEND is a NOOP as you can't have multiple reviewers
+ # We test multiple assignment in EE specs
+ stub_licensed_features(multiple_merge_request_reviewers: false)
+ end
+
+ it 'is a NO-OP in FOSS' do
+ expect(mutated_merge_request).to eq(merge_request)
+ expect(mutated_merge_request.reviewers).to contain_exactly(reviewer2)
+ expect(subject[:errors]).to be_empty
+ end
+ end
+
+ context 'when passing "remove" as true' do
+ before do
+ merge_request.reviewers = [reviewer]
+ merge_request.save!
+ end
+
+ it 'removes named reviewer' do
+ mutated_merge_request = mutation.resolve(
+ project_path: merge_request.project.full_path,
+ iid: merge_request.iid,
+ reviewer_usernames: reviewer_usernames,
+ operation_mode: Types::MutationOperationModeEnum.enum[:remove]
+ )[:merge_request]
+
+ expect(mutated_merge_request).to eq(merge_request)
+ expect(mutated_merge_request.reviewers).to eq([])
+ expect(subject[:errors]).to be_empty
+ end
+
+ it 'does not remove unnamed reviewer' do
+ mutated_merge_request = mutation.resolve(
+ project_path: merge_request.project.full_path,
+ iid: merge_request.iid,
+ reviewer_usernames: [reviewer2.username],
+ operation_mode: Types::MutationOperationModeEnum.enum[:remove]
+ )[:merge_request]
+
+ expect(mutated_merge_request).to eq(merge_request)
+ expect(mutated_merge_request.reviewers).to contain_exactly(reviewer)
+ expect(subject[:errors]).to be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/releases/create_spec.rb b/spec/graphql/mutations/releases/create_spec.rb
index 1f2c3ed537f..b6b9449aa39 100644
--- a/spec/graphql/mutations/releases/create_spec.rb
+++ b/spec/graphql/mutations/releases/create_spec.rb
@@ -11,9 +11,9 @@ RSpec.describe Mutations::Releases::Create do
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
- let(:tag) { 'v1.1.0'}
- let(:ref) { 'master'}
- let(:name) { 'Version 1.0'}
+ let(:tag) { 'v1.1.0' }
+ let(:ref) { 'master' }
+ let(:name) { 'Version 1.0' }
let(:description) { 'The first release :rocket:' }
let(:released_at) { Time.parse('2018-12-10') }
let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
diff --git a/spec/graphql/mutations/releases/delete_spec.rb b/spec/graphql/mutations/releases/delete_spec.rb
index 9934aea0031..09b420fe1ea 100644
--- a/spec/graphql/mutations/releases/delete_spec.rb
+++ b/spec/graphql/mutations/releases/delete_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Mutations::Releases::Delete do
let_it_be(:reporter) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:maintainer) { create(:user) }
- let_it_be(:tag) { 'v1.1.0'}
+ let_it_be(:tag) { 'v1.1.0' }
let_it_be(:release) { create(:release, project: project, tag: tag) }
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
diff --git a/spec/graphql/mutations/releases/update_spec.rb b/spec/graphql/mutations/releases/update_spec.rb
index 9fae703b85a..15b10ea0648 100644
--- a/spec/graphql/mutations/releases/update_spec.rb
+++ b/spec/graphql/mutations/releases/update_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe Mutations::Releases::Update do
let_it_be(:reporter) { create(:user) }
let_it_be(:developer) { create(:user) }
- let_it_be(:tag) { 'v1.1.0'}
- let_it_be(:name) { 'Version 1.0'}
+ let_it_be(:tag) { 'v1.1.0' }
+ let_it_be(:name) { 'Version 1.0' }
let_it_be(:description) { 'The first release :rocket:' }
let_it_be(:released_at) { Time.parse('2018-12-10').utc }
let_it_be(:created_at) { Time.parse('2018-11-05').utc }
diff --git a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb
index 53b673e255b..ba8a127bec5 100644
--- a/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runner_jobs_resolver_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Resolvers::Ci::RunnerJobsResolver do
let!(:build_one) { create(:ci_build, :success, name: 'Build One', runner: runner, pipeline: pipeline) }
let!(:build_two) { create(:ci_build, :success, name: 'Build Two', runner: runner, pipeline: pipeline) }
let!(:build_three) { create(:ci_build, :failed, name: 'Build Three', runner: runner, pipeline: pipeline) }
- let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
+ let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline) }
let(:args) { {} }
let(:runner) { create(:ci_runner, :project, projects: [project]) }
diff --git a/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb b/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb
new file mode 100644
index 00000000000..0128ec792b3
--- /dev/null
+++ b/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Crm::ContactStateCountsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+
+ before_all do
+ create(:contact, group: group, email: "x@test.com")
+ create(:contact, group: group, email: "y@test.com", state: 'inactive')
+ create_list(:contact, 3, group: group)
+ create_list(:contact, 2, group: group, state: 'inactive')
+ end
+
+ describe '#resolve' do
+ context 'with unauthorized user' do
+ it 'does not raise an error and returns no counts' do
+ expect { resolve_counts(group) }.not_to raise_error
+ expect(resolve_counts(group).all).to be(0)
+ end
+ end
+
+ context 'with authorized user' do
+ before do
+ group.add_reporter(user)
+ end
+
+ context 'without parent' do
+ it 'returns no counts' do
+ expect(resolve_counts(nil).all).to be(0)
+ end
+ end
+
+ context 'with a group' do
+ context 'when no filter is provided' do
+ it 'returns the count of all contacts' do
+ counts = resolve_counts(group)
+ expect(counts.all).to eq(7)
+ expect(counts.active).to eq(4)
+ expect(counts.inactive).to eq(3)
+ end
+ end
+
+ context 'when search term is provided' do
+ it 'returns the correct counts' do
+ counts = resolve_counts(group, { search: "@test.com" })
+
+ expect(counts.all).to be(2)
+ expect(counts.active).to be(1)
+ expect(counts.inactive).to be(1)
+ end
+ end
+ end
+ end
+ end
+
+ def resolve_counts(parent, args = {}, context = { current_user: user })
+ resolve(described_class, obj: parent, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
index 98da4aeac28..c7c2d11e114 100644
--- a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
+++ b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Resolvers::Crm::ContactsResolver do
last_name: "DEF",
email: "ghi@test.com",
description: "LMNO",
+ organization: create(:organization, group: group),
state: "inactive"
)
end
@@ -61,11 +62,29 @@ RSpec.describe Resolvers::Crm::ContactsResolver do
end
context 'when no filter is provided' do
- it 'returns all the contacts in the correct order' do
+ it 'returns all the contacts in the default order' do
expect(resolve_contacts(group)).to eq([contact_a, contact_b])
end
end
+ context 'when a sort is provided' do
+ it 'returns all the contacts in the correct order' do
+ expect(resolve_contacts(group, { sort: 'EMAIL_DESC' })).to eq([contact_b, contact_a])
+ end
+ end
+
+ context 'when a sort is provided needing offset_pagination' do
+ it 'returns all the contacts in the correct order' do
+ expect(resolve_contacts(group, { sort: 'ORGANIZATION_ASC' })).to eq([contact_a, contact_b])
+ end
+ end
+
+ context 'when filtering for all states' do
+ it 'returns all the contacts in the correct order' do
+ expect(resolve_contacts(group, { state: 'all' })).to eq([contact_a, contact_b])
+ end
+ end
+
context 'when search term is provided' do
it 'returns the correct contacts' do
expect(resolve_contacts(group, { search: "x@test.com" })).to contain_exactly(contact_b)
diff --git a/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb b/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb
index 8d0b8f9398d..e1c67bc7c18 100644
--- a/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_members/notification_email_resolver_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Resolvers::GroupMembers::NotificationEmailResolver do
expect(described_class).to have_nullable_graphql_type(GraphQL::Types::String)
end
- subject { batch_sync { resolve_notification_email(developer.group_members.first, current_user) }}
+ subject { batch_sync { resolve_notification_email(developer.group_members.first, current_user) } }
context 'when current_user is admin' do
let(:current_user) { create(:user, :admin) }
diff --git a/spec/graphql/resolvers/project_jobs_resolver_spec.rb b/spec/graphql/resolvers/project_jobs_resolver_spec.rb
index bb711a4c857..eb9d31ea7e5 100644
--- a/spec/graphql/resolvers/project_jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_jobs_resolver_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Resolvers::ProjectJobsResolver do
let_it_be(:failed_build) { create(:ci_build, :failed, name: 'Build Three', pipeline: pipeline) }
let_it_be(:pending_build) { create(:ci_build, :pending, name: 'Build Three', pipeline: pipeline) }
- let(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
+ let(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline) }
let(:args) { {} }
let(:current_user) { create(:user) }
diff --git a/spec/graphql/resolvers/projects/fork_targets_resolver_spec.rb b/spec/graphql/resolvers/projects/fork_targets_resolver_spec.rb
new file mode 100644
index 00000000000..ef1b18f0a11
--- /dev/null
+++ b/spec/graphql/resolvers/projects/fork_targets_resolver_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Projects::ForkTargetsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group, path: 'namespace-group') }
+ let_it_be(:another_group) { create(:group, path: 'namespace-another-group') }
+ let_it_be(:project) { create(:project, :private, group: group) }
+ let_it_be(:user) { create(:user, username: 'namespace-user', maintainer_projects: [project]) }
+
+ let(:args) { { search: 'namespace' } }
+
+ describe '#resolve' do
+ before_all do
+ group.add_owner(user)
+ another_group.add_owner(user)
+ end
+
+ it 'returns forkable namespaces' do
+ expect_next_instance_of(ForkTargetsFinder) do |finder|
+ expect(finder).to receive(:execute).with(args).and_call_original
+ end
+
+ expect(resolve_targets(args).items).to match_array([user.namespace, project.namespace, another_group])
+ end
+ end
+
+ context 'when a user cannot fork the project' do
+ let(:user) { create(:user) }
+
+ it 'does not return results' do
+ project.add_guest(user)
+
+ expect(resolve_targets(args)).to be_nil
+ end
+ end
+
+ def resolve_targets(args, opts = {})
+ field_options = described_class.field_options.merge(
+ owner: resolver_parent,
+ name: 'field_value'
+ ).merge(opts)
+
+ field = ::Types::BaseField.new(**field_options)
+ resolve_field(field, project, args: args, ctx: { current_user: user }, object_type: resolver_parent)
+ end
+end
diff --git a/spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb b/spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb
index 854e763fbdd..546b8592546 100644
--- a/spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects/grafana_integration_resolver_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Resolvers::Projects::GrafanaIntegrationResolver do
let_it_be(:project) { create(:project) }
let_it_be(:current_user) { create(:user) }
- let_it_be(:grafana_integration) { create(:grafana_integration, project: project)}
+ let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
describe '#resolve' do
context 'when object is not a project' do
@@ -19,7 +19,7 @@ RSpec.describe Resolvers::Projects::GrafanaIntegrationResolver do
end
context 'when object is nil' do
- it { expect(resolve_integration(obj: nil)).to eq nil}
+ it { expect(resolve_integration(obj: nil)).to eq nil }
end
end
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
index 2685115d1a2..453fafb9590 100644
--- a/spec/graphql/resolvers/projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -142,7 +142,7 @@ RSpec.describe Resolvers::ProjectsResolver do
context 'when no sort is provided' do
it 'returns projects in descending order by id' do
- is_expected.to match_array((visible_projecs + named_projects).sort_by { |p| p[:id]}.reverse )
+ is_expected.to match_array((visible_projecs + named_projects).sort_by { |p| p[:id] }.reverse )
end
end
end
diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb
index 439678e7e16..b85716e4d21 100644
--- a/spec/graphql/types/base_field_spec.rb
+++ b/spec/graphql/types/base_field_spec.rb
@@ -209,7 +209,7 @@ RSpec.describe Types::BaseField do
describe '#visible?' do
context 'and has a feature_flag' do
let(:flag) { :test_feature }
- let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false) }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, _deprecated_feature_flag: flag, null: false) }
let(:context) { {} }
before do
@@ -253,7 +253,7 @@ RSpec.describe Types::BaseField do
describe '#description' do
context 'feature flag given' do
- let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, feature_flag: flag, null: false, description: 'Test description.') }
+ let(:field) { described_class.new(name: 'test', type: GraphQL::Types::String, _deprecated_feature_flag: flag, null: false, description: 'Test description.') }
let(:flag) { :test_flag }
it 'prepends the description' do
@@ -299,7 +299,7 @@ RSpec.describe Types::BaseField do
end
it 'returns the correct availability in the description' do
- expect(field.description). to eq expected_description
+ expect(field.description).to eq expected_description
end
end
end
@@ -313,11 +313,11 @@ RSpec.describe Types::BaseField do
described_class.new(**base_args.merge(args))
end
- it 'interacts well with the `feature_flag` property' do
+ it 'interacts well with the `_deprecated_feature_flag` property' do
field = subject(
deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
description: 'Field description.',
- feature_flag: 'foo_flag'
+ _deprecated_feature_flag: 'foo_flag'
)
expect(field.description).to start_with('Field description. Available only when feature flag `foo_flag` is enabled.')
diff --git a/spec/graphql/types/ci/group_variable_type_spec.rb b/spec/graphql/types/ci/group_variable_type_spec.rb
new file mode 100644
index 00000000000..106935642f2
--- /dev/null
+++ b/spec/graphql/types/ci/group_variable_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiGroupVariable'] do
+ specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) }
+
+ specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least }
+end
diff --git a/spec/graphql/types/ci/instance_variable_type_spec.rb b/spec/graphql/types/ci/instance_variable_type_spec.rb
new file mode 100644
index 00000000000..cf4aaed31f1
--- /dev/null
+++ b/spec/graphql/types/ci/instance_variable_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiInstanceVariable'] do
+ specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) }
+
+ specify { expect(described_class).to have_graphql_fields(:masked, :protected).at_least }
+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 c1a3c4dd54d..457d46b6896 100644
--- a/spec/graphql/types/ci/job_token_scope_type_spec.rb
+++ b/spec/graphql/types/ci/job_token_scope_type_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
subject { GitlabSchema.execute(query, context: { current_user: current_user }).as_json }
let(:projects_field) { subject.dig('data', 'project', 'ciJobTokenScope', 'projects', 'nodes') }
- let(:returned_project_paths) { projects_field.map { |project| project['path']} }
+ let(:returned_project_paths) { projects_field.map { |project| project['path'] } }
context 'with access to scope' do
before do
diff --git a/spec/graphql/types/ci/manual_variable_type_spec.rb b/spec/graphql/types/ci/manual_variable_type_spec.rb
new file mode 100644
index 00000000000..2884c818a52
--- /dev/null
+++ b/spec/graphql/types/ci/manual_variable_type_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiManualVariable'] do
+ specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) }
+end
diff --git a/spec/graphql/types/ci/project_variable_type_spec.rb b/spec/graphql/types/ci/project_variable_type_spec.rb
new file mode 100644
index 00000000000..e6e045b2bca
--- /dev/null
+++ b/spec/graphql/types/ci/project_variable_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiProjectVariable'] do
+ specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) }
+
+ specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least }
+end
diff --git a/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb b/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb
new file mode 100644
index 00000000000..ef378f3fc5a
--- /dev/null
+++ b/spec/graphql/types/ci/runner_upgrade_status_enum_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::RunnerUpgradeStatusEnum do
+ let(:model_only_enum_values) { %w[not_processed] }
+ let(:expected_graphql_source_values) do
+ Ci::RunnerVersion.statuses.keys - model_only_enum_values
+ end
+
+ specify { expect(described_class.graphql_name).to eq('CiRunnerUpgradeStatus') }
+
+ it 'exposes all upgrade status values except not_processed' do
+ expect(described_class.values.keys).to match_array(
+ expected_graphql_source_values
+ .map(&:upcase)
+ .map { |v| v == 'INVALID_VERSION' ? 'INVALID' : v }
+ )
+ end
+
+ it 'exposes all upgrade status values except enum-only values' do
+ expect(described_class.values.values.map(&:value).map(&:to_s)).to match_array(expected_graphql_source_values)
+ end
+end
diff --git a/spec/graphql/types/ci/runner_upgrade_status_type_enum_spec.rb b/spec/graphql/types/ci/runner_upgrade_status_type_enum_spec.rb
deleted file mode 100644
index 03c784dcbe7..00000000000
--- a/spec/graphql/types/ci/runner_upgrade_status_type_enum_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Types::Ci::RunnerUpgradeStatusTypeEnum do
- let(:model_only_enum_values) { %w[not_processed] }
- let(:expected_graphql_source_values) do
- Ci::RunnerVersion.statuses.keys - model_only_enum_values
- end
-
- specify { expect(described_class.graphql_name).to eq('CiRunnerUpgradeStatusType') }
-
- it 'exposes all upgrade status values except not_processed' do
- expect(described_class.values.keys).to match_array(
- expected_graphql_source_values
- .map(&:upcase)
- .map { |v| v == 'INVALID_VERSION' ? 'INVALID' : v }
- )
- end
-
- it 'exposes all upgrade status values except enum-only values' do
- expect(described_class.values.values.map(&:value).map(&:to_s)).to match_array(expected_graphql_source_values)
- end
-end
diff --git a/spec/graphql/types/ci/variable_input_type_spec.rb b/spec/graphql/types/ci/variable_input_type_spec.rb
new file mode 100644
index 00000000000..a56b6287dee
--- /dev/null
+++ b/spec/graphql/types/ci/variable_input_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiVariableInput'] do
+ include GraphqlHelpers
+
+ it 'has the correct arguments' do
+ expect(described_class.arguments.keys).to match_array(%w[key value])
+ end
+end
diff --git a/spec/graphql/types/ci/variable_interface_spec.rb b/spec/graphql/types/ci/variable_interface_spec.rb
new file mode 100644
index 00000000000..8cef0ac2a14
--- /dev/null
+++ b/spec/graphql/types/ci/variable_interface_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiVariable'] do
+ specify do
+ expect(described_class).to have_graphql_fields(
+ :id, :key, :value, :variable_type, :raw
+ ).at_least
+ end
+end
diff --git a/spec/graphql/types/ci/variable_type_spec.rb b/spec/graphql/types/ci/variable_type_spec.rb
deleted file mode 100644
index a81e6adbab6..00000000000
--- a/spec/graphql/types/ci/variable_type_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GitlabSchema.types['CiVariable'] do
- it 'contains attributes related to CI variables' do
- expect(described_class).to have_graphql_fields(
- :id, :key, :value, :variable_type, :protected, :masked, :raw, :environment_scope
- )
- end
-end
diff --git a/spec/graphql/types/customer_relations/contact_sort_enum_spec.rb b/spec/graphql/types/customer_relations/contact_sort_enum_spec.rb
new file mode 100644
index 00000000000..5b0538042c8
--- /dev/null
+++ b/spec/graphql/types/customer_relations/contact_sort_enum_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContactSort'] do
+ specify { expect(described_class.graphql_name).to eq('ContactSort') }
+
+ it_behaves_like 'common sort values'
+
+ it 'exposes all the contact sort values' do
+ expect(described_class.values.keys).to include(
+ *%w[
+ FIRST_NAME_ASC
+ FIRST_NAME_DESC
+ LAST_NAME_ASC
+ LAST_NAME_DESC
+ EMAIL_ASC
+ EMAIL_DESC
+ PHONE_ASC
+ PHONE_DESC
+ DESCRIPTION_ASC
+ DESCRIPTION_DESC
+ ORGANIZATION_ASC
+ ORGANIZATION_DESC
+ ]
+ )
+ end
+end
diff --git a/spec/graphql/types/customer_relations/contact_state_counts_type_spec.rb b/spec/graphql/types/customer_relations/contact_state_counts_type_spec.rb
new file mode 100644
index 00000000000..b022febb90f
--- /dev/null
+++ b/spec/graphql/types/customer_relations/contact_state_counts_type_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContactStateCounts'] do
+ let(:fields) do
+ %w[
+ all
+ active
+ inactive
+ ]
+ end
+
+ it { expect(described_class.graphql_name).to eq('ContactStateCounts') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+ it { expect(described_class).to require_graphql_authorizations(:read_crm_contact) }
+end
diff --git a/spec/graphql/types/global_id_type_spec.rb b/spec/graphql/types/global_id_type_spec.rb
index a57db9234f1..fa0b34113bc 100644
--- a/spec/graphql/types/global_id_type_spec.rb
+++ b/spec/graphql/types/global_id_type_spec.rb
@@ -114,7 +114,11 @@ RSpec.describe Types::GlobalIDType do
end
before do
- deprecation = Gitlab::GlobalId::Deprecations::Deprecation.new(old_model_name: 'OldIssue', new_model_name: 'Issue', milestone: '10.0')
+ deprecation = Gitlab::GlobalId::Deprecations::NameDeprecation.new(
+ old_name: 'OldIssue',
+ new_name: 'Issue',
+ milestone: '10.0'
+ )
stub_global_id_deprecations(deprecation)
end
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 69c7eaf111f..72b3bb90194 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['Group'] do
+ include GraphqlHelpers
+
specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Group) }
specify { expect(described_class.graphql_name).to eq('Group') }
@@ -22,8 +24,8 @@ RSpec.describe GitlabSchema.types['Group'] do
dependency_proxy_blobs dependency_proxy_image_count
dependency_proxy_blob_count dependency_proxy_total_size
dependency_proxy_image_prefix dependency_proxy_image_ttl_policy
- shared_runners_setting timelogs organizations contacts work_item_types
- recent_issue_boards ci_variables
+ shared_runners_setting timelogs organizations contacts contact_state_counts
+ work_item_types recent_issue_boards ci_variables
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -53,7 +55,52 @@ RSpec.describe GitlabSchema.types['Group'] do
end
end
+ describe 'contact_state_counts field' do
+ subject { described_class.fields['contactStateCounts'] }
+
+ it { is_expected.to have_graphql_type(Types::CustomerRelations::ContactStateCountsType) }
+ it { is_expected.to have_graphql_resolver(Resolvers::Crm::ContactStateCountsResolver) }
+ end
+
it_behaves_like 'a GraphQL type with labels' do
let(:labels_resolver_arguments) { [:search_term, :includeAncestorGroups, :includeDescendantGroups, :onlyGroupLabels] }
end
+
+ describe 'milestones' do
+ let(:user) { create(:user) }
+ let(:subgroup) { create(:group, parent: create(:group)) }
+ let(:query) do
+ %(
+ query {
+ group(fullPath: "#{subgroup.full_path}") {
+ milestones {
+ nodes {
+ id
+ title
+ projectMilestone
+ groupMilestone
+ subgroupMilestone
+ }
+ }
+ }
+ }
+ )
+ end
+
+ def clean_state_query
+ run_with_clean_state(query, context: { current_user: user })
+ end
+
+ it 'avoids N+1 queries' do
+ subgroup.add_reporter(user)
+
+ create(:milestone, group: subgroup)
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) { clean_state_query }
+
+ create_list(:milestone, 2, group: subgroup)
+
+ expect { clean_state_query }.not_to exceed_all_query_limit(control)
+ end
+ end
end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index e7454b85357..2a0ae79b2c4 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -167,7 +167,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
shared_examples_for 'does not include private notes' do
it "does not return private notes" do
notes = subject.dig("data", "project", "issue", "notes", 'edges')
- notes_body = notes.map {|n| n.dig('node', 'body')}
+ notes_body = notes.map { |n| n.dig('node', 'body') }
expect(notes.size).to eq 1
expect(notes_body).not_to include(private_note_body)
@@ -178,7 +178,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
shared_examples_for 'includes private notes' do
it "returns all notes" do
notes = subject.dig("data", "project", "issue", "notes", 'edges')
- notes_body = notes.map {|n| n.dig('node', 'body')}
+ notes_body = notes.map { |n| n.dig('node', 'body') }
expect(notes.size).to eq 2
expect(notes_body).to include(private_note_body)
@@ -209,7 +209,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
end
describe 'hidden', :enable_admin_mode do
- let_it_be(:admin) { create(:user, :admin)}
+ let_it_be(:admin) { create(:user, :admin) }
let_it_be(:banned_user) { create(:user, :banned) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
diff --git a/spec/graphql/types/namespace_type_spec.rb b/spec/graphql/types/namespace_type_spec.rb
index 3b7f7e65e4b..168a6ba4eaa 100644
--- a/spec/graphql/types/namespace_type_spec.rb
+++ b/spec/graphql/types/namespace_type_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe GitlabSchema.types['Namespace'] do
expected_fields = %w[
id name path full_name full_path description description_html visibility
lfs_enabled request_access_enabled projects root_storage_statistics shared_runners_setting
+ timelog_categories
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/notes/note_type_spec.rb b/spec/graphql/types/notes/note_type_spec.rb
index 03ff7828cf5..cbf7f086dbe 100644
--- a/spec/graphql/types/notes/note_type_spec.rb
+++ b/spec/graphql/types/notes/note_type_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe GitlabSchema.types['Note'] do
body
body_html
confidential
+ internal
created_at
discussion
id
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index ed93d31da0f..5ff7653ce39 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -37,7 +37,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
- recent_issue_boards ci_config_path_or_default ci_variables
+ timelog_categories fork_targets
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -195,8 +195,8 @@ RSpec.describe GitlabSchema.types['Project'] do
expect(secure_analyzers['type']).to eq('string')
expect(secure_analyzers['field']).to eq('SECURE_ANALYZERS_PREFIX')
expect(secure_analyzers['label']).to eq('Image prefix')
- expect(secure_analyzers['defaultValue']).to eq(secure_analyzers_prefix)
- expect(secure_analyzers['value']).to eq(secure_analyzers_prefix)
+ expect(secure_analyzers['defaultValue']).to eq('$CI_TEMPLATE_REGISTRY_HOST/security-products')
+ expect(secure_analyzers['value']).to eq('$CI_TEMPLATE_REGISTRY_HOST/security-products')
expect(secure_analyzers['size']).to eq('LARGE')
expect(secure_analyzers['options']).to be_nil
end
diff --git a/spec/graphql/types/projects/service_type_enum_spec.rb b/spec/graphql/types/projects/service_type_enum_spec.rb
index ead69e60f6c..f7256910bb0 100644
--- a/spec/graphql/types/projects/service_type_enum_spec.rb
+++ b/spec/graphql/types/projects/service_type_enum_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe GitlabSchema.types['ServiceType'] do
PIPELINES_EMAIL_SERVICE
PIVOTALTRACKER_SERVICE
PROMETHEUS_SERVICE
+ PUMBLE_SERVICE
PUSHOVER_SERVICE
REDMINE_SERVICE
SHIMO_SERVICE
diff --git a/spec/graphql/types/subscription_type_spec.rb b/spec/graphql/types/subscription_type_spec.rb
index 1a2629ed422..9b043fa52cf 100644
--- a/spec/graphql/types/subscription_type_spec.rb
+++ b/spec/graphql/types/subscription_type_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe GitlabSchema.types['Subscription'] do
issue_crm_contacts_updated
issuable_title_updated
issuable_labels_updated
+ issuable_dates_updated
]
expect(described_class).to have_graphql_fields(*expected_fields).only
diff --git a/spec/graphql/types/time_tracking/timelog_category_type_spec.rb b/spec/graphql/types/time_tracking/timelog_category_type_spec.rb
new file mode 100644
index 00000000000..a14069e8b58
--- /dev/null
+++ b/spec/graphql/types/time_tracking/timelog_category_type_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['TimeTrackingTimelogCategory'] do
+ let(:fields) do
+ %w[
+ id
+ name
+ description
+ color
+ billable
+ billing_rate
+ created_at
+ updated_at
+ ]
+ end
+
+ it { expect(described_class.graphql_name).to eq('TimeTrackingTimelogCategory') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+ it { expect(described_class).to require_graphql_authorizations(:read_timelog_category) }
+end
diff --git a/spec/graphql/types/upload_type_spec.rb b/spec/graphql/types/upload_type_spec.rb
new file mode 100644
index 00000000000..2b959fbf105
--- /dev/null
+++ b/spec/graphql/types/upload_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['FileUpload'] do
+ it { expect(described_class).to require_graphql_authorizations(:read_upload) }
+
+ it 'has the expected fields' do
+ expected_fields = %w[id size path]
+
+ expect(described_class).to include_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index fec6a771640..dcf25ff0667 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe GitlabSchema.types['User'] do
end
describe 'name field' do
- let_it_be(:admin) { create(:user, :admin)}
+ let_it_be(:admin) { create(:user, :admin) }
let_it_be(:user) { create(:user) }
let_it_be(:requested_user) { create(:user, name: 'John Smith') }
let_it_be(:requested_project_bot) { create(:user, :project_bot, name: 'Project bot') }
diff --git a/spec/graphql/types/work_item_type_spec.rb b/spec/graphql/types/work_item_type_spec.rb
index 7ed58786b5b..c556424b0b4 100644
--- a/spec/graphql/types/work_item_type_spec.rb
+++ b/spec/graphql/types/work_item_type_spec.rb
@@ -11,16 +11,21 @@ RSpec.describe GitlabSchema.types['WorkItem'] do
it 'has specific fields' do
fields = %i[
+ confidential
description
description_html
id
iid
lock_version
+ project
state title
title_html
userPermissions
widgets
work_item_type
+ created_at
+ updated_at
+ closed_at
]
fields.each do |field_name|
diff --git a/spec/graphql/types/work_items/widget_interface_spec.rb b/spec/graphql/types/work_items/widget_interface_spec.rb
index caf986c961f..b9e8edacf15 100644
--- a/spec/graphql/types/work_items/widget_interface_spec.rb
+++ b/spec/graphql/types/work_items/widget_interface_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Types::WorkItems::WidgetInterface do
WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType
WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType
WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType
+ WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType
end
with_them do
diff --git a/spec/graphql/types/work_items/widgets/assignees_input_type_spec.rb b/spec/graphql/types/work_items/widgets/assignees_input_type_spec.rb
new file mode 100644
index 00000000000..2fcda2a43be
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/assignees_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::WorkItems::Widgets::AssigneesInputType do
+ it { expect(described_class.graphql_name).to eq('WorkItemWidgetAssigneesInput') }
+
+ it { expect(described_class.arguments.keys).to match_array(%w[assigneeIds]) }
+end
diff --git a/spec/graphql/types/work_items/widgets/labels_type_spec.rb b/spec/graphql/types/work_items/widgets/labels_type_spec.rb
new file mode 100644
index 00000000000..028ebe979f3
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/labels_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::LabelsType do
+ it 'exposes the expected fields' do
+ expected_fields = %i[labels allowsScopedLabels type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/start_and_due_date_type_spec.rb b/spec/graphql/types/work_items/widgets/start_and_due_date_type_spec.rb
new file mode 100644
index 00000000000..ddc26d964be
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/start_and_due_date_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::StartAndDueDateType do
+ it 'exposes the expected fields' do
+ expected_fields = %i[due_date start_date type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/start_and_due_date_update_input_type_spec.rb b/spec/graphql/types/work_items/widgets/start_and_due_date_update_input_type_spec.rb
new file mode 100644
index 00000000000..91631093e4e
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/start_and_due_date_update_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::WorkItems::Widgets::StartAndDueDateUpdateInputType do
+ it { expect(described_class.graphql_name).to eq('WorkItemWidgetStartAndDueDateUpdateInput') }
+
+ it { expect(described_class.arguments.keys).to contain_exactly('startDate', 'dueDate') }
+end
diff --git a/spec/helpers/admin/identities_helper_spec.rb b/spec/helpers/admin/identities_helper_spec.rb
new file mode 100644
index 00000000000..9a7fdd3aa69
--- /dev/null
+++ b/spec/helpers/admin/identities_helper_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::IdentitiesHelper do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:identity) { create(:identity, provider: 'ldapmain', extern_uid: 'ldap-uid') }
+
+ describe '#label_for_identity_provider' do
+ it 'shows label for identity provider' do
+ expect(helper.label_for_identity_provider(identity)).to eq 'ldap (ldapmain)'
+ end
+ end
+
+ describe '#provider_id_cell_testid' do
+ it 'shows blank provider id for data-testid' do
+ expect(helper.provider_id_cell_testid(identity)).to eq 'provider_id_blank'
+ end
+ end
+
+ describe '#provider_id' do
+ it 'shows no provider id' do
+ expect(helper.provider_id(identity)).to eq '-'
+ end
+ end
+
+ describe '#saml_group_cell_testid' do
+ it 'shows blank SAML group for data-testid' do
+ expect(helper.saml_group_cell_testid(identity)).to eq 'saml_group_blank'
+ end
+ end
+
+ describe '#saml_group_link' do
+ it 'shows no link to SAML group' do
+ expect(helper.saml_group_link(identity)).to eq '-'
+ end
+ end
+
+ describe '#identity_cells_to_render?' do
+ context 'without identities' do
+ it 'returns false' do
+ expect(helper.identity_cells_to_render?([], user)).to eq false
+ end
+ end
+
+ context 'with identities' do
+ it 'returns true' do
+ expect(helper.identity_cells_to_render?(identity, user)).to eq true
+ end
+ end
+ end
+
+ describe '#scim_identities_collection' do
+ it 'returns empty array' do
+ expect(helper.scim_identities_collection(user)).to eq []
+ end
+ end
+end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 47c31546629..264431b1bb5 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -192,6 +192,14 @@ RSpec.describe ApplicationHelper do
end
end
+ describe '#community_forum' do
+ subject { helper.community_forum }
+
+ it 'returns the url' do
+ is_expected.to eq("https://forum.gitlab.com")
+ end
+ end
+
describe '#support_url' do
context 'when alternate support url is specified' do
let(:alternate_url) { 'http://company.example.com/getting-help' }
diff --git a/spec/helpers/boards_helper_spec.rb b/spec/helpers/boards_helper_spec.rb
index 8d5dc3fb4be..ccc150c397a 100644
--- a/spec/helpers/boards_helper_spec.rb
+++ b/spec/helpers/boards_helper_spec.rb
@@ -130,6 +130,7 @@ RSpec.describe BoardsHelper do
it 'returns can_admin_list as false by default' do
expect(helper.board_data[:can_admin_list]).to eq('false')
end
+
it 'returns can_admin_list as true when user can admin the board lists' do
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, project).and_return(true)
@@ -141,6 +142,7 @@ RSpec.describe BoardsHelper do
it 'returns can_admin_board as false by default' do
expect(helper.board_data[:can_admin_board]).to eq('false')
end
+
it 'returns can_admin_board as true when user can admin the board' do
allow(helper).to receive(:can?).with(user, :admin_issue_board, project).and_return(true)
@@ -178,6 +180,7 @@ RSpec.describe BoardsHelper do
it 'returns can_admin_list as false by default' do
expect(helper.board_data[:can_admin_list]).to eq('false')
end
+
it 'returns can_admin_list as true when user can admin the board lists' do
allow(helper).to receive(:can?).with(user, :admin_issue_board_list, base_group).and_return(true)
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index bc9e47a4ca1..1950d685980 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::PipelineEditorHelper do
+ include CycleAnalyticsHelpers
+
let_it_be(:project) { create(:project) }
describe 'can_view_pipeline_editor?' do
@@ -62,8 +64,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-path" => project.path,
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
- "runner-help-page-path" => help_page_path('ci/runners/index'),
- "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'),
+ "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')
@@ -93,8 +94,7 @@ RSpec.describe Ci::PipelineEditorHelper do
"project-path" => project.path,
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
- "runner-help-page-path" => help_page_path('ci/runners/index'),
- "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'),
+ "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')
diff --git a/spec/helpers/ci/runners_helper_spec.rb b/spec/helpers/ci/runners_helper_spec.rb
index 4d1b1c7682c..3b18572ad64 100644
--- a/spec/helpers/ci/runners_helper_spec.rb
+++ b/spec/helpers/ci/runners_helper_spec.rb
@@ -109,7 +109,7 @@ RSpec.describe Ci::RunnersHelper do
it 'returns group data for top level group' do
result = {
- update_path: "/api/v4/groups/#{parent.id}",
+ group_id: parent.id,
shared_runners_setting: Namespace::SR_ENABLED,
parent_shared_runners_setting: nil
}.merge(runner_constants)
@@ -119,7 +119,7 @@ RSpec.describe Ci::RunnersHelper do
it 'returns group data for child group' do
result = {
- update_path: "/api/v4/groups/#{group.id}",
+ group_id: group.id,
shared_runners_setting: Namespace::SR_DISABLED_AND_UNOVERRIDABLE,
parent_shared_runners_setting: Namespace::SR_ENABLED
}.merge(runner_constants)
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index b5b572e9719..b27954de0d4 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -153,16 +153,24 @@ RSpec.describe CommitsHelper do
end
describe "#conditionally_paginate_diff_files" do
- let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::Commit, diff_files: diff_files) }
- let(:diff_files) { Gitlab::Git::DiffCollection.new(files) }
- let(:page) { nil }
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:diffs_collection) { instance_double(Gitlab::Diff::FileCollection::Commit, diff_files: decorated_diff_files, project: project) }
+ let(:decorated_diff_files) do
+ diffs.map do |diff|
+ Gitlab::Diff::File.new(diff, repository: project.repository)
+ end
+ end
+ let(:diffs) { Gitlab::Git::DiffCollection.new(files) }
let(:files) do
Array.new(85).map do
{ too_large: false, diff: "" }
end
end
+ let(:page) { nil }
+
subject { helper.conditionally_paginate_diff_files(diffs_collection, paginate: paginate, page: page, per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE) }
before do
@@ -203,8 +211,8 @@ RSpec.describe CommitsHelper do
context "pagination is disabled" do
let(:paginate) { false }
- it "returns a standard DiffCollection" do
- expect(subject).to be_a(Gitlab::Git::DiffCollection)
+ it "returns the unpaginated collection" do
+ expect(subject.size).to eq(85)
end
end
end
diff --git a/spec/helpers/form_helper_spec.rb b/spec/helpers/form_helper_spec.rb
index c9c8c6b13b6..4b76c370810 100644
--- a/spec/helpers/form_helper_spec.rb
+++ b/spec/helpers/form_helper_spec.rb
@@ -3,6 +3,82 @@
require 'spec_helper'
RSpec.describe FormHelper do
+ include Devise::Test::ControllerHelpers
+
+ describe '#dropdown_max_select' do
+ context "with the :limit_reviewer_and_assignee_size feature flag on" do
+ it 'correctly returns the max amount of reviewers or assignees to allow' do
+ max = MergeRequest::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS
+
+ expect(helper.dropdown_max_select({}))
+ .to eq(max)
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }))
+ .to eq(5)
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => max + 5 }))
+ .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)
+ end
+
+ it 'correctly returns the max amount of reviewers or assignees to allow' do
+ expect(helper.dropdown_max_select({}))
+ .to eq(nil)
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 5 }))
+ .to eq(5)
+ expect(helper.dropdown_max_select({ 'max-select'.to_sym => 120 }))
+ .to eq(120)
+ end
+ end
+ end
+
+ describe '#reviewers_dropdown_options' do
+ let(:merge_request) { build(:merge_request) }
+
+ context "with the :limit_reviewer_and_assignee_size feature flag on" do
+ context "with multiple reviewers" do
+ it 'correctly returns the max amount of reviewers or assignees to allow' 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)
+ end
+ end
+
+ context "with only 1 reviewer" do
+ it 'correctly returns the max amount of reviewers or assignees to allow' do
+ expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select'])
+ .to eq(1)
+ end
+ 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)
+ end
+
+ context "with multiple reviewers" do
+ it 'correctly returns the max amount of reviewers or assignees to allow' 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(nil)
+ end
+ end
+
+ context "with only 1 reviewer" do
+ it 'correctly returns the max amount of reviewers or assignees to allow' do
+ expect(helper.reviewers_dropdown_options(merge_request)[:data][:'max-select'])
+ .to eq(1)
+ end
+ end
+ end
+ end
+
describe 'form_errors' do
it 'returns nil when model has no errors' do
model = double(errors: [])
@@ -13,10 +89,7 @@ RSpec.describe FormHelper do
it 'renders an appropriately styled alert div' do
model = double(errors: errors_stub('Error 1'))
- expect(helper.form_errors(model, pajamas_alert: false))
- .to include('<div class="alert alert-danger" id="error_explanation">')
-
- expect(helper.form_errors(model, pajamas_alert: true))
+ expect(helper.form_errors(model))
.to include(
'<div class="gl-alert gl-mb-5 gl-alert-danger gl-alert-not-dismissible" id="error_explanation" role="alert">'
)
diff --git a/spec/helpers/gitlab_script_tag_helper_spec.rb b/spec/helpers/gitlab_script_tag_helper_spec.rb
index 35f2c0795be..9d71e25286e 100644
--- a/spec/helpers/gitlab_script_tag_helper_spec.rb
+++ b/spec/helpers/gitlab_script_tag_helper_spec.rb
@@ -14,6 +14,16 @@ RSpec.describe GitlabScriptTagHelper do
expect(helper.javascript_include_tag(script_url).to_s)
.to eq "<script src=\"/javascripts/#{script_url}\" defer=\"defer\" nonce=\"noncevalue\"></script>"
end
+
+ it 'returns a script tag with defer=false and a nonce' do
+ expect(helper.javascript_include_tag(script_url, defer: nil).to_s)
+ .to eq "<script src=\"/javascripts/#{script_url}\" nonce=\"noncevalue\"></script>"
+ end
+
+ it 'returns a script tag with a nonce even nonce is set to nil' do
+ expect(helper.javascript_include_tag(script_url, nonce: nil).to_s)
+ .to eq "<script src=\"/javascripts/#{script_url}\" defer=\"defer\" nonce=\"noncevalue\"></script>"
+ end
end
describe 'inline script tag' do
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index 89c26c21338..0d53225bbcf 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe Groups::GroupMembersHelper do
describe '#group_member_header_subtext' do
it 'contains expected text with group name' do
- expect(helper.group_member_header_subtext(group)).to match("You can invite a new member to .*#{group.name}")
+ expect(helper.group_member_header_subtext(group)).to match("You're viewing members of .*#{group.name}")
end
end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index d00cd8f1d6b..2c1061d2f1b 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe GroupsHelper do
include ApplicationHelper
+ include AvatarsHelper
describe '#group_icon_url' do
it 'returns an url for the avatar' do
@@ -135,6 +136,37 @@ RSpec.describe GroupsHelper do
end
end
+ describe '#group_title_link' do
+ let_it_be(:group) { create(:group, :with_avatar) }
+
+ let(:raw_link) { group_title_link(group, show_avatar: true) }
+ let(:document) { Nokogiri::HTML.parse(raw_link) }
+
+ describe 'link' do
+ subject(:link) { document.css('.group-path').first }
+
+ it 'uses the group name as innerText' do
+ expect(link.inner_text).to eq(group.name)
+ end
+
+ it 'links to the group path' do
+ expect(link.attr('href')).to eq(group_path(group))
+ end
+ end
+
+ describe 'icon' do
+ subject(:icon) { document.css('.avatar-tile').first }
+
+ it 'specifies the group name as the alt text' do
+ expect(icon.attr('alt')).to eq(group.name)
+ end
+
+ it 'uses the group\'s avatar_url' do
+ expect(icon.attr('src')).to eq(group.avatar_url)
+ end
+ end
+ end
+
describe '#share_with_group_lock_help_text' do
context 'traversal queries' do
let_it_be_with_reload(:root_group) { create(:group) }
@@ -420,9 +452,31 @@ RSpec.describe GroupsHelper do
end
end
- describe '#group_name_and_path_app_data' do
- let_it_be(:group) { build(:group, name: 'My awesome group', path: 'my-awesome-group') }
+ describe '#subgroup_creation_data' do
+ let_it_be(:name) { 'parent group' }
+ let_it_be(:group) { build(:group, name: name) }
let_it_be(:subgroup) { build(:group, parent: group) }
+
+ context 'when group has a parent' do
+ it 'returns expected hash' do
+ expect(subgroup_creation_data(subgroup)).to eq({
+ import_existing_group_path: '/groups/new#import-group-pane',
+ parent_group_name: name
+ })
+ end
+ end
+
+ context 'when group does not have a parent' do
+ it 'returns expected hash' do
+ expect(subgroup_creation_data(group)).to eq({
+ import_existing_group_path: '/groups/new#import-group-pane',
+ parent_group_name: nil
+ })
+ end
+ end
+ end
+
+ describe '#group_name_and_path_app_data' do
let_it_be(:root_url) { 'https://gitlab.com/' }
before do
@@ -432,17 +486,10 @@ RSpec.describe GroupsHelper do
context 'when group has a parent' do
it 'returns expected hash' do
- expect(group_name_and_path_app_data(subgroup)).to match(
- { base_path: 'https://gitlab.com/my-awesome-group', mattermost_enabled: 'true' }
- )
- end
- end
-
- context 'when group does not have a parent' do
- it 'returns expected hash' do
- expect(group_name_and_path_app_data(group)).to match(
- { base_path: root_url, mattermost_enabled: 'true' }
- )
+ expect(group_name_and_path_app_data).to match({
+ base_path: 'https://gitlab.com/',
+ mattermost_enabled: 'true'
+ })
end
end
end
@@ -461,7 +508,7 @@ RSpec.describe GroupsHelper do
it 'returns expected hash' do
expect(helper.subgroups_and_projects_list_app_data(group)).to match({
show_schema_markup: 'true',
- new_subgroup_path: including("groups/new?parent_id=#{group.id}"),
+ new_subgroup_path: including("groups/new?parent_id=#{group.id}#create-group-pane"),
new_project_path: including("/projects/new?namespace_id=#{group.id}"),
new_subgroup_illustration: including('illustrations/subgroup-create-new-sm'),
new_project_illustration: including('illustrations/project-create-new-sm'),
diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb
index 768ce5975c1..bd8af384d40 100644
--- a/spec/helpers/issuables_description_templates_helper_spec.rb
+++ b/spec/helpers/issuables_description_templates_helper_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
- include_context 'project issuable templates context'
-
describe '#issuable_templates' do
+ include_context 'project issuable templates context'
+
let_it_be(:inherited_from) { nil }
let_it_be(:user) { create(:user) }
let_it_be(:parent_group, reload: true) { create(:group) }
@@ -44,7 +44,7 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
end
end
- describe '#selected_template' do
+ describe '#available_service_desk_templates_for' do
let_it_be(:project) { build(:project) }
before do
@@ -72,46 +72,103 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
].to_json
expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
+ end
- context 'when no issuable_template parameter or default template is present' do
- it 'does not select a template' do
- expect(helper.selected_template(project)).to be(nil)
- end
+ context 'when there are no templates in the project' do
+ let(:templates) { {} }
+
+ it 'returns empty array' do
+ value = [].to_json
+ expect(helper.available_service_desk_templates_for(@project)).to eq(value)
end
+ end
+ end
- context 'when an issuable_template parameter has been provided' do
- before do
- allow(helper).to receive(:params).and_return({ issuable_template: 'another_issue_template' })
- end
+ describe '#selected_template_name' do
+ let(:template_names) { %w(another_issue_template custom_issue_template) }
- it 'selects the issuable template' do
- expect(helper.selected_template(project)).to eq('another_issue_template')
- end
+ context 'when no issuable_template parameter is provided' do
+ it 'does not select a template' do
+ expect(helper.selected_template_name(template_names)).to be_nil
end
+ end
- context 'when there is a default template' do
- let(:templates) do
- {
- "" => [
- { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
- { name: "default", id: "default", project_id: project.id }
- ]
- }
+ context 'when an issuable_template parameter has been provided' do
+ before do
+ allow(helper).to receive(:params).and_return({ issuable_template: template_param_value })
+ end
+
+ context 'when param matches existing templates' do
+ let(:template_param_value) { 'another_issue_template' }
+
+ it 'returns the matching issuable template' do
+ expect(helper.selected_template_name(template_names)).to eq('another_issue_template')
end
+ end
- it 'selects the default template' do
- expect(helper.selected_template(project)).to eq('default')
+ context 'when param does not match any templates' do
+ let(:template_param_value) { 'non_matching_issue_template' }
+
+ it 'returns nil' do
+ expect(helper.selected_template_name(template_names)).to be_nil
end
end
end
+ end
- context 'when there are not templates in the project' do
- let(:templates) { {} }
+ describe '#default_template_name' do
+ context 'when a default template is available' do
+ let(:template_names) { %w(another_issue_template deFault) }
- it 'returns empty array' do
- value = [].to_json
- expect(helper.available_service_desk_templates_for(@project)).to eq(value)
+ it 'returns the default template' do
+ issue = build(:issue)
+
+ expect(helper.default_template_name(template_names, issue)).to be('deFault')
+ end
+
+ it 'returns nil when issuable has a description set' do
+ issue = build(:issue, description: 'from template in project settings')
+
+ expect(helper.default_template_name(template_names, issue)).to be_nil
+ end
+
+ it 'returns nil when issuable is persisted' do
+ issue = create(:issue)
+
+ expect(helper.default_template_name(template_names, issue)).to be_nil
+ end
+ end
+
+ context 'when there is no default template' do
+ let(:template_names) { %w(another_issue_template) }
+
+ it 'returns nil' do
+ expect(helper.default_template_name(template_names, build(:issue))).to be_nil
end
end
end
+
+ describe '#template_names' do
+ let(:project) { build(:project) }
+ let(:templates) do
+ {
+ "Project templates" => [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id },
+ { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
+ ],
+ "Group templates" => [
+ { name: "another_issue_template", id: "another_issue_template", project_id: project.id }
+ ]
+ }
+ end
+
+ before do
+ allow(helper).to receive(:ref_project).and_return(project)
+ allow(helper).to receive(:issuable_templates).and_return(templates)
+ end
+
+ it 'returns unique list of template names' do
+ expect(helper.template_names(build(:issue))).to contain_exactly('another_issue_template', 'custom_issue_template')
+ end
+ end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 73527bea14e..069465c2fec 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -98,11 +98,55 @@ RSpec.describe IssuablesHelper do
end
end
- describe '#issuable_meta' do
+ describe '#issuable_meta', time_travel_to: '2022-08-05 00:00:00 +0000' do
let(:user) { create(:user) }
let_it_be(:project) { create(:project) }
+ describe 'Issuable created status text' do
+ subject { helper.issuable_meta(issuable, project) }
+
+ context 'when issuable is a work item and flag is off' do
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ stub_feature_flags(work_items: false)
+ end
+
+ where(:issuable_type, :text) do
+ :issue | 'Issue created Aug 05, 2022 by'
+ :incident | 'Incident created Aug 05, 2022 by'
+ end
+
+ let(:issuable) { build_stubbed(:work_item, issuable_type, created_at: Date.current) }
+
+ with_them do
+ it { is_expected.to have_content(text) }
+ end
+ end
+
+ context 'when issuable is a work item and flag is on' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :text) do
+ :issue | 'Issue created Aug 05, 2022 by'
+ :incident | 'Incident created Aug 05, 2022 by'
+ end
+
+ let(:issuable) { build_stubbed(:work_item, issuable_type, created_at: Date.current) }
+
+ with_them do
+ it { is_expected.to have_content(text) }
+ end
+ end
+
+ context 'when issuable is not a work item' do
+ let(:issuable) { build_stubbed(:merge_request, created_at: Date.current) }
+
+ it { is_expected.to have_content('Created Aug 05, 2022') }
+ end
+ end
+
describe 'author status' do
let(:issuable) { build(:merge_request, source_project: project, author: user, created_at: '2020-01-30') }
@@ -299,7 +343,7 @@ RSpec.describe IssuablesHelper do
initialTitleText: issue.title,
initialDescriptionHtml: '<p dir="auto">issue text</p>',
initialDescriptionText: 'issue text',
- initialTaskStatus: '0 of 0 tasks completed',
+ initialTaskStatus: '0 of 0 checklist items completed',
issueType: 'issue',
iid: issue.iid.to_s,
isHidden: false
diff --git a/spec/helpers/members_helper_spec.rb b/spec/helpers/members_helper_spec.rb
index e94eb63fc2c..4a3a623ce77 100644
--- a/spec/helpers/members_helper_spec.rb
+++ b/spec/helpers/members_helper_spec.rb
@@ -74,4 +74,37 @@ RSpec.describe MembersHelper do
expect(localized_tasks_to_be_done_choices).to include(*MemberTask::TASKS.keys)
end
end
+
+ describe '#member_request_access_link' do
+ let(:project) { create(:project) }
+ let(:group) { create(:group) }
+ let(:project_member) { create(:project_member, :reporter, project: project) }
+ let(:group_member) { create(:group_member, :reporter, group: group) }
+
+ it 'returns request link for project members' do
+ user = project_member.user
+ source = project_member.source
+ link = member_request_access_link(project_member)
+
+ user_link = link_to user.name, user, class: :highlight
+ access_level = content_tag :span, project_member.human_access, class: :highlight
+ source_link = link_to source.human_name, polymorphic_url([project_member.source, :members]), class: :highlight
+ source_type = source.model_name.singular
+
+ expect(link).to eq "#{user_link} requested #{access_level} access to the #{source_link} #{source_type}."
+ end
+
+ it 'returns the request link for group members' do
+ user = group_member.user
+ source = group_member.source
+ link = member_request_access_link(group_member)
+
+ user_link = link_to user.name, user, class: :highlight
+ access_level = content_tag :span, group_member.human_access, class: :highlight
+ source_link = link_to source.human_name, polymorphic_url([group_member.source, :members]), class: :highlight
+ source_type = source.model_name.singular
+
+ expect(link).to eq "#{user_link} requested #{access_level} access to the #{source_link} #{source_type}."
+ end
+ end
end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 97ad55d9df9..fb23b5c1dc8 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -27,6 +27,38 @@ RSpec.describe MergeRequestsHelper do
end
end
+ describe '#merge_path_description' do
+ let(:project) { create(:project) }
+ let(:forked_project) { fork_project(project) }
+ let(:merge_request_forked) { create(:merge_request, source_project: forked_project, target_project: project) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ where(:case_name, :mr, :with_arrow, :result) do
+ [
+ ['forked with arrow', ref(:merge_request_forked), true, lazy do
+ "Project:Branches: #{
+ mr.source_project_path}:#{mr.source_branch} → #{
+ mr.target_project.full_path}:#{mr.target_branch}"
+ end],
+ ['forked default', ref(:merge_request_forked), false, lazy do
+ "Project:Branches: #{
+ mr.source_project_path}:#{mr.source_branch} to #{
+ mr.target_project.full_path}:#{mr.target_branch}"
+ end],
+ ['with arrow', ref(:merge_request), true, lazy { "Branches: #{mr.source_branch} → #{mr.target_branch}" }],
+ ['default', ref(:merge_request), false, lazy { "Branches: #{mr.source_branch} to #{mr.target_branch}" }]
+ ]
+ end
+
+ with_them do
+ subject { merge_path_description(mr, with_arrow: with_arrow) }
+
+ it {
+ is_expected.to eq(result)
+ }
+ end
+ end
+
describe '#tab_link_for' do
let(:merge_request) { create(:merge_request, :simple) }
let(:options) { {} }
@@ -46,8 +78,7 @@ RSpec.describe MergeRequestsHelper do
let(:user) do
double(
assigned_open_merge_requests_count: 1,
- review_requested_open_merge_requests_count: 2,
- attention_requested_open_merge_requests_count: 3
+ review_requested_open_merge_requests_count: 2
)
end
@@ -57,33 +88,12 @@ RSpec.describe MergeRequestsHelper do
allow(helper).to receive(:current_user).and_return(user)
end
- describe 'mr_attention_requests disabled' do
- before do
- allow(user).to receive(:mr_attention_requests_enabled?).and_return(false)
- end
-
- it "returns assigned, review requested and total merge request counts" do
- expect(subject).to eq(
- assigned: user.assigned_open_merge_requests_count,
- review_requested: user.review_requested_open_merge_requests_count,
- total: user.assigned_open_merge_requests_count + user.review_requested_open_merge_requests_count
- )
- end
- end
-
- describe 'mr_attention_requests enabled' do
- before do
- allow(user).to receive(:mr_attention_requests_enabled?).and_return(true)
- end
-
- it "returns assigned, review requested, attention requests and total merge request counts" do
- expect(subject).to eq(
- assigned: user.assigned_open_merge_requests_count,
- review_requested: user.review_requested_open_merge_requests_count,
- attention_requested_count: user.attention_requested_open_merge_requests_count,
- total: user.attention_requested_open_merge_requests_count
- )
- end
+ it "returns assigned, review requested and total merge request counts" do
+ expect(subject).to eq(
+ assigned: user.assigned_open_merge_requests_count,
+ review_requested: user.review_requested_open_merge_requests_count,
+ total: user.assigned_open_merge_requests_count + user.review_requested_open_merge_requests_count
+ )
end
end
@@ -134,6 +144,7 @@ RSpec.describe MergeRequestsHelper do
it 'returns reviewer label with no names' do
expect(helper.reviewers_label(merge_request)).to eq("Reviewers: ")
end
+
it 'returns reviewer label only with include_value: false' do
expect(helper.reviewers_label(merge_request, include_value: false)).to eq("Reviewers")
end
diff --git a/spec/helpers/namespaces_helper_spec.rb b/spec/helpers/namespaces_helper_spec.rb
index 39f0e1c15f5..f7500709d0e 100644
--- a/spec/helpers/namespaces_helper_spec.rb
+++ b/spec/helpers/namespaces_helper_spec.rb
@@ -45,39 +45,6 @@ RSpec.describe NamespacesHelper do
user_group.add_owner(user)
end
- describe '#namespaces_as_json' do
- let(:result) { helper.namespaces_as_json(user) }
-
- before do
- allow(helper).to receive(:current_user).and_return(user)
- end
-
- it 'returns the user\'s groups' do
- json_data = Gitlab::Json.parse(result)
-
- expect(result).to include('group')
- expect(json_data['group']).to include(
- "id" => user_group.id,
- "name" => user_group.name,
- "display_path" => user_group.full_path,
- "human_name" => user_group.human_name
- )
- end
-
- it 'returns the user\'s namespace' do
- user_namespace = user.namespace
- json_data = Gitlab::Json.parse(result)
-
- expect(result).to include('user')
- expect(json_data['user']).to include(
- "id" => user_namespace.id,
- "name" => user_namespace.name,
- "display_path" => user_namespace.full_path,
- "human_name" => user_namespace.human_name
- )
- end
- end
-
describe '#namespaces_options' do
context 'when admin mode is enabled', :enable_admin_mode do
it 'returns groups without being a member for admin' do
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb
index 2fe237fb996..45664a7e0bd 100644
--- a/spec/helpers/nav/new_dropdown_helper_spec.rb
+++ b/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe Nav::NewDropdownHelper do
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_subgroup',
title: 'New subgroup',
- href: "/groups/new?parent_id=#{group.id}",
+ href: "/groups/new?parent_id=#{group.id}#create-group-pane",
data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
)
)
diff --git a/spec/helpers/nav/top_nav_helper_spec.rb b/spec/helpers/nav/top_nav_helper_spec.rb
index 9d43e057521..e4fa503b5ee 100644
--- a/spec/helpers/nav/top_nav_helper_spec.rb
+++ b/spec/helpers/nav/top_nav_helper_spec.rb
@@ -88,18 +88,6 @@ RSpec.describe Nav::TopNavHelper do
expect(subject[:shortcuts]).to eq(expected_shortcuts)
end
- it 'has expected :secondary' do
- expected_secondary = [
- ::Gitlab::Nav::TopNavMenuItem.build(
- href: '/help',
- id: 'help',
- title: 'Help',
- icon: 'question-o'
- )
- ]
- expect(subject[:secondary]).to eq(expected_secondary)
- end
-
context 'with current nav as project' do
before do
helper.nav('project')
diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb
index 399726263db..63641e65942 100644
--- a/spec/helpers/profiles_helper_spec.rb
+++ b/spec/helpers/profiles_helper_spec.rb
@@ -67,38 +67,6 @@ RSpec.describe ProfilesHelper do
end
end
- describe "#user_status_set_to_busy?" do
- using RSpec::Parameterized::TableSyntax
-
- where(:availability, :result) do
- "busy" | true
- "not_set" | false
- "" | false
- nil | false
- end
-
- with_them do
- it { expect(helper.user_status_set_to_busy?(OpenStruct.new(availability: availability))).to eq(result) }
- end
- end
-
- describe "#show_status_emoji?" do
- using RSpec::Parameterized::TableSyntax
-
- where(:message, :emoji, :result) do
- "Some message" | UserStatus::DEFAULT_EMOJI | true
- "Some message" | "" | true
- "" | "basketball" | true
- "" | "basketball" | true
- "" | UserStatus::DEFAULT_EMOJI | false
- "" | UserStatus::DEFAULT_EMOJI | false
- end
-
- with_them do
- it { expect(helper.show_status_emoji?(OpenStruct.new(message: message, emoji: emoji))).to eq(result) }
- end
- end
-
describe "#ssh_key_expiration_tooltip" do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/helpers/projects/pipeline_helper_spec.rb b/spec/helpers/projects/pipeline_helper_spec.rb
index 2b2dad286c7..8ce4e9f5293 100644
--- a/spec/helpers/projects/pipeline_helper_spec.rb
+++ b/spec/helpers/projects/pipeline_helper_spec.rb
@@ -27,7 +27,13 @@ RSpec.describe Projects::PipelineHelper do
metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, format: :json),
pipeline_iid: pipeline.iid,
pipeline_project_path: project.full_path,
- total_job_count: pipeline.total_size
+ total_job_count: pipeline.total_size,
+ summary_endpoint: summary_project_pipeline_tests_path(project, pipeline, format: :json),
+ suite_endpoint: project_pipeline_test_path(project, pipeline, suite_name: 'suite', format: :json),
+ blob_path: project_blob_path(project, pipeline.sha),
+ has_test_report: pipeline.has_reports?(Ci::JobArtifact.test_reports),
+ empty_state_image_path: match_asset_path('illustrations/empty-state/empty-test-cases-lg.svg'),
+ artifacts_expired_image_path: match_asset_path('illustrations/pipeline.svg')
})
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index b7cc8c217a4..04c066986b7 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -966,7 +966,10 @@ RSpec.describe ProjectsHelper do
operationsAccessLevel: project.project_feature.operations_access_level,
showDefaultAwardEmojis: project.show_default_award_emojis?,
securityAndComplianceAccessLevel: project.security_and_compliance_access_level,
- containerRegistryAccessLevel: project.project_feature.container_registry_access_level
+ containerRegistryAccessLevel: project.project_feature.container_registry_access_level,
+ environmentsAccessLevel: project.project_feature.environments_access_level,
+ featureFlagsAccessLevel: project.project_feature.feature_flags_access_level,
+ releasesAccessLevel: project.project_feature.releases_access_level
)
end
@@ -1313,4 +1316,38 @@ RSpec.describe ProjectsHelper do
end
end
end
+
+ describe '#project_coverage_chart_data_attributes' do
+ let(:ref) { 'ref' }
+ let(:daily_coverage_options) do
+ {
+ base_params: {
+ start_date: Date.current - 90.days,
+ end_date: Date.current,
+ ref_path: project.repository.expand_ref(ref),
+ param_type: 'coverage'
+ },
+ download_path: namespace_project_ci_daily_build_group_report_results_path(
+ namespace_id: project.namespace,
+ project_id: project,
+ format: :csv
+ ),
+ graph_api_path: namespace_project_ci_daily_build_group_report_results_path(
+ namespace_id: project.namespace,
+ project_id: project,
+ format: :json
+ )
+ }
+ end
+
+ it 'returns project data to render coverage chart' do
+ expect(helper.project_coverage_chart_data_attributes(daily_coverage_options, ref)).to include(
+ graph_endpoint: start_with(daily_coverage_options.fetch(:graph_api_path)),
+ graph_start_date: daily_coverage_options.dig(:base_params, :start_date).strftime('%b %d'),
+ graph_end_date: daily_coverage_options.dig(:base_params, :end_date).strftime('%b %d'),
+ graph_ref: ref,
+ graph_csv_path: start_with(daily_coverage_options.fetch(:download_path))
+ )
+ end
+ end
end
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 1ead1fc9b8b..513e2865ee3 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -74,19 +74,21 @@ RSpec.describe SearchHelper do
expect(result.keys).to match_array(%i[category id value label url avatar_url])
end
- it 'includes the users recently viewed issues', :aggregate_failures do
+ it 'includes the users recently viewed issues and project with correct order', :aggregate_failures do
recent_issues = instance_double(::Gitlab::Search::RecentIssues)
expect(::Gitlab::Search::RecentIssues).to receive(:new).with(user: user).and_return(recent_issues)
project1 = create(:project, :with_avatar, namespace: user.namespace)
project2 = create(:project, namespace: user.namespace)
issue1 = create(:issue, title: 'issue 1', project: project1)
issue2 = create(:issue, title: 'issue 2', project: project2)
+ project = create(:project, title: 'the search term')
+ project.add_developer(user)
expect(recent_issues).to receive(:search).with('the search term').and_return(Issue.id_in_ordered([issue1.id, issue2.id]))
results = search_autocomplete_opts("the search term")
- expect(results.count).to eq(2)
+ expect(results.count).to eq(3)
expect(results[0]).to include({
category: 'Recent issues',
@@ -103,6 +105,13 @@ RSpec.describe SearchHelper do
url: Gitlab::Routing.url_helpers.project_issue_path(issue2.project, issue2),
avatar_url: '' # This project didn't have an avatar so set this to ''
})
+
+ expect(results[2]).to include({
+ category: 'Projects',
+ id: project.id,
+ label: project.full_name,
+ url: Gitlab::Routing.url_helpers.project_path(project)
+ })
end
it 'includes the users recently viewed issues with the exact same name', :aggregate_failures do
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index 4b46bf169e0..6c3556c874b 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -57,8 +57,8 @@ RSpec.describe StorageHelper do
let_it_be(:paid_group) { create(:group) }
before do
- allow(helper).to receive(:can?).with(current_user, :maintain_namespace, free_group).and_return(true)
- allow(helper).to receive(:can?).with(current_user, :maintain_namespace, paid_group).and_return(true)
+ allow(helper).to receive(:can?).with(current_user, :maintainer_access, free_group).and_return(true)
+ allow(helper).to receive(:can?).with(current_user, :maintainer_access, paid_group).and_return(true)
allow(helper).to receive(:current_user) { current_user }
allow(paid_group).to receive(:paid?).and_return(true)
@@ -84,7 +84,7 @@ RSpec.describe StorageHelper do
end
it 'returns nil when current_user do not have access usage quotas page' do
- allow(helper).to receive(:can?).with(current_user, :maintain_namespace, free_group).and_return(false)
+ allow(helper).to receive(:can?).with(current_user, :maintainer_access, free_group).and_return(false)
expect(helper.storage_enforcement_banner_info(free_group)).to be(nil)
end
@@ -97,12 +97,16 @@ RSpec.describe StorageHelper do
context 'when current_user can access the usage quotas page' do
it 'returns a hash' do
+ used_storage = helper.storage_counter(free_group.root_storage_statistics&.storage_size || 0)
+
expect(helper.storage_enforcement_banner_info(free_group)).to eql({
- text: "From #{storage_enforcement_date} storage limits will apply to this namespace. You are currently using 0 Bytes of namespace storage. View and manage your usage from <strong>Group settings &gt; Usage quotas</strong>.",
+ text_paragraph_1: "Effective #{storage_enforcement_date}, namespace storage limits will apply to the <strong>#{free_group.name}</strong> namespace. View the <a href=\"/help/user/usage_quotas#namespace-storage-limit-enforcement-schedule\" >rollout schedule for this change</a>.",
+ text_paragraph_2: "The namespace is currently using <strong>#{used_storage}</strong> of namespace storage. Group owners can view namespace storage usage and purchase more from <strong>Group settings &gt; Usage quotas</strong>. <a href=\"/help/user/usage_quotas#manage-your-storage-usage\" >Learn more.</a>",
+ text_paragraph_3: "See our <a href=\"https://about.gitlab.com/pricing/faq-efficient-free-tier/#storage-limits-on-gitlab-saas-free-tier\" >FAQ</a> for more information.",
variant: 'warning',
+ namespace_id: free_group.id,
callouts_feature_name: 'storage_enforcement_banner_second_enforcement_threshold',
- callouts_path: '/-/users/group_callouts',
- learn_more_link: '<a rel="noopener noreferrer" target="_blank" href="/help//">Learn more.</a>'
+ callouts_path: '/-/users/group_callouts'
})
end
@@ -112,7 +116,7 @@ RSpec.describe StorageHelper do
end
it 'returns a hash with the correct storage size text' do
- expect(helper.storage_enforcement_banner_info(free_group)[:text]).to eql("From #{storage_enforcement_date} storage limits will apply to this namespace. You are currently using 100 KB of namespace storage. View and manage your usage from <strong>Group settings &gt; Usage quotas</strong>.")
+ expect(helper.storage_enforcement_banner_info(free_group)[:text_paragraph_2]).to eql("The namespace is currently using <strong>100 KB</strong> of namespace storage. Group owners can view namespace storage usage and purchase more from <strong>Group settings &gt; Usage quotas</strong>. <a href=\"/help/user/usage_quotas#manage-your-storage-usage\" >Learn more.</a>")
end
end
@@ -120,11 +124,12 @@ RSpec.describe StorageHelper do
let_it_be(:sub_group) { build(:group) }
before do
+ allow(helper).to receive(:can?).with(current_user, :maintainer_access, sub_group).and_return(true)
allow(sub_group).to receive(:root_ancestor).and_return(free_group)
end
it 'returns the banner hash' do
- expect(helper.storage_enforcement_banner_info(sub_group).keys).to match_array(%i(text variant callouts_feature_name callouts_path learn_more_link))
+ expect(helper.storage_enforcement_banner_info(sub_group).keys).to match_array(%i(text_paragraph_1 text_paragraph_2 text_paragraph_3 variant namespace_id callouts_feature_name callouts_path))
end
end
end
@@ -136,7 +141,8 @@ RSpec.describe StorageHelper do
end
it 'returns the enforcement info' do
- expect(helper.storage_enforcement_banner_info(free_group)[:text]).to include("From #{Date.current} storage limits will apply to this namespace.")
+ puts helper.storage_enforcement_banner_info(free_group)[:text_paragraph_1]
+ expect(helper.storage_enforcement_banner_info(free_group)[:text_paragraph_1]).to include("Effective #{Date.current}, namespace storage limits will apply")
end
end
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 88030299574..78a15f52be5 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -421,6 +421,25 @@ RSpec.describe UsersHelper do
end
end
+ describe '#user_email_help_text' do
+ subject(:user_email_help_text) { helper.user_email_help_text(user) }
+
+ context 'when `user.unconfirmed_email` is not set' do
+ it 'contains avatar detection text' do
+ expect(user_email_help_text).to include _('We also use email for avatar detection if no avatar is uploaded.')
+ end
+ end
+
+ context 'when `user.unconfirmed_email` is set' do
+ let(:user) { create(:user, :unconfirmed, unconfirmed_email: 'foo@bar.com') }
+
+ it 'contains resend confirmation e-mail text' do
+ expect(user_email_help_text).to include _('Resend confirmation e-mail')
+ expect(user_email_help_text).to include _('Please click the link in the confirmation email before continuing. It was sent to ')
+ end
+ end
+ end
+
describe '#admin_user_actions_data_attributes' do
subject(:data) { helper.admin_user_actions_data_attributes(user) }
diff --git a/spec/initializers/00_deprecations_spec.rb b/spec/initializers/00_deprecations_spec.rb
new file mode 100644
index 00000000000..e52e64415af
--- /dev/null
+++ b/spec/initializers/00_deprecations_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe '00_deprecations' do
+ where(:warning) do
+ [
+ "ActiveModel::Errors#keys is deprecated and will be removed in Rails 6.2",
+ "Rendering actions with '.' in the name is deprecated:",
+ "default_hash is deprecated and will be removed from Rails 6.2"
+ ]
+ end
+
+ with_them do
+ specify do
+ expect { ActiveSupport::Deprecation.warn(warning) }
+ .to raise_error(ActiveSupport::DeprecationException)
+ end
+ end
+end
diff --git a/spec/initializers/0_log_deprecations_spec.rb b/spec/initializers/0_log_deprecations_spec.rb
index f5065126eaf..d34be32f7d0 100644
--- a/spec/initializers/0_log_deprecations_spec.rb
+++ b/spec/initializers/0_log_deprecations_spec.rb
@@ -11,6 +11,15 @@ RSpec.describe '0_log_deprecations' do
load Rails.root.join('config/initializers/0_log_deprecations.rb')
end
+ def with_deprecation_behavior
+ behavior = ActiveSupport::Deprecation.behavior
+ ActiveSupport::Deprecation.behavior = deprecation_behavior
+ yield
+ ensure
+ ActiveSupport::Deprecation.behavior = behavior
+ end
+
+ let(:deprecation_behavior) { :stderr }
let(:env_var) { '1' }
before do
@@ -24,19 +33,39 @@ RSpec.describe '0_log_deprecations' do
end
around do |example|
- # reset state changed by initializer
- Warning.clear(&example)
+ with_deprecation_behavior do
+ # reset state changed by initializer
+ Warning.clear(&example)
+ end
end
describe 'Ruby deprecations' do
- context 'when catching deprecations through Kernel#warn' do
- it 'also logs them to deprecation logger' do
+ shared_examples 'deprecation logger' do
+ it 'logs them to deprecation logger once and to stderr' do
expect(Gitlab::DeprecationJsonLogger).to receive(:info).with(
message: 'ABC gem is deprecated',
source: 'ruby'
)
- expect { warn('ABC gem is deprecated') }.to output.to_stderr
+ expect { subject }.to output.to_stderr
+ end
+ end
+
+ context 'when catching deprecations through Kernel#warn' do
+ subject { warn('ABC gem is deprecated') }
+
+ include_examples 'deprecation logger'
+
+ context 'with non-notify deprecation behavior' do
+ let(:deprecation_behavior) { :silence }
+
+ include_examples 'deprecation logger'
+ end
+
+ context 'with notify deprecation behavior' do
+ let(:deprecation_behavior) { :notify }
+
+ include_examples 'deprecation logger'
end
end
@@ -60,13 +89,40 @@ RSpec.describe '0_log_deprecations' do
end
describe 'Rails deprecations' do
- it 'logs them to deprecation logger' do
- expect(Gitlab::DeprecationJsonLogger).to receive(:info).with(
- message: match(/^DEPRECATION WARNING: ABC will be removed/),
- source: 'rails'
- )
+ subject { ActiveSupport::Deprecation.warn('ABC will be removed') }
+
+ shared_examples 'deprecation logger' do
+ it 'logs them to deprecation logger once' do
+ expect(Gitlab::DeprecationJsonLogger).to receive(:info).with(
+ message: match(/^DEPRECATION WARNING: ABC will be removed/),
+ source: 'rails'
+ )
+
+ subject
+ end
+ end
+
+ context 'with non-notify deprecation behavior' do
+ let(:deprecation_behavior) { :silence }
+
+ include_examples 'deprecation logger'
+ end
+
+ context 'with notify deprecation behavior' do
+ let(:deprecation_behavior) { :notify }
+
+ include_examples 'deprecation logger'
+ end
+
+ context 'when deprecations were silenced' do
+ around do |example|
+ silenced = ActiveSupport::Deprecation.silenced
+ ActiveSupport::Deprecation.silenced = true
+ example.run
+ ActiveSupport::Deprecation.silenced = silenced
+ end
- expect { ActiveSupport::Deprecation.warn('ABC will be removed') }.to output.to_stderr
+ include_examples 'deprecation logger'
end
context 'when disabled via environment' do
diff --git a/spec/initializers/diagnostic_reports_spec.rb b/spec/initializers/diagnostic_reports_spec.rb
new file mode 100644
index 00000000000..70574194916
--- /dev/null
+++ b/spec/initializers/diagnostic_reports_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'diagnostic reports' do
+ subject(:load_initializer) do
+ load Rails.root.join('config/initializers/diagnostic_reports.rb')
+ end
+
+ shared_examples 'does not modify worker startup hooks' do
+ it do
+ expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
+ expect(Gitlab::Memory::ReportsDaemon).not_to receive(:instance)
+
+ load_initializer
+ end
+ end
+
+ context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is set to true' do
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_ENABLED', true)
+ end
+
+ context 'when run in application context' do
+ before do
+ allow(::Gitlab::Runtime).to receive(:application?).and_return(true)
+ end
+
+ it 'modifies worker startup hooks' do
+ report_daemon = instance_double(Gitlab::Memory::ReportsDaemon)
+
+ 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)
+
+ load_initializer
+ end
+ end
+
+ context 'when run in non-application context, such as rails console or tests' do
+ before do
+ allow(::Gitlab::Runtime).to receive(:application?).and_return(false)
+ end
+
+ include_examples 'does not modify worker startup hooks'
+ end
+ end
+
+ context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is not set' do
+ before do
+ allow(::Gitlab::Runtime).to receive(:application?).and_return(true)
+ end
+
+ include_examples 'does not modify worker startup hooks'
+ end
+
+ 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)
+ end
+
+ include_examples 'does not modify worker startup hooks'
+ end
+end
diff --git a/spec/initializers/global_id_spec.rb b/spec/initializers/global_id_spec.rb
index 4deb1833999..edca4533b3a 100644
--- a/spec/initializers/global_id_spec.rb
+++ b/spec/initializers/global_id_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'global_id' do
it 'patches GlobalID to find aliased models when a deprecation exists' do
allow(Gitlab::GlobalId::Deprecations).to receive(:deprecation_for).and_call_original
- allow(Gitlab::GlobalId::Deprecations).to receive(:deprecation_for).with('Issue').and_return(double(new_model_name: 'Project'))
+ allow(Gitlab::GlobalId::Deprecations).to receive(:deprecation_for).with('Issue').and_return(double(new_name: 'Project'))
project = create(:project)
gid_string = Gitlab::GlobalId.build(model_name: Issue.name, id: project.id).to_s
diff --git a/spec/initializers/memory_watchdog_spec.rb b/spec/initializers/memory_watchdog_spec.rb
new file mode 100644
index 00000000000..56f995b5cd3
--- /dev/null
+++ b/spec/initializers/memory_watchdog_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe 'memory watchdog' do
+ subject(:run_initializer) do
+ load Rails.root.join('config/initializers/memory_watchdog.rb')
+ end
+
+ context 'when GITLAB_MEMORY_WATCHDOG_ENABLED is truthy' do
+ let(:env_switch) { 'true' }
+
+ before do
+ stub_env('GITLAB_MEMORY_WATCHDOG_ENABLED', env_switch)
+ end
+
+ context 'when runtime is an application' do
+ let(:watchdog) { instance_double(Gitlab::Memory::Watchdog) }
+ let(:background_task) { instance_double(Gitlab::BackgroundTask) }
+
+ before do
+ allow(Gitlab::Runtime).to receive(:application?).and_return(true)
+ end
+
+ it 'registers a life-cycle hook' do
+ expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start)
+
+ 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
+
+ run_initializer
+ end
+ end
+
+ # In tests, the Puma constant does not exist so we cannot use a verified double.
+ # rubocop: disable RSpec/VerifiedDoubles
+ context 'when puma' do
+ let(:puma) do
+ Class.new do
+ def self.cli_config
+ Struct.new(:options).new
+ end
+ end
+ end
+
+ before do
+ stub_const('Puma', puma)
+ stub_const('Puma::Cluster::WorkerHandle', double.as_null_object)
+
+ allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
+ end
+
+ it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::PumaHandler
+ end
+ # rubocop: enable RSpec/VerifiedDoubles
+
+ context 'when sidekiq' do
+ before do
+ allow(Gitlab::Runtime).to receive(:sidekiq?).and_return(true)
+ end
+
+ it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::TermProcessHandler
+ end
+
+ context 'when other runtime' do
+ it_behaves_like 'starts watchdog with handler', Gitlab::Memory::Watchdog::NullHandler
+ end
+ end
+
+ context 'when runtime is unsupported' do
+ it 'does not register life-cycle hook' do
+ expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
+
+ run_initializer
+ end
+ end
+ end
+
+ context 'when GITLAB_MEMORY_WATCHDOG_ENABLED is false' do
+ let(:env_switch) { 'false' }
+
+ before do
+ stub_env('GITLAB_MEMORY_WATCHDOG_ENABLED', env_switch)
+ # To rule out we return early due to this being false.
+ allow(Gitlab::Runtime).to receive(:application?).and_return(true)
+ end
+
+ it 'does not register life-cycle hook' do
+ expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
+
+ run_initializer
+ end
+ end
+
+ context 'when GITLAB_MEMORY_WATCHDOG_ENABLED is not set' do
+ before do
+ # To rule out we return early due to this being false.
+ allow(Gitlab::Runtime).to receive(:application?).and_return(true)
+ end
+
+ it 'does not register life-cycle hook' do
+ expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
+
+ run_initializer
+ end
+ end
+end
diff --git a/spec/lib/api/ci/helpers/runner_helpers_spec.rb b/spec/lib/api/ci/helpers/runner_helpers_spec.rb
index c6cdc1732f5..b254c419cbc 100644
--- a/spec/lib/api/ci/helpers/runner_helpers_spec.rb
+++ b/spec/lib/api/ci/helpers/runner_helpers_spec.rb
@@ -71,8 +71,8 @@ RSpec.describe API::Ci::Helpers::Runner do
end
end
- describe '#log_artifact_size' do
- subject { runner_helper.log_artifact_size(artifact) }
+ describe '#log_artifacts_filesize' do
+ subject { runner_helper.log_artifacts_filesize(artifact) }
let(:runner_params) { {} }
let(:artifact) { create(:ci_job_artifact, size: 42) }
diff --git a/spec/lib/api/entities/bulk_imports/entity_spec.rb b/spec/lib/api/entities/bulk_imports/entity_spec.rb
index f91ae1fc5a1..4de85862ab9 100644
--- a/spec/lib/api/entities/bulk_imports/entity_spec.rb
+++ b/spec/lib/api/entities/bulk_imports/entity_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe API::Entities::BulkImports::Entity do
:status,
:source_full_path,
:destination_name,
+ :destination_slug,
:destination_namespace,
:parent_id,
:namespace_id,
diff --git a/spec/lib/api/entities/ci/job_request/image_spec.rb b/spec/lib/api/entities/ci/job_request/image_spec.rb
index 3ab14ffc3ae..fca3b5d3fa9 100644
--- a/spec/lib/api/entities/ci/job_request/image_spec.rb
+++ b/spec/lib/api/entities/ci/job_request/image_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe API::Entities::Ci::JobRequest::Image do
- let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }]}
+ let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }] }
let(:image) { double(name: 'image_name', entrypoint: ['foo'], ports: ports, pull_policy: ['if-not-present']) }
let(:entity) { described_class.new(image) }
diff --git a/spec/lib/api/entities/ci/job_request/port_spec.rb b/spec/lib/api/entities/ci/job_request/port_spec.rb
index 8e0d2cabcfc..3f2ca3275c1 100644
--- a/spec/lib/api/entities/ci/job_request/port_spec.rb
+++ b/spec/lib/api/entities/ci/job_request/port_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ::API::Entities::Ci::JobRequest::Port do
- let(:port) { double(number: 80, protocol: 'http', name: 'name')}
+ let(:port) { double(number: 80, protocol: 'http', name: 'name') }
let(:entity) { described_class.new(port) }
subject { entity.as_json }
diff --git a/spec/lib/api/entities/ci/job_request/service_spec.rb b/spec/lib/api/entities/ci/job_request/service_spec.rb
index 47c2c4e04c9..86f2120c321 100644
--- a/spec/lib/api/entities/ci/job_request/service_spec.rb
+++ b/spec/lib/api/entities/ci/job_request/service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe API::Entities::Ci::JobRequest::Service do
- let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }]}
+ let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }] }
let(:service) do
instance_double(
::Gitlab::Ci::Build::Image,
diff --git a/spec/lib/api/entities/project_spec.rb b/spec/lib/api/entities/project_spec.rb
index 6b542278fa6..f4073683919 100644
--- a/spec/lib/api/entities/project_spec.rb
+++ b/spec/lib/api/entities/project_spec.rb
@@ -13,6 +13,19 @@ RSpec.describe ::API::Entities::Project do
subject(:json) { entity.as_json }
+ context 'without project feature' do
+ before do
+ project.project_feature.destroy!
+ project.reload
+ end
+
+ it 'returns a response' do
+ expect(json[:issues_access_level]).to be_nil
+ expect(json[:repository_access_level]).to be_nil
+ expect(json[:merge_requests_access_level]).to be_nil
+ end
+ end
+
describe '.service_desk_address' do
before do
allow(project).to receive(:service_desk_enabled?).and_return(true)
diff --git a/spec/lib/api/helpers/authentication_spec.rb b/spec/lib/api/helpers/authentication_spec.rb
index eea5c10d4f8..ac5886fdadd 100644
--- a/spec/lib/api/helpers/authentication_spec.rb
+++ b/spec/lib/api/helpers/authentication_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe API::Helpers::Authentication do
class << cls
def helpers(*modules, &block)
modules.each { |m| include m }
- include Module.new.tap { |m| m.class_eval(&block) } if block_given?
+ include Module.new.tap { |m| m.class_eval(&block) } if block
end
end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 23c97e2c0a3..cd41d362d03 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -185,7 +185,7 @@ RSpec.describe API::Helpers do
context 'support for IDs and paths as argument' do
let_it_be(:project) { create(:project) }
- let(:user) { project.first_owner}
+ let(:user) { project.first_owner }
before do
allow(helper).to receive(:current_user).and_return(user)
diff --git a/spec/lib/api/support/git_access_actor_spec.rb b/spec/lib/api/support/git_access_actor_spec.rb
index a09cabf4cd7..e1c800d25a7 100644
--- a/spec/lib/api/support/git_access_actor_spec.rb
+++ b/spec/lib/api/support/git_access_actor_spec.rb
@@ -83,6 +83,36 @@ RSpec.describe API::Support::GitAccessActor do
end
end
+ describe '#deploy_key_or_user' do
+ it 'returns a deploy key when the params contains deploy key' do
+ key = create(:deploy_key)
+ params = { key_id: key.id }
+
+ expect(described_class.from_params(params).deploy_key_or_user).to eq(key)
+ end
+
+ it 'returns a user when the params contains personal key' do
+ key = create(:key)
+ params = { key_id: key.id }
+
+ expect(described_class.from_params(params).deploy_key_or_user).to eq(key.user)
+ end
+
+ it 'returns a user when the params contains user id' do
+ user = create(:user)
+ params = { user_id: user.id }
+
+ expect(described_class.from_params(params).deploy_key_or_user).to eq(user)
+ end
+
+ it 'returns a user when the params contains user name' do
+ user = create(:user)
+ params = { username: user.username }
+
+ expect(described_class.from_params(params).deploy_key_or_user).to eq(user)
+ end
+ end
+
describe '#username' do
context 'when initialized with a User' do
let(:user) { build(:user) }
diff --git a/spec/lib/backup/database_spec.rb b/spec/lib/backup/database_spec.rb
index 53db7f0f149..ed5b34b7f8c 100644
--- a/spec/lib/backup/database_spec.rb
+++ b/spec/lib/backup/database_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Backup::Database do
let(:data) { Rails.root.join("spec/fixtures/pages_empty.tar.gz").to_s }
let(:force) { true }
- subject { described_class.new(progress, force: force) }
+ subject { described_class.new(Gitlab::Database::MAIN_DATABASE_NAME.to_sym, progress, force: force) }
before do
allow(subject).to receive(:pg_restore_cmd).and_return(cmd)
@@ -68,7 +68,7 @@ RSpec.describe Backup::Database do
context 'when the restore command prints errors' do
let(:visible_error) { "This is a test error\n" }
- let(:noise) { "Table projects does not exist\nmust be owner of extension pg_trgm\nWARNING: no privileges could be revoked for public\n" }
+ let(:noise) { "must be owner of extension pg_trgm\nWARNING: no privileges could be revoked for public\n" }
let(:cmd) { %W[#{Gem.ruby} -e $stderr.write("#{noise}#{visible_error}")] }
it 'filters out noise from errors and has a post restore warning' do
@@ -105,5 +105,25 @@ RSpec.describe Backup::Database do
expect(output).to include(%("PGUSER"=>"#{config['username']}")) if config['username']
end
end
+
+ context 'when the source file is missing' do
+ let(:main_database) { described_class.new(Gitlab::Database::MAIN_DATABASE_NAME.to_sym, progress, force: force) }
+ let(:ci_database) { described_class.new(Gitlab::Database::CI_DATABASE_NAME.to_sym, progress, force: force) }
+ let(:missing_file) { Rails.root.join("spec/fixtures/missing_file.tar.gz").to_s }
+
+ it 'main database raises an error about missing source file' do
+ expect(Rake::Task['gitlab:db:drop_tables']).not_to receive(:invoke)
+
+ expect do
+ main_database.restore(missing_file)
+ end.to raise_error(Backup::Error, /Source database file does not exist/)
+ end
+
+ it 'ci database tolerates missing source file' do
+ expect(Rake::Task['gitlab:db:drop_tables']).not_to receive(:invoke)
+ skip_if_multiple_databases_not_setup
+ expect { ci_database.restore(missing_file) }.not_to raise_error
+ end
+ end
end
end
diff --git a/spec/lib/backup/gitaly_backup_spec.rb b/spec/lib/backup/gitaly_backup_spec.rb
index 3a9c4dfe3fb..d427e41026e 100644
--- a/spec/lib/backup/gitaly_backup_spec.rb
+++ b/spec/lib/backup/gitaly_backup_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Backup::GitalyBackup do
let(:max_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-parallel', '3', '-layout', 'pointer', '-id', backup_id).and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-layout', 'pointer', '-parallel', '3', '-id', backup_id).and_call_original
subject.start(:create, destination, backup_id: backup_id)
subject.finish!
@@ -84,7 +84,7 @@ RSpec.describe Backup::GitalyBackup do
let(:storage_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-parallel-storage', '3', '-layout', 'pointer', '-id', backup_id).and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-layout', 'pointer', '-parallel-storage', '3', '-id', backup_id).and_call_original
subject.start(:create, destination, backup_id: backup_id)
subject.finish!
@@ -103,36 +103,6 @@ RSpec.describe Backup::GitalyBackup do
expect { subject.start(:create, destination, backup_id: backup_id) }.to raise_error(::Backup::Error, 'gitaly-backup binary not found and gitaly_backup_path is not configured')
end
-
- context 'feature flag incremental_repository_backup disabled' do
- before do
- stub_feature_flags(incremental_repository_backup: false)
- end
-
- it 'creates repository bundles', :aggregate_failures do
- # Add data to the wiki, design repositories, and snippets, so they will be included in the dump.
- create(:wiki_page, container: project)
- create(:design, :with_file, issue: create(:issue, project: project))
- project_snippet = create(:project_snippet, :repository, project: project)
- personal_snippet = create(:personal_snippet, :repository, author: project.first_owner)
-
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything).and_call_original
-
- subject.start(:create, destination, backup_id: backup_id)
- subject.enqueue(project, Gitlab::GlRepository::PROJECT)
- subject.enqueue(project, Gitlab::GlRepository::WIKI)
- subject.enqueue(project, Gitlab::GlRepository::DESIGN)
- subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
- subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
- subject.finish!
-
- expect(File).to exist(File.join(destination, project.disk_path + '.bundle'))
- expect(File).to exist(File.join(destination, project.disk_path + '.wiki.bundle'))
- expect(File).to exist(File.join(destination, project.disk_path + '.design.bundle'))
- expect(File).to exist(File.join(destination, personal_snippet.disk_path + '.bundle'))
- expect(File).to exist(File.join(destination, project_snippet.disk_path + '.bundle'))
- end
- end
end
context 'hashed storage' do
@@ -208,7 +178,7 @@ RSpec.describe Backup::GitalyBackup do
let(:max_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-parallel', '3', '-layout', 'pointer').and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-layout', 'pointer', '-parallel', '3').and_call_original
subject.start(:restore, destination, backup_id: backup_id)
subject.finish!
@@ -219,45 +189,13 @@ RSpec.describe Backup::GitalyBackup do
let(:storage_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-parallel-storage', '3', '-layout', 'pointer').and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-layout', 'pointer', '-parallel-storage', '3').and_call_original
subject.start(:restore, destination, backup_id: backup_id)
subject.finish!
end
end
- context 'feature flag incremental_repository_backup disabled' do
- before do
- stub_feature_flags(incremental_repository_backup: false)
- end
-
- it 'restores from repository bundles', :aggregate_failures do
- copy_bundle_to_backup_path('project_repo.bundle', project.disk_path + '.bundle')
- copy_bundle_to_backup_path('wiki_repo.bundle', project.disk_path + '.wiki.bundle')
- copy_bundle_to_backup_path('design_repo.bundle', project.disk_path + '.design.bundle')
- copy_bundle_to_backup_path('personal_snippet_repo.bundle', personal_snippet.disk_path + '.bundle')
- copy_bundle_to_backup_path('project_snippet_repo.bundle', project_snippet.disk_path + '.bundle')
-
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything).and_call_original
-
- subject.start(:restore, destination, backup_id: backup_id)
- subject.enqueue(project, Gitlab::GlRepository::PROJECT)
- subject.enqueue(project, Gitlab::GlRepository::WIKI)
- subject.enqueue(project, Gitlab::GlRepository::DESIGN)
- subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
- subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
- subject.finish!
-
- collect_commit_shas = -> (repo) { repo.commits('master', limit: 10).map(&:sha) }
-
- expect(collect_commit_shas.call(project.repository)).to match_array(['393a7d860a5a4c3cc736d7eb00604e3472bb95ec'])
- expect(collect_commit_shas.call(project.wiki.repository)).to match_array(['c74b9948d0088d703ee1fafeddd9ed9add2901ea'])
- expect(collect_commit_shas.call(project.design_repository)).to match_array(['c3cd4d7bd73a51a0f22045c3a4c871c435dc959d'])
- expect(collect_commit_shas.call(personal_snippet.repository)).to match_array(['3b3c067a3bc1d1b695b51e2be30c0f8cf698a06e'])
- expect(collect_commit_shas.call(project_snippet.repository)).to match_array(['6e44ba56a4748be361a841e759c20e421a1651a1'])
- end
- end
-
it 'raises when the exit code not zero' do
expect(subject).to receive(:bin_path).and_return(Gitlab::Utils.which('false'))
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index 519d414f643..f85b005f4d1 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -24,7 +24,17 @@ RSpec.describe Backup::Manager do
describe '#run_create_task' do
let(:enabled) { true }
let(:task) { instance_double(Backup::Task) }
- let(:definitions) { { 'my_task' => Backup::Manager::TaskDefinition.new(task: task, enabled: enabled, destination_path: 'my_task.tar.gz', human_name: 'my task') } }
+ let(:definitions) do
+ {
+ 'my_task' => Backup::Manager::TaskDefinition.new(
+ task: task,
+ enabled: enabled,
+ destination_path: 'my_task.tar.gz',
+ human_name: 'my task',
+ task_group: 'group1'
+ )
+ }
+ end
it 'calls the named task' do
expect(task).to receive(:dump)
@@ -53,6 +63,16 @@ RSpec.describe Backup::Manager do
subject.run_create_task('my_task')
end
end
+
+ describe 'task group skipped' do
+ it 'informs the user' do
+ stub_env('SKIP', 'group1')
+
+ expect(Gitlab::BackupLogger).to receive(:info).with(message: 'Dumping my task ... [SKIPPED]')
+
+ subject.run_create_task('my_task')
+ end
+ end
end
describe '#run_restore_task' do
@@ -164,7 +184,7 @@ RSpec.describe Backup::Manager do
before do
stub_env('INCREMENTAL', incremental_env)
- allow(ActiveRecord::Base.connection).to receive(:reconnect!)
+ allow(ApplicationRecord.connection).to receive(:reconnect!)
allow(Gitlab::BackupLogger).to receive(:info)
allow(Kernel).to receive(:system).and_return(true)
diff --git a/spec/lib/banzai/cross_project_reference_spec.rb b/spec/lib/banzai/cross_project_reference_spec.rb
index e703bbc4927..8748a910003 100644
--- a/spec/lib/banzai/cross_project_reference_spec.rb
+++ b/spec/lib/banzai/cross_project_reference_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Banzai::CrossProjectReference do
let(:including_class) { Class.new.include(described_class).new }
- let(:reference_cache) { Banzai::Filter::References::ReferenceCache.new(including_class, {}, {})}
+ let(:reference_cache) { Banzai::Filter::References::ReferenceCache.new(including_class, {}, {}) }
before do
allow(including_class).to receive(:context).and_return({})
diff --git a/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb b/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb
index a2d35eaa6b6..c581750d2a9 100644
--- a/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb
+++ b/spec/lib/banzai/filter/broadcast_message_placeholders_filter_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Banzai::Filter::BroadcastMessagePlaceholdersFilter do
end
context 'works with empty text' do
- let(:text) {" "}
+ let(:text) { " " }
it { expect(subject).to eq(" ") }
end
@@ -42,13 +42,13 @@ RSpec.describe Banzai::Filter::BroadcastMessagePlaceholdersFilter do
context 'available placeholders' do
context 'replaces the email of the user' do
- let(:text) { "{{email}}"}
+ let(:text) { "{{email}}" }
it { expect(subject).to eq(user.email) }
end
context 'replaces the name of the user' do
- let(:text) { "{{name}}"}
+ let(:text) { "{{name}}" }
it { expect(subject).to eq(user.name) }
end
diff --git a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
index f7cb6b92b48..38f9bda57e6 100644
--- a/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_trailers_filter_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Banzai::Filter::CommitTrailersFilter do
let(:secondary_email) { create(:email, :confirmed) }
let(:user) { create(:user) }
- let(:trailer) { "#{FFaker::Lorem.word}-by:"}
+ let(:trailer) { "#{FFaker::Lorem.word}-by:" }
let(:commit_message) { trailer_line(trailer, user.name, user.email) }
let(:commit_message_html) { commit_html(commit_message) }
diff --git a/spec/lib/banzai/filter/task_list_filter_spec.rb b/spec/lib/banzai/filter/task_list_filter_spec.rb
index c89acd1a643..920904b0f29 100644
--- a/spec/lib/banzai/filter/task_list_filter_spec.rb
+++ b/spec/lib/banzai/filter/task_list_filter_spec.rb
@@ -10,4 +10,38 @@ RSpec.describe Banzai::Filter::TaskListFilter do
expect(doc.xpath('.//li//task-button').count).to eq(2)
end
+
+ describe 'inapplicable list items' do
+ shared_examples 'a valid inapplicable task list item' do |html|
+ it "behaves correctly for `#{html}`" do
+ doc = filter("<ul><li>#{html}</li></ul>")
+
+ expect(doc.css('li.inapplicable input[data-inapplicable]').count).to eq(1)
+ expect(doc.css('li.inapplicable > s').count).to eq(1)
+ end
+ end
+
+ shared_examples 'an invalid inapplicable task list item' do |html|
+ it "does nothing for `#{html}`" do
+ doc = filter("<ul><li>#{html}</li></ul>")
+
+ expect(doc.css('li.inapplicable input[data-inapplicable]').count).to eq(0)
+ end
+ end
+
+ it_behaves_like 'a valid inapplicable task list item', '[~] foobar'
+ it_behaves_like 'a valid inapplicable task list item', '[~] foo <em>bar</em>'
+ it_behaves_like 'an invalid inapplicable task list item', '[ ] foobar'
+ it_behaves_like 'an invalid inapplicable task list item', '[x] foobar'
+ it_behaves_like 'an invalid inapplicable task list item', 'foo [~] bar'
+
+ it 'does not wrap a sublist with <s>' do
+ html = '[~] foo <em>bar</em>\n<ol><li>sublist</li></ol>'
+ doc = filter("<ul><li>#{html}</li></ul>")
+
+ expect(doc.to_html).to include('<s>foo <em>bar</em>\n</s>')
+ expect(doc.css('li.inapplicable input[data-inapplicable]').count).to eq(1)
+ expect(doc.css('li.inapplicable > s').count).to eq(1)
+ end
+ end
end
diff --git a/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb b/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb
index 09d2919c6c4..4bccae04fda 100644
--- a/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb
@@ -10,9 +10,9 @@ RSpec.describe Banzai::Pipeline::IncidentManagement::TimelineEventPipeline do
expect(described_class.filters).to eq(
[
*Banzai::Pipeline::PlainMarkdownPipeline.filters,
+ Banzai::Filter::SanitizationFilter,
*Banzai::Pipeline::GfmPipeline.reference_filters,
Banzai::Filter::EmojiFilter,
- Banzai::Filter::SanitizationFilter,
Banzai::Filter::ExternalLinkFilter,
Banzai::Filter::ImageLinkFilter
]
@@ -62,7 +62,32 @@ RSpec.describe Banzai::Pipeline::IncidentManagement::TimelineEventPipeline do
context 'when markdown contains emojis' do
let(:markdown) { ':+1:ðŸ‘' }
- it { is_expected.to eq('<p>ðŸ‘ðŸ‘</p>') }
+ it 'renders emojis wrapped in <gl-emoji> tag' do
+ # rubocop:disable Layout/LineLength
+ is_expected.to eq(
+ %q(<p><gl-emoji title="thumbs up sign" data-name="thumbsup" data-unicode-version="6.0">ðŸ‘</gl-emoji><gl-emoji title="thumbs up sign" data-name="thumbsup" data-unicode-version="6.0">ðŸ‘</gl-emoji></p>)
+ )
+ # rubocop:enable Layout/LineLength
+ end
+ end
+
+ context 'when markdown contains labels' do
+ let(:label) { create(:label, project: project, title: 'backend') }
+ let(:markdown) { %Q(~"#{label.name}" ~unknown) }
+
+ it 'replaces existing label to a link' do
+ # rubocop:disable Layout/LineLength
+ is_expected.to match(
+ %r(<p>.+<a href=\"[\w/]+-/issues\?label_name=#{label.name}\".+style=\"background-color: #\d{6}\".*>#{label.name}</span></a></span> ~unknown</p>)
+ )
+ # rubocop:enable Layout/LineLength
+ end
+ end
+
+ context 'when markdown contains table' do
+ let(:markdown) { '<table><tr><th>table head</th><tr><tr><td>table content</td></tr></table>' }
+
+ it { is_expected.to eq('table headtable content') }
end
context 'when markdown contains a reference to an issue' do
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
index 80392fe264f..536f2a67415 100644
--- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -11,9 +11,9 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
it 'converts all reference punctuation to literals' do
reference_chars = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS
- markdown = reference_chars.split('').map {|char| char.prepend("\\") }.join
+ markdown = reference_chars.split('').map { |char| char.prepend("\\") }.join
punctuation = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS.split('')
- punctuation = punctuation.delete_if {|char| char == '&' }
+ punctuation = punctuation.delete_if { |char| char == '&' }
punctuation << '&amp;'
result = described_class.call(markdown, project: project)
diff --git a/spec/lib/banzai/renderer_spec.rb b/spec/lib/banzai/renderer_spec.rb
index d487268da78..ae9cf4c5068 100644
--- a/spec/lib/banzai/renderer_spec.rb
+++ b/spec/lib/banzai/renderer_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe Banzai::Renderer do
describe '#post_process' do
let(:context_options) { {} }
- let(:html) { 'Consequatur aperiam et nesciunt modi aut assumenda quo id. '}
+ let(:html) { 'Consequatur aperiam et nesciunt modi aut assumenda quo id. ' }
let(:post_processed_html) { double(html_safe: 'safe doc') }
let(:doc) { double(to_html: post_processed_html) }
diff --git a/spec/lib/bitbucket_server/connection_spec.rb b/spec/lib/bitbucket_server/connection_spec.rb
index 873eded58d7..ae73955e1d1 100644
--- a/spec/lib/bitbucket_server/connection_spec.rb
+++ b/spec/lib/bitbucket_server/connection_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe BitbucketServer::Connection do
context 'branch API' do
let(:branch_path) { '/projects/foo/repos/bar/branches' }
let(:branch_url) { 'https://test:7990/rest/branch-utils/1.0/projects/foo/repos/bar/branches' }
- let(:path) { }
+ let(:path) {}
it 'returns JSON body' do
WebMock.stub_request(:delete, branch_url).with(headers: headers).to_return(body: payload.to_json, status: 200, headers: headers)
diff --git a/spec/lib/bulk_imports/clients/http_spec.rb b/spec/lib/bulk_imports/clients/http_spec.rb
index c9730e03311..75c5f363b1f 100644
--- a/spec/lib/bulk_imports/clients/http_spec.rb
+++ b/spec/lib/bulk_imports/clients/http_spec.rb
@@ -56,15 +56,17 @@ RSpec.describe BulkImports::Clients::HTTP do
[
'http://gitlab.example/api/v4/resource',
hash_including(
- follow_redirects: false,
query: {
page: described_class::DEFAULT_PAGE,
- per_page: described_class::DEFAULT_PER_PAGE
+ per_page: described_class::DEFAULT_PER_PAGE,
+ private_token: token
},
headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{token}"
- }
+ 'Content-Type' => 'application/json'
+ },
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
)
]
end
@@ -106,12 +108,13 @@ RSpec.describe BulkImports::Clients::HTTP do
def stub_http_get(path, query, response)
uri = "http://gitlab.example/api/v4/#{path}"
params = {
- follow_redirects: false,
- headers: {
- "Authorization" => "Bearer token",
- "Content-Type" => "application/json"
- }
- }.merge(query: query)
+ headers: { "Content-Type" => "application/json" },
+ query: { private_token: token },
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
+ }
+ params[:query] = params[:query].merge(query)
allow(Gitlab::HTTP).to receive(:get).with(uri, params).and_return(response)
end
@@ -127,11 +130,17 @@ RSpec.describe BulkImports::Clients::HTTP do
'http://gitlab.example/api/v4/resource',
hash_including(
body: {},
- follow_redirects: false,
headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{token}"
- }
+ 'Content-Type' => 'application/json'
+ },
+ query: {
+ page: described_class::DEFAULT_PAGE,
+ per_page: described_class::DEFAULT_PER_PAGE,
+ private_token: token
+ },
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
)
]
end
@@ -146,11 +155,17 @@ RSpec.describe BulkImports::Clients::HTTP do
[
'http://gitlab.example/api/v4/resource',
hash_including(
- follow_redirects: false,
headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{token}"
- }
+ 'Content-Type' => 'application/json'
+ },
+ query: {
+ page: described_class::DEFAULT_PAGE,
+ per_page: described_class::DEFAULT_PER_PAGE,
+ private_token: token
+ },
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
)
]
end
@@ -164,9 +179,16 @@ RSpec.describe BulkImports::Clients::HTTP do
hash_including(
stream_body: true,
headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Bearer #{token}"
- }
+ 'Content-Type' => 'application/json'
+ },
+ query: {
+ page: described_class::DEFAULT_PAGE,
+ per_page: described_class::DEFAULT_PER_PAGE,
+ private_token: token
+ },
+ follow_redirects: true,
+ resend_on_redirect: false,
+ limit: 2
)
]
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 b769aa4af5a..f0b461e518e 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
@@ -11,8 +11,8 @@ RSpec.describe BulkImports::Common::Pipelines::LfsObjectsPipeline do
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
let(:lfs_dir_path) { tmpdir }
- let(:lfs_json_file_path) { File.join(lfs_dir_path, 'lfs_objects.json')}
- let(:lfs_file_path) { File.join(lfs_dir_path, oid)}
+ let(:lfs_json_file_path) { File.join(lfs_dir_path, 'lfs_objects.json') }
+ let(:lfs_file_path) { File.join(lfs_dir_path, oid) }
subject(:pipeline) { described_class.new(context) }
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 9d43bb3ebfb..f650e931dc7 100644
--- a/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline do
let(:tmpdir) { Dir.mktmpdir }
let(:uploads_dir_path) { File.join(tmpdir, '72a497a02fe3ee09edae2ed06d390038') }
- let(:upload_file_path) { File.join(uploads_dir_path, 'upload.txt')}
+ let(:upload_file_path) { File.join(uploads_dir_path, 'upload.txt') }
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
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 d775cf6b026..896af865c56 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
@@ -13,7 +13,7 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
:bulk_import_entity,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
- destination_name: 'destination-name-path',
+ destination_slug: 'destination-slug-path',
destination_namespace: parent.full_path
)
end
@@ -41,14 +41,14 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer do
'name' => 'Name',
'description' => 'Description',
'parent_id' => parent.id,
- 'path' => 'destination-name-path'
+ 'path' => 'destination-slug-path'
})
end
- it 'transforms path from destination_name' do
+ it 'transforms path from destination_slug' do
transformed_data = subject.transform(context, data)
- expect(transformed_data['path']).to eq(entity.destination_name)
+ expect(transformed_data['path']).to eq(entity.destination_slug)
end
it 'removes full path' do
diff --git a/spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb
index 2633598b48d..a376cdd712c 100644
--- a/spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/releases_pipeline_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
}
end
- let(:attributes) {{ 'links' => [link] }}
+ let(:attributes) { { 'links' => [link] } }
it 'restores release links' do
pipeline.run
@@ -106,7 +106,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
}
end
- let(:attributes) {{ 'milestone_releases' => [{ 'milestone' => milestone }] }}
+ let(:attributes) { { 'milestone_releases' => [{ 'milestone' => milestone }] } }
it 'restores release milestone' do
pipeline.run
@@ -133,7 +133,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
end
context 'when release is historical' do
- let(:attributes) {{ 'released_at' => '2018-12-26T10:17:14.621Z' }}
+ let(:attributes) { { 'released_at' => '2018-12-26T10:17:14.621Z' } }
it 'does not create release evidence' do
expect(::Releases::CreateEvidenceWorker).not_to receive(:perform_async)
@@ -143,7 +143,7 @@ RSpec.describe BulkImports::Projects::Pipelines::ReleasesPipeline do
end
context 'when release is upcoming' do
- let(:attributes) {{ 'released_at' => Time.zone.now + 30.days }}
+ let(:attributes) { { 'released_at' => Time.zone.now + 30.days } }
it 'does not create release evidence' do
expect(::Releases::CreateEvidenceWorker).not_to receive(:perform_async)
diff --git a/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb
index 9897e74ec7b..4d12b49e2c0 100644
--- a/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe BulkImports::Projects::Pipelines::SnippetsRepositoryPipeline do
let(:project) { create(:project) }
let(:bulk_import) { create(:bulk_import, user: user) }
let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
- let!(:matched_snippet) { create(:snippet, project: project, created_at: "1981-12-13T23:59:59Z")}
+ let!(:matched_snippet) { create(:snippet, project: project, created_at: "1981-12-13T23:59:59Z") }
let(:entity) do
create(
:bulk_import_entity,
diff --git a/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb b/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
index a1d77b9732d..c1c4d0bf0db 100644
--- a/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe BulkImports::Projects::Transformers::ProjectAttributesTransformer
source_type: :project_entity,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
- destination_name: 'Destination Project Name',
+ destination_slug: 'Destination Project Name',
destination_namespace: destination_group.full_path
)
end
@@ -32,12 +32,12 @@ RSpec.describe BulkImports::Projects::Transformers::ProjectAttributesTransformer
subject(:transformed_data) { described_class.new.transform(context, data) }
- it 'transforms name to destination name' do
- expect(transformed_data[:name]).to eq(entity.destination_name)
+ it 'transforms name to destination slug' do
+ expect(transformed_data[:name]).to eq(entity.destination_slug)
end
it 'adds path as parameterized name' do
- expect(transformed_data[:path]).to eq(entity.destination_name.parameterize)
+ expect(transformed_data[:path]).to eq(entity.destination_slug.parameterize)
end
it 'transforms visibility level' do
@@ -65,7 +65,7 @@ RSpec.describe BulkImports::Projects::Transformers::ProjectAttributesTransformer
source_type: :project_entity,
bulk_import: bulk_import,
source_full_path: 'source/full/path',
- destination_name: 'Destination Project Name',
+ destination_slug: 'Destination Project Name',
destination_namespace: ''
)
diff --git a/spec/lib/container_registry/gitlab_api_client_spec.rb b/spec/lib/container_registry/gitlab_api_client_spec.rb
index f2c627734a3..7836d8706f6 100644
--- a/spec/lib/container_registry/gitlab_api_client_spec.rb
+++ b/spec/lib/container_registry/gitlab_api_client_spec.rb
@@ -212,6 +212,105 @@ RSpec.describe ContainerRegistry::GitlabApiClient do
end
end
+ describe '#tags' do
+ let(:path) { 'namespace/path/to/repository' }
+ let(:page_size) { 100 }
+ let(:last) { nil }
+ let(:response) do
+ [
+ {
+ name: '0.1.0',
+ digest: 'sha256:1234567890',
+ media_type: 'application/vnd.oci.image.manifest.v1+json',
+ size_bytes: 1234567890,
+ created_at: 5.minutes.ago
+ },
+ {
+ name: 'latest',
+ digest: 'sha256:1234567892',
+ media_type: 'application/vnd.oci.image.manifest.v1+json',
+ size_bytes: 1234567892,
+ created_at: 10.minutes.ago
+ }
+ ]
+ end
+
+ subject { client.tags(path, page_size: page_size, last: last) }
+
+ context 'with valid parameters' do
+ let(:expected) do
+ {
+ pagination: {},
+ response_body: ::Gitlab::Json.parse(response.to_json)
+ }
+ end
+
+ before do
+ stub_tags(path, page_size: page_size, respond_with: response)
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'with a response with a link header' do
+ let(:next_page_url) { 'http://sandbox.org/test?last=b' }
+ let(:expected) do
+ {
+ pagination: { next: { uri: URI(next_page_url) } },
+ response_body: ::Gitlab::Json.parse(response.to_json)
+ }
+ end
+
+ before do
+ stub_tags(path, page_size: page_size, next_page_url: next_page_url, respond_with: response)
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'with a large page size set' do
+ let(:page_size) { described_class::MAX_TAGS_PAGE_SIZE + 1000 }
+
+ let(:expected) do
+ {
+ pagination: {},
+ response_body: ::Gitlab::Json.parse(response.to_json)
+ }
+ end
+
+ before do
+ stub_tags(path, page_size: described_class::MAX_TAGS_PAGE_SIZE, respond_with: response)
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'with a last parameter set' do
+ let(:last) { 'test' }
+
+ let(:expected) do
+ {
+ pagination: {},
+ response_body: ::Gitlab::Json.parse(response.to_json)
+ }
+ end
+
+ before do
+ stub_tags(path, page_size: page_size, last: last, respond_with: response)
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'with non successful response' do
+ before do
+ stub_tags(path, page_size: page_size, status_code: 404)
+ end
+
+ it { is_expected.to eq({}) }
+ end
+ end
+
describe '.supports_gitlab_api?' do
subject { described_class.supports_gitlab_api? }
@@ -389,4 +488,30 @@ RSpec.describe ContainerRegistry::GitlabApiClient do
.with(headers: headers)
.to_return(status: status_code, body: respond_with.to_json, headers: { 'Content-Type' => described_class::JSON_TYPE })
end
+
+ def stub_tags(path, page_size: nil, last: nil, next_page_url: nil, status_code: 200, respond_with: {})
+ params = { n: page_size, last: last }.compact
+
+ url = "#{registry_api_url}/gitlab/v1/repositories/#{path}/tags/list/"
+
+ if params.present?
+ url += "?#{params.map { |param, val| "#{param}=#{val}" }.join('&')}"
+ end
+
+ request_headers = { 'Accept' => described_class::JSON_TYPE }
+ request_headers['Authorization'] = "bearer #{token}" if token
+
+ response_headers = { 'Content-Type' => described_class::JSON_TYPE }
+ if next_page_url
+ response_headers['Link'] = "<#{next_page_url}>; rel=\"next\""
+ end
+
+ stub_request(:get, url)
+ .with(headers: request_headers)
+ .to_return(
+ status: status_code,
+ body: respond_with.to_json,
+ headers: response_headers
+ )
+ end
end
diff --git a/spec/lib/container_registry/tag_spec.rb b/spec/lib/container_registry/tag_spec.rb
index 9b931ab6dbc..190ddef0cd5 100644
--- a/spec/lib/container_registry/tag_spec.rb
+++ b/spec/lib/container_registry/tag_spec.rb
@@ -205,6 +205,41 @@ RSpec.describe ContainerRegistry::Tag do
it_behaves_like 'a processable'
end
+
+ describe '#force_created_at_from_iso8601' do
+ subject { tag.force_created_at_from_iso8601(input) }
+
+ shared_examples 'setting and caching the created_at value' do
+ it 'sets and caches the created_at value' do
+ expect(tag).not_to receive(:config)
+
+ subject
+
+ expect(tag.created_at).to eq(expected_value)
+ end
+ end
+
+ context 'with a valid input' do
+ let(:input) { 2.days.ago.iso8601 }
+ let(:expected_value) { DateTime.iso8601(input) }
+
+ it_behaves_like 'setting and caching the created_at value'
+ end
+
+ context 'with a nil input' do
+ let(:input) { nil }
+ let(:expected_value) { nil }
+
+ it_behaves_like 'setting and caching the created_at value'
+ end
+
+ context 'with an invalid input' do
+ let(:input) { 'not a timestamp' }
+ let(:expected_value) { nil }
+
+ it_behaves_like 'setting and caching the created_at value'
+ end
+ end
end
end
end
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 4db3f04717b..56e0b4bca30 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -491,8 +491,8 @@ RSpec.describe Feature, stub_feature_flags: false do
end
shared_examples_for 'logging' do
- let(:expected_action) { }
- let(:expected_extra) { }
+ let(:expected_action) {}
+ let(:expected_extra) {}
it 'logs the event' do
expect(Feature.logger).to receive(:info).with(key: key, action: expected_action, **expected_extra)
diff --git a/spec/lib/gitlab/alert_management/payload/base_spec.rb b/spec/lib/gitlab/alert_management/payload/base_spec.rb
index d3c1a96253c..ad2a3c7b462 100644
--- a/spec/lib/gitlab/alert_management/payload/base_spec.rb
+++ b/spec/lib/gitlab/alert_management/payload/base_spec.rb
@@ -228,6 +228,46 @@ RSpec.describe Gitlab::AlertManagement::Payload::Base do
it { is_expected.to eq({ hosts: shortened_hosts, project_id: project.id }) }
end
end
+
+ context 'with present, non-string values for string fields' do
+ let_it_be(:stubs) do
+ {
+ description: { "description" => "description" },
+ monitoring_tool: ['datadog', 5],
+ service: 4356875,
+ title: true
+ }
+ end
+
+ before do
+ allow(parsed_payload).to receive_messages(stubs)
+ end
+
+ it 'casts values to strings' do
+ is_expected.to eq({
+ description: "{\"description\"=>\"description\"}",
+ monitoring_tool: "[\"datadog\", 5]",
+ service: '4356875',
+ project_id: project.id,
+ title: "true"
+ })
+ end
+ end
+
+ context 'with blank values for string fields' do
+ let_it_be(:stubs) do
+ {
+ description: nil,
+ monitoring_tool: '',
+ service: {},
+ title: []
+ }
+ end
+
+ it 'leaves the fields blank' do
+ is_expected.to eq({ project_id: project.id })
+ end
+ end
end
describe '#gitlab_fingerprint' do
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index f9e18a65af4..8b2a228b935 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::ApplicationContext do
end
it 'raises an error when passing invalid options' do
- expect { described_class.push(no: 'option')}.to raise_error(ArgumentError)
+ expect { described_class.push(no: 'option') }.to raise_error(ArgumentError)
end
end
diff --git a/spec/lib/gitlab/application_rate_limiter_spec.rb b/spec/lib/gitlab/application_rate_limiter_spec.rb
index 177ce1134d8..41e79f811fa 100644
--- a/spec/lib/gitlab/application_rate_limiter_spec.rb
+++ b/spec/lib/gitlab/application_rate_limiter_spec.rb
@@ -111,23 +111,35 @@ RSpec.describe Gitlab::ApplicationRateLimiter, :clean_gitlab_redis_rate_limiting
shared_examples 'throttles based on key and scope' do
let(:start_time) { Time.current.beginning_of_hour }
- it 'returns true when threshold is exceeded' do
+ let(:threshold) { nil }
+ let(:interval) { nil }
+
+ it 'returns true when threshold is exceeded', :aggregate_failures do
travel_to(start_time) do
- expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(false)
end
travel_to(start_time + 1.minute) do
- expect(subject.throttled?(:test_action, scope: scope)).to eq(true)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(true)
# Assert that it does not affect other actions or scope
expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
- expect(subject.throttled?(:test_action, scope: [user])).to eq(false)
+
+ expect(subject.throttled?(
+ :test_action, scope: [user], threshold: threshold, interval: interval)
+ ).to eq(false)
end
end
- it 'returns false when interval has elapsed' do
+ it 'returns false when interval has elapsed', :aggregate_failures do
travel_to(start_time) do
- expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(false)
# another_action has a threshold of 2 so we simulate 2 requests
expect(subject.throttled?(:another_action, scope: scope)).to eq(false)
@@ -135,21 +147,34 @@ RSpec.describe Gitlab::ApplicationRateLimiter, :clean_gitlab_redis_rate_limiting
end
travel_to(start_time + 2.minutes) do
- expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(false)
# Assert that another_action has its own interval that hasn't elapsed
expect(subject.throttled?(:another_action, scope: scope)).to eq(true)
end
end
- it 'allows peeking at the current state without changing its value' do
+ it 'allows peeking at the current state without changing its value', :aggregate_failures do
travel_to(start_time) do
- expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(false)
+
2.times do
- expect(subject.throttled?(:test_action, scope: scope, peek: true)).to eq(false)
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval, peek: true)
+ ).to eq(false)
end
- expect(subject.throttled?(:test_action, scope: scope)).to eq(true)
- expect(subject.throttled?(:test_action, scope: scope, peek: true)).to eq(true)
+
+ expect(subject.throttled?(
+ :test_action, scope: scope, threshold: threshold, interval: interval)
+ ).to eq(true)
+
+ expect(subject.throttled?(
+ :test_action, scope: scope, peek: true, threshold: threshold, interval: interval)
+ ).to eq(true)
end
end
end
@@ -165,6 +190,28 @@ RSpec.describe Gitlab::ApplicationRateLimiter, :clean_gitlab_redis_rate_limiting
it_behaves_like 'throttles based on key and scope'
end
+
+ context 'when threshold and interval get overwritten from rate_limits' do
+ let(:rate_limits) do
+ {
+ test_action: {
+ threshold: 0,
+ interval: 0
+ },
+ another_action: {
+ threshold: -> { 2 },
+ interval: -> { 3.minutes }
+ }
+ }
+ end
+
+ let(:scope) { [user, project] }
+
+ it_behaves_like 'throttles based on key and scope' do
+ let(:threshold) { 1 }
+ let(:interval) { 2.minutes }
+ end
+ end
end
describe '.peek' do
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index bfea1315d90..b2bce2076b0 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -791,7 +791,7 @@ module Gitlab
end
context 'when the file does not exist' do
- it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]")}
+ it { is_expected.to include("[ERROR: include::#{include_path}[] - unresolved directive]") }
end
end
diff --git a/spec/lib/gitlab/audit/auditor_spec.rb b/spec/lib/gitlab/audit/auditor_spec.rb
new file mode 100644
index 00000000000..fc5917ca583
--- /dev/null
+++ b/spec/lib/gitlab/audit/auditor_spec.rb
@@ -0,0 +1,258 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Audit::Auditor do
+ let(:name) { 'audit_operation' }
+ let(:author) { create(:user) }
+ let(:group) { create(:group) }
+ let(:provider) { 'standard' }
+ let(:context) do
+ { name: name,
+ author: author,
+ scope: group,
+ target: group,
+ authentication_event: true,
+ authentication_provider: provider,
+ message: "Signed in using standard authentication" }
+ end
+
+ let(:logger) { instance_spy(Gitlab::AuditJsonLogger) }
+
+ subject(:auditor) { described_class }
+
+ describe '.audit' do
+ context 'when authentication event' do
+ let(:audit!) { auditor.audit(context) }
+
+ it 'creates an authentication event' do
+ expect(AuthenticationEvent).to receive(:new).with(
+ {
+ user: author,
+ user_name: author.name,
+ ip_address: author.current_sign_in_ip,
+ result: AuthenticationEvent.results[:success],
+ provider: provider
+ }
+ ).and_call_original
+
+ audit!
+ end
+
+ it 'logs audit events to database', :aggregate_failures do
+ freeze_time do
+ audit!
+
+ audit_event = AuditEvent.last
+
+ expect(audit_event.author_id).to eq(author.id)
+ expect(audit_event.entity_id).to eq(group.id)
+ expect(audit_event.entity_type).to eq(group.class.name)
+ expect(audit_event.created_at).to eq(Time.zone.now)
+ expect(audit_event.details[:target_id]).to eq(group.id)
+ expect(audit_event.details[:target_type]).to eq(group.class.name)
+ end
+ end
+
+ it 'logs audit events to file' do
+ expect(::Gitlab::AuditJsonLogger).to receive(:build).and_return(logger)
+
+ audit!
+
+ expect(logger).to have_received(:info).with(
+ hash_including(
+ 'author_id' => author.id,
+ 'author_name' => author.name,
+ 'entity_id' => group.id,
+ 'entity_type' => group.class.name,
+ 'details' => kind_of(Hash)
+ )
+ )
+ end
+
+ context 'when overriding the create datetime' do
+ let(:context) do
+ { name: name,
+ author: author,
+ scope: group,
+ target: group,
+ created_at: 3.weeks.ago,
+ authentication_event: true,
+ authentication_provider: provider,
+ message: "Signed in using standard authentication" }
+ end
+
+ it 'logs audit events to database', :aggregate_failures do
+ freeze_time do
+ audit!
+
+ audit_event = AuditEvent.last
+
+ expect(audit_event.author_id).to eq(author.id)
+ expect(audit_event.entity_id).to eq(group.id)
+ expect(audit_event.entity_type).to eq(group.class.name)
+ expect(audit_event.created_at).to eq(3.weeks.ago)
+ expect(audit_event.details[:target_id]).to eq(group.id)
+ expect(audit_event.details[:target_type]).to eq(group.class.name)
+ end
+ end
+
+ it 'logs audit events to file' do
+ freeze_time do
+ expect(::Gitlab::AuditJsonLogger).to receive(:build).and_return(logger)
+
+ audit!
+
+ expect(logger).to have_received(:info).with(
+ hash_including(
+ 'author_id' => author.id,
+ 'author_name' => author.name,
+ 'entity_id' => group.id,
+ 'entity_type' => group.class.name,
+ 'details' => kind_of(Hash),
+ 'created_at' => 3.weeks.ago.iso8601(3)
+ )
+ )
+ end
+ end
+ end
+
+ context 'when overriding the additional_details' do
+ additional_details = { action: :custom, from: false, to: true }
+ let(:context) do
+ { name: name,
+ author: author,
+ scope: group,
+ target: group,
+ created_at: Time.zone.now,
+ additional_details: additional_details,
+ authentication_event: true,
+ authentication_provider: provider,
+ message: "Signed in using standard authentication" }
+ end
+
+ it 'logs audit events to database' do
+ freeze_time do
+ audit!
+
+ expect(AuditEvent.last.details).to include(additional_details)
+ end
+ end
+
+ it 'logs audit events to file' do
+ freeze_time do
+ expect(::Gitlab::AuditJsonLogger).to receive(:build).and_return(logger)
+
+ audit!
+
+ expect(logger).to have_received(:info).with(
+ hash_including(
+ 'details' => hash_including('action' => 'custom', 'from' => 'false', 'to' => 'true'),
+ 'action' => 'custom',
+ 'from' => 'false',
+ 'to' => 'true'
+ )
+ )
+ end
+ end
+ end
+
+ context 'when overriding the target_details' do
+ target_details = "this is my target details"
+ let(:context) do
+ {
+ name: name,
+ author: author,
+ scope: group,
+ target: group,
+ created_at: Time.zone.now,
+ target_details: target_details,
+ authentication_event: true,
+ authentication_provider: provider,
+ message: "Signed in using standard authentication"
+ }
+ end
+
+ it 'logs audit events to database' do
+ freeze_time do
+ audit!
+
+ audit_event = AuditEvent.last
+ expect(audit_event.details).to include({ target_details: target_details })
+ expect(audit_event.target_details).to eq(target_details)
+ end
+ end
+
+ it 'logs audit events to file' do
+ freeze_time do
+ expect(::Gitlab::AuditJsonLogger).to receive(:build).and_return(logger)
+
+ audit!
+
+ expect(logger).to have_received(:info).with(
+ hash_including(
+ 'details' => hash_including('target_details' => target_details),
+ 'target_details' => target_details
+ )
+ )
+ end
+ end
+ end
+ end
+
+ context 'when authentication event is false' do
+ let(:context) do
+ { name: name, author: author, scope: group,
+ target: group, authentication_event: false, message: "sample message" }
+ end
+
+ it 'does not create an authentication event' do
+ expect { auditor.audit(context) }.not_to change(AuthenticationEvent, :count)
+ end
+ end
+
+ context 'when authentication event is invalid' do
+ let(:audit!) { auditor.audit(context) }
+
+ before do
+ allow(AuthenticationEvent).to receive(:new).and_raise(ActiveRecord::RecordInvalid)
+ allow(Gitlab::ErrorTracking).to receive(:track_exception)
+ end
+
+ it 'tracks error' do
+ audit!
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_exception).with(
+ kind_of(ActiveRecord::RecordInvalid),
+ { audit_operation: name }
+ )
+ end
+
+ it 'does not throw exception' do
+ expect { auditor.audit(context) }.not_to raise_exception
+ end
+ end
+
+ context 'when audit events are invalid' do
+ let(:audit!) { auditor.audit(context) }
+
+ before do
+ allow(AuditEvent).to receive(:bulk_insert!).and_raise(ActiveRecord::RecordInvalid)
+ allow(Gitlab::ErrorTracking).to receive(:track_exception)
+ end
+
+ it 'tracks error' do
+ audit!
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_exception).with(
+ kind_of(ActiveRecord::RecordInvalid),
+ { audit_operation: name }
+ )
+ end
+
+ it 'does not throw exception' do
+ expect { auditor.audit(context) }.not_to raise_exception
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
index f55e1b44936..89664c57084 100644
--- a/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
+++ b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Audit::CiRunnerTokenAuthor do
describe '.initialize' do
subject { described_class.new(audit_event) }
- let(:details) { }
+ let(:details) {}
let(:audit_event) { instance_double(AuditEvent, details: details, entity_type: 'Project', entity_path: 'd/e') }
context 'with runner_authentication_token' do
diff --git a/spec/lib/gitlab/audit/deploy_key_author_spec.rb b/spec/lib/gitlab/audit/deploy_key_author_spec.rb
new file mode 100644
index 00000000000..72444f77c91
--- /dev/null
+++ b/spec/lib/gitlab/audit/deploy_key_author_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Audit::DeployKeyAuthor do
+ describe '#initialize' do
+ it 'sets correct attributes' do
+ expect(described_class.new(name: 'Lorem deploy key'))
+ .to have_attributes(id: -3, name: 'Lorem deploy key')
+ end
+
+ it 'sets default name when it is not provided' do
+ expect(described_class.new)
+ .to have_attributes(id: -3, name: 'Deploy Key')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/audit/null_author_spec.rb b/spec/lib/gitlab/audit/null_author_spec.rb
index 2045139a5f7..e2f71a34534 100644
--- a/spec/lib/gitlab/audit/null_author_spec.rb
+++ b/spec/lib/gitlab/audit/null_author_spec.rb
@@ -57,6 +57,15 @@ RSpec.describe Gitlab::Audit::NullAuthor do
expect(subject.for(-2, audit_event)).to be_a(Gitlab::Audit::DeployTokenAuthor)
expect(subject.for(-2, audit_event)).to have_attributes(id: -2, name: 'Test deploy token')
end
+
+ it 'returns DeployKeyAuthor when id equals -3', :aggregate_failures do
+ allow(audit_event).to receive(:[]).with(:author_name).and_return('Test deploy key')
+ allow(audit_event).to receive(:details).and_return({})
+ allow(audit_event).to receive(:target_type)
+
+ expect(subject.for(-3, audit_event)).to be_a(Gitlab::Audit::DeployKeyAuthor)
+ expect(subject.for(-3, audit_event)).to have_attributes(id: -3, name: 'Test deploy key')
+ end
end
describe '#current_sign_in_ip' do
diff --git a/spec/lib/gitlab/audit/null_target_spec.rb b/spec/lib/gitlab/audit/null_target_spec.rb
new file mode 100644
index 00000000000..f192e0cd8db
--- /dev/null
+++ b/spec/lib/gitlab/audit/null_target_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Audit::NullTarget do
+ subject { described_class.new }
+
+ describe '#id' do
+ it 'returns nil' do
+ expect(subject.id).to eq(nil)
+ end
+ end
+
+ describe '#type' do
+ it 'returns nil' do
+ expect(subject.type).to eq(nil)
+ end
+ end
+
+ describe '#details' do
+ it 'returns nil' do
+ expect(subject.details).to eq(nil)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/audit/target_spec.rb b/spec/lib/gitlab/audit/target_spec.rb
new file mode 100644
index 00000000000..5c06cd117a9
--- /dev/null
+++ b/spec/lib/gitlab/audit/target_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Audit::Target do
+ let(:object) { double('object') } # rubocop:disable RSpec/VerifiedDoubles
+
+ subject { described_class.new(object) }
+
+ describe '#id' do
+ it 'returns object id' do
+ allow(object).to receive(:id).and_return(object_id)
+
+ expect(subject.id).to eq(object_id)
+ end
+ end
+
+ describe '#type' do
+ it 'returns object class name' do
+ allow(object).to receive_message_chain(:class, :name).and_return('User')
+
+ expect(subject.type).to eq('User')
+ end
+ end
+
+ describe '#details' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:name, :audit_details, :details) do
+ 'jackie' | 'wanderer' | 'jackie'
+ 'jackie' | nil | 'jackie'
+ nil | 'wanderer' | 'wanderer'
+ nil | nil | 'unknown'
+ end
+
+ before do
+ allow(object).to receive(:name).and_return(name) if name
+ allow(object).to receive(:audit_details).and_return(audit_details) if audit_details
+ end
+
+ with_them do
+ it 'returns details' do
+ expect(subject.details).to eq(details)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index e985f66bfe9..d0b44135a2f 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -127,7 +127,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
before do
- set_bearer_token(doorkeeper_access_token.token)
+ set_bearer_token(doorkeeper_access_token.plaintext_token)
end
it { is_expected.to eq user }
@@ -577,7 +577,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
context 'passed as header' do
before do
- set_bearer_token(doorkeeper_access_token.token)
+ set_bearer_token(doorkeeper_access_token.plaintext_token)
end
it 'returns token if valid oauth_access_token' do
@@ -587,7 +587,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
context 'passed as param' do
it 'returns user if valid oauth_access_token' do
- set_param(:access_token, doorkeeper_access_token.token)
+ set_param(:access_token, doorkeeper_access_token.plaintext_token)
expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
end
diff --git a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
index f23fdd3fbcb..3d9be4c3489 100644
--- a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
+++ b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_cachin
}
end
- subject { described_class.new(ip) }
+ subject(:rate_limiter) { described_class.new(ip) }
before do
stub_rack_attack_setting(options)
@@ -25,7 +25,7 @@ RSpec.describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_cachin
end
after do
- subject.reset!
+ rate_limiter.reset!
end
describe '#register_fail!' do
@@ -86,7 +86,7 @@ RSpec.describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_cachin
end
end
- context 'when IP is whitlisted' do
+ context 'when IP is allow listed' do
let(:ip) { '127.0.0.1' }
it_behaves_like 'skips the rate limiter'
@@ -97,4 +97,20 @@ RSpec.describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_cachin
it_behaves_like 'skips the rate limiter'
end
+
+ describe '#trusted_ip?' do
+ subject { rate_limiter.trusted_ip? }
+
+ context 'when ip is in the trusted list' do
+ let(:ip) { '127.0.0.1' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when ip is not in the trusted list' do
+ let(:ip) { '10.0.0.1' }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb b/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
index 69068883096..a044094179c 100644
--- a/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/auth_hash_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe Gitlab::Auth::OAuth::AuthHash do
)
end
+ let(:provider_config) { { 'args' => { 'gitlab_username_claim' => 'first_name' } } }
let(:uid_raw) do
+"CN=Onur K\xC3\xBC\xC3\xA7\xC3\xBCk,OU=Test,DC=example,DC=net"
end
@@ -35,6 +36,7 @@ RSpec.describe Gitlab::Auth::OAuth::AuthHash do
let(:email_utf8) { email_ascii.force_encoding(Encoding::UTF_8) }
let(:nickname_utf8) { nickname_ascii.force_encoding(Encoding::UTF_8) }
let(:name_utf8) { name_ascii.force_encoding(Encoding::UTF_8) }
+ let(:first_name_utf8) { first_name_ascii.force_encoding(Encoding::UTF_8) }
let(:info_hash) do
{
@@ -91,6 +93,34 @@ RSpec.describe Gitlab::Auth::OAuth::AuthHash do
end
end
+ context 'custom username field provided' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for).and_return(provider_config)
+ end
+
+ it 'uses the custom field for the username' do
+ expect(auth_hash.username).to eql first_name_utf8
+ end
+
+ it 'uses the default claim for the username when the custom claim is not found' do
+ provider_config['args']['gitlab_username_claim'] = 'nonexistent'
+
+ expect(auth_hash.username).to eql nickname_utf8
+ end
+
+ it 'uses the default claim for the username when the custom claim is empty' do
+ info_hash[:first_name] = ''
+
+ expect(auth_hash.username).to eql nickname_utf8
+ end
+
+ it 'uses the default claim for the username when the custom claim is nil' do
+ info_hash[:first_name] = nil
+
+ expect(auth_hash.username).to eql nickname_utf8
+ end
+ end
+
context 'auth_hash constructed with ASCII-8BIT encoding' do
it 'forces utf8 encoding on uid' do
expect(auth_hash.uid.encoding).to eql Encoding::UTF_8
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index 5f5e7f211f8..b160f322fb8 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -727,6 +727,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context 'signup with linked omniauth and LDAP account' do
before do
stub_omniauth_config(auto_link_ldap_user: true)
+ stub_ldap_setting(enabled: true)
allow(ldap_user).to receive(:uid) { uid }
allow(ldap_user).to receive(:username) { uid }
allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] }
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 1e869df0988..c2d64aa2fb3 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
context 'when IP is already banned' do
- subject { gl_auth.find_for_git_client('username', 'password', project: nil, ip: 'ip') }
+ subject { gl_auth.find_for_git_client('username-does-not-matter', 'password-does-not-matter', project: nil, ip: 'ip') }
before do
expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter|
@@ -219,16 +219,16 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it 'recognizes master passwords' do
- user = create(:user, password: 'password')
+ user = create(:user)
- expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
+ expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
end
include_examples 'user login operation with unique ip limit' do
- let(:user) { create(:user, password: 'password') }
+ let(:user) { create(:user) }
def operation
- expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
+ expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities)
end
end
@@ -502,8 +502,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user = create(
:user,
:blocked,
- username: 'normal_user',
- password: 'my-secret'
+ username: 'normal_user'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@@ -512,7 +511,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when 2fa is enabled globally' do
let_it_be(:user) do
- create(:user, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
+ create(:user, username: 'normal_user', otp_grace_period_started_at: 1.day.ago)
end
before do
@@ -536,7 +535,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when 2fa is enabled personally' do
let(:user) do
- create(:user, :two_factor, username: 'normal_user', password: 'my-secret', otp_grace_period_started_at: 1.day.ago)
+ create(:user, :two_factor, username: 'normal_user', otp_grace_period_started_at: 1.day.ago)
end
it 'fails' do
@@ -548,8 +547,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'goes through lfs authentication' do
user = create(
:user,
- username: 'normal_user',
- password: 'my-secret'
+ username: 'normal_user'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@@ -559,8 +557,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'goes through oauth authentication when the username is oauth2' do
user = create(
:user,
- username: 'oauth2',
- password: 'my-secret'
+ username: 'oauth2'
)
expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
@@ -635,7 +632,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'when deploy token and user have the same username' do
let(:username) { 'normal_user' }
- let(:user) { create(:user, username: username, password: 'my-secret') }
+ let(:user) { create(:user, username: username) }
let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) }
it 'succeeds for the token' do
@@ -648,7 +645,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'succeeds for the user' do
auth_success = { actor: user, project: nil, type: :gitlab_or_ldap, authentication_abilities: described_class.full_authentication_abilities }
- expect(gl_auth.find_for_git_client(username, 'my-secret', project: project, ip: 'ip'))
+ expect(gl_auth.find_for_git_client(username, user.password, project: project, ip: 'ip'))
.to have_attributes(auth_success)
end
end
@@ -834,72 +831,64 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
describe 'find_with_user_password' do
- let!(:user) do
- create(:user,
- username: username,
- password: password,
- password_confirmation: password)
- end
-
+ let!(:user) { create(:user, username: username) }
let(:username) { 'John' } # username isn't lowercase, test this
- let(:password) { 'my-secret' }
it "finds user by valid login/password" do
- expect(gl_auth.find_with_user_password(username, password)).to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).to eql user
end
it 'finds user by valid email/password with case-insensitive email' do
- expect(gl_auth.find_with_user_password(user.email.upcase, password)).to eql user
+ expect(gl_auth.find_with_user_password(user.email.upcase, user.password)).to eql user
end
it 'finds user by valid username/password with case-insensitive username' do
- expect(gl_auth.find_with_user_password(username.upcase, password)).to eql user
+ expect(gl_auth.find_with_user_password(username.upcase, user.password)).to eql user
end
it "does not find user with invalid password" do
- password = 'wrong'
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ expect(gl_auth.find_with_user_password(username, 'incorrect_password')).not_to eql user
end
it "does not find user with invalid login" do
- user = 'wrong'
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ username = 'wrong'
+ expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
include_examples 'user login operation with unique ip limit' do
def operation
- expect(gl_auth.find_with_user_password(username, password)).to eq(user)
+ expect(gl_auth.find_with_user_password(username, user.password)).to eq(user)
end
end
it 'finds the user in deactivated state' do
user.deactivate!
- expect(gl_auth.find_with_user_password(username, password)).to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).to eql user
end
it "does not find user in blocked state" do
user.block
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it 'does not find user in locked state' do
user.lock_access!
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it "does not find user in ldap_blocked state" do
user.ldap_block
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
it 'does not find user in blocked_pending_approval state' do
user.block_pending_approval
- expect(gl_auth.find_with_user_password(username, password)).not_to eql user
+ expect(gl_auth.find_with_user_password(username, user.password)).not_to eql user
end
context 'with increment_failed_attempts' do
@@ -917,7 +906,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user.save!
expect do
- gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
+ gl_auth.find_with_user_password(username, user.password, increment_failed_attempts: true)
user.reload
end.to change(user, :failed_attempts).from(2).to(0)
end
@@ -946,7 +935,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
user.save!
expect do
- gl_auth.find_with_user_password(username, password, increment_failed_attempts: true)
+ gl_auth.find_with_user_password(username, user.password, increment_failed_attempts: true)
user.reload
end.not_to change(user, :failed_attempts)
end
@@ -961,7 +950,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it "tries to autheticate with db before ldap" do
expect(Gitlab::Auth::Ldap::Authentication).not_to receive(:login)
- expect(gl_auth.find_with_user_password(username, password)).to eq(user)
+ expect(gl_auth.find_with_user_password(username, user.password)).to eq(user)
end
it "does not find user by using ldap as fallback to for authentication" do
@@ -983,7 +972,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it "does not find user by valid login/password" do
- expect(gl_auth.find_with_user_password(username, password)).to be_nil
+ expect(gl_auth.find_with_user_password(username, user.password)).to be_nil
end
context "with ldap enabled" do
@@ -992,7 +981,7 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end
it "does not find non-ldap user by valid login/password" do
- expect(gl_auth.find_with_user_password(username, password)).to be_nil
+ expect(gl_auth.find_with_user_password(username, user.password)).to be_nil
end
end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_ci_namespace_mirrors_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_namespace_mirrors_spec.rb
deleted file mode 100644
index 8980a26932b..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_ci_namespace_mirrors_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillCiNamespaceMirrors, :migration, schema: 20211208122200 do
- let(:namespaces) { table(:namespaces) }
- let(:ci_namespace_mirrors) { table(:ci_namespace_mirrors) }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'creates hierarchies for all namespaces in range' do
- namespaces.create!(id: 5, name: 'test1', path: 'test1')
- namespaces.create!(id: 7, name: 'test2', path: 'test2')
- namespaces.create!(id: 8, name: 'test3', path: 'test3')
-
- subject.perform(5, 7)
-
- expect(ci_namespace_mirrors.all).to contain_exactly(
- an_object_having_attributes(namespace_id: 5, traversal_ids: [5]),
- an_object_having_attributes(namespace_id: 7, traversal_ids: [7])
- )
- end
-
- it 'handles existing hierarchies gracefully' do
- namespaces.create!(id: 5, name: 'test1', path: 'test1')
- test2 = namespaces.create!(id: 7, name: 'test2', path: 'test2')
- namespaces.create!(id: 8, name: 'test3', path: 'test3', parent_id: 7)
- namespaces.create!(id: 9, name: 'test4', path: 'test4')
-
- # Simulate a situation where a user has had a chance to move a group to another parent
- # before the background migration has had a chance to run
- test2.update!(parent_id: 5)
- ci_namespace_mirrors.create!(namespace_id: test2.id, traversal_ids: [5, 7])
-
- subject.perform(5, 8)
-
- expect(ci_namespace_mirrors.all).to contain_exactly(
- an_object_having_attributes(namespace_id: 5, traversal_ids: [5]),
- an_object_having_attributes(namespace_id: 7, traversal_ids: [5, 7]),
- an_object_having_attributes(namespace_id: 8, traversal_ids: [5, 7, 8])
- )
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_ci_project_mirrors_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_project_mirrors_spec.rb
deleted file mode 100644
index 4eec83879e3..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_ci_project_mirrors_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillCiProjectMirrors, :migration, schema: 20211208122201 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:ci_project_mirrors) { table(:ci_project_mirrors) }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'creates ci_project_mirrors for all projects in range' do
- namespaces.create!(id: 10, name: 'namespace1', path: 'namespace1')
- projects.create!(id: 5, namespace_id: 10, name: 'test1', path: 'test1')
- projects.create!(id: 7, namespace_id: 10, name: 'test2', path: 'test2')
- projects.create!(id: 8, namespace_id: 10, name: 'test3', path: 'test3')
-
- subject.perform(5, 7)
-
- expect(ci_project_mirrors.all).to contain_exactly(
- an_object_having_attributes(project_id: 5, namespace_id: 10),
- an_object_having_attributes(project_id: 7, namespace_id: 10)
- )
- end
-
- it 'handles existing ci_project_mirrors gracefully' do
- namespaces.create!(id: 10, name: 'namespace1', path: 'namespace1')
- namespaces.create!(id: 11, name: 'namespace2', path: 'namespace2', parent_id: 10)
- projects.create!(id: 5, namespace_id: 10, name: 'test1', path: 'test1')
- projects.create!(id: 7, namespace_id: 11, name: 'test2', path: 'test2')
- projects.create!(id: 8, namespace_id: 11, name: 'test3', path: 'test3')
-
- # Simulate a situation where a user has had a chance to move a project to another namespace
- # before the background migration has had a chance to run
- ci_project_mirrors.create!(project_id: 7, namespace_id: 10)
-
- subject.perform(5, 7)
-
- expect(ci_project_mirrors.all).to contain_exactly(
- an_object_having_attributes(project_id: 5, namespace_id: 10),
- an_object_having_attributes(project_id: 7, namespace_id: 10)
- )
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb
index 1aac5970a77..aaf8c124a83 100644
--- a/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_ci_queuing_tables_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillCiQueuingTables, :migration, schema: 20220208115439 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillCiQueuingTables, :migration,
+ :suppress_gitlab_schemas_validate_connection, schema: 20220208115439 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:ci_cd_settings) { table(:project_ci_cd_settings) }
diff --git a/spec/lib/gitlab/background_migration/backfill_ci_runner_semver_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_runner_semver_spec.rb
deleted file mode 100644
index 7c78d8b0305..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_ci_runner_semver_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillCiRunnerSemver, :migration, schema: 20220601151900 do
- let(:ci_runners) { table(:ci_runners, database: :ci) }
-
- subject do
- described_class.new(
- start_id: 10,
- end_id: 15,
- batch_table: :ci_runners,
- batch_column: :id,
- sub_batch_size: 10,
- pause_ms: 0,
- connection: Ci::ApplicationRecord.connection)
- end
-
- describe '#perform' do
- it 'populates semver column on all runners in range' do
- ci_runners.create!(id: 10, runner_type: 1, version: %q(HEAD-fd84d97))
- ci_runners.create!(id: 11, runner_type: 1, version: %q(v1.2.3))
- ci_runners.create!(id: 12, runner_type: 1, version: %q(2.1.0))
- ci_runners.create!(id: 13, runner_type: 1, version: %q(11.8.0~beta.935.g7f6d2abc))
- ci_runners.create!(id: 14, runner_type: 1, version: %q(13.2.2/1.1.0))
- ci_runners.create!(id: 15, runner_type: 1, version: %q('14.3.4'))
-
- subject.perform
-
- expect(ci_runners.all).to contain_exactly(
- an_object_having_attributes(id: 10, semver: nil),
- an_object_having_attributes(id: 11, semver: '1.2.3'),
- an_object_having_attributes(id: 12, semver: '2.1.0'),
- an_object_having_attributes(id: 13, semver: '11.8.0'),
- an_object_having_attributes(id: 14, semver: '13.2.2'),
- an_object_having_attributes(id: 15, semver: '14.3.4')
- )
- end
-
- it 'skips runners that already have semver value' do
- ci_runners.create!(id: 10, runner_type: 1, version: %q(1.2.4), semver: '1.2.3')
- ci_runners.create!(id: 11, runner_type: 1, version: %q(1.2.5))
- ci_runners.create!(id: 12, runner_type: 1, version: %q(HEAD), semver: '1.2.4')
-
- subject.perform
-
- expect(ci_runners.all).to contain_exactly(
- an_object_having_attributes(id: 10, semver: '1.2.3'),
- an_object_having_attributes(id: 11, semver: '1.2.5'),
- an_object_having_attributes(id: 12, semver: '1.2.4')
- )
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
index d84bc479554..e0be5a785b8 100644
--- a/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillGroupFeatures, :migration, s
batch_column: :id,
sub_batch_size: 10,
pause_ms: 0,
+ job_arguments: [4],
connection: ActiveRecord::Base.connection)
end
@@ -27,7 +28,7 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillGroupFeatures, :migration, s
group_features.create!(id: 1, group_id: 4)
expect(group_features.count).to eq 1
- expect { subject.perform(4) }.to change { group_features.count }.by(2)
+ expect { subject.perform }.to change { group_features.count }.by(2)
expect(group_features.count).to eq 3
expect(group_features.all.pluck(:group_id)).to contain_exactly(1, 3, 4)
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb
new file mode 100644
index 00000000000..564aa3b8c01
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdOfVulnerabilityReads, schema: 20220722145845 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:users) { table(:users) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_reads) { table(:vulnerability_reads) }
+
+ let(:namespace) { namespaces.create!(name: 'user', path: 'user') }
+ let(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) }
+ let(:user) { users.create!(username: 'john_doe', email: 'johndoe@gitlab.com', projects_limit: 10) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'external_id', name: 'Test Scanner') }
+ let(:vulnerability) do
+ vulnerabilities.create!(
+ project_id: project.id,
+ author_id: user.id,
+ title: 'test',
+ severity: 1,
+ confidence: 1,
+ report_type: 1
+ )
+ end
+
+ let(:vulnerability_read) do
+ vulnerability_reads.create!(
+ project_id: project.id,
+ vulnerability_id: vulnerability.id,
+ scanner_id: scanner.id,
+ severity: 1,
+ report_type: 1,
+ state: 1,
+ uuid: SecureRandom.uuid
+ )
+ end
+
+ subject(:perform_migration) do
+ described_class.new(start_id: vulnerability_read.vulnerability_id,
+ end_id: vulnerability_read.vulnerability_id,
+ batch_table: :vulnerability_reads,
+ batch_column: :vulnerability_id,
+ sub_batch_size: 1,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection)
+ .perform
+ end
+
+ it 'sets the namespace_id of existing record' do
+ expect { perform_migration }.to change { vulnerability_read.reload.namespace_id }.from(nil).to(namespace.id)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb
new file mode 100644
index 00000000000..ae296483166
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_project_import_level_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+# rubocop:disable Layout/HashAlignment
+RSpec.describe Gitlab::BackgroundMigration::BackfillProjectImportLevel do
+ let(:migration) do
+ described_class.new(
+ start_id: table(:namespaces).minimum(:id),
+ end_id: table(:namespaces).maximum(:id),
+ batch_table: :namespaces,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ )
+ end
+ # rubocop:enable Layout/HashAlignment
+
+ let(:namespaces_table) { table(:namespaces) }
+ let(:namespace_settings_table) { table(:namespace_settings) }
+
+ let!(:user_namespace) do
+ namespaces_table.create!(
+ name: 'user_namespace',
+ path: 'user_namespace',
+ type: 'User',
+ project_creation_level: 100
+ )
+ end
+
+ let!(:group_namespace_nil) do
+ namespaces_table.create!(
+ name: 'group_namespace_nil',
+ path: 'group_namespace_nil',
+ type: 'Group',
+ project_creation_level: nil
+ )
+ end
+
+ let!(:group_namespace_0) do
+ namespaces_table.create!(
+ name: 'group_namespace_0',
+ path: 'group_namespace_0',
+ type: 'Group',
+ project_creation_level: 0
+ )
+ end
+
+ let!(:group_namespace_1) do
+ namespaces_table.create!(
+ name: 'group_namespace_1',
+ path: 'group_namespace_1',
+ type: 'Group',
+ project_creation_level: 1
+ )
+ end
+
+ let!(:group_namespace_2) do
+ namespaces_table.create!(
+ name: 'group_namespace_2',
+ path: 'group_namespace_2',
+ type: 'Group',
+ project_creation_level: 2
+ )
+ end
+
+ let!(:group_namespace_9999) do
+ namespaces_table.create!(
+ name: 'group_namespace_9999',
+ path: 'group_namespace_9999',
+ type: 'Group',
+ project_creation_level: 9999
+ )
+ end
+
+ subject(:perform_migration) { migration.perform }
+
+ before do
+ namespace_settings_table.create!(namespace_id: user_namespace.id)
+ namespace_settings_table.create!(namespace_id: group_namespace_nil.id)
+ namespace_settings_table.create!(namespace_id: group_namespace_0.id)
+ namespace_settings_table.create!(namespace_id: group_namespace_1.id)
+ namespace_settings_table.create!(namespace_id: group_namespace_2.id)
+ namespace_settings_table.create!(namespace_id: group_namespace_9999.id)
+ end
+
+ describe 'Groups' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:namespace_id, :prev_level, :new_level) do
+ lazy { group_namespace_0.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::NO_ACCESS
+ lazy { group_namespace_1.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::MAINTAINER
+ lazy { group_namespace_2.id } | ::Gitlab::Access::OWNER | ::Gitlab::Access::DEVELOPER
+ end
+
+ with_them do
+ it 'backfills the correct project_import_level of Group namespaces' do
+ expect { perform_migration }
+ .to change { namespace_settings_table.find_by(namespace_id: namespace_id).project_import_level }
+ .from(prev_level).to(new_level)
+ end
+ end
+
+ it 'does not update `User` namespaces or values outside range' do
+ expect { perform_migration }
+ .not_to change { namespace_settings_table.find_by(namespace_id: user_namespace.id).project_import_level }
+
+ expect { perform_migration }
+ .not_to change { namespace_settings_table.find_by(namespace_id: group_namespace_9999.id).project_import_level }
+ end
+
+ it 'maintains default import_level if creation_level is nil' do
+ project_import_level = namespace_settings_table.find_by(namespace_id: group_namespace_nil.id).project_import_level
+
+ expect { perform_migration }
+ .not_to change { project_import_level }
+
+ expect(project_import_level).to eq(::Gitlab::Access::OWNER)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb b/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb
index 49056154744..4a65ecf8c75 100644
--- a/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectsWithCoverage, schema: 20210818185845 do
+RSpec.describe Gitlab::BackgroundMigration::BackfillProjectsWithCoverage,
+ :suppress_gitlab_schemas_validate_connection, schema: 20210818185845 do
let(:projects) { table(:projects) }
let(:project_ci_feature_usages) { table(:project_ci_feature_usages) }
let(:ci_pipelines) { table(:ci_pipelines) }
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index b5122af5cd4..6f75d3faef3 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat
let(:file_name) { 'file_name.rb' }
let(:content) { 'content' }
- let(:ids) { snippets.pluck('MIN(id)', 'MAX(id)').first }
+ let(:ids) { snippets.pick('MIN(id)', 'MAX(id)') }
let(:service) { described_class.new }
subject { service.perform(*ids) }
diff --git a/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb b/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb
new file mode 100644
index 00000000000..79699375a8d
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityReadsClusterAgent, :migration, schema: 20220525221133 do # rubocop:disable Layout/LineLength
+ let(:migration) do
+ described_class.new(start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection)
+ end
+
+ let(:users_table) { table(:users) }
+ let(:vulnerability_reads_table) { table(:vulnerability_reads) }
+ let(:vulnerability_scanners_table) { table(:vulnerability_scanners) }
+ let(:vulnerabilities_table) { table(:vulnerabilities) }
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:cluster_agents_table) { table(:cluster_agents) }
+
+ let(:table_name) { 'vulnerability_reads' }
+ let(:batch_column) { :id }
+ let(:sub_batch_size) { 1_000 }
+ let(:pause_ms) { 0 }
+
+ subject(:perform_migration) { migration.perform }
+
+ before do
+ users_table.create!(id: 1, name: 'John Doe', email: 'test@example.com', projects_limit: 5)
+
+ namespaces_table.create!(id: 1, name: 'Namespace 1', path: 'namespace-1')
+ namespaces_table.create!(id: 2, name: 'Namespace 2', path: 'namespace-2')
+
+ projects_table.create!(id: 1, namespace_id: 1, name: 'Project 1', path: 'project-1', project_namespace_id: 1)
+ projects_table.create!(id: 2, namespace_id: 2, name: 'Project 2', path: 'project-2', project_namespace_id: 2)
+
+ cluster_agents_table.create!(id: 1, name: 'Agent 1', project_id: 1)
+ cluster_agents_table.create!(id: 2, name: 'Agent 2', project_id: 2)
+
+ vulnerability_scanners_table.create!(id: 1, project_id: 1, external_id: 'starboard', name: 'Starboard')
+ vulnerability_scanners_table.create!(id: 2, project_id: 2, external_id: 'starboard', name: 'Starboard')
+
+ add_vulnerability_read!(1, project_id: 1, cluster_agent_id: 1, report_type: 7)
+ add_vulnerability_read!(3, project_id: 1, cluster_agent_id: 2, report_type: 7)
+ add_vulnerability_read!(5, project_id: 2, cluster_agent_id: 2, report_type: 5)
+ add_vulnerability_read!(7, project_id: 2, cluster_agent_id: 3, report_type: 7)
+ add_vulnerability_read!(9, project_id: 2, cluster_agent_id: 2, report_type: 7)
+ add_vulnerability_read!(10, project_id: 1, cluster_agent_id: 1, report_type: 7)
+ add_vulnerability_read!(11, project_id: 1, cluster_agent_id: 1, report_type: 7)
+ end
+
+ it 'backfills `casted_cluster_agent_id` for the selected records', :aggregate_failures do
+ queries = ActiveRecord::QueryRecorder.new do
+ perform_migration
+ end
+
+ expect(queries.count).to eq(3)
+ expect(vulnerability_reads_table.where.not(casted_cluster_agent_id: nil).count).to eq 3
+ expect(vulnerability_reads_table.where.not(casted_cluster_agent_id: nil).pluck(:id)).to match_array([1, 9, 10])
+ end
+
+ it 'tracks timings of queries' do
+ expect(migration.batch_metrics.timings).to be_empty
+
+ expect { perform_migration }.to change { migration.batch_metrics.timings }
+ end
+
+ private
+
+ def add_vulnerability_read!(id, project_id:, cluster_agent_id:, report_type:)
+ vulnerabilities_table.create!(
+ id: id,
+ project_id: project_id,
+ author_id: 1,
+ title: "Vulnerability #{id}",
+ severity: 5,
+ confidence: 5,
+ report_type: report_type
+ )
+
+ vulnerability_reads_table.create!(
+ id: id,
+ uuid: SecureRandom.uuid,
+ severity: 5,
+ state: 1,
+ vulnerability_id: id,
+ scanner_id: project_id,
+ cluster_agent_id: cluster_agent_id.to_s,
+ project_id: project_id,
+ report_type: report_type
+ )
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb b/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb
index 98866bb765f..f03f90ddbbb 100644
--- a/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb
+++ b/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb
@@ -3,6 +3,113 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BatchedMigrationJob do
+ let(:connection) { Gitlab::Database.database_base_models[:main].connection }
+
+ describe '.generic_instance' do
+ it 'defines generic instance with only some of the attributes set' do
+ generic_instance = described_class.generic_instance(
+ batch_table: 'projects', batch_column: 'id',
+ job_arguments: %w(x y), connection: connection
+ )
+
+ expect(generic_instance.send(:batch_table)).to eq('projects')
+ expect(generic_instance.send(:batch_column)).to eq('id')
+ expect(generic_instance.instance_variable_get('@job_arguments')).to eq(%w(x y))
+ expect(generic_instance.send(:connection)).to eq(connection)
+
+ %i(start_id end_id sub_batch_size pause_ms).each do |attr|
+ expect(generic_instance.send(attr)).to eq(0)
+ end
+ end
+ end
+
+ describe '.job_arguments' do
+ let(:job_class) do
+ Class.new(described_class) do
+ job_arguments :value_a, :value_b
+ end
+ end
+
+ subject(:job_instance) do
+ job_class.new(start_id: 1, end_id: 10,
+ batch_table: '_test_table',
+ batch_column: 'id',
+ sub_batch_size: 2,
+ pause_ms: 1000,
+ job_arguments: %w(a b),
+ connection: connection)
+ end
+
+ it 'defines methods' do
+ expect(job_instance.value_a).to eq('a')
+ expect(job_instance.value_b).to eq('b')
+ expect(job_class.job_arguments_count).to eq(2)
+ end
+
+ context 'when no job arguments are defined' do
+ let(:job_class) do
+ Class.new(described_class)
+ end
+
+ it 'job_arguments_count is 0' do
+ expect(job_class.job_arguments_count).to eq(0)
+ end
+ end
+ end
+
+ describe '.scope_to' do
+ subject(:job_instance) do
+ job_class.new(start_id: 1, end_id: 10,
+ batch_table: '_test_table',
+ batch_column: 'id',
+ sub_batch_size: 2,
+ pause_ms: 1000,
+ job_arguments: %w(a b),
+ connection: connection)
+ end
+
+ context 'when additional scoping is defined' do
+ let(:job_class) do
+ Class.new(described_class) do
+ job_arguments :value_a, :value_b
+ scope_to ->(r) { "#{r}-#{value_a}-#{value_b}".upcase }
+ end
+ end
+
+ it 'applies additional scope to the provided relation' do
+ expect(job_instance.filter_batch('relation')).to eq('RELATION-A-B')
+ end
+ end
+
+ context 'when there is no additional scoping defined' do
+ let(:job_class) do
+ Class.new(described_class) do
+ end
+ end
+
+ it 'returns provided relation as is' do
+ expect(job_instance.filter_batch('relation')).to eq('relation')
+ end
+ end
+ end
+
+ describe 'descendants', :eager_load do
+ it 'have the same method signature for #perform' do
+ expected_arity = described_class.instance_method(:perform).arity
+ offences = described_class.descendants.select { |klass| klass.instance_method(:perform).arity != expected_arity }
+
+ expect(offences).to be_empty, "expected no descendants of #{described_class} to accept arguments for " \
+ "'#perform', but some do: #{offences.join(", ")}"
+ end
+
+ it 'do not use .batching_scope' do
+ offences = described_class.descendants.select { |klass| klass.respond_to?(:batching_scope) }
+
+ expect(offences).to be_empty, "expected no descendants of #{described_class} to define '.batching_scope', " \
+ "but some do: #{offences.join(", ")}"
+ end
+ end
+
describe '#perform' do
let(:connection) { Gitlab::Database.database_base_models[:main].connection }
@@ -66,6 +173,30 @@ RSpec.describe Gitlab::BackgroundMigration::BatchedMigrationJob do
expect(test_table.order(:id).pluck(:to_column)).to contain_exactly(5, 10, nil, 20)
end
+ context 'with additional scoping' do
+ let(:job_class) do
+ Class.new(described_class) do
+ scope_to ->(r) { r.where('mod(id, 2) = 0') }
+
+ def perform(*job_arguments)
+ each_sub_batch(
+ operation_name: :update,
+ batching_arguments: { order_hint: :updated_at },
+ batching_scope: -> (relation) { relation.where.not(bar: nil) }
+ ) do |sub_batch|
+ sub_batch.update_all('to_column = from_column')
+ end
+ end
+ end
+ end
+
+ it 'respects #filter_batch' do
+ expect { perform_job }.to change { test_table.where(to_column: nil).count }.from(4).to(2)
+
+ expect(test_table.order(:id).pluck(:to_column)).to contain_exactly(nil, 10, nil, 20)
+ end
+ end
+
it 'instruments the batch operation' do
expect(job_instance.batch_metrics.affected_rows).to be_empty
@@ -84,7 +215,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchedMigrationJob do
context 'when batching_arguments are given' do
it 'forwards them for batching' do
- expect(job_instance).to receive(:parent_batch_relation).and_return(test_table)
+ expect(job_instance).to receive(:base_relation).and_return(test_table)
expect(test_table).to receive(:each_batch).with(column: 'id', of: 2, order_hint: :updated_at)
@@ -155,6 +286,24 @@ RSpec.describe Gitlab::BackgroundMigration::BatchedMigrationJob do
expect(job_instance.batch_metrics.affected_rows[:insert]).to contain_exactly(2, 1)
end
+
+ context 'when used in combination with scope_to' do
+ let(:job_class) do
+ Class.new(described_class) do
+ scope_to ->(r) { r.where.not(from_column: 10) }
+
+ def perform(*job_arguments)
+ distinct_each_batch(operation_name: :insert) do |sub_batch|
+ end
+ end
+ end
+ end
+
+ it 'raises an error' do
+ expect { perform_job }.to raise_error RuntimeError,
+ /distinct_each_batch can not be used when additional filters are defined with scope_to/
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
index 943b5744b64..9fdd7bf8adc 100644
--- a/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
+++ b/spec/lib/gitlab/background_migration/batching_strategies/primary_key_batching_strategy_spec.rb
@@ -45,19 +45,16 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
end
end
- context 'when job_class is provided with a batching_scope' do
+ context 'when job class supports batch scope DSL' do
let(:job_class) do
- Class.new(described_class) do
- def self.batching_scope(relation, job_arguments:)
- min_id = job_arguments.first
-
- relation.where.not(type: 'Project').where('id >= ?', min_id)
- end
+ Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do
+ job_arguments :min_id
+ scope_to ->(r) { r.where.not(type: 'Project').where('id >= ?', min_id) }
end
end
- it 'applies the batching scope' do
- expect(job_class).to receive(:batching_scope).and_call_original
+ it 'applies the additional scope' do
+ expect(job_class).to receive(:generic_instance).and_call_original
batch_bounds = batching_strategy.next_batch(:namespaces, :id, batch_min_value: namespace4.id, batch_size: 3, job_arguments: [1], job_class: job_class)
diff --git a/spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb b/spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb
deleted file mode 100644
index db822f36c21..00000000000
--- a/spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::CopyCiBuildsColumnsToSecurityScans, schema: 20210728174349 do
- let(:migration) { described_class.new }
-
- let_it_be(:namespaces) { table(:namespaces) }
- let_it_be(:projects) { table(:projects) }
- let_it_be(:ci_pipelines) { table(:ci_pipelines) }
- let_it_be(:ci_builds) { table(:ci_builds) }
- let_it_be(:security_scans) { table(:security_scans) }
-
- let!(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
- let!(:project1) { projects.create!(namespace_id: namespace.id) }
- let!(:project2) { projects.create!(namespace_id: namespace.id) }
- let!(:pipeline1) { ci_pipelines.create!(status: "success")}
- let!(:pipeline2) { ci_pipelines.create!(status: "success")}
-
- let!(:build1) { ci_builds.create!(commit_id: pipeline1.id, type: 'Ci::Build', project_id: project1.id) }
- let!(:build2) { ci_builds.create!(commit_id: pipeline2.id, type: 'Ci::Build', project_id: project2.id) }
- let!(:build3) { ci_builds.create!(commit_id: pipeline1.id, type: 'Ci::Build', project_id: project1.id) }
-
- let!(:scan1) { security_scans.create!(build_id: build1.id, scan_type: 1) }
- let!(:scan2) { security_scans.create!(build_id: build2.id, scan_type: 1) }
- let!(:scan3) { security_scans.create!(build_id: build3.id, scan_type: 1) }
-
- subject { migration.perform(scan1.id, scan2.id) }
-
- before do
- stub_const("#{described_class}::UPDATE_BATCH_SIZE", 2)
- end
-
- it 'copies `project_id`, `commit_id` from `ci_builds` to `security_scans`', :aggregate_failures do
- expect(migration).to receive(:mark_job_as_succeeded).with(scan1.id, scan2.id)
-
- subject
-
- scan1.reload
- expect(scan1.project_id).to eq(project1.id)
- expect(scan1.pipeline_id).to eq(pipeline1.id)
-
- scan2.reload
- expect(scan2.project_id).to eq(project2.id)
- expect(scan2.pipeline_id).to eq(pipeline2.id)
-
- scan3.reload
- expect(scan3.project_id).to be_nil
- expect(scan3.pipeline_id).to be_nil
- end
-end
diff --git a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
index 78bd1afd8d2..9c33100a0b3 100644
--- a/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
+++ b/spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
ActiveRecord::Migration.new.extend(Gitlab::Database::MigrationHelpers)
end
+ let(:job_arguments) { %w(name name_convert_to_text) }
let(:copy_job) do
described_class.new(start_id: 12,
end_id: 20,
@@ -23,6 +24,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
batch_column: 'id',
sub_batch_size: sub_batch_size,
pause_ms: pause_ms,
+ job_arguments: job_arguments,
connection: connection)
end
@@ -53,32 +55,42 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
SQL
end
- it 'copies all primary keys in range' do
- temporary_column = helpers.convert_to_bigint_column(:id)
+ context 'primary keys' do
+ let(:temporary_column) { helpers.convert_to_bigint_column(:id) }
+ let(:job_arguments) { ['id', temporary_column] }
- copy_job.perform('id', temporary_column)
+ it 'copies all in range' do
+ copy_job.perform
- expect(test_table.count).to eq(4)
- expect(test_table.where("id = #{temporary_column}").pluck(:id)).to contain_exactly(12, 15, 19)
- expect(test_table.where(temporary_column => 0).pluck(:id)).to contain_exactly(11)
+ expect(test_table.count).to eq(4)
+ expect(test_table.where("id = #{temporary_column}").pluck(:id)).to contain_exactly(12, 15, 19)
+ expect(test_table.where(temporary_column => 0).pluck(:id)).to contain_exactly(11)
+ end
end
- it 'copies all foreign keys in range' do
- temporary_column = helpers.convert_to_bigint_column(:fk)
+ context 'foreign keys' do
+ let(:temporary_column) { helpers.convert_to_bigint_column(:fk) }
+ let(:job_arguments) { ['fk', temporary_column] }
- copy_job.perform('fk', temporary_column)
+ it 'copies all in range' do
+ copy_job.perform
- expect(test_table.count).to eq(4)
- expect(test_table.where("fk = #{temporary_column}").pluck(:id)).to contain_exactly(12, 15, 19)
- expect(test_table.where(temporary_column => 0).pluck(:id)).to contain_exactly(11)
+ expect(test_table.count).to eq(4)
+ expect(test_table.where("fk = #{temporary_column}").pluck(:id)).to contain_exactly(12, 15, 19)
+ expect(test_table.where(temporary_column => 0).pluck(:id)).to contain_exactly(11)
+ end
end
- it 'copies columns with NULLs' do
- expect { copy_job.perform('name', 'name_convert_to_text') }
- .to change { test_table.where("name_convert_to_text = 'no name'").count }.from(4).to(1)
+ context 'columns with NULLs' do
+ let(:job_arguments) { %w(name name_convert_to_text) }
- expect(test_table.where('name = name_convert_to_text').pluck(:id)).to contain_exactly(12, 19)
- expect(test_table.where('name is NULL and name_convert_to_text is NULL').pluck(:id)).to contain_exactly(15)
+ it 'copies all in range' do
+ expect { copy_job.perform }
+ .to change { test_table.where("name_convert_to_text = 'no name'").count }.from(4).to(1)
+
+ expect(test_table.where('name = name_convert_to_text').pluck(:id)).to contain_exactly(12, 19)
+ expect(test_table.where('name is NULL and name_convert_to_text is NULL').pluck(:id)).to contain_exactly(15)
+ end
end
context 'when multiple columns are given' do
@@ -87,8 +99,10 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
let(:columns_to_copy_from) { %w[id fk] }
let(:columns_to_copy_to) { [id_tmp_column, fk_tmp_column] }
+ let(:job_arguments) { [columns_to_copy_from, columns_to_copy_to] }
+
it 'copies all values in the range' do
- copy_job.perform(columns_to_copy_from, columns_to_copy_to)
+ copy_job.perform
expect(test_table.count).to eq(4)
expect(test_table.where("id = #{id_tmp_column} AND fk = #{fk_tmp_column}").pluck(:id)).to contain_exactly(12, 15, 19)
@@ -100,7 +114,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
it 'raises an error' do
expect do
- copy_job.perform(columns_to_copy_from, columns_to_copy_to)
+ copy_job.perform
end.to raise_error(ArgumentError, 'number of source and destination columns must match')
end
end
@@ -109,7 +123,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
it 'tracks timings of queries' do
expect(copy_job.batch_metrics.timings).to be_empty
- copy_job.perform('name', 'name_convert_to_text')
+ copy_job.perform
expect(copy_job.batch_metrics.timings[:update_all]).not_to be_empty
end
@@ -120,7 +134,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
it 'sleeps for the specified time between sub-batches' do
expect(copy_job).to receive(:sleep).with(0.005)
- copy_job.perform('name', 'name_convert_to_text')
+ copy_job.perform
end
context 'when pause_ms value is negative' do
@@ -129,7 +143,7 @@ RSpec.describe Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJo
it 'treats it as a 0' do
expect(copy_job).to receive(:sleep).with(0)
- copy_job.perform('name', 'name_convert_to_text')
+ copy_job.perform
end
end
end
diff --git a/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb
new file mode 100644
index 00000000000..d20eaef3650
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::DisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects,
+ :migration,
+ schema: 20220722084543 do
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:project_settings_table) { table(:project_settings) }
+ let(:project_statistics_table) { table(:project_statistics) }
+ let(:issues_table) { table(:issues) }
+
+ subject(:perform_migration) do
+ described_class.new(start_id: projects_table.minimum(:id),
+ end_id: projects_table.maximum(:id),
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection)
+ .perform
+ end
+
+ it 'sets `legacy_open_source_license_available` to false only for public projects with no issues and no repo',
+ :aggregate_failures do
+ project_with_no_issues_no_repo = create_legacy_license_public_project('project-with-no-issues-no-repo')
+ project_with_repo = create_legacy_license_public_project('project-with-repo', repo_size: 1)
+ project_with_issues = create_legacy_license_public_project('project-with-issues', with_issue: true)
+ project_with_issues_and_repo =
+ create_legacy_license_public_project('project-with-issues-and-repo', repo_size: 1, with_issue: true)
+
+ queries = ActiveRecord::QueryRecorder.new { perform_migration }
+
+ expect(queries.count).to eq(7)
+ expect(migrated_attribute(project_with_no_issues_no_repo)).to be_falsey
+ expect(migrated_attribute(project_with_repo)).to be_truthy
+ expect(migrated_attribute(project_with_issues)).to be_truthy
+ expect(migrated_attribute(project_with_issues_and_repo)).to be_truthy
+ end
+
+ def create_legacy_license_public_project(path, repo_size: 0, with_issue: false)
+ namespace = namespaces_table.create!(name: "namespace-#{path}", path: "namespace-#{path}")
+ project_namespace =
+ namespaces_table.create!(name: "-project-namespace-#{path}", path: "project-namespace-#{path}", type: 'Project')
+ project = projects_table
+ .create!(
+ name: path, path: path, namespace_id: namespace.id,
+ project_namespace_id: project_namespace.id, visibility_level: 20
+ )
+
+ project_statistics_table.create!(project_id: project.id, namespace_id: namespace.id, repository_size: repo_size)
+ issues_table.create!(project_id: project.id) if with_issue
+ project_settings_table.create!(project_id: project.id, legacy_open_source_license_available: true)
+
+ project
+ end
+
+ def migrated_attribute(project)
+ project_settings_table.find(project.id).legacy_open_source_license_available
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb
new file mode 100644
index 00000000000..0dba1d7c8a2
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::DisableLegacyOpenSourceLicenseForOneMemberNoRepoProjects,
+ :migration,
+ schema: 20220721031446 do
+ let(:namespaces_table) { table(:namespaces) }
+ let(:projects_table) { table(:projects) }
+ let(:project_settings_table) { table(:project_settings) }
+ let(:project_statistics_table) { table(:project_statistics) }
+ let(:users_table) { table(:users) }
+ let(:project_authorizations_table) { table(:project_authorizations) }
+
+ subject(:perform_migration) do
+ described_class.new(start_id: projects_table.minimum(:id),
+ end_id: projects_table.maximum(:id),
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection)
+ .perform
+ end
+
+ it 'sets `legacy_open_source_license_available` to false only for public projects with 1 member and no repo',
+ :aggregate_failures do
+ project_with_no_repo_one_member = create_legacy_license_public_project('project-with-one-member-no-repo')
+ project_with_repo_one_member = create_legacy_license_public_project('project-with-repo', repo_size: 1)
+ project_with_no_repo_two_members = create_legacy_license_public_project('project-with-two-members', members: 2)
+ project_with_repo_two_members =
+ create_legacy_license_public_project('project-with-repo', repo_size: 1, members: 2)
+
+ queries = ActiveRecord::QueryRecorder.new { perform_migration }
+
+ expect(queries.count).to eq(7)
+ expect(migrated_attribute(project_with_no_repo_one_member)).to be_falsey
+ expect(migrated_attribute(project_with_repo_one_member)).to be_truthy
+ expect(migrated_attribute(project_with_no_repo_two_members)).to be_truthy
+ expect(migrated_attribute(project_with_repo_two_members)).to be_truthy
+ end
+
+ def create_legacy_license_public_project(path, repo_size: 0, members: 1)
+ namespace = namespaces_table.create!(name: "namespace-#{path}", path: "namespace-#{path}")
+ project_namespace =
+ namespaces_table.create!(name: "-project-namespace-#{path}", path: "project-namespace-#{path}", type: 'Project')
+ project = projects_table
+ .create!(
+ name: path, path: path, namespace_id: namespace.id,
+ project_namespace_id: project_namespace.id, visibility_level: 20
+ )
+
+ members.times do |member_id|
+ user = users_table.create!(email: "user#{member_id}-project-#{project.id}@gitlab.com", projects_limit: 100)
+ project_authorizations_table.create!(project_id: project.id, user_id: user.id, access_level: 50)
+ end
+ project_statistics_table.create!(project_id: project.id, namespace_id: namespace.id, repository_size: repo_size)
+ project_settings_table.create!(project_id: project.id, legacy_open_source_license_available: true)
+
+ project
+ end
+
+ def migrated_attribute(project)
+ project_settings_table.find(project.id).legacy_open_source_license_available
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb b/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb
index 7cc64889fc8..5fdd8683d06 100644
--- a/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::DropInvalidSecurityFindings, schema: 20211108211434 do
+RSpec.describe Gitlab::BackgroundMigration::DropInvalidSecurityFindings, :suppress_gitlab_schemas_validate_connection,
+ schema: 20211108211434 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user', type: Namespaces::UserNamespace.sti_name) }
let(:project) { table(:projects).create!(namespace_id: namespace.id) }
diff --git a/spec/lib/gitlab/background_migration/extract_project_topics_into_separate_table_spec.rb b/spec/lib/gitlab/background_migration/extract_project_topics_into_separate_table_spec.rb
index 65d55f85a98..51a09d50a19 100644
--- a/spec/lib/gitlab/background_migration/extract_project_topics_into_separate_table_spec.rb
+++ b/spec/lib/gitlab/background_migration/extract_project_topics_into_separate_table_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::ExtractProjectTopicsIntoSeparateTable, schema: 20210730104800 do
+RSpec.describe Gitlab::BackgroundMigration::ExtractProjectTopicsIntoSeparateTable,
+ :suppress_gitlab_schemas_validate_connection, schema: 20210730104800 do
it 'correctly extracts project topics into separate table' do
namespaces = table(:namespaces)
projects = table(:projects)
diff --git a/spec/lib/gitlab/background_migration/migrate_project_taggings_context_from_tags_to_topics_spec.rb b/spec/lib/gitlab/background_migration/migrate_project_taggings_context_from_tags_to_topics_spec.rb
index 5e2f32c54be..5495d786a48 100644
--- a/spec/lib/gitlab/background_migration/migrate_project_taggings_context_from_tags_to_topics_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_project_taggings_context_from_tags_to_topics_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::MigrateProjectTaggingsContextFromTagsToTopics, schema: 20210511095658 do
+RSpec.describe Gitlab::BackgroundMigration::MigrateProjectTaggingsContextFromTagsToTopics,
+ :suppress_gitlab_schemas_validate_connection, schema: 20210511095658 do
it 'correctly migrates project taggings context from tags to topics' do
taggings = table(:taggings)
diff --git a/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb b/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
index e38edfc3643..2f0eef3c399 100644
--- a/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
+++ b/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
@@ -2,12 +2,13 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::NullifyOrphanRunnerIdOnCiBuilds, :migration, schema: 20220223112304 do
+RSpec.describe Gitlab::BackgroundMigration::NullifyOrphanRunnerIdOnCiBuilds,
+ :suppress_gitlab_schemas_validate_connection, migration: :gitlab_ci, schema: 20220223112304 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
- let(:ci_runners) { table(:ci_runners, database: :ci) }
- let(:ci_pipelines) { table(:ci_pipelines, database: :ci) }
- let(:ci_builds) { table(:ci_builds, database: :ci) }
+ let(:ci_runners) { table(:ci_runners) }
+ let(:ci_pipelines) { table(:ci_pipelines) }
+ let(:ci_builds) { table(:ci_builds) }
subject { described_class.new }
@@ -20,7 +21,9 @@ RSpec.describe Gitlab::BackgroundMigration::NullifyOrphanRunnerIdOnCiBuilds, :mi
end
after do
- helpers.add_concurrent_foreign_key(:ci_builds, :ci_runners, column: :runner_id, on_delete: :nullify, validate: false)
+ helpers.add_concurrent_foreign_key(
+ :ci_builds, :ci_runners, column: :runner_id, on_delete: :nullify, validate: false
+ )
end
describe '#perform' do
diff --git a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
index 2ad561ead87..bff803e2035 100644
--- a/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
+++ b/spec/lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces_spec.rb
@@ -5,199 +5,211 @@ require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNamespaces, :migration, schema: 20220326161803 do
include MigrationsHelpers
- context 'when migrating data', :aggregate_failures do
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
+ RSpec.shared_examples 'backfills project namespaces' do
+ context 'when migrating data', :aggregate_failures do
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
- let(:parent_group1) { namespaces.create!(name: 'parent_group1', path: 'parent_group1', visibility_level: 20, type: 'Group') }
- let(:parent_group2) { namespaces.create!(name: 'test1', path: 'test1', runners_token: 'my-token1', project_creation_level: 1, visibility_level: 20, type: 'Group') }
+ let(:parent_group1) { namespaces.create!(name: 'parent_group1', path: 'parent_group1', visibility_level: 20, type: 'Group') }
+ let(:parent_group2) { namespaces.create!(name: 'test1', path: 'test1', runners_token: 'my-token1', project_creation_level: 1, visibility_level: 20, type: 'Group') }
- let(:parent_group1_project) { projects.create!(name: 'parent_group1_project', path: 'parent_group1_project', namespace_id: parent_group1.id, visibility_level: 20) }
- let(:parent_group2_project) { projects.create!(name: 'parent_group2_project', path: 'parent_group2_project', namespace_id: parent_group2.id, visibility_level: 20) }
+ let(:parent_group1_project) { projects.create!(name: 'parent_group1_project', path: 'parent_group1_project', namespace_id: parent_group1.id, visibility_level: 20) }
+ let(:parent_group2_project) { projects.create!(name: 'parent_group2_project', path: 'parent_group2_project', namespace_id: parent_group2.id, visibility_level: 20) }
- let(:child_nodes_count) { 2 }
- let(:tree_depth) { 3 }
+ let(:child_nodes_count) { 2 }
+ let(:tree_depth) { 3 }
- let(:backfilled_namespace) { nil }
+ let(:backfilled_namespace) { nil }
- before do
- BackfillProjectNamespaces::TreeGenerator.new(namespaces, projects, [parent_group1, parent_group2], child_nodes_count, tree_depth).build_tree
- end
-
- describe '#up' do
- shared_examples 'back-fill project namespaces' do
- it 'back-fills all project namespaces' do
- start_id = ::Project.minimum(:id)
- end_id = ::Project.maximum(:id)
- projects_count = ::Project.count
- batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
- project_namespaces_count = ::Namespace.where(type: 'Project').count
- migration = described_class.new
-
- expect(projects_count).not_to eq(project_namespaces_count)
- expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
- expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
- expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
-
- expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(Namespace.where(type: 'Project'), :count)
-
- expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
- check_projects_in_sync_with(Namespace.where(type: 'Project'))
- end
-
- context 'when passing specific group as parameter' do
- let(:backfilled_namespace) { parent_group1 }
-
- it 'back-fills project namespaces for the specified group hierarchy' do
- backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
- start_id = backfilled_namespace_projects.minimum(:id)
- end_id = backfilled_namespace_projects.maximum(:id)
- group_projects_count = backfilled_namespace_projects.count
- batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
- project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
+ before do
+ BackfillProjectNamespaces::TreeGenerator.new(namespaces, projects, [parent_group1, parent_group2], child_nodes_count, tree_depth).build_tree
+ end
+ describe '#up' do
+ shared_examples 'back-fill project namespaces' do
+ it 'back-fills all project namespaces' do
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ projects_count = ::Project.count
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
+ project_namespaces_count = ::Namespace.where(type: 'Project').count
migration = described_class.new
- expect(project_namespaces_in_hierarchy.count).to eq(0)
+ expect(projects_count).not_to eq(project_namespaces_count)
expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
- expect(group_projects_count).to eq(14)
- expect(project_namespaces_in_hierarchy.count).to eq(0)
-
- migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'up')
+ expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(Namespace.where(type: 'Project'), :count)
- expect(project_namespaces_in_hierarchy.count).to eq(14)
- check_projects_in_sync_with(project_namespaces_in_hierarchy)
+ expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
+ check_projects_in_sync_with(Namespace.where(type: 'Project'))
end
- end
- context 'when projects already have project namespaces' do
- before do
- hierarchy1_projects = base_ancestor(parent_group1).first.all_projects
- start_id = hierarchy1_projects.minimum(:id)
- end_id = hierarchy1_projects.maximum(:id)
+ context 'when passing specific group as parameter' do
+ let(:backfilled_namespace) { parent_group1 }
- described_class.new.perform(start_id, end_id, nil, nil, nil, nil, parent_group1.id, 'up')
- end
+ it 'back-fills project namespaces for the specified group hierarchy' do
+ backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
+ start_id = backfilled_namespace_projects.minimum(:id)
+ end_id = backfilled_namespace_projects.maximum(:id)
+ group_projects_count = backfilled_namespace_projects.count
+ batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
+ project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
- it 'does not duplicate project namespaces' do
- # check there are already some project namespaces but not for all
- projects_count = ::Project.count
- start_id = ::Project.minimum(:id)
- end_id = ::Project.maximum(:id)
- batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
- project_namespaces = ::Namespace.where(type: 'Project')
- migration = described_class.new
+ migration = described_class.new
- expect(project_namespaces_in_hierarchy(base_ancestor(parent_group1)).count).to be >= 14
- expect(project_namespaces_in_hierarchy(base_ancestor(parent_group2)).count).to eq(0)
- expect(projects_count).not_to eq(project_namespaces.count)
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
+ expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
- # run migration again to test we do not generate extra project namespaces
- expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
- expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
- expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
+ expect(group_projects_count).to eq(14)
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
- expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(project_namespaces, :count).by(14)
+ migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'up')
- expect(projects_count).to eq(project_namespaces.count)
+ expect(project_namespaces_in_hierarchy.count).to eq(14)
+ check_projects_in_sync_with(project_namespaces_in_hierarchy)
+ end
end
- end
- end
- it 'checks no project namespaces exist in the defined hierarchies' do
- hierarchy1_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group1))
- hierarchy2_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group2))
- hierarchy1_projects_count = base_ancestor(parent_group1).first.all_projects.count
- hierarchy2_projects_count = base_ancestor(parent_group2).first.all_projects.count
+ context 'when projects already have project namespaces' do
+ before do
+ hierarchy1_projects = base_ancestor(parent_group1).first.all_projects
+ start_id = hierarchy1_projects.minimum(:id)
+ end_id = hierarchy1_projects.maximum(:id)
+
+ described_class.new.perform(start_id, end_id, nil, nil, nil, nil, parent_group1.id, 'up')
+ end
+
+ it 'does not duplicate project namespaces' do
+ # check there are already some project namespaces but not for all
+ projects_count = ::Project.count
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
+ project_namespaces = ::Namespace.where(type: 'Project')
+ migration = described_class.new
+
+ expect(project_namespaces_in_hierarchy(base_ancestor(parent_group1)).count).to be >= 14
+ expect(project_namespaces_in_hierarchy(base_ancestor(parent_group2)).count).to eq(0)
+ expect(projects_count).not_to eq(project_namespaces.count)
+
+ # run migration again to test we do not generate extra project namespaces
+ expect(migration).to receive(:batch_insert_namespaces).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:batch_update_project_namespaces_traversal_ids).exactly(batches_count).and_call_original
+
+ expect { migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up') }.to change(project_namespaces, :count).by(14)
+
+ expect(projects_count).to eq(project_namespaces.count)
+ end
+ end
+ end
- expect(hierarchy1_project_namespaces).to be_empty
- expect(hierarchy2_project_namespaces).to be_empty
- expect(hierarchy1_projects_count).to eq(14)
- expect(hierarchy2_projects_count).to eq(14)
- end
+ it 'checks no project namespaces exist in the defined hierarchies' do
+ hierarchy1_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group1))
+ hierarchy2_project_namespaces = project_namespaces_in_hierarchy(base_ancestor(parent_group2))
+ hierarchy1_projects_count = base_ancestor(parent_group1).first.all_projects.count
+ hierarchy2_projects_count = base_ancestor(parent_group2).first.all_projects.count
- context 'back-fill project namespaces in a single batch' do
- it_behaves_like 'back-fill project namespaces'
- end
+ expect(hierarchy1_project_namespaces).to be_empty
+ expect(hierarchy2_project_namespaces).to be_empty
+ expect(hierarchy1_projects_count).to eq(14)
+ expect(hierarchy2_projects_count).to eq(14)
+ end
- context 'back-fill project namespaces in batches' do
- before do
- stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
+ context 'back-fill project namespaces in a single batch' do
+ it_behaves_like 'back-fill project namespaces'
end
- it_behaves_like 'back-fill project namespaces'
- end
- end
+ context 'back-fill project namespaces in batches' do
+ before do
+ stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
+ end
- describe '#down' do
- before do
- start_id = ::Project.minimum(:id)
- end_id = ::Project.maximum(:id)
- # back-fill first
- described_class.new.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up')
+ it_behaves_like 'back-fill project namespaces'
+ end
end
- shared_examples 'cleanup project namespaces' do
- it 'removes project namespaces' do
- projects_count = ::Project.count
+ describe '#down' do
+ before do
start_id = ::Project.minimum(:id)
end_id = ::Project.maximum(:id)
- migration = described_class.new
- batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
+ # back-fill first
+ described_class.new.perform(start_id, end_id, nil, nil, nil, nil, nil, 'up')
+ end
- expect(projects_count).to be > 0
- expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
+ shared_examples 'cleanup project namespaces' do
+ it 'removes project namespaces' do
+ projects_count = ::Project.count
+ start_id = ::Project.minimum(:id)
+ end_id = ::Project.maximum(:id)
+ migration = described_class.new
+ batches_count = (projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
- expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
- expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
+ expect(projects_count).to be > 0
+ expect(projects_count).to eq(::Namespace.where(type: 'Project').count)
- migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'down')
+ expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
- expect(::Project.count).to be > 0
- expect(::Namespace.where(type: 'Project').count).to eq(0)
- end
+ migration.perform(start_id, end_id, nil, nil, nil, nil, nil, 'down')
+
+ expect(::Project.count).to be > 0
+ expect(::Namespace.where(type: 'Project').count).to eq(0)
+ end
- context 'when passing specific group as parameter' do
- let(:backfilled_namespace) { parent_group1 }
+ context 'when passing specific group as parameter' do
+ let(:backfilled_namespace) { parent_group1 }
- it 'removes project namespaces only for the specific group hierarchy' do
- backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
- start_id = backfilled_namespace_projects.minimum(:id)
- end_id = backfilled_namespace_projects.maximum(:id)
- group_projects_count = backfilled_namespace_projects.count
- batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
- project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
- migration = described_class.new
+ it 'removes project namespaces only for the specific group hierarchy' do
+ backfilled_namespace_projects = base_ancestor(backfilled_namespace).first.all_projects
+ start_id = backfilled_namespace_projects.minimum(:id)
+ end_id = backfilled_namespace_projects.maximum(:id)
+ group_projects_count = backfilled_namespace_projects.count
+ batches_count = (group_projects_count / described_class::SUB_BATCH_SIZE.to_f).ceil
+ project_namespaces_in_hierarchy = project_namespaces_in_hierarchy(base_ancestor(backfilled_namespace))
+ migration = described_class.new
- expect(project_namespaces_in_hierarchy.count).to eq(14)
- expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
- expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
+ expect(project_namespaces_in_hierarchy.count).to eq(14)
+ expect(migration).to receive(:nullify_project_namespaces_in_projects).exactly(batches_count).and_call_original
+ expect(migration).to receive(:delete_project_namespace_records).exactly(batches_count).and_call_original
- migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'down')
+ migration.perform(start_id, end_id, nil, nil, nil, nil, backfilled_namespace.id, 'down')
- expect(::Namespace.where(type: 'Project').count).to be > 0
- expect(project_namespaces_in_hierarchy.count).to eq(0)
+ expect(::Namespace.where(type: 'Project').count).to be > 0
+ expect(project_namespaces_in_hierarchy.count).to eq(0)
+ end
end
end
- end
- context 'cleanup project namespaces in a single batch' do
- it_behaves_like 'cleanup project namespaces'
- end
-
- context 'cleanup project namespaces in batches' do
- before do
- stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
+ context 'cleanup project namespaces in a single batch' do
+ it_behaves_like 'cleanup project namespaces'
end
- it_behaves_like 'cleanup project namespaces'
+ context 'cleanup project namespaces in batches' do
+ before do
+ stub_const("#{described_class.name}::SUB_BATCH_SIZE", 2)
+ end
+
+ it_behaves_like 'cleanup project namespaces'
+ end
end
end
end
+ it_behaves_like 'backfills project namespaces'
+
+ context 'when namespaces.id is bigint' do
+ before do
+ namespaces.connection.execute("ALTER TABLE namespaces ALTER COLUMN id TYPE bigint")
+ end
+
+ it_behaves_like 'backfills project namespaces'
+ end
+
def base_ancestor(ancestor)
::Namespace.where(id: ancestor.id)
end
@@ -209,7 +221,7 @@ RSpec.describe Gitlab::BackgroundMigration::ProjectNamespaces::BackfillProjectNa
def check_projects_in_sync_with(namespaces)
project_namespaces_attrs = namespaces.order(:id).pluck(:id, :name, :path, :parent_id, :visibility_level, :shared_runners_enabled)
corresponding_projects_attrs = Project.where(project_namespace_id: project_namespaces_attrs.map(&:first))
- .order(:project_namespace_id).pluck(:project_namespace_id, :name, :path, :namespace_id, :visibility_level, :shared_runners_enabled)
+ .order(:project_namespace_id).pluck(:project_namespace_id, :name, :path, :namespace_id, :visibility_level, :shared_runners_enabled)
expect(project_namespaces_attrs).to eq(corresponding_projects_attrs)
end
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 8d71b117107..a609227be05 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
@@ -20,7 +20,7 @@ def create_background_migration_job(ids, status)
)
end
-RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid, schema: 20211124132705 do
+RSpec.describe Gitlab::BackgroundMigration::RecalculateVulnerabilitiesOccurrencesUuid, :suppress_gitlab_schemas_validate_connection, schema: 20211124132705 do
let(:background_migration_jobs) { table(:background_migration_jobs) }
let(:pending_jobs) { background_migration_jobs.where(status: Gitlab::Database::BackgroundMigrationJob.statuses['pending']) }
let(:succeeded_jobs) { background_migration_jobs.where(status: Gitlab::Database::BackgroundMigrationJob.statuses['succeeded']) }
diff --git a/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb b/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb
index 8cdcec9621c..eabc012f98b 100644
--- a/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_all_trace_expiration_dates_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RemoveAllTraceExpirationDates, :migration, schema: 20220131000001 do
+RSpec.describe Gitlab::BackgroundMigration::RemoveAllTraceExpirationDates, :migration,
+ :suppress_gitlab_schemas_validate_connection, schema: 20220131000001 do
subject(:perform) { migration.perform(1, 99) }
let(:migration) { described_class.new }
diff --git a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
index 07cff32304e..33ad74fbee8 100644
--- a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration, schema: 20220326161803 do
+RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration,
+ :suppress_gitlab_schemas_validate_connection, schema: 20220326161803 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
diff --git a/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
index 035ea6eadcf..e9f73672144 100644
--- a/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
@@ -4,14 +4,14 @@ require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::SetLegacyOpenSourceLicenseAvailableForNonPublicProjects,
:migration,
- schema: 20220520040416 do
+ schema: 20220722110026 do
let(:namespaces_table) { table(:namespaces) }
let(:projects_table) { table(:projects) }
let(:project_settings_table) { table(:project_settings) }
subject(:perform_migration) do
- described_class.new(start_id: 1,
- end_id: 30,
+ described_class.new(start_id: projects_table.minimum(:id),
+ end_id: projects_table.maximum(:id),
batch_table: :projects,
batch_column: :id,
sub_batch_size: 2,
@@ -20,35 +20,34 @@ RSpec.describe Gitlab::BackgroundMigration::SetLegacyOpenSourceLicenseAvailableF
.perform
end
- let(:queries) { ActiveRecord::QueryRecorder.new { perform_migration } }
+ it 'sets `legacy_open_source_license_available` attribute to false for non-public projects', :aggregate_failures do
+ private_project = create_legacy_license_project('private-project', visibility_level: 0)
+ internal_project = create_legacy_license_project('internal-project', visibility_level: 10)
+ public_project = create_legacy_license_project('public-project', visibility_level: 20)
- before do
- namespaces_table.create!(id: 1, name: 'namespace', path: 'namespace-path-1')
- namespaces_table.create!(id: 2, name: 'namespace', path: 'namespace-path-2', type: 'Project')
- namespaces_table.create!(id: 3, name: 'namespace', path: 'namespace-path-3', type: 'Project')
- namespaces_table.create!(id: 4, name: 'namespace', path: 'namespace-path-4', type: 'Project')
+ queries = ActiveRecord::QueryRecorder.new { perform_migration }
- projects_table
- .create!(id: 11, name: 'proj-1', path: 'path-1', namespace_id: 1, project_namespace_id: 2, visibility_level: 0)
- projects_table
- .create!(id: 12, name: 'proj-2', path: 'path-2', namespace_id: 1, project_namespace_id: 3, visibility_level: 10)
- projects_table
- .create!(id: 13, name: 'proj-3', path: 'path-3', namespace_id: 1, project_namespace_id: 4, visibility_level: 20)
+ expect(queries.count).to eq(5)
- project_settings_table.create!(project_id: 11, legacy_open_source_license_available: true)
- project_settings_table.create!(project_id: 12, legacy_open_source_license_available: true)
- project_settings_table.create!(project_id: 13, legacy_open_source_license_available: true)
+ expect(migrated_attribute(private_project)).to be_falsey
+ expect(migrated_attribute(internal_project)).to be_falsey
+ expect(migrated_attribute(public_project)).to be_truthy
end
- it 'sets `legacy_open_source_license_available` attribute to false for non-public projects', :aggregate_failures do
- expect(queries.count).to eq(3)
-
- expect(migrated_attribute(11)).to be_falsey
- expect(migrated_attribute(12)).to be_falsey
- expect(migrated_attribute(13)).to be_truthy
+ def create_legacy_license_project(path, visibility_level:)
+ namespace = namespaces_table.create!(name: "namespace-#{path}", path: "namespace-#{path}")
+ project_namespace = namespaces_table.create!(name: "project-namespace-#{path}", path: path, type: 'Project')
+ project = projects_table.create!(name: path,
+ path: path,
+ namespace_id: namespace.id,
+ project_namespace_id: project_namespace.id,
+ visibility_level: visibility_level)
+ project_settings_table.create!(project_id: project.id, legacy_open_source_license_available: true)
+
+ project
end
- def migrated_attribute(project_id)
- project_settings_table.find(project_id).legacy_open_source_license_available
+ def migrated_attribute(project)
+ project_settings_table.find(project.id).legacy_open_source_license_available
end
end
diff --git a/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
index b96d3f7f0b5..c090c1df424 100644
--- a/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -2,10 +2,26 @@
require 'spec_helper'
-RSpec.describe Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeBasedOnUrl, schema: 20210421163509 do
- let(:services_table) { table(:services) }
- let(:service_jira_cloud) { services_table.create!(id: 1, type: 'JiraService') }
- let(:service_jira_server) { services_table.create!(id: 2, type: 'JiraService') }
+RSpec.describe Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeBasedOnUrl do
+ let(:integrations_table) { table(:integrations) }
+ let(:service_jira_cloud) { integrations_table.create!(id: 1, type_new: 'JiraService') }
+ let(:service_jira_server) { integrations_table.create!(id: 2, type_new: 'JiraService') }
+ let(:service_jira_unknown) { integrations_table.create!(id: 3, type_new: 'JiraService') }
+
+ let(:table_name) { :jira_tracker_data }
+ let(:batch_column) { :id }
+ let(:sub_batch_size) { 1 }
+ let(:pause_ms) { 0 }
+ let(:migration) do
+ described_class.new(start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection)
+ end
+
+ subject(:perform_migration) do
+ migration.perform
+ end
before do
jira_tracker_data = Class.new(ApplicationRecord) do
@@ -27,18 +43,21 @@ RSpec.describe Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeB
end
stub_const('JiraTrackerData', jira_tracker_data)
- end
- let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, service_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: 0) }
- let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, service_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: 0) }
+ stub_const('UNKNOWN', 0)
+ stub_const('SERVER', 1)
+ stub_const('CLOUD', 2)
+ end
- subject { described_class.new.perform(tracker_data_cloud.id, tracker_data_server.id) }
+ let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, integration_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: UNKNOWN) }
+ let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, integration_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: UNKNOWN) }
+ let!(:tracker_data_unknown) { JiraTrackerData.create!(id: 3, integration_id: service_jira_unknown.id, url: "", deployment_type: UNKNOWN) }
it "changes unknown deployment_types based on URL" do
- expect(JiraTrackerData.pluck(:deployment_type)).to eq([0, 0])
+ expect(JiraTrackerData.pluck(:deployment_type)).to match_array([UNKNOWN, UNKNOWN, UNKNOWN])
- subject
+ perform_migration
- expect(JiraTrackerData.pluck(:deployment_type)).to eq([2, 1])
+ expect(JiraTrackerData.order(:id).pluck(:deployment_type)).to match_array([CLOUD, SERVER, UNKNOWN])
end
end
diff --git a/spec/lib/gitlab/background_task_spec.rb b/spec/lib/gitlab/background_task_spec.rb
new file mode 100644
index 00000000000..102556b6b2f
--- /dev/null
+++ b/spec/lib/gitlab/background_task_spec.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+# We need to capture task state from a closure, which requires instance variables.
+# rubocop: disable RSpec/InstanceVariable
+RSpec.describe Gitlab::BackgroundTask do
+ let(:options) { {} }
+ let(:task) do
+ proc do
+ @task_run = true
+ @task_thread = Thread.current
+ end
+ end
+
+ subject(:background_task) { described_class.new(task, **options) }
+
+ def expect_condition
+ Timeout.timeout(3) do
+ sleep 0.1 until yield
+ end
+ end
+
+ context 'when stopped' do
+ it 'is not running' do
+ expect(background_task).not_to be_running
+ end
+
+ describe '#start' do
+ it 'runs the given task on a background thread' do
+ test_thread = Thread.current
+
+ background_task.start
+
+ expect_condition { @task_run == true }
+ expect_condition { @task_thread != test_thread }
+ expect(background_task).to be_running
+ end
+
+ it 'returns self' do
+ expect(background_task.start).to be(background_task)
+ end
+
+ context 'when installing exit handler' do
+ it 'stops a running background task' do
+ expect(background_task).to receive(:at_exit).and_yield
+
+ background_task.start
+
+ expect(background_task).not_to be_running
+ end
+ end
+
+ context 'when task responds to start' do
+ let(:task_class) do
+ Struct.new(:started, :start_retval, :run) do
+ def start
+ self.started = true
+ self.start_retval
+ end
+
+ def call
+ self.run = true
+ end
+ end
+ end
+
+ let(:task) { task_class.new }
+
+ it 'calls start' do
+ background_task.start
+
+ expect_condition { task.started == true }
+ end
+
+ context 'when start returns true' do
+ it 'runs the task' do
+ task.start_retval = true
+
+ background_task.start
+
+ expect_condition { task.run == true }
+ end
+ end
+
+ context 'when start returns false' do
+ it 'does not run the task' do
+ task.start_retval = false
+
+ background_task.start
+
+ expect_condition { task.run.nil? }
+ end
+ end
+ end
+
+ context 'when synchronous is set to true' do
+ let(:options) { { synchronous: true } }
+
+ it 'calls join on the thread' do
+ # Thread has to be run in a block, expect_next_instance_of does not support this.
+ allow_any_instance_of(Thread).to receive(:join) # rubocop:disable RSpec/AnyInstanceOf
+
+ background_task.start
+
+ expect_condition { @task_run == true }
+ expect(@task_thread).to have_received(:join)
+ end
+ end
+ end
+
+ describe '#stop' do
+ it 'is a no-op' do
+ expect { background_task.stop }.not_to change { subject.running? }
+ expect_condition { @task_run.nil? }
+ end
+ end
+ end
+
+ context 'when running' do
+ before do
+ background_task.start
+ end
+
+ describe '#start' do
+ it 'raises an error' do
+ expect { background_task.start }.to raise_error(described_class::AlreadyStartedError)
+ end
+ end
+
+ describe '#stop' do
+ it 'stops running' do
+ expect { background_task.stop }.to change { subject.running? }.from(true).to(false)
+ end
+
+ context 'when task responds to stop' do
+ let(:task_class) do
+ Struct.new(:stopped, :call) do
+ def stop
+ self.stopped = true
+ end
+ end
+ end
+
+ let(:task) { task_class.new }
+
+ it 'calls stop' do
+ background_task.stop
+
+ expect_condition { task.stopped == true }
+ end
+ end
+
+ context 'when task stop raises an error' do
+ let(:error) { RuntimeError.new('task error') }
+ let(:options) { { name: 'test_background_task' } }
+
+ let(:task_class) do
+ Struct.new(:call, :error, keyword_init: true) do
+ def stop
+ raise error
+ end
+ end
+ end
+
+ let(:task) { task_class.new(error: error) }
+
+ it 'stops gracefully' do
+ expect { background_task.stop }.not_to raise_error
+ expect(background_task).not_to be_running
+ end
+
+ it 'reports the error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ error, { extra: { reported_by: 'test_background_task' } }
+ )
+
+ background_task.stop
+ end
+ end
+ end
+
+ context 'when task run raises exception' do
+ let(:error) { RuntimeError.new('task error') }
+ let(:options) { { name: 'test_background_task' } }
+ let(:task) do
+ proc do
+ @task_run = true
+ raise error
+ end
+ end
+
+ it 'stops gracefully' do
+ expect_condition { @task_run == true }
+ expect { background_task.stop }.not_to raise_error
+ expect(background_task).not_to be_running
+ end
+
+ it 'reports the error' do
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+ error, { extra: { reported_by: 'test_background_task' } }
+ )
+
+ background_task.stop
+ end
+ end
+ end
+end
+# rubocop: enable RSpec/InstanceVariable
diff --git a/spec/lib/gitlab/bare_repository_import/repository_spec.rb b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
index d29447ee376..becfdced5fb 100644
--- a/spec/lib/gitlab/bare_repository_import/repository_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
@@ -54,16 +54,16 @@ RSpec.describe ::Gitlab::BareRepositoryImport::Repository do
end
context 'hashed storage' do
- let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
let(:hashed_path) { "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" }
let(:root_path) { 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) }
+ let(:full_path) { 'to/repo' }
before do
raw_repository.create_repository
- raw_repository.set_full_path(full_path: 'to/repo')
+ raw_repository.set_full_path(full_path: full_path) if full_path
end
after do
@@ -95,16 +95,17 @@ RSpec.describe ::Gitlab::BareRepositoryImport::Repository do
expect(subject).not_to be_processable
end
- it 'returns false when group and project name are missing' do
- repository = Rugged::Repository.new(repo_path)
- repository.config.delete('gitlab.fullpath')
-
- expect(subject).not_to be_processable
- end
-
it 'returns true when group path and project name are present' do
expect(subject).to be_processable
end
+
+ context 'group and project name are missing' do
+ let(:full_path) { nil }
+
+ it 'returns false' do
+ expect(subject).not_to be_processable
+ end
+ end
end
describe '#project_full_path' do
diff --git a/spec/lib/gitlab/batch_pop_queueing_spec.rb b/spec/lib/gitlab/batch_pop_queueing_spec.rb
index 41efc5417e4..5af78ddabe7 100644
--- a/spec/lib/gitlab/batch_pop_queueing_spec.rb
+++ b/spec/lib/gitlab/batch_pop_queueing_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::BatchPopQueueing do
context 'when the queue key does not exist in Redis' do
before do
- allow(queue).to receive(:enqueue) { }
+ allow(queue).to receive(:enqueue) {}
end
it 'yields empty array' do
diff --git a/spec/lib/gitlab/chat_name_token_spec.rb b/spec/lib/gitlab/chat_name_token_spec.rb
index 906c02d54db..8d5702a6b27 100644
--- a/spec/lib/gitlab/chat_name_token_spec.rb
+++ b/spec/lib/gitlab/chat_name_token_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::ChatNameToken do
context 'when using unknown token' do
- let(:token) { }
+ let(:token) {}
subject { described_class.new(token).get }
diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb
index 27c2b005a93..30359a7170f 100644
--- a/spec/lib/gitlab/ci/ansi2html_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2html_spec.rb
@@ -210,8 +210,8 @@ RSpec.describe Gitlab::Ci::Ansi2html do
let(:section_start_time) { Time.new(2017, 9, 20).utc }
let(:section_duration) { 3.seconds }
let(:section_end_time) { section_start_time + section_duration }
- let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K"}
- let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K"}
+ let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K" }
+ let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K" }
let(:section_start_html) do
'<div class="section-start"' \
" data-timestamp=\"#{section_start_time.to_i}\" data-section=\"#{class_name(section_name)}\"" \
@@ -258,13 +258,13 @@ RSpec.describe Gitlab::Ci::Ansi2html do
it_behaves_like 'a legit section'
context 'section name includes $' do
- let(:section_name) { 'my_$ection'}
+ let(:section_name) { 'my_$ection' }
it_behaves_like 'forbidden char in section_name'
end
context 'section name includes <' do
- let(:section_name) { '<a_tag>'}
+ let(:section_name) { '<a_tag>' }
it_behaves_like 'forbidden char in section_name'
end
diff --git a/spec/lib/gitlab/ci/ansi2json_spec.rb b/spec/lib/gitlab/ci/ansi2json_spec.rb
index f9d23ff97bc..4b3b049176f 100644
--- a/spec/lib/gitlab/ci/ansi2json_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2json_spec.rb
@@ -78,8 +78,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:section_duration) { 63.seconds }
let(:section_start_time) { Time.new(2019, 9, 17).utc }
let(:section_end_time) { section_start_time + section_duration }
- let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K"}
- let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K"}
+ let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K" }
+ 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([
@@ -258,8 +258,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:nested_section_duration) { 2.seconds }
let(:nested_section_start_time) { Time.new(2019, 9, 17).utc }
let(:nested_section_end_time) { nested_section_start_time + nested_section_duration }
- let(:nested_section_start) { "section_start:#{nested_section_start_time.to_i}:#{nested_section_name}\r\033[0K"}
- let(:nested_section_end) { "section_end:#{nested_section_end_time.to_i}:#{nested_section_name}\r\033[0K"}
+ let(:nested_section_start) { "section_start:#{nested_section_start_time.to_i}:#{nested_section_name}\r\033[0K" }
+ let(:nested_section_end) { "section_end:#{nested_section_end_time.to_i}:#{nested_section_name}\r\033[0K" }
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"
@@ -342,7 +342,7 @@ RSpec.describe Gitlab::Ci::Ansi2json do
end
context 'with section options' do
- let(:option_section_start) { "section_start:#{section_start_time.to_i}:#{section_name}[collapsed=true,unused_option=123]\r\033[0K"}
+ let(:option_section_start) { "section_start:#{section_start_time.to_i}:#{section_name}[collapsed=true,unused_option=123]\r\033[0K" }
it 'provides section options when set' do
trace = "#{option_section_start}hello#{section_end}"
@@ -463,8 +463,8 @@ RSpec.describe Gitlab::Ci::Ansi2json do
let(:section_duration) { 63.seconds }
let(:section_start_time) { Time.new(2019, 9, 17).utc }
let(:section_end_time) { section_start_time + section_duration }
- let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K"}
- let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K"}
+ let(:section_start) { "section_start:#{section_start_time.to_i}:#{section_name}\r\033[0K" }
+ let(:section_end) { "section_end:#{section_end_time.to_i}:#{section_name}\r\033[0K" }
context 'with split section body' do
let(:pre_text) { "#{section_start}this is a header\nand " }
diff --git a/spec/lib/gitlab/ci/artifacts/logger_spec.rb b/spec/lib/gitlab/ci/artifacts/logger_spec.rb
new file mode 100644
index 00000000000..7753cb0d25e
--- /dev/null
+++ b/spec/lib/gitlab/ci/artifacts/logger_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Artifacts::Logger do
+ before do
+ Gitlab::ApplicationContext.push(feature_category: 'test', caller_id: 'caller')
+ end
+
+ describe '.log_created' do
+ it 'logs information about created artifact' do
+ artifact = create(:ci_job_artifact, :archive)
+
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ message: 'Artifact created',
+ job_artifact_id: artifact.id,
+ size: artifact.size,
+ type: artifact.file_type,
+ build_id: artifact.job_id,
+ project_id: artifact.project_id,
+ 'correlation_id' => an_instance_of(String),
+ 'meta.feature_category' => 'test',
+ 'meta.caller_id' => 'caller'
+ )
+ )
+
+ described_class.log_created(artifact)
+ end
+ end
+
+ describe '.log_deleted' do
+ it 'logs information about deleted artifacts' do
+ artifact_1 = create(:ci_job_artifact, :archive, :expired)
+ artifact_2 = create(:ci_job_artifact, :archive)
+ artifacts = [artifact_1, artifact_2]
+ method = 'Foo#method'
+
+ artifacts.each do |artifact|
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ message: 'Artifact deleted',
+ job_artifact_id: artifact.id,
+ expire_at: artifact.expire_at,
+ size: artifact.size,
+ type: artifact.file_type,
+ build_id: artifact.job_id,
+ project_id: artifact.project_id,
+ method: method,
+ 'correlation_id' => an_instance_of(String),
+ 'meta.feature_category' => 'test',
+ 'meta.caller_id' => 'caller'
+ )
+ )
+ end
+
+ described_class.log_deleted(artifacts, method)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/artifacts/metrics_spec.rb b/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
index 0ce76285b03..39e440f09e1 100644
--- a/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
+++ b/spec/lib/gitlab/ci/artifacts/metrics_spec.rb
@@ -5,6 +5,25 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Artifacts::Metrics, :prometheus do
let(:metrics) { described_class.new }
+ describe '.build_completed_report_type_counter' do
+ context 'when incrementing by more than one' do
+ let(:sast_counter) { described_class.send(:build_completed_report_type_counter, :sast) }
+ let(:dast_counter) { described_class.send(:build_completed_report_type_counter, :dast) }
+
+ it 'increments a single counter' do
+ [dast_counter, sast_counter].each do |counter|
+ counter.increment(status: 'success')
+ counter.increment(status: 'success')
+ counter.increment(status: 'failed')
+
+ expect(counter.get(status: 'success')).to eq 2.0
+ expect(counter.get(status: 'failed')).to eq 1.0
+ expect(counter.values.count).to eq 2
+ end
+ end
+ end
+ end
+
describe '#increment_destroyed_artifacts' do
context 'when incrementing by more than one' do
let(:counter) { metrics.send(:destroyed_artifacts_counter) }
diff --git a/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb b/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb
new file mode 100644
index 00000000000..2c236ba3726
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/artifacts/adapters/zip_stream_spec.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Build::Artifacts::Adapters::ZipStream do
+ let(:file_name) { 'single_file.zip' }
+ let(:fixture_path) { "lib/gitlab/ci/build/artifacts/adapters/zip_stream/#{file_name}" }
+ let(:stream) { File.open(expand_fixture_path(fixture_path), 'rb') }
+
+ describe '#initialize' do
+ it 'initializes when stream is passed' do
+ expect { described_class.new(stream) }.not_to raise_error
+ end
+
+ context 'when stream is not passed' do
+ let(:stream) { nil }
+
+ it 'raises an error' do
+ expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+
+ describe '#each_blob' do
+ let(:adapter) { described_class.new(stream) }
+
+ context 'when stream is a zip file' do
+ it 'iterates file content when zip file contains one file' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_with_args("file 1 content\n")
+ end
+
+ context 'when zip file contains multiple files' do
+ let(:file_name) { 'multiple_files.zip' }
+
+ it 'iterates content of all files' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_successive_args("file 1 content\n", "file 2 content\n")
+ end
+ end
+
+ context 'when zip file includes files in a directory' do
+ let(:file_name) { 'with_directory.zip' }
+
+ it 'iterates contents from files only' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_successive_args("file 1 content\n", "file 2 content\n")
+ end
+ end
+
+ context 'when zip contains a file which decompresses beyond the size limit' do
+ let(:file_name) { '200_mb_decompressed.zip' }
+
+ it 'does not read the file' do
+ expect { |b| adapter.each_blob(&b) }.not_to yield_control
+ end
+ end
+
+ context 'when the zip contains too many files' do
+ let(:file_name) { '100_files.zip' }
+
+ it 'stops processing when the limit is reached' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_control.exactly(described_class::MAX_FILES_PROCESSED).times
+ end
+ end
+
+ context 'when stream is a zipbomb' do
+ let(:file_name) { 'zipbomb.zip' }
+
+ it 'does not read the file' do
+ expect { |b| adapter.each_blob(&b) }.not_to yield_control
+ end
+ end
+ end
+
+ context 'when stream is not a zip file' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
+
+ it 'does not yield any data' do
+ expect { |b| adapter.each_blob(&b) }.not_to yield_control
+ expect { adapter.each_blob { |b| b } }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
index c8ace28108b..7b35c9ba483 100644
--- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb
@@ -67,6 +67,7 @@ RSpec.describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
subject { |example| path(example).children }
it { is_expected.to all(be_an_instance_of(described_class)) }
+
it do
is_expected.to contain_exactly entry('path/dir_1/file_1'),
entry('path/dir_1/file_b'),
@@ -79,6 +80,7 @@ RSpec.describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
it { is_expected.to all(be_file) }
it { is_expected.to all(be_an_instance_of(described_class)) }
+
it do
is_expected.to contain_exactly entry('path/dir_1/file_1'),
entry('path/dir_1/file_b')
@@ -99,6 +101,7 @@ RSpec.describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do
it { is_expected.to all(be_directory) }
it { is_expected.to all(be_an_instance_of(described_class)) }
+
it do
is_expected.to contain_exactly entry('path/dir_1/subdir/'),
entry('path/')
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 94c14cfa479..baabab73ea2 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
end
context 'kubernetes namespace does not exist' do
- let(:namespace_builder) { double(execute: kubernetes_namespace)}
+ let(:namespace_builder) { double(execute: kubernetes_namespace) }
before do
allow(Clusters::KubernetesNamespaceFinder).to receive(:new)
diff --git a/spec/lib/gitlab/ci/build/releaser_spec.rb b/spec/lib/gitlab/ci/build/releaser_spec.rb
index 435f70e9ac5..ffa7073818a 100644
--- a/spec/lib/gitlab/ci/build/releaser_spec.rb
+++ b/spec/lib/gitlab/ci/build/releaser_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Gitlab::Ci::Build::Releaser do
name: 'Release $CI_COMMIT_SHA',
description: 'Created using the release-cli $EXTRA_DESCRIPTION',
tag_name: 'release-$CI_COMMIT_SHA',
+ tag_message: 'Annotated tag message',
ref: '$CI_COMMIT_SHA',
milestones: %w[m1 m2 m3],
released_at: '2020-07-15T08:00:00Z',
@@ -27,7 +28,7 @@ RSpec.describe Gitlab::Ci::Build::Releaser do
end
it 'generates the script' do
- expect(subject).to eq(['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" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\",\"filepath\":\"/pretty/asset/1\"}" --assets-link "{\"name\":\"asset2\",\"url\":\"https://example.com/assets/2\"}"'])
+ expect(subject).to eq(['release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "release-$CI_COMMIT_SHA" --tag-message "Annotated tag message" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3" --assets-link "{\"name\":\"asset1\",\"url\":\"https://example.com/assets/1\",\"link_type\":\"other\",\"filepath\":\"/pretty/asset/1\"}" --assets-link "{\"name\":\"asset2\",\"url\":\"https://example.com/assets/2\"}"'])
end
end
@@ -39,6 +40,7 @@ RSpec.describe Gitlab::Ci::Build::Releaser do
:name | 'Release $CI_COMMIT_SHA' | 'release-cli create --name "Release $CI_COMMIT_SHA"'
:description | 'Release-cli $EXTRA_DESCRIPTION' | 'release-cli create --description "Release-cli $EXTRA_DESCRIPTION"'
:tag_name | 'release-$CI_COMMIT_SHA' | 'release-cli create --tag-name "release-$CI_COMMIT_SHA"'
+ :tag_message | 'Annotated tag message' | 'release-cli create --tag-message "Annotated tag message"'
:ref | '$CI_COMMIT_SHA' | 'release-cli create --ref "$CI_COMMIT_SHA"'
:milestones | %w[m1 m2 m3] | 'release-cli create --milestone "m1" --milestone "m2" --milestone "m3"'
:released_at | '2020-07-15T08:00:00Z' | 'release-cli create --released-at "2020-07-15T08:00:00Z"'
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 3892b88598a..234ba68d627 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
@@ -4,7 +4,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
describe '#satisfied_by?' do
- subject { described_class.new(globs).satisfied_by?(pipeline, context) }
+ let(:context) { instance_double(Gitlab::Ci::Build::Context::Base) }
+
+ subject(:satisfied_by) { described_class.new(globs).satisfied_by?(pipeline, context) }
context 'a glob matching rule' do
using RSpec::Parameterized::TableSyntax
@@ -18,11 +20,9 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
# rubocop:disable Layout/LineLength
where(:case_name, :globs, :files, :satisfied) do
- 'exact top-level match' | ['Dockerfile'] | { 'Dockerfile' => '', 'Gemfile' => '' } | true
'exact top-level match' | { paths: ['Dockerfile'] } | { 'Dockerfile' => '', 'Gemfile' => '' } | true
'exact top-level no match' | { paths: ['Dockerfile'] } | { 'Gemfile' => '' } | false
'pattern top-level match' | { paths: ['Docker*'] } | { 'Dockerfile' => '', 'Gemfile' => '' } | true
- 'pattern top-level no match' | ['Docker*'] | { 'Gemfile' => '' } | false
'pattern top-level no match' | { paths: ['Docker*'] } | { 'Gemfile' => '' } | false
'exact nested match' | { paths: ['project/build.properties'] } | { 'project/build.properties' => '' } | true
'exact nested no match' | { paths: ['project/build.properties'] } | { 'project/README.md' => '' } | false
@@ -92,5 +92,97 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
it { is_expected.to be_truthy }
end
end
+
+ context 'when using compare_to' do
+ let_it_be(:project) do
+ create(:project, :custom_repo,
+ files: { 'README.md' => 'readme' })
+ end
+
+ let_it_be(:user) { project.owner }
+
+ before_all do
+ project.repository.add_branch(user, 'feature_1', 'master')
+
+ project.repository.create_file(
+ user, 'file1.txt', 'file 1', message: 'Create file1.txt', branch_name: 'feature_1'
+ )
+ project.repository.add_tag(user, 'tag_1', 'feature_1')
+
+ project.repository.create_file(
+ user, 'file2.txt', 'file 2', message: 'Create file2.txt', branch_name: 'feature_1'
+ )
+ project.repository.add_branch(user, 'feature_2', 'feature_1')
+
+ project.repository.update_file(
+ user, 'file2.txt', 'file 2 updated', message: 'Update file2.txt', branch_name: 'feature_2'
+ )
+ end
+
+ 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
+ end
+
+ with_them do
+ let(:globs) { { paths: paths, compare_to: compare_to } }
+
+ let(:pipeline) 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
+
+ context 'when compare_to is a sha' do
+ let(:globs) { { paths: ['file2.txt'], compare_to: project.commit('tag_1').sha } }
+
+ let(:pipeline) do
+ build(:ci_pipeline, project: project, ref: 'feature_2', sha: project.commit('feature_2').sha)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when compare_to is not a valid ref' do
+ let(:globs) { { paths: ['file1.txt'], compare_to: 'xyz' } }
+
+ let(:pipeline) do
+ build(:ci_pipeline, project: project, ref: 'feature_2', sha: project.commit('feature_2').sha)
+ end
+
+ it 'raises ParseError' do
+ expect { satisfied_by }.to raise_error(
+ ::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
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/if_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/if_spec.rb
index 81bce989833..31c7437cfe0 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/if_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/if_spec.rb
@@ -51,14 +51,6 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::If do
end
it { is_expected.to eq(true) }
-
- context 'when the FF ci_fix_rules_if_comparison_with_regexp_variable is disabled' do
- before do
- stub_feature_flags(ci_fix_rules_if_comparison_with_regexp_variable: false)
- end
-
- it { is_expected.to eq(false) }
- end
end
context 'when comparison is false' do
diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb
index 0fa6d4f8804..6121c28070f 100644
--- a/spec/lib/gitlab/ci/config/entry/image_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'support/helpers/stubbed_feature'
-require 'support/helpers/stub_feature_flags'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Image do
- include StubFeatureFlags
-
before do
stub_feature_flags(ci_docker_image_pull_policy: true)
diff --git a/spec/lib/gitlab/ci/config/entry/imageable_spec.rb b/spec/lib/gitlab/ci/config/entry/imageable_spec.rb
new file mode 100644
index 00000000000..88f8e260611
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/imageable_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Config::Entry::Imageable do
+ let(:node_class) do
+ Class.new(::Gitlab::Config::Entry::Node) do
+ include ::Gitlab::Ci::Config::Entry::Imageable
+
+ validations do
+ validates :config, allowed_keys: ::Gitlab::Ci::Config::Entry::Imageable::IMAGEABLE_ALLOWED_KEYS
+ end
+
+ def self.name
+ 'node'
+ end
+
+ def value
+ if string?
+ { name: @config }
+ elsif hash?
+ {
+ name: @config[:name]
+ }.compact
+ else
+ {}
+ end
+ end
+ end
+ end
+
+ subject(:entry) { node_class.new(config) }
+
+ before do
+ entry.compose!
+ end
+
+ context 'when entry value is correct' do
+ let(:config) { 'image:1.0' }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not correct' do
+ let(:config) { ['image:1.0'] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors.first)
+ .to match /config should be a hash or a string/
+ end
+ end
+
+ describe '#valid?' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ end
+ end
+ end
+
+ context 'when unexpected key is specified' do
+ let(:config) { { name: 'image:1.0', non_existing: 'test' } }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors.first)
+ .to match /config contains unknown keys: non_existing/
+ end
+ end
+
+ describe '#valid?' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ end
+ 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 5b9337ede34..714b0a3b6aa 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -212,7 +212,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
let(:unspecified) { double('unspecified', 'specified?' => false) }
let(:default) { double('default', '[]' => unspecified) }
let(:workflow) { double('workflow', 'has_rules?' => false) }
- let(:variables) { }
+ let(:variables) {}
let(:deps) do
double('deps',
diff --git a/spec/lib/gitlab/ci/config/entry/release_spec.rb b/spec/lib/gitlab/ci/config/entry/release_spec.rb
index e5155f91be4..7b6b31ca748 100644
--- a/spec/lib/gitlab/ci/config/entry/release_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/release_spec.rb
@@ -128,25 +128,25 @@ RSpec.describe Gitlab::Ci::Config::Entry::Release do
end
context "when 'ref' is a short commit SHA" do
- let(:ref) { 'b3235930'}
+ let(:ref) { 'b3235930' }
it_behaves_like 'a valid entry'
end
context "when 'ref' is a branch name" do
- let(:ref) { 'fix/123-branch-name'}
+ let(:ref) { 'fix/123-branch-name' }
it_behaves_like 'a valid entry'
end
context "when 'ref' is a semantic versioning tag" do
- let(:ref) { 'v1.2.3'}
+ let(:ref) { 'v1.2.3' }
it_behaves_like 'a valid entry'
end
context "when 'ref' is a semantic versioning tag rc" do
- let(:ref) { 'v1.2.3-rc'}
+ let(:ref) { 'v1.2.3-rc' }
it_behaves_like 'a valid entry'
end
@@ -188,6 +188,30 @@ RSpec.describe Gitlab::Ci::Config::Entry::Release do
end
end
+ context "when value includes 'tag_message' keyword" do
+ let(:config) do
+ {
+ tag_name: 'v0.06',
+ description: "./release_changelog.txt",
+ tag_message: "Annotated tag message"
+ }
+ end
+
+ it_behaves_like 'a valid entry'
+ end
+
+ context "when 'tag_message' is nil" do
+ let(:config) do
+ {
+ tag_name: 'v0.06',
+ description: "./release_changelog.txt",
+ tag_message: nil
+ }
+ end
+
+ it_behaves_like 'a valid entry'
+ end
+
context 'when entry value is not correct' do
describe '#errors' do
context 'when value of attribute is invalid' do
@@ -231,6 +255,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Release do
it_behaves_like 'reports error', 'release milestones should be an array of strings or a string'
end
+
+ context 'when `tag_message` is not a string' do
+ let(:config) { { tag_message: 100 } }
+
+ it_behaves_like 'reports error', 'release tag message should be a string'
+ end
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index 051cccb4833..45aa859a356 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -47,6 +47,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do
:dotenv | 'build.dotenv'
:terraform | 'tfplan.json'
:accessibility | 'gl-accessibility.json'
+ :cyclonedx | 'gl-sbom.cdx.zip'
end
with_them do
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 55ad119ea21..1f8543227c9 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }],
only: { refs: %w(branches tags) },
- job_variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
after_script: [],
ignore: false,
@@ -215,7 +215,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
stage: 'test',
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
- job_variables: { 'VAR' => 'job' },
+ job_variables: { 'VAR' => { value: 'job' } },
root_variables_inheritance: true,
ignore: false,
after_script: ['make clean'],
diff --git a/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb b/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb
index 295561b3c4d..64f0a64074c 100644
--- a/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/rules/rule/changes_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule::Changes do
let(:factory) do
@@ -119,6 +119,23 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule::Changes do
end
end
end
+
+ context 'with paths and compare_to' do
+ let(:config) { { paths: %w[app/ lib/], compare_to: 'branch1' } }
+
+ it { is_expected.to be_valid }
+
+ context 'when compare_to is not a string' do
+ let(:config) { { paths: %w[app/ lib/], compare_to: 1 } }
+
+ it { is_expected.not_to be_valid }
+
+ it 'returns information about errors' do
+ expect(entry.errors)
+ .to include(/should be a string/)
+ end
+ end
+ end
end
describe '#value' do
@@ -137,5 +154,13 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule::Changes do
it { is_expected.to eq(config) }
end
+
+ context 'with paths and compare_to' do
+ let(:config) do
+ { paths: ['app/', 'lib/'], compare_to: 'branch1' }
+ end
+
+ it { is_expected.to eq(config) }
+ 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 93f4a66bfb6..c85fe366da6 100644
--- a/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/rules/rule_spec.rb
@@ -2,7 +2,6 @@
require 'fast_spec_helper'
require 'gitlab_chronic_duration'
-require 'support/helpers/stub_feature_flags'
require_dependency 'active_model'
RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do
@@ -418,6 +417,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules::Rule do
it { is_expected.to eq(config) }
end
+
+ context 'when using changes with paths and compare_to' do
+ let(:config) { { changes: { paths: %w[app/ lib/ spec/ other/* paths/**/*.rb], compare_to: 'branch1' } } }
+
+ it { is_expected.to eq(config) }
+ end
end
context 'when default value has been provided' do
diff --git a/spec/lib/gitlab/ci/config/entry/service_spec.rb b/spec/lib/gitlab/ci/config/entry/service_spec.rb
index 3c000fd09ed..821ab442d61 100644
--- a/spec/lib/gitlab/ci/config/entry/service_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-require 'support/helpers/stubbed_feature'
-require 'support/helpers/stub_feature_flags'
+require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Service do
- include StubFeatureFlags
-
before do
stub_feature_flags(ci_docker_image_pull_policy: true)
entry.compose!
diff --git a/spec/lib/gitlab/ci/config/entry/tags_spec.rb b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
index e05d4ae52b2..24efd08c855 100644
--- a/spec/lib/gitlab/ci/config/entry/tags_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Tags do
end
context 'when tags limit is reached' do
- let(:config) { Array.new(50) {|i| "tag-#{i}" } }
+ let(:config) { Array.new(50) { |i| "tag-#{i}" } }
it 'reports error' do
expect(entry.errors)
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
index 280bebe1a7c..1306d61d99c 100644
--- a/spec/lib/gitlab/ci/config/external/file/base_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::External::File::Base do
- let(:variables) { }
+ let(:variables) {}
let(:context_params) { { sha: 'HEAD', variables: variables } }
let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
@@ -100,7 +100,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Base do
describe '#to_hash' do
context 'with includes' do
let(:location) { 'some/file/config.yml' }
- let(:content) { 'include: { template: Bash.gitlab-ci.yml }'}
+ let(:content) { 'include: { template: Bash.gitlab-ci.yml }' }
before do
allow_any_instance_of(test_class)
diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
index 0e78498c98e..f5b36ebfa45 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -167,7 +167,7 @@ RSpec.describe Gitlab::Ci::Config::External::File::Local do
describe '#to_hash' do
context 'properly includes another local file in the same repository' do
let(:location) { 'some/file/config.yml' }
- let(:content) { 'include: { local: another-config.yml }'}
+ let(:content) { 'include: { local: another-config.yml }' }
let(:another_location) { 'another-config.yml' }
let(:another_content) { 'rspec: JOB' }
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
index 3e1c4df4e32..45dfea636f3 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::External::File::Remote do
include StubRequests
- let(:variables) {Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) }
+ let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'GITLAB_TOKEN', 'value' => 'secret_file', 'masked' => true }]) }
let(:context_params) { { sha: '12345', variables: variables } }
let(:context) { Gitlab::Ci::Config::External::Context.new(**context_params) }
let(:params) { { remote: location } }
diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb
index 354392eb42e..96ca5d98a6e 100644
--- a/spec/lib/gitlab/ci/config/normalizer_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb
@@ -232,7 +232,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
context 'when parallel config does not matches a factory' do
let(:variables_config) { {} }
- let(:parallel_config) { }
+ let(:parallel_config) {}
it 'does not alter the job config' do
is_expected.to match(config)
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 5eb04d969eb..055114769ea 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -872,4 +872,21 @@ RSpec.describe Gitlab::Ci::Config do
end
end
end
+
+ describe '#workflow_rules' do
+ subject(:workflow_rules) { config.workflow_rules }
+
+ let(:yml) do
+ <<-EOS
+ workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == "master"
+
+ rspec:
+ script: exit 0
+ EOS
+ end
+
+ it { is_expected.to eq([{ if: '$CI_COMMIT_REF_NAME == "master"' }]) }
+ end
end
diff --git a/spec/lib/gitlab/ci/cron_parser_spec.rb b/spec/lib/gitlab/ci/cron_parser_spec.rb
index 4017accb462..33474865a93 100644
--- a/spec/lib/gitlab/ci/cron_parser_spec.rb
+++ b/spec/lib/gitlab/ci/cron_parser_spec.rb
@@ -178,7 +178,7 @@ RSpec.describe Gitlab::Ci::CronParser do
end
context 'when time crosses a Daylight Savings boundary' do
- let(:cron) { '* 0 1 12 *'}
+ let(:cron) { '* 0 1 12 *' }
# Note this previously only failed if the time zone is set
# to a zone that observes Daylight Savings
diff --git a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
new file mode 100644
index 00000000000..c99cfa94aa6
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_properties_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Parsers::Sbom::CyclonedxProperties do
+ subject(:parse_source) { described_class.parse_source(properties) }
+
+ context 'when properties are nil' do
+ let(:properties) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when report does not have gitlab properties' do
+ let(:properties) { ['name' => 'foo', 'value' => 'bar'] }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when schema_version is missing' do
+ let(:properties) do
+ [
+ { 'name' => 'gitlab:dependency_scanning:dependency_file', 'value' => 'package-lock.json' },
+ { 'name' => 'gitlab:dependency_scanning:package_manager_name', 'value' => 'npm' },
+ { 'name' => 'gitlab:dependency_scanning:language', 'value' => 'JavaScript' }
+ ]
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when schema version is unsupported' do
+ let(:properties) do
+ [
+ { 'name' => 'gitlab:meta:schema_version', 'value' => '2' },
+ { 'name' => 'gitlab:dependency_scanning:dependency_file', 'value' => 'package-lock.json' },
+ { 'name' => 'gitlab:dependency_scanning:package_manager_name', 'value' => 'npm' },
+ { 'name' => 'gitlab:dependency_scanning:language', 'value' => 'JavaScript' }
+ ]
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when no dependency_scanning properties are present' do
+ let(:properties) do
+ [
+ { 'name' => 'gitlab:meta:schema_version', 'value' => '1' }
+ ]
+ end
+
+ it 'does not call dependency_scanning parser' do
+ expect(Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning).not_to receive(:parse_source)
+
+ parse_source
+ end
+ end
+
+ context 'when dependency_scanning properties are present' do
+ let(:properties) do
+ [
+ { 'name' => 'gitlab:meta:schema_version', 'value' => '1' },
+ { 'name' => 'gitlab:dependency_scanning:category', 'value' => 'development' },
+ { 'name' => 'gitlab:dependency_scanning:input_file:path', 'value' => 'package-lock.json' },
+ { 'name' => 'gitlab:dependency_scanning:source_file:path', 'value' => 'package.json' },
+ { 'name' => 'gitlab:dependency_scanning:package_manager:name', 'value' => 'npm' },
+ { 'name' => 'gitlab:dependency_scanning:language:name', 'value' => 'JavaScript' },
+ { 'name' => 'gitlab:dependency_scanning:unsupported_property', 'value' => 'Should be ignored' }
+ ]
+ end
+
+ let(:expected_input) do
+ {
+ 'category' => 'development',
+ 'input_file' => { 'path' => 'package-lock.json' },
+ 'source_file' => { 'path' => 'package.json' },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ }
+ end
+
+ it 'passes only supported properties to the dependency scanning parser' do
+ expect(Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning).to receive(:source).with(expected_input)
+
+ parse_source
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
new file mode 100644
index 00000000000..431fe9f3591
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/sbom/cyclonedx_spec.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Parsers::Sbom::Cyclonedx do
+ let(:report) { instance_double('Gitlab::Ci::Reports::Sbom::Report') }
+ let(:report_data) { base_report_data }
+ let(:raw_report_data) { report_data.to_json }
+ let(:report_valid?) { true }
+ let(:validator_errors) { [] }
+ let(:properties_parser) { class_double('Gitlab::Ci::Parsers::Sbom::CyclonedxProperties') }
+
+ let(:base_report_data) do
+ {
+ 'bomFormat' => 'CycloneDX',
+ 'specVersion' => '1.4',
+ 'version' => 1
+ }
+ end
+
+ subject(:parse!) { described_class.new.parse!(raw_report_data, report) }
+
+ before do
+ allow_next_instance_of(Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator) do |validator|
+ allow(validator).to receive(:valid?).and_return(report_valid?)
+ allow(validator).to receive(:errors).and_return(validator_errors)
+ end
+
+ allow(properties_parser).to receive(:parse_source)
+ stub_const('Gitlab::Ci::Parsers::Sbom::CyclonedxProperties', properties_parser)
+ end
+
+ context 'when report JSON is invalid' do
+ let(:raw_report_data) { '{ ' }
+
+ it 'handles errors and adds them to the report' do
+ expect(report).to receive(:add_error).with(a_string_including("Report JSON is invalid:"))
+
+ expect { parse! }.not_to raise_error
+ end
+ end
+
+ context 'when report uses an unsupported spec version' do
+ let(:report_data) { base_report_data.merge({ 'specVersion' => '1.3' }) }
+
+ it 'reports unsupported version as an error' do
+ expect(report).to receive(:add_error).with("Unsupported CycloneDX spec version. Must be one of: 1.4")
+
+ parse!
+ end
+ end
+
+ context 'when report does not conform to the CycloneDX schema' do
+ let(:report_valid?) { false }
+ let(:validator_errors) { %w[error1 error2] }
+
+ it 'reports all errors returned by the validator' do
+ expect(report).to receive(:add_error).with("error1")
+ expect(report).to receive(:add_error).with("error2")
+
+ parse!
+ end
+ end
+
+ context 'when cyclonedx report has no components' do
+ it 'skips component processing' do
+ expect(report).not_to receive(:add_component)
+
+ parse!
+ end
+ end
+
+ context 'when report has components' do
+ let(:report_data) { base_report_data.merge({ 'components' => components }) }
+ let(:components) do
+ [
+ {
+ "name" => "activesupport",
+ "version" => "5.1.4",
+ "purl" => "pkg:gem/activesupport@5.1.4",
+ "type" => "library",
+ "bom-ref" => "pkg:gem/activesupport@5.1.4"
+ },
+ {
+ "name" => "byebug",
+ "version" => "10.0.0",
+ "purl" => "pkg:gem/byebug@10.0.0",
+ "type" => "library",
+ "bom-ref" => "pkg:gem/byebug@10.0.0"
+ },
+ {
+ "name" => "minimal-component",
+ "type" => "library"
+ },
+ {
+ # Should be skipped
+ "name" => "unrecognized-type",
+ "type" => "unknown"
+ }
+ ]
+ end
+
+ it 'adds each component, ignoring unused attributes' do
+ expect(report).to receive(:add_component)
+ .with({ "name" => "activesupport", "version" => "5.1.4", "type" => "library" })
+ expect(report).to receive(:add_component)
+ .with({ "name" => "byebug", "version" => "10.0.0", "type" => "library" })
+ expect(report).to receive(:add_component)
+ .with({ "name" => "minimal-component", "type" => "library" })
+
+ parse!
+ end
+ end
+
+ context 'when report has metadata properties' do
+ let(:report_data) { base_report_data.merge({ 'metadata' => { 'properties' => properties } }) }
+
+ let(:properties) do
+ [
+ { 'name' => 'gitlab:meta:schema_version', 'value' => '1' },
+ { 'name' => 'gitlab:dependency_scanning:category', 'value' => 'development' },
+ { 'name' => 'gitlab:dependency_scanning:input_file:path', 'value' => 'package-lock.json' },
+ { 'name' => 'gitlab:dependency_scanning:source_file:path', 'value' => 'package.json' },
+ { 'name' => 'gitlab:dependency_scanning:package_manager:name', 'value' => 'npm' },
+ { 'name' => 'gitlab:dependency_scanning:language:name', 'value' => 'JavaScript' }
+ ]
+ end
+
+ it 'passes them to the properties parser' do
+ expect(properties_parser).to receive(:parse_source).with(properties)
+
+ parse!
+ end
+ end
+end
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
new file mode 100644
index 00000000000..30114b17cac
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/sbom/source/dependency_scanning_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Parsers::Sbom::Source::DependencyScanning do
+ subject { described_class.source(property_data) }
+
+ context 'when all property data is present' do
+ let(:property_data) do
+ {
+ 'category' => 'development',
+ 'input_file' => { 'path' => 'package-lock.json' },
+ 'source_file' => { 'path' => 'package.json' },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ }
+ end
+
+ it 'returns expected source data' do
+ is_expected.to eq({
+ 'type' => :dependency_scanning,
+ 'data' => property_data,
+ 'fingerprint' => '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ })
+ end
+ end
+
+ context 'when required properties are missing' do
+ let(:property_data) do
+ {
+ 'category' => 'development',
+ 'source_file' => { 'path' => 'package.json' },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ }
+ end
+
+ it { is_expected.to be_nil }
+ 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
new file mode 100644
index 00000000000..c54a3268bbe
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/sbom/validators/cyclonedx_schema_validator_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Gitlab::Ci::Parsers::Sbom::Validators::CyclonedxSchemaValidator do
+ # Reports should be valid or invalid according to the specification at
+ # https://cyclonedx.org/docs/1.4/json/
+
+ subject(:validator) { described_class.new(report_data) }
+
+ let_it_be(:required_attributes) do
+ {
+ "bomFormat" => "CycloneDX",
+ "specVersion" => "1.4",
+ "version" => 1
+ }
+ end
+
+ context "with minimally valid report" do
+ let_it_be(:report_data) { required_attributes }
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when report has components" do
+ let(:report_data) { required_attributes.merge({ "components" => components }) }
+
+ context "with minimally valid components" do
+ let(:components) do
+ [
+ {
+ "type" => "library",
+ "name" => "activesupport"
+ },
+ {
+ "type" => "library",
+ "name" => "byebug"
+ }
+ ]
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when components have versions" do
+ let(:components) do
+ [
+ {
+ "type" => "library",
+ "name" => "activesupport",
+ "version" => "5.1.4"
+ },
+ {
+ "type" => "library",
+ "name" => "byebug",
+ "version" => "10.0.0"
+ }
+ ]
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when components are not valid" do
+ let(:components) do
+ [
+ { "type" => "foo" },
+ { "name" => "activesupport" }
+ ]
+ end
+
+ 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"
+ ])
+ end
+ end
+ end
+
+ context "when report has metadata" do
+ let(:metadata) do
+ {
+ "timestamp" => "2022-02-23T08:02:39Z",
+ "tools" => [{ "vendor" => "GitLab", "name" => "Gemnasium", "version" => "2.34.0" }],
+ "authors" => [{ "name" => "GitLab", "email" => "support@gitlab.com" }]
+ }
+ end
+
+ let(:report_data) { required_attributes.merge({ "metadata" => metadata }) }
+
+ it { is_expected.to be_valid }
+
+ context "when metadata has properties" do
+ before do
+ metadata.merge!({ "properties" => properties })
+ end
+
+ context "when properties are valid" do
+ let(:properties) do
+ [
+ { "name" => "gitlab:dependency_scanning:input_file", "value" => "Gemfile.lock" },
+ { "name" => "gitlab:dependency_scanning:package_manager", "value" => "bundler" }
+ ]
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when properties are invalid" do
+ let(:properties) do
+ [
+ { "name" => ["gitlab:meta:schema_version"], "value" => 1 }
+ ]
+ end
+
+ 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"
+ ])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
index d06077d69b6..7828aa99f6a 100644
--- a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let_it_be(:project) { create(:project) }
let(:supported_dast_versions) { described_class::SUPPORTED_VERSIONS[:dast].join(', ') }
+ let(:deprecated_schema_version_message) {}
+ let(:missing_schema_version_message) do
+ "Report version not provided, dast report type supports versions: #{supported_dast_versions}"
+ end
let(:scanner) do
{
@@ -24,7 +28,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
expect(described_class::SUPPORTED_VERSIONS.keys).to eq(described_class::DEPRECATED_VERSIONS.keys)
end
- context 'when a schema JSON file exists for a particular report type version' do
+ context 'when all files under schema path are explicitly listed' do
# We only care about the part that comes before report-format.json
# https://rubular.com/r/N8Juz7r8hYDYgD
filename_regex = /(?<report_type>[-\w]*)\-report-format.json/
@@ -38,7 +42,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
matches = filename_regex.match(file)
report_type = matches[:report_type].tr("-", "_").to_sym
- it "#{report_type} #{version} is in the constant" do
+ it "#{report_type} #{version}" do
expect(described_class::SUPPORTED_VERSIONS[report_type]).to include(version)
end
end
@@ -64,11 +68,54 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
describe '#valid?' do
subject { validator.valid? }
+ context 'when given a supported MAJOR.MINOR schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) do
+ latest_vendored_version = described_class::SUPPORTED_VERSIONS[report_type].last.split(".")
+ (latest_vendored_version[0...2] << "34").join(".")
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ it { is_expected.to be_falsey }
+
+ it 'logs related information' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ message: "security report schema validation problem",
+ security_report_type: report_type,
+ security_report_version: report_version,
+ project_id: project.id,
+ security_report_failure: 'schema_validation_fails',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
+
+ subject
+ end
+ end
+ end
+
context 'when given a supported schema version' do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'when the report is valid' do
+ context 'and the report is valid' do
let(:report_data) do
{
'version' => report_version,
@@ -79,7 +126,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to be_truthy }
end
- context 'when the report is invalid' do
+ context 'and the report is invalid' do
let(:report_data) do
{
'version' => report_version
@@ -118,7 +165,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_const("#{described_class}::DEPRECATED_VERSIONS", deprecations_hash)
end
- context 'when the report passes schema validation' do
+ context 'and the report passes schema validation' do
let(:report_data) do
{
'version' => '10.0.0',
@@ -143,34 +190,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end
end
- context 'when the report does not pass schema validation' do
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
- end
-
- let(:report_data) do
- {
- 'version' => 'V2.7.0'
- }
- end
-
- it { is_expected.to be_falsey }
+ context 'and the report does not pass schema validation' do
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- let(:report_data) do
- {
- 'version' => 'V2.7.0'
- }
- end
-
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to be_falsey }
end
end
@@ -178,20 +205,40 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { "12.37.0" }
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
end
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
+ it { is_expected.to be_falsey }
+
+ it 'logs related information' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ message: "security report schema validation problem",
+ security_report_type: report_type,
+ security_report_version: report_version,
+ project_id: project.id,
+ security_report_failure: 'using_unsupported_schema_version',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
- it { is_expected.to be_falsey }
+ subject
+ end
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ context 'and scanner information is empty' do
+ let(:scanner) { {} }
it 'logs related information' do
expect(Gitlab::AppLogger).to receive(:info).with(
@@ -199,79 +246,26 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
security_report_type: report_type,
security_report_version: report_version,
project_id: project.id,
+ security_report_failure: 'schema_validation_fails',
+ security_report_scanner_id: nil,
+ security_report_scanner_version: nil
+ )
+
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ message: "security report schema validation problem",
+ security_report_type: report_type,
+ security_report_version: report_version,
+ project_id: project.id,
security_report_failure: 'using_unsupported_schema_version',
- security_report_scanner_id: 'gemnasium',
- security_report_scanner_version: '2.1.0'
+ security_report_scanner_id: nil,
+ security_report_scanner_version: nil
)
subject
end
end
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- context 'when scanner information is empty' do
- let(:scanner) { {} }
-
- it 'logs related information' do
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'schema_validation_fails',
- security_report_scanner_id: nil,
- security_report_scanner_version: nil
- )
-
- expect(Gitlab::AppLogger).to receive(:info).with(
- message: "security report schema validation problem",
- security_report_type: report_type,
- security_report_version: report_version,
- project_id: project.id,
- security_report_failure: 'using_unsupported_schema_version',
- security_report_scanner_id: nil,
- security_report_scanner_version: nil
- )
-
- subject
- end
- end
-
- it { is_expected.to be_falsey }
- end
- end
-
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to be_falsey }
end
end
@@ -284,19 +278,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
- before do
- stub_feature_flags(enforce_security_report_validation: true)
- end
-
it { is_expected.to be_falsey }
-
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- it { is_expected.to be_truthy }
- end
end
end
@@ -307,7 +289,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'when the report is valid' do
+ context 'and the report is valid' do
let(:report_data) do
{
'version' => report_version,
@@ -318,34 +300,20 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to be_empty }
end
- context 'when the report is invalid' do
+ context 'and the report is invalid' do
let(:report_data) do
{
'version' => report_version
}
end
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: project)
- end
-
- let(:expected_errors) do
- [
- 'root is missing required keys: vulnerabilities'
- ]
- end
-
- it { is_expected.to match_array(expected_errors) }
+ let(:expected_errors) do
+ [
+ 'root is missing required keys: vulnerabilities'
+ ]
end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- it { is_expected.to be_empty }
- end
+ it { is_expected.to match_array(expected_errors) }
end
end
@@ -363,7 +331,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_const("#{described_class}::DEPRECATED_VERSIONS", deprecations_hash)
end
- context 'when the report passes schema validation' do
+ context 'and the report passes schema validation' do
let(:report_data) do
{
'version' => '10.0.0',
@@ -374,119 +342,77 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to be_empty }
end
- context 'when the report does not pass schema validation' do
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
- end
-
- let(:report_data) do
- {
- 'version' => 'V2.7.0'
- }
- end
-
- let(:expected_errors) do
- [
- "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "root is missing required keys: vulnerabilities"
- ]
- end
-
- it { is_expected.to match_array(expected_errors) }
+ context 'and the report does not pass schema validation' do
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- let(:report_data) do
- {
- 'version' => 'V2.7.0'
- }
- end
-
- it { is_expected.to be_empty }
+ let(:expected_errors) do
+ [
+ "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "root is missing required keys: vulnerabilities"
+ ]
end
+
+ it { is_expected.to match_array(expected_errors) }
end
end
context 'when given an unsupported schema version' do
let(:report_type) { :dast }
let(:report_version) { "12.37.0" }
+ let(:expected_unsupported_message) do
+ "Version #{report_version} for report type #{report_type} is unsupported, supported versions for this report type are: "\
+ "#{supported_dast_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"
+ end
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
end
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- let(:expected_errors) do
- [
- "Version 12.37.0 for report type dast is unsupported, supported versions for this report type are: #{supported_dast_versions}"
- ]
- end
-
- it { is_expected.to match_array(expected_errors) }
+ let(:expected_errors) do
+ [
+ expected_unsupported_message
+ ]
end
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- let(:expected_errors) do
- [
- "Version 12.37.0 for report type dast is unsupported, supported versions for this report type are: #{supported_dast_versions}",
- "root is missing required keys: vulnerabilities"
- ]
- end
-
- it { is_expected.to match_array(expected_errors) }
- end
+ it { is_expected.to match_array(expected_errors) }
end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
end
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
+ let(:expected_errors) do
+ [
+ expected_unsupported_message,
+ "root is missing required keys: vulnerabilities"
+ ]
end
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it { is_expected.to match_array(expected_errors) }
end
end
context 'when not given a schema version' do
let(:report_type) { :dast }
let(:report_version) { nil }
+ let(:expected_missing_version_message) do
+ "Report version not provided, #{report_type} report type supports versions: #{supported_dast_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"
+ end
+
let(:report_data) do
{
'vulnerabilities' => []
@@ -496,19 +422,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:expected_errors) do
[
"root is missing required keys: version",
- "Report version not provided, dast report type supports versions: #{supported_dast_versions}"
+ expected_missing_version_message
]
end
it { is_expected.to match_array(expected_errors) }
-
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- it { is_expected.to be_empty }
- end
end
end
@@ -519,7 +437,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- context 'when the report is valid' do
+ context 'and the report is valid' do
let(:report_data) do
{
'version' => report_version,
@@ -530,7 +448,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to be_empty }
end
- context 'when the report is invalid' do
+ context 'and the report is invalid' do
let(:report_data) do
{
'version' => report_version
@@ -550,9 +468,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end
let(:report_version) { described_class::DEPRECATED_VERSIONS[report_type].last }
+ let(:expected_deprecation_message) do
+ "Version #{report_version} for report type #{report_type} has been deprecated, supported versions for this "\
+ "report type are: #{supported_dast_versions}. GitLab will attempt to parse and ingest this report if valid."
+ end
+
let(:expected_deprecation_warnings) do
[
- "Version V2.7.0 for report type dast has been deprecated, supported versions for this report type are: #{supported_dast_versions}"
+ expected_deprecation_message
]
end
@@ -560,7 +483,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_const("#{described_class}::DEPRECATED_VERSIONS", deprecations_hash)
end
- context 'when the report passes schema validation' do
+ context 'and the report passes schema validation' do
let(:report_data) do
{
'version' => report_version,
@@ -571,7 +494,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to match_array(expected_deprecation_warnings) }
end
- context 'when the report does not pass schema validation' do
+ context 'and the report does not pass schema validation' do
let(:report_data) do
{
'version' => 'V2.7.0'
@@ -600,11 +523,27 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
describe '#warnings' do
subject { validator.warnings }
- context 'when given a supported schema version' do
+ context 'when given a supported MAJOR.MINOR schema version' do
let(:report_type) { :dast }
- let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
+ let(:report_version) do
+ latest_vendored_version = described_class::SUPPORTED_VERSIONS[report_type].last.split(".")
+ (latest_vendored_version[0...2] << "34").join(".")
+ end
+
+ let(:latest_patch_version) do
+ ::Security::ReportSchemaVersionMatcher.new(
+ report_declared_version: report_version,
+ supported_versions: described_class::SUPPORTED_VERSIONS[report_type]
+ ).call
+ end
+
+ let(:message) do
+ "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"\
+ " #{latest_patch_version}"
+ end
- context 'when the report is valid' do
+ context 'and the report is valid' do
let(:report_data) do
{
'version' => report_version,
@@ -612,37 +551,57 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
}
end
- it { is_expected.to be_empty }
+ it { is_expected.to match_array([message]) }
end
- context 'when the report is invalid' do
+ context 'and the report is invalid' do
let(:report_data) do
{
'version' => report_version
}
end
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: project)
- end
+ it { is_expected.to match_array([message]) }
+
+ it 'logs related information' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ message: "security report schema validation problem",
+ security_report_type: report_type,
+ security_report_version: report_version,
+ project_id: project.id,
+ security_report_failure: 'schema_validation_fails',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
- it { is_expected.to be_empty }
+ subject
end
+ end
+ end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
+ context 'when given a supported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- let(:expected_warnings) do
- [
- 'root is missing required keys: vulnerabilities'
- ]
- end
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ it { is_expected.to be_empty }
+ end
- it { is_expected.to match_array(expected_warnings) }
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
end
+
+ it { is_expected.to be_empty }
end
end
@@ -660,7 +619,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_const("#{described_class}::DEPRECATED_VERSIONS", deprecations_hash)
end
- context 'when the report passes schema validation' do
+ context 'and the report passes schema validation' do
let(:report_data) do
{
'vulnerabilities' => []
@@ -670,35 +629,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
it { is_expected.to be_empty }
end
- context 'when the report does not pass schema validation' do
+ context 'and the report does not pass schema validation' do
let(:report_data) do
{
'version' => 'V2.7.0'
}
end
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
- end
-
- it { is_expected.to be_empty }
- end
-
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- let(:expected_warnings) do
- [
- "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
- "root is missing required keys: vulnerabilities"
- ]
- end
-
- it { is_expected.to match_array(expected_warnings) }
- end
+ it { is_expected.to be_empty }
end
end
@@ -706,71 +644,25 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:report_type) { :dast }
let(:report_version) { "12.37.0" }
- context 'when enforce_security_report_validation is enabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: true)
- end
-
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- it { is_expected.to be_empty }
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
end
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- it { is_expected.to be_empty }
- end
+ it { is_expected.to be_empty }
end
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- context 'when the report is valid' do
- let(:report_data) do
- {
- 'version' => report_version,
- 'vulnerabilities' => []
- }
- end
-
- let(:expected_warnings) do
- [
- "Version 12.37.0 for report type dast is unsupported, supported versions for this report type are: #{supported_dast_versions}"
- ]
- end
-
- it { is_expected.to match_array(expected_warnings) }
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
end
- context 'when the report is invalid' do
- let(:report_data) do
- {
- 'version' => report_version
- }
- end
-
- let(:expected_warnings) do
- [
- "Version 12.37.0 for report type dast is unsupported, supported versions for this report type are: #{supported_dast_versions}",
- "root is missing required keys: vulnerabilities"
- ]
- end
-
- it { is_expected.to match_array(expected_warnings) }
- end
+ it { is_expected.to be_empty }
end
end
@@ -784,21 +676,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end
it { is_expected.to be_empty }
-
- context 'when enforce_security_report_validation is disabled' do
- before do
- stub_feature_flags(enforce_security_report_validation: false)
- end
-
- let(:expected_warnings) do
- [
- "root is missing required keys: version",
- "Report version not provided, dast report type supports versions: #{supported_dast_versions}"
- ]
- end
-
- it { is_expected.to match_array(expected_warnings) }
- end
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index 0d78ce3440a..de43e759193 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -282,7 +282,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
subject { command.ambiguous_ref? }
context 'when ref is not ambiguous' do
- it { is_expected. to eq(false) }
+ it { is_expected.to eq(false) }
end
context 'when ref is ambiguous' do
@@ -291,7 +291,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Command do
project.repository.add_branch(project.creator, 'ref', 'master')
end
- it { is_expected. to eq(true) }
+ it { is_expected.to eq(true) }
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
index cbf92f8fa83..be5d3a96126 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CreateDeployments do
end
context 'when the corresponding environment does not exist' do
- let!(:environment) { }
+ let!(:environment) {}
it 'does not create a deployment record' do
expect { subject }.not_to change { Deployment.count }
diff --git a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
index e30a78546af..eb5a37f19f4 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules do
before do
allow(step).to receive(:workflow_rules_result)
.and_return(
- double(pass?: true, variables: { 'VAR1' => 'val2' })
+ double(pass?: true, variables: { 'VAR1' => 'val2', 'VAR2' => 3 })
)
step.perform!
@@ -65,7 +65,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EvaluateWorkflowRules do
end
it 'saves workflow_rules_result' do
- expect(command.workflow_rules_result.variables).to eq({ 'VAR1' => 'val2' })
+ expect(command.workflow_rules_result.variables).to eq({ 'VAR1' => 'val2', 'VAR2' => 3 })
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
index fabfbd779f3..5ee96b0baa8 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Chain::SeedBlock do
let(:project) { create(:project, :repository) }
let(:user) { create(:user, developer_projects: [project]) }
- let(:seeds_block) { }
+ let(:seeds_block) {}
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
index 687bb82a8ef..f7774e199fb 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_projects: [project]) }
- let(:seeds_block) { }
+ let(:seeds_block) {}
let(:command) { initialize_command }
let(:pipeline) { build(:ci_pipeline, project: project) }
@@ -205,6 +205,30 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Seed do
end
end
+ describe '#rule_variables' do
+ let(:config) do
+ {
+ variables: { VAR1: 11 },
+ workflow: {
+ rules: [{ if: '$CI_PIPELINE_SOURCE',
+ variables: { SYMBOL: :symbol, STRING: "string", INTEGER: 1 } },
+ { when: 'always' }]
+ },
+ rspec: { script: 'rake' }
+ }
+ end
+
+ let(:rspec_variables) { command.pipeline_seed.stages[0].statuses[0].variables.to_hash }
+
+ it 'correctly parses rule variables' do
+ run_chain
+
+ expect(rspec_variables['SYMBOL']).to eq("symbol")
+ expect(rspec_variables['STRING']).to eq("string")
+ expect(rspec_variables['INTEGER']).to eq("1")
+ end
+ end
+
context 'N+1 queries' do
it 'avoids N+1 queries when calculating variables of jobs', :use_sql_query_cache do
warm_up_pipeline, warm_up_command = prepare_pipeline1
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index eeac0c85a77..fb1a360a4b7 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -148,6 +148,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
payload = Gitlab::Json.parse(params[:body])
+ expect(payload['total_builds_count']).to eq(0)
+
builds = payload['builds']
expect(builds.count).to eq(2)
expect(builds[0]['services']).to be_nil
@@ -160,6 +162,23 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
perform!
end
+
+ context "with existing jobs from other project's alive pipelines" do
+ before do
+ create(:ci_pipeline, :with_job, user: user)
+ create(:ci_pipeline, :with_job)
+ end
+
+ it 'returns the expected total_builds_count' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['total_builds_count']).to eq(1)
+ end
+
+ perform!
+ end
+ end
end
context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
@@ -243,7 +262,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
context 'when save_incompleted is false' do
- let(:save_incompleted) { false}
+ let(:save_incompleted) { false }
it 'adds errors to the pipeline without dropping it' do
perform!
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
index 83742699d3d..47f172922a5 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/matches_spec.rb
@@ -160,14 +160,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::Matches do
let(:left_value) { 'abcde' }
it { is_expected.to eq(true) }
-
- context 'when the FF ci_fix_rules_if_comparison_with_regexp_variable is disabled' do
- before do
- stub_feature_flags(ci_fix_rules_if_comparison_with_regexp_variable: false)
- end
-
- it { is_expected.to eq(false) }
- end
end
context 'when not matching' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb
index aad33106647..9e7ea3e4ea4 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/not_matches_spec.rb
@@ -160,14 +160,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::NotMatches do
let(:left_value) { 'abcde' }
it { is_expected.to eq(false) }
-
- context 'when the FF ci_fix_rules_if_comparison_with_regexp_variable is disabled' do
- before do
- stub_feature_flags(ci_fix_rules_if_comparison_with_regexp_variable: false)
- end
-
- it { is_expected.to eq(true) }
- end
end
context 'when not matching' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
index bbd11a00149..acaec07f95b 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
@@ -179,24 +179,16 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Statement do
.to_hash
end
- where(:expression, :ff, :result) do
- '$teststring =~ "abcde"' | true | true
- '$teststring =~ "abcde"' | false | true
- '$teststring =~ $teststring' | true | true
- '$teststring =~ $teststring' | false | true
- '$teststring =~ $pattern1' | true | true
- '$teststring =~ $pattern1' | false | false
- '$teststring =~ $pattern2' | true | false
- '$teststring =~ $pattern2' | false | false
+ where(:expression, :result) do
+ '$teststring =~ "abcde"' | true
+ '$teststring =~ $teststring' | true
+ '$teststring =~ $pattern1' | true
+ '$teststring =~ $pattern2' | false
end
with_them do
let(:text) { expression }
- before do
- stub_feature_flags(ci_fix_rules_if_comparison_with_regexp_variable: ff)
- end
-
it { is_expected.to eq(result) }
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
index 8f727749ee2..a742c619584 100644
--- a/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/quota/deployments_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Quota::Deployments do
let(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
- let(:pipeline_seed) { double(:pipeline_seed, deployments_count: 2)}
+ let(:pipeline_seed) { double(:pipeline_seed, deployments_count: 2) }
let(:command) do
double(:command,
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 040f3ab5830..75f6a773c2d 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -97,15 +97,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- job_variables: [{ key: 'VAR1', value: 'var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true }],
+ job_variables: [{ key: 'VAR1', value: 'var 1' },
+ { key: 'VAR2', value: 'var 2' }],
rules: [{ if: '$VAR == null', variables: { VAR1: 'new var 1', VAR3: 'var 3' } }] }
end
it do
- is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }])
+ is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1' },
+ { key: 'VAR3', value: 'var 3' },
+ { key: 'VAR2', value: 'var 2' }])
end
end
@@ -114,13 +114,13 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
{
name: 'rspec',
ref: 'master',
- job_variables: [{ key: 'VARIABLE', value: 'value', public: true }],
+ job_variables: [{ key: 'VARIABLE', value: 'value' }],
tag_list: ['static-tag', '$VARIABLE', '$NO_VARIABLE']
}
end
it { is_expected.to include(tag_list: ['static-tag', 'value', '$NO_VARIABLE']) }
- it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value', public: true }]) }
+ it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value' }]) }
end
context 'with cache:key' do
@@ -257,19 +257,19 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- yaml_variables: [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }],
- job_variables: [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }],
+ yaml_variables: [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }],
+ job_variables: [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }],
root_variables_inheritance: root_variables_inheritance }
end
context 'when the pipeline has variables' do
let(:root_variables) do
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var pipeline 2', public: true },
- { key: 'VAR3', value: 'var pipeline 3', public: true },
- { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var pipeline 2' },
+ { key: 'VAR3', value: 'var pipeline 3' },
+ { key: 'VAR4', value: 'new var pipeline 4' }]
end
context 'when root_variables_inheritance is true' do
@@ -277,10 +277,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true },
- { key: 'VAR4', value: 'new var pipeline 4', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' },
+ { key: 'VAR4', value: 'new var pipeline 4' }]
)
end
end
@@ -290,8 +290,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns job variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }]
+ [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }]
)
end
end
@@ -301,9 +301,9 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
- { key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }]
+ [{ key: 'VAR1', value: 'var overridden pipeline 1' },
+ { key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }]
)
end
end
@@ -314,8 +314,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns seed yaml variables' do
expect(subject[:yaml_variables]).to match_array(
- [{ key: 'VAR2', value: 'var 2', public: true },
- { key: 'VAR3', value: 'var 3', public: true }])
+ [{ key: 'VAR2', value: 'var 2' },
+ { key: 'VAR3', value: 'var 3' }])
end
end
end
@@ -324,8 +324,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
- yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
- job_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
+ yaml_variables: [{ key: 'VAR1', value: 'var 1' }],
+ job_variables: [{ key: 'VAR1', value: 'var 1' }],
root_variables_inheritance: root_variables_inheritance,
rules: rules }
end
@@ -338,14 +338,14 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
it 'recalculates the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
- { key: 'VAR2', value: 'new var 2', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' },
+ { key: 'VAR2', value: 'new var 2' })
end
end
context 'when the rules use root variables' do
let(:root_variables) do
- [{ key: 'VAR2', value: 'var pipeline 2', public: true }]
+ [{ key: 'VAR2', value: 'var pipeline 2' }]
end
let(:rules) do
@@ -353,15 +353,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
it 'recalculates the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
- { key: 'VAR2', value: 'overridden var 2', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1' },
+ { key: 'VAR2', value: 'overridden var 2' })
end
context 'when the root_variables_inheritance is false' do
let(:root_variables_inheritance) { false }
it 'does not recalculate the variables' do
- expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1', public: true })
+ expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1' })
end
end
end
@@ -769,7 +769,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
with_them do
it { is_expected.not_to be_included }
- it 'correctly populates when:' do
+ it 'still correctly populates when:' do
expect(seed_build.attributes).to include(when: 'never')
end
end
@@ -958,6 +958,26 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
expect(seed_build.attributes).to include(when: 'never')
end
end
+
+ context 'with invalid rules raising error' do
+ let(:rule_set) do
+ [
+ { changes: { paths: ['README.md'], compare_to: 'invalid-ref' }, when: 'never' }
+ ]
+ end
+
+ it { is_expected.not_to be_included }
+
+ it 'correctly populates when:' do
+ expect(seed_build.attributes).to include(when: 'never')
+ end
+
+ it 'returns an error' do
+ expect(seed_build.errors).to contain_exactly(
+ 'Failed to parse rule for rspec: rules:changes:compare_to is not a valid ref'
+ )
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/reports/sbom/component_spec.rb b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
new file mode 100644
index 00000000000..672117c311f
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/sbom/component_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::Sbom::Component do
+ let(:attributes) do
+ {
+ 'type' => 'library',
+ 'name' => 'component-name',
+ 'version' => 'v0.0.1'
+ }
+ end
+
+ subject { described_class.new(attributes) }
+
+ it 'has correct attributes' do
+ expect(subject).to have_attributes(
+ component_type: 'library',
+ name: 'component-name',
+ version: 'v0.0.1'
+ )
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/sbom/report_spec.rb b/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
new file mode 100644
index 00000000000..d7a285ab13c
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/sbom/report_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::Sbom::Report do
+ subject(:report) { described_class.new }
+
+ describe '#add_error' do
+ it 'appends errors to a list' do
+ report.add_error('error1')
+ report.add_error('error2')
+
+ expect(report.errors).to match_array(%w[error1 error2])
+ end
+ end
+
+ describe '#set_source' do
+ let_it_be(:source) do
+ {
+ 'type' => :dependency_scanning,
+ 'data' => {
+ 'input_file' => { 'path' => 'package-lock.json' },
+ 'source_file' => { 'path' => 'package.json' },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ },
+ 'fingerprint' => 'c01df1dc736c1148717e053edbde56cb3a55d3e31f87cea955945b6f67c17d42'
+ }
+ end
+
+ it 'stores the source' do
+ report.set_source(source)
+
+ expect(report.source).to be_a(Gitlab::Ci::Reports::Sbom::Source)
+ end
+ end
+
+ describe '#add_component' do
+ let_it_be(:components) do
+ [
+ { 'type' => 'library', 'name' => 'component1', 'version' => 'v0.0.1' },
+ { 'type' => 'library', 'name' => 'component2', 'version' => 'v0.0.2' },
+ { 'type' => 'library', 'name' => 'component2' }
+ ]
+ end
+
+ it 'appends components to a list' do
+ components.each { |component| report.add_component(component) }
+
+ expect(report.components.size).to eq(3)
+ expect(report.components).to all(be_a(Gitlab::Ci::Reports::Sbom::Component))
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb b/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb
new file mode 100644
index 00000000000..97d8d7abb33
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/sbom/reports_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::Sbom::Reports do
+ subject(:reports_list) { described_class.new }
+
+ describe '#add_report' do
+ let(:rep1) { Gitlab::Ci::Reports::Sbom::Report.new }
+ let(:rep2) { Gitlab::Ci::Reports::Sbom::Report.new }
+
+ it 'appends the report to the report list' do
+ reports_list.add_report(rep1)
+ reports_list.add_report(rep2)
+
+ expect(reports_list.reports.length).to eq(2)
+ expect(reports_list.reports.first).to eq(rep1)
+ expect(reports_list.reports.last).to eq(rep2)
+ 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
new file mode 100644
index 00000000000..2d6434534a0
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Reports::Sbom::Source do
+ let(:attributes) do
+ {
+ 'type' => :dependency_scanning,
+ 'data' => {
+ 'category' => 'development',
+ 'input_file' => { 'path' => 'package-lock.json' },
+ 'source_file' => { 'path' => 'package.json' },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ },
+ 'fingerprint' => '4dbcb747e6f0fb3ed4f48d96b777f1d64acdf43e459fdfefad404e55c004a188'
+ }
+ end
+
+ subject { described_class.new(attributes) }
+
+ it 'has correct attributes' do
+ expect(subject).to have_attributes(
+ source_type: attributes['type'],
+ data: attributes['data'],
+ fingerprint: attributes['fingerprint']
+ )
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/security/reports_spec.rb b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
index 79eee642552..e240edc4a12 100644
--- a/spec/lib/gitlab/ci/reports/security/reports_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/reports_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Reports do
let(:high_severity_dast) { build(:ci_reports_security_finding, severity: 'high', report_type: 'dast') }
let(:vulnerabilities_allowed) { 0 }
let(:severity_levels) { %w(critical high) }
- let(:vulnerability_states) { %w(newly_detected)}
+ let(:vulnerability_states) { %w(newly_detected) }
subject { security_reports.violates_default_policy_against?(target_reports, vulnerabilities_allowed, severity_levels, vulnerability_states) }
diff --git a/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb
index 44e66fd9028..6f75e2c55e8 100644
--- a/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb
+++ b/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::VulnerabilityReportsComparer do
end
describe '#added' do
- let(:new_location) {build(:ci_reports_security_locations_sast, :dynamic) }
+ let(:new_location) { build(:ci_reports_security_locations_sast, :dynamic) }
let(:vul_params) { vuln_params(project.id, [identifier], confidence: :high) }
let(:vuln) { build(:ci_reports_security_finding, severity: Enums::Vulnerability.severity_levels[:critical], location: new_location, **vul_params) }
let(:low_vuln) { build(:ci_reports_security_finding, severity: Enums::Vulnerability.severity_levels[:low], location: new_location, **vul_params) }
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
index 1d6b39a7831..4a1f77bed65 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
subject { test_suite.with_attachment! }
context 'when test cases do not contain an attachment' do
- let(:test_case) { build(:report_test_case, :failed)}
+ let(:test_case) { build(:report_test_case, :failed) }
before do
test_suite.add_test_case(test_case)
@@ -103,7 +103,7 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
end
context 'when test cases contain an attachment' do
- let(:test_case_with_attachment) { build(:report_test_case, :failed_with_attachment)}
+ let(:test_case_with_attachment) { build(:report_test_case, :failed_with_attachment) }
before do
test_suite.add_test_case(test_case_with_attachment)
diff --git a/spec/lib/gitlab/ci/runner_releases_spec.rb b/spec/lib/gitlab/ci/runner_releases_spec.rb
index 576eb02ad83..ad1e9b12b8a 100644
--- a/spec/lib/gitlab/ci/runner_releases_spec.rb
+++ b/spec/lib/gitlab/ci/runner_releases_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerReleases do
subject { described_class.instance }
- let(:runner_releases_url) { 'the release API URL' }
+ let(:runner_releases_url) { 'http://testurl.com/runner_public_releases' }
def releases
subject.releases
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Ci::RunnerReleases do
before do
subject.reset_backoff!
- stub_application_setting(public_runner_releases_url: runner_releases_url)
+ allow(subject).to receive(:runner_releases_url).and_return(runner_releases_url)
end
describe 'caching behavior', :use_clean_rails_memory_store_caching do
@@ -77,7 +77,8 @@ RSpec.describe Gitlab::Ci::RunnerReleases do
allow(Gitlab::HTTP).to receive(:get).with(runner_releases_url, anything) do
http_call_timestamp_offsets << Time.now.utc - start_time
- raise Net::OpenTimeout if opts&.dig(:raise_timeout)
+ err_class = opts&.dig(:raise_error)
+ raise err_class if err_class
mock_http_response(response)
end
@@ -113,12 +114,13 @@ RSpec.describe Gitlab::Ci::RunnerReleases do
end
context 'when request results in timeout' do
- let(:response) { }
+ let(:response) {}
let(:expected_releases) { nil }
let(:expected_releases_by_minor) { nil }
it_behaves_like 'requests that follow cache status', 5.seconds
- it_behaves_like 'a service implementing exponential backoff', raise_timeout: true
+ it_behaves_like 'a service implementing exponential backoff', raise_error: Net::OpenTimeout
+ it_behaves_like 'a service implementing exponential backoff', raise_error: Errno::ETIMEDOUT
end
context 'when response is nil' do
diff --git a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
index f2507a24b10..55c3834bfa7 100644
--- a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
+++ b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
@@ -5,36 +5,35 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
using RSpec::Parameterized::TableSyntax
- describe '#check_runner_upgrade_status' do
- subject(:result) { described_class.instance.check_runner_upgrade_status(runner_version) }
+ subject(:instance) { described_class.new(gitlab_version, runner_releases) }
+
+ describe '#check_runner_upgrade_suggestion' do
+ subject(:result) { instance.check_runner_upgrade_suggestion(runner_version) }
let(:gitlab_version) { '14.1.1' }
let(:parsed_runner_version) { ::Gitlab::VersionInfo.parse(runner_version, parse_suffix: true) }
-
- before do
- allow(described_class.instance).to receive(:gitlab_version)
- .and_return(::Gitlab::VersionInfo.parse(gitlab_version))
- end
+ let(:runner_releases) { instance_double(Gitlab::Ci::RunnerReleases) }
context 'with failing Gitlab::Ci::RunnerReleases request' do
let(:runner_version) { '14.1.123' }
- let(:runner_releases_double) { instance_double(Gitlab::Ci::RunnerReleases) }
before do
- allow(Gitlab::Ci::RunnerReleases).to receive(:instance).and_return(runner_releases_double)
- allow(runner_releases_double).to receive(:releases).and_return(nil)
+ allow(runner_releases).to receive(:releases).and_return(nil)
end
it 'returns :error' do
- is_expected.to eq({ error: parsed_runner_version })
+ is_expected.to eq([parsed_runner_version, :error])
end
end
context 'with available_runner_releases configured' do
- before do
- url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+ let(:runner_releases) { Gitlab::Ci::RunnerReleases.instance }
+ let(:runner_releases_url) do
+ ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+ end
- WebMock.stub_request(:get, url).to_return(
+ before do
+ WebMock.stub_request(:get, runner_releases_url).to_return(
body: available_runner_releases.map { |v| { name: v } }.to_json,
status: 200,
headers: { 'Content-Type' => 'application/json' }
@@ -53,7 +52,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:runner_version) { 'v14.0.1' }
it 'returns :not_available' do
- is_expected.to eq({ not_available: parsed_runner_version })
+ is_expected.to eq([parsed_runner_version, :not_available])
end
end
end
@@ -68,7 +67,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:runner_version) { nil }
it 'returns :invalid_version' do
- is_expected.to match({ invalid_version: anything })
+ is_expected.to match([anything, :invalid_version])
end
end
@@ -76,7 +75,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:runner_version) { 'junk' }
it 'returns :invalid_version' do
- is_expected.to match({ invalid_version: anything })
+ is_expected.to match([anything, :invalid_version])
end
end
@@ -87,7 +86,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:runner_version) { 'v14.2.0' }
it 'returns :not_available' do
- is_expected.to eq({ not_available: parsed_runner_version })
+ is_expected.to eq([parsed_runner_version, :not_available])
end
end
end
@@ -96,7 +95,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:gitlab_version) { '14.0.1' }
context 'with valid params' do
- where(:runner_version, :expected_result, :expected_suggested_version) do
+ where(:runner_version, :expected_status, :expected_suggested_version) do
'v15.0.0' | :not_available | '15.0.0' # not available since the GitLab instance is still on 14.x, a major version might be incompatible, and a patch upgrade is not available
'v14.1.0-rc3' | :recommended | '14.1.1' # recommended since even though the GitLab instance is still on 14.0.x, there is a patch release (14.1.1) available which might contain security fixes
'v14.1.0~beta.1574.gf6ea9389' | :recommended | '14.1.1' # suffixes are correctly handled
@@ -116,7 +115,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
end
with_them do
- it { is_expected.to eq({ expected_result => Gitlab::VersionInfo.parse(expected_suggested_version) }) }
+ it { is_expected.to eq([Gitlab::VersionInfo.parse(expected_suggested_version), expected_status]) }
end
end
end
@@ -125,7 +124,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:gitlab_version) { '13.9.0' }
context 'with valid params' do
- where(:runner_version, :expected_result, :expected_suggested_version) do
+ where(:runner_version, :expected_status, :expected_suggested_version) do
'v14.0.0' | :recommended | '14.0.2' # recommended upgrade since 14.0.2 is available, even though the GitLab instance is still on 13.x and a major version might be incompatible
'v13.10.1' | :not_available | '13.10.1' # not available since 13.10.1 is already ahead of GitLab instance version and is the latest patch update for 13.10.x
'v13.10.0' | :recommended | '13.10.1' # recommended upgrade since 13.10.1 is available
@@ -136,7 +135,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
end
with_them do
- it { is_expected.to eq({ expected_result => Gitlab::VersionInfo.parse(expected_suggested_version) }) }
+ it { is_expected.to eq([Gitlab::VersionInfo.parse(expected_suggested_version), expected_status]) }
end
end
end
@@ -152,7 +151,7 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
let(:runner_version) { '14.11.0~beta.29.gd0c550e3' }
it 'recommends 15.1.0 since 14.11 is an unknown release and 15.1.0 is available' do
- is_expected.to eq({ recommended: Gitlab::VersionInfo.new(15, 1, 0) })
+ is_expected.to eq([Gitlab::VersionInfo.new(15, 1, 0), :recommended])
end
end
end
diff --git a/spec/lib/gitlab/ci/status/bridge/common_spec.rb b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
index 30e6ad234a0..37524afc83d 100644
--- a/spec/lib/gitlab/ci/status/bridge/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
@@ -29,15 +29,7 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Common do
end
it { expect(subject).to have_details }
- it { expect(subject.details_path).to include "jobs/#{bridge.id}" }
-
- context 'with ci_retry_downstream_pipeline ff disabled' do
- before do
- stub_feature_flags(ci_retry_downstream_pipeline: false)
- end
-
- it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
- end
+ it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
end
context 'when user does not have access to read downstream pipeline' do
diff --git a/spec/lib/gitlab/ci/status/build/canceled_spec.rb b/spec/lib/gitlab/ci/status/build/canceled_spec.rb
index e30a2211c8f..519b970ca5e 100644
--- a/spec/lib/gitlab/ci/status/build/canceled_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/canceled_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Ci::Status::Build::Canceled do
end
describe '.matches?' do
- subject {described_class.matches?(build, user) }
+ subject { described_class.matches?(build, user) }
context 'when build is canceled' do
let(:build) { create(:ci_build, :canceled) }
diff --git a/spec/lib/gitlab/ci/status/build/created_spec.rb b/spec/lib/gitlab/ci/status/build/created_spec.rb
index 49468674140..9738b3c1f36 100644
--- a/spec/lib/gitlab/ci/status/build/created_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/created_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Ci::Status::Build::Created do
end
describe '.matches?' do
- subject {described_class.matches?(build, user) }
+ subject { described_class.matches?(build, user) }
context 'when build is created' do
let(:build) { create(:ci_build, :created) }
diff --git a/spec/lib/gitlab/ci/status/build/manual_spec.rb b/spec/lib/gitlab/ci/status/build/manual_spec.rb
index 150705c1e36..a1152cb77e3 100644
--- a/spec/lib/gitlab/ci/status/build/manual_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/manual_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Ci::Status::Build::Manual do
end
describe '.matches?' do
- subject {described_class.matches?(build, user) }
+ subject { described_class.matches?(build, user) }
context 'when build is manual' do
let(:build) { create(:ci_build, :manual) }
diff --git a/spec/lib/gitlab/ci/status/build/pending_spec.rb b/spec/lib/gitlab/ci/status/build/pending_spec.rb
index 7b695d33877..b7dda9ce9c9 100644
--- a/spec/lib/gitlab/ci/status/build/pending_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/pending_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Ci::Status::Build::Pending do
end
describe '.matches?' do
- subject {described_class.matches?(build, user) }
+ subject { described_class.matches?(build, user) }
context 'when build is pending' do
let(:build) { create(:ci_build, :pending) }
diff --git a/spec/lib/gitlab/ci/status/build/skipped_spec.rb b/spec/lib/gitlab/ci/status/build/skipped_spec.rb
index 0b998a52a57..4437ac0089f 100644
--- a/spec/lib/gitlab/ci/status/build/skipped_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/skipped_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Ci::Status::Build::Skipped do
end
describe '.matches?' do
- subject {described_class.matches?(build, user) }
+ subject { described_class.matches?(build, user) }
context 'when build is skipped' do
let(:build) { create(:ci_build, :skipped) }
diff --git a/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb b/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb
index 91a9724d043..26087fd771c 100644
--- a/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb
+++ b/spec/lib/gitlab/ci/status/processable/waiting_for_resource_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Ci::Status::Processable::WaitingForResource do
end
describe '.matches?' do
- subject {described_class.matches?(processable, user) }
+ subject { described_class.matches?(processable, user) }
context 'when processable is waiting for resource' do
let(:processable) { create(:ci_build, :waiting_for_resource) }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
index 0f97bc06a4e..5ff179b6fee 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
@@ -36,9 +36,10 @@ RSpec.describe 'Jobs/SAST-IaC.latest.gitlab-ci.yml' do
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) { service.execute(merge_request).payload }
- it 'has no jobs' do
+ it 'creates a pipeline with the expected jobs' do
expect(pipeline).to be_merge_request_event
- expect(build_names).to be_empty
+ expect(pipeline.errors.full_messages).to be_empty
+ expect(build_names).to match_array(%w(kics-iac-sast))
end
end
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 78d3982a79f..1a909f52ec3 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
context 'when the project is set for deployment to AWS' do
let(:platform_value) { 'ECS' }
- let(:review_prod_build_names) { build_names.select {|n| n.include?('review') || n.include?('production')} }
+ let(:review_prod_build_names) { build_names.select { |n| n.include?('review') || n.include?('production') } }
before do
create(:ci_variable, project: project, key: 'AUTO_DEVOPS_PLATFORM_TARGET', value: platform_value)
diff --git a/spec/lib/gitlab/ci/trace/remote_checksum_spec.rb b/spec/lib/gitlab/ci/trace/remote_checksum_spec.rb
index 1cd88034166..be29543676f 100644
--- a/spec/lib/gitlab/ci/trace/remote_checksum_spec.rb
+++ b/spec/lib/gitlab/ci/trace/remote_checksum_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe Gitlab::Ci::Trace::RemoteChecksum do
end
context 'when the response does not include :content_md5' do
- let(:metadata) {{}}
+ let(:metadata) { {} }
it 'raises an exception' do
expect { subject }.to raise_error KeyError, /content_md5/
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::Ci::Trace::RemoteChecksum do
end
context 'when the response include :content_md5' do
- let(:metadata) {{ content_md5: base64checksum }}
+ let(:metadata) { { content_md5: base64checksum } }
it { is_expected.to eq(checksum) }
end
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 8ec0846bdca..6ab2089cce8 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Variables::Builder do
+ include Ci::TemplateHelpers
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :repository, namespace: group) }
let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) }
@@ -92,6 +93,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
value: project.pages_url },
{ key: 'CI_API_V4_URL',
value: API::Helpers::Version.new('v4').root_url },
+ { key: 'CI_TEMPLATE_REGISTRY_HOST',
+ value: template_registry_host },
{ key: 'CI_PIPELINE_IID',
value: pipeline.iid.to_s },
{ key: 'CI_PIPELINE_SOURCE',
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index 26c560565e0..8ac03301322 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -302,6 +302,7 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
.append(key: 'CI_BUILD_ID', value: '1')
.append(key: 'RAW_VAR', value: '$TEST1', raw: true)
.append(key: 'TEST1', value: 'test-3')
+ .append(key: 'FILEVAR1', value: 'file value 1', file: true)
end
context 'table tests' do
@@ -311,28 +312,23 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
{
"empty value": {
value: '',
- result: '',
- keep_undefined: false
+ result: ''
},
"simple expansions": {
value: 'key$TEST1-$CI_BUILD_ID',
- result: 'keytest-3-1',
- keep_undefined: false
+ result: 'keytest-3-1'
},
"complex expansion": {
value: 'key${TEST1}-${CI_JOB_NAME}',
- result: 'keytest-3-test-1',
- keep_undefined: false
+ result: 'keytest-3-test-1'
},
"complex expansions with raw variable": {
value: 'key${RAW_VAR}-${CI_JOB_NAME}',
- result: 'key$TEST1-test-1',
- keep_undefined: false
+ result: 'key$TEST1-test-1'
},
"missing variable not keeping original": {
value: 'key${MISSING_VAR}-${CI_JOB_NAME}',
- result: 'key-test-1',
- keep_undefined: false
+ result: 'key-test-1'
},
"missing variable keeping original": {
value: 'key${MISSING_VAR}-${CI_JOB_NAME}',
@@ -341,14 +337,24 @@ RSpec.describe Gitlab::Ci::Variables::Collection do
},
"escaped characters are kept intact": {
value: 'key-$TEST1-%%HOME%%-$${HOME}',
- result: 'key-test-3-%%HOME%%-$${HOME}',
- keep_undefined: false
+ result: 'key-test-3-%%HOME%%-$${HOME}'
+ },
+ "file variable with expand_file_vars: true": {
+ value: 'key-$FILEVAR1-$TEST1',
+ result: 'key-file value 1-test-3'
+ },
+ "file variable with expand_file_vars: false": {
+ value: 'key-$FILEVAR1-$TEST1',
+ result: 'key-$FILEVAR1-test-3',
+ expand_file_vars: false
}
}
end
with_them do
- subject { collection.expand_value(value, keep_undefined: keep_undefined) }
+ let(:options) { { keep_undefined: keep_undefined, expand_file_vars: expand_file_vars }.compact }
+
+ subject(:result) { collection.expand_value(value, **options) }
it 'matches expected expansion' do
is_expected.to eq(result)
diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb
index f13b334c10e..2a1cdaeb3a7 100644
--- a/spec/lib/gitlab/ci/variables/helpers_spec.rb
+++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb
@@ -15,21 +15,27 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
end
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
subject { described_class.merge_variables(current_variables, new_variables) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when new variables is a hash' do
let(:new_variables) do
{ 'key2' => 'value22', 'key3' => 'value3' }
end
- it { is_expected.to eq(result) }
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
+ end
+
+ it { is_expected.to match_array(result) }
end
context 'when new variables is a hash with symbol keys' do
@@ -37,67 +43,72 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
{ key2: 'value22', key3: 'value3' }
end
- it { is_expected.to eq(result) }
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
+ end
+
+ it { is_expected.to match_array(result) }
end
context 'when new variables is nil' do
let(:new_variables) {}
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
- describe '.transform_to_yaml_variables' do
- let(:variables) do
- { 'key1' => 'value1', 'key2' => 'value2' }
- end
+ describe '.transform_to_array' do
+ subject { described_class.transform_to_array(variables) }
- let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
- end
+ context 'when values are strings' do
+ let(:variables) do
+ { 'key1' => 'value1', 'key2' => 'value2' }
+ end
- subject { described_class.transform_to_yaml_variables(variables) }
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
+ end
context 'when variables is nil' do
let(:variables) {}
- it { is_expected.to eq([]) }
- end
- end
-
- describe '.transform_from_yaml_variables' do
- let(:variables) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value2', public: true }]
+ it { is_expected.to match_array([]) }
end
- let(:result) do
- { 'key1' => 'value1', 'key2' => 'value2' }
- end
+ context 'when values are hashes' do
+ let(:variables) do
+ { 'key1' => { value: 'value1', description: 'var 1' }, 'key2' => { value: 'value2' } }
+ end
- subject { described_class.transform_from_yaml_variables(variables) }
+ let(:result) do
+ [{ key: 'key1', value: 'value1', description: 'var 1' },
+ { key: 'key2', value: 'value2' }]
+ end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
- context 'when variables is nil' do
- let(:variables) {}
+ context 'when a value data has `key` as a key' do
+ let(:variables) do
+ { 'key1' => { value: 'value1', key: 'new_key1' }, 'key2' => { value: 'value2' } }
+ end
- it { is_expected.to eq({}) }
- end
+ let(:result) do
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value2' }]
+ end
- context 'when variables is a hash' do
- let(:variables) do
- { key1: 'value1', 'key2' => 'value2' }
+ it { is_expected.to match_array(result) }
end
-
- it { is_expected.to eq(result) }
end
end
@@ -115,35 +126,35 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
let(:inheritance) { true }
let(:result) do
- [{ key: 'key1', value: 'value1', public: true },
- { key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key1', value: 'value1' },
+ { key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) }
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
context 'when inheritance is false' do
let(:inheritance) { false }
let(:result) do
- [{ key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
context 'when inheritance is array' do
let(:inheritance) { ['key2'] }
let(:result) do
- [{ key: 'key2', value: 'value22', public: true },
- { key: 'key3', value: 'value3', public: true }]
+ [{ key: 'key2', value: 'value22' },
+ { key: 'key3', value: 'value3' }]
end
- it { is_expected.to eq(result) }
+ it { is_expected.to match_array(result) }
end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
index 8416501e949..f7a0905d9da 100644
--- a/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor/result_spec.rb
@@ -72,8 +72,8 @@ module Gitlab
it 'returns calculated variables with root and job variables' do
is_expected.to match_array([
- { key: 'VAR1', value: 'value 11', public: true },
- { key: 'VAR2', value: 'value 2', public: true }
+ { key: 'VAR1', value: 'value 11' },
+ { key: 'VAR2', value: 'value 2' }
])
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 22bc6b0db59..3477fe837b4 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -448,7 +448,7 @@ module Gitlab
it 'parses the root:variables as #root_variables' do
expect(subject.root_variables)
- .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
+ .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' })
end
end
@@ -490,7 +490,7 @@ module Gitlab
it 'parses the root:variables as #root_variables' do
expect(subject.root_variables)
- .to contain_exactly({ key: 'SUPPORTED', value: 'parsed', public: true })
+ .to contain_exactly({ key: 'SUPPORTED', value: 'parsed' })
end
end
@@ -1098,8 +1098,8 @@ module Gitlab
it 'returns job variables' do
expect(job_variables).to contain_exactly(
- { key: 'VAR1', value: 'value1', public: true },
- { key: 'VAR2', value: 'value2', public: true }
+ { key: 'VAR1', value: 'value1' },
+ { key: 'VAR2', value: 'value2' }
)
expect(root_variables_inheritance).to eq(true)
end
@@ -1203,21 +1203,21 @@ module Gitlab
expect(config_processor.builds[0]).to include(
name: 'test1',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'test1 var 1', public: true },
- { key: 'VAR2', value: 'test2 var 2', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'test1 var 1' },
+ { key: 'VAR2', value: 'test2 var 2' }]
)
expect(config_processor.builds[1]).to include(
name: 'test2',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'base var 1', public: true },
- { key: 'VAR2', value: 'test2 var 2', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'base var 1' },
+ { key: 'VAR2', value: 'test2 var 2' }]
)
expect(config_processor.builds[2]).to include(
name: 'test3',
options: { script: ['test'] },
- job_variables: [{ key: 'VAR1', value: 'base var 1', public: true }]
+ job_variables: [{ key: 'VAR1', value: 'base var 1' }]
)
expect(config_processor.builds[3]).to include(
@@ -1425,7 +1425,7 @@ module Gitlab
it 'returns the parallel config' do
build_options = builds.map { |build| build[:options] }
parallel_config = {
- matrix: parallel[:matrix].map { |var| var.transform_values { |v| Array(v).flatten }},
+ matrix: parallel[:matrix].map { |var| var.transform_values { |v| Array(v).flatten } },
total: build_options.size
}
@@ -1766,6 +1766,7 @@ module Gitlab
script: ["make changelog | tee release_changelog.txt"],
release: {
tag_name: "$CI_COMMIT_TAG",
+ tag_message: "Annotated tag message",
name: "Release $CI_TAG_NAME",
description: "./release_changelog.txt",
ref: 'b3235930aa443112e639f941c69c578912189bdd',
@@ -1956,7 +1957,7 @@ module Gitlab
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
context 'no dependencies' do
- let(:dependencies) { }
+ let(:dependencies) {}
it { is_expected.to be_valid }
end
@@ -2012,8 +2013,8 @@ module Gitlab
end
describe "Job Needs" do
- let(:needs) { }
- let(:dependencies) { }
+ let(:needs) {}
+ let(:dependencies) {}
let(:config) do
{
@@ -2893,7 +2894,7 @@ module Gitlab
end
end
- describe 'Rules' do
+ describe 'Job rules' do
context 'changes' do
let(:config) do
<<~YAML
@@ -2938,6 +2939,49 @@ module Gitlab
end
end
+ describe 'Workflow rules' do
+ context 'changes' do
+ let(:config) do
+ <<~YAML
+ workflow:
+ rules:
+ - changes: [README.md]
+
+ rspec:
+ script: exit 0
+ YAML
+ end
+
+ it 'returns pipeline with correct rules' do
+ expect(processor.builds.size).to eq(1)
+ expect(processor.workflow_rules).to eq(
+ [{ changes: { paths: ["README.md"] } }]
+ )
+ end
+
+ context 'with paths' do
+ let(:config) do
+ <<~YAML
+ workflow:
+ rules:
+ - changes:
+ paths: [README.md]
+
+ rspec:
+ script: exit 0
+ YAML
+ end
+
+ it 'returns pipeline with correct rules' do
+ expect(processor.builds.size).to eq(1)
+ expect(processor.workflow_rules).to eq(
+ [{ changes: { paths: ["README.md"] } }]
+ )
+ end
+ end
+ end
+ end
+
describe '#execute' do
subject { Gitlab::Ci::YamlProcessor.new(content).execute }
diff --git a/spec/lib/gitlab/composer/cache_spec.rb b/spec/lib/gitlab/composer/cache_spec.rb
index 071771960c6..a4d632da848 100644
--- a/spec/lib/gitlab/composer/cache_spec.rb
+++ b/spec/lib/gitlab/composer/cache_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::Composer::Cache do
cache_file = Packages::Composer::CacheFile.last
freeze_time do
- expect { subject }.to change { cache_file.reload.delete_at}.from(nil).to(1.day.from_now)
+ expect { subject }.to change { cache_file.reload.delete_at }.from(nil).to(1.day.from_now)
end
end
end
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 7173ea43450..0e7d7f1efda 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::CycleAnalytics::StageSummary do
+ include CycleAnalyticsHelpers
+
let_it_be(:project) { create(:project, :repository) }
let(:options) { { from: 1.day.ago } }
diff --git a/spec/lib/gitlab/data_builder/build_spec.rb b/spec/lib/gitlab/data_builder/build_spec.rb
index 9cee0802e87..2c239d5868a 100644
--- a/spec/lib/gitlab/data_builder/build_spec.rb
+++ b/spec/lib/gitlab/data_builder/build_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::DataBuilder::Build do
let!(:tag_names) { %w(tag-1 tag-2) }
- let(:runner) { create(:ci_runner, :instance, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n)}) }
+ let(:runner) { create(:ci_runner, :instance, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n) }) }
let(:user) { create(:user, :public_email) }
let(:build) { create(:ci_build, :running, runner: runner, user: user) }
@@ -33,6 +33,7 @@ RSpec.describe Gitlab::DataBuilder::Build do
it { expect(data[:project_id]).to eq(build.project.id) }
it { expect(data[:project_name]).to eq(build.project.full_name) }
it { expect(data[:pipeline_id]).to eq(build.pipeline.id) }
+
it {
expect(data[:user]).to eq(
{
@@ -43,6 +44,7 @@ RSpec.describe Gitlab::DataBuilder::Build do
email: user.email
})
}
+
it { expect(data[:commit][:id]).to eq(build.pipeline.id) }
it { expect(data[:runner][:id]).to eq(build.runner.id) }
it { expect(data[:runner][:tags]).to match_array(tag_names) }
diff --git a/spec/lib/gitlab/data_builder/issuable_spec.rb b/spec/lib/gitlab/data_builder/issuable_spec.rb
index c1ae65c160f..f0802f335f4 100644
--- a/spec/lib/gitlab/data_builder/issuable_spec.rb
+++ b/spec/lib/gitlab/data_builder/issuable_spec.rb
@@ -113,6 +113,7 @@ RSpec.describe Gitlab::DataBuilder::Issuable do
expect(data[:object_attributes]['assignee_id']).to eq(user.id)
expect(data[:assignees].first).to eq(user.hook_attrs)
expect(data).not_to have_key(:assignee)
+ expect(data).not_to have_key(:reviewers)
end
end
@@ -126,5 +127,25 @@ RSpec.describe Gitlab::DataBuilder::Issuable do
expect(data).not_to have_key(:assignee)
end
end
+
+ context 'merge_request is assigned reviewers' do
+ let(:merge_request) { create(:merge_request, reviewers: [user]) }
+ let(:data) { described_class.new(merge_request).build(user: user) }
+
+ it 'returns correct hook data' do
+ expect(data[:object_attributes]['reviewer_ids']).to match_array([user.id])
+ expect(data[:reviewers].first).to eq(user.hook_attrs)
+ end
+ end
+
+ context 'when merge_request does not have reviewers and assignees' do
+ let(:merge_request) { create(:merge_request) }
+ let(:data) { described_class.new(merge_request).build(user: user) }
+
+ it 'returns correct hook data' do
+ expect(data).not_to have_key(:assignees)
+ expect(data).not_to have_key(:reviewers)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 469812c80fc..86a1539a836 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
context 'build with runner' do
let_it_be(:tag_names) { %w(tag-1 tag-2) }
- let_it_be(:ci_runner) { create(:ci_runner, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n)}) }
+ let_it_be(:ci_runner) { create(:ci_runner, tag_list: tag_names.map { |n| ActsAsTaggableOn::Tag.create!(name: n) }) }
let_it_be(:build) { create(:ci_build, pipeline: pipeline, runner: ci_runner) }
it 'has runner attributes', :aggregate_failures do
diff --git a/spec/lib/gitlab/data_builder/push_spec.rb b/spec/lib/gitlab/data_builder/push_spec.rb
index 7eb81a880bf..a3dd4e49e83 100644
--- a/spec/lib/gitlab/data_builder/push_spec.rb
+++ b/spec/lib/gitlab/data_builder/push_spec.rb
@@ -67,6 +67,7 @@ RSpec.describe Gitlab::DataBuilder::Push do
it { expect(data[:project_id]).to eq(15) }
it { expect(data[:commits].size).to eq(1) }
it { expect(data[:total_commits_count]).to eq(1) }
+
it 'contains project data' do
expect(data[:project]).to be_a(Hash)
expect(data[:project][:id]).to eq(15)
diff --git a/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb b/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb
new file mode 100644
index 00000000000..adb0f45706d
--- /dev/null
+++ b/spec/lib/gitlab/database/async_indexes/index_destructor_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::AsyncIndexes::IndexDestructor do
+ include ExclusiveLeaseHelpers
+
+ describe '#perform' do
+ subject { described_class.new(async_index) }
+
+ let(:async_index) { create(:postgres_async_index, :with_drop) }
+
+ let(:index_model) { Gitlab::Database::AsyncIndexes::PostgresAsyncIndex }
+
+ let(:model) { Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME] }
+ let(:connection) { model.connection }
+
+ let!(:lease) { stub_exclusive_lease(lease_key, :uuid, timeout: lease_timeout) }
+ let(:lease_key) { "gitlab/database/async_indexes/index_destructor/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
+ let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION }
+
+ before do
+ connection.add_index(async_index.table_name, 'id', name: async_index.name)
+ end
+
+ around do |example|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ example.run
+ end
+ end
+
+ context 'when the index does not exist' do
+ before do
+ connection.execute(async_index.definition)
+ end
+
+ it 'skips index destruction' do
+ expect(connection).not_to receive(:execute).with(/DROP INDEX/)
+
+ subject.perform
+ end
+ end
+
+ it 'creates the index while controlling lock timeout' do
+ allow(connection).to receive(:execute).and_call_original
+ expect(connection).to receive(:execute).with("SET lock_timeout TO '60000ms'").and_call_original
+ expect(connection).to receive(:execute).with(async_index.definition).and_call_original
+ expect(connection).to receive(:execute)
+ .with("RESET idle_in_transaction_session_timeout; RESET lock_timeout")
+ .and_call_original
+
+ subject.perform
+ end
+
+ it 'removes the index preparation record from postgres_async_indexes' do
+ expect(async_index).to receive(:destroy).and_call_original
+
+ expect { subject.perform }.to change { index_model.count }.by(-1)
+ end
+
+ it 'skips logic if not able to acquire exclusive lease' do
+ expect(lease).to receive(:try_obtain).ordered.and_return(false)
+ expect(connection).not_to receive(:execute).with(/DROP INDEX/)
+ expect(async_index).not_to receive(:destroy)
+
+ expect { subject.perform }.not_to change { index_model.count }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/async_indexes/migration_helpers_spec.rb b/spec/lib/gitlab/database/async_indexes/migration_helpers_spec.rb
index 9ba3dad72b3..52f5e37eff2 100644
--- a/spec/lib/gitlab/database/async_indexes/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/migration_helpers_spec.rb
@@ -142,4 +142,42 @@ RSpec.describe Gitlab::Database::AsyncIndexes::MigrationHelpers do
end
end
end
+
+ describe '#prepare_async_index_removal' do
+ before do
+ connection.create_table(table_name)
+ connection.add_index(table_name, 'id', name: index_name)
+ end
+
+ it 'creates the record for the async index removal' do
+ expect do
+ migration.prepare_async_index_removal(table_name, 'id', name: index_name)
+ end.to change { index_model.where(name: index_name).count }.by(1)
+
+ record = index_model.find_by(name: index_name)
+
+ expect(record.table_name).to eq(table_name)
+ expect(record.definition).to match(/DROP INDEX CONCURRENTLY "#{index_name}"/)
+ end
+
+ context 'when the index does not exist' do
+ it 'does not create the record' do
+ connection.remove_index(table_name, 'id', name: index_name)
+
+ expect do
+ migration.prepare_async_index_removal(table_name, 'id', name: index_name)
+ end.not_to change { index_model.where(name: index_name).count }
+ end
+ end
+
+ context 'when the record already exists' do
+ it 'does attempt to create the record' do
+ create(:postgres_async_index, table_name: table_name, name: index_name)
+
+ expect do
+ migration.prepare_async_index_removal(table_name, 'id', name: index_name)
+ end.not_to change { index_model.where(name: index_name).count }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb b/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
index 223730f87c0..806d57af4b3 100644
--- a/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/postgres_async_index_spec.rb
@@ -16,4 +16,21 @@ RSpec.describe Gitlab::Database::AsyncIndexes::PostgresAsyncIndex, type: :model
it { is_expected.to validate_presence_of(:definition) }
it { is_expected.to validate_length_of(:definition).is_at_most(definition_limit) }
end
+
+ describe 'scopes' do
+ let!(:async_index_creation) { create(:postgres_async_index) }
+ let!(:async_index_destruction) { create(:postgres_async_index, :with_drop) }
+
+ describe '.to_create' do
+ subject { described_class.to_create }
+
+ it { is_expected.to contain_exactly(async_index_creation) }
+ end
+
+ describe '.to_drop' do
+ subject { described_class.to_drop }
+
+ it { is_expected.to contain_exactly(async_index_destruction) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/async_indexes_spec.rb b/spec/lib/gitlab/database/async_indexes_spec.rb
index 74e30ea2c4e..8a5509f892f 100644
--- a/spec/lib/gitlab/database/async_indexes_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::Database::AsyncIndexes do
end
it 'takes 2 pending indexes and creates those' do
- Gitlab::Database::AsyncIndexes::PostgresAsyncIndex.order(:id).limit(2).each do |index|
+ Gitlab::Database::AsyncIndexes::PostgresAsyncIndex.to_create.order(:id).limit(2).each do |index|
creator = double('index creator')
expect(Gitlab::Database::AsyncIndexes::IndexCreator).to receive(:new).with(index).and_return(creator)
expect(creator).to receive(:perform)
@@ -20,4 +20,22 @@ RSpec.describe Gitlab::Database::AsyncIndexes do
subject
end
end
+
+ describe '.drop_pending_indexes!' do
+ subject { described_class.drop_pending_indexes! }
+
+ before do
+ create_list(:postgres_async_index, 4, :with_drop)
+ end
+
+ it 'takes 2 pending indexes and destroys those' do
+ Gitlab::Database::AsyncIndexes::PostgresAsyncIndex.to_drop.order(:id).limit(2).each do |index|
+ destructor = double('index destructor')
+ expect(Gitlab::Database::AsyncIndexes::IndexDestructor).to receive(:new).with(index).and_return(destructor)
+ expect(destructor).to receive(:perform)
+ end
+
+ subject
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index a7b3670da7c..32746a46308 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -304,6 +304,13 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
it { expect(subject).to be_falsey }
end
+
+ context 'when the batch_size is 1' do
+ let(:job) { create(:batched_background_migration_job, :failed, batch_size: 1) }
+ let(:exception) { ActiveRecord::StatementTimeout.new }
+
+ it { expect(subject).to be_falsey }
+ end
end
describe '#time_efficiency' do
@@ -415,10 +422,18 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
context 'when batch size is already 1' do
- let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 1) }
+ let!(:job) { create(:batched_background_migration_job, :failed, batch_size: 1, attempts: 3) }
- it 'raises an exception' do
- expect { job.split_and_retry! }.to raise_error 'Job cannot be split further'
+ it 'keeps the same batch size' do
+ job.split_and_retry!
+
+ expect(job.reload.batch_size).to eq 1
+ end
+
+ it 'resets the number of attempts' do
+ job.split_and_retry!
+
+ expect(job.attempts).to eq 0
end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
index b8ff78be333..4ef2e7f936b 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
end
before do
- allow(Gitlab::Database::BackgroundMigration::HealthStatus).to receive(:evaluate)
- .and_return(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal)
+ normal_signal = instance_double(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal, stop?: false)
+ allow(Gitlab::Database::BackgroundMigration::HealthStatus).to receive(:evaluate).and_return([normal_signal])
end
describe '#run_migration_job' do
@@ -77,14 +77,14 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
end
it 'puts migration on hold on stop signal' do
- expect(health_status).to receive(:evaluate).and_return(stop_signal)
+ expect(health_status).to receive(:evaluate).and_return([stop_signal])
expect { runner.run_migration_job(migration) }.to change { migration.on_hold? }
.from(false).to(true)
end
it 'optimizes migration on normal signal' do
- expect(health_status).to receive(:evaluate).and_return(normal_signal)
+ expect(health_status).to receive(:evaluate).and_return([normal_signal])
expect(migration).to receive(:optimize!)
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
end
it 'optimizes migration on no signal' do
- expect(health_status).to receive(:evaluate).and_return(not_available_signal)
+ expect(health_status).to receive(:evaluate).and_return([not_available_signal])
expect(migration).to receive(:optimize!)
@@ -100,7 +100,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
end
it 'optimizes migration on unknown signal' do
- expect(health_status).to receive(:evaluate).and_return(unknown_signal)
+ expect(health_status).to receive(:evaluate).and_return([unknown_signal])
expect(migration).to receive(:optimize!)
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 55f607c0cb0..06c2bc32db3 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -307,7 +307,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
describe '#batch_class' do
- let(:batch_class) { Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy}
+ let(:batch_class) { Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy }
let(:batched_migration) { build(:batched_background_migration) }
it 'returns the class of the batch strategy for the migration' do
@@ -617,6 +617,49 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
+ describe '#progress' do
+ subject { migration.progress }
+
+ context 'when the migration is finished' do
+ let(:migration) do
+ create(:batched_background_migration, :finished, total_tuple_count: 1).tap do |record|
+ create(:batched_background_migration_job, :succeeded, batched_migration: record, batch_size: 1)
+ end
+ end
+
+ it 'returns 100' do
+ expect(subject).to be 100
+ end
+ end
+
+ context 'when the migration does not have jobs' do
+ let(:migration) { create(:batched_background_migration, :active) }
+
+ it 'returns zero' do
+ expect(subject).to be 0
+ end
+ end
+
+ context 'when the `total_tuple_count` is zero' do
+ let(:migration) { create(:batched_background_migration, :active, total_tuple_count: 0) }
+ let!(:batched_job) { create(:batched_background_migration_job, :succeeded, batched_migration: migration) }
+
+ it 'returns nil' do
+ expect(subject).to be nil
+ end
+ end
+
+ context 'when migration has completed jobs' do
+ let(:migration) { create(:batched_background_migration, :active, total_tuple_count: 100) }
+
+ let!(:batched_job) { create(:batched_background_migration_job, :succeeded, batched_migration: migration, batch_size: 8) }
+
+ it 'calculates the progress' do
+ expect(subject).to be 8
+ end
+ end
+ end
+
describe '.for_configuration' do
let!(:attributes) do
{
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
index 83c0275a870..983f482d464 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb
@@ -38,10 +38,11 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
batch_column: 'id',
sub_batch_size: 1,
pause_ms: pause_ms,
+ job_arguments: active_migration.job_arguments,
connection: connection)
.and_return(job_instance)
- expect(job_instance).to receive(:perform).with('id', 'other_id')
+ expect(job_instance).to receive(:perform).with(no_args)
perform
end
@@ -49,7 +50,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
it 'updates the tracking record in the database' do
test_metrics = { 'my_metrics' => 'some value' }
- expect(job_instance).to receive(:perform).with('id', 'other_id')
+ expect(job_instance).to receive(:perform).with(no_args)
expect(job_instance).to receive(:batch_metrics).and_return(test_metrics)
freeze_time do
@@ -78,7 +79,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
it 'increments attempts and updates other fields' do
updated_metrics = { 'updated_metrics' => 'some_value' }
- expect(job_instance).to receive(:perform).with('id', 'other_id')
+ expect(job_instance).to receive(:perform).with(no_args)
expect(job_instance).to receive(:batch_metrics).and_return(updated_metrics)
freeze_time do
@@ -97,7 +98,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
context 'when the migration job does not raise an error' do
it 'marks the tracking record as succeeded' do
- expect(job_instance).to receive(:perform).with('id', 'other_id')
+ expect(job_instance).to receive(:perform).with(no_args)
freeze_time do
perform
@@ -110,7 +111,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
end
it 'tracks metrics of the execution' do
- expect(job_instance).to receive(:perform).with('id', 'other_id')
+ expect(job_instance).to receive(:perform).with(no_args)
expect(metrics_tracker).to receive(:track).with(job_record)
perform
@@ -120,7 +121,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
context 'when the migration job raises an error' do
shared_examples 'an error is raised' do |error_class|
it 'marks the tracking record as failed' do
- expect(job_instance).to receive(:perform).with('id', 'other_id').and_raise(error_class)
+ expect(job_instance).to receive(:perform).with(no_args).and_raise(error_class)
freeze_time do
expect { perform }.to raise_error(error_class)
@@ -133,7 +134,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
end
it 'tracks metrics of the execution' do
- expect(job_instance).to receive(:perform).with('id', 'other_id').and_raise(error_class)
+ expect(job_instance).to receive(:perform).with(no_args).and_raise(error_class)
expect(metrics_tracker).to receive(:track).with(job_record)
expect { perform }.to raise_error(error_class)
@@ -147,6 +148,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, '
context 'when the batched background migration does not inherit from BatchedMigrationJob' do
let(:job_class) { Class.new }
+ let(:job_instance) { job_class.new }
it 'runs the job with the correct arguments' do
expect(job_class).to receive(:new).with(no_args).and_return(job_instance)
diff --git a/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb b/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb
index 21204814f17..db4383a79d4 100644
--- a/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/health_status/indicators/autovacuum_active_on_table_spec.rb
@@ -20,9 +20,9 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::
swapout_view_for_table(:postgres_autovacuum_activity)
end
- let(:context) { Gitlab::Database::BackgroundMigration::HealthStatus::Context.new(tables) }
let(:tables) { [table] }
let(:table) { 'users' }
+ let(:context) { Gitlab::Database::BackgroundMigration::HealthStatus::Context.new(connection, tables) }
context 'without autovacuum activity' do
it 'returns Normal signal' do
diff --git a/spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb b/spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb
new file mode 100644
index 00000000000..650f11e3cd5
--- /dev/null
+++ b/spec/lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog do
+ let(:connection) { Gitlab::Database.database_base_models[:main].connection }
+
+ around do |example|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ example.run
+ end
+ end
+
+ describe '#evaluate' do
+ let(:tables) { [table] }
+ let(:table) { 'users' }
+ let(:context) { Gitlab::Database::BackgroundMigration::HealthStatus::Context.new(connection, tables) }
+
+ subject(:evaluate) { described_class.new(context).evaluate }
+
+ it 'remembers the indicator class' do
+ expect(evaluate.indicator_class).to eq(described_class)
+ end
+
+ it 'returns NoSignal signal in case the feature flag is disabled' do
+ stub_feature_flags(batched_migrations_health_status_wal: false)
+
+ expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable)
+ expect(evaluate.reason).to include('indicator disabled')
+ end
+
+ it 'returns NoSignal signal when WAL archive queue can not be calculated' do
+ expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => nil }])
+
+ expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::NotAvailable)
+ expect(evaluate.reason).to include('WAL archive queue can not be calculated')
+ end
+
+ it 'uses primary database' do
+ expect(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary).and_yield
+
+ evaluate
+ end
+
+ context 'when WAL archive queue size is below the limit' do
+ it 'returns Normal signal' do
+ expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => 1 }])
+ expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Normal)
+ expect(evaluate.reason).to include('WAL archive queue is within limit')
+ end
+ end
+
+ context 'when WAL archive queue size is above the limit' do
+ it 'returns Stop signal' do
+ expect(connection).to receive(:execute).and_return([{ 'pending_wal_count' => 420 }])
+ expect(evaluate).to be_a(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Stop)
+ expect(evaluate.reason).to include('WAL archive queue is too big')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/background_migration/health_status_spec.rb b/spec/lib/gitlab/database/background_migration/health_status_spec.rb
index 6d0430dcbbb..8bc04d80fa1 100644
--- a/spec/lib/gitlab/database/background_migration/health_status_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/health_status_spec.rb
@@ -12,30 +12,47 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus do
end
describe '.evaluate' do
- subject(:evaluate) { described_class.evaluate(migration, indicator_class) }
+ subject(:evaluate) { described_class.evaluate(migration, [autovacuum_indicator_class]) }
let(:migration) { build(:batched_background_migration, :active) }
- let(:health_status) { 'Gitlab::Database::BackgroundMigration::HealthStatus' }
- let(:indicator_class) { class_double("#{health_status}::Indicators::AutovacuumActiveOnTable") }
- let(:indicator) { instance_double("#{health_status}::Indicators::AutovacuumActiveOnTable") }
+ let(:health_status) { Gitlab::Database::BackgroundMigration::HealthStatus }
+ let(:autovacuum_indicator_class) { health_status::Indicators::AutovacuumActiveOnTable }
+ let(:wal_indicator_class) { health_status::Indicators::WriteAheadLog }
+ let(:autovacuum_indicator) { instance_double(autovacuum_indicator_class) }
+ let(:wal_indicator) { instance_double(wal_indicator_class) }
before do
- allow(indicator_class).to receive(:new).with(migration.health_context).and_return(indicator)
+ allow(autovacuum_indicator_class).to receive(:new).with(migration.health_context).and_return(autovacuum_indicator)
end
- it 'returns a signal' do
+ context 'with default indicators' do
+ subject(:evaluate) { described_class.evaluate(migration) }
+
+ it 'returns a collection of signals' do
+ normal_signal = instance_double("#{health_status}::Signals::Normal", log_info?: false)
+ not_available_signal = instance_double("#{health_status}::Signals::NotAvailable", log_info?: false)
+
+ expect(autovacuum_indicator).to receive(:evaluate).and_return(normal_signal)
+ expect(wal_indicator_class).to receive(:new).with(migration.health_context).and_return(wal_indicator)
+ expect(wal_indicator).to receive(:evaluate).and_return(not_available_signal)
+
+ expect(evaluate).to contain_exactly(normal_signal, not_available_signal)
+ end
+ end
+
+ it 'returns a collection of signals' do
signal = instance_double("#{health_status}::Signals::Normal", log_info?: false)
- expect(indicator).to receive(:evaluate).and_return(signal)
+ expect(autovacuum_indicator).to receive(:evaluate).and_return(signal)
- expect(evaluate).to eq(signal)
+ expect(evaluate).to contain_exactly(signal)
end
it 'logs interesting signals' do
signal = instance_double("#{health_status}::Signals::Stop", log_info?: true)
- expect(indicator).to receive(:evaluate).and_return(signal)
+ expect(autovacuum_indicator).to receive(:evaluate).and_return(signal)
expect(described_class).to receive(:log_signal).with(signal, migration)
evaluate
@@ -44,7 +61,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus do
it 'does not log signals of no interest' do
signal = instance_double("#{health_status}::Signals::Normal", log_info?: false)
- expect(indicator).to receive(:evaluate).and_return(signal)
+ expect(autovacuum_indicator).to receive(:evaluate).and_return(signal)
expect(described_class).not_to receive(:log_signal)
evaluate
@@ -54,7 +71,7 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus do
let(:error) { RuntimeError.new('everything broken') }
before do
- expect(indicator).to receive(:evaluate).and_raise(error)
+ expect(autovacuum_indicator).to receive(:evaluate).and_raise(error)
end
it 'does not fail' do
@@ -62,8 +79,10 @@ RSpec.describe Gitlab::Database::BackgroundMigration::HealthStatus do
end
it 'returns Unknown signal' do
- expect(evaluate).to be_an_instance_of(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown)
- expect(evaluate.reason).to eq("unexpected error: everything broken (RuntimeError)")
+ signal = evaluate.first
+
+ expect(signal).to be_an_instance_of(Gitlab::Database::BackgroundMigration::HealthStatus::Signals::Unknown)
+ expect(signal.reason).to eq("unexpected error: everything broken (RuntimeError)")
end
it 'reports the exception to error tracking' do
diff --git a/spec/lib/gitlab/database/bulk_update_spec.rb b/spec/lib/gitlab/database/bulk_update_spec.rb
index 08b4d50f83b..fa519cffd6b 100644
--- a/spec/lib/gitlab/database/bulk_update_spec.rb
+++ b/spec/lib/gitlab/database/bulk_update_spec.rb
@@ -91,7 +91,8 @@ RSpec.describe Gitlab::Database::BulkUpdate do
.to eq(['MR a', 'Issue a', 'Issue b'])
end
- context 'validates prepared_statements support', :reestablished_active_record_base do
+ context 'validates prepared_statements support', :reestablished_active_record_base,
+ :suppress_gitlab_schemas_validate_connection do
using RSpec::Parameterized::TableSyntax
where(:prepared_statements) do
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 34eb64997c1..9c09253b24c 100644
--- a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -358,7 +358,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
it 'returns true for deeply wrapped/nested errors' do
- top = twice_wrapped_exception(ActionView::Template::Error, ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished)
+ top = twice_wrapped_exception(
+ ActionView::Template::Error,
+ ActiveRecord::StatementInvalid,
+ ActiveRecord::ConnectionNotEstablished
+ )
expect(lb.connection_error?(top)).to eq(true)
end
@@ -404,7 +408,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
describe '#select_up_to_date_host' do
- let(:location) { 'AB/12345'}
+ let(:location) { 'AB/12345' }
let(:hosts) { lb.host_list.hosts }
let(:set_host) { request_cache[described_class::CACHE_KEY] }
@@ -455,7 +459,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
it 'does not modify connection class pool' do
- expect { with_replica_pool(5) { } }.not_to change { ActiveRecord::Base.connection_pool }
+ expect { with_replica_pool(5) {} }.not_to change { ActiveRecord::Base.connection_pool }
end
def with_replica_pool(*args)
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 b768d4ecea3..a1c141af537 100644
--- a/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/rack_middleware_spec.rb
@@ -30,6 +30,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::RackMiddleware, :redis do
expect(app).to receive(:call).with(env).and_return(10)
+ allow(ActiveSupport::Notifications).to receive(:instrument).and_call_original
+
expect(ActiveSupport::Notifications)
.to receive(:instrument)
.with('web_transaction_completed.load_balancing')
diff --git a/spec/lib/gitlab/database/load_balancing/session_spec.rb b/spec/lib/gitlab/database/load_balancing/session_spec.rb
index 74512f76fd4..05b44579c62 100644
--- a/spec/lib/gitlab/database/load_balancing/session_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/session_spec.rb
@@ -132,7 +132,11 @@ RSpec.describe Gitlab::Database::LoadBalancing::Session do
it 'does not prevent using primary if an exception is raised' do
instance = described_class.new
- instance.ignore_writes { raise ArgumentError } rescue ArgumentError
+ begin
+ instance.ignore_writes { raise ArgumentError }
+ rescue ArgumentError
+ nil
+ end
instance.write!
expect(instance).to be_using_primary
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 31be3963565..8053bd57bba 100644
--- a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_gitlab_redis_queues do
let(:middleware) { described_class.new }
let(:worker) { worker_class.new }
- let(:location) {'0/D525E3A8' }
+ let(:location) { '0/D525E3A8' }
let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations } }
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
index f3139bb1b4f..2ffb2c32c32 100644
--- a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -77,6 +77,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
let(:last_write_location) { 'foo' }
before do
+ allow(ActiveSupport::Notifications).to receive(:instrument).and_call_original
+
allow(sticking)
.to receive(:last_write_location_for)
.with(:user, 42)
diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb
index f320fe0276f..76dfaa74ae6 100644
--- a/spec/lib/gitlab/database/load_balancing_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Database::LoadBalancing do
+RSpec.describe Gitlab::Database::LoadBalancing, :suppress_gitlab_schemas_validate_connection do
describe '.base_models' do
it 'returns the models to apply load balancing to' do
models = described_class.base_models
diff --git a/spec/lib/gitlab/database/lock_writes_manager_spec.rb b/spec/lib/gitlab/database/lock_writes_manager_spec.rb
new file mode 100644
index 00000000000..eb527d492cf
--- /dev/null
+++ b/spec/lib/gitlab/database/lock_writes_manager_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LockWritesManager do
+ let(:connection) { ApplicationRecord.connection }
+ let(:test_table) { '_test_table' }
+ let(:logger) { instance_double(Logger) }
+
+ subject(:lock_writes_manager) do
+ described_class.new(
+ table_name: test_table,
+ connection: connection,
+ database_name: 'main',
+ logger: logger
+ )
+ end
+
+ before do
+ allow(logger).to receive(:info)
+
+ connection.execute(<<~SQL)
+ CREATE TABLE #{test_table} (id integer NOT NULL, value integer NOT NULL DEFAULT 0);
+
+ INSERT INTO #{test_table} (id, value)
+ VALUES (1, 1), (2, 2), (3, 3)
+ SQL
+ end
+
+ describe '#lock_writes' do
+ it 'prevents any writes on the table' do
+ subject.lock_writes
+
+ expect do
+ connection.execute("delete from #{test_table}")
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "#{test_table}" is write protected/)
+ end
+
+ it 'prevents truncating the table' do
+ subject.lock_writes
+
+ expect do
+ connection.execute("truncate #{test_table}")
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "#{test_table}" is write protected/)
+ end
+
+ it 'adds 3 triggers to the ci schema tables on the main database' do
+ expect do
+ subject.lock_writes
+ end.to change {
+ number_of_triggers_on(connection, test_table)
+ }.by(3) # Triggers to block INSERT / UPDATE / DELETE
+ # Triggers on TRUNCATE are not added to the information_schema.triggers
+ # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
+ end
+
+ it 'logs the write locking' do
+ expect(logger).to receive(:info).with("Database: 'main', Table: '_test_table': Lock Writes")
+
+ subject.lock_writes
+ end
+
+ it 'retries again if it receives a statement_timeout a few number of times' do
+ error_message = "PG::QueryCanceled: ERROR: canceling statement due to statement timeout"
+ call_count = 0
+ allow(connection).to receive(:execute) do |statement|
+ if statement.include?("CREATE TRIGGER")
+ call_count += 1
+ raise(ActiveRecord::QueryCanceled, error_message) if call_count.even?
+ end
+ end
+ subject.lock_writes
+ end
+
+ it 'raises the exception if it happened many times' do
+ error_message = "PG::QueryCanceled: ERROR: canceling statement due to statement timeout"
+ allow(connection).to receive(:execute) do |statement|
+ if statement.include?("CREATE TRIGGER")
+ raise(ActiveRecord::QueryCanceled, error_message)
+ end
+ end
+
+ expect do
+ subject.lock_writes
+ end.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+
+ describe '#unlock_writes' do
+ before do
+ subject.lock_writes
+ end
+
+ it 'allows writing on the table again' do
+ subject.unlock_writes
+
+ expect do
+ connection.execute("delete from #{test_table}")
+ end.not_to raise_error
+ end
+
+ it 'removes the write protection triggers from the gitlab_main tables on the ci database' do
+ expect do
+ subject.unlock_writes
+ end.to change {
+ number_of_triggers_on(connection, test_table)
+ }.by(-3) # Triggers to block INSERT / UPDATE / DELETE
+ # Triggers on TRUNCATE are not added to the information_schema.triggers
+ # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
+ end
+
+ it 'logs the write unlocking' do
+ expect(logger).to receive(:info).with("Database: 'main', Table: '_test_table': Allow Writes")
+
+ subject.unlock_writes
+ end
+ end
+
+ def number_of_triggers_on(connection, table_name)
+ connection
+ .select_value("SELECT count(*) FROM information_schema.triggers WHERE event_object_table=$1", nil, [table_name])
+ end
+end
diff --git a/spec/lib/gitlab/database/loose_foreign_keys_spec.rb b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
index 87a3e0f81e4..ff99f681b0c 100644
--- a/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
+++ b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
@@ -84,4 +84,32 @@ RSpec.describe Gitlab::Database::LooseForeignKeys do
end
end
end
+
+ describe '.definitions' do
+ subject(:definitions) { described_class.definitions }
+
+ it 'contains at least all parent tables that have triggers' do
+ all_definition_parent_tables = definitions.map { |d| d.to_table }.to_set
+
+ triggers_query = <<~SQL
+ SELECT event_object_table, trigger_name
+ FROM information_schema.triggers
+ WHERE trigger_name LIKE '%_loose_fk_trigger'
+ GROUP BY event_object_table, trigger_name
+ SQL
+
+ all_triggers = ApplicationRecord.connection.execute(triggers_query)
+
+ all_triggers.each do |trigger|
+ table = trigger['event_object_table']
+ trigger_name = trigger['trigger_name']
+ error_message = <<~END
+ Missing a loose foreign key definition for parent table: #{table} with trigger: #{trigger_name}.
+ Loose foreign key definitions must be added before triggers are added and triggers must be removed before removing the loose foreign key definition.
+ Read more at https://docs.gitlab.com/ee/development/database/loose_foreign_keys.html ."
+ END
+ expect(all_definition_parent_tables).to include(table), error_message
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb b/spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb
index 1009ec354c3..e43cfe0814e 100644
--- a/spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb
@@ -5,6 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::MigrationHelpers::RestrictGitlabSchema, query_analyzers: false, stub_feature_flags: false do
let(:schema_class) { Class.new(Gitlab::Database::Migration[1.0]).include(described_class) }
+ # We keep only the GitlabSchemasValidateConnection analyzer running
+ around do |example|
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed(false) do
+ example.run
+ end
+ end
+
describe '#restrict_gitlab_migration' do
it 'invalid schema raises exception' do
expect { schema_class.restrict_gitlab_migration gitlab_schema: :gitlab_non_exisiting }
diff --git a/spec/lib/gitlab/database/migration_helpers/v2_spec.rb b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
index 5c054795697..2055dc33d48 100644
--- a/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers/v2_spec.rb
@@ -266,7 +266,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
let(:env) { { 'DISABLE_LOCK_RETRIES' => 'true' } }
it 'sets the migration class name in the logs' do
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
buffer.rewind
expect(buffer.read).to include("\"class\":\"#{model.class}\"")
@@ -280,7 +280,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
expect(Gitlab::Database::WithLockRetries).to receive(:new).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: raise_on_exhaustion)
- model.with_lock_retries(env: env, logger: in_memory_logger, raise_on_exhaustion: raise_on_exhaustion) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger, raise_on_exhaustion: raise_on_exhaustion) {}
end
end
@@ -289,7 +289,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
expect(Gitlab::Database::WithLockRetries).to receive(:new).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: false)
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
end
it 'defaults to disallowing subtransactions' do
@@ -297,7 +297,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
expect(Gitlab::Database::WithLockRetries).to receive(:new).with(hash_including(allow_savepoints: false)).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: false)
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
end
context 'when in transaction' do
@@ -323,7 +323,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers::V2 do
end
it 'raises an error' do
- expect { model.with_lock_retries(env: env, logger: in_memory_logger) { } }.to raise_error /can not be run inside an already open transaction/
+ expect { model.with_lock_retries(env: env, logger: in_memory_logger) {} }.to raise_error /can not be run inside an already open transaction/
end
end
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 3ccc3a17862..dd5ad40d8ef 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
describe 'overridden dynamic model helpers' do
- let(:test_table) { '__test_batching_table' }
+ let(:test_table) { '_test_batching_table' }
before do
model.connection.execute(<<~SQL)
@@ -1022,6 +1022,40 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(Project.sum(:star_count)).to eq(2 * Project.count)
end
end
+
+ context 'when the table is write-locked' do
+ let(:test_table) { '_test_table' }
+ let(:lock_writes_manager) do
+ Gitlab::Database::LockWritesManager.new(
+ table_name: test_table,
+ connection: model.connection,
+ database_name: 'main'
+ )
+ end
+
+ before do
+ model.connection.execute(<<~SQL)
+ CREATE TABLE #{test_table} (id integer NOT NULL, value integer NOT NULL DEFAULT 0);
+
+ INSERT INTO #{test_table} (id, value)
+ VALUES (1, 1), (2, 2), (3, 3)
+ SQL
+
+ lock_writes_manager.lock_writes
+ end
+
+ it 'disables the write-lock trigger function' do
+ expect do
+ model.update_column_in_batches(test_table, :value, Arel.sql('1+1'), disable_lock_writes: true)
+ end.not_to raise_error
+ end
+
+ it 'raises an error if it does not disable the trigger function' do
+ expect do
+ model.update_column_in_batches(test_table, :value, Arel.sql('1+1'), disable_lock_writes: false)
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "#{test_table}" is write protected/)
+ end
+ end
end
context 'when running inside the transaction' do
@@ -1080,6 +1114,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
it 'renames a column concurrently' do
+ expect(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection).to receive(:with_suppressed).and_yield
+
expect(model).to receive(:check_trigger_permissions!).with(:users)
expect(model).to receive(:install_rename_triggers)
@@ -1112,6 +1148,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
let(:connection) { ActiveRecord::Migration.connection }
before do
+ expect(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection).to receive(:with_suppressed).and_yield
expect(Gitlab::Database::UnidirectionalCopyTrigger).to receive(:on_table)
.with(:users, connection: connection).and_return(copy_trigger)
end
@@ -1119,6 +1156,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
it 'copies the value to the new column using the type_cast_function', :aggregate_failures do
expect(model).to receive(:copy_indexes).with(:users, :id, :new)
expect(model).to receive(:add_not_null_constraint).with(:users, :new)
+ expect(model).to receive(:execute).with("SELECT set_config('lock_writes.users', 'false', true)")
expect(model).to receive(:execute).with("UPDATE \"users\" SET \"new\" = cast_to_jsonb_with_default(\"users\".\"id\") WHERE \"users\".\"id\" >= #{user.id}")
expect(copy_trigger).to receive(:create).with(:id, :new, trigger_name: nil)
@@ -1165,6 +1203,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
it 'copies the default to the new column' do
+ expect(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection).to receive(:with_suppressed).and_yield
+
expect(model).to receive(:change_column_default)
.with(:users, :new, old_column.default)
@@ -1176,6 +1216,34 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
end
+ context 'when the table in the other database is write-locked' do
+ let(:test_table) { '_test_table' }
+ let(:lock_writes_manager) do
+ Gitlab::Database::LockWritesManager.new(
+ table_name: test_table,
+ connection: model.connection,
+ database_name: 'main'
+ )
+ end
+
+ before do
+ model.connection.execute(<<~SQL)
+ CREATE TABLE #{test_table} (id integer NOT NULL, value integer NOT NULL DEFAULT 0);
+
+ INSERT INTO #{test_table} (id, value)
+ VALUES (1, 1), (2, 2), (3, 3)
+ SQL
+
+ lock_writes_manager.lock_writes
+ end
+
+ it 'does not raise an error when renaming the column' do
+ expect do
+ model.rename_column_concurrently(test_table, :value, :new_value)
+ end.not_to raise_error
+ end
+ end
+
context 'when the column to be renamed does not exist' do
before do
allow(model).to receive(:columns).and_return([])
@@ -1246,6 +1314,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
it 'reverses the operations of cleanup_concurrent_column_rename' do
+ expect(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection).to receive(:with_suppressed).and_yield
+
expect(model).to receive(:check_trigger_permissions!).with(:users)
expect(model).to receive(:install_rename_triggers)
@@ -1302,6 +1372,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
end
it 'copies the default to the old column' do
+ expect(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection).to receive(:with_suppressed).and_yield
+
expect(model).to receive(:change_column_default)
.with(:users, :old, new_column.default)
@@ -2438,7 +2510,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
let(:env) { { 'DISABLE_LOCK_RETRIES' => 'true' } }
it 'sets the migration class name in the logs' do
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
buffer.rewind
expect(buffer.read).to include("\"class\":\"#{model.class}\"")
@@ -2452,7 +2524,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(Gitlab::Database::WithLockRetries).to receive(:new).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: raise_on_exhaustion)
- model.with_lock_retries(env: env, logger: in_memory_logger, raise_on_exhaustion: raise_on_exhaustion) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger, raise_on_exhaustion: raise_on_exhaustion) {}
end
end
@@ -2461,7 +2533,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(Gitlab::Database::WithLockRetries).to receive(:new).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: false)
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
end
it 'defaults to allowing subtransactions' do
@@ -2470,7 +2542,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
expect(Gitlab::Database::WithLockRetries).to receive(:new).with(hash_including(allow_savepoints: true)).and_return(with_lock_retries)
expect(with_lock_retries).to receive(:run).with(raise_on_exhaustion: false)
- model.with_lock_retries(env: env, logger: in_memory_logger) { }
+ model.with_lock_retries(env: env, logger: in_memory_logger) {}
end
end
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index c423340a572..f21f1ac5e52 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -37,12 +37,6 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
freeze_time { example.run }
end
- before do
- User.class_eval do
- include EachBatch
- end
- end
-
it 'returns the final expected delay' do
Sidekiq::Testing.fake! do
final_delay = model.queue_background_migration_jobs_by_range_at_intervals(User, 'FooJob', 10.minutes, batch_size: 2)
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
index 5bfb2516ba1..a2f6e6b43ed 100644
--- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
@@ -15,12 +15,25 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
describe '#queue_batched_background_migration' do
let(:pgclass_info) { instance_double('Gitlab::Database::PgClass', cardinality_estimate: 42) }
+ let(:job_class) do
+ Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do
+ def self.name
+ 'MyJobClass'
+ end
+ end
+ end
before do
allow(Gitlab::Database::PgClass).to receive(:for_table).and_call_original
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!)
allow(migration).to receive(:transaction_open?).and_return(false)
+
+ stub_const("Gitlab::Database::BackgroundMigration::BatchedMigration::JOB_CLASS_MODULE", '')
+ allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |batched_migration|
+ allow(batched_migration).to receive(:job_class)
+ .and_return(job_class)
+ end
end
context 'when such migration already exists' do
@@ -42,7 +55,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
expect do
migration.queue_batched_background_migration(
- 'MyJobClass',
+ job_class.name,
:projects,
:id,
[:id], [:id_convert_to_bigint],
@@ -62,7 +75,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
expect do
migration.queue_batched_background_migration(
- 'MyJobClass',
+ job_class.name,
:projects,
:id,
job_interval: 5.minutes,
@@ -97,7 +110,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
it 'sets the job interval to the minimum value' do
expect do
- migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: minimum_delay - 1.minute)
+ migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: minimum_delay - 1.minute)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
@@ -107,26 +120,76 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
end
context 'when additional arguments are passed to the method' do
- it 'saves the arguments on the database record' do
- expect do
- migration.queue_batched_background_migration(
- 'MyJobClass',
- :projects,
- :id,
- 'my',
- 'arguments',
- job_interval: 5.minutes,
- batch_max_value: 1000)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+ context 'when the job class provides job_arguments_count' do
+ context 'when defined job arguments for the job class does not match provided arguments' do
+ it 'raises an error' do
+ expect do
+ migration.queue_batched_background_migration(
+ job_class.name,
+ :projects,
+ :id,
+ 'my',
+ 'arguments',
+ job_interval: 2.minutes)
+ end.to raise_error(RuntimeError, /Wrong number of job arguments for MyJobClass \(given 2, expected 0\)/)
+ end
+ end
- expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
- job_class_name: 'MyJobClass',
- table_name: 'projects',
- column_name: 'id',
- interval: 300,
- min_value: 1,
- max_value: 1000,
- job_arguments: %w[my arguments])
+ context 'when defined job arguments for the job class match provided arguments' do
+ let(:job_class) do
+ Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do
+ def self.name
+ 'MyJobClass'
+ end
+
+ job_arguments :foo, :bar
+ end
+ end
+
+ it 'saves the arguments on the database record' do
+ expect do
+ migration.queue_batched_background_migration(
+ job_class.name,
+ :projects,
+ :id,
+ 'my',
+ 'arguments',
+ job_interval: 5.minutes,
+ batch_max_value: 1000)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
+ job_class_name: 'MyJobClass',
+ table_name: 'projects',
+ column_name: 'id',
+ interval: 300,
+ min_value: 1,
+ max_value: 1000,
+ job_arguments: %w[my arguments])
+ end
+ end
+ end
+
+ context 'when the job class does not provide job_arguments_count' do
+ let(:job_class) do
+ Class.new do
+ def self.name
+ 'MyJobClass'
+ end
+ end
+ end
+
+ it 'does not raise an error' do
+ expect do
+ migration.queue_batched_background_migration(
+ job_class.name,
+ :projects,
+ :id,
+ 'my',
+ 'arguments',
+ job_interval: 2.minutes)
+ end.not_to raise_error
+ end
end
end
@@ -138,7 +201,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
it 'creates the record with the current max value' do
expect do
- migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
@@ -148,7 +211,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
it 'creates the record with an active status' do
expect do
- migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_active
@@ -158,7 +221,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
context 'when the database is empty' do
it 'sets the max value to the min value' do
expect do
- migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
@@ -168,7 +231,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
it 'creates the record with a finished status' do
expect do
- migration.queue_batched_background_migration('MyJobClass', :projects, :id, job_interval: 5.minutes)
+ migration.queue_batched_background_migration(job_class.name, :projects, :id, job_interval: 5.minutes)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished
@@ -181,7 +244,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
expect(migration).to receive(:gitlab_schema_from_context).and_return(:gitlab_ci)
expect do
- migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes)
end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
index c31244060ec..3540a120b8f 100644
--- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -122,7 +122,11 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
it 'records observations for all migrations' do
subject.observe(version: migration_version, name: migration_name, connection: connection) {}
- subject.observe(version: migration_version_2, name: migration_name_2, connection: connection) { raise 'something went wrong' } rescue nil
+ begin
+ subject.observe(version: migration_version_2, name: migration_name_2, connection: connection) { raise 'something went wrong' }
+ rescue StandardError
+ nil
+ end
expect { load_observation(result_dir, migration_name) }.not_to raise_error
expect { load_observation(result_dir, migration_name_2) }.not_to raise_error
diff --git a/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb b/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
index 50ad77caaf1..6092d985ce8 100644
--- a/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
+++ b/spec/lib/gitlab/database/migrations/lock_retry_mixin_spec.rb
@@ -83,10 +83,10 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
context 'with transactions disabled' do
let(:migration) { double('migration', enable_lock_retries?: false) }
- let(:receiver) { double('receiver', use_transaction?: false)}
+ let(:receiver) { double('receiver', use_transaction?: false) }
it 'calls super method' do
- p = proc { }
+ p = proc {}
expect(receiver).to receive(:ddl_transaction).with(migration, &p)
@@ -95,11 +95,11 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
end
context 'with transactions enabled, but lock retries disabled' do
- let(:receiver) { double('receiver', use_transaction?: true)}
+ let(:receiver) { double('receiver', use_transaction?: true) }
let(:migration) { double('migration', enable_lock_retries?: false) }
it 'calls super method' do
- p = proc { }
+ p = proc {}
expect(receiver).to receive(:ddl_transaction).with(migration, &p)
@@ -108,12 +108,12 @@ RSpec.describe Gitlab::Database::Migrations::LockRetryMixin do
end
context 'with transactions enabled and lock retries enabled' do
- let(:receiver) { double('receiver', use_transaction?: true)}
+ let(:receiver) { double('receiver', use_transaction?: true) }
let(:migration) { double('migration', migration_connection: connection, enable_lock_retries?: true) }
let(:connection) { ActiveRecord::Base.connection }
it 'calls super method' do
- p = proc { }
+ p = proc {}
expect(receiver).not_to receive(:ddl_transaction)
expect_next_instance_of(Gitlab::Database::WithLockRetries) do |retries|
diff --git a/spec/lib/gitlab/database/migrations/runner_spec.rb b/spec/lib/gitlab/database/migrations/runner_spec.rb
index e7f68e3e4a8..a37247ba0c6 100644
--- a/spec/lib/gitlab/database/migrations/runner_spec.rb
+++ b/spec/lib/gitlab/database/migrations/runner_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
allow(described_class).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"}
+ 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
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 f1f72d71e1a..9451a6bd34a 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
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez
let(:connection) { ApplicationRecord.connection }
- let(:table_name) { "_test_column_copying"}
+ let(:table_name) { "_test_column_copying" }
before do
connection.execute(<<~SQL)
@@ -50,18 +50,16 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez
context 'with jobs to run' do
let(:migration_name) { 'TestBackgroundMigration' }
- before do
- migration.queue_batched_background_migration(
- migration_name, table_name, :id, job_interval: 5.minutes, batch_size: 100
- )
- end
-
it 'samples jobs' do
calls = []
define_background_migration(migration_name) do |*args|
calls << args
end
+ migration.queue_batched_background_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.count).to eq(10) # 1000 rows / batch size 100 = 10
@@ -70,6 +68,9 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez
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
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 d8b06ee1a5d..04b9fba5b2f 100644
--- a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
@@ -48,61 +48,43 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
end
describe '#validate_and_fix' do
- context 'feature flag is disabled' do
- before do
- stub_feature_flags(fix_sliding_list_partitioning: false)
- end
+ it 'does not call change_column_default if the partitioning in a valid state' do
+ expect(strategy.model.connection).not_to receive(:change_column_default)
- it 'does not try to fix the default partition value' do
- connection.change_column_default(model.table_name, strategy.partitioning_key, 3)
- expect(strategy.model.connection).not_to receive(:change_column_default)
- strategy.validate_and_fix
- end
+ strategy.validate_and_fix
end
- context 'feature flag is enabled' do
- before do
- stub_feature_flags(fix_sliding_list_partitioning: true)
- end
-
- it 'does not call change_column_default if the partitioning in a valid state' do
- expect(strategy.model.connection).not_to receive(:change_column_default)
-
- strategy.validate_and_fix
- end
-
- it 'calls change_column_default on partition_key with the most default partition number' do
- connection.change_column_default(model.table_name, strategy.partitioning_key, 1)
+ it 'calls change_column_default on partition_key with the most default partition number' do
+ connection.change_column_default(model.table_name, strategy.partitioning_key, 1)
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Fixed default value of sliding_list_strategy partitioning_key',
- connection_name: 'main',
- old_value: 1,
- new_value: 2,
- table_name: table_name,
- column: strategy.partitioning_key
- )
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Fixed default value of sliding_list_strategy partitioning_key',
+ connection_name: 'main',
+ old_value: 1,
+ new_value: 2,
+ table_name: table_name,
+ column: strategy.partitioning_key
+ )
- expect(strategy.model.connection).to receive(:change_column_default).with(
- model.table_name, strategy.partitioning_key, 2
- ).and_call_original
+ expect(strategy.model.connection).to receive(:change_column_default).with(
+ model.table_name, strategy.partitioning_key, 2
+ ).and_call_original
- strategy.validate_and_fix
- end
+ strategy.validate_and_fix
+ end
- it 'does not change the default column if it has been changed in the meanwhile by another process' do
- expect(strategy).to receive(:current_default_value).and_return(1, 2)
+ it 'does not change the default column if it has been changed in the meanwhile by another process' do
+ expect(strategy).to receive(:current_default_value).and_return(1, 2)
- expect(strategy.model.connection).not_to receive(:change_column_default)
+ expect(strategy.model.connection).not_to receive(:change_column_default)
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Table partitions or partition key default value have been changed by another process',
- table_name: table_name,
- default_value: 2
- )
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Table partitions or partition key default value have been changed by another process',
+ table_name: table_name,
+ default_value: 2
+ )
- strategy.validate_and_fix
- end
+ strategy.validate_and_fix
end
end
diff --git a/spec/lib/gitlab/database/partitioning_spec.rb b/spec/lib/gitlab/database/partitioning_spec.rb
index 7c69f639aab..36c8b0811fe 100644
--- a/spec/lib/gitlab/database/partitioning_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe Gitlab::Database::Partitioning do
end
it 'manages partitions for each given model' do
- expect { described_class.sync_partitions(models)}
+ expect { described_class.sync_partitions(models) }
.to change { find_partitions(table_names.first).size }.from(0)
.and change { find_partitions(table_names.last).size }.from(0)
end
diff --git a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
index 5e8afc0102e..ddf5793049d 100644
--- a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection_spec.rb
@@ -5,6 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection, query_analyzers: false do
let(:analyzer) { described_class }
+ # We keep only the GitlabSchemasValidateConnection analyzer running
+ around do |example|
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed(false) do
+ example.run
+ end
+ end
+
context 'properly observes all queries', :request_store do
using RSpec::Parameterized::TableSyntax
@@ -61,6 +68,24 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection
end
end
+ context "when analyzer is enabled for tests", :query_analyzers do
+ before do
+ skip_if_multiple_databases_not_setup
+ end
+
+ it "throws an error when trying to access a table that belongs to the gitlab_main schema from the ci database" do
+ expect do
+ Ci::ApplicationRecord.connection.execute("select * from users limit 1")
+ end.to raise_error(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection::CrossSchemaAccessError)
+ end
+
+ it "throws an error when trying to access a table that belongs to the gitlab_ci schema from the main database" do
+ expect do
+ ApplicationRecord.connection.execute("select * from ci_builds limit 1")
+ end.to raise_error(Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection::CrossSchemaAccessError)
+ end
+ end
+
def process_sql(model, sql)
Gitlab::Database::QueryAnalyzer.instance.within([analyzer]) do
# Skip load balancer and retrieve connection assigned to model
diff --git a/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb b/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb
index 34670696787..1bccdda3be1 100644
--- a/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Database::Reindexing::GrafanaNotifier do
include Database::DatabaseHelpers
let(:api_key) { "foo" }
- let(:api_url) { "http://bar"}
+ let(:api_url) { "http://bar" }
let(:additional_tag) { "some-tag" }
let(:action) { create(:reindex_action) }
diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb
index 976b9896dfa..495e953f993 100644
--- a/spec/lib/gitlab/database/reindexing_spec.rb
+++ b/spec/lib/gitlab/database/reindexing_spec.rb
@@ -46,6 +46,27 @@ RSpec.describe Gitlab::Database::Reindexing do
end
end
+ context 'when async index destruction is enabled' do
+ it 'executes async index destruction prior to any reindexing actions' do
+ stub_feature_flags(database_async_index_destruction: true)
+
+ expect(Gitlab::Database::AsyncIndexes).to receive(:drop_pending_indexes!).ordered.exactly(databases_count).times
+ expect(described_class).to receive(:automatic_reindexing).ordered.exactly(databases_count).times
+
+ described_class.invoke
+ end
+ end
+
+ context 'when async index destruction is disabled' do
+ it 'does not execute async index destruction' do
+ stub_feature_flags(database_async_index_destruction: false)
+
+ expect(Gitlab::Database::AsyncIndexes).not_to receive(:drop_pending_indexes!)
+
+ described_class.invoke
+ end
+ end
+
context 'calls automatic reindexing' do
it 'uses all candidate indexes' do
expect(described_class).to receive(:automatic_reindexing).exactly(databases_count).times
diff --git a/spec/lib/gitlab/database/shared_model_spec.rb b/spec/lib/gitlab/database/shared_model_spec.rb
index c88edc17817..7e0ba3397d1 100644
--- a/spec/lib/gitlab/database/shared_model_spec.rb
+++ b/spec/lib/gitlab/database/shared_model_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe Gitlab::Database::SharedModel do
shared_model = shared_model_class.new
- expect(shared_model.connection_db_config). to eq(described_class.connection_db_config)
+ expect(shared_model.connection_db_config).to eq(described_class.connection_db_config)
end
end
end
diff --git a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
index 6c32fb3ca17..836332524a9 100644
--- a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb
@@ -232,14 +232,14 @@ RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do
expect(connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
expect(connection).to receive(:execute).with("SET lock_timeout TO '15ms'").and_call_original
- subject.run { }
+ subject.run {}
end
it 'calls `sleep` after the first iteration fails, using the configured sleep time' do
expect(subject).to receive(:run_block_with_lock_timeout).and_raise(ActiveRecord::LockWaitTimeout).twice
expect(subject).to receive(:sleep).with(0.025)
- subject.run { }
+ subject.run {}
end
end
end
diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb
index 6b35ccafabc..797a01c482d 100644
--- a/spec/lib/gitlab/database/with_lock_retries_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb
@@ -248,14 +248,14 @@ RSpec.describe Gitlab::Database::WithLockRetries do
expect(connection).to receive(:execute).with("SET LOCAL lock_timeout TO '15ms'").and_call_original
expect(connection).to receive(:execute).with("RELEASE SAVEPOINT active_record_1", "TRANSACTION").and_call_original
- subject.run { }
+ subject.run {}
end
it 'calls `sleep` after the first iteration fails, using the configured sleep time' do
expect(subject).to receive(:run_block_with_lock_timeout).and_raise(ActiveRecord::LockWaitTimeout).twice
expect(subject).to receive(:sleep).with(0.025)
- subject.run { }
+ subject.run {}
end
end
@@ -265,13 +265,13 @@ RSpec.describe Gitlab::Database::WithLockRetries do
it 'prevents running inside already open transaction' do
allow(connection).to receive(:transaction_open?).and_return(true)
- expect { subject.run { } }.to raise_error(/should not run inside already open transaction/)
+ expect { subject.run {} }.to raise_error(/should not run inside already open transaction/)
end
it 'does not raise the error if not inside open transaction' do
allow(connection).to receive(:transaction_open?).and_return(false)
- expect { subject.run { } }.not_to raise_error
+ expect { subject.run {} }.not_to raise_error
end
end
end
diff --git a/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb b/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb
index fdf16069381..1150de880b5 100644
--- a/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb
+++ b/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe Gitlab::DatabaseImporters::CommonMetrics::Importer do
end
context 'if ID is missing' do
- let(:query_identifier) { }
+ let(:query_identifier) {}
it 'raises exception' do
expect { subject.execute }.to raise_error(Gitlab::DatabaseImporters::CommonMetrics::Importer::MissingQueryId)
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index 5350dda5fb2..1d1ffc8c275 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -115,6 +115,10 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
.once
.and_call_original
+ Gitlab::Redis::Cache.with do |redis|
+ expect(redis).to receive(:expire).with(cache.key, described_class::EXPIRATION)
+ end
+
2.times { cache.write_if_empty }
end
@@ -259,8 +263,12 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
describe '#key' do
subject { cache.key }
+ def options_hash(options_array)
+ OpenSSL::Digest::SHA256.hexdigest(options_array.join)
+ end
+
it 'returns cache key' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, true, true])}")
end
context 'when the `use_marker_ranges` feature flag is disabled' do
@@ -269,7 +277,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
end
it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false:true")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, false, true])}")
end
end
@@ -279,7 +287,7 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
end
it 'returns the original version of the cache' do
- is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:false")
+ is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, true, false])}")
end
end
end
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index 624160d2f48..c378ecb8134 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -117,7 +117,7 @@ RSpec.describe Gitlab::Diff::Highlight do
it 'reports to Sentry if configured' do
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).and_call_original
- expect { subject }. to raise_exception(RangeError)
+ expect { subject }.to raise_exception(RangeError)
end
end
diff --git a/spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb b/spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb
index 42ab2d1d063..ad92d90e253 100644
--- a/spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb
+++ b/spec/lib/gitlab/diff/rendered/notebook/diff_file_helper_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::Diff::Rendered::Notebook::DiffFileHelper do
describe '#image_as_rich_text' do
let(:img) { 'data:image/png;base64,some_image_here' }
- let(:line_text) { " ![](#{img})"}
+ let(:line_text) { " ![](#{img})" }
subject { dummy.image_as_rich_text(line_text) }
diff --git a/spec/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512_spec.rb b/spec/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512_spec.rb
new file mode 100644
index 00000000000..e953733c997
--- /dev/null
+++ b/spec/lib/gitlab/doorkeeper_secret_storing/pbkdf2_sha512_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::DoorkeeperSecretStoring::Pbkdf2Sha512 do
+ describe '.transform_secret' do
+ let(:plaintext_token) { 'CzOBzBfU9F-HvsqfTaTXF4ivuuxYZuv3BoAK4pnvmyw' }
+
+ it 'generates a PBKDF2+SHA512 hashed value in the correct format' do
+ expect(described_class.transform_secret(plaintext_token))
+ .to eq("$pbkdf2-sha512$20000$$.c0G5XJVEew1TyeJk5TrkvB0VyOaTmDzPrsdNRED9vVeZlSyuG3G90F0ow23zUCiWKAVwmNnR/ceh.nJG3MdpQ") # rubocop:disable Layout/LineLength
+ end
+
+ context 'when hash_oauth_tokens is disabled' do
+ before do
+ stub_feature_flags(hash_oauth_tokens: false)
+ end
+
+ it 'returns a plaintext token' do
+ expect(described_class.transform_secret(plaintext_token)).to eq(plaintext_token)
+ end
+ end
+ end
+
+ describe 'STRETCHES' do
+ it 'is 20_000' do
+ expect(described_class::STRETCHES).to eq(20_000)
+ end
+ end
+
+ describe 'SALT' do
+ it 'is empty' do
+ expect(described_class::SALT).to be_empty
+ end
+ end
+end
diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
index 9ff395070ea..585dce331ed 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
it_behaves_like :note_handler_shared_examples do
let(:recipient) { sent_notification.recipient }
- let(:update_commands_only) { fixture_file('emails/update_commands_only_reply.eml')}
+ let(:update_commands_only) { fixture_file('emails/update_commands_only_reply.eml') }
let(:no_content) { fixture_file('emails/no_content_reply.eml') }
let(:commands_in_reply) { fixture_file('emails/commands_in_reply.eml') }
let(:with_quick_actions) { fixture_file('emails/valid_reply_with_quick_actions.eml') }
@@ -54,7 +54,7 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
end
context 'with a secondary verified email address' do
- let(:verified_email) { 'alan@adventuretime.ooo'}
+ let(:verified_email) { 'alan@adventuretime.ooo' }
let(:email_raw) { fixture_file('emails/valid_reply.eml').gsub('jake@adventuretime.ooo', verified_email) }
before do
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index d0aba70081b..08a7383700b 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -493,11 +493,19 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
it 'does not create an issue' do
- expect { receiver.execute rescue nil }.not_to change { Issue.count }
+ expect do
+ receiver.execute
+ rescue StandardError
+ nil
+ end.not_to change { Issue.count }
end
it 'does not send thank you email' do
- expect { receiver.execute rescue nil }.not_to have_enqueued_job.on_queue('mailers')
+ expect do
+ receiver.execute
+ rescue StandardError
+ nil
+ end.not_to have_enqueued_job.on_queue('mailers')
end
end
@@ -532,7 +540,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
context 'service desk is disabled for the project' do
- let(:group) { create(:group)}
+ let(:group) { create(:group) }
let(:project) { create(:project, :public, group: group, path: 'test', service_desk_enabled: false) }
it 'bounces the email' do
@@ -540,7 +548,11 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
it "doesn't create an issue" do
- expect { receiver.execute rescue nil }.not_to change { Issue.count }
+ expect do
+ receiver.execute
+ rescue StandardError
+ nil
+ end.not_to change { Issue.count }
end
end
end
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb
index b5c3415fe12..7a09feb5b64 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/admin_verify_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::AdminVerify do
let(:series) { 0 }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe 'public methods' do
it 'returns value for series', :aggregate_failures do
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
index 35470ef3555..d5aec280ea6 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/create_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Create do
let_it_be(:group) { build(:group) }
let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe "public methods" do
where(series: [0, 1, 2])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb
index daeacef53f6..3ac2076bf35 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/team_short_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::TeamShort do
let(:series) { 0 }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe 'public methods' do
it 'returns value for series', :aggregate_failures do
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
index eca8ba1df00..3354b2ed5cf 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/team_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Team do
let_it_be(:group) { build(:group) }
let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe "public methods" do
where(series: [0, 1])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb
index ebad4672eb3..cf0a119ea80 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/trial_short_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::TrialShort do
let(:series) { 0 }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe 'public methods' do
it 'returns value for series', :aggregate_failures do
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
index 3e18b8e35b6..7f86c9a6c6f 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/trial_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Trial do
let_it_be(:group) { build(:group) }
let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe "public methods" do
where(series: [0, 1, 2])
diff --git a/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb b/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
index a7da2e9553d..7e6f62289d2 100644
--- a/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
+++ b/spec/lib/gitlab/email/message/in_product_marketing/verify_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Email::Message::InProductMarketing::Verify do
let_it_be(:group) { build(:group) }
let_it_be(:user) { build(:user) }
- subject(:message) { described_class.new(group: group, user: user, series: series)}
+ subject(:message) { described_class.new(group: group, user: user, series: series) }
describe "public methods" do
context 'with series 0' do
diff --git a/spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb b/spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb
index 81e2a410962..bcd59c34ea2 100644
--- a/spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb
+++ b/spec/lib/gitlab/error_tracking/error_repository/open_api_strategy_spec.rb
@@ -430,7 +430,7 @@ RSpec.describe Gitlab::ErrorTracking::ErrorRepository::OpenApiStrategy do
it do
is_expected
- .to eq("#{config.scheme}://#{public_key}@#{config.host}/errortracking/api/v1/projects/api/#{project.id}")
+ .to eq("#{config.scheme}://#{public_key}@#{config.host}/errortracking/api/v1/projects/#{project.id}")
end
end
end
diff --git a/spec/lib/gitlab/error_tracking/logger_spec.rb b/spec/lib/gitlab/error_tracking/logger_spec.rb
index 751ec10a1f0..1b722fc7896 100644
--- a/spec/lib/gitlab/error_tracking/logger_spec.rb
+++ b/spec/lib/gitlab/error_tracking/logger_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::ErrorTracking::Logger do
describe '.capture_exception' do
let(:exception) { RuntimeError.new('boom') }
let(:payload) { { foo: '123' } }
- let(:log_entry) { { message: 'boom', context: payload }}
+ let(:log_entry) { { message: 'boom', context: payload } }
it 'calls Gitlab::ErrorTracking::Logger.error with formatted log entry' do
expect_next_instance_of(Gitlab::ErrorTracking::LogFormatter) do |log_formatter|
diff --git a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
index d33f8393904..bc4526758c0 100644
--- a/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
@@ -159,13 +159,13 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
context 'when processing via the default error handler' do
context 'with Raven events' do
- let(:event) { raven_event}
+ let(:event) { raven_event }
include_examples 'Sidekiq arguments', args_in_job_hash: true
end
context 'with Sentry events' do
- let(:event) { sentry_event}
+ let(:event) { sentry_event }
include_examples 'Sidekiq arguments', args_in_job_hash: true
end
@@ -173,13 +173,13 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
context 'when processing via Gitlab::ErrorTracking' do
context 'with Raven events' do
- let(:event) { raven_event}
+ let(:event) { raven_event }
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
context 'with Sentry events' do
- let(:event) { sentry_event}
+ let(:event) { sentry_event }
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
@@ -209,13 +209,13 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
end
context 'with Raven events' do
- let(:event) { raven_event}
+ let(:event) { raven_event }
it_behaves_like 'handles jobstr fields'
end
context 'with Sentry events' do
- let(:event) { sentry_event}
+ let(:event) { sentry_event }
it_behaves_like 'handles jobstr fields'
end
@@ -233,13 +233,13 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
end
context 'with Raven events' do
- let(:event) { raven_event}
+ let(:event) { raven_event }
it_behaves_like 'does nothing'
end
context 'with Sentry events' do
- let(:event) { sentry_event}
+ let(:event) { sentry_event }
it_behaves_like 'does nothing'
end
@@ -256,13 +256,13 @@ RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor, :sentry do
end
context 'with Raven events' do
- let(:event) { raven_event}
+ let(:event) { raven_event }
it_behaves_like 'does nothing'
end
context 'with Sentry events' do
- let(:event) { sentry_event}
+ let(:event) { sentry_event }
it_behaves_like 'does nothing'
end
diff --git a/spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb b/spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb
index f74fbf1206f..1f30ac79488 100644
--- a/spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_helpers/sleeping_lock_spec.rb
@@ -52,6 +52,28 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers::SleepingLock, :clean_gitlab_redis_
end
end
+ context 'when the lease is obtained already' do
+ let!(:lease) { stub_exclusive_lease_taken(key) }
+
+ context 'when retries are not specified' do
+ it 'retries to obtain a lease and raises an error' do
+ expect(lease).to receive(:try_obtain).exactly(10).times
+
+ expect { subject.obtain }.to raise_error('Failed to obtain a lock')
+ end
+ end
+
+ context 'when specified retries are above the maximum attempts' do
+ let(:max_attempts) { 100 }
+
+ it 'retries to obtain a lease and raises an error' do
+ expect(lease).to receive(:try_obtain).exactly(65).times
+
+ expect { subject.obtain(max_attempts) }.to raise_error('Failed to obtain a lock')
+ end
+ end
+ end
+
context 'when the lease is held elsewhere' do
let!(:lease) { stub_exclusive_lease_taken(key) }
let(:max_attempts) { 7 }
diff --git a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
index 8bf06bcebe2..f9db93a6167 100644
--- a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
@@ -9,12 +9,12 @@ RSpec.describe Gitlab::ExclusiveLeaseHelpers, :clean_gitlab_redis_shared_state d
let(:unique_key) { SecureRandom.hex(10) }
describe '#in_lock' do
- subject { class_instance.in_lock(unique_key, **options) { } }
+ subject { class_instance.in_lock(unique_key, **options) {} }
let(:options) { {} }
context 'when unique key is not set' do
- let(:unique_key) { }
+ let(:unique_key) {}
it 'raises an error' do
expect { subject }.to raise_error ArgumentError
diff --git a/spec/lib/gitlab/file_markdown_link_builder_spec.rb b/spec/lib/gitlab/file_markdown_link_builder_spec.rb
index ea21bda12d3..d684beaaaca 100644
--- a/spec/lib/gitlab/file_markdown_link_builder_spec.rb
+++ b/spec/lib/gitlab/file_markdown_link_builder_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Gitlab::FileMarkdownLinkBuilder do
end
describe 'markdown_link' do
- let(:url) { "/uploads/#{filename}"}
+ let(:url) { "/uploads/#{filename}" }
before do
allow(custom_class).to receive(:secure_url).and_return(url)
diff --git a/spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb b/spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb
index 2b1fcac9257..98fb154fb05 100644
--- a/spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb
+++ b/spec/lib/gitlab/form_builders/gitlab_ui_form_builder_spec.rb
@@ -9,6 +9,40 @@ RSpec.describe Gitlab::FormBuilders::GitlabUiFormBuilder do
let_it_be(:form_builder) { described_class.new(:user, user, fake_action_view_base, {}) }
+ describe '#submit' do
+ context 'without pajamas_button enabled' do
+ subject(:submit_html) do
+ form_builder.submit('Save', class: 'gl-button btn-confirm custom-class', data: { test: true })
+ end
+
+ it 'renders a submit input' do
+ expected_html = <<~EOS
+ <input type="submit" name="commit" value="Save" class="gl-button btn-confirm custom-class" data-test="true" data-disable-with="Save" />
+ EOS
+
+ expect(html_strip_whitespace(submit_html)).to eq(html_strip_whitespace(expected_html))
+ end
+ end
+
+ context 'with pajamas_button enabled' do
+ subject(:submit_html) do
+ form_builder.submit('Save', pajamas_button: true, class: 'custom-class', data: { test: true })
+ end
+
+ it 'renders a submit button' do
+ expected_html = <<~EOS
+ <button class="gl-button btn btn-md btn-confirm custom-class" data-test="true" type="submit">
+ <span class="gl-button-text">
+ Save
+ </span>
+ </button>
+ EOS
+
+ expect(html_strip_whitespace(submit_html)).to eq(html_strip_whitespace(expected_html))
+ end
+ end
+ end
+
describe '#gitlab_ui_checkbox_component' do
context 'when not using slots' do
let(:optional_args) { {} }
@@ -25,7 +59,7 @@ RSpec.describe Gitlab::FormBuilders::GitlabUiFormBuilder do
it 'renders correct html' do
expected_html = <<~EOS
<div class="gl-form-checkbox custom-control custom-checkbox">
- <input name="user[view_diffs_file_by_file]" type="hidden" value="0" />
+ <input name="user[view_diffs_file_by_file]" type="hidden" value="0" autocomplete="off" />
<input class="custom-control-input" type="checkbox" value="1" name="user[view_diffs_file_by_file]" id="user_view_diffs_file_by_file" />
<label class="custom-control-label" for="user_view_diffs_file_by_file">
<span>Show one file at a time on merge request&#39;s Changes tab</span>
@@ -51,7 +85,7 @@ RSpec.describe Gitlab::FormBuilders::GitlabUiFormBuilder do
it 'renders help text' do
expected_html = <<~EOS
<div class="gl-form-checkbox custom-control custom-checkbox">
- <input name="user[view_diffs_file_by_file]" type="hidden" value="1" />
+ <input name="user[view_diffs_file_by_file]" type="hidden" value="1" autocomplete="off" />
<input class="custom-control-input checkbox-foo-bar" type="checkbox" value="3" name="user[view_diffs_file_by_file]" id="user_view_diffs_file_by_file" />
<label class="custom-control-label label-foo-bar" for="user_view_diffs_file_by_file">
<span>Show one file at a time on merge request&#39;s Changes tab</span>
@@ -101,7 +135,7 @@ RSpec.describe Gitlab::FormBuilders::GitlabUiFormBuilder do
it 'renders correct html' do
expected_html = <<~EOS
<div class="gl-form-checkbox custom-control custom-checkbox">
- <input name="user[view_diffs_file_by_file]" type="hidden" value="0" />
+ <input name="user[view_diffs_file_by_file]" type="hidden" value="0" autocomplete="off" />
<input class="custom-control-input" type="checkbox" value="1" name="user[view_diffs_file_by_file]" id="user_view_diffs_file_by_file" />
<label class="custom-control-label" for="user_view_diffs_file_by_file">
<span>Show one file at a time on merge request&#39;s Changes tab</span>
@@ -195,6 +229,45 @@ RSpec.describe Gitlab::FormBuilders::GitlabUiFormBuilder do
end
end
+ describe '#gitlab_ui_datepicker' do
+ subject(:datepicker_html) do
+ form_builder.gitlab_ui_datepicker(
+ :expires_at,
+ **optional_args
+ )
+ end
+
+ let(:optional_args) { {} }
+
+ context 'without optional arguments' do
+ it 'renders correct html' do
+ expected_html = <<~EOS
+ <input class="datepicker form-control gl-form-input" type="text" name="user[expires_at]" id="user_expires_at" />
+ EOS
+
+ expect(html_strip_whitespace(datepicker_html)).to eq(html_strip_whitespace(expected_html))
+ end
+ end
+
+ context 'with optional arguments' do
+ let(:optional_args) do
+ {
+ id: 'milk_gone_bad',
+ data: { action: 'throw' },
+ value: '2022-08-01'
+ }
+ end
+
+ it 'renders correct html' do
+ expected_html = <<~EOS
+ <input id="milk_gone_bad" data-action="throw" value="2022-08-01" class="datepicker form-control gl-form-input" type="text" name="user[expires_at]" />
+ EOS
+
+ expect(html_strip_whitespace(datepicker_html)).to eq(html_strip_whitespace(expected_html))
+ end
+ end
+ end
+
private
def html_strip_whitespace(html)
diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb
index e514e128785..45d88f57c09 100644
--- a/spec/lib/gitlab/git/blame_spec.rb
+++ b/spec/lib/gitlab/git/blame_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Gitlab::Git::Blame do
it 'only returns the range' do
expect(result.size).to eq(range.size)
- expect(result.map {|r| r[:line] }).to eq(['', 'This guide details how contribute to GitLab.', ''])
+ expect(result.map { |r| r[:line] }).to eq(['', 'This guide details how contribute to GitLab.', ''])
end
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index fb4510a78de..0da7aa7dad0 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Git::Blob, :seed_helper do
end
context 'utf-8 branch' do
- let(:blob) { Gitlab::Git::Blob.find(repository, 'Ääh-test-utf-8', "files/ruby/popen.rb")}
+ let(:blob) { Gitlab::Git::Blob.find(repository, 'Ääh-test-utf-8', "files/ruby/popen.rb") }
it { expect(blob.id).to eq(SeedRepo::RubyBlob::ID) }
end
@@ -235,6 +235,7 @@ RSpec.describe Gitlab::Git::Blob, :seed_helper do
it { expect(blob.id).to eq('409f37c4f05865e4fb208c771485f211a22c4c2d') }
it { expect(blob.data).to eq('') }
+
it 'does not mark the blob as binary' do
expect(blob).not_to be_binary_in_repo
end
diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb
index 97cd4777b4d..feaa1f6595c 100644
--- a/spec/lib/gitlab/git/branch_spec.rb
+++ b/spec/lib/gitlab/git/branch_spec.rb
@@ -2,8 +2,9 @@
require "spec_helper"
-RSpec.describe Gitlab::Git::Branch, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
+RSpec.describe Gitlab::Git::Branch do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw }
subject { repository.branches }
@@ -54,14 +55,14 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
describe '#size' do
subject { super().size }
- it { is_expected.to eq(SeedRepo::Repo::BRANCHES.size) }
+ it { is_expected.to eq(TestEnv::BRANCH_SHA.size) }
end
describe 'first branch' do
let(:branch) { repository.branches.first }
- it { expect(branch.name).to eq(SeedRepo::Repo::BRANCHES.first) }
- it { expect(branch.dereferenced_target.sha).to eq("0b4bc9a49b562e85de7cc9e834518ea6828729b9") }
+ it { expect(branch.name).to eq(TestEnv::BRANCH_SHA.keys.min) }
+ it { expect(branch.dereferenced_target.sha).to start_with(TestEnv::BRANCH_SHA[TestEnv::BRANCH_SHA.keys.min]) }
end
describe 'master branch' do
@@ -69,14 +70,10 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
repository.branches.find { |branch| branch.name == 'master' }
end
- it { expect(branch.dereferenced_target.sha).to eq(SeedRepo::LastCommit::ID) }
+ it { expect(branch.dereferenced_target.sha).to start_with(TestEnv::BRANCH_SHA['master']) }
end
context 'with active, stale and future branches' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project')
- end
-
let(:user) { create(:user) }
let(:stale_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago - 5.days) { create_commit } }
let(:active_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago + 5.days) { create_commit } }
@@ -88,10 +85,6 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
repository.create_branch('future-1', future_sha)
end
- after do
- ensure_seeds
- end
-
describe 'examine if the branch is active or stale' do
let(:stale_branch) { repository.find_branch('stale-1') }
let(:active_branch) { repository.find_branch('active-1') }
@@ -117,8 +110,6 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
end
end
- it { expect(repository.branches.size).to eq(SeedRepo::Repo::BRANCHES.size) }
-
def create_commit
repository.multi_action(
user,
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index da77d8ee5d6..95b49186d0f 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -222,6 +222,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 10 elements' do
expect(subject.size).to eq(10)
end
+
it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
end
@@ -240,6 +241,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 10 elements' do
expect(subject.size).to eq(10)
end
+
it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
end
@@ -259,6 +261,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
+
it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
end
@@ -279,6 +282,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
+
it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
@@ -299,6 +303,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 3 elements' do
expect(subject.size).to eq(3)
end
+
it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
@@ -570,13 +575,13 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
describe '#id' do
subject { super().id }
- it { is_expected.to eq(sample_commit_hash[:id])}
+ it { is_expected.to eq(sample_commit_hash[:id]) }
end
describe '#message' do
subject { super().message }
- it { is_expected.to eq(sample_commit_hash[:message])}
+ it { is_expected.to eq(sample_commit_hash[:message]) }
end
end
@@ -648,6 +653,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
it 'has 2 element' do
expect(subject.size).to eq(2)
end
+
it { is_expected.to include("master") }
it { is_expected.not_to include("feature") }
end
diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb
index 114b3d01952..0e3e92e03cf 100644
--- a/spec/lib/gitlab/git/diff_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_collection_spec.rb
@@ -520,7 +520,7 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
describe '#real_size' do
subject { super().real_size }
- it { is_expected.to eq('0')}
+ it { is_expected.to eq('0') }
end
describe '#line_count' do
@@ -595,7 +595,7 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
end
context 'multi-file collections' do
- let(:iterator) { [{ diff: 'b' }, { diff: 'a' * 20480 }]}
+ let(:iterator) { [{ diff: 'b' }, { diff: 'a' * 20480 }] }
it 'prunes diffs that are quite big' do
diff = nil
diff --git a/spec/lib/gitlab/git/raw_diff_change_spec.rb b/spec/lib/gitlab/git/raw_diff_change_spec.rb
index f894ae1d98b..c55fcc729b6 100644
--- a/spec/lib/gitlab/git/raw_diff_change_spec.rb
+++ b/spec/lib/gitlab/git/raw_diff_change_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Git::RawDiffChange do
- let(:raw_change) { }
+ let(:raw_change) {}
let(:change) { described_class.new(raw_change) }
context 'bad input' do
diff --git a/spec/lib/gitlab/git/remote_repository_spec.rb b/spec/lib/gitlab/git/remote_repository_spec.rb
deleted file mode 100644
index c7bc81573a6..00000000000
--- a/spec/lib/gitlab/git/remote_repository_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Git::RemoteRepository, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
-
- subject { described_class.new(repository) }
-
- describe '#empty?' do
- using RSpec::Parameterized::TableSyntax
-
- where(:repository, :result) do
- Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') | false
- Gitlab::Git::Repository.new('default', 'does-not-exist.git', '', 'group/project') | true
- end
-
- with_them do
- it { expect(subject.empty?).to eq(result) }
- end
- end
-
- describe '#commit_id' do
- it 'returns an OID if the revision exists' do
- expect(subject.commit_id('v1.0.0')).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
- end
-
- it 'is nil when the revision does not exist' do
- expect(subject.commit_id('does-not-exist')).to be_nil
- end
- end
-
- describe '#branch_exists?' do
- using RSpec::Parameterized::TableSyntax
-
- where(:branch, :result) do
- 'master' | true
- 'does-not-exist' | false
- end
-
- with_them do
- it { expect(subject.branch_exists?(branch)).to eq(result) }
- end
- end
-
- describe '#same_repository?' do
- using RSpec::Parameterized::TableSyntax
-
- where(:other_repository, :result) do
- repository | true
- Gitlab::Git::Repository.new(repository.storage, repository.relative_path, '', 'group/project') | true
- Gitlab::Git::Repository.new('broken', TEST_REPO_PATH, '', 'group/project') | false
- Gitlab::Git::Repository.new(repository.storage, 'wrong/relative-path.git', '', 'group/project') | false
- Gitlab::Git::Repository.new('broken', 'wrong/relative-path.git', '', 'group/project') | false
- end
-
- with_them do
- it { expect(subject.same_repository?(other_repository)).to eq(result) }
- end
- end
-end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index e20d5b928c4..a1fb8b70bd7 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1252,8 +1252,8 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
describe '#raw_changes_between' do
- let(:old_rev) { }
- let(:new_rev) { }
+ let(:old_rev) {}
+ let(:new_rev) {}
let(:changes) { repository.raw_changes_between(old_rev, new_rev) }
context 'initial commit' do
@@ -1837,6 +1837,47 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#find_tag' do
+ it 'returns a tag' do
+ tag = repository.find_tag('v1.0.0')
+
+ expect(tag).to be_a_kind_of(Gitlab::Git::Tag)
+ expect(tag.name).to eq('v1.0.0')
+ end
+
+ shared_examples 'a nonexistent tag' do
+ it 'returns nil' do
+ expect(repository.find_tag('this-is-garbage')).to be_nil
+ end
+ end
+
+ context 'when asking for a non-existent tag' do
+ it_behaves_like 'a nonexistent tag'
+ end
+
+ context 'when Gitaly returns Internal error' do
+ before do
+ expect(repository.gitaly_ref_client)
+ .to receive(:find_tag)
+ .and_raise(GRPC::Internal, "tag not found")
+ end
+
+ it_behaves_like 'a nonexistent tag'
+ end
+
+ context 'when Gitaly returns tag_not_found error' do
+ before do
+ expect(repository.gitaly_ref_client)
+ .to receive(:find_tag)
+ .and_raise(new_detailed_error(GRPC::Core::StatusCodes::NOT_FOUND,
+ "tag was not found",
+ Gitaly::FindTagError.new(tag_not_found: Gitaly::ReferenceNotFoundError.new)))
+ end
+
+ it_behaves_like 'a nonexistent tag'
+ end
+ end
+
describe '#languages' do
it 'returns exactly the expected results' do
languages = repository.languages('4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6')
@@ -2017,17 +2058,14 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
describe '#set_full_path' do
before do
- repository_rugged.config["gitlab.fullpath"] = repository_path
+ repository.set_full_path(full_path: repository_path)
end
context 'is given a path' do
it 'writes it to disk' do
repository.set_full_path(full_path: "not-the/real-path.git")
- config = File.read(File.join(repository_path, "config"))
-
- expect(config).to include("[gitlab]")
- expect(config).to include("fullpath = not-the/real-path.git")
+ expect(repository.full_path).to eq('not-the/real-path.git')
end
end
@@ -2035,15 +2073,12 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
it 'does not write it to disk' do
repository.set_full_path(full_path: "")
- config = File.read(File.join(repository_path, "config"))
-
- expect(config).to include("[gitlab]")
- expect(config).to include("fullpath = #{repository_path}")
+ expect(repository.full_path).to eq(repository_path)
end
end
context 'repository does not exist' do
- it 'raises NoRepository and does not call Gitaly WriteConfig' do
+ it 'raises NoRepository and does not call SetFullPath' do
repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project')
expect(repository.gitaly_repository_client).not_to receive(:set_full_path)
@@ -2055,6 +2090,18 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#full_path' do
+ let(:full_path) { 'some/path' }
+
+ before do
+ repository.set_full_path(full_path: full_path)
+ end
+
+ it 'returns the full path' do
+ expect(repository.full_path).to eq(full_path)
+ end
+ end
+
describe '#merge_to_ref' do
let(:repository) { mutable_repository }
let(:branch_head) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
@@ -2468,7 +2515,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end
describe '#rename' do
- let(:project) { create(:project, :repository)}
+ let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
it 'moves the repository' do
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 b2603e099e6..03d1c125e36 100644
--- a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
+++ b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
@@ -58,35 +58,55 @@ RSpec.describe Gitlab::Git::RuggedImpl::UseRugged, :seed_helper do
end
end
- context 'when not running puma with multiple threads' do
- before do
- allow(subject).to receive(:running_puma_with_multiple_threads?).and_return(false)
+ context 'when skip_rugged_auto_detect feature flag is enabled' do
+ context 'when not running puma with multiple threads' do
+ before do
+ allow(subject).to receive(:running_puma_with_multiple_threads?).and_return(false)
+ stub_feature_flags(feature_flag_name => nil)
+ stub_feature_flags(skip_rugged_auto_detect: true)
+ end
+
+ it 'returns false' do
+ expect(subject.use_rugged?(repository, feature_flag_name)).to be false
+ end
end
+ end
- it 'returns true when gitaly matches disk' do
- expect(subject.use_rugged?(repository, feature_flag_name)).to be true
+ context 'when skip_rugged_auto_detect feature flag is disabled' do
+ before do
+ stub_feature_flags(skip_rugged_auto_detect: false)
end
- it 'returns false when disk access fails' do
- allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return("/fake/path/doesnt/exist")
+ context 'when not running puma with multiple threads' do
+ before do
+ allow(subject).to receive(:running_puma_with_multiple_threads?).and_return(false)
+ end
- expect(subject.use_rugged?(repository, feature_flag_name)).to be false
- end
+ it 'returns true when gitaly matches disk' do
+ expect(subject.use_rugged?(repository, feature_flag_name)).to be true
+ end
- it "returns false when gitaly doesn't match disk" do
- allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return(temp_gitaly_metadata_file)
+ it 'returns false when disk access fails' do
+ allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return("/fake/path/doesnt/exist")
- expect(subject.use_rugged?(repository, feature_flag_name)).to be_falsey
+ expect(subject.use_rugged?(repository, feature_flag_name)).to be false
+ end
- File.delete(temp_gitaly_metadata_file)
- end
+ it "returns false when gitaly doesn't match disk" do
+ allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return(temp_gitaly_metadata_file)
+
+ expect(subject.use_rugged?(repository, feature_flag_name)).to be_falsey
- it "doesn't lead to a second rpc call because gitaly client should use the cached value" do
- expect(subject.use_rugged?(repository, feature_flag_name)).to be true
+ File.delete(temp_gitaly_metadata_file)
+ end
- expect(Gitlab::GitalyClient).not_to receive(:filesystem_id)
+ it "doesn't lead to a second rpc call because gitaly client should use the cached value" do
+ expect(subject.use_rugged?(repository, feature_flag_name)).to be true
- subject.use_rugged?(repository, feature_flag_name)
+ expect(Gitlab::GitalyClient).not_to receive(:filesystem_id)
+
+ subject.use_rugged?(repository, feature_flag_name)
+ end
end
end
end
@@ -165,7 +185,7 @@ RSpec.describe Gitlab::Git::RuggedImpl::UseRugged, :seed_helper do
context 'all features are enabled' do
let(:feature_keys) { [:feature_key_1, :feature_key_2] }
- it { is_expected.to be_truthy}
+ it { is_expected.to be_truthy }
end
context 'all features are not enabled' do
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index 4f56595d7d2..240cf6ed46f 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -2,12 +2,13 @@
require "spec_helper"
-RSpec.describe Gitlab::Git::Tag, :seed_helper do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
+RSpec.describe Gitlab::Git::Tag do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
describe '#tags' do
- describe 'first tag' do
- let(:tag) { repository.tags.first }
+ describe 'unsigned tag' do
+ let(:tag) { repository.tags.detect { |t| t.name == 'v1.0.0' } }
it { expect(tag.name).to eq("v1.0.0") }
it { expect(tag.target).to eq("f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8") }
@@ -22,29 +23,13 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
it { expect(tag.tagger.timezone).to eq("+0200") }
end
- describe 'last tag' do
- let(:tag) { repository.tags.last }
-
- it { expect(tag.name).to eq("v1.2.1") }
- it { expect(tag.target).to eq("2ac1f24e253e08135507d0830508febaaccf02ee") }
- it { expect(tag.dereferenced_target.sha).to eq("fa1b1e6c004a68b7d8763b86455da9e6b23e36d6") }
- it { expect(tag.message).to eq("Version 1.2.1") }
- it { expect(tag.has_signature?).to be_falsey }
- it { expect(tag.signature_type).to eq(:NONE) }
- it { expect(tag.signature).to be_nil }
- it { expect(tag.tagger.name).to eq("Douwe Maan") }
- it { expect(tag.tagger.email).to eq("douwe@selenight.nl") }
- it { expect(tag.tagger.date).to eq(Google::Protobuf::Timestamp.new(seconds: 1427789449)) }
- it { expect(tag.tagger.timezone).to eq("+0200") }
- end
-
describe 'signed tag' do
- let(:project) { create(:project, :repository) }
- let(:tag) { project.repository.find_tag('v1.1.1') }
+ let(:tag) { repository.tags.detect { |t| t.name == 'v1.1.1' } }
+ it { expect(tag.name).to eq("v1.1.1") }
it { expect(tag.target).to eq("8f03acbcd11c53d9c9468078f32a2622005a4841") }
it { expect(tag.dereferenced_target.sha).to eq("189a6c924013fc3fe40d6f1ec1dc20214183bc97") }
- it { expect(tag.message).to eq("x509 signed tag" + "\n" + X509Helpers::User1.signed_tag_signature.chomp) }
+ it { expect(tag.message).to eq("x509 signed tag\n" + X509Helpers::User1.signed_tag_signature.chomp) }
it { expect(tag.has_signature?).to be_truthy }
it { expect(tag.signature_type).to eq(:X509) }
it { expect(tag.signature).not_to be_nil }
@@ -54,11 +39,11 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
it { expect(tag.tagger.timezone).to eq("+0100") }
end
- it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
+ it { expect(repository.tags.size).to be > 0 }
end
describe '.get_message' do
- let(:tag_ids) { %w[f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8 8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b] }
+ let(:tag_ids) { %w[f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8 8f03acbcd11c53d9c9468078f32a2622005a4841] }
subject do
tag_ids.map { |id| described_class.get_message(repository, id) }
@@ -66,7 +51,7 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
it 'gets tag messages' do
expect(subject[0]).to eq("Release\n")
- expect(subject[1]).to eq("Version 1.1.0\n")
+ expect(subject[1]).to eq("x509 signed tag\n" + X509Helpers::User1.signed_tag_signature)
end
it 'gets messages in one batch', :request_store do
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 172d7a3f27b..b520de03929 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -2,10 +2,11 @@
require "spec_helper"
-RSpec.describe Gitlab::Git::Tree, :seed_helper do
+RSpec.describe Gitlab::Git::Tree do
let_it_be(:user) { create(:user) }
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw }
shared_examples :repo do
subject(:tree) { Gitlab::Git::Tree.where(repository, sha, path, recursive, pagination_params) }
@@ -105,10 +106,6 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do
).newrev
end
- after do
- ensure_seeds
- end
-
it { expect(subdir_file.flat_path).to eq('files/flat/path/correct') }
end
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 5ee9cf05b3e..8577cad1011 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::GitAccess do
+RSpec.describe Gitlab::GitAccess, :aggregate_failures do
include TermsHelper
include GitHelpers
include AdminModeHelper
@@ -78,9 +78,7 @@ RSpec.describe Gitlab::GitAccess do
let(:auth_result_type) { :ci }
it "doesn't block http pull" do
- aggregate_failures do
- expect { pull_access_check }.not_to raise_error
- end
+ expect { pull_access_check }.not_to raise_error
end
end
end
@@ -153,6 +151,15 @@ RSpec.describe Gitlab::GitAccess do
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
@@ -229,9 +236,9 @@ RSpec.describe Gitlab::GitAccess do
end
context 'key is expired' do
- let(:actor) { create(:rsa_key_2048, :expired) }
+ let(:actor) { create(:deploy_key, :expired) }
- it 'does not allow expired keys', :aggregate_failures do
+ it 'does not allow expired keys' do
expect { pull_access_check }.to raise_forbidden('Your SSH key has expired.')
expect { push_access_check }.to raise_forbidden('Your SSH key has expired.')
end
@@ -242,7 +249,7 @@ RSpec.describe Gitlab::GitAccess do
stub_application_setting(rsa_key_restriction: 4096)
end
- it 'does not allow keys which are too small', :aggregate_failures do
+ it 'does not allow keys which are too small' do
expect(actor).not_to be_valid
expect { pull_access_check }.to raise_forbidden('Your SSH key must be at least 4096 bits.')
expect { push_access_check }.to raise_forbidden('Your SSH key must be at least 4096 bits.')
@@ -254,7 +261,7 @@ RSpec.describe Gitlab::GitAccess do
stub_application_setting(rsa_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
end
- it 'does not allow keys which are too small', :aggregate_failures do
+ it 'does not allow keys which are too small' do
expect(actor).not_to be_valid
expect { pull_access_check }.to raise_forbidden(/Your SSH key type is forbidden/)
expect { push_access_check }.to raise_forbidden(/Your SSH key type is forbidden/)
@@ -263,7 +270,7 @@ RSpec.describe Gitlab::GitAccess do
end
it_behaves_like '#check with a key that is not valid' do
- let(:actor) { build(:rsa_key_2048, user: user) }
+ let(:actor) { build(:deploy_key, user: user) }
end
it_behaves_like '#check with a key that is not valid' do
@@ -736,6 +743,15 @@ RSpec.describe Gitlab::GitAccess do
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
end
end
@@ -1163,13 +1179,13 @@ RSpec.describe Gitlab::GitAccess do
-> { push_access_check }]
end
- it 'blocks access when the user did not accept terms', :aggregate_failures do
+ it 'blocks access when the user did not accept terms' do
actions.each do |action|
expect { action.call }.to raise_forbidden(/must accept the Terms of Service in order to perform this action/)
end
end
- it 'allows access when the user accepted the terms', :aggregate_failures do
+ it 'allows access when the user accepted the terms' do
accept_terms(user)
actions.each do |action|
diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb
index 784d25f55c1..f359679a930 100644
--- a/spec/lib/gitlab/git_spec.rb
+++ b/spec/lib/gitlab/git_spec.rb
@@ -54,6 +54,7 @@ RSpec.describe Gitlab::Git do
with_them do
it { expect(described_class.shas_eql?(sha1, sha2)).to eq(result) }
+
it 'is commutative' do
expect(described_class.shas_eql?(sha2, sha1)).to eq(result)
end
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index d5d1bef7bff..0d591fe6c43 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -340,7 +340,7 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
describe '#list_new_commits' do
let(:revisions) { [revision] }
let(:gitaly_commits) { create_list(:gitaly_commit, 3) }
- let(:expected_commits) { gitaly_commits.map { |c| Gitlab::Git::Commit.new(repository, c) }}
+ let(:expected_commits) { gitaly_commits.map { |c| Gitlab::Git::Commit.new(repository, c) } }
subject do
client.list_new_commits(revisions)
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index e04895d975f..5d854f0c9d1 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -84,37 +84,6 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
subject
end
- describe '#user_merge_to_ref' do
- let(:first_parent_ref) { 'refs/heads/my-branch' }
- let(:source_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
- let(:ref) { 'refs/merge-requests/x/merge' }
- let(:message) { 'validación' }
- let(:response) { Gitaly::UserMergeToRefResponse.new(commit_id: 'new-commit-id') }
-
- let(:payload) do
- { source_sha: source_sha, branch: 'branch', target_ref: ref,
- message: message, first_parent_ref: first_parent_ref, allow_conflicts: true }
- end
-
- it 'sends a user_merge_to_ref message' do
- freeze_time do
- expect_any_instance_of(Gitaly::OperationService::Stub).to receive(:user_merge_to_ref) do |_, request, options|
- expect(options).to be_kind_of(Hash)
- expect(request.to_h).to eq(
- payload.merge({
- repository: repository.gitaly_repository.to_h,
- message: message.dup.force_encoding(Encoding::ASCII_8BIT),
- user: Gitlab::Git::User.from_gitlab(user).to_gitaly.to_h,
- timestamp: { nanos: 0, seconds: Time.current.to_i }
- })
- )
- end.and_return(response)
-
- client.user_merge_to_ref(user, **payload)
- end
- end
- end
-
context "when pre_receive_error is present" do
let(:response) do
Gitaly::UserUpdateBranchResponse.new(pre_receive_error: "GitLab: something failed")
@@ -131,6 +100,37 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
end
end
+ describe '#user_merge_to_ref' do
+ let(:first_parent_ref) { 'refs/heads/my-branch' }
+ let(:source_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
+ let(:ref) { 'refs/merge-requests/x/merge' }
+ let(:message) { 'validación' }
+ let(:response) { Gitaly::UserMergeToRefResponse.new(commit_id: 'new-commit-id') }
+
+ let(:payload) do
+ { source_sha: source_sha, branch: 'branch', target_ref: ref,
+ message: message, first_parent_ref: first_parent_ref, allow_conflicts: true }
+ end
+
+ it 'sends a user_merge_to_ref message' do
+ freeze_time do
+ expect_any_instance_of(Gitaly::OperationService::Stub).to receive(:user_merge_to_ref) do |_, request, options|
+ expect(options).to be_kind_of(Hash)
+ expect(request.to_h).to eq(
+ payload.merge({
+ repository: repository.gitaly_repository.to_h,
+ message: message.dup.force_encoding(Encoding::ASCII_8BIT),
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly.to_h,
+ timestamp: { nanos: 0, seconds: Time.current.to_i }
+ })
+ )
+ end.and_return(response)
+
+ client.user_merge_to_ref(user, **payload)
+ end
+ end
+ end
+
describe '#user_delete_branch' do
let(:branch_name) { 'my-branch' }
let(:request) do
@@ -551,7 +551,7 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
end
let(:expected_error) { Gitlab::Git::Repository::CreateTreeError }
- let(:expected_error_message) { }
+ let(:expected_error_message) {}
it_behaves_like '#user_cherry_pick with a gRPC error'
end
@@ -559,7 +559,7 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
context 'when a non-detailed gRPC error is raised' do
let(:raised_error) { GRPC::Internal.new('non-detailed error') }
let(:expected_error) { GRPC::Internal }
- let(:expected_error_message) { }
+ let(:expected_error_message) {}
it_behaves_like '#user_cherry_pick with a gRPC error'
end
@@ -813,4 +813,146 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
end
end
end
+
+ describe '#add_tag' do
+ let(:tag_name) { 'some-tag' }
+ let(:tag_message) { nil }
+ let(:target) { 'master' }
+
+ subject(:add_tag) do
+ client.add_tag(tag_name, user, target, tag_message)
+ end
+
+ context 'without tag message' do
+ let(:tag_name) { 'lightweight-tag' }
+
+ it 'creates a lightweight tag' do
+ tag = add_tag
+ expect(tag.name).to eq(tag_name)
+ expect(tag.message).to eq('')
+ end
+ end
+
+ context 'with tag message' do
+ let(:tag_name) { 'annotated-tag' }
+ let(:tag_message) { "tag message" }
+
+ it 'creates an annotated tag' do
+ tag = add_tag
+ expect(tag.name).to eq(tag_name)
+ expect(tag.message).to eq(tag_message)
+ end
+ end
+
+ context 'with preexisting tag' do
+ let(:tag_name) { 'v1.0.0' }
+
+ it 'raises a TagExistsError' do
+ expect { add_tag }.to raise_error(Gitlab::Git::Repository::TagExistsError)
+ end
+ end
+
+ context 'with invalid target' do
+ let(:target) { 'refs/heads/does-not-exist' }
+
+ it 'raises an InvalidRef error' do
+ expect { add_tag }.to raise_error(Gitlab::Git::Repository::InvalidRef)
+ end
+ end
+
+ context 'with pre-receive error' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_create_tag)
+ .and_return(Gitaly::UserCreateTagResponse.new(pre_receive_error: "GitLab: something failed"))
+ end
+
+ it 'raises a PreReceiveError' do
+ expect { add_tag }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
+ end
+ end
+
+ context 'with internal error' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_create_tag)
+ .and_raise(GRPC::Internal.new('undetailed internal error'))
+ end
+
+ it 'raises an Internal error' do
+ expect { add_tag }.to raise_error do |error|
+ expect(error).to be_a(GRPC::Internal)
+ expect(error.details).to eq('undetailed internal error')
+ end
+ end
+ end
+
+ context 'with structured errors' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_create_tag)
+ .and_raise(structured_error)
+ end
+
+ context 'with ReferenceExistsError' do
+ let(:structured_error) do
+ new_detailed_error(
+ GRPC::Core::StatusCodes::ALREADY_EXISTS,
+ 'tag exists already',
+ Gitaly::UserCreateTagError.new(
+ reference_exists: Gitaly::ReferenceExistsError.new(
+ reference_name: tag_name,
+ oid: 'something'
+ )))
+ end
+
+ it 'raises a TagExistsError' do
+ expect { add_tag }.to raise_error(Gitlab::Git::Repository::TagExistsError)
+ end
+ end
+
+ context 'with AccessCheckError' do
+ let(:structured_error) do
+ new_detailed_error(
+ GRPC::Core::StatusCodes::PERMISSION_DENIED,
+ "error creating tag",
+ Gitaly::UserCreateTagError.new(
+ access_check: Gitaly::AccessCheckError.new(
+ error_message: "You are not allowed to create this tag.",
+ protocol: "web",
+ user_id: "user-15",
+ changes: "df15b32277d2c55c6c595845a87109b09c913c556 5d6e0f935ad9240655f64e883cd98fad6f9a17ee refs/tags/v1.0.0\n"
+ )))
+ end
+
+ it 'raises a PreReceiveError' do
+ expect { add_tag }.to raise_error do |error|
+ expect(error).to be_a(Gitlab::Git::PreReceiveError)
+ expect(error.message).to eq("You are not allowed to create this tag.")
+ end
+ end
+ end
+
+ context 'with CustomHookError' do
+ let(:structured_error) do
+ new_detailed_error(
+ GRPC::Core::StatusCodes::PERMISSION_DENIED,
+ "custom hook error",
+ Gitaly::UserCreateTagError.new(
+ custom_hook: Gitaly::CustomHookError.new(
+ stdout: "some stdout",
+ stderr: "GitLab: some custom hook error message",
+ hook_type: Gitaly::CustomHookError::HookType::HOOK_TYPE_PRERECEIVE
+ )))
+ end
+
+ it 'raises a PreReceiveError' do
+ expect { add_tag }.to raise_error do |error|
+ expect(error).to be_a(Gitlab::Git::PreReceiveError)
+ expect(error.message).to eq("some custom hook error message")
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 566bdbacf4a..277276bb1d3 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -120,6 +120,28 @@ RSpec.describe Gitlab::GitalyClient::RefService do
expect(client.find_tag('')).to be_nil
end
end
+
+ context 'when Gitaly returns an Internal error' do
+ it 'raises an Internal error' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_tag)
+ .and_raise(GRPC::Internal.new('something went wrong'))
+
+ expect { client.find_tag('v1.0.0') }.to raise_error(GRPC::Internal)
+ end
+ end
+
+ context 'when Gitaly returns a tag_not_found error' do
+ it 'raises an UnknownRef error' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_tag)
+ .and_raise(new_detailed_error(GRPC::Core::StatusCodes::NOT_FOUND,
+ "tag was not found",
+ Gitaly::FindTagError.new(tag_not_found: Gitaly::ReferenceNotFoundError.new)))
+
+ expect { client.find_tag('v1.0.0') }.to raise_error(Gitlab::Git::UnknownRef, 'tag does not exist: v1.0.0')
+ end
+ end
end
describe '#default_branch_name' do
@@ -286,7 +308,7 @@ RSpec.describe Gitlab::GitalyClient::RefService do
end
context 'with a invalid format error' do
- let(:invalid_refs) {['\invali.\d/1', '\.invali/d/2']}
+ let(:invalid_refs) { ['\invali.\d/1', '\.invali/d/2'] }
let(:invalid_reference_format_error) do
new_detailed_error(
GRPC::Core::StatusCodes::INVALID_ARGUMENT,
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 39de9a65390..63d32cb906f 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -276,32 +276,12 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
describe '#disconnect_alternates' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
- let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
- let(:pool_repository) { create(:pool_repository) }
- let(:object_pool) { pool_repository.object_pool }
- let(:object_pool_service) { Gitlab::GitalyClient::ObjectPoolService.new(object_pool) }
-
- before do
- object_pool_service.create(repository) # rubocop:disable Rails/SaveBang
- object_pool_service.link_repository(repository)
- end
-
- it 'deletes the alternates file' do
- repository.disconnect_alternates
-
- alternates_file = File.join(repository_path, "objects", "info", "alternates")
+ it 'sends a disconnect_git_alternates message' do
+ expect_any_instance_of(Gitaly::ObjectPoolService::Stub)
+ .to receive(:disconnect_git_alternates)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
- expect(File.exist?(alternates_file)).to be_falsey
- end
-
- context 'when called twice' do
- it "doesn't raise an error" do
- repository.disconnect_alternates
-
- expect { repository.disconnect_alternates }.not_to raise_error
- end
+ client.disconnect_alternates
end
end
@@ -351,4 +331,16 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
client.set_full_path(path)
end
end
+
+ describe '#full_path' do
+ let(:path) { 'repo/path' }
+
+ it 'sends a full_path message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:full_path)
+ .and_return(double(path: path))
+
+ expect(client.full_path).to eq(path)
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
index c4d05e92633..2bd3910ad87 100644
--- a/spec/lib/gitlab/github_import/client_spec.rb
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe Gitlab::GithubImport::Client do
expect(client).to receive(:requests_remaining?).and_return(true)
- client.with_rate_limit { }
+ client.with_rate_limit {}
end
it 'ignores rate limiting when disabled' do
diff --git a/spec/lib/gitlab/github_import/importer/events/base_importer_spec.rb b/spec/lib/gitlab/github_import/importer/events/base_importer_spec.rb
new file mode 100644
index 00000000000..41fe5fbdbbd
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/events/base_importer_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Events::BaseImporter do
+ let(:project) { instance_double('Project') }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+ let(:issue_event) { instance_double('Gitlab::GithubImport::Representation::IssueEvent') }
+ let(:importer_class) { Class.new(described_class) }
+ let(:importer_instance) { importer_class.new(project, client) }
+
+ describe '#execute' do
+ it { expect { importer_instance.execute(issue_event) }.to raise_error(NotImplementedError) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/events/changed_assignee_spec.rb b/spec/lib/gitlab/github_import/importer/events/changed_assignee_spec.rb
new file mode 100644
index 00000000000..2f6f727dc38
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/events/changed_assignee_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedAssignee do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:assigner) { create(:user) }
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+ let(:issue) { create(:issue, project: project) }
+
+ let(:issue_event) do
+ Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
+ 'id' => 6501124486,
+ 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'event' => event_type,
+ 'commit_id' => nil,
+ 'created_at' => '2022-04-26 18:30:53 UTC',
+ 'assigner' => { 'id' => assigner.id, 'login' => assigner.username },
+ 'assignee' => { 'id' => assignee.id, 'login' => assignee.username },
+ 'issue' => { 'number' => issue.iid }
+ )
+ end
+
+ let(:note_attrs) do
+ {
+ noteable_id: issue.id,
+ noteable_type: Issue.name,
+ project_id: project.id,
+ author_id: assigner.id,
+ system: true,
+ created_at: issue_event.created_at,
+ updated_at: issue_event.created_at
+ }.stringify_keys
+ end
+
+ let(:expected_system_note_metadata_attrs) do
+ {
+ action: "assignee",
+ created_at: issue_event.created_at,
+ updated_at: issue_event.created_at
+ }.stringify_keys
+ end
+
+ shared_examples 'new note' do
+ it 'creates expected note' do
+ expect { importer.execute(issue_event) }.to change { issue.notes.count }
+ .from(0).to(1)
+
+ expect(issue.notes.last)
+ .to have_attributes(expected_note_attrs)
+ end
+
+ it 'creates expected system note metadata' do
+ expect { importer.execute(issue_event) }.to change { SystemNoteMetadata.count }
+ .from(0).to(1)
+
+ expect(SystemNoteMetadata.last)
+ .to have_attributes(
+ expected_system_note_metadata_attrs.merge(
+ note_id: Note.last.id
+ )
+ )
+ end
+ end
+
+ describe '#execute' do
+ before do
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(assignee.id, assignee.username).and_return(assignee.id)
+ allow(finder).to receive(:find).with(assigner.id, assigner.username).and_return(assigner.id)
+ end
+ end
+
+ context 'when importing an assigned event' do
+ let(:event_type) { 'assigned' }
+ let(:expected_note_attrs) { note_attrs.merge(note: "assigned to @#{assignee.username}") }
+
+ it_behaves_like 'new note'
+ end
+
+ context 'when importing an unassigned event' do
+ let(:event_type) { 'unassigned' }
+ let(:expected_note_attrs) { note_attrs.merge(note: "unassigned @#{assigner.username}") }
+
+ it_behaves_like 'new note'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/events/changed_label_spec.rb b/spec/lib/gitlab/github_import/importer/events/changed_label_spec.rb
index b773598853d..e21672aa430 100644
--- a/spec/lib/gitlab/github_import/importer/events/changed_label_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/events/changed_label_spec.rb
@@ -3,23 +3,25 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
- subject(:importer) { described_class.new(project, user.id) }
+ subject(:importer) { described_class.new(project, client) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let!(:label) { create(:label, project: project) }
let(:issue_event) do
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
'id' => 6501124486,
- 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'actor' => { 'id' => user.id, 'login' => user.username },
'event' => event_type,
'commit_id' => nil,
'label_title' => label.title,
'issue_db_id' => issue.id,
- 'created_at' => '2022-04-26 18:30:53 UTC'
+ 'created_at' => '2022-04-26 18:30:53 UTC',
+ 'issue' => { 'number' => issue.iid }
)
end
@@ -43,6 +45,12 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedLabel do
before do
allow(Gitlab::Cache::Import::Caching).to receive(:read_integer).and_return(label.id)
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
end
context 'when importing a labeled event' do
diff --git a/spec/lib/gitlab/github_import/importer/events/changed_milestone_spec.rb b/spec/lib/gitlab/github_import/importer/events/changed_milestone_spec.rb
new file mode 100644
index 00000000000..2687627fc23
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/events/changed_milestone_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::Events::ChangedMilestone do
+ subject(:importer) { described_class.new(project, client) }
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
+ let(:issue) { create(:issue, project: project) }
+ let!(:milestone) { create(:milestone, project: project) }
+
+ let(:issue_event) do
+ Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
+ 'id' => 6501124486,
+ 'actor' => { 'id' => user.id, 'login' => user.username },
+ 'event' => event_type,
+ 'commit_id' => nil,
+ 'milestone_title' => milestone.title,
+ 'issue_db_id' => issue.id,
+ 'created_at' => '2022-04-26 18:30:53 UTC',
+ 'issue' => { 'number' => issue.iid }
+ )
+ end
+
+ let(:event_attrs) do
+ {
+ user_id: user.id,
+ issue_id: issue.id,
+ milestone_id: milestone.id,
+ state: 'opened',
+ created_at: issue_event.created_at
+ }.stringify_keys
+ end
+
+ shared_examples 'new event' do
+ it 'creates a new milestone event' do
+ expect { importer.execute(issue_event) }.to change { issue.resource_milestone_events.count }
+ .from(0).to(1)
+ expect(issue.resource_milestone_events.last)
+ .to have_attributes(expected_event_attrs)
+ end
+ end
+
+ describe '#execute' do
+ before do
+ allow(Gitlab::Cache::Import::Caching).to receive(:read_integer).and_return(milestone.id)
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
+ end
+
+ context 'when importing a milestoned event' do
+ let(:event_type) { 'milestoned' }
+ let(:expected_event_attrs) { event_attrs.merge(action: 'add') }
+
+ it_behaves_like 'new event'
+ end
+
+ context 'when importing demilestoned event' do
+ let(:event_type) { 'demilestoned' }
+ let(:expected_event_attrs) { event_attrs.merge(action: 'remove') }
+
+ it_behaves_like 'new event'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/events/closed_spec.rb b/spec/lib/gitlab/github_import/importer/events/closed_spec.rb
index 116917d3e06..9a49d80a8bb 100644
--- a/spec/lib/gitlab/github_import/importer/events/closed_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/events/closed_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
- subject(:importer) { described_class.new(project, user.id) }
+ subject(:importer) { described_class.new(project, client) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:commit_id) { nil }
@@ -16,11 +17,11 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
'id' => 6501124486,
'node_id' => 'CE_lADOHK9fA85If7x0zwAAAAGDf0mG',
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
- 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'actor' => { 'id' => user.id, 'login' => user.username },
'event' => 'closed',
'created_at' => '2022-04-26 18:30:53 UTC',
'commit_id' => commit_id,
- 'issue_db_id' => issue.id
+ 'issue' => { 'number' => issue.iid }
)
end
@@ -45,6 +46,15 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Closed do
}.stringify_keys
end
+ before do
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
+ end
+
it 'creates expected event and state event' do
importer.execute(issue_event)
diff --git a/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb b/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb
index 118c482a7d9..68e001c7364 100644
--- a/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/events/cross_referenced_spec.rb
@@ -3,15 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_gitlab_redis_cache do
- subject(:importer) { described_class.new(project, user.id) }
+ subject(:importer) { described_class.new(project, client) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
- let(:sawyer_stub) { Struct.new(:iid, :issuable_type, keyword_init: true) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
- let(:issue) { create(:issue, project: project) }
- let(:referenced_in) { build_stubbed(:issue, project: project) }
+ let(:issue_iid) { 999 }
+ let(:issue) { create(:issue, project: project, iid: issue_iid) }
+ let(:referenced_in) { build_stubbed(:issue, project: project, iid: issue_iid + 1) }
let(:commit_id) { nil }
let(:issue_event) do
@@ -19,7 +20,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
'id' => 6501124486,
'node_id' => 'CE_lADOHK9fA85If7x0zwAAAAGDf0mG',
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
- 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'actor' => { 'id' => user.id, 'login' => user.username },
'event' => 'cross-referenced',
'source' => {
'type' => 'issue',
@@ -29,7 +30,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
}
},
'created_at' => '2022-04-26 18:30:53 UTC',
- 'issue_db_id' => issue.id
+ 'issue' => { 'number' => issue.iid }
)
end
@@ -38,7 +39,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
{
system: true,
noteable_type: Issue.name,
- noteable_id: issue_event.issue_db_id,
+ noteable_id: issue.id,
project_id: project.id,
author_id: user.id,
note: expected_note_body,
@@ -47,12 +48,16 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
end
context 'when referenced in other issue' do
- let(:expected_note_body) { "mentioned in issue ##{issue.iid}" }
+ let(:expected_note_body) { "mentioned in issue ##{referenced_in.iid}" }
before do
- other_issue_resource = sawyer_stub.new(iid: referenced_in.iid, issuable_type: 'Issue')
- Gitlab::GithubImport::IssuableFinder.new(project, other_issue_resource)
- .cache_database_id(referenced_in.iid)
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(referenced_in.iid)
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
end
it 'creates expected note' do
@@ -71,10 +76,13 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
let(:expected_note_body) { "mentioned in merge request !#{referenced_in.iid}" }
before do
- other_issue_resource =
- sawyer_stub.new(iid: referenced_in.iid, issuable_type: 'MergeRequest')
- Gitlab::GithubImport::IssuableFinder.new(project, other_issue_resource)
- .cache_database_id(referenced_in.iid)
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(referenced_in.iid)
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
end
it 'creates expected note' do
@@ -87,7 +95,7 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::CrossReferenced, :clean_g
end
context 'when referenced in out of project issue/pull_request' do
- it 'creates expected note' do
+ it 'does not create expected note' do
importer.execute(issue_event)
expect(issue.notes.count).to eq 0
diff --git a/spec/lib/gitlab/github_import/importer/events/renamed_spec.rb b/spec/lib/gitlab/github_import/importer/events/renamed_spec.rb
index a8c3fbcb05d..316ea798965 100644
--- a/spec/lib/gitlab/github_import/importer/events/renamed_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/events/renamed_spec.rb
@@ -3,23 +3,24 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::Events::Renamed do
- subject(:importer) { described_class.new(project, user.id) }
+ subject(:importer) { described_class.new(project, client) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:issue) { create(:issue, project: project) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue_event) do
Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(
'id' => 6501124486,
- 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'actor' => { 'id' => user.id, 'login' => user.username },
'event' => 'renamed',
'commit_id' => nil,
'created_at' => '2022-04-26 18:30:53 UTC',
'old_title' => 'old title',
'new_title' => 'new title',
- 'issue_db_id' => issue.id
+ 'issue' => { 'number' => issue.iid }
)
end
@@ -45,6 +46,15 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Renamed do
end
describe '#execute' do
+ before do
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
+ end
+
it 'creates expected note' do
expect { importer.execute(issue_event) }.to change { issue.notes.count }
.from(0).to(1)
diff --git a/spec/lib/gitlab/github_import/importer/events/reopened_spec.rb b/spec/lib/gitlab/github_import/importer/events/reopened_spec.rb
index 81653b0ecdc..2461dbb9701 100644
--- a/spec/lib/gitlab/github_import/importer/events/reopened_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/events/reopened_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_failures do
- subject(:importer) { described_class.new(project, user.id) }
+ subject(:importer) { described_class.new(project, client) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
+ let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:issue) { create(:issue, project: project) }
let(:issue_event) do
@@ -15,10 +16,10 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
'id' => 6501124486,
'node_id' => 'CE_lADOHK9fA85If7x0zwAAAAGDf0mG',
'url' => 'https://api.github.com/repos/elhowm/test-import/issues/events/6501124486',
- 'actor' => { 'id' => 4, 'login' => 'alice' },
+ 'actor' => { 'id' => user.id, 'login' => user.username },
'event' => 'reopened',
'created_at' => '2022-04-26 18:30:53 UTC',
- 'issue_db_id' => issue.id
+ 'issue' => { 'number' => issue.iid }
)
end
@@ -42,6 +43,15 @@ RSpec.describe Gitlab::GithubImport::Importer::Events::Reopened, :aggregate_fail
}.stringify_keys
end
+ before do
+ allow_next_instance_of(Gitlab::GithubImport::IssuableFinder) do |finder|
+ allow(finder).to receive(:database_id).and_return(issue.id)
+ end
+ allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
+ allow(finder).to receive(:find).with(user.id, user.username).and_return(user.id)
+ end
+ end
+
it 'creates expected event and state event' do
importer.execute(issue_event)
diff --git a/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb
index da32a3b3766..33d5fbf13a0 100644
--- a/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_event_importer_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
specific_importer = double(importer_class.name) # rubocop:disable RSpec/VerifiedDoubles
expect(importer_class)
- .to receive(:new).with(project, user.id)
+ .to receive(:new).with(project, client)
.and_return(specific_importer)
expect(specific_importer).to receive(:execute).with(issue_event)
@@ -43,12 +43,6 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
describe '#execute' do
before do
- allow_next_instance_of(Gitlab::GithubImport::UserFinder) do |finder|
- allow(finder).to receive(:author_id_for)
- .with(issue_event, author_key: :actor)
- .and_return(user.id, true)
- end
-
issue_event.attributes[:issue_db_id] = issue.id
end
@@ -87,6 +81,20 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
Gitlab::GithubImport::Importer::Events::Renamed
end
+ context "when it's milestoned issue event" do
+ let(:event_name) { 'milestoned' }
+
+ it_behaves_like 'triggers specific event importer',
+ Gitlab::GithubImport::Importer::Events::ChangedMilestone
+ end
+
+ context "when it's demilestoned issue event" do
+ let(:event_name) { 'demilestoned' }
+
+ it_behaves_like 'triggers specific event importer',
+ Gitlab::GithubImport::Importer::Events::ChangedMilestone
+ end
+
context "when it's cross-referenced issue event" do
let(:event_name) { 'cross-referenced' }
@@ -94,6 +102,20 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueEventImporter, :clean_gitlab
Gitlab::GithubImport::Importer::Events::CrossReferenced
end
+ context "when it's assigned issue event" do
+ let(:event_name) { 'assigned' }
+
+ it_behaves_like 'triggers specific event importer',
+ Gitlab::GithubImport::Importer::Events::ChangedAssignee
+ end
+
+ context "when it's unassigned issue event" do
+ let(:event_name) { 'unassigned' }
+
+ it_behaves_like 'triggers specific event importer',
+ Gitlab::GithubImport::Importer::Events::ChangedAssignee
+ end
+
context "when it's unknown issue event" do
let(:event_name) { 'fake' }
diff --git a/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb
new file mode 100644
index 00000000000..8d4c1b01e50
--- /dev/null
+++ b/spec/lib/gitlab/github_import/importer/issue_events_importer_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GithubImport::Importer::IssueEventsImporter do
+ subject(:importer) { described_class.new(project, client, parallel: parallel) }
+
+ let(:project) { instance_double(Project, id: 4, import_source: 'foo/bar') }
+ let(:client) { instance_double(Gitlab::GithubImport::Client) }
+
+ let(:parallel) { true }
+ let(:issue_event) do
+ struct = Struct.new(
+ :id, :node_id, :url, :actor, :event, :commit_id, :commit_url, :label, :rename, :milestone,
+ :source, :assignee, :assigner, :issue, :created_at, :performed_via_github_app,
+ keyword_init: true
+ )
+ struct.new(id: rand(10), event: 'closed', created_at: '2022-04-26 18:30:53 UTC')
+ end
+
+ describe '#parallel?' do
+ context 'when running in parallel mode' do
+ it { expect(importer).to be_parallel }
+ end
+
+ context 'when running in sequential mode' do
+ let(:parallel) { false }
+
+ it { expect(importer).not_to be_parallel }
+ end
+ end
+
+ describe '#execute' do
+ context 'when running in parallel mode' do
+ it 'imports events in parallel' do
+ expect(importer).to receive(:parallel_import)
+
+ importer.execute
+ end
+ end
+
+ context 'when running in sequential mode' do
+ let(:parallel) { false }
+
+ it 'imports notes in sequence' do
+ expect(importer).to receive(:sequential_import)
+
+ importer.execute
+ end
+ end
+ end
+
+ describe '#sequential_import' do
+ let(:parallel) { false }
+
+ it 'imports each event in sequence' do
+ event_importer = instance_double(Gitlab::GithubImport::Importer::IssueEventImporter)
+
+ allow(importer).to receive(:each_object_to_import).and_yield(issue_event)
+
+ expect(Gitlab::GithubImport::Importer::IssueEventImporter)
+ .to receive(:new)
+ .with(
+ an_instance_of(Gitlab::GithubImport::Representation::IssueEvent),
+ project,
+ client
+ )
+ .and_return(event_importer)
+
+ expect(event_importer).to receive(:execute)
+
+ importer.sequential_import
+ end
+ end
+
+ describe '#parallel_import' do
+ it 'imports each note in parallel' do
+ allow(importer).to receive(:each_object_to_import).and_yield(issue_event)
+
+ expect(Gitlab::GithubImport::ImportIssueEventWorker).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
+
+ expect(waiter).to be_an_instance_of(Gitlab::JobWaiter)
+ expect(waiter.jobs_remaining).to eq(1)
+ end
+ end
+
+ describe '#importer_class' do
+ it { expect(importer.importer_class).to eq Gitlab::GithubImport::Importer::IssueEventImporter }
+ end
+
+ describe '#representation_class' do
+ it { expect(importer.representation_class).to eq Gitlab::GithubImport::Representation::IssueEvent }
+ end
+
+ describe '#sidekiq_worker_class' do
+ it { expect(importer.sidekiq_worker_class).to eq Gitlab::GithubImport::ImportIssueEventWorker }
+ end
+
+ describe '#object_type' do
+ it { expect(importer.object_type).to eq :issue_event }
+ end
+
+ describe '#collection_method' do
+ it { expect(importer.collection_method).to eq :repository_issue_events }
+ end
+
+ describe '#id_for_already_imported_cache' do
+ it 'returns the ID of the given note' do
+ expect(importer.id_for_already_imported_cache(issue_event)).to eq(issue_event.id)
+ end
+ end
+
+ describe '#collection_options' do
+ it { expect(importer.collection_options).to eq({}) }
+ end
+end
diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
index 570d26cdf2d..1692aac49f2 100644
--- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cache do
+ let_it_be(:work_item_type_id) { ::WorkItems::Type.default_issue_type.id }
+
let(:project) { create(:project) }
let(:client) { double(:client) }
let(:user) { create(:user) }
@@ -25,7 +27,8 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
author: Gitlab::GithubImport::Representation::User.new(id: 4, login: 'alice'),
created_at: created_at,
updated_at: updated_at,
- pull_request: false
+ pull_request: false,
+ work_item_type_id: work_item_type_id
)
end
@@ -116,6 +119,17 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
.and_return(milestone.id)
end
+ it 'creates issues with a work item type id' do
+ allow(importer.user_finder)
+ .to receive(:author_id_for)
+ .with(issue)
+ .and_return([user.id, true])
+
+ issue_id = importer.create_issue
+
+ expect(Issue.find(issue_id).work_item_type_id).to eq(work_item_type_id)
+ end
+
context 'when the issue author could be found' do
it 'creates the issue with the found author as the issue author' do
allow(importer.user_finder)
@@ -136,7 +150,8 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
milestone_id: milestone.id,
state_id: 1,
created_at: created_at,
- updated_at: updated_at
+ updated_at: updated_at,
+ work_item_type_id: work_item_type_id
},
project.issues
)
@@ -166,7 +181,8 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
milestone_id: milestone.id,
state_id: 1,
created_at: created_at,
- updated_at: updated_at
+ updated_at: updated_at,
+ work_item_type_id: work_item_type_id
},
project.issues
)
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 6dfd4424342..251829b83a0 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
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LfsObjectsImporter do
let(:lfs_attributes) do
{
- oid: 'oid',
+ oid: 'a' * 64,
size: 1,
link: 'http://www.gitlab.com/lfs_objects/oid'
}
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 c1b0f4df29a..c5846fa7a87 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
@@ -149,7 +149,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
expect(importer)
.to receive(:update_repository)
- importer.each_object_to_import { }
+ importer.each_object_to_import {}
end
end
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 087faeffe02..bb1ee79ad93 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
@@ -53,7 +53,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_db_id, keyword_init: true)
+ 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')
end
@@ -81,7 +81,7 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter
counter = 0
subject.each_object_to_import do |object|
expect(object).to eq issue_event
- expect(issue_event.issue_db_id).to eq issue.id
+ expect(issue_event.issue['number']).to eq issue.iid
counter += 1
end
expect(counter).to eq 1
diff --git a/spec/lib/gitlab/github_import/issuable_finder_spec.rb b/spec/lib/gitlab/github_import/issuable_finder_spec.rb
index 3afd006109b..d550f15e8c5 100644
--- a/spec/lib/gitlab/github_import/issuable_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/issuable_finder_spec.rb
@@ -5,7 +5,7 @@ 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, iid: 1)
+ double(:issue, issuable_type: MergeRequest, issuable_id: 1)
end
let(:finder) { described_class.new(project, issue) }
diff --git a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
index 999f8ffb21e..738e7c88d7d 100644
--- a/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_scheduling_spec.rb
@@ -243,7 +243,7 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
expect(repr_class)
.to receive(:from_api_response)
- .with(object)
+ .with(object, {})
.and_return(repr_instance)
expect(importer)
@@ -281,7 +281,7 @@ RSpec.describe Gitlab::GithubImport::ParallelScheduling do
allow(repr_class)
.to receive(:from_api_response)
- .with(object)
+ .with(object, {})
.and_return({ title: 'Foo' })
end
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 23da8276f64..d3a98035e73 100644
--- a/spec/lib/gitlab/github_import/representation/issue_event_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/issue_event_spec.rb
@@ -25,8 +25,8 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
expect(issue_event.source).to eq({ type: 'issue', id: 123456 })
end
- it 'includes the issue_db_id' do
- expect(issue_event.issue_db_id).to eq(100500)
+ it 'includes the issue data' do
+ expect(issue_event.issue).to eq({ number: 2, pull_request: pull_request })
end
context 'when actor data present' do
@@ -77,11 +77,66 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
end
end
+ context 'when milestone data is present' do
+ it 'includes the milestone_title' do
+ expect(issue_event.milestone_title).to eq('milestone title')
+ end
+ end
+
+ context 'when milestone data is empty' do
+ let(:with_milestone) { false }
+
+ it 'does not return such info' do
+ expect(issue_event.milestone_title).to eq nil
+ end
+ end
+
+ context 'when assignee and assigner data is present' do
+ it 'includes assignee and assigner details' do
+ expect(issue_event.assignee)
+ .to be_an_instance_of(Gitlab::GithubImport::Representation::User)
+ expect(issue_event.assignee.id).to eq(5)
+ expect(issue_event.assignee.login).to eq('tom')
+
+ expect(issue_event.assigner)
+ .to be_an_instance_of(Gitlab::GithubImport::Representation::User)
+ expect(issue_event.assigner.id).to eq(6)
+ expect(issue_event.assigner.login).to eq('jerry')
+ end
+ end
+
+ context 'when assignee and assigner data is empty' do
+ let(:with_assignee) { false }
+
+ it 'does not return such info' do
+ expect(issue_event.assignee).to eq nil
+ expect(issue_event.assigner).to eq nil
+ end
+ end
+
it 'includes the created timestamp' do
expect(issue_event.created_at).to eq('2022-04-26 18:30:53 UTC')
end
end
+ describe '#issuable_id' do
+ it 'returns issuable_id' do
+ expect(issue_event.issuable_id).to eq(2)
+ end
+ end
+
+ describe '#issuable_type' do
+ context 'when event related to issue' do
+ it { expect(issue_event.issuable_type).to eq('Issue') }
+ end
+
+ context 'when event related to pull request' do
+ let(:pull_request) { { url: FFaker::Internet.http_url } }
+
+ it { expect(issue_event.issuable_type).to eq('MergeRequest') }
+ end
+ end
+
describe '#github_identifiers' do
it 'returns a hash with needed identifiers' do
expect(issue_event.github_identifiers).to eq({ id: 6501124486 })
@@ -92,8 +147,8 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
describe '.from_api_response' do
let(:response) do
event_resource = Struct.new(
- :id, :node_id, :url, :actor, :event, :commit_id, :commit_url, :label,
- :rename, :issue_db_id, :created_at, :performed_via_github_app, :source,
+ :id, :node_id, :url, :actor, :event, :commit_id, :commit_url, :label, :rename, :milestone,
+ :source, :assignee, :assigner, :issue, :created_at, :performed_via_github_app,
keyword_init: true
)
user_resource = Struct.new(:id, :login, keyword_init: true)
@@ -106,10 +161,13 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
commit_id: '570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
commit_url: 'https://api.github.com/repos/octocat/Hello-World/commits'\
'/570e7b2abdd848b95f2f578043fc23bd6f6fd24d',
+ label: with_label ? { name: 'label title' } : nil,
rename: with_rename ? { from: 'old title', to: 'new title' } : nil,
+ milestone: with_milestone ? { title: 'milestone title' } : nil,
source: { type: 'issue', id: 123456 },
- issue_db_id: 100500,
- label: with_label ? { name: 'label title' } : nil,
+ assignee: with_assignee ? user_resource.new(id: 5, login: 'tom') : nil,
+ assigner: with_assignee ? user_resource.new(id: 6, login: 'jerry') : nil,
+ issue: { 'number' => 2, 'pull_request' => pull_request },
created_at: '2022-04-26 18:30:53 UTC',
performed_via_github_app: nil
)
@@ -118,6 +176,9 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
let(:with_actor) { true }
let(:with_label) { true }
let(:with_rename) { true }
+ let(:with_milestone) { true }
+ let(:with_assignee) { true }
+ let(:pull_request) { nil }
it_behaves_like 'an IssueEvent' do
let(:issue_event) { described_class.from_api_response(response) }
@@ -139,8 +200,11 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
'label_title' => (with_label ? 'label title' : nil),
'old_title' => with_rename ? 'old title' : nil,
'new_title' => with_rename ? 'new title' : nil,
+ 'milestone_title' => (with_milestone ? 'milestone title' : nil),
'source' => { 'type' => 'issue', 'id' => 123456 },
- "issue_db_id" => 100500,
+ 'assignee' => (with_assignee ? { 'id' => 5, 'login' => 'tom' } : nil),
+ 'assigner' => (with_assignee ? { 'id' => 6, 'login' => 'jerry' } : nil),
+ 'issue' => { 'number' => 2, 'pull_request' => pull_request },
'created_at' => '2022-04-26 18:30:53 UTC',
'performed_via_github_app' => nil
}
@@ -149,6 +213,9 @@ RSpec.describe Gitlab::GithubImport::Representation::IssueEvent do
let(:with_actor) { true }
let(:with_label) { true }
let(:with_rename) { true }
+ let(:with_milestone) { true }
+ let(:with_assignee) { true }
+ let(:pull_request) { nil }
let(:issue_event) { described_class.from_json_hash(hash) }
end
diff --git a/spec/lib/gitlab/github_import/representation/issue_spec.rb b/spec/lib/gitlab/github_import/representation/issue_spec.rb
index f3052efea70..5898518343a 100644
--- a/spec/lib/gitlab/github_import/representation/issue_spec.rb
+++ b/spec/lib/gitlab/github_import/representation/issue_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Representation::Issue do
+ let_it_be(:work_item_type_id) { ::WorkItems::Type.default_issue_type.id }
+
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
@@ -60,6 +62,10 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
expect(issue.updated_at).to eq(updated_at)
end
+ it 'includes the work_item_type_id' do
+ expect(issue.work_item_type_id).to eq(work_item_type_id)
+ end
+
it 'is not a pull request' do
expect(issue.pull_request?).to eq(false)
end
@@ -84,8 +90,10 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
)
end
+ let(:additional_data) { { work_item_type_id: work_item_type_id } }
+
it_behaves_like 'an Issue' do
- let(:issue) { described_class.from_api_response(response) }
+ let(:issue) { described_class.from_api_response(response, additional_data) }
end
it 'does not set the user if the response did not include a user' do
@@ -93,7 +101,7 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
.to receive(:user)
.and_return(nil)
- issue = described_class.from_api_response(response)
+ issue = described_class.from_api_response(response, additional_data)
expect(issue.author).to be_nil
end
@@ -113,7 +121,8 @@ RSpec.describe Gitlab::GithubImport::Representation::Issue do
'author' => { 'id' => 4, 'login' => 'alice' },
'created_at' => created_at.to_s,
'updated_at' => updated_at.to_s,
- 'pull_request' => false
+ 'pull_request' => false,
+ 'work_item_type_id' => work_item_type_id
}
end
diff --git a/spec/lib/gitlab/github_import/user_finder_spec.rb b/spec/lib/gitlab/github_import/user_finder_spec.rb
index 8eb6eedd72d..d85e298785c 100644
--- a/spec/lib/gitlab/github_import/user_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/user_finder_spec.rb
@@ -15,32 +15,64 @@ RSpec.describe Gitlab::GithubImport::UserFinder, :clean_gitlab_redis_cache do
let(:finder) { described_class.new(project, client) }
describe '#author_id_for' 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)
+ 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)
- expect(finder).to receive(:user_id_for).with(user).and_return(42)
+ expect(finder).to receive(:user_id_for).with(user).and_return(42)
- expect(finder.author_id_for(note)).to eq([42, true])
- end
+ expect(finder.author_id_for(note)).to eq([42, true])
+ 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)
+ 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)
- expect(finder).to receive(:user_id_for).with(user).and_return(nil)
+ expect(finder).to receive(:user_id_for).with(user).and_return(nil)
- expect(finder.author_id_for(note)).to eq([project.creator_id, false])
- end
+ expect(finder.author_id_for(note)).to eq([project.creator_id, false])
+ end
+
+ it 'returns the ID of the ghost user when the object has no user' do
+ note = double(:note, author: nil)
- it 'returns the ID of the ghost user when the object has no user' do
- note = double(:note, author: nil)
+ expect(finder.author_id_for(note)).to eq([User.ghost.id, true])
+ end
- expect(finder.author_id_for(note)).to eq([User.ghost.id, true])
+ it 'returns the ID of the ghost user when the given object is nil' do
+ expect(finder.author_id_for(nil)).to eq([User.ghost.id, true])
+ end
end
- it 'returns the ID of the ghost user when the given object is nil' do
- expect(finder.author_id_for(nil)).to eq([User.ghost.id, true])
+ context 'with a non-default author_key' do
+ let(:user) { double(:user, id: 4, login: 'kittens') }
+
+ shared_examples 'user ID finder' do |author_key|
+ it 'returns the user ID for an object' do
+ expect(finder).to receive(:user_id_for).with(user).and_return(42)
+
+ expect(finder.author_id_for(issue_event, author_key: author_key)).to eq([42, true])
+ end
+ end
+
+ context 'when the author_key parameter is :actor' do
+ let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', 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) }
+
+ it_behaves_like 'user ID finder', :assignee
+ end
+
+ context 'when the author_key parameter is :assigner' do
+ let(:issue_event) { double('Gitlab::GithubImport::Representation::IssueEvent', assigner: user) }
+
+ it_behaves_like 'user ID finder', :assigner
+ end
end
end
diff --git a/spec/lib/gitlab/global_id/deprecations_spec.rb b/spec/lib/gitlab/global_id/deprecations_spec.rb
index 22a4766c0a0..3824473c95b 100644
--- a/spec/lib/gitlab/global_id/deprecations_spec.rb
+++ b/spec/lib/gitlab/global_id/deprecations_spec.rb
@@ -1,12 +1,21 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'graphql'
+require_relative '../../../../app/graphql/types/base_scalar'
+require_relative '../../../../app/graphql/types/global_id_type'
+require_relative '../../../support/helpers/global_id_deprecation_helpers'
RSpec.describe Gitlab::GlobalId::Deprecations do
include GlobalIDDeprecationHelpers
- let_it_be(:deprecation_1) { described_class::Deprecation.new(old_model_name: 'Foo::Model', new_model_name: 'Bar', milestone: '9.0') }
- let_it_be(:deprecation_2) { described_class::Deprecation.new(old_model_name: 'Baz', new_model_name: 'Qux::Model', milestone: '10.0') }
+ let(:deprecation_1) do
+ described_class::NameDeprecation.new(old_name: 'Foo::Model', new_name: 'Bar', milestone: '9.0')
+ end
+
+ let(:deprecation_2) do
+ described_class::NameDeprecation.new(old_name: 'Baz', new_name: 'Qux::Model', milestone: '10.0')
+ end
before do
stub_global_id_deprecations(deprecation_1, deprecation_2)
diff --git a/spec/lib/gitlab/gpg_spec.rb b/spec/lib/gitlab/gpg_spec.rb
index 72c6c8efb5e..e64555f1079 100644
--- a/spec/lib/gitlab/gpg_spec.rb
+++ b/spec/lib/gitlab/gpg_spec.rb
@@ -218,7 +218,7 @@ RSpec.describe Gitlab::Gpg do
expect(Retriable).to receive(:sleep).at_least(:twice)
expect(FileUtils).to receive(:remove_entry).with(tmp_dir).at_least(:twice).and_raise('Deletion failed')
- expect { described_class.using_tmp_keychain { } }.to raise_error(described_class::CleanupError)
+ expect { described_class.using_tmp_keychain {} }.to raise_error(described_class::CleanupError)
end
it 'does not attempt multiple times when the deletion succeeds' do
@@ -226,7 +226,7 @@ RSpec.describe Gitlab::Gpg do
expect(FileUtils).to receive(:remove_entry).with(tmp_dir).once.and_raise('Deletion failed')
expect(FileUtils).to receive(:remove_entry).with(tmp_dir).and_call_original
- expect { described_class.using_tmp_keychain { } }.not_to raise_error
+ expect { described_class.using_tmp_keychain {} }.not_to raise_error
expect(File.exist?(tmp_dir)).to be false
end
diff --git a/spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb
new file mode 100644
index 00000000000..d2022a28a90
--- /dev/null
+++ b/spec/lib/gitlab/grape_logging/loggers/token_logger_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GrapeLogging::Loggers::TokenLogger do
+ subject { described_class.new }
+
+ describe ".parameters" do
+ let(:token_id) { 1 }
+ let(:token_type) { "PersonalAccessToken" }
+
+ describe 'when no token information is available' do
+ let(:mock_request) { instance_double(ActionDispatch::Request, 'env', env: {}) }
+
+ it 'returns an empty hash' do
+ expect(subject.parameters(mock_request, nil)).to eq({})
+ end
+ end
+
+ describe 'when token information is available' do
+ let(:mock_request) do
+ instance_double(ActionDispatch::Request, 'env',
+ env: {
+ 'gitlab.api.token' => { 'token_id': token_id, 'token_type': token_type }
+ }
+ )
+ end
+
+ it 'adds the token information to log parameters' do
+ expect(subject.parameters(mock_request, nil)).to eq( { 'token_id': 1, 'token_type': "PersonalAccessToken" })
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/deprecation_spec.rb b/spec/lib/gitlab/graphql/deprecation_spec.rb
index 2931e28a6ee..c9b47219198 100644
--- a/spec/lib/gitlab/graphql/deprecation_spec.rb
+++ b/spec/lib/gitlab/graphql/deprecation_spec.rb
@@ -6,30 +6,57 @@ require 'active_model'
RSpec.describe ::Gitlab::Graphql::Deprecation do
let(:options) { {} }
- subject(:deprecation) { described_class.parse(options) }
+ subject(:deprecation) { described_class.new(**options) }
describe '.parse' do
- context 'with nil' do
- let(:options) { nil }
+ subject(:parsed_deprecation) { described_class.parse(**options) }
- it 'parses to nil' do
- expect(deprecation).to be_nil
+ context 'with no arguments' do
+ it 'returns nil' do
+ expect(parsed_deprecation).to be_nil
end
end
- context 'with empty options' do
- let(:options) { {} }
+ context 'with an incomplete `deprecated` argument' do
+ let(:options) { { deprecated: {} } }
- it 'parses to an empty deprecation' do
- expect(deprecation).to eq(described_class.new)
+ it 'parses as an invalid deprecation' do
+ expect(parsed_deprecation).not_to be_valid
+ expect(parsed_deprecation).to eq(described_class.new)
end
end
- context 'with defined options' do
- let(:options) { { reason: :renamed, milestone: '10.10' } }
+ context 'with a `deprecated` argument' do
+ let(:options) { { deprecated: { reason: :renamed, milestone: '10.10' } } }
+
+ it 'parses as a deprecation' do
+ expect(parsed_deprecation).to be_valid
+ expect(parsed_deprecation).to eq(
+ described_class.new(reason: 'This was renamed', milestone: '10.10')
+ )
+ end
+ end
+
+ context 'with an `alpha` argument' do
+ let(:options) { { alpha: { milestone: '10.10' } } }
+
+ it 'parses as an alpha' do
+ expect(parsed_deprecation).to be_valid
+ expect(parsed_deprecation).to eq(
+ described_class.new(reason: :alpha, milestone: '10.10')
+ )
+ end
+ end
+
+ context 'with both `deprecated` and `alpha` arguments' do
+ let(:options) do
+ { alpha: { milestone: '10.10' }, deprecated: { reason: :renamed, milestone: '10.10' } }
+ end
- it 'assigns the properties' do
- expect(deprecation).to eq(described_class.new(reason: 'This was renamed', milestone: '10.10'))
+ it 'raises an error' do
+ expect { parsed_deprecation }.to raise_error(ArgumentError,
+ '`alpha` and `deprecated` arguments cannot be passed at the same time'
+ )
end
end
end
@@ -210,4 +237,20 @@ RSpec.describe ::Gitlab::Graphql::Deprecation do
end
end
end
+
+ describe '#alpha?' do
+ let(:options) { { milestone: '10.10', reason: reason } }
+
+ context 'when `reason` is `:alpha`' do
+ let(:reason) { described_class::REASON_ALPHA }
+
+ it { is_expected.to be_alpha }
+ end
+
+ context 'when `reason` is not `:alpha`' do
+ let(:reason) { described_class::REASON_RENAMED }
+
+ it { is_expected.not_to be_alpha }
+ end
+ end
end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb
deleted file mode 100644
index eecdaa3409f..00000000000
--- a/spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Pagination::Keyset::Conditions::NotNullCondition do
- describe '#build' do
- let(:operators) { ['>', '>'] }
- let(:before_or_after) { :after }
- let(:condition) { described_class.new(arel_table, order_list, values, operators, before_or_after) }
-
- context 'when there is only one ordering field' do
- let(:arel_table) { Issue.arel_table }
- let(:order_list) { [double(named_function: nil, attribute_name: 'id')] }
- let(:values) { [500] }
- let(:operators) { ['>'] }
-
- it 'generates a single condition sql' do
- expected_sql = <<~SQL
- ("issues"."id" > 500)
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when ordering by a column attribute' do
- let(:arel_table) { Issue.arel_table }
- let(:order_list) { [double(named_function: nil, attribute_name: 'relative_position'), double(named_function: nil, attribute_name: 'id')] }
- let(:values) { [1500, 500] }
-
- shared_examples ':after condition' do
- it 'generates :after sql' do
- expected_sql = <<~SQL
- ("issues"."relative_position" > 1500)
- OR (
- "issues"."relative_position" = 1500
- AND
- "issues"."id" > 500
- )
- OR ("issues"."relative_position" IS NULL)
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :after' do
- it_behaves_like ':after condition'
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates :before sql' do
- expected_sql = <<~SQL
- ("issues"."relative_position" > 1500)
- OR (
- "issues"."relative_position" = 1500
- AND
- "issues"."id" > 500
- )
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :foo' do
- let(:before_or_after) { :foo }
-
- it_behaves_like ':after condition'
- end
- end
-
- context 'when ordering by LOWER' do
- let(:arel_table) { Project.arel_table }
- let(:relation) { Project.order(arel_table['name'].lower.asc).order(:id) }
- let(:order_list) { Gitlab::Graphql::Pagination::Keyset::OrderInfo.build_order_list(relation) }
- let(:values) { ['Test', 500] }
-
- context 'when :after' do
- it 'generates :after sql' do
- expected_sql = <<~SQL
- (LOWER("projects"."name") > 'test')
- OR (
- LOWER("projects"."name") = 'test'
- AND
- "projects"."id" > 500
- )
- OR (LOWER("projects"."name") IS NULL)
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates :before sql' do
- expected_sql = <<~SQL
- (LOWER("projects"."name") > 'test')
- OR (
- LOWER("projects"."name") = 'test'
- AND
- "projects"."id" > 500
- )
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_spec.rb
deleted file mode 100644
index 582f96299ec..00000000000
--- a/spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_spec.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Pagination::Keyset::Conditions::NullCondition do
- describe '#build' do
- let(:values) { [nil, 500] }
- let(:operators) { [nil, '>'] }
- let(:before_or_after) { :after }
- let(:condition) { described_class.new(arel_table, order_list, values, operators, before_or_after) }
-
- context 'when ordering by a column attribute' do
- let(:arel_table) { Issue.arel_table }
- let(:order_list) { [double(named_function: nil, attribute_name: 'relative_position'), double(named_function: nil, attribute_name: 'id')] }
-
- shared_examples ':after condition' do
- it 'generates sql' do
- expected_sql = <<~SQL
- (
- "issues"."relative_position" IS NULL
- AND
- "issues"."id" > 500
- )
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :after' do
- it_behaves_like ':after condition'
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates :before sql' do
- expected_sql = <<~SQL
- (
- "issues"."relative_position" IS NULL
- AND
- "issues"."id" > 500
- )
- OR ("issues"."relative_position" IS NOT NULL)
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :foo' do
- let(:before_or_after) { :foo }
-
- it_behaves_like ':after condition'
- end
- end
-
- context 'when ordering by LOWER' do
- let(:arel_table) { Project.arel_table }
- let(:relation) { Project.order(arel_table['name'].lower.asc).order(:id) }
- let(:order_list) { Gitlab::Graphql::Pagination::Keyset::OrderInfo.build_order_list(relation) }
-
- context 'when :after' do
- it 'generates sql' do
- expected_sql = <<~SQL
- (
- LOWER("projects"."name") IS NULL
- AND
- "projects"."id" > 500
- )
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates :before sql' do
- expected_sql = <<~SQL
- (
- LOWER("projects"."name") IS NULL
- AND
- "projects"."id" > 500
- )
- OR (LOWER("projects"."name") IS NOT NULL)
- SQL
-
- expect(condition.build.squish).to eq expected_sql.squish
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
deleted file mode 100644
index 8a2b5ae0d38..00000000000
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
+++ /dev/null
@@ -1,415 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
- include GraphqlHelpers
-
- # https://gitlab.com/gitlab-org/gitlab/-/issues/334973
- # The spec will be merged with connection_spec.rb in the future.
- let(:nodes) { Project.all.order(id: :asc) }
- let(:arguments) { {} }
- let(:context) { GraphQL::Query::Context.new(query: query_double, values: nil, object: nil) }
-
- let_it_be(:column_order_id) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].asc) }
- let_it_be(:column_order_id_desc) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].desc) }
- let_it_be(:column_order_updated_at) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'updated_at', order_expression: Project.arel_table[:updated_at].asc) }
- let_it_be(:column_order_created_at) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'created_at', order_expression: Project.arel_table[:created_at].asc) }
- let_it_be(:column_order_last_repo) do
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'last_repository_check_at',
- column_expression: Project.arel_table[:last_repository_check_at],
- order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
- reversed_order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
- order_direction: :asc,
- nullable: :nulls_last,
- distinct: false)
- end
-
- let_it_be(:column_order_last_repo_desc) do
- Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
- attribute_name: 'last_repository_check_at',
- column_expression: Project.arel_table[:last_repository_check_at],
- order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
- reversed_order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
- order_direction: :desc,
- nullable: :nulls_last,
- distinct: false)
- end
-
- subject(:connection) do
- described_class.new(nodes, **{ context: context, max_page_size: 3 }.merge(arguments))
- end
-
- def encoded_cursor(node)
- described_class.new(nodes, context: context).cursor_for(node)
- end
-
- def decoded_cursor(cursor)
- Gitlab::Json.parse(Base64Bp.urlsafe_decode64(cursor))
- end
-
- describe "With generic keyset order support" do
- let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
-
- it_behaves_like 'a connection with collection methods'
-
- it_behaves_like 'a redactable connection' do
- let_it_be(:projects) { create_list(:project, 2) }
- let(:unwanted) { projects.second }
- end
-
- describe '#cursor_for' do
- let(:project) { create(:project) }
- let(:cursor) { connection.cursor_for(project) }
-
- it 'returns an encoded ID' do
- expect(decoded_cursor(cursor)).to eq('id' => project.id.to_s)
- end
-
- context 'when an order is specified' do
- let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
-
- it 'returns the encoded value of the order' do
- expect(decoded_cursor(cursor)).to include('id' => project.id.to_s)
- end
- end
-
- context 'when multiple orders are specified' do
- let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_updated_at, column_order_created_at, column_order_id])) }
-
- it 'returns the encoded value of the order' do
- expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
- end
- end
- end
-
- describe '#sliced_nodes' do
- let(:projects) { create_list(:project, 4) }
-
- context 'when before is passed' do
- let(:arguments) { { before: encoded_cursor(projects[1]) } }
-
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(projects.first)
- end
-
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id_desc])) }
-
- it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
- end
- end
- end
-
- context 'when after is passed' do
- let(:arguments) { { after: encoded_cursor(projects[1]) } }
-
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
- end
-
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id_desc])) }
-
- it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(projects.first)
- end
- end
- end
-
- context 'when both before and after are passed' do
- let(:arguments) do
- {
- after: encoded_cursor(projects[1]),
- before: encoded_cursor(projects[3])
- }
- end
-
- it 'returns the expected set' do
- expect(subject.sliced_nodes).to contain_exactly(projects[2])
- end
- end
-
- shared_examples 'nodes are in ascending order' do
- context 'when no cursor is passed' do
- let(:arguments) { {} }
-
- it 'returns projects in ascending order' do
- expect(subject.sliced_nodes).to eq(ascending_nodes)
- end
- end
-
- context 'when before cursor value is not NULL' do
- let(:arguments) { { before: encoded_cursor(ascending_nodes[2]) } }
-
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes.first(2))
- end
- end
-
- context 'when after cursor value is not NULL' do
- let(:arguments) { { after: encoded_cursor(ascending_nodes[1]) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes.last(3))
- end
- end
-
- context 'when before and after cursor' do
- let(:arguments) { { before: encoded_cursor(ascending_nodes.last), after: encoded_cursor(ascending_nodes.first) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes[1..3])
- end
- end
- end
-
- shared_examples 'nodes are in descending order' do
- context 'when no cursor is passed' do
- let(:arguments) { {} }
-
- it 'only returns projects in descending order' do
- expect(subject.sliced_nodes).to eq(descending_nodes)
- end
- end
-
- context 'when before cursor value is not NULL' do
- let(:arguments) { { before: encoded_cursor(descending_nodes[2]) } }
-
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes.first(2))
- end
- end
-
- context 'when after cursor value is not NULL' do
- let(:arguments) { { after: encoded_cursor(descending_nodes[1]) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes.last(3))
- end
- end
-
- context 'when before and after cursor' do
- let(:arguments) { { before: encoded_cursor(descending_nodes.last), after: encoded_cursor(descending_nodes.first) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes[1..3])
- end
- end
- end
-
- context 'when multiple orders with nil values are defined' do
- let_it_be(:project1) { create(:project, last_repository_check_at: 10.days.ago) } # Asc: project5 Desc: project3
- let_it_be(:project2) { create(:project, last_repository_check_at: nil) } # Asc: project1 Desc: project1
- let_it_be(:project3) { create(:project, last_repository_check_at: 5.days.ago) } # Asc: project3 Desc: project5
- let_it_be(:project4) { create(:project, last_repository_check_at: nil) } # Asc: project2 Desc: project2
- let_it_be(:project5) { create(:project, last_repository_check_at: 20.days.ago) } # Asc: project4 Desc: project4
-
- context 'when ascending' do
- let_it_be(:order) { Gitlab::Pagination::Keyset::Order.build([column_order_last_repo, column_order_id]) }
- let_it_be(:nodes) { Project.order(order) }
- let_it_be(:ascending_nodes) { [project5, project1, project3, project2, project4] }
-
- it_behaves_like 'nodes are in ascending order'
-
- context 'when before cursor value is NULL' do
- let(:arguments) { { before: encoded_cursor(project4) } }
-
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq([project5, project1, project3, project2])
- end
- end
-
- context 'when after cursor value is NULL' do
- let(:arguments) { { after: encoded_cursor(project2) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq([project4])
- end
- end
- end
-
- context 'when descending' do
- let_it_be(:order) { Gitlab::Pagination::Keyset::Order.build([column_order_last_repo_desc, column_order_id]) }
- let_it_be(:nodes) { Project.order(order) }
- let_it_be(:descending_nodes) { [project3, project1, project5, project2, project4] }
-
- it_behaves_like 'nodes are in descending order'
-
- context 'when before cursor value is NULL' do
- let(:arguments) { { before: encoded_cursor(project4) } }
-
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq([project3, project1, project5, project2])
- end
- end
-
- context 'when after cursor value is NULL' do
- let(:arguments) { { after: encoded_cursor(project2) } }
-
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq([project4])
- end
- end
- end
- end
-
- context 'when ordering by similarity' do
- let_it_be(:project1) { create(:project, name: 'test') }
- let_it_be(:project2) { create(:project, name: 'testing') }
- let_it_be(:project3) { create(:project, name: 'tests') }
- let_it_be(:project4) { create(:project, name: 'testing stuff') }
- let_it_be(:project5) { create(:project, name: 'test') }
-
- let_it_be(:nodes) do
- # Note: sorted_by_similarity_desc scope internally supports the generic keyset order.
- Project.sorted_by_similarity_desc('test', include_in_select: true)
- end
-
- let_it_be(:descending_nodes) { nodes.to_a }
-
- it_behaves_like 'nodes are in descending order'
- end
-
- context 'when an invalid cursor is provided' do
- let(:arguments) { { before: Base64Bp.urlsafe_encode64('invalidcursor', padding: false) } }
-
- it 'raises an error' do
- expect { subject.sliced_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
- end
- end
- end
-
- describe '#nodes' do
- let_it_be(:all_nodes) { create_list(:project, 5) }
-
- let(:paged_nodes) { subject.nodes }
-
- it_behaves_like 'connection with paged nodes' do
- let(:paged_nodes_size) { 3 }
- end
-
- context 'when both are passed' do
- let(:arguments) { { first: 2, last: 2 } }
-
- it 'raises an error' do
- expect { paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
- end
- end
-
- context 'when primary key is not in original order' do
- let(:nodes) { Project.order(last_repository_check_at: :desc) }
-
- it 'is added to end' do
- sliced = subject.sliced_nodes
-
- order_sql = sliced.order_values.last.to_sql
-
- expect(order_sql).to end_with(Project.arel_table[:id].desc.to_sql)
- end
- end
-
- context 'when there is no primary key' do
- before do
- stub_const('NoPrimaryKey', Class.new(ActiveRecord::Base))
- NoPrimaryKey.class_eval do
- self.table_name = 'no_primary_key'
- self.primary_key = nil
- end
- end
-
- let(:nodes) { NoPrimaryKey.all }
-
- it 'raises an error' do
- expect(NoPrimaryKey.primary_key).to be_nil
- expect { subject.sliced_nodes }.to raise_error(ArgumentError, 'Relation must have a primary key')
- end
- end
- end
-
- describe '#has_previous_page and #has_next_page' do
- # using a list of 5 items with a max_page of 3
- let_it_be(:project_list) { create_list(:project, 5) }
- let_it_be(:nodes) { Project.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
-
- context 'when default query' do
- let(:arguments) { {} }
-
- it 'has no previous, but a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- context 'when before is first item' do
- let(:arguments) { { before: encoded_cursor(project_list.first) } }
-
- it 'has no previous, but a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- describe 'using `before`' do
- context 'when before is the last item' do
- let(:arguments) { { before: encoded_cursor(project_list.last) } }
-
- it 'has no previous, but a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- context 'when before and last specified' do
- let(:arguments) { { before: encoded_cursor(project_list.last), last: 2 } }
-
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- context 'when before and last does request all remaining nodes' do
- let(:arguments) { { before: encoded_cursor(project_list[1]), last: 3 } }
-
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- expect(subject.nodes).to eq [project_list[0]]
- end
- end
- end
-
- describe 'using `after`' do
- context 'when after is the first item' do
- let(:arguments) { { after: encoded_cursor(project_list.first) } }
-
- it 'has a previous, and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- context 'when after and first specified' do
- let(:arguments) { { after: encoded_cursor(project_list.first), first: 2 } }
-
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- context 'when before and last does request all remaining nodes' do
- let(:arguments) { { after: encoded_cursor(project_list[2]), last: 3 } }
-
- it 'has a previous but no next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_falsey
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index 6574b3e3131..b54c618d8e0 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -5,10 +5,38 @@ require 'spec_helper'
RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
include GraphqlHelpers
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/334973
+ # The spec will be merged with connection_spec.rb in the future.
let(:nodes) { Project.all.order(id: :asc) }
let(:arguments) { {} }
let(:context) { GraphQL::Query::Context.new(query: query_double, values: nil, object: nil) }
+ let_it_be(:column_order_id) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].asc) }
+ let_it_be(:column_order_id_desc) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].desc) }
+ let_it_be(:column_order_updated_at) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'updated_at', order_expression: Project.arel_table[:updated_at].asc) }
+ let_it_be(:column_order_created_at) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'created_at', order_expression: Project.arel_table[:created_at].asc) }
+ let_it_be(:column_order_last_repo) do
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'last_repository_check_at',
+ column_expression: Project.arel_table[:last_repository_check_at],
+ order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
+ reversed_order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
+ order_direction: :asc,
+ nullable: :nulls_last,
+ distinct: false)
+ end
+
+ let_it_be(:column_order_last_repo_desc) do
+ Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
+ attribute_name: 'last_repository_check_at',
+ column_expression: Project.arel_table[:last_repository_check_at],
+ order_expression: Project.arel_table[:last_repository_check_at].desc.nulls_last,
+ reversed_order_expression: Project.arel_table[:last_repository_check_at].asc.nulls_last,
+ order_direction: :desc,
+ nullable: :nulls_last,
+ distinct: false)
+ end
+
subject(:connection) do
described_class.new(nodes, **{ context: context, max_page_size: 3 }.merge(arguments))
end
@@ -21,414 +49,293 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
Gitlab::Json.parse(Base64Bp.urlsafe_decode64(cursor))
end
- # see: https://gitlab.com/gitlab-org/gitlab/-/issues/297358
- context 'the relation has been preloaded' do
- let(:projects) { Project.all.preload(:issues) }
- let(:nodes) { projects.first.issues }
-
- before do
- project = create(:project)
- create_list(:issue, 3, project: project)
- end
-
- it 'is loaded' do
- expect(nodes).to be_loaded
- end
-
- it 'does not error when accessing pagination information' do
- connection.first = 2
-
- expect(connection).to have_attributes(
- has_previous_page: false,
- has_next_page: true
- )
- end
-
- it 'can generate cursors' do
- connection.send(:ordered_items) # necessary to generate the order-list
-
- expect(connection.cursor_for(nodes.first)).to be_a(String)
- end
-
- it 'can read the next page' do
- connection.send(:ordered_items) # necessary to generate the order-list
- ordered = nodes.reorder(id: :desc)
- next_page = described_class.new(nodes,
- context: context,
- max_page_size: 3,
- after: connection.cursor_for(ordered.second))
-
- expect(next_page.sliced_nodes).to contain_exactly(ordered.third)
- end
- end
-
- it_behaves_like 'a connection with collection methods'
-
- it_behaves_like 'a redactable connection' do
- let_it_be(:projects) { create_list(:project, 2) }
- let(:unwanted) { projects.second }
- end
-
- describe '#cursor_for' do
- let(:project) { create(:project) }
- let(:cursor) { connection.cursor_for(project) }
-
- it 'returns an encoded ID' do
- expect(decoded_cursor(cursor)).to eq('id' => project.id.to_s)
- end
-
- context 'when SimpleOrderBuilder cannot build keyset paginated query' do
- it 'increments the `old_keyset_pagination_usage` counter', :prometheus do
- expect(Gitlab::Pagination::Keyset::SimpleOrderBuilder).to receive(:build).and_return([false, nil])
-
- decoded_cursor(cursor)
-
- counter = Gitlab::Metrics.registry.get(:old_keyset_pagination_usage)
- expect(counter.get(model: 'Project')).to eq(1)
- end
- end
-
- context 'when an order is specified' do
- let(:nodes) { Project.order(:updated_at) }
+ describe "with generic keyset order support" do
+ let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
- it 'returns the encoded value of the order' do
- expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
- end
-
- it 'includes the :id even when not specified in the order' do
- expect(decoded_cursor(cursor)).to include('id' => project.id.to_s)
- end
- end
+ it_behaves_like 'a connection with collection methods'
- context 'when multiple orders are specified' do
- let(:nodes) { Project.order(:updated_at).order(:created_at) }
-
- it 'returns the encoded value of the order' do
- expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
- end
+ it_behaves_like 'a redactable connection' do
+ let_it_be(:projects) { create_list(:project, 2) }
+ let(:unwanted) { projects.second }
end
- context 'when multiple orders with SQL are specified' do
- let(:nodes) { Project.order(Arel.sql('projects.updated_at IS NULL')).order(:updated_at).order(:id) }
+ describe '#cursor_for' do
+ let(:project) { create(:project) }
+ let(:cursor) { connection.cursor_for(project) }
- it 'returns the encoded value of the order' do
- expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
+ it 'returns an encoded ID' do
+ expect(decoded_cursor(cursor)).to eq('id' => project.id.to_s)
end
- end
- end
- describe '#sliced_nodes' do
- let(:projects) { create_list(:project, 4) }
+ context 'when an order is specified' do
+ let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
- context 'when before is passed' do
- let(:arguments) { { before: encoded_cursor(projects[1]) } }
-
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ it 'returns the encoded value of the order' do
+ expect(decoded_cursor(cursor)).to include('id' => project.id.to_s)
+ end
end
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(id: :desc) }
+ context 'when multiple orders are specified' do
+ let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_updated_at, column_order_created_at, column_order_id])) }
- it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
+ it 'returns the encoded value of the order' do
+ expect(decoded_cursor(cursor)).to include('updated_at' => project.updated_at.to_s(:inspect))
end
end
end
- context 'when after is passed' do
- let(:arguments) { { after: encoded_cursor(projects[1]) } }
+ describe '#sliced_nodes' do
+ let(:projects) { create_list(:project, 4) }
- it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
- end
+ context 'when before is passed' do
+ let(:arguments) { { before: encoded_cursor(projects[1]) } }
- context 'when the sort order is descending' do
- let(:nodes) { Project.all.order(id: :desc) }
-
- it 'returns the correct nodes' do
+ it 'only returns the project before the selected one' do
expect(subject.sliced_nodes).to contain_exactly(projects.first)
end
- end
- end
- context 'when both before and after are passed' do
- let(:arguments) do
- {
- after: encoded_cursor(projects[1]),
- before: encoded_cursor(projects[3])
- }
- end
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id_desc])) }
- it 'returns the expected set' do
- expect(subject.sliced_nodes).to contain_exactly(projects[2])
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
+ end
+ end
end
- end
- shared_examples 'nodes are in ascending order' do
- context 'when no cursor is passed' do
- let(:arguments) { {} }
+ context 'when after is passed' do
+ let(:arguments) { { after: encoded_cursor(projects[1]) } }
- it 'returns projects in ascending order' do
- expect(subject.sliced_nodes).to eq(ascending_nodes)
+ it 'only returns the project before the selected one' do
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
end
- end
- context 'when before cursor value is not NULL' do
- let(:arguments) { { before: encoded_cursor(ascending_nodes[2]) } }
+ context 'when the sort order is descending' do
+ let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id_desc])) }
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes.first(2))
+ it 'returns the correct nodes' do
+ expect(subject.sliced_nodes).to contain_exactly(projects.first)
+ end
end
end
- context 'when after cursor value is not NULL' do
- let(:arguments) { { after: encoded_cursor(ascending_nodes[1]) } }
+ context 'when both before and after are passed' do
+ let(:arguments) do
+ {
+ after: encoded_cursor(projects[1]),
+ before: encoded_cursor(projects[3])
+ }
+ end
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes.last(3))
+ it 'returns the expected set' do
+ expect(subject.sliced_nodes).to contain_exactly(projects[2])
end
end
- context 'when before and after cursor' do
- let(:arguments) { { before: encoded_cursor(ascending_nodes.last), after: encoded_cursor(ascending_nodes.first) } }
+ shared_examples 'nodes are in ascending order' do
+ context 'when no cursor is passed' do
+ let(:arguments) { {} }
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(ascending_nodes[1..3])
+ it 'returns projects in ascending order' do
+ expect(subject.sliced_nodes).to eq(ascending_nodes)
+ end
end
- end
- end
- shared_examples 'nodes are in descending order' do
- context 'when no cursor is passed' do
- let(:arguments) { {} }
+ context 'when before cursor value is not NULL' do
+ let(:arguments) { { before: encoded_cursor(ascending_nodes[2]) } }
- it 'only returns projects in descending order' do
- expect(subject.sliced_nodes).to eq(descending_nodes)
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq(ascending_nodes.first(2))
+ end
end
- end
- context 'when before cursor value is not NULL' do
- let(:arguments) { { before: encoded_cursor(descending_nodes[2]) } }
+ context 'when after cursor value is not NULL' do
+ let(:arguments) { { after: encoded_cursor(ascending_nodes[1]) } }
- it 'returns all projects before the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes.first(2))
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq(ascending_nodes.last(3))
+ end
end
- end
- context 'when after cursor value is not NULL' do
- let(:arguments) { { after: encoded_cursor(descending_nodes[1]) } }
+ context 'when before and after cursor' do
+ let(:arguments) { { before: encoded_cursor(ascending_nodes.last), after: encoded_cursor(ascending_nodes.first) } }
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes.last(3))
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq(ascending_nodes[1..3])
+ end
end
end
- context 'when before and after cursor' do
- let(:arguments) { { before: encoded_cursor(descending_nodes.last), after: encoded_cursor(descending_nodes.first) } }
+ shared_examples 'nodes are in descending order' do
+ context 'when no cursor is passed' do
+ let(:arguments) { {} }
- it 'returns all projects after the cursor' do
- expect(subject.sliced_nodes).to eq(descending_nodes[1..3])
+ it 'only returns projects in descending order' do
+ expect(subject.sliced_nodes).to eq(descending_nodes)
+ end
end
- end
- end
- context 'when ordering uses LOWER' do
- let!(:project1) { create(:project, name: 'A') } # Asc: project1 Desc: project4
- let!(:project2) { create(:project, name: 'c') } # Asc: project5 Desc: project2
- let!(:project3) { create(:project, name: 'b') } # Asc: project3 Desc: project3
- let!(:project4) { create(:project, name: 'd') } # Asc: project2 Desc: project5
- let!(:project5) { create(:project, name: 'a') } # Asc: project4 Desc: project1
+ context 'when before cursor value is not NULL' do
+ let(:arguments) { { before: encoded_cursor(descending_nodes[2]) } }
- context 'when ascending' do
- let(:nodes) do
- Project.order(Arel::Table.new(:projects)['name'].lower.asc).order(id: :asc)
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq(descending_nodes.first(2))
+ end
end
- let(:ascending_nodes) { [project1, project5, project3, project2, project4] }
+ context 'when after cursor value is not NULL' do
+ let(:arguments) { { after: encoded_cursor(descending_nodes[1]) } }
- it_behaves_like 'nodes are in ascending order'
- end
-
- context 'when descending' do
- let(:nodes) do
- Project.order(Arel::Table.new(:projects)['name'].lower.desc).order(id: :desc)
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq(descending_nodes.last(3))
+ end
end
- let(:descending_nodes) { [project4, project2, project3, project5, project1] }
+ context 'when before and after cursor' do
+ let(:arguments) { { before: encoded_cursor(descending_nodes.last), after: encoded_cursor(descending_nodes.first) } }
- it_behaves_like 'nodes are in descending order'
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq(descending_nodes[1..3])
+ end
+ end
end
- end
- context 'NULLS order' do
- using RSpec::Parameterized::TableSyntax
+ context 'when multiple orders with nil values are defined' do
+ let_it_be(:project1) { create(:project, last_repository_check_at: 10.days.ago) } # Asc: project5 Desc: project3
+ let_it_be(:project2) { create(:project, last_repository_check_at: nil) } # Asc: project1 Desc: project1
+ let_it_be(:project3) { create(:project, last_repository_check_at: 5.days.ago) } # Asc: project3 Desc: project5
+ let_it_be(:project4) { create(:project, last_repository_check_at: nil) } # Asc: project2 Desc: project2
+ let_it_be(:project5) { create(:project, last_repository_check_at: 20.days.ago) } # Asc: project4 Desc: project4
- let_it_be(:issue1) { create(:issue, relative_position: nil) }
- let_it_be(:issue2) { create(:issue, relative_position: 100) }
- let_it_be(:issue3) { create(:issue, relative_position: 200) }
- let_it_be(:issue4) { create(:issue, relative_position: nil) }
- let_it_be(:issue5) { create(:issue, relative_position: 300) }
+ context 'when ascending' do
+ let_it_be(:order) { Gitlab::Pagination::Keyset::Order.build([column_order_last_repo, column_order_id]) }
+ let_it_be(:nodes) { Project.order(order) }
+ let_it_be(:ascending_nodes) { [project5, project1, project3, project2, project4] }
- context 'when ascending NULLS LAST (ties broken by id DESC implicitly)' do
- let(:ascending_nodes) { [issue2, issue3, issue5, issue4, issue1] }
+ it_behaves_like 'nodes are in ascending order'
- where(:nodes) do
- [
- lazy { Issue.order(Issue.arel_table[:relative_position].asc.nulls_last) }
- ]
- end
+ context 'when before cursor value is NULL' do
+ let(:arguments) { { before: encoded_cursor(project4) } }
- with_them do
- it_behaves_like 'nodes are in ascending order'
- end
- end
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project5, project1, project3, project2])
+ end
+ end
- context 'when descending NULLS LAST (ties broken by id DESC implicitly)' do
- let(:descending_nodes) { [issue5, issue3, issue2, issue4, issue1] }
+ context 'when after cursor value is NULL' do
+ let(:arguments) { { after: encoded_cursor(project2) } }
- where(:nodes) do
- [
- lazy { Issue.order(Issue.arel_table[:relative_position].desc.nulls_last) }
-]
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project4])
+ end
+ end
end
- with_them do
+ context 'when descending' do
+ let_it_be(:order) { Gitlab::Pagination::Keyset::Order.build([column_order_last_repo_desc, column_order_id]) }
+ let_it_be(:nodes) { Project.order(order) }
+ let_it_be(:descending_nodes) { [project3, project1, project5, project2, project4] }
+
it_behaves_like 'nodes are in descending order'
- end
- end
- context 'when ascending NULLS FIRST with a tie breaker' do
- let(:ascending_nodes) { [issue1, issue4, issue2, issue3, issue5] }
+ context 'when before cursor value is NULL' do
+ let(:arguments) { { before: encoded_cursor(project4) } }
- where(:nodes) do
- [
- lazy { Issue.order(Issue.arel_table[:relative_position].asc.nulls_first).order(id: :asc) }
-]
- end
+ it 'returns all projects before the cursor' do
+ expect(subject.sliced_nodes).to eq([project3, project1, project5, project2])
+ end
+ end
- with_them do
- it_behaves_like 'nodes are in ascending order'
+ context 'when after cursor value is NULL' do
+ let(:arguments) { { after: encoded_cursor(project2) } }
+
+ it 'returns all projects after the cursor' do
+ expect(subject.sliced_nodes).to eq([project4])
+ end
+ end
end
end
- context 'when descending NULLS FIRST with a tie breaker' do
- let(:descending_nodes) { [issue1, issue4, issue5, issue3, issue2] }
+ context 'when ordering by similarity' do
+ let_it_be(:project1) { create(:project, name: 'test') }
+ let_it_be(:project2) { create(:project, name: 'testing') }
+ let_it_be(:project3) { create(:project, name: 'tests') }
+ let_it_be(:project4) { create(:project, name: 'testing stuff') }
+ let_it_be(:project5) { create(:project, name: 'test') }
- where(:nodes) do
- [
- lazy { Issue.order(Issue.arel_table[:relative_position].desc.nulls_first).order(id: :asc) }
-]
+ let_it_be(:nodes) do
+ # Note: sorted_by_similarity_desc scope internally supports the generic keyset order.
+ Project.sorted_by_similarity_desc('test', include_in_select: true)
end
- with_them do
- it_behaves_like 'nodes are in descending order'
- end
- end
- end
+ let_it_be(:descending_nodes) { nodes.to_a }
- context 'when ordering by similarity' do
- let!(:project1) { create(:project, name: 'test') }
- let!(:project2) { create(:project, name: 'testing') }
- let!(:project3) { create(:project, name: 'tests') }
- let!(:project4) { create(:project, name: 'testing stuff') }
- let!(:project5) { create(:project, name: 'test') }
-
- let(:nodes) do
- Project.sorted_by_similarity_desc('test', include_in_select: true)
+ it_behaves_like 'nodes are in descending order'
end
- let(:descending_nodes) { nodes.to_a }
-
- it_behaves_like 'nodes are in descending order'
- end
+ context 'when an invalid cursor is provided' do
+ let(:arguments) { { before: Base64Bp.urlsafe_encode64('invalidcursor', padding: false) } }
- context 'when an invalid cursor is provided' do
- let(:arguments) { { before: Base64Bp.urlsafe_encode64('invalidcursor', padding: false) } }
-
- it 'raises an error' do
- expect { subject.sliced_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it 'raises an error' do
+ expect { subject.sliced_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
end
end
- end
- describe '#nodes' do
- let_it_be(:all_nodes) { create_list(:project, 5) }
+ describe '#nodes' do
+ let_it_be(:all_nodes) { create_list(:project, 5) }
- let(:paged_nodes) { subject.nodes }
+ let(:paged_nodes) { subject.nodes }
- it_behaves_like 'connection with paged nodes' do
- let(:paged_nodes_size) { 3 }
- end
-
- context 'when both are passed' do
- let(:arguments) { { first: 2, last: 2 } }
-
- it 'raises an error' do
- expect { paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ it_behaves_like 'connection with paged nodes' do
+ let(:paged_nodes_size) { 3 }
end
- end
- context 'when primary key is not in original order' do
- let(:nodes) { Project.order(last_repository_check_at: :desc) }
+ context 'when both are passed' do
+ let(:arguments) { { first: 2, last: 2 } }
- before do
- stub_feature_flags(new_graphql_keyset_pagination: false)
+ it 'raises an error' do
+ expect { paged_nodes }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
end
- it 'is added to end' do
- sliced = subject.sliced_nodes
+ context 'when primary key is not in original order' do
+ let(:nodes) { Project.order(last_repository_check_at: :desc) }
- order_sql = sliced.order_values.last.to_sql
+ it 'is added to end' do
+ sliced = subject.sliced_nodes
- expect(order_sql).to end_with(Project.arel_table[:id].desc.to_sql)
- end
- end
+ order_sql = sliced.order_values.last.to_sql
- context 'when there is no primary key' do
- before do
- stub_const('NoPrimaryKey', Class.new(ActiveRecord::Base))
- NoPrimaryKey.class_eval do
- self.table_name = 'no_primary_key'
- self.primary_key = nil
+ expect(order_sql).to end_with(Project.arel_table[:id].desc.to_sql)
end
end
- let(:nodes) { NoPrimaryKey.all }
-
- it 'raises an error' do
- expect(NoPrimaryKey.primary_key).to be_nil
- expect { subject.sliced_nodes }.to raise_error(ArgumentError, 'Relation must have a primary key')
- end
- end
- end
-
- describe '#has_previous_page and #has_next_page' do
- # using a list of 5 items with a max_page of 3
- let_it_be(:project_list) { create_list(:project, 5) }
- let_it_be(:nodes) { Project.order(:id) }
+ context 'when there is no primary key' do
+ before do
+ stub_const('NoPrimaryKey', Class.new(ActiveRecord::Base))
+ NoPrimaryKey.class_eval do
+ self.table_name = 'no_primary_key'
+ self.primary_key = nil
+ end
+ end
- context 'when default query' do
- let(:arguments) { {} }
+ let(:nodes) { NoPrimaryKey.all }
- it 'has no previous, but a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
+ it 'raises an error' do
+ expect(NoPrimaryKey.primary_key).to be_nil
+ expect { subject.sliced_nodes }.to raise_error(ArgumentError, 'Relation must have a primary key')
+ end
end
end
- context 'when before is first item' do
- let(:arguments) { { before: encoded_cursor(project_list.first) } }
+ describe '#has_previous_page and #has_next_page' do
+ # using a list of 5 items with a max_page of 3
+ let_it_be(:project_list) { create_list(:project, 5) }
+ let_it_be(:nodes) { Project.order(Gitlab::Pagination::Keyset::Order.build([column_order_id])) }
- it 'has no previous, but a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- end
- end
-
- describe 'using `before`' do
- context 'when before is the last item' do
- let(:arguments) { { before: encoded_cursor(project_list.last) } }
+ context 'when default query' do
+ let(:arguments) { {} }
it 'has no previous, but a next' do
expect(subject.has_previous_page).to be_falsey
@@ -436,51 +343,71 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
end
end
- context 'when before and last specified' do
- let(:arguments) { { before: encoded_cursor(project_list.last), last: 2 } }
+ context 'when before is first item' do
+ let(:arguments) { { before: encoded_cursor(project_list.first) } }
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_truthy
+ it 'has no previous, but a next' do
+ expect(subject.has_previous_page).to be_falsey
expect(subject.has_next_page).to be_truthy
end
end
- context 'when before and last does request all remaining nodes' do
- let(:arguments) { { before: encoded_cursor(project_list[1]), last: 3 } }
+ describe 'using `before`' do
+ context 'when before is the last item' do
+ let(:arguments) { { before: encoded_cursor(project_list.last) } }
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_falsey
- expect(subject.has_next_page).to be_truthy
- expect(subject.nodes).to eq [project_list[0]]
+ it 'has no previous, but a next' do
+ expect(subject.has_previous_page).to be_falsey
+ expect(subject.has_next_page).to be_truthy
+ end
end
- end
- end
- describe 'using `after`' do
- context 'when after is the first item' do
- let(:arguments) { { after: encoded_cursor(project_list.first) } }
+ context 'when before and last specified' do
+ let(:arguments) { { before: encoded_cursor(project_list.last), last: 2 } }
- it 'has a previous, and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
+ it 'has a previous and a next' do
+ expect(subject.has_previous_page).to be_truthy
+ expect(subject.has_next_page).to be_truthy
+ end
end
- end
- context 'when after and first specified' do
- let(:arguments) { { after: encoded_cursor(project_list.first), first: 2 } }
+ context 'when before and last does request all remaining nodes' do
+ let(:arguments) { { before: encoded_cursor(project_list[1]), last: 3 } }
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
+ it 'has a previous and a next' do
+ expect(subject.has_previous_page).to be_falsey
+ expect(subject.has_next_page).to be_truthy
+ expect(subject.nodes).to eq [project_list[0]]
+ end
end
end
- context 'when before and last does request all remaining nodes' do
- let(:arguments) { { after: encoded_cursor(project_list[2]), last: 3 } }
+ describe 'using `after`' do
+ context 'when after is the first item' do
+ let(:arguments) { { after: encoded_cursor(project_list.first) } }
+
+ it 'has a previous, and a next' do
+ expect(subject.has_previous_page).to be_truthy
+ expect(subject.has_next_page).to be_truthy
+ end
+ end
+
+ context 'when after and first specified' do
+ let(:arguments) { { after: encoded_cursor(project_list.first), first: 2 } }
+
+ it 'has a previous and a next' do
+ expect(subject.has_previous_page).to be_truthy
+ expect(subject.has_next_page).to be_truthy
+ end
+ end
+
+ context 'when before and last does request all remaining nodes' do
+ let(:arguments) { { after: encoded_cursor(project_list[2]), last: 3 } }
- it 'has a previous but no next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_falsey
+ it 'has a previous but no next' do
+ expect(subject.has_previous_page).to be_truthy
+ expect(subject.has_next_page).to be_falsey
+ end
end
end
end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb
deleted file mode 100644
index 40ee47ece49..00000000000
--- a/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Pagination::Keyset::OrderInfo do
- describe '#build_order_list' do
- let(:order_list) { described_class.build_order_list(relation) }
-
- context 'when multiple orders with SQL is specified' do
- let(:relation) { Project.order(Arel.sql('projects.updated_at IS NULL')).order(:updated_at).order(:id) }
-
- it 'ignores the SQL order' do
- expect(order_list.count).to eq 2
- expect(order_list.first.attribute_name).to eq 'updated_at'
- expect(order_list.first.operator_for(:after)).to eq '>'
- expect(order_list.last.attribute_name).to eq 'id'
- expect(order_list.last.operator_for(:after)).to eq '>'
- end
- end
-
- context 'when order contains NULLS LAST' do
- let(:relation) { Project.order(Arel.sql('projects.updated_at Asc Nulls Last')).order(:id) }
-
- it 'does not ignore the SQL order' do
- expect(order_list.count).to eq 2
- expect(order_list.first.attribute_name).to eq 'projects.updated_at'
- expect(order_list.first.operator_for(:after)).to eq '>'
- expect(order_list.last.attribute_name).to eq 'id'
- expect(order_list.last.operator_for(:after)).to eq '>'
- end
- end
-
- context 'when order contains invalid formatted NULLS LAST ' do
- let(:relation) { Project.order(Arel.sql('projects.updated_at created_at Asc Nulls Last')).order(:id) }
-
- it 'ignores the SQL order' do
- expect(order_list.count).to eq 1
- end
- end
-
- context 'when order contains LOWER' do
- let(:relation) { Project.order(Arel::Table.new(:projects)['name'].lower.asc).order(:id) }
-
- it 'does not ignore the SQL order' do
- expect(order_list.count).to eq 2
- expect(order_list.first.attribute_name).to eq 'name'
- expect(order_list.first.named_function).to be_kind_of(Arel::Nodes::NamedFunction)
- expect(order_list.first.named_function.to_sql).to eq 'LOWER("projects"."name")'
- expect(order_list.first.operator_for(:after)).to eq '>'
- expect(order_list.last.attribute_name).to eq 'id'
- expect(order_list.last.operator_for(:after)).to eq '>'
- end
- end
-
- context 'when ordering by CASE', :aggregate_failuers do
- let(:relation) { Project.order(Arel::Nodes::Case.new(Project.arel_table[:pending_delete]).when(true).then(100).else(1000).asc) }
-
- it 'assigns the right attribute name, named function, and direction' do
- expect(order_list.count).to eq 1
- expect(order_list.first.attribute_name).to eq 'case_order_value'
- expect(order_list.first.named_function).to be_kind_of(Arel::Nodes::Case)
- expect(order_list.first.sort_direction).to eq :asc
- end
- end
-
- context 'when ordering by ARRAY_POSITION', :aggregate_failuers do
- let(:array_position) { Arel::Nodes::NamedFunction.new('ARRAY_POSITION', [Arel.sql("ARRAY[1,0]::smallint[]"), Project.arel_table[:auto_cancel_pending_pipelines]]) }
- let(:relation) { Project.order(array_position.asc) }
-
- it 'assigns the right attribute name, named function, and direction' do
- expect(order_list.count).to eq 1
- expect(order_list.first.attribute_name).to eq 'array_position'
- expect(order_list.first.named_function).to be_kind_of(Arel::Nodes::NamedFunction)
- expect(order_list.first.sort_direction).to eq :asc
- end
- end
- end
-
- describe '#validate_ordering' do
- let(:order_list) { described_class.build_order_list(relation) }
-
- context 'when number of ordering fields is 0' do
- let(:relation) { Project.all }
-
- it 'raises an error' do
- expect { described_class.validate_ordering(relation, order_list) }
- .to raise_error(ArgumentError, 'A minimum of 1 ordering field is required')
- end
- end
-
- context 'when number of ordering fields is over 2' do
- let(:relation) { Project.order(last_repository_check_at: :desc).order(updated_at: :desc).order(:id) }
-
- it 'raises an error' do
- expect { described_class.validate_ordering(relation, order_list) }
- .to raise_error(ArgumentError, 'A maximum of 2 ordering fields are allowed')
- end
- end
-
- context 'when the second (or first) column is nullable' do
- let(:relation) { Project.order(last_repository_check_at: :desc).order(updated_at: :desc) }
-
- it 'raises an error' do
- expect { described_class.validate_ordering(relation, order_list) }
- .to raise_error(ArgumentError, "Column `updated_at` must not allow NULL")
- end
- end
-
- context 'for last ordering field' do
- let(:relation) { Project.order(namespace_id: :desc) }
-
- it 'raises error if primary key is not last field' do
- expect { described_class.validate_ordering(relation, order_list) }
- .to raise_error(ArgumentError, "Last ordering field must be the primary key, `#{relation.primary_key}`")
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb
deleted file mode 100644
index 31c02fd43e8..00000000000
--- a/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::Graphql::Pagination::Keyset::QueryBuilder do
- context 'when number of ordering fields is 0' do
- it 'raises an error' do
- expect { described_class.new(Issue.arel_table, [], {}, :after) }
- .to raise_error(ArgumentError, 'No ordering scopes have been supplied')
- end
- end
-
- describe '#conditions' do
- let(:relation) { Issue.order(relative_position: :desc).order(:id) }
- let(:order_list) { Gitlab::Graphql::Pagination::Keyset::OrderInfo.build_order_list(relation) }
- let(:arel_table) { Issue.arel_table }
- let(:builder) { described_class.new(arel_table, order_list, decoded_cursor, before_or_after) }
- let(:before_or_after) { :after }
-
- context 'when only a single ordering' do
- let(:relation) { Issue.order(id: :desc) }
-
- context 'when the value is nil' do
- let(:decoded_cursor) { { 'id' => nil } }
-
- it 'raises an error' do
- expect { builder.conditions }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'Before/after cursor invalid: `nil` was provided as only sortable value')
- end
- end
-
- context 'when value is not nil' do
- let(:decoded_cursor) { { 'id' => 100 } }
- let(:conditions) { builder.conditions }
-
- context 'when :after' do
- it 'generates the correct condition' do
- expect(conditions.strip).to eq '("issues"."id" < 100)'
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates the correct condition' do
- expect(conditions.strip).to eq '("issues"."id" > 100)'
- end
- end
- end
- end
-
- context 'when two orderings' do
- let(:decoded_cursor) { { 'relative_position' => 1500, 'id' => 100 } }
-
- context 'when no values are nil' do
- context 'when :after' do
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '"issues"."relative_position" < 1500'
- expect(conditions).to include '"issues"."id" > 100'
- expect(conditions).to include 'OR ("issues"."relative_position" IS NULL)'
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '("issues"."relative_position" > 1500)'
- expect(conditions).to include '"issues"."id" < 100'
- expect(conditions).to include '"issues"."relative_position" = 1500'
- end
- end
- end
-
- context 'when first value is nil' do
- let(:decoded_cursor) { { 'relative_position' => nil, 'id' => 100 } }
-
- context 'when :after' do
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '"issues"."relative_position" IS NULL'
- expect(conditions).to include '"issues"."id" > 100'
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '"issues"."relative_position" IS NULL'
- expect(conditions).to include '"issues"."id" < 100'
- expect(conditions).to include 'OR ("issues"."relative_position" IS NOT NULL)'
- end
- end
- end
- end
-
- context 'when sorting using LOWER' do
- let(:relation) { Project.order(Arel::Table.new(:projects)['name'].lower.asc).order(:id) }
- let(:arel_table) { Project.arel_table }
- let(:decoded_cursor) { { 'name' => 'Test', 'id' => 100 } }
-
- context 'when no values are nil' do
- context 'when :after' do
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '(LOWER("projects"."name") > \'test\')'
- expect(conditions).to include '"projects"."id" > 100'
- expect(conditions).to include 'OR (LOWER("projects"."name") IS NULL)'
- end
- end
-
- context 'when :before' do
- let(:before_or_after) { :before }
-
- it 'generates the correct condition' do
- conditions = builder.conditions
-
- expect(conditions).to include '(LOWER("projects"."name") < \'test\')'
- expect(conditions).to include '"projects"."id" < 100'
- expect(conditions).to include 'LOWER("projects"."name") = \'test\''
- end
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/graphql/type_name_deprecations_spec.rb b/spec/lib/gitlab/graphql/type_name_deprecations_spec.rb
new file mode 100644
index 00000000000..0505e709a3b
--- /dev/null
+++ b/spec/lib/gitlab/graphql/type_name_deprecations_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../support/helpers/type_name_deprecation_helpers'
+
+RSpec.describe Gitlab::Graphql::TypeNameDeprecations do
+ include TypeNameDeprecationHelpers
+
+ let(:deprecation_1) do
+ described_class::NameDeprecation.new(old_name: 'Foo::Model', new_name: 'Bar', milestone: '9.0')
+ end
+
+ let(:deprecation_2) do
+ described_class::NameDeprecation.new(old_name: 'Baz', new_name: 'Qux::Model', milestone: '10.0')
+ end
+
+ before do
+ stub_type_name_deprecations(deprecation_1, deprecation_2)
+ end
+
+ describe '.deprecated?' do
+ it 'returns a boolean to signal if model name has a deprecation', :aggregate_failures do
+ expect(described_class.deprecated?('Foo::Model')).to eq(true)
+ expect(described_class.deprecated?('Qux::Model')).to eq(false)
+ end
+ end
+
+ describe '.deprecation_for' do
+ it 'returns the deprecation for the model if it exists', :aggregate_failures do
+ expect(described_class.deprecation_for('Foo::Model')).to eq(deprecation_1)
+ expect(described_class.deprecation_for('Qux::Model')).to be_nil
+ end
+ end
+
+ describe '.deprecation_by' do
+ it 'returns the deprecation by the model if it exists', :aggregate_failures do
+ expect(described_class.deprecation_by('Foo::Model')).to be_nil
+ expect(described_class.deprecation_by('Qux::Model')).to eq(deprecation_2)
+ end
+ end
+
+ describe '.apply_to_graphql_name' do
+ it 'returns the corresponding graphql_name of the GID for the new model', :aggregate_failures do
+ expect(described_class.apply_to_graphql_name('Foo::Model')).to eq('Bar')
+ expect(described_class.apply_to_graphql_name('Baz')).to eq('Qux::Model')
+ end
+
+ it 'returns the same value if there is no deprecation' do
+ expect(described_class.apply_to_graphql_name('Project')).to eq('Project')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphs/commits_spec.rb b/spec/lib/gitlab/graphs/commits_spec.rb
index 79cec2d8705..c3c696ceedc 100644
--- a/spec/lib/gitlab/graphs/commits_spec.rb
+++ b/spec/lib/gitlab/graphs/commits_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Graphs::Commits do
let!(:project) { create(:project, :public) }
let!(:commit1) { create(:commit, git_commit: RepoHelpers.sample_commit, project: project, committed_date: Time.now) }
- let!(:commit1_yesterday) { create(:commit, git_commit: RepoHelpers.sample_commit, project: project, committed_date: 1.day.ago)}
+ let!(:commit1_yesterday) { create(:commit, git_commit: RepoHelpers.sample_commit, project: project, committed_date: 1.day.ago) }
let!(:commit2) { create(:commit, git_commit: RepoHelpers.another_sample_commit, project: project, committed_date: Time.now) }
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 537e59d91c3..d7ae6ed06a4 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Highlight do
context 'diff highlighting' do
let(:file_name) { 'test.diff' }
- let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
+ let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n" }
let(:expected) do
%q(<span id="LC1" class="line" lang="diff"><span class="gi">+aaa</span></span>
<span id="LC2" class="line" lang="diff"><span class="gi">+bbb</span></span>
diff --git a/spec/lib/gitlab/hook_data/group_builder_spec.rb b/spec/lib/gitlab/hook_data/group_builder_spec.rb
index d7347ff99d4..4e6152390a4 100644
--- a/spec/lib/gitlab/hook_data/group_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/group_builder_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe Gitlab::HookData::GroupBuilder do
let(:event) { :create }
it { expect(event_name).to eq('group_create') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include old path attributes'
end
@@ -46,6 +47,7 @@ RSpec.describe Gitlab::HookData::GroupBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('group_destroy') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include old path attributes'
end
@@ -54,6 +56,7 @@ RSpec.describe Gitlab::HookData::GroupBuilder do
let(:event) { :rename }
it { expect(event_name).to eq('group_rename') }
+
it_behaves_like 'includes the required attributes'
it 'includes old path details' do
diff --git a/spec/lib/gitlab/hook_data/group_member_builder_spec.rb b/spec/lib/gitlab/hook_data/group_member_builder_spec.rb
index 78c62fd23c7..35ce31ab897 100644
--- a/spec/lib/gitlab/hook_data/group_member_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/group_member_builder_spec.rb
@@ -39,6 +39,7 @@ RSpec.describe Gitlab::HookData::GroupMemberBuilder do
let(:event) { :create }
it { expect(event_name).to eq('user_add_to_group') }
+
it_behaves_like 'includes the required attributes'
end
@@ -46,6 +47,7 @@ RSpec.describe Gitlab::HookData::GroupMemberBuilder do
let(:event) { :update }
it { expect(event_name).to eq('user_update_for_group') }
+
it_behaves_like 'includes the required attributes'
end
@@ -53,6 +55,7 @@ RSpec.describe Gitlab::HookData::GroupMemberBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('user_remove_from_group') }
+
it_behaves_like 'includes the required attributes'
end
end
diff --git a/spec/lib/gitlab/hook_data/key_builder_spec.rb b/spec/lib/gitlab/hook_data/key_builder_spec.rb
index 86f33df115f..2c87c9a10e6 100644
--- a/spec/lib/gitlab/hook_data/key_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/key_builder_spec.rb
@@ -36,6 +36,7 @@ RSpec.describe Gitlab::HookData::KeyBuilder do
it { expect(event_name).to eq('key_create') }
it { expect(data[:username]).to eq(key.user.username) }
+
it_behaves_like 'includes the required attributes'
end
@@ -44,6 +45,7 @@ RSpec.describe Gitlab::HookData::KeyBuilder do
it { expect(event_name).to eq('key_destroy') }
it { expect(data[:username]).to eq(key.user.username) }
+
it_behaves_like 'includes the required attributes'
end
end
@@ -58,6 +60,7 @@ RSpec.describe Gitlab::HookData::KeyBuilder do
let(:event) { :create }
it { expect(event_name).to eq('key_create') }
+
it_behaves_like 'includes the required attributes'
end
@@ -65,6 +68,7 @@ RSpec.describe Gitlab::HookData::KeyBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('key_destroy') }
+
it_behaves_like 'includes the required attributes'
end
end
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index 25b84a67ab2..cb8fef60ab2 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -29,6 +29,7 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
merge_user_id
merge_when_pipeline_succeeds
milestone_id
+ reviewer_ids
source_branch
source_project_id
state_id
@@ -72,6 +73,7 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
human_time_estimate
assignee_ids
assignee_id
+ reviewer_ids
labels
state
blocking_discussions_resolved
diff --git a/spec/lib/gitlab/hook_data/project_builder_spec.rb b/spec/lib/gitlab/hook_data/project_builder_spec.rb
index e86ac66b1ad..729712510ea 100644
--- a/spec/lib/gitlab/hook_data/project_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/project_builder_spec.rb
@@ -52,6 +52,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
let(:event) { :create }
it { expect(event_name).to eq('project_create') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include `old_path_with_namespace` attribute'
end
@@ -60,6 +61,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('project_destroy') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include `old_path_with_namespace` attribute'
end
@@ -68,6 +70,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
let(:event) { :rename }
it { expect(event_name).to eq('project_rename') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'includes `old_path_with_namespace` attribute'
end
@@ -76,6 +79,7 @@ RSpec.describe Gitlab::HookData::ProjectBuilder do
let(:event) { :transfer }
it { expect(event_name).to eq('project_transfer') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'includes `old_path_with_namespace` attribute'
end
diff --git a/spec/lib/gitlab/hook_data/project_member_builder_spec.rb b/spec/lib/gitlab/hook_data/project_member_builder_spec.rb
index 3fb84223581..76446adf7b7 100644
--- a/spec/lib/gitlab/hook_data/project_member_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/project_member_builder_spec.rb
@@ -37,6 +37,7 @@ RSpec.describe Gitlab::HookData::ProjectMemberBuilder do
let(:event) { :create }
it { expect(event_name).to eq('user_add_to_team') }
+
it_behaves_like 'includes the required attributes'
end
@@ -44,6 +45,7 @@ RSpec.describe Gitlab::HookData::ProjectMemberBuilder do
let(:event) { :update }
it { expect(event_name).to eq('user_update_for_team') }
+
it_behaves_like 'includes the required attributes'
end
@@ -51,6 +53,7 @@ RSpec.describe Gitlab::HookData::ProjectMemberBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('user_remove_from_team') }
+
it_behaves_like 'includes the required attributes'
end
end
diff --git a/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb b/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb
index 89e5dffd7b4..b25320af891 100644
--- a/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/subgroup_builder_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe Gitlab::HookData::SubgroupBuilder do
let(:event) { :create }
it { expect(event_name).to eq('subgroup_create') }
+
it_behaves_like 'includes the required attributes'
end
@@ -45,6 +46,7 @@ RSpec.describe Gitlab::HookData::SubgroupBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('subgroup_destroy') }
+
it_behaves_like 'includes the required attributes'
end
end
diff --git a/spec/lib/gitlab/hook_data/user_builder_spec.rb b/spec/lib/gitlab/hook_data/user_builder_spec.rb
index f971089850b..ae844308fb1 100644
--- a/spec/lib/gitlab/hook_data/user_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/user_builder_spec.rb
@@ -44,6 +44,7 @@ RSpec.describe Gitlab::HookData::UserBuilder do
let(:event) { :create }
it { expect(event_name).to eq('user_create') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include old username attributes'
it_behaves_like 'does not include state attributes'
@@ -53,6 +54,7 @@ RSpec.describe Gitlab::HookData::UserBuilder do
let(:event) { :destroy }
it { expect(event_name).to eq('user_destroy') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include old username attributes'
it_behaves_like 'does not include state attributes'
@@ -62,6 +64,7 @@ RSpec.describe Gitlab::HookData::UserBuilder do
let(:event) { :rename }
it { expect(event_name).to eq('user_rename') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include state attributes'
@@ -76,6 +79,7 @@ RSpec.describe Gitlab::HookData::UserBuilder do
let(:event) { :failed_login }
it { expect(event_name).to eq('user_failed_login') }
+
it_behaves_like 'includes the required attributes'
it_behaves_like 'does not include old username attributes'
diff --git a/spec/lib/gitlab/http_io_spec.rb b/spec/lib/gitlab/http_io_spec.rb
index 5ba0cb5e686..1376b726df3 100644
--- a/spec/lib/gitlab/http_io_spec.rb
+++ b/spec/lib/gitlab/http_io_spec.rb
@@ -262,7 +262,7 @@ RSpec.describe Gitlab::HttpIO do
end
it 'reads a trace' do
- expect { subject }.to raise_error(Gitlab::HttpIO::FailedToGetChunkError)
+ expect { subject }.to raise_error(Gitlab::HttpIO::FailedToGetChunkError, 'Unexpected response code: 500')
end
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 451fd6c6f46..42cf9c54798 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,12 +9,21 @@ 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
let(:example_url) { 'http://www.example.com' }
let(:strategy) { subject.new(url: example_url, http_method: 'post') }
- let!(:project) { create(:project, :with_export) }
- let!(:user) { build(:user) }
+ let(:user) { build(:user) }
+ let(:project) { import_export_upload.project }
+ let(:import_export_upload) do
+ create(
+ :import_export_upload,
+ export_file: fixture_file_upload('spec/fixtures/gitlab/import_export/lightweight_project_export.tar.gz')
+ )
+ end
subject { described_class }
@@ -36,20 +45,42 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
describe '#execute' do
context 'when upload succeeds' do
before do
- allow(strategy).to receive(:send_file)
- allow(strategy).to receive(:handle_response_error)
+ stub_full_request(example_url, method: :post).to_return(status: 200)
end
- it 'does not remove the exported project file after the upload' do
+ it 'does not remove the exported project file after the upload', :aggregate_failures do
expect(project).not_to receive(:remove_exports)
- strategy.execute(user, project)
+ expect { strategy.execute(user, project) }.not_to change(project, :export_status)
+
+ expect(project.export_status).to eq(:finished)
end
- it 'has finished export status' do
- strategy.execute(user, project)
+ it 'logs when upload starts and finishes' do
+ export_size = import_export_upload.export_file.size
+
+ expect_next_instance_of(Gitlab::Export::Logger) do |logger|
+ expect(logger).to receive(:info).ordered.with(
+ {
+ message: "Started uploading project",
+ project_id: project.id,
+ project_name: project.name,
+ export_size: export_size
+ }
+ )
+
+ expect(logger).to receive(:info).ordered.with(
+ {
+ message: "Finished uploading project",
+ project_id: project.id,
+ project_name: project.name,
+ export_size: export_size,
+ upload_duration: anything
+ }
+ )
+ end
- expect(project.export_status).to eq(:finished)
+ strategy.execute(user, project)
end
end
@@ -64,5 +95,124 @@ RSpec.describe Gitlab::ImportExport::AfterExportStrategies::WebUploadStrategy do
expect(errors.first).to eq "Error uploading the project. Code 404: Page not found"
end
end
+
+ context 'when 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
+ 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
+ end
+ expect(Gitlab::ImportExport::RemoteStreamUpload).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' }
+
+ 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)
+ 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)
+ 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
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 8c1e60e78b0..9aec3271913 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -140,6 +140,12 @@ project_members:
- project
- member_task
- member_namespace
+- member_role
+member_roles:
+- members
+- namespace
+- base_access_level
+- download_code
merge_requests:
- status_check_responses
- subscriptions
@@ -591,6 +597,7 @@ project:
- alert_management_alerts
- repository_storage_moves
- freeze_periods
+- pumble_integration
- webex_teams_integration
- build_report_results
- vulnerability_statistic
@@ -621,6 +628,7 @@ project:
- security_trainings
- vulnerability_reads
- build_artifacts_size_refresh
+- project_callouts
award_emoji:
- awardable
- user
@@ -646,6 +654,11 @@ search_data:
merge_request_assignees:
- merge_request
- assignee
+- updated_state_by
+merge_request_reviewers:
+- merge_request
+- reviewer
+- updated_state_by
lfs_file_locks:
- user
project_badges:
@@ -805,3 +818,6 @@ bulk_import_export:
- group
service_desk_setting:
- file_template_project
+approvals:
+ - user
+ - merge_request
diff --git a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
index b8999f608b1..4ef8f4b5d76 100644
--- a/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/base/relation_factory_spec.rb
@@ -139,6 +139,30 @@ RSpec.describe Gitlab::ImportExport::Base::RelationFactory do
expect(subject.value).to be_nil
end
end
+
+ context 'with duplicate assignees' do
+ let(:relation_sym) { :issues }
+ let(:relation_hash) do
+ { "title" => "title", "state" => "opened" }.merge(issue_assignees)
+ end
+
+ context 'when duplicate assignees are present' do
+ let(:issue_assignees) do
+ {
+ "issue_assignees" => [
+ IssueAssignee.new(user_id: 1),
+ IssueAssignee.new(user_id: 2),
+ IssueAssignee.new(user_id: 1),
+ { user_id: 3 }
+ ]
+ }
+ end
+
+ it 'removes duplicate assignees' do
+ expect(subject.issue_assignees.map(&:user_id)).to contain_exactly(1, 2)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb b/spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb
index 7c84b9604a6..9f1b15aa049 100644
--- a/spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/base/relation_object_saver_spec.rb
@@ -58,8 +58,8 @@ RSpec.describe Gitlab::ImportExport::Base::RelationObjectSaver do
end
context 'when subrelation collection count is small' do
- let(:notes) { build_list(:note, 2, project: project, importing: true) }
- let(:relation_object) { build(:issue, project: project, notes: notes) }
+ let(:note) { build(:note, project: project, importing: true) }
+ let(:relation_object) { build(:issue, project: project, notes: [note]) }
let(:relation_definition) { { 'notes' => {} } }
it 'saves subrelation as part of the relation object itself' do
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::ImportExport::Base::RelationObjectSaver do
saver.execute
issue = project.issues.last
- expect(issue.notes.count).to eq(2)
+ expect(issue.notes.count).to eq(1)
end
end
diff --git a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
index dea584e5019..9af72cc0dea 100644
--- a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
+++ b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb
@@ -51,10 +51,11 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator do
shared_examples 'logs raised exception and terminates validator process group' do
let(:std) { double(:std, close: nil, value: nil) }
let(:wait_thr) { double }
+ let(:wait_threads) { [wait_thr, wait_thr] }
before do
allow(Process).to receive(:getpgid).and_return(2)
- allow(Open3).to receive(:popen3).and_return([std, std, std, wait_thr])
+ allow(Open3).to receive(:pipeline_r).and_return([std, wait_threads])
allow(wait_thr).to receive(:[]).with(:pid).and_return(1)
allow(wait_thr).to receive(:value).and_raise(exception)
end
@@ -67,7 +68,7 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator do
import_upload_archive_size: File.size(filepath),
message: error_message
)
- expect(Process).to receive(:kill).with(-1, 2)
+ expect(Process).to receive(:kill).with(-1, 2).twice
expect(subject.valid?).to eq(false)
end
end
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 9b01005c2e9..89ae869ae86 100644
--- a/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/group/tree_restorer_spec.rb
@@ -204,19 +204,5 @@ RSpec.describe Gitlab::ImportExport::Group::TreeRestorer do
end
end
- context 'when import_relation_object_persistence feature flag is enabled' do
- before do
- stub_feature_flags(import_relation_object_persistence: true)
- end
-
- include_examples 'group restoration'
- end
-
- context 'when import_relation_object_persistence feature flag is disabled' do
- before do
- stub_feature_flags(import_relation_object_persistence: false)
- end
-
- include_examples 'group restoration'
- end
+ include_examples 'group restoration'
end
diff --git a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
index 90966cb4915..51c0008b2b4 100644
--- a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
+++ b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
@@ -88,8 +88,8 @@ RSpec.describe 'Test coverage of the Project Import' do
def relations_from_json(json_file)
json = Gitlab::Json.parse(IO.read(json_file))
- [].tap {|res| gather_relations({ project: json }, res, [])}
- .map {|relation_names| relation_names.join('.')}
+ [].tap { |res| gather_relations({ project: json }, res, []) }
+ .map { |relation_names| relation_names.join('.') }
end
def gather_relations(item, res, path)
@@ -103,7 +103,7 @@ RSpec.describe 'Test coverage of the Project Import' do
end
end
when Array
- item.each {|i| gather_relations(i, res, path)}
+ item.each { |i| gather_relations(i, res, path) }
end
end
diff --git a/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb b/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
index 9be95591ae9..452d63d548e 100644
--- a/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/ndjson_writer_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::ImportExport::Json::NdjsonWriter do
file_path = File.join(path, exportable_path, "#{relation}.ndjson")
subject.write_relation(exportable_path, relation, values[0])
- expect {subject.write_relation(exportable_path, relation, values[1])}.to raise_exception("The #{file_path} already exist")
+ expect { subject.write_relation(exportable_path, relation, values[1]) }.to raise_exception("The #{file_path} already exist")
end
end
end
diff --git a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
index 3f73a730744..3088129a732 100644
--- a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
end
let(:exportable_path) { 'project' }
+ let(:logger) { Gitlab::Export::Logger.build }
let(:json_writer) { instance_double('Gitlab::ImportExport::Json::LegacyWriter') }
let(:hash) { { name: exportable.name, description: exportable.description }.stringify_keys }
let(:include) { [] }
@@ -42,7 +43,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
end
subject do
- described_class.new(exportable, relations_schema, json_writer, exportable_path: exportable_path)
+ described_class.new(exportable, relations_schema, json_writer, exportable_path: exportable_path, logger: logger)
end
describe '#execute' do
@@ -73,6 +74,21 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
subject.execute
end
+ it 'logs the relation name and the number of records to export' do
+ allow(json_writer).to receive(:write_relation_array)
+ allow(logger).to receive(:info)
+
+ subject.execute
+
+ expect(logger).to have_received(:info).with(
+ importer: 'Import/Export',
+ message: "Exporting issues relation. Number of records to export: 16",
+ project_id: exportable.id,
+ project_name: exportable.name,
+ project_path: exportable.full_path
+ )
+ end
+
context 'default relation ordering' do
it 'orders exported issues by primary key(:id)' do
expected_issues = exportable.issues.reorder(:id).map(&:to_json)
@@ -138,6 +154,21 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
subject.execute
end
+
+ it 'logs the relation name' do
+ allow(json_writer).to receive(:write_relation)
+ allow(logger).to receive(:info)
+
+ subject.execute
+
+ expect(logger).to have_received(:info).with(
+ importer: 'Import/Export',
+ message: 'Exporting group relation',
+ project_id: exportable.id,
+ project_name: exportable.name,
+ project_path: exportable.full_path
+ )
+ end
end
context 'with array relation' do
@@ -155,6 +186,21 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer do
subject.execute
end
+
+ it 'logs the relation name and the number of records to export' do
+ allow(json_writer).to receive(:write_relation_array)
+ allow(logger).to receive(:info)
+
+ subject.execute
+
+ expect(logger).to have_received(:info).with(
+ importer: 'Import/Export',
+ message: 'Exporting project_members relation. Number of records to export: 1',
+ project_id: exportable.id,
+ project_name: exportable.name,
+ project_path: exportable.full_path
+ )
+ end
end
describe 'load balancing' do
diff --git a/spec/lib/gitlab/import_export/log_util_spec.rb b/spec/lib/gitlab/import_export/log_util_spec.rb
new file mode 100644
index 00000000000..2b1a4b7bb61
--- /dev/null
+++ b/spec/lib/gitlab/import_export/log_util_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::LogUtil do
+ describe '.exportable_to_log_payload' do
+ subject { described_class.exportable_to_log_payload(exportable) }
+
+ context 'when exportable is a group' do
+ let(:exportable) { build_stubbed(:group) }
+
+ it 'returns hash with group keys' do
+ expect(subject).to be_a(Hash)
+ expect(subject.keys).to eq(%i[group_id group_name group_path])
+ end
+ end
+
+ context 'when exportable is a project' do
+ let(:exportable) { build_stubbed(:project) }
+
+ it 'returns hash with project keys' do
+ expect(subject).to be_a(Hash)
+ expect(subject.keys).to eq(%i[project_id project_name project_path])
+ end
+ end
+
+ context 'when exportable is a new record' do
+ let(:exportable) { Project.new }
+
+ it 'returns empty hash' do
+ expect(subject).to eq({})
+ end
+ end
+
+ context 'when exportable is an unexpected type' do
+ let(:exportable) { build_stubbed(:issue) }
+
+ it 'returns empty hash' do
+ expect(subject).to eq({})
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/relation_saver_spec.rb b/spec/lib/gitlab/import_export/project/relation_saver_spec.rb
new file mode 100644
index 00000000000..dec51b3afd1
--- /dev/null
+++ b/spec/lib/gitlab/import_export/project/relation_saver_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::Project::RelationSaver do
+ include ImportExport::CommonUtil
+
+ subject(:relation_saver) { described_class.new(project: project, shared: shared, relation: relation) }
+
+ let_it_be(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
+ let_it_be(:project) { setup_project }
+
+ let(:relation) { Projects::ImportExport::RelationExport::ROOT_RELATION }
+ let(:shared) do
+ shared = project.import_export_shared
+ allow(shared).to receive(:export_path).and_return(export_path)
+ shared
+ end
+
+ after do
+ FileUtils.rm_rf(export_path)
+ end
+
+ describe '#save' do
+ context 'when relation is the root node' do
+ let(:relation) { Projects::ImportExport::RelationExport::ROOT_RELATION }
+
+ it 'serializes the root node as a json file in the export path' do
+ relation_saver.save # rubocop:disable Rails/SaveBang
+
+ json = read_json(File.join(shared.export_path, 'project.json'))
+ expect(json).to include({ 'description' => 'Project description' })
+ end
+
+ it 'serializes only allowed attributes' do
+ relation_saver.save # rubocop:disable Rails/SaveBang
+
+ json = read_json(File.join(shared.export_path, 'project.json'))
+ expect(json).to include({ 'description' => 'Project description' })
+ expect(json.keys).not_to include('name')
+ end
+
+ it 'successfuly serializes without errors' do
+ result = relation_saver.save # rubocop:disable Rails/SaveBang
+
+ expect(result).to eq(true)
+ expect(shared.errors).to be_empty
+ end
+ end
+
+ context 'when relation is a child node' do
+ let(:relation) { 'labels' }
+
+ it 'serializes the child node as a ndjson file in the export path inside the project folder' do
+ relation_saver.save # rubocop:disable Rails/SaveBang
+
+ ndjson = read_ndjson(File.join(shared.export_path, 'project', "#{relation}.ndjson"))
+ expect(ndjson.first).to include({ 'title' => 'Label 1' })
+ expect(ndjson.second).to include({ 'title' => 'Label 2' })
+ end
+
+ it 'serializes only allowed attributes' do
+ relation_saver.save # rubocop:disable Rails/SaveBang
+
+ ndjson = read_ndjson(File.join(shared.export_path, 'project', "#{relation}.ndjson"))
+ expect(ndjson.first.keys).not_to include('description_html')
+ end
+
+ it 'successfuly serializes without errors' do
+ result = relation_saver.save # rubocop:disable Rails/SaveBang
+
+ expect(result).to eq(true)
+ expect(shared.errors).to be_empty
+ end
+ end
+
+ context 'when relation name is not supported' do
+ let(:relation) { 'unknown' }
+
+ it 'returns false and register the error' do
+ result = relation_saver.save # rubocop:disable Rails/SaveBang
+
+ expect(result).to eq(false)
+ expect(shared.errors).to be_present
+ end
+ end
+
+ context 'when an exception occurs during serialization' do
+ it 'returns false and register the exception error message' do
+ allow_next_instance_of(Gitlab::ImportExport::Json::StreamingSerializer) do |serializer|
+ allow(serializer).to receive(:serialize_root).and_raise('Error!')
+ end
+
+ result = relation_saver.save # rubocop:disable Rails/SaveBang
+
+ expect(result).to eq(false)
+ expect(shared.errors).to include('Error!')
+ end
+ end
+ end
+
+ def setup_project
+ project = create(:project,
+ description: 'Project description'
+ )
+
+ create(:label, project: project, title: 'Label 1')
+ create(:label, project: project, title: 'Label 2')
+
+ project
+ end
+
+ def read_json(path)
+ Gitlab::Json.parse(IO.read(path))
+ end
+
+ def read_ndjson(path)
+ relations = []
+ File.foreach(path) do |line|
+ json = Gitlab::Json.parse(line)
+ relations << json
+ end
+ relations
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index 157cd408da9..47d7555c8f4 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -254,6 +254,16 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
end
+ it 'has multiple merge request assignees' do
+ expect(MergeRequest.find_by(title: 'MR1').assignees).to contain_exactly(@user, *@existing_members)
+ expect(MergeRequest.find_by(title: 'MR2').assignees).to be_empty
+ end
+
+ it 'has multiple merge request reviewers' do
+ expect(MergeRequest.find_by(title: 'MR1').reviewers).to contain_exactly(@user, *@existing_members)
+ expect(MergeRequest.find_by(title: 'MR2').reviewers).to be_empty
+ end
+
it 'has labels associated to label links, associated to issues' do
expect(Label.first.label_links.first.target).not_to be_nil
end
@@ -262,6 +272,11 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
expect(ProjectLabel.count).to eq(3)
end
+ it 'has merge request approvals' do
+ expect(MergeRequest.find_by(title: 'MR1').approvals.pluck(:user_id)).to contain_exactly(@user.id, *@existing_members.map(&:id))
+ expect(MergeRequest.find_by(title: 'MR2').approvals).to be_empty
+ end
+
it 'has no group labels' do
expect(GroupLabel.count).to eq(0)
end
@@ -589,7 +604,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it 'issue system note metadata restored successfully' do
note_content = 'created merge request !1 to address this issue'
- note = project.issues.first.notes.find { |n| n.note.match(/#{note_content}/)}
+ note = project.issues.first.notes.find { |n| n.note.match(/#{note_content}/) }
expect(note.noteable_type).to eq('Issue')
expect(note.system).to eq(true)
@@ -1085,35 +1100,13 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
end
end
- context 'when import_relation_object_persistence feature flag is enabled' do
- before do
- stub_feature_flags(import_relation_object_persistence: true)
- end
-
- context 'enable ndjson import' do
- it_behaves_like 'project tree restorer work properly', :legacy_reader, true
+ context 'enable ndjson import' do
+ it_behaves_like 'project tree restorer work properly', :legacy_reader, true
- it_behaves_like 'project tree restorer work properly', :ndjson_reader, true
- end
-
- context 'disable ndjson import' do
- it_behaves_like 'project tree restorer work properly', :legacy_reader, false
- end
+ it_behaves_like 'project tree restorer work properly', :ndjson_reader, true
end
- context 'when import_relation_object_persistence feature flag is disabled' do
- before do
- stub_feature_flags(import_relation_object_persistence: false)
- end
-
- context 'enable ndjson import' do
- it_behaves_like 'project tree restorer work properly', :legacy_reader, true
-
- it_behaves_like 'project tree restorer work properly', :ndjson_reader, true
- end
-
- context 'disable ndjson import' do
- it_behaves_like 'project tree restorer work properly', :legacy_reader, false
- end
+ context 'disable ndjson import' do
+ it_behaves_like 'project tree restorer work properly', :legacy_reader, false
end
end
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index ba781ae78b7..15108d28bf2 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -68,6 +68,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
it 'has merge request\'s milestones' do
expect(subject.first['milestone']).not_to be_empty
end
+
it 'has merge request\'s source branch SHA' do
expect(subject.first['source_branch_sha']).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0')
end
@@ -100,9 +101,30 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
expect(subject.first['notes'].first['author']).not_to be_empty
end
+ it 'has merge request approvals' do
+ approval = subject.first['approvals'].first
+
+ expect(approval).not_to be_nil
+ expect(approval['user_id']).to eq(user.id)
+ end
+
it 'has merge request resource label events' do
expect(subject.first['resource_label_events']).not_to be_empty
end
+
+ it 'has merge request assignees' do
+ reviewer = subject.first['merge_request_assignees'].first
+
+ expect(reviewer).not_to be_nil
+ expect(reviewer['user_id']).to eq(user.id)
+ end
+
+ it 'has merge request reviewers' do
+ reviewer = subject.first['merge_request_reviewers'].first
+
+ expect(reviewer).not_to be_nil
+ expect(reviewer['user_id']).to eq(user.id)
+ end
end
context 'with snippets' do
@@ -404,7 +426,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
context 'when streaming has to retry', :aggregate_failures do
let(:shared) { double('shared', export_path: exportable_path) }
- let(:logger) { Gitlab::Import::Logger.build }
+ let(:logger) { Gitlab::Export::Logger.build }
let(:serializer) { double('serializer') }
let(:error_class) { Net::OpenTimeout }
let(:info_params) do
@@ -468,7 +490,8 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
create(:label_link, label: group_label, target: issue)
create(:label_priority, label: group_label, priority: 1)
milestone = create(:milestone, project: project)
- merge_request = create(:merge_request, source_project: project, milestone: milestone)
+ merge_request = create(:merge_request, source_project: project, milestone: milestone, assignees: [user], reviewers: [user])
+ create(:approval, merge_request: merge_request, user: user)
ci_build = create(:ci_build, project: project, when: nil)
ci_build.pipeline.update!(project: project)
diff --git a/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb b/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb
new file mode 100644
index 00000000000..b1bc6b7eeaf
--- /dev/null
+++ b/spec/lib/gitlab/import_export/remote_stream_upload_spec.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ImportExport::RemoteStreamUpload do
+ include StubRequests
+
+ subject do
+ described_class.new(
+ download_url: download_url,
+ upload_url: upload_url,
+ options: {
+ upload_method: upload_method,
+ upload_content_type: upload_content_type
+ }
+ )
+ end
+
+ let(:download_url) { 'http://object-storage/file.txt' }
+ let(:upload_url) { 'http://example.com/file.txt' }
+ let(:upload_method) { :post }
+ let(:upload_content_type) { 'text/plain' }
+
+ describe '#execute' do
+ context 'when download request and upload request return 200' do
+ it 'uploads the downloaded content' do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:post, upload_url)
+
+ subject.execute
+
+ expect(
+ a_request(:post, upload_url).with(
+ body: 'ABC', headers: { 'Content-Length' => 3, 'Content-Type' => 'text/plain' }
+ )
+ ).to have_been_made
+ end
+ end
+
+ context 'when upload method is put' do
+ let(:upload_method) { :put }
+
+ it 'uploads using the put method' do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:put, upload_url)
+
+ subject.execute
+
+ expect(
+ a_request(:put, upload_url).with(
+ body: 'ABC', headers: { 'Content-Length' => 3, 'Content-Type' => 'text/plain' }
+ )
+ ).to have_been_made
+ end
+ end
+
+ context 'when download request does not return 200' do
+ it do
+ stub_request(:get, download_url).to_return(status: 404)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::ImportExport::RemoteStreamUpload::StreamError,
+ "Invalid response code while downloading file. Code: 404"
+ )
+ end
+ end
+
+ context 'when upload request does not returns 200' do
+ it do
+ stub_request(:get, download_url).to_return(status: 200, body: 'ABC', headers: { 'Content-Length' => 3 })
+ stub_request(:post, upload_url).to_return(status: 403)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::ImportExport::RemoteStreamUpload::StreamError,
+ "Invalid response code while uploading file. Code: 403"
+ )
+ end
+ end
+
+ context 'when download URL is a local address' do
+ let(:download_url) { 'http://127.0.0.1/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://127.0.0.1/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+
+ context 'when local requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when download URL is a local network' do
+ let(:download_url) { 'http://172.16.0.0/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://172.16.0.0/file.txt' is blocked: Requests to the local network are not allowed"
+ )
+ end
+
+ context 'when local network requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL is a local address' do
+ let(:upload_url) { 'http://127.0.0.1/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ stub_request(:get, download_url)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://127.0.0.1/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+
+ context 'when local requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL it is a request to local network' do
+ let(:upload_url) { 'http://172.16.0.0/file.txt' }
+
+ before do
+ stub_request(:get, download_url)
+ stub_request(:post, upload_url)
+ end
+
+ it 'raises error' do
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://172.16.0.0/file.txt' is blocked: Requests to the local network are not allowed"
+ )
+ end
+
+ context 'when local network requests are allowed' do
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
+ end
+
+ it 'raises does not error' do
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+
+ context 'when upload URL resolves to a local address' do
+ let(:upload_url) { 'http://example.com/file.txt' }
+
+ it 'raises error' do
+ stub_request(:get, download_url)
+ stub_full_request(upload_url, ip_address: '127.0.0.1', method: upload_method)
+
+ expect { subject.execute }.to raise_error(
+ Gitlab::HTTP::BlockedUrlError,
+ "URL 'http://example.com/file.txt' is blocked: Requests to localhost are not allowed"
+ )
+ end
+ end
+ end
+
+ describe Gitlab::ImportExport::RemoteStreamUpload::ChunkStream do
+ describe 'StringIO#copy_stream compatibility' do
+ it 'copies all chunks' do
+ chunks = %w[ABC EFD].to_enum
+ chunk_stream = described_class.new(chunks)
+ new_stream = StringIO.new
+
+ IO.copy_stream(chunk_stream, new_stream)
+ new_stream.rewind
+
+ expect(new_stream.read).to eq('ABCEFD')
+ end
+
+ context 'with chunks smaller and bigger than buffer size' do
+ before do
+ stub_const('Gitlab::ImportExport::RemoteStreamUpload::ChunkStream::DEFAULT_BUFFER_SIZE', 4)
+ end
+
+ it 'copies all chunks' do
+ chunks = %w[A BC DEF GHIJ KLMNOPQ RSTUVWXYZ].to_enum
+ chunk_stream = described_class.new(chunks)
+ new_stream = StringIO.new
+
+ IO.copy_stream(chunk_stream, new_stream)
+ new_stream.rewind
+
+ expect(new_stream.read).to eq('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index bd60bb53d49..6cfc24a8996 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -521,7 +521,6 @@ Project:
- star_count
- ci_id
- shared_runners_enabled
-- build_coverage_regex
- build_allow_git_fetchs
- build_timeout
- pending_delete
@@ -584,6 +583,9 @@ ProjectFeature:
- security_and_compliance_access_level
- container_registry_access_level
- package_registry_access_level
+- environments_access_level
+- feature_flags_access_level
+- releases_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
@@ -741,6 +743,14 @@ MergeRequestAssignee:
- id
- user_id
- merge_request_id
+- created_at
+- state
+MergeRequestReviewer:
+- id
+- user_id
+- merge_request_id
+- created_at
+- state
ProjectMetricsSetting:
- project_id
- external_dashboard_url
@@ -903,3 +913,7 @@ MergeRequest::CleanupSchedule:
- completed_at
- created_at
- updated_at
+Approval:
+ - user_id
+ - created_at
+ - updated_at
diff --git a/spec/lib/gitlab/import_export/shared_spec.rb b/spec/lib/gitlab/import_export/shared_spec.rb
index 1945156ca59..408ed3a2176 100644
--- a/spec/lib/gitlab/import_export/shared_spec.rb
+++ b/spec/lib/gitlab/import_export/shared_spec.rb
@@ -68,12 +68,18 @@ RSpec.describe Gitlab::ImportExport::Shared do
expect(subject.errors).to eq(['Error importing into [FILTERED] Permission denied @ unlink_internal - [FILTERED]'])
end
- it 'updates the import JID' do
+ it 'tracks exception' do
import_state = create(:import_state, project: project, jid: 'jid-test')
expect(Gitlab::ErrorTracking)
.to receive(:track_exception)
- .with(error, hash_including(import_jid: import_state.jid))
+ .with(error, hash_including(
+ importer: 'Import/Export',
+ project_id: project.id,
+ project_name: project.name,
+ project_path: project.full_path,
+ import_jid: import_state.jid
+ ))
subject.error(error)
end
diff --git a/spec/lib/gitlab/import_export/version_checker_spec.rb b/spec/lib/gitlab/import_export/version_checker_spec.rb
index 9e69e04b17c..14c62edb786 100644
--- a/spec/lib/gitlab/import_export/version_checker_spec.rb
+++ b/spec/lib/gitlab/import_export/version_checker_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Gitlab::ImportExport::VersionChecker do
end
context 'newer version' do
- let(:version) { '900.0'}
+ let(:version) { '900.0' }
it 'returns false if export version is newer' do
expect(described_class.check!(shared: shared)).to be false
diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb
index 79d626386d4..4fa9079144d 100644
--- a/spec/lib/gitlab/instrumentation_helper_spec.rb
+++ b/spec/lib/gitlab/instrumentation_helper_spec.rb
@@ -195,6 +195,28 @@ RSpec.describe Gitlab::InstrumentationHelper do
expect(payload[:uploaded_file_size_bytes]).to eq(uploaded_file.size)
end
end
+
+ context 'when an api call to the search api is made' do
+ before do
+ Gitlab::Instrumentation::GlobalSearchApi.set_information(
+ type: 'basic',
+ level: 'global',
+ scope: 'issues',
+ search_duration_s: 0.1
+ )
+ end
+
+ it 'adds search data' do
+ subject
+
+ expect(payload).to include({
+ 'meta.search.type' => 'basic',
+ 'meta.search.level' => 'global',
+ 'meta.search.scope' => 'issues',
+ global_search_duration_s: 0.1
+ })
+ end
+ end
end
describe 'duration calculations' do
diff --git a/spec/lib/gitlab/jira/dvcs_spec.rb b/spec/lib/gitlab/jira/dvcs_spec.rb
index 09e777b38ea..76d81343875 100644
--- a/spec/lib/gitlab/jira/dvcs_spec.rb
+++ b/spec/lib/gitlab/jira/dvcs_spec.rb
@@ -24,8 +24,8 @@ RSpec.describe Gitlab::Jira::Dvcs do
end
describe '.encode_project_name' do
- let(:group) { create(:group)}
- let(:project) { create(:project, group: group)}
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
context 'root group' do
it 'returns project path' do
@@ -34,7 +34,7 @@ RSpec.describe Gitlab::Jira::Dvcs do
end
context 'nested group' do
- let(:group) { create(:group, :nested)}
+ let(:group) { create(:group, :nested) }
it 'returns encoded project full path' do
expect(described_class.encode_project_name(project)).to eq(described_class.encode_slash(project.full_path))
diff --git a/spec/lib/gitlab/jira_import/issues_importer_spec.rb b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
index 1bc052ee0b6..a2a482dde7c 100644
--- a/spec/lib/gitlab/jira_import/issues_importer_spec.rb
+++ b/spec/lib/gitlab/jira_import/issues_importer_spec.rb
@@ -40,7 +40,7 @@ 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)] }
+ let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2), jira_issue.new(3)] }
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
@@ -125,6 +125,47 @@ 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/kubernetes/rollout_status_spec.rb b/spec/lib/gitlab/kubernetes/rollout_status_spec.rb
index 8ed9fdd799c..21d345f0739 100644
--- a/spec/lib/gitlab/kubernetes/rollout_status_spec.rb
+++ b/spec/lib/gitlab/kubernetes/rollout_status_spec.rb
@@ -213,7 +213,7 @@ RSpec.describe Gitlab::Kubernetes::RolloutStatus do
let(:specs) { specs_half_finished }
- it { is_expected.to be_falsy}
+ it { is_expected.to be_falsy }
end
end
diff --git a/spec/lib/gitlab/mail_room/mail_room_spec.rb b/spec/lib/gitlab/mail_room/mail_room_spec.rb
index 06a25be757e..0c2c9b89005 100644
--- a/spec/lib/gitlab/mail_room/mail_room_spec.rb
+++ b/spec/lib/gitlab/mail_room/mail_room_spec.rb
@@ -246,7 +246,7 @@ RSpec.describe Gitlab::MailRoom do
redis_url: "localhost",
redis_db: 99,
namespace: "resque:gitlab",
- queue: "email_receiver",
+ queue: "default",
worker: "EmailReceiverWorker",
sentinels: [{ host: "localhost", port: 1234 }]
}
@@ -259,7 +259,7 @@ RSpec.describe Gitlab::MailRoom do
redis_url: "localhost",
redis_db: 99,
namespace: "resque:gitlab",
- queue: "service_desk_email_receiver",
+ queue: "default",
worker: "ServiceDeskEmailReceiverWorker",
sentinels: [{ host: "localhost", port: 1234 }]
}
diff --git a/spec/lib/gitlab/memory/jemalloc_spec.rb b/spec/lib/gitlab/memory/jemalloc_spec.rb
index 8847516b52c..482ac6e5802 100644
--- a/spec/lib/gitlab/memory/jemalloc_spec.rb
+++ b/spec/lib/gitlab/memory/jemalloc_spec.rb
@@ -28,11 +28,12 @@ RSpec.describe Gitlab::Memory::Jemalloc do
describe '.dump_stats' do
it 'writes stats JSON file' do
- described_class.dump_stats(path: outdir, format: format)
+ file_path = described_class.dump_stats(path: outdir, format: format)
file = Dir.entries(outdir).find { |e| e.match(/jemalloc_stats\.#{$$}\.\d+\.json$/) }
expect(file).not_to be_nil
- expect(File.read(File.join(outdir, file))).to eq(output)
+ expect(file_path).to eq(File.join(outdir, file))
+ expect(File.read(file_path)).to eq(output)
end
end
end
@@ -52,12 +53,22 @@ RSpec.describe Gitlab::Memory::Jemalloc do
end
describe '.dump_stats' do
- it 'writes stats text file' do
- described_class.dump_stats(path: outdir, format: format)
+ shared_examples 'writes stats text file' do |filename_label, filename_pattern|
+ it do
+ described_class.dump_stats(path: outdir, format: format, filename_label: filename_label)
+
+ file = Dir.entries(outdir).find { |e| e.match(filename_pattern) }
+ expect(file).not_to be_nil
+ expect(File.read(File.join(outdir, file))).to eq(output)
+ end
+ end
- file = Dir.entries(outdir).find { |e| e.match(/jemalloc_stats\.#{$$}\.\d+\.txt$/) }
- expect(file).not_to be_nil
- expect(File.read(File.join(outdir, file))).to eq(output)
+ context 'when custom filename label is passed' do
+ include_examples 'writes stats text file', 'puma_0', /jemalloc_stats\.#{$$}\.puma_0\.\d+\.txt$/
+ end
+
+ context 'when custom filename label is not passed' do
+ include_examples 'writes stats text file', nil, /jemalloc_stats\.#{$$}\.\d+\.txt$/
end
end
end
diff --git a/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb b/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb
new file mode 100644
index 00000000000..53fae48776b
--- /dev/null
+++ b/spec/lib/gitlab/memory/reports/jemalloc_stats_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::Reports::JemallocStats do
+ let(:reports_dir) { '/empty-dir' }
+ let(:jemalloc_stats) { described_class.new(reports_path: reports_dir) }
+
+ describe '.run' do
+ context 'when :report_jemalloc_stats ops FF is enabled' do
+ let(:worker_id) { 'puma_1' }
+ let(:report_name) { 'report.json' }
+ let(:report_path) { File.join(reports_dir, report_name) }
+
+ before do
+ allow(Prometheus::PidProvider).to receive(:worker_id).and_return(worker_id)
+ end
+
+ it 'invokes Jemalloc.dump_stats and returns file path' do
+ expect(Gitlab::Memory::Jemalloc)
+ .to receive(:dump_stats).with(path: reports_dir, filename_label: worker_id).and_return(report_path)
+
+ expect(jemalloc_stats.run).to eq(report_path)
+ end
+
+ describe 'reports cleanup' do
+ let_it_be(:outdir) { Dir.mktmpdir }
+
+ let(:jemalloc_stats) { described_class.new(reports_path: outdir) }
+
+ before do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_JEMALLOC_MAX_REPORTS_STORED', 3)
+ allow(Gitlab::Memory::Jemalloc).to receive(:dump_stats)
+ end
+
+ after do
+ FileUtils.rm_f(outdir)
+ end
+
+ context 'when number of reports exceeds `max_reports_stored`' do
+ let_it_be(:reports) do
+ now = Time.current
+
+ (1..5).map do |i|
+ Tempfile.new("jemalloc_stats.#{i}.worker_#{i}.#{Time.current.to_i}.json", outdir).tap do |f|
+ FileUtils.touch(f, mtime: (now + i.second).to_i)
+ end
+ end
+ end
+
+ after do
+ reports.each do |f|
+ f.close
+ f.unlink
+ rescue Errno::ENOENT
+ # Some of the files are already unlinked by the code we test; Ignore
+ end
+ end
+
+ it 'keeps only `max_reports_stored` total newest files' do
+ expect { jemalloc_stats.run }
+ .to change { Dir.entries(outdir).count { |e| e.match(/jemalloc_stats.*/) } }
+ .from(5).to(3)
+
+ # Keeps only the newest reports
+ expect(reports.last(3).all? { |r| File.exist?(r) }).to be true
+ end
+ end
+
+ context 'when number of reports does not exceed `max_reports_stored`' do
+ let_it_be(:reports) do
+ now = Time.current
+
+ (1..3).map do |i|
+ Tempfile.new("jemalloc_stats.#{i}.worker_#{i}.#{Time.current.to_i}.json", outdir).tap do |f|
+ FileUtils.touch(f, mtime: (now + i.second).to_i)
+ end
+ end
+ end
+
+ after do
+ reports.each do |f|
+ f.close
+ f.unlink
+ end
+ end
+
+ it 'does not remove any reports' do
+ expect { jemalloc_stats.run }
+ .not_to change { Dir.entries(outdir).count { |e| e.match(/jemalloc_stats.*/) } }
+ end
+ end
+ end
+ end
+
+ context 'when :report_jemalloc_stats ops FF is disabled' do
+ before do
+ stub_feature_flags(report_jemalloc_stats: false)
+ end
+
+ it 'does not run the report and returns nil' do
+ expect(Gitlab::Memory::Jemalloc).not_to receive(:dump_stats)
+
+ expect(jemalloc_stats.run).to be_nil
+ end
+ end
+ end
+
+ describe '.active?' do
+ subject(:active) { jemalloc_stats.active? }
+
+ context 'when :report_jemalloc_stats ops FF is enabled' do
+ it { is_expected.to be true }
+ end
+
+ context 'when :report_jemalloc_stats ops FF is disabled' do
+ before do
+ stub_feature_flags(report_jemalloc_stats: false)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/reports_daemon_spec.rb b/spec/lib/gitlab/memory/reports_daemon_spec.rb
new file mode 100644
index 00000000000..c9562470971
--- /dev/null
+++ b/spec/lib/gitlab/memory/reports_daemon_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::ReportsDaemon do
+ let(:daemon) { described_class.new }
+
+ describe '#run_thread' do
+ let(:report_duration_counter) { instance_double(::Prometheus::Client::Counter) }
+ let(:file_size) { 1_000_000 }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:counter).and_return(report_duration_counter)
+ allow(report_duration_counter).to receive(:increment)
+
+ # make sleep no-op
+ allow(daemon).to receive(:sleep) {}
+
+ # let alive return 3 times: true, true, false
+ allow(daemon).to receive(:alive).and_return(true, true, false)
+
+ 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 '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(
+ hash_including(
+ :duration_s,
+ :cpu_s,
+ perf_report_size_bytes: file_size,
+ message: 'finished',
+ pid: Process.pid,
+ worker_id: 'worker_1',
+ perf_report: 'jemalloc_stats'
+ )).twice
+
+ daemon.send(:run_thread)
+ end
+
+ context 'when the report object returns invalid file path' do
+ before do
+ allow(File).to receive(:size).with(/#{daemon.reports_path}.*\.json/).and_raise(Errno::ENOENT)
+ end
+
+ it 'logs `0` as `perf_report_size_bytes`' do
+ 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
+ # We configure it with new reports classes which are not yet defined so we cannot make this an instance_double.
+ active_report_1 = double("Active Report 1", active?: true)
+ active_report_2 = double("Active Report 2", active?: true)
+ inactive_report = double("Inactive Report", active?: false)
+ # rubocop: enable RSpec/VerifiedDoubles
+
+ 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(inactive_report).not_to receive(:run)
+
+ daemon.send(:run_thread)
+ end
+
+ context 'sleep timers logic' do
+ it 'wakes up every (fixed interval + defined delta), sleeps between reports each cycle' do
+ stub_env('GITLAB_DIAGNOSTIC_REPORTS_SLEEP_MAX_DELTA_S', 1) # rand(1) == 0, so we will have fixed sleep interval
+ daemon = described_class.new
+ allow(daemon).to receive(:alive).and_return(true, true, false)
+
+ 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
+ expect(daemon).to receive(:sleep).with(described_class::DEFAULT_SLEEP_BETWEEN_REPORTS_S).ordered
+
+ daemon.send(:run_thread)
+ end
+ end
+ end
+
+ describe '#stop_working' do
+ it 'changes :alive to false' do
+ expect { daemon.send(:stop_working) }.to change { daemon.send(:alive) }.from(true).to(false)
+ end
+ end
+
+ context 'timer intervals settings' do
+ context 'when no settings are set in the environment' do
+ it 'uses defaults' do
+ daemon = described_class.new
+
+ expect(daemon.sleep_s).to eq(described_class::DEFAULT_SLEEP_S)
+ expect(daemon.sleep_max_delta_s).to eq(described_class::DEFAULT_SLEEP_MAX_DELTA_S)
+ expect(daemon.sleep_between_reports_s).to eq(described_class::DEFAULT_SLEEP_BETWEEN_REPORTS_S)
+ expect(daemon.reports_path).to eq(described_class::DEFAULT_REPORTS_PATH)
+ end
+ end
+
+ context 'when settings are passed through the environment' do
+ before 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')
+ end
+
+ it 'uses provided values' do
+ daemon = described_class.new
+
+ 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')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog_spec.rb b/spec/lib/gitlab/memory/watchdog_spec.rb
index 8b82078bcb9..010f6884df3 100644
--- a/spec/lib/gitlab/memory/watchdog_spec.rb
+++ b/spec/lib/gitlab/memory/watchdog_spec.rb
@@ -14,32 +14,57 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
let(:sleep_time) { 0.1 }
let(:max_heap_fragmentation) { 0.2 }
+ # Tests should set this to control the number of loop iterations in `call`.
+ let(:watchdog_iterations) { 1 }
+
subject(:watchdog) do
described_class.new(handler: handler, logger: logger, sleep_time_seconds: sleep_time,
- max_strikes: max_strikes, max_heap_fragmentation: max_heap_fragmentation)
+ max_strikes: max_strikes, max_heap_fragmentation: max_heap_fragmentation).tap do |instance|
+ # We need to defuse `sleep` and stop the internal loop after N iterations.
+ iterations = 0
+ expect(instance).to receive(:sleep) do
+ instance.stop if (iterations += 1) >= watchdog_iterations
+ end.at_most(watchdog_iterations)
+ end
+ 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_heap_frag_violations_total, anything, anything)
+ .and_return(heap_frag_violations_counter)
+ allow(Gitlab::Metrics).to receive(:counter)
+ .with(:gitlab_memwd_heap_frag_violations_handled_total, anything, anything)
+ .and_return(heap_frag_violations_handled_counter)
+
+ allow(heap_frag_limit_gauge).to receive(:set)
+ allow(heap_frag_violations_counter).to receive(:increment)
+ allow(heap_frag_violations_handled_counter).to receive(:increment)
end
before do
+ stub_prometheus_metrics
+
allow(handler).to receive(:on_high_heap_fragmentation).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)
- end
- after do
- watchdog.stop
+ allow(::Prometheus::PidProvider).to receive(:worker_id).and_return('worker_1')
end
- context 'when starting up' do
+ context 'when created' do
let(:fragmentation) { 0 }
let(:max_strikes) { 0 }
it 'sets the heap fragmentation limit gauge' do
- allow(Gitlab::Metrics).to receive(:gauge).and_return(heap_frag_limit_gauge)
-
expect(heap_frag_limit_gauge).to receive(:set).with({}, max_heap_fragmentation)
+
+ watchdog
end
context 'when no settings are set in the environment' do
@@ -76,77 +101,54 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
it 'does not signal the handler' do
expect(handler).not_to receive(:on_high_heap_fragmentation)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
end
context 'when process exceeds heap fragmentation threshold permanently' do
let(:fragmentation) { max_heap_fragmentation + 0.1 }
-
- before do
- allow(Gitlab::Metrics).to receive(:counter)
- .with(:gitlab_memwd_heap_frag_violations_total, anything, anything)
- .and_return(heap_frag_violations_counter)
- allow(Gitlab::Metrics).to receive(:counter)
- .with(:gitlab_memwd_heap_frag_violations_handled_total, anything, anything)
- .and_return(heap_frag_violations_handled_counter)
- allow(heap_frag_violations_counter).to receive(:increment)
- allow(heap_frag_violations_handled_counter).to receive(:increment)
- end
+ let(:max_strikes) { 3 }
context 'when process has not exceeded allowed number of strikes' do
- let(:max_strikes) { 10 }
+ let(:watchdog_iterations) { max_strikes }
it 'does not signal the handler' do
expect(handler).not_to receive(:on_high_heap_fragmentation)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
it 'does not log any events' do
expect(logger).not_to receive(:warn)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
it 'increments the violations counter' do
- expect(heap_frag_violations_counter).to receive(:increment)
-
- watchdog.start
+ expect(heap_frag_violations_counter).to receive(:increment).exactly(watchdog_iterations)
- sleep sleep_time * 3
+ watchdog.call
end
it 'does not increment violations handled counter' do
expect(heap_frag_violations_handled_counter).not_to receive(:increment)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
end
context 'when process exceeds the allowed number of strikes' do
- let(:max_strikes) { 1 }
+ let(:watchdog_iterations) { max_strikes + 1 }
it 'signals the handler and resets strike counter' do
expect(handler).to receive(:on_high_heap_fragmentation).and_return(true)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
expect(watchdog.strikes).to eq(0)
end
it 'logs the event' do
- expect(::Prometheus::PidProvider).to receive(:worker_id).at_least(:once).and_return('worker_1')
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',
@@ -161,18 +163,14 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
memwd_rss_bytes: 1024
})
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
it 'increments both the violations and violations handled counters' do
- expect(heap_frag_violations_counter).to receive(:increment)
+ expect(heap_frag_violations_counter).to receive(:increment).exactly(watchdog_iterations)
expect(heap_frag_violations_handled_counter).to receive(:increment)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
context 'when enforce_memory_watchdog ops toggle is off' do
@@ -186,35 +184,31 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
receive(:on_high_heap_fragmentation).with(fragmentation).and_return(true)
)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
end
- end
-
- context 'when handler result is true' do
- let(:max_strikes) { 1 }
- it 'considers the event handled and stops itself' do
- expect(handler).to receive(:on_high_heap_fragmentation).once.and_return(true)
+ context 'when handler result is true' do
+ it 'considers the event handled and stops itself' do
+ expect(handler).to receive(:on_high_heap_fragmentation).once.and_return(true)
+ expect(logger).to receive(:info).with(hash_including(message: 'stopped'))
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
+ end
end
- end
-
- context 'when handler result is false' do
- let(:max_strikes) { 1 }
- it 'keeps running' do
- # Return true the third time to terminate the daemon.
- expect(handler).to receive(:on_high_heap_fragmentation).and_return(false, false, true)
+ context 'when handler result is false' do
+ let(:max_strikes) { 0 } # to make sure the handler fires each iteration
+ let(:watchdog_iterations) { 3 }
- watchdog.start
+ it 'keeps running' do
+ expect(heap_frag_violations_counter).to receive(:increment).exactly(watchdog_iterations)
+ expect(heap_frag_violations_handled_counter).to receive(:increment).exactly(watchdog_iterations)
+ # Return true the third time to terminate the daemon.
+ expect(handler).to receive(:on_high_heap_fragmentation).and_return(false, false, true)
- sleep sleep_time * 4
+ watchdog.call
+ end
end
end
end
@@ -222,6 +216,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
context 'when process exceeds heap fragmentation threshold temporarily' do
let(:fragmentation) { max_heap_fragmentation }
let(:max_strikes) { 1 }
+ let(:watchdog_iterations) { 4 }
before do
allow(Gitlab::Metrics::Memory).to receive(:gc_heap_fragmentation).and_return(
@@ -235,9 +230,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
it 'does not signal the handler' do
expect(handler).not_to receive(:on_high_heap_fragmentation)
- watchdog.start
-
- sleep sleep_time * 4
+ watchdog.call
end
end
@@ -252,9 +245,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, :prometheus do
it 'does not monitor heap fragmentation' do
expect(Gitlab::Metrics::Memory).not_to receive(:gc_heap_fragmentation)
- watchdog.start
-
- sleep sleep_time * 3
+ watchdog.call
end
end
end
diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb
index 83bee84df99..2e48070cb4f 100644
--- a/spec/lib/gitlab/metrics/background_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/background_transaction_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::Metrics::BackgroundTransaction do
end
it 'removes the transaction from the current thread upon completion' do
- transaction.run { }
+ transaction.run {}
expect(Thread.current[described_class::THREAD_KEY]).to be_nil
end
diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb
index 06ce58a9e84..d6590efcf4f 100644
--- a/spec/lib/gitlab/metrics/web_transaction_spec.rb
+++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::Metrics::WebTransaction do
end
it 'removes the transaction from the current thread upon completion' do
- transaction.run { }
+ transaction.run {}
expect(Thread.current[described_class::THREAD_KEY]).to be_nil
expect(described_class.current).to be_nil
diff --git a/spec/lib/gitlab/middleware/compressed_json_spec.rb b/spec/lib/gitlab/middleware/compressed_json_spec.rb
index a07cd49c572..6d49ab58d5d 100644
--- a/spec/lib/gitlab/middleware/compressed_json_spec.rb
+++ b/spec/lib/gitlab/middleware/compressed_json_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Gitlab::Middleware::CompressedJson do
describe '#call' do
context 'with collector route' do
- let(:path) { '/api/v4/error_tracking/collector/1/store'}
+ let(:path) { '/api/v4/error_tracking/collector/1/store' }
it_behaves_like 'decompress middleware'
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::Middleware::CompressedJson do
end
context 'with collector route under relative url' do
- let(:path) { '/gitlab/api/v4/error_tracking/collector/1/store'}
+ let(:path) { '/gitlab/api/v4/error_tracking/collector/1/store' }
before do
stub_config_setting(relative_url_root: '/gitlab')
@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Middleware::CompressedJson do
let(:body_limit) { Gitlab::Middleware::CompressedJson::MAXIMUM_BODY_SIZE }
let(:decompressed_input) { 'a' * (body_limit + 100) }
let(:input) { ActiveSupport::Gzip.compress(decompressed_input) }
- let(:path) { '/api/v4/error_tracking/collector/1/envelope'}
+ let(:path) { '/api/v4/error_tracking/collector/1/envelope' }
it 'reads only limited size' do
expect(middleware.call(env))
diff --git a/spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb b/spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb
index e6815a46a56..91c030a0f45 100644
--- a/spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb
+++ b/spec/lib/gitlab/middleware/sidekiq_web_static_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Gitlab::Middleware::SidekiqWebStatic do
end
context 'with an /admin/sidekiq route' do
- let(:path) { '/admin/sidekiq/javascripts/application.js'}
+ let(:path) { '/admin/sidekiq/javascripts/application.js' }
it 'deletes the HTTP_X_SENDFILE_TYPE header' do
expect(app).to receive(:call)
diff --git a/spec/lib/gitlab/octokit/middleware_spec.rb b/spec/lib/gitlab/octokit/middleware_spec.rb
index bc4d95738c7..92e424978ff 100644
--- a/spec/lib/gitlab/octokit/middleware_spec.rb
+++ b/spec/lib/gitlab/octokit/middleware_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Octokit::Middleware do
it_behaves_like 'Public URL'
end
- context 'when the URL is a localhost adresss' do
+ context 'when the URL is a localhost address' do
let(:env) { { url: 'http://127.0.0.1' } }
context 'when localhost requests are not allowed' do
diff --git a/spec/lib/gitlab/otp_key_rotator_spec.rb b/spec/lib/gitlab/otp_key_rotator_spec.rb
index e328b190db4..e3b9f006b19 100644
--- a/spec/lib/gitlab/otp_key_rotator_spec.rb
+++ b/spec/lib/gitlab/otp_key_rotator_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe Gitlab::OtpKeyRotator do
it 'stores the calculated values in a spreadsheet' do
rotation
- expect(data).to match_array(users.map {|u| build_row(u) })
+ expect(data).to match_array(users.map { |u| build_row(u) })
end
context 'new key is too short' do
diff --git a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
index dcb8138bdde..0bafd436bd0 100644
--- a/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
+++ b/spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb
@@ -126,5 +126,19 @@ RSpec.describe Gitlab::Pagination::GitalyKeysetPager do
end
end
end
+
+ context 'with "none" pagination option' do
+ let(:expected_result) { double(:result) }
+ let(:query) { { pagination: 'none' } }
+
+ it 'uses offset pagination' do
+ expect(finder).to receive(:execute).with(gitaly_pagination: false).and_return(expected_result)
+ expect(Kaminari).not_to receive(:paginate_array)
+ expect(Gitlab::Pagination::OffsetPagination).not_to receive(:new)
+
+ actual_result = pager.paginate(finder)
+ expect(actual_result).to eq(expected_result)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/pagination/keyset_spec.rb b/spec/lib/gitlab/pagination/keyset_spec.rb
index 81dc40b35d5..8885e684d8a 100644
--- a/spec/lib/gitlab/pagination/keyset_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Pagination::Keyset do
describe '.available?' do
subject { described_class }
- let(:request_context) { double("request context", page: page)}
+ let(:request_context) { double("request context", page: page) }
let(:page) { double("page", order_by: order_by) }
shared_examples_for 'keyset pagination is available' do
diff --git a/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb
index c368b349a3c..a444e7fdf47 100644
--- a/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb
+++ b/spec/lib/gitlab/phabricator_import/conduit/response_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::PhabricatorImport::Conduit::Response do
- let(:response) { described_class.new(Gitlab::Json.parse(fixture_file('phabricator_responses/maniphest.search.json')))}
+ let(:response) { described_class.new(Gitlab::Json.parse(fixture_file('phabricator_responses/maniphest.search.json'))) }
let(:error_response) { described_class.new(Gitlab::Json.parse(fixture_file('phabricator_responses/auth_failed.json'))) }
describe '.parse!' do
diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb
index 89ddde4a01d..9083c5625d4 100644
--- a/spec/lib/gitlab/prometheus_client_spec.rb
+++ b/spec/lib/gitlab/prometheus_client_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe Gitlab::PrometheusClient do
end
describe 'failure to reach a provided prometheus url' do
- let(:prometheus_url) {"https://prometheus.invalid.example.com/api/v1/query?query=1"}
+ let(:prometheus_url) { "https://prometheus.invalid.example.com/api/v1/query?query=1" }
shared_examples 'exceptions are raised' do
Gitlab::HTTP::HTTP_ERRORS.each do |error|
diff --git a/spec/lib/gitlab/quick_actions/extractor_spec.rb b/spec/lib/gitlab/quick_actions/extractor_spec.rb
index c040a70e403..e2f289041ce 100644
--- a/spec/lib/gitlab/quick_actions/extractor_spec.rb
+++ b/spec/lib/gitlab/quick_actions/extractor_spec.rb
@@ -7,10 +7,10 @@ RSpec.describe Gitlab::QuickActions::Extractor do
Class.new do
include Gitlab::QuickActions::Dsl
- command(:reopen, :open) { }
- command(:assign) { }
- command(:labels) { }
- command(:power) { }
+ command(:reopen, :open) {}
+ command(:assign) {}
+ command(:labels) {}
+ command(:power) {}
command(:noop_command)
substitution(:substitution) { 'foo' }
substitution :shrug do |comment|
diff --git a/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb b/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb
index bd167ee2e3e..8151519ddec 100644
--- a/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb
+++ b/spec/lib/gitlab/rack_attack/instrumented_cache_store_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Gitlab::RackAttack::InstrumentedCacheStore do
let(:store) { ::ActiveSupport::Cache::NullStore.new }
- subject { described_class.new(upstream_store: store)}
+ subject { described_class.new(upstream_store: store) }
where(:operation, :params, :test_proc) do
:fetch | [:key] | ->(s) { s.fetch(:key) }
diff --git a/spec/lib/gitlab/rack_attack/user_allowlist_spec.rb b/spec/lib/gitlab/rack_attack/user_allowlist_spec.rb
index aa604dfab71..1b6fa584e3e 100644
--- a/spec/lib/gitlab/rack_attack/user_allowlist_spec.rb
+++ b/spec/lib/gitlab/rack_attack/user_allowlist_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::RackAttack::UserAllowlist do
using RSpec::Parameterized::TableSyntax
- subject { described_class.new(input)}
+ subject { described_class.new(input) }
where(:input, :elements) do
nil | []
diff --git a/spec/lib/gitlab/redis/cache_spec.rb b/spec/lib/gitlab/redis/cache_spec.rb
index 31141ac1139..1f0ebbe107f 100644
--- a/spec/lib/gitlab/redis/cache_spec.rb
+++ b/spec/lib/gitlab/redis/cache_spec.rb
@@ -15,4 +15,16 @@ RSpec.describe Gitlab::Redis::Cache do
expect(subject.send(:raw_config_hash)).to eq(url: 'redis://localhost:6380' )
end
end
+
+ describe '.active_support_config' do
+ it 'has a default ttl of 2 weeks' do
+ expect(described_class.active_support_config[:expires_in]).to eq(2.weeks)
+ end
+
+ it 'allows configuring the TTL through an env variable' do
+ stub_env('GITLAB_RAILS_CACHE_DEFAULT_TTL_SECONDS' => '86400')
+
+ expect(described_class.active_support_config[:expires_in]).to eq(1.day)
+ end
+ end
end
diff --git a/spec/lib/gitlab/redis/hll_spec.rb b/spec/lib/gitlab/redis/hll_spec.rb
index e452e5b2f52..9cd339239bb 100644
--- a/spec/lib/gitlab/redis/hll_spec.rb
+++ b/spec/lib/gitlab/redis/hll_spec.rb
@@ -64,10 +64,10 @@ RSpec.describe Gitlab::Redis::HLL, :clean_gitlab_redis_shared_state do
let(:event_2020_33) { '2020-33-{expand_vulnerabilities}' }
let(:event_2020_34) { '2020-34-{expand_vulnerabilities}' }
- let(:entity1) { 'user_id_1'}
- let(:entity2) { 'user_id_2'}
- let(:entity3) { 'user_id_3'}
- let(:entity4) { 'user_id_4'}
+ let(:entity1) { 'user_id_1' }
+ let(:entity2) { 'user_id_2' }
+ let(:entity3) { 'user_id_3' }
+ let(:entity4) { 'user_id_4' }
before do
track_event(event_2020_32, entity1)
diff --git a/spec/lib/gitlab/redis/multi_store_spec.rb b/spec/lib/gitlab/redis/multi_store_spec.rb
index 50ebf43a05e..ef8549548d7 100644
--- a/spec/lib/gitlab/redis/multi_store_spec.rb
+++ b/spec/lib/gitlab/redis/multi_store_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
let_it_be(:primary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
let_it_be(:secondary_store) { create_redis_store(redis_store_class.params, db: secondary_db, serializer: nil) }
let_it_be(:instance_name) { 'TestStore' }
- let_it_be(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+ let_it_be(:multi_store) { described_class.new(primary_store, secondary_store, instance_name) }
subject { multi_store.send(name, *args) }
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
context 'when primary_store is nil' do
- let(:multi_store) { described_class.new(nil, secondary_store, instance_name)}
+ let(:multi_store) { described_class.new(nil, secondary_store, instance_name) }
it 'fails with exception' do
expect { multi_store }.to raise_error(ArgumentError, /primary_store is required/)
@@ -46,7 +46,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
context 'when secondary_store is nil' do
- let(:multi_store) { described_class.new(primary_store, nil, instance_name)}
+ let(:multi_store) { described_class.new(primary_store, nil, instance_name) }
it 'fails with exception' do
expect { multi_store }.to raise_error(ArgumentError, /secondary_store is required/)
@@ -55,7 +55,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
context 'when instance_name is nil' do
let(:instance_name) { nil }
- let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+ let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name) }
it 'fails with exception' do
expect { multi_store }.to raise_error(ArgumentError, /instance_name is required/)
@@ -111,8 +111,8 @@ RSpec.describe Gitlab::Redis::MultiStore do
context 'with READ redis commands' do
let_it_be(:key1) { "redis:{1}:key_a" }
let_it_be(:key2) { "redis:{1}:key_b" }
- let_it_be(:value1) { "redis_value1"}
- let_it_be(:value2) { "redis_value2"}
+ let_it_be(:value1) { "redis_value1" }
+ let_it_be(:value2) { "redis_value2" }
let_it_be(:skey) { "redis:set:key" }
let_it_be(:keys) { [key1, key2] }
let_it_be(:values) { [value1, value2] }
@@ -330,7 +330,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
context 'with both primary and secondary store using same redis instance' do
let(:primary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
let(:secondary_store) { create_redis_store(redis_store_class.params, db: primary_db, serializer: nil) }
- let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+ let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name) }
it_behaves_like 'secondary store'
end
@@ -356,8 +356,8 @@ RSpec.describe Gitlab::Redis::MultiStore do
context 'with WRITE redis commands' do
let_it_be(:key1) { "redis:{1}:key_a" }
let_it_be(:key2) { "redis:{1}:key_b" }
- let_it_be(:value1) { "redis_value1"}
- let_it_be(:value2) { "redis_value2"}
+ let_it_be(:value1) { "redis_value1" }
+ let_it_be(:value2) { "redis_value2" }
let_it_be(:key1_value1) { [key1, value1] }
let_it_be(:key1_value2) { [key1, value2] }
let_it_be(:ttl) { 10 }
@@ -395,7 +395,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
with_them do
describe "#{name}" do
- let(:expected_args) {args || no_args }
+ let(:expected_args) { args || no_args }
before do
allow(primary_store).to receive(name).and_call_original
@@ -496,8 +496,8 @@ RSpec.describe Gitlab::Redis::MultiStore do
RSpec.shared_examples_for 'pipelined command' do |name|
let_it_be(:key1) { "redis:{1}:key_a" }
- let_it_be(:value1) { "redis_value1"}
- let_it_be(:value2) { "redis_value2"}
+ let_it_be(:value1) { "redis_value1" }
+ let_it_be(:value2) { "redis_value2" }
let_it_be(:expected_value) { value1 }
let_it_be(:verification_name) { :get }
let_it_be(:verification_args) { key1 }
diff --git a/spec/lib/gitlab/reference_counter_spec.rb b/spec/lib/gitlab/reference_counter_spec.rb
index 83e4006c69b..05294fb84e7 100644
--- a/spec/lib/gitlab/reference_counter_spec.rb
+++ b/spec/lib/gitlab/reference_counter_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::ReferenceCounter, :clean_gitlab_redis_shared_state do
it 'resets reference count down to zero' do
3.times { reference_counter.increase }
- expect { reference_counter.reset! }.to change { reference_counter.value}.from(3).to(0)
+ expect { reference_counter.reset! }.to change { reference_counter.value }.from(3).to(0)
end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index a3afbed18e2..d8f182d903d 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -270,7 +270,7 @@ RSpec.describe Gitlab::Regex do
context 'conan recipe components' do
shared_examples 'accepting valid recipe components values' do
- let(:fifty_one_characters) { 'f_a' * 17}
+ let(:fifty_one_characters) { 'f_a' * 17 }
it { is_expected.to match('foobar') }
it { is_expected.to match('foo_bar') }
@@ -374,12 +374,12 @@ RSpec.describe Gitlab::Regex do
end
end
- it { is_expected.to match('0')}
+ it { is_expected.to match('0') }
it { is_expected.to match('1') }
it { is_expected.to match('03') }
it { is_expected.to match('2.0') }
it { is_expected.to match('01.2') }
- it { is_expected.to match('10.2.3-beta')}
+ it { is_expected.to match('10.2.3-beta') }
it { is_expected.to match('1.2-SNAPSHOT') }
it { is_expected.to match('20') }
it { is_expected.to match('20.3') }
@@ -454,7 +454,7 @@ RSpec.describe Gitlab::Regex do
it { is_expected.to match('0.1') }
it { is_expected.to match('2.0') }
- it { is_expected.to match('1.2.0')}
+ it { is_expected.to match('1.2.0') }
it { is_expected.to match('0100!0.0') }
it { is_expected.to match('00!1.2') }
it { is_expected.to match('1.0a') }
diff --git a/spec/lib/gitlab/search/abuse_detection_spec.rb b/spec/lib/gitlab/search/abuse_detection_spec.rb
index a18d28456cd..2a8d74a62ab 100644
--- a/spec/lib/gitlab/search/abuse_detection_spec.rb
+++ b/spec/lib/gitlab/search/abuse_detection_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Search::AbuseDetection do
subject { described_class.new(params) }
- let(:params) {{ query_string: 'foobar' }}
+ let(:params) { { query_string: 'foobar' } }
describe 'abusive scopes validation' do
it 'allows only approved scopes' do
diff --git a/spec/lib/gitlab/search_context/builder_spec.rb b/spec/lib/gitlab/search_context/builder_spec.rb
index a09115f3f21..78799b67a69 100644
--- a/spec/lib/gitlab/search_context/builder_spec.rb
+++ b/spec/lib/gitlab/search_context/builder_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::SearchContext::Builder, type: :controller do
- controller(ApplicationController) { }
+ controller(ApplicationController) {}
subject(:builder) { described_class.new(controller.view_context) }
diff --git a/spec/lib/gitlab/seeder_spec.rb b/spec/lib/gitlab/seeder_spec.rb
index a94ae2bca7a..0ad80323085 100644
--- a/spec/lib/gitlab/seeder_spec.rb
+++ b/spec/lib/gitlab/seeder_spec.rb
@@ -77,4 +77,44 @@ RSpec.describe Gitlab::Seeder do
end
end
end
+
+ describe ::Gitlab::Seeder::Ci::DailyBuildGroupReportResult do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be(:build) { create(:ci_build, :success, pipeline: pipeline) }
+
+ subject(:build_report) do
+ described_class.new(project)
+ end
+
+ describe '#seed' do
+ it 'creates daily build results for the project' do
+ expect { build_report.seed }.to change {
+ Ci::DailyBuildGroupReportResult.count
+ }.by(Gitlab::Seeder::Ci::DailyBuildGroupReportResult::COUNT_OF_DAYS)
+ end
+
+ it 'matches project data with last report' do
+ build_report.seed
+
+ report = project.daily_build_group_report_results.last
+ reports_count = project.daily_build_group_report_results.count
+
+ expect(build.group_name).to eq(report.group_name)
+ expect(pipeline.source_ref_path).to eq(report.ref_path)
+ expect(pipeline.default_branch?).to eq(report.default_branch)
+ expect(reports_count).to eq(Gitlab::Seeder::Ci::DailyBuildGroupReportResult::COUNT_OF_DAYS)
+ end
+
+ it 'does not raise error on RecordNotUnique' do
+ build_report.seed
+ build_report.seed
+
+ reports_count = project.daily_build_group_report_results.count
+
+ expect(reports_count).to eq(Gitlab::Seeder::Ci::DailyBuildGroupReportResult::COUNT_OF_DAYS)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/session_spec.rb b/spec/lib/gitlab/session_spec.rb
index de680e8425e..67ad59f956d 100644
--- a/spec/lib/gitlab/session_spec.rb
+++ b/spec/lib/gitlab/session_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Gitlab::Session do
end
it 'restores current store after' do
- described_class.with_session(two: 2) { }
+ described_class.with_session(two: 2) {}
expect(described_class.current).to eq nil
end
diff --git a/spec/lib/gitlab/sidekiq_config_spec.rb b/spec/lib/gitlab/sidekiq_config_spec.rb
index 4a1a9beb21a..c62302d8bba 100644
--- a/spec/lib/gitlab/sidekiq_config_spec.rb
+++ b/spec/lib/gitlab/sidekiq_config_spec.rb
@@ -194,7 +194,7 @@ RSpec.describe Gitlab::SidekiqConfig do
queues = described_class.routing_queues
expect(queues).to match_array(%w[
- default mailers high_urgency gitaly email_receiver service_desk_email_receiver
+ default mailers high_urgency gitaly
])
expect(queues).not_to include('not_exist')
end
diff --git a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
index 01b7270d761..635f572daef 100644
--- a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
+++ b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
end
describe '#stop_working' do
- subject { memory_killer.send(:stop_working)}
+ subject { memory_killer.send(:stop_working) }
it 'changes enable? to false' do
expect { subject }.to change { memory_killer.send(:enabled?) }
@@ -355,6 +355,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
let(:reason) { 'rss out of range reason description' }
let(:queue) { 'default' }
let(:running_jobs) { [{ jid: jid, worker_class: 'DummyWorker' }] }
+ let(:metrics) { memory_killer.instance_variable_get(:@metrics) }
let(:worker) do
Class.new do
def self.name
@@ -390,6 +391,9 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
reason: reason,
running_jobs: running_jobs)
+ expect(metrics[:sidekiq_memory_killer_running_jobs]).to receive(:increment)
+ .with({ worker_class: "DummyWorker", deadline_exceeded: true })
+
Gitlab::SidekiqDaemon::Monitor.instance.within_job(DummyWorker, jid, queue) do
subject
end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index 9c0cbe21e6b..e3d9549a3c0 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(job, 'test_queue') { }
+ call_subject(job, 'test_queue') {}
end
end
@@ -40,7 +40,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(wrapped_job, 'test_queue') { }
+ call_subject(wrapped_job, 'test_queue') {}
end
end
@@ -175,7 +175,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(job, 'test_queue') { }
+ call_subject(job, 'test_queue') {}
end
end
@@ -188,7 +188,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(job.except("created_at", "enqueued_at"), 'test_queue') { }
+ call_subject(job.except("created_at", "enqueued_at"), 'test_queue') {}
end
end
end
@@ -204,7 +204,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(job, 'test_queue') { }
+ call_subject(job, 'test_queue') {}
end
end
end
@@ -233,7 +233,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(subject).to receive(:log_job_start).and_call_original
expect(subject).to receive(:log_job_done).and_call_original
- call_subject(job, 'test_queue') { }
+ call_subject(job, 'test_queue') {}
end
end
end
@@ -266,7 +266,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expect(logger).to receive(:info).with(start_payload).ordered
expect(logger).to receive(:info).with(expected_end_payload).ordered
- call_subject(job, 'test_queue') { }
+ call_subject(job, 'test_queue') {}
end
end
end
@@ -330,7 +330,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
Gitlab::SafeRequestStore.clear!
- call_subject(job.dup, 'test_queue') { }
+ call_subject(job.dup, 'test_queue') {}
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb b/spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb
index 85cddfa7bf1..d61c9765753 100644
--- a/spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb
@@ -41,7 +41,9 @@ RSpec.describe Gitlab::SidekiqMiddleware::Monitor do
::Sidekiq::DeadSet.new.clear
expect do
- subject rescue Sidekiq::JobRetry::Skip
+ subject
+ rescue Sidekiq::JobRetry::Skip
+ nil
end.to change { ::Sidekiq::DeadSet.new.size }.by(1)
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 117b37ffda3..d6d24ea3a24 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -109,6 +109,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
expect(elasticsearch_seconds_metric).to receive(:observe).with(labels_with_job_status, elasticsearch_duration)
expect(redis_requests_total).to receive(:increment).with(labels_with_job_status, redis_calls)
expect(elasticsearch_requests_total).to receive(:increment).with(labels_with_job_status, elasticsearch_calls)
+ expect(sidekiq_mem_total_bytes).to receive(:set).with(labels_with_job_status, mem_total_bytes)
subject.call(worker, job, :test) { nil }
end
diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb
index 5167523ff58..5af234ff88e 100644
--- a/spec/lib/gitlab/slash_commands/deploy_spec.rb
+++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb
@@ -165,7 +165,7 @@ RSpec.describe Gitlab::SlashCommands::Deploy do
context 'with ReDoS attempts' do
def duration_for(&block)
start = Time.zone.now
- yield if block_given?
+ yield if block
Time.zone.now - start
end
diff --git a/spec/lib/gitlab/spamcheck/client_spec.rb b/spec/lib/gitlab/spamcheck/client_spec.rb
index a6e7665569c..956ed2a976f 100644
--- a/spec/lib/gitlab/spamcheck/client_spec.rb
+++ b/spec/lib/gitlab/spamcheck/client_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Spamcheck::Client do
let(:stub) { double(:spamcheck_stub, check_for_spam_issue: response) }
context 'is tls ' do
- let(:endpoint) { 'tls://spamcheck.example.com'}
+ let(:endpoint) { 'tls://spamcheck.example.com' }
it 'uses secure connection' do
expect(Spamcheck::SpamcheckService::Stub).to receive(:new).with(endpoint.sub(%r{^tls://}, ''),
@@ -97,7 +97,7 @@ RSpec.describe Gitlab::Spamcheck::Client do
context: cxt)
expect(issue_pb.title).to eq issue.title
expect(issue_pb.description).to eq issue.description
- expect(issue_pb.user_in_project). to be false
+ expect(issue_pb.user_in_project).to be false
expect(issue_pb.project.project_id).to eq issue.project_id
expect(issue_pb.created_at).to eq timestamp_to_protobuf_timestamp(issue.created_at)
expect(issue_pb.updated_at).to eq timestamp_to_protobuf_timestamp(issue.updated_at)
@@ -118,7 +118,7 @@ RSpec.describe Gitlab::Spamcheck::Client do
end
context 'when user has multiple email addresses' do
- let(:secondary_email) {create(:email, :confirmed, user: user)}
+ let(:secondary_email) { create(:email, :confirmed, user: user) }
before do
user.emails << secondary_email
diff --git a/spec/lib/gitlab/ssh/commit_spec.rb b/spec/lib/gitlab/ssh/commit_spec.rb
new file mode 100644
index 00000000000..cc977a80f95
--- /dev/null
+++ b/spec/lib/gitlab/ssh/commit_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ssh::Commit do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:signed_by_key) { create(:key) }
+
+ let(:commit) { create(:commit, project: project) }
+ let(:signature_text) { 'signature_text' }
+ let(:signed_text) { 'signed_text' }
+ let(:signature_data) { [signature_text, signed_text] }
+ let(:verifier) { instance_double('Gitlab::Ssh::Signature') }
+ let(:verification_status) { :verified }
+
+ subject(:signature) { described_class.new(commit).signature }
+
+ before do
+ allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
+ .with(Gitlab::Git::Repository, commit.sha)
+ .and_return(signature_data)
+
+ allow(verifier).to receive(:verification_status).and_return(verification_status)
+ allow(verifier).to receive(:signed_by_key).and_return(signed_by_key)
+
+ allow(Gitlab::Ssh::Signature).to receive(:new)
+ .with(signature_text, signed_text, commit.committer_email)
+ .and_return(verifier)
+ end
+
+ describe '#signature' do
+ it 'returns the cached signature on multiple calls' do
+ ssh_commit = described_class.new(commit)
+
+ expect(ssh_commit).to receive(:create_cached_signature!).and_call_original
+ ssh_commit.signature
+
+ expect(ssh_commit).not_to receive(:create_cached_signature!)
+ ssh_commit.signature
+ end
+
+ context 'when all expected data is present' do
+ it 'calls signature verifier and uses returned attributes' do
+ expect(signature).to have_attributes(
+ commit_sha: commit.sha,
+ project: project,
+ key_id: signed_by_key.id,
+ verification_status: 'verified'
+ )
+ end
+ end
+
+ context 'when signed_by_key is nil' do
+ let_it_be(:signed_by_key) { nil }
+
+ let(:verification_status) { :unknown_key }
+
+ it 'creates signature without a key_id' do
+ expect(signature).to have_attributes(
+ commit_sha: commit.sha,
+ project: project,
+ key_id: nil,
+ verification_status: 'unknown_key'
+ )
+ end
+ end
+ end
+
+ describe '#update_signature!' do
+ it 'updates verification status' do
+ allow(verifier).to receive(:verification_status).and_return(:unverified)
+ signature
+
+ stored_signature = CommitSignatures::SshSignature.find_by_commit_sha(commit.sha)
+
+ allow(verifier).to receive(:verification_status).and_return(:verified)
+
+ expect { described_class.new(commit).update_signature!(stored_signature) }.to(
+ change { signature.reload.verification_status }.from('unverified').to('verified')
+ )
+ end
+ end
+end
diff --git a/spec/lib/gitlab/suggestions/file_suggestion_spec.rb b/spec/lib/gitlab/suggestions/file_suggestion_spec.rb
index 1d25bf6edbd..5971f4ebbce 100644
--- a/spec/lib/gitlab/suggestions/file_suggestion_spec.rb
+++ b/spec/lib/gitlab/suggestions/file_suggestion_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Gitlab::Suggestions::FileSuggestion do
let_it_be(:user) { create(:user) }
- let_it_be(:file_path) { 'files/ruby/popen.rb'}
+ let_it_be(:file_path) { 'files/ruby/popen.rb' }
let_it_be(:project) { create(:project, :repository) }
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
index 2554a15d97e..48092a33da3 100644
--- a/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
@@ -48,40 +48,8 @@ RSpec.describe Gitlab::Tracking::Destinations::SnowplowMicro do
allow(Gitlab.config).to receive(:snowplow_micro).and_raise(Settingslogic::MissingSetting)
end
- context 'when SNOWPLOW_MICRO_URI has scheme and port' do
- before do
- stub_env('SNOWPLOW_MICRO_URI', 'http://gdk.test:9091')
- end
-
- it 'returns hostname URI part' do
- expect(subject.hostname).to eq('gdk.test:9091')
- end
- end
-
- context 'when SNOWPLOW_MICRO_URI is without protocol' do
- before do
- stub_env('SNOWPLOW_MICRO_URI', 'gdk.test:9091')
- end
-
- it 'returns hostname URI part' do
- expect(subject.hostname).to eq('gdk.test:9091')
- end
- end
-
- context 'when SNOWPLOW_MICRO_URI is hostname only' do
- before do
- stub_env('SNOWPLOW_MICRO_URI', 'uriwithoutport')
- end
-
- it 'returns hostname URI with default HTTP port' do
- expect(subject.hostname).to eq('uriwithoutport:80')
- end
- end
-
- context 'when SNOWPLOW_MICRO_URI is not set' do
- it 'returns localhost hostname' do
- expect(subject.hostname).to eq('localhost:9090')
- end
+ it 'returns localhost hostname' do
+ expect(subject.hostname).to eq('localhost:9090')
end
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index dd62c832f6f..028c985f3b3 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -90,15 +90,6 @@ RSpec.describe Gitlab::Tracking do
it_behaves_like 'delegates to SnowplowMicro destination with proper options'
end
-
- context "enabled with env variable" do
- before do
- allow(Gitlab.config).to receive(:snowplow_micro).and_raise(Settingslogic::MissingSetting)
- stub_env('SNOWPLOW_MICRO_ENABLE', '1')
- end
-
- it_behaves_like 'delegates to SnowplowMicro destination with proper options'
- end
end
it 'when feature flag is disabled' do
@@ -149,7 +140,6 @@ RSpec.describe Gitlab::Tracking do
context 'when destination is Snowplow' do
before do
- stub_env('SNOWPLOW_MICRO_ENABLE', '0')
allow(Rails.env).to receive(:development?).and_return(true)
end
@@ -158,7 +148,6 @@ RSpec.describe Gitlab::Tracking do
context 'when destination is SnowplowMicro' do
before do
- stub_env('SNOWPLOW_MICRO_ENABLE', '1')
allow(Rails.env).to receive(:development?).and_return(true)
end
@@ -181,7 +170,7 @@ RSpec.describe Gitlab::Tracking do
let_it_be(:definition_action) { 'definition_action' }
let_it_be(:definition_category) { 'definition_category' }
let_it_be(:label_description) { 'definition label description' }
- let_it_be(:test_definition) {{ 'category': definition_category, 'action': definition_action }}
+ let_it_be(:test_definition) { { 'category': definition_category, 'action': definition_action } }
before do
allow_next_instance_of(described_class) do |instance|
@@ -212,4 +201,28 @@ RSpec.describe Gitlab::Tracking do
project: project, user: user, namespace: namespace, extra_key_1: 'extra value 1')
end
end
+
+ describe 'snowplow_micro_enabled?' do
+ before do
+ allow(Rails.env).to receive(:development?).and_return(true)
+ end
+
+ it 'returns true when snowplow_micro is enabled' do
+ stub_config(snowplow_micro: { enabled: true })
+
+ expect(described_class).to be_snowplow_micro_enabled
+ end
+
+ it 'returns false when snowplow_micro is disabled' do
+ stub_config(snowplow_micro: { enabled: false })
+
+ expect(described_class).not_to be_snowplow_micro_enabled
+ end
+
+ it 'returns false when snowplow_micro is not configured' do
+ allow(Gitlab.config).to receive(:snowplow_micro).and_raise(Settingslogic::MissingSetting)
+
+ expect(described_class).not_to be_snowplow_micro_enabled
+ end
+ end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
index 8e7bd7b84e6..f73155642d6 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
@@ -160,6 +160,38 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
end
end
end
+
+ context 'with custom timestamp column' do
+ subject do
+ described_class.tap do |metric_class|
+ metric_class.relation { Issue }
+ metric_class.operation :count
+ metric_class.timestamp_column :last_edited_at
+ end.new(time_frame: '28d')
+ end
+
+ it 'calculates a correct result' do
+ create(:issue, last_edited_at: 5.days.ago)
+
+ expect(subject.value).to eq(1)
+ end
+ end
+
+ context 'with default timestamp column' do
+ subject do
+ described_class.tap do |metric_class|
+ metric_class.relation { Issue }
+ metric_class.operation :count
+ end.new(time_frame: '28d')
+ end
+
+ it 'calculates a correct result' do
+ create(:issue, last_edited_at: 5.days.ago)
+ create(:issue, created_at: 5.days.ago)
+
+ expect(subject.value).to eq(1)
+ end
+ end
end
context 'with unimplemented operation method used' do
diff --git a/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb
index 9ee8bc6b568..f9cd6e88e0a 100644
--- a/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe Gitlab::Usage::Metrics::NameSuggestion do
let(:key_path) { 'counts.jira_imports_total_imported_issues_count' }
let(:operation) { :sum }
let(:relation) { JiraImportState.finished }
- let(:column) { :imported_issues_count}
+ let(:column) { :imported_issues_count }
let(:name_suggestion) { /sum_imported_issues_count_from_<adjective describing\: '\(jira_imports\.status = \d+\)'>_jira_imports/ }
end
end
@@ -77,7 +77,7 @@ RSpec.describe Gitlab::Usage::Metrics::NameSuggestion do
let(:key_path) { 'counts.ci_pipeline_duration' }
let(:operation) { :average }
let(:relation) { Ci::Pipeline }
- let(:column) { :duration}
+ let(:column) { :duration }
let(:name_suggestion) { /average_duration_from_ci_pipelines/ }
end
end
diff --git a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
index 167dba9b57d..7e8b15d23db 100644
--- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
end
describe '#add_metric' do
- let(:metric) {'CountIssuesMetric' }
+ let(:metric) { 'CountIssuesMetric' }
it 'computes the suggested name for given metric' do
expect(described_class.add_metric(metric)).to eq('count_issues')
diff --git a/spec/lib/gitlab/usage/service_ping_report_spec.rb b/spec/lib/gitlab/usage/service_ping_report_spec.rb
index 1e8f9db4dea..7a37a31b195 100644
--- a/spec/lib/gitlab/usage/service_ping_report_spec.rb
+++ b/spec/lib/gitlab/usage/service_ping_report_spec.rb
@@ -111,8 +111,12 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
# Because test cases are run inside a transaction, if any query raise and error all queries that follows
# it are automatically canceled by PostgreSQL, to avoid that problem, and to provide exhaustive information
# about every metric, queries are wrapped explicitly in sub transactions.
- ApplicationRecord.transaction do
- ApplicationRecord.connection.execute(query)&.first&.values&.first
+ table = PgQuery.parse(query).tables.first
+ gitlab_schema = Gitlab::Database::GitlabSchema.tables_to_schema[table]
+ base_model = gitlab_schema == :gitlab_main ? ApplicationRecord : Ci::ApplicationRecord
+
+ base_model.transaction do
+ base_model.connection.execute(query)&.first&.values&.first
end
rescue ActiveRecord::StatementInvalid => e
e.message
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 54d49b432f4..e0b334cb5af 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
@@ -77,32 +77,18 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
end
describe '.unique_events_data' do
- context 'with use_redis_hll_instrumentation_classes feature enabled' do
- it 'does not include instrumented categories' do
- stub_feature_flags(use_redis_hll_instrumentation_classes: true)
-
- expect(described_class.unique_events_data.keys)
- .not_to include(*described_class::CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
- end
- end
-
- context 'with use_redis_hll_instrumentation_classes feature disabled' do
- it 'includes instrumented categories' do
- stub_feature_flags(use_redis_hll_instrumentation_classes: false)
-
- expect(described_class.unique_events_data.keys)
- .to include(*described_class::CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS)
- end
+ it 'does not include instrumented categories' do
+ expect(described_class.unique_events_data.keys)
+ .not_to include(*described_class.categories_collected_from_metrics_definitions)
end
end
end
describe '.categories' do
- it 'gets all unique category names' do
- expect(described_class.categories).to contain_exactly(
+ it 'gets CE unique category names' do
+ expect(described_class.categories).to include(
'deploy_token_packages',
'user_packages',
- 'compliance',
'ecosystem',
'analytics',
'ide_edit',
@@ -130,7 +116,8 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'work_items',
'ci_users',
'error_tracking',
- 'manage'
+ 'manage',
+ 'kubernetes_agent'
)
end
end
@@ -483,7 +470,7 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
describe '.weekly_redis_keys' do
using RSpec::Parameterized::TableSyntax
- let(:weekly_event) { 'g_compliance_dashboard' }
+ let(:weekly_event) { 'i_search_total' }
let(:redis_event) { described_class.send(:event_for, weekly_event) }
subject(:weekly_redis_keys) { described_class.send(:weekly_redis_keys, events: [redis_event], start_date: DateTime.parse(start_date), end_date: DateTime.parse(end_date)) }
@@ -493,13 +480,13 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
'2020-12-21' | '2020-12-20' | []
'2020-12-21' | '2020-11-21' | []
'2021-01-01' | '2020-12-28' | []
- '2020-12-21' | '2020-12-28' | ['g_{compliance}_dashboard-2020-52']
- '2020-12-21' | '2021-01-01' | ['g_{compliance}_dashboard-2020-52']
- '2020-12-27' | '2021-01-01' | ['g_{compliance}_dashboard-2020-52']
- '2020-12-26' | '2021-01-04' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53']
- '2020-12-26' | '2021-01-11' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01']
- '2020-12-26' | '2021-01-17' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01']
- '2020-12-26' | '2021-01-18' | ['g_{compliance}_dashboard-2020-52', 'g_{compliance}_dashboard-2020-53', 'g_{compliance}_dashboard-2021-01', 'g_{compliance}_dashboard-2021-02']
+ '2020-12-21' | '2020-12-28' | ['i_{search}_total-2020-52']
+ '2020-12-21' | '2021-01-01' | ['i_{search}_total-2020-52']
+ '2020-12-27' | '2021-01-01' | ['i_{search}_total-2020-52']
+ '2020-12-26' | '2021-01-04' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53']
+ '2020-12-26' | '2021-01-11' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01']
+ '2020-12-26' | '2021-01-17' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01']
+ '2020-12-26' | '2021-01-18' | ['i_{search}_total-2020-52', 'i_{search}_total-2020-53', 'i_{search}_total-2021-01', 'i_{search}_total-2021-02']
end
with_them do
diff --git a/spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb
index 60c4424d2ae..b778f532a11 100644
--- a/spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/ipynb_diff_activity_counter_spec.rb
@@ -43,18 +43,18 @@ RSpec.describe Gitlab::UsageDataCounters::IpynbDiffActivityCounter, :clean_gitla
let(:for_commit) { true }
it_behaves_like 'an action that tracks events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION }
end
it_behaves_like 'an action that tracks events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION }
end
it_behaves_like 'an action that does not track events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION }
end
end
@@ -62,35 +62,35 @@ RSpec.describe Gitlab::UsageDataCounters::IpynbDiffActivityCounter, :clean_gitla
let(:for_mr) { true }
it_behaves_like 'an action that tracks events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION }
end
it_behaves_like 'an action that tracks events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION }
end
it_behaves_like 'an action that does not track events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION }
end
end
context 'note is for neither MR nor Commit' do
it_behaves_like 'an action that does not track events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION }
end
it_behaves_like 'an action that does not track events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION }
end
it_behaves_like 'an action that does not track events' do
- let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
- let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
+ let(:action) { described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION }
+ let(:per_user_action) { described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION }
end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
index 1b73e5269d7..84a6f338282 100644
--- a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
@@ -6,7 +6,12 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
let_it_be(:user1) { build(:user, id: 1) }
let_it_be(:user2) { build(:user, id: 2) }
let_it_be(:user3) { build(:user, id: 3) }
+ let_it_be(:project) { build(:project) }
+ let_it_be(:category) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CATEGORY }
+ let_it_be(:event_action) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_ACTION }
+ let_it_be(:event_label) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_LABEL }
+ let(:event_property) { action }
let(:time) { Time.zone.now }
context 'for Issue title edit actions' do
@@ -120,8 +125,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
context 'for Issue cloned actions' do
- it_behaves_like 'a daily tracked issuable event' do
- let(:action) { described_class::ISSUE_CLONED }
+ it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
+ let_it_be(:action) { described_class::ISSUE_CLONED }
def track_action(params)
described_class.track_issue_cloned_action(**params)
@@ -239,8 +244,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
- context 'for Issue comment added actions' do
- it_behaves_like 'a daily tracked issuable event' do
+ context 'for Issue comment added actions', :snowplow do
+ it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
let(:action) { described_class::ISSUE_COMMENT_ADDED }
def track_action(params)
@@ -249,8 +254,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
- context 'for Issue comment edited actions' do
- it_behaves_like 'a daily tracked issuable event' do
+ context 'for Issue comment edited actions', :snowplow do
+ it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
let(:action) { described_class::ISSUE_COMMENT_EDITED }
def track_action(params)
@@ -259,8 +264,8 @@ RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_git
end
end
- context 'for Issue comment removed actions' do
- it_behaves_like 'a daily tracked issuable event' do
+ context 'for Issue comment removed actions', :snowplow do
+ it_behaves_like 'daily tracked issuable snowplow and service ping events with project' do
let(:action) { described_class::ISSUE_COMMENT_REMOVED }
def track_action(params)
diff --git a/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb
new file mode 100644
index 00000000000..e073fac504a
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::MergeRequestWidgetExtensionCounter do
+ it_behaves_like 'a redis usage counter', 'Widget Extension', :test_summary_count_expand
+
+ it_behaves_like 'a redis usage counter with totals', :i_code_review_merge_request_widget, test_summary_count_expand: 5
+end
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 0264236f087..0bcdbe82a7a 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
@@ -20,4 +20,12 @@ RSpec.describe Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter, :clean_
it_behaves_like 'work item unique counter'
end
+
+ describe '.track_work_item_date_changed_action' do
+ subject(:track_event) { described_class.track_work_item_date_changed_action(author: user) }
+
+ let(:event_name) { described_class::WORK_ITEM_DATE_CHANGED }
+
+ it_behaves_like 'work item unique counter'
+ end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 6eb00053b17..692b6483149 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -1203,12 +1203,14 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe 'redis_hll_counters' do
subject { described_class.redis_hll_counters }
- let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
+ let(:migrated_categories) do
+ ::Gitlab::UsageDataCounters::HLLRedisCounter.categories_collected_from_metrics_definitions
+ end
+ let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories - migrated_categories }
let(:ignored_metrics) { ["i_package_composer_deploy_token_weekly"] }
it 'has all known_events' do
- stub_feature_flags(use_redis_hll_instrumentation_classes: false)
expect(subject).to have_key(:redis_hll_counters)
expect(subject[:redis_hll_counters].keys).to match_array(categories)
diff --git a/spec/lib/gitlab/utils/batch_loader_spec.rb b/spec/lib/gitlab/utils/batch_loader_spec.rb
new file mode 100644
index 00000000000..c1f6d6df07a
--- /dev/null
+++ b/spec/lib/gitlab/utils/batch_loader_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'batch-loader'
+
+RSpec.describe Gitlab::Utils::BatchLoader do
+ let(:stubbed_loader) do
+ double( # rubocop:disable RSpec/VerifiedDoubles
+ 'Loader',
+ load_lazy_method: [],
+ load_lazy_method_same_batch_key: [],
+ load_lazy_method_other_batch_key: []
+ )
+ end
+
+ let(:test_module) do
+ Module.new do
+ def self.lazy_method(id)
+ BatchLoader.for(id).batch(key: :my_batch_name) do |ids, loader|
+ stubbed_loader.load_lazy_method(ids)
+
+ ids.each { |id| loader.call(id, id) }
+ end
+ end
+
+ def self.lazy_method_same_batch_key(id)
+ BatchLoader.for(id).batch(key: :my_batch_name) do |ids, loader|
+ stubbed_loader.load_lazy_method_same_batch_key(ids)
+
+ ids.each { |id| loader.call(id, id) }
+ end
+ end
+
+ def self.lazy_method_other_batch_key(id)
+ BatchLoader.for(id).batch(key: :other_batch_name) do |ids, loader|
+ stubbed_loader.load_lazy_method_other_batch_key(ids)
+
+ ids.each { |id| loader.call(id, id) }
+ end
+ end
+ end
+ end
+
+ before do
+ BatchLoader::Executor.clear_current
+ allow(test_module).to receive(:stubbed_loader).and_return(stubbed_loader)
+ end
+
+ describe '.clear_key' do
+ it 'clears batched items which match the specified batch key' do
+ test_module.lazy_method(1)
+ test_module.lazy_method_same_batch_key(2)
+ test_module.lazy_method_other_batch_key(3)
+
+ described_class.clear_key(:my_batch_name)
+
+ test_module.lazy_method(4).to_i
+ test_module.lazy_method_same_batch_key(5).to_i
+ test_module.lazy_method_other_batch_key(6).to_i
+
+ expect(stubbed_loader).to have_received(:load_lazy_method).with([4])
+ expect(stubbed_loader).to have_received(:load_lazy_method_same_batch_key).with([5])
+ expect(stubbed_loader).to have_received(:load_lazy_method_other_batch_key).with([3, 6])
+ end
+
+ it 'clears loaded values which match the specified batch key' do
+ test_module.lazy_method(1).to_i
+ test_module.lazy_method_same_batch_key(2).to_i
+ test_module.lazy_method_other_batch_key(3).to_i
+
+ described_class.clear_key(:my_batch_name)
+
+ test_module.lazy_method(1).to_i
+ test_module.lazy_method_same_batch_key(2).to_i
+ test_module.lazy_method_other_batch_key(3).to_i
+
+ expect(stubbed_loader).to have_received(:load_lazy_method).with([1]).twice
+ expect(stubbed_loader).to have_received(:load_lazy_method_same_batch_key).with([2]).twice
+ expect(stubbed_loader).to have_received(:load_lazy_method_other_batch_key).with([3])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/utils/link_header_parser_spec.rb b/spec/lib/gitlab/utils/link_header_parser_spec.rb
new file mode 100644
index 00000000000..e15ef930271
--- /dev/null
+++ b/spec/lib/gitlab/utils/link_header_parser_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Utils::LinkHeaderParser do
+ let(:parser) { described_class.new(header) }
+
+ describe '#parse' do
+ subject { parser.parse }
+
+ context 'with a valid header' do
+ let(:header) { generate_header(next: 'http://sandbox.org/next') }
+ let(:expected) { { next: { uri: URI('http://sandbox.org/next') } } }
+
+ it { is_expected.to eq(expected) }
+
+ context 'with multiple links' do
+ let(:header) { generate_header(next: 'http://sandbox.org/next', previous: 'http://sandbox.org/previous') }
+ let(:expected) do
+ {
+ next: { uri: URI('http://sandbox.org/next') },
+ previous: { uri: URI('http://sandbox.org/previous') }
+ }
+ end
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'with an incomplete uri' do
+ let(:header) { '<http://sandbox.org/next; rel="next"' }
+
+ it { is_expected.to eq({}) }
+ end
+
+ context 'with no rel' do
+ let(:header) { '<http://sandbox.org/next>; direction="next"' }
+
+ it { is_expected.to eq({}) }
+ end
+
+ context 'with multiple rel elements' do
+ # check https://datatracker.ietf.org/doc/html/rfc5988#section-5.3:
+ # occurrences after the first MUST be ignored by parsers
+ let(:header) { '<http://sandbox.org/next>; rel="next"; rel="dummy"' }
+
+ it { is_expected.to eq(expected) }
+ end
+
+ context 'when the url is too long' do
+ let(:header) { "<http://sandbox.org/#{'a' * 500}>; rel=\"next\"" }
+
+ it { is_expected.to eq({}) }
+ end
+ end
+
+ context 'with nil header' do
+ let(:header) { nil }
+
+ it { is_expected.to eq({}) }
+ end
+
+ context 'with empty header' do
+ let(:header) { '' }
+
+ it { is_expected.to eq({}) }
+ end
+
+ def generate_header(links)
+ stringified_links = links.map do |rel, url|
+ "<#{url}>; rel=\"#{rel}\""
+ end
+ stringified_links.join(', ')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/utils/sanitize_node_link_spec.rb b/spec/lib/gitlab/utils/sanitize_node_link_spec.rb
index 514051b1cc0..3ab592dfc62 100644
--- a/spec/lib/gitlab/utils/sanitize_node_link_spec.rb
+++ b/spec/lib/gitlab/utils/sanitize_node_link_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::Utils::SanitizeNodeLink do
describe "#safe_protocol?" do
let(:doc) { HTML::Pipeline.parse("<a href='#{scheme}alert(1);'>foo</a>") }
let(:node) { doc.children.first }
- let(:uri) { Addressable::URI.parse(node['href'])}
+ let(:uri) { Addressable::URI.parse(node['href']) }
it "returns false" do
expect(object.safe_protocol?(scheme)).to be_falsy
diff --git a/spec/lib/gitlab/utils/strong_memoize_spec.rb b/spec/lib/gitlab/utils/strong_memoize_spec.rb
index 5350e090e2b..cb03797b3d9 100644
--- a/spec/lib/gitlab/utils/strong_memoize_spec.rb
+++ b/spec/lib/gitlab/utils/strong_memoize_spec.rb
@@ -1,10 +1,27 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'rspec-benchmark'
+
+RSpec.configure do |config|
+ config.include RSpec::Benchmark::Matchers
+end
RSpec.describe Gitlab::Utils::StrongMemoize do
let(:klass) do
- struct = Struct.new(:value) do
+ strong_memoize_class = described_class
+
+ Struct.new(:value) do
+ include strong_memoize_class
+
+ def self.method_added_list
+ @method_added_list ||= []
+ end
+
+ def self.method_added(name)
+ method_added_list << name
+ end
+
def method_name
strong_memoize(:method_name) do
trace << value
@@ -12,21 +29,56 @@ RSpec.describe Gitlab::Utils::StrongMemoize do
end
end
+ def method_name_attr
+ trace << value
+ value
+ end
+ strong_memoize_attr :method_name_attr
+
+ strong_memoize_attr :different_method_name_attr, :different_member_name_attr
+ def different_method_name_attr
+ trace << value
+ value
+ end
+
+ strong_memoize_attr :enabled?
+ def enabled?
+ true
+ end
+
def trace
@trace ||= []
end
- end
- struct.include(described_class)
- struct
+ protected
+
+ def private_method
+ end
+ private :private_method
+ strong_memoize_attr :private_method
+
+ public
+
+ def protected_method
+ end
+ protected :protected_method
+ strong_memoize_attr :protected_method
+
+ private
+
+ def public_method
+ end
+ public :public_method
+ strong_memoize_attr :public_method
+ end
end
subject(:object) { klass.new(value) }
shared_examples 'caching the value' do
it 'only calls the block once' do
- value0 = object.method_name
- value1 = object.method_name
+ value0 = object.send(method_name)
+ value1 = object.send(method_name)
expect(value0).to eq(value)
expect(value1).to eq(value)
@@ -34,8 +86,8 @@ RSpec.describe Gitlab::Utils::StrongMemoize do
end
it 'returns and defines the instance variable for the exact value' do
- returned_value = object.method_name
- memoized_value = object.instance_variable_get(:@method_name)
+ returned_value = object.send(method_name)
+ memoized_value = object.instance_variable_get(:"@#{member_name}")
expect(returned_value).to eql(value)
expect(memoized_value).to eql(value)
@@ -46,12 +98,19 @@ RSpec.describe Gitlab::Utils::StrongMemoize do
[nil, false, true, 'value', 0, [0]].each do |value|
context "with value #{value}" do
let(:value) { value }
+ let(:method_name) { :method_name }
+ let(:member_name) { :method_name }
it_behaves_like 'caching the value'
- it 'raises exception for invalid key' do
+ it 'raises exception for invalid type as key' do
expect { object.strong_memoize(10) { 20 } }.to raise_error /Invalid type of '10'/
end
+
+ it 'raises exception for invalid characters in key' do
+ expect { object.strong_memoize(:enabled?) { 20 } }
+ .to raise_error /is not allowed as an instance variable name/
+ end
end
end
@@ -109,4 +168,64 @@ RSpec.describe Gitlab::Utils::StrongMemoize do
expect(object.instance_variable_defined?(:@method_name)).to be(false)
end
end
+
+ describe '.strong_memoize_attr' do
+ [nil, false, true, 'value', 0, [0]].each do |value|
+ let(:value) { value }
+
+ context "memoized after method definition with value #{value}" do
+ let(:method_name) { :method_name_attr }
+ let(:member_name) { :method_name_attr }
+
+ it_behaves_like 'caching the value'
+
+ it 'calls the existing .method_added' do
+ expect(klass.method_added_list).to include(:method_name_attr)
+ end
+ end
+
+ context "memoized before method definition with different member name and value #{value}" do
+ let(:method_name) { :different_method_name_attr }
+ let(:member_name) { :different_member_name_attr }
+
+ it_behaves_like 'caching the value'
+
+ it 'calls the existing .method_added' do
+ expect(klass.method_added_list).to include(:different_method_name_attr)
+ end
+ end
+
+ context 'with valid method name' do
+ let(:method_name) { :enabled? }
+
+ context 'with invalid member name' do
+ let(:member_name) { :enabled? }
+
+ it 'is invalid' do
+ expect { object.send(method_name) { value } }.to raise_error /is not allowed as an instance variable name/
+ end
+ end
+ end
+ end
+
+ describe 'method visibility' do
+ it 'sets private visibility' do
+ expect(klass.private_instance_methods).to include(:private_method)
+ expect(klass.protected_instance_methods).not_to include(:private_method)
+ expect(klass.public_instance_methods).not_to include(:private_method)
+ end
+
+ it 'sets protected visibility' do
+ expect(klass.private_instance_methods).not_to include(:protected_method)
+ expect(klass.protected_instance_methods).to include(:protected_method)
+ expect(klass.public_instance_methods).not_to include(:protected_method)
+ end
+
+ it 'sets public visibility' do
+ expect(klass.private_instance_methods).not_to include(:public_method)
+ expect(klass.protected_instance_methods).not_to include(:public_method)
+ expect(klass.public_instance_methods).to include(:public_method)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index 25ba5a3e09e..13d046b0816 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Utils::UsageData do
end
describe '#add_metric' do
- let(:metric) { 'UuidMetric'}
+ let(:metric) { 'UuidMetric' }
it 'computes the metric value for given metric' do
expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 0648d276a6b..ad1a65ffae8 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe Gitlab::Utils do
end
it 'raises error for a non-string' do
- expect {check_allowed_absolute_path_and_path_traversal!(nil, allowed_paths)}.to raise_error(StandardError)
+ expect { check_allowed_absolute_path_and_path_traversal!(nil, allowed_paths) }.to raise_error(StandardError)
end
it 'raises an exception if an absolute path is not allowed' do
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Utils do
end
describe '.allowlisted?' do
- let(:allowed_paths) { ['/home/foo', '/foo/bar', '/etc/passwd']}
+ let(:allowed_paths) { ['/home/foo', '/foo/bar', '/etc/passwd'] }
it 'returns true if path is allowed' do
expect(allowlisted?('/foo/bar', allowed_paths)).to be(true)
diff --git a/spec/lib/gitlab/verify/uploads_spec.rb b/spec/lib/gitlab/verify/uploads_spec.rb
index 3e5154d5029..f9aa196ffde 100644
--- a/spec/lib/gitlab/verify/uploads_spec.rb
+++ b/spec/lib/gitlab/verify/uploads_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe Gitlab::Verify::Uploads do
end
def perform_task
- described_class.new(batch_size: 100).run_batches { }
+ described_class.new(batch_size: 100).run_batches {}
end
end
end
diff --git a/spec/lib/gitlab/version_info_spec.rb b/spec/lib/gitlab/version_info_spec.rb
index 6ed094f11c8..078f952afad 100644
--- a/spec/lib/gitlab/version_info_spec.rb
+++ b/spec/lib/gitlab/version_info_spec.rb
@@ -79,11 +79,12 @@ RSpec.describe Gitlab::VersionInfo do
describe '.unknown' do
it { expect(@unknown).not_to be @v0_0_1 }
it { expect(@unknown).not_to be described_class.new }
- it { expect {@unknown > @v0_0_1}.to raise_error(ArgumentError) }
- it { expect {@unknown < @v0_0_1}.to raise_error(ArgumentError) }
+ it { expect { @unknown > @v0_0_1 }.to raise_error(ArgumentError) }
+ it { expect { @unknown < @v0_0_1 }.to raise_error(ArgumentError) }
end
describe '.parse' do
+ it { expect(described_class.parse(described_class.new(1, 0, 0))).to eq(@v1_0_0) }
it { expect(described_class.parse("1.0.0")).to eq(@v1_0_0) }
it { expect(described_class.parse("1.0.0.1")).to eq(@v1_0_0) }
it { expect(described_class.parse("1.0.0-ee")).to eq(@v1_0_0) }
@@ -133,6 +134,20 @@ RSpec.describe Gitlab::VersionInfo do
it { expect(@unknown.to_s).to eq("Unknown") }
end
+ describe '.to_json' do
+ let(:correct_version) do
+ "{\"major\":1,\"minor\":0,\"patch\":1}"
+ end
+
+ let(:unknown_version) do
+ "{\"major\":0,\"minor\":0,\"patch\":0}"
+ end
+
+ it { expect(@v1_0_1.to_json).to eq(correct_version) }
+ it { expect(@v1_0_1_rc2.to_json).to eq(correct_version) }
+ it { expect(@unknown.to_json).to eq(unknown_version) }
+ end
+
describe '.hash' do
it { expect(described_class.parse("1.0.0").hash).to eq(@v1_0_0.hash) }
it { expect(described_class.parse("1.0.0.1").hash).to eq(@v1_0_0.hash) }
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index ba49c00245e..aeca7b09a88 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -10,6 +10,25 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
let(:gcp_project_id) { String('gcp_proj_id') }
let(:operation) { true }
let(:database_instance) { Google::Apis::SqladminV1beta4::DatabaseInstance.new(state: 'RUNNABLE') }
+ let(:instance_name) { 'mock-instance-name' }
+ let(:root_password) { 'mock-root-password' }
+ let(:database_version) { 'mock-database-version' }
+ let(:region) { 'mock-region' }
+ 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)
+ ])
+ 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)
+ ])
+ end
describe '.session_key_for_redirect_uri' do
let(:state) { 'random_string' }
@@ -217,7 +236,11 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
describe '#list_projects' do
subject { client.list_projects }
- let(:list_of_projects) { [{}, {}, {}] }
+ let(:gcp_project_01) { Google::Apis::CloudresourcemanagerV1::Project.new(project_id: '01') }
+ let(:gcp_project_02) { Google::Apis::CloudresourcemanagerV1::Project.new(project_id: '02') }
+ let(:gcp_project_03) { Google::Apis::CloudresourcemanagerV1::Project.new(project_id: '03') }
+ let(:list_of_projects) { [gcp_project_03, gcp_project_01, gcp_project_02] }
+
let(:next_page_token) { nil }
let(:operation) { double('projects': list_of_projects, 'next_page_token': next_page_token) }
@@ -225,7 +248,8 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
expect_any_instance_of(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService)
.to receive(:list_projects)
.and_return(operation)
- is_expected.to eq(list_of_projects)
+
+ is_expected.to contain_exactly(gcp_project_01, gcp_project_02, gcp_project_03)
end
end
@@ -337,6 +361,42 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
end
end
+ describe '#enable_cloud_sql_admin' do
+ subject { client.enable_cloud_sql_admin(gcp_project_id) }
+
+ it 'calls Google Api ServiceUsageService' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/sqladmin.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
+ describe '#enable_compute' do
+ subject { client.enable_compute(gcp_project_id) }
+
+ it 'calls Google Api ServiceUsageService' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/compute.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
+ describe '#enable_service_networking' do
+ subject { client.enable_service_networking(gcp_project_id) }
+
+ it 'calls Google Api ServiceUsageService' do
+ expect_any_instance_of(Google::Apis::ServiceusageV1::ServiceUsageService)
+ .to receive(:enable_service)
+ .with("projects/#{gcp_project_id}/services/servicenetworking.googleapis.com")
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
describe '#revoke_authorizations' do
subject { client.revoke_authorizations }
@@ -388,4 +448,57 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
is_expected.to eq(database_instance)
end
end
+
+ describe '#list_cloudsql_databases' do
+ subject { client.list_cloudsql_databases(:gcp_project_id, :instance_name) }
+
+ it 'calls Google Api SQLAdminService#list_databases' do
+ expect_any_instance_of(Google::Apis::SqladminV1beta4::SQLAdminService)
+ .to receive(:list_databases)
+ .with(any_args)
+ .and_return(database_list)
+ is_expected.to eq(database_list)
+ end
+ end
+
+ describe '#list_cloudsql_users' do
+ subject { client.list_cloudsql_users(:gcp_project_id, :instance_name) }
+
+ it 'calls Google Api SQLAdminService#list_users' do
+ expect_any_instance_of(Google::Apis::SqladminV1beta4::SQLAdminService)
+ .to receive(:list_users)
+ .with(any_args)
+ .and_return(user_list)
+ is_expected.to eq(user_list)
+ end
+ end
+
+ describe '#create_cloudsql_instance' do
+ subject do
+ client.create_cloudsql_instance(
+ gcp_project_id,
+ instance_name,
+ root_password,
+ database_version,
+ region,
+ tier
+ )
+ end
+
+ it 'calls Google Api SQLAdminService#insert_instance' do
+ expect_any_instance_of(Google::Apis::SqladminV1beta4::SQLAdminService)
+ .to receive(:insert_instance)
+ .with(gcp_project_id,
+ having_attributes(
+ class: ::Google::Apis::SqladminV1beta4::DatabaseInstance,
+ name: instance_name,
+ root_password: root_password,
+ database_version: database_version,
+ region: region,
+ settings: instance_of(Google::Apis::SqladminV1beta4::Settings)
+ ))
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
end
diff --git a/spec/lib/json_web_token/rsa_token_spec.rb b/spec/lib/json_web_token/rsa_token_spec.rb
index 6d2026752d6..b77345d8b7a 100644
--- a/spec/lib/json_web_token/rsa_token_spec.rb
+++ b/spec/lib/json_web_token/rsa_token_spec.rb
@@ -30,8 +30,9 @@ RSpec.describe JSONWebToken::RSAToken do
subject { JWT.decode(rsa_encoded, rsa_key, true, { algorithm: 'RS256' }) }
- it { expect {subject}.not_to raise_error }
+ it { expect { subject }.not_to raise_error }
it { expect(subject.first).to include('key' => 'value') }
+
it do
expect(subject.second).to eq(
"typ" => "JWT",
@@ -45,7 +46,7 @@ RSpec.describe JSONWebToken::RSAToken do
subject { JWT.decode(rsa_encoded, new_key, true, { algorithm: 'RS256' }) }
- it { expect {subject}.to raise_error(JWT::DecodeError) }
+ it { expect { subject }.to raise_error(JWT::DecodeError) }
end
end
end
diff --git a/spec/lib/marginalia_spec.rb b/spec/lib/marginalia_spec.rb
index 693b7bd45c9..59add4e8347 100644
--- a/spec/lib/marginalia_spec.rb
+++ b/spec/lib/marginalia_spec.rb
@@ -11,10 +11,15 @@ RSpec.describe 'Marginalia spec' do
render body: nil
end
+ def first_ci_pipeline
+ Ci::Pipeline.first
+ render body: nil
+ end
+
private
[:auth_user, :current_user, :set_experimentation_subject_id_cookie, :signed_in?].each do |method|
- define_method(method) { }
+ define_method(method) {}
end
end
@@ -36,7 +41,7 @@ RSpec.describe 'Marginalia spec' do
describe 'For rails web requests' do
let(:correlation_id) { SecureRandom.uuid }
- let(:recorded) { ActiveRecord::QueryRecorder.new { make_request(correlation_id) } }
+ let(:recorded) { ActiveRecord::QueryRecorder.new { make_request(correlation_id, :first_user) } }
let(:component_map) do
{
@@ -54,10 +59,11 @@ RSpec.describe 'Marginalia spec' do
end
context 'when using CI database' do
+ let(:recorded) { ActiveRecord::QueryRecorder.new { make_request(correlation_id, :first_ci_pipeline) } }
let(:component_map) do
{
"application" => "test",
- "endpoint_id" => "MarginaliaTestController#first_user",
+ "endpoint_id" => "MarginaliaTestController#first_ci_pipeline",
"correlation_id" => correlation_id,
"db_config_name" => 'ci'
}
@@ -65,8 +71,6 @@ RSpec.describe 'Marginalia spec' do
before do
skip_if_multiple_databases_not_setup
-
- allow(User).to receive(:connection) { Ci::ApplicationRecord.connection }
end
it 'generates a query that includes the component and value' do
@@ -140,11 +144,11 @@ RSpec.describe 'Marginalia spec' do
end
end
- def make_request(correlation_id)
+ def make_request(correlation_id, action_name)
request_env = Rack::MockRequest.env_for('/')
::Labkit::Correlation::CorrelationId.use_id(correlation_id) do
- MarginaliaTestController.action(:first_user).call(request_env)
+ MarginaliaTestController.action(action_name).call(request_env)
end
end
end
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index 2158076e4b5..d208ef93224 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Mattermost::Session, type: :request do
describe '#with session' do
let(:location) { 'http://location.tld' }
- let(:cookie_header) {'MMOAUTH=taskik8az7rq8k6rkpuas7htia; Path=/;'}
+ let(:cookie_header) { 'MMOAUTH=taskik8az7rq8k6rkpuas7htia; Path=/;' }
let!(:stub) do
stub_full_request("#{mattermost_url}/oauth/gitlab/login")
.to_return(headers: { 'location' => location, 'Set-Cookie' => cookie_header }, status: 302)
diff --git a/spec/lib/microsoft_teams/notifier_spec.rb b/spec/lib/microsoft_teams/notifier_spec.rb
index 3b7892334dd..905b118d934 100644
--- a/spec/lib/microsoft_teams/notifier_spec.rb
+++ b/spec/lib/microsoft_teams/notifier_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe MicrosoftTeams::Notifier do
subject { described_class.new(webhook_url) }
- let(:webhook_url) { 'https://example.gitlab.com/'}
+ let(:webhook_url) { 'https://example.gitlab.com/' }
let(:header) { { 'Content-Type' => 'application/json' } }
let(:options) do
{
diff --git a/spec/lib/release_highlights/validator/entry_spec.rb b/spec/lib/release_highlights/validator/entry_spec.rb
index 5f7ccbf4310..b8b745ac8cd 100644
--- a/spec/lib/release_highlights/validator/entry_spec.rb
+++ b/spec/lib/release_highlights/validator/entry_spec.rb
@@ -25,18 +25,18 @@ RSpec.describe ReleaseHighlights::Validator::Entry do
it 'returns line numbers in errors' do
subject.valid?
- expect(entry.errors[:packages].first).to match('(line 6)')
+ expect(entry.errors[:available_in].first).to match('(line 6)')
end
end
context 'with a blank entry' do
- it 'validate presence of title, body and stage' do
+ it 'validate presence of name, description and stage' do
subject.valid?
- expect(subject.errors[:title]).not_to be_empty
- expect(subject.errors[:body]).not_to be_empty
+ expect(subject.errors[:name]).not_to be_empty
+ expect(subject.errors[:description]).not_to be_empty
expect(subject.errors[:stage]).not_to be_empty
- expect(subject.errors[:packages]).not_to be_empty
+ expect(subject.errors[:available_in]).not_to be_empty
end
it 'validates boolean value of "self-managed" and "gitlab-com"' do
@@ -52,11 +52,11 @@ RSpec.describe ReleaseHighlights::Validator::Entry do
it 'validates URI of "url" and "image_url"' do
stub_env('RSPEC_ALLOW_INVALID_URLS', 'false')
allow(entry).to receive(:value_for).with(:image_url).and_return('https://foobar.x/images/ci/gitlab-ci-cd-logo_2x.png')
- allow(entry).to receive(:value_for).with(:url).and_return('')
+ allow(entry).to receive(:value_for).with(:documentation_link).and_return('')
subject.valid?
- expect(subject.errors[:url]).to include(/must be a valid URL/)
+ expect(subject.errors[:documentation_link]).to include(/must be a valid URL/)
expect(subject.errors[:image_url]).to include(/is blocked: Host cannot be resolved or invalid/)
end
@@ -76,12 +76,12 @@ RSpec.describe ReleaseHighlights::Validator::Entry do
expect(subject.errors[:published_at]).to include(/must be valid Date/)
end
- it 'validates packages are included in list' do
- allow(entry).to receive(:value_for).with(:packages).and_return(['ALL'])
+ it 'validates available_in are included in list' do
+ allow(entry).to receive(:value_for).with(:available_in).and_return(['ALL'])
subject.valid?
- expect(subject.errors[:packages].first).to include("must be one of", "Free", "Premium", "Ultimate")
+ expect(subject.errors[:available_in].first).to include("must be one of", "Free", "Premium", "Ultimate")
end
end
end
diff --git a/spec/lib/release_highlights/validator_spec.rb b/spec/lib/release_highlights/validator_spec.rb
index f30754b4167..dd1b3aa4803 100644
--- a/spec/lib/release_highlights/validator_spec.rb
+++ b/spec/lib/release_highlights/validator_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe ReleaseHighlights::Validator do
---------------------------------------------------------
Validation failed for spec/fixtures/whats_new/invalid.yml
---------------------------------------------------------
- * Packages must be one of ["Free", "Premium", "Ultimate"] (line 6)
+ * Available in must be one of ["Free", "Premium", "Ultimate"] (line 6)
MESSAGE
end
diff --git a/spec/lib/security/report_schema_version_matcher_spec.rb b/spec/lib/security/report_schema_version_matcher_spec.rb
new file mode 100644
index 00000000000..9c40f0bc6fa
--- /dev/null
+++ b/spec/lib/security/report_schema_version_matcher_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Security::ReportSchemaVersionMatcher do
+ let(:vendored_versions) { %w[14.0.0 14.0.1 14.0.2 14.1.0] }
+ let(:version_finder) do
+ described_class.new(
+ report_declared_version: report_version,
+ supported_versions: vendored_versions
+ )
+ end
+
+ describe '#call' do
+ subject { version_finder.call }
+
+ context 'when minor version matches' do
+ context 'and report schema patch version does not match any vendored schema versions' do
+ context 'and report version is 14.1.1' do
+ let(:report_version) { '14.1.1' }
+
+ it 'returns 14.1.0' do
+ expect(subject).to eq('14.1.0')
+ end
+ end
+
+ context 'and report version is 14.0.32' do
+ let(:report_version) { '14.0.32' }
+
+ it 'returns 14.0.2' do
+ expect(subject).to eq('14.0.2')
+ end
+ end
+ end
+ end
+
+ context 'when report minor version does not match' do
+ let(:report_version) { '14.2.1' }
+
+ it 'does not return a version' do
+ expect(subject).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb b/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb
index 5f67ee11970..1b27db53b6f 100644
--- a/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb
+++ b/spec/lib/sidebars/groups/menus/group_information_menu_spec.rb
@@ -18,13 +18,13 @@ RSpec.describe Sidebars::Groups::Menus::GroupInformationMenu do
subject { described_class.new(context).title }
context 'when group is a root group' do
- specify { is_expected.to eq 'Group information'}
+ specify { is_expected.to eq 'Group information' }
end
context 'when group is a child group' do
let(:group) { build(:group, parent: root_group) }
- specify { is_expected.to eq 'Subgroup information'}
+ specify { is_expected.to eq 'Subgroup information' }
end
end
@@ -32,13 +32,13 @@ RSpec.describe Sidebars::Groups::Menus::GroupInformationMenu do
subject { described_class.new(context).sprite_icon }
context 'when group is a root group' do
- specify { is_expected.to eq 'group'}
+ specify { is_expected.to eq 'group' }
end
context 'when group is a child group' do
let(:group) { build(:group, parent: root_group) }
- specify { is_expected.to eq 'subgroup'}
+ specify { is_expected.to eq 'subgroup' }
end
end
diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb
index bdd9f22d5a0..53a889c2db8 100644
--- a/spec/lib/sidebars/menu_spec.rb
+++ b/spec/lib/sidebars/menu_spec.rb
@@ -219,7 +219,7 @@ RSpec.describe Sidebars::Menu do
end
describe '#link' do
- let(:foo_path) { '/foo_path'}
+ let(:foo_path) { '/foo_path' }
let(:foo_menu) do
::Sidebars::MenuItem.new(
diff --git a/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb b/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb
index dfb3c511470..4e17e91f019 100644
--- a/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb
+++ b/spec/lib/tasks/gitlab/metrics_exporter_task_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'gitlab:metrics_exporter:install' do
let(:expected_clone_params) do
{
repo: 'https://gitlab.com/gitlab-org/gitlab-metrics-exporter.git',
- version: 'main',
+ version: an_instance_of(String),
target_dir: 'path/to/exporter'
}
end
diff --git a/spec/lib/unnested_in_filters/rewriter_spec.rb b/spec/lib/unnested_in_filters/rewriter_spec.rb
index e2ccbd92504..a808aec7728 100644
--- a/spec/lib/unnested_in_filters/rewriter_spec.rb
+++ b/spec/lib/unnested_in_filters/rewriter_spec.rb
@@ -88,6 +88,35 @@ RSpec.describe UnnestedInFilters::Rewriter do
expect(issued_query.gsub(/\s/, '')).to start_with(expected_query.gsub(/\s/, ''))
end
+ context 'when the relation has a subquery' do
+ let(:relation) { User.where(state: User.select(:state), user_type: %i(support_bot alert_bot)).limit(1) }
+
+ let(:expected_query) do
+ <<~SQL
+ SELECT
+ "users".*
+ FROM
+ unnest(ARRAY(SELECT "users"."state" FROM "users")::character varying[]) AS "states"("state"),
+ unnest('{1,2}'::smallint[]) AS "user_types"("user_type"),
+ LATERAL (
+ SELECT
+ "users".*
+ FROM
+ "users"
+ WHERE
+ (users."state" = "states"."state") AND
+ (users."user_type" = "user_types"."user_type")
+ LIMIT 1
+ ) AS users
+ LIMIT 1
+ SQL
+ end
+
+ it 'changes the query' do
+ expect(issued_query.gsub(/\s/, '')).to start_with(expected_query.gsub(/\s/, ''))
+ end
+ end
+
context 'when there is an order' do
let(:relation) { User.where(state: %w(active blocked banned)).order(order).limit(2) }
let(:expected_query) do
diff --git a/spec/mailers/emails/admin_notification_spec.rb b/spec/mailers/emails/admin_notification_spec.rb
index 1b770d6d4a2..33b8558bfa3 100644
--- a/spec/mailers/emails/admin_notification_spec.rb
+++ b/spec/mailers/emails/admin_notification_spec.rb
@@ -11,68 +11,4 @@ RSpec.describe Emails::AdminNotification do
expect(Notify).to be_respond_to(email_method)
end
end
-
- describe 'user_auto_banned_email' do
- let_it_be(:admin) { create(:user) }
- let_it_be(:user) { create(:user) }
-
- let(:max_project_downloads) { 5 }
- let(:time_period) { 600 }
- let(:group) { nil }
-
- subject do
- Notify.user_auto_banned_email(
- admin.id, user.id,
- max_project_downloads: max_project_downloads,
- within_seconds: time_period,
- group: group
- )
- end
-
- it_behaves_like 'an email sent from GitLab'
- it_behaves_like 'it should not have Gmail Actions links'
- it_behaves_like 'a user cannot unsubscribe through footer link'
- it_behaves_like 'appearance header and footer enabled'
- it_behaves_like 'appearance header and footer not enabled'
-
- it 'is sent to the administrator' do
- is_expected.to deliver_to admin.email
- end
-
- it 'has the correct subject' do
- is_expected.to have_subject "We've detected unusual activity"
- end
-
- it 'includes the name of the user' do
- is_expected.to have_body_text user.name
- end
-
- it 'includes the scope of the ban' do
- is_expected.to have_body_text "banned from your GitLab instance"
- end
-
- it 'includes the reason' do
- is_expected.to have_body_text "due to them downloading more than 5 project repositories within 10 minutes"
- end
-
- it 'includes a link to unban the user' do
- is_expected.to have_body_text admin_users_url(filter: 'banned')
- end
-
- it 'includes a link to change the settings' do
- is_expected.to have_body_text network_admin_application_settings_url(anchor: 'js-ip-limits-settings')
- 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
-
- context 'when scoped to a group' do
- let(:group) { create(:group) }
-
- it 'includes the scope of the ban' do
- is_expected.to have_body_text "banned from your group (#{group.name})"
- end
- end
- end
end
diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb
index 09ed27eb90f..fce55256922 100644
--- a/spec/mailers/emails/profile_spec.rb
+++ b/spec/mailers/emails/profile_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe Emails::Profile do
describe 'for users that signed up, the email' do
let(:example_site_path) { root_path }
- let(:new_user) { create(:user, email: new_user_address, password: "securePassword") }
+ let(:new_user) { create(:user, email: new_user_address) }
subject { Notify.new_user_email(new_user.id) }
@@ -59,6 +59,7 @@ RSpec.describe Emails::Profile do
it_behaves_like 'a user cannot unsubscribe through footer link'
it 'does not contain the new user\'s password' do
+ is_expected.not_to have_body_text(new_user.password)
is_expected.not_to have_body_text /password/
end
end
diff --git a/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
deleted file mode 100644
index 9a59c739ecd..00000000000
--- a/spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleUpdateJiraTrackerDataDeploymentTypeBasedOnUrl, :migration do
- let(:services_table) { table(:services) }
- let(:service_jira_cloud) { services_table.create!(id: 1, type: 'JiraService') }
- let(:service_jira_server) { services_table.create!(id: 2, type: 'JiraService') }
-
- before do
- jira_tracker_data = Class.new(ApplicationRecord) do
- self.table_name = 'jira_tracker_data'
-
- def self.encryption_options
- {
- key: Settings.attr_encrypted_db_key_base_32,
- encode: true,
- mode: :per_attribute_iv,
- algorithm: 'aes-256-gcm'
- }
- end
-
- attr_encrypted :url, encryption_options
- attr_encrypted :api_url, encryption_options
- attr_encrypted :username, encryption_options
- attr_encrypted :password, encryption_options
- end
-
- stub_const('JiraTrackerData', jira_tracker_data)
- stub_const("#{described_class}::BATCH_SIZE", 1)
- end
-
- let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, service_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: 0) }
- let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, service_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: 0) }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules background migration' do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_migration(tracker_data_cloud.id, tracker_data_cloud.id)
- expect(described_class::MIGRATION).to be_scheduled_migration(tracker_data_server.id, tracker_data_server.id)
- end
-end
diff --git a/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb b/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
index d35184e78a8..8dfeacc4774 100644
--- a/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
+++ b/spec/migrations/2021061716138_cascade_delete_freeze_periods_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
require_migration!
-RSpec.describe CascadeDeleteFreezePeriods do
+RSpec.describe CascadeDeleteFreezePeriods, :suppress_gitlab_schemas_validate_connection do
let(:namespace) { table(:namespaces).create!(name: 'deploy_freeze', path: 'deploy_freeze') }
let(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
let(:freeze_periods) { table(:ci_freeze_periods) }
diff --git a/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
index 29f554a003b..13a6aa5413e 100644
--- a/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
+++ b/spec/migrations/20210818185845_backfill_projects_with_coverage_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe BackfillProjectsWithCoverage do
+RSpec.describe BackfillProjectsWithCoverage, :suppress_gitlab_schemas_validate_connection do
let(:projects) { table(:projects) }
let(:ci_pipelines) { table(:ci_pipelines) }
let(:ci_daily_build_group_report_results) { table(:ci_daily_build_group_report_results) }
diff --git a/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
index c1d96f50dc8..cf6a033b4b8 100644
--- a/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
require_migration!
-RSpec.describe ScheduleRemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration do
+RSpec.describe ScheduleRemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings,
+ :suppress_gitlab_schemas_validate_connection, :migration do
let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let_it_be(:users) { table(:users) }
diff --git a/spec/migrations/20220124130028_dedup_runner_projects_spec.rb b/spec/migrations/20220124130028_dedup_runner_projects_spec.rb
index 127f4798f33..3429ccc4df1 100644
--- a/spec/migrations/20220124130028_dedup_runner_projects_spec.rb
+++ b/spec/migrations/20220124130028_dedup_runner_projects_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe DedupRunnerProjects, :migration, schema: 20220120085655 do
+RSpec.describe DedupRunnerProjects, :migration, :suppress_gitlab_schemas_validate_connection, schema: 20220120085655 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:runners) { table(:ci_runners) }
diff --git a/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb b/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb
index a48464befdf..a23f9995875 100644
--- a/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb
+++ b/spec/migrations/20220128155251_remove_dangling_running_builds_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!('remove_dangling_running_builds')
-RSpec.describe RemoveDanglingRunningBuilds do
+RSpec.describe RemoveDanglingRunningBuilds, :suppress_gitlab_schemas_validate_connection do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:project) { table(:projects).create!(namespace_id: namespace.id) }
let(:runner) { table(:ci_runners).create!(runner_type: 1) }
@@ -47,6 +47,6 @@ RSpec.describe RemoveDanglingRunningBuilds do
migrate!
expect(running_metadata.reload).to be_present
- expect { failed_metadata.reload } .to raise_error(ActiveRecord::RecordNotFound)
+ expect { failed_metadata.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
diff --git a/spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb b/spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb
index 0c4d0e86789..ec58a54b085 100644
--- a/spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb
+++ b/spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
require_migration!
RSpec.describe UpdateIndexOnAlertsToExcludeNullFingerprints do
- let(:alerts) { 'alert_management_alerts'}
+ let(:alerts) { 'alert_management_alerts' }
let(:old_index) { described_class::OLD_INDEX_NAME }
let(:new_index) { described_class::NEW_INDEX_NAME }
diff --git a/spec/migrations/20220506154054_create_sync_namespace_details_trigger_spec.rb b/spec/migrations/20220506154054_create_sync_namespace_details_trigger_spec.rb
new file mode 100644
index 00000000000..411b1eacb86
--- /dev/null
+++ b/spec/migrations/20220506154054_create_sync_namespace_details_trigger_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe CreateSyncNamespaceDetailsTrigger do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:namespace_details) { table(:namespace_details) }
+ let!(:timestamp) { Time.new(2020, 01, 01).utc }
+
+ let(:synced_attributes) do
+ {
+ description: 'description',
+ description_html: '<p>description</p>',
+ cached_markdown_version: 1966080,
+ created_at: timestamp,
+ updated_at: timestamp
+ }
+ end
+
+ let(:other_attributes) do
+ {
+ name: 'name',
+ path: 'path'
+ }
+ end
+
+ let(:attributes) { other_attributes.merge(synced_attributes) }
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'INSERT trigger' do
+ it 'creates a namespace_detail record' do
+ expect do
+ namespaces.create!(attributes)
+ end.to change(namespace_details, :count).by(1)
+ end
+
+ it 'the created namespace_details record has matching attributes' do
+ namespaces.create!(attributes)
+ synced_namespace_details = namespace_details.last
+
+ expect(synced_namespace_details).to have_attributes(synced_attributes)
+ end
+ end
+
+ describe 'UPDATE trigger' do
+ let!(:namespace) { namespaces.create!(attributes) }
+
+ it 'updates the attribute in the synced namespace_details record' do
+ namespace.update!(description: 'new_description')
+
+ synced_namespace_details = namespace_details.last
+ expect(synced_namespace_details.description).to eq('new_description')
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the trigger' do
+ expect do
+ namespaces.create!(attributes)
+ end.not_to change(namespace_details, :count)
+ end
+ end
+end
diff --git a/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb
deleted file mode 100644
index e3bc832a10b..00000000000
--- a/spec/migrations/20220520040416_schedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe ScheduleSetLegacyOpenSourceLicenseAvailableForNonPublicProjects do
- context 'on gitlab.com' do
- let(:migration) { described_class::MIGRATION }
-
- before do
- allow(Gitlab).to receive(:com?).and_return(true)
- end
-
- describe '#up' do
- it 'schedules background jobs for each batch of projects' do
- migrate!
-
- expect(migration).to(
- have_scheduled_batched_migration(
- table_name: :projects,
- 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
- migrate!
- schema_migrate_down!
-
- expect(migration).not_to have_scheduled_batched_migration
- end
- end
- end
-
- context 'on self-managed instance' do
- let(:migration) { described_class.new }
-
- before do
- allow(Gitlab).to receive(:com?).and_return(false)
- end
-
- describe '#up' do
- it 'does not schedule background job' do
- expect(migration).not_to receive(:queue_batched_background_migration)
-
- migration.up
- end
- end
-
- describe '#down' do
- it 'does not delete background job' do
- expect(migration).not_to receive(:delete_batched_background_migration)
-
- migration.down
- end
- end
- end
-end
diff --git a/spec/migrations/20220524184149_create_sync_project_namespace_details_trigger_spec.rb b/spec/migrations/20220524184149_create_sync_project_namespace_details_trigger_spec.rb
new file mode 100644
index 00000000000..f85a59357e1
--- /dev/null
+++ b/spec/migrations/20220524184149_create_sync_project_namespace_details_trigger_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe CreateSyncProjectNamespaceDetailsTrigger do
+ let(:migration) { described_class.new }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:namespace_details) { table(:namespace_details) }
+ let!(:timestamp) { Time.new(2020, 01, 01).utc }
+ let!(:project_namespace) { namespaces.create!(name: 'name', path: 'path') }
+ let!(:namespace) { namespaces.create!(name: 'group', path: 'group_path') }
+
+ let(:synced_attributes) do
+ {
+ description: 'description',
+ description_html: '<p>description</p>',
+ cached_markdown_version: 1966080,
+ updated_at: timestamp
+ }
+ end
+
+ let(:other_attributes) do
+ {
+ name: 'project_name',
+ project_namespace_id: project_namespace.id,
+ namespace_id: namespace.id
+ }
+ end
+
+ let(:attributes) { other_attributes.merge(synced_attributes) }
+
+ describe '#up' do
+ before do
+ migrate!
+ end
+
+ describe 'INSERT trigger' do
+ it 'the created namespace_details record has matching attributes' do
+ project = projects.create!(attributes)
+ synced_namespace_details = namespace_details.find_by(namespace_id: project.project_namespace_id)
+
+ expect(synced_namespace_details).to have_attributes(synced_attributes)
+ end
+ end
+
+ describe 'UPDATE trigger' do
+ let!(:project) { projects.create!(attributes) }
+
+ it 'updates the attribute in the synced namespace_details record' do
+ project.update!(description: 'new_description')
+
+ synced_namespace_details = namespace_details.find_by(namespace_id: project.project_namespace_id)
+ expect(synced_namespace_details.description).to eq('new_description')
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ migration.up
+ migration.down
+ end
+
+ it 'drops the trigger' do
+ expect do
+ projects.create!(attributes)
+ end.not_to change(namespace_details, :count)
+ end
+ end
+end
diff --git a/spec/migrations/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent_spec.rb b/spec/migrations/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent_spec.rb
new file mode 100644
index 00000000000..3f1a2d8c4b9
--- /dev/null
+++ b/spec/migrations/20220525221133_schedule_backfill_vulnerability_reads_cluster_agent_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleBackfillVulnerabilityReadsClusterAgent do
+ let_it_be(:batched_migration) { described_class::MIGRATION_NAME }
+
+ it 'schedules background jobs for each batch of vulnerability reads' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :vulnerability_reads,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL
+ )
+ }
+ end
+ end
+end
diff --git a/spec/migrations/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences_spec.rb b/spec/migrations/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences_spec.rb
new file mode 100644
index 00000000000..68fac1c2221
--- /dev/null
+++ b/spec/migrations/20220607082910_add_sync_tmp_index_for_potentially_misassociated_vulnerability_occurrences_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+require_migration!
+
+RSpec.describe AddSyncTmpIndexForPotentiallyMisassociatedVulnerabilityOccurrences do
+ let(:table) { "vulnerability_occurrences" }
+ let(:index) { described_class::INDEX_NAME }
+
+ it "creates and drops the index" do
+ reversible_migration do |migration|
+ migration.before -> do
+ expect(ActiveRecord::Base.connection.indexes(table).map(&:name)).not_to include(index)
+ end
+
+ migration.after -> do
+ expect(ActiveRecord::Base.connection.indexes(table).map(&:name)).to include(index)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb b/spec/migrations/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb
new file mode 100644
index 00000000000..b17a0215f4e
--- /dev/null
+++ b/spec/migrations/20220721031446_schedule_disable_legacy_open_source_license_for_one_member_no_repo_projects_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleDisableLegacyOpenSourceLicenseForOneMemberNoRepoProjects do
+ context 'when on gitlab.com' do
+ let(:migration) { described_class::MIGRATION }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of projects' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ table_name: :projects,
+ column_name: :id,
+ interval: described_class::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
+
+ context 'when on self-managed instance' do
+ let(:migration) { described_class.new }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ end
+
+ describe '#up' do
+ it 'does not schedule background job' do
+ expect(migration).not_to receive(:queue_batched_background_migration)
+
+ migration.up
+ end
+ end
+
+ describe '#down' do
+ it 'does not delete background job' do
+ expect(migration).not_to receive(:delete_batched_background_migration)
+
+ migration.down
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb b/spec/migrations/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb
new file mode 100644
index 00000000000..cb0f941aea1
--- /dev/null
+++ b/spec/migrations/20220722084543_schedule_disable_legacy_open_source_license_for_no_issues_no_repo_projects_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleDisableLegacyOpenSourceLicenseForNoIssuesNoRepoProjects do
+ context 'when on gitlab.com' do
+ let(:migration) { described_class::MIGRATION }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of projects' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ table_name: :projects,
+ column_name: :id,
+ interval: described_class::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
+
+ context 'when on self-managed instance' do
+ let(:migration) { described_class.new }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ end
+
+ describe '#up' do
+ it 'does not schedule background job' do
+ expect(migration).not_to receive(:queue_batched_background_migration)
+
+ migration.up
+ end
+ end
+
+ describe '#down' do
+ it 'does not delete background job' do
+ expect(migration).not_to receive(:delete_batched_background_migration)
+
+ migration.down
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/migrations/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb
new file mode 100644
index 00000000000..99a30c7f2a9
--- /dev/null
+++ b/spec/migrations/20220722110026_reschedule_set_legacy_open_source_license_available_for_non_public_projects_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe RescheduleSetLegacyOpenSourceLicenseAvailableForNonPublicProjects do
+ context 'when on gitlab.com' do
+ let(:migration) { described_class::MIGRATION }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of projects' do
+ migrate!
+
+ expect(migration).to(
+ have_scheduled_batched_migration(
+ table_name: :projects,
+ column_name: :id,
+ interval: described_class::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
+
+ context 'when on self-managed instance' do
+ let(:migration) { described_class.new }
+
+ before do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ end
+
+ describe '#up' do
+ it 'does not schedule background job' do
+ expect(migration).not_to receive(:queue_batched_background_migration)
+
+ migration.up
+ end
+ end
+
+ describe '#down' do
+ it 'does not delete background job' do
+ expect(migration).not_to receive(:delete_batched_background_migration)
+
+ migration.down
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20220725150127_update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/migrations/20220725150127_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
new file mode 100644
index 00000000000..2651e46ba53
--- /dev/null
+++ b/spec/migrations/20220725150127_update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe UpdateJiraTrackerDataDeploymentTypeBasedOnUrl, :migration do
+ let(:integrations_table) { table(:integrations) }
+ let(:service_jira_cloud) { integrations_table.create!(id: 1, type_new: 'JiraService') }
+ let(:service_jira_server) { integrations_table.create!(id: 2, type_new: 'JiraService') }
+
+ before do
+ jira_tracker_data = Class.new(ApplicationRecord) do
+ self.table_name = 'jira_tracker_data'
+
+ def self.encryption_options
+ {
+ key: Settings.attr_encrypted_db_key_base_32,
+ encode: true,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm'
+ }
+ end
+
+ attr_encrypted :url, encryption_options
+ attr_encrypted :api_url, encryption_options
+ attr_encrypted :username, encryption_options
+ attr_encrypted :password, encryption_options
+ end
+
+ stub_const('JiraTrackerData', jira_tracker_data)
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 1)
+ end
+
+ # rubocop:disable Layout/LineLength
+ # rubocop:disable RSpec/ScatteredLet
+ let!(:tracker_data_cloud) { JiraTrackerData.create!(id: 1, integration_id: service_jira_cloud.id, url: "https://test-domain.atlassian.net", deployment_type: 0) }
+ let!(:tracker_data_server) { JiraTrackerData.create!(id: 2, integration_id: service_jira_server.id, url: "http://totally-not-jira-server.company.org", deployment_type: 0) }
+ # rubocop:enable Layout/LineLength
+ # rubocop:enable RSpec/ScatteredLet
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ let(:migration) { described_class::MIGRATION } # rubocop:disable RSpec/ScatteredLet
+
+ it 'schedules background migration' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :jira_tracker_data,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ gitlab_schema: :gitlab_main
+ )
+ end
+end
diff --git a/spec/migrations/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics_spec.rb b/spec/migrations/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics_spec.rb
new file mode 100644
index 00000000000..cc1c1dac4c3
--- /dev/null
+++ b/spec/migrations/20220802114351_reschedule_backfill_container_registry_size_into_project_statistics_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe RescheduleBackfillContainerRegistrySizeIntoProjectStatistics do
+ let_it_be(:batched_migration) { described_class::MIGRATION_CLASS }
+
+ it 'does not schedule background jobs when Gitlab.com is false' do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(false)
+
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+ end
+ end
+
+ it 'schedules background jobs for each batch of container_repository' do
+ allow(Gitlab).to receive(:com?).and_return(true)
+
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :container_repositories,
+ column_name: :project_id,
+ interval: described_class::DELAY_INTERVAL
+ )
+ }
+ end
+ end
+end
diff --git a/spec/migrations/20220802204737_remove_deactivated_user_highest_role_stats_spec.rb b/spec/migrations/20220802204737_remove_deactivated_user_highest_role_stats_spec.rb
new file mode 100644
index 00000000000..3ea286ca138
--- /dev/null
+++ b/spec/migrations/20220802204737_remove_deactivated_user_highest_role_stats_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe RemoveDeactivatedUserHighestRoleStats do
+ let!(:users) { table(:users) }
+ let!(:user_highest_roles) { table(:user_highest_roles) }
+
+ let!(:user1) do
+ users.create!(username: 'user1', email: 'user1@example.com', projects_limit: 10, state: 'active')
+ end
+
+ let!(:user2) do
+ users.create!(username: 'user2', email: 'user2@example.com', projects_limit: 10, state: 'deactivated')
+ end
+
+ let!(:highest_role1) { user_highest_roles.create!(user_id: user1.id) }
+ let!(:highest_role2) { user_highest_roles.create!(user_id: user2.id) }
+
+ describe '#up' do
+ context 'when on gitlab.com' do
+ it 'does not change user highest role records' do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ expect { migrate! }.not_to change(user_highest_roles, :count)
+ end
+ end
+
+ context 'when not on gitlab.com' do
+ it 'removes all user highest role records for deactivated users' do
+ allow(Gitlab).to receive(:com?).and_return(false)
+ migrate!
+ expect(user_highest_roles.pluck(:user_id)).to contain_exactly(
+ user1.id
+ )
+ end
+ end
+ end
+end
diff --git a/spec/migrations/associate_existing_dast_builds_with_variables_spec.rb b/spec/migrations/associate_existing_dast_builds_with_variables_spec.rb
index 74429e498df..dd86989912f 100644
--- a/spec/migrations/associate_existing_dast_builds_with_variables_spec.rb
+++ b/spec/migrations/associate_existing_dast_builds_with_variables_spec.rb
@@ -4,73 +4,7 @@ require 'spec_helper'
require_migration!
RSpec.describe AssociateExistingDastBuildsWithVariables do
- subject(:migration) { described_class.new }
-
- let_it_be(:namespaces_table) { table(:namespaces) }
- let_it_be(:projects_table) { table(:projects) }
- let_it_be(:ci_pipelines_table) { table(:ci_pipelines) }
- let_it_be(:ci_builds_table) { table(:ci_builds) }
- let_it_be(:dast_sites_table) { table(:dast_sites) }
- let_it_be(:dast_site_profiles_table) { table(:dast_site_profiles) }
- let_it_be(:dast_scanner_profiles_table) { table(:dast_scanner_profiles) }
- let_it_be(:dast_site_profiles_builds_table) { table(:dast_site_profiles_builds) }
- let_it_be(:dast_profiles_table) { table(:dast_profiles) }
- let_it_be(:dast_profiles_pipelines_table) { table(:dast_profiles_pipelines) }
-
- let!(:group) { namespaces_table.create!(type: 'Group', name: 'group', path: 'group') }
- let!(:project) { projects_table.create!(name: 'project', path: 'project', namespace_id: group.id) }
-
- let!(:pipeline_0) { ci_pipelines_table.create!(project_id: project.id, source: 13) }
- let!(:pipeline_1) { ci_pipelines_table.create!(project_id: project.id, source: 13) }
- let!(:build_0) { ci_builds_table.create!(project_id: project.id, commit_id: pipeline_0.id, name: :dast, stage: :dast) }
- let!(:build_1) { ci_builds_table.create!(project_id: project.id, commit_id: pipeline_0.id, name: :dast, stage: :dast) }
- let!(:build_2) { ci_builds_table.create!(project_id: project.id, commit_id: pipeline_1.id, name: :dast, stage: :dast) }
- let!(:build_3) { ci_builds_table.create!(project_id: project.id, commit_id: pipeline_1.id, name: :dast) }
- let!(:build_4) { ci_builds_table.create!(project_id: project.id, commit_id: pipeline_1.id, stage: :dast) }
-
- let!(:dast_site) { dast_sites_table.create!(project_id: project.id, url: generate(:url)) }
- let!(:dast_site_profile) { dast_site_profiles_table.create!(project_id: project.id, dast_site_id: dast_site.id, name: SecureRandom.hex) }
- let!(:dast_scanner_profile) { dast_scanner_profiles_table.create!(project_id: project.id, name: SecureRandom.hex) }
-
- let!(:dast_profile) do
- dast_profiles_table.create!(
- project_id: project.id,
- dast_site_profile_id: dast_site_profile.id,
- dast_scanner_profile_id: dast_scanner_profile.id,
- name: SecureRandom.hex,
- description: SecureRandom.hex
- )
- end
-
- let!(:dast_profiles_pipeline_0) { dast_profiles_pipelines_table.create!(dast_profile_id: dast_profile.id, ci_pipeline_id: pipeline_0.id) }
- let!(:dast_profiles_pipeline_1) { dast_profiles_pipelines_table.create!(dast_profile_id: dast_profile.id, ci_pipeline_id: pipeline_1.id) }
-
- context 'when there are ci_pipelines with associated dast_profiles' do
- describe 'migration up' do
- it 'adds association of dast_site_profiles to ci_builds', :aggregate_failures do
- expect(dast_site_profiles_builds_table.all).to be_empty
-
- migration.up
-
- expected_results = [
- [dast_site_profile.id, build_0.id],
- [dast_site_profile.id, build_1.id],
- [dast_site_profile.id, build_2.id]
- ]
-
- expect(dast_site_profiles_builds_table.all.map { |assoc| [assoc.dast_site_profile_id, assoc.ci_build_id] }).to contain_exactly(*expected_results)
- end
- end
- end
-
- describe 'migration down' do
- it 'deletes all records in the dast_site_profiles_builds table', :aggregate_failures do
- expect(dast_site_profiles_builds_table.all).to be_empty
-
- migration.up
- migration.down
-
- expect(dast_site_profiles_builds_table.all).to be_empty
- end
+ it 'is a no-op' do
+ migrate!
end
end
diff --git a/spec/migrations/backfill_project_import_level_spec.rb b/spec/migrations/backfill_project_import_level_spec.rb
new file mode 100644
index 00000000000..c24ddac0730
--- /dev/null
+++ b/spec/migrations/backfill_project_import_level_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillProjectImportLevel do
+ let_it_be(:batched_migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of namespaces' do
+ migrate!
+
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :namespaces,
+ column_name: :id,
+ interval: described_class::INTERVAL
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/change_public_projects_cost_factor_spec.rb b/spec/migrations/change_public_projects_cost_factor_spec.rb
index 78030736093..039edda750b 100644
--- a/spec/migrations/change_public_projects_cost_factor_spec.rb
+++ b/spec/migrations/change_public_projects_cost_factor_spec.rb
@@ -3,16 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe ChangePublicProjectsCostFactor, :migration do
- # This is a workaround to force the migration to run against the
- # `gitlab_ci` schema. Otherwise it only runs against `gitlab_main`.
- around do |example| # rubocop: disable Style/MultilineIfModifier
- with_reestablished_active_record_base do
- reconfigure_db_connection(name: :ci)
- example.run
- end
- end if Gitlab::Database.has_config?(:ci)
-
+RSpec.describe ChangePublicProjectsCostFactor, migration: :gitlab_ci do
let(:runners) { table(:ci_runners) }
let!(:shared_1) { runners.create!(runner_type: 1, public_projects_minutes_cost_factor: 0) }
diff --git a/spec/migrations/clean_up_pending_builds_table_spec.rb b/spec/migrations/clean_up_pending_builds_table_spec.rb
index 9c8d4413337..17e62e1b486 100644
--- a/spec/migrations/clean_up_pending_builds_table_spec.rb
+++ b/spec/migrations/clean_up_pending_builds_table_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe CleanUpPendingBuildsTable do
+RSpec.describe CleanUpPendingBuildsTable, :suppress_gitlab_schemas_validate_connection do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:queue) { table(:ci_pending_builds) }
diff --git a/spec/migrations/cleanup_mr_attention_request_todos_spec.rb b/spec/migrations/cleanup_mr_attention_request_todos_spec.rb
new file mode 100644
index 00000000000..9f593ca8292
--- /dev/null
+++ b/spec/migrations/cleanup_mr_attention_request_todos_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe CleanupMrAttentionRequestTodos, :migration do
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:users) { table(:users) }
+ let(:todos) { table(:todos) }
+
+ let(:author) { users.create!(projects_limit: 1) }
+ let(:namespace) { namespaces.create!(name: 'test', path: 'test') }
+ let(:project) do
+ projects.create!(
+ namespace_id: namespace.id,
+ project_namespace_id: namespace.id,
+ name: 'test-project'
+ )
+ end
+
+ let(:attention_requested) { 10 }
+ let(:todo_attrs) do
+ {
+ project_id: project.id,
+ author_id: author.id,
+ user_id: author.id,
+ target_type: 'TestType',
+ state: 'pending'
+ }
+ end
+
+ let!(:todo1) { todos.create!(todo_attrs.merge(action: Todo::ASSIGNED)) }
+ let!(:todo2) { todos.create!(todo_attrs.merge(action: Todo::MENTIONED)) }
+ let!(:todo3) { todos.create!(todo_attrs.merge(action: Todo::REVIEW_REQUESTED)) }
+ let!(:todo4) { todos.create!(todo_attrs.merge(action: attention_requested)) }
+ let!(:todo5) { todos.create!(todo_attrs.merge(action: attention_requested)) }
+
+ describe '#up' do
+ it 'clean up attention request todos' do
+ expect { migrate! }.to change(todos, :count).by(-2)
+
+ expect(todos.all).to include(todo1, todo2, todo3)
+ end
+ end
+end
diff --git a/spec/migrations/delete_security_findings_without_uuid_spec.rb b/spec/migrations/delete_security_findings_without_uuid_spec.rb
index b32ea89f8aa..bfd89f1aa82 100644
--- a/spec/migrations/delete_security_findings_without_uuid_spec.rb
+++ b/spec/migrations/delete_security_findings_without_uuid_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe DeleteSecurityFindingsWithoutUuid do
+RSpec.describe DeleteSecurityFindingsWithoutUuid, :suppress_gitlab_schemas_validate_connection do
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
diff --git a/spec/migrations/disable_job_token_scope_when_unused_spec.rb b/spec/migrations/disable_job_token_scope_when_unused_spec.rb
index d969c98aa0f..3ce4ef5c102 100644
--- a/spec/migrations/disable_job_token_scope_when_unused_spec.rb
+++ b/spec/migrations/disable_job_token_scope_when_unused_spec.rb
@@ -4,41 +4,7 @@ require 'spec_helper'
require_migration!
RSpec.describe DisableJobTokenScopeWhenUnused do
- let(:ci_cd_settings) { table(:project_ci_cd_settings) }
- let(:links) { table(:ci_job_token_project_scope_links) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
-
- let(:namespace) { namespaces.create!(name: 'test', path: 'path', type: 'Group') }
-
- let(:project_with_used_scope) { projects.create!(namespace_id: namespace.id) }
- let!(:used_scope_settings) { ci_cd_settings.create!(project_id: project_with_used_scope.id, job_token_scope_enabled: true) }
- let(:target_project) { projects.create!(namespace_id: namespace.id) }
- let!(:link) { links.create!(source_project_id: project_with_used_scope.id, target_project_id: target_project.id) }
-
- let(:project_with_unused_scope) { projects.create!(namespace_id: namespace.id) }
- let!(:unused_scope_settings) { ci_cd_settings.create!(project_id: project_with_unused_scope.id, job_token_scope_enabled: true) }
-
- let(:project_with_disabled_scope) { projects.create!(namespace_id: namespace.id) }
- let!(:disabled_scope_settings) { ci_cd_settings.create!(project_id: project_with_disabled_scope.id, job_token_scope_enabled: false) }
-
- describe '#up' do
- it 'sets job_token_scope_enabled to false for projects not having job token scope configured' do
- migrate!
-
- expect(unused_scope_settings.reload.job_token_scope_enabled).to be_falsey
- end
-
- it 'keeps the scope enabled for projects that are using it' do
- migrate!
-
- expect(used_scope_settings.reload.job_token_scope_enabled).to be_truthy
- end
-
- it 'keeps the scope disabled for projects having it disabled' do
- migrate!
-
- expect(disabled_scope_settings.reload.job_token_scope_enabled).to be_falsey
- end
+ it 'is a no-op' do
+ migrate!
end
end
diff --git a/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb b/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb
index 2108adcc973..01805a9eb79 100644
--- a/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb
+++ b/spec/migrations/migrate_protected_attribute_to_pending_builds_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe MigrateProtectedAttributeToPendingBuilds do
+RSpec.describe MigrateProtectedAttributeToPendingBuilds, :suppress_gitlab_schemas_validate_connection do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:queue) { table(:ci_pending_builds) }
diff --git a/spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb b/spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb
index 8a9b993b869..45a2772adda 100644
--- a/spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb
+++ b/spec/migrations/re_schedule_latest_pipeline_id_population_with_all_security_related_artifact_types_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
require_migration!
-RSpec.describe ReScheduleLatestPipelineIdPopulationWithAllSecurityRelatedArtifactTypes do
+RSpec.describe ReScheduleLatestPipelineIdPopulationWithAllSecurityRelatedArtifactTypes,
+ :suppress_gitlab_schemas_validate_connection do
let(:namespaces) { table(:namespaces) }
let(:pipelines) { table(:ci_pipelines) }
let(:projects) { table(:projects) }
diff --git a/spec/migrations/schedule_backfilling_the_namespace_id_for_vulnerability_reads_spec.rb b/spec/migrations/schedule_backfilling_the_namespace_id_for_vulnerability_reads_spec.rb
new file mode 100644
index 00000000000..e03096de98d
--- /dev/null
+++ b/spec/migrations/schedule_backfilling_the_namespace_id_for_vulnerability_reads_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe ScheduleBackfillingTheNamespaceIdForVulnerabilityReads do
+ let_it_be(:migration) { described_class::MIGRATION_NAME }
+
+ describe '#up' do
+ it 'schedules background jobs for each batch of vulnerabilities' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :vulnerability_reads,
+ column_name: :vulnerability_id,
+ interval: 2.minutes,
+ batch_size: 10_000,
+ sub_batch_size: 200
+ )
+ 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/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb b/spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb
index 012c7d065fc..67d54ea92a0 100644
--- a/spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb
+++ b/spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb
@@ -4,49 +4,7 @@ require 'spec_helper'
require_migration!
RSpec.describe ScheduleCopyCiBuildsColumnsToSecurityScans2 do
- let_it_be(:namespaces) { table(:namespaces) }
- let_it_be(:projects) { table(:projects) }
- let_it_be(:ci_pipelines) { table(:ci_pipelines) }
- let_it_be(:ci_builds) { table(:ci_builds) }
- let_it_be(:security_scans) { table(:security_scans) }
- let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
-
- let!(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:pipeline) { ci_pipelines.create!(status: "success")}
-
- let!(:build1) { ci_builds.create!(commit_id: pipeline.id, type: 'Ci::Build', project_id: project.id) }
- let!(:build2) { ci_builds.create!(commit_id: pipeline.id, type: 'Ci::Build', project_id: project.id) }
- let!(:build3) { ci_builds.create!(commit_id: pipeline.id, type: 'Ci::Build', project_id: project.id) }
-
- let!(:scan1) { security_scans.create!(build_id: build1.id, scan_type: 1) }
- let!(:scan2) { security_scans.create!(build_id: build2.id, scan_type: 1) }
- let!(:scan3) { security_scans.create!(build_id: build3.id, scan_type: 1) }
-
- let!(:job_class_name) { described_class::MIGRATION }
- let!(:tracked_pending_job) { background_migration_jobs.create!(class_name: job_class_name, status: 0, arguments: [1]) }
- let!(:tracked_successful_job) { background_migration_jobs.create!(class_name: job_class_name, status: 1, arguments: [2]) }
- let(:jobs) { Gitlab::Database::BackgroundMigrationJob.where(id: [tracked_pending_job.id, tracked_successful_job.id] ).for_migration_class(job_class_name) }
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
- allow_next_instance_of(Gitlab::BackgroundMigration::CopyCiBuildsColumnsToSecurityScans) do |instance|
- allow(instance).to receive(:mark_job_as_succeeded)
- end
- end
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules background migrations', :aggregate_failures do
- expect(jobs).not_to be_empty
-
+ it 'is a no-op' do
migrate!
-
- expect(jobs).to be_empty
- expect(BackgroundMigrationWorker.jobs.size).to eq(2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, scan1.id, scan2.id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, scan3.id, scan3.id)
end
end
diff --git a/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb b/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb
new file mode 100644
index 00000000000..f00d6568b67
--- /dev/null
+++ b/spec/migrations/schedule_migrate_shared_vulnerability_scanners_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+require_migration!
+
+RSpec.describe ScheduleMigrateSharedVulnerabilityScanners, :migration do
+ describe "#up" do
+ before do
+ migrate!
+ end
+
+ it "schedules" do
+ expect(described_class::MIGRATION).to have_scheduled_batched_migration(
+ table_name: described_class::TABLE_NAME,
+ column_name: described_class::BATCH_COLUMN,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ max_batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE,
+ gitlab_schema: :gitlab_main
+ )
+ end
+
+ describe "ID range" do
+ let(:expected_range) do
+ { min_value: described_class::BATCH_MIN_VALUE,
+ max_value: described_class::BATCH_MAX_VALUE }
+ end
+
+ subject do
+ Gitlab::Database::BackgroundMigration::BatchedMigration
+ .for_configuration(:gitlab_main,
+ described_class::MIGRATION,
+ described_class::TABLE_NAME,
+ described_class::BATCH_COLUMN,
+ [])
+ end
+
+ it "is set" do
+ # The `have_scheduled_batched_migration` matcher accepts the
+ # `batch_min_value` and `batch_max_value` keywords. However the respective
+ # column names are `min_value` and `max_value`. Hence the matcher cannot
+ # be used in this case, as it asserts the wrong attributes.
+ expect(subject).to all(have_attributes(expected_range))
+ end
+ end
+ end
+
+ describe '#down' do
+ before do
+ schema_migrate_down!
+ end
+
+ it "deletes" do
+ expect(described_class::MIGRATION).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/migrations/schedule_populate_status_column_of_security_scans_spec.rb b/spec/migrations/schedule_populate_status_column_of_security_scans_spec.rb
deleted file mode 100644
index 601935db8db..00000000000
--- a/spec/migrations/schedule_populate_status_column_of_security_scans_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require_migration!
-
-RSpec.describe SchedulePopulateStatusColumnOfSecurityScans do
- before do
- allow(Gitlab).to receive(:ee?).and_return(ee?)
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- context 'when the Gitlab instance is CE' do
- let(:ee?) { false }
-
- it 'does not run the migration' do
- expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size }
- end
- end
-
- context 'when the Gitlab instance is EE' do
- let(:ee?) { true }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:pipelines) { table(:ci_pipelines) }
- let(:builds) { table(:ci_builds) }
- let(:security_scans) { table(:security_scans) }
-
- let(:namespace) { namespaces.create!(name: "foo", path: "bar") }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') }
- let(:ci_build) { builds.create!(commit_id: pipeline.id, retried: false, type: 'Ci::Build') }
-
- let!(:security_scan_1) { security_scans.create!(build_id: ci_build.id, scan_type: 1) }
- let!(:security_scan_2) { security_scans.create!(build_id: ci_build.id, scan_type: 2) }
-
- around do |example|
- freeze_time { Sidekiq::Testing.fake! { example.run } }
- end
-
- it 'schedules the background jobs', :aggregate_failures do
- migrate!
-
- expect(BackgroundMigrationWorker.jobs.size).to be(2)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, security_scan_1.id, security_scan_1.id)
- expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, security_scan_2.id, security_scan_2.id)
- end
- end
-end
diff --git a/spec/migrations/start_backfill_ci_queuing_tables_spec.rb b/spec/migrations/start_backfill_ci_queuing_tables_spec.rb
index a1e4179efb6..08fd244089f 100644
--- a/spec/migrations/start_backfill_ci_queuing_tables_spec.rb
+++ b/spec/migrations/start_backfill_ci_queuing_tables_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe StartBackfillCiQueuingTables do
+RSpec.describe StartBackfillCiQueuingTables, :suppress_gitlab_schemas_validate_connection do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:builds) { table(:ci_builds) }
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index 751d31ad95a..5d316f7cff2 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -175,7 +175,7 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_sessions do
expect(Gitlab::Redis::Sessions).to receive(:with).and_yield(redis)
sessions = %w[session-a session-b]
- mget_responses = sessions.map { |session| [Marshal.dump(session)]}
+ mget_responses = sessions.map { |session| [Marshal.dump(session)] }
expect(redis).to receive(:mget).twice.times.and_return(*mget_responses)
expect(ActiveSession.sessions_from_ids([1, 2])).to eql(sessions)
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 0b3521cdd0c..16e1d8fbc4d 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -116,6 +116,7 @@ RSpec.describe ApplicationSetting do
it { is_expected.to validate_presence_of(:max_yaml_depth) }
it { is_expected.to validate_numericality_of(:max_yaml_depth).only_integer.is_greater_than(0) }
it { is_expected.to validate_presence_of(:max_pages_size) }
+
it 'ensures max_pages_size is an integer greater than 0 (or equal to 0 to indicate unlimited/maximum)' do
is_expected.to validate_numericality_of(:max_pages_size).only_integer.is_greater_than_or_equal_to(0)
.is_less_than(::Gitlab::Pages::MAX_SIZE / 1.megabyte)
@@ -1438,4 +1439,10 @@ RSpec.describe ApplicationSetting do
end
end
end
+
+ context 'personal accesss token prefix' do
+ it 'sets the correct default value' do
+ expect(setting.personal_access_token_prefix).to eql('glpat-')
+ end
+ end
end
diff --git a/spec/models/aws/role_spec.rb b/spec/models/aws/role_spec.rb
index ee93c9d6fad..f23f18ab44f 100644
--- a/spec/models/aws/role_spec.rb
+++ b/spec/models/aws/role_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Aws::Role do
end
context 'ARN is nil' do
- let(:role_arn) { }
+ let(:role_arn) {}
it { is_expected.to be_truthy }
end
diff --git a/spec/models/board_spec.rb b/spec/models/board_spec.rb
index 775cccd2aec..6017298e85b 100644
--- a/spec/models/board_spec.rb
+++ b/spec/models/board_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Board do
- let(:project) { create(:project) }
- let(:other_project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:other_project) { create(:project) }
describe 'relationships' do
it { is_expected.to belong_to(:project) }
diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb
index 1d2ad8b4dce..02c38479d1a 100644
--- a/spec/models/chat_name_spec.rb
+++ b/spec/models/chat_name_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe ChatName do
it { is_expected.to validate_presence_of(:team_id) }
it { is_expected.to validate_presence_of(:chat_id) }
- it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:service_id) }
- it { is_expected.to validate_uniqueness_of(:chat_id).scoped_to(:service_id, :team_id) }
+ it { is_expected.to validate_uniqueness_of(:user_id).scoped_to(:integration_id) }
+ it { is_expected.to validate_uniqueness_of(:chat_id).scoped_to(:integration_id, :team_id) }
it 'is removed when the project is deleted' do
expect { subject.reload.integration.project.delete }.to change { ChatName.count }.by(-1)
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index cb29cce554f..40c2d62c465 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe Ci::Bridge do
expect(bridge).to have_many(:sourced_pipelines)
end
+ it_behaves_like 'has ID tokens', :ci_bridge
+
it 'has one downstream pipeline' do
expect(bridge).to have_one(:sourced_pipeline)
expect(bridge).to have_one(:downstream_pipeline)
@@ -401,6 +403,18 @@ RSpec.describe Ci::Bridge do
end
end
+ describe '#downstream_project_path' do
+ context 'when trigger is defined' do
+ context 'when using variable expansion' do
+ let(:options) { { trigger: { project: 'my/$BRIDGE/project' } } }
+
+ it 'correctly expands variables' do
+ expect(bridge.downstream_project_path).to eq('my/cross/project')
+ end
+ end
+ end
+ end
+
describe '#target_ref' do
context 'when trigger is defined' do
it 'returns a ref name' do
diff --git a/spec/models/ci/build_dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb
index 91048cae064..737348765d9 100644
--- a/spec/models/ci/build_dependencies_spec.rb
+++ b/spec/models/ci/build_dependencies_spec.rb
@@ -76,8 +76,8 @@ RSpec.describe Ci::BuildDependencies do
end
describe 'jobs from specified dependencies' do
- let(:dependencies) { }
- let(:needs) { }
+ let(:dependencies) {}
+ let(:needs) {}
let!(:job) do
scheduling_type = needs.present? ? :dag : :stage
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 5e30f9160cd..e904463a5ca 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -105,6 +105,13 @@ RSpec.describe Ci::BuildMetadata do
}
}
}
+ metadata.id_tokens = {
+ TEST_JWT_TOKEN: {
+ id_token: {
+ aud: 'https://gitlab.test'
+ }
+ }
+ }
expect(metadata).to be_valid
end
@@ -113,10 +120,14 @@ RSpec.describe Ci::BuildMetadata do
context 'when data is invalid' do
it 'returns errors' do
metadata.secrets = { DATABASE_PASSWORD: { vault: {} } }
+ metadata.id_tokens = { TEST_JWT_TOKEN: { id_token: { aud: nil } } }
aggregate_failures do
expect(metadata).to be_invalid
- expect(metadata.errors.full_messages).to eq(["Secrets must be a valid json schema"])
+ expect(metadata.errors.full_messages).to contain_exactly(
+ 'Secrets must be a valid json schema',
+ 'Id tokens must be a valid json schema'
+ )
end
end
end
diff --git a/spec/models/ci/build_runner_session_spec.rb b/spec/models/ci/build_runner_session_spec.rb
index 601c6ad26f9..ed5ed456d7b 100644
--- a/spec/models/ci/build_runner_session_spec.rb
+++ b/spec/models/ci/build_runner_session_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Ci::BuildRunnerSession, model: true do
end
describe '#service_specification' do
- let(:service) { 'foo'}
+ let(:service) { 'foo' }
let(:port) { 80 }
let(:path) { 'path' }
let(:subprotocols) { nil }
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index e0166ba64a4..b865688d370 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -3,6 +3,9 @@
require 'spec_helper'
RSpec.describe Ci::Build do
+ include Ci::TemplateHelpers
+ include AfterNextHelpers
+
let_it_be(:user) { create(:user) }
let_it_be(:group, reload: true) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :repository, group: group) }
@@ -59,11 +62,36 @@ RSpec.describe Ci::Build do
describe 'callbacks' do
context 'when running after_create callback' do
- it 'triggers asynchronous build hooks worker' do
- expect(BuildHooksWorker).to receive(:perform_async)
+ it 'executes hooks' do
+ expect_next(described_class).to receive(:execute_hooks)
create(:ci_build)
end
+
+ context 'when the execute_build_hooks_inline flag is disabled' do
+ before do
+ stub_feature_flags(execute_build_hooks_inline: false)
+ end
+
+ it 'uses the old job hooks worker' do
+ expect(::BuildHooksWorker).to receive(:perform_async).with(Ci::Build)
+
+ create(:ci_build)
+ end
+ end
+
+ context 'when the execute_build_hooks_inline flag is enabled for a project' do
+ before do
+ stub_feature_flags(execute_build_hooks_inline: project)
+ end
+
+ it 'executes hooks inline' do
+ expect(::BuildHooksWorker).not_to receive(:perform_async)
+ expect_next(described_class).to receive(:execute_hooks)
+
+ create(:ci_build, project: project)
+ end
+ end
end
end
@@ -81,6 +109,8 @@ RSpec.describe Ci::Build do
end
end
+ it_behaves_like 'has ID tokens', :ci_build
+
describe '.manual_actions' do
let!(:manual_but_created) { create(:ci_build, :manual, status: :created, pipeline: pipeline) }
let!(:manual_but_succeeded) { create(:ci_build, :manual, status: :success, pipeline: pipeline) }
@@ -1289,7 +1319,7 @@ RSpec.describe Ci::Build do
let(:subject) { build.hide_secrets(data) }
context 'hide runners token' do
- let(:data) { "new #{project.runners_token} data"}
+ let(:data) { "new #{project.runners_token} data" }
it { is_expected.to match(/^new x+ data$/) }
@@ -1303,7 +1333,7 @@ RSpec.describe Ci::Build do
end
context 'hide build token' do
- let(:data) { "new #{build.token} data"}
+ let(:data) { "new #{build.token} data" }
it { is_expected.to match(/^new x+ data$/) }
@@ -1335,6 +1365,43 @@ RSpec.describe Ci::Build do
end
end
+ describe 'state transition metrics' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { build.send(event) }
+
+ where(:ff_enabled, :state, :report_count, :trait) do
+ true | :success! | 1 | :sast
+ true | :cancel! | 1 | :sast
+ true | :drop! | 2 | :multiple_report_artifacts
+ true | :success! | 0 | :allowed_to_fail
+ true | :skip! | 0 | :pending
+ false | :success! | 0 | :sast
+ end
+
+ with_them do
+ let(:build) { create(:ci_build, trait, project: project, pipeline: pipeline) }
+ let(:event) { state }
+
+ context "when transitioning to #{params[:state]}" do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ stub_feature_flags(report_artifact_build_completed_metrics_on_build_completion: ff_enabled)
+ end
+
+ it 'increments build_completed_report_type metric' do
+ expect(
+ ::Gitlab::Ci::Artifacts::Metrics
+ ).to receive(
+ :build_completed_report_type_counter
+ ).exactly(report_count).times.and_call_original
+
+ subject
+ end
+ end
+ end
+ end
+
describe 'state transition as a deployable' do
subject { build.send(event) }
@@ -1518,8 +1585,8 @@ RSpec.describe Ci::Build do
end
end
- describe '#environment_deployment_tier' do
- subject { build.environment_deployment_tier }
+ describe '#environment_tier_from_options' do
+ subject { build.environment_tier_from_options }
let(:build) { described_class.new(options: options) }
let(:options) { { environment: { deployment_tier: 'production' } } }
@@ -1533,6 +1600,30 @@ RSpec.describe Ci::Build do
end
end
+ describe '#environment_tier' do
+ subject { build.environment_tier }
+
+ let(:options) { { environment: { deployment_tier: 'production' } } }
+ let!(:environment) { create(:environment, name: 'production', tier: 'development', project: project) }
+ let(:build) { described_class.new(options: options, environment: 'production', project: project) }
+
+ it { is_expected.to eq('production') }
+
+ context 'when options does not include deployment_tier' do
+ let(:options) { { environment: { name: 'production' } } }
+
+ it 'uses tier from environment' do
+ is_expected.to eq('development')
+ end
+
+ context 'when persisted environment is absent' do
+ let(:environment) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+
describe 'environment' do
describe '#has_environment?' do
subject { build.has_environment? }
@@ -1601,20 +1692,18 @@ RSpec.describe Ci::Build do
end
it 'returns an expanded environment name with a list of variables' do
- expect(build).to receive(:simple_variables).once.and_call_original
-
is_expected.to eq('review/host')
end
context 'when build metadata has already persisted the expanded environment name' do
before do
- build.metadata.expanded_environment_name = 'review/host'
+ build.metadata.expanded_environment_name = 'review/foo'
end
it 'returns a persisted expanded environment name without a list of variables' do
expect(build).not_to receive(:simple_variables)
- is_expected.to eq('review/host')
+ is_expected.to eq('review/foo')
end
end
end
@@ -1642,14 +1731,6 @@ RSpec.describe Ci::Build do
end
it { is_expected.to eq('review/master') }
-
- context 'when the FF ci_expand_environment_name_and_url is disabled' do
- before do
- stub_feature_flags(ci_expand_environment_name_and_url: false)
- end
-
- it { is_expected.to eq('review/${CI_COMMIT_REF_NAME}') }
- end
end
end
@@ -1693,7 +1774,7 @@ RSpec.describe Ci::Build do
end
context 'with a dynamic value' do
- let(:namespace) { 'deploy-$CI_COMMIT_REF_NAME'}
+ let(:namespace) { 'deploy-$CI_COMMIT_REF_NAME' }
it { is_expected.to eq 'deploy-master' }
end
@@ -1806,6 +1887,21 @@ RSpec.describe Ci::Build do
end
context 'build is erasable' do
+ context 'logging erase' do
+ let!(:build) { create(:ci_build, :test_reports, :trace_artifact, :success, :artifacts) }
+
+ it 'logs erased artifacts' do
+ expect(Gitlab::Ci::Artifacts::Logger)
+ .to receive(:log_deleted)
+ .with(
+ match_array(build.job_artifacts.to_a),
+ 'Ci::Build#erase'
+ )
+
+ build.erase
+ end
+ end
+
context 'when project is undergoing stats refresh' do
let!(:build) { create(:ci_build, :test_reports, :trace_artifact, :success, :artifacts) }
@@ -1908,7 +2004,14 @@ RSpec.describe Ci::Build do
end
end
- it "erases erasable artifacts" do
+ it "erases erasable artifacts and logs them" do
+ expect(Gitlab::Ci::Artifacts::Logger)
+ .to receive(:log_deleted)
+ .with(
+ match_array(build.job_artifacts.erasable.to_a),
+ 'Ci::Build#erase_erasable_artifacts!'
+ )
+
subject
expect(build.job_artifacts.erasable).to be_empty
@@ -2627,7 +2730,7 @@ RSpec.describe Ci::Build do
build.update_columns(token_encrypted: nil)
end
- it { is_expected.to be_nil}
+ it { is_expected.to be_nil }
end
end
@@ -2812,6 +2915,7 @@ RSpec.describe Ci::Build do
public: true,
masked: false },
{ key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false },
+ { key: 'CI_TEMPLATE_REGISTRY_HOST', value: template_registry_host, public: true, masked: false },
{ key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false },
{ key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
{ key: 'CI_PIPELINE_CREATED_AT', value: pipeline.created_at.iso8601, public: true, masked: false },
@@ -2929,7 +3033,7 @@ RSpec.describe Ci::Build do
let(:expected_variables) do
predefined_variables.map { |variable| variable.fetch(:key) } +
%w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
- CI_ENVIRONMENT_TIER CI_ENVIRONMENT_ACTION CI_ENVIRONMENT_URL]
+ CI_ENVIRONMENT_ACTION CI_ENVIRONMENT_TIER CI_ENVIRONMENT_URL]
end
before do
@@ -3096,6 +3200,16 @@ RSpec.describe Ci::Build do
end
end
+ context 'when environment_tier is updated in options' do
+ before do
+ build.update!(options: { environment: { name: 'production', deployment_tier: 'development' } })
+ end
+
+ it 'uses tier from options' do
+ is_expected.to include({ key: 'CI_ENVIRONMENT_TIER', value: 'development', public: true, masked: false })
+ end
+ end
+
context 'when project has an environment specific variable' do
let(:environment_specific_variable) do
{ key: 'MY_STAGING_ONLY_VARIABLE', value: 'environment_specific_variable', public: false, masked: false }
@@ -3508,8 +3622,8 @@ RSpec.describe Ci::Build do
context 'when gitlab-deploy-token does not exist for project' do
it 'does not include deploy token variables' do
- expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER'}).to be_nil
- expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD'}).to be_nil
+ expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER' }).to be_nil
+ expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD' }).to be_nil
end
context 'when gitlab-deploy-token exists for group' do
@@ -3527,8 +3641,8 @@ RSpec.describe Ci::Build do
end
it 'does not include deploy token variables' do
- expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER'}).to be_nil
- expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD'}).to be_nil
+ expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER' }).to be_nil
+ expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD' }).to be_nil
end
end
end
@@ -3559,10 +3673,10 @@ RSpec.describe Ci::Build do
context 'when harbor_integration does not exist' do
it 'does not include harbor variables' do
- expect(subject.find { |v| v[:key] == 'HARBOR_URL'}).to be_nil
- expect(subject.find { |v| v[:key] == 'HARBOR_PROJECT_NAME'}).to be_nil
- expect(subject.find { |v| v[:key] == 'HARBOR_USERNAME'}).to be_nil
- expect(subject.find { |v| v[:key] == 'HARBOR_PASSWORD'}).to be_nil
+ expect(subject.find { |v| v[:key] == 'HARBOR_URL' }).to be_nil
+ expect(subject.find { |v| v[:key] == 'HARBOR_PROJECT_NAME' }).to be_nil
+ expect(subject.find { |v| v[:key] == 'HARBOR_USERNAME' }).to be_nil
+ expect(subject.find { |v| v[:key] == 'HARBOR_PASSWORD' }).to be_nil
end
end
end
@@ -3807,8 +3921,20 @@ RSpec.describe Ci::Build do
build.enqueue
end
- it 'queues BuildHooksWorker' do
- expect(BuildHooksWorker).to receive(:perform_async).with(build)
+ context 'when the execute_build_hooks_inline flag is disabled' do
+ before do
+ stub_feature_flags(execute_build_hooks_inline: false)
+ end
+
+ it 'queues BuildHooksWorker' do
+ expect(BuildHooksWorker).to receive(:perform_async).with(build)
+
+ build.enqueue
+ end
+ end
+
+ it 'executes hooks' do
+ expect(build).to receive(:execute_hooks)
build.enqueue
end
@@ -4526,7 +4652,7 @@ RSpec.describe Ci::Build do
end
describe '#each_report' do
- let(:report_types) { Ci::JobArtifact::COVERAGE_REPORT_FILE_TYPES }
+ let(:report_types) { Ci::JobArtifact.file_types_for_report(:coverage) }
let!(:codequality) { create(:ci_job_artifact, :codequality, job: build) }
let!(:coverage) { create(:ci_job_artifact, :coverage_gocov_xml, job: build) }
@@ -4559,6 +4685,7 @@ RSpec.describe Ci::Build do
end
before do
+ allow(build).to receive(:execute_hooks)
stub_artifacts_object_storage
end
@@ -5499,7 +5626,7 @@ RSpec.describe Ci::Build do
build.cancel_gracefully?
end
- let_it_be(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
it 'cannot cancel gracefully' do
expect(subject).to be false
@@ -5520,4 +5647,58 @@ RSpec.describe Ci::Build do
let!(:model) { create(:ci_build, user: create(:user)) }
let!(:parent) { model.user }
end
+
+ describe '#clone' do
+ let_it_be(:user) { FactoryBot.build(:user) }
+
+ context 'when given new job variables' do
+ context 'when the cloned build has an action' do
+ it 'applies the new job variables' do
+ build = create(:ci_build, :actionable)
+ 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.save!
+
+ expect(new_build.job_variables.count).to be(2)
+ expect(new_build.job_variables.pluck(:key)).to contain_exactly('TEST_KEY', 'NEW_KEY')
+ expect(new_build.job_variables.map(&:value)).to contain_exactly('new value', 'exciting new value')
+ end
+ end
+
+ context 'when the cloned build does not have an action' do
+ it 'applies the old job variables' 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.save!
+
+ expect(new_build.job_variables.count).to be(1)
+ expect(new_build.job_variables.pluck(:key)).to contain_exactly('TEST_KEY')
+ expect(new_build.job_variables.map(&:value)).to contain_exactly('old value')
+ end
+ end
+ end
+
+ context 'when not given new job variables' do
+ it 'applies the old job variables' 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_build.save!
+
+ expect(new_build.job_variables.count).to be(1)
+ expect(new_build.job_variables.pluck(:key)).to contain_exactly('TEST_KEY')
+ expect(new_build.job_variables.map(&:value)).to contain_exactly('old value')
+ end
+ end
+ end
end
diff --git a/spec/models/ci/daily_build_group_report_result_spec.rb b/spec/models/ci/daily_build_group_report_result_spec.rb
index 43ba4c32477..d0141a1469e 100644
--- a/spec/models/ci/daily_build_group_report_result_spec.rb
+++ b/spec/models/ci/daily_build_group_report_result_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::DailyBuildGroupReportResult do
- let(:daily_build_group_report_result) { build(:ci_daily_build_group_report_result)}
+ let(:daily_build_group_report_result) { build(:ci_daily_build_group_report_result) }
describe 'associations' do
it { is_expected.to belong_to(:last_pipeline) }
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index b9cac6c3f99..b996bf84529 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -128,6 +128,18 @@ RSpec.describe Ci::JobArtifact do
end
end
+ describe '.file_types_for_report' do
+ it 'returns the report file types for the report type' do
+ expect(described_class.file_types_for_report(:test)).to match_array(%w[junit])
+ end
+
+ context 'when given an unrecognized report type' do
+ it 'raises error' do
+ expect { described_class.file_types_for_report(:blah) }.to raise_error(KeyError, /blah/)
+ end
+ end
+ end
+
describe '.associated_file_types_for' do
using RSpec::Parameterized::TableSyntax
@@ -193,7 +205,7 @@ RSpec.describe Ci::JobArtifact do
it { is_expected.to be_truthy }
context 'when the job does have archived trace' do
- let!(:artifact) { }
+ let!(:artifact) {}
it { is_expected.to be_falsy }
end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 3c295fb345b..b28b61e2b39 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Ci::PipelineSchedule do
end
context 'when there are no runnable schedules' do
- let!(:pipeline_schedule) { }
+ let!(:pipeline_schedule) {}
it 'returns an empty array' do
is_expected.to be_empty
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 6a71b2cfbed..0c28c99c113 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -844,6 +844,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it 'has 8 items' do
expect(subject.size).to eq(8)
end
+
it { expect(pipeline.sha).to start_with(subject) }
end
@@ -2162,6 +2163,60 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#modified_paths_since' do
+ let(:project) do
+ create(:project, :custom_repo,
+ files: { 'file1.txt' => 'file 1' })
+ end
+
+ let(:user) { project.owner }
+ let(:main_branch) { project.default_branch }
+ let(:new_branch) { 'feature_x' }
+ let(:pipeline) { build(:ci_pipeline, project: project, sha: new_branch) }
+
+ subject(:modified_paths_since) { pipeline.modified_paths_since(main_branch) }
+
+ before do
+ project.repository.add_branch(user, new_branch, main_branch)
+ end
+
+ context 'when no change in the new branch' do
+ it 'returns an empty array' do
+ expect(modified_paths_since).to be_empty
+ end
+ end
+
+ context 'when adding a new file' do
+ before do
+ project.repository.create_file(user, 'file2.txt', 'file 2', message: 'Create file2.txt', branch_name: new_branch)
+ end
+
+ it 'returns the new file path' do
+ expect(modified_paths_since).to eq(['file2.txt'])
+ end
+
+ context 'and when updating an existing file' do
+ before do
+ project.repository.update_file(user, 'file1.txt', 'file 1 updated', message: 'Update file1.txt', branch_name: new_branch)
+ end
+
+ it 'returns the new and updated file paths' do
+ expect(modified_paths_since).to eq(['file1.txt', 'file2.txt'])
+ end
+ end
+ end
+
+ context 'when updating an existing file' do
+ before do
+ project.repository.update_file(user, 'file1.txt', 'file 1 updated', message: 'Update file1.txt', branch_name: new_branch)
+ end
+
+ it 'returns the updated file path' do
+ expect(modified_paths_since).to eq(['file1.txt'])
+ end
+ end
+ end
+
describe '#all_worktree_paths' do
let(:files) { { 'main.go' => '', 'mocks/mocks.go' => '' } }
let(:project) { create(:project, :custom_repo, files: files) }
@@ -2866,7 +2921,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#cancel_running' do
- subject(:latest_status) { pipeline.statuses.pluck(:status) }
+ let(:latest_status) { pipeline.statuses.pluck(:status) }
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
@@ -2909,6 +2964,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ context 'with bridge jobs' do
+ before do
+ create(:ci_bridge, :created, pipeline: pipeline)
+
+ pipeline.cancel_running
+ end
+
+ it 'bridges are canceled' do
+ expect(pipeline.bridges.first.status).to eq 'canceled'
+ end
+ end
+
+ context 'when pipeline is not cancelable' do
+ before do
+ create(:ci_build, :canceled, stage_idx: 0, pipeline: pipeline)
+
+ pipeline.cancel_running
+ end
+
+ it 'does not send cancel signal to cancel self' do
+ expect(pipeline).not_to receive(:cancel_self_only)
+
+ pipeline.cancel_running
+ end
+ end
+
context 'preloading relations' do
let(:pipeline1) { create(:ci_empty_pipeline, :created) }
let(:pipeline2) { create(:ci_empty_pipeline, :created) }
@@ -2940,37 +3021,211 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
- context 'when the first try cannot get an exclusive lock' do
- let(:retries) { 1 }
+ shared_examples 'retries' do
+ context 'when the first try cannot get an exclusive lock' do
+ let(:retries) { 1 }
- subject(:cancel_running) { pipeline.cancel_running(retries: retries) }
+ subject { pipeline.cancel_running(retries: retries) }
- before do
- build = create(:ci_build, :running, pipeline: pipeline)
+ before do
+ create(:ci_build, :running, pipeline: pipeline)
- allow(pipeline.cancelable_statuses).to receive(:find_in_batches).and_yield([build])
+ stub_first_cancel_call_fails
+ end
+
+ it 'retries again and cancels the build' do
+ subject
+
+ expect(latest_status).to contain_exactly('canceled')
+ end
+ context 'when the retries parameter is 0' do
+ let(:retries) { 0 }
+
+ it 'raises error' do
+ expect { subject }.to raise_error(ActiveRecord::StaleObjectError)
+ end
+ end
+ end
+
+ def stub_first_cancel_call_fails
call_count = 0
- allow(build).to receive(:cancel).and_wrap_original do |original, *args|
- call_count >= retries ? raise(ActiveRecord::StaleObjectError) : original.call(*args)
- call_count += 1
+ allow_next_found_instance_of(Ci::Build) do |build|
+ allow(build).to receive(:cancel).and_wrap_original do |original, *args| # rubocop:disable RSpec/AnyInstanceOf
+ call_count >= retries ? raise(ActiveRecord::StaleObjectError) : original.call(*args)
+
+ call_count += 1
+ end
end
end
+ end
+
+ it_behaves_like 'retries'
- it 'retries again and cancels the build' do
- cancel_running
+ context 'when auto canceled' do
+ let!(:canceled_by) { create(:ci_empty_pipeline) }
- expect(latest_status).to contain_exactly('canceled')
+ before do
+ create(:ci_build, :running, pipeline: pipeline)
+
+ pipeline.cancel_running(auto_canceled_by_pipeline_id: canceled_by.id)
+ end
+
+ it 'sets auto cancel' do
+ jobs_canceled_by = pipeline.statuses.map { |s| s.auto_canceled_by.id }
+
+ expect(jobs_canceled_by).to contain_exactly(canceled_by.id)
+ expect(pipeline.auto_canceled_by.id).to eq(canceled_by.id)
end
+ end
- context 'when the retries parameter is 0' do
- let(:retries) { 0 }
+ context 'when there are child pipelines', :sidekiq_inline do
+ let_it_be(:child_pipeline) { create(:ci_empty_pipeline, :created, child_of: pipeline) }
- it 'raises error' do
- expect do
+ before do
+ project.clear_memoization(:cascade_cancel_pipelines_enabled)
+
+ pipeline.reload
+ end
+
+ context 'when cascade_to_children is true' do
+ let(:cascade_to_children) { true }
+ let(:canceled_by) { nil }
+ let(:execute_async) { true }
+
+ let(:params) do
+ {
+ cascade_to_children: cascade_to_children,
+ execute_async: execute_async
+ }.tap do |p|
+ p.merge!(auto_canceled_by_pipeline_id: canceled_by.id) if canceled_by
+ end
+ end
+
+ subject(:cancel_running) { pipeline.cancel_running(**params) }
+
+ context 'when cancelable child pipeline builds' do
+ before do
+ create(:ci_build, :created, pipeline: child_pipeline)
+ create(:ci_build, :running, pipeline: child_pipeline)
+ end
+
+ it 'cancels child builds' do
cancel_running
- end.to raise_error(ActiveRecord::StaleObjectError)
+
+ latest_status_for_child = child_pipeline.statuses.pluck(:status)
+ expect(latest_status_for_child).to eq %w(canceled canceled)
+ expect(latest_status).to eq %w(canceled)
+ end
+
+ it 'cancels bridges' do
+ create(:ci_bridge, :created, pipeline: pipeline)
+ create(:ci_bridge, :created, pipeline: child_pipeline)
+
+ cancel_running
+
+ expect(pipeline.bridges.reload.first.status).to eq 'canceled'
+ expect(child_pipeline.bridges.reload.first.status).to eq 'canceled'
+ end
+
+ context 'with nested child pipelines' do
+ let!(:nested_child_pipeline) { create(:ci_empty_pipeline, :created, child_of: child_pipeline) }
+ let!(:nested_child_pipeline_build) { create(:ci_build, :created, pipeline: nested_child_pipeline) }
+
+ it 'cancels them' do
+ cancel_running
+
+ expect(nested_child_pipeline.reload.status).to eq 'canceled'
+ expect(nested_child_pipeline_build.reload.status).to eq 'canceled'
+ end
+ end
+
+ context 'when auto canceled' do
+ let(:canceled_by) { create(:ci_empty_pipeline) }
+
+ it 'sets auto cancel' do
+ cancel_running
+
+ pipeline.reload
+
+ jobs_canceled_by_ids = pipeline.statuses.map(&:auto_canceled_by_id)
+ child_pipelines_canceled_by_ids = pipeline.child_pipelines.map(&:auto_canceled_by_id)
+ child_pipelines_jobs_canceled_by_ids = pipeline.child_pipelines.map(&:statuses).flatten.map(&:auto_canceled_by_id)
+
+ expect(jobs_canceled_by_ids).to contain_exactly(canceled_by.id)
+ expect(pipeline.auto_canceled_by_id).to eq(canceled_by.id)
+ expect(child_pipelines_canceled_by_ids).to contain_exactly(canceled_by.id)
+ expect(child_pipelines_jobs_canceled_by_ids).to contain_exactly(canceled_by.id, canceled_by.id)
+ end
+ end
+
+ context 'when execute_async is false' do
+ let(:execute_async) { false }
+
+ it 'runs sync' do
+ expect(::Ci::CancelPipelineWorker).not_to receive(:perform_async)
+
+ cancel_running
+ end
+
+ it 'cancels children' do
+ cancel_running
+
+ latest_status_for_child = child_pipeline.statuses.pluck(:status)
+ expect(latest_status_for_child).to eq %w(canceled canceled)
+ expect(latest_status).to eq %w(canceled)
+ end
+
+ context 'with nested child pipelines' do
+ let!(:nested_child_pipeline) { create(:ci_empty_pipeline, :created, child_of: child_pipeline) }
+ let!(:nested_child_pipeline_build) { create(:ci_build, :created, pipeline: nested_child_pipeline) }
+
+ it 'cancels them' do
+ cancel_running
+
+ expect(nested_child_pipeline.reload.status).to eq 'canceled'
+ expect(nested_child_pipeline_build.reload.status).to eq 'canceled'
+ end
+ end
+ end
+ end
+
+ it 'does not cancel uncancelable child pipeline builds' do
+ create(:ci_build, :failed, pipeline: child_pipeline)
+
+ cancel_running
+
+ latest_status_for_child = child_pipeline.statuses.pluck(:status)
+ expect(latest_status_for_child).to eq %w(failed)
+ expect(latest_status).to eq %w(canceled)
+ end
+ end
+
+ context 'when cascade_to_children is false' do
+ let(:cascade_to_children) { false }
+
+ subject(:cancel_running) { pipeline.cancel_running(cascade_to_children: cascade_to_children) }
+
+ it 'does not cancel cancelable child pipeline builds' do
+ create(:ci_build, :created, pipeline: child_pipeline)
+ create(:ci_build, :running, pipeline: child_pipeline)
+
+ cancel_running
+
+ latest_status_for_child = child_pipeline.statuses.order_id_desc.pluck(:status)
+ expect(latest_status_for_child).to eq %w(running created)
+ expect(latest_status).to eq %w(canceled)
+ end
+
+ it 'does not cancel uncancelable child pipeline builds' do
+ create(:ci_build, :failed, pipeline: child_pipeline)
+
+ cancel_running
+
+ latest_status_for_child = child_pipeline.statuses.pluck(:status)
+ expect(latest_status_for_child).to eq %w(failed)
+ expect(latest_status).to eq %w(canceled)
end
end
end
@@ -3352,7 +3607,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
context 'when pipeline is a triggered pipeline' do
- let!(:upstream) { create(:ci_pipeline, project: create(:project), upstream_of: pipeline)}
+ let!(:upstream) { create(:ci_pipeline, project: create(:project), upstream_of: pipeline) }
it 'returns self id' do
expect(subject).to contain_exactly(pipeline.id)
@@ -4335,24 +4590,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
end
-
- describe '#find_stage_by_name' do
- subject { pipeline.find_stage_by_name!(stage_name) }
-
- context 'when stage exists' do
- it { is_expected.to eq(stage) }
- end
-
- context 'when stage does not exist' do
- let(:stage_name) { 'build' }
-
- it 'raises an ActiveRecord exception' do
- expect do
- subject
- end.to raise_exception(ActiveRecord::RecordNotFound)
- end
- end
- end
end
describe '#full_error_messages' do
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index 789ae3a2ccc..127a1417d9e 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe Ci::Processable do
job_artifacts_network_referee job_artifacts_dotenv
job_artifacts_cobertura needs job_artifacts_accessibility
job_artifacts_requirements job_artifacts_coverage_fuzzing
- job_artifacts_api_fuzzing terraform_state_versions].freeze
+ job_artifacts_api_fuzzing terraform_state_versions job_artifacts_cyclonedx].freeze
end
let(:ignore_accessors) do
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 2fbfbbaf830..ae8748f8ae3 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -489,7 +489,7 @@ RSpec.describe Ci::Runner do
let!(:runner3) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago) }
let!(:runner4) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago) }
- it { is_expected.to eq([runner1, runner3, runner4])}
+ it { is_expected.to eq([runner1, runner3, runner4]) }
end
describe '.active' do
@@ -552,6 +552,10 @@ RSpec.describe Ci::Runner do
allow_any_instance_of(described_class).to receive(:cached_attribute).and_call_original
allow_any_instance_of(described_class).to receive(:cached_attribute)
.with(:platform).and_return("darwin")
+ allow_any_instance_of(described_class).to receive(:cached_attribute)
+ .with(:version).and_return("14.0.0")
+
+ allow(Ci::Runners::ProcessRunnerVersionUpdateWorker).to receive(:perform_async).once
end
context 'table tests' do
@@ -623,6 +627,10 @@ RSpec.describe Ci::Runner do
allow_any_instance_of(described_class).to receive(:cached_attribute).and_call_original
allow_any_instance_of(described_class).to receive(:cached_attribute)
.with(:platform).and_return("darwin")
+ allow_any_instance_of(described_class).to receive(:cached_attribute)
+ .with(:version).and_return("14.0.0")
+
+ allow(Ci::Runners::ProcessRunnerVersionUpdateWorker).to receive(:perform_async).once
end
context 'no cache value' do
@@ -693,19 +701,6 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq([runner1]) }
end
- describe '#tick_runner_queue' do
- it 'sticks the runner to the primary and calls the original method' do
- runner = create(:ci_runner)
-
- expect(described_class.sticking).to receive(:stick)
- .with(:runner, runner.id)
-
- expect(Gitlab::Workhorse).to receive(:set_key_and_notify)
-
- runner.tick_runner_queue
- end
- end
-
describe '#matches_build?' do
using RSpec::Parameterized::TableSyntax
@@ -866,7 +861,7 @@ RSpec.describe Ci::Runner do
describe '#status' do
let(:runner) { build(:ci_runner, :instance, created_at: 4.months.ago) }
- let(:legacy_mode) { }
+ let(:legacy_mode) {}
subject { runner.status(legacy_mode) }
@@ -989,6 +984,16 @@ RSpec.describe Ci::Runner do
it 'returns a new last_update value' do
expect(runner.tick_runner_queue).not_to be_empty
end
+
+ it 'sticks the runner to the primary and calls the original method' do
+ runner = create(:ci_runner)
+
+ expect(described_class.sticking).to receive(:stick).with(:runner, runner.id)
+
+ expect(Gitlab::Workhorse).to receive(:set_key_and_notify)
+
+ runner.tick_runner_queue
+ end
end
describe '#ensure_runner_queue_value' do
@@ -1055,14 +1060,19 @@ RSpec.describe Ci::Runner do
it 'updates cache' do
expect_redis_update
+ expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).not_to receive(:perform_async)
heartbeat
+
+ expect(runner.runner_version).to be_nil
end
end
context 'when database was not updated recently' do
before do
runner.contacted_at = 2.hours.ago
+
+ allow(Ci::Runners::ProcessRunnerVersionUpdateWorker).to receive(:perform_async)
end
context 'with invalid runner' do
@@ -1075,12 +1085,25 @@ RSpec.describe Ci::Runner do
expect_redis_update
does_db_update
+
+ expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).to have_received(:perform_async).once
+ end
+ end
+
+ context 'with unchanged runner version' do
+ let(:runner) { create(:ci_runner, version: version) }
+
+ it 'does not schedule ci_runner_versions update' do
+ heartbeat
+
+ expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).not_to have_received(:perform_async)
end
end
it 'updates redis cache and database' do
expect_redis_update
does_db_update
+ expect(Ci::Runners::ProcessRunnerVersionUpdateWorker).to have_received(:perform_async).once
end
%w(custom shell docker docker-windows docker-ssh ssh parallels virtualbox docker+machine docker-ssh+machine kubernetes some-unknown-type).each do |executor|
@@ -1795,11 +1818,21 @@ RSpec.describe Ci::Runner do
end
context ':recommended' do
- let(:upgrade_status) { :recommended}
+ let(:upgrade_status) { :recommended }
it 'returns runners whose version is assigned :recommended' do
is_expected.to contain_exactly(runner_14_1_0)
end
end
+
+ describe 'composed with other scopes' do
+ subject { described_class.active(false).with_upgrade_status(:available) }
+
+ let(:inactive_runner_14_0_0) { create(:ci_runner, version: '14.0.0', active: false) }
+
+ it 'returns runner matching the composed scope' do
+ is_expected.to contain_exactly(inactive_runner_14_0_0)
+ end
+ end
end
end
diff --git a/spec/models/ci/runner_version_spec.rb b/spec/models/ci/runner_version_spec.rb
index d3395942a39..7a4b2e8f21e 100644
--- a/spec/models/ci/runner_version_spec.rb
+++ b/spec/models/ci/runner_version_spec.rb
@@ -27,16 +27,11 @@ RSpec.describe Ci::RunnerVersion do
create(:ci_runner_version, version: 'abc456', status: :available)
end
- let_it_be(:runner_version_unknown) do
- create(:ci_runner_version, version: 'abc567', status: :unknown)
- end
-
- it 'contains any runner version that is not already recommended' do
+ it 'contains any valid or unprocessed runner version that is not already recommended' do
is_expected.to match_array([
runner_version_nil,
runner_version_not_available,
- runner_version_available,
- runner_version_unknown
+ runner_version_available
])
end
end
diff --git a/spec/models/ci/secure_file_spec.rb b/spec/models/ci/secure_file_spec.rb
index a3f1c7b7ef7..e47efff5dfd 100644
--- a/spec/models/ci/secure_file_spec.rb
+++ b/spec/models/ci/secure_file_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe Ci::SecureFile do
it { is_expected.to validate_presence_of(:file_store) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:project_id) }
+
context 'unique filename' do
let_it_be(:project1) { create(:project) }
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 65ead01a2bd..73cd7bb9075 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -1278,14 +1278,14 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
context 'generic timeout' do
let(:connection_status) { { connection_status: :unreachable, connection_error: :http_error } }
- let(:error_message) { 'Timed out connecting to server'}
+ let(:error_message) { 'Timed out connecting to server' }
it { is_expected.to eq(**connection_status, **expected_nodes) }
end
context 'gateway timeout' do
let(:connection_status) { { connection_status: :unreachable, connection_error: :http_error } }
- let(:error_message) { '504 Gateway Timeout for GET https://kubernetes.example.com/api/v1'}
+ let(:error_message) { '504 Gateway Timeout for GET https://kubernetes.example.com/api/v1' }
it { is_expected.to eq(**connection_status, **expected_nodes) }
end
diff --git a/spec/models/commit_signatures/ssh_signature_spec.rb b/spec/models/commit_signatures/ssh_signature_spec.rb
index ac4496e9d8c..64d95fe3a71 100644
--- a/spec/models/commit_signatures/ssh_signature_spec.rb
+++ b/spec/models/commit_signatures/ssh_signature_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe CommitSignatures::SshSignature do
it_behaves_like 'commit signature'
describe 'associations' do
- it { is_expected.to belong_to(:key).required }
+ it { is_expected.to belong_to(:key).optional }
end
describe '.by_commit_sha scope' do
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 3cccc41a892..78d4d9de84e 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -747,7 +747,7 @@ RSpec.describe CommitStatus do
end
context 'when failure_reason is nil' do
- let(:reason) { }
+ let(:reason) {}
let(:failure_reason) { 'unknown_failure' }
it { is_expected.to be_unknown_failure }
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index e6b197f34ca..569dc3a3a3e 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -170,7 +170,9 @@ RSpec.describe BulkInsertSafe do
all_items = bulk_insert_item_class.valid_list(10) + bulk_insert_item_class.invalid_list(10)
expect do
- bulk_insert_item_class.bulk_insert!(all_items, batch_size: 2) rescue nil
+ bulk_insert_item_class.bulk_insert!(all_items, batch_size: 2)
+ rescue StandardError
+ nil
end.not_to change { bulk_insert_item_class.count }
end
diff --git a/spec/models/concerns/chronic_duration_attribute_spec.rb b/spec/models/concerns/chronic_duration_attribute_spec.rb
index 00e28e19bd5..61b86455840 100644
--- a/spec/models/concerns/chronic_duration_attribute_spec.rb
+++ b/spec/models/concerns/chronic_duration_attribute_spec.rb
@@ -95,8 +95,8 @@ end
RSpec.describe 'ChronicDurationAttribute' do
context 'when default value is not set' do
- let(:source_field) {:maximum_timeout}
- let(:virtual_field) {:maximum_timeout_human_readable}
+ let(:source_field) { :maximum_timeout }
+ let(:virtual_field) { :maximum_timeout_human_readable }
let(:default_value) { nil }
subject { create(:ci_runner) }
@@ -106,8 +106,8 @@ RSpec.describe 'ChronicDurationAttribute' do
end
context 'when default value is set' do
- let(:source_field) {:build_timeout}
- let(:virtual_field) {:build_timeout_human_readable}
+ let(:source_field) { :build_timeout }
+ let(:virtual_field) { :build_timeout_human_readable }
let(:default_value) { 3600 }
subject { create(:project) }
@@ -118,8 +118,8 @@ RSpec.describe 'ChronicDurationAttribute' do
end
RSpec.describe 'ChronicDurationAttribute - reader' do
- let(:source_field) {:timeout}
- let(:virtual_field) {:timeout_human_readable}
+ let(:source_field) { :timeout }
+ let(:virtual_field) { :timeout_human_readable }
subject { create(:ci_build).ensure_metadata }
diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb
index 6af244a5a0f..64691165e21 100644
--- a/spec/models/concerns/ci/artifactable_spec.rb
+++ b/spec/models/concerns/ci/artifactable_spec.rb
@@ -46,8 +46,30 @@ RSpec.describe Ci::Artifactable do
end
end
+ context 'when file format is zip' do
+ context 'when artifact contains one file' do
+ let(:artifact) { build(:ci_job_artifact, :zip_with_single_file) }
+
+ it 'iterates blob once' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.once
+ end
+ end
+
+ context 'when artifact contains two files' do
+ let(:artifact) { build(:ci_job_artifact, :zip_with_multiple_files) }
+
+ it 'iterates blob two times' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.exactly(2).times
+ end
+ end
+ end
+
context 'when there are no adapters for the file format' do
- let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
+ let(:artifact) { build(:ci_job_artifact, :junit) }
+
+ before do
+ allow(artifact).to receive(:file_format).and_return(:unknown)
+ end
it 'raises an error' do
expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError)
diff --git a/spec/models/concerns/counter_attribute_spec.rb b/spec/models/concerns/counter_attribute_spec.rb
index a19fbae3cfb..8d32ef14f47 100644
--- a/spec/models/concerns/counter_attribute_spec.rb
+++ b/spec/models/concerns/counter_attribute_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe CounterAttribute, :counter_attribute, :clean_gitlab_redis_shared_
end
describe 'after_flush callbacks' do
- let(:attribute) { model.class.counter_attributes.first}
+ let(:attribute) { model.class.counter_attributes.first }
subject { model.flush_increments_to_database!(attribute) }
diff --git a/spec/models/concerns/cross_database_modification_spec.rb b/spec/models/concerns/cross_database_modification_spec.rb
index 72544536953..c3831b654cf 100644
--- a/spec/models/concerns/cross_database_modification_spec.rb
+++ b/spec/models/concerns/cross_database_modification_spec.rb
@@ -4,38 +4,6 @@ require 'spec_helper'
RSpec.describe CrossDatabaseModification do
describe '.transaction' do
- context 'feature flag disabled' do
- before do
- stub_feature_flags(track_gitlab_schema_in_current_transaction: false)
- end
-
- it 'does not add to gitlab_transactions_stack' do
- ApplicationRecord.transaction do
- expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
-
- Project.first
- end
-
- expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
- end
- end
-
- context 'feature flag is not yet setup' do
- before do
- allow(Feature::FlipperFeature).to receive(:table_exists?).and_raise(ActiveRecord::NoDatabaseError)
- end
-
- it 'does not add to gitlab_transactions_stack' do
- ApplicationRecord.transaction do
- expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
-
- Project.first
- end
-
- expect(ApplicationRecord.gitlab_transactions_stack).to be_empty
- end
- end
-
it 'adds the current gitlab schema to gitlab_transactions_stack', :aggregate_failures do
ApplicationRecord.transaction do
expect(ApplicationRecord.gitlab_transactions_stack).to contain_exactly(:gitlab_main)
diff --git a/spec/models/concerns/database_event_tracking_spec.rb b/spec/models/concerns/database_event_tracking_spec.rb
new file mode 100644
index 00000000000..976462b4174
--- /dev/null
+++ b/spec/models/concerns/database_event_tracking_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DatabaseEventTracking, :snowplow do
+ let(:test_class) do
+ Class.new(ActiveRecord::Base) do
+ include DatabaseEventTracking
+
+ self.table_name = 'application_setting_terms'
+
+ self::SNOWPLOW_ATTRIBUTES = %w[id].freeze # rubocop:disable RSpec/LeakyConstantDeclaration
+ end
+ end
+
+ subject(:create_test_class_record) { test_class.create!(id: 1, terms: "") }
+
+ context 'if event emmiter failed' do
+ before do
+ allow(Gitlab::Tracking).to receive(:event).and_raise(StandardError) # rubocop:disable RSpec/ExpectGitlabTracking
+ end
+
+ it 'tracks the exception' do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
+
+ create_test_class_record
+ end
+ end
+
+ context 'if product_intelligence_database_event_tracking FF is off' do
+ before do
+ stub_feature_flags(product_intelligence_database_event_tracking: false)
+ end
+
+ it 'does not track the event' do
+ create_test_class_record
+
+ expect_no_snowplow_event
+ end
+ end
+
+ describe 'event tracking' do
+ let(:category) { test_class.to_s }
+ let(:event) { 'database_event' }
+
+ it 'when created' do
+ create_test_class_record
+
+ expect_snowplow_event(category: category, action: "#{event}_create", label: 'application_setting_terms',
+ property: 'create', namespace: nil, "id" => 1)
+ end
+
+ it 'when updated' do
+ create_test_class_record
+ test_class.first.update!(id: 3)
+
+ expect_snowplow_event(category: category, action: "#{event}_update", label: 'application_setting_terms',
+ property: 'update', namespace: nil, "id" => 3)
+ end
+
+ it 'when destroyed' do
+ create_test_class_record
+ test_class.first.destroy!
+
+ expect_snowplow_event(category: category, action: "#{event}_destroy", label: 'application_setting_terms',
+ property: 'destroy', namespace: nil, "id" => 1)
+ end
+ end
+end
diff --git a/spec/models/concerns/expirable_spec.rb b/spec/models/concerns/expirable_spec.rb
index 5eb6530881e..50dfb138ac9 100644
--- a/spec/models/concerns/expirable_spec.rb
+++ b/spec/models/concerns/expirable_spec.rb
@@ -16,6 +16,11 @@ RSpec.describe Expirable do
it { expect(ProjectMember.expired).to match_array([expired]) }
end
+ describe '.not_expired' do
+ it { expect(ProjectMember.not_expired).to include(no_expire, expire_later) }
+ it { expect(ProjectMember.not_expired).not_to include(expired) }
+ end
+
describe '#expired?' do
it { expect(no_expire.expired?).to eq(false) }
it { expect(expire_later.expired?).to eq(false) }
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 87821de3cf5..6763cc904b4 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -569,6 +569,27 @@ RSpec.describe Issuable do
end
end
+ context 'merge_request update reviewers' do
+ let(:merge_request) { create(:merge_request) }
+ let(:user2) { create(:user) }
+
+ before do
+ merge_request.update!(reviewers: [user])
+ merge_request.update!(reviewers: [user, user2])
+ expect(Gitlab::DataBuilder::Issuable)
+ .to receive(:new).with(merge_request).and_return(builder)
+ end
+
+ it 'delegates to Gitlab::DataBuilder::Issuable#build' do
+ expect(builder).to receive(:build).with(
+ user: user,
+ changes: hash_including(
+ 'reviewers' => [[user.hook_attrs], [user.hook_attrs, user2.hook_attrs]]
+ ))
+ merge_request.to_hook_data(user, old_associations: { reviewers: [user] })
+ end
+ end
+
context 'incident severity is updated' do
let(:issue) { create(:incident) }
diff --git a/spec/models/concerns/nullify_if_blank_spec.rb b/spec/models/concerns/nullify_if_blank_spec.rb
index 2d1bdba39dd..b0e229f4c91 100644
--- a/spec/models/concerns/nullify_if_blank_spec.rb
+++ b/spec/models/concerns/nullify_if_blank_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe NullifyIfBlank do
context 'attribute is nil' do
let(:name) { nil }
- it { is_expected.to be_nil}
+ it { is_expected.to be_nil }
end
context 'attribute is not blank' do
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index b92c7c52f0b..f7f68cb38d8 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -124,6 +124,7 @@ RSpec.describe Participable do
end
let(:readable) { true }
+ let(:project) { build(:project, :public) }
it 'returns the list of participants' do
model.participant(:foo)
@@ -132,7 +133,6 @@ RSpec.describe Participable do
user1 = build(:user)
user2 = build(:user)
user3 = build(:user)
- project = build(:project, :public)
instance = model.new
allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
@@ -155,7 +155,6 @@ RSpec.describe Participable do
instance = model.new
user1 = build(:user)
user2 = build(:user)
- project = build(:project, :public)
allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
allow(instance).to receive(:bar).and_return(user2)
@@ -164,6 +163,29 @@ RSpec.describe Participable do
expect(instance.visible_participants(user1)).to be_empty
end
end
+
+ context 'with multiple system notes from the same author and mentioned_users' do
+ let!(:user1) { create(:user) }
+ let!(:user2) { create(:user) }
+
+ it 'skips expensive checks if the author is aleady in participants list' do
+ model.participant(:notes)
+
+ instance = model.new
+ note1 = create(:system_note, author: user1)
+ note2 = create(:system_note, author: user1) # only skip system notes with no mentioned users
+ note3 = create(:system_note, author: user1, note: "assigned to #{user2.to_reference}")
+ note4 = create(:note, author: user2)
+
+ allow(instance).to receive(:project).and_return(project)
+ allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
+ allow(instance).to receive(:notes).and_return([note1, note2, note3, note4])
+
+ allow(Ability).to receive(:allowed?).with(anything, :read_project, anything).and_return(true)
+ allow(Ability).to receive(:allowed?).with(anything, :read_note, anything).exactly(3).times.and_return(true)
+ expect(instance.visible_participants(user1)).to match_array [user1, user2]
+ end
+ end
end
describe '#participant?' do
diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb
index f2dc8464e86..b49b9ce8a2a 100644
--- a/spec/models/concerns/project_features_compatibility_spec.rb
+++ b/spec/models/concerns/project_features_compatibility_spec.rb
@@ -5,7 +5,11 @@ require 'spec_helper'
RSpec.describe ProjectFeaturesCompatibility do
let(:project) { create(:project) }
let(:features_enabled) { %w(issues wiki builds merge_requests snippets security_and_compliance) }
- let(:features) { features_enabled + %w(repository pages operations container_registry package_registry) }
+ let(:features) do
+ features_enabled + %w(
+ repository pages operations container_registry package_registry environments feature_flags releases
+ )
+ end
# We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table
# All those fields got moved to a new table called project_feature and are now integers instead of booleans
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 5468699f9dd..cb9bb676ede 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -320,7 +320,7 @@ RSpec.describe ReactiveCaching, :use_clean_rails_memory_store_caching do
stub_reactive_cache(instance, "preexisting")
end
- let(:calculation) { -> { raise "foo"} }
+ let(:calculation) { -> { raise "foo" } }
it 'leaves the cache untouched' do
expect { go! }.to raise_error("foo")
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index a2ce02f4661..3f6bbe795cc 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe ApplicationSetting, 'TokenAuthenticatable' do
subject { described_class.send(:add_authentication_token_field, :runners_registration_token) }
it 'raises error' do
- expect {subject}.to raise_error(ArgumentError)
+ expect { subject }.to raise_error(ArgumentError)
end
end
end
@@ -126,7 +126,7 @@ RSpec.describe PersonalAccessToken, 'TokenAuthenticatable' do
end
end
- let(:token_value) { 'token' }
+ let(:token_value) { Devise.friendly_token }
let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
let(:user) { create(:user) }
let(:personal_access_token) do
@@ -442,7 +442,7 @@ RSpec.shared_examples 'prefixed token rotation' do
context 'token is not set' do
it 'generates a new token' do
- expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/)
+ expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/o)
expect(instance).not_to be_persisted
end
end
@@ -453,7 +453,7 @@ RSpec.shared_examples 'prefixed token rotation' do
end
it 'generates a new token' do
- expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/)
+ expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/o)
expect(instance).not_to be_persisted
end
end
@@ -475,7 +475,7 @@ RSpec.shared_examples 'prefixed token rotation' do
context 'token is not set' do
it 'generates a new token' do
- expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/)
+ expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/o)
expect(instance).to be_persisted
end
end
@@ -486,7 +486,7 @@ RSpec.shared_examples 'prefixed token rotation' do
end
it 'generates a new token' do
- expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/)
+ expect(subject).to match(/^#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}/o)
expect(instance).to be_persisted
end
end
diff --git a/spec/models/container_expiration_policy_spec.rb b/spec/models/container_expiration_policy_spec.rb
index 191913ed454..b88eddf19dc 100644
--- a/spec/models/container_expiration_policy_spec.rb
+++ b/spec/models/container_expiration_policy_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe ContainerExpirationPolicy, type: :model do
end
context 'when there are no runnable schedules' do
- let!(:policy) { }
+ let!(:policy) {}
it 'returns an empty array' do
is_expected.to be_empty
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index e35788b1848..a4329993e91 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -525,6 +525,162 @@ RSpec.describe ContainerRepository, :aggregate_failures do
end
end
+ describe '#each_tags_page' do
+ let(:page_size) { 100 }
+
+ shared_examples 'iterating through a page' do |expected_tags: true|
+ it 'iterates through one page' do
+ expect(repository.gitlab_api_client).to receive(:tags)
+ .with(repository.path, page_size: page_size, last: nil)
+ .and_return(client_response)
+ expect { |b| repository.each_tags_page(page_size: page_size, &b) }
+ .to yield_with_args(expected_tags ? expected_tags_from(client_response_tags) : [])
+ end
+ end
+
+ context 'with an empty page' do
+ let(:client_response) { { pagination: {}, response_body: [] } }
+
+ it_behaves_like 'iterating through a page', expected_tags: false
+ end
+
+ context 'with one page' do
+ let(:client_response) { { pagination: {}, response_body: client_response_tags } }
+ let(:client_response_tags) do
+ [
+ {
+ 'name' => '0.1.0',
+ 'created_at' => '2022-06-07T12:10:12.412+00:00'
+ },
+ {
+ 'name' => 'latest',
+ 'created_at' => '2022-06-07T12:11:13.633+00:00'
+ }
+ ]
+ end
+
+ context 'with a nil created_at' do
+ let(:client_response_tags) { ['name' => '0.1.0', 'created_at' => nil] }
+
+ it_behaves_like 'iterating through a page'
+ end
+
+ context 'with an invalid created_at' do
+ let(:client_response_tags) { ['name' => '0.1.0', 'created_at' => 'not_a_timestamp'] }
+
+ it_behaves_like 'iterating through a page'
+ end
+ end
+
+ context 'with two pages' do
+ let(:client_response1) { { pagination: { next: { uri: URI('http://localhost/next?last=latest') } }, response_body: client_response_tags1 } }
+ let(:client_response_tags1) do
+ [
+ {
+ 'name' => '0.1.0',
+ 'created_at' => '2022-06-07T12:10:12.412+00:00'
+ },
+ {
+ 'name' => 'latest',
+ 'created_at' => '2022-06-07T12:11:13.633+00:00'
+ }
+ ]
+ end
+
+ let(:client_response2) { { pagination: {}, response_body: client_response_tags2 } }
+ let(:client_response_tags2) do
+ [
+ {
+ 'name' => '1.2.3',
+ 'created_at' => '2022-06-10T12:10:15.412+00:00'
+ },
+ {
+ 'name' => '2.3.4',
+ 'created_at' => '2022-06-11T12:11:17.633+00:00'
+ }
+ ]
+ end
+
+ it 'iterates through two pages' do
+ expect(repository.gitlab_api_client).to receive(:tags)
+ .with(repository.path, page_size: page_size, last: nil)
+ .and_return(client_response1)
+ expect(repository.gitlab_api_client).to receive(:tags)
+ .with(repository.path, page_size: page_size, last: 'latest')
+ .and_return(client_response2)
+ expect { |b| repository.each_tags_page(page_size: page_size, &b) }
+ .to yield_successive_args(expected_tags_from(client_response_tags1), expected_tags_from(client_response_tags2))
+ end
+ end
+
+ context 'when max pages is reached' do
+ before do
+ stub_const('ContainerRepository::MAX_TAGS_PAGES', 0)
+ end
+
+ it 'raises an error' do
+ expect { repository.each_tags_page(page_size: page_size) {} }
+ .to raise_error(StandardError, 'too many pages requested')
+ end
+ end
+
+ context 'without a block set' do
+ it 'raises an Argument error' do
+ expect { repository.each_tags_page(page_size: page_size) }.to raise_error(ArgumentError, 'block not given')
+ end
+ end
+
+ context 'without a page size set' do
+ let(:client_response) { { pagination: {}, response_body: [] } }
+
+ it 'uses a default size' do
+ expect(repository.gitlab_api_client).to receive(:tags)
+ .with(repository.path, page_size: 100, last: nil)
+ .and_return(client_response)
+ expect { |b| repository.each_tags_page(&b) }.to yield_with_args([])
+ end
+ end
+
+ context 'with an empty client response' do
+ let(:client_response) { {} }
+
+ it 'breaks the loop' do
+ expect(repository.gitlab_api_client).to receive(:tags)
+ .with(repository.path, page_size: page_size, last: nil)
+ .and_return(client_response)
+ expect { |b| repository.each_tags_page(page_size: page_size, &b) }.not_to yield_control
+ end
+ end
+
+ context 'with a nil page' do
+ let(:client_response) { { pagination: {}, response_body: nil } }
+
+ it_behaves_like 'iterating through a page', expected_tags: false
+ end
+
+ context 'calling on a non migrated repository' do
+ before do
+ repository.update!(created_at: described_class::MIGRATION_PHASE_1_ENDED_AT - 3.days)
+ end
+
+ it 'raises an Argument error' do
+ expect { repository.each_tags_page }.to raise_error(ArgumentError, 'not a migrated repository')
+ end
+ end
+
+ def expected_tags_from(client_tags)
+ client_tags.map do |tag|
+ created_at =
+ begin
+ DateTime.iso8601(tag['created_at'])
+ rescue ArgumentError
+ nil
+ end
+ an_object_having_attributes(name: tag['name'], created_at: created_at)
+ end
+ end
+ end
+
describe '#tags_count' do
it 'returns the count of tags' do
expect(repository.tags_count).to eq(1)
@@ -1195,7 +1351,7 @@ RSpec.describe ContainerRepository, :aggregate_failures do
described_class::MIGRATION_STATES.each do |state|
context "when in #{state} migration_state" do
- let(:container_repository) { create(:container_repository, state.to_sym)}
+ let(:container_repository) { create(:container_repository, state.to_sym) }
it { is_expected.to eq(state == 'importing' || state == 'pre_importing') }
end
@@ -1207,7 +1363,7 @@ RSpec.describe ContainerRepository, :aggregate_failures do
described_class::MIGRATION_STATES.each do |state|
context "when in #{state} migration_state" do
- let(:container_repository) { create(:container_repository, state.to_sym)}
+ let(:container_repository) { create(:container_repository, state.to_sym) }
it { is_expected.to eq(state == 'importing') }
end
@@ -1219,7 +1375,7 @@ RSpec.describe ContainerRepository, :aggregate_failures do
described_class::MIGRATION_STATES.each do |state|
context "when in #{state} migration_state" do
- let(:container_repository) { create(:container_repository, state.to_sym)}
+ let(:container_repository) { create(:container_repository, state.to_sym) }
it { is_expected.to eq(state == 'pre_importing') }
end
@@ -1348,6 +1504,28 @@ RSpec.describe ContainerRepository, :aggregate_failures do
end
end
+ describe '#migrated?' do
+ subject { repository.migrated? }
+
+ it { is_expected.to eq(true) }
+
+ context 'with a created_at older than phase 1 ends' do
+ before do
+ repository.update!(created_at: described_class::MIGRATION_PHASE_1_ENDED_AT - 3.days)
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'with migration state set to import_done' do
+ before do
+ repository.update!(migration_state: 'import_done')
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
+
context 'with repositories' do
let_it_be_with_reload(:repository) { create(:container_repository, :cleanup_unscheduled) }
let_it_be(:other_repository) { create(:container_repository, :cleanup_unscheduled) }
diff --git a/spec/models/customer_relations/contact_spec.rb b/spec/models/customer_relations/contact_spec.rb
index f91546f5240..487af404a7c 100644
--- a/spec/models/customer_relations/contact_spec.rb
+++ b/spec/models/customer_relations/contact_spec.rb
@@ -226,15 +226,58 @@ RSpec.describe CustomerRelations::Contact, type: :model do
end
end
- describe '.sort_by_name' do
+ describe '.counts_by_state' do
+ before do
+ create_list(:contact, 3, group: group)
+ create_list(:contact, 2, group: group, state: 'inactive')
+ end
+
+ it 'returns correct contact counts' do
+ counts = group.contacts.counts_by_state
+
+ expect(counts['active']).to be(3)
+ expect(counts['inactive']).to be(2)
+ end
+ end
+
+ describe 'sorting' do
+ let_it_be(:organization_a) { create(:organization, name: 'a') }
+ let_it_be(:organization_b) { create(:organization, name: 'b') }
let_it_be(:contact_a) { create(:contact, group: group, first_name: "c", last_name: "d") }
- let_it_be(:contact_b) { create(:contact, group: group, first_name: "a", last_name: "b") }
- let_it_be(:contact_c) { create(:contact, group: group, first_name: "e", last_name: "d") }
+ let_it_be(:contact_b) do
+ create(:contact,
+ group: group,
+ first_name: "a",
+ last_name: "b",
+ phone: "123",
+ organization: organization_a)
+ end
- context 'when sorting the contacts' do
- it 'sorts them by last name then first name in ascendent order' do
+ let_it_be(:contact_c) do
+ create(:contact,
+ group: group,
+ first_name: "e",
+ last_name: "d",
+ phone: "456",
+ organization: organization_b)
+ end
+
+ describe '.sort_by_name' do
+ it 'sorts them by last name then first name in ascending order' do
expect(group.contacts.sort_by_name).to eq([contact_b, contact_a, contact_c])
end
end
+
+ describe '.sort_by_organization' do
+ it 'sorts them by organization in descending order' do
+ expect(group.contacts.sort_by_organization(:desc)).to eq([contact_c, contact_b, contact_a])
+ end
+ end
+
+ describe '.sort_by_field' do
+ it 'sorts them by phone in ascending order' do
+ expect(group.contacts.sort_by_field('phone', :asc)).to eq([contact_b, contact_c, contact_a])
+ end
+ end
end
end
diff --git a/spec/models/customer_relations/contact_state_counts_spec.rb b/spec/models/customer_relations/contact_state_counts_spec.rb
new file mode 100644
index 00000000000..a19f6f08489
--- /dev/null
+++ b/spec/models/customer_relations/contact_state_counts_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CustomerRelations::ContactStateCounts do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+
+ let(:counter) { described_class.new(user, group, params) }
+ let(:params) { {} }
+
+ before_all do
+ group.add_reporter(user)
+ create(:contact, group: group, first_name: 'filter')
+ create(:contact, group: group, last_name: 'filter')
+ create(:contact, group: group)
+ create(:contact, group: group, state: 'inactive', email: 'filter@example.com')
+ create(:contact, group: group, state: 'inactive')
+ end
+
+ describe '.declarative_policy_class' do
+ subject { described_class.declarative_policy_class }
+
+ it { is_expected.to eq('CustomerRelations::ContactPolicy') }
+ end
+
+ describe '#all' do
+ it 'returns the total number of contacts' do
+ expect(counter.all).to be(5)
+ end
+ end
+
+ describe '#active' do
+ it 'returns the number of active contacts' do
+ expect(counter.active).to be(3)
+ end
+ end
+
+ describe '#inactive' do
+ it 'returns the number of inactive contacts' do
+ expect(counter.inactive).to be(2)
+ end
+ end
+
+ describe 'when filtered' do
+ let(:params) { { search: 'filter' } }
+
+ it '#all returns the number of contacts with a filter' do
+ expect(counter.all).to be(3)
+ end
+
+ it '#active returns the number of active contacts with a filter' do
+ expect(counter.active).to be(2)
+ end
+
+ it '#inactive returns the number of inactive contacts with a filter' do
+ expect(counter.inactive).to be(1)
+ end
+ end
+end
diff --git a/spec/models/data_list_spec.rb b/spec/models/data_list_spec.rb
index 67db2730a78..6e01f4786ba 100644
--- a/spec/models/data_list_spec.rb
+++ b/spec/models/data_list_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe DataList do
let(:zentao_integration) { create(:zentao_integration) }
let(:cases) do
[
- [jira_integration, 'Integrations::JiraTrackerData', 'service_id'],
+ [jira_integration, 'Integrations::JiraTrackerData', 'integration_id'],
[zentao_integration, 'Integrations::ZentaoTrackerData', 'integration_id']
]
end
diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb
index c22bad0e062..3272d5236d3 100644
--- a/spec/models/deploy_key_spec.rb
+++ b/spec/models/deploy_key_spec.rb
@@ -5,17 +5,20 @@ require 'spec_helper'
RSpec.describe DeployKey, :mailer do
describe "Associations" do
it { is_expected.to have_many(:deploy_keys_projects) }
+
it do
is_expected.to have_many(:deploy_keys_projects_with_write_access)
.conditions(can_push: true)
.class_name('DeployKeysProject')
end
+
it do
is_expected.to have_many(:projects_with_write_access)
.class_name('Project')
.through(:deploy_keys_projects_with_write_access)
.source(:project)
end
+
it { is_expected.to have_many(:projects) }
it { is_expected.to have_many(:protected_branch_push_access_levels) }
end
@@ -146,4 +149,10 @@ RSpec.describe DeployKey, :mailer do
end
end
end
+
+ describe '#audit_details' do
+ it "equals to the key's title" do
+ expect(subject.audit_details).to eq(subject.title)
+ end
+ end
end
diff --git a/spec/models/design_management/version_spec.rb b/spec/models/design_management/version_spec.rb
index 303bac61e1e..519ba3c67b4 100644
--- a/spec/models/design_management/version_spec.rb
+++ b/spec/models/design_management/version_spec.rb
@@ -142,14 +142,18 @@ RSpec.describe DesignManagement::Version do
it 'does not leave invalid versions around if creation fails' do
expect do
- described_class.create_for_designs([], 'abcdef', author) rescue nil
+ described_class.create_for_designs([], 'abcdef', author)
+ rescue StandardError
+ nil
end.not_to change { described_class.count }
end
it 'does not leave orphaned design-versions around if creation fails' do
actions = as_actions(designs)
expect do
- described_class.create_for_designs(actions, '', author) rescue nil
+ described_class.create_for_designs(actions, '', author)
+ rescue StandardError
+ nil
end.not_to change { DesignManagement::Action.count }
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index e3207636bdc..3f4372dafd0 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -42,6 +42,48 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
end
+ describe 'validate and sanitize external url' do
+ let_it_be_with_refind(:environment) { create(:environment) }
+
+ where(:source_external_url, :expected_error_message) do
+ nil | nil
+ 'http://example.com' | nil
+ 'example.com' | nil
+ 'www.example.io' | nil
+ 'http://$URL' | nil
+ 'http://$(URL)' | nil
+ 'custom://example.com' | nil
+ '1.1.1.1' | nil
+ '$BASE_URL/${CI_COMMIT_REF_NAME}' | nil
+ '$ENVIRONMENT_URL' | nil
+ 'https://$SUB.$MAIN' | nil
+ 'https://$SUB-$REGION.$MAIN' | nil
+ 'https://example.com?param={()}' | nil
+ 'http://XSS?x=<script>alert(1)</script>' | nil
+ 'https://user:${VARIABLE}@example.io' | nil
+ 'https://example.com/test?param={data}' | nil
+ 'http://${URL}' | 'URI is invalid'
+ 'https://${URL}.example/test' | 'URI is invalid'
+ 'http://test${CI_MERGE_REQUEST_IID}.example.com' | 'URI is invalid'
+ 'javascript:alert("hello")' | 'javascript scheme is not allowed'
+ end
+ with_them do
+ it 'sets an external URL or an error' do
+ environment.external_url = source_external_url
+
+ environment.valid?
+
+ if expected_error_message
+ expect(environment.errors[:external_url].first).to eq(expected_error_message)
+ else
+ expect(environment.errors[:external_url]).to be_empty,
+ "There were unexpected errors: #{environment.errors.full_messages}"
+ expect(environment.external_url).to eq(source_external_url)
+ end
+ end
+ end
+ end
+
describe '.before_save' do
it 'ensures environment tier when a new object is created' do
environment = build(:environment, name: 'gprd', tier: nil)
@@ -194,7 +236,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
context 'when query is nil' do
- let(:query) { }
+ let(:query) {}
it 'raises an error' do
expect { subject }.to raise_error(NoMethodError)
@@ -770,16 +812,6 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
it 'returns the successful deployment jobs for the last deployment pipeline' do
expect(subject.pluck(:id)).to contain_exactly(deployment_a.id, deployment_b.id)
end
-
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(batch_load_environment_last_deployment_group: false)
- end
-
- it 'returns the successful deployment jobs for the last deployment pipeline' do
- expect(subject.pluck(:id)).to contain_exactly(deployment_a.id, deployment_b.id)
- end
- end
end
end
@@ -817,8 +849,8 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
describe '#actions_for' do
let(:deployment) { create(:deployment, :success, environment: environment) }
let(:pipeline) { deployment.deployable.pipeline }
- let!(:review_action) { create(:ci_build, :manual, name: 'review-apps', pipeline: pipeline, environment: 'review/$CI_COMMIT_REF_NAME' )}
- let!(:production_action) { create(:ci_build, :manual, name: 'production', pipeline: pipeline, environment: 'production' )}
+ let!(:review_action) { create(:ci_build, :manual, name: 'review-apps', pipeline: pipeline, environment: 'review/$CI_COMMIT_REF_NAME' ) }
+ let!(:production_action) { create(:ci_build, :manual, name: 'production', pipeline: pipeline, environment: 'production' ) }
it 'returns a list of actions with matching environment' do
expect(environment.actions_for('review/master')).to contain_exactly(review_action)
@@ -993,178 +1025,29 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
describe '#last_visible_deployable' do
subject { environment.last_visible_deployable }
- context 'does not join across databases' do
- let(:pipeline_a) { create(:ci_pipeline, project: project) }
- let(:pipeline_b) { create(:ci_pipeline, project: project) }
- let(:ci_build_a) { create(:ci_build, project: project, pipeline: pipeline_a) }
- let(:ci_build_b) { create(:ci_build, project: project, pipeline: pipeline_b) }
-
- before do
- create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b)
- end
-
- it 'for direct call' do
- with_cross_joins_prevented do
- expect(subject.id).to eq(ci_build_b.id)
- end
- end
-
- it 'for preload' do
- environment.reload
-
- with_cross_joins_prevented do
- ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_deployable: []])
- expect(subject.id).to eq(ci_build_b.id)
- end
- end
+ let!(:deployment) do
+ create(:deployment, :success, project: project, environment: environment, deployable: deployable)
end
- context 'call after preload' do
- it 'fetches from association cache' do
- pipeline = create(:ci_pipeline, project: project)
- ci_build = create(:ci_build, project: project, pipeline: pipeline)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
-
- environment.reload
- ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_deployable: []])
-
- query_count = ActiveRecord::QueryRecorder.new do
- expect(subject.id).to eq(ci_build.id)
- end.count
+ let!(:deployable) { create(:ci_build, :success, project: project) }
- expect(query_count).to eq(0)
- end
+ it 'fetches the deployable through the last visible deployment' do
+ is_expected.to eq(deployable)
end
end
describe '#last_visible_pipeline' do
- let(:user) { create(:user) }
- let_it_be(:project) { create(:project, :repository) }
-
- let(:environment) { create(:environment, project: project) }
- let(:commit) { project.commit }
-
- let(:success_pipeline) do
- create(:ci_pipeline, :success, project: project, user: user, sha: commit.sha)
- end
-
- let(:failed_pipeline) do
- create(:ci_pipeline, :failed, project: project, user: user, sha: commit.sha)
- end
-
- it 'uses the last deployment even if it failed' do
- pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
- ci_build = create(:ci_build, project: project, pipeline: pipeline)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build, sha: commit.sha)
-
- last_pipeline = environment.last_visible_pipeline
+ subject { environment.last_visible_pipeline }
- expect(last_pipeline).to eq(pipeline)
+ let!(:deployment) do
+ create(:deployment, :success, project: project, environment: environment, deployable: deployable)
end
- it 'returns nil if there is no deployment' do
- create(:ci_build, project: project, pipeline: success_pipeline)
+ let!(:deployable) { create(:ci_build, :success, project: project, pipeline: pipeline) }
+ let!(:pipeline) { create(:ci_pipeline, :success, project: project) }
- expect(environment.last_visible_pipeline).to be_nil
- end
-
- it 'does not return an invisible pipeline' do
- failed_pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
- ci_build_a = create(:ci_build, project: project, pipeline: failed_pipeline)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_a, sha: commit.sha)
- pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
- ci_build_b = create(:ci_build, project: project, pipeline: pipeline)
- create(:deployment, :created, project: project, environment: environment, deployable: ci_build_b, sha: commit.sha)
-
- last_pipeline = environment.last_visible_pipeline
-
- expect(last_pipeline).to eq(failed_pipeline)
- end
-
- context 'does not join across databases' do
- let(:pipeline_a) { create(:ci_pipeline, project: project) }
- let(:pipeline_b) { create(:ci_pipeline, project: project) }
- let(:ci_build_a) { create(:ci_build, project: project, pipeline: pipeline_a) }
- let(:ci_build_b) { create(:ci_build, project: project, pipeline: pipeline_b) }
-
- before do
- create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b)
- end
-
- subject { environment.last_visible_pipeline }
-
- it 'for direct call' do
- with_cross_joins_prevented do
- expect(subject.id).to eq(pipeline_b.id)
- end
- end
-
- it 'for preload' do
- environment.reload
-
- with_cross_joins_prevented do
- ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_pipeline: []])
- expect(subject.id).to eq(pipeline_b.id)
- end
- end
- end
-
- context 'for the environment' do
- it 'returns the last pipeline' do
- pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
- ci_build = create(:ci_build, project: project, pipeline: pipeline)
- create(:deployment, :success, project: project, environment: environment, deployable: ci_build, sha: commit.sha)
-
- last_pipeline = environment.last_visible_pipeline
-
- expect(last_pipeline).to eq(pipeline)
- end
-
- context 'with multiple deployments' do
- it 'returns the last pipeline' do
- pipeline_a = create(:ci_pipeline, project: project, user: user)
- pipeline_b = create(:ci_pipeline, project: project, user: user)
- ci_build_a = create(:ci_build, project: project, pipeline: pipeline_a)
- ci_build_b = create(:ci_build, project: project, pipeline: pipeline_b)
- create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
- create(:deployment, :success, project: project, environment: environment, deployable: ci_build_b)
-
- last_pipeline = environment.last_visible_pipeline
-
- expect(last_pipeline).to eq(pipeline_b)
- end
- end
-
- context 'with multiple pipelines' do
- it 'returns the last pipeline' do
- create(:ci_build, project: project, pipeline: success_pipeline)
- ci_build_b = create(:ci_build, project: project, pipeline: failed_pipeline)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b, sha: commit.sha)
-
- last_pipeline = environment.last_visible_pipeline
-
- expect(last_pipeline).to eq(failed_pipeline)
- end
- end
- end
-
- context 'call after preload' do
- it 'fetches from association cache' do
- pipeline = create(:ci_pipeline, project: project)
- ci_build = create(:ci_build, project: project, pipeline: pipeline)
- create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
-
- environment.reload
- ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_pipeline: []])
-
- query_count = ActiveRecord::QueryRecorder.new do
- expect(environment.last_visible_pipeline.id).to eq(pipeline.id)
- end.count
-
- expect(query_count).to eq(0)
- end
+ it 'fetches the pipeline through the last visible deployment' do
+ is_expected.to eq(pipeline)
end
end
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
index ebfd9f04f6a..0685144dea6 100644
--- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -121,36 +121,36 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
end
- end
- describe 'before_validation :reset_token' do
- context 'when a token was previously set' do
- subject { create(:project_error_tracking_setting, project: project) }
+ describe 'before_validation :reset_token' do
+ context 'when a token was previously set' do
+ subject { create(:project_error_tracking_setting, project: project) }
- it 'resets token if url changed' do
- subject.api_url = 'http://sentry.com/api/0/projects/org-slug/proj-slug/'
+ it 'resets token if url changed' do
+ subject.api_url = 'http://sentry.com/api/0/projects/org-slug/proj-slug/'
- expect(subject).not_to be_valid
- expect(subject.token).to be_nil
- end
+ expect(subject).not_to be_valid
+ expect(subject.token).to be_nil
+ end
- it "does not reset token if new url is set together with the same token" do
- subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/'
- current_token = subject.token
- subject.token = current_token
+ it "does not reset token if new url is set together with the same token" do
+ subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/'
+ current_token = subject.token
+ subject.token = current_token
- expect(subject).to be_valid
- expect(subject.token).to eq(current_token)
- expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/')
- end
+ expect(subject).to be_valid
+ expect(subject.token).to eq(current_token)
+ expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/')
+ end
- it 'does not reset token if new url is set together with a new token' do
- subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/'
- subject.token = 'token'
+ it 'does not reset token if new url is set together with a new token' do
+ subject.api_url = 'http://sentrytest.com/api/0/projects/org-slug/proj-slug/'
+ subject.token = 'token'
- expect(subject).to be_valid
- expect(subject.token).to eq('token')
- expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/')
+ expect(subject).to be_valid
+ expect(subject.token).to eq('token')
+ expect(subject.api_url).to eq('http://sentrytest.com/api/0/projects/org-slug/proj-slug/')
+ end
end
end
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 2c1bbfcb35f..9700852e567 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -264,6 +264,8 @@ RSpec.describe Event do
let(:project) { public_project }
let(:issue) { create(:issue, project: project, author: author, assignees: [assignee]) }
let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignees: [assignee]) }
+ let(:work_item) { create(:work_item, project: project, author: author) }
+ let(:confidential_work_item) { create(:work_item, :confidential, project: project, author: author) }
let(:project_snippet) { create(:project_snippet, :public, project: project, author: author) }
let(:personal_snippet) { create(:personal_snippet, :public, author: author) }
let(:design) { create(:design, issue: issue, project: project) }
@@ -380,6 +382,28 @@ RSpec.describe Event do
end
end
+ context 'work item event' do
+ context 'for non confidential work item' do
+ let(:target) { work_item }
+
+ include_examples 'visibility examples' do
+ let(:visibility) { visible_to_all }
+ end
+
+ include_examples 'visible to assignee and author', true
+ end
+
+ context 'for confidential work item' do
+ let(:target) { confidential_work_item }
+
+ include_examples 'visibility examples' do
+ let(:visibility) { visible_to_none_except(:member, :admin) }
+ end
+
+ include_examples 'visible to author', true
+ end
+ end
+
context 'issue note event' do
context 'on non confidential issues' do
let(:target) { note_on_issue }
@@ -947,7 +971,7 @@ RSpec.describe Event do
let_it_be(:user) { create(:user) }
let_it_be(:note_on_project_snippet) { create(:note_on_project_snippet, author: user) }
let_it_be(:note_on_personal_snippet) { create(:note_on_personal_snippet, author: user) }
- let_it_be(:other_note) { create(:note_on_issue, author: user)}
+ let_it_be(:other_note) { create(:note_on_issue, author: user) }
let_it_be(:personal_snippet_event) { create(:event, :commented, project: nil, target: note_on_personal_snippet, author: user) }
let_it_be(:project_snippet_event) { create(:event, :commented, project: note_on_project_snippet.project, target: note_on_project_snippet, author: user) }
let_it_be(:other_event) { create(:event, :commented, project: other_note.project, target: other_note, author: user) }
diff --git a/spec/models/group_group_link_spec.rb b/spec/models/group_group_link_spec.rb
index 72c700e7981..969987c7e64 100644
--- a/spec/models/group_group_link_spec.rb
+++ b/spec/models/group_group_link_spec.rb
@@ -24,12 +24,60 @@ RSpec.describe GroupGroupLink do
it 'returns all records which are greater than Guests access' do
expect(described_class.non_guests).to match_array([
- group_group_link_reporter, group_group_link,
- group_group_link_maintainer, group_group_link_owner
+ group_group_link_reporter, group_group_link,
+ group_group_link_maintainer, group_group_link_owner
])
end
end
+ describe '.with_owner_or_maintainer_access' do
+ let_it_be(:group_group_link_maintainer) { create :group_group_link, :maintainer }
+ let_it_be(:group_group_link_owner) { create :group_group_link, :owner }
+ let_it_be(:group_group_link_reporter) { create :group_group_link, :reporter }
+ let_it_be(:group_group_link_guest) { create :group_group_link, :guest }
+
+ it 'returns all records which have OWNER or MAINTAINER access' do
+ expect(described_class.with_owner_or_maintainer_access).to match_array([
+ group_group_link_maintainer,
+ group_group_link_owner
+ ])
+ end
+ end
+
+ context 'for access via group shares' do
+ let_it_be(:shared_with_group_1) { create(:group) }
+ let_it_be(:shared_with_group_2) { create(:group) }
+ let_it_be(:shared_with_group_3) { create(:group) }
+ let_it_be(:shared_group_1) { create(:group) }
+ let_it_be(:shared_group_2) { create(:group) }
+ let_it_be(:shared_group_3) { create(:group) }
+ let_it_be(:shared_group_1_subgroup) { create(:group, parent: shared_group_1) }
+
+ before do
+ create :group_group_link, shared_with_group: shared_with_group_1, shared_group: shared_group_1
+ create :group_group_link, shared_with_group: shared_with_group_2, shared_group: shared_group_2
+ create :group_group_link, shared_with_group: shared_with_group_3, shared_group: shared_group_3
+ end
+
+ describe '.groups_accessible_via' do
+ it 'returns other groups that you can get access to, via the group shares of the specified groups' do
+ group_ids = [shared_with_group_1.id, shared_with_group_2.id]
+ expected_result = Group.id_in([shared_group_1.id, shared_group_1_subgroup.id, shared_group_2.id])
+
+ expect(described_class.groups_accessible_via(group_ids)).to match_array(expected_result)
+ end
+ end
+
+ describe '.groups_having_access_to' do
+ it 'returns all other groups that are having access to these specified groups, via group share' do
+ group_ids = [shared_group_1.id, shared_group_2.id]
+ expected_result = Group.id_in([shared_with_group_1.id, shared_with_group_2.id])
+
+ expect(described_class.groups_having_access_to(group_ids)).to match_array(expected_result)
+ end
+ end
+ end
+
describe '.distinct_on_shared_with_group_id_with_group_access' do
let_it_be(:sub_shared_group) { create(:group, parent: shared_group) }
let_it_be(:other_group) { create(:group) }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index e8e805b2678..61662411ac8 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -359,7 +359,7 @@ RSpec.describe Group do
context 'parent is updated' do
let(:new_parent) { create(:group) }
- subject {group.update!(parent: new_parent, name: 'new name') }
+ subject { group.update!(parent: new_parent, name: 'new name') }
it_behaves_like 'update on column', :traversal_ids
end
@@ -806,6 +806,20 @@ RSpec.describe Group do
end
end
+ describe '.project_creation_allowed' do
+ let_it_be(:group_1) { create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS) }
+ let_it_be(:group_2) { create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
+ let_it_be(:group_3) { create(:group, project_creation_level: Gitlab::Access::MAINTAINER_PROJECT_ACCESS) }
+ let_it_be(:group_4) { create(:group, project_creation_level: nil) }
+
+ it 'only includes groups where project creation is allowed' do
+ result = described_class.project_creation_allowed
+
+ expect(result).to include(group_2, group_3, group_4)
+ expect(result).not_to include(group_1)
+ end
+ end
+
describe 'by_ids_or_paths' do
let(:group_path) { 'group_path' }
let!(:group) { create(:group, path: group_path) }
@@ -2603,7 +2617,11 @@ RSpec.describe Group do
it 'does not enable shared runners' do
expect do
- subject rescue nil
+ begin
+ subject
+ rescue StandardError
+ nil
+ end
parent.reload
group.reload
@@ -2704,7 +2722,11 @@ RSpec.describe Group do
it 'does not allow descendants to override' do
expect do
- subject rescue nil
+ begin
+ subject
+ rescue StandardError
+ nil
+ end
parent.reload
group.reload
@@ -2848,7 +2870,7 @@ RSpec.describe Group do
end
context 'for subgroup project' do
- let_it_be(:subgroup) { create(:group, :private, parent: group)}
+ let_it_be(:subgroup) { create(:group, :private, parent: group) }
let_it_be(:project) { create(:project, group: subgroup, service_desk_enabled: true) }
it { is_expected.to eq(true) }
@@ -3383,6 +3405,20 @@ RSpec.describe Group do
end
end
+ describe '#work_items_mvc_2_feature_flag_enabled?' do
+ it_behaves_like 'checks self and root ancestor feature flag' do
+ let(:feature_flag) { :work_items_mvc_2 }
+ let(:feature_flag_method) { :work_items_mvc_2_feature_flag_enabled? }
+ end
+ end
+
+ describe '#work_items_create_from_markdown_feature_flag_enabled?' do
+ it_behaves_like 'checks self and root ancestor feature flag' do
+ let(:feature_flag) { :work_items_create_from_markdown }
+ let(:feature_flag_method) { :work_items_create_from_markdown_feature_flag_enabled? }
+ end
+ end
+
describe 'group shares' do
let!(:sub_group) { create(:group, parent: group) }
let!(:sub_sub_group) { create(:group, parent: sub_group) }
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index 9f5f81dd6c0..f4786083b75 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe SystemHook do
let(:project) { create(:project, namespace: user.namespace) }
let(:group) { create(:group) }
let(:params) do
- { name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: 'mydummypass' }
+ { name: 'John Doe', username: 'jduser', email: 'jg@example.com', password: User.random_password }
end
before do
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 9faa5e1567c..036d2effc0f 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -482,12 +482,6 @@ RSpec.describe WebHook do
expect(hook).not_to be_temporarily_disabled
end
-
- it 'can ignore the feature flag' do
- stub_feature_flags(web_hooks_disable_failed: false)
-
- expect(hook).to be_temporarily_disabled(ignore_flag: true)
- end
end
end
@@ -510,12 +504,6 @@ RSpec.describe WebHook do
expect(hook).not_to be_permanently_disabled
end
-
- it 'can ignore the feature flag' do
- stub_feature_flags(web_hooks_disable_failed: false)
-
- expect(hook).to be_permanently_disabled(ignore_flag: true)
- end
end
end
diff --git a/spec/models/incident_management/issuable_escalation_status_spec.rb b/spec/models/incident_management/issuable_escalation_status_spec.rb
index 39d1fb325f5..f87e6e8327a 100644
--- a/spec/models/incident_management/issuable_escalation_status_spec.rb
+++ b/spec/models/incident_management/issuable_escalation_status_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatus do
describe 'associations' do
it { is_expected.to belong_to(:issue) }
+
it do
is_expected.to have_one(:project).through(:issue).inverse_of(:incident_management_issuable_escalation_statuses)
end
diff --git a/spec/models/incident_management/timeline_event_spec.rb b/spec/models/incident_management/timeline_event_spec.rb
index 17150fc9266..9f4011fe6a7 100644
--- a/spec/models/incident_management/timeline_event_spec.rb
+++ b/spec/models/incident_management/timeline_event_spec.rb
@@ -47,11 +47,20 @@ RSpec.describe IncidentManagement::TimelineEvent do
describe '#cache_markdown_field' do
let(:note) { 'note **bold** _italic_ `code` ![image](/path/img.png) :+1:ðŸ‘' }
+
+ let(:expected_image_html) do
+ '<a class="with-attachment-icon" href="/path/img.png" target="_blank" rel="noopener noreferrer">image</a>'
+ end
+
+ # rubocop:disable Layout/LineLength
+ let(:expected_emoji_html) do
+ '<gl-emoji title="thumbs up sign" data-name="thumbsup" data-unicode-version="6.0">ðŸ‘</gl-emoji><gl-emoji title="thumbs up sign" data-name="thumbsup" data-unicode-version="6.0">ðŸ‘</gl-emoji>'
+ end
+
let(:expected_note_html) do
- # rubocop:disable Layout/LineLength
- '<p>note <strong>bold</strong> <em>italic</em> <code>code</code> <a class="with-attachment-icon" href="/path/img.png" target="_blank" rel="noopener noreferrer">image</a> ðŸ‘ðŸ‘</p>'
- # rubocop:enable Layout/LineLength
+ %Q(<p>note <strong>bold</strong> <em>italic</em> <code>code</code> #{expected_image_html} #{expected_emoji_html}</p>)
end
+ # rubocop:enable Layout/LineLength
before do
allow(Banzai::Renderer).to receive(:cacheless_render_field).and_call_original
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 86074765c7b..950f2c639fb 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -11,9 +11,8 @@ RSpec.describe Integration do
describe "Associations" do
it { is_expected.to belong_to(:project).inverse_of(:integrations) }
it { is_expected.to belong_to(:group).inverse_of(:integrations) }
- it { is_expected.to have_one(:service_hook).inverse_of(:integration).with_foreign_key(:service_id) }
- it { is_expected.to have_one(:issue_tracker_data).autosave(true).inverse_of(:integration).with_foreign_key(:service_id).class_name('Integrations::IssueTrackerData') }
- it { is_expected.to have_one(:jira_tracker_data).autosave(true).inverse_of(:integration).with_foreign_key(:service_id).class_name('Integrations::JiraTrackerData') }
+ it { is_expected.to have_one(:issue_tracker_data).autosave(true).inverse_of(:integration).with_foreign_key(:integration_id).class_name('Integrations::IssueTrackerData') }
+ it { is_expected.to have_one(:jira_tracker_data).autosave(true).inverse_of(:integration).with_foreign_key(:integration_id).class_name('Integrations::JiraTrackerData') }
end
describe 'validations' do
diff --git a/spec/models/integrations/bamboo_spec.rb b/spec/models/integrations/bamboo_spec.rb
index 574b87d6c60..e92226d109f 100644
--- a/spec/models/integrations/bamboo_spec.rb
+++ b/spec/models/integrations/bamboo_spec.rb
@@ -33,6 +33,7 @@ RSpec.describe Integrations::Bamboo, :use_clean_rails_memory_store_caching do
it { is_expected.to validate_presence_of(:build_key) }
it { is_expected.to validate_presence_of(:bamboo_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :bamboo_url
describe '#username' do
diff --git a/spec/models/integrations/bugzilla_spec.rb b/spec/models/integrations/bugzilla_spec.rb
index 432306c8fa8..f05bc26d066 100644
--- a/spec/models/integrations/bugzilla_spec.rb
+++ b/spec/models/integrations/bugzilla_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Integrations::Bugzilla do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:issues_url) }
it { is_expected.to validate_presence_of(:new_issue_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :project_url
it_behaves_like 'issue tracker integration URL attribute', :issues_url
it_behaves_like 'issue tracker integration URL attribute', :new_issue_url
diff --git a/spec/models/integrations/buildkite_spec.rb b/spec/models/integrations/buildkite_spec.rb
index af2e587dc7b..38ceb5db49c 100644
--- a/spec/models/integrations/buildkite_spec.rb
+++ b/spec/models/integrations/buildkite_spec.rb
@@ -30,6 +30,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:token) }
+
it_behaves_like 'issue tracker integration URL attribute', :project_url
end
diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb
index 48e24299bbd..a6bcd22b6f6 100644
--- a/spec/models/integrations/campfire_spec.rb
+++ b/spec/models/integrations/campfire_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Integrations::Campfire do
describe 'Validations' do
it { is_expected.to validate_numericality_of(:room).is_greater_than(0).only_integer }
- it { is_expected.to validate_length_of(:subdomain).is_at_most(63) }
+ it { is_expected.to validate_length_of(:subdomain).is_at_least(1).is_at_most(63).allow_blank }
it { is_expected.to allow_value("foo").for(:subdomain) }
it { is_expected.not_to allow_value("foo.bar").for(:subdomain) }
it { is_expected.not_to allow_value("foo.bar/#").for(:subdomain) }
diff --git a/spec/models/integrations/chat_message/issue_message_spec.rb b/spec/models/integrations/chat_message/issue_message_spec.rb
index 7026a314b78..4a86322cdaf 100644
--- a/spec/models/integrations/chat_message/issue_message_spec.rb
+++ b/spec/models/integrations/chat_message/issue_message_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Integrations::ChatMessage::IssueMessage do
end
it 'returns a message regarding closing of issues' do
- expect(subject.pretext). to eq(
+ expect(subject.pretext).to eq(
'[<http://somewhere.com|project_name>] Issue <http://url.com|#100 Issue title> closed by Test User (test.user)')
expect(subject.attachments).to be_empty
end
@@ -111,7 +111,7 @@ RSpec.describe Integrations::ChatMessage::IssueMessage do
end
it 'returns a message regarding closing of issues' do
- expect(subject.pretext). to eq(
+ expect(subject.pretext).to eq(
'[[project_name](http://somewhere.com)] Issue [#100 Issue title](http://url.com) closed by Test User (test.user)')
expect(subject.attachments).to be_empty
expect(subject.activity).to eq({
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 4aa96c7e031..16659311c52 100644
--- a/spec/models/integrations/chat_message/wiki_page_message_spec.rb
+++ b/spec/models/integrations/chat_message/wiki_page_message_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Integrations::ChatMessage::WikiPageMessage do
let(:username) { 'test.user' }
let(:avatar_url) { 'http://someavatar.com' }
let(:project_name) { 'project_name' }
- let(:project_url) {'http://somewhere.com' }
+ let(:project_url) { 'http://somewhere.com' }
let(:url) { 'http://url.com' }
let(:diff_url) { 'http://url.com/diff?version_id=1234' }
let(:wiki_page_title) { 'Wiki page title' }
diff --git a/spec/models/integrations/custom_issue_tracker_spec.rb b/spec/models/integrations/custom_issue_tracker_spec.rb
index e1ffe7a74f0..11f98b99bbe 100644
--- a/spec/models/integrations/custom_issue_tracker_spec.rb
+++ b/spec/models/integrations/custom_issue_tracker_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Integrations::CustomIssueTracker do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:issues_url) }
it { is_expected.to validate_presence_of(:new_issue_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :project_url
it_behaves_like 'issue tracker integration URL attribute', :issues_url
it_behaves_like 'issue tracker integration URL attribute', :new_issue_url
diff --git a/spec/models/integrations/datadog_spec.rb b/spec/models/integrations/datadog_spec.rb
index 47f916e8457..cfc44b22a84 100644
--- a/spec/models/integrations/datadog_spec.rb
+++ b/spec/models/integrations/datadog_spec.rb
@@ -240,20 +240,4 @@ RSpec.describe Integrations::Datadog do
end
end
end
-
- describe '#fields' do
- it 'includes the archive_trace_events field' do
- expect(instance.fields).to include(have_attributes(name: 'archive_trace_events'))
- end
-
- context 'when the FF :datadog_integration_logs_collection is disabled' do
- before do
- stub_feature_flags(datadog_integration_logs_collection: false)
- end
-
- it 'does not include the archive_trace_events field' do
- expect(instance.fields).not_to include(have_attributes(name: 'archive_trace_events'))
- end
- end
- end
end
diff --git a/spec/models/integrations/drone_ci_spec.rb b/spec/models/integrations/drone_ci_spec.rb
index 5ae4af1a665..8a51f8a0705 100644
--- a/spec/models/integrations/drone_ci_spec.rb
+++ b/spec/models/integrations/drone_ci_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do
it { is_expected.to validate_presence_of(:token) }
it { is_expected.to validate_presence_of(:drone_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :drone_url
end
diff --git a/spec/models/integrations/ewm_spec.rb b/spec/models/integrations/ewm_spec.rb
index 49681fefe55..dc48a2c982f 100644
--- a/spec/models/integrations/ewm_spec.rb
+++ b/spec/models/integrations/ewm_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe Integrations::Ewm do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:issues_url) }
it { is_expected.to validate_presence_of(:new_issue_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :project_url
it_behaves_like 'issue tracker integration URL attribute', :issues_url
it_behaves_like 'issue tracker integration URL attribute', :new_issue_url
diff --git a/spec/models/integrations/external_wiki_spec.rb b/spec/models/integrations/external_wiki_spec.rb
index 1621605d39f..8644e20690c 100644
--- a/spec/models/integrations/external_wiki_spec.rb
+++ b/spec/models/integrations/external_wiki_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Integrations::ExternalWiki do
end
it { is_expected.to validate_presence_of(:external_wiki_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :external_wiki_url
end
diff --git a/spec/models/integrations/harbor_spec.rb b/spec/models/integrations/harbor_spec.rb
index 5d8597969a1..3952495119a 100644
--- a/spec/models/integrations/harbor_spec.rb
+++ b/spec/models/integrations/harbor_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Integrations::Harbor do
it { is_expected.not_to allow_value('https://192.168.1.1').for(:url) }
it { is_expected.not_to allow_value('https://127.0.0.1').for(:url) }
- it { is_expected.to allow_value('https://demo.goharbor.io').for(:url)}
+ it { is_expected.to allow_value('https://demo.goharbor.io').for(:url) }
end
describe '#fields' do
@@ -63,6 +63,8 @@ RSpec.describe Integrations::Harbor do
it 'returns vars when harbor_integration is activated' do
ci_vars = [
{ key: 'HARBOR_URL', value: url },
+ { key: 'HARBOR_HOST', value: 'demo.goharbor.io' },
+ { key: 'HARBOR_OCI', value: 'oci://demo.goharbor.io' },
{ key: 'HARBOR_PROJECT', value: project_name },
{ key: 'HARBOR_USERNAME', value: username },
{ key: 'HARBOR_PASSWORD', value: password, public: false, masked: true }
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
index 01c08a0948f..a52a4514ebe 100644
--- a/spec/models/integrations/jira_spec.rb
+++ b/spec/models/integrations/jira_spec.rb
@@ -619,6 +619,18 @@ RSpec.describe Integrations::Jira do
close_issue
end
+ it_behaves_like 'Snowplow event tracking' do
+ subject { close_issue }
+
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:category) { 'Integrations::Jira' }
+ let(:action) { 'perform_integrations_action' }
+ let(:namespace) { project.namespace }
+ let(:user) { current_user }
+ let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' }
+ let(:property) { 'i_ecosystem_jira_service_close_issue' }
+ end
+
it 'does not fail if remote_link.all on issue returns nil' do
allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
@@ -962,6 +974,16 @@ RSpec.describe Integrations::Jira do
subject
end
+
+ it_behaves_like 'Snowplow event tracking' do
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:category) { 'Integrations::Jira' }
+ let(:action) { 'perform_integrations_action' }
+ let(:namespace) { project.namespace }
+ let(:user) { current_user }
+ let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' }
+ let(:property) { 'i_ecosystem_jira_service_cross_reference' }
+ end
end
context 'for commits' do
diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb
index af6c142525c..b1b3e42b5e9 100644
--- a/spec/models/integrations/microsoft_teams_spec.rb
+++ b/spec/models/integrations/microsoft_teams_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe Integrations::MicrosoftTeams do
end
it { is_expected.to validate_presence_of(:webhook) }
+
it_behaves_like 'issue tracker integration URL attribute', :webhook
end
diff --git a/spec/models/integrations/pumble_spec.rb b/spec/models/integrations/pumble_spec.rb
new file mode 100644
index 00000000000..8b9b5d214c6
--- /dev/null
+++ b/spec/models/integrations/pumble_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Integrations::Pumble do
+ it_behaves_like "chat integration", "Pumble" do
+ let(:client_arguments) { webhook_url }
+ let(:payload) do
+ {
+ text: be_present
+ }
+ end
+ end
+end
diff --git a/spec/models/integrations/slack_spec.rb b/spec/models/integrations/slack_spec.rb
index 5801a4c3749..ed282f1d39d 100644
--- a/spec/models/integrations/slack_spec.rb
+++ b/spec/models/integrations/slack_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe Integrations::Slack do
it_behaves_like Integrations::SlackMattermostNotifier, "Slack"
describe '#execute' do
- let_it_be(:slack_integration) { create(:integrations_slack, branches_to_be_notified: 'all') }
+ let(:slack_integration) { create(:integrations_slack, branches_to_be_notified: 'all', project_id: project.id) }
+ let(:project) { create_default(:project, :repository, :wiki_repo) }
before do
stub_request(:post, slack_integration.webhook)
@@ -20,13 +21,23 @@ RSpec.describe Integrations::Slack do
context 'hook data includes a user object' do
let_it_be(:user) { create_default(:user) }
- let_it_be(:project) { create_default(:project, :repository, :wiki_repo) }
shared_examples 'increases the usage data counter' do |event_name|
+ subject(:execute) { slack_integration.execute(data) }
+
it 'increases the usage data counter' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: user.id).and_call_original
- slack_integration.execute(data)
+ execute
+ end
+
+ it_behaves_like 'Snowplow event tracking' do
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+ let(:category) { 'Integrations::Slack' }
+ let(:action) { 'perform_integrations_action' }
+ let(:namespace) { project.namespace }
+ let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' }
+ let(:property) { event_name }
end
end
diff --git a/spec/models/integrations/teamcity_spec.rb b/spec/models/integrations/teamcity_spec.rb
index 046476225a6..da559264c1e 100644
--- a/spec/models/integrations/teamcity_spec.rb
+++ b/spec/models/integrations/teamcity_spec.rb
@@ -76,6 +76,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do
it { is_expected.to validate_presence_of(:build_type) }
it { is_expected.to validate_presence_of(:teamcity_url) }
+
it_behaves_like 'issue tracker integration URL attribute', :teamcity_url
describe '#username' do
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 89c440dc49c..15fe6d7625a 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -69,7 +69,57 @@ RSpec.describe Issue do
end
describe 'validations' do
- subject { issue.valid? }
+ subject(:valid?) { issue.valid? }
+
+ describe 'due_date_after_start_date' do
+ let(:today) { Date.today }
+
+ context 'when both values are not present' do
+ let(:issue) { build(:issue) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when start date is present and due date is not' do
+ let(:issue) { build(:work_item, start_date: today) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when due date is present and start date is not' do
+ let(:issue) { build(:work_item, due_date: today) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when both date values are present' do
+ context 'when due date is greater than start date' do
+ let(:issue) { build(:work_item, start_date: today, due_date: 1.week.from_now) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when due date is equal to start date' do
+ let(:issue) { build(:work_item, start_date: today, due_date: today) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when due date is before start date' do
+ let(:issue) { build(:work_item, due_date: today, start_date: 1.week.from_now) }
+
+ it { is_expected.to be_falsey }
+
+ it 'adds an error message' do
+ valid?
+
+ expect(issue.errors.full_messages).to contain_exactly(
+ 'Due date must be greater than or equal to start date'
+ )
+ end
+ end
+ end
+ end
describe 'issue_type' do
let(:issue) { build(:issue, issue_type: issue_type) }
@@ -86,6 +136,54 @@ RSpec.describe Issue do
it { is_expected.to eq(false) }
end
end
+
+ describe 'confidentiality' do
+ let_it_be(:project) { create(:project) }
+
+ context 'when parent and child are confidential' do
+ let_it_be(:parent) { create(:work_item, confidential: true, project: project) }
+ let_it_be(:child) { create(:work_item, :task, confidential: true, project: project) }
+ let_it_be(:link) { create(:parent_link, work_item: child, work_item_parent: parent) }
+
+ it 'does not allow to make child not-confidential' do
+ issue = Issue.find(child.id)
+ issue.confidential = false
+
+ expect(issue).not_to be_valid
+ expect(issue.errors[:confidential])
+ .to include('associated parent is confidential and can not have non-confidential children.')
+ end
+
+ it 'allows to make parent not-confidential' do
+ issue = Issue.find(parent.id)
+ issue.confidential = false
+
+ expect(issue).to be_valid
+ end
+ end
+
+ context 'when parent and child are not-confidential' do
+ let_it_be(:parent) { create(:work_item, project: project) }
+ let_it_be(:child) { create(:work_item, :task, project: project) }
+ let_it_be(:link) { create(:parent_link, work_item: child, work_item_parent: parent) }
+
+ it 'does not allow to make parent confidential' do
+ issue = Issue.find(parent.id)
+ issue.confidential = true
+
+ expect(issue).not_to be_valid
+ expect(issue.errors[:confidential])
+ .to include('confidential parent can not be used if there are non-confidential children.')
+ end
+
+ it 'allows to make child confidential' do
+ issue = Issue.find(child.id)
+ issue.confidential = true
+
+ expect(issue).to be_valid
+ end
+ end
+ end
end
subject { create(:issue, project: reusable_project) }
@@ -124,6 +222,61 @@ RSpec.describe Issue do
end
end
+ describe '#ensure_work_item_type' do
+ let_it_be(:issue_type) { create(:work_item_type, :issue, :default) }
+ let_it_be(:task_type) { create(:work_item_type, :issue, :default) }
+ let_it_be(:project) { create(:project) }
+
+ context 'when a type was already set' do
+ let_it_be(:issue, refind: true) { create(:issue, project: project) }
+
+ it 'does not fetch a work item type from the DB' do
+ expect(issue.work_item_type_id).to eq(issue_type.id)
+ expect(WorkItems::Type).not_to receive(:default_by_type)
+
+ expect(issue).to be_valid
+ end
+
+ it 'does not fetch a work item type from the DB when updating the type' do
+ expect(issue.work_item_type_id).to eq(issue_type.id)
+ expect(WorkItems::Type).not_to receive(:default_by_type)
+
+ issue.update!(work_item_type: task_type, issue_type: 'task')
+
+ expect(issue.work_item_type_id).to eq(task_type.id)
+ end
+
+ it 'ensures a work item type if updated to nil' do
+ expect(issue.work_item_type_id).to eq(issue_type.id)
+
+ expect do
+ issue.update!(work_item_type: nil)
+ end.to not_change(issue, :work_item_type).from(issue_type)
+ end
+ end
+
+ context 'when no type was set' do
+ let_it_be(:issue, refind: true) { build(:issue, project: project, work_item_type: nil).tap { |issue| issue.save!(validate: false) } }
+
+ it 'sets a work item type before validation' do
+ expect(issue.work_item_type_id).to be_nil
+
+ issue.save!
+
+ expect(issue.work_item_type_id).to eq(issue_type.id)
+ end
+
+ it 'does not fetch type from DB if provided during update' do
+ expect(issue.work_item_type_id).to be_nil
+ expect(WorkItems::Type).not_to receive(:default_by_type)
+
+ issue.update!(work_item_type: task_type, issue_type: 'task')
+
+ expect(issue.work_item_type_id).to eq(task_type.id)
+ end
+ end
+ end
+
describe '#record_create_action' do
it 'records the creation action after saving' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_created_action)
@@ -289,7 +442,7 @@ RSpec.describe Issue do
# TODO: Remove when NOT NULL constraint is added to the relationship
describe '#work_item_type' do
- let(:issue) { create(:issue, :incident, project: reusable_project, work_item_type: nil) }
+ let(:issue) { build(:issue, :incident, project: reusable_project, work_item_type: nil).tap { |issue| issue.save!(validate: false) } }
it 'returns a default type if the legacy issue does not have a work item type associated yet' do
expect(issue.work_item_type_id).to be_nil
@@ -493,7 +646,7 @@ RSpec.describe Issue do
let_it_be(:authorized_issue_a) { create(:issue, project: authorized_project) }
let_it_be(:authorized_issue_b) { create(:issue, project: authorized_project) }
let_it_be(:authorized_issue_c) { create(:issue, project: authorized_project2) }
- let_it_be(:authorized_incident_a) { create(:incident, project: authorized_project )}
+ let_it_be(:authorized_incident_a) { create(:incident, project: authorized_project ) }
let_it_be(:unauthorized_issue) { create(:issue, project: unauthorized_project) }
@@ -550,7 +703,7 @@ RSpec.describe Issue do
subject { issue.can_move?(user) }
context 'user is not a member of project issue belongs to' do
- it { is_expected.to eq false}
+ it { is_expected.to eq false }
end
context 'user is reporter in project issue belongs to' do
@@ -1074,7 +1227,7 @@ RSpec.describe Issue do
end
context 'when issue is moved to a private project' do
- let(:private_project) { build(:project, :private)}
+ let(:private_project) { build(:project, :private) }
before do
issue.update!(project: private_project) # move issue to private project
@@ -1621,4 +1774,20 @@ RSpec.describe Issue do
end
end
end
+
+ describe '#full_search' do
+ context 'when searching non-english terms' do
+ [
+ 'abc 中文語',
+ '中文語cn',
+ '中文語'
+ ].each do |term|
+ it 'adds extra where clause to match partial index' do
+ expect(described_class.full_search(term).to_sql).to include(
+ "AND (issues.title NOT SIMILAR TO '[\\u0000-\\u218F]*' OR issues.description NOT SIMILAR TO '[\\u0000-\\u218F]*')"
+ )
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/jira_import_state_spec.rb b/spec/models/jira_import_state_spec.rb
index a272d001429..95e9594f885 100644
--- a/spec/models/jira_import_state_spec.rb
+++ b/spec/models/jira_import_state_spec.rb
@@ -25,25 +25,25 @@ RSpec.describe JiraImportState do
let(:project) { create(:project) }
context 'when project has an initial jira_import' do
- let!(:jira_import) { create(:jira_import_state, project: project)}
+ let!(:jira_import) { create(:jira_import_state, project: project) }
it_behaves_like 'multiple running imports not allowed'
end
context 'when project has a scheduled jira_import' do
- let!(:jira_import) { create(:jira_import_state, :scheduled, project: project)}
+ let!(:jira_import) { create(:jira_import_state, :scheduled, project: project) }
it_behaves_like 'multiple running imports not allowed'
end
context 'when project has a started jira_import' do
- let!(:jira_import) { create(:jira_import_state, :started, project: project)}
+ let!(:jira_import) { create(:jira_import_state, :started, project: project) }
it_behaves_like 'multiple running imports not allowed'
end
context 'when project has a failed jira_import' do
- let!(:jira_import) { create(:jira_import_state, :failed, project: project)}
+ let!(:jira_import) { create(:jira_import_state, :failed, project: project) }
it 'returns valid' do
new_import = build(:jira_import_state, project: project)
@@ -54,7 +54,7 @@ RSpec.describe JiraImportState do
end
context 'when project has a finished jira_import' do
- let!(:jira_import) { create(:jira_import_state, :finished, project: project)}
+ let!(:jira_import) { create(:jira_import_state, :finished, project: project) }
it 'returns valid' do
new_import = build(:jira_import_state, project: project)
@@ -83,40 +83,40 @@ RSpec.describe JiraImportState do
let(:project) { create(:project) }
context 'when jira import is in initial state' do
- let!(:jira_import) { build(:jira_import_state, project: project)}
+ let!(:jira_import) { build(:jira_import_state, project: project) }
it_behaves_like 'can transition', [:schedule, :do_fail]
it_behaves_like 'cannot transition', [:start, :finish]
end
context 'when jira import is in scheduled state' do
- let!(:jira_import) { build(:jira_import_state, :scheduled, project: project)}
+ let!(:jira_import) { build(:jira_import_state, :scheduled, project: project) }
it_behaves_like 'can transition', [:start, :do_fail]
it_behaves_like 'cannot transition', [:finish]
end
context 'when jira import is in started state' do
- let!(:jira_import) { build(:jira_import_state, :started, project: project)}
+ let!(:jira_import) { build(:jira_import_state, :started, project: project) }
it_behaves_like 'can transition', [:finish, :do_fail]
it_behaves_like 'cannot transition', [:schedule]
end
context 'when jira import is in failed state' do
- let!(:jira_import) { build(:jira_import_state, :failed, project: project)}
+ let!(:jira_import) { build(:jira_import_state, :failed, project: project) }
it_behaves_like 'cannot transition', [:schedule, :finish, :do_fail]
end
context 'when jira import is in finished state' do
- let!(:jira_import) { build(:jira_import_state, :finished, project: project)}
+ let!(:jira_import) { build(:jira_import_state, :finished, project: project) }
it_behaves_like 'cannot transition', [:schedule, :do_fail, :start]
end
context 'after transition to scheduled' do
- let!(:jira_import) { build(:jira_import_state, project: project)}
+ let!(:jira_import) { build(:jira_import_state, project: project) }
it 'triggers the import job' do
expect(Gitlab::JiraImport::Stage::StartImportWorker).to receive(:perform_async).and_return('some-job-id')
@@ -129,7 +129,7 @@ RSpec.describe JiraImportState do
end
context 'after transition to finished' do
- let!(:jira_import) { build(:jira_import_state, :started, jid: 'some-other-jid', project: project)}
+ let!(:jira_import) { build(:jira_import_state, :started, jid: 'some-other-jid', project: project) }
subject { jira_import.finish }
@@ -172,7 +172,7 @@ RSpec.describe JiraImportState do
end
context 'when jira import has no error_message' do
- let(:jira_import) { build(:jira_import_state, project: project)}
+ let(:jira_import) { build(:jira_import_state, project: project) }
it 'does not run the callback', :aggregate_failures do
expect { jira_import.save! }.to change { JiraImportState.count }.by(1)
@@ -181,7 +181,7 @@ RSpec.describe JiraImportState do
end
context 'when jira import error_message does not exceed the limit' do
- let(:jira_import) { build(:jira_import_state, project: project, error_message: 'error')}
+ let(:jira_import) { build(:jira_import_state, project: project, error_message: 'error') }
it 'does not run the callback', :aggregate_failures do
expect { jira_import.save! }.to change { JiraImportState.count }.by(1)
@@ -190,7 +190,7 @@ RSpec.describe JiraImportState do
end
context 'when error_message exceeds limit' do
- let(:jira_import) { build(:jira_import_state, project: project, error_message: 'error message longer than the limit')}
+ let(:jira_import) { build(:jira_import_state, project: project, error_message: 'error message longer than the limit') }
it 'truncates error_message to the limit', :aggregate_failures do
expect { jira_import.save! }.to change { JiraImportState.count }.by(1)
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 5210709a468..c25d0451f18 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -193,9 +193,9 @@ RSpec.describe LfsObject do
end
describe '.unreferenced_in_batches' do
- let!(:unreferenced_lfs_object1) { create(:lfs_object, oid: '1') }
+ let!(:unreferenced_lfs_object1) { create(:lfs_object, oid: '1' * 64) }
let!(:referenced_lfs_object) { create(:lfs_objects_project).lfs_object }
- let!(:unreferenced_lfs_object2) { create(:lfs_object, oid: '2') }
+ let!(:unreferenced_lfs_object2) { create(:lfs_object, oid: '2' * 64) }
it 'returns lfs objects in batches' do
stub_const('LfsObject::BATCH_SIZE', 1)
diff --git a/spec/models/loose_foreign_keys/deleted_record_spec.rb b/spec/models/loose_foreign_keys/deleted_record_spec.rb
index 23e0ed1f39d..9ee5b7340f3 100644
--- a/spec/models/loose_foreign_keys/deleted_record_spec.rb
+++ b/spec/models/loose_foreign_keys/deleted_record_spec.rb
@@ -94,14 +94,6 @@ RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
end
it { is_expected.to eq(true) }
-
- context 'when the lfk_automatic_partition_creation FF is off' do
- before do
- stub_feature_flags(lfk_automatic_partition_creation: false)
- end
-
- it { is_expected.to eq(false) }
- end
end
end
@@ -126,14 +118,6 @@ RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
end
it { is_expected.to eq(true) }
-
- context 'when the lfk_automatic_partition_dropping FF is off' do
- before do
- stub_feature_flags(lfk_automatic_partition_dropping: false)
- end
-
- it { is_expected.to eq(false) }
- end
end
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 286167c918f..2716244b7f3 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe Member do
describe 'Associations' do
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:member_namespace) }
+ it { is_expected.to belong_to(:member_role) }
it { is_expected.to have_one(:member_task) }
end
@@ -166,6 +167,36 @@ RSpec.describe Member do
end
end
end
+
+ context 'member role access level' do
+ let_it_be(:member) { create(:group_member, access_level: Gitlab::Access::DEVELOPER) }
+
+ context 'no member role is associated' do
+ it 'is valid' do
+ expect(member).to be_valid
+ end
+ end
+
+ context 'member role is associated' do
+ let_it_be(:member_role) do
+ create(:member_role, members: [member])
+ end
+
+ context 'member role matches access level' do
+ it 'is valid' do
+ expect(member).to be_valid
+ end
+ end
+
+ context 'member role does not match access level' do
+ it 'is invalid' do
+ member_role.base_access_level = Gitlab::Access::MAINTAINER
+
+ expect(member).not_to be_valid
+ end
+ end
+ end
+ end
end
describe 'Scopes & finders' do
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index 94032146f51..c6266f15340 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -165,78 +165,28 @@ RSpec.describe GroupMember do
let_it_be(:project_b) { create(:project, group: group) }
let_it_be(:project_c) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
- let_it_be(:affected_project_ids) { Project.id_in([project_a, project_b, project_c]).ids }
- before do
- stub_const(
- "#{described_class.name}::THRESHOLD_FOR_REFRESHING_AUTHORIZATIONS_VIA_PROJECTS",
- affected_project_ids.size - 1)
- end
-
- shared_examples_for 'calls UserProjectAccessChangedService to recalculate authorizations' do
- it 'calls UserProjectAccessChangedService to recalculate authorizations' do
- expect_next_instance_of(UserProjectAccessChangedService, user.id) do |service|
- expect(service).to receive(:execute).with(blocking: blocking)
- end
+ shared_examples_for 'calls AuthorizedProjectsWorker inline to recalculate authorizations' do
+ # this is inline with the overridden behaviour in stubbed_member.rb
+ it 'calls AuthorizedProjectsWorker inline to recalculate authorizations' do
+ worker_instance = AuthorizedProjectsWorker.new
+ expect(AuthorizedProjectsWorker).to receive(:new).and_return(worker_instance)
+ expect(worker_instance).to receive(:perform).with(user.id)
action
end
end
- shared_examples_for 'tries to update permissions via refreshing authorizations for the affected projects' do
- context 'when the number of affected projects exceeds the set threshold' do
- it 'updates permissions via refreshing authorizations for the affected projects asynchronously' do
- expect_next_instance_of(
- AuthorizedProjectUpdate::ProjectAccessChangedService, affected_project_ids
- ) do |service|
- expect(service).to receive(:execute).with(blocking: false)
- end
-
- action
- end
-
- it 'calls AuthorizedProjectUpdate::UserRefreshFromReplicaWorker with a delay as a safety net' do
- expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to(
- receive(:bulk_perform_in)
- .with(1.hour,
- [[user.id]],
- batch_delay: 30.seconds, batch_size: 100)
- )
-
- action
- end
- end
-
- context 'when the number of affected projects does not exceed the set threshold' do
- before do
- stub_const(
- "#{described_class.name}::THRESHOLD_FOR_REFRESHING_AUTHORIZATIONS_VIA_PROJECTS",
- affected_project_ids.size + 1)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
- end
-
context 'on create' do
let(:action) { group.add_member(user, Gitlab::Access::GUEST) }
- let(:blocking) { true }
- it 'changes access level', :sidekiq_inline do
+ it 'changes access level' do
expect { action }.to change { user.can?(:guest_access, project_a) }.from(false).to(true)
.and change { user.can?(:guest_access, project_b) }.from(false).to(true)
.and change { user.can?(:guest_access, project_c) }.from(false).to(true)
end
- it_behaves_like 'tries to update permissions via refreshing authorizations for the affected projects'
-
- context 'when the feature flag `refresh_authorizations_via_affected_projects_on_group_membership` is disabled' do
- before do
- stub_feature_flags(refresh_authorizations_via_affected_projects_on_group_membership: false)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
+ it_behaves_like 'calls AuthorizedProjectsWorker inline to recalculate authorizations'
end
context 'on update' do
@@ -245,23 +195,14 @@ RSpec.describe GroupMember do
end
let(:action) { group.members.find_by(user: user).update!(access_level: Gitlab::Access::DEVELOPER) }
- let(:blocking) { true }
- it 'changes access level', :sidekiq_inline do
+ it 'changes access level' do
expect { action }.to change { user.can?(:developer_access, project_a) }.from(false).to(true)
.and change { user.can?(:developer_access, project_b) }.from(false).to(true)
.and change { user.can?(:developer_access, project_c) }.from(false).to(true)
end
- it_behaves_like 'tries to update permissions via refreshing authorizations for the affected projects'
-
- context 'when the feature flag `refresh_authorizations_via_affected_projects_on_group_membership` is disabled' do
- before do
- stub_feature_flags(refresh_authorizations_via_affected_projects_on_group_membership: false)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
- end
+ it_behaves_like 'calls AuthorizedProjectsWorker inline to recalculate authorizations'
end
context 'on destroy' do
@@ -270,7 +211,6 @@ RSpec.describe GroupMember do
end
let(:action) { group.members.find_by(user: user).destroy! }
- let(:blocking) { false }
it 'changes access level', :sidekiq_inline do
expect { action }.to change { user.can?(:guest_access, project_a) }.from(true).to(false)
@@ -278,14 +218,10 @@ RSpec.describe GroupMember do
.and change { user.can?(:guest_access, project_c) }.from(true).to(false)
end
- it_behaves_like 'tries to update permissions via refreshing authorizations for the affected projects'
+ it 'schedules an AuthorizedProjectsWorker job to recalculate authorizations' do
+ expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async).with([[user.id]])
- context 'when the feature flag `refresh_authorizations_via_affected_projects_on_group_membership` is disabled' do
- before do
- stub_feature_flags(refresh_authorizations_via_affected_projects_on_group_membership: false)
- end
-
- it_behaves_like 'calls UserProjectAccessChangedService to recalculate authorizations'
+ action
end
end
end
diff --git a/spec/models/members/member_role_spec.rb b/spec/models/members/member_role_spec.rb
new file mode 100644
index 00000000000..e8993491918
--- /dev/null
+++ b/spec/models/members/member_role_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MemberRole do
+ describe 'associations' do
+ it { is_expected.to belong_to(:namespace) }
+ it { is_expected.to have_many(:members) }
+ end
+
+ describe 'validation' do
+ subject { described_class.new }
+
+ it { is_expected.to validate_presence_of(:namespace_id) }
+ it { is_expected.to validate_presence_of(:base_access_level) }
+ end
+end
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 39d9d25a98c..99fc5dc14df 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -213,10 +213,11 @@ RSpec.describe ProjectMember do
let_it_be(:user) { create(:user) }
shared_examples_for 'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker inline to recalculate authorizations' do
- it 'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker' do
- expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).to receive(:bulk_perform_and_wait).with(
- [[project.id, user.id]]
- )
+ # this is inline with the overridden behaviour in stubbed_member.rb
+ it 'calls AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker inline' do
+ worker_instance = AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.new
+ expect(AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker).to receive(:new).and_return(worker_instance)
+ expect(worker_instance).to receive(:perform).with(project.id, user.id)
action
end
diff --git a/spec/models/merge_request/approval_removal_settings_spec.rb b/spec/models/merge_request/approval_removal_settings_spec.rb
new file mode 100644
index 00000000000..5f879207a72
--- /dev/null
+++ b/spec/models/merge_request/approval_removal_settings_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequest::ApprovalRemovalSettings do
+ describe 'validations' do
+ let(:reset_approvals_on_push) {}
+ let(:selective_code_owner_removals) {}
+
+ subject { described_class.new(project, reset_approvals_on_push, selective_code_owner_removals) }
+
+ context 'when enabling selective_code_owner_removals and reset_approvals_on_push is disabled' do
+ let(:project) { create(:project, reset_approvals_on_push: false) }
+ let(:selective_code_owner_removals) { true }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when enabling selective_code_owner_removals and reset_approvals_on_push is enabled' do
+ let(:project) { create(:project) }
+ let(:selective_code_owner_removals) { true }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when enabling reset_approvals_on_push and selective_code_owner_removals is disabled' do
+ let(:project) { create(:project) }
+ let(:reset_approvals_on_push) { true }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when enabling reset_approvals_on_push and selective_code_owner_removals is enabled' do
+ let(:project) { create(:project) }
+ let(:reset_approvals_on_push) { true }
+
+ before do
+ project.project_setting.update!(selective_code_owner_removals: true)
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when enabling reset_approvals_on_push and selective_code_owner_removals' do
+ let(:project) { create(:project) }
+ let(:reset_approvals_on_push) { true }
+ let(:selective_code_owner_removals) { true }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index c3e325c4e6c..19026a4772d 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -114,10 +114,10 @@ RSpec.describe MergeRequest, factory_default: :keep do
let_it_be(:user1) { create(:user) }
let_it_be(:user2) { create(:user) }
- let_it_be(:merge_request1) { create(:merge_request, :unique_branches, reviewers: [user1])}
- let_it_be(:merge_request2) { create(:merge_request, :unique_branches, reviewers: [user2])}
- let_it_be(:merge_request3) { create(:merge_request, :unique_branches, reviewers: [])}
- let_it_be(:merge_request4) { create(:merge_request, :draft_merge_request)}
+ let_it_be(:merge_request1) { create(:merge_request, :unique_branches, reviewers: [user1]) }
+ let_it_be(:merge_request2) { create(:merge_request, :unique_branches, reviewers: [user2]) }
+ let_it_be(:merge_request3) { create(:merge_request, :unique_branches, reviewers: []) }
+ let_it_be(:merge_request4) { create(:merge_request, :draft_merge_request) }
describe '.review_requested' do
it 'returns MRs that have any review requests' do
@@ -145,8 +145,8 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
describe '.attention' do
- let_it_be(:merge_request5) { create(:merge_request, :unique_branches, assignees: [user2])}
- let_it_be(:merge_request6) { create(:merge_request, :unique_branches, assignees: [user2])}
+ let_it_be(:merge_request5) { create(:merge_request, :unique_branches, assignees: [user2]) }
+ let_it_be(:merge_request6) { create(:merge_request, :unique_branches, assignees: [user2]) }
before do
assignee = merge_request6.find_assignee(user2)
@@ -2056,7 +2056,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
context 'when failed to find an actual head pipeline' do
before do
- allow(merge_request).to receive(:find_actual_head_pipeline) { }
+ allow(merge_request).to receive(:find_actual_head_pipeline) {}
end
it 'does not update the current head pipeline' do
@@ -3232,6 +3232,62 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#detailed_merge_status' do
+ subject(:detailed_merge_status) { merge_request.detailed_merge_status }
+
+ context 'when merge status is cannot_be_merged_rechecking' do
+ let(:merge_request) { create(:merge_request, merge_status: :cannot_be_merged_rechecking) }
+
+ it 'returns :checking' do
+ expect(detailed_merge_status).to eq(:checking)
+ end
+ end
+
+ context 'when merge status is preparing' do
+ let(:merge_request) { create(:merge_request, merge_status: :preparing) }
+
+ it 'returns :checking' do
+ expect(detailed_merge_status).to eq(:checking)
+ end
+ end
+
+ context 'when merge status is checking' do
+ let(:merge_request) { create(:merge_request, merge_status: :checking) }
+
+ it 'returns :checking' do
+ expect(detailed_merge_status).to eq(:checking)
+ end
+ end
+
+ context 'when merge status is unchecked' do
+ let(:merge_request) { create(:merge_request, merge_status: :unchecked) }
+
+ it 'returns :unchecked' do
+ expect(detailed_merge_status).to eq(:unchecked)
+ end
+ end
+
+ context 'when merge checks are a success' do
+ let(:merge_request) { create(:merge_request) }
+
+ it 'returns :mergeable' do
+ expect(detailed_merge_status).to eq(:mergeable)
+ end
+ end
+
+ context 'when merge status have a failure' do
+ let(:merge_request) { create(:merge_request) }
+
+ before do
+ merge_request.close!
+ end
+
+ it 'returns the failure reason' do
+ expect(detailed_merge_status).to eq(:not_open)
+ end
+ end
+ end
+
describe '#mergeable_state?' do
it_behaves_like 'for mergeable_state'
@@ -4660,6 +4716,37 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#in_locked_state' do
+ let(:merge_request) { create(:merge_request, :opened) }
+
+ context 'when the merge request does not change state' do
+ it 'returns to previous state and has no errors on the object' do
+ expect(merge_request.opened?).to eq(true)
+
+ merge_request.in_locked_state do
+ expect(merge_request.locked?).to eq(true)
+ end
+
+ expect(merge_request.opened?).to eq(true)
+ expect(merge_request.errors).to be_empty
+ end
+ end
+
+ context 'when the merge request is merged while locked' do
+ it 'becomes merged and has no errors on the object' do
+ expect(merge_request.opened?).to eq(true)
+
+ merge_request.in_locked_state do
+ expect(merge_request.locked?).to eq(true)
+ merge_request.mark_as_merged!
+ end
+
+ expect(merge_request.merged?).to eq(true)
+ expect(merge_request.errors).to be_empty
+ end
+ end
+ end
+
describe '#cleanup_refs' do
subject { merge_request.cleanup_refs(only: only) }
@@ -5047,6 +5134,12 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
+ describe '#merge_blocked_by_other_mrs?' do
+ it 'returns false when there is no blocking merge requests' do
+ expect(subject.merge_blocked_by_other_mrs?).to be_falsy
+ end
+ end
+
describe '#merge_request_reviewers_with' do
let_it_be(:reviewer1) { create(:user) }
let_it_be(:reviewer2) { create(:user) }
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 72a57b6076a..af1383b68bf 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -257,7 +257,7 @@ RSpec.describe Milestone do
let(:milestone) { create(:milestone, title: 'foo', description: 'bar') }
it 'returns milestones with a matching title' do
- expect(described_class.search_title(milestone.title)) .to eq([milestone])
+ expect(described_class.search_title(milestone.title)).to eq([milestone])
end
it 'returns milestones with a partially matching title' do
@@ -272,7 +272,7 @@ RSpec.describe Milestone do
it 'searches only on the title and ignores milestones with a matching description' do
create(:milestone, title: 'bar', description: 'foo')
- expect(described_class.search_title(milestone.title)) .to eq([milestone])
+ expect(described_class.search_title(milestone.title)).to eq([milestone])
end
end
diff --git a/spec/models/ml/candidate_metric_spec.rb b/spec/models/ml/candidate_metric_spec.rb
new file mode 100644
index 00000000000..5ee6030fb8e
--- /dev/null
+++ b/spec/models/ml/candidate_metric_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ml::CandidateMetric do
+ describe 'associations' do
+ it { is_expected.to belong_to(:candidate) }
+ end
+end
diff --git a/spec/models/ml/candidate_param_spec.rb b/spec/models/ml/candidate_param_spec.rb
new file mode 100644
index 00000000000..ff38e471219
--- /dev/null
+++ b/spec/models/ml/candidate_param_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ml::CandidateParam do
+ describe 'associations' do
+ it { is_expected.to belong_to(:candidate) }
+ end
+end
diff --git a/spec/models/ml/candidate_spec.rb b/spec/models/ml/candidate_spec.rb
new file mode 100644
index 00000000000..a48e291fa55
--- /dev/null
+++ b/spec/models/ml/candidate_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ml::Candidate do
+ describe 'associations' do
+ it { is_expected.to belong_to(:experiment) }
+ it { is_expected.to belong_to(:user) }
+ it { is_expected.to have_many(:params) }
+ it { is_expected.to have_many(:metrics) }
+ end
+end
diff --git a/spec/models/ml/experiment_spec.rb b/spec/models/ml/experiment_spec.rb
new file mode 100644
index 00000000000..dca5280a8fe
--- /dev/null
+++ b/spec/models/ml/experiment_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ml::Experiment do
+ 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
+end
diff --git a/spec/models/namespace/detail_spec.rb b/spec/models/namespace/detail_spec.rb
new file mode 100644
index 00000000000..1bb756c441b
--- /dev/null
+++ b/spec/models/namespace/detail_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespace::Detail, type: :model do
+ describe 'associations' do
+ it { is_expected.to belong_to :namespace }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:namespace) }
+ end
+
+ context 'when namespace description changes' do
+ let(:namespace) { create(:namespace, description: "old") }
+
+ it 'changes namespace details description' do
+ expect { namespace.update!(description: "new") }
+ .to change { namespace.namespace_details.description }.from("old").to("new")
+ end
+ end
+
+ context 'when project description changes' do
+ let(:project) { create(:project, description: "old") }
+
+ it 'changes project namespace details description' do
+ expect { project.update!(description: "new") }
+ .to change { project.project_namespace.namespace_details.description }.from("old").to("new")
+ end
+ end
+
+ context 'when group description changes' do
+ let(:group) { create(:group, description: "old") }
+
+ it 'changes group namespace details description' do
+ expect { group.update!(description: "new") }
+ .to change { group.namespace_details.description }.from("old").to("new")
+ end
+ end
+end
diff --git a/spec/models/namespace/root_storage_statistics_spec.rb b/spec/models/namespace/root_storage_statistics_spec.rb
index d2ee0b40ed6..14ac08b545a 100644
--- a/spec/models/namespace/root_storage_statistics_spec.rb
+++ b/spec/models/namespace/root_storage_statistics_spec.rb
@@ -100,8 +100,8 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
it_behaves_like 'does not include personal snippets'
context 'with subgroups' do
- let(:subgroup1) { create(:group, parent: namespace)}
- let(:subgroup2) { create(:group, parent: subgroup1)}
+ let(:subgroup1) { create(:group, parent: namespace) }
+ let(:subgroup2) { create(:group, parent: subgroup1) }
let(:project1) { create(:project, namespace: subgroup1) }
let(:project2) { create(:project, namespace: subgroup2) }
diff --git a/spec/models/namespace/traversal_hierarchy_spec.rb b/spec/models/namespace/traversal_hierarchy_spec.rb
index 51932ab943c..918ff6aa154 100644
--- a/spec/models/namespace/traversal_hierarchy_spec.rb
+++ b/spec/models/namespace/traversal_hierarchy_spec.rb
@@ -85,7 +85,11 @@ RSpec.describe Namespace::TraversalHierarchy, type: :model do
it { expect { subject }.to raise_error(ActiveRecord::Deadlocked) }
it 'increment db_deadlock counter' do
- expect { subject rescue nil }.to change { db_deadlock_total('Namespace#sync_traversal_ids!') }.by(1)
+ expect do
+ subject
+ rescue StandardError
+ nil
+ end.to change { db_deadlock_total('Namespace#sync_traversal_ids!') }.by(1)
end
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 664cdb27290..71ce3afda44 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe Namespace do
include ProjectForksHelper
- include GitHelpers
include ReloadHelpers
let_it_be(:group_sti_name) { Group.sti_name }
@@ -23,6 +22,7 @@ RSpec.describe Namespace do
it { is_expected.to have_one :root_storage_statistics }
it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_one :namespace_settings }
+ it { is_expected.to have_one :namespace_details }
it { is_expected.to have_one(:namespace_statistics) }
it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation }
@@ -31,6 +31,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :pending_builds }
it { is_expected.to have_one :namespace_route }
it { is_expected.to have_many :namespace_members }
+ it { is_expected.to have_many :member_roles }
it { is_expected.to have_one :cluster_enabled_grant }
it { is_expected.to have_many(:work_items) }
@@ -373,14 +374,6 @@ RSpec.describe Namespace do
context 'linear' do
it_behaves_like 'namespace traversal scopes'
-
- context 'without inner join ancestors query' do
- before do
- stub_feature_flags(use_traversal_ids_for_ancestor_scopes_with_inner_join: false)
- end
-
- it_behaves_like 'namespace traversal scopes'
- end
end
shared_examples 'makes recursive queries' do
@@ -1075,9 +1068,9 @@ RSpec.describe Namespace do
it 'updates project full path in .git/config' do
parent.update!(path: 'mygroup_new')
- expect(project_rugged(project_in_parent_group).config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
- expect(project_rugged(hashed_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
- expect(project_rugged(legacy_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
+ expect(project_in_parent_group.reload.repository.full_path).to eq "mygroup_new/#{project_in_parent_group.path}"
+ expect(hashed_project_in_subgroup.reload.repository.full_path).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
+ expect(legacy_project_in_subgroup.reload.repository.full_path).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
end
it 'updates the project storage location' do
@@ -1091,14 +1084,6 @@ RSpec.describe Namespace do
expect(repository_hashed_project_in_subgroup.reload.disk_path).to eq hashed_project_in_subgroup.disk_path
expect(repository_legacy_project_in_subgroup.reload.disk_path).to eq "mygroup_moved/mysubgroup/#{legacy_project_in_subgroup.path}"
end
-
- def project_rugged(project)
- # Routes are loaded when creating the projects, so we need to manually
- # reload them for the below code to be aware of the above UPDATE.
- project.route.reload
-
- rugged_repo(project.repository)
- end
end
end
@@ -1556,7 +1541,7 @@ RSpec.describe Namespace do
describe '#share_with_group_lock with subgroups' do
context 'when creating a subgroup' do
- let(:subgroup) { create(:group, parent: root_group )}
+ let(:subgroup) { create(:group, parent: root_group ) }
context 'under a parent with "Share with group lock" enabled' do
let(:root_group) { create(:group, share_with_group_lock: true) }
@@ -1577,7 +1562,7 @@ RSpec.describe Namespace do
context 'when enabling the parent group "Share with group lock"' do
let(:root_group) { create(:group) }
- let!(:subgroup) { create(:group, parent: root_group )}
+ let!(:subgroup) { create(:group, parent: root_group ) }
it 'the subgroup "Share with group lock" becomes enabled' do
root_group.update!(share_with_group_lock: true)
@@ -1590,7 +1575,7 @@ RSpec.describe Namespace do
let(:root_group) { create(:group, share_with_group_lock: true) }
context 'and the subgroup "Share with group lock" is enabled' do
- let(:subgroup) { create(:group, parent: root_group, share_with_group_lock: true )}
+ let(:subgroup) { create(:group, parent: root_group, share_with_group_lock: true ) }
it 'the subgroup "Share with group lock" does not change' do
root_group.update!(share_with_group_lock: false)
@@ -1600,7 +1585,7 @@ RSpec.describe Namespace do
end
context 'but the subgroup "Share with group lock" is disabled' do
- let(:subgroup) { create(:group, parent: root_group )}
+ let(:subgroup) { create(:group, parent: root_group ) }
it 'the subgroup "Share with group lock" does not change' do
root_group.update!(share_with_group_lock: false)
@@ -1615,7 +1600,7 @@ RSpec.describe Namespace do
let(:root_group) { create(:group, share_with_group_lock: true) }
context 'when the subgroup "Share with group lock" is enabled' do
- let(:subgroup) { create(:group, share_with_group_lock: true )}
+ let(:subgroup) { create(:group, share_with_group_lock: true ) }
it 'the subgroup "Share with group lock" does not change' do
subgroup.parent = root_group
@@ -1626,7 +1611,7 @@ RSpec.describe Namespace do
end
context 'when the subgroup "Share with group lock" is disabled' do
- let(:subgroup) { create(:group)}
+ let(:subgroup) { create(:group) }
it 'the subgroup "Share with group lock" becomes enabled' do
subgroup.parent = root_group
@@ -1641,7 +1626,7 @@ RSpec.describe Namespace do
let(:root_group) { create(:group) }
context 'when the subgroup "Share with group lock" is enabled' do
- let(:subgroup) { create(:group, share_with_group_lock: true )}
+ let(:subgroup) { create(:group, share_with_group_lock: true ) }
it 'the subgroup "Share with group lock" does not change' do
subgroup.parent = root_group
@@ -1652,7 +1637,7 @@ RSpec.describe Namespace do
end
context 'when the subgroup "Share with group lock" is disabled' do
- let(:subgroup) { create(:group)}
+ let(:subgroup) { create(:group) }
it 'the subgroup "Share with group lock" does not change' do
subgroup.parent = root_group
@@ -2027,7 +2012,7 @@ RSpec.describe Namespace do
end
with_them do
- let(:namespace) { build(:namespace, shared_runners_enabled: shared_runners_enabled, allow_descendants_override_disabled_shared_runners: allow_descendants_override_disabled_shared_runners)}
+ let(:namespace) { build(:namespace, shared_runners_enabled: shared_runners_enabled, allow_descendants_override_disabled_shared_runners: allow_descendants_override_disabled_shared_runners) }
it 'returns the result' do
expect(namespace.shared_runners_setting).to eq(shared_runners_setting)
@@ -2051,7 +2036,7 @@ RSpec.describe Namespace do
end
with_them do
- let(:namespace) { build(:namespace, shared_runners_enabled: shared_runners_enabled, allow_descendants_override_disabled_shared_runners: allow_descendants_override_disabled_shared_runners)}
+ let(:namespace) { build(:namespace, shared_runners_enabled: shared_runners_enabled, allow_descendants_override_disabled_shared_runners: allow_descendants_override_disabled_shared_runners) }
it 'returns the result' do
expect(namespace.shared_runners_setting_higher_than?(other_setting)).to eq(result)
@@ -2282,9 +2267,8 @@ RSpec.describe Namespace do
stub_feature_flags(namespace_storage_limit_bypass_date_check: false)
end
- # Date TBD: https://gitlab.com/gitlab-org/gitlab/-/issues/350632
- it 'returns nil' do
- expect(namespace.storage_enforcement_date).to be(nil)
+ it 'returns correct date' do
+ expect(namespace.storage_enforcement_date).to eql(Date.new(2022, 10, 19))
end
context 'when :storage_banner_bypass_date_check is enabled' do
diff --git a/spec/models/namespaces/project_namespace_spec.rb b/spec/models/namespaces/project_namespace_spec.rb
index c995571c3c9..78403db7fa8 100644
--- a/spec/models/namespaces/project_namespace_spec.rb
+++ b/spec/models/namespaces/project_namespace_spec.rb
@@ -5,6 +5,14 @@ require 'spec_helper'
RSpec.describe Namespaces::ProjectNamespace, type: :model do
describe 'relationships' do
it { is_expected.to have_one(:project).with_foreign_key(:project_namespace_id).inverse_of(:project_namespace) }
+
+ specify do
+ project = create(:project)
+ namespace = project.project_namespace
+ namespace.reload_project
+
+ expect(namespace.project).to eq project
+ end
end
describe 'validations' do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index fc6f7832c2c..ca558848cb0 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -823,14 +823,14 @@ RSpec.describe Note do
end
context 'with :label action' do
- let!(:metadata) {create(:system_note_metadata, note: note, action: :label)}
+ let!(:metadata) { create(:system_note_metadata, note: note, action: :label) }
it_behaves_like 'system_note_metadata includes note action'
it { expect(note.system_note_with_references?).to be_falsy }
context 'with cross reference label note' do
- let(:label) { create(:label, project: issue.project)}
+ let(:label) { create(:label, project: issue.project) }
let(:note) { create(:system_note, note: "added #{label.to_reference} label", noteable: issue, project: issue.project) }
it { expect(note.system_note_with_references?).to be_truthy }
@@ -838,14 +838,14 @@ RSpec.describe Note do
end
context 'with :milestone action' do
- let!(:metadata) {create(:system_note_metadata, note: note, action: :milestone)}
+ let!(:metadata) { create(:system_note_metadata, note: note, action: :milestone) }
it_behaves_like 'system_note_metadata includes note action'
it { expect(note.system_note_with_references?).to be_falsy }
context 'with cross reference milestone note' do
- let(:milestone) { create(:milestone, project: issue.project)}
+ let(:milestone) { create(:milestone, project: issue.project) }
let(:note) { create(:system_note, note: "added #{milestone.to_reference} milestone", noteable: issue, project: issue.project) }
it { expect(note.system_note_with_references?).to be_truthy }
@@ -1130,7 +1130,7 @@ RSpec.describe Note do
end
describe '#cache_markdown_field' do
- let(:html) { '<p>some html</p>'}
+ let(:html) { '<p>some html</p>' }
before do
allow(Banzai::Renderer).to receive(:cacheless_render_field).and_call_original
@@ -1792,4 +1792,68 @@ RSpec.describe Note do
end
end
end
+
+ shared_examples 'note that replaces task for checklist item in body text' do
+ subject { note.public_send(field_name) }
+
+ context 'when note is not a system note' do
+ let(:note) { create(:note, note: original_note_body) }
+
+ it { is_expected.to eq(unchanged_note_body) }
+ end
+
+ context 'when note is a system note' do
+ context 'when note noteable_type is not Issue' do
+ let(:note) { create(:note, :system, :on_merge_request, note: original_note_body) }
+
+ it { is_expected.to eq(unchanged_note_body) }
+ end
+
+ context 'when note noteable_type is Issue' do
+ let(:note) { create(:note, :system, :on_issue, note: original_note_body) }
+
+ it { is_expected.to eq(expected_text_replacement) }
+ end
+ end
+ end
+
+ describe '#note' do
+ let(:field_name) { :note }
+
+ it_behaves_like 'note that replaces task for checklist item in body text' do
+ let(:original_note_body) { 'marked the task **task 1** as completed' }
+ let(:unchanged_note_body) { original_note_body }
+ let(:expected_text_replacement) { 'marked the checklist item **task 1** as completed' }
+ end
+
+ it_behaves_like 'note that replaces task for checklist item in body text' do
+ let(:original_note_body) { 'marked the task **task 1** as incomplete' }
+ let(:unchanged_note_body) { original_note_body }
+ let(:expected_text_replacement) { 'marked the checklist item **task 1** as incomplete' }
+ end
+ end
+
+ describe '#note_html' do
+ let(:field_name) { :note_html }
+
+ it_behaves_like 'note that replaces task for checklist item in body text' do
+ let(:original_note_body) { 'marked the task **task 1** as completed' }
+ let(:unchanged_note_body) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the task <strong>task 1</strong> as completed</p>' }
+ 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)
+ end
+ end
+
+ it_behaves_like 'note that replaces task for checklist item in body text' do
+ let(:original_note_body) { 'marked the task **task 1** as incomplete' }
+ let(:unchanged_note_body) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the task <strong>task 1</strong> as incomplete</p>' }
+ 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)
+ end
+ end
+ end
end
diff --git a/spec/models/oauth_access_token_spec.rb b/spec/models/oauth_access_token_spec.rb
index 2b47da1ebe1..544f6643712 100644
--- a/spec/models/oauth_access_token_spec.rb
+++ b/spec/models/oauth_access_token_spec.rb
@@ -10,27 +10,6 @@ RSpec.describe OauthAccessToken do
let(:token) { create(:oauth_access_token, application_id: app_one.id) }
describe 'scopes' do
- describe '.distinct_resource_owner_counts' do
- let(:tokens) { described_class.all }
-
- before do
- token
- create_list(:oauth_access_token, 2, resource_owner: user, application_id: app_two.id)
- end
-
- it 'returns unique owners' do
- expect(tokens.count).to eq(3)
- expect(tokens.distinct_resource_owner_counts([app_one])).to eq({ app_one.id => 1 })
- expect(tokens.distinct_resource_owner_counts([app_two])).to eq({ app_two.id => 1 })
- expect(tokens.distinct_resource_owner_counts([app_three])).to eq({})
- expect(tokens.distinct_resource_owner_counts([app_one, app_two]))
- .to eq({
- app_one.id => 1,
- app_two.id => 1
- })
- end
- end
-
describe '.latest_per_application' do
let!(:app_two_token1) { create(:oauth_access_token, application: app_two) }
let!(:app_two_token2) { create(:oauth_access_token, application: app_two) }
@@ -43,4 +22,51 @@ RSpec.describe OauthAccessToken do
end
end
end
+
+ describe 'Doorkeeper secret storing' do
+ it 'stores the token in hashed format' do
+ expect(token.token).not_to eq(token.plaintext_token)
+ end
+
+ it 'does not allow falling back to plaintext token comparison' do
+ expect(described_class.by_token(token.token)).to be_nil
+ end
+
+ it 'finds a token by plaintext token' do
+ expect(described_class.by_token(token.plaintext_token)).to be_a(OauthAccessToken)
+ end
+
+ context 'when the token is stored in plaintext' do
+ let(:plaintext_token) { Devise.friendly_token(20) }
+
+ before do
+ token.update_column(:token, plaintext_token)
+ end
+
+ it 'falls back to plaintext token comparison' do
+ expect(described_class.by_token(plaintext_token)).to be_a(OauthAccessToken)
+ end
+ end
+
+ context 'when hash_oauth_secrets is disabled' do
+ let(:hashed_token) { create(:oauth_access_token, application_id: app_one.id) }
+
+ before do
+ hashed_token
+ stub_feature_flags(hash_oauth_tokens: false)
+ end
+
+ it 'stores the token in plaintext' do
+ expect(token.token).to eq(token.plaintext_token)
+ end
+
+ it 'finds a token by plaintext token' do
+ expect(described_class.by_token(token.plaintext_token)).to be_a(OauthAccessToken)
+ end
+
+ it 'does not find a token that was previously stored as hashed' do
+ expect(described_class.by_token(hashed_token.plaintext_token)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb
index 80a39404d10..9688dd01c71 100644
--- a/spec/models/onboarding_progress_spec.rb
+++ b/spec/models/onboarding_progress_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe OnboardingProgress do
describe 'validations' do
describe 'namespace_is_root_namespace' do
- subject(:onboarding_progress) { build(:onboarding_progress, namespace: namespace)}
+ subject(:onboarding_progress) { build(:onboarding_progress, namespace: namespace) }
context 'when associated namespace is root' do
it { is_expected.to be_valid }
diff --git a/spec/models/packages/cleanup/policy_spec.rb b/spec/models/packages/cleanup/policy_spec.rb
index a37042520e7..0b6dff472c1 100644
--- a/spec/models/packages/cleanup/policy_spec.rb
+++ b/spec/models/packages/cleanup/policy_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Packages::Cleanup::Policy, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
+
it do
is_expected
.to validate_inclusion_of(:keep_n_duplicated_package_files)
diff --git a/spec/models/packages/conan/metadatum_spec.rb b/spec/models/packages/conan/metadatum_spec.rb
index d00723e8e43..92c8b126639 100644
--- a/spec/models/packages/conan/metadatum_spec.rb
+++ b/spec/models/packages/conan/metadatum_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Packages::Conan::Metadatum, type: :model do
end
describe 'validations' do
- let(:fifty_one_characters) { 'f_a' * 17}
+ let(:fifty_one_characters) { 'f_a' * 17 }
it { is_expected.to validate_presence_of(:package) }
it { is_expected.to validate_presence_of(:package_username) }
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index 82f5b44f38f..9554fc3bb1b 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -126,7 +126,7 @@ RSpec.describe Packages::PackageFile, type: :model do
describe '.with_conan_package_reference' do
let_it_be(:non_matching_package_file) { create(:package_file, :nuget) }
let_it_be(:metadatum) { create(:conan_file_metadatum, :package_file) }
- let_it_be(:reference) { metadatum.conan_package_reference}
+ let_it_be(:reference) { metadatum.conan_package_reference }
it 'returns matching packages' do
expect(described_class.with_conan_package_reference(reference))
@@ -150,8 +150,8 @@ RSpec.describe Packages::PackageFile, type: :model do
context 'Debian scopes' do
let_it_be(:debian_changes) { debian_package.package_files.last }
- let_it_be(:debian_deb) { create(:debian_package_file, package: debian_package)}
- let_it_be(:debian_udeb) { create(:debian_package_file, :udeb, package: debian_package)}
+ let_it_be(:debian_deb) { create(:debian_package_file, package: debian_package) }
+ let_it_be(:debian_udeb) { create(:debian_package_file, :udeb, package: debian_package) }
let_it_be(:debian_contrib) do
create(:debian_package_file, package: debian_package).tap do |pf|
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 06f02f021cf..526c57d08b0 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -131,7 +131,7 @@ RSpec.describe Packages::Package, type: :model do
context 'conan package' do
subject { build_stubbed(:conan_package) }
- let(:fifty_one_characters) {'f_b' * 17}
+ let(:fifty_one_characters) { 'f_b' * 17 }
it { is_expected.to allow_value('foo+bar').for(:name) }
it { is_expected.to allow_value('foo_bar').for(:name) }
@@ -243,7 +243,7 @@ RSpec.describe Packages::Package, type: :model do
context 'conan package' do
subject { build_stubbed(:conan_package) }
- let(:fifty_one_characters) {'1.2' * 17}
+ let(:fifty_one_characters) { '1.2' * 17 }
it { is_expected.to allow_value('1.2').for(:version) }
it { is_expected.to allow_value('1.2.3-beta').for(:version) }
@@ -441,7 +441,7 @@ RSpec.describe Packages::Package, type: :model do
context 'npm package' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
- let_it_be(:second_project) { create(:project, namespace: group)}
+ let_it_be(:second_project) { create(:project, namespace: group) }
let(:package) { build(:npm_package, project: project, name: name) }
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 69866d497a1..f3ef347121e 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -193,6 +193,20 @@ RSpec.describe PersonalAccessToken do
end
describe 'scopes' do
+ describe '.active' do
+ let_it_be(:revoked_token) { create(:personal_access_token, :revoked) }
+ let_it_be(:not_revoked_false_token) { create(:personal_access_token, revoked: false) }
+ let_it_be(:not_revoked_nil_token) { create(:personal_access_token, revoked: nil) }
+ let_it_be(:expired_token) { create(:personal_access_token, :expired) }
+ let_it_be(:not_expired_token) { create(:personal_access_token) }
+ let_it_be(:never_expires_token) { create(:personal_access_token, expires_at: nil) }
+
+ it 'includes non-revoked and non-expired tokens' do
+ expect(described_class.active)
+ .to match_array([not_revoked_false_token, not_revoked_nil_token, not_expired_token, never_expires_token])
+ end
+ end
+
describe '.expiring_and_not_notified' do
let_it_be(:expired_token) { create(:personal_access_token, expires_at: 2.days.ago) }
let_it_be(:revoked_token) { create(:personal_access_token, revoked: true) }
@@ -251,7 +265,7 @@ RSpec.describe PersonalAccessToken do
describe '.simple_sorts' do
it 'includes overridden keys' do
- expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc expires_at_desc))
+ expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc expires_at_desc expires_at_asc_id_desc))
end
end
@@ -270,5 +284,13 @@ RSpec.describe PersonalAccessToken do
expect(described_class.order_expires_at_desc).to match [later_token, earlier_token]
end
end
+
+ describe '.order_expires_at_asc_id_desc' do
+ let_it_be(:earlier_token_2) { create(:personal_access_token, expires_at: 2.days.ago) }
+
+ it 'returns ordered list in combination of expires_at ascending and id descending' do
+ expect(described_class.order_expires_at_asc_id_desc).to eq [earlier_token_2, earlier_token, later_token]
+ end
+ end
end
end
diff --git a/spec/models/postgresql/replication_slot_spec.rb b/spec/models/postgresql/replication_slot_spec.rb
index 63a19541ab5..35c166ab064 100644
--- a/spec/models/postgresql/replication_slot_spec.rb
+++ b/spec/models/postgresql/replication_slot_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe Postgresql::ReplicationSlot do
describe '#slots_retained_bytes' do
it 'returns the number of retained bytes' do
- slot = described_class.slots_retained_bytes.find {|x| x['slot_name'] == 'test_slot' }
+ slot = described_class.slots_retained_bytes.find { |x| x['slot_name'] == 'test_slot' }
expect(slot).not_to be_nil
expect(slot['retained_bytes']).to be_nil
diff --git a/spec/models/preloaders/labels_preloader_spec.rb b/spec/models/preloaders/labels_preloader_spec.rb
index 94de00bb94c..86e64d114c7 100644
--- a/spec/models/preloaders/labels_preloader_spec.rb
+++ b/spec/models/preloaders/labels_preloader_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Preloaders::LabelsPreloader do
let_it_be(:user) { create(:user) }
shared_examples 'an efficient database query' do
- let(:subscriptions) { labels.each { |l| create(:subscription, subscribable: l, project: l.project, user: user) }}
+ let(:subscriptions) { labels.each { |l| create(:subscription, subscribable: l, project: l.project, user: user) } }
it 'does not make n+1 queries' do
first_label = labels_with_preloaded_data.first
diff --git a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
index 2060e6cd44a..5e2aaa8b456 100644
--- a/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
+++ b/spec/models/preloaders/user_max_access_level_in_groups_preloader_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Preloaders::UserMaxAccessLevelInGroupsPreloader do
context 'when the preloader is used', :request_store do
context 'when user has indirect access to groups' do
- let_it_be(:child_maintainer) { create(:group, :private, parent: group1).tap {|g| g.add_maintainer(user)} }
+ let_it_be(:child_maintainer) { create(:group, :private, parent: group1).tap { |g| g.add_maintainer(user) } }
let_it_be(:child_indirect_access) { create(:group, :private, parent: group1) }
let(:groups) { [group1, group2, group3, child_maintainer, child_indirect_access] }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index f46a1646554..98b202299a8 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe Project, factory_default: :keep do
include ProjectForksHelper
- include GitHelpers
include ExternalAuthorizationServiceHelpers
include ReloadHelpers
include StubGitlabCalls
@@ -45,6 +44,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_one(:mattermost_integration) }
it { is_expected.to have_one(:hangouts_chat_integration) }
it { is_expected.to have_one(:unify_circuit_integration) }
+ it { is_expected.to have_one(:pumble_integration) }
it { is_expected.to have_one(:webex_teams_integration) }
it { is_expected.to have_one(:packagist_integration) }
it { is_expected.to have_one(:pushover_integration) }
@@ -148,6 +148,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_many(:build_trace_chunks).through(:builds).dependent(:restrict_with_error) }
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) }
# GitLab Pages
it { is_expected.to have_many(:pages_domains) }
@@ -832,6 +833,9 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to delegate_method(:last_pipeline).to(:commit).allow_nil }
it { is_expected.to delegate_method(:container_registry_enabled?).to(:project_feature) }
it { is_expected.to delegate_method(:container_registry_access_level).to(:project_feature) }
+ 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) }
describe 'read project settings' do
%i(
@@ -873,6 +877,12 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#ci_allow_fork_pipelines_to_run_in_parent_project?' do
+ it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
+ let(:delegated_method) { :allow_fork_pipelines_to_run_in_parent_project? }
+ end
+ end
+
describe '#ci_job_token_scope_enabled?' do
it_behaves_like 'a ci_cd_settings predicate method', prefix: 'ci_' do
let(:delegated_method) { :job_token_scope_enabled? }
@@ -5741,16 +5751,18 @@ RSpec.describe Project, factory_default: :keep do
describe '#set_full_path' do
let_it_be(:project) { create(:project, :repository) }
+ let(:repository) { project.repository.raw }
+
it 'writes full path in .git/config when key is missing' do
project.set_full_path
- expect(rugged_config['gitlab.fullpath']).to eq project.full_path
+ expect(repository.full_path).to eq project.full_path
end
it 'updates full path in .git/config when key is present' do
project.set_full_path(gl_full_path: 'old/path')
- expect { project.set_full_path }.to change { rugged_config['gitlab.fullpath'] }.from('old/path').to(project.full_path)
+ expect { project.set_full_path }.to change { repository.full_path }.from('old/path').to(project.full_path)
end
it 'does not raise an error with an empty repository' do
@@ -5880,7 +5892,7 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#has_active_hooks?' do
- let_it_be(:project) { create(:project) }
+ let_it_be_with_refind(:project) { create(:project) }
it { expect(project.has_active_hooks?).to be_falsey }
@@ -7471,7 +7483,7 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it { is_expected.to eq expected_result}
+ it { is_expected.to eq expected_result }
end
end
@@ -7488,7 +7500,7 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it { is_expected.to eq expected_result}
+ it { is_expected.to eq expected_result }
end
context 'for a different package type' do
@@ -7511,7 +7523,7 @@ RSpec.describe Project, factory_default: :keep do
end
with_them do
- it { is_expected.to eq expected_result}
+ it { is_expected.to eq expected_result }
end
end
end
@@ -8240,58 +8252,52 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#work_items_feature_flag_enabled?' do
- shared_examples 'project checking work_items feature flag' do
- context 'when work_items FF is disabled globally' do
- before do
- stub_feature_flags(work_items: false)
- end
+ let_it_be(:group_project) { create(:project, :in_subgroup) }
- it { is_expected.to be_falsey }
+ it_behaves_like 'checks parent group feature flag' do
+ let(:feature_flag_method) { :work_items_feature_flag_enabled? }
+ let(:feature_flag) { :work_items }
+ let(:subject_project) { group_project }
+ end
+
+ context 'when feature flag is enabled for the project' do
+ subject { subject_project.work_items_feature_flag_enabled? }
+
+ before do
+ stub_feature_flags(work_items: subject_project)
end
- context 'when work_items FF is enabled for the project' do
- before do
- stub_feature_flags(work_items: project)
- end
+ context 'when project belongs to a group' do
+ let(:subject_project) { group_project }
it { is_expected.to be_truthy }
end
- context 'when work_items FF is enabled globally' do
+ context 'when project does not belong to a group' do
+ let(:subject_project) { create(:project, namespace: create(:namespace)) }
+
it { is_expected.to be_truthy }
end
end
+ end
- subject { project.work_items_feature_flag_enabled? }
-
- context 'when a project does not belong to a group' do
- let_it_be(:project) { create(:project, namespace: namespace) }
+ describe '#work_items_mvc_2_feature_flag_enabled?' do
+ let_it_be(:group_project) { create(:project, :in_subgroup) }
- it_behaves_like 'project checking work_items feature flag'
+ it_behaves_like 'checks parent group feature flag' do
+ let(:feature_flag_method) { :work_items_mvc_2_feature_flag_enabled? }
+ let(:feature_flag) { :work_items_mvc_2 }
+ let(:subject_project) { group_project }
end
+ end
- context 'when project belongs to a group' do
- let_it_be(:root_group) { create(:group) }
- let_it_be(:group) { create(:group, parent: root_group) }
- let_it_be(:project) { create(:project, group: group) }
-
- it_behaves_like 'project checking work_items feature flag'
-
- context 'when work_items FF is enabled for the root group' do
- before do
- stub_feature_flags(work_items: root_group)
- end
-
- it { is_expected.to be_truthy }
- end
+ describe '#work_items_create_from_markdown_feature_flag_enabled?' do
+ let_it_be(:group_project) { create(:project, :in_subgroup) }
- context 'when work_items FF is enabled for the group' do
- before do
- stub_feature_flags(work_items: group)
- end
-
- it { is_expected.to be_truthy }
- end
+ it_behaves_like 'checks parent group feature flag' do
+ let(:feature_flag_method) { :work_items_create_from_markdown_feature_flag_enabled? }
+ let(:feature_flag) { :work_items_create_from_markdown }
+ let(:subject_project) { group_project }
end
end
@@ -8428,6 +8434,23 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#destroy_deployment_by_id' do
+ let(:project) { create(:project, :repository) }
+
+ let!(:deployment) { create(:deployment, :created, project: project) }
+ let!(:old_deployment) { create(:deployment, :created, project: project, finished_at: 1.year.ago) }
+
+ it 'will call fast_destroy_all on a specific deployment by id' do
+ expect(Deployment).to receive(:fast_destroy_all).and_call_original
+
+ expect do
+ project.destroy_deployment_by_id(project.deployments.first.id)
+ end.to change { project.deployments.count }.by(-1)
+
+ expect(project.deployments).to match_array([old_deployment])
+ end
+ end
+
private
def finish_job(export_job)
@@ -8435,10 +8458,6 @@ RSpec.describe Project, factory_default: :keep do
export_job.finish
end
- def rugged_config
- rugged_repo(project.repository).config
- end
-
def create_pipeline(project, status = 'success')
create(:ci_pipeline, project: project,
sha: project.commit.sha,
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index 53175a2f840..f4edc68457b 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -26,31 +26,20 @@ RSpec.describe ProjectStatistics do
end
describe 'statistics columns' do
- it "support values up to 8 exabytes" do
- statistics.update!(
- commit_count: 8.exabytes - 1,
- repository_size: 2.exabytes,
- wiki_size: 1.exabytes,
- lfs_objects_size: 2.exabytes,
- build_artifacts_size: 1.exabyte,
- snippets_size: 1.exabyte,
- pipeline_artifacts_size: 512.petabytes - 1,
- uploads_size: 512.petabytes,
- container_registry_size: 12.petabytes
- )
-
- statistics.reload
-
- expect(statistics.commit_count).to eq(8.exabytes - 1)
- expect(statistics.repository_size).to eq(2.exabytes)
- expect(statistics.wiki_size).to eq(1.exabytes)
- expect(statistics.lfs_objects_size).to eq(2.exabytes)
- expect(statistics.build_artifacts_size).to eq(1.exabyte)
- expect(statistics.storage_size).to eq(8.exabytes - 1)
- expect(statistics.snippets_size).to eq(1.exabyte)
- expect(statistics.pipeline_artifacts_size).to eq(512.petabytes - 1)
- expect(statistics.uploads_size).to eq(512.petabytes)
- expect(statistics.container_registry_size).to eq(12.petabytes)
+ it "supports bigint values" do
+ expect do
+ statistics.update!(
+ commit_count: 3.gigabytes,
+ repository_size: 3.gigabytes,
+ wiki_size: 3.gigabytes,
+ lfs_objects_size: 3.gigabytes,
+ build_artifacts_size: 3.gigabytes,
+ snippets_size: 3.gigabytes,
+ pipeline_artifacts_size: 3.gigabytes,
+ uploads_size: 3.gigabytes,
+ container_registry_size: 3.gigabytes
+ )
+ end.not_to raise_error
end
end
diff --git a/spec/models/projects/import_export/relation_export_spec.rb b/spec/models/projects/import_export/relation_export_spec.rb
index c74ca82e161..8643fbc7b46 100644
--- a/spec/models/projects/import_export/relation_export_spec.rb
+++ b/spec/models/projects/import_export/relation_export_spec.rb
@@ -20,4 +20,36 @@ RSpec.describe Projects::ImportExport::RelationExport, type: :model do
it { is_expected.to validate_length_of(:jid).is_at_most(255) }
it { is_expected.to validate_length_of(:export_error).is_at_most(300) }
end
+
+ describe '.by_relation' do
+ it 'returns export relations filtered by relation name' do
+ project_relation_export_1 = create(:project_relation_export, relation: 'labels')
+ project_relation_export_2 = create(:project_relation_export, relation: 'labels')
+ create(:project_relation_export, relation: 'uploads')
+
+ relations = described_class.by_relation('labels').to_a
+
+ expect(relations).to match_array([project_relation_export_1, project_relation_export_2])
+ end
+ end
+
+ describe '.relation_names_list' do
+ it 'includes extra relations list' do
+ expect(described_class.relation_names_list).to include(
+ 'design_repository', 'lfs_objects', 'repository', 'snippets_repository', 'uploads', 'wiki_repository'
+ )
+ end
+
+ it 'includes root tree relation name project' do
+ expect(described_class.relation_names_list).to include('project')
+ end
+
+ it 'includes project tree top level relation nodes' do
+ expect(described_class.relation_names_list).to include('milestones', 'issues', 'snippets', 'releases')
+ end
+
+ it 'includes project tree nested relation nodes' do
+ expect(described_class.relation_names_list).not_to include('events', 'notes')
+ end
+ end
end
diff --git a/spec/models/projects/topic_spec.rb b/spec/models/projects/topic_spec.rb
index fc9d9bef437..f9659ef352c 100644
--- a/spec/models/projects/topic_spec.rb
+++ b/spec/models/projects/topic_spec.rb
@@ -30,6 +30,17 @@ RSpec.describe Projects::Topic do
end
describe 'scopes' do
+ describe 'without_assigned_projects' do
+ let_it_be(:unassigned_topic) { create(:topic, name: 'unassigned topic') }
+ let_it_be(:project) { create(:project, :public, topic_list: 'topic') }
+
+ it 'returns topics without assigned projects' do
+ topics = described_class.without_assigned_projects
+
+ expect(topics).to contain_exactly(unassigned_topic)
+ end
+ end
+
describe 'order_by_non_private_projects_count' do
let!(:topic1) { create(:topic, name: 'topicB') }
let!(:topic2) { create(:topic, name: 'topicC') }
diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb
index a3fc09b31fb..3936e7127b8 100644
--- a/spec/models/protected_branch_spec.rb
+++ b/spec/models/protected_branch_spec.rb
@@ -167,36 +167,130 @@ RSpec.describe ProtectedBranch do
expect(described_class.protected?(project, nil)).to eq(false)
end
- context 'with caching', :use_clean_rails_memory_store_caching do
+ context 'with caching', :use_clean_rails_redis_caching do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:protected_branch) { create(:protected_branch, project: project, name: "“jawnâ€") }
+ let(:feature_flag) { true }
+ let(:dry_run) { true }
+
+ shared_examples_for 'hash based cache implementation' do
+ it 'calls only hash based cache implementation' do
+ expect_next_instance_of(ProtectedBranches::CacheService) do |instance|
+ expect(instance).to receive(:fetch).with('missing-branch', anything).and_call_original
+ end
+
+ expect(Rails.cache).not_to receive(:fetch)
+
+ described_class.protected?(project, 'missing-branch', dry_run: dry_run)
+ end
+ end
+
before do
- allow(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).once.and_call_original
+ stub_feature_flags(hash_based_cache_for_protected_branches: feature_flag)
+ allow(described_class).to receive(:matching).and_call_original
# the original call works and warms the cache
- described_class.protected?(project, protected_branch.name)
+ described_class.protected?(project, protected_branch.name, dry_run: dry_run)
end
- it 'correctly invalidates a cache' do
- expect(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).once.and_call_original
+ context 'Dry-run: true' do
+ it 'recalculates a fresh value every time in order to check the cache is not returning stale data' do
+ expect(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).twice
+
+ 2.times { described_class.protected?(project, protected_branch.name) }
+ end
- create(:protected_branch, project: project, name: "bar")
- # the cache is invalidated because the project has been "updated"
- expect(described_class.protected?(project, protected_branch.name)).to eq(true)
+ it_behaves_like 'hash based cache implementation'
end
- it 'correctly uses the cached version' do
- expect(described_class).not_to receive(:matching)
- expect(described_class.protected?(project, protected_branch.name)).to eq(true)
+ context 'Dry-run: false' do
+ let(:dry_run) { false }
+
+ it 'correctly invalidates a cache' do
+ expect(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).exactly(3).times.and_call_original
+
+ create_params = { name: 'bar', merge_access_levels_attributes: [{ access_level: Gitlab::Access::DEVELOPER }] }
+ branch = ProtectedBranches::CreateService.new(project, project.owner, create_params).execute
+ expect(described_class.protected?(project, protected_branch.name, dry_run: dry_run)).to eq(true)
+
+ ProtectedBranches::UpdateService.new(project, project.owner, name: 'ber').execute(branch)
+ expect(described_class.protected?(project, protected_branch.name, dry_run: dry_run)).to eq(true)
+
+ ProtectedBranches::DestroyService.new(project, project.owner).execute(branch)
+ expect(described_class.protected?(project, protected_branch.name, dry_run: dry_run)).to eq(true)
+ end
+
+ it_behaves_like 'hash based cache implementation'
+
+ context 'when project is updated' do
+ it 'does not invalidate a cache' do
+ expect(described_class).not_to receive(:matching).with(protected_branch.name, protected_refs: anything)
+
+ project.touch
+
+ described_class.protected?(project, protected_branch.name, dry_run: dry_run)
+ end
+ end
+
+ context 'when other project protected branch is updated' do
+ it 'does not invalidate the current project cache' do
+ expect(described_class).not_to receive(:matching).with(protected_branch.name, protected_refs: anything)
+
+ another_project = create(:project)
+ ProtectedBranches::CreateService.new(another_project, another_project.owner, name: 'bar').execute
+
+ described_class.protected?(project, protected_branch.name, dry_run: dry_run)
+ end
+ end
+
+ it 'correctly uses the cached version' do
+ expect(described_class).not_to receive(:matching)
+
+ expect(described_class.protected?(project, protected_branch.name, dry_run: dry_run)).to eq(true)
+ end
end
- it 'sets expires_in for a cache key' do
- cache_key = described_class.protected_ref_cache_key(project, protected_branch.name)
+ context 'when feature flag hash_based_cache_for_protected_branches is off' do
+ let(:feature_flag) { false }
- expect(Rails.cache).to receive(:fetch).with(cache_key, expires_in: 1.hour)
+ it 'does not call hash based cache implementation' do
+ expect(ProtectedBranches::CacheService).not_to receive(:new)
+ expect(Rails.cache).to receive(:fetch).and_call_original
+
+ described_class.protected?(project, 'missing-branch')
+ end
+
+ it 'correctly invalidates a cache' do
+ expect(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).once.and_call_original
+
+ create(:protected_branch, project: project, name: "bar")
+ # the cache is invalidated because the project has been "updated"
+ expect(described_class.protected?(project, protected_branch.name)).to eq(true)
+ end
- described_class.protected?(project, protected_branch.name)
+ it 'sets expires_in of 1 hour for the Rails cache key' do
+ cache_key = described_class.protected_ref_cache_key(project, protected_branch.name)
+
+ expect(Rails.cache).to receive(:fetch).with(cache_key, expires_in: 1.hour)
+
+ described_class.protected?(project, protected_branch.name)
+ end
+
+ context 'when project is updated' do
+ it 'invalidates Rails cache' do
+ expect(described_class).to receive(:matching).with(protected_branch.name, protected_refs: anything).once.and_call_original
+
+ project.touch
+
+ described_class.protected?(project, protected_branch.name)
+ end
+ end
+
+ it 'correctly uses the cached version' do
+ expect(described_class).not_to receive(:matching)
+ expect(described_class.protected?(project, protected_branch.name)).to eq(true)
+ end
end
end
end
diff --git a/spec/models/release_highlight_spec.rb b/spec/models/release_highlight_spec.rb
index 14a43df4229..3555dfba769 100644
--- a/spec/models/release_highlight_spec.rb
+++ b/spec/models/release_highlight_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
let(:page) { 3 }
it 'responds with paginated results' do
- expect(subject[:items].first['title']).to eq('bright')
+ expect(subject[:items].first['name']).to eq('bright')
expect(subject[:next_page]).to eq(4)
end
end
@@ -37,7 +37,7 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
let(:page) { 4 }
it 'responds with paginated results and no next_page' do
- expect(subject[:items].first['title']).to eq("It's gonna be a bright")
+ expect(subject[:items].first['name']).to eq("It's gonna be a bright")
expect(subject[:next_page]).to eq(nil)
end
end
@@ -63,12 +63,12 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
it 'returns platform specific items' do
expect(subject[:items].count).to eq(1)
- expect(subject[:items].first['title']).to eq("bright and sunshinin' day")
+ expect(subject[:items].first['name']).to eq("bright and sunshinin' day")
expect(subject[:next_page]).to eq(2)
end
- it 'parses the body as markdown and returns html, and links are target="_blank"' do
- expect(subject[:items].first['body']).to match('<p data-sourcepos="1:1-1:62" dir="auto">bright and sunshinin\' <a href="https://en.wikipedia.org/wiki/Day" rel="nofollow noreferrer noopener" target="_blank">day</a></p>')
+ it 'parses the description as markdown and returns html, and links are target="_blank"' do
+ expect(subject[:items].first['description']).to match('<p data-sourcepos="1:1-1:62" dir="auto">bright and sunshinin\' <a href="https://en.wikipedia.org/wiki/Day" rel="nofollow noreferrer noopener" target="_blank">day</a></p>')
end
it 'logs an error if theres an error parsing markdown for an item, and skips it' do
@@ -83,7 +83,7 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
it 'responds with a different set of data' do
expect(subject[:items].count).to eq(1)
- expect(subject[:items].first['title']).to eq("I think I can make it now the pain is gone")
+ expect(subject[:items].first['name']).to eq("I think I can make it now the pain is gone")
end
end
@@ -171,7 +171,7 @@ RSpec.describe ReleaseHighlight, :clean_gitlab_redis_cache do
items = described_class.load_items(page: 2)
expect(items.count).to eq(1)
- expect(items.first['title']).to eq("View epics on a board")
+ expect(items.first['name']).to eq("View epics on a board")
end
end
end
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 83d7596ff51..180a76ff593 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -233,6 +233,6 @@ RSpec.describe Release do
let_it_be(:milestone_2) { create(:milestone, project: project, title: 'Milestone 2') }
let_it_be(:release) { create(:release, project: project, milestones: [milestone_1, milestone_2]) }
- it { expect(release.milestone_titles).to eq("#{milestone_1.title}, #{milestone_2.title}")}
+ it { expect(release.milestone_titles).to eq("#{milestone_1.title}, #{milestone_2.title}") }
end
end
diff --git a/spec/models/releases/link_spec.rb b/spec/models/releases/link_spec.rb
index 74ef38f482b..4910de61c22 100644
--- a/spec/models/releases/link_spec.rb
+++ b/spec/models/releases/link_spec.rb
@@ -127,7 +127,7 @@ RSpec.describe Releases::Link do
describe 'FILEPATH_REGEX with table' do
using RSpec::Parameterized::TableSyntax
- let(:link) { build(:release_link)}
+ let(:link) { build(:release_link) }
where(:reason, :filepath, :result) do
'cannot contain `//`' | '/https//www.example.com' | be_invalid
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 51351c9fdd1..429ad550626 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe RemoteMirror, :mailer do
- include GitHelpers
-
before do
stub_feature_flags(remote_mirror_no_delay: false)
end
@@ -96,16 +94,6 @@ RSpec.describe RemoteMirror, :mailer do
expect(mirror.url).to eq('http://foo:bar@test.com')
expect(mirror.credentials).to eq({ user: 'foo', password: 'bar' })
end
-
- it 'does not update the repository config if credentials changed' do
- mirror = create_mirror(url: 'http://foo:bar@test.com')
- repo = mirror.project.repository
- old_config = rugged_repo(repo).config
-
- mirror.update_attribute(:url, 'http://foo:baz@test.com')
-
- expect(rugged_repo(repo).config.to_hash).to eq(old_config.to_hash)
- end
end
end
@@ -231,7 +219,7 @@ RSpec.describe RemoteMirror, :mailer do
end
describe '#hard_retry!' do
- let(:remote_mirror) { create(:remote_mirror).tap {|mirror| mirror.update_column(:url, 'invalid') } }
+ let(:remote_mirror) { create(:remote_mirror).tap { |mirror| mirror.update_column(:url, 'invalid') } }
it 'transitions an invalid mirror to the to_retry state' do
remote_mirror.hard_retry!('Invalid')
@@ -242,7 +230,7 @@ RSpec.describe RemoteMirror, :mailer do
end
describe '#hard_fail!' do
- let(:remote_mirror) { create(:remote_mirror).tap {|mirror| mirror.update_column(:url, 'invalid') } }
+ let(:remote_mirror) { create(:remote_mirror).tap { |mirror| mirror.update_column(:url, 'invalid') } }
it 'transitions an invalid mirror to the failed state' do
remote_mirror.hard_fail!('Invalid')
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index b3fbe75a526..530b03714b4 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1469,6 +1469,20 @@ RSpec.describe Repository do
expect(repository.find_branch(branch_name)).to be_nil
end
end
+
+ it 'expires branches cache' do
+ expect(repository).to receive(:expire_branches_cache)
+
+ subject
+ end
+
+ context 'when expire_cache: false' do
+ it 'does not expire branches cache' do
+ expect(repository).not_to receive(:expire_branches_cache)
+
+ repository.add_branch(user, branch_name, target, expire_cache: false)
+ end
+ end
end
shared_examples 'asymmetric cached method' do |method|
@@ -2263,10 +2277,34 @@ RSpec.describe Repository do
.with(%i(branch_names merged_branch_names branch_count has_visible_content? has_ambiguous_refs?))
.and_call_original
+ expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
+ expect(cache_service).to receive(:refresh)
+ end
+
repository.expire_branches_cache
end
end
+ describe '#expire_protected_branches_cache' do
+ it 'expires the cache' do
+ expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
+ expect(cache_service).to receive(:refresh)
+ end
+
+ repository.expire_protected_branches_cache
+ end
+
+ context 'when repository does not have a project' do
+ let!(:snippet) { create(:personal_snippet, :repository) }
+
+ it 'does not expire the cache' do
+ expect(ProtectedBranches::CacheService).not_to receive(:new)
+
+ snippet.repository.expire_protected_branches_cache
+ end
+ end
+ end
+
describe '#expire_tags_cache' do
it 'expires the cache' do
expect(repository).to receive(:expire_method_caches)
@@ -3123,7 +3161,7 @@ RSpec.describe Repository do
it 'after_create is not executed' do
expect(repository).not_to receive(:after_create)
- expect {repository.create_from_bundle(valid_bundle_path)}.to raise_error(::Gitlab::Git::BundleFile::InvalidBundleError)
+ expect { repository.create_from_bundle(valid_bundle_path) }.to raise_error(::Gitlab::Git::BundleFile::InvalidBundleError)
end
end
end
diff --git a/spec/models/snippet_input_action_collection_spec.rb b/spec/models/snippet_input_action_collection_spec.rb
index 3ec206bd031..269a9e1c787 100644
--- a/spec/models/snippet_input_action_collection_spec.rb
+++ b/spec/models/snippet_input_action_collection_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe SnippetInputActionCollection do
it { is_expected.to delegate_method(:[]).to(:actions) }
describe '#to_commit_actions' do
- subject { described_class.new(data).to_commit_actions}
+ subject { described_class.new(data).to_commit_actions }
it 'translates all actions to commit actions' do
transformed_action = action.merge(action: action_name.to_sym)
@@ -22,14 +22,14 @@ RSpec.describe SnippetInputActionCollection do
end
describe '#valid?' do
- subject { described_class.new(data).valid?}
+ subject { described_class.new(data).valid? }
it 'returns true' do
expect(subject).to be true
end
context 'when any of the actions is invalid' do
- let(:data) { [action, { action: 'foo' }, action]}
+ let(:data) { [action, { action: 'foo' }, action] }
it 'returns false' do
expect(subject).to be false
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index a54edc8510e..38bd189f6f4 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -571,8 +571,8 @@ RSpec.describe Snippet do
context 'when some blobs are not retrievable from repository' do
let(:snippet) { create(:snippet, :repository) }
let(:container) { double(:container) }
- let(:retrievable_filename) { 'retrievable_file'}
- let(:unretrievable_filename) { 'unretrievable_file'}
+ let(:retrievable_filename) { 'retrievable_file' }
+ let(:unretrievable_filename) { 'unretrievable_file' }
before do
allow(snippet).to receive(:list_files).and_return([retrievable_filename, unretrievable_filename])
diff --git a/spec/models/u2f_registration_spec.rb b/spec/models/u2f_registration_spec.rb
index 6bb9ccfcf35..1fab3882c2a 100644
--- a/spec/models/u2f_registration_spec.rb
+++ b/spec/models/u2f_registration_spec.rb
@@ -6,23 +6,68 @@ RSpec.describe U2fRegistration do
let_it_be(:user) { create(:user) }
let(:u2f_registration_name) { 'u2f_device' }
+ let(:app_id) { FFaker::BaconIpsum.characters(5) }
+ let(:device) { U2F::FakeU2F.new(app_id) }
- let(:u2f_registration) do
- device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
- create(:u2f_registration, name: u2f_registration_name,
- user: user,
- certificate: Base64.strict_encode64(device.cert_raw),
- key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
- public_key: Base64.strict_encode64(device.origin_public_key_raw))
+ describe '.authenticate' do
+ context 'when registration is found' do
+ it 'returns true' do
+ create_u2f_registration
+ device_challenge = U2F.urlsafe_encode64(SecureRandom.random_bytes(32))
+ sign_response_json = device.sign_response(device_challenge)
+
+ response = U2fRegistration.authenticate(
+ user,
+ app_id,
+ sign_response_json,
+ device_challenge
+ )
+
+ expect(response).to eq true
+ end
+ end
+
+ context 'when registration not found' do
+ it 'returns nil' do
+ device_challenge = U2F.urlsafe_encode64(SecureRandom.random_bytes(32))
+ sign_response_json = device.sign_response(device_challenge)
+
+ # data is valid but user does not have any u2f_registrations
+ response = U2fRegistration.authenticate(
+ user,
+ app_id,
+ sign_response_json,
+ device_challenge
+ )
+
+ expect(response).to eq nil
+ end
+ end
+
+ context 'when args passed in are invalid' do
+ it 'returns false' do
+ some_app_id = 123
+ invalid_json = 'invalid JSON'
+ challenges = 'whatever'
+
+ response = U2fRegistration.authenticate(
+ user,
+ some_app_id,
+ invalid_json,
+ challenges
+ )
+
+ expect(response).to eq false
+ end
+ end
end
describe 'callbacks' do
- describe '#create_webauthn_registration' do
+ describe 'after create' do
shared_examples_for 'creates webauthn registration' do
it 'creates webauthn registration' do
- created_record = u2f_registration
-
- webauthn_registration = WebauthnRegistration.where(u2f_registration_id: created_record.id)
+ u2f_registration = create_u2f_registration
+ webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
expect(webauthn_registration).to exist
end
end
@@ -52,8 +97,45 @@ RSpec.describe U2fRegistration do
receive(:track_exception).with(kind_of(StandardError),
u2f_registration_id: 123))
- u2f_registration
+ create_u2f_registration
end
end
+
+ describe 'after update' do
+ context 'when counter is updated' do
+ it 'updates the webauthn registration counter to be the same value' do
+ u2f_registration = create_u2f_registration
+ new_counter = u2f_registration.counter + 1
+ webauthn_registration = WebauthnRegistration.find_by(u2f_registration_id: u2f_registration.id)
+
+ u2f_registration.update!(counter: new_counter)
+
+ expect(u2f_registration.reload.counter).to eq(new_counter)
+ expect(webauthn_registration.reload.counter).to eq(new_counter)
+ end
+ end
+
+ context 'when sign count of registration is not updated' do
+ it 'does not update the counter' do
+ u2f_registration = create_u2f_registration
+ webauthn_registration = WebauthnRegistration.find_by(u2f_registration_id: u2f_registration.id)
+
+ expect do
+ u2f_registration.update!(name: 'a new name')
+ end.not_to change { webauthn_registration.counter }
+ end
+ end
+ end
+ end
+
+ def create_u2f_registration
+ create(
+ :u2f_registration,
+ name: u2f_registration_name,
+ user: user,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw)
+ )
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index ae6ebdbc6fd..69cd51137b5 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -137,6 +137,7 @@ RSpec.describe User do
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
it 'does not persist `user_detail` by default' do
@@ -1082,20 +1083,6 @@ RSpec.describe User do
end
end
- describe '.by_id_and_login' do
- let_it_be(:user) { create(:user) }
-
- it 'finds a user regardless of case' do
- expect(described_class.by_id_and_login(user.id, user.username.upcase))
- .to contain_exactly(user)
- end
-
- it 'finds a user when login is an email address regardless of case' do
- expect(described_class.by_id_and_login(user.id, user.email.upcase))
- .to contain_exactly(user)
- end
- end
-
describe '.for_todos' do
let_it_be(:user1) { create(:user) }
let_it_be(:user2) { create(:user) }
@@ -1792,9 +1779,10 @@ RSpec.describe User do
describe '#generate_password' do
it 'does not generate password by default' do
- user = create(:user, password: 'abcdefghe')
+ password = User.random_password
+ user = create(:user, password: password)
- expect(user.password).to eq('abcdefghe')
+ expect(user.password).to eq(password)
end
end
@@ -2831,162 +2819,144 @@ RSpec.describe User do
end
end
- shared_examples '.search examples' do
- describe '.search' do
- let_it_be(:user) { create(:user, name: 'user', username: 'usern', email: 'email@example.com') }
- let_it_be(:public_email) do
- create(:email, :confirmed, user: user, email: 'publicemail@example.com').tap do |email|
- user.update!(public_email: email.email)
- end
+ describe '.search' do
+ let_it_be(:user) { create(:user, name: 'user', username: 'usern', email: 'email@example.com') }
+ let_it_be(:public_email) do
+ create(:email, :confirmed, user: user, email: 'publicemail@example.com').tap do |email|
+ user.update!(public_email: email.email)
end
+ end
- let_it_be(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@example.com') }
- let_it_be(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@example.com') }
- let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, name: 'not verified', username: 'notverified') }
-
- let_it_be(:unconfirmed_secondary_email) { create(:email, user: user, email: 'alias@example.com') }
- let_it_be(:confirmed_secondary_email) { create(:email, :confirmed, user: user, email: 'alias2@example.com') }
+ let_it_be(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@example.com') }
+ let_it_be(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@example.com') }
+ let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, name: 'not verified', username: 'notverified') }
- describe 'name user and email relative ordering' do
- let_it_be(:named_alexander) { create(:user, name: 'Alexander Person', username: 'abcd', email: 'abcd@example.com') }
- let_it_be(:username_alexand) { create(:user, name: 'Joao Alexander', username: 'Alexand', email: 'joao@example.com') }
+ let_it_be(:unconfirmed_secondary_email) { create(:email, user: user, email: 'alias@example.com') }
+ let_it_be(:confirmed_secondary_email) { create(:email, :confirmed, user: user, email: 'alias2@example.com') }
- it 'prioritizes exact matches' do
- expect(described_class.search('Alexand')).to eq([username_alexand, named_alexander])
- end
+ describe 'name user and email relative ordering' do
+ let_it_be(:named_alexander) { create(:user, name: 'Alexander Person', username: 'abcd', email: 'abcd@example.com') }
+ let_it_be(:username_alexand) { create(:user, name: 'Joao Alexander', username: 'Alexand', email: 'joao@example.com') }
- it 'falls back to ordering by name' do
- expect(described_class.search('Alexander')).to eq([named_alexander, username_alexand])
- end
+ it 'prioritizes exact matches' do
+ expect(described_class.search('Alexand')).to eq([username_alexand, named_alexander])
end
- describe 'name matching' do
- it 'returns users with a matching name with exact match first' do
- expect(described_class.search(user.name)).to eq([user, user2])
- end
-
- it 'returns users with a partially matching name' do
- expect(described_class.search(user.name[0..2])).to eq([user, user2])
- end
-
- it 'returns users with a matching name regardless of the casing' do
- expect(described_class.search(user2.name.upcase)).to eq([user2])
- end
+ it 'falls back to ordering by name' do
+ expect(described_class.search('Alexander')).to eq([named_alexander, username_alexand])
+ end
+ end
- it 'returns users with a exact matching name shorter than 3 chars' do
- expect(described_class.search(user3.name)).to eq([user3])
- end
+ describe 'name matching' do
+ it 'returns users with a matching name with exact match first' do
+ expect(described_class.search(user.name)).to eq([user, user2])
+ end
- it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
- expect(described_class.search(user3.name.upcase)).to eq([user3])
- end
+ it 'returns users with a partially matching name' do
+ expect(described_class.search(user.name[0..2])).to eq([user, user2])
+ end
- context 'when use_minimum_char_limit is false' do
- it 'returns users with a partially matching name' do
- expect(described_class.search('u', use_minimum_char_limit: false)).to eq([user3, user, user2])
- end
- end
+ it 'returns users with a matching name regardless of the casing' do
+ expect(described_class.search(user2.name.upcase)).to eq([user2])
end
- describe 'email matching' do
- it 'returns users with a matching public email' do
- expect(described_class.search(user.public_email)).to match_array([user])
- end
+ it 'returns users with a exact matching name shorter than 3 chars' do
+ expect(described_class.search(user3.name)).to eq([user3])
+ end
- it 'does not return users with a partially matching public email' do
- expect(described_class.search(user.public_email[1...-1])).to be_empty
- end
+ it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.name.upcase)).to eq([user3])
+ end
- it 'returns users with a matching public email regardless of the casing' do
- expect(described_class.search(user.public_email.upcase)).to match_array([user])
+ context 'when use_minimum_char_limit is false' do
+ it 'returns users with a partially matching name' do
+ expect(described_class.search('u', use_minimum_char_limit: false)).to eq([user3, user, user2])
end
+ end
+ end
- it 'does not return users with a matching private email' do
- expect(described_class.search(user.email)).to be_empty
-
- expect(described_class.search(unconfirmed_secondary_email.email)).to be_empty
- expect(described_class.search(confirmed_secondary_email.email)).to be_empty
- end
+ describe 'email matching' do
+ it 'returns users with a matching public email' do
+ expect(described_class.search(user.public_email)).to match_array([user])
+ end
- context 'with private emails search' do
- it 'returns users with matching private primary email' do
- expect(described_class.search(user.email, with_private_emails: true)).to match_array([user])
- end
+ it 'does not return users with a partially matching public email' do
+ expect(described_class.search(user.public_email[1...-1])).to be_empty
+ end
- it 'returns users with matching private unconfirmed primary email' do
- expect(described_class.search(unconfirmed_user.email, with_private_emails: true)).to match_array([unconfirmed_user])
- end
+ it 'returns users with a matching public email regardless of the casing' do
+ expect(described_class.search(user.public_email.upcase)).to match_array([user])
+ end
- it 'returns users with matching private confirmed secondary email' do
- expect(described_class.search(confirmed_secondary_email.email, with_private_emails: true)).to match_array([user])
- end
+ it 'does not return users with a matching private email' do
+ expect(described_class.search(user.email)).to be_empty
- it 'does not return users with matching private unconfirmed secondary email' do
- expect(described_class.search(unconfirmed_secondary_email.email, with_private_emails: true)).to be_empty
- end
- end
+ expect(described_class.search(unconfirmed_secondary_email.email)).to be_empty
+ expect(described_class.search(confirmed_secondary_email.email)).to be_empty
end
- describe 'username matching' do
- it 'returns users with a matching username' do
- expect(described_class.search(user.username)).to eq([user, user2])
+ context 'with private emails search' do
+ it 'returns users with matching private primary email' do
+ expect(described_class.search(user.email, with_private_emails: true)).to match_array([user])
end
- it 'returns users with a matching username starting with a @' do
- expect(described_class.search("@#{user.username}")).to eq([user, user2])
+ it 'returns users with matching private unconfirmed primary email' do
+ expect(described_class.search(unconfirmed_user.email, with_private_emails: true)).to match_array([unconfirmed_user])
end
- it 'returns users with a partially matching username' do
- expect(described_class.search(user.username[0..2])).to eq([user, user2])
+ it 'returns users with matching private confirmed secondary email' do
+ expect(described_class.search(confirmed_secondary_email.email, with_private_emails: true)).to match_array([user])
end
- it 'returns users with a partially matching username starting with @' do
- expect(described_class.search("@#{user.username[0..2]}")).to eq([user, user2])
+ it 'does not return users with matching private unconfirmed secondary email' do
+ expect(described_class.search(unconfirmed_secondary_email.email, with_private_emails: true)).to be_empty
end
+ end
+ end
- it 'returns users with a matching username regardless of the casing' do
- expect(described_class.search(user2.username.upcase)).to eq([user2])
- end
+ describe 'username matching' do
+ it 'returns users with a matching username' do
+ expect(described_class.search(user.username)).to eq([user, user2])
+ end
- it 'returns users with a exact matching username shorter than 3 chars' do
- expect(described_class.search(user3.username)).to eq([user3])
- end
+ it 'returns users with a matching username starting with a @' do
+ expect(described_class.search("@#{user.username}")).to eq([user, user2])
+ end
- it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
- expect(described_class.search(user3.username.upcase)).to eq([user3])
- end
+ it 'returns users with a partially matching username' do
+ expect(described_class.search(user.username[0..2])).to eq([user, user2])
+ end
- context 'when use_minimum_char_limit is false' do
- it 'returns users with a partially matching username' do
- expect(described_class.search('se', use_minimum_char_limit: false)).to eq([user3, user, user2])
- end
- end
+ it 'returns users with a partially matching username starting with @' do
+ expect(described_class.search("@#{user.username[0..2]}")).to eq([user, user2])
end
- it 'returns no matches for an empty string' do
- expect(described_class.search('')).to be_empty
+ it 'returns users with a matching username regardless of the casing' do
+ expect(described_class.search(user2.username.upcase)).to eq([user2])
end
- it 'returns no matches for nil' do
- expect(described_class.search(nil)).to be_empty
+ it 'returns users with a exact matching username shorter than 3 chars' do
+ expect(described_class.search(user3.username)).to eq([user3])
end
- end
- end
- context 'when the use_keyset_aware_user_search_query FF is on' do
- before do
- stub_feature_flags(use_keyset_aware_user_search_query: true)
- end
+ it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.username.upcase)).to eq([user3])
+ end
- it_behaves_like '.search examples'
- end
+ context 'when use_minimum_char_limit is false' do
+ it 'returns users with a partially matching username' do
+ expect(described_class.search('se', use_minimum_char_limit: false)).to eq([user3, user, user2])
+ end
+ end
+ end
- context 'when the use_keyset_aware_user_search_query FF is off' do
- before do
- stub_feature_flags(use_keyset_aware_user_search_query: false)
+ it 'returns no matches for an empty string' do
+ expect(described_class.search('')).to be_empty
end
- it_behaves_like '.search examples'
+ it 'returns no matches for nil' do
+ expect(described_class.search(nil)).to be_empty
+ end
end
describe '.user_search_minimum_char_limit' do
@@ -3019,17 +2989,53 @@ RSpec.describe User do
end
end
+ shared_examples "find user by login" do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:invalid_login) { "#{user.username}-NOT-EXISTS" }
+
+ context 'when login is nil or empty' do
+ it 'returns nil' do
+ expect(login_method(nil)).to be_nil
+ expect(login_method('')).to be_nil
+ end
+ end
+
+ context 'when login is invalid' do
+ it 'returns nil' do
+ expect(login_method(invalid_login)).to be_nil
+ end
+ end
+
+ context 'when login is username' do
+ it 'returns user' do
+ expect(login_method(user.username)).to eq(user)
+ expect(login_method(user.username.downcase)).to eq(user)
+ expect(login_method(user.username.upcase)).to eq(user)
+ end
+ end
+
+ context 'when login is email' do
+ it 'returns user' do
+ expect(login_method(user.email)).to eq(user)
+ expect(login_method(user.email.downcase)).to eq(user)
+ expect(login_method(user.email.upcase)).to eq(user)
+ end
+ end
+ end
+
describe '.by_login' do
- let(:username) { 'John' }
- let!(:user) { create(:user, username: username) }
+ it_behaves_like "find user by login" do
+ def login_method(login)
+ described_class.by_login(login).take
+ end
+ end
+ end
- it 'gets the correct user' do
- expect(described_class.by_login(user.email.upcase)).to eq user
- expect(described_class.by_login(user.email)).to eq user
- expect(described_class.by_login(username.downcase)).to eq user
- expect(described_class.by_login(username)).to eq user
- expect(described_class.by_login(nil)).to be_nil
- expect(described_class.by_login('')).to be_nil
+ describe '.find_by_login' do
+ it_behaves_like "find user by login" do
+ def login_method(login)
+ described_class.find_by_login(login)
+ end
end
end
@@ -5120,7 +5126,6 @@ RSpec.describe User do
expect(cache_mock).to receive(:delete).with(['users', user.id, 'assigned_open_merge_requests_count'])
expect(cache_mock).to receive(:delete).with(['users', user.id, 'review_requested_open_merge_requests_count'])
- expect(cache_mock).to receive(:delete).with(['users', user.id, 'attention_requested_open_merge_requests_count'])
allow(Rails).to receive(:cache).and_return(cache_mock)
@@ -5128,20 +5133,6 @@ RSpec.describe User do
end
end
- describe '#invalidate_attention_requested_count' do
- let(:user) { build_stubbed(:user) }
-
- it 'invalidates cache for issue counter' do
- cache_mock = double
-
- expect(cache_mock).to receive(:delete).with(['users', user.id, 'attention_requested_open_merge_requests_count'])
-
- allow(Rails).to receive(:cache).and_return(cache_mock)
-
- user.invalidate_attention_requested_count
- end
- end
-
describe '#invalidate_personal_projects_count' do
let(:user) { build_stubbed(:user) }
@@ -5228,43 +5219,6 @@ RSpec.describe User do
end
end
- describe '#attention_requested_open_merge_requests_count' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :public) }
- let(:archived_project) { create(:project, :public, :archived) }
-
- before do
- mr1 = create(:merge_request, source_project: project, author: user, reviewers: [user])
- mr2 = create(:merge_request, :closed, source_project: project, author: user, reviewers: [user])
- mr3 = create(:merge_request, source_project: archived_project, author: user, reviewers: [user])
-
- mr1.find_reviewer(user).update!(state: :attention_requested)
- mr2.find_reviewer(user).update!(state: :attention_requested)
- mr3.find_reviewer(user).update!(state: :attention_requested)
- end
-
- it 'returns number of open merge requests from non-archived projects' do
- expect(Rails.cache).not_to receive(:fetch)
- expect(user.attention_requested_open_merge_requests_count(force: true)).to eq 1
- end
-
- context 'when uncached_mr_attention_requests_count is disabled' do
- before do
- stub_feature_flags(uncached_mr_attention_requests_count: false)
- end
-
- it 'fetches from cache' do
- expect(Rails.cache).to receive(:fetch).with(
- user.attention_request_cache_key,
- force: false,
- expires_in: described_class::COUNT_CACHE_VALIDITY_PERIOD
- ).and_call_original
-
- expect(user.attention_requested_open_merge_requests_count).to eq 1
- end
- end
- end
-
describe '#assigned_open_issues_count' do
it 'returns number of open issues from non-archived projects' do
user = create(:user)
@@ -6158,8 +6112,9 @@ RSpec.describe User do
end
context 'user with a bcrypt password hash' do
- # Plaintext password 'eiFubohV6iro'
- let(:encrypted_password) { '$2a$10$xLTxCKOa75IU4RQGqqOrTuZOgZdJEzfSzjG6ZSEi/C31TB/yLZYpi' }
+ # Manually set a 'known' encrypted password
+ let(:password) { User.random_password }
+ let(:encrypted_password) { Devise::Encryptor.digest(User, password) }
let(:user) { create(:user, encrypted_password: encrypted_password) }
shared_examples 'not re-encrypting with PBKDF2' do
@@ -6171,9 +6126,12 @@ RSpec.describe User do
end
context 'using the wrong password' do
+ # password 'WRONG PASSWORD' will not match the bcrypt hash
let(:password) { 'WRONG PASSWORD' }
+ let(:encrypted_password) { Devise::Encryptor.digest(User, User.random_password) }
it { is_expected.to be_falsey }
+
it_behaves_like 'not re-encrypting with PBKDF2'
context 'when pbkdf2_password_encryption is disabled' do
@@ -6182,13 +6140,12 @@ RSpec.describe User do
end
it { is_expected.to be_falsey }
+
it_behaves_like 'not re-encrypting with PBKDF2'
end
end
context 'using the correct password' do
- let(:password) { 'eiFubohV6iro' }
-
it { is_expected.to be_truthy }
it 'validates the password and re-encrypts with PBKDF2' do
@@ -6207,6 +6164,7 @@ RSpec.describe User do
end
it { is_expected.to be_truthy }
+
it_behaves_like 'not re-encrypting with PBKDF2'
end
@@ -6216,14 +6174,18 @@ RSpec.describe User do
end
it { is_expected.to be_truthy }
+
it_behaves_like 'not re-encrypting with PBKDF2'
end
end
end
context 'user with password hash that is neither PBKDF2 nor BCrypt' do
- let(:user) { create(:user, encrypted_password: '$argon2i$v=19$m=512,t=4,p=2$eM+ZMyYkpDRGaI3xXmuNcQ$c5DeJg3eb5dskVt1mDdxfw') }
- let(:password) { 'password' }
+ # Manually calculated User.random_password
+ let(:password) { "gg_w215TmVXGWSt7RJKXwYTVz886f6SDM3zvzztaJf2mX9ttUE8gRkNJSbWyWRLqxz4LFzxBekPe75ydDcGauE9wqg-acKMRT-WpSYjTm1Rdx-tnssE7CQByJcnxwWNH" }
+ # Created with https://argon2.online/ using 'aaaaaaaa' as the salt
+ let(:encrypted_password) { "$argon2i$v=19$m=512,t=4,p=2$YWFhYWFhYWE$PvJscKO5XRlevcgRReUg6w" }
+ let(:user) { create(:user, encrypted_password: encrypted_password) }
it { is_expected.to be_falsey }
@@ -6240,7 +6202,7 @@ RSpec.describe User do
# These entire test section can be removed once the :pbkdf2_password_encryption feature flag is removed.
describe '#password=' do
let(:user) { create(:user) }
- let(:password) { 'Oot5iechahqu' }
+ let(:password) { User.random_password }
def compare_bcrypt_password(user, password)
Devise::Encryptor.compare(User, user.encrypted_password, password)
@@ -6422,7 +6384,7 @@ RSpec.describe User do
end
context 'when password_automatically_set is true' do
- let(:user) { create(:omniauth_user, provider: 'ldap')}
+ let(:user) { create(:omniauth_user, provider: 'ldap') }
it_behaves_like 'password expired not applicable'
end
@@ -6701,6 +6663,40 @@ RSpec.describe User do
end
end
+ describe '#dismissed_callout_for_project?' do
+ let_it_be(:user, refind: true) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:feature_name) { Users::ProjectCallout.feature_names.each_key.first }
+
+ context 'when no callout dismissal record exists' do
+ it 'returns false when no ignore_dismissal_earlier_than provided' do
+ expect(user.dismissed_callout_for_project?(feature_name: feature_name, project: project)).to eq false
+ end
+ end
+
+ context 'when dismissed callout exists' do
+ before_all do
+ create(:project_callout,
+ user: user,
+ project_id: project.id,
+ feature_name: feature_name,
+ dismissed_at: 4.months.ago)
+ end
+
+ it 'returns true when no ignore_dismissal_earlier_than provided' do
+ expect(user.dismissed_callout_for_project?(feature_name: feature_name, project: project)).to eq true
+ end
+
+ it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do
+ expect(user.dismissed_callout_for_project?(feature_name: feature_name, project: project, ignore_dismissal_earlier_than: 6.months.ago)).to eq true
+ end
+
+ it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do
+ expect(user.dismissed_callout_for_project?(feature_name: feature_name, project: project, ignore_dismissal_earlier_than: 3.months.ago)).to eq false
+ end
+ end
+ end
+
describe '#find_or_initialize_group_callout' do
let_it_be(:user, refind: true) { create(:user) }
let_it_be(:group) { create(:group) }
@@ -6745,6 +6741,50 @@ RSpec.describe User do
end
end
+ describe '#find_or_initialize_project_callout' do
+ let_it_be(:user, refind: true) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:feature_name) { Users::ProjectCallout.feature_names.each_key.first }
+
+ subject(:callout_with_source) do
+ user.find_or_initialize_project_callout(feature_name, project.id)
+ end
+
+ context 'when callout exists' do
+ let!(:callout) do
+ create(:project_callout, user: user, feature_name: feature_name, project_id: project.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::ProjectCallout)
+ end
+
+ it 'is valid' do
+ expect(callout_with_source).to 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::ProjectCallout)
+ end
+
+ it 'is not valid' do
+ expect(callout_with_source).not_to be_valid
+ end
+ end
+ end
+ end
+
describe '#hook_attrs' do
let(:user) { create(:user) }
let(:user_attributes) do
@@ -7374,4 +7414,12 @@ RSpec.describe User do
expect(another_user.mr_attention_requests_enabled?).to be(false)
end
end
+
+ describe 'user age' do
+ let(:user) { create(:user, created_at: Date.yesterday) }
+
+ it 'returns age in days' do
+ expect(user.account_age_in_days).to be(1)
+ end
+ end
end
diff --git a/spec/models/user_status_spec.rb b/spec/models/user_status_spec.rb
index 87d1fa14aca..663df9712ab 100644
--- a/spec/models/user_status_spec.rb
+++ b/spec/models/user_status_spec.rb
@@ -47,4 +47,30 @@ RSpec.describe UserStatus do
end
end
end
+
+ describe '#customized?' do
+ it 'is customized when message text is present' do
+ subject.message = 'My custom status'
+
+ expect(subject).to be_customized
+ end
+
+ it 'is not customized when message text is absent' do
+ subject.message = nil
+
+ expect(subject).not_to be_customized
+ end
+
+ it 'is customized without message but with custom emoji' do
+ subject.emoji = 'bow'
+
+ expect(subject).to be_customized
+ end
+
+ it 'is not customized without message but with default custom emoji' do
+ subject.emoji = 'speech_balloon'
+
+ expect(subject).not_to be_customized
+ end
+ end
end
diff --git a/spec/models/users/calloutable_spec.rb b/spec/models/users/calloutable_spec.rb
index 01603d8bbd6..791fe1c1bc4 100644
--- a/spec/models/users/calloutable_spec.rb
+++ b/spec/models/users/calloutable_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe Users::Calloutable do
describe '#dismissed_after?' do
let(:some_feature_name) { Users::Callout.feature_names.keys.second }
- let(:callout_dismissed_month_ago) { create(:callout, feature_name: some_feature_name, dismissed_at: 1.month.ago )}
- let(:callout_dismissed_day_ago) { create(:callout, feature_name: some_feature_name, dismissed_at: 1.day.ago )}
+ let(:callout_dismissed_month_ago) { create(:callout, feature_name: some_feature_name, dismissed_at: 1.month.ago ) }
+ let(:callout_dismissed_day_ago) { create(:callout, feature_name: some_feature_name, dismissed_at: 1.day.ago ) }
it 'returns whether a callout dismissed after specified date' do
expect(callout_dismissed_month_ago.dismissed_after?(15.days.ago)).to eq(false)
diff --git a/spec/models/users/in_product_marketing_email_spec.rb b/spec/models/users/in_product_marketing_email_spec.rb
index 7796b54babc..78de9ad8bdb 100644
--- a/spec/models/users/in_product_marketing_email_spec.rb
+++ b/spec/models/users/in_product_marketing_email_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do
context 'for a track+series email' do
it { is_expected.to validate_presence_of(:track) }
it { is_expected.to validate_presence_of(:series) }
+
it {
is_expected.to validate_uniqueness_of(:user_id)
.scoped_to([:track, :series]).with_message('track series email has already been sent')
@@ -30,10 +31,12 @@ RSpec.describe Users::InProductMarketingEmail, type: :model do
it { is_expected.to validate_presence_of(:campaign) }
it { is_expected.not_to validate_presence_of(:track) }
it { is_expected.not_to validate_presence_of(:series) }
+
it {
is_expected.to validate_uniqueness_of(:user_id)
.scoped_to(:campaign).with_message('campaign email has already been sent')
}
+
it { is_expected.to validate_inclusion_of(:campaign).in_array(described_class::CAMPAIGNS) }
end
diff --git a/spec/models/users/project_callout_spec.rb b/spec/models/users/project_callout_spec.rb
new file mode 100644
index 00000000000..87d865c4bdf
--- /dev/null
+++ b/spec/models/users/project_callout_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::ProjectCallout do
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create_default(:project) }
+ let_it_be(:callout) { create(:project_callout) }
+
+ 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) }
+ it { is_expected.to validate_presence_of(:feature_name) }
+
+ it {
+ is_expected.to validate_uniqueness_of(:feature_name).scoped_to(:user_id, :project_id).ignoring_case_sensitivity
+ }
+ end
+end
diff --git a/spec/models/webauthn_registration_spec.rb b/spec/models/webauthn_registration_spec.rb
index 6813854bf6c..240e7002ca3 100644
--- a/spec/models/webauthn_registration_spec.rb
+++ b/spec/models/webauthn_registration_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe WebauthnRegistration do
it { is_expected.to validate_presence_of(:counter) }
it { is_expected.to validate_length_of(:name).is_at_least(0) }
it { is_expected.not_to allow_value(nil).for(:name) }
+
it do
is_expected.to validate_numericality_of(:counter)
.only_integer
diff --git a/spec/models/wiki_page/meta_spec.rb b/spec/models/wiki_page/meta_spec.rb
index 37a282657d9..4d1a2dc1c98 100644
--- a/spec/models/wiki_page/meta_spec.rb
+++ b/spec/models/wiki_page/meta_spec.rb
@@ -89,7 +89,7 @@ RSpec.describe WikiPage::Meta do
shared_examples 'canonical_slug setting examples' do
# Constant overhead of two queries for the transaction
let(:upper_query_limit) { query_limit + 2 }
- let(:lower_query_limit) { [upper_query_limit - 1, 0].max}
+ let(:lower_query_limit) { [upper_query_limit - 1, 0].max }
let(:other_slug) { generate(:sluggified_title) }
it 'changes it to the correct value' do
diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb
index f33c8e0a186..e2240c225a9 100644
--- a/spec/models/work_item_spec.rb
+++ b/spec/models/work_item_spec.rb
@@ -40,10 +40,13 @@ RSpec.describe WorkItem do
subject { build(:work_item).widgets }
it 'returns instances of supported widgets' do
- is_expected.to match_array([instance_of(WorkItems::Widgets::Description),
- instance_of(WorkItems::Widgets::Hierarchy),
- instance_of(WorkItems::Widgets::Assignees),
- instance_of(WorkItems::Widgets::Weight)])
+ is_expected.to include(
+ instance_of(WorkItems::Widgets::Description),
+ instance_of(WorkItems::Widgets::Hierarchy),
+ instance_of(WorkItems::Widgets::Labels),
+ instance_of(WorkItems::Widgets::Assignees),
+ instance_of(WorkItems::Widgets::StartAndDueDate)
+ )
end
end
@@ -107,5 +110,61 @@ RSpec.describe WorkItem do
it { is_expected.to eq(false) }
end
end
+
+ describe 'confidentiality' do
+ let_it_be(:project) { create(:project) }
+
+ context 'when parent and child are confidential' do
+ let_it_be(:parent) { create(:work_item, confidential: true, project: project) }
+ let_it_be(:child) { create(:work_item, :task, confidential: true, project: project) }
+ let_it_be(:link) { create(:parent_link, work_item: child, work_item_parent: parent) }
+
+ it 'does not allow to make child non-confidential' do
+ child.confidential = false
+
+ expect(child).not_to be_valid
+ expect(child.errors[:confidential])
+ .to include('associated parent is confidential and can not have non-confidential children.')
+ end
+
+ it 'allows to make parent non-confidential' do
+ parent.confidential = false
+
+ expect(parent).to be_valid
+ end
+ end
+
+ context 'when parent and child are non-confidential' do
+ let_it_be(:parent) { create(:work_item, project: project) }
+ let_it_be(:child) { create(:work_item, :task, project: project) }
+ let_it_be(:link) { create(:parent_link, work_item: child, work_item_parent: parent) }
+
+ it 'does not allow to make parent confidential' do
+ parent.confidential = true
+
+ expect(parent).not_to be_valid
+ expect(parent.errors[:confidential])
+ .to include('confidential parent can not be used if there are non-confidential children.')
+ end
+
+ it 'allows to make child confidential' do
+ child.confidential = true
+
+ expect(child).to be_valid
+ end
+ end
+
+ context 'when creating new child' do
+ let_it_be(:child) { build(:work_item, project: project) }
+
+ it 'does not allow to set confidential parent' do
+ child.work_item_parent = create(:work_item, confidential: true, project: project)
+
+ expect(child).not_to be_valid
+ expect(child.errors[:confidential])
+ .to include('associated parent is confidential and can not have non-confidential children.')
+ end
+ end
+ end
end
end
diff --git a/spec/models/work_items/parent_link_spec.rb b/spec/models/work_items/parent_link_spec.rb
index a16b15bbfc9..070b2eef86a 100644
--- a/spec/models/work_items/parent_link_spec.rb
+++ b/spec/models/work_items/parent_link_spec.rb
@@ -69,6 +69,70 @@ RSpec.describe WorkItems::ParentLink do
expect(link1).to be_valid
end
end
+
+ context 'when setting confidentiality' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:confidential_parent, :confidential_child, :valid) do
+ false | false | true
+ true | true | true
+ false | true | true
+ true | false | false
+ end
+
+ with_them do
+ before do
+ issue.confidential = confidential_parent
+ task1.confidential = confidential_child
+ end
+
+ it 'validates if child confidentiality is compatible with parent' do
+ link = build(:parent_link, work_item_parent: issue, work_item: task1)
+
+ expect(link.valid?).to eq(valid)
+ end
+ end
+ end
+ end
+ end
+
+ context 'with confidential work items' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:confidential_child) { create(:work_item, :task, confidential: true, project: project) }
+ let_it_be(:putlic_child) { create(:work_item, :task, project: project) }
+ let_it_be(:confidential_parent) { create(:work_item, confidential: true, project: project) }
+ let_it_be(:public_parent) { create(:work_item, project: project) }
+
+ describe '.has_public_children?' do
+ subject { described_class.has_public_children?(public_parent.id) }
+
+ context 'with confidential child' do
+ let_it_be(:link) { create(:parent_link, work_item_parent: public_parent, work_item: confidential_child) }
+
+ it { is_expected.to be_falsey }
+
+ context 'with also public child' do
+ let_it_be(:link) { create(:parent_link, work_item_parent: public_parent, work_item: putlic_child) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+
+ describe '.has_confidential_parent?' do
+ subject { described_class.has_confidential_parent?(confidential_child.id) }
+
+ context 'with confidential parent' do
+ let_it_be(:link) { create(:parent_link, work_item_parent: confidential_parent, work_item: confidential_child) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with public parent' do
+ let_it_be(:link) { create(:parent_link, work_item_parent: public_parent, work_item: confidential_child) }
+
+ it { is_expected.to be_falsey }
+ end
end
end
end
diff --git a/spec/models/work_items/type_spec.rb b/spec/models/work_items/type_spec.rb
index e91617effc0..e41df7f0f61 100644
--- a/spec/models/work_items/type_spec.rb
+++ b/spec/models/work_items/type_spec.rb
@@ -64,10 +64,13 @@ RSpec.describe WorkItems::Type do
subject { described_class.available_widgets }
it 'returns list of all possible widgets' do
- is_expected.to match_array([::WorkItems::Widgets::Description,
- ::WorkItems::Widgets::Hierarchy,
- ::WorkItems::Widgets::Assignees,
- ::WorkItems::Widgets::Weight])
+ is_expected.to include(
+ ::WorkItems::Widgets::Description,
+ ::WorkItems::Widgets::Hierarchy,
+ ::WorkItems::Widgets::Labels,
+ ::WorkItems::Widgets::Assignees,
+ ::WorkItems::Widgets::StartAndDueDate
+ )
end
end
diff --git a/spec/models/work_items/widgets/hierarchy_spec.rb b/spec/models/work_items/widgets/hierarchy_spec.rb
index ab2bcfee13f..cd528772710 100644
--- a/spec/models/work_items/widgets/hierarchy_spec.rb
+++ b/spec/models/work_items/widgets/hierarchy_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
end
describe '#parent' do
- let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item_parent) }
+ let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item_parent).reload }
subject { described_class.new(parent_link.work_item).parent }
@@ -45,8 +45,8 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
end
describe '#children' do
- let_it_be(:parent_link1) { create(:parent_link, work_item_parent: work_item_parent, work_item: task) }
- let_it_be(:parent_link2) { create(:parent_link, work_item_parent: work_item_parent) }
+ let_it_be(:parent_link1) { create(:parent_link, work_item_parent: work_item_parent, work_item: task).reload }
+ let_it_be(:parent_link2) { create(:parent_link, work_item_parent: work_item_parent).reload }
subject { described_class.new(work_item_parent).children }
diff --git a/spec/models/work_items/widgets/labels_spec.rb b/spec/models/work_items/widgets/labels_spec.rb
new file mode 100644
index 00000000000..15e8aaa1cf3
--- /dev/null
+++ b/spec/models/work_items/widgets/labels_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::Labels do
+ let_it_be(:work_item) { create(:work_item, labels: [create(:label)]) }
+
+ describe '.type' do
+ subject { described_class.type }
+
+ it { is_expected.to eq(:labels) }
+ end
+
+ describe '#type' do
+ subject { described_class.new(work_item).type }
+
+ it { is_expected.to eq(:labels) }
+ end
+
+ describe '#labels' do
+ subject { described_class.new(work_item).labels }
+
+ it { is_expected.to eq(work_item.labels) }
+ end
+
+ describe '#allowScopedLabels' do
+ subject { described_class.new(work_item).allows_scoped_labels? }
+
+ it { is_expected.to eq(work_item.allows_scoped_labels?) }
+ end
+end
diff --git a/spec/models/work_items/widgets/start_and_due_date_spec.rb b/spec/models/work_items/widgets/start_and_due_date_spec.rb
new file mode 100644
index 00000000000..b023cc73e0f
--- /dev/null
+++ b/spec/models/work_items/widgets/start_and_due_date_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::StartAndDueDate do
+ let_it_be(:work_item) { create(:work_item, start_date: Date.today, due_date: 1.week.from_now) }
+
+ describe '.type' do
+ subject { described_class.type }
+
+ it { is_expected.to eq(:start_and_due_date) }
+ end
+
+ describe '#type' do
+ subject { described_class.new(work_item).type }
+
+ it { is_expected.to eq(:start_and_due_date) }
+ end
+
+ describe '#start_date' do
+ subject { described_class.new(work_item).start_date }
+
+ it { is_expected.to eq(work_item.start_date) }
+ end
+
+ describe '#due_date' do
+ subject { described_class.new(work_item).due_date }
+
+ it { is_expected.to eq(work_item.due_date) }
+ end
+end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 3ef859376a4..57923142648 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe GroupPolicy do
include_context 'GroupPolicy context'
- using RSpec::Parameterized::TableSyntax
context 'public group with no user' do
let(:group) { create(:group, :public, :crm_enabled) }
@@ -1231,29 +1230,11 @@ RSpec.describe GroupPolicy do
it { is_expected.to be_disallowed(:admin_crm_organization) }
end
- describe 'maintain_namespace' do
- context 'with non-admin roles' do
- where(:role, :allowed) do
- :guest | false
- :reporter | false
- :developer | false
- :maintainer | true
- :owner | true
- end
-
- with_them do
- let(:current_user) { public_send(role) }
+ it_behaves_like 'checks timelog categories permissions' do
+ let(:group) { create(:group) }
+ let(:namespace) { group }
+ let(:users_container) { group }
- it do
- expect(subject.allowed?(:maintain_namespace)).to eq allowed
- end
- end
- end
-
- context 'as an admin', :enable_admin_mode do
- let(:current_user) { admin }
-
- it { is_expected.to be_allowed(:maintain_namespace) }
- end
+ subject { described_class.new(current_user, group) }
end
end
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index 5e2a307e959..706570babd5 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -113,5 +113,45 @@ RSpec.describe IssuablePolicy, models: true do
end
end
end
+
+ context 'when user is anonymous' do
+ it 'does not allow timelogs creation' do
+ expect(permissions(nil, issue)).to be_disallowed(:create_timelog)
+ end
+ end
+
+ context 'when user is not a member of the project' do
+ it 'does not allow timelogs creation' do
+ expect(policies).to be_disallowed(:create_timelog)
+ end
+ end
+
+ context 'when user is not a member of the project but the author of the issuable' do
+ let(:issue) { create(:issue, project: project, author: user) }
+
+ it 'does not allow timelogs creation' do
+ expect(policies).to be_disallowed(:create_timelog)
+ end
+ end
+
+ context 'when user is a guest member of the project' do
+ it 'does not allow timelogs creation' do
+ expect(permissions(guest, issue)).to be_disallowed(:create_timelog)
+ end
+ end
+
+ context 'when user is a guest member of the project and the author of the issuable' do
+ let(:issue) { create(:issue, project: project, author: guest) }
+
+ it 'does not allow timelogs creation' do
+ expect(permissions(guest, issue)).to be_disallowed(:create_timelog)
+ end
+ end
+
+ context 'when user is at least reporter of the project' do
+ it 'allows timelogs creation' do
+ expect(permissions(reporter, issue)).to be_allowed(:create_timelog)
+ end
+ end
end
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index fefbb59a830..7ca4baddb79 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -3,7 +3,9 @@
require 'spec_helper'
RSpec.describe IssuePolicy do
+ include_context 'ProjectPolicyTable context'
include ExternalAuthorizationServiceHelpers
+ include ProjectHelpers
let(:guest) { create(:user) }
let(:author) { create(:user) }
@@ -50,6 +52,19 @@ RSpec.describe IssuePolicy do
end
end
+ shared_examples 'grants the expected permissions' do |policy|
+ specify do
+ enable_admin_mode!(user) if admin_mode
+ update_feature_access_level(project, feature_access_level)
+
+ if expected_count == 1
+ expect(permissions(user, issue)).to be_allowed(policy)
+ else
+ expect(permissions(user, issue)).to be_disallowed(policy)
+ end
+ end
+ end
+
context 'a private project' do
let(:project) { create(:project, :private) }
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
@@ -85,7 +100,6 @@ RSpec.describe IssuePolicy do
it 'allows reporters from group links to read, update, and admin issues' do
expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
- expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
expect(permissions(reporter_from_group_link, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality)
end
@@ -217,7 +231,7 @@ RSpec.describe IssuePolicy do
it 'allows reporters from group links to read, update, reopen and admin issues' do
expect(permissions(reporter_from_group_link, issue)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality)
- expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :reopen_issue, :set_issue_metadata, :set_confidentiality)
+ expect(permissions(reporter_from_group_link, issue_no_assignee)).to be_allowed(:reopen_issue)
expect(permissions(reporter_from_group_link, issue_locked)).to be_allowed(:read_issue, :read_issue_iid, :update_issue, :admin_issue, :set_issue_metadata, :set_confidentiality)
expect(permissions(reporter_from_group_link, issue_locked)).to be_disallowed(:reopen_issue)
expect(permissions(reporter, new_issue)).to be_allowed(:create_issue, :set_issue_metadata, :set_confidentiality)
@@ -295,18 +309,23 @@ RSpec.describe IssuePolicy do
it 'forbids visitors from viewing issues' do
expect(permissions(visitor, issue)).to be_disallowed(:read_issue)
end
+
it 'forbids visitors from commenting' do
expect(permissions(visitor, issue)).to be_disallowed(:create_note)
end
+
it 'forbids visitors from subscribing' do
expect(permissions(visitor, issue)).to be_disallowed(:update_subscription)
end
+
it 'allows guests to view' do
expect(permissions(guest, issue)).to be_allowed(:read_issue)
end
+
it 'allows guests to comment' do
expect(permissions(guest, issue)).to be_allowed(:create_note)
end
+
it 'allows guests to subscribe' do
expect(permissions(guest, issue)).to be_allowed(:update_subscription)
end
@@ -454,7 +473,7 @@ RSpec.describe IssuePolicy do
end
end
- context 'when peronsal namespace' do
+ context 'when personal namespace' do
let(:project) { create(:project) }
it 'is disallowed' do
@@ -465,4 +484,34 @@ RSpec.describe IssuePolicy do
end
end
end
+
+ context 'when user is an inherited member from the group' do
+ let(:user) { create_user_from_membership(group, membership) }
+ let(:project) { create(:project, project_level, group: group) }
+ let(:issue) { create(:issue, project: project) }
+
+ context 'and policy allows guest access' do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
+ permission_table_for_guest_feature_access
+ end
+
+ with_them do
+ it_behaves_like 'grants the expected permissions', :read_issue
+ it_behaves_like 'grants the expected permissions', :read_issue_iid
+ end
+ end
+
+ context 'and policy allows reporter access' do
+ where(:project_level, :feature_access_level, :membership, :admin_mode, :expected_count) do
+ permission_table_for_reporter_issue_access
+ end
+
+ with_them do
+ it_behaves_like 'grants the expected permissions', :update_issue
+ it_behaves_like 'grants the expected permissions', :admin_issue
+ it_behaves_like 'grants the expected permissions', :set_issue_metadata
+ it_behaves_like 'grants the expected permissions', :set_confidentiality
+ end
+ end
+ end
end
diff --git a/spec/policies/namespaces/project_namespace_policy_spec.rb b/spec/policies/namespaces/project_namespace_policy_spec.rb
index 5ceea9dfb9d..4519f44a6ad 100644
--- a/spec/policies/namespaces/project_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/project_namespace_policy_spec.rb
@@ -3,45 +3,11 @@
require 'spec_helper'
RSpec.describe Namespaces::ProjectNamespacePolicy do
- let_it_be(:parent) { create(:namespace) }
- let_it_be(:project) { create(:project, namespace: parent) }
- let_it_be(:namespace) { project.project_namespace }
-
- let(:permissions) do
- [:owner_access, :create_projects, :admin_namespace, :read_namespace,
- :read_statistics, :transfer_projects, :admin_package,
- :create_jira_connect_subscription]
- end
-
subject { described_class.new(current_user, namespace) }
- context 'with no user' do
- let_it_be(:current_user) { nil }
-
- it { is_expected.to be_disallowed(*permissions) }
- end
-
- context 'regular user' do
- let_it_be(:current_user) { create(:user) }
-
- it { is_expected.to be_disallowed(*permissions) }
- end
-
- context 'parent owner' do
- let_it_be(:current_user) { parent.first_owner }
-
- it { is_expected.to be_disallowed(*permissions) }
- end
-
- context 'admin' do
- let_it_be(:current_user) { create(:admin) }
-
- context 'when admin mode is enabled', :enable_admin_mode do
- it { is_expected.to be_disallowed(*permissions) }
- end
-
- context 'when admin mode is disabled' do
- it { is_expected.to be_disallowed(*permissions) }
- end
+ it_behaves_like 'checks timelog categories permissions' do
+ let(:project) { create(:project) }
+ let(:namespace) { project.project_namespace }
+ let(:users_container) { project }
end
end
diff --git a/spec/policies/namespaces/user_namespace_policy_spec.rb b/spec/policies/namespaces/user_namespace_policy_spec.rb
index e8a3c9b828d..22c3f6a6d67 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, :maintain_namespace] }
+ let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects, :admin_package] }
subject { described_class.new(current_user, namespace) }
diff --git a/spec/policies/project_hook_policy_spec.rb b/spec/policies/project_hook_policy_spec.rb
new file mode 100644
index 00000000000..cfa7b6ee4bf
--- /dev/null
+++ b/spec/policies/project_hook_policy_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProjectHookPolicy do
+ let_it_be(:user) { create(:user) }
+
+ let(:hook) { create(:project_hook) }
+
+ subject(:policy) { described_class.new(user, hook) }
+
+ context 'when the user is not a maintainer' do
+ before do
+ hook.project.add_developer(user)
+ end
+
+ it "cannot read and destroy web-hooks" do
+ expect(policy).to be_disallowed(:read_web_hook, :destroy_web_hook)
+ end
+ end
+
+ context 'when the user is a maintainer' do
+ before do
+ hook.project.add_maintainer(user)
+ end
+
+ it "can read and destroy web-hooks" do
+ expect(policy).to be_allowed(:read_web_hook, :destroy_web_hook)
+ end
+ end
+end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index c041c72a0be..e8fdf9a8e25 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1930,6 +1930,10 @@ RSpec.describe ProjectPolicy do
describe 'operations feature' do
using RSpec::Parameterized::TableSyntax
+ before do
+ stub_feature_flags(split_operations_visibility_permissions: false)
+ end
+
let(:guest_operations_permissions) { [:read_environment, :read_deployment] }
let(:developer_operations_permissions) do
@@ -2002,38 +2006,234 @@ RSpec.describe ProjectPolicy do
end
end
- def project_subject(project_type)
- case project_type
- when :public
- public_project
- when :internal
- internal_project
+ def permissions_abilities(role)
+ case role
+ when :maintainer
+ maintainer_operations_permissions
+ when :developer
+ developer_operations_permissions
else
- private_project
+ guest_operations_permissions
end
end
+ end
+ end
- def user_subject(role)
- case role
- when :maintainer
- maintainer
- when :developer
- developer
- when :guest
- guest
- when :anonymous
- anonymous
+ describe 'environments feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_environments_permissions) { [:read_environment, :read_deployment] }
+
+ let(:developer_environments_permissions) do
+ guest_environments_permissions + [
+ :create_environment, :create_deployment, :update_environment, :update_deployment, :destroy_environment
+ ]
+ end
+
+ let(:maintainer_environments_permissions) do
+ developer_environments_permissions + [:admin_environment, :admin_deployment]
+ end
+
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | false
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | false
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { user_subject(role) }
+ let(:project) { project_subject(project_visibility) }
+
+ it 'allows/disallows the abilities based on the environments feature access level' do
+ project.project_feature.update!(environments_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
end
end
def permissions_abilities(role)
case role
when :maintainer
- maintainer_operations_permissions
+ maintainer_environments_permissions
when :developer
- developer_operations_permissions
+ developer_environments_permissions
else
- guest_operations_permissions
+ guest_environments_permissions
+ end
+ end
+ end
+ end
+
+ describe 'feature flags feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_permissions) { [] }
+
+ let(:developer_permissions) do
+ guest_permissions + [
+ :read_feature_flag, :create_feature_flag, :update_feature_flag, :destroy_feature_flag, :admin_feature_flag,
+ :admin_feature_flags_user_lists
+ ]
+ end
+
+ let(:maintainer_permissions) do
+ developer_permissions + [:admin_feature_flags_client]
+ end
+
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | false
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | false
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { user_subject(role) }
+ let(:project) { project_subject(project_visibility) }
+
+ it 'allows/disallows the abilities based on the feature flags access level' do
+ project.project_feature.update!(feature_flags_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
+ end
+ end
+ end
+ end
+
+ describe 'Releases feature' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:guest_permissions) { [:read_release] }
+
+ let(:developer_permissions) do
+ guest_permissions + [:create_release, :update_release, :destroy_release]
+ end
+
+ let(:maintainer_permissions) do
+ developer_permissions
+ end
+
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | true
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | true
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+
+ with_them do
+ let(:current_user) { user_subject(role) }
+ let(:project) { project_subject(project_visibility) }
+
+ it 'allows/disallows the abilities based on the Releases access level' do
+ project.project_feature.update!(releases_access_level: access_level)
+
+ if allowed
+ expect_allowed(*permissions_abilities(role))
+ else
+ expect_disallowed(*permissions_abilities(role))
end
end
end
@@ -2481,4 +2681,39 @@ RSpec.describe ProjectPolicy do
end
end
end
+
+ def project_subject(project_type)
+ case project_type
+ when :public
+ public_project
+ when :internal
+ internal_project
+ else
+ private_project
+ end
+ end
+
+ def user_subject(role)
+ case role
+ when :maintainer
+ maintainer
+ when :developer
+ developer
+ when :guest
+ guest
+ when :anonymous
+ anonymous
+ end
+ end
+
+ def permissions_abilities(role)
+ case role
+ when :maintainer
+ maintainer_permissions
+ when :developer
+ developer_permissions
+ else
+ guest_permissions
+ end
+ end
end
diff --git a/spec/policies/system_hook_policy_spec.rb b/spec/policies/system_hook_policy_spec.rb
new file mode 100644
index 00000000000..37f97a8a3d1
--- /dev/null
+++ b/spec/policies/system_hook_policy_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe SystemHookPolicy do
+ let(:hook) { create(:system_hook) }
+
+ subject(:policy) { described_class.new(user, hook) }
+
+ context 'when the user is not an admin' do
+ let(:user) { create(:user) }
+
+ %i[read_web_hook destroy_web_hook].each do |thing|
+ it "cannot #{thing}" do
+ expect(policy).to be_disallowed(thing)
+ end
+ end
+ end
+
+ context 'when the user is an admin', :enable_admin_mode do
+ let(:user) { create(:admin) }
+
+ %i[read_web_hook destroy_web_hook].each do |thing|
+ it "can #{thing}" do
+ expect(policy).to be_allowed(thing)
+ end
+ end
+ end
+end
diff --git a/spec/policies/timelog_policy_spec.rb b/spec/policies/timelog_policy_spec.rb
index 97e61cfe5ce..31912c637ce 100644
--- a/spec/policies/timelog_policy_spec.rb
+++ b/spec/policies/timelog_policy_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe TimelogPolicy, models: true do
let_it_be(:author) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
+ let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
let(:user) { nil }
let(:policy) { described_class.new(user, timelog) }
diff --git a/spec/policies/upload_policy_spec.rb b/spec/policies/upload_policy_spec.rb
new file mode 100644
index 00000000000..1169df0b300
--- /dev/null
+++ b/spec/policies/upload_policy_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UploadPolicy do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:guest) { create(:user).tap { |user| group.add_guest(user) } }
+ let_it_be(:developer) { create(:user).tap { |user| group.add_developer(user) } }
+ let_it_be(:maintainer) { create(:user).tap { |user| group.add_maintainer(user) } }
+ let_it_be(:owner) { create(:user).tap { |user| group.add_owner(user) } }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:non_member_user) { create(:user) }
+
+ let(:upload_permissions) { [:read_upload, :destroy_upload] }
+
+ shared_examples_for 'uploads policy' do
+ subject { described_class.new(current_user, upload) }
+
+ context 'when user is guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(*upload_permissions) }
+ end
+
+ context 'when user is developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_disallowed(*upload_permissions) }
+ end
+
+ context 'when user is maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(*upload_permissions) }
+ end
+
+ context 'when user is owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(*upload_permissions) }
+ end
+
+ context 'when user is admin' do
+ let(:current_user) { admin }
+
+ it { is_expected.to be_disallowed(*upload_permissions) }
+
+ context 'with admin mode', :enable_admin_mode do
+ it { is_expected.to be_allowed(*upload_permissions) }
+ end
+ end
+ end
+
+ describe 'destroy_upload' do
+ context 'when deleting project upload' do
+ let_it_be(:upload) { create(:upload, model: project) }
+
+ it_behaves_like 'uploads policy'
+ end
+
+ context 'when deleting group upload' do
+ let_it_be(:upload) { create(:upload, model: group) }
+
+ it_behaves_like 'uploads policy'
+ end
+
+ context 'when deleting upload associated with other model' do
+ let_it_be(:upload) { create(:upload, model: maintainer) }
+
+ subject { described_class.new(maintainer, upload) }
+
+ it { is_expected.to be_disallowed(*upload_permissions) }
+ end
+ end
+end
diff --git a/spec/policies/work_item_policy_spec.rb b/spec/policies/work_item_policy_spec.rb
index f8ec7d9f9bc..ed76ec1eccf 100644
--- a/spec/policies/work_item_policy_spec.rb
+++ b/spec/policies/work_item_policy_spec.rb
@@ -63,6 +63,27 @@ RSpec.describe WorkItemPolicy do
end
end
+ describe 'admin_work_item' do
+ context 'when user is reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:admin_work_item) }
+ end
+
+ context 'when user is guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:admin_work_item) }
+
+ context 'when guest authored the work item' do
+ let(:work_item_subject) { authored_work_item }
+ let(:current_user) { guest_author }
+
+ it { is_expected.to be_disallowed(:admin_work_item) }
+ end
+ end
+ end
+
describe 'update_work_item' do
context 'when user is reporter' do
let(:current_user) { reporter }
@@ -160,4 +181,24 @@ RSpec.describe WorkItemPolicy do
end
end
end
+
+ describe 'set_work_item_metadata' do
+ context 'when user is reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_allowed(:set_work_item_metadata) }
+ end
+
+ context 'when user is guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:set_work_item_metadata) }
+
+ context 'when the work item is not persisted yet' do
+ let(:work_item_subject) { build(:work_item, project: project) }
+
+ it { is_expected.to be_allowed(:set_work_item_metadata) }
+ end
+ end
+ end
end
diff --git a/spec/presenters/alert_management/alert_presenter_spec.rb b/spec/presenters/alert_management/alert_presenter_spec.rb
index 21c0cb3fead..fe228f174fe 100644
--- a/spec/presenters/alert_management/alert_presenter_spec.rb
+++ b/spec/presenters/alert_management/alert_presenter_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe AlertManagement::AlertPresenter do
it 'formats the start time of the alert' do
alert.started_at = Time.utc(2019, 5, 5)
- expect(presenter.start_time). to eq('05 May 2019, 12:00AM (UTC)')
+ expect(presenter.start_time).to eq('05 May 2019, 12:00AM (UTC)')
end
end
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index ace65307321..fe2d8f0f670 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -309,25 +309,64 @@ RSpec.describe Ci::BuildRunnerPresenter do
end
describe '#runner_variables' do
- subject { presenter.runner_variables }
+ subject(:runner_variables) { presenter.runner_variables }
let_it_be(:project) { create(:project, :repository) }
- shared_examples 'returns an array with the expected variables' do
- it 'returns an array' do
- is_expected.to be_an_instance_of(Array)
+ let(:sha) { project.repository.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it 'returns an array' do
+ is_expected.to be_an_instance_of(Array)
+ end
+
+ it 'returns the expected variables' do
+ is_expected.to eq(presenter.variables.to_runner_variables)
+ end
+
+ context 'when there are variables to expand' do
+ before_all do
+ create(:ci_variable, project: project,
+ key: 'regular_var',
+ value: 'value 1')
+ create(:ci_variable, project: project,
+ key: 'file_var',
+ value: 'value 2',
+ variable_type: :file)
+ create(:ci_variable, project: project,
+ key: 'var_with_variables',
+ value: 'value 3 and $regular_var and $file_var and $undefined_var')
end
- it 'returns the expected variables' do
- is_expected.to eq(presenter.variables.to_runner_variables)
+ it 'returns variables with expanded' do
+ expect(runner_variables).to include(
+ { key: 'regular_var', value: 'value 1',
+ public: false, masked: false },
+ { key: 'file_var', value: 'value 2',
+ public: false, masked: false, file: true },
+ { key: 'var_with_variables', value: 'value 3 and value 1 and $file_var and $undefined_var',
+ public: false, masked: false }
+ )
end
- end
- let(:sha) { project.repository.commit.sha }
- let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
+ 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)
+ end
- it_behaves_like 'returns an array with the expected variables'
+ it 'returns variables with expanded' do
+ expect(runner_variables).to include(
+ { key: 'regular_var', value: 'value 1',
+ public: false, masked: false },
+ { key: 'file_var', value: 'value 2',
+ public: false, masked: false, file: true },
+ { key: 'var_with_variables', value: 'value 3 and value 1 and value 2 and $undefined_var',
+ public: false, masked: false }
+ )
+ end
+ end
+ end
end
describe '#runner_variables subset' do
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 798bee70e42..31aa4778d3c 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -17,29 +17,8 @@ RSpec.describe MergeRequestPresenter do
allow(resource).to receive(:mergeable_discussions_state?).and_return(discussions_state)
end
- context 'when change_response_code_merge_status is enabled' do
- it 'returns the mergeable_discussions_state' do
- is_expected.to eq(discussions_state)
- end
- end
-
- context 'when change_response_code_merge_status is disabled' do
- before do
- stub_feature_flags(change_response_code_merge_status: false)
- end
-
- context 'when it is not mergeable' do
- it 'returns false' do
- resource.close!
- is_expected.to eq(false)
- end
- end
-
- context 'when it is mergeable' do
- it 'returns the mergeable_discussions_state' do
- is_expected.to eq(discussions_state)
- end
- end
+ it 'returns the mergeable_discussions_state' do
+ is_expected.to eq(discussions_state)
end
end
diff --git a/spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb b/spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb
index be454e5168c..c966b1fc8e1 100644
--- a/spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb
+++ b/spec/presenters/packages/pypi/simple_package_versions_presenter_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe ::Packages::Pypi::SimplePackageVersionsPresenter, :aggregate_fail
let(:project_or_group) { project }
- it { is_expected.not_to include(package_file_pending_destruction.file_name)}
+ it { is_expected.not_to include(package_file_pending_destruction.file_name) }
end
end
end
diff --git a/spec/presenters/project_hook_presenter_spec.rb b/spec/presenters/project_hook_presenter_spec.rb
index 2e4bd17bbe1..a85865652d8 100644
--- a/spec/presenters/project_hook_presenter_spec.rb
+++ b/spec/presenters/project_hook_presenter_spec.rb
@@ -18,10 +18,10 @@ RSpec.describe ProjectHookPresenter do
end
describe '#logs_retry_path' do
- subject { web_hook.present.logs_details_path(web_hook_log) }
+ subject { web_hook.present.logs_retry_path(web_hook_log) }
let(:expected_path) do
- "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}"
+ "/#{project.namespace.path}/#{project.name}/-/hooks/#{web_hook.id}/hook_logs/#{web_hook_log.id}/retry"
end
it { is_expected.to eq(expected_path) }
diff --git a/spec/presenters/project_member_presenter_spec.rb b/spec/presenters/project_member_presenter_spec.rb
index ad45a23c183..1cfc8cfb53b 100644
--- a/spec/presenters/project_member_presenter_spec.rb
+++ b/spec/presenters/project_member_presenter_spec.rb
@@ -55,39 +55,95 @@ RSpec.describe ProjectMemberPresenter do
end
describe '#can_update?' do
- context 'when user can update_project_member' do
+ context 'when user is NOT attempting to update an Owner' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(true)
+ allow(project_member).to receive(:owner?).and_return(false)
end
- it { expect(presenter.can_update?).to eq(true) }
+ context 'when user can update_project_member' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(true)
+ end
+
+ specify { expect(presenter.can_update?).to eq(true) }
+ end
+
+ context 'when user cannot update_project_member' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(false)
+ allow(presenter).to receive(:can?).with(user, :override_project_member, presenter).and_return(false)
+ end
+
+ specify { expect(presenter.can_update?).to eq(false) }
+ end
end
- context 'when user cannot update_project_member' do
+ context 'when user is attempting to update an Owner' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(false)
- allow(presenter).to receive(:can?).with(user, :override_project_member, presenter).and_return(false)
+ allow(project_member).to receive(:owner?).and_return(true)
+ end
+
+ context 'when user can manage owners' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :manage_owners, project).and_return(true)
+ end
+
+ specify { expect(presenter.can_update?).to eq(true) }
end
- it { expect(presenter.can_update?).to eq(false) }
+ context 'when user cannot manage owners' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :manage_owners, project).and_return(false)
+ end
+
+ specify { expect(presenter.can_update?).to eq(false) }
+ end
end
end
describe '#can_remove?' do
- context 'when user can destroy_project_member' do
+ context 'when user is NOT attempting to remove an Owner' do
before do
- allow(presenter).to receive(:can?).with(user, :destroy_project_member, presenter).and_return(true)
+ allow(project_member).to receive(:owner?).and_return(false)
end
- it { expect(presenter.can_remove?).to eq(true) }
+ context 'when user can destroy_project_member' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :destroy_project_member, presenter).and_return(true)
+ end
+
+ specify { expect(presenter.can_remove?).to eq(true) }
+ end
+
+ context 'when user cannot destroy_project_member' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :destroy_project_member, presenter).and_return(false)
+ end
+
+ specify { expect(presenter.can_remove?).to eq(false) }
+ end
end
- context 'when user cannot destroy_project_member' do
+ context 'when user is attempting to remove an Owner' do
before do
- allow(presenter).to receive(:can?).with(user, :destroy_project_member, presenter).and_return(false)
+ allow(project_member).to receive(:owner?).and_return(true)
+ end
+
+ context 'when user can manage owners' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :manage_owners, project).and_return(true)
+ end
+
+ specify { expect(presenter.can_remove?).to eq(true) }
end
- it { expect(presenter.can_remove?).to eq(false) }
+ context 'when user cannot manage owners' do
+ before do
+ allow(presenter).to receive(:can?).with(user, :manage_owners, project).and_return(false)
+ end
+
+ specify { expect(presenter.can_remove?).to eq(false) }
+ end
end
end
@@ -99,7 +155,7 @@ RSpec.describe ProjectMemberPresenter do
context 'and user can update_project_member' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(true)
+ allow(presenter).to receive(:can_update?).and_return(true)
end
it { expect(presenter.can_approve?).to eq(true) }
@@ -107,8 +163,7 @@ RSpec.describe ProjectMemberPresenter do
context 'and user cannot update_project_member' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(false)
- allow(presenter).to receive(:can?).with(user, :override_project_member, presenter).and_return(false)
+ allow(presenter).to receive(:can_update?).and_return(false)
end
it { expect(presenter.can_approve?).to eq(false) }
@@ -122,7 +177,7 @@ RSpec.describe ProjectMemberPresenter do
context 'and user can update_project_member' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(true)
+ allow(presenter).to receive(:can_update?).and_return(true)
end
it { expect(presenter.can_approve?).to eq(false) }
@@ -130,7 +185,7 @@ RSpec.describe ProjectMemberPresenter do
context 'and user cannot update_project_member' do
before do
- allow(presenter).to receive(:can?).with(user, :update_project_member, presenter).and_return(false)
+ allow(presenter).to receive(:can_update?).and_return(false)
end
it { expect(presenter.can_approve?).to eq(false) }
@@ -138,9 +193,32 @@ RSpec.describe ProjectMemberPresenter do
end
end
- it_behaves_like '#valid_level_roles', :project do
+ describe 'valid level roles' do
before do
- entity.group = group
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(member_user, :manage_owners, entity).and_return(can_manage_owners)
+ end
+
+ context 'when user cannot manage owners' do
+ it_behaves_like '#valid_level_roles', :project do
+ let(:expected_roles) { { 'Developer' => 30, 'Maintainer' => 40, 'Reporter' => 20 } }
+ let(:can_manage_owners) { false }
+
+ before do
+ entity.group = group
+ end
+ end
+ end
+
+ context 'when user can manage owners' do
+ it_behaves_like '#valid_level_roles', :project do
+ let(:expected_roles) { { 'Developer' => 30, 'Maintainer' => 40, 'Owner' => 50, 'Reporter' => 20 } }
+ let(:can_manage_owners) { true }
+
+ before do
+ entity.group = group
+ end
+ end
end
end
end
diff --git a/spec/requests/admin/broadcast_messages_controller_spec.rb b/spec/requests/admin/broadcast_messages_controller_spec.rb
new file mode 100644
index 00000000000..9101370d42d
--- /dev/null
+++ b/spec/requests/admin/broadcast_messages_controller_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::BroadcastMessagesController, :enable_admin_mode do
+ before do
+ sign_in(create(:admin))
+ end
+
+ describe 'POST /preview' do
+ it 'renders preview partial' do
+ post preview_admin_broadcast_messages_path, params: { broadcast_message: { message: "Hello, world!" } }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to render_template(:_preview)
+ end
+ end
+end
diff --git a/spec/requests/admin/integrations_controller_spec.rb b/spec/requests/admin/integrations_controller_spec.rb
index cfb40063095..128aada0975 100644
--- a/spec/requests/admin/integrations_controller_spec.rb
+++ b/spec/requests/admin/integrations_controller_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe Admin::IntegrationsController, :enable_admin_mode do
expect(response).to include_pagination_headers
expect(json_response).to contain_exactly(
{
+ 'id' => project.id,
'avatar_url' => project.avatar_url,
'full_name' => project.full_name,
'name' => project.name,
diff --git a/spec/requests/api/api_spec.rb b/spec/requests/api/api_spec.rb
index b6cb790bb71..260f7cbc226 100644
--- a/spec/requests/api/api_spec.rb
+++ b/spec/requests/api/api_spec.rb
@@ -262,4 +262,54 @@ RSpec.describe API::API do
end
end
end
+
+ describe 'content security policy header' do
+ let_it_be(:user) { create(:user) }
+
+ let(:csp) { nil }
+ let(:report_only) { false }
+
+ subject { get api("/users/#{user.id}", user) }
+
+ before do
+ allow(Rails.application.config).to receive(:content_security_policy).and_return(csp)
+ allow(Rails.application.config).to receive(:content_security_policy_report_only).and_return(report_only)
+ end
+
+ context 'when CSP is not configured globally' do
+ it 'does not set the CSP header' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['Content-Security-Policy']).to be_nil
+ end
+ end
+
+ context 'when CSP is configured globally' do
+ let(:csp) do
+ ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.default_src :self
+ end
+ end
+
+ it 'sets a stricter CSP header' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['Content-Security-Policy']).to eq("default-src 'none'")
+ end
+
+ context 'when report_only is true' do
+ let(:report_only) { true }
+
+ it 'does not set any CSP header' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['Content-Security-Policy']).to be_nil
+ expect(response.headers['Content-Security-Policy-Report-Only']).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index ca6492396cd..817e1324c7c 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -57,9 +57,11 @@ RSpec.describe API::Boards do
let(:url) { "/projects/#{board_parent.id}/boards/#{board.id}" }
it 'delete the issue board' do
- delete api(url, user)
+ expect do
+ delete api(url, user)
- expect(response).to have_gitlab_http_status(:no_content)
+ expect(response).to have_gitlab_http_status(:no_content)
+ end.to change { board_parent.boards.count }.by(-1)
end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 780e45cf443..cc696d76a02 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe API::Branches do
let_it_be(:user) { create(:user) }
- let(:project) { create(:project, :repository, creator: user, path: 'my.project') }
+ let(:project) { create(:project, :repository, creator: user, path: 'my.project', create_branch: 'ends-with.txt') }
let(:guest) { create(:user).tap { |u| project.add_guest(u) } }
let(:branch_name) { 'feature' }
let(:branch_sha) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
@@ -17,7 +17,6 @@ RSpec.describe API::Branches do
before do
project.add_maintainer(user)
- project.repository.add_branch(user, 'ends-with.txt', branch_sha)
stub_feature_flags(branch_list_keyset_pagination: false)
end
@@ -201,7 +200,7 @@ RSpec.describe API::Branches do
context 'when sort value is not supported' do
it_behaves_like '400 response' do
- let(:request) { get api(route, user), params: { sort: 'unknown' }}
+ let(:request) { get api(route, user), params: { sort: 'unknown' } }
end
end
end
diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb
index 9f9907f4f00..6a3d13567bd 100644
--- a/spec/requests/api/bulk_imports_spec.rb
+++ b/spec/requests/api/bulk_imports_spec.rb
@@ -53,23 +53,80 @@ RSpec.describe API::BulkImports do
end
end
- it 'starts a new migration' do
- post api('/bulk_imports', user), params: {
- configuration: {
- url: 'http://gitlab.example',
- access_token: 'access_token'
- },
- entities: [
- source_type: 'group_entity',
- source_full_path: 'full_path',
- destination_name: 'destination_slug',
- destination_namespace: 'destination_namespace'
- ]
- }
-
- expect(response).to have_gitlab_http_status(:created)
-
- expect(json_response['status']).to eq('created')
+ shared_examples 'starting a new migration' do
+ it 'starts a new migration' do
+ post api('/bulk_imports', user), params: {
+ configuration: {
+ url: 'http://gitlab.example',
+ access_token: 'access_token'
+ },
+ entities: [
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full_path',
+ destination_namespace: 'destination_namespace'
+ }.merge(destination_param)
+ ]
+ }
+
+ expect(response).to have_gitlab_http_status(:created)
+
+ expect(json_response['status']).to eq('created')
+ end
+ end
+
+ include_examples 'starting a new migration' do
+ let(:destination_param) { { destination_slug: 'destination_slug' } }
+ end
+
+ include_examples 'starting a new migration' do
+ let(:destination_param) { { destination_name: 'destination_name' } }
+ end
+
+ context 'when both destination_name & destination_slug are provided' do
+ it 'returns a mutually exclusive error' do
+ post api('/bulk_imports', user), params: {
+ configuration: {
+ url: 'http://gitlab.example',
+ access_token: 'access_token'
+ },
+ entities: [
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full_path',
+ destination_name: 'destination_name',
+ destination_slug: 'destination_slug',
+ destination_namespace: 'destination_namespace'
+ }
+ ]
+ }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+
+ expect(json_response['error']).to eq('entities[0][destination_slug], entities[0][destination_name] are mutually exclusive')
+ end
+ end
+
+ context 'when neither destination_name nor destination_slug is provided' do
+ it 'returns at_least_one_of error' do
+ post api('/bulk_imports', user), params: {
+ configuration: {
+ url: 'http://gitlab.example',
+ access_token: 'access_token'
+ },
+ entities: [
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full_path',
+ destination_namespace: 'destination_namespace'
+ }
+ ]
+ }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+
+ expect(json_response['error']).to eq('entities[0][destination_slug], entities[0][destination_name] are missing, at least one parameter must be provided')
+ end
end
context 'when provided url is blocked' do
@@ -82,7 +139,7 @@ RSpec.describe API::BulkImports do
entities: [
source_type: 'group_entity',
source_full_path: 'full_path',
- destination_name: 'destination_slug',
+ destination_slug: 'destination_slug',
destination_namespace: 'destination_namespace'
]
}
diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb
index 84ef9f8db1b..57828e50320 100644
--- a/spec/requests/api/ci/jobs_spec.rb
+++ b/spec/requests/api/ci/jobs_spec.rb
@@ -158,7 +158,7 @@ RSpec.describe API::Ci::Jobs do
context 'with basic auth header' do
let(:personal_access_token) { create(:personal_access_token, user: user) }
- let(:token) { personal_access_token.token}
+ let(:token) { personal_access_token.token }
include_context 'with auth headers' do
let(:header) { { Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => token } }
diff --git a/spec/requests/api/ci/pipeline_schedules_spec.rb b/spec/requests/api/ci/pipeline_schedules_spec.rb
index 5fb94976c5f..30badadde13 100644
--- a/spec/requests/api/ci/pipeline_schedules_spec.rb
+++ b/spec/requests/api/ci/pipeline_schedules_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe API::Ci::PipelineSchedules do
end
matcher :return_pipeline_schedule_sucessfully do
- match_unless_raises do |reponse|
+ match_unless_raises do |response|
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('pipeline_schedule')
end
@@ -207,6 +207,110 @@ RSpec.describe API::Ci::PipelineSchedules do
end
end
+ describe 'GET /projects/:id/pipeline_schedules/:pipeline_schedule_id/pipelines' do
+ let(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer) }
+
+ before do
+ create_list(:ci_pipeline, 2, project: project, pipeline_schedule: pipeline_schedule, source: :schedule)
+ end
+
+ let(:url) { "/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}/pipelines" }
+
+ matcher :return_pipeline_schedule_pipelines_successfully do
+ match_unless_raises do |reponse|
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/pipelines')
+ end
+ end
+
+ shared_examples 'request with project permissions' do
+ context 'authenticated user with project permissions' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns the details of pipelines triggered from the pipeline schedule' do
+ get api(url, user)
+
+ expect(response).to return_pipeline_schedule_pipelines_successfully
+ end
+ end
+ end
+
+ shared_examples 'request with schedule ownership' do
+ context 'authenticated user with pipeline schedule ownership' do
+ it 'returns the details of pipelines triggered from the pipeline schedule' do
+ get api(url, developer)
+
+ expect(response).to return_pipeline_schedule_pipelines_successfully
+ end
+ end
+ end
+
+ shared_examples 'request with unauthenticated user' do
+ context 'with unauthenticated user' do
+ it 'does not return the details of pipelines triggered from the pipeline schedule' do
+ get api(url)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ shared_examples 'request with non-existing pipeline_schedule' do
+ it "responds with 404 Not Found if requesting for a non-existing pipeline schedule's pipelines" do
+ get api("/projects/#{project.id}/pipeline_schedules/#{non_existing_record_id}/pipelines", developer)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'with private project' do
+ it_behaves_like 'request with schedule ownership'
+ it_behaves_like 'request with project permissions'
+ it_behaves_like 'request with unauthenticated user'
+ it_behaves_like 'request with non-existing pipeline_schedule'
+
+ context 'authenticated user with no project permissions' do
+ it 'does not return the details of pipelines triggered from the pipeline schedule' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'authenticated user with insufficient project permissions' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'does not return the details of pipelines triggered from the pipeline schedule' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'with public project' do
+ let_it_be(:project) { create(:project, :repository, :public, public_builds: false) }
+
+ it_behaves_like 'request with schedule ownership'
+ it_behaves_like 'request with project permissions'
+ it_behaves_like 'request with unauthenticated user'
+ it_behaves_like 'request with non-existing pipeline_schedule'
+
+ context 'authenticated user with no project permissions' do
+ it 'returns the details of pipelines triggered from the pipeline schedule' do
+ get api(url, user)
+
+ expect(response).to return_pipeline_schedule_pipelines_successfully
+ end
+ end
+ end
+ end
+
describe 'POST /projects/:id/pipeline_schedules' do
let(:params) { attributes_for(:ci_pipeline_schedule) }
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 746be1ccc44..cd58251cfcc 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
describe 'POST /api/v4/jobs/request' do
let!(:last_update) {}
- let!(:new_update) { }
+ let!(:new_update) {}
let(:user_agent) { 'gitlab-runner 9.0.0 (9-0-stable; go1.7.4; linux/amd64)' }
before do
diff --git a/spec/requests/api/ci/runner/jobs_trace_spec.rb b/spec/requests/api/ci/runner/jobs_trace_spec.rb
index c3c074d80d9..d42043a7fe5 100644
--- a/spec/requests/api/ci/runner/jobs_trace_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_trace_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_trace_chunks do
end
context 'when job has been updated recently' do
- it { expect { patch_the_trace }.not_to change { job.updated_at }}
+ it { expect { patch_the_trace }.not_to change { job.updated_at } }
it "changes the job's trace" do
patch_the_trace
@@ -70,7 +70,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_trace_chunks do
end
context 'when Runner makes a force-patch' do
- it { expect { force_patch_the_trace }.not_to change { job.updated_at }}
+ it { expect { force_patch_the_trace }.not_to change { job.updated_at } }
it "doesn't change the build.trace" do
force_patch_the_trace
diff --git a/spec/requests/api/ci/runner/runners_post_spec.rb b/spec/requests/api/ci/runner/runners_post_spec.rb
index 50ace7adccb..47302046865 100644
--- a/spec/requests/api/ci/runner/runners_post_spec.rb
+++ b/spec/requests/api/ci/runner/runners_post_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context 'when invalid token is provided' do
it 'returns 403 error' do
allow_next_instance_of(::Ci::Runners::RegisterRunnerService) do |service|
- allow(service).to receive(:execute).and_return(nil)
+ allow(service).to receive(:execute)
+ .and_return(ServiceResponse.error(message: 'invalid token supplied', http_status: :forbidden))
end
post api('/runners'), params: { token: 'invalid' }
@@ -58,7 +59,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(service).to receive(:execute)
.once
.with('valid token', a_hash_including(expected_params))
- .and_return(new_runner)
+ .and_return(ServiceResponse.success(payload: { runner: new_runner }))
end
end
@@ -113,7 +114,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
.once
.with('valid token', a_hash_including('maintenance_note' => 'Some maintainer notes')
.and(excluding('maintainter_note' => anything)))
- .and_return(new_runner)
+ .and_return(ServiceResponse.success(payload: { runner: new_runner }))
end
request
@@ -139,7 +140,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(service).to receive(:execute)
.once
.with('valid token', a_hash_including(expected_params))
- .and_return(new_runner)
+ .and_return(ServiceResponse.success(payload: { runner: new_runner }))
end
request
diff --git a/spec/requests/api/ci/secure_files_spec.rb b/spec/requests/api/ci/secure_files_spec.rb
index 6f16fe5460b..f1f22dfadc2 100644
--- a/spec/requests/api/ci/secure_files_spec.rb
+++ b/spec/requests/api/ci/secure_files_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe API::Ci::SecureFiles do
expect do
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
- end.not_to change {project.secure_files.count}
+ end.not_to change { project.secure_files.count }
expect(response).to have_gitlab_http_status(:service_unavailable)
end
@@ -78,7 +78,7 @@ RSpec.describe API::Ci::SecureFiles do
it 'returns a 201 when uploading a file when the ci_secure_files_read_only feature flag is disabled' do
expect do
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
- end.to change {project.secure_files.count}.by(1)
+ end.to change { project.secure_files.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
end
@@ -249,7 +249,7 @@ RSpec.describe API::Ci::SecureFiles do
it 'creates a secure file' do
expect do
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
- end.to change {project.secure_files.count}.by(1)
+ end.to change { project.secure_files.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['name']).to eq('upload-keystore.jks')
diff --git a/spec/requests/api/ci/triggers_spec.rb b/spec/requests/api/ci/triggers_spec.rb
index a036a55f5f3..953dcb8a483 100644
--- a/spec/requests/api/ci/triggers_spec.rb
+++ b/spec/requests/api/ci/triggers_spec.rb
@@ -136,8 +136,8 @@ RSpec.describe API::Ci::Triggers do
end
context 'when triggered from another running job' do
- let!(:trigger) { }
- let!(:trigger_request) { }
+ let!(:trigger) {}
+ let!(:trigger_request) {}
context 'when other job is triggered by a user' do
let(:trigger_token) { create(:ci_build, :running, project: project, user: user).token }
@@ -242,7 +242,7 @@ RSpec.describe API::Ci::Triggers do
expect do
post api("/projects/#{project.id}/triggers", user),
params: { description: 'trigger' }
- end.to change {project.triggers.count}.by(1)
+ end.to change { project.triggers.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to include('description' => 'trigger')
@@ -335,7 +335,7 @@ RSpec.describe API::Ci::Triggers do
delete api("/projects/#{project.id}/triggers/#{trigger.id}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.triggers.count}.by(-1)
+ end.to change { project.triggers.count }.by(-1)
end
it 'responds with 404 Not Found if requesting non-existing trigger' do
diff --git a/spec/requests/api/ci/variables_spec.rb b/spec/requests/api/ci/variables_spec.rb
index dc524e121d5..74ed8c1551d 100644
--- a/spec/requests/api/ci/variables_spec.rb
+++ b/spec/requests/api/ci/variables_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe API::Ci::Variables do
it 'creates variable' do
expect do
post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
- end.to change {project.variables.count}.by(1)
+ end.to change { project.variables.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
@@ -129,7 +129,7 @@ RSpec.describe API::Ci::Variables do
it 'creates variable with optional attributes' do
expect do
post api("/projects/#{project.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
- end.to change {project.variables.count}.by(1)
+ end.to change { project.variables.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
@@ -142,7 +142,7 @@ RSpec.describe API::Ci::Variables do
it 'does not allow to duplicate variable key' do
expect do
post api("/projects/#{project.id}/variables", user), params: { key: variable.key, value: 'VALUE_2' }
- end.to change {project.variables.count}.by(0)
+ end.to change { project.variables.count }.by(0)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -268,7 +268,7 @@ RSpec.describe API::Ci::Variables do
delete api("/projects/#{project.id}/variables/#{variable.key}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.variables.count}.by(-1)
+ end.to change { project.variables.count }.by(-1)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
@@ -295,7 +295,7 @@ RSpec.describe API::Ci::Variables do
delete api("/projects/#{project.id}/variables/key1", user), params: { 'filter[environment_scope]': 'production' }
expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.variables.count}.by(-1)
+ end.to change { project.variables.count }.by(-1)
expect(var1.reload).to be_present
expect { var2.reload }.to raise_error(ActiveRecord::RecordNotFound)
diff --git a/spec/requests/api/clusters/agents_spec.rb b/spec/requests/api/clusters/agents_spec.rb
index 72d4266b9e3..5e3bdd69529 100644
--- a/spec/requests/api/clusters/agents_spec.rb
+++ b/spec/requests/api/clusters/agents_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe API::Clusters::Agents do
expect do
post(api("/projects/#{project.id}/cluster_agents", user),
params: { name: 'some-agent' })
- end.to change {project.cluster_agents.count}.by(1)
+ end.to change { project.cluster_agents.count }.by(1)
aggregate_failures "testing response" do
expect(response).to have_gitlab_http_status(:created)
@@ -139,7 +139,7 @@ RSpec.describe API::Clusters::Agents do
delete api("/projects/#{project.id}/cluster_agents/#{agent.id}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.cluster_agents.count}.by(-1)
+ end.to change { project.cluster_agents.count }.by(-1)
end
it 'returns a 404 error when deleting non existent agent' do
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 9ef845f06bf..68fe45cd026 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -206,11 +206,13 @@ RSpec.describe API::Commits do
let(:page) { 1 }
let(:per_page) { 5 }
let(:ref_name) { 'master' }
- let!(:request) do
+ let(:request) do
get api("/projects/#{project_id}/repository/commits?page=#{page}&per_page=#{per_page}&ref_name=#{ref_name}", user)
end
it 'returns correct headers' do
+ request
+
expect(response).to include_limited_pagination_headers
expect(response.headers['Link']).to match(/page=1&per_page=5/)
expect(response.headers['Link']).to match(/page=2&per_page=5/)
@@ -218,6 +220,8 @@ RSpec.describe API::Commits do
context 'viewing the first page' do
it 'returns the first 5 commits' do
+ request
+
commit = project.repository.commit
expect(json_response.size).to eq(per_page)
@@ -230,6 +234,8 @@ RSpec.describe API::Commits do
let(:page) { 3 }
it 'returns the third 5 commits' do
+ request
+
commit = project.repository.commits('HEAD', limit: per_page, offset: (page - 1) * per_page).first
expect(json_response.size).to eq(per_page)
@@ -238,10 +244,55 @@ RSpec.describe API::Commits do
end
end
- context 'when per_page is 0' do
- let(:per_page) { 0 }
+ context 'when pagination params are invalid' do
+ let_it_be(:project) { create(:project, :repository) }
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:page, :per_page, :error_message) do
+ 0 | nil | 'page does not have a valid value'
+ -1 | nil | 'page does not have a valid value'
+ 'a' | nil | 'page is invalid'
+ nil | 0 | 'per_page does not have a valid value'
+ nil | -1 | 'per_page does not have a valid value'
+ nil | 'a' | 'per_page is invalid'
+ end
+
+ with_them do
+ it 'returns 400 response' do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq(error_message)
+ end
+ end
- it_behaves_like '400 response'
+ context 'when FF is off' do
+ before do
+ stub_feature_flags(only_positive_pagination_values: false)
+ end
+
+ where(:page, :per_page, :error_message, :status) do
+ 0 | nil | nil | :success
+ -10 | nil | nil | :internal_server_error
+ 'a' | nil | 'page is invalid' | :bad_request
+ nil | 0 | 'per_page has a value not allowed' | :bad_request
+ nil | -1 | nil | :success
+ nil | 'a' | 'per_page is invalid' | :bad_request
+ end
+
+ with_them do
+ it 'returns a response' do
+ request
+
+ expect(response).to have_gitlab_http_status(status)
+
+ if error_message
+ expect(json_response['error']).to eq(error_message)
+ end
+ end
+ end
+ end
end
end
@@ -928,6 +979,40 @@ RSpec.describe API::Commits do
end
end
+ context 'when action is missing' do
+ let(:params) do
+ {
+ branch: 'master',
+ commit_message: 'Invalid',
+ actions: [{ action: nil, file_path: 'files/ruby/popen.rb' }]
+ }
+ end
+
+ it 'responds with 400 bad request' do
+ post api(url, user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('actions[0][action] is empty')
+ end
+ end
+
+ context 'when action is not supported' do
+ let(:params) do
+ {
+ branch: 'master',
+ commit_message: 'Invalid',
+ actions: [{ action: 'unknown', file_path: 'files/ruby/popen.rb' }]
+ }
+ end
+
+ it 'responds with 400 bad request' do
+ post api(url, user), params: params
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('actions[0][action] does not have a valid value')
+ end
+ end
+
context 'when committing into a fork as a maintainer' do
include_context 'merge request allowing collaboration'
@@ -988,8 +1073,8 @@ RSpec.describe API::Commits do
it 'returns all refs with no scope' do
get api(route, current_user), params: { per_page: 100 }
- refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
- refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
+ refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
+ refs.concat(project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] })
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_limited_pagination_headers
@@ -1000,8 +1085,8 @@ RSpec.describe API::Commits do
it 'returns all refs' do
get api(route, current_user), params: { type: 'all', per_page: 100 }
- refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
- refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
+ refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
+ refs.concat(project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] })
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
@@ -1010,7 +1095,7 @@ RSpec.describe API::Commits do
it 'returns the branch refs' do
get api(route, current_user), params: { type: 'branch', per_page: 100 }
- refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
+ refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
@@ -1019,7 +1104,7 @@ RSpec.describe API::Commits do
it 'returns the tag refs' do
get api(route, current_user), params: { type: 'tag', per_page: 100 }
- refs = project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]}
+ refs = project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
@@ -2036,7 +2121,7 @@ RSpec.describe API::Commits do
context 'unsigned commit' do
it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
- let(:message) { '404 Signature Not Found'}
+ let(:message) { '404 Signature Not Found' }
end
end
diff --git a/spec/requests/api/conan_instance_packages_spec.rb b/spec/requests/api/conan_instance_packages_spec.rb
index 54cad3093d7..e4747e0eb99 100644
--- a/spec/requests/api/conan_instance_packages_spec.rb
+++ b/spec/requests/api/conan_instance_packages_spec.rb
@@ -94,7 +94,7 @@ RSpec.describe API::ConanInstancePackages do
end
describe 'DELETE /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
- subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
+ subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers }
it_behaves_like 'delete package endpoint'
end
diff --git a/spec/requests/api/conan_project_packages_spec.rb b/spec/requests/api/conan_project_packages_spec.rb
index e28105eb8eb..48e36b55a68 100644
--- a/spec/requests/api/conan_project_packages_spec.rb
+++ b/spec/requests/api/conan_project_packages_spec.rb
@@ -93,7 +93,7 @@ RSpec.describe API::ConanProjectPackages do
end
describe 'DELETE /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
- subject { delete api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
+ subject { delete api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}"), headers: headers }
it_behaves_like 'delete package endpoint'
end
diff --git a/spec/requests/api/dependency_proxy_spec.rb b/spec/requests/api/dependency_proxy_spec.rb
index 067852ef1e9..a8617fcb0bf 100644
--- a/spec/requests/api/dependency_proxy_spec.rb
+++ b/spec/requests/api/dependency_proxy_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe API::DependencyProxy, api: true do
let_it_be(:user) { create(:user) }
- let_it_be(:blob) { create(:dependency_proxy_blob )}
+ let_it_be(:blob) { create(:dependency_proxy_blob ) }
let_it_be(:group, reload: true) { blob.group }
before do
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index 69f7b54c277..24c3ee59c18 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -448,6 +448,90 @@ RSpec.describe API::Deployments do
end
end
+ describe 'DELETE /projects/:id/deployments/:deployment_id' do
+ let(:project) { create(:project, :repository) }
+ let(:environment) { create(:environment, project: project) }
+ let(:commits) { project.repository.commits(nil, { limit: 3 }) }
+ let!(:deploy) do
+ create(
+ :deployment,
+ :success,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[1].sha
+ )
+ end
+
+ let!(:old_deploy) do
+ create(
+ :deployment,
+ :success,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[0].sha,
+ finished_at: 1.year.ago
+ )
+ end
+
+ let!(:running_deploy) do
+ create(
+ :deployment,
+ :running,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[2].sha
+ )
+ end
+
+ context 'as an maintainer' do
+ it 'deletes a deployment' do
+ delete api("/projects/#{project.id}/deployments/#{old_deploy.id}", user)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'will not delete a running deployment' do
+ delete api("/projects/#{project.id}/deployments/#{running_deploy.id}", user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.body).to include("Cannot destroy running deployment")
+ end
+ end
+
+ context 'as a developer' do
+ let(:developer) { create(:user) }
+
+ before do
+ project.add_developer(developer)
+ end
+
+ it 'is forbidden' do
+ delete api("/projects/#{project.id}/deployments/#{deploy.id}", developer)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'as non member' do
+ it 'is not found' do
+ delete api("/projects/#{project.id}/deployments/#{deploy.id}", non_member)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'for non-existent deployment' do
+ it 'is not found' do
+ delete api("/projects/#{project.id}/deployments/#{non_existing_record_id}", project.first_owner)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe 'GET /projects/:id/deployments/:deployment_id/merge_requests' do
let(:project) { create(:project, :repository) }
let!(:deployment) { create(:deployment, :success, project: project) }
diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb
index 77f1dadff46..14da9a600cd 100644
--- a/spec/requests/api/doorkeeper_access_spec.rb
+++ b/spec/requests/api/doorkeeper_access_spec.rb
@@ -9,13 +9,13 @@ RSpec.describe 'doorkeeper access' do
describe "unauthenticated" do
it "returns authentication success" do
- get api("/user"), params: { access_token: token.token }
+ get api("/user"), params: { access_token: token.plaintext_token }
expect(response).to have_gitlab_http_status(:ok)
end
include_examples 'user login request with unique ip limit' do
def request
- get api('/user'), params: { access_token: token.token }
+ get api('/user'), params: { access_token: token.plaintext_token }
end
end
end
@@ -42,7 +42,7 @@ RSpec.describe 'doorkeeper access' do
shared_examples 'forbidden request' do
it 'returns 403 response' do
- get api("/user"), params: { access_token: token.token }
+ get api("/user"), params: { access_token: token.plaintext_token }
expect(response).to have_gitlab_http_status(:forbidden)
end
diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb
index 0143340de11..7c44fddc303 100644
--- a/spec/requests/api/go_proxy_spec.rb
+++ b/spec/requests/api/go_proxy_spec.rb
@@ -318,7 +318,7 @@ RSpec.describe API::GoProxy do
context 'with a case sensitive project and versions' do
let_it_be(:project) { create :project_empty_repo, :public, creator: user, path: 'MyGoLib' }
let_it_be(:base) { "#{Settings.build_gitlab_go_url}/#{project.full_path}" }
- let_it_be(:base_encoded) { base.gsub(/[A-Z]/) { |s| "!#{s.downcase}"} }
+ let_it_be(:base_encoded) { base.gsub(/[A-Z]/) { |s| "!#{s.downcase}" } }
let_it_be(:modules) do
create(:go_module_commit, :files, project: project, files: { 'README.md' => "Hi" })
@@ -376,7 +376,7 @@ RSpec.describe API::GoProxy do
end
it 'returns ok with a job token' do
- get_resource(oauth_access_token: job)
+ get_resource(access_token: job)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -395,7 +395,7 @@ RSpec.describe API::GoProxy do
it 'returns unauthorized with a failed job token' do
job.update!(status: :failed)
- get_resource(oauth_access_token: job)
+ get_resource(access_token: job)
expect(response).to have_gitlab_http_status(:unauthorized)
end
@@ -445,7 +445,7 @@ RSpec.describe API::GoProxy do
end
it 'returns not found with a job token' do
- get_resource(oauth_access_token: job)
+ get_resource(access_token: job)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
index 6324db0be4a..484ddc3469b 100644
--- a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'get board lists' do
let_it_be(:group_label2) { create(:group_label, group: group, name: 'Testing') }
let(:params) { '' }
- let(:board) { }
+ let(:board) {}
let(:confidential) { false }
let(:board_parent_type) { board_parent.class.to_s.downcase }
let(:board_data) { graphql_data[board_parent_type]['boards']['nodes'][0] }
diff --git a/spec/requests/api/graphql/boards/board_lists_query_spec.rb b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
index 39ff108a9e1..6fe2e41cf35 100644
--- a/spec/requests/api/graphql/boards/board_lists_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'get board lists' do
let_it_be(:group_label2) { create(:group_label, group: group, name: 'Testing') }
let(:params) { '' }
- let(:board) { }
+ let(:board) {}
let(:board_parent_type) { board_parent.class.to_s.downcase }
let(:board_data) { graphql_data[board_parent_type]['boards']['edges'].first['node'] }
let(:lists_data) { board_data['lists']['edges'] }
diff --git a/spec/requests/api/graphql/ci/instance_variables_spec.rb b/spec/requests/api/graphql/ci/instance_variables_spec.rb
index 7acf73a4e7a..c5c88697bf4 100644
--- a/spec/requests/api/graphql/ci/instance_variables_spec.rb
+++ b/spec/requests/api/graphql/ci/instance_variables_spec.rb
@@ -57,4 +57,16 @@ RSpec.describe 'Query.ciVariables' do
expect(graphql_data.dig('ciVariables')).to be_nil
end
end
+
+ context 'when the user is unauthenticated' do
+ let_it_be(:user) { nil }
+
+ it 'returns nothing' do
+ create(:ci_instance_variable, value: 'verysecret', masked: true)
+
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data.dig('ciVariables')).to be_nil
+ end
+ end
end
diff --git a/spec/requests/api/graphql/ci/manual_variables_spec.rb b/spec/requests/api/graphql/ci/manual_variables_spec.rb
index b7aa76511a3..a15bac2b8bd 100644
--- a/spec/requests/api/graphql/ci/manual_variables_spec.rb
+++ b/spec/requests/api/graphql/ci/manual_variables_spec.rb
@@ -35,8 +35,8 @@ RSpec.describe 'Query.project(fullPath).pipelines.jobs.manualVariables' do
project.add_maintainer(user)
end
- it 'returns the manual variables for the jobs' do
- job = create(:ci_build, :manual, pipeline: pipeline)
+ it 'returns the manual variables for actionable jobs' do
+ job = create(:ci_build, :actionable, pipeline: pipeline)
create(:ci_job_variable, key: 'MANUAL_TEST_VAR', job: job)
post_graphql(query, current_user: user)
@@ -46,8 +46,8 @@ RSpec.describe 'Query.project(fullPath).pipelines.jobs.manualVariables' do
expect(variables_data.map { |var| var['key'] }).to match_array(['MANUAL_TEST_VAR'])
end
- it 'does not fetch job variables for jobs that are not manual' do
- job = create(:ci_build, pipeline: pipeline)
+ it 'does not fetch job variables for jobs that are not actionable' do
+ job = create(:ci_build, pipeline: pipeline, status: :manual)
create(:ci_job_variable, key: 'THIS_VAR_WOULD_SHOULD_NEVER_EXIST', job: job)
post_graphql(query, current_user: user)
diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb
index a968e5508cb..f471a152603 100644
--- a/spec/requests/api/graphql/ci/pipelines_spec.rb
+++ b/spec/requests/api/graphql/ci/pipelines_spec.rb
@@ -166,6 +166,35 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
end
end
+ describe '.job' do
+ let(:first_n) { var('Int') }
+ let(:query_path) do
+ [
+ [:project, { full_path: project.full_path }],
+ [:pipelines],
+ [:nodes],
+ [:job, { name: 'Job 1' }]
+ ]
+ end
+
+ let(:query) do
+ wrap_fields(query_graphql_path(query_path, :status))
+ end
+
+ before_all do
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, pipeline: pipeline, name: 'Job 1', status: :failed, retried: true)
+ create(:ci_build, pipeline: pipeline, name: 'Job 1', status: :success)
+ end
+
+ it 'fetches the latest job with the given name' do
+ post_graphql(query, current_user: user)
+ expect(graphql_data_at(*query_path.map(&:first))).to contain_exactly a_hash_including(
+ 'status' => 'SUCCESS'
+ )
+ end
+ end
+
describe '.jobs' do
let(:first_n) { var('Int') }
let(:query_path) do
diff --git a/spec/requests/api/graphql/ci/runners_spec.rb b/spec/requests/api/graphql/ci/runners_spec.rb
index a5b8115286e..749f6839cb5 100644
--- a/spec/requests/api/graphql/ci/runners_spec.rb
+++ b/spec/requests/api/graphql/ci/runners_spec.rb
@@ -37,7 +37,9 @@ RSpec.describe 'Query.runners' do
end
before do
- allow(Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_status)
+ allow_next_instance_of(::Gitlab::Ci::RunnerUpgradeCheck) do |instance|
+ allow(instance).to receive(:check_runner_upgrade_suggestion)
+ end
post_graphql(query, current_user: current_user)
end
diff --git a/spec/requests/api/graphql/crm/contacts_spec.rb b/spec/requests/api/graphql/crm/contacts_spec.rb
index 7e824140894..a676e92dc3b 100644
--- a/spec/requests/api/graphql/crm/contacts_spec.rb
+++ b/spec/requests/api/graphql/crm/contacts_spec.rb
@@ -12,11 +12,11 @@ RSpec.describe 'getting CRM contacts' do
create(
:contact,
group: group,
- first_name: "ABC",
- last_name: "DEF",
- email: "ghi@test.com",
- description: "LMNO",
- state: "inactive"
+ first_name: "PQR",
+ last_name: "STU",
+ email: "aaa@test.com",
+ description: "YZ",
+ state: "active"
)
end
@@ -26,9 +26,9 @@ RSpec.describe 'getting CRM contacts' do
group: group,
first_name: "ABC",
last_name: "DEF",
- email: "vwx@test.com",
- description: "YZ",
- state: "active"
+ email: "ghi@test.com",
+ description: "LMNO",
+ state: "inactive"
)
end
@@ -36,9 +36,9 @@ RSpec.describe 'getting CRM contacts' do
create(
:contact,
group: group,
- first_name: "PQR",
- last_name: "STU",
- email: "aaa@test.com",
+ first_name: "JKL",
+ last_name: "MNO",
+ email: "vwx@test.com",
description: "YZ",
state: "active"
)
@@ -51,7 +51,7 @@ RSpec.describe 'getting CRM contacts' do
it_behaves_like 'sorted paginated query' do
let(:sort_argument) { {} }
let(:first_param) { 2 }
- let(:all_records) { [contact_a, contact_b, contact_c] }
+ let(:all_records) { [contact_b, contact_c, contact_a] }
let(:data_path) { [:group, :contacts] }
def pagination_query(params)
diff --git a/spec/requests/api/graphql/current_user/groups_query_spec.rb b/spec/requests/api/graphql/current_user/groups_query_spec.rb
index ef0f32bacf0..6e36beb2afc 100644
--- a/spec/requests/api/graphql/current_user/groups_query_spec.rb
+++ b/spec/requests/api/graphql/current_user/groups_query_spec.rb
@@ -6,10 +6,11 @@ RSpec.describe 'Query current user groups' do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
+ let_it_be(:root_group) { create(:group, name: 'Root group', path: 'root-group') }
let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') }
- let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer') }
+ let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_group) }
let_it_be(:public_developer_group) { create(:group, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') }
- let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer') }
+ let_it_be(:public_maintainer_group) { create(:group, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_group) }
let_it_be(:public_owner_group) { create(:group, name: 'a public owner', path: 'a-public-owner') }
let(:group_arguments) { {} }
@@ -77,7 +78,7 @@ RSpec.describe 'Query current user groups' do
end
context 'when search is provided' do
- let(:group_arguments) { { permission_scope: :CREATE_PROJECTS, search: 'maintainer' } }
+ let(:group_arguments) { { permission_scope: :CREATE_PROJECTS, search: 'root-group maintainer' } }
specify do
is_expected.to match(
@@ -127,6 +128,18 @@ RSpec.describe 'Query current user groups' do
)
)
end
+
+ context 'when searching for a full path (including parent)' do
+ let(:group_arguments) { { search: 'root-group/b-private-maintainer' } }
+
+ specify do
+ is_expected.to match(
+ expected_group_hash(
+ private_maintainer_group
+ )
+ )
+ end
+ end
end
def expected_group_hash(*groups)
diff --git a/spec/requests/api/graphql/custom_emoji_query_spec.rb b/spec/requests/api/graphql/custom_emoji_query_spec.rb
index 874357d9eef..13b7a22e791 100644
--- a/spec/requests/api/graphql/custom_emoji_query_spec.rb
+++ b/spec/requests/api/graphql/custom_emoji_query_spec.rb
@@ -31,8 +31,8 @@ RSpec.describe 'getting custom emoji within namespace' do
post_graphql(custom_emoji_query(group), current_user: current_user)
expect(response).to have_gitlab_http_status(:ok)
- expect(graphql_data['group']['customEmoji']['nodes'].count). to eq(1)
- expect(graphql_data['group']['customEmoji']['nodes'].first['name']). to eq(custom_emoji.name)
+ expect(graphql_data['group']['customEmoji']['nodes'].count).to eq(1)
+ expect(graphql_data['group']['customEmoji']['nodes'].first['name']).to eq(custom_emoji.name)
end
it 'returns nil when unauthorised' do
diff --git a/spec/requests/api/graphql/group/group_members_spec.rb b/spec/requests/api/graphql/group/group_members_spec.rb
index 1ff5b134e92..bab8d5b770c 100644
--- a/spec/requests/api/graphql/group/group_members_spec.rb
+++ b/spec/requests/api/graphql/group/group_members_spec.rb
@@ -64,24 +64,6 @@ RSpec.describe 'getting group members information' do
expect_array_response(user_2)
end
-
- context 'when the use_keyset_aware_user_search_query FF is off' do
- before do
- stub_feature_flags(use_keyset_aware_user_search_query: false)
- end
-
- it 'raises error on the 2nd page due to missing cursor data' do
- fetch_members(args: { search: 'Same Name', first: 1 })
-
- # user_2 because the "old" order was undeterministic (insert order), no tie-breaker column
- expect_array_response(user_2)
-
- next_cursor = graphql_data_at(:group, :groupMembers, :pageInfo, :endCursor)
- fetch_members(args: { search: 'Same Name', first: 1, after: next_cursor })
-
- expect(graphql_errors.first['message']).to include('PG::UndefinedColumn')
- end
- end
end
end
end
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
index fd0ee5d52b9..8ee5c3c5d73 100644
--- a/spec/requests/api/graphql/group_query_spec.rb
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -122,6 +122,87 @@ RSpec.describe 'getting group information' do
end
end
+ context 'with timelog categories' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:timelog_category) { create(:timelog_category, namespace: group, name: 'TimelogCategoryTest') }
+
+ context 'when user is guest' do
+ it 'includes empty timelog categories array' do
+ post_graphql(group_query(group), current_user: user2)
+
+ expect(graphql_data_at(:group, :timelogCategories, :nodes)).to match([])
+ end
+ end
+
+ context 'when user has reporter role' do
+ before do
+ group.add_reporter(user2)
+ end
+
+ it 'returns the timelog category with all its fields' do
+ post_graphql(group_query(group), current_user: user2)
+
+ expect(graphql_data_at(:group, :timelogCategories, :nodes))
+ .to contain_exactly(a_graphql_entity_for(timelog_category))
+ end
+
+ context 'when timelog_categories flag is disabled' do
+ before do
+ stub_feature_flags(timelog_categories: false)
+ end
+
+ it 'returns no timelog categories' do
+ post_graphql(group_query(group), current_user: user2)
+
+ expect(graphql_data_at(:group, :timelogCategories)).to be_nil
+ end
+ end
+ end
+
+ context 'for N+1 queries' do
+ let!(:group1) { create(:group) }
+ let!(:group2) { create(:group) }
+
+ before do
+ group1.add_reporter(user2)
+ group2.add_reporter(user2)
+ end
+
+ it 'avoids N+1 database queries' do
+ pending('See: https://gitlab.com/gitlab-org/gitlab/-/issues/369396')
+
+ ctx = { current_user: user2 }
+
+ baseline_query = <<~GQL
+ query {
+ a: group(fullPath: "#{group1.full_path}") { ... g }
+ }
+
+ fragment g on Group {
+ timelogCategories { nodes { name } }
+ }
+ GQL
+
+ query = <<~GQL
+ query {
+ a: group(fullPath: "#{group1.full_path}") { ... g }
+ b: group(fullPath: "#{group2.full_path}") { ... g }
+ }
+
+ fragment g on Group {
+ timelogCategories { nodes { name } }
+ }
+ GQL
+
+ control = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(baseline_query, context: ctx)
+ end
+
+ expect { run_with_clean_state(query, context: ctx) }.not_to exceed_query_limit(control)
+ end
+ end
+ end
+
context "when authenticated as admin" do
it "returns any existing group" do
post_graphql(group_query(private_group), current_user: admin)
diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
index fdf5503a3a2..3879e58cecf 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe 'Adding an AwardEmoji' do
end
describe 'marking Todos as done' do
- let(:user) { current_user}
+ let(:user) { current_user }
subject { post_graphql_mutation(mutation, current_user: user) }
diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
index 6b26e37e30c..7ddffa1ab0a 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe 'Toggling an AwardEmoji' do
end
describe 'marking Todos as done' do
- let(:user) { current_user}
+ let(:user) { current_user }
subject { post_graphql_mutation(mutation, current_user: user) }
diff --git a/spec/requests/api/graphql/mutations/boards/destroy_spec.rb b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb
index 23e099e94b6..7620da3e7e0 100644
--- a/spec/requests/api/graphql/mutations/boards/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb
@@ -65,15 +65,8 @@ RSpec.describe Mutations::Boards::Destroy do
other_board.destroy!
end
- it 'does not destroy the board' do
- expect { subject }.not_to change { Board.count }.from(1)
- end
-
- it 'returns an error and not nil board' do
- subject
-
- expect(mutation_response['errors']).not_to be_empty
- expect(mutation_response['board']).not_to be_nil
+ it 'does destroy the board' do
+ expect { subject }.to change { Board.count }.by(-1)
end
end
end
diff --git a/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb b/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb
index ef640183bd8..8cf559a372a 100644
--- a/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/job_retry_spec.rb
@@ -47,6 +47,38 @@ RSpec.describe 'JobRetry' do
expect(new_job).not_to be_retried
end
+ context 'when given CI variables' do
+ let(:job) { create(:ci_build, :success, :actionable, pipeline: pipeline, name: 'build') }
+
+ let(:mutation) do
+ variables = {
+ id: job.to_global_id.to_s,
+ variables: { key: 'MANUAL_VAR', value: 'test manual var' }
+ }
+
+ graphql_mutation(:job_retry, variables,
+ <<-QL
+ errors
+ job {
+ id
+ }
+ QL
+ )
+ end
+
+ it 'applies them to a retried manual job' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+
+ new_job_id = GitlabSchema.object_from_id(mutation_response['job']['id']).sync.id
+ new_job = ::Ci::Build.find(new_job_id)
+ expect(new_job.job_variables.count).to be(1)
+ expect(new_job.job_variables.first.key).to eq('MANUAL_VAR')
+ expect(new_job.job_variables.first.value).to eq('test manual var')
+ end
+ end
+
context 'when the job is not retryable' do
let(:job) { create(:ci_build, :retried, pipeline: pipeline) }
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb
index d9106aa42c4..6ec1b7ce9b6 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe 'PipelineCancel' do
expect(build).not_to be_canceled
end
- it "cancels all cancelable builds from a pipeline" do
+ it 'cancels all cancelable builds from a pipeline', :sidekiq_inline do
build = create(:ci_build, :running, pipeline: pipeline)
post_graphql_mutation(mutation, current_user: user)
diff --git a/spec/requests/api/graphql/mutations/merge_requests/request_attention_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/request_attention_spec.rb
deleted file mode 100644
index 9c751913827..00000000000
--- a/spec/requests/api/graphql/mutations/merge_requests/request_attention_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Request attention' do
- include GraphqlHelpers
-
- let_it_be(:current_user) { create(:user) }
- let_it_be(:user) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user]) }
- let_it_be(:project) { merge_request.project }
-
- let(:input) { { user_id: global_id_of(user) } }
-
- let(:mutation) do
- variables = {
- project_path: project.full_path,
- iid: merge_request.iid.to_s
- }
- graphql_mutation(:merge_request_request_attention, variables.merge(input),
- <<-QL.strip_heredoc
- clientMutationId
- errors
- QL
- )
- end
-
- def mutation_response
- graphql_mutation_response(:merge_request_request_attention)
- end
-
- def mutation_errors
- mutation_response['errors']
- end
-
- before_all do
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- it 'is successful' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).to be_empty
- end
-
- context 'when current user is not allowed to update the merge request' do
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: create(:user))
-
- expect(graphql_errors).not_to be_empty
- end
- end
-
- context 'when user is not a reviewer' do
- let(:input) { { user_id: global_id_of(create(:user)) } }
-
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).not_to be_empty
- end
- end
-
- context 'feature flag is disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
- end
-
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(graphql_errors[0]["message"]).to eq "Feature disabled"
- end
- end
-end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb
new file mode 100644
index 00000000000..be786256ef2
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/merge_requests/set_reviewers_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting reviewers of a merge request', :assume_throttled do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:current_user) { create(:user, developer_projects: [project]) }
+ let_it_be(:reviewer) { create(:user) }
+ let_it_be(:reviewer2) { create(:user) }
+ let_it_be_with_reload(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:input) { { reviewer_usernames: [reviewer.username] } }
+ let(:expected_result) do
+ [{ 'username' => reviewer.username }]
+ end
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: merge_request.iid.to_s
+ }
+ graphql_mutation(:merge_request_set_reviewers, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ mergeRequest {
+ id
+ reviewers {
+ nodes {
+ username
+ }
+ }
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:merge_request_set_reviewers)
+ end
+
+ def mutation_reviewer_nodes
+ mutation_response['mergeRequest']['reviewers']['nodes']
+ end
+
+ def run_mutation!
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ before do
+ project.add_developer(reviewer)
+ project.add_developer(reviewer2)
+
+ merge_request.update!(reviewers: [])
+ end
+
+ it 'returns an error if the user is not allowed to update the merge request' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ context 'when the current user does not have permission to add reviewers' do
+ let(:current_user) { create(:user) }
+
+ it 'does not change the reviewers' do
+ project.add_guest(current_user)
+
+ expect { run_mutation! }.not_to change { merge_request.reset.reviewers.pluck(:id) }
+
+ expect(graphql_errors).not_to be_empty
+ end
+ end
+
+ context 'with reviewers already assigned' do
+ before do
+ merge_request.reviewers = [reviewer2]
+ merge_request.save!
+ end
+
+ it 'replaces the reviewer' do
+ run_mutation!
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_reviewer_nodes).to match_array(expected_result)
+ end
+ end
+
+ context 'when passing an empty list of reviewers' do
+ let(:input) { { reviewer_usernames: [] } }
+
+ before do
+ merge_request.reviewers = [reviewer2]
+ merge_request.save!
+ end
+
+ it 'removes reviewer' do
+ run_mutation!
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_reviewer_nodes).to eq([])
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb
deleted file mode 100644
index cf497cb2579..00000000000
--- a/spec/requests/api/graphql/mutations/merge_requests/update_reviewer_state_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Toggle attention requested for reviewer' do
- include GraphqlHelpers
-
- let(:current_user) { create(:user) }
- let(:merge_request) { create(:merge_request, reviewers: [user]) }
- let(:project) { merge_request.project }
- let(:user) { create(:user) }
- let(:input) { { user_id: global_id_of(user) } }
-
- let(:mutation) do
- variables = {
- project_path: project.full_path,
- iid: merge_request.iid.to_s
- }
- graphql_mutation(:merge_request_toggle_attention_requested, variables.merge(input),
- <<-QL.strip_heredoc
- clientMutationId
- errors
- QL
- )
- end
-
- def mutation_response
- graphql_mutation_response(:merge_request_toggle_attention_requested)
- end
-
- def mutation_errors
- mutation_response['errors']
- end
-
- before do
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- it 'returns an error if the user is not allowed to update the merge request' do
- post_graphql_mutation(mutation, current_user: create(:user))
-
- expect(graphql_errors).not_to be_empty
- end
-
- describe 'reviewer does not exist' do
- let(:input) { { user_id: global_id_of(create(:user)) } }
-
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).not_to be_empty
- end
- end
-
- describe 'reviewer exists' do
- it 'does not return an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).to be_empty
- end
- end
-end
diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
index 22b5f2d5112..9c3842db31a 100644
--- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
@@ -79,21 +79,29 @@ RSpec.describe 'Adding a Note' do
context 'for an issue' do
let(:noteable) { create(:issue, project: project) }
- let(:mutation) do
- variables = {
+ let(:mutation) { graphql_mutation(:create_note, variables) }
+ let(:variables) do
+ {
noteable_id: GitlabSchema.id_from_object(noteable).to_s,
- body: body,
- confidential: true
- }
-
- graphql_mutation(:create_note, variables)
+ body: body
+ }.merge(variables_extra)
end
before do
project.add_developer(current_user)
end
- it_behaves_like 'a Note mutation with confidential notes'
+ context 'when using internal param' do
+ let(:variables_extra) { { internal: true } }
+
+ it_behaves_like 'a Note mutation with confidential notes'
+ end
+
+ context 'when using deprecated confidential param' do
+ let(:variables_extra) { { confidential: true } }
+
+ it_behaves_like 'a Note mutation with confidential notes'
+ end
end
context 'when body only contains quick actions' do
diff --git a/spec/requests/api/graphql/mutations/releases/create_spec.rb b/spec/requests/api/graphql/mutations/releases/create_spec.rb
index 1e62942c29d..2541072b766 100644
--- a/spec/requests/api/graphql/mutations/releases/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/create_spec.rb
@@ -16,10 +16,10 @@ RSpec.describe 'Creation of a new release' do
let(:mutation_name) { :release_create }
- let(:tag_name) { 'v7.12.5'}
+ let(:tag_name) { 'v7.12.5' }
let(:tag_message) { nil }
- let(:ref) { 'master'}
- let(:name) { 'Version 7.12.5'}
+ let(:ref) { 'master' }
+ let(:name) { 'Version 7.12.5' }
let(:description) { 'Release 7.12.5 :rocket:' }
let(:released_at) { '2018-12-10' }
let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
diff --git a/spec/requests/api/graphql/mutations/releases/update_spec.rb b/spec/requests/api/graphql/mutations/releases/update_spec.rb
index 0fa3d7de299..33d4e57904c 100644
--- a/spec/requests/api/graphql/mutations/releases/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/releases/update_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Updating an existing release' do
let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
let_it_be(:tag_name) { 'v1.1.0' }
- let_it_be(:name) { 'Version 7.12.5'}
+ let_it_be(:name) { 'Version 7.12.5' }
let_it_be(:description) { 'Release 7.12.5 :rocket:' }
let_it_be(:released_at) { '2018-12-10' }
let_it_be(:created_at) { '2018-11-05' }
diff --git a/spec/requests/api/graphql/mutations/remove_attention_request_spec.rb b/spec/requests/api/graphql/mutations/remove_attention_request_spec.rb
deleted file mode 100644
index 053559b039d..00000000000
--- a/spec/requests/api/graphql/mutations/remove_attention_request_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Remove attention request' do
- include GraphqlHelpers
-
- let_it_be(:current_user) { create(:user) }
- let_it_be(:user) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user]) }
- let_it_be(:project) { merge_request.project }
-
- let(:input) { { user_id: global_id_of(user) } }
-
- let(:mutation) do
- variables = {
- project_path: project.full_path,
- iid: merge_request.iid.to_s
- }
- graphql_mutation(:merge_request_remove_attention_request, variables.merge(input),
- <<-QL.strip_heredoc
- clientMutationId
- errors
- QL
- )
- end
-
- def mutation_response
- graphql_mutation_response(:merge_request_remove_attention_request)
- end
-
- def mutation_errors
- mutation_response['errors']
- end
-
- before_all do
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- it 'is successful' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).to be_empty
- end
-
- context 'when current user is not allowed to update the merge request' do
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: create(:user))
-
- expect(graphql_errors).not_to be_empty
- end
- end
-
- context 'when user is not a reviewer' do
- let(:input) { { user_id: global_id_of(create(:user)) } }
-
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_errors).not_to be_empty
- end
- end
-
- context 'feature flag is disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
- end
-
- it 'returns an error' do
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(graphql_errors[0]["message"]).to eq "Feature disabled"
- end
- end
-end
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index 9a3cea3ca14..264fa5732c3 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe 'Creating a Snippet' do
let(:title) { 'Initial title' }
let(:visibility_level) { 'public' }
let(:action) { :create }
- let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' }}
- let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' }}
+ let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' } }
+ let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' } }
let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
let(:project_path) { nil }
let(:uploaded_files) { nil }
@@ -149,7 +149,7 @@ RSpec.describe 'Creating a Snippet' do
end
context 'when there non ActiveRecord errors' do
- let(:file_1) { { filePath: 'invalid://file/path', content: 'foobar' }}
+ let(:file_1) { { filePath: 'invalid://file/path', content: 'foobar' } }
it_behaves_like 'a mutation that returns errors in the response', errors: ['Repository Error creating the snippet - Invalid file name']
it_behaves_like 'does not create snippet'
diff --git a/spec/requests/api/graphql/mutations/timelogs/create_spec.rb b/spec/requests/api/graphql/mutations/timelogs/create_spec.rb
new file mode 100644
index 00000000000..eea04b89783
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/timelogs/create_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Create a timelog' do
+ include GraphqlHelpers
+
+ let_it_be(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:time_spent) { '1h' }
+
+ let(:current_user) { nil }
+ let(:users_container) { project }
+ let(:mutation) do
+ graphql_mutation(:timelogCreate, {
+ 'time_spent' => time_spent,
+ 'spent_at' => '2022-07-08',
+ 'summary' => 'Test summary',
+ 'issuable_id' => issuable.to_global_id.to_s
+ })
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:timelog_create) }
+
+ context 'when issuable is an Issue' do
+ let_it_be(:issuable) { create(:issue, project: project) }
+
+ it_behaves_like 'issuable supports timelog creation mutation'
+ end
+
+ context 'when issuable is a MergeRequest' do
+ let_it_be(:issuable) { create(:merge_request, source_project: project) }
+
+ it_behaves_like 'issuable supports timelog creation mutation'
+ end
+
+ context 'when issuable is a WorkItem' do
+ let_it_be(:issuable) { create(:work_item, project: project, title: 'WorkItem') }
+
+ it_behaves_like 'issuable supports timelog creation mutation'
+ end
+
+ context 'when issuable is an Incident' do
+ let_it_be(:issuable) { create(:incident, project: project) }
+
+ it_behaves_like 'issuable supports timelog creation mutation'
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb b/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb
index b674e77f093..d304bfbdf00 100644
--- a/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/timelogs/delete_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Delete a timelog' do
let_it_be(:author) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
+ let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
let(:current_user) { nil }
let(:mutation) { graphql_mutation(:timelogDelete, { 'id' => timelog.to_global_id.to_s }) }
diff --git a/spec/requests/api/graphql/mutations/uploads/delete_spec.rb b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb
new file mode 100644
index 00000000000..f44bf179397
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/uploads/delete_spec.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Delete an upload' do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:developer) { create(:user).tap { |user| group.add_developer(user) } }
+ let_it_be(:maintainer) { create(:user).tap { |user| group.add_maintainer(user) } }
+
+ let(:extra_params) { {} }
+ let(:params) { { filename: File.basename(upload.path), secret: upload.secret }.merge(extra_params) }
+ let(:mutation) { graphql_mutation(:uploadDelete, params) }
+ let(:mutation_response) { graphql_mutation_response(:upload_delete) }
+
+ shared_examples_for 'upload deletion' do
+ context 'when the user is not allowed to delete uploads' do
+ let(:current_user) { developer }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when the user is anonymous' do
+ let(:current_user) { nil }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to delete uploads' do
+ let(:current_user) { maintainer }
+
+ it 'deletes the upload' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['upload']).to include('id' => upload.to_global_id.to_s)
+ expect(mutation_response['errors']).to be_empty
+ end
+
+ context 'when upload does not exist' do
+ let(:params) { { filename: 'invalid', secret: upload.secret }.merge(extra_params) }
+
+ it 'returns an error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ 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."
+ ])
+ end
+ end
+ end
+ end
+
+ context 'when deleting project upload' do
+ let_it_be_with_reload(:upload) { create(:upload, :issuable_upload, model: project) }
+
+ let(:extra_params) { { project_path: project.full_path } }
+
+ it_behaves_like 'upload deletion'
+ end
+
+ context 'when deleting group upload' do
+ let_it_be_with_reload(:upload) { create(:upload, :namespace_upload, model: group) }
+
+ let(:extra_params) { { group_path: group.full_path } }
+
+ it_behaves_like 'upload deletion'
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb
index b1356bbe6fd..e7f4917ddde 100644
--- a/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/create_from_task_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Create a work item from a task in a work item's description" do
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, description: '- [ ] A task in a list', lock_version: 3) }
+ let_it_be(:work_item, refind: true) { create(:work_item, :confidential, project: project, description: '- [ ] A task in a list', lock_version: 3) }
let(:lock_version) { work_item.lock_version }
let(:input) do
@@ -48,6 +48,7 @@ RSpec.describe "Create a work item from a task in a work item's description" do
expect(created_work_item.issue_type).to eq('task')
expect(created_work_item.work_item_type.base_type).to eq('task')
expect(created_work_item.work_item_parent).to eq(work_item)
+ expect(created_work_item).to be_confidential
expect(mutation_response['workItem']).to include('id' => work_item.to_global_id.to_s)
expect(mutation_response['newWorkItem']).to include('id' => created_work_item.to_global_id.to_s)
end
diff --git a/spec/requests/api/graphql/mutations/work_items/create_spec.rb b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
index 911568bc39f..8233821053f 100644
--- a/spec/requests/api/graphql/mutations/work_items/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/create_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe 'Create a work item' do
{
'title' => 'new title',
'description' => 'new description',
+ 'confidential' => true,
'workItemTypeId' => WorkItems::Type.default_by_type(:task).to_global_id.to_s
}
end
@@ -38,6 +39,7 @@ RSpec.describe 'Create a work item' do
expect(response).to have_gitlab_http_status(:success)
expect(created_work_item.issue_type).to eq('task')
+ expect(created_work_item).to be_confidential
expect(created_work_item.work_item_type.base_type).to eq('task')
expect(mutation_response['workItem']).to include(
input.except('workItemTypeId').merge(
@@ -127,7 +129,7 @@ RSpec.describe 'Create a work item' do
end
context 'when parent work item is not found' do
- let_it_be(:parent) { build_stubbed(:work_item, id: non_existing_record_id)}
+ let_it_be(:parent) { build_stubbed(:work_item, id: non_existing_record_id) }
it 'returns a top level error' do
post_graphql_mutation(mutation, current_user: current_user)
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 77f7b9bacef..909d6549fa5 100644
--- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -34,6 +34,10 @@ RSpec.describe 'Update a work item' do
context 'when user has permissions to update a work item' do
let(:current_user) { developer }
+ it_behaves_like 'has spam protection' do
+ let(:mutation_class) { ::Mutations::WorkItems::Update }
+ end
+
context 'when the work item is open' do
it 'closes and updates the work item' do
expect do
@@ -71,36 +75,48 @@ RSpec.describe 'Update a work item' do
end
end
- context 'when unsupported widget input is sent' do
- let_it_be(:test_case) { create(:work_item_type, :default, :test_case, name: 'some_test_case_name') }
- let_it_be(:work_item) { create(:work_item, work_item_type: test_case, project: project) }
-
- let(:input) do
- {
- 'hierarchyWidget' => {}
+ context 'when updating confidentiality' do
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ confidential
}
+ errors
+ FIELDS
end
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ["Following widget keys are not supported by some_test_case_name type: [:hierarchy_widget]"]
- end
+ shared_examples 'toggling confidentiality' do
+ it 'successfully updates work item' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :confidential).from(values[:old]).to(values[:new])
- it_behaves_like 'has spam protection' do
- let(:mutation_class) { ::Mutations::WorkItems::Update }
- end
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']).to include(
+ 'confidential' => values[:new]
+ )
+ end
+ end
- context 'when the work_items feature flag is disabled' do
- before do
- stub_feature_flags(work_items: false)
+ context 'when setting as confidential' do
+ let(:input) { { 'confidential' => true } }
+
+ it_behaves_like 'toggling confidentiality' do
+ let(:values) { { old: false, new: true } }
+ end
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, :title)
+ context 'when setting as non-confidential' do
+ let(:input) { { 'confidential' => false } }
- expect(mutation_response['errors']).to contain_exactly('`work_items` feature flag disabled for this project')
+ before do
+ work_item.update!(confidential: true)
+ end
+
+ it_behaves_like 'toggling confidentiality' do
+ let(:values) { { old: true, new: false } }
+ end
end
end
@@ -128,26 +144,90 @@ RSpec.describe 'Update a work item' do
end
end
- context 'with weight widget input' do
+ context 'with due and start date widget input' do
+ let(:start_date) { Date.today }
+ let(:due_date) { 1.week.from_now.to_date }
let(:fields) do
<<~FIELDS
- workItem {
- widgets {
- type
- ... on WorkItemWidgetWeight {
- weight
+ workItem {
+ widgets {
+ type
+ ... on WorkItemWidgetStartAndDueDate {
+ startDate
+ dueDate
+ }
}
}
- }
- errors
+ errors
FIELDS
end
- it_behaves_like 'update work item weight widget' do
- let(:new_weight) { 2 }
+ let(:input) do
+ { 'startAndDueDateWidget' => { 'startDate' => start_date.to_s, 'dueDate' => due_date.to_s } }
+ end
- let(:input) do
- { 'weightWidget' => { 'weight' => new_weight } }
+ it 'updates start and due date' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :start_date).from(nil).to(start_date).and(
+ change(work_item, :due_date).from(nil).to(due_date)
+ )
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']['widgets']).to include(
+ {
+ 'startDate' => start_date.to_s,
+ 'dueDate' => due_date.to_s,
+ 'type' => 'START_AND_DUE_DATE'
+ }
+ )
+ end
+
+ context 'when provided input is invalid' do
+ let(:due_date) { 1.week.ago.to_date }
+
+ it 'returns validation errors without the work item' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(mutation_response['workItem']).to be_nil
+ expect(mutation_response['errors']).to contain_exactly('Due date must be greater than or equal to start date')
+ end
+ end
+
+ context 'when dates were already set for the work item' do
+ before do
+ work_item.update!(start_date: start_date, due_date: due_date)
+ end
+
+ context 'when updating only start date' do
+ let(:input) do
+ { 'startAndDueDateWidget' => { 'startDate' => nil } }
+ end
+
+ it 'allows setting a single date to null' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :start_date).from(start_date).to(nil).and(
+ not_change(work_item, :due_date).from(due_date)
+ )
+ end
+ end
+
+ context 'when updating only due date' do
+ let(:input) do
+ { 'startAndDueDateWidget' => { 'dueDate' => nil } }
+ end
+
+ it 'allows setting a single date to null' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :due_date).from(due_date).to(nil).and(
+ not_change(work_item, :start_date).from(start_date)
+ )
+ end
end
end
end
@@ -179,7 +259,7 @@ RSpec.describe 'Update a work item' do
end
context 'when updating parent' do
- let_it_be(:work_item) { create(:work_item, :task, project: project) }
+ let_it_be(:work_item, reload: true) { create(:work_item, :task, project: project) }
let_it_be(:valid_parent) { create(:work_item, project: project) }
let_it_be(:invalid_parent) { create(:work_item, :task, project: project) }
@@ -346,5 +426,78 @@ RSpec.describe 'Update a work item' do
end
end
end
+
+ context 'when updating assignees' do
+ let(:fields) do
+ <<~FIELDS
+ workItem {
+ widgets {
+ type
+ ... on WorkItemWidgetAssignees {
+ assignees {
+ nodes {
+ id
+ username
+ }
+ }
+ }
+ }
+ }
+ errors
+ FIELDS
+ end
+
+ let(:input) do
+ { 'assigneesWidget' => { 'assigneeIds' => [developer.to_global_id.to_s] } }
+ end
+
+ it 'updates the work item assignee' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ work_item.reload
+ end.to change(work_item, :assignee_ids).from([]).to([developer.id])
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['workItem']['widgets']).to include(
+ {
+ 'type' => 'ASSIGNEES',
+ 'assignees' => {
+ 'nodes' => [
+ { 'id' => developer.to_global_id.to_s, 'username' => developer.username }
+ ]
+ }
+ }
+ )
+ end
+ end
+
+ context 'when unsupported widget input is sent' do
+ let_it_be(:test_case) { create(:work_item_type, :default, :test_case, name: 'some_test_case_name') }
+ let_it_be(:work_item) { create(:work_item, work_item_type: test_case, project: project) }
+
+ let(:input) do
+ {
+ 'hierarchyWidget' => {}
+ }
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: ["Following widget keys are not supported by some_test_case_name type: [:hierarchy_widget]"]
+ 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, :title)
+
+ 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/namespace/root_storage_statistics_spec.rb b/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
index 37cc502103d..8d8a0baae36 100644
--- a/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
+++ b/spec/requests/api/graphql/namespace/root_storage_statistics_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'rendering namespace statistics' do
it_behaves_like 'a working namespace with storage statistics query'
context 'when the namespace is public' do
- let(:group) { create(:group, :public)}
+ let(:group) { create(:group, :public) }
it 'hides statistics for unauthenticated requests' do
post_graphql(query, current_user: nil)
diff --git a/spec/requests/api/graphql/packages/conan_spec.rb b/spec/requests/api/graphql/packages/conan_spec.rb
index 1f3732980d9..5bd5a71bbeb 100644
--- a/spec/requests/api/graphql/packages/conan_spec.rb
+++ b/spec/requests/api/graphql/packages/conan_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'conan package details' do
let_it_be(:package) { create(:conan_package, project: project) }
let(:metadata) { query_graphql_fragment('ConanMetadata') }
- let(:package_files_metadata) {query_graphql_fragment('ConanFileMetadata')}
+ let(:package_files_metadata) { query_graphql_fragment('ConanFileMetadata') }
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
diff --git a/spec/requests/api/graphql/packages/helm_spec.rb b/spec/requests/api/graphql/packages/helm_spec.rb
index 397096f70db..1675b8faa23 100644
--- a/spec/requests/api/graphql/packages/helm_spec.rb
+++ b/spec/requests/api/graphql/packages/helm_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'helm package details' do
let_it_be(:package) { create(:helm_package, project: project) }
- let(:package_files_metadata) {query_graphql_fragment('HelmFileMetadata')}
+ let(:package_files_metadata) { query_graphql_fragment('HelmFileMetadata') }
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 0335c1085b4..c28b37db5af 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe 'package details' do
let(:depth) { 3 }
let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
let(:metadata) { query_graphql_fragment('ComposerMetadata') }
- let(:package_files) {all_graphql_fields_for('PackageFile')}
+ let(:package_files) { all_graphql_fields_for('PackageFile') }
let(:package_global_id) { global_id_of(composer_package) }
let(:package_details) { graphql_data_at(:package) }
diff --git a/spec/requests/api/graphql/project/base_service_spec.rb b/spec/requests/api/graphql/project/base_service_spec.rb
index 5dc0f55db88..58d10ade8cf 100644
--- a/spec/requests/api/graphql/project/base_service_spec.rb
+++ b/spec/requests/api/graphql/project/base_service_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'query Jira service' do
)
end
- let(:services) { graphql_data.dig('project', 'services', 'nodes')}
+ let(:services) { graphql_data.dig('project', 'services', 'nodes') }
it_behaves_like 'unauthorized users cannot read services'
diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
index 2b85704f479..2fe5fb593fe 100644
--- a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
+++ b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
@@ -34,6 +34,8 @@ RSpec.describe 'getting a detailed sentry error' do
context 'when data is loading via reactive cache' do
before do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
post_graphql(query, current_user: current_user)
end
@@ -48,6 +50,10 @@ RSpec.describe 'getting a detailed sentry error' do
.to receive(:issue_details)
.and_return({ issue: sentry_detailed_error })
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with('error_tracking_view_details', values: current_user.id)
+
post_graphql(query, current_user: current_user)
end
diff --git a/spec/requests/api/graphql/project/fork_targets_spec.rb b/spec/requests/api/graphql/project/fork_targets_spec.rb
new file mode 100644
index 00000000000..b21a11ff4dc
--- /dev/null
+++ b/spec/requests/api/graphql/project/fork_targets_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting a list of fork targets for a project' do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:another_group) { create(:group) }
+ let_it_be(:project) { create(:project, :private, group: group) }
+ let_it_be(:user) { create(:user, developer_projects: [project]) }
+
+ let(:current_user) { user }
+ let(:fields) do
+ <<~GRAPHQL
+ forkTargets{
+ nodes { id name fullPath visibility }
+ }
+ GRAPHQL
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ fields
+ )
+ end
+
+ before_all do
+ group.add_owner(user)
+ another_group.add_owner(user)
+ end
+
+ context 'when user has access to the project' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns fork targets for the project' do
+ expect(graphql_data.dig('project', 'forkTargets', 'nodes')).to match_array(
+ [user.namespace, project.namespace, another_group].map do |target|
+ hash_including(
+ {
+ 'id' => target.to_global_id.to_s,
+ 'name' => target.name,
+ 'fullPath' => target.full_path,
+ 'visibility' => target.visibility
+ }
+ )
+ end
+ )
+ end
+ end
+
+ context "when user doesn't have access to the project" do
+ let(:current_user) { create(:user) }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it 'does not return the project' do
+ expect(graphql_data).to eq('project' => nil)
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/jira_import_spec.rb b/spec/requests/api/graphql/project/jira_import_spec.rb
index 98a3f08baa6..202220f4bf6 100644
--- a/spec/requests/api/graphql/project/jira_import_spec.rb
+++ b/spec/requests/api/graphql/project/jira_import_spec.rb
@@ -56,8 +56,8 @@ RSpec.describe 'query Jira import data' do
)
end
- let(:jira_imports) { graphql_data.dig('project', 'jiraImports', 'nodes')}
- let(:jira_import_status) { graphql_data.dig('project', 'jiraImportStatus')}
+ let(:jira_imports) { graphql_data.dig('project', 'jiraImports', 'nodes') }
+ let(:jira_import_status) { graphql_data.dig('project', 'jiraImportStatus') }
context 'when user cannot read Jira import data' do
before do
@@ -89,11 +89,11 @@ RSpec.describe 'query Jira import data' do
context 'list of jira imports sorted ascending by scheduledAt time' do
it 'retuns list of jira imports' do
- jira_proket_keys = jira_imports.map {|ji| ji['jiraProjectKey']}
- usernames = jira_imports.map {|ji| ji.dig('scheduledBy', 'username')}
- imported_issues_count = jira_imports.map {|ji| ji.dig('importedIssuesCount')}
- failed_issues_count = jira_imports.map {|ji| ji.dig('failedToImportCount')}
- total_issue_count = jira_imports.map {|ji| ji.dig('totalIssueCount')}
+ jira_proket_keys = jira_imports.map { |ji| ji['jiraProjectKey'] }
+ usernames = jira_imports.map { |ji| ji.dig('scheduledBy', 'username') }
+ imported_issues_count = jira_imports.map { |ji| ji.dig('importedIssuesCount') }
+ failed_issues_count = jira_imports.map { |ji| ji.dig('failedToImportCount') }
+ total_issue_count = jira_imports.map { |ji| ji.dig('totalIssueCount') }
expect(jira_imports.size).to eq 2
expect(jira_proket_keys).to eq %w(BB AA)
diff --git a/spec/requests/api/graphql/project/project_members_spec.rb b/spec/requests/api/graphql/project/project_members_spec.rb
index 4225c3ad3e8..97a79ab3b0e 100644
--- a/spec/requests/api/graphql/project/project_members_spec.rb
+++ b/spec/requests/api/graphql/project/project_members_spec.rb
@@ -48,24 +48,6 @@ RSpec.describe 'getting project members information' do
expect_array_response(user_2)
end
-
- context 'when the use_keyset_aware_user_search_query FF is off' do
- before do
- stub_feature_flags(use_keyset_aware_user_search_query: false)
- end
-
- it 'raises error on the 2nd page due to missing cursor data' do
- fetch_members(project: parent_project, args: { search: 'Same Name', first: 1 })
-
- # user_2 because the "old" order was undeterministic (insert order), no tie-breaker column
- expect_array_response(user_2)
-
- next_cursor = graphql_data_at(:project, :projectMembers, :pageInfo, :endCursor)
- fetch_members(project: parent_project, args: { search: 'Same Name', first: 1, after: next_cursor })
-
- expect(graphql_errors.first['message']).to include('PG::UndefinedColumn')
- end
- end
end
end
end
diff --git a/spec/requests/api/graphql/project/work_items_spec.rb b/spec/requests/api/graphql/project/work_items_spec.rb
index 66742fcbeb6..6ef28392b8b 100644
--- a/spec/requests/api/graphql/project/work_items_spec.rb
+++ b/spec/requests/api/graphql/project/work_items_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe 'getting an work item list for a project' do
<<~QUERY
edges {
node {
- #{all_graphql_fields_for('workItems'.classify)}
+ #{all_graphql_fields_for('workItems'.classify, max_depth: 2)}
}
}
QUERY
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index 310a8e9fa33..d1b990629a1 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -190,4 +190,100 @@ RSpec.describe 'getting project information' do
end
end
end
+
+ context 'with timelog categories' do
+ let_it_be(:timelog_category) do
+ create(:timelog_category, namespace: project.project_namespace, name: 'TimelogCategoryTest')
+ end
+
+ let(:project_fields) do
+ <<~GQL
+ timelogCategories {
+ nodes {
+ #{all_graphql_fields_for('TimeTrackingTimelogCategory')}
+ }
+ }
+ GQL
+ end
+
+ context 'when user is guest and the project is public' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it 'includes empty timelog categories array' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:project, :timelogCategories, :nodes)).to match([])
+ end
+ end
+
+ context 'when user has reporter role' do
+ before do
+ project.add_reporter(current_user)
+ end
+
+ it 'returns the timelog category with all its fields' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:project, :timelogCategories, :nodes))
+ .to contain_exactly(a_graphql_entity_for(timelog_category))
+ end
+
+ context 'when timelog_categories flag is disabled' do
+ before do
+ stub_feature_flags(timelog_categories: false)
+ end
+
+ it 'returns no timelog categories' do
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:project, :timelogCategories)).to be_nil
+ end
+ end
+ end
+
+ context 'for N+1 queries' do
+ let!(:project1) { create(:project) }
+ let!(:project2) { create(:project) }
+
+ before do
+ project1.add_reporter(current_user)
+ project2.add_reporter(current_user)
+ end
+
+ it 'avoids N+1 database queries' do
+ pending('See: https://gitlab.com/gitlab-org/gitlab/-/issues/369396')
+
+ ctx = { current_user: current_user }
+
+ baseline_query = <<~GQL
+ query {
+ a: project(fullPath: "#{project1.full_path}") { ... p }
+ }
+
+ fragment p on Project {
+ timelogCategories { nodes { name } }
+ }
+ GQL
+
+ query = <<~GQL
+ query {
+ a: project(fullPath: "#{project1.full_path}") { ... p }
+ b: project(fullPath: "#{project2.full_path}") { ... p }
+ }
+
+ fragment p on Project {
+ timelogCategories { nodes { name } }
+ }
+ GQL
+
+ control = ActiveRecord::QueryRecorder.new do
+ run_with_clean_state(baseline_query, context: ctx)
+ end
+
+ expect { run_with_clean_state(query, context: ctx) }.not_to exceed_query_limit(control)
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb
index f17d2ebbb7e..34644e5893a 100644
--- a/spec/requests/api/graphql/work_item_spec.rb
+++ b/spec/requests/api/graphql/work_item_spec.rb
@@ -8,7 +8,16 @@ RSpec.describe 'Query.work_item(id)' do
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, :private) }
- let_it_be(:work_item) { create(:work_item, project: project, description: '- List item', weight: 1) }
+ let_it_be(:work_item) do
+ create(
+ :work_item,
+ project: project,
+ description: '- List item',
+ start_date: Date.today,
+ due_date: 1.week.from_now
+ )
+ end
+
let_it_be(:child_item1) { create(:work_item, :task, project: project) }
let_it_be(:child_item2) { create(:work_item, :task, confidential: true, project: project) }
let_it_be(:child_link1) { create(:parent_link, work_item_parent: work_item, work_item: child_item1) }
@@ -16,7 +25,7 @@ RSpec.describe 'Query.work_item(id)' do
let(:current_user) { developer }
let(:work_item_data) { graphql_data['workItem'] }
- let(:work_item_fields) { all_graphql_fields_for('WorkItem') }
+ let(:work_item_fields) { all_graphql_fields_for('WorkItem', max_depth: 2) }
let(:global_id) { work_item.to_gid.to_s }
let(:query) do
@@ -41,8 +50,10 @@ RSpec.describe 'Query.work_item(id)' do
'lockVersion' => work_item.lock_version,
'state' => "OPEN",
'title' => work_item.title,
+ 'confidential' => work_item.confidential,
'workItemType' => hash_including('id' => work_item.work_item_type.to_gid.to_s),
- 'userPermissions' => { 'readWorkItem' => true, 'updateWorkItem' => true, 'deleteWorkItem' => false }
+ 'userPermissions' => { 'readWorkItem' => true, 'updateWorkItem' => true, 'deleteWorkItem' => false },
+ 'project' => hash_including('id' => project.to_gid.to_s, 'fullPath' => project.full_path)
)
end
@@ -163,14 +174,24 @@ RSpec.describe 'Query.work_item(id)' do
end
end
- describe 'weight widget' do
+ describe 'assignees widget' do
+ let(:assignees) { create_list(:user, 2) }
+ let(:work_item) { create(:work_item, project: project, assignees: assignees) }
+
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
- ... on WorkItemWidgetWeight {
- weight
+ ... on WorkItemWidgetAssignees {
+ allowsMultipleAssignees
+ canInviteMembers
+ assignees {
+ nodes {
+ id
+ username
+ }
+ }
}
}
GRAPHQL
@@ -181,30 +202,34 @@ RSpec.describe 'Query.work_item(id)' do
'id' => work_item.to_gid.to_s,
'widgets' => include(
hash_including(
- 'type' => 'WEIGHT',
- 'weight' => work_item.weight
+ 'type' => 'ASSIGNEES',
+ 'allowsMultipleAssignees' => boolean,
+ 'canInviteMembers' => boolean,
+ 'assignees' => {
+ 'nodes' => match_array(
+ assignees.map { |a| { 'id' => a.to_gid.to_s, 'username' => a.username } }
+ )
+ }
)
)
)
end
end
- describe 'assignees widget' do
- let(:assignees) { create_list(:user, 2) }
- let(:work_item) { create(:work_item, project: project, assignees: assignees) }
+ describe 'labels widget' do
+ let(:labels) { create_list(:label, 2, project: project) }
+ let(:work_item) { create(:work_item, project: project, labels: labels) }
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
- ... on WorkItemWidgetAssignees {
- allowsMultipleAssignees
- canInviteMembers
- assignees {
+ ... on WorkItemWidgetLabels {
+ labels {
nodes {
id
- username
+ title
}
}
}
@@ -217,12 +242,10 @@ RSpec.describe 'Query.work_item(id)' do
'id' => work_item.to_gid.to_s,
'widgets' => include(
hash_including(
- 'type' => 'ASSIGNEES',
- 'allowsMultipleAssignees' => boolean,
- 'canInviteMembers' => boolean,
- 'assignees' => {
+ 'type' => 'LABELS',
+ 'labels' => {
'nodes' => match_array(
- assignees.map { |a| { 'id' => a.to_gid.to_s, 'username' => a.username } }
+ labels.map { |a| { 'id' => a.to_gid.to_s, 'title' => a.title } }
)
}
)
@@ -230,6 +253,34 @@ RSpec.describe 'Query.work_item(id)' do
)
end
end
+
+ describe 'start and due date widget' do
+ let(:work_item_fields) do
+ <<~GRAPHQL
+ id
+ widgets {
+ type
+ ... on WorkItemWidgetStartAndDueDate {
+ startDate
+ dueDate
+ }
+ }
+ GRAPHQL
+ end
+
+ it 'returns widget information' do
+ expect(work_item_data).to include(
+ 'id' => work_item.to_gid.to_s,
+ 'widgets' => include(
+ hash_including(
+ 'type' => 'START_AND_DUE_DATE',
+ 'startDate' => work_item.start_date.to_s,
+ 'dueDate' => work_item.due_date.to_s
+ )
+ )
+ )
+ end
+ end
end
context 'when an Issue Global ID is provided' do
diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb
index d94257c61eb..1c1ae73ddfe 100644
--- a/spec/requests/api/graphql_spec.rb
+++ b/spec/requests/api/graphql_spec.rb
@@ -463,50 +463,21 @@ RSpec.describe 'GraphQL' do
)
end
- context 'when new_graphql_keyset_pagination feature flag is off' do
- before do
- stub_feature_flags(new_graphql_keyset_pagination: false)
- end
-
- it 'paginates datetimes correctly when they have millisecond data' do
- # let's make sure we're actually querying a timestamp, just in case
- expect(Gitlab::Graphql::Pagination::Keyset::QueryBuilder)
- .to receive(:new).with(anything, anything, hash_including('created_at'), anything).and_call_original
+ it 'paginates datetimes correctly when they have millisecond data' do
+ execute_query
+ first_page = graphql_data
+ edges = first_page.dig(*issues_edges)
+ cursor = first_page.dig(*end_cursor)
- execute_query
- first_page = graphql_data
- edges = first_page.dig(*issues_edges)
- cursor = first_page.dig(*end_cursor)
+ expect(edges.count).to eq(6)
+ expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s)
- expect(edges.count).to eq(6)
- expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s)
+ execute_query(after: cursor)
+ second_page = graphql_data
+ edges = second_page.dig(*issues_edges)
- execute_query(after: cursor)
- second_page = graphql_data
- edges = second_page.dig(*issues_edges)
-
- expect(edges.count).to eq(4)
- expect(edges.last['node']['iid']).to eq(issues[0].iid.to_s)
- end
- end
-
- context 'when new_graphql_keyset_pagination feature flag is on' do
- it 'paginates datetimes correctly when they have millisecond data' do
- execute_query
- first_page = graphql_data
- edges = first_page.dig(*issues_edges)
- cursor = first_page.dig(*end_cursor)
-
- expect(edges.count).to eq(6)
- expect(edges.last['node']['iid']).to eq(issues[4].iid.to_s)
-
- execute_query(after: cursor)
- second_page = graphql_data
- edges = second_page.dig(*issues_edges)
-
- expect(edges.count).to eq(4)
- expect(edges.last['node']['iid']).to eq(issues[0].iid.to_s)
- end
+ expect(edges.count).to eq(4)
+ expect(edges.last['node']['iid']).to eq(issues[0].iid.to_s)
end
end
end
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index a7b4bea362f..4fed7dd7624 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe API::GroupVariables do
it 'creates variable' do
expect do
post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
- end.to change {group.variables.count}.by(1)
+ end.to change { group.variables.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
@@ -105,7 +105,7 @@ RSpec.describe API::GroupVariables do
it 'creates variable with optional attributes' do
expect do
post api("/groups/#{group.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
- end.to change {group.variables.count}.by(1)
+ end.to change { group.variables.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
expect(json_response['key']).to eq('TEST_VARIABLE_2')
@@ -119,7 +119,7 @@ RSpec.describe API::GroupVariables do
it 'does not allow to duplicate variable key' do
expect do
post api("/groups/#{group.id}/variables", user), params: { key: variable.key, value: 'VALUE_2' }
- end.to change {group.variables.count}.by(0)
+ end.to change { group.variables.count }.by(0)
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -207,7 +207,7 @@ RSpec.describe API::GroupVariables do
delete api("/groups/#{group.id}/variables/#{variable.key}", user)
expect(response).to have_gitlab_http_status(:no_content)
- end.to change {group.variables.count}.by(-1)
+ end.to change { group.variables.count }.by(-1)
end
it 'responds with 404 Not Found if requesting non-existing variable' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 3bc3cce5310..bc37f8e4655 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -864,7 +864,7 @@ RSpec.describe API::Groups do
end
describe 'PUT /groups/:id' do
- let(:new_group_name) { 'New Group'}
+ let(:new_group_name) { 'New Group' }
let(:file_path) { 'spec/fixtures/dk.png' }
it_behaves_like 'group avatar upload' do
diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index 8961f3177b6..e29e5c31a34 100644
--- a/spec/requests/api/helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -26,8 +26,8 @@ RSpec.describe API::Helpers do
}
end
- let(:header) { }
- let(:request) { Grape::Request.new(env)}
+ let(:header) {}
+ let(:request) { Grape::Request.new(env) }
let(:params) { request.params }
before do
@@ -539,7 +539,7 @@ RSpec.describe API::Helpers do
let(:token) { create(:oauth_access_token) }
before do
- env['HTTP_AUTHORIZATION'] = "Bearer #{token.token}"
+ env['HTTP_AUTHORIZATION'] = "Bearer #{token.plaintext_token}"
end
it_behaves_like 'sudo'
diff --git a/spec/requests/api/integrations_spec.rb b/spec/requests/api/integrations_spec.rb
index b2db7f7caef..1e8061f9606 100644
--- a/spec/requests/api/integrations_spec.rb
+++ b/spec/requests/api/integrations_spec.rb
@@ -66,6 +66,7 @@ RSpec.describe API::Integrations do
mattermost: %i[deployment_channel labels_to_be_notified],
mock_ci: %i[enable_ssl_verification],
prometheus: %i[manual_configuration],
+ pumble: %i[branches_to_be_notified notify_only_broken_pipelines],
slack: %i[alert_events alert_channel deployment_channel labels_to_be_notified],
unify_circuit: %i[branches_to_be_notified notify_only_broken_pipelines],
webex_teams: %i[branches_to_be_notified notify_only_broken_pipelines]
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index acfe476a864..e100684018a 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -376,10 +376,17 @@ RSpec.describe API::Internal::Base do
shared_examples 'rate limited request' do
let(:action) { 'git-upload-pack' }
let(:actor) { key }
+ let(:rate_limiter) { double(:rate_limiter, ip: "127.0.0.1", trusted_ip?: false) }
+
+ before do
+ allow(::Gitlab::Auth::IpRateLimiter).to receive(:new).with("127.0.0.1").and_return(rate_limiter)
+ end
it 'is throttled by rate limiter' do
allow(::Gitlab::ApplicationRateLimiter).to receive(:threshold).and_return(1)
+
expect(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:gitlab_shell_operation, scope: [action, project.full_path, actor]).twice.and_call_original
+ expect(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:gitlab_shell_operation, scope: [action, project.full_path, "127.0.0.1"]).and_call_original
request
@@ -402,6 +409,28 @@ RSpec.describe API::Internal::Base do
subject
end
end
+
+ context 'when rate_limit_gitlab_shell_by_ip feature flag is disabled' do
+ before do
+ stub_feature_flags(rate_limit_gitlab_shell_by_ip: false)
+ end
+
+ it 'is not throttled by rate limiter' do
+ expect(::Gitlab::ApplicationRateLimiter).not_to receive(:throttled?)
+
+ subject
+ end
+ end
+
+ context 'when the IP is in a trusted range' do
+ let(:rate_limiter) { double(:rate_limiter, ip: "127.0.0.1", trusted_ip?: true) }
+
+ it 'is not throttled by rate limiter' do
+ expect(::Gitlab::ApplicationRateLimiter).not_to receive(:throttled?)
+
+ subject
+ end
+ end
end
context "access granted" do
@@ -1451,7 +1480,7 @@ RSpec.describe API::Internal::Base do
describe 'POST /internal/two_factor_otp_check' do
let(:key_id) { key.id }
- let(:otp) { '123456'}
+ let(:otp) { '123456' }
subject do
post api('/internal/two_factor_otp_check'),
@@ -1472,7 +1501,7 @@ RSpec.describe API::Internal::Base do
describe 'POST /internal/two_factor_manual_otp_check' do
let(:key_id) { key.id }
- let(:otp) { '123456'}
+ let(:otp) { '123456' }
subject do
post api('/internal/two_factor_manual_otp_check'),
@@ -1493,7 +1522,7 @@ RSpec.describe API::Internal::Base do
describe 'POST /internal/two_factor_push_otp_check' do
let(:key_id) { key.id }
- let(:otp) { '123456'}
+ let(:otp) { '123456' }
subject do
post api('/internal/two_factor_push_otp_check'),
@@ -1514,7 +1543,7 @@ RSpec.describe API::Internal::Base do
describe 'POST /internal/two_factor_manual_otp_check' do
let(:key_id) { key.id }
- let(:otp) { '123456'}
+ let(:otp) { '123456' }
subject do
post api('/internal/two_factor_manual_otp_check'),
@@ -1534,7 +1563,7 @@ RSpec.describe API::Internal::Base do
describe 'POST /internal/two_factor_push_otp_check' do
let(:key_id) { key.id }
- let(:otp) { '123456'}
+ let(:otp) { '123456' }
subject do
post api('/internal/two_factor_push_otp_check'),
diff --git a/spec/requests/api/internal/error_tracking_spec.rb b/spec/requests/api/internal/error_tracking_spec.rb
index 69eb54d5ed2..4c420eb8505 100644
--- a/spec/requests/api/internal/error_tracking_spec.rb
+++ b/spec/requests/api/internal/error_tracking_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe API::Internal::ErrorTracking do
let(:secret_token) { Gitlab::CurrentSettings.error_tracking_access_token }
let(:headers) do
- { ::API::Internal::ErrorTracking::GITLAB_ERROR_TRACKING_TOKEN_HEADER => Base64.encode64(secret_token) }
+ { ::API::Internal::ErrorTracking::GITLAB_ERROR_TRACKING_TOKEN_HEADER => secret_token }
end
describe 'GET /internal/error_tracking/allowed' do
diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb
index c0a979995c9..67d8a18dfd8 100644
--- a/spec/requests/api/internal/kubernetes_spec.rb
+++ b/spec/requests/api/internal/kubernetes_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe API::Internal::Kubernetes do
end
end
- describe 'POST /internal/kubernetes/usage_metrics' do
+ describe 'POST /internal/kubernetes/usage_metrics', :clean_gitlab_redis_shared_state do
def send_request(headers: {}, params: {})
post api('/internal/kubernetes/usage_metrics'), params: params, headers: headers.reverse_merge(jwt_auth_headers)
end
@@ -69,29 +69,102 @@ RSpec.describe API::Internal::Kubernetes do
context 'is authenticated for an agent' do
let!(:agent_token) { create(:cluster_agent_token) }
+ # Todo: Remove gitops_sync_count and k8s_api_proxy_request_count in the next milestone
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/369489
+ # We're only keeping it for backwards compatibility until KAS is released
+ # using `counts:` instead
+ context 'deprecated events' do
+ it 'returns no_content for valid events' do
+ send_request(params: { gitops_sync_count: 10, k8s_api_proxy_request_count: 5 })
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'returns no_content for counts of zero' do
+ send_request(params: { gitops_sync_count: 0, k8s_api_proxy_request_count: 0 })
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'returns 400 for non number' do
+ send_request(params: { gitops_sync_count: 'string', k8s_api_proxy_request_count: 1 })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 for negative number' do
+ send_request(params: { gitops_sync_count: -1, k8s_api_proxy_request_count: 1 })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'tracks events' do
+ counters = { gitops_sync_count: 10, k8s_api_proxy_request_count: 5 }
+ expected_counters = {
+ kubernetes_agent_gitops_sync: counters[:gitops_sync_count],
+ kubernetes_agent_k8s_api_proxy_request: counters[:k8s_api_proxy_request_count]
+ }
+
+ send_request(params: counters)
+
+ expect(Gitlab::UsageDataCounters::KubernetesAgentCounter.totals).to eq(expected_counters)
+ end
+ end
+
it 'returns no_content for valid events' do
- send_request(params: { gitops_sync_count: 10, k8s_api_proxy_request_count: 5 })
+ counters = { gitops_sync: 10, k8s_api_proxy_request: 5 }
+ unique_counters = { agent_users_using_ci_tunnel: [10] }
+
+ send_request(params: { counters: counters, unique_counters: unique_counters })
expect(response).to have_gitlab_http_status(:no_content)
end
it 'returns no_content for counts of zero' do
- send_request(params: { gitops_sync_count: 0, k8s_api_proxy_request_count: 0 })
+ counters = { gitops_sync: 0, k8s_api_proxy_request: 0 }
+ unique_counters = { agent_users_using_ci_tunnel: [] }
+
+ send_request(params: { counters: counters, unique_counters: unique_counters })
expect(response).to have_gitlab_http_status(:no_content)
end
- it 'returns 400 for non number' do
- send_request(params: { gitops_sync_count: 'string', k8s_api_proxy_request_count: 1 })
+ it 'returns 400 for non counter number' do
+ counters = { gitops_sync: 'string', k8s_api_proxy_request: 0 }
+
+ send_request(params: { counters: counters })
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'returns 400 for negative number' do
- send_request(params: { gitops_sync_count: -1, k8s_api_proxy_request_count: 1 })
+ it 'returns 400 for non unique_counter set' do
+ unique_counters = { agent_users_using_ci_tunnel: 1 }
+
+ send_request(params: { unique_counters: unique_counters })
expect(response).to have_gitlab_http_status(:bad_request)
end
+
+ it 'tracks events' do
+ counters = { gitops_sync: 10, k8s_api_proxy_request: 5 }
+ unique_counters = { agent_users_using_ci_tunnel: [10] }
+ expected_counters = {
+ kubernetes_agent_gitops_sync: counters[:gitops_sync],
+ kubernetes_agent_k8s_api_proxy_request: counters[:k8s_api_proxy_request]
+ }
+
+ send_request(params: { counters: counters, unique_counters: unique_counters })
+
+ expect(Gitlab::UsageDataCounters::KubernetesAgentCounter.totals).to eq(expected_counters)
+
+ expect(
+ Gitlab::UsageDataCounters::HLLRedisCounter
+ .unique_events(
+ event_names: 'agent_users_using_ci_tunnel',
+ start_date: Date.current, end_date: Date.current + 10
+ )
+ ).to eq(1)
+ end
end
end
@@ -180,4 +253,95 @@ RSpec.describe API::Internal::Kubernetes do
end
end
end
+
+ describe 'GET /internal/kubernetes/project_info' do
+ def send_request(headers: {}, params: {})
+ get api('/internal/kubernetes/project_info'), params: params, headers: headers.reverse_merge(jwt_auth_headers)
+ end
+
+ include_examples 'authorization'
+ include_examples 'agent authentication'
+
+ context 'an agent is found' do
+ let_it_be(:agent_token) { create(:cluster_agent_token) }
+
+ shared_examples 'agent token tracking'
+
+ context 'project is public' do
+ let(:project) { create(:project, :public) }
+
+ it 'returns expected data', :aggregate_failures do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:success)
+
+ expect(json_response).to match(
+ a_hash_including(
+ 'project_id' => project.id,
+ 'gitaly_info' => a_hash_including(
+ 'address' => match(/\.socket$/),
+ 'token' => 'secret',
+ 'features' => {}
+ ),
+ 'gitaly_repository' => a_hash_including(
+ 'storage_name' => project.repository_storage,
+ 'relative_path' => project.disk_path + '.git',
+ 'gl_repository' => "project-#{project.id}",
+ 'gl_project_path' => project.full_path
+ ),
+ 'default_branch' => project.default_branch_or_main
+ )
+ )
+ end
+
+ context 'repository is for project members only' do
+ let(:project) { create(:project, :public, :repository_private) }
+
+ it 'returns 404' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'project is private' do
+ let(:project) { create(:project, :private) }
+
+ it 'returns 404' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'and agent belongs to project' do
+ let(:agent_token) { create(:cluster_agent_token, agent: create(:cluster_agent, project: project)) }
+
+ it 'returns 200' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
+
+ context 'project is internal' do
+ let(:project) { create(:project, :internal) }
+
+ it 'returns 404' do
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'project does not exist' do
+ it 'returns 404' do
+ send_request(params: { id: non_existing_record_id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/internal/workhorse_spec.rb b/spec/requests/api/internal/workhorse_spec.rb
index d40c14cc0fd..bcf63bf7c2f 100644
--- a/spec/requests/api/internal/workhorse_spec.rb
+++ b/spec/requests/api/internal/workhorse_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe API::Internal::Workhorse, :allow_forgery_protection do
end
it { expect_status(:success) }
+
it 'returns the temp upload path' do
subject
expect(json_response['TempPath']).to eq(Rails.root.join('tmp/tests/public/uploads/tmp').to_s)
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index cb351635081..a795b49c44e 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -447,7 +447,7 @@ RSpec.describe API::Invitations do
emails = 'email3@example.com,email4@example.com,email5@example.com,email6@example.com,email7@example.com'
- unresolved_n_plus_ones = 32 # currently there are 8 queries added per email
+ unresolved_n_plus_ones = 36 # currently there are 9 queries added per email
expect do
post invitations_url(group, maintainer), params: { email: emails, access_level: Member::DEVELOPER }
diff --git a/spec/requests/api/issue_links_spec.rb b/spec/requests/api/issue_links_spec.rb
index 90238c8bf76..98f72f22cdc 100644
--- a/spec/requests/api/issue_links_spec.rb
+++ b/spec/requests/api/issue_links_spec.rb
@@ -162,12 +162,29 @@ RSpec.describe API::IssueLinks do
end
context 'when unauthenticated' do
- it 'returns 401' do
- issue_link = create(:issue_link)
+ context 'when accessing an issue of a private project' do
+ it 'returns 401' do
+ issue_link = create(:issue_link)
- perform_request(issue_link.id)
+ perform_request(issue_link.id)
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ # This isn't ideal, see https://gitlab.com/gitlab-org/gitlab/-/issues/364077
+ context 'when accessing an issue of a public project' do
+ let(:project) { create(:project, :public) }
+ let(:issue) { create(:issue, project: project) }
+ let(:public_issue) { create(:issue, project: project) }
+
+ it 'returns 401' do
+ issue_link = create(:issue_link, source: issue, target: public_issue)
+
+ perform_request(issue_link.id)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
end
end
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
index 346f8975835..ec6cc060c83 100644
--- a/spec/requests/api/issues/get_project_issues_spec.rb
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe API::Issues do
create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, merge_requests_access_level: ProjectFeature::PRIVATE)
end
+ let_it_be(:group) { create(:group, :public) }
+
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
@@ -85,6 +87,8 @@ RSpec.describe API::Issues do
end
before_all do
+ group.add_reporter(user)
+ group.add_guest(guest)
project.add_reporter(user)
project.add_guest(guest)
private_mrs_project.add_reporter(user)
@@ -107,6 +111,22 @@ RSpec.describe API::Issues do
end
end
+ shared_examples 'returns project issues without confidential issues for guests' do
+ specify do
+ get api(api_url, guest)
+
+ expect_paginated_array_response_contain_exactly(open_issue.id, closed_issue.id)
+ end
+ end
+
+ shared_examples 'returns all project issues for reporters' do
+ specify do
+ get api(api_url, user)
+
+ expect_paginated_array_response_contain_exactly(open_issue.id, confidential_issue.id, closed_issue.id)
+ end
+ end
+
describe "GET /projects/:id/issues" do
let(:base_url) { "/projects/#{project.id}" }
@@ -183,6 +203,30 @@ RSpec.describe API::Issues do
end
end
+ context 'when user is an inherited member from the group' do
+ let!(:open_issue) { create(:issue, project: group_project) }
+ let!(:confidential_issue) { create(:issue, :confidential, project: group_project) }
+ let!(:closed_issue) { create(:issue, state: :closed, project: group_project) }
+
+ let!(:api_url) { "/projects/#{group_project.id}/issues" }
+
+ context 'and group project is public and issues are private' do
+ let_it_be(:group_project) do
+ create(:project, :public, issues_access_level: ProjectFeature::PRIVATE, group: group)
+ end
+
+ it_behaves_like 'returns project issues without confidential issues for guests'
+ it_behaves_like 'returns all project issues for reporters'
+ end
+
+ context 'and group project is private' do
+ let_it_be(:group_project) { create(:project, :private, group: group) }
+
+ it_behaves_like 'returns project issues without confidential issues for guests'
+ it_behaves_like 'returns all project issues for reporters'
+ end
+ end
+
it 'avoids N+1 queries' do
get api("/projects/#{project.id}/issues", user)
diff --git a/spec/requests/api/markdown_spec.rb b/spec/requests/api/markdown_spec.rb
index 47e1f007daa..3e702b05bc9 100644
--- a/spec/requests/api/markdown_spec.rb
+++ b/spec/requests/api/markdown_spec.rb
@@ -5,9 +5,11 @@ require "spec_helper"
RSpec.describe API::Markdown do
describe "POST /markdown" do
let(:user) {} # No-op. It gets overwritten in the contexts below.
+ let(:disable_authenticate_markdown_api) { false }
before do
stub_commonmark_sourcepos_disabled
+ stub_feature_flags(authenticate_markdown_api: false) if disable_authenticate_markdown_api
post api("/markdown", user), params: params
end
@@ -21,27 +23,53 @@ RSpec.describe API::Markdown do
end
end
- shared_examples "404 Project Not Found" do
- it "responses with 404 Not Found" do
+ shared_examples '404 Project Not Found' do
+ it 'responds with 404 Not Found' do
expect(response).to have_gitlab_http_status(:not_found)
expect(response.headers["Content-Type"]).to eq("application/json")
expect(json_response).to be_a(Hash)
- expect(json_response["message"]).to eq("404 Project Not Found")
+ expect(json_response['message']).to eq('404 Project Not Found')
end
end
- context "when arguments are invalid" do
- context "when text is missing" do
- let(:params) { {} }
+ shared_examples '400 Bad Request' do
+ it 'responds with 400 Bad Request' do
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(response.headers['Content-Type']).to eq('application/json')
+ expect(json_response).to be_a(Hash)
+ expect(json_response['error']).to eq('text is missing')
+ end
+ end
+
+ context 'when not logged in' do
+ let(:user) {}
+ let(:params) { {} }
- it "responses with 400 Bad Request" do
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(response.headers["Content-Type"]).to eq("application/json")
+ context 'and authenticate_markdown_api turned on' do
+ it 'responds with 401 Unathorized' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response.headers['Content-Type']).to eq('application/json')
expect(json_response).to be_a(Hash)
- expect(json_response["error"]).to eq("text is missing")
+ expect(json_response['message']).to eq('401 Unauthorized')
end
end
+ context 'and authenticate_markdown_api turned off' do
+ let(:disable_authenticate_markdown_api) { true }
+
+ it_behaves_like '400 Bad Request'
+ end
+ end
+
+ context 'when arguments are invalid' do
+ let(:user) { create(:user) }
+
+ context 'when text is missing' do
+ let(:params) { {} }
+
+ it_behaves_like '400 Bad Request'
+ end
+
context "when project is not found" do
let(:params) { { text: "Hello world!", gfm: true, project: "Dummy project" } }
@@ -53,6 +81,7 @@ RSpec.describe API::Markdown do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
+ let(:user) { create(:user) }
let(:issue_url) { "http://#{Gitlab.config.gitlab.host}/#{issue.project.namespace.path}/#{issue.project.path}/-/issues/#{issue.iid}" }
let(:text) { ":tada: Hello world! :100: #{issue.to_reference}" }
@@ -131,14 +160,13 @@ RSpec.describe API::Markdown do
end
context 'when not logged in' do
- let(:user) { }
+ let(:user) {}
+ let(:disable_authenticate_markdown_api) { true }
it_behaves_like 'user without proper access'
end
context 'when logged in as user without access' do
- let(:user) { create(:user) }
-
it_behaves_like 'user without proper access'
end
@@ -175,8 +203,9 @@ RSpec.describe API::Markdown do
end
end
- context 'when not logged in' do
- let(:user) { }
+ context 'when not logged in and authenticate_markdown_api turned off' do
+ let(:user) {}
+ let(:disable_authenticate_markdown_api) { true }
it_behaves_like 'user without proper access'
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index ba82d2facc6..1b378788b6a 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe API::MavenPackages do
end
let(:version) { '1.0-SNAPSHOT' }
- let(:param_path) { "#{package_name}/#{version}"}
+ let(:param_path) { "#{package_name}/#{version}" }
before do
project.add_developer(user)
@@ -1000,20 +1000,45 @@ RSpec.describe API::MavenPackages do
context 'for sha1 file' do
let(:dummy_package) { double(Packages::Package) }
+ let(:file_upload) { fixture_file_upload('spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.pom.sha1') }
+ let(:stored_sha1) { File.read(file_upload.path) }
- it 'checks the sha1' do
+ subject(:upload) { upload_file_with_token(params: params, file_extension: 'pom.sha1') }
+
+ before do
# The sha verification done by the maven api is between:
# - the sha256 set by workhorse helpers
# - the sha256 of the sha1 of the uploaded package file
# We're going to send `file_upload` for the sha1 and stub the sha1 of the package file so that
# both sha256 being the same
- expect(::Packages::PackageFileFinder).to receive(:new).and_return(double(execute!: dummy_package))
- expect(dummy_package).to receive(:file_sha1).and_return(File.read(file_upload.path))
+ allow(::Packages::PackageFileFinder).to receive(:new).and_return(double(execute!: dummy_package))
+ allow(dummy_package).to receive(:file_sha1).and_return(stored_sha1)
+ end
- upload_file_with_token(params: params, file_extension: 'jar.sha1')
+ it 'returns no content' do
+ upload
expect(response).to have_gitlab_http_status(:no_content)
end
+
+ context 'when the stored sha1 is not the same' do
+ let(:sent_sha1) { File.read(file_upload.path) }
+ let(:stored_sha1) { 'wrong sha1' }
+
+ it 'logs an error and returns conflict' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ instance_of(ArgumentError),
+ message: 'maven package file sha1 conflict',
+ stored_sha1: stored_sha1,
+ received_sha256: Digest::SHA256.hexdigest(sent_sha1),
+ sha256_hexdigest_of_stored_sha1: Digest::SHA256.hexdigest(stored_sha1)
+ )
+
+ upload
+
+ expect(response).to have_gitlab_http_status(:conflict)
+ end
+ end
end
context 'for md5 file' do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index e4c2f17af47..9df9c75b020 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -3,14 +3,14 @@
require 'spec_helper'
RSpec.describe API::Members do
- let(:maintainer) { create(:user, username: 'maintainer_user') }
- let(:maintainer2) { create(:user, username: 'user-with-maintainer-role') }
- let(:developer) { create(:user) }
- let(:access_requester) { create(:user) }
- let(:stranger) { create(:user) }
- let(:user_with_minimal_access) { create(:user) }
-
- let(:project) do
+ let_it_be(:maintainer) { create(:user, username: 'maintainer_user') }
+ let_it_be(:maintainer2) { create(:user, username: 'user-with-maintainer-role') }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:access_requester) { create(:user) }
+ let_it_be(:stranger) { create(:user) }
+ let_it_be(:user_with_minimal_access) { create(:user) }
+
+ let_it_be(:project, refind: true) do
create(:project, :public, creator_id: maintainer.id, group: create(:group, :public)) do |project|
project.add_maintainer(maintainer)
project.add_developer(developer, current_user: maintainer)
@@ -18,7 +18,7 @@ RSpec.describe API::Members do
end
end
- let!(:group) do
+ let_it_be(:group, refind: true) do
create(:group, :public) do |group|
group.add_owner(maintainer)
group.add_developer(developer, maintainer)
@@ -187,8 +187,8 @@ RSpec.describe API::Members do
end
context 'with a subgroup' do
- let(:group) { create(:group, :private)}
- let(:subgroup) { create(:group, :private, parent: group)}
+ let(:group) { create(:group, :private) }
+ let(:subgroup) { create(:group, :private, parent: group) }
let(:project) { create(:project, group: subgroup) }
before do
@@ -231,6 +231,33 @@ RSpec.describe API::Members do
end
end
end
+
+ context 'with ancestral membership' do
+ shared_examples 'response with correct access levels' do
+ it do
+ get api("/#{source_type.pluralize}/#{source.id}/members/#{all ? 'all/' : ''}#{developer.id}", developer)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['access_level']).to eq(Member::MAINTAINER)
+ end
+ end
+
+ before do
+ source.add_maintainer(developer)
+ end
+
+ include_examples 'response with correct access levels'
+
+ context 'having email invite' do
+ before do
+ Member
+ .find_by(source: group, user: developer)
+ .update!(invite_email: 'email@email.com')
+ end
+
+ include_examples 'response with correct access levels'
+ end
+ end
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 695c0ed1749..2a03ae89389 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe API::MergeRequests do
context 'with merge status recheck projection' do
it 'checks mergeability asynchronously' do
- expect_next_instance_of(check_service_class) do |service|
+ expect_next_instances_of(check_service_class, (1..2)) do |service|
expect(service).not_to receive(:execute)
expect(service).to receive(:async_execute).and_call_original
end
@@ -595,6 +595,22 @@ RSpec.describe API::MergeRequests do
end
end
+ RSpec.shared_examples 'a non-cached MergeRequest api request' do |call_count|
+ it 'serializes merge request' do
+ expect(API::Entities::MergeRequestBasic).to receive(:represent).exactly(call_count).times.and_call_original
+
+ get api(endpoint_path)
+ end
+ end
+
+ RSpec.shared_examples 'a cached MergeRequest api request' do
+ it 'serializes merge request' do
+ expect(API::Entities::MergeRequestBasic).not_to receive(:represent)
+
+ get api(endpoint_path)
+ end
+ end
+
describe 'route shadowing' do
include GrapePathHelpers::NamedRouteMatcher
@@ -979,13 +995,43 @@ RSpec.describe API::MergeRequests do
end
end
- describe "GET /projects/:id/merge_requests" do
+ describe "GET /projects/:id/merge_requests", :use_clean_rails_memory_store_caching do
include_context 'with merge requests'
let(:endpoint_path) { "/projects/#{project.id}/merge_requests" }
it_behaves_like 'merge requests list'
+ context 'caching' do
+ let(:params) { {} }
+
+ before do
+ get api(endpoint_path)
+ end
+
+ context 'when it is cached' do
+ it_behaves_like 'a cached MergeRequest api request'
+ end
+
+ context 'when it is not cached' do
+ context 'when the status changes' do
+ before do
+ merge_request.mark_as_unchecked!
+ end
+
+ it_behaves_like 'a non-cached MergeRequest api request', 1
+ end
+
+ context 'when another user requests' do
+ before do
+ sign_in(user2)
+ end
+
+ it_behaves_like 'a non-cached MergeRequest api request', 4
+ end
+ end
+ end
+
it "returns 404 for non public projects" do
project = create(:project, :private)
@@ -1466,6 +1512,45 @@ RSpec.describe API::MergeRequests do
end
end
+ describe 'GET /projects/:id/merge_requests/:merge_request_iid/reviewers' do
+ it 'returns reviewers' do
+ reviewer = create(:user)
+ merge_request.merge_request_reviewers.create!(reviewer: reviewer)
+
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/reviewers", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(merge_request.merge_request_reviewers.size)
+
+ expect(json_response.last['user']['id']).to eq(reviewer.id)
+ expect(json_response.last['user']['name']).to eq(reviewer.name)
+ expect(json_response.last['user']['username']).to eq(reviewer.username)
+ expect(json_response.last['state']).to eq('unreviewed')
+ expect(json_response.last['updated_state_by']).to be_nil
+ expect(json_response.last['created_at']).to be_present
+ end
+
+ it 'returns a 404 when iid does not exist' do
+ get api("/projects/#{project.id}/merge_requests/#{non_existing_record_iid}/reviewers", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns a 404 when id is used instead of iid' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/reviewers", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when merge request author has only guest access' do
+ it_behaves_like 'rejects user from accessing merge request info' do
+ let(:url) { "/projects/#{project.id}/merge_requests/#{merge_request.iid}/reviewers" }
+ end
+ end
+ end
+
describe 'GET /projects/:id/merge_requests/:merge_request_iid/commits' do
include_context 'with merge requests'
@@ -2482,39 +2567,37 @@ RSpec.describe API::MergeRequests do
let(:pipeline) { create(:ci_pipeline, project: project) }
it "returns merge_request in case of success" do
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
+ expect { put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user) }
+ .to change { merge_request.reload.merged? }
+ .from(false)
+ .to(true)
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when change_response_code_merge_status is enabled' do
- it "returns 422 if branch can't be merged" do
- allow_next_found_instance_of(MergeRequest) do |merge_request|
- allow(merge_request).to receive(:can_be_merged?).and_return(false)
+ context 'when the merge request fails to merge' do
+ it 'returns 422' do
+ expect_next_instance_of(::MergeRequests::MergeService) do |service|
+ expect(service).to receive(:execute)
end
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
+ expect { put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user) }
+ .not_to change { merge_request.reload.merged? }
expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(json_response['message']).to eq('Branch cannot be merged')
+ expect(json_response['message']).to eq("Branch cannot be merged")
end
end
- context 'when change_response_code_merge_status is disabled' do
- before do
- stub_feature_flags(change_response_code_merge_status: false)
+ it "returns 422 if branch can't be merged" do
+ allow_next_found_instance_of(MergeRequest) do |merge_request|
+ allow(merge_request).to receive(:can_be_merged?).and_return(false)
end
- it "returns 406 if branch can't be merged" do
- allow_next_found_instance_of(MergeRequest) do |merge_request|
- allow(merge_request).to receive(:can_be_merged?).and_return(false)
- end
-
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
- expect(response).to have_gitlab_http_status(:not_acceptable)
- expect(json_response['message']).to eq('Branch cannot be merged')
- end
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq('Branch cannot be merged')
end
it "returns 405 if merge_request is not open" do
diff --git a/spec/requests/api/metrics/dashboard/annotations_spec.rb b/spec/requests/api/metrics/dashboard/annotations_spec.rb
index 79a38702354..5e64ac7d481 100644
--- a/spec/requests/api/metrics/dashboard/annotations_spec.rb
+++ b/spec/requests/api/metrics/dashboard/annotations_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe API::Metrics::Dashboard::Annotations do
let(:dashboard) { 'config/prometheus/common_metrics.yml' }
let(:starting_at) { Time.now.iso8601 }
let(:ending_at) { 1.hour.from_now.iso8601 }
- let(:params) { attributes_for(:metrics_dashboard_annotation, environment: environment, starting_at: starting_at, ending_at: ending_at, dashboard_path: dashboard)}
+ let(:params) { attributes_for(:metrics_dashboard_annotation, environment: environment, starting_at: starting_at, ending_at: ending_at, dashboard_path: dashboard) }
shared_examples 'POST /:source_type/:id/metrics_dashboard/annotations' do |source_type|
let(:url) { "/#{source_type.pluralize}/#{source.id}/metrics_dashboard/annotations" }
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index f6a65274ca2..89abb28140a 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -111,7 +111,7 @@ RSpec.describe API::Notes do
system: false
end
- let(:test_url) {"/projects/#{ext_proj.id}/issues/#{ext_issue.iid}/notes"}
+ let(:test_url) { "/projects/#{ext_proj.id}/issues/#{ext_issue.iid}/notes" }
shared_examples 'a notes request' do
it 'is a note array response' do
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 62809b432af..3bcffac2760 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe API::NpmProjectPackages do
end
context 'with access token' do
- let(:headers) { build_token_auth_header(token.token) }
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
it_behaves_like 'successfully downloads the file'
it_behaves_like 'a package tracking event', 'API::NpmPackages', 'pull_package'
@@ -95,7 +95,7 @@ RSpec.describe API::NpmProjectPackages do
it_behaves_like 'a package file that requires auth'
context 'with guest' do
- let(:headers) { build_token_auth_header(token.token) }
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
it 'denies download when not enough permissions' do
project.add_guest(user)
@@ -307,8 +307,8 @@ RSpec.describe API::NpmProjectPackages do
expect { upload_package_with_token }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
- .and change { Packages::Dependency.count}.by(4)
- .and change { Packages::DependencyLink.count}.by(6)
+ .and change { Packages::Dependency.count }.by(4)
+ .and change { Packages::DependencyLink.count }.by(6)
expect(response).to have_gitlab_http_status(:ok)
end
@@ -323,8 +323,8 @@ RSpec.describe API::NpmProjectPackages do
expect { upload_package_with_token }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
- .and not_change { Packages::Dependency.count}
- .and change { Packages::DependencyLink.count}.by(6)
+ .and not_change { Packages::Dependency.count }
+ .and change { Packages::DependencyLink.count }.by(6)
end
end
end
@@ -356,7 +356,7 @@ RSpec.describe API::NpmProjectPackages do
end
def upload_with_token(package_name, params = {})
- upload_package(package_name, params.merge(access_token: token.token))
+ upload_package(package_name, params.merge(access_token: token.plaintext_token))
end
def upload_with_job_token(package_name, params = {})
diff --git a/spec/requests/api/nuget_group_packages_spec.rb b/spec/requests/api/nuget_group_packages_spec.rb
index 1b71f0f9de1..c1375288809 100644
--- a/spec/requests/api/nuget_group_packages_spec.rb
+++ b/spec/requests/api/nuget_group_packages_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe API::NugetGroupPackages do
let(:include_prereleases) { true }
let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases }.compact }
- subject { get api(url), headers: {}}
+ subject { get api(url), headers: {} }
shared_examples 'handling mixed visibilities' do
where(:group_visibility, :subgroup_visibility, :expected_status) do
diff --git a/spec/requests/api/pages/pages_spec.rb b/spec/requests/api/pages/pages_spec.rb
index 0eb2ae64f43..7d44ff533aa 100644
--- a/spec/requests/api/pages/pages_spec.rb
+++ b/spec/requests/api/pages/pages_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe API::Pages do
end
it_behaves_like '404 response' do
- let(:request) { delete api("/projects/#{project.id}/pages", admin)}
+ let(:request) { delete api("/projects/#{project.id}/pages", admin) }
end
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index 75183156c9d..cd4e8b30d8f 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -19,8 +19,8 @@ RSpec.describe API::PagesDomains do
end
let(:pages_domain_secure_params) { build(:pages_domain, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
- let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
- let(:pages_domain_secure_missing_chain_params) {build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
+ let(:pages_domain_secure_key_missmatch_params) { build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
+ let(:pages_domain_secure_missing_chain_params) { build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
let(:route) { "/projects/#{project.id}/pages/domains" }
let(:route_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain.domain}" }
diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb
index 403c646ee32..8d8998cfdd6 100644
--- a/spec/requests/api/personal_access_tokens_spec.rb
+++ b/spec/requests/api/personal_access_tokens_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe API::PersonalAccessTokens do
context 'logged in as a non-Administrator' do
let_it_be(:current_user) { create(:user) }
let_it_be(:user) { create(:user) }
- let_it_be(:token) { create(:personal_access_token, user: current_user)}
+ let_it_be(: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) }
@@ -100,7 +100,7 @@ RSpec.describe API::PersonalAccessTokens do
it 'fails to return PAT because no PAT exists with this id' do
get api(invalid_path, admin_user)
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml
index 8d3622ca17d..670035187cb 100644
--- a/spec/requests/api/project_attributes.yml
+++ b/spec/requests/api/project_attributes.yml
@@ -101,6 +101,7 @@ ci_cd_settings:
job_token_scope_enabled: ci_job_token_scope_enabled
separated_caches: ci_separated_caches
opt_in_jwt: ci_opt_in_jwt
+ allow_fork_pipelines_to_run_in_parent_project: ci_allow_fork_pipelines_to_run_in_parent_project
build_import_state: # import_state
unexposed_attributes:
@@ -157,6 +158,7 @@ project_setting:
- cve_id_request_enabled
- mr_default_target_self
- target_platforms
+ - selective_code_owner_removals
build_service_desk_setting: # service_desk_setting
unexposed_attributes:
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 8655e5b0238..afe5a7d4a21 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures do
it 'executes a limited number of queries' do
control_count = ActiveRecord::QueryRecorder.new { subject }.count
- expect(control_count).to be <= 108
+ expect(control_count).to be <= 109
end
it 'schedules an import using a namespace' do
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index 5f4b8899a33..7a05da8e13f 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -86,6 +86,18 @@ RSpec.describe API::ProjectPackages do
expect(json_response).to include(a_hash_including('_links' => a_hash_including('web_path' => include(nested_project.namespace.full_path))))
end
end
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user) }
+
+ subject { get api(url, job_token: job.token) }
+
+ it_behaves_like 'returns packages', :project, :maintainer
+ it_behaves_like 'returns packages', :project, :developer
+ it_behaves_like 'returns packages', :project, :reporter
+ it_behaves_like 'returns packages', :project, :no_type
+ it_behaves_like 'returns packages', :project, :guest
+ end
end
context 'project is private' do
@@ -116,6 +128,19 @@ RSpec.describe API::ProjectPackages do
end
end
end
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user) }
+
+ subject { get api(url, job_token: job.token) }
+
+ it_behaves_like 'returns packages', :project, :maintainer
+ it_behaves_like 'returns packages', :project, :developer
+ it_behaves_like 'returns packages', :project, :reporter
+ it_behaves_like 'rejects packages access', :project, :no_type, :not_found
+ # TODO uncomment when https://gitlab.com/gitlab-org/gitlab/-/issues/370998 is resolved
+ # it_behaves_like 'rejects packages access', :project, :guest, :not_found
+ end
end
context 'with pagination params' do
@@ -177,6 +202,8 @@ RSpec.describe API::ProjectPackages do
end
describe 'GET /projects/:id/packages/:package_id' do
+ let(:single_package_schema) { 'public_api/v4/packages/package' }
+
subject { get api(package_url, user) }
shared_examples 'no destroy url' do
@@ -217,7 +244,7 @@ RSpec.describe API::ProjectPackages do
subject
expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/packages/package')
+ expect(response).to match_response_schema(single_package_schema)
end
it 'returns 404 when the package does not exist' do
@@ -233,6 +260,18 @@ RSpec.describe API::ProjectPackages do
end
it_behaves_like 'no destroy url'
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user) }
+
+ subject { get api(package_url, job_token: job.token) }
+
+ it_behaves_like 'returns package', :project, :maintainer
+ it_behaves_like 'returns package', :project, :developer
+ it_behaves_like 'returns package', :project, :reporter
+ it_behaves_like 'returns package', :project, :no_type
+ it_behaves_like 'returns package', :project, :guest
+ end
end
context 'project is private' do
@@ -259,7 +298,7 @@ RSpec.describe API::ProjectPackages do
subject
expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('public_api/v4/packages/package')
+ expect(response).to match_response_schema(single_package_schema)
end
it_behaves_like 'no destroy url'
@@ -273,6 +312,19 @@ RSpec.describe API::ProjectPackages do
it_behaves_like 'destroy url'
end
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user) }
+
+ subject { get api(package_url, job_token: job.token) }
+
+ it_behaves_like 'returns package', :project, :maintainer
+ it_behaves_like 'returns package', :project, :developer
+ it_behaves_like 'returns package', :project, :reporter
+ # TODO uncomment when https://gitlab.com/gitlab-org/gitlab/-/issues/370998 is resolved
+ # it_behaves_like 'rejects packages access', :project, :guest, :not_found
+ it_behaves_like 'rejects packages access', :project, :no_type, :not_found
+ end
+
context 'with pipeline' do
let!(:package1) { create(:npm_package, :with_build, project: project) }
@@ -355,6 +407,26 @@ RSpec.describe API::ProjectPackages do
expect(response).to have_gitlab_http_status(:no_content)
end
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user) }
+
+ it 'returns 403 for a user without enough permissions' do
+ project.add_developer(user)
+
+ expect { delete api(package_url, job_token: job.token) }.not_to change { ::Packages::Package.pending_destruction.count }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'returns 204' do
+ project.add_maintainer(user)
+
+ expect { delete api(package_url, job_token: job.token) }.to change { ::Packages::Package.pending_destruction.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
end
context 'with a maven package' do
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index 070fd6db3dc..87d70a87f42 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe API::ProjectTemplates do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/template_list')
- expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
+ expect(json_response.map { |t| t['key'] }).to match_array(%w(bug feature_proposal template_test))
end
it 'returns merge request templates' do
@@ -86,7 +86,7 @@ RSpec.describe API::ProjectTemplates do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/template_list')
- expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
+ expect(json_response.map { |t| t['key'] }).to match_array(%w(bug feature_proposal template_test))
end
it 'returns 400 for an unknown template type' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index ae689d7327b..94688833d88 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1093,7 +1093,7 @@ RSpec.describe API::Projects do
it 'does not create new project and respond with 403' do
allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
expect { post api('/projects', user2), params: { name: 'foo' } }
- .to change {Project.count}.by(0)
+ .to change { Project.count }.by(0)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
@@ -2427,6 +2427,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['ci_default_git_depth']).to eq(project.ci_default_git_depth)
expect(json_response['ci_forward_deployment_enabled']).to eq(project.ci_forward_deployment_enabled)
+ expect(json_response['ci_allow_fork_pipelines_to_run_in_parent_project']).to eq(project.ci_allow_fork_pipelines_to_run_in_parent_project)
expect(json_response['ci_separated_caches']).to eq(project.ci_separated_caches)
expect(json_response['merge_method']).to eq(project.merge_method.to_s)
expect(json_response['squash_option']).to eq(project.squash_option.to_s)
@@ -3692,6 +3693,7 @@ RSpec.describe API::Projects do
merge_method: 'ff',
ci_default_git_depth: 20,
ci_forward_deployment_enabled: false,
+ ci_allow_fork_pipelines_to_run_in_parent_project: false,
ci_separated_caches: false,
description: 'new description' }
diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb
index 8efb822cb83..9f10eb1bb9f 100644
--- a/spec/requests/api/protected_branches_spec.rb
+++ b/spec/requests/api/protected_branches_spec.rb
@@ -3,14 +3,22 @@
require 'spec_helper'
RSpec.describe API::ProtectedBranches do
- let(:user) { create(:user) }
- let!(:project) { create(:project, :repository) }
+ let_it_be_with_reload(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+
let(:protected_name) { 'feature' }
let(:branch_name) { protected_name }
+
let!(:protected_branch) do
create(:protected_branch, project: project, name: protected_name)
end
+ before_all do
+ project.add_maintainer(maintainer)
+ project.add_guest(guest)
+ end
+
describe "GET /projects/:id/protected_branches" do
let(:params) { {} }
let(:route) { "/projects/#{project.id}/protected_branches" }
@@ -29,9 +37,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a maintainer' do
- before do
- project.add_maintainer(user)
- end
+ let(:user) { maintainer }
context 'when search param is not present' do
it_behaves_like 'protected branches' do
@@ -49,9 +55,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a guest' do
- before do
- project.add_guest(user)
- end
+ let(:user) { guest }
it_behaves_like '403 response' do
let(:request) { get api(route, user) }
@@ -84,9 +88,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a maintainer' do
- before do
- project.add_maintainer(user)
- end
+ let(:user) { maintainer }
it_behaves_like 'protected branch'
@@ -104,9 +106,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a guest' do
- before do
- project.add_guest(user)
- end
+ let(:user) { guest }
it_behaves_like '403 response' do
let(:request) { get api(route, user) }
@@ -124,9 +124,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a maintainer' do
- before do
- project.add_maintainer(user)
- end
+ let(:user) { maintainer }
it 'protects a single branch' do
post post_endpoint, params: { name: branch_name }
@@ -226,13 +224,10 @@ RSpec.describe API::ProtectedBranches do
end
end
- context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- expect(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
+ context 'when a policy restricts rule creation' do
+ it "prevents creations of the protected branch rule" do
+ disallow(:create_protected_branch, an_instance_of(ProtectedBranch))
- it "prevents deletion of the protected branch rule" do
post post_endpoint, params: { name: branch_name }
expect(response).to have_gitlab_http_status(:forbidden)
@@ -241,9 +236,7 @@ RSpec.describe API::ProtectedBranches do
end
context 'when authenticated as a guest' do
- before do
- project.add_guest(user)
- end
+ let(:user) { guest }
it "returns a 403 error if guest" do
post post_endpoint, params: { name: branch_name }
@@ -254,12 +247,9 @@ RSpec.describe API::ProtectedBranches do
end
describe "DELETE /projects/:id/protected_branches/unprotect/:branch" do
+ let(:user) { maintainer }
let(:delete_endpoint) { api("/projects/#{project.id}/protected_branches/#{branch_name}", user) }
- before do
- project.add_maintainer(user)
- end
-
it "unprotects a single branch" do
delete delete_endpoint
@@ -277,12 +267,9 @@ RSpec.describe API::ProtectedBranches do
end
context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- expect(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
-
it "prevents deletion of the protected branch rule" do
+ disallow(:destroy_protected_branch, protected_branch)
+
delete delete_endpoint
expect(response).to have_gitlab_http_status(:forbidden)
@@ -299,4 +286,9 @@ RSpec.describe API::ProtectedBranches do
end
end
end
+
+ def disallow(ability, protected_branch)
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, ability, protected_branch).and_return(false)
+ end
end
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index 9e0d3780fd8..6c130bb4963 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package GET requests'
context 'with group path as id' do
- let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple"}
+ let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple" }
it_behaves_like 'deploy token for package GET requests'
end
@@ -102,7 +102,7 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package GET requests'
context 'with group path as id' do
- let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple/#{package_name}"}
+ let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple/#{package_name}" }
it_behaves_like 'deploy token for package GET requests'
end
diff --git a/spec/requests/api/release/links_spec.rb b/spec/requests/api/release/links_spec.rb
index 2345c0063dd..57b2e005929 100644
--- a/spec/requests/api/release/links_spec.rb
+++ b/spec/requests/api/release/links_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe API::Release::Links do
end
context 'when release does not exist' do
- let!(:release) { }
+ let!(:release) {}
it_behaves_like '404 response' do
let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer) }
@@ -98,7 +98,7 @@ RSpec.describe API::Release::Links do
end
context 'when the release does not exists' do
- let!(:release) { }
+ let!(:release) {}
it_behaves_like '403 response' do
let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member) }
@@ -409,7 +409,7 @@ RSpec.describe API::Release::Links do
end
context 'when there are no corresponding release link' do
- let!(:release_link) { }
+ let!(:release_link) {}
it_behaves_like '404 response' do
let(:request) do
@@ -510,7 +510,7 @@ RSpec.describe API::Release::Links do
end
context 'when there are no corresponding release link' do
- let!(:release_link) { }
+ let!(:release_link) {}
it_behaves_like '404 response' do
let(:request) do
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index c050214ff50..1d9e3a6c887 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -962,7 +962,7 @@ RSpec.describe API::Releases do
context 'with milestones' do
let(:subject) { post api("/projects/#{project.id}/releases", maintainer), params: params }
let(:milestone) { create(:milestone, project: project, title: 'v1.0') }
- let(:returned_milestones) { json_response['milestones'].map {|m| m['title']} }
+ let(:returned_milestones) { json_response['milestones'].map { |m| m['title'] } }
before do
params.merge!(milestone_params)
@@ -1120,7 +1120,7 @@ RSpec.describe API::Releases do
end
context 'when there are no corresponding releases' do
- let!(:release) { }
+ let!(:release) {}
it 'forbids the request' do
put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
@@ -1158,7 +1158,7 @@ RSpec.describe API::Releases do
end
context 'with milestones' do
- let(:returned_milestones) { json_response['milestones'].map {|m| m['title']} }
+ let(:returned_milestones) { json_response['milestones'].map { |m| m['title'] } }
subject { put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params }
@@ -1310,7 +1310,7 @@ RSpec.describe API::Releases do
end
context 'when there are no corresponding releases' do
- let!(:release) { }
+ let!(:release) {}
it 'forbids the request' do
delete api("/projects/#{project.id}/releases/v0.1", maintainer)
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index cf0165d123f..3c22f918af5 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -92,6 +92,32 @@ RSpec.describe API::Repositories do
expect(json_response.map { |t| t["id"] }).not_to include(page_token)
end
end
+
+ context 'with pagination=none' do
+ context 'with recursive=1' do
+ it 'returns unpaginated recursive project paths tree' do
+ get api("#{route}?recursive=1&pagination=none", current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(response).not_to include_pagination_headers
+ expect(json_response[4]['name']).to eq('html')
+ expect(json_response[4]['path']).to eq('files/html')
+ expect(json_response[4]['type']).to eq('tree')
+ expect(json_response[4]['mode']).to eq('040000')
+ end
+ end
+
+ context 'with recursive=0' do
+ it 'returns 400' do
+ get api("#{route}?recursive=0&pagination=none", current_user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error'])
+ .to eq('pagination cannot be "none" unless "recursive" is true')
+ end
+ end
+ end
end
context 'when unauthenticated', 'and project is public' do
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 4d2a69cd85b..66b78829e0d 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -350,6 +350,17 @@ RSpec.describe API::Search do
include_examples 'pagination', scope: :snippet_titles
end
end
+
+ it 'sets global search information for logging' do
+ expect(Gitlab::Instrumentation::GlobalSearchApi).to receive(:set_information).with(
+ type: 'basic',
+ level: 'global',
+ scope: 'issues',
+ search_duration_s: a_kind_of(Numeric)
+ )
+
+ get api(endpoint, user), params: { scope: 'issues', search: 'john doe' }
+ end
end
it_behaves_like 'rate limited endpoint', rate_limit_key: :search_rate_limit do
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index d4a8e591622..6f0d5827a80 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['spam_check_api_key']).to be_nil
expect(json_response['wiki_page_max_content_bytes']).to be_a(Integer)
expect(json_response['require_admin_approval_after_user_signup']).to eq(true)
- expect(json_response['personal_access_token_prefix']).to be_nil
+ expect(json_response['personal_access_token_prefix']).to eq('glpat-')
expect(json_response['admin_mode']).to be(false)
expect(json_response['whats_new_variant']).to eq('all_tiers')
expect(json_response['user_deactivation_emails_enabled']).to be(true)
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 0ba1011684a..0dd6e484e8d 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
+ expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
public_snippet.id,
internal_snippet.id,
private_snippet.id)
@@ -75,7 +75,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
it 'returns snippets available for user in given time range' do
get api(path, personal_access_token: user_token)
- expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
+ expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
private_snippet_in_time_range1.id,
private_snippet_in_time_range2.id)
end
@@ -99,10 +99,10 @@ RSpec.describe API::Snippets, factory_default: :keep do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
+ expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
public_snippet.id,
public_snippet_other.id)
- expect(json_response.map { |snippet| snippet['web_url']} ).to contain_exactly(
+ expect(json_response.map { |snippet| snippet['web_url'] } ).to contain_exactly(
"http://localhost/-/snippets/#{public_snippet.id}",
"http://localhost/-/snippets/#{public_snippet_other.id}")
expect(json_response[0]['files'].first).to eq snippet_blob_file(public_snippet_other.blobs.first)
@@ -126,7 +126,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
it 'returns public snippets available to user in given time range' do
get api(path, personal_access_token: user_token)
- expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
+ expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
public_snippet_in_time_range.id)
end
end
diff --git a/spec/requests/api/topics_spec.rb b/spec/requests/api/topics_spec.rb
index e711414a895..72221e3fb6a 100644
--- a/spec/requests/api/topics_spec.rb
+++ b/spec/requests/api/topics_spec.rb
@@ -36,6 +36,22 @@ RSpec.describe API::Topics do
expect(json_response[2]['total_projects_count']).to eq(1)
end
+ context 'with without_projects' do
+ let_it_be(:topic_4) { create(:topic, name: 'unassigned topic', total_projects_count: 0) }
+
+ it 'returns topics without assigned projects' do
+ get api('/topics'), params: { without_projects: true }
+
+ expect(json_response.map { |t| t['id'] }).to contain_exactly(topic_4.id)
+ end
+
+ it 'returns topics without assigned projects' do
+ get api('/topics'), params: { without_projects: false }
+
+ expect(json_response.map { |t| t['id'] }).to contain_exactly(topic_1.id, topic_2.id, topic_3.id, topic_4.id)
+ end
+ end
+
context 'with search' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/requests/api/unleash_spec.rb b/spec/requests/api/unleash_spec.rb
index 7bdb89fb286..3ee895d9421 100644
--- a/spec/requests/api/unleash_spec.rb
+++ b/spec/requests/api/unleash_spec.rb
@@ -8,8 +8,8 @@ RSpec.describe API::Unleash do
let_it_be(:project, refind: true) { create(:project) }
let(:project_id) { project.id }
- let(:params) { }
- let(:headers) { }
+ let(:params) {}
+ let(:headers) {}
shared_examples 'authenticated request' do
context 'when using instance id' do
@@ -57,7 +57,7 @@ RSpec.describe API::Unleash do
context 'when using header' do
let(:client) { create(:operations_feature_flags_client, project: project) }
- let(:headers) { { "UNLEASH-INSTANCEID" => client.token }}
+ let(:headers) { { "UNLEASH-INSTANCEID" => client.token } }
it 'responds with OK' do
subject
diff --git a/spec/requests/api/user_counts_spec.rb b/spec/requests/api/user_counts_spec.rb
index 2d4705920cf..ab2aa87d1b7 100644
--- a/spec/requests/api/user_counts_spec.rb
+++ b/spec/requests/api/user_counts_spec.rb
@@ -43,21 +43,6 @@ RSpec.describe API::UserCounts do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_a Hash
expect(json_response['merge_requests']).to eq(2)
- expect(json_response['attention_requests']).to eq(0)
- end
-
- describe 'mr_attention_requests is disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
- end
-
- it 'does not include attention_requests count' do
- create(:merge_request, source_project: project, author: user, assignees: [user])
-
- get api('/user_counts', user)
-
- expect(json_response.key?('attention_requests')).to be(false)
- end
end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 81ca2548995..26238a87209 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1184,7 +1184,7 @@ RSpec.describe API::Users do
post api('/users', admin),
params: {
email: 'invalid email',
- password: 'password',
+ password: User.random_password,
name: 'test'
}
expect(response).to have_gitlab_http_status(:bad_request)
@@ -1250,7 +1250,7 @@ RSpec.describe API::Users do
post api('/users', admin),
params: {
email: 'test@example.com',
- password: 'password',
+ password: User.random_password,
username: 'test',
name: 'foo'
}
@@ -1262,7 +1262,7 @@ RSpec.describe API::Users do
params: {
name: 'foo',
email: 'test@example.com',
- password: 'password',
+ password: User.random_password,
username: 'foo'
}
end.to change { User.count }.by(0)
@@ -1276,7 +1276,7 @@ RSpec.describe API::Users do
params: {
name: 'foo',
email: 'foo@example.com',
- password: 'password',
+ password: User.random_password,
username: 'test'
}
end.to change { User.count }.by(0)
@@ -1290,7 +1290,7 @@ RSpec.describe API::Users do
params: {
name: 'foo',
email: 'foo@example.com',
- password: 'password',
+ password: User.random_password,
username: 'TEST'
}
end.to change { User.count }.by(0)
@@ -1710,8 +1710,8 @@ RSpec.describe API::Users do
context "with existing user" do
before do
- post api("/users", admin), params: { email: 'test@example.com', password: 'password', username: 'test', name: 'test' }
- post api("/users", admin), params: { email: 'foo@bar.com', password: 'password', username: 'john', name: 'john' }
+ post api("/users", admin), params: { email: 'test@example.com', password: User.random_password, username: 'test', name: 'test' }
+ post api("/users", admin), params: { email: 'foo@bar.com', password: User.random_password, username: 'john', name: 'john' }
@user = User.all.last
end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 05b16119a0e..3ffca7e3c62 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe 'Git HTTP requests' do
end
context 'when namespace exists' do
- let(:path) { "#{user.namespace.path}/new-project.git"}
+ let(:path) { "#{user.namespace.path}/new-project.git" }
context 'when authenticated' do
it 'creates a new project under the existing namespace' do
diff --git a/spec/requests/groups/milestones_controller_spec.rb b/spec/requests/groups/milestones_controller_spec.rb
index 43f0fc714b3..e6418c7694d 100644
--- a/spec/requests/groups/milestones_controller_spec.rb
+++ b/spec/requests/groups/milestones_controller_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Groups::MilestonesController do
milestones = json_response
expect(milestones.count).to eq(3)
- expect(milestones.map {|x| x['title']}).not_to include(private_milestone.title)
+ expect(milestones.map { |x| x['title'] }).not_to include(private_milestone.title)
end
end
diff --git a/spec/requests/jira_connect/subscriptions_controller_spec.rb b/spec/requests/jira_connect/subscriptions_controller_spec.rb
index b10d07b3771..d8f329f13f5 100644
--- a/spec/requests/jira_connect/subscriptions_controller_spec.rb
+++ b/spec/requests/jira_connect/subscriptions_controller_spec.rb
@@ -18,12 +18,12 @@ RSpec.describe JiraConnect::SubscriptionsController do
subject(:content_security_policy) { response.headers['Content-Security-Policy'] }
- it { is_expected.to include('http://self-managed-gitlab.com/-/jira_connect/oauth_application_ids')}
+ it { is_expected.to include('http://self-managed-gitlab.com/-/jira_connect/oauth_application_ids') }
context 'with no self-managed instance configured' do
let_it_be(:installation) { create(:jira_connect_installation, instance_url: '') }
- it { is_expected.not_to include('http://self-managed-gitlab.com')}
+ it { is_expected.not_to include('http://self-managed-gitlab.com') }
end
end
end
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index 70097234762..db3be617a53 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -22,6 +22,17 @@ RSpec.describe JwtController do
end
end
+ shared_examples 'a token that expires today' do
+ let(:pat) { create(:personal_access_token, user: user, scopes: ['api'], expires_at: Date.today ) }
+ let(:headers) { { authorization: credentials('personal_access_token', pat.token) } }
+
+ it 'fails authentication' do
+ get '/jwt/auth', params: parameters, headers: headers
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
context 'authenticating against container registry' do
context 'existing service' do
subject! { get '/jwt/auth', params: parameters }
@@ -104,6 +115,7 @@ RSpec.describe JwtController do
it_behaves_like 'rejecting a blocked user'
it_behaves_like 'user logging'
+ it_behaves_like 'a token that expires today'
end
end
@@ -253,6 +265,7 @@ RSpec.describe JwtController do
let(:credential_password) { personal_access_token.token }
it_behaves_like 'with valid credentials'
+ it_behaves_like 'a token that expires today'
end
context 'with user credentials token' do
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index acf83916f82..3529239a4d9 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -129,13 +129,13 @@ RSpec.describe 'Git LFS API and storage' do
it_behaves_like 'LFS http 200 blob response'
context 'when user password is expired' do
- let_it_be(:user) { create(:user, password_expires_at: 1.minute.ago)}
+ let_it_be(:user) { create(:user, password_expires_at: 1.minute.ago) }
it_behaves_like 'LFS http 401 response'
end
context 'when user is blocked' do
- let_it_be(:user) { create(:user, :blocked)}
+ let_it_be(:user) { create(:user, :blocked) }
it_behaves_like 'LFS http 401 response'
end
@@ -347,17 +347,17 @@ RSpec.describe 'Git LFS API and storage' do
end
context 'when user password is expired' do
- let_it_be(:user) { create(:user, password_expires_at: 1.minute.ago)}
+ let_it_be(:user) { create(:user, password_expires_at: 1.minute.ago) }
- let(:role) { :reporter}
+ let(:role) { :reporter }
it_behaves_like 'LFS http 401 response'
end
context 'when user is blocked' do
- let_it_be(:user) { create(:user, :blocked)}
+ let_it_be(:user) { create(:user, :blocked) }
- let(:role) { :reporter}
+ let(:role) { :reporter }
it_behaves_like 'LFS http 401 response'
end
@@ -1013,7 +1013,7 @@ RSpec.describe 'Git LFS API and storage' do
end
context 'when user is blocked' do
- let_it_be(:user) { create(:user, :blocked)}
+ let_it_be(:user) { create(:user, :blocked) }
it_behaves_like 'LFS http 401 response'
end
diff --git a/spec/requests/oauth/tokens_controller_spec.rb b/spec/requests/oauth/tokens_controller_spec.rb
index 3895304dbde..e4cb28cc42b 100644
--- a/spec/requests/oauth/tokens_controller_spec.rb
+++ b/spec/requests/oauth/tokens_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Oauth::TokensController do
let(:cors_request_headers) { { 'Origin' => 'http://notgitlab.com' } }
let(:other_headers) { {} }
- let(:headers) { cors_request_headers.merge(other_headers)}
+ let(:headers) { cors_request_headers.merge(other_headers) }
let(:allowed_methods) { 'POST, OPTIONS' }
shared_examples 'cross-origin POST request' do
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 89d46b64311..65540f86d34 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -3,13 +3,15 @@
require 'spec_helper'
RSpec.describe 'value stream analytics events' do
+ include CycleAnalyticsHelpers
+
let(:user) { create(:user) }
let(:project) { create(:project, :repository, public_builds: false) }
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
describe 'GET /:namespace/:project/value_stream_analytics/events/issues' do
- let(:first_issue_iid) { project.issues.sort_by_attribute(:created_desc).pluck(:iid).first.to_s }
- let(:first_mr_iid) { project.merge_requests.sort_by_attribute(:created_desc).pluck(:iid).first.to_s }
+ let(:first_issue_iid) { project.issues.sort_by_attribute(:created_desc).pick(:iid).to_s }
+ let(:first_mr_iid) { project.merge_requests.sort_by_attribute(:created_desc).pick(:iid).to_s }
before do
project.add_developer(user)
diff --git a/spec/requests/projects/merge_requests/diffs_spec.rb b/spec/requests/projects/merge_requests/diffs_spec.rb
index e17be1ff984..937b0f1d713 100644
--- a/spec/requests/projects/merge_requests/diffs_spec.rb
+++ b/spec/requests/projects/merge_requests/diffs_spec.rb
@@ -13,8 +13,6 @@ RSpec.describe 'Merge Requests Diffs' do
end
describe 'GET diffs_batch' do
- let(:headers) { {} }
-
shared_examples_for 'serializes diffs with expected arguments' do
it 'serializes paginated merge request diff collection' do
expect_next_instance_of(PaginatedDiffSerializer) do |instance|
@@ -24,6 +22,8 @@ RSpec.describe 'Merge Requests Diffs' do
end
subject
+
+ expect(response).to have_gitlab_http_status(:success)
end
end
@@ -40,7 +40,7 @@ RSpec.describe 'Merge Requests Diffs' do
}
end
- def go(extra_params = {})
+ def go(headers: {}, **extra_params)
params = {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -54,13 +54,15 @@ RSpec.describe 'Merge Requests Diffs' do
end
context 'with caching', :use_clean_rails_memory_store_caching do
- subject { go(page: 0, per_page: 5) }
+ subject { go(headers: headers, page: 0, per_page: 5) }
+
+ let(:headers) { {} }
context 'when the request has not been cached' do
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20) }
- end
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
+
+ it_behaves_like 'serializes diffs with expected arguments'
end
context 'when the request has already been cached' do
@@ -76,21 +78,61 @@ RSpec.describe 'Merge Requests Diffs' do
subject
end
+ context 'when using ETags' do
+ context 'when etag_merge_request_diff_batches is true' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+
+ it 'does not serialize diffs' do
+ expect(PaginatedDiffSerializer).not_to receive(:new)
+
+ go(headers: headers, page: 0, per_page: 5)
+
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+ end
+
+ context 'when etag_merge_request_diff_batches is false' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+
+ before do
+ stub_feature_flags(etag_merge_request_diff_batches: false)
+ end
+
+ it 'does not serialize diffs' do
+ expect_next_instance_of(PaginatedDiffSerializer) do |instance|
+ expect(instance).not_to receive(:represent)
+ end
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
+
context 'with the different user' do
let(:another_user) { create(:user) }
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
before do
project.add_maintainer(another_user)
sign_in(another_user)
end
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20) }
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with a new unfoldable diff position' do
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
+
let(:unfoldable_position) do
create(:diff_position)
end
@@ -103,80 +145,155 @@ RSpec.describe 'Merge Requests Diffs' do
end
end
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20) }
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with disabled display_merge_conflicts_in_diff feature' do
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) }
+
before do
stub_feature_flags(display_merge_conflicts_in_diff: false)
end
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) }
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with diff_head option' do
subject { go(page: 0, per_page: 5, diff_head: true) }
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) }
+
before do
merge_request.create_merge_head_diff!
end
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) }
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with the different pagination option' do
subject { go(page: 5, per_page: 5) }
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20) }
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
+
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with the different diff_view' do
subject { go(page: 0, per_page: 5, view: :parallel) }
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) }
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) }
+
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with the different expanded option' do
subject { go(page: 0, per_page: 5, expanded: true ) }
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
- let(:expected_options) { collection_arguments(total_pages: 20) }
+ let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
+
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
context 'with the different ignore_whitespace_change option' do
subject { go(page: 0, per_page: 5, w: 1) }
- it_behaves_like 'serializes diffs with expected arguments' do
- let(:collection) { Gitlab::Diff::FileCollection::Compare }
- let(:expected_options) { collection_arguments(total_pages: 20) }
+ let(:collection) { Gitlab::Diff::FileCollection::Compare }
+ let(:expected_options) { collection_arguments(total_pages: 20) }
+
+ it_behaves_like 'serializes diffs with expected arguments'
+
+ context 'when using ETag caching' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
+ end
end
end
end
context 'when the paths is given' do
- subject { go(page: 0, per_page: 5, paths: %w[README CHANGELOG]) }
+ subject { go(headers: headers, page: 0, per_page: 5, paths: %w[README CHANGELOG]) }
+
+ before do
+ go(page: 0, per_page: 5, paths: %w[README CHANGELOG])
+ end
- it 'does not use cache' do
- expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original
+ context 'when using ETag caching' do
+ let(:headers) { { 'If-None-Match' => response.etag } }
- subject
+ context 'when etag_merge_request_diff_batches is true' do
+ it 'does not serialize diffs' do
+ expect(PaginatedDiffSerializer).not_to receive(:new)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_modified)
+ end
+ end
+
+ context 'when etag_merge_request_diff_batches is false' do
+ before do
+ stub_feature_flags(etag_merge_request_diff_batches: false)
+ end
+
+ it 'does not use cache' do
+ expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+ end
+ end
+
+ context 'when not using ETag caching' do
+ it 'does not use cache' do
+ expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
end
end
end
diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb
index c761af86c16..9503dafcf2a 100644
--- a/spec/requests/projects/merge_requests_discussions_spec.rb
+++ b/spec/requests/projects/merge_requests_discussions_spec.rb
@@ -16,9 +16,16 @@ RSpec.describe 'merge requests discussions' do
login_as(user)
end
+ # rubocop:disable RSpec/InstanceVariable
def send_request
- get discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid)
+ get(
+ discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid),
+ headers: { 'If-None-Match' => @etag }
+ )
+
+ @etag = response.etag
end
+ # rubocop:enable RSpec/InstanceVariable
it 'returns 200' do
send_request
@@ -63,11 +70,6 @@ RSpec.describe 'merge requests discussions' do
let!(:award_emoji) { create(:award_emoji, awardable: first_note) }
let!(:author_membership) { project.add_maintainer(author) }
- before do
- # Make a request to cache the discussions
- send_request
- end
-
shared_examples 'cache miss' do
it 'does not hit a warm cache' do
expect_next_instance_of(DiscussionSerializer) do |serializer|
@@ -80,176 +82,195 @@ RSpec.describe 'merge requests discussions' do
end
end
- it 'gets cached on subsequent requests' do
- expect_next_instance_of(DiscussionSerializer) do |serializer|
- expect(serializer).not_to receive(:represent)
- end
+ shared_examples 'cache hit' do
+ it 'gets cached on subsequent requests' do
+ expect_next_instance_of(DiscussionSerializer) do |serializer|
+ expect(serializer).not_to receive(:represent)
+ end
- send_request
+ send_request
+ end
end
- context 'when a note in a discussion got updated' do
+ context 'when mr_discussions_http_cache and disabled_mr_discussions_redis_cache are enabled' do
before do
- first_note.update!(updated_at: 1.minute.from_now)
+ send_request
end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
- end
- end
+ it_behaves_like 'cache hit'
- context 'when a note in a discussion got its reference state updated' do
- before do
- reference.close!
- end
+ context 'when a note in a discussion got updated' do
+ before do
+ first_note.update!(updated_at: 1.minute.from_now)
+ end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when a note in a discussion got resolved' do
- before do
- travel_to(1.minute.from_now) do
- first_note.resolve!(user)
+ context 'when a note in a discussion got its reference state updated' do
+ before do
+ reference.close!
end
- end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when a note is added to a discussion' do
- let!(:third_note) { create(:diff_note_on_merge_request, in_reply_to: first_note, noteable: merge_request, project: project) }
+ context 'when a note in a discussion got resolved' do
+ before do
+ travel_to(1.minute.from_now) do
+ first_note.resolve!(user)
+ end
+ end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note, third_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when a note is removed from a discussion' do
- before do
- second_note.destroy!
- end
+ context 'when a note is added to a discussion' do
+ let!(:third_note) { create(:diff_note_on_merge_request, in_reply_to: first_note, noteable: merge_request, project: project) }
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note, third_note] }
+ end
end
- end
- context 'when an emoji is awarded to a note in discussion' do
- before do
- travel_to(1.minute.from_now) do
- create(:award_emoji, awardable: first_note)
+ context 'when a note is removed from a discussion' do
+ before do
+ second_note.destroy!
end
- end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note] }
+ end
end
- end
- context 'when an award emoji is removed from a note in discussion' do
- before do
- travel_to(1.minute.from_now) do
- award_emoji.destroy!
+ context 'when an emoji is awarded to a note in discussion' do
+ before do
+ travel_to(1.minute.from_now) do
+ create(:award_emoji, awardable: first_note)
+ end
end
- end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when the diff note position changes' do
- before do
- # This replicates a position change wherein timestamps aren't updated
- # which is why `Gitlab::Timeless.timeless` is utilized. This is the
- # same approach being used in Discussions::UpdateDiffPositionService
- # which is responsible for updating the positions of diff discussions
- # when MR updates.
- first_note.position = Gitlab::Diff::Position.new(
- old_path: first_note.position.old_path,
- new_path: first_note.position.new_path,
- old_line: first_note.position.old_line,
- new_line: first_note.position.new_line + 1,
- diff_refs: first_note.position.diff_refs
- )
-
- Gitlab::Timeless.timeless(first_note, &:save)
- end
+ context 'when an award emoji is removed from a note in discussion' do
+ before do
+ travel_to(1.minute.from_now) do
+ award_emoji.destroy!
+ end
+ end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when the HEAD diff note position changes' do
- before do
- # This replicates a DiffNotePosition change. This is the same approach
- # being used in Discussions::CaptureDiffNotePositionService which is
- # responsible for updating/creating DiffNotePosition of a diff discussions
- # in relation to HEAD diff.
- new_position = Gitlab::Diff::Position.new(
- old_path: first_note.position.old_path,
- new_path: first_note.position.new_path,
- old_line: first_note.position.old_line,
- new_line: first_note.position.new_line + 1,
- diff_refs: first_note.position.diff_refs
- )
-
- DiffNotePosition.create_or_update_for(
- first_note,
- diff_type: :head,
- position: new_position,
- line_code: 'bd4b7bfff3a247ccf6e3371c41ec018a55230bcc_534_521'
- )
- end
+ context 'when the diff note position changes' do
+ before do
+ # This replicates a position change wherein timestamps aren't updated
+ # which is why `Gitlab::Timeless.timeless` is utilized. This is the
+ # same approach being used in Discussions::UpdateDiffPositionService
+ # which is responsible for updating the positions of diff discussions
+ # when MR updates.
+ first_note.position = Gitlab::Diff::Position.new(
+ old_path: first_note.position.old_path,
+ new_path: first_note.position.new_path,
+ old_line: first_note.position.old_line,
+ new_line: first_note.position.new_line + 1,
+ diff_refs: first_note.position.diff_refs
+ )
+
+ Gitlab::Timeless.timeless(first_note, &:save)
+ end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when author detail changes' do
- before do
- author.update!(name: "#{author.name} (Updated)")
- end
+ context 'when the HEAD diff note position changes' do
+ before do
+ # This replicates a DiffNotePosition change. This is the same approach
+ # being used in Discussions::CaptureDiffNotePositionService which is
+ # responsible for updating/creating DiffNotePosition of a diff discussions
+ # in relation to HEAD diff.
+ new_position = Gitlab::Diff::Position.new(
+ old_path: first_note.position.old_path,
+ new_path: first_note.position.new_path,
+ old_line: first_note.position.old_line,
+ new_line: first_note.position.new_line + 1,
+ diff_refs: first_note.position.diff_refs
+ )
+
+ DiffNotePosition.create_or_update_for(
+ first_note,
+ diff_type: :head,
+ position: new_position,
+ line_code: 'bd4b7bfff3a247ccf6e3371c41ec018a55230bcc_534_521'
+ )
+ end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when author status changes' do
- before do
- Users::SetStatusService.new(author, message: "updated status").execute
+ context 'when author detail changes' do
+ before do
+ author.update!(name: "#{author.name} (Updated)")
+ end
+
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ context 'when author status changes' do
+ before do
+ Users::SetStatusService.new(author, message: "updated status").execute
+ end
+
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- end
- context 'when author role changes' do
- before do
- Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(author_membership)
+ context 'when author role changes' do
+ before do
+ Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(author_membership)
+ end
+
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
+ context 'when current_user role changes' do
+ before do
+ Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(project.member(user))
+ end
+
+ it_behaves_like 'cache miss' do
+ let(:changed_notes) { [first_note, second_note] }
+ end
end
end
- context 'when current_user role changes' do
+ context 'when disabled_mr_discussions_redis_cache is disabled' do
before do
- Members::UpdateService.new(owner, access_level: Gitlab::Access::GUEST).execute(project.member(user))
+ stub_feature_flags(disabled_mr_discussions_redis_cache: false)
+ send_request
end
- it_behaves_like 'cache miss' do
- let(:changed_notes) { [first_note, second_note] }
- end
+ it_behaves_like 'cache hit'
end
end
end
diff --git a/spec/requests/projects/settings/packages_and_registries_controller_spec.rb b/spec/requests/projects/settings/packages_and_registries_controller_spec.rb
new file mode 100644
index 00000000000..6d8a152c769
--- /dev/null
+++ b/spec/requests/projects/settings/packages_and_registries_controller_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Settings::PackagesAndRegistriesController do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, namespace: user.namespace) }
+
+ let(:container_registry_enabled) { true }
+ let(:container_registry_enabled_on_project) { ProjectFeature::ENABLED }
+
+ before do
+ project.project_feature.update!(container_registry_access_level: container_registry_enabled_on_project)
+ project.container_expiration_policy.update!(enabled: true)
+
+ stub_container_registry_config(enabled: container_registry_enabled)
+ end
+
+ describe 'GET #cleanup_tags' do
+ subject { get cleanup_image_tags_namespace_project_settings_packages_and_registries_path(user.namespace, project) }
+
+ context 'when user is unauthorized' do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ project.add_reporter(user)
+ sign_in(user)
+ subject
+ end
+
+ it 'shows 404' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is authorized' do
+ let(:user) { project.creator }
+
+ before do
+ sign_in(user)
+ subject
+ end
+
+ it 'renders content' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:cleanup_tags)
+ end
+
+ context 'when registry is disabled' do
+ let(:container_registry_enabled) { false }
+
+ it 'shows 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when container registry is disabled on project' do
+ let(:container_registry_enabled_on_project) { ProjectFeature::DISABLED }
+
+ it 'shows 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index 115f78a5600..f6b9bc527ac 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -104,8 +104,8 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
end
context 'with the token in the OAuth headers' do
- let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
- let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(other_user_token)) }
it_behaves_like 'rate-limited user based token-authenticated requests'
end
@@ -131,8 +131,8 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
end
context 'with the token in the OAuth headers' do
- let(:request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(token)) }
- let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, oauth_token_headers(other_user_token)) }
+ let(:request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(token)) }
+ let(:other_user_request_args) { api_get_args_with_token_headers(api_partial_url, bearer_headers(other_user_token)) }
it_behaves_like 'rate-limited user based token-authenticated requests'
end
@@ -1189,7 +1189,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
it 'request is authenticated by token in the OAuth headers' do
expect_authenticated_request
- get url, headers: oauth_token_headers(personal_access_token)
+ get url, headers: bearer_headers(personal_access_token)
end
it 'request is authenticated by token in basic auth' do
@@ -1206,7 +1206,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
it 'request is authenticated by token in query string' do
expect_authenticated_request
- get url, params: { access_token: oauth_token.token }
+ get url, params: { access_token: oauth_token.plaintext_token }
end
it 'request is authenticated by token in the headers' do
diff --git a/spec/requests/users/namespace_callouts_spec.rb b/spec/requests/users/namespace_callouts_spec.rb
new file mode 100644
index 00000000000..5a4e269eefb
--- /dev/null
+++ b/spec/requests/users/namespace_callouts_spec.rb
@@ -0,0 +1,57 @@
+# 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/project_callouts_spec.rb b/spec/requests/users/project_callouts_spec.rb
new file mode 100644
index 00000000000..98c00fef052
--- /dev/null
+++ b/spec/requests/users/project_callouts_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Project callouts' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'POST /-/users/project_callouts' do
+ let(:params) { { feature_name: feature_name, project_id: project.id } }
+
+ subject { post project_callouts_path, params: params, headers: { 'ACCEPT' => 'application/json' } }
+
+ context 'with valid feature name and project' do
+ let(:feature_name) { Users::ProjectCallout.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::ProjectCallout.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(:project_callout,
+ feature_name: Users::ProjectCallout.feature_names.each_key.first,
+ user: user,
+ project: project)
+ end
+
+ it 'returns success', :aggregate_failures do
+ expect { subject }.not_to change { Users::ProjectCallout.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/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 1d58a31bd6e..f701dd9c488 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -772,6 +772,16 @@ RSpec.describe 'project routing' do
end
end
+ describe Projects::Settings::PackagesAndRegistriesController, 'routing' do
+ it 'to #show' do
+ expect(get('/gitlab/gitlabhq/-/settings/packages_and_registries')).to route_to('projects/settings/packages_and_registries#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+
+ it 'to #cleanup_tags' do
+ expect(get('gitlab/gitlabhq/-/settings/packages_and_registries/cleanup_image_tags')).to route_to('projects/settings/packages_and_registries#cleanup_tags', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ end
+ end
+
describe Projects::Settings::IntegrationsController, 'routing' do
it 'to #index' do
expect(get('/gitlab/gitlabhq/-/settings/integrations')).to route_to('projects/settings/integrations#index', namespace_id: 'gitlab', project_id: 'gitlabhq')
@@ -953,12 +963,6 @@ RSpec.describe 'project routing' do
end
end
- describe Projects::Ci::SecureFilesController, 'routing' do
- it 'to #show' do
- expect(get('/gitlab/gitlabhq/-/ci/secure_files')).to route_to('projects/ci/secure_files#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
- end
- end
-
context 'with a non-existent project' do
it 'routes to 404 with get request' do
expect(get: "/gitlab/not_exist").to route_to(
diff --git a/spec/rubocop/code_reuse_helpers_spec.rb b/spec/rubocop/code_reuse_helpers_spec.rb
index d437ada85ee..0d06d37d67a 100644
--- a/spec/rubocop/code_reuse_helpers_spec.rb
+++ b/spec/rubocop/code_reuse_helpers_spec.rb
@@ -152,6 +152,26 @@ RSpec.describe RuboCop::CodeReuseHelpers do
end
end
+ describe '#in_graphql?' do
+ it 'returns true for a node in the FOSS GraphQL directory' do
+ node = build_and_parse_source('10', rails_root_join('app', 'graphql', 'foo.rb'))
+
+ expect(cop.in_graphql?(node)).to eq(true)
+ end
+
+ it 'returns true for a node in the EE GraphQL directory' do
+ node = build_and_parse_source('10', rails_root_join('ee', 'app', 'graphql', 'foo.rb'))
+
+ expect(cop.in_graphql?(node)).to eq(true)
+ end
+
+ it 'returns false for a node outside the GraphQL directory' do
+ node = build_and_parse_source('10', rails_root_join('app', 'foo', 'foo.rb'))
+
+ expect(cop.in_graphql?(node)).to eq(false)
+ end
+ end
+
describe '#in_graphql_types?' do
%w[
app/graphql/types
@@ -169,7 +189,7 @@ RSpec.describe RuboCop::CodeReuseHelpers do
app/graphql/resolvers
app/foo
].each do |path|
- it "returns true for a node in #{path}" do
+ it "returns false for a node in #{path}" do
node = build_and_parse_source('10', rails_root_join(path, 'foo.rb'))
expect(cop.in_graphql_types?(node)).to eq(false)
@@ -255,6 +275,44 @@ RSpec.describe RuboCop::CodeReuseHelpers do
end
end
+ describe '#in_graphql_directory?' do
+ it 'returns true for a directory in the FOSS app/graphql directory' do
+ node = build_and_parse_source('10', rails_root_join('app', 'graphql', 'subdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(true)
+ end
+
+ it 'returns true for a directory in the EE app/graphql directory' do
+ node = build_and_parse_source('10', rails_root_join('ee', 'app', 'graphql', 'subdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(true)
+ end
+
+ it 'returns true for a directory in the EE app/graphql/ee directory' do
+ node = build_and_parse_source('10', rails_root_join('ee', 'app', 'graphql', 'ee', 'subdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(true)
+ end
+
+ it 'returns false for a directory in the FOSS app/graphql directory' do
+ node = build_and_parse_source('10', rails_root_join('app', 'graphql', 'anotherdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(false)
+ end
+
+ it 'returns false for a directory in the EE app/graphql directory' do
+ node = build_and_parse_source('10', rails_root_join('ee', 'app', 'graphql', 'anotherdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(false)
+ end
+
+ it 'returns false for a directory in the EE app/graphql/ee directory' do
+ node = build_and_parse_source('10', rails_root_join('ee', 'app', 'graphql', 'ee', 'anotherdir', 'foo.rb'))
+
+ expect(cop.in_graphql_directory?(node, 'subdir')).to eq(false)
+ end
+ end
+
describe '#name_of_receiver' do
it 'returns the name of a send receiver' do
node = build_and_parse_source('Foo.bar')
diff --git a/spec/rubocop/cop/code_reuse/worker_spec.rb b/spec/rubocop/cop/code_reuse/worker_spec.rb
index 8155791a3e3..a548e90d8e1 100644
--- a/spec/rubocop/cop/code_reuse/worker_spec.rb
+++ b/spec/rubocop/cop/code_reuse/worker_spec.rb
@@ -31,7 +31,24 @@ RSpec.describe RuboCop::Cop::CodeReuse::Worker do
resource :projects do
get '/' do
FooWorker.perform_async
- ^^^^^^^^^^^^^^^^^^^^^^^ Workers can not be used in a Grape API.
+ ^^^^^^^^^^^^^^^^^^^^^^^ Workers can not be used in an API endpoint.
+ end
+ end
+ end
+ SOURCE
+ end
+
+ it 'flags the use of a worker in GraphQL' do
+ allow(cop)
+ .to receive(:in_graphql?)
+ .and_return(true)
+
+ expect_offense(<<~SOURCE)
+ module Mutations
+ class Foo < BaseMutation
+ def resolve
+ FooWorker.perform_async
+ ^^^^^^^^^^^^^^^^^^^^^^^ Workers can not be used in an API endpoint.
end
end
end
diff --git a/spec/rubocop/cop/gemspec/avoid_executing_git_spec.rb b/spec/rubocop/cop/gemspec/avoid_executing_git_spec.rb
new file mode 100644
index 00000000000..f94a990a2f7
--- /dev/null
+++ b/spec/rubocop/cop/gemspec/avoid_executing_git_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../../rubocop/cop/gemspec/avoid_executing_git'
+
+RSpec.describe RuboCop::Cop::Gemspec::AvoidExecutingGit do
+ subject(:cop) { described_class.new }
+
+ it 'flags violation for executing git' do
+ expect_offense(<<~RUBY)
+ Gem::Specification.new do |gem|
+ gem.executable = `git ls-files -- bin/*`.split("\\n").map{ |f| File.basename(f) }
+ ^^^^^^^^^^^^^^^^^^^^^^^ Do not execute `git` in gemspec.
+ gem.files = `git ls-files`.split("\\n")
+ ^^^^^^^^^^^^^^ Do not execute `git` in gemspec.
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\\n")
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not execute `git` in gemspec.
+ end
+ RUBY
+ end
+
+ it 'does not flag violation for using a glob' do
+ expect_no_offenses(<<~RUBY)
+ Gem::Specification.new do |gem|
+ gem.files = Dir.glob("lib/**/*.*")
+ gem.test_files = Dir.glob("spec/**/**/*.*")
+ end
+ RUBY
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/deprecate_track_redis_hll_event_spec.rb b/spec/rubocop/cop/gitlab/deprecate_track_redis_hll_event_spec.rb
new file mode 100644
index 00000000000..453f0c36c14
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/deprecate_track_redis_hll_event_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../../rubocop/cop/gitlab/deprecate_track_redis_hll_event'
+
+RSpec.describe RuboCop::Cop::Gitlab::DeprecateTrackRedisHLLEvent do
+ subject(:cop) { described_class.new }
+
+ it 'does not flag the use of track_event' do
+ expect_no_offenses('track_event :show, name: "p_analytics_insights"')
+ end
+
+ it 'flags the use of track_redis_hll_event' do
+ expect_offense(<<~SOURCE)
+ track_redis_hll_event :show, name: 'p_analytics_valuestream'
+ ^^^^^^^^^^^^^^^^^^^^^ `track_redis_hll_event` is deprecated[...]
+ SOURCE
+ end
+end
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 2ec3ae7aada..9ab5cdc24a4 100644
--- a/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb
+++ b/spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb
@@ -217,8 +217,8 @@ RSpec.describe RuboCop::Cop::Gitlab::MarkUsedFeatureFlags do
allow(cop).to receive(:in_graphql_types?).and_return(true)
end
- include_examples 'sets flag as used', 'field :runners, Types::Ci::RunnerType.connection_type, null: true, feature_flag: :foo', 'foo'
- include_examples 'sets flag as used', 'field :runners, null: true, feature_flag: :foo', 'foo'
+ include_examples 'sets flag as used', 'field :runners, Types::Ci::RunnerType.connection_type, null: true, _deprecated_feature_flag: :foo', 'foo'
+ include_examples 'sets flag as used', 'field :runners, null: true, _deprecated_feature_flag: :foo', 'foo'
include_examples 'does not set any flags as used', 'field :solution'
include_examples 'does not set any flags as used', 'field :runners, Types::Ci::RunnerType.connection_type'
include_examples 'does not set any flags as used', 'field :runners, Types::Ci::RunnerType.connection_type, null: true, description: "hello world"'
diff --git a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
index 962efc23453..3596badc599 100644
--- a/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
+++ b/spec/rubocop/cop/inject_enterprise_edition_module_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe RuboCop::Cop::InjectEnterpriseEditionModule do
end
SOURCE
end
+
it 'flags the use of `extend_mod_with` in the middle of a file' do
expect_offense(<<~SOURCE)
class Foo
diff --git a/spec/rubocop/cop_todo_spec.rb b/spec/rubocop/cop_todo_spec.rb
new file mode 100644
index 00000000000..978df2c01ee
--- /dev/null
+++ b/spec/rubocop/cop_todo_spec.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../rubocop/cop_todo'
+
+RSpec.describe RuboCop::CopTodo do
+ let(:cop_name) { 'Cop/Rule' }
+
+ subject(:cop_todo) { described_class.new(cop_name) }
+
+ describe '#initialize' do
+ it 'initializes a cop todo' do
+ expect(cop_todo).to have_attributes(
+ cop_name: cop_name,
+ files: be_empty,
+ offense_count: 0,
+ previously_disabled: false
+ )
+ end
+ end
+
+ describe '#record' do
+ it 'records offenses' do
+ cop_todo.record('a.rb', 1)
+ cop_todo.record('b.rb', 2)
+
+ expect(cop_todo).to have_attributes(
+ files: contain_exactly('a.rb', 'b.rb'),
+ offense_count: 3
+ )
+ end
+ end
+
+ describe '#autocorrectable?' do
+ subject { cop_todo.autocorrectable? }
+
+ context 'when found in rubocop registry' do
+ before do
+ fake_cop = double(:cop, support_autocorrect?: autocorrectable) # rubocop:disable RSpec/VerifiedDoubles
+
+ allow(described_class).to receive(:find_cop_by_name)
+ .with(cop_name).and_return(fake_cop)
+ end
+
+ context 'when autocorrectable' do
+ let(:autocorrectable) { true }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when not autocorrectable' do
+ let(:autocorrectable) { false }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'when not found in rubocop registry' do
+ before do
+ allow(described_class).to receive(:find_cop_by_name)
+ .with(cop_name).and_return(nil).and_call_original
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#to_yaml' do
+ subject(:yaml) { cop_todo.to_yaml }
+
+ context 'when autocorrectable' do
+ before do
+ allow(cop_todo).to receive(:autocorrectable?).and_return(true)
+ end
+
+ specify do
+ expect(yaml).to eq(<<~YAML)
+ ---
+ # Cop supports --auto-correct.
+ #{cop_name}:
+ Exclude:
+ YAML
+ end
+ end
+
+ context 'when previously disabled' do
+ specify do
+ cop_todo.record('a.rb', 1)
+ cop_todo.record('b.rb', 2)
+ cop_todo.previously_disabled = true
+
+ expect(yaml).to eq(<<~YAML)
+ ---
+ #{cop_name}:
+ # Offense count: 3
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'a.rb'
+ - 'b.rb'
+ YAML
+ end
+ end
+
+ context 'with multiple files' do
+ before do
+ cop_todo.record('a.rb', 0)
+ cop_todo.record('c.rb', 0)
+ cop_todo.record('b.rb', 0)
+ end
+
+ it 'sorts excludes alphabetically' do
+ expect(yaml).to eq(<<~YAML)
+ ---
+ #{cop_name}:
+ Exclude:
+ - 'a.rb'
+ - 'b.rb'
+ - 'c.rb'
+ YAML
+ end
+ end
+ end
+end
diff --git a/spec/rubocop/formatter/todo_formatter_spec.rb b/spec/rubocop/formatter/todo_formatter_spec.rb
index fcff028f07d..df56ee45931 100644
--- a/spec/rubocop/formatter/todo_formatter_spec.rb
+++ b/spec/rubocop/formatter/todo_formatter_spec.rb
@@ -261,16 +261,12 @@ RSpec.describe RuboCop::Formatter::TodoFormatter do
double(:offense, cop_name: cop_name)
end
- def stub_rubocop_registry(**cops)
- rubocop_registry = double(:rubocop_registry)
-
- allow(RuboCop::Cop::Registry).to receive(:global).and_return(rubocop_registry)
-
- allow(rubocop_registry).to receive(:find_by_cop_name)
- .with(String).and_return(nil)
+ def stub_rubocop_registry(cops)
+ allow(RuboCop::CopTodo).to receive(:find_cop_by_name)
+ .with(String).and_return(nil).and_call_original
cops.each do |cop_name, attributes|
- allow(rubocop_registry).to receive(:find_by_cop_name)
+ allow(RuboCop::CopTodo).to receive(:find_cop_by_name)
.with(cop_name).and_return(fake_cop(**attributes))
end
end
diff --git a/spec/scripts/changed-feature-flags_spec.rb b/spec/scripts/changed-feature-flags_spec.rb
index bbae49a90e4..f4058614d85 100644
--- a/spec/scripts/changed-feature-flags_spec.rb
+++ b/spec/scripts/changed-feature-flags_spec.rb
@@ -81,8 +81,8 @@ RSpec.describe 'scripts/changed-feature-flags' do
end
describe '.extracted_flags' do
- let(:file_name1) { "foo_ff_#{SecureRandom.hex(8)}"}
- let(:file_name2) { "bar_ff_#{SecureRandom.hex(8)}"}
+ let(:file_name1) { "foo_ff_#{SecureRandom.hex(8)}" }
+ let(:file_name2) { "bar_ff_#{SecureRandom.hex(8)}" }
let(:ff_dir) { FileUtils.mkdir_p(File.join(Dir.tmpdir, ff_sub_dir)) }
let(:diffs_dir) { FileUtils.mkdir_p(File.join(Dir.tmpdir, 'diffs')).first }
diff --git a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
index 149a384d31e..fe815aa6f1e 100644
--- a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
+++ b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
@@ -65,13 +65,19 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
## Strong
+ This example doesn't have an extension after the `example` keyword, so its
+ `source_specification` will be `commonmark`.
+
```````````````````````````````` example
__bold__
.
<p><strong>bold</strong></p>
````````````````````````````````
- ```````````````````````````````` example strong
+ This example has an extension after the `example` keyword, so its
+ `source_specification` will be `github`.
+
+ ```````````````````````````````` example some_extension_name
__bold with more text__
.
<p><strong>bold with more text</strong></p>
@@ -132,6 +138,10 @@ RSpec.describe Glfm::UpdateExampleSnapshots, '#process' do
## Strong but with HTML
+ This example has the `gitlab` keyword after the `example` keyword, so its
+ `source_specification` will be `gitlab`.
+
+
```````````````````````````````` example gitlab strong
<strong>
bold
diff --git a/spec/scripts/trigger-build_spec.rb b/spec/scripts/trigger-build_spec.rb
index 76a3cdbeaa2..d0f1d3dc41b 100644
--- a/spec/scripts/trigger-build_spec.rb
+++ b/spec/scripts/trigger-build_spec.rb
@@ -882,7 +882,6 @@ RSpec.describe Trigger do
let(:ops_gitlab_client) { double('ops_gitlab_client') }
let(:downstream_gitlab_client_endpoint) { ops_api_endpoint }
- let(:downstream_gitlab_client_token) { ops_api_token }
let(:downstream_gitlab_client) { ops_gitlab_client }
let(:ref) { 'master' }
@@ -890,7 +889,6 @@ RSpec.describe Trigger do
let(:env) do
super().merge(
- 'GITLABCOM_DATABASE_TESTING_ACCESS_TOKEN' => ops_api_token,
'GITLABCOM_DATABASE_TESTING_TRIGGER_TOKEN' => trigger_token
)
end
@@ -902,6 +900,13 @@ RSpec.describe Trigger do
private_token: com_api_token
)
.and_return(com_gitlab_client)
+
+ allow(Gitlab).to receive(:client)
+ .with(
+ endpoint: downstream_gitlab_client_endpoint
+ )
+ .and_return(downstream_gitlab_client)
+
allow(com_gitlab_client).to receive(:merge_request_notes)
.with(
env['CI_PROJECT_PATH'],
diff --git a/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb b/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb
index c39eb14e339..7ea72351594 100644
--- a/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb
+++ b/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe DeployKeys::BasicDeployKeyEntity do
include RequestAwareEntity
let(:user) { create(:user) }
- let(:project) { create(:project, :internal)}
- let(:project_private) { create(:project, :private)}
+ let(:project) { create(:project, :internal) }
+ let(:project_private) { create(:project, :private) }
let(:deploy_key) { create(:deploy_key) }
let(:options) { { user: user } }
diff --git a/spec/serializers/deploy_keys/deploy_key_entity_spec.rb b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb
index e989aa8656c..7719cafae11 100644
--- a/spec/serializers/deploy_keys/deploy_key_entity_spec.rb
+++ b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe DeployKeys::DeployKeyEntity do
include RequestAwareEntity
let(:user) { create(:user) }
- let(:project) { create(:project, :internal)}
- let(:project_private) { create(:project, :private)}
+ let(:project) { create(:project, :internal) }
+ let(:project_private) { create(:project, :private) }
let(:deploy_key) { create(:deploy_key) }
let(:options) { { user: user } }
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
index 05644dad151..01d1e47b5bb 100644
--- a/spec/serializers/environment_serializer_spec.rb
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -101,6 +101,37 @@ RSpec.describe EnvironmentSerializer do
expect(subject.third[:latest][:environment_type]).to be_nil
end
end
+
+ context 'when folders and standalone environments share the same name' do
+ before do
+ create(:environment, project: project, name: 'staging/my-review-1')
+ create(:environment, project: project, name: 'staging/my-review-2')
+ create(:environment, project: project, name: 'production/my-review-3')
+ create(:environment, project: project, name: 'staging')
+ create(:environment, project: project, name: 'testing')
+ end
+
+ it 'does not group standalone environments with folders that have the same name' do
+ expect(subject.count).to eq 4
+
+ expect(subject.first[:name]).to eq 'production'
+ expect(subject.first[:size]).to eq 1
+ expect(subject.first[:latest][:name]).to eq 'production/my-review-3'
+ expect(subject.first[:latest][:environment_type]).to eq 'production'
+ expect(subject.second[:name]).to eq 'staging'
+ expect(subject.second[:size]).to eq 1
+ expect(subject.second[:latest][:name]).to eq 'staging'
+ expect(subject.second[:latest][:environment_type]).to be_nil
+ expect(subject.third[:name]).to eq 'staging'
+ expect(subject.third[:size]).to eq 2
+ expect(subject.third[:latest][:name]).to eq 'staging/my-review-2'
+ expect(subject.third[:latest][:environment_type]).to eq 'staging'
+ expect(subject.fourth[:name]).to eq 'testing'
+ expect(subject.fourth[:size]).to eq 1
+ expect(subject.fourth[:latest][:name]).to eq 'testing'
+ expect(subject.fourth[:latest][:environment_type]).to be_nil
+ end
+ end
end
context 'when used with pagination' do
diff --git a/spec/serializers/group_access_token_entity_spec.rb b/spec/serializers/group_access_token_entity_spec.rb
new file mode 100644
index 00000000000..39b587c7df7
--- /dev/null
+++ b/spec/serializers/group_access_token_entity_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupAccessTokenEntity do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bot) { create(:user, :project_bot) }
+ let_it_be(:token) { create(:personal_access_token, user: bot) }
+
+ subject(:json) { described_class.new(token, group: group).as_json }
+
+ context 'when bot is a member of the group' do
+ before do
+ group.add_developer(bot)
+ end
+
+ it 'has the correct attributes' do
+ expected_revoke_path = Gitlab::Routing.url_helpers
+ .revoke_group_settings_access_token_path(
+ { id: token,
+ group_id: group.path })
+
+ expect(json).to(
+ include(
+ id: token.id,
+ name: token.name,
+ scopes: token.scopes,
+ user_id: token.user_id,
+ revoke_path: expected_revoke_path,
+ access_level: ::Gitlab::Access::DEVELOPER
+ ))
+
+ expect(json).not_to include(:token)
+ end
+ end
+
+ context 'when bot is unrelated to the group' do
+ it 'has the correct attributes' do
+ expected_revoke_path = Gitlab::Routing.url_helpers
+ .revoke_group_settings_access_token_path(
+ { id: token,
+ group_id: group.path })
+
+ expect(json).to(
+ include(
+ id: token.id,
+ name: token.name,
+ scopes: token.scopes,
+ user_id: token.user_id,
+ revoke_path: expected_revoke_path,
+ access_level: nil
+ ))
+
+ expect(json).not_to include(:token)
+ end
+ end
+end
diff --git a/spec/serializers/group_access_token_serializer_spec.rb b/spec/serializers/group_access_token_serializer_spec.rb
new file mode 100644
index 00000000000..3b12c3115c9
--- /dev/null
+++ b/spec/serializers/group_access_token_serializer_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupAccessTokenSerializer do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:bot) { create(:user, :project_bot) }
+
+ subject(:serializer) { described_class.new }
+
+ before do
+ group.add_developer(bot)
+ end
+
+ describe '#represent' do
+ it 'can render a single token' do
+ token = create(:personal_access_token, user: bot)
+
+ expect(serializer.represent(token, group: group)).to be_kind_of(Hash)
+ end
+
+ it 'can render a collection of tokens' do
+ tokens = create_list(:personal_access_token, 2, user: bot)
+
+ expect(serializer.represent(tokens, group: group)).to be_kind_of(Array)
+ end
+ end
+end
diff --git a/spec/serializers/integrations/project_entity_spec.rb b/spec/serializers/integrations/project_entity_spec.rb
index 1564f7fad63..ac633d1d5c6 100644
--- a/spec/serializers/integrations/project_entity_spec.rb
+++ b/spec/serializers/integrations/project_entity_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Integrations::ProjectEntity do
it 'contains needed attributes' do
expect(subject).to include(
+ id: project.id,
avatar_url: include('uploads'),
name: project.name,
full_path: project_path(project),
diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb
index 6b9c703c627..9335ca61b7d 100644
--- a/spec/serializers/issue_entity_spec.rb
+++ b/spec/serializers/issue_entity_spec.rb
@@ -39,6 +39,13 @@ RSpec.describe IssueEntity do
expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent)
end
+ describe 'current_user' do
+ it 'has the exprected permissions' do
+ expect(subject[:current_user]).to include(:can_create_note, :can_update, :can_set_issue_metadata,
+ :can_award_emoji)
+ end
+ end
+
context 'when issue got moved' do
let(:public_project) { create(:project, :public) }
let(:member) { create(:user) }
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 409585e52f1..90a82d16e38 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -184,38 +184,8 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
describe '#mergeable_discussions_state?' do
- context 'when change_response_code_merge_status is true' do
- before do
- stub_feature_flags(change_response_code_merge_status: true)
- end
-
- it 'returns mergeable discussions state' do
- expect(subject[:mergeable_discussions_state]).to eq(true)
- end
- end
-
- context 'when change_response_code_merge_status is false' do
- context 'when merge request is in a mergeable state' do
- before do
- stub_feature_flags(change_response_code_merge_status: false)
- allow(resource).to receive(:mergeable_discussions_state?).and_return(true)
- end
-
- it 'returns mergeable discussions state' do
- expect(subject[:mergeable_discussions_state]).to eq(true)
- end
- end
-
- context 'when merge request is not in a mergeable state' do
- before do
- stub_feature_flags(change_response_code_merge_status: false)
- allow(resource).to receive(:mergeable_state?).and_return(false)
- end
-
- it 'returns mergeable discussions state' do
- expect(subject[:mergeable_discussions_state]).to eq(false)
- end
- end
+ it 'returns mergeable discussions state' do
+ expect(subject[:mergeable_discussions_state]).to eq(true)
end
end
end
diff --git a/spec/serializers/merge_request_user_entity_spec.rb b/spec/serializers/merge_request_user_entity_spec.rb
index 7877356ff0f..5c7120ab6a4 100644
--- a/spec/serializers/merge_request_user_entity_spec.rb
+++ b/spec/serializers/merge_request_user_entity_spec.rb
@@ -18,8 +18,7 @@ RSpec.describe MergeRequestUserEntity do
it 'exposes needed attributes' do
is_expected.to include(
:id, :name, :username, :state, :avatar_url, :web_url,
- :can_merge, :can_update_merge_request, :reviewed, :approved,
- :attention_requested
+ :can_merge, :can_update_merge_request, :reviewed, :approved
)
end
@@ -57,14 +56,6 @@ RSpec.describe MergeRequestUserEntity do
end
end
- context 'attention_requested' do
- before do
- merge_request.find_assignee(user).update!(state: :attention_requested)
- end
-
- it { is_expected.to include(attention_requested: true ) }
- end
-
describe 'performance' do
let_it_be(:user_a) { create(:user) }
let_it_be(:user_b) { create(:user) }
diff --git a/spec/serializers/personal_access_token_entity_spec.rb b/spec/serializers/personal_access_token_entity_spec.rb
new file mode 100644
index 00000000000..8a77a4e0036
--- /dev/null
+++ b/spec/serializers/personal_access_token_entity_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PersonalAccessTokenEntity do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { create(:personal_access_token, user: user) }
+
+ subject(:json) { described_class.new(token).as_json }
+
+ it 'has the correct attributes' do
+ expected_revoke_path = Gitlab::Routing.url_helpers
+ .revoke_profile_personal_access_token_path(
+ { id: token })
+
+ expect(json).to(
+ include(
+ id: token.id,
+ name: token.name,
+ scopes: token.scopes,
+ user_id: token.user_id,
+ revoke_path: expected_revoke_path
+ ))
+
+ expect(json).not_to include(:token)
+ end
+end
diff --git a/spec/serializers/personal_access_token_serializer_spec.rb b/spec/serializers/personal_access_token_serializer_spec.rb
new file mode 100644
index 00000000000..e4adc6abccb
--- /dev/null
+++ b/spec/serializers/personal_access_token_serializer_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PersonalAccessTokenSerializer do
+ subject(:serializer) { described_class.new }
+
+ describe '#represent' do
+ it 'can render a single token' do
+ token = create(:personal_access_token)
+
+ expect(serializer.represent(token)).to be_kind_of(Hash)
+ end
+
+ it 'can render a collection of tokens' do
+ tokens = create_list(:personal_access_token, 2)
+
+ expect(serializer.represent(tokens)).to be_kind_of(Array)
+ end
+ end
+end
diff --git a/spec/serializers/project_access_token_entity_spec.rb b/spec/serializers/project_access_token_entity_spec.rb
new file mode 100644
index 00000000000..616aa45e9d5
--- /dev/null
+++ b/spec/serializers/project_access_token_entity_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProjectAccessTokenEntity do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:bot) { create(:user, :project_bot) }
+ let_it_be(:token) { create(:personal_access_token, user: bot) }
+
+ subject(:json) { described_class.new(token, project: project).as_json }
+
+ context 'when bot is a member of the project' do
+ before do
+ project.add_developer(bot)
+ end
+
+ it 'has the correct attributes' do
+ expected_revoke_path = Gitlab::Routing.url_helpers
+ .revoke_namespace_project_settings_access_token_path(
+ { id: token,
+ namespace_id: project.namespace.path,
+ project_id: project.path })
+
+ expect(json).to(
+ include(
+ id: token.id,
+ name: token.name,
+ scopes: token.scopes,
+ user_id: token.user_id,
+ revoke_path: expected_revoke_path,
+ access_level: ::Gitlab::Access::DEVELOPER
+ ))
+
+ expect(json).not_to include(:token)
+ end
+ end
+
+ context 'when bot is unrelated to the project' do
+ let_it_be(:project) { create(:project) }
+
+ it 'has the correct attributes' do
+ expected_revoke_path = Gitlab::Routing.url_helpers
+ .revoke_namespace_project_settings_access_token_path(
+ { id: token,
+ namespace_id: project.namespace.path,
+ project_id: project.path })
+
+ expect(json).to(
+ include(
+ id: token.id,
+ name: token.name,
+ scopes: token.scopes,
+ user_id: token.user_id,
+ revoke_path: expected_revoke_path,
+ access_level: nil
+ ))
+
+ expect(json).not_to include(:token)
+ end
+ end
+end
diff --git a/spec/serializers/project_access_token_serializer_spec.rb b/spec/serializers/project_access_token_serializer_spec.rb
new file mode 100644
index 00000000000..1c0898d7841
--- /dev/null
+++ b/spec/serializers/project_access_token_serializer_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProjectAccessTokenSerializer do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:bot) { create(:user, :project_bot) }
+
+ subject(:serializer) { described_class.new }
+
+ before do
+ project.add_developer(bot)
+ end
+
+ describe '#represent' do
+ it 'can render a single token' do
+ token = create(:personal_access_token, user: bot)
+
+ expect(serializer.represent(token, project: project)).to be_kind_of(Hash)
+ end
+
+ it 'can render a collection of tokens' do
+ tokens = create_list(:personal_access_token, 2, user: bot)
+
+ expect(serializer.represent(tokens, project: project)).to be_kind_of(Array)
+ end
+ end
+end
diff --git a/spec/services/alert_management/process_prometheus_alert_service_spec.rb b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
index 86a6cdee52d..ae52a09be48 100644
--- a/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+++ b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
@@ -44,6 +44,7 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
end
it_behaves_like 'processes new firing alert'
+ include_examples 'handles race condition in alert creation'
context 'with resolving payload' do
let(:prometheus_status) { 'resolved' }
diff --git a/spec/services/audit_events/build_service_spec.rb b/spec/services/audit_events/build_service_spec.rb
new file mode 100644
index 00000000000..caf405a53aa
--- /dev/null
+++ b/spec/services/audit_events/build_service_spec.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuditEvents::BuildService do
+ let(:author) { build_stubbed(:author, current_sign_in_ip: '127.0.0.1') }
+ let(:deploy_token) { build_stubbed(:deploy_token, user: author) }
+ let(:scope) { build_stubbed(:group) }
+ let(:target) { build_stubbed(:project) }
+ let(:ip_address) { '192.168.8.8' }
+ let(:message) { 'Added an interesting field from project Gotham' }
+ let(:additional_details) { { action: :custom } }
+
+ subject(:service) do
+ described_class.new(
+ author: author,
+ scope: scope,
+ target: target,
+ message: message,
+ additional_details: additional_details,
+ ip_address: ip_address
+ )
+ end
+
+ describe '#execute', :request_store do
+ subject(:event) { service.execute }
+
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(ip_address)
+ end
+
+ it 'sets correct attributes', :aggregate_failures do
+ freeze_time do
+ expect(event).to have_attributes(
+ author_id: author.id,
+ author_name: author.name,
+ entity_id: scope.id,
+ entity_type: scope.class.name)
+
+ expect(event.details).to eq(
+ author_name: author.name,
+ author_class: author.class.name,
+ target_id: target.id,
+ target_type: target.class.name,
+ target_details: target.name,
+ custom_message: message,
+ action: :custom)
+
+ expect(event.ip_address).to be_nil
+ expect(event.created_at).to eq(DateTime.current)
+ end
+ end
+
+ context 'when IP address is not provided' do
+ let(:ip_address) { nil }
+
+ it 'uses author current_sign_in_ip' do
+ expect(event.ip_address).to be_nil
+ end
+ end
+
+ context 'when overriding target details' do
+ subject(:service) do
+ described_class.new(
+ author: author,
+ scope: scope,
+ target: target,
+ message: message,
+ target_details: "This is my target details"
+ )
+ end
+
+ it 'uses correct target details' do
+ expect(event.target_details).to eq("This is my target details")
+ end
+ end
+
+ context 'when deploy token is passed as author' do
+ let(:service) do
+ described_class.new(
+ author: deploy_token,
+ scope: scope,
+ target: target,
+ message: message
+ )
+ end
+
+ it 'expect author to be user' do
+ expect(event.author_id).to eq(-2)
+ expect(event.author_name).to eq(deploy_token.name)
+ end
+ end
+
+ context 'when deploy key is passed as author' do
+ let(:deploy_key) { build_stubbed(:deploy_key, user: author) }
+
+ let(:service) do
+ described_class.new(
+ author: deploy_key,
+ scope: scope,
+ target: target,
+ message: message
+ )
+ end
+
+ it 'expect author to be deploy key' do
+ expect(event.author_id).to eq(-3)
+ expect(event.author_name).to eq(deploy_key.name)
+ end
+ end
+
+ context 'when author is passed as UnauthenticatedAuthor' do
+ let(:service) do
+ described_class.new(
+ author: ::Gitlab::Audit::UnauthenticatedAuthor.new,
+ scope: scope,
+ target: target,
+ message: message
+ )
+ end
+
+ it 'sets author as unauthenticated user' do
+ expect(event.author).to be_an_instance_of(::Gitlab::Audit::UnauthenticatedAuthor)
+ expect(event.author_name).to eq('An unauthenticated user')
+ end
+ end
+
+ context 'when attributes are missing' do
+ context 'when author is missing' do
+ let(:author) { nil }
+
+ it { expect { service }.to raise_error(described_class::MissingAttributeError) }
+ end
+
+ context 'when scope is missing' do
+ let(:scope) { nil }
+
+ it { expect { service }.to raise_error(described_class::MissingAttributeError) }
+ end
+
+ context 'when target is missing' do
+ let(:target) { nil }
+
+ it { expect { service }.to raise_error(described_class::MissingAttributeError) }
+ end
+
+ context 'when message is missing' do
+ let(:message) { nil }
+
+ it { expect { service }.to raise_error(described_class::MissingAttributeError) }
+ end
+ end
+ end
+end
diff --git a/spec/services/auto_merge/base_service_spec.rb b/spec/services/auto_merge/base_service_spec.rb
index 3f535b83788..6c804a14620 100644
--- a/spec/services/auto_merge/base_service_spec.rb
+++ b/spec/services/auto_merge/base_service_spec.rb
@@ -254,7 +254,7 @@ RSpec.describe AutoMerge::BaseService do
subject { service.abort(merge_request, reason) }
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- let(:reason) { 'an error'}
+ let(:reason) { 'an error' }
it_behaves_like 'Canceled or Dropped'
diff --git a/spec/services/auto_merge_service_spec.rb b/spec/services/auto_merge_service_spec.rb
index 335c608c206..043b413acff 100644
--- a/spec/services/auto_merge_service_spec.rb
+++ b/spec/services/auto_merge_service_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe AutoMergeService do
end
context 'when strategy is not present' do
- let(:strategy) { }
+ let(:strategy) {}
it 'returns nil' do
is_expected.to be_nil
@@ -140,7 +140,7 @@ RSpec.describe AutoMergeService do
end
context 'when strategy is not specified' do
- let(:strategy) { }
+ let(:strategy) {}
it 'chooses the most preferred strategy' do
is_expected.to eq(:merge_when_pipeline_succeeds)
diff --git a/spec/services/branches/create_service_spec.rb b/spec/services/branches/create_service_spec.rb
index 0d2f5838574..26cc1a0665e 100644
--- a/spec/services/branches/create_service_spec.rb
+++ b/spec/services/branches/create_service_spec.rb
@@ -2,17 +2,155 @@
require 'spec_helper'
-RSpec.describe Branches::CreateService do
+RSpec.describe Branches::CreateService, :use_clean_rails_redis_caching do
subject(:service) { described_class.new(project, user) }
let_it_be(:project) { create(:project_empty_repo) }
let_it_be(:user) { create(:user) }
+ describe '#bulk_create' do
+ subject { service.bulk_create(branches) }
+
+ let_it_be(:project) { create(:project, :custom_repo, files: { 'foo/a.txt' => 'foo' }) }
+
+ let(:branches) { { 'branch' => 'master', 'another_branch' => 'master' } }
+
+ it 'creates two branches' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:branches].map(&:name)).to match_array(%w[branch another_branch])
+
+ expect(project.repository.branch_exists?('branch')).to be_truthy
+ expect(project.repository.branch_exists?('another_branch')).to be_truthy
+ end
+
+ context 'when branches are empty' do
+ let(:branches) { {} }
+
+ it 'is successful' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:branches]).to eq([])
+ end
+ end
+
+ context 'when incorrect reference is provided' do
+ let(:branches) { { 'new-feature' => 'unknown' } }
+
+ before do
+ allow(project.repository).to receive(:add_branch).and_return(false)
+ end
+
+ it 'returns an error with a reference name' do
+ err_msg = 'Failed to create branch \'new-feature\': invalid reference name \'unknown\''
+
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match_array([err_msg])
+ end
+ end
+
+ context 'when branch already exists' do
+ let(:branches) { { 'master' => 'master' } }
+
+ it 'returns an error' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match_array(['Branch already exists'])
+ end
+ end
+
+ context 'when an ambiguous branch name is provided' do
+ let(:branches) { { 'ambiguous/test' => 'master', 'ambiguous' => 'master' } }
+
+ it 'returns an error that branch could not be created' do
+ err_msg = 'Failed to create branch \'ambiguous\': 13:reference is ambiguous.'
+
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match_array([err_msg])
+ end
+ end
+
+ context 'when PreReceiveError exception' do
+ let(:branches) { { 'error' => 'master' } }
+
+ it 'logs and returns an error if there is a PreReceiveError exception' do
+ error_message = 'pre receive error'
+ raw_message = "GitLab: #{error_message}"
+ pre_receive_error = Gitlab::Git::PreReceiveError.new(raw_message)
+
+ allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
+
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ pre_receive_error,
+ pre_receive_message: raw_message,
+ branch_name: 'error',
+ ref: 'master'
+ )
+
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match_array([error_message])
+ end
+ end
+
+ context 'when multiple errors occur' do
+ let(:branches) { { 'master' => 'master', '' => 'master', 'failed_branch' => 'master' } }
+
+ it 'returns all errors' do
+ allow(project.repository).to receive(:add_branch).with(
+ user,
+ 'failed_branch',
+ 'master',
+ expire_cache: false
+ ).and_return(false)
+
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to match_array(
+ [
+ 'Branch already exists',
+ 'Branch name is invalid',
+ "Failed to create branch 'failed_branch': invalid reference name 'master'"
+ ]
+ )
+ end
+ end
+
+ context 'without N+1 for Redis cache' do
+ let(:branches) { { 'branch1' => 'master', 'branch2' => 'master', 'branch3' => 'master' } }
+
+ it 'does not trigger Redis recreation' do
+ project.repository.expire_branches_cache
+
+ control = RedisCommands::Recorder.new(pattern: ':branch_names:') { subject }
+
+ expect(control.by_command(:sadd).count).to eq(1)
+ end
+ end
+
+ context 'without N+1 branch cache expiration' do
+ let(:branches) { { 'branch_1' => 'master', 'branch_2' => 'master', 'branch_3' => 'master' } }
+
+ it 'triggers branch cache expiration only once' do
+ expect(project.repository).to receive(:expire_branches_cache).once
+
+ subject
+ end
+
+ context 'when branches were not added' do
+ let(:branches) { { 'master' => 'master' } }
+
+ it 'does not trigger branch expiration' do
+ expect(project.repository).not_to receive(:expire_branches_cache)
+
+ subject
+ end
+ end
+ end
+ end
+
describe '#execute' do
context 'when repository is empty' do
it 'creates master branch' do
- service.execute('my-feature', 'master')
+ result = service.execute('my-feature', 'master')
+ expect(result[:status]).to eq(:success)
+ expect(result[:branch].name).to eq('my-feature')
expect(project.repository.branch_exists?('master')).to be_truthy
end
diff --git a/spec/services/bulk_imports/create_service_spec.rb b/spec/services/bulk_imports/create_service_spec.rb
index 67ec6fee1ae..4b655dd5d6d 100644
--- a/spec/services/bulk_imports/create_service_spec.rb
+++ b/spec/services/bulk_imports/create_service_spec.rb
@@ -10,19 +10,19 @@ RSpec.describe BulkImports::CreateService do
{
source_type: 'group_entity',
source_full_path: 'full/path/to/group1',
- destination_name: 'destination group 1',
+ destination_slug: 'destination group 1',
destination_namespace: 'full/path/to/destination1'
},
{
source_type: 'group_entity',
source_full_path: 'full/path/to/group2',
- destination_name: 'destination group 2',
+ destination_slug: 'destination group 2',
destination_namespace: 'full/path/to/destination2'
},
{
source_type: 'project_entity',
source_full_path: 'full/path/to/project1',
- destination_name: 'destination project 1',
+ destination_slug: 'destination project 1',
destination_namespace: 'full/path/to/destination1'
}
]
diff --git a/spec/services/bulk_imports/file_download_service_spec.rb b/spec/services/bulk_imports/file_download_service_spec.rb
index bd664d6e996..81229cc8431 100644
--- a/spec/services/bulk_imports/file_download_service_spec.rb
+++ b/spec/services/bulk_imports/file_download_service_spec.rb
@@ -136,14 +136,45 @@ RSpec.describe BulkImports::FileDownloadService do
end
context 'when chunk code is not 200' do
- let(:chunk_double) { double('chunk', size: 1000, code: 307) }
+ let(:chunk_double) { double('chunk', size: 1000, code: 500) }
it 'raises an error' do
expect { subject.execute }.to raise_error(
described_class::ServiceError,
- 'File download error 307'
+ 'File download error 500'
)
end
+
+ context 'when chunk code is redirection' do
+ let(:chunk_double) { double('redirection', size: 1000, code: 303) }
+
+ it 'does not write a redirection chunk' do
+ expect { subject.execute }.not_to raise_error
+
+ expect(File.read(filepath)).not_to include('redirection')
+ end
+
+ context 'when redirection chunk appears at a later stage of the download' do
+ it 'raises an error' do
+ another_chunk_double = double('another redirection', size: 1000, code: 303)
+ data_chunk = double('data chunk', size: 1000, code: 200)
+
+ allow_next_instance_of(BulkImports::Clients::HTTP) do |client|
+ allow(client).to receive(:head).and_return(response_double)
+ allow(client)
+ .to receive(:stream)
+ .and_yield(chunk_double)
+ .and_yield(data_chunk)
+ .and_yield(another_chunk_double)
+ end
+
+ expect { subject.execute }.to raise_error(
+ described_class::ServiceError,
+ 'File download error 303'
+ )
+ end
+ end
+ end
end
context 'when file is a symlink' do
diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb
index e3e38aacaa2..7c5bd1db565 100644
--- a/spec/services/bulk_update_integration_service_spec.rb
+++ b/spec/services/bulk_update_integration_service_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe BulkUpdateIntegrationService do
context 'with integration with data fields' do
let(:excluded_attributes) do
- %w[id service_id created_at updated_at encrypted_properties encrypted_properties_iv]
+ %w[id integration_id created_at updated_at encrypted_properties encrypted_properties_iv]
end
it 'updates the data fields from the integration', :aggregate_failures do
diff --git a/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb b/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
index 9add096d782..7c698242921 100644
--- a/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/evaluate_runner_tags_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::CreatePipelineService do
let_it_be(:group) { create(:group, :private) }
- let_it_be(:group_variable) { create(:ci_group_variable, group: group, key: 'RUNNER_TAG', value: 'group')}
+ let_it_be(:group_variable) { create(:ci_group_variable, group: group, key: 'RUNNER_TAG', value: 'group') }
let_it_be(:project) { create(:project, :repository, group: group) }
let_it_be(:user) { create(:user) }
diff --git a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
index 4326fa5533f..cc808b7e61c 100644
--- a/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
+++ b/spec/services/ci/create_pipeline_service/parent_child_pipeline_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
expect(pipeline.statuses).to match_array [test, bridge]
expect(bridge.options).to eq(expected_bridge_options)
expect(bridge.yaml_variables)
- .to include(key: 'CROSS', value: 'downstream', public: true)
+ .to include(key: 'CROSS', value: 'downstream')
end
end
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index d0ce1c5aba8..6e48141226d 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -7,10 +7,38 @@ RSpec.describe Ci::CreatePipelineService do
let(:ref) { 'refs/heads/master' }
let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source).payload }
+ let(:response) { execute_service }
+ let(:pipeline) { response.payload }
let(:build_names) { pipeline.builds.pluck(:name) }
+ def execute_service(before: '00000000', variables_attributes: nil)
+ params = { ref: ref, before: before, after: project.commit(ref).sha, variables_attributes: variables_attributes }
+
+ described_class
+ .new(project, user, params)
+ .execute(source) do |pipeline|
+ yield(pipeline) if block_given?
+ end
+ end
+
context 'job:rules' do
+ let(:regular_job) { find_job('regular-job') }
+ let(:rules_job) { find_job('rules-job') }
+ let(:delayed_job) { find_job('delayed-job') }
+
+ def find_job(name)
+ pipeline.builds.find_by(name: name)
+ end
+
+ shared_examples 'rules jobs are excluded' do
+ it 'only persists the job without rules' do
+ expect(pipeline).to be_persisted
+ expect(regular_job).to be_persisted
+ expect(rules_job).to be_nil
+ expect(delayed_job).to be_nil
+ end
+ end
+
before do
stub_ci_pipeline_yaml_file(config)
allow_next_instance_of(Ci::BuildScheduleWorker) do |instance|
@@ -95,10 +123,6 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'with allow_failure and exit_codes', :aggregate_failures do
- def find_job(name)
- pipeline.builds.find_by(name: name)
- end
-
let(:config) do
<<-EOY
job-1:
@@ -280,6 +304,773 @@ RSpec.describe Ci::CreatePipelineService do
end
end
end
+
+ context 'with simple if: clauses' do
+ let(:config) do
+ <<-EOY
+ regular-job:
+ script: 'echo Hello, World!'
+
+ master-job:
+ script: "echo hello world, $CI_COMMIT_REF_NAME"
+ rules:
+ - if: $CI_COMMIT_REF_NAME == "nonexistant-branch"
+ when: never
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ negligible-job:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ allow_failure: true
+
+ delayed-job:
+ script: "echo See you later, World!"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: delayed
+ start_in: 1 hour
+
+ never-job:
+ script: "echo Goodbye, World!"
+ rules:
+ - if: $CI_COMMIT_REF_NAME
+ when: never
+ EOY
+ end
+
+ context 'with matches' do
+ it 'creates a pipeline with the vanilla and manual jobs' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly(
+ 'regular-job', 'delayed-job', 'master-job', 'negligible-job'
+ )
+ end
+
+ it 'assigns job:when values to the builds' do
+ expect(find_job('regular-job').when).to eq('on_success')
+ expect(find_job('master-job').when).to eq('manual')
+ expect(find_job('negligible-job').when).to eq('on_success')
+ expect(find_job('delayed-job').when).to eq('delayed')
+ end
+
+ it 'assigns job:allow_failure values to the builds' do
+ expect(find_job('regular-job').allow_failure).to eq(false)
+ expect(find_job('master-job').allow_failure).to eq(false)
+ expect(find_job('negligible-job').allow_failure).to eq(true)
+ expect(find_job('delayed-job').allow_failure).to eq(false)
+ end
+
+ it 'assigns start_in for delayed jobs' do
+ expect(delayed_job.options[:start_in]).to eq('1 hour')
+ end
+ end
+
+ context 'with no matches' do
+ let(:ref) { 'refs/heads/feature' }
+
+ it_behaves_like 'rules jobs are excluded'
+ end
+ end
+
+ context 'with complex if: clauses' do
+ let(:config) do
+ <<-EOY
+ regular-job:
+ script: 'echo Hello, World!'
+ rules:
+ - if: $VAR == 'present' && $OTHER || $CI_COMMIT_REF_NAME
+ when: manual
+ allow_failure: true
+ EOY
+ end
+
+ it 'matches the first rule' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ expect(regular_job.when).to eq('manual')
+ expect(regular_job.allow_failure).to eq(true)
+ end
+ end
+ end
+
+ context 'changes:' do
+ let(:config) do
+ <<-EOY
+ regular-job:
+ script: 'echo Hello, World!'
+
+ rules-job:
+ script: "echo hello world, $CI_COMMIT_REF_NAME"
+ rules:
+ - changes:
+ - README.md
+ when: manual
+ - changes:
+ - app.rb
+ when: on_success
+
+ delayed-job:
+ script: "echo See you later, World!"
+ rules:
+ - changes:
+ - README.md
+ when: delayed
+ start_in: 4 hours
+
+ negligible-job:
+ script: "can be failed sometimes"
+ rules:
+ - changes:
+ - README.md
+ allow_failure: true
+
+ README:
+ script: "I use variables for changes!"
+ rules:
+ - changes:
+ - $CI_JOB_NAME*
+
+ changes-paths:
+ script: "I am using a new syntax!"
+ rules:
+ - changes:
+ paths: [README.md]
+ EOY
+ end
+
+ context 'and matches' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[README.md])
+ end
+ end
+
+ it 'creates five jobs' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly(
+ 'regular-job', 'rules-job', 'delayed-job', 'negligible-job', 'README', 'changes-paths'
+ )
+ end
+
+ it 'sets when: for all jobs' do
+ expect(regular_job.when).to eq('on_success')
+ expect(rules_job.when).to eq('manual')
+ expect(delayed_job.when).to eq('delayed')
+ expect(delayed_job.options[:start_in]).to eq('4 hours')
+ end
+
+ it 'sets allow_failure: for negligible job' do
+ expect(find_job('negligible-job').allow_failure).to eq(true)
+ end
+ end
+
+ context 'and matches the second rule' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[app.rb])
+ end
+ end
+
+ it 'includes both jobs' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job', 'rules-job')
+ end
+
+ it 'sets when: for the created rules job based on the second clause' do
+ expect(regular_job.when).to eq('on_success')
+ expect(rules_job.when).to eq('on_success')
+ end
+ end
+
+ context 'and does not match' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[useless_script.rb])
+ end
+ end
+
+ it_behaves_like 'rules jobs are excluded'
+
+ it 'sets when: for the created job' do
+ expect(regular_job.when).to eq('on_success')
+ end
+ end
+
+ context 'with paths and compare_to' do
+ let_it_be(:project) { create(:project, :empty_repo) }
+ let_it_be(:user) { project.first_owner }
+
+ before_all do
+ project.repository.add_branch(user, 'feature_1', 'master')
+
+ project.repository.create_file(
+ user, 'file1.txt', 'file 1', message: 'Create file1.txt', branch_name: 'feature_1'
+ )
+
+ project.repository.add_branch(user, 'feature_2', 'feature_1')
+
+ project.repository.create_file(
+ user, 'file2.txt', 'file 2', message: 'Create file2.txt', branch_name: 'feature_2'
+ )
+ end
+
+ let(:changed_file) { 'file2.txt' }
+ let(:ref) { 'feature_2' }
+
+ let(:response) { execute_service(before: nil) }
+
+ context 'for jobs rules' do
+ let(:config) do
+ <<-EOY
+ job1:
+ script: exit 0
+ rules:
+ - changes:
+ paths: [#{changed_file}]
+ compare_to: #{compare_to}
+
+ job2:
+ script: exit 0
+ EOY
+ end
+
+ context 'when there is no such compare_to ref' do
+ 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
+ end
+ end
+
+ context 'when the compare_to ref exists' do
+ let(:compare_to) { 'feature_1' }
+
+ context 'when the rule matches' do
+ 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
+ let(:changed_file) { 'file1.txt' }
+
+ 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
+
+ context 'for workflow rules' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - changes:
+ paths: [#{changed_file}]
+ compare_to: #{compare_to}
+
+ job1:
+ script: exit 0
+ EOY
+ end
+
+ let(:compare_to) { 'feature_1' }
+
+ context 'when the rule matches' do
+ it 'creates job1' do
+ 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
+ let(:changed_file) { 'file1.txt' }
+
+ it 'does not create job1' do
+ expect(pipeline).not_to be_created_successfully
+ expect(build_names).to be_empty
+ end
+ end
+ end
+ end
+ end
+
+ context 'mixed if: and changes: rules' do
+ let(:config) do
+ <<-EOY
+ regular-job:
+ script: 'echo Hello, World!'
+
+ rules-job:
+ script: "echo hello world, $CI_COMMIT_REF_NAME"
+ allow_failure: true
+ rules:
+ - changes:
+ - README.md
+ when: manual
+ - if: $CI_COMMIT_REF_NAME == "master"
+ when: on_success
+ allow_failure: false
+
+ delayed-job:
+ script: "echo See you later, World!"
+ rules:
+ - changes:
+ - README.md
+ when: delayed
+ start_in: 4 hours
+ allow_failure: true
+ - if: $CI_COMMIT_REF_NAME == "master"
+ when: delayed
+ start_in: 1 hour
+ EOY
+ end
+
+ context 'and changes: matches before if' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[README.md])
+ end
+ end
+
+ it 'creates two jobs' do
+ expect(pipeline).to be_persisted
+ expect(build_names)
+ .to contain_exactly('regular-job', 'rules-job', 'delayed-job')
+ end
+
+ it 'sets when: for all jobs' do
+ expect(regular_job.when).to eq('on_success')
+ expect(rules_job.when).to eq('manual')
+ expect(delayed_job.when).to eq('delayed')
+ expect(delayed_job.options[:start_in]).to eq('4 hours')
+ end
+
+ it 'sets allow_failure: for all jobs' do
+ expect(regular_job.allow_failure).to eq(false)
+ expect(rules_job.allow_failure).to eq(true)
+ expect(delayed_job.allow_failure).to eq(true)
+ end
+ end
+
+ context 'and if: matches after changes' do
+ it 'includes both jobs' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job', 'rules-job', 'delayed-job')
+ end
+
+ it 'sets when: for the created rules job based on the second clause' do
+ expect(regular_job.when).to eq('on_success')
+ expect(rules_job.when).to eq('on_success')
+ expect(delayed_job.when).to eq('delayed')
+ expect(delayed_job.options[:start_in]).to eq('1 hour')
+ end
+ end
+
+ context 'and does not match' do
+ let(:ref) { 'refs/heads/wip' }
+
+ it_behaves_like 'rules jobs are excluded'
+
+ it 'sets when: for the created job' do
+ expect(regular_job.when).to eq('on_success')
+ end
+ end
+ end
+
+ context 'mixed if: and changes: clauses' do
+ let(:config) do
+ <<-EOY
+ regular-job:
+ script: 'echo Hello, World!'
+
+ rules-job:
+ script: "echo hello world, $CI_COMMIT_REF_NAME"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ changes: [README.md]
+ when: on_success
+ allow_failure: true
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ changes: [app.rb]
+ when: manual
+ EOY
+ end
+
+ context 'with if matches and changes matches' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[app.rb])
+ end
+ end
+
+ it 'persists all jobs' do
+ expect(pipeline).to be_persisted
+ expect(regular_job).to be_persisted
+ expect(rules_job).to be_persisted
+ expect(rules_job.when).to eq('manual')
+ expect(rules_job.allow_failure).to eq(false)
+ end
+ end
+
+ context 'with if matches and no change matches' do
+ it_behaves_like 'rules jobs are excluded'
+ end
+
+ context 'with change matches and no if matches' do
+ let(:ref) { 'refs/heads/feature' }
+
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[README.md])
+ end
+ end
+
+ it_behaves_like 'rules jobs are excluded'
+ end
+
+ context 'and no matches' do
+ let(:ref) { 'refs/heads/feature' }
+
+ it_behaves_like 'rules jobs are excluded'
+ end
+ end
+
+ context 'complex if: allow_failure usages' do
+ let(:config) do
+ <<-EOY
+ job-1:
+ script: "exit 1"
+ allow_failure: true
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ allow_failure: false
+
+ job-2:
+ script: "exit 1"
+ allow_failure: true
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
+ allow_failure: false
+
+ job-3:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
+ allow_failure: true
+
+ job-4:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ allow_failure: false
+
+ job-5:
+ script: "exit 1"
+ allow_failure: false
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ allow_failure: true
+
+ job-6:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
+ allow_failure: false
+ - allow_failure: true
+ EOY
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('job-1', 'job-4', 'job-5', 'job-6')
+ end
+
+ it 'assigns job:allow_failure values to the builds' do
+ expect(find_job('job-1').allow_failure).to eq(false)
+ expect(find_job('job-4').allow_failure).to eq(false)
+ expect(find_job('job-5').allow_failure).to eq(true)
+ expect(find_job('job-6').allow_failure).to eq(true)
+ end
+ end
+
+ context 'complex if: allow_failure & when usages' do
+ let(:config) do
+ <<-EOY
+ job-1:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ job-2:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+ allow_failure: true
+
+ job-3:
+ script: "exit 1"
+ allow_failure: true
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ job-4:
+ script: "exit 1"
+ allow_failure: true
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+ allow_failure: false
+
+ job-5:
+ script: "exit 1"
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
+ when: manual
+ allow_failure: false
+ - when: always
+ allow_failure: true
+
+ job-6:
+ script: "exit 1"
+ allow_failure: false
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ job-7:
+ script: "exit 1"
+ allow_failure: false
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
+ when: manual
+ - when: :on_failure
+ allow_failure: true
+ EOY
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly(
+ 'job-1', 'job-2', 'job-3', 'job-4', 'job-5', 'job-6', 'job-7'
+ )
+ end
+
+ it 'assigns job:allow_failure values to the builds' do
+ expect(find_job('job-1').allow_failure).to eq(false)
+ expect(find_job('job-2').allow_failure).to eq(true)
+ expect(find_job('job-3').allow_failure).to eq(true)
+ expect(find_job('job-4').allow_failure).to eq(false)
+ expect(find_job('job-5').allow_failure).to eq(true)
+ expect(find_job('job-6').allow_failure).to eq(false)
+ expect(find_job('job-7').allow_failure).to eq(true)
+ end
+
+ it 'assigns job:when values to the builds' do
+ expect(find_job('job-1').when).to eq('manual')
+ expect(find_job('job-2').when).to eq('manual')
+ expect(find_job('job-3').when).to eq('manual')
+ expect(find_job('job-4').when).to eq('manual')
+ expect(find_job('job-5').when).to eq('always')
+ expect(find_job('job-6').when).to eq('manual')
+ expect(find_job('job-7').when).to eq('on_failure')
+ end
+ end
+
+ context 'deploy freeze period `if:` clause' do
+ # '0 23 * * 5' == "At 23:00 on Friday."", '0 7 * * 1' == "At 07:00 on Monday.""
+ let!(:freeze_period) { create(:ci_freeze_period, project: project, freeze_start: '0 23 * * 5', freeze_end: '0 7 * * 1') }
+
+ context 'with 2 jobs' do
+ let(:config) do
+ <<-EOY
+ stages:
+ - test
+ - deploy
+
+ test-job:
+ script:
+ - echo 'running TEST stage'
+
+ deploy-job:
+ stage: deploy
+ script:
+ - echo 'running DEPLOY stage'
+ rules:
+ - if: $CI_DEPLOY_FREEZE == null
+ EOY
+ end
+
+ context 'when outside freeze period' do
+ it 'creates two jobs' do
+ Timecop.freeze(2020, 4, 10, 22, 59) do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('test-job', 'deploy-job')
+ end
+ end
+ end
+
+ context 'when inside freeze period' do
+ it 'creates one job' do
+ Timecop.freeze(2020, 4, 10, 23, 1) do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('test-job')
+ end
+ end
+ end
+ end
+
+ context 'with 1 job' do
+ let(:config) do
+ <<-EOY
+ stages:
+ - deploy
+
+ deploy-job:
+ stage: deploy
+ script:
+ - echo 'running DEPLOY stage'
+ rules:
+ - if: $CI_DEPLOY_FREEZE == null
+ EOY
+ end
+
+ context 'when outside freeze period' do
+ it 'creates two jobs' do
+ Timecop.freeze(2020, 4, 10, 22, 59) do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('deploy-job')
+ end
+ end
+ end
+
+ context 'when inside freeze period' do
+ it 'does not create the pipeline', :aggregate_failures do
+ Timecop.freeze(2020, 4, 10, 23, 1) do
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+ end
+ end
+
+ context 'with when:manual' do
+ let(:config) do
+ <<-EOY
+ job-with-rules:
+ script: 'echo hey'
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+
+ job-when-with-rules:
+ script: 'echo hey'
+ when: manual
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+
+ job-when-with-rules-when:
+ script: 'echo hey'
+ when: manual
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: on_success
+
+ job-with-rules-when:
+ script: 'echo hey'
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ job-without-rules:
+ script: 'echo this is a job with NO rules'
+ EOY
+ end
+
+ let(:job_with_rules) { find_job('job-with-rules') }
+ let(:job_when_with_rules) { find_job('job-when-with-rules') }
+ let(:job_when_with_rules_when) { find_job('job-when-with-rules-when') }
+ let(:job_with_rules_when) { find_job('job-with-rules-when') }
+ let(:job_without_rules) { find_job('job-without-rules') }
+
+ context 'when matching the rules' do
+ let(:ref) { 'refs/heads/master' }
+
+ it 'adds the job-with-rules with a when:manual' do
+ expect(job_with_rules).to be_persisted
+ expect(job_when_with_rules).to be_persisted
+ expect(job_when_with_rules_when).to be_persisted
+ expect(job_with_rules_when).to be_persisted
+ expect(job_without_rules).to be_persisted
+
+ expect(job_with_rules.when).to eq('on_success')
+ expect(job_when_with_rules.when).to eq('manual')
+ expect(job_when_with_rules_when.when).to eq('on_success')
+ expect(job_with_rules_when.when).to eq('manual')
+ expect(job_without_rules.when).to eq('on_success')
+ end
+ end
+
+ context 'when there is no match to the rule' do
+ let(:ref) { 'refs/heads/wip' }
+
+ it 'does not add job_with_rules' do
+ expect(job_with_rules).to be_nil
+ expect(job_when_with_rules).to be_nil
+ expect(job_when_with_rules_when).to be_nil
+ expect(job_with_rules_when).to be_nil
+ expect(job_without_rules).to be_persisted
+ end
+ end
end
end
@@ -447,5 +1238,232 @@ RSpec.describe Ci::CreatePipelineService do
end
end
end
+
+ context 'with persisted variables' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == "master"
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+ end
+
+ context 'with no matches' do
+ let(:ref) { 'refs/heads/feature' }
+
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+
+ context 'with pipeline variables' do
+ let(:pipeline) do
+ execute_service(variables_attributes: variables_attributes).payload
+ end
+
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ let(:variables_attributes) do
+ [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+ end
+
+ context 'with no matches' do
+ let(:variables_attributes) { {} }
+
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+
+ context 'with trigger variables' do
+ let(:pipeline) do
+ execute_service do |pipeline|
+ pipeline.variables.build(variables)
+ end.payload
+ end
+
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ regular-job:
+ script: 'echo Hello, World!'
+ EOY
+ end
+
+ context 'with matches' do
+ let(:variables) do
+ [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('regular-job')
+ end
+
+ context 'when a job requires the same variable' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ build:
+ stage: build
+ script: 'echo build'
+ rules:
+ - if: $SOME_VARIABLE
+
+ test1:
+ stage: test
+ script: 'echo test1'
+ needs: [build]
+
+ test2:
+ stage: test
+ script: 'echo test2'
+ EOY
+ end
+
+ it 'creates a pipeline' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('build', 'test1', 'test2')
+ end
+ end
+ end
+
+ context 'with no matches' do
+ let(:variables) { {} }
+
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+
+ context 'when a job requires the same variable' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - if: $SOME_VARIABLE
+
+ build:
+ stage: build
+ script: 'echo build'
+ rules:
+ - if: $SOME_VARIABLE
+
+ test1:
+ stage: test
+ script: 'echo test1'
+ needs: [build]
+
+ test2:
+ stage: test
+ script: 'echo test2'
+ EOY
+ end
+
+ it 'does not create a pipeline', :aggregate_failures do
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+ end
+
+ context 'changes' do
+ shared_examples 'comparing file changes with workflow rules' do
+ context 'when matches' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[file1.md])
+ end
+ end
+
+ it 'creates the pipeline with a job' do
+ expect(pipeline).to be_persisted
+ expect(build_names).to contain_exactly('job')
+ end
+ end
+
+ context 'when does not match' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:modified_paths).and_return(%w[unknown])
+ end
+ end
+
+ it 'creates the pipeline with a job' do
+ expect(pipeline.errors.full_messages).to eq(['Pipeline filtered out by workflow rules.'])
+ expect(response).to be_error
+ expect(pipeline).not_to be_persisted
+ end
+ end
+ end
+
+ context 'changes is an array' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - changes: [file1.md]
+
+ job:
+ script: exit 0
+ EOY
+ end
+
+ it_behaves_like 'comparing file changes with workflow rules'
+ end
+
+ context 'changes:paths is an array' do
+ let(:config) do
+ <<-EOY
+ workflow:
+ rules:
+ - changes:
+ paths: [file1.md]
+
+ job:
+ script: exit 0
+ EOY
+ end
+
+ it_behaves_like 'comparing file changes with workflow rules'
+ end
+ end
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 9cef7f7dadb..a9442b0dc68 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Ci::CreatePipelineService do
# rubocop:disable Metrics/ParameterLists
def execute_service(
source: :push,
+ before: '00000000',
after: project.commit.id,
ref: ref_name,
trigger_request: nil,
@@ -29,7 +30,7 @@ RSpec.describe Ci::CreatePipelineService do
target_sha: nil,
save_on_errors: true)
params = { ref: ref,
- before: '00000000',
+ before: before,
after: after,
variables_attributes: variables_attributes,
push_options: push_options,
@@ -1865,818 +1866,6 @@ RSpec.describe Ci::CreatePipelineService do
end
end
end
-
- context 'when rules are used' do
- let(:ref_name) { 'refs/heads/master' }
- let(:response) { execute_service }
- let(:pipeline) { response.payload }
- let(:build_names) { pipeline.builds.pluck(:name) }
- let(:regular_job) { find_job('regular-job') }
- let(:rules_job) { find_job('rules-job') }
- let(:delayed_job) { find_job('delayed-job') }
-
- context 'with when:manual' do
- let(:config) do
- <<-EOY
- job-with-rules:
- script: 'echo hey'
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
-
- job-when-with-rules:
- script: 'echo hey'
- when: manual
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
-
- job-when-with-rules-when:
- script: 'echo hey'
- when: manual
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: on_success
-
- job-with-rules-when:
- script: 'echo hey'
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-without-rules:
- script: 'echo this is a job with NO rules'
- EOY
- end
-
- let(:job_with_rules) { find_job('job-with-rules') }
- let(:job_when_with_rules) { find_job('job-when-with-rules') }
- let(:job_when_with_rules_when) { find_job('job-when-with-rules-when') }
- let(:job_with_rules_when) { find_job('job-with-rules-when') }
- let(:job_without_rules) { find_job('job-without-rules') }
-
- context 'when matching the rules' do
- let(:ref_name) { 'refs/heads/master' }
-
- it 'adds the job-with-rules with a when:manual' do
- expect(job_with_rules).to be_persisted
- expect(job_when_with_rules).to be_persisted
- expect(job_when_with_rules_when).to be_persisted
- expect(job_with_rules_when).to be_persisted
- expect(job_without_rules).to be_persisted
-
- expect(job_with_rules.when).to eq('on_success')
- expect(job_when_with_rules.when).to eq('manual')
- expect(job_when_with_rules_when.when).to eq('on_success')
- expect(job_with_rules_when.when).to eq('manual')
- expect(job_without_rules.when).to eq('on_success')
- end
- end
-
- context 'when there is no match to the rule' do
- let(:ref_name) { 'refs/heads/wip' }
-
- it 'does not add job_with_rules' do
- expect(job_with_rules).to be_nil
- expect(job_when_with_rules).to be_nil
- expect(job_when_with_rules_when).to be_nil
- expect(job_with_rules_when).to be_nil
- expect(job_without_rules).to be_persisted
- end
- end
- end
-
- shared_examples 'rules jobs are excluded' do
- it 'only persists the job without rules' do
- expect(pipeline).to be_persisted
- expect(regular_job).to be_persisted
- expect(rules_job).to be_nil
- expect(delayed_job).to be_nil
- end
- end
-
- def find_job(name)
- pipeline.builds.find_by(name: name)
- end
-
- before do
- stub_ci_pipeline_yaml_file(config)
- allow_any_instance_of(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
- end
-
- context 'with simple if: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- master-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - if: $CI_COMMIT_REF_NAME == "nonexistant-branch"
- when: never
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- negligible-job:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: true
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: delayed
- start_in: 1 hour
-
- never-job:
- script: "echo Goodbye, World!"
- rules:
- - if: $CI_COMMIT_REF_NAME
- when: never
- EOY
- end
-
- context 'with matches' do
- it 'creates a pipeline with the vanilla and manual jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'regular-job', 'delayed-job', 'master-job', 'negligible-job'
- )
- end
-
- it 'assigns job:when values to the builds' do
- expect(find_job('regular-job').when).to eq('on_success')
- expect(find_job('master-job').when).to eq('manual')
- expect(find_job('negligible-job').when).to eq('on_success')
- expect(find_job('delayed-job').when).to eq('delayed')
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('regular-job').allow_failure).to eq(false)
- expect(find_job('master-job').allow_failure).to eq(false)
- expect(find_job('negligible-job').allow_failure).to eq(true)
- expect(find_job('delayed-job').allow_failure).to eq(false)
- end
-
- it 'assigns start_in for delayed jobs' do
- expect(delayed_job.options[:start_in]).to eq('1 hour')
- end
- end
-
- context 'with no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it_behaves_like 'rules jobs are excluded'
- end
- end
-
- context 'with complex if: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
- rules:
- - if: $VAR == 'present' && $OTHER || $CI_COMMIT_REF_NAME
- when: manual
- allow_failure: true
- EOY
- end
-
- it 'matches the first rule' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- expect(regular_job.when).to eq('manual')
- expect(regular_job.allow_failure).to eq(true)
- end
- end
-
- context 'with changes:' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - changes:
- - README.md
- when: manual
- - changes:
- - app.rb
- when: on_success
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - changes:
- - README.md
- when: delayed
- start_in: 4 hours
-
- negligible-job:
- script: "can be failed sometimes"
- rules:
- - changes:
- - README.md
- allow_failure: true
-
- README:
- script: "I use variables for changes!"
- rules:
- - changes:
- - $CI_JOB_NAME*
-
- changes-paths:
- script: "I am using a new syntax!"
- rules:
- - changes:
- paths: [README.md]
- EOY
- end
-
- context 'and matches' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it 'creates five jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'regular-job', 'rules-job', 'delayed-job', 'negligible-job', 'README', 'changes-paths'
- )
- end
-
- it 'sets when: for all jobs' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('manual')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('4 hours')
- end
-
- it 'sets allow_failure: for negligible job' do
- expect(find_job('negligible-job').allow_failure).to eq(true)
- end
- end
-
- context 'and matches the second rule' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[app.rb])
- end
-
- it 'includes both jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job', 'rules-job')
- end
-
- it 'sets when: for the created rules job based on the second clause' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('on_success')
- end
- end
-
- context 'and does not match' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[useless_script.rb])
- end
-
- it_behaves_like 'rules jobs are excluded'
-
- it 'sets when: for the created job' do
- expect(regular_job.when).to eq('on_success')
- end
- end
- end
-
- context 'with mixed if: and changes: rules' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- allow_failure: true
- rules:
- - changes:
- - README.md
- when: manual
- - if: $CI_COMMIT_REF_NAME == "master"
- when: on_success
- allow_failure: false
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - changes:
- - README.md
- when: delayed
- start_in: 4 hours
- allow_failure: true
- - if: $CI_COMMIT_REF_NAME == "master"
- when: delayed
- start_in: 1 hour
- EOY
- end
-
- context 'and changes: matches before if' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it 'creates two jobs' do
- expect(pipeline).to be_persisted
- expect(build_names)
- .to contain_exactly('regular-job', 'rules-job', 'delayed-job')
- end
-
- it 'sets when: for all jobs' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('manual')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('4 hours')
- end
-
- it 'sets allow_failure: for all jobs' do
- expect(regular_job.allow_failure).to eq(false)
- expect(rules_job.allow_failure).to eq(true)
- expect(delayed_job.allow_failure).to eq(true)
- end
- end
-
- context 'and if: matches after changes' do
- it 'includes both jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job', 'rules-job', 'delayed-job')
- end
-
- it 'sets when: for the created rules job based on the second clause' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('on_success')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('1 hour')
- end
- end
-
- context 'and does not match' do
- let(:ref_name) { 'refs/heads/wip' }
-
- it_behaves_like 'rules jobs are excluded'
-
- it 'sets when: for the created job' do
- expect(regular_job.when).to eq('on_success')
- end
- end
- end
-
- context 'with mixed if: and changes: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- changes: [README.md]
- when: on_success
- allow_failure: true
- - if: $CI_COMMIT_REF_NAME =~ /master/
- changes: [app.rb]
- when: manual
- EOY
- end
-
- context 'with if matches and changes matches' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[app.rb])
- end
-
- it 'persists all jobs' do
- expect(pipeline).to be_persisted
- expect(regular_job).to be_persisted
- expect(rules_job).to be_persisted
- expect(rules_job.when).to eq('manual')
- expect(rules_job.allow_failure).to eq(false)
- end
- end
-
- context 'with if matches and no change matches' do
- it_behaves_like 'rules jobs are excluded'
- end
-
- context 'with change matches and no if matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it_behaves_like 'rules jobs are excluded'
- end
-
- context 'and no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it_behaves_like 'rules jobs are excluded'
- end
- end
-
- context 'with complex if: allow_failure usages' do
- let(:config) do
- <<-EOY
- job-1:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: false
-
- job-2:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: false
-
- job-3:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: true
-
- job-4:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: false
-
- job-5:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: true
-
- job-6:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: false
- - allow_failure: true
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('job-1', 'job-4', 'job-5', 'job-6')
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('job-1').allow_failure).to eq(false)
- expect(find_job('job-4').allow_failure).to eq(false)
- expect(find_job('job-5').allow_failure).to eq(true)
- expect(find_job('job-6').allow_failure).to eq(true)
- end
- end
-
- context 'with complex if: allow_failure & when usages' do
- let(:config) do
- <<-EOY
- job-1:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-2:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
- allow_failure: true
-
- job-3:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-4:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
- allow_failure: false
-
- job-5:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- when: manual
- allow_failure: false
- - when: always
- allow_failure: true
-
- job-6:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-7:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- when: manual
- - when: :on_failure
- allow_failure: true
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'job-1', 'job-2', 'job-3', 'job-4', 'job-5', 'job-6', 'job-7'
- )
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('job-1').allow_failure).to eq(false)
- expect(find_job('job-2').allow_failure).to eq(true)
- expect(find_job('job-3').allow_failure).to eq(true)
- expect(find_job('job-4').allow_failure).to eq(false)
- expect(find_job('job-5').allow_failure).to eq(true)
- expect(find_job('job-6').allow_failure).to eq(false)
- expect(find_job('job-7').allow_failure).to eq(true)
- end
-
- it 'assigns job:when values to the builds' do
- expect(find_job('job-1').when).to eq('manual')
- expect(find_job('job-2').when).to eq('manual')
- expect(find_job('job-3').when).to eq('manual')
- expect(find_job('job-4').when).to eq('manual')
- expect(find_job('job-5').when).to eq('always')
- expect(find_job('job-6').when).to eq('manual')
- expect(find_job('job-7').when).to eq('on_failure')
- end
- end
-
- context 'with deploy freeze period `if:` clause' do
- # '0 23 * * 5' == "At 23:00 on Friday."", '0 7 * * 1' == "At 07:00 on Monday.""
- let!(:freeze_period) { create(:ci_freeze_period, project: project, freeze_start: '0 23 * * 5', freeze_end: '0 7 * * 1') }
-
- context 'with 2 jobs' do
- let(:config) do
- <<-EOY
- stages:
- - test
- - deploy
-
- test-job:
- script:
- - echo 'running TEST stage'
-
- deploy-job:
- stage: deploy
- script:
- - echo 'running DEPLOY stage'
- rules:
- - if: $CI_DEPLOY_FREEZE == null
- EOY
- end
-
- context 'when outside freeze period' do
- it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('test-job', 'deploy-job')
- end
- end
- end
-
- context 'when inside freeze period' do
- it 'creates one job' do
- Timecop.freeze(2020, 4, 10, 23, 1) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('test-job')
- end
- end
- end
- end
-
- context 'with 1 job' do
- let(:config) do
- <<-EOY
- stages:
- - deploy
-
- deploy-job:
- stage: deploy
- script:
- - echo 'running DEPLOY stage'
- rules:
- - if: $CI_DEPLOY_FREEZE == null
- EOY
- end
-
- context 'when outside freeze period' do
- it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('deploy-job')
- end
- end
- end
-
- context 'when inside freeze period' do
- it 'does not create the pipeline', :aggregate_failures do
- Timecop.freeze(2020, 4, 10, 23, 1) do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
- end
- end
-
- context 'with workflow rules with persisted variables' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $CI_COMMIT_REF_NAME == "master"
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
- end
-
- context 'with no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
-
- context 'with workflow rules with pipeline variables' do
- let(:pipeline) do
- execute_service(variables_attributes: variables_attributes).payload
- end
-
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- let(:variables_attributes) do
- [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
- end
-
- context 'with no matches' do
- let(:variables_attributes) { {} }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
-
- context 'with workflow rules with trigger variables' do
- let(:pipeline) do
- execute_service do |pipeline|
- pipeline.variables.build(variables)
- end.payload
- end
-
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- let(:variables) do
- [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
-
- context 'when a job requires the same variable' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- build:
- stage: build
- script: 'echo build'
- rules:
- - if: $SOME_VARIABLE
-
- test1:
- stage: test
- script: 'echo test1'
- needs: [build]
-
- test2:
- stage: test
- script: 'echo test2'
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('build', 'test1', 'test2')
- end
- end
- end
-
- context 'with no matches' do
- let(:variables) { {} }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
-
- context 'when a job requires the same variable' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- build:
- stage: build
- script: 'echo build'
- rules:
- - if: $SOME_VARIABLE
-
- test1:
- stage: test
- script: 'echo test1'
- needs: [build]
-
- test2:
- stage: test
- script: 'echo test2'
- EOY
- end
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
- end
- end
end
describe '#execute!' do
diff --git a/spec/services/ci/deployments/destroy_service_spec.rb b/spec/services/ci/deployments/destroy_service_spec.rb
new file mode 100644
index 00000000000..60a57c05728
--- /dev/null
+++ b/spec/services/ci/deployments/destroy_service_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::Deployments::DestroyService do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:environment) { create(:environment, project: project) }
+ let(:commits) { project.repository.commits(nil, { limit: 3 }) }
+ let!(:deploy) do
+ create(
+ :deployment,
+ :success,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[2].sha
+ )
+ end
+
+ let!(:running_deploy) do
+ create(
+ :deployment,
+ :running,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[1].sha
+ )
+ end
+
+ let!(:old_deploy) do
+ create(
+ :deployment,
+ :success,
+ project: project,
+ environment: environment,
+ deployable: nil,
+ sha: commits[0].sha,
+ finished_at: 1.year.ago
+ )
+ end
+
+ let(:user) { project.first_owner }
+
+ subject { described_class.new(project, user) }
+
+ context 'when deleting a deployment' do
+ it 'delete is accepted for old deployment' do
+ expect(subject.execute(old_deploy)).to be_success
+ end
+
+ it 'does not delete a running deployment' do
+ response = subject.execute(running_deploy)
+ expect(response).to be_an_error
+ expect(response.message).to eq("Cannot destroy running deployment")
+ end
+
+ it 'does not delete the last deployment' do
+ response = subject.execute(deploy)
+ expect(response).to be_an_error
+ expect(response.message).to eq("Deployment currently deployed to environment")
+ end
+ end
+end
diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb
index 045051c7152..6bd7fe7559c 100644
--- a/spec/services/ci/destroy_pipeline_service_spec.rb
+++ b/spec/services/ci/destroy_pipeline_service_spec.rb
@@ -90,15 +90,23 @@ RSpec.describe ::Ci::DestroyPipelineService do
end
end
- context 'when pipeline is in cancelable state' do
- before do
- allow(pipeline).to receive(:cancelable?).and_return(true)
- end
+ context 'when pipeline is in cancelable state', :sidekiq_inline do
+ let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
+ let!(:child_pipeline) { create(:ci_pipeline, :running, child_of: pipeline) }
+ let!(:child_build) { create(:ci_build, :running, pipeline: child_pipeline) }
+
+ it 'cancels the pipelines sync' do
+ # turn off deletion for all instances of pipeline to allow for testing cancellation
+ allow(pipeline).to receive_message_chain(:reset, :destroy!)
+ allow_next_found_instance_of(Ci::Pipeline) { |p| allow(p).to receive_message_chain(:reset, :destroy!) }
- it 'cancels the pipeline' do
- expect(pipeline).to receive(:cancel_running)
+ # ensure cancellation happens sync so we accumulate minutes
+ expect(::Ci::CancelPipelineWorker).not_to receive(:perform)
subject
+
+ expect(build.reload.status).to eq('canceled')
+ expect(child_build.reload.status).to eq('canceled')
end
end
end
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index b7a810ce47e..7b3f67b192f 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -34,6 +34,14 @@ RSpec.describe Ci::JobArtifacts::CreateService do
subject { service.execute(artifacts_file, params, metadata_file: metadata_file) }
context 'when artifacts file is uploaded' do
+ it 'logs the created artifact' do
+ expect(Gitlab::Ci::Artifacts::Logger)
+ .to receive(:log_created)
+ .with(an_instance_of(Ci::JobArtifact))
+
+ subject
+ end
+
it 'returns artifact in the response' do
response = subject
new_artifact = job.job_artifacts.last
diff --git a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
index 05069054483..9ca39d4d32e 100644
--- a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
+++ b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
@@ -40,7 +40,14 @@ RSpec.describe Ci::JobArtifacts::DestroyBatchService do
expect { execute }.not_to change { artifact_with_file.file.exists? }
end
- it 'deletes the artifact records' do
+ it 'deletes the artifact records and logs them' do
+ expect(Gitlab::Ci::Artifacts::Logger)
+ .to receive(:log_deleted)
+ .with(
+ match_array([artifact_with_file, artifact_without_file]),
+ 'Ci::JobArtifacts::DestroyBatchService#execute'
+ )
+
expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
end
diff --git a/spec/services/ci/list_config_variables_service_spec.rb b/spec/services/ci/list_config_variables_service_spec.rb
index 1735f4cfc97..4953b18bfcc 100644
--- a/spec/services/ci/list_config_variables_service_spec.rb
+++ b/spec/services/ci/list_config_variables_service_spec.rb
@@ -40,8 +40,8 @@ RSpec.describe Ci::ListConfigVariablesService, :use_clean_rails_memory_store_cac
it 'returns variable list' do
expect(subject['KEY1']).to eq({ value: 'val 1', description: 'description 1' })
expect(subject['KEY2']).to eq({ value: 'val 2', description: '' })
- expect(subject['KEY3']).to eq({ value: 'val 3', description: nil })
- expect(subject['KEY4']).to eq({ value: 'val 4', description: nil })
+ expect(subject['KEY3']).to eq({ value: 'val 3' })
+ expect(subject['KEY4']).to eq({ value: 'val 4' })
end
end
diff --git a/spec/services/ci/parse_dotenv_artifact_service_spec.rb b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
index aaab849cd93..7b3af33ac72 100644
--- a/spec/services/ci/parse_dotenv_artifact_service_spec.rb
+++ b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
@@ -292,7 +292,7 @@ RSpec.describe Ci::ParseDotenvArtifactService do
end
context 'when build does not have a dotenv artifact' do
- let!(:artifact) { }
+ let!(:artifact) {}
it 'raises an error' do
expect { subject }.to raise_error(ArgumentError)
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
index 7868629d34d..289e004fcce 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe Ci::PipelineProcessing::AtomicProcessingService::StatusCollection
describe '#processing_processables' do
it 'returns processables marked as processing' do
- expect(collection.processing_processables.map { |processable| processable[:id]} )
+ expect(collection.processing_processables.map { |processable| processable[:id] } )
.to contain_exactly(build_a.id, build_b.id, test_a.id, test_b.id, deploy.id)
end
end
diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb
index b54fc45d36a..2fcb4ce73ff 100644
--- a/spec/services/ci/process_build_service_spec.rb
+++ b/spec/services/ci/process_build_service_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe Ci::ProcessBuildService, '#execute' do
context 'when build has delayed option' do
before do
- allow(Ci::BuildScheduleWorker).to receive(:perform_at) { }
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at) {}
end
let(:build) { create(:ci_build, :created, :schedulable, user: user, project: project) }
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 2316575f164..cabd60a22d1 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -129,6 +129,12 @@ module Ci
let!(:build2_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) }
let!(:build1_project3) { create(:ci_build, :pending, :queued, pipeline: pipeline3) }
+ it 'picks builds one-by-one' do
+ expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original
+
+ expect(execute(shared_runner)).to eq(build1_project1)
+ end
+
context 'when using fair scheduling' do
context 'when all builds are pending' do
it 'prefers projects without builds first' do
@@ -485,6 +491,48 @@ module Ci
end
context 'when "dependencies" keyword is specified' do
+ let!(:pre_stage_job) do
+ create(:ci_build, :success, :artifacts, pipeline: pipeline, name: 'test', stage_idx: 0)
+ end
+
+ let!(:pending_job) do
+ create(:ci_build, :pending, :queued,
+ pipeline: pipeline, stage_idx: 1,
+ options: { script: ["bash"], dependencies: dependencies })
+ end
+
+ let(:dependencies) { %w[test] }
+
+ subject { execute(specific_runner) }
+
+ it 'picks a build with a dependency' do
+ picked_build = execute(specific_runner)
+
+ expect(picked_build).to be_present
+ end
+
+ context 'when there are multiple dependencies with artifacts' do
+ let!(:pre_stage_job_second) do
+ create(:ci_build, :success, :artifacts, pipeline: pipeline, name: 'deploy', stage_idx: 0)
+ end
+
+ let(:dependencies) { %w[test deploy] }
+
+ it 'logs build artifacts size' do
+ execute(specific_runner)
+
+ artifacts_size = [pre_stage_job, pre_stage_job_second].sum do |job|
+ job.job_artifacts_archive.size
+ end
+
+ expect(artifacts_size).to eq 107464 * 2
+ expect(Gitlab::ApplicationContext.current).to include({
+ 'meta.artifacts_dependencies_size' => artifacts_size,
+ 'meta.artifacts_dependencies_count' => 2
+ })
+ end
+ end
+
shared_examples 'not pick' do
it 'does not pick the build and drops the build' do
expect(subject).to be_nil
@@ -572,16 +620,6 @@ module Ci
end
end
- let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) }
-
- let!(:pending_job) do
- create(:ci_build, :pending, :queued,
- pipeline: pipeline, stage_idx: 1,
- options: { script: ["bash"], dependencies: ['test'] })
- end
-
- subject { execute(specific_runner) }
-
it_behaves_like 'validation is active'
end
@@ -739,16 +777,6 @@ module Ci
end
end
- context 'when a long queue is created' do
- it 'picks builds one-by-one' do
- expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original
-
- expect(execute(specific_runner)).to eq(pending_job)
- end
-
- include_examples 'handles runner assignment'
- end
-
context 'when using pending builds table' do
include_examples 'handles runner assignment'
diff --git a/spec/services/ci/retry_job_service_spec.rb b/spec/services/ci/retry_job_service_spec.rb
index f042471bd1f..b14e4187c7a 100644
--- a/spec/services/ci/retry_job_service_spec.rb
+++ b/spec/services/ci/retry_job_service_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Ci::RetryJobService do
name: 'test')
end
+ let(:job_variables_attributes) { [{ key: 'MANUAL_VAR', value: 'manual test var' }] }
let(:user) { developer }
let(:service) { described_class.new(project, user) }
@@ -206,6 +207,14 @@ RSpec.describe Ci::RetryJobService do
include_context 'retryable bridge'
it_behaves_like 'clones the job'
+
+ context 'when given variables' do
+ let(:new_job) { service.clone!(job, variables: job_variables_attributes) }
+
+ it 'does not give variables to the new bridge' do
+ expect { new_job }.not_to raise_error
+ end
+ end
end
context 'when the job to be cloned is a build' do
@@ -250,6 +259,28 @@ RSpec.describe Ci::RetryJobService do
expect { new_job }.not_to change { Environment.count }
end
end
+
+ context 'when given variables' do
+ let(:new_job) { service.clone!(job, variables: job_variables_attributes) }
+
+ context 'when the build is actionable' do
+ let_it_be_with_refind(:job) { create(:ci_build, :actionable, pipeline: pipeline) }
+
+ it 'gives variables to the new build' do
+ expect(new_job.job_variables.count).to be(1)
+ expect(new_job.job_variables.first.key).to eq('MANUAL_VAR')
+ expect(new_job.job_variables.first.value).to eq('manual test var')
+ end
+ end
+
+ context 'when the build is not actionable' do
+ let_it_be_with_refind(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'does not give variables to the new build' do
+ expect(new_job.job_variables.count).to be_zero
+ end
+ end
+ end
end
end
@@ -260,6 +291,14 @@ RSpec.describe Ci::RetryJobService do
include_context 'retryable bridge'
it_behaves_like 'retries the job'
+
+ context 'when given variables' do
+ let(:new_job) { service.clone!(job, variables: job_variables_attributes) }
+
+ it 'does not give variables to the new bridge' do
+ expect { new_job }.not_to raise_error
+ end
+ end
end
context 'when the job to be retried is a build' do
@@ -288,6 +327,28 @@ RSpec.describe Ci::RetryJobService do
expect { service.execute(job) }.not_to exceed_all_query_limit(control_count)
end
end
+
+ context 'when given variables' do
+ let(:new_job) { service.clone!(job, variables: job_variables_attributes) }
+
+ context 'when the build is actionable' do
+ let_it_be_with_refind(:job) { create(:ci_build, :actionable, pipeline: pipeline) }
+
+ it 'gives variables to the new build' do
+ expect(new_job.job_variables.count).to be(1)
+ expect(new_job.job_variables.first.key).to eq('MANUAL_VAR')
+ expect(new_job.job_variables.first.value).to eq('manual test var')
+ end
+ end
+
+ context 'when the build is not actionable' do
+ let_it_be_with_refind(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'does not give variables to the new build' do
+ expect(new_job.job_variables.count).to be_zero
+ end
+ end
+ end
end
end
end
diff --git a/spec/services/ci/runners/assign_runner_service_spec.rb b/spec/services/ci/runners/assign_runner_service_spec.rb
index 00b176bb759..08bb99830fb 100644
--- a/spec/services/ci/runners/assign_runner_service_spec.rb
+++ b/spec/services/ci/runners/assign_runner_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::AssignRunnerService, '#execute' do
- subject { described_class.new(runner, project, user).execute }
+ subject(:execute) { described_class.new(runner, project, user).execute }
let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
let_it_be(:project) { create(:project) }
@@ -11,30 +11,32 @@ RSpec.describe ::Ci::Runners::AssignRunnerService, '#execute' do
context 'without user' do
let(:user) { nil }
- it 'does not call assign_to on runner and returns false' do
+ it 'does not call assign_to on runner and returns error response', :aggregate_failures do
expect(runner).not_to receive(:assign_to)
- is_expected.to eq(false)
+ is_expected.to be_error
+ expect(execute.message).to eq('user not allowed to assign runner')
end
end
context 'with unauthorized user' do
let(:user) { build(:user) }
- it 'does not call assign_to on runner and returns false' do
+ it 'does not call assign_to on runner and returns error message' do
expect(runner).not_to receive(:assign_to)
- is_expected.to eq(false)
+ is_expected.to be_error
+ expect(execute.message).to eq('user not allowed to assign runner')
end
end
context 'with admin user', :enable_admin_mode do
let(:user) { create_default(:user, :admin) }
- it 'calls assign_to on runner and returns value unchanged' do
- expect(runner).to receive(:assign_to).with(project, user).once.and_return('assign_to return value')
+ it 'calls assign_to on runner and returns success response' do
+ expect(runner).to receive(:assign_to).with(project, user).once.and_call_original
- is_expected.to eq('assign_to return value')
+ is_expected.to be_success
end
end
end
diff --git a/spec/services/ci/runners/bulk_delete_runners_service_spec.rb b/spec/services/ci/runners/bulk_delete_runners_service_spec.rb
new file mode 100644
index 00000000000..8e9fc4e3012
--- /dev/null
+++ b/spec/services/ci/runners/bulk_delete_runners_service_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
+ subject(:execute) { described_class.new(**service_args).execute }
+
+ let(:service_args) { { runners: runners_arg } }
+ let(:runners_arg) {}
+
+ context 'with runners specified' do
+ let!(:instance_runner) { create(:ci_runner) }
+ let!(:group_runner) { create(:ci_runner, :group) }
+ let!(:project_runner) { create(:ci_runner, :project) }
+
+ shared_examples 'a service deleting runners in bulk' do
+ it 'destroys runners', :aggregate_failures do
+ expect { subject }.to change { Ci::Runner.count }.by(-2)
+
+ is_expected.to be_success
+ expect(execute.payload).to eq({ deleted_count: 2, deleted_ids: [instance_runner.id, project_runner.id] })
+ expect(instance_runner[:errors]).to be_nil
+ expect(project_runner[:errors]).to be_nil
+ expect { project_runner.runner_projects.first.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { group_runner.reload }.not_to raise_error
+ expect { instance_runner.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { project_runner.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ context 'with some runners already deleted' do
+ before do
+ instance_runner.destroy!
+ end
+
+ let(:runners_arg) { [instance_runner.id, project_runner.id] }
+
+ it 'destroys runners and returns only deleted runners', :aggregate_failures do
+ expect { subject }.to change { Ci::Runner.count }.by(-1)
+
+ is_expected.to be_success
+ expect(execute.payload).to eq({ deleted_count: 1, deleted_ids: [project_runner.id] })
+ expect(instance_runner[:errors]).to be_nil
+ expect(project_runner[:errors]).to be_nil
+ expect { project_runner.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'with too many runners specified' do
+ before do
+ stub_const("#{described_class}::RUNNER_LIMIT", 1)
+ end
+
+ it 'deletes only first RUNNER_LIMIT runners' do
+ expect { subject }.to change { Ci::Runner.count }.by(-1)
+
+ is_expected.to be_success
+ expect(execute.payload).to eq({ deleted_count: 1, deleted_ids: [instance_runner.id] })
+ end
+ end
+ end
+
+ context 'with runners specified as relation' do
+ let(:runners_arg) { Ci::Runner.not_group_type }
+
+ include_examples 'a service deleting runners in bulk'
+ end
+
+ context 'with runners specified as array of IDs' do
+ let(:runners_arg) { Ci::Runner.not_group_type.ids }
+
+ include_examples 'a service deleting runners in bulk'
+ end
+
+ context 'with no arguments specified' do
+ let(:runners_arg) { nil }
+
+ it 'returns 0 deleted runners' do
+ is_expected.to be_success
+ expect(execute.payload).to eq({ deleted_count: 0, deleted_ids: [] })
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/runners/process_runner_version_update_service_spec.rb b/spec/services/ci/runners/process_runner_version_update_service_spec.rb
new file mode 100644
index 00000000000..b885138fc7a
--- /dev/null
+++ b/spec/services/ci/runners/process_runner_version_update_service_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Runners::ProcessRunnerVersionUpdateService do
+ subject(:service) { described_class.new(version) }
+
+ let(:version) { '1.0.0' }
+ let(:available_runner_releases) { %w[1.0.0 1.0.1] }
+
+ describe '#execute' do
+ subject(:execute) { service.execute }
+
+ context 'with upgrade check returning error' do
+ let(:service_double) { instance_double(Gitlab::Ci::RunnerUpgradeCheck) }
+
+ before do
+ allow(service_double).to receive(:check_runner_upgrade_suggestion).with(version)
+ .and_return([version, :error])
+ allow(service).to receive(:upgrade_check_service).and_return(service_double)
+ end
+
+ it 'does not update ci_runner_versions records', :aggregate_failures do
+ expect do
+ expect(execute).to be_error
+ expect(execute.message).to eq 'upgrade version check failed'
+ end.not_to change(Ci::RunnerVersion, :count).from(0)
+ expect(service_double).to have_received(:check_runner_upgrade_suggestion).with(version).once
+ end
+ end
+
+ context 'with successful result from upgrade check' do
+ before do
+ url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+
+ WebMock.stub_request(:get, url).to_return(
+ body: available_runner_releases.map { |v| { name: v } }.to_json,
+ status: 200,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+ end
+
+ context 'with no existing ci_runner_version record' do
+ it 'creates ci_runner_versions record', :aggregate_failures do
+ expect do
+ expect(execute).to be_success
+ expect(execute.http_status).to eq :ok
+ expect(execute.payload).to eq({ upgrade_status: 'recommended' })
+ end.to change(Ci::RunnerVersion, :all).to contain_exactly(
+ an_object_having_attributes(version: version, status: 'recommended')
+ )
+ end
+ end
+
+ context 'with existing ci_runner_version record' do
+ let!(:runner_version) { create(:ci_runner_version, version: '1.0.0', status: :not_available) }
+
+ it 'updates ci_runner_versions record', :aggregate_failures do
+ expect do
+ expect(execute).to be_success
+ expect(execute.http_status).to eq :ok
+ expect(execute.payload).to eq({ upgrade_status: 'recommended' })
+ end.to change { runner_version.reload.status }.from('not_available').to('recommended')
+ end
+ end
+
+ context 'with up-to-date ci_runner_version record' do
+ let!(:runner_version) { create(:ci_runner_version, version: '1.0.0', status: :recommended) }
+
+ it 'does not update ci_runner_versions record', :aggregate_failures do
+ expect do
+ expect(execute).to be_success
+ expect(execute.http_status).to eq :ok
+ expect(execute.payload).to eq({ upgrade_status: 'recommended' })
+ end.not_to change { runner_version.reload.status }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb b/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
index f8313eaab90..1690190320a 100644
--- a/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
+++ b/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute' do
+ include RunnerReleasesHelper
+
subject(:execute) { described_class.new.execute }
let_it_be(:runner_14_0_1) { create(:ci_runner, version: '14.0.1') }
@@ -11,12 +13,12 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
end
context 'with RunnerUpgradeCheck recommending 14.0.2' do
+ let(:upgrade_check) { instance_double(::Gitlab::Ci::RunnerUpgradeCheck) }
+
before do
stub_const('Ci::Runners::ReconcileExistingRunnerVersionsService::VERSION_BATCH_SIZE', 1)
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
- .and_return({ recommended: ::Gitlab::VersionInfo.new(14, 0, 2) })
+ allow(::Gitlab::Ci::RunnerUpgradeCheck).to receive(:new).and_return(upgrade_check).once
end
context 'with runner with new version' do
@@ -25,10 +27,11 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
let!(:runner_14_0_0) { create(:ci_runner, version: '14.0.0') }
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 2), :recommended])
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
.with('14.0.2')
- .and_return({ not_available: ::Gitlab::VersionInfo.new(14, 0, 2) })
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 2), :not_available])
.once
end
@@ -39,14 +42,13 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
.once
.and_call_original
- result = nil
- expect { result = execute }
+ expect { execute }
.to change { runner_version_14_0_0.reload.status }.from('not_available').to('recommended')
.and change { runner_version_14_0_1.reload.status }.from('not_available').to('recommended')
.and change { ::Ci::RunnerVersion.find_by(version: '14.0.2')&.status }.from(nil).to('not_available')
- expect(result).to eq({
- status: :success,
+ expect(execute).to be_success
+ expect(execute.payload).to eq({
total_inserted: 1, # 14.0.2 is inserted
total_updated: 3, # 14.0.0, 14.0.1 are updated, and newly inserted 14.0.2's status is calculated
total_deleted: 0
@@ -58,19 +60,17 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
let!(:runner_version_14_0_2) { create(:ci_runner_version, version: '14.0.2', status: :not_available) }
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
- .and_return({ not_available: ::Gitlab::VersionInfo.new(14, 0, 2) })
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 2), :not_available])
end
it 'deletes orphan ci_runner_versions entry', :aggregate_failures do
- result = nil
- expect { result = execute }
+ expect { execute }
.to change { ::Ci::RunnerVersion.find_by_version('14.0.2')&.status }.from('not_available').to(nil)
.and not_change { runner_version_14_0_1.reload.status }.from('not_available')
- expect(result).to eq({
- status: :success,
+ expect(execute).to be_success
+ expect(execute.payload).to eq({
total_inserted: 0,
total_updated: 0,
total_deleted: 1 # 14.0.2 is deleted
@@ -80,17 +80,15 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
context 'with no runner version changes' do
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
- .and_return({ not_available: ::Gitlab::VersionInfo.new(14, 0, 1) })
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 1), :not_available])
end
it 'does not modify ci_runner_versions entries', :aggregate_failures do
- result = nil
- expect { result = execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
+ expect { execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
- expect(result).to eq({
- status: :success,
+ expect(execute).to be_success
+ expect(execute.payload).to eq({
total_inserted: 0,
total_updated: 0,
total_deleted: 0
@@ -100,17 +98,15 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
context 'with failing version check' do
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_status)
- .and_return({ error: ::Gitlab::VersionInfo.new(14, 0, 1) })
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 1), :error])
end
it 'makes no changes to ci_runner_versions', :aggregate_failures do
- result = nil
- expect { result = execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
+ expect { execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
- expect(result).to eq({
- status: :success,
+ expect(execute).to be_success
+ expect(execute.payload).to eq({
total_inserted: 0,
total_updated: 0,
total_deleted: 0
@@ -120,26 +116,15 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
end
context 'integration testing with Gitlab::Ci::RunnerUpgradeCheck' do
- let(:available_runner_releases) do
- %w[14.0.0 14.0.1]
- end
-
before do
- url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
-
- WebMock.stub_request(:get, url).to_return(
- body: available_runner_releases.map { |v| { name: v } }.to_json,
- status: 200,
- headers: { 'Content-Type' => 'application/json' }
- )
+ stub_runner_releases(%w[14.0.0 14.0.1])
end
it 'does not modify ci_runner_versions entries', :aggregate_failures do
- result = nil
- expect { result = execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
+ expect { execute }.not_to change { runner_version_14_0_1.reload.status }.from('not_available')
- expect(result).to eq({
- status: :success,
+ expect(execute).to be_success
+ expect(execute.payload).to eq({
total_inserted: 0,
total_updated: 0,
total_deleted: 0
diff --git a/spec/services/ci/runners/register_runner_service_spec.rb b/spec/services/ci/runners/register_runner_service_spec.rb
index 03dcf851e53..6d7b39de21e 100644
--- a/spec/services/ci/runners/register_runner_service_spec.rb
+++ b/spec/services/ci/runners/register_runner_service_spec.rb
@@ -4,8 +4,9 @@ require 'spec_helper'
RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:registration_token) { 'abcdefg123456' }
- let(:token) { }
+ let(:token) {}
let(:args) { {} }
+ let(:runner) { execute.payload[:runner] }
before do
stub_feature_flags(runner_registration_control: false)
@@ -13,21 +14,25 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
stub_application_setting(valid_runner_registrars: ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES)
end
- subject(:runner) { described_class.new.execute(token, args) }
+ subject(:execute) { described_class.new.execute(token, args) }
context 'when no token is provided' do
let(:token) { '' }
- it 'returns nil' do
- is_expected.to be_nil
+ it 'returns error response' do
+ expect(execute).to be_error
+ expect(execute.message).to eq 'invalid token supplied'
+ expect(execute.http_status).to eq :forbidden
end
end
context 'when invalid token is provided' do
let(:token) { 'invalid' }
- it 'returns nil' do
- is_expected.to be_nil
+ it 'returns error response' do
+ expect(execute).to be_error
+ expect(execute.message).to eq 'invalid token supplied'
+ expect(execute.http_status).to eq :forbidden
end
end
@@ -36,12 +41,14 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:token) { registration_token }
it 'creates runner with default values' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_truthy
- expect(subject.run_untagged).to be true
- expect(subject.active).to be true
- expect(subject.token).not_to eq(registration_token)
- expect(subject).to be_instance_type
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.persisted?).to be_truthy
+ expect(runner.run_untagged).to be true
+ expect(runner.active).to be true
+ expect(runner.token).not_to eq(registration_token)
+ expect(runner).to be_instance_type
end
context 'with non-default arguments' do
@@ -67,25 +74,27 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'creates runner with specified values', :aggregate_failures do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.active).to eq args[:active]
- expect(subject.locked).to eq args[:locked]
- expect(subject.run_untagged).to eq args[:run_untagged]
- expect(subject.tags).to contain_exactly(
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.active).to eq args[:active]
+ expect(runner.locked).to eq args[:locked]
+ expect(runner.run_untagged).to eq args[:run_untagged]
+ expect(runner.tags).to contain_exactly(
an_object_having_attributes(name: 'tag1'),
an_object_having_attributes(name: 'tag2')
)
- expect(subject.access_level).to eq args[:access_level]
- expect(subject.maximum_timeout).to eq args[:maximum_timeout]
- expect(subject.name).to eq args[:name]
- expect(subject.version).to eq args[:version]
- expect(subject.revision).to eq args[:revision]
- expect(subject.platform).to eq args[:platform]
- expect(subject.architecture).to eq args[:architecture]
- expect(subject.ip_address).to eq args[:ip_address]
-
- expect(Ci::Runner.tagged_with('tag1')).to include(subject)
- expect(Ci::Runner.tagged_with('tag2')).to include(subject)
+ expect(runner.access_level).to eq args[:access_level]
+ expect(runner.maximum_timeout).to eq args[:maximum_timeout]
+ expect(runner.name).to eq args[:name]
+ expect(runner.version).to eq args[:version]
+ expect(runner.revision).to eq args[:revision]
+ expect(runner.platform).to eq args[:platform]
+ expect(runner.architecture).to eq args[:architecture]
+ expect(runner.ip_address).to eq args[:ip_address]
+
+ expect(Ci::Runner.tagged_with('tag1')).to include(runner)
+ expect(Ci::Runner.tagged_with('tag2')).to include(runner)
end
end
@@ -95,8 +104,10 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'creates runner with token expiration' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.token_expires_at).to eq(5.days.from_now)
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.token_expires_at).to eq(5.days.from_now)
end
end
end
@@ -106,12 +117,14 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:token) { project.runners_token }
it 'creates project runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
expect(project.runners.size).to eq(1)
- is_expected.to eq(project.runners.first)
- expect(subject.token).not_to eq(registration_token)
- expect(subject.token).not_to eq(project.runners_token)
- expect(subject).to be_project_type
+ expect(runner).to eq(project.runners.first)
+ expect(runner.token).not_to eq(registration_token)
+ expect(runner.token).not_to eq(project.runners_token)
+ expect(runner).to be_project_type
end
context 'when it exceeds the application limits' do
@@ -121,9 +134,13 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'does not create runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_falsey
- expect(subject.errors.messages).to eq('runner_projects.base': ['Maximum number of ci registered project runners (1) exceeded'])
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.persisted?).to be_falsey
+ expect(runner.errors.messages).to eq(
+ 'runner_projects.base': ['Maximum number of ci registered project runners (1) exceeded']
+ )
expect(project.runners.reload.size).to eq(1)
end
end
@@ -135,8 +152,10 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'creates runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.errors).to be_empty
expect(project.runners.reload.size).to eq(2)
expect(project.runners.recent.size).to eq(1)
end
@@ -153,15 +172,18 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'returns 403 error' do
- is_expected.to be_nil
+ 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
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(subject.active).to be true
+ 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
end
end
@@ -172,12 +194,14 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
let(:token) { group.runners_token }
it 'creates a group runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.errors).to be_empty
expect(group.runners.reload.size).to eq(1)
- expect(subject.token).not_to eq(registration_token)
- expect(subject.token).not_to eq(group.runners_token)
- expect(subject).to be_group_type
+ expect(runner.token).not_to eq(registration_token)
+ expect(runner.token).not_to eq(group.runners_token)
+ expect(runner).to be_group_type
end
context 'when it exceeds the application limits' do
@@ -187,9 +211,13 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'does not create runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.persisted?).to be_falsey
- expect(subject.errors.messages).to eq('runner_namespaces.base': ['Maximum number of ci registered group runners (1) exceeded'])
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.persisted?).to be_falsey
+ expect(runner.errors.messages).to eq(
+ 'runner_namespaces.base': ['Maximum number of ci registered group runners (1) exceeded']
+ )
expect(group.runners.reload.size).to eq(1)
end
end
@@ -202,8 +230,10 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
end
it 'creates runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
+ expect(execute).to be_success
+
+ expect(runner).to be_an_instance_of(::Ci::Runner)
+ expect(runner.errors).to be_empty
expect(group.runners.reload.size).to eq(3)
expect(group.runners.recent.size).to eq(1)
end
@@ -219,16 +249,18 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute' do
stub_feature_flags(runner_registration_control: true)
end
- it 'returns nil' do
- is_expected.to be_nil
+ it 'returns error response' do
+ is_expected.to be_error
end
end
context 'when feature flag is disabled' do
it 'registers the runner' do
- is_expected.to be_an_instance_of(::Ci::Runner)
- expect(subject.errors).to be_empty
- expect(subject.active).to be true
+ 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
end
end
diff --git a/spec/services/ci/runners/reset_registration_token_service_spec.rb b/spec/services/ci/runners/reset_registration_token_service_spec.rb
index c4bfff51cc8..79059712032 100644
--- a/spec/services/ci/runners/reset_registration_token_service_spec.rb
+++ b/spec/services/ci/runners/reset_registration_token_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::ResetRegistrationTokenService, '#execute' do
- subject { described_class.new(scope, current_user).execute }
+ subject(:execute) { described_class.new(scope, current_user).execute }
let_it_be(:user) { build(:user) }
let_it_be(:admin_user) { create(:user, :admin) }
@@ -12,20 +12,20 @@ RSpec.describe ::Ci::Runners::ResetRegistrationTokenService, '#execute' do
context 'without user' do
let(:current_user) { nil }
- it 'does not reset registration token and returns nil' do
+ it 'does not reset registration token and returns error response' do
expect(scope).not_to receive(token_reset_method_name)
- is_expected.to be_nil
+ expect(execute).to be_error
end
end
context 'with unauthorized user' do
let(:current_user) { user }
- it 'does not reset registration token and returns nil' do
+ it 'does not reset registration token and returns error response' do
expect(scope).not_to receive(token_reset_method_name)
- is_expected.to be_nil
+ expect(execute).to be_error
end
end
@@ -37,7 +37,8 @@ RSpec.describe ::Ci::Runners::ResetRegistrationTokenService, '#execute' do
expect(scope).to receive(token_method_name).once.and_return("#{token_method_name} return value")
end
- is_expected.to eq("#{token_method_name} return value")
+ expect(execute).to be_success
+ expect(execute.payload[:new_registration_token]).to eq("#{token_method_name} return value")
end
end
end
diff --git a/spec/services/ci/runners/unassign_runner_service_spec.rb b/spec/services/ci/runners/unassign_runner_service_spec.rb
index 3fb6925f4bd..cf710cf6893 100644
--- a/spec/services/ci/runners/unassign_runner_service_spec.rb
+++ b/spec/services/ci/runners/unassign_runner_service_spec.rb
@@ -3,21 +3,21 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::UnassignRunnerService, '#execute' do
- subject(:service) { described_class.new(runner_project, user).execute }
-
- let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
let_it_be(:project) { create(:project) }
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:runner_project) { runner.runner_projects.last }
+ subject(:execute) { described_class.new(runner_project, user).execute }
+
context 'without user' do
let(:user) { nil }
it 'does not destroy runner_project', :aggregate_failures do
expect(runner_project).not_to receive(:destroy)
- expect { service }.not_to change { runner.runner_projects.count }.from(1)
+ expect { execute }.not_to change { runner.runner_projects.count }.from(1)
- is_expected.to eq(false)
+ is_expected.to be_error
end
end
@@ -27,17 +27,27 @@ RSpec.describe ::Ci::Runners::UnassignRunnerService, '#execute' do
it 'does not call destroy on runner_project' do
expect(runner).not_to receive(:destroy)
- service
+ is_expected.to be_error
end
end
context 'with admin user', :enable_admin_mode do
let(:user) { create_default(:user, :admin) }
- it 'destroys runner_project' do
- expect(runner_project).to receive(:destroy).once
+ context 'with destroy returning false' do
+ it 'returns error response' do
+ expect(runner_project).to receive(:destroy).once.and_return(false)
+
+ is_expected.to be_error
+ end
+ end
+
+ context 'with destroy returning true' do
+ it 'returns success response' do
+ expect(runner_project).to receive(:destroy).once.and_return(true)
- service
+ is_expected.to be_success
+ end
end
end
end
diff --git a/spec/services/ci/runners/unregister_runner_service_spec.rb b/spec/services/ci/runners/unregister_runner_service_spec.rb
index df1a0a90067..77fc299e4e1 100644
--- a/spec/services/ci/runners/unregister_runner_service_spec.rb
+++ b/spec/services/ci/runners/unregister_runner_service_spec.rb
@@ -3,13 +3,16 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::UnregisterRunnerService, '#execute' do
- subject { described_class.new(runner, 'some_token').execute }
+ subject(:execute) { described_class.new(runner, 'some_token').execute }
let(:runner) { create(:ci_runner) }
it 'destroys runner' do
expect(runner).to receive(:destroy).once.and_call_original
- expect { subject }.to change { Ci::Runner.count }.by(-1)
+
+ expect do
+ expect(execute).to be_success
+ end.to change { Ci::Runner.count }.by(-1)
expect(runner[:errors]).to be_nil
end
end
diff --git a/spec/services/ci/runners/update_runner_service_spec.rb b/spec/services/ci/runners/update_runner_service_spec.rb
index b02ea8f58b0..e008fde9982 100644
--- a/spec/services/ci/runners/update_runner_service_spec.rb
+++ b/spec/services/ci/runners/update_runner_service_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Ci::Runners::UpdateRunnerService do
end
context 'with cost factor params' do
- let(:params) { { public_projects_minutes_cost_factor: 1.1, private_projects_minutes_cost_factor: 2.2 }}
+ let(:params) { { public_projects_minutes_cost_factor: 1.1, private_projects_minutes_cost_factor: 2.2 } }
it 'updates the runner cost factors' do
expect(update).to be_truthy
diff --git a/spec/services/ci/stuck_builds/drop_pending_service_spec.rb b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
index ebc57af77a0..a452a65829a 100644
--- a/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
+++ b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
create(:ci_build, pipeline: pipeline, runner: runner)
end
- let(:created_at) { }
- let(:updated_at) { }
+ let(:created_at) {}
+ let(:updated_at) {}
subject(:service) { described_class.new }
diff --git a/spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb b/spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb
index 1416fab3d25..a4f9f97fffc 100644
--- a/spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb
+++ b/spec/services/ci/stuck_builds/drop_scheduled_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Ci::StuckBuilds::DropScheduledService do
end
context 'when there are no stale scheduled builds' do
- let(:job) { }
+ let(:job) {}
it 'does not drop the stale scheduled build yet' do
expect { service.execute }.not_to raise_error
diff --git a/spec/services/ci/track_failed_build_service_spec.rb b/spec/services/ci/track_failed_build_service_spec.rb
new file mode 100644
index 00000000000..d83e56f0669
--- /dev/null
+++ b/spec/services/ci/track_failed_build_service_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::TrackFailedBuildService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+
+ let_it_be(:exit_code) { 42 }
+ let_it_be(:failure_reason) { "script_failure" }
+
+ describe '#execute' do
+ context 'when a build has failed' do
+ let_it_be(:build) { create(:ci_build, :failed, :sast_report, pipeline: pipeline, user: user) }
+
+ subject { described_class.new(build: build, exit_code: exit_code, failure_reason: failure_reason) }
+
+ it 'tracks the build failed event', :snowplow do
+ response = subject.execute
+
+ expect(response.success?).to be true
+
+ expect_snowplow_event(
+ category: 'ci::build',
+ action: 'failed',
+ context: [{
+ schema: described_class::SCHEMA_URL,
+ data: {
+ build_id: build.id,
+ build_name: build.name,
+ build_artifact_types: ["sast"],
+ exit_code: exit_code,
+ failure_reason: failure_reason
+ }
+ }],
+ user: user,
+ project: project.id)
+ end
+ end
+
+ context 'when a build has not failed' do
+ let_it_be(:build) { create(:ci_build, :success, :sast_report, pipeline: pipeline, user: user) }
+
+ subject { described_class.new(build: build, exit_code: nil, failure_reason: nil) }
+
+ it 'does not track the build failed event', :snowplow do
+ response = subject.execute
+
+ expect(response.error?).to be true
+
+ expect_no_snowplow_event
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
index 937b19beff5..90a86e7ae59 100644
--- a/spec/services/ci/update_build_state_service_spec.rb
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -33,6 +33,24 @@ RSpec.describe Ci::UpdateBuildStateService do
end
end
+ context 'when build has failed' do
+ let(:params) do
+ {
+ output: { checksum: 'crc32:12345678', bytesize: 123 },
+ state: 'failed',
+ failure_reason: 'script_failure',
+ exit_code: 7
+ }
+ end
+
+ it 'sends a build failed event to Snowplow' do
+ expect(::Ci::TrackFailedBuildWorker)
+ .to receive(:perform_async).with(build.id, params[:exit_code], params[:failure_reason])
+
+ subject.execute
+ end
+ end
+
context 'when build does not have checksum' do
context 'when state has changed' do
let(:params) { { state: 'success' } }
diff --git a/spec/services/clusters/integrations/create_service_spec.rb b/spec/services/clusters/integrations/create_service_spec.rb
index 016511a3c01..9104e07504d 100644
--- a/spec/services/clusters/integrations/create_service_spec.rb
+++ b/spec/services/clusters/integrations/create_service_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe Clusters::Integrations::CreateService, '#execute' do
end
it 'errors' do
- expect { service.execute}.to raise_error(ArgumentError)
+ expect { service.execute }.to raise_error(ArgumentError)
end
end
diff --git a/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
index 7147f1b9b28..526462931a6 100644
--- a/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
+++ b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
@@ -51,6 +51,7 @@ RSpec.describe Clusters::Integrations::PrometheusHealthCheckService, '#execute'
let(:prometheus_enabled) { false }
it { expect(subject).to eq(nil) }
+
include_examples 'no alert'
end
diff --git a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
index a4f018aec0c..064f9e42e96 100644
--- a/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
+++ b/spec/services/clusters/kubernetes/create_or_update_service_account_service_spec.rb
@@ -136,7 +136,7 @@ RSpec.describe Clusters::Kubernetes::CreateOrUpdateServiceAccountService do
context 'With RBAC enabled cluster' do
let(:rbac) { true }
- let(:role_binding_name) { "gitlab-#{namespace}"}
+ let(:role_binding_name) { "gitlab-#{namespace}" }
before do
cluster.platform_kubernetes.rbac!
diff --git a/spec/services/database/consistency_check_service_spec.rb b/spec/services/database/consistency_check_service_spec.rb
index 2e642451432..6695e4b5e9f 100644
--- a/spec/services/database/consistency_check_service_spec.rb
+++ b/spec/services/database/consistency_check_service_spec.rb
@@ -24,9 +24,27 @@ RSpec.describe Database::ConsistencyCheckService do
)
end
- describe '#random_start_id' do
- let(:batch_size) { 5 }
+ describe '#min_id' do
+ before do
+ create_list(:namespace, 3)
+ end
+ it 'returns the id of the first record in the database' do
+ expect(subject.send(:min_id)).to eq(Namespace.first.id)
+ end
+ end
+
+ describe '#max_id' do
+ before do
+ create_list(:namespace, 3)
+ end
+
+ it 'returns the id of the first record in the database' do
+ expect(subject.send(:max_id)).to eq(Namespace.last.id)
+ end
+ end
+
+ describe '#random_start_id' do
before do
create_list(:namespace, 50) # This will also create Ci::NameSpaceMirror objects
end
@@ -58,12 +76,11 @@ RSpec.describe Database::ConsistencyCheckService do
end
context 'no cursor has been saved before' do
- let(:selected_start_id) { Namespace.order(:id).limit(5).pluck(:id).last }
- let(:expected_next_start_id) { selected_start_id + batch_size * max_batches }
+ let(:min_id) { Namespace.first.id }
+ let(:max_id) { Namespace.last.id }
before do
create_list(:namespace, 50) # This will also create Ci::NameSpaceMirror objects
- expect(consistency_check_service).to receive(:random_start_id).and_return(selected_start_id)
end
it 'picks a random start_id' do
@@ -72,17 +89,21 @@ RSpec.describe Database::ConsistencyCheckService do
matches: 10,
mismatches: 0,
mismatches_details: [],
- start_id: selected_start_id,
- next_start_id: expected_next_start_id
+ start_id: be_between(min_id, max_id),
+ next_start_id: be_between(min_id, max_id)
}
- expect(consistency_check_service.execute).to eq(expected_result)
+ expect(consistency_check_service).to receive(:rand).with(min_id..max_id).and_call_original
+ result = consistency_check_service.execute
+ expect(result).to match(expected_result)
end
it 'calls the ConsistencyCheckService with the expected parameters' do
+ expect(consistency_check_service).to receive(:random_start_id).and_return(min_id)
+
allow_next_instance_of(Gitlab::Database::ConsistencyChecker) do |instance|
- expect(instance).to receive(:execute).with(start_id: selected_start_id).and_return({
+ expect(instance).to receive(:execute).with(start_id: min_id).and_return({
batches: 2,
- next_start_id: expected_next_start_id,
+ next_start_id: min_id + batch_size,
matches: 10,
mismatches: 0,
mismatches_details: []
@@ -98,17 +119,19 @@ RSpec.describe Database::ConsistencyCheckService do
expected_result = {
batches: 2,
- start_id: selected_start_id,
- next_start_id: expected_next_start_id,
matches: 10,
mismatches: 0,
- mismatches_details: []
+ mismatches_details: [],
+ start_id: be_between(min_id, max_id),
+ next_start_id: be_between(min_id, max_id)
}
- expect(consistency_check_service.execute).to eq(expected_result)
+ result = consistency_check_service.execute
+ expect(result).to match(expected_result)
end
it 'saves the next_start_id in Redis for he next iteration' do
- expect(consistency_check_service).to receive(:save_next_start_id).with(expected_next_start_id).and_call_original
+ expect(consistency_check_service).to receive(:save_next_start_id)
+ .with(be_between(min_id, max_id)).and_call_original
consistency_check_service.execute
end
end
diff --git a/spec/services/deployments/create_for_build_service_spec.rb b/spec/services/deployments/create_for_build_service_spec.rb
index 38d94580512..a2e1acadcc1 100644
--- a/spec/services/deployments/create_for_build_service_spec.rb
+++ b/spec/services/deployments/create_for_build_service_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Deployments::CreateForBuildService do
end
context 'when the corresponding environment does not exist' do
- let!(:environment) { }
+ let!(:environment) {}
it 'does not create a deployment record' do
expect { subject }.not_to change { Deployment.count }
diff --git a/spec/services/deployments/update_environment_service_spec.rb b/spec/services/deployments/update_environment_service_spec.rb
index 8ab53a37a33..4485ce585bb 100644
--- a/spec/services/deployments/update_environment_service_spec.rb
+++ b/spec/services/deployments/update_environment_service_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Deployments::UpdateEnvironmentService do
end
context 'when external URL is invalid' do
- let(:external_url) { 'google.com' }
+ let(:external_url) { 'javascript:alert("hello")' }
it 'fails to update the tier due to validation error' do
expect { subject.execute }.not_to change { environment.tier }
@@ -123,7 +123,7 @@ RSpec.describe Deployments::UpdateEnvironmentService do
.with(an_instance_of(described_class::EnvironmentUpdateFailure),
project_id: project.id,
environment_id: environment.id,
- reason: %q{External url is blocked: Only allowed schemes are http, https})
+ reason: %q{External url javascript scheme is not allowed})
.once
subject.execute
@@ -307,14 +307,6 @@ RSpec.describe Deployments::UpdateEnvironmentService do
end
it { is_expected.to eq('http://appname-master.example.com') }
-
- context 'when the FF ci_expand_environment_name_and_url is disabled' do
- before do
- stub_feature_flags(ci_expand_environment_name_and_url: false)
- end
-
- it { is_expected.to eq('http://${STACK_NAME}.example.com') }
- end
end
context 'when yaml environment does not have url' do
diff --git a/spec/services/design_management/delete_designs_service_spec.rb b/spec/services/design_management/delete_designs_service_spec.rb
index bc7625d7c28..a0e049ea42a 100644
--- a/spec/services/design_management/delete_designs_service_spec.rb
+++ b/spec/services/design_management/delete_designs_service_spec.rb
@@ -59,7 +59,11 @@ RSpec.describe DesignManagement::DeleteDesignsService do
it_behaves_like "a service error"
it 'does not create any events in the activity stream' do
- expect { run_service rescue nil }.not_to change { Event.count }
+ expect do
+ run_service
+ rescue StandardError
+ nil
+ end.not_to change { Event.count }
end
end
@@ -78,7 +82,11 @@ RSpec.describe DesignManagement::DeleteDesignsService do
it 'does not log any events' do
counter = ::Gitlab::UsageDataCounters::DesignsCounter
- expect { run_service rescue nil }
+ expect do
+ run_service
+ rescue StandardError
+ nil
+ end
.not_to change { [counter.totals, Event.count] }
end
@@ -86,10 +94,18 @@ RSpec.describe DesignManagement::DeleteDesignsService do
redis_hll = ::Gitlab::UsageDataCounters::HLLRedisCounter
event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_DESIGNS_REMOVED
- expect { run_service rescue nil }
+ expect do
+ run_service
+ rescue StandardError
+ nil
+ end
.not_to change { redis_hll.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }
- run_service rescue nil
+ begin
+ run_service
+ rescue StandardError
+ nil
+ end
end
end
diff --git a/spec/services/design_management/generate_image_versions_service_spec.rb b/spec/services/design_management/generate_image_versions_service_spec.rb
index e06b6fbf116..5409ec12016 100644
--- a/spec/services/design_management/generate_image_versions_service_spec.rb
+++ b/spec/services/design_management/generate_image_versions_service_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe DesignManagement::GenerateImageVersionsService do
end
it 'skips generating image versions if the mime type is not whitelisted' do
- stub_const('DesignManagement::DesignV432x230Uploader::MIME_TYPE_WHITELIST', [])
+ stub_const('DesignManagement::DesignV432x230Uploader::MIME_TYPE_ALLOWLIST', [])
described_class.new(version).execute
diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb
index 8d41b20c8a9..6280f1263c3 100644
--- a/spec/services/git/branch_push_service_spec.rb
+++ b/spec/services/git/branch_push_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Git::BranchPushService, services: true do
include RepoHelpers
let_it_be(:user) { create(:user) }
- let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be_with_refind(:project) { create(:project, :repository) }
let(:blankrev) { Gitlab::Git::BLANK_SHA }
let(:oldrev) { sample_commit.parent_id }
@@ -573,7 +573,7 @@ RSpec.describe Git::BranchPushService, services: true do
before do
allow(project).to receive(:default_branch).and_return('feature')
- expect(project).to receive(:change_head) { 'feature'}
+ expect(project).to receive(:change_head) { 'feature' }
end
it 'push to first branch updates HEAD' do
diff --git a/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb b/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb
new file mode 100644
index 00000000000..cd0dd75e576
--- /dev/null
+++ b/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::CreateCloudsqlInstanceService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:gcp_project_id) { 'gcp_project_120' }
+ let(:environment_name) { 'test_env_42' }
+ let(:database_version) { 'POSTGRES_8000' }
+ let(:tier) { 'REIT_TIER' }
+ let(:service) do
+ described_class.new(project, user, {
+ gcp_project_id: gcp_project_id,
+ environment_name: environment_name,
+ database_version: database_version,
+ tier: tier
+ })
+ end
+
+ describe '#execute' do
+ before do
+ allow_next_instance_of(::Ci::VariablesFinder) do |variable_finder|
+ allow(variable_finder).to receive(:execute).and_return([])
+ end
+ end
+
+ it 'triggers creation of a cloudsql instance' do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ expected_instance_name = "gitlab-#{project.id}-postgres-8000-test-env-42"
+ expect(client).to receive(:create_cloudsql_instance)
+ .with(gcp_project_id,
+ expected_instance_name,
+ String,
+ database_version,
+ 'us-east1',
+ tier)
+ end
+
+ result = service.execute
+ expect(result[:status]).to be(:success)
+ end
+
+ it 'triggers worker to manage cloudsql instance creation operation results' do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ expect(client).to receive(:create_cloudsql_instance)
+ end
+
+ expect(GoogleCloud::CreateCloudsqlInstanceWorker).to receive(:perform_in)
+
+ result = service.execute
+ expect(result[:status]).to be(:success)
+ end
+
+ context 'when google APIs fail' do
+ it 'returns error' do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ expect(client).to receive(:create_cloudsql_instance).and_raise(Google::Apis::Error.new('mock-error'))
+ end
+
+ result = service.execute
+ expect(result[:status]).to eq(:error)
+ end
+ end
+
+ context 'when project has GCP_REGION defined' do
+ let(:gcp_region) { instance_double(::Ci::Variable, key: 'GCP_REGION', value: 'user-defined-region') }
+
+ before do
+ allow_next_instance_of(::Ci::VariablesFinder) do |variable_finder|
+ allow(variable_finder).to receive(:execute).and_return([gcp_region])
+ end
+ end
+
+ it 'uses defined region' do
+ expect_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ expect(client).to receive(:create_cloudsql_instance)
+ .with(gcp_project_id,
+ String,
+ String,
+ database_version,
+ 'user-defined-region',
+ tier)
+ end
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/google_cloud/enable_cloudsql_service_spec.rb b/spec/services/google_cloud/enable_cloudsql_service_spec.rb
new file mode 100644
index 00000000000..e54e5a8d446
--- /dev/null
+++ b/spec/services/google_cloud/enable_cloudsql_service_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::EnableCloudsqlService do
+ let_it_be(:project) { create(:project) }
+
+ subject(:result) { described_class.new(project).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.'
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq(message)
+ end
+ end
+
+ context 'when a project has GCP_PROJECT_IDs configured' do
+ before do
+ project.variables.build(environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj-prod')
+ project.variables.build(environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj-staging')
+ project.save!
+ end
+
+ 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('prj-prod')
+ expect(instance).to receive(:enable_compute).with('prj-prod')
+ expect(instance).to receive(:enable_service_networking).with('prj-prod')
+ expect(instance).to receive(:enable_cloud_sql_admin).with('prj-staging')
+ expect(instance).to receive(:enable_compute).with('prj-staging')
+ expect(instance).to receive(:enable_service_networking).with('prj-staging')
+ end
+
+ expect(result[:status]).to eq(:success)
+ end
+ end
+end
diff --git a/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb b/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb
new file mode 100644
index 00000000000..4587a5077c0
--- /dev/null
+++ b/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GoogleCloud::GetCloudsqlInstancesService do
+ let(:service) { described_class.new(project) }
+ let(:project) { create(:project) }
+
+ context 'when project has no registered cloud sql instances' do
+ it 'result is empty' do
+ expect(service.execute.length).to eq(0)
+ end
+ end
+
+ context 'when project has registered cloud sql instance' do
+ before do
+ keys = %w[
+ GCP_PROJECT_ID
+ GCP_CLOUDSQL_INSTANCE_NAME
+ GCP_CLOUDSQL_CONNECTION_NAME
+ GCP_CLOUDSQL_PRIMARY_IP_ADDRESS
+ GCP_CLOUDSQL_VERSION
+ GCP_CLOUDSQL_DATABASE_NAME
+ GCP_CLOUDSQL_DATABASE_USER
+ GCP_CLOUDSQL_DATABASE_PASS
+ ]
+
+ envs = %w[
+ *
+ STG
+ PRD
+ ]
+
+ keys.each do |key|
+ envs.each do |env|
+ project.variables.build(protected: false, environment_scope: env, key: key, value: "value-#{key}-#{env}")
+ end
+ end
+ end
+
+ it 'result is grouped by environment', :aggregate_failures do
+ expect(service.execute).to contain_exactly({
+ ref: '*',
+ gcp_project: 'value-GCP_PROJECT_ID-*',
+ instance_name: 'value-GCP_CLOUDSQL_INSTANCE_NAME-*',
+ version: 'value-GCP_CLOUDSQL_VERSION-*'
+ },
+ {
+ ref: 'STG',
+ gcp_project: 'value-GCP_PROJECT_ID-STG',
+ instance_name: 'value-GCP_CLOUDSQL_INSTANCE_NAME-STG',
+ version: 'value-GCP_CLOUDSQL_VERSION-STG'
+ },
+ {
+ ref: 'PRD',
+ gcp_project: 'value-GCP_PROJECT_ID-PRD',
+ instance_name: 'value-GCP_CLOUDSQL_INSTANCE_NAME-PRD',
+ version: 'value-GCP_CLOUDSQL_VERSION-PRD'
+ })
+ end
+ end
+end
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 55553097423..e0a622bfa4a 100644
--- a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb
+++ b/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb
@@ -5,6 +5,21 @@ require 'spec_helper'
RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
let(:random_user) { create(:user) }
let(:project) { create(:project) }
+ 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')
+ ])
+ 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')
+ ])
+ end
context 'when unauthorized user triggers worker' do
subject do
@@ -76,6 +91,8 @@ RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |google_api_client|
expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
expect(google_api_client).to receive(:create_cloudsql_database).and_return(operation_fail)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases_empty)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users_empty)
end
message = subject[:message]
@@ -92,6 +109,8 @@ RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
expect(google_api_client).to receive(:create_cloudsql_database).and_return(operation_done)
expect(google_api_client).to receive(:create_cloudsql_user).and_return(operation_fail)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases_empty)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users_empty)
end
message = subject[:message]
@@ -102,12 +121,59 @@ RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
end
end
+ context 'when database and user already exist' do
+ it 'does not try to create a database or user' do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |google_api_client|
+ expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
+ expect(google_api_client).not_to receive(:create_cloudsql_database)
+ expect(google_api_client).not_to receive(:create_cloudsql_user)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users)
+ end
+
+ status = subject[:status]
+ expect(status).to eq(:success)
+ end
+ end
+
+ context 'when database already exists' do
+ it 'does not try to create a database' do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |google_api_client|
+ expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
+ expect(google_api_client).not_to receive(:create_cloudsql_database)
+ expect(google_api_client).to receive(:create_cloudsql_user).and_return(operation_done)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users_empty)
+ end
+
+ status = subject[:status]
+ expect(status).to eq(:success)
+ end
+ end
+
+ context 'when user already exists' do
+ it 'does not try to create a user' do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |google_api_client|
+ expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
+ expect(google_api_client).to receive(:create_cloudsql_database).and_return(operation_done)
+ expect(google_api_client).not_to receive(:create_cloudsql_user)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases_empty)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users)
+ end
+
+ status = subject[:status]
+ expect(status).to eq(:success)
+ end
+ end
+
context 'when database and user creation succeeds' do
it 'stores project CI vars' do
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |google_api_client|
expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
expect(google_api_client).to receive(:create_cloudsql_database).and_return(operation_done)
expect(google_api_client).to receive(:create_cloudsql_user).and_return(operation_done)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases_empty)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users_empty)
end
subject
@@ -143,6 +209,8 @@ RSpec.describe GoogleCloud::SetupCloudsqlInstanceService do
expect(google_api_client).to receive(:get_cloudsql_instance).and_return(get_instance_response_runnable)
expect(google_api_client).to receive(:create_cloudsql_database).and_return(operation_done)
expect(google_api_client).to receive(:create_cloudsql_user).and_return(operation_done)
+ expect(google_api_client).to receive(:list_cloudsql_databases).and_return(list_databases_empty)
+ expect(google_api_client).to receive(:list_cloudsql_users).and_return(list_users_empty)
end
subject
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 6e074f451c4..0cfde9ef434 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -176,6 +176,15 @@ RSpec.describe Groups::CreateService, '#execute' do
end
end
+ describe 'creating a details record' do
+ let(:service) { described_class.new(user, group_params) }
+
+ it 'create the details record connected to the group' do
+ group = subject
+ expect(group.namespace_details).to be_persisted
+ end
+ end
+
describe 'create service for the group' do
let(:service) { described_class.new(user, group_params) }
let(:created_group) { service.execute }
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index f43f64fdf89..0d699dd447b 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Groups::DestroyService do
let!(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
let!(:project) { create(:project, :repository, :legacy_storage, namespace: group) }
- let!(:notification_setting) { create(:notification_setting, source: group)}
+ let!(:notification_setting) { create(:notification_setting, source: group) }
let(:gitlab_shell) { Gitlab::Shell.new }
let(:remove_path) { group.path + "+#{group.id}+deleted" }
@@ -74,6 +74,17 @@ RSpec.describe Groups::DestroyService do
end
end
end
+
+ context 'event store', :sidekiq_might_not_need_inline do
+ it 'publishes a GroupDeletedEvent' do
+ expect { destroy_group(group, user, async) }
+ .to publish_event(Groups::GroupDeletedEvent)
+ .with(
+ group_id: group.id,
+ root_namespace_id: group.root_ancestor.id
+ )
+ end
+ end
end
describe 'asynchronous delete' do
@@ -271,7 +282,7 @@ RSpec.describe Groups::DestroyService do
end
context 'the shared_with group is deleted' do
- let!(:group2_subgroup) { create(:group, :private, parent: group2)}
+ let!(:group2_subgroup) { create(:group, :private, parent: group2) }
let!(:group2_subgroup_project) { create(:project, :private, group: group2_subgroup) }
it 'updates project authorizations so users of both groups lose access', :aggregate_failures do
diff --git a/spec/services/groups/merge_requests_count_service_spec.rb b/spec/services/groups/merge_requests_count_service_spec.rb
index 10c7ba5fca4..8bd350d6f0e 100644
--- a/spec/services/groups/merge_requests_count_service_spec.rb
+++ b/spec/services/groups/merge_requests_count_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Groups::MergeRequestsCountService, :use_clean_rails_memory_store_caching do
let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group, :public)}
+ let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :repository, namespace: group) }
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
diff --git a/spec/services/groups/open_issues_count_service_spec.rb b/spec/services/groups/open_issues_count_service_spec.rb
index fca09bfdebe..923caa6c150 100644
--- a/spec/services/groups/open_issues_count_service_spec.rb
+++ b/spec/services/groups/open_issues_count_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Groups::OpenIssuesCountService, :use_clean_rails_memory_store_caching do
- let_it_be(:group) { create(:group, :public)}
+ let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, namespace: group) }
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue, :opened, project: project) }
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index fbcca215282..b543661e9a0 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -22,6 +22,18 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
let!(:group_member) { create(:group_member, :owner, group: group, user: user) }
let(:transfer_service) { described_class.new(group, user) }
+ shared_examples 'publishes a GroupTransferedEvent' do
+ it do
+ expect { transfer_service.execute(target) }
+ .to publish_event(Groups::GroupTransferedEvent)
+ .with(
+ group_id: group.id,
+ old_root_namespace_id: group.root_ancestor.id,
+ new_root_namespace_id: target.root_ancestor.id
+ )
+ end
+ end
+
context 'handling packages' do
let_it_be(:group) { create(:group, :public) }
let_it_be(:new_group) { create(:group, :public) }
@@ -895,6 +907,10 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect { transfer_service.execute(root_group) }
.not_to change { CustomerRelations::IssueContact.count }
end
+
+ it_behaves_like 'publishes a GroupTransferedEvent' do
+ let(:target) { root_group }
+ end
end
context 'moving down' do
@@ -904,6 +920,10 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect { transfer_service.execute(another_subgroup) }
.not_to change { CustomerRelations::IssueContact.count }
end
+
+ it_behaves_like 'publishes a GroupTransferedEvent' do
+ let(:target) { another_subgroup }
+ end
end
context 'moving sideways' do
@@ -913,6 +933,10 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect { transfer_service.execute(another_subgroup) }
.not_to change { CustomerRelations::IssueContact.count }
end
+
+ it_behaves_like 'publishes a GroupTransferedEvent' do
+ let(:target) { another_subgroup }
+ end
end
context 'moving to new root group' do
@@ -932,6 +956,10 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect { transfer_service.execute(new_parent_group) }
.not_to change { CustomerRelations::IssueContact.count }
end
+
+ it_behaves_like 'publishes a GroupTransferedEvent' do
+ let(:target) { new_parent_group }
+ end
end
context 'moving to a subgroup within a new root group' do
@@ -953,6 +981,10 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect { transfer_service.execute(subgroup_in_new_parent_group) }
.not_to change { CustomerRelations::IssueContact.count }
end
+
+ it_behaves_like 'publishes a GroupTransferedEvent' do
+ let(:target) { subgroup_in_new_parent_group }
+ end
end
context 'with permission on the subgroup' do
@@ -965,6 +997,11 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
expect(transfer_service.error).to eq("Transfer failed: Group contains contacts/organizations and you don't have enough permissions to move them to the new root group.")
end
+
+ it 'does not publish a GroupTransferedEvent' do
+ expect { transfer_service.execute(subgroup_in_new_parent_group) }
+ .not_to publish_event(Groups::GroupTransferedEvent)
+ end
end
end
end
diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb
index 856dd4a2567..5c87b9ac8bb 100644
--- a/spec/services/groups/update_service_spec.rb
+++ b/spec/services/groups/update_service_spec.rb
@@ -339,8 +339,44 @@ RSpec.describe Groups::UpdateService do
end
end
+ context 'EventStore' do
+ let(:service) { described_class.new(group, user, **params) }
+ let(:root_group) { create(:group, path: 'root') }
+ let(:group) do
+ create(:group, parent: root_group, path: 'old-path').tap { |g| g.add_owner(user) }
+ end
+
+ context 'when changing a group path' do
+ let(:new_path) { SecureRandom.hex }
+ let(:params) { { path: new_path } }
+
+ it 'publishes a GroupPathChangedEvent' do
+ old_path = group.full_path
+
+ expect { service.execute }
+ .to publish_event(Groups::GroupPathChangedEvent)
+ .with(
+ group_id: group.id,
+ root_namespace_id: group.root_ancestor.id,
+ old_path: old_path,
+ new_path: "root/#{new_path}"
+ )
+ end
+ end
+
+ context 'when not changing a group path' do
+ let(:params) { { name: 'very-new-name' } }
+
+ it 'does not publish a GroupPathChangedEvent' do
+ expect { service.execute }
+ .not_to publish_event(Groups::GroupPathChangedEvent)
+ end
+ end
+ end
+
context 'rename group' do
- let!(:service) { described_class.new(internal_group, user, path: SecureRandom.hex) }
+ let(:new_path) { SecureRandom.hex }
+ let!(:service) { described_class.new(internal_group, user, path: new_path) }
before do
internal_group.add_member(user, Gitlab::Access::MAINTAINER)
@@ -371,7 +407,7 @@ RSpec.describe Groups::UpdateService do
end
it "hasn't changed the path" do
- expect { service.execute}.not_to change { internal_group.reload.path}
+ expect { service.execute }.not_to change { internal_group.reload.path }
end
end
end
diff --git a/spec/services/groups/update_statistics_service_spec.rb b/spec/services/groups/update_statistics_service_spec.rb
index 5bef51c2727..84b18b670a7 100644
--- a/spec/services/groups/update_statistics_service_spec.rb
+++ b/spec/services/groups/update_statistics_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Groups::UpdateStatisticsService do
let(:statistics) { %w(wiki_size) }
- subject(:service) { described_class.new(group, statistics: statistics)}
+ subject(:service) { described_class.new(group, statistics: statistics) }
describe '#execute', :aggregate_failures do
context 'when group is nil' do
diff --git a/spec/services/import/fogbugz_service_spec.rb b/spec/services/import/fogbugz_service_spec.rb
index c9477dba7a5..7b86c5c45b0 100644
--- a/spec/services/import/fogbugz_service_spec.rb
+++ b/spec/services/import/fogbugz_service_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe Import::FogbugzService do
let(:error_messages_array) { instance_double(Array, join: "something went wrong") }
let(:errors_double) { instance_double(ActiveModel::Errors, full_messages: error_messages_array, :[] => nil) }
let(:project_double) { instance_double(Project, persisted?: false, errors: errors_double) }
- let(:project_creator) { instance_double(Gitlab::FogbugzImport::ProjectCreator, execute: project_double )}
+ let(:project_creator) { instance_double(Gitlab::FogbugzImport::ProjectCreator, execute: project_double ) }
before do
allow(Gitlab::FogbugzImport::ProjectCreator).to receive(:new).and_return(project_creator)
diff --git a/spec/services/import/prepare_service_spec.rb b/spec/services/import/prepare_service_spec.rb
new file mode 100644
index 00000000000..0097198f7a9
--- /dev/null
+++ b/spec/services/import/prepare_service_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Import::PrepareService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:file) { double }
+ let(:upload_service) { double }
+ let(:uploader) { double }
+ let(:upload) { double }
+
+ let(:service) { described_class.new(project, user, file: file) }
+
+ subject { service.execute }
+
+ context 'when file is uploaded correctly' do
+ let(:upload_id) { 99 }
+
+ before do
+ mock_upload
+ end
+
+ it 'raises NotImplemented error for worker' do
+ expect { subject }.to raise_error(NotImplementedError)
+ end
+
+ context 'when a job is enqueued' do
+ before do
+ worker = double
+
+ allow(service).to receive(:worker).and_return(worker)
+ allow(worker).to receive(:perform_async)
+ end
+
+ it 'raises NotImplemented error for success_message when a job is enqueued' do
+ expect { subject }.to raise_error(NotImplementedError)
+ end
+
+ it 'returns a success respnse when a success_message is implemented' do
+ message = 'It works!'
+
+ allow(service).to receive(:success_message).and_return(message)
+
+ result = subject
+
+ expect(result).to be_success
+ expect(result.message).to eq(message)
+ end
+ end
+ end
+
+ context 'when file upload fails' do
+ before do
+ mock_upload(false)
+ end
+
+ it 'returns an error message' do
+ result = subject
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('File upload error.')
+ end
+ end
+end
diff --git a/spec/services/import/validate_remote_git_endpoint_service_spec.rb b/spec/services/import/validate_remote_git_endpoint_service_spec.rb
index 9dc862b6ca3..221ac2cd73a 100644
--- a/spec/services/import/validate_remote_git_endpoint_service_spec.rb
+++ b/spec/services/import/validate_remote_git_endpoint_service_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Import::ValidateRemoteGitEndpointService do
end
context 'when uri is using git:// protocol' do
- subject { described_class.new(url: 'git://demo.host/repo')}
+ subject { described_class.new(url: 'git://demo.host/repo') }
it 'returns success' do
result = subject.execute
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 a4e928b98f4..b999403e168 100644
--- a/spec/services/incident_management/timeline_events/create_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/create_service_spec.rb
@@ -244,5 +244,88 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
it_behaves_like 'successfully created timeline event'
end
+
+ describe '.change_labels' do
+ subject(:execute) do
+ described_class.change_labels(incident, current_user, added_labels: added, removed_labels: removed)
+ end
+
+ let_it_be(:labels) { create_list(:label, 4, project: project) }
+
+ let(:expected_action) { 'label' }
+
+ context 'when there are neither added nor removed labels' do
+ let(:added) { [] }
+ let(:removed) { [] }
+
+ it 'responds with error', :aggregate_failures do
+ expect(execute).to be_error
+ expect(execute.message).to eq(_('There are no changed labels'))
+ end
+
+ it 'does not create timeline event' do
+ expect { execute }.not_to change { incident.incident_management_timeline_events.count }
+ end
+ end
+
+ context 'when there are only added labels' do
+ let(:added) { [labels[0], labels[1]] }
+ let(:removed) { [] }
+
+ let(:expected_note) { "@#{current_user.username} added #{added.map(&:to_reference).join(' ')} labels" }
+
+ it_behaves_like 'successfully created timeline event'
+ end
+
+ context 'when there are only removed labels' do
+ let(:added) { [] }
+ let(:removed) { [labels[2], labels[3]] }
+
+ let(:expected_note) { "@#{current_user.username} removed #{removed.map(&:to_reference).join(' ')} labels" }
+
+ it_behaves_like 'successfully created timeline event'
+ end
+
+ context 'when there are both added and removed labels' do
+ let(:added) { [labels[0], labels[1]] }
+ let(:removed) { [labels[2], labels[3]] }
+
+ let(:expected_note) do
+ added_note = "added #{added.map(&:to_reference).join(' ')} labels"
+ removed_note = "removed #{removed.map(&:to_reference).join(' ')} labels"
+
+ "@#{current_user.username} #{added_note} and #{removed_note}"
+ end
+
+ it_behaves_like 'successfully created timeline event'
+ end
+
+ context 'when there is a single added and single removed labels' do
+ let(:added) { [labels[0]] }
+ let(:removed) { [labels[3]] }
+
+ let(:expected_note) do
+ added_note = "added #{added.first.to_reference} label"
+ removed_note = "removed #{removed.first.to_reference} label"
+
+ "@#{current_user.username} #{added_note} and #{removed_note}"
+ end
+
+ it_behaves_like 'successfully created timeline event'
+ end
+
+ context 'when feature flag is disabled' do
+ let(:added) { [labels[0], labels[1]] }
+ let(:removed) { [labels[2], labels[3]] }
+
+ before do
+ stub_feature_flags(incident_timeline_events_from_labels: false)
+ end
+
+ it 'does not create timeline event' do
+ expect { execute }.not_to change { incident.incident_management_timeline_events.count }
+ end
+ end
+ 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 728f2fa3e9d..f612c72e2a8 100644
--- a/spec/services/incident_management/timeline_events/update_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/update_service_spec.rb
@@ -32,6 +32,10 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
expect(execute.message).to eq(message)
end
+ it 'does not update the note' do
+ expect { execute }.not_to change { timeline_event.reload.note }
+ end
+
it_behaves_like 'does not track incident management event', :incident_management_timeline_event_edited
end
@@ -94,16 +98,7 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
context 'when note is blank' do
let(:params) { { note: '', occurred_at: occurred_at } }
- it_behaves_like 'successful response'
- it_behaves_like 'passing the correct was_changed value', :occurred_at
-
- it 'does not update the note' do
- expect { execute }.not_to change { timeline_event.reload.note }
- end
-
- it 'updates occurred_at' do
- expect { execute }.to change { timeline_event.occurred_at }.to(params[:occurred_at])
- end
+ it_behaves_like 'error response', "Note can't be blank"
end
context 'when occurred_at is nil' do
@@ -121,6 +116,12 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
end
end
+ context 'when occurred_at is blank' do
+ let(:params) { { note: 'Updated note', occurred_at: '' } }
+
+ it_behaves_like 'error response', "Occurred at can't be blank"
+ end
+
context 'when both occurred_at and note is nil' do
let(:params) { {} }
diff --git a/spec/services/issuable/common_system_notes_service_spec.rb b/spec/services/issuable/common_system_notes_service_spec.rb
index 1426ef2a1f6..0d2b8a4ac3c 100644
--- a/spec/services/issuable/common_system_notes_service_spec.rb
+++ b/spec/services/issuable/common_system_notes_service_spec.rb
@@ -8,6 +8,37 @@ RSpec.describe Issuable::CommonSystemNotesService do
let(:issuable) { create(:issue, project: project) }
+ shared_examples 'system note for issuable date changes' do
+ it 'creates a system note for due_date set' do
+ issuable.update!(due_date: Date.today)
+
+ expect { subject }.to change(issuable.notes, :count).from(0).to(1)
+ expect(issuable.notes.last.note).to match('changed due date to')
+ end
+
+ it 'creates a system note for start_date set' do
+ issuable.update!(start_date: Date.today)
+
+ expect { subject }.to change(issuable.notes, :count).from(0).to(1)
+ expect(issuable.notes.last.note).to match('changed start date to')
+ end
+
+ it 'creates a note when both start and due date are changed' do
+ issuable.update!(start_date: Date.today, due_date: 1.week.from_now)
+
+ expect { subject }.to change { issuable.notes.count }.from(0).to(1)
+ expect(issuable.notes.last.note).to match(/changed start date to.+and changed due date to/)
+ end
+
+ it 'does not call SystemNoteService if no dates are changed' do
+ issuable.update!(title: 'new title')
+
+ expect(SystemNoteService).not_to receive(:change_start_date_or_due_date)
+
+ subject
+ end
+ end
+
context 'on issuable update' do
it_behaves_like 'system note creation', { title: 'New title' }, 'changed title'
it_behaves_like 'system note creation', { description: 'New description' }, 'changed the description'
@@ -61,6 +92,12 @@ RSpec.describe Issuable::CommonSystemNotesService do
end
end
end
+
+ context 'when changing dates' do
+ it_behaves_like 'system note for issuable date changes' do
+ subject { described_class.new(project: project, current_user: user).execute(issuable) }
+ end
+ end
end
context 'on issuable create' do
@@ -102,12 +139,8 @@ RSpec.describe Issuable::CommonSystemNotesService do
end
end
- it 'creates a system note for due_date set' do
- issuable.due_date = Date.today
- issuable.save!
-
- expect { subject }.to change { issuable.notes.count }.from(0).to(1)
- expect(issuable.notes.last.note).to match('changed due date')
+ context 'when changing dates' do
+ it_behaves_like 'system note for issuable date changes'
end
end
end
diff --git a/spec/services/issues/clone_service_spec.rb b/spec/services/issues/clone_service_spec.rb
index 858dfc4ab3a..435488b7f66 100644
--- a/spec/services/issues/clone_service_spec.rb
+++ b/spec/services/issues/clone_service_spec.rb
@@ -57,8 +57,20 @@ RSpec.describe Issues::CloneService do
expect(old_issue.notes.last.note).to start_with 'cloned to'
end
- it 'adds system note to new issue at the end' do
- expect(new_issue.notes.last.note).to start_with 'cloned from'
+ it 'adds system note to new issue at the start' do
+ # We set an assignee so an assignee system note will be generated and
+ # we can assert that the "cloned from" note is the first one
+ assignee = create(:user)
+ new_project.add_developer(assignee)
+ old_issue.assignees = [assignee]
+
+ new_issue = clone_service.execute(old_issue, new_project)
+
+ expect(new_issue.notes.size).to eq(2)
+
+ cloned_from_note = new_issue.notes.last
+ expect(cloned_from_note.note).to start_with 'cloned from'
+ expect(new_issue.notes.fresh.first).to eq(cloned_from_note)
end
it 'keeps old issue open' do
@@ -128,11 +140,11 @@ RSpec.describe Issues::CloneService do
context 'issue with award emoji' do
let!(:award_emoji) { create(:award_emoji, awardable: old_issue) }
- it 'copies the award emoji' do
+ it 'does not copy the award emoji' do
old_issue.reload
new_issue = clone_service.execute(old_issue, new_project)
- expect(old_issue.award_emoji.first.name).to eq new_issue.reload.award_emoji.first.name
+ expect(new_issue.reload.award_emoji).to be_empty
end
end
@@ -170,19 +182,21 @@ RSpec.describe Issues::CloneService do
context 'issue with due date' do
let(:date) { Date.parse('2020-01-10') }
+ let(:new_date) { date + 1.week }
let(:old_issue) do
create(:issue, title: title, description: description, project: old_project, author: author, due_date: date)
end
before do
- SystemNoteService.change_due_date(old_issue, old_project, author, old_issue.due_date)
+ old_issue.update!(due_date: new_date)
+ SystemNoteService.change_start_date_or_due_date(old_issue, old_project, author, old_issue.previous_changes.slice('due_date'))
end
it 'keeps the same due date' do
new_issue = clone_service.execute(old_issue, new_project)
- expect(new_issue.due_date).to eq(date)
+ expect(new_issue.due_date).to eq(old_issue.due_date)
end
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 0bc8511e3e3..80c455e72b0 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -69,6 +69,12 @@ RSpec.describe Issues::CreateService do
expect(issue.issue_customer_relations_contacts).to be_empty
end
+ it 'calls NewIssueWorker with correct arguments' do
+ expect(NewIssueWorker).to receive(:perform_async).with(Integer, user.id, 'Issue')
+
+ issue
+ 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 }
@@ -143,6 +149,12 @@ RSpec.describe Issues::CreateService do
issue
end
+ it 'calls NewIssueWorker with correct arguments' do
+ expect(NewIssueWorker).to receive(:perform_async).with(Integer, reporter.id, 'Issue')
+
+ issue
+ end
+
context 'when invalid' do
before do
opts.merge!(title: '')
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index 5a1bb2e8b74..863df810d01 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Issues::MoveService do
let_it_be(:new_project) { create(:project, namespace: sub_group_2) }
let(:old_issue) do
- create(:issue, title: title, description: description, project: old_project, author: author)
+ create(:issue, title: title, description: description, project: old_project, author: author, created_at: 1.day.ago, updated_at: 1.day.ago)
end
subject(:move_service) do
@@ -62,8 +62,11 @@ RSpec.describe Issues::MoveService do
expect(old_issue.notes.last.note).to start_with 'moved to'
end
- it 'adds system note to new issue at the end' do
- expect(new_issue.notes.last.note).to start_with 'moved from'
+ it 'adds system note to new issue at the end', :freeze_time do
+ system_note = new_issue.notes.last
+
+ expect(system_note.note).to start_with 'moved from'
+ expect(system_note.created_at).to be_like_time(Time.current)
end
it 'closes old issue' do
@@ -137,7 +140,8 @@ RSpec.describe Issues::MoveService do
end
before do
- SystemNoteService.change_due_date(old_issue, old_project, author, old_issue.due_date)
+ old_issue.update!(due_date: Date.today)
+ SystemNoteService.change_start_date_or_due_date(old_issue, old_project, author, old_issue.previous_changes.slice('due_date'))
end
it 'does not create extra system notes' do
diff --git a/spec/services/issues/prepare_import_csv_service_spec.rb b/spec/services/issues/prepare_import_csv_service_spec.rb
new file mode 100644
index 00000000000..ded23ee43b9
--- /dev/null
+++ b/spec/services/issues/prepare_import_csv_service_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issues::PrepareImportCsvService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+
+ let(:file) { double }
+ let(:upload_service) { double }
+ let(:uploader) { double }
+ let(:upload) { double }
+
+ let(:subject) do
+ described_class.new(project, user, file: file).execute
+ end
+
+ context 'when file is uploaded correctly' do
+ let(:upload_id) { 99 }
+
+ before do
+ mock_upload
+ end
+
+ it 'returns a success message' do
+ result = subject
+
+ expect(result[:status]).to eq(:success)
+ expect(result[:message]).to eq("Your issues are being imported. Once finished, you'll get a confirmation email.")
+ end
+
+ it 'enqueues the ImportRequirementsCsvWorker' do
+ expect(ImportIssuesCsvWorker).to receive(:perform_async).with(user.id, project.id, upload_id)
+
+ subject
+ end
+ end
+
+ context 'when file upload fails' do
+ before do
+ mock_upload(false)
+ end
+
+ it 'returns an error message' do
+ result = subject
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('File upload error.')
+ end
+ end
+end
diff --git a/spec/services/issues/referenced_merge_requests_service_spec.rb b/spec/services/issues/referenced_merge_requests_service_spec.rb
index dc55ba8ebea..16166c1fa33 100644
--- a/spec/services/issues/referenced_merge_requests_service_spec.rb
+++ b/spec/services/issues/referenced_merge_requests_service_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe Issues::ReferencedMergeRequestsService do
end
describe '#closed_by_merge_requests' do
- let(:closed_issue) { build(:issue, :closed, project: project)}
+ let(:closed_issue) { build(:issue, :closed, project: project) }
it 'returns the open merge requests that close this issue' do
create_closing_mr(source_project: project, state: 'closed')
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index e2e8828ae89..aef3608831c 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -849,8 +849,8 @@ RSpec.describe Issues::UpdateService, :mailer do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 1** as completed')
- note2 = find_note('marked the task **Task 2** as completed')
+ note1 = find_note('marked the checklist item **Task 1** as completed')
+ note2 = find_note('marked the checklist item **Task 2** as completed')
expect(note1).not_to be_nil
expect(note2).not_to be_nil
@@ -867,8 +867,8 @@ RSpec.describe Issues::UpdateService, :mailer do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 1** as incomplete')
- note2 = find_note('marked the task **Task 2** as incomplete')
+ note1 = find_note('marked the checklist item **Task 1** as incomplete')
+ note2 = find_note('marked the checklist item **Task 2** as incomplete')
expect(note1).not_to be_nil
expect(note2).not_to be_nil
@@ -885,7 +885,7 @@ RSpec.describe Issues::UpdateService, :mailer do
end
it 'does not create a system note for the task' do
- task_note = find_note('marked the task **Task 2** as incomplete')
+ task_note = find_note('marked the checklist item **Task 2** as incomplete')
description_notes = find_notes('description')
expect(task_note).to be_nil
@@ -900,7 +900,7 @@ RSpec.describe Issues::UpdateService, :mailer do
end
it 'does not create a system note referencing the position the old item' do
- task_note = find_note('marked the task **Two** as incomplete')
+ task_note = find_note('marked the checklist item **Two** as incomplete')
description_notes = find_notes('description')
expect(task_note).to be_nil
@@ -988,6 +988,52 @@ RSpec.describe Issues::UpdateService, :mailer do
end
end
+ context 'updating dates' do
+ subject(:result) { described_class.new(project: project, current_user: user, params: params).execute(issue) }
+
+ let(:updated_date) { 1.week.from_now.to_date }
+
+ shared_examples 'issue update service that triggers date updates' do
+ it 'triggers graphql date updated subscription' do
+ expect(GraphqlTriggers).to receive(:issuable_dates_updated).with(issue).and_call_original
+
+ result
+ end
+ end
+
+ shared_examples 'issue update service that does not trigger date updates' do
+ it 'does not trigger date updated subscriptions' do
+ expect(GraphqlTriggers).not_to receive(:issuable_dates_updated)
+
+ result
+ end
+ end
+
+ context 'when due_date is updated' do
+ let(:params) { { due_date: updated_date } }
+
+ it_behaves_like 'issue update service that triggers date updates'
+ end
+
+ context 'when start_date is updated' do
+ let(:params) { { start_date: updated_date } }
+
+ it_behaves_like 'issue update service that triggers date updates'
+ end
+
+ context 'when no date is updated' do
+ let(:params) { { title: 'should not trigger date updates' } }
+
+ it_behaves_like 'issue update service that does not trigger date updates'
+ end
+
+ context 'when update is not successful but date is provided' do
+ let(:params) { { title: '', due_date: updated_date } }
+
+ it_behaves_like 'issue update service that does not trigger date updates'
+ end
+ end
+
context 'updating asssignee_id' do
it 'does not update assignee when assignee_id is invalid' do
update_issue(assignee_ids: [-1])
diff --git a/spec/services/jira_import/start_import_service_spec.rb b/spec/services/jira_import/start_import_service_spec.rb
index 510f58f0e75..c0db3012a30 100644
--- a/spec/services/jira_import/start_import_service_spec.rb
+++ b/spec/services/jira_import/start_import_service_spec.rb
@@ -136,7 +136,7 @@ RSpec.describe JiraImport::StartImportService do
end
context 'when multiple Jira imports for same Jira project' do
- let!(:jira_imports) { create_list(:jira_import_state, 3, :finished, project: project, jira_project_key: fake_key)}
+ let!(:jira_imports) { create_list(:jira_import_state, 3, :finished, project: project, jira_project_key: fake_key) }
it 'creates Jira label title with correct number' do
jira_import = subject.payload[:import_data]
diff --git a/spec/services/lfs/push_service_spec.rb b/spec/services/lfs/push_service_spec.rb
index e1564ca2359..f52bba94eea 100644
--- a/spec/services/lfs/push_service_spec.rb
+++ b/spec/services/lfs/push_service_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Lfs::PushService do
end
def batch_spec(*objects, upload: true, verify: false)
- { 'transfer' => 'basic', 'objects' => objects.map {|o| object_spec(o, upload: upload) } }
+ { 'transfer' => 'basic', 'objects' => objects.map { |o| object_spec(o, upload: upload) } }
end
def object_spec(object, upload: true, verify: false)
diff --git a/spec/services/markdown_content_rewriter_service_spec.rb b/spec/services/markdown_content_rewriter_service_spec.rb
index 91a117536ca..d94289856cf 100644
--- a/spec/services/markdown_content_rewriter_service_spec.rb
+++ b/spec/services/markdown_content_rewriter_service_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe MarkdownContentRewriterService do
let_it_be(:target_parent) { create(:project, :public) }
let(:content) { 'My content' }
- let(:issue) { create(:issue, project: source_parent, description: content)}
+ let(:issue) { create(:issue, project: source_parent, description: content) }
describe '#initialize' do
it 'raises an error if source_parent is not a Project' do
diff --git a/spec/services/members/groups/creator_service_spec.rb b/spec/services/members/groups/creator_service_spec.rb
index 4130fbd44fa..fced7195046 100644
--- a/spec/services/members/groups/creator_service_spec.rb
+++ b/spec/services/members/groups/creator_service_spec.rb
@@ -27,7 +27,10 @@ RSpec.describe Members::Groups::CreatorService do
context 'authorized projects update' do
it 'schedules a single project authorization update job when called multiple times' do
- expect(AuthorizedProjectsWorker).to receive(:bulk_perform_and_wait).once
+ # this is inline with the overridden behaviour in stubbed_member.rb
+ worker_instance = AuthorizedProjectsWorker.new
+ expect(AuthorizedProjectsWorker).to receive(:new).once.and_return(worker_instance)
+ expect(worker_instance).to receive(:perform).with(user.id)
1.upto(3) do
described_class.add_member(source, user, :maintainer)
diff --git a/spec/services/members/invite_service_spec.rb b/spec/services/members/invite_service_spec.rb
index d25c8996931..6dbe161ee02 100644
--- a/spec/services/members/invite_service_spec.rb
+++ b/spec/services/members/invite_service_spec.rb
@@ -455,7 +455,7 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
end
context 'when access_level is lower than inheriting member' do
- let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::GUEST }}
+ let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::GUEST } }
it 'does not add the member and returns an error' do
msg = "Access level should be greater than or equal " \
@@ -467,7 +467,7 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
end
context 'when access_level is the same as the inheriting member' do
- let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::DEVELOPER }}
+ let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::DEVELOPER } }
it 'adds the member with correct access_level' do
expect_to_create_members(count: 1)
@@ -477,7 +477,7 @@ RSpec.describe Members::InviteService, :aggregate_failures, :clean_gitlab_redis_
end
context 'when access_level is greater than the inheriting member' do
- let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::MAINTAINER }}
+ let(:params) { { user_id: group_member.user_id, access_level: ProjectMember::MAINTAINER } }
it 'adds the member with correct access_level' do
expect_to_create_members(count: 1)
diff --git a/spec/services/merge_requests/approval_service_spec.rb b/spec/services/merge_requests/approval_service_spec.rb
index e1fbb945ee3..ab98fad5d73 100644
--- a/spec/services/merge_requests/approval_service_spec.rb
+++ b/spec/services/merge_requests/approval_service_spec.rb
@@ -20,79 +20,111 @@ RSpec.describe MergeRequests::ApprovalService do
allow(merge_request.approvals).to receive(:new).and_return(double(save: false))
end
- it 'does not create an approval note' do
- expect(SystemNoteService).not_to receive(:approve_mr)
+ it 'does not reset approvals' do
+ expect(merge_request.approvals).not_to receive(:reset)
service.execute(merge_request)
end
- it 'does not mark pending todos as done' do
- service.execute(merge_request)
-
- expect(todo.reload).to be_pending
- end
-
it 'does not track merge request approve action' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.not_to receive(:track_approve_mr_action).with(user: user)
service.execute(merge_request)
end
- end
-
- context 'with valid approval' do
- let(:notification_service) { NotificationService.new }
- before do
- allow(service).to receive(:notification_service).and_return(notification_service)
+ it 'does not publish MergeRequests::ApprovedEvent' do
+ expect { service.execute(merge_request) }.not_to publish_event(MergeRequests::ApprovedEvent)
end
- it 'creates an approval note and marks pending todos as done' do
- expect(SystemNoteService).to receive(:approve_mr).with(merge_request, user)
- expect(merge_request.approvals).to receive(:reset)
+ context 'async_after_approval feature flag is disabled' do
+ before do
+ stub_feature_flags(async_after_approval: false)
+ end
- service.execute(merge_request)
+ it 'does not create approve MR event' do
+ expect(EventCreateService).not_to receive(:new)
- expect(todo.reload).to be_done
- end
+ service.execute(merge_request)
+ end
- it 'creates approve MR event' do
- expect_next_instance_of(EventCreateService) do |instance|
- expect(instance).to receive(:approve_mr)
- .with(merge_request, user)
+ it 'does not create an approval note' do
+ expect(SystemNoteService).not_to receive(:approve_mr)
+
+ service.execute(merge_request)
end
- service.execute(merge_request)
+ it 'does not mark pending todos as done' do
+ service.execute(merge_request)
+
+ expect(todo.reload).to be_pending
+ end
end
+ end
- it 'sends a notification when approving' do
- expect(notification_service).to receive_message_chain(:async, :approve_mr)
- .with(merge_request, user)
+ context 'with valid approval' do
+ it 'resets approvals' do
+ expect(merge_request.approvals).to receive(:reset)
service.execute(merge_request)
end
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: user, merge_request: merge_request, user: user)
- .and_call_original
+ it 'tracks merge request approve action' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_approve_mr_action).with(user: user, merge_request: merge_request)
service.execute(merge_request)
end
- context 'with remaining approvals' do
- it 'fires an approval webhook' do
- expect(service).to receive(:execute_hooks).with(merge_request, 'approved')
+ it 'publishes MergeRequests::ApprovedEvent' do
+ expect { service.execute(merge_request) }
+ .to publish_event(MergeRequests::ApprovedEvent)
+ .with(current_user_id: user.id, merge_request_id: merge_request.id)
+ end
+
+ context 'async_after_approval feature flag is disabled' do
+ let(:notification_service) { NotificationService.new }
+
+ before do
+ stub_feature_flags(async_after_approval: false)
+ allow(service).to receive(:notification_service).and_return(notification_service)
+ end
+
+ it 'creates approve MR event' do
+ expect_next_instance_of(EventCreateService) do |instance|
+ expect(instance).to receive(:approve_mr)
+ .with(merge_request, user)
+ end
service.execute(merge_request)
end
- end
- it 'tracks merge request approve action' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
- .to receive(:track_approve_mr_action).with(user: user, merge_request: merge_request)
+ it 'creates an approval note' do
+ expect(SystemNoteService).to receive(:approve_mr).with(merge_request, user)
- service.execute(merge_request)
+ service.execute(merge_request)
+ end
+
+ it 'marks pending todos as done' do
+ service.execute(merge_request)
+
+ expect(todo.reload).to be_done
+ end
+
+ it 'sends a notification when approving' do
+ expect(notification_service).to receive_message_chain(:async, :approve_mr)
+ .with(merge_request, user)
+
+ service.execute(merge_request)
+ end
+
+ context 'with remaining approvals' do
+ it 'fires an approval webhook' do
+ expect(service).to receive(:execute_hooks).with(merge_request, 'approved')
+
+ service.execute(merge_request)
+ end
+ end
end
end
diff --git a/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb b/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
deleted file mode 100644
index b2326a28e63..00000000000
--- a/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MergeRequests::BulkRemoveAttentionRequestedService do
- let(:current_user) { create(:user) }
- let(:user) { create(:user) }
- let(:assignee_user) { create(:user) }
- let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
- let(:reviewer) { merge_request.find_reviewer(user) }
- let(:assignee) { merge_request.find_assignee(assignee_user) }
- let(:project) { merge_request.project }
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, users: [user, assignee_user]) }
- let(:result) { service.execute }
-
- before do
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- describe '#execute' do
- context 'invalid permissions' do
- let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request, users: [user]) }
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'updates reviewers and assignees' do
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates reviewers state' do
- service.execute
- reviewer.reload
- assignee.reload
-
- expect(reviewer.state).to eq 'reviewed'
- expect(assignee.state).to eq 'reviewed'
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [assignee_user, user] }
- end
- end
- end
-end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index cd1c362a19f..8f448184b45 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -54,10 +54,6 @@ RSpec.describe MergeRequests::CloseService do
expect(todo.reload).to be_done
end
- it 'removes attention requested state' do
- expect(merge_request.find_assignee(user2).attention_requested?).to eq(false)
- end
-
context 'when auto merge is enabled' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
diff --git a/spec/services/merge_requests/create_approval_event_service_spec.rb b/spec/services/merge_requests/create_approval_event_service_spec.rb
new file mode 100644
index 00000000000..3d41ace11a7
--- /dev/null
+++ b/spec/services/merge_requests/create_approval_event_service_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::CreateApprovalEventService do
+ let(:user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+
+ subject(:service) { described_class.new(project: project, current_user: user) }
+
+ describe '#execute' do
+ it 'creates approve MR event' do
+ expect_next_instance_of(EventCreateService) do |instance|
+ expect(instance).to receive(:approve_mr)
+ .with(merge_request, user)
+ end
+
+ service.execute(merge_request)
+ end
+ end
+end
diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb
index 03a37ea59a3..c443d758a77 100644
--- a/spec/services/merge_requests/create_pipeline_service_spec.rb
+++ b/spec/services/merge_requests/create_pipeline_service_spec.rb
@@ -74,6 +74,16 @@ RSpec.describe MergeRequests::CreatePipelineService do
expect(response.payload.project).to eq(project)
end
+ context 'when the feature is disabled in CI/CD settings' do
+ before do
+ project.update!(ci_allow_fork_pipelines_to_run_in_parent_project: false)
+ end
+
+ it 'creates a pipeline in the source project' do
+ expect(response.payload.project).to eq(source_project)
+ end
+ end
+
context 'when source branch is protected' do
context 'when actor does not have permission to update the protected branch in target project' do
let!(:protected_branch) { create(:protected_branch, name: '*', project: project) }
diff --git a/spec/services/merge_requests/execute_approval_hooks_service_spec.rb b/spec/services/merge_requests/execute_approval_hooks_service_spec.rb
new file mode 100644
index 00000000000..863c47e8191
--- /dev/null
+++ b/spec/services/merge_requests/execute_approval_hooks_service_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ExecuteApprovalHooksService do
+ let(:user) { create(:user) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
+
+ subject(:service) { described_class.new(project: project, current_user: user) }
+
+ describe '#execute' do
+ let(:notification_service) { NotificationService.new }
+
+ before do
+ allow(service).to receive(:notification_service).and_return(notification_service)
+ end
+ it 'sends a notification when approving' do
+ expect(notification_service).to receive_message_chain(:async, :approve_mr)
+ .with(merge_request, user)
+
+ service.execute(merge_request)
+ end
+
+ context 'with remaining approvals' do
+ it 'fires an approval webhook' do
+ expect(service).to receive(:execute_hooks).with(merge_request, 'approved')
+
+ service.execute(merge_request)
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/handle_assignees_change_service_spec.rb b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
index fa3b1614e21..c43f5db6059 100644
--- a/spec/services/merge_requests/handle_assignees_change_service_spec.rb
+++ b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
@@ -87,14 +87,6 @@ RSpec.describe MergeRequests::HandleAssigneesChangeService do
expect(todo).to be_pending
end
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: user, merge_request: merge_request, user: user)
- .and_call_original
-
- execute
- end
-
it 'tracks users assigned event' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_users_assigned_to_mr).once.with(users: [assignee])
diff --git a/spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb b/spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb
index 9e178c121ef..6cc1079c94a 100644
--- a/spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/check_broken_status_service_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe MergeRequests::Mergeability::CheckBrokenStatusService do
let(:merge_request) { build(:merge_request) }
describe '#execute' do
+ let(:result) { check_broken_status.execute }
+
before do
expect(merge_request).to receive(:broken?).and_return(broken)
end
@@ -16,7 +18,8 @@ RSpec.describe MergeRequests::Mergeability::CheckBrokenStatusService do
let(:broken) { true }
it 'returns a check result with status failed' do
- expect(check_broken_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.payload[:reason]).to eq(:broken_status)
end
end
@@ -24,7 +27,7 @@ RSpec.describe MergeRequests::Mergeability::CheckBrokenStatusService do
let(:broken) { false }
it 'returns a check result with status success' do
- expect(check_broken_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
end
end
end
diff --git a/spec/services/merge_requests/mergeability/check_ci_status_service_spec.rb b/spec/services/merge_requests/mergeability/check_ci_status_service_spec.rb
index 6fbbecd7c0e..def3cb0ca28 100644
--- a/spec/services/merge_requests/mergeability/check_ci_status_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/check_ci_status_service_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe MergeRequests::Mergeability::CheckCiStatusService do
let(:skip_check) { false }
describe '#execute' do
+ let(:result) { check_ci_status.execute }
+
before do
expect(merge_request).to receive(:mergeable_ci_state?).and_return(mergeable)
end
@@ -18,7 +20,7 @@ RSpec.describe MergeRequests::Mergeability::CheckCiStatusService do
let(:mergeable) { true }
it 'returns a check result with status success' do
- expect(check_ci_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
end
end
@@ -26,7 +28,8 @@ RSpec.describe MergeRequests::Mergeability::CheckCiStatusService do
let(:mergeable) { false }
it 'returns a check result with status failed' do
- expect(check_ci_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.payload[:reason]).to eq :ci_must_pass
end
end
end
diff --git a/spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb b/spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb
index c24d40967c4..9f107ce046a 100644
--- a/spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/check_discussions_status_service_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe MergeRequests::Mergeability::CheckDiscussionsStatusService do
let(:skip_check) { false }
describe '#execute' do
+ let(:result) { check_discussions_status.execute }
+
before do
expect(merge_request).to receive(:mergeable_discussions_state?).and_return(mergeable)
end
@@ -18,7 +20,7 @@ RSpec.describe MergeRequests::Mergeability::CheckDiscussionsStatusService do
let(:mergeable) { true }
it 'returns a check result with status success' do
- expect(check_discussions_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
end
end
@@ -26,7 +28,8 @@ RSpec.describe MergeRequests::Mergeability::CheckDiscussionsStatusService do
let(:mergeable) { false }
it 'returns a check result with status failed' do
- expect(check_discussions_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.payload[:reason]).to eq(:discussions_not_resolved)
end
end
end
diff --git a/spec/services/merge_requests/mergeability/check_draft_status_service_spec.rb b/spec/services/merge_requests/mergeability/check_draft_status_service_spec.rb
index 923cff220ef..e9363e5d676 100644
--- a/spec/services/merge_requests/mergeability/check_draft_status_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/check_draft_status_service_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe MergeRequests::Mergeability::CheckDraftStatusService do
let(:merge_request) { build(:merge_request) }
describe '#execute' do
+ let(:result) { check_draft_status.execute }
+
before do
expect(merge_request).to receive(:draft?).and_return(draft)
end
@@ -16,7 +18,8 @@ RSpec.describe MergeRequests::Mergeability::CheckDraftStatusService do
let(:draft) { true }
it 'returns a check result with status failed' do
- expect(check_draft_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.payload[:reason]).to eq(:draft_status)
end
end
@@ -24,7 +27,7 @@ RSpec.describe MergeRequests::Mergeability::CheckDraftStatusService do
let(:draft) { false }
it 'returns a check result with status success' do
- expect(check_draft_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
end
end
end
diff --git a/spec/services/merge_requests/mergeability/check_open_status_service_spec.rb b/spec/services/merge_requests/mergeability/check_open_status_service_spec.rb
index b1c9a930317..936524b020a 100644
--- a/spec/services/merge_requests/mergeability/check_open_status_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/check_open_status_service_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe MergeRequests::Mergeability::CheckOpenStatusService do
let(:merge_request) { build(:merge_request) }
describe '#execute' do
+ let(:result) { check_open_status.execute }
+
before do
expect(merge_request).to receive(:open?).and_return(open)
end
@@ -16,7 +18,7 @@ RSpec.describe MergeRequests::Mergeability::CheckOpenStatusService do
let(:open) { true }
it 'returns a check result with status success' do
- expect(check_open_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
end
end
@@ -24,7 +26,8 @@ RSpec.describe MergeRequests::Mergeability::CheckOpenStatusService do
let(:open) { false }
it 'returns a check result with status failed' do
- expect(check_open_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
+ expect(result.payload[:reason]).to eq(:not_open)
end
end
end
diff --git a/spec/services/merge_requests/mergeability/run_checks_service_spec.rb b/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
index 2bb7dc3eef7..afea3e952a1 100644
--- a/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
+++ b/spec/services/merge_requests/mergeability/run_checks_service_spec.rb
@@ -5,11 +5,11 @@ require 'spec_helper'
RSpec.describe MergeRequests::Mergeability::RunChecksService do
subject(:run_checks) { described_class.new(merge_request: merge_request, params: {}) }
- let_it_be(:merge_request) { create(:merge_request) }
-
describe '#execute' do
subject(:execute) { run_checks.execute }
+ let_it_be(:merge_request) { create(:merge_request) }
+
let(:params) { {} }
let(:success_result) { Gitlab::MergeRequests::Mergeability::CheckResult.success }
@@ -23,7 +23,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
end
it 'is still a success' do
- expect(execute.all?(&:success?)).to eq(true)
+ expect(execute.success?).to eq(true)
end
end
@@ -41,13 +41,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
expect(service).not_to receive(:execute)
end
- # Since we're only marking one check to be skipped, we expect to receive
- # `# of checks - 1` success result objects in return
- #
- check_count = merge_request.mergeability_checks.count - 1
- success_array = (1..check_count).each_with_object([]) { |_, array| array << success_result }
-
- expect(execute).to match_array(success_array)
+ expect(execute.success?).to eq(true)
end
end
@@ -75,7 +69,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
expect(service).to receive(:read).with(merge_check: merge_check).and_return(success_result)
end
- expect(execute).to match_array([success_result])
+ expect(execute.success?).to eq(true)
end
end
@@ -86,7 +80,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
expect(service).to receive(:write).with(merge_check: merge_check, result_hash: success_result.to_hash).and_return(true)
end
- expect(execute).to match_array([success_result])
+ expect(execute.success?).to eq(true)
end
end
end
@@ -97,7 +91,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
it 'does not call the results store' do
expect(Gitlab::MergeRequests::Mergeability::ResultsStore).not_to receive(:new)
- expect(execute).to match_array([success_result])
+ expect(execute.success?).to eq(true)
end
end
@@ -109,9 +103,81 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
it 'does not call the results store' do
expect(Gitlab::MergeRequests::Mergeability::ResultsStore).not_to receive(:new)
- expect(execute).to match_array([success_result])
+ expect(execute.success?).to eq(true)
end
end
end
end
+
+ describe '#success?' do
+ subject(:success) { run_checks.success? }
+
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ context 'when the execute method has been executed' do
+ before do
+ run_checks.execute
+ end
+
+ context 'when all the checks succeed' do
+ it 'returns true' do
+ expect(success).to eq(true)
+ end
+ end
+
+ context 'when one check fails' do
+ before do
+ allow(merge_request).to receive(:open?).and_return(false)
+ run_checks.execute
+ end
+
+ it 'returns false' do
+ expect(success).to eq(false)
+ end
+ end
+ end
+
+ context 'when execute has not been exectued' do
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(/Execute needs to be called before/)
+ end
+ end
+ end
+
+ describe '#failure_reason' do
+ subject(:failure_reason) { run_checks.failure_reason }
+
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ context 'when the execute method has been executed' do
+ before do
+ run_checks.execute
+ end
+
+ context 'when all the checks succeed' do
+ it 'returns nil' do
+ expect(failure_reason).to eq(nil)
+ end
+ end
+
+ context 'when one check fails' do
+ before do
+ allow(merge_request).to receive(:open?).and_return(false)
+ run_checks.execute
+ end
+
+ it 'returns the open reason' do
+ expect(failure_reason).to eq(:not_open)
+ end
+ end
+ end
+
+ context 'when execute has not been exectued' do
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(/Execute needs to be called before/)
+ end
+ end
+ end
end
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index 338057f23d5..391377ad801 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -179,7 +179,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
end
@@ -231,7 +231,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the merge request to merge when pipeline succeeds'
@@ -284,7 +284,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can remove the source branch when it is merged'
@@ -337,7 +337,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the target of a merge request'
@@ -390,7 +390,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the title of a merge request'
@@ -443,7 +443,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the description of a merge request'
@@ -503,7 +503,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the draft of a merge request'
@@ -564,7 +564,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can change labels of a merge request', 2
@@ -617,7 +617,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can change labels of a merge request', 1
@@ -672,7 +672,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
context 'with an existing branch that has a merge request open' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can set the milestone of a merge request'
@@ -713,7 +713,7 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do
shared_examples 'with an existing branch that has a merge request open in foss' do
let(:changes) { existing_branch_changes }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch)}
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: source_branch) }
it_behaves_like 'a service that does not create a merge request'
it_behaves_like 'a service that can change assignees of a merge request', 1
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 4b7dd84474a..09d06b8b2ab 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -185,7 +185,7 @@ RSpec.describe MergeRequests::RefreshService do
end
context 'when pipeline exists for the source branch' do
- let!(:pipeline) { create(:ci_empty_pipeline, ref: @merge_request.source_branch, project: @project, sha: @commits.first.sha)}
+ let!(:pipeline) { create(:ci_empty_pipeline, ref: @merge_request.source_branch, project: @project, sha: @commits.first.sha) }
subject { service.new(project: @project, current_user: @user).execute(@oldrev, @newrev, 'refs/heads/master') }
diff --git a/spec/services/merge_requests/remove_attention_requested_service_spec.rb b/spec/services/merge_requests/remove_attention_requested_service_spec.rb
deleted file mode 100644
index 576049b9f1b..00000000000
--- a/spec/services/merge_requests/remove_attention_requested_service_spec.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MergeRequests::RemoveAttentionRequestedService do
- let_it_be(:current_user) { create(:user) }
- let_it_be(:user) { create(:user) }
- let_it_be(:assignee_user) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
-
- let(:reviewer) { merge_request.find_reviewer(user) }
- let(:assignee) { merge_request.find_assignee(assignee_user) }
- let(:project) { merge_request.project }
-
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- )
- end
-
- let(:result) { service.execute }
-
- before do
- allow(SystemNoteService).to receive(:remove_attention_request)
-
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- describe '#execute' do
- context 'when current user cannot update merge request' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: create(:user),
- merge_request: merge_request,
- user: user
- )
- end
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'when user is not a reviewer nor assignee' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: create(:user)
- )
- end
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'when user is a reviewer' do
- before do
- reviewer.update!(state: :attention_requested)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates reviewer state' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq 'reviewed'
- end
-
- it 'creates a remove attention request system note' do
- expect(SystemNoteService)
- .to receive(:remove_attention_request)
- .with(merge_request, merge_request.project, current_user, user)
-
- service.execute
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [user] }
- end
- end
-
- context 'when user is an assignee' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: assignee_user
- )
- end
-
- before do
- assignee.update!(state: :attention_requested)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates assignee state' do
- service.execute
- assignee.reload
-
- expect(assignee.state).to eq 'reviewed'
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [assignee_user] }
- end
-
- it 'creates a remove attention request system note' do
- expect(SystemNoteService)
- .to receive(:remove_attention_request)
- .with(merge_request, merge_request.project, current_user, assignee_user)
-
- service.execute
- end
- end
-
- context 'when user is an assignee and reviewer at the same time' do
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user], assignees: [user]) }
-
- let(:assignee) { merge_request.find_assignee(user) }
-
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- )
- end
-
- before do
- reviewer.update!(state: :attention_requested)
- assignee.update!(state: :attention_requested)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates reviewers and assignees state' do
- service.execute
- reviewer.reload
- assignee.reload
-
- expect(reviewer.state).to eq 'reviewed'
- expect(assignee.state).to eq 'reviewed'
- end
- end
-
- context 'when state is already not attention_requested' do
- before do
- reviewer.update!(state: :reviewed)
- end
-
- it 'does not change state' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq 'reviewed'
- end
-
- it 'does not create a remove attention request system note' do
- expect(SystemNoteService).not_to receive(:remove_attention_request)
-
- service.execute
- end
- end
- end
-end
diff --git a/spec/services/merge_requests/request_attention_service_spec.rb b/spec/services/merge_requests/request_attention_service_spec.rb
deleted file mode 100644
index 813a8150625..00000000000
--- a/spec/services/merge_requests/request_attention_service_spec.rb
+++ /dev/null
@@ -1,220 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MergeRequests::RequestAttentionService do
- let_it_be(:current_user) { create(:user) }
- let_it_be(:user) { create(:user) }
- let_it_be(:assignee_user) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
-
- let(:reviewer) { merge_request.find_reviewer(user) }
- let(:assignee) { merge_request.find_assignee(assignee_user) }
- let(:project) { merge_request.project }
-
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- )
- end
-
- let(:result) { service.execute }
- let(:todo_svc) { instance_double('TodoService') }
- let(:notification_svc) { instance_double('NotificationService') }
-
- before do
- allow(service).to receive(:todo_service).and_return(todo_svc)
- allow(service).to receive(:notification_service).and_return(notification_svc)
- allow(todo_svc).to receive(:create_attention_requested_todo)
- allow(notification_svc).to receive_message_chain(:async, :attention_requested_of_merge_request)
- allow(SystemNoteService).to receive(:request_attention)
-
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- describe '#execute' do
- context 'when current user cannot update merge request' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: create(:user),
- merge_request: merge_request,
- user: user
- )
- end
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'when user is not a reviewer nor assignee' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: create(:user)
- )
- end
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'when user is a reviewer' do
- before do
- reviewer.update!(state: :reviewed)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates reviewers state' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq 'attention_requested'
- end
-
- it 'adds who toggled attention' do
- service.execute
- reviewer.reload
-
- expect(reviewer.updated_state_by).to eq current_user
- end
-
- it 'creates a new todo for the reviewer' do
- expect(todo_svc).to receive(:create_attention_requested_todo).with(merge_request, current_user, user)
-
- service.execute
- end
-
- it 'sends email to reviewer' do
- expect(notification_svc)
- .to receive_message_chain(:async, :attention_requested_of_merge_request)
- .with(merge_request, current_user, user)
-
- service.execute
- end
-
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
- .and_call_original
-
- service.execute
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [user] }
- end
- end
-
- context 'when user is an assignee' do
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: assignee_user
- )
- end
-
- before do
- assignee.update!(state: :reviewed)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates assignees state' do
- service.execute
- assignee.reload
-
- expect(assignee.state).to eq 'attention_requested'
- end
-
- it 'creates a new todo for the reviewer' do
- expect(todo_svc).to receive(:create_attention_requested_todo).with(merge_request, current_user, assignee_user)
-
- service.execute
- end
-
- it 'creates a request attention system note' do
- expect(SystemNoteService)
- .to receive(:request_attention)
- .with(merge_request, merge_request.project, current_user, assignee_user)
-
- service.execute
- end
-
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
- .and_call_original
-
- service.execute
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [assignee_user] }
- end
- end
-
- context 'when user is an assignee and reviewer at the same time' do
- let_it_be(:merge_request) { create(:merge_request, reviewers: [user], assignees: [user]) }
-
- let(:assignee) { merge_request.find_assignee(user) }
-
- let(:service) do
- described_class.new(
- project: project,
- current_user: current_user,
- merge_request: merge_request,
- user: user
- )
- end
-
- before do
- reviewer.update!(state: :reviewed)
- assignee.update!(state: :reviewed)
- end
-
- it 'updates reviewers and assignees state' do
- service.execute
- reviewer.reload
- assignee.reload
-
- expect(reviewer.state).to eq 'attention_requested'
- expect(assignee.state).to eq 'attention_requested'
- end
- end
-
- context 'when state is attention_requested' do
- before do
- reviewer.update!(state: :attention_requested)
- end
-
- it 'does not change state' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq 'attention_requested'
- end
-
- it 'does not create a new todo for the reviewer' do
- expect(todo_svc).not_to receive(:create_attention_requested_todo).with(merge_request, current_user, user)
-
- service.execute
- end
- end
- end
-end
diff --git a/spec/services/merge_requests/toggle_attention_requested_service_spec.rb b/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
deleted file mode 100644
index 20bc536b21e..00000000000
--- a/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
+++ /dev/null
@@ -1,188 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe MergeRequests::ToggleAttentionRequestedService do
- let(:current_user) { create(:user) }
- let(:user) { create(:user) }
- let(:assignee_user) { create(:user) }
- let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
- let(:reviewer) { merge_request.find_reviewer(user) }
- let(:assignee) { merge_request.find_assignee(assignee_user) }
- let(:project) { merge_request.project }
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
- let(:result) { service.execute }
- let(:todo_service) { spy('todo service') }
- let(:notification_service) { spy('notification service') }
-
- before do
- allow(NotificationService).to receive(:new) { notification_service }
- allow(service).to receive(:todo_service).and_return(todo_service)
- allow(service).to receive(:notification_service).and_return(notification_service)
- allow(SystemNoteService).to receive(:request_attention)
- allow(SystemNoteService).to receive(:remove_attention_request)
-
- project.add_developer(current_user)
- project.add_developer(user)
- end
-
- describe '#execute' do
- context 'invalid permissions' do
- let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request, user: user) }
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'reviewer does not exist' do
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: create(:user)) }
-
- it 'returns an error' do
- expect(result[:status]).to eq :error
- end
- end
-
- context 'reviewer exists' do
- before do
- reviewer.update!(state: :reviewed)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates reviewers state' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq 'attention_requested'
- end
-
- it 'adds who toggled attention' do
- service.execute
- reviewer.reload
-
- expect(reviewer.updated_state_by).to eq current_user
- end
-
- it 'creates a new todo for the reviewer' do
- expect(todo_service).to receive(:create_attention_requested_todo).with(merge_request, current_user, user)
-
- service.execute
- end
-
- it 'sends email to reviewer' do
- expect(notification_service).to receive_message_chain(:async, :attention_requested_of_merge_request).with(merge_request, current_user, user)
-
- service.execute
- end
-
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
- .and_call_original
-
- service.execute
- end
-
- it 'invalidates cache' do
- cache_mock = double
-
- expect(cache_mock).to receive(:delete).with(['users', user.id, 'attention_requested_open_merge_requests_count'])
-
- allow(Rails).to receive(:cache).and_return(cache_mock)
-
- service.execute
- end
- end
-
- context 'assignee exists' do
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: assignee_user) }
-
- before do
- assignee.update!(state: :reviewed)
- end
-
- it 'returns success' do
- expect(result[:status]).to eq :success
- end
-
- it 'updates assignees state' do
- service.execute
- assignee.reload
-
- expect(assignee.state).to eq 'attention_requested'
- end
-
- it 'creates a new todo for the reviewer' do
- expect(todo_service).to receive(:create_attention_requested_todo).with(merge_request, current_user, assignee_user)
-
- service.execute
- end
-
- it 'creates a request attention system note' do
- expect(SystemNoteService).to receive(:request_attention).with(merge_request, merge_request.project, current_user, assignee_user)
-
- service.execute
- end
-
- it 'removes attention requested state' do
- expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
- .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
- .and_call_original
-
- service.execute
- end
-
- it_behaves_like 'invalidates attention request cache' do
- let(:users) { [assignee_user] }
- end
- end
-
- context 'assignee is the same as reviewer' do
- let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [user]) }
- let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
- let(:assignee) { merge_request.find_assignee(user) }
-
- before do
- reviewer.update!(state: :reviewed)
- assignee.update!(state: :reviewed)
- end
-
- it 'updates reviewers and assignees state' do
- service.execute
- reviewer.reload
- assignee.reload
-
- expect(reviewer.state).to eq 'attention_requested'
- expect(assignee.state).to eq 'attention_requested'
- end
- end
-
- context 'state is attention_requested' do
- before do
- reviewer.update!(state: :attention_requested)
- end
-
- it 'toggles state to reviewed' do
- service.execute
- reviewer.reload
-
- expect(reviewer.state).to eq "reviewed"
- end
-
- it 'does not create a new todo for the reviewer' do
- expect(todo_service).not_to receive(:create_attention_requested_todo).with(merge_request, current_user, assignee_user)
-
- service.execute
- end
-
- it 'creates a remove attention request system note' do
- expect(SystemNoteService).to receive(:remove_attention_request).with(merge_request, merge_request.project, current_user, user)
-
- service.execute
- end
- end
- end
-end
diff --git a/spec/services/merge_requests/update_reviewers_service_spec.rb b/spec/services/merge_requests/update_reviewers_service_spec.rb
new file mode 100644
index 00000000000..8920141adbb
--- /dev/null
+++ b/spec/services/merge_requests/update_reviewers_service_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::UpdateReviewersService do
+ include AfterNextHelpers
+
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :private, :repository, group: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:user3) { create(:user) }
+
+ let_it_be_with_reload(:merge_request) do
+ create(:merge_request, :simple, :unique_branches,
+ title: 'Old title',
+ description: "FYI #{user2.to_reference}",
+ reviewer_ids: [user3.id],
+ source_project: project,
+ target_project: project,
+ author: create(:user))
+ end
+
+ before do
+ project.add_maintainer(user)
+ project.add_developer(user2)
+ project.add_developer(user3)
+ merge_request.errors.clear
+ end
+
+ let(:service) { described_class.new(project: project, current_user: user, params: opts) }
+ let(:opts) { { reviewer_ids: [user2.id] } }
+
+ describe 'execute' do
+ def set_reviewers
+ service.execute(merge_request)
+ end
+
+ def find_note(starting_with)
+ merge_request.notes.find do |note|
+ note && note.note.start_with?(starting_with)
+ end
+ end
+
+ shared_examples 'removing all reviewers' do
+ it 'removes all reviewers' do
+ expect(set_reviewers).to have_attributes(reviewers: be_empty, errors: be_none)
+ end
+ end
+
+ context 'when the parameters are valid' do
+ context 'when using sentinel values' do
+ let(:opts) { { reviewer_ids: [0] } }
+
+ it_behaves_like 'removing all reviewers'
+ end
+
+ context 'when the reviewer_ids parameter is the empty list' do
+ let(:opts) { { reviewer_ids: [] } }
+
+ it_behaves_like 'removing all reviewers'
+ end
+
+ it 'updates the MR' do
+ expect { set_reviewers }
+ .to change { merge_request.reload.reviewers }.from([user3]).to([user2])
+ .and change(merge_request, :updated_at)
+ .and change(merge_request, :updated_by).to(user)
+ end
+
+ it 'creates system note about merge_request review request' do
+ set_reviewers
+
+ note = find_note('requested review from')
+
+ expect(note).not_to be_nil
+ expect(note.note).to include "requested review from #{user2.to_reference}"
+ end
+
+ it 'creates a pending todo for new review request' do
+ set_reviewers
+
+ attributes = {
+ project: project,
+ author: user,
+ user: user2,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
+ action: Todo::REVIEW_REQUESTED,
+ state: :pending
+ }
+
+ expect(Todo.where(attributes).count).to eq 1
+ end
+
+ it 'sends email reviewer change notifications to old and new reviewers', :sidekiq_inline, :mailer do
+ perform_enqueued_jobs do
+ set_reviewers
+ end
+
+ should_email(user2)
+ should_email(user3)
+ end
+
+ it 'updates open merge request counter for reviewers', :use_clean_rails_memory_store_caching do
+ # Cache them to ensure the cache gets invalidated on update
+ expect(user2.review_requested_open_merge_requests_count).to eq(0)
+ expect(user3.review_requested_open_merge_requests_count).to eq(1)
+
+ set_reviewers
+
+ expect(user2.review_requested_open_merge_requests_count).to eq(1)
+ expect(user3.review_requested_open_merge_requests_count).to eq(0)
+ end
+
+ it 'updates the tracking' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_users_review_requested)
+ .with(users: [user2])
+
+ set_reviewers
+ end
+
+ it 'tracks reviewers changed event' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
+ .to receive(:track_reviewers_changed_action).once.with(user: user)
+
+ 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)
+ end
+
+ set_reviewers
+ end
+
+ it 'executes hooks with update action' do
+ expect(service).to receive(:execute_hooks)
+ .with(
+ merge_request,
+ 'update',
+ old_associations: {
+ reviewers: [user3]
+ }
+ )
+
+ set_reviewers
+ end
+
+ it 'does not update the reviewers if they do not have access' do
+ opts[:reviewer_ids] = [create(:user).id]
+
+ expect(set_reviewers).to have_attributes(
+ reviewers: [user3],
+ errors: be_any
+ )
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 212f75d853f..b7fb48718d8 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
context 'usage counters' do
let(:merge_request2) { create(:merge_request) }
- let(:draft_merge_request) { create(:merge_request, :draft_merge_request)}
+ let(:draft_merge_request) { create(:merge_request, :draft_merge_request) }
it 'update as expected' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
@@ -980,8 +980,8 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 1** as completed')
- note2 = find_note('marked the task **Task 2** as completed')
+ note1 = find_note('marked the checklist item **Task 1** as completed')
+ note2 = find_note('marked the checklist item **Task 2** as completed')
expect(note1).not_to be_nil
expect(note2).not_to be_nil
@@ -998,8 +998,8 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 1** as incomplete')
- note2 = find_note('marked the task **Task 2** as incomplete')
+ note1 = find_note('marked the checklist item **Task 1** as incomplete')
+ note2 = find_note('marked the checklist item **Task 2** as incomplete')
expect(note1).not_to be_nil
expect(note2).not_to be_nil
diff --git a/spec/services/milestones/transfer_service_spec.rb b/spec/services/milestones/transfer_service_spec.rb
index afbc9c7dca2..b15d90d685c 100644
--- a/spec/services/milestones/transfer_service_spec.rb
+++ b/spec/services/milestones/transfer_service_spec.rb
@@ -11,9 +11,9 @@ RSpec.describe Milestones::TransferService do
let(:new_group) { create(:group) }
let(:old_group) { create(:group) }
let(:project) { create(:project, namespace: old_group) }
- let(:group_milestone) { create(:milestone, group: old_group)}
- let(:group_milestone2) { create(:milestone, group: old_group)}
- let(:project_milestone) { create(:milestone, project: project)}
+ let(:group_milestone) { create(:milestone, group: old_group) }
+ let(:group_milestone2) { create(:milestone, group: old_group) }
+ let(:project_milestone) { create(:milestone, project: project) }
let!(:issue_with_group_milestone) { create(:issue, project: project, milestone: group_milestone) }
let!(:issue_with_project_milestone) { create(:issue, project: project, milestone: project_milestone) }
let!(:mr_with_group_milestone) { create(:merge_request, source_project: project, source_branch: 'branch-1', milestone: group_milestone) }
@@ -43,7 +43,7 @@ RSpec.describe Milestones::TransferService do
context 'when milestone is from an ancestor group' do
let(:old_group_ancestor) { create(:group) }
let(:old_group) { create(:group, parent: old_group_ancestor) }
- let(:group_milestone) { create(:milestone, group: old_group_ancestor)}
+ let(:group_milestone) { create(:milestone, group: old_group_ancestor) }
it 'recreates the missing group milestones at project level' do
expect { service.execute }.to change(project.milestones, :count).by(1)
diff --git a/spec/services/notes/build_service_spec.rb b/spec/services/notes/build_service_spec.rb
index 0e2bbcc8c66..c25895d2efa 100644
--- a/spec/services/notes/build_service_spec.rb
+++ b/spec/services/notes/build_service_spec.rb
@@ -170,7 +170,7 @@ RSpec.describe Notes::BuildService do
end
context 'when creating a new confidential comment' do
- let(:params) { { confidential: true, noteable: issue } }
+ let(:params) { { internal: true, noteable: issue } }
shared_examples 'user allowed to set comment as confidential' do
it { expect(new_note.confidential).to be_truthy }
@@ -219,6 +219,14 @@ RSpec.describe Notes::BuildService do
it_behaves_like 'user not allowed to set comment as confidential'
end
+
+ context 'when using the deprecated `confidential` parameter' do
+ let(:params) { { internal: true, noteable: issue } }
+
+ shared_examples 'user allowed to set comment as confidential' do
+ it { expect(new_note.confidential).to be_truthy }
+ end
+ end
end
context 'when replying to a confidential comment' do
diff --git a/spec/services/notes/copy_service_spec.rb b/spec/services/notes/copy_service_spec.rb
index fd8802e6640..f146a49e929 100644
--- a/spec/services/notes/copy_service_spec.rb
+++ b/spec/services/notes/copy_service_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe Notes::CopyService do
context 'notes with upload' do
let(:uploader) { build(:file_uploader, project: from_noteable.project) }
- let(:text) { "Simple text with image: #{uploader.markdown_link} "}
+ let(:text) { "Simple text with image: #{uploader.markdown_link} " }
let!(:note) { create(:note, noteable: from_noteable, note: text, project: from_noteable.project) }
it 'rewrites note content correctly' do
@@ -146,8 +146,8 @@ RSpec.describe Notes::CopyService do
new_note = to_noteable.notes.first
aggregate_failures do
- expect(note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/)
- expect(new_note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/)
+ expect(note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/o)
+ expect(new_note.note).to match(/Simple text with image: #{FileUploader::MARKDOWN_PATTERN}/o)
expect(note.note).not_to eq(new_note.note)
expect(note.note_html).not_to eq(new_note.note_html)
end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 53b75a3c991..37318d76586 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -7,37 +7,74 @@ RSpec.describe Notes::CreateService do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
- let(:opts) do
- { note: 'Awesome comment', noteable_type: 'Issue', noteable_id: issue.id, confidential: true }
- end
+ let(:base_opts) { { note: 'Awesome comment', noteable_type: 'Issue', noteable_id: issue.id } }
+ let(:opts) { base_opts.merge(confidential: true) }
describe '#execute' do
+ subject(:note) { described_class.new(project, user, opts).execute }
+
before do
project.add_maintainer(user)
end
context "valid params" do
it 'returns a valid note' do
- note = described_class.new(project, user, opts).execute
-
expect(note).to be_valid
end
it 'returns a persisted note' do
- note = described_class.new(project, user, opts).execute
-
expect(note).to be_persisted
end
- it 'note has valid content' do
- note = described_class.new(project, user, opts).execute
+ context 'with internal parameter' do
+ context 'when confidential' do
+ let(:opts) { base_opts.merge(internal: true) }
+
+ it 'returns a confidential note' do
+ expect(note).to be_confidential
+ end
+ end
+
+ context 'when not confidential' do
+ let(:opts) { base_opts.merge(internal: false) }
+
+ it 'returns a confidential note' do
+ expect(note).not_to be_confidential
+ end
+ end
+ end
+
+ context 'with confidential parameter' do
+ context 'when confidential' do
+ let(:opts) { base_opts.merge(confidential: true) }
+
+ it 'returns a confidential note' do
+ expect(note).to be_confidential
+ end
+ end
+
+ context 'when not confidential' do
+ let(:opts) { base_opts.merge(confidential: false) }
+ it 'returns a confidential note' do
+ expect(note).not_to be_confidential
+ end
+ end
+ end
+
+ context 'with confidential and internal parameter set' do
+ let(:opts) { base_opts.merge(internal: true, confidential: false) }
+
+ it 'prefers the internal parameter' do
+ expect(note).to be_confidential
+ end
+ end
+
+ it 'note has valid content' do
expect(note.note).to eq(opts[:note])
end
it 'note belongs to the correct project' do
- note = described_class.new(project, user, opts).execute
-
expect(note.project).to eq(project)
end
@@ -60,8 +97,6 @@ RSpec.describe Notes::CreateService do
end
context 'issue is an incident' do
- subject { described_class.new(project, user, opts).execute }
-
let(:issue) { create(:incident, project: project) }
it_behaves_like 'an incident management tracked event', :incident_management_incident_comment do
@@ -69,20 +104,31 @@ RSpec.describe Notes::CreateService do
end
end
- it 'tracks issue comment usage data', :clean_gitlab_redis_shared_state do
- event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_ADDED
- counter = Gitlab::UsageDataCounters::HLLRedisCounter
+ describe 'event tracking', :snowplow do
+ let(:event) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_ADDED }
+ let(:execute_create_service) { described_class.new(project, user, opts).execute }
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_added_action).with(author: user).and_call_original
- expect do
- described_class.new(project, user, opts).execute
- end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
- end
+ it 'tracks issue comment usage data', :clean_gitlab_redis_shared_state do
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
+
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_added_action)
+ .with(author: user, project: project)
+ .and_call_original
+ expect do
+ execute_create_service
+ end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ end
- it 'does not track merge request usage data' do
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_create_comment_action)
+ it 'does not track merge request usage data' do
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_create_comment_action)
- described_class.new(project, user, opts).execute
+ execute_create_service
+ end
+
+ it_behaves_like 'issue_edit snowplow tracking' do
+ let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_ADDED }
+ subject(:service_action) { execute_create_service }
+ end
end
context 'in a merge request' do
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index 55acdabef82..be95a4bb181 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -25,15 +25,25 @@ RSpec.describe Notes::DestroyService do
.to change { user.todos_pending_count }.from(1).to(0)
end
- it 'tracks issue comment removal usage data', :clean_gitlab_redis_shared_state do
- note = create(:note, project: project, noteable: issue)
- event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_REMOVED
- counter = Gitlab::UsageDataCounters::HLLRedisCounter
+ describe 'comment removed event tracking', :snowplow do
+ let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_REMOVED }
+ let(:note) { create(:note, project: project, noteable: issue) }
+ let(:service_action) { described_class.new(project, user).execute(note) }
+
+ it 'tracks issue comment removal usage data', :clean_gitlab_redis_shared_state do
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
+
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_removed_action)
+ .with(author: user, project: project)
+ .and_call_original
+ expect do
+ service_action
+ end.to change { counter.unique_events(event_names: property, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ end
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_removed_action).with(author: user).and_call_original
- expect do
- described_class.new(project, user).execute(note)
- end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ it_behaves_like 'issue_edit snowplow tracking' do
+ subject(:execute_service_action) { service_action }
+ end
end
it 'tracks merge request usage data' do
diff --git a/spec/services/notes/update_service_spec.rb b/spec/services/notes/update_service_spec.rb
index ae7bea30944..989ca7b8df1 100644
--- a/spec/services/notes/update_service_spec.rb
+++ b/spec/services/notes/update_service_spec.rb
@@ -47,21 +47,31 @@ RSpec.describe Notes::UpdateService do
end
end
- it 'does not track usage data when params is blank' do
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
- expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_edit_comment_action)
+ describe 'event tracking', :snowplow do
+ let(:event) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_EDITED }
- update_note({})
- end
+ it 'does not track usage data when params is blank' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_comment_edited_action)
+ expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter).not_to receive(:track_edit_comment_action)
- it 'tracks issue usage data', :clean_gitlab_redis_shared_state do
- event = Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_EDITED
- counter = Gitlab::UsageDataCounters::HLLRedisCounter
+ update_note({})
+ end
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_edited_action).with(author: user).and_call_original
- expect do
- update_note(note: 'new text')
- end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ it 'tracks issue usage data', :clean_gitlab_redis_shared_state do
+ counter = Gitlab::UsageDataCounters::HLLRedisCounter
+
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_comment_edited_action)
+ .with(author: user, project: project)
+ .and_call_original
+ expect do
+ update_note(note: 'new text')
+ end.to change { counter.unique_events(event_names: event, start_date: 1.day.ago, end_date: 1.day.from_now) }.by(1)
+ end
+
+ it_behaves_like 'issue_edit snowplow tracking' do
+ let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_COMMENT_EDITED }
+ subject(:service_action) { update_note(note: 'new text') }
+ end
end
context 'when note text was changed' do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 98fe8a40c61..935dcef1011 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2006,19 +2006,19 @@ RSpec.describe NotificationService, :mailer do
context 'participating' do
it_behaves_like 'participating by assignee notification' do
- let(:participant) { create(:user, username: 'user-participant')}
+ let(:participant) { create(:user, username: 'user-participant') }
let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end
it_behaves_like 'participating by note notification' do
- let(:participant) { create(:user, username: 'user-participant')}
+ let(:participant) { create(:user, username: 'user-participant') }
let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end
context 'by author' do
- let(:participant) { create(:user, username: 'user-participant')}
+ let(:participant) { create(:user, username: 'user-participant') }
before do
merge_request.author = participant
@@ -2657,45 +2657,6 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.review_requested_of_merge_request(merge_request, current_user, reviewer) }
end
end
-
- describe '#attention_requested_of_merge_request' do
- let_it_be(:current_user) { create(:user) }
- let_it_be(:reviewer) { create(:user) }
- let_it_be(:merge_request) { create(:merge_request, source_project: project, reviewers: [reviewer]) }
-
- it 'sends email to reviewer', :aggregate_failures do
- notification.attention_requested_of_merge_request(merge_request, current_user, reviewer)
-
- merge_request.reviewers.each { |reviewer| should_email(reviewer) }
- should_not_email(merge_request.author)
- should_not_email(@u_watcher)
- should_not_email(@u_participant_mentioned)
- should_not_email(@subscriber)
- should_not_email(@watcher_and_subscriber)
- should_not_email(@u_guest_watcher)
- should_not_email(@u_guest_custom)
- should_not_email(@u_custom_global)
- should_not_email(@unsubscriber)
- should_not_email(@u_participating)
- should_not_email(@u_disabled)
- should_not_email(@u_lazy_participant)
- end
-
- it 'adds "attention requested" reason' do
- notification.attention_requested_of_merge_request(merge_request, current_user, [reviewer])
-
- merge_request.reviewers.each do |reviewer|
- email = find_email_for(reviewer)
-
- expect(email).to have_header('X-GitLab-NotificationReason', NotificationReason::ATTENTION_REQUESTED)
- end
- end
-
- it_behaves_like 'project emails are disabled' do
- let(:notification_target) { merge_request }
- let(:notification_trigger) { notification.attention_requested_of_merge_request(merge_request, current_user, reviewer) }
- end
- end
end
describe 'Projects', :deliver_mails_inline do
diff --git a/spec/services/packages/composer/create_package_service_spec.rb b/spec/services/packages/composer/create_package_service_spec.rb
index b04a6c8382f..26429a7b5d9 100644
--- a/spec/services/packages/composer/create_package_service_spec.rb
+++ b/spec/services/packages/composer/create_package_service_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe Packages::Composer::CreatePackageService do
end
context 'belonging to another project' do
- let(:other_project) { create(:project)}
+ let(:other_project) { create(:project) }
let!(:other_package) { create(:composer_package, name: package_name, version: 'dev-master', project: other_project) }
it 'fails with an error' do
diff --git a/spec/services/packages/create_dependency_service_spec.rb b/spec/services/packages/create_dependency_service_spec.rb
index 55414ea68fe..f95e21cd045 100644
--- a/spec/services/packages/create_dependency_service_spec.rb
+++ b/spec/services/packages/create_dependency_service_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
RSpec.describe Packages::CreateDependencyService do
describe '#execute' do
- let_it_be(:namespace) {create(:namespace)}
+ let_it_be(:namespace) { create(:namespace) }
let_it_be(:version) { '1.0.1' }
let_it_be(:package_name) { "@#{namespace.path}/my-app" }
diff --git a/spec/services/packages/debian/extract_deb_metadata_service_spec.rb b/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
index ee3f3d179dc..66a9ca5f9e0 100644
--- a/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
+++ b/spec/services/packages/debian/extract_deb_metadata_service_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe Packages::Debian::ExtractDebMetadataService do
let(:file_name) { 'README.md' }
it 'raise error' do
- expect {subject.execute}.to raise_error(described_class::CommandFailedError, /is not a Debian format archive/i)
+ expect { subject.execute }.to raise_error(described_class::CommandFailedError, /is not a Debian format archive/i)
end
end
end
diff --git a/spec/services/packages/debian/extract_metadata_service_spec.rb b/spec/services/packages/debian/extract_metadata_service_spec.rb
index e3911dbbfe0..02c81ad1644 100644
--- a/spec/services/packages/debian/extract_metadata_service_spec.rb
+++ b/spec/services/packages/debian/extract_metadata_service_spec.rb
@@ -11,15 +11,10 @@ RSpec.describe Packages::Debian::ExtractMetadataService do
end
RSpec.shared_examples 'Test Debian ExtractMetadata Service' do |expected_file_type, expected_architecture, expected_fields|
- it "returns file_type #{expected_file_type.inspect}" do
+ it "returns file_type #{expected_file_type.inspect}, architecture #{expected_architecture.inspect} and fields #{expected_fields.nil? ? '' : 'including '}#{expected_fields.inspect}", :aggregate_failures do
expect(subject[:file_type]).to eq(expected_file_type)
- end
-
- it "returns architecture #{expected_architecture.inspect}" do
expect(subject[:architecture]).to eq(expected_architecture)
- end
- it "returns fields #{expected_fields.nil? ? '' : 'including '}#{expected_fields.inspect}" do
if expected_fields.nil?
expect(subject[:fields]).to be_nil
else
diff --git a/spec/services/packages/debian/parse_debian822_service_spec.rb b/spec/services/packages/debian/parse_debian822_service_spec.rb
index cad4e81f350..ff146fda250 100644
--- a/spec/services/packages/debian/parse_debian822_service_spec.rb
+++ b/spec/services/packages/debian/parse_debian822_service_spec.rb
@@ -102,7 +102,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
let(:input) { ' continuation' }
it 'raise error' do
- expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, 'Parse error. Unexpected continuation line')
+ expect { subject.execute }.to raise_error(described_class::InvalidDebian822Error, 'Parse error. Unexpected continuation line')
end
end
@@ -116,7 +116,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
end
it 'raise error' do
- expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, "Duplicate field 'Source' in section 'Package: libsample0'")
+ expect { subject.execute }.to raise_error(described_class::InvalidDebian822Error, "Duplicate field 'Source' in section 'Package: libsample0'")
end
end
@@ -128,7 +128,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
end
it 'raise error' do
- expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, 'Parse error on line Hello')
+ expect { subject.execute }.to raise_error(described_class::InvalidDebian822Error, 'Parse error on line Hello')
end
end
@@ -142,7 +142,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
end
it 'raise error' do
- expect {subject.execute}.to raise_error(described_class::InvalidDebian822Error, "Duplicate section 'Package: libsample0'")
+ expect { subject.execute }.to raise_error(described_class::InvalidDebian822Error, "Duplicate section 'Package: libsample0'")
end
end
end
diff --git a/spec/services/packages/debian/sign_distribution_service_spec.rb b/spec/services/packages/debian/sign_distribution_service_spec.rb
index 2aec0e50636..fc070b6e45e 100644
--- a/spec/services/packages/debian/sign_distribution_service_spec.rb
+++ b/spec/services/packages/debian/sign_distribution_service_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Packages::Debian::SignDistributionService do
end
context 'with an existing key' do
- let!(:key) { create("debian_#{container_type}_distribution_key", distribution: distribution)}
+ let!(:key) { create("debian_#{container_type}_distribution_key", distribution: distribution) }
it 'returns the content signed', :aggregate_failures do
expect(Packages::Debian::GenerateDistributionKeyService).not_to receive(:new)
diff --git a/spec/services/packages/helm/process_file_service_spec.rb b/spec/services/packages/helm/process_file_service_spec.rb
index d22c1de2335..1be0153a4a5 100644
--- a/spec/services/packages/helm/process_file_service_spec.rb
+++ b/spec/services/packages/helm/process_file_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Packages::Helm::ProcessFileService do
- let(:package) { create(:helm_package, without_package_files: true, status: 'processing')}
+ let(:package) { create(:helm_package, without_package_files: true, status: 'processing') }
let!(:package_file) { create(:helm_package_file, without_loaded_metadatum: true, package: package) }
let(:channel) { 'stable' }
let(:service) { described_class.new(channel, package_file) }
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index 5b41055397b..a3e59913918 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Packages::Npm::CreatePackageService do
- let(:namespace) {create(:namespace)}
+ let(:namespace) { create(:namespace) }
let(:project) { create(:project, namespace: namespace) }
let(:user) { create(:user) }
let(:version) { '1.0.1' }
@@ -129,7 +129,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
end
describe 'max file size validation' do
- let(:max_file_size) { 5.bytes}
+ let(:max_file_size) { 5.bytes }
shared_examples_for 'max file size validation failure' do
it 'returns a 400 error', :aggregate_failures do
@@ -160,7 +160,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
end
context "when encoded package data is padded with '='" do
- let(:max_file_size) { 4.bytes}
+ let(:max_file_size) { 4.bytes }
# 'Hello' (size = 5 bytes) => 'SGVsbG8='
let(:encoded_package_data) { 'SGVsbG8=' }
@@ -168,7 +168,7 @@ RSpec.describe Packages::Npm::CreatePackageService do
end
context "when encoded package data is padded with '=='" do
- let(:max_file_size) { 3.bytes}
+ let(:max_file_size) { 3.bytes }
# 'Hell' (size = 4 bytes) => 'SGVsbA=='
let(:encoded_package_data) { 'SGVsbA==' }
diff --git a/spec/services/packages/npm/create_tag_service_spec.rb b/spec/services/packages/npm/create_tag_service_spec.rb
index e7a784068fa..a4b07bf97cc 100644
--- a/spec/services/packages/npm/create_tag_service_spec.rb
+++ b/spec/services/packages/npm/create_tag_service_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Packages::Npm::CreateTagService do
shared_examples 'it creates the tag' do
it { expect { subject }.to change { Packages::Tag.count }.by(1) }
it { expect(subject.name).to eq(tag_name) }
+
it 'adds tag to the package' do
tag = subject
expect(package.reload.tags).to match_array([tag])
diff --git a/spec/services/packages/rubygems/dependency_resolver_service_spec.rb b/spec/services/packages/rubygems/dependency_resolver_service_spec.rb
index f23ed0e5fbc..bb84e0cd361 100644
--- a/spec/services/packages/rubygems/dependency_resolver_service_spec.rb
+++ b/spec/services/packages/rubygems/dependency_resolver_service_spec.rb
@@ -47,9 +47,9 @@ RSpec.describe Packages::Rubygems::DependencyResolverService do
end
context 'package with dependencies' do
- let(:dependency_link) { create(:packages_dependency_link, :rubygems, package: package)}
- let(:dependency_link2) { create(:packages_dependency_link, :rubygems, package: package)}
- let(:dependency_link3) { create(:packages_dependency_link, :rubygems, package: package)}
+ let(:dependency_link) { create(:packages_dependency_link, :rubygems, package: package) }
+ let(:dependency_link2) { create(:packages_dependency_link, :rubygems, package: package) }
+ let(:dependency_link3) { create(:packages_dependency_link, :rubygems, package: package) }
it 'returns a set of dependencies' do
expected_result = [{
@@ -68,11 +68,11 @@ RSpec.describe Packages::Rubygems::DependencyResolverService do
end
context 'package with multiple versions' do
- let(:dependency_link) { create(:packages_dependency_link, :rubygems, package: package)}
- let(:dependency_link2) { create(:packages_dependency_link, :rubygems, package: package)}
- let(:dependency_link3) { create(:packages_dependency_link, :rubygems, package: package)}
+ let(:dependency_link) { create(:packages_dependency_link, :rubygems, package: package) }
+ let(:dependency_link2) { create(:packages_dependency_link, :rubygems, package: package) }
+ let(:dependency_link3) { create(:packages_dependency_link, :rubygems, package: package) }
let(:package2) { create(:package, project: project, name: package.name, version: '9.9.9') }
- let(:dependency_link4) { create(:packages_dependency_link, :rubygems, package: package2)}
+ let(:dependency_link4) { create(:packages_dependency_link, :rubygems, package: package2) }
it 'returns a set of dependencies' do
expected_result = [{
diff --git a/spec/services/pages/delete_service_spec.rb b/spec/services/pages/delete_service_spec.rb
index 29d9a47c72e..8b9e72ac9b1 100644
--- a/spec/services/pages/delete_service_spec.rb
+++ b/spec/services/pages/delete_service_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Pages::DeleteService do
let_it_be(:admin) { create(:admin) }
- let(:project) { create(:project, path: "my.project")}
- let(:service) { described_class.new(project, admin)}
+ let(:project) { create(:project, path: "my.project") }
+ let(:service) { described_class.new(project, admin) }
before do
project.mark_pages_as_deployed
diff --git a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
index 79654c9b190..ecb445fa441 100644
--- a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
+++ b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
@@ -135,7 +135,7 @@ RSpec.describe PagesDomains::ObtainLetsEncryptCertificateService do
cert.add_extension ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")
- cert.sign key, OpenSSL::Digest.new('SHA1')
+ cert.sign key, OpenSSL::Digest.new('SHA256')
cert.to_pem
end
diff --git a/spec/services/personal_access_tokens/revoke_service_spec.rb b/spec/services/personal_access_tokens/revoke_service_spec.rb
index a25484e218e..f16b6f00a0a 100644
--- a/spec/services/personal_access_tokens/revoke_service_spec.rb
+++ b/spec/services/personal_access_tokens/revoke_service_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe PersonalAccessTokens::RevokeService do
shared_examples_for 'a successfully revoked token' do
it { expect(subject.success?).to be true }
it { expect(service.token.revoked?).to be true }
+
it 'logs the event' do
expect(Gitlab::AppLogger).to receive(:info).with(/PAT REVOCATION: revoked_by: '#{current_user.username}', revoked_for: '#{token.user.username}', token_id: '\d+'/)
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index 9dc15131bc5..edf4bbe0f7f 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
RSpec.describe Projects::AfterRenameService do
- let(:rugged_config) { rugged_repo(project.repository).config }
let(:legacy_storage) { Storage::LegacyProject.new(project) }
let(:hashed_storage) { Storage::Hashed.new(project) }
let!(:path_before_rename) { project.path }
@@ -71,10 +70,10 @@ RSpec.describe Projects::AfterRenameService do
end
end
- it 'updates project full path in .git/config' do
+ it 'updates project full path in gitaly' do
service_execute
- expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
+ expect(project.repository.full_path).to eq(project.full_path)
end
it 'updates storage location' do
@@ -173,10 +172,10 @@ RSpec.describe Projects::AfterRenameService do
end
end
- it 'updates project full path in .git/config' do
+ it 'updates project full path in gitaly' do
service_execute
- expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
+ expect(project.repository.full_path).to eq(project.full_path)
end
it 'updates storage location' do
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb
index feae8f3967c..aa2ef39bf98 100644
--- a/spec/services/projects/alerting/notify_service_spec.rb
+++ b/spec/services/projects/alerting/notify_service_spec.rb
@@ -56,6 +56,7 @@ RSpec.describe Projects::Alerting::NotifyService do
it_behaves_like 'processes new firing alert'
it_behaves_like 'properly assigns the alert properties'
+ include_examples 'handles race condition in alert creation'
it 'passes the integration to alert processing' do
expect(Gitlab::AlertManagement::Payload)
@@ -118,10 +119,10 @@ RSpec.describe Projects::Alerting::NotifyService do
end
context 'with overlong payload' do
- let(:deep_size_object) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
+ let(:payload_raw) { { 'the-payload-is-too-big' => true } }
before do
- allow(Gitlab::Utils::DeepSize).to receive(:new).and_return(deep_size_object)
+ stub_const('::Gitlab::Utils::DeepSize::DEFAULT_MAX_DEPTH', 0)
end
it_behaves_like 'alerts service responds with an error and takes no actions', :bad_request
diff --git a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
index 22cada7816b..4de36452684 100644
--- a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe Projects::ContainerRepository::ThirdParty::DeleteTagsService do
stub_put_manifest_request('Ba', 500, {})
end
- it { is_expected.to eq(status: :error, message: "could not delete tags: #{tags.join(', ')}")}
+ it { is_expected.to eq(status: :error, message: "could not delete tags: #{tags.join(', ')}") }
context 'when a large list of tag updates fails' do
let(:tags) { Array.new(1000) { |i| "tag_#{i}" } }
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 59dee209ff9..e112c1e2497 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
RSpec.describe Projects::CreateService, '#execute' do
include ExternalAuthorizationServiceHelpers
- include GitHelpers
let(:user) { create :user }
let(:project_name) { 'GitLab' }
@@ -254,6 +253,39 @@ RSpec.describe Projects::CreateService, '#execute' do
end
end
+ context 'user with project limit' do
+ let_it_be(:user_with_projects_limit) { create(:user, projects_limit: 0) }
+
+ let(:params) { opts.merge!(namespace_id: target_namespace.id) }
+
+ subject(:project) { create_project(user_with_projects_limit, params) }
+
+ context 'under personal namespace' do
+ let(:target_namespace) { user_with_projects_limit.namespace }
+
+ it 'cannot create a project' do
+ expect(project.errors.errors.length).to eq 1
+ expect(project.errors.messages[:limit_reached].first).to eq(_('Personal project creation is not allowed. Please contact your administrator with questions'))
+ end
+ end
+
+ context 'under group namespace' do
+ let_it_be(:group) do
+ create(:group).tap do |group|
+ group.add_owner(user_with_projects_limit)
+ end
+ end
+
+ let(:target_namespace) { group }
+
+ it 'can create a project' do
+ expect(project).to be_valid
+ expect(project).to be_saved
+ expect(project.errors.errors.length).to eq 0
+ end
+ end
+ end
+
context 'membership overrides', :sidekiq_inline do
let_it_be(:group) { create(:group, :private) }
let_it_be(:subgroup_for_projects) { create(:group, :private, parent: group) }
@@ -769,11 +801,10 @@ RSpec.describe Projects::CreateService, '#execute' do
create_project(user, opts)
end
- it 'writes project full path to .git/config' do
+ it 'writes project full path to gitaly' do
project = create_project(user, opts)
- rugged = rugged_repo(project.repository)
- expect(rugged.config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.full_path).to eq project.full_path
end
it 'triggers PostCreationWorker' do
diff --git a/spec/services/projects/enable_deploy_key_service_spec.rb b/spec/services/projects/enable_deploy_key_service_spec.rb
index f297ec374cf..c0b3992037e 100644
--- a/spec/services/projects/enable_deploy_key_service_spec.rb
+++ b/spec/services/projects/enable_deploy_key_service_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::EnableDeployKeyService do
let(:deploy_key) { create(:deploy_key, public: true) }
let(:project) { create(:project) }
- let(:user) { project.creator}
+ let(:user) { project.creator }
let!(:params) { { key_id: deploy_key.id } }
it 'enables the key' do
diff --git a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
index d0064873972..65da1976dc2 100644
--- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
+++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
@@ -68,12 +68,10 @@ RSpec.describe Projects::HashedStorage::MigrateRepositoryService do
service.execute
end
- it 'writes project full path to .git/config' do
+ it 'writes project full path to gitaly' do
service.execute
- rugged_config = rugged_repo(project.repository).config['gitlab.fullpath']
-
- expect(rugged_config).to eq project.full_path
+ expect(project.repository.full_path).to eq project.full_path
end
end
diff --git a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb
index 23e776b72bc..385c03e6308 100644
--- a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb
+++ b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab_redis_shared_state do
- include GitHelpers
-
let(:gitlab_shell) { Gitlab::Shell.new }
let(:project) { create(:project, :repository, :wiki_repo, :design_repo, storage_version: ::Project::HASHED_STORAGE_FEATURES[:repository]) }
let(:legacy_storage) { Storage::LegacyProject.new(project) }
@@ -68,12 +66,10 @@ RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab
service.execute
end
- it 'writes project full path to .git/config' do
+ it 'writes project full path to gitaly' do
service.execute
- rugged_config = rugged_repo(project.repository).config['gitlab.fullpath']
-
- expect(rugged_config).to eq project.full_path
+ expect(project.repository.full_path).to eq project.full_path
end
end
diff --git a/spec/services/projects/import_export/export_service_spec.rb b/spec/services/projects/import_export/export_service_spec.rb
index 54abbc04084..285687505e9 100644
--- a/spec/services/projects/import_export/export_service_spec.rb
+++ b/spec/services/projects/import_export/export_service_spec.rb
@@ -89,7 +89,21 @@ RSpec.describe Projects::ImportExport::ExportService do
context 'when all saver services succeed' do
before do
- allow(service).to receive(:save_services).and_return(true)
+ allow(service).to receive(:save_exporters).and_return(true)
+ end
+
+ it 'logs a successful message' do
+ allow(Gitlab::ImportExport::Saver).to receive(:save).and_return(true)
+
+ expect(service.instance_variable_get(:@logger)).to receive(:info).ordered.with(
+ hash_including({ message: 'Project export started', project_id: project.id })
+ )
+
+ expect(service.instance_variable_get(:@logger)).to receive(:info).ordered.with(
+ hash_including({ message: 'Project successfully exported', project_id: project.id })
+ )
+
+ service.execute
end
it 'saves the project in the file system' do
@@ -111,6 +125,7 @@ RSpec.describe Projects::ImportExport::ExportService do
end
it 'calls the after export strategy' do
+ allow(Gitlab::ImportExport::Saver).to receive(:save).and_return(true)
expect(after_export_strategy).to receive(:execute)
service.execute(after_export_strategy)
@@ -119,7 +134,7 @@ RSpec.describe Projects::ImportExport::ExportService do
context 'when after export strategy fails' do
before do
allow(after_export_strategy).to receive(:execute).and_return(false)
- expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
+ allow(Gitlab::ImportExport::Saver).to receive(:save).and_return(true)
end
after do
@@ -140,7 +155,9 @@ RSpec.describe Projects::ImportExport::ExportService do
end
it 'notifies logger' do
- expect(service.instance_variable_get(:@logger)).to receive(:error)
+ expect(service.instance_variable_get(:@logger)).to receive(:error).with(
+ hash_including({ message: 'Project export error', project_id: project.id })
+ )
end
end
end
diff --git a/spec/services/projects/import_export/relation_export_service_spec.rb b/spec/services/projects/import_export/relation_export_service_spec.rb
new file mode 100644
index 00000000000..94f5653ee7d
--- /dev/null
+++ b/spec/services/projects/import_export/relation_export_service_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ImportExport::RelationExportService do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:service) { described_class.new(relation_export, 'jid') }
+
+ let_it_be(:project_export_job) { create(:project_export_job) }
+ let_it_be(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
+ let_it_be(:archive_path) { "#{Dir.tmpdir}/project_archive_spec" }
+
+ let(:relation_export) { create(:project_relation_export, relation: relation, project_export_job: project_export_job) }
+
+ before do
+ stub_uploads_object_storage(ImportExportUploader, enabled: false)
+
+ allow(project_export_job.project.import_export_shared).to receive(:export_path).and_return(export_path)
+ allow(project_export_job.project.import_export_shared).to receive(:archive_path).and_return(archive_path)
+ allow(FileUtils).to receive(:remove_entry).with(any_args).and_call_original
+ end
+
+ describe '#execute' do
+ let(:relation) { 'labels' }
+
+ it 'removes temporary paths used to export files' do
+ expect(FileUtils).to receive(:remove_entry).with(export_path)
+ expect(FileUtils).to receive(:remove_entry).with(archive_path)
+
+ service.execute
+ end
+
+ context 'when saver fails to export relation' do
+ before do
+ allow_next_instance_of(Gitlab::ImportExport::Project::RelationSaver) do |saver|
+ allow(saver).to receive(:save).and_return(false)
+ end
+ end
+
+ it 'flags export as failed' do
+ service.execute
+
+ expect(relation_export.failed?).to eq(true)
+ end
+
+ it 'logs failed message' do
+ expect_next_instance_of(Gitlab::Export::Logger) do |logger|
+ expect(logger).to receive(:error).with(
+ export_error: '',
+ message: 'Project relation export failed',
+ project_export_job_id: project_export_job.id,
+ project_id: project_export_job.project.id,
+ project_name: project_export_job.project.name
+ )
+ end
+
+ service.execute
+ end
+ end
+
+ context 'when an exception is raised' do
+ before do
+ allow_next_instance_of(Gitlab::ImportExport::Project::RelationSaver) do |saver|
+ allow(saver).to receive(:save).and_raise('Error!')
+ end
+ end
+
+ it 'flags export as failed' do
+ service.execute
+
+ expect(relation_export.failed?).to eq(true)
+ expect(relation_export.export_error).to eq('Error!')
+ end
+
+ it 'logs exception error message' do
+ expect_next_instance_of(Gitlab::Export::Logger) do |logger|
+ expect(logger).to receive(:error).with(
+ export_error: 'Error!',
+ message: 'Project relation export failed',
+ project_export_job_id: project_export_job.id,
+ project_id: project_export_job.project.id,
+ project_name: project_export_job.project.name
+ )
+ end
+
+ service.execute
+ end
+ end
+
+ describe 'relation name and saver class' do
+ where(:relation_name, :saver) do
+ Projects::ImportExport::RelationExport::UPLOADS_RELATION | Gitlab::ImportExport::UploadsSaver
+ Projects::ImportExport::RelationExport::REPOSITORY_RELATION | Gitlab::ImportExport::RepoSaver
+ Projects::ImportExport::RelationExport::WIKI_REPOSITORY_RELATION | Gitlab::ImportExport::WikiRepoSaver
+ Projects::ImportExport::RelationExport::LFS_OBJECTS_RELATION | Gitlab::ImportExport::LfsSaver
+ Projects::ImportExport::RelationExport::SNIPPETS_REPOSITORY_RELATION | Gitlab::ImportExport::SnippetsRepoSaver
+ Projects::ImportExport::RelationExport::DESIGN_REPOSITORY_RELATION | Gitlab::ImportExport::DesignRepoSaver
+ Projects::ImportExport::RelationExport::ROOT_RELATION | Gitlab::ImportExport::Project::RelationSaver
+ 'labels' | Gitlab::ImportExport::Project::RelationSaver
+ end
+
+ with_them do
+ let(:relation) { relation_name }
+
+ it 'exports relation using correct saver' do
+ expect(saver).to receive(:new).and_call_original
+
+ service.execute
+ end
+
+ it 'assigns finished status and relation file' do
+ service.execute
+
+ expect(relation_export.finished?).to eq(true)
+ expect(relation_export.upload.export_file.filename).to eq("#{relation}.tar.gz")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
index 047ebe65dff..d472d6493c3 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Projects::LfsPointers::LfsDownloadLinkListService do
let(:lfs_endpoint) { "#{import_url}/info/lfs/objects/batch" }
let!(:project) { create(:project, import_url: import_url) }
let(:new_oids) { { 'oid1' => 123, 'oid2' => 125 } }
- let(:headers) { { 'X-Some-Header' => '456' }}
+ let(:headers) { { 'X-Some-Header' => '456' } }
let(:remote_uri) { URI.parse(lfs_endpoint) }
let(:request_object) { HTTParty::Request.new(Net::HTTP::Post, '/') }
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index 04c6349bf52..b67b4d64c1d 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -250,7 +250,7 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
end
context 'that is not blocked' do
- let(:redirect_link) { "http://example.com/"}
+ let(:redirect_link) { "http://example.com/" }
before do
stub_full_request(download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
diff --git a/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
index 981d7027a17..adcc2b85706 100644
--- a/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
@@ -3,8 +3,8 @@ require 'spec_helper'
RSpec.describe Projects::LfsPointers::LfsObjectDownloadListService do
let(:import_url) { 'http://www.gitlab.com/demo/repo.git' }
- let(:default_endpoint) { "#{import_url}/info/lfs/objects/batch"}
- let(:group) { create(:group, lfs_enabled: true)}
+ let(:default_endpoint) { "#{import_url}/info/lfs/objects/batch" }
+ let(:group) { create(:group, lfs_enabled: true) }
let!(:project) { create(:project, namespace: group, import_url: import_url, lfs_enabled: true) }
let!(:lfs_objects_project) { create_list(:lfs_objects_project, 2, project: project) }
let!(:existing_lfs_objects) { LfsObject.pluck(:oid, :size).to_h }
@@ -75,7 +75,7 @@ RSpec.describe Projects::LfsPointers::LfsObjectDownloadListService do
end
context 'when import url has credentials' do
- let(:import_url) { 'http://user:password@www.gitlab.com/demo/repo.git'}
+ let(:import_url) { 'http://user:password@www.gitlab.com/demo/repo.git' }
it 'adds the credentials to the new endpoint' do
expect(Projects::LfsPointers::LfsDownloadLinkListService)
diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb
index 61edfd23700..fc745cd669f 100644
--- a/spec/services/projects/participants_service_spec.rb
+++ b/spec/services/projects/participants_service_spec.rb
@@ -107,7 +107,7 @@ RSpec.describe Projects::ParticipantsService do
shared_examples 'return project members' do
context 'when there is a project in group namespace' do
let_it_be(:public_group) { create(:group, :public) }
- let_it_be(:public_project) { create(:project, :public, namespace: public_group)}
+ let_it_be(:public_project) { create(:project, :public, namespace: public_group) }
let_it_be(:public_group_owner) { create(:user) }
@@ -125,9 +125,9 @@ RSpec.describe Projects::ParticipantsService do
context 'when there is a private group and a public project' do
let_it_be(:public_group) { create(:group, :public) }
let_it_be(:private_group) { create(:group, :private, :nested) }
- let_it_be(:public_project) { create(:project, :public, namespace: public_group)}
+ let_it_be(:public_project) { create(:project, :public, namespace: public_group) }
- let_it_be(:project_issue) { create(:issue, project: public_project)}
+ let_it_be(:project_issue) { create(:issue, project: public_project) }
let_it_be(:public_group_owner) { create(:user) }
let_it_be(:private_group_member) { create(:user) }
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index 6f760e6dbfa..7bf6dfd0fd8 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -177,6 +177,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
it { is_expected.to be_success }
+
include_examples 'does not send alert notification emails'
include_examples 'does not process incident issues'
end
@@ -187,6 +188,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
it { is_expected.to be_success }
+
include_examples 'does not send alert notification emails'
end
@@ -196,6 +198,7 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
it { is_expected.to be_success }
+
include_examples 'does not process incident issues'
end
end
@@ -313,11 +316,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
end
context 'when the payload is too big' do
- let(:payload) { { 'the-payload-is-too-big' => true } }
- let(:deep_size_object) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
+ let(:payload_raw) { { 'the-payload-is-too-big' => true } }
+ let(:payload) { ActionController::Parameters.new(payload_raw).permit! }
before do
- allow(Gitlab::Utils::DeepSize).to receive(:new).and_return(deep_size_object)
+ stub_const('::Gitlab::Utils::DeepSize::DEFAULT_MAX_DEPTH', 0)
end
it_behaves_like 'alerts service responds with an error and takes no actions', :bad_request
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index ecf9f92d74f..8f505c31c5a 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe Projects::TransferService do
- include GitHelpers
-
let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') }
@@ -64,6 +62,30 @@ RSpec.describe Projects::TransferService do
expect(project.namespace).to eq(group)
end
+ context 'EventStore' do
+ let(:group) do
+ create(:group, :nested).tap { |g| g.add_owner(user) }
+ end
+
+ let(:target) do
+ create(:group, :nested).tap { |g| g.add_owner(user) }
+ end
+
+ let(:project) { create(:project, namespace: group) }
+
+ it 'publishes a ProjectTransferedEvent' do
+ expect { execute_transfer }
+ .to publish_event(Projects::ProjectTransferedEvent)
+ .with(
+ project_id: project.id,
+ old_namespace_id: group.id,
+ old_root_namespace_id: group.root_ancestor.id,
+ new_namespace_id: target.id,
+ new_root_namespace_id: target.root_ancestor.id
+ )
+ end
+ end
+
context 'when project has an associated project namespace' do
it 'keeps project namespace in sync with project' do
transfer_result = execute_transfer
@@ -178,10 +200,10 @@ RSpec.describe Projects::TransferService do
expect(project.disk_path).to start_with(group.path)
end
- it 'updates project full path in .git/config' do
+ it 'updates project full path in gitaly' do
execute_transfer
- expect(rugged_config['gitlab.fullpath']).to eq "#{group.full_path}/#{project.path}"
+ expect(project.repository.full_path).to eq "#{group.full_path}/#{project.path}"
end
it 'updates storage location' do
@@ -272,10 +294,10 @@ RSpec.describe Projects::TransferService do
expect(original_path).to eq current_path
end
- it 'rolls back project full path in .git/config' do
+ it 'rolls back project full path in gitaly' do
attempt_project_transfer
- expect(rugged_config['gitlab.fullpath']).to eq project.full_path
+ expect(project.repository.full_path).to eq project.full_path
end
it "doesn't send move notifications" do
@@ -299,6 +321,11 @@ RSpec.describe Projects::TransferService do
)
end
+ it 'does not publish a ProjectTransferedEvent' do
+ expect { attempt_project_transfer }
+ .not_to publish_event(Projects::ProjectTransferedEvent)
+ end
+
context 'when project has pending builds', :sidekiq_inline do
let!(:other_project) { create(:project) }
let!(:pending_build) { create(:ci_pending_build, project: project.reload) }
@@ -741,10 +768,6 @@ RSpec.describe Projects::TransferService do
end
end
- def rugged_config
- rugged_repo(project.repository).config
- end
-
def project_namespace_in_sync(group)
project.reload
expect(project.namespace).to eq(group)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index ca838be0fa8..85d3e99109d 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -348,6 +348,18 @@ RSpec.describe Projects::UpdateService do
end
end
+ context 'when archiving a project' do
+ it 'publishes a ProjectTransferedEvent' do
+ expect { update_project(project, user, archived: true) }
+ .to publish_event(Projects::ProjectArchivedEvent)
+ .with(
+ project_id: project.id,
+ namespace_id: project.namespace_id,
+ root_namespace_id: project.root_namespace.id
+ )
+ end
+ end
+
context 'when changing operations feature visibility' do
let(:feature_params) { { operations_access_level: ProjectFeature::DISABLED } }
diff --git a/spec/services/projects/update_statistics_service_spec.rb b/spec/services/projects/update_statistics_service_spec.rb
index 6987185b549..1cc69e7e2fe 100644
--- a/spec/services/projects/update_statistics_service_spec.rb
+++ b/spec/services/projects/update_statistics_service_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::UpdateStatisticsService do
using RSpec::Parameterized::TableSyntax
- let(:service) { described_class.new(project, nil, statistics: statistics)}
+ let(:service) { described_class.new(project, nil, statistics: statistics) }
let(:statistics) { %w(repository_size) }
describe '#execute' do
diff --git a/spec/services/protected_branches/cache_service_spec.rb b/spec/services/protected_branches/cache_service_spec.rb
new file mode 100644
index 00000000000..4fa7553c23d
--- /dev/null
+++ b/spec/services/protected_branches/cache_service_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+# rubocop:disable Style/RedundantFetchBlock
+#
+require 'spec_helper'
+
+RSpec.describe ProtectedBranches::CacheService, :clean_gitlab_redis_cache do
+ subject(:service) { described_class.new(project, user) }
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.first_owner }
+
+ let(:immediate_expiration) { 0 }
+
+ describe '#fetch' do
+ it 'caches the value' do
+ expect(service.fetch('main') { true }).to eq(true)
+ expect(service.fetch('not-found') { false }).to eq(false)
+
+ # Uses cached values
+ expect(service.fetch('main') { false }).to eq(true)
+ expect(service.fetch('not-found') { true }).to eq(false)
+ end
+
+ it 'sets expiry on the key' do
+ stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
+
+ expect(service.fetch('main') { true }).to eq(true)
+ expect(service.fetch('not-found') { false }).to eq(false)
+
+ expect(service.fetch('main') { false }).to eq(false)
+ expect(service.fetch('not-found') { true }).to eq(true)
+ end
+
+ it 'does not set an expiry on the key after the hash is already created' do
+ expect(service.fetch('main') { true }).to eq(true)
+
+ stub_const("#{described_class.name}::CACHE_EXPIRE_IN", immediate_expiration)
+
+ expect(service.fetch('not-found') { false }).to eq(false)
+
+ expect(service.fetch('main') { false }).to eq(true)
+ expect(service.fetch('not-found') { true }).to eq(false)
+ end
+
+ context 'when CACHE_LIMIT is exceeded' do
+ before do
+ stub_const("#{described_class.name}::CACHE_LIMIT", 2)
+ end
+
+ it 'recreates cache' do
+ expect(service.fetch('main') { true }).to eq(true)
+ expect(service.fetch('not-found') { false }).to eq(false)
+
+ # Uses cached values
+ expect(service.fetch('main') { false }).to eq(true)
+ expect(service.fetch('not-found') { true }).to eq(false)
+
+ # Overflow
+ expect(service.fetch('new-branch') { true }).to eq(true)
+
+ # Refreshes values
+ expect(service.fetch('main') { false }).to eq(false)
+ expect(service.fetch('not-found') { true }).to eq(true)
+ end
+ end
+
+ context 'when dry_run is on' do
+ it 'does not use cached value' do
+ expect(service.fetch('main', dry_run: true) { true }).to eq(true)
+ expect(service.fetch('main', dry_run: true) { false }).to eq(false)
+ end
+
+ context 'when cache mismatch' do
+ it 'logs an error' do
+ expect(service.fetch('main', dry_run: true) { true }).to eq(true)
+
+ expect(Gitlab::AppLogger).to receive(:error).with(
+ 'class' => described_class.name,
+ 'message' => /Cache mismatch/,
+ 'project_id' => project.id,
+ 'project_path' => project.full_path
+ )
+
+ expect(service.fetch('main', dry_run: true) { false }).to eq(false)
+ end
+ end
+
+ context 'when cache matches' do
+ it 'does not log an error' do
+ expect(service.fetch('main', dry_run: true) { true }).to eq(true)
+
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect(service.fetch('main', dry_run: true) { true }).to eq(true)
+ end
+ end
+ end
+ end
+
+ describe '#refresh' do
+ it 'clears cached values' do
+ expect(service.fetch('main') { true }).to eq(true)
+ expect(service.fetch('not-found') { false }).to eq(false)
+
+ service.refresh
+
+ # Recreates cache
+ expect(service.fetch('main') { false }).to eq(false)
+ expect(service.fetch('not-found') { true }).to eq(true)
+ end
+ end
+end
+# rubocop:enable Style/RedundantFetchBlock
diff --git a/spec/services/protected_branches/create_service_spec.rb b/spec/services/protected_branches/create_service_spec.rb
index 3ac42d41377..b42524e761c 100644
--- a/spec/services/protected_branches/create_service_spec.rb
+++ b/spec/services/protected_branches/create_service_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe ProtectedBranches::CreateService do
- let(:project) { create(:project) }
+ let_it_be_with_reload(:project) { create(:project) }
+
let(:user) { project.first_owner }
let(:params) do
{
@@ -13,22 +14,28 @@ RSpec.describe ProtectedBranches::CreateService do
}
end
+ subject(:service) { described_class.new(project, user, params) }
+
describe '#execute' do
let(:name) { 'master' }
- subject(:service) { described_class.new(project, user, params) }
-
it 'creates a new protected branch' do
expect { service.execute }.to change(ProtectedBranch, :count).by(1)
expect(project.protected_branches.last.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::MAINTAINER])
expect(project.protected_branches.last.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MAINTAINER])
end
+ it 'refreshes the cache' do
+ expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
+ expect(cache_service).to receive(:refresh)
+ end
+
+ service.execute
+ end
+
context 'when protecting a branch with a name that contains HTML tags' do
let(:name) { 'foo<b>bar<\b>' }
- subject(:service) { described_class.new(project, user, params) }
-
it 'creates a new protected branch' do
expect { service.execute }.to change(ProtectedBranch, :count).by(1)
expect(project.protected_branches.last.name).to eq(name)
@@ -52,16 +59,18 @@ RSpec.describe ProtectedBranches::CreateService do
end
context 'when a policy restricts rule creation' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- expect(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
-
it "prevents creation of the protected branch rule" do
+ disallow(:create_protected_branch, an_instance_of(ProtectedBranch))
+
expect do
service.execute
end.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
+
+ def disallow(ability, protected_branch)
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, ability, protected_branch).and_return(false)
+ end
end
diff --git a/spec/services/protected_branches/destroy_service_spec.rb b/spec/services/protected_branches/destroy_service_spec.rb
index 4e55c72f312..9fa07820148 100644
--- a/spec/services/protected_branches/destroy_service_spec.rb
+++ b/spec/services/protected_branches/destroy_service_spec.rb
@@ -3,30 +3,41 @@
require 'spec_helper'
RSpec.describe ProtectedBranches::DestroyService do
- let(:protected_branch) { create(:protected_branch) }
- let(:project) { protected_branch.project }
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:protected_branch) { create(:protected_branch, project: project) }
let(:user) { project.first_owner }
- describe '#execute' do
- subject(:service) { described_class.new(project, user) }
+ subject(:service) { described_class.new(project, user) }
+ describe '#execute' do
it 'destroys a protected branch' do
service.execute(protected_branch)
expect(protected_branch).to be_destroyed
end
- context 'when a policy restricts rule deletion' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- expect(ProtectedBranchPolicy).to receive(:new).and_return(policy)
+ it 'refreshes the cache' do
+ expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
+ expect(cache_service).to receive(:refresh)
end
+ service.execute(protected_branch)
+ end
+
+ context 'when a policy restricts rule deletion' do
it "prevents deletion of the protected branch rule" do
+ disallow(:destroy_protected_branch, protected_branch)
+
expect do
service.execute(protected_branch)
end.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
+
+ def disallow(ability, protected_branch)
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, ability, protected_branch).and_return(false)
+ end
end
diff --git a/spec/services/protected_branches/update_service_spec.rb b/spec/services/protected_branches/update_service_spec.rb
index 4405af35c37..c4fe4d78070 100644
--- a/spec/services/protected_branches/update_service_spec.rb
+++ b/spec/services/protected_branches/update_service_spec.rb
@@ -3,27 +3,34 @@
require 'spec_helper'
RSpec.describe ProtectedBranches::UpdateService do
- let(:protected_branch) { create(:protected_branch) }
- let(:project) { protected_branch.project }
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:protected_branch) { create(:protected_branch, project: project) }
let(:user) { project.first_owner }
let(:params) { { name: new_name } }
+ subject(:service) { described_class.new(project, user, params) }
+
describe '#execute' do
let(:new_name) { 'new protected branch name' }
let(:result) { service.execute(protected_branch) }
- subject(:service) { described_class.new(project, user, params) }
-
it 'updates a protected branch' do
expect(result.reload.name).to eq(params[:name])
end
+ it 'refreshes the cache' do
+ expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
+ expect(cache_service).to receive(:refresh)
+ end
+
+ result
+ end
+
context 'when updating name of a protected branch to one that contains HTML tags' do
let(:new_name) { 'foo<b>bar<\b>' }
let(:result) { service.execute(protected_branch) }
- subject(:service) { described_class.new(project, user, params) }
-
it 'updates a protected branch' do
expect(result.reload.name).to eq(new_name)
end
@@ -37,15 +44,17 @@ RSpec.describe ProtectedBranches::UpdateService do
end
end
- context 'when a policy restricts rule creation' do
- before do
- policy = instance_double(ProtectedBranchPolicy, allowed?: false)
- expect(ProtectedBranchPolicy).to receive(:new).and_return(policy)
- end
+ context 'when a policy restricts rule update' do
+ it "prevents update of the protected branch rule" do
+ disallow(:update_protected_branch, protected_branch)
- it "prevents creation of the protected branch rule" do
expect { service.execute(protected_branch) }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
+
+ def disallow(ability, protected_branch)
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, ability, protected_branch).and_return(false)
+ end
end
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 3f11eaa7e93..2d38d968ce4 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -810,38 +810,6 @@ RSpec.describe QuickActions::InterpretService do
end
end
- shared_examples 'attention command' do
- it 'updates reviewers attention status' do
- _, _, message = service.execute(content, issuable)
-
- expect(message).to eq("Requested attention from #{developer.to_reference}.")
-
- reviewer.reload
-
- expect(reviewer).to be_attention_requested
- end
-
- it 'supports attn alias' do
- attn_cmd = content.gsub(/attention/, 'attn')
- _, _, message = service.execute(attn_cmd, issuable)
-
- expect(message).to eq("Requested attention from #{developer.to_reference}.")
-
- reviewer.reload
-
- expect(reviewer).to be_attention_requested
- end
- end
-
- shared_examples 'remove attention command' do
- it 'updates reviewers attention status' do
- _, _, message = service.execute(content, issuable)
-
- expect(message).to eq("Removed attention from #{developer.to_reference}.")
- expect(reviewer).not_to be_attention_requested
- end
- end
-
it_behaves_like 'reopen command' do
let(:content) { '/reopen' }
let(:issuable) { issue }
@@ -1888,7 +1856,7 @@ RSpec.describe QuickActions::InterpretService do
context '/target_branch command' do
let(:non_empty_project) { create(:project, :repository) }
let(:another_merge_request) { create(:merge_request, author: developer, source_project: non_empty_project) }
- let(:service) { described_class.new(non_empty_project, developer)}
+ let(:service) { described_class.new(non_empty_project, developer) }
it 'updates target_branch if /target_branch command is executed' do
_, updates, _ = service.execute('/target_branch merge-test', merge_request)
@@ -2481,82 +2449,6 @@ RSpec.describe QuickActions::InterpretService do
expect(message).to eq('One or more contacts were successfully removed.')
end
end
-
- describe 'attention command' do
- let(:issuable) { create(:merge_request, reviewers: [developer], source_project: project) }
- let(:reviewer) { issuable.merge_request_reviewers.find_by(user_id: developer.id) }
- let(:content) { "/attention @#{developer.username}" }
-
- context 'with one user' do
- before do
- reviewer.update!(state: :reviewed)
- end
-
- it_behaves_like 'attention command'
- end
-
- context 'with no user' do
- let(:content) { "/attention" }
-
- it_behaves_like 'failed command', 'Failed to request attention because no user was found.'
- end
-
- context 'with incorrect permissions' do
- let(:service) { described_class.new(project, create(:user)) }
-
- it_behaves_like 'failed command', 'Could not apply attention command.'
- end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
- end
-
- it_behaves_like 'failed command', 'Could not apply attention command.'
- end
-
- context 'with an issue instead of a merge request' do
- let(:issuable) { issue }
-
- it_behaves_like 'failed command', 'Could not apply attention command.'
- end
- end
-
- describe 'remove attention command' do
- let(:issuable) { create(:merge_request, reviewers: [developer], source_project: project) }
- let(:reviewer) { issuable.merge_request_reviewers.find_by(user_id: developer.id) }
- let(:content) { "/remove_attention @#{developer.username}" }
-
- context 'with one user' do
- it_behaves_like 'remove attention command'
- end
-
- context 'with no user' do
- let(:content) { "/remove_attention" }
-
- it_behaves_like 'failed command', 'Failed to remove attention because no user was found.'
- end
-
- context 'with incorrect permissions' do
- let(:service) { described_class.new(project, create(:user)) }
-
- it_behaves_like 'failed command', 'Could not apply remove_attention command.'
- end
-
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(mr_attention_requests: false)
- end
-
- it_behaves_like 'failed command', 'Could not apply remove_attention command.'
- end
-
- context 'with an issue instead of a merge request' do
- let(:issuable) { issue }
-
- it_behaves_like 'failed command', 'Could not apply remove_attention command.'
- end
- end
end
describe '#explain' do
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index 566d73a3b75..2421fab0eec 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -111,14 +111,6 @@ RSpec.describe Releases::CreateService do
expect(result[:message]).to eq("Milestone(s) not found: #{inexistent_milestone_tag}")
end
end
- end
-
- describe '#find_or_build_release' do
- it 'does not save the built release' do
- service.find_or_build_release
-
- expect(project.releases.count).to eq(0)
- end
context 'when existing milestone is passed in' do
let(:title) { 'v1.0' }
diff --git a/spec/services/releases/destroy_service_spec.rb b/spec/services/releases/destroy_service_spec.rb
index bc5bff0b31d..46550ac5bef 100644
--- a/spec/services/releases/destroy_service_spec.rb
+++ b/spec/services/releases/destroy_service_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Releases::DestroyService do
end
context 'when release is not found' do
- let!(:release) { }
+ let!(:release) {}
it 'returns an error' do
is_expected.to include(status: :error,
diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb
index 932a7fab5ec..7461470a844 100644
--- a/spec/services/releases/update_service_spec.rb
+++ b/spec/services/releases/update_service_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Releases::UpdateService do
end
context 'when the release does not exist' do
- let!(:release) { }
+ let!(:release) {}
it_behaves_like 'a failed update'
end
diff --git a/spec/services/resource_access_tokens/create_service_spec.rb b/spec/services/resource_access_tokens/create_service_spec.rb
index 127948549b0..442232920f9 100644
--- a/spec/services/resource_access_tokens/create_service_spec.rb
+++ b/spec/services/resource_access_tokens/create_service_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ResourceAccessTokens::CreateService do
describe '#execute' do
shared_examples 'token creation fails' do
- let(:resource) { create(:project)}
+ let(:resource) { create(:project) }
it 'does not add the project bot as a member' do
expect { subject }.not_to change { resource.members.count }
diff --git a/spec/services/resource_events/change_labels_service_spec.rb b/spec/services/resource_events/change_labels_service_spec.rb
index c2c0a4c2126..8dc7b07e397 100644
--- a/spec/services/resource_events/change_labels_service_spec.rb
+++ b/spec/services/resource_events/change_labels_service_spec.rb
@@ -5,11 +5,40 @@ require 'spec_helper'
RSpec.describe ResourceEvents::ChangeLabelsService do
let_it_be(:project) { create(:project) }
let_it_be(:author) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:incident) { create(:incident, project: project) }
- let(:resource) { create(:issue, project: project) }
+ let(:resource) { issue }
- describe '.change_labels' do
- subject { described_class.new(resource, author).execute(added_labels: added, removed_labels: removed) }
+ describe '#execute' do
+ shared_examples 'creating timeline events' do
+ context 'when resource is not an incident' do
+ let(:resource) { issue }
+
+ it 'does not call create timeline events service' do
+ expect(IncidentManagement::TimelineEvents::CreateService).not_to receive(:change_labels)
+
+ change_labels
+ end
+ end
+
+ context 'when resource is an incident' do
+ let(:resource) { incident }
+
+ it 'calls create timeline events service with correct attributes' do
+ expect(IncidentManagement::TimelineEvents::CreateService)
+ .to receive(:change_labels)
+ .with(resource, author, added_labels: added, removed_labels: removed)
+ .and_call_original
+
+ change_labels
+ end
+ end
+ end
+
+ subject(:change_labels) do
+ described_class.new(resource, author).execute(added_labels: added, removed_labels: removed)
+ end
let_it_be(:labels) { create_list(:label, 2, project: project) }
@@ -20,9 +49,9 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
end
it 'expires resource note etag cache' do
- expect_any_instance_of(Gitlab::EtagCaching::Store)
- .to receive(:touch)
- .with("/#{resource.project.namespace.to_param}/#{resource.project.to_param}/noteable/issue/#{resource.id}/notes")
+ expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(
+ "/#{resource.project.namespace.to_param}/#{resource.project.to_param}/noteable/issue/#{resource.id}/notes"
+ )
described_class.new(resource, author).execute(added_labels: [labels[0]])
end
@@ -32,10 +61,12 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
let(:removed) { [] }
it 'creates new label event' do
- expect { subject }.to change { resource.resource_label_events.count }.from(0).to(1)
+ expect { change_labels }.to change { resource.resource_label_events.count }.from(0).to(1)
expect_label_event(resource.resource_label_events.first, labels[0], 'add')
end
+
+ it_behaves_like 'creating timeline events'
end
context 'when removing a label' do
@@ -43,10 +74,12 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
let(:removed) { [labels[1]] }
it 'creates new label event' do
- expect { subject }.to change { resource.resource_label_events.count }.from(0).to(1)
+ expect { change_labels }.to change { resource.resource_label_events.count }.from(0).to(1)
expect_label_event(resource.resource_label_events.first, labels[1], 'remove')
end
+
+ it_behaves_like 'creating timeline events'
end
context 'when both adding and removing labels' do
@@ -55,8 +88,10 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
it 'creates all label events in a single query' do
expect(ApplicationRecord).to receive(:legacy_bulk_insert).once.and_call_original
- expect { subject }.to change { resource.resource_label_events.count }.from(0).to(2)
+ expect { change_labels }.to change { resource.resource_label_events.count }.from(0).to(2)
end
+
+ it_behaves_like 'creating timeline events'
end
describe 'usage data' do
@@ -67,7 +102,7 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
it 'tracks changed labels' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_label_changed_action)
- subject
+ change_labels
end
end
@@ -75,9 +110,10 @@ RSpec.describe ResourceEvents::ChangeLabelsService do
let(:resource) { create(:merge_request, source_project: project) }
it 'does not track changed labels' do
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_label_changed_action)
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter)
+ .not_to receive(:track_issue_label_changed_action)
- subject
+ change_labels
end
end
end
diff --git a/spec/services/search/group_service_spec.rb b/spec/services/search/group_service_spec.rb
index 7beeec98b23..152d0700cc1 100644
--- a/spec/services/search/group_service_spec.rb
+++ b/spec/services/search/group_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Search::GroupService do
# These projects shouldn't be found
let!(:outside_project) { create(:project, :public, name: "Outside #{term}") }
- let!(:private_project) { create(:project, :private, namespace: nested_group, name: "Private #{term}" )}
+ let!(:private_project) { create(:project, :private, namespace: nested_group, name: "Private #{term}" ) }
let!(:other_project) { create(:project, :public, namespace: nested_group, name: term.reverse) }
# These projects should be found
diff --git a/spec/services/security/ci_configuration/sast_parser_service_spec.rb b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
index 4346d0a9e07..1fd196cdcee 100644
--- a/spec/services/security/ci_configuration/sast_parser_service_spec.rb
+++ b/spec/services/security/ci_configuration/sast_parser_service_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Security::CiConfiguration::SastParserService do
let(:bandit) { configuration['analyzers'][0] }
let(:brakeman) { configuration['analyzers'][1] }
let(:sast_brakeman_level) { brakeman['variables'][0] }
+ let(:secure_analyzers_prefix) { '$CI_TEMPLATE_REGISTRY_HOST/security-products' }
it 'parses the configuration for SAST' do
expect(secure_analyzers['default_value']).to eql(secure_analyzers_prefix)
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index f61d33e2436..67cc258b4b6 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe Snippets::UpdateService do
context 'when snippet_actions param is used' do
let(:file_path) { 'CHANGELOG' }
- let(:created_file_path) { 'New file'}
+ let(:created_file_path) { 'New file' }
let(:content) { 'foobar' }
let(:snippet_actions) { [{ action: :move, previous_path: snippet.file_name, file_path: file_path }, { action: :create, file_path: created_file_path, content: content }] }
let(:base_opts) do
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index 6052882813e..e34324d5fe2 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -359,7 +359,7 @@ RSpec.describe Suggestions::ApplyService do
end
context 'multiple suggestions' do
- let(:author_emails) { suggestions.map {|s| s.note.author.commit_email_or_default } }
+ let(:author_emails) { suggestions.map { |s| s.note.author.commit_email_or_default } }
let(:first_author) { suggestion.note.author }
let(:commit) { project.repository.commit }
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 741d136b9a0..a192fae27db 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -134,15 +134,15 @@ RSpec.describe SystemNoteService do
end
end
- describe '.change_due_date' do
- let(:due_date) { double }
+ describe '.change_start_date_or_due_date' do
+ let(:changed_dates) { double }
it 'calls TimeTrackingService' do
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
- expect(service).to receive(:change_due_date).with(due_date)
+ expect(service).to receive(:change_start_date_or_due_date).with(changed_dates)
end
- described_class.change_due_date(noteable, project, author, due_date)
+ described_class.change_start_date_or_due_date(noteable, project, author, changed_dates)
end
end
@@ -159,30 +159,6 @@ RSpec.describe SystemNoteService do
end
end
- describe '.request_attention' do
- let(:user) { double }
-
- it 'calls IssuableService' do
- expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:request_attention).with(user)
- end
-
- described_class.request_attention(noteable, project, author, user)
- end
- end
-
- describe '.remove_attention_request' do
- let(:user) { double }
-
- it 'calls IssuableService' do
- expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:remove_attention_request).with(user)
- end
-
- described_class.remove_attention_request(noteable, project, author, user)
- end
- end
-
describe '.merge_when_pipeline_succeeds' do
it 'calls MergeRequestsService' do
sha = double
@@ -375,13 +351,14 @@ RSpec.describe SystemNoteService do
describe '.noteable_cloned' do
let(:noteable_ref) { double }
let(:direction) { double }
+ let(:created_at) { double }
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:noteable_cloned).with(noteable_ref, direction)
+ expect(service).to receive(:noteable_cloned).with(noteable_ref, direction, created_at: created_at)
end
- described_class.noteable_cloned(double, double, noteable_ref, double, direction: direction)
+ described_class.noteable_cloned(double, double, noteable_ref, double, direction: direction, created_at: created_at)
end
end
@@ -431,9 +408,22 @@ RSpec.describe SystemNoteService do
end
end
+ describe '.created_timelog' do
+ let(:issue) { create(:issue, project: project) }
+ let(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
+
+ it 'calls TimeTrackingService' do
+ expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
+ expect(service).to receive(:created_timelog)
+ end
+
+ described_class.created_timelog(noteable, project, author, timelog)
+ end
+ end
+
describe '.remove_timelog' do
let(:issue) { create(:issue, project: project) }
- let(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
+ let(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
it 'calls TimeTrackingService' do
expect_next_instance_of(::SystemNotes::TimeTrackingService) do |service|
@@ -742,4 +732,38 @@ RSpec.describe SystemNoteService do
described_class.delete_timeline_event(noteable, author)
end
end
+
+ describe '.relate_work_item' do
+ let(:work_item) { double('work_item', issue_type: :task) }
+ let(:noteable) { double }
+
+ before do
+ allow(noteable).to receive(:project).and_return(double)
+ end
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:hierarchy_changed).with(work_item, 'relate')
+ end
+
+ described_class.relate_work_item(noteable, work_item, double)
+ end
+ end
+
+ describe '.unrelate_wotk_item' do
+ let(:work_item) { double('work_item', issue_type: :task) }
+ let(:noteable) { double }
+
+ before do
+ allow(noteable).to receive(:project).and_return(double)
+ end
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:hierarchy_changed).with(work_item, 'unrelate')
+ end
+
+ described_class.unrelate_work_item(noteable, work_item, double)
+ end
+ end
end
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index 5bc7ea82976..b2ccd9dba52 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -247,42 +247,6 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
- describe '#request_attention' do
- subject { service.request_attention(user) }
-
- let(:user) { create(:user) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'attention_requested' }
- end
-
- context 'when attention requested' do
- it_behaves_like 'a note with overridable created_at'
-
- it 'sets the note text' do
- expect(subject.note).to eq "requested attention from @#{user.username}"
- end
- end
- end
-
- describe '#remove_attention_request' do
- subject { service.remove_attention_request(user) }
-
- let(:user) { create(:user) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'attention_request_removed' }
- end
-
- context 'when attention request is removed' do
- it_behaves_like 'a note with overridable created_at'
-
- it 'sets the note text' do
- expect(subject.note).to eq "removed attention request from @#{user.username}"
- end
- end
- end
-
describe '#change_title' do
let(:noteable) { create(:issue, project: project, title: 'Lorem ipsum') }
@@ -559,8 +523,8 @@ RSpec.describe ::SystemNotes::IssuablesService do
let(:action) { 'task' }
end
- it "posts the 'marked the task as complete' system note" do
- expect(subject.note).to eq("marked the task **task** as completed")
+ it "posts the 'marked the checklist item as complete' system note" do
+ expect(subject.note).to eq("marked the checklist item **task** as completed")
end
end
@@ -625,8 +589,8 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
describe '#noteable_cloned' do
- let(:new_project) { create(:project) }
- let(:new_noteable) { create(:issue, project: new_project) }
+ let_it_be(:new_project) { create(:project) }
+ let_it_be(:new_noteable) { create(:issue, project: new_project) }
subject do
service.noteable_cloned(new_noteable, direction)
@@ -684,6 +648,22 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
+ context 'custom created timestamp' do
+ let(:direction) { :from }
+
+ it 'allows setting of custom created_at value' do
+ timestamp = 1.day.ago
+
+ note = service.noteable_cloned(new_noteable, direction, created_at: timestamp)
+
+ expect(note.created_at).to be_like_time(timestamp)
+ end
+
+ it 'defaults to current time when created_at is not given', :freeze_time do
+ expect(subject.created_at).to be_like_time(Time.current)
+ end
+ end
+
context 'metrics' do
context 'cloned from' do
let(:direction) { :from }
@@ -696,15 +676,20 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
- context 'cloned to' do
+ context 'cloned to', :snowplow do
let(:direction) { :to }
it 'tracks usage' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter)
- .to receive(:track_issue_cloned_action).with(author: author)
+ .to receive(:track_issue_cloned_action).with(author: author, project: project )
subject
end
+
+ it_behaves_like 'issue_edit snowplow tracking' do
+ let(:property) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CLONED }
+ let(:user) { author }
+ end
end
end
end
@@ -886,4 +871,43 @@ RSpec.describe ::SystemNotes::IssuablesService do
it { expect(subject.note).to eq "changed issue type to incident" }
end
+
+ describe '#hierarchy_changed' do
+ let_it_be_with_reload(:work_item) { create(:work_item, project: project) }
+ let_it_be_with_reload(:task) { create(:work_item, :task, project: project) }
+
+ let(:service) { described_class.new(noteable: work_item, project: project, author: author) }
+
+ subject { service.hierarchy_changed(task, hierarchy_change_action) }
+
+ context 'when task is added as a child' do
+ let(:hierarchy_change_action) { 'relate' }
+
+ it_behaves_like 'a system note' do
+ let(:expected_noteable) { task }
+ let(:action) { 'relate_to_parent' }
+ end
+
+ it 'sets the correct note text' do
+ expect { subject }.to change { Note.system.count }.by(2)
+ expect(work_item.notes.last.note).to eq("added ##{task.iid} as child task")
+ expect(task.notes.last.note).to eq("added ##{work_item.iid} as parent issue")
+ end
+ end
+
+ context 'when child task is removed' do
+ let(:hierarchy_change_action) { 'unrelate' }
+
+ it_behaves_like 'a system note' do
+ let(:expected_noteable) { task }
+ let(:action) { 'unrelate_from_parent' }
+ end
+
+ it 'sets the correct note text' do
+ expect { subject }.to change { Note.system.count }.by(2)
+ expect(work_item.notes.last.note).to eq("removed child task ##{task.iid}")
+ expect(task.notes.last.note).to eq("removed parent issue ##{work_item.iid}")
+ end
+ end
+ end
end
diff --git a/spec/services/system_notes/merge_requests_service_spec.rb b/spec/services/system_notes/merge_requests_service_spec.rb
index 58d2489f878..3e66ccef106 100644
--- a/spec/services/system_notes/merge_requests_service_spec.rb
+++ b/spec/services/system_notes/merge_requests_service_spec.rb
@@ -167,8 +167,8 @@ RSpec.describe ::SystemNotes::MergeRequestsService do
end
describe '.change_branch' do
- let(:old_branch) { 'old_branch'}
- let(:new_branch) { 'new_branch'}
+ let(:old_branch) { 'old_branch' }
+ let(:new_branch) { 'new_branch' }
it_behaves_like 'a system note' do
let(:action) { 'branch' }
diff --git a/spec/services/system_notes/time_tracking_service_spec.rb b/spec/services/system_notes/time_tracking_service_spec.rb
index fdf18f4f29a..33608deaa64 100644
--- a/spec/services/system_notes/time_tracking_service_spec.rb
+++ b/spec/services/system_notes/time_tracking_service_spec.rb
@@ -3,35 +3,112 @@
require 'spec_helper'
RSpec.describe ::SystemNotes::TimeTrackingService do
- let_it_be(:author) { create(:user) }
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
- describe '#change_due_date' do
- subject { described_class.new(noteable: noteable, project: project, author: author).change_due_date(due_date) }
+ describe '#change_start_date_or_due_date' do
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:work_item) { create(:work_item, project: project) }
- let(:due_date) { Date.today }
+ subject(:note) { described_class.new(noteable: noteable, project: project, author: author).change_start_date_or_due_date(changed_dates) }
- context 'when noteable is an issue' do
- let_it_be(:noteable) { create(:issue, project: project) }
+ let(:start_date) { Date.today }
+ let(:due_date) { 1.week.from_now.to_date }
+ let(:changed_dates) { { 'due_date' => [nil, due_date], 'start_date' => [nil, start_date] } }
+ shared_examples 'issuable getting date change notes' do
it_behaves_like 'a note with overridable created_at'
it_behaves_like 'a system note' do
- let(:action) { 'due_date' }
+ let(:action) { 'start_date_or_due_date' }
end
- context 'when due date added' do
- it 'sets the note text' do
- expect(subject.note).to eq "changed due date to #{due_date.to_s(:long)}"
+ context 'when both dates are added' do
+ it 'sets the correct note message' do
+ expect(note.note).to eq("changed start date to #{start_date.to_s(:long)} and changed due date to #{due_date.to_s(:long)}")
end
end
- context 'when due date removed' do
- let(:due_date) { nil }
+ context 'when both dates are removed' do
+ let(:changed_dates) { { 'due_date' => [due_date, nil], 'start_date' => [start_date, nil] } }
- it 'sets the note text' do
- expect(subject.note).to eq 'removed due date'
+ before do
+ noteable.update!(start_date: start_date, due_date: due_date)
+ end
+
+ it 'sets the correct note message' do
+ expect(note.note).to eq('removed start date and removed due date')
+ end
+ end
+
+ context 'when due date is added' do
+ let(:changed_dates) { { 'due_date' => [nil, due_date] } }
+
+ it 'sets the correct note message' do
+ expect(note.note).to eq("changed due date to #{due_date.to_s(:long)}")
+ end
+
+ it 'tracks the issue event in usage ping' do
+ expect(activity_counter_class).to receive(activity_counter_method).with(author: author)
+
+ subject
end
+
+ context 'and start date removed' do
+ let(:changed_dates) { { 'due_date' => [nil, due_date], 'start_date' => [start_date, nil] } }
+
+ it 'sets the correct note message' do
+ expect(note.note).to eq("removed start date and changed due date to #{due_date.to_s(:long)}")
+ end
+ end
+ end
+
+ context 'when start_date is added' do
+ let(:changed_dates) { { 'start_date' => [nil, start_date] } }
+
+ it 'does not track the issue event in usage ping' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_due_date_changed_action)
+
+ subject
+ end
+
+ it 'sets the correct note message' do
+ expect(note.note).to eq("changed start date to #{start_date.to_s(:long)}")
+ end
+
+ context 'and due date removed' do
+ let(:changed_dates) { { 'due_date' => [due_date, nil], 'start_date' => [nil, start_date] } }
+
+ it 'sets the correct note message' do
+ expect(note.note).to eq("changed start date to #{start_date.to_s(:long)} and removed due date")
+ end
+ end
+ end
+
+ context 'when no dates are changed' do
+ let(:changed_dates) { {} }
+
+ it 'does not create a note and returns nil' do
+ expect do
+ note
+ end.to not_change(Note, :count)
+
+ expect(note).to be_nil
+ end
+ end
+ end
+
+ context 'when noteable is an issue' do
+ let(:noteable) { issue }
+ let(:activity_counter_class) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter }
+ let(:activity_counter_method) { :track_issue_due_date_changed_action }
+
+ it_behaves_like 'issuable getting date change notes'
+
+ it 'does not track the work item event in usage ping' do
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).not_to receive(:track_work_item_date_changed_action)
+
+ subject
end
it 'tracks the issue event in usage ping' do
@@ -39,13 +116,48 @@ RSpec.describe ::SystemNotes::TimeTrackingService do
subject
end
+
+ context 'when only start_date is added' do
+ let(:changed_dates) { { 'start_date' => [nil, start_date] } }
+
+ it 'does not track the issue event in usage ping' do
+ expect(activity_counter_class).not_to receive(activity_counter_method)
+
+ subject
+ end
+ end
+ end
+
+ context 'when noteable is a work item' do
+ let(:noteable) { work_item }
+ let(:activity_counter_class) { Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter }
+ let(:activity_counter_method) { :track_work_item_date_changed_action }
+
+ it_behaves_like 'issuable getting date change notes'
+
+ it 'does not track the issue event in usage ping' do
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_due_date_changed_action)
+
+ subject
+ end
+
+ context 'when only start_date is added' do
+ let(:changed_dates) { { 'start_date' => [nil, start_date] } }
+
+ it 'tracks the issue event in usage ping' do
+ expect(activity_counter_class).to receive(activity_counter_method).with(author: author)
+
+ subject
+ end
+ end
end
context 'when noteable is a merge request' do
- let_it_be(:noteable) { create(:merge_request, source_project: project) }
+ let(:noteable) { create(:merge_request, source_project: project) }
it 'does not track the issue event in usage ping' do
- expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_due_date_changed_action).with(author: author)
+ expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_due_date_changed_action)
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).not_to receive(:track_work_item_date_changed_action)
subject
end
@@ -106,13 +218,37 @@ RSpec.describe ::SystemNotes::TimeTrackingService do
end
end
+ describe '#create_timelog' do
+ subject { described_class.new(noteable: noteable, project: project, author: author).created_timelog(timelog) }
+
+ context 'when the timelog has a positive time spent value' do
+ let_it_be(:noteable, reload: true) { create(:issue, project: project) }
+
+ let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: 1800, spent_at: '2022-03-30T00:00:00.000Z') }
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "added 30m of time spent at 2022-03-30"
+ end
+ end
+
+ context 'when the timelog has a negative time spent value' do
+ let_it_be(:noteable, reload: true) { create(:issue, project: project) }
+
+ let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: -1800, spent_at: '2022-03-30T00:00:00.000Z') }
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "subtracted 30m of time spent at 2022-03-30"
+ end
+ end
+ end
+
describe '#remove_timelog' do
subject { described_class.new(noteable: noteable, project: project, author: author).remove_timelog(timelog) }
context 'when the timelog has a positive time spent value' do
let_it_be(:noteable, reload: true) { create(:issue, project: project) }
- let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: 1800, spent_at: '2022-03-30T00:00:00.000Z')}
+ let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: 1800, spent_at: '2022-03-30T00:00:00.000Z') }
it 'sets the note text' do
expect(subject.note).to eq "deleted 30m of spent time from 2022-03-30"
@@ -122,7 +258,7 @@ RSpec.describe ::SystemNotes::TimeTrackingService do
context 'when the timelog has a negative time spent value' do
let_it_be(:noteable, reload: true) { create(:issue, project: project) }
- let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: -1800, spent_at: '2022-03-30T00:00:00.000Z')}
+ let(:timelog) { create(:timelog, user: author, issue: noteable, time_spent: -1800, spent_at: '2022-03-30T00:00:00.000Z') }
it 'sets the note text' do
expect(subject.note).to eq "deleted -30m of spent time from 2022-03-30"
diff --git a/spec/services/terraform/remote_state_handler_spec.rb b/spec/services/terraform/remote_state_handler_spec.rb
index 19c1d4109e9..369309e4d5a 100644
--- a/spec/services/terraform/remote_state_handler_spec.rb
+++ b/spec/services/terraform/remote_state_handler_spec.rb
@@ -171,7 +171,7 @@ RSpec.describe Terraform::RemoteStateHandler do
end
context 'with no lock ID (force-unlock)' do
- let(:lock_id) { }
+ let(:lock_id) {}
it 'unlocks the state' do
state = handler.unlock!
diff --git a/spec/services/timelogs/create_service_spec.rb b/spec/services/timelogs/create_service_spec.rb
new file mode 100644
index 00000000000..b5ed4a005c7
--- /dev/null
+++ b/spec/services/timelogs/create_service_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Timelogs::CreateService do
+ let_it_be(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:time_spent) { 3600 }
+ let_it_be(:spent_at) { "2022-07-08" }
+ let_it_be(:summary) { "Test summary" }
+
+ let(:issuable) { nil }
+ let(:users_container) { project }
+ let(:service) { described_class.new(issuable, time_spent, spent_at, summary, user) }
+
+ describe '#execute' do
+ subject { service.execute }
+
+ context 'when issuable is an Issue' do
+ let_it_be(:issuable) { create(:issue, project: project) }
+ let_it_be(:note_noteable) { create(:issue, project: project) }
+
+ it_behaves_like 'issuable supports timelog creation service'
+ end
+
+ context 'when issuable is a MergeRequest' do
+ let_it_be(:issuable) { create(:merge_request, source_project: project, source_branch: 'branch-1') }
+ let_it_be(:note_noteable) { create(:merge_request, source_project: project, source_branch: 'branch-2') }
+
+ it_behaves_like 'issuable supports timelog creation service'
+ end
+
+ context 'when issuable is a WorkItem' do
+ let_it_be(:issuable) { create(:work_item, project: project, title: 'WorkItem-1') }
+ let_it_be(:note_noteable) { create(:work_item, project: project, title: 'WorkItem-2') }
+
+ it_behaves_like 'issuable supports timelog creation service'
+ end
+
+ context 'when issuable is an Incident' do
+ let_it_be(:issuable) { create(:incident, project: project) }
+ let_it_be(:note_noteable) { create(:incident, project: project) }
+
+ it_behaves_like 'issuable supports timelog creation service'
+ end
+ end
+end
diff --git a/spec/services/timelogs/delete_service_spec.rb b/spec/services/timelogs/delete_service_spec.rb
index c52cebdc5bf..ee1133af6b3 100644
--- a/spec/services/timelogs/delete_service_spec.rb
+++ b/spec/services/timelogs/delete_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Timelogs::DeleteService do
let_it_be(:author) { create(:user) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
+ let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
let(:service) { described_class.new(timelog, user) }
@@ -21,8 +21,8 @@ RSpec.describe Timelogs::DeleteService do
end
it 'returns the removed timelog' do
- expect(subject).to be_success
- expect(subject.payload).to eq(timelog)
+ is_expected.to be_success
+ expect(subject.payload[:timelog]).to eq(timelog)
end
end
@@ -31,7 +31,7 @@ RSpec.describe Timelogs::DeleteService do
let!(:timelog) { nil }
it 'returns an error' do
- expect(subject).to be_error
+ is_expected.to be_error
expect(subject.message).to eq('Timelog doesn\'t exist or you don\'t have permission to delete it')
expect(subject.http_status).to eq(404)
end
@@ -41,7 +41,7 @@ RSpec.describe Timelogs::DeleteService do
let(:user) { create(:user) }
it 'returns an error' do
- expect(subject).to be_error
+ is_expected.to be_error
expect(subject.message).to eq('Timelog doesn\'t exist or you don\'t have permission to delete it')
expect(subject.http_status).to eq(404)
end
@@ -49,14 +49,14 @@ RSpec.describe Timelogs::DeleteService do
context 'when the timelog deletion fails' do
let(:user) { author }
- let!(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
+ let!(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
before do
allow(timelog).to receive(:destroy).and_return(false)
end
it 'returns an error' do
- expect(subject).to be_error
+ is_expected.to be_error
expect(subject.message).to eq('Failed to remove timelog')
expect(subject.http_status).to eq(400)
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 1cb44366457..45a8268043f 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -207,7 +207,7 @@ RSpec.describe TodoService do
end
it_behaves_like 'an incident management tracked event', :incident_management_incident_todo do
- let(:current_user) { john_doe}
+ let(:current_user) { john_doe }
end
end
end
@@ -1139,7 +1139,7 @@ RSpec.describe TodoService do
it 'updates related todos for the user with the new_state' do
method_call
- expect(collection.all? { |todo| todo.reload.state?(new_state)}).to be_truthy
+ expect(collection.all? { |todo| todo.reload.state?(new_state) }).to be_truthy
end
if new_resolved_by
@@ -1250,17 +1250,6 @@ RSpec.describe TodoService do
end
end
- describe '#create_attention_requested_todo' do
- let(:target) { create(:merge_request, author: author, source_project: project) }
- let(:user) { create(:user) }
-
- it 'creates a todo for user' do
- service.create_attention_requested_todo(target, author, user)
-
- should_create_todo(user: user, target: target, action: Todo::ATTENTION_REQUESTED)
- end
- end
-
def should_create_todo(attributes = {})
attributes.reverse_merge!(
project: project,
diff --git a/spec/services/todos/destroy/design_service_spec.rb b/spec/services/todos/destroy/design_service_spec.rb
index 61a6718dc9d..92b25d94dc6 100644
--- a/spec/services/todos/destroy/design_service_spec.rb
+++ b/spec/services/todos/destroy/design_service_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe Todos::Destroy::DesignService do
let_it_be(:design_2) { create(:design) }
let_it_be(:design_3) { create(:design) }
- let_it_be(:create_action) { create(:design_action, design: design)}
- let_it_be(:create_action_2) { create(:design_action, design: design_2)}
+ let_it_be(:create_action) { create(:design_action, design: design) }
+ let_it_be(:create_action_2) { create(:design_action, design: design_2) }
describe '#execute' do
before do
@@ -23,8 +23,8 @@ RSpec.describe Todos::Destroy::DesignService do
subject { described_class.new([design.id, design_2.id, design_3.id]).execute }
context 'when the design has been archived' do
- let_it_be(:archive_action) { create(:design_action, design: design, event: :deletion)}
- let_it_be(:archive_action_2) { create(:design_action, design: design_3, event: :deletion)}
+ let_it_be(:archive_action) { create(:design_action, design: design, event: :deletion) }
+ let_it_be(:archive_action_2) { create(:design_action, design: design_3, event: :deletion) }
it 'removes todos for that design' do
expect { subject }.to change { Todo.count }.from(4).to(1)
diff --git a/spec/services/todos/destroy/destroyed_issuable_service_spec.rb b/spec/services/todos/destroy/destroyed_issuable_service_spec.rb
index 24f74bae7c8..6d6abe06d1c 100644
--- a/spec/services/todos/destroy/destroyed_issuable_service_spec.rb
+++ b/spec/services/todos/destroy/destroyed_issuable_service_spec.rb
@@ -4,31 +4,46 @@ require 'spec_helper'
RSpec.describe Todos::Destroy::DestroyedIssuableService do
describe '#execute' do
- let_it_be(:target) { create(:merge_request) }
- let_it_be(:pending_todo) { create(:todo, :pending, project: target.project, target: target, user: create(:user)) }
- let_it_be(:done_todo) { create(:todo, :done, project: target.project, target: target, user: create(:user)) }
+ let_it_be(:user) { create(:user) }
- def execute
- described_class.new(target.id, target.class.name).execute
- end
+ subject { described_class.new(target.id, target.class.name).execute }
+
+ context 'when target is merge request' do
+ let_it_be(:target) { create(:merge_request) }
+ let_it_be(:pending_todo) { create(:todo, :pending, project: target.project, target: target, user: user) }
+ let_it_be(:done_todo) { create(:todo, :done, project: target.project, target: target, user: user) }
- it 'deletes todos for specified target ID and type' do
- control_count = ActiveRecord::QueryRecorder.new { execute }.count
+ it 'deletes todos for specified target ID and type' do
+ control_count = ActiveRecord::QueryRecorder.new { subject }.count
- # Create more todos for the target
- create(:todo, :pending, project: target.project, target: target, user: create(:user))
- create(:todo, :pending, project: target.project, target: target, user: create(:user))
- create(:todo, :done, project: target.project, target: target, user: create(:user))
- create(:todo, :done, project: target.project, target: target, user: create(:user))
+ # Create more todos for the target
+ create(:todo, :pending, project: target.project, target: target, user: user)
+ create(:todo, :pending, project: target.project, target: target, user: user)
+ create(:todo, :done, project: target.project, target: target, user: user)
+ create(:todo, :done, project: target.project, target: target, user: user)
- expect { execute }.not_to exceed_query_limit(control_count)
- expect(target.reload.todos.count).to eq(0)
+ expect { subject }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'invalidates todos cache counts of todo users', :use_clean_rails_redis_caching do
+ expect { subject }
+ .to change { pending_todo.user.todos_pending_count }.from(1).to(0)
+ .and change { done_todo.user.todos_done_count }.from(1).to(0)
+ end
end
- it 'invalidates todos cache counts of todo users', :use_clean_rails_redis_caching do
- expect { execute }
- .to change { pending_todo.user.todos_pending_count }.from(1).to(0)
- .and change { done_todo.user.todos_done_count }.from(1).to(0)
+ context 'when target is an work item' do
+ let_it_be(:target) { create(:work_item) }
+ let_it_be(:todo1) { create(:todo, :pending, project: target.project, target: target, user: user) }
+ let_it_be(:todo2) { create(:todo, :done, project: target.project, target: target, user: user) }
+ # rubocop: disable Cop/AvoidBecomes
+ let_it_be(:todo3) { create(:todo, :pending, project: target.project, target: target.becomes(Issue), user: user) }
+ let_it_be(:todo4) { create(:todo, :done, project: target.project, target: target.becomes(Issue), user: user) }
+ # rubocop: enable Cop/AvoidBecomes
+
+ it 'deletes todos' do
+ expect { subject }.to change(Todo, :count).by(-4)
+ end
end
end
end
diff --git a/spec/services/topics/merge_service_spec.rb b/spec/services/topics/merge_service_spec.rb
new file mode 100644
index 00000000000..971917eb8e9
--- /dev/null
+++ b/spec/services/topics/merge_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Topics::MergeService do
+ let_it_be(:source_topic) { create(:topic, name: 'source_topic') }
+ let_it_be(:target_topic) { create(:topic, name: 'target_topic') }
+ let_it_be(:project_1) { create(:project, :public, topic_list: source_topic.name ) }
+ let_it_be(:project_2) { create(:project, :private, topic_list: source_topic.name ) }
+ let_it_be(:project_3) { create(:project, :public, topic_list: target_topic.name ) }
+ let_it_be(:project_4) { create(:project, :public, topic_list: [source_topic.name, target_topic.name] ) }
+
+ subject { described_class.new(source_topic, target_topic).execute }
+
+ describe '#execute' do
+ it 'merges source topic into target topic' do
+ subject
+
+ expect(target_topic.projects).to contain_exactly(project_1, project_2, project_3, project_4)
+ expect { source_topic.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'refreshes counters of target topic' do
+ expect { subject }
+ .to change { target_topic.reload.total_projects_count }.by(2)
+ .and change { target_topic.reload.non_private_projects_count }.by(1)
+ end
+
+ context 'when source topic fails to delete' do
+ it 'reverts previous changes' do
+ allow(source_topic.reload).to receive(:destroy!).and_raise(ActiveRecord::RecordNotDestroyed)
+
+ expect { subject }.to raise_error(ActiveRecord::RecordNotDestroyed)
+
+ expect(source_topic.projects).to contain_exactly(project_1, project_2, project_4)
+ expect(target_topic.projects).to contain_exactly(project_3, project_4)
+ end
+ end
+
+ context 'for parameter validation' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(source_topic_parameter, target_topic_parameter).execute }
+
+ where(:source_topic_parameter, :target_topic_parameter, :expected_message) do
+ nil | ref(:target_topic) | 'The source topic is not a topic.'
+ ref(:source_topic) | nil | 'The target topic is not a topic.'
+ ref(:target_topic) | ref(:target_topic) | 'The source topic and the target topic are identical.' # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ end
+
+ with_them do
+ it 'raises correct error' do
+ expect { subject }.to raise_error(ArgumentError) do |error|
+ expect(error.message).to eq(expected_message)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/uploads/destroy_service_spec.rb b/spec/services/uploads/destroy_service_spec.rb
new file mode 100644
index 00000000000..bb58da231b6
--- /dev/null
+++ b/spec/services/uploads/destroy_service_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Uploads::DestroyService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:upload) { create(:upload, :issuable_upload, model: project) }
+
+ let(:filename) { File.basename(upload.path) }
+ let(:secret) { upload.secret }
+ let(:model) { project }
+ let(:service) { described_class.new(model, user) }
+
+ describe '#execute' do
+ subject { service.execute(secret, filename) }
+
+ shared_examples_for 'upload not found' do
+ it 'does not delete any upload' do
+ expect { subject }.not_to change { Upload.count }
+ end
+
+ it 'returns an error' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[: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 user is nil' do
+ let(:user) { nil }
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when user cannot destroy upload' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when user can destroy upload' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'deletes the upload' do
+ expect { subject }.to change { Upload.count }.by(-1)
+ end
+
+ it 'returns success response' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:upload]).to eq(upload)
+ end
+
+ context 'when upload is not found' do
+ let(:filename) { 'not existing filename' }
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when upload secret is not found' do
+ let(:secret) { 'aaaaaaaaaa' }
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when upload secret has invalid format' do
+ let(:secret) { 'invalid' }
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when unknown model is used' do
+ let(:model) { user }
+
+ it 'raises an error' do
+ expect { subject }.to raise_exception(ArgumentError)
+ end
+ end
+
+ context 'when upload belongs to other model' do
+ let_it_be(:upload) { create(:upload, :namespace_upload) }
+
+ it_behaves_like 'upload not found'
+ end
+
+ context 'when upload destroy fails' do
+ before do
+ allow(service).to receive(:find_upload).and_return(upload)
+ allow(upload).to receive(:destroy).and_return(false)
+ end
+
+ it 'returns error' do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to eq('Upload could not be deleted.')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/users/create_service_spec.rb b/spec/services/users/create_service_spec.rb
index 74340bac055..f3c9701c556 100644
--- a/spec/services/users/create_service_spec.rb
+++ b/spec/services/users/create_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Users::CreateService do
describe '#execute' do
+ let(:password) { User.random_password }
let(:admin_user) { create(:admin) }
context 'with an admin user' do
@@ -12,7 +13,7 @@ RSpec.describe Users::CreateService do
context 'when required parameters are provided' do
let(:params) do
- { name: 'John Doe', username: 'jduser', email: email, password: 'mydummypass' }
+ { name: 'John Doe', username: 'jduser', email: email, password: password }
end
it 'returns a persisted user' do
@@ -82,13 +83,13 @@ RSpec.describe Users::CreateService do
context 'when force_random_password parameter is true' do
let(:params) do
- { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', force_random_password: true }
+ { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: password, force_random_password: true }
end
it 'generates random password' do
user = service.execute
- expect(user.password).not_to eq 'mydummypass'
+ expect(user.password).not_to eq password
expect(user.password).to be_present
end
end
@@ -99,7 +100,7 @@ RSpec.describe Users::CreateService do
name: 'John Doe',
username: 'jduser',
email: 'jd@example.com',
- password: 'mydummypass',
+ password: password,
password_automatically_set: true
}
end
@@ -121,7 +122,7 @@ RSpec.describe Users::CreateService do
context 'when skip_confirmation parameter is true' do
let(:params) do
- { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true }
+ { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: password, skip_confirmation: true }
end
it 'confirms the user' do
@@ -131,7 +132,7 @@ RSpec.describe Users::CreateService do
context 'when reset_password parameter is true' do
let(:params) do
- { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', reset_password: true }
+ { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: password, reset_password: true }
end
it 'resets password even if a password parameter is given' do
@@ -152,7 +153,7 @@ RSpec.describe Users::CreateService do
context 'with nil user' do
let(:params) do
- { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass', skip_confirmation: true }
+ { name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: password, skip_confirmation: true }
end
let(:service) { described_class.new(nil, params) }
diff --git a/spec/services/users/dismiss_namespace_callout_service_spec.rb b/spec/services/users/dismiss_namespace_callout_service_spec.rb
new file mode 100644
index 00000000000..fbcdb66c9e8
--- /dev/null
+++ b/spec/services/users/dismiss_namespace_callout_service_spec.rb
@@ -0,0 +1,24 @@
+# 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/dismiss_project_callout_service_spec.rb b/spec/services/users/dismiss_project_callout_service_spec.rb
new file mode 100644
index 00000000000..73e50a4c37d
--- /dev/null
+++ b/spec/services/users/dismiss_project_callout_service_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::DismissProjectCalloutService do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ let(:params) { { feature_name: feature_name, project_id: project.id } }
+ let(:feature_name) { Users::ProjectCallout.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::ProjectCallout
+
+ it 'sets the project_id' do
+ expect(execute.project_id).to eq(project.id)
+ end
+ end
+end
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 52c7b54ed72..411cd7316d8 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Users::UpdateService do
- let(:password) { 'longsecret987!' }
+ let(:password) { User.random_password }
let(:user) { create(:user, password: password, password_confirmation: password) }
describe '#execute' do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 339ffc44e4d..fed3ae7a543 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -190,7 +190,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
end
context 'when auth credentials are present' do
- let_it_be(:url) {'https://example.org'}
+ let_it_be(:url) { 'https://example.org' }
let_it_be(:project_hook) { create(:project_hook, url: 'https://demo:demo@example.org/') }
it 'uses the credentials' do
@@ -205,7 +205,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
end
context 'when auth credentials are partial present' do
- let_it_be(:url) {'https://example.org'}
+ let_it_be(:url) { 'https://example.org' }
let_it_be(:project_hook) { create(:project_hook, url: 'https://demo@example.org/') }
it 'uses the credentials anyways' do
diff --git a/spec/services/web_hooks/destroy_service_spec.rb b/spec/services/web_hooks/destroy_service_spec.rb
index 4d9bb18e540..ca8cb8a1b75 100644
--- a/spec/services/web_hooks/destroy_service_spec.rb
+++ b/spec/services/web_hooks/destroy_service_spec.rb
@@ -8,43 +8,54 @@ RSpec.describe WebHooks::DestroyService do
subject { described_class.new(user) }
describe '#execute' do
- %i[system_hook project_hook].each do |factory|
- context "deleting a #{factory}" do
- let!(:hook) { create(factory) } # rubocop: disable Rails/SaveBang (false-positive!)
- let!(:log) { create_list(:web_hook_log, 3, web_hook: hook) }
+ # Testing with a project hook only - for permission tests, see policy specs.
+ let!(:hook) { create(:project_hook) }
+ let!(:log) { create_list(:web_hook_log, 3, web_hook: hook) }
+
+ context 'when the user does not have permission' do
+ it 'is an error' do
+ expect(subject.execute(hook))
+ .to be_error
+ .and have_attributes(message: described_class::DENIED)
+ end
+ end
- it 'is successful' do
- expect(subject.execute(hook)).to be_success
- end
+ context 'when the user does have permission' do
+ before do
+ hook.project.add_maintainer(user)
+ end
- it 'destroys the hook' do
- expect { subject.execute(hook) }.to change(WebHook, :count).from(1).to(0)
- end
+ it 'is successful' do
+ expect(subject.execute(hook)).to be_success
+ end
- it 'does not destroy logs' do
- expect { subject.execute(hook) }.not_to change(WebHookLog, :count)
- end
+ it 'destroys the hook' do
+ expect { subject.execute(hook) }.to change(WebHook, :count).from(1).to(0)
+ end
- it 'schedules the destruction of logs' do
- expect(WebHooks::LogDestroyWorker).to receive(:perform_async).with({ 'hook_id' => hook.id })
- expect(Gitlab::AppLogger).to receive(:info).with(match(/scheduled a deletion of logs/))
+ it 'does not destroy logs' do
+ expect { subject.execute(hook) }.not_to change(WebHookLog, :count)
+ end
- subject.execute(hook)
- end
+ it 'schedules the destruction of logs' do
+ expect(WebHooks::LogDestroyWorker).to receive(:perform_async).with({ 'hook_id' => hook.id })
+ expect(Gitlab::AppLogger).to receive(:info).with(match(/scheduled a deletion of logs/))
- context 'when the hook fails to destroy' do
- before do
- allow(hook).to receive(:destroy).and_return(false)
- end
+ subject.execute(hook)
+ end
+
+ context 'when the hook fails to destroy' do
+ before do
+ allow(hook).to receive(:destroy).and_return(false)
+ end
- it 'is not a success' do
- expect(WebHooks::LogDestroyWorker).not_to receive(:perform_async)
+ it 'is not a success' do
+ expect(WebHooks::LogDestroyWorker).not_to receive(:perform_async)
- r = subject.execute(hook)
+ r = subject.execute(hook)
- expect(r).to be_error
- expect(r[:message]).to match %r{Unable to destroy}
- end
+ expect(r).to be_error
+ expect(r[:message]).to match %r{Unable to destroy}
end
end
end
diff --git a/spec/services/web_hooks/log_execution_service_spec.rb b/spec/services/web_hooks/log_execution_service_spec.rb
index 873f6adc8dc..1967a8368fb 100644
--- a/spec/services/web_hooks/log_execution_service_spec.rb
+++ b/spec/services/web_hooks/log_execution_service_spec.rb
@@ -101,27 +101,6 @@ RSpec.describe WebHooks::LogExecutionService do
it 'resets the failure count' do
expect { service.execute }.to change(project_hook, :recent_failures).to(0)
end
-
- it 'sends a message to AuthLogger if the hook as not previously enabled' do
- project_hook.update!(recent_failures: ::WebHook::FAILURE_THRESHOLD + 1)
-
- expect(Gitlab::AuthLogger).to receive(:info).with include(
- message: 'WebHook change active_state',
- # identification
- hook_id: project_hook.id,
- hook_type: project_hook.type,
- project_id: project_hook.project_id,
- group_id: nil,
- # relevant data
- prev_state: :permanently_disabled,
- new_state: :enabled,
- duration: 1.2,
- response_status: '200',
- recent_hook_failures: 0
- )
-
- service.execute
- end
end
end
@@ -158,27 +137,6 @@ RSpec.describe WebHooks::LogExecutionService do
expect { service.execute }.not_to change(project_hook, :recent_failures)
end
end
-
- it 'sends a message to AuthLogger if the state would change' do
- project_hook.update!(recent_failures: ::WebHook::FAILURE_THRESHOLD)
-
- expect(Gitlab::AuthLogger).to receive(:info).with include(
- message: 'WebHook change active_state',
- # identification
- hook_id: project_hook.id,
- hook_type: project_hook.type,
- project_id: project_hook.project_id,
- group_id: nil,
- # relevant data
- prev_state: :enabled,
- new_state: :permanently_disabled,
- duration: (be > 0),
- response_status: data[:response_status],
- recent_hook_failures: ::WebHook::FAILURE_THRESHOLD + 1
- )
-
- service.execute
- end
end
context 'when response_category is :error' do
@@ -200,25 +158,6 @@ RSpec.describe WebHooks::LogExecutionService do
expect { service.execute }.to change(project_hook, :backoff_count).by(1)
end
- it 'sends a message to AuthLogger if the state would change' do
- expect(Gitlab::AuthLogger).to receive(:info).with include(
- message: 'WebHook change active_state',
- # identification
- hook_id: project_hook.id,
- hook_type: project_hook.type,
- project_id: project_hook.project_id,
- group_id: nil,
- # relevant data
- prev_state: :enabled,
- new_state: :temporarily_disabled,
- duration: (be > 0),
- response_status: data[:response_status],
- recent_hook_failures: 0
- )
-
- service.execute
- 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)
diff --git a/spec/services/webauthn/authenticate_service_spec.rb b/spec/services/webauthn/authenticate_service_spec.rb
index 61f64f24f5e..b40f9465b63 100644
--- a/spec/services/webauthn/authenticate_service_spec.rb
+++ b/spec/services/webauthn/authenticate_service_spec.rb
@@ -30,19 +30,28 @@ RSpec.describe Webauthn::AuthenticateService do
get_result['clientExtensionResults'] = {}
service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
- expect(service.execute).to be_truthy
+ expect(service.execute).to eq true
end
- it 'returns false if the response is valid but no matching stored credential is present' do
- other_client = WebAuthn::FakeClient.new(origin)
- other_client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
+ context 'when response is valid but no matching stored credential is present' do
+ it 'returns false' do
+ other_client = WebAuthn::FakeClient.new(origin)
+ other_client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
- get_result = other_client.get(challenge: challenge)
+ get_result = other_client.get(challenge: challenge)
- get_result['clientExtensionResults'] = {}
- service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+ get_result['clientExtensionResults'] = {}
+ service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+
+ expect(service.execute).to eq false
+ end
+ end
- expect(service.execute).to be_falsey
+ context 'when device response includes invalid json' do
+ it 'returns false' do
+ service = Webauthn::AuthenticateService.new(user, 'invalid JSON', '')
+ expect(service.execute).to eq false
+ end
end
end
end
diff --git a/spec/services/work_items/create_and_link_service_spec.rb b/spec/services/work_items/create_and_link_service_spec.rb
index 81be15f9e2f..e259a22d388 100644
--- a/spec/services/work_items/create_and_link_service_spec.rb
+++ b/spec/services/work_items/create_and_link_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe WorkItems::CreateAndLinkService do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
- let_it_be(:related_work_item) { create(:work_item, project: project) }
+ let_it_be(:related_work_item, refind: true) { create(:work_item, project: project) }
let_it_be(:invalid_parent) { create(:work_item, :task, project: project) }
let(:spam_params) { double }
@@ -24,6 +24,26 @@ RSpec.describe WorkItems::CreateAndLinkService do
project.add_developer(user)
end
+ shared_examples 'successful work item and link creator' do
+ it 'creates a work item successfully with links' do
+ expect do
+ service_result
+ end.to change(WorkItem, :count).by(1).and(
+ change(WorkItems::ParentLink, :count).by(1)
+ )
+ end
+
+ it 'copies confidential status from the parent' do
+ expect do
+ service_result
+ end.to change(WorkItem, :count).by(1)
+
+ created_task = WorkItem.last
+
+ expect(created_task.confidential).to eq(related_work_item.confidential)
+ end
+ end
+
describe '#execute' do
subject(:service_result) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params, link_params: link_params).execute }
@@ -42,15 +62,21 @@ RSpec.describe WorkItems::CreateAndLinkService do
)
end
+ it_behaves_like 'title with extra spaces'
+
context 'when link params are valid' do
let(:link_params) { { parent_work_item: related_work_item } }
- it 'creates a work item successfully with links' do
- expect do
- service_result
- end.to change(WorkItem, :count).by(1).and(
- change(WorkItems::ParentLink, :count).by(1)
- )
+ context 'when parent is not confidential' do
+ it_behaves_like 'successful work item and link creator'
+ end
+
+ context 'when parent is confidential' do
+ before do
+ related_work_item.update!(confidential: true)
+ end
+
+ it_behaves_like 'successful work item and link creator'
end
end
diff --git a/spec/services/work_items/create_from_task_service_spec.rb b/spec/services/work_items/create_from_task_service_spec.rb
index 7d2dab228b1..7c5430f038c 100644
--- a/spec/services/work_items/create_from_task_service_spec.rb
+++ b/spec/services/work_items/create_from_task_service_spec.rb
@@ -64,6 +64,8 @@ RSpec.describe WorkItems::CreateFromTaskService do
expect(list_work_item.description).to eq("- [ ] #{created_work_item.to_reference}+")
end
+
+ it_behaves_like 'title with extra spaces'
end
context 'when last operation fails' do
diff --git a/spec/services/work_items/create_service_spec.rb b/spec/services/work_items/create_service_spec.rb
index 4009c85bacd..c0bcf9b606d 100644
--- a/spec/services/work_items/create_service_spec.rb
+++ b/spec/services/work_items/create_service_spec.rb
@@ -65,6 +65,12 @@ RSpec.describe WorkItems::CreateService do
expect(work_item.description).to eq('please fix')
expect(work_item.work_item_type.base_type).to eq('issue')
end
+
+ it 'calls NewIssueWorker with correct arguments' do
+ expect(NewIssueWorker).to receive(:perform_async).with(Integer, current_user.id, 'WorkItem')
+
+ service_result
+ end
end
context 'when params are invalid' do
@@ -170,7 +176,7 @@ RSpec.describe WorkItems::CreateService do
let_it_be(:parent) { create(:work_item, :task, project: project) }
it_behaves_like 'fails creating work item and returns errors' do
- let(:error_message) { 'only Issue and Incident can be parent of Task.'}
+ let(:error_message) { 'only Issue and Incident can be parent of Task.' }
end
end
@@ -197,7 +203,7 @@ RSpec.describe WorkItems::CreateService do
end
it_behaves_like 'fails creating work item and returns errors' do
- let(:error_message) { 'No matching task found. Make sure that you are adding a valid task ID.'}
+ let(:error_message) { 'No matching task found. Make sure that you are adding a valid task ID.' }
end
end
end
diff --git a/spec/services/work_items/parent_links/create_service_spec.rb b/spec/services/work_items/parent_links/create_service_spec.rb
index 85b0ee040cd..0ba41373544 100644
--- a/spec/services/work_items/parent_links/create_service_spec.rb
+++ b/spec/services/work_items/parent_links/create_service_spec.rb
@@ -12,10 +12,10 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
let_it_be(:task1) { create(:work_item, :task, project: project) }
let_it_be(:task2) { create(:work_item, :task, project: project) }
let_it_be(:guest_task) { create(:work_item, :task) }
- let_it_be(:invalid_task) { build_stubbed(:work_item, :task, id: non_existing_record_id)}
+ let_it_be(:invalid_task) { build_stubbed(:work_item, :task, id: non_existing_record_id) }
let_it_be(:another_project) { (create :project) }
let_it_be(:other_project_task) { create(:work_item, :task, iid: 100, project: another_project) }
- let_it_be(:existing_parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item)}
+ let_it_be(:existing_parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item) }
let(:parent_link_class) { WorkItems::ParentLink }
let(:issuable_type) { :task }
@@ -84,13 +84,26 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
expect(subject[:created_references].map(&:work_item_id)).to match_array([task1.id, task2.id])
end
+ it 'creates notes', :aggregate_failures do
+ subject
+
+ work_item_notes = work_item.notes.last(2)
+ expect(work_item_notes.first.note).to eq("added #{task1.to_reference} as child task")
+ expect(work_item_notes.last.note).to eq("added #{task2.to_reference} as child task")
+ expect(task1.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(task2.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ end
+
context 'when task is already assigned' do
let(:params) { { issuable_references: [task, task2] } }
- it 'creates links only for non related tasks' do
+ it 'creates links only for non related tasks', :aggregate_failures do
expect { subject }.to change(parent_link_class, :count).by(1)
expect(subject[:created_references].map(&:work_item_id)).to match_array([task2.id])
+ expect(work_item.notes.last.note).to eq("added #{task2.to_reference} as child task")
+ expect(task2.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(task.notes).to be_empty
end
end
@@ -109,6 +122,15 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
is_expected.to eq(service_error(error, http_status: 422))
end
+
+ it 'creates notes for valid links' do
+ subject
+
+ expect(work_item.notes.last.note).to eq("added #{task1.to_reference} as child task")
+ expect(task1.notes.last.note).to eq("added #{work_item.to_reference} as parent issue")
+ expect(issue.notes).to be_empty
+ expect(other_project_task.notes).to be_empty
+ end
end
context 'when parent type is invalid' do
diff --git a/spec/services/work_items/parent_links/destroy_service_spec.rb b/spec/services/work_items/parent_links/destroy_service_spec.rb
index 574b70af397..654a03ef6f7 100644
--- a/spec/services/work_items/parent_links/destroy_service_spec.rb
+++ b/spec/services/work_items/parent_links/destroy_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
let_it_be(:project) { create(:project) }
let_it_be(:work_item) { create(:work_item, project: project) }
let_it_be(:task) { create(:work_item, :task, project: project) }
- let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item)}
+ let_it_be(:parent_link) { create(:parent_link, work_item: task, work_item_parent: work_item) }
let(:parent_link_class) { WorkItems::ParentLink }
@@ -23,8 +23,11 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
context 'when user has permissions to update work items' do
let(:user) { reporter }
- it 'removes relation' do
+ it 'removes relation and creates notes', :aggregate_failures do
expect { subject }.to change(parent_link_class, :count).by(-1)
+
+ expect(work_item.notes.last.note).to eq("removed child task #{task.to_reference}")
+ expect(task.notes.last.note).to eq("removed parent issue #{work_item.to_reference}")
end
it 'returns success message' do
@@ -35,8 +38,10 @@ RSpec.describe WorkItems::ParentLinks::DestroyService do
context 'when user has insufficient permissions' do
let(:user) { guest }
- it 'does not remove relation' do
+ it 'does not remove relation', :aggregate_failures do
expect { subject }.not_to change(parent_link_class, :count).from(1)
+
+ expect(SystemNoteService).not_to receive(:unrelate_work_item)
end
it 'returns error message' do
diff --git a/spec/services/work_items/update_service_spec.rb b/spec/services/work_items/update_service_spec.rb
index b17c9ffb4fb..2e0b0051495 100644
--- a/spec/services/work_items/update_service_spec.rb
+++ b/spec/services/work_items/update_service_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe WorkItems::UpdateService do
let_it_be(:developer) { create(:user) }
- let_it_be(:project) { create(:project).tap { |proj| proj.add_developer(developer) } }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:project) { create(:project) }
let_it_be(:parent) { create(:work_item, project: project) }
let_it_be_with_reload(:work_item) { create(:work_item, project: project, assignees: [developer]) }
@@ -13,21 +14,36 @@ RSpec.describe WorkItems::UpdateService do
let(:opts) { {} }
let(:current_user) { developer }
+ before do
+ project.add_developer(developer)
+ project.add_guest(guest)
+ end
+
describe '#execute' do
- subject(:update_work_item) do
+ let(:service) do
described_class.new(
project: project,
current_user: current_user,
params: opts,
spam_params: spam_params,
widget_params: widget_params
- ).execute(work_item)
+ )
end
+ subject(:update_work_item) { service.execute(work_item) }
+
before do
stub_spam_services
end
+ shared_examples 'update service that triggers graphql dates updated subscription' do
+ it 'triggers graphql subscription issueableDatesUpdated' do
+ expect(GraphqlTriggers).to receive(:issuable_dates_updated).with(work_item).and_call_original
+
+ update_work_item
+ end
+ end
+
context 'when title is changed' do
let(:opts) { { title: 'changed' } }
@@ -50,6 +66,16 @@ RSpec.describe WorkItems::UpdateService do
end
end
+ context 'when dates are changed' do
+ let(:opts) { { start_date: Date.today } }
+
+ it 'tracks users updating work item dates' do
+ expect(Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter).to receive(:track_work_item_date_changed_action).with(author: current_user)
+
+ update_work_item
+ end
+ end
+
context 'when updating state_event' do
context 'when state_event is close' do
let(:opts) { { state_event: 'close' } }
@@ -82,8 +108,7 @@ RSpec.describe WorkItems::UpdateService do
let(:widget_params) do
{
hierarchy_widget: { parent: parent },
- description_widget: { description: 'foo' },
- weight_widget: { weight: 1 }
+ description_widget: { description: 'foo' }
}
end
@@ -101,8 +126,7 @@ RSpec.describe WorkItems::UpdateService do
let(:supported_widgets) do
[
- { klass: WorkItems::Widgets::DescriptionService::UpdateService, callback: :update, params: { description: 'foo' } },
- { klass: WorkItems::Widgets::WeightService::UpdateService, callback: :update, params: { weight: 1 } },
+ { klass: WorkItems::Widgets::DescriptionService::UpdateService, callback: :before_update_callback, params: { description: 'foo' } },
{ klass: WorkItems::Widgets::HierarchyService::UpdateService, callback: :before_update_in_transaction, params: { parent: parent } }
]
end
@@ -126,7 +150,7 @@ RSpec.describe WorkItems::UpdateService do
before do
allow_next_instance_of(widget_service_class) do |instance|
allow(instance)
- .to receive(:update)
+ .to receive(:before_update_callback)
.with(params: { description: 'changed' }).and_return(nil)
end
end
@@ -142,6 +166,69 @@ RSpec.describe WorkItems::UpdateService do
expect(work_item.description).to eq('changed')
end
+
+ context 'with mentions', :mailer, :sidekiq_might_not_need_inline do
+ shared_examples 'creates the todo and sends email' do |attribute|
+ it 'creates a todo and sends email' do
+ expect { perform_enqueued_jobs { update_work_item } }.to change(Todo, :count).by(1)
+ expect(work_item.reload.attributes[attribute.to_s]).to eq("mention #{guest.to_reference}")
+ should_email(guest)
+ end
+ end
+
+ context 'when description contains a user mention' do
+ let(:widget_params) { { description_widget: { description: "mention #{guest.to_reference}" } } }
+
+ it_behaves_like 'creates the todo and sends email', :description
+ end
+
+ context 'when title contains a user mention' do
+ let(:opts) { { title: "mention #{guest.to_reference}" } }
+
+ it_behaves_like 'creates the todo and sends email', :title
+ end
+ end
+
+ context 'when work item validation fails' do
+ let(:opts) { { title: '' } }
+
+ it 'returns validation errors' do
+ expect(update_work_item[:message]).to contain_exactly("Title can't be blank")
+ end
+
+ it 'does not execute after-update widgets', :aggregate_failures do
+ expect(service).to receive(:update).and_call_original
+ expect(service).not_to receive(:execute_widgets).with(callback: :update, widget_params: widget_params)
+
+ expect { update_work_item }.not_to change(work_item, :description)
+ end
+ end
+ end
+
+ context 'for start and due date widget' do
+ let(:updated_date) { 1.week.from_now.to_date }
+
+ context 'when due_date is updated' do
+ let(:widget_params) { { start_and_due_date_widget: { due_date: updated_date } } }
+
+ it_behaves_like 'update service that triggers graphql dates updated subscription'
+ end
+
+ context 'when start_date is updated' do
+ let(:widget_params) { { start_and_due_date_widget: { start_date: updated_date } } }
+
+ it_behaves_like 'update service that triggers graphql dates updated subscription'
+ end
+
+ context 'when no date param is updated' do
+ let(:opts) { { title: 'should not trigger' } }
+
+ it 'does not trigger date updated subscription' do
+ expect(GraphqlTriggers).not_to receive(:issuable_dates_updated)
+
+ update_work_item
+ end
+ end
end
context 'for the hierarchy widget' do
@@ -175,6 +262,22 @@ RSpec.describe WorkItems::UpdateService do
end.to not_change(WorkItems::ParentLink, :count).and(not_change(work_item, :title))
end
end
+
+ context 'when work item validation fails' do
+ let(:opts) { { title: '' } }
+
+ it 'returns validation errors' do
+ expect(update_work_item[:message]).to contain_exactly("Title can't be blank")
+ end
+
+ it 'does not execute after-update widgets', :aggregate_failures do
+ expect(service).to receive(:update).and_call_original
+ expect(service).not_to receive(:execute_widgets).with(callback: :before_update_in_transaction, widget_params: widget_params)
+ expect(work_item.work_item_children).not_to include(child_work_item)
+
+ update_work_item
+ end
+ end
end
end
end
diff --git a/spec/services/work_items/widgets/assignees_service/update_service_spec.rb b/spec/services/work_items/widgets/assignees_service/update_service_spec.rb
new file mode 100644
index 00000000000..0ab2c85f078
--- /dev/null
+++ b/spec/services/work_items/widgets/assignees_service/update_service_spec.rb
@@ -0,0 +1,116 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::AssigneesService::UpdateService, :freeze_time do
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:new_assignee) { create(:user) }
+
+ let(:work_item) do
+ create(:work_item, project: project, updated_at: 1.day.ago)
+ end
+
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Assignees) } }
+ let(:current_user) { reporter }
+ let(:params) { { assignee_ids: [new_assignee.id] } }
+
+ before_all do
+ project.add_reporter(reporter)
+ project.add_guest(new_assignee)
+ end
+
+ describe '#before_update_in_transaction' do
+ subject do
+ described_class.new(widget: widget, current_user: current_user)
+ .before_update_in_transaction(params: params)
+ end
+
+ it 'updates the assignees and sets updated_at to the current time' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+
+ context 'when passing an empty array' do
+ let(:params) { { assignee_ids: [] } }
+
+ before do
+ work_item.assignee_ids = [reporter.id]
+ end
+
+ it 'removes existing assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+
+ context 'when user does not have access' do
+ let(:current_user) { create(:user) }
+
+ it 'does not update the assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+
+ context 'when multiple assignees are given' do
+ let(:params) { { assignee_ids: [new_assignee.id, reporter.id] } }
+
+ context 'when work item allows multiple assignees' do
+ before do
+ allow(work_item).to receive(:allows_multiple_assignees?).and_return(true)
+ end
+
+ it 'sets all the given assignees' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id, reporter.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+
+ context 'when work item does not allow multiple assignees' do
+ before do
+ allow(work_item).to receive(:allows_multiple_assignees?).and_return(false)
+ end
+
+ it 'only sets the first assignee' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(Time.current)
+ end
+ end
+ end
+
+ context 'when assignee does not have access to the work item' do
+ let(:params) { { assignee_ids: [create(:user).id] } }
+
+ it 'does not set the assignee' do
+ subject
+
+ expect(work_item.assignee_ids).to be_empty
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+
+ context 'when assignee ids are the same as the existing ones' do
+ before do
+ work_item.assignee_ids = [new_assignee.id]
+ end
+
+ it 'does not touch updated_at' do
+ subject
+
+ expect(work_item.assignee_ids).to contain_exactly(new_assignee.id)
+ expect(work_item.updated_at).to be_like_time(1.day.ago)
+ end
+ end
+ end
+end
diff --git a/spec/services/work_items/widgets/description_service/update_service_spec.rb b/spec/services/work_items/widgets/description_service/update_service_spec.rb
index a2eceb97f09..582d9dc85f7 100644
--- a/spec/services/work_items/widgets/description_service/update_service_spec.rb
+++ b/spec/services/work_items/widgets/description_service/update_service_spec.rb
@@ -3,32 +3,102 @@
require 'spec_helper'
RSpec.describe WorkItems::Widgets::DescriptionService::UpdateService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be_with_reload(:work_item) { create(:work_item, project: project, description: 'old description') }
+ let_it_be(:random_user) { create(:user) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Description) } }
+ let(:params) { { description: 'updated description' } }
+ let(:current_user) { author }
+ let(:work_item) do
+ create(:work_item, author: author, project: project, description: 'old description',
+ last_edited_at: Date.yesterday, last_edited_by: random_user
+ )
+ end
- describe '#update' do
- subject { described_class.new(widget: widget, current_user: user).update(params: params) } # rubocop:disable Rails/SaveBang
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Description) } }
- context 'when description param is present' do
- let(:params) { { description: 'updated description' } }
+ describe '#update' do
+ subject { described_class.new(widget: widget, current_user: current_user).before_update_callback(params: params) }
+ shared_examples 'sets work item description' do
it 'correctly sets work item description value' do
subject
- expect(work_item.description).to eq('updated description')
+ expect(work_item.description).to eq(params[:description])
+ expect(work_item.last_edited_by).to eq(current_user)
+ expect(work_item.last_edited_at).to be_within(2.seconds).of(Time.current)
end
end
- context 'when description param is not present' do
- let(:params) { {} }
-
+ shared_examples 'does not set work item description' do
it 'does not change work item description value' do
subject
expect(work_item.description).to eq('old description')
+ expect(work_item.last_edited_by).to eq(random_user)
+ expect(work_item.last_edited_at).to eq(Date.yesterday)
+ end
+ end
+
+ context 'when user has permission to update description' do
+ context 'when user is work item author' do
+ let(:current_user) { author }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when user is a project reporter' do
+ let(:current_user) { reporter }
+
+ before do
+ project.add_reporter(reporter)
+ end
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description is nil' do
+ let(:current_user) { author }
+ let(:params) { { description: nil } }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description is empty' do
+ let(:current_user) { author }
+ let(:params) { { description: '' } }
+
+ it_behaves_like 'sets work item description'
+ end
+
+ context 'when description param is not present' do
+ let(:params) { {} }
+
+ it_behaves_like 'does not set work item description'
+ end
+ end
+
+ context 'when user does not have permission to update description' do
+ context 'when user is a project guest' do
+ let(:current_user) { guest }
+
+ before do
+ project.add_guest(guest)
+ end
+
+ it_behaves_like 'does not set work item description'
+ end
+
+ context 'with private project' do
+ let_it_be(:project) { create(:project) }
+
+ context 'when user is work item author' do
+ let(:current_user) { author }
+
+ it_behaves_like 'does not set work item description'
+ end
end
end
end
diff --git a/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb b/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
index 4f6ff1b8676..9a425d5308c 100644
--- a/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
+++ b/spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
let_it_be(:child_work_item) { create(:work_item, :task, project: project) }
let_it_be(:existing_link) { create(:parent_link, work_item: child_work_item, work_item_parent: work_item) }
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Hierarchy) } }
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::Hierarchy) } }
let(:not_found_error) { 'No matching task found. Make sure that you are adding a valid task ID.' }
shared_examples 'raises a WidgetError' do
@@ -29,13 +29,21 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
end
+ context 'when invalid params are present' do
+ let(:params) { { other_parent: parent_work_item } }
+
+ it_behaves_like 'raises a WidgetError' do
+ let(:message) { 'One or more arguments are invalid: other_parent.' }
+ end
+ end
+
context 'when updating children' do
let_it_be(:child_work_item2) { create(:work_item, :task, project: project) }
let_it_be(:child_work_item3) { create(:work_item, :task, project: project) }
let_it_be(:child_work_item4) { create(:work_item, :task, project: project) }
context 'when work_items_hierarchy feature flag is disabled' do
- let(:params) { { children: [child_work_item4] }}
+ let(:params) { { children: [child_work_item4] } }
before do
stub_feature_flags(work_items_hierarchy: false)
@@ -47,7 +55,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when user has insufficient permissions to link work items' do
- let(:params) { { children: [child_work_item4] }}
+ let(:params) { { children: [child_work_item4] } }
it_behaves_like 'raises a WidgetError' do
let(:message) { not_found_error }
@@ -60,7 +68,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'with valid params' do
- let(:params) { { children: [child_work_item2, child_work_item3] }}
+ let(:params) { { children: [child_work_item2, child_work_item3] } }
it 'correctly sets work item parent' do
subject
@@ -71,7 +79,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when child is already assigned' do
- let(:params) { { children: [child_work_item] }}
+ let(:params) { { children: [child_work_item] } }
it_behaves_like 'raises a WidgetError' do
let(:message) { 'Task(s) already assigned' }
@@ -81,7 +89,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
context 'when child type is invalid' do
let_it_be(:child_issue) { create(:work_item, project: project) }
- let(:params) { { children: [child_issue] }}
+ let(:params) { { children: [child_issue] } }
it_behaves_like 'raises a WidgetError' do
let(:message) do
@@ -95,7 +103,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
context 'when updating parent' do
let_it_be(:work_item) { create(:work_item, :task, project: project) }
- let(:params) {{ parent: parent_work_item } }
+ let(:params) { { parent: parent_work_item } }
context 'when work_items_hierarchy feature flag is disabled' do
before do
@@ -144,9 +152,9 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
end
context 'when type is invalid' do
- let_it_be(:parent_task) { create(:work_item, :task, project: project)}
+ let_it_be(:parent_task) { create(:work_item, :task, project: project) }
- let(:params) {{ parent: parent_task } }
+ let(:params) { { parent: parent_task } }
it_behaves_like 'raises a WidgetError' do
let(:message) do
diff --git a/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb b/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb
new file mode 100644
index 00000000000..d328c541fc7
--- /dev/null
+++ b/spec/services/work_items/widgets/start_and_due_date_service/update_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::Widgets::StartAndDueDateService::UpdateService do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:work_item) { create(:work_item, project: project) }
+
+ let(:widget) { work_item.widgets.find { |widget| widget.is_a?(WorkItems::Widgets::StartAndDueDate) } }
+
+ describe '#before_update_callback' do
+ let(:start_date) { Date.today }
+ let(:due_date) { 1.week.from_now.to_date }
+
+ subject(:update_params) do
+ described_class.new(widget: widget, current_user: user).before_update_callback(params: params)
+ end
+
+ context 'when start and due date params are present' do
+ let(:params) { { start_date: Date.today, due_date: 1.week.from_now.to_date } }
+
+ it 'correctly sets date values' do
+ expect do
+ update_params
+ end.to change(work_item, :start_date).from(nil).to(start_date).and(
+ change(work_item, :due_date).from(nil).to(due_date)
+ )
+ end
+ end
+
+ context 'when date params are not present' do
+ let(:params) { {} }
+
+ it 'does not change work item date values' do
+ expect do
+ update_params
+ end.to not_change(work_item, :start_date).from(nil).and(
+ not_change(work_item, :due_date).from(nil)
+ )
+ end
+ end
+
+ context 'when work item had both date values already set' do
+ before do
+ work_item.update!(start_date: start_date, due_date: due_date)
+ end
+
+ context 'when one of the two params is null' do
+ let(:params) { { start_date: nil } }
+
+ it 'sets only one date to null' do
+ expect do
+ update_params
+ end.to change(work_item, :start_date).from(start_date).to(nil).and(
+ not_change(work_item, :due_date).from(due_date)
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/work_items/widgets/weight_service/update_service_spec.rb b/spec/services/work_items/widgets/weight_service/update_service_spec.rb
deleted file mode 100644
index 97e17f1c526..00000000000
--- a/spec/services/work_items/widgets/weight_service/update_service_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe WorkItems::Widgets::WeightService::UpdateService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
- let_it_be_with_reload(:work_item) { create(:work_item, project: project, weight: 1) }
-
- let(:widget) { work_item.widgets.find {|widget| widget.is_a?(WorkItems::Widgets::Weight) } }
-
- describe '#update' do
- subject { described_class.new(widget: widget, current_user: user).update(params: params) } # rubocop:disable Rails/SaveBang
-
- context 'when weight param is present' do
- let(:params) { { weight: 2 } }
-
- it 'correctly sets work item weight value' do
- subject
-
- expect(work_item.weight).to eq(2)
- end
- end
-
- context 'when weight param is not present' do
- let(:params) { {} }
-
- it 'does not change work item weight value', :aggregate_failures do
- expect { subject }
- .to not_change { work_item.weight }
-
- expect(work_item.weight).to eq(1)
- end
- end
- end
-end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 47cd78873f8..8acf3bcf9c0 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -53,10 +53,8 @@ end
require 'rainbow/ext/string'
Rainbow.enabled = false
-# Require JH first because we need override some EE methods with JH methods,
-# if we load EE first, we can't find JH modules in prepend_mod method
-require_relative('../jh/spec/spec_helper') if Gitlab.jh?
require_relative('../ee/spec/spec_helper') if Gitlab.ee?
+require_relative('../jh/spec/spec_helper') if Gitlab.jh?
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
@@ -161,7 +159,6 @@ RSpec.configure do |config|
config.include LicenseHelpers
config.include ActiveJob::TestHelper
config.include ActiveSupport::Testing::TimeHelpers
- config.include CycleAnalyticsHelpers
config.include FactoryBot::Syntax::Methods
config.include FixtureHelpers
config.include NonExistingRecordsHelpers
@@ -208,6 +205,7 @@ RSpec.configure do |config|
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.
@@ -334,6 +332,9 @@ 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
@@ -391,6 +392,11 @@ RSpec.configure do |config|
Gitlab::WithRequestStore.with_request_store { example.run }
end
+ config.around(:example, :enable_rugged) do |example|
+ # Skip tests that need rugged when using praefect DB.
+ example.run unless GitalySetup.praefect_with_db?
+ end
+
# previous test runs may have left some resources throttled
config.before do
::Gitlab::ExclusiveLease.reset_all!("el:throttle:*")
@@ -505,3 +511,16 @@ module TouchRackUploadedFile
end
Rack::Test::UploadedFile.prepend(TouchRackUploadedFile)
+
+# Monkey-patch to enable ActiveSupport::Notifications for Redis commands
+module RedisCommands
+ module Instrumentation
+ def process(commands, &block)
+ ActiveSupport::Notifications.instrument('redis.process_commands', commands: commands) do
+ super(commands, &block)
+ end
+ end
+ end
+end
+
+Redis::Client.prepend(RedisCommands::Instrumentation)
diff --git a/spec/support/database/cross-join-allowlist.yml b/spec/support/database/cross-join-allowlist.yml
index 19b1ce30d5f..fe51488c706 100644
--- a/spec/support/database/cross-join-allowlist.yml
+++ b/spec/support/database/cross-join-allowlist.yml
@@ -1,6 +1 @@
-- "./spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb"
-- "./spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb"
-- "./spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb"
-- "./spec/migrations/associate_existing_dast_builds_with_variables_spec.rb"
-- "./spec/migrations/disable_job_token_scope_when_unused_spec.rb"
-- "./spec/migrations/schedule_copy_ci_builds_columns_to_security_scans2_spec.rb"
+[]
diff --git a/spec/support/database/gitlab_schemas_validate_connection.rb b/spec/support/database/gitlab_schemas_validate_connection.rb
new file mode 100644
index 00000000000..118c6ea5001
--- /dev/null
+++ b/spec/support/database/gitlab_schemas_validate_connection.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ def with_gitlab_schemas_validate_connection_prevented
+ Gitlab::Database::QueryAnalyzers::GitlabSchemasValidateConnection.with_suppressed do
+ yield
+ end
+ end
+
+ config.around(:each, :suppress_gitlab_schemas_validate_connection) do |example|
+ with_gitlab_schemas_validate_connection_prevented(&example)
+ end
+
+ config.around(:each, query_analyzers: false) do |example|
+ with_gitlab_schemas_validate_connection_prevented(&example)
+ end
+end
diff --git a/spec/support/database/multiple_databases.rb b/spec/support/database/multiple_databases.rb
index 94857b47127..05f26e57e9c 100644
--- a/spec/support/database/multiple_databases.rb
+++ b/spec/support/database/multiple_databases.rb
@@ -98,6 +98,26 @@ RSpec.configure do |config|
example.run
end
end
+
+ config.around(:each, :migration) do |example|
+ 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
+
+ # Migration require an `ActiveRecord::Base` to point to desired database
+ if base_model != ActiveRecord::Base
+ with_reestablished_active_record_base do
+ reconfigure_db_connection(
+ model: ActiveRecord::Base,
+ config_model: base_model
+ )
+
+ example.run
+ end
+ else
+ example.run
+ end
+ end
end
ActiveRecord::Base.singleton_class.prepend(::Database::ActiveRecordBaseEstablishConnection) # rubocop:disable Database/MultipleDatabases
diff --git a/spec/support/finder_collection_allowlist.yml b/spec/support/finder_collection_allowlist.yml
index 8f09153afec..1ac8e49fb45 100644
--- a/spec/support/finder_collection_allowlist.yml
+++ b/spec/support/finder_collection_allowlist.yml
@@ -57,6 +57,8 @@
- Security::ScanExecutionPoliciesFinder
- Security::TrainingProviders::BaseUrlFinder
- Security::TrainingUrlsFinder
+- Security::TrainingProviders::KontraUrlFinder
+- Security::TrainingProviders::SecureCodeWarriorUrlFinder
- SentryIssueFinder
- ServerlessDomainFinder
- TagsFinder
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index fd85071cca3..62bb9576695 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -19,15 +19,17 @@ module ApiHelpers
# => "/api/v2/issues?foo=bar&private_token=..."
#
# Returns the relative path to the requested API resource
- def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil, job_token: nil)
+ def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil, job_token: nil, access_token: nil)
full_path = "/api/#{version}#{path}"
if oauth_access_token
- query_string = "access_token=#{oauth_access_token.token}"
+ query_string = "access_token=#{oauth_access_token.plaintext_token}"
elsif personal_access_token
query_string = "private_token=#{personal_access_token.token}"
elsif job_token
query_string = "job_token=#{job_token}"
+ elsif access_token
+ query_string = "access_token=#{access_token.token}"
elsif user
personal_access_token = create(:personal_access_token, user: user)
query_string = "private_token=#{personal_access_token.token}"
@@ -66,6 +68,13 @@ module ApiHelpers
expect(json_response.map { |item| item['id'] }).to contain_exactly(*items)
end
+ def expect_paginated_array_response_contain_exactly(*items)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |item| item['id'] }).to contain_exactly(*items)
+ end
+
def stub_last_activity_update
allow_any_instance_of(Users::ActivityService).to receive(:execute)
end
diff --git a/spec/support/helpers/ci/template_helpers.rb b/spec/support/helpers/ci/template_helpers.rb
index 598a5a0becc..119f8d001a1 100644
--- a/spec/support/helpers/ci/template_helpers.rb
+++ b/spec/support/helpers/ci/template_helpers.rb
@@ -5,6 +5,10 @@ module Ci
def secure_analyzers_prefix
'registry.gitlab.com/security-products'
end
+
+ def template_registry_host
+ 'registry.gitlab.com'
+ end
end
end
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 044ec56b1cc..05e9a099a2b 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
module CycleAnalyticsHelpers
- include GitHelpers
-
def toggle_value_stream_dropdown
page.find('[data-testid="dropdown-value-streams"]').click
end
@@ -129,10 +127,6 @@ module CycleAnalyticsHelpers
repository = project.repository
oldrev = repository.commit(branch_name)&.sha || Gitlab::Git::BLANK_SHA
- if Timecop.frozen?
- mock_gitaly_multi_action_dates(repository, commit_time)
- end
-
commit_shas = Array.new(count) do |index|
commit_sha = repository.create_file(user, generate(:branch), "content", message: message, branch_name: branch_name)
repository.commit(commit_sha)
@@ -241,23 +235,4 @@ module CycleAnalyticsHelpers
pipeline: dummy_pipeline(project),
protected: false)
end
-
- def mock_gitaly_multi_action_dates(repository, commit_time)
- allow(repository.raw).to receive(:multi_action).and_wrap_original do |m, user, kargs|
- new_date = commit_time || Time.now
- branch_update = m.call(user, **kargs)
-
- if branch_update.newrev
- commit = rugged_repo(repository).rev_parse(branch_update.newrev)
-
- branch_update.newrev = commit.amend(
- update_ref: "#{Gitlab::Git::BRANCH_REF_PREFIX}#{kargs[:branch_name]}",
- author: commit.author.merge(time: new_date),
- committer: commit.committer.merge(time: new_date)
- )
- end
-
- branch_update
- end
- end
end
diff --git a/spec/support/helpers/dns_helpers.rb b/spec/support/helpers/dns_helpers.rb
index b941e7c4808..c60c14f10a3 100644
--- a/spec/support/helpers/dns_helpers.rb
+++ b/spec/support/helpers/dns_helpers.rb
@@ -5,6 +5,7 @@ module DnsHelpers
stub_all_dns!
stub_invalid_dns!
permit_local_dns!
+ permit_postgresql!
end
def permit_dns!
@@ -25,14 +26,30 @@ module DnsHelpers
def permit_local_dns!
local_addresses = %r{
\A
- ::1? | # IPV6
- (127|10)\.0\.0\.\d{1,3} | # 127.0.0.x or 10.0.0.x local network
- (192\.168|172\.16)\.\d{1,3}\.\d{1,3} | # 192.168.x.x or 172.16.x.x local network
- 0\.0\.0\.0 | # loopback
+ ::1? | # IPV6
+ (127|10)\.0\.0\.\d{1,3} | # 127.0.0.x or 10.0.0.x local network
+ 192\.168\.\d{1,3}\.\d{1,3} | # 192.168.x.x local network
+ 172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3} | # 172.16.x.x - 172.31.x.x local network
+ 0\.0\.0\.0 | # loopback
localhost
\z
}xi
allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM).and_call_original
allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM, anything, anything, any_args).and_call_original
end
+
+ # pg v1.4.0, unlike v1.3.5, uses AddrInfo.getaddrinfo to resolve IPv4 and IPv6 addresses:
+ # https://github.com/ged/ruby-pg/pull/459
+ def permit_postgresql!
+ db_hosts.each do |host|
+ next if host.start_with?('/') # Exclude UNIX sockets
+
+ # https://github.com/ged/ruby-pg/blob/252512608a814de16bbad55911f9bbcef0e73cb9/lib/pg/connection.rb#L720
+ allow(Addrinfo).to receive(:getaddrinfo).with(host, anything, nil, :STREAM).and_call_original
+ end
+ end
+
+ def db_hosts
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).map(&:host).compact.uniq
+ end
end
diff --git a/spec/support/helpers/features/blob_spec_helpers.rb b/spec/support/helpers/features/blob_spec_helpers.rb
index 880a7249284..7ccfc9be7e2 100644
--- a/spec/support/helpers/features/blob_spec_helpers.rb
+++ b/spec/support/helpers/features/blob_spec_helpers.rb
@@ -11,12 +11,4 @@ module BlobSpecHelpers
def unset_default_button
set_default_button('')
end
-
- def editor_value
- evaluate_script('monaco.editor.getModels()[0].getValue()')
- end
-
- def set_editor_value(value)
- execute_script("monaco.editor.getModels()[0].setValue('#{value}')")
- end
end
diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb
index b56ac5b32c6..d02ec06d886 100644
--- a/spec/support/helpers/features/invite_members_modal_helper.rb
+++ b/spec/support/helpers/features/invite_members_modal_helper.rb
@@ -11,7 +11,7 @@ module Spec
page.within invite_modal_selector do
select_members(names)
choose_options(role, expires_at)
- click_button 'Invite'
+ submit_invites
end
page.refresh if refresh
@@ -42,11 +42,15 @@ module Spec
click_button name
choose_options(role, expires_at)
- click_button 'Invite'
+ submit_invites
page.refresh
end
+ def submit_invites
+ click_button 'Invite'
+ end
+
def choose_options(role, expires_at)
unless role == 'Guest'
click_button 'Guest'
@@ -86,12 +90,47 @@ module Spec
"[data-token-id='#{id}']"
end
+ def more_invite_errors_button_selector
+ "[data-testid='accordion-button']"
+ end
+
+ def limited_invite_error_selector
+ "[data-testid='errors-limited-item']"
+ end
+
+ def expanded_invite_error_selector
+ "[data-testid='errors-expanded-item']"
+ end
+
def remove_token(id)
page.within member_token_selector(id) do
find('[data-testid="close-icon"]').click
end
end
+ def expect_to_have_successful_invite_indicator(page, user)
+ expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100")
+ expect(page).not_to have_text("#{user.name}: ")
+ end
+
+ def expect_to_have_invalid_invite_indicator(page, user, message: true)
+ expect(page).to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100")
+ expect(page).to have_selector(member_token_error_selector(user.id))
+ expect(page).to have_text("#{user.name}: Access level should be greater than or equal to") if message
+ end
+
+ def expect_to_have_normal_invite_indicator(page, user)
+ expect(page).to have_selector(member_token_selector(user.id))
+ expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-red-100")
+ expect(page).not_to have_selector("#{member_token_selector(user.id)} .gl-bg-green-100")
+ expect(page).not_to have_text("#{user.name}: ")
+ end
+
+ def expect_to_have_invite_removed(page, user)
+ expect(page).not_to have_selector(member_token_selector(user.id))
+ expect(page).not_to have_text("#{user.name}: Access level should be greater than or equal to")
+ end
+
def expect_to_have_group(group)
expect(page).to have_selector("[entity-id='#{group.id}']")
end
diff --git a/spec/support/helpers/features/runner_helpers.rb b/spec/support/helpers/features/runners_helpers.rb
index 63fc628358c..63fc628358c 100644
--- a/spec/support/helpers/features/runner_helpers.rb
+++ b/spec/support/helpers/features/runners_helpers.rb
diff --git a/spec/support/helpers/features/source_editor_spec_helpers.rb b/spec/support/helpers/features/source_editor_spec_helpers.rb
index cdc59f9cbe1..f7eb2a52507 100644
--- a/spec/support/helpers/features/source_editor_spec_helpers.rb
+++ b/spec/support/helpers/features/source_editor_spec_helpers.rb
@@ -12,8 +12,11 @@ module Spec
def editor_set_value(value)
editor = find('.monaco-editor')
uri = editor['data-uri']
+ execute_script("localMonaco.getModel('#{uri}').setValue('#{escape_javascript(value)}')")
- execute_script("monaco.editor.getModel('#{uri}').setValue('#{escape_javascript(value)}')")
+ # We only check that the first line is present because when the content is long,
+ # only a part of the text will be rendered in the DOM due to scrolling
+ page.has_selector?('.gl-source-editor .view-lines', text: value.lines.first)
end
end
end
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 56993fc27b7..278dc79e1d0 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -12,6 +12,8 @@ require 'logger'
require 'fileutils'
require 'bundler'
+require_relative '../../../lib/gitlab/utils'
+
module GitalySetup
extend self
@@ -139,7 +141,7 @@ module GitalySetup
end
def start_praefect
- if ENV['GITALY_PRAEFECT_WITH_DB']
+ if praefect_with_db?
LOGGER.debug 'Starting Praefect with database election strategy'
start(:praefect, File.join(tmp_tests_gitaly_dir, 'praefect-db.config.toml'))
else
@@ -290,7 +292,7 @@ module GitalySetup
# In CI we need to pre-generate both config files.
# For local testing we'll create the correct file on-demand.
- if ENV['CI'] || ENV['GITALY_PRAEFECT_WITH_DB'].nil?
+ if ENV['CI'] || !praefect_with_db?
Gitlab::SetupHelper::Praefect.create_configuration(
gitaly_dir,
{ 'praefect' => repos_path },
@@ -298,7 +300,7 @@ module GitalySetup
)
end
- if ENV['CI'] || ENV['GITALY_PRAEFECT_WITH_DB']
+ if ENV['CI'] || praefect_with_db?
Gitlab::SetupHelper::Praefect.create_configuration(
gitaly_dir,
{ 'praefect' => repos_path },
@@ -319,7 +321,7 @@ module GitalySetup
end
def setup_praefect
- return unless ENV['GITALY_PRAEFECT_WITH_DB']
+ return unless praefect_with_db?
migrate_cmd = service_cmd(:praefect, File.join(tmp_tests_gitaly_dir, 'praefect-db.config.toml')) + ['sql-migrate']
system(env, *migrate_cmd, [:out, :err] => 'log/praefect-test.log')
@@ -396,4 +398,8 @@ module GitalySetup
def praefect_binary
File.join(tmp_tests_gitaly_dir, "_build", "bin", "praefect")
end
+
+ def praefect_with_db?
+ Gitlab::Utils.to_boolean(ENV['GITALY_PRAEFECT_WITH_DB'], default: false)
+ end
end
diff --git a/spec/support/helpers/global_id_deprecation_helpers.rb b/spec/support/helpers/global_id_deprecation_helpers.rb
index 37ba1420fb3..5c6862ca84a 100644
--- a/spec/support/helpers/global_id_deprecation_helpers.rb
+++ b/spec/support/helpers/global_id_deprecation_helpers.rb
@@ -2,9 +2,11 @@
module GlobalIDDeprecationHelpers
def stub_global_id_deprecations(*deprecations)
- old_name_map = deprecations.index_by(&:old_model_name)
- new_name_map = deprecations.index_by(&:new_model_name)
- old_graphql_name_map = deprecations.index_by { |d| Types::GlobalIDType.model_name_to_graphql_name(d.old_model_name) }
+ old_name_map = deprecations.index_by(&:old_name)
+ new_name_map = deprecations.index_by(&:new_name)
+ old_graphql_name_map = deprecations.index_by do |d|
+ Gitlab::GlobalId::Deprecations.map_graphql_name(d.old_name)
+ end
stub_const('Gitlab::GlobalId::Deprecations::OLD_NAME_MAP', old_name_map)
stub_const('Gitlab::GlobalId::Deprecations::NEW_NAME_MAP', new_name_map)
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index d0a1941817a..d78c523decd 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -170,7 +170,7 @@ module GraphqlHelpers
# or `prepare` in app/graphql/types/range_input_type.rb, used by Types::TimeframeInputType
def args_internal(field, args:, query_ctx:, parent:, extras:, query:)
arguments = GraphqlHelpers.deep_transform_args(args, field)
- arguments.merge!(extras.reject {|k, v| v == :not_given})
+ arguments.merge!(extras.reject { |k, v| v == :not_given })
end
# Pros:
@@ -185,7 +185,7 @@ module GraphqlHelpers
# take internal style args, and force them into client style args
def args_internal_prepared(field, args:, query_ctx:, parent:, extras:, query:)
arguments = GraphqlHelpers.as_graphql_argument_literals(args)
- arguments.merge!(extras.reject {|k, v| v == :not_given})
+ arguments.merge!(extras.reject { |k, v| v == :not_given })
# Use public API to properly prepare the args for use by the resolver.
# It uses `coerce_arguments` under the covers
@@ -307,14 +307,14 @@ module GraphqlHelpers
end
def graphql_mutation(name, input, fields = nil, &block)
- raise ArgumentError, 'Please pass either `fields` parameter or a block to `#graphql_mutation`, but not both.' if fields.present? && block_given?
+ raise ArgumentError, 'Please pass either `fields` parameter or a block to `#graphql_mutation`, but not both.' if fields.present? && block
name = name.graphql_name if name.respond_to?(:graphql_name)
mutation_name = GraphqlHelpers.fieldnamerize(name)
input_variable_name = "$#{input_variable_name_for_mutation(name)}"
mutation_field = GitlabSchema.mutation.fields[mutation_name]
- fields = yield if block_given?
+ fields = yield if block
fields ||= all_graphql_fields_for(mutation_field.type.to_type_signature)
query = <<~MUTATION
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 84cd0181533..32e6e8d50bd 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -2,6 +2,7 @@
require 'action_dispatch/testing/test_request'
require 'fileutils'
+require 'graphlyte'
require_relative '../../../lib/gitlab/popen'
@@ -47,7 +48,8 @@ module JavaScriptFixturesHelpers
path = Rails.root / base / query_path
queries = Gitlab::Graphql::Queries.find(path)
if queries.length == 1
- queries.first.text(mode: Gitlab.ee? ? :ee : :ce )
+ query = queries.first.text(mode: Gitlab.ee? ? :ee : :ce )
+ inflate_query_with_typenames(query)
else
raise "Could not find query file at #{path}, please check your query_path" % path
end
@@ -55,6 +57,23 @@ module JavaScriptFixturesHelpers
private
+ # Private: Parse a GraphQL query and inflate the fields with a __typename
+ #
+ # query - the GraqhQL query to parse
+ def inflate_query_with_typenames(query, doc: Graphlyte.parse(query))
+ typename_editor.edit(doc)
+
+ doc.to_s
+ end
+
+ def typename_editor
+ typename = Graphlyte::Syntax::Field.new(name: '__typename')
+
+ @editor ||= Graphlyte::Editor.new.on_field do |field|
+ field.selection << typename unless field.selection.empty? || field.selection.map(&:name).include?('__typename')
+ end
+ end
+
# Private: Store a response object as fixture file
#
# response - string or response object to store
diff --git a/spec/support/helpers/lfs_http_helpers.rb b/spec/support/helpers/lfs_http_helpers.rb
index 199d5e70e32..91ed56b4d13 100644
--- a/spec/support/helpers/lfs_http_helpers.rb
+++ b/spec/support/helpers/lfs_http_helpers.rb
@@ -52,11 +52,9 @@ module LfsHttpHelpers
end
def request_body(operation, objects)
- objects = [objects] unless objects.is_a?(Array)
-
{
'operation' => operation,
- 'objects' => objects
+ 'objects' => Array.wrap(objects)
}
end
end
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index c93ef8b0ead..f83f5c7bfde 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -91,12 +91,12 @@ module LoginHelpers
# user - User instance to login with
# remember - Whether or not to check "Remember me" (default: false)
# two_factor_auth - If two-factor authentication is enabled (default: false)
- # password - password to attempt to login with
+ # password - password to attempt to login with (default: user.password)
def gitlab_sign_in_with(user, remember: false, two_factor_auth: false, password: nil)
visit new_user_session_path
fill_in "user_login", with: user.email
- fill_in "user_password", with: (password || "12345678")
+ fill_in "user_password", with: (password || user.password)
check 'user_remember_me' if remember
find('[data-testid="sign-in-button"]:enabled').click
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index 01839a74e65..dd124ed9c7f 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -14,7 +14,7 @@ module ActiveRecord
@skip_schema_queries = skip_schema_queries
@query_recorder_debug = ENV['QUERY_RECORDER_DEBUG'] || query_recorder_debug
@log_file = log_file
- record(&block) if block_given?
+ record(&block) if block
end
def record(&block)
diff --git a/spec/support/helpers/rack_attack_spec_helpers.rb b/spec/support/helpers/rack_attack_spec_helpers.rb
index 6c06781df03..2502889e17c 100644
--- a/spec/support/helpers/rack_attack_spec_helpers.rb
+++ b/spec/support/helpers/rack_attack_spec_helpers.rb
@@ -17,8 +17,12 @@ module RackAttackSpecHelpers
{ Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => personal_access_token.token }
end
+ def bearer_headers(token)
+ { 'AUTHORIZATION' => "Bearer #{token.token}" }
+ end
+
def oauth_token_headers(oauth_access_token)
- { 'AUTHORIZATION' => "Bearer #{oauth_access_token.token}" }
+ { 'AUTHORIZATION' => "Bearer #{oauth_access_token.plaintext_token}" }
end
def basic_auth_headers(user, personal_access_token)
diff --git a/spec/support/helpers/redis_commands/recorder.rb b/spec/support/helpers/redis_commands/recorder.rb
new file mode 100644
index 00000000000..05a1aa67853
--- /dev/null
+++ b/spec/support/helpers/redis_commands/recorder.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module RedisCommands
+ class Recorder
+ def initialize(pattern: nil, &block)
+ @log = []
+ @pattern = pattern
+
+ record(&block) if block
+ end
+
+ attr_reader :log
+
+ def record(&block)
+ ActiveSupport::Notifications.subscribed(method(:callback), 'redis.process_commands', &block)
+ end
+
+ def by_command(command)
+ @log.select { |record| record.include?(command) }
+ end
+
+ def count
+ @count ||= @log.count
+ end
+
+ private
+
+ def callback(name, start, finish, message_id, values)
+ commands = values[:commands]
+
+ @log << commands.flatten if @pattern.nil? || commands.to_s.include?(@pattern)
+ end
+ end
+end
diff --git a/spec/support/helpers/runner_releases_helper.rb b/spec/support/helpers/runner_releases_helper.rb
new file mode 100644
index 00000000000..ab16a705425
--- /dev/null
+++ b/spec/support/helpers/runner_releases_helper.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module RunnerReleasesHelper
+ def stub_runner_releases(available_runner_releases, gitlab_version: nil)
+ # We stub the behavior of RunnerReleases so that we don't need to rely on flaky global settings
+ available_runner_releases = available_runner_releases
+ .map { |v| ::Gitlab::VersionInfo.parse(v, parse_suffix: true) }
+ .sort
+ releases_by_minor = available_runner_releases
+ .group_by(&:without_patch)
+ .transform_values(&:max)
+
+ runner_releases_double = instance_double(Gitlab::Ci::RunnerReleases)
+ allow(::Gitlab::Ci::RunnerUpgradeCheck).to receive(:new).and_wrap_original do |method, *_original_args|
+ gitlab_version ||= available_runner_releases.max
+ method.call(gitlab_version, runner_releases_double)
+ end
+
+ allow(runner_releases_double).to receive(:releases).and_return(available_runner_releases)
+ allow(runner_releases_double).to receive(:releases_by_minor).and_return(releases_by_minor)
+ end
+end
diff --git a/spec/support/helpers/stub_member.rb b/spec/support/helpers/stub_member.rb
new file mode 100644
index 00000000000..bcd0b675041
--- /dev/null
+++ b/spec/support/helpers/stub_member.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module StubMember
+ def self.included(base)
+ Member.prepend(StubbedMember::Member)
+ ProjectMember.prepend(StubbedMember::ProjectMember)
+ end
+end
diff --git a/spec/support/helpers/stub_method_calls.rb b/spec/support/helpers/stub_method_calls.rb
index 45d704958ca..ccbede16563 100644
--- a/spec/support/helpers/stub_method_calls.rb
+++ b/spec/support/helpers/stub_method_calls.rb
@@ -44,7 +44,7 @@ module StubMethodCalls
end
def self.stub_method(object, method, &block)
- raise ArgumentError, "Block is required" unless block_given?
+ raise ArgumentError, "Block is required" unless block
backup_method(object, method) unless backed_up_method?(object, method)
object.define_singleton_method(method, &block)
diff --git a/spec/support/helpers/stubbed_member.rb b/spec/support/helpers/stubbed_member.rb
new file mode 100644
index 00000000000..27420c9b709
--- /dev/null
+++ b/spec/support/helpers/stubbed_member.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# Extend the ProjectMember & GroupMember class with the ability to
+# to run project_authorizations refresh jobs inline.
+
+# This is needed so that calls like `group.add_member(user, access_level)` or `create(:project_member)`
+# in the specs can be run without including `:sidekiq_inline` trait.
+module StubbedMember
+ extend ActiveSupport::Concern
+
+ module Member
+ private
+
+ def refresh_member_authorized_projects(blocking:)
+ return super unless blocking
+
+ AuthorizedProjectsWorker.new.perform(user_id)
+ end
+ end
+
+ module ProjectMember
+ private
+
+ def blocking_project_authorizations_refresh
+ AuthorizedProjectUpdate::ProjectRecalculatePerUserWorker.new.perform(project.id, user.id)
+ end
+ end
+end
diff --git a/spec/support/helpers/type_name_deprecation_helpers.rb b/spec/support/helpers/type_name_deprecation_helpers.rb
new file mode 100644
index 00000000000..591737ab532
--- /dev/null
+++ b/spec/support/helpers/type_name_deprecation_helpers.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module TypeNameDeprecationHelpers
+ def stub_type_name_deprecations(*deprecations)
+ old_name_map = deprecations.index_by(&:old_name)
+ new_name_map = deprecations.index_by(&:new_name)
+ old_graphql_name_map = deprecations.index_by do |d|
+ Gitlab::Graphql::TypeNameDeprecations.map_graphql_name(d.old_name)
+ end
+
+ stub_const('Gitlab::Graphql::TypeNameDeprecations::OLD_NAME_MAP', old_name_map)
+ stub_const('Gitlab::Graphql::TypeNameDeprecations::NEW_NAME_MAP', new_name_map)
+ stub_const('Gitlab::Graphql::TypeNameDeprecations::OLD_GRAPHQL_NAME_MAP', old_graphql_name_map)
+ end
+end
diff --git a/spec/support/matchers/event_store.rb b/spec/support/matchers/event_store.rb
index 14f6a42d7f4..4ecb924b3ed 100644
--- a/spec/support/matchers/event_store.rb
+++ b/spec/support/matchers/event_store.rb
@@ -23,8 +23,8 @@ RSpec::Matchers.define :publish_event do |expected_event_class|
def match_data?(actual, expected)
values_match?(actual.keys, expected.keys) &&
- actual.keys.each do |key|
- values_match?(actual[key], expected[key])
+ actual.keys.all? do |key|
+ values_match?(expected[key], actual[key])
end
end
diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb
index 1932f78506f..8bec3be2535 100644
--- a/spec/support/matchers/markdown_matchers.rb
+++ b/spec/support/matchers/markdown_matchers.rb
@@ -189,8 +189,10 @@ module MarkdownMatchers
match do |actual|
expect(actual).to have_selector('ul.task-list', count: 2)
- expect(actual).to have_selector('li.task-list-item', count: 7)
+ expect(actual).to have_selector('li.task-list-item', count: 9)
+ expect(actual).to have_selector('li.task-list-item.inapplicable > s', count: 2)
expect(actual).to have_selector('input[checked]', count: 3)
+ expect(actual).to have_selector('input[data-inapplicable]', count: 2)
end
end
diff --git a/spec/support/shared_contexts/bulk_imports_requests_shared_context.rb b/spec/support/shared_contexts/bulk_imports_requests_shared_context.rb
index 62d708420c3..5fcb14e075a 100644
--- a/spec/support/shared_contexts/bulk_imports_requests_shared_context.rb
+++ b/spec/support/shared_contexts/bulk_imports_requests_shared_context.rb
@@ -12,17 +12,17 @@ RSpec.shared_context 'bulk imports requests context' do |url|
}
end
- let(:request_headers) { { 'Authorization' => 'Bearer demo-pat', 'Content-Type' => 'application/json' } }
+ let(:request_headers) { { 'Content-Type' => 'application/json' } }
before do
- stub_request(:get, "#{url}/api/v4/version")
+ stub_request(:get, "#{url}/api/v4/version?page=1&per_page=20&private_token=demo-pat")
.with(headers: request_headers)
.to_return(
status: 200,
body: { version: ::BulkImport.min_gl_version_for_project_migration.to_s }.to_json,
headers: { 'Content-Type' => 'application/json' })
- stub_request(:get, "https://gitlab.example.com/api/v4/groups?min_access_level=50&page=1&per_page=20&search=test&top_level_only=true")
+ stub_request(:get, "https://gitlab.example.com/api/v4/groups?min_access_level=50&page=1&per_page=20&private_token=demo-pat&search=test&top_level_only=true")
.with(headers: request_headers)
.to_return(status: 200,
body: [{
@@ -33,10 +33,9 @@ RSpec.shared_context 'bulk imports requests context' do |url|
full_name: 'Test',
full_path: 'stub-test-group'
}].to_json,
- headers: page_response_headers
- )
+ headers: page_response_headers)
- stub_request(:get, "%{url}/api/v4/groups?page=1&per_page=20&top_level_only=true&min_access_level=50&search=" % { url: url })
+ stub_request(:get, "%{url}/api/v4/groups?min_access_level=50&page=1&per_page=20&private_token=demo-pat&search=&top_level_only=true" % { url: url })
.to_return(
body: [{
id: 2595438,
@@ -46,7 +45,6 @@ RSpec.shared_context 'bulk imports requests context' do |url|
full_name: 'Stub',
full_path: 'stub-group'
}].to_json,
- headers: page_response_headers
- )
+ headers: page_response_headers)
end
end
diff --git a/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
index 255c4e6f882..ca2fe8a6c54 100644
--- a/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
+++ b/spec/support/shared_contexts/features/integrations/integrations_shared_context.rb
@@ -66,7 +66,7 @@ Integration.available_integration_names.each do |integration|
hash.merge!(k => 'foo@bar.com')
elsif (integration == 'slack' || integration == 'mattermost') && k == :labels_to_be_notified_behavior
hash.merge!(k => "match_any")
- elsif integration == 'campfire' && k = :room
+ elsif integration == 'campfire' && k == :room
hash.merge!(k => '1234')
else
hash.merge!(k => "someword")
diff --git a/spec/support/shared_contexts/fixtures/analytics_shared_context.rb b/spec/support/shared_contexts/fixtures/analytics_shared_context.rb
index 13d3697a378..8e09cccee3e 100644
--- a/spec/support/shared_contexts/fixtures/analytics_shared_context.rb
+++ b/spec/support/shared_contexts/fixtures/analytics_shared_context.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
RSpec.shared_context 'Analytics fixtures shared context' do
+ include CycleAnalyticsHelpers
include JavaScriptFixturesHelpers
let_it_be(:group) { create(:group) }
diff --git a/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb
index 449db59e35d..b6c54e902a2 100644
--- a/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb
+++ b/spec/support/shared_contexts/lib/gitlab/sidekiq_middleware/server_metrics_shared_context.rb
@@ -17,6 +17,7 @@ RSpec.shared_context 'server metrics with mocked prometheus' do
let(:elasticsearch_seconds_metric) { double('elasticsearch seconds metric') }
let(:elasticsearch_requests_total) { double('elasticsearch calls total metric') }
let(:load_balancing_metric) { double('load balancing metric') }
+ let(:sidekiq_mem_total_bytes) { double('sidekiq mem total bytes') }
before do
allow(Gitlab::Metrics).to receive(:histogram).and_call_original
@@ -37,6 +38,7 @@ RSpec.shared_context 'server metrics with mocked prometheus' do
allow(Gitlab::Metrics).to receive(:counter).with(:sidekiq_load_balancing_count, anything).and_return(load_balancing_metric)
allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_running_jobs, anything, {}, :all).and_return(running_jobs_metric)
allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_concurrency, anything, {}, :all).and_return(concurrency_metric)
+ allow(Gitlab::Metrics).to receive(:gauge).with(:sidekiq_mem_total_bytes, anything, {}, :all).and_return(sidekiq_mem_total_bytes)
allow(concurrency_metric).to receive(:set)
end
@@ -61,13 +63,16 @@ RSpec.shared_context 'server metrics call' do
let(:elasticsearch_calls) { 8 }
let(:elasticsearch_duration) { 0.54 }
+
+ let(:mem_total_bytes) { 1000000000 }
let(:instrumentation) do
{
gitaly_duration_s: gitaly_duration,
redis_calls: redis_calls,
redis_duration_s: redis_duration,
elasticsearch_calls: elasticsearch_calls,
- elasticsearch_duration_s: elasticsearch_duration
+ elasticsearch_duration_s: elasticsearch_duration,
+ mem_total_bytes: mem_total_bytes
}
end
@@ -95,5 +100,6 @@ RSpec.shared_context 'server metrics call' do
allow(completion_seconds_metric).to receive(:observe)
allow(redis_seconds_metric).to receive(:observe)
allow(elasticsearch_seconds_metric).to receive(:observe)
+ allow(sidekiq_mem_total_bytes).to receive(:set)
end
end
diff --git a/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb b/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
index a90fe9e1723..040b2da9f37 100644
--- a/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
+++ b/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
@@ -9,6 +9,9 @@ RSpec.shared_context 'with API::Markdown Snapshot shared context' do |glfm_speci
# rubocop:enable Layout/LineLength
include ApiHelpers
+ let_it_be(:user) { create(:user) }
+ let_it_be(:api_url) { api('/markdown', user) }
+
markdown_examples, html_examples = %w[markdown.yml html.yml].map do |file_name|
yaml = File.read("#{glfm_specification_dir}/example_snapshots/#{file_name}")
YAML.safe_load(yaml, symbolize_names: true, aliases: true)
@@ -29,8 +32,6 @@ RSpec.shared_context 'with API::Markdown Snapshot shared context' do |glfm_speci
let(:normalizations) { normalizations_by_example_name.dig(name, :html, :static, :snapshot) }
it "verifies conversion of GLFM to HTML", :unlimited_max_formatted_output_length do
- api_url = api "/markdown"
-
# noinspection RubyResolve
normalized_html = normalize_html(html, normalizations)
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 eec6e92c5fe..893d3702407 100644
--- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -56,6 +56,7 @@ RSpec.shared_context 'GroupPolicy context' do
admin_package
create_projects
create_cluster update_cluster admin_cluster add_cluster
+ destroy_upload
]
end
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
index 789b385c435..1d4731d9b39 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -62,6 +62,7 @@ RSpec.shared_context 'ProjectPolicy context' do
admin_project admin_project_member admin_snippet admin_terraform_state
admin_wiki create_deploy_token destroy_deploy_token
push_to_delete_protected_branch read_deploy_token update_snippet
+ destroy_upload
]
end
diff --git a/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
index fbd82fbbe31..b18ce14eba6 100644
--- a/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_table_shared_context.rb
@@ -545,5 +545,62 @@ RSpec.shared_context 'ProjectPolicyTable context' do
:private | :non_member | nil | 0
:private | :anonymous | nil | 0
end
+
+ # Based on the permission_table_for_reporter_feature_access table, but for issue
+ # features where public and internal projects with issues enabled only allow
+ # access to reporters and above (excluding admins if admin mode is disabled)
+ #
+ # project_level, :feature_access_level, :membership, :admin_mode, :expected_count
+ def permission_table_for_reporter_issue_access
+ :public | :enabled | :admin | true | 1
+ :public | :enabled | :admin | false | 0
+ :public | :enabled | :reporter | nil | 1
+ :public | :enabled | :guest | nil | 0
+ :public | :enabled | :non_member | nil | 0
+ :public | :enabled | :anonymous | nil | 0
+
+ :public | :private | :admin | true | 1
+ :public | :private | :admin | false | 0
+ :public | :private | :reporter | nil | 1
+ :public | :private | :guest | nil | 0
+ :public | :private | :non_member | nil | 0
+ :public | :private | :anonymous | nil | 0
+
+ :public | :disabled | :reporter | nil | 0
+ :public | :disabled | :guest | nil | 0
+ :public | :disabled | :non_member | nil | 0
+ :public | :disabled | :anonymous | nil | 0
+
+ :internal | :enabled | :admin | true | 1
+ :internal | :enabled | :admin | false | 0
+ :internal | :enabled | :reporter | nil | 1
+ :internal | :enabled | :guest | nil | 0
+ :internal | :enabled | :non_member | nil | 0
+ :internal | :enabled | :anonymous | nil | 0
+
+ :internal | :private | :admin | true | 1
+ :internal | :private | :admin | false | 0
+ :internal | :private | :reporter | nil | 1
+ :internal | :private | :guest | nil | 0
+ :internal | :private | :non_member | nil | 0
+ :internal | :private | :anonymous | nil | 0
+
+ :internal | :disabled | :reporter | nil | 0
+ :internal | :disabled | :guest | nil | 0
+ :internal | :disabled | :non_member | nil | 0
+ :internal | :disabled | :anonymous | nil | 0
+
+ :private | :private | :admin | true | 1
+ :private | :private | :admin | false | 0
+ :private | :private | :reporter | nil | 1
+ :private | :private | :guest | nil | 0
+ :private | :private | :non_member | nil | 0
+ :private | :private | :anonymous | nil | 0
+
+ :private | :disabled | :reporter | nil | 0
+ :private | :disabled | :guest | nil | 0
+ :private | :disabled | :non_member | nil | 0
+ :private | :disabled | :anonymous | nil | 0
+ end
# rubocop:enable Metrics/AbcSize
end
diff --git a/spec/support/shared_contexts/upload_type_check_shared_context.rb b/spec/support/shared_contexts/upload_type_check_shared_context.rb
index 5fce31b4a15..57b8d7472df 100644
--- a/spec/support/shared_contexts/upload_type_check_shared_context.rb
+++ b/spec/support/shared_contexts/upload_type_check_shared_context.rb
@@ -3,7 +3,7 @@
# Construct an `uploader` variable that is configured to `check_upload_type`
# with `mime_types` and `extensions`.
# @param uploader [CarrierWave::Uploader::Base] uploader with extension_whitelist method.
-RSpec.shared_context 'ignore extension whitelist check' do
+RSpec.shared_context 'ignore extension allowlist check' do
before do
allow(uploader).to receive(:extension_whitelist).and_return(nil)
end
@@ -16,3 +16,15 @@ RSpec.shared_context 'force content type detection to mime_type' do
allow(Gitlab::Utils::MimeType).to receive(:from_io).and_return(mime_type)
end
end
+
+def mock_upload(success = true)
+ allow(UploadService).to receive(:new).with(project, file).and_return(upload_service)
+
+ if success
+ allow(upload_service).to receive(:execute).and_return(uploader)
+ allow(uploader).to receive(:upload).and_return(upload)
+ allow(upload).to receive(:id).and_return(upload_id)
+ else
+ allow(upload_service).to receive(:execute).and_return(nil)
+ end
+end
diff --git a/spec/support/shared_examples/attention_request_cache_invalidation_examples.rb b/spec/support/shared_examples/attention_request_cache_invalidation_examples.rb
deleted file mode 100644
index 7fe696abc69..00000000000
--- a/spec/support/shared_examples/attention_request_cache_invalidation_examples.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'invalidates attention request cache' do
- it 'invalidates the merge requests requiring attention count' do
- cache_mock = double
-
- users.each do |user|
- expect(cache_mock).to receive(:delete).with(['users', user.id, 'attention_requested_open_merge_requests_count'])
- end
-
- allow(Rails).to receive(:cache).and_return(cache_mock)
-
- service.execute
- end
-end
diff --git a/spec/support/shared_examples/boards/destroy_service_shared_examples.rb b/spec/support/shared_examples/boards/destroy_service_shared_examples.rb
index 33bae3da44b..b1cb58a736f 100644
--- a/spec/support/shared_examples/boards/destroy_service_shared_examples.rb
+++ b/spec/support/shared_examples/boards/destroy_service_shared_examples.rb
@@ -20,10 +20,10 @@ RSpec.shared_examples 'board destroy service' do
end
context 'when there is only one board' do
- it 'does not remove board' do
+ it 'does remove board' do
expect do
- expect(service.execute(board)).to be_error
- end.not_to change(boards, :count)
+ service.execute(board)
+ end.to change(boards, :count).by(-1)
end
end
end
diff --git a/spec/support/shared_examples/components/pajamas_shared_examples.rb b/spec/support/shared_examples/components/pajamas_shared_examples.rb
index 5c0ad1a1bc9..bcf7df24fd9 100644
--- a/spec/support/shared_examples/components/pajamas_shared_examples.rb
+++ b/spec/support/shared_examples/components/pajamas_shared_examples.rb
@@ -2,12 +2,18 @@
RSpec.shared_examples 'it renders help text' do
it 'renders help text' do
- expect(rendered_component).to have_selector('[data-testid="pajamas-component-help-text"]', text: help_text)
+ expect(page).to have_css('[data-testid="pajamas-component-help-text"]', text: help_text)
end
end
RSpec.shared_examples 'it does not render help text' do
it 'does not render help text' do
- expect(rendered_component).not_to have_selector('[data-testid="pajamas-component-help-text"]')
+ expect(page).not_to have_css('[data-testid="pajamas-component-help-text"]')
+ end
+end
+
+RSpec.shared_examples 'it renders unchecked checkbox with value of `1`' do
+ it 'renders unchecked checkbox with value of `1`' do
+ expect(page).to have_unchecked_field(label, with: '1')
end
end
diff --git a/spec/support/shared_examples/controllers/search_cross_project_authorization_shared_examples.rb b/spec/support/shared_examples/controllers/search_cross_project_authorization_shared_examples.rb
new file mode 100644
index 00000000000..9421561aea4
--- /dev/null
+++ b/spec/support/shared_examples/controllers/search_cross_project_authorization_shared_examples.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples_for 'when the user cannot read cross project' do |action, params|
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(false)
+ end
+
+ it 'blocks access without a project_id' do
+ get action, params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'allows access with a project_id' do
+ get action, params: params.merge(project_id: create(:project, :public).id)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+end
diff --git a/spec/support/shared_examples/controllers/search_external_authorization_service_shared_examples.rb b/spec/support/shared_examples/controllers/search_external_authorization_service_shared_examples.rb
new file mode 100644
index 00000000000..6b72988b3e6
--- /dev/null
+++ b/spec/support/shared_examples/controllers/search_external_authorization_service_shared_examples.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples_for 'with external authorization service enabled' do |action, params|
+ include ExternalAuthorizationServiceHelpers
+
+ let(:project) { create(:project, namespace: user.namespace) }
+ let(:note) { create(:note_on_issue, project: project) }
+
+ before do
+ enable_external_authorization_service_check
+ end
+
+ it 'renders a 403 when no project is given' do
+ get action, params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'renders a 200 when a project was set' do
+ get action, params: params.merge(project_id: project.id)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ 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 98fc52add51..2e691d1b36f 100644
--- a/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
+++ b/spec/support/shared_examples/controllers/snowplow_event_tracking_examples.rb
@@ -2,22 +2,26 @@
#
# Requires a context containing:
# - subject
-# - project
# - feature_flag_name
# - category
# - action
# - namespace
+# Optionaly, the context can contain:
+# - project
+# - property
# - user
+# - label
+# - **extra
-shared_examples 'Snowplow event tracking' do
- let(:label) { nil }
+shared_examples 'Snowplow event tracking' do |overrides: {}|
+ let(:extra) { {} }
it 'is not emitted if FF is disabled' do
stub_feature_flags(feature_flag_name => false)
subject
- expect_no_snowplow_event
+ expect_no_snowplow_event(category: category, action: action)
end
it 'is emitted' do
@@ -25,10 +29,11 @@ shared_examples 'Snowplow event tracking' do
category: category,
action: action,
namespace: namespace,
- user: user,
- project: project,
- label: label
- }.compact
+ user: try(:user),
+ project: try(:project),
+ label: try(:label),
+ property: try(:property)
+ }.merge(overrides).compact.merge(extra)
subject
diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
index 6dca94ecf0a..0792ac14e47 100644
--- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
@@ -205,41 +205,13 @@ RSpec.shared_examples 'handle uploads' do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
+ it "responds with the appropriate status code" do
+ show_upload
- it "responds with appropriate status" do
- show_upload
-
- # We're switching here based on the class due to the feature
- # flag :enforce_auth_checks_on_uploads switching on project.
- # When it is enabled fully, we will apply the code it guards
- # to both Projects::UploadsController as well as
- # Groups::UploadsController.
- #
- # https://gitlab.com/gitlab-org/gitlab/-/issues/352291
- #
- if model.instance_of?(Group)
- expect(response).to have_gitlab_http_status(:ok)
- else
- expect(response).to have_gitlab_http_status(:redirect)
- end
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
-
- expect(response).to have_gitlab_http_status(:ok)
- end
+ if model.instance_of?(Group)
+ expect(response).to have_gitlab_http_status(:ok)
+ else
+ expect(response).to have_gitlab_http_status(:redirect)
end
end
end
@@ -308,41 +280,13 @@ RSpec.shared_examples 'handle uploads' do
allow_any_instance_of(FileUploader).to receive(:image?).and_return(true)
end
- context "enforce_auth_checks_on_uploads feature flag" do
- context "with flag enabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: true)
- end
-
- it "responds with status 404" do
- show_upload
-
- # We're switching here based on the class due to the feature
- # flag :enforce_auth_checks_on_uploads switching on
- # project. When it is enabled fully, we will apply the
- # code it guards to both Projects::UploadsController as
- # well as Groups::UploadsController.
- #
- # https://gitlab.com/gitlab-org/gitlab/-/issues/352291
- #
- if model.instance_of?(Group)
- expect(response).to have_gitlab_http_status(:ok)
- else
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context "with flag disabled" do
- before do
- stub_feature_flags(enforce_auth_checks_on_uploads: false)
- end
-
- it "responds with status 200" do
- show_upload
+ it "responds with the appropriate status code" do
+ show_upload
- expect(response).to have_gitlab_http_status(:ok)
- end
+ if model.instance_of?(Group)
+ expect(response).to have_gitlab_http_status(:ok)
+ else
+ expect(response).to have_gitlab_http_status(:not_found)
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 c162ed36881..0fc45b154d8 100644
--- a/spec/support/shared_examples/features/access_tokens_shared_examples.rb
+++ b/spec/support/shared_examples/features/access_tokens_shared_examples.rb
@@ -38,7 +38,7 @@ RSpec.shared_examples 'resource access tokens creation' do |resource_type|
expect(active_resource_access_tokens).to have_text('in')
expect(active_resource_access_tokens).to have_text('read_api')
expect(active_resource_access_tokens).to have_text('read_repository')
- expect(active_resource_access_tokens).to have_text('Maintainer')
+ expect(active_resource_access_tokens).to have_text('Guest')
expect(created_resource_access_token).not_to be_empty
end
end
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 0ea82f37db0..3fa7beea97e 100644
--- a/spec/support/shared_examples/features/content_editor_shared_examples.rb
+++ b/spec/support/shared_examples/features/content_editor_shared_examples.rb
@@ -13,9 +13,8 @@ RSpec.shared_examples 'edits content using the content editor' do
expect(page).to have_css('[data-testid="formatting-bubble-menu"]')
end
- it 'does not show a formatting bubble menu for code' do
- find(content_editor_testid).send_keys 'This is a `code`'
- find(content_editor_testid).send_keys [:shift, :left]
+ it 'does not show a formatting bubble menu for code blocks' do
+ find(content_editor_testid).send_keys '```js '
expect(page).not_to have_css('[data-testid="formatting-bubble-menu"]')
end
diff --git a/spec/support/shared_examples/features/inviting_members_shared_examples.rb b/spec/support/shared_examples/features/inviting_members_shared_examples.rb
index bca0e02fcdd..277ec6a7fa7 100644
--- a/spec/support/shared_examples/features/inviting_members_shared_examples.rb
+++ b/spec/support/shared_examples/features/inviting_members_shared_examples.rb
@@ -147,9 +147,9 @@ RSpec.shared_examples 'inviting members' do |snowplow_invite_label|
invite_member(user2.name, role: role, refresh: false)
- expect(page).to have_selector(invite_modal_selector)
- expect(page).to have_content "#{user2.name}: Access level should be greater than or equal to Developer " \
- "inherited membership from group #{group.name}"
+ invite_modal = page.find(invite_modal_selector)
+ expect(invite_modal).to have_content "#{user2.name}: Access level should be greater than or equal to " \
+ "Developer inherited membership from group #{group.name}"
page.refresh
@@ -166,31 +166,85 @@ RSpec.shared_examples 'inviting members' do |snowplow_invite_label|
group.add_maintainer(user3)
end
- it 'shows the user errors and then removes them from the form', :js do
- visit subentity_members_page_path
+ it 'shows the partial user error and success and then removes them from the form', :js do
+ user4 = create(:user)
+ user5 = create(:user)
+ user6 = create(:user)
+ user7 = create(:user)
+
+ group.add_maintainer(user6)
+ group.add_maintainer(user7)
- invite_member([user2.name, user3.name], role: role, refresh: false)
+ visit subentity_members_page_path
- expect(page).to have_selector(invite_modal_selector)
- expect(page).to have_selector(member_token_error_selector(user2.id))
- expect(page).to have_selector(member_token_error_selector(user3.id))
- expect(page).to have_text("The following 2 members couldn't be invited")
- expect(page).to have_text("#{user2.name}: Access level should be greater than or equal to")
- expect(page).to have_text("#{user3.name}: Access level should be greater than or equal to")
+ invite_member([user2.name, user3.name, user4.name, user6.name, user7.name], role: role, refresh: false)
+
+ # we have more than 2 errors, so one will be hidden
+ invite_modal = page.find(invite_modal_selector)
+ expect(invite_modal).to have_text("The following 4 members couldn't be invited")
+ expect(invite_modal).to have_selector(limited_invite_error_selector, count: 2, visible: :visible)
+ expect(invite_modal).to have_selector(expanded_invite_error_selector, count: 2, visible: :hidden)
+ # unpredictability of return order means we can't rely on message showing in any order here
+ # so we will not expect on the message
+ expect_to_have_invalid_invite_indicator(invite_modal, user2, message: false)
+ expect_to_have_invalid_invite_indicator(invite_modal, user3, message: false)
+ expect_to_have_invalid_invite_indicator(invite_modal, user6, message: false)
+ expect_to_have_invalid_invite_indicator(invite_modal, user7, message: false)
+ expect_to_have_successful_invite_indicator(invite_modal, user4)
+ expect(invite_modal).to have_button('Show more (2)')
+
+ # now we want to test the show more errors count logic
+ remove_token(user7.id)
+
+ # count decreases from 4 to 3 and 2 to 1
+ expect(invite_modal).to have_text("The following 3 members couldn't be invited")
+ expect(invite_modal).to have_button('Show more (1)')
+
+ # we want to show this error now for user6
+ invite_modal.find(more_invite_errors_button_selector).click
+
+ # now we should see the error for all users and our collapse button text
+ expect(invite_modal).to have_selector(limited_invite_error_selector, count: 2, visible: :visible)
+ expect(invite_modal).to have_selector(expanded_invite_error_selector, count: 1, visible: :visible)
+ expect_to_have_invalid_invite_indicator(invite_modal, user2, message: true)
+ expect_to_have_invalid_invite_indicator(invite_modal, user3, message: true)
+ expect_to_have_invalid_invite_indicator(invite_modal, user6, message: true)
+ expect(invite_modal).to have_button('Show less')
+
+ # adds new token, but doesn't submit
+ select_members(user5.name)
+
+ expect_to_have_normal_invite_indicator(invite_modal, user5)
remove_token(user2.id)
- expect(page).not_to have_selector(member_token_error_selector(user2.id))
- expect(page).to have_selector(member_token_error_selector(user3.id))
- expect(page).to have_text("The following member couldn't be invited")
- expect(page).not_to have_text("#{user2.name}: Access level should be greater than or equal to")
+ expect(invite_modal).to have_text("The following 2 members couldn't be invited")
+ expect(invite_modal).not_to have_selector(more_invite_errors_button_selector)
+ expect_to_have_invite_removed(invite_modal, user2)
+ expect_to_have_invalid_invite_indicator(invite_modal, user3)
+ expect_to_have_invalid_invite_indicator(invite_modal, user6)
+ expect_to_have_successful_invite_indicator(invite_modal, user4)
+ expect_to_have_normal_invite_indicator(invite_modal, user5)
+
+ remove_token(user6.id)
+
+ expect(invite_modal).to have_text("The following member couldn't be invited")
+ expect_to_have_invite_removed(invite_modal, user6)
+ expect_to_have_invalid_invite_indicator(invite_modal, user3)
+ expect_to_have_successful_invite_indicator(invite_modal, user4)
+ expect_to_have_normal_invite_indicator(invite_modal, user5)
remove_token(user3.id)
- expect(page).not_to have_selector(member_token_error_selector(user3.id))
- expect(page).not_to have_text("The following member couldn't be invited")
- expect(page).not_to have_text("Review the invite errors and try again")
- expect(page).not_to have_text("#{user3.name}: Access level should be greater than or equal to")
+ expect(invite_modal).not_to have_text("The following member couldn't be invited")
+ expect(invite_modal).not_to have_text("Review the invite errors and try again")
+ expect_to_have_invite_removed(invite_modal, user3)
+ expect_to_have_successful_invite_indicator(invite_modal, user4)
+ expect_to_have_normal_invite_indicator(invite_modal, user5)
+
+ submit_invites
+
+ expect(page).not_to have_selector(invite_modal_selector)
page.refresh
@@ -203,6 +257,10 @@ RSpec.shared_examples 'inviting members' do |snowplow_invite_label|
expect(page).to have_content('Maintainer')
expect(page).not_to have_button('Maintainer')
end
+
+ page.within find_invited_member_row(user4.name) do
+ expect(page).to have_button(role)
+ end
end
it 'only shows the error for an invalid formatted email and does not display other member errors', :js do
@@ -210,12 +268,12 @@ RSpec.shared_examples 'inviting members' do |snowplow_invite_label|
invite_member([user2.name, user3.name, 'bad@email'], role: role, refresh: false)
- expect(page).to have_selector(invite_modal_selector)
- expect(page).to have_text('email contains an invalid email address')
- expect(page).not_to have_text("The following 2 members couldn't be invited")
- expect(page).not_to have_text("Review the invite errors and try again")
- expect(page).not_to have_text("#{user2.name}: Access level should be greater than or equal to")
- expect(page).not_to have_text("#{user3.name}: Access level should be greater than or equal to")
+ invite_modal = page.find(invite_modal_selector)
+ expect(invite_modal).to have_text('email contains an invalid email address')
+ expect(invite_modal).not_to have_text("The following 2 members couldn't be invited")
+ expect(invite_modal).not_to have_text("Review the invite errors and try again")
+ expect(invite_modal).not_to have_text("#{user2.name}: Access level should be greater than or equal to")
+ expect(invite_modal).not_to have_text("#{user3.name}: Access level should be greater than or equal to")
end
end
end
diff --git a/spec/support/shared_examples/features/multiple_assignees_widget_mr_shared_examples.rb b/spec/support/shared_examples/features/multiple_assignees_widget_mr_shared_examples.rb
index bbde448a1a1..ef2683d6424 100644
--- a/spec/support/shared_examples/features/multiple_assignees_widget_mr_shared_examples.rb
+++ b/spec/support/shared_examples/features/multiple_assignees_widget_mr_shared_examples.rb
@@ -32,7 +32,7 @@ RSpec.shared_examples 'multiple assignees widget merge request' do |action, save
end
page.within '.dropdown-menu-user' do
- click_link user.name
+ click_button user.name
end
page.within '.issuable-sidebar' do
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 345dfbce423..95c0a76d726 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
@@ -16,7 +16,9 @@ RSpec.shared_examples 'date sidebar widget' do
page.within('[data-testid="sidebar-due-date"]') do
today = Date.today.day
- click_button 'Edit'
+ button = find_button('Edit')
+ scroll_to(button)
+ button.click
click_button today.to_s
diff --git a/spec/support/shared_examples/features/trial_email_validation_shared_example.rb b/spec/support/shared_examples/features/trial_email_validation_shared_example.rb
new file mode 100644
index 00000000000..8304a91af86
--- /dev/null
+++ b/spec/support/shared_examples/features/trial_email_validation_shared_example.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'user email validation' do
+ let(:email_hint_message) { 'We recommend a work email address.' }
+ let(:email_error_message) { 'Please provide a valid email address.' }
+
+ let(:email_warning_message) do
+ 'This email address does not look right, are you sure you typed it correctly?'
+ end
+
+ context 'with trial_email_validation flag enabled' do
+ it 'shows an error message until a correct email is entered' do
+ visit path
+ expect(page).to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
+
+ fill_in 'new_user_email', with: 'foo@'
+ fill_in 'new_user_first_name', with: ''
+
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
+
+ fill_in 'new_user_email', with: 'foo@bar'
+ fill_in 'new_user_first_name', with: ''
+
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).to have_content(email_warning_message)
+
+ fill_in 'new_user_email', with: 'foo@gitlab.com'
+ fill_in 'new_user_first_name', with: ''
+
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
+ end
+ end
+
+ context 'when trial_email_validation flag disabled' do
+ before do
+ stub_feature_flags trial_email_validation: false
+ end
+
+ it 'does not show an error message' do
+ visit path
+ expect(page).to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
+
+ fill_in 'new_user_email', with: 'foo@'
+
+ expect(page).to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/user_views_tag_shared_examples.rb b/spec/support/shared_examples/features/user_views_tag_shared_examples.rb
new file mode 100644
index 00000000000..989de1dbfbb
--- /dev/null
+++ b/spec/support/shared_examples/features/user_views_tag_shared_examples.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'user views tag' do
+ context 'when user views with the tag' do
+ let(:project) { create(:project, :repository) }
+ let(:user) { create(:user) }
+ let(:tag_name) { "stable" }
+ let!(:release) { create(:release, project: project, tag: tag_name, name: "ReleaseName") }
+
+ before do
+ project.add_developer(user)
+ project.repository.add_tag(user, tag_name, project.default_branch_or_main)
+
+ sign_in(user)
+ end
+
+ shared_examples 'shows tag' do
+ it do
+ visit tag_page
+
+ expect(page).to have_content tag_name
+ expect(page).to have_link("ReleaseName", href: project_release_path(project, release))
+ end
+ end
+
+ it_behaves_like 'shows tag'
+
+ context 'when tag name contains a slash' do
+ let(:tag_name) { "stable/v0.1" }
+
+ it_behaves_like 'shows tag'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/variable_list_shared_examples.rb b/spec/support/shared_examples/features/variable_list_shared_examples.rb
index c63faace6b2..9d81c0e9a3e 100644
--- a/spec/support/shared_examples/features/variable_list_shared_examples.rb
+++ b/spec/support/shared_examples/features/variable_list_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'variable list' do
+RSpec.shared_examples 'variable list' do |is_admin|
it 'shows a list of variables' do
page.within('[data-testid="ci-variable-table"]') do
expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq(variable.key)
@@ -166,7 +166,7 @@ RSpec.shared_examples 'variable list' do
wait_for_requests
expect(find('.flash-container')).to be_present
- expect(find('[data-testid="alert-danger"]').text).to have_content('Variables key (key) has already been taken')
+ expect(find('[data-testid="alert-danger"]').text).to have_content('(key) has already been taken')
end
it 'prevents a variable to be added if no values are provided when a variable is set to masked' do
@@ -257,7 +257,11 @@ RSpec.shared_examples 'variable list' do
end
it 'shows a message regarding the changed default' do
- expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
+ if is_admin
+ expect(page).to have_content 'Environment variables on this GitLab instance are configured to be protected by default'
+ else
+ expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
+ end
end
end
diff --git a/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb b/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb
index 0ef1ccdfe57..8d1502bed84 100644
--- a/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb
@@ -12,8 +12,8 @@ RSpec.shared_examples 'wiki file attachments' do
end
context 'before uploading' do
- it 'shows "Attach a file" button' do
- expect(page).to have_button('Attach a file')
+ it 'shows "Attach a file or image" button' do
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
end
@@ -26,7 +26,7 @@ RSpec.shared_examples 'wiki file attachments' do
click_button 'Cancel'
end
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_button('Cancel')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
@@ -41,11 +41,11 @@ RSpec.shared_examples 'wiki file attachments' do
end
context 'uploading is complete' do
- it 'shows "Attach a file" button on uploading complete' do
+ it 'shows "Attach a file or image" button on uploading complete' do
attach_with_dropzone
wait_for_requests
- expect(page).to have_button('Attach a file')
+ expect(page).to have_selector('[data-testid="button-attach-file"]')
expect(page).not_to have_selector('.uploading-progress-container', visible: true)
end
diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb
index 79c7c1891ac..87067336a36 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
@@ -140,7 +140,7 @@ RSpec.shared_examples 'User updates wiki page' do
context 'when using the content editor' do
context 'with feature flag on' do
before do
- click_button 'Edit rich text'
+ find('[data-testid="toggle-editing-mode-button"] label', text: 'Rich text').click
end
it_behaves_like 'edits content using the content editor'
diff --git a/spec/support/shared_examples/graphql/mutations/timelogs/create_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/timelogs/create_shared_examples.rb
new file mode 100644
index 00000000000..f28348fb945
--- /dev/null
+++ b/spec/support/shared_examples/graphql/mutations/timelogs/create_shared_examples.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable supports timelog creation mutation' do
+ context 'when the user is anonymous' do
+ before do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when the user is a guest member of the namespace' do
+ let(:current_user) { create(:user) }
+
+ before do
+ users_container.add_guest(current_user)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to create a timelog' do
+ let(:current_user) { author }
+
+ before do
+ users_container.add_reporter(current_user)
+ end
+
+ context 'with valid data' do
+ it 'creates the timelog' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change(Timelog, :count).by(1)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['errors']).to be_empty
+ expect(mutation_response['timelog']).to include(
+ 'timeSpent' => 3600,
+ 'spentAt' => '2022-07-08T00:00:00Z',
+ 'summary' => 'Test summary'
+ )
+ end
+ end
+
+ context 'with invalid time_spent' do
+ let(:time_spent) { '3h e' }
+
+ it 'returns an error' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change(Timelog, :count).by(0)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['errors']).to match_array(['Time spent can\'t be blank'])
+ expect(mutation_response['timelog']).to be_nil
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'issuable does not support timelog creation mutation' do
+ context 'when the user is anonymous' do
+ before do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when the user is a guest member of the namespace' do
+ let(:current_user) { create(:user) }
+
+ before do
+ users_container.add_guest(current_user)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors' do
+ let(:match_errors) { contain_exactly(include('is not a valid ID for')) }
+ end
+ end
+
+ context 'when user has permissions to create a timelog' do
+ let(:current_user) { author }
+
+ before do
+ users_container.add_reporter(current_user)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors' do
+ let(:match_errors) { contain_exactly(include('is not a valid ID for')) }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb
deleted file mode 100644
index 3c32b7e0310..00000000000
--- a/spec/support/shared_examples/graphql/mutations/work_items/update_weight_widget_shared_examples.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'update work item weight widget' do
- it 'updates the weight widget' do
- expect do
- post_graphql_mutation(mutation, current_user: current_user)
- work_item.reload
- end.to change(work_item, :weight).from(nil).to(new_weight)
-
- expect(response).to have_gitlab_http_status(:success)
- expect(mutation_response['workItem']['widgets']).to include(
- {
- 'weight' => new_weight,
- 'type' => 'WEIGHT'
- }
- )
- end
-
- context 'when the updated work item is not valid' do
- it 'returns validation errors without the work item' do
- errors = ActiveModel::Errors.new(work_item).tap { |e| e.add(:weight, 'error message') }
-
- allow_next_found_instance_of(::WorkItem) do |instance|
- allow(instance).to receive(:valid?).and_return(false)
- allow(instance).to receive(:errors).and_return(errors)
- end
-
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(mutation_response['workItem']).to be_nil
- expect(mutation_response['errors']).to match_array(['Weight error message'])
- end
- end
-end
diff --git a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
index 2c6118779e6..0aa3bf8944f 100644
--- a/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/notes_creation_shared_examples.rb
@@ -94,5 +94,6 @@ RSpec.shared_examples 'a Note mutation with confidential notes' do
expect(mutation_response).to have_key('note')
expect(mutation_response['note']['confidential']).to eq(true)
+ expect(mutation_response['note']['internal']).to eq(true)
end
end
diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
index 7fd54408b11..2d7da9f9f00 100644
--- a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
@@ -69,4 +69,21 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
'This feature is in Alpha. It can be changed or removed at any time. Introduced in 1.10.'
)
end
+
+ it 'supports :alpha' do
+ deprecable = subject(alpha: { milestone: '1.10' })
+
+ expect(deprecable.deprecation_reason).to eq(
+ 'This feature is in Alpha. It can be changed or removed at any time. Introduced in 1.10.'
+ )
+ end
+
+ it 'does not allow :alpha and :deprecated together' do
+ expect do
+ subject(alpha: { milestone: '1.10' }, deprecated: { milestone: '1.10', reason: 'my reason' } )
+ end.to raise_error(
+ ArgumentError,
+ eq("`alpha` and `deprecated` arguments cannot be passed at the same time")
+ )
+ end
end
diff --git a/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb b/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb
index c2c27fb65ca..61c8a3f47df 100644
--- a/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb
+++ b/spec/support/shared_examples/helpers/wiki_helpers_shared_examples.rb
@@ -2,7 +2,7 @@
RSpec.shared_examples 'wiki endpoint helpers' do
let(:resource_path) { page.wiki.container.class.to_s.pluralize.downcase }
- let(:url) { "/api/v4/#{resource_path}/#{page.wiki.container.id}/wikis/#{page.slug}?version=#{page.version.id}"}
+ let(:url) { "/api/v4/#{resource_path}/#{page.wiki.container.id}/wikis/#{page.slug}?version=#{page.version.id}" }
it 'returns the full endpoint url' do
expect(helper.wiki_page_render_api_endpoint(page)).to end_with(url)
diff --git a/spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb
index 95772b1774a..5eae8777a20 100644
--- a/spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb
@@ -86,7 +86,10 @@ RSpec.shared_examples 'with inheritable CI config' do
expect do
# we ignore exceptions as `#overwrite_entry`
# can raise exception on duplicates
- entry.send(:inherit!, deps) rescue described_class::InheritError
+
+ entry.send(:inherit!, deps)
+ rescue described_class::InheritError
+ nil
end.not_to change { entry[entry_key] }
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
index 9d280d9404a..481e11bcf0e 100644
--- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb
@@ -33,7 +33,7 @@ RSpec.shared_examples 'does not track when feature flag is disabled' do |feature
end
end
-RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events' do
+RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events for given event params' do
before do
stub_application_setting(usage_ping_enabled: true)
end
@@ -44,22 +44,21 @@ RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events
specify do
aggregate_failures do
- expect(track_action(author: user1, project: project)).to be_truthy
- expect(track_action(author: user1, project: project)).to be_truthy
- expect(track_action(author: user2, project: project)).to be_truthy
+ expect(track_action({ author: user1 }.merge(track_params))).to be_truthy
+ expect(track_action({ author: user1 }.merge(track_params))).to be_truthy
+ expect(track_action({ author: user2 }.merge(track_params))).to be_truthy
expect(count_unique).to eq(2)
end
end
it 'does not track edit actions if author is not present' do
- expect(track_action(author: nil, project: project)).to be_nil
+ expect(track_action({ author: nil }.merge(track_params))).to be_nil
end
it 'emits snowplow event' do
- track_action(author: user1, project: project)
+ track_action({ author: user1 }.merge(track_params))
- expect_snowplow_event(category: 'issues_edit', action: action, user: user1,
- namespace: project.namespace, project: project)
+ expect_snowplow_event(**{ category: category, action: event_action, user: user1 }.merge(event_params))
end
context 'with route_hll_to_snowplow_phase2 disabled' do
@@ -68,9 +67,33 @@ RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events
end
it 'does not emit snowplow event' do
- track_action(author: user1, project: project)
+ track_action({ author: user1 }.merge(track_params))
expect_no_snowplow_event
end
end
end
+
+RSpec.shared_examples 'daily tracked issuable snowplow and service ping events with project' do
+ it_behaves_like 'a daily tracked issuable snowplow and service ping events for given event params' do
+ let(:track_params) { { project: project } }
+ let(:event_params) { track_params.merge(label: event_label, property: event_property, namespace: project.namespace) }
+ end
+end
+
+RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events with namespace' do
+ it_behaves_like 'a daily tracked issuable snowplow and service ping events for given event params' do
+ let(:track_params) { { namespace: namespace } }
+ let(:event_params) { track_params.merge(label: event_label, property: event_property) }
+ end
+end
+
+RSpec.shared_examples 'does not track with namespace when feature flag is disabled' do |feature_flag|
+ context "when feature flag #{feature_flag} is disabled" do
+ it 'does not track action' do
+ stub_feature_flags(feature_flag => false)
+
+ expect(track_action(author: user1, namespace: namespace)).to be_nil
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
index d189e91effd..fb08784f34f 100644
--- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -3,7 +3,6 @@
RSpec.shared_examples "chat integration" do |integration_name|
describe "Associations" do
it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
end
describe "Validations" do
@@ -13,6 +12,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
end
it { is_expected.to validate_presence_of(:webhook) }
+
it_behaves_like "issue tracker integration URL attribute", :webhook
end
diff --git a/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb b/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb
new file mode 100644
index 00000000000..0c71ebe7a4d
--- /dev/null
+++ b/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples_for 'has ID tokens' do |ci_type|
+ subject(:ci) { FactoryBot.build(ci_type) }
+
+ describe 'delegations' do
+ it { is_expected.to delegate_method(:id_tokens).to(:metadata).allow_nil }
+ end
+
+ describe '#id_tokens?' do
+ subject { ci.id_tokens? }
+
+ context 'without metadata' do
+ let(:ci) { FactoryBot.build(ci_type) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'with metadata' do
+ let(:ci) { FactoryBot.build(ci_type, metadata: FactoryBot.build(:ci_build_metadata, id_tokens: id_tokens)) }
+
+ context 'when ID tokens exist' do
+ let(:id_tokens) { { TEST_JOB_JWT: { id_token: { aud: 'developers ' } } } }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when ID tokens do not exist' do
+ let(:id_tokens) { {} }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
+
+ describe '#id_tokens=' do
+ it 'assigns the ID tokens to the CI job' do
+ id_tokens = [{ 'JOB_ID_TOKEN' => { 'id_token' => { 'aud' => 'https://gitlab.test ' } } }]
+ ci.id_tokens = id_tokens
+
+ expect(ci.id_tokens).to match_array(id_tokens)
+ 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 f92ed3d7396..f4d5ab3d5c6 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
@@ -2,6 +2,10 @@
require 'spec_helper'
RSpec.shared_examples_for CounterAttribute do |counter_attributes|
+ before do
+ Gitlab::ApplicationContext.push(feature_category: 'test', caller_id: 'caller')
+ end
+
it 'defines a Redis counter_key' do
expect(model.counter_key(:counter_name))
.to eq("project:{#{model.project_id}}:counters:CounterAttributeModel:#{model.id}:counter_name")
@@ -22,7 +26,21 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
where(:increment) { [10, -3] }
with_them do
- it 'increments the counter in Redis' do
+ it 'increments the counter in Redis and logs it' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ message: 'Increment counter attribute',
+ attribute: attribute,
+ project_id: model.project_id,
+ increment: increment,
+ new_counter_value: 0 + increment,
+ current_db_value: model.read_attribute(attribute),
+ 'correlation_id' => an_instance_of(String),
+ 'meta.feature_category' => 'test',
+ 'meta.caller_id' => 'caller'
+ )
+ )
+
subject
Gitlab::Redis::SharedState.with do |redis|
@@ -86,7 +104,21 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
model.delayed_increment_counter(incremented_attribute, -3)
end
- it 'updates the record' do
+ it 'updates the record and logs it' do
+ expect(Gitlab::AppLogger).to receive(:info).with(
+ hash_including(
+ message: 'Flush counter attribute to database',
+ attribute: incremented_attribute,
+ project_id: model.project_id,
+ increment: 7,
+ previous_db_value: 0,
+ new_db_value: 7,
+ 'correlation_id' => an_instance_of(String),
+ 'meta.feature_category' => 'test',
+ 'meta.caller_id' => 'caller'
+ )
+ )
+
expect { subject }.to change { model.reset.read_attribute(incremented_attribute) }.by(7)
end
@@ -153,4 +185,32 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes|
end
end
end
+
+ describe '#clear_counter!' do
+ let(:attribute) { counter_attributes.first }
+
+ before do
+ 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'
+ )
+ )
+
+ model.clear_counter!(attribute)
+
+ Gitlab::Redis::SharedState.with do |redis|
+ key_exists = redis.exists(model.counter_key(attribute))
+ expect(key_exists).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
index d80be5be3b3..7512a9f2855 100644
--- a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
@@ -13,7 +13,6 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |integration_name
describe "Associations" do
it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
end
describe 'Validations' do
@@ -23,6 +22,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |integration_name
end
it { is_expected.to validate_presence_of(:webhook) }
+
it_behaves_like 'issue tracker integration URL attribute', :webhook
end
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 ae72cb6ec5d..2f693edeb53 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
@@ -3,6 +3,10 @@
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) }
+ end
+
describe 'callbacks' do
it 'calls #update_web_hook! when enabled' do
expect(integration).to receive(:update_web_hook!)
diff --git a/spec/support/shared_examples/models/issuable_link_shared_examples.rb b/spec/support/shared_examples/models/issuable_link_shared_examples.rb
index 9892e66b582..42c7be5ddc3 100644
--- a/spec/support/shared_examples/models/issuable_link_shared_examples.rb
+++ b/spec/support/shared_examples/models/issuable_link_shared_examples.rb
@@ -16,6 +16,7 @@ RSpec.shared_examples 'issuable link' do
it { is_expected.to validate_presence_of(:source) }
it { is_expected.to validate_presence_of(:target) }
+
it do
is_expected.to validate_uniqueness_of(:source)
.scoped_to(:target_id)
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index aa40a2c7135..287b046cbec 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -63,16 +63,23 @@ RSpec.shared_examples '#valid_level_roles' do |entity_name|
let(:entity) { create(entity_name) } # rubocop:disable Rails/SaveBang
let(:entity_member) { create("#{entity_name}_member", :developer, source: entity, user: member_user) }
let(:presenter) { described_class.new(entity_member, current_user: member_user) }
- let(:expected_roles) { { 'Developer' => 30, 'Maintainer' => 40, 'Reporter' => 20 } }
- it 'returns all roles when no parent member is present' do
- expect(presenter.valid_level_roles).to eq(entity_member.class.access_level_roles)
+ context 'when no parent member is present' do
+ let(:all_permissible_roles) { entity_member.class.permissible_access_level_roles(member_user, entity) }
+
+ it 'returns all permissible roles' do
+ expect(presenter.valid_level_roles).to eq(all_permissible_roles)
+ end
end
- it 'returns higher roles when a parent member is present' do
- group.add_reporter(member_user)
+ context 'when parent member is present' do
+ before do
+ group.add_reporter(member_user)
+ end
- expect(presenter.valid_level_roles).to eq(expected_roles)
+ it 'returns higher roles when a parent member is present' do
+ expect(presenter.valid_level_roles).to eq(expected_roles)
+ end
end
end
diff --git a/spec/support/shared_examples/models/project_shared_examples.rb b/spec/support/shared_examples/models/project_shared_examples.rb
index 475ac1da04b..0b880f00a22 100644
--- a/spec/support/shared_examples/models/project_shared_examples.rb
+++ b/spec/support/shared_examples/models/project_shared_examples.rb
@@ -25,3 +25,38 @@ RSpec.shared_examples 'returns true if project is inactive' do
end
end
end
+
+RSpec.shared_examples 'checks parent group feature flag' do
+ let(:group) { subject_project.group }
+ let(:root_group) { group.parent }
+
+ subject { subject_project.public_send(feature_flag_method) }
+
+ context 'when feature flag is disabled globally' do
+ before do
+ stub_feature_flags(feature_flag => false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when feature flag is enabled globally' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when feature flag is enabled for the root group' do
+ before do
+ stub_feature_flags(feature_flag => root_group)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when feature flag is enabled for the group' do
+ before do
+ stub_feature_flags(feature_flag => group)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+end
diff --git a/spec/support/shared_examples/models/taskable_shared_examples.rb b/spec/support/shared_examples/models/taskable_shared_examples.rb
index 34b1d735bcd..3ae240c8da8 100644
--- a/spec/support/shared_examples/models/taskable_shared_examples.rb
+++ b/spec/support/shared_examples/models/taskable_shared_examples.rb
@@ -18,9 +18,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('2 of')
- expect(subject.task_status).to match('5 tasks completed')
+ expect(subject.task_status).to match('5 checklist items completed')
expect(subject.task_status_short).to match('2/')
- expect(subject.task_status_short).to match('5 tasks')
+ expect(subject.task_status_short).to match('5 checklist items')
end
describe '#tasks?' do
@@ -53,9 +53,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('3 of')
- expect(subject.task_status).to match('9 tasks completed')
+ expect(subject.task_status).to match('9 checklist items completed')
expect(subject.task_status_short).to match('3/')
- expect(subject.task_status_short).to match('9 tasks')
+ expect(subject.task_status_short).to match('9 checklist items')
end
end
@@ -68,9 +68,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('0 of')
- expect(subject.task_status).to match('1 task completed')
+ expect(subject.task_status).to match('1 checklist item completed')
expect(subject.task_status_short).to match('0/')
- expect(subject.task_status_short).to match('1 task')
+ expect(subject.task_status_short).to match('1 checklist item')
end
end
@@ -87,9 +87,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('0 of')
- expect(subject.task_status).to match('0 tasks completed')
+ expect(subject.task_status).to match('0 checklist items completed')
expect(subject.task_status_short).to match('0/')
- expect(subject.task_status_short).to match('0 task')
+ expect(subject.task_status_short).to match('0 checklist items')
end
end
@@ -102,9 +102,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('1 of')
- expect(subject.task_status).to match('1 task completed')
+ expect(subject.task_status).to match('1 checklist item completed')
expect(subject.task_status_short).to match('1/')
- expect(subject.task_status_short).to match('1 task')
+ expect(subject.task_status_short).to match('1 checklist item')
end
end
@@ -123,9 +123,9 @@ RSpec.shared_examples 'a Taskable' do
it 'returns the correct task status' do
expect(subject.task_status).to match('2 of')
- expect(subject.task_status).to match('4 tasks completed')
+ expect(subject.task_status).to match('4 checklist items completed')
expect(subject.task_status_short).to match('2/')
- expect(subject.task_status_short).to match('4 tasks')
+ expect(subject.task_status_short).to match('4 checklist items')
end
end
end
diff --git a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
index 45da1d382c1..807295f8442 100644
--- a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
@@ -273,14 +273,6 @@ RSpec.shared_examples 'namespace traversal scopes' do
include_examples '.self_and_descendants'
end
-
- context 'with linear_scopes_superset feature flag disabled' do
- before do
- stub_feature_flags(linear_scopes_superset: false)
- end
-
- include_examples '.self_and_descendants'
- end
end
shared_examples '.self_and_descendant_ids' do
@@ -324,14 +316,6 @@ RSpec.shared_examples 'namespace traversal scopes' do
include_examples '.self_and_descendant_ids'
end
-
- context 'with linear_scopes_superset feature flag disabled' do
- before do
- stub_feature_flags(linear_scopes_superset: false)
- end
-
- include_examples '.self_and_descendant_ids'
- end
end
shared_examples '.self_and_hierarchy' do
diff --git a/spec/support/shared_examples/policies/group_project_namespace_policy_shared_examples.rb b/spec/support/shared_examples/policies/group_project_namespace_policy_shared_examples.rb
new file mode 100644
index 00000000000..9a1f0e685be
--- /dev/null
+++ b/spec/support/shared_examples/policies/group_project_namespace_policy_shared_examples.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'checks timelog categories permissions' do
+ context 'with no user' do
+ let_it_be(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:read_timelog_category) }
+ end
+
+ context 'with a regular user' do
+ let_it_be(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:read_timelog_category) }
+ end
+
+ context 'with a reporter user' do
+ let_it_be(:current_user) { create(:user) }
+
+ before do
+ users_container.add_reporter(current_user)
+ end
+
+ context 'when timelog_categories is enabled' do
+ it { is_expected.to be_allowed(:read_timelog_category) }
+ end
+
+ context 'when timelog_categories is disabled' do
+ before do
+ stub_feature_flags(timelog_categories: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_timelog_category) }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/discussions_shared_examples.rb b/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
index a12cb24a513..32562aef8d2 100644
--- a/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/discussions_shared_examples.rb
@@ -128,10 +128,10 @@ RSpec.shared_examples 'discussions API' do |parent_type, noteable_type, id_name,
stub_feature_flags(notes_create_service_tracking: false)
end
- it 'does not track any events', :snowplow do
+ it 'does not track Notes::CreateService events', :snowplow do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions"), params: { body: 'hi!' }
- expect_no_snowplow_event
+ expect_no_snowplow_event(category: 'Notes::CreateService', action: 'execute')
end
end
diff --git a/spec/support/shared_examples/requests/api/notes_shared_examples.rb b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
index a59235486ec..8479493911b 100644
--- a/spec/support/shared_examples/requests/api/notes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
@@ -376,13 +376,28 @@ RSpec.shared_examples 'noteable API with confidential notes' do |parent_type, no
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params
end
- it "creates a confidential note if confidential is set to true" do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params.merge(confidential: true)
+ context 'with internal param' do
+ it "creates a confidential note if internal is set to true" do
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params.merge(internal: true)
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['body']).to eq('hi!')
- expect(json_response['confidential']).to be_truthy
- expect(json_response['author']['username']).to eq(user.username)
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['body']).to eq('hi!')
+ expect(json_response['confidential']).to be_truthy
+ expect(json_response['internal']).to be_truthy
+ expect(json_response['author']['username']).to eq(user.username)
+ end
+ end
+
+ context 'with deprecated confidential param' do
+ it "creates a confidential note if confidential is set to true" do
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params.merge(confidential: true)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['body']).to eq('hi!')
+ expect(json_response['confidential']).to be_truthy
+ expect(json_response['internal']).to be_truthy
+ expect(json_response['author']['username']).to eq(user.username)
+ end
end
end
end
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index 8d6d85732be..b651ffc8996 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
@@ -244,7 +244,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
let(:headers) do
case auth
when :oauth
- build_token_auth_header(token.token)
+ build_token_auth_header(token.plaintext_token)
when :personal_access_token
build_token_auth_header(personal_access_token.token)
when :job_token
@@ -404,7 +404,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
shared_examples 'handling all conditions' do
context 'with oauth token' do
- let(:headers) { build_token_auth_header(token.token) }
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
it_behaves_like 'handling different package names, visibilities and user roles'
end
@@ -514,7 +514,7 @@ RSpec.shared_examples 'handling create dist tag requests' do |scope: :project|
shared_examples 'handling all conditions' do
context 'with oauth token' do
- let(:headers) { build_token_auth_header(token.token) }
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
it_behaves_like 'handling different package names, visibilities and user roles'
end
@@ -622,7 +622,7 @@ RSpec.shared_examples 'handling delete dist tag requests' do |scope: :project|
shared_examples 'handling all conditions' do
context 'with oauth token' do
- let(:headers) { build_token_auth_header(token.token) }
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
it_behaves_like 'handling different package names, visibilities and user roles'
end
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
index ca86cb082a7..6cae7d8e00f 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/alert_firing_shared_examples.rb
@@ -23,7 +23,7 @@ RSpec.shared_examples 'creates an alert management alert or errors' do
end
context 'and fails to save' do
- let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] })}
+ let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] }, '[]': [] )}
before do
allow(service).to receive(:alert).and_call_original
@@ -35,9 +35,10 @@ RSpec.shared_examples 'creates an alert management alert or errors' do
it 'writes a warning to the log' do
expect(Gitlab::AppLogger).to receive(:warn).with(
- message: "Unable to create AlertManagement::Alert from #{source}",
+ message: "Unable to create AlertManagement::Alert",
project_id: project.id,
- alert_errors: { hosts: ['hosts array is over 255 chars'] }
+ alert_errors: { hosts: ['hosts array is over 255 chars'] },
+ alert_source: source
)
subject
@@ -45,6 +46,46 @@ RSpec.shared_examples 'creates an alert management alert or errors' do
end
end
+RSpec.shared_examples 'handles race condition in alert creation' do
+ let(:other_alert) { create(:alert_management_alert, project: project) }
+
+ context 'when another alert is saved at the same time' do
+ before do
+ allow_next_instance_of(::AlertManagement::Alert) do |alert|
+ allow(alert).to receive(:save) do
+ other_alert.update!(fingerprint: alert.fingerprint)
+
+ raise ActiveRecord::RecordNotUnique
+ end
+ end
+ end
+
+ it 'finds the other alert and increments the counter' do
+ subject
+
+ expect(other_alert.reload.events).to eq(2)
+ end
+ end
+
+ context 'when another alert is saved before the validation runes' do
+ before do
+ allow_next_instance_of(::AlertManagement::Alert) do |alert|
+ allow(alert).to receive(:save).and_wrap_original do |method, *args|
+ other_alert.update!(fingerprint: alert.fingerprint)
+
+ method.call(*args)
+ end
+ end
+ end
+
+ it 'finds the other alert and increments the counter' do
+ subject
+
+ expect(other_alert.reload.events).to eq(2)
+ end
+ end
+end
+
# This shared_example requires the following variables:
# - last_alert_attributes, last created alert
# - project, project that alert created
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
index f8e096297d3..eb9f76d8626 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/alert_recovery_shared_examples.rb
@@ -4,8 +4,6 @@
# - `alert`, the alert to be resolved
RSpec.shared_examples 'resolves an existing alert management alert' do
it 'sets the end time and status' do
- expect(Gitlab::AppLogger).not_to receive(:warn)
-
expect { subject }
.to change { alert.reload.resolved? }.to(true)
.and change { alert.ended_at.present? }.to(true)
@@ -22,36 +20,6 @@ RSpec.shared_examples 'does not change the alert end time' do
end
end
-# This shared_example requires the following variables:
-# - `project`, expected project for an incoming alert
-# - `service`, a service which includes AlertManagement::AlertProcessing
-# - `alert` (optional), the alert which should fail to resolve. If not
-# included, the log is expected to correspond to a new alert
-RSpec.shared_examples 'writes a warning to the log for a failed alert status update' do
- before do
- allow(service).to receive(:alert).and_call_original
- allow(service).to receive_message_chain(:alert, :resolve).and_return(false)
- end
-
- specify do
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to update AlertManagement::Alert status to resolved',
- project_id: project.id,
- alert_id: alert ? alert.id : (last_alert_id + 1)
- )
-
- # Failure to resolve a recovery alert is not a critical failure
- expect(subject).to be_success
- end
-
- private
-
- def last_alert_id
- AlertManagement::Alert.connection
- .select_value("SELECT nextval('#{AlertManagement::Alert.sequence_name}')")
- end
-end
-
RSpec.shared_examples 'processes recovery alert' do
context 'seen for the first time' do
let(:alert) { AlertManagement::Alert.last }
@@ -69,7 +37,6 @@ RSpec.shared_examples 'processes recovery alert' do
it_behaves_like 'creates expected system notes for alert', :recovery_alert, :resolve_alert
it_behaves_like 'sends alert notification emails if enabled'
it_behaves_like 'closes related incident if enabled'
- it_behaves_like 'writes a warning to the log for a failed alert status update'
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not process incident issues'
@@ -83,7 +50,6 @@ RSpec.shared_examples 'processes recovery alert' do
it_behaves_like 'creates expected system notes for alert', :recovery_alert, :resolve_alert
it_behaves_like 'sends alert notification emails if enabled'
it_behaves_like 'closes related incident if enabled'
- it_behaves_like 'writes a warning to the log for a failed alert status update'
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not process incident issues'
@@ -97,7 +63,6 @@ RSpec.shared_examples 'processes recovery alert' do
it_behaves_like 'creates expected system notes for alert', :recovery_alert, :resolve_alert
it_behaves_like 'sends alert notification emails if enabled'
it_behaves_like 'closes related incident if enabled'
- it_behaves_like 'writes a warning to the log for a failed alert status update'
it_behaves_like 'does not create an alert management alert'
it_behaves_like 'does not process incident issues'
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb
index 98834f01ce2..6becc3dc071 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# Expects usage of 'incident settings enabled' context.
+# Expects usage of 'incident management settings enabled' context.
#
# This shared_example includes the following option:
# - with_issue: includes a test for when the defined `alert` has an associated issue
@@ -8,7 +8,7 @@
# This shared_example requires the following variables:
# - `alert`, required if :with_issue is true
RSpec.shared_examples 'processes incident issues if enabled' do |with_issue: false|
- include_examples 'processes incident issues', with_issue
+ include_examples 'processes incident issues', with_issue: with_issue
context 'with incident setting disabled' do
let(:create_issue) { false }
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb
index 3add5485fca..1973577d742 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/incident_resolution_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# Expects usage of 'incident settings enabled' context.
+# Expects usage of 'incident management settings enabled' context.
#
# This shared_example requires the following variables:
# - `alert`, alert for which related incidents should be closed
diff --git a/spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb b/spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb
index 5f30b58176b..92e7dee7533 100644
--- a/spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management/alert_processing/notifications_shared_examples.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
-# Expects usage of 'incident settings enabled' context.
+# Expects usage of 'incident management settings enabled' context.
#
# This shared_example includes the following option:
# - count: number of notifications expected to be sent
RSpec.shared_examples 'sends alert notification emails if enabled' do |count: 1|
- include_examples 'sends alert notification emails', count
+ include_examples 'sends alert notification emails', count: count
context 'with email setting disabled' do
let(:send_email) { false }
diff --git a/spec/support/shared_examples/services/boards/lists_move_service_shared_examples.rb b/spec/support/shared_examples/services/boards/lists_move_service_shared_examples.rb
index bf84b912610..97d0bae3552 100644
--- a/spec/support/shared_examples/services/boards/lists_move_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/lists_move_service_shared_examples.rb
@@ -1,95 +1,103 @@
# frozen_string_literal: true
RSpec.shared_examples 'lists move service' do
- let!(:planning) { create(:list, board: board, position: 0) }
- let!(:development) { create(:list, board: board, position: 1) }
- let!(:review) { create(:list, board: board, position: 2) }
- let!(:staging) { create(:list, board: board, position: 3) }
- let!(:closed) { create(:closed_list, board: board) }
+ shared_examples 'correct movement behavior' do
+ context 'when list type is set to label' do
+ it 'does not reorder lists when new position is nil' do
+ service = described_class.new(parent, user, position: nil)
- context 'when list type is set to label' do
- it 'keeps position of lists when new position is nil' do
- service = described_class.new(parent, user, position: nil)
+ service.execute(planning)
- service.execute(planning)
+ expect(ordered_lists).to eq([planning, development, review, staging])
+ end
- expect(current_list_positions).to eq [0, 1, 2, 3]
- end
-
- it 'keeps position of lists when new position is equal to old position' do
- service = described_class.new(parent, user, position: planning.position)
+ it 'does not reorder lists when new position is equal to old position' do
+ service = described_class.new(parent, user, position: planning.position)
- service.execute(planning)
+ service.execute(planning)
- expect(current_list_positions).to eq [0, 1, 2, 3]
- end
+ expect(ordered_lists).to eq([planning, development, review, staging])
+ end
- it 'keeps position of lists when new position is negative' do
- service = described_class.new(parent, user, position: -1)
+ it 'does not reorder lists when new position is negative' do
+ service = described_class.new(parent, user, position: -1)
- service.execute(planning)
+ service.execute(planning)
- expect(current_list_positions).to eq [0, 1, 2, 3]
- end
+ expect(ordered_lists).to eq([planning, development, review, staging])
+ end
- it 'keeps position of lists when new position is equal to number of labels lists' do
- service = described_class.new(parent, user, position: board.lists.label.size)
+ it 'does not reorder lists when new position is bigger then last position' do
+ service = described_class.new(parent, user, position: ordered_lists.last.position + 1)
- service.execute(planning)
+ service.execute(planning)
- expect(current_list_positions).to eq [0, 1, 2, 3]
- end
+ expect(ordered_lists).to eq([planning, development, review, staging])
+ end
- it 'keeps position of lists when new position is greater than number of labels lists' do
- service = described_class.new(parent, user, position: board.lists.label.size + 1)
+ it 'moves the list to the first position when new position is equal to first position' do
+ service = described_class.new(parent, user, position: 0)
- service.execute(planning)
+ service.execute(staging)
- expect(current_list_positions).to eq [0, 1, 2, 3]
- end
+ expect(ordered_lists).to eq([staging, planning, development, review])
+ end
- it 'increments position of intermediate lists when new position is equal to first position' do
- service = described_class.new(parent, user, position: 0)
+ it 'moves the list to the last position when new position is equal to last position' do
+ service = described_class.new(parent, user, position: board.lists.label.last.position)
- service.execute(staging)
+ service.execute(planning)
- expect(current_list_positions).to eq [1, 2, 3, 0]
- end
+ expect(ordered_lists).to eq([development, review, staging, planning])
+ end
- it 'decrements position of intermediate lists when new position is equal to last position' do
- service = described_class.new(parent, user, position: board.lists.label.last.position)
+ it 'moves the list to the correct position when new position is greater than old position (third list)' do
+ service = described_class.new(parent, user, position: review.position)
- service.execute(planning)
+ service.execute(planning)
- expect(current_list_positions).to eq [3, 0, 1, 2]
- end
+ expect(ordered_lists).to eq([development, review, planning, staging])
+ end
- it 'decrements position of intermediate lists when new position is greater than old position' do
- service = described_class.new(parent, user, position: 2)
+ it 'moves the list to the correct position when new position is lower than old position (second list)' do
+ service = described_class.new(parent, user, position: development.position)
- service.execute(planning)
+ service.execute(staging)
- expect(current_list_positions).to eq [2, 0, 1, 3]
+ expect(ordered_lists).to eq([planning, staging, development, review])
+ end
end
- it 'increments position of intermediate lists when new position is lower than old position' do
- service = described_class.new(parent, user, position: 1)
+ it 'keeps position of lists when list type is closed' do
+ service = described_class.new(parent, user, position: 2)
- service.execute(staging)
+ service.execute(closed)
- expect(current_list_positions).to eq [0, 2, 3, 1]
+ expect(ordered_lists).to eq([planning, development, review, staging])
end
end
- it 'keeps position of lists when list type is closed' do
- service = described_class.new(parent, user, position: 2)
+ context 'with complete position sequence' do
+ let!(:planning) { create(:list, board: board, position: 0) }
+ let!(:development) { create(:list, board: board, position: 1) }
+ let!(:review) { create(:list, board: board, position: 2) }
+ let!(:staging) { create(:list, board: board, position: 3) }
+ let!(:closed) { create(:closed_list, board: board) }
+
+ it_behaves_like 'correct movement behavior'
+ end
- service.execute(closed)
+ context 'with corrupted position sequence' do
+ let!(:planning) { create(:list, board: board, position: 0) }
+ let!(:staging) { create(:list, board: board, position: 6) }
+ let!(:development) { create(:list, board: board, position: 1) }
+ let!(:review) { create(:list, board: board, position: 4) }
+ let!(:closed) { create(:closed_list, board: board) }
- expect(current_list_positions).to eq [0, 1, 2, 3]
+ it_behaves_like 'correct movement behavior'
end
- def current_list_positions
- [planning, development, review, staging].map { |list| list.reload.position }
+ def ordered_lists
+ board.lists.where.not(position: nil)
end
end
diff --git a/spec/support/shared_examples/services/issuable_shared_examples.rb b/spec/support/shared_examples/services/issuable_shared_examples.rb
index a50a386afe1..142d4ae8531 100644
--- a/spec/support/shared_examples/services/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/services/issuable_shared_examples.rb
@@ -45,7 +45,7 @@ RSpec.shared_examples 'updating a single task' do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 1** as completed')
+ note1 = find_note('marked the checklist item **Task 1** as completed')
expect(note1).not_to be_nil
@@ -61,7 +61,7 @@ RSpec.shared_examples 'updating a single task' do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 2** as incomplete')
+ note1 = find_note('marked the checklist item **Task 2** as incomplete')
expect(note1).not_to be_nil
@@ -92,7 +92,7 @@ RSpec.shared_examples 'updating a single task' do
end
it 'creates system note about task status change' do
- note1 = find_note('marked the task **Task 2** as incomplete')
+ note1 = find_note('marked the checklist item **Task 2** as incomplete')
expect(note1).not_to be_nil
diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb
index 6bc4f171d9c..704a4bbe0b8 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -81,6 +81,26 @@ RSpec.shared_examples 'returns packages' do |container_type, user_type|
end
end
+RSpec.shared_examples 'returns package' do |container_type, user_type|
+ context "for #{user_type}" do
+ before do
+ send(container_type)&.send("add_#{user_type}", user) unless user_type == :no_type
+ end
+
+ it 'returns success response' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+
+ it 'returns a valid response schema' do
+ subject
+
+ expect(response).to match_response_schema(single_package_schema)
+ end
+ end
+end
+
RSpec.shared_examples 'returns packages with subgroups' do |container_type, user_type|
context "with subgroups for #{user_type}" do
before do
diff --git a/spec/support/shared_examples/services/snowplow_tracking_shared_examples.rb b/spec/support/shared_examples/services/snowplow_tracking_shared_examples.rb
new file mode 100644
index 00000000000..0687be6f429
--- /dev/null
+++ b/spec/support/shared_examples/services/snowplow_tracking_shared_examples.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+shared_examples 'issue_edit snowplow tracking' do
+ let(:category) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CATEGORY }
+ let(:action) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_ACTION }
+ let(:label) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_LABEL }
+ let(:namespace) { project.namespace }
+ let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
+
+ it_behaves_like 'Snowplow event tracking'
+end
diff --git a/spec/support/shared_examples/services/timelogs/create_service_shared_examples.rb b/spec/support/shared_examples/services/timelogs/create_service_shared_examples.rb
new file mode 100644
index 00000000000..53c42ec0e00
--- /dev/null
+++ b/spec/support/shared_examples/services/timelogs/create_service_shared_examples.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable supports timelog creation service' do
+ shared_examples 'success_response' do
+ it 'sucessfully saves the timelog' do
+ is_expected.to be_success
+
+ timelog = subject.payload[:timelog]
+
+ expect(timelog).to be_persisted
+ expect(timelog.time_spent).to eq(time_spent)
+ expect(timelog.spent_at).to eq('Fri, 08 Jul 2022 00:00:00.000000000 UTC +00:00')
+ expect(timelog.summary).to eq(summary)
+ expect(timelog.issuable).to eq(issuable)
+ end
+ end
+
+ context 'when the user does not have permission' do
+ let(:user) { create(:user) }
+
+ it 'returns an error' do
+ is_expected.to be_error
+
+ expect(subject.message).to eq(
+ "#{issuable.base_class_name} doesn't exist or you don't have permission to add timelog to it.")
+ expect(subject.http_status).to eq(404)
+ end
+ end
+
+ context 'when the user has permissions' do
+ let(:user) { author }
+
+ before do
+ users_container.add_reporter(user)
+ end
+
+ context 'when the timelog save fails' do
+ before do
+ allow_next_instance_of(Timelog) do |timelog|
+ allow(timelog).to receive(:save).and_return(false)
+ end
+ end
+
+ it 'returns an error' do
+ is_expected.to be_error
+ expect(subject.message).to eq('Failed to save timelog')
+ end
+ end
+
+ context 'when the creation completes sucessfully' do
+ it_behaves_like 'success_response'
+ end
+ end
+end
+
+RSpec.shared_examples 'issuable does not support timelog creation service' do
+ shared_examples 'error_response' do
+ it 'returns an error' do
+ is_expected.to be_error
+
+ issuable_type = if issuable.nil?
+ 'Issuable'
+ else
+ issuable.base_class_name
+ end
+
+ expect(subject.message).to eq(
+ "#{issuable_type} doesn't exist or you don't have permission to add timelog to it."
+ )
+ expect(subject.http_status).to eq(404)
+ end
+ end
+
+ context 'when the user does not have permission' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'error_response'
+ end
+
+ context 'when the user has permissions' do
+ let(:user) { author }
+
+ before do
+ users_container.add_reporter(user)
+ end
+
+ it_behaves_like 'error_response'
+ end
+end
diff --git a/spec/support/shared_examples/services/work_items/create_task_shared_examples.rb b/spec/support/shared_examples/services/work_items/create_task_shared_examples.rb
new file mode 100644
index 00000000000..7771e7f0e21
--- /dev/null
+++ b/spec/support/shared_examples/services/work_items/create_task_shared_examples.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'title with extra spaces' do
+ context 'when title has extra spaces' do
+ before do
+ params[:title] = " Awesome work item "
+ end
+
+ it 'removes extra leading and trailing whitespaces from title' do
+ subject
+
+ created_work_item = WorkItem.last
+ expect(created_work_item.title).to eq('Awesome work item')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb b/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb
index 1da21633504..3ba5f080a01 100644
--- a/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb
+++ b/spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_database|
+RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_database, table_name|
include ExclusiveLeaseHelpers
describe 'defining the job attributes' do
@@ -136,8 +136,10 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
let(:job_interval) { 5.minutes }
let(:lease_timeout) { 15.minutes }
let(:lease_key) { described_class.name.demodulize.underscore }
- let(:migration) { build(:batched_background_migration, :active, interval: job_interval) }
let(:interval_variance) { described_class::INTERVAL_VARIANCE }
+ let(:migration) do
+ build(:batched_background_migration, :active, interval: job_interval, table_name: table_name)
+ end
before do
allow(Gitlab::Database::BackgroundMigration::BatchedMigration).to receive(:active_migration)
@@ -233,7 +235,9 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
let(:migration_class) do
Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do
- def perform(matching_status)
+ job_arguments :matching_status
+
+ def perform
each_sub_batch(
operation_name: :update_all,
batching_scope: -> (relation) { relation.where(status: matching_status) }
@@ -249,7 +253,7 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
create(
:batched_background_migration,
:active,
- table_name: table_name,
+ table_name: new_table_name,
column_name: :id,
max_value: migration_records,
batch_size: batch_size,
@@ -261,14 +265,14 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
end
let(:base_model) { Gitlab::Database.database_base_models[tracking_database] }
- let(:table_name) { 'example_data' }
+ let(:new_table_name) { '_test_example_data' }
let(:batch_size) { 5 }
let(:sub_batch_size) { 2 }
let(:number_of_batches) { 10 }
let(:migration_records) { batch_size * number_of_batches }
let(:connection) { Gitlab::Database.database_base_models[tracking_database].connection }
- let(:example_data) { define_batchable_model(table_name, connection: connection) }
+ let(:example_data) { define_batchable_model(new_table_name, connection: connection) }
around do |example|
Gitlab::Database::SharedModel.using_connection(connection) do
@@ -283,16 +287,16 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
# - one record beyond the migration's range
# - one record that doesn't match the migration job's batch condition
connection.execute(<<~SQL)
- CREATE TABLE #{table_name} (
+ CREATE TABLE #{new_table_name} (
id integer primary key,
some_column integer,
status smallint);
- INSERT INTO #{table_name} (id, some_column, status)
+ INSERT INTO #{new_table_name} (id, some_column, status)
SELECT generate_series, generate_series, 1
FROM generate_series(1, #{migration_records + 1});
- UPDATE #{table_name}
+ UPDATE #{new_table_name}
SET status = 0
WHERE some_column = #{migration_records - 5};
SQL
@@ -362,6 +366,15 @@ RSpec.shared_examples 'it runs batched background migration jobs' do |tracking_d
expect { migration_run }.to change { migration.reload.on_hold? }.from(false).to(true)
end
+
+ it 'puts migration on hold when the pending WAL count is above the limit' do
+ sql = Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog::PENDING_WAL_COUNT_SQL
+ limit = Gitlab::Database::BackgroundMigration::HealthStatus::Indicators::WriteAheadLog::LIMIT
+
+ expect(connection).to receive(:execute).with(sql).and_return([{ 'pending_wal_count' => limit + 1 }])
+
+ expect { migration_run }.to change { migration.reload.on_hold? }.from(false).to(true)
+ end
end
end
end
diff --git a/spec/support_specs/database/prevent_cross_joins_spec.rb b/spec/support_specs/database/prevent_cross_joins_spec.rb
index efeabd15b58..5a80d0c0203 100644
--- a/spec/support_specs/database/prevent_cross_joins_spec.rb
+++ b/spec/support_specs/database/prevent_cross_joins_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Database::PreventCrossJoins do
+RSpec.describe Database::PreventCrossJoins, :suppress_gitlab_schemas_validate_connection do
context 'when running in a default scope' do
context 'when only non-CI tables are used' do
it 'does not raise exception' do
diff --git a/spec/support_specs/helpers/redis_commands/recorder_spec.rb b/spec/support_specs/helpers/redis_commands/recorder_spec.rb
new file mode 100644
index 00000000000..6f93ed2fcf0
--- /dev/null
+++ b/spec/support_specs/helpers/redis_commands/recorder_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe RedisCommands::Recorder, :use_clean_rails_redis_caching do
+ subject(:recorder) { described_class.new(pattern: pattern) }
+
+ let(:cache) { Rails.cache }
+ let(:pattern) { nil }
+
+ describe '#initialize' do
+ context 'with a block' do
+ it 'records Redis commands' do
+ recorder = described_class.new { cache.read('key1') }
+
+ expect(recorder.log).to include([:get, 'cache:gitlab:key1'])
+ end
+ end
+
+ context 'without block' do
+ it 'only initializes the recorder' do
+ recorder = described_class.new
+
+ expect(recorder.log).to eq([])
+ end
+ end
+ end
+
+ describe '#record' do
+ it 'records Redis commands' do
+ recorder.record do
+ cache.write('key1', '1')
+ cache.read('key1')
+ cache.read('key2')
+ cache.delete('key1')
+ end
+
+ expect(recorder.log).to include([:set, 'cache:gitlab:key1', anything])
+ expect(recorder.log).to include([:get, 'cache:gitlab:key1'])
+ expect(recorder.log).to include([:get, 'cache:gitlab:key2'])
+ expect(recorder.log).to include([:del, 'cache:gitlab:key1'])
+ end
+
+ it 'does not record commands before the call' do
+ cache.write('key1', 1)
+
+ recorder.record do
+ cache.read('key1')
+ end
+
+ expect(recorder.log).not_to include([:set, anything, anything])
+ expect(recorder.log).to include([:get, 'cache:gitlab:key1'])
+ end
+
+ it 'refreshes recording after reinitialization' do
+ cache.read('key1')
+
+ recorder1 = described_class.new
+ recorder1.record do
+ cache.read('key2')
+ end
+
+ recorder2 = described_class.new
+
+ cache.read('key3')
+
+ recorder2.record do
+ cache.read('key4')
+ end
+
+ expect(recorder1.log).to include([:get, 'cache:gitlab:key2'])
+ expect(recorder1.log).not_to include([:get, 'cache:gitlab:key1'])
+ expect(recorder1.log).not_to include([:get, 'cache:gitlab:key3'])
+ expect(recorder1.log).not_to include([:get, 'cache:gitlab:key4'])
+
+ expect(recorder2.log).to include([:get, 'cache:gitlab:key4'])
+ expect(recorder2.log).not_to include([:get, 'cache:gitlab:key1'])
+ expect(recorder2.log).not_to include([:get, 'cache:gitlab:key2'])
+ expect(recorder2.log).not_to include([:get, 'cache:gitlab:key3'])
+ end
+ end
+
+ describe 'Pattern recording' do
+ let(:pattern) { 'key1' }
+
+ it 'records only matching keys' do
+ recorder.record do
+ cache.write('key1', '1')
+ cache.read('key2')
+ cache.read('key1')
+ cache.delete('key2')
+ end
+
+ expect(recorder.log).to include([:set, 'cache:gitlab:key1', anything])
+ expect(recorder.log).to include([:get, 'cache:gitlab:key1'])
+ expect(recorder.log).not_to include([:get, 'cache:gitlab:key2'])
+ expect(recorder.log).not_to include([:del, 'cache:gitlab:key2'])
+ end
+ end
+
+ describe '#by_command' do
+ it 'returns only matching commands' do
+ recorder.record do
+ cache.write('key1', '1')
+ cache.read('key2')
+ cache.read('key1')
+ cache.delete('key2')
+ end
+
+ expect(recorder.by_command(:del)).to match_array([[:del, 'cache:gitlab:key2']])
+ end
+ end
+
+ describe '#count' do
+ it 'returns the number of recorded commands' do
+ cache.read 'warmup'
+
+ recorder.record do
+ cache.write('key1', '1')
+ cache.read('key2')
+ cache.read('key1')
+ cache.delete('key2')
+ end
+
+ expect(recorder.count).to eq(4)
+ end
+ end
+end
diff --git a/spec/tasks/dev_rake_spec.rb b/spec/tasks/dev_rake_spec.rb
index 14a5ccfa323..a09756b862e 100644
--- a/spec/tasks/dev_rake_spec.rb
+++ b/spec/tasks/dev_rake_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'dev rake tasks' do
Rake.application.rake_require 'tasks/dev'
Rake.application.rake_require 'active_record/railties/databases'
Rake.application.rake_require 'tasks/gitlab/db'
+ Rake.application.rake_require 'tasks/seed_fu'
end
describe 'setup' do
@@ -38,6 +39,30 @@ RSpec.describe 'dev rake tasks' do
end
end
+ describe 'fixtures:load' do
+ subject(:load_task) { run_rake_task('dev:fixtures:load', task_param) }
+
+ context 'by name' do
+ let(:task_param) { ['fixture_name'] }
+
+ it 'loads fixture' do
+ expect(Rake::Task['db:seed_fu']).to receive(:invoke)
+
+ load_task
+ end
+ end
+
+ context 'by empty name' do
+ let(:task_param) { '' }
+
+ it 'does not load fixture' do
+ expect(Rake::Task['db:seed_fu']).not_to receive(:invoke)
+
+ expect { load_task }.to output(/No fixture name was provided/).to_stdout
+ end
+ end
+ end
+
describe 'load' do
subject(:load_task) { run_rake_task('dev:load') }
diff --git a/spec/tasks/gitlab/background_migrations_rake_spec.rb b/spec/tasks/gitlab/background_migrations_rake_spec.rb
index bbd33f71e60..d8ce00a65e6 100644
--- a/spec/tasks/gitlab/background_migrations_rake_spec.rb
+++ b/spec/tasks/gitlab/background_migrations_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:background_migrations namespace rake tasks' do
+RSpec.describe 'gitlab:background_migrations namespace rake tasks', :suppress_gitlab_schemas_validate_connection do
before do
Rake.application.rake_require 'tasks/gitlab/background_migrations'
end
@@ -155,7 +155,7 @@ RSpec.describe 'gitlab:background_migrations namespace rake tasks' do
context 'with multiple databases' do
subject(:status_task) { run_rake_task('gitlab:background_migrations:status') }
- let(:base_models) { { 'main' => main_model, 'ci' => ci_model } }
+ let(:base_models) { { main: main_model, ci: ci_model } }
let(:main_model) { double(:model, connection: connection) }
let(:ci_model) { double(:model, connection: connection) }
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 9e914f8202e..dc112b885ae 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -5,7 +5,11 @@ 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_types) { %w{db repositories 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|
+ array.insert(1, 'ci_db') if Gitlab::Database.has_config?(:ci)
+ end
+ end
def tars_glob
Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar'))
@@ -151,7 +155,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
describe 'backup' do
before do
# This reconnect makes our project fixture disappear, breaking the restore. Stub it out.
- allow(ActiveRecord::Base.connection).to receive(:reconnect!)
+ allow(ApplicationRecord.connection).to receive(:reconnect!)
+ allow(Ci::ApplicationRecord.connection).to receive(:reconnect!)
end
let!(:project) { create(:project, :repository) }
@@ -199,7 +204,9 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
end
it 'logs the progress to log file' do
- expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping database ... [SKIPPED]")
+ 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 ... ")
diff --git a/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb b/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb
index 29b80176ef8..b03e964ce87 100644
--- a/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb
+++ b/spec/tasks/gitlab/db/decomposition/rollback/bump_ci_sequences_rake_spec.rb
@@ -2,7 +2,8 @@
require 'rake_helper'
-RSpec.describe 'gitlab:db:decomposition:rollback:bump_ci_sequences', :silence_stdout do
+RSpec.describe 'gitlab:db:decomposition:rollback:bump_ci_sequences', :silence_stdout,
+ :suppress_gitlab_schemas_validate_connection do
before :all do
Rake.application.rake_require 'tasks/gitlab/db/decomposition/rollback/bump_ci_sequences'
diff --git a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
index 034c520887e..d03e15224cb 100644
--- a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
+++ b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
@@ -2,7 +2,8 @@
require 'rake_helper'
-RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_record_base do
+RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_record_base,
+ :suppress_gitlab_schemas_validate_connection do
before :all do
Rake.application.rake_require 'active_record/railties/databases'
Rake.application.rake_require 'tasks/seed_fu'
@@ -48,26 +49,6 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
end
context 'when locking writes' do
- it 'adds 3 triggers to the ci schema tables on the main database' do
- expect do
- run_rake_task('gitlab:db:lock_writes')
- end.to change {
- number_of_triggers_on(main_connection, Ci::Build.table_name)
- }.by(3) # Triggers to block INSERT / UPDATE / DELETE
- # Triggers on TRUNCATE are not added to the information_schema.triggers
- # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
- end
-
- it 'adds 3 triggers to the main schema tables on the ci database' do
- expect do
- run_rake_task('gitlab:db:lock_writes')
- end.to change {
- number_of_triggers_on(ci_connection, Project.table_name)
- }.by(3) # Triggers to block INSERT / UPDATE / DELETE
- # Triggers on TRUNCATE are not added to the information_schema.triggers
- # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
- end
-
it 'still allows writes on the tables with the correct connections' do
Project.update_all(updated_at: Time.now)
Ci::Build.update_all(updated_at: Time.now)
@@ -106,30 +87,22 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
main_connection.execute("truncate ci_build_needs")
end.to raise_error(ActiveRecord::StatementInvalid, /Table: "ci_build_needs" is write protected/)
end
+ end
- it 'retries again if it receives a statement_timeout a few number of times' do
- error_message = "PG::QueryCanceled: ERROR: canceling statement due to statement timeout"
- call_count = 0
- allow(main_connection).to receive(:execute) do |statement|
- if statement.include?("CREATE TRIGGER")
- call_count += 1
- raise(ActiveRecord::QueryCanceled, error_message) if call_count.even?
- end
- end
- run_rake_task('gitlab:db:lock_writes')
+ context 'multiple shared databases' do
+ before do
+ allow(::Gitlab::Database).to receive(:db_config_share_with).and_return(nil)
+ ci_db_config = Ci::ApplicationRecord.connection_db_config
+ allow(::Gitlab::Database).to receive(:db_config_share_with).with(ci_db_config).and_return('main')
end
- it 'raises the exception if it happened many times' do
- error_message = "PG::QueryCanceled: ERROR: canceling statement due to statement timeout"
- allow(main_connection).to receive(:execute) do |statement|
- if statement.include?("CREATE TRIGGER")
- raise(ActiveRecord::QueryCanceled, error_message)
- end
- end
+ it 'does not lock any tables if the ci database is shared with main database' do
+ run_rake_task('gitlab:db:lock_writes')
expect do
- run_rake_task('gitlab:db:lock_writes')
- end.to raise_error(ActiveRecord::QueryCanceled)
+ ApplicationRecord.connection.execute("delete from ci_builds")
+ Ci::ApplicationRecord.connection.execute("delete from users")
+ end.not_to raise_error
end
end
@@ -138,26 +111,8 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
run_rake_task('gitlab:db:lock_writes')
end
- it 'removes the write protection triggers from the gitlab_main tables on the ci database' do
- expect do
- run_rake_task('gitlab:db:unlock_writes')
- end.to change {
- number_of_triggers_on(ci_connection, Project.table_name)
- }.by(-3) # Triggers to block INSERT / UPDATE / DELETE
- # Triggers on TRUNCATE are not added to the information_schema.triggers
- # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
-
- expect do
- ci_connection.execute("delete from projects")
- end.not_to raise_error
- end
-
- it 'removes the write protection triggers from the gitlab_ci tables on the main database' do
- expect do
- run_rake_task('gitlab:db:unlock_writes')
- end.to change {
- number_of_triggers_on(main_connection, Ci::Build.table_name)
- }.by(-3)
+ it 'allows writes again on the gitlab_ci tables on the main database' do
+ run_rake_task('gitlab:db:unlock_writes')
expect do
main_connection.execute("delete from ci_builds")
@@ -169,9 +124,4 @@ RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_r
def number_of_triggers(connection)
connection.select_value("SELECT count(*) FROM information_schema.triggers")
end
-
- def number_of_triggers_on(connection, table_name)
- connection
- .select_value("SELECT count(*) FROM information_schema.triggers WHERE event_object_table=$1", nil, [table_name])
- end
end
diff --git a/spec/tasks/gitlab/db/validate_config_rake_spec.rb b/spec/tasks/gitlab/db/validate_config_rake_spec.rb
index 03d7504e8b1..ad15c7f0d1c 100644
--- a/spec/tasks/gitlab/db/validate_config_rake_spec.rb
+++ b/spec/tasks/gitlab/db/validate_config_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:db:validate_config', :silence_stdout do
+RSpec.describe 'gitlab:db:validate_config', :silence_stdout, :suppress_gitlab_schemas_validate_connection do
# We don't need to delete this data since it only modifies `ar_internal_metadata`
# which would not be cleaned either by `DbCleaner`
self.use_transactional_tests = false
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 74bec406947..8f8178cde4d 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -370,7 +370,7 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
it 'outputs changed message for automation after operations happen' do
allow(ActiveRecord::Base.connection.schema_migration).to receive(:table_exists?).and_return(schema_migration_table_exists)
allow_any_instance_of(ActiveRecord::MigrationContext).to receive(:needs_migration?).and_return(needs_migrations)
- expect { run_rake_task('gitlab:db:unattended') }. to output(/^#{rake_output}$/).to_stdout
+ expect { run_rake_task('gitlab:db:unattended') }.to output(/^#{rake_output}$/).to_stdout
end
end
end
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index 70c7ddb1d6e..e57021f749b 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
.with(%w[which gmake])
.and_return(['/usr/bin/gmake', 0])
expect(Gitlab::Popen).to receive(:popen)
- .with(%w[gmake all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .with(%w[gmake clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
.and_return(['ok', 0])
subject
@@ -78,7 +78,7 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
.with(%w[which gmake])
.and_return(['/usr/bin/gmake', 0])
expect(Gitlab::Popen).to receive(:popen)
- .with(%w[gmake all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .with(%w[gmake clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
.and_return(['output', 1])
expect { subject }.to raise_error /Gitaly failed to compile: output/
@@ -95,14 +95,14 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
it 'calls make in the gitaly directory' do
expect(Gitlab::Popen).to receive(:popen)
- .with(%w[make all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
+ .with(%w[make clean-build all git], nil, { "BUNDLE_GEMFILE" => nil, "RUBYOPT" => nil })
.and_return(['output', 0])
subject
end
context 'when Rails.env is test' do
- let(:command) { %w[make all git] }
+ let(:command) { %w[make clean-build all git] }
before do
stub_rails_env('test')
diff --git a/spec/tasks/gitlab/password_rake_spec.rb b/spec/tasks/gitlab/password_rake_spec.rb
index 65bba836024..5d5e5af2536 100644
--- a/spec/tasks/gitlab/password_rake_spec.rb
+++ b/spec/tasks/gitlab/password_rake_spec.rb
@@ -3,7 +3,8 @@
require 'rake_helper'
RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
- let_it_be(:user_1) { create(:user, username: 'foobar', password: 'initial_password') }
+ let_it_be(:user_1) { create(:user, username: 'foobar', password: User.random_password) }
+ let_it_be(:password) { User.random_password }
def stub_username(username)
allow(Gitlab::TaskHelpers).to receive(:prompt).with('Enter username: ').and_return(username)
@@ -19,14 +20,14 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
Rake.application.rake_require 'tasks/gitlab/password'
stub_username('foobar')
- stub_password('secretpassword')
+ stub_password(password)
end
describe ':reset' do
context 'when all inputs are correct' do
it 'updates the password properly' do
run_rake_task('gitlab:password:reset', user_1.username)
- expect(user_1.reload.valid_password?('secretpassword')).to eq(true)
+ expect(user_1.reload.valid_password?(password)).to eq(true)
end
end
@@ -55,7 +56,7 @@ RSpec.describe 'gitlab:password rake tasks', :silence_stdout do
context 'when passwords do not match' do
before do
- stub_password('randompassword', 'differentpassword')
+ stub_password(password, User.random_password)
end
it 'aborts with an error' do
diff --git a/spec/tasks/gitlab/web_hook_rake_spec.rb b/spec/tasks/gitlab/web_hook_rake_spec.rb
index 2c582dc78f8..cb6a6e72ab1 100644
--- a/spec/tasks/gitlab/web_hook_rake_spec.rb
+++ b/spec/tasks/gitlab/web_hook_rake_spec.rb
@@ -50,6 +50,10 @@ RSpec.describe 'gitlab:web_hook namespace rake tasks', :silence_stdout do
let(:other_url) { 'http://other.example.com' }
+ it 'complains if URL is not provided' do
+ expect { run_rake_task('gitlab:web_hook:rm') }.to raise_error(ArgumentError, 'URL is required')
+ end
+
it 'removes a web hook from all projects by URL' do
stub_env('URL' => url)
run_rake_task('gitlab:web_hook:rm')
diff --git a/spec/tooling/danger/customer_success_spec.rb b/spec/tooling/danger/customer_success_spec.rb
new file mode 100644
index 00000000000..798905212f1
--- /dev/null
+++ b/spec/tooling/danger/customer_success_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'rspec-parameterized'
+require 'gitlab-dangerfiles'
+require 'gitlab/dangerfiles/spec_helper'
+require_relative '../../../tooling/danger/customer_success'
+
+RSpec.describe Tooling::Danger::CustomerSuccess do
+ include_context "with dangerfile"
+
+ let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
+ let(:customer_success) { fake_danger.new(helper: fake_helper) }
+
+ describe 'customer success danger' do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ 'with data category changes to Ops and no Customer Success::Impact Check label' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml app/models/user.rb),
+ changed_lines: ['-data_category: cat1', '+data_category: operational'],
+ customer_labeled: false,
+ impacted: true,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ },
+ 'with data category changes and Customer Success::Impact Check label' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml),
+ changed_lines: ['-data_category: cat1', '+data_category: operational'],
+ customer_labeled: true,
+ impacted: false,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ },
+ 'with metric file changes and no data category changes' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml),
+ changed_lines: ['-product_stage: growth'],
+ customer_labeled: false,
+ impacted: false,
+ impacted_files: []
+ },
+ 'with data category changes from Ops' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml app/models/user.rb),
+ changed_lines: ['-data_category: operational', '+data_category: cat2'],
+ customer_labeled: false,
+ impacted: true,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ },
+ 'with data category removed' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml app/models/user.rb),
+ changed_lines: ['-data_category: operational'],
+ customer_labeled: false,
+ impacted: true,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ },
+ 'with data category added' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml app/models/user.rb),
+ changed_lines: ['+data_category: operational'],
+ customer_labeled: false,
+ impacted: true,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ },
+ 'with data category in uppercase' => {
+ modified_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml app/models/user.rb),
+ changed_lines: ['+data_category: Operational'],
+ customer_labeled: false,
+ impacted: true,
+ impacted_files: %w(config/metrics/20210216182127_user_secret_detection_jobs.yml)
+ }
+ }
+ end
+
+ with_them do
+ before do
+ allow(fake_helper).to receive(:modified_files).and_return(modified_files)
+ allow(fake_helper).to receive(:changed_lines).and_return(changed_lines)
+ allow(fake_helper).to receive(:has_scoped_label_with_scope?).and_return(customer_labeled)
+ allow(fake_helper).to receive(:markdown_list).with(impacted_files)
+ .and_return(impacted_files.map { |item| "* `#{item}`" }.join("\n"))
+ end
+
+ it 'generates correct message' do
+ expect(customer_success.build_message).to match_expected_message
+ end
+ end
+ end
+
+ def match_expected_message
+ return be_nil unless impacted
+
+ start_with(described_class::CHANGED_SCHEMA_MESSAGE).and(include(*impacted_files))
+ end
+end
diff --git a/spec/tooling/graphql/docs/renderer_spec.rb b/spec/tooling/graphql/docs/renderer_spec.rb
index 18256fea2d6..bf2383507aa 100644
--- a/spec/tooling/graphql/docs/renderer_spec.rb
+++ b/spec/tooling/graphql/docs/renderer_spec.rb
@@ -347,6 +347,128 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
it_behaves_like 'renders correctly as GraphQL documentation'
end
+ context 'when an argument is in alpha' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'AlphaTest'
+ description 'A thing with arguments in alpha'
+
+ field :foo,
+ type: GraphQL::Types::String,
+ null: false,
+ description: 'A description.' do
+ argument :foo_arg, GraphQL::Types::String,
+ required: false,
+ description: 'Argument description.',
+ alpha: { milestone: '101.2' }
+ end
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ##### `AlphaTest.foo`
+
+ A description.
+
+ Returns [`String!`](#string).
+
+ ###### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="alphatestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Introduced** in 101.2. This feature is in Alpha. It can be changed or removed at any time. Argument description. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a field is in alpha' do
+ let(:type) do
+ Class.new(Types::BaseObject) do
+ graphql_name 'AlphaTest'
+ description 'A thing with fields in alpha'
+
+ field :foo,
+ type: GraphQL::Types::String,
+ null: false,
+ alpha: { milestone: '1.10' },
+ description: 'A description.'
+ field :foo_with_args,
+ type: GraphQL::Types::String,
+ null: false,
+ alpha: { milestone: '1.10' },
+ description: 'A description.' do
+ argument :arg, GraphQL::Types::Int, required: false, description: 'Argity'
+ end
+ end
+ end
+
+ let(:section) do
+ <<~DOC
+ ### `AlphaTest`
+
+ A thing with fields in alpha.
+
+ #### Fields
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="alphatestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Introduced** in 1.10. This feature is in Alpha. It can be changed or removed at any time. A description. |
+
+ #### Fields with arguments
+
+ ##### `AlphaTest.fooWithArgs`
+
+ A description.
+
+ WARNING:
+ **Introduced** in 1.10.
+ This feature is in Alpha. It can be changed or removed at any time.
+
+ Returns [`String!`](#string).
+
+ ###### Arguments
+
+ | Name | Type | Description |
+ | ---- | ---- | ----------- |
+ | <a id="alphatestfoowithargsarg"></a>`arg` | [`Int`](#int) | Argity. |
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
+ context 'when a Query.field is in alpha' do
+ before do
+ query_type.field(
+ name: :bar,
+ type: type,
+ null: true,
+ description: 'A bar',
+ alpha: { milestone: '10.11' }
+ )
+ end
+
+ let(:type) { ::GraphQL::Types::Int }
+ let(:section) do
+ <<~DOC
+ ### `Query.bar`
+
+ A bar.
+
+ WARNING:
+ **Introduced** in 10.11.
+ This feature is in Alpha. It can be changed or removed at any time.
+
+ Returns [`Int`](#int).
+ DOC
+ end
+
+ it_behaves_like 'renders correctly as GraphQL documentation'
+ end
+
context 'when a field has an Enumeration type' do
let(:type) do
enum_type = Class.new(Types::BaseEnum) do
diff --git a/spec/tooling/lib/tooling/find_codeowners_spec.rb b/spec/tooling/lib/tooling/find_codeowners_spec.rb
index 10c2a076847..5f6f83ab2c7 100644
--- a/spec/tooling/lib/tooling/find_codeowners_spec.rb
+++ b/spec/tooling/lib/tooling/find_codeowners_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe Tooling::FindCodeowners do
allow(subject).to receive(:load_config).and_return(
'[Section name]': {
'@group': {
+ entries: %w[whatever entries],
allow: {
keywords: %w[dir0 file],
patterns: ['/%{keyword}/**/*', '/%{keyword}']
@@ -31,8 +32,11 @@ RSpec.describe Tooling::FindCodeowners do
end
end.to output(<<~CODEOWNERS).to_stdout
[Section name]
+ whatever @group
+ entries @group
/dir0/dir1/ @group
/file @group
+
CODEOWNERS
end
end
@@ -57,21 +61,33 @@ RSpec.describe Tooling::FindCodeowners do
patterns: ['%{keyword}']
}
}
+ },
+ '[Compliance]': {
+ '@gitlab-org/manage/compliance': {
+ entries: %w[
+ /ee/app/services/audit_events/build_service.rb
+ ],
+ allow: {
+ patterns: %w[
+ /ee/app/services/audit_events/*
+ ]
+ }
+ }
}
}
)
end
it 'expands the allow and deny list with keywords and patterns' do
- subject.load_definitions.each do |section, group_defintions|
- group_defintions.each do |group, definitions|
- expect(definitions[:allow]).to be_an(Array)
- expect(definitions[:deny]).to be_an(Array)
- end
+ group_defintions = subject.load_definitions[:'[Authentication and Authorization]']
+
+ group_defintions.each do |group, definitions|
+ expect(definitions[:allow]).to be_an(Array)
+ expect(definitions[:deny]).to be_an(Array)
end
end
- it 'expands the auth group' do
+ it 'expands the patterns for the auth group' do
auth = subject.load_definitions.dig(
:'[Authentication and Authorization]',
:'@gitlab-org/manage/authentication-and-authorization')
@@ -95,6 +111,21 @@ RSpec.describe Tooling::FindCodeowners do
]
)
end
+
+ it 'retains the array and expands the patterns for the compliance group' do
+ compliance = subject.load_definitions.dig(
+ :'[Compliance]',
+ :'@gitlab-org/manage/compliance')
+
+ expect(compliance).to eq(
+ entries: %w[
+ /ee/app/services/audit_events/build_service.rb
+ ],
+ allow: %w[
+ /ee/app/services/audit_events/*
+ ]
+ )
+ end
end
describe '#load_config' do
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
index 10afcb18a73..f4eea28b66f 100644
--- a/spec/tooling/quality/test_level_spec.rb
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
- .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,events,factories,finders,frontend,graphql,haml_lint,helpers,initializers,lib,metrics_server,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,sidekiq_cluster,spam,support_specs,tasks,uploaders,validators,views,workers,tooling,components}{,/**/}*_spec.rb")
+ .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,lib,metrics_server,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,sidekiq_cluster,spam,support_specs,tasks,uploaders,validators,views,workers,tooling,components}{,/**/}*_spec.rb")
end
end
@@ -121,7 +121,7 @@ RSpec.describe Quality::TestLevel do
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
- .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|events|factories|finders|frontend|graphql|haml_lint|helpers|initializers|lib|metrics_server|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|sidekiq_cluster|spam|support_specs|tasks|uploaders|validators|views|workers|tooling|components)/})
+ .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|lib|metrics_server|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|sidekiq_cluster|spam|support_specs|tasks|uploaders|validators|views|workers|tooling|components)/})
end
end
diff --git a/spec/uploaders/avatar_uploader_spec.rb b/spec/uploaders/avatar_uploader_spec.rb
index 1fadd9425ef..a55e5c23fe8 100644
--- a/spec/uploaders/avatar_uploader_spec.rb
+++ b/spec/uploaders/avatar_uploader_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe AvatarUploader do
# in a stub below so we can set any path.
let_it_be(:path) { File.join('spec', 'fixtures', 'video_sample.mp4') }
- where(:mime_type) { described_class::MIME_WHITELIST }
+ where(:mime_type) { described_class::MIME_ALLOWLIST }
with_them do
include_context 'force content type detection to mime_type'
diff --git a/spec/uploaders/design_management/design_v432x230_uploader_spec.rb b/spec/uploaders/design_management/design_v432x230_uploader_spec.rb
index b3a106ef94b..a18a37e73da 100644
--- a/spec/uploaders/design_management/design_v432x230_uploader_spec.rb
+++ b/spec/uploaders/design_management/design_v432x230_uploader_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe DesignManagement::DesignV432x230Uploader do
# in a stub below so we can set any path.
let_it_be(:path) { File.join('spec', 'fixtures', 'dk.png') }
- where(:mime_type) { described_class::MIME_TYPE_WHITELIST }
+ where(:mime_type) { described_class::MIME_TYPE_ALLOWLIST }
with_them do
include_context 'force content type detection to mime_type'
diff --git a/spec/uploaders/favicon_uploader_spec.rb b/spec/uploaders/favicon_uploader_spec.rb
index 6bff3ff8a14..7f452075293 100644
--- a/spec/uploaders/favicon_uploader_spec.rb
+++ b/spec/uploaders/favicon_uploader_spec.rb
@@ -7,13 +7,13 @@ RSpec.describe FaviconUploader do
let_it_be(:uploader) { described_class.new(model, :favicon) }
context 'accept whitelist file content type' do
- include_context 'ignore extension whitelist check'
+ include_context 'ignore extension allowlist check'
# We need to feed through a valid path, but we force the parsed mime type
# in a stub below so we can set any path.
let_it_be(:path) { File.join('spec', 'fixtures', 'video_sample.mp4') }
- where(:mime_type) { described_class::MIME_WHITELIST }
+ where(:mime_type) { described_class::MIME_ALLOWLIST }
with_them do
include_context 'force content type detection to mime_type'
@@ -23,7 +23,7 @@ RSpec.describe FaviconUploader do
end
context 'upload non-whitelisted file content type' do
- include_context 'ignore extension whitelist check'
+ include_context 'ignore extension allowlist check'
let_it_be(:path) { File.join('spec', 'fixtures', 'sanitized.svg') }
@@ -31,7 +31,7 @@ RSpec.describe FaviconUploader do
end
context 'upload misnamed non-whitelisted file content type' do
- include_context 'ignore extension whitelist check'
+ include_context 'ignore extension allowlist check'
let_it_be(:path) { File.join('spec', 'fixtures', 'not_a_png.png') }
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 1bcc43b81a8..a4f6116f7d7 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -256,8 +256,22 @@ RSpec.describe ObjectStorage do
describe '#use_open_file' do
context 'when file is stored locally' do
- it "returns the file" do
- expect { |b| uploader.use_open_file(&b) }.to yield_with_args(an_instance_of(ObjectStorage::Concern::OpenFile))
+ it "returns the file unlinked" do
+ expect { |b| uploader.use_open_file(&b) }.to yield_with_args(
+ satisfying do |f|
+ expect(f).to be_an_instance_of(ObjectStorage::Concern::OpenFile)
+ expect(f.file_path).to be_nil
+ end
+ )
+ end
+
+ it "returns the file not unlinked" do
+ expect { |b| uploader.use_open_file(unlink_early: false, &b) }.to yield_with_args(
+ satisfying do |f|
+ expect(f).to be_an_instance_of(ObjectStorage::Concern::OpenFile)
+ expect(File.exist?(f.file_path)).to be_truthy
+ end
+ )
end
end
diff --git a/spec/views/admin/identities/index.html.haml_spec.rb b/spec/views/admin/identities/index.html.haml_spec.rb
new file mode 100644
index 00000000000..3e8def003ae
--- /dev/null
+++ b/spec/views/admin/identities/index.html.haml_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'admin/identities/index.html.haml', :aggregate_failures do
+ include Admin::IdentitiesHelper
+
+ let_it_be(:ldap_user) { create(:omniauth_user, provider: 'ldapmain', extern_uid: 'ldap-uid') }
+
+ before do
+ assign(:user, ldap_user)
+ view.lookup_context.prefixes = ['admin/identities']
+ end
+
+ context 'without identities' do
+ before do
+ assign(:identities, [])
+ end
+
+ it 'shows table headers' do
+ render
+
+ expect(rendered).to include('<th class="gl-border-t-0!">').exactly(5)
+ expect(rendered).to include(_('Provider'))
+ expect(rendered).to include(s_('Identity|Provider ID'))
+ expect(rendered).to include(_('Group'))
+ expect(rendered).to include(_('Identifier'))
+ expect(rendered).to include(_('Actions'))
+ end
+
+ it 'shows information text' do
+ render
+
+ expect(rendered).to include('<td colspan="5">').exactly(1)
+ expect(rendered).to include(_('This user has no identities'))
+ end
+ end
+
+ context 'with LDAP identities' do
+ before do
+ assign(:identities, ldap_user.identities)
+ end
+
+ it 'shows exactly 5 columns' do
+ render
+
+ expect(rendered).to include('</td>').exactly(5)
+ end
+
+ it 'shows identity without provider ID or group' do
+ render
+
+ # Provider
+ expect(rendered).to include('ldap (ldapmain)')
+ # Provider ID
+ expect(rendered).to include('data-testid="provider_id_blank"')
+ # Group
+ expect(rendered).to include('data-testid="saml_group_blank"')
+ # Identifier
+ expect(rendered).to include('ldap-uid')
+ end
+
+ it 'shows edit and delete identity buttons' do
+ render
+
+ expect(rendered).to include("aria-label=\"#{_('Edit')}\"")
+ expect(rendered).to include("aria-label=\"#{_('Delete identity')}\"")
+ end
+ end
+end
diff --git a/spec/views/devise/sessions/new.html.haml_spec.rb b/spec/views/devise/sessions/new.html.haml_spec.rb
index b3cd1493149..c8e9aa15287 100644
--- a/spec/views/devise/sessions/new.html.haml_spec.rb
+++ b/spec/views/devise/sessions/new.html.haml_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe 'devise/sessions/new' do
before do
stub_devise
disable_captcha
+ stub_feature_flags(restyle_login_page: false)
allow(Gitlab).to receive(:com?).and_return(true)
end
@@ -29,67 +30,74 @@ RSpec.describe 'devise/sessions/new' do
end
end
- describe 'ldap' do
- include LdapHelpers
-
- let(:server) { { provider_name: 'ldapmain', label: 'LDAP' }.with_indifferent_access }
-
+ flag_values = [true, false]
+ flag_values.each do |val|
before do
- enable_ldap
- stub_devise
- disable_captcha
- disable_sign_up
- disable_other_signin_methods
-
- allow(view).to receive(:experiment_enabled?).and_return(false)
+ stub_feature_flags(restyle_login_page: val)
end
- it 'is shown when enabled' do
- render
+ describe 'ldap' do
+ include LdapHelpers
- expect(rendered).to have_selector('.new-session-tabs')
- expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
- expect(rendered).to have_field('LDAP Username')
- end
+ let(:server) { { provider_name: 'ldapmain', label: 'LDAP' }.with_indifferent_access }
- it 'is not shown when LDAP sign in is disabled' do
- disable_ldap_sign_in
+ before do
+ enable_ldap
+ stub_devise
+ disable_captcha
+ disable_sign_up
+ disable_other_signin_methods
- render
+ allow(view).to receive(:experiment_enabled?).and_return(false)
+ end
- expect(rendered).to have_content('No authentication methods configured')
- expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
- expect(rendered).not_to have_field('LDAP Username')
- end
- end
+ it 'is shown when enabled' do
+ render
- describe 'Google Tag Manager' do
- let!(:gtm_id) { 'GTM-WWKMTWS'}
+ expect(rendered).to have_selector('.new-session-tabs')
+ expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
+ expect(rendered).to have_field('LDAP Username')
+ end
- subject { rendered }
+ it 'is not shown when LDAP sign in is disabled' do
+ disable_ldap_sign_in
- before do
- stub_devise
- disable_captcha
- stub_config(extra: { google_tag_manager_id: gtm_id, google_tag_manager_nonce_id: gtm_id })
+ render
+
+ expect(rendered).to have_content('No authentication methods configured')
+ expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
+ expect(rendered).not_to have_field('LDAP Username')
+ end
end
- describe 'when Google Tag Manager is enabled' do
+ describe 'Google Tag Manager' do
+ let!(:gtm_id) { 'GTM-WWKMTWS' }
+
+ subject { rendered }
+
before do
- enable_gtm
- render
+ stub_devise
+ disable_captcha
+ stub_config(extra: { google_tag_manager_id: gtm_id, google_tag_manager_nonce_id: gtm_id })
end
- it { is_expected.to match /www.googletagmanager.com/ }
- end
+ describe 'when Google Tag Manager is enabled' do
+ before do
+ enable_gtm
+ render
+ end
- describe 'when Google Tag Manager is disabled' do
- before do
- disable_gtm
- render
+ it { is_expected.to match /www.googletagmanager.com/ }
end
- it { is_expected.not_to match /www.googletagmanager.com/ }
+ describe 'when Google Tag Manager is disabled' do
+ before do
+ disable_gtm
+ render
+ end
+
+ it { is_expected.not_to match /www.googletagmanager.com/ }
+ end
end
end
diff --git a/spec/views/groups/group_members/index.html.haml_spec.rb b/spec/views/groups/group_members/index.html.haml_spec.rb
index 2d7d50555d6..c7aebb94a45 100644
--- a/spec/views/groups/group_members/index.html.haml_spec.rb
+++ b/spec/views/groups/group_members/index.html.haml_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe 'groups/group_members/index', :aggregate_failures do
render
expect(rendered).to have_content('Group members')
- expect(rendered).to have_content('You can invite a new member')
+ expect(rendered).to have_content("You're viewing members")
expect(rendered).to have_selector('.js-invite-group-trigger')
expect(rendered).to have_selector('.js-invite-members-trigger')
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index 208da345e7f..79c22871b44 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -40,7 +40,10 @@ RSpec.describe 'layouts/header/_new_dropdown' do
it 'has a "New subgroup" link' do
render
- expect(rendered).to have_link('New subgroup', href: new_group_path(parent_id: group.id))
+ expect(rendered).to have_link(
+ 'New subgroup',
+ href: new_group_path(parent_id: group.id, anchor: 'create-group-pane')
+ )
end
end
diff --git a/spec/views/projects/blob/_viewer.html.haml_spec.rb b/spec/views/projects/blob/_viewer.html.haml_spec.rb
index 893cfec1491..2761d10f9ad 100644
--- a/spec/views/projects/blob/_viewer.html.haml_spec.rb
+++ b/spec/views/projects/blob/_viewer.html.haml_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe 'projects/blob/_viewer.html.haml' do
before do
assign(:project, project)
assign(:blob, blob)
+ assign(:ref, 'master')
assign(:id, File.join('master', blob.path))
controller.params[:controller] = 'projects/blob'
diff --git a/spec/views/projects/pages/new.html.haml_spec.rb b/spec/views/projects/pages/new.html.haml_spec.rb
new file mode 100644
index 00000000000..919b2fe84ee
--- /dev/null
+++ b/spec/views/projects/pages/new.html.haml_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'projects/pages/new' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ before do
+ allow(project).to receive(:show_pages_onboarding?).and_return(true)
+ project.add_maintainer(user)
+
+ assign(:project, project)
+ allow(view).to receive(:current_user).and_return(user)
+ end
+
+ describe 'with onboarding wizard feature enabled' do
+ before do
+ Feature.enable(:use_pipeline_wizard_for_pages)
+ end
+
+ it "shows the onboarding wizard" do
+ render
+ expect(rendered).to have_selector('#js-pages')
+ end
+ end
+
+ describe 'with onboarding wizard feature disabled' do
+ before do
+ Feature.disable(:use_pipeline_wizard_for_pages)
+ end
+
+ it "does not show the onboarding wizard" do
+ render
+ expect(rendered).not_to have_selector('#js-pages')
+ end
+
+ it "renders the usage instructions" do
+ render
+ expect(rendered).to render_template('projects/pages/_use')
+ end
+ end
+end
diff --git a/spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb b/spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb
index e650e183bc8..37c9908af1d 100644
--- a/spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb
+++ b/spec/views/projects/pipeline_schedules/_pipeline_schedule.html.haml_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'projects/pipeline_schedules/_pipeline_schedule' do
it 'non-owner can take ownership of pipeline' do
render
- expect(rendered).to have_link('Take ownership')
+ expect(rendered).to have_button('Take ownership')
end
end
@@ -42,7 +42,7 @@ RSpec.describe 'projects/pipeline_schedules/_pipeline_schedule' do
it 'owner cannot take ownership of pipeline' do
render
- expect(rendered).not_to have_link('Take ownership')
+ expect(rendered).not_to have_button('Take ownership')
end
end
end
diff --git a/spec/workers/archive_trace_worker_spec.rb b/spec/workers/archive_trace_worker_spec.rb
deleted file mode 100644
index a9f256b1b3b..00000000000
--- a/spec/workers/archive_trace_worker_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ArchiveTraceWorker do
- describe '#perform' do
- subject { described_class.new.perform(job&.id) }
-
- context 'when job is found' do
- let(:job) { create(:ci_build, :trace_live) }
-
- it 'executes service' do
- expect_any_instance_of(Ci::ArchiveTraceService)
- .to receive(:execute).with(job, anything)
-
- subject
- end
- end
-
- context 'when job is not found' do
- let(:job) { nil }
-
- it 'does not execute service' do
- expect_any_instance_of(Ci::ArchiveTraceService)
- .not_to receive(:execute)
-
- subject
- end
- end
- end
-end
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
deleted file mode 100644
index 2ff173c1558..00000000000
--- a/spec/workers/build_finished_worker_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildFinishedWorker do
- let(:worker) { described_class.new }
-
- subject { worker.perform(build.id) }
-
- describe '#perform' do
- context 'when build exists' do
- let_it_be(:build) { create(:ci_build, :success, pipeline: create(:ci_pipeline)) }
-
- before do
- expect(Ci::Build).to receive(:find_by).with({ id: build.id }).and_return(build)
- end
-
- it 'calculates coverage and calls hooks', :aggregate_failures do
- expect(build).to receive(:update_coverage).ordered
-
- expect_next_instance_of(Ci::BuildReportResultService) do |build_report_result_service|
- expect(build_report_result_service).to receive(:execute).with(build)
- end
-
- expect(BuildHooksWorker).to receive(:perform_async)
- expect(ChatNotificationWorker).not_to receive(:perform_async)
- expect(Ci::ArchiveTraceWorker).to receive(:perform_in)
-
- subject
- end
-
- context 'when build is failed' do
- before do
- build.update!(status: :failed)
- end
-
- it 'adds a todo' do
- expect(::Ci::MergeRequests::AddTodoWhenBuildFailsWorker).to receive(:perform_async)
-
- subject
- end
- end
-
- context 'when build has a chat' do
- before do
- build.pipeline.update!(source: :chat)
- end
-
- it 'schedules a ChatNotification job' do
- expect(ChatNotificationWorker).to receive(:perform_async).with(build.id)
-
- subject
- end
- end
-
- context 'when project is deleted' do
- before do
- allow(build).to receive(:project).and_return(nil)
- end
-
- it 'does no processing' do
- expect(worker).not_to receive(:process_build)
-
- subject
- end
- end
-
- context 'when project is pending_delete' do
- before do
- build.project.update_attribute(:pending_delete, true)
- end
-
- it 'does no processing' do
- expect(worker).not_to receive(:process_build)
-
- subject
- end
- end
- end
-
- context 'when build does not exist' do
- it 'does not raise exception' do
- expect { described_class.new.perform(non_existing_record_id) }
- .not_to raise_error
- end
- end
- end
-end
diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb
index 426eb03638c..80dc36d268f 100644
--- a/spec/workers/build_hooks_worker_spec.rb
+++ b/spec/workers/build_hooks_worker_spec.rb
@@ -23,8 +23,8 @@ RSpec.describe BuildHooksWorker do
end
end
- describe '.perform_async' do
- it 'sends a message to the application logger, before performing', :sidekiq_inline do
+ describe '.perform_async', :sidekiq_inline do
+ it 'sends a message to the application logger, before performing' do
build = create(:ci_build)
expect(Gitlab::AppLogger).to receive(:info).with(
diff --git a/spec/workers/ci/build_finished_worker_spec.rb b/spec/workers/ci/build_finished_worker_spec.rb
index 201182636e7..5ddaabc3938 100644
--- a/spec/workers/ci/build_finished_worker_spec.rb
+++ b/spec/workers/ci/build_finished_worker_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::BuildFinishedWorker do
+ include AfterNextHelpers
+
subject { described_class.new.perform(build.id) }
describe '#perform' do
@@ -16,17 +18,28 @@ RSpec.describe Ci::BuildFinishedWorker do
it 'calculates coverage and calls hooks', :aggregate_failures do
expect(build).to receive(:update_coverage).ordered
- expect_next_instance_of(Ci::BuildReportResultService) do |build_report_result_service|
- expect(build_report_result_service).to receive(:execute).with(build)
- end
+ expect_next(Ci::BuildReportResultService).to receive(:execute).with(build)
- expect(BuildHooksWorker).to receive(:perform_async)
+ expect(build).to receive(:execute_hooks)
expect(ChatNotificationWorker).not_to receive(:perform_async)
expect(Ci::ArchiveTraceWorker).to receive(:perform_in)
subject
end
+ context 'when the execute_build_hooks_inline feature flag is disabled' do
+ before do
+ stub_feature_flags(execute_build_hooks_inline: false)
+ end
+
+ it 'uses the BuildHooksWorker' do
+ expect(build).not_to receive(:execute_hooks)
+ expect(BuildHooksWorker).to receive(:perform_async).with(build)
+
+ subject
+ end
+ end
+
context 'when build is failed' do
before do
build.update!(status: :failed)
diff --git a/spec/workers/ci/cancel_pipeline_worker_spec.rb b/spec/workers/ci/cancel_pipeline_worker_spec.rb
new file mode 100644
index 00000000000..6165aaff1c7
--- /dev/null
+++ b/spec/workers/ci/cancel_pipeline_worker_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CancelPipelineWorker, :aggregate_failures do
+ let!(:pipeline) { create(:ci_pipeline, :running) }
+
+ describe '#perform' do
+ subject(:perform) { described_class.new.perform(pipeline.id, pipeline.id) }
+
+ it 'calls cancel_running' do
+ allow(::Ci::Pipeline).to receive(:find_by_id).and_return(pipeline)
+ expect(pipeline).to receive(:cancel_running).with(
+ auto_canceled_by_pipeline_id: pipeline.id,
+ cascade_to_children: false
+ )
+
+ perform
+ end
+
+ context 'if pipeline is deleted' do
+ subject(:perform) { described_class.new.perform(non_existing_record_id, non_existing_record_id) }
+
+ it 'does not error' do
+ expect(pipeline).not_to receive(:cancel_running)
+
+ perform
+ end
+ end
+
+ describe 'with builds and state transition side effects', :sidekiq_inline do
+ let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it_behaves_like 'an idempotent worker', :sidekiq_inline do
+ let(:job_args) { [pipeline.id, pipeline.id] }
+
+ it 'cancels the pipeline' do
+ perform
+
+ pipeline.reload
+
+ expect(pipeline).to be_canceled
+ expect(pipeline.builds.first).to be_canceled
+ expect(pipeline.builds.first.auto_canceled_by_id).to eq pipeline.id
+ expect(pipeline.auto_canceled_by_id).to eq pipeline.id
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/runners/process_runner_version_update_worker_spec.rb b/spec/workers/ci/runners/process_runner_version_update_worker_spec.rb
new file mode 100644
index 00000000000..ff67266c3e8
--- /dev/null
+++ b/spec/workers/ci/runners/process_runner_version_update_worker_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Runners::ProcessRunnerVersionUpdateWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ let(:version) { '1.0.0' }
+ let(:job_args) { version }
+
+ include_examples 'an idempotent worker' do
+ subject(:perform_twice) { perform_multiple(job_args, worker: worker, exec_times: 2) }
+
+ let(:service) { ::Ci::Runners::ProcessRunnerVersionUpdateService.new(version) }
+ let(:available_runner_releases) do
+ %w[1.0.0 1.0.1]
+ end
+
+ before do
+ allow(Ci::Runners::ProcessRunnerVersionUpdateService).to receive(:new).and_return(service)
+ allow(service).to receive(:execute).and_call_original
+
+ url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+
+ WebMock.stub_request(:get, url).to_return(
+ body: available_runner_releases.map { |v| { name: v } }.to_json,
+ status: 200,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+ end
+
+ it 'logs the service result', :aggregate_failures do
+ perform_twice
+
+ expect(Ci::Runners::ProcessRunnerVersionUpdateService).to have_received(:new).twice
+ expect(service).to have_received(:execute).twice
+ expect(worker.logging_extras).to eq(
+ {
+ 'extra.ci_runners_process_runner_version_update_worker.status' => :success,
+ 'extra.ci_runners_process_runner_version_update_worker.message' => nil,
+ 'extra.ci_runners_process_runner_version_update_worker.upgrade_status' => 'recommended'
+ }
+ )
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/runners/reconcile_existing_runner_versions_cron_worker_spec.rb b/spec/workers/ci/runners/reconcile_existing_runner_versions_cron_worker_spec.rb
new file mode 100644
index 00000000000..1292df62ce5
--- /dev/null
+++ b/spec/workers/ci/runners/reconcile_existing_runner_versions_cron_worker_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Runners::ReconcileExistingRunnerVersionsCronWorker do
+ subject(:worker) { described_class.new }
+
+ describe '#perform' do
+ context 'when scheduled by cronjob' do
+ it 'reschedules itself' do
+ expect(described_class).to(receive(:perform_in).with(a_value_between(0, 12.hours.in_seconds), false))
+ expect(::Ci::Runners::ReconcileExistingRunnerVersionsService).not_to receive(:new)
+
+ worker.perform
+ end
+ end
+
+ context 'when self-scheduled' do
+ include_examples 'an idempotent worker' do
+ subject(:perform) { perform_multiple(false, worker: worker) }
+
+ it 'executes the service' do
+ expect_next_instance_of(Ci::Runners::ReconcileExistingRunnerVersionsService) do |service|
+ expect(service).to receive(:execute).and_return(ServiceResponse.success)
+ end.exactly(worker_exec_times)
+
+ perform
+ end
+ end
+
+ it 'logs the service result' do
+ expect_next_instance_of(Ci::Runners::ReconcileExistingRunnerVersionsService) do |service|
+ expect(service).to receive(:execute)
+ .and_return(ServiceResponse.success(payload: { some_job_result_key: 'some_value' }))
+ end
+
+ worker.perform(false)
+
+ expect(worker.logging_extras).to eq({
+ 'extra.ci_runners_reconcile_existing_runner_versions_cron_worker.some_job_result_key' => 'some_value'
+ })
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/track_failed_build_worker_spec.rb b/spec/workers/ci/track_failed_build_worker_spec.rb
new file mode 100644
index 00000000000..12d0e64afc5
--- /dev/null
+++ b/spec/workers/ci/track_failed_build_worker_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ci::TrackFailedBuildWorker do
+ let_it_be(:build) { create(:ci_build, :failed, :sast_report) }
+ let_it_be(:exit_code) { 42 }
+ let_it_be(:failure_reason) { "script_failure" }
+
+ subject { described_class.new.perform(build.id, exit_code, failure_reason) }
+
+ describe '#perform' do
+ context 'when a build has failed' do
+ it 'executes track service' do
+ expect(Ci::TrackFailedBuildService)
+ .to receive(:new)
+ .with(build: build, exit_code: exit_code, failure_reason: failure_reason)
+ .and_call_original
+
+ subject
+ end
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [build.id, exit_code, failure_reason] }
+ end
+ end
+end
diff --git a/spec/workers/concerns/limited_capacity/job_tracker_spec.rb b/spec/workers/concerns/limited_capacity/job_tracker_spec.rb
index eeccdbd0e2d..0e3fa350fcd 100644
--- a/spec/workers/concerns/limited_capacity/job_tracker_spec.rb
+++ b/spec/workers/concerns/limited_capacity/job_tracker_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe LimitedCapacity::JobTracker, :clean_gitlab_redis_shared_state do
describe '#register' do
it 'adds jid to the set' do
- expect(job_tracker.register('a-job-id', max_jids)). to be true
+ expect(job_tracker.register('a-job-id', max_jids)).to be true
expect(job_tracker.running_jids).to contain_exactly('a-job-id')
end
diff --git a/spec/workers/concerns/waitable_worker_spec.rb b/spec/workers/concerns/waitable_worker_spec.rb
index f6d4cc4679d..bf156c3b8cb 100644
--- a/spec/workers/concerns/waitable_worker_spec.rb
+++ b/spec/workers/concerns/waitable_worker_spec.rb
@@ -30,19 +30,33 @@ RSpec.describe WaitableWorker do
describe '.bulk_perform_and_wait' do
context '1 job' do
- it 'inlines the job' do
- args_list = [[1]]
- expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original
- expect(Gitlab::AppJsonLogger).to(
- receive(:info).with(a_hash_including('message' => 'running inline',
- 'class' => 'Gitlab::Foo::Bar::DummyWorker',
- 'job_status' => 'running',
- 'queue' => 'foo_bar_dummy'))
- .once)
-
- worker.bulk_perform_and_wait(args_list)
-
- expect(worker.counter).to eq(1)
+ it 'runs the jobs asynchronously' do
+ arguments = [[1]]
+
+ expect(worker).to receive(:bulk_perform_async).with(arguments)
+
+ worker.bulk_perform_and_wait(arguments)
+ end
+
+ context 'when the feature flag `always_async_project_authorizations_refresh` is turned off' do
+ before do
+ stub_feature_flags(always_async_project_authorizations_refresh: false)
+ end
+
+ it 'inlines the job' do
+ args_list = [[1]]
+ expect(worker).to receive(:bulk_perform_inline).with(args_list).and_call_original
+ expect(Gitlab::AppJsonLogger).to(
+ receive(:info).with(a_hash_including('message' => 'running inline',
+ 'class' => 'Gitlab::Foo::Bar::DummyWorker',
+ 'job_status' => 'running',
+ 'queue' => 'foo_bar_dummy'))
+ .once)
+
+ worker.bulk_perform_and_wait(args_list)
+
+ expect(worker.counter).to eq(1)
+ end
end
end
diff --git a/spec/workers/database/batched_background_migration/ci_database_worker_spec.rb b/spec/workers/database/batched_background_migration/ci_database_worker_spec.rb
index 2b4a42060d9..dfe7a266be2 100644
--- a/spec/workers/database/batched_background_migration/ci_database_worker_spec.rb
+++ b/spec/workers/database/batched_background_migration/ci_database_worker_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Database::BatchedBackgroundMigration::CiDatabaseWorker, :clean_gitlab_redis_shared_state do
- it_behaves_like 'it runs batched background migration jobs', :ci
+ it_behaves_like 'it runs batched background migration jobs', :ci, :ci_builds
end
diff --git a/spec/workers/database/batched_background_migration_worker_spec.rb b/spec/workers/database/batched_background_migration_worker_spec.rb
index a6c7db60abe..e57bd7581c2 100644
--- a/spec/workers/database/batched_background_migration_worker_spec.rb
+++ b/spec/workers/database/batched_background_migration_worker_spec.rb
@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe Database::BatchedBackgroundMigrationWorker do
- it_behaves_like 'it runs batched background migration jobs', :main
+ it_behaves_like 'it runs batched background migration jobs', :main, :events
end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index e8ec7c28537..4a1bf7dbbf9 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -382,6 +382,7 @@ RSpec.describe 'Every Sidekiq worker' do
'ProjectScheduleBulkRepositoryShardMovesWorker' => 3,
'ProjectTemplateExportWorker' => false,
'ProjectUpdateRepositoryStorageWorker' => 3,
+ 'Projects::DisableLegacyOpenSourceLicenseForInactiveProjectsWorker' => 3,
'Projects::GitGarbageCollectWorker' => false,
'Projects::InactiveProjectsDeletionNotificationWorker' => 3,
'Projects::PostCreationWorker' => 3,
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 b3c6a48767c..932152c0764 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
@@ -8,37 +8,66 @@ 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] }
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
- it 'imports all the issue events' do
- waiter = Gitlab::JobWaiter.new(2, '123')
+ context 'when single endpoint feature flag enabled' do
+ it 'imports all the issue events' do
+ waiter = Gitlab::JobWaiter.new(2, '123')
- expect(Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter)
- .to receive(:new)
- .with(project, client)
- .and_return(importer)
+ expect(Gitlab::GithubImport::Importer::IssueEventsImporter).not_to receive(:new)
+ expect(Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter)
+ .to receive(:new)
+ .with(project, client)
+ .and_return(importer)
- expect(importer).to receive(:execute).and_return(waiter)
+ expect(importer).to receive(:execute).and_return(waiter)
- expect(Gitlab::GithubImport::AdvanceStageWorker)
- .to receive(:perform_async)
- .with(project.id, { '123' => 2 }, :notes)
+ expect(Gitlab::GithubImport::AdvanceStageWorker)
+ .to receive(:perform_async)
+ .with(project.id, { '123' => 2 }, :notes)
- worker.import(client, project)
+ worker.import(client, project)
+ 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 flag is disabled' do
+ context 'when feature flags are disabled' do
let(:feature_flag_state) { false }
+ let(:single_endpoint_feature_flag_state) { 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/merge_requests/create_approval_event_worker_spec.rb b/spec/workers/merge_requests/create_approval_event_worker_spec.rb
new file mode 100644
index 00000000000..8389949ecc9
--- /dev/null
+++ b/spec/workers/merge_requests/create_approval_event_worker_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::CreateApprovalEventWorker do
+ let!(:user) { create(:user) }
+ let!(:project) { create(:project) }
+ let!(:merge_request) { create(:merge_request, source_project: project) }
+ let(:data) { { current_user_id: user.id, merge_request_id: merge_request.id } }
+ let(:approved_event) { MergeRequests::ApprovedEvent.new(data: data) }
+
+ it_behaves_like 'subscribes to event' do
+ let(:event) { approved_event }
+ end
+
+ it 'calls MergeRequests::CreateApprovalEventService' do
+ expect_next_instance_of(
+ MergeRequests::CreateApprovalEventService,
+ project: project, current_user: user
+ ) do |service|
+ expect(service).to receive(:execute).with(merge_request)
+ end
+
+ consume_event(subscriber: described_class, event: approved_event)
+ end
+
+ shared_examples 'when object does not exist' do
+ it 'does not call MergeRequests::CreateApprovalEventService' do
+ expect(MergeRequests::CreateApprovalEventService).not_to receive(:new)
+
+ expect { consume_event(subscriber: described_class, event: approved_event) }
+ .not_to raise_exception
+ end
+ end
+
+ context 'when the user does not exist' do
+ before do
+ user.destroy!
+ end
+
+ it_behaves_like 'when object does not exist'
+ end
+
+ context 'when the merge request does not exist' do
+ before do
+ merge_request.destroy!
+ end
+
+ it_behaves_like 'when object does not exist'
+ end
+end
diff --git a/spec/workers/merge_requests/create_approval_note_worker_spec.rb b/spec/workers/merge_requests/create_approval_note_worker_spec.rb
new file mode 100644
index 00000000000..f58d38599fc
--- /dev/null
+++ b/spec/workers/merge_requests/create_approval_note_worker_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::CreateApprovalNoteWorker do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:data) { { current_user_id: user.id, merge_request_id: merge_request.id } }
+ let(:approved_event) { MergeRequests::ApprovedEvent.new(data: data) }
+
+ it_behaves_like 'subscribes to event' do
+ let(:event) { approved_event }
+ end
+
+ it 'calls SystemNoteService.approve_mr' do
+ expect(SystemNoteService).to receive(:approve_mr).with(merge_request, user)
+
+ consume_event(subscriber: described_class, event: approved_event)
+ end
+
+ shared_examples 'when object does not exist' do
+ it 'logs and does not call SystemNoteService.approve_mr' do
+ expect(Sidekiq.logger).to receive(:info).with(hash_including(log_payload))
+ expect(SystemNoteService).not_to receive(:approve_mr)
+
+ expect { consume_event(subscriber: described_class, event: approved_event) }
+ .not_to raise_exception
+ end
+ end
+
+ context 'when the user does not exist' do
+ before do
+ user.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Current user not found.', 'current_user_id' => user.id } }
+ end
+ end
+
+ context 'when the merge request does not exist' do
+ before do
+ merge_request.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Merge request not found.', 'merge_request_id' => merge_request.id } }
+ end
+ end
+end
diff --git a/spec/workers/merge_requests/execute_approval_hooks_worker_spec.rb b/spec/workers/merge_requests/execute_approval_hooks_worker_spec.rb
new file mode 100644
index 00000000000..0130ef63f50
--- /dev/null
+++ b/spec/workers/merge_requests/execute_approval_hooks_worker_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ExecuteApprovalHooksWorker do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:data) { { current_user_id: user.id, merge_request_id: merge_request.id } }
+ let(:approved_event) { MergeRequests::ApprovedEvent.new(data: data) }
+
+ it_behaves_like 'subscribes to event' do
+ let(:event) { approved_event }
+ end
+
+ it 'calls MergeRequests::ExecuteApprovalHooksService' do
+ expect_next_instance_of(
+ MergeRequests::ExecuteApprovalHooksService,
+ project: project, current_user: user
+ ) do |service|
+ expect(service).to receive(:execute).with(merge_request)
+ end
+
+ consume_event(subscriber: described_class, event: approved_event)
+ end
+
+ shared_examples 'when object does not exist' do
+ it 'logs and does not call MergeRequests::ExecuteApprovalHooksService' do
+ expect(Sidekiq.logger).to receive(:info).with(hash_including(log_payload))
+ expect(MergeRequests::ExecuteApprovalHooksService).not_to receive(:new)
+
+ expect { consume_event(subscriber: described_class, event: approved_event) }
+ .not_to raise_exception
+ end
+ end
+
+ context 'when the user does not exist' do
+ before do
+ user.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Current user not found.', 'current_user_id' => user.id } }
+ end
+ end
+
+ context 'when the merge request does not exist' do
+ before do
+ merge_request.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Merge request not found.', 'merge_request_id' => merge_request.id } }
+ end
+ end
+end
diff --git a/spec/workers/merge_requests/resolve_todos_after_approval_worker_spec.rb b/spec/workers/merge_requests/resolve_todos_after_approval_worker_spec.rb
new file mode 100644
index 00000000000..f8316a8ff05
--- /dev/null
+++ b/spec/workers/merge_requests/resolve_todos_after_approval_worker_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::ResolveTodosAfterApprovalWorker do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let(:data) { { current_user_id: user.id, merge_request_id: merge_request.id } }
+ let(:approved_event) { MergeRequests::ApprovedEvent.new(data: data) }
+
+ it_behaves_like 'subscribes to event' do
+ let(:event) { approved_event }
+ end
+
+ it 'calls TodoService#resolve_todos_for_target' do
+ expect_next_instance_of(TodoService) do |todo_service|
+ expect(todo_service)
+ .to receive(:resolve_todos_for_target)
+ .with(merge_request, user)
+ end
+
+ consume_event(subscriber: described_class, event: approved_event)
+ end
+
+ shared_examples 'when object does not exist' do
+ it 'logs and does not call TodoService#resolve_todos_for_target' do
+ expect(Sidekiq.logger).to receive(:info).with(hash_including(log_payload))
+ expect(TodoService).not_to receive(:new)
+
+ expect { consume_event(subscriber: described_class, event: approved_event) }
+ .not_to raise_exception
+ end
+ end
+
+ context 'when the user does not exist' do
+ before do
+ user.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Current user not found.', 'current_user_id' => user.id } }
+ end
+ end
+
+ context 'when the merge request does not exist' do
+ before do
+ merge_request.destroy!
+ end
+
+ it_behaves_like 'when object does not exist' do
+ let(:log_payload) { { 'message' => 'Merge request not found.', 'merge_request_id' => merge_request.id } }
+ end
+ end
+end
diff --git a/spec/workers/new_issue_worker_spec.rb b/spec/workers/new_issue_worker_spec.rb
index 35b83c3bee8..b9053b10419 100644
--- a/spec/workers/new_issue_worker_spec.rb
+++ b/spec/workers/new_issue_worker_spec.rb
@@ -74,6 +74,8 @@ RSpec.describe NewIssueWorker do
it 'creates a new event record' do
expect { worker.perform(issue.id, user.id) }.to change { Event.count }.from(0).to(1)
+
+ expect(Event.last).to have_attributes(target_id: issue.id, target_type: 'Issue')
end
it 'creates a notification for the mentioned user' do
@@ -89,6 +91,14 @@ RSpec.describe NewIssueWorker do
worker.perform(issue.id, user.id)
end
+
+ context 'when a class is set' do
+ it 'creates event with the correct type' do
+ expect { worker.perform(issue.id, user.id, 'WorkItem') }.to change { Event.count }.from(0).to(1)
+
+ expect(Event.last).to have_attributes(target_id: issue.id, target_type: 'WorkItem')
+ end
+ end
end
end
end
diff --git a/spec/workers/packages/cleanup/execute_policy_worker_spec.rb b/spec/workers/packages/cleanup/execute_policy_worker_spec.rb
index 81fcec1a360..6325a82ed3d 100644
--- a/spec/workers/packages/cleanup/execute_policy_worker_spec.rb
+++ b/spec/workers/packages/cleanup/execute_policy_worker_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe Packages::Cleanup::ExecutePolicyWorker do
end
describe '#remaining_work_count' do
- subject { worker.remaining_work_count}
+ subject { worker.remaining_work_count }
context 'with no policies' do
it { is_expected.to eq(0) }
diff --git a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
index 1c1586ef199..9272e26a34f 100644
--- a/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
+++ b/spec/workers/pages/invalidate_domain_cache_worker_spec.rb
@@ -13,8 +13,8 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do
it_behaves_like 'subscribes to event'
it 'clears the cache with Gitlab::Pages::CacheControl' do
- caches.each do |cache_type, cache_id|
- expect_next_instance_of(Gitlab::Pages::CacheControl, type: cache_type, id: cache_id) do |cache_control|
+ caches.each do |cache|
+ expect_next_instance_of(Gitlab::Pages::CacheControl, type: cache[:type], id: cache[:id]) do |cache_control|
expect(cache_control).to receive(:clear_cache)
end
end
@@ -26,20 +26,120 @@ RSpec.describe Pages::InvalidateDomainCacheWorker do
it_behaves_like 'clears caches with',
event_class: Pages::PageDeployedEvent,
event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: { namespace: 3, project: 1 }
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
it_behaves_like 'clears caches with',
event_class: Pages::PageDeletedEvent,
event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: { namespace: 3, project: 1 }
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
it_behaves_like 'clears caches with',
event_class: Projects::ProjectDeletedEvent,
event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: { namespace: 3, project: 1 }
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
it_behaves_like 'clears caches with',
event_class: Projects::ProjectCreatedEvent,
event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
- caches: { namespace: 3, project: 1 }
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectArchivedEvent,
+ event_data: { project_id: 1, namespace_id: 2, root_namespace_id: 3 },
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectPathChangedEvent,
+ event_data: {
+ project_id: 1,
+ namespace_id: 2,
+ root_namespace_id: 3,
+ old_path: 'old_path',
+ new_path: 'new_path'
+ },
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :project, id: 1 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectTransferedEvent,
+ event_data: {
+ project_id: 1,
+ old_namespace_id: 2,
+ old_root_namespace_id: 3,
+ new_namespace_id: 4,
+ new_root_namespace_id: 5
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 3 },
+ { type: :namespace, id: 5 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Groups::GroupTransferedEvent,
+ event_data: {
+ group_id: 1,
+ old_root_namespace_id: 3,
+ new_root_namespace_id: 5
+ },
+ caches: [
+ { type: :namespace, id: 3 },
+ { type: :namespace, id: 5 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Groups::GroupPathChangedEvent,
+ event_data: {
+ group_id: 1,
+ root_namespace_id: 2,
+ old_path: 'old_path',
+ new_path: 'new_path'
+ },
+ caches: [
+ { type: :namespace, id: 2 }
+ ]
+
+ it_behaves_like 'clears caches with',
+ event_class: Groups::GroupDeletedEvent,
+ event_data: {
+ group_id: 1,
+ root_namespace_id: 3
+ },
+ caches: [
+ { type: :namespace, id: 3 }
+ ]
+
+ context 'when namespace based cache keys are duplicated' do
+ # de-dups namespace cache keys
+ it_behaves_like 'clears caches with',
+ event_class: Projects::ProjectTransferedEvent,
+ event_data: {
+ project_id: 1,
+ old_namespace_id: 2,
+ old_root_namespace_id: 5,
+ new_namespace_id: 4,
+ new_root_namespace_id: 5
+ },
+ caches: [
+ { type: :project, id: 1 },
+ { type: :namespace, id: 5 }
+ ]
+ end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index 4ddb793516f..d632ca39e44 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -452,6 +452,12 @@ RSpec.describe PostReceive do
perform
end
+ it 'updates the snippet model updated_at' do
+ expect(snippet).to receive(:touch)
+
+ perform
+ end
+
it 'updates snippet statistics' do
expect(Snippets::UpdateStatisticsService).to receive(:new).with(snippet).and_call_original
diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb
index 7f42c700ce4..30c85464452 100644
--- a/spec/workers/project_cache_worker_spec.rb
+++ b/spec/workers/project_cache_worker_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe ProjectCacheWorker do
.twice
expect(UpdateProjectStatisticsWorker).to receive(:perform_in)
- .with(lease_timeout, project.id, statistics)
+ .with(lease_timeout, lease_key, project.id, statistics)
.and_call_original
expect(Namespaces::ScheduleAggregationWorker)
diff --git a/spec/workers/projects/import_export/relation_export_worker_spec.rb b/spec/workers/projects/import_export/relation_export_worker_spec.rb
new file mode 100644
index 00000000000..236650fe55b
--- /dev/null
+++ b/spec/workers/projects/import_export/relation_export_worker_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ImportExport::RelationExportWorker, type: :worker do
+ let(:project_relation_export) { create(:project_relation_export) }
+ let(:job_args) { [project_relation_export.id] }
+
+ it_behaves_like 'an idempotent worker'
+
+ describe '#perform' do
+ subject(:worker) { described_class.new }
+
+ context 'when relation export has initial state queued' do
+ let(:project_relation_export) { create(:project_relation_export) }
+
+ it 'calls RelationExportService' do
+ expect_next_instance_of(Projects::ImportExport::RelationExportService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ worker.perform(project_relation_export.id)
+ end
+ end
+
+ context 'when relation export does not have queued state' do
+ let(:project_relation_export) { create(:project_relation_export, status_event: :start) }
+
+ it 'does not call RelationExportService' do
+ expect(Projects::ImportExport::RelationExportService).not_to receive(:new)
+
+ worker.perform(project_relation_export.id)
+ end
+ end
+ end
+end
diff --git a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
index 6007d3b34f8..2562a7bc6fe 100644
--- a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
+++ b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
@@ -6,12 +6,12 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker do
let(:worker) { described_class.new }
describe '#perform' do
- let!(:unreferenced_lfs_object1) { create(:lfs_object, oid: '1') }
- let!(:unreferenced_lfs_object2) { create(:lfs_object, oid: '2') }
+ let!(:unreferenced_lfs_object1) { create(:lfs_object, oid: '1' * 64) }
+ let!(:unreferenced_lfs_object2) { create(:lfs_object, oid: '2' * 64) }
let!(:project1) { create(:project, lfs_enabled: true) }
let!(:project2) { create(:project, lfs_enabled: true) }
- let!(:referenced_lfs_object1) { create(:lfs_object, oid: '3') }
- let!(:referenced_lfs_object2) { create(:lfs_object, oid: '4') }
+ let!(:referenced_lfs_object1) { create(:lfs_object, oid: '3' * 64) }
+ let!(:referenced_lfs_object2) { create(:lfs_object, oid: '4' * 64) }
let!(:lfs_objects_project1_1) do
create(:lfs_objects_project,
project: project1,
diff --git a/spec/workers/update_project_statistics_worker_spec.rb b/spec/workers/update_project_statistics_worker_spec.rb
index 1f840e363ea..2f356376d7c 100644
--- a/spec/workers/update_project_statistics_worker_spec.rb
+++ b/spec/workers/update_project_statistics_worker_spec.rb
@@ -3,17 +3,35 @@
require 'spec_helper'
RSpec.describe UpdateProjectStatisticsWorker do
+ include ExclusiveLeaseHelpers
+
let(:worker) { described_class.new }
let(:project) { create(:project, :repository) }
let(:statistics) { %w(repository_size) }
+ let(:lease_key) { "namespace:namespaces_root_statistics:#{project.namespace_id}" }
describe '#perform' do
- it 'updates the project statistics' do
- expect(Projects::UpdateStatisticsService).to receive(:new)
- .with(project, nil, statistics: statistics)
- .and_call_original
+ context 'when a lease could be obtained' do
+ it 'updates the project statistics' do
+ expect(Projects::UpdateStatisticsService).to receive(:new)
+ .with(project, nil, statistics: statistics)
+ .and_call_original
+
+ worker.perform(lease_key, project.id, statistics)
+ end
+ end
+
+ context 'when a lease could not be obtained' do
+ before do
+ stub_exclusive_lease_taken(lease_key, timeout: ProjectCacheWorker::LEASE_TIMEOUT)
+ end
+
+ it 'does not update the project statistics' do
+ lease_key = "namespace:namespaces_root_statistics:#{project.namespace_id}"
+ expect(Projects::UpdateStatisticsService).not_to receive(:new)
- worker.perform(project.id, statistics)
+ worker.perform(lease_key, project.id, statistics)
+ end
end
end
end
diff --git a/spec/workers/users/deactivate_dormant_users_worker_spec.rb b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
index 297301c45e2..263ca31e0a0 100644
--- a/spec/workers/users/deactivate_dormant_users_worker_spec.rb
+++ b/spec/workers/users/deactivate_dormant_users_worker_spec.rb
@@ -25,20 +25,13 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
context 'when automatic deactivation of dormant users is enabled' do
before do
stub_application_setting(deactivate_dormant_users: true)
- stub_const("#{described_class.name}::PAUSE_SECONDS", 0)
end
it 'deactivates dormant users' do
- freeze_time do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
-
- expect(worker).to receive(:sleep).twice
-
- worker.perform
+ worker.perform
- expect(User.dormant.count).to eq(0)
- expect(User.with_no_activity.count).to eq(0)
- end
+ expect(User.dormant.count).to eq(0)
+ expect(User.with_no_activity.count).to eq(0)
end
where(:user_type, :expected_state) do
@@ -78,6 +71,14 @@ RSpec.describe Users::DeactivateDormantUsersWorker do
expect(inactive_recently_created.reload.state).to eq('active')
end
+
+ it 'triggers update of highest user role for deactivated users', :clean_gitlab_redis_shared_state do
+ [dormant, inactive].each do |user|
+ expect(UpdateHighestRoleWorker).to receive(:perform_in).with(anything, user.id)
+ end
+
+ worker.perform
+ end
end
context 'when automatic deactivation of dormant users is disabled' do
diff --git a/storybook/yarn.lock b/storybook/yarn.lock
index 39beb793906..8b925a05ba1 100644
--- a/storybook/yarn.lock
+++ b/storybook/yarn.lock
@@ -9001,9 +9001,9 @@ tapable@^1.0.0, tapable@^1.1.3:
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^6.0.2:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
- integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
+ version "6.1.11"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
+ integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
diff --git a/tests.yml b/tests.yml
index 5fb0abe20b0..3b1ac26a195 100644
--- a/tests.yml
+++ b/tests.yml
@@ -19,6 +19,10 @@ mapping:
- source: ee/lib/(.+)\.rb
test: ee/spec/lib/%s_spec.rb
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/368628
+ - source: lib/gitlab/usage_data_counters/(.+)\.rb
+ test: spec/lib/gitlab/usage_data_spec.rb
+
# FOSS lib & tooling should map to respective spec
- source: (tooling/)?lib/(.+)\.rb
test: spec/%slib/%s_spec.rb
diff --git a/tooling/bin/qa/package_and_qa_check b/tooling/bin/qa/package_and_qa_check
deleted file mode 100755
index 21deb0fcd2d..00000000000
--- a/tooling/bin/qa/package_and_qa_check
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-require 'pathname'
-
-# This script checks if the package-and-qa job should trigger downstream pipelines to run the QA suite.
-#
-# It assumes the first argument is a directory of files containing diffs of changes from an MR
-# (e.g., created by tooling/bin/find_change_diffs). It exits with a success code if there are no diffs, or if the diffs
-# are suitable to run QA tests.
-#
-# The script will abort (exit code 1) if the argument is missing.
-#
-# The following condition will result in a failure code (2), indicating that package-and-qa should not run:
-#
-# - If the changes only include tests being put in quarantine
-
-abort("ERROR: Please specify the directory containing MR diffs.") if ARGV.empty?
-diffs_dir = Pathname.new(ARGV.shift).expand_path
-
-# Run package-and-qa if there are no diffs. E.g., in scheduled pipelines
-exit 0 if diffs_dir.glob('**/*').empty?
-
-files_count = 0
-specs_count = 0
-quarantine_specs_count = 0
-
-diffs_dir.glob('**/*').each do |path|
- next if path.directory?
-
- files_count += 1
- next unless path.to_s.end_with?('_spec.rb.diff')
-
- specs_count += 1
- quarantine_specs_count += 1 if path.read.match?(/^\+.*, quarantine:/)
-end
-
-# Run package-and-qa if there are no specs. E.g., when the MR changes QA framework files.
-exit 0 if specs_count == 0
-
-# Skip package-and-qa if there are only specs being put in quarantine.
-exit 2 if quarantine_specs_count == specs_count && quarantine_specs_count == files_count
-
-# Run package-and-qa under any other circumstances. E.g., if there are specs being put in quarantine but there are also
-# other changes that might need to be tested.
diff --git a/tooling/bin/qa/run_qa_check b/tooling/bin/qa/run_qa_check
new file mode 100755
index 00000000000..5b8844ec4fd
--- /dev/null
+++ b/tooling/bin/qa/run_qa_check
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'pathname'
+
+# This script checks if the code changes justify running the QA suite.
+#
+# It assumes the first argument is a directory of files containing diffs of changes from an MR
+# (e.g., created by tooling/bin/find_change_diffs). It exits with a success code if there are no diffs, or if the diffs
+# are suitable to run QA tests.
+#
+# The script will abort (exit code 1) if the argument is missing.
+#
+# The following condition will result in a failure code (2), indicating that QA tests should not run:
+#
+# - If the changes only include tests being put in quarantine
+
+abort("ERROR: Please specify the directory containing MR diffs.") if ARGV.empty?
+diffs_dir = Pathname.new(ARGV.shift).expand_path
+
+# Run QA tests if there are no diffs. E.g., in scheduled pipelines
+exit 0 if diffs_dir.glob('**/*').empty?
+
+files_count = 0
+specs_count = 0
+quarantine_specs_count = 0
+
+diffs_dir.glob('**/*').each do |path|
+ next if path.directory?
+
+ files_count += 1
+ next unless path.to_s.end_with?('_spec.rb.diff')
+
+ specs_count += 1
+ quarantine_specs_count += 1 if path.read.match?(/^\+.*,? quarantine:/)
+end
+
+# Run QA tests if there are no specs. E.g., when the MR changes QA framework files.
+exit 0 if specs_count == 0
+
+# Skip QA tests if there are only specs being put in quarantine.
+exit 2 if quarantine_specs_count == specs_count && quarantine_specs_count == files_count
+
+# Run QA tests under any other circumstances. E.g., if there are specs being put in quarantine but there are also
+# other changes that might need to be tested.
diff --git a/tooling/config/CODEOWNERS.yml b/tooling/config/CODEOWNERS.yml
index a8ae90437e2..71818b67ab1 100644
--- a/tooling/config/CODEOWNERS.yml
+++ b/tooling/config/CODEOWNERS.yml
@@ -3,7 +3,7 @@
# And paste the contents into .gitlab/CODEOWNERS
'[Authentication and Authorization]':
- '@gitlab-org/manage/authentication-and-authorization':
+ '@gitlab-org/manage/authentication-and-authorization/approvers':
allow:
keywords:
- 'password'
@@ -55,3 +55,27 @@
- '/lib/gitlab/conan_token.rb'
patterns:
- '%{keyword}'
+
+'[Compliance]':
+ '@gitlab-org/manage/compliance':
+ entries:
+ - '/ee/app/services/audit_events/build_service.rb'
+ - '/ee/spec/services/audit_events/custom_audit_event_service_spec.rb'
+ allow:
+ keywords:
+ - audit
+ patterns:
+ - '**%{keyword}**'
+ deny:
+ keywords:
+ - '*.png'
+ - '*bundler-audit*'
+ - '**/merge_requests/**'
+ - '/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/*'
+ - '/qa/**/*'
+ patterns:
+ - '%{keyword}'
diff --git a/tooling/danger/customer_success.rb b/tooling/danger/customer_success.rb
new file mode 100644
index 00000000000..43bdeadd8a4
--- /dev/null
+++ b/tooling/danger/customer_success.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Danger
+ module CustomerSuccess
+ CHANGED_SCHEMA_MESSAGE = <<~MSG
+ Notification to the Customer Success about changes to files with possible breaking downstream processes, add label `Customer Success::Impact Check`.
+
+ /label ~"Customer Success::Impact Check"
+
+ The following files require a review:
+ MSG
+
+ FILE_PATH_REGEX = %r{((ee|jh)/)?config/metrics/.+\.yml}.freeze
+ CATEGORY_CHANGED = /data_category: operational/i.freeze
+
+ def build_message
+ return unless impacted?
+
+ CHANGED_SCHEMA_MESSAGE + helper.markdown_list(impacted_files)
+ end
+
+ private
+
+ def impacted?
+ !helper.has_scoped_label_with_scope?('Customer Success') && impacted_files.any?
+ end
+
+ def impacted_files
+ @impacted_files ||=
+ metric_files.select do |file|
+ helper.changed_lines(file).any? { |change| metric_category_changed?(change) }
+ end.compact
+ end
+
+ def metric_files
+ helper.modified_files.grep(FILE_PATH_REGEX)
+ end
+
+ def metric_category_changed?(change)
+ change =~ CATEGORY_CHANGED
+ end
+ end
+ end
+end
diff --git a/tooling/danger/product_intelligence.rb b/tooling/danger/product_intelligence.rb
index 0f007e970b4..621a7b509b0 100644
--- a/tooling/danger/product_intelligence.rb
+++ b/tooling/danger/product_intelligence.rb
@@ -7,7 +7,7 @@ module Tooling
APPROVED_LABEL = 'product intelligence::approved'
REVIEW_LABEL = 'product intelligence::review pending'
CHANGED_FILES_MESSAGE = <<~MSG
- For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/growth/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
+ For the following files, a review from the [Data team and Product Intelligence team](https://gitlab.com/groups/gitlab-org/analytics-section/product-intelligence/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
Please check the ~"product intelligence" [Service Ping guide](https://docs.gitlab.com/ee/development/service_ping/) or the [Snowplow guide](https://docs.gitlab.com/ee/development/snowplow/).
For MR review guidelines, see the [Service Ping review guidelines](https://docs.gitlab.com/ee/development/service_ping/review_guidelines.html) or the [Snowplow review guidelines](https://docs.gitlab.com/ee/development/snowplow/review_guidelines.html).
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index b37b86ceecc..d8c7d617927 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -63,6 +63,7 @@ module Tooling
%r{\A((ee|jh)/)?app/views/} => [:frontend, :backend],
%r{\A((ee|jh)/)?public/} => :frontend,
%r{\A((ee|jh)/)?spec/(javascripts|frontend|frontend_integration)/} => :frontend,
+ %r{\A((ee|jh)/)?spec/contracts/consumer} => :frontend,
%r{\A((ee|jh)/)?vendor/assets/} => :frontend,
%r{\A((ee|jh)/)?scripts/frontend/} => :frontend,
%r{(\A|/)(
@@ -117,6 +118,7 @@ module Tooling
%r{\Alib/gitlab/ci/templates} => :ci_template,
%r{\A((ee|jh)/)?spec/features/} => :test,
+ %r{\A((ee|jh)/)?spec/contracts/} => :test,
%r{\A((ee|jh)/)?spec/support/shared_examples/features/} => :test,
%r{\A((ee|jh)/)?spec/support/shared_contexts/features/} => :test,
%r{\A((ee|jh)/)?spec/support/helpers/features/} => :test,
diff --git a/tooling/graphql/docs/helper.rb b/tooling/graphql/docs/helper.rb
index e4f14129f3b..a76773ed28d 100644
--- a/tooling/graphql/docs/helper.rb
+++ b/tooling/graphql/docs/helper.rb
@@ -315,14 +315,17 @@ module Tooling
def render_deprecation(object, owner, context)
buff = []
deprecation = schema_deprecation(owner, object[:name])
+ original_description = deprecation&.original_description || render_description_of(object, owner)
- buff << (deprecation&.original_description || render_description_of(object, owner)) if context == :block
+ buff << original_description if context == :block
buff << if deprecation
deprecation.markdown(context: context)
else
"**Deprecated:** #{object[:deprecation_reason]}"
end
+ buff << original_description if context == :inline && deprecation&.alpha?
+
join(context, buff)
end
diff --git a/tooling/lib/tooling/find_codeowners.rb b/tooling/lib/tooling/find_codeowners.rb
index 3b50b33d85c..6a90f86eecc 100644
--- a/tooling/lib/tooling/find_codeowners.rb
+++ b/tooling/lib/tooling/find_codeowners.rb
@@ -9,37 +9,10 @@ module Tooling
puts section
group_defintions.each do |group, list|
- matched_files = git_ls_files.each_line.select do |line|
- list[:allow].find do |pattern|
- path = "/#{line.chomp}"
+ print_entries(group, list[:entries]) if list[:entries]
+ print_expanded_entries(group, list) if list[:allow]
- path_matches?(pattern, path) &&
- list[:deny].none? { |pattern| path_matches?(pattern, path) }
- end
- end
-
- consolidated = consolidate_paths(matched_files)
- consolidated_again = consolidate_paths(consolidated)
-
- # Consider the directory structure is a tree structure:
- # https://en.wikipedia.org/wiki/Tree_(data_structure)
- # After we consolidated the leaf entries, it could be possible that
- # we can consolidate further for the new leaves. Repeat this
- # process until we see no improvements.
- while consolidated_again.size < consolidated.size
- consolidated = consolidated_again
- consolidated_again = consolidate_paths(consolidated)
- end
-
- consolidated.each do |line|
- path = line.chomp
-
- if File.directory?(path)
- puts "/#{path}/ #{group}"
- else
- puts "/#{path} #{group}"
- end
- end
+ puts
end
end
end
@@ -50,10 +23,20 @@ module Tooling
result.each do |section, group_defintions|
group_defintions.each do |group, definitions|
definitions.transform_values! do |rules|
- rules[:keywords].flat_map do |keyword|
- rules[:patterns].map do |pattern|
- pattern % { keyword: keyword }
+ case rules
+ when Hash
+ case rules[:keywords]
+ when Array
+ rules[:keywords].flat_map do |keyword|
+ rules[:patterns].map do |pattern|
+ pattern % { keyword: keyword }
+ end
+ end
+ else
+ rules[:patterns]
end
+ when Array
+ rules
end
end
end
@@ -118,6 +101,49 @@ module Tooling
private
+ def print_entries(group, entries)
+ entries.each do |entry|
+ puts "#{entry} #{group}"
+ end
+ end
+
+ def print_expanded_entries(group, list)
+ matched_files = git_ls_files.each_line.select do |line|
+ list[:allow].find do |pattern|
+ path = "/#{line.chomp}"
+
+ path_matches?(pattern, path) &&
+ (
+ list[:deny].nil? ||
+ list[:deny].none? { |pattern| path_matches?(pattern, path) }
+ )
+ end
+ end
+
+ consolidated = consolidate_paths(matched_files)
+ consolidated_again = consolidate_paths(consolidated)
+
+ # Consider the directory structure is a tree structure:
+ # https://en.wikipedia.org/wiki/Tree_(data_structure)
+ # After we consolidated the leaf entries, it could be possible that
+ # we can consolidate further for the new leaves. Repeat this
+ # process until we see no improvements.
+ while consolidated_again.size < consolidated.size
+ consolidated = consolidated_again
+ consolidated_again = consolidate_paths(consolidated)
+ end
+
+ consolidated.each do |line|
+ path = line.chomp
+
+ if File.directory?(path)
+ puts "/#{path}/ #{group}"
+ else
+ puts "/#{path} #{group}"
+ end
+ end
+ end
+
def find_dir_maxdepth_1(dir)
`find #{dir} -maxdepth 1`
end
diff --git a/tooling/lib/tooling/helm3_client.rb b/tooling/lib/tooling/helm3_client.rb
index 6e4a35e82f1..82ebe3f51dc 100644
--- a/tooling/lib/tooling/helm3_client.rb
+++ b/tooling/lib/tooling/helm3_client.rb
@@ -84,7 +84,7 @@ module Tooling
# method - The Octokit method to use for getting the data.
# args - Arguments to pass to the `helm list` command.
def each_releases_page(args, &block)
- return to_enum(__method__, args) unless block_given?
+ return to_enum(__method__, args) unless block
page = 0
final_args = args.dup
@@ -100,7 +100,7 @@ module Tooling
#
# args - Any arguments to pass to the `helm list` command.
def each_release(args, &block)
- return to_enum(__method__, args) unless block_given?
+ return to_enum(__method__, args) unless block
each_releases_page(args) do |page|
page.releases.each do |release|
diff --git a/tooling/lib/tooling/test_map_packer.rb b/tooling/lib/tooling/test_map_packer.rb
index d74edb9500f..151ce88111f 100644
--- a/tooling/lib/tooling/test_map_packer.rb
+++ b/tooling/lib/tooling/test_map_packer.rb
@@ -44,7 +44,7 @@ module Tooling
end
def traverse(tree, segments = [], &block)
- return to_enum(__method__, tree, segments) unless block_given?
+ return to_enum(__method__, tree, segments) unless block
if tree == MARKER
return yield segments.join(SEPARATOR)
diff --git a/tooling/overcommit/Gemfile b/tooling/overcommit/Gemfile
deleted file mode 100644
index 26dad738bab..00000000000
--- a/tooling/overcommit/Gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-# Make sure to run `make` (in this directory) when you update this file.
-source 'https://rubygems.org'
-
-gem 'overcommit'
-gem 'gitlab-styles', '~> 5.4.0', require: false
-gem 'haml_lint', '~> 0.34.0', require: false
diff --git a/tooling/overcommit/Gemfile.lock b/tooling/overcommit/Gemfile.lock
deleted file mode 100644
index a4b6f62a979..00000000000
--- a/tooling/overcommit/Gemfile.lock
+++ /dev/null
@@ -1,83 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- activesupport (6.0.3.4)
- concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 0.7, < 2)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- zeitwerk (~> 2.2, >= 2.2.2)
- ast (2.4.1)
- childprocess (3.0.0)
- concurrent-ruby (1.1.7)
- gitlab-styles (5.4.0)
- rubocop (~> 0.89.1)
- rubocop-gitlab-security (~> 0.1.0)
- rubocop-performance (~> 1.8.1)
- rubocop-rails (~> 2.8)
- rubocop-rspec (~> 1.44)
- haml (5.1.2)
- temple (>= 0.8.0)
- tilt
- haml_lint (0.34.0)
- haml (>= 4.0, < 5.2)
- rainbow
- rubocop (>= 0.50.0)
- sysexits (~> 1.1)
- i18n (1.8.5)
- concurrent-ruby (~> 1.0)
- iniparse (1.5.0)
- minitest (5.14.2)
- overcommit (0.53.0)
- childprocess (>= 0.6.3, < 4)
- iniparse (~> 1.4)
- parallel (1.19.2)
- parser (2.7.2.0)
- ast (~> 2.4.1)
- rack (2.2.3.1)
- rainbow (3.0.0)
- regexp_parser (1.8.2)
- rexml (3.2.4)
- rubocop (0.89.1)
- parallel (~> 1.10)
- parser (>= 2.7.1.1)
- rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.7)
- rexml
- rubocop-ast (>= 0.3.0, < 1.0)
- ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (0.8.0)
- parser (>= 2.7.1.5)
- rubocop-gitlab-security (0.1.1)
- rubocop (>= 0.51)
- rubocop-performance (1.8.1)
- rubocop (>= 0.87.0)
- rubocop-ast (>= 0.4.0)
- rubocop-rails (2.8.1)
- activesupport (>= 4.2.0)
- rack (>= 1.1)
- rubocop (>= 0.87.0)
- rubocop-rspec (1.44.1)
- rubocop (~> 0.87)
- rubocop-ast (>= 0.7.1)
- ruby-progressbar (1.10.1)
- sysexits (1.2.0)
- temple (0.8.2)
- thread_safe (0.3.6)
- tilt (2.0.10)
- tzinfo (1.2.8)
- thread_safe (~> 0.1)
- unicode-display_width (1.7.0)
- zeitwerk (2.4.1)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- gitlab-styles (~> 5.4.0)
- haml_lint (~> 0.34.0)
- overcommit
-
-BUNDLED WITH
- 2.1.4
diff --git a/tooling/overcommit/Makefile b/tooling/overcommit/Makefile
deleted file mode 100644
index 7da3c7c0569..00000000000
--- a/tooling/overcommit/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-.PHONY: install
-
-install:
- if [ -e ../../.overcommit.yml ]; then cp -f ../../.overcommit.yml ../../.overcommit.yml.backup; fi
- cp ../../.overcommit.yml.example ../../.overcommit.yml
- bundle install
- cd ../../ && overcommit -i
diff --git a/tooling/quality/test_level.rb b/tooling/quality/test_level.rb
index 82da0121e31..d630ffd5432 100644
--- a/tooling/quality/test_level.rb
+++ b/tooling/quality/test_level.rb
@@ -24,7 +24,6 @@ module Quality
elastic
elastic_integration
experiments
- events
factories
finders
frontend
diff --git a/vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml b/vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml
index a2517953178..ed5e27f5a8c 100644
--- a/vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml
+++ b/vendor/gems/devise-pbkdf2-encryptable/.gitlab-ci.yml
@@ -13,6 +13,8 @@ workflow:
- 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
diff --git a/vendor/gems/error_tracking_open_api/README.md b/vendor/gems/error_tracking_open_api/README.md
index 18757e2e183..1d7c3df8526 100644
--- a/vendor/gems/error_tracking_open_api/README.md
+++ b/vendor/gems/error_tracking_open_api/README.md
@@ -1,4 +1,4 @@
-# Generated by `rake gems:error_tracking_open_api:generate` on 2022-07-14
+# Generated by `rake gems:error_tracking_open_api:generate` on 2022-07-18
See https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/rake_tasks.md#update-openapi-client-for-error-tracking-feature
@@ -60,6 +60,14 @@ Please follow the [installation](#installation) procedure and then run the follo
# Load the gem
require 'error_tracking_open_api'
+# Setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
+
api_instance = ErrorTrackingOpenAPI::ErrorsApi.new
project_id = 56 # Integer | ID of the project where the error was created
fingerprint = 56 # Integer | ID of the error that needs to be updated deleted
@@ -99,5 +107,11 @@ Class | Method | HTTP request | Description
## Documentation for Authorization
- All endpoints do not require authorization.
+
+### internalToken
+
+
+- **Type**: API key
+- **API key parameter name**: Gitlab-Error-Tracking-Token
+- **Location**: HTTP header
diff --git a/vendor/gems/error_tracking_open_api/docs/ErrorsApi.md b/vendor/gems/error_tracking_open_api/docs/ErrorsApi.md
index 79d0c2a46de..b9b7d2f6421 100644
--- a/vendor/gems/error_tracking_open_api/docs/ErrorsApi.md
+++ b/vendor/gems/error_tracking_open_api/docs/ErrorsApi.md
@@ -21,6 +21,13 @@ Get information about the error
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::ErrorsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -66,7 +73,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
@@ -85,6 +92,13 @@ List of errors
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::ErrorsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -140,7 +154,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
@@ -159,6 +173,13 @@ Get information about the events related to the error
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::ErrorsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -212,7 +233,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
@@ -231,6 +252,13 @@ Update the status of the error
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::ErrorsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -278,7 +306,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
diff --git a/vendor/gems/error_tracking_open_api/docs/EventsApi.md b/vendor/gems/error_tracking_open_api/docs/EventsApi.md
index 3b4586be611..a9882fac515 100644
--- a/vendor/gems/error_tracking_open_api/docs/EventsApi.md
+++ b/vendor/gems/error_tracking_open_api/docs/EventsApi.md
@@ -20,6 +20,13 @@ Get information about the events related to the error
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::EventsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -73,7 +80,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
@@ -92,6 +99,13 @@ Ingestion endpoint for error events sent from client SDKs
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::EventsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -135,7 +149,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
@@ -154,6 +168,13 @@ Ingestion endpoint for error events sent from client SDKs
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::EventsApi.new
project_id = 56 # Integer | ID of the project where the error was created
@@ -197,7 +218,7 @@ end
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
diff --git a/vendor/gems/error_tracking_open_api/docs/ProjectsApi.md b/vendor/gems/error_tracking_open_api/docs/ProjectsApi.md
index e6397b23f8f..adcb4a84ad9 100644
--- a/vendor/gems/error_tracking_open_api/docs/ProjectsApi.md
+++ b/vendor/gems/error_tracking_open_api/docs/ProjectsApi.md
@@ -18,6 +18,13 @@ Deletes all project related data. Mostly for testing purposes and later for prod
```ruby
require 'time'
require 'error_tracking_open_api'
+# setup authorization
+ErrorTrackingOpenAPI.configure do |config|
+ # Configure API key authorization: internalToken
+ config.api_key['internalToken'] = 'YOUR API KEY'
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
+ # config.api_key_prefix['internalToken'] = 'Bearer'
+end
api_instance = ErrorTrackingOpenAPI::ProjectsApi.new
id = 56 # Integer | ID of the project
@@ -60,7 +67,7 @@ nil (empty response body)
### Authorization
-No authorization required
+[internalToken](../README.md#internalToken)
### HTTP request headers
diff --git a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/errors_api.rb b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/errors_api.rb
index f21d3c51baf..992d37abb6c 100644
--- a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/errors_api.rb
+++ b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/errors_api.rb
@@ -67,7 +67,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'Error'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"ErrorsApi.get_error",
@@ -159,7 +159,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'Array<Error>'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"ErrorsApi.list_errors",
@@ -247,7 +247,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'Array<ErrorEvent>'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"ErrorsApi.list_events",
@@ -325,7 +325,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'Error'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"ErrorsApi.update_error",
diff --git a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/events_api.rb b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/events_api.rb
index 49e2af7bb64..48e9375b266 100644
--- a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/events_api.rb
+++ b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/events_api.rb
@@ -88,7 +88,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'Array<ErrorEvent>'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"EventsApi.list_events",
@@ -149,7 +149,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'ErrorEvent'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"EventsApi.projects_api_project_id_envelope_post",
@@ -210,7 +210,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type] || 'ErrorEvent'
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"EventsApi.projects_api_project_id_store_post",
diff --git a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/projects_api.rb b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/projects_api.rb
index 15ebe6efc35..781b1a17512 100644
--- a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/projects_api.rb
+++ b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api/projects_api.rb
@@ -59,7 +59,7 @@ module ErrorTrackingOpenAPI
return_type = opts[:debug_return_type]
# auth_names
- auth_names = opts[:debug_auth_names] || []
+ auth_names = opts[:debug_auth_names] || ['internalToken']
new_options = opts.merge(
:operation => :"ProjectsApi.delete_project",
diff --git a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api_client.rb b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api_client.rb
index e2dedf57925..02118a56a3a 100644
--- a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api_client.rb
+++ b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/api_client.rb
@@ -95,6 +95,7 @@ module ErrorTrackingOpenAPI
form_params = opts[:form_params] || {}
follow_location = opts[:follow_location] || true
+ update_params_for_auth! header_params, query_params, opts[:auth_names]
# set ssl_verifyhosts option based on @config.verify_ssl_host (true/false)
_verify_ssl_host = @config.verify_ssl_host ? 2 : 0
diff --git a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/configuration.rb b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/configuration.rb
index c27c0aa3bb9..6855082c17b 100644
--- a/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/configuration.rb
+++ b/vendor/gems/error_tracking_open_api/lib/error_tracking_open_api/configuration.rb
@@ -216,6 +216,13 @@ module ErrorTrackingOpenAPI
# Returns Auth Settings hash for api client.
def auth_settings
{
+ 'internalToken' =>
+ {
+ type: 'api_key',
+ in: 'header',
+ key: 'Gitlab-Error-Tracking-Token',
+ value: api_key_with_prefix('internalToken')
+ },
}
end
diff --git a/vendor/gems/ipynbdiff/.gitlab-ci.yml b/vendor/gems/ipynbdiff/.gitlab-ci.yml
index 7b0c9df6cd9..bf8f8b15c26 100644
--- a/vendor/gems/ipynbdiff/.gitlab-ci.yml
+++ b/vendor/gems/ipynbdiff/.gitlab-ci.yml
@@ -19,6 +19,8 @@ workflow:
- 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
diff --git a/vendor/gems/mail-smtp_pool/.gitlab-ci.yml b/vendor/gems/mail-smtp_pool/.gitlab-ci.yml
index 4c9e62f7d11..dee865f3cd6 100644
--- a/vendor/gems/mail-smtp_pool/.gitlab-ci.yml
+++ b/vendor/gems/mail-smtp_pool/.gitlab-ci.yml
@@ -13,14 +13,12 @@ workflow:
- 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.6:
- image: "ruby:2.6"
- extends: .rspec
-
rspec-2.7:
image: "ruby:2.7"
extends: .rspec
diff --git a/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml b/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
new file mode 100644
index 00000000000..575fec39767
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+
+.rspec:
+ cache:
+ key: omniauth-azure-oauth2
+ paths:
+ - vendor/gems/omniauth-azure-oauth2/vendor/ruby
+ before_script:
+ - cd vendor/gems/omniauth-azure-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-azure-oauth2/CHANGELOG.md b/vendor/gems/omniauth-azure-oauth2/CHANGELOG.md
new file mode 100644
index 00000000000..ca274303b18
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/CHANGELOG.md
@@ -0,0 +1,31 @@
+# Version 0.0.9
+* Expand JWT dep. Thanks @ronaldsalas
+
+# Version 0.0.9
+* Added support for dynamic tenant urls. Thanks @marcus-fellinger-esc
+
+# Version 0.0.8
+* Upgrade to omniauth-oauth2 1.4.0 and fix callback url issue
+* Allow prompt parameter, thanks @hilu
+* Add tenant id to info
+* Updated base url
+
+# Version 0.0.6
+* Use 'name' from Azure for name, and 'unique_name' for nickname per Auth Hash spec. Thanks @jayme-github
+
+# Version 0.0.5
+* loosen jwt requirement
+
+# Version 0.0.5
+* loosen jwt requirement
+
+# VERSION 0.0.4
+* fix for JWT scoping, thanks @tobsher
+
+# VERSION 0.0.3
+* added common endpoint and removed mandatory requirement for tenant-id
+* upgraded jwt
+
+# VERSION 0.0.1
+
+* Initial build \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/Gemfile b/vendor/gems/omniauth-azure-oauth2/Gemfile
new file mode 100644
index 00000000000..ef2f8b4147f
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Gemfile
@@ -0,0 +1,8 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in omniauth-azure-oauth2.gemspec
+gemspec
+
+group :example do
+ gem 'sinatra'
+end \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/Gemfile.lock b/vendor/gems/omniauth-azure-oauth2/Gemfile.lock
new file mode 100644
index 00000000000..0bd5d401175
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Gemfile.lock
@@ -0,0 +1,73 @@
+PATH
+ remote: .
+ specs:
+ omniauth-azure-oauth2 (0.0.10)
+ jwt (>= 1.0, < 3.0)
+ omniauth (~> 1.0, < 3)
+ omniauth-oauth2 (~> 1.4)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ 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)
+ mustermann (2.0.2)
+ ruby2_keywords (~> 0.0.1)
+ oauth2 (2.0.6)
+ 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.1)
+ omniauth (1.9.1)
+ hashie (>= 3.4.6)
+ rack (>= 1.6.2, < 3)
+ omniauth-oauth2 (1.7.3)
+ oauth2 (>= 1.4, < 3)
+ omniauth (>= 1.9, < 3)
+ rack (2.2.4)
+ rack-protection (2.2.2)
+ rack
+ rake (13.0.6)
+ rash_alt (0.4.12)
+ hashie (>= 3.4)
+ 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)
+ ruby2_keywords (0.0.5)
+ sinatra (2.2.2)
+ mustermann (~> 2.0)
+ rack (~> 2.2)
+ rack-protection (= 2.2.2)
+ tilt (~> 2.0)
+ tilt (2.0.11)
+ version_gem (1.1.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ omniauth-azure-oauth2!
+ rake
+ rspec (>= 2.14.0)
+ sinatra
+
+BUNDLED WITH
+ 2.3.20
diff --git a/vendor/gems/omniauth-azure-oauth2/LICENSE b/vendor/gems/omniauth-azure-oauth2/LICENSE
new file mode 100644
index 00000000000..57ecd3eabb9
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014 Deltek
+
+MIT License
+
+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/omniauth-azure-oauth2/README.md b/vendor/gems/omniauth-azure-oauth2/README.md
new file mode 100644
index 00000000000..a28e9ffdfd2
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/README.md
@@ -0,0 +1,161 @@
+# OmniAuth Windows Azure Active Directory Strategy
+
+This is fork of [omniauth-azure-oauth2](https://github.com/marknadig/omniauth-azure-oauth2) to support:
+
+1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default
+ and defaults to POST. GitLab already has patched v1 to use POST,
+ but other dependencies need to be updated:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/30073.
+2. We may deprecate this library entirely in the future:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/366212
+
+[![Build Status](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2.svg?branch=master)](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2)
+
+This gem provides a simple way to authenticate to Windows Azure Active Directory (WAAD) over OAuth2 using OmniAuth.
+
+One of the unique challenges of WAAD OAuth is that WAAD is multi tenant. Any given tenant can have multiple active
+directories. The CLIENT-ID, REPLY-URL and keys will be unique to the tenant/AD/application combination. This gem simply
+provides hooks for determining those unique values for each call.
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+```ruby
+gem 'omniauth-azure-oauth2'
+```
+
+## Usage
+
+First, you will need to add your site as an application in WAAD.:
+[Adding, Updating, and Removing an Application](http://msdn.microsoft.com/en-us/library/azure/dn132599.aspx)
+
+Summary:
+Select your Active Directory in https://manage.windowsazure.com/<tenantid> of type 'Web Application'. Name, sign-on url,
+logo are not important. You will need the CLIENT-ID from the application configuration and you will need to generate
+an expiring key (aka 'client secret'). REPLY URL is the oauth redirect uri which will be the omniauth callback path
+https://example.com/users/auth/azure_oauth2/callback. The APP ID UI just needs to be unique to that tenant and identify
+your site and isn't needed to configure the gem.
+Permissions need Delegated Permissions to at least have "Enable sign-on and read user's profiles".
+
+Note: Seems like the terminology is still fluid, so follow the MS guidance (buwahaha) to set this up.
+
+The TenantInfo information can be a hash or class. It must provide client_id and client_secret.
+Optionally a domain_hint and tenant_id. For a simple single-tenant app, this could be:
+
+```ruby
+use OmniAuth::Builder do
+ provider :azure_oauth2,
+ {
+ client_id: ENV['AZURE_CLIENT_ID'],
+ client_secret: ENV['AZURE_CLIENT_SECRET'],
+ tenant_id: ENV['AZURE_TENANT_ID']
+ }
+end
+```
+
+Or the alternative format for use with [devise](https://github.com/plataformatec/devise):
+
+```ruby
+config.omniauth :azure_oauth2, client_id: ENV['AZURE_CLIENT_ID'],
+ client_secret: ENV['AZURE_CLIENT_SECRET'], tenant_id: ENV['AZURE_TENANT_ID']
+```
+
+For multi-tenant apps where you don't know the tenant_id in advance, simply leave out the tenant_id to use the
+[common endpoint](http://msdn.microsoft.com/en-us/library/azure/dn645542.aspx).
+
+```ruby
+use OmniAuth::Builder do
+ provider :azure_oauth2,
+ {
+ client_id: ENV['AZURE_CLIENT_ID'],
+ client_secret: ENV['AZURE_CLIENT_SECRET']
+ }
+end
+```
+
+For dynamic tenant assignment, pass a class that supports those same attributes and accepts the strategy as a parameter
+
+```ruby
+class YouTenantProvider
+ def initialize(strategy)
+ @strategy = strategy
+ end
+
+ def client_id
+ tenant.azure_client_id
+ end
+
+ def client_secret
+ tenant.azure_client_secret
+ end
+
+ def tenant_id
+ tenant.azure_tanant_id
+ end
+
+ def domain_hint
+ tenant.azure_domain_hint
+ end
+
+ private
+
+ def tenant
+ # whatever strategy you want to figure out the right tenant from params/session
+ @tenant ||= Customer.find(@strategy.session[:customer_id])
+ end
+end
+
+use OmniAuth::Builder do
+ provider :azure_oauth2, YourTenantProvider
+end
+```
+
+The base_azure_url can be overridden in the provider configuration for different locales; e.g. `base_azure_url: "https://login.microsoftonline.de"`
+
+
+## Auth Hash Schema
+
+The following information is provided back to you for this provider:
+
+```ruby
+{
+ uid: '12345',
+ info: {
+ name: 'some one',
+ first_name: 'some',
+ last_name: 'one',
+ email: 'someone@example.com'
+ },
+ credentials: {
+ token: 'thetoken',
+ refresh_token: 'refresh'
+ },
+ extra: { raw_info: raw_api_response }
+}
+```
+## notes
+
+When you make a request to WAAD you must specify a resource. The gem currently assumes this is the AD identified as '00000002-0000-0000-c000-000000000000'.
+This can be passed in as part of the config. It currently isn't designed to be dynamic.
+
+```ruby
+use OmniAuth::Builder do
+ provider :azure_oauth2, TenantInfo, resource: 'myresource'
+end
+```
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Make your changes, add tests, run tests (`rake`)
+4. Commit your changes and tests (`git commit -am 'Added some feature'`)
+5. Push to the branch (`git push origin my-new-feature`)
+6. Create new Pull Request
+
+
+## Misc
+Run tests `bundle exec rake`
+Push to rubygems `bundle exec rake release`.
+
diff --git a/vendor/gems/omniauth-azure-oauth2/Rakefile b/vendor/gems/omniauth-azure-oauth2/Rakefile
new file mode 100644
index 00000000000..965431eb7c9
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/Rakefile
@@ -0,0 +1,6 @@
+require File.join('bundler', 'gem_tasks')
+require File.join('rspec', 'core', 'rake_task')
+
+RSpec::Core::RakeTask.new(:spec)
+
+task :default => :spec \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb b/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb
new file mode 100644
index 00000000000..3db9e5fe435
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/examples/sinatra.rb
@@ -0,0 +1,31 @@
+$:.push File.dirname(__FILE__) + '/../lib'
+
+require 'omniauth-azure-oauth2'
+require 'sinatra'
+
+class MyAzureProvider
+ def self.client_id
+ ENV['AZURE_CLIENT_ID']
+ end
+
+ def self.client_secret
+ ENV['AZURE_CLIENT_SECRET']
+ end
+
+ def self.tenant_id
+ ENV['AZURE_TENANT_ID']
+ end
+
+end
+
+use Rack::Session::Cookie
+use OmniAuth::Strategies::Azure, MyAzureProvider
+
+get '/' do
+ "<a href='/auth/azure_oauth2'>Log in with Azure</a>"
+end
+
+get '/auth/azure_oauth2/callback' do
+ content_type 'text/plain'
+ request.env['omniauth.auth'].inspect
+end \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb
new file mode 100644
index 00000000000..121c26842aa
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth-azure-oauth2.rb
@@ -0,0 +1 @@
+require File.join('omniauth', 'azure_oauth2') \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb
new file mode 100644
index 00000000000..69651ede9e7
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2.rb
@@ -0,0 +1 @@
+require File.join('omniauth', 'strategies', 'azure_oauth2') \ No newline at end of file
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb
new file mode 100644
index 00000000000..cfaa9ddd458
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/azure_oauth2/version.rb
@@ -0,0 +1,5 @@
+module OmniAuth
+ module AzureOauth2
+ VERSION = "0.0.10"
+ end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb
new file mode 100644
index 00000000000..f18babc0619
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/lib/omniauth/strategies/azure_oauth2.rb
@@ -0,0 +1,73 @@
+require 'omniauth/strategies/oauth2'
+require 'jwt'
+
+module OmniAuth
+ module Strategies
+ class AzureOauth2 < OmniAuth::Strategies::OAuth2
+ BASE_AZURE_URL = 'https://login.microsoftonline.com'
+
+ option :name, 'azure_oauth2'
+
+ option :tenant_provider, nil
+
+ # AD resource identifier
+ option :resource, '00000002-0000-0000-c000-000000000000'
+
+ # tenant_provider must return client_id, client_secret and optionally tenant_id and base_azure_url
+ args [:tenant_provider]
+
+ def client
+ if options.tenant_provider
+ provider = options.tenant_provider.new(self)
+ else
+ provider = options # if pass has to config, get mapped right on to options
+ end
+
+ options.client_id = provider.client_id
+ options.client_secret = provider.client_secret
+ options.tenant_id =
+ provider.respond_to?(:tenant_id) ? provider.tenant_id : 'common'
+ options.base_azure_url =
+ provider.respond_to?(:base_azure_url) ? provider.base_azure_url : BASE_AZURE_URL
+
+ options.authorize_params = provider.authorize_params if provider.respond_to?(:authorize_params)
+ options.authorize_params.domain_hint = provider.domain_hint if provider.respond_to?(:domain_hint) && provider.domain_hint
+ options.authorize_params.prompt = request.params['prompt'] if request.params['prompt']
+ options.client_options.authorize_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/authorize"
+ options.client_options.token_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/token"
+ super
+ end
+
+ uid {
+ raw_info['sub']
+ }
+
+ info do
+ {
+ name: raw_info['name'],
+ nickname: raw_info['unique_name'],
+ first_name: raw_info['given_name'],
+ last_name: raw_info['family_name'],
+ email: raw_info['email'] || raw_info['upn'],
+ oid: raw_info['oid'],
+ tid: raw_info['tid']
+ }
+ end
+
+ def token_params
+ azure_resource = request.env['omniauth.params'] && request.env['omniauth.params']['azure_resource']
+ super.merge(resource: azure_resource || options.resource)
+ end
+
+ def callback_url
+ full_host + script_name + callback_path
+ end
+
+ def raw_info
+ # it's all here in JWT http://msdn.microsoft.com/en-us/library/azure/dn195587.aspx
+ @raw_info ||= ::JWT.decode(access_token.token, nil, false).first
+ end
+
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec b/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec
new file mode 100644
index 00000000000..6e1bc583881
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/omniauth-azure-oauth2.gemspec
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path(File.join('..', 'lib', 'omniauth', 'azure_oauth2', 'version'), __FILE__)
+
+Gem::Specification.new do |gem|
+ gem.authors = ["Mark Nadig"]
+ gem.email = ["mark@nadigs.net"]
+ gem.description = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth}
+ gem.summary = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth}
+ gem.homepage = "https://github.com/KonaTeam/omniauth-azure-oauth2"
+
+ gem.files = Dir.glob("lib/**/*.*")
+ gem.test_files = Dir.glob("spec/**/**/*.*")
+ gem.name = "omniauth-azure-oauth2"
+ gem.require_paths = ["lib"]
+ gem.version = OmniAuth::AzureOauth2::VERSION
+ gem.license = "MIT"
+
+ gem.add_runtime_dependency 'omniauth', '~> 1.0', '< 3'
+ gem.add_dependency 'jwt', ['>= 1.0', '< 3.0']
+
+ gem.add_runtime_dependency 'omniauth-oauth2', '~> 1.4'
+
+ gem.add_development_dependency 'rspec', '>= 2.14.0'
+ gem.add_development_dependency 'rake'
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb b/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb
new file mode 100644
index 00000000000..d171d88ac6c
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/spec/omniauth/strategies/azure_oauth2_spec.rb
@@ -0,0 +1,332 @@
+require 'spec_helper'
+require 'omniauth-azure-oauth2'
+
+module OmniAuth
+ module Strategies
+ module JWT; end
+ end
+end
+
+describe OmniAuth::Strategies::AzureOauth2 do
+ let(:request) { double('Request', :params => {}, :cookies => {}, :env => {}) }
+ let(:app) {
+ lambda do
+ [200, {}, ["Hello."]]
+ end
+ }
+
+ before do
+ OmniAuth.config.test_mode = true
+ end
+
+ after do
+ OmniAuth.config.test_mode = false
+ end
+
+ describe 'static configuration' do
+ let(:options) { @options || {} }
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant'}.merge(options))
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ allow(subject).to receive(:request) { request }
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize')
+ end
+
+ it 'has correct authorize params' do
+ allow(subject).to receive(:request) { request }
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to be_nil
+ end
+
+ it 'has correct token url' do
+ allow(subject).to receive(:request) { request }
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token')
+ end
+
+ describe "overrides" do
+ it 'should override domain_hint' do
+ @options = {domain_hint: 'hint'}
+ allow(subject).to receive(:request) { request }
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to eql('hint')
+ end
+ end
+ end
+
+ end
+
+ describe 'static configuration - german' do
+ let(:options) { @options || {} }
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant', base_azure_url: 'https://login.microsoftonline.de'}.merge(options))
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ allow(subject).to receive(:request) { request }
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize')
+ end
+
+ it 'has correct authorize params' do
+ allow(subject).to receive(:request) { request }
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to be_nil
+ end
+
+ it 'has correct token url' do
+ allow(subject).to receive(:request) { request }
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token')
+ end
+
+ it 'has correct token params' do
+ allow(subject).to receive(:request) { request }
+ subject.client
+ expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+ end
+
+ describe "overrides" do
+ it 'should override domain_hint' do
+ @options = {domain_hint: 'hint'}
+ allow(subject).to receive(:request) { request }
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to eql('hint')
+ end
+ end
+ end
+ end
+
+ describe 'static common configuration' do
+ let(:options) { @options || {} }
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'}.merge(options))
+ end
+
+ before do
+ allow(subject).to receive(:request) { request }
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize')
+ end
+
+ it 'has correct token url' do
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token')
+ end
+ end
+ end
+
+ describe 'dynamic configuration' do
+ let(:provider_klass) {
+ Class.new {
+ def initialize(strategy)
+ end
+
+ def client_id
+ 'id'
+ end
+
+ def client_secret
+ 'secret'
+ end
+
+ def tenant_id
+ 'tenant'
+ end
+
+ def authorize_params
+ { custom_option: 'value' }
+ end
+ }
+ }
+
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+ end
+
+ before do
+ allow(subject).to receive(:request) { request }
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize')
+ end
+
+ it 'has correct authorize params' do
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to be_nil
+ expect(subject.authorize_params[:custom_option]).to eql('value')
+ end
+
+ it 'has correct token url' do
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token')
+ end
+
+ it 'has correct token params' do
+ subject.client
+ expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+ end
+
+ # todo: how to get this working?
+ # describe "overrides" do
+ # it 'should override domain_hint' do
+ # provider_klass.domain_hint = 'hint'
+ # subject.client
+ # expect(subject.authorize_params[:domain_hint]).to eql('hint')
+ # end
+ # end
+ end
+
+ end
+
+ describe 'dynamic configuration - german' do
+ let(:provider_klass) {
+ Class.new {
+ def initialize(strategy)
+ end
+
+ def client_id
+ 'id'
+ end
+
+ def client_secret
+ 'secret'
+ end
+
+ def tenant_id
+ 'tenant'
+ end
+
+ def base_azure_url
+ 'https://login.microsoftonline.de'
+ end
+ }
+ }
+
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+ end
+
+ before do
+ allow(subject).to receive(:request) { request }
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize')
+ end
+
+ it 'has correct authorize params' do
+ subject.client
+ expect(subject.authorize_params[:domain_hint]).to be_nil
+ end
+
+ it 'has correct token url' do
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token')
+ end
+
+ it 'has correct token params' do
+ subject.client
+ expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000')
+ end
+
+ # todo: how to get this working?
+ # describe "overrides" do
+ # it 'should override domain_hint' do
+ # provider_klass.domain_hint = 'hint'
+ # subject.client
+ # expect(subject.authorize_params[:domain_hint]).to eql('hint')
+ # end
+ # end
+ end
+
+ end
+
+ describe 'dynamic common configuration' do
+ let(:provider_klass) {
+ Class.new {
+ def initialize(strategy)
+ end
+
+ def client_id
+ 'id'
+ end
+
+ def client_secret
+ 'secret'
+ end
+ }
+ }
+
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, provider_klass)
+ end
+
+ before do
+ allow(subject).to receive(:request) { request }
+ end
+
+ describe '#client' do
+ it 'has correct authorize url' do
+ expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize')
+ end
+
+ it 'has correct token url' do
+ expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token')
+ end
+ end
+ end
+
+ describe "raw_info" do
+ subject do
+ OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'})
+ end
+
+ let(:token) do
+ JWT.encode({"some" => "payload"}, "secret")
+ end
+
+ let(:access_token) do
+ double(:token => token)
+ end
+
+ before do
+ allow(subject).to receive(:access_token) { access_token }
+ allow(subject).to receive(:request) { request }
+ end
+
+ it "does not clash if JWT strategy is used" do
+ expect do
+ subject.info
+ end.to_not raise_error
+ end
+ end
+
+ describe 'token_params' do
+ let(:strategy) { OmniAuth::Strategies::AzureOauth2.new(app, client_id: 'id', client_secret: 'secret') }
+ let(:request) { double('Request', env: env) }
+ let(:env) { {} }
+
+ subject { strategy.token_params }
+
+ before { allow(strategy).to receive(:request).and_return request }
+
+ it { is_expected.to be_a OmniAuth::Strategy::Options }
+ it 'has default resource' do
+ expect(subject.resource).to eq '00000002-0000-0000-c000-000000000000'
+ end
+
+ context 'when custom crm url' do
+ let(:crm_url) { 'https://mydomain.crm.dynamics.com/' }
+ let(:env) { { 'omniauth.params' => { 'azure_resource' => crm_url } } }
+
+ it 'has resource from url params' do
+ expect(subject.resource).to eq crm_url
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb b/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb
new file mode 100644
index 00000000000..9d0890421a2
--- /dev/null
+++ b/vendor/gems/omniauth-azure-oauth2/spec/spec_helper.rb
@@ -0,0 +1,2 @@
+require File.join('bundler', 'setup')
+require 'rspec' \ No newline at end of file
diff --git a/vendor/gems/omniauth-cas3/.gitlab-ci.yml b/vendor/gems/omniauth-cas3/.gitlab-ci.yml
new file mode 100644
index 00000000000..e728d704d21
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+workflow:
+ rules:
+ - if: $CI_MERGE_REQUEST_ID
+
+.rspec:
+ cache:
+ key: omniauth-cas3-ruby
+ paths:
+ - vendor/gems/omniauth-cas3/vendor/ruby
+ before_script:
+ - cd vendor/gems/omniauth-cas3
+ - 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-cas3/Gemfile b/vendor/gems/omniauth-cas3/Gemfile
new file mode 100644
index 00000000000..adc6d8b37a3
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in omniauth-cas3.gemspec
+gemspec
diff --git a/vendor/gems/omniauth-cas3/Gemfile.lock b/vendor/gems/omniauth-cas3/Gemfile.lock
new file mode 100644
index 00000000000..4c59eb05d50
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/Gemfile.lock
@@ -0,0 +1,64 @@
+PATH
+ remote: .
+ specs:
+ omniauth-cas3 (1.1.4)
+ addressable (~> 2.3)
+ nokogiri (~> 1.7, >= 1.7.1)
+ omniauth (~> 1.2, < 3)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ addressable (2.8.0)
+ public_suffix (>= 2.0.2, < 5.0)
+ awesome_print (1.9.2)
+ crack (0.4.5)
+ rexml
+ diff-lcs (1.5.0)
+ hashdiff (1.0.1)
+ hashie (5.0.0)
+ mini_portile2 (2.8.0)
+ nokogiri (1.13.7)
+ mini_portile2 (~> 2.8.0)
+ racc (~> 1.4)
+ omniauth (1.9.1)
+ hashie (>= 3.4.6)
+ rack (>= 1.6.2, < 3)
+ public_suffix (4.0.7)
+ racc (1.6.0)
+ rack (2.2.4)
+ rack-test (0.8.3)
+ rack (>= 1.0, < 3)
+ rake (10.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)
+ webmock (3.14.0)
+ addressable (>= 2.8.0)
+ crack (>= 0.3.2)
+ hashdiff (>= 0.4.0, < 2.0.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ awesome_print
+ omniauth-cas3!
+ rack-test (~> 0.6)
+ rake (~> 10.0)
+ rspec (>= 3.4)
+ webmock
+
+BUNDLED WITH
+ 2.3.18
diff --git a/vendor/gems/omniauth-cas3/LICENSE b/vendor/gems/omniauth-cas3/LICENSE
new file mode 100644
index 00000000000..402cb6e4380
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2011 Derek Lindahl and CustomInk, LLC
+Copyright (c) 2015 tduehr
+
+MIT License
+
+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/omniauth-cas3/README.md b/vendor/gems/omniauth-cas3/README.md
new file mode 100644
index 00000000000..3c66341defb
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/README.md
@@ -0,0 +1,134 @@
+# OmniAuth CAS Strategy [![Gem Version][version_badge]][version] [![Build Status][travis_status]][travis]
+
+This is a fork of [omniauth-cas3](https://github.com/tduehr/omniauth-cas3) to
+support:
+
+1. OmniAuth v1 and v2. OmniAuth v2 disables GET requests by default
+ and defaults to POST. GitLab already has patched v1 to use POST,
+ but other dependencies need to be updated:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/30073.
+2. We may deprecate this library entirely in the future:
+ https://gitlab.com/gitlab-org/gitlab/-/issues/366212
+
+[version_badge]: https://badge.fury.io/rb/omniauth-cas3.png
+[version]: http://badge.fury.io/rb/omniauth-cas3
+[travis]: http://travis-ci.org/tduehr/omniauth-cas3
+[travis_status]: https://secure.travis-ci.org/dlindahl/omniauth-cas3.png
+[releases]: https://github.com/tduehr/omniauth-cas3/releases
+
+This is a OmniAuth 1.0 compatible port of the previously available
+[OmniAuth CAS strategy][old_omniauth_cas] that was bundled with OmniAuth 0.3. This strategy has also been updated for CAS protocol version 3.0 and patched to deal with namespace issues.
+
+* [View the documentation][document_up]
+* [Changelog][releases]
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+ gem 'omniauth-cas3'
+
+And then execute:
+
+ $ bundle
+
+Or install it yourself as:
+
+ $ gem install omniauth-cas3
+
+## Usage
+
+Use like any other OmniAuth strategy:
+
+```ruby
+Rails.application.config.middleware.use OmniAuth::Builder do
+ provider :cas3, host: 'cas.yourdomain.com'
+end
+```
+
+### Configuration Options
+
+#### Required
+
+OmniAuth CAS requires at least one of the following two configuration options:
+
+ * `url` - Defines the URL of your CAS server (i.e. `http://example.org:8080`)
+ * `host` - Defines the host of your CAS server (i.e. `example.org`).
+
+#### Optional
+
+Other configuration options:
+
+ * `port` - The port to use for your configured CAS `host`. Optional if using `url`.
+ * `ssl` - TRUE to connect to your CAS server over SSL. Optional if using `url`.
+ * `service_validate_url` - The URL to use to validate a user. Defaults to `'/serviceValidate'`.
+ * `callback_url` - The URL custom URL path which CAS uses to call back to the service. Defaults to `/users/auth/cas3/callback`.
+ * `logout_url` - The URL to use to logout a user. Defaults to `'/logout'`.
+ * `login_url` - Defines the URL used to prompt users for their login information. Defaults to `/login` If no `host` is configured, the host application's domain will be used.
+ * `uid_field` - The user data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
+ * `ca_path` - Optional when `ssl` is `true`. Sets path of a CA certification directory. See [Net::HTTP][net_http] for more details.
+ * `disable_ssl_verification` - Optional when `ssl` is true. Disables verification.
+ * `on_single_sign_out` - Optional. Callback used when a [CAS 3.1 Single Sign Out][sso]
+ request is received.
+ * `fetch_raw_info` - Optional. Callback used to return additional "raw" user
+ info from other sources.
+
+ ```ruby
+ provider :cas3,
+ fetch_raw_info: lambda { |strategy, options, ticket, user_info|
+ ExternalService.get(user_info[:user]).attributes
+ }
+ ```
+
+Configurable options for values returned by CAS:
+
+ * `uid_key` - The user ID data attribute to use as your user's unique identifier. Defaults to `'user'` (which usually contains the user's login name).
+ * `name_key` - The data attribute containing user first and last name. Defaults to `'name'`.
+ * `email_key` - The data attribute containing user email address. Defaults to `'email'`.
+ * `nickname_key` - The data attribute containing user's nickname. Defaults to `'user'`.
+ * `first_name_key` - The data attribute containing user first name. Defaults to `'first_name'`.
+ * `last_name_key` - The data attribute containing user last name. Defaults to `'last_name'`.
+ * `location_key` - The data attribute containing user location/address. Defaults to `'location'`.
+ * `image_key` - The data attribute containing user image/picture. Defaults to `'image'`.
+ * `phone_key` - The data attribute containing user contact phone number. Defaults to `'phone'`.
+
+## Migrating from OmniAuth 0.3
+
+Given the following OmniAuth 0.3 configuration:
+
+```ruby
+provider :CAS, cas_server: 'https://cas.example.com/cas/'
+```
+
+Your new settings should look similar to this:
+
+```ruby
+provider :cas3,
+ host: 'cas.example.com',
+ login_url: '/cas/login',
+ service_validate_url: '/cas/p3/serviceValidate'
+```
+
+If you encounter problems wih SSL certificates you may want to set the `ca_path` parameter or activate `disable_ssl_verification` (not recommended).
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Added some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
+
+## Thanks
+
+Special thanks go out to the following people
+
+ * @dlindahl For the original work in porting this from OmniAuth 0.3
+ * Phillip Aldridge (@iterateNZ) and JB Barth (@jbbarth) for helping out with Issue #3
+ * Elber Ribeiro (@dynaum) for Ubuntu SSL configuration support
+ * @rbq for README updates and OmniAuth 0.3 migration guide
+
+[old_omniauth_cas]: https://github.com/intridea/omniauth/blob/0-3-stable/oa-enterprise/lib/omniauth/strategies/cas.rb
+[document_up]: http://tduehr.github.com/omniauth-cas3/
+[net_http]: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
+[sso]: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
diff --git a/vendor/gems/omniauth-cas3/Rakefile b/vendor/gems/omniauth-cas3/Rakefile
new file mode 100644
index 00000000000..af92638ba13
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/Rakefile
@@ -0,0 +1,15 @@
+#!/usr/bin/env rake
+require 'bundler/gem_tasks'
+
+require 'rspec/core/rake_task'
+desc 'Default: run specs.'
+task default: :spec
+
+desc 'Run specs'
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.rspec_opts = '--require spec_helper --color --order rand'
+end
+
+task :test do
+ fail %q{This application uses RSpec. Try running "rake spec"}
+end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb
new file mode 100644
index 00000000000..58509b933c8
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth-cas3.rb
@@ -0,0 +1 @@
+require 'omniauth/cas3'
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb
new file mode 100644
index 00000000000..80460aa1f31
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth/cas3.rb
@@ -0,0 +1,2 @@
+require 'omniauth/cas3/version'
+require 'omniauth/strategies/cas3' \ No newline at end of file
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb b/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb
new file mode 100644
index 00000000000..9508dd69125
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth/cas3/version.rb
@@ -0,0 +1,5 @@
+module Omniauth
+ module Cas3
+ VERSION = '1.1.4'
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb
new file mode 100644
index 00000000000..7271621c564
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3.rb
@@ -0,0 +1,222 @@
+require 'omniauth'
+require 'addressable/uri'
+
+module OmniAuth
+ module Strategies
+ class CAS3
+ include OmniAuth::Strategy
+
+ # Custom Exceptions
+ class MissingCASTicket < StandardError; end
+ class InvalidCASTicket < StandardError; end
+
+ autoload :ServiceTicketValidator, 'omniauth/strategies/cas3/service_ticket_validator'
+ autoload :LogoutRequest, 'omniauth/strategies/cas3/logout_request'
+
+ attr_accessor :raw_info
+ alias_method :user_info, :raw_info
+
+ option :name, :cas3 # Required property by OmniAuth::Strategy
+
+ option :host, nil
+ option :port, nil
+ option :path, nil
+ option :ssl, true
+ option :service_validate_url, '/p3/serviceValidate'
+ option :login_url, '/login'
+ option :logout_url, '/logout'
+ option :on_single_sign_out, Proc.new {}
+ # A Proc or lambda that returns a Hash of additional user info to be
+ # merged with the info returned by the CAS server.
+ #
+ # @param [Object] An instance of OmniAuth::Strategies::CAS for the current request
+ # @param [String] The user's Service Ticket value
+ # @param [Hash] The user info for the Service Ticket returned by the CAS server
+ #
+ # @return [Hash] Extra user info
+ option :fetch_raw_info, Proc.new { Hash.new }
+ # Make all the keys configurable with some defaults set here
+ option :uid_field, 'user'
+ option :name_key, 'name'
+ option :email_key, 'email'
+ option :nickname_key, 'user'
+ option :first_name_key, 'first_name'
+ option :last_name_key, 'last_name'
+ option :location_key, 'location'
+ option :image_key, 'image'
+ option :phone_key, 'phone'
+
+ # As required by https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
+ AuthHashSchemaKeys = %w{name email nickname first_name last_name location image phone}
+ info do
+ prune!({
+ name: raw_info[options[:name_key].to_s],
+ email: raw_info[options[:email_key].to_s],
+ nickname: raw_info[options[:nickname_key].to_s],
+ first_name: raw_info[options[:first_name_key].to_s],
+ last_name: raw_info[options[:last_name_key].to_s],
+ location: raw_info[options[:location_key].to_s],
+ image: raw_info[options[:image_key].to_s],
+ phone: raw_info[options[:phone_key].to_s]
+ })
+ end
+
+ extra do
+ prune!(
+ raw_info.delete_if{ |k,v| AuthHashSchemaKeys.include?(k) }
+ )
+ end
+
+ uid do
+ raw_info[options[:uid_field].to_s]
+ end
+
+ credentials do
+ prune!({ ticket: @ticket })
+ end
+
+ def callback_phase
+ if on_sso_path?
+ single_sign_out_phase
+ else
+ @ticket = request.params['ticket']
+ return fail!(:no_ticket, MissingCASTicket.new('No CAS Ticket')) unless @ticket
+ fetch_raw_info(@ticket)
+ return fail!(:invalid_ticket, InvalidCASTicket.new('Invalid CAS Ticket')) if raw_info.empty?
+ super
+ end
+ end
+
+ def request_phase
+ service_url = append_params(callback_url, return_url)
+
+ [
+ 302,
+ {
+ 'Location' => login_url(service_url),
+ 'Content-Type' => 'text/plain'
+ },
+ ["You are being redirected to CAS for sign-in."]
+ ]
+ end
+
+ def on_sso_path?
+ request.post? && request.params.has_key?('logoutRequest')
+ end
+
+ def single_sign_out_phase
+ logout_request_service.new(self, request).call(options)
+ end
+
+ # Build a CAS host with protocol and port
+ #
+ #
+ def cas_url
+ extract_url if options['url']
+ validate_cas_setup
+ @cas_url ||= begin
+ uri = Addressable::URI.new
+ uri.host = options.host
+ uri.scheme = options.ssl ? 'https' : 'http'
+ uri.port = options.port
+ uri.path = options.path
+ uri.to_s
+ end
+ end
+
+ def extract_url
+ url = Addressable::URI.parse(options.delete('url'))
+ options.merge!(
+ 'host' => url.host,
+ 'port' => url.port,
+ 'path' => url.path,
+ 'ssl' => url.scheme == 'https'
+ )
+ end
+
+ def validate_cas_setup
+ if options.host.nil? || options.login_url.nil?
+ raise ArgumentError.new(":host and :login_url MUST be provided")
+ end
+ end
+
+ # Build a service-validation URL from +service+ and +ticket+.
+ # If +service+ has a ticket param, first remove it. URL-encode
+ # +service+ and add it and the +ticket+ as paraemters to the
+ # CAS serviceValidate URL.
+ #
+ # @param [String] service the service (a.k.a. return-to) URL
+ # @param [String] ticket the ticket to validate
+ #
+ # @return [String] a URL like `http://cas.mycompany.com/serviceValidate?service=...&ticket=...`
+ def service_validate_url(service_url, ticket)
+ service_url = Addressable::URI.parse(service_url)
+ service_url.query_values = service_url.query_values.tap { |qs| qs.delete('ticket') }
+ cas_url + append_params(options.service_validate_url, {
+ service: service_url.to_s,
+ ticket: ticket
+ })
+ end
+
+ # Build a CAS login URL from +service+.
+ #
+ # @param [String] service the service (a.k.a. return-to) URL
+ #
+ # @return [String] a URL like `http://cas.mycompany.com/login?service=...`
+ def login_url(service)
+ cas_url + append_params(options.login_url, { service: service })
+ end
+
+ # Adds URL-escaped +parameters+ to +base+.
+ #
+ # @param [String] base the base URL
+ # @param [String] params the parameters to append to the URL
+ #
+ # @return [String] the new joined URL.
+ def append_params(base, params)
+ params = params.each { |k,v| v = Rack::Utils.escape(v) }
+ Addressable::URI.parse(base).tap do |base_uri|
+ base_uri.query_values = (base_uri.query_values || {}).merge(params)
+ end.to_s
+ end
+
+ # Validate the Service Ticket
+ # @return [Object] the validated Service Ticket
+ def validate_service_ticket(ticket)
+ ServiceTicketValidator.new(self, options, callback_url, ticket).call
+ end
+
+ private
+
+ def fetch_raw_info(ticket)
+ ticket_user_info = validate_service_ticket(ticket).user_info
+ custom_user_info = options.fetch_raw_info.call(self, options, ticket, ticket_user_info)
+ self.raw_info = ticket_user_info.merge(custom_user_info)
+ end
+
+ # Deletes Hash pairs with `nil` values.
+ # From https://github.com/mkdynamic/omniauth-facebook/blob/972ed5e3456bcaed7df1f55efd7c05c216c8f48e/lib/omniauth/strategies/facebook.rb#L122-127
+ def prune!(hash)
+ hash.delete_if do |_, value|
+ prune!(value) if value.is_a?(Hash)
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
+ end
+ end
+
+ def return_url
+ # If the request already has a `url` parameter, then it will already be appended to the callback URL.
+ if request.params && request.params['url']
+ {}
+ else
+ { url: request.referer }
+ end
+ end
+
+ def logout_request_service
+ LogoutRequest
+ end
+ end
+ end
+end
+
+OmniAuth.config.add_camelization 'cas3', 'CAS3'
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb
new file mode 100644
index 00000000000..72978227edb
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/logout_request.rb
@@ -0,0 +1,73 @@
+module OmniAuth
+ module Strategies
+ class CAS3
+ class LogoutRequest
+ def initialize(strategy, request)
+ @strategy, @request = strategy, request
+ end
+
+ def call(options = {})
+ @options = options
+
+ begin
+ result = single_sign_out_callback.call(*logout_request)
+ rescue StandardError => err
+ return @strategy.fail! :logout_request, err
+ else
+ result = [200,{},'OK'] if result == true || result.nil?
+ ensure
+ return unless result
+
+ # TODO: Why does ActionPack::Response return [status,headers,body]
+ # when Rack::Response#new wants [body,status,headers]? Additionally,
+ # why does Rack::Response differ in argument order from the usual
+ # Rack-like [status,headers,body] array?
+ return Rack::Response.new(result[2],result[0],result[1]).finish
+ end
+ end
+
+ private
+
+ def logout_request
+ @logout_request ||= begin
+ saml = parse_and_ensure_namespaces(@request.params['logoutRequest'])
+ ns = saml.collect_namespaces
+ name_id = saml.xpath('//saml:NameID', ns).text
+ sess_idx = saml.xpath('//samlp:SessionIndex', ns).text
+ inject_params(name_id:name_id, session_index:sess_idx)
+ @request
+ end
+ end
+
+ def parse_and_ensure_namespaces(logout_request_xml)
+ doc = Nokogiri.parse(logout_request_xml)
+ ns = doc.collect_namespaces
+ if ns.include?('xmlns:samlp') && ns.include?('xmlns:saml')
+ doc
+ else
+ add_namespaces(doc)
+ end
+ end
+
+ def add_namespaces(logout_request_doc)
+ root = logout_request_doc.root
+ root.add_namespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol')
+ root.add_namespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion\\')
+
+ # In order to add namespaces properly we need to re-parse the document
+ Nokogiri.parse(logout_request_doc.to_s)
+ end
+
+ def inject_params(new_params)
+ new_params.each do |key, val|
+ @request.update_param(key, val)
+ end
+ end
+
+ def single_sign_out_callback
+ @options[:on_single_sign_out]
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb
new file mode 100644
index 00000000000..4f9a61c5216
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/lib/omniauth/strategies/cas3/service_ticket_validator.rb
@@ -0,0 +1,103 @@
+require 'net/http'
+require 'net/https'
+require 'nokogiri'
+
+module OmniAuth
+ module Strategies
+ class CAS3
+ class ServiceTicketValidator
+ VALIDATION_REQUEST_HEADERS = { 'Accept' => '*/*' }
+
+ # Build a validator from a +configuration+, a
+ # +return_to+ URL, and a +ticket+.
+ #
+ # @param [Hash] options the OmniAuth Strategy options
+ # @param [String] return_to_url the URL of this CAS client service
+ # @param [String] ticket the service ticket to validate
+ def initialize(strategy, options, return_to_url, ticket)
+ @options = options
+ @uri = URI.parse(strategy.service_validate_url(return_to_url, ticket))
+ end
+
+ # Executes a network request to process the CAS Service Response
+ def call
+ @response_body = get_service_response_body
+ @success_body = find_authentication_success(@response_body)
+ self
+ end
+
+ # Request validation of the ticket from the CAS server's
+ # serviceValidate (CAS 2.0) function.
+ #
+ # Swallows all XML parsing errors (and returns +nil+ in those cases).
+ #
+ # @return [Hash, nil] a user information hash if the response is valid; +nil+ otherwise.
+ #
+ # @raise any connection errors encountered.
+ def user_info
+ parse_user_info(@success_body)
+ end
+
+ private
+
+ # turns an `<cas:authenticationSuccess>` node into a Hash;
+ # returns nil if given nil
+ def parse_user_info(node)
+ return nil if node.nil?
+ {}.tap do |hash|
+ node.children.each do |e|
+ node_name = e.name.sub(/^cas:/, '')
+ unless e.kind_of?(Nokogiri::XML::Text) || node_name == 'proxies'
+ # There are no child elements
+ if e.element_children.count == 0
+ hash[node_name] = e.content
+ elsif e.element_children.count
+ # JASIG style extra attributes
+ if node_name == 'attributes'
+ hash.merge!(parse_user_info(e))
+ else
+ hash[node_name] = [] if hash[node_name].nil?
+ hash[node_name].push(parse_user_info(e))
+ end
+ end
+ end
+ end
+ end
+ end
+
+ # finds an `<cas:authenticationSuccess>` node in
+ # a `<cas:serviceResponse>` body if present; returns nil
+ # if the passed body is nil or if there is no such node.
+ def find_authentication_success(body)
+ return nil if body.nil? || body == ''
+ begin
+ doc = Nokogiri::XML(body)
+ begin
+ doc.xpath('/cas:serviceResponse/cas:authenticationSuccess')
+ rescue Nokogiri::XML::XPath::SyntaxError
+ doc.xpath('/serviceResponse/authenticationSuccess')
+ end
+ rescue Nokogiri::XML::XPath::SyntaxError
+ nil
+ end
+ end
+
+ # retrieves the `<cas:serviceResponse>` XML from the CAS server
+ def get_service_response_body
+ result = ''
+ http = Net::HTTP.new(@uri.host, @uri.port)
+ http.use_ssl = @uri.port == 443 || @uri.instance_of?(URI::HTTPS)
+ if http.use_ssl?
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @options.disable_ssl_verification?
+ http.ca_path = @options.ca_path
+ end
+ http.start do |c|
+ response = c.get "#{@uri.path}?#{@uri.query}", VALIDATION_REQUEST_HEADERS.dup
+ result = response.body
+ end
+ result
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec b/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec
new file mode 100644
index 00000000000..abbcaa268d0
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/omniauth-cas3.gemspec
@@ -0,0 +1,27 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../lib/omniauth/cas3/version', __FILE__)
+
+Gem::Specification.new do |gem|
+ gem.authors = ["Derek Lindahl, tduehr"]
+ gem.email = ["td@matasano.com"]
+ gem.summary = %q{CAS 3.0 Strategy for OmniAuth}
+ gem.description = gem.summary
+ gem.homepage = "https://github.com/tduehr/omniauth-cas3"
+
+ gem.files = Dir.glob("lib/**/*.*")
+ gem.test_files = Dir.glob("spec/**/**/*.*")
+ gem.name = "omniauth-cas3"
+ gem.require_paths = ["lib"]
+ gem.version = Omniauth::Cas3::VERSION
+
+ gem.add_dependency 'omniauth', '~> 1.2', '< 3'
+ gem.add_dependency 'nokogiri', '~> 1.7', '>= 1.7.1'
+ gem.add_dependency 'addressable', '~> 2.3'
+
+ gem.add_development_dependency 'rake', '~> 10.0'
+ gem.add_development_dependency 'webmock'
+ gem.add_development_dependency 'rspec', '>= 3.4'
+ gem.add_development_dependency 'rack-test', '~> 0.6'
+
+ gem.add_development_dependency 'awesome_print'
+end
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml
new file mode 100644
index 00000000000..f8238a18014
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/fixtures/cas_failure.xml
@@ -0,0 +1,4 @@
+<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ <cas:authenticationFailure>
+ </cas:authenticationFailure>
+</cas:serviceResponse>
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml
new file mode 100644
index 00000000000..18904f64b35
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success.xml
@@ -0,0 +1,14 @@
+<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ <cas:authenticationSuccess>
+ <cas:user>psegel</cas:user>
+ <cas:employeeid>54</cas:employeeid>
+ <cas:first_name>P. Segel</cas:first_name>
+ <cas:first_name>Peter</cas:first_name>
+ <cas:last_name>Segel</cas:last_name>
+ <cas:email>psegel@intridea.com</cas:email>
+ <cas:location>Washington, D.C.</cas:location>
+ <cas:image>/images/user.jpg</cas:image>
+ <cas:phone>555-555-5555</cas:phone>
+ <cas:hire_date>2004-07-13</cas:hire_date>
+ </cas:authenticationSuccess>
+</cas:serviceResponse>
diff --git a/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml
new file mode 100644
index 00000000000..72f58edfb46
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/fixtures/cas_success_jasig.xml
@@ -0,0 +1,16 @@
+<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ <cas:authenticationSuccess>
+ <cas:user>psegel</cas:user>
+ <cas:attributes>
+ <cas:employeeid>54</cas:employeeid>
+ <cas:first_name>P. Segel</cas:first_name>
+ <cas:first_name>Peter</cas:first_name>
+ <cas:last_name>Segel</cas:last_name>
+ <cas:email>psegel@intridea.com</cas:email>
+ <cas:location>Washington, D.C.</cas:location>
+ <cas:image>/images/user.jpg</cas:image>
+ <cas:phone>555-555-5555</cas:phone>
+ <cas:hire_date>2004-07-13</cas:hire_date>
+ </cas:attributes>
+ </cas:authenticationSuccess>
+</cas:serviceResponse>
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb
new file mode 100644
index 00000000000..4834347fa03
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/logout_request_spec.rb
@@ -0,0 +1,127 @@
+require 'spec_helper'
+
+describe OmniAuth::Strategies::CAS3::LogoutRequest do
+ let(:strategy) { double('strategy') }
+ let(:env) do
+ { 'rack.input' => StringIO.new('','r') }
+ end
+ let(:request) { double('request', params:params, env:env) }
+ let(:params) { { 'url' => url, 'logoutRequest' => logoutRequest } }
+ let(:url) { 'http://notes.dev/signed_in' }
+ let(:logoutRequest) do
+ %Q[
+ <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
+ <saml:NameID>@NOT_USED@</saml:NameID>
+ <samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex>
+ </samlp:LogoutRequest>
+ ]
+ end
+
+ subject { described_class.new(strategy, request).call(options) }
+
+ describe 'SAML attributes' do
+ let(:callback) { Proc.new{} }
+ let(:options) do
+ { on_single_sign_out: callback }
+ end
+
+ before do
+ @rack_input = nil
+ allow(callback).to receive(:call) do |req|
+ @rack_input = req.env['rack.input'].read
+ true
+ end
+ end
+
+ it 'are parsed and injected into the Rack Request parameters', :skip => true do
+ subject
+ expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-123456-123abc456def'
+ end
+
+ it 'are parsed and injected even if saml defined inside NameID', :skip => true do
+ request.params['logoutRequest'] =
+ %Q[
+ <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="foobarbaz" Version="2.0" IssueInstant="2014-10-19T17:13:50Z">
+ <saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">@NOT_USED@</saml:NameID>
+ <samlp:SessionIndex>ST-foo-bar</samlp:SessionIndex>
+ </samlp:LogoutRequest>
+ ]
+ subject
+ expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-foo-bar'
+ end
+
+ it 'are parsed and injected even if saml and samlp namespaces not defined', :skip => true do
+ request.params['logoutRequest'] =
+ %Q[
+ <samlp:LogoutRequest ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
+ <saml:NameID>@NOT_USED@</saml:NameID>
+ <samlp:SessionIndex>ST-789000-456def789ghi</samlp:SessionIndex>
+ </samlp:LogoutRequest>
+ ]
+ subject
+ expect(@rack_input).to eq 'name_id=%40NOT_USED%40&session_index=ST-789000-456def789ghi'
+ end
+
+ context 'that raise when parsed' do
+ let(:env) { { 'rack.input' => nil } }
+
+ before do
+ allow(strategy).to receive(:fail!)
+ subject
+ expect(strategy).to have_received(:fail!)
+ end
+
+ it 'responds with an error', skip: true do
+ expect(strategy).to have_received(:fail!)
+ end
+ end
+ end
+
+ describe 'with a configured callback' do
+ let(:options) do
+ { on_single_sign_out: callback }
+ end
+
+ context 'that returns TRUE' do
+ let(:callback) { Proc.new{true} }
+
+ it 'responds with OK', skip: true do
+ expect(subject[0]).to eq 200
+ expect(subject[2].body).to eq ['OK']
+ end
+ end
+
+ context 'that returns Nil' do
+ let(:callback) { Proc.new{} }
+
+ it 'responds with OK', skip: true do
+ expect(subject[0]).to eq 200
+ expect(subject[2].body).to eq ['OK']
+ end
+ end
+
+ context 'that returns a tuple' do
+ let(:callback) { Proc.new{ [400,{},'Bad Request'] } }
+
+ it 'responds with OK', skip: true do
+ expect(subject[0]).to eq 400
+ expect(subject[2].body).to eq ['Bad Request']
+ end
+ end
+
+ context 'that raises an error' do
+ let(:exception) { RuntimeError.new('error' )}
+ let(:callback) { Proc.new{raise exception} }
+
+ before do
+ allow(strategy).to receive(:fail!)
+ subject
+ end
+
+ it 'responds with an error', skip: true do
+ expect(strategy).to have_received(:fail!)
+ .with(:logout_request, exception)
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb
new file mode 100644
index 00000000000..b031d1d68fc
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3/service_ticket_validator_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe OmniAuth::Strategies::CAS3::ServiceTicketValidator do
+ let(:strategy) do
+ double('strategy',
+ service_validate_url: 'https://example.org/serviceValidate'
+ )
+ end
+ let(:provider_options) do
+ double('provider_options',
+ disable_ssl_verification?: false,
+ ca_path: '/etc/ssl/certsZOMG'
+ )
+ end
+ let(:validator) do
+ OmniAuth::Strategies::CAS3::ServiceTicketValidator.new( strategy, provider_options, '/foo', nil )
+ end
+
+ describe '#call' do
+ before do
+ stub_request(:get, 'https://example.org/serviceValidate?')
+ .to_return(status: 200, body: '')
+ end
+
+ subject { validator.call }
+
+ it 'returns itself' do
+ expect(subject).to eq validator
+ end
+
+ it 'uses the configured CA path' do
+ subject
+ expect(provider_options).to have_received :ca_path
+ end
+ end
+
+ describe '#user_info' do
+ let(:ok_fixture) do
+ File.expand_path(File.join(File.dirname(__FILE__), '../../../fixtures/cas_success.xml'))
+ end
+ let(:service_response) { File.read(ok_fixture) }
+
+ before do
+ stub_request(:get, 'https://example.org/serviceValidate?')
+ .to_return(status: 200, body:service_response)
+ validator.call
+ end
+
+ subject { validator.user_info }
+
+ it 'parses user info from the response' do
+ expect(subject).to include 'user' => 'psegel'
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb
new file mode 100644
index 00000000000..fd61fc79580
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/omniauth/strategies/cas3_spec.rb
@@ -0,0 +1,250 @@
+require 'spec_helper'
+
+describe OmniAuth::Strategies::CAS3, type: :strategy do
+ include Rack::Test::Methods
+
+ let(:my_cas_provider) { Class.new(OmniAuth::Strategies::CAS3) }
+ before do
+ stub_const 'MyCasProvider', my_cas_provider
+ end
+ let(:app) do
+ Rack::Builder.new {
+ use OmniAuth::Test::PhonySession
+ use MyCasProvider, name: :cas3, host: 'cas.example.org', ssl: false, port: 8080, uid_field: :employeeid
+ run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
+ }.to_app
+ end
+
+ # TODO: Verify that these are even useful tests
+ shared_examples_for 'a CAS redirect response' do
+ let(:redirect_params) { 'service=' + Rack::Utils.escape("http://example.org/auth/cas3/callback?url=#{Rack::Utils.escape(return_url)}") }
+
+ before { get url, nil, request_env }
+
+ subject { last_response }
+
+ it { should be_redirect }
+
+ it 'redirects to the CAS server' do
+ expect(subject.headers).to include 'Location' => "http://cas.example.org:8080/login?#{redirect_params}"
+ end
+ end
+
+ describe '#cas_url' do
+ let(:params) { Hash.new }
+ let(:provider) { MyCasProvider.new(nil, params) }
+
+ subject { provider.cas_url }
+
+ it 'raises an ArgumentError' do
+ expect{subject}.to raise_error ArgumentError, %r{:host and :login_url MUST be provided}
+ end
+
+ context 'with an explicit :url option' do
+ let(:url) { 'https://example.org:8080/my_cas' }
+ let(:params) { super().merge url:url }
+
+ before { subject }
+
+ it { should eq url }
+
+ it 'parses the URL into it the appropriate strategy options' do
+ expect(provider.options).to include ssl:true
+ expect(provider.options).to include host:'example.org'
+ expect(provider.options).to include port:8080
+ expect(provider.options).to include path:'/my_cas'
+ end
+ end
+
+ context 'with explicit URL component' do
+ let(:params) { super().merge host:'example.org', port:1234, ssl:true, path:'/a/path' }
+
+ before { subject }
+
+ it { should eq 'https://example.org:1234/a/path' }
+
+ it 'parses the URL into it the appropriate strategy options' do
+ expect(provider.options).to include ssl:true
+ expect(provider.options).to include host:'example.org'
+ expect(provider.options).to include port:1234
+ expect(provider.options).to include path:'/a/path'
+ end
+ end
+ end
+
+ describe 'defaults' do
+ subject { MyCasProvider.default_options.to_hash }
+
+ it { should include('ssl' => true) }
+ end
+
+ describe 'GET /auth/cas3' do
+ let(:return_url) { 'http://myapp.com/admin/foo' }
+
+ context 'with a referer' do
+ let(:url) { '/auth/cas3' }
+
+ let(:request_env) { { 'HTTP_REFERER' => return_url } }
+
+ it_behaves_like 'a CAS redirect response'
+ end
+
+ context 'with an explicit return URL' do
+ let(:url) { "/auth/cas3?url=#{return_url}" }
+
+ let(:request_env) { {} }
+
+ it_behaves_like 'a CAS redirect response'
+ end
+ end
+
+ describe 'GET /auth/cas3/callback' do
+ context 'without a ticket' do
+ before { get '/auth/cas3/callback' }
+
+ subject { last_response }
+
+ it { should be_redirect }
+
+ it 'redirects with a failure message' do
+ expect(subject.headers).to include 'Location' => '/auth/failure?message=no_ticket&strategy=cas3'
+ end
+ end
+
+ context 'with an invalid ticket' do
+ before do
+ stub_request(:get, /^http:\/\/cas.example.org:8080?\/p3\/serviceValidate\?([^&]+&)?ticket=9391d/).
+ to_return( body: File.read('spec/fixtures/cas_failure.xml') )
+ get '/auth/cas3/callback?ticket=9391d'
+ end
+
+ subject { last_response }
+
+ it { should be_redirect }
+
+ it 'redirects with a failure message' do
+ expect(subject.headers).to include 'Location' => '/auth/failure?message=invalid_ticket&strategy=cas3'
+ end
+ end
+
+ describe 'with a valid ticket' do
+ shared_examples :successful_validation do
+ before do
+ stub_request(:get, /^http:\/\/cas.example.org:8080?\/p3\/serviceValidate\?([^&]+&)?ticket=593af/)
+ .with { |request| @request_uri = request.uri.to_s }
+ .to_return( body: File.read("spec/fixtures/#{xml_file_name}") )
+
+ get "/auth/cas3/callback?ticket=593af&url=#{return_url}"
+ end
+
+ it 'strips the ticket parameter from the callback URL' do
+ expect(@request_uri.scan('ticket=').size).to eq 1
+ end
+
+ it 'properly encodes the service URL' do
+ expect(WebMock).to have_requested(:get, 'http://cas.example.org:8080/p3/serviceValidate')
+ .with(query: {
+ ticket: '593af',
+ service: 'http://example.org/auth/cas3/callback?url=' + Rack::Utils.escape('http://127.0.0.10/?some=parameter')
+ })
+ end
+
+ context "request.env['omniauth.auth']" do
+ subject { last_request.env['omniauth.auth'] }
+
+ it { should be_kind_of Hash }
+
+ it 'identifes the provider' do
+ expect(subject.provider).to eq :cas3
+ end
+
+ it 'returns the UID of the user' do
+ expect(subject.uid).to eq '54'
+ end
+
+ context 'the info hash' do
+ subject { last_request.env['omniauth.auth']['info'] }
+
+ it 'includes user info attributes' do
+ expect(subject.name).to eq 'Peter Segel'
+ expect(subject.first_name).to eq 'Peter'
+ expect(subject.last_name).to eq 'Segel'
+ expect(subject.nickname).to eq 'psegel'
+ expect(subject.email).to eq 'psegel@intridea.com'
+ expect(subject.location).to eq 'Washington, D.C.'
+ expect(subject.image).to eq '/images/user.jpg'
+ expect(subject.phone).to eq '555-555-5555'
+ end
+ end
+
+ context 'the extra hash' do
+ subject { last_request.env['omniauth.auth']['extra'] }
+
+ it 'includes additional user attributes' do
+ expect(subject.user).to eq 'psegel'
+ expect(subject.employeeid).to eq '54'
+ expect(subject.hire_date).to eq '2004-07-13'
+ end
+ end
+
+ context 'the credentials hash' do
+ subject { last_request.env['omniauth.auth']['credentials'] }
+
+ it 'has a ticket value' do
+ expect(subject.ticket).to eq '593af'
+ end
+ end
+ end
+
+ it 'calls through to the master app' do
+ expect(last_response.body).to eq 'true'
+ end
+ end
+
+ let(:return_url) { 'http://127.0.0.10/?some=parameter' }
+
+ context 'with JASIG flavored XML' do
+ let(:xml_file_name) { 'cas_success_jasig.xml' }
+
+ it_behaves_like :successful_validation
+ end
+
+ context 'with classic XML' do
+ let(:xml_file_name) { 'cas_success.xml' }
+
+ it_behaves_like :successful_validation
+ end
+ end
+ end
+
+ describe 'POST /auth/cas3/callback' do
+ describe 'with a Single Sign-Out logoutRequest' do
+ let(:logoutRequest) do
+ %Q[
+ <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion\" ID="123abc-1234-ab12-cd34-1234abcd" Version="2.0" IssueInstant="#{Time.now.to_s}">
+ <saml:NameID>@NOT_USED@</saml:NameID>
+ <samlp:SessionIndex>ST-123456-123abc456def</samlp:SessionIndex>
+ </samlp:LogoutRequest>
+ ]
+ end
+
+ let(:logout_request) { double('logout_request', call:[200,{},'OK']) }
+
+ subject do
+ post 'auth/cas3/callback', logoutRequest:logoutRequest
+ end
+
+ before do
+ allow_any_instance_of(MyCasProvider)
+ .to receive(:logout_request_service)
+ .and_return double('LogoutRequest', new:logout_request)
+
+ subject
+ end
+
+ it 'initializes a LogoutRequest' do
+ expect(logout_request).to have_received :call
+ end
+ end
+ end
+end
diff --git a/vendor/gems/omniauth-cas3/spec/spec_helper.rb b/vendor/gems/omniauth-cas3/spec/spec_helper.rb
new file mode 100644
index 00000000000..75231268ff3
--- /dev/null
+++ b/vendor/gems/omniauth-cas3/spec/spec_helper.rb
@@ -0,0 +1,13 @@
+require 'bundler/setup'
+require 'awesome_print'
+
+RSpec.configure do |c|
+ c.filter_run focus: true
+ c.run_all_when_everything_filtered = true
+end
+
+require 'rack/test'
+require 'webmock/rspec'
+require 'omniauth-cas3'
+
+OmniAuth.config.logger = Logger.new( '/dev/null' )
diff --git a/vendor/gems/omniauth-gitlab/.gitlab-ci.yml b/vendor/gems/omniauth-gitlab/.gitlab-ci.yml
index ad9545e2998..da6547a1766 100644
--- a/vendor/gems/omniauth-gitlab/.gitlab-ci.yml
+++ b/vendor/gems/omniauth-gitlab/.gitlab-ci.yml
@@ -13,18 +13,16 @@ workflow:
- 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.6:
- image: "ruby:2.6"
- extends: .rspec
-
rspec-2.7:
image: "ruby:2.7"
extends: .rspec
rspec-3.0:
image: "ruby:3.0"
- extends: .rspec \ No newline at end of file
+ extends: .rspec
diff --git a/vendor/gems/omniauth_crowd/.gitlab-ci.yml b/vendor/gems/omniauth_crowd/.gitlab-ci.yml
index 98e686db4e3..08a5da1a3d1 100644
--- a/vendor/gems/omniauth_crowd/.gitlab-ci.yml
+++ b/vendor/gems/omniauth_crowd/.gitlab-ci.yml
@@ -4,7 +4,7 @@ workflow:
.rspec:
cache:
- key: omniauth-gitlab-ruby
+ key: omniauth_crowd
paths:
- vendor/gems/omniauth_crowd/vendor/ruby
before_script:
@@ -13,14 +13,12 @@ workflow:
- 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.6:
- image: "ruby:2.6"
- extends: .rspec
-
rspec-2.7:
image: "ruby:2.7"
extends: .rspec
diff --git a/vendor/gems/omniauth_crowd/Gemfile.lock b/vendor/gems/omniauth_crowd/Gemfile.lock
index 0ac781e9948..56c9bd4cc7e 100644
--- a/vendor/gems/omniauth_crowd/Gemfile.lock
+++ b/vendor/gems/omniauth_crowd/Gemfile.lock
@@ -9,49 +9,51 @@ PATH
GEM
remote: http://rubygems.org/
specs:
- activesupport (5.0.0.1)
+ activesupport (7.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (~> 0.7)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- addressable (2.5.2)
- public_suffix (>= 2.0.2, < 4.0)
- concurrent-ruby (1.0.5)
- crack (0.4.3)
- safe_yaml (~> 1.0.0)
- diff-lcs (1.2.5)
- hashdiff (0.3.6)
- hashie (3.4.3)
- i18n (0.8.1)
- mini_portile2 (2.1.0)
- minitest (5.10.1)
- nokogiri (1.6.8.1)
- mini_portile2 (~> 2.1.0)
- omniauth (1.3.1)
- hashie (>= 1.2, < 4)
- rack (>= 1.0, < 3)
- public_suffix (3.0.0)
- rack (1.6.4)
- rack-test (0.6.3)
- rack (>= 1.0)
- rake (10.5.0)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ addressable (2.8.0)
+ public_suffix (>= 2.0.2, < 5.0)
+ concurrent-ruby (1.1.10)
+ crack (0.4.5)
+ rexml
+ diff-lcs (1.5.0)
+ hashdiff (1.0.1)
+ hashie (5.0.0)
+ i18n (1.12.0)
+ concurrent-ruby (~> 1.0)
+ mini_portile2 (2.8.0)
+ minitest (5.16.2)
+ nokogiri (1.13.8)
+ mini_portile2 (~> 2.8.0)
+ racc (~> 1.4)
+ omniauth (1.9.1)
+ hashie (>= 3.4.6)
+ rack (>= 1.6.2, < 3)
+ public_suffix (4.0.7)
+ racc (1.6.0)
+ rack (2.2.4)
+ rack-test (2.0.2)
+ rack (>= 1.3)
+ rake (13.0.6)
rexml (3.2.5)
- rspec (3.0.0)
- rspec-core (~> 3.0.0)
- rspec-expectations (~> 3.0.0)
- rspec-mocks (~> 3.0.0)
- rspec-core (3.0.4)
- rspec-support (~> 3.0.0)
- rspec-expectations (3.0.4)
+ 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.0.0)
- rspec-mocks (3.0.4)
- rspec-support (~> 3.0.0)
- rspec-support (3.0.4)
- safe_yaml (1.0.4)
- thread_safe (0.3.6)
- tzinfo (1.2.2)
- thread_safe (~> 0.1)
+ 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)
+ tzinfo (2.0.5)
+ concurrent-ruby (~> 1.0)
webmock (3.0.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
@@ -67,8 +69,8 @@ DEPENDENCIES
rack-test
rake
rexml (~> 3.2.5)
- rspec (~> 3.0.0)
+ rspec (>= 3.4)
webmock (~> 3.0.0)
BUNDLED WITH
- 2.3.15
+ 2.3.19
diff --git a/vendor/gems/omniauth_crowd/omniauth_crowd.gemspec b/vendor/gems/omniauth_crowd/omniauth_crowd.gemspec
index 4963c5fef1b..1707c7f3f10 100644
--- a/vendor/gems/omniauth_crowd/omniauth_crowd.gemspec
+++ b/vendor/gems/omniauth_crowd/omniauth_crowd.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
gem.add_development_dependency(%q<rake>, [">= 0"])
gem.add_development_dependency(%q<rack-test>, [">= 0"])
gem.add_development_dependency(%q<rexml>, ["~> 3.2.5"])
- gem.add_development_dependency(%q<rspec>, ["~> 3.0.0"])
+ gem.add_development_dependency(%q<rspec>, [">= 3.4"])
gem.add_development_dependency(%q<webmock>, ["~> 3.0.0"])
gem.add_development_dependency(%q<bundler>, ["> 1.0.0"])
end
diff --git a/vendor/project_templates/hugo.tar.gz b/vendor/project_templates/hugo.tar.gz
index 1f756a696e3..3d037bbf1df 100644
--- a/vendor/project_templates/hugo.tar.gz
+++ b/vendor/project_templates/hugo.tar.gz
Binary files differ
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 10a0b13b50e..e2191c1a749 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -4,7 +4,7 @@ go 1.17
require (
github.com/Azure/azure-storage-blob-go v0.14.0
- github.com/BurntSushi/toml v1.1.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
@@ -20,13 +20,13 @@ require (
github.com/johannesboyne/gofakes3 v0.0.0-20220627085814-c3ac35da23b2
github.com/jpillora/backoff v1.0.0
github.com/mitchellh/copystructure v1.2.0
- github.com/prometheus/client_golang v1.12.2
+ github.com/prometheus/client_golang v1.13.0
github.com/rafaeljusto/redigomock/v3 v3.1.1
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
- github.com/sirupsen/logrus v1.8.1
+ 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.1.2
+ gitlab.com/gitlab-org/gitaly/v15 v15.2.2
gitlab.com/gitlab-org/golang-archive-zip v0.1.1
gitlab.com/gitlab-org/labkit v1.16.0
gocloud.dev v0.25.0
@@ -34,9 +34,9 @@ require (
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/net v0.0.0-20220531201128-c960675eff93
golang.org/x/tools v0.1.11
- google.golang.org/grpc v1.45.0
- google.golang.org/protobuf v1.28.0
- honnef.co/go/tools v0.3.2
+ google.golang.org/grpc v1.48.0
+ google.golang.org/protobuf v1.28.1
+ honnef.co/go/tools v0.3.3
)
require (
@@ -68,15 +68,16 @@ require (
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/google/go-cmp v0.5.7 // indirect
+ github.com/google/go-cmp v0.5.8 // indirect
github.com/google/pprof v0.0.0-20210804190019-f964ff605595 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/wire v0.5.0 // indirect
github.com/googleapis/gax-go/v2 v2.2.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
- github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 // indirect
+ github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
+ github.com/kr/text v0.2.0 // indirect
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20210210170715-a8dfcb80d3a7 // indirect
github.com/lightstep/lightstep-tracer-go v0.25.0 // indirect
github.com/mattn/go-ieproxy v0.0.6 // indirect
@@ -88,8 +89,8 @@ require (
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
- github.com/prometheus/common v0.32.1 // indirect
- github.com/prometheus/procfs v0.7.3 // indirect
+ github.com/prometheus/common v0.37.0 // indirect
+ github.com/prometheus/procfs v0.8.0 // indirect
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
github.com/shabbyrobe/gocovmerge v0.0.0-20190829150210-3e036491d500 // indirect
github.com/shirou/gopsutil/v3 v3.21.2 // indirect
@@ -97,7 +98,7 @@ require (
github.com/tinylib/msgp v1.1.2 // indirect
github.com/tklauser/go-sysconf v0.3.4 // indirect
github.com/tklauser/numcpus v0.2.1 // indirect
- github.com/uber/jaeger-client-go v2.29.1+incompatible // indirect
+ github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
@@ -106,7 +107,7 @@ require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
- golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
+ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
@@ -116,3 +117,20 @@ require (
gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+
+exclude (
+ // CVE-2019-0205
+ github.com/apache/thrift v0.12.0
+ github.com/apache/thrift v0.13.0
+
+ // CVE-2020-28483
+ github.com/gin-gonic/gin v1.4.0
+ github.com/gin-gonic/gin v1.6.3
+
+ // CVE-2021-42576
+ github.com/microcosm-cc/bluemonday v1.0.2
+ github.com/nats-io/jwt v0.3.0
+
+ // CVE-2020-26892
+ github.com/nats-io/nats-server/v2 v2.1.2
+)
diff --git a/workhorse/go.sum b/workhorse/go.sum
index ec1ee3eac11..d143f62f812 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -145,8 +145,8 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
-github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
+github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
@@ -197,8 +197,6 @@ github.com/alexbrainman/sspi v0.0.0-20180125232955-4729b3d4d858/go.mod h1:976q2E
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -283,13 +281,15 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
+github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/client9/reopen v1.0.0 h1:8tpLVR74DLpLObrn2KvsyxJY++2iORGR17WLUdSzUws=
github.com/client9/reopen v1.0.0/go.mod h1:caXVCEr+lUtoN1FlsRiOWdfQtdRHIYfcb0ai8qKWtkQ=
github.com/cloudflare/tableflip v0.0.0-20190329062924-8392f1641731/go.mod h1:erh4dYezoMVbIa52pi7i1Du7+cXOgqNuTamt10qvMoA=
-github.com/cloudflare/tableflip v1.2.2 h1:WkhiowHlg0nZuH7Y2beLVIZDfxtSvKta1f22PEgUN7w=
github.com/cloudflare/tableflip v1.2.2/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB37pUFMmv7j2E=
+github.com/cloudflare/tableflip v1.2.3 h1:8I+B99QnnEWPHOY3fWipwVKxS70LGgUsslG7CSfmHMw=
+github.com/cloudflare/tableflip v1.2.3/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB37pUFMmv7j2E=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -297,12 +297,14 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/containerd/cgroups v0.0.0-20201118023556-2819c83ced99/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
+github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -361,6 +363,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
+github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
@@ -373,6 +376,7 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
+github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -388,10 +392,7 @@ github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJ
github.com/getsentry/sentry-go v0.10.0/go.mod h1:kELm/9iCblqUYh+ZRML7PNdCvEuw24wBvJPYyi86cws=
github.com/getsentry/sentry-go v0.13.0/go.mod h1:EOsfu5ZdvKPfeHYV6pTVQnsjfp30+XA7//UooKNumH0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
-github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.3/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/git-lfs/git-lfs v1.5.1-0.20210304194248-2e1d981afbe3/go.mod h1:8Xqs4mqL7o6xEnaXckIgELARTeK7RYtm3pBab7S79Js=
@@ -405,7 +406,9 @@ github.com/git-lfs/wildmatch v1.0.4/go.mod h1:SdHAGnApDpnFYQ0vAxbniWR0sn7yLJ3QXo
github.com/git-lfs/wildmatch/v2 v2.0.1/go.mod h1:EVqonpk9mXbREP3N8UkwoWdrF249uHpCUo5CPXY81gw=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
+github.com/go-enry/go-enry/v2 v2.8.2/go.mod h1:GVzIiAytiS5uT/QiuakK7TF1u4xDab87Y8V5EJRpsIQ=
github.com/go-enry/go-license-detector/v4 v4.3.0/go.mod h1:HaM4wdNxSlz/9Gw0uVOKSQS5JVFqf2Pk8xUPEn6bldI=
+github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
@@ -422,16 +425,17 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -526,8 +530,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-replayers/grpcreplay v1.0.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
@@ -633,8 +638,9 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 h1:Y4V+SFe7d3iH+9pJCoeWIOS5/xBJIFsltS7E+KJSsJY=
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
+github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
+github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hhatto/gorst v0.0.0-20181029133204-ca9f730cac5b/go.mod h1:HmaZGXHdSwQh1jnUlBGN2BeEYOHACLVGzYOXCbsLvxY=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -664,6 +670,7 @@ github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
+github.com/jackc/pgconn v1.12.1/go.mod h1:ZkhRC59Llhrq3oSfrikvwQ5NaxYExr6twkdkMLaKono=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
@@ -677,6 +684,7 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
+github.com/jackc/pgproto3/v2 v2.3.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
@@ -684,12 +692,14 @@ github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrU
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
+github.com/jackc/pgtype v1.11.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
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.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M=
github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
+github.com/jackc/pgx/v4 v4.16.1/go.mod h1:SIhx0D5hoADaiXZVyv+3gSm3LCIIINTVO0PficsvWGQ=
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=
@@ -747,6 +757,7 @@ github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiD
github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
+github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@@ -833,7 +844,6 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg=
github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ=
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
-github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a/go.mod h1:v8eSC2SMp9/7FTKUncp7fH9IwPfw+ysMObcEz5FWheQ=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@@ -863,14 +873,10 @@ github.com/montanaflynn/stats v0.0.0-20151014174947-eeaced052adb/go.mod h1:wL8QJ
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/neurosnap/sentences v1.0.6/go.mod h1:pg1IapvYpWCJJm/Etxeh0+gtMf1rI1STY9S7eUCPbDc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -916,6 +922,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP
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.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
+github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
@@ -924,6 +931,7 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pires/go-proxyproto v0.5.0/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
+github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.0.0-20170505043639-c605e284fe17/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -942,8 +950,9 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU=
+github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -957,16 +966,18 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
+github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
+github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rafaeljusto/redigomock/v3 v3.1.1 h1:SdWE9v+SPy3x6G5hS3aofIJgHJY3OdBJ0BdUTk4dYbA=
github.com/rafaeljusto/redigomock/v3 v3.1.1/go.mod h1:F9zPqz8rMriScZkPtUiLJoLruYcpGo/XXREpeyasREM=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -1014,8 +1025,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -1071,12 +1083,12 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-client-go v2.27.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
-github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4=
github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
+github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
-github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
@@ -1112,17 +1124,21 @@ github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wK
gitlab.com/gitlab-org/gitaly v1.68.0 h1:VlcJs1+PrhW7lqJUU7Fh1q8FMJujmbbivdfde/cwB98=
gitlab.com/gitlab-org/gitaly v1.68.0/go.mod h1:/pCsB918Zu5wFchZ9hLYin9WkJ2yQqdVNz0zlv5HbXg=
gitlab.com/gitlab-org/gitaly/v14 v14.0.0-rc1/go.mod h1:4Cz8tOAyueSZX5o6gYum1F/unupaOclxqETPcg4ODvQ=
-gitlab.com/gitlab-org/gitaly/v15 v15.1.2 h1:6NcpZENpvV4ialIjtrPuxCFHLn6VOrE3mJ9rd/4DuzU=
-gitlab.com/gitlab-org/gitaly/v15 v15.1.2/go.mod h1:fZSeTXPLtbmTxNRk9AECM2shtJ6JNzIiLxAgknWBdT4=
+gitlab.com/gitlab-org/gitaly/v14 v14.9.0-rc5.0.20220329111719-51da8bc17059/go.mod h1:uX1qhFKBDuPqATlpMcFL2dKDiX8D/tbUg7CYWx7OXt4=
+gitlab.com/gitlab-org/gitaly/v15 v15.2.2 h1:/hSbAhBqRrT6Epc35k83qFwwVbKottNY6wDFr+5DYQo=
+gitlab.com/gitlab-org/gitaly/v15 v15.2.2/go.mod h1:WjitFL44l9ovitGC4OvSuGwfeq0VpHUbHS6sDw13LV8=
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20201117050822-3f9890ef73dc/go.mod h1:5QSTbpAHY2v0iIH5uHh2KA9w7sPUqPmnLjDApI/sv1U=
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20210720163109-50da611814d2/go.mod h1:QWDYBwuy24qGMandtCngLRPzFgnGPg6LSNoJWPKmJMc=
+gitlab.com/gitlab-org/gitlab-shell/v14 v14.8.0/go.mod h1:Z1S5MihpEmtA7GDXGsU0kUf1nzm7zr8w6bP+uXRnxaw=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE=
gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c/go.mod h1:rYhLgfrbEcyfinG+R3EvKu6bZSsmwQqcXzLfHWSfUKM=
gitlab.com/gitlab-org/labkit v0.0.0-20200908084045-45895e129029/go.mod h1:SNfxkfUwVNECgtmluVayv0GWFgEjjBs5AzgsowPQuo0=
gitlab.com/gitlab-org/labkit v1.0.0/go.mod h1:nohrYTSLDnZix0ebXZrbZJjymRar8HeV2roWL5/jw2U=
gitlab.com/gitlab-org/labkit v1.4.1/go.mod h1:x5JO5uvdX4t6e/TZXLXZnFL5AcKz2uLLd3uKXZcuO4k=
+gitlab.com/gitlab-org/labkit v1.5.0/go.mod h1:1ZuVZpjSpCKUgjLx8P6jzkkQFxJI1thUKr6yKV3p0vY=
gitlab.com/gitlab-org/labkit v1.14.0/go.mod h1:bcxc4ZpAC+WyACgyKl7FcvT2XXAbl8CrzN6UY+w8cMc=
+gitlab.com/gitlab-org/labkit v1.15.0/go.mod h1:bcxc4ZpAC+WyACgyKl7FcvT2XXAbl8CrzN6UY+w8cMc=
gitlab.com/gitlab-org/labkit v1.16.0 h1:Vm3NAMZ8RqAunXlvPWby3GJ2R35vsYGP6Uu0YjyMIlY=
gitlab.com/gitlab-org/labkit v1.16.0/go.mod h1:bcxc4ZpAC+WyACgyKl7FcvT2XXAbl8CrzN6UY+w8cMc=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -1149,8 +1165,9 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
-go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
+go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1446,6 +1463,7 @@ golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1459,8 +1477,9 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
-golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1762,8 +1781,10 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
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 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
+google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w=
+google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
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=
@@ -1778,8 +1799,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/DataDog/dd-trace-go.v1 v1.7.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg=
gopkg.in/DataDog/dd-trace-go.v1 v1.30.0/go.mod h1:SnKViq44dv/0gjl9RpkP0Y2G3BJSRkp6eYdCSu39iI8=
gopkg.in/DataDog/dd-trace-go.v1 v1.32.0 h1:DkD0plWEVUB8v/Ru6kRBW30Hy/fRNBC8hPdcExuBZMc=
@@ -1796,8 +1818,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
-gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
-gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@@ -1835,8 +1855,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.3.2 h1:ytYb4rOqyp1TSa2EPvNVwtPQJctSELKaMyLfqNP4+34=
-honnef.co/go/tools v0.3.2/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
+honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA=
+honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/yarn.lock b/yarn.lock
index 45b79207b6b..c143f007aec 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,17 @@
# yarn lockfile v1
+"@_ueberdosis/prosemirror-tables@1.1.3", "@_ueberdosis/prosemirror-tables@^1.1.3":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@_ueberdosis/prosemirror-tables/-/prosemirror-tables-1.1.3.tgz#56fdbc8b1d6ec43e7b7beb21e213c131eec451cd"
+ integrity sha512-su3pbFi1DT89g6Cuh72TE0MWWKHmWgHcQJ3ODRkm6XfIppWaGpU49t02ur3sgJc7hUhfQXjB93aSkDgOmIii2w==
+ dependencies:
+ prosemirror-keymap "^1.1.2"
+ prosemirror-model "^1.8.1"
+ prosemirror-state "^1.3.1"
+ prosemirror-transform "^1.2.1"
+ prosemirror-view "^1.13.3"
+
"@ampproject/remapping@^2.1.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34"
@@ -27,14 +38,7 @@
tslib "^2.3.0"
zen-observable-ts "^1.2.0"
-"@babel/code-frame@7.12.11":
- version "7.12.11"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
- integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
- dependencies:
- "@babel/highlight" "^7.10.4"
-
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.7":
+"@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==
@@ -46,7 +50,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab"
integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==
-"@babel/core@^7.1.0", "@babel/core@^7.17.0", "@babel/core@^7.18.5", "@babel/core@^7.7.5":
+"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.17.0", "@babel/core@^7.18.5", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
version "7.18.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.5.tgz#c597fa680e58d571c28dda9827669c78cdd7f000"
integrity sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==
@@ -83,7 +87,7 @@
dependencies:
eslint-rule-composer "^0.3.0"
-"@babel/generator@^7.18.2":
+"@babel/generator@^7.18.2", "@babel/generator@^7.7.2":
version "7.18.2"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d"
integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==
@@ -289,7 +293,7 @@
"@babel/traverse" "^7.18.2"
"@babel/types" "^7.18.2"
-"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7":
+"@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==
@@ -298,7 +302,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8", "@babel/parser@^7.18.5":
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8", "@babel/parser@^7.18.5":
version "7.18.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.5.tgz#337062363436a893a2d22faa60be5bb37091c83c"
integrity sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==
@@ -559,13 +563,20 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
-"@babel/plugin-syntax-top-level-await@^7.14.5":
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
+"@babel/plugin-syntax-typescript@^7.7.2":
+ version "7.17.10"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.10.tgz#80031e6042cad6a95ed753f672ebd23c30933195"
+ integrity sha512-xJefea1DWXW09pW4Tm9bjwVlPDyYA2it3fWlmEjpYz6alPvTUjL0EOzNzI/FEOyI3r4/J7uVH5UqKgl1TQ5hqQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
"@babel/plugin-transform-arrow-functions@^7.17.12":
version "7.17.12"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz#dddd783b473b1b1537ef46423e3944ff24898c45"
@@ -934,7 +945,7 @@
"@babel/parser" "^7.16.7"
"@babel/types" "^7.16.7"
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.18.5":
+"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.18.5", "@babel/traverse@^7.7.2":
version "7.18.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.5.tgz#94a8195ad9642801837988ab77f36e992d9a20cd"
integrity sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==
@@ -968,14 +979,6 @@
resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz#fe364f025ba74f6de6c837a84ef44bdb1d61e68f"
integrity sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==
-"@cnakazawa/watch@^1.0.3":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
- integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==
- dependencies:
- exec-sh "^0.3.2"
- minimist "^1.2.0"
-
"@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"
@@ -996,19 +999,19 @@
ts-node "^9"
tslib "^2"
-"@eslint/eslintrc@^0.4.3":
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
- integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
+"@eslint/eslintrc@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
+ integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
dependencies:
ajv "^6.12.4"
- debug "^4.1.1"
- espree "^7.3.0"
- globals "^13.9.0"
- ignore "^4.0.6"
+ debug "^4.3.2"
+ espree "^9.3.2"
+ globals "^13.15.0"
+ ignore "^5.2.0"
import-fresh "^3.2.1"
- js-yaml "^3.13.1"
- minimatch "^3.0.4"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@gitlab/at.js@1.5.7":
@@ -1016,10 +1019,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@13.1.0":
- version "13.1.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-13.1.0.tgz#d0698251e601d8732b6db994c8ebd8c37be404fa"
- integrity sha512-/eWbTomAipyp/nbaNLq8aU1IcqG029+clvUOgkckm704q38G0/r6KHgcuXvxWj2erzwcEveEXXyilZAaTQquRA==
+"@gitlab/eslint-plugin@16.0.0":
+ version "16.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-16.0.0.tgz#83b71bb3f749c6e52138d2c1c17ac623e7b2e3db"
+ integrity sha512-2n7geoRPkeMAq4GCqyvFzcTgcSrTM7pdCOxfcqIeuTmh/PFGhh+m7YC+YC4enhGOCN8lo08buLZhXkSgWiHSqA==
dependencies:
"@babel/core" "^7.17.0"
"@babel/eslint-parser" "^7.17.0"
@@ -1031,7 +1034,7 @@
eslint-plugin-jest "^23.8.2"
eslint-plugin-promise "^4.2.1"
eslint-plugin-unicorn "^40.1.0"
- eslint-plugin-vue "^8.5.0"
+ eslint-plugin-vue "^9.3.0"
lodash "^4.17.21"
"@gitlab/favicon-overlay@2.0.0":
@@ -1048,19 +1051,19 @@
stylelint-declaration-strict-value "1.8.0"
stylelint-scss "4.2.0"
-"@gitlab/svgs@2.28.0":
- version "2.28.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.28.0.tgz#a22ad2a4716db18af993d544a628d1d1f128aa7e"
- integrity sha512-V1CO91bcYVYuYiYrc6EV02BEzutp06SclzRtC6CRvGoz8mf+qEh7L25a7GxpJyW7hbLo+xajY+IJYhKNmB/qVg==
+"@gitlab/svgs@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.1.0.tgz#0108498a17e2f79d16158015db0be764b406cc09"
+ integrity sha512-kZ45VTQOgLdwQCLRSj7+aohF+6AUnAaoucR1CFY/6DPDLnNNGeflwsCLN0sFBKwx42HLxFfNwvDmKOMLdSQg5A==
-"@gitlab/ui@42.22.0":
- version "42.22.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-42.22.0.tgz#22102109cbe64884fbbc69993f1c517962d78bae"
- integrity sha512-I5n8FeRRgLVyj4FpnXbUUBElTHH1yhCyNarSwcf/qIeR4LeZIOm7Dm5wLAahUlGsStaq0SXlBguImtTRL7Re+g==
+"@gitlab/ui@43.6.0":
+ version "43.6.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-43.6.0.tgz#95f85f405455aa95ee5b68b5072bcbe1bd22f375"
+ integrity sha512-d0ebKUU7BBBCVoblEA6iWbD3BfR4t0YsDbC7UlN7nyR++MhojCmaML+L9MuDeJGpd0DWR0HLxAGWawtcdeZErw==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.20.1"
- dompurify "^2.3.9"
+ dompurify "^2.3.10"
echarts "^5.3.2"
iframe-resizer "^4.3.2"
lodash "^4.17.20"
@@ -1072,10 +1075,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.7.3.tgz#9ea641146436da388ffbad25d7f2abe0df52c235"
integrity sha512-NMV++7Ew1FSBDN1xiZaauU9tfeSfgDHcOLpn+8bGpP+O5orUPm2Eu66R5eC5gkjBPaXosNAxNWtriee+aFk4+g==
-"@graphql-eslint/eslint-plugin@3.10.6":
- version "3.10.6"
- resolved "https://registry.yarnpkg.com/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.10.6.tgz#4d5748fade6c11d74aeff9a99d6e38d2ed8f6310"
- integrity sha512-rxGSrKVsDHCuZRvP81ElgtCs0sikdhcHqQySiyhir4G+VhiNlPZ7SQJWrXm9JJEAeB0wQ50kabvse5NRk0hqog==
+"@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==
dependencies:
"@babel/code-frame" "^7.16.7"
"@graphql-tools/code-file-loader" "^7.2.14"
@@ -1245,19 +1248,24 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950"
integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==
-"@humanwhocodes/config-array@^0.5.0":
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
- integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+"@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==
dependencies:
- "@humanwhocodes/object-schema" "^1.2.0"
+ "@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
minimatch "^3.0.4"
-"@humanwhocodes/object-schema@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
- integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
+"@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/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@iarna/toml@^2.2.5":
version "2.2.5"
@@ -1280,167 +1288,165 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
-"@jest/console@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.5.2.tgz#94fc4865b1abed7c352b5e21e6c57be4b95604a6"
- integrity sha512-lJELzKINpF1v74DXHbCRIkQ/+nUV1M+ntj+X1J8LxCgpmJZjfLmhFejiMSbjjD66fayxl5Z06tbs3HMyuik6rw==
+"@jest/console@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba"
+ integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
chalk "^4.0.0"
- jest-message-util "^26.5.2"
- jest-util "^26.5.2"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
slash "^3.0.0"
-"@jest/core@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.5.2.tgz#e39f14676f4ba4632ecabfdc374071ab22131f22"
- integrity sha512-LLTo1LQMg7eJjG/+P1NYqFof2B25EV1EqzD5FonklihG4UJKiK2JBIvWonunws6W7e+DhNLoFD+g05tCY03eyA==
+"@jest/core@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626"
+ integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==
dependencies:
- "@jest/console" "^26.5.2"
- "@jest/reporters" "^26.5.2"
- "@jest/test-result" "^26.5.2"
- "@jest/transform" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/console" "^27.5.1"
+ "@jest/reporters" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
ansi-escapes "^4.2.1"
chalk "^4.0.0"
+ emittery "^0.8.1"
exit "^0.1.2"
- graceful-fs "^4.2.4"
- jest-changed-files "^26.5.2"
- jest-config "^26.5.2"
- jest-haste-map "^26.5.2"
- jest-message-util "^26.5.2"
- jest-regex-util "^26.0.0"
- jest-resolve "^26.5.2"
- jest-resolve-dependencies "^26.5.2"
- jest-runner "^26.5.2"
- jest-runtime "^26.5.2"
- jest-snapshot "^26.5.2"
- jest-util "^26.5.2"
- jest-validate "^26.5.2"
- jest-watcher "^26.5.2"
- micromatch "^4.0.2"
- p-each-series "^2.1.0"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^27.5.1"
+ jest-config "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-resolve-dependencies "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ jest-watcher "^27.5.1"
+ micromatch "^4.0.4"
rimraf "^3.0.0"
slash "^3.0.0"
strip-ansi "^6.0.0"
-"@jest/environment@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.5.2.tgz#eba3cfc698f6e03739628f699c28e8a07f5e65fe"
- integrity sha512-YjhCD/Zhkz0/1vdlS/QN6QmuUdDkpgBdK4SdiVg4Y19e29g4VQYN5Xg8+YuHjdoWGY7wJHMxc79uDTeTOy9Ngw==
+"@jest/environment@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
+ integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==
dependencies:
- "@jest/fake-timers" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
- jest-mock "^26.5.2"
+ jest-mock "^27.5.1"
-"@jest/fake-timers@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.5.2.tgz#1291ac81680ceb0dc7daa1f92c059307eea6400a"
- integrity sha512-09Hn5Oraqt36V1akxQeWMVL0fR9c6PnEhpgLaYvREXZJAh2H2Y+QLCsl0g7uMoJeoWJAuz4tozk1prbR1Fc1sw==
+"@jest/fake-timers@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
+ integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==
dependencies:
- "@jest/types" "^26.5.2"
- "@sinonjs/fake-timers" "^6.0.1"
+ "@jest/types" "^27.5.1"
+ "@sinonjs/fake-timers" "^8.0.1"
"@types/node" "*"
- jest-message-util "^26.5.2"
- jest-mock "^26.5.2"
- jest-util "^26.5.2"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
-"@jest/globals@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.5.2.tgz#c333f82c29e19ecb609a75d1a532915a5c956c59"
- integrity sha512-9PmnFsAUJxpPt1s/stq02acS1YHliVBDNfAWMe1bwdRr1iTCfhbNt3ERQXrO/ZfZSweftoA26Q/2yhSVSWQ3sw==
+"@jest/globals@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b"
+ integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==
dependencies:
- "@jest/environment" "^26.5.2"
- "@jest/types" "^26.5.2"
- expect "^26.5.2"
+ "@jest/environment" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ expect "^27.5.1"
-"@jest/reporters@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.5.2.tgz#0f1c900c6af712b46853d9d486c9c0382e4050f6"
- integrity sha512-zvq6Wvy6MmJq/0QY0YfOPb49CXKSf42wkJbrBPkeypVa8I+XDxijvFuywo6TJBX/ILPrdrlE/FW9vJZh6Rf9vA==
+"@jest/reporters@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04"
+ integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==
dependencies:
"@bcoe/v8-coverage" "^0.2.3"
- "@jest/console" "^26.5.2"
- "@jest/test-result" "^26.5.2"
- "@jest/transform" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/console" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
chalk "^4.0.0"
collect-v8-coverage "^1.0.0"
exit "^0.1.2"
glob "^7.1.2"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
istanbul-lib-coverage "^3.0.0"
- istanbul-lib-instrument "^4.0.3"
+ istanbul-lib-instrument "^5.1.0"
istanbul-lib-report "^3.0.0"
istanbul-lib-source-maps "^4.0.0"
- istanbul-reports "^3.0.2"
- jest-haste-map "^26.5.2"
- jest-resolve "^26.5.2"
- jest-util "^26.5.2"
- jest-worker "^26.5.0"
+ istanbul-reports "^3.1.3"
+ jest-haste-map "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
slash "^3.0.0"
source-map "^0.6.0"
string-length "^4.0.1"
terminal-link "^2.0.0"
- v8-to-istanbul "^5.0.1"
- optionalDependencies:
- node-notifier "^8.0.0"
+ v8-to-istanbul "^8.1.0"
-"@jest/source-map@^26.5.0":
- version "26.5.0"
- resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.5.0.tgz#98792457c85bdd902365cd2847b58fff05d96367"
- integrity sha512-jWAw9ZwYHJMe9eZq/WrsHlwF8E3hM9gynlcDpOyCb9bR8wEd9ZNBZCi7/jZyzHxC7t3thZ10gO2IDhu0bPKS5g==
+"@jest/source-map@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
+ integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==
dependencies:
callsites "^3.0.0"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
source-map "^0.6.0"
-"@jest/test-result@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.5.2.tgz#cc1a44cfd4db2ecee3fb0bc4e9fe087aa54b5230"
- integrity sha512-E/Zp6LURJEGSCWpoMGmCFuuEI1OWuI3hmZwmULV0GsgJBh7u0rwqioxhRU95euUuviqBDN8ruX/vP/4bwYolXw==
+"@jest/test-result@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb"
+ integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==
dependencies:
- "@jest/console" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/console" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/istanbul-lib-coverage" "^2.0.0"
collect-v8-coverage "^1.0.0"
-"@jest/test-sequencer@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.5.2.tgz#c4559c7e134b27b020317303ee5399bf62917a4b"
- integrity sha512-XmGEh7hh07H2B8mHLFCIgr7gA5Y6Hw1ZATIsbz2fOhpnQ5AnQtZk0gmP0Q5/+mVB2xygO64tVFQxOajzoptkNA==
+"@jest/test-sequencer@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b"
+ integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==
dependencies:
- "@jest/test-result" "^26.5.2"
- graceful-fs "^4.2.4"
- jest-haste-map "^26.5.2"
- jest-runner "^26.5.2"
- jest-runtime "^26.5.2"
+ "@jest/test-result" "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-runtime "^27.5.1"
-"@jest/transform@^26.5.2":
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.5.2.tgz#6a0033a1d24316a1c75184d010d864f2c681bef5"
- integrity sha512-AUNjvexh+APhhmS8S+KboPz+D3pCxPvEAGduffaAJYxIFxGi/ytZQkrqcKDUU0ERBAo5R7087fyOYr2oms1seg==
+"@jest/transform@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409"
+ integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==
dependencies:
"@babel/core" "^7.1.0"
- "@jest/types" "^26.5.2"
- babel-plugin-istanbul "^6.0.0"
+ "@jest/types" "^27.5.1"
+ babel-plugin-istanbul "^6.1.1"
chalk "^4.0.0"
convert-source-map "^1.4.0"
fast-json-stable-stringify "^2.0.0"
- graceful-fs "^4.2.4"
- jest-haste-map "^26.5.2"
- jest-regex-util "^26.0.0"
- jest-util "^26.5.2"
- micromatch "^4.0.2"
- pirates "^4.0.1"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-util "^27.5.1"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
slash "^3.0.0"
source-map "^0.6.1"
write-file-atomic "^3.0.0"
-"@jest/types@^26.5.2", "@jest/types@^26.6.2":
+"@jest/types@^26.6.2":
version "26.6.2"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==
@@ -1451,6 +1457,17 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
+"@jest/types@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80"
+ integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
"@jridgewell/gen-mapping@^0.3.0":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9"
@@ -1607,11 +1624,6 @@
"@sentry/types" "5.30.0"
tslib "^1.9.3"
-"@sindresorhus/is@^0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
- integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
-
"@sinonjs/commons@^1.7.0":
version "1.8.1"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
@@ -1619,10 +1631,10 @@
dependencies:
type-detect "4.0.8"
-"@sinonjs/fake-timers@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40"
- integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==
+"@sinonjs/fake-timers@^8.0.1":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
+ integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==
dependencies:
"@sinonjs/commons" "^1.7.0"
@@ -1631,13 +1643,6 @@
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.60.tgz#2043877fabb7eb986fcb61b67ee480afbb29f4f0"
integrity sha512-T+MvM8SUF7daA279hyQgwmva3J5LvPqwgQ/mWwxdVshehOQIPLUd310I0c6x6nZ0F/x4UjDWgRWzAqy6NLwV1w==
-"@szmarczak/http-timer@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
- integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
- dependencies:
- defer-to-connect "^1.0.1"
-
"@testing-library/dom@^7.16.2":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.5.tgz#862124eec8c37ad184716379f09742476b23815d"
@@ -1651,238 +1656,230 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@tiptap/core@^2.0.0-beta.176":
- version "2.0.0-beta.176"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.176.tgz#a8bb9b57d2ecf77b6cd02340324626ef3e336a15"
- integrity sha512-Gs/+yUYTNpt8PnclEHbfBnY56D/9PpKTyzrg8VZwCFK9S69aVD2dqLsYs/Gn+EjzKImXRAiqSe1/FWcNEDkmCg==
- dependencies:
- "@types/prosemirror-commands" "^1.0.4"
- "@types/prosemirror-keymap" "^1.0.4"
- "@types/prosemirror-model" "^1.16.0"
- "@types/prosemirror-schema-list" "^1.0.3"
- "@types/prosemirror-state" "^1.2.8"
- "@types/prosemirror-transform" "^1.1.5"
- "@types/prosemirror-view" "^1.23.1"
- prosemirror-commands "^1.2.1"
- prosemirror-keymap "^1.1.5"
- prosemirror-model "^1.16.1"
- prosemirror-schema-list "^1.1.6"
- prosemirror-state "^1.3.4"
- prosemirror-transform "^1.3.3"
- prosemirror-view "^1.23.6"
-
-"@tiptap/extension-blockquote@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.26.tgz#e5ae4b7bd9376db37407a23e22080c7b11287f3b"
- integrity sha512-A6yjcYovONJfOjQFk6vDYXswaCdCtCwjL7w9VTB0R2DLTuJvvRt9DWN0IDcMrj5G+aMgDq4GUUTitv+2Y8krDg==
-
-"@tiptap/extension-bold@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.26.tgz#aa1c7850df28cec8e0614fde437183bd4ae3e66b"
- integrity sha512-pnO0I5sEQM3pmowjMGQ74adLzvc6HqGyLyqMizaGMicPu9uTYlSdId+qckYEEgPwPMaEShtv2Vg+ZHs7KVqfcg==
-
-"@tiptap/extension-bubble-menu@^2.0.0-beta.56":
- version "2.0.0-beta.56"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.56.tgz#d99cb673610a3af7e12444f4538463c7c58bfa04"
- integrity sha512-nZozwauICdaNPmDPrSn1JFd/9/2rLtK8i2vBOcqxWHObVROvu8ZlJspnrJv23vS6P7/ZO3e/QLVHpnn+1yVq3g==
- dependencies:
- prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.6"
+"@tiptap/core@^2.0.0-beta.182":
+ version "2.0.0-beta.182"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.182.tgz#d2001e9b765adda95e15d171479860a3349e2d04"
+ integrity sha512-MZGkMGnVnWhBzjvpBNwQ9zBz38ndi3Irbf90uCTSArR0kaCVkW4vmyuPuOXd+0SO8Yv/l5oyDdOCpaG3rnQYfw==
+ dependencies:
+ prosemirror-commands "1.3.0"
+ prosemirror-keymap "1.2.0"
+ prosemirror-model "1.18.1"
+ prosemirror-schema-list "1.2.0"
+ prosemirror-state "1.4.1"
+ prosemirror-transform "1.6.0"
+ prosemirror-view "1.26.2"
+
+"@tiptap/extension-blockquote@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.29.tgz#6f1c4b17efa6457c7776f32d0807e96d848d4389"
+ integrity sha512-zMYT5TtpKWav9VhTn4JLyMvXmhEdbD6on0MdhcTjRm0I5ugyR4ZbJwh2aelM7G9DZVYzB8jZU18OSDJmo7Af7w==
+
+"@tiptap/extension-bold@^2.0.0-beta.28":
+ version "2.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.28.tgz#cf67c264a80434ffb2368f3dd37cf357ae0c2064"
+ integrity sha512-DY8GOzw9xjmTFrnvTbgHUNxTnDfKrkDgrhe0SUvdkT2udntWp8umPdhPiD3vczLgHOJw6tX68qMRjbsR1ZPcHQ==
+
+"@tiptap/extension-bubble-menu@^2.0.0-beta.61":
+ version "2.0.0-beta.61"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.61.tgz#cc61ce8b094fdbcec58f44f0fa39172a726c024c"
+ integrity sha512-T3Yx+y1sUnXAJjK1CUfsQewSxOpDca9KzKqN2H9c9RZ9UlorR9XmZg6YYW7m9a7adeihj+o3cCO9jRd8dV+nnA==
+ dependencies:
+ prosemirror-state "1.4.1"
+ prosemirror-view "1.26.2"
tippy.js "^6.3.7"
-"@tiptap/extension-bullet-list@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.26.tgz#b42126d2d984c04041b14037e8d3ec1bcf16e7ec"
- integrity sha512-1n5HV8gY1tLjPk4x48nva6SZlFHoPlRfF6pqSu9JcJxPO7FUSPxUokuz4swYNe0LRrtykfyNz44dUcxKVhoFow==
+"@tiptap/extension-bullet-list@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.29.tgz#640883e4fffc1a86c7cbd78792688e7edee5ee41"
+ integrity sha512-R8VB2l1ZB6VeGWx/t/04nBS5Wg3qjIDEZCpPihj2fccJOw99Lu0Ub2UJg/SfdGmeNNpBh4ZYYFv1g/XjyzlXKg==
-"@tiptap/extension-code-block-lowlight@2.0.0-beta.68":
- version "2.0.0-beta.68"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.68.tgz#c0da8c327eb2b49d808e3ead303f6ff6b0203e05"
- integrity sha512-927vw4DJ5pq3lYOdJbBrCjJZ/YsbsEzWkb7SwRsaztDXcgsF2z8gt6dy7onXMaqm5rDx6eNofLPdhUyLCswW8Q==
+"@tiptap/extension-code-block-lowlight@2.0.0-beta.73":
+ version "2.0.0-beta.73"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.73.tgz#3f4711fadb1a1f51efbf58389216e6c8bca83d84"
+ integrity sha512-57jqDd2jzQPlYKPtnDIlwwaZrHLlgUVCe+NIWgK6bpP1yF4bUE3Dguqw1owN6oBWBf0kQnm0TQjbn50B/wnUjQ==
dependencies:
- "@tiptap/extension-code-block" "^2.0.0-beta.37"
+ "@tiptap/extension-code-block" "^2.0.0-beta.42"
"@types/lowlight" "^0.0.3"
- lowlight "^1.20.0"
- prosemirror-model "^1.16.1"
- prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.6"
+ prosemirror-model "1.18.1"
+ prosemirror-state "1.4.1"
+ prosemirror-view "1.26.2"
-"@tiptap/extension-code-block@^2.0.0-beta.37":
- version "2.0.0-beta.37"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.37.tgz#c07c007248a21d9e0434458fd05c363b7078227f"
- integrity sha512-mJAM+PHaNoKRYwM3D36lZ51/aoPxxvZNQn3UBnZ6G7l0ZJSgB3JvBEzqK6S8nNFeYIIxGwv4QF6vXe4MG9ie2g==
+"@tiptap/extension-code-block@^2.0.0-beta.42":
+ version "2.0.0-beta.42"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.42.tgz#2abfd92eb22399fa542aafb3b76dddfb41d87ab5"
+ integrity sha512-4wzLup4mI8w9ypIceekUV/8g41cQIPn31qs1iC9u1/JuTkjMj/tA+TFUyp6IMugLxoI/P2DlTztU6/6m7n9DyQ==
dependencies:
- prosemirror-state "^1.3.4"
+ prosemirror-state "1.4.1"
-"@tiptap/extension-code@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.26.tgz#bbfa600a252ee2cded6947b56b6c4c33d998e53a"
- integrity sha512-QcFWdEFfbJ1n5UFFBD17QPPAJ3J5p/b7XV484u0shCzywO7aNPV32QeHy1z0eMoyZtCbOWf6hg/a7Ugv8IwpHw==
+"@tiptap/extension-code@^2.0.0-beta.28":
+ version "2.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.28.tgz#a22c0e873497ac0bbcd77e4a855322f8591f954e"
+ integrity sha512-QPJ2Gwb1+3NgcC1ZIhvVcb+FsnWWDu5VZXTKXM4mz892i9V2x48uHg5anPiUV6pcolXsW1F5VNbXIHGTUUO6CQ==
-"@tiptap/extension-document@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.15.tgz#5d17a0289244a913ab2ef08e8495a1e46950711e"
- integrity sha512-ypENC+xUYD5m2t+KOKNYqyXnanXd5fxyIyhR1qeEEwwQwMXGNrO3kCH6O4mIDCpy+/WqHvVay2tV5dVsXnvY8w==
+"@tiptap/extension-document@^2.0.0-beta.17":
+ version "2.0.0-beta.17"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.17.tgz#ded4182dd860762bcf41c588f712d83908c472a3"
+ integrity sha512-L6sg0FNchbtIpQkCSjMmItVGs3/vep8Fq56WRtDc1wBSGUSmtHaxQG7F2FZLnNIUMuvzVMRD81m2vYG73WkY6A==
-"@tiptap/extension-dropcursor@^2.0.0-beta.25":
- version "2.0.0-beta.25"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.25.tgz#962f290a200259533a26194daca5a4b4a53e72d3"
- integrity sha512-GYf5s6dkZtsDy+TEkrQK6kLbfbitG4qnk02D+FlhlJMI/Nnx8rYCRJbwEHDdqrfX7XwZzULMqqqHvzxZYrEeNg==
+"@tiptap/extension-dropcursor@^2.0.0-beta.28":
+ version "2.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.28.tgz#55013b1356fd589990003c83bb719d7b4ccad46d"
+ integrity sha512-t61/pALhkV7gORM+KM2M7hypNfJt+bHgk1Lk7FrWqKXQCkVGQzdOgPfnuFxpzi8kC2m7jQxvZC3S+4oBBKhkPA==
dependencies:
- "@types/prosemirror-dropcursor" "^1.0.3"
- prosemirror-dropcursor "^1.4.0"
+ prosemirror-dropcursor "^1.5.0"
-"@tiptap/extension-floating-menu@^2.0.0-beta.51":
- version "2.0.0-beta.51"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.51.tgz#a1e53fd1c1d2ac00025d7f094d2b62eb08e81902"
- integrity sha512-rEe7jADK9xr2n2LJsrGEN3Dz7sEGC1JT/7AdTdaZBxQRQvwxTjomqYGrt+LnX+v0MYggh6swMzj7upJosnKbBg==
+"@tiptap/extension-floating-menu@^2.0.0-beta.56":
+ version "2.0.0-beta.56"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.56.tgz#c7428d9109d215bdbd9033f69782c4aadb2aabec"
+ integrity sha512-j/evHE/6UPGkIgXny9IGcAh0IrcnQmg0b2NBYebs2mqx9xYKYoe+0jVgNdLp/0M3MRgQCzyWTyatBDBFOUR2mw==
dependencies:
- prosemirror-state "^1.3.4"
- prosemirror-view "^1.23.6"
+ prosemirror-state "1.4.1"
+ prosemirror-view "1.26.2"
tippy.js "^6.3.7"
-"@tiptap/extension-gapcursor@^2.0.0-beta.34":
- version "2.0.0-beta.34"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.34.tgz#0e4971affb1621934422dd5fc4bf2dd7a84f70f7"
- integrity sha512-Vm8vMWWQ2kJcUOLfB5CEo5pYgyudI7JeeiZvX9ScPmUmgKVYhEpt3EAICY9pUYJ41aAVH35gZLXkUtsz2f9GHw==
+"@tiptap/extension-gapcursor@^2.0.0-beta.38":
+ version "2.0.0-beta.38"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.38.tgz#14254eed2c8702a287c4952d4e83bc3baeacd759"
+ integrity sha512-sNMgfXLsTUew9LnjV2YTCGO0Ed6o2tkZkEQyWDoLMhdjffRPM9QUar0H+a/U+BTW8jJLwU1cRpw6uykBtWAVCw==
dependencies:
- "@types/prosemirror-gapcursor" "^1.0.4"
- prosemirror-gapcursor "^1.2.1"
+ prosemirror-gapcursor "^1.3.0"
-"@tiptap/extension-hard-break@^2.0.0-beta.30":
- version "2.0.0-beta.30"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.30.tgz#165494f1194a7bad08907e6d64d349dd15851b72"
- integrity sha512-X9xj/S+CikrbIE7ccUFVwit5QHEbflnKVxod+4zPwr1cxogFbE9AyLZE2MpYdx3z9LcnTYYi9leBqFrP4T/Olw==
+"@tiptap/extension-hard-break@^2.0.0-beta.33":
+ version "2.0.0-beta.33"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.33.tgz#e2f355a22aaaec6e831cf2880c52aa5b0b860573"
+ integrity sha512-41xf0vSV9hcyTFd01ItLq/CjhjgmOFLCrO3UWN/P2E/cIxuDTyXcvjTE/KXeqRCOV3OYd9fVr0wO91hc8Ij1Yg==
-"@tiptap/extension-heading@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.26.tgz#112b14b4d488772bda36abbf7cb2bc8aba7c42f5"
- integrity sha512-nR6W/3rjnZH1Swo7tGBoYsmO6xMvu9MGq6jlm3WVHCB7B3CsrRvCkTwGjVIbKTaZC4bQfx5gvAUpQFvwuU+M5w==
+"@tiptap/extension-heading@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.29.tgz#d017d216c0fd1962c266f6f61a335093f9749862"
+ integrity sha512-q92jYcsT5bPhvuQaB0h44Z9r+Ii22tDYo082KMVnR4+tknHT/3xx+p4JC8KHjh+/5W8Quyafqy6mS8L8VX0zsQ==
-"@tiptap/extension-history@^2.0.0-beta.21":
- version "2.0.0-beta.21"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.21.tgz#5d96a17a83a7130744f0757a3275dd5b11eb1bf7"
- integrity sha512-0v8Cl30V4dsabdpspLdk+f+lMoIvLFlJN5WRxtc7RRZ5gfJVxPHwooIKdvC51brfh/oJtWFCNMRjhoz0fRaF9A==
+"@tiptap/extension-history@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.25.tgz#756d8e82e8873278e567b460c67445f71563b797"
+ integrity sha512-G3z6BYeb742U9G2wQPhv9qzf74WxDU3h8VlD3NKl3zdqciFG/lXYH6k3+B+aKHwAWfgdYo7NtLtdWPV9EE2vCg==
dependencies:
- "@types/prosemirror-history" "^1.0.3"
- prosemirror-history "^1.2.0"
+ prosemirror-history "^1.3.0"
-"@tiptap/extension-horizontal-rule@^2.0.0-beta.31":
- version "2.0.0-beta.31"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.31.tgz#efb383a6cedbbf4f2175d7d207eaeeba626faab0"
- integrity sha512-MNc4retfjRgkv3qxqGya0+/BEd1Kmn+oMsCRvE+8x3sXyKIse+vdqMuG5qUcA6np0ZD/9hh1riiQ1GQdgc23Ng==
+"@tiptap/extension-horizontal-rule@^2.0.0-beta.36":
+ version "2.0.0-beta.36"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.36.tgz#daf8e2d0f30b210a90fdb8f015646653661cfa04"
+ integrity sha512-o+Zp7dcn3zAQhtlhZiFB69mTHuH3ZRbGEF7Cbf1D3uX1izotni5zIZbPaFFUT4r6OmVe/vDDt/nopfcGc10ktQ==
dependencies:
- prosemirror-state "^1.3.4"
+ prosemirror-state "1.4.1"
-"@tiptap/extension-image@^2.0.0-beta.27":
- version "2.0.0-beta.27"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.27.tgz#62152240cfa7ead03080c38485c1ebda4a603d18"
- integrity sha512-kdJ7V39yNdVWUco/RBe7WgvFevd81l+pU6+Je9HpelqBBP953wDttzLMuAWQB4AeLv9WhKSlORHiFv2SKsV5NA==
+"@tiptap/extension-image@^2.0.0-beta.30":
+ version "2.0.0-beta.30"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.30.tgz#60c6cfd09bfd017a3d8b1feaf0931462ffd71a60"
+ integrity sha512-VhEmgiKkZMiKR7hbpJgIlIUS/QNjSGI5ER7mKDAbuV1IB5yb6nGjZ6o3Exrr2/CaTaW5hQarBC1z2Xgdu05EGg==
-"@tiptap/extension-italic@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.26.tgz#b00c9e32b81b1bd94eaed24bb2a22e44d5dc54a3"
- integrity sha512-vejGe2ra4K5ipFOn1U9viqF9X9nPTX8WSJpSOux+9UbKjHpANy7bz69tp66OIi/Wh5L/MMDc+luH/04qfVnpZw==
+"@tiptap/extension-italic@^2.0.0-beta.28":
+ version "2.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.28.tgz#bf88ecae64c8f2f69f1f508b802c1efd7454a84e"
+ integrity sha512-/pKRiCfewh7nqiXRD3N4hQHfGrGNOiWPFYZfY35bSpvTms7PDb/MF7xT1CWW23hSpY31BBS+R/a66vlR/gqu7Q==
-"@tiptap/extension-link@^2.0.0-beta.38":
- version "2.0.0-beta.38"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.38.tgz#e7fb0ebee0d557ef921bf3c7fa6a7c62335f66a5"
- integrity sha512-j+ygwq3cpDu5/8zPBcHyfgC5cuyO3jfV+2KcJw2I6Qi73y4Kwo3PW/leEYlSHkIt7i1zjyFHo/oDfC4K9x9eQg==
+"@tiptap/extension-link@^2.0.0-beta.43":
+ version "2.0.0-beta.43"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.43.tgz#c123a2170dd50d075b9fe7fb91d86d23f778ffb0"
+ integrity sha512-AYueqfTW713KGVfWSWhVbj4ObeWudgawikm3m0uYcKSdsAz/CfEvOD2/NA0uyQzlxmYLA6Pf8HMxoKGN+O4Cmg==
dependencies:
linkifyjs "^3.0.5"
- prosemirror-model "^1.16.1"
- prosemirror-state "^1.3.4"
+ prosemirror-model "1.18.1"
+ prosemirror-state "1.4.1"
+
+"@tiptap/extension-list-item@^2.0.0-beta.23":
+ version "2.0.0-beta.23"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.23.tgz#6d1ac7235462b0bcee196f42bb1871669480b843"
+ integrity sha512-AkzvdELz3ZnrlZM0r9+ritBDOnAjXHR/8zCZhW0ZlWx4zyKPMsNG5ygivY+xr4QT65NEGRT8P8b2zOhXrMjjMQ==
+
+"@tiptap/extension-ordered-list@^2.0.0-beta.30":
+ version "2.0.0-beta.30"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.30.tgz#1f656b664302d90272c244b2e478d7056203f2a8"
+ integrity sha512-GRxGQdq1u0Rp5N8TjthCqoZ//460m343A0HCN7UwfQOnX7Ipv0UJemwNkSHWrl7Pexym9vy3yPWgrn7oRRmgEw==
+
+"@tiptap/extension-paragraph@^2.0.0-beta.26":
+ version "2.0.0-beta.26"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.26.tgz#5199c8cedb9c076347a2e15cc67442ef7c3c3fbb"
+ integrity sha512-WcYsuUa7LLfk0vi7I1dVjdMRu53B52FMMqd+UL1qPdDKVkU3DBsZVwPj+yyfQyqN8Mc/xyg9VacGaiKFLmWNDg==
-"@tiptap/extension-list-item@^2.0.0-beta.20":
- version "2.0.0-beta.20"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.20.tgz#7169528b226dee4590e013bdf6e5fc6d83729b0f"
- integrity sha512-5IPEspJt38t9ROj4xLUesOVEYlTT/R9Skd9meHRxJQZX1qrzBICs5PC/WRIsnexrvTBhdxpYgCYjpvpsJBlKuQ==
+"@tiptap/extension-strike@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.29.tgz#7004d0c5d126b0517fa78efc5a333a4b8e3334bf"
+ integrity sha512-zqFuY7GfNmZ/KClt6kxQ+msGo3syqucP/Xnlihxi+/h/G+oTvEwyOIXCtDOltvxcsWH/TUsdr5vzLp0j+Mdc6Q==
-"@tiptap/extension-ordered-list@^2.0.0-beta.27":
- version "2.0.0-beta.27"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.27.tgz#ed48a53a9b012d578613b68375db31e8664bfdc9"
- integrity sha512-apFDeignxdZb3cA3p1HJu0zw1JgJdBYUBz1r7f99qdNybYuk3I/1MPUvlOuOgvIrBB/wydoyVDP+v9F7QN3tfQ==
+"@tiptap/extension-subscript@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.13.tgz#5da9523b50240c4f4999b1941d5d66d6ca85189d"
+ integrity sha512-L9f2zKzNI5y4YvMdNxHDT4Y+8gS1UwtbTJ1vUJdCZGfF8DrMuTZIRp3LjOxYXydr7NGEXyYbucdm97Tzrsp8WA==
-"@tiptap/extension-paragraph@^2.0.0-beta.23":
+"@tiptap/extension-superscript@^2.0.0-beta.13":
+ version "2.0.0-beta.13"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.13.tgz#053b7df90ea26451c020075424b78053325672c1"
+ integrity sha512-Vr9KIG2c4jzymcMMQCjhx2gppmRvnbw6Xvrd8YCpK4szyYI1ClMQ5KQMYl2zV3Y4ZIsivRSy9cE0ipGsXGE3Gw==
+
+"@tiptap/extension-table-cell@^2.0.0-beta.23":
version "2.0.0-beta.23"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.23.tgz#2ab77308519494994d7a9e5a4acd14042f45f28c"
- integrity sha512-VWAxyzecErYWk97Kv/Gkghh97zAQTcaVOisEnYYArZAlyYDaYM48qVssAC/vnRRynP2eQxb1EkppbAxE+bMHAA==
-
-"@tiptap/extension-strike@^2.0.0-beta.27":
- version "2.0.0-beta.27"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.27.tgz#c5187bf3c28837f95a5c0c0617d0dd31c318353d"
- integrity sha512-2dmCgtesuDdivM/54Q+Y6Tc3JbGz1SkHP6c62piuqBiYLWg3xa16zChZOhfN8szbbQlBgLT6XRTDt3c2Ux+Dug==
-
-"@tiptap/extension-subscript@^2.0.0-beta.10":
- version "2.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.10.tgz#177e9501f805d3cdcb359411b80b54dc7d77373e"
- integrity sha512-er8/1lp0Rb+SKwEioW0w4oVf3EkdQZ0WS/5kPBG4W0DncfUMT+bw5de76S3kRL9PLZ9UShAL7wuXtuiSi5QsMw==
-
-"@tiptap/extension-superscript@^2.0.0-beta.10":
- version "2.0.0-beta.10"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.10.tgz#f91c19c2d30aabe3f8c21e87f8e5e8b2e6a55893"
- integrity sha512-TUUBS8XsD2MorGORYVlhGDH7wcc9diSbHscD4Dnz8pKWVR0JPUd/od4h5qSffDzAOKxtphTiX9LOFWk6zVooKg==
-
-"@tiptap/extension-table-cell@^2.0.0-beta.20":
- version "2.0.0-beta.20"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-cell/-/extension-table-cell-2.0.0-beta.20.tgz#859456fe8d7276a87161006a3f9b3642b306524c"
- integrity sha512-IllQyxLQvgm1FAewz3U+DkgNHRthmuVrtUQnG6la45qdUOLCOrpFbRRaQ1LJ/BpbvZ2Xs1o2yAa97BqZOPwovQ==
-
-"@tiptap/extension-table-header@^2.0.0-beta.22":
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-cell/-/extension-table-cell-2.0.0-beta.23.tgz#a460318be151434ac31daffe94c2c4e53f2ea229"
+ integrity sha512-LTvmAXkbwpLlGhwvVJabOKJbrWZYRp+0DizJaFtBXLSAHqzW9FQjuUhkTokeDRSc+PHMOb0tE1Kz6CRd8onIkA==
+
+"@tiptap/extension-table-header@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-header/-/extension-table-header-2.0.0-beta.25.tgz#65e16d2a12973c60b837de100a5ac88be1da7372"
+ integrity sha512-MO9Fa4Ng2sSBAov8cBJR3CxUBSaQQhNY6Dq2h3JINWUs03GPN3iihiVtD5N+0SFs8O4xJ5B8Cifkvd72lSqI3w==
+
+"@tiptap/extension-table-row@^2.0.0-beta.22":
version "2.0.0-beta.22"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-header/-/extension-table-header-2.0.0-beta.22.tgz#a1672970d8985c383411bb21c18e71fc7e53e262"
- integrity sha512-nMrghrfl+ZS4EDixs3lgXnHw1Q+ECyTugpRvS36rP7b8GFp3GXm9DfbIAUzwGGfcq1D7DwRnJUDM6ARdWXyw0w==
-
-"@tiptap/extension-table-row@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.19.tgz#b45e82f29dfcc7405440ba237b069dbb93d1a94a"
- integrity sha512-ldEVDpIUX7ZqbViTy4c/RfyNGRv++O/r3A/Ivuon1PykaDDTbPlp5JM89FunAD39cLAbo2HKtweqdmzCMlZsqA==
-
-"@tiptap/extension-table@^2.0.0-beta.49":
- version "2.0.0-beta.49"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.49.tgz#10e2fbc204290ae39b6768c9247f6aaced666776"
- integrity sha512-7irrvMUe9z/6Y8DcFwSuxaIVQ71VUUT1xxv6NZADvdf0HJWesCaTpVORISTnNuQdO5nwEyJXXJ5Ri/82YzWe0g==
- dependencies:
- "@types/prosemirror-model" "^1.16.0"
- "@types/prosemirror-state" "^1.2.8"
- prosemirror-model "^1.16.1"
- prosemirror-state "^1.3.4"
- prosemirror-tables "^1.1.1"
- prosemirror-view "^1.23.6"
-
-"@tiptap/extension-task-item@^2.0.0-beta.32":
- version "2.0.0-beta.32"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.32.tgz#590efcf36143cf0afd0bbd7bc1d55bfb91025bf4"
- integrity sha512-ogeZHDUBNZtlcV6on+I6zenlvsXHzjFcgQIVedK+o4h8icnURFf5m4D3m1hMuM8UGj1pIu4atFDDvAAVi7RLew==
-
-"@tiptap/extension-task-list@^2.0.0-beta.26":
- version "2.0.0-beta.26"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.26.tgz#75a20795429c40c3b12544483ea63014487d71c7"
- integrity sha512-7zPpz9eOUCnFyWNDFYPCUJ39gjID+mCI5BuXyXrjJjDfm8wxg/xTgg9+KC6xakczos7DypnhzlRKSs4EFczeUg==
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.22.tgz#a113ca3cde46af1fe7ecc4c229770726aedfd342"
+ integrity sha512-o47oQn3Sv27iIinBf1s1nHoiFLdujNtSkfHhUgUz8zeyXRT2PtKmwSSEglB3c5jGAmt1CLfU8QJrmrV38CwFYw==
+
+"@tiptap/extension-table@^2.0.0-beta.54":
+ version "2.0.0-beta.54"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.54.tgz#d0590fb1634bbad34fe407018c9c4de1388803d3"
+ integrity sha512-KZbocjS9EbWMr/z7U8CUnVhMlV/YEDi7nV1lmrfzmQ6CVIJFQ9FrWCztN1QH3hWnvIcRnR6GM+5VdjFlalsp3A==
+ dependencies:
+ "@_ueberdosis/prosemirror-tables" "1.1.3"
+ prosemirror-model "1.18.1"
+ prosemirror-state "1.4.1"
+ prosemirror-view "1.26.2"
+
+"@tiptap/extension-task-item@^2.0.0-beta.37":
+ version "2.0.0-beta.37"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.37.tgz#fcf719c4f6d09a69a6525f116bb96560bddfdf51"
+ integrity sha512-zdTE7G6KHgdr+V32eWk7V6YkKxV3X0VJvfuybRlUcS4QyX4dSWnIqeHzzmX8Jd9IXjRghIFtjNi7IKxIGAhMsg==
-"@tiptap/extension-text@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz#f08cff1b78f1c6996464dfba1fef8ec1e107617f"
- integrity sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA==
+"@tiptap/extension-task-list@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.29.tgz#3ca388b9251e4d42d152177c609f6cebb57c4a1e"
+ integrity sha512-PbHlVmYWevClA3mmXyshhR58GT1J22vVlFEDj2o25WRPY2dCTv4X136wPRVf9ee4nZII0Xcp2SsVC1kfgtuVRg==
-"@tiptap/vue-2@^2.0.0-beta.79":
- version "2.0.0-beta.79"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.79.tgz#8192fc56b083097559f8158a177f76572ecfabf1"
- integrity sha512-dwprmBVRvPJl0gMgH6LBU79yqhTbjiDQ3ReNtZ+MFBqwujQfkAqnsm6VVgLjd4jHsV+nzblP5HPH8s9MhIdySw==
+"@tiptap/extension-text@^2.0.0-beta.17":
+ version "2.0.0-beta.17"
+ 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/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"
+ integrity sha512-LJGVqD69pQn+8ZxYpROcRG4Zv2eAK7mFsKGf/tywtews09OkEynLbwyAePsF1nxsUASiA8M7rEiWoKWGFtJ6Qg==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.0-beta.56"
- "@tiptap/extension-floating-menu" "^2.0.0-beta.51"
- prosemirror-view "^1.23.6"
+ "@tiptap/extension-bubble-menu" "^2.0.0-beta.61"
+ "@tiptap/extension-floating-menu" "^2.0.0-beta.56"
+ prosemirror-view "1.26.2"
+
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
"@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"
integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A==
-"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7":
- version "7.1.9"
- resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d"
- integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==
+"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
+ version "7.1.19"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460"
+ integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
@@ -2022,13 +2019,13 @@
dependencies:
"@types/istanbul-lib-report" "*"
-"@types/jest@^26.0.24":
- version "26.0.24"
- resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a"
- integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==
+"@types/jest@^27.5.1":
+ version "27.5.2"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c"
+ integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==
dependencies:
- jest-diff "^26.0.0"
- pretty-format "^26.0.0"
+ 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"
@@ -2087,11 +2084,6 @@
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
-"@types/orderedmap@*":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@types/orderedmap/-/orderedmap-1.0.0.tgz#807455a192bba52cbbb4517044bc82bdbfa8c596"
- integrity sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==
-
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@@ -2107,93 +2099,10 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb"
integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==
-"@types/prettier@^2.0.0":
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3"
- integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA==
-
-"@types/prosemirror-commands@*", "@types/prosemirror-commands@^1.0.4":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz#d08551415127d93ae62e7239d30db0b5e7208e22"
- integrity sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
- "@types/prosemirror-view" "*"
-
-"@types/prosemirror-dropcursor@^1.0.3":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz#49250849b8a0b86e8c29eb1ba70a463e53e46947"
- integrity sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg==
- dependencies:
- "@types/prosemirror-state" "*"
-
-"@types/prosemirror-gapcursor@^1.0.4":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.4.tgz#7df7d373edb33ea8da12084bfd462cf84cd69761"
- integrity sha512-9xKjFIG5947dzerFvkLWp6F53JwrUYoYwh3SgcTFEp8SbSfNNrez/PFYVZKPnoqPoaK5WtTdQTaMwpCV9rXQIg==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
-
-"@types/prosemirror-history@^1.0.3":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-history/-/prosemirror-history-1.0.3.tgz#f1110efbe758129b5475e466ff077f0a8d9b964f"
- integrity sha512-5TloMDRavgLjOAKXp1Li8u0xcsspzbT1Cm9F2pwHOkgvQOz1jWQb2VIXO7RVNsFjLBZdIXlyfSLivro3DuMWXg==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
-
-"@types/prosemirror-keymap@^1.0.4":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz#f73c79810e8d0e0a20d153d84f998f02e5afbc0c"
- integrity sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==
- dependencies:
- "@types/prosemirror-commands" "*"
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
- "@types/prosemirror-view" "*"
-
-"@types/prosemirror-model@*", "@types/prosemirror-model@^1.16.0":
- version "1.16.0"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-model/-/prosemirror-model-1.16.0.tgz#8b22c7431a4c93f7f550fc89c4b0e2d44d42c8b6"
- integrity sha512-nv93YLyTEcDDl17OB90EldxZjyJQJll2WSMLDvLzTewbpvE/vtMjHT3j4mik3uSzQ6YD486AcloCO3WODY/lDg==
- dependencies:
- "@types/orderedmap" "*"
-
-"@types/prosemirror-schema-list@^1.0.3":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz#bdf1893a7915fbdc5c49b3cac9368e96213d70de"
- integrity sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==
- dependencies:
- "@types/orderedmap" "*"
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
-
-"@types/prosemirror-state@*", "@types/prosemirror-state@^1.2.8":
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-state/-/prosemirror-state-1.2.8.tgz#65080eeec52f63c50bf7034377f07773b4f6b2ac"
- integrity sha512-mq9uyQWcpu8jeamO6Callrdvf/e1H/aRLR2kZWSpZrPHctEsxWHBbluD/wqVjXBRIOoMHLf6ZvOkrkmGLoCHVA==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-transform" "*"
- "@types/prosemirror-view" "*"
-
-"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.5":
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.5.tgz#e6949398c64a5d3ca53e6081352751aa9e9ce76e"
- integrity sha512-Wr2HXaEF4JPklWpC17RTxE6PxyU54Taqk5FMhK1ojgcN93J+GpkYW8s0mD3rl7KfTmlhVwZPCHE9o0cYf2Go5A==
- dependencies:
- "@types/prosemirror-model" "*"
-
-"@types/prosemirror-view@*", "@types/prosemirror-view@^1.23.1":
- version "1.23.1"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.23.1.tgz#a9a926bb6b6e6873e3a9d8caa61c32f3402629eb"
- integrity sha512-6e1B2oKUnhmZPUrsVvYjDqeVjE6jGezygjtoHsAK4ZENAxHzHqy5NT4jUvdPTWjCYeH0t2Y7pSfRPNrPIyQX4A==
- dependencies:
- "@types/prosemirror-model" "*"
- "@types/prosemirror-state" "*"
- "@types/prosemirror-transform" "*"
+"@types/prettier@^2.1.5":
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.1.tgz#76e72d8a775eef7ce649c63c8acae1a0824bbaed"
+ integrity sha512-XFjFHmaLVifrAKaZ+EKghFHtHSUonyw8P2Qmy2/+osBnrKbH9UYtlK10zg8/kCt47MFilll/DEDKy3DHfJ0URw==
"@types/qs@*":
version "6.9.7"
@@ -2268,6 +2177,13 @@
dependencies:
"@types/yargs-parser" "*"
+"@types/yargs@^16.0.0":
+ version "16.0.4"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977"
+ integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==
+ 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"
@@ -2315,6 +2231,17 @@
lodash "^4.17.15"
pretty "^2.0.0"
+"@vue/vue2-jest@^27.0.0":
+ version "27.0.0"
+ resolved "https://registry.yarnpkg.com/@vue/vue2-jest/-/vue2-jest-27.0.0.tgz#456076e27f7fa0179a37b04baea3e0b3cf786c6d"
+ integrity sha512-r8YGOuqEWpAf2wGfgxfOL6Jce3WYOMcYji2qd8kuDe466ZsybHFeMryMJi6JrELOOI+MCA/8eFsSOx1KoJa7Dg==
+ dependencies:
+ "@babel/plugin-transform-modules-commonjs" "^7.2.0"
+ "@vue/component-compiler-utils" "^3.1.0"
+ chalk "^2.1.0"
+ css-tree "^2.0.1"
+ source-map "0.5.6"
+
"@webassemblyjs/ast@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
@@ -2513,10 +2440,10 @@
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
-abab@^2.0.3:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
- integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
+abab@^2.0.3, abab@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
+ integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
abbrev@1:
version "1.1.1"
@@ -2546,10 +2473,10 @@ acorn-globals@^6.0.0:
acorn "^7.1.1"
acorn-walk "^7.1.1"
-acorn-jsx@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
- integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn-walk@^7.1.1:
version "7.2.0"
@@ -2561,27 +2488,27 @@ acorn-walk@^8.0.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3"
integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==
-acorn@^6.3.0, acorn@^6.4.1:
+acorn@^6.4.1:
version "6.4.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
-acorn@^7.1.1, acorn@^7.4.0:
+acorn@^7.1.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-acorn@^8.0.4, acorn@^8.7.0:
- version "8.7.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
- integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
+acorn@^8.0.4, acorn@^8.2.4, 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==
-agent-base@4, agent-base@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
- integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
- es6-promisify "^5.0.0"
+ debug "4"
aggregate-error@^3.0.0:
version "3.0.1"
@@ -2615,7 +2542,7 @@ ajv-keywords@^5.0.0:
dependencies:
fast-deep-equal "^3.1.3"
-ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
+ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2635,18 +2562,6 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.10.0, ajv@^8.8.0:
require-from-string "^2.0.2"
uri-js "^4.2.2"
-ansi-align@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
- integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
- dependencies:
- string-width "^3.0.0"
-
-ansi-colors@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
- integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
-
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -2660,9 +2575,9 @@ ansi-html-community@^0.0.8:
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
ansi-regex@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
- integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
+ integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
ansi-regex@^5.0.0, ansi-regex@^5.0.1:
version "5.0.1"
@@ -2688,14 +2603,6 @@ 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==
-anymatch@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
- integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
- dependencies:
- micromatch "^3.1.4"
- normalize-path "^2.1.1"
-
anymatch@^3.0.3, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
@@ -2816,18 +2723,6 @@ asn1.js@^4.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
@@ -2860,31 +2755,6 @@ autosize@^5.0.1:
resolved "https://registry.yarnpkg.com/autosize/-/autosize-5.0.1.tgz#ed269b0fa9b7eb47627048a1bb3299e99e003a0f"
integrity sha512-UIWUlE4TOVPNNj2jjrU39wI4hEYbneUypEqcyRmRFIx5CC2gNdg3rQr+Zh7/3h6egbBvm33TDQjNQKtj9Tk1HA==
-aws-sdk@^2.637.0:
- version "2.637.0"
- resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.637.0.tgz#810e25e53acf2250d35fc74498f9d4492e154217"
- integrity sha512-e7EYX5rNtQyEaleQylUtLSNKXOmvOwfifQ4bYkfF80mFsVI3DSydczLHXrqPzXoEJaS/GI/9HqVnlQcPs6Q3ew==
- dependencies:
- buffer "4.9.1"
- events "1.1.1"
- ieee754 "1.1.13"
- jmespath "0.15.0"
- querystring "0.2.0"
- sax "1.2.1"
- url "0.10.3"
- uuid "3.3.2"
- xml2js "0.4.19"
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
- version "1.10.1"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428"
- integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==
-
axios-mock-adapter@^1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.15.0.tgz#fbc06825d8302c95c3334d21023bba996255d45d"
@@ -2899,18 +2769,18 @@ axios@^0.24.0:
dependencies:
follow-redirects "^1.14.4"
-babel-jest@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.5.2.tgz#164f367a35946c6cf54eaccde8762dec50422250"
- integrity sha512-U3KvymF3SczA3vOL/cgiUFOznfMET+XDIXiWnoJV45siAp2pLMG8i2+/MGZlAC3f/F6Q40LR4M4qDrWZ9wkK8A==
+babel-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
+ integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==
dependencies:
- "@jest/transform" "^26.5.2"
- "@jest/types" "^26.5.2"
- "@types/babel__core" "^7.1.7"
- babel-plugin-istanbul "^6.0.0"
- babel-preset-jest "^26.5.0"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^27.5.1"
chalk "^4.0.0"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
slash "^3.0.0"
babel-loader@^8.2.5:
@@ -2930,21 +2800,21 @@ babel-plugin-dynamic-import-node@^2.3.3:
dependencies:
object.assign "^4.1.0"
-babel-plugin-istanbul@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765"
- integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==
+babel-plugin-istanbul@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
+ integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@istanbuljs/load-nyc-config" "^1.0.0"
"@istanbuljs/schema" "^0.1.2"
- istanbul-lib-instrument "^4.0.0"
+ istanbul-lib-instrument "^5.0.4"
test-exclude "^6.0.0"
-babel-plugin-jest-hoist@^26.5.0:
- version "26.5.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.5.0.tgz#3916b3a28129c29528de91e5784a44680db46385"
- integrity sha512-ck17uZFD3CDfuwCLATWZxkkuGGFhMij8quP8CNhwj8ek1mqFgbFzRJ30xwC04LLscj/aKsVFfRST+b5PT7rSuw==
+babel-plugin-jest-hoist@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e"
+ integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==
dependencies:
"@babel/template" "^7.3.3"
"@babel/types" "^7.3.3"
@@ -2986,10 +2856,10 @@ babel-plugin-polyfill-regenerator@^0.3.0:
dependencies:
"@babel/helper-define-polyfill-provider" "^0.3.1"
-babel-preset-current-node-syntax@^0.1.3:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz#826f1f8e7245ad534714ba001f84f7e906c3b615"
- integrity sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==
+babel-preset-current-node-syntax@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
+ integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==
dependencies:
"@babel/plugin-syntax-async-generators" "^7.8.4"
"@babel/plugin-syntax-bigint" "^7.8.3"
@@ -3002,19 +2872,15 @@ babel-preset-current-node-syntax@^0.1.3:
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-top-level-await" "^7.8.3"
-babel-preset-jest@^26.5.0:
- version "26.5.0"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.5.0.tgz#f1b166045cd21437d1188d29f7fba470d5bdb0e7"
- integrity sha512-F2vTluljhqkiGSJGBg/jOruA8vIIIL11YrxRcO7nviNTMbbofPSHwnm8mgP7d/wS7wRSexRoI6X1A6T74d4LQA==
+babel-preset-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81"
+ integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==
dependencies:
- babel-plugin-jest-hoist "^26.5.0"
- babel-preset-current-node-syntax "^0.1.3"
-
-babylon@7.0.0-beta.19:
- version "7.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.19.tgz#e928c7e807e970e0536b078ab3e0c48f9e052503"
- integrity sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==
+ babel-plugin-jest-hoist "^27.5.1"
+ babel-preset-current-node-syntax "^1.0.0"
backo2@^1.0.2:
version "1.0.2"
@@ -3059,13 +2925,6 @@ batch@0.6.1:
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
- dependencies:
- tweetnacl "^0.14.3"
-
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -3081,7 +2940,7 @@ binaryextensions@2:
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935"
integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==
-bluebird@^3.1.1, bluebird@^3.5.5, bluebird@~3.5.0:
+bluebird@^3.1.1, bluebird@^3.5.5:
version "3.5.5"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
@@ -3138,20 +2997,6 @@ bootstrap@4.5.3, "bootstrap@>=4.5.3 <5.0.0":
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
-boxen@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
- integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
- dependencies:
- ansi-align "^3.0.0"
- camelcase "^5.3.1"
- chalk "^3.0.0"
- cli-boxes "^2.2.0"
- string-width "^4.1.0"
- term-size "^2.1.0"
- type-fest "^0.8.1"
- widest-line "^3.1.0"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -3284,7 +3129,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
-buffer@4.9.1, buffer@^4.3.0:
+buffer@^4.3.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=
@@ -3392,19 +3237,6 @@ cache-loader@^4.1.0:
neo-async "^2.6.1"
schema-utils "^2.0.0"
-cacheable-request@^6.0.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
- integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
- dependencies:
- clone-response "^1.0.2"
- get-stream "^5.1.0"
- http-cache-semantics "^4.0.0"
- keyv "^3.0.0"
- lowercase-keys "^2.0.0"
- normalize-url "^4.1.0"
- responselike "^1.0.2"
-
call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -3427,45 +3259,26 @@ camelcase-keys@^6.2.2:
map-obj "^4.0.0"
quick-lru "^4.0.1"
-camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1:
+camelcase@^5.2.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-camelcase@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
- integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
+camelcase@^6.2.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
+ integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001332:
- version "1.0.30001344"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb"
- integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==
+ version "1.0.30001340"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz#029a2f8bfc025d4820fafbfaa6259fd7778340c7"
+ integrity sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==
canvas-confetti@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/canvas-confetti/-/canvas-confetti-1.4.0.tgz#840f6db4a566f8f32abe28c00dcd82acf39c92bd"
integrity sha512-S18o4Y9PqI/uabdlT/jI3MY7XBJjNxnfapFIkjkMwpz6qNxLFZOm2b22OMf4ZYDL9lpNWI+Ih4fEMVPwO1KHFQ==
-capture-exit@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
- integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==
- dependencies:
- rsvp "^4.8.4"
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
-catharsis@~0.8.9:
- version "0.8.9"
- resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.8.9.tgz#98cc890ca652dd2ef0e70b37925310ff9e90fc8b"
- integrity sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=
- dependencies:
- underscore-contrib "~0.3.0"
-
ccount@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
@@ -3480,14 +3293,6 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
- integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -3506,11 +3311,6 @@ character-entities@^2.0.0:
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.1.tgz#98724833e1e27990dee0bd0f2b8a859c3476aac7"
integrity sha512-OzmutCf2Kmc+6DrFrrPS8/tDh2+DpnrfzdICHWhcVC9eOd0N1PXmQEE1a8iM4IziIAG+8tmTq3K+oo0ubH6RRQ==
-charenc@~0.0.1:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
- integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
-
cheerio-select@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.4.0.tgz#3a16f21e37a2ef0f211d6d1aa4eff054bb22cdc9"
@@ -3535,7 +3335,7 @@ cheerio@^1.0.0-rc.9:
parse5-htmlparser2-tree-adapter "^6.0.1"
tslib "^2.2.0"
-"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.4.1, chokidar@^3.5.3:
+"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.4.1, chokidar@^3.5.2, chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
@@ -3572,10 +3372,10 @@ ci-info@^2.0.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
-ci-info@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2"
- integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==
+ci-info@^3.2.0, ci-info@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32"
+ integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
@@ -3585,6 +3385,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"
+cjs-module-lexer@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
+ integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
+
class-utils@^0.3.5:
version "0.3.6"
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
@@ -3607,11 +3412,6 @@ clean-stack@^2.0.0:
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-cli-boxes@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
- integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
-
clipboard@^2.0.0, clipboard@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
@@ -3621,14 +3421,14 @@ clipboard@^2.0.0, clipboard@^2.0.8:
select "^1.1.2"
tiny-emitter "^2.0.0"
-cliui@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
- integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+cliui@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+ integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
- wrap-ansi "^6.2.0"
+ wrap-ansi "^7.0.0"
clone-deep@^4.0.1:
version "4.0.1"
@@ -3646,23 +3446,11 @@ clone-regexp@^2.1.0:
dependencies:
is-regexp "^2.0.0"
-clone-response@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
- integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
- dependencies:
- mimic-response "^1.0.0"
-
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
-codemirror@^5.48.4:
- version "5.53.2"
- resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.53.2.tgz#9799121cf8c50809cca487304e9de3a74d33f428"
- integrity sha512-wvSQKS4E+P8Fxn/AQ+tQtJnF1qH5UOlxtugFLpubEZ5jcdH2iXTVinb+Xc/4QjshuOxRm4fUsU2QPF1JJKiyXA==
-
codesandbox-api@0.0.23:
version "0.0.23"
resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.23.tgz#bf650a21b5f3c2369e03f0c19d10b4e2ba255b4f"
@@ -3734,7 +3522,7 @@ colorette@^2.0.10, colorette@^2.0.14:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -3761,10 +3549,10 @@ commander@^6.0.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
-commander@^9.2.0:
- version "9.2.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-9.2.0.tgz#6e21014b2ed90d8b7c9647230d8b7a94a4a419a9"
- integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==
+commander@^9.4.0:
+ version "9.4.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c"
+ integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==
commander@~9.0.0:
version "9.0.0"
@@ -3844,18 +3632,6 @@ config-chain@^1.1.12:
ini "^1.3.4"
proto-list "~1.2.1"
-configstore@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
- integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
- dependencies:
- dot-prop "^5.2.0"
- graceful-fs "^4.1.2"
- make-dir "^3.0.0"
- unique-string "^2.0.0"
- write-file-atomic "^3.0.0"
- xdg-basedir "^4.0.0"
-
confusing-browser-globals@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59"
@@ -3966,17 +3742,17 @@ 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.23.5:
- version "3.23.5"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.23.5.tgz#1f82b0de5eece800827a2f59d597509c67650475"
- integrity sha512-7Vh11tujtAZy82da4duVreQysIoO2EvVrur7y6IzZkH1IHPSekuDi8Vuw1+YKjkbfWLRD7Nc9ICQ/sIUDutcyg==
+core-js@^3.24.1:
+ version "3.24.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f"
+ integrity sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg==
core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
integrity sha1-+rg/uwstjchfpjbEudNMdUIMbWU=
-core-util-is@1.0.2, core-util-is@~1.0.0:
+core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
@@ -4051,7 +3827,7 @@ cropper@^2.3.0:
dependencies:
jquery ">= 1.9.1"
-cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
@@ -4062,7 +3838,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -4083,11 +3859,6 @@ cross-undici-fetch@^0.1.19:
undici "^5.0.0"
web-streams-polyfill "^3.2.0"
-crypt@~0.0.1:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
- integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
-
crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
@@ -4105,11 +3876,6 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
-crypto-random-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
- integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-
css-color-names@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
@@ -4158,6 +3924,14 @@ css-shorthand-properties@^1.0.0:
resolved "https://registry.yarnpkg.com/css-shorthand-properties/-/css-shorthand-properties-1.1.1.tgz#1c808e63553c283f289f2dd56fcee8f3337bd935"
integrity sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==
+css-tree@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.1.0.tgz#170e27ccf94e7c5facb183765c25898be843d1d2"
+ integrity sha512-PcysZRzToBbrpoUrZ9qfblRIRf8zbEAkU0AIpQFtgkFK0vSbzOmBCvdSAx2Zg7Xx5wiYJKUKk0NMP7kxevie/A==
+ dependencies:
+ mdn-data "2.0.27"
+ source-map-js "^1.0.1"
+
css-values@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/css-values/-/css-values-0.1.0.tgz#128b7ce103d4dc027a814a5d5995c54781d7b4c6"
@@ -4168,19 +3942,9 @@ css-values@^0.1.0:
postcss-value-parser "^3.3.0"
css-what@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.0.tgz#f0bf4f8bac07582722346ab243f6a35b512cfc47"
- integrity sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==
-
-css@^2.1.0:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
- integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
- dependencies:
- inherits "^2.0.3"
- source-map "^0.6.1"
- source-map-resolve "^0.5.2"
- urix "^0.1.0"
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe"
+ integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==
cssesc@^3.0.0:
version "3.0.0"
@@ -4202,7 +3966,7 @@ cssom@~0.3.6:
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
-cssstyle@^2.2.0:
+cssstyle@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
@@ -4737,13 +4501,6 @@ dagre@^0.8.5:
graphlib "^2.1.8"
lodash "^4.17.15"
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
data-urls@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
@@ -4780,27 +4537,20 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
- ms "2.0.0"
+ ms "2.1.2"
-debug@^3.1.0, debug@^3.2.6, debug@^3.2.7:
+debug@^3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
-debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
- integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
- dependencies:
- ms "2.1.2"
-
decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -4814,10 +4564,10 @@ decamelize@^1.1.0, decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
-decimal.js@^10.2.0:
- version "10.2.1"
- resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3"
- integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==
+decimal.js@^10.2.1:
+ version "10.3.1"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
+ integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
deckar01-task_list@^2.3.1:
version "2.3.1"
@@ -4836,12 +4586,10 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
-decompress-response@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
- integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
- dependencies:
- mimic-response "^1.0.0"
+dedent@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+ integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
deep-equal@^1.0.1:
version "1.0.1"
@@ -4870,11 +4618,6 @@ default-gateway@^6.0.3:
dependencies:
execa "^5.0.0"
-defer-to-connect@^1.0.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
- integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
@@ -4965,15 +4708,10 @@ detect-node@^2.0.4:
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
-diff-sequences@^26.6.2:
- version "26.6.2"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
- integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
-
-diff-sequences@^27.4.0:
- version "27.4.0"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5"
- integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==
+diff-sequences@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
+ integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
diff@^3.4.0:
version "3.5.0"
@@ -5018,11 +4756,6 @@ dns-packet@^5.2.2:
dependencies:
"@leichtgewicht/ip-codec" "^2.0.1"
-docdash@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/docdash/-/docdash-1.0.2.tgz#0449a8f6bb247f563020b78a5485dea95ae2e094"
- integrity sha512-IEM57bWPLtVXpUeCKbiGvHsHtW9O9ZiiBPfeQDAZ7JdQiAF3aNWQoJ3e/+uJ63lHO009yn0tbJjtKpXJ2AURCQ==
-
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@@ -5085,15 +4818,15 @@ domhandler@^4.0.0, domhandler@^4.2.0:
dependencies:
domelementtype "^2.2.0"
-dompurify@2.3.6:
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
- integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
+dompurify@2.3.8:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
+ integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==
-dompurify@^2.3.9:
- version "2.3.9"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.9.tgz#a4be5e7278338d6db09922dffcf6182cd099d70a"
- integrity sha512-3zOnuTwup4lPV/GfGS6UzG4ub9nhSYagR/5tB3AvDEwqyy5dtyCM2dVjwGDCnrPerXifBKTYh/UWCGKK7ydhhw==
+dompurify@^2.3.10:
+ version "2.3.10"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.10.tgz#901f7390ffe16a91a5a556b94043314cd4850385"
+ integrity sha512-o7Fg/AgC7p/XpKjf/+RC3Ok6k4St5F7Q6q6+Nnm3p2zGWioAY6dh0CbbuwOhH2UcSzKsdniE/YnE2/92JcsA+g==
domutils@^2.5.2, domutils@^2.6.0:
version "2.6.0"
@@ -5104,27 +4837,15 @@ domutils@^2.5.2, domutils@^2.6.0:
domelementtype "^2.2.0"
domhandler "^4.2.0"
-dot-prop@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
- integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==
- dependencies:
- is-obj "^2.0.0"
-
dropzone@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3"
integrity sha1-++esu5kY4HBkiQcu9mPv/u+KefM=
dset@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.1.tgz#07de5af7a8d03eab337ad1a8ba77fe17bba61a8c"
- integrity sha512-hYf+jZNNqJBD2GiMYb+5mqOIX4R4RRHXU3qWMWYN+rqcR2/YpRL2bUHr8C8fU+5DNvqYjJ8YvMGSLuVPWU1cNg==
-
-duplexer3@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
- integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
+ integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
duplexer@^0.1.2:
version "0.1.2"
@@ -5141,14 +4862,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
- dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
-
echarts@^5.3.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.3.3.tgz#df97b09c4c0e2ffcdfb44acf518d50c50e0b838e"
@@ -5178,9 +4891,9 @@ ee-first@1.1.1:
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.4.118:
- version "1.4.140"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.140.tgz#1b5836b7244aff341a11c8efd63dfe003dee4a19"
- integrity sha512-NLz5va823QfJBYOO/hLV4AfU4Crmkl/6Hl2pH3qdJcmi0ySZ3YTWHxOlDm3uJOFBEPy3pIhu8gKQo6prQTWKKA==
+ version "1.4.137"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz#186180a45617283f1c012284458510cd99d6787f"
+ integrity sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==
elliptic@^6.0.0:
version "6.5.4"
@@ -5195,21 +4908,16 @@ elliptic@^6.0.0:
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
-emittery@^0.7.1:
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451"
- integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ==
+emittery@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
+ integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
emoji-regex@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.0.tgz#96559e19f82231b436403e059571241d627c42b8"
integrity sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw==
-emoji-regex@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
- integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -5255,18 +4963,16 @@ enhanced-resolve@^4.5.0:
memory-fs "^0.5.0"
tapable "^1.0.0"
-enquirer@^2.3.5:
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
- integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
- dependencies:
- ansi-colors "^4.1.1"
-
entities@^2.0.0, entities@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
+entities@~3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
+ integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
+
envinfo@^7.7.3:
version "7.8.1"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
@@ -5331,39 +5037,22 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es6-promise@^4.0.3:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
- integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
-
es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=
-es6-promisify@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
- integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
- dependencies:
- es6-promise "^4.0.3"
-
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
-escape-goat@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
- integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==
-
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5:
+escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -5383,13 +5072,13 @@ escape-string-regexp@^5.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
-escodegen@^1.14.1:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
- integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
+escodegen@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
+ integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
dependencies:
esprima "^4.0.1"
- estraverse "^4.2.0"
+ estraverse "^5.2.0"
esutils "^2.0.2"
optionator "^0.8.1"
optionalDependencies:
@@ -5516,17 +5205,18 @@ eslint-plugin-unicorn@^40.1.0:
semver "^7.3.5"
strip-indent "^3.0.0"
-eslint-plugin-vue@^8.5.0:
- version "8.7.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz#f13c53547a0c9d64588a675cc5ecc6ccaf63703f"
- integrity sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==
+eslint-plugin-vue@^9.3.0:
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.3.0.tgz#c3f5ce515dae387e062428725c5cf96098d9da0b"
+ integrity sha512-iscKKkBZgm6fGZwFt6poRoWC0Wy2dQOlwUPW++CiPoQiw1enctV2Hj5DBzzjJZfyqs+FAXhgzL4q0Ww03AgSmQ==
dependencies:
eslint-utils "^3.0.0"
natural-compare "^1.4.0"
nth-check "^2.0.1"
postcss-selector-parser "^6.0.9"
semver "^7.3.5"
- vue-eslint-parser "^8.0.1"
+ vue-eslint-parser "^9.0.1"
+ xml-name-validator "^4.0.0"
eslint-rule-composer@^0.3.0:
version "0.3.0"
@@ -5549,7 +5239,7 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
-eslint-scope@^7.0.0:
+eslint-scope@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
@@ -5557,7 +5247,7 @@ eslint-scope@^7.0.0:
esrecurse "^4.3.0"
estraverse "^5.2.0"
-eslint-utils@^2.0.0, eslint-utils@^2.1.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==
@@ -5571,7 +5261,7 @@ eslint-utils@^3.0.0:
dependencies:
eslint-visitor-keys "^2.0.0"
-eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.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==
@@ -5581,73 +5271,63 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
-eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.3.0:
+eslint-visitor-keys@^3.3.0:
version "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@7.32.0:
- version "7.32.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
- integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
+eslint@8.22.0:
+ version "8.22.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
+ integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
dependencies:
- "@babel/code-frame" "7.12.11"
- "@eslint/eslintrc" "^0.4.3"
- "@humanwhocodes/config-array" "^0.5.0"
+ "@eslint/eslintrc" "^1.3.0"
+ "@humanwhocodes/config-array" "^0.10.4"
+ "@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
- debug "^4.0.1"
+ debug "^4.3.2"
doctrine "^3.0.0"
- enquirer "^2.3.5"
escape-string-regexp "^4.0.0"
- eslint-scope "^5.1.1"
- eslint-utils "^2.1.0"
- eslint-visitor-keys "^2.0.0"
- espree "^7.3.1"
+ eslint-scope "^7.1.1"
+ eslint-utils "^3.0.0"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.3.3"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^6.0.1"
+ find-up "^5.0.0"
functional-red-black-tree "^1.0.1"
- glob-parent "^5.1.2"
- globals "^13.6.0"
- ignore "^4.0.6"
+ glob-parent "^6.0.1"
+ globals "^13.15.0"
+ globby "^11.1.0"
+ grapheme-splitter "^1.0.4"
+ ignore "^5.2.0"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
- js-yaml "^3.13.1"
+ js-yaml "^4.1.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash.merge "^4.6.2"
- minimatch "^3.0.4"
+ minimatch "^3.1.2"
natural-compare "^1.4.0"
optionator "^0.9.1"
- progress "^2.0.0"
- regexpp "^3.1.0"
- semver "^7.2.1"
- strip-ansi "^6.0.0"
+ regexpp "^3.2.0"
+ strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
- table "^6.0.9"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^7.3.0, espree@^7.3.1:
- version "7.3.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
- integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
- dependencies:
- acorn "^7.4.0"
- acorn-jsx "^5.3.1"
- eslint-visitor-keys "^1.3.0"
-
-espree@^9.0.0:
- version "9.3.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
- integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
+espree@^9.3.1, espree@^9.3.2, espree@^9.3.3:
+ version "9.3.3"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
+ integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
dependencies:
- acorn "^8.7.0"
- acorn-jsx "^5.3.1"
+ acorn "^8.8.0"
+ acorn-jsx "^5.3.2"
eslint-visitor-keys "^3.3.0"
esprima@^4.0.0, esprima@^4.0.1:
@@ -5669,7 +5349,7 @@ esrecurse@^4.1.0, esrecurse@^4.3.0:
dependencies:
estraverse "^5.2.0"
-estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.1.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
@@ -5709,11 +5389,6 @@ eventemitter3@^4.0.0:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
-events@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
- integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
-
events@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
@@ -5727,39 +5402,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
-exec-sh@^0.3.2:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
- integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==
-
-execa@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
- integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
- dependencies:
- cross-spawn "^6.0.0"
- get-stream "^4.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-execa@^4.0.0:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2"
- integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==
- dependencies:
- cross-spawn "^7.0.0"
- get-stream "^5.0.0"
- human-signals "^1.1.1"
- is-stream "^2.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^4.0.0"
- onetime "^5.1.0"
- signal-exit "^3.0.2"
- strip-final-newline "^2.0.0"
-
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
@@ -5800,17 +5442,15 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-expect@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/expect/-/expect-26.5.2.tgz#3e0631c4a657a83dbec769ad246a2998953a55a6"
- integrity sha512-ccTGrXZd8DZCcvCz4htGXTkd/LOoy6OEtiDS38x3/VVf6E4AQL0QoeksBiw7BtGR5xDNiRYPB8GN6pfbuTOi7w==
+expect@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
+ integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
dependencies:
- "@jest/types" "^26.5.2"
- ansi-styles "^4.0.0"
- jest-get-type "^26.3.0"
- jest-matcher-utils "^26.5.2"
- jest-message-util "^26.5.2"
- jest-regex-util "^26.0.0"
+ "@jest/types" "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
express@^4.17.3:
version "4.17.3"
@@ -5863,7 +5503,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
-extend@^3.0.0, extend@~3.0.2:
+extend@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -5892,18 +5532,6 @@ extract-files@^11.0.0:
resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a"
integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==
-extract-from-css@^0.4.4:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/extract-from-css/-/extract-from-css-0.4.4.tgz#1ea7df2e7c7c6eb9922fa08e8adaea486f6f8f92"
- integrity sha1-HqffLnx8brmSL6COitrqSG9vj5I=
- dependencies:
- css "^2.1.0"
-
-extsprintf@1.3.0, extsprintf@^1.2.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
fake-xml-http-request@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-2.1.1.tgz#279fdac235840d7a4dff77d98ec44bce9fc690a6"
@@ -5952,13 +5580,6 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
-fault@^1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13"
- integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==
- dependencies:
- format "^0.2.0"
-
fault@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fault/-/fault-2.0.1.tgz#d47ca9f37ca26e4bd38374a7c500b5a384755b6c"
@@ -6075,6 +5696,14 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
find-yarn-workspace-root@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
@@ -6113,23 +5742,18 @@ for-in@^1.0.2:
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
form-data-encoder@^1.7.1:
version "1.7.2"
resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040"
integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
dependencies:
asynckit "^0.4.0"
- combined-stream "^1.0.6"
+ combined-stream "^1.0.8"
mime-types "^2.1.12"
format@^0.2.0:
@@ -6206,7 +5830,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@^2.1.2, fsevents@~2.3.2:
+fsevents@^2.3.2, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -6246,7 +5870,7 @@ gensync@^1.0.0-beta.2:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
-get-caller-file@^2.0.1:
+get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
@@ -6280,20 +5904,6 @@ get-stdin@~9.0.0:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575"
integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==
-get-stream@^4.0.0, get-stream@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
- integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^5.0.0, get-stream@^5.1.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
- integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
- dependencies:
- pump "^3.0.0"
-
get-stream@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
@@ -6312,13 +5922,6 @@ get-value@^2.0.3, get-value@^2.0.6:
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
gettext-extractor-vue@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/gettext-extractor-vue/-/gettext-extractor-vue-5.0.0.tgz#dc463868d49e14097c4545c8ed4851d8d3edd6dd"
@@ -6346,6 +5949,13 @@ glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2:
dependencies:
is-glob "^4.0.1"
+glob-parent@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
"glob@5 - 7", glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
@@ -6358,13 +5968,6 @@ glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2:
once "^1.3.0"
path-is-absolute "^1.0.0"
-global-dirs@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
- integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==
- dependencies:
- ini "^1.3.5"
-
global-modules@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
@@ -6394,10 +5997,10 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^13.6.0, globals@^13.9.0:
- version "13.9.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.9.0.tgz#4bf2bf635b334a173fb1daf7c5e6b218ecdc06cb"
- integrity sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==
+globals@^13.15.0:
+ version "13.16.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.16.0.tgz#9be4aca28f311aaeb974ea54978ebbb5e35ce46a"
+ integrity sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==
dependencies:
type-fest "^0.20.2"
@@ -6425,28 +6028,16 @@ good-listener@^1.2.2:
dependencies:
delegate "^3.1.2"
-got@^9.6.0:
- version "9.6.0"
- resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
- integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
- dependencies:
- "@sindresorhus/is" "^0.14.0"
- "@szmarczak/http-timer" "^1.1.2"
- cacheable-request "^6.0.0"
- decompress-response "^3.3.0"
- duplexer3 "^0.1.4"
- get-stream "^4.1.0"
- lowercase-keys "^1.0.1"
- mimic-response "^1.0.1"
- p-cancelable "^1.0.0"
- to-readable-stream "^1.0.0"
- url-parse-lax "^3.0.0"
-
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
version "4.2.10"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+grapheme-splitter@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+ integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
graphlib@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
@@ -6505,11 +6096,6 @@ graphql@^15.7.2:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.7.2.tgz#85ab0eeb83722977151b3feb4d631b5f2ab287ef"
integrity sha512-AnnKk7hFQFmU/2I9YSQf3xw44ctnSFCfp3zE0N6W174gqe9fWG/2rKaKxROK7CcI3XtERpjEKFqts8o319Kf7A==
-growly@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
- integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
-
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@@ -6522,19 +6108,6 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
- version "5.1.5"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
- integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
- dependencies:
- ajv "^6.12.3"
- har-schema "^2.0.0"
-
hard-rejection@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
@@ -6605,11 +6178,6 @@ has-values@^1.0.0:
is-number "^3.0.0"
kind-of "^4.0.0"
-has-yarn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
- integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
-
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
@@ -6729,11 +6297,6 @@ highlight.js@^11.5.1, highlight.js@~11.5.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.5.1.tgz#027c24e4509e2f4dcd00b4a6dda542ce0a1f7aea"
integrity sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==
-highlight.js@~10.7.0:
- version "10.7.2"
- resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360"
- integrity sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==
-
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -6751,9 +6314,9 @@ hoist-non-react-statics@^3.3.2:
react-is "^16.7.0"
hosted-git-info@^2.1.4:
- version "2.8.8"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
- integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hosted-git-info@^4.0.1:
version "4.1.0"
@@ -6809,11 +6372,6 @@ htmlparser2@^6.1.0:
domutils "^2.5.2"
entities "^2.0.0"
-http-cache-semantics@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
- integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
-
http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
@@ -6845,13 +6403,14 @@ http-parser-js@>=0.5.1:
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
-http-proxy-agent@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
- integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+http-proxy-agent@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
+ integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
dependencies:
- agent-base "4"
- debug "3.1.0"
+ "@tootallnate/once" "1"
+ agent-base "6"
+ debug "4"
http-proxy-middleware@^2.0.3:
version "2.0.4"
@@ -6873,32 +6432,18 @@ http-proxy@^1.18.1:
follow-redirects "^1.0.0"
requires-port "^1.0.0"
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
https-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
-https-proxy-agent@^2.2.3:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
- integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+https-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
- agent-base "^4.3.0"
- debug "^3.1.0"
-
-human-signals@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
- integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+ agent-base "6"
+ debug "4"
human-signals@^2.1.0:
version "2.1.0"
@@ -6931,7 +6476,7 @@ icss-utils@^4.1.0:
dependencies:
postcss "^7.0.14"
-ieee754@1.1.13, ieee754@^1.1.13, ieee754@^1.1.4:
+ieee754@^1.1.13, ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
@@ -6951,11 +6496,6 @@ ignore-by-default@^1.0.1:
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
-ignore@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
- integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
-
ignore@^5.2.0, ignore@~5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
@@ -6966,10 +6506,10 @@ immediate@~3.0.5:
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
-immer@^7.0.7:
- version "7.0.7"
- resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.7.tgz#9dfe713d49bf871cc59aedfce59b1992fa37a977"
- integrity sha512-Q8yYwVADJXrNfp1ZUAh4XDHkcoE3wpdpb4mC5abDSajs2EbW8+cGdPyAnglMyLnm7EF6ojD2xBFX7L5i4TIytw==
+immer@^9.0.15:
+ version "9.0.15"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc"
+ integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==
immutable@^4.0.0:
version "4.1.0"
@@ -6984,11 +6524,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1:
parent-module "^1.0.0"
resolve-from "^4.0.0"
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
import-lazy@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
@@ -7045,7 +6580,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
+ini@^1.3.4, ini@^1.3.5:
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
@@ -7084,11 +6619,6 @@ interpret@^2.2.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
-ip-regex@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
- integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
-
ipaddr.js@1.9.1, ipaddr.js@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
@@ -7140,7 +6670,7 @@ is-boolean-object@^1.1.0:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
-is-buffer@^1.1.5, is-buffer@~1.1.1:
+is-buffer@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
@@ -7235,11 +6765,6 @@ is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
-
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
@@ -7257,24 +6782,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
-is-installed-globally@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
- integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==
- dependencies:
- global-dirs "^2.0.1"
- is-path-inside "^3.0.1"
-
is-negative-zero@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
-is-npm@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
- integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
-
is-number-object@^1.0.4:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
@@ -7294,16 +6806,6 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-is-obj@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
- integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
-
-is-path-inside@^3.0.1:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
- integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
-
is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
@@ -7331,10 +6833,10 @@ is-plain-object@^5.0.0:
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
-is-potential-custom-element-name@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
- integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
is-regex@^1.1.4:
version "1.1.4"
@@ -7356,11 +6858,6 @@ is-shared-array-buffer@^1.0.2:
dependencies:
call-bind "^1.0.2"
-is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-
is-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
@@ -7380,7 +6877,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
dependencies:
has-symbols "^1.0.2"
-is-typedarray@^1.0.0, is-typedarray@~1.0.0:
+is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
@@ -7414,11 +6911,6 @@ is-wsl@^2.1.1, is-wsl@^2.2.0:
dependencies:
is-docker "^2.0.0"
-is-yarn-global@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
- integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -7446,24 +6938,20 @@ isomorphic-ws@^4.0.1:
resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc"
integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-istanbul-lib-coverage@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec"
- integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==
+istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
+ integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==
-istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d"
- integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==
+istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f"
+ integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==
dependencies:
- "@babel/core" "^7.7.5"
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
"@istanbuljs/schema" "^0.1.2"
- istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-coverage "^3.2.0"
semver "^6.3.0"
istanbul-lib-report@^3.0.0:
@@ -7484,10 +6972,10 @@ istanbul-lib-source-maps@^4.0.0:
istanbul-lib-coverage "^3.0.0"
source-map "^0.6.1"
-istanbul-reports@^3.0.0, istanbul-reports@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b"
- integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==
+istanbul-reports@^3.0.0, istanbul-reports@^3.1.3:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c"
+ integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==
dependencies:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
@@ -7519,175 +7007,188 @@ jest-canvas-mock@^2.1.2:
cssfontparser "^1.2.1"
parse-color "^1.0.0"
-jest-changed-files@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.5.2.tgz#330232c6a5c09a7f040a5870e8f0a9c6abcdbed5"
- integrity sha512-qSmssmiIdvM5BWVtyK/nqVpN3spR5YyvkvPqz1x3BR1bwIxsWmU/MGwLoCrPNLbkG2ASAKfvmJpOduEApBPh2w==
+jest-changed-files@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5"
+ integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==
dependencies:
- "@jest/types" "^26.5.2"
- execa "^4.0.0"
- throat "^5.0.0"
+ "@jest/types" "^27.5.1"
+ execa "^5.0.0"
+ throat "^6.0.1"
-jest-cli@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.5.2.tgz#0df114399b4036a3f046f0a9f25c50372c76b3a2"
- integrity sha512-usm48COuUvRp8YEG5OWOaxbSM0my7eHn3QeBWxiGUuFhvkGVBvl1fic4UjC02EAEQtDv8KrNQUXdQTV6ZZBsoA==
+jest-circus@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc"
+ integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==
dependencies:
- "@jest/core" "^26.5.2"
- "@jest/test-result" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^0.7.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+ throat "^6.0.1"
+
+jest-cli@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145"
+ integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
chalk "^4.0.0"
exit "^0.1.2"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
import-local "^3.0.2"
- is-ci "^2.0.0"
- jest-config "^26.5.2"
- jest-util "^26.5.2"
- jest-validate "^26.5.2"
+ jest-config "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
prompts "^2.0.1"
- yargs "^15.4.1"
+ yargs "^16.2.0"
-jest-config@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.5.2.tgz#6e828e25f10124433dd008fbd83348636de0972a"
- integrity sha512-dqJOnSegNdE5yDiuGHsjTM5gec7Z4AcAMHiW+YscbOYJAlb3LEtDSobXCq0or9EmGQI5SFmKy4T7P1FxetJOfg==
+jest-config@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41"
+ integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==
dependencies:
- "@babel/core" "^7.1.0"
- "@jest/test-sequencer" "^26.5.2"
- "@jest/types" "^26.5.2"
- babel-jest "^26.5.2"
+ "@babel/core" "^7.8.0"
+ "@jest/test-sequencer" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ babel-jest "^27.5.1"
chalk "^4.0.0"
+ ci-info "^3.2.0"
deepmerge "^4.2.2"
glob "^7.1.1"
- graceful-fs "^4.2.4"
- jest-environment-jsdom "^26.5.2"
- jest-environment-node "^26.5.2"
- jest-get-type "^26.3.0"
- jest-jasmine2 "^26.5.2"
- jest-regex-util "^26.0.0"
- jest-resolve "^26.5.2"
- jest-util "^26.5.2"
- jest-validate "^26.5.2"
- micromatch "^4.0.2"
- pretty-format "^26.5.2"
-
-jest-diff@^26.0.0, jest-diff@^26.5.2:
- version "26.6.2"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394"
- integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==
- dependencies:
- chalk "^4.0.0"
- diff-sequences "^26.6.2"
- jest-get-type "^26.3.0"
- pretty-format "^26.6.2"
+ graceful-fs "^4.2.9"
+ jest-circus "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-jasmine2 "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
-jest-diff@^27.4.6:
- version "27.4.6"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d"
- integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w==
+jest-diff@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
+ integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
dependencies:
chalk "^4.0.0"
- diff-sequences "^27.4.0"
- jest-get-type "^27.4.0"
- pretty-format "^27.4.6"
+ diff-sequences "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
-jest-docblock@^26.0.0:
- version "26.0.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5"
- integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==
+jest-docblock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
+ integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==
dependencies:
detect-newline "^3.0.0"
-jest-each@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.5.2.tgz#35e68d6906a7f826d3ca5803cfe91d17a5a34c31"
- integrity sha512-w7D9FNe0m2D3yZ0Drj9CLkyF/mGhmBSULMQTypzAKR746xXnjUrK8GUJdlLTWUF6dd0ks3MtvGP7/xNFr9Aphg==
+jest-each@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e"
+ integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
chalk "^4.0.0"
- jest-get-type "^26.3.0"
- jest-util "^26.5.2"
- pretty-format "^26.5.2"
-
-jest-environment-jsdom@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.5.2.tgz#5feab05b828fd3e4b96bee5e0493464ddd2bb4bc"
- integrity sha512-fWZPx0bluJaTQ36+PmRpvUtUlUFlGGBNyGX1SN3dLUHHMcQ4WseNEzcGGKOw4U5towXgxI4qDoI3vwR18H0RTw==
- dependencies:
- "@jest/environment" "^26.5.2"
- "@jest/fake-timers" "^26.5.2"
- "@jest/types" "^26.5.2"
+ jest-get-type "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-environment-jsdom@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546"
+ integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
- jest-mock "^26.5.2"
- jest-util "^26.5.2"
- jsdom "^16.4.0"
-
-jest-environment-node@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.5.2.tgz#275a0f01b5e47447056f1541a15ed4da14acca03"
- integrity sha512-YHjnDsf/GKFCYMGF1V+6HF7jhY1fcLfLNBDjhAOvFGvt6d8vXvNdJGVM7uTZ2VO/TuIyEFhPGaXMX5j3h7fsrA==
- dependencies:
- "@jest/environment" "^26.5.2"
- "@jest/fake-timers" "^26.5.2"
- "@jest/types" "^26.5.2"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+ jsdom "^16.6.0"
+
+jest-environment-node@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e"
+ integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
- jest-mock "^26.5.2"
- jest-util "^26.5.2"
-
-jest-get-type@^26.3.0:
- version "26.3.0"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
- integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
-jest-get-type@^27.4.0:
- version "27.4.0"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5"
- integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==
+jest-get-type@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
+ integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
-jest-haste-map@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.5.2.tgz#a15008abfc502c18aa56e4919ed8c96304ceb23d"
- integrity sha512-lJIAVJN3gtO3k4xy+7i2Xjtwh8CfPcH08WYjZpe9xzveDaqGw9fVNCpkYu6M525wKFVkLmyi7ku+DxCAP1lyMA==
+jest-haste-map@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f"
+ integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
"@types/graceful-fs" "^4.1.2"
"@types/node" "*"
anymatch "^3.0.3"
fb-watchman "^2.0.0"
- graceful-fs "^4.2.4"
- jest-regex-util "^26.0.0"
- jest-serializer "^26.5.0"
- jest-util "^26.5.2"
- jest-worker "^26.5.0"
- micromatch "^4.0.2"
- sane "^4.0.3"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^27.5.1"
+ jest-serializer "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ micromatch "^4.0.4"
walker "^1.0.7"
optionalDependencies:
- fsevents "^2.1.2"
-
-jest-jasmine2@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.5.2.tgz#0e33819d31b1f2aab5efd1e02ce502209c0e64a2"
- integrity sha512-2J+GYcgLVPTkpmvHEj0/IDTIAuyblGNGlyGe4fLfDT2aktEPBYvoxUwFiOmDDxxzuuEAD2uxcYXr0+1Yw4tjFA==
- dependencies:
- "@babel/traverse" "^7.1.0"
- "@jest/environment" "^26.5.2"
- "@jest/source-map" "^26.5.0"
- "@jest/test-result" "^26.5.2"
- "@jest/types" "^26.5.2"
+ fsevents "^2.3.2"
+
+jest-jasmine2@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4"
+ integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
chalk "^4.0.0"
co "^4.6.0"
- expect "^26.5.2"
+ expect "^27.5.1"
is-generator-fn "^2.0.0"
- jest-each "^26.5.2"
- jest-matcher-utils "^26.5.2"
- jest-message-util "^26.5.2"
- jest-runtime "^26.5.2"
- jest-snapshot "^26.5.2"
- jest-util "^26.5.2"
- pretty-format "^26.5.2"
- throat "^5.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ throat "^6.0.1"
jest-junit@^12.0.0:
version "12.0.0"
@@ -7699,44 +7200,45 @@ jest-junit@^12.0.0:
uuid "^3.3.3"
xml "^1.0.1"
-jest-leak-detector@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.5.2.tgz#83fcf9a4a6ef157549552cb4f32ca1d6221eea69"
- integrity sha512-h7ia3dLzBFItmYERaLPEtEKxy3YlcbcRSjj0XRNJgBEyODuu+3DM2o62kvIFvs3PsaYoIIv+e+nLRI61Dj1CNw==
+jest-leak-detector@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
+ integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==
dependencies:
- jest-get-type "^26.3.0"
- pretty-format "^26.5.2"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
-jest-matcher-utils@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.5.2.tgz#6aa2c76ce8b9c33e66f8856ff3a52bab59e6c85a"
- integrity sha512-W9GO9KBIC4gIArsNqDUKsLnhivaqf8MSs6ujO/JDcPIQrmY+aasewweXVET8KdrJ6ADQaUne5UzysvF/RR7JYA==
+jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
+ integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
dependencies:
chalk "^4.0.0"
- jest-diff "^26.5.2"
- jest-get-type "^26.3.0"
- pretty-format "^26.5.2"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
-jest-message-util@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.5.2.tgz#6c4c4c46dcfbabb47cd1ba2f6351559729bc11bb"
- integrity sha512-Ocp9UYZ5Jl15C5PNsoDiGEk14A4NG0zZKknpWdZGoMzJuGAkVt10e97tnEVMYpk7LnQHZOfuK2j/izLBMcuCZw==
+jest-message-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
+ integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==
dependencies:
- "@babel/code-frame" "^7.0.0"
- "@jest/types" "^26.5.2"
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^27.5.1"
"@types/stack-utils" "^2.0.0"
chalk "^4.0.0"
- graceful-fs "^4.2.4"
- micromatch "^4.0.2"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^27.5.1"
slash "^3.0.0"
- stack-utils "^2.0.2"
+ stack-utils "^2.0.3"
-jest-mock@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.5.2.tgz#c9302e8ef807f2bfc749ee52e65ad11166a1b6a1"
- integrity sha512-9SiU4b5PtO51v0MtJwVRqeGEroH66Bnwtq4ARdNP7jNXbpT7+ByeWNAk4NeT/uHfNSVDXEXgQo1XRuwEqS6Rdw==
+jest-mock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6"
+ integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
jest-pnp-resolver@^1.2.2:
@@ -7749,120 +7251,125 @@ jest-raw-loader@^1.0.1:
resolved "https://registry.yarnpkg.com/jest-raw-loader/-/jest-raw-loader-1.0.1.tgz#ce9f56d54650f157c4a7d16d224ba5d613bcd626"
integrity sha1-zp9W1UZQ8VfEp9FtIkul1hO81iY=
-jest-regex-util@^26.0.0:
- version "26.0.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28"
- integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==
+jest-regex-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95"
+ integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==
-jest-resolve-dependencies@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.5.2.tgz#ee30b7cfea81c81bf5e195a9287d7ec07f893170"
- integrity sha512-LLkc8LuRtxqOx0AtX/Npa2C4I23WcIrwUgNtHYXg4owYF/ZDQShcwBAHjYZIFR06+HpQcZ43+kCTMlQ3aDCYTg==
+jest-resolve-dependencies@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8"
+ integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==
dependencies:
- "@jest/types" "^26.5.2"
- jest-regex-util "^26.0.0"
- jest-snapshot "^26.5.2"
+ "@jest/types" "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-snapshot "^27.5.1"
-jest-resolve@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.5.2.tgz#0d719144f61944a428657b755a0e5c6af4fc8602"
- integrity sha512-XsPxojXGRA0CoDD7Vis59ucz2p3cQFU5C+19tz3tLEAlhYKkK77IL0cjYjikY9wXnOaBeEdm1rOgSJjbZWpcZg==
+jest-resolve@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384"
+ integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
chalk "^4.0.0"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
jest-pnp-resolver "^1.2.2"
- jest-util "^26.5.2"
- read-pkg-up "^7.0.1"
- resolve "^1.17.0"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ resolve "^1.20.0"
+ resolve.exports "^1.1.0"
slash "^3.0.0"
-jest-runner@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.5.2.tgz#4f9e6b0bb7eb4710c209a9e145b8a10894f4c19f"
- integrity sha512-GKhYxtSX5+tXZsd2QwfkDqPIj5C2HqOdXLRc2x2qYqWE26OJh17xo58/fN/mLhRkO4y6o60ZVloan7Kk5YA6hg==
+jest-runner@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5"
+ integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==
dependencies:
- "@jest/console" "^26.5.2"
- "@jest/environment" "^26.5.2"
- "@jest/test-result" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/console" "^27.5.1"
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
chalk "^4.0.0"
- emittery "^0.7.1"
- exit "^0.1.2"
- graceful-fs "^4.2.4"
- jest-config "^26.5.2"
- jest-docblock "^26.0.0"
- jest-haste-map "^26.5.2"
- jest-leak-detector "^26.5.2"
- jest-message-util "^26.5.2"
- jest-resolve "^26.5.2"
- jest-runtime "^26.5.2"
- jest-util "^26.5.2"
- jest-worker "^26.5.0"
+ emittery "^0.8.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-leak-detector "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
source-map-support "^0.5.6"
- throat "^5.0.0"
-
-jest-runtime@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.5.2.tgz#b72f5f79eb2fe0c46bfef4cdb9c1e01d1c69ba41"
- integrity sha512-zArr4DatX/Sn0wswX/AnAuJgmwgAR5rNtrUz36HR8BfMuysHYNq5sDbYHuLC4ICyRdy5ae/KQ+sczxyS9G6Qvw==
- dependencies:
- "@jest/console" "^26.5.2"
- "@jest/environment" "^26.5.2"
- "@jest/fake-timers" "^26.5.2"
- "@jest/globals" "^26.5.2"
- "@jest/source-map" "^26.5.0"
- "@jest/test-result" "^26.5.2"
- "@jest/transform" "^26.5.2"
- "@jest/types" "^26.5.2"
- "@types/yargs" "^15.0.0"
+ throat "^6.0.1"
+
+jest-runtime@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af"
+ integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/globals" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
collect-v8-coverage "^1.0.0"
- exit "^0.1.2"
+ execa "^5.0.0"
glob "^7.1.3"
- graceful-fs "^4.2.4"
- jest-config "^26.5.2"
- jest-haste-map "^26.5.2"
- jest-message-util "^26.5.2"
- jest-mock "^26.5.2"
- jest-regex-util "^26.0.0"
- jest-resolve "^26.5.2"
- jest-snapshot "^26.5.2"
- jest-util "^26.5.2"
- jest-validate "^26.5.2"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
slash "^3.0.0"
strip-bom "^4.0.0"
- yargs "^15.4.1"
-jest-serializer@^26.5.0:
- version "26.5.0"
- resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.5.0.tgz#f5425cc4c5f6b4b355f854b5f0f23ec6b962bc13"
- integrity sha512-+h3Gf5CDRlSLdgTv7y0vPIAoLgX/SI7T4v6hy+TEXMgYbv+ztzbg5PSN6mUXAT/hXYHvZRWm+MaObVfqkhCGxA==
+jest-serializer@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64"
+ integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==
dependencies:
"@types/node" "*"
- graceful-fs "^4.2.4"
+ graceful-fs "^4.2.9"
-jest-snapshot@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.5.2.tgz#0cf7642eaf8e8d2736bd443f619959bf237f9ccf"
- integrity sha512-MkXIDvEefzDubI/WaDVSRH4xnkuirP/Pz8LhAIDXcVQTmcEfwxywj5LGwBmhz+kAAIldA7XM4l96vbpzltSjqg==
+jest-snapshot@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1"
+ integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==
dependencies:
+ "@babel/core" "^7.7.2"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/traverse" "^7.7.2"
"@babel/types" "^7.0.0"
- "@jest/types" "^26.5.2"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/babel__traverse" "^7.0.4"
- "@types/prettier" "^2.0.0"
+ "@types/prettier" "^2.1.5"
+ babel-preset-current-node-syntax "^1.0.0"
chalk "^4.0.0"
- expect "^26.5.2"
- graceful-fs "^4.2.4"
- jest-diff "^26.5.2"
- jest-get-type "^26.3.0"
- jest-haste-map "^26.5.2"
- jest-matcher-utils "^26.5.2"
- jest-message-util "^26.5.2"
- jest-resolve "^26.5.2"
+ expect "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
natural-compare "^1.4.0"
- pretty-format "^26.5.2"
+ pretty-format "^27.5.1"
semver "^7.3.2"
jest-transform-graphql@^2.1.0:
@@ -7870,65 +7377,60 @@ jest-transform-graphql@^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@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.5.2.tgz#8403f75677902cc52a1b2140f568e91f8ed4f4d7"
- integrity sha512-WTL675bK+GSSAYgS8z9FWdCT2nccO1yTIplNLPlP0OD8tUk/H5IrWKMMRudIQQ0qp8bb4k+1Qa8CxGKq9qnYdg==
+jest-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
+ integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==
dependencies:
- "@jest/types" "^26.5.2"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
chalk "^4.0.0"
- graceful-fs "^4.2.4"
- is-ci "^2.0.0"
- micromatch "^4.0.2"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
-jest-validate@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.5.2.tgz#7ea266700b64234cd1c0cee982490c5a80e9b0f0"
- integrity sha512-FmJks0zY36mp6Af/5sqO6CTL9bNMU45yKCJk3hrz8d2aIqQIlN1pr9HPIwZE8blLaewOla134nt5+xAmWsx3SQ==
+jest-validate@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067"
+ integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==
dependencies:
- "@jest/types" "^26.5.2"
- camelcase "^6.0.0"
+ "@jest/types" "^27.5.1"
+ camelcase "^6.2.0"
chalk "^4.0.0"
- jest-get-type "^26.3.0"
+ jest-get-type "^27.5.1"
leven "^3.1.0"
- pretty-format "^26.5.2"
+ pretty-format "^27.5.1"
-jest-watcher@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.5.2.tgz#2957f4461007e0769d74b537379ecf6b7c696916"
- integrity sha512-i3m1NtWzF+FXfJ3ljLBB/WQEp4uaNhX7QcQUWMokcifFTUQBDFyUMEwk0JkJ1kopHbx7Een3KX0Q7+9koGM/Pw==
+jest-watcher@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2"
+ integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==
dependencies:
- "@jest/test-result" "^26.5.2"
- "@jest/types" "^26.5.2"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
"@types/node" "*"
ansi-escapes "^4.2.1"
chalk "^4.0.0"
- jest-util "^26.5.2"
+ jest-util "^27.5.1"
string-length "^4.0.1"
-jest-worker@^26.5.0:
- version "26.5.0"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.5.0.tgz#87deee86dbbc5f98d9919e0dadf2c40e3152fa30"
- integrity sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==
+jest-worker@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
dependencies:
"@types/node" "*"
merge-stream "^2.0.0"
- supports-color "^7.0.0"
+ supports-color "^8.0.0"
-jest@^26.5.2:
- version "26.5.2"
- resolved "https://registry.yarnpkg.com/jest/-/jest-26.5.2.tgz#c6791642b331fe7abd2f993b0a74aa546f7be0fb"
- integrity sha512-4HFabJVwsgDwul/7rhXJ3yFAF/aUkVIXiJWmgFxb+WMdZG39fVvOwYAs8/3r4AlFPc4m/n5sTMtuMbOL3kNtrQ==
+jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc"
+ integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
dependencies:
- "@jest/core" "^26.5.2"
+ "@jest/core" "^27.5.1"
import-local "^3.0.2"
- jest-cli "^26.5.2"
-
-jmespath@0.15.0:
- version "0.15.0"
- resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
- integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=
+ jest-cli "^27.5.1"
jquery.caret@^0.3.1:
version "0.3.1"
@@ -7961,7 +7463,7 @@ js-cookie@^3.0.0:
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.13.1, js-yaml@^3.14.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==
@@ -7976,71 +7478,37 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
-js2xmlparser@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-3.0.0.tgz#3fb60eaa089c5440f9319f51760ccd07e2499733"
- integrity sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=
- dependencies:
- xmlcreate "^1.0.1"
-
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-jsdoc-vue@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/jsdoc-vue/-/jsdoc-vue-1.0.0.tgz#ff3ac1ba6bc4a74079bb79058a7bf0066e346235"
- integrity sha1-/zrBumvEp0B5u3kFinvwBm40YjU=
-
-jsdoc@^3.5.5:
- version "3.5.5"
- resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.5.5.tgz#484521b126e81904d632ff83ec9aaa096708fa4d"
- integrity sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==
- dependencies:
- babylon "7.0.0-beta.19"
- bluebird "~3.5.0"
- catharsis "~0.8.9"
- escape-string-regexp "~1.0.5"
- js2xmlparser "~3.0.0"
- klaw "~2.0.0"
- marked "~0.3.6"
- mkdirp "~0.5.1"
- requizzle "~0.2.1"
- strip-json-comments "~2.0.1"
- taffydb "2.6.2"
- underscore "~1.8.3"
-
-jsdom@^16.4.0:
- version "16.4.0"
- resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb"
- integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==
+jsdom@^16.6.0:
+ version "16.7.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
+ integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==
dependencies:
- abab "^2.0.3"
- acorn "^7.1.1"
+ abab "^2.0.5"
+ acorn "^8.2.4"
acorn-globals "^6.0.0"
cssom "^0.4.4"
- cssstyle "^2.2.0"
+ cssstyle "^2.3.0"
data-urls "^2.0.0"
- decimal.js "^10.2.0"
+ decimal.js "^10.2.1"
domexception "^2.0.1"
- escodegen "^1.14.1"
+ escodegen "^2.0.0"
+ form-data "^3.0.0"
html-encoding-sniffer "^2.0.1"
- is-potential-custom-element-name "^1.0.0"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-potential-custom-element-name "^1.0.1"
nwsapi "^2.2.0"
- parse5 "5.1.1"
- request "^2.88.2"
- request-promise-native "^1.0.8"
- saxes "^5.0.0"
+ parse5 "6.0.1"
+ saxes "^5.0.1"
symbol-tree "^3.2.4"
- tough-cookie "^3.0.1"
+ tough-cookie "^4.0.0"
w3c-hr-time "^1.0.2"
w3c-xmlserializer "^2.0.0"
webidl-conversions "^6.1.0"
whatwg-encoding "^1.0.5"
whatwg-mimetype "^2.3.0"
- whatwg-url "^8.0.0"
- ws "^7.2.3"
+ whatwg-url "^8.5.0"
+ ws "^7.4.6"
xml-name-validator "^3.0.0"
jsesc@^2.5.1:
@@ -8053,11 +7521,6 @@ jsesc@~0.5.0:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
-json-buffer@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
- integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-
json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -8078,21 +7541,11 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
-json-stringify-safe@~5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
- integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
@@ -8105,11 +7558,6 @@ json5@^2.1.2, json5@^2.2.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
-jsonc-parser@^2.2.1, jsonc-parser@^2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.1.tgz#59549150b133f2efacca48fe9ce1ec0659af2342"
- integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==
-
jsonc-parser@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22"
@@ -8122,16 +7570,6 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
-
jszip-utils@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/jszip-utils/-/jszip-utils-0.0.2.tgz#457d5cbca60a1c2e0706e9da2b544e8e7bc50bf8"
@@ -8155,13 +7593,6 @@ katex@^0.13.2:
dependencies:
commander "^6.0.0"
-keyv@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
- integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
- dependencies:
- json-buffer "3.0.0"
-
khroma@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.0.0.tgz#7577de98aed9f36c7a474c4d453d94c0d6c6588b"
@@ -8198,13 +7629,6 @@ klaw-sync@^6.0.0:
dependencies:
graceful-fs "^4.1.11"
-klaw@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/klaw/-/klaw-2.0.0.tgz#59c128e0dc5ce410201151194eeb9cbf858650f6"
- integrity sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=
- dependencies:
- graceful-fs "^4.1.9"
-
kleur@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
@@ -8220,13 +7644,6 @@ known-css-properties@^0.25.0:
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==
-latest-version@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
- integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
- dependencies:
- package-json "^6.3.0"
-
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -8267,6 +7684,13 @@ linkify-it@^3.0.1:
dependencies:
uc.micro "^1.0.1"
+linkify-it@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
+ integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
+ dependencies:
+ uc.micro "^1.0.1"
+
linkifyjs@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.5.tgz#99e51a3a0c0e232fcb63ebb89eea3ff923378f34"
@@ -8318,6 +7742,13 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@@ -8433,11 +7864,6 @@ lodash.snakecase@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
-lodash.sortby@^4.7.0:
- version "4.7.0"
- resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
- integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-
lodash.truncate@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
@@ -8458,7 +7884,7 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
-lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
+lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -8475,24 +7901,6 @@ loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
-lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
- integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
-
-lowercase-keys@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
- integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
-lowlight@^1.20.0:
- version "1.20.0"
- resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888"
- integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==
- dependencies:
- fault "^1.0.0"
- highlight.js "~10.7.0"
-
lowlight@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-2.6.1.tgz#d3cbc7ae0530c848e512b8e6528609587520b44f"
@@ -8578,7 +7986,7 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-markdown-it@12.3.2, markdown-it@^12.0.0:
+markdown-it@12.3.2:
version "12.3.2"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
@@ -8589,6 +7997,17 @@ markdown-it@12.3.2, markdown-it@^12.0.0:
mdurl "^1.0.1"
uc.micro "^1.0.5"
+markdown-it@^13.0.1:
+ version "13.0.1"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
+ integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
+ dependencies:
+ argparse "^2.0.1"
+ entities "~3.0.1"
+ linkify-it "^4.0.1"
+ mdurl "^1.0.1"
+ uc.micro "^1.0.5"
+
markdown-table@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c"
@@ -8622,10 +8041,10 @@ markdownlint@~0.25.1:
dependencies:
markdown-it "12.3.2"
-marked@^0.3.12, marked@~0.3.6:
- version "0.3.19"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790"
- integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==
+marked@^4.0.18:
+ version "4.0.18"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.18.tgz#cd0ac54b2e5610cfb90e8fd46ccaa8292c9ed569"
+ integrity sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==
mathjax@3:
version "3.1.2"
@@ -8645,15 +8064,6 @@ md5.js@^1.3.4:
hash-base "^3.0.0"
inherits "^2.0.1"
-md5@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
- integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
- dependencies:
- charenc "~0.0.1"
- crypt "~0.0.1"
- is-buffer "~1.1.1"
-
mdast-util-definitions@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.0.tgz#b6d10ef00a3c4cf191e8d9a5fa58d7f4a366f817"
@@ -8690,6 +8100,13 @@ mdast-util-from-markdown@^1.0.0:
unist-util-stringify-position "^3.0.0"
uvu "^0.5.0"
+mdast-util-frontmatter@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.0.tgz#ef12469379782e4a0fd995fed60cc3b871e6c819"
+ integrity sha512-7itKvp0arEVNpCktOET/eLFAYaZ+0cNjVtFtIPxgQ5tV+3i+D4SDDTjTzPWl44LT59PC+xdx+glNTawBdF98Mw==
+ dependencies:
+ micromark-extension-frontmatter "^1.0.0"
+
mdast-util-gfm-autolink-literal@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970"
@@ -8781,6 +8198,11 @@ mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0:
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9"
integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==
+mdn-data@2.0.27:
+ version "2.0.27"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.27.tgz#1710baa7b0db8176d3b3d565ccb7915fc69525ab"
+ integrity sha512-kwqO0I0jtWr25KcfLm9pia8vLZ8qoAKhWZuZMbneJq3jjBD3gl5nZs8l8Tu3ZBlBAHVQtDur9rdDGyvtfVraHQ==
+
mdurl@^1.0.0, mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
@@ -8859,16 +8281,16 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-mermaid@^9.1.1:
- version "9.1.1"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.1.1.tgz#5d3d330ca4adf7f3c8ca51095f8bb2f0fb1a93bb"
- integrity sha512-2RVD+WkzZ4VDyO9gQvQAuQ/ux2gLigJtKDTlbwjYqOR/NwsVzTSfGm/kx648/qWJsg6Sv04tE9BWCO8s6a+pFA==
+mermaid@^9.1.3:
+ version "9.1.3"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.1.3.tgz#15d08662c66250124ce31106a4620285061ac59c"
+ integrity sha512-jTIYiqKwsUXVCoxHUVkK8t0QN3zSKIdJlb9thT0J5jCnzXyc+gqTbZE2QmjRfavFTPPn5eRy5zaFp7V+6RhxYg==
dependencies:
"@braintree/sanitize-url" "^6.0.0"
d3 "^7.0.0"
dagre "^0.8.5"
dagre-d3 "^0.6.4"
- dompurify "2.3.6"
+ dompurify "2.3.8"
graphlib "^2.1.8"
khroma "^2.0.0"
moment-mini "^2.24.0"
@@ -8906,6 +8328,15 @@ micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1:
micromark-util-types "^1.0.1"
uvu "^0.5.0"
+micromark-extension-frontmatter@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.0.0.tgz#612498e6dad87c132c95e25f0918e7cc0cd535f6"
+ integrity sha512-EXjmRnupoX6yYuUJSQhrQ9ggK0iQtQlpi6xeJzVD5xscyAI+giqco5fdymayZhJMbIFecjnE2yz85S9NzIgQpg==
+ dependencies:
+ fault "^2.0.0"
+ micromark-util-character "^1.0.0"
+ micromark-util-symbol "^1.0.0"
+
micromark-extension-gfm-autolink-literal@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058"
@@ -9159,7 +8590,7 @@ micromark@^3.0.0:
micromark-util-types "^1.0.1"
uvu "^0.5.0"
-micromatch@^3.1.10, micromatch@^3.1.4:
+micromatch@^3.1.10:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -9199,7 +8630,7 @@ mime-db@1.52.0, "mime-db@>= 1.40.0 < 2":
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@@ -9221,11 +8652,6 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-mimic-response@^1.0.0, mimic-response@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
- integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
-
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
@@ -9278,7 +8704,7 @@ minimist-options@4.1.0:
is-plain-obj "^1.1.0"
kind-of "^6.0.3"
-minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
@@ -9375,7 +8801,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
+mkdirp@^0.5.1, mkdirp@^0.5.3:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
@@ -9397,24 +8823,26 @@ moment-mini@^2.24.0:
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18"
integrity sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==
-monaco-editor-webpack-plugin@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.0.0.tgz#95be3f48f4220999b909266a9997727f0deab947"
- integrity sha512-4BT9XDRQXraMQjxEUjR+uuubRe3RIPkvVoGw8zwWG++s7wq6TAiXaSOMdkdS9TrjCREgSnygCOlVzY6MS8RPuA==
+monaco-editor-webpack-plugin@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-6.0.0.tgz#628956ce1851afa2a5f6c88d0ecbb24e9a444898"
+ integrity sha512-vC886Mzpd2AkSM35XLkfQMjH+Ohz6RISVwhAejDUzZDheJAiz6G34lky1vyO8fZ702v7IrcKmsGwL1rRFnwvUA==
dependencies:
loader-utils "^2.0.0"
-monaco-editor@^0.25.2:
- version "0.25.2"
- resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.25.2.tgz#119e2b15bbd968a1a99c03cac9c329316d7c37e9"
- integrity sha512-5iylzSJevCnzJn9UVsW8yOZ3yHjmAs4TfvH3zsbftKiFKmHG0xirGN6DK9Kk04VSWxYCZZAIafYJoNJJMAU1KA==
+monaco-editor@^0.30.1:
+ version "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@^2.5.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/monaco-yaml/-/monaco-yaml-2.5.1.tgz#af9303a4aa6e3b94db62b8a8659362f31944590d"
- integrity sha512-U+zIAcwnQzlUgy6vdzFdNf5PToFzuz099FxYmUxIeen9GTiq6XYDX9mmXSR31mMrgiSaU5a2bGEyG4p2fbW/7A==
+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:
- yaml-language-server "^0.11.1"
+ "@types/json-schema" "^7.0.8"
+ js-yaml "^3.14.1"
+ yaml-ast-parser-custom-tags "^0.0.43"
mousetrap@1.6.5:
version "1.6.5"
@@ -9559,43 +8987,26 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
-node-modules-regexp@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
- integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
-
-node-notifier@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620"
- integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==
- dependencies:
- growly "^1.3.0"
- is-wsl "^2.2.0"
- semver "^7.3.2"
- shellwords "^0.1.1"
- uuid "^8.3.0"
- which "^2.0.2"
-
node-releases@^2.0.3:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
- integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
-
-nodemon@^2.0.4:
version "2.0.4"
- resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416"
- integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476"
+ integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==
+
+nodemon@^2.0.19:
+ version "2.0.19"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.19.tgz#cac175f74b9cb8b57e770d47841995eebe4488bd"
+ integrity sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==
dependencies:
- chokidar "^3.2.2"
- debug "^3.2.6"
+ chokidar "^3.5.2"
+ debug "^3.2.7"
ignore-by-default "^1.0.1"
minimatch "^3.0.4"
- pstree.remy "^1.1.7"
+ pstree.remy "^1.1.8"
semver "^5.7.1"
+ simple-update-notifier "^1.0.7"
supports-color "^5.5.0"
touch "^3.1.0"
- undefsafe "^2.0.2"
- update-notifier "^4.0.0"
+ undefsafe "^2.0.5"
nopt@^4.0.3:
version "4.0.3"
@@ -9644,19 +9055,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-normalize-url@^4.1.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
- integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
-
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
- dependencies:
- path-key "^2.0.0"
-
-npm-run-path@^4.0.0, npm-run-path@^4.0.1:
+npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@@ -9675,11 +9074,6 @@ nwsapi@^2.2.0:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -9770,7 +9164,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
-onetime@^5.1.0, onetime@^5.1.2:
+onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
@@ -9831,10 +9225,10 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
-orderedmap@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-1.1.1.tgz#c618e77611b3b21d0fe3edc92586265e0059c789"
- integrity sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==
+orderedmap@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.0.0.tgz#12ff5ef6ea9d12d6430b80c701b35475e1c9ff34"
+ integrity sha512-buf4PoAMlh45b8a8gsGy/X6w279TSqkyAS0C0wdTSJwFSU+ljQFJON5I8NfjLHoCXwpSROIo2wr0g33T+kQshQ==
os-browserify@^0.3.0:
version "0.3.0"
@@ -9859,21 +9253,6 @@ osenv@^0.1.4:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
-p-cancelable@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
- integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
-
-p-each-series@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48"
- integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-
p-limit@3.1.0, p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
@@ -9916,6 +9295,13 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
@@ -9941,16 +9327,6 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-package-json@^6.3.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
- integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
- dependencies:
- got "^9.6.0"
- registry-auth-token "^4.0.0"
- registry-url "^5.0.0"
- semver "^6.2.0"
-
pako@~1.0.2, pako@~1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
@@ -9995,7 +9371,7 @@ parse-color@^1.0.0:
dependencies:
color-convert "~0.5.0"
-parse-json@^5.0.0:
+parse-json@^5.0.0, parse-json@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
@@ -10012,16 +9388,11 @@ parse5-htmlparser2-tree-adapter@^6.0.0, parse5-htmlparser2-tree-adapter@^6.0.1:
dependencies:
parse5 "^6.0.1"
-"parse5@5 - 6", parse5@^6.0.0, parse5@^6.0.1:
+"parse5@5 - 6", parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
-parse5@5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
- integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
-
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -10071,10 +9442,10 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-path-key@^2.0.0, path-key@^2.0.1:
+path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+ integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
path-key@^3.0.0, path-key@^3.1.0:
version "3.1.1"
@@ -10115,11 +9486,6 @@ pdfjs-dist@^2.0.943:
node-ensure "^0.0.0"
worker-loader "^2.0.0"
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
picocolors@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
@@ -10130,7 +9496,7 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
@@ -10145,12 +9511,10 @@ pikaday@^1.8.0:
resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.8.0.tgz#ce930e257042e852e6aadee1115e01554b2d71c5"
integrity sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA==
-pirates@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
- integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
- dependencies:
- node-modules-regexp "^1.0.0"
+pirates@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
+ integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==
pkg-dir@^3.0.0:
version "3.0.0"
@@ -10288,11 +9652,6 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-prepend-http@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
- integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-
pretender@^3.4.3:
version "3.4.3"
resolved "https://registry.yarnpkg.com/pretender/-/pretender-3.4.3.tgz#a3b4160516007075d29127262f3a0063d19896e9"
@@ -10301,11 +9660,6 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
- integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
-
prettier@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
@@ -10316,7 +9670,7 @@ prettier@^1.18.2:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
-pretty-format@^26.0.0, pretty-format@^26.4.2, pretty-format@^26.5.2, pretty-format@^26.6.2:
+pretty-format@^26.4.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
@@ -10326,10 +9680,10 @@ pretty-format@^26.0.0, pretty-format@^26.4.2, pretty-format@^26.5.2, pretty-form
ansi-styles "^4.0.0"
react-is "^17.0.1"
-pretty-format@^27.4.6:
- version "27.4.6"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7"
- integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==
+pretty-format@^27.0.0, pretty-format@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
dependencies:
ansi-regex "^5.0.1"
ansi-styles "^5.0.0"
@@ -10366,11 +9720,6 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
-progress@^2.0.0:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
- integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
-
promise-inflight@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
@@ -10398,120 +9747,110 @@ property-information@^6.0.0:
resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22"
integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==
-prosemirror-commands@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.2.1.tgz#eae0cb714df695260659b78ff5d201d3a037e50d"
- integrity sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==
+prosemirror-commands@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.3.0.tgz#361b2e2b2a347ce7453386459f97c3f549a1113b"
+ integrity sha512-BwBbZ5OAScPcm0x7H8SPbqjuEJnCU2RJT9LDyOiiIl/3NbL1nJZI4SFNHwU2e/tRr2Xe7JsptpzseqvZvToLBQ==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-dropcursor@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz#91a859d4ee79c99b1c0ba6ee61c093b195c0d9f0"
- integrity sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==
+prosemirror-dropcursor@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.5.0.tgz#edbc61d6f71f9f924130eec8e85b0861357957c9"
+ integrity sha512-vy7i77ddKyXlu8kKBB3nlxLBnsWyKUmQIPB5x8RkYNh01QNp/qqGmdd5yZefJs0s3rtv5r7Izfu2qbtr+tYAMQ==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
prosemirror-view "^1.1.0"
-prosemirror-gapcursor@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.1.tgz#02365e1bcc1ad25d390b0fb7f0e94a7fc173ad75"
- integrity sha512-PHa9lj27iM/g4C46gxVzsefuXVfy/LrGQH4QjMRht7VDBgw77iWYWn8ZHMWSFkwtr9jQEuxI5gccHHHwWG80nw==
+prosemirror-gapcursor@^1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.1.tgz#8cfd874592e4504d63720e14ed680c7866e64554"
+ integrity sha512-GKTeE7ZoMsx5uVfc51/ouwMFPq0o8YrZ7Hx4jTF4EeGbXxBveUV8CGv46mSHuBBeXGmvu50guoV2kSnOeZZnUA==
dependencies:
prosemirror-keymap "^1.0.0"
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-view "^1.0.0"
-prosemirror-history@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.2.0.tgz#04cc4df8d2f7b2a46651a2780de191ada6d465ea"
- integrity sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==
+prosemirror-history@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.3.0.tgz#bf5a1ff7759aca759ddf0c722c2fa5b14fb0ddc1"
+ integrity sha512-qo/9Wn4B/Bq89/YD+eNWFbAytu6dmIM85EhID+fz9Jcl9+DfGEo8TTSrRhP15+fFEoaPqpHSxlvSzSEbmlxlUA==
dependencies:
prosemirror-state "^1.2.2"
prosemirror-transform "^1.0.0"
rope-sequence "^1.3.0"
-prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz#b5984c7d30f5c75956c853126c54e9e624c0327b"
- integrity sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==
+prosemirror-keymap@1.2.0, prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.2.0.tgz#d5cc9da9b712020690a994b50b92a0e448a60bf5"
+ integrity sha512-TdSfu+YyLDd54ufN/ZeD1VtBRYpgZnTPnnbY+4R08DDgs84KrIPEPbJL8t1Lm2dkljFx6xeBE26YWH3aIzkPKg==
dependencies:
prosemirror-state "^1.0.0"
w3c-keyname "^2.2.0"
-prosemirror-markdown@1.8.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.8.0.tgz#4ae430470f9e433d6fb9d1e981842d7e4f664f69"
- integrity sha512-RxGyM8dqdmlkYpM3PY/C5JBputv2xeKLNRqFpN04TtFlR9McN9Tmpf8DaP6HblfaZ8RofdUtQW+ghdArjANLvQ==
+prosemirror-markdown@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.9.1.tgz#37d58cf7ccc5d0771b2be1fd41bc46e9daed9a94"
+ integrity sha512-qvCvkbpeXFoohB5M0/cfQuDRB2uh5yw7OMterDE4xvwCAbEMiaCzCzgrzm5DOehYrHkaTiybDw+DZBqGTE/kRA==
dependencies:
- markdown-it "^12.0.0"
+ markdown-it "^13.0.1"
prosemirror-model "^1.0.0"
-prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.16.1, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.16.1.tgz#fb388270bc9609b66298d6a7e15d0cc1d6c61253"
- integrity sha512-r1/w0HDU40TtkXp0DyKBnFPYwd8FSlUSJmGCGFv4DeynfeSlyQF2FD0RQbVEMOe6P3PpUSXM6LZBV7W/YNZ4mA==
+prosemirror-model@1.18.1, prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
+ version "1.18.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.18.1.tgz#1d5d6b6de7b983ee67a479dc607165fdef3935bd"
+ integrity sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==
dependencies:
- orderedmap "^1.1.0"
+ orderedmap "^2.0.0"
-prosemirror-schema-basic@^1.0.0, prosemirror-schema-basic@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.1.2.tgz#4bde5c339c845e0d08ec8fe473064e372ca51ae3"
- integrity sha512-G4q8WflNsR1Q33QAV4MQO0xWrHLOJ+BQcKswGXMy626wlQj6c/1n1v4eC9ns+h2y1r/fJHZEgSZnsNhm9lbrDw==
+prosemirror-schema-basic@^1.0.0, prosemirror-schema-basic@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.0.tgz#c33ad74426efae1d41e2260371866f623e8eb10e"
+ integrity sha512-JMN/ammP94ObOUS6cpIy121r0MEDN9V95mAxFVALwC4bbmhpWXGjBGHTA5LHPPdbqZKyR6Jar1Akv4Z5k9CNLw==
dependencies:
prosemirror-model "^1.2.0"
-prosemirror-schema-list@^1.0.0, prosemirror-schema-list@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz#c3e13fe2f74750e4a53ff88d798dc0c4ccca6707"
- integrity sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==
+prosemirror-schema-list@1.2.0, prosemirror-schema-list@^1.0.0, prosemirror-schema-list@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.2.0.tgz#1932268593a7396c0ac168cbe31f28187406ce24"
+ integrity sha512-8PT/9xOx1HHdC7fDNNfhQ50Z8Mzu7nKyA1KCDltSpcZVZIbB0k7KtsHrnXyuIhbLlScoymBiLZ00c5MH6wdFsA==
dependencies:
prosemirror-model "^1.0.0"
+ prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.3.4.tgz#4c6b52628216e753fc901c6d2bfd84ce109e8952"
- integrity sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==
+prosemirror-state@1.4.1, prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.4.1.tgz#f6e26c7b6a7e11206176689eb6ebbf91870953e1"
+ integrity sha512-U/LBDW2gNmVa07sz/D229XigSdDQ5CLFwVB1Vb32MJbAHHhWe/6pOc721faI17tqw4pZ49i1xfY/jEZ9tbIhPg==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-tables@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.1.1.tgz#ad66300cc49500455cf1243bb129c9e7d883321e"
- integrity sha512-LmCz4jrlqQZRsYRDzCRYf/pQ5CUcSOyqZlAj5kv67ZWBH1SVLP2U9WJEvQfimWgeRlIz0y0PQVqO1arRm1+woA==
- dependencies:
- prosemirror-keymap "^1.1.2"
- prosemirror-model "^1.8.1"
- prosemirror-state "^1.3.1"
- prosemirror-transform "^1.2.1"
- prosemirror-view "^1.13.3"
-
-prosemirror-test-builder@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/prosemirror-test-builder/-/prosemirror-test-builder-1.0.6.tgz#5b3df044beee6050791e96abc80fb48e66be30ea"
- integrity sha512-71pbSJqaqUJfbLwGett1yhMRQ/TV7QcOPfHvj6X9U/u/nQeZQNnsHsaVBpUeLgICADtusQSVPvyeGC0LGknwgA==
+prosemirror-test-builder@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-test-builder/-/prosemirror-test-builder-1.1.0.tgz#70d0b10d56e45dff47e0e4b0a1b29c4403a5d9e6"
+ integrity sha512-8fHiArJ5U3GyIjEriC02d9AcfFVYRKOarlV2aehdN5qEVO0YFFPCHoeaFeneInA29ubHycNQua7HqgykWHqr+w==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-schema-basic "^1.0.0"
prosemirror-schema-list "^1.0.0"
-prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.3.3.tgz#5f6712b0577a119cc418686fe7588b6dd9b7464d"
- integrity sha512-9NLVXy1Sfa2G6qPqhWMkEvwQQMTw7OyTqOZbJaGQWsCeH3hH5Cw+c5eNaLM1Uu75EyKLsEZhJ93XpHJBa6RX8A==
+prosemirror-transform@1.6.0, prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.6.0.tgz#8162dbfaf124f9253a7ab28605a9460411a96a53"
+ integrity sha512-MAp7AjsjEGEqQY0sSMufNIUuEyB1ZR9Fqlm8dTwwWwpEJRv/plsKjWXBbx52q3Ml8MtaMcd7ic14zAHVB3WaMw==
dependencies:
prosemirror-model "^1.0.0"
-prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.23.13, prosemirror-view@^1.23.6:
- version "1.23.13"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.13.tgz#d423c601d33ad3adfd1ab73fb72270acc9de9adf"
- integrity sha512-X/NcwZv8pgcEWfs3n++Wz4nDgqDIeDvJ9kfCk6DCoC9XUlDekqJLFt9wCcCUBXedb8hs/dmd+JmcaLgbr67XZw==
+prosemirror-view@1.26.2, prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.26.1:
+ version "1.26.2"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.26.2.tgz#e673894ecf26aea330b727622d561c51b41d31eb"
+ integrity sha512-CGKw+GadkfSBEwRAJTHCEKJ4DlV6/3IhAdjpwGyZHUHtbP7jX4Ol4zmi7xa2c6GOabDlIJLYXJydoNYLX7lNeQ==
dependencies:
prosemirror-model "^1.16.0"
prosemirror-state "^1.0.0"
@@ -10540,12 +9879,12 @@ pseudomap@^1.0.2:
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-psl@^1.1.28:
+psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
-pstree.remy@^1.1.7:
+pstree.remy@^1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
@@ -10596,13 +9935,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-pupa@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726"
- integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==
- dependencies:
- escape-goat "^2.0.0"
-
purgecss-from-html@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/purgecss-from-html/-/purgecss-from-html-4.0.3.tgz#28d86d3dc8292581c4ab529a77a57daf7c2dd940"
@@ -10626,11 +9958,6 @@ qs@6.9.7:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==
-qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -10696,16 +10023,6 @@ raw-loader@^4.0.2:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
-rc@^1.2.8:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -10837,7 +10154,7 @@ regexp.prototype.flags@^1.4.3:
define-properties "^1.1.3"
functions-have-names "^1.2.2"
-regexpp@^3.1.0:
+regexpp@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
@@ -10854,20 +10171,6 @@ regexpu-core@^5.0.1:
unicode-match-property-ecmascript "^2.0.0"
unicode-match-property-value-ecmascript "^2.0.0"
-registry-auth-token@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479"
- integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==
- dependencies:
- rc "^1.2.8"
-
-registry-url@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009"
- integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==
- dependencies:
- rc "^1.2.8"
-
regjsgen@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d"
@@ -10889,6 +10192,16 @@ rehype-raw@^6.1.1:
hast-util-raw "^7.2.0"
unified "^10.0.0"
+remark-frontmatter@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz#84560f7ccef114ef076d3d3735be6d69f8922309"
+ integrity sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==
+ dependencies:
+ "@types/mdast" "^3.0.0"
+ mdast-util-frontmatter "^1.0.0"
+ micromark-extension-frontmatter "^1.0.0"
+ unified "^10.0.0"
+
remark-gfm@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f"
@@ -10933,57 +10246,6 @@ repeat-string@^1.6.1:
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-request-light@^0.2.4:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.5.tgz#38a3da7b2e56f7af8cbba57e8a94930ee2380746"
- integrity sha512-eBEh+GzJAftUnex6tcL6eV2JCifY0+sZMIUpUPOVXbs2nV5hla4ZMmO3icYKGuGVuQ2zHE9evh4OrRcH4iyYYw==
- dependencies:
- http-proxy-agent "^2.1.0"
- https-proxy-agent "^2.2.3"
- vscode-nls "^4.1.1"
-
-request-promise-core@1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
- integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
- dependencies:
- lodash "^4.17.19"
-
-request-promise-native@^1.0.8:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
- integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
- dependencies:
- request-promise-core "1.1.4"
- stealthy-require "^1.1.1"
- tough-cookie "^2.3.3"
-
-request@^2.88.2:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- har-validator "~5.1.3"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- oauth-sign "~0.9.0"
- performance-now "^2.1.0"
- qs "~6.5.2"
- safe-buffer "^5.1.2"
- tough-cookie "~2.5.0"
- tunnel-agent "^0.6.0"
- uuid "^3.3.2"
-
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -10994,11 +10256,6 @@ require-from-string@^2.0.2:
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
-require-main-filename@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
- integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
-
require-package-name@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/require-package-name/-/require-package-name-2.0.1.tgz#c11e97276b65b8e2923f75dabf5fb2ef0c3841b9"
@@ -11009,13 +10266,6 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-requizzle@~0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.1.tgz#6943c3530c4d9a7e46f1cddd51c158fc670cdbde"
- integrity sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=
- dependencies:
- underscore "~1.6.0"
-
resolve-cwd@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
@@ -11038,7 +10288,12 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.9.0:
+resolve.exports@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
+ integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
+
+resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.9.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@@ -11047,13 +10302,6 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.2
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
-responselike@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
- integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
- dependencies:
- lowercase-keys "^1.0.0"
-
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@@ -11106,11 +10354,6 @@ route-recognizer@^0.3.3:
resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3"
integrity sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==
-rsvp@^4.8.4:
- version "4.8.4"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.4.tgz#b50e6b34583f3dd89329a2f23a8a2be072845911"
- integrity sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==
-
run-con@~1.2.10:
version "1.2.10"
resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.10.tgz#90de9d43d20274d00478f4c000495bd72f417d22"
@@ -11147,7 +10390,7 @@ sade@^1.7.3:
dependencies:
mri "^1.1.0"
-safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
@@ -11171,26 +10414,11 @@ safe-regex@^2.1.1:
dependencies:
regexp-tree "~0.1.1"
-"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sane@^4.0.3:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded"
- integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==
- dependencies:
- "@cnakazawa/watch" "^1.0.3"
- anymatch "^2.0.0"
- capture-exit "^2.0.0"
- exec-sh "^0.3.2"
- execa "^1.0.0"
- fb-watchman "^2.0.0"
- micromatch "^3.1.4"
- minimist "^1.1.1"
- walker "~1.0.5"
-
sass@^1.49.9:
version "1.49.9"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.49.9.tgz#b15a189ecb0ca9e24634bae5d1ebc191809712f9"
@@ -11200,12 +10428,7 @@ sass@^1.49.9:
immutable "^4.0.0"
source-map-js ">=0.6.2 <2.0.0"
-sax@1.2.1, sax@>=0.6.0:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
- integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o=
-
-saxes@^5.0.0:
+saxes@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
@@ -11284,32 +10507,25 @@ selfsigned@^2.0.1:
dependencies:
node-forge "^1"
-semver-diff@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
- integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==
- dependencies:
- semver "^6.3.0"
-
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-semver@7.0.0:
+semver@7.0.0, semver@~7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
- version "7.3.5"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
- integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7:
+ version "7.3.7"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
+ integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
dependencies:
lru-cache "^6.0.0"
@@ -11374,11 +10590,6 @@ serve-static@1.14.2:
parseurl "~1.3.3"
send "0.17.2"
-set-blocking@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
- integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -11422,7 +10633,7 @@ shallow-clone@^3.0.0:
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+ integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
dependencies:
shebang-regex "^1.0.0"
@@ -11436,18 +10647,13 @@ shebang-command@^2.0.0:
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+ integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-shellwords@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
- integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
-
shortcss@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/shortcss/-/shortcss-0.1.3.tgz#ee2a7904d80b7f5502c98408f4a2f313faadfb48"
@@ -11469,11 +10675,18 @@ sigmund@^1.0.1:
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
-signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
+signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+simple-update-notifier@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc"
+ integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==
+ dependencies:
+ semver "~7.0.0"
+
sirv@^1.0.7:
version "1.0.11"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.11.tgz#81c19a29202048507d6ec0d8ba8910fda52eb5a4"
@@ -11565,12 +10778,12 @@ source-list-map@^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-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2:
+"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"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
-source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
+source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
@@ -11675,39 +10888,24 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-sshpk@^1.7.0:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- bcrypt-pbkdf "^1.0.0"
- dashdash "^1.12.0"
- ecc-jsbn "~0.1.1"
- getpass "^0.1.1"
- jsbn "~0.1.0"
- safer-buffer "^2.0.2"
- tweetnacl "~0.14.0"
-
ssri@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
- integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
+ integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
dependencies:
figgy-pudding "^3.5.1"
ssri@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808"
- integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
+ integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
dependencies:
minipass "^3.1.1"
-stack-utils@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593"
- integrity sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==
+stack-utils@^2.0.3:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
+ integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==
dependencies:
escape-string-regexp "^2.0.0"
@@ -11724,11 +10922,6 @@ static-extend@^0.1.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-stealthy-require@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
- integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
-
stream-browserify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
@@ -11779,16 +10972,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-string-width@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
- integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
- dependencies:
- emoji-regex "^7.0.1"
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^5.1.0"
-
-string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -11827,7 +11011,7 @@ string_decoder@~0.10.x:
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
@@ -11851,11 +11035,6 @@ strip-bom@^4.0.0:
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
- integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-
strip-final-newline@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
@@ -11873,11 +11052,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-strip-json-comments@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
- integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-
style-loader@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c"
@@ -11993,6 +11167,13 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
@@ -12039,7 +11220,7 @@ sync-fetch@^0.3.1:
buffer "^5.7.0"
node-fetch "^2.6.1"
-table@^6.0.9, table@^6.8.0:
+table@^6.8.0:
version "6.8.0"
resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca"
integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==
@@ -12050,11 +11231,6 @@ table@^6.0.9, table@^6.8.0:
string-width "^4.2.3"
strip-ansi "^6.0.1"
-taffydb@2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268"
- integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=
-
tapable@^0.1.8:
version "0.1.10"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
@@ -12066,9 +11242,9 @@ tapable@^1.0.0, tapable@^1.1.3:
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^6.0.2:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
- integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
+ version "6.1.11"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
+ integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
@@ -12077,11 +11253,6 @@ tar@^6.0.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
-term-size@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753"
- integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==
-
terminal-link@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
@@ -12106,9 +11277,9 @@ terser-webpack-plugin@^1.4.3:
worker-farm "^1.7.0"
terser@^4.1.2:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65"
- integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==
+ version "4.8.1"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f"
+ integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==
dependencies:
commander "^2.20.0"
source-map "~0.6.1"
@@ -12148,10 +11319,10 @@ three@^0.84.0:
resolved "https://registry.yarnpkg.com/three/-/three-0.84.0.tgz#95be85a55a0fa002aa625ed559130957dcffd918"
integrity sha1-lb6FpVoPoAKqYl7VWRMJV9z/2Rg=
-throat@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
- integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==
+throat@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
+ integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
throttle-debounce@^2.1.0:
version "2.1.0"
@@ -12208,9 +11379,9 @@ tmp@^0.0.33:
os-tmpdir "~1.0.2"
tmpl@1.0.x:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
- integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
to-arraybuffer@^1.0.0:
version "1.0.1"
@@ -12229,11 +11400,6 @@ to-object-path@^0.3.0:
dependencies:
kind-of "^3.0.2"
-to-readable-stream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
- integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
-
to-regex-range@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
@@ -12276,27 +11442,19 @@ touch@^3.1.0:
dependencies:
nopt "~1.0.10"
-tough-cookie@^2.3.3, tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
-tough-cookie@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2"
- integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==
+tough-cookie@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
+ integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
dependencies:
- ip-regex "^2.1.0"
- psl "^1.1.28"
+ psl "^1.1.33"
punycode "^2.1.1"
+ universalify "^0.1.2"
-tr46@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479"
- integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==
+tr46@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
+ integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
dependencies:
punycode "^2.1.1"
@@ -12354,7 +11512,7 @@ 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.3.1, tslib@~2.4.0:
+tslib@^2, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.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==
@@ -12371,18 +11529,6 @@ tty-browserify@0.0.0:
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
- dependencies:
- safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
@@ -12467,34 +11613,15 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"
-undefsafe@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76"
- integrity sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=
- dependencies:
- debug "^2.2.0"
-
-underscore-contrib@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/underscore-contrib/-/underscore-contrib-0.3.0.tgz#665b66c24783f8fa2b18c9f8cbb0e2c7d48c26c7"
- integrity sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=
- dependencies:
- underscore "1.6.0"
-
-underscore@1.6.0, underscore@~1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
- integrity sha1-izixDKze9jM3uLJOT/htRa6lKag=
-
-underscore@~1.8.3:
- version "1.8.3"
- resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
- integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=
+undefsafe@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
+ integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
undici@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/undici/-/undici-5.0.0.tgz#3c1e08c7f0df90c485d5d8dbb0517e11e34f2090"
- integrity sha512-VhUpiZ3No1DOPPQVQnsDZyfcbTTcHdcgWej1PdFnSvOeJmOVDgiOHkunJmBLfmjt4CqgPQddPVjSWW0dsTs5Yg==
+ version "5.8.0"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.0.tgz#dec9a8ccd90e5a1d81d43c0eab6503146d649a4f"
+ integrity sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q==
unicode-canonical-property-names-ecmascript@^2.0.0:
version "2.0.0"
@@ -12556,13 +11683,6 @@ unique-slug@^2.0.0:
dependencies:
imurmurhash "^0.1.4"
-unique-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
- integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
- dependencies:
- crypto-random-string "^2.0.0"
-
unist-builder@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04"
@@ -12628,7 +11748,7 @@ unist-util-visit@^4.0.0:
unist-util-is "^5.0.0"
unist-util-visit-parents "^5.0.0"
-universalify@^0.1.0:
+universalify@^0.1.0, universalify@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
@@ -12653,25 +11773,6 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
-update-notifier@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3"
- integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==
- dependencies:
- boxen "^4.2.0"
- chalk "^3.0.0"
- configstore "^5.0.1"
- has-yarn "^2.1.0"
- import-lazy "^2.1.0"
- is-ci "^2.0.0"
- is-installed-globally "^0.3.1"
- is-npm "^4.0.0"
- is-yarn-global "^0.3.0"
- latest-version "^5.0.0"
- pupa "^2.0.1"
- semver-diff "^3.1.1"
- xdg-basedir "^4.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"
@@ -12693,21 +11794,6 @@ url-loader@^4.1.1:
mime-types "^2.1.27"
schema-utils "^3.0.0"
-url-parse-lax@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
- integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
- dependencies:
- prepend-http "^2.0.0"
-
-url@0.10.3:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
- integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=
- dependencies:
- punycode "1.3.2"
- querystring "0.2.0"
-
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@@ -12745,22 +11831,17 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-uuid@3.3.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
- integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
-
uuid@8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
-uuid@^3.3.2, uuid@^3.3.3:
+uuid@^3.3.3:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-uuid@^8.3.0, uuid@^8.3.2:
+uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
@@ -12780,10 +11861,10 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0:
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
-v8-to-istanbul@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-5.0.1.tgz#0608f5b49a481458625edb058488607f25498ba5"
- integrity sha512-mbDNjuDajqYe3TXFk5qxcQy8L1msXNE37WTlLoqqpBfRsimbNcrlhQlDPntmECEcUvdC+AQ8CyMMf6EUx1r74Q==
+v8-to-istanbul@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"
+ integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==
dependencies:
"@types/istanbul-lib-coverage" "^2.0.1"
convert-source-map "^1.6.0"
@@ -12807,15 +11888,6 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
vfile-location@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.0.1.tgz#06f2b9244a3565bef91f099359486a08b10d3a95"
@@ -12852,78 +11924,6 @@ 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-json-languageservice@^3.6.0:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.9.1.tgz#f72b581f8cd2bd9b47445ccf8b0ddcde6aba7483"
- integrity sha512-oJkknkdCVitQ5XPSRa0weHjUxt8eSCptaL+MBQQlRsa6Nb8XnEY0S5wYnLUFHzEvKzwt01/LKk8LdOixWEXkNA==
- dependencies:
- jsonc-parser "^2.3.1"
- vscode-languageserver-textdocument "^1.0.1"
- vscode-languageserver-types "3.16.0-next.2"
- vscode-nls "^5.0.0"
- vscode-uri "^2.1.2"
-
-vscode-jsonrpc@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9"
- integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg==
-
-vscode-languageserver-protocol@3.14.1:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz#b8aab6afae2849c84a8983d39a1cf742417afe2f"
- integrity sha512-IL66BLb2g20uIKog5Y2dQ0IiigW0XKrvmWiOvc0yXw80z3tMEzEnHjaGAb3ENuU7MnQqgnYJ1Cl2l9RvNgDi4g==
- dependencies:
- vscode-jsonrpc "^4.0.0"
- vscode-languageserver-types "3.14.0"
-
-vscode-languageserver-textdocument@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f"
- integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA==
-
-vscode-languageserver-types@3.14.0:
- version "3.14.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
- integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
-
-vscode-languageserver-types@3.16.0-next.2:
- version "3.16.0-next.2"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083"
- integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==
-
-vscode-languageserver-types@^3.15.1:
- version "3.15.1"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
- integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==
-
-vscode-languageserver@^5.2.1:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.2.1.tgz#0d2feddd33f92aadf5da32450df498d52f6f14eb"
- integrity sha512-GuayqdKZqAwwaCUjDvMTAVRPJOp/SLON3mJ07eGsx/Iq9HjRymhKWztX41rISqDKhHVVyFM+IywICyZDla6U3A==
- dependencies:
- vscode-languageserver-protocol "3.14.1"
- vscode-uri "^1.0.6"
-
-vscode-nls@^4.1.1, vscode-nls@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
- integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==
-
-vscode-nls@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840"
- integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==
-
-vscode-uri@^1.0.6:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.8.tgz#9769aaececae4026fb6e22359cb38946580ded59"
- integrity sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==
-
-vscode-uri@^2.1.1, vscode-uri@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
- integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
-
vue-apollo@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.7.tgz#97a031d45641faa4888a6d5a7f71c40834359704"
@@ -12933,18 +11933,18 @@ vue-apollo@^3.0.7:
serialize-javascript "^4.0.0"
throttle-debounce "^2.1.0"
-vue-eslint-parser@^8.0.1:
- version "8.3.0"
- resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
- integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
+vue-eslint-parser@^9.0.1:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz#0c17a89e0932cc94fa6a79f0726697e13bfe3c96"
+ integrity sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==
dependencies:
- debug "^4.3.2"
- eslint-scope "^7.0.0"
- eslint-visitor-keys "^3.1.0"
- espree "^9.0.0"
+ debug "^4.3.4"
+ eslint-scope "^7.1.1"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.3.1"
esquery "^1.4.0"
lodash "^4.17.21"
- semver "^7.3.5"
+ semver "^7.3.6"
vue-functional-data-merge@^3.1.0:
version "3.1.0"
@@ -12956,17 +11956,6 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
integrity sha512-2j/t+wIbyVMP5NvctQoSUvLkYKoWAAk2QlQiilrM2a6/ulzFgdcLUJfTvs4XQ/3eZhHiBmmEojbjmM4AzZj8JA==
-vue-jest@4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-4.0.1.tgz#683efc351c24456865b1356bae69d5bb663dafb5"
- integrity sha512-4jewjN8HVgpIW0ZdEwzCWz5vcRLIs1PxMs+5IqJ/6f9KRbEQ+DEqEKHUzIjoNzW2UJOUYBZzWpBnVHakpc/k5w==
- dependencies:
- "@babel/plugin-transform-modules-commonjs" "^7.2.0"
- "@vue/component-compiler-utils" "^3.1.0"
- chalk "^2.1.0"
- extract-from-css "^0.4.4"
- source-map "0.5.6"
-
vue-loader@^15.9.6:
version "15.9.6"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
@@ -13062,7 +12051,7 @@ w3c-xmlserializer@^2.0.0:
dependencies:
xml-name-validator "^3.0.0"
-walker@^1.0.7, walker@~1.0.5:
+walker@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
@@ -13173,10 +12162,10 @@ webpack-dev-middleware@^5.3.1:
range-parser "^1.2.1"
schema-utils "^4.0.0"
-webpack-dev-server@4.9.3:
- version "4.9.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9"
- integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==
+webpack-dev-server@4.10.0:
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.10.0.tgz#de270d0009eba050546912be90116e7fd740a9ca"
+ integrity sha512-7dezwAs+k6yXVFZ+MaL8VnE+APobiO3zvpp3rBHe/HmWQ+avwh0Q3d0xxacOiBybZZ3syTZw9HXzpa3YNbAZDQ==
dependencies:
"@types/bonjour" "^3.5.9"
"@types/connect-history-api-fallback" "^1.3.5"
@@ -13292,14 +12281,14 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
-whatwg-url@^8.0.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771"
- integrity sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==
+whatwg-url@^8.0.0, whatwg-url@^8.5.0:
+ version "8.7.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
+ integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^2.0.2"
- webidl-conversions "^5.0.0"
+ lodash "^4.7.0"
+ tr46 "^2.1.0"
+ webidl-conversions "^6.1.0"
which-boxed-primitive@^1.0.2:
version "1.0.2"
@@ -13312,11 +12301,6 @@ which-boxed-primitive@^1.0.2:
is-string "^1.0.5"
is-symbol "^1.0.3"
-which-module@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
- integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-
which@^1.2.9, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -13324,20 +12308,13 @@ which@^1.2.9, which@^1.3.1:
dependencies:
isexe "^2.0.0"
-which@^2.0.1, which@^2.0.2:
+which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
-widest-line@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
- integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==
- dependencies:
- string-width "^4.0.0"
-
wildcard@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
@@ -13363,10 +12340,10 @@ worker-loader@^2.0.0:
loader-utils "^1.0.0"
schema-utils "^0.4.0"
-wrap-ansi@^6.2.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
- integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
@@ -13395,21 +12372,16 @@ write-file-atomic@^4.0.1:
imurmurhash "^0.1.4"
signal-exit "^3.0.7"
-"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.2.3, ws@^7.3.1:
- version "7.5.5"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881"
- integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==
+"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.3.1, ws@^7.4.6:
+ version "7.5.7"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67"
+ integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==
ws@^8.3.0, ws@^8.4.2:
version "8.5.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
-xdg-basedir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
- integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
xhr-mock@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/xhr-mock/-/xhr-mock-2.5.1.tgz#c591498a8269cc1ce5fefac20d590357affd348b"
@@ -13423,34 +12395,21 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
-xml2js@0.4.19:
- version "0.4.19"
- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
- integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==
- dependencies:
- sax ">=0.6.0"
- xmlbuilder "~9.0.1"
+xml-name-validator@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
+ integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=
-xmlbuilder@~9.0.1:
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
- integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
-
xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
-xmlcreate@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f"
- integrity sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=
-
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -13462,9 +12421,14 @@ xterm@3.14.5:
integrity sha512-DVmQ8jlEtL+WbBKUZuMxHMBgK/yeIZwkXB81bH+MGaKKnJGYwA+770hzhXPfwEIokK9On9YIFPRleVp/5G7z9g==
y18n@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
- integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+ integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yallist@^2.1.2:
version "2.1.2"
@@ -13481,28 +12445,11 @@ 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:
+yaml-ast-parser-custom-tags@^0.0.43:
version "0.0.43"
resolved "https://registry.yarnpkg.com/yaml-ast-parser-custom-tags/-/yaml-ast-parser-custom-tags-0.0.43.tgz#46968145ce4e24cb03c3312057f0f141b93a7d02"
integrity sha512-R5063FF/JSAN6qXCmylwjt9PcDH6M0ExEme/nJBzLspc6FJDmHHIqM7xh2WfEmsTJqClF79A9VkXjkAqmZw9SQ==
-yaml-language-server@^0.11.1:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/yaml-language-server/-/yaml-language-server-0.11.1.tgz#4ddc72eb9a6dd7dc41f31af2a8f5c72cce456cc9"
- integrity sha512-N3Tu3g4O6ZWV7W0LVsNk62DtKJDQkbnPZRDd7ntaAeEl8QkxL1vnMunI26uzDU4PwwG4tPJ8g/VRS6U+fVp/6A==
- dependencies:
- js-yaml "^3.13.1"
- jsonc-parser "^2.2.1"
- request-light "^0.2.4"
- vscode-json-languageservice "^3.6.0"
- vscode-languageserver "^5.2.1"
- vscode-languageserver-types "^3.15.1"
- vscode-nls "^4.1.2"
- vscode-uri "^2.1.1"
- yaml-ast-parser-custom-tags "0.0.43"
- optionalDependencies:
- prettier "2.0.5"
-
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
@@ -13513,35 +12460,23 @@ yaml@^2.0.0-10:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-10.tgz#d5b59e2d14b8683313a534f2bbc648e211a2753e"
integrity sha512-FHV8s5ODFFQXX/enJEU2EkanNl1UDBUz8oa4k5Qo/sR+Iq7VmhCDkRMb0/mjJCNeAWQ31W8WV6PYStDE4d9EIw==
-yargs-parser@^18.1.2:
- version "18.1.3"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
- integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
-
-yargs-parser@^20.2.3:
+yargs-parser@^20.2.2, yargs-parser@^20.2.3:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
-yargs@^15.4.1:
- version "15.4.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
- integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+yargs@^16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+ integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
dependencies:
- cliui "^6.0.0"
- decamelize "^1.2.0"
- find-up "^4.1.0"
- get-caller-file "^2.0.1"
+ cliui "^7.0.2"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
require-directory "^2.1.1"
- require-main-filename "^2.0.0"
- set-blocking "^2.0.0"
string-width "^4.2.0"
- which-module "^2.0.0"
- y18n "^4.0.0"
- yargs-parser "^18.1.2"
+ y18n "^5.0.5"
+ yargs-parser "^20.2.2"
yarn-check-webpack-plugin@^1.2.0:
version "1.2.0"
@@ -13550,15 +12485,15 @@ yarn-check-webpack-plugin@^1.2.0:
dependencies:
chalk "^2.4.2"
-yarn-deduplicate@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-5.0.0.tgz#8977b9a4b1a2fd905568c3a23507b1021fa381eb"
- integrity sha512-sYA5tqBSY3m+DtEcwfMYP1G2zWq1UtWSNg2goESqiu/JXBoBF/Qh+FuTJGGjsrisxL+5yOgq/ez1Rd+KSPwzvA==
+yarn-deduplicate@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-5.0.2.tgz#b56484c94d8f1163a828bf20516607f89c078675"
+ integrity sha512-pxKa+dM7DMQ4X2vYLKqGCUgtEoTtdMVk9gNoIsxsMSP0rOV51IWFcKHfRIcZjAPNgHTrxz46sKB4xr7Nte7jdw==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
- commander "^9.2.0"
- semver "^7.3.2"
- tslib "^2.3.1"
+ commander "^9.4.0"
+ semver "^7.3.7"
+ tslib "^2.4.0"
yn@3.1.1:
version "3.1.1"